diff --git a/App/lib/core/Gen/Expr/ExprGenOps.vp b/App/lib/core/Gen/Expr/ExprGenOps.vp index ab9acf7..ab972f4 100644 --- a/App/lib/core/Gen/Expr/ExprGenOps.vp +++ b/App/lib/core/Gen/Expr/ExprGenOps.vp @@ -1345,20 +1345,18 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): 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。 + # 除法/整除/取模也做静态折叠(与 + - * 完全同口径:算精确值,再由下面按值自动提升位宽)。 + # 语义**与运行期一致**:Div/FloorDiv → sdiv(向零截断),Mod → srem(余数符号随被除数) + # —— 宿主侧的 `//` / `%` 正是这两个语义(本语言把 FloorDiv 也映射成 sdiv, + # 见本文件运行期分支;AssignGenMixin 的常量求值器同款)。无符号位型常量按规范 + # 恒为非负,负值常量必属有符号操作数集 ⇒ 与运行期 udiv/urem 的取值一致。 + # 除零:绝不交给宿主(Python 会直接把编译器打挂)——先关掉折叠再 fail-fast + # (诊断文本与 AssignGenMixin 的常量求值器一致)。 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.Mod: cf_v = lhs.IntVal % rhs.IntVal + else: cf_v = lhs.IntVal // rhs.IntVal 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