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.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());

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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