Mercurial > lbo > hg > ylisp
changeset 98:8498c1faba07
built-ins: Improve let built-in and implement ybuiltin_translate()
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Mon, 26 Aug 2019 17:01:40 +0200 |
parents | 3b468dad363f |
children | 7b041326c9f7 |
files | src/built-ins.c src/built-ins.h src/built-ins_test.c |
diffstat | 3 files changed, 45 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- a/src/built-ins.c Mon Aug 26 17:01:14 2019 +0200 +++ b/src/built-ins.c Mon Aug 26 17:01:40 2019 +0200 @@ -63,6 +63,16 @@ return YBUILTIN_UNDEF; } +bool ybuiltin_translate(yexpr_t* expr) { + if (expr->typ != YEXPR_REF) return false; + if (yref_type(&expr->value.ref) != YREF_SYM) return false; + YBUILTIN_TYPE bi = ybuiltin_id(&expr->value.ref.ref.sym); + if (bi == YBUILTIN_UNDEF) return false; + yexpr_destroy(expr); + yexpr_set_builtin(expr, bi); + return true; +} + static void nothing(void){}; /// Expects a list expression starting with built-in "let" on the stack. It is not modified. @@ -70,7 +80,7 @@ /// Returns an UNDEF expression by default, or an EXCEPTION if something went /// wrong. yexpr_t ybuiltin_fn_let(yeval_state_t* state) { - yexpr_t let, *ref, *val; + yexpr_t let, *ref; size_t counter = 0; yvec_t* letlist = &let.value.list; @@ -83,13 +93,11 @@ goto badexprfail; ref = YVEC_AT(letlist, counter++, yexpr_t); - // TODO evaluate all expressions and assign last - val = YVEC_AT(letlist, counter++, yexpr_t); - if (ref->typ != YEXPR_REF || val->typ == YEXPR_UNDEF) goto typefail; + if (ref->typ != YEXPR_REF) goto typefail; yvalue_t newvalue = { .typ = YVALUE_EXPR, - .value.expr = yeval(state, val, /* in_place= */ false)}; + .value.expr = yeval_list_return_last(state, letlist, 2)}; yvalue_set(ref->value.ref, &newvalue); return yexpr_new(); @@ -105,15 +113,11 @@ typefail: nothing(); - yexpr_t args = yexpr_new(); - yexpr_init_or_extend(&args, *ref); - yexpr_init_or_extend(&args, *val); yexpr_t exc = ybuiltin_type_error( YBUILTIN_LET, ystr_new( - "type mismatch: want (reference, value), received something else"), - &args); - yexpr_destroy(&args); + "type mismatch: want (let reference [exprs...] expr), received something else"), + &let); return exc; }
--- a/src/built-ins.h Mon Aug 26 17:01:14 2019 +0200 +++ b/src/built-ins.h Mon Aug 26 17:01:40 2019 +0200 @@ -19,6 +19,11 @@ const char* ybuiltin_name(YBUILTIN_TYPE t); /** + * @brief If possible, make an ID (in a parse tree) into a built-in reference. + */ +bool ybuiltin_translate(yexpr_t* expr); + +/** * @brief Run a built-in function. The caller assumes ownership of the returned value. */ yexpr_t ybuiltin_run(YBUILTIN_TYPE t, yeval_state_t* state);
--- a/src/built-ins_test.c Mon Aug 26 17:01:14 2019 +0200 +++ b/src/built-ins_test.c Mon Aug 26 17:01:40 2019 +0200 @@ -4,6 +4,28 @@ #include <src/parse.h> #include <src/value.h> +void test_builtin_translate(void) { + yexpr_t expr = yexpr_new(); + + yexpr_set_atom(&expr, yatom_get_or_add("atom")); + assert(!ybuiltin_translate(&expr)); + assert(YEXPR_ATOM == expr.typ); + + yexpr_set_ref(&expr, yref_new()); + assert(!ybuiltin_translate(&expr)); + assert(YEXPR_REF == expr.typ); + + yexpr_set_ref(&expr, yref_new_c("my-ref")); + assert(!ybuiltin_translate(&expr)); + assert(YEXPR_REF == expr.typ); + yexpr_destroy(&expr); + + yexpr_set_ref(&expr, yref_new_c("let")); + assert(ybuiltin_translate(&expr)); + assert(YEXPR_BUILTIN == expr.typ); + assert(YBUILTIN_LET == expr.value.builtin); +} + void test_builtin_let(void) { yexpr_t ref_expr = yexpr_new(); yexpr_t let_expr = yexpr_new(); @@ -71,7 +93,7 @@ void test_builtin_let_parsed(void) { ystr_t input = ystr_new("(let my-var (1 2 3))"), error = ystr_new(NULL); - yexpr_t program, *let_expr; + yexpr_t program = yexpr_new(), *let_expr; assert(yparse_str(&input, &program, &error)); let_expr = YVEC_AT(&program.value.list, 0, yexpr_t); @@ -94,6 +116,7 @@ assert(YVEC_AT(&stored->value.expr.value.list, 1, yexpr_t)->value.n == 2); yexpr_destroy(&result); + yexpr_destroy(&program); yref_destroy(&my_var_ref); yvec_destroy(&state.call_stack); ystr_destroy(&input); @@ -101,6 +124,7 @@ } int main(void) { + test_builtin_translate(); test_builtin_let(); test_builtin_let_parsed(); return 0;