4 KiB
Lab 11: Denotational Semantics
CSci 2041: Advanced Programming Principles, Spring 2017
Due: Friday, April 7 at 5:00pm. You should be able to complete this work during lab.
Lab goals
This lab will explore the interpreter that we wrote in lecture and extend it a bit.
Getting started.
Copy the file interpreter.ml
from either the
SamplePrograms/Sec_01_1:25pm
or
SamplePrograms/Sec_10_3:35pm
directory of
the public class repository into a
new directory named Lab_11
. Name the copy of this file
interpreter.ml
.
Review
Open the file and familiarize your self with the data types and the
functions eval
and exec
.
Run exec program_2 []
. And enter 10
. How many times does
sum
appear in the final state?
Create a let-binding in your file of the from
let num_sum = ...
where ...
is replaced by the number of times that sum
appears
in the final state.
Add and conditional statement -- if-then-else
Add a new constructor of the following form to stmt
:
| IfThenElse expr * stmt * stmt
Then write to clause for this new constructor in the match
expression in exec
.
Next, add a modulus operator constructor to expr
:
| Mod of expr * expr
Then write the clause for this new constructor in the match
expression in eval
.
Hint: in OCaml, mod
is the infix operator for modulus. Try it out
in utop
.
Another program:
Construct a new program of type stmt
named program_3
. It
should correspond to the following comment already in
interpreter.ml
. Note how program_1
and program_2
both
have similar comments for them. You need to construct a let-binding
for program_3
that corresponds to the program in the comment below:
(* read x;
i = 0;
sum_evens = 0;
sum_odds = 0;
while (i < x) {
write i;
if i mod 2 = 0 then
sum_evens = sum_evens + i;
else
sum_odds = sum_odds + i;
i = i + 1
}
write sum_evens;
write sum_odds
*)
Test your extended exec
Run exec program_3 []
and enter 8
when prompted to enter a
number.
It should print out the integers from 0 to 7 and the print 12 and then 16.
Run exec program_3 []
and enter 15
when prompted.
Create the following let-bindings in your file:
let val_sum_evens =
let val_sum_odds =
let num_sum_evens =
let num_sum_odds =
- give
val_sum_evens
the value ofsum_evens
in the final state - give
val_sum_odds
the value ofsum_odds
in the final state - give
num_sum_evens
the number of timessum_evens
appears in the final state - give
num_sum_odds
the number of timessum_odds
appears in the final state
Create a testable version of program_3
Define program_3_test
in your file to be the same as
program_3
, but replace
Read "x"
with
Assign ("x", Value (Int 12))
The following should evaluate to Int 30
lookup "sum_evens" (exec program_3_test [])
This is one of the automated tests.
An if-then and a skip statement
Add the following constructors to stmt
:
| IfThen of expr * stmt
| Skip
The first is the if-then statement you should expect. The second is a
"skip" statement that does nothing. It is like pass
in Python or
a "noop" in assembly language.
Complete the implementation of exec
to handle these new
constructs. You might implement the IfThen
construct based on
the observation that executing "if ...cond... then ...stmt..." is the same as
executing "if ...cond... then ...stmt... else skip".
Next, define program_4
to correspond to to the following comment:
(* y = 0;
if x mod 2 = 0 then y = y + 2;
if x mod 3 = 0 then y = y + 3;
if x mod 4 = 0 then y = y + 4;
*)
Now try exec program_4 [ ("x",Int 4) ]
.
For example lookup "y" (exec program_4 [ ("x",Int 4) ])
should
evaluate to Int 6
.
Push your work.
Now be sure to commit and push your work. Check the feedback file that should be generated each time you push this work.