22c:054 Team Projects

Scheme Interpreter (Prolog, Oz)

Write an interpreter in any of the languages seen in class for a Scheme-like language. Refer to Chapter 10.3 of the textbook for a discussion of Scheme.

Implement the interpreter as the function TopEval which, takes a well-formed Scheme expression and returns the value of the expression, or a undefined value error if some identifier in the expression in unbound.

TopEval is defined in terms of the function Eval which, takes as input a Scheme expression and environment.

Environments

An environment is essentially a lookup table that contains value bindings for a certain number of variables. It can be conceptually described as an abstract datatype envir with the following signature and specification (given here in Miranda syntax).

abstype envir
with EmptyEnv:: envir
LookUp:: (schemeVar, envir) -> schemeVal
AddBinding:: (schemeVar, schemeVal, envir) -> envir
where

Closures

The evaluation of a lambda expression (the equivalent of anonymous functions in SML) produces an internal data structure called closure. In essence, a closure encapsulates the current environment into a lambda expression in order to preserve the values of non-local variables in the body of the lambda expression. (It is really closures that are passed around in functional programming, not plain anonymous functions.)

Closures can be conceptually described as an abstract datatype of the form:

abstype closure
with NewClos:: (schemeVar, schemeExp, envir) -> closure
ClosVar:: closure -> schemeVar
ClosExp:: closure -> schemeExp
ClosEnv:: closure -> envir
where

Scheme's Operational Semantics

The operational semantics of Scheme is defined by the following assertions describing the behavior of the Scheme interpreter. (The interpreter's funtions are in boldface to improve readability.)

TopEval

Eval Apply

Implementation Details (Oz)

For simplicity:

Hints: Be careful in implementing AddBinding. Expressions with occurrences of different local variables with the same name such as

((lambda (x) (plus x ((lambda (x) (times x x)) 4))) 3)
or
(plus ((lambda (x) (plus x 1)) 2) ((lambda (x) (plus x 1)) 4))

are legal in Scheme and behave as you would expect because variables are lexically scoped. Your implementation too must provide lexical scoping for variables.
(See Chapter 5.2 of the textbook for more details on lexical scoping).

Implementation Details (Prolog)

As for Oz, with the following differences:


Last Updated: Mar 6, 2000