aboutsummaryrefslogtreecommitdiff
path: root/src/analyzer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/analyzer.c')
-rw-r--r--src/analyzer.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/src/analyzer.c b/src/analyzer.c
index 4a5a2c6..bf77745 100644
--- a/src/analyzer.c
+++ b/src/analyzer.c
@@ -309,13 +309,16 @@ analyzeexpr(struct azctx ctx, scope_t *scps, type_t *types, ast_t ast,
err("analyzer: Unknown symbol ‘%.*s’", SV_PRI_ARGS(sv));
}
+ case ASTUNCMPL:
case ASTUNNEG: {
idx_t ni, rhs;
rhs = ast.kids[i].rhs;
ni = analyzeexpr(ctx, scps, types, ast, aux, toks, rhs);
type_t t = types[rhs];
- if (t.kind != TYPE_NUM || !t.issigned)
+ if (ast.kinds[i] == ASTUNNEG && (t.kind != TYPE_NUM || !t.issigned))
err("analyzer: Unary negation is reserved for signed numeric types");
+ else if (ast.kinds[i] == ASTUNCMPL && (t.kind != TYPE_NUM || t.isfloat))
+ err("analyzer: Unary negation is reserved for numeric integer types");
types[i] = t;
return ni;
}
@@ -323,7 +326,8 @@ analyzeexpr(struct azctx ctx, scope_t *scps, type_t *types, ast_t ast,
case ASTBINSUB:
case ASTBINMUL:
case ASTBINDIV:
- case ASTBINMOD: {
+ case ASTBINMOD:
+ case ASTBINXOR: {
idx_t lhs, rhs;
lhs = ast.kids[i].lhs;
rhs = ast.kids[i].rhs;
@@ -338,6 +342,9 @@ analyzeexpr(struct azctx ctx, scope_t *scps, type_t *types, ast_t ast,
err("analyzer: Remainder is not defined for non-integer types");
if (types[rhs].kind != TYPE_NUM || types[rhs].isfloat)
err("analyzer: Remainder is not defined for non-integer types");
+ } else if (ast.kinds[i] == ASTBINXOR) {
+ if (types[lhs].kind != TYPE_NUM || types[lhs].isfloat)
+ err("analyzer: XOR is not defined for non-integer types");
}
/* In the expression ‘x ⋆ y’ where ⋆ is a binary operator, the
@@ -519,6 +526,12 @@ constfoldexpr(struct cfctx ctx, mpq_t *folds, scope_t *scps, type_t *types,
}
}
}
+ case ASTUNCMPL: {
+ idx_t ni = constfoldexpr(ctx, folds, scps, types, ast, toks, ast.kids[i].rhs);
+ if (MPQ_IS_INIT(folds[ast.kids[i].rhs]))
+ err("analyzer: Cannot perform bitwise complement of constant");
+ return ni;
+ }
case ASTUNNEG: {
idx_t rhs = ast.kids[i].rhs;
idx_t ni = constfoldexpr(ctx, folds, scps, types, ast, toks, rhs);
@@ -568,7 +581,14 @@ constfoldexpr(struct cfctx ctx, mpq_t *folds, scope_t *scps, type_t *types,
}
return ni;
}
- case ASTBINMOD: {
+ case ASTBINMOD:
+ case ASTBINXOR: {
+ static void (*const mpz_fns[UINT8_MAX])(mpz_t, const mpz_t,
+ const mpz_t) = {
+ ['%'] = mpz_tdiv_q,
+ ['~'] = mpz_xor,
+ };
+
idx_t lhs, rhs;
lhs = ast.kids[i].lhs;
rhs = ast.kids[i].rhs;
@@ -578,8 +598,8 @@ constfoldexpr(struct cfctx ctx, mpq_t *folds, scope_t *scps, type_t *types,
if (MPQ_IS_INIT(folds[lhs]) && MPQ_IS_INIT(folds[rhs])) {
mpq_init(folds[i]);
- mpz_tdiv_r(mpq_numref(folds[i]), mpq_numref(folds[lhs]),
- mpq_numref(folds[rhs]));
+ mpz_fns[ast.kinds[i]](mpq_numref(folds[i]), mpq_numref(folds[lhs]),
+ mpq_numref(folds[rhs]));
}
return ni;
}