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