fix(assign): 类型变量赋值限定链根为模块

f19d2578 退役 t/c 模块时移除了 IsTModule 检查,任意 x = y.attr 都被当作类型变量赋值:只发射 __x_fmt/__x_kind 两个 store 就 return,真实赋值丢失。includes/json 链表遍历 cur = cur.next 因此不前进,viperc.exe 运行卡在 Load_project_config。恢复判据:链根必须是 import 模块,且属性名是已知类型名。
This commit is contained in:
TermiNexus committed 2026-10-19 19:05:13 +08:00
1 parent 103cd4ff26
commit 077d705609
1 file changed
+52 -29
+52 -29
View File
@@ -65,36 +65,59 @@ class AssignHandle(BaseHandle):
sys.exit(1)
if isinstance(Node.value, ast.Attribute) and isinstance(Node.value.value, ast.Name) :
AttrName: str = Node.value.attr
Gen.var_type_info[VarName] = {'type': 't_type', 'name': AttrName}
Gen.var_type_assignments.setdefault(VarName, []).append({'type': 't_type', 'name': AttrName})
c_type_name: str = ''
resolved: tuple[type, int] | None = CTypeRegistry.ResolveName(AttrName)
if resolved is not None:
ctype_cls: type = resolved[0]
ptr_level: int = resolved[1]
c_type_name = CTypeRegistry.CTypeToName(ctype_cls)
if ptr_level > 0 and c_type_name:
c_type_name = c_type_name + ' *'
if not c_type_name:
if AttrName == 'CPtr':
c_type_name = 'void *'
is_unsigned: bool = Gen._is_type_unsigned(c_type_name) if c_type_name else False
fmt_str: str = "%u\n" if is_unsigned else "%d\n"
fmt_ptr: ir.Value = Gen._create_string_global(fmt_str)
fmt_var_name: str = f"__{VarName}_fmt"
if fmt_var_name not in Gen.variables:
fmt_alloca: ir.AllocaInstr = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name=fmt_var_name)
Gen.variables[fmt_var_name] = fmt_alloca
Gen.builder.store(fmt_ptr, Gen.variables[fmt_var_name])
kind_var_name: str = f"__{VarName}_kind"
if kind_var_name not in Gen.variables:
kind_alloca: ir.AllocaInstr = Gen._allocaEntry(ir.IntType(32), name=kind_var_name)
Gen.variables[kind_var_name] = kind_alloca
Gen.builder.store(ir.Constant(ir.IntType(32), 0), Gen.variables[kind_var_name])
if VarName not in Gen.variables:
dummy_var: ir.AllocaInstr = Gen._alloca(ir.IntType(8), name=VarName)
Gen.variables[VarName] = dummy_var
return
# 只有"模块名.类型名"才是类型变量赋值(旧 t/c 模块写法:x = t.CInt32T)。
# 判据必须限定链根是模块:f19d2578 退役 t/c 时丢了 IsTModule 检查,
# 使普通属性读取赋值(如 cur = cur.next)也被当成类型赋值 —— 只发射
# __<var>_fmt / __<var>_kind 两个无效 store 就 return,真实赋值丢失
# (现场:includes/json 链表遍历 cur 永不前进 → 死循环)。
_BaseName: str = Node.value.value.id
_SymTab = self.Trans.SymbolTable
_BaseIsModule: bool = bool(
_BaseName in (getattr(self.Trans, '_ImportedModules', None) or set())
or _BaseName in _SymTab.import_aliases)
if not _BaseIsModule:
_AliasInfo = _SymTab.lookup(_BaseName)
_BaseIsModule = bool(_AliasInfo is not None
and getattr(_AliasInfo, 'IsModuleAlias', False))
_TypeInfo = _SymTab.lookup(AttrName)
_IsTypeName: bool = bool(
_BaseIsModule and (
resolved is not None or AttrName == 'CPtr'
or (_TypeInfo is not None and (
getattr(_TypeInfo, 'IsTypedef', False)
or getattr(_TypeInfo, 'IsStruct', False)
or getattr(_TypeInfo, 'IsEnum', False)))))
if _IsTypeName:
Gen.var_type_info[VarName] = {'type': 't_type', 'name': AttrName}
Gen.var_type_assignments.setdefault(VarName, []).append({'type': 't_type', 'name': AttrName})
c_type_name: str = ''
if resolved is not None:
ctype_cls: type = resolved[0]
ptr_level: int = resolved[1]
c_type_name = CTypeRegistry.CTypeToName(ctype_cls)
if ptr_level > 0 and c_type_name:
c_type_name = c_type_name + ' *'
if not c_type_name:
if AttrName == 'CPtr':
c_type_name = 'void *'
is_unsigned: bool = Gen._is_type_unsigned(c_type_name) if c_type_name else False
fmt_str: str = "%u\n" if is_unsigned else "%d\n"
fmt_ptr: ir.Value = Gen._create_string_global(fmt_str)
fmt_var_name: str = f"__{VarName}_fmt"
if fmt_var_name not in Gen.variables:
fmt_alloca: ir.AllocaInstr = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name=fmt_var_name)
Gen.variables[fmt_var_name] = fmt_alloca
Gen.builder.store(fmt_ptr, Gen.variables[fmt_var_name])
kind_var_name: str = f"__{VarName}_kind"
if kind_var_name not in Gen.variables:
kind_alloca: ir.AllocaInstr = Gen._allocaEntry(ir.IntType(32), name=kind_var_name)
Gen.variables[kind_var_name] = kind_alloca
Gen.builder.store(ir.Constant(ir.IntType(32), 0), Gen.variables[kind_var_name])
if VarName not in Gen.variables:
dummy_var: ir.AllocaInstr = Gen._alloca(ir.IntType(8), name=VarName)
Gen.variables[VarName] = dummy_var
return
if isinstance(Node.value, ast.Name) and Node.value.id in Gen.structs:
ClassName: str = Node.value.id
Gen.var_type_info[VarName] = {'type': 'class_cast', 'name': ClassName}