CS558 Homework #6
Due 5:00 PM, Monday, February 23, 2015

Homework must be submitted via D2L. All submitted files (3 for this assignment sol6A.hs, sol6B.txt, and sol6C.e6) must be submitted in the appropriate D2L directory in the drop box HW6. It is your responsibility to submit the homework in the proper format with the proper names. For example.

-- Homework 6  Tom Smith   tom_smith@gmail.com

All programs mentioned can be downloaded from the this document

Consider a typed variant of our familiar simple language with imperative expressions, functions, and integers, characters, booleans, pairs, and lists. We'll call this language E6. It is very similar to language E3, except it is typed, and it supports booleans, characters and lists as primitive values. We do not encode booleans as integers or encode lists as right-nested pairs, as we did in E3. Instead there are primitive operations for each of these. It also include characters as we did in language E4. E6's concretized abstract syntax is given by the following grammar:

prog := '(' { fundef | globaldef } ')' exp

fundef := '(' 'fun' fname typ '(' { var typ } ')' exp ')'

globaldef := '('  'global' vname exp ')'

typ := 'Int'
| 'Bool'
| 'Char'
| '(' typ '.' typ ')'
| '[' typ ']'
| letter

exp := var
| '(' ':=' var exp ')'
| '(' 'write' exp ')'
| '(' 'local' '(' { var exp } ')' exp ')'
| '(' 'block' { exp } ')'
| '(' '@' fname { exp } ')'
| '(' 'while' exp exp ')'

| True
| False
| '(' 'if' exp exp exp ')'

| int
| '(' '+' exp exp ')'
| '(' '-' exp exp ')'
| '(' '*' exp exp ')'
| '(' '/' exp exp ')'
| '(' '<=' exp exp ')'

| char
| '(' = exp exp ')

| '(' 'pair' exp exp ')'
| '(' 'fst' exp ')'
| '(' 'snd' exp ')'

| '(' 'cons' exp exp ')'
| '(' 'head' exp ')'
| '(' 'tail' exp ')'
| 'nil'
| '(' null exp ')'


fname := letter { letter | digit }
var := letter { letter | digit }

Note that there is now a new type of syntax to represent types (typ). Note that the expressions (exp) come arranged in groups organized around the type of values they manipulate.

The semantics of E6 expressions and functions are similar to those of previous homeworks. All scoping is static. The scope of each function name is the entire program, allowing two or more functions to be mutually recursive. The language obeys a type discipline, distinguishing integers, characters, booleans, lists, and pairs; every variable and expression must belong to a unique type. Each function parameter is explicitly typed, as is the function result.

For example, the code

(fun f Int (b Bool p (Int . Int))
           (if b (+ (fst p) (snd p)) 0))

defines a function f with return type Int , and two parameters: b (whose type is Bool), and p (whose type is a Pair of Ints).

Local variables and globals do not have to be explicitly typed, as their types can always be infered from their initializing expressions.

It is a typing error to use an undefined function or variable name, or to define the same function name twice. If the same variable name appears twice in a parameter list or local declaration, the second appearance hides the first.

An E6 interpreter in Haskell (only) has been provided ( hw6.hs ). It reads a file containing an E6 program in the syntax described above, echoes the program (to confirm correct parsing), performs some typechecking on it, executes it (possibly producing output from write expressions), and displays the overall result, and then places the user in a read-typecheck-eval-print loop.

The typechecker catches some typing errors. For example, the program:

(
(fun not Bool (y Bool) (if y False True))
(fun f Int (x Int) (+ 2 3))
)
(@not (@ f 4))

casues the following output

********** PARSING ******************
Program:
((fun not Bool (y Bool) (if y False True))
 (fun f Int (x Int) (+ 2 3)))
(@ not (@ f 4))

********** Type Checking *************
not::(Bool-> Bool)
f::(Int-> Int)


******** LOADING DEFS **************
not f

********** EXECUTING BODY **********
*** Exception: Non Bool as argument to if test: 5

The error is caused because f 's result type (i.e ., Int ) doesn't match the argument type of not (i.e., Bool ).

What to do

  1. sol6A.hs (45 points) . For many programs, the output of the typechecker will be the message: Typechecking failed: unimplemented indicating that the necessary typechecking code is missing. Your task is to complete the typechecker, by doing proper typechecking at the eight places where the unimplemented message is currently generated (between lines 375 and 485).

    Use the existing code as a model. Your completed interpreter should be able to find all type errors in E6 programs. You may use typedlists.e6 as one test file. But I don't guarantee how much that file covers all the features of language E6. All the changes you need to make are between lines 375 and 485 of Hw6.hs. You need to remove the calls to notYet (sh term) and replace it with your own haskell code. There are 8 such calls. Hint. If there is an unimplemented case for an Exp, look what happens at similar cases.

    If you've done it properly, the interpreter should never fail during evaluation with a checked runtime error of any kind.

    Put your modified interpreter into a file called sol6A.hs and submit it.

  2. sol6B.txt (25 points). Run the small file simple.e6. Inside the read-typecheck-eval-print loop, type in 10 expressions. Each expression should cause a type error. You should choose your 10 expressions so they exercise the code you wrote in in sol6A.hs above. Collect a transcript of the entire interaction, place it in a file called sol6B.txt, and submit it to D2L. Here is a sample solution with only one test.

    ********** PARSING ******************
    Program:
    ((global n 7)
     (global b True)
     (global p (pair 5 True))
     (global l (cons 3 (cons 4 (cons 9 nil))))
     (global c 'a'))
    (+ n 1)
    
    ********** Type Checking *************
    
    n::Int
    b::Bool
    p::(Int . Bool)
    l::[Int]
    c::Char
    
    ******** LOADING DEFS **************
    n b p l c
    
    ********** EXECUTING BODY **********
    8
    
    *********** ENTERING READ EVAL PRINT ***************
    type ':q' to exit, type 'trace' to flip tracer state
    
    enter Exp>
    (+ n True)
    user error (
    *** Error, near "unknown location" (line 0, column 0)
    Int =/= Bool (Different type constuctors)
    Checking (+)
    While infering the type of
       True
    Expected type: Int
    Computed type: Bool)
    enter Exp>
    

    Be sure your file has 10 tests, and that it exercises code you wrote!.

  3. sol6C.e6 (30 points). In this part you will write a small E6 program to solve the following problems.

    Place all these functions in a file sol6C.e6 and submit it to D2L.