from __future__ import annotations from typing import TYPE_CHECKING, Any if TYPE_CHECKING: from lib.core.translator import Translator from lib.core.LlvmCodeGenerator import LlvmCodeGenerator import ast import copy import traceback import llvmlite.ir as ir from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta from lib.core.SymbolUtils import IsTModule from lib.core.VLogger import get_logger as _vlog from lib.constants.config import mode as _config_mode from lib.includes import t from lib.includes.t import CTypeRegistry # t 模块存储类标记装饰器名称集合 _T_STORAGE_DECORATORS = frozenset({'CExport', 'CExtern', 'CStatic', 'State', 'CInline', 'TLS'}) class FunctionHandle(BaseHandle): @staticmethod def _ExtractFuncMeta(decorator_list: list[ast.AST]) -> FuncMeta: meta: FuncMeta = FuncMeta.NONE if not decorator_list: return meta for d in decorator_list: if isinstance(d, ast.Name): if d.id == 'staticmethod': meta |= FuncMeta.STATIC_METHOD elif d.id == 'property': meta |= FuncMeta.PROPERTY_GETTER elif d.id == 'classmethod': meta |= FuncMeta.CLASS_METHOD elif isinstance(d, ast.Attribute): if isinstance(d.value, ast.Name): # 支持 @property.setter 和 @propname.setter 两种形式 # @propname.setter 中 propname 是之前用 @property 定义的同名属性 if d.value.id == 'property' or d.attr in ('setter', 'getter', 'deleter'): if d.attr == 'setter': meta |= FuncMeta.PROPERTY_SETTER elif d.attr == 'getter': meta |= FuncMeta.PROPERTY_GETTER elif d.attr == 'deleter': meta |= FuncMeta.PROPERTY_DELETER return meta def _extract_decorator_storage_flags(self, Node: ast.FunctionDef) -> dict[str, bool]: """从装饰器列表中提取 t 模块存储类标记 支持 @t.CExport, @t.CExtern, @t.CStatic, @t.State, @t.CInline 也支持 from t import CExport 等别名形式 Returns: dict with keys: 'is_export', 'is_extern', 'is_static', 'is_state', 'is_inline' """ flags: dict[str, bool] = { 'is_export': False, 'is_extern': False, 'is_static': False, 'is_state': False, 'is_inline': False, } if not Node.decorator_list: return flags symtab: object = self.Trans.SymbolTable for decorator in Node.decorator_list: attr_name: str | None = None # @t.CExport 形式 if isinstance(decorator, ast.Attribute) and isinstance(decorator.value, ast.Name): if IsTModule(decorator.value.id, symtab): attr_name = decorator.attr # @CExport 形式 (from t import CExport) elif isinstance(decorator, ast.Name): cls: type | None = getattr(t, decorator.id, None) if cls is None and hasattr(symtab, '_t_type_symbols'): cls = symtab._t_type_symbols.get(decorator.id) if cls is not None and isinstance(cls, type) and issubclass(cls, t.CType): attr_name = cls.__name__ if attr_name and attr_name in _T_STORAGE_DECORATORS: if attr_name == 'CExport': flags['is_export'] = True elif attr_name == 'CExtern': flags['is_extern'] = True elif attr_name == 'CStatic': flags['is_static'] = True elif attr_name == 'State': flags['is_state'] = True elif attr_name == 'CInline': flags['is_inline'] = True return flags @staticmethod def _is_t_storage_decorator(decorator: ast.AST, symtab: object) -> bool: """检查装饰器是否是 t 模块存储类标记(用于排除 behavior_decorators)""" attr_name: str | None = None if isinstance(decorator, ast.Attribute) and isinstance(decorator.value, ast.Name): if IsTModule(decorator.value.id, symtab): attr_name = decorator.attr elif isinstance(decorator, ast.Name): cls: type | None = getattr(t, decorator.id, None) if cls is None and hasattr(symtab, '_t_type_symbols'): cls = symtab._t_type_symbols.get(decorator.id) if cls is not None and isinstance(cls, type) and issubclass(cls, t.CType): attr_name = cls.__name__ elif decorator.id in _T_STORAGE_DECORATORS and hasattr(t, decorator.id): # TLS 是普通函数标记,不是 CType 子类 attr_name = decorator.id return attr_name in _T_STORAGE_DECORATORS if attr_name else False def _body_contains_raise(self, body: list[ast.AST]) -> bool: for node in ast.walk(ast.Module(body=body, type_ignores=[])): if isinstance(node, ast.Raise): if node.exc: if isinstance(node.exc, ast.Name) and node.exc.id == 'StopIteration': continue if isinstance(node.exc, ast.Call) and isinstance(node.exc.func, ast.Name) and node.exc.func.id == 'StopIteration': continue return True if isinstance(node, ast.Call): called_name: str | None = None if isinstance(node.func, ast.Name): called_name = node.func.id elif isinstance(node.func, ast.Attribute): called_name = node.func.attr if called_name: Gen: LlvmCodeGenerator = self.Trans.LlvmGen for prefix in ['', f'{called_name}.', f'__']: for suffix in ['', f'.{called_name}']: fname: str = f'{prefix}{called_name}{suffix}' if fname in Gen.functions: func: Any = Gen.functions[fname] if len(func.args) > 0: for arg in func.args: if hasattr(arg, 'name') and arg.name in ('__eh_msg_out__', '__eh_code_out__'): return True break return False _LLVM_ATTR_NAMES = frozenset({ 'nobuiltin', 'nounwind', 'noredzone', 'willreturn', 'mustprogress', 'optnone', 'noinline', 'alwaysinline', 'readnone', 'readonly', 'writeonly', 'inaccessiblememonly', 'inaccessiblemem_or_argmemonly', }) def _ExtractLLVMAttrs(self, node: ast.AST) -> list[str]: attrs: list[str] = [] if isinstance(node, ast.BinOp): attrs.extend(self._ExtractLLVMAttrs(node.left)) attrs.extend(self._ExtractLLVMAttrs(node.right)) elif isinstance(node, ast.Attribute): attr_name: str | None = self._GetAttrLLVMName(node) if attr_name: attrs.append(attr_name) return attrs def _GetAttrLLVMName(self, node: ast.AST) -> str | None: if not isinstance(node, ast.Attribute): return None if node.attr not in self._LLVM_ATTR_NAMES: return None value: ast.AST = node.value if not isinstance(value, ast.Attribute) or value.attr != 'llvm': return None inner: ast.AST = value.value if not isinstance(inner, ast.Attribute) or inner.attr != 'attr': return None if not isinstance(inner.value, ast.Name) or inner.value.id != 't': return None return node.attr def _infer_return_type_from_body(self, Node: ast.AST, Gen: LlvmCodeGenerator | None = None, ClassName: str | None = None) -> tuple[str, bool] | None: local_var_types: dict[str, tuple[str, bool]] = {} for child in ast.walk(Node): if isinstance(child, ast.Assign) and len(child.targets) == 1: target: ast.AST = child.targets[0] if isinstance(target, ast.Name) and isinstance(child.value, ast.Subscript): sub: ast.Subscript = child.value if (isinstance(sub.value, ast.Attribute) and isinstance(sub.value.value, ast.Name) and sub.value.value.id == 'self' and ClassName and ClassName in Gen.class_members): member_name: str = sub.value.attr for m_name, m_type in Gen.class_members[ClassName]: if m_name == member_name: if isinstance(m_type, ir.ArrayType): elem_type: ir.Type = m_type.element if isinstance(elem_type, ir.FloatType): local_var_types[target.id] = ('float', False) elif isinstance(elem_type, ir.DoubleType): local_var_types[target.id] = ('double', False) elif isinstance(elem_type, ir.IntType): if elem_type.width == 8: local_var_types[target.id] = ('char', False) else: local_var_types[target.id] = ('int', False) elif isinstance(elem_type, ir.PointerType): if isinstance(elem_type.pointee, ir.IntType) and elem_type.pointee.width == 8: local_var_types[target.id] = ('char', True) else: local_var_types[target.id] = ('void', True) elif isinstance(elem_type, ir.IdentifiedStructType): struct_name: str = elem_type.name if struct_name: for sn, st in Gen.structs.items(): if st.name == struct_name or sn == struct_name: local_var_types[target.id] = (sn, False) break else: local_var_types[target.id] = (elem_type.name, False) elif isinstance(m_type, ir.PointerType): pointee: ir.Type = m_type.pointee if isinstance(pointee, ir.FloatType): local_var_types[target.id] = ('float', False) elif isinstance(pointee, ir.DoubleType): local_var_types[target.id] = ('double', False) elif isinstance(pointee, ir.IntType): if pointee.width == 8: local_var_types[target.id] = ('char', False) else: local_var_types[target.id] = ('int', False) elif isinstance(pointee, ir.PointerType): local_var_types[target.id] = ('void', True) elif isinstance(pointee, ir.IdentifiedStructType): for sn, st in Gen.structs.items(): if st == pointee or st.name == pointee.name: local_var_types[target.id] = (sn, True) break break for child in ast.walk(Node): if isinstance(child, ast.Return) and child.value: val: ast.AST = child.value if isinstance(val, ast.Name) and val.id == 'self' and ClassName: return (ClassName, True) if isinstance(val, ast.Call): if isinstance(val.func, ast.Name): callee: str = val.func.id if callee == 'malloc': return ('char', True) if callee == 'chr': return ('char', False) if Gen and callee in Gen.functions: func: Any = Gen.functions[callee] if hasattr(func, 'ftype'): ret_type: ir.Type = func.ftype.return_type if isinstance(ret_type, ir.PointerType): if isinstance(ret_type.pointee, ir.IntType) and ret_type.pointee.width == 8: return ('char', True) return ('void', True) elif isinstance(ret_type, ir.IntType): if ret_type.width == 8: return ('char', False) return ('int', False) elif isinstance(ret_type, ir.VoidType): return ('void', False) elif isinstance(val.func, ast.Attribute): pass callee_name: str | None = None if isinstance(val.func, ast.Name): callee_name = val.func.id elif isinstance(val.func, ast.Attribute): callee_name = getattr(val.func, 'attr', None) if callee_name: sym: Any = self.Trans.SymbolTable.lookup(callee_name) if sym and isinstance(sym, dict): ret_type_str: str = sym.get('return_type', '') if ret_type_str and ret_type_str != 'int': IsPtr: bool = sym.get('IsPtr', False) return (ret_type_str, IsPtr) elif isinstance(val, ast.Constant): if val.value is None: return ('char', True) elif isinstance(val.value, str) and len(val.value) <= 1: return ('char', True) elif isinstance(val, ast.Name): var_name: str = val.id if var_name in local_var_types: return local_var_types[var_name] var_info: Any = self.Trans.SymbolTable.lookup(var_name) if var_info and isinstance(var_info, dict): var_type: str = var_info.get('type', '') if var_type and var_type != 'int': IsPtr: bool = var_info.get('IsPtr', False) return (var_type, IsPtr) elif isinstance(val, ast.Subscript): if (isinstance(val.value, ast.Attribute) and isinstance(val.value.value, ast.Name) and val.value.value.id == 'self' and ClassName): member_name: str = val.value.attr if ClassName in Gen.class_members: for m_name, m_type in Gen.class_members[ClassName]: if m_name == member_name: if isinstance(m_type, ir.ArrayType): elem_type: ir.Type = m_type.element if isinstance(elem_type, ir.FloatType): return ('float', False) elif isinstance(elem_type, ir.DoubleType): return ('double', False) elif isinstance(elem_type, ir.IntType): if elem_type.width == 8: return ('char', False) return ('int', False) elif isinstance(elem_type, ir.PointerType): if isinstance(elem_type.pointee, ir.IntType) and elem_type.pointee.width == 8: return ('char', True) return ('void', True) elif isinstance(elem_type, ir.IdentifiedStructType): struct_name: str = elem_type.name if struct_name: for sn, st in Gen.structs.items(): if st.name == struct_name or sn == struct_name: return (sn, False) return (elem_type.name, False) elif isinstance(m_type, ir.PointerType): pointee: ir.Type = m_type.pointee if isinstance(pointee, ir.FloatType): return ('float', False) elif isinstance(pointee, ir.DoubleType): return ('double', False) elif isinstance(pointee, ir.IntType): if pointee.width == 8: return ('char', False) return ('int', False) elif isinstance(pointee, ir.PointerType): return ('void', True) elif isinstance(pointee, ir.IdentifiedStructType): for sn, st in Gen.structs.items(): if st == pointee or st.name == pointee.name: return (sn, True) return (pointee.name, True) break if isinstance(val.value, ast.Name): var_name: str = val.value.id var_info: Any = self.Trans.SymbolTable.lookup(var_name) if var_info and isinstance(var_info, dict): var_type: str = var_info.get('type', '') if var_type.startswith('list[') or var_type.startswith('List[') or var_type.startswith('t.CArray['): inner: str = var_type[var_type.index('[') + 1:var_type.rindex(']')] parts: list[str] = inner.split(',') elem_type_str: str = parts[0].strip() if elem_type_str and elem_type_str != 'int': IsPtr: bool = var_info.get('IsPtr', False) return (elem_type_str, IsPtr) return None def _GetFunctionSignatureLlvm(self, Node: ast.FunctionDef, Gen: LlvmCodeGenerator, ClassName: str | None = None, extra_params: list[tuple[str, Any]] | None = None) -> tuple[str, ir.FunctionType, Any, list[Any], list[ast.AST], bool, str | None, bool]: RawFuncName: str = Node.name if ClassName: FuncName: str = f"{ClassName}.{RawFuncName}" else: FuncName = RawFuncName # property setter/deleter 使用不同的函数名后缀,避免与 getter 冲突 func_meta: FuncMeta = self._ExtractFuncMeta(Node.decorator_list) if FuncMeta.PROPERTY_SETTER in func_meta: FuncName = FuncName + '$set' elif FuncMeta.PROPERTY_DELETER in func_meta: FuncName = FuncName + '$del' CReturnTypes: list[ast.AST] = [] if Node.decorator_list: for decorator in Node.decorator_list: if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute): if decorator.func.attr == 'CReturn': for arg in decorator.args: CReturnTypes.append(arg) if Node.returns: llvm_attrs: list[str] = self._ExtractLLVMAttrs(Node.returns) if llvm_attrs: if not hasattr(self, '_pending_llvm_attrs'): self._pending_llvm_attrs = {} self._pending_llvm_attrs[FuncName] = llvm_attrs if isinstance(Node.returns, ast.Subscript) and isinstance(Node.returns.value, ast.Name) and Node.returns.value.id == 'tuple': slice_node: ast.AST = Node.returns.slice if isinstance(slice_node, ast.Tuple): for elt in slice_node.elts: CReturnTypes.append(elt) else: CReturnTypes.append(slice_node) IsPtr: bool = False ReturnTypeInfo: Any = None if Node.returns: if CReturnTypes: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CVoid() else: try: if isinstance(Node.returns, ast.BinOp) and isinstance(Node.returns.op, ast.BitOr): ReturnTypeInfo = getattr(self.Trans, 'TypeMergeHandler', None) and self.Trans.TypeMergeHandler.MergeTypes(Node.returns) if not isinstance(ReturnTypeInfo, CTypeInfo): ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CVoid() if (ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState) or ReturnTypeInfo.PtrCount >= 2: def _FindNonVoidCTypeInfo(node: ast.AST) -> Any: if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): results: list[Any] = [] for child in [node.left, node.right]: r: Any = _FindNonVoidCTypeInfo(child) if r and not r.IsVoid: results.append(r) for r in results: if not r.IsPtr and not r.IsStruct: return r return results[0] if results else None try: SideInfo: Any = CTypeInfo.FromNode(node, self.Trans.SymbolTable) if SideInfo: return SideInfo except Exception as _e: if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") return None found: Any = _FindNonVoidCTypeInfo(Node.returns) if found and not found.IsVoid: ReturnTypeInfo = found if ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() else: is_str_type: bool = False if isinstance(Node.returns, ast.Name) and Node.returns.id in ('str', 'bytes'): is_str_type = True ReturnTypeInfo = CTypeInfo.FromNode(Node.returns, self.Trans.SymbolTable) if ReturnTypeInfo and ReturnTypeInfo.IsDefine: inferred: Any = self._infer_return_type_from_body(Node, Gen, ClassName) if inferred: ReturnTypeInfo = CTypeInfo.FromTypeName(inferred[0]) ReturnTypeInfo.PtrCount = 1 if inferred[1] else 0 else: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() if not hasattr(self, '_cdefine_funcs'): self._cdefine_funcs = set() self._cdefine_funcs.add(FuncName) elif ReturnTypeInfo and ReturnTypeInfo.IsState: if ReturnTypeInfo.PtrCount > 0 or (ReturnTypeInfo.BaseType and not isinstance(ReturnTypeInfo.BaseType, t.CVoid)): pass else: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CVoid() if ReturnTypeInfo is None: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CVoid() if is_str_type or ReturnTypeInfo.IsStr: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CChar() ReturnTypeInfo.PtrCount = 1 # 检查泛型类返回类型 (如 list[str]) # 注意:_from_node_subscript 对未识别的泛型下标(如 list[str])返回空 CTypeInfo(BaseType=None), # 此时 IsVoid 为 False(因为 IsVoid 仅检查 t.CVoid 实例),需额外检测 BaseType is None if (isinstance(Node.returns, ast.Subscript) and isinstance(Node.returns.value, ast.Name) and hasattr(self.Trans.ClassHandler, '_generic_class_templates') and Node.returns.value.id in self.Trans.ClassHandler._generic_class_templates and (ReturnTypeInfo.IsVoid or ReturnTypeInfo.BaseType is None) and ReturnTypeInfo.PtrCount == 0): ret_class: str = Node.returns.value.id ret_slice: ast.AST = Node.returns.slice ret_type_args: list[str] = [] ret_type_names: list[str] = [] if isinstance(ret_slice, ast.Tuple): for elt in ret_slice.elts: if isinstance(elt, ast.Name): tn2: str = elt.id ts2: str = tn2 if tn2 == 'int': ts2, tn2 = 'int', 'CInt' ret_type_args.append(ts2) ret_type_names.append(tn2) elif isinstance(ret_slice, ast.Name): tn2: str = ret_slice.id ts2: str = tn2 if tn2 == 'int': ts2, tn2 = 'int', 'CInt' ret_type_args.append(ts2) ret_type_names.append(tn2) spec_name2: str | None = self.Trans.ClassHandler._specialize_generic_class( ret_class, ret_type_args, Gen, type_names=ret_type_names) if spec_name2 and spec_name2 in Gen.structs: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CStruct(name=spec_name2) ReturnTypeInfo.PtrCount = 1 if (ReturnTypeInfo.IsVoid or ReturnTypeInfo.BaseType is None) and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() except Exception: # 回退:设置默认返回类型为 CInt ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() else: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() inferred: Any = self._infer_return_type_from_body(Node, Gen, ClassName) if inferred: ReturnTypeInfo = CTypeInfo.FromTypeName(inferred[0]) ReturnTypeInfo.PtrCount = 1 if inferred[1] else 0 IsPtr = ReturnTypeInfo.IsPtr if ReturnTypeInfo else False ReturnType: ir.Type = Gen._ctype_to_llvm(ReturnTypeInfo) if isinstance(ReturnType, ir.PointerType) and isinstance(ReturnType.pointee, ir.PointerType): if isinstance(ReturnType.pointee.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): ReturnType = ir.PointerType(ReturnType.pointee.pointee) if isinstance(ReturnType, ir.IntType) and ReturnType.width == 8: if RawFuncName == '__str__': ReturnType = ir.PointerType(ir.IntType(8)) if isinstance(ReturnType, ir.VoidType) and FuncName == 'main': ReturnType = ir.IntType(32) IsMethod: bool = False IsClassMethod: bool = False ResolvedClassName: str | None = ClassName func_meta = self._ExtractFuncMeta(Node.decorator_list) if not ResolvedClassName: for potential_class in Gen.class_methods: if FuncName.startswith(f"{potential_class}."): IsMethod = True ResolvedClassName = potential_class break else: IsMethod = FuncMeta.STATIC_METHOD not in func_meta and FuncMeta.CLASS_METHOD not in func_meta IsClassMethod = FuncMeta.CLASS_METHOD in func_meta if RawFuncName == '__init__': IsMethod = False ParamTypes: list[ir.Type] = [] ParamNames: list[str] = [] ParamTypeStrs: list[Any] = [] auto_addr_modes: list[str | None] = [] CReturnLlvmTypes: list[ir.Type] = [] if CReturnTypes: for i, ReturnTypeNode in enumerate(CReturnTypes): ReturnTypeInfo = CTypeInfo.FromNode(ReturnTypeNode, self.Trans.SymbolTable) if ReturnTypeInfo and ReturnTypeInfo.IsStr: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CChar() ReturnTypeInfo.PtrCount = 1 if ReturnTypeInfo is None: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() RetType: ir.Type = Gen._ctype_to_llvm(ReturnTypeInfo) CReturnLlvmTypes.append(RetType) ReturnType = ir.LiteralStructType(CReturnLlvmTypes) for Arg in Node.args.args: ParamIsUnsigned: bool = False if Arg.annotation: try: ParamTypeInfo: Any ParamTypeInfo = self.ResolveAnnotationType(Arg.annotation) if ParamTypeInfo is None: ParamTypeInfo = CTypeInfo() ParamTypeInfo.BaseType = t.CInt() IsPtr = ParamTypeInfo.IsPtr if ParamTypeInfo and getattr(ParamTypeInfo, 'IsCpythonObject', False) and not IsPtr: IsPtr = True ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1) if ParamTypeInfo.IsStr or (isinstance(Arg.annotation, ast.Name) and Arg.annotation.id in ('str', 'bytes')): ParamTypeInfo = CTypeInfo() ParamTypeInfo.BaseType = t.CChar() ParamTypeInfo.PtrCount = 1 IsPtr = True # C 语言中数组参数退化为指针:list[type, N] → type* if ParamTypeInfo.ArrayDims: ParamTypeInfo.ArrayDims = [] ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1) ParamType: ir.Type = Gen._ctype_to_llvm(ParamTypeInfo) ParamTypeStr: Any = ParamTypeInfo except Exception as e: ParamType = ir.IntType(32) ParamTypeStr = CTypeInfo() ParamTypeStr.BaseType = t.CInt() else: if ClassName and Arg.arg != 'self': op_method_names: list[str] = ['__add__', '__sub__', '__mul__', '__truediv__', '__floordiv__', '__mod__', '__pow__', '__radd__', '__rsub__', '__rmul__', '__rtruediv__', '__rfloordiv__', '__rmod__', '__rpow__', '__iadd__', '__isub__', '__imul__', '__itruediv__', '__ifloordiv__', '__imod__', '__ipow__', '__eq__', '__ne__', '__lt__', '__le__', '__gt__', '__ge__', '__neg__', '__pos__', '__abs__', '__call__'] if RawFuncName in op_method_names and ClassName in Gen.structs: ParamType = ir.PointerType(Gen.structs[ClassName]) else: ParamType = ir.IntType(32) else: ParamType = ir.IntType(32) ParamTypeStr = CTypeInfo() ParamTypeStr.BaseType = t.CInt() ParamTypes.append(ParamType) ParamNames.append(Arg.arg) ParamTypeStrs.append(ParamTypeStr) # 检测 t.CNeedPtr / t.CAutoPtr 参数注解 auto_mode: str | None = None if ParamTypeStr is not None and hasattr(ParamTypeStr, 'BaseType') and ParamTypeStr.BaseType is not None: if isinstance(ParamTypeStr.BaseType, t.CAutoPtr): auto_mode = 'always' elif isinstance(ParamTypeStr.BaseType, t.CNeedPtr): auto_mode = 'need' auto_addr_modes.append(auto_mode) if IsMethod and ResolvedClassName and ResolvedClassName in Gen.structs: StructPtrType: ir.PointerType = ir.PointerType(Gen.structs[ResolvedClassName]) SelfIdx: int = next((i for i, n in enumerate(ParamNames) if n == "self"), -1) if SelfIdx >= 0: ParamTypes[SelfIdx] = StructPtrType else: ParamTypes.insert(0, StructPtrType) ParamNames.insert(0, "self") ParamTypeStrs.insert(0, f"struct {ResolvedClassName}") elif not IsMethod and ResolvedClassName and ResolvedClassName in Gen.structs: SelfIdx: int = next((i for i, n in enumerate(ParamNames) if n == "self"), -1) if SelfIdx >= 0: StructPtrType: ir.PointerType = ir.PointerType(Gen.structs[ResolvedClassName]) ParamTypes[SelfIdx] = StructPtrType # @classmethod: 将 cls 参数设为类指针类型 if IsClassMethod: ClsIdx: int = next((i for i, n in enumerate(ParamNames) if n == "cls"), -1) if ClsIdx >= 0: StructPtrType: ir.PointerType = ir.PointerType(Gen.structs[ResolvedClassName]) ParamTypes[ClsIdx] = StructPtrType IsVariadic: bool = Node.args.vararg is not None if extra_params: for var_name, ptr_type in extra_params: ParamTypes.append(ptr_type) ParamNames.append(f'__nonlocal_{var_name}__') if IsMethod and RawFuncName == '__next__': ParamTypes.append(ir.PointerType(ir.IntType(1))) ParamNames.append('__stop_iter_flag__') HasRaise: bool = self._body_contains_raise(Node.body) if HasRaise and RawFuncName != 'main': ParamTypes.append(ir.PointerType(ir.PointerType(ir.IntType(8)))) ParamNames.append('__eh_msg_out__') ParamTypes.append(ir.PointerType(ir.IntType(32))) ParamNames.append('__eh_code_out__') FuncType: ir.FunctionType = ir.FunctionType(ReturnType, ParamTypes, var_arg=IsVariadic) # 存储 auto_addr_modes(为额外参数补 None) total_params: int = len(ParamTypes) while len(auto_addr_modes) < total_params: auto_addr_modes.append(None) Gen._auto_addr_params[FuncName] = auto_addr_modes return FuncName, FuncType, ReturnTypeInfo, ParamTypeStrs, CReturnTypes, IsMethod, ResolvedClassName, IsVariadic def _is_generic_function(self, Node: ast.FunctionDef) -> bool: if hasattr(Node, 'type_params') and Node.type_params: return True return False def _mangle_generic_name(self, func_name: str, type_args: list[str], has_cexport: bool = False) -> str: mangled_args: list[str] = [] for ta in type_args: llvm_str: str | None = CTypeRegistry.NameToLLVM(ta) if llvm_str: if llvm_str in ('float', 'double', 'half', 'fp128'): mangled: str = 'f' + str(CTypeRegistry.GetClassByName(ta)().Size) else: mangled = llvm_str else: mangled = ta mangled_args.append(mangled) if has_cexport: return func_name + '_T_' + '_'.join(mangled_args) return func_name + '[' + ']['.join(mangled_args) + ']' def _apply_type_map_to_node(self, Node: ast.FunctionDef, type_map: dict[str, str]) -> None: for arg in Node.args.args: if arg.annotation: arg.annotation = self._replace_type_in_annotation(arg.annotation, type_map) if Node.returns: Node.returns = self._replace_type_in_annotation(Node.returns, type_map) self._apply_type_map_to_body(Node.body, type_map) def _replace_type_in_annotation(self, node: ast.AST, type_map: dict[str, str]) -> ast.AST: if isinstance(node, ast.Name): if node.id in type_map: replacement: str = type_map[node.id] return ast.Name(id=replacement, ctx=ast.Load()) elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): node.left = self._replace_type_in_annotation(node.left, type_map) node.right = self._replace_type_in_annotation(node.right, type_map) elif isinstance(node, ast.Attribute): if hasattr(node, 'attr') and node.attr in type_map: replacement: str = type_map[node.attr] return ast.Name(id=replacement, ctx=ast.Load()) return node def _apply_type_map_to_body(self, body: list[ast.AST], type_map: dict[str, str]) -> None: for stmt in body: self._apply_type_map_to_stmt(stmt, type_map) def _apply_type_map_to_stmt(self, node: ast.AST, type_map: dict[str, str]) -> None: if isinstance(node, ast.Return) and node.value: self._apply_type_map_to_expr(node.value, type_map) elif isinstance(node, ast.Assign): for t in node.targets: self._apply_type_map_to_expr(t, type_map) self._apply_type_map_to_expr(node.value, type_map) elif isinstance(node, ast.AnnAssign): if node.annotation: node.annotation = self._replace_type_in_annotation(node.annotation, type_map) if node.value: self._apply_type_map_to_expr(node.value, type_map) elif isinstance(node, ast.AugAssign): self._apply_type_map_to_expr(node.target, type_map) self._apply_type_map_to_expr(node.value, type_map) elif isinstance(node, ast.Expr): self._apply_type_map_to_expr(node.value, type_map) elif isinstance(node, ast.If): self._apply_type_map_to_expr(node.test, type_map) for s in node.body: self._apply_type_map_to_stmt(s, type_map) for s in node.orelse: self._apply_type_map_to_stmt(s, type_map) elif isinstance(node, ast.For): self._apply_type_map_to_expr(node.iter, type_map) for s in node.body: self._apply_type_map_to_stmt(s, type_map) elif isinstance(node, ast.While): self._apply_type_map_to_expr(node.test, type_map) for s in node.body: self._apply_type_map_to_stmt(s, type_map) def _apply_type_map_to_expr(self, node: ast.AST | None, type_map: dict[str, str]) -> None: if node is None: return if isinstance(node, ast.Call): if isinstance(node.func, ast.Name) and node.func.id in type_map: replacement: str = type_map[node.func.id] node.func = ast.Name(id=replacement, ctx=ast.Load()) elif isinstance(node.func, ast.Attribute): if isinstance(node.func.value, ast.Name) and node.func.value.id in type_map: replacement: str = type_map[node.func.value.id] node.func.value = ast.Name(id=replacement, ctx=ast.Load()) for arg in node.args: self._apply_type_map_to_expr(arg, type_map) elif isinstance(node, ast.Attribute): if isinstance(node.value, ast.Name) and node.value.id in type_map: replacement: str = type_map[node.value.id] node.value = ast.Name(id=replacement, ctx=ast.Load()) elif isinstance(node, ast.BinOp): self._apply_type_map_to_expr(node.left, type_map) self._apply_type_map_to_expr(node.right, type_map) elif isinstance(node, ast.UnaryOp): self._apply_type_map_to_expr(node.operand, type_map) elif isinstance(node, ast.Compare): self._apply_type_map_to_expr(node.left, type_map) for comp in node.comparators: self._apply_type_map_to_expr(comp, type_map) elif isinstance(node, ast.BoolOp): for val in node.values: self._apply_type_map_to_expr(val, type_map) elif isinstance(node, ast.IfExp): self._apply_type_map_to_expr(node.test, type_map) self._apply_type_map_to_expr(node.body, type_map) self._apply_type_map_to_expr(node.orelse, type_map) elif isinstance(node, ast.Name): if node.id in type_map: node.id = type_map[node.id] def _infer_type_arg_from_value(self, val: ir.Value, Gen: LlvmCodeGenerator) -> str: if val is None: return 'int' if isinstance(val.type, ir.IntType): if val.type.width == 64: return 'i64' elif val.type.width == 16: return 'i16' elif val.type.width == 8: return 'i8' return 'int' elif isinstance(val.type, ir.DoubleType): return 'double' elif isinstance(val.type, ir.FloatType): return 'float' elif isinstance(val.type, ir.PointerType): return 'void*' return 'int' def _specialize_generic_function(self, FuncName: str, type_args: list[str], Gen: LlvmCodeGenerator) -> str | None: if not hasattr(self, '_generic_templates') or FuncName not in self._generic_templates: return None template: dict[str, Any] = self._generic_templates[FuncName] Node: ast.FunctionDef = template['node'] type_param_names: list[str] = template['type_params'] ClassName: str | None = template['class_name'] if len(type_args) != len(type_param_names): return None spec_key: str = FuncName + '<' + ','.join(type_args) + '>' if not hasattr(self, '_generic_specializations'): self._generic_specializations = {} if spec_key in self._generic_specializations: return self._generic_specializations[spec_key] has_cexport: bool = False if Node.returns: try: RetTypeInfo: Any = None if isinstance(Node.returns, ast.BinOp) and isinstance(Node.returns.op, ast.BitOr): RetTypeInfo = self.Trans.TypeMergeHandler.MergeTypes(Node.returns) else: RetTypeInfo = CTypeInfo.FromNode(Node.returns, self.Trans.SymbolTable) if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, t.CExport): has_cexport = True except Exception as _e: if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") spec_name: str = self._mangle_generic_name(FuncName, type_args, has_cexport) type_map: dict[str, str] = {} for i, tp_name in enumerate(type_param_names): type_map[tp_name] = type_args[i] SpecNode: ast.FunctionDef = copy.deepcopy(Node) SpecNode.type_params = [] SpecNode.name = spec_name self._apply_type_map_to_node(SpecNode, type_map) if has_cexport: if not hasattr(Gen, '_export_funcs'): Gen._export_funcs = set() Gen._export_funcs.add(spec_name) saved_builder: Any = Gen.builder saved_variables: dict[str, Any] = dict(Gen.variables) if Gen.variables else {} saved_direct_values: dict[str, Any] = dict(Gen._direct_values) if Gen._direct_values else {} saved_var_type_info: dict[str, Any] = dict(Gen.var_type_info) if Gen.var_type_info else {} saved_var_signedness: dict[str, Any] = dict(Gen.var_signedness) if Gen.var_signedness else {} saved_global_vars: set[str] = set(Gen.global_vars) if Gen.global_vars else set() saved_var_scopes: list[dict[str, Any]] = [dict(s) for s in self.Trans.VarScopes] if self.Trans.VarScopes else [] saved_func: Any = Gen.func saved_current_func_name: str | None = getattr(Gen, '_current_func_name', None) saved_block: Any = None if Gen.builder and Gen.builder.block and not Gen.builder.block.is_terminated: saved_block = Gen.builder.block self._EmitFunctionForwardDeclLlvm(SpecNode, Gen, ClassName=ClassName) self._EmitFunctionLlvm(SpecNode, Gen, ClassName=ClassName) Gen.builder = saved_builder if saved_block is not None and Gen.builder is not None: Gen.builder.position_at_end(saved_block) Gen.variables = saved_variables Gen._direct_values = saved_direct_values Gen.var_type_info = saved_var_type_info Gen.var_signedness = saved_var_signedness Gen.global_vars = saved_global_vars Gen.func = saved_func if saved_current_func_name is not None: Gen._current_func_name = saved_current_func_name self.Trans.VarScopes = saved_var_scopes self._generic_specializations[spec_key] = spec_name if not hasattr(self.Trans, '_generic_specializations'): self.Trans._generic_specializations = {} self.Trans._generic_specializations[spec_key] = spec_name return spec_name def _EmitFunctionForwardDeclLlvm(self, Node: ast.FunctionDef, Gen: LlvmCodeGenerator, ClassName: str | None = None) -> None: if self._is_generic_function(Node): if not hasattr(self, '_generic_templates'): self._generic_templates = {} RawFuncName: str = Node.name if ClassName: FuncName: str = f"{ClassName}.{RawFuncName}" else: FuncName = RawFuncName type_params: list[str] = [tp.name for tp in Node.type_params] self._generic_templates[FuncName] = { 'node': Node, 'type_params': type_params, 'class_name': ClassName, } return result: Any = self._GetFunctionSignatureLlvm(Node, Gen, ClassName) if result is None: return FuncName: str FuncType: ir.FunctionType ReturnTypeInfo: Any ParamTypeStrs: list[Any] CReturnTypes: list[ast.AST] IsMethod: bool ResolvedClassName: str | None IsVariadic: bool FuncName, FuncType, ReturnTypeInfo, ParamTypeStrs, CReturnTypes, IsMethod, ResolvedClassName, IsVariadic = result if Node.returns: try: RetTypeInfo: Any = None RetTypeInfo = self.ResolveAnnotationType(Node.returns) if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, t.CExport) and not RetTypeInfo.IsState: Gen._export_funcs.add(FuncName) if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, t.CExtern): Gen._export_funcs.add(FuncName) if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.IsState: Gen._export_funcs.add(FuncName) # t.State 标记的函数必须保持原始名称,以便链接器解析 except Exception as _e: if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") # 装饰器形式的存储类标记(@t.CExport / @t.CExtern / @t.State 等) deco_flags: dict[str, bool] = self._extract_decorator_storage_flags(Node) if deco_flags['is_export'] or deco_flags['is_extern'] or deco_flags['is_state']: Gen._export_funcs.add(FuncName) MangledName: str = Gen._mangle_func_name(FuncName) need_new: bool = MangledName not in Gen.functions if not need_new: existing: Any = Gen.functions[MangledName] if getattr(existing, 'name', MangledName) != MangledName: need_new = True if need_new: try: func: ir.Function = ir.Function(Gen.module, FuncType, name=MangledName) func.attributes.add('noredzone') if hasattr(self, '_cdefine_funcs') and FuncName in self._cdefine_funcs: func.linkage = 'linkonce_odr' func.attributes.add('alwaysinline') if hasattr(self, '_pending_llvm_attrs') and FuncName in self._pending_llvm_attrs: for attr_name in self._pending_llvm_attrs[FuncName]: try: func.attributes.add(attr_name) except Exception as _e: if _config_mode == "strict": raise _vlog().warning(f"添加函数属性失败: {_e}", "Exception") Gen.functions[MangledName] = func Gen.functions[FuncName] = func except Exception as _e: if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") else: existing = Gen.functions[MangledName] existing_type: ir.FunctionType | None = getattr(existing, 'ftype', None) if existing_type and existing_type != FuncType: Gen.functions[MangledName] = self._replace_function_decl(Gen, FuncName, FuncType) Gen.functions[FuncName] = Gen.functions[MangledName] elif not existing_type: try: Gen.functions[MangledName] = self._replace_function_decl(Gen, FuncName, FuncType) Gen.functions[FuncName] = Gen.functions[MangledName] except Exception as _e: if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") self.Trans.FunctionDefCache[FuncName] = Node def _replace_function_decl(self, Gen: LlvmCodeGenerator, FuncName: str, NewFuncType: ir.FunctionType) -> ir.Function: MangledName: str = Gen._mangle_func_name(FuncName) old_func: Any = Gen.functions.get(MangledName) if old_func is None: try: return ir.Function(Gen.module, NewFuncType, name=MangledName) except Exception: # 回退:函数已存在时返回旧函数 return old_func try: old_name: str = old_func.name if old_name in getattr(Gen.module, 'globals', {}): del Gen.module.globals[old_name] module_scope: Any = getattr(Gen.module, 'scope', None) if getattr(module_scope, '_useset', None): module_scope._useset.discard(old_name) if getattr(Gen.module, '_guessed_names', None): Gen.module._guessed_names.discard(FuncName) new_func: ir.Function = ir.Function(Gen.module, NewFuncType, name=MangledName) Gen.functions[MangledName] = new_func Gen.functions[FuncName] = new_func return new_func except Exception as ex: traceback.print_exc() Gen.functions[MangledName] = old_func Gen.functions[FuncName] = old_func return old_func def _EmitFunctionLlvm(self, Node: ast.FunctionDef, Gen: LlvmCodeGenerator, ClassName: str | None = None, extra_params: list[tuple[str, ir.Type]] | None = None) -> ir.Function | None: if self._is_generic_function(Node): return RawFuncName = Node.name if ClassName: FuncName = f"{ClassName}.{RawFuncName}" else: FuncName = RawFuncName # property setter/deleter 使用不同的函数名后缀,避免与 getter 冲突 func_meta = self._ExtractFuncMeta(Node.decorator_list) if FuncMeta.PROPERTY_SETTER in func_meta: FuncName = FuncName + '$set' elif FuncMeta.PROPERTY_DELETER in func_meta: FuncName = FuncName + '$del' CReturnTypes = [] IsPtr = False fn_attrs = {} # 自定义行为装饰器列表,用于生成 wrapper 函数 # 任何 @name 或 @name(args) 只要不是内置装饰器,都视为自定义行为装饰器 behavior_decorators = [] # 内置装饰器名称,这些由编译器特殊处理,不作为行为装饰器 _BUILTIN_DECORATORS = {'staticmethod', 'property', 'classmethod'} _symtab: object = self.Trans.SymbolTable if Node.decorator_list: for decorator in Node.decorator_list: # 跳过 t 模块存储类标记装饰器(@t.CExport / @CExport 等) if self._is_t_storage_decorator(decorator, _symtab): continue # 识别自定义行为装饰器:@name(ast.Name 形式) if isinstance(decorator, ast.Name): if decorator.id not in _BUILTIN_DECORATORS: behavior_decorators.append({'name': decorator.id, 'args': [], 'kwargs': {}}) continue # 识别带参数的自定义行为装饰器:@name(arg1, key=val)(ast.Call + ast.Name 形式) if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Name): deco_name = decorator.func.id if deco_name not in _BUILTIN_DECORATORS: deco_info = {'name': deco_name, 'args': [], 'kwargs': {}} for arg in decorator.args: if isinstance(arg, ast.Constant): deco_info['args'].append(arg.value) for kw in decorator.keywords: if isinstance(kw.value, ast.Constant): deco_info['kwargs'][kw.arg] = kw.value.value behavior_decorators.append(deco_info) continue if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute): if decorator.func.attr == 'CReturn': for arg in decorator.args: CReturnTypes.append(arg) elif decorator.func.attr == 'Attribute' and isinstance(decorator.func.value, ast.Name) and decorator.func.value.id == 'c': for arg in decorator.args: if isinstance(arg, ast.Call) and isinstance(arg.func, ast.Attribute): if isinstance(arg.func.value, ast.Attribute) and isinstance(arg.func.value.value, ast.Name) and IsTModule(arg.func.value.value.id, self.Trans.SymbolTable) and arg.func.value.attr == 'attr': attr_name = arg.func.attr str_args = [a.value for a in arg.args if isinstance(a, ast.Constant) and isinstance(a.value, str)] int_args = [a.value for a in arg.args if isinstance(a, ast.Constant) and isinstance(a.value, int)] if attr_name == 'section' and str_args: fn_attrs['section'] = str_args[0] elif attr_name == 'aligned' and int_args: fn_attrs['aligned'] = int_args[0] elif attr_name == 'visibility' and str_args: fn_attrs['visibility'] = str_args[0] elif attr_name in ('noreturn', 'always_inline', 'noinline', 'cold', 'hot', 'constructor', 'destructor', 'pure', 'const', 'malloc', 'returns_nonnull', 'used', 'naked', 'no_instrument_function', 'warn_unused_result', 'weak', 'fallthrough'): if not arg.args: fn_attrs[attr_name] = True elif isinstance(arg.func.value, ast.Attribute) and arg.func.value.attr == 'llvm' and isinstance(arg.func.value.value, ast.Attribute) and arg.func.value.value.attr == 'attr' and isinstance(arg.func.value.value.value, ast.Name) and IsTModule(arg.func.value.value.value.id, self.Trans.SymbolTable): llvm_attr_name = arg.func.attr if llvm_attr_name in self._LLVM_ATTR_NAMES: fn_attrs[f'llvm.{llvm_attr_name}'] = True elif isinstance(arg, ast.Attribute): if isinstance(arg.value, ast.Attribute) and isinstance(arg.value.value, ast.Name) and IsTModule(arg.value.value.id, self.Trans.SymbolTable) and arg.value.attr == 'attr': attr_name = arg.attr if attr_name in ('noreturn', 'always_inline', 'noinline', 'cold', 'hot', 'constructor', 'destructor', 'pure', 'const', 'malloc', 'returns_nonnull', 'used', 'naked', 'no_instrument_function', 'warn_unused_result', 'weak', 'fallthrough', 'packed'): fn_attrs[attr_name] = True elif isinstance(arg.value, ast.Attribute) and arg.value.attr == 'llvm' and isinstance(arg.value.value, ast.Attribute) and arg.value.value.attr == 'attr' and isinstance(arg.value.value.value, ast.Name) and IsTModule(arg.value.value.value.id, self.Trans.SymbolTable): llvm_attr_name = arg.attr if llvm_attr_name in self._LLVM_ATTR_NAMES: fn_attrs[f'llvm.{llvm_attr_name}'] = True # 检查 @t.TLS 装饰器(一次性初始化标记) is_tls_func: bool = False if Node.decorator_list: for decorator in Node.decorator_list: if isinstance(decorator, ast.Attribute) and isinstance(decorator.value, ast.Name): if IsTModule(decorator.value.id, _symtab) and decorator.attr == 'TLS': is_tls_func = True break elif isinstance(decorator, ast.Name) and decorator.id == 'TLS' and hasattr(t, 'TLS'): is_tls_func = True break if Node.returns: if isinstance(Node.returns, ast.Subscript) and isinstance(Node.returns.value, ast.Name) and Node.returns.value.id == 'tuple': slice_node = Node.returns.slice if isinstance(slice_node, ast.Tuple): for elt in slice_node.elts: CReturnTypes.append(elt) else: CReturnTypes.append(slice_node) # 先强制检查 str 类型注解 is_str_return = False ReturnTypeInfo = None if Node.returns: if isinstance(Node.returns, ast.Name) and Node.returns.id in ('str', 'bytes'): is_str_return = True else: try: rt_info = CTypeInfo.FromNode(Node.returns, self.Trans.SymbolTable) if rt_info and rt_info.IsStr: is_str_return = True except Exception as _e: if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") if is_str_return: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CChar() ReturnTypeInfo.PtrCount = 1 elif Node.returns: if CReturnTypes: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CVoid() else: try: if isinstance(Node.returns, ast.BinOp) and isinstance(Node.returns.op, ast.BitOr): ReturnTypeInfo = getattr(self.Trans, 'TypeMergeHandler', None) and self.Trans.TypeMergeHandler.MergeTypes(Node.returns) if not isinstance(ReturnTypeInfo, CTypeInfo): ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CVoid() if (ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState) or ReturnTypeInfo.PtrCount >= 2: def _FindNonVoidCTypeInfo(node): if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): results = [] for child in [node.left, node.right]: r = _FindNonVoidCTypeInfo(child) if r and not r.IsVoid: results.append(r) for r in results: if not r.IsPtr and not r.IsStruct: return r return results[0] if results else None try: SideInfo = CTypeInfo.FromNode(node, self.Trans.SymbolTable) if SideInfo: return SideInfo except Exception as _e: if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") return None found = _FindNonVoidCTypeInfo(Node.returns) if found and not found.IsVoid: ReturnTypeInfo = found if ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() else: is_str_type = False if isinstance(Node.returns, ast.Name) and Node.returns.id in ('str', 'bytes'): is_str_type = True ReturnTypeInfo = CTypeInfo.FromNode(Node.returns, self.Trans.SymbolTable) if ReturnTypeInfo and ReturnTypeInfo.IsDefine: inferred = self._infer_return_type_from_body(Node, Gen, ClassName) if inferred: ReturnTypeInfo = CTypeInfo.FromTypeName(inferred[0]) ReturnTypeInfo.PtrCount = 1 if inferred[1] else 0 else: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() if not hasattr(self, '_cdefine_funcs'): self._cdefine_funcs = set() self._cdefine_funcs.add(FuncName) elif ReturnTypeInfo and ReturnTypeInfo.IsState: pass # t.State is a modifier, preserve the actual return type if ReturnTypeInfo is None: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CVoid() if is_str_type or ReturnTypeInfo.IsStr: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CChar() ReturnTypeInfo.PtrCount = 1 # 检查泛型类返回类型 (如 list[str]) # 注意:_from_node_subscript 对未识别的泛型下标(如 list[str])返回空 CTypeInfo(BaseType=None), # 此时 IsVoid 为 False(因为 IsVoid 仅检查 t.CVoid 实例),需额外检测 BaseType is None if (isinstance(Node.returns, ast.Subscript) and isinstance(Node.returns.value, ast.Name) and hasattr(self.Trans.ClassHandler, '_generic_class_templates') and Node.returns.value.id in self.Trans.ClassHandler._generic_class_templates and (ReturnTypeInfo.IsVoid or ReturnTypeInfo.BaseType is None) and ReturnTypeInfo.PtrCount == 0): ret_class: str = Node.returns.value.id ret_slice: ast.AST = Node.returns.slice ret_type_args: list[str] = [] ret_type_names: list[str] = [] if isinstance(ret_slice, ast.Tuple): for elt in ret_slice.elts: if isinstance(elt, ast.Name): tn2: str = elt.id ts2: str = tn2 if tn2 == 'int': ts2, tn2 = 'int', 'CInt' ret_type_args.append(ts2) ret_type_names.append(tn2) elif isinstance(ret_slice, ast.Name): tn2: str = ret_slice.id ts2: str = tn2 if tn2 == 'int': ts2, tn2 = 'int', 'CInt' ret_type_args.append(ts2) ret_type_names.append(tn2) spec_name2: str | None = self.Trans.ClassHandler._specialize_generic_class( ret_class, ret_type_args, Gen, type_names=ret_type_names) if spec_name2 and spec_name2 in Gen.structs: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CStruct(name=spec_name2) ReturnTypeInfo.PtrCount = 1 if (ReturnTypeInfo.IsVoid or ReturnTypeInfo.BaseType is None) and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() except Exception: # 回退:设置默认返回类型为 CInt ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() else: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() inferred = self._infer_return_type_from_body(Node, Gen, ClassName) if inferred: ReturnTypeInfo = CTypeInfo.FromTypeName(inferred[0]) ReturnTypeInfo.PtrCount = 1 if inferred[1] else 0 ReturnType = Gen._ctype_to_llvm(ReturnTypeInfo) if isinstance(ReturnType, ir.VoidType) and FuncName == 'main': ReturnType = ir.IntType(32) IsMethod = False IsClassMethod = False ResolvedClassName = ClassName # func_meta 已在函数开头提取(用于 setter/deleter 函数名后缀) if not ResolvedClassName: for potential_class in Gen.class_methods: if FuncName.startswith(f"{potential_class}."): IsMethod = True ResolvedClassName = potential_class break else: IsMethod = FuncMeta.STATIC_METHOD not in func_meta and FuncMeta.CLASS_METHOD not in func_meta IsClassMethod = FuncMeta.CLASS_METHOD in func_meta if RawFuncName == '__init__': IsMethod = False # __new__ methods should return a pointer to the struct (for heap allocation replacement) if RawFuncName == '__new__' and ResolvedClassName: StructType = Gen.structs.get(ResolvedClassName) if StructType: if isinstance(StructType, ir.PointerType): ReturnType = StructType else: ReturnType = ir.PointerType(StructType) ParamTypes = [] ParamNames = [] ParamTypeStrs = [] auto_addr_modes_emit: list[str | None] = [] self.Trans.VarScopes.append({}) for Arg in Node.args.args: ParamIsUnsigned = False if Arg.annotation: try: ParamTypeInfo = self.ResolveAnnotationType(Arg.annotation) if ParamTypeInfo is None: ParamTypeInfo = CTypeInfo() ParamTypeInfo.BaseType = t.CInt() IsPtr = ParamTypeInfo.IsPtr if ParamTypeInfo and getattr(ParamTypeInfo, 'IsCpythonObject', False) and not IsPtr: IsPtr = True ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1) if ParamTypeInfo.IsStr or (isinstance(Arg.annotation, ast.Name) and Arg.annotation.id in ('str', 'bytes')): ParamTypeInfo = CTypeInfo() ParamTypeInfo.BaseType = t.CChar() ParamTypeInfo.PtrCount = 1 IsPtr = True # C 语言中数组参数退化为指针:list[type, N] → type* if ParamTypeInfo.ArrayDims: ParamTypeInfo.ArrayDims = [] ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1) ParamType = Gen._ctype_to_llvm(ParamTypeInfo) if ParamTypeInfo and ParamTypeInfo.IsFuncPtr: ParamType = ir.IntType(8).as_pointer() ParamIsUnsigned = ParamTypeInfo.IsUInt except Exception: # 回退:参数类型解析失败时使用默认 i32 ParamType = ir.IntType(32) ParamTypeInfo = CTypeInfo() ParamTypeInfo.BaseType = t.CInt() else: ParamType = ir.IntType(32) ParamTypeInfo = CTypeInfo() ParamTypeInfo.BaseType = t.CInt() ParamTypes.append(ParamType) ParamNames.append(Arg.arg) ParamTypeStrs.append(ParamTypeInfo) # 检测 t.CNeedPtr / t.CAutoPtr 参数注解 auto_mode_emit: str | None = None if ParamTypeInfo is not None and hasattr(ParamTypeInfo, 'BaseType') and ParamTypeInfo.BaseType is not None: if isinstance(ParamTypeInfo.BaseType, t.CAutoPtr): auto_mode_emit = 'always' elif isinstance(ParamTypeInfo.BaseType, t.CNeedPtr): auto_mode_emit = 'need' auto_addr_modes_emit.append(auto_mode_emit) Gen._record_var_signedness(Arg.arg, ParamIsUnsigned) self.Trans.VarScopes[-1][Arg.arg] = ParamTypeInfo if Arg.annotation: try: PInfo = self.ResolveAnnotationType(Arg.annotation) if PInfo and (PInfo.DataConst or PInfo.VarConst): Gen.var_const_flags[Arg.arg] = True except Exception as _e: if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") if CReturnTypes: CReturnLlvmTypes = [] for i, ReturnTypeNode in enumerate(CReturnTypes): ReturnTypeInfo = CTypeInfo.FromNode(ReturnTypeNode, self.Trans.SymbolTable) if ReturnTypeInfo and ReturnTypeInfo.IsStr: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CChar() ReturnTypeInfo.PtrCount = 1 if ReturnTypeInfo is None: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() RetType = Gen._ctype_to_llvm(ReturnTypeInfo) CReturnLlvmTypes.append(RetType) ReturnType = ir.LiteralStructType(CReturnLlvmTypes) self.Trans.CurrentCReturnTypes = CReturnTypes else: self.Trans.CurrentCReturnTypes = None if IsMethod and ResolvedClassName and ResolvedClassName in Gen.structs: StructPtrType = ir.PointerType(Gen.structs[ResolvedClassName]) SelfIdx = next((i for i, n in enumerate(ParamNames) if n == "self"), -1) if SelfIdx >= 0: ParamTypes[SelfIdx] = StructPtrType else: ParamTypes.insert(0, StructPtrType) ParamNames.insert(0, "self") elif not IsMethod and ResolvedClassName and ResolvedClassName in Gen.structs: SelfIdx = next((i for i, n in enumerate(ParamNames) if n == "self"), -1) if SelfIdx >= 0: StructPtrType = ir.PointerType(Gen.structs[ResolvedClassName]) ParamTypes[SelfIdx] = StructPtrType # @classmethod: 将 cls 参数设为类指针类型 if IsClassMethod: ClsIdx = next((i for i, n in enumerate(ParamNames) if n == "cls"), -1) if ClsIdx >= 0: StructPtrType = ir.PointerType(Gen.structs[ResolvedClassName]) ParamTypes[ClsIdx] = StructPtrType IsVariadic = Node.args.vararg is not None if extra_params: for var_name, ptr_type in extra_params: ParamTypes.append(ptr_type) ParamNames.append(f'__nonlocal_{var_name}__') HasStopIterFlag = False if IsMethod and RawFuncName == '__next__': ParamTypes.append(ir.PointerType(ir.IntType(1))) ParamNames.append('__stop_iter_flag__') HasStopIterFlag = True HasRaise = self._body_contains_raise(Node.body) if HasRaise and RawFuncName != 'main': ParamTypes.append(ir.PointerType(ir.PointerType(ir.IntType(8)))) ParamNames.append('__eh_msg_out__') ParamTypes.append(ir.PointerType(ir.IntType(32))) ParamNames.append('__eh_code_out__') FuncType = ir.FunctionType(ReturnType, ParamTypes, var_arg=IsVariadic) # 存储 auto_addr_modes(为额外参数补 None) total_params_emit: int = len(ParamTypes) while len(auto_addr_modes_emit) < total_params_emit: auto_addr_modes_emit.append(None) Gen._auto_addr_params[FuncName] = auto_addr_modes_emit self.Trans.FunctionDefCache[FuncName] = Node IsInlineFunc = False IsExternFunc = False IsStateFunc = False if Node.returns: try: RetTypeInfo = None RetTypeInfo = self.ResolveAnnotationType(Node.returns) if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, t.CInline): IsInlineFunc = True if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, t.CExport) and not RetTypeInfo.IsState: Gen._export_funcs.add(FuncName) if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, t.CExtern): IsExternFunc = True Gen._export_funcs.add(FuncName) if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.IsState: IsStateFunc = True Gen._export_funcs.add(FuncName) # 外部 C 函数声明必须保持原始名称 except Exception as _e: if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") # 装饰器形式的存储类标记(@t.CExport / @t.CExtern / @t.CStatic / @t.State / @t.CInline) deco_flags: dict[str, bool] = self._extract_decorator_storage_flags(Node) if deco_flags['is_inline']: IsInlineFunc = True if deco_flags['is_extern']: IsExternFunc = True if deco_flags['is_state']: IsStateFunc = True if deco_flags['is_export'] or deco_flags['is_extern'] or deco_flags['is_state']: Gen._export_funcs.add(FuncName) MangledName = Gen._mangle_func_name(FuncName) if MangledName in Gen.functions: func = Gen.functions[MangledName] if getattr(func, 'name', MangledName) != MangledName: func = ir.Function(Gen.module, FuncType, name=MangledName) Gen.functions[MangledName] = func else: existing_type = getattr(func, 'ftype', None) if existing_type and existing_type != FuncType: func = self._replace_function_decl(Gen, FuncName, FuncType) else: func = ir.Function(Gen.module, FuncType, name=MangledName) Gen.functions[MangledName] = func Gen.functions[FuncName] = func func.attributes.add('noredzone') if IsInlineFunc: func.linkage = 'linkonce_odr' func.attributes.add('alwaysinline') if hasattr(self, '_cdefine_funcs') and FuncName in self._cdefine_funcs: func.linkage = 'linkonce_odr' func.attributes.add('alwaysinline') if fn_attrs: _LLVM_FN_ATTR_MAP = { 'noreturn': 'noreturn', 'always_inline': 'alwaysinline', 'noinline': 'noinline', 'cold': 'cold', 'hot': 'hot', 'constructor': 'constructor', 'destructor': 'destructor', 'malloc': 'malloc', 'returns_nonnull': 'returns_nonnull', 'used': 'used', 'naked': 'naked', 'no_instrument_function': 'no_instrument_function', 'warn_unused_result': 'warn_unused_result', 'fallthrough': 'fallthrough', 'pure': 'readonly', 'const': 'readnone', } if 'section' in fn_attrs: func.section = fn_attrs['section'] if 'visibility' in fn_attrs: func.linkage = 'internal' func.attributes.add('visibility') if fn_attrs.get('weak'): func.linkage = 'weak' for attr_name, llvm_name in _LLVM_FN_ATTR_MAP.items(): if fn_attrs.get(attr_name): try: func.attributes.add(llvm_name) except Exception as _e: if _config_mode == "strict": raise _vlog().warning(f"添加函数属性失败: {_e}", "Exception") for key in fn_attrs: if key.startswith('llvm.'): llvm_attr_name = key[5:] try: func.attributes.add(llvm_attr_name) except Exception as _e: if _config_mode == "strict": raise _vlog().warning(f"添加函数属性失败: {_e}", "Exception") if hasattr(self, '_pending_llvm_attrs') and FuncName in self._pending_llvm_attrs: for attr_name in self._pending_llvm_attrs.pop(FuncName): try: func.attributes.add(attr_name) except Exception as _e: if _config_mode == "strict": raise _vlog().warning(f"添加函数属性失败: {_e}", "Exception") # 记录自定义行为装饰器信息,供 DecoratorPass 使用 if behavior_decorators: if not hasattr(Gen, '_decorated_funcs'): Gen._decorated_funcs = {} Gen._decorated_funcs[MangledName] = { 'decorators': behavior_decorators, 'func_name': FuncName, 'func_type': FuncType, 'return_type': FuncType.return_type, 'param_types': [p.type for p in func.args], 'param_names': ParamNames, 'is_export': FuncName in Gen._export_funcs, } if IsExternFunc or IsStateFunc: return EntryBlock = func.append_basic_block(name="entry") Gen.builder = ir.IRBuilder(EntryBlock) Gen.func = func Gen.variables = {} Gen._reg_values = {} Gen.global_vars = set() if 'aligned' in fn_attrs: Gen._emit_stack_align(fn_attrs['aligned']) # 保存当前的 var_type_info,以便函数结束时恢复 saved_var_type_info = Gen.var_type_info.copy() saved_var_type_assignments = Gen.var_type_assignments.copy() # 函数内部定义的变量会在赋值时添加到 var_type_info 中 # 这样函数内部定义的元类型变量(如 a = t.CInt32T)就能被正确处理 for stmt in Node.body: if isinstance(stmt, ast.Global): self.Trans.ForHandler._RegisterGlobalNames(stmt.names, Gen) for param, param_name in zip(func.args, ParamNames): param.name = param_name if param_name == '__stop_iter_flag__': Gen._stop_iter_flag_param = param Gen.builder.store(ir.Constant(ir.IntType(1), 0), param) elif param_name.startswith('__nonlocal_') and param_name.endswith('__'): var_name = param_name[len('__nonlocal_'):-2] Gen.variables[var_name] = param else: if isinstance(param.type, ir.PointerType) and isinstance(param.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): var = Gen.builder.alloca(param.type, name=param_name) Gen._store(param, var) Gen.variables[param_name] = var for CN, ST in Gen.structs.items(): if param.type.pointee == ST or (isinstance(param.type.pointee, ir.IdentifiedStructType) and isinstance(ST, ir.IdentifiedStructType) and param.type.pointee.name == ST.name): Gen.var_struct_class[param_name] = CN break elif isinstance(param.type, (ir.LiteralStructType, ir.IdentifiedStructType)): var = Gen.builder.alloca(param.type, name=param_name) Gen._store(param, var) Gen.variables[param_name] = var for CN, ST in Gen.structs.items(): if param.type == ST or (isinstance(param.type, ir.IdentifiedStructType) and isinstance(ST, ir.IdentifiedStructType) and param.type.name == ST.name): Gen.var_struct_class[param_name] = CN break else: # 所有参数都存入 alloca,确保循环体中对参数的修改能正确反映 var = Gen._allocaEntry(param.type, name=param_name) Gen._store(param, var) Gen.variables[param_name] = var if ResolvedClassName and (IsMethod or RawFuncName == '__init__'): self.Trans._CurrentCpythonObjectClass = ResolvedClassName Gen._variadic_info = None if IsVariadic and Node.args.vararg: vararg_name = getattr(Node.args.vararg, 'arg', 'args') last_param_name = ParamNames[-1] if ParamNames else None last_param_ptr = None for param, pn in zip(func.args, ParamNames): if pn == last_param_name: last_param_ptr = param break triple = getattr(Gen, 'module_triple', '') or getattr(Gen.module, 'triple', '') is_windows = 'windows' in triple if triple else False ptr_size = getattr(Gen, 'ptr_size', 8) # va_list 大小取决于 ABI:Windows x64 = 1个指针,Linux x64 = __va_list_tag[1](24字节) # 32位平台:Windows = 4字节指针,Linux = 12字节 if ptr_size == 4: va_list_size = 4 if is_windows else 12 va_list_align = 4 else: va_list_size = 8 if is_windows else 24 va_list_align = 8 if is_windows else 16 va_list_type = ir.ArrayType(ir.IntType(8), va_list_size) va_list_alloc = Gen._allocaEntry(va_list_type, name=f"{vararg_name}_va_list", align=va_list_align) va_list_ptr = Gen.builder.bitcast(va_list_alloc, ir.IntType(8).as_pointer(), name=f"{vararg_name}_va_list_i8ptr") Gen._variadic_info = { 'vararg_name': vararg_name, 'va_list_ptr': va_list_ptr, 'last_param_ptr': last_param_ptr, 'va_start_called': False, } if last_param_ptr: last_param_alloc = Gen._allocaEntry(last_param_ptr.type, name="last_param_copy") Gen.builder.store(last_param_ptr, last_param_alloc) Gen.emit_va_start(va_list_ptr) Gen._variadic_info['va_start_called'] = True Gen.variables[vararg_name] = va_list_ptr # @t.TLS 一次性初始化检查:首次调用执行函数体,后续调用直接返回 if is_tls_func: flag_name: str = f"__tls_init_done_{FuncName}" flag_global = None for gv in Gen.module.global_values: if gv.name == flag_name: flag_global = gv break if flag_global is None: flag_global = ir.GlobalVariable(Gen.module, ir.IntType(1), name=flag_name) flag_global.initializer = ir.Constant(ir.IntType(1), 0) flag_global.linkage = 'internal' flag_val = Gen.builder.load(flag_global, name="tls_flag_check") skip_bb = func.append_basic_block("tls_skip") cont_bb = func.append_basic_block("tls_continue") Gen.builder.cbranch(flag_val, skip_bb, cont_bb) Gen.builder.position_at_end(skip_bb) ActualReturnType = func.function_type.return_type if isinstance(ActualReturnType, ir.VoidType): Gen.builder.ret_void() elif isinstance(ActualReturnType, ir.IntType): Gen.builder.ret(ir.Constant(ActualReturnType, 0)) elif isinstance(ActualReturnType, (ir.FloatType, ir.DoubleType)): Gen.builder.ret(ir.Constant(ActualReturnType, 0.0)) elif isinstance(ActualReturnType, ir.PointerType): Gen.builder.ret(ir.Constant(ActualReturnType, None)) else: Gen.builder.ret(ir.Constant(ActualReturnType, None)) Gen.builder.position_at_end(cont_bb) Gen.builder.store(ir.Constant(ir.IntType(1), 1), flag_global) _saved_class_name = getattr(Gen, '_current_class_name', None) Gen._current_class_name = ClassName self.Trans.BodyHandler.HandleBodyLlvm(Node.body) if not Gen.builder.block.is_terminated: if 'naked' in fn_attrs: Gen.builder.unreachable() return Gen._emit_local_heap_frees() if Gen._variadic_info and Gen._variadic_info.get('va_start_called'): va_list_ptr = Gen._variadic_info.get('va_list_ptr') if va_list_ptr: Gen.emit_va_end(va_list_ptr) ActualReturnType = func.function_type.return_type if isinstance(ActualReturnType, ir.VoidType): Gen.builder.ret_void() elif isinstance(ActualReturnType, ir.IntType): Gen.builder.ret(ir.Constant(ActualReturnType, 0)) elif isinstance(ActualReturnType, (ir.FloatType, ir.DoubleType)): Gen.builder.ret(ir.Constant(ActualReturnType, 0.0)) elif isinstance(ActualReturnType, ir.PointerType): Gen.builder.ret(ir.Constant(ActualReturnType, None)) elif isinstance(ActualReturnType, ir.IdentifiedStructType): if ActualReturnType.elements: zero_val = ir.Constant(ActualReturnType, [ir.Constant(et, None) if isinstance(et, (ir.PointerType, ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)) else ir.Constant(et, 0) if isinstance(et, (ir.IntType, ir.FloatType, ir.DoubleType)) else ir.Constant(et, ir.Undefined) for et in ActualReturnType.elements]) else: zero_val = ir.Constant(ActualReturnType, None) Gen.builder.ret(zero_val) elif isinstance(ActualReturnType, ir.ArrayType): Gen.builder.ret(ir.Constant(ActualReturnType, None)) else: Gen.builder.ret_void() Gen.builder = None Gen.func = None Gen._current_class_name = _saved_class_name Gen.variables = {} Gen.var_signedness = {} Gen._reg_values = {} Gen._direct_values = {} Gen.var_struct_class = {} Gen.var_ptr_element = {} Gen.var_const_flags = {} # 恢复保存的 var_type_info Gen.var_type_info = saved_var_type_info Gen.var_type_assignments = saved_var_type_assignments Gen._stop_iter_flag_param = None Gen._local_heap_ptrs = [] Gen._var_to_heap_ptr = {} Gen._variadic_info = None self.Trans._CurrentCpythonObjectClass = None self.Trans.CurrentCReturnTypes = None if self.Trans.VarScopes: self.Trans.VarScopes.pop() self.Trans.FunctionReturnTypes[FuncName] = ReturnTypeInfo if not self.Trans.SymbolTable.has(FuncName): FuncInfo = CTypeInfo() FuncInfo.Name = FuncName FuncInfo.IsFunction = True FuncInfo.MetaList = func_meta if IsInlineFunc: FuncInfo.IsInline = True FuncInfo.InlineBody = Node.body FuncInfo.InlineParams = [arg.arg for arg in Node.args.args] self.Trans.SymbolTable.insert(FuncName, FuncInfo) else: existing = self.Trans.SymbolTable[FuncName] if existing.MetaList == FuncMeta.NONE and func_meta != FuncMeta.NONE: existing.MetaList = func_meta if IsInlineFunc: existing.IsInline = True existing.InlineBody = Node.body existing.InlineParams = [arg.arg for arg in Node.args.args] # property setter/deleter: 在原始 PropKey(不带后缀)下注册 MetaList if FuncMeta.PROPERTY_SETTER in func_meta or FuncMeta.PROPERTY_DELETER in func_meta: BasePropKey = f"{ClassName}.{RawFuncName}" if ClassName else RawFuncName base_existing = self.Trans.SymbolTable.lookup(BasePropKey) if base_existing: if func_meta != FuncMeta.NONE: base_existing.MetaList = base_existing.MetaList | func_meta else: PropInfo = CTypeInfo() PropInfo.Name = BasePropKey PropInfo.IsFunction = True PropInfo.MetaList = func_meta self.Trans.SymbolTable.insert(BasePropKey, PropInfo) return func