aboutsummaryrefslogtreecommitdiff
path: root/src/analyzer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/analyzer.c')
-rw-r--r--src/analyzer.c68
1 files changed, 21 insertions, 47 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;
-}