2017-01-27 14:31:41 -05:00
|
|
|
package function.builtin.special;
|
|
|
|
|
2017-11-12 09:42:25 -05:00
|
|
|
import static org.junit.Assert.assertFalse;
|
|
|
|
import static org.junit.Assert.assertTrue;
|
2017-03-02 09:54:23 -05:00
|
|
|
import static sexpression.LispNumber.ONE;
|
|
|
|
import static sexpression.Nil.NIL;
|
|
|
|
import static sexpression.Symbol.T;
|
2017-11-12 09:42:25 -05:00
|
|
|
import static testutil.TestUtilities.assertSExpressionsMatch;
|
|
|
|
import static testutil.TestUtilities.evaluateString;
|
|
|
|
import static testutil.TestUtilities.parseString;
|
2017-01-27 14:31:41 -05:00
|
|
|
|
|
|
|
import org.junit.Test;
|
|
|
|
|
2017-11-12 09:42:25 -05:00
|
|
|
import function.ArgumentValidator.BadArgumentTypeException;
|
|
|
|
import function.ArgumentValidator.DottedArgumentListException;
|
|
|
|
import function.ArgumentValidator.TooFewArgumentsException;
|
|
|
|
import function.ArgumentValidator.TooManyArgumentsException;
|
2018-03-15 18:48:33 -04:00
|
|
|
import function.builtin.EVAL.UndefinedFunctionException;
|
2017-11-12 09:42:25 -05:00
|
|
|
import sexpression.Cons;
|
|
|
|
import sexpression.LispNumber;
|
|
|
|
import sexpression.Symbol;
|
2017-07-19 15:23:15 -04:00
|
|
|
import testutil.SymbolAndFunctionCleaner;
|
2017-01-27 14:31:41 -05:00
|
|
|
|
2017-07-19 15:23:15 -04:00
|
|
|
public class LAMBDATest extends SymbolAndFunctionCleaner {
|
2017-01-27 14:31:41 -05:00
|
|
|
|
|
|
|
@Test
|
2017-02-27 12:00:24 -05:00
|
|
|
public void lambda() {
|
2017-01-27 14:31:41 -05:00
|
|
|
String input = "(lambda (x) x)";
|
|
|
|
|
|
|
|
assertSExpressionsMatch(parseString("(LAMBDA (X) X)"), evaluateString(input));
|
|
|
|
}
|
|
|
|
|
2018-02-11 14:17:49 -05:00
|
|
|
@Test
|
|
|
|
public void lambdaSymbol() {
|
|
|
|
String input = "(λ (x) x)";
|
|
|
|
|
|
|
|
assertSExpressionsMatch(parseString("(LAMBDA (X) X)"), evaluateString(input));
|
|
|
|
}
|
|
|
|
|
2017-02-04 15:38:47 -05:00
|
|
|
@Test
|
2017-02-27 12:00:24 -05:00
|
|
|
public void lambdaWithNoBody() {
|
2017-02-04 15:38:47 -05:00
|
|
|
String input = "(lambda ())";
|
|
|
|
|
|
|
|
assertSExpressionsMatch(parseString("(LAMBDA ())"), evaluateString(input));
|
|
|
|
}
|
|
|
|
|
2017-01-27 14:31:41 -05:00
|
|
|
@Test
|
|
|
|
public void lambdaExpressionIsLambdaExpression() {
|
2017-03-02 09:54:23 -05:00
|
|
|
Cons lambdaExpression = new Cons(new Symbol("LAMBDA"), new Cons(NIL, new Cons(NIL, NIL)));
|
2017-01-27 14:31:41 -05:00
|
|
|
|
|
|
|
assertTrue(LAMBDA.isLambdaExpression(lambdaExpression));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void somethingElseIsNotLambdaExpression() {
|
2017-03-02 09:54:23 -05:00
|
|
|
assertFalse(LAMBDA.isLambdaExpression(T));
|
2017-01-27 14:31:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
2017-02-27 12:00:24 -05:00
|
|
|
public void createLambdaExpression() {
|
2017-03-02 09:54:23 -05:00
|
|
|
Cons lambdaExpression = new Cons(new Symbol("LAMBDA"), new Cons(NIL, new Cons(NIL, NIL)));
|
2017-01-27 14:31:41 -05:00
|
|
|
|
|
|
|
assertSExpressionsMatch(parseString("(:LAMBDA () ())"),
|
|
|
|
LAMBDA.createFunction(lambdaExpression).getLambdaExpression());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test(expected = DottedArgumentListException.class)
|
2017-02-27 12:00:24 -05:00
|
|
|
public void lambdaWithDottedArgumentList() {
|
2017-01-27 14:31:41 -05:00
|
|
|
String input = "(apply 'lambda (cons '(x) 1))";
|
|
|
|
|
|
|
|
evaluateString(input);
|
|
|
|
}
|
|
|
|
|
2017-02-04 13:51:10 -05:00
|
|
|
@Test(expected = DottedArgumentListException.class)
|
2017-02-27 12:00:24 -05:00
|
|
|
public void lambdaWithDottedLambdaList() {
|
2017-02-04 13:51:10 -05:00
|
|
|
String input = "(funcall 'lambda (cons 'a 'b) ())";
|
|
|
|
|
|
|
|
evaluateString(input);
|
|
|
|
}
|
|
|
|
|
2017-01-27 14:31:41 -05:00
|
|
|
@Test(expected = DottedArgumentListException.class)
|
2017-02-27 12:00:24 -05:00
|
|
|
public void createFunctionWithDottedArgumentList() {
|
2017-03-02 09:54:23 -05:00
|
|
|
Cons lambdaExpression = new Cons(new Symbol("LAMBDA"), new Cons(NIL, ONE));
|
2017-01-27 14:31:41 -05:00
|
|
|
|
|
|
|
LAMBDA.createFunction(lambdaExpression);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test(expected = BadArgumentTypeException.class)
|
2017-02-27 12:00:24 -05:00
|
|
|
public void createFunctionWithNonList() {
|
2017-03-02 09:54:23 -05:00
|
|
|
Cons lambdaExpression = new Cons(new Symbol("LAMBDA"), ONE);
|
2017-01-27 14:31:41 -05:00
|
|
|
|
|
|
|
LAMBDA.createFunction(lambdaExpression);
|
|
|
|
}
|
|
|
|
|
2017-02-04 13:51:10 -05:00
|
|
|
@Test(expected = BadArgumentTypeException.class)
|
2017-02-27 12:00:24 -05:00
|
|
|
public void lambdaWithNonSymbolParameter() {
|
2017-02-04 13:51:10 -05:00
|
|
|
evaluateString("(lambda (1) ())");
|
|
|
|
}
|
|
|
|
|
2017-01-27 14:31:41 -05:00
|
|
|
@Test(expected = TooFewArgumentsException.class)
|
2017-02-27 12:00:24 -05:00
|
|
|
public void lambdaWithTooFewArguments() {
|
2017-02-04 15:38:47 -05:00
|
|
|
evaluateString("(lambda)");
|
2017-01-27 14:31:41 -05:00
|
|
|
}
|
|
|
|
|
2017-02-04 13:51:10 -05:00
|
|
|
@Test
|
|
|
|
public void anonymousLambdaCall() {
|
|
|
|
String input = "((lambda (x) x) 203)";
|
|
|
|
|
|
|
|
assertSExpressionsMatch(new LispNumber("203"), evaluateString(input));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void anonymousLambdaCallWithMultipleArguments() {
|
|
|
|
String input = "((lambda (x y) (+ x y)) 203 2)";
|
|
|
|
|
|
|
|
assertSExpressionsMatch(new LispNumber("205"), evaluateString(input));
|
|
|
|
}
|
|
|
|
|
2018-02-11 14:17:49 -05:00
|
|
|
@Test
|
|
|
|
public void anonymousLambdaCallWithSymbol() {
|
|
|
|
String input = "((λ (x) (+ x 1)) 3)";
|
|
|
|
|
|
|
|
assertSExpressionsMatch(new LispNumber("4"), evaluateString(input));
|
|
|
|
}
|
|
|
|
|
2017-02-04 13:51:10 -05:00
|
|
|
@Test(expected = TooFewArgumentsException.class)
|
|
|
|
public void anonymousLambdaCallWithTooFewArguments() {
|
|
|
|
evaluateString("((lambda (x) x))");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test(expected = TooManyArgumentsException.class)
|
|
|
|
public void anonymousLambdaCallWithTooManyArguments() {
|
|
|
|
evaluateString("((lambda (x y) x) 1 2 3)");
|
|
|
|
}
|
|
|
|
|
2018-03-15 18:48:33 -04:00
|
|
|
@Test(expected = UndefinedFunctionException.class)
|
|
|
|
public void badAnonymousFunctionCall() {
|
|
|
|
evaluateString("((bad-lambda (x y) x) 1 2 3)");
|
|
|
|
}
|
|
|
|
|
2017-02-27 12:00:24 -05:00
|
|
|
@Test
|
|
|
|
public void lexicalClosure() {
|
2017-03-07 16:41:26 -05:00
|
|
|
evaluateString("(setq increment-count (let ((counter 0)) (lambda () (setq counter (+ 1 counter)))))");
|
2017-02-27 12:00:24 -05:00
|
|
|
|
|
|
|
assertSExpressionsMatch(parseString("1"), evaluateString("(funcall increment-count)"));
|
|
|
|
assertSExpressionsMatch(parseString("2"), evaluateString("(funcall increment-count)"));
|
|
|
|
assertSExpressionsMatch(parseString("3"), evaluateString("(funcall increment-count)"));
|
|
|
|
assertSExpressionsMatch(parseString("4"), evaluateString("(funcall increment-count)"));
|
|
|
|
}
|
|
|
|
|
2017-01-27 14:31:41 -05:00
|
|
|
}
|