aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--interpreter/eval.c94
-rw-r--r--interpreter/graphs.c56
-rw-r--r--interpreter/graphs.h4
-rw-r--r--interpreter/print.c8
4 files changed, 119 insertions, 43 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;
}
diff --git a/interpreter/graphs.c b/interpreter/graphs.c
index ad70abb..d793efb 100644
--- a/interpreter/graphs.c
+++ b/interpreter/graphs.c
@@ -10,11 +10,20 @@ void use_node(struct node* node, unsigned int count) {
node->used_count += count;
- if (node->kind == NODE_LIST ||
- node->kind == NODE_TUPLE ||
- node->kind == NODE_APP) {
- use_node(node->var1, count);
- use_node(node->var2, count);
+ switch (node->kind) {
+ case NODE_INT:
+ case NODE_NAME:
+ case NODE_CODE:
+ break;
+
+ case NODE_LIST:
+ case NODE_TUPLE:
+ case NODE_APP:
+ use_node(node->var2, count);
+
+ case NODE_REDIRECT:
+ use_node(node->var1, count);
+ break;
}
}
@@ -24,11 +33,20 @@ void free_node(struct node* node, unsigned int count, unsigned free_first) {
node->used_count -= count;
- if (node->kind == NODE_LIST ||
- node->kind == NODE_TUPLE ||
- node->kind == NODE_APP) {
- free_node((struct node*) node->var1, count, 1);
- free_node((struct node*) node->var2, count, 1);
+ switch (node->kind) {
+ case NODE_INT:
+ case NODE_NAME:
+ case NODE_CODE:
+ break;
+
+ case NODE_LIST:
+ case NODE_TUPLE:
+ case NODE_APP:
+ free_node(node->var2, count, 1);
+
+ case NODE_REDIRECT:
+ free_node(node->var1, count, 1);
+ break;
}
if (node->used_count == 0) {
@@ -38,11 +56,25 @@ void free_node(struct node* node, unsigned int count, unsigned free_first) {
if (node->kind == NODE_CODE)
my_free(node->var2);
+ node->var1 = node->var2 = NULL;
+
if (free_first)
my_free(node);
}
}
+void remove_redirects(struct node *node) {
+ while (node->kind == NODE_REDIRECT) {
+ struct node *child = (struct node*) node->var1;
+ node->kind = child->kind;
+ node->var1 = child->var1;
+ node->var2 = child->var2;
+ child->used_count -= node->used_count;
+ if (child->used_count == 0)
+ my_free(child);
+ }
+}
+
void cpy_expression_to_node(struct node* dst, expression* src) {
if (!dst || !src)
return;
@@ -120,5 +152,9 @@ void cpy_node_to_expression(expression* dst, struct node* src) {
cpy_node_to_expression(dst->var2, src->var2);
}
break;
+
+ case NODE_REDIRECT:
+ cpy_node_to_expression(dst, src->var1);
+ break;
}
}
diff --git a/interpreter/graphs.h b/interpreter/graphs.h
index fcb314e..0cebe9e 100644
--- a/interpreter/graphs.h
+++ b/interpreter/graphs.h
@@ -10,6 +10,8 @@ typedef enum {
NODE_LIST,
NODE_TUPLE,
NODE_APP,
+
+ NODE_REDIRECT /* Redirect to another node */
} node_kind;
struct node {
@@ -22,6 +24,8 @@ struct node {
void use_node(struct node* node, unsigned int count);
void free_node(struct node* node, unsigned int count, unsigned free_first);
+void remove_redirects(struct node *node);
+
void cpy_expression_to_node(struct node* dst, expression* src);
void cpy_node_to_expression(expression* dst, struct node* src);
diff --git a/interpreter/print.c b/interpreter/print.c
index 3f39b13..d2c03ae 100644
--- a/interpreter/print.c
+++ b/interpreter/print.c
@@ -214,6 +214,14 @@ void print_node_to_file(struct node* node, FILE* f, struct visited_nodes *visite
(uintptr_t) node, (uintptr_t) node->var2, node->used_count);
}
break;
+
+ case NODE_REDIRECT:
+ fprintf(f, "%" PRIuPTR " [label=\"%p: Redirection (%d)\", penwidth=%d];\n",
+ (uintptr_t) node, node, node->used_count, node->used_count);
+ print_node_to_file((struct node*) node->var1, f, visited);
+ fprintf(f, "%" PRIuPTR " -> %" PRIuPTR " [label=\"l\", penwidth=%d];\n",
+ (uintptr_t) node, (uintptr_t) node->var1, node->used_count);
+ break;
}
if (close) {