Started refactoring UserDefinedFunction

This commit is contained in:
Mike Cifelli 2017-01-27 16:19:09 -05:00
parent 27fdc7b328
commit 5351168763
1 changed files with 26 additions and 20 deletions

View File

@ -12,7 +12,7 @@ public class UserDefinedFunction extends LispFunction {
private String name; private String name;
private Cons body; private Cons body;
private Cons lambdaExpression; private Cons lambdaExpression;
private SymbolTable environment; private SymbolTable scope;
private ArrayList<String> formalParameters; private ArrayList<String> formalParameters;
private ArgumentValidator argumentValidator; private ArgumentValidator argumentValidator;
@ -20,7 +20,7 @@ public class UserDefinedFunction extends LispFunction {
this.name = name; this.name = name;
this.body = body; this.body = body;
this.lambdaExpression = new Cons(new Symbol(name), new Cons(lambdaList, body)); this.lambdaExpression = new Cons(new Symbol(name), new Cons(lambdaList, body));
this.environment = SETF.getSymbolTable(); this.scope = SETF.getSymbolTable();
for (this.formalParameters = new ArrayList<>(); lambdaList.consp(); lambdaList = (Cons) lambdaList.getCdr()) for (this.formalParameters = new ArrayList<>(); lambdaList.consp(); lambdaList = (Cons) lambdaList.getCdr())
this.formalParameters.add(lambdaList.getCar().toString()); this.formalParameters.add(lambdaList.getCar().toString());
@ -29,46 +29,52 @@ public class UserDefinedFunction extends LispFunction {
this.argumentValidator.setExactNumberOfArguments(this.formalParameters.size()); this.argumentValidator.setExactNumberOfArguments(this.formalParameters.size());
} }
public SExpression call(Cons argList) { public SExpression call(Cons argumentList) {
argumentValidator.validate(argList); argumentValidator.validate(argumentList);
// push a new symbol table onto this function's environment (for its
// parameters)
environment = new SymbolTable(environment);
// bind the values of the arguments to the formal parameter names // bind the values of the arguments to the formal parameter names
for (String param : formalParameters) { bindParameterValues(argumentList);
SExpression currentArg = argList.getCar();
environment.put(param, currentArg);
argList = (Cons) argList.getCdr();
}
// store the environment of the S-expression that called this function // store the environment of the S-expression that called this function
// (the current environment) // (the current environment)
SymbolTable currentEnvironment = SETF.getSymbolTable(); SymbolTable callingScope = SETF.getSymbolTable();
// replace the current environment with the environment of this // replace the current environment with the environment of this
// function // function
SETF.setSymbolTable(environment); SETF.setSymbolTable(scope);
Cons currentSExpression = body; Cons currentSExpression = body;
SExpression retval = null; SExpression lastValue = null;
// evaluate all the S-expressions making up this function's body // evaluate all the S-expressions making up this function's body
while (currentSExpression.consp()) { while (currentSExpression.consp()) {
retval = EVAL.eval(currentSExpression.getCar()); lastValue = EVAL.eval(currentSExpression.getCar());
currentSExpression = (Cons) currentSExpression.getCdr(); currentSExpression = (Cons) currentSExpression.getCdr();
} }
// replace the environment of the S-expression that called this // replace the environment of the S-expression that called this
// function // function
SETF.setSymbolTable(currentEnvironment); SETF.setSymbolTable(callingScope);
// remove the bindings of the arguments to the formal parameter names // remove the bindings of the arguments to the formal parameter names
// in the environment of this function // in the environment of this function
environment = new SymbolTable(environment.getParent()); releaseParameterValues();
return retval; return lastValue;
}
private void bindParameterValues(Cons argumentList) {
scope = new SymbolTable(scope);
for (String parameter : formalParameters) {
SExpression currentArg = argumentList.getCar();
scope.put(parameter, currentArg);
argumentList = (Cons) argumentList.getCdr();
}
}
private void releaseParameterValues() {
scope = new SymbolTable(scope.getParent());
} }
public Cons getLambdaExpression() { public Cons getLambdaExpression() {