changeset 178:d9c942e7f1ad

expr: Integrate YEXPR_FUNC into expr functions (copy, destroy, debug...)
author Lewin Bormann <lbo@spheniscida.de>
date Thu, 12 Sep 2019 08:24:52 +0200
parents e55251d97380
children 53dc68a0488d
files src/expr.c
diffstat 1 files changed, 41 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/expr.c	Thu Sep 12 08:24:29 2019 +0200
+++ b/src/expr.c	Thu Sep 12 08:24:52 2019 +0200
@@ -45,6 +45,13 @@
             yvec_destroy(list);
 #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));
+            yvec_destroy(&v->value.closure->captured);
+            yref_destroy(&v->value.closure->id);
+            free(v->value.closure);
+            break;
         default:
             assert(false /* handle all cases!! */);
     }
@@ -74,6 +81,17 @@
             copy = *orig;
             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);
+            break;
         case YEXPR_LIST:
             // Recursively copy list...
             yvec_init(&copy.value.list, orig->value.list.size,
@@ -144,6 +162,15 @@
     v->value.str = message;
 }
 
+void yexpr_set_closure(yexpr_t* v, yref_t funcref, yvec_t captured) {
+    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;
+}
+
 void yexpr_append_value(yexpr_t* v, yexpr_t new_val) {
     assert(v->typ == YEXPR_UNDEF || v->typ == YEXPR_LIST);
 
@@ -243,6 +270,20 @@
         case YEXPR_EXCEPTION:
             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;
+            }
+            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));
+            break;
         default:
             assert(false /* Unhandled YEXPR_TYPE */);
     }