Convert more builtins to kotlin
This commit is contained in:
		
							parent
							
								
									b2867042fe
								
							
						
					
					
						commit
						d95b5cc46f
					
				@ -1,39 +0,0 @@
 | 
				
			|||||||
package function.builtin;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import function.ArgumentValidator;
 | 
					 | 
				
			||||||
import function.FunctionNames;
 | 
					 | 
				
			||||||
import function.LispFunction;
 | 
					 | 
				
			||||||
import sexpression.Cons;
 | 
					 | 
				
			||||||
import sexpression.SExpression;
 | 
					 | 
				
			||||||
import table.FunctionTable;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import static function.builtin.Eval.applyFunction;
 | 
					 | 
				
			||||||
import static function.builtin.Eval.lookupFunctionOrLambda;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@FunctionNames({ "APPLY" })
 | 
					 | 
				
			||||||
public class APPLY extends LispFunction {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static SExpression apply(Cons argumentList) {
 | 
					 | 
				
			||||||
        return FunctionTable.INSTANCE.lookupFunction("APPLY").call(argumentList);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private ArgumentValidator argumentValidator;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public APPLY(String name) {
 | 
					 | 
				
			||||||
        this.argumentValidator = new ArgumentValidator(name);
 | 
					 | 
				
			||||||
        this.argumentValidator.setExactNumberOfArguments(2);
 | 
					 | 
				
			||||||
        this.argumentValidator.setTrailingArgumentExpectedType(Cons.class);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public SExpression call(Cons argumentList) {
 | 
					 | 
				
			||||||
        argumentValidator.validate(argumentList);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Cons rest = (Cons) argumentList.getRest();
 | 
					 | 
				
			||||||
        Cons functionArguments = (Cons) rest.getFirst();
 | 
					 | 
				
			||||||
        SExpression functionName = argumentList.getFirst();
 | 
					 | 
				
			||||||
        LispFunction function = lookupFunctionOrLambda(functionName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return applyFunction(function, functionArguments);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										38
									
								
								src/main/kotlin/function/builtin/Apply.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/main/kotlin/function/builtin/Apply.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					package function.builtin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import function.ArgumentValidator
 | 
				
			||||||
 | 
					import function.FunctionNames
 | 
				
			||||||
 | 
					import function.LispFunction
 | 
				
			||||||
 | 
					import sexpression.Cons
 | 
				
			||||||
 | 
					import sexpression.SExpression
 | 
				
			||||||
 | 
					import table.FunctionTable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import function.builtin.Eval.Companion.applyFunction
 | 
				
			||||||
 | 
					import function.builtin.Eval.Companion.lookupFunctionOrLambda
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@FunctionNames("APPLY")
 | 
				
			||||||
 | 
					class Apply(name: String) : LispFunction() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private val argumentValidator: ArgumentValidator = ArgumentValidator(name).apply {
 | 
				
			||||||
 | 
					        setExactNumberOfArguments(2)
 | 
				
			||||||
 | 
					        setTrailingArgumentExpectedType(Cons::class.java)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun call(argumentList: Cons): SExpression {
 | 
				
			||||||
 | 
					        argumentValidator.validate(argumentList)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val rest = argumentList.rest as Cons
 | 
				
			||||||
 | 
					        val functionArguments = rest.first as Cons
 | 
				
			||||||
 | 
					        val functionName = argumentList.first
 | 
				
			||||||
 | 
					        val function = lookupFunctionOrLambda(functionName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return applyFunction(function, functionArguments)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    companion object {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fun apply(argumentList: Cons): SExpression {
 | 
				
			||||||
 | 
					            return FunctionTable.lookupFunction("APPLY")!!.call(argumentList)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,29 +0,0 @@
 | 
				
			|||||||
package function.builtin;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import function.ArgumentValidator;
 | 
					 | 
				
			||||||
import function.FunctionNames;
 | 
					 | 
				
			||||||
import function.LispFunction;
 | 
					 | 
				
			||||||
import sexpression.Cons;
 | 
					 | 
				
			||||||
import sexpression.SExpression;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import static function.builtin.APPLY.apply;
 | 
					 | 
				
			||||||
import static function.builtin.cons.LIST.makeList;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@FunctionNames({ "FUNCALL", "CALL" })
 | 
					 | 
				
			||||||
public class FUNCALL extends LispFunction {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private ArgumentValidator argumentValidator;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public FUNCALL(String name) {
 | 
					 | 
				
			||||||
        this.argumentValidator = new ArgumentValidator(name);
 | 
					 | 
				
			||||||
        this.argumentValidator.setMinimumNumberOfArguments(1);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public SExpression call(Cons argumentList) {
 | 
					 | 
				
			||||||
        argumentValidator.validate(argumentList);
 | 
					 | 
				
			||||||
        Cons applyArgs = new Cons(argumentList.getFirst(), makeList(argumentList.getRest()));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return apply(applyArgs);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										24
									
								
								src/main/kotlin/function/builtin/Funcall.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/main/kotlin/function/builtin/Funcall.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					package function.builtin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import function.ArgumentValidator
 | 
				
			||||||
 | 
					import function.FunctionNames
 | 
				
			||||||
 | 
					import function.LispFunction
 | 
				
			||||||
 | 
					import function.builtin.Apply.Companion.apply
 | 
				
			||||||
 | 
					import function.builtin.cons.LIST.makeList
 | 
				
			||||||
 | 
					import sexpression.Cons
 | 
				
			||||||
 | 
					import sexpression.SExpression
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@FunctionNames("FUNCALL", "CALL")
 | 
				
			||||||
 | 
					class Funcall(name: String) : LispFunction() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private val argumentValidator: ArgumentValidator = ArgumentValidator(name).apply {
 | 
				
			||||||
 | 
					        setMinimumNumberOfArguments(1)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun call(argumentList: Cons): SExpression {
 | 
				
			||||||
 | 
					        argumentValidator.validate(argumentList)
 | 
				
			||||||
 | 
					        val applyArgs = Cons(argumentList.first, makeList(argumentList.rest))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return apply(applyArgs)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,42 +0,0 @@
 | 
				
			|||||||
package function.builtin;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import function.ArgumentValidator;
 | 
					 | 
				
			||||||
import function.FunctionNames;
 | 
					 | 
				
			||||||
import function.LispFunction;
 | 
					 | 
				
			||||||
import sexpression.Cons;
 | 
					 | 
				
			||||||
import sexpression.SExpression;
 | 
					 | 
				
			||||||
import sexpression.Symbol;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.math.BigInteger;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@FunctionNames({ "GENSYM" })
 | 
					 | 
				
			||||||
public class GENSYM extends LispFunction {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static final String GENSYM_PREFIX = "#G";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private static BigInteger counter = BigInteger.ZERO;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private static Symbol generateSymbol() {
 | 
					 | 
				
			||||||
        incrementCounter();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return new Symbol(GENSYM_PREFIX + counter);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private static void incrementCounter() {
 | 
					 | 
				
			||||||
        counter = counter.add(BigInteger.ONE);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private ArgumentValidator argumentValidator;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public GENSYM(String name) {
 | 
					 | 
				
			||||||
        this.argumentValidator = new ArgumentValidator(name);
 | 
					 | 
				
			||||||
        this.argumentValidator.setMaximumNumberOfArguments(0);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public SExpression call(Cons argumentList) {
 | 
					 | 
				
			||||||
        argumentValidator.validate(argumentList);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return generateSymbol();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										41
									
								
								src/main/kotlin/function/builtin/Gensym.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/main/kotlin/function/builtin/Gensym.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					package function.builtin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import function.ArgumentValidator
 | 
				
			||||||
 | 
					import function.FunctionNames
 | 
				
			||||||
 | 
					import function.LispFunction
 | 
				
			||||||
 | 
					import sexpression.Cons
 | 
				
			||||||
 | 
					import sexpression.SExpression
 | 
				
			||||||
 | 
					import sexpression.Symbol
 | 
				
			||||||
 | 
					import java.math.BigInteger.ONE
 | 
				
			||||||
 | 
					import java.math.BigInteger.ZERO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@FunctionNames("GENSYM")
 | 
				
			||||||
 | 
					class Gensym(name: String) : LispFunction() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private val argumentValidator: ArgumentValidator = ArgumentValidator(name).apply {
 | 
				
			||||||
 | 
					        setMaximumNumberOfArguments(0)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun call(argumentList: Cons): SExpression {
 | 
				
			||||||
 | 
					        argumentValidator.validate(argumentList)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return generateSymbol()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    companion object {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const val GENSYM_PREFIX = "#G"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private var counter = ZERO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private fun generateSymbol(): Symbol {
 | 
				
			||||||
 | 
					            incrementCounter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return Symbol(GENSYM_PREFIX + counter)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private fun incrementCounter() {
 | 
				
			||||||
 | 
					            counter = counter.add(ONE)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,28 +0,0 @@
 | 
				
			|||||||
package function.builtin;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import function.ArgumentValidator;
 | 
					 | 
				
			||||||
import function.FunctionNames;
 | 
					 | 
				
			||||||
import function.LispFunction;
 | 
					 | 
				
			||||||
import sexpression.Cons;
 | 
					 | 
				
			||||||
import sexpression.SExpression;
 | 
					 | 
				
			||||||
import table.ExecutionContext;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@FunctionNames({ "SYMBOLS" })
 | 
					 | 
				
			||||||
public class SYMBOLS extends LispFunction {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private ArgumentValidator argumentValidator;
 | 
					 | 
				
			||||||
    private ExecutionContext executionContext;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public SYMBOLS(String name) {
 | 
					 | 
				
			||||||
        this.argumentValidator = new ArgumentValidator(name);
 | 
					 | 
				
			||||||
        this.argumentValidator.setExactNumberOfArguments(0);
 | 
					 | 
				
			||||||
        this.executionContext = ExecutionContext.INSTANCE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public SExpression call(Cons argumentList) {
 | 
					 | 
				
			||||||
        argumentValidator.validate(argumentList);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return executionContext.toList();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,63 +0,0 @@
 | 
				
			|||||||
package function.builtin;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import error.LispException;
 | 
					 | 
				
			||||||
import function.ArgumentValidator;
 | 
					 | 
				
			||||||
import function.FunctionNames;
 | 
					 | 
				
			||||||
import function.LispFunction;
 | 
					 | 
				
			||||||
import function.LispSpecialFunction;
 | 
					 | 
				
			||||||
import function.UserDefinedFunction;
 | 
					 | 
				
			||||||
import sexpression.Cons;
 | 
					 | 
				
			||||||
import sexpression.SExpression;
 | 
					 | 
				
			||||||
import sexpression.Symbol;
 | 
					 | 
				
			||||||
import table.FunctionTable;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import static java.text.MessageFormat.format;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@FunctionNames({ "SYMBOL-FUNCTION" })
 | 
					 | 
				
			||||||
public class SYMBOL_FUNCTION extends LispFunction {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private ArgumentValidator argumentValidator;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public SYMBOL_FUNCTION(String name) {
 | 
					 | 
				
			||||||
        this.argumentValidator = new ArgumentValidator(name);
 | 
					 | 
				
			||||||
        this.argumentValidator.setExactNumberOfArguments(1);
 | 
					 | 
				
			||||||
        this.argumentValidator.setEveryArgumentExpectedType(Symbol.class);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public SExpression call(Cons argumentList) {
 | 
					 | 
				
			||||||
        argumentValidator.validate(argumentList);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        SExpression symbol = argumentList.getFirst();
 | 
					 | 
				
			||||||
        LispFunction function = FunctionTable.INSTANCE.lookupFunction(symbol.toString());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (function != null)
 | 
					 | 
				
			||||||
            return createRepresentation(symbol, function);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        throw new UndefinedSymbolFunctionException(symbol);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private SExpression createRepresentation(SExpression symbol, LispFunction function) {
 | 
					 | 
				
			||||||
        if (function instanceof UserDefinedFunction)
 | 
					 | 
				
			||||||
            return ((UserDefinedFunction) function).getLambdaExpression();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        String typeIndicator = function instanceof LispSpecialFunction ? "SPECIAL-FUNCTION" : "FUNCTION";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return new Symbol(format("#<{0} {1}>", typeIndicator, symbol));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static class UndefinedSymbolFunctionException extends LispException {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private static final long serialVersionUID = 1L;
 | 
					 | 
				
			||||||
        private SExpression function;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public UndefinedSymbolFunctionException(SExpression function) {
 | 
					 | 
				
			||||||
            this.function = function;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        @Override
 | 
					 | 
				
			||||||
        public String getMessage() {
 | 
					 | 
				
			||||||
            return format("SYMBOL-FUNCTION: undefined function: {0}", function);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										47
									
								
								src/main/kotlin/function/builtin/SymbolFunction.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/main/kotlin/function/builtin/SymbolFunction.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					package function.builtin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import error.LispException
 | 
				
			||||||
 | 
					import function.ArgumentValidator
 | 
				
			||||||
 | 
					import function.FunctionNames
 | 
				
			||||||
 | 
					import function.LispFunction
 | 
				
			||||||
 | 
					import function.LispSpecialFunction
 | 
				
			||||||
 | 
					import function.UserDefinedFunction
 | 
				
			||||||
 | 
					import sexpression.Cons
 | 
				
			||||||
 | 
					import sexpression.SExpression
 | 
				
			||||||
 | 
					import sexpression.Symbol
 | 
				
			||||||
 | 
					import table.FunctionTable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@FunctionNames("SYMBOL-FUNCTION")
 | 
				
			||||||
 | 
					class SymbolFunction(name: String) : LispFunction() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private val argumentValidator: ArgumentValidator = ArgumentValidator(name).apply {
 | 
				
			||||||
 | 
					        setExactNumberOfArguments(1)
 | 
				
			||||||
 | 
					        setEveryArgumentExpectedType(Symbol::class.java)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun call(argumentList: Cons): SExpression {
 | 
				
			||||||
 | 
					        argumentValidator.validate(argumentList)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val symbol = argumentList.first
 | 
				
			||||||
 | 
					        val function = FunctionTable.lookupFunction(symbol.toString())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (function != null)
 | 
				
			||||||
 | 
					            return createRepresentation(symbol, function)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        throw UndefinedSymbolFunctionException(symbol)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun createRepresentation(symbol: SExpression, function: LispFunction): SExpression {
 | 
				
			||||||
 | 
					        if (function is UserDefinedFunction)
 | 
				
			||||||
 | 
					            return function.lambdaExpression
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val typeIndicator = if (function is LispSpecialFunction) "SPECIAL-FUNCTION" else "FUNCTION"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return Symbol("#<$typeIndicator $symbol>")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class UndefinedSymbolFunctionException(function: SExpression) : LispException() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        override val message = "SYMBOL-FUNCTION: undefined function: $function"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										22
									
								
								src/main/kotlin/function/builtin/Symbols.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/main/kotlin/function/builtin/Symbols.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					package function.builtin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import function.ArgumentValidator
 | 
				
			||||||
 | 
					import function.FunctionNames
 | 
				
			||||||
 | 
					import function.LispFunction
 | 
				
			||||||
 | 
					import sexpression.Cons
 | 
				
			||||||
 | 
					import sexpression.SExpression
 | 
				
			||||||
 | 
					import table.ExecutionContext
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@FunctionNames("SYMBOLS")
 | 
				
			||||||
 | 
					class Symbols(name: String) : LispFunction() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private val argumentValidator: ArgumentValidator = ArgumentValidator(name).apply {
 | 
				
			||||||
 | 
					        setExactNumberOfArguments(0)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun call(argumentList: Cons): SExpression {
 | 
				
			||||||
 | 
					        argumentValidator.validate(argumentList)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ExecutionContext.toList()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,100 +0,0 @@
 | 
				
			|||||||
package function.builtin.predicate;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import function.ArgumentValidator;
 | 
					 | 
				
			||||||
import function.FunctionNames;
 | 
					 | 
				
			||||||
import function.LispFunction;
 | 
					 | 
				
			||||||
import sexpression.Cons;
 | 
					 | 
				
			||||||
import sexpression.Nil;
 | 
					 | 
				
			||||||
import sexpression.SExpression;
 | 
					 | 
				
			||||||
import sexpression.Symbol;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.util.HashMap;
 | 
					 | 
				
			||||||
import java.util.Map;
 | 
					 | 
				
			||||||
import java.util.Map.Entry;
 | 
					 | 
				
			||||||
import java.util.regex.Matcher;
 | 
					 | 
				
			||||||
import java.util.regex.Pattern;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import static function.builtin.GENSYM.GENSYM_PREFIX;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@FunctionNames({ "GENSYM-EQUAL", "GENSYM-EQUAL?" })
 | 
					 | 
				
			||||||
public class GENSYM_EQUAL extends LispFunction {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private ArgumentValidator argumentValidator;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public GENSYM_EQUAL(String name) {
 | 
					 | 
				
			||||||
        this.argumentValidator = new ArgumentValidator(name);
 | 
					 | 
				
			||||||
        this.argumentValidator.setExactNumberOfArguments(2);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public SExpression call(Cons argumentList) {
 | 
					 | 
				
			||||||
        argumentValidator.validate(argumentList);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Cons rest = (Cons) argumentList.getRest();
 | 
					 | 
				
			||||||
        SExpression firstArgument = argumentList.getFirst();
 | 
					 | 
				
			||||||
        SExpression secondArgument = rest.getFirst();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return gensymEqual(firstArgument, secondArgument);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private SExpression gensymEqual(SExpression firstArgument, SExpression secondArgument) {
 | 
					 | 
				
			||||||
        String firstEqualized = equalizeGensyms(firstArgument);
 | 
					 | 
				
			||||||
        String secondEqualized = equalizeGensyms(secondArgument);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return firstEqualized.equals(secondEqualized) ? Symbol.Companion.getT() : Nil.INSTANCE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private String equalizeGensyms(SExpression expression) {
 | 
					 | 
				
			||||||
        GensymEqualizer equalizer = new GensymEqualizer(expression.toString());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return equalizer.equalize();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private static class GensymEqualizer {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private static final String GENSYM_REGEX = Pattern.quote(GENSYM_PREFIX) + "[0-9]+";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Map<String, String> gensymAliases;
 | 
					 | 
				
			||||||
        Matcher matcher;
 | 
					 | 
				
			||||||
        String expression;
 | 
					 | 
				
			||||||
        int counter;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public GensymEqualizer(String expression) {
 | 
					 | 
				
			||||||
            this.gensymAliases = new HashMap<>();
 | 
					 | 
				
			||||||
            this.matcher = Pattern.compile(GENSYM_REGEX).matcher(expression);
 | 
					 | 
				
			||||||
            this.expression = expression;
 | 
					 | 
				
			||||||
            this.counter = 0;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public String equalize() {
 | 
					 | 
				
			||||||
            createGensymAliases();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return equalizeGensyms();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private void createGensymAliases() {
 | 
					 | 
				
			||||||
            while (matcher.find())
 | 
					 | 
				
			||||||
                createAliasForGensym();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private void createAliasForGensym() {
 | 
					 | 
				
			||||||
            String gensym = matcher.group();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (isNewGensym(gensym))
 | 
					 | 
				
			||||||
                gensymAliases.put(gensym, GENSYM_PREFIX + (counter++));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private boolean isNewGensym(String gensym) {
 | 
					 | 
				
			||||||
            return !gensymAliases.containsKey(gensym);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private String equalizeGensyms() {
 | 
					 | 
				
			||||||
            String equalizedExpression = expression;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            for (Entry<String, String> entry : gensymAliases.entrySet())
 | 
					 | 
				
			||||||
                equalizedExpression = equalizedExpression.replace(entry.getKey(), entry.getValue());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return equalizedExpression;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										82
									
								
								src/main/kotlin/function/builtin/predicate/GensymEqual.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								src/main/kotlin/function/builtin/predicate/GensymEqual.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,82 @@
 | 
				
			|||||||
 | 
					package function.builtin.predicate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import function.ArgumentValidator
 | 
				
			||||||
 | 
					import function.FunctionNames
 | 
				
			||||||
 | 
					import function.LispFunction
 | 
				
			||||||
 | 
					import function.builtin.Gensym.Companion.GENSYM_PREFIX
 | 
				
			||||||
 | 
					import sexpression.Cons
 | 
				
			||||||
 | 
					import sexpression.Nil
 | 
				
			||||||
 | 
					import sexpression.SExpression
 | 
				
			||||||
 | 
					import sexpression.Symbol
 | 
				
			||||||
 | 
					import java.util.regex.Pattern
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@FunctionNames("GENSYM-EQUAL", "GENSYM-EQUAL?")
 | 
				
			||||||
 | 
					class GensymEqual(name: String) : LispFunction() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private val argumentValidator: ArgumentValidator = ArgumentValidator(name).apply {
 | 
				
			||||||
 | 
					        setExactNumberOfArguments(2)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun call(argumentList: Cons): SExpression {
 | 
				
			||||||
 | 
					        argumentValidator.validate(argumentList)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val rest = argumentList.rest as Cons
 | 
				
			||||||
 | 
					        val firstArgument = argumentList.first
 | 
				
			||||||
 | 
					        val secondArgument = rest.first
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return gensymEqual(firstArgument, secondArgument)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun gensymEqual(firstArgument: SExpression, secondArgument: SExpression): SExpression {
 | 
				
			||||||
 | 
					        val firstEqualized = equalizeGensyms(firstArgument)
 | 
				
			||||||
 | 
					        val secondEqualized = equalizeGensyms(secondArgument)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return if (firstEqualized == secondEqualized) Symbol.T else Nil
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun equalizeGensyms(expression: SExpression) =
 | 
				
			||||||
 | 
					        GensymEqualizer(expression.toString()).equalize()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private class GensymEqualizer(internal var expression: String) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal val gensymAliases = mutableMapOf<String, String>()
 | 
				
			||||||
 | 
					        internal var matcher = Pattern.compile(GENSYM_REGEX).matcher(expression)
 | 
				
			||||||
 | 
					        internal var counter: Int = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fun equalize(): String {
 | 
				
			||||||
 | 
					            createGensymAliases()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return equalizeGensyms()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private fun createGensymAliases() {
 | 
				
			||||||
 | 
					            while (matcher.find())
 | 
				
			||||||
 | 
					                createAliasForGensym()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private fun createAliasForGensym() {
 | 
				
			||||||
 | 
					            val gensym = matcher.group()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (isNewGensym(gensym))
 | 
				
			||||||
 | 
					                gensymAliases[gensym] = GENSYM_PREFIX + counter++
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private fun isNewGensym(gensym: String): Boolean {
 | 
				
			||||||
 | 
					            return !gensymAliases.containsKey(gensym)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private fun equalizeGensyms(): String {
 | 
				
			||||||
 | 
					            var equalizedExpression = expression
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for ((key, value) in gensymAliases)
 | 
				
			||||||
 | 
					                equalizedExpression = equalizedExpression.replace(key, value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return equalizedExpression
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        companion object {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            private val GENSYM_REGEX = Pattern.quote(GENSYM_PREFIX) + "[0-9]+"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,78 +0,0 @@
 | 
				
			|||||||
package function.builtin;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import function.ArgumentValidator.BadArgumentTypeException;
 | 
					 | 
				
			||||||
import function.ArgumentValidator.DottedArgumentListException;
 | 
					 | 
				
			||||||
import function.ArgumentValidator.TooFewArgumentsException;
 | 
					 | 
				
			||||||
import function.ArgumentValidator.TooManyArgumentsException;
 | 
					 | 
				
			||||||
import function.builtin.Eval.UndefinedFunctionException;
 | 
					 | 
				
			||||||
import org.junit.Test;
 | 
					 | 
				
			||||||
import sexpression.Cons;
 | 
					 | 
				
			||||||
import testutil.SymbolAndFunctionCleaner;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import static function.builtin.APPLY.apply;
 | 
					 | 
				
			||||||
import static testutil.TestUtilities.assertSExpressionsMatch;
 | 
					 | 
				
			||||||
import static testutil.TestUtilities.evaluateString;
 | 
					 | 
				
			||||||
import static testutil.TestUtilities.parseString;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class APPLYTest extends SymbolAndFunctionCleaner {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void applyWithSymbol() {
 | 
					 | 
				
			||||||
        String input = "(apply '+ '(1 2 3))";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertSExpressionsMatch(parseString("6"), evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void applyWithLambdaExpression() {
 | 
					 | 
				
			||||||
        String input = "(apply (lambda (x) (+ x 1)) '(25))";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertSExpressionsMatch(parseString("26"), evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void applyWithQuotedLambdaExpression() {
 | 
					 | 
				
			||||||
        String input = "(apply '(lambda (x) (+ x 1)) '(25))";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertSExpressionsMatch(parseString("26"), evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void staticApplyCall() {
 | 
					 | 
				
			||||||
        String argumentList = "(+ (25 10))";
 | 
					 | 
				
			||||||
        Cons parsedArgumentList = (Cons) parseString(argumentList);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertSExpressionsMatch(parseString("35"), apply(parsedArgumentList));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test(expected = UndefinedFunctionException.class)
 | 
					 | 
				
			||||||
    public void applyWithUndefinedFunction() {
 | 
					 | 
				
			||||||
        evaluateString("(apply 'f '(1 2 3))");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test(expected = BadArgumentTypeException.class)
 | 
					 | 
				
			||||||
    public void applyWithNonListSecondArgument() {
 | 
					 | 
				
			||||||
        evaluateString("(apply '+ '2)");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test(expected = TooManyArgumentsException.class)
 | 
					 | 
				
			||||||
    public void applyWithTooManyArguments() {
 | 
					 | 
				
			||||||
        evaluateString("(apply '1 '2 '3)");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test(expected = TooFewArgumentsException.class)
 | 
					 | 
				
			||||||
    public void applyWithTooFewArguments() {
 | 
					 | 
				
			||||||
        evaluateString("(apply '1)");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test(expected = DottedArgumentListException.class)
 | 
					 | 
				
			||||||
    public void applyWithDottedArgumentList_ThrowsException() {
 | 
					 | 
				
			||||||
        evaluateString("(apply 'apply (cons 'T 'T))");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void applyWithMacro() {
 | 
					 | 
				
			||||||
        evaluateString("(defmacro m (x) `(+ 2 ,x))");
 | 
					 | 
				
			||||||
        assertSExpressionsMatch(parseString("27"), evaluateString("(apply 'm '(25))"));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										90
									
								
								src/test/kotlin/function/builtin/ApplyTest.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								src/test/kotlin/function/builtin/ApplyTest.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,90 @@
 | 
				
			|||||||
 | 
					package function.builtin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import function.ArgumentValidator.BadArgumentTypeException
 | 
				
			||||||
 | 
					import function.ArgumentValidator.DottedArgumentListException
 | 
				
			||||||
 | 
					import function.ArgumentValidator.TooFewArgumentsException
 | 
				
			||||||
 | 
					import function.ArgumentValidator.TooManyArgumentsException
 | 
				
			||||||
 | 
					import function.builtin.Apply.Companion.apply
 | 
				
			||||||
 | 
					import function.builtin.Eval.UndefinedFunctionException
 | 
				
			||||||
 | 
					import org.junit.jupiter.api.Assertions.assertThrows
 | 
				
			||||||
 | 
					import org.junit.jupiter.api.Test
 | 
				
			||||||
 | 
					import sexpression.Cons
 | 
				
			||||||
 | 
					import testutil.LispTestInstance
 | 
				
			||||||
 | 
					import testutil.SymbolAndFunctionCleaner
 | 
				
			||||||
 | 
					import testutil.TestUtilities.assertSExpressionsMatch
 | 
				
			||||||
 | 
					import testutil.TestUtilities.evaluateString
 | 
				
			||||||
 | 
					import testutil.TestUtilities.parseString
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@LispTestInstance
 | 
				
			||||||
 | 
					class ApplyTest : SymbolAndFunctionCleaner() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun applyWithSymbol() {
 | 
				
			||||||
 | 
					        val input = "(apply '+ '(1 2 3))"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(parseString("6"), evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun applyWithLambdaExpression() {
 | 
				
			||||||
 | 
					        val input = "(apply (lambda (x) (+ x 1)) '(25))"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(parseString("26"), evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun applyWithQuotedLambdaExpression() {
 | 
				
			||||||
 | 
					        val input = "(apply '(lambda (x) (+ x 1)) '(25))"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(parseString("26"), evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun staticApplyCall() {
 | 
				
			||||||
 | 
					        val argumentList = "(+ (25 10))"
 | 
				
			||||||
 | 
					        val parsedArgumentList = parseString(argumentList) as Cons
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(parseString("35"), apply(parsedArgumentList))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun applyWithUndefinedFunction() {
 | 
				
			||||||
 | 
					        assertThrows(UndefinedFunctionException::class.java) {
 | 
				
			||||||
 | 
					            evaluateString("(apply 'f '(1 2 3))")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun applyWithNonListSecondArgument() {
 | 
				
			||||||
 | 
					        assertThrows(BadArgumentTypeException::class.java) {
 | 
				
			||||||
 | 
					            evaluateString("(apply '+ '2)")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun applyWithTooManyArguments() {
 | 
				
			||||||
 | 
					        assertThrows(TooManyArgumentsException::class.java) {
 | 
				
			||||||
 | 
					            evaluateString("(apply '1 '2 '3)")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun applyWithTooFewArguments() {
 | 
				
			||||||
 | 
					        assertThrows(TooFewArgumentsException::class.java) {
 | 
				
			||||||
 | 
					            evaluateString("(apply '1)")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun applyWithDottedArgumentList_ThrowsException() {
 | 
				
			||||||
 | 
					        assertThrows(DottedArgumentListException::class.java) {
 | 
				
			||||||
 | 
					            evaluateString("(apply 'apply (cons 'T 'T))")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun applyWithMacro() {
 | 
				
			||||||
 | 
					        evaluateString("(defmacro m (x) `(+ 2 ,x))")
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(parseString("27"), evaluateString("(apply 'm '(25))"))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,40 +0,0 @@
 | 
				
			|||||||
package function.builtin;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import function.ArgumentValidator.TooFewArgumentsException;
 | 
					 | 
				
			||||||
import org.junit.Test;
 | 
					 | 
				
			||||||
import testutil.SymbolAndFunctionCleaner;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import static testutil.TestUtilities.assertSExpressionsMatch;
 | 
					 | 
				
			||||||
import static testutil.TestUtilities.evaluateString;
 | 
					 | 
				
			||||||
import static testutil.TestUtilities.parseString;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class FUNCALLTest extends SymbolAndFunctionCleaner {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void funcallWithNumbers() {
 | 
					 | 
				
			||||||
        String input = "(funcall '+ 1 2 3)";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertSExpressionsMatch(parseString("6"), evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void callWithNumbers() {
 | 
					 | 
				
			||||||
        String input = "(call '+ 1 2 3)";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertSExpressionsMatch(parseString("6"), evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void funcallWithUserDefinedFunction() {
 | 
					 | 
				
			||||||
        String defineUserFunction = "(defun x (n m) (+ n m))";
 | 
					 | 
				
			||||||
        String input = "(funcall 'x 2 30)";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        evaluateString(defineUserFunction);
 | 
					 | 
				
			||||||
        assertSExpressionsMatch(parseString("32"), evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test(expected = TooFewArgumentsException.class)
 | 
					 | 
				
			||||||
    public void funcallWithTooFewArguments() {
 | 
					 | 
				
			||||||
        evaluateString("(funcall)");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										44
									
								
								src/test/kotlin/function/builtin/FuncallTest.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/test/kotlin/function/builtin/FuncallTest.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					package function.builtin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import function.ArgumentValidator.TooFewArgumentsException
 | 
				
			||||||
 | 
					import org.junit.jupiter.api.Assertions.assertThrows
 | 
				
			||||||
 | 
					import org.junit.jupiter.api.Test
 | 
				
			||||||
 | 
					import testutil.LispTestInstance
 | 
				
			||||||
 | 
					import testutil.SymbolAndFunctionCleaner
 | 
				
			||||||
 | 
					import testutil.TestUtilities.assertSExpressionsMatch
 | 
				
			||||||
 | 
					import testutil.TestUtilities.evaluateString
 | 
				
			||||||
 | 
					import testutil.TestUtilities.parseString
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@LispTestInstance
 | 
				
			||||||
 | 
					class FuncallTest : SymbolAndFunctionCleaner() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun funcallWithNumbers() {
 | 
				
			||||||
 | 
					        val input = "(funcall '+ 1 2 3)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(parseString("6"), evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun callWithNumbers() {
 | 
				
			||||||
 | 
					        val input = "(call '+ 1 2 3)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(parseString("6"), evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun funcallWithUserDefinedFunction() {
 | 
				
			||||||
 | 
					        val defineUserFunction = "(defun x (n m) (+ n m))"
 | 
				
			||||||
 | 
					        val input = "(funcall 'x 2 30)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        evaluateString(defineUserFunction)
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(parseString("32"), evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun funcallWithTooFewArguments() {
 | 
				
			||||||
 | 
					        assertThrows(TooFewArgumentsException::class.java) {
 | 
				
			||||||
 | 
					            evaluateString("(funcall)")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,42 +0,0 @@
 | 
				
			|||||||
package function.builtin;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import function.ArgumentValidator.TooManyArgumentsException;
 | 
					 | 
				
			||||||
import org.junit.Test;
 | 
					 | 
				
			||||||
import testutil.SymbolAndFunctionCleaner;
 | 
					 | 
				
			||||||
import token.TokenFactory.BadCharacterException;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import static function.builtin.GENSYM.GENSYM_PREFIX;
 | 
					 | 
				
			||||||
import static testutil.TestUtilities.assertSExpressionsDoNotMatch;
 | 
					 | 
				
			||||||
import static testutil.TestUtilities.assertSExpressionsMatch;
 | 
					 | 
				
			||||||
import static testutil.TestUtilities.evaluateString;
 | 
					 | 
				
			||||||
import static testutil.TypeAssertions.assertSymbol;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class GENSYMTest extends SymbolAndFunctionCleaner {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymCreatesSymbol() {
 | 
					 | 
				
			||||||
        assertSymbol(evaluateString("(gensym)"));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymCreatesUniqueSymbol() {
 | 
					 | 
				
			||||||
        assertSExpressionsDoNotMatch(evaluateString("(gensym)"), evaluateString("(gensym)"));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void simpleGensymUsage() {
 | 
					 | 
				
			||||||
        String input = "(let ((x (gensym))) (set x 23) (eval x))";
 | 
					 | 
				
			||||||
        assertSExpressionsMatch(evaluateString("23"), evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test(expected = BadCharacterException.class)
 | 
					 | 
				
			||||||
    public void cannotUseGensymValueManually() {
 | 
					 | 
				
			||||||
        String variableName = GENSYM_PREFIX + 1;
 | 
					 | 
				
			||||||
        evaluateString("(setq " + variableName + " 100)");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test(expected = TooManyArgumentsException.class)
 | 
					 | 
				
			||||||
    public void gensymWithTooManyArguments() {
 | 
					 | 
				
			||||||
        evaluateString("(gensym 1)");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										47
									
								
								src/test/kotlin/function/builtin/GensymTest.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/test/kotlin/function/builtin/GensymTest.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					package function.builtin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import function.ArgumentValidator.TooManyArgumentsException
 | 
				
			||||||
 | 
					import function.builtin.Gensym.Companion.GENSYM_PREFIX
 | 
				
			||||||
 | 
					import org.junit.jupiter.api.Assertions.assertThrows
 | 
				
			||||||
 | 
					import org.junit.jupiter.api.Test
 | 
				
			||||||
 | 
					import testutil.SymbolAndFunctionCleaner
 | 
				
			||||||
 | 
					import testutil.TestUtilities.assertSExpressionsDoNotMatch
 | 
				
			||||||
 | 
					import testutil.TestUtilities.assertSExpressionsMatch
 | 
				
			||||||
 | 
					import testutil.TestUtilities.evaluateString
 | 
				
			||||||
 | 
					import testutil.TypeAssertions.assertSymbol
 | 
				
			||||||
 | 
					import token.TokenFactory.BadCharacterException
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class GensymTest : SymbolAndFunctionCleaner() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymCreatesSymbol() {
 | 
				
			||||||
 | 
					        assertSymbol(evaluateString("(gensym)"))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymCreatesUniqueSymbol() {
 | 
				
			||||||
 | 
					        assertSExpressionsDoNotMatch(evaluateString("(gensym)"), evaluateString("(gensym)"))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun simpleGensymUsage() {
 | 
				
			||||||
 | 
					        val input = "(let ((x (gensym))) (set x 23) (eval x))"
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(evaluateString("23"), evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun cannotUseGensymValueManually() {
 | 
				
			||||||
 | 
					        val variableName = GENSYM_PREFIX + 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertThrows(BadCharacterException::class.java) {
 | 
				
			||||||
 | 
					            evaluateString("(setq $variableName 100)")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymWithTooManyArguments() {
 | 
				
			||||||
 | 
					        assertThrows(TooManyArgumentsException::class.java) {
 | 
				
			||||||
 | 
					            evaluateString("(gensym 1)")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,56 +0,0 @@
 | 
				
			|||||||
package function.builtin;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import function.ArgumentValidator.TooManyArgumentsException;
 | 
					 | 
				
			||||||
import org.junit.Test;
 | 
					 | 
				
			||||||
import testutil.SymbolAndFunctionCleaner;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import static testutil.TestUtilities.assertSExpressionsMatch;
 | 
					 | 
				
			||||||
import static testutil.TestUtilities.evaluateString;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class SYMBOLSTest extends SymbolAndFunctionCleaner {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void noSymbols() {
 | 
					 | 
				
			||||||
        assertSExpressionsMatch(evaluateString("'(nil)"), evaluateString("(symbols)"));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void globalSymbol() {
 | 
					 | 
				
			||||||
        evaluateString("(setq x 10)");
 | 
					 | 
				
			||||||
        assertSExpressionsMatch(evaluateString("'(((x 10)))"), evaluateString("(symbols)"));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void multipleSymbolsSorted() {
 | 
					 | 
				
			||||||
        evaluateString("(setq x 10)");
 | 
					 | 
				
			||||||
        evaluateString("(setq a 20)");
 | 
					 | 
				
			||||||
        evaluateString("(setq y 30)");
 | 
					 | 
				
			||||||
        evaluateString("(setq w 40)");
 | 
					 | 
				
			||||||
        evaluateString("(setq e 50)");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertSExpressionsMatch(evaluateString("'(((a 20) (e 50) (w 40) (x 10) (y 30)))"), evaluateString("(symbols)"));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void fullExecutionContext() {
 | 
					 | 
				
			||||||
        evaluateString("(setq x 10)");
 | 
					 | 
				
			||||||
        evaluateString("(setq y 30)");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertSExpressionsMatch(evaluateString("'(((x 10) (y 30)) ((a 100) (q 99) (z nil)))"),
 | 
					 | 
				
			||||||
                                evaluateString("(let ((q 99) (a 100) (z)) (symbols))"));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void updateSymbolInLet() {
 | 
					 | 
				
			||||||
        evaluateString("(setq x 10)");
 | 
					 | 
				
			||||||
        evaluateString("(setq y 30)");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertSExpressionsMatch(evaluateString("'(((x 10) (y 30)) ((q 99) (x 1) (z 2)))"),
 | 
					 | 
				
			||||||
                                evaluateString("(let ((q 99) (x 100) (z 2)) (setq x 1) (symbols))"));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test(expected = TooManyArgumentsException.class)
 | 
					 | 
				
			||||||
    public void symbolsWithTooManyArguments() {
 | 
					 | 
				
			||||||
        evaluateString("(symbols 1)");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,72 +0,0 @@
 | 
				
			|||||||
package function.builtin;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import function.ArgumentValidator.BadArgumentTypeException;
 | 
					 | 
				
			||||||
import function.ArgumentValidator.TooFewArgumentsException;
 | 
					 | 
				
			||||||
import function.ArgumentValidator.TooManyArgumentsException;
 | 
					 | 
				
			||||||
import function.builtin.SYMBOL_FUNCTION.UndefinedSymbolFunctionException;
 | 
					 | 
				
			||||||
import org.junit.Test;
 | 
					 | 
				
			||||||
import sexpression.Nil;
 | 
					 | 
				
			||||||
import testutil.SymbolAndFunctionCleaner;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import static error.Severity.ERROR;
 | 
					 | 
				
			||||||
import static org.junit.Assert.assertEquals;
 | 
					 | 
				
			||||||
import static org.junit.Assert.assertNotNull;
 | 
					 | 
				
			||||||
import static org.junit.Assert.assertTrue;
 | 
					 | 
				
			||||||
import static testutil.TestUtilities.evaluateString;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class SYMBOL_FUNCTIONTest extends SymbolAndFunctionCleaner {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void symbolFunction_BuiltInFunction() {
 | 
					 | 
				
			||||||
        String input = "(symbol-function '+)";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertEquals("#<FUNCTION +>", evaluateString(input).toString());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void symbolFunction_BuiltInSpecialFunction() {
 | 
					 | 
				
			||||||
        String input = "(symbol-function 'if)";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertEquals("#<SPECIAL-FUNCTION IF>", evaluateString(input).toString());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void symbolFunction_UserDefinedFunction() {
 | 
					 | 
				
			||||||
        String defineUserFunction = "(defun y (n m) (+ n m))";
 | 
					 | 
				
			||||||
        String input = "(symbol-function 'y)";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        evaluateString(defineUserFunction);
 | 
					 | 
				
			||||||
        assertEquals("(Y (N M) (+ N M))", evaluateString(input).toString());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test(expected = UndefinedSymbolFunctionException.class)
 | 
					 | 
				
			||||||
    public void symbolFunction_NonFunction() {
 | 
					 | 
				
			||||||
        String input = "(symbol-function 'a)";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        evaluateString(input);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test(expected = BadArgumentTypeException.class)
 | 
					 | 
				
			||||||
    public void symbolFunctionWithBadArgumentType() {
 | 
					 | 
				
			||||||
        evaluateString("(symbol-function 2)");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test(expected = TooManyArgumentsException.class)
 | 
					 | 
				
			||||||
    public void symbolFunctionWithTooManyArguments() {
 | 
					 | 
				
			||||||
        evaluateString("(symbol-function 'a 'b)");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test(expected = TooFewArgumentsException.class)
 | 
					 | 
				
			||||||
    public void symbolFunctionWithTooFewArguments() {
 | 
					 | 
				
			||||||
        evaluateString("(symbol-function)");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void undefinedSymbolFunctionException_HasCorrectAttributes() {
 | 
					 | 
				
			||||||
        UndefinedSymbolFunctionException e = new UndefinedSymbolFunctionException(Nil.INSTANCE);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertEquals(ERROR, e.getSeverity());
 | 
					 | 
				
			||||||
        assertNotNull(e.getMessage());
 | 
					 | 
				
			||||||
        assertTrue(e.getMessage().length() > 0);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										76
									
								
								src/test/kotlin/function/builtin/SymbolFunctionTest.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/test/kotlin/function/builtin/SymbolFunctionTest.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,76 @@
 | 
				
			|||||||
 | 
					package function.builtin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import function.ArgumentValidator.BadArgumentTypeException
 | 
				
			||||||
 | 
					import function.ArgumentValidator.TooFewArgumentsException
 | 
				
			||||||
 | 
					import function.ArgumentValidator.TooManyArgumentsException
 | 
				
			||||||
 | 
					import function.builtin.SymbolFunction.UndefinedSymbolFunctionException
 | 
				
			||||||
 | 
					import org.assertj.core.api.Assertions.assertThat
 | 
				
			||||||
 | 
					import org.junit.jupiter.api.Assertions.assertThrows
 | 
				
			||||||
 | 
					import org.junit.jupiter.api.Test
 | 
				
			||||||
 | 
					import sexpression.Nil
 | 
				
			||||||
 | 
					import testutil.LispTestInstance
 | 
				
			||||||
 | 
					import testutil.SymbolAndFunctionCleaner
 | 
				
			||||||
 | 
					import testutil.TestUtilities.assertIsErrorWithMessage
 | 
				
			||||||
 | 
					import testutil.TestUtilities.evaluateString
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@LispTestInstance
 | 
				
			||||||
 | 
					class SymbolFunctionTest : SymbolAndFunctionCleaner() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun symbolFunction_BuiltInFunction() {
 | 
				
			||||||
 | 
					        val input = "(symbol-function '+)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertThat(evaluateString(input).toString()).isEqualTo("#<FUNCTION +>")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun symbolFunction_BuiltInSpecialFunction() {
 | 
				
			||||||
 | 
					        val input = "(symbol-function 'if)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertThat(evaluateString(input).toString()).isEqualTo("#<SPECIAL-FUNCTION IF>")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun symbolFunction_UserDefinedFunction() {
 | 
				
			||||||
 | 
					        val defineUserFunction = "(defun y (n m) (+ n m))"
 | 
				
			||||||
 | 
					        val input = "(symbol-function 'y)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        evaluateString(defineUserFunction)
 | 
				
			||||||
 | 
					        assertThat(evaluateString(input).toString()).isEqualTo("(Y (N M) (+ N M))")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun symbolFunction_NonFunction() {
 | 
				
			||||||
 | 
					        val input = "(symbol-function 'a)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertThrows(UndefinedSymbolFunctionException::class.java) {
 | 
				
			||||||
 | 
					            evaluateString(input)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun symbolFunctionWithBadArgumentType() {
 | 
				
			||||||
 | 
					        assertThrows(BadArgumentTypeException::class.java) {
 | 
				
			||||||
 | 
					            evaluateString("(symbol-function 2)")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun symbolFunctionWithTooManyArguments() {
 | 
				
			||||||
 | 
					        assertThrows(TooManyArgumentsException::class.java) {
 | 
				
			||||||
 | 
					            evaluateString("(symbol-function 'a 'b)")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun symbolFunctionWithTooFewArguments() {
 | 
				
			||||||
 | 
					        assertThrows(TooFewArgumentsException::class.java) {
 | 
				
			||||||
 | 
					            evaluateString("(symbol-function)")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun undefinedSymbolFunctionException_HasCorrectAttributes() {
 | 
				
			||||||
 | 
					        assertIsErrorWithMessage(UndefinedSymbolFunctionException(Nil))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										60
									
								
								src/test/kotlin/function/builtin/SymbolsTest.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/test/kotlin/function/builtin/SymbolsTest.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					package function.builtin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import function.ArgumentValidator.TooManyArgumentsException
 | 
				
			||||||
 | 
					import org.junit.jupiter.api.Assertions.assertThrows
 | 
				
			||||||
 | 
					import org.junit.jupiter.api.Test
 | 
				
			||||||
 | 
					import testutil.LispTestInstance
 | 
				
			||||||
 | 
					import testutil.SymbolAndFunctionCleaner
 | 
				
			||||||
 | 
					import testutil.TestUtilities.assertSExpressionsMatch
 | 
				
			||||||
 | 
					import testutil.TestUtilities.evaluateString
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@LispTestInstance
 | 
				
			||||||
 | 
					class SymbolsTest : SymbolAndFunctionCleaner() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun noSymbols() {
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(evaluateString("'(nil)"), evaluateString("(symbols)"))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun globalSymbol() {
 | 
				
			||||||
 | 
					        evaluateString("(setq x 10)")
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(evaluateString("'(((x 10)))"), evaluateString("(symbols)"))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun multipleSymbolsSorted() {
 | 
				
			||||||
 | 
					        evaluateString("(setq x 10)")
 | 
				
			||||||
 | 
					        evaluateString("(setq a 20)")
 | 
				
			||||||
 | 
					        evaluateString("(setq y 30)")
 | 
				
			||||||
 | 
					        evaluateString("(setq w 40)")
 | 
				
			||||||
 | 
					        evaluateString("(setq e 50)")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(evaluateString("'(((a 20) (e 50) (w 40) (x 10) (y 30)))"), evaluateString("(symbols)"))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun fullExecutionContext() {
 | 
				
			||||||
 | 
					        evaluateString("(setq x 10)")
 | 
				
			||||||
 | 
					        evaluateString("(setq y 30)")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(evaluateString("'(((x 10) (y 30)) ((a 100) (q 99) (z nil)))"),
 | 
				
			||||||
 | 
					                                evaluateString("(let ((q 99) (a 100) (z)) (symbols))"))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun updateSymbolInLet() {
 | 
				
			||||||
 | 
					        evaluateString("(setq x 10)")
 | 
				
			||||||
 | 
					        evaluateString("(setq y 30)")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(evaluateString("'(((x 10) (y 30)) ((q 99) (x 1) (z 2)))"),
 | 
				
			||||||
 | 
					                                evaluateString("(let ((q 99) (x 100) (z 2)) (setq x 1) (symbols))"))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun symbolsWithTooManyArguments() {
 | 
				
			||||||
 | 
					        assertThrows(TooManyArgumentsException::class.java) {
 | 
				
			||||||
 | 
					            evaluateString("(symbols 1)")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,160 +0,0 @@
 | 
				
			|||||||
package function.builtin.predicate;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import function.ArgumentValidator.TooFewArgumentsException;
 | 
					 | 
				
			||||||
import function.ArgumentValidator.TooManyArgumentsException;
 | 
					 | 
				
			||||||
import org.junit.Test;
 | 
					 | 
				
			||||||
import testutil.SymbolAndFunctionCleaner;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import static testutil.TestUtilities.evaluateString;
 | 
					 | 
				
			||||||
import static testutil.TypeAssertions.assertNil;
 | 
					 | 
				
			||||||
import static testutil.TypeAssertions.assertT;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class GENSYM_EQUALTest extends SymbolAndFunctionCleaner {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymEqualWithTwoEqualAtoms() {
 | 
					 | 
				
			||||||
        String input = "(gensym-equal 'a 'a)";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertT(evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymEqualWithTwoEqualAtomsAndAlias() {
 | 
					 | 
				
			||||||
        String input = "(gensym-equal? 'a 'a)";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertT(evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymEqualWithTwoUnequalAtoms() {
 | 
					 | 
				
			||||||
        String input = "(gensym-equal 'a 'b)";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertNil(evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymEqualWithTwoEqualNumbers() {
 | 
					 | 
				
			||||||
        String input = "(gensym-equal -4 -4)";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertT(evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymEqualWithTwoUnequalNumbers() {
 | 
					 | 
				
			||||||
        String input = "(gensym-equal +5 +7)";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertNil(evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymEqualWithTwoEqualStrings() {
 | 
					 | 
				
			||||||
        String input = "(gensym-equal \"potato\" \"potato\")";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertT(evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymEqualWithTwoUnequalStrings() {
 | 
					 | 
				
			||||||
        String input = "(gensym-equal \"tomato\" \"potato\")";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertNil(evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymEqualWithTwoDifferentCasedStrings() {
 | 
					 | 
				
			||||||
        String input = "(gensym-equal \"Potato\" \"potato\")";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertNil(evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymEqualWithAtomAndList() {
 | 
					 | 
				
			||||||
        String input = "(gensym-equal \"string\" '(m i k e))";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertNil(evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymEqualWithListAndAtom() {
 | 
					 | 
				
			||||||
        String input = "(gensym-equal '(m i k e) \"string\")";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertNil(evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymEqualWithTwoEqualLists() {
 | 
					 | 
				
			||||||
        String input = "(gensym-equal '(1 2 3) '(1 2 3))";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertT(evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymEqualWithTwoUnequalLists() {
 | 
					 | 
				
			||||||
        String input = "(gensym-equal '(1 2 3) '(1 3 3))";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertNil(evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymEqualWithTwoEqualNestedLists() {
 | 
					 | 
				
			||||||
        String input = "(gensym-equal '(1 ((2) 3)) '(1 ((2) 3)))";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertT(evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test(expected = TooManyArgumentsException.class)
 | 
					 | 
				
			||||||
    public void gensymEqualWithTooManyArguments() {
 | 
					 | 
				
			||||||
        evaluateString("(gensym-equal 1 2 3)");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test(expected = TooFewArgumentsException.class)
 | 
					 | 
				
			||||||
    public void gensymEqualWithTooFewArguments() {
 | 
					 | 
				
			||||||
        evaluateString("(gensym-equal 1)");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymEqualWithGensyms() {
 | 
					 | 
				
			||||||
        String input = "(gensym-equal (gensym) (gensym))";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertT(evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymEqualWithNestedGensyms() {
 | 
					 | 
				
			||||||
        String input = "(gensym-equal `(1 ,(gensym) (2 ,(gensym))) `(1 ,(gensym) (2 ,(gensym))))";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertT(evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymEqualWithUnmatchedGensymPositions() {
 | 
					 | 
				
			||||||
        String input = "(gensym-equal (let ((one (gensym))) `(,one ,one))"
 | 
					 | 
				
			||||||
                       + " (let ((one (gensym)) (two (gensym))) `(,one ,two)))";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertNil(evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymEqualWithMatchedGensymPositions() {
 | 
					 | 
				
			||||||
        String input = "(gensym-equal (let ((one (gensym))) `(,one ,one))"
 | 
					 | 
				
			||||||
                       + " (let ((one (gensym)) (two (gensym))) `(,one ,one)))";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertT(evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymEqualWithComplexMatchedGensymPositions() {
 | 
					 | 
				
			||||||
        String input = "(gensym-equal (let ((x (gensym)) (y (gensym)) (z (gensym))) `(,x (,y ,z)))"
 | 
					 | 
				
			||||||
                       + " (let ((a (gensym)) (b (gensym)) (c (gensym))) `(,c (,a ,b))))";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertT(evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					 | 
				
			||||||
    public void gensymEqualWithComplexUnmatchedGensymPositions() {
 | 
					 | 
				
			||||||
        String input = "(gensym-equal (let ((x (gensym)) (y (gensym)) (z (gensym))) `(,x , y (,z ,z)))"
 | 
					 | 
				
			||||||
                       + " (let ((a (gensym)) (b (gensym)) (c (gensym))) `(,a ,c (,b ,c))))";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertNil(evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										166
									
								
								src/test/kotlin/function/builtin/predicate/GensymEqualTest.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								src/test/kotlin/function/builtin/predicate/GensymEqualTest.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,166 @@
 | 
				
			|||||||
 | 
					package function.builtin.predicate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import function.ArgumentValidator.TooFewArgumentsException
 | 
				
			||||||
 | 
					import function.ArgumentValidator.TooManyArgumentsException
 | 
				
			||||||
 | 
					import org.junit.jupiter.api.Assertions.assertThrows
 | 
				
			||||||
 | 
					import org.junit.jupiter.api.Test
 | 
				
			||||||
 | 
					import testutil.LispTestInstance
 | 
				
			||||||
 | 
					import testutil.SymbolAndFunctionCleaner
 | 
				
			||||||
 | 
					import testutil.TestUtilities.evaluateString
 | 
				
			||||||
 | 
					import testutil.TypeAssertions.assertNil
 | 
				
			||||||
 | 
					import testutil.TypeAssertions.assertT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@LispTestInstance
 | 
				
			||||||
 | 
					class GensymEqualTest : SymbolAndFunctionCleaner() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithTwoEqualAtoms() {
 | 
				
			||||||
 | 
					        val input = "(gensym-equal 'a 'a)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertT(evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithTwoEqualAtomsAndAlias() {
 | 
				
			||||||
 | 
					        val input = "(gensym-equal? 'a 'a)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertT(evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithTwoUnequalAtoms() {
 | 
				
			||||||
 | 
					        val input = "(gensym-equal 'a 'b)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertNil(evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithTwoEqualNumbers() {
 | 
				
			||||||
 | 
					        val input = "(gensym-equal -4 -4)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertT(evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithTwoUnequalNumbers() {
 | 
				
			||||||
 | 
					        val input = "(gensym-equal +5 +7)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertNil(evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithTwoEqualStrings() {
 | 
				
			||||||
 | 
					        val input = "(gensym-equal \"potato\" \"potato\")"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertT(evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithTwoUnequalStrings() {
 | 
				
			||||||
 | 
					        val input = "(gensym-equal \"tomato\" \"potato\")"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertNil(evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithTwoDifferentCasedStrings() {
 | 
				
			||||||
 | 
					        val input = "(gensym-equal \"Potato\" \"potato\")"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertNil(evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithAtomAndList() {
 | 
				
			||||||
 | 
					        val input = "(gensym-equal \"string\" '(m i k e))"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertNil(evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithListAndAtom() {
 | 
				
			||||||
 | 
					        val input = "(gensym-equal '(m i k e) \"string\")"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertNil(evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithTwoEqualLists() {
 | 
				
			||||||
 | 
					        val input = "(gensym-equal '(1 2 3) '(1 2 3))"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertT(evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithTwoUnequalLists() {
 | 
				
			||||||
 | 
					        val input = "(gensym-equal '(1 2 3) '(1 3 3))"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertNil(evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithTwoEqualNestedLists() {
 | 
				
			||||||
 | 
					        val input = "(gensym-equal '(1 ((2) 3)) '(1 ((2) 3)))"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertT(evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithTooManyArguments() {
 | 
				
			||||||
 | 
					        assertThrows(TooManyArgumentsException::class.java) {
 | 
				
			||||||
 | 
					            evaluateString("(gensym-equal 1 2 3)")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithTooFewArguments() {
 | 
				
			||||||
 | 
					        assertThrows(TooFewArgumentsException::class.java) {
 | 
				
			||||||
 | 
					            evaluateString("(gensym-equal 1)")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithGensyms() {
 | 
				
			||||||
 | 
					        val input = "(gensym-equal (gensym) (gensym))"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertT(evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithNestedGensyms() {
 | 
				
			||||||
 | 
					        val input = "(gensym-equal `(1 ,(gensym) (2 ,(gensym))) `(1 ,(gensym) (2 ,(gensym))))"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertT(evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithUnmatchedGensymPositions() {
 | 
				
			||||||
 | 
					        val input = "(gensym-equal (let ((one (gensym))) `(,one ,one))" +
 | 
				
			||||||
 | 
					                " (let ((one (gensym)) (two (gensym))) `(,one ,two)))"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertNil(evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithMatchedGensymPositions() {
 | 
				
			||||||
 | 
					        val input = "(gensym-equal (let ((one (gensym))) `(,one ,one))" +
 | 
				
			||||||
 | 
					                " (let ((one (gensym)) (two (gensym))) `(,one ,one)))"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertT(evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithComplexMatchedGensymPositions() {
 | 
				
			||||||
 | 
					        val input = "(gensym-equal (let ((x (gensym)) (y (gensym)) (z (gensym))) `(,x (,y ,z)))" +
 | 
				
			||||||
 | 
					                " (let ((a (gensym)) (b (gensym)) (c (gensym))) `(,c (,a ,b))))"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertT(evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun gensymEqualWithComplexUnmatchedGensymPositions() {
 | 
				
			||||||
 | 
					        val input = "(gensym-equal (let ((x (gensym)) (y (gensym)) (z (gensym))) `(,x , y (,z ,z)))" +
 | 
				
			||||||
 | 
					                " (let ((a (gensym)) (b (gensym)) (c (gensym))) `(,a ,c (,b ,c))))"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertNil(evaluateString(input))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user