/* * sym.c — symbol table. Plan 9-flavoured: a per-scope hashtable * chained to the parent scope. Lookup walks up. Duplicate definitions * within the same scope are flagged by the caller (we just refuse the * insert and return the first one). */ #include "ww.h" #include #define INIT_BUCKETS 16 static u64 hashstr(const char *s) { /* FNV-1a 64-bit; small fixed footprint, decent distribution */ u64 h = 0xcbf29ce484222325ULL; for (; *s; s++) { h ^= (unsigned char)*s; h *= 0x100000001b3ULL; } return h; } Scope * newscope(Arena *a, Scope *parent) { Scope *s = amalloc(a, sizeof *s); s->parent = parent; s->a = a; s->nbuckets = INIT_BUCKETS; s->buckets = amalloc(a, s->nbuckets * sizeof(Sym *)); return s; } Sym * scope_lookup_local(Scope *s, const char *name) { if (s == NULL) return NULL; u64 h = hashstr(name) % s->nbuckets; for (Sym *b = s->buckets[h]; b; b = b->hashnext) if (strcmp(b->name, name) == 0) return b; return NULL; } Sym * scope_lookup(Scope *s, const char *name) { for (; s; s = s->parent) { Sym *r = scope_lookup_local(s, name); if (r) return r; } return NULL; } Sym * scope_define(Scope *s, const char *name, Skind k, Type *t, Node *decl) { if (scope_lookup_local(s, name) != NULL) return NULL; Sym *sy = amalloc(s->a, sizeof *sy); sy->name = name; sy->kind = k; sy->type = t; sy->decl = decl; sy->scope = s; u64 h = hashstr(name) % s->nbuckets; sy->hashnext = s->buckets[h]; s->buckets[h] = sy; if (s->first == NULL) s->first = sy; else s->last->next = sy; s->last = sy; return sy; }