changeset 128:38714d118bbd

value: Implement stack-references for function calls
author Lewin Bormann <lbo@spheniscida.de>
date Sun, 01 Sep 2019 19:22:12 +0200
parents dbed1593881c
children e4c55f83eef0
files src/value.c src/value.h src/value_test.c
diffstat 3 files changed, 49 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/value.c	Sun Sep 01 19:21:46 2019 +0200
+++ b/src/value.c	Sun Sep 01 19:22:12 2019 +0200
@@ -36,7 +36,9 @@
 // reference-counting in different table)
 static yvalue_id_t yvalue_counter = YVALUE_COUNTER_OFFSET;
 
+// Marker bytes to distinguish yref_t without an extra field.
 static const yvalue_id_t YVALUE_ID_MARKER = 0xff00000000000000;
+static const uint64_t YVALUE_CIX_MARKER = 0xfe00000000000000;
 
 static inline void yvalue_init_tables(void) {
     if (yvalue_table_initialized) return;
@@ -53,6 +55,9 @@
     if ((ref->ref.id & YVALUE_ID_MARKER) == YVALUE_ID_MARKER) {
         return YREF_ID;
     }
+    if ((ref->ref.id & YVALUE_CIX_MARKER) == YVALUE_CIX_MARKER) {
+        return YREF_STACK;
+    }
     return YREF_SYM;
 }
 
@@ -79,15 +84,24 @@
     return ref;
 }
 
+yref_t yref_new_cix(size_t ix) {
+    yref_t ref = {.ref.cix = ix | YVALUE_CIX_MARKER};
+    return ref;
+}
+
+uint64_t yref_cix(yref_t* ref) { return ref->ref.cix ^ YVALUE_CIX_MARKER; }
+
 yref_t yref_clone(yref_t* ref) {
     switch (yref_type(ref)) {
         case YREF_SYM:
             // Copy string.
             return yref_new_c(ystr_str(&ref->ref.sym));
         case YREF_ID:
+        case YREF_STACK:
             return *ref;
         default:
-            assert(yref_type(ref) == YREF_SYM || yref_type(ref) == YREF_ID);
+            assert(yref_type(ref) == YREF_SYM || yref_type(ref) == YREF_ID ||
+                   yref_type(ref) == YREF_STACK);
             return yref_new();
     }
 }
@@ -116,6 +130,10 @@
         ystr_t s = ystr_new(NULL);
         ystr_build(&s, "id:<\"%s\">", ystr_str(&ref->ref.sym));
         return s;
+    } else if (typ == YREF_STACK) {
+        ystr_t s = ystr_new(NULL);
+        ystr_build(&s, "id:<stackrel:%lld>", -(int64_t)yref_cix(ref));
+        return s;
     }
     return ystr_new("id:INVALID");
 }
@@ -244,7 +262,9 @@
 
 void yvalue_free_all(void) {
     for (yvalue_id_t i = 0; i < yvalue_counter - YVALUE_COUNTER_OFFSET; i++) {
-        yexpr_destroy(YVEC_AT(&yvalue_table, i, yexpr_t));
+        yvalue_t* val = YVEC_AT(&yvalue_table, i, yvalue_t);
+        if (val->typ == YVALUE_EXPR) yexpr_destroy(&val->value.expr);
+        if (val->typ == YVALUE_FUNC) yfunc_destroy(&val->value.func);
     }
 }
 
--- a/src/value.h	Sun Sep 01 19:21:46 2019 +0200
+++ b/src/value.h	Sun Sep 01 19:22:12 2019 +0200
@@ -73,6 +73,16 @@
 yref_t yref_new_c(const char* sym);
 
 /**
+ * Create a new reference to function argument.
+ */
+yref_t yref_new_cix(size_t ix);
+
+/**
+ * Return the stack-relative index of ref.
+ */
+uint64_t yref_cix(yref_t* ref);
+
+/**
  * Create a debug description of ref.
  */
 ystr_t yref_debug(yref_t* ref);
--- a/src/value_test.c	Sun Sep 01 19:21:46 2019 +0200
+++ b/src/value_test.c	Sun Sep 01 19:22:12 2019 +0200
@@ -101,9 +101,26 @@
     yref_destroy(&ref_invalid);
 }
 
+void test_value_refs(void) {
+    yref_t ref = yref_new_c("hello");
+    assert(YREF_SYM == yref_type(&ref));
+    yref_destroy(&ref);
+    ref = yref_new();
+    assert(YREF_ID == yref_type(&ref));
+    yref_destroy(&ref);
+    ref = yref_new_cix(2);
+    assert(YREF_STACK == yref_type(&ref));
+    assert(2 == yref_cix(&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();
 }