From bf55e73560fae478c7440fab858c48884938b9fa Mon Sep 17 00:00:00 2001 From: Thomas Voss Date: Mon, 8 Jul 2024 21:13:59 +0200 Subject: Actually make unary plus an AST node --- src/analyzer.c | 20 ++++++++++---------- src/codegen.c | 2 ++ src/parser.c | 16 ++++++++++------ src/parser.h | 4 ++++ 4 files changed, 26 insertions(+), 16 deletions(-) (limited to 'src') 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, -- cgit v1.2.3