...

- (40 pts.) Write an evaluator for arithmetic expressions as follows:
- Write the (function) template for
`ArithExpr`

Write a function

that maps an`to-list`

to the corresponding "list" representation in Racket. Numbers are unchanged. Some other examples include:`ArithExpr`

Code Block (to-list 21) => 21 (to-list (make-sum (make-prod 4 7) 25)) => '(+ (* 4 7) 25) (to-list (make-quot (make-diff 4 7) 25)) => '(/ (- 4 7) 25)

Notes:

The notation

abbreviates**'(+ (* 4 7) 25)**.`(list '+ (list '* 4 7) 25)`

You need to define the output type (named

) for this function, but you can omit the template because this assignment does not include any functions that process this type. There are several mathematically distinct definitions that are correct. Some are more restrictive (narrower) than others but all are correct. In general, narrow definitions are better because they imply stronger claims about the elements of the type.`RacketExpr`

The notation

abbreviates**'(+ (* 4 7) 25)**.`(list '+ (list '* 4 7) 25)`

- Write a function
that evaluates an`eval: ArithExpr -> number`

. Your evaluator should produce exactly the same result for an`ArithExpr`

that Racket evaluation would produce for the list representation`ArithExpr`

`E`

.`(to-list E)`

- Write the (function) template for
- (40 pts.) Extend the definition of
as follows:`ArithExpr`

- Add a clause for variables represented as Racket symbols.
- Write the (function) template for this extended definition; it should be similar to your template for
from Problem 1.`ArithExpr`

- Modify your definition of
to support the expanded definition of`to-list`

.`ArithExpr`

Given the Racket structure definition:

Code Block (define-structure binding (var val))

a

is`binding`

where`(make-binding s n)`

is a symbol and`s`

`n`

is a number. Anis a`environment`

.`(list-of binding)`

.`environment`

- Define a top-level variable
that is bound to the empty`empty-env`

containing no bindings (`environment`

*i.e.*, thelist). Note that`empty`

is really a constant since variables cannot be re-bound in our functional subset of Racket.`empty-env`

Write a function

that takes environment`extend`

, a symbol`env`

, and a number`s`

, and returns an extended environment identical to`n`

except that it adds the additional binding of`env`

to`s`

(as the most`n`

*local*[*inner*] binding).

The definition ofis trivial; it requires no recursion. As a result,`extend`

satisfies the invariant`extend`

Code Block (check-expect (extend empty-env s n) (list (make-binding s n)))

where

is any symbol and`s`

is any number. Hence,`n`

Code Block (extend empty-env 'a 4) => (list (make-binding 'a 4))

In the remainder of the problem, use

and`empty-env`

to define example environments for test cases.`extend`

- Write a function
that takes a symbol`lookup`

and an environment`s`

and returns the first`env`

in`binding`

with a`env`

component that equals`var`

. If no match is found,`s`

returns`lookup`

. Note that the return type of`empty`

is not simply`lookup`

because it can return`binding`

. Define the new union type called`empty`

for the return type. You do not need to write a template for this type since it is a trivial union type.`option-binding`

Write a new

function for the expanded definition of`eval`

. The new`ArithExpr`

takes`eval`

*two*arguments: an`ArithExpr`

**E****environment env****specifying the values of free variables in**. For example,`E`

Code Block (eval 'x (extend empty-env 'x 17)) => 17 (eval (make-prod 4 7) (extend empty-env 'x 17)) = 28 (eval 'y (extend empty-env 'x 17)) => some form of run-time error

**If an**`ArithExpr`

contains a free variable that is not bound in the`E`

, then`environment env`

will naturally produce some form of run-time error if you have correctly coded`(eval E env)`

. Do`eval`

*not*explicitly test for this form of error since the behavioral contract forsays nothing about detecting errors.`eval`

**(20 pts.) An**is really a finite function (a finite set of ordered pairs). It is`environment`

*finite*in the sense that it can be completely defined by a finite table, which is not true of nearly all the primitive and library functions in Racket (and other programming languages). Even the identity function is*not*finite. For the purpose of this exercise, we redefine the typeas`environment`

which includes infinite objects (since`(symbol -> option-binding)`

is infinite).`symbol`

- Rewrite
to use`eval`

defined as the type`environment`

instead of as a`(symbol -> option-binding)`

. If you cleanly coded your definition of`(list-of option-binding)`

in the preceding problem using`eval`

,`lookup`

, and`make-binding`

, all that you have to do to your solution to the previous problem is redefine the bindings of`extend`

,`lookup`

, and`empty-env`

`extend`

. You can literally copy the entire text of your solution to problem 2; change the definitions of`extend`

,`lookup`

, and`empty-env`

; update your documentation (annotations) concerning the`extend`

type; and revise your tests for`environment`

. Note that`extend`

cannot be directly tested (since the result is a function!) but we can write indirect tests by using`extend`

to examine it. (Note: if you wrote a correct solution to problem 2, you can do this problem in less than 15 minutes!)`lookup`

**Hint:**you can use-notation in Racket to define a constant function for`lambda`

`empty-env`

can be defined as a functional that takes a function (representing an environment) and adds a new pair to the function--using an`extend`

`if`

embedded inside a-abstraction.`lambda`

- Rewrite
**Extra Credit (50 pts.) Add support for**-abstractions in your evaluator from Problem 2 as follows:`lambda`

- Extend the definition of
by adding a clause for unary`ArithExpr`

`lambda`

-*abstractions*and a clause for*unary applications*of an(which can be a function!) to an`ArithExpr`

. Use the name`ArithExpr`

for the structure representing a`lam`

`lambda`

-*abstraction*and the namesand`var`

for the accessors of this structure. Use the name`body`

for the structure representing a`app`

*unary application*and the namesand`rator`

for the argument of this structure. Note that the`rand`

of an`rator`

`app`

is annot a`ArithExpr`

(which is a proper subtype of`lam`

**ArithExpr** - Write a template for this additional expansion of the definition of
.`ArithExpr`

- Extend the definition of
to support this expansion of the definition of`to-list`

. You print the corresponding "concrete" syntax that would be given as input to a compiler. Hence,`ArithExpr`

(`to-list (make-lam 'x (make-plus 'x 'y))) => (list 'lambda (list 'x) '(+ x y)) = '(lambda (x) (+ x y))`

- Extend the definition of
to support this expansion of`eval`

. Note that`ArithExpr`

can now return functions as well as numbers. Your biggest challenge is determining a good representation for function values. What does`eval`

return as the value of a`eval`

input? That input may contain free variables. In principle, you could represent the value of the`lam`

input by a revised`lam`

(with no free variables) obtained by substituting the values for free variables from the environment input (just like we do in hand-evaluation). But this approach is tedious and computationally expensive. A better strategy is to define a structure type (called a`lam`

*closure*) to represent a function value. The structure type must contain the originaland a description of what substitution (of values for identifiersfree variables) would have been made, deferring the actual substitution just as`lam`

defers substitutions by maintaining an environment. For this problem, you can use brute force to describe the substitution, which makes constructing and applying closures nearly trivial to code. In practice, there are much more computationally efficient approaches.`eval`

- Extend the definition of