aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2024-07-09 16:14:23 +0200
committerThomas Voss <mail@thomasvoss.com> 2024-07-09 16:14:23 +0200
commit674bce8c96309ae7c38a7e2b946f3f18430a0b00 (patch)
tree9a2b58ad0194493e1998211c08e6c82109309654 /src
parent1a769e8ef02893f737a88fe683add8ffea7affb1 (diff)
Support static-local variables
Diffstat (limited to 'src')
-rw-r--r--src/analyzer.c2
-rw-r--r--src/codegen.c26
-rw-r--r--src/parser.c21
3 files changed, 38 insertions, 11 deletions
diff --git a/src/analyzer.c b/src/analyzer.c
index b67bc91..6154029 100644
--- a/src/analyzer.c
+++ b/src/analyzer.c
@@ -296,6 +296,8 @@ analyzedecl(struct azctx *ctx, idx_t i)
nctx.decl = sv;
ni = analyzeexpr(&nctx, p.rhs);
rtype = ctx->types[p.rhs];
+ if (isstatic && !TESTBIT(ctx->cnst, p.rhs))
+ err("analyzer: Assigning non-constant expression to static");
} else
ni = fwdnode(ctx->ast, i);
diff --git a/src/codegen.c b/src/codegen.c
index 5c81721..2286374 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -369,11 +369,13 @@ codegenalloca(struct cgctx ctx, idx_t i)
i = codegenalloca(ctx, i);
break;
case ASTDECL: {
- strview_t sv = ctx.toks.strs[ctx.ast.lexemes[i]];
- uchar *name = tmpalloc(ctx.s, sv.len + 1, 1);
- LLVMTypeRef t = type2llvm(ctx, ctx.types[i]);
- symtab_insert(&ctx.scps[ctx.scpi].map, sv, NULL)->v =
- LLVMBuildAlloca(ctx.bob, t, svtocstr(name, sv));
+ if (!ctx.aux.buf[ctx.ast.kids[i].lhs].decl.isstatic) {
+ strview_t sv = ctx.toks.strs[ctx.ast.lexemes[i]];
+ uchar *name = tmpalloc(ctx.s, sv.len + 1, 1);
+ LLVMTypeRef t = type2llvm(ctx, ctx.types[i]);
+ symtab_insert(&ctx.scps[ctx.scpi].map, sv, NULL)->v =
+ LLVMBuildAlloca(ctx.bob, t, svtocstr(name, sv));
+ }
} /* fallthrough */
default:
i = fwdnode(ctx.ast, i);
@@ -465,9 +467,19 @@ codegendecl(struct cgctx ctx, idx_t i)
if (ctx.aux.buf[p.lhs].decl.isstatic) {
/* TODO: Namespace the name */
- char *name = tmpalloc(ctx.s, sv.len + 1, 1);
+ char *name;
+ if (ctx.namespace.len != 0) {
+ size_t bufsz = ctx.namespace.len + sv.len + 2;
+ name = tmpalloc(ctx.s, bufsz, 1);
+ snprintf(name, bufsz, "%.*s.%.*s", SV_PRI_ARGS(ctx.namespace),
+ SV_PRI_ARGS(sv));
+ } else {
+ name = tmpalloc(ctx.s, sv.len + 1, 1);
+ svtocstr(name, sv);
+ }
+
LLVMTypeRef t = type2llvm(ctx, ctx.types[i]);
- LLVMValueRef globl = LLVMAddGlobal(ctx.mod, t, svtocstr(name, sv));
+ LLVMValueRef globl = LLVMAddGlobal(ctx.mod, t, name);
symtab_insert(&ctx.scps[ctx.scpi].map, sv, NULL)->v = globl;
LLVMValueRef v;
diff --git a/src/parser.c b/src/parser.c
index e602271..eff98df 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -158,9 +158,15 @@ parsedecl(ast_t *ast, aux_t *aux, lexemes_t toks, bool toplvl)
aux->buf = bufalloc(aux->buf, aux->cap, sizeof(*aux->buf));
}
- /* TODO: Support ‘static’ as a keyword */
- aux->buf[j].decl.isstatic = toplvl;
- aux->buf[j].decl.isundef = false;
+ bool static_kw = toks.kinds[toksidx] == LEXIDENT
+ && strview_eq(SV("static"), toks.strs[toksidx]);
+ if (static_kw) {
+ toksidx++;
+ if (toplvl)
+ err("parser: The ‘static’ doesn’t apply to global variables");
+ }
+
+ aux->buf[j].decl.isundef = false;
if (toplvl && toks.kinds[toksidx] == LEXIDENT
&& strview_eq(SV("pub"), toks.strs[toksidx]))
{
@@ -187,12 +193,17 @@ parsedecl(ast_t *ast, aux_t *aux, lexemes_t toks, bool toplvl)
err("parser: No type provided in non-assigning declaration");
ast->kinds[i] = ASTDECL;
ast->kids[i].rhs = AST_EMPTY;
+ aux->buf[j].decl.isstatic = toplvl || static_kw;
return i;
case LEXCOLON:
ast->kinds[i] = ASTCDECL;
+ aux->buf[j].decl.isstatic = false;
+ if (static_kw)
+ err("parser: Cannot declare a constant symbol ‘static’");
break;
case LEXEQ:
ast->kinds[i] = ASTDECL;
+ aux->buf[j].decl.isstatic = toplvl || static_kw;
break;
default:
err("parser: Expected colon, equals, or semicolon");
@@ -388,7 +399,9 @@ parsestmt(ast_t *ast, aux_t *aux, lexemes_t toks)
ast->kids[i].rhs = rhs;
if (toks.kinds[toksidx++] != LEXSEMI)
err("parser: Expected semicolon");
- } else if (toks.kinds[toksidx + 1] == LEXCOLON) {
+ } else if (strview_eq(SV("static"), sv)
+ || toks.kinds[toksidx + 1] == LEXCOLON)
+ {
i = parsedecl(ast, aux, toks, false);
} else /* assignment or funcall */ {
idx_t lhs, rhs;