diff --git a/App/lib/core/Gen/Expr/ExprGenOps.vp b/App/lib/core/Gen/Expr/ExprGenOps.vp index a786e41..ab9acf7 100644 --- a/App/lib/core/Gen/Expr/ExprGenOps.vp +++ b/App/lib/core/Gen/Expr/ExprGenOps.vp @@ -1344,6 +1344,21 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): elif op == ast.OpKind.BitOr: cf_v = lhs.IntVal | rhs.IntVal elif op == ast.OpKind.BitAnd: cf_v = lhs.IntVal & rhs.IntVal elif op == ast.OpKind.BitXor: cf_v = lhs.IntVal ^ rhs.IntVal + elif op == ast.OpKind.Div or op == ast.OpKind.FloorDiv or op == ast.OpKind.Mod: + # 除法/整除/取模也做静态折叠(与 + - * 同口径:算精确值,再由下面按值自动提升位宽)。 + # ① 除零:绝不交给宿主(Python 会直接把编译器打挂)——先关掉折叠再 fail-fast + # (诊断口径与 AssignGenMixin 的常量求值器一致)。 + # ② 负数语义**待定**(负值参与时 sdiv/srem 的向零截断 vs 地板语义尚无结论)⇒ + # 暂只折叠两侧都非负的情形(此时 sdiv 与 udiv 结果相同,无歧义); + # 含负操作数的算式不折叠,照旧走运行期 sdiv/udiv/srem/urem。 + if rhs.IntVal == 0: + cf_ok = 0 + self.Gen.TypeGenErr.fatal_error(node, "constant expression division by zero: the right operand of '/', '//' or '%' evaluates to 0 at compile time.", "ValueError") + elif lhs.IntVal >= 0 and rhs.IntVal >= 0: + if op == ast.OpKind.Mod: cf_v = lhs.IntVal % rhs.IntVal + else: cf_v = lhs.IntVal // rhs.IntVal + else: + cf_ok = 0 elif op == ast.OpKind.LShift or op == ast.OpKind.RShift: if rhs.IntVal >= 0 and rhs.IntVal < 64: if op == ast.OpKind.LShift: cf_v = lhs.IntVal << rhs.IntVal