Started changing car/cdr to first/rest, modified acceptance test fixture
This commit is contained in:
parent
496f30cded
commit
0855789fde
|
@ -29,20 +29,13 @@ public class LispInterpreterFixture {
|
|||
return builder.build();
|
||||
}
|
||||
|
||||
public void input(String input) throws IOException {
|
||||
public String evaluate(String input) throws IOException {
|
||||
environment.setInput(new ByteArrayInputStream(input.getBytes()));
|
||||
interpreter.interpret();
|
||||
}
|
||||
|
||||
public String output() {
|
||||
String output = outputStream.toString();
|
||||
discardOutput();
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public void discardOutput() {
|
||||
outputStream.reset();
|
||||
|
||||
return output.trim();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
Test
|
||||
---
|
||||
| script | lisp interpreter fixture |
|
||||
| evaluate | (defun adderx (x) (lambda (y) (+ x y))) |
|
||||
| evaluate | (setf adder20 (adderx 20)) |
|
||||
| check | evaluate | (funcall adder20 2) | 22 |
|
|
@ -1,9 +0,0 @@
|
|||
| script | lisp interpreter fixture |
|
||||
| input | (defun adderx (x) (lambda (y) (+ x y))) |
|
||||
| discard output |
|
||||
| input | (setf adder20 (adderx 20)) |
|
||||
| discard output |
|
||||
| input | (funcall adder20 2) |
|
||||
| check | output |!-22
|
||||
|
||||
-!|
|
|
@ -1,4 +1,4 @@
|
|||
|LispInterpreter.TestOne||09:26:08 Fri, Feb 24, 2017|
|
||||
|LispInterpreter.SuiteSetUp||14:27:52 Wed, Feb 22, 2017|
|
||||
|LispInterpreter.TestOne||14:27:42 Wed, Feb 22, 2017|
|
||||
|LispInterpreter||14:24:41 Wed, Feb 22, 2017|
|
||||
|FrontPage||14:15:03 Wed, Feb 22, 2017|
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package function;
|
||||
|
||||
import static function.builtin.cons.LENGTH.getLength;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import error.LispException;
|
||||
import function.builtin.cons.LENGTH;
|
||||
import sexpression.*;
|
||||
|
||||
public class ArgumentValidator {
|
||||
|
@ -62,9 +63,9 @@ public class ArgumentValidator {
|
|||
}
|
||||
|
||||
private void validateListNotDotted(Cons argumentList) {
|
||||
SExpression next = argumentList.getCdr();
|
||||
SExpression next = argumentList.getRest();
|
||||
|
||||
for (Cons current = argumentList; next.consp(); next = current.getCdr())
|
||||
for (Cons current = argumentList; next.consp(); next = current.getRest())
|
||||
current = (Cons) next;
|
||||
|
||||
if (!next.nullp())
|
||||
|
@ -79,13 +80,27 @@ public class ArgumentValidator {
|
|||
}
|
||||
|
||||
private boolean containsTooFewArguments(Cons argumentList) {
|
||||
return (minimumNumberOfArguments != null)
|
||||
&& (LENGTH.getLength(argumentList).compareTo(minimumNumberOfArguments) < 0);
|
||||
return isMinimum() && isLengthLessThanMinimum(argumentList);
|
||||
}
|
||||
|
||||
private boolean isMinimum() {
|
||||
return minimumNumberOfArguments != null;
|
||||
}
|
||||
|
||||
private boolean isLengthLessThanMinimum(Cons argumentList) {
|
||||
return getLength(argumentList).compareTo(minimumNumberOfArguments) < 0;
|
||||
}
|
||||
|
||||
private boolean containsTooManyArguments(Cons argumentList) {
|
||||
return (maximumNumberOfArguments != null)
|
||||
&& (LENGTH.getLength(argumentList).compareTo(maximumNumberOfArguments) > 0);
|
||||
return isMaximum() && isLengthGreaterThanMaximum(argumentList);
|
||||
}
|
||||
|
||||
private boolean isMaximum() {
|
||||
return maximumNumberOfArguments != null;
|
||||
}
|
||||
|
||||
private boolean isLengthGreaterThanMaximum(Cons argumentList) {
|
||||
return getLength(argumentList).compareTo(maximumNumberOfArguments) > 0;
|
||||
}
|
||||
|
||||
private void validateArgumentTypes(Cons argumentList) {
|
||||
|
@ -95,11 +110,11 @@ public class ArgumentValidator {
|
|||
|
||||
private void validateFirstArgument(Cons argumentList) {
|
||||
if (!isFirstArgumentValid(argumentList))
|
||||
throw new BadArgumentTypeException(functionName, argumentList.getCar(), firstArgumentType);
|
||||
throw new BadArgumentTypeException(functionName, argumentList.getFirst(), firstArgumentType);
|
||||
}
|
||||
|
||||
private boolean isFirstArgumentValid(Cons argumentList) {
|
||||
return argumentList.nullp() || isExpectedFirstArgumentType(argumentList.getCar());
|
||||
return argumentList.nullp() || isExpectedFirstArgumentType(argumentList.getFirst());
|
||||
}
|
||||
|
||||
private boolean isExpectedFirstArgumentType(SExpression firstArgument) {
|
||||
|
@ -111,9 +126,9 @@ public class ArgumentValidator {
|
|||
}
|
||||
|
||||
private void validateTrailingArguments(Cons argumentList) {
|
||||
for (Cons cons = (Cons) argumentList.getCdr(); !cons.nullp(); cons = (Cons) cons.getCdr())
|
||||
if (!isExpectedTrailingArgumentType(cons.getCar()))
|
||||
throw new BadArgumentTypeException(functionName, cons.getCar(), trailingArgumentType);
|
||||
for (Cons cons = (Cons) argumentList.getRest(); !cons.nullp(); cons = (Cons) cons.getRest())
|
||||
if (!isExpectedTrailingArgumentType(cons.getFirst()))
|
||||
throw new BadArgumentTypeException(functionName, cons.getFirst(), trailingArgumentType);
|
||||
}
|
||||
|
||||
private boolean isExpectedTrailingArgumentType(SExpression trailingArgument) {
|
||||
|
|
|
@ -24,8 +24,8 @@ public class UserDefinedFunction extends LispFunction {
|
|||
this.executionContext = ExecutionContext.getInstance();
|
||||
this.functionScope = executionContext.getScope();
|
||||
|
||||
for (this.formalParameters = new ArrayList<>(); lambdaList.consp(); lambdaList = (Cons) lambdaList.getCdr())
|
||||
this.formalParameters.add(lambdaList.getCar().toString());
|
||||
for (this.formalParameters = new ArrayList<>(); lambdaList.consp(); lambdaList = (Cons) lambdaList.getRest())
|
||||
this.formalParameters.add(lambdaList.getFirst().toString());
|
||||
|
||||
this.argumentValidator = new ArgumentValidator(this.name);
|
||||
this.argumentValidator.setExactNumberOfArguments(this.formalParameters.size());
|
||||
|
@ -40,8 +40,8 @@ public class UserDefinedFunction extends LispFunction {
|
|||
|
||||
SExpression lastEvaluation = Nil.getInstance();
|
||||
|
||||
for (Cons expression = body; expression.consp(); expression = (Cons) expression.getCdr())
|
||||
lastEvaluation = eval(expression.getCar());
|
||||
for (Cons expression = body; expression.consp(); expression = (Cons) expression.getRest())
|
||||
lastEvaluation = eval(expression.getFirst());
|
||||
|
||||
executionContext.setScope(callingScope);
|
||||
releaseParameterValues();
|
||||
|
@ -53,9 +53,9 @@ public class UserDefinedFunction extends LispFunction {
|
|||
functionScope = new SymbolTable(functionScope);
|
||||
|
||||
for (String parameter : formalParameters) {
|
||||
SExpression currentArg = argumentList.getCar();
|
||||
SExpression currentArg = argumentList.getFirst();
|
||||
functionScope.put(parameter, currentArg);
|
||||
argumentList = (Cons) argumentList.getCdr();
|
||||
argumentList = (Cons) argumentList.getRest();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,9 +20,9 @@ public class APPLY extends LispFunction {
|
|||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
|
||||
Cons cdr = (Cons) argumentList.getCdr();
|
||||
SExpression functionName = argumentList.getCar();
|
||||
SExpression functionArguments = cdr.getCar();
|
||||
Cons cdr = (Cons) argumentList.getRest();
|
||||
SExpression functionName = argumentList.getFirst();
|
||||
SExpression functionArguments = cdr.getFirst();
|
||||
LispFunction function = EVAL.lookupFunctionOrLambda(functionName);
|
||||
|
||||
return function.call((Cons) functionArguments);
|
||||
|
|
|
@ -57,7 +57,7 @@ public class EVAL extends LispFunction {
|
|||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
|
||||
SExpression argument = argumentList.getCar();
|
||||
SExpression argument = argumentList.getFirst();
|
||||
|
||||
if (argument.listp()) {
|
||||
if (argument.consp())
|
||||
|
@ -79,8 +79,8 @@ public class EVAL extends LispFunction {
|
|||
}
|
||||
|
||||
private SExpression evaluateList(Cons list) {
|
||||
SExpression functionName = list.getCar();
|
||||
SExpression arguments = list.getCdr();
|
||||
SExpression functionName = list.getFirst();
|
||||
SExpression arguments = list.getRest();
|
||||
LispFunction function = lookupFunctionOrLambda(functionName);
|
||||
|
||||
ArgumentValidator functionListValidator = new ArgumentValidator(functionName.toString());
|
||||
|
@ -98,8 +98,8 @@ public class EVAL extends LispFunction {
|
|||
if (arguments.nullp())
|
||||
return Nil.getInstance();
|
||||
|
||||
SExpression car = eval(arguments.getCar());
|
||||
SExpression cdr = arguments.getCdr();
|
||||
SExpression car = eval(arguments.getFirst());
|
||||
SExpression cdr = arguments.getRest();
|
||||
|
||||
return new Cons(car, evaluateArgList((Cons) cdr));
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package function.builtin;
|
||||
|
||||
import static function.builtin.APPLY.apply;
|
||||
|
||||
import function.*;
|
||||
import function.builtin.cons.LIST;
|
||||
import sexpression.*;
|
||||
|
@ -15,9 +17,9 @@ public class FUNCALL extends LispFunction {
|
|||
|
||||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
Cons applyArgs = new Cons(argumentList.getCar(), LIST.makeList(argumentList.getCdr()));
|
||||
Cons applyArgs = new Cons(argumentList.getFirst(), LIST.makeList(argumentList.getRest()));
|
||||
|
||||
return APPLY.apply(applyArgs);
|
||||
return apply(applyArgs);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ public class LOAD extends LispFunction {
|
|||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
|
||||
LispString quotedName = (LispString) argumentList.getCar();
|
||||
LispString quotedName = (LispString) argumentList.getFirst();
|
||||
String fileName = removeSurroundingQuotes(quotedName.toString());
|
||||
|
||||
return processFile(fileName);
|
||||
|
|
|
@ -17,7 +17,7 @@ public class PRINT extends LispFunction {
|
|||
|
||||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
SExpression argument = argumentList.getCar();
|
||||
SExpression argument = argumentList.getFirst();
|
||||
environment.getOutput().println(argument);
|
||||
|
||||
return argument;
|
||||
|
|
|
@ -20,7 +20,7 @@ public class SYMBOL_FUNCTION extends LispFunction {
|
|||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
|
||||
SExpression symbol = argumentList.getCar();
|
||||
SExpression symbol = argumentList.getFirst();
|
||||
LispFunction function = FunctionTable.lookupFunction(symbol.toString());
|
||||
|
||||
if (function != null) {
|
||||
|
|
|
@ -15,9 +15,9 @@ public class CAR extends LispFunction {
|
|||
|
||||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
Cons argument = (Cons) argumentList.getCar();
|
||||
Cons argument = (Cons) argumentList.getFirst();
|
||||
|
||||
return argument.getCar();
|
||||
return argument.getFirst();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,9 +15,9 @@ public class CDR extends LispFunction {
|
|||
|
||||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
Cons argument = (Cons) argumentList.getCar();
|
||||
Cons argument = (Cons) argumentList.getFirst();
|
||||
|
||||
return argument.getCdr();
|
||||
return argument.getRest();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,9 +15,9 @@ public class CONS extends LispFunction {
|
|||
public Cons call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
|
||||
Cons cdr = (Cons) argumentList.getCdr();
|
||||
SExpression firstArgument = argumentList.getCar();
|
||||
SExpression secondArgument = cdr.getCar();
|
||||
Cons cdr = (Cons) argumentList.getRest();
|
||||
SExpression firstArgument = argumentList.getFirst();
|
||||
SExpression secondArgument = cdr.getFirst();
|
||||
|
||||
return new Cons(firstArgument, secondArgument);
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ public class LENGTH extends LispFunction {
|
|||
}
|
||||
|
||||
private LispNumber callTailRecursive(BigInteger accumulatedLength, Cons argumentList) {
|
||||
Cons list = (Cons) argumentList.getCar();
|
||||
Cons restOfList = LIST.makeList(list.getCdr());
|
||||
Cons list = (Cons) argumentList.getFirst();
|
||||
Cons restOfList = LIST.makeList(list.getRest());
|
||||
|
||||
if (list.nullp())
|
||||
return new LispNumber(accumulatedLength);
|
||||
|
|
|
@ -25,8 +25,8 @@ public class LIST extends LispFunction {
|
|||
if (argumentList.nullp())
|
||||
return Nil.getInstance();
|
||||
|
||||
SExpression firstArgument = argumentList.getCar();
|
||||
Cons remainingArguments = (Cons) argumentList.getCdr();
|
||||
SExpression firstArgument = argumentList.getFirst();
|
||||
Cons remainingArguments = (Cons) argumentList.getRest();
|
||||
|
||||
return new Cons(firstArgument, callRecursive(remainingArguments));
|
||||
}
|
||||
|
|
|
@ -16,17 +16,17 @@ class MathFunction {
|
|||
}
|
||||
|
||||
public LispNumber callTailRecursive(Cons argumentList) {
|
||||
Cons remainingArguments = (Cons) argumentList.getCdr();
|
||||
SExpression firstArgument = argumentList.getCar();
|
||||
Cons remainingArguments = (Cons) argumentList.getRest();
|
||||
SExpression firstArgument = argumentList.getFirst();
|
||||
LispNumber number1 = (LispNumber) firstArgument;
|
||||
|
||||
if (remainingArguments.nullp())
|
||||
return singleValueOperation.apply(number1);
|
||||
|
||||
SExpression secondArgument = remainingArguments.getCar();
|
||||
SExpression secondArgument = remainingArguments.getFirst();
|
||||
LispNumber number2 = (LispNumber) secondArgument;
|
||||
LispNumber operationResult = multipleValueOperation.apply(number1, number2);
|
||||
SExpression remainingNumbers = remainingArguments.getCdr();
|
||||
SExpression remainingNumbers = remainingArguments.getRest();
|
||||
|
||||
if (remainingNumbers.nullp())
|
||||
return operationResult;
|
||||
|
|
|
@ -14,7 +14,7 @@ public class ATOM extends LispFunction {
|
|||
|
||||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
SExpression argument = argumentList.getCar();
|
||||
SExpression argument = argumentList.getFirst();
|
||||
|
||||
return argument.atomp() ? Symbol.T : Nil.getInstance();
|
||||
}
|
||||
|
|
|
@ -15,9 +15,9 @@ public class EQ extends LispFunction {
|
|||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
|
||||
Cons cdr = (Cons) argumentList.getCdr();
|
||||
SExpression firstArgument = argumentList.getCar();
|
||||
SExpression secondArgument = cdr.getCar();
|
||||
Cons cdr = (Cons) argumentList.getRest();
|
||||
SExpression firstArgument = argumentList.getFirst();
|
||||
SExpression secondArgument = cdr.getFirst();
|
||||
|
||||
return eq(firstArgument, secondArgument);
|
||||
}
|
||||
|
|
|
@ -20,19 +20,19 @@ public class EQUAL extends LispFunction {
|
|||
}
|
||||
|
||||
private SExpression callRecursive(Cons argumentList) {
|
||||
Cons cdr = (Cons) argumentList.getCdr();
|
||||
SExpression firstArgument = argumentList.getCar();
|
||||
SExpression secondArgument = cdr.getCar();
|
||||
Cons cdr = (Cons) argumentList.getRest();
|
||||
SExpression firstArgument = argumentList.getFirst();
|
||||
SExpression secondArgument = cdr.getFirst();
|
||||
|
||||
if (!isListPair(firstArgument, secondArgument))
|
||||
return equal(firstArgument, secondArgument);
|
||||
|
||||
Cons listOne = (Cons) firstArgument;
|
||||
Cons listTwo = (Cons) secondArgument;
|
||||
SExpression listOneCar = listOne.getCar();
|
||||
SExpression listTwoCar = listTwo.getCar();
|
||||
SExpression listOneCdr = listOne.getCdr();
|
||||
SExpression listTwoCdr = listTwo.getCdr();
|
||||
SExpression listOneCar = listOne.getFirst();
|
||||
SExpression listTwoCar = listTwo.getFirst();
|
||||
SExpression listOneCdr = listOne.getRest();
|
||||
SExpression listTwoCdr = listTwo.getRest();
|
||||
|
||||
SExpression carEqual = callRecursive(makeArgumentList(listOneCar, listTwoCar));
|
||||
SExpression cdrEqual = callRecursive(makeArgumentList(listOneCdr, listTwoCdr));
|
||||
|
|
|
@ -20,14 +20,14 @@ public class EQUALSP extends LispFunction {
|
|||
}
|
||||
|
||||
private SExpression callTailRecursive(Cons argumentList) {
|
||||
Cons remainingArguments = (Cons) argumentList.getCdr();
|
||||
Cons remainingArguments = (Cons) argumentList.getRest();
|
||||
|
||||
if (remainingArguments.nullp())
|
||||
return Symbol.T;
|
||||
|
||||
SExpression firstArgument = argumentList.getCar();
|
||||
SExpression firstArgument = argumentList.getFirst();
|
||||
LispNumber number1 = (LispNumber) firstArgument;
|
||||
SExpression secondArgument = remainingArguments.getCar();
|
||||
SExpression secondArgument = remainingArguments.getFirst();
|
||||
LispNumber number2 = (LispNumber) secondArgument;
|
||||
|
||||
if (!isEqual(number1, number2))
|
||||
|
|
|
@ -20,13 +20,13 @@ public class GREATERP extends LispFunction {
|
|||
}
|
||||
|
||||
private SExpression callTailRecursive(Cons argumentList) {
|
||||
Cons remainingArguments = (Cons) argumentList.getCdr();
|
||||
Cons remainingArguments = (Cons) argumentList.getRest();
|
||||
|
||||
if (remainingArguments.nullp())
|
||||
return Symbol.T;
|
||||
|
||||
SExpression firstArgument = argumentList.getCar();
|
||||
SExpression secondArgument = remainingArguments.getCar();
|
||||
SExpression firstArgument = argumentList.getFirst();
|
||||
SExpression secondArgument = remainingArguments.getFirst();
|
||||
LispNumber number1 = (LispNumber) firstArgument;
|
||||
LispNumber number2 = (LispNumber) secondArgument;
|
||||
|
||||
|
|
|
@ -20,13 +20,13 @@ public class LESSP extends LispFunction {
|
|||
}
|
||||
|
||||
private SExpression callTailRecursive(Cons argumentList) {
|
||||
Cons remainingArguments = (Cons) argumentList.getCdr();
|
||||
Cons remainingArguments = (Cons) argumentList.getRest();
|
||||
|
||||
if (remainingArguments.nullp())
|
||||
return Symbol.T;
|
||||
|
||||
SExpression firstArgument = argumentList.getCar();
|
||||
SExpression secondArgument = remainingArguments.getCar();
|
||||
SExpression firstArgument = argumentList.getFirst();
|
||||
SExpression secondArgument = remainingArguments.getFirst();
|
||||
LispNumber number1 = (LispNumber) firstArgument;
|
||||
LispNumber number2 = (LispNumber) secondArgument;
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ public class LISTP extends LispFunction {
|
|||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
|
||||
return argumentList.getCar().listp() ? Symbol.T : Nil.getInstance();
|
||||
return argumentList.getFirst().listp() ? Symbol.T : Nil.getInstance();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ public class NULL extends LispFunction {
|
|||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
|
||||
return argumentList.getCar().nullp() ? Symbol.T : Nil.getInstance();
|
||||
return argumentList.getFirst().nullp() ? Symbol.T : Nil.getInstance();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ public class AND extends LispFunction {
|
|||
}
|
||||
|
||||
private SExpression callTailRecursive(Cons argumentList, SExpression lastValue) {
|
||||
SExpression currentValue = eval(argumentList.getCar());
|
||||
Cons remainingValues = (Cons) argumentList.getCdr();
|
||||
SExpression currentValue = eval(argumentList.getFirst());
|
||||
Cons remainingValues = (Cons) argumentList.getRest();
|
||||
|
||||
if (argumentList.nullp())
|
||||
return lastValue;
|
||||
|
|
|
@ -25,9 +25,9 @@ public class COND extends LispFunction {
|
|||
if (argumentList.nullp())
|
||||
return Nil.getInstance();
|
||||
|
||||
Cons clause = (Cons) argumentList.getCar();
|
||||
Cons remainingClauses = (Cons) argumentList.getCdr();
|
||||
SExpression test = eval(clause.getCar());
|
||||
Cons clause = (Cons) argumentList.getFirst();
|
||||
Cons remainingClauses = (Cons) argumentList.getRest();
|
||||
SExpression test = eval(clause.getFirst());
|
||||
|
||||
if (isTestSuccessful(test))
|
||||
return evaluateResult(clause, test);
|
||||
|
@ -42,18 +42,18 @@ public class COND extends LispFunction {
|
|||
private SExpression evaluateResult(Cons clause, SExpression test) {
|
||||
SExpression lastResultValue = test;
|
||||
|
||||
for (SExpression result = clause.getCdr(); result.consp(); result = advanceCons(result))
|
||||
for (SExpression result = clause.getRest(); result.consp(); result = advanceCons(result))
|
||||
lastResultValue = eval(getCar(result));
|
||||
|
||||
return lastResultValue;
|
||||
}
|
||||
|
||||
private SExpression advanceCons(SExpression knownCons) {
|
||||
return ((Cons) knownCons).getCdr();
|
||||
return ((Cons) knownCons).getRest();
|
||||
}
|
||||
|
||||
private SExpression getCar(SExpression knownCons) {
|
||||
return ((Cons) knownCons).getCar();
|
||||
return ((Cons) knownCons).getFirst();
|
||||
}
|
||||
|
||||
public boolean evaluateArguments() {
|
||||
|
|
|
@ -33,15 +33,15 @@ public class DEFUN extends LispFunction {
|
|||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
|
||||
Cons remainingArguments = (Cons) argumentList.getCdr();
|
||||
SExpression functionName = argumentList.getCar();
|
||||
SExpression secondArgument = remainingArguments.getCar();
|
||||
Cons remainingArguments = (Cons) argumentList.getRest();
|
||||
SExpression functionName = argumentList.getFirst();
|
||||
SExpression secondArgument = remainingArguments.getFirst();
|
||||
lambdaListIsListValidator.validate(LIST.makeList(secondArgument));
|
||||
|
||||
Cons lambdaList = (Cons) secondArgument;
|
||||
lambdaListValidator.validate(lambdaList);
|
||||
|
||||
Cons functionBody = (Cons) remainingArguments.getCdr();
|
||||
Cons functionBody = (Cons) remainingArguments.getRest();
|
||||
UserDefinedFunction function = new UserDefinedFunction(functionName.toString(), lambdaList, functionBody);
|
||||
|
||||
if (FunctionTable.isAlreadyDefined(functionName.toString()))
|
||||
|
|
|
@ -18,7 +18,7 @@ public class IF extends LispFunction {
|
|||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
|
||||
SExpression test = eval(argumentList.getCar());
|
||||
SExpression test = eval(argumentList.getFirst());
|
||||
SExpression thenForm = getThenForm(argumentList);
|
||||
SExpression elseForm = getElseForm(argumentList);
|
||||
|
||||
|
@ -32,17 +32,17 @@ public class IF extends LispFunction {
|
|||
private SExpression getThenForm(Cons argumentList) {
|
||||
Cons expressions = getRestOfList(argumentList);
|
||||
|
||||
return expressions.getCar();
|
||||
return expressions.getFirst();
|
||||
}
|
||||
|
||||
private Cons getRestOfList(Cons argumentList) {
|
||||
return (Cons) argumentList.getCdr();
|
||||
return (Cons) argumentList.getRest();
|
||||
}
|
||||
|
||||
private SExpression getElseForm(Cons argumentList) {
|
||||
Cons expressions = getRestOfList(argumentList);
|
||||
|
||||
return getRestOfList(expressions).getCar();
|
||||
return getRestOfList(expressions).getFirst();
|
||||
}
|
||||
|
||||
public boolean evaluateArguments() {
|
||||
|
|
|
@ -8,7 +8,7 @@ public class LAMBDA extends LispFunction {
|
|||
|
||||
public static boolean isLambdaExpression(SExpression sexpr) {
|
||||
if (sexpr.consp()) {
|
||||
SExpression first = ((Cons) sexpr).getCar();
|
||||
SExpression first = ((Cons) sexpr).getFirst();
|
||||
|
||||
return "LAMBDA".equals(first.toString());
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ public class LAMBDA extends LispFunction {
|
|||
}
|
||||
|
||||
public static UserDefinedFunction createFunction(Cons lambdaExpression) {
|
||||
SExpression cdr = lambdaExpression.getCdr();
|
||||
SExpression cdr = lambdaExpression.getRest();
|
||||
|
||||
ArgumentValidator lambdaValidator = new ArgumentValidator("LAMBDA|create|");
|
||||
lambdaValidator.setEveryArgumentExpectedType(Cons.class);
|
||||
|
@ -43,9 +43,9 @@ public class LAMBDA extends LispFunction {
|
|||
public LambdaExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
|
||||
SExpression car = argumentList.getCar();
|
||||
SExpression car = argumentList.getFirst();
|
||||
Cons lambdaList = (Cons) car;
|
||||
Cons body = (Cons) argumentList.getCdr();
|
||||
Cons body = (Cons) argumentList.getRest();
|
||||
|
||||
lambdaListValidator.validate(lambdaList);
|
||||
|
||||
|
|
|
@ -30,8 +30,8 @@ public class LET extends LispFunction {
|
|||
|
||||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
Cons variableDefinitions = (Cons) argumentList.getCar();
|
||||
Cons body = (Cons) argumentList.getCdr();
|
||||
Cons variableDefinitions = (Cons) argumentList.getFirst();
|
||||
Cons body = (Cons) argumentList.getRest();
|
||||
|
||||
return evaluateInScope(variableDefinitions, body);
|
||||
}
|
||||
|
@ -55,16 +55,16 @@ public class LET extends LispFunction {
|
|||
private void addVariablesToScope(SymbolTable scope, Cons variableDefinitions) {
|
||||
variableDefinitionListValidator.validate(variableDefinitions);
|
||||
|
||||
for (; variableDefinitions.consp(); variableDefinitions = (Cons) variableDefinitions.getCdr())
|
||||
addPairToScope((Cons) variableDefinitions.getCar(), scope);
|
||||
for (; variableDefinitions.consp(); variableDefinitions = (Cons) variableDefinitions.getRest())
|
||||
addPairToScope((Cons) variableDefinitions.getFirst(), scope);
|
||||
}
|
||||
|
||||
private void addPairToScope(Cons symbolValuePair, SymbolTable scope) {
|
||||
pairValidator.validate(symbolValuePair);
|
||||
|
||||
Cons restOfPair = (Cons) symbolValuePair.getCdr();
|
||||
SExpression symbol = symbolValuePair.getCar();
|
||||
SExpression value = restOfPair.getCar();
|
||||
Cons restOfPair = (Cons) symbolValuePair.getRest();
|
||||
SExpression symbol = symbolValuePair.getFirst();
|
||||
SExpression value = restOfPair.getFirst();
|
||||
|
||||
scope.put(symbol.toString(), eval(value));
|
||||
}
|
||||
|
@ -72,8 +72,8 @@ public class LET extends LispFunction {
|
|||
private SExpression evaluateBody(Cons body) {
|
||||
SExpression lastEvaluation = Nil.getInstance();
|
||||
|
||||
for (; body.consp(); body = (Cons) body.getCdr())
|
||||
lastEvaluation = eval(body.getCar());
|
||||
for (; body.consp(); body = (Cons) body.getRest())
|
||||
lastEvaluation = eval(body.getFirst());
|
||||
|
||||
return lastEvaluation;
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ public class OR extends LispFunction {
|
|||
}
|
||||
|
||||
private SExpression callTailRecursive(Cons argumentList) {
|
||||
SExpression currentValue = eval(argumentList.getCar());
|
||||
Cons remainingValues = (Cons) argumentList.getCdr();
|
||||
SExpression currentValue = eval(argumentList.getFirst());
|
||||
Cons remainingValues = (Cons) argumentList.getRest();
|
||||
|
||||
if (remainingValues.nullp() || !currentValue.nullp())
|
||||
return currentValue;
|
||||
|
|
|
@ -15,7 +15,7 @@ public class QUOTE extends LispFunction {
|
|||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
|
||||
return argumentList.getCar();
|
||||
return argumentList.getFirst();
|
||||
}
|
||||
|
||||
public boolean evaluateArguments() {
|
||||
|
|
|
@ -21,9 +21,9 @@ public class SETF extends LispFunction {
|
|||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
|
||||
Cons cdr = (Cons) argumentList.getCdr();
|
||||
SExpression symbol = argumentList.getCar();
|
||||
SExpression value = eval(cdr.getCar());
|
||||
Cons cdr = (Cons) argumentList.getRest();
|
||||
SExpression symbol = argumentList.getFirst();
|
||||
SExpression value = eval(cdr.getFirst());
|
||||
|
||||
SymbolTable table = findScopeOfSymbol(symbol);
|
||||
table.put(symbol.toString(), value);
|
||||
|
|
|
@ -3,28 +3,28 @@ package sexpression;
|
|||
@DisplayName("list")
|
||||
public class Cons extends SExpression {
|
||||
|
||||
private SExpression car;
|
||||
private SExpression cdr;
|
||||
private SExpression first;
|
||||
private SExpression rest;
|
||||
|
||||
public Cons(SExpression car, SExpression cdr) {
|
||||
this.car = car;
|
||||
this.cdr = cdr;
|
||||
public Cons(SExpression first, SExpression rest) {
|
||||
this.first = first;
|
||||
this.rest = rest;
|
||||
}
|
||||
|
||||
public SExpression getCar() {
|
||||
return car;
|
||||
public SExpression getFirst() {
|
||||
return first;
|
||||
}
|
||||
|
||||
public SExpression getCdr() {
|
||||
return cdr;
|
||||
public SExpression getRest() {
|
||||
return rest;
|
||||
}
|
||||
|
||||
public void setCar(SExpression newCar) {
|
||||
car = newCar;
|
||||
public void setFirst(SExpression first) {
|
||||
this.first = first;
|
||||
}
|
||||
|
||||
public void setCdr(SExpression newCdr) {
|
||||
cdr = newCdr;
|
||||
public void setRest(SExpression rest) {
|
||||
this.rest = rest;
|
||||
}
|
||||
|
||||
public boolean consp() {
|
||||
|
@ -35,20 +35,13 @@ public class Cons extends SExpression {
|
|||
return ("(" + toStringAux());
|
||||
}
|
||||
|
||||
// Returns a string representation of the car of a CONS cell followed by
|
||||
// its cdr. If the cdr of this CONS cell is not a CONS cell itself, this
|
||||
// method places a ')' at the end of its return value. Also, if the cdr of
|
||||
// this CONS cell is NIL, it will not be included in the return value of
|
||||
// this method. When used in conjunction with the 'toString' method of this
|
||||
// class, this method provides a means for creating the correct string
|
||||
// representation of a list.
|
||||
private String toStringAux() {
|
||||
if (cdr.nullp())
|
||||
return (car.toString() + ")");
|
||||
else if (cdr.consp())
|
||||
return (car.toString() + " " + ((Cons) cdr).toStringAux());
|
||||
if (rest.nullp())
|
||||
return (first.toString() + ")");
|
||||
else if (rest.consp())
|
||||
return (first.toString() + " " + ((Cons) rest).toStringAux());
|
||||
|
||||
return (car.toString() + " . " + cdr.toString() + ")");
|
||||
return (first.toString() + " . " + rest.toString() + ")");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ public class Nil extends Cons {
|
|||
private Nil() {
|
||||
super(null, null);
|
||||
|
||||
super.setCar(this);
|
||||
super.setCdr(this);
|
||||
super.setFirst(this);
|
||||
super.setRest(this);
|
||||
}
|
||||
|
||||
public boolean nullp() {
|
||||
|
@ -35,12 +35,12 @@ public class Nil extends Cons {
|
|||
/**
|
||||
* The car of NIL can not be changed.
|
||||
*/
|
||||
public void setCar(SExpression newCar) {}
|
||||
public void setFirst(SExpression newCar) {}
|
||||
|
||||
/**
|
||||
* The cdr of NIL can not be changed.
|
||||
*/
|
||||
public void setCdr(SExpression newCdr) {}
|
||||
public void setRest(SExpression newCdr) {}
|
||||
|
||||
public String toString() {
|
||||
return "NIL";
|
||||
|
|
|
@ -106,28 +106,28 @@ public class SExpressionTester {
|
|||
|
||||
@Test
|
||||
public void testCarOfNilIsNil() {
|
||||
assertEquals(Nil.getInstance(), Nil.getInstance().getCar());
|
||||
assertEquals(Nil.getInstance(), Nil.getInstance().getFirst());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCdrOfNilIsNil() {
|
||||
assertEquals(Nil.getInstance(), Nil.getInstance().getCdr());
|
||||
assertEquals(Nil.getInstance(), Nil.getInstance().getRest());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterSettingCarOfNil_ShouldStillBeNil() {
|
||||
Cons nil = Nil.getInstance();
|
||||
nil.setCar(new LispNumber("2"));
|
||||
nil.setFirst(new LispNumber("2"));
|
||||
|
||||
assertEquals(Nil.getInstance(), nil.getCar());
|
||||
assertEquals(Nil.getInstance(), nil.getFirst());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterSettingCdrOfNil_ShouldStillBeNil() {
|
||||
Cons nil = Nil.getInstance();
|
||||
nil.setCdr(new LispNumber("2"));
|
||||
nil.setRest(new LispNumber("2"));
|
||||
|
||||
assertEquals(Nil.getInstance(), nil.getCdr());
|
||||
assertEquals(Nil.getInstance(), nil.getRest());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue