From 2218e6612081d14c2cd3c94391472ffe2f338944 Mon Sep 17 00:00:00 2001 From: Camil Staps Date: Tue, 30 Aug 2016 21:28:08 +0200 Subject: Fix one memory leak mentioned in #2; add debug dot graphs output --- interpreter/code.c | 4 +-- interpreter/eval.c | 76 +++++++++++++++++++++++++++++++--------------------- interpreter/graphs.c | 8 +++--- interpreter/graphs.h | 2 +- interpreter/print.c | 63 +++++++++++++++++++++++++++++++++++++++++++ interpreter/print.h | 6 +++++ 6 files changed, 122 insertions(+), 37 deletions(-) diff --git a/interpreter/code.c b/interpreter/code.c index c194d02..d0b5416 100644 --- a/interpreter/code.c +++ b/interpreter/code.c @@ -6,14 +6,14 @@ #include "mem.h" void fill_node_int(struct node** node, int i) { - free_node(*node, 0); + free_node(*node, 1, 0); (*node)->kind = EXPR_INT; (*node)->var1 = my_calloc(1, sizeof(int)); *((int*) (*node)->var1) = i; } void fill_node_name(struct node** node, char* s) { - free_node(*node, 0); + free_node(*node, 1, 0); (*node)->kind = EXPR_NAME; (*node)->var1 = my_calloc(1, strlen(s) + 1); strcpy((*node)->var1, s); diff --git a/interpreter/eval.c b/interpreter/eval.c index 74b869a..7e762ef 100644 --- a/interpreter/eval.c +++ b/interpreter/eval.c @@ -6,6 +6,10 @@ #include "graphs.h" #include "mem.h" +#ifdef _FUSPEL_DEBUG +#include "print.h" +#endif + typedef struct { char* name; struct node* node; @@ -35,43 +39,38 @@ replacements* push_repl(replacements* repls, char* name, struct node* node) { void replace_all(replacements* repls, struct node** node) { unsigned char i; unsigned int org_used_count; - unsigned rerun = 1; if (!node || !*node) return; - while (rerun) { - rerun = 0; - - switch ((*node)->kind) { - case EXPR_INT: - case EXPR_CODE: - break; + switch ((*node)->kind) { + case EXPR_INT: + case EXPR_CODE: + break; - case EXPR_NAME: - for (i = 0; repls->replacements[i].name; i++) { - if (!strcmp(repls->replacements[i].name, - (char*) (*node)->var1)) { - org_used_count = (*node)->used_count; - free_node(*node, 1); - *node = repls->replacements[i].node; - use_node(*node, org_used_count); - rerun = 1; - break; - } + case EXPR_NAME: + for (i = 0; repls->replacements[i].name; i++) { + if (!strcmp(repls->replacements[i].name, + (char*) (*node)->var1)) { + org_used_count = (*node)->used_count; + free_node(*node, 1, 1); + *node = repls->replacements[i].node; + use_node(*node, org_used_count); + break; } - break; + } + break; - case EXPR_LIST: - case EXPR_TUPLE: - case EXPR_APP: - replace_all(repls, (struct node**) &(*node)->var1); - replace_all(repls, (struct node**) &(*node)->var2); - break; - } + case EXPR_LIST: + case EXPR_TUPLE: + case EXPR_APP: + replace_all(repls, (struct node**) &(*node)->var1); + replace_all(repls, (struct node**) &(*node)->var2); + break; } } + struct node** flatten_app_args(struct node* from) { struct node** result; unsigned int i; @@ -210,6 +209,10 @@ void eval_code_app(fuspel* rules, struct node** node, my_free(args); } +#ifdef _FUSPEL_DEBUG +struct node* root_node; +#endif + void eval(fuspel* rules, struct node** node, replacements** repls, nodes_array** to_free, unsigned to_rnf) { fuspel* _rules; @@ -228,6 +231,13 @@ void eval(fuspel* rules, struct node** node, (*to_free)->length = 10; } +#ifdef _FUSPEL_DEBUG + if (!root_node) { + root_node = *node; + print_node_to_file(root_node, NULL); + } +#endif + do { rerun = 0; @@ -261,13 +271,13 @@ void eval(fuspel* rules, struct node** node, for (j = 0; (*repls)->replacements[j].node; j++) use_node((*repls)->replacements[j].node, 1); - free_node(*_node, 0); + free_node(*_node, 1, 0); cpy_expression_to_node(*_node, &_rules->rule.rhs); replace_all(*repls, _node); use_node(*_node, org_used_count - 1); for (j = 0; (*repls)->replacements[j].node; j++) - free_node((*repls)->replacements[j].node, 1); + free_node((*repls)->replacements[j].node, add_args + 1, 1); (*to_free)->nodes[0] = NULL; (*repls)->replacements[0].name = NULL; @@ -300,6 +310,11 @@ void eval(fuspel* rules, struct node** node, //TODO break; } + +#ifdef _FUSPEL_DEBUG + if (rerun) + print_node_to_file(root_node, NULL); +#endif } while (rerun); } @@ -318,7 +333,8 @@ expression* eval_main(fuspel* rules) { cpy_node_to_expression(expr, main_node); - free_node(main_node, 1); + printf("main is used %d time(s)\n", main_node->used_count); + free_node(main_node, 1, 1); my_free(*repls); my_free(*to_free); diff --git a/interpreter/graphs.c b/interpreter/graphs.c index 34877a2..d802b0f 100644 --- a/interpreter/graphs.c +++ b/interpreter/graphs.c @@ -18,17 +18,17 @@ void use_node(struct node* node, unsigned int count) { } } -void free_node(struct node* node, unsigned free_first) { +void free_node(struct node* node, unsigned int count, unsigned free_first) { if (!node) return; - node->used_count--; + node->used_count -= count; if (node->kind == EXPR_LIST || node->kind == EXPR_TUPLE || node->kind == EXPR_APP) { - free_node((struct node*) node->var1, 1); - free_node((struct node*) node->var2, 1); + free_node((struct node*) node->var1, count, 1); + free_node((struct node*) node->var2, count, 1); } if (node->used_count == 0) { diff --git a/interpreter/graphs.h b/interpreter/graphs.h index 07ca663..f127642 100644 --- a/interpreter/graphs.h +++ b/interpreter/graphs.h @@ -16,7 +16,7 @@ typedef struct { } nodes_array; void use_node(struct node* node, unsigned int count); -void free_node(struct node* node, unsigned free_first); +void free_node(struct node* node, unsigned int count, unsigned free_first); nodes_array* push_node(nodes_array* nodes, struct node* node); diff --git a/interpreter/print.c b/interpreter/print.c index edcedf3..fa784ed 100644 --- a/interpreter/print.c +++ b/interpreter/print.c @@ -122,3 +122,66 @@ void print_node(struct node* node) { free_expression(e); my_free(e); } + +#ifdef _FUSPEL_DEBUG +static unsigned int file_count = 0; + +void print_node_to_file(struct node* node, FILE* f) { + unsigned close = 0; + + if (!node) + return; + + if (!f) { + char fname[20]; + sprintf(fname, "graph-%03u.dot", file_count++); + f = fopen(fname, "w"); + fprintf(f, "digraph {\n"); + fprintf(f, "node [shape=rectangle];\n"); + close = 1; + } + + switch (node->kind) { + case EXPR_INT: + fprintf(f, "%d [label=\"%d (%d)\"];\n", + node, *((int*) node->var1), node->used_count); + break; + + case EXPR_NAME: + fprintf(f, "%d [label=\"%s (%d)\"];\n", + node, (char*) node->var1, node->used_count); + break; + + case EXPR_CODE: + fprintf(f, "%d [label=\"code: %p (%d)\"];\n", + node, node->var1, node->used_count); + break; + + case EXPR_LIST: + case EXPR_TUPLE: + case EXPR_APP: + if (node->kind == EXPR_LIST) + fprintf(f, "%d [label=\"List (%d)\"];\n", + node, node->used_count); + else if (node->kind == EXPR_TUPLE) + fprintf(f, "%d [label=\"Tuple (%d)\"];\n", + node, node->used_count); + else if (node->kind == EXPR_APP) + fprintf(f, "%d [label=\"App (%d)\"];\n", + node, node->used_count); + + if (node->var1) { + print_node_to_file((struct node*) node->var1, f); + print_node_to_file((struct node*) node->var2, f); + fprintf(f, "%d -> %d;\n", node, node->var1); + fprintf(f, "%d -> %d;\n", node, node->var2); + } + break; + } + + if (close) { + fprintf(f, "}"); + fclose(f); + } +} +#endif diff --git a/interpreter/print.h b/interpreter/print.h index 544786f..047a7f7 100644 --- a/interpreter/print.h +++ b/interpreter/print.h @@ -4,6 +4,8 @@ #include "syntax.h" #include "graphs.h" +#include + void print_token(token*); void print_token_list(token_list*); @@ -13,4 +15,8 @@ void print_fuspel(fuspel*); void print_node(struct node*); +#ifdef _FUSPEL_DEBUG +void print_node_to_file(struct node*, FILE*); +#endif + #endif -- cgit v1.2.3