aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2024-07-08 21:13:59 +0200
committerThomas Voss <mail@thomasvoss.com> 2024-07-08 21:13:59 +0200
commitbf55e73560fae478c7440fab858c48884938b9fa (patch)
tree1a15cd2ab876ab8c7f2b6bd111133e2c732a8e51
parent37ba226ae87ad85db064e025278d457b86f015e8 (diff)
Actually make unary plus an AST node
-rw-r--r--src/analyzer.c20
-rw-r--r--src/codegen.c2
-rw-r--r--src/parser.c16
-rw-r--r--src/parser.h4
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,