transcendental-lisp/eval/LET.java

117 lines
4.0 KiB
Java

/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 2
*/
package eval;
import parser.*;
/**
* <code>LET</code> represents the LET form in Lisp.
*/
public class LET extends LispFunction {
public SExpression call(Cons argList) {
// make sure we have received at least one argument
if (argList.nullp()) {
throw new RuntimeException("too few arguments given to LET");
}
// create a new symbol table on top of the current environment to add
// all the local variables to
SymbolTable environment = new SymbolTable(SETF.getEnvironment());
SExpression car = argList.getCar();
Cons cdr = (Cons) argList.getCdr();
addVariablesToTable(environment, car);
SETF.setEnvironment(environment);
SExpression retval = Nil.getUniqueInstance();
// evaluate all S-expression in the body
while (cdr.consp()) {
retval = EVAL.eval(cdr.getCar());
cdr = (Cons) cdr.getCdr();
}
// restore the environment to its original value
SETF.setEnvironment(environment.getParent());
return retval;
}
// Add a list of variables and their values to the specified symbol table.
//
// Parameters: environment - the symbol table to add the variables and
// their values to (must not be null)
// vars - a list of variable/value pairs (must be either a
// proper list of pairs or NIL)
// Throws: RuntimeException - Indicates that 'vars' is not a proper list or
// that it contains an member that is not a
// variable/value pair.
// Precondition: 'environment' and 'vars' must not be null.
// Postcondition: All of the variables in 'vars' have been placed into
// 'environment' with their values.
private void addVariablesToTable(SymbolTable environment,
SExpression vars) {
// makes sure the list of variable/value pairs is a list
if (! vars.listp()) {
throw new RuntimeException("LET: " + vars +
" is not a properly formatted" +
" variable/value pair list");
}
// add all variables in 'vars' to 'environment'
while (vars.consp()) {
Cons varList = (Cons) vars;
SExpression varListCar = varList.getCar();
// make sure this variable/value pair is a list
if (! varListCar.consp()) {
throw new RuntimeException("LET: " + varListCar +
" is not a properly formatted" +
" variable/value pair");
}
Cons varSpec = (Cons) varListCar;
SExpression symbol = varSpec.getCar();
SExpression varSpecCdr = varSpec.getCdr();
// make sure this variable pair has a value associated with it
if (! varSpecCdr.consp()) {
throw new RuntimeException("LET: illegal variable " +
"specification " + varSpec);
}
Cons varValue = (Cons) varSpecCdr;
SExpression value = varValue.getCar();
// make sure there are no more members of this variable/value pair
// and that 'symbol' is actually a symbol
if ((! varValue.getCdr().nullp()) || (! symbol.symbolp())) {
throw new RuntimeException("LET: illegal variable " +
"specification " + varSpec);
}
environment.put(symbol.toString(), value);
vars = varList.getCdr();
}
}
/**
* Determine if the arguments passed to this Lisp function should be
* evaluated.
*
* @return
* <code>false</code>
*/
public boolean evaluateArguments() {
return false;
}
}