Added special functions (forms) and refactored internal s-expression predicates
This commit is contained in:
parent
b9466d2c5d
commit
4f4bc8f71a
|
@ -65,10 +65,10 @@ public class ArgumentValidator {
|
||||||
private void validateListNotDotted(Cons argumentList) {
|
private void validateListNotDotted(Cons argumentList) {
|
||||||
SExpression next = argumentList.getRest();
|
SExpression next = argumentList.getRest();
|
||||||
|
|
||||||
for (Cons current = argumentList; next.consp(); next = current.getRest())
|
for (Cons current = argumentList; next.isCons(); next = current.getRest())
|
||||||
current = (Cons) next;
|
current = (Cons) next;
|
||||||
|
|
||||||
if (!next.nullp())
|
if (!next.isNull())
|
||||||
throw new DottedArgumentListException(functionName, argumentList);
|
throw new DottedArgumentListException(functionName, argumentList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ public class ArgumentValidator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isFirstArgumentValid(Cons argumentList) {
|
private boolean isFirstArgumentValid(Cons argumentList) {
|
||||||
return argumentList.nullp() || isExpectedFirstArgumentType(argumentList.getFirst());
|
return argumentList.isNull() || isExpectedFirstArgumentType(argumentList.getFirst());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isExpectedFirstArgumentType(SExpression firstArgument) {
|
private boolean isExpectedFirstArgumentType(SExpression firstArgument) {
|
||||||
|
@ -122,11 +122,11 @@ public class ArgumentValidator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isDisallowedNil(SExpression argument) {
|
private boolean isDisallowedNil(SExpression argument) {
|
||||||
return !isNilAcceptable && argument.nullp();
|
return !isNilAcceptable && argument.isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateTrailingArguments(Cons argumentList) {
|
private void validateTrailingArguments(Cons argumentList) {
|
||||||
for (Cons cons = (Cons) argumentList.getRest(); !cons.nullp(); cons = (Cons) cons.getRest())
|
for (Cons cons = (Cons) argumentList.getRest(); !cons.isNull(); cons = (Cons) cons.getRest())
|
||||||
if (!isExpectedTrailingArgumentType(cons.getFirst()))
|
if (!isExpectedTrailingArgumentType(cons.getFirst()))
|
||||||
throw new BadArgumentTypeException(functionName, cons.getFirst(), trailingArgumentType);
|
throw new BadArgumentTypeException(functionName, cons.getFirst(), trailingArgumentType);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,6 @@ public abstract class LispFunction {
|
||||||
|
|
||||||
public abstract SExpression call(Cons argList);
|
public abstract SExpression call(Cons argList);
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if the arguments passed to this Lisp function should be evaluated. A subclass
|
|
||||||
* should override this method to return false if it does not want its arguments to be evaluated
|
|
||||||
* prior to being passed.
|
|
||||||
*/
|
|
||||||
public boolean evaluateArguments() {
|
public boolean evaluateArguments() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package function;
|
||||||
|
|
||||||
|
public abstract class LispSpecialFunction extends LispFunction {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean evaluateArguments() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -24,7 +24,7 @@ public class UserDefinedFunction extends LispFunction {
|
||||||
this.executionContext = ExecutionContext.getInstance();
|
this.executionContext = ExecutionContext.getInstance();
|
||||||
this.functionScope = executionContext.getScope();
|
this.functionScope = executionContext.getScope();
|
||||||
|
|
||||||
for (this.formalParameters = new ArrayList<>(); lambdaList.consp(); lambdaList = (Cons) lambdaList.getRest())
|
for (this.formalParameters = new ArrayList<>(); lambdaList.isCons(); lambdaList = (Cons) lambdaList.getRest())
|
||||||
this.formalParameters.add(lambdaList.getFirst().toString());
|
this.formalParameters.add(lambdaList.getFirst().toString());
|
||||||
|
|
||||||
this.argumentValidator = new ArgumentValidator(this.name);
|
this.argumentValidator = new ArgumentValidator(this.name);
|
||||||
|
@ -38,10 +38,7 @@ public class UserDefinedFunction extends LispFunction {
|
||||||
SymbolTable callingScope = executionContext.getScope();
|
SymbolTable callingScope = executionContext.getScope();
|
||||||
executionContext.setScope(functionScope);
|
executionContext.setScope(functionScope);
|
||||||
|
|
||||||
SExpression lastEvaluation = Nil.getInstance();
|
SExpression lastEvaluation = evaluateBody();
|
||||||
|
|
||||||
for (Cons expression = body; expression.consp(); expression = (Cons) expression.getRest())
|
|
||||||
lastEvaluation = eval(expression.getFirst());
|
|
||||||
|
|
||||||
executionContext.setScope(callingScope);
|
executionContext.setScope(callingScope);
|
||||||
releaseParameterValues();
|
releaseParameterValues();
|
||||||
|
@ -59,6 +56,15 @@ public class UserDefinedFunction extends LispFunction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SExpression evaluateBody() {
|
||||||
|
SExpression lastEvaluation = Nil.getInstance();
|
||||||
|
|
||||||
|
for (Cons expression = body; expression.isCons(); expression = (Cons) expression.getRest())
|
||||||
|
lastEvaluation = eval(expression.getFirst());
|
||||||
|
|
||||||
|
return lastEvaluation;
|
||||||
|
}
|
||||||
|
|
||||||
private void releaseParameterValues() {
|
private void releaseParameterValues() {
|
||||||
functionScope = new SymbolTable(functionScope.getParent());
|
functionScope = new SymbolTable(functionScope.getParent());
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package function;
|
||||||
|
|
||||||
|
import sexpression.Cons;
|
||||||
|
|
||||||
|
public class UserDefinedSpecialFunction extends UserDefinedFunction {
|
||||||
|
|
||||||
|
public UserDefinedSpecialFunction(String name, Cons lambdaList, Cons body) {
|
||||||
|
super(name, lambdaList, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean evaluateArguments() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -21,7 +21,7 @@ public class EVAL extends LispFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LispFunction createLambdaFunction(SExpression lambdaExpression) {
|
private static LispFunction createLambdaFunction(SExpression lambdaExpression) {
|
||||||
if (lambdaExpression.functionp())
|
if (lambdaExpression.isFunction())
|
||||||
return ((LambdaExpression) lambdaExpression).getFunction();
|
return ((LambdaExpression) lambdaExpression).getFunction();
|
||||||
else if (LAMBDA.isLambdaExpression(lambdaExpression))
|
else if (LAMBDA.isLambdaExpression(lambdaExpression))
|
||||||
return LAMBDA.createFunction((Cons) lambdaExpression);
|
return LAMBDA.createFunction((Cons) lambdaExpression);
|
||||||
|
@ -59,14 +59,14 @@ public class EVAL extends LispFunction {
|
||||||
|
|
||||||
SExpression argument = argumentList.getFirst();
|
SExpression argument = argumentList.getFirst();
|
||||||
|
|
||||||
if (argument.listp()) {
|
if (argument.isList()) {
|
||||||
if (argument.consp())
|
if (argument.isCons())
|
||||||
return evaluateList((Cons) argument);
|
return evaluateList((Cons) argument);
|
||||||
|
|
||||||
return argument; // NIL
|
return argument; // NIL
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argument.symbolp()) {
|
if (argument.isSymbol()) {
|
||||||
SExpression symbolValue = lookupSymbol(argument.toString());
|
SExpression symbolValue = lookupSymbol(argument.toString());
|
||||||
|
|
||||||
if (symbolValue != null)
|
if (symbolValue != null)
|
||||||
|
@ -95,7 +95,7 @@ public class EVAL extends LispFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Cons evaluateArgList(Cons arguments) {
|
private Cons evaluateArgList(Cons arguments) {
|
||||||
if (arguments.nullp())
|
if (arguments.isNull())
|
||||||
return Nil.getInstance();
|
return Nil.getInstance();
|
||||||
|
|
||||||
SExpression first = eval(arguments.getFirst());
|
SExpression first = eval(arguments.getFirst());
|
||||||
|
|
|
@ -36,7 +36,7 @@ public class LENGTH extends LispFunction {
|
||||||
Cons list = (Cons) argumentList.getFirst();
|
Cons list = (Cons) argumentList.getFirst();
|
||||||
Cons restOfList = LIST.makeList(list.getRest());
|
Cons restOfList = LIST.makeList(list.getRest());
|
||||||
|
|
||||||
if (list.nullp())
|
if (list.isNull())
|
||||||
return new LispNumber(accumulatedLength);
|
return new LispNumber(accumulatedLength);
|
||||||
|
|
||||||
return callTailRecursive(increment(accumulatedLength), restOfList);
|
return callTailRecursive(increment(accumulatedLength), restOfList);
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class LIST extends LispFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Cons callRecursive(Cons argumentList) {
|
private Cons callRecursive(Cons argumentList) {
|
||||||
if (argumentList.nullp())
|
if (argumentList.isNull())
|
||||||
return Nil.getInstance();
|
return Nil.getInstance();
|
||||||
|
|
||||||
SExpression firstArgument = argumentList.getFirst();
|
SExpression firstArgument = argumentList.getFirst();
|
||||||
|
|
|
@ -20,7 +20,7 @@ class MathFunction {
|
||||||
SExpression firstArgument = argumentList.getFirst();
|
SExpression firstArgument = argumentList.getFirst();
|
||||||
LispNumber number1 = (LispNumber) firstArgument;
|
LispNumber number1 = (LispNumber) firstArgument;
|
||||||
|
|
||||||
if (remainingArguments.nullp())
|
if (remainingArguments.isNull())
|
||||||
return singleValueOperation.apply(number1);
|
return singleValueOperation.apply(number1);
|
||||||
|
|
||||||
SExpression secondArgument = remainingArguments.getFirst();
|
SExpression secondArgument = remainingArguments.getFirst();
|
||||||
|
@ -28,7 +28,7 @@ class MathFunction {
|
||||||
LispNumber operationResult = multipleValueOperation.apply(number1, number2);
|
LispNumber operationResult = multipleValueOperation.apply(number1, number2);
|
||||||
SExpression remainingNumbers = remainingArguments.getRest();
|
SExpression remainingNumbers = remainingArguments.getRest();
|
||||||
|
|
||||||
if (remainingNumbers.nullp())
|
if (remainingNumbers.isNull())
|
||||||
return operationResult;
|
return operationResult;
|
||||||
|
|
||||||
return callTailRecursive(new Cons(operationResult, remainingNumbers));
|
return callTailRecursive(new Cons(operationResult, remainingNumbers));
|
||||||
|
|
|
@ -16,7 +16,7 @@ public class ATOM extends LispFunction {
|
||||||
argumentValidator.validate(argumentList);
|
argumentValidator.validate(argumentList);
|
||||||
SExpression argument = argumentList.getFirst();
|
SExpression argument = argumentList.getFirst();
|
||||||
|
|
||||||
return argument.atomp() ? Symbol.T : Nil.getInstance();
|
return argument.isAtom() ? Symbol.T : Nil.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ public class EQ extends LispFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isAtomPair(SExpression firstArgument, SExpression secondArgument) {
|
private boolean isAtomPair(SExpression firstArgument, SExpression secondArgument) {
|
||||||
return firstArgument.atomp() && secondArgument.atomp();
|
return firstArgument.isAtom() && secondArgument.isAtom();
|
||||||
}
|
}
|
||||||
|
|
||||||
private SExpression atomEq(SExpression firstArgument, SExpression secondArgument) {
|
private SExpression atomEq(SExpression firstArgument, SExpression secondArgument) {
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class EQUAL extends LispFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isListPair(SExpression firstArgument, SExpression secondArgument) {
|
private boolean isListPair(SExpression firstArgument, SExpression secondArgument) {
|
||||||
return firstArgument.consp() && secondArgument.consp();
|
return firstArgument.isCons() && secondArgument.isCons();
|
||||||
}
|
}
|
||||||
|
|
||||||
private SExpression equal(SExpression firstArgument, SExpression secondArgument) {
|
private SExpression equal(SExpression firstArgument, SExpression secondArgument) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class EQUALSP extends LispFunction {
|
||||||
private SExpression callTailRecursive(Cons argumentList) {
|
private SExpression callTailRecursive(Cons argumentList) {
|
||||||
Cons remainingArguments = (Cons) argumentList.getRest();
|
Cons remainingArguments = (Cons) argumentList.getRest();
|
||||||
|
|
||||||
if (remainingArguments.nullp())
|
if (remainingArguments.isNull())
|
||||||
return Symbol.T;
|
return Symbol.T;
|
||||||
|
|
||||||
SExpression firstArgument = argumentList.getFirst();
|
SExpression firstArgument = argumentList.getFirst();
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class GREATERP extends LispFunction {
|
||||||
private SExpression callTailRecursive(Cons argumentList) {
|
private SExpression callTailRecursive(Cons argumentList) {
|
||||||
Cons remainingArguments = (Cons) argumentList.getRest();
|
Cons remainingArguments = (Cons) argumentList.getRest();
|
||||||
|
|
||||||
if (remainingArguments.nullp())
|
if (remainingArguments.isNull())
|
||||||
return Symbol.T;
|
return Symbol.T;
|
||||||
|
|
||||||
SExpression firstArgument = argumentList.getFirst();
|
SExpression firstArgument = argumentList.getFirst();
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class LESSP extends LispFunction {
|
||||||
private SExpression callTailRecursive(Cons argumentList) {
|
private SExpression callTailRecursive(Cons argumentList) {
|
||||||
Cons remainingArguments = (Cons) argumentList.getRest();
|
Cons remainingArguments = (Cons) argumentList.getRest();
|
||||||
|
|
||||||
if (remainingArguments.nullp())
|
if (remainingArguments.isNull())
|
||||||
return Symbol.T;
|
return Symbol.T;
|
||||||
|
|
||||||
SExpression firstArgument = argumentList.getFirst();
|
SExpression firstArgument = argumentList.getFirst();
|
||||||
|
|
|
@ -15,7 +15,7 @@ public class LISTP extends LispFunction {
|
||||||
public SExpression call(Cons argumentList) {
|
public SExpression call(Cons argumentList) {
|
||||||
argumentValidator.validate(argumentList);
|
argumentValidator.validate(argumentList);
|
||||||
|
|
||||||
return argumentList.getFirst().listp() ? Symbol.T : Nil.getInstance();
|
return argumentList.getFirst().isList() ? Symbol.T : Nil.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ public class NULL extends LispFunction {
|
||||||
public SExpression call(Cons argumentList) {
|
public SExpression call(Cons argumentList) {
|
||||||
argumentValidator.validate(argumentList);
|
argumentValidator.validate(argumentList);
|
||||||
|
|
||||||
return argumentList.getFirst().nullp() ? Symbol.T : Nil.getInstance();
|
return argumentList.getFirst().isNull() ? Symbol.T : Nil.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import static function.builtin.EVAL.eval;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
public class AND extends LispFunction {
|
public class AND extends LispSpecialFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
||||||
|
@ -23,17 +23,13 @@ public class AND extends LispFunction {
|
||||||
SExpression currentValue = eval(argumentList.getFirst());
|
SExpression currentValue = eval(argumentList.getFirst());
|
||||||
Cons remainingValues = (Cons) argumentList.getRest();
|
Cons remainingValues = (Cons) argumentList.getRest();
|
||||||
|
|
||||||
if (argumentList.nullp())
|
if (argumentList.isNull())
|
||||||
return lastValue;
|
return lastValue;
|
||||||
|
|
||||||
if (currentValue.nullp())
|
if (currentValue.isNull())
|
||||||
return currentValue;
|
return currentValue;
|
||||||
|
|
||||||
return callTailRecursive(remainingValues, currentValue);
|
return callTailRecursive(remainingValues, currentValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean evaluateArguments() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import static function.builtin.EVAL.eval;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
public class COND extends LispFunction {
|
public class COND extends LispSpecialFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ public class COND extends LispFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
private SExpression callTailRecursive(Cons argumentList) {
|
private SExpression callTailRecursive(Cons argumentList) {
|
||||||
if (argumentList.nullp())
|
if (argumentList.isNull())
|
||||||
return Nil.getInstance();
|
return Nil.getInstance();
|
||||||
|
|
||||||
Cons clause = (Cons) argumentList.getFirst();
|
Cons clause = (Cons) argumentList.getFirst();
|
||||||
|
@ -42,7 +42,7 @@ public class COND extends LispFunction {
|
||||||
private SExpression evaluateResult(Cons clause, SExpression test) {
|
private SExpression evaluateResult(Cons clause, SExpression test) {
|
||||||
SExpression lastResultValue = test;
|
SExpression lastResultValue = test;
|
||||||
|
|
||||||
for (SExpression result = clause.getRest(); result.consp(); result = advanceCons(result))
|
for (SExpression result = clause.getRest(); result.isCons(); result = advanceCons(result))
|
||||||
lastResultValue = eval(getFirst(result));
|
lastResultValue = eval(getFirst(result));
|
||||||
|
|
||||||
return lastResultValue;
|
return lastResultValue;
|
||||||
|
@ -56,8 +56,4 @@ public class COND extends LispFunction {
|
||||||
return ((Cons) knownCons).getFirst();
|
return ((Cons) knownCons).getFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean evaluateArguments() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import function.builtin.cons.LIST;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
import table.FunctionTable;
|
import table.FunctionTable;
|
||||||
|
|
||||||
public class DEFUN extends LispFunction {
|
public class DEFUN extends LispSpecialFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
private ArgumentValidator lambdaListIsListValidator;
|
private ArgumentValidator lambdaListIsListValidator;
|
||||||
|
@ -52,10 +52,6 @@ public class DEFUN extends LispFunction {
|
||||||
return functionName;
|
return functionName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean evaluateArguments() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class RedefiningFunctionWarning extends LispWarning {
|
public class RedefiningFunctionWarning extends LispWarning {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
|
@ -5,7 +5,7 @@ import static function.builtin.EVAL.eval;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
public class IF extends LispFunction {
|
public class IF extends LispSpecialFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ public class IF extends LispFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isNil(SExpression test) {
|
private boolean isNil(SExpression test) {
|
||||||
return test.nullp();
|
return test.isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
private SExpression getThenForm(Cons argumentList) {
|
private SExpression getThenForm(Cons argumentList) {
|
||||||
|
@ -45,8 +45,4 @@ public class IF extends LispFunction {
|
||||||
return getRestOfList(expressions).getFirst();
|
return getRestOfList(expressions).getFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean evaluateArguments() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,10 @@ import static function.builtin.cons.LIST.makeList;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
public class LAMBDA extends LispFunction {
|
public class LAMBDA extends LispSpecialFunction {
|
||||||
|
|
||||||
public static boolean isLambdaExpression(SExpression sexpr) {
|
public static boolean isLambdaExpression(SExpression sexpr) {
|
||||||
if (sexpr.consp()) {
|
if (sexpr.isCons()) {
|
||||||
SExpression first = ((Cons) sexpr).getFirst();
|
SExpression first = ((Cons) sexpr).getFirst();
|
||||||
|
|
||||||
return "LAMBDA".equals(first.toString());
|
return "LAMBDA".equals(first.toString());
|
||||||
|
@ -59,8 +59,4 @@ public class LAMBDA extends LispFunction {
|
||||||
return new Cons(new Symbol("LAMBDA"), argumentList);
|
return new Cons(new Symbol("LAMBDA"), argumentList);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean evaluateArguments() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
import table.*;
|
import table.*;
|
||||||
|
|
||||||
public class LET extends LispFunction {
|
public class LET extends LispSpecialFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
private ArgumentValidator variableDefinitionListValidator;
|
private ArgumentValidator variableDefinitionListValidator;
|
||||||
|
@ -55,7 +55,7 @@ public class LET extends LispFunction {
|
||||||
private void addVariablesToScope(SymbolTable scope, Cons variableDefinitions) {
|
private void addVariablesToScope(SymbolTable scope, Cons variableDefinitions) {
|
||||||
variableDefinitionListValidator.validate(variableDefinitions);
|
variableDefinitionListValidator.validate(variableDefinitions);
|
||||||
|
|
||||||
for (; variableDefinitions.consp(); variableDefinitions = (Cons) variableDefinitions.getRest())
|
for (; variableDefinitions.isCons(); variableDefinitions = (Cons) variableDefinitions.getRest())
|
||||||
addPairToScope((Cons) variableDefinitions.getFirst(), scope);
|
addPairToScope((Cons) variableDefinitions.getFirst(), scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ public class LET extends LispFunction {
|
||||||
private SExpression evaluateBody(Cons body) {
|
private SExpression evaluateBody(Cons body) {
|
||||||
SExpression lastEvaluation = Nil.getInstance();
|
SExpression lastEvaluation = Nil.getInstance();
|
||||||
|
|
||||||
for (; body.consp(); body = (Cons) body.getRest())
|
for (; body.isCons(); body = (Cons) body.getRest())
|
||||||
lastEvaluation = eval(body.getFirst());
|
lastEvaluation = eval(body.getFirst());
|
||||||
|
|
||||||
return lastEvaluation;
|
return lastEvaluation;
|
||||||
|
@ -82,8 +82,4 @@ public class LET extends LispFunction {
|
||||||
executionContext.setScope(localScope.getParent());
|
executionContext.setScope(localScope.getParent());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean evaluateArguments() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import static function.builtin.EVAL.eval;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
public class OR extends LispFunction {
|
public class OR extends LispSpecialFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
||||||
|
@ -23,14 +23,10 @@ public class OR extends LispFunction {
|
||||||
SExpression currentValue = eval(argumentList.getFirst());
|
SExpression currentValue = eval(argumentList.getFirst());
|
||||||
Cons remainingValues = (Cons) argumentList.getRest();
|
Cons remainingValues = (Cons) argumentList.getRest();
|
||||||
|
|
||||||
if (remainingValues.nullp() || !currentValue.nullp())
|
if (remainingValues.isNull() || !currentValue.isNull())
|
||||||
return currentValue;
|
return currentValue;
|
||||||
|
|
||||||
return callTailRecursive(remainingValues);
|
return callTailRecursive(remainingValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean evaluateArguments() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package function.builtin.special;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
public class QUOTE extends LispFunction {
|
public class QUOTE extends LispSpecialFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
||||||
|
@ -18,8 +18,4 @@ public class QUOTE extends LispFunction {
|
||||||
return argumentList.getFirst();
|
return argumentList.getFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean evaluateArguments() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
import table.*;
|
import table.*;
|
||||||
|
|
||||||
public class SETF extends LispFunction {
|
public class SETF extends LispSpecialFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
private ExecutionContext executionContext;
|
private ExecutionContext executionContext;
|
||||||
|
@ -48,8 +48,4 @@ public class SETF extends LispFunction {
|
||||||
return table.getParent() == null;
|
return table.getParent() == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean evaluateArguments() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ public abstract class Atom extends SExpression {
|
||||||
this.text = text;
|
this.text = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean atomp() {
|
public boolean isAtom() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ public class Cons extends SExpression {
|
||||||
this.rest = rest;
|
this.rest = rest;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean consp() {
|
public boolean isCons() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,9 +36,9 @@ public class Cons extends SExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String toStringAux() {
|
private String toStringAux() {
|
||||||
if (rest.nullp())
|
if (rest.isNull())
|
||||||
return (first.toString() + ")");
|
return (first.toString() + ")");
|
||||||
else if (rest.consp())
|
else if (rest.isCons())
|
||||||
return (first.toString() + " " + ((Cons) rest).toStringAux());
|
return (first.toString() + " " + ((Cons) rest).toStringAux());
|
||||||
|
|
||||||
return (first.toString() + " . " + rest.toString() + ")");
|
return (first.toString() + " . " + rest.toString() + ")");
|
||||||
|
|
|
@ -13,7 +13,7 @@ public class LambdaExpression extends SExpression {
|
||||||
this.function = function;
|
this.function = function;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean functionp() {
|
public boolean isFunction() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ public class LispNumber extends Atom {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean numberp() {
|
public boolean isNumber() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ public class LispString extends Atom {
|
||||||
super(text);
|
super(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean stringp() {
|
public boolean isString() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,19 +16,19 @@ public class Nil extends Cons {
|
||||||
super.setRest(this);
|
super.setRest(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean nullp() {
|
public boolean isNull() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean atomp() {
|
public boolean isAtom() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean consp() {
|
public boolean isCons() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean symbolp() {
|
public boolean isSymbol() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,35 +3,35 @@ package sexpression;
|
||||||
@DisplayName("s-expression")
|
@DisplayName("s-expression")
|
||||||
public abstract class SExpression {
|
public abstract class SExpression {
|
||||||
|
|
||||||
public boolean nullp() {
|
public boolean isNull() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean atomp() {
|
public boolean isAtom() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean consp() {
|
public boolean isCons() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean listp() {
|
public boolean isList() {
|
||||||
return (consp() || nullp());
|
return (isCons() || isNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean numberp() {
|
public boolean isNumber() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean symbolp() {
|
public boolean isSymbol() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean functionp() {
|
public boolean isFunction() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean stringp() {
|
public boolean isString() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ public class Symbol extends Atom {
|
||||||
super(text.toUpperCase());
|
super(text.toUpperCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean symbolp() {
|
public boolean isSymbol() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,6 @@ import java.util.function.Supplier;
|
||||||
import file.FilePosition;
|
import file.FilePosition;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
/**
|
|
||||||
* A token in Lisp.
|
|
||||||
*/
|
|
||||||
public abstract class Token {
|
public abstract class Token {
|
||||||
|
|
||||||
private String text;
|
private String text;
|
||||||
|
@ -26,10 +23,12 @@ public abstract class Token {
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sExpr ::= NUMBER | IDENTIFIER | STRING | QUOTE_MARK sExpr | LEFT_PAREN sExprTail
|
// s-expression ::= NUMBER | IDENTIFIER | STRING | QUOTE_MARK s-expression | LEFT_PAREN
|
||||||
|
// s-expression-tail
|
||||||
|
// s-expression-tail ::= RIGHT_PAREN | s-expression s-expression-tail
|
||||||
|
|
||||||
public abstract SExpression parseSExpression(Supplier<Token> getNextToken);
|
public abstract SExpression parseSExpression(Supplier<Token> getNextToken);
|
||||||
|
|
||||||
// sExprTail ::= RIGHT_PAREN | sExpr sExprTail
|
|
||||||
public SExpression parseSExpressionTail(Supplier<Token> getNextToken) {
|
public SExpression parseSExpressionTail(Supplier<Token> getNextToken) {
|
||||||
SExpression first = parseSExpression(getNextToken);
|
SExpression first = parseSExpression(getNextToken);
|
||||||
|
|
||||||
|
|
|
@ -7,61 +7,61 @@ import sexpression.*;
|
||||||
public final class TypeAssertions {
|
public final class TypeAssertions {
|
||||||
|
|
||||||
public static void assertList(SExpression sExpression) {
|
public static void assertList(SExpression sExpression) {
|
||||||
assertFalse(sExpression.atomp());
|
assertFalse(sExpression.isAtom());
|
||||||
assertTrue(sExpression.consp());
|
assertTrue(sExpression.isCons());
|
||||||
assertFalse(sExpression.functionp());
|
assertFalse(sExpression.isFunction());
|
||||||
assertTrue(sExpression.listp());
|
assertTrue(sExpression.isList());
|
||||||
assertFalse(sExpression.nullp());
|
assertFalse(sExpression.isNull());
|
||||||
assertFalse(sExpression.numberp());
|
assertFalse(sExpression.isNumber());
|
||||||
assertFalse(sExpression.stringp());
|
assertFalse(sExpression.isString());
|
||||||
assertFalse(sExpression.symbolp());
|
assertFalse(sExpression.isSymbol());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void assertNil(SExpression sExpression) {
|
public static void assertNil(SExpression sExpression) {
|
||||||
assertEquals(Nil.getInstance(), sExpression);
|
assertEquals(Nil.getInstance(), sExpression);
|
||||||
|
|
||||||
assertTrue(sExpression.atomp());
|
assertTrue(sExpression.isAtom());
|
||||||
assertFalse(sExpression.consp());
|
assertFalse(sExpression.isCons());
|
||||||
assertFalse(sExpression.functionp());
|
assertFalse(sExpression.isFunction());
|
||||||
assertTrue(sExpression.listp());
|
assertTrue(sExpression.isList());
|
||||||
assertTrue(sExpression.nullp());
|
assertTrue(sExpression.isNull());
|
||||||
assertFalse(sExpression.numberp());
|
assertFalse(sExpression.isNumber());
|
||||||
assertFalse(sExpression.stringp());
|
assertFalse(sExpression.isString());
|
||||||
assertTrue(sExpression.symbolp());
|
assertTrue(sExpression.isSymbol());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void assertNumber(SExpression sExpression) {
|
public static void assertNumber(SExpression sExpression) {
|
||||||
assertTrue(sExpression.atomp());
|
assertTrue(sExpression.isAtom());
|
||||||
assertFalse(sExpression.consp());
|
assertFalse(sExpression.isCons());
|
||||||
assertFalse(sExpression.functionp());
|
assertFalse(sExpression.isFunction());
|
||||||
assertFalse(sExpression.listp());
|
assertFalse(sExpression.isList());
|
||||||
assertFalse(sExpression.nullp());
|
assertFalse(sExpression.isNull());
|
||||||
assertTrue(sExpression.numberp());
|
assertTrue(sExpression.isNumber());
|
||||||
assertFalse(sExpression.stringp());
|
assertFalse(sExpression.isString());
|
||||||
assertFalse(sExpression.symbolp());
|
assertFalse(sExpression.isSymbol());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void assertString(SExpression sExpression) {
|
public static void assertString(SExpression sExpression) {
|
||||||
assertTrue(sExpression.atomp());
|
assertTrue(sExpression.isAtom());
|
||||||
assertFalse(sExpression.consp());
|
assertFalse(sExpression.isCons());
|
||||||
assertFalse(sExpression.functionp());
|
assertFalse(sExpression.isFunction());
|
||||||
assertFalse(sExpression.listp());
|
assertFalse(sExpression.isList());
|
||||||
assertFalse(sExpression.nullp());
|
assertFalse(sExpression.isNull());
|
||||||
assertFalse(sExpression.numberp());
|
assertFalse(sExpression.isNumber());
|
||||||
assertTrue(sExpression.stringp());
|
assertTrue(sExpression.isString());
|
||||||
assertFalse(sExpression.symbolp());
|
assertFalse(sExpression.isSymbol());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void assertSymbol(SExpression sExpression) {
|
public static void assertSymbol(SExpression sExpression) {
|
||||||
assertTrue(sExpression.atomp());
|
assertTrue(sExpression.isAtom());
|
||||||
assertFalse(sExpression.consp());
|
assertFalse(sExpression.isCons());
|
||||||
assertFalse(sExpression.functionp());
|
assertFalse(sExpression.isFunction());
|
||||||
assertFalse(sExpression.listp());
|
assertFalse(sExpression.isList());
|
||||||
assertFalse(sExpression.nullp());
|
assertFalse(sExpression.isNull());
|
||||||
assertFalse(sExpression.numberp());
|
assertFalse(sExpression.isNumber());
|
||||||
assertFalse(sExpression.stringp());
|
assertFalse(sExpression.isString());
|
||||||
assertTrue(sExpression.symbolp());
|
assertTrue(sExpression.isSymbol());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void assertT(SExpression sExpression) {
|
public static void assertT(SExpression sExpression) {
|
||||||
|
|
Loading…
Reference in New Issue