diff options
-rw-r--r-- | interpreter/eval.c | 94 | ||||
-rw-r--r-- | interpreter/graphs.c | 56 | ||||
-rw-r--r-- | interpreter/graphs.h | 4 | ||||
-rw-r--r-- | interpreter/print.c | 8 |
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) { |