2016-12-19 13:05:53 -05:00
|
|
|
package function.builtin;
|
2016-12-07 16:38:26 -05:00
|
|
|
|
2016-12-19 13:05:53 -05:00
|
|
|
import function.*;
|
2016-12-15 15:33:48 -05:00
|
|
|
import sexpression.*;
|
2016-12-07 16:38:26 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* <code>APPLY</code> represents the APPLY function in Lisp.
|
|
|
|
*/
|
|
|
|
public class APPLY extends LispFunction {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Call APPLY with the specified argument list.
|
|
|
|
*
|
|
|
|
* @param argList
|
2016-12-15 15:33:48 -05:00
|
|
|
* the list of arguments to be sent to APPLY (MUST BE A PROPER LIST)
|
|
|
|
* @return the result of evaluating APPLY on <code>argList</code>
|
2016-12-07 16:38:26 -05:00
|
|
|
*/
|
|
|
|
public static SExpression apply(Cons argList) {
|
|
|
|
return new APPLY().call(argList);
|
|
|
|
}
|
|
|
|
|
|
|
|
// The number of arguments that APPLY takes.
|
|
|
|
private static final int NUM_ARGS = 2;
|
|
|
|
|
|
|
|
public SExpression call(Cons argList) {
|
|
|
|
// retrieve the number of arguments passed to APPLY
|
|
|
|
int argListLength = LENGTH.getLength(argList);
|
|
|
|
|
|
|
|
// make sure we have received the proper number of arguments
|
|
|
|
if (argListLength != NUM_ARGS) {
|
|
|
|
Cons originalSExpr = new Cons(new Symbol("APPLY"), argList);
|
2016-12-15 15:33:48 -05:00
|
|
|
String errMsg = "too " + ((argListLength > NUM_ARGS) ? "many" : "few") + " arguments given to APPLY: "
|
|
|
|
+ originalSExpr;
|
2016-12-07 16:38:26 -05:00
|
|
|
|
|
|
|
throw new RuntimeException(errMsg);
|
|
|
|
}
|
|
|
|
|
2016-12-15 15:33:48 -05:00
|
|
|
SExpression car = argList.getCar(); // function name
|
2016-12-07 16:38:26 -05:00
|
|
|
Cons cdr = (Cons) argList.getCdr();
|
2016-12-15 15:33:48 -05:00
|
|
|
SExpression cadr = cdr.getCar(); // argument list
|
2016-12-07 16:38:26 -05:00
|
|
|
|
|
|
|
// make sure the second argument is a list
|
|
|
|
if (cadr.listp()) {
|
|
|
|
LispFunction function = EVAL.lookupFunction(car.toString());
|
|
|
|
|
|
|
|
if (function == null) {
|
|
|
|
// check if the car of the list is a lambda expression
|
|
|
|
if (car.functionp()) {
|
|
|
|
function = ((LambdaExpression) car).getFunction();
|
|
|
|
} else if (LAMBDA.isLambdaExpression(car)) {
|
|
|
|
Cons lexpr = (Cons) car;
|
|
|
|
|
|
|
|
function = LAMBDA.createFunction(lexpr);
|
|
|
|
} else {
|
|
|
|
throw new RuntimeException("undefined function " + car);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// apply the given function to the given argument list
|
|
|
|
return function.call((Cons) cadr);
|
|
|
|
}
|
|
|
|
|
|
|
|
// the second argument is not a list
|
|
|
|
throw new RuntimeException("APPLY: " + cadr + " is not a list");
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|