- 全量降级点改 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 等
301 lines
13 KiB
Plaintext
301 lines
13 KiB
Plaintext
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
|