Mercurial > lbo > hg > ylisp
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; }