package function.builtin.special; import static sexpression.Nil.NIL; import static testutil.TestUtilities.*; import org.junit.*; import function.ArgumentValidator.*; import function.builtin.EVAL.UndefinedSymbolException; import sexpression.*; import table.ExecutionContext; public class LET_STARTester { private ExecutionContext executionContext; public LET_STARTester() { this.executionContext = ExecutionContext.getInstance(); } @Before public void setUp() { executionContext.clearContext(); } @After public void tearDown() { executionContext.clearContext(); } @Test public void simpleLet() { String input = "(let* ((x 1)) x)"; assertSExpressionsMatch(new LispNumber("1"), evaluateString(input)); } @Test public void emptyLet_ReturnsNil() { String input = "(let* ())"; assertSExpressionsMatch(NIL, evaluateString(input)); } @Test public void letStarWithSymbolsOnly_SetsValuesToNil() { String input = "(let* ((x) (y)) (list x y))"; assertSExpressionsMatch(new Cons(NIL, new Cons(NIL, NIL)), evaluateString(input)); } @Test public void letStarWithSetf_DoesNotAlterGlobalVariable() { String before = "(setq x 22)"; String input = "(let* ((x 1)) x)"; String after = "x"; assertSExpressionsMatch(new LispNumber("22"), evaluateString(before)); assertSExpressionsMatch(new LispNumber("1"), evaluateString(input)); assertSExpressionsMatch(new LispNumber("22"), evaluateString(after)); } @Test public void letStarWithNestedSetf_DoesNotAlterGlobalVariable() { String before = "(setq x 22)"; String input = "(let* ((x 33)) (setq x 44) x)"; String after = "x"; assertSExpressionsMatch(new LispNumber("22"), evaluateString(before)); assertSExpressionsMatch(new LispNumber("44"), evaluateString(input)); assertSExpressionsMatch(new LispNumber("22"), evaluateString(after)); } @Test public void nestedLet() { String input = "(let* ((x 1)) (let* ((y (+ 1 x))) y))"; assertSExpressionsMatch(new LispNumber("2"), evaluateString(input)); } @Test public void nestedLetWithGlobals() { String before = "(setq x 92)"; String input = "(let* ((x 1)) (let* ((y (+ 1 x))) y))"; String after = "x"; assertSExpressionsMatch(new LispNumber("92"), evaluateString(before)); assertSExpressionsMatch(new LispNumber("2"), evaluateString(input)); assertSExpressionsMatch(new LispNumber("92"), evaluateString(after)); } @Test public void alterGlobalVariableFromLet() { String before = "(setq x 1)"; String input = "(let* ((y 1)) (setq x 2))"; String after = "x"; assertSExpressionsMatch(new LispNumber("1"), evaluateString(before)); assertSExpressionsMatch(new LispNumber("2"), evaluateString(input)); assertSExpressionsMatch(new LispNumber("2"), evaluateString(after)); } @Test public void accessGlobalVariableFromLet() { String before = "(setq x 1)"; String input = "(let* () x)"; assertSExpressionsMatch(new LispNumber("1"), evaluateString(before)); assertSExpressionsMatch(new LispNumber("1"), evaluateString(input)); } @Test(expected = UndefinedSymbolException.class) public void letStarDoesNotSetGlobalVariable() { String input = "(let* ((x 1)) nil)"; evaluateString(input); evaluateString("x"); } @Test(expected = BadArgumentTypeException.class) public void letStarWithNonList() { evaluateString("(let* a)"); } @Test(expected = BadArgumentTypeException.class) public void letStarWithNoPairs() { evaluateString("(let* (a))"); } @Test(expected = TooFewArgumentsException.class) public void letStarWithTooFewItemsInPair() { evaluateString("(let* (()))"); } @Test(expected = TooManyArgumentsException.class) public void letStarWithTooManyItemsInPair() { evaluateString("(let* ((a b c)))"); } @Test(expected = BadArgumentTypeException.class) public void letStarWithNonSymbolInPair() { evaluateString("(let* ((1 b)))"); } @Test(expected = TooFewArgumentsException.class) public void letStarWithTooFewArguments() { evaluateString("(let*)"); } @Test(expected = DottedArgumentListException.class) public void letStarWithDottedArgumentList() { evaluateString("(apply 'let* (cons 'a 'b))"); } @Test(expected = DottedArgumentListException.class) public void letStarWithDottedPairList() { evaluateString("(apply 'let* (cons (cons 'a 'b) nil))"); } @Test(expected = DottedArgumentListException.class) public void letStarWithDottedPair() { evaluateString("(apply 'let* (cons (cons (cons 'a 'b) nil) nil))"); } @Test public void letStarEvaluatesSymbolsInSequence() { String input = "(let* ((x 1) (y (+ x 1))) (+ x y))"; assertSExpressionsMatch(new LispNumber("3"), evaluateString(input)); } }