changeset 86:5c761c80c411

eval: Implement first iteration of yeval()
author Lewin Bormann <lbo@spheniscida.de>
date Mon, 26 Aug 2019 12:03:31 +0200
parents 7f0a4a258b69
children 8156b5031546
files src/.clang src/built-ins.c src/eval.c
diffstat 3 files changed, 71 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/.clang	Mon Aug 26 12:02:51 2019 +0200
+++ b/src/.clang	Mon Aug 26 12:03:31 2019 +0200
@@ -1,1 +1,1 @@
-compilation_database = "../build/compile_commands.json"
+flags = -I.. -I../build
--- a/src/built-ins.c	Mon Aug 26 12:02:51 2019 +0200
+++ b/src/built-ins.c	Mon Aug 26 12:03:31 2019 +0200
@@ -64,7 +64,7 @@
 
 static void nothing(void){};
 
-/// Expects a list expression starting with built-in "let" on the stack.
+/// Expects a list expression starting with built-in "let" on the stack. It is not modified.
 ///
 /// Returns an UNDEF expression by default, or an EXCEPTION if something went
 /// wrong.
--- a/src/eval.c	Mon Aug 26 12:02:51 2019 +0200
+++ b/src/eval.c	Mon Aug 26 12:03:31 2019 +0200
@@ -1,8 +1,75 @@
 #include "eval.h"
 
+#include <src/built-ins.h>
 #include <src/expr.h>
+#include <src/value.h>
+
+static void nothing(void){/* labels need to be followed by statement */};
+
+yexpr_t yeval_call_func(yvalue_t* ref, yexpr_t* call) { return yexpr_new(); }
 
 yexpr_t yeval(yeval_state_t* state, yexpr_t* expr, bool in_place) {
-    assert(false /* yeval is not yet implemented */);
-    return yexpr_new();
+    yexpr_t result;
+    switch (expr->typ) {
+        case YEXPR_ATOM:
+        case YEXPR_NUMBER:
+        case YEXPR_STRING:
+        case YEXPR_EXCEPTION:
+        case YEXPR_BUILTIN:
+            // Flat copy is enough.
+            return *expr;
+        case YEXPR_REF:
+            // Reference is resolved if expr-ref. func-refs are not resolved.
+            // NOTE: Can this result in infinite recursion?
+            nothing();
+            yvalue_t* val = yvalue_get(expr->value.ref);
+            if (val->typ == YVALUE_EXPR) {
+                result = yexpr_copy(&val->value.expr);
+                return result;
+            } else if (val->typ == YVALUE_FUNC) {
+                return *expr;
+            }
+            assert(val->typ == YVALUE_FUNC || val->typ == YVALUE_EXPR);
+            break;
+        case YEXPR_LIST:
+            // Is empty list?
+            if (expr->value.list.len == 0) {
+                result = *expr;
+                result.value.list = yvec_clone(&expr->value.list);
+                return result;
+            }
+            // Is builtin call?
+            yexpr_t* first = YVEC_AT(&expr->value.list, 0, yexpr_t);
+            if (first->typ == YEXPR_BUILTIN) {
+                // both must be yexpr_t vecs.
+                assert(expr->value.list.size == state->call_stack.size);
+                // Builtins expect their call list on the stack.
+                YVEC_PUSH(&state->call_stack, expr);
+                ybuiltin_run(first->value.builtin, state);
+            }
+            // Is function call?
+            if (first->typ == YEXPR_REF) {
+                yvalue_t* val = yvalue_get(first->value.ref);
+                // Call function.
+                if (val->typ == YVALUE_FUNC) {
+                    result = yeval_call_func(val, expr);
+                    return result;
+                } else if (val->typ == YVALUE_EXPR) {
+                    // resolve as normal below; this seems to be a "data list".
+                } else {
+                    assert(val->typ == YVALUE_FUNC || val->typ == YVALUE_EXPR);
+                }
+            }
+            result = *expr;
+            result.value.list = yvec_clone(&expr->value.list);
+            for (size_t i = 0; i < result.value.list.len; i++) {
+                yexpr_t* elem = YVEC_AT(&result.value.list, i, yexpr_t);
+                yexpr_t elem_result = yeval(state, elem, false);
+                *elem = elem_result;
+            }
+            return result;
+        default:
+            assert(false /* yeval is not yet fully implemented */);
+    }
+    return result;
 }