aboutsummaryrefslogtreecommitdiff
path: root/symtab.c
diff options
context:
space:
mode:
Diffstat (limited to 'symtab.c')
-rw-r--r--symtab.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/symtab.c b/symtab.c
new file mode 100644
index 0000000..4229a63
--- /dev/null
+++ b/symtab.c
@@ -0,0 +1,60 @@
+#include <stdlib.h>
+#include <string.h>
+#include "symtab.h"
+
+
+struct symtab* symtab_make() {
+ struct symtab *symtab = malloc(sizeof(struct symtab));
+ symtab->parent = NULL;
+ symtab->cap = 16;
+ symtab->len = 0;
+ symtab->syms = malloc(symtab->cap * sizeof(struct symbol*));
+ return symtab;
+}
+
+void symtab_delete_recursive(struct symtab *symtab) {
+ free(symtab->syms);
+ struct symtab *parent = symtab->parent;
+ free(symtab);
+ if (parent) symtab_delete_recursive(parent);
+}
+
+struct symbol* symtab_find(const struct symtab *symtab, const char *name) {
+ struct symbol *sym = symtab_find_local(symtab, name);
+ if (sym) return sym;
+ else if (symtab->parent) return symtab_find(symtab->parent, name);
+ else return NULL;
+}
+
+struct symbol* symtab_find_local(const struct symtab *symtab, const char *name) {
+ for (int i = 0; i < symtab->len; i++) {
+ if (strcmp(symtab->syms[i]->name, name) == 0) return symtab->syms[i];
+ }
+ return NULL;
+}
+
+void symtab_insert(struct symtab *symtab, struct symbol *sym) {
+ if (symtab->len == symtab->cap) {
+ symtab->cap *= 2;
+ symtab->syms = realloc(symtab->syms, symtab->cap * sizeof(struct symbol*));
+ }
+ symtab->syms[symtab->len++] = sym;
+}
+
+struct symtab* symtab_root(struct symtab *symtab) {
+ if (symtab->parent) return symtab_root(symtab->parent);
+ else return symtab;
+}
+
+struct symtab* symtab_sub(struct symtab *symtab) {
+ struct symtab *sub = symtab_make();
+ sub->parent = symtab;
+ return sub;
+}
+
+struct symtab* symtab_delete_get_parent(struct symtab *symtab) {
+ struct symtab *parent = symtab->parent;
+ symtab->parent = NULL;
+ symtab_delete_recursive(symtab);
+ return parent;
+}