/* * Symbol table stack * (C) 2006, Pascal Schmidt * see file ../doc/LICENSE for license */ #include #include "runtime.h" /* * Tear down symbol table stack * * Deallocates all memory used by the symbol table stack. */ void symtab_stack_teardown(arena_state *s) { sanity(s->global_table); while (s->local_depth > 0) { symtab_stack_leave(s); } free(s->local_tables); s->local_tables = NULL; symtab_free(s->global_table); s->global_table = NULL; } /* * Initialize symbol table stack * * This function allocates memory for the global symbol table * and resets the local symbol table stack to depth 0. */ void symtab_stack_init(arena_state *s) { if (!s->global_table) { s->global_table = oom(symtab_alloc(0)); s->local_depth = 0; s->local_tables = NULL; } } /* * Enter local symbol table * * This function adds a new local symbol table to the stack. The * new symbol table obscures the previous toplevel local table. */ void symtab_stack_enter(arena_state *s) { symtab **local; symtab *newtab; newtab = symtab_alloc(7); local = oom(realloc(s->local_tables, (s->local_depth + 1) * sizeof(symtab *))); s->local_tables = local; local[s->local_depth] = newtab; ++s->local_depth; } /* * Leave local symbol table * * This function removes and frees the topmost local symbol table. * The previous local symbol table becomes visible again. */ void symtab_stack_leave(arena_state *s) { symtab **local = s->local_tables; if (s->local_depth == 0) { return; } --s->local_depth; symtab_free(local[s->local_depth]); } /* * Pop symbol table stack * * This function returns the topmost local symbol table and makes * the previous local symbol table visible again. */ symtab *symtab_stack_pop(arena_state *s) { symtab **local = s->local_tables; sanity(s->local_depth > 0); --s->local_depth; return local[s->local_depth]; } /* * Get stack depth * * This function returns the current depth of the local symbol * table stack. It returns 0 if there are no local symbol tables * at the moment. */ unsigned int symtab_stack_depth(arena_state *s) { return s->local_depth; } /* * Add symbol table entry to stack * * This functions adds the given entry to the topmost symbol * table of the stack. This means the global table if no * local symbol table exists. */ void symtab_stack_add(arena_state *s, symtab_entry *entry) { symtab **local = s->local_tables; sanity(entry); if (s->local_depth > 0) { symtab_add(local[s->local_depth-1], entry); } else { symtab_add(s->global_table, entry); } } /* * Put symbol table entry into global table * * This function adds the given entry to the global symbol * table, no matter whether a current local table exists. */ void symtab_stack_add_global(arena_state *s, const char *name, value *val) { sanity(name && val); symtab_add_variable(s->global_table, name, val); } /* * Add variable entry to stack * * This functions adds the given variable to the topmost symbol * table of the stack. This means the global table if no local * symbol table exists. */ void symtab_stack_add_variable(arena_state *s, const char *name, value *val) { symtab **local = s->local_tables; sanity(name && val); if (s->local_depth > 0) { symtab_add_variable(local[s->local_depth-1], name, val); } else { symtab_add_variable(s->global_table, name, val); } } /* * Add function entry to stack * * This function adds the given function to the topmost symbol * table of the stack. This means the global table if no local * symbol table exists. */ void symtab_stack_add_function(arena_state *s, const char *name, const signature *sig) { symtab **local = s->local_tables; sanity(name && sig); if (s->local_depth > 0) { symtab_add_function(local[s->local_depth-1], name, sig); } else { symtab_add_function(s->global_table, name, sig); } } /* * Add template entry to stack * * This function adds the given template to the topmost symbol table * of the stack. This means the global table if no local symbol * table exists. */ void symtab_stack_add_template(arena_state *s, const char *name, const char *parent, void *def) { symtab **local = s->local_tables; sanity(name && def); if (s->local_depth > 0) { symtab_add_template(local[s->local_depth-1], name, parent, def); } else { symtab_add_template(s->global_table, name, parent, def); } } /* * Lookup symbol in stack * * This function looks for the given symbol name in the topmost * local symbol table. If the symbol is not found there, it is * also searched for in the global table. */ symtab_entry *symtab_stack_lookup(arena_state *s, const char *symbol) { symtab **local = s->local_tables; symtab_entry *entry = NULL; if (s->local_depth > 0) { entry = symtab_lookup(local[s->local_depth-1], symbol); } if (!entry) { entry = symtab_lookup(s->global_table, symbol); } return entry; } /* * Check locality * * This function returns 1 if the given symbol name would be * resolved from a local symbol table. If the global table is * active at the moment, the answer is always "yes". */ int symtab_stack_local(arena_state *s, const char *symbol) { symtab **local = s->local_tables; symtab_entry *entry; if (s->local_depth > 0) { entry = symtab_lookup(local[s->local_depth-1], symbol); return (entry != NULL); } return 1; } /* * Delete symbol from stack * * This function deletes the given symbol name from the topmost * symbol table in the stack. This means the global table if no * local symbol table exists. */ void symtab_stack_delete(arena_state *s, const char *symbol) { symtab **local = s->local_tables; if (s->local_depth > 0) { symtab_delete(local[s->local_depth-1], symbol); } else { symtab_delete(s->global_table, symbol); } }