aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/doer.c63
-rw-r--r--src/include/doer.h2
-rw-r--r--src/include/tree.h26
-rw-r--r--src/tree.c72
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