Convert And and Or to kotlin
This commit is contained in:
parent
ac821abde2
commit
8ca2eb199c
|
@ -1,43 +0,0 @@
|
||||||
package function.builtin.special;
|
|
||||||
|
|
||||||
import function.ArgumentValidator;
|
|
||||||
import function.FunctionNames;
|
|
||||||
import function.LispSpecialFunction;
|
|
||||||
import recursion.TailCall;
|
|
||||||
import sexpression.Cons;
|
|
||||||
import sexpression.SExpression;
|
|
||||||
import sexpression.Symbol;
|
|
||||||
|
|
||||||
import static function.builtin.Eval.eval;
|
|
||||||
import static recursion.TailCalls.done;
|
|
||||||
import static recursion.TailCalls.tailCall;
|
|
||||||
|
|
||||||
@FunctionNames({ "AND" })
|
|
||||||
public class AND extends LispSpecialFunction {
|
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
|
||||||
|
|
||||||
public AND(String name) {
|
|
||||||
this.argumentValidator = new ArgumentValidator(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SExpression call(Cons argumentList) {
|
|
||||||
argumentValidator.validate(argumentList);
|
|
||||||
|
|
||||||
return callTailRecursive(argumentList, Symbol.Companion.getT()).invoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TailCall<SExpression> callTailRecursive(Cons argumentList, SExpression lastValue) {
|
|
||||||
SExpression currentValue = eval(argumentList.getFirst());
|
|
||||||
Cons remainingValues = (Cons) argumentList.getRest();
|
|
||||||
|
|
||||||
if (argumentList.isNull())
|
|
||||||
return done(lastValue);
|
|
||||||
|
|
||||||
if (currentValue.isNull())
|
|
||||||
return done(currentValue);
|
|
||||||
|
|
||||||
return tailCall(() -> callTailRecursive(remainingValues, currentValue));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package function.builtin.special
|
||||||
|
|
||||||
|
import function.ArgumentValidator
|
||||||
|
import function.FunctionNames
|
||||||
|
import function.LispSpecialFunction
|
||||||
|
import function.builtin.Eval.Companion.eval
|
||||||
|
import sexpression.Cons
|
||||||
|
import sexpression.SExpression
|
||||||
|
import sexpression.Symbol.Companion.T
|
||||||
|
|
||||||
|
@FunctionNames("AND")
|
||||||
|
class And(name: String) : LispSpecialFunction() {
|
||||||
|
|
||||||
|
private val argumentValidator = ArgumentValidator(name)
|
||||||
|
|
||||||
|
override fun call(argumentList: Cons): SExpression {
|
||||||
|
argumentValidator.validate(argumentList)
|
||||||
|
|
||||||
|
return callTailRecursive(argumentList, T)
|
||||||
|
}
|
||||||
|
|
||||||
|
private tailrec fun callTailRecursive(argumentList: Cons, lastValue: SExpression): SExpression {
|
||||||
|
val currentValue = eval(argumentList.first)
|
||||||
|
val remainingValues = argumentList.rest as Cons
|
||||||
|
|
||||||
|
return when {
|
||||||
|
argumentList.isNull -> lastValue
|
||||||
|
currentValue.isNull -> currentValue
|
||||||
|
else -> callTailRecursive(remainingValues, currentValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,39 +0,0 @@
|
||||||
package function.builtin.special;
|
|
||||||
|
|
||||||
import function.ArgumentValidator;
|
|
||||||
import function.FunctionNames;
|
|
||||||
import function.LispSpecialFunction;
|
|
||||||
import recursion.TailCall;
|
|
||||||
import sexpression.Cons;
|
|
||||||
import sexpression.SExpression;
|
|
||||||
|
|
||||||
import static function.builtin.Eval.eval;
|
|
||||||
import static recursion.TailCalls.done;
|
|
||||||
import static recursion.TailCalls.tailCall;
|
|
||||||
|
|
||||||
@FunctionNames({ "OR" })
|
|
||||||
public class OR extends LispSpecialFunction {
|
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
|
||||||
|
|
||||||
public OR(String name) {
|
|
||||||
this.argumentValidator = new ArgumentValidator(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SExpression call(Cons argumentList) {
|
|
||||||
argumentValidator.validate(argumentList);
|
|
||||||
|
|
||||||
return callTailRecursive(argumentList).invoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TailCall<SExpression> callTailRecursive(Cons argumentList) {
|
|
||||||
SExpression currentValue = eval(argumentList.getFirst());
|
|
||||||
Cons remainingValues = (Cons) argumentList.getRest();
|
|
||||||
|
|
||||||
if (remainingValues.isNull() || !currentValue.isNull())
|
|
||||||
return done(currentValue);
|
|
||||||
|
|
||||||
return tailCall(() -> callTailRecursive(remainingValues));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
package function.builtin.special
|
||||||
|
|
||||||
|
import function.ArgumentValidator
|
||||||
|
import function.FunctionNames
|
||||||
|
import function.LispSpecialFunction
|
||||||
|
import function.builtin.Eval.Companion.eval
|
||||||
|
import sexpression.Cons
|
||||||
|
import sexpression.SExpression
|
||||||
|
|
||||||
|
@FunctionNames("OR")
|
||||||
|
class Or(name: String) : LispSpecialFunction() {
|
||||||
|
|
||||||
|
private val argumentValidator = ArgumentValidator(name)
|
||||||
|
|
||||||
|
override fun call(argumentList: Cons): SExpression {
|
||||||
|
argumentValidator.validate(argumentList)
|
||||||
|
|
||||||
|
return callTailRecursive(argumentList)
|
||||||
|
}
|
||||||
|
|
||||||
|
private tailrec fun callTailRecursive(argumentList: Cons): SExpression {
|
||||||
|
val currentValue = eval(argumentList.first)
|
||||||
|
val remainingValues = argumentList.rest as Cons
|
||||||
|
|
||||||
|
return if (remainingValues.isNull || !currentValue.isNull)
|
||||||
|
currentValue
|
||||||
|
else
|
||||||
|
callTailRecursive(remainingValues)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,64 +0,0 @@
|
||||||
package function.builtin.special;
|
|
||||||
|
|
||||||
import function.builtin.Eval.UndefinedSymbolException;
|
|
||||||
import org.junit.Test;
|
|
||||||
import sexpression.LispNumber;
|
|
||||||
import testutil.SymbolAndFunctionCleaner;
|
|
||||||
|
|
||||||
import static testutil.TestUtilities.assertSExpressionsMatch;
|
|
||||||
import static testutil.TestUtilities.evaluateString;
|
|
||||||
import static testutil.TypeAssertions.assertNil;
|
|
||||||
import static testutil.TypeAssertions.assertT;
|
|
||||||
|
|
||||||
public class ANDTest extends SymbolAndFunctionCleaner {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void andByItself() {
|
|
||||||
String input = "(and)";
|
|
||||||
|
|
||||||
assertT(evaluateString(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void andWithNil() {
|
|
||||||
String input = "(and nil)";
|
|
||||||
|
|
||||||
assertNil(evaluateString(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void andWithT() {
|
|
||||||
String input = "(and t)";
|
|
||||||
|
|
||||||
assertT(evaluateString(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void andWithNumber() {
|
|
||||||
String input = "(and 7)";
|
|
||||||
|
|
||||||
assertSExpressionsMatch(new LispNumber("7"), evaluateString(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void andWithSeveralValues() {
|
|
||||||
String input = "(and t t nil t t)";
|
|
||||||
|
|
||||||
assertNil(evaluateString(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void andWithSeveralNumbers() {
|
|
||||||
String input = "(and 1 2 3)";
|
|
||||||
|
|
||||||
assertSExpressionsMatch(new LispNumber("3"), evaluateString(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = UndefinedSymbolException.class)
|
|
||||||
public void andShortCircuits() {
|
|
||||||
String input = "(and nil (setq x 22))";
|
|
||||||
|
|
||||||
assertNil(evaluateString(input));
|
|
||||||
evaluateString("x");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
package function.builtin.special
|
||||||
|
|
||||||
|
import function.builtin.Eval.UndefinedSymbolException
|
||||||
|
import org.junit.jupiter.api.Assertions.assertThrows
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import sexpression.LispNumber
|
||||||
|
import testutil.LispTestInstance
|
||||||
|
import testutil.SymbolAndFunctionCleaner
|
||||||
|
import testutil.TestUtilities.assertSExpressionsMatch
|
||||||
|
import testutil.TestUtilities.evaluateString
|
||||||
|
import testutil.TypeAssertions.assertNil
|
||||||
|
import testutil.TypeAssertions.assertT
|
||||||
|
|
||||||
|
@LispTestInstance
|
||||||
|
class AndTest : SymbolAndFunctionCleaner() {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun andByItself() {
|
||||||
|
val input = "(and)"
|
||||||
|
|
||||||
|
assertT(evaluateString(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun andWithNil() {
|
||||||
|
val input = "(and nil)"
|
||||||
|
|
||||||
|
assertNil(evaluateString(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun andWithT() {
|
||||||
|
val input = "(and t)"
|
||||||
|
|
||||||
|
assertT(evaluateString(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun andWithNumber() {
|
||||||
|
val input = "(and 7)"
|
||||||
|
|
||||||
|
assertSExpressionsMatch(LispNumber("7"), evaluateString(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun andWithSeveralValues() {
|
||||||
|
val input = "(and t t nil t t)"
|
||||||
|
|
||||||
|
assertNil(evaluateString(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun andWithSeveralNumbers() {
|
||||||
|
val input = "(and 1 2 3)"
|
||||||
|
|
||||||
|
assertSExpressionsMatch(LispNumber("3"), evaluateString(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun andShortCircuits() {
|
||||||
|
val input = "(and nil (setq x 22))"
|
||||||
|
|
||||||
|
assertNil(evaluateString(input))
|
||||||
|
|
||||||
|
assertThrows(UndefinedSymbolException::class.java) {
|
||||||
|
evaluateString("x")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,11 +16,13 @@ import sexpression.LispNumber.Companion.ONE
|
||||||
import sexpression.Nil
|
import sexpression.Nil
|
||||||
import sexpression.Symbol
|
import sexpression.Symbol
|
||||||
import sexpression.Symbol.Companion.T
|
import sexpression.Symbol.Companion.T
|
||||||
|
import testutil.LispTestInstance
|
||||||
import testutil.SymbolAndFunctionCleaner
|
import testutil.SymbolAndFunctionCleaner
|
||||||
import testutil.TestUtilities.assertSExpressionsMatch
|
import testutil.TestUtilities.assertSExpressionsMatch
|
||||||
import testutil.TestUtilities.evaluateString
|
import testutil.TestUtilities.evaluateString
|
||||||
import testutil.TestUtilities.parseString
|
import testutil.TestUtilities.parseString
|
||||||
|
|
||||||
|
@LispTestInstance
|
||||||
class LambdaTest : SymbolAndFunctionCleaner() {
|
class LambdaTest : SymbolAndFunctionCleaner() {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
package function.builtin.special;
|
|
||||||
|
|
||||||
import function.builtin.Eval.UndefinedSymbolException;
|
|
||||||
import org.junit.Test;
|
|
||||||
import sexpression.LispNumber;
|
|
||||||
import testutil.SymbolAndFunctionCleaner;
|
|
||||||
|
|
||||||
import static testutil.TestUtilities.assertSExpressionsMatch;
|
|
||||||
import static testutil.TestUtilities.evaluateString;
|
|
||||||
import static testutil.TypeAssertions.assertNil;
|
|
||||||
import static testutil.TypeAssertions.assertT;
|
|
||||||
|
|
||||||
public class ORTest extends SymbolAndFunctionCleaner {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void orByItself() {
|
|
||||||
String input = "(or)";
|
|
||||||
|
|
||||||
assertNil(evaluateString(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void orWithNil() {
|
|
||||||
String input = "(or nil)";
|
|
||||||
|
|
||||||
assertNil(evaluateString(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void orWithT() {
|
|
||||||
String input = "(or t)";
|
|
||||||
|
|
||||||
assertT(evaluateString(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void orWithNumber() {
|
|
||||||
String input = "(or 7)";
|
|
||||||
|
|
||||||
assertSExpressionsMatch(new LispNumber("7"), evaluateString(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void orWithSeveralValues() {
|
|
||||||
String input = "(or nil nil nil t nil)";
|
|
||||||
|
|
||||||
assertT(evaluateString(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void orWithSeveralNumbers() {
|
|
||||||
String input = "(or 1 2 3)";
|
|
||||||
|
|
||||||
assertSExpressionsMatch(new LispNumber("1"), evaluateString(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = UndefinedSymbolException.class)
|
|
||||||
public void orShortCircuits() {
|
|
||||||
String input = "(or t (setq x 22))";
|
|
||||||
|
|
||||||
assertT(evaluateString(input));
|
|
||||||
evaluateString("x");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
package function.builtin.special
|
||||||
|
|
||||||
|
import function.builtin.Eval.UndefinedSymbolException
|
||||||
|
import org.junit.jupiter.api.Assertions.assertThrows
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import sexpression.LispNumber
|
||||||
|
import testutil.LispTestInstance
|
||||||
|
import testutil.SymbolAndFunctionCleaner
|
||||||
|
import testutil.TestUtilities.assertSExpressionsMatch
|
||||||
|
import testutil.TestUtilities.evaluateString
|
||||||
|
import testutil.TypeAssertions.assertNil
|
||||||
|
import testutil.TypeAssertions.assertT
|
||||||
|
|
||||||
|
@LispTestInstance
|
||||||
|
class OrTest : SymbolAndFunctionCleaner() {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun orByItself() {
|
||||||
|
val input = "(or)"
|
||||||
|
|
||||||
|
assertNil(evaluateString(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun orWithNil() {
|
||||||
|
val input = "(or nil)"
|
||||||
|
|
||||||
|
assertNil(evaluateString(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun orWithT() {
|
||||||
|
val input = "(or t)"
|
||||||
|
|
||||||
|
assertT(evaluateString(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun orWithNumber() {
|
||||||
|
val input = "(or 7)"
|
||||||
|
|
||||||
|
assertSExpressionsMatch(LispNumber("7"), evaluateString(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun orWithSeveralValues() {
|
||||||
|
val input = "(or nil nil nil t nil)"
|
||||||
|
|
||||||
|
assertT(evaluateString(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun orWithSeveralNumbers() {
|
||||||
|
val input = "(or 1 2 3)"
|
||||||
|
|
||||||
|
assertSExpressionsMatch(LispNumber("1"), evaluateString(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun orShortCircuits() {
|
||||||
|
val input = "(or t (setq x 22))"
|
||||||
|
|
||||||
|
assertT(evaluateString(input))
|
||||||
|
|
||||||
|
assertThrows(UndefinedSymbolException::class.java) {
|
||||||
|
evaluateString("x")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,94 +0,0 @@
|
||||||
package function.builtin.special;
|
|
||||||
|
|
||||||
import function.ArgumentValidator.BadArgumentTypeException;
|
|
||||||
import function.ArgumentValidator.TooFewArgumentsException;
|
|
||||||
import function.ArgumentValidator.TooManyArgumentsException;
|
|
||||||
import function.builtin.Eval.UndefinedSymbolException;
|
|
||||||
import org.junit.Test;
|
|
||||||
import sexpression.LispNumber;
|
|
||||||
import table.SymbolTable;
|
|
||||||
import testutil.SymbolAndFunctionCleaner;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
import static testutil.TestUtilities.assertSExpressionsMatch;
|
|
||||||
import static testutil.TestUtilities.evaluateString;
|
|
||||||
|
|
||||||
public class SetqTest extends SymbolAndFunctionCleaner {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void setq() {
|
|
||||||
evaluateString("(setq a 23)");
|
|
||||||
assertSExpressionsMatch(new LispNumber("23"), evaluateString("a"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void lookupDefinedSymbol() {
|
|
||||||
evaluateString("(setq a 23)");
|
|
||||||
assertSExpressionsMatch(new LispNumber("23"), getExecutionContext().lookupSymbolValue("A"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void lookupUndefinedSymbol() {
|
|
||||||
assertNull(getExecutionContext().lookupSymbolValue("A"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void setqGlobalVariable() {
|
|
||||||
evaluateString("(setq a 23)");
|
|
||||||
SymbolTable global = getExecutionContext().getScope();
|
|
||||||
getExecutionContext().setScope(new SymbolTable(global));
|
|
||||||
|
|
||||||
evaluateString("(setq a 94)");
|
|
||||||
getExecutionContext().setScope(global);
|
|
||||||
assertSExpressionsMatch(new LispNumber("94"), evaluateString("a"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void setqLocalVariable() {
|
|
||||||
SymbolTable global = getExecutionContext().getScope();
|
|
||||||
SymbolTable local = new SymbolTable(global);
|
|
||||||
local.set("A", new LispNumber("99"));
|
|
||||||
getExecutionContext().setScope(local);
|
|
||||||
|
|
||||||
evaluateString("(setq a 94)");
|
|
||||||
assertSExpressionsMatch(new LispNumber("94"), evaluateString("a"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = UndefinedSymbolException.class)
|
|
||||||
public void setqLocalVariableDefined_DoesNotSetGlobal() {
|
|
||||||
SymbolTable global = getExecutionContext().getScope();
|
|
||||||
SymbolTable local = new SymbolTable(global);
|
|
||||||
local.set("A", new LispNumber("99"));
|
|
||||||
getExecutionContext().setScope(local);
|
|
||||||
|
|
||||||
evaluateString("(setq a 94)");
|
|
||||||
getExecutionContext().setScope(global);
|
|
||||||
evaluateString("a");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void setqLocalVariableUndefined_SetsGlobal() {
|
|
||||||
SymbolTable global = getExecutionContext().getScope();
|
|
||||||
SymbolTable local = new SymbolTable(global);
|
|
||||||
getExecutionContext().setScope(local);
|
|
||||||
|
|
||||||
evaluateString("(setq a 94)");
|
|
||||||
getExecutionContext().setScope(global);
|
|
||||||
assertSExpressionsMatch(new LispNumber("94"), evaluateString("a"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = BadArgumentTypeException.class)
|
|
||||||
public void setqWithNonSymbol() {
|
|
||||||
evaluateString("(setq 1 2)");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = TooFewArgumentsException.class)
|
|
||||||
public void setqWithTooFewArguments() {
|
|
||||||
evaluateString("(setq x)");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = TooManyArgumentsException.class)
|
|
||||||
public void setqWithTooManyArguments() {
|
|
||||||
evaluateString("(setq a b c)");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
package function.builtin.special
|
||||||
|
|
||||||
|
import function.ArgumentValidator.BadArgumentTypeException
|
||||||
|
import function.ArgumentValidator.TooFewArgumentsException
|
||||||
|
import function.ArgumentValidator.TooManyArgumentsException
|
||||||
|
import function.builtin.Eval.UndefinedSymbolException
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.junit.jupiter.api.Assertions.assertThrows
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import sexpression.LispNumber
|
||||||
|
import table.SymbolTable
|
||||||
|
import testutil.LispTestInstance
|
||||||
|
import testutil.SymbolAndFunctionCleaner
|
||||||
|
import testutil.TestUtilities.assertSExpressionsMatch
|
||||||
|
import testutil.TestUtilities.evaluateString
|
||||||
|
|
||||||
|
@LispTestInstance
|
||||||
|
class SetqTest : SymbolAndFunctionCleaner() {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun setq() {
|
||||||
|
evaluateString("(setq a 23)")
|
||||||
|
assertSExpressionsMatch(LispNumber("23"), evaluateString("a"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun lookupDefinedSymbol() {
|
||||||
|
evaluateString("(setq a 23)")
|
||||||
|
assertSExpressionsMatch(LispNumber("23"), executionContext.lookupSymbolValue("A")!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun lookupUndefinedSymbol() {
|
||||||
|
assertThat(executionContext.lookupSymbolValue("A")).isNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun setqGlobalVariable() {
|
||||||
|
evaluateString("(setq a 23)")
|
||||||
|
val global = executionContext.scope
|
||||||
|
executionContext.scope = SymbolTable(global)
|
||||||
|
|
||||||
|
evaluateString("(setq a 94)")
|
||||||
|
executionContext.scope = global
|
||||||
|
assertSExpressionsMatch(LispNumber("94"), evaluateString("a"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun setqLocalVariable() {
|
||||||
|
val global = executionContext.scope
|
||||||
|
val local = SymbolTable(global)
|
||||||
|
local["A"] = LispNumber("99")
|
||||||
|
executionContext.scope = local
|
||||||
|
|
||||||
|
evaluateString("(setq a 94)")
|
||||||
|
assertSExpressionsMatch(LispNumber("94"), evaluateString("a"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun setqLocalVariableDefined_DoesNotSetGlobal() {
|
||||||
|
val global = executionContext.scope
|
||||||
|
val local = SymbolTable(global)
|
||||||
|
local["A"] = LispNumber("99")
|
||||||
|
executionContext.scope = local
|
||||||
|
|
||||||
|
evaluateString("(setq a 94)")
|
||||||
|
executionContext.scope = global
|
||||||
|
|
||||||
|
assertThrows(UndefinedSymbolException::class.java) {
|
||||||
|
evaluateString("a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun setqLocalVariableUndefined_SetsGlobal() {
|
||||||
|
val global = executionContext.scope
|
||||||
|
val local = SymbolTable(global)
|
||||||
|
executionContext.scope = local
|
||||||
|
|
||||||
|
evaluateString("(setq a 94)")
|
||||||
|
executionContext.scope = global
|
||||||
|
assertSExpressionsMatch(LispNumber("94"), evaluateString("a"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun setqWithNonSymbol() {
|
||||||
|
assertThrows(BadArgumentTypeException::class.java) {
|
||||||
|
evaluateString("(setq 1 2)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun setqWithTooFewArguments() {
|
||||||
|
assertThrows(TooFewArgumentsException::class.java) {
|
||||||
|
evaluateString("(setq x)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun setqWithTooManyArguments() {
|
||||||
|
assertThrows(TooManyArgumentsException::class.java) {
|
||||||
|
evaluateString("(setq a b c)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue