From 3a687db0bbbd251cd9a5f46f4baf4a63892bbede Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 14 Oct 2026 22:28:43 +0800 Subject: [PATCH] =?UTF-8?q?feat(viperc):=20=E9=9D=99=E6=80=81=E5=B8=B8?= =?UTF-8?q?=E9=87=8F=E7=AE=97=E5=BC=8F=E8=A1=A5=E4=B8=8A=E9=99=A4=E6=B3=95?= =?UTF-8?q?/=E6=95=B4=E9=99=A4/=E5=8F=96=E6=A8=A1=E6=8A=98=E5=8F=A0?= =?UTF-8?q?=EF=BC=88=E4=B8=8E=E8=BF=90=E8=A1=8C=E6=9C=9F=20sdiv/srem=20?= =?UTF-8?q?=E5=90=8C=E5=8F=A3=E5=BE=84=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 此前纯常量折叠只覆盖 + - * | & ^ << >>,Div/FloorDiv/Mod 一律落到运行期 sdiv/udiv/srem/urem。现按同一维护口径补上:以精确值折叠,再由既有逻辑按结果值自动提升位宽(不无故抬宽,避免把 A/1 这类算式整体抬成 i64)。语义与运行期一致:Div/FloorDiv → sdiv(向零截断)、Mod → srem(余数符号随被除数)——宿主侧 // 与 % 正是这两个语义,无须额外修正;无符号位型常量按规范恒为非负,与运行期 udiv/urem 取值一致。除零不交给宿主(会打挂编译器):先关掉折叠再 fail-fast,诊断文本与 AssignGenMixin 的常量求值器保持一致。 --- App/lib/core/Gen/Expr/ExprGenOps.vp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) 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