2017-02-04 12:03:16 -05:00
|
|
|
package function.builtin.special;
|
|
|
|
|
2017-03-02 09:54:23 -05:00
|
|
|
import static sexpression.Nil.NIL;
|
2017-02-04 12:03:16 -05:00
|
|
|
import static testutil.TestUtilities.*;
|
|
|
|
|
|
|
|
import org.junit.*;
|
|
|
|
|
|
|
|
import function.ArgumentValidator.*;
|
|
|
|
import function.builtin.EVAL.UndefinedSymbolException;
|
2017-03-02 09:54:23 -05:00
|
|
|
import sexpression.LispNumber;
|
2017-02-04 12:03:16 -05:00
|
|
|
import table.ExecutionContext;
|
|
|
|
|
|
|
|
public class LETTester {
|
|
|
|
|
|
|
|
private ExecutionContext executionContext;
|
|
|
|
|
|
|
|
public LETTester() {
|
|
|
|
this.executionContext = ExecutionContext.getInstance();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Before
|
|
|
|
public void setUp() {
|
|
|
|
executionContext.clearContext();
|
|
|
|
}
|
|
|
|
|
2017-02-05 16:00:56 -05:00
|
|
|
@After
|
|
|
|
public void tearDown() {
|
|
|
|
executionContext.clearContext();
|
|
|
|
}
|
|
|
|
|
2017-02-04 12:03:16 -05:00
|
|
|
@Test
|
|
|
|
public void simpleLet() {
|
|
|
|
String input = "(let ((x 1)) x)";
|
|
|
|
|
|
|
|
assertSExpressionsMatch(new LispNumber("1"), evaluateString(input));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void emptyLet_ReturnsNil() {
|
|
|
|
String input = "(let ())";
|
|
|
|
|
2017-03-02 09:54:23 -05:00
|
|
|
assertSExpressionsMatch(NIL, evaluateString(input));
|
2017-02-04 12:03:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void letWithSetf_DoesNotAlterGlobalVariable() {
|
|
|
|
String before = "(setf 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 letWithNestedSetf_DoesNotAlterGlobalVariable() {
|
|
|
|
String before = "(setf x 22)";
|
|
|
|
String input = "(let ((x 33)) (setf 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));
|
|
|
|
}
|
|
|
|
|
2017-02-04 13:51:10 -05:00
|
|
|
@Test
|
|
|
|
public void nestedLetWithGlobals() {
|
|
|
|
String before = "(setf 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));
|
|
|
|
}
|
|
|
|
|
2017-02-04 12:03:16 -05:00
|
|
|
@Test
|
|
|
|
public void alterGlobalVariableFromLet() {
|
|
|
|
String before = "(setf x 1)";
|
|
|
|
String input = "(let ((y 1)) (setf 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 = "(setf x 1)";
|
|
|
|
String input = "(let () x)";
|
|
|
|
|
|
|
|
assertSExpressionsMatch(new LispNumber("1"), evaluateString(before));
|
|
|
|
assertSExpressionsMatch(new LispNumber("1"), evaluateString(input));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test(expected = UndefinedSymbolException.class)
|
|
|
|
public void letDoesNotSetGlobalVariable() {
|
|
|
|
String input = "(let ((x 1)) nil)";
|
|
|
|
|
|
|
|
evaluateString(input);
|
|
|
|
evaluateString("x");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test(expected = BadArgumentTypeException.class)
|
2017-02-28 15:01:05 -05:00
|
|
|
public void letWithNonList() {
|
2017-02-04 12:03:16 -05:00
|
|
|
evaluateString("(let a)");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test(expected = BadArgumentTypeException.class)
|
2017-02-28 15:01:05 -05:00
|
|
|
public void letWithNoPairs() {
|
2017-02-04 12:03:16 -05:00
|
|
|
evaluateString("(let (a))");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test(expected = TooFewArgumentsException.class)
|
2017-02-28 15:01:05 -05:00
|
|
|
public void letWithTooFewItemsInPair() {
|
2017-02-04 12:03:16 -05:00
|
|
|
evaluateString("(let ((a)))");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test(expected = TooManyArgumentsException.class)
|
2017-02-28 15:01:05 -05:00
|
|
|
public void letWithTooManyItemsInPair() {
|
2017-02-04 12:03:16 -05:00
|
|
|
evaluateString("(let ((a b c)))");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test(expected = BadArgumentTypeException.class)
|
2017-02-28 15:01:05 -05:00
|
|
|
public void letWithNonSymbolInPair() {
|
2017-02-04 12:03:16 -05:00
|
|
|
evaluateString("(let ((1 b)))");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test(expected = TooFewArgumentsException.class)
|
2017-02-28 15:01:05 -05:00
|
|
|
public void letWithTooFewArguments() {
|
2017-02-04 12:03:16 -05:00
|
|
|
evaluateString("(let)");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test(expected = DottedArgumentListException.class)
|
2017-02-28 15:01:05 -05:00
|
|
|
public void letWithDottedArgumentList() {
|
2017-02-04 12:03:16 -05:00
|
|
|
evaluateString("(apply 'let (cons 'a 'b))");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test(expected = DottedArgumentListException.class)
|
2017-02-28 15:01:05 -05:00
|
|
|
public void letWithDottedPairList() {
|
2017-02-04 12:03:16 -05:00
|
|
|
evaluateString("(apply 'let (cons (cons 'a 'b) nil))");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test(expected = DottedArgumentListException.class)
|
2017-02-28 15:01:05 -05:00
|
|
|
public void letWithDottedPair() {
|
2017-02-04 12:03:16 -05:00
|
|
|
evaluateString("(apply 'let (cons (cons (cons 'a 'b) nil) nil))");
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|