Files
ViperC/App/lib/core/Handles/HandlesAugAssign.vp
T
TermiNexus 9d3483e97e refactor: 全面 fail-fast 化(去兜底)+ 泛型补译/解引用宽度修复
- 全量降级点改 fail-fast:23 文件约 140+ 处静默 i32/i8*/void/continue 兜底改为 HandlesType.fatal_error(python traceback 风格)或 VLogger.error 终止,暴露上游根因;保留语言语义默认(无注解 i32/infer 链/CIf/star 回退)
- 泛型特化 Phase B 补译 reemit 强制发射方法体(修复 list[...] define 缺失)
- c.Deref 读取宽度仅按赋值直接 RHS 推断(修复 CurAssignAnnot 残留误判 i32)
- 类型别名清理:t.CChar|t.CPtr→str、t.CInt→int 等
2026-08-13 02:11:49 +08:00

301 lines
13 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import stdio
import string
import viperlib
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesVar as HandlesVar
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesType as HandlesType
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
#
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
# P6 对象化重构:模块级无状态函数已迁移为 lib.core.Gen.AssignGenMixin
# 的方法,本模块保留同名模块级函数作为"一行委托":延迟 import Gen
# 取全局单例(BuildPipeline/main 创建后 set_global_gen 注册),再调用
# gen 的对应方法。签名与旧函数完全一致,调用方零改动。
# ============================================================
_g_gen: t.CVoid | t.CPtr = None
def set_global_gen(gen: t.CVoid | t.CPtr) -> None:
"""注入全局 gen 单例(BuildPipeline/main 调用)"""
global _g_gen
_g_gen = gen
# ============================================================
# HandlesAugAssign - 增强赋值语句处理(Mixin 继承模式)
#
# 处理 += -= *= /= %= &= |= ^= <<= >>=
# 流程: load target → apply binop → store result
#
# 支持 local/global/nonlocal 三种变量作用域
# ============================================================
@t.NoVTable
class AugAssignHandle(HandlesBase.Mixin):
"""增强赋值处理器 (+=, -=, *=, etc.):继承 Mixin 获得 Trans 回指针"""
def __init__(self, trans: HT.Translator | t.CPtr):
self.Trans = trans
# ============================================================
# Handle - 处理 AugAssign 语句,返回新增变量数(始终为 0)
# ============================================================
def Handle(self, node: ast.AST | t.CPtr) -> int:
"""翻译增强赋值语句 (x += 1, y -= 2, etc.)"""
if node is None:
return 0
aug: ast.AugAssign | t.CPtr = (ast.AugAssign | t.CPtr)(node)
if aug is None:
return 0
target: ast.AST | t.CPtr = aug.target
if target is None:
return 0
tk: int = target.kind()
# Attribute 目标: self.field += 1
# 流程: get_attribute_ptr → load → binop → store
if tk == ast.ASTKind.Attribute:
pool: memhub.MemBuddy | t.CPtr = self.Trans.Pool
builder: llvmlite.IRBuilder | t.CPtr = self.Trans._cur_builder
mod: llvmlite.LLVMModule | t.CPtr = self.Trans.Module
# 1. 获取字段指针
field_ptr: llvmlite.Value | t.CPtr = HandlesExpr.get_attribute_ptr(
builder, pool, mod, target, self.Trans)
if field_ptr is None:
# fail-fast: 属性指针解析失败
HandlesType.fatal_error(target, "attribute ptr is None", "TypeError")
# 2. 确定字段类型并加载当前值
target_ty: llvmlite.LLVMType | t.CPtr = None
if field_ptr.Ty is not None and field_ptr.Ty.Pointee is not None:
target_ty = field_ptr.Ty.Pointee
if target_ty is None:
# fail-fast: 字段类型信息缺失,禁止兜底 i32
HandlesType.fatal_error(target, "字段类型信息缺失", "TypeError")
cur_val: llvmlite.Value | t.CPtr = llvmlite.build_load(
builder, target_ty, field_ptr)
if cur_val is None:
# fail-fast: 属性当前值加载失败
HandlesType.fatal_error(target, "无法加载 attribute 当前值", "TypeError")
# 3. 翻译 RHS 值
rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
builder, pool, mod, aug.value, None, 0, self.Trans)
if rhs_val is None:
# fail-fast: RHS 翻译失败
HandlesType.fatal_error(target, "rhs 翻译失败", "TypeError")
# 4. 应用二元运算
result: llvmlite.Value | t.CPtr = _apply_aug_op(
pool, builder, aug.op, cur_val, rhs_val, node, self.Trans, target)
if result is None:
# fail-fast: attribute 二元运算失败
HandlesType.fatal_error(target, f"attribute 二元运算失败 op={aug.op}", "TypeError")
# 5. 类型对齐并存储
result = HandlesExpr.coerce_to_type(builder, result, target_ty, node)
if result is None:
# fail-fast: 类型对齐失败
HandlesType.fatal_error(target, "类型对齐失败", "TypeError")
llvmlite.build_store(builder, result, field_ptr)
return 0
# Subscript 目标: self.state[i] += x / arr[i] += x
# 流程: get_subscript_ptr → load → binop → store
if tk == ast.ASTKind.Subscript:
pool: memhub.MemBuddy | t.CPtr = self.Trans.Pool
builder: llvmlite.IRBuilder | t.CPtr = self.Trans._cur_builder
mod: llvmlite.LLVMModule | t.CPtr = self.Trans.Module
# 1. 获取元素指针
elem_ptr: llvmlite.Value | t.CPtr = HandlesExpr.get_subscript_ptr(
builder, pool, mod, target, self.Trans)
if elem_ptr is None:
# fail-fast: 下标指针解析失败
HandlesType.fatal_error(target, "subscript ptr is None", "TypeError")
# 2. 确定元素类型并加载当前值
target_ty: llvmlite.LLVMType | t.CPtr = None
if elem_ptr.Ty is not None and elem_ptr.Ty.Pointee is not None:
target_ty = elem_ptr.Ty.Pointee
if target_ty is None:
# fail-fast: 元素类型信息缺失,禁止兜底 i32
HandlesType.fatal_error(target, "元素类型信息缺失", "TypeError")
cur_val: llvmlite.Value | t.CPtr = llvmlite.build_load(
builder, target_ty, elem_ptr)
if cur_val is None:
# fail-fast: 元素当前值加载失败
HandlesType.fatal_error(target, "无法加载 subscript 元素当前值", "TypeError")
# 3. 翻译 RHS 值
rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
builder, pool, mod, aug.value, None, 0, self.Trans)
if rhs_val is None:
# fail-fast: RHS 翻译失败
HandlesType.fatal_error(target, "rhs 翻译失败", "TypeError")
# 4. 应用二元运算
result: llvmlite.Value | t.CPtr = _apply_aug_op(
pool, builder, aug.op, cur_val, rhs_val, node, self.Trans, target)
if result is None:
# fail-fast: subscript 二元运算失败
HandlesType.fatal_error(target, f"subscript 二元运算失败 op={aug.op}", "TypeError")
# 5. 类型对齐并存储
result = HandlesExpr.coerce_to_type(builder, result, target_ty, node)
if result is None:
# fail-fast: 类型对齐失败
HandlesType.fatal_error(target, "类型对齐失败", "TypeError")
llvmlite.build_store(builder, result, elem_ptr)
return 0
if tk != ast.ASTKind.Name:
# fail-fast: 不支持的 AugAssign 目标类型
HandlesType.fatal_error(
target, "AugAssign 目标类型不支持,仅支持 Name/Attribute/Subscript", "TypeError")
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(target)
if nm is None or nm.id is None:
return 0
pool: memhub.MemBuddy | t.CPtr = self.Trans.Pool
builder: llvmlite.IRBuilder | t.CPtr = self.Trans._cur_builder
mod: llvmlite.LLVMModule | t.CPtr = self.Trans.Module
# 1. 确定变量作用域类型: 0=local, 1=global, 2=nonlocal
scope_type: int = 0
if HT.is_global_name(self.Trans, nm.id) != 0:
scope_type = 1
elif HT.is_nonlocal_name(self.Trans, nm.id) != 0:
scope_type = 2
# 2. 加载当前值
cur_val: llvmlite.Value | t.CPtr = None
target_alloca: llvmlite.Value | t.CPtr = None
target_ty: llvmlite.LLVMType | t.CPtr = None
if scope_type == 1:
# global 变量
target_alloca = HandlesVar.lookup_module_var(
self.Trans.SymTab, nm.id)
if target_alloca is not None:
if target_alloca.Ty is None:
# fail-fast: 变量类型信息缺失,禁止兜底 i32
HandlesType.fatal_error(target, "变量类型信息缺失", "TypeError")
target_ty = target_alloca.Ty.Pointee
cur_val = llvmlite.build_load(builder, target_ty, target_alloca)
elif scope_type == 2:
# nonlocal 变量(通过闭包 env)
cur_val = HandlesNonlocal.load_nonlocal_var(self.Trans, nm.id)
if cur_val is not None:
target_ty = cur_val.Ty
else:
# 普通局部变量
target_alloca = HandlesVar.lookup_var(self.Trans.SymTab, nm.id)
if target_alloca is not None:
if target_alloca.Ty is None:
# fail-fast: 变量类型信息缺失,禁止兜底 i32
HandlesType.fatal_error(target, "变量类型信息缺失", "TypeError")
target_ty = target_alloca.Ty.Pointee
cur_val = llvmlite.build_load(builder, target_ty, target_alloca)
if cur_val is None:
# fail-fast: 目标变量当前值加载失败
HandlesType.fatal_error(
target,
f"无法加载目标变量 '{nm.id}' 的当前值",
"TypeError")
# 3. 翻译 RHS 值
rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
builder, pool, mod, aug.value, None, 0, self.Trans)
if rhs_val is None:
# fail-fast: RHS 翻译失败
HandlesType.fatal_error(target, "rhs 翻译失败", "TypeError")
# 4. 类型对齐 + 应用二元运算
# 注意: AugAssign 不走运算符重载(语义上需要 __iadd__ 而非 __add__)
result: llvmlite.Value | t.CPtr = _apply_aug_op(
pool, builder, aug.op, cur_val, rhs_val, node, self.Trans, target)
if result is None:
# fail-fast: 二元运算失败
HandlesType.fatal_error(
target,
f"对变量 '{nm.id}' 应用二元运算失败 op={aug.op}",
"TypeError")
# 5. 存储结果
result = HandlesExpr.coerce_to_type(builder, result, target_ty, node)
if result is None:
# fail-fast: 类型对齐失败
HandlesType.fatal_error(target, "类型对齐失败", "TypeError")
if scope_type == 1:
# global 变量
if target_alloca is not None:
llvmlite.build_store(builder, result, target_alloca)
elif scope_type == 2:
# nonlocal 变量
nl_ptr: llvmlite.Value | t.CPtr = HandlesNonlocal.get_nonlocal_var_ptr(
self.Trans, nm.id)
if nl_ptr is not None:
llvmlite.build_store(builder, result, nl_ptr)
else:
# 普通局部变量
if target_alloca is not None:
llvmlite.build_store(builder, result, target_alloca)
return 0
# ============================================================
# _apply_aug_op - 应用增强赋值的二元运算
#
# 支持浮点运算、指针算术: ptr += int / ptr -= int
# 整数运算自动类型提升
# ============================================================
def _apply_aug_op(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
op: int,
lhs: llvmlite.Value | t.CPtr,
rhs: llvmlite.Value | t.CPtr,
node: ast.AST | t.CPtr = None,
trans: HT.Translator | t.CPtr = None,
lhs_node: ast.AST | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""应用增强赋值的二元运算(浮点 + 指针算术 + 整数运算,委托到 gen._apply_aug_op)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._apply_aug_op(pool, builder, op, lhs, rhs, node, trans, lhs_node)
return None
# ============================================================
# NewAugAssignHandle - 工厂函数
# ============================================================
def NewAugAssignHandle(pool: memhub.MemBuddy | t.CPtr,
trans: HT.Translator | t.CPtr) -> AugAssignHandle | t.CPtr:
h: AugAssignHandle | t.CPtr = pool.alloc(AugAssignHandle.__sizeof__())
if h is None:
return None
string.memset(h, 0, AugAssignHandle.__sizeof__())
h.Trans = trans
return h