From 9bb6fa51e9a621b04119d76801453e123d2cc099 Mon Sep 17 00:00:00 2001 From: c Date: Sat, 13 Apr 2024 10:47:01 -0400 Subject: Many things. --- src/doer.c | 63 ++++++++++++++++++++++++++++++++++++++++------- src/include/doer.h | 2 ++ src/include/tree.h | 26 +++++++++++++------- src/tree.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+), 18 deletions(-) diff --git a/src/doer.c b/src/doer.c index 59742ac..ffcf1fc 100644 --- a/src/doer.c +++ b/src/doer.c @@ -67,6 +67,22 @@ tree_t* doer_find_target_from_call(target_t* targetl, tree_t* call) { } } +tree_t* doer_eval_prim(doer_t* doer) { + switch (doer->tree->type) { + case TREE_TYPE_CALL: + doer_do_call(doer); + return doer_eval_prim(doer); + case TREE_TYPE_DEF: + doer->tree = doer->tree->data.def.val; + return doer_eval_prim(doer); + case TREE_TYPE_LSTR: + case TREE_TYPE_LINT: + return doer->tree; + default: + DIE("???"); + } +} + char* doer_eval_str(doer_t* doer) { // Assume tree type is a simple call to variable. // Search through target list for matching variable. @@ -111,18 +127,32 @@ tree_t* blin_print(doer_t* doer) { tree_t* blin_printl(doer_t* doer) { tree_t* oldt = doer->tree; doer->tree = doer->tree->data.call.arg->data.carg.val; - char* strval = doer_eval_str(doer); + tree_t* arg = doer_eval_prim(doer); - printf( - "%s\n", - strval - ); + char* rval; + + switch (arg->type) { + case TREE_TYPE_LINT: + printf("%d\n", arg->data.lint.val); + rval = ecalloc(64, sizeof(char)); + sprintf(rval, "%d\n", arg->data.lint.val); + break; + case TREE_TYPE_LSTR: + printf("%s\n", arg->data.lstr.val); + rval = ecalloc(arg->data.lstr.len + 2, sizeof(char)); + sprintf(rval, "%s\n", arg->data.lstr.val); + break; + default: + rval = ecalloc(2, sizeof(char)); + rval[0] = '\n'; + rval[1] = '\0'; + } tree_t* lstr = tree_init(TREE_TYPE_LSTR, oldt->parent); - lstr->data.lstr.val = strval; - lstr->data.lstr.len = strlen(strval); + lstr->data.lstr.val = rval; + lstr->data.lstr.len = strlen(rval); - return doer->tree; + return lstr; } tree_t* blin_str_cat(doer_t* doer) { @@ -184,6 +214,7 @@ void doer_do_def(doer_t* doer) { doer_add_target(doer, target); } +#if 0 void doer_do_call(doer_t* doer) { tree_t* oldt = doer->tree; tree_t* blinrval = doer_do_call_blin(doer); // Could modify the *current* @@ -199,9 +230,23 @@ void doer_do_call(doer_t* doer) { tree_destroy(oldt); } +#endif + +void doer_do_call(doer_t* doer) { + tree_t* oldt = doer->tree; + tree_t* blinrval = doer_do_call_blin(doer); // Could modify the *current* + // tree, but only if it's a + // blin. + + if (blinrval) { + tree_swp_call(oldt, blinrval); + } else { + tree_t* newt = doer_find_target_from_call(doer->targets, oldt); + tree_swp_call(oldt, newt); + } +} tree_t* doer_do_call_blin(doer_t* doer) { - // Search through built-in functions first. for (int i = 0; i < sizeof(blinfs) / sizeof(blinf_t); i++) { if (!strcmp(blinfs[i].name, doer->tree->data.call.target)) { return (blinfs[i].fp)(doer); diff --git a/src/include/doer.h b/src/include/doer.h index 0b4337b..a59a81a 100644 --- a/src/include/doer.h +++ b/src/include/doer.h @@ -49,6 +49,8 @@ typedef struct BLINF { void doer_add_target(doer_t* doer, target_t* target); tree_t* doer_find_target_from_call(target_t* targetl, tree_t* call); +// Given a tree, evaluate it to a primitive type. +tree_t* doer_eval_prim(doer_t* doer); // Given a tree, evaluate it to a string (or type error). char* doer_eval_str(doer_t* doer); diff --git a/src/include/tree.h b/src/include/tree.h index e1adf85..5e0279f 100644 --- a/src/include/tree.h +++ b/src/include/tree.h @@ -4,15 +4,15 @@ #include "util.h" typedef enum TREE_TYPE { - TREE_TYPE_BLOCK, - TREE_TYPE_EXPR, - TREE_TYPE_LINT, - TREE_TYPE_LSTR, - TREE_TYPE_TAG, - TREE_TYPE_DARG, - TREE_TYPE_CARG, - TREE_TYPE_DEF, - TREE_TYPE_CALL + TREE_TYPE_BLOCK = 0, + TREE_TYPE_EXPR = 1, // Deprecated. + TREE_TYPE_LINT = 2, + TREE_TYPE_LSTR = 3, + TREE_TYPE_TAG = 4, + TREE_TYPE_DARG = 5, + TREE_TYPE_CARG = 6, + TREE_TYPE_DEF = 7, + TREE_TYPE_CALL = 8, } tree_type_t; /* The Abstract Syntax Tree (AST) structure. */ @@ -87,12 +87,20 @@ tree_t* tree_init(tree_type_t type, tree_t* parent); /* Destroy the AST (if it exists). */ void tree_destroy(tree_t* tree); +void tree_rm(tree_t* t); +// void tree_append(tree_t** dest, tree_t* t); + +tree_t* tree_copy_out(tree_t* tree); + /* Compare two trees. For testing. Returns 1 if the same, otherwise 0. */ int tree_cmp(tree_t* tree_0, tree_t* tree_1); +// Swaps a tree for another. +void tree_swp_call(tree_t* t0, tree_t* t1); + /* Print a tree. */ void tree_print(tree_t* tree, int nest); diff --git a/src/tree.c b/src/tree.c index 6d58220..0497f70 100644 --- a/src/tree.c +++ b/src/tree.c @@ -53,6 +53,7 @@ tree_t* tree_init(tree_type_t type, tree_t* parent) { void tree_destroy(tree_t* tree) { if (!tree) { return; } + // Stop calls from being double freed. if (tree->parent && tree->type == TREE_TYPE_CALL) { tree_t* treep = tree->parent; switch (treep->type) { @@ -112,6 +113,12 @@ void tree_destroy(tree_t* tree) { free(tree); } +tree_t* tree_copy_out(tree_t* tree) { + tree_t* newt = tree_init(tree->type, tree->parent); + memcpy(&newt->data, &tree->data, sizeof(newt->data)); + return newt; +} + int tree_cmp(tree_t* tree_0, tree_t* tree_1) { if ((tree_0 && !tree_1) || (!tree_0 && tree_1)) { return 0; } /* Only 1 is defined (failure). */ if (!tree_0 && !tree_1) { return 1; } /* Both are undefined (success). */ @@ -159,6 +166,71 @@ int tree_cmp(tree_t* tree_0, tree_t* tree_1) { return 0; } +void tree_rm(tree_t* t) { + tree_t* parent = t->parent; + + t->parent = NULL; + + switch (parent->type) { + case TREE_TYPE_BLOCK: + if (parent->data.block.val == t) parent->data.block.val = NULL; + else parent->data.block.nxt = NULL; + break; + case TREE_TYPE_EXPR: // Deprecated? + parent->data.expr.val = NULL; + break; + case TREE_TYPE_TAG: + parent->data.tag.nxt = NULL; + break; + case TREE_TYPE_DARG: + if (parent->data.darg.tag == t) parent->data.darg.tag = NULL; + else parent->data.darg.nxt = NULL; + break; + case TREE_TYPE_CARG: + if (parent->data.carg.val == t) parent->data.carg.val = NULL; + else parent->data.carg.nxt = NULL; + break; + case TREE_TYPE_DEF: + if (parent->data.def.tag == t) parent->data.def.tag = NULL; + else if (parent->data.def.arg == t) parent->data.def.arg = NULL; + else parent->data.def.val = NULL; + break; + case TREE_TYPE_CALL: + parent->data.call.arg = NULL; + break; + default: + LOG_WAR("Fscked state reached."); + break; + } +} + +void tree_swp_call(tree_t* t0, tree_t* t1) { + tree_t* parent = t0->parent; + + tree_rm(t0); + + t1->parent = parent; + + switch (parent->type) { + case TREE_TYPE_BLOCK: + parent->data.block.val = t1; + break; + case TREE_TYPE_EXPR: + parent->data.expr.val = t1; + break; + case TREE_TYPE_CARG: + parent->data.carg.val = t1; + break; + case TREE_TYPE_DEF: + parent->data.def.val = t1; + break; + default: + break; + } + +// tree_destroy(t0); +} + /* Every time I think there's a problem with the parser, it turns out it's just this stupid tree print function. Now it works. Never touching it -- cgit v1.2.3