4 — Interpreting Functions
Due Tuesday, 04 February, 6am
The purpose of this assignment is to understand the interpretation of statically scoped functions and conditional expressions.
Delivery Deliver your solutions in a folder called 4 in your github repo with the following organization:
xinterpreter as specified in the testing task below.
ITests/ as specified in the testing task below.
Other/, which contains the solutions to the programming tasks.
Programming Task
Step One Design a parser and an environment-based This is not a request to adapt your static-distance interpreter. interpreter for the language of FVExpr. You may wish to adapt existing code.
- a Var |
- an Int |
all variables declared in one sequence are pairwise distinct |
- a JSON array of the shape ["call",FVExpr,FVExpr,...,FVExpr] |
as in all mainstream languages, the first and required |
FVExpr is to evaluate to a function value |
|
- a JSON array of the shape ["let", Var, "=", ["fun*", VarList, FVExpr]FVExpr] |
|
all variables declared in one sequence are pairwise distinct |
Recall that "fun*", "call", and "if-0" are keywords.
The meaning of "fun*" and "if-0" expressions are as discussed in class. The first is a function of as many arguments as there are Vars. The second is the conditional expression that uses 0 as the only true value. The interpretation of all other expressions is adapted mutatis mutandis.
Stop! Does your chosen programming language have an "if-0"-like expression?
If the given program evaluates to a function value, the interpreter returns the String "closure"; otherwise a regular answer is a number and the interpreter returns it.
An FVExpr is one of: |
... |
where the first FVExpr is not a keyword |
... |
For now, allow "+", "*", and "^" (for exponentiation with non-negative exponent argument). The standard prelude assigns an implementation-dependent data representation to the conventional meaning of these three operations.
Hint In functional languages you may use functions to represent such prelude functions. In object-oriented languages that don’t have anonymous function expressions, you may wish to use objects after looking up the command pattern (or recall it from OOD).
Step Three Ensure that your interpreter does not leak. In particular, it should explicitly catch all possible errors and it should evaluate the sub-expressions of a function application and binary operation strictly from right to left.
"variable s undeclared" (for any String s)
"arithmetic error" (number expected)
"number of arguments does not match number of parameters"
"closure or primop expected" "function application (closure expected)"
These error messages are additional results that your interpreter may return.
Testing Task Write the test harness xinterpreter for your interpreter programs.
Create ten tests for xinterpreter. Place them in ITests/. A test consists of two files: N-in.json and N-out.json for N in [0 .. 9]. An input file in ITests contains a single FVExpr as modified and constrained in the programming task above. An output is an Answer, which is either a number or a JSON string.
Recall JSON: Simplicity and Complexity.