Programming
Assignment 4: |
|
Supporting Code for
Preparation Create a programs/4 directory within your comp311 directory. All of your files for this assignment should be stored in the programs/4 subdirectory.
Teamwork You are required to do this assignment and all other programming assignments using pair programming. When you submit your assignment, indicate the composition of your team (names, student ids, and email addresses) in your README file.
If you cannot find a partner and would like one, send an email to comp311@rice.edu and we will try to find one for you. Teams of more than two members are not permitted.
Task Your task is to extend and modify the nine interpreters from Assignment 3 or one of the solutions for Assignment 3 to support imperative programming by adding ML-style reference cells and blocks. In particular, you will add the unary operators ref and ! and the binary assignment operator <-, and blocks consisting of a sequence of expressions enclosed in { and } and separated by semicolons (i.e. the final expression in the sequence does NOT have a semicolon following it). In other words
Exp ::= ...
| Block
Block ::= "{" StatementList "}"
StatementList ::= Exp | Exp ; StatementList
Unop ::= ... | ref | !
Binop ::= ... | <-
You must modify your lexer and parser to accept this extended syntax as well as the new unary operators ref and ! and the new binary operator <-. The supporting code for this assignment includes solutions to the previous assignment. In future assignments, there will be no supporting code.
Adding ref cells and assignment The unary operation ref E evaluates the expression E to produce an arbitrary value V, creates a new box b holding V and returns the box b.
The unary operation ! E evaluates the expression E to produce a value which must be a box and returns the contents of the box. If the value of E is not a box, the interpreter generates a run-time error (EvalException, EvalError, etc.).
The binary operation E1<- E2 evaluates the expression E1 to produce a value V1 that must be a box, evaluates E2 to produce an arbitrary value V2, stores V2 in box V1, and returns the special value unit which is distinct from the “undefined” value used in call-by-value recursive let. If E1 is not a box, then the interpreter generates a run-time error. The unit value can appear anywhere in a computation, but many primitive operations (those for which it makes no sense) reject it as an illegal input; it is analogous to the value (void) in Scheme.
A box is a Jam value and can be returned as the result of an expression. When converted to a string, the output of a box shoud be (ref <value>). This expression
let x := ref 10; in {x <- ref 17; x}
should be displayed as the string
(ref (ref 17))
in call-by-value and call-by-need. Call-by-name will display the string
(ref 10)
You will have to modify your "to string" function to support the correct display of boxes.
Adding blocks The block { e1 . . . en }, n > 1, evaluates e1, ... , en in left-to-right order and returns the value of en. The expressions e1, ... , en may evaluate to the unit value without aborting the computation. In the Jam grammar, a Block is a an additional form for an expression analogous to map, if, and let. Hence, it cannot appear as the first argument in a binary operation unless it is enclosed in parentheses. The “empty block” is a parser error (ParseException, ParseError, etc.).
Optional extra credit (15%) Devise a Jam program that exhibits different behavior for eight of the nine modes of interpretation. It should not generate a run-time error in any of the nine cases, but it may diverge in one case.
Testing You are expected to write unit tests for all of your non-trivial methods or functions. For more information, refer back to Assignment 1.
All versions The interface of all versions remains identical to that in Assignment 3.
Choice of Language Generic Java, Scheme, and O'Caml are the only languages permitted for this assignment.
The directory tests will contain Java, O'Caml and Scheme test files Assign4Test.java, assign4test.ml, and assign4test.ss containing some very simple unit tests for your program. While these files are being prepared, you can make minor modifications to the test files Assign3Test.java, assign3test.ml and assign3test.ss to create corresponding (and exceedingly incomplete) test files for this assignment.
Your program directory should only contain the files that you want to submit. We will subsequently provide you with test scripts similar to the ones we provided for Assignment 3. Running these scripts will alert you to any problems with your directory configuration. We will also place a few addtional test programs in the directory tests.
Make sure that your program passes the sample unit tests and works with our grading script before submitting it. You must provide a README file in the directory programs/4 with the following format:
cork camus(in either order), followed by an empty new line, and nothing else.
Any test data files for your program must be stored in the programs/4 directory. Please make sure you submit your unit tests! You cannot get credit for parts not submitted!
Each procedure or method in your program should include a short comment stating precisely what it does. For routines that parse a particular form of program phrase, give grammar rules describing that form.
To submit your program, make sure that everything that you want to submit is located in the directory programs/3 and type the command
turnin311 -t[scheme|java|ocaml] 4
from within the comp311/programs directory. For example, if you have an O'Caml version you would execute
turnin311 -tocaml 4
The command will inform you whether or not your submission succeeded. Only submit one copy of your program per team. If you need to resubmit an improved version your program, submit it from the same account as the original so that the old version is replaced.
Note if turnin311 is not on your path, you will need to add /home/comp311/bin to your path:
export PATH=$PATH:/home/comp311/bin