summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dimension/grammar.y2
-rw-r--r--dimension/main.c2
-rw-r--r--dimension/parse.c71
-rw-r--r--dimension/parse.h8
-rw-r--r--dimension/realize.c3
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");