diff options
-rw-r--r-- | dimension/grammar.y | 2 | ||||
-rw-r--r-- | dimension/main.c | 2 | ||||
-rw-r--r-- | dimension/parse.c | 71 | ||||
-rw-r--r-- | dimension/parse.h | 8 | ||||
-rw-r--r-- | dimension/realize.c | 3 |
5 files changed, 75 insertions, 11 deletions
diff --git a/dimension/grammar.y b/dimension/grammar.y index 7955476..e52d668 100644 --- a/dimension/grammar.y +++ b/dimension/grammar.y @@ -1134,7 +1134,7 @@ dmnsn_parse(FILE *file, dmnsn_symbol_table *symtable) filename = fnode->ptr; } else { filename = "<>"; - dmnsn_push_symbol(symtable, "__file__", dmnsn_new_ast_string(filename)); + dmnsn_declare_symbol(symtable, "__file__", dmnsn_new_ast_string(filename)); } void *scanner; diff --git a/dimension/main.c b/dimension/main.c index 561ee99..9083a07 100644 --- a/dimension/main.c +++ b/dimension/main.c @@ -157,7 +157,7 @@ main(int argc, char **argv) { /* Construct the symbol table */ dmnsn_symbol_table *symtable = dmnsn_new_symbol_table(); - dmnsn_push_symbol(symtable, "__file__", dmnsn_new_ast_string(input)); + dmnsn_declare_symbol(symtable, "__file__", dmnsn_new_ast_string(input)); /* Debugging option - output the abstract syntax tree as an S-expression */ if (parse) { diff --git a/dimension/parse.c b/dimension/parse.c index 0bc080f..1916941 100644 --- a/dimension/parse.c +++ b/dimension/parse.c @@ -117,14 +117,19 @@ dmnsn_new_symbol_table() } static void +dmnsn_delete_symbol(dmnsn_symbol symbol) +{ + free(symbol.id); + dmnsn_delete_astnode(symbol.value); +} + +static void dmnsn_delete_scope(dmnsn_array *scope) { while (dmnsn_array_size(scope) > 0) { dmnsn_symbol symbol; dmnsn_array_pop(scope, &symbol); - - free(symbol.id); - dmnsn_delete_astnode(symbol.value); + dmnsn_delete_symbol(symbol); } dmnsn_delete_array(scope); } @@ -154,18 +159,72 @@ void dmnsn_pop_scope(dmnsn_symbol_table *symtable) dmnsn_delete_scope(scope); } -void dmnsn_push_symbol(dmnsn_symbol_table *symtable, - const char *id, dmnsn_astnode value) +void dmnsn_local_symbol(dmnsn_symbol_table *symtable, + const char *id, dmnsn_astnode value) { ++*value.refcount; dmnsn_array *scope; dmnsn_array_get(symtable, dmnsn_array_size(symtable) - 1, &scope); + unsigned int i; + for (i = 0; i < dmnsn_array_size(scope); ++i) { + dmnsn_symbol *symbol = dmnsn_array_at(scope, + dmnsn_array_size(scope) - i - 1); + + if (strcmp(id, symbol->id) == 0) { + dmnsn_delete_astnode(symbol->value); + symbol->value = value; + return; + } + } + dmnsn_symbol symbol = { .id = strdup(id), .value = value }; dmnsn_array_push(scope, &symbol); } +void +dmnsn_declare_symbol(dmnsn_symbol_table *symtable, + const char *id, dmnsn_astnode value) +{ + ++*value.refcount; + + dmnsn_astnode *node = dmnsn_find_symbol(symtable, id); + if (node) { + /* Always update the most local symbol */ + dmnsn_delete_astnode(*node); + *node = value; + } else { + /* but create new ones at the least local scope */ + dmnsn_array *scope; + dmnsn_array_get(symtable, 0, &scope); + + dmnsn_symbol symbol = { .id = strdup(id), .value = value }; + dmnsn_array_push(scope, &symbol); + } +} + +void +dmnsn_undef_symbol(dmnsn_symbol_table *symtable, const char *id) +{ + unsigned int i; + for (i = 0; i < dmnsn_array_size(symtable); ++i) { + dmnsn_array *scope; + dmnsn_array_get(symtable, dmnsn_array_size(symtable) - i - 1, &scope); + + unsigned int j; + for (j = 0; j < dmnsn_array_size(scope); ++j) { + dmnsn_symbol *symbol = dmnsn_array_at(scope, + dmnsn_array_size(scope) - j - 1); + + if (strcmp(id, symbol->id) == 0) { + dmnsn_array_remove(scope, j); + return; + } + } + } +} + dmnsn_astnode * dmnsn_find_symbol(dmnsn_symbol_table *symtable, const char *id) { @@ -175,7 +234,7 @@ dmnsn_find_symbol(dmnsn_symbol_table *symtable, const char *id) dmnsn_array_get(symtable, dmnsn_array_size(symtable) - i - 1, &scope); unsigned int j; - for (j = 0; j < dmnsn_array_size(symtable); ++j) { + for (j = 0; j < dmnsn_array_size(scope); ++j) { dmnsn_symbol *symbol = dmnsn_array_at(scope, dmnsn_array_size(scope) - j - 1); diff --git a/dimension/parse.h b/dimension/parse.h index 6f8755d..6f5b981 100644 --- a/dimension/parse.h +++ b/dimension/parse.h @@ -115,8 +115,12 @@ void dmnsn_delete_symbol_table(dmnsn_symbol_table *symtable); void dmnsn_push_scope(dmnsn_symbol_table *symtable); void dmnsn_pop_scope(dmnsn_symbol_table *symtable); -void dmnsn_push_symbol(dmnsn_symbol_table *symtable, - const char *id, dmnsn_astnode value); +void dmnsn_local_symbol(dmnsn_symbol_table *symtable, + const char *id, dmnsn_astnode value); +void dmnsn_declare_symbol(dmnsn_symbol_table *symtable, + const char *id, dmnsn_astnode value); +void dmnsn_undef_symbol(dmnsn_symbol_table *symtable, const char *id); + dmnsn_astnode *dmnsn_find_symbol(dmnsn_symbol_table *symtable, const char *id); /* Evaluate an arithmetic expression */ diff --git a/dimension/realize.c b/dimension/realize.c index eda7056..5a13d8b 100644 --- a/dimension/realize.c +++ b/dimension/realize.c @@ -636,7 +636,8 @@ dmnsn_realize_string(const char *str, dmnsn_symbol_table *symtable) symtable = dmnsn_new_symbol_table(); } if (!dmnsn_find_symbol(symtable, "__file__")) { - dmnsn_push_symbol(symtable, "__file__", dmnsn_new_ast_string("<string>")); + dmnsn_declare_symbol(symtable, "__file__", + dmnsn_new_ast_string("<string>")); } FILE *file = fmemopen((void *)str, strlen(str), "r"); |