Convert sexpressions to kotlin
This commit is contained in:
parent
4c8342a9f7
commit
16118a9a78
|
@ -4,6 +4,7 @@ import error.LispException;
|
|||
import recursion.TailCall;
|
||||
import recursion.TailCalls;
|
||||
import sexpression.Cons;
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
import sexpression.Symbol;
|
||||
import table.ExecutionContext;
|
||||
|
@ -14,7 +15,6 @@ import java.util.ArrayList;
|
|||
import static function.builtin.EVAL.eval;
|
||||
import static java.text.MessageFormat.format;
|
||||
import static recursion.TailCalls.done;
|
||||
import static sexpression.Nil.NIL;
|
||||
|
||||
public class UserDefinedFunction extends LispFunction {
|
||||
|
||||
|
@ -136,7 +136,7 @@ public class UserDefinedFunction extends LispFunction {
|
|||
}
|
||||
|
||||
private SExpression evaluateBody() {
|
||||
SExpression lastEvaluation = NIL;
|
||||
SExpression lastEvaluation = Nil.INSTANCE;
|
||||
|
||||
for (Cons expression = body; expression.isCons(); expression = (Cons) expression.getRest())
|
||||
lastEvaluation = eval(expression.getFirst());
|
||||
|
|
|
@ -6,10 +6,10 @@ import sexpression.AtSignExpression;
|
|||
import sexpression.BackquoteExpression;
|
||||
import sexpression.CommaExpression;
|
||||
import sexpression.Cons;
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
|
||||
import static function.builtin.EVAL.eval;
|
||||
import static sexpression.Nil.NIL;
|
||||
|
||||
class BackquoteEvaluator {
|
||||
|
||||
|
@ -24,7 +24,7 @@ class BackquoteEvaluator {
|
|||
this.listValidator = new ArgumentValidator("`|list|");
|
||||
this.atSignValidator = new ArgumentValidator("@|list|");
|
||||
this.backTick = backTick;
|
||||
this.resolvedList = new Cons(NIL, NIL);
|
||||
this.resolvedList = new Cons(Nil.INSTANCE, Nil.INSTANCE);
|
||||
this.leader = resolvedList;
|
||||
this.follower = resolvedList;
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ class BackquoteEvaluator {
|
|||
for (; list.isCons(); list = (Cons) list.getRest())
|
||||
resolveExpression(list.getFirst());
|
||||
|
||||
follower.setRest(NIL);
|
||||
follower.setRest(Nil.INSTANCE);
|
||||
}
|
||||
|
||||
private void resolveExpression(SExpression expression) {
|
||||
|
@ -123,7 +123,7 @@ class BackquoteEvaluator {
|
|||
|
||||
private void addResolvedExpression(SExpression expression) {
|
||||
leader.setFirst(expression);
|
||||
leader.setRest(new Cons(NIL, NIL));
|
||||
leader.setRest(new Cons(Nil.INSTANCE, Nil.INSTANCE));
|
||||
follower = leader;
|
||||
leader = (Cons) leader.getRest();
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import function.builtin.special.RECUR.RecurNotInTailPositionException;
|
|||
import sexpression.BackquoteExpression;
|
||||
import sexpression.Cons;
|
||||
import sexpression.LambdaExpression;
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
import sexpression.Symbol;
|
||||
import table.ExecutionContext;
|
||||
|
@ -16,8 +17,6 @@ import table.FunctionTable;
|
|||
import static function.builtin.cons.LIST.makeList;
|
||||
import static function.builtin.special.Lambda.Lambda;
|
||||
import static java.text.MessageFormat.format;
|
||||
import static sexpression.Nil.NIL;
|
||||
import static sexpression.Symbol.T;
|
||||
|
||||
@FunctionNames({ "EVAL" })
|
||||
public class EVAL extends LispFunction {
|
||||
|
@ -67,9 +66,9 @@ public class EVAL extends LispFunction {
|
|||
|
||||
public static SExpression lookupSymbol(String symbolName) {
|
||||
if (symbolName.equals("NIL"))
|
||||
return NIL;
|
||||
return Nil.INSTANCE;
|
||||
else if (symbolName.equals("T"))
|
||||
return T;
|
||||
return Symbol.Companion.getT();
|
||||
else if (symbolName.startsWith(":"))
|
||||
return new Symbol(symbolName);
|
||||
|
||||
|
@ -155,7 +154,7 @@ public class EVAL extends LispFunction {
|
|||
|
||||
private Cons evaluateArgumentList(Cons arguments) {
|
||||
if (arguments.isNull())
|
||||
return NIL;
|
||||
return Nil.INSTANCE;
|
||||
|
||||
SExpression first = eval(arguments.getFirst());
|
||||
SExpression rest = arguments.getRest();
|
||||
|
|
|
@ -5,7 +5,7 @@ import function.ArgumentValidator
|
|||
import function.FunctionNames
|
||||
import function.LispFunction
|
||||
import sexpression.Cons
|
||||
import sexpression.Nil.NIL
|
||||
import sexpression.Nil
|
||||
import sexpression.SExpression
|
||||
|
||||
@FunctionNames("EXIT")
|
||||
|
@ -21,6 +21,6 @@ class Exit(name: String) : LispFunction() {
|
|||
argumentValidator.validate(argumentList)
|
||||
RuntimeEnvironment.terminateSuccessfully()
|
||||
|
||||
return NIL
|
||||
return Nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,9 @@ import function.LispFunction;
|
|||
import parser.LispParser;
|
||||
import sexpression.Cons;
|
||||
import sexpression.LispString;
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
import sexpression.Symbol;
|
||||
import util.Path;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
|
@ -18,8 +20,6 @@ import java.util.Stack;
|
|||
|
||||
import static function.builtin.EVAL.eval;
|
||||
import static java.text.MessageFormat.format;
|
||||
import static sexpression.Nil.NIL;
|
||||
import static sexpression.Symbol.T;
|
||||
|
||||
@FunctionNames({ "LOAD" })
|
||||
public class LOAD extends LispFunction {
|
||||
|
@ -57,7 +57,7 @@ public class LOAD extends LispFunction {
|
|||
if (parser != null)
|
||||
isSuccessful = isSuccessfulEvaluationWithPathPrefix(prefixedFileName, parser);
|
||||
|
||||
return isSuccessful ? T : NIL;
|
||||
return isSuccessful ? Symbol.Companion.getT() : Nil.INSTANCE;
|
||||
}
|
||||
|
||||
private String prefixFileNameIfNecessary(String fileName) {
|
||||
|
|
|
@ -4,10 +4,9 @@ import function.ArgumentValidator;
|
|||
import function.FunctionNames;
|
||||
import function.LispFunction;
|
||||
import sexpression.Cons;
|
||||
import sexpression.Nil;
|
||||
import table.FunctionTable;
|
||||
|
||||
import static sexpression.Nil.NIL;
|
||||
|
||||
@FunctionNames({ "APPEND" })
|
||||
public class APPEND extends LispFunction {
|
||||
|
||||
|
@ -53,11 +52,11 @@ public class APPEND extends LispFunction {
|
|||
}
|
||||
|
||||
private Cons copy(Cons list) {
|
||||
Cons newList = new Cons(list.getFirst(), NIL);
|
||||
Cons newList = new Cons(list.getFirst(), Nil.INSTANCE);
|
||||
Cons builder = newList;
|
||||
|
||||
for (Cons iterator = (Cons) list.getRest(); iterator.isCons(); iterator = (Cons) iterator.getRest()) {
|
||||
builder.setRest(new Cons(iterator.getFirst(), NIL));
|
||||
builder.setRest(new Cons(iterator.getFirst(), Nil.INSTANCE));
|
||||
builder = (Cons) builder.getRest();
|
||||
}
|
||||
|
||||
|
|
|
@ -4,15 +4,14 @@ import function.ArgumentValidator;
|
|||
import function.FunctionNames;
|
||||
import function.LispFunction;
|
||||
import sexpression.Cons;
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
|
||||
import static sexpression.Nil.NIL;
|
||||
|
||||
@FunctionNames({ "LIST" })
|
||||
public class LIST extends LispFunction {
|
||||
|
||||
public static Cons makeList(SExpression sexpr) {
|
||||
return new Cons(sexpr, NIL);
|
||||
return new Cons(sexpr, Nil.INSTANCE);
|
||||
}
|
||||
|
||||
private ArgumentValidator argumentValidator;
|
||||
|
|
|
@ -6,8 +6,6 @@ import function.LispFunction;
|
|||
import sexpression.Cons;
|
||||
import sexpression.LispNumber;
|
||||
|
||||
import static sexpression.LispNumber.ONE;
|
||||
|
||||
@FunctionNames({ "*" })
|
||||
public class MULTIPLY extends LispFunction {
|
||||
|
||||
|
@ -24,7 +22,7 @@ public class MULTIPLY extends LispFunction {
|
|||
public LispNumber call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
|
||||
return mathFunction.callTailRecursive(new Cons(ONE, argumentList)).invoke();
|
||||
return mathFunction.callTailRecursive(new Cons(LispNumber.Companion.getONE(), argumentList)).invoke();
|
||||
}
|
||||
|
||||
private LispNumber multiply(LispNumber number1, LispNumber number2) {
|
||||
|
|
|
@ -6,8 +6,6 @@ import function.LispFunction;
|
|||
import sexpression.Cons;
|
||||
import sexpression.LispNumber;
|
||||
|
||||
import static sexpression.LispNumber.ZERO;
|
||||
|
||||
@FunctionNames({ "+" })
|
||||
public class PLUS extends LispFunction {
|
||||
|
||||
|
@ -24,7 +22,7 @@ public class PLUS extends LispFunction {
|
|||
public LispNumber call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
|
||||
return mathFunction.callTailRecursive(new Cons(ZERO, argumentList)).invoke();
|
||||
return mathFunction.callTailRecursive(new Cons(LispNumber.Companion.getZERO(), argumentList)).invoke();
|
||||
}
|
||||
|
||||
private LispNumber add(LispNumber number1, LispNumber number2) {
|
||||
|
|
|
@ -4,10 +4,9 @@ import function.ArgumentValidator;
|
|||
import function.FunctionNames;
|
||||
import function.LispFunction;
|
||||
import sexpression.Cons;
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
|
||||
import static sexpression.Nil.NIL;
|
||||
import static sexpression.Symbol.T;
|
||||
import sexpression.Symbol;
|
||||
|
||||
@FunctionNames({ "ATOM", "ATOM?" })
|
||||
public class ATOM extends LispFunction {
|
||||
|
@ -24,6 +23,6 @@ public class ATOM extends LispFunction {
|
|||
argumentValidator.validate(argumentList);
|
||||
SExpression argument = argumentList.getFirst();
|
||||
|
||||
return argument.isAtom() ? T : NIL;
|
||||
return argument.isAtom() ? Symbol.Companion.getT() : Nil.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,9 @@ import function.ArgumentValidator;
|
|||
import function.FunctionNames;
|
||||
import function.LispFunction;
|
||||
import sexpression.Cons;
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
|
||||
import static sexpression.Nil.NIL;
|
||||
import static sexpression.Symbol.T;
|
||||
import sexpression.Symbol;
|
||||
|
||||
@FunctionNames({ "EQ", "EQ?" })
|
||||
public class EQ extends LispFunction {
|
||||
|
@ -42,7 +41,7 @@ public class EQ extends LispFunction {
|
|||
}
|
||||
|
||||
private SExpression atomEq(SExpression firstArgument, SExpression secondArgument) {
|
||||
return isEq(firstArgument, secondArgument) ? T : NIL;
|
||||
return isEq(firstArgument, secondArgument) ? Symbol.Companion.getT() : Nil.INSTANCE;
|
||||
}
|
||||
|
||||
private boolean isEq(SExpression firstArgument, SExpression secondArgument) {
|
||||
|
@ -50,6 +49,6 @@ public class EQ extends LispFunction {
|
|||
}
|
||||
|
||||
private SExpression listEq(SExpression firstArgument, SExpression secondArgument) {
|
||||
return (firstArgument == secondArgument) ? T : NIL;
|
||||
return (firstArgument == secondArgument) ? Symbol.Companion.getT() : Nil.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,9 @@ import function.ArgumentValidator;
|
|||
import function.FunctionNames;
|
||||
import function.LispFunction;
|
||||
import sexpression.Cons;
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
|
||||
import static sexpression.Nil.NIL;
|
||||
import static sexpression.Symbol.T;
|
||||
import sexpression.Symbol;
|
||||
|
||||
@FunctionNames({ "EQUAL", "EQUAL?" })
|
||||
public class EQUAL extends LispFunction {
|
||||
|
@ -35,6 +34,6 @@ public class EQUAL extends LispFunction {
|
|||
}
|
||||
|
||||
private SExpression equal(SExpression firstArgument, SExpression secondArgument) {
|
||||
return isEqual(firstArgument, secondArgument) ? T : NIL;
|
||||
return isEqual(firstArgument, secondArgument) ? Symbol.Companion.getT() : Nil.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,9 @@ import function.ArgumentValidator;
|
|||
import function.FunctionNames;
|
||||
import function.LispFunction;
|
||||
import sexpression.Cons;
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
import sexpression.Symbol;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -13,8 +15,6 @@ import java.util.regex.Matcher;
|
|||
import java.util.regex.Pattern;
|
||||
|
||||
import static function.builtin.GENSYM.GENSYM_PREFIX;
|
||||
import static sexpression.Nil.NIL;
|
||||
import static sexpression.Symbol.T;
|
||||
|
||||
@FunctionNames({ "GENSYM-EQUAL", "GENSYM-EQUAL?" })
|
||||
public class GENSYM_EQUAL extends LispFunction {
|
||||
|
@ -41,7 +41,7 @@ public class GENSYM_EQUAL extends LispFunction {
|
|||
String firstEqualized = equalizeGensyms(firstArgument);
|
||||
String secondEqualized = equalizeGensyms(secondArgument);
|
||||
|
||||
return firstEqualized.equals(secondEqualized) ? T : NIL;
|
||||
return firstEqualized.equals(secondEqualized) ? Symbol.Companion.getT() : Nil.INSTANCE;
|
||||
}
|
||||
|
||||
private String equalizeGensyms(SExpression expression) {
|
||||
|
|
|
@ -4,10 +4,9 @@ import function.ArgumentValidator;
|
|||
import function.FunctionNames;
|
||||
import function.LispFunction;
|
||||
import sexpression.Cons;
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
|
||||
import static sexpression.Nil.NIL;
|
||||
import static sexpression.Symbol.T;
|
||||
import sexpression.Symbol;
|
||||
|
||||
@FunctionNames({ "LISTP", "LIST?" })
|
||||
public class LISTP extends LispFunction {
|
||||
|
@ -23,6 +22,6 @@ public class LISTP extends LispFunction {
|
|||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
|
||||
return argumentList.getFirst().isList() ? T : NIL;
|
||||
return argumentList.getFirst().isList() ? Symbol.Companion.getT() : Nil.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,9 @@ import function.ArgumentValidator;
|
|||
import function.FunctionNames;
|
||||
import function.LispFunction;
|
||||
import sexpression.Cons;
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
|
||||
import static sexpression.Nil.NIL;
|
||||
import static sexpression.Symbol.T;
|
||||
import sexpression.Symbol;
|
||||
|
||||
@FunctionNames({ "NULL", "NULL?" })
|
||||
public class NULL extends LispFunction {
|
||||
|
@ -23,6 +22,6 @@ public class NULL extends LispFunction {
|
|||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
|
||||
return argumentList.getFirst().isNull() ? T : NIL;
|
||||
return argumentList.getFirst().isNull() ? Symbol.Companion.getT() : Nil.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,12 +6,12 @@ import function.LispFunction;
|
|||
import recursion.TailCall;
|
||||
import sexpression.Cons;
|
||||
import sexpression.LispNumber;
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
import sexpression.Symbol;
|
||||
|
||||
import static recursion.TailCalls.done;
|
||||
import static recursion.TailCalls.tailCall;
|
||||
import static sexpression.Nil.NIL;
|
||||
import static sexpression.Symbol.T;
|
||||
|
||||
@FunctionNames({ ">" })
|
||||
public class NUMERIC_GREATER extends LispFunction {
|
||||
|
@ -35,7 +35,7 @@ public class NUMERIC_GREATER extends LispFunction {
|
|||
Cons remainingArguments = (Cons) argumentList.getRest();
|
||||
|
||||
if (remainingArguments.isNull())
|
||||
return done(T);
|
||||
return done(Symbol.Companion.getT());
|
||||
|
||||
SExpression firstArgument = argumentList.getFirst();
|
||||
SExpression secondArgument = remainingArguments.getFirst();
|
||||
|
@ -43,7 +43,7 @@ public class NUMERIC_GREATER extends LispFunction {
|
|||
LispNumber number2 = (LispNumber) secondArgument;
|
||||
|
||||
if (!isFirstGreater(number1, number2))
|
||||
return done(NIL);
|
||||
return done(Nil.INSTANCE);
|
||||
|
||||
return tailCall(() -> callTailRecursive(remainingArguments));
|
||||
}
|
||||
|
|
|
@ -6,12 +6,12 @@ import function.LispFunction;
|
|||
import recursion.TailCall;
|
||||
import sexpression.Cons;
|
||||
import sexpression.LispNumber;
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
import sexpression.Symbol;
|
||||
|
||||
import static recursion.TailCalls.done;
|
||||
import static recursion.TailCalls.tailCall;
|
||||
import static sexpression.Nil.NIL;
|
||||
import static sexpression.Symbol.T;
|
||||
|
||||
@FunctionNames({ "<" })
|
||||
public class NUMERIC_LESS extends LispFunction {
|
||||
|
@ -35,7 +35,7 @@ public class NUMERIC_LESS extends LispFunction {
|
|||
Cons remainingArguments = (Cons) argumentList.getRest();
|
||||
|
||||
if (remainingArguments.isNull())
|
||||
return done(T);
|
||||
return done(Symbol.Companion.getT());
|
||||
|
||||
SExpression firstArgument = argumentList.getFirst();
|
||||
SExpression secondArgument = remainingArguments.getFirst();
|
||||
|
@ -43,7 +43,7 @@ public class NUMERIC_LESS extends LispFunction {
|
|||
LispNumber number2 = (LispNumber) secondArgument;
|
||||
|
||||
if (!isFirstLesser(number1, number2))
|
||||
return done(NIL);
|
||||
return done(Nil.INSTANCE);
|
||||
|
||||
return tailCall(() -> callTailRecursive(remainingArguments));
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@ import function.FunctionNames
|
|||
import function.LispFunction
|
||||
import sexpression.Cons
|
||||
import sexpression.LispNumber
|
||||
import sexpression.Nil.NIL
|
||||
import sexpression.Nil
|
||||
import sexpression.SExpression
|
||||
import sexpression.Symbol.T
|
||||
import sexpression.Symbol.Companion.T
|
||||
|
||||
@FunctionNames("=")
|
||||
class NumericEqual(name: String) : LispFunction() {
|
||||
|
@ -34,6 +34,6 @@ class NumericEqual(name: String) : LispFunction() {
|
|||
val number1 = argumentList.first as LispNumber
|
||||
val number2 = remainingArguments.first as LispNumber
|
||||
|
||||
return if (number1.value != number2.value) NIL else callTailRecursive(remainingArguments)
|
||||
return if (number1.value != number2.value) Nil else callTailRecursive(remainingArguments)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,11 @@ import function.LispSpecialFunction;
|
|||
import recursion.TailCall;
|
||||
import sexpression.Cons;
|
||||
import sexpression.SExpression;
|
||||
import sexpression.Symbol;
|
||||
|
||||
import static function.builtin.EVAL.eval;
|
||||
import static recursion.TailCalls.done;
|
||||
import static recursion.TailCalls.tailCall;
|
||||
import static sexpression.Symbol.T;
|
||||
|
||||
@FunctionNames({ "AND" })
|
||||
public class AND extends LispSpecialFunction {
|
||||
|
@ -25,7 +25,7 @@ public class AND extends LispSpecialFunction {
|
|||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
|
||||
return callTailRecursive(argumentList, T).invoke();
|
||||
return callTailRecursive(argumentList, Symbol.Companion.getT()).invoke();
|
||||
}
|
||||
|
||||
private TailCall<SExpression> callTailRecursive(Cons argumentList, SExpression lastValue) {
|
||||
|
|
|
@ -7,13 +7,12 @@ import recursion.TailCall;
|
|||
import sexpression.Cons;
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
import sexpression.Symbol;
|
||||
|
||||
import static function.builtin.EVAL.eval;
|
||||
import static function.builtin.predicate.EQUAL.isEqual;
|
||||
import static recursion.TailCalls.done;
|
||||
import static recursion.TailCalls.tailCall;
|
||||
import static sexpression.Nil.NIL;
|
||||
import static sexpression.Symbol.T;
|
||||
|
||||
@FunctionNames({ "CASE" })
|
||||
public class CASE extends LispSpecialFunction {
|
||||
|
@ -37,7 +36,7 @@ public class CASE extends LispSpecialFunction {
|
|||
|
||||
private TailCall<SExpression> callTailRecursive(SExpression key, Cons argumentList) {
|
||||
if (argumentList.isNull())
|
||||
return done(NIL);
|
||||
return done(Nil.INSTANCE);
|
||||
|
||||
Cons clause = (Cons) argumentList.getFirst();
|
||||
Cons remainingClauses = (Cons) argumentList.getRest();
|
||||
|
@ -55,7 +54,7 @@ public class CASE extends LispSpecialFunction {
|
|||
else if (keyList.isCons())
|
||||
return containsMatch(key, keyList);
|
||||
|
||||
return isEqual(key, keyList) || isEqual(T, keyList);
|
||||
return isEqual(key, keyList) || isEqual(Symbol.Companion.getT(), keyList);
|
||||
}
|
||||
|
||||
private boolean containsMatch(SExpression key, SExpression keyList) {
|
||||
|
@ -75,7 +74,7 @@ public class CASE extends LispSpecialFunction {
|
|||
}
|
||||
|
||||
private SExpression evaluateConsequents(SExpression consequentList) {
|
||||
SExpression lastConsequentValue = NIL;
|
||||
SExpression lastConsequentValue = Nil.INSTANCE;
|
||||
|
||||
for (; consequentList.isCons(); consequentList = advanceCons(consequentList))
|
||||
lastConsequentValue = eval(getFirst(consequentList));
|
||||
|
|
|
@ -11,7 +11,6 @@ import sexpression.SExpression;
|
|||
import static function.builtin.EVAL.eval;
|
||||
import static recursion.TailCalls.done;
|
||||
import static recursion.TailCalls.tailCall;
|
||||
import static sexpression.Nil.NIL;
|
||||
|
||||
@FunctionNames({ "COND" })
|
||||
public class COND extends LispSpecialFunction {
|
||||
|
@ -33,7 +32,7 @@ public class COND extends LispSpecialFunction {
|
|||
|
||||
private TailCall<SExpression> callTailRecursive(Cons argumentList) {
|
||||
if (argumentList.isNull())
|
||||
return done(NIL);
|
||||
return done(Nil.INSTANCE);
|
||||
|
||||
Cons clause = (Cons) argumentList.getFirst();
|
||||
Cons remainingClauses = (Cons) argumentList.getRest();
|
||||
|
@ -46,7 +45,7 @@ public class COND extends LispSpecialFunction {
|
|||
}
|
||||
|
||||
private boolean isTestSuccessful(SExpression test) {
|
||||
return test != NIL;
|
||||
return test != Nil.INSTANCE;
|
||||
}
|
||||
|
||||
private SExpression evaluateConsequents(SExpression consequentList, SExpression test) {
|
||||
|
|
|
@ -4,13 +4,13 @@ import function.ArgumentValidator;
|
|||
import function.FunctionNames;
|
||||
import function.LispSpecialFunction;
|
||||
import sexpression.Cons;
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
import sexpression.Symbol;
|
||||
import table.ExecutionContext;
|
||||
import table.SymbolTable;
|
||||
|
||||
import static function.builtin.EVAL.eval;
|
||||
import static sexpression.Nil.NIL;
|
||||
|
||||
@FunctionNames({ "LET" })
|
||||
public class LET extends LispSpecialFunction {
|
||||
|
@ -79,7 +79,7 @@ public class LET extends LispSpecialFunction {
|
|||
}
|
||||
|
||||
private SExpression evaluateBody(Cons body) {
|
||||
SExpression lastEvaluation = NIL;
|
||||
SExpression lastEvaluation = Nil.INSTANCE;
|
||||
|
||||
for (; body.isCons(); body = (Cons) body.getRest())
|
||||
lastEvaluation = eval(body.getFirst());
|
||||
|
|
|
@ -5,12 +5,12 @@ import function.FunctionNames;
|
|||
import function.LispSpecialFunction;
|
||||
import recursion.TailCall;
|
||||
import sexpression.Cons;
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
|
||||
import static function.builtin.EVAL.eval;
|
||||
import static recursion.TailCalls.done;
|
||||
import static recursion.TailCalls.tailCall;
|
||||
import static sexpression.Nil.NIL;
|
||||
|
||||
@FunctionNames({ "PROGN", "BEGIN" })
|
||||
public class PROGN extends LispSpecialFunction {
|
||||
|
@ -25,7 +25,7 @@ public class PROGN extends LispSpecialFunction {
|
|||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
|
||||
return callTailRecursive(argumentList, NIL).invoke();
|
||||
return callTailRecursive(argumentList, Nil.INSTANCE).invoke();
|
||||
}
|
||||
|
||||
private TailCall<SExpression> callTailRecursive(Cons argumentList, SExpression lastValue) {
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
package sexpression;
|
||||
|
||||
public class AtSignExpression extends SExpression {
|
||||
|
||||
private SExpression expression;
|
||||
|
||||
public AtSignExpression(SExpression expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
public SExpression getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAtSign() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "@" + expression;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package sexpression
|
||||
|
||||
class AtSignExpression(val expression: SExpression) : SExpression() {
|
||||
|
||||
override val isAtSign: Boolean
|
||||
get() = true
|
||||
|
||||
override fun toString() = "@$expression"
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
package sexpression;
|
||||
|
||||
@DisplayName("atom")
|
||||
public abstract class Atom extends SExpression {
|
||||
|
||||
private String text;
|
||||
|
||||
public Atom(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAtom() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return text;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package sexpression
|
||||
|
||||
@DisplayName("atom")
|
||||
abstract class Atom(private val text: String) : SExpression() {
|
||||
|
||||
override val isAtom: Boolean
|
||||
get() = true
|
||||
|
||||
override fun toString() = text
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package sexpression;
|
||||
|
||||
public class BackquoteExpression extends SExpression {
|
||||
|
||||
private SExpression expression;
|
||||
|
||||
public BackquoteExpression(SExpression expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
public SExpression getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBackquote() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "`" + expression;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package sexpression
|
||||
|
||||
class BackquoteExpression(val expression: SExpression) : SExpression() {
|
||||
|
||||
override val isBackquote: Boolean
|
||||
get() = true
|
||||
|
||||
override fun toString() = "`$expression"
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package sexpression;
|
||||
|
||||
public class CommaExpression extends SExpression {
|
||||
|
||||
private SExpression expression;
|
||||
|
||||
public CommaExpression(SExpression expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
public SExpression getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isComma() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "," + expression;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package sexpression
|
||||
|
||||
class CommaExpression(val expression: SExpression) : SExpression() {
|
||||
|
||||
override val isComma: Boolean
|
||||
get() = true
|
||||
|
||||
override fun toString() = ",$expression"
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
package sexpression;
|
||||
|
||||
import recursion.TailCall;
|
||||
|
||||
import static recursion.TailCalls.done;
|
||||
import static recursion.TailCalls.tailCall;
|
||||
|
||||
@DisplayName("list")
|
||||
public class Cons extends SExpression {
|
||||
|
||||
private SExpression first;
|
||||
private SExpression rest;
|
||||
|
||||
public Cons(SExpression first, SExpression rest) {
|
||||
this.first = first;
|
||||
this.rest = rest;
|
||||
}
|
||||
|
||||
public SExpression getFirst() {
|
||||
return first;
|
||||
}
|
||||
|
||||
public SExpression getRest() {
|
||||
return rest;
|
||||
}
|
||||
|
||||
public void setFirst(SExpression first) {
|
||||
this.first = first;
|
||||
}
|
||||
|
||||
public void setRest(SExpression rest) {
|
||||
this.rest = rest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCons() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringTailRecursive(new StringBuilder("(")).invoke();
|
||||
}
|
||||
|
||||
private TailCall<String> toStringTailRecursive(StringBuilder leadingString) {
|
||||
leadingString.append(first.toString());
|
||||
|
||||
if (rest.isNull())
|
||||
return done(leadingString.append(")").toString());
|
||||
else if (rest.isCons()) {
|
||||
return tailCall(() -> ((Cons) rest).toStringTailRecursive(leadingString.append(" ")));
|
||||
}
|
||||
|
||||
return done(leadingString.append(" . " + rest.toString() + ")").toString());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package sexpression
|
||||
|
||||
import recursion.TailCall
|
||||
|
||||
import recursion.TailCalls.done
|
||||
import recursion.TailCalls.tailCall
|
||||
|
||||
@DisplayName("list")
|
||||
open class Cons(open var first: SExpression, open var rest: SExpression) : SExpression() {
|
||||
|
||||
override val isCons: Boolean
|
||||
get() = true
|
||||
|
||||
override fun toString(): String {
|
||||
return toStringTailRecursive(StringBuilder("(")).invoke()
|
||||
}
|
||||
|
||||
private fun toStringTailRecursive(leadingString: StringBuilder): TailCall<String> {
|
||||
leadingString.append(first.toString())
|
||||
|
||||
if (rest.isNull)
|
||||
return done(leadingString.append(")").toString())
|
||||
else if (rest.isCons) {
|
||||
return tailCall { (rest as Cons).toStringTailRecursive(leadingString.append(" ")) }
|
||||
}
|
||||
|
||||
return done(leadingString.append(" . " + rest.toString() + ")").toString())
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package sexpression;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface DisplayName {
|
||||
|
||||
String value();
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package sexpression
|
||||
|
||||
import kotlin.annotation.AnnotationRetention.RUNTIME
|
||||
import kotlin.annotation.AnnotationTarget.CLASS
|
||||
import kotlin.annotation.AnnotationTarget.FILE
|
||||
|
||||
@Retention(RUNTIME)
|
||||
@Target(CLASS, FILE)
|
||||
annotation class DisplayName(val value: String)
|
|
@ -1,33 +0,0 @@
|
|||
package sexpression;
|
||||
|
||||
import function.UserDefinedFunction;
|
||||
|
||||
@DisplayName("lambda-expression")
|
||||
public class LambdaExpression extends SExpression {
|
||||
|
||||
private Cons lambdaExpression;
|
||||
private UserDefinedFunction function;
|
||||
|
||||
public LambdaExpression(Cons lambdaExpression, UserDefinedFunction function) {
|
||||
this.lambdaExpression = lambdaExpression;
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFunction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Cons getLambdaExpression() {
|
||||
return lambdaExpression;
|
||||
}
|
||||
|
||||
public UserDefinedFunction getFunction() {
|
||||
return function;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return lambdaExpression.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package sexpression
|
||||
|
||||
import function.UserDefinedFunction
|
||||
|
||||
@DisplayName("lambda-expression")
|
||||
class LambdaExpression(val lambdaExpression: Cons, val function: UserDefinedFunction) : SExpression() {
|
||||
|
||||
override val isFunction: Boolean
|
||||
get() = true
|
||||
|
||||
override fun toString() = lambdaExpression.toString()
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
package sexpression;
|
||||
|
||||
import error.LispException;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import static java.text.MessageFormat.format;
|
||||
|
||||
@DisplayName("number")
|
||||
public class LispNumber extends Atom {
|
||||
|
||||
public static final LispNumber ZERO = new LispNumber(BigInteger.ZERO);
|
||||
public static final LispNumber ONE = new LispNumber(BigInteger.ONE);
|
||||
|
||||
private BigInteger value;
|
||||
|
||||
public LispNumber(String text) {
|
||||
super(text.replaceFirst("^0+(?!$)", ""));
|
||||
|
||||
try {
|
||||
this.value = new BigInteger(text);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new InvalidNumberException(text);
|
||||
}
|
||||
}
|
||||
|
||||
public LispNumber(BigInteger value) {
|
||||
super(value.toString());
|
||||
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNumber() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public BigInteger getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public class InvalidNumberException extends LispException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String text;
|
||||
|
||||
public InvalidNumberException(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return format("{0} is not a valid integer", text);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package sexpression
|
||||
|
||||
import error.LispException
|
||||
|
||||
import java.math.BigInteger
|
||||
|
||||
import java.text.MessageFormat.format
|
||||
|
||||
@DisplayName("number")
|
||||
class LispNumber : Atom {
|
||||
|
||||
var value: BigInteger? = null
|
||||
private set
|
||||
|
||||
override val isNumber: Boolean
|
||||
get() = true
|
||||
|
||||
constructor(text: String) : super(text.replaceFirst("^0+(?!$)".toRegex(), "")) {
|
||||
try {
|
||||
this.value = BigInteger(text)
|
||||
} catch (e: NumberFormatException) {
|
||||
throw InvalidNumberException(text)
|
||||
}
|
||||
}
|
||||
|
||||
constructor(value: BigInteger) : super(value.toString()) {
|
||||
this.value = value
|
||||
}
|
||||
|
||||
inner class InvalidNumberException(private val text: String) : LispException() {
|
||||
override val message: String
|
||||
get() = format("{0} is not a valid integer", text)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ZERO = LispNumber(BigInteger.ZERO)
|
||||
val ONE = LispNumber(BigInteger.ONE)
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package sexpression;
|
||||
|
||||
@DisplayName("string")
|
||||
public class LispString extends Atom {
|
||||
|
||||
public LispString(String text) {
|
||||
super(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isString() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package sexpression
|
||||
|
||||
@DisplayName("string")
|
||||
class LispString(text: String) : Atom(text) {
|
||||
|
||||
override val isString: Boolean
|
||||
get() = true
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
package sexpression;
|
||||
|
||||
@DisplayName("nil")
|
||||
public class Nil extends Cons {
|
||||
|
||||
public static final Nil NIL = new Nil();
|
||||
|
||||
private Nil() {
|
||||
super(null, null);
|
||||
|
||||
super.setFirst(this);
|
||||
super.setRest(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNull() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAtom() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCons() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSymbol() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The first of NIL can not be changed.
|
||||
*/
|
||||
@Override
|
||||
public void setFirst(SExpression first) {}
|
||||
|
||||
/**
|
||||
* The rest of NIL can not be changed.
|
||||
*/
|
||||
@Override
|
||||
public void setRest(SExpression rest) {}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NIL";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package sexpression
|
||||
|
||||
import sexpression.Symbol.Companion.T
|
||||
|
||||
@DisplayName("nil")
|
||||
object Nil : Cons(T, T) {
|
||||
|
||||
override var first: SExpression = this
|
||||
set(_) {}
|
||||
|
||||
override var rest: SExpression = this
|
||||
set(_) {}
|
||||
|
||||
override val isNull: Boolean
|
||||
get() = true
|
||||
|
||||
override val isAtom: Boolean
|
||||
get() = true
|
||||
|
||||
override val isCons: Boolean
|
||||
get() = false
|
||||
|
||||
override val isSymbol: Boolean
|
||||
get() = true
|
||||
|
||||
override fun toString() = "NIL"
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
package sexpression;
|
||||
|
||||
@DisplayName("s-expression")
|
||||
public abstract class SExpression {
|
||||
|
||||
public boolean isNull() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isAtom() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isCons() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isList() {
|
||||
return (isCons() || isNull());
|
||||
}
|
||||
|
||||
public boolean isNumber() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isSymbol() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isFunction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isString() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isBackquote() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isComma() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isAtSign() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package sexpression
|
||||
|
||||
@DisplayName("s-expression")
|
||||
abstract class SExpression {
|
||||
|
||||
open val isNull: Boolean
|
||||
get() = false
|
||||
|
||||
open val isAtom: Boolean
|
||||
get() = false
|
||||
|
||||
open val isCons: Boolean
|
||||
get() = false
|
||||
|
||||
open val isList: Boolean
|
||||
get() = isCons || isNull
|
||||
|
||||
open val isNumber: Boolean
|
||||
get() = false
|
||||
|
||||
open val isSymbol: Boolean
|
||||
get() = false
|
||||
|
||||
open val isFunction: Boolean
|
||||
get() = false
|
||||
|
||||
open val isString: Boolean
|
||||
get() = false
|
||||
|
||||
open val isBackquote: Boolean
|
||||
get() = false
|
||||
|
||||
open val isComma: Boolean
|
||||
get() = false
|
||||
|
||||
open val isAtSign: Boolean
|
||||
get() = false
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package sexpression;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
@DisplayName("symbol")
|
||||
public class Symbol extends Atom {
|
||||
|
||||
public static final Symbol T = new Symbol("T");
|
||||
|
||||
public static Symbol createQuote() {
|
||||
return new Symbol("QUOTE");
|
||||
}
|
||||
|
||||
public Symbol(String text) {
|
||||
super(text.toUpperCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSymbol() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package sexpression
|
||||
|
||||
import java.util.Locale
|
||||
|
||||
@DisplayName("symbol")
|
||||
open class Symbol(text: String) : Atom(text.toUpperCase(Locale.ROOT)) {
|
||||
|
||||
override val isSymbol: Boolean
|
||||
get() = true
|
||||
|
||||
companion object {
|
||||
val T = Symbol("T")
|
||||
|
||||
fun createQuote() = Symbol("QUOTE")
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ package table
|
|||
|
||||
import function.LispFunction
|
||||
import sexpression.Cons
|
||||
import sexpression.Nil.NIL
|
||||
import sexpression.Nil
|
||||
import sexpression.SExpression
|
||||
import table.SymbolTable.NullSymbolTable
|
||||
import java.util.Stack
|
||||
|
@ -39,7 +39,7 @@ object ExecutionContext {
|
|||
}
|
||||
|
||||
fun toList(): Cons {
|
||||
var symbols: Cons = NIL
|
||||
var symbols: Cons = Nil
|
||||
|
||||
for (table in scope)
|
||||
symbols = Cons(table.toList(), symbols)
|
||||
|
|
|
@ -3,14 +3,14 @@ package table
|
|||
import function.builtin.cons.APPEND.append
|
||||
import function.builtin.cons.LIST.makeList
|
||||
import sexpression.Cons
|
||||
import sexpression.Nil.NIL
|
||||
import sexpression.Nil
|
||||
import sexpression.SExpression
|
||||
import sexpression.Symbol
|
||||
import kotlin.collections.Map.Entry
|
||||
|
||||
open class SymbolTable @JvmOverloads constructor(open val parent: SymbolTable? = NullSymbolTable) : Iterable<SymbolTable> {
|
||||
|
||||
private val table = mutableMapOf<String, SExpression>()
|
||||
private val table = mutableMapOf<String, SExpression>()
|
||||
|
||||
override fun iterator(): Iterator<SymbolTable> = SymbolTableIterator(this)
|
||||
operator fun contains(symbolName: String) = symbolName in table
|
||||
|
@ -23,7 +23,7 @@ open class SymbolTable @JvmOverloads constructor(open val parent: SymbolTable? =
|
|||
fun isGlobal() = parent === NullSymbolTable
|
||||
|
||||
fun toList(): Cons {
|
||||
var context: Cons = NIL
|
||||
var context: Cons = Nil
|
||||
|
||||
for (binding in table.toSortedMap().entries)
|
||||
context = append(context, makeList(makeSymbolValuePair(binding)))
|
||||
|
|
|
@ -2,7 +2,7 @@ package token
|
|||
|
||||
import file.FilePosition
|
||||
import sexpression.Cons
|
||||
import sexpression.Nil.NIL
|
||||
import sexpression.Nil
|
||||
import sexpression.SExpression
|
||||
import sexpression.Symbol
|
||||
|
||||
|
@ -12,6 +12,6 @@ class QuoteMark(text: String, position: FilePosition) : Token(text, position) {
|
|||
val nextToken = getNextToken()
|
||||
val argument = nextToken.parseSExpression(getNextToken)
|
||||
|
||||
return Cons(Symbol.createQuote(), Cons(argument, NIL))
|
||||
return Cons(Symbol.createQuote(), Cons(argument, Nil))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import file.FilePosition
|
|||
import recursion.TailCall
|
||||
import recursion.TailCalls.done
|
||||
import sexpression.Cons
|
||||
import sexpression.Nil.NIL
|
||||
import sexpression.Nil
|
||||
import sexpression.SExpression
|
||||
|
||||
class RightParenthesis(text: String, position: FilePosition) : Token(text, position) {
|
||||
|
@ -15,7 +15,7 @@ class RightParenthesis(text: String, position: FilePosition) : Token(text, posit
|
|||
}
|
||||
|
||||
override fun parseListTail(getNextToken: () -> Token): TailCall<Cons> {
|
||||
return done(NIL)
|
||||
return done(Nil)
|
||||
}
|
||||
|
||||
override fun parseListTailRecursive(start: Cons, end: Cons, getNextToken: () -> Token): TailCall<Cons> {
|
||||
|
|
|
@ -4,7 +4,7 @@ import file.FilePosition
|
|||
import recursion.TailCall
|
||||
import recursion.TailCalls.tailCall
|
||||
import sexpression.Cons
|
||||
import sexpression.Nil.NIL
|
||||
import sexpression.Nil
|
||||
import sexpression.SExpression
|
||||
|
||||
abstract class Token(val text: String, val position: FilePosition) {
|
||||
|
@ -20,14 +20,14 @@ abstract class Token(val text: String, val position: FilePosition) {
|
|||
abstract fun parseSExpression(getNextToken: () -> Token): SExpression
|
||||
|
||||
open fun parseListTail(getNextToken: () -> Token): TailCall<Cons> {
|
||||
val firstCons = Cons(parseSExpression(getNextToken), NIL)
|
||||
val firstCons = Cons(parseSExpression(getNextToken), Nil)
|
||||
val next = getNextToken()
|
||||
|
||||
return tailCall { next.parseListTailRecursive(firstCons, firstCons, getNextToken) }
|
||||
}
|
||||
|
||||
protected open fun parseListTailRecursive(start: Cons, end: Cons, getNextToken: () -> Token): TailCall<Cons> {
|
||||
val newEnd = Cons(parseSExpression(getNextToken), NIL)
|
||||
val newEnd = Cons(parseSExpression(getNextToken), Nil)
|
||||
val next = getNextToken()
|
||||
end.rest = newEnd
|
||||
|
||||
|
|
|
@ -3,13 +3,11 @@
|
|||
(defmacro dlambda (&rest methods)
|
||||
(let ((arguments (gensym)))
|
||||
|
||||
`(lambda (&rest ,arguments)
|
||||
(case (first ,arguments)
|
||||
,@(mapcar
|
||||
(lambda (method)
|
||||
`(,(first method)
|
||||
(apply (lambda ,@(rest method))
|
||||
,(if (equal t (first method))
|
||||
arguments
|
||||
`(rest ,arguments)))))
|
||||
methods)))))
|
||||
`(lambda (&rest, arguments)
|
||||
(case (first, arguments), @(mapcar
|
||||
(lambda (method))
|
||||
`(, (first method))
|
||||
(apply (lambda, @(rest method)), (if (equal t (first method)))
|
||||
arguments
|
||||
`(rest, arguments))
|
||||
methods)))))
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
(defun maplist (function-name the-list)
|
||||
(cond
|
||||
((null the-list) nil)
|
||||
(t (cons (funcall function-name the-list)
|
||||
(maplist function-name (rest the-list))))))
|
||||
((null the-list) nil)
|
||||
(t (cons (funcall function-name the-list)
|
||||
(maplist function-name (rest the-list))))))
|
||||
|
||||
(defun map (function the-list)
|
||||
(reverse (map-tail function the-list nil)))
|
||||
|
@ -42,7 +42,7 @@
|
|||
|
||||
(defun reverse-tail (accumulator the-list)
|
||||
(if (null the-list) accumulator
|
||||
(recur (cons (first the-list) accumulator) (rest the-list))))
|
||||
(recur (cons (first the-list) accumulator) (rest the-list))))
|
||||
|
||||
(defun deep-reverse (the-list)
|
||||
(if the-list
|
||||
|
@ -55,9 +55,9 @@
|
|||
|
||||
(defun nth (n listA)
|
||||
(cond
|
||||
((equal 0 n) (first listA))
|
||||
(t (nth (- n 1) (rest listA)))))
|
||||
((equal 0 n) (first listA))
|
||||
(t (nth (- n 1) (rest listA)))))
|
||||
|
||||
(eval
|
||||
(let ((expr (gensym)))
|
||||
`(defun global-eval (,expr) (eval ,expr))))
|
||||
`(defun global-eval (, expr) (eval, expr))))
|
||||
|
|
|
@ -16,18 +16,16 @@ import static error.Severity.ERROR;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static sexpression.Nil.NIL;
|
||||
import static sexpression.Symbol.T;
|
||||
|
||||
public class ArgumentValidatorTest {
|
||||
|
||||
private ArgumentValidator validator;
|
||||
|
||||
private Cons makeArgumentListOfSize(int size) {
|
||||
Cons argumentList = NIL;
|
||||
Cons argumentList = Nil.INSTANCE;
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
argumentList = new Cons(NIL, argumentList);
|
||||
argumentList = new Cons(Nil.INSTANCE, argumentList);
|
||||
|
||||
return argumentList;
|
||||
}
|
||||
|
@ -84,7 +82,7 @@ public class ArgumentValidatorTest {
|
|||
|
||||
@Test
|
||||
public void tooManyArgumentsException_HasCorrectAttributes() {
|
||||
TooManyArgumentsException e = new TooManyArgumentsException("TEST", NIL);
|
||||
TooManyArgumentsException e = new TooManyArgumentsException("TEST", Nil.INSTANCE);
|
||||
|
||||
assertEquals(ERROR, e.getSeverity());
|
||||
assertNotNull(e.getMessage());
|
||||
|
@ -93,7 +91,7 @@ public class ArgumentValidatorTest {
|
|||
|
||||
@Test
|
||||
public void tooFewArgumentsException_HasCorrectAttributes() {
|
||||
TooFewArgumentsException e = new TooFewArgumentsException("TEST", NIL);
|
||||
TooFewArgumentsException e = new TooFewArgumentsException("TEST", Nil.INSTANCE);
|
||||
|
||||
assertEquals(ERROR, e.getSeverity());
|
||||
assertNotNull(e.getMessage());
|
||||
|
@ -102,7 +100,7 @@ public class ArgumentValidatorTest {
|
|||
|
||||
@Test
|
||||
public void badArgumentTypeException_HasCorrectAttributes() {
|
||||
BadArgumentTypeException e = new BadArgumentTypeException("TEST", NIL, SExpression.class);
|
||||
BadArgumentTypeException e = new BadArgumentTypeException("TEST", Nil.INSTANCE, SExpression.class);
|
||||
|
||||
assertEquals(ERROR, e.getSeverity());
|
||||
assertNotNull(e.getMessage());
|
||||
|
@ -123,7 +121,7 @@ public class ArgumentValidatorTest {
|
|||
|
||||
@Test
|
||||
public void correctFirstAndRestArgumentTypes_DoesNotThrowException() {
|
||||
Cons argumentList = new Cons(T, new Cons(NIL, NIL));
|
||||
Cons argumentList = new Cons(Symbol.Companion.getT(), new Cons(Nil.INSTANCE, Nil.INSTANCE));
|
||||
|
||||
validator.setFirstArgumentExpectedType(Symbol.class);
|
||||
validator.setTrailingArgumentExpectedType(Cons.class);
|
||||
|
@ -132,7 +130,7 @@ public class ArgumentValidatorTest {
|
|||
|
||||
@Test(expected = BadArgumentTypeException.class)
|
||||
public void badFirstArgumentType_ThrowsException() {
|
||||
Cons argumentList = new Cons(T, new Cons(NIL, NIL));
|
||||
Cons argumentList = new Cons(Symbol.Companion.getT(), new Cons(Nil.INSTANCE, Nil.INSTANCE));
|
||||
|
||||
validator.setFirstArgumentExpectedType(Cons.class);
|
||||
validator.setTrailingArgumentExpectedType(Cons.class);
|
||||
|
@ -141,7 +139,7 @@ public class ArgumentValidatorTest {
|
|||
|
||||
@Test(expected = BadArgumentTypeException.class)
|
||||
public void badTrailingArgumentType_ThrowsException() {
|
||||
Cons argumentList = new Cons(T, new Cons(NIL, NIL));
|
||||
Cons argumentList = new Cons(Symbol.Companion.getT(), new Cons(Nil.INSTANCE, Nil.INSTANCE));
|
||||
|
||||
validator.setFirstArgumentExpectedType(Symbol.class);
|
||||
validator.setTrailingArgumentExpectedType(Symbol.class);
|
||||
|
@ -150,7 +148,7 @@ public class ArgumentValidatorTest {
|
|||
|
||||
@Test
|
||||
public void expectedTypeWithNoDisplayName_DoesNotCauseNPE() {
|
||||
Cons argumentList = new Cons(T, new Cons(NIL, NIL));
|
||||
Cons argumentList = new Cons(Symbol.Companion.getT(), new Cons(Nil.INSTANCE, Nil.INSTANCE));
|
||||
SExpression withoutDisplayName = new SExpression() {};
|
||||
|
||||
validator.setEveryArgumentExpectedType(withoutDisplayName.getClass());
|
||||
|
@ -165,21 +163,22 @@ public class ArgumentValidatorTest {
|
|||
|
||||
@Test(expected = DottedArgumentListException.class)
|
||||
public void givenDottedArgumentList_ThrowsException() {
|
||||
Cons argumentList = new Cons(T, T);
|
||||
Cons argumentList = new Cons(Symbol.Companion.getT(), Symbol.Companion.getT());
|
||||
|
||||
validator.validate(argumentList);
|
||||
}
|
||||
|
||||
@Test(expected = DottedArgumentListException.class)
|
||||
public void givenLargeDottedArgumentList_ThrowsException() {
|
||||
Cons argumentList = new Cons(T, new Cons(T, T));
|
||||
Cons argumentList =
|
||||
new Cons(Symbol.Companion.getT(), new Cons(Symbol.Companion.getT(), Symbol.Companion.getT()));
|
||||
|
||||
validator.validate(argumentList);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dottedArgumentListException_HasCorrectAttributes() {
|
||||
DottedArgumentListException e = new DottedArgumentListException("TEST", NIL);
|
||||
DottedArgumentListException e = new DottedArgumentListException("TEST", Nil.INSTANCE);
|
||||
|
||||
assertEquals(ERROR, e.getSeverity());
|
||||
assertNotNull(e.getMessage());
|
||||
|
@ -189,36 +188,36 @@ public class ArgumentValidatorTest {
|
|||
@Test
|
||||
public void excludedFirstArgumentType_DoesNotAffectTrailingArguments() {
|
||||
validator.setFirstArgumentExcludedType(Nil.class);
|
||||
validator.validate(new Cons(T, new Cons(NIL, NIL)));
|
||||
validator.validate(new Cons(Symbol.Companion.getT(), new Cons(Nil.INSTANCE, Nil.INSTANCE)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void excludedTrailingArgumentType_DoesNotAffectFirstArgument() {
|
||||
validator.setTrailingArgumentExcludedType(Nil.class);
|
||||
validator.validate(new Cons(NIL, new Cons(T, NIL)));
|
||||
validator.validate(new Cons(Nil.INSTANCE, new Cons(Symbol.Companion.getT(), Nil.INSTANCE)));
|
||||
}
|
||||
|
||||
@Test(expected = BadArgumentTypeException.class)
|
||||
public void excludedFirstArgumentType_ThrowsException() {
|
||||
validator.setFirstArgumentExcludedType(Nil.class);
|
||||
validator.validate(new Cons(NIL, new Cons(T, NIL)));
|
||||
validator.validate(new Cons(Nil.INSTANCE, new Cons(Symbol.Companion.getT(), Nil.INSTANCE)));
|
||||
}
|
||||
|
||||
@Test(expected = BadArgumentTypeException.class)
|
||||
public void excludedTrailingArgumentType_ThrowsException() {
|
||||
validator.setTrailingArgumentExcludedType(Nil.class);
|
||||
validator.validate(new Cons(T, new Cons(NIL, NIL)));
|
||||
validator.validate(new Cons(Symbol.Companion.getT(), new Cons(Nil.INSTANCE, Nil.INSTANCE)));
|
||||
}
|
||||
|
||||
@Test(expected = BadArgumentTypeException.class)
|
||||
public void excludedArgumentType_ThrowsExceptionOnFirstArgument() {
|
||||
validator.setEveryArgumentExcludedType(Nil.class);
|
||||
validator.validate(new Cons(NIL, new Cons(T, NIL)));
|
||||
validator.validate(new Cons(Nil.INSTANCE, new Cons(Symbol.Companion.getT(), Nil.INSTANCE)));
|
||||
}
|
||||
|
||||
@Test(expected = BadArgumentTypeException.class)
|
||||
public void excludedArgumentType_ThrowsExceptionOnTrailingArgument() {
|
||||
validator.setEveryArgumentExcludedType(Nil.class);
|
||||
validator.validate(new Cons(T, new Cons(NIL, NIL)));
|
||||
validator.validate(new Cons(Symbol.Companion.getT(), new Cons(Nil.INSTANCE, Nil.INSTANCE)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,13 @@ import function.UserDefinedFunction.IllegalKeywordRestPositionException;
|
|||
import org.junit.Test;
|
||||
import sexpression.Cons;
|
||||
import sexpression.LispNumber;
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
import sexpression.Symbol;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static sexpression.Nil.NIL;
|
||||
import static testutil.TestUtilities.assertSExpressionsMatch;
|
||||
|
||||
public class UserDefinedFunctionTest {
|
||||
|
@ -21,24 +21,27 @@ public class UserDefinedFunctionTest {
|
|||
private static final String FUNCTION_NAME = "TEST";
|
||||
|
||||
private UserDefinedFunction createNoArgumentFunctionThatReturnsNil() {
|
||||
return new UserDefinedFunction(FUNCTION_NAME, NIL, new Cons(NIL, NIL));
|
||||
return new UserDefinedFunction(FUNCTION_NAME,
|
||||
Nil.INSTANCE, new Cons(Nil.INSTANCE, Nil.INSTANCE));
|
||||
}
|
||||
|
||||
private UserDefinedFunction createOneArgumentFunctionThatReturnsArgument() {
|
||||
return new UserDefinedFunction(FUNCTION_NAME, new Cons(new Symbol("X"), NIL), new Cons(new Symbol("X"), NIL));
|
||||
return new UserDefinedFunction(FUNCTION_NAME, new Cons(new Symbol("X"), Nil.INSTANCE), new Cons(new Symbol("X"),
|
||||
Nil.INSTANCE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nilFunctionCall() {
|
||||
UserDefinedFunction function = createNoArgumentFunctionThatReturnsNil();
|
||||
|
||||
assertEquals(NIL, function.call(NIL));
|
||||
assertEquals(Nil.INSTANCE, function.call(Nil.INSTANCE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nilFunctionToString() {
|
||||
UserDefinedFunction function = createNoArgumentFunctionThatReturnsNil();
|
||||
Cons expected = new Cons(new Symbol(FUNCTION_NAME), new Cons(NIL, new Cons(NIL, NIL)));
|
||||
Cons expected = new Cons(new Symbol(FUNCTION_NAME), new Cons(Nil.INSTANCE, new Cons(Nil.INSTANCE,
|
||||
Nil.INSTANCE)));
|
||||
|
||||
assertSExpressionsMatch(expected, function.getLambdaExpression());
|
||||
}
|
||||
|
@ -47,7 +50,7 @@ public class UserDefinedFunctionTest {
|
|||
public void oneArgumentFunction_ReturnsCorrectValue() {
|
||||
UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument();
|
||||
SExpression argument = new LispNumber("23");
|
||||
Cons argumentList = new Cons(argument, NIL);
|
||||
Cons argumentList = new Cons(argument, Nil.INSTANCE);
|
||||
|
||||
assertSExpressionsMatch(argument, function.call(argumentList));
|
||||
}
|
||||
|
@ -56,7 +59,7 @@ public class UserDefinedFunctionTest {
|
|||
public void oneArgumentFunction_ThrowsExceptionWithTooManyArguments() {
|
||||
UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument();
|
||||
SExpression argument = new LispNumber("23");
|
||||
Cons argumentList = new Cons(argument, new Cons(argument, NIL));
|
||||
Cons argumentList = new Cons(argument, new Cons(argument, Nil.INSTANCE));
|
||||
|
||||
function.call(argumentList);
|
||||
}
|
||||
|
@ -65,12 +68,13 @@ public class UserDefinedFunctionTest {
|
|||
public void oneArgumentFunction_ThrowsExceptionWithTooFewArguments() {
|
||||
UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument();
|
||||
|
||||
function.call(NIL);
|
||||
function.call(Nil.INSTANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void illegalKeywordRestPositionException_HasCorrectAttributes() {
|
||||
IllegalKeywordRestPositionException e = new IllegalKeywordRestPositionException(FUNCTION_NAME, NIL);
|
||||
IllegalKeywordRestPositionException e = new IllegalKeywordRestPositionException(FUNCTION_NAME,
|
||||
Nil.INSTANCE);
|
||||
|
||||
assertNotNull(e.getMessage());
|
||||
assertTrue(e.getMessage().length() > 0);
|
||||
|
|
|
@ -12,11 +12,10 @@ import sexpression.CommaExpression;
|
|||
import sexpression.Cons;
|
||||
import sexpression.LispNumber;
|
||||
import sexpression.LispString;
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
import sexpression.Symbol;
|
||||
|
||||
import static sexpression.Nil.NIL;
|
||||
import static sexpression.Symbol.T;
|
||||
import static testutil.TestUtilities.assertIsErrorWithMessage;
|
||||
import static testutil.TestUtilities.assertSExpressionsMatch;
|
||||
import static testutil.TestUtilities.makeList;
|
||||
|
@ -29,9 +28,9 @@ public class BackquoteEvaluatorTest {
|
|||
|
||||
@Test
|
||||
public void evaluateNil() {
|
||||
BackquoteEvaluator evaluator = createBackquoteEvaluator(NIL);
|
||||
BackquoteEvaluator evaluator = createBackquoteEvaluator(Nil.INSTANCE);
|
||||
|
||||
assertSExpressionsMatch(NIL, evaluator.evaluate());
|
||||
assertSExpressionsMatch(Nil.INSTANCE, evaluator.evaluate());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -155,14 +154,17 @@ public class BackquoteEvaluatorTest {
|
|||
|
||||
@Test(expected = DottedArgumentListException.class)
|
||||
public void evaluateDottedList() {
|
||||
BackquoteEvaluator evaluator = createBackquoteEvaluator(new Cons(T, T));
|
||||
BackquoteEvaluator evaluator =
|
||||
createBackquoteEvaluator(new Cons(Symbol.Companion.getT(), Symbol.Companion.getT()));
|
||||
|
||||
evaluator.evaluate();
|
||||
}
|
||||
|
||||
@Test(expected = DottedArgumentListException.class)
|
||||
public void atSignWithDottedList() {
|
||||
SExpression input = makeList(new CommaExpression(new AtSignExpression(makeList(new Symbol("CONS"), T, T))));
|
||||
SExpression input = makeList(new CommaExpression(new AtSignExpression(makeList(new Symbol("CONS"),
|
||||
Symbol.Companion.getT(),
|
||||
Symbol.Companion.getT()))));
|
||||
BackquoteEvaluator evaluator = createBackquoteEvaluator(input);
|
||||
|
||||
evaluator.evaluate();
|
||||
|
|
|
@ -10,12 +10,12 @@ import function.builtin.EVAL.UnmatchedAtSignException;
|
|||
import function.builtin.EVAL.UnmatchedCommaException;
|
||||
import function.builtin.special.RECUR.RecurNotInTailPositionException;
|
||||
import org.junit.Test;
|
||||
import sexpression.Nil;
|
||||
import testutil.SymbolAndFunctionCleaner;
|
||||
|
||||
import static function.builtin.EVAL.lookupSymbol;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.fail;
|
||||
import static sexpression.Nil.NIL;
|
||||
import static testutil.TestUtilities.assertIsErrorWithMessage;
|
||||
import static testutil.TestUtilities.assertSExpressionsMatch;
|
||||
import static testutil.TestUtilities.evaluateString;
|
||||
|
@ -100,12 +100,12 @@ public class EVALTest extends SymbolAndFunctionCleaner {
|
|||
|
||||
@Test
|
||||
public void undefinedFunctionException_HasCorrectAttributes() {
|
||||
assertIsErrorWithMessage(new UndefinedFunctionException(NIL));
|
||||
assertIsErrorWithMessage(new UndefinedFunctionException(Nil.INSTANCE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undefinedSymbolException_HasCorrectAttributes() {
|
||||
assertIsErrorWithMessage(new UndefinedSymbolException(NIL));
|
||||
assertIsErrorWithMessage(new UndefinedSymbolException(Nil.INSTANCE));
|
||||
}
|
||||
|
||||
@Test(expected = UnmatchedCommaException.class)
|
||||
|
|
|
@ -5,13 +5,13 @@ import function.ArgumentValidator.TooFewArgumentsException;
|
|||
import function.ArgumentValidator.TooManyArgumentsException;
|
||||
import function.builtin.SYMBOL_FUNCTION.UndefinedSymbolFunctionException;
|
||||
import org.junit.Test;
|
||||
import sexpression.Nil;
|
||||
import testutil.SymbolAndFunctionCleaner;
|
||||
|
||||
import static error.Severity.ERROR;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static sexpression.Nil.NIL;
|
||||
import static testutil.TestUtilities.evaluateString;
|
||||
|
||||
public class SYMBOL_FUNCTIONTest extends SymbolAndFunctionCleaner {
|
||||
|
@ -63,7 +63,7 @@ public class SYMBOL_FUNCTIONTest extends SymbolAndFunctionCleaner {
|
|||
|
||||
@Test
|
||||
public void undefinedSymbolFunctionException_HasCorrectAttributes() {
|
||||
UndefinedSymbolFunctionException e = new UndefinedSymbolFunctionException(NIL);
|
||||
UndefinedSymbolFunctionException e = new UndefinedSymbolFunctionException(Nil.INSTANCE);
|
||||
|
||||
assertEquals(ERROR, e.getSeverity());
|
||||
assertNotNull(e.getMessage());
|
||||
|
|
|
@ -8,9 +8,9 @@ import function.builtin.EVAL.UndefinedSymbolException;
|
|||
import org.junit.Test;
|
||||
import sexpression.Cons;
|
||||
import sexpression.LispNumber;
|
||||
import sexpression.Nil;
|
||||
import testutil.SymbolAndFunctionCleaner;
|
||||
|
||||
import static sexpression.Nil.NIL;
|
||||
import static testutil.TestUtilities.assertSExpressionsMatch;
|
||||
import static testutil.TestUtilities.evaluateString;
|
||||
|
||||
|
@ -27,14 +27,14 @@ public class LETTest extends SymbolAndFunctionCleaner {
|
|||
public void emptyLet_ReturnsNil() {
|
||||
String input = "(let ())";
|
||||
|
||||
assertSExpressionsMatch(NIL, evaluateString(input));
|
||||
assertSExpressionsMatch(Nil.INSTANCE, evaluateString(input));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void letWithSymbolsOnly_SetsValuesToNil() {
|
||||
String input = "(let ((x) (y)) (list x y))";
|
||||
|
||||
assertSExpressionsMatch(new Cons(NIL, new Cons(NIL, NIL)), evaluateString(input));
|
||||
assertSExpressionsMatch(new Cons(Nil.INSTANCE, new Cons(Nil.INSTANCE, Nil.INSTANCE)), evaluateString(input));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -8,9 +8,9 @@ import function.builtin.EVAL.UndefinedSymbolException;
|
|||
import org.junit.Test;
|
||||
import sexpression.Cons;
|
||||
import sexpression.LispNumber;
|
||||
import sexpression.Nil;
|
||||
import testutil.SymbolAndFunctionCleaner;
|
||||
|
||||
import static sexpression.Nil.NIL;
|
||||
import static testutil.TestUtilities.assertSExpressionsMatch;
|
||||
import static testutil.TestUtilities.evaluateString;
|
||||
|
||||
|
@ -27,14 +27,14 @@ public class LET_STARTest extends SymbolAndFunctionCleaner {
|
|||
public void emptyLet_ReturnsNil() {
|
||||
String input = "(let* ())";
|
||||
|
||||
assertSExpressionsMatch(NIL, evaluateString(input));
|
||||
assertSExpressionsMatch(Nil.INSTANCE, evaluateString(input));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void letStarWithSymbolsOnly_SetsValuesToNil() {
|
||||
String input = "(let* ((x) (y)) (list x y))";
|
||||
|
||||
assertSExpressionsMatch(new Cons(NIL, new Cons(NIL, NIL)), evaluateString(input));
|
||||
assertSExpressionsMatch(new Cons(Nil.INSTANCE, new Cons(Nil.INSTANCE, Nil.INSTANCE)), evaluateString(input));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -12,10 +12,10 @@ import org.junit.jupiter.api.Assertions.assertThrows
|
|||
import org.junit.jupiter.api.Test
|
||||
import sexpression.Cons
|
||||
import sexpression.LispNumber
|
||||
import sexpression.LispNumber.ONE
|
||||
import sexpression.Nil.NIL
|
||||
import sexpression.LispNumber.Companion.ONE
|
||||
import sexpression.Nil
|
||||
import sexpression.Symbol
|
||||
import sexpression.Symbol.T
|
||||
import sexpression.Symbol.Companion.T
|
||||
import testutil.SymbolAndFunctionCleaner
|
||||
import testutil.TestUtilities.assertSExpressionsMatch
|
||||
import testutil.TestUtilities.evaluateString
|
||||
|
@ -46,7 +46,7 @@ class LambdaTest : SymbolAndFunctionCleaner() {
|
|||
|
||||
@Test
|
||||
fun `lambda expression is a lambda expression`() {
|
||||
val lambdaExpression = Cons(Symbol("LAMBDA"), Cons(NIL, Cons(NIL, NIL)))
|
||||
val lambdaExpression = Cons(Symbol("LAMBDA"), Cons(Nil, Cons(Nil, Nil)))
|
||||
|
||||
assertThat(isLambdaExpression(lambdaExpression)).isTrue()
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ class LambdaTest : SymbolAndFunctionCleaner() {
|
|||
|
||||
@Test
|
||||
fun `create lambda expression`() {
|
||||
val lambdaExpression = Cons(Symbol("LAMBDA"), Cons(NIL, Cons(NIL, NIL)))
|
||||
val lambdaExpression = Cons(Symbol("LAMBDA"), Cons(Nil, Cons(Nil, Nil)))
|
||||
|
||||
assertSExpressionsMatch(parseString("(:LAMBDA () ())"), createFunction(lambdaExpression).lambdaExpression)
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ class LambdaTest : SymbolAndFunctionCleaner() {
|
|||
|
||||
@Test
|
||||
fun `create function with dotted argument list`() {
|
||||
val lambdaExpression = Cons(Symbol("LAMBDA"), Cons(NIL, ONE))
|
||||
val lambdaExpression = Cons(Symbol("LAMBDA"), Cons(Nil, ONE))
|
||||
|
||||
assertThrows(DottedArgumentListException::class.java) { createFunction(lambdaExpression) }
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import static error.Severity.ERROR;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static sexpression.Nil.NIL;
|
||||
import static testutil.TestUtilities.assertSExpressionsMatch;
|
||||
import static testutil.TestUtilities.makeList;
|
||||
|
||||
|
@ -25,7 +24,7 @@ public class SExpressionTest {
|
|||
public void nil_ToString() {
|
||||
String input = "NIL";
|
||||
|
||||
assertSExpressionMatchesString(input, NIL);
|
||||
assertSExpressionMatchesString(input, Nil.INSTANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -83,7 +82,8 @@ public class SExpressionTest {
|
|||
@Test
|
||||
public void lambdaExpression_ToString() {
|
||||
String expected = "(LAMBDA)";
|
||||
LambdaExpression lambda = new LambdaExpression(makeList(new Symbol("lambda")), null);
|
||||
LambdaExpression lambda = new LambdaExpression(makeList(new Symbol("lambda")),
|
||||
new UserDefinedFunction("", Nil.INSTANCE, Nil.INSTANCE));
|
||||
|
||||
assertSExpressionMatchesString(expected, lambda);
|
||||
}
|
||||
|
@ -91,7 +91,8 @@ public class SExpressionTest {
|
|||
@Test
|
||||
public void lambdaExpression_GetLambdaExpression() {
|
||||
String expected = "(LAMBDA)";
|
||||
LambdaExpression lambda = new LambdaExpression(makeList(new Symbol("lambda")), null);
|
||||
LambdaExpression lambda = new LambdaExpression(makeList(new Symbol("lambda")),
|
||||
new UserDefinedFunction("", Nil.INSTANCE, Nil.INSTANCE));
|
||||
|
||||
assertSExpressionMatchesString(expected, lambda.getLambdaExpression());
|
||||
}
|
||||
|
@ -99,7 +100,7 @@ public class SExpressionTest {
|
|||
@Test
|
||||
public void lambdaExpression_GetFunction() {
|
||||
String expected = "(LAMBDA)";
|
||||
UserDefinedFunction function = new UserDefinedFunction(expected, NIL, NIL);
|
||||
UserDefinedFunction function = new UserDefinedFunction(expected, Nil.INSTANCE, Nil.INSTANCE);
|
||||
LambdaExpression lambda = new LambdaExpression(makeList(new Symbol("lambda")), function);
|
||||
|
||||
assertEquals(function, lambda.getFunction());
|
||||
|
@ -107,28 +108,28 @@ public class SExpressionTest {
|
|||
|
||||
@Test
|
||||
public void firstOfNilIsNil() {
|
||||
assertEquals(NIL, NIL.getFirst());
|
||||
assertEquals(Nil.INSTANCE, Nil.INSTANCE.getFirst());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restOfNilIsNil() {
|
||||
assertEquals(NIL, NIL.getRest());
|
||||
assertEquals(Nil.INSTANCE, Nil.INSTANCE.getRest());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterSettingFirstOfNil_ShouldStillBeNil() {
|
||||
Cons nil = NIL;
|
||||
Cons nil = Nil.INSTANCE;
|
||||
nil.setFirst(new LispNumber("2"));
|
||||
|
||||
assertEquals(NIL, nil.getFirst());
|
||||
assertEquals(Nil.INSTANCE, nil.getFirst());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterSettingRestOfNil_ShouldStillBeNil() {
|
||||
Cons nil = NIL;
|
||||
Cons nil = Nil.INSTANCE;
|
||||
nil.setRest(new LispNumber("2"));
|
||||
|
||||
assertEquals(NIL, nil.getRest());
|
||||
assertEquals(Nil.INSTANCE, nil.getRest());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -159,8 +160,8 @@ public class SExpressionTest {
|
|||
|
||||
@Test
|
||||
public void lispNumberConstants() {
|
||||
assertEquals(BigInteger.ZERO, LispNumber.ZERO.getValue());
|
||||
assertEquals(BigInteger.ONE, LispNumber.ONE.getValue());
|
||||
assertEquals(BigInteger.ZERO, LispNumber.Companion.getZERO().getValue());
|
||||
assertEquals(BigInteger.ONE, LispNumber.Companion.getONE().getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -6,8 +6,8 @@ import org.junit.jupiter.api.BeforeEach
|
|||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import sexpression.Nil.NIL
|
||||
import sexpression.Symbol.T
|
||||
import sexpression.Nil
|
||||
import sexpression.Symbol.Companion.T
|
||||
import table.SymbolTable.NullSymbolTable
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
|
@ -75,11 +75,11 @@ class ExecutionContextTest {
|
|||
fun `lookup a shadowed variable`() {
|
||||
val scope = SymbolTable(ExecutionContext.scope)
|
||||
|
||||
scope["shadowed"] = NIL
|
||||
scope["shadowed"] = Nil
|
||||
ExecutionContext.scope["shadowed"] = T
|
||||
ExecutionContext.scope = scope
|
||||
|
||||
assertThat(ExecutionContext.lookupSymbolValue("shadowed")).isEqualTo(NIL)
|
||||
assertThat(ExecutionContext.lookupSymbolValue("shadowed")).isEqualTo(Nil)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -13,8 +13,7 @@ import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
|||
import sexpression.Cons
|
||||
import sexpression.LispString
|
||||
import sexpression.Nil
|
||||
import sexpression.Nil.NIL
|
||||
import sexpression.Symbol.T
|
||||
import sexpression.Symbol.Companion.T
|
||||
import table.FunctionTable.LispFunctionInstantiationException
|
||||
import table.FunctionTable.defineFunction
|
||||
import table.FunctionTable.isAlreadyDefined
|
||||
|
@ -31,11 +30,11 @@ class FunctionTableTest {
|
|||
|
||||
@FunctionNames("BAD")
|
||||
class BadFunction : LispFunction() {
|
||||
override fun call(argumentList: Cons): Nil = NIL
|
||||
override fun call(argumentList: Cons): Nil = Nil
|
||||
}
|
||||
|
||||
class UglyFunction : LispFunction() {
|
||||
override fun call(argumentList: Cons): Nil = NIL
|
||||
override fun call(argumentList: Cons): Nil = Nil
|
||||
}
|
||||
|
||||
private fun createLispFunction() = object : LispFunction() {
|
||||
|
|
|
@ -5,8 +5,8 @@ import org.junit.jupiter.api.BeforeEach
|
|||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import sexpression.Nil.NIL
|
||||
import sexpression.Symbol.T
|
||||
import sexpression.Nil
|
||||
import sexpression.Symbol.Companion.T
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class SymbolTableTest {
|
||||
|
@ -40,9 +40,9 @@ class SymbolTableTest {
|
|||
@Test
|
||||
fun `redefine the value of a symbol`() {
|
||||
symbolTable["symbol"] = T
|
||||
symbolTable["symbol"] = NIL
|
||||
symbolTable["symbol"] = Nil
|
||||
|
||||
assertThat(symbolTable["symbol"]).isEqualTo(NIL)
|
||||
assertThat(symbolTable["symbol"]).isEqualTo(Nil)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -6,7 +6,7 @@ import function.builtin.EVAL.eval
|
|||
import org.assertj.core.api.Assertions.assertThat
|
||||
import parser.LispParser
|
||||
import sexpression.Cons
|
||||
import sexpression.Nil.NIL
|
||||
import sexpression.Nil
|
||||
import sexpression.SExpression
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.IOException
|
||||
|
@ -64,7 +64,7 @@ object TestUtilities {
|
|||
@JvmStatic()
|
||||
fun makeList(vararg expressionList: SExpression): Cons {
|
||||
if (expressionList.isEmpty())
|
||||
return NIL
|
||||
return Nil
|
||||
|
||||
val rest = makeList(*Arrays.copyOfRange(expressionList, 1, expressionList.size))
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package testutil
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import sexpression.Nil.NIL
|
||||
import sexpression.Nil
|
||||
import sexpression.SExpression
|
||||
import sexpression.Symbol.T
|
||||
import sexpression.Symbol.Companion.T
|
||||
|
||||
object TypeAssertions {
|
||||
|
||||
|
@ -24,7 +24,7 @@ object TypeAssertions {
|
|||
|
||||
@JvmStatic()
|
||||
fun assertNil(sExpression: SExpression) {
|
||||
assertThat(sExpression).isEqualTo(NIL)
|
||||
assertThat(sExpression).isEqualTo(Nil)
|
||||
|
||||
assertThat(sExpression.isAtom).isTrue()
|
||||
assertThat(sExpression.isCons).isFalse()
|
||||
|
|
Loading…
Reference in New Issue