diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/analyzer.c | 68 | ||||
-rw-r--r-- | src/analyzer.h | 3 | ||||
-rw-r--r-- | src/symtab.c | 27 | ||||
-rw-r--r-- | src/symtab.h | 26 |
4 files changed, 75 insertions, 49 deletions
diff --git a/src/analyzer.c b/src/analyzer.c index c1f7e05..fa26df3 100644 --- a/src/analyzer.c +++ b/src/analyzer.c @@ -14,6 +14,7 @@ #include "errors.h" #include "parser.h" #include "strview.h" +#include "symtab.h" #include "types.h" /* In debug builds we want to actually alloc a new mpq_t so that it’s @@ -24,13 +25,6 @@ # define MPQCPY(x, y) (*(x) = *(y)) #endif -/* Mapping of symbol names to their indicies in the AST */ -typedef struct symtab { - struct symtab *child[4]; - strview_t key; - idx_t val; -} symtab_t; - typedef struct { scope_t *buf; size_t len, cap; @@ -95,12 +89,6 @@ static const type_t *typegrab(ast_t, lexemes_t, idx_t) static bool typecompat(type_t, type_t); static bool returns(ast_t, idx_t); -/* Index the symbol table M with the key SV, returning a pointer to the - value. If no entry exists and A is non-null, a pointer to a newly - allocated (and zeroed) value is returned, NULL otherwise. */ -static idx_t *symtab_insert(symtab_t **m, strview_t sv, arena_t *a) - __attribute__((nonnull(1))); - /* Defined in primitives.gperf */ const type_t *typelookup(const uchar *, size_t) __attribute__((nonnull)); @@ -152,12 +140,13 @@ find_unordered_syms(scopes_t *scps, ast_t ast, aux_t aux, lexemes_t toks, if (isstatic || isconst) { strview_t sv = toks.strs[ast.lexemes[i]]; - idx_t *p = symtab_insert(&scp->map, sv, a); - if (*p != AST_EMPTY) { + symval_t *p = symtab_insert(&scp->map, sv, a); + if (p->exists) { err("analyzer: Symbol ‘%.*s’ declared multiple times", SV_PRI_ARGS(sv)); } - *p = i; + p->i = i; + p->exists = true; } else if (ast.kinds[i] == ASTBLK) { pair_t p = ast.kids[i]; find_unordered_syms(scps, ast, aux, toks, beg, p.lhs, p.rhs, a); @@ -193,12 +182,13 @@ analyzedecl(struct azctx ctx, scope_t *scps, type_t *types, ast_t ast, { strview_t sv = toks.strs[ast.lexemes[i]]; if (ctx.si > 0 && ast.kinds[i] == ASTDECL) { - idx_t *ip = symtab_insert(&scps[ctx.si].map, sv, ctx.a); - if (*ip == AST_EMPTY) - *ip = i; - else { + symval_t *sym = symtab_insert(&scps[ctx.si].map, sv, ctx.a); + if (sym->exists) { err("analyzer: Variable ‘%.*s’ declared multiple times", SV_PRI_ARGS(sv)); + } else { + sym->i = i; + sym->exists = true; } } @@ -281,24 +271,24 @@ analyzeexpr(struct azctx ctx, scope_t *scps, type_t *types, ast_t ast, for (idx_t lvl = ctx.si;;) { scope_t scp = scps[lvl]; - idx_t *ip = symtab_insert(&scp.map, sv, NULL); + symval_t *sym = symtab_insert(&scp.map, sv, NULL); - if (ip == NULL) { + if (sym == NULL) { if (lvl == 0) break; lvl = scp.up; } else { - switch (types[*ip].kind) { + switch (types[sym->i].kind) { case TYPE_UNSET: ctx.si = lvl; - analyzedecl(ctx, scps, types, ast, aux, toks, *ip); + analyzedecl(ctx, scps, types, ast, aux, toks, sym->i); break; case TYPE_CHECKING: err("analyzer: Circular definition of ‘%.*s’", SV_PRI_ARGS(sv)); } - types[i] = types[*ip]; + types[i] = types[sym->i]; return i + 1; } } @@ -420,23 +410,23 @@ constfoldexpr(struct cfctx ctx, mpq_t *folds, scope_t *scps, type_t *types, for (idx_t lvl = ctx.si;;) { scope_t scp = scps[lvl]; - idx_t *ip = symtab_insert(&scp.map, sv, NULL); + symval_t *sym = symtab_insert(&scp.map, sv, NULL); - if (ip == NULL) { + if (sym == NULL) { assert(lvl != 0); lvl = scp.up; } else { - switch (ast.kinds[*ip]) { + switch (ast.kinds[sym->i]) { case ASTDECL: break; case ASTCDECL: { - idx_t expr = ast.kids[*ip].rhs; + idx_t expr = ast.kids[sym->i].rhs; assert(expr != AST_EMPTY); MPQCPY(folds[i], folds[expr]); if (MPQ_IS_INIT(folds[i])) { ctx.si = lvl; - (void)constfolddecl(ctx, folds, scps, types, ast, toks, - *ip); + (void)constfolddecl(ctx, folds, scps, types, + ast, toks, sym->i); MPQCPY(folds[i], folds[expr]); assert(MPQ_IS_INIT(folds[i])); } @@ -513,19 +503,3 @@ typecompat(type_t lhs, type_t rhs) return lhs.issigned == rhs.issigned && lhs.isfloat == rhs.isfloat && lhs.size == rhs.size; } - -idx_t * -symtab_insert(symtab_t **m, strview_t k, arena_t *a) -{ - for (uint64_t h = strview_hash(k); *m; h <<= 2) { - if (strview_eq(k, (*m)->key)) - return &(*m)->val; - m = &(*m)->child[h >> 62]; - } - if (a == NULL) - return NULL; - *m = arena_new(a, symtab_t, 1); - (*m)->key = k; - (*m)->val = AST_EMPTY; - return &(*m)->val; -} diff --git a/src/analyzer.h b/src/analyzer.h index 2173694..abb4395 100644 --- a/src/analyzer.h +++ b/src/analyzer.h @@ -8,6 +8,7 @@ #include "alloc.h" #include "lexer.h" #include "parser.h" +#include "symtab.h" #include "types.h" /* The different base types */ @@ -31,8 +32,6 @@ enum { static_assert(_TYPE_LAST_ENT - 1 <= UINT8_MAX, "Too many AST tokens to fix in uint8_t"); -typedef struct symtab symtab_t; - typedef struct { idx_t up, i; symtab_t *map; diff --git a/src/symtab.c b/src/symtab.c new file mode 100644 index 0000000..279fdb9 --- /dev/null +++ b/src/symtab.c @@ -0,0 +1,27 @@ +#include <stddef.h> +#include <stdint.h> + +#include "alloc.h" +#include "symtab.h" +#include "strview.h" + +struct symtab { + symtab_t *child[4]; + strview_t key; + symval_t val; +}; + +symval_t * +symtab_insert(symtab_t **m, strview_t sv, arena_t *a) +{ + for (uint64_t h = strview_hash(sv); *m; h <<= 2) { + if (strview_eq(sv, (*m)->key)) + return &(*m)->val; + m = &(*m)->child[h >> 62]; + } + if (a == NULL) + return NULL; + *m = arena_new(a, symtab_t, 1); + (*m)->key = sv; + return &(*m)->val; +} diff --git a/src/symtab.h b/src/symtab.h new file mode 100644 index 0000000..29c4868 --- /dev/null +++ b/src/symtab.h @@ -0,0 +1,26 @@ +#ifndef ORYX_SYMTAB_H +#define ORYX_SYMTAB_H + +#include <stdbool.h> + +#include <llvm-c/Types.h> + +#include "alloc.h" +#include "strview.h" +#include "types.h" + +typedef struct symtab symtab_t; + +typedef struct { + bool exists; + idx_t i; + LLVMValueRef v; +} symval_t; + +/* Index the symbol table M with the key SV, returning a pointer to the + value. If no entry exists and A is non-null, a pointer to a newly + allocated (and zeroed) value is returned, NULL otherwise. */ +symval_t *symtab_insert(symtab_t **m, strview_t sv, arena_t *a) + __attribute__((nonnull(1))); + +#endif /* !ORYX_SYMTAB_H */ |