aboutsummaryrefslogtreecommitdiff
path: root/interpreter/eval.c
diff options
context:
space:
mode:
authorCamil Staps2016-09-24 14:12:05 +0200
committerCamil Staps2016-09-24 14:12:05 +0200
commit4981e0caf24b3906200e4af12593f4e10a17c699 (patch)
treeab24637a480c5a1c3147b8a2dc9d63d8b90fe566 /interpreter/eval.c
parentFix format strings (diff)
Fix issue with overwritten references
Diffstat (limited to 'interpreter/eval.c')
-rw-r--r--interpreter/eval.c94
1 files changed, 61 insertions, 33 deletions
diff --git a/interpreter/eval.c b/interpreter/eval.c
index 5efd0d8..889eeed 100644
--- a/interpreter/eval.c
+++ b/interpreter/eval.c
@@ -19,8 +19,7 @@ typedef struct replacements {
struct replacements* rest;
} replacements;
-void eval(fuspel* rules, struct node** node, replacements* repls,
- unsigned to_rnf);
+void eval(fuspel* rules, struct node** node, unsigned to_rnf);
void push_repl(replacements* repls, char* name, struct node* node, unsigned is_strict) {
while (repls->rest) repls = repls->rest;
@@ -66,11 +65,22 @@ void replace_all(fuspel *rules, replacements* repls, struct node** node) {
node,
*node);
org_used_count = (*node)->used_count;
- free_node(*node, 1, 1);
- *node = repls->replacement.node;
- use_node(*node, org_used_count);
- if (repls->replacement.is_strict)
- eval(rules, node, NULL, 0);
+ if (org_used_count == 1) {
+ free_node(*node, 1, 1);
+ *node = repls->replacement.node;
+ use_node(*node, org_used_count);
+ } else {
+ printf("---- REDIRECTION ---- \n");
+ free_node(*node, 1, 0);
+ (*node)->kind = NODE_REDIRECT;
+ (*node)->var1 = repls->replacement.node;
+ (*node)->var2 = NULL;
+ use_node(*node, org_used_count - 1);
+ }
+ if (repls->replacement.is_strict) {
+ eval(rules, node, 1);
+ free_node(*node, 1, 0);
+ }
break;
}
}
@@ -82,6 +92,10 @@ void replace_all(fuspel *rules, replacements* repls, struct node** node) {
replace_all(rules, repls, (struct node**) &(*node)->var1);
replace_all(rules, repls, (struct node**) &(*node)->var2);
break;
+
+ case NODE_REDIRECT:
+ replace_all(rules, repls, (struct node**) &(*node)->var1);
+ break;
}
}
@@ -91,9 +105,12 @@ struct node*** flatten_app_args(struct node** from) {
unsigned char len = 0;
struct node* _from = *from;
+ remove_redirects(_from);
+
while (_from->kind == NODE_APP) {
len++;
_from = _from->var1;
+ remove_redirects(_from);
}
len++;
@@ -114,12 +131,14 @@ unsigned match_expr(fuspel* rules, expression* expr, struct node** node,
replacements* _repls;
for (_repls = repls; _repls->rest; _repls = _repls->rest);
+ remove_redirects(*node);
+
is_strict |= expr->is_strict;
if (expr->kind == EXPR_INT ||
expr->kind == EXPR_LIST ||
expr->kind == EXPR_TUPLE)
- eval(rules, node, NULL, 1);
+ eval(rules, node, 1);
switch (expr->kind) {
case EXPR_INT:
@@ -189,6 +208,10 @@ int match_rule(fuspel* rules, rewrite_rule* rule, struct node** node,
return -1;
break;
+ case NODE_REDIRECT:
+ return match_rule(rules, rule, (*node)->var1, repls);
+ break;
+
default:
return -1;
}
@@ -199,7 +222,7 @@ unsigned is_code_app(struct node* node) {
return node->kind == NODE_CODE;
}
-void eval_code_app(fuspel* rules, struct node** node, replacements* repls) {
+void eval_code_app(fuspel* rules, struct node** node) {
struct node *root, ***args;
Code_1* f1;
Code_2* f2;
@@ -212,7 +235,7 @@ void eval_code_app(fuspel* rules, struct node** node, replacements* repls) {
args = flatten_app_args(node);
for (i = 1; i <= *((unsigned char*) root->var2); i++)
- eval(rules, args[i], repls, 0);
+ eval(rules, args[i], 0);
switch (*((unsigned char*) root->var2)) {
case 1:
@@ -232,18 +255,15 @@ void eval_code_app(fuspel* rules, struct node** node, replacements* repls) {
struct node** root_node;
#endif
-void eval(fuspel* rules, struct node** node, replacements* repls,
- unsigned to_rnf) {
+void eval(fuspel* rules, struct node** node, unsigned to_rnf) {
fuspel* _rules;
- unsigned rerun, do_free_repls = 0;
+ unsigned rerun;
+ replacements* repls;
if (!node || !*node)
return;
- if (!repls) {
- repls = my_calloc(1, sizeof(replacements));
- do_free_repls = 1;
- }
+ repls = my_calloc(1, sizeof(replacements));
#ifdef _FUSPEL_DEBUG
if (!root_node) {
@@ -268,7 +288,7 @@ void eval(fuspel* rules, struct node** node, replacements* repls,
case NODE_NAME:
case NODE_APP:
if (is_code_app(*node)) {
- eval_code_app(rules, node, repls);
+ eval_code_app(rules, node);
rerun = 1;
break;
}
@@ -305,16 +325,25 @@ void eval(fuspel* rules, struct node** node, replacements* repls,
printf(">\n");
replace_all(rules, _repls->rest, &new_node);
- use_node(new_node, org_used_count - 1);
+
+ if (org_used_count == 1) {
+ free_node(*_node, 1, 1);
+ use_node(new_node, org_used_count - 1);
+ *_node = new_node;
+ } else {
+ free_node(*_node, org_used_count, 0);
+ (*_node)->kind = NODE_REDIRECT;
+ (*_node)->var1 = new_node;
+ (*_node)->var2 = NULL;
+ (*_node)->used_count = org_used_count;
+ use_node(new_node, org_used_count - 1);
+ }
for (__repls = _repls->rest;
__repls && __repls->replacement.node;
__repls = __repls->rest)
free_node(__repls->replacement.node, 1, 1);
- free_node(*_node, 1, 1);
- *_node = new_node;
-
rerun = 1;
break;
}
@@ -334,13 +363,18 @@ void eval(fuspel* rules, struct node** node, replacements* repls,
if (to_rnf)
break;
- eval(rules, (struct node**) &(*node)->var1, repls, to_rnf);
- eval(rules, (struct node**) &(*node)->var2, repls, to_rnf);
+ eval(rules, (struct node**) &(*node)->var1, to_rnf);
+ eval(rules, (struct node**) &(*node)->var2, to_rnf);
break;
case NODE_CODE:
//TODO
break;
+
+ case NODE_REDIRECT:
+ remove_redirects(*node);
+ rerun = 1;
+ break;
}
#ifdef _FUSPEL_DEBUG
@@ -349,30 +383,24 @@ void eval(fuspel* rules, struct node** node, replacements* repls,
#endif
} while (rerun);
- if (do_free_repls) {
- free_repls(repls);
- my_free(repls);
- }
+ free_repls(repls);
+ my_free(repls);
}
expression* eval_main(fuspel* rules) {
struct node* main_node = my_calloc(1, sizeof(struct node));
expression* expr = my_calloc(1, sizeof(expression));
- replacements* repls = my_calloc(1, sizeof(replacements));
main_node->kind = EXPR_NAME;
main_node->used_count = 1;
main_node->var1 = my_calloc(1, 5);
strcpy(main_node->var1, "main");
- eval(rules, &main_node, repls, 0);
+ eval(rules, &main_node, 0);
cpy_node_to_expression(expr, main_node);
free_node(main_node, 1, 1);
- free_repls(repls);
- my_free(repls);
-
return expr;
}