aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/analyzer.c68
-rw-r--r--src/analyzer.h3
-rw-r--r--src/symtab.c27
-rw-r--r--src/symtab.h26
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 */