aboutsummaryrefslogtreecommitdiff
path: root/src/analyzer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/analyzer.c')
-rw-r--r--src/analyzer.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/src/analyzer.c b/src/analyzer.c
index 2686e07..fff7716 100644
--- a/src/analyzer.c
+++ b/src/analyzer.c
@@ -331,8 +331,12 @@ analyzeexpr(struct azctx ctx, scope_t *scps, type_t *types, ast_t ast,
idx_t ni = analyzeexpr(ctx, scps, types, ast, aux, toks, rhs);
if (!typecompat(types[lhs], types[rhs]))
err("analyzer: Binary oprand type mismatch");
- if (ast.kinds[i] == ASTBINMOD && types[lhs].isfloat)
- err("analyzer: Modulus is not defined for floating-point types");
+ 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");
+ }
types[i] = types[rhs];
return ni;
}
@@ -488,8 +492,8 @@ constfoldexpr(struct cfctx ctx, mpq_t *folds, scope_t *scps, type_t *types,
MPQCPY(folds[i], folds[expr]);
if (!MPQ_IS_INIT(folds[i])) {
ctx.si = lvl;
- (void)constfolddecl(ctx, folds, scps, types,
- ast, toks, sym->i);
+ (void)constfolddecl(ctx, folds, scps, types, ast, toks,
+ sym->i);
MPQCPY(folds[i], folds[expr]);
assert(MPQ_IS_INIT(folds[i]));
}
@@ -516,16 +520,14 @@ constfoldexpr(struct cfctx ctx, mpq_t *folds, scope_t *scps, type_t *types,
case ASTBINADD:
case ASTBINSUB:
case ASTBINMUL:
- case ASTBINDIV:
- case ASTBINMOD: {
- static void (*const mpq_fns[UINT8_MAX])(mpq_t, const mpq_t, const mpq_t) = {
+ case ASTBINDIV: {
+ static void (*const mpq_fns[UINT8_MAX])(mpq_t, const mpq_t,
+ const mpq_t) = {
['+'] = mpq_add,
['-'] = mpq_sub,
['*'] = mpq_mul,
['/'] = mpq_div,
};
- /* TODO: Support modulus */
-
idx_t lhs, rhs;
lhs = ast.kids[i].lhs;
rhs = ast.kids[i].rhs;
@@ -537,6 +539,21 @@ constfoldexpr(struct cfctx ctx, mpq_t *folds, scope_t *scps, type_t *types,
}
return ni;
}
+ case ASTBINMOD: {
+ idx_t lhs, rhs;
+ lhs = ast.kids[i].lhs;
+ rhs = ast.kids[i].rhs;
+
+ (void)constfoldexpr(ctx, folds, scps, types, ast, toks, lhs);
+ idx_t ni = constfoldexpr(ctx, folds, scps, types, ast, toks, rhs);
+
+ 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]));
+ }
+ return ni;
+ }
case ASTFN:
return constfoldblk(ctx, folds, scps, types, ast, toks,
ast.kids[i].rhs);