CSci 2041 Lab 12: Denotational Semantics solution

$25.00

Original Work ?
Category: You will Instantly receive a download link for .ZIP solution file upon Payment

Description

5/5 - (1 vote)

Lab goals

This lab will explore the interpreter that we wrote in lecture and
extend it a bit. This is based on “denotational semantics”. This is a
mechanism for defining the semantics of imperative programs in which
the meaning of a program is seen as a state transformation function.

You can read more about denotational semantics in the paper
[“The Denotational Semantics of Programming Languages”](https://github.umn.edu/umn-csci-2041-S18/public-class-repo/blob/master/Resources/Denotational_Semantics_Tennent.pdf) by
R. D. Tennent. This paper is also in the Resources directory in the
public class repository.

## Getting started.

Copy the file “interpreter.ml“ from either the
“Sample Programs/Sec_01_1:25pm“ or
“Sample Programs/Sec_10_3:35pm“ directory of
the public class repository into a
new directory named “Lab_12“. 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_while []“. 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 a conditional statement — if-then-else

Add a new constructor of the following form to “stmt“:
“`
| IfThenElse of 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_while_ifthenelse“. It should correspond to the following
comment already in “interpreter.ml“. Note how “program_seq“ and
“program_while“ both have similar comments for them. You need to
construct a let-binding for “program_while_ifthenelse“ 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_while_ifthenelse []`` 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_while_ifthenelse []`` and enter ``15`` when prompted. Then 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 of ``sum_evens`` in the final state + give ``val_sum_odds`` the value of ``sum_odds`` in the final state + give ``num_sum_evens`` the number of times ``sum_evens`` appears in the final state + give ``num_sum_odds`` the number of times ``sum_odds`` appears in the final state ## Create a testable version of ``program_while_ifthenelse`` Define ``program_while_ifthenelse_test`` in your file to be the same as ``program_while_ifthenelse``, but replace ``` ReadNum "x" ``` with ``` Assign ("x", Val (Int 12)) ``` The following should evaluate to ``Int 30`` ``` lookup "sum_evens" (exec program_while_ifthenelse_test []) ``` ## Add a skip statement Add the following constructor to ``stmt``: ``` | Skip ``` This 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 this new construct. Also, re-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_ifthen`` 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_ifthen [ ("x",Int 4) ]``. For example ``lookup "y" (exec program_ifthen [ ("x",Int 4) ])`` should evaluate to ``Int 6``. ## Add a for loop Next, add the following ``stmt`` constructor ``` | For of string * expr * expr * stmt ``` that represents a for-loop with a name of the integer counter (the ``string``) and the lower and upper bounds (the two ``expr`` components) and the body of the loop (the ``stmt``). Complete the implementation of ``exec`` to handle this new construct. Define ``program_for`` to be ``` For ("i", Val (Int 1), Val (Int 5), WriteNum (Var "i")) ``` When run, this will print out the values 1, 2, 3, 4, and 5. You can see the bounds are inclusive. Add the following declaration to your file: ``` let program_sum_10 = (* sum = 0 for i = 1 to 10 sum = sum + i write sum *) Seq (Assign ("sum", Val (Int 0)), Seq (For ("i", Val (Int 1), Val (Int 10), Assign("sum", Add (Var "sum", Var "i"))), WriteNum (Var "sum") ) ) ``` Run it to check that ``55`` is displayed. Consider this alternate version. It should print out ``55`` two times. Why is that? Ensure that your implementation of the for-loop gives this same behavior. ``` let program_sum_10_n = (* n = 10 sum = 0 for i = 1 to n sum = sum + i n = sum write sum write n *) Seq (Assign ("n", Val (Int 10)), Seq (Assign ("sum", Val (Int 0)), Seq (For ("i", Val (Int 1), Var "n", Seq (Assign("sum", Add (Var "sum", Var "i")), Assign("n", Var "sum") ) ), Seq(WriteNum (Var "sum"), WriteNum (Var "n") ) ) ) ) ``` ## Repeat-until If time allows, attempt this optional task. Add a repeat-until loop. It consists of a ``stmt`` and ``expr``. It executes the loop body first, then does the check. It keeps looping until the ``expr`` evaluates to true. You might use this as the constructor in ``stmt``: ``` | Repeat of stmt * expr ``` ## 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.