Homework must be submitted via D2L. All submitted files (3 for this assignment sol5A.e5, hw5A.hs, and sol5B.hs) must be submitted in the appropriate D2L directory in the drop box HW5.It is your responsibility to submit the homework in the proper format with the proper names. For example.
-- Homework 5 Tom Smith tom_smith@gmail.com
All programs mentioned can be downloaded from the this document
This homework has two parts. First, altering the definitional interpreter for a small functional language, and Second, writing a few small programs in a functional language (Haskell).
prog := { decl } 'in' exp exp := var | int | char | '(' '=' exp exp ')' | '(' 'if' exp exp exp ')' | '(' 'let' { decl } 'in' exp ')' | '(' 'lambda' ( {var} ) exp ')' | '(' '@' exp exp { exp } ')' | '(' '+' exp exp ')' | '(' '-' exp exp ')' | '(' '*' exp exp ')' | '(' '/' exp exp ')' | '(' '<=' exp exp ')' | '(' 'pair' exp exp ')' | '(' 'fst' exp ')' | '(' 'snd' exp ')' | '(' 'ispair' exp ')' | '(' 'ischar' exp ')' | '(' 'isint' exp ')' var := letter { letter | digit } decl := '(' 'fun' var '(' { var } ')' exp ')' | '(' 'val' var exp ')'
As usual, comments may be included by enclosing them between comment braces '{-' and '-}' characters, and they may be nested.
E5 is similar to some of our earlier languages (especially E4), it retains characters and their operations, but lacks imperative features including assignment, while , block , and write.
The local expression has been renamed let (to emphasize that it acts like an Haskell-style immutable binding). A let contains a series of zero or more declarations, the keyword 'in', and then an expression which acts as the body of the let. The value of a let is the value of its body, BUT, the body is evaluated in an enriched environment, which contains local bindings for the values and functions introduced by the let's declarations.
There are two kinds of declarations: 'fun' and 'val'. A 'val' declaration is much like a 'local' declaration from language E4. A declaration (val x exp), extends the environment with the name 'x', binding it to the value of 'exp'.
The most important changes are in the treatment of functions, which can be defined in two ways.
Functions are treated as just another kind of value, and they share the same name space as other values.
Applications now take an arbitrary expression in the function position; this must evaluate to a function value. Functions take an arbitrary number of additional arguments (including zero). Functions are completely "first-class", i.e., they can be passed as arguments to, or returned as results of, other functions, and can be stored in pairs. A program is a series of declarations, the keyword 'in' follwoed by an expression. The value of the program is the value of this expression, evaluated in an environment created by the declarations.
The web site gives several example E5 programs. Program static.e5 illustrates that nested functions use static scoping rules; program compose.e5 shows how to write a higher-order function that composes two existing functions.
An E5 interpreter in Haskell (only) has been provided ( hw5.hs ).
In the E5 language there are exactly 4 kinds of values. Ints, Characters, Pairs, and Functions. There are 3 predicates on values: ispair, ischar, and isint. With these you can test what kind of value any object takes. In addition, the interpreter for E5 attempts to recognize the convention we have used to encode lists. Recall that convention, it uses right-nested pairs ending in 0. For example (pair 4 (pair 'z' 0)) evaluates to (4.('z'.0)). In the interpreter for E5 if such a right-nested pair is recognized it is printed as [4,'z']. The interpreter also recognizes right-nested pairs of characters, and prints them as strings. For example (pair 'a' (pair 'b' (pair 'c' 0))) prints as "abc". There are still only 4 kinds of values, though we print some of them using the list conventions. Here are some examples
You will need to write some small E5 programs. You will also modify the definitional interpreter. You might try adding the list convention functions to an E5 program. While the idea is the same, the format of definitions is very different in E5 than in E3 and E4. This would be good practice before you start.
Turn in a file named hw5A.hs in to D2L which is your modified interpreter.
Note that this interpreter has some significant changes from the previous one for E4. We no longer use a stack, just an environment and a heap. There is a (single) environment (because both functions and other values can now be stored in the same name space). The environment now maps all identifiers directly to addresses in the heap. But, we use addresses only when we allocate new cells in the heap, We never change values in the heap since there is no assignment (or call by reference).