diff options
author | Thomas Voss <mail@thomasvoss.com> | 2024-07-08 21:13:59 +0200 |
---|---|---|
committer | Thomas Voss <mail@thomasvoss.com> | 2024-07-08 21:13:59 +0200 |
commit | bf55e73560fae478c7440fab858c48884938b9fa (patch) | |
tree | 1a15cd2ab876ab8c7f2b6bd111133e2c732a8e51 /src | |
parent | 37ba226ae87ad85db064e025278d457b86f015e8 (diff) |
Actually make unary plus an AST node
Diffstat (limited to 'src')
-rw-r--r-- | src/analyzer.c | 20 | ||||
-rw-r--r-- | src/codegen.c | 2 | ||||
-rw-r--r-- | src/parser.c | 16 | ||||
-rw-r--r-- | src/parser.h | 4 |
4 files changed, 26 insertions, 16 deletions
diff --git a/src/analyzer.c b/src/analyzer.c index b1c18e2..1bbb43c 100644 --- a/src/analyzer.c +++ b/src/analyzer.c @@ -21,15 +21,12 @@ #include "types.h" #define LOG2_10 (3.321928) -#define MP_BITCNT_MAX ((mp_bitcnt_t)-1) - -/* In debug builds we want to actually alloc a new mpq_t so that it’s - easier to free memory without doing a double free */ -#if DEBUG -# define MPQCPY(x, y) do { mpq_init(x); mpq_set(x, y); } while (false) -#else -# define MPQCPY(x, y) (*(x) = *(y)) -#endif +#define MP_BITCNT_MAX ((mp_bitcnt_t) - 1) +#define MPQCPY(x, y) \ + do { \ + mpq_init(x); \ + mpq_set(x, y); \ + } while (false) typedef struct { scope_t *buf; @@ -409,6 +406,7 @@ analyzeexpr(struct azctx *ctx, idx_t i) err("analyzer: Unknown symbol ‘%.*s’", SV_PRI_ARGS(sv)); } + case ASTUNPLUS: case ASTUNCMPL: case ASTUNNEG: { idx_t ni, rhs; @@ -708,12 +706,14 @@ out: err("analyzer: Cannot perform bitwise complement of constant"); break; } + case ASTUNPLUS: case ASTUNNEG: { idx_t rhs = ctx->ast.kids[i].rhs; ni = constfoldexpr(ctx, ctx->types[i], rhs); if (TESTBIT(ctx->cnst, rhs)) { MPQCPY(ctx->folds[i].q, ctx->folds[rhs].q); - mpq_neg(ctx->folds[i].q, ctx->folds[i].q); + if (ctx->ast.kinds[i] == ASTUNNEG) + mpq_neg(ctx->folds[i].q, ctx->folds[i].q); } break; } diff --git a/src/codegen.c b/src/codegen.c index 27f5277..35e19f9 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -211,6 +211,8 @@ codegentypedexpr(struct cgctx ctx, idx_t i, type_t *T, LLVMValueRef *outv) *outv = LLVMBuildLoad2(ctx.bob, t, ptrval, "load"); return fwdnode(ctx.ast, i); } + case ASTUNPLUS: + return codegentypedexpr(ctx, ctx.ast.kids[i].rhs, T, outv); case ASTUNCMPL: { LLVMValueRef v, minus_one; minus_one = LLVMConstInt(type2llvm(ctx, ctx.types[i]), -1, false); diff --git a/src/parser.c b/src/parser.c index 0a5f632..e602271 100644 --- a/src/parser.c +++ b/src/parser.c @@ -83,6 +83,7 @@ fwdnode(ast_t ast, idx_t i) case ASTFN: case ASTUNCMPL: case ASTUNNEG: + case ASTUNPLUS: i = ast.kids[i].rhs; break; case ASTCALLSTMT: @@ -259,12 +260,6 @@ parseexpratom(ast_t *ast, lexemes_t toks) idx_t i = astalloc(ast); - /* Unary plus is kind of a fake syntactic construct. We just pretend - like it doesn’t exist, but allow it in the syntax to be consistent - with unary negation. */ - while (toks.kinds[toksidx] == LEXPLUS) - toksidx++; - ast->lexemes[i] = toksidx; switch (toks.kinds[toksidx++]) { @@ -274,6 +269,15 @@ parseexpratom(ast_t *ast, lexemes_t toks) case LEXIDENT: ast->kinds[i] = ASTIDENT; break; + case LEXPLUS: + /* Unary plus is kind of a fake syntactic construct. We would + ideally just pretend like it doesn’t exist, but allow it in + the syntax to be consistent with unary negation. We can’t + just ignoring it in parsing though, because we need to + disallow the statements ‘x := 0; +x = 1;’ */ + ast->kinds[i] = ASTUNPLUS; + ast->kids[i].rhs = parseexpratom(ast, toks); + break; case LEXMINUS: ast->kinds[i] = ASTUNNEG; ast->kids[i].rhs = parseexpratom(ast, toks); diff --git a/src/parser.h b/src/parser.h index 5d5c53b..14ab4b8 100644 --- a/src/parser.h +++ b/src/parser.h @@ -53,6 +53,10 @@ enum { ‘lhs = rhs’ */ ASTASIGN, + /* Unary plus + ‘+rhs’ */ + ASTUNPLUS, + /* Unary negation ‘-rhs’ */ ASTUNNEG, |