aboutsummaryrefslogtreecommitdiff
path: root/src/analyzer.c
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2024-06-29 13:14:26 +0200
committerThomas Voss <mail@thomasvoss.com> 2024-06-29 13:14:26 +0200
commitcb962cc19004c08381b4425da8cf12a36456a7cb (patch)
tree377162577c7153fcf81e139a4c1b726d0f6410fe /src/analyzer.c
parent8dbb8162f99efe0f35b99df6379c71336a575222 (diff)
Add (x & y) and (x | y)
Diffstat (limited to 'src/analyzer.c')
-rw-r--r--src/analyzer.c33
1 files changed, 18 insertions, 15 deletions
diff --git a/src/analyzer.c b/src/analyzer.c
index ad69c69..4f5500a 100644
--- a/src/analyzer.c
+++ b/src/analyzer.c
@@ -330,9 +330,11 @@ analyzeexpr(struct azctx ctx, scope_t *scps, type_t *types, ast_t ast,
return ni;
}
case ASTBINADD:
+ case ASTBINAND:
case ASTBINDIV:
case ASTBINMOD:
case ASTBINMUL:
+ case ASTBINIOR:
case ASTBINSHL:
case ASTBINSHR:
case ASTBINSUB:
@@ -344,24 +346,19 @@ analyzeexpr(struct azctx ctx, scope_t *scps, type_t *types, ast_t ast,
idx_t ni = analyzeexpr(ctx, scps, types, ast, aux, toks, rhs);
bool isshift = ast.kinds[i] == ASTBINSHL || ast.kinds[i] == ASTBINSHR;
-
if (!isshift && !typecompat(types[lhs], types[rhs]))
err("analyzer: Binary oprand type mismatch");
- if (ast.kinds[i] == ASTBINMOD) {
- if (types[lhs].kind != TYPE_NUM || types[lhs].isfloat)
- 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");
- } else if (isshift) {
- if (types[lhs].kind != TYPE_NUM || types[lhs].isfloat
- || types[rhs].kind != TYPE_NUM || types[rhs].isfloat)
- {
- err("analyzer: Bit shift is not defined for non-integer types");
- }
+ static const bool int_only[UINT8_MAX + 1] = {
+ [ASTBINAND] = true, [ASTBINIOR] = true, [ASTBINMOD] = true,
+ [ASTBINSHL] = true, [ASTBINSHR] = true, [ASTBINXOR] = true,
+ };
+
+ if (int_only[ast.kinds[i]]
+ && (types[lhs].kind != TYPE_NUM || types[lhs].isfloat
+ || types[rhs].kind != TYPE_NUM || types[rhs].isfloat))
+ {
+ err("analyzer: Operation not defined for non-integer types");
}
/* In the expression ‘x ⋆ y’ where ⋆ is a binary operator, the
@@ -614,11 +611,15 @@ out:
}
break;
}
+ case ASTBINAND:
+ case ASTBINIOR:
case ASTBINMOD:
case ASTBINXOR: {
static void (*const mpz_fns[UINT8_MAX + 1])(mpz_t, const mpz_t,
const mpz_t) = {
['%'] = mpz_tdiv_q,
+ ['&'] = mpz_and,
+ ['|'] = mpz_ior,
['~'] = mpz_xor,
};
@@ -630,6 +631,8 @@ out:
ni = constfoldexpr(ctx, folds, scps, types, ast, toks, types[i], rhs);
if (MPQ_IS_INIT(folds[lhs]) && MPQ_IS_INIT(folds[rhs])) {
+ assert(MPQ_IS_WHOLE(folds[lhs]));
+ assert(MPQ_IS_WHOLE(folds[rhs]));
mpq_init(folds[i]);
mpz_fns[ast.kinds[i]](mpq_numref(folds[i]), mpq_numref(folds[lhs]),
mpq_numref(folds[rhs]));