Convert sexpressions to kotlin

This commit is contained in:
Mike Cifelli 2018-08-11 08:44:41 -04:00
parent 4c8342a9f7
commit 16118a9a78
68 changed files with 393 additions and 576 deletions

View File

@ -4,6 +4,7 @@ import error.LispException;
import recursion.TailCall; import recursion.TailCall;
import recursion.TailCalls; import recursion.TailCalls;
import sexpression.Cons; import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression; import sexpression.SExpression;
import sexpression.Symbol; import sexpression.Symbol;
import table.ExecutionContext; import table.ExecutionContext;
@ -14,7 +15,6 @@ import java.util.ArrayList;
import static function.builtin.EVAL.eval; import static function.builtin.EVAL.eval;
import static java.text.MessageFormat.format; import static java.text.MessageFormat.format;
import static recursion.TailCalls.done; import static recursion.TailCalls.done;
import static sexpression.Nil.NIL;
public class UserDefinedFunction extends LispFunction { public class UserDefinedFunction extends LispFunction {
@ -136,7 +136,7 @@ public class UserDefinedFunction extends LispFunction {
} }
private SExpression evaluateBody() { private SExpression evaluateBody() {
SExpression lastEvaluation = NIL; SExpression lastEvaluation = Nil.INSTANCE;
for (Cons expression = body; expression.isCons(); expression = (Cons) expression.getRest()) for (Cons expression = body; expression.isCons(); expression = (Cons) expression.getRest())
lastEvaluation = eval(expression.getFirst()); lastEvaluation = eval(expression.getFirst());

View File

@ -6,10 +6,10 @@ import sexpression.AtSignExpression;
import sexpression.BackquoteExpression; import sexpression.BackquoteExpression;
import sexpression.CommaExpression; import sexpression.CommaExpression;
import sexpression.Cons; import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression; import sexpression.SExpression;
import static function.builtin.EVAL.eval; import static function.builtin.EVAL.eval;
import static sexpression.Nil.NIL;
class BackquoteEvaluator { class BackquoteEvaluator {
@ -24,7 +24,7 @@ class BackquoteEvaluator {
this.listValidator = new ArgumentValidator("`|list|"); this.listValidator = new ArgumentValidator("`|list|");
this.atSignValidator = new ArgumentValidator("@|list|"); this.atSignValidator = new ArgumentValidator("@|list|");
this.backTick = backTick; this.backTick = backTick;
this.resolvedList = new Cons(NIL, NIL); this.resolvedList = new Cons(Nil.INSTANCE, Nil.INSTANCE);
this.leader = resolvedList; this.leader = resolvedList;
this.follower = resolvedList; this.follower = resolvedList;
} }
@ -53,7 +53,7 @@ class BackquoteEvaluator {
for (; list.isCons(); list = (Cons) list.getRest()) for (; list.isCons(); list = (Cons) list.getRest())
resolveExpression(list.getFirst()); resolveExpression(list.getFirst());
follower.setRest(NIL); follower.setRest(Nil.INSTANCE);
} }
private void resolveExpression(SExpression expression) { private void resolveExpression(SExpression expression) {
@ -123,7 +123,7 @@ class BackquoteEvaluator {
private void addResolvedExpression(SExpression expression) { private void addResolvedExpression(SExpression expression) {
leader.setFirst(expression); leader.setFirst(expression);
leader.setRest(new Cons(NIL, NIL)); leader.setRest(new Cons(Nil.INSTANCE, Nil.INSTANCE));
follower = leader; follower = leader;
leader = (Cons) leader.getRest(); leader = (Cons) leader.getRest();
} }

View File

@ -8,6 +8,7 @@ import function.builtin.special.RECUR.RecurNotInTailPositionException;
import sexpression.BackquoteExpression; import sexpression.BackquoteExpression;
import sexpression.Cons; import sexpression.Cons;
import sexpression.LambdaExpression; import sexpression.LambdaExpression;
import sexpression.Nil;
import sexpression.SExpression; import sexpression.SExpression;
import sexpression.Symbol; import sexpression.Symbol;
import table.ExecutionContext; import table.ExecutionContext;
@ -16,8 +17,6 @@ import table.FunctionTable;
import static function.builtin.cons.LIST.makeList; import static function.builtin.cons.LIST.makeList;
import static function.builtin.special.Lambda.Lambda; import static function.builtin.special.Lambda.Lambda;
import static java.text.MessageFormat.format; import static java.text.MessageFormat.format;
import static sexpression.Nil.NIL;
import static sexpression.Symbol.T;
@FunctionNames({ "EVAL" }) @FunctionNames({ "EVAL" })
public class EVAL extends LispFunction { public class EVAL extends LispFunction {
@ -67,9 +66,9 @@ public class EVAL extends LispFunction {
public static SExpression lookupSymbol(String symbolName) { public static SExpression lookupSymbol(String symbolName) {
if (symbolName.equals("NIL")) if (symbolName.equals("NIL"))
return NIL; return Nil.INSTANCE;
else if (symbolName.equals("T")) else if (symbolName.equals("T"))
return T; return Symbol.Companion.getT();
else if (symbolName.startsWith(":")) else if (symbolName.startsWith(":"))
return new Symbol(symbolName); return new Symbol(symbolName);
@ -155,7 +154,7 @@ public class EVAL extends LispFunction {
private Cons evaluateArgumentList(Cons arguments) { private Cons evaluateArgumentList(Cons arguments) {
if (arguments.isNull()) if (arguments.isNull())
return NIL; return Nil.INSTANCE;
SExpression first = eval(arguments.getFirst()); SExpression first = eval(arguments.getFirst());
SExpression rest = arguments.getRest(); SExpression rest = arguments.getRest();

View File

@ -5,7 +5,7 @@ import function.ArgumentValidator
import function.FunctionNames import function.FunctionNames
import function.LispFunction import function.LispFunction
import sexpression.Cons import sexpression.Cons
import sexpression.Nil.NIL import sexpression.Nil
import sexpression.SExpression import sexpression.SExpression
@FunctionNames("EXIT") @FunctionNames("EXIT")
@ -21,6 +21,6 @@ class Exit(name: String) : LispFunction() {
argumentValidator.validate(argumentList) argumentValidator.validate(argumentList)
RuntimeEnvironment.terminateSuccessfully() RuntimeEnvironment.terminateSuccessfully()
return NIL return Nil
} }
} }

View File

@ -9,7 +9,9 @@ import function.LispFunction;
import parser.LispParser; import parser.LispParser;
import sexpression.Cons; import sexpression.Cons;
import sexpression.LispString; import sexpression.LispString;
import sexpression.Nil;
import sexpression.SExpression; import sexpression.SExpression;
import sexpression.Symbol;
import util.Path; import util.Path;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -18,8 +20,6 @@ import java.util.Stack;
import static function.builtin.EVAL.eval; import static function.builtin.EVAL.eval;
import static java.text.MessageFormat.format; import static java.text.MessageFormat.format;
import static sexpression.Nil.NIL;
import static sexpression.Symbol.T;
@FunctionNames({ "LOAD" }) @FunctionNames({ "LOAD" })
public class LOAD extends LispFunction { public class LOAD extends LispFunction {
@ -57,7 +57,7 @@ public class LOAD extends LispFunction {
if (parser != null) if (parser != null)
isSuccessful = isSuccessfulEvaluationWithPathPrefix(prefixedFileName, parser); isSuccessful = isSuccessfulEvaluationWithPathPrefix(prefixedFileName, parser);
return isSuccessful ? T : NIL; return isSuccessful ? Symbol.Companion.getT() : Nil.INSTANCE;
} }
private String prefixFileNameIfNecessary(String fileName) { private String prefixFileNameIfNecessary(String fileName) {

View File

@ -4,10 +4,9 @@ import function.ArgumentValidator;
import function.FunctionNames; import function.FunctionNames;
import function.LispFunction; import function.LispFunction;
import sexpression.Cons; import sexpression.Cons;
import sexpression.Nil;
import table.FunctionTable; import table.FunctionTable;
import static sexpression.Nil.NIL;
@FunctionNames({ "APPEND" }) @FunctionNames({ "APPEND" })
public class APPEND extends LispFunction { public class APPEND extends LispFunction {
@ -53,11 +52,11 @@ public class APPEND extends LispFunction {
} }
private Cons copy(Cons list) { private Cons copy(Cons list) {
Cons newList = new Cons(list.getFirst(), NIL); Cons newList = new Cons(list.getFirst(), Nil.INSTANCE);
Cons builder = newList; Cons builder = newList;
for (Cons iterator = (Cons) list.getRest(); iterator.isCons(); iterator = (Cons) iterator.getRest()) { 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(); builder = (Cons) builder.getRest();
} }

View File

@ -4,15 +4,14 @@ import function.ArgumentValidator;
import function.FunctionNames; import function.FunctionNames;
import function.LispFunction; import function.LispFunction;
import sexpression.Cons; import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression; import sexpression.SExpression;
import static sexpression.Nil.NIL;
@FunctionNames({ "LIST" }) @FunctionNames({ "LIST" })
public class LIST extends LispFunction { public class LIST extends LispFunction {
public static Cons makeList(SExpression sexpr) { public static Cons makeList(SExpression sexpr) {
return new Cons(sexpr, NIL); return new Cons(sexpr, Nil.INSTANCE);
} }
private ArgumentValidator argumentValidator; private ArgumentValidator argumentValidator;

View File

@ -6,8 +6,6 @@ import function.LispFunction;
import sexpression.Cons; import sexpression.Cons;
import sexpression.LispNumber; import sexpression.LispNumber;
import static sexpression.LispNumber.ONE;
@FunctionNames({ "*" }) @FunctionNames({ "*" })
public class MULTIPLY extends LispFunction { public class MULTIPLY extends LispFunction {
@ -24,7 +22,7 @@ public class MULTIPLY extends LispFunction {
public LispNumber call(Cons argumentList) { public LispNumber call(Cons argumentList) {
argumentValidator.validate(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) { private LispNumber multiply(LispNumber number1, LispNumber number2) {

View File

@ -6,8 +6,6 @@ import function.LispFunction;
import sexpression.Cons; import sexpression.Cons;
import sexpression.LispNumber; import sexpression.LispNumber;
import static sexpression.LispNumber.ZERO;
@FunctionNames({ "+" }) @FunctionNames({ "+" })
public class PLUS extends LispFunction { public class PLUS extends LispFunction {
@ -24,7 +22,7 @@ public class PLUS extends LispFunction {
public LispNumber call(Cons argumentList) { public LispNumber call(Cons argumentList) {
argumentValidator.validate(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) { private LispNumber add(LispNumber number1, LispNumber number2) {

View File

@ -4,10 +4,9 @@ import function.ArgumentValidator;
import function.FunctionNames; import function.FunctionNames;
import function.LispFunction; import function.LispFunction;
import sexpression.Cons; import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression; import sexpression.SExpression;
import sexpression.Symbol;
import static sexpression.Nil.NIL;
import static sexpression.Symbol.T;
@FunctionNames({ "ATOM", "ATOM?" }) @FunctionNames({ "ATOM", "ATOM?" })
public class ATOM extends LispFunction { public class ATOM extends LispFunction {
@ -24,6 +23,6 @@ public class ATOM extends LispFunction {
argumentValidator.validate(argumentList); argumentValidator.validate(argumentList);
SExpression argument = argumentList.getFirst(); SExpression argument = argumentList.getFirst();
return argument.isAtom() ? T : NIL; return argument.isAtom() ? Symbol.Companion.getT() : Nil.INSTANCE;
} }
} }

View File

@ -4,10 +4,9 @@ import function.ArgumentValidator;
import function.FunctionNames; import function.FunctionNames;
import function.LispFunction; import function.LispFunction;
import sexpression.Cons; import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression; import sexpression.SExpression;
import sexpression.Symbol;
import static sexpression.Nil.NIL;
import static sexpression.Symbol.T;
@FunctionNames({ "EQ", "EQ?" }) @FunctionNames({ "EQ", "EQ?" })
public class EQ extends LispFunction { public class EQ extends LispFunction {
@ -42,7 +41,7 @@ public class EQ extends LispFunction {
} }
private SExpression atomEq(SExpression firstArgument, SExpression secondArgument) { 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) { private boolean isEq(SExpression firstArgument, SExpression secondArgument) {
@ -50,6 +49,6 @@ public class EQ extends LispFunction {
} }
private SExpression listEq(SExpression firstArgument, SExpression secondArgument) { private SExpression listEq(SExpression firstArgument, SExpression secondArgument) {
return (firstArgument == secondArgument) ? T : NIL; return (firstArgument == secondArgument) ? Symbol.Companion.getT() : Nil.INSTANCE;
} }
} }

View File

@ -4,10 +4,9 @@ import function.ArgumentValidator;
import function.FunctionNames; import function.FunctionNames;
import function.LispFunction; import function.LispFunction;
import sexpression.Cons; import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression; import sexpression.SExpression;
import sexpression.Symbol;
import static sexpression.Nil.NIL;
import static sexpression.Symbol.T;
@FunctionNames({ "EQUAL", "EQUAL?" }) @FunctionNames({ "EQUAL", "EQUAL?" })
public class EQUAL extends LispFunction { public class EQUAL extends LispFunction {
@ -35,6 +34,6 @@ public class EQUAL extends LispFunction {
} }
private SExpression equal(SExpression firstArgument, SExpression secondArgument) { private SExpression equal(SExpression firstArgument, SExpression secondArgument) {
return isEqual(firstArgument, secondArgument) ? T : NIL; return isEqual(firstArgument, secondArgument) ? Symbol.Companion.getT() : Nil.INSTANCE;
} }
} }

View File

@ -4,7 +4,9 @@ import function.ArgumentValidator;
import function.FunctionNames; import function.FunctionNames;
import function.LispFunction; import function.LispFunction;
import sexpression.Cons; import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression; import sexpression.SExpression;
import sexpression.Symbol;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -13,8 +15,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import static function.builtin.GENSYM.GENSYM_PREFIX; import static function.builtin.GENSYM.GENSYM_PREFIX;
import static sexpression.Nil.NIL;
import static sexpression.Symbol.T;
@FunctionNames({ "GENSYM-EQUAL", "GENSYM-EQUAL?" }) @FunctionNames({ "GENSYM-EQUAL", "GENSYM-EQUAL?" })
public class GENSYM_EQUAL extends LispFunction { public class GENSYM_EQUAL extends LispFunction {
@ -41,7 +41,7 @@ public class GENSYM_EQUAL extends LispFunction {
String firstEqualized = equalizeGensyms(firstArgument); String firstEqualized = equalizeGensyms(firstArgument);
String secondEqualized = equalizeGensyms(secondArgument); String secondEqualized = equalizeGensyms(secondArgument);
return firstEqualized.equals(secondEqualized) ? T : NIL; return firstEqualized.equals(secondEqualized) ? Symbol.Companion.getT() : Nil.INSTANCE;
} }
private String equalizeGensyms(SExpression expression) { private String equalizeGensyms(SExpression expression) {

View File

@ -4,10 +4,9 @@ import function.ArgumentValidator;
import function.FunctionNames; import function.FunctionNames;
import function.LispFunction; import function.LispFunction;
import sexpression.Cons; import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression; import sexpression.SExpression;
import sexpression.Symbol;
import static sexpression.Nil.NIL;
import static sexpression.Symbol.T;
@FunctionNames({ "LISTP", "LIST?" }) @FunctionNames({ "LISTP", "LIST?" })
public class LISTP extends LispFunction { public class LISTP extends LispFunction {
@ -23,6 +22,6 @@ public class LISTP extends LispFunction {
public SExpression call(Cons argumentList) { public SExpression call(Cons argumentList) {
argumentValidator.validate(argumentList); argumentValidator.validate(argumentList);
return argumentList.getFirst().isList() ? T : NIL; return argumentList.getFirst().isList() ? Symbol.Companion.getT() : Nil.INSTANCE;
} }
} }

View File

@ -4,10 +4,9 @@ import function.ArgumentValidator;
import function.FunctionNames; import function.FunctionNames;
import function.LispFunction; import function.LispFunction;
import sexpression.Cons; import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression; import sexpression.SExpression;
import sexpression.Symbol;
import static sexpression.Nil.NIL;
import static sexpression.Symbol.T;
@FunctionNames({ "NULL", "NULL?" }) @FunctionNames({ "NULL", "NULL?" })
public class NULL extends LispFunction { public class NULL extends LispFunction {
@ -23,6 +22,6 @@ public class NULL extends LispFunction {
public SExpression call(Cons argumentList) { public SExpression call(Cons argumentList) {
argumentValidator.validate(argumentList); argumentValidator.validate(argumentList);
return argumentList.getFirst().isNull() ? T : NIL; return argumentList.getFirst().isNull() ? Symbol.Companion.getT() : Nil.INSTANCE;
} }
} }

View File

@ -6,12 +6,12 @@ import function.LispFunction;
import recursion.TailCall; import recursion.TailCall;
import sexpression.Cons; import sexpression.Cons;
import sexpression.LispNumber; import sexpression.LispNumber;
import sexpression.Nil;
import sexpression.SExpression; import sexpression.SExpression;
import sexpression.Symbol;
import static recursion.TailCalls.done; import static recursion.TailCalls.done;
import static recursion.TailCalls.tailCall; import static recursion.TailCalls.tailCall;
import static sexpression.Nil.NIL;
import static sexpression.Symbol.T;
@FunctionNames({ ">" }) @FunctionNames({ ">" })
public class NUMERIC_GREATER extends LispFunction { public class NUMERIC_GREATER extends LispFunction {
@ -35,7 +35,7 @@ public class NUMERIC_GREATER extends LispFunction {
Cons remainingArguments = (Cons) argumentList.getRest(); Cons remainingArguments = (Cons) argumentList.getRest();
if (remainingArguments.isNull()) if (remainingArguments.isNull())
return done(T); return done(Symbol.Companion.getT());
SExpression firstArgument = argumentList.getFirst(); SExpression firstArgument = argumentList.getFirst();
SExpression secondArgument = remainingArguments.getFirst(); SExpression secondArgument = remainingArguments.getFirst();
@ -43,7 +43,7 @@ public class NUMERIC_GREATER extends LispFunction {
LispNumber number2 = (LispNumber) secondArgument; LispNumber number2 = (LispNumber) secondArgument;
if (!isFirstGreater(number1, number2)) if (!isFirstGreater(number1, number2))
return done(NIL); return done(Nil.INSTANCE);
return tailCall(() -> callTailRecursive(remainingArguments)); return tailCall(() -> callTailRecursive(remainingArguments));
} }

View File

@ -6,12 +6,12 @@ import function.LispFunction;
import recursion.TailCall; import recursion.TailCall;
import sexpression.Cons; import sexpression.Cons;
import sexpression.LispNumber; import sexpression.LispNumber;
import sexpression.Nil;
import sexpression.SExpression; import sexpression.SExpression;
import sexpression.Symbol;
import static recursion.TailCalls.done; import static recursion.TailCalls.done;
import static recursion.TailCalls.tailCall; import static recursion.TailCalls.tailCall;
import static sexpression.Nil.NIL;
import static sexpression.Symbol.T;
@FunctionNames({ "<" }) @FunctionNames({ "<" })
public class NUMERIC_LESS extends LispFunction { public class NUMERIC_LESS extends LispFunction {
@ -35,7 +35,7 @@ public class NUMERIC_LESS extends LispFunction {
Cons remainingArguments = (Cons) argumentList.getRest(); Cons remainingArguments = (Cons) argumentList.getRest();
if (remainingArguments.isNull()) if (remainingArguments.isNull())
return done(T); return done(Symbol.Companion.getT());
SExpression firstArgument = argumentList.getFirst(); SExpression firstArgument = argumentList.getFirst();
SExpression secondArgument = remainingArguments.getFirst(); SExpression secondArgument = remainingArguments.getFirst();
@ -43,7 +43,7 @@ public class NUMERIC_LESS extends LispFunction {
LispNumber number2 = (LispNumber) secondArgument; LispNumber number2 = (LispNumber) secondArgument;
if (!isFirstLesser(number1, number2)) if (!isFirstLesser(number1, number2))
return done(NIL); return done(Nil.INSTANCE);
return tailCall(() -> callTailRecursive(remainingArguments)); return tailCall(() -> callTailRecursive(remainingArguments));
} }

View File

@ -5,9 +5,9 @@ import function.FunctionNames
import function.LispFunction import function.LispFunction
import sexpression.Cons import sexpression.Cons
import sexpression.LispNumber import sexpression.LispNumber
import sexpression.Nil.NIL import sexpression.Nil
import sexpression.SExpression import sexpression.SExpression
import sexpression.Symbol.T import sexpression.Symbol.Companion.T
@FunctionNames("=") @FunctionNames("=")
class NumericEqual(name: String) : LispFunction() { class NumericEqual(name: String) : LispFunction() {
@ -34,6 +34,6 @@ class NumericEqual(name: String) : LispFunction() {
val number1 = argumentList.first as LispNumber val number1 = argumentList.first as LispNumber
val number2 = remainingArguments.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)
} }
} }

View File

@ -6,11 +6,11 @@ import function.LispSpecialFunction;
import recursion.TailCall; import recursion.TailCall;
import sexpression.Cons; import sexpression.Cons;
import sexpression.SExpression; import sexpression.SExpression;
import sexpression.Symbol;
import static function.builtin.EVAL.eval; import static function.builtin.EVAL.eval;
import static recursion.TailCalls.done; import static recursion.TailCalls.done;
import static recursion.TailCalls.tailCall; import static recursion.TailCalls.tailCall;
import static sexpression.Symbol.T;
@FunctionNames({ "AND" }) @FunctionNames({ "AND" })
public class AND extends LispSpecialFunction { public class AND extends LispSpecialFunction {
@ -25,7 +25,7 @@ public class AND extends LispSpecialFunction {
public SExpression call(Cons argumentList) { public SExpression call(Cons argumentList) {
argumentValidator.validate(argumentList); argumentValidator.validate(argumentList);
return callTailRecursive(argumentList, T).invoke(); return callTailRecursive(argumentList, Symbol.Companion.getT()).invoke();
} }
private TailCall<SExpression> callTailRecursive(Cons argumentList, SExpression lastValue) { private TailCall<SExpression> callTailRecursive(Cons argumentList, SExpression lastValue) {

View File

@ -7,13 +7,12 @@ import recursion.TailCall;
import sexpression.Cons; import sexpression.Cons;
import sexpression.Nil; import sexpression.Nil;
import sexpression.SExpression; import sexpression.SExpression;
import sexpression.Symbol;
import static function.builtin.EVAL.eval; import static function.builtin.EVAL.eval;
import static function.builtin.predicate.EQUAL.isEqual; import static function.builtin.predicate.EQUAL.isEqual;
import static recursion.TailCalls.done; import static recursion.TailCalls.done;
import static recursion.TailCalls.tailCall; import static recursion.TailCalls.tailCall;
import static sexpression.Nil.NIL;
import static sexpression.Symbol.T;
@FunctionNames({ "CASE" }) @FunctionNames({ "CASE" })
public class CASE extends LispSpecialFunction { public class CASE extends LispSpecialFunction {
@ -37,7 +36,7 @@ public class CASE extends LispSpecialFunction {
private TailCall<SExpression> callTailRecursive(SExpression key, Cons argumentList) { private TailCall<SExpression> callTailRecursive(SExpression key, Cons argumentList) {
if (argumentList.isNull()) if (argumentList.isNull())
return done(NIL); return done(Nil.INSTANCE);
Cons clause = (Cons) argumentList.getFirst(); Cons clause = (Cons) argumentList.getFirst();
Cons remainingClauses = (Cons) argumentList.getRest(); Cons remainingClauses = (Cons) argumentList.getRest();
@ -55,7 +54,7 @@ public class CASE extends LispSpecialFunction {
else if (keyList.isCons()) else if (keyList.isCons())
return containsMatch(key, keyList); 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) { private boolean containsMatch(SExpression key, SExpression keyList) {
@ -75,7 +74,7 @@ public class CASE extends LispSpecialFunction {
} }
private SExpression evaluateConsequents(SExpression consequentList) { private SExpression evaluateConsequents(SExpression consequentList) {
SExpression lastConsequentValue = NIL; SExpression lastConsequentValue = Nil.INSTANCE;
for (; consequentList.isCons(); consequentList = advanceCons(consequentList)) for (; consequentList.isCons(); consequentList = advanceCons(consequentList))
lastConsequentValue = eval(getFirst(consequentList)); lastConsequentValue = eval(getFirst(consequentList));

View File

@ -11,7 +11,6 @@ import sexpression.SExpression;
import static function.builtin.EVAL.eval; import static function.builtin.EVAL.eval;
import static recursion.TailCalls.done; import static recursion.TailCalls.done;
import static recursion.TailCalls.tailCall; import static recursion.TailCalls.tailCall;
import static sexpression.Nil.NIL;
@FunctionNames({ "COND" }) @FunctionNames({ "COND" })
public class COND extends LispSpecialFunction { public class COND extends LispSpecialFunction {
@ -33,7 +32,7 @@ public class COND extends LispSpecialFunction {
private TailCall<SExpression> callTailRecursive(Cons argumentList) { private TailCall<SExpression> callTailRecursive(Cons argumentList) {
if (argumentList.isNull()) if (argumentList.isNull())
return done(NIL); return done(Nil.INSTANCE);
Cons clause = (Cons) argumentList.getFirst(); Cons clause = (Cons) argumentList.getFirst();
Cons remainingClauses = (Cons) argumentList.getRest(); Cons remainingClauses = (Cons) argumentList.getRest();
@ -46,7 +45,7 @@ public class COND extends LispSpecialFunction {
} }
private boolean isTestSuccessful(SExpression test) { private boolean isTestSuccessful(SExpression test) {
return test != NIL; return test != Nil.INSTANCE;
} }
private SExpression evaluateConsequents(SExpression consequentList, SExpression test) { private SExpression evaluateConsequents(SExpression consequentList, SExpression test) {

View File

@ -4,13 +4,13 @@ import function.ArgumentValidator;
import function.FunctionNames; import function.FunctionNames;
import function.LispSpecialFunction; import function.LispSpecialFunction;
import sexpression.Cons; import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression; import sexpression.SExpression;
import sexpression.Symbol; import sexpression.Symbol;
import table.ExecutionContext; import table.ExecutionContext;
import table.SymbolTable; import table.SymbolTable;
import static function.builtin.EVAL.eval; import static function.builtin.EVAL.eval;
import static sexpression.Nil.NIL;
@FunctionNames({ "LET" }) @FunctionNames({ "LET" })
public class LET extends LispSpecialFunction { public class LET extends LispSpecialFunction {
@ -79,7 +79,7 @@ public class LET extends LispSpecialFunction {
} }
private SExpression evaluateBody(Cons body) { private SExpression evaluateBody(Cons body) {
SExpression lastEvaluation = NIL; SExpression lastEvaluation = Nil.INSTANCE;
for (; body.isCons(); body = (Cons) body.getRest()) for (; body.isCons(); body = (Cons) body.getRest())
lastEvaluation = eval(body.getFirst()); lastEvaluation = eval(body.getFirst());

View File

@ -5,12 +5,12 @@ import function.FunctionNames;
import function.LispSpecialFunction; import function.LispSpecialFunction;
import recursion.TailCall; import recursion.TailCall;
import sexpression.Cons; import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression; import sexpression.SExpression;
import static function.builtin.EVAL.eval; import static function.builtin.EVAL.eval;
import static recursion.TailCalls.done; import static recursion.TailCalls.done;
import static recursion.TailCalls.tailCall; import static recursion.TailCalls.tailCall;
import static sexpression.Nil.NIL;
@FunctionNames({ "PROGN", "BEGIN" }) @FunctionNames({ "PROGN", "BEGIN" })
public class PROGN extends LispSpecialFunction { public class PROGN extends LispSpecialFunction {
@ -25,7 +25,7 @@ public class PROGN extends LispSpecialFunction {
public SExpression call(Cons argumentList) { public SExpression call(Cons argumentList) {
argumentValidator.validate(argumentList); argumentValidator.validate(argumentList);
return callTailRecursive(argumentList, NIL).invoke(); return callTailRecursive(argumentList, Nil.INSTANCE).invoke();
} }
private TailCall<SExpression> callTailRecursive(Cons argumentList, SExpression lastValue) { private TailCall<SExpression> callTailRecursive(Cons argumentList, SExpression lastValue) {

View File

@ -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;
}
}

View File

@ -0,0 +1,9 @@
package sexpression
class AtSignExpression(val expression: SExpression) : SExpression() {
override val isAtSign: Boolean
get() = true
override fun toString() = "@$expression"
}

View File

@ -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;
}
}

View File

@ -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
}

View File

@ -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;
}
}

View File

@ -0,0 +1,9 @@
package sexpression
class BackquoteExpression(val expression: SExpression) : SExpression() {
override val isBackquote: Boolean
get() = true
override fun toString() = "`$expression"
}

View File

@ -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;
}
}

View File

@ -0,0 +1,9 @@
package sexpression
class CommaExpression(val expression: SExpression) : SExpression() {
override val isComma: Boolean
get() = true
override fun toString() = ",$expression"
}

View File

@ -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());
}
}

View File

@ -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())
}
}

View File

@ -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();
}

View File

@ -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)

View File

@ -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();
}
}

View File

@ -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()
}

View File

@ -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);
}
}
}

View File

@ -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)
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,8 @@
package sexpression
@DisplayName("string")
class LispString(text: String) : Atom(text) {
override val isString: Boolean
get() = true
}

View File

@ -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";
}
}

View File

@ -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"
}

View File

@ -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;
}
}

View File

@ -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
}

View File

@ -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;
}
}

View File

@ -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")
}
}

View File

@ -2,7 +2,7 @@ package table
import function.LispFunction import function.LispFunction
import sexpression.Cons import sexpression.Cons
import sexpression.Nil.NIL import sexpression.Nil
import sexpression.SExpression import sexpression.SExpression
import table.SymbolTable.NullSymbolTable import table.SymbolTable.NullSymbolTable
import java.util.Stack import java.util.Stack
@ -39,7 +39,7 @@ object ExecutionContext {
} }
fun toList(): Cons { fun toList(): Cons {
var symbols: Cons = NIL var symbols: Cons = Nil
for (table in scope) for (table in scope)
symbols = Cons(table.toList(), symbols) symbols = Cons(table.toList(), symbols)

View File

@ -3,7 +3,7 @@ package table
import function.builtin.cons.APPEND.append import function.builtin.cons.APPEND.append
import function.builtin.cons.LIST.makeList import function.builtin.cons.LIST.makeList
import sexpression.Cons import sexpression.Cons
import sexpression.Nil.NIL import sexpression.Nil
import sexpression.SExpression import sexpression.SExpression
import sexpression.Symbol import sexpression.Symbol
import kotlin.collections.Map.Entry import kotlin.collections.Map.Entry
@ -23,7 +23,7 @@ open class SymbolTable @JvmOverloads constructor(open val parent: SymbolTable? =
fun isGlobal() = parent === NullSymbolTable fun isGlobal() = parent === NullSymbolTable
fun toList(): Cons { fun toList(): Cons {
var context: Cons = NIL var context: Cons = Nil
for (binding in table.toSortedMap().entries) for (binding in table.toSortedMap().entries)
context = append(context, makeList(makeSymbolValuePair(binding))) context = append(context, makeList(makeSymbolValuePair(binding)))

View File

@ -2,7 +2,7 @@ package token
import file.FilePosition import file.FilePosition
import sexpression.Cons import sexpression.Cons
import sexpression.Nil.NIL import sexpression.Nil
import sexpression.SExpression import sexpression.SExpression
import sexpression.Symbol import sexpression.Symbol
@ -12,6 +12,6 @@ class QuoteMark(text: String, position: FilePosition) : Token(text, position) {
val nextToken = getNextToken() val nextToken = getNextToken()
val argument = nextToken.parseSExpression(getNextToken) val argument = nextToken.parseSExpression(getNextToken)
return Cons(Symbol.createQuote(), Cons(argument, NIL)) return Cons(Symbol.createQuote(), Cons(argument, Nil))
} }
} }

View File

@ -5,7 +5,7 @@ import file.FilePosition
import recursion.TailCall import recursion.TailCall
import recursion.TailCalls.done import recursion.TailCalls.done
import sexpression.Cons import sexpression.Cons
import sexpression.Nil.NIL import sexpression.Nil
import sexpression.SExpression import sexpression.SExpression
class RightParenthesis(text: String, position: FilePosition) : Token(text, position) { 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> { override fun parseListTail(getNextToken: () -> Token): TailCall<Cons> {
return done(NIL) return done(Nil)
} }
override fun parseListTailRecursive(start: Cons, end: Cons, getNextToken: () -> Token): TailCall<Cons> { override fun parseListTailRecursive(start: Cons, end: Cons, getNextToken: () -> Token): TailCall<Cons> {

View File

@ -4,7 +4,7 @@ import file.FilePosition
import recursion.TailCall import recursion.TailCall
import recursion.TailCalls.tailCall import recursion.TailCalls.tailCall
import sexpression.Cons import sexpression.Cons
import sexpression.Nil.NIL import sexpression.Nil
import sexpression.SExpression import sexpression.SExpression
abstract class Token(val text: String, val position: FilePosition) { 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 abstract fun parseSExpression(getNextToken: () -> Token): SExpression
open fun parseListTail(getNextToken: () -> Token): TailCall<Cons> { open fun parseListTail(getNextToken: () -> Token): TailCall<Cons> {
val firstCons = Cons(parseSExpression(getNextToken), NIL) val firstCons = Cons(parseSExpression(getNextToken), Nil)
val next = getNextToken() val next = getNextToken()
return tailCall { next.parseListTailRecursive(firstCons, firstCons, getNextToken) } return tailCall { next.parseListTailRecursive(firstCons, firstCons, getNextToken) }
} }
protected open fun parseListTailRecursive(start: Cons, end: Cons, getNextToken: () -> Token): TailCall<Cons> { 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() val next = getNextToken()
end.rest = newEnd end.rest = newEnd

View File

@ -4,12 +4,10 @@
(let ((arguments (gensym))) (let ((arguments (gensym)))
`(lambda (&rest, arguments) `(lambda (&rest, arguments)
(case (first ,arguments) (case (first, arguments), @(mapcar
,@(mapcar (lambda (method))
(lambda (method) `(, (first method))
`(,(first method) (apply (lambda, @(rest method)), (if (equal t (first method)))
(apply (lambda ,@(rest method))
,(if (equal t (first method))
arguments arguments
`(rest ,arguments))))) `(rest, arguments))
methods))))) methods)))))

View File

@ -16,18 +16,16 @@ import static error.Severity.ERROR;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static sexpression.Nil.NIL;
import static sexpression.Symbol.T;
public class ArgumentValidatorTest { public class ArgumentValidatorTest {
private ArgumentValidator validator; private ArgumentValidator validator;
private Cons makeArgumentListOfSize(int size) { private Cons makeArgumentListOfSize(int size) {
Cons argumentList = NIL; Cons argumentList = Nil.INSTANCE;
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)
argumentList = new Cons(NIL, argumentList); argumentList = new Cons(Nil.INSTANCE, argumentList);
return argumentList; return argumentList;
} }
@ -84,7 +82,7 @@ public class ArgumentValidatorTest {
@Test @Test
public void tooManyArgumentsException_HasCorrectAttributes() { public void tooManyArgumentsException_HasCorrectAttributes() {
TooManyArgumentsException e = new TooManyArgumentsException("TEST", NIL); TooManyArgumentsException e = new TooManyArgumentsException("TEST", Nil.INSTANCE);
assertEquals(ERROR, e.getSeverity()); assertEquals(ERROR, e.getSeverity());
assertNotNull(e.getMessage()); assertNotNull(e.getMessage());
@ -93,7 +91,7 @@ public class ArgumentValidatorTest {
@Test @Test
public void tooFewArgumentsException_HasCorrectAttributes() { public void tooFewArgumentsException_HasCorrectAttributes() {
TooFewArgumentsException e = new TooFewArgumentsException("TEST", NIL); TooFewArgumentsException e = new TooFewArgumentsException("TEST", Nil.INSTANCE);
assertEquals(ERROR, e.getSeverity()); assertEquals(ERROR, e.getSeverity());
assertNotNull(e.getMessage()); assertNotNull(e.getMessage());
@ -102,7 +100,7 @@ public class ArgumentValidatorTest {
@Test @Test
public void badArgumentTypeException_HasCorrectAttributes() { 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()); assertEquals(ERROR, e.getSeverity());
assertNotNull(e.getMessage()); assertNotNull(e.getMessage());
@ -123,7 +121,7 @@ public class ArgumentValidatorTest {
@Test @Test
public void correctFirstAndRestArgumentTypes_DoesNotThrowException() { 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.setFirstArgumentExpectedType(Symbol.class);
validator.setTrailingArgumentExpectedType(Cons.class); validator.setTrailingArgumentExpectedType(Cons.class);
@ -132,7 +130,7 @@ public class ArgumentValidatorTest {
@Test(expected = BadArgumentTypeException.class) @Test(expected = BadArgumentTypeException.class)
public void badFirstArgumentType_ThrowsException() { 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.setFirstArgumentExpectedType(Cons.class);
validator.setTrailingArgumentExpectedType(Cons.class); validator.setTrailingArgumentExpectedType(Cons.class);
@ -141,7 +139,7 @@ public class ArgumentValidatorTest {
@Test(expected = BadArgumentTypeException.class) @Test(expected = BadArgumentTypeException.class)
public void badTrailingArgumentType_ThrowsException() { 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.setFirstArgumentExpectedType(Symbol.class);
validator.setTrailingArgumentExpectedType(Symbol.class); validator.setTrailingArgumentExpectedType(Symbol.class);
@ -150,7 +148,7 @@ public class ArgumentValidatorTest {
@Test @Test
public void expectedTypeWithNoDisplayName_DoesNotCauseNPE() { 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() {}; SExpression withoutDisplayName = new SExpression() {};
validator.setEveryArgumentExpectedType(withoutDisplayName.getClass()); validator.setEveryArgumentExpectedType(withoutDisplayName.getClass());
@ -165,21 +163,22 @@ public class ArgumentValidatorTest {
@Test(expected = DottedArgumentListException.class) @Test(expected = DottedArgumentListException.class)
public void givenDottedArgumentList_ThrowsException() { public void givenDottedArgumentList_ThrowsException() {
Cons argumentList = new Cons(T, T); Cons argumentList = new Cons(Symbol.Companion.getT(), Symbol.Companion.getT());
validator.validate(argumentList); validator.validate(argumentList);
} }
@Test(expected = DottedArgumentListException.class) @Test(expected = DottedArgumentListException.class)
public void givenLargeDottedArgumentList_ThrowsException() { 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); validator.validate(argumentList);
} }
@Test @Test
public void dottedArgumentListException_HasCorrectAttributes() { public void dottedArgumentListException_HasCorrectAttributes() {
DottedArgumentListException e = new DottedArgumentListException("TEST", NIL); DottedArgumentListException e = new DottedArgumentListException("TEST", Nil.INSTANCE);
assertEquals(ERROR, e.getSeverity()); assertEquals(ERROR, e.getSeverity());
assertNotNull(e.getMessage()); assertNotNull(e.getMessage());
@ -189,36 +188,36 @@ public class ArgumentValidatorTest {
@Test @Test
public void excludedFirstArgumentType_DoesNotAffectTrailingArguments() { public void excludedFirstArgumentType_DoesNotAffectTrailingArguments() {
validator.setFirstArgumentExcludedType(Nil.class); 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 @Test
public void excludedTrailingArgumentType_DoesNotAffectFirstArgument() { public void excludedTrailingArgumentType_DoesNotAffectFirstArgument() {
validator.setTrailingArgumentExcludedType(Nil.class); 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) @Test(expected = BadArgumentTypeException.class)
public void excludedFirstArgumentType_ThrowsException() { public void excludedFirstArgumentType_ThrowsException() {
validator.setFirstArgumentExcludedType(Nil.class); 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) @Test(expected = BadArgumentTypeException.class)
public void excludedTrailingArgumentType_ThrowsException() { public void excludedTrailingArgumentType_ThrowsException() {
validator.setTrailingArgumentExcludedType(Nil.class); 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) @Test(expected = BadArgumentTypeException.class)
public void excludedArgumentType_ThrowsExceptionOnFirstArgument() { public void excludedArgumentType_ThrowsExceptionOnFirstArgument() {
validator.setEveryArgumentExcludedType(Nil.class); 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) @Test(expected = BadArgumentTypeException.class)
public void excludedArgumentType_ThrowsExceptionOnTrailingArgument() { public void excludedArgumentType_ThrowsExceptionOnTrailingArgument() {
validator.setEveryArgumentExcludedType(Nil.class); 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)));
} }
} }

View File

@ -7,13 +7,13 @@ import function.UserDefinedFunction.IllegalKeywordRestPositionException;
import org.junit.Test; import org.junit.Test;
import sexpression.Cons; import sexpression.Cons;
import sexpression.LispNumber; import sexpression.LispNumber;
import sexpression.Nil;
import sexpression.SExpression; import sexpression.SExpression;
import sexpression.Symbol; import sexpression.Symbol;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static sexpression.Nil.NIL;
import static testutil.TestUtilities.assertSExpressionsMatch; import static testutil.TestUtilities.assertSExpressionsMatch;
public class UserDefinedFunctionTest { public class UserDefinedFunctionTest {
@ -21,24 +21,27 @@ public class UserDefinedFunctionTest {
private static final String FUNCTION_NAME = "TEST"; private static final String FUNCTION_NAME = "TEST";
private UserDefinedFunction createNoArgumentFunctionThatReturnsNil() { 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() { 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 @Test
public void nilFunctionCall() { public void nilFunctionCall() {
UserDefinedFunction function = createNoArgumentFunctionThatReturnsNil(); UserDefinedFunction function = createNoArgumentFunctionThatReturnsNil();
assertEquals(NIL, function.call(NIL)); assertEquals(Nil.INSTANCE, function.call(Nil.INSTANCE));
} }
@Test @Test
public void nilFunctionToString() { public void nilFunctionToString() {
UserDefinedFunction function = createNoArgumentFunctionThatReturnsNil(); 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()); assertSExpressionsMatch(expected, function.getLambdaExpression());
} }
@ -47,7 +50,7 @@ public class UserDefinedFunctionTest {
public void oneArgumentFunction_ReturnsCorrectValue() { public void oneArgumentFunction_ReturnsCorrectValue() {
UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument(); UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument();
SExpression argument = new LispNumber("23"); SExpression argument = new LispNumber("23");
Cons argumentList = new Cons(argument, NIL); Cons argumentList = new Cons(argument, Nil.INSTANCE);
assertSExpressionsMatch(argument, function.call(argumentList)); assertSExpressionsMatch(argument, function.call(argumentList));
} }
@ -56,7 +59,7 @@ public class UserDefinedFunctionTest {
public void oneArgumentFunction_ThrowsExceptionWithTooManyArguments() { public void oneArgumentFunction_ThrowsExceptionWithTooManyArguments() {
UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument(); UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument();
SExpression argument = new LispNumber("23"); 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); function.call(argumentList);
} }
@ -65,12 +68,13 @@ public class UserDefinedFunctionTest {
public void oneArgumentFunction_ThrowsExceptionWithTooFewArguments() { public void oneArgumentFunction_ThrowsExceptionWithTooFewArguments() {
UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument(); UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument();
function.call(NIL); function.call(Nil.INSTANCE);
} }
@Test @Test
public void illegalKeywordRestPositionException_HasCorrectAttributes() { public void illegalKeywordRestPositionException_HasCorrectAttributes() {
IllegalKeywordRestPositionException e = new IllegalKeywordRestPositionException(FUNCTION_NAME, NIL); IllegalKeywordRestPositionException e = new IllegalKeywordRestPositionException(FUNCTION_NAME,
Nil.INSTANCE);
assertNotNull(e.getMessage()); assertNotNull(e.getMessage());
assertTrue(e.getMessage().length() > 0); assertTrue(e.getMessage().length() > 0);

View File

@ -12,11 +12,10 @@ import sexpression.CommaExpression;
import sexpression.Cons; import sexpression.Cons;
import sexpression.LispNumber; import sexpression.LispNumber;
import sexpression.LispString; import sexpression.LispString;
import sexpression.Nil;
import sexpression.SExpression; import sexpression.SExpression;
import sexpression.Symbol; import sexpression.Symbol;
import static sexpression.Nil.NIL;
import static sexpression.Symbol.T;
import static testutil.TestUtilities.assertIsErrorWithMessage; import static testutil.TestUtilities.assertIsErrorWithMessage;
import static testutil.TestUtilities.assertSExpressionsMatch; import static testutil.TestUtilities.assertSExpressionsMatch;
import static testutil.TestUtilities.makeList; import static testutil.TestUtilities.makeList;
@ -29,9 +28,9 @@ public class BackquoteEvaluatorTest {
@Test @Test
public void evaluateNil() { public void evaluateNil() {
BackquoteEvaluator evaluator = createBackquoteEvaluator(NIL); BackquoteEvaluator evaluator = createBackquoteEvaluator(Nil.INSTANCE);
assertSExpressionsMatch(NIL, evaluator.evaluate()); assertSExpressionsMatch(Nil.INSTANCE, evaluator.evaluate());
} }
@Test @Test
@ -155,14 +154,17 @@ public class BackquoteEvaluatorTest {
@Test(expected = DottedArgumentListException.class) @Test(expected = DottedArgumentListException.class)
public void evaluateDottedList() { public void evaluateDottedList() {
BackquoteEvaluator evaluator = createBackquoteEvaluator(new Cons(T, T)); BackquoteEvaluator evaluator =
createBackquoteEvaluator(new Cons(Symbol.Companion.getT(), Symbol.Companion.getT()));
evaluator.evaluate(); evaluator.evaluate();
} }
@Test(expected = DottedArgumentListException.class) @Test(expected = DottedArgumentListException.class)
public void atSignWithDottedList() { 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); BackquoteEvaluator evaluator = createBackquoteEvaluator(input);
evaluator.evaluate(); evaluator.evaluate();

View File

@ -10,12 +10,12 @@ import function.builtin.EVAL.UnmatchedAtSignException;
import function.builtin.EVAL.UnmatchedCommaException; import function.builtin.EVAL.UnmatchedCommaException;
import function.builtin.special.RECUR.RecurNotInTailPositionException; import function.builtin.special.RECUR.RecurNotInTailPositionException;
import org.junit.Test; import org.junit.Test;
import sexpression.Nil;
import testutil.SymbolAndFunctionCleaner; import testutil.SymbolAndFunctionCleaner;
import static function.builtin.EVAL.lookupSymbol; import static function.builtin.EVAL.lookupSymbol;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static sexpression.Nil.NIL;
import static testutil.TestUtilities.assertIsErrorWithMessage; import static testutil.TestUtilities.assertIsErrorWithMessage;
import static testutil.TestUtilities.assertSExpressionsMatch; import static testutil.TestUtilities.assertSExpressionsMatch;
import static testutil.TestUtilities.evaluateString; import static testutil.TestUtilities.evaluateString;
@ -100,12 +100,12 @@ public class EVALTest extends SymbolAndFunctionCleaner {
@Test @Test
public void undefinedFunctionException_HasCorrectAttributes() { public void undefinedFunctionException_HasCorrectAttributes() {
assertIsErrorWithMessage(new UndefinedFunctionException(NIL)); assertIsErrorWithMessage(new UndefinedFunctionException(Nil.INSTANCE));
} }
@Test @Test
public void undefinedSymbolException_HasCorrectAttributes() { public void undefinedSymbolException_HasCorrectAttributes() {
assertIsErrorWithMessage(new UndefinedSymbolException(NIL)); assertIsErrorWithMessage(new UndefinedSymbolException(Nil.INSTANCE));
} }
@Test(expected = UnmatchedCommaException.class) @Test(expected = UnmatchedCommaException.class)

View File

@ -5,13 +5,13 @@ import function.ArgumentValidator.TooFewArgumentsException;
import function.ArgumentValidator.TooManyArgumentsException; import function.ArgumentValidator.TooManyArgumentsException;
import function.builtin.SYMBOL_FUNCTION.UndefinedSymbolFunctionException; import function.builtin.SYMBOL_FUNCTION.UndefinedSymbolFunctionException;
import org.junit.Test; import org.junit.Test;
import sexpression.Nil;
import testutil.SymbolAndFunctionCleaner; import testutil.SymbolAndFunctionCleaner;
import static error.Severity.ERROR; import static error.Severity.ERROR;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static sexpression.Nil.NIL;
import static testutil.TestUtilities.evaluateString; import static testutil.TestUtilities.evaluateString;
public class SYMBOL_FUNCTIONTest extends SymbolAndFunctionCleaner { public class SYMBOL_FUNCTIONTest extends SymbolAndFunctionCleaner {
@ -63,7 +63,7 @@ public class SYMBOL_FUNCTIONTest extends SymbolAndFunctionCleaner {
@Test @Test
public void undefinedSymbolFunctionException_HasCorrectAttributes() { public void undefinedSymbolFunctionException_HasCorrectAttributes() {
UndefinedSymbolFunctionException e = new UndefinedSymbolFunctionException(NIL); UndefinedSymbolFunctionException e = new UndefinedSymbolFunctionException(Nil.INSTANCE);
assertEquals(ERROR, e.getSeverity()); assertEquals(ERROR, e.getSeverity());
assertNotNull(e.getMessage()); assertNotNull(e.getMessage());

View File

@ -8,9 +8,9 @@ import function.builtin.EVAL.UndefinedSymbolException;
import org.junit.Test; import org.junit.Test;
import sexpression.Cons; import sexpression.Cons;
import sexpression.LispNumber; import sexpression.LispNumber;
import sexpression.Nil;
import testutil.SymbolAndFunctionCleaner; import testutil.SymbolAndFunctionCleaner;
import static sexpression.Nil.NIL;
import static testutil.TestUtilities.assertSExpressionsMatch; import static testutil.TestUtilities.assertSExpressionsMatch;
import static testutil.TestUtilities.evaluateString; import static testutil.TestUtilities.evaluateString;
@ -27,14 +27,14 @@ public class LETTest extends SymbolAndFunctionCleaner {
public void emptyLet_ReturnsNil() { public void emptyLet_ReturnsNil() {
String input = "(let ())"; String input = "(let ())";
assertSExpressionsMatch(NIL, evaluateString(input)); assertSExpressionsMatch(Nil.INSTANCE, evaluateString(input));
} }
@Test @Test
public void letWithSymbolsOnly_SetsValuesToNil() { public void letWithSymbolsOnly_SetsValuesToNil() {
String input = "(let ((x) (y)) (list x y))"; 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 @Test

View File

@ -8,9 +8,9 @@ import function.builtin.EVAL.UndefinedSymbolException;
import org.junit.Test; import org.junit.Test;
import sexpression.Cons; import sexpression.Cons;
import sexpression.LispNumber; import sexpression.LispNumber;
import sexpression.Nil;
import testutil.SymbolAndFunctionCleaner; import testutil.SymbolAndFunctionCleaner;
import static sexpression.Nil.NIL;
import static testutil.TestUtilities.assertSExpressionsMatch; import static testutil.TestUtilities.assertSExpressionsMatch;
import static testutil.TestUtilities.evaluateString; import static testutil.TestUtilities.evaluateString;
@ -27,14 +27,14 @@ public class LET_STARTest extends SymbolAndFunctionCleaner {
public void emptyLet_ReturnsNil() { public void emptyLet_ReturnsNil() {
String input = "(let* ())"; String input = "(let* ())";
assertSExpressionsMatch(NIL, evaluateString(input)); assertSExpressionsMatch(Nil.INSTANCE, evaluateString(input));
} }
@Test @Test
public void letStarWithSymbolsOnly_SetsValuesToNil() { public void letStarWithSymbolsOnly_SetsValuesToNil() {
String input = "(let* ((x) (y)) (list x y))"; 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 @Test

View File

@ -12,10 +12,10 @@ import org.junit.jupiter.api.Assertions.assertThrows
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import sexpression.Cons import sexpression.Cons
import sexpression.LispNumber import sexpression.LispNumber
import sexpression.LispNumber.ONE import sexpression.LispNumber.Companion.ONE
import sexpression.Nil.NIL import sexpression.Nil
import sexpression.Symbol import sexpression.Symbol
import sexpression.Symbol.T import sexpression.Symbol.Companion.T
import testutil.SymbolAndFunctionCleaner import testutil.SymbolAndFunctionCleaner
import testutil.TestUtilities.assertSExpressionsMatch import testutil.TestUtilities.assertSExpressionsMatch
import testutil.TestUtilities.evaluateString import testutil.TestUtilities.evaluateString
@ -46,7 +46,7 @@ class LambdaTest : SymbolAndFunctionCleaner() {
@Test @Test
fun `lambda expression is a lambda expression`() { 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() assertThat(isLambdaExpression(lambdaExpression)).isTrue()
} }
@ -58,7 +58,7 @@ class LambdaTest : SymbolAndFunctionCleaner() {
@Test @Test
fun `create lambda expression`() { 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) assertSExpressionsMatch(parseString("(:LAMBDA () ())"), createFunction(lambdaExpression).lambdaExpression)
} }
@ -79,7 +79,7 @@ class LambdaTest : SymbolAndFunctionCleaner() {
@Test @Test
fun `create function with dotted argument list`() { 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) } assertThrows(DottedArgumentListException::class.java) { createFunction(lambdaExpression) }
} }

View File

@ -11,7 +11,6 @@ import static error.Severity.ERROR;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static sexpression.Nil.NIL;
import static testutil.TestUtilities.assertSExpressionsMatch; import static testutil.TestUtilities.assertSExpressionsMatch;
import static testutil.TestUtilities.makeList; import static testutil.TestUtilities.makeList;
@ -25,7 +24,7 @@ public class SExpressionTest {
public void nil_ToString() { public void nil_ToString() {
String input = "NIL"; String input = "NIL";
assertSExpressionMatchesString(input, NIL); assertSExpressionMatchesString(input, Nil.INSTANCE);
} }
@Test @Test
@ -83,7 +82,8 @@ public class SExpressionTest {
@Test @Test
public void lambdaExpression_ToString() { public void lambdaExpression_ToString() {
String expected = "(LAMBDA)"; 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); assertSExpressionMatchesString(expected, lambda);
} }
@ -91,7 +91,8 @@ public class SExpressionTest {
@Test @Test
public void lambdaExpression_GetLambdaExpression() { public void lambdaExpression_GetLambdaExpression() {
String expected = "(LAMBDA)"; 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()); assertSExpressionMatchesString(expected, lambda.getLambdaExpression());
} }
@ -99,7 +100,7 @@ public class SExpressionTest {
@Test @Test
public void lambdaExpression_GetFunction() { public void lambdaExpression_GetFunction() {
String expected = "(LAMBDA)"; 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); LambdaExpression lambda = new LambdaExpression(makeList(new Symbol("lambda")), function);
assertEquals(function, lambda.getFunction()); assertEquals(function, lambda.getFunction());
@ -107,28 +108,28 @@ public class SExpressionTest {
@Test @Test
public void firstOfNilIsNil() { public void firstOfNilIsNil() {
assertEquals(NIL, NIL.getFirst()); assertEquals(Nil.INSTANCE, Nil.INSTANCE.getFirst());
} }
@Test @Test
public void restOfNilIsNil() { public void restOfNilIsNil() {
assertEquals(NIL, NIL.getRest()); assertEquals(Nil.INSTANCE, Nil.INSTANCE.getRest());
} }
@Test @Test
public void afterSettingFirstOfNil_ShouldStillBeNil() { public void afterSettingFirstOfNil_ShouldStillBeNil() {
Cons nil = NIL; Cons nil = Nil.INSTANCE;
nil.setFirst(new LispNumber("2")); nil.setFirst(new LispNumber("2"));
assertEquals(NIL, nil.getFirst()); assertEquals(Nil.INSTANCE, nil.getFirst());
} }
@Test @Test
public void afterSettingRestOfNil_ShouldStillBeNil() { public void afterSettingRestOfNil_ShouldStillBeNil() {
Cons nil = NIL; Cons nil = Nil.INSTANCE;
nil.setRest(new LispNumber("2")); nil.setRest(new LispNumber("2"));
assertEquals(NIL, nil.getRest()); assertEquals(Nil.INSTANCE, nil.getRest());
} }
@Test @Test
@ -159,8 +160,8 @@ public class SExpressionTest {
@Test @Test
public void lispNumberConstants() { public void lispNumberConstants() {
assertEquals(BigInteger.ZERO, LispNumber.ZERO.getValue()); assertEquals(BigInteger.ZERO, LispNumber.Companion.getZERO().getValue());
assertEquals(BigInteger.ONE, LispNumber.ONE.getValue()); assertEquals(BigInteger.ONE, LispNumber.Companion.getONE().getValue());
} }
@Test @Test

View File

@ -6,8 +6,8 @@ import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
import sexpression.Nil.NIL import sexpression.Nil
import sexpression.Symbol.T import sexpression.Symbol.Companion.T
import table.SymbolTable.NullSymbolTable import table.SymbolTable.NullSymbolTable
@TestInstance(PER_CLASS) @TestInstance(PER_CLASS)
@ -75,11 +75,11 @@ class ExecutionContextTest {
fun `lookup a shadowed variable`() { fun `lookup a shadowed variable`() {
val scope = SymbolTable(ExecutionContext.scope) val scope = SymbolTable(ExecutionContext.scope)
scope["shadowed"] = NIL scope["shadowed"] = Nil
ExecutionContext.scope["shadowed"] = T ExecutionContext.scope["shadowed"] = T
ExecutionContext.scope = scope ExecutionContext.scope = scope
assertThat(ExecutionContext.lookupSymbolValue("shadowed")).isEqualTo(NIL) assertThat(ExecutionContext.lookupSymbolValue("shadowed")).isEqualTo(Nil)
} }
@Test @Test

View File

@ -13,8 +13,7 @@ import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
import sexpression.Cons import sexpression.Cons
import sexpression.LispString import sexpression.LispString
import sexpression.Nil import sexpression.Nil
import sexpression.Nil.NIL import sexpression.Symbol.Companion.T
import sexpression.Symbol.T
import table.FunctionTable.LispFunctionInstantiationException import table.FunctionTable.LispFunctionInstantiationException
import table.FunctionTable.defineFunction import table.FunctionTable.defineFunction
import table.FunctionTable.isAlreadyDefined import table.FunctionTable.isAlreadyDefined
@ -31,11 +30,11 @@ class FunctionTableTest {
@FunctionNames("BAD") @FunctionNames("BAD")
class BadFunction : LispFunction() { class BadFunction : LispFunction() {
override fun call(argumentList: Cons): Nil = NIL override fun call(argumentList: Cons): Nil = Nil
} }
class UglyFunction : LispFunction() { class UglyFunction : LispFunction() {
override fun call(argumentList: Cons): Nil = NIL override fun call(argumentList: Cons): Nil = Nil
} }
private fun createLispFunction() = object : LispFunction() { private fun createLispFunction() = object : LispFunction() {

View File

@ -5,8 +5,8 @@ import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
import sexpression.Nil.NIL import sexpression.Nil
import sexpression.Symbol.T import sexpression.Symbol.Companion.T
@TestInstance(PER_CLASS) @TestInstance(PER_CLASS)
class SymbolTableTest { class SymbolTableTest {
@ -40,9 +40,9 @@ class SymbolTableTest {
@Test @Test
fun `redefine the value of a symbol`() { fun `redefine the value of a symbol`() {
symbolTable["symbol"] = T symbolTable["symbol"] = T
symbolTable["symbol"] = NIL symbolTable["symbol"] = Nil
assertThat(symbolTable["symbol"]).isEqualTo(NIL) assertThat(symbolTable["symbol"]).isEqualTo(Nil)
} }
@Test @Test

View File

@ -6,7 +6,7 @@ import function.builtin.EVAL.eval
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import parser.LispParser import parser.LispParser
import sexpression.Cons import sexpression.Cons
import sexpression.Nil.NIL import sexpression.Nil
import sexpression.SExpression import sexpression.SExpression
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
import java.io.IOException import java.io.IOException
@ -64,7 +64,7 @@ object TestUtilities {
@JvmStatic() @JvmStatic()
fun makeList(vararg expressionList: SExpression): Cons { fun makeList(vararg expressionList: SExpression): Cons {
if (expressionList.isEmpty()) if (expressionList.isEmpty())
return NIL return Nil
val rest = makeList(*Arrays.copyOfRange(expressionList, 1, expressionList.size)) val rest = makeList(*Arrays.copyOfRange(expressionList, 1, expressionList.size))

View File

@ -1,9 +1,9 @@
package testutil package testutil
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import sexpression.Nil.NIL import sexpression.Nil
import sexpression.SExpression import sexpression.SExpression
import sexpression.Symbol.T import sexpression.Symbol.Companion.T
object TypeAssertions { object TypeAssertions {
@ -24,7 +24,7 @@ object TypeAssertions {
@JvmStatic() @JvmStatic()
fun assertNil(sExpression: SExpression) { fun assertNil(sExpression: SExpression) {
assertThat(sExpression).isEqualTo(NIL) assertThat(sExpression).isEqualTo(Nil)
assertThat(sExpression.isAtom).isTrue() assertThat(sExpression.isAtom).isTrue()
assertThat(sExpression.isCons).isFalse() assertThat(sExpression.isCons).isFalse()