changeset 184:263256062455

Make project compile again. Implement basic ref logic
author Lewin Bormann <lbo@spheniscida.de>
date Sun, 29 Sep 2019 14:14:04 +0200
parents 37b01b114b50
children db386ec98dc3
files doc/syntax.md src/bin/ylisp.c src/built-ins.c src/built-ins.h src/built-ins_test.c src/eval.c src/eval.h src/eval_test.c src/expr.c src/expr.h src/expr_test.c src/preprocess_test.c src/sizes_test.c src/types.h src/value.c src/value.h src/value_test.c
diffstat 17 files changed, 246 insertions(+), 556 deletions(-) [+]
line wrap: on
line diff
--- a/doc/syntax.md	Sat Sep 28 19:13:26 2019 +0200
+++ b/doc/syntax.md	Sun Sep 29 14:14:04 2019 +0200
@@ -10,7 +10,7 @@
 of them has a `ybuiltin_fn` associated with it that can be called with a pointer
 to the call stack, executing the defined logic.
 
-#### `defn`: Define function
+#### `defn`: Define closure
 
 ```
 (defn name (arg arg ...) (body body) (body) ...)
--- a/src/bin/ylisp.c	Sat Sep 28 19:13:26 2019 +0200
+++ b/src/bin/ylisp.c	Sun Sep 29 14:14:04 2019 +0200
@@ -6,7 +6,7 @@
 #include <src/eval.h>
 
 yexpr_t run(FILE* input) {
-    return result;
+    return yexpr_new();
 }
 
 int main(int argc, char** argv) {
--- a/src/built-ins.c	Sat Sep 28 19:13:26 2019 +0200
+++ b/src/built-ins.c	Sun Sep 29 14:14:04 2019 +0200
@@ -8,6 +8,7 @@
 
 // TODO: Write standard library!
 
+
 static FILE* output_handle = NULL;
 
 void ybuiltin_set_output(FILE* out) { output_handle = out; }
@@ -17,7 +18,7 @@
  *
  * The functions return a yexpr_t of which the caller assumes ownership.
  */
-typedef yexpr_t (*ybuiltin_fn)(yeval_state_t* state);
+typedef yexpr_t (*ybuiltin_fn)(yeval_t* state, yexpr_t* self);
 
 struct ybuiltin_id_mapping {
     const char* id;
@@ -42,8 +43,6 @@
     {"push", YBUILTIN_PUSH},
     {"raise", YBUILTIN_RAISE},
     {"recover", YBUILTIN_RECOVER},
-
-    {"_mkclsr", YBUILTIN_INTERNAL_MKCLSR},
 };
 
 static const char* YBUILTIN_ENUM_STR[] = {
@@ -122,8 +121,7 @@
 
 /// Returns a YEXPR_UNDEF expression. TODO: Automatically add symbolic reference
 /// "undef".
-yexpr_t ybuiltin_fn_undef(yeval_state_t* state) {
-    yvec_pop(&state->call_stack, NULL);
+yexpr_t ybuiltin_fn_undef(yeval_t* state, yexpr_t* self) {
     return yexpr_new();
 }
 
@@ -136,14 +134,13 @@
 /// Returns a list of each of the last expressions in the for loop. If the last
 /// expression is an undefined value (`(undef)`), the value is not added to the
 /// resulting list.
-yexpr_t ybuiltin_fn_for(yeval_state_t* state) {
+yexpr_t ybuiltin_fn_for(yeval_t* state, yexpr_t* for_exprp) {
 #define _pattern "(for ref (item [...]) [exprs...] expr)"
-    yexpr_t for_expr;
+    yexpr_t for_expr = *for_exprp;
     yvec_t* for_list = &for_expr.value.list;
     size_t items = 0, counter = 0;
     yvec_t result;
 
-    if (!yvec_pop(&state->call_stack, &for_expr)) NOTENOUGHFAIL(FOR);
     if (for_expr.typ != YEXPR_LIST) BADEXPRFAIL(FOR, for_expr);
     if (for_expr.value.list.len < 4) TYPEFAIL(FOR, for_expr, _pattern);
 
@@ -165,11 +162,11 @@
     // nested loop: first items, then exprs
     for (size_t item = 0; item < for_items_l->len; item++) {
         yexpr_t* expr = YVEC_AT(for_items_l, item, yexpr_t);
-        yexpr_t evald = yeval(state, expr, false);
-        yvalue_t value = {.typ = YVALUE_EXPR, .value.expr = evald};
+        yexpr_t evald = yeval(state, expr);
+
+        // TODO: Proper binding
 
         // For each item, bind reference and execute body.
-        yvalue_set(for_ref->value.ref, &value);
         yexpr_t exprs_result = yeval_list_return_last(state, for_list, counter);
 
         // Make deep copy of result
@@ -179,7 +176,6 @@
             YVEC_PUSH(&result, &expr_result_cp);
 
         yexpr_destroy(&exprs_result);
-        yvalue_destroy(&value);
     }
 
     yexpr_t result_expr = yexpr_new();
@@ -194,18 +190,19 @@
 ///
 /// Returns an UNDEF expression by default, or an EXCEPTION if something went
 /// wrong.
-yexpr_t ybuiltin_fn_let(yeval_state_t* state) {
+yexpr_t ybuiltin_fn_let(yeval_t* state, yexpr_t* self) {
 #define _pattern "(let ref [expr ...] expr)"
+    // TODO: implement
+    assert(false);
 #undef _pattern
 }
 
 /// Expects a list expression starting with built-in "+" on the stack. It is not
 /// modified. Returns a number expression or an exception.
-yexpr_t ybuiltin_fn_plus(yeval_state_t* state) {
+yexpr_t ybuiltin_fn_plus(yeval_t* state, yexpr_t* self) {
 #define _pattern "(+ numeric-expr numeric-expr [numeric-expr ...])"
-    yexpr_t plus;
+    yexpr_t plus = *self;
 
-    if (!yvec_pop(&state->call_stack, &plus)) NOTENOUGHFAIL(PLUS);
     if (plus.typ != YEXPR_LIST) BADEXPRFAIL(PLUS, plus);
     if (plus.value.list.len < 3) BADEXPRFAIL(PLUS, plus);
 
@@ -214,7 +211,7 @@
     long long result = 0;
     for (size_t i = 1; i < plus_list->len; i++) {
         yexpr_t* expr = YVEC_AT(plus_list, i, yexpr_t);
-        yexpr_t evald = yeval(state, expr, false);
+        yexpr_t evald = yeval(state, expr);
         if (evald.typ != YEXPR_NUMBER) TYPEFAIL(PLUS, evald, _pattern);
         result += evald.value.n;
         yexpr_destroy(&evald);
@@ -229,11 +226,10 @@
 
 /// Expects a list expression starting with built-in "-" on the stack. It is not
 /// modified. Returns a number expression or an exception.
-yexpr_t ybuiltin_fn_minus(yeval_state_t* state) {
+yexpr_t ybuiltin_fn_minus(yeval_t* state, yexpr_t* self) {
 #define _pattern "(- numeric-expr numeric-expr [numeric-expr ...])"
-    yexpr_t minus;
+    yexpr_t minus = *self;
 
-    if (!yvec_pop(&state->call_stack, &minus)) NOTENOUGHFAIL(MINUS);
     if (minus.typ != YEXPR_LIST) BADEXPRFAIL(MINUS, minus);
     if (minus.value.list.len < 3) BADEXPRFAIL(MINUS, minus);
 
@@ -243,7 +239,7 @@
     bool first = true;
     for (size_t i = 1; i < minus_list->len; i++) {
         yexpr_t* expr = YVEC_AT(minus_list, i, yexpr_t);
-        yexpr_t evald = yeval(state, expr, false);
+        yexpr_t evald = yeval(state, expr);
         if (evald.typ != YEXPR_NUMBER) TYPEFAIL(MINUS, evald, _pattern);
         if (first) {
             result += evald.value.n;
@@ -263,11 +259,10 @@
 
 /// Expects a list expression starting with built-in "*" on the stack. It is not
 /// modified. Returns a number expression or an exception.
-yexpr_t ybuiltin_fn_times(yeval_state_t* state) {
+yexpr_t ybuiltin_fn_times(yeval_t* state, yexpr_t* self) {
 #define _pattern "(* numeric-expr numeric-expr [numeric-expr ...])"
-    yexpr_t times;
+    yexpr_t times = *self;
 
-    if (!yvec_pop(&state->call_stack, &times)) NOTENOUGHFAIL(MULT);
     if (times.typ != YEXPR_LIST) BADEXPRFAIL(MULT, times);
     if (times.value.list.len < 3) BADEXPRFAIL(MULT, times);
 
@@ -276,7 +271,7 @@
     long long result = 1;
     for (size_t i = 1; i < times_list->len; i++) {
         yexpr_t* expr = YVEC_AT(times_list, i, yexpr_t);
-        yexpr_t evald = yeval(state, expr, false);
+        yexpr_t evald = yeval(state, expr);
         if (evald.typ != YEXPR_NUMBER) TYPEFAIL(MULT, evald, _pattern);
         result *= evald.value.n;
         yexpr_destroy(&evald);
@@ -289,12 +284,11 @@
 #undef _pattern
 }
 
-yexpr_t ybuiltin_fn_if(yeval_state_t* state) {
+yexpr_t ybuiltin_fn_if(yeval_t* state, yexpr_t* self) {
 #define _pattern \
     "(if condition then-expr/(then-exprs) [else-expr/(else-exprs)])"
     yexpr_t if_expr;
 
-    if (!yvec_pop(&state->call_stack, &if_expr)) NOTENOUGHFAIL(IF);
     if (if_expr.typ != YEXPR_LIST) BADEXPRFAIL(IF, if_expr);
     if (if_expr.value.list.len < 3) BADEXPRFAIL(IF, if_expr);
 
@@ -304,7 +298,7 @@
     if (if_expr.value.list.len > 3)
         else_expr = YVEC_AT(&if_expr.value.list, 3, yexpr_t);
 
-    yexpr_t cond_result = yeval(state, condition, false);
+    yexpr_t cond_result = yeval(state, condition);
     bool result = false;
     if (cond_result.typ == YEXPR_ATOM &&
         yatom_get_or_add("true") == cond_result.value.atom)
@@ -315,11 +309,11 @@
     if (result) {
         if (then_expr->typ == YEXPR_LIST)
             return yeval_list_return_last(state, &then_expr->value.list, 0);
-        return yeval(state, then_expr, false);
+        return yeval(state, then_expr);
     } else if (else_expr != NULL) {
         if (else_expr->typ == YEXPR_LIST)
             return yeval_list_return_last(state, &else_expr->value.list, 0);
-        return yeval(state, else_expr, false);
+        return yeval(state, else_expr);
     } else {
         return yexpr_new();
     }
@@ -327,18 +321,17 @@
 #undef _pattern
 }
 
-yexpr_t ybuiltin_fn_print(yeval_state_t* state) {
+yexpr_t ybuiltin_fn_print(yeval_t* state, yexpr_t* self) {
 #define _pattern "(print expr [expr...])"
-    yexpr_t print;
+    yexpr_t print = *self;
     FILE* out = output_handle == NULL ? stdout : output_handle;
 
-    if (!yvec_pop(&state->call_stack, &print)) NOTENOUGHFAIL(PRINT);
     if (print.typ != YEXPR_LIST) BADEXPRFAIL(PRINT, print);
     if (print.value.list.len < 1) BADEXPRFAIL(PRINT, print);
 
     for (size_t i = 1; i < print.value.list.len; i++) {
         yexpr_t evald =
-            yeval(state, YVEC_AT(&print.value.list, i, yexpr_t), false);
+            yeval(state, YVEC_AT(&print.value.list, i, yexpr_t));
         if (evald.typ == YEXPR_STRING) {
             fputs(ystr_str(&evald.value.str), out);
             goto cleanup_continue;
@@ -357,18 +350,17 @@
 #undef _pattern
 }
 
-yexpr_t ybuiltin_fn_eq(yeval_state_t* state) {
+yexpr_t ybuiltin_fn_eq(yeval_t* state, yexpr_t* self) {
 #define _pattern "(== expr expr [expr...])"
-    yexpr_t eq;
+    yexpr_t eq = *self;
 
-    if (!yvec_pop(&state->call_stack, &eq)) NOTENOUGHFAIL(EQ);
     if (eq.typ != YEXPR_LIST) BADEXPRFAIL(EQ, eq);
     if (eq.value.list.len < 3) BADEXPRFAIL(EQ, eq);
 
     yexpr_t* first = YVEC_AT(&eq.value.list, 1, yexpr_t);
     yexpr_t* second = YVEC_AT(&eq.value.list, 2, yexpr_t);
-    yexpr_t firstevald = yeval(state, first, false);
-    yexpr_t secondevald = yeval(state, second, false);
+    yexpr_t firstevald = yeval(state, first);
+    yexpr_t secondevald = yeval(state, second);
     bool equal = yexpr_equal(&firstevald, &secondevald);
     yexpr_destroy(&firstevald);
     yexpr_destroy(&secondevald);
@@ -382,16 +374,6 @@
 #undef _pattern
 }
 
-yexpr_t ybuiltin_fn_mkclsr(yeval_state_t* state) {
-#define _pattern \
-    "(_mkclsr function-ref captured1 captured2 ...)"  // Sets function-ref to a
-                                                      // yexpr_t of type
-                                                      // YEXPR_FUNC, with
-                                                      // captured values.
-    // TODO: continue implementation
-#undef _pattern
-}
-
 /**
  * @brief Table of built-in functions, indexed by YBUILTIN_TYPE.
  *
@@ -413,16 +395,15 @@
                                            NULL,
                                            NULL,
                                            NULL,
-                                           NULL,
-                                           ybuiltin_fn_mkclsr};
+                                           NULL};
 
 const char* ybuiltin_name(YBUILTIN_TYPE t) {
     assert(t * sizeof(const char*) < sizeof(YBUILTIN_ENUM_STR));
     return YBUILTIN_ENUM_STR[t];
 }
 
-yexpr_t ybuiltin_run(YBUILTIN_TYPE t, yeval_state_t* state) {
+yexpr_t ybuiltin_run(YBUILTIN_TYPE t, yeval_t* state, yexpr_t* expr) {
     assert((t * sizeof(ybuiltin_fn)) < sizeof(YBUILTIN_FNS));
-    return YBUILTIN_FNS[t](state);
+    return YBUILTIN_FNS[t](state, expr);
 }
 
--- a/src/built-ins.h	Sat Sep 28 19:13:26 2019 +0200
+++ b/src/built-ins.h	Sun Sep 29 14:14:04 2019 +0200
@@ -26,7 +26,7 @@
 /**
  * @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);
+yexpr_t ybuiltin_run(YBUILTIN_TYPE t, yeval_t* state, yexpr_t* self);
 
 /**
  * @brief Set standard output for output built-ins.
--- a/src/built-ins_test.c	Sat Sep 28 19:13:26 2019 +0200
+++ b/src/built-ins_test.c	Sun Sep 29 14:14:04 2019 +0200
@@ -19,7 +19,7 @@
     assert(!ybuiltin_translate(&expr));
     assert(YEXPR_ATOM == expr.typ);
 
-    yexpr_set_ref(&expr, yref_new());
+    yexpr_set_ref(&expr, yref_new_anon());
     assert(!ybuiltin_translate(&expr));
     assert(YEXPR_REF == expr.typ);
 
@@ -34,322 +34,9 @@
     assert(YBUILTIN_LET == expr.value.builtin);
 }
 
-void test_builtin_for(void) {
-    fprintf(stderr, "test_builtin_for ============\n");
-
-    ystr_t input = ystr_new("(for loopvar (1 2 3) loopvar)"),
-           error = ystr_new(NULL);
-    yexpr_t program = yexpr_new();
-    assert(yparse_str(&input, &program, &error));
-    yexpr_t* for_expr = YVEC_AT(&program.value.list, 0, yexpr_t);
-    assert(for_expr->typ == YEXPR_LIST);
-
-    yexpr_debug(&program);
-    ypreprocess_resolve_builtins(&program);
-    ypreprocess_refs(&program);
-    yexpr_debug(&program);
-
-    yeval_state_t state = {.call_stack = YVEC_NEW(NULL, 0, yexpr_t)};
-    state.locals = YVEC_NEW(NULL, 0, yeval_local_def_t);
-    YVEC_PUSH(&state.call_stack, for_expr);
-
-    yexpr_t result = ybuiltin_run(YBUILTIN_FOR, &state);
-    assert(result.typ == YEXPR_LIST);
-
-    yexpr_debug(&result);
-
-    yvec_destroy(&state.call_stack);
-    yvec_destroy(&state.locals);
-    yexpr_destroy(&program);
-    yexpr_destroy(&result);
-    ystr_destroy(&input);
-}
-
-void test_builtin_for_complex(void) {
-    fprintf(stderr, "test_builtin_for_complex ============\n");
-
-    ystr_t input = ystr_new("(for loopvar (1 2 3) (+ loopvar 1 2))"),
-           error = ystr_new(NULL);
-    yexpr_t program = yexpr_new();
-    assert(yparse_str(&input, &program, &error));
-    yexpr_t* for_expr = YVEC_AT(&program.value.list, 0, yexpr_t);
-    assert(for_expr->typ == YEXPR_LIST);
-
-    ypreprocess(&program);
-    yexpr_debug(for_expr);
-
-    yeval_state_t state = {.call_stack = YVEC_NEW(NULL, 0, yexpr_t)};
-    state.locals = YVEC_NEW(NULL, 0, yeval_local_def_t);
-    YVEC_PUSH(&state.call_stack, for_expr);
-
-    yexpr_t result = ybuiltin_run(YBUILTIN_FOR, &state);
-    assert(result.typ == YEXPR_LIST);
-
-    // (1 2 3) should each be increased by 3.
-    yexpr_debug(&result);
-    assert(4 == YVEC_AT(&result.value.list, 0, yexpr_t)->value.n);
-
-    yvec_destroy(&state.call_stack);
-    yvec_destroy(&state.locals);
-    yexpr_destroy(&program);
-    yexpr_destroy(&result);
-    ystr_destroy(&input);
-}
-
-void test_builtin_for_noresult(void) {
-    fprintf(stderr, "test_builtin_for_noresult ============\n");
-
-    ystr_t input = ystr_new("(for loopvar (1 2 3) (undef))"),
-           error = ystr_new(NULL);
-    yexpr_t program = yexpr_new();
-    assert(yparse_str(&input, &program, &error));
-    yexpr_t* for_expr = YVEC_AT(&program.value.list, 0, yexpr_t);
-    assert(for_expr->typ == YEXPR_LIST);
-
-    ypreprocess_resolve_builtins(&program);
-    ypreprocess_refs(&program);
-    yexpr_debug(for_expr);
-
-    yeval_state_t state = {.call_stack = YVEC_NEW(NULL, 0, yexpr_t)};
-    state.locals = YVEC_NEW(NULL, 0, yeval_local_def_t);
-    YVEC_PUSH(&state.call_stack, for_expr);
-
-    yexpr_t result = ybuiltin_run(YBUILTIN_FOR, &state);
-    assert(result.typ == YEXPR_LIST);
-    assert(result.value.list.len == 0);
-
-    yvec_destroy(&state.call_stack);
-    yvec_destroy(&state.locals);
-    yexpr_destroy(&program);
-    ystr_destroy(&input);
-    yexpr_destroy(&result);
-}
-
-void test_builtin_let(void) {
-    fprintf(stderr, "test_builtin_let ============\n");
-
-    yexpr_t ref_expr = yexpr_new();
-    yexpr_t let_expr = yexpr_new();
-    yref_t ref = yref_new();
-    yexpr_t val_expr = yexpr_new();
-    yexpr_t let_call = yexpr_new();
-
-    // (let <ref> 'my-atom)
-    yexpr_set_ref(&ref_expr, ref);
-    yexpr_set_builtin(&let_expr, YBUILTIN_LET);
-    yexpr_set_atom(&val_expr, yatom_get_or_add("my-atom"));
-
-    yvec_t let_args;
-    YVEC_INIT(&let_args, 4, yexpr_t);
-    YVEC_PUSH(&let_args, &let_expr);
-    YVEC_PUSH(&let_args, &ref_expr);
-    YVEC_PUSH(&let_args, &val_expr);
-
-    yexpr_set_list(&let_call, let_args);
-
-    // NOTE: The expressions should be copied, but for this test we can store
-    // them directly.
-    yeval_state_t state;
-    yvec_t* stack = &state.call_stack;
-    YVEC_INIT(stack, 4, yexpr_t);
-    YVEC_PUSH(stack, &let_call);
-
-    yexpr_t result = ybuiltin_run(YBUILTIN_LET, &state);
-    yexpr_debug(&result);
-    assert(result.typ == YEXPR_UNDEF);
-    assert(stack->len == 0);
-
-    yvalue_t* stored = yvalue_get(ref);
-    assert(stored->typ == YVALUE_EXPR);
-    assert(stored->value.expr.typ == YEXPR_ATOM);
-    assert(stored->value.expr.value.atom == val_expr.value.atom);
-
-    // Type mismatch exception.
-    yexpr_set_number(YVEC_AT(&let_call.value.list, 1, yexpr_t), 124);
-    YVEC_PUSH(stack, &let_call);
-    result = ybuiltin_run(YBUILTIN_LET, &state);
-    yexpr_debug(&result);
-    assert(result.typ == YEXPR_EXCEPTION);
-    assert(stack->len == 0);
-    yexpr_destroy(&result);
-
-    // Not enough arguments on stack.
-    result = ybuiltin_run(YBUILTIN_LET, &state);
-    assert(result.typ == YEXPR_EXCEPTION);
-    fputs(ystr_str(&result.value.str), stderr);
-    fputs("\n", stderr);
-    assert(0 ==
-           ystr_cmp_str(
-               &result.value.str,
-               "BUILTIN:LET: BUG: not enough arguments on call stack: NULL"));
-
-    yexpr_destroy(&result);
-    yexpr_destroy(&ref_expr);
-    yexpr_destroy(&val_expr);
-    yexpr_destroy(&let_call);
-    yvec_destroy(stack);
-};
-
-void test_builtin_let_parsed(void) {
-    fprintf(stderr, "test_builtin_let_parsed ============\n");
-
-    ystr_t input = ystr_new("(let my-var (1 2 3))"), error = ystr_new(NULL);
-    yexpr_t program = yexpr_new(), *let_expr;
-    assert(yparse_str(&input, &program, &error));
-    ypreprocess_resolve_builtins(&program);
-
-    let_expr = YVEC_AT(&program.value.list, 0, yexpr_t);
-
-    yeval_state_t state;
-    YVEC_INIT(&state.call_stack, 4, yexpr_t);
-    state.locals = YVEC_NEW(NULL, 0, yeval_local_def_t);
-    YVEC_PUSH(&state.call_stack, let_expr);
-    yexpr_t result = ybuiltin_run(YBUILTIN_LET, &state);
-    assert(result.typ == YEXPR_UNDEF);
-    assert(state.call_stack.len == 0);
-
-    // Retrieve stored value.
-    yref_t my_var_ref = yref_new_c("my-var");
-    yvalue_t* stored = yvalue_get(my_var_ref);
-    assert(stored->typ == YVALUE_EXPR);
-    assert(stored->value.expr.typ == YEXPR_LIST);
-    assert(stored->value.expr.value.list.len == 3);
-    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);
-    yvec_destroy(&state.locals);
-    ystr_destroy(&input);
-    ystr_destroy(&error);
-}
-
-void test_builtin_let_recall(void) {
-    fprintf(stderr, "test_builtin_let_recall ============\n");
-
-    ystr_t input = ystr_new(
-        "(let my-var ('a 'b) \"cd\")"
-        "(my-var)");
-    ystr_t error = ystr_new(NULL);
-    yexpr_t program = yexpr_new();
-    assert(yparse_str(&input, &program, &error));
-    assert(YEXPR_LIST == program.typ && 2 == program.value.list.len);
-
-    ypreprocess_resolve_builtins(&program);
-
-    yeval_state_t state = {.call_stack = YVEC_NEW(NULL, 0, yexpr_t)};
-    state.locals = YVEC_NEW(NULL, 0, yeval_local_def_t);
-    // Evaluate whole program
-    yexpr_t result = yeval_list_return_last(&state, &program.value.list, 0);
-
-    // Check that result is "cd"
-    assert(YEXPR_LIST == result.typ && 1 == result.value.list.len);
-    yexpr_t* inner = YVEC_AT(&result.value.list, 0, yexpr_t);
-    assert(YEXPR_STRING == inner->typ);
-    yexpr_debug(inner);
-    assert(0 == ystr_cmp_str(&inner->value.str, "cd"));
-
-    yvec_destroy(&state.call_stack);
-    yvec_destroy(&state.locals);
-    yexpr_destroy(&result);
-    ystr_destroy(&error);
-    ystr_destroy(&input);
-    yexpr_destroy(&program);
-}
-
-void test_builtin_eq(void) {
-    fprintf(stderr, "test_builtin_eq ============\n");
-
-    ystr_t input = ystr_new(
-        "(let var-a 1)"
-        "(let var-b 'atom)"
-        "(let var-c \"string\")"
-        "((== var-a 1) (== 1 var-a) (== var-a var-a) (== for for) (== (1 2 3) "
-        "(var-a 2 3)) (== var-b 'atom) (== "
-        "'atom2 'atom2) (== "
-        "var-c \"string\"))");
-    ystr_t error = ystr_new(NULL);
-    yexpr_t program = yexpr_new();
-    assert(yparse_str(&input, &program, &error));
-
-    yexpr_debug(&program);
-    ypreprocess(&program);
-    yexpr_debug(&program);
-
-    yeval_state_t state;
-    YVEC_INIT(&state.call_stack, 4, yexpr_t);
-    state.locals = YVEC_NEW(NULL, 0, yeval_local_def_t);
-    yexpr_t result = yeval_list_return_last(&state, &program.value.list, 0);
-    assert(result.typ == YEXPR_LIST);
-    yexpr_debug(&result);
-    for (size_t i = 0; i < result.value.list.len; i++) {
-        yexpr_t* elem = YVEC_AT(&result.value.list, i, yexpr_t);
-        assert(YEXPR_ATOM == elem->typ &&
-               yatom_get_or_add("true") == elem->value.atom);
-    }
-
-    yexpr_destroy(&result);
-    yexpr_destroy(&program);
-    ystr_destroy(&input);
-    ystr_destroy(&error);
-    yvec_destroy(&state.call_stack);
-    yvec_destroy(&state.locals);
-}
-
-void test_builtin_print(void) {
-    fprintf(stderr, "test_builtin_print ============\n");
-
-    char buf[512];
-    memset(buf, 0, 512);
-    FILE* output = fmemopen(buf, 512, "w");
-
-    ybuiltin_set_output(output);
-
-    ystr_t input = ystr_new(
-            "(let a \"hello\")"
-            "(let b 'world)"
-            "(print 1 a b)");
-    ystr_t expected = ystr_new("1 hello world");
-
-    ystr_t error = ystr_new(NULL);
-    yexpr_t program = yexpr_new();
-    assert(yparse_str(&input, &program, &error));
-
-    ypreprocess(&program);
-
-    yeval_state_t state;
-    YVEC_INIT(&state.call_stack, 4, yexpr_t);
-    state.locals = YVEC_NEW(NULL, 0, yeval_local_def_t);
-
-    yexpr_t result = yeval_list_return_last(&state, &program.value.list, 0);
-    assert(result.typ == YEXPR_UNDEF);
-
-    fclose(output);
-
-    assert(0 == ystr_cmp_str(&expected, buf));
-
-    ystr_destroy(&expected);
-    yexpr_destroy(&result);
-    yexpr_destroy(&program);
-    ystr_destroy(&input);
-    ystr_destroy(&error);
-    yvec_destroy(&state.call_stack);
-    yvec_destroy(&state.locals);
-}
 
 int main(void) {
     test_builtin_translate();
-    test_builtin_for();
-    test_builtin_for_complex();
-    test_builtin_for_noresult();
-    test_builtin_let();
-    test_builtin_let_parsed();
-    test_builtin_let_recall();
-    test_builtin_eq();
-    test_builtin_print();
-
-    yvalue_free_all();
     yatom_free_all();
     return 0;
 }
--- a/src/eval.c	Sat Sep 28 19:13:26 2019 +0200
+++ b/src/eval.c	Sun Sep 29 14:14:04 2019 +0200
@@ -5,3 +5,14 @@
 #include "expr.h"
 #include "value.h"
 
+yexpr_t yeval(yeval_t* state, yexpr_t* expr) {
+    return yexpr_new();
+}
+
+yexpr_t yeval_noresult(yeval_t* state, yexpr_t* expr) {
+    return yexpr_new();
+}
+
+yexpr_t yeval_list_return_last(yeval_t* state, yvec_t* list, size_t start) {
+    return yexpr_new();
+}
--- a/src/eval.h	Sat Sep 28 19:13:26 2019 +0200
+++ b/src/eval.h	Sun Sep 29 14:14:04 2019 +0200
@@ -11,6 +11,38 @@
  * @{
  */
 
+/// A mapping from reference to value.
+typedef struct {
+    yref_t ref;
+    yexpr_t val;
+} yeval_map_t;
+
+/// Evaluation state.
+typedef struct {
+    yvec_t /* <yeval_map_t> */ vars;
+} yeval_t;
+
+/**
+ * @brief Create a valid initial evaluation state.
+ */
+yeval_t yeval_new_state(void);
+
+/**
+ * Evaluate an expression yielding a result expression.
+ */
+yexpr_t yeval(yeval_t* state, yexpr_t* expr);
+
+/**
+ * @brief Evaluate an expression purely for side effects. Only exceptions are
+ * returned as such, if no exception occurred, a YEXPR_UNDEF value is returned.
+ */
+yexpr_t yeval_noresult(yeval_t* state, yexpr_t* expr);
+
+/**
+ * @brief Evaluate expressions in `list` starting at `start` and return the
+ * result of the last expression.
+ */
+yexpr_t yeval_list_return_last(yeval_t* state, yvec_t* list, size_t start);
 
 /**
  * @}
--- a/src/eval_test.c	Sat Sep 28 19:13:26 2019 +0200
+++ b/src/eval_test.c	Sun Sep 29 14:14:04 2019 +0200
@@ -8,7 +8,6 @@
 
 
 int main(void) {
-    yvalue_free_all();
     yatom_free_all();
     return 0;
 }
--- a/src/expr.c	Sat Sep 28 19:13:26 2019 +0200
+++ b/src/expr.c	Sun Sep 29 14:14:04 2019 +0200
@@ -46,10 +46,13 @@
 #undef list
             break;
         case YEXPR_FUNC:
-            for (size_t i = 0; i < v->value.closure->captured.len; i++)
-                yexpr_destroy(YVEC_AT(&v->value.closure->captured, i, yexpr_t));
+            for (size_t i = 0; i < v->value.closure->captured.len; i++) {
+                yref_destroy(&YVEC_AT(&v->value.closure->captured, i, yeval_map_t)->ref);
+                yexpr_destroy(&YVEC_AT(&v->value.closure->captured, i, yeval_map_t)->val);
+            }
+            for (size_t i = 0; i < v->value.closure->args.len; i++)
+                yref_destroy(YVEC_AT(&v->value.closure->args, i, yref_t));
             yvec_destroy(&v->value.closure->captured);
-            yref_destroy(&v->value.closure->id);
             free(v->value.closure);
             break;
         default:
@@ -82,15 +85,7 @@
             copy.value.ref = yref_clone(&orig->value.ref);
             break;
         case YEXPR_FUNC:
-            copy.value.closure = malloc(sizeof(yclosure_t));
-            copy.value.closure->captured =
-                yvec_clone(&orig->value.closure->captured);
-            yvec_t* captured = &copy.value.closure->captured;
-            for (size_t i = 0; i < captured->len; i++) {
-                *YVEC_AT(captured, i, yexpr_t) = yexpr_copy(
-                    YVEC_AT(&orig->value.closure->captured, i, yexpr_t));
-            }
-            copy.value.closure->id = yref_clone(&orig->value.closure->id);
+            copy.value.closure = orig->value.closure;
             break;
         case YEXPR_LIST:
             // Recursively copy list...
@@ -162,13 +157,10 @@
     v->value.str = message;
 }
 
-void yexpr_set_closure(yexpr_t* v, yref_t funcref, yvec_t captured) {
+void yexpr_set_closure(yexpr_t* v, yclosure_t* cl) {
     yexpr_destroy(v);
     v->typ = YEXPR_FUNC;
-    v->value.closure = malloc(sizeof(yclosure_t));
-    yclosure_t* closure = v->value.closure;
-    closure->id = funcref;
-    closure->captured = captured;
+    v->value.closure = cl;
 }
 
 void yexpr_append_value(yexpr_t* v, yexpr_t new_val) {
@@ -196,11 +188,7 @@
         case YEXPR_EXCEPTION:
             return 0 == ystr_cmp(&a->value.str, &b->value.str);
         case YEXPR_REF:
-            if (yref_eq(&a->value.ref, &b->value.ref)) return true;
-            yvalue_t* aexpr = yvalue_get(a->value.ref);
-            yvalue_t* bexpr = yvalue_get(b->value.ref);
-            if (aexpr->typ != bexpr->typ) return false;
-            return yexpr_equal(&aexpr->value.expr, &bexpr->value.expr);
+            return yref_eq(&a->value.ref, &b->value.ref);
         case YEXPR_LIST:
             if (a->value.list.len != b->value.list.len) return false;
             for (size_t i = 0; i < a->value.list.len; i++) {
@@ -271,18 +259,12 @@
             ystr_build(&tmp, "EXCEPTION<%s>", ystr_str(&expr->value.str));
             break;
         case YEXPR_FUNC:
-            ystr_build(&tmp, "CLOSURE");
-            yvalue_t* funcval = yvalue_get(expr->value.closure->id);
-            if (funcval == NULL) {
-                ystr_build(&tmp, "<INVALID-REF>");
-                break;
+            ystr_build(&tmp, "CLOSURE<");
+            yclosure_t* cl = expr->value.closure;
+            for (size_t i = 0; i < cl->args.len; i++) {
+                ystr_build(&tmp, "%s ", yref_debug(YVEC_AT(&cl->args, i, yref_t)));
             }
-            if (funcval->typ != YVALUE_FUNC) {
-                ystr_build(&tmp, "<INVALID-VALUE-REF>");
-                break;
-            }
-            yfunc_t* func = &funcval->value.func;
-            ystr_build(&tmp, "<%s>", ystr_str(&func->name));
+            ystr_build(&tmp, ">");
             break;
         default:
             assert(false /* Unhandled YEXPR_TYPE */);
--- a/src/expr.h	Sat Sep 28 19:13:26 2019 +0200
+++ b/src/expr.h	Sun Sep 29 14:14:04 2019 +0200
@@ -87,7 +87,7 @@
  * function) with `captured` values (vector of yexpr_t in order of the
  * `captured` field of the function).
  */
-void yexpr_set_closure(yexpr_t* v, yref_t funcref, yvec_t captured);
+void yexpr_set_closure(yexpr_t* v, yclosure_t* cl);
 
 /**
  * Initialize a yexpr_t value if not yet done and append another value to it.
--- a/src/expr_test.c	Sat Sep 28 19:13:26 2019 +0200
+++ b/src/expr_test.c	Sun Sep 29 14:14:04 2019 +0200
@@ -20,13 +20,8 @@
 
     yexpr_destroy(&exprref);
 
-    ystr_t str2 = ystr_new("abc");
-    ref = yref_new_id(yvalue_resolve_or_create_symbol(&str2));
-    assert(YREF_ID == yref_type(&ref));
-    ystr_destroy(&str2);
-    ref0 = ref;
-
-    ref = yref_new();
+    ref0 = yref_new_anon();
+    ref = yref_new_anon();
     assert(YREF_ID == yref_type(&ref));
     assert(ref.ref.id == ref0.ref.id + 1);
 }
@@ -96,8 +91,7 @@
     // Test refs, symbolic and numeric.
     yexpr_set_ref(&expr, yref_new_c("my-ref"));
     yexpr_debug(&expr);
-    yvalue_resolve_or_create_ref(&expr.value.ref);
-    assert(YREF_ID == yref_type(&expr.value.ref));
+    assert(YREF_SYM == yref_type(&expr.value.ref));
     yexpr_debug(&expr);
     yexpr_destroy(&expr);
     expr = yexpr_new();
--- a/src/preprocess_test.c	Sat Sep 28 19:13:26 2019 +0200
+++ b/src/preprocess_test.c	Sun Sep 29 14:14:04 2019 +0200
@@ -12,7 +12,6 @@
 
 int main(void) {
     fprintf(stderr, "global destroy ===========\n");
-    yvalue_free_all();
     yatom_free_all();
     return 0;
 }
--- a/src/sizes_test.c	Sat Sep 28 19:13:26 2019 +0200
+++ b/src/sizes_test.c	Sun Sep 29 14:14:04 2019 +0200
@@ -34,7 +34,7 @@
     assert(24 == sizeof(yexpr_t));
     assert(16 == sizeof(yref_t));
     assert(48 == sizeof(yfunc_t));
-    assert(32 == sizeof(yclosure_t));
+    assert(40 == sizeof(yclosure_t));
 }
 
 /**
--- a/src/types.h	Sat Sep 28 19:13:26 2019 +0200
+++ b/src/types.h	Sun Sep 29 14:14:04 2019 +0200
@@ -22,13 +22,10 @@
 typedef enum {
     /// An uninitialized reference.
     YREF_UNDEF = 0,
-    /// A reference into the global value table - deprecated.
+    /// A numeric reference.
     YREF_ID = 1,
-    /// An unresolved reference consisting of a string in the `ref.sym` field.
+    /// A reference consisting of a string in the `ref.sym` field.
     YREF_SYM = 2,
-    /// A stack-relative reference
-    YREF_STACK = 3,
-    YREF_LOCAL = 4,
 } YREF_TYPE;
 
 /**
@@ -42,10 +39,8 @@
     union {
         /// A symbol, i.e. name, of a variable or function.
         ystr_t sym;
-        /// An ID pointing to a slot in the values table (see value.c)
+        /// A numeric ID.
         yvalue_id_t id;
-        /// An ID pointing to a position on the call stack.
-        yvalue_id_t sid;
     } ref;
 } yref_t;
 
@@ -82,8 +77,6 @@
 
     YBUILTIN_RAISE = 15,
     YBUILTIN_RECOVER = 16,
-
-    YBUILTIN_INTERNAL_MKCLSR = 17,
 } YBUILTIN_TYPE;
 
 /**
@@ -114,11 +107,16 @@
     YEXPR_EXCEPTION = 8,
 } YEXPR_TYPE;
 
+struct yexpr_t;
+typedef struct yexpr_t yexpr_t;
+
 typedef struct {
     /// Reference to function code.
-    yref_t id;
-    /// List of ycaptured_t.
-    yvec_t captured;
+    yexpr_t* body;
+    /// Arguments.
+    yvec_t /* <yref_t> */ args;
+    /// Captured variables.
+    yvec_t /* <yeval_map_t> */ captured;
 } yclosure_t;
 
 /**
--- a/src/value.c	Sat Sep 28 19:13:26 2019 +0200
+++ b/src/value.c	Sun Sep 29 14:14:04 2019 +0200
@@ -4,4 +4,84 @@
 #include <search.h>
 #include <string.h>
 
+const yref_t YREF_NULL = { .ref.sym.inner.big = {.base = NULL, .cap = 0, .len = 0, .size = 0} };
 
+const yvalue_id_t YREF_ID_MARKER = 0xff00000000000000;
+
+YREF_TYPE yref_type(yref_t* ref) {
+    if ((YREF_ID_MARKER & ref->ref.id) == YREF_ID_MARKER)
+        return YREF_ID;
+    return YREF_SYM;
+}
+
+ystr_t yref_debug(yref_t* ref) {
+    ystr_t tmp = ystr_new(NULL);
+
+    if (yref_is_null(ref)) {
+        ystr_build(&tmp, "r:NULL");
+        return tmp;
+    }
+
+    switch (yref_type(ref)) {
+        case YREF_ID:
+            ystr_build(&tmp, "r:%llu", ref->ref.id);
+            return tmp;
+        case YREF_SYM:
+            ystr_build(&tmp, "r:%s", ystr_str(&ref->ref.sym));
+            return tmp;
+        default:
+            ystr_build(&tmp, "r:INVALID");
+            return tmp;
+    }
+}
+
+yref_t yref_new_null(void) {
+    return YREF_NULL;
+}
+
+bool yref_is_null(yref_t* ref) {
+    return 0 == (ref->ref.id & YREF_ID_MARKER) && ystr_len(&ref->ref.sym) == 0;
+}
+
+yref_t yref_new_anon(void) {
+    static yvalue_id_t anon_counter = YREF_ID_MARKER | 0x0010101010101010;
+    yref_t ref;
+    ref.ref.id = anon_counter++;
+    return ref;
+}
+
+yref_t yref_new_str(ystr_t* sym) {
+    yref_t ref;
+    ref.ref.sym = *sym;
+    return ref;
+}
+
+yref_t yref_new_c(const char* sym) {
+    yref_t ref;
+    ref.ref.sym = ystr_new(sym);
+    return ref;
+}
+
+bool yref_eq(yref_t* a, yref_t* b) {
+    if (yref_type(a) == YREF_ID && yref_type(b) == YREF_ID) {
+        return a->ref.id == b->ref.id;
+    } else if (yref_type(a) == YREF_SYM && yref_type(b) == YREF_SYM) {
+        return ystr_cmp(&a->ref.sym, &b->ref.sym) == 0;
+    }
+    return false;
+}
+
+yref_t yref_clone(yref_t* ref) {
+    if (yref_type(ref) == YREF_SYM) {
+        yref_t new = *ref;
+        new.ref.sym = ystr_clone(&ref->ref.sym);
+        return new;
+    }
+    return *ref;
+}
+
+void yref_destroy(yref_t* ref) {
+    if (yref_type(ref) == YREF_SYM)
+        ystr_destroy(&ref->ref.sym);
+    return;
+}
--- a/src/value.h	Sat Sep 28 19:13:26 2019 +0200
+++ b/src/value.h	Sun Sep 29 14:14:04 2019 +0200
@@ -15,11 +15,64 @@
 
 /**
  * @file value.h
- * @brief Types and functions for describing values and references to values.
+ * @brief Types and functions for describing references to values.
  * @addtogroup language
  * @{
  */
 
+/// A void reference.
+extern const yref_t YREF_NULL;
+
+/**
+ * @brief Retrieve the type of a reference.
+ */
+YREF_TYPE yref_type(yref_t* ref);
+
+/**
+ * @brief Return a null reference.
+ */
+yref_t yref_new_null(void);
+
+/**
+ * @brief Return a debug representation of a reference. The caller owns the returned string.
+ */
+ystr_t yref_debug(yref_t* ref);
+
+/**
+ * @brief Returns true if ref is void.
+ */
+bool yref_is_null(yref_t* ref);
+
+/**
+ * @brief Returns an anonymous reference.
+ */
+yref_t yref_new_anon(void);
+
+/**
+ * @brief Return a named reference. Ownership of `sym` is transferred to the new reference.
+ */
+yref_t yref_new_str(ystr_t* sym);
+
+/**
+ * @brief Return a named reference from the C string.
+ */
+yref_t yref_new_c(const char* sym);
+
+/**
+ * @brief Returns true if the two references are identical.
+ */
+bool yref_eq(yref_t* a, yref_t* b);
+
+/**
+ * @brief Clone a reference.
+ */
+yref_t yref_clone(yref_t* ref);
+
+/**
+ * @brief Free a reference.
+ */
+void yref_destroy(yref_t* ref);
+
 /**
  * @}
  */
--- a/src/value_test.c	Sat Sep 28 19:13:26 2019 +0200
+++ b/src/value_test.c	Sun Sep 29 14:14:04 2019 +0200
@@ -2,133 +2,7 @@
 
 #include <assert.h>
 
-void test_value_create_resolve(void) {
-    ystr_t sym;
-    ystr_init(&sym, "vcr_symbol");
-
-    assert(YVALUE_INVALID_ID == yvalue_resolve_symbol(&sym));
-
-    yvalue_id_t id = yvalue_resolve_or_create_symbol(&sym);
-    assert(YVALUE_INVALID_ID != id);
-    assert(id == yvalue_resolve_symbol(&sym));
-
-    yvalue_id_t id2 = yvalue_create();
-    assert(id2 != id);
-    assert(id2 == id+1);
-
-    ystr_destroy(&sym);
-}
-
-void test_ref_create_resolve(void) {
-    ystr_t symbol = ystr_new("rcr_symbol_long_long");
-    ystr_t symbol2 = ystr_new(NULL);
-    ystr_copy(&symbol, &symbol2);
-    yref_t ref = yref_new_str(&symbol);  // symbol is now owned by ref.
-
-    yref_t cloned = yref_clone(&ref);
-    assert(cloned.ref.sym.inner.big.base != ref.ref.sym.inner.big.base);
-
-    yvalue_resolve_or_create_ref(&ref);
-    assert(YVALUE_INVALID_ID != yvalue_resolve_symbol(&symbol2));
-    assert(YREF_ID == yref_type(&ref));
-    assert(ref.ref.id == yref_clone(&ref).ref.id);
-    assert(YREF_SYM == yref_type(&cloned));
-    assert(ref.ref.id == yvalue_resolve_symbol(&symbol2));
-
-    ystr_destroy(&symbol2);
-    yref_destroy(&ref);
-    yref_destroy(&cloned);
-}
-
-void test_value_clone(void) {
-    yvalue_t first_value = { .typ = YVALUE_EXPR, .value.expr = yexpr_new() };
-    yexpr_set_str(&first_value.value.expr, ystr_new("a long external test string"));
-    yref_t first = yvalue_set(YVALUE_INSERT, &first_value);
-    yref_t second = yvalue_set(YVALUE_INSERT, &first_value);
-    yref_t cloned = yvalue_clone(&first);
-    assert(first.ref.id != cloned.ref.id);
-
-    *ystr_at(&yvalue_get(first)->value.expr.value.str, 0) = 'A';
-    assert('A' == *ystr_at(&yvalue_get(first)->value.expr.value.str, 0));
-    assert('A' == *ystr_at(&yvalue_get(second)->value.expr.value.str, 0));
-    assert('A' == *ystr_at(&yvalue_get(yref_clone(&first))->value.expr.value.str, 0));
-    assert('a' == *ystr_at(&yvalue_get(cloned)->value.expr.value.str, 0));
-
-    // Double-free expected!
-}
-
-void test_value_set(void) {
-    yexpr_t expr;
-    expr.typ = YEXPR_NUMBER;
-    expr.value.n = 12345;
-    yvalue_t val;
-    val.typ = YVALUE_EXPR;
-    val.value.expr = expr;
-
-    // Allocate unnamed ref.
-    yref_t ref = yvalue_set(YVALUE_INSERT, &val);
-    assert(YREF_ID == yref_type(&ref));
-    yvalue_t* got = yvalue_get(ref);
-    assert(YVALUE_EXPR == got->typ);
-    assert(YEXPR_NUMBER == got->value.expr.typ);
-    assert(12345 == got->value.expr.value.n);
-
-    // Use named refs.
-    ystr_t symbol = ystr_new("vs_symbol");
-    ystr_t symbol2 = ystr_new("vs_symbol");
-
-    val.value.expr.value.n = 12346;
-    yvalue_id_t id = yvalue_resolve_or_create_symbol(&symbol);
-    yref_t ref2 = yref_new_id(id);
-    yref_t ref2b = yvalue_set(ref2, &val);
-    assert(ref2b.ref.id == ref2.ref.id);
-    yvalue_t* got2 = yvalue_get(ref2);
-    assert(12346 == got2->value.expr.value.n);
-
-    // Get symbolically.
-    yref_t ref3 = yref_new_str(&symbol2);
-    yvalue_t* got3 = yvalue_get(ref3);
-    assert(12346 == got3->value.expr.value.n);
-
-    // Get invalid entry.
-    yref_t ref_invalid = yref_new_c("invalid_entry");
-    assert(NULL == yvalue_get(ref_invalid));
-    assert(NULL != yvalue_get(ref3));
-
-    yvalue_destroy(&val);
-    yref_destroy(&ref);
-    yref_destroy(&ref2);
-    yref_destroy(&ref2b);
-    yref_destroy(&ref3);
-    yref_destroy(&ref_invalid);
-}
-
-void test_value_refs(void) {
-    yref_t ref = yref_new_c("hello");
-    assert(YREF_SYM == yref_type(&ref));
-    assert(yref_eq(&ref, &ref));
-    yref_destroy(&ref);
-    ref = yref_new();
-    assert(YREF_ID == yref_type(&ref));
-    assert(yref_eq(&ref, &ref));
-    yref_destroy(&ref);
-    ref = yref_new_cix(2);
-    assert(YREF_STACK == yref_type(&ref));
-    assert(2 == yref_cix(&ref));
-    assert(yref_eq(&ref, &ref));
-    ystr_t dbg = yref_debug(&ref);
-    assert(0 == ystr_cmp_str(&dbg, "id:<stackrel:-2>"));
-    ystr_destroy(&dbg);
-    yref_destroy(&ref);
-}
-
 int main(void) {
-    test_value_create_resolve();
-    test_ref_create_resolve();
-    test_value_clone();
-    test_value_set();
-    test_value_refs();
-    //yvalue_free_all(); test_value_clone does some weird thigns, so we can't free all values.
     yatom_free_all();
     return 0;
 }