Convert sexpressions to kotlin
This commit is contained in:
		
							parent
							
								
									4c8342a9f7
								
							
						
					
					
						commit
						16118a9a78
					
				@ -4,6 +4,7 @@ import error.LispException;
 | 
				
			|||||||
import recursion.TailCall;
 | 
					import recursion.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());
 | 
				
			||||||
 | 
				
			|||||||
@ -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();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -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();
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -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) {
 | 
				
			||||||
 | 
				
			|||||||
@ -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();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -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;
 | 
				
			||||||
 | 
				
			|||||||
@ -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) {
 | 
				
			||||||
 | 
				
			|||||||
@ -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) {
 | 
				
			||||||
 | 
				
			|||||||
@ -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;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -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;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -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;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -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) {
 | 
				
			||||||
 | 
				
			|||||||
@ -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;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -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;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -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));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -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));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -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)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -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) {
 | 
				
			||||||
 | 
				
			|||||||
@ -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));
 | 
				
			||||||
 | 
				
			|||||||
@ -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) {
 | 
				
			||||||
 | 
				
			|||||||
@ -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());
 | 
				
			||||||
 | 
				
			|||||||
@ -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) {
 | 
				
			||||||
 | 
				
			|||||||
@ -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;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										9
									
								
								src/main/kotlin/sexpression/AtSignExpression.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/main/kotlin/sexpression/AtSignExpression.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					package sexpression
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AtSignExpression(val expression: SExpression) : SExpression() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override val isAtSign: Boolean
 | 
				
			||||||
 | 
					        get() = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun toString() = "@$expression"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,21 +0,0 @@
 | 
				
			|||||||
package sexpression;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@DisplayName("atom")
 | 
					 | 
				
			||||||
public abstract class Atom extends SExpression {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private String text;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public Atom(String text) {
 | 
					 | 
				
			||||||
        this.text = text;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public boolean isAtom() {
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public String toString() {
 | 
					 | 
				
			||||||
        return text;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										10
									
								
								src/main/kotlin/sexpression/Atom.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/main/kotlin/sexpression/Atom.kt
									
									
									
									
									
										Normal 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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -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;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										9
									
								
								src/main/kotlin/sexpression/BackquoteExpression.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/main/kotlin/sexpression/BackquoteExpression.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					package sexpression
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BackquoteExpression(val expression: SExpression) : SExpression() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override val isBackquote: Boolean
 | 
				
			||||||
 | 
					        get() = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun toString() = "`$expression"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,24 +0,0 @@
 | 
				
			|||||||
package sexpression;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class CommaExpression extends SExpression {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private SExpression expression;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public CommaExpression(SExpression expression) {
 | 
					 | 
				
			||||||
        this.expression = expression;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public SExpression getExpression() {
 | 
					 | 
				
			||||||
        return expression;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public boolean isComma() {
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public String toString() {
 | 
					 | 
				
			||||||
        return "," + expression;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										9
									
								
								src/main/kotlin/sexpression/CommaExpression.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/main/kotlin/sexpression/CommaExpression.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					package sexpression
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CommaExpression(val expression: SExpression) : SExpression() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override val isComma: Boolean
 | 
				
			||||||
 | 
					        get() = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun toString() = ",$expression"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,56 +0,0 @@
 | 
				
			|||||||
package sexpression;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import recursion.TailCall;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import static recursion.TailCalls.done;
 | 
					 | 
				
			||||||
import static recursion.TailCalls.tailCall;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@DisplayName("list")
 | 
					 | 
				
			||||||
public class Cons extends SExpression {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private SExpression first;
 | 
					 | 
				
			||||||
    private SExpression rest;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public Cons(SExpression first, SExpression rest) {
 | 
					 | 
				
			||||||
        this.first = first;
 | 
					 | 
				
			||||||
        this.rest = rest;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public SExpression getFirst() {
 | 
					 | 
				
			||||||
        return first;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public SExpression getRest() {
 | 
					 | 
				
			||||||
        return rest;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void setFirst(SExpression first) {
 | 
					 | 
				
			||||||
        this.first = first;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void setRest(SExpression rest) {
 | 
					 | 
				
			||||||
        this.rest = rest;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public boolean isCons() {
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public String toString() {
 | 
					 | 
				
			||||||
        return toStringTailRecursive(new StringBuilder("(")).invoke();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private TailCall<String> toStringTailRecursive(StringBuilder leadingString) {
 | 
					 | 
				
			||||||
        leadingString.append(first.toString());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (rest.isNull())
 | 
					 | 
				
			||||||
            return done(leadingString.append(")").toString());
 | 
					 | 
				
			||||||
        else if (rest.isCons()) {
 | 
					 | 
				
			||||||
            return tailCall(() -> ((Cons) rest).toStringTailRecursive(leadingString.append(" ")));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return done(leadingString.append(" . " + rest.toString() + ")").toString());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										29
									
								
								src/main/kotlin/sexpression/Cons.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/main/kotlin/sexpression/Cons.kt
									
									
									
									
									
										Normal 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())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -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();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										9
									
								
								src/main/kotlin/sexpression/DisplayName.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/main/kotlin/sexpression/DisplayName.kt
									
									
									
									
									
										Normal 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)
 | 
				
			||||||
@ -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();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										12
									
								
								src/main/kotlin/sexpression/LambdaExpression.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/main/kotlin/sexpression/LambdaExpression.kt
									
									
									
									
									
										Normal 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()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -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);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										39
									
								
								src/main/kotlin/sexpression/LispNumber.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/main/kotlin/sexpression/LispNumber.kt
									
									
									
									
									
										Normal 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)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -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;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										8
									
								
								src/main/kotlin/sexpression/LispString.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/main/kotlin/sexpression/LispString.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					package sexpression
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@DisplayName("string")
 | 
				
			||||||
 | 
					class LispString(text: String) : Atom(text) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override val isString: Boolean
 | 
				
			||||||
 | 
					        get() = true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,51 +0,0 @@
 | 
				
			|||||||
package sexpression;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@DisplayName("nil")
 | 
					 | 
				
			||||||
public class Nil extends Cons {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static final Nil NIL = new Nil();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private Nil() {
 | 
					 | 
				
			||||||
        super(null, null);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        super.setFirst(this);
 | 
					 | 
				
			||||||
        super.setRest(this);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public boolean isNull() {
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public boolean isAtom() {
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public boolean isCons() {
 | 
					 | 
				
			||||||
        return false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public boolean isSymbol() {
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * The first of NIL can not be changed.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void setFirst(SExpression first) {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * The rest of NIL can not be changed.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void setRest(SExpression rest) {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public String toString() {
 | 
					 | 
				
			||||||
        return "NIL";
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										27
									
								
								src/main/kotlin/sexpression/Nil.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/main/kotlin/sexpression/Nil.kt
									
									
									
									
									
										Normal 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"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -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;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										38
									
								
								src/main/kotlin/sexpression/SExpression.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/main/kotlin/sexpression/SExpression.kt
									
									
									
									
									
										Normal 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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -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;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										16
									
								
								src/main/kotlin/sexpression/Symbol.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/main/kotlin/sexpression/Symbol.kt
									
									
									
									
									
										Normal 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")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -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)
 | 
				
			||||||
 | 
				
			|||||||
@ -3,14 +3,14 @@ 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
open class SymbolTable @JvmOverloads constructor(open val parent: SymbolTable? = NullSymbolTable) : Iterable<SymbolTable> {
 | 
					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)
 | 
					    override fun iterator(): Iterator<SymbolTable> = SymbolTableIterator(this)
 | 
				
			||||||
    operator fun contains(symbolName: String) = symbolName in table
 | 
					    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 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)))
 | 
				
			||||||
 | 
				
			|||||||
@ -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))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -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> {
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,13 +3,11 @@
 | 
				
			|||||||
(defmacro dlambda (&rest methods)
 | 
					(defmacro dlambda (&rest methods)
 | 
				
			||||||
  (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))
 | 
					                                                                                                                            arguments
 | 
				
			||||||
                       ,(if (equal t (first method))
 | 
					                                                                                                                            `(rest, arguments))
 | 
				
			||||||
                         arguments
 | 
					                                                             methods)))))
 | 
				
			||||||
                         `(rest ,arguments)))))
 | 
					 | 
				
			||||||
            methods)))))
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -6,9 +6,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
(defun maplist (function-name the-list)
 | 
					(defun maplist (function-name the-list)
 | 
				
			||||||
  (cond
 | 
					  (cond
 | 
				
			||||||
   ((null the-list) nil)
 | 
					    ((null the-list) nil)
 | 
				
			||||||
   (t (cons (funcall function-name the-list)
 | 
					    (t (cons (funcall function-name the-list)
 | 
				
			||||||
       (maplist function-name (rest the-list))))))
 | 
					          (maplist function-name (rest the-list))))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(defun map (function the-list)
 | 
					(defun map (function the-list)
 | 
				
			||||||
  (reverse (map-tail function the-list nil)))
 | 
					  (reverse (map-tail function the-list nil)))
 | 
				
			||||||
@ -42,7 +42,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
(defun reverse-tail (accumulator the-list)
 | 
					(defun reverse-tail (accumulator the-list)
 | 
				
			||||||
  (if (null the-list) accumulator
 | 
					  (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)
 | 
					(defun deep-reverse (the-list)
 | 
				
			||||||
  (if the-list
 | 
					  (if the-list
 | 
				
			||||||
@ -55,9 +55,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
(defun nth (n listA)
 | 
					(defun nth (n listA)
 | 
				
			||||||
  (cond
 | 
					  (cond
 | 
				
			||||||
   ((equal 0 n) (first listA))
 | 
					    ((equal 0 n) (first listA))
 | 
				
			||||||
   (t (nth (- n 1) (rest listA)))))
 | 
					    (t (nth (- n 1) (rest listA)))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(eval
 | 
					(eval
 | 
				
			||||||
  (let ((expr (gensym)))
 | 
					  (let ((expr (gensym)))
 | 
				
			||||||
    `(defun global-eval (,expr) (eval ,expr))))
 | 
					    `(defun global-eval (, expr) (eval, expr))))
 | 
				
			||||||
 | 
				
			|||||||
@ -16,18 +16,16 @@ import static error.Severity.ERROR;
 | 
				
			|||||||
import static org.junit.Assert.assertEquals;
 | 
					import static org.junit.Assert.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)));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -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);
 | 
				
			||||||
 | 
				
			|||||||
@ -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();
 | 
				
			||||||
 | 
				
			|||||||
@ -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)
 | 
				
			||||||
 | 
				
			|||||||
@ -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());
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
 | 
				
			|||||||
@ -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) }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
 | 
				
			|||||||
@ -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() {
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
 | 
				
			|||||||
@ -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))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -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()
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user