nooc

nooc programming language compiler
git clone git://git.nihaljere.xyz/nooc
Log | Files | Refs | LICENSE

commit 853042c6acd2835ac7b16bc527fe33372ecab78f
parent a1d655b3ecc7d71e3a27ac1a9be28ea053ed6a57
Author: Nihal Jere <nihal@nihaljere.xyz>
Date:   Fri, 24 Dec 2021 22:36:52 -0600

fix global declarations

This adds basic compile-time evaluation of constants back, in a less
hacky way than it was present before.

Diffstat:
Mmain.c | 49+++++++++++++++++++++++++++++++++++++++++--------
Mnooc.h | 3++-
Mparse.c | 2+-
Atest/global.pass.nooc | 9+++++++++
4 files changed, 53 insertions(+), 10 deletions(-)

diff --git a/main.c b/main.c @@ -71,6 +71,13 @@ data_pushzero(size_t len) } void +decl_set(struct decl *decl, void *ptr) +{ + struct type *type = &types.data[decl->type]; + memcpy(&data_seg.data[decl->loc.addr - DATA_OFFSET], ptr, type->size); +} + +void decl_alloc(struct block *block, struct decl *decl) { struct type *type = &types.data[decl->type]; @@ -233,7 +240,7 @@ dumpval(struct expr *e) { switch (e->class) { case C_INT: - fprintf(stderr, "%ld", e->d.v.v.i); + fprintf(stderr, "%ld", e->d.v.v.i64); break; case C_STR: fprintf(stderr, "\"%.*s\"", (int)e->d.v.v.s.len, e->d.v.v.s.data); @@ -435,7 +442,7 @@ genexpr(char *buf, size_t idx, struct out *out) enum reg reg = getreg(); switch (expr->class) { case C_INT: - total += mov_r64_imm(buf ? buf + total : buf, reg, expr->d.v.v.i); + total += mov_r64_imm(buf ? buf + total : buf, reg, expr->d.v.v.i64); break; case C_STR: { int addr = data_push(expr->d.v.v.s.data, expr->d.v.v.s.len); @@ -525,6 +532,28 @@ genexpr(char *buf, size_t idx, struct out *out) return total; } +void +evalexpr(struct decl *decl) +{ + struct expr *expr = &exprs.data[decl->val]; + if (expr->kind == EXPR_LIT) { + switch (expr->class) { + case C_INT: + decl_set(decl, &expr->d.v.v); + break; + case C_STR: { + uint64_t addr = data_push(expr->d.v.v.s.data, expr->d.v.v.s.len); + decl_set(decl, &addr); + break; + } + default: + error(expr->start->line, expr->start->col, "genexpr: unknown value type!"); + } + } else { + error(expr->start->line, expr->start->col, "cannot evaluate expression at compile time"); + } +} + // FIXME: It is not ideal to calculate length by doing all the calculations to generate instruction, before we actually write the instructions. size_t genblock(char *buf, struct block *block, bool toplevel) @@ -544,12 +573,16 @@ genblock(char *buf, struct block *block, bool toplevel) decl->kind = toplevel ? DECL_DATA : DECL_STACK; decl_alloc(block, decl); - if (expr->class == C_PROC) { - block->decls.data[item->idx].loc.addr = total + TEXT_OFFSET; - // FIXME: won't work for nested functions - curproc = &expr->d.proc; - total += genproc(buf ? buf + total : NULL, &(expr->d.proc)); - curproc = NULL; + if (toplevel) { + if (expr->class == C_PROC) { + block->decls.data[item->idx].loc.addr = total + TEXT_OFFSET; + // FIXME: won't work for nested functions + curproc = &expr->d.proc; + total += genproc(buf ? buf + total : NULL, &(expr->d.proc)); + curproc = NULL; + } else { + evalexpr(decl); + } } else { struct out tempout = {OUT_REG, getreg()}; total += genexpr(buf ? buf + total : NULL, block->decls.data[item->idx].val, &tempout); diff --git a/nooc.h b/nooc.h @@ -180,7 +180,8 @@ enum binop { struct value { union { - uint64_t i; + int64_t i64; + int32_t i32; struct slice s; } v; }; diff --git a/parse.c b/parse.c @@ -228,7 +228,7 @@ parseexpr(struct block *block) expr.kind = EXPR_LIT; expr.class = C_INT; // FIXME: error check - expr.d.v.v.i = strtol(tok->slice.data, NULL, 10); + expr.d.v.v.i64 = strtol(tok->slice.data, NULL, 10); tok = tok->next; break; case TOK_GREATER: diff --git a/test/global.pass.nooc b/test/global.pass.nooc @@ -0,0 +1,9 @@ +let a i32 = 10 + +let main proc() = proc() { + if > a 5 { + syscall(60, 0) + } else { + syscall(60, 1) + } +}