diff options
-rw-r--r-- | interpreter/code.c | 73 | ||||
-rw-r--r-- | interpreter/code.h | 4 | ||||
-rw-r--r-- | interpreter/eval.c | 43 | ||||
-rw-r--r-- | interpreter/graphs.c | 29 | ||||
-rw-r--r-- | interpreter/graphs.h | 2 | ||||
-rw-r--r-- | interpreter/print.c | 107 |
6 files changed, 164 insertions, 94 deletions
diff --git a/interpreter/code.c b/interpreter/code.c index be9ece0..ddd8402 100644 --- a/interpreter/code.c +++ b/interpreter/code.c @@ -104,42 +104,49 @@ void code_ne(struct node** result, struct node* a, struct node* b) { fill_node_bool(result, *((int*) a->var1) != *((int*) b->var1)); } +struct code_mapping { + char* name; + void* f; + unsigned char arity; +}; + +static struct code_mapping code_table[] = { + { "time", code_time, 0 }, + { "trace", code_trace, 2 }, + { "add", code_add, 2 }, + { "mul", code_mul, 2 }, + { "sub", code_sub, 2 }, + { "eq", code_eq, 2 }, + { "ge", code_ge, 2 }, + { "gt", code_gt, 2 }, + { "le", code_le, 2 }, + { "lt", code_lt, 2 }, + { "ne", code_ne, 2 }, + { NULL } +}; + unsigned char code_find(char* name, void** function) { - if (!strcmp(name, "time")) { - *function = (void(*)(void)) code_time; - return 0; - } else if (!strcmp(name, "trace")) { - *function = (void(*)(void)) code_trace; - return 2; - } else if (!strcmp(name, "add")) { - *function = (void(*)(void)) code_add; - return 2; - } else if (!strcmp(name, "mul")) { - *function = (void(*)(void)) code_mul; - return 2; - } else if (!strcmp(name, "sub")) { - *function = (void(*)(void)) code_sub; - return 2; - } else if (!strcmp(name, "eq")) { - *function = (void(*)(void)) code_eq; - return 2; - } else if (!strcmp(name, "ge")) { - *function = (void(*)(void)) code_ge; - return 2; - } else if (!strcmp(name, "gt")) { - *function = (void(*)(void)) code_gt; - return 2; - } else if (!strcmp(name, "le")) { - *function = (void(*)(void)) code_le; - return 2; - } else if (!strcmp(name, "lt")) { - *function = (void(*)(void)) code_lt; - return 2; - } else if (!strcmp(name, "ne")) { - *function = (void(*)(void)) code_ne; - return 2; + struct code_mapping *entry = code_table; + while (entry) { + if (!strcmp(name, entry->name)) { + *function = entry->f; + return entry->arity; + } + entry++; } *function = NULL; return 0; } + +#ifdef _FUSPEL_DEBUG +char *code_find_name(void* f) { + struct code_mapping *entry = code_table; + while (entry) { + if (f == entry->f) + return entry->name; + entry++; + } + return NULL; +} +#endif diff --git a/interpreter/code.h b/interpreter/code.h index 144a7c3..8b7d060 100644 --- a/interpreter/code.h +++ b/interpreter/code.h @@ -10,4 +10,8 @@ typedef void (Code_2) (struct node**, struct node*, struct node*); unsigned char code_find(char* name, void** function); +#ifdef _FUSPEL_DEBUG +char *code_find_name(void* f); +#endif + #endif diff --git a/interpreter/eval.c b/interpreter/eval.c index cd72f40..a9d2edc 100644 --- a/interpreter/eval.c +++ b/interpreter/eval.c @@ -89,33 +89,6 @@ void replace_all(fuspel *rules, replacements* repls, struct node** node) { } } -struct node*** flatten_app_args(struct node** from) { - struct node ***result; - unsigned int i; - unsigned char len = 0; - struct node* _from = *from; - - remove_redirects(_from); - - while (_from->kind == NODE_APP) { - len++; - _from = _from->var1; - remove_redirects(_from); - } - len++; - - result = my_calloc(1, sizeof(struct node**) * (len + 1)); - i = 1; - while ((*from)->kind == NODE_APP) { - result[len - i] = (struct node**) &(*from)->var2; - from = (struct node**) &(*from)->var1; - i++; - } - result[0] = from; - result[len] = NULL; - return result; -} - bool match_expr(fuspel* rules, expression* expr, struct node** node, replacements* repls) { replacements* _repls; @@ -164,7 +137,7 @@ int match_rule(fuspel* rules, rewrite_rule* rule, struct node** node, break; case NODE_APP: - node_args = flatten_app_args(node); + node_args = flatten_app_args(node, true); i = 0; if (!strcmp((*node_args[0])->var1, rule->name)) { struct node** node = node_args[++i]; @@ -218,7 +191,7 @@ void eval_code_app(fuspel* rules, struct node** node) { if (root->kind != NODE_CODE || !root->var1) return; - args = flatten_app_args(node); + args = flatten_app_args(node, true); for (i = 1; i <= *((unsigned char*) root->var2); i++) eval(rules, args[i], 0); @@ -242,6 +215,9 @@ struct node** root_node; void eval(fuspel* rules, struct node** node, bool to_rnf) { fuspel* _rules; bool rerun; +#ifdef _FUSPEL_DEBUG + bool print_graph; +#endif replacements* repls; if (!node || !*node) @@ -258,6 +234,9 @@ void eval(fuspel* rules, struct node** node, bool to_rnf) { do { rerun = 0; +#ifdef _FUSPEL_DEBUG + print_graph = true; +#endif switch ((*node)->kind) { case NODE_INT: @@ -316,6 +295,10 @@ void eval(fuspel* rules, struct node** node, bool to_rnf) { free_node(_repls->replacement.node, 1, 1); rerun = 1; +#ifdef _FUSPEL_DEBUG + if (is_code_app(*node)) + print_graph = false; +#endif break; } @@ -354,7 +337,7 @@ void eval(fuspel* rules, struct node** node, bool to_rnf) { } #ifdef _FUSPEL_DEBUG - if (rerun) + if (rerun && print_graph) print_node_to_file(*root_node, NULL, NULL); #endif } while (rerun); diff --git a/interpreter/graphs.c b/interpreter/graphs.c index 3871a50..48284ec 100644 --- a/interpreter/graphs.c +++ b/interpreter/graphs.c @@ -63,6 +63,35 @@ void free_node(struct node* node, unsigned int count, bool free_first) { } } +struct node*** flatten_app_args(struct node** from, bool remove_redirs) { + struct node ***result; + unsigned int i; + unsigned char len = 0; + struct node* _from = *from; + + if (remove_redirs) + remove_redirects(_from); + + while (_from->kind == NODE_APP) { + len++; + _from = _from->var1; + if (remove_redirs) + remove_redirects(_from); + } + len++; + + result = my_calloc(1, sizeof(struct node**) * (len + 1)); + i = 1; + while ((*from)->kind == NODE_APP) { + result[len - i] = (struct node**) &(*from)->var2; + from = (struct node**) &(*from)->var1; + i++; + } + result[0] = from; + result[len] = NULL; + return result; +} + void remove_redirects(struct node *node) { while (node->kind == NODE_REDIRECT) { struct node *child = (struct node*) node->var1; diff --git a/interpreter/graphs.h b/interpreter/graphs.h index a577095..204993c 100644 --- a/interpreter/graphs.h +++ b/interpreter/graphs.h @@ -25,6 +25,8 @@ struct node { void use_node(struct node* node, unsigned int count); void free_node(struct node* node, unsigned int count, bool free_first); +struct node*** flatten_app_args(struct node** from, bool remove_redirs); + void remove_redirects(struct node *node); void cpy_expression_to_node(struct node* dst, expression* src); diff --git a/interpreter/print.c b/interpreter/print.c index 40df756..bc1f6dc 100644 --- a/interpreter/print.c +++ b/interpreter/print.c @@ -3,6 +3,8 @@ #ifdef _FUSPEL_DEBUG #include <inttypes.h> #include <stdbool.h> +#include <string.h> +#include "code.h" #endif #include "log.h" @@ -159,10 +161,34 @@ bool visited_node_exists(struct visited_nodes *list, struct node *node) { return 0; } +char *get_app_name(struct node *node) { + char *name; + if (node->kind == NODE_NAME) { + name = my_calloc(strlen(node->var1) + 1, 1); + strcpy(name, (char*) node->var1); + } else if (node->kind == NODE_CODE) { + name = my_calloc(24, 1); + strncpy(name, code_find_name(node->var1), 23); + } else { + name = my_calloc(9, 1); + strcpy(name, "Redirect"); + } + return name; +} + +void *get_app_root(struct node *node) { + while (node->kind == NODE_APP) + node = node->var1; + return node; +} + void print_node_to_file(struct node* node, FILE* f, struct visited_nodes *visited) { bool close = 0; bool do_free_visited = 0; - unsigned int borderwidth, edgewidth; + + struct node ***args_list; + unsigned int arg_i; + char *app_name; if (visited_node_exists(visited, node)) return; @@ -179,58 +205,77 @@ void print_node_to_file(struct node* node, FILE* f, struct visited_nodes *visite sprintf(fname, "graph-%03u.dot", file_count++); f = fopen(fname, "w"); fprintf(f, "digraph {\n"); - fprintf(f, "node [shape=rectangle];\n"); + fprintf(f, "node [shape=record];\n"); close = 1; } - borderwidth = node->used_count > 20 ? 20 : node->used_count; - edgewidth = borderwidth > 5 ? 5 : borderwidth; - switch (node->kind) { case NODE_INT: - fprintf(f, "%" PRIuPTR " [label=\"%d (%d)\", penwidth=%d];\n", - (uintptr_t) node, *((int*) node->var1), node->used_count, borderwidth); + fprintf(f, "%" PRIuPTR " [label=\"%d\"];\n", + (uintptr_t) node, *((int*) node->var1)); break; case NODE_NAME: - fprintf(f, "%" PRIuPTR " [label=\"%s (%d)\", penwidth=%d];\n", - (uintptr_t) node, (char*) node->var1, node->used_count, borderwidth); + fprintf(f, "%" PRIuPTR " [label=\"%s\"];\n", + (uintptr_t) node, (char*) node->var1); break; case NODE_CODE: - fprintf(f, "%" PRIuPTR " [label=\"code: %p (%d)\", penwidth=%d];\n", - (uintptr_t) node, node->var1, node->used_count, borderwidth); + fprintf(f, "%" PRIuPTR " [label=\"%s\"];\n", + (uintptr_t) node, code_find_name(node->var1)); + break; + + case NODE_APP: + args_list = flatten_app_args(&node, false); + app_name = get_app_name(*args_list[0]); + fprintf(f, "%" PRIuPTR " [label=\"%s", + (uintptr_t) node, + app_name); + my_free(app_name); + for (arg_i = 1; args_list[arg_i]; arg_i++) + fprintf(f, "|<%u>", arg_i); + fprintf(f, "\"];\n"); + for (arg_i = 1; args_list[arg_i]; arg_i++) { + print_node_to_file(*args_list[arg_i], f, visited); + fprintf(f, "%" PRIuPTR ":%d -> %" PRIuPTR ";\n", + (uintptr_t) node, //(*args_list[0])->var1, + arg_i, + (uintptr_t) *args_list[arg_i]); + } + my_free(args_list); break; case NODE_LIST: + if (!node->var1) { + fprintf(f, "%" PRIuPTR " [label=\"Nil\"];\n", + (uintptr_t) node); + break; + } case NODE_TUPLE: - case NODE_APP: if (node->kind == NODE_LIST) - fprintf(f, "%" PRIuPTR " [label=\"List (%d)\", color=gray, fontcolor=gray, penwidth=%d];\n", - (uintptr_t) node, node->used_count, borderwidth); + fprintf(f, "%" PRIuPTR " [label=\"Cons|<l>|<r>\", color=gray, fontcolor=gray];\n", + (uintptr_t) node); else if (node->kind == NODE_TUPLE) - fprintf(f, "%" PRIuPTR " [label=\"Tuple (%d)\", color=gray, fontcolor=gray, penwidth=%d];\n", - (uintptr_t) node, node->used_count, borderwidth); + fprintf(f, "%" PRIuPTR " [label=\"Tuple|<l>|<r>\", color=gray, fontcolor=gray];\n", + (uintptr_t) node); else if (node->kind == NODE_APP) - fprintf(f, "%" PRIuPTR " [label=\"App (%d)\", color=gray, fontcolor=gray, penwidth=%d];\n", - (uintptr_t) node, node->used_count, borderwidth); - - if (node->var1) { - print_node_to_file((struct node*) node->var1, f, visited); - print_node_to_file((struct node*) node->var2, f, visited); - fprintf(f, "%" PRIuPTR " -> %" PRIuPTR " [color=blue, penwidth=%d];\n", - (uintptr_t) node, (uintptr_t) node->var1, edgewidth); - fprintf(f, "%" PRIuPTR " -> %" PRIuPTR " [color=red, penwidth=%d];\n", - (uintptr_t) node, (uintptr_t) node->var2, edgewidth); - } + fprintf(f, "%" PRIuPTR " [label=\"App|<l>|<r>\", color=gray, fontcolor=gray];\n", + (uintptr_t) node); + + print_node_to_file((struct node*) node->var1, f, visited); + print_node_to_file((struct node*) node->var2, f, visited); + fprintf(f, "%" PRIuPTR ":l -> %" PRIuPTR ";\n", + (uintptr_t) node, (uintptr_t) node->var1); + fprintf(f, "%" PRIuPTR ":r -> %" PRIuPTR ";\n", + (uintptr_t) node, (uintptr_t) node->var2); break; case NODE_REDIRECT: - fprintf(f, "%" PRIuPTR " [label=\"Redirection (%d)\", color=gray, fontcolor=gray, penwidth=%d];\n", - (uintptr_t) node, node->used_count, borderwidth); + fprintf(f, "%" PRIuPTR " [label=\"Redirection\", color=gray, fontcolor=gray];\n", + (uintptr_t) node); print_node_to_file((struct node*) node->var1, f, visited); - fprintf(f, "%" PRIuPTR " -> %" PRIuPTR " [penwidth=%d];\n", - (uintptr_t) node, (uintptr_t) node->var1, edgewidth); + fprintf(f, "%" PRIuPTR " -> %" PRIuPTR ";\n", + (uintptr_t) node, (uintptr_t) node->var1); break; } |