changeset 147:1e9d534b903d

eval: Return type errors for undefined functions; test recursion
author Lewin Bormann <lbo@spheniscida.de>
date Tue, 03 Sep 2019 12:16:23 +0200
parents aa551e42de49
children 1620bde57dcb
files src/eval.c src/eval_test.c
diffstat 2 files changed, 38 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/eval.c	Tue Sep 03 12:15:51 2019 +0200
+++ b/src/eval.c	Tue Sep 03 12:16:23 2019 +0200
@@ -117,6 +117,14 @@
                     // resolve as normal below; this seems to be a "data
                     // list".
                 } else {
+                    yexpr_t exc = yexpr_new();
+                    ystr_t msg = ystr_new(NULL);
+                    ystr_build(&msg, "possibly undefined function: ");
+                    ystr_t dbg = yref_debug(&first->value.ref);
+                    ystr_append(&msg, &dbg);
+                    ystr_destroy(&dbg);
+                    yexpr_set_exception(&exc, msg);
+                    return exc;
                     assert(val->typ == YVALUE_FUNC || val->typ == YVALUE_EXPR);
                 }
             }
--- a/src/eval_test.c	Tue Sep 03 12:15:51 2019 +0200
+++ b/src/eval_test.c	Tue Sep 03 12:16:23 2019 +0200
@@ -55,9 +55,39 @@
     yexpr_destroy(&result);
 }
 
+void test_eval_recursion(void) {
+    fprintf(stderr, "test_eval_recursion ===========\n");
+
+    // Calculate faculty values from 1 to 10.
+    ystr_t input = ystr_new(
+        "(defn fac (n) (if (== n 0) 1 ((* n (fac (- n 1))))))"
+        "(for i (1 2 3 4 5 6 7 8 9 10) (fac i))");
+    yexpr_t program = yexpr_new();
+    ystr_t error = ystr_new(NULL);
+    assert(yparse_str(&input, &program, &error));
+    yexpr_debug(&program);
+    ypreprocess(&program);
+    yexpr_debug(&program);
+
+    yeval_state_t state;
+    state.call_stack = YVEC_NEW(NULL, 4, yexpr_t);
+    yexpr_t result = yeval_list_return_last(&state, &program.value.list, 0);
+    yexpr_debug(&result);
+    assert(YEXPR_LIST == result.typ);
+    assert(362880 == YVEC_AT(&result.value.list, 8, yexpr_t)->value.n);
+
+    yexpr_destroy(&program);
+    yvec_destroy(&state.call_stack);
+    ystr_destroy(&error);
+    yexpr_destroy(&result);
+    ystr_destroy(&input);
+}
+
 int main(void) {
     test_eval_edge_cases();
     test_eval_func_wrong_call();
+    test_eval_recursion();
     yvalue_free_all();
+    yatom_free_all();
     return 0;
 }