diff --git a/src/main/resources/dlambda.lisp b/src/main/resources/dlambda.lisp index c43fc95..4d67997 100644 --- a/src/main/resources/dlambda.lisp +++ b/src/main/resources/dlambda.lisp @@ -3,11 +3,13 @@ (defmacro dlambda (&rest methods) (let ((arguments (gensym))) - `(lambda (&rest, arguments) - (case (first, arguments), @(mapcar - (lambda (method)) - `(, (first method)) - (apply (lambda, @(rest method)), (if (equal t (first method))) - arguments - `(rest, arguments)) - methods))))) + `(lambda (&rest ,arguments) + (case (first ,arguments) + ,@(mapcar + (lambda (method) + `(,(first method) + (apply (lambda ,@(rest method)) + ,(if (equal t (first method)) + arguments + `(rest ,arguments))))) + methods))))) diff --git a/src/main/resources/functions.lisp b/src/main/resources/functions.lisp index 72701e6..985b765 100644 --- a/src/main/resources/functions.lisp +++ b/src/main/resources/functions.lisp @@ -6,9 +6,9 @@ (defun maplist (function-name the-list) (cond - ((null the-list) nil) - (t (cons (funcall function-name the-list) - (maplist function-name (rest the-list)))))) + ((null the-list) nil) + (t (cons (funcall function-name the-list) + (maplist function-name (rest the-list)))))) (defun map (function the-list) (reverse (map-tail function the-list nil))) @@ -42,7 +42,7 @@ (defun reverse-tail (accumulator the-list) (if (null the-list) accumulator - (recur (cons (first the-list) accumulator) (rest the-list)))) + (recur (cons (first the-list) accumulator) (rest the-list)))) (defun deep-reverse (the-list) (if the-list @@ -55,9 +55,9 @@ (defun nth (n listA) (cond - ((equal 0 n) (first listA)) - (t (nth (- n 1) (rest listA))))) + ((equal 0 n) (first listA)) + (t (nth (- n 1) (rest listA))))) (eval (let ((expr (gensym))) - `(defun global-eval (, expr) (eval, expr)))) + `(defun global-eval (,expr) (eval ,expr)))) diff --git a/src/test/kotlin/sexpression/SExpressionTest.java b/src/test/kotlin/sexpression/SExpressionTest.java deleted file mode 100644 index 6cca9fb..0000000 --- a/src/test/kotlin/sexpression/SExpressionTest.java +++ /dev/null @@ -1,224 +0,0 @@ -package sexpression; - -import function.UserDefinedFunction; -import org.junit.Test; -import sexpression.LispNumber.InvalidNumberException; - -import java.math.BigInteger; -import java.util.Locale; - -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.assertSExpressionsMatch; -import static testutil.TestUtilities.makeList; - -public class SExpressionTest { - - private void assertSExpressionMatchesString(String expected, SExpression sExpression) { - assertEquals(expected, sExpression.toString()); - } - - @Test - public void nil_ToString() { - String input = "NIL"; - - assertSExpressionMatchesString(input, Nil.INSTANCE); - } - - @Test - public void number_ToString() { - String input = "12"; - - assertSExpressionMatchesString(input, new LispNumber(input)); - } - - @Test - public void numberValue_ToString() { - String expected = "12"; - - assertSExpressionMatchesString(expected, new LispNumber("12")); - } - - @Test - public void string_ToString() { - String input = "\"hi\""; - - assertSExpressionMatchesString(input, new LispString(input)); - } - - @Test - public void symbol_ToString() { - String input = "symbol"; - - assertSExpressionMatchesString(input.toUpperCase(Locale.ROOT), new Symbol(input)); - } - - @Test - public void simpleCons_ToString() { - String expected = "(1)"; - Cons cons = makeList(new LispNumber("1")); - - assertSExpressionMatchesString(expected, cons); - } - - @Test - public void complexCons_ToString() { - String expected = "(1 A \"string\")"; - Cons list = makeList(new LispNumber("1"), new Symbol("a"), new LispString("\"string\"")); - - assertSExpressionMatchesString(expected, list); - } - - @Test - public void improperList_ToString() { - String expected = "(A . B)"; - Cons list = new Cons(new Symbol("A"), new Symbol("B")); - - assertSExpressionMatchesString(expected, list); - } - - @Test - public void lambdaExpression_ToString() { - String expected = "(LAMBDA)"; - LambdaExpression lambda = new LambdaExpression(makeList(new Symbol("lambda")), - new UserDefinedFunction("", Nil.INSTANCE, Nil.INSTANCE)); - - assertSExpressionMatchesString(expected, lambda); - } - - @Test - public void lambdaExpression_GetLambdaExpression() { - String expected = "(LAMBDA)"; - LambdaExpression lambda = new LambdaExpression(makeList(new Symbol("lambda")), - new UserDefinedFunction("", Nil.INSTANCE, Nil.INSTANCE)); - - assertSExpressionMatchesString(expected, lambda.getLambdaExpression()); - } - - @Test - public void lambdaExpression_GetFunction() { - String expected = "(LAMBDA)"; - UserDefinedFunction function = new UserDefinedFunction(expected, Nil.INSTANCE, Nil.INSTANCE); - LambdaExpression lambda = new LambdaExpression(makeList(new Symbol("lambda")), function); - - assertEquals(function, lambda.getFunction()); - } - - @Test - public void firstOfNilIsNil() { - assertEquals(Nil.INSTANCE, Nil.INSTANCE.getFirst()); - } - - @Test - public void restOfNilIsNil() { - assertEquals(Nil.INSTANCE, Nil.INSTANCE.getRest()); - } - - @Test - public void afterSettingFirstOfNil_ShouldStillBeNil() { - Cons nil = Nil.INSTANCE; - nil.setFirst(new LispNumber("2")); - - assertEquals(Nil.INSTANCE, nil.getFirst()); - } - - @Test - public void afterSettingRestOfNil_ShouldStillBeNil() { - Cons nil = Nil.INSTANCE; - nil.setRest(new LispNumber("2")); - - assertEquals(Nil.INSTANCE, nil.getRest()); - } - - @Test - public void numberValue() { - BigInteger value = new BigInteger("12"); - LispNumber number = new LispNumber(value.toString()); - - assertEquals(value, number.getValue()); - } - - @Test(expected = InvalidNumberException.class) - public void invalidNumberText_ThrowsException() { - new LispNumber("a"); - } - - @Test - public void invalidNumberException_HasCorrectAttributes() { - try { - new LispNumber("a"); - } catch (InvalidNumberException e) { - String message = e.getMessage(); - - assertEquals(ERROR, e.getSeverity()); - assertNotNull(message); - assertTrue(message.length() > 0); - } - } - - @Test - public void lispNumberConstants() { - assertEquals(BigInteger.ZERO, LispNumber.Companion.getZERO().getValue()); - assertEquals(BigInteger.ONE, LispNumber.Companion.getONE().getValue()); - } - - @Test - public void backTickExpression_ToString() { - String expected = "`(TEST)"; - SExpression backTick = new BackquoteExpression(makeList(new Symbol("TEST"))); - - assertSExpressionMatchesString(expected, backTick); - } - - @Test - public void commaExpression_ToString() { - String expected = ",A"; - SExpression comma = new CommaExpression(new Symbol("A")); - - assertSExpressionMatchesString(expected, comma); - } - - @Test - public void atSignExpression_ToString() { - String expected = "@A"; - SExpression atSign = new AtSignExpression(new Symbol("A")); - - assertSExpressionMatchesString(expected, atSign); - } - - @Test - public void complexBackTickExpression_ToString() { - String expected = "`(LIST ,A ,@B)"; - SExpression backTick = new BackquoteExpression(makeList(new Symbol("LIST"), - new CommaExpression(new Symbol("A")), - new CommaExpression(new AtSignExpression(new Symbol("B"))))); - - assertSExpressionMatchesString(expected, backTick); - } - - @Test - public void backTickExpression_GetExpression() { - SExpression expression = makeList(new Symbol("TEST")); - BackquoteExpression backTick = new BackquoteExpression(expression); - - assertSExpressionsMatch(expression, backTick.getExpression()); - } - - @Test - public void commaExpression_GetExpression() { - SExpression expression = new Symbol("A"); - CommaExpression comma = new CommaExpression(expression); - - assertSExpressionsMatch(expression, comma.getExpression()); - } - - @Test - public void atSignExpression_GetExpression() { - SExpression expression = new Symbol("A"); - AtSignExpression atSign = new AtSignExpression(expression); - - assertSExpressionsMatch(expression, atSign.getExpression()); - } -} diff --git a/src/test/kotlin/sexpression/SExpressionTest.kt b/src/test/kotlin/sexpression/SExpressionTest.kt new file mode 100644 index 0000000..d24c933 --- /dev/null +++ b/src/test/kotlin/sexpression/SExpressionTest.kt @@ -0,0 +1,210 @@ +package sexpression + +import function.UserDefinedFunction +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Assertions.assertThrows +import org.junit.jupiter.api.Test +import sexpression.LispNumber.InvalidNumberException +import testutil.TestUtilities.assertIsErrorWithMessage +import testutil.TestUtilities.assertSExpressionsMatch +import testutil.TestUtilities.makeList +import java.math.BigInteger +import java.util.Locale + +class SExpressionTest { + + private fun assertSExpressionMatchesString(expected: String, sExpression: SExpression) { + assertThat(sExpression.toString()).isEqualTo(expected) + } + + @Test + fun `nil to string`() { + val input = "NIL" + + assertSExpressionMatchesString(input, Nil) + } + + @Test + fun `number to string`() { + val input = "12" + + assertSExpressionMatchesString(input, LispNumber(input)) + } + + @Test + fun `string to string`() { + val input = "\"hi\"" + + assertSExpressionMatchesString(input, LispString(input)) + } + + @Test + fun `symbol to string`() { + val input = "symbol" + + assertSExpressionMatchesString(input.toUpperCase(Locale.ROOT), Symbol(input)) + } + + @Test + fun `simple cons to string`() { + val expected = "(1)" + val cons = makeList(LispNumber("1")) + + assertSExpressionMatchesString(expected, cons) + } + + @Test + fun `complex cons to string`() { + val expected = "(1 A \"string\")" + val list = makeList(LispNumber("1"), Symbol("a"), LispString("\"string\"")) + + assertSExpressionMatchesString(expected, list) + } + + @Test + fun `improper list to string`() { + val expected = "(A . B)" + val list = Cons(Symbol("A"), Symbol("B")) + + assertSExpressionMatchesString(expected, list) + } + + @Test + fun `lambda expression to string`() { + val expected = "(LAMBDA)" + val lambda = LambdaExpression(makeList(Symbol("lambda")), + UserDefinedFunction("", Nil, Nil)) + + assertSExpressionMatchesString(expected, lambda) + } + + @Test + fun `get lambda expression from lambda`() { + val expected = "(LAMBDA)" + val lambda = LambdaExpression(makeList(Symbol("lambda")), + UserDefinedFunction("", Nil, Nil)) + + assertSExpressionMatchesString(expected, lambda.lambdaExpression) + } + + @Test + fun `get function from lambda`() { + val expected = "(LAMBDA)" + val function = UserDefinedFunction(expected, Nil, Nil) + val lambda = LambdaExpression(makeList(Symbol("lambda")), function) + + assertThat(lambda.function).isEqualTo(function) + } + + @Test + fun `first of nil is nil`() { + assertThat(Nil.first).isEqualTo(Nil) + } + + @Test + fun `rest of nil is nil`() { + assertThat(Nil.rest).isEqualTo(Nil) + } + + @Test + fun `cannot change first of nil`() { + val nil = Nil + nil.first = LispNumber("2") + + assertThat(nil.first).isEqualTo(Nil) + } + + @Test + fun `cannot change rest of nil`() { + val nil = Nil + nil.rest = LispNumber("2") + + assertThat(nil.rest).isEqualTo(Nil) + } + + @Test + fun `number value`() { + val value = BigInteger("12") + val number = LispNumber(value.toString()) + + assertThat(number.value).isEqualTo(value) + } + + @Test + fun `invalid number text throws an exception`() { + assertThrows(InvalidNumberException::class.java) { LispNumber("a") } + } + + @Test + fun `InvalidNumberException is cool`() { + try { + LispNumber("a") + } catch (e: InvalidNumberException) { + assertIsErrorWithMessage(e) + } + } + + @Test + fun `lisp number constants are accurate`() { + assertThat(LispNumber.ZERO.value).isEqualTo(BigInteger.ZERO) + assertThat(LispNumber.ONE.value).isEqualTo(BigInteger.ONE) + } + + @Test + fun `back tick expression to string`() { + val expected = "`(TEST)" + val backTick = BackquoteExpression(makeList(Symbol("TEST"))) + + assertSExpressionMatchesString(expected, backTick) + } + + @Test + fun `comma expression to string`() { + val expected = ",A" + val comma = CommaExpression(Symbol("A")) + + assertSExpressionMatchesString(expected, comma) + } + + @Test + fun `at sign expression to string`() { + val expected = "@A" + val atSign = AtSignExpression(Symbol("A")) + + assertSExpressionMatchesString(expected, atSign) + } + + @Test + fun `complex back tick expression to string`() { + val expected = "`(LIST ,A ,@B)" + val backTick = BackquoteExpression(makeList(Symbol("LIST"), + CommaExpression(Symbol("A")), + CommaExpression(AtSignExpression(Symbol("B"))))) + + assertSExpressionMatchesString(expected, backTick) + } + + @Test + fun `get expression from back tick expression`() { + val expression = makeList(Symbol("TEST")) + val backTick = BackquoteExpression(expression) + + assertSExpressionsMatch(expression, backTick.expression) + } + + @Test + fun `get expression from comma expression`() { + val expression = Symbol("A") + val comma = CommaExpression(expression) + + assertSExpressionsMatch(expression, comma.expression) + } + + @Test + fun `get expression from at sign expression`() { + val expression = Symbol("A") + val atSign = AtSignExpression(expression) + + assertSExpressionsMatch(expression, atSign.expression) + } +}