Description
- Implementing the mul461 Language: Write a mul461 interpreter, i.e., a Racket function eval-exp that takes a mul461 expression e and either returns the mul461 value that e evaluates to under the empty environment or calls Racket’s error if evaluation encounters a run-time mul461 type error or unbound mul461
A mul461 expression is evaluated under an environment (for evaluating variables, as usual). In your interpreter, use a Racket list of Racket pairs to represent this environment (which is initially empty) so that you can use without modification the provided envlookup function. Here is a description of the semantics of mul461 expressions:
- All values evaluate to themselves. For example, (eval-exp (mul461-int 17)) would return (mul461-int 17), not
- A variable evaluates to the value associated with it in the environment.(This case for var is done for you.)
- An addition/subtraction/multiplication evaluates its subexpressions and, assuming they both produce integers, produces the mul461-int n that is their sum/difference/product. (Note the case for addition is done for you to get you pointed in the right direction.)
- An < or = comparison evaluates its subexpressions and, assuming they both produce integers, produces the mul461-bool b that is the result of comparing the two integer values.
- An and/or evaluates its subexpressions and, assuming they both produce booleans, produces the mul461-bool b that is their and/or boolean operation result.
- A not evaluates its subexpression and, assuming it produces a boolean, produces the mul461-bool b that is the logical negation of its subexpression result.
- An if evaluates its first expression to a value v1. If it is a boolean, then if it is mul461-bool #t, then if evaluates to its second subexpression, else it evaluates its third subexpression. Only one of e2 and e3 should be evaluated. Do not evaluate both e2 and e3.
- A let expression evaluates its first expression to a value v. Then it evaluates the second expression to a value, in an environment extended to map the name in the let expression to v.
Here is additional description of the semantics of mul461 expressions from Part B:
- All values evaluate to themselves. For example, (mul461-null), (mul461-closure f env) are already mul461
- For a pair creater expression (mul461-cons e1 e2), you should first evaluate the sub-expressions e1 and e2 to mul461 values v1 and v2, and the original pair will evaluate to (mul461-cons v1 v2)
- For mul461-car and mul461-cdr, you should first evaluate the subexpression e to mul461 value v. If v is not of the form (mul461-cons v1 v2), then you should raise a type error similar to when adding non-integers. Assume e evaluates to (mul461-cons v1 v2), then (mul461-car e) should evaluate to v1 and (mul461-cdr e) should evaluate to v2.
- For (mul461-isnull e), you should first evaluate e to a value v. If v is (mul461-null), then the testing expression should evaluate to mul461-bool #t; other wise the testing expression should evaluate to mul461-bool #f.
- For a mul461 expression e that is (mul461-fun fname formal body), it should be evaluated to a closure (mul461-closure e env) where env is the current env that provides mapping for all potential free vars in e.
- For a function call mul461 expression (mul461-call f actual), you should first evaluate f to v1 and actual to v2, and then make sure that v1 is a closure (or otherwise a type error should be raised). Assume v1 is a closure of the form (mul461-closure (mul461-fun fname formal body) env), then you should add these two bindings to the env in the closure (formal: v2, fname:v1, env) and evaluate body with this new environment that binds the formal parameter to the actual argument value and binds the function name to the function closure for recursive functions.
- Expanding the Language: mul461 is a small language, but we can write Racket functions that act like mul461 macros so that users of these functions feel like mul461 is larger. The Racket functions produce mul461 expressions that could then be put inside larger mul461 expressions or passed to eval-exp. In implementing these Racket functions, do not use closure (which is used only internally in eval-exp). Also do not use eval-exp (we are creating a program, not running it).
- Write a Racket function makelet* that takes a Racket list of Racket pairs ’((s1 . e1) …(si . ei) …(sn . en)) and a final mul461 expression en+1. In each pair, assume si is a Racket string and ei is a mul461 makelet* returns a mul461 expression whose value is en+1 evaluated in an environment where each si is a variable bound to the result of evaluating the corresponding ei for 1 ≤ i ≤ n. The bindings are done sequentially, so that each ei is evaluated in an environment where s1 through si−1 have been previously bound to the values e1 through ei−1.
- Write a Racket function makelist that takes a Racket list of mul461 expressions, and creates a mul461 expression that is essentially a list of these mul461 expressions using mul461-cons and mul461-null. Do not evaluate any of the expressions.
- Using the Language: We can write mul461 expressions directly in Racket using the constructors for the structs and (for convenience) the functions we wrote in the previous problem.
- Write a function makefactorial that gives a racket integer n, returns a mul461 expression that is similar to n ∗ ((n − 1) ∗ (n − 2)… ∗ 1) using mul461 For example (makefactorial 3) should return this value:
(mul461-* (mul461-int 3) (mul461-* (mul461-int 2) (mul461-int 1))).
- Bind to the Racket variable mul461-filter a mul461 function that acts like filter (as we used in Racket). Your function should be curried: it should take a mul461 function and return a mul461 function that takes a mul461 list and applies the function to every element of the list returning a new mul461 list with all the elements for which the function returns (mul461-bool #t). Recall a mul461 list is (mul461-null) or a pair where the second component is a mul461
- Bind to the Racket variable mul461-map a mul461 function that acts like map (as we used in Racket). Your function should be curried: it should take a mul461 function and return a mul461 function that takes a mul461 list and applies the function to every element of the list, returning a new mul461 list with all the elements be the return value of the function.




