diff --git a/lib/Projectrans/DeclarationGenerator.py b/lib/Projectrans/DeclarationGenerator.py index f7a2267..95407d0 100644 --- a/lib/Projectrans/DeclarationGenerator.py +++ b/lib/Projectrans/DeclarationGenerator.py @@ -10,7 +10,7 @@ import llvmlite.ir as ir from lib.core import TypeSystem from lib.core.TypeSystem import CTypeRegistry from lib.core.SymbolUtils import ( - IsListAnnotation, AnnotationContainsName, IsCPtrSubscriptNode, + IsListAnnotation, IsCPtrSubscriptNode, IsRawPtrSubscriptNode, IsPtrSubscriptNode, ResolveGenericTypeArgStr, EnumClassIntWidth, ClassHasFuncLevelCVTable) @@ -97,9 +97,6 @@ class DeclarationGenerator: Markers: tuple[str, ...] = tuple(getattr(node, 'Markers', None) or ()) + tuple( getattr(node.annotation, 'Markers', None) or ()) is_typedef: bool = 'typedef' in Markers - if not is_typedef and AnnotationContainsName(node.annotation, 'CTypedef'): - # 兼容旧写法 `名字: CTypedef = 类型`(仅文本判据回落)。 - is_typedef = True if is_typedef and node.value: self.typedef_map[var_name] = node.value @@ -231,7 +228,7 @@ class DeclarationGenerator: """检查函数是否导出/外部可见(export / extern / state)。 新语法的 `export def` / `extern def` 由解析器写入 FunctionDef.Export / - Extern;旧语法的 `-> CExport | T` / `-> State | T` 仍走注解兼容判据。 + Extern。 """ if bool(getattr(node, 'Export', False)) or bool(getattr(node, 'Extern', False)): return True @@ -243,35 +240,28 @@ class DeclarationGenerator: return self._check_annotation_for_export(node.returns) def _check_annotation_for_export(self, annotation: ast.AST | None) -> bool: - """检查类型注解是否带 export / extern / state 标记。 - - 优先读 AST 的 Markers 字段;旧的 CExport/State 文本判断仅作兼容。 - """ + """检查类型注解是否带 export / extern / state 标记(只读 Markers)。""" if annotation is None: return False Markers: tuple[str, ...] = getattr(annotation, 'Markers', None) or () - if 'export' in Markers or 'extern' in Markers or 'state' in Markers: - return True - return (AnnotationContainsName(annotation, 'CExport') - or AnnotationContainsName(annotation, 'CExtern') - or AnnotationContainsName(annotation, 'State')) + return 'export' in Markers or 'extern' in Markers or 'state' in Markers def _generate_global_decl(self, node: ast.AnnAssign) -> str | None: """生成全局变量声明""" if not isinstance(node.target, ast.Name): return None var_name: str = node.target.id - # CDefine 是编译期常量,不是变量:stub 里**不得**生成 external global, + # define 是编译期常量,不是变量:stub 里**不得**生成 external global, # 否则其他模块引用它时变成未定义符号(链接失败)。标记由 Markers 字段承载。 Markers: tuple[str, ...] = tuple(getattr(node, 'Markers', None) or ()) + tuple( getattr(node.annotation, 'Markers', None) or ()) - if 'define' in Markers or AnnotationContainsName(node.annotation, 'CDefine'): + if 'define' in Markers: return None - if 'typedef' in Markers or AnnotationContainsName(node.annotation, 'CTypedef'): + if 'typedef' in Markers: return None if isinstance(node.annotation, ast.List): for elt in node.annotation.elts: - if isinstance(elt, ast.Attribute) and hasattr(elt, 'attr') and elt.attr in ('CTypedef', 'Callable'): + if isinstance(elt, ast.Attribute) and hasattr(elt, 'attr') and elt.attr == 'Callable': return None if isinstance(elt, ast.Subscript) and isinstance(elt.value, ast.Name) and elt.value.id == 'Callable': return None diff --git a/lib/Projectrans/Phase1Generator.py b/lib/Projectrans/Phase1Generator.py index e0e69c1..cd52c57 100644 --- a/lib/Projectrans/Phase1Generator.py +++ b/lib/Projectrans/Phase1Generator.py @@ -9,7 +9,7 @@ import traceback from lib.Projectrans.Utils import compute_sha1, get_file_dependencies, find_reachable_files_from_entries, parse_python_file from lib.Projectrans.DeclarationGenerator import DeclarationGenerator from lib.core.VLogger import get_logger as _vlog -from lib.core.SymbolUtils import ExpandSoftKeywords, AnnotationContainsName +from lib.core.SymbolUtils import ExpandSoftKeywords from lib.constants.config import mode as _ConfigMode from lib.core import TypeSystem from StubGen import PythonToStubConverter @@ -381,13 +381,10 @@ class Phase1Generator: if isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name): var_name: str = node.target.id # 新语法 `typedef 名字 = 类型` 由解析器写入 - # node/annotation 的 Markers;旧 `名字: CTypedef = 类型` - # 只作为兼容回落。 + # node/annotation 的 Markers。 _Markers: tuple[str, ...] = (tuple(getattr(node, 'Markers', None) or ()) + tuple(getattr(node.annotation, 'Markers', None) or ())) - is_typedef: bool = ( - 'typedef' in _Markers - or AnnotationContainsName(node.annotation, 'CTypedef')) + is_typedef: bool = 'typedef' in _Markers if is_typedef and node.value and var_name not in typedef_map: typedef_map[var_name] = node.value except Exception as _e: @@ -403,7 +400,7 @@ class Phase1Generator: 当前 include 的 .stub.ll 缓存应失效(因为类型引用的 SHA1 前缀会变化)。 签名同时纳入 includes/builtins.vp:它是注解类型解析的隐式输入 - (不在任何模块的 import 闭包,但其 CTypedef 参与签名/字段类型解析), + (不在任何模块的 import 闭包,但其 typedef 参与签名/字段类型解析), 其内容变化必须让所有 .stub.ll 失效——否则旧声明(如 sizet 曾被解析成 %"{mod}.sizet"* 假结构体)会被缓存继续引用,源码修复不生效。 """ diff --git a/lib/Projectrans/Phase2Translator.py b/lib/Projectrans/Phase2Translator.py index 4244ae4..d464d24 100644 --- a/lib/Projectrans/Phase2Translator.py +++ b/lib/Projectrans/Phase2Translator.py @@ -18,9 +18,9 @@ from lib.constants.config import mode as _config_mode from lib.core.Handles.HandlesBase import CTypeInfo from lib.core.SymbolData import ModuleSymbols from lib.core import TypeSystem -from lib.core.SymbolUtils import AnnotationContainsName, ExpandSoftKeywords, DefineDeclIntTypeFromAnnotation +from lib.core.SymbolUtils import ExpandSoftKeywords, DefineDeclIntTypeFromAnnotation from lib.core.SymbolUtils import ClassHasFuncLevelCVTable, IsVtableSlotMethod -from lib.Projectrans.Utils import compute_sha1, _check_annotation_for_export, find_reachable_files_from_entries, topological_sort_files, parse_python_file +from lib.Projectrans.Utils import compute_sha1, find_reachable_files_from_entries, topological_sort_files, parse_python_file from lib.Projectrans.Phase1Generator import _TryGlobalCache, _SaveToGlobalCache, _GLOBAL_CACHE_DIR import TransPyC from StubGen import PythonToStubConverter @@ -606,7 +606,7 @@ def _PickWorkerCount(n_files: int, per_worker_mb: int = 350) -> int: def _ExtractCDefineConstantsFromPyi(pyi_path: str, all_dc: dict[str, object], symtab: object | None = None, all_dt: dict[str, tuple[int, bool]] | None = None) -> None: - """从 .pyi 文件中提取 CDefine 常量到 all_dc。文件不存在时静默跳过。 + """从 .pyi 文件中提取 define 常量到 all_dc。文件不存在时静默跳过。 治本修复:原实现只支持 ast.Constant 和 float() 调用, 无法处理 CUnsignedLong(-11)(ast.Call)和 @@ -616,7 +616,7 @@ def _ExtractCDefineConstantsFromPyi(pyi_path: str, all_dc: dict[str, object], - ast.Call: 类型构造 (CUnsignedLong(-11)) - ast.BinOp: 位运算 (FOREGROUND_RED | FOREGROUND_GREEN) - ast.UnaryOp: 一元运算 (-11) - - ast.Name: 引用其他 CDefine 常量 + - ast.Name: 引用其他 define 常量 """ if not os.path.exists(pyi_path): return @@ -642,10 +642,8 @@ def _ExtractCDefineConstantsFromPyi(pyi_path: str, all_dc: dict[str, object], if isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name): Markers: tuple[str, ...] = (tuple(getattr(node, 'Markers', None) or ()) + tuple(getattr(node.annotation, 'Markers', None) or ())) - # 新语法 `define NAME = v` 由解析器写入 Markers;旧 - # `NAME: CDefine = v` 仅作兼容回落。 - if ('define' in Markers - or AnnotationContainsName(node.annotation, 'CDefine')) and node.value: + # 新语法 `define NAME = v` 由解析器写入 Markers。 + if 'define' in Markers and node.value: val: object = ConstEvaluator.eval_full(node.value, ctx) if val is None and isinstance(node.value, ast.Call) and len(node.value.args) == 1: # 类型构造的**裸别名**形态(如 `DWORD(-11)`,非 `CUnsignedLong(-11)`): @@ -655,7 +653,7 @@ def _ExtractCDefineConstantsFromPyi(pyi_path: str, all_dc: dict[str, object], # 现场:win32file.vp 的 STD_INPUT/OUTPUT/ERROR_HANDLE 是全仓**唯一**用 # 别名构造写的 define → 唯独这三个进不了 _all_define_constants,导致 # 模块属性访问 `wf.STD_ERROR_HANDLE` 解析落空、退化成未定义的全局符号 - # (链接失败)。CDefine 关心的是常量值,故回退求值其唯一实参(位型一致)。 + # (链接失败)。define 关心的是常量值,故回退求值其唯一实参(位型一致)。 val = ConstEvaluator.eval_full(node.value.args[0], ctx) if val is not None and isinstance(val, (int, float, str)): all_dc[node.target.id] = val @@ -670,21 +668,18 @@ def _ExtractCDefineConstantsFromPyi(pyi_path: str, all_dc: dict[str, object], def _IsExportExternFuncNode(node: ast.FunctionDef) -> bool: - """函数是否导出/外部可见:优先读 `export def` / `extern def` 的 AST 标记, - 再回落到 Markers,最后兼容旧的 `-> CExport/CExtern/State` 注解写法。""" + """函数是否导出/外部可见:读 `export def` / `extern def` 的 AST 标记与 Markers。""" if bool(getattr(node, 'Export', False)) or bool(getattr(node, 'Extern', False)): return True Markers: tuple[str, ...] = getattr(node, 'Markers', None) or () - if 'export' in Markers or 'extern' in Markers or 'state' in Markers: - return True - return _check_annotation_for_export(node.returns) + return 'export' in Markers or 'extern' in Markers or 'state' in Markers def _CountUnresolvedTypedefs(module_symbols: object) -> int: """该模块"有值注解却解析不出类型"的 typedef 个数(供声明阶段判断是否要下一轮)。 typedef 右侧可以引用**其它模块**的 typedef:例 win32base 的 - `HANDLE: CTypedef = VOIDPTR`(VOIDPTR 在 stdint)——本模块先 stage 时右侧 + `typedef HANDLE = VOIDPTR`(VOIDPTR 在 stdint)——本模块先 stage 时右侧 解析为空(original_type_kind/original_class 均为 None),要等依赖模块入表后 重 stage 才能补全。返回 0 表示本模块声明已完整(不再需要重跑)。 """ @@ -4359,15 +4354,10 @@ class Phase2Translator: module_name = os.path.splitext(os.path.basename(src_path))[0] for node in ast.iter_child_nodes(tree): if isinstance(node, ast.FunctionDef) and node.returns: - # 新语法 `inline` 由解析器写入返回注解的 Markers; - # 旧 `-> CInline | T` 的联合形态已废止(下方 fail-fast)。 + # 新语法 `inline` 由解析器写入返回注解的 Markers。 ReturnMarkers: tuple[str, ...] = getattr(node.returns, 'Markers', None) or () is_inline: bool = 'inline' in ReturnMarkers - if isinstance(node.returns, ast.Attribute) and node.returns.attr == 'CInline': - is_inline = True - elif isinstance(node.returns, ast.Name) and node.returns.id == 'CInline': - is_inline = True - elif isinstance(node.returns, ast.BinOp) and isinstance(node.returns.op, ast.BitOr): + if isinstance(node.returns, ast.BinOp) and isinstance(node.returns.op, ast.BitOr): _Line: int = getattr(node.returns, 'lineno', 0) or 0 raise TypeError( f"[TPC] 不支持类型联合 'T1 | T2'(第 {_Line} 行);" @@ -4454,7 +4444,7 @@ class Phase2Translator: # ① 声明阶段(全部模块;多轮直到"本轮没有新增可解析的声明") # 单轮仍会与模块顺序有关:typedef 右侧可以引用**其它模块**的 typedef, - # 例 win32base 的 `HANDLE: CTypedef = VOIDPTR`,VOIDPTR 在 stdint + # 例 win32base 的 `typedef HANDLE = VOIDPTR`,VOIDPTR 在 stdint # ⇒ 本模块先 stage 时右侧解析为空;下一轮把它重 stage 一遍(重 stage 覆盖 # 登记,条目随依赖入表而变完整)。无进展即停,最多再跑一轮。 _stage_map: dict[tuple[str, str], ModuleSymbols] = {} diff --git a/lib/Projectrans/Utils.py b/lib/Projectrans/Utils.py index 701ddbf..3821b8b 100644 --- a/lib/Projectrans/Utils.py +++ b/lib/Projectrans/Utils.py @@ -8,7 +8,7 @@ import vast as ast from lib.core.VLogger import get_logger as _vlog from lib.constants.config import mode as _ConfigMode -from lib.core.SymbolUtils import AnnotationContainsName, ExpandSoftKeywords +from lib.core.SymbolUtils import ExpandSoftKeywords # compute_sha1 结果缓存:同一内容字符串(如 parse_python_file 缓存中的 content)会被 @@ -43,17 +43,12 @@ _FILE_AST_CACHE: dict[str, tuple[float, str, ast.Module]] = {} def _check_annotation_for_export(annotation: ast.AST | None) -> bool: """检查类型注解是否带 export / extern / state。 - 优先读解析器写入的 Markers 字段(export/extern/state);旧的 - CExport/CExtern/State 文本判断仅作兼容回落。 + 只读解析器写入的 Markers 字段(export/extern/state)。 """ if not annotation: return False Markers: tuple[str, ...] = getattr(annotation, 'Markers', None) or () - if 'export' in Markers or 'extern' in Markers or 'state' in Markers: - return True - return (AnnotationContainsName(annotation, 'CExport') or - AnnotationContainsName(annotation, 'CExtern') or - AnnotationContainsName(annotation, 'State')) + return 'export' in Markers or 'extern' in Markers or 'state' in Markers def sha1_file(filepath: str) -> str: diff --git a/lib/StubGen/Converter.py b/lib/StubGen/Converter.py index 03b4568..f821d86 100644 --- a/lib/StubGen/Converter.py +++ b/lib/StubGen/Converter.py @@ -19,22 +19,10 @@ _ConvertCacheMaxSize: int = 4096 _RE_LINE_COMMENT: re.Pattern[str] = re.compile(r'#.*$') +# 内部指针标记 -> 源码语法名(仅保留内部标记还原,不做旧类型名兼容) _STUB_TYPE_ALIASES: dict[str, str] = { 'CPtr': 'rawptr', 'CArrayPtr': 'rawptr', 'CAutoPtr': 'rawptr', 'CRef': 'rawptr', 'CTempRef': 'rawptr', - # 旧内建类型名 → 新语法内建名(输入兼容;输出不得再出现 C* 标记) - 'CChar': 'char', 'CInt': 'int', 'CShort': 'short', 'CLong': 'long', - 'CLongLong': 'longlong', 'CFloat': 'float', 'CDouble': 'double', - 'CVoid': 'void', 'CUnsigned': 'uint', 'CUnsignedChar': 'uchar', - 'CUnsignedInt': 'uint', 'CUnsignedShort': 'ushort', - 'CUnsignedLong': 'ulong', 'CUnsignedLongLong': 'ulonglong', - 'CSignedChar': 'char', 'CBool': 'bool', 'CSizeT': 'sizet', - 'CInt8T': 'int8', 'CInt16T': 'int16', 'CInt32T': 'int32', 'CInt64T': 'int64', - 'CUInt8T': 'uint8', 'CUInt16T': 'uint16', 'CUInt32T': 'uint32', 'CUInt64T': 'uint64', - 'CIntPtrT': 'intptr', 'CUIntPtrT': 'uintptr', 'CPtrDiffT': 'ptrdifft', - 'CWCharT': 'wchar', 'CChar8T': 'char8', 'CChar16T': 'char16', 'CChar32T': 'char32', - 'CFloat8T': 'float8', 'CFloat16T': 'float16', 'CFloat32T': 'float32', - 'CFloat64T': 'float64', 'CFloat128T': 'float128', } @@ -175,7 +163,7 @@ class PythonToStubConverter: _AnnMarkers: tuple[str, ...] = ( tuple(getattr(node, 'Markers', None) or ()) + tuple(getattr(node.annotation, 'Markers', None) or ())) - HasStatic: bool = 'static' in _AnnMarkers or 'CStatic' in TypeStr + HasStatic: bool = 'static' in _AnnMarkers # 检查变量是否应该被排除 ShouldExclude: bool = False if isinstance(node.target, ast.Name) and not HasStatic: @@ -375,17 +363,18 @@ class PythonToStubConverter: else: lines.append(f'{MemberIndent}{item.target.id}: {TypeStr}') continue - # 检查是否是宏变量(Markers 标记 define;CDefine 仅兼容旧文本) + # 检查是否是宏变量(Markers 标记 define) _MemberMarkers: tuple[str, ...] = ( tuple(getattr(item, 'Markers', None) or ()) + tuple(getattr(item.annotation, 'Markers', None) or ())) - if 'define' in _MemberMarkers or 'CDefine' in TypeStr: + if 'define' in _MemberMarkers: # 检查宏变量是否应该被排除 if isinstance(item.target, ast.Name): MacroName: str = item.target.id if PythonToStubConverter._ShouldExcludeMacro(MacroName): continue # 跳过该宏 # 统一输出新语法 `define NAME[: 类型] = 值` + # 解析器对未标注类型的 define 以 CDefine 作注解占位(同 Unparser)。 ImplicitType: bool = ( isinstance(item.annotation, ast.Name) and item.annotation.id == 'CDefine') @@ -464,8 +453,6 @@ class PythonToStubConverter: # 跳过宏守卫相关行 if line.strip().startswith('CIfndef(') or line.strip().startswith('CEndif()'): continue - if ': CDefine' in line and '__' in line: - continue FilteredLines.append(line) lines.extend(FilteredLines) @@ -486,14 +473,9 @@ class PythonToStubConverter: lines: list[str] = [] IndentStr: str = ' ' * indent - # 检查是否是宏函数:新语法由解析器写 node.Define;旧 `-> CDefine` - # 返回注解仅作兼容回落。 + # 检查是否是宏函数:新语法由解析器写 node.Define / 返回注解 Markers ReturnMarkers: tuple[str, ...] = getattr(node.returns, 'Markers', None) or () if node.returns else () is_macro_func: bool = bool(getattr(node, 'Define', False)) or 'define' in ReturnMarkers - if node.returns: - ReturnType: str = PythonToStubConverter._GetTypeString(node.returns) - if 'CDefine' in ReturnType: - is_macro_func = True # 如果是宏函数,检查是否应该被排除 if is_macro_func: @@ -525,7 +507,7 @@ class PythonToStubConverter: # 处理函数装饰器:存储类/一次性初始化还原为关键字前缀。 # 新语法的 `extern def` / `export def` / `static def` 由解析器写入 - # FunctionDef.Extern/Export/Static;旧装饰器形态仅作兼容。 + # FunctionDef.Extern/Export/Static。 IsExternFunc: bool = bool(getattr(node, 'Extern', False)) IsExportFunc: bool = bool(getattr(node, 'Export', False)) IsStaticFunc: bool = bool(getattr(node, 'Static', False)) @@ -538,12 +520,6 @@ class PythonToStubConverter: DecoratorShort: str = DecoratorStr.rsplit('.', 1)[-1] if DecoratorShort == 'TLS': IsTlsFunc = True - elif DecoratorShort == 'CStatic': - IsStaticFunc = True - elif DecoratorShort == 'CExport': - IsExportFunc = True - elif DecoratorShort == 'CExtern': - IsExternFunc = True elif DecoratorShort == 'CVTable': IsVirtualFunc = True elif DecoratorShort == 'NoVTable': @@ -639,12 +615,13 @@ class PythonToStubConverter: TypeStr: str = PythonToStubConverter._GetTypeString(node.annotation) Markers: tuple[str, ...] = (tuple(getattr(node, 'Markers', None) or ()) + tuple(getattr(node.annotation, 'Markers', None) or ())) - # 检查是否是宏变量(优先读 Markers 的 define;CDefine 仅兼容旧文本) - if 'CDefine' in TypeStr or 'define' in Markers: + # 检查是否是宏变量(读 Markers 的 define) + if 'define' in Markers: # 检查宏变量是否应该被排除 if PythonToStubConverter._ShouldExcludeMacro(VarName): return lines # 返回空列表,排除该宏 - # 统一输出新语法 `define NAME[: 类型] = 值`(旧写法在此归一化) + # 统一输出新语法 `define NAME[: 类型] = 值` + # 解析器对未标注类型的 define 以 CDefine 作注解占位(同 Unparser)。 ImplicitType: bool = ( isinstance(node.annotation, ast.Name) and node.annotation.id == 'CDefine') @@ -661,7 +638,7 @@ class PythonToStubConverter: return lines # 非宏变量:不加 State # 含有 typedef 的变量不加 extern,普通变量需要加 extern - has_typedef: bool = 'CTypedef' in TypeStr or 'typedef' in Markers + has_typedef: bool = 'typedef' in Markers if has_typedef: ValueNode: ast.AST | None = node.value if node.value is not None else node.annotation ValueTypeStr: str = PythonToStubConverter._GetTypeString(ValueNode) @@ -803,8 +780,7 @@ class PythonToStubConverter: return PythonToStubConverter._GetTypeString(annotation.slice) + '*' return f'{base}[{SliceStr}]' elif isinstance(annotation, ast.BinOp): - # 类型注解不再接受 `T1 | T2` 联合(包括旧的 CExtern | T / - # CDefine | T / T | CRef):一律 fail-fast,不做任何合并。 + # 类型注解不接受 `T1 | T2` 联合:一律 fail-fast。 if isinstance(annotation.op, ast.BitOr): Line: int = getattr(annotation, 'lineno', 0) or 0 raise TypeError( @@ -880,11 +856,7 @@ class PythonToStubConverter: elements: list[str] = [PythonToStubConverter._GetTypeString(elem) for elem in annotation.elts] return f'[{", ".join(elements)}]' elif isinstance(annotation, ast.Call): - # 处理函数调用形式的类型注解,如 Postdefinition(xxa) 或 callable(CVoid, app_id = CInt) - # 如果是 __set_default__ 调用,只返回函数名部分 - if isinstance(annotation.func, ast.Attribute) and annotation.func.attr in ('__set_default__', '__set_default'): - return PythonToStubConverter._GetTypeString(annotation.func.value) - + # 处理函数调用形式的类型注解,如 Postdefinition(xxa) 或 callable(void, app_id = int) FuncStr: str = PythonToStubConverter._GetTypeString(annotation.func) ArgsStr: str = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in annotation.args]) # 处理关键字参数 @@ -913,17 +885,7 @@ class PythonToStubConverter: """从 Postdefinition 类型注解中提取类名 例如:Postdefinition(__buddy_system) -> '__buddy_system' - Postdefinition(xxx) | CTypedef -> 'xxx' """ - # 类型注解中的 BinOp(BitOr) 联合已废止:fail-fast,不做合并。 - if isinstance(annotation, ast.BinOp): - if isinstance(annotation.op, ast.BitOr): - Line: int = getattr(annotation, 'lineno', 0) or 0 - raise TypeError( - f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);" - f"类型注解只能是单一类型") - return None - # 处理函数调用 (如: Postdefinition(__buddy_system)) if isinstance(annotation, ast.Call): FuncStr: str = PythonToStubConverter._GetTypeString(annotation.func) diff --git a/lib/core/Handles/HandlesAssign.py b/lib/core/Handles/HandlesAssign.py index 99b24b3..eba063d 100644 --- a/lib/core/Handles/HandlesAssign.py +++ b/lib/core/Handles/HandlesAssign.py @@ -2407,12 +2407,6 @@ class AssignHandle(BaseHandle): raise TypeError( f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);" f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字") - if isinstance(annotation, ast.Attribute): - if annotation.attr in ('CTypedef', 'CDefine'): - return True - # 兼容旧 AST:裸标记名(新表示为 Markers,已在函数入口命中)。 - if isinstance(annotation, ast.Name): - return annotation.id in ('CTypedef', 'CDefine') if isinstance(annotation, ast.Subscript): return self._IsTypedefAnnotation(annotation.value) return False diff --git a/lib/core/Handles/HandlesExprBuiltin.py b/lib/core/Handles/HandlesExprBuiltin.py index 2f1d8f9..bab40b9 100644 --- a/lib/core/Handles/HandlesExprBuiltin.py +++ b/lib/core/Handles/HandlesExprBuiltin.py @@ -737,20 +737,6 @@ class ExprBuiltinHandle(BaseHandle): result = self.Trans.ExprUtils._try_operator_overLoad(_matched_cn, '__len__', val, Gen) if result is not None: return result - if _matched_cn.startswith('list['): - try: - _count_off: int | None = Gen._get_member_offset('__count__', _matched_cn, pointee) - except Exception: - # 特化结构体尚未展开布局(opaque):_list.vp 的 list 依次为 - # __data__(ptr) / __count__ / __capacity__ / __pool__ / ... - _count_off = 8 - if _count_off is not None: - _i8p = Gen.builder.bitcast(val, ir.PointerType(ir.IntType(8)), name='list_i8p') - _count_addr = Gen.builder.gep( - _i8p, [ir.Constant(ir.IntType(64), _count_off)], name='list_count_addr') - _count_ptr = Gen.builder.bitcast( - _count_addr, ir.PointerType(ir.IntType(64)), name='list_count_ptr') - return Gen._load(_count_ptr, name='list_count') self._FailFastLenUnsupported(arg_node, Gen, val, f"len() 参数类型 '{_matched_cn}' 没有 __len__ 方法") else: # 未在 Gen.structs 登记的 struct(opaque/匿名)→ fail-fast。 diff --git a/lib/core/Handles/HandlesExprCall.py b/lib/core/Handles/HandlesExprCall.py index 108b8aa..1b1c705 100644 --- a/lib/core/Handles/HandlesExprCall.py +++ b/lib/core/Handles/HandlesExprCall.py @@ -3031,17 +3031,6 @@ class ExprCallHandle(BaseHandle): Gen._generic_spec_error = f'{type(_spec_err).__name__}: {_spec_err}' return cached_name: str = cached[0] - was_declare_only: bool = cached[1] - if not was_declare_only: - # 缓存声称已完整,但方法确实不存在:强制补发一次 - spec_cache[spec_key] = (cached_name, True) - try: - self.Trans.ClassHandler._specialize_generic_class( - base_name, _TypeArgs, Gen, - type_names=_TypeNames, declare_only=False) - except Exception as _spec_err: - Gen._generic_spec_error = f'强制补发失败: {type(_spec_err).__name__}: {_spec_err}' - return # 检查方法是否已有 define(blocks 非空表示已编译方法体) struct_sha1_map = getattr(Gen, '_struct_sha1_map', {}) class_sha1 = struct_sha1_map.get(cached_name) @@ -3942,22 +3931,6 @@ class ExprCallHandle(BaseHandle): adjusted = Gen._adjust_args(call_args_fb, func) result = Gen.builder.call(func, adjusted, name=f"call_{FullMethodName}") return result - if ClassName.startswith('list[') and ClassName in Gen.structs: - # 泛型特化方法未生成时,回退到裸模板 list 的同名方法 - struct_type = Gen.structs[ClassName] - self_ptr_type = ir.PointerType(struct_type) - BareFuncName: str = f'list.{MethodName}' - func = Gen._find_function(BareFuncName) - if func is not None: - if isinstance(ObjVal.type, ir.PointerType) and ObjVal.type.pointee == struct_type: - call_self = ObjVal - else: - call_self = Gen.builder.bitcast(ObjVal, self_ptr_type, name=f"method_self_{ClassName}") - call_args_fb = [call_self] + CallArgs - self._fill_default_args(call_args_fb, func, BareFuncName) - self._append_eh_msg_out_arg(call_args_fb, func, Gen) - adjusted = Gen._adjust_args(call_args_fb, func) - return Gen.builder.call(func, adjusted, name=f"call_{BareFuncName}") _spec_diag: str = getattr(Gen, '_generic_spec_error', '') raise Exception( f"Undefined method '{MethodName}' in class '{ClassName}' " @@ -4161,20 +4134,6 @@ class ExprCallHandle(BaseHandle): result = self.Trans.ExprUtils._try_operator_overLoad(_matched_cn, '__len__', val, Gen) if result is not None: return result - if _matched_cn.startswith('list['): - try: - _count_off: int | None = Gen._get_member_offset('__count__', _matched_cn, pointee) - except Exception: - # 特化结构体尚未展开布局(opaque):_list.vp 的 list 依次为 - # __data__(ptr) / __count__ / __capacity__ / __pool__ / ... - _count_off = 8 - if _count_off is not None: - _i8p = Gen.builder.bitcast(val, ir.PointerType(ir.IntType(8)), name='list_i8p') - _count_addr = Gen.builder.gep( - _i8p, [ir.Constant(ir.IntType(64), _count_off)], name='list_count_addr') - _count_ptr = Gen.builder.bitcast( - _count_addr, ir.PointerType(ir.IntType(64)), name='list_count_ptr') - return Gen._load(_count_ptr, name='list_count') self._FailFastLenUnsupported(arg_node, Gen, val, f"len() 参数类型 '{_matched_cn}' 没有 __len__ 方法") else: # 未在 Gen.structs 登记的 struct(opaque/匿名)→ fail-fast。 diff --git a/lib/core/Handles/HandlesExprUtils.py b/lib/core/Handles/HandlesExprUtils.py index 2be7a99..7d8b087 100644 --- a/lib/core/Handles/HandlesExprUtils.py +++ b/lib/core/Handles/HandlesExprUtils.py @@ -178,7 +178,7 @@ class ExprUtils: if not Gen._has_function(FullMethodName): FullMethodName = f'{ClassName}.{op_name}__' if not Gen._has_function(FullMethodName) and '[' in ClassName: - # 泛型特化方法尚未生成时,先补发特化,再回退裸模板类(如 list.__len__) + # 泛型特化方法尚未生成时,先补发特化 try: self.Trans.ExprCallHandle._try_complete_generic_specialization(ClassName, op_name, Gen) except Exception: @@ -186,18 +186,6 @@ class ExprUtils: FullMethodName = f'{ClassName}.{op_name}' if not Gen._has_function(FullMethodName): FullMethodName = f'{ClassName}.{op_name}__' - if not Gen._has_function(FullMethodName): - _SpecTy: Any = Gen.structs.get(ClassName) - _SpecName: str = getattr(_SpecTy, 'name', '') if _SpecTy is not None else '' - if _SpecName: - FullMethodName = f'{_SpecName}.{op_name}' - if not Gen._has_function(FullMethodName): - FullMethodName = f'{_SpecName}.{op_name}__' - if not Gen._has_function(FullMethodName): - _BareClass: str = ClassName.split('[', 1)[0] - FullMethodName = f'{_BareClass}.{op_name}' - if not Gen._has_function(FullMethodName): - FullMethodName = f'{_BareClass}.{op_name}__' if not Gen._has_function(FullMethodName): # 多继承:沿 MRO 祖先链查找 dunder 方法(先声明父类优先,与 VPC 一致) for anc in Gen._get_mro_chain(ClassName)[1:]: diff --git a/lib/core/Handles/HandlesFunctions.py b/lib/core/Handles/HandlesFunctions.py index d12af69..0a5465b 100644 --- a/lib/core/Handles/HandlesFunctions.py +++ b/lib/core/Handles/HandlesFunctions.py @@ -68,12 +68,6 @@ def _IsVoidOrDeclAnnotation(Annot: ast.AST) -> bool: return Annot.value is None if isinstance(Annot, ast.Subscript): return _IsVoidOrDeclAnnotation(Annot.value) - if isinstance(Annot, ast.Attribute): - # 兼容旧 AST:t.CVoid / t.State / t.CExport / t.CExtern - return getattr(Annot, 'attr', '') in ('CVoid', 'State', 'CExport', 'CExtern') - if isinstance(Annot, ast.Name): - # 兼容旧 AST:裸标记名 - return Annot.id in ('CVoid', 'State', 'CExport', 'CExtern') return False diff --git a/lib/core/Handles/HandlesImports.py b/lib/core/Handles/HandlesImports.py index 87266e9..d16f0eb 100644 --- a/lib/core/Handles/HandlesImports.py +++ b/lib/core/Handles/HandlesImports.py @@ -1270,11 +1270,6 @@ class ImportHandle(BaseHandle): """ if annotation is None: return None - if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): - Line: int = getattr(annotation, 'lineno', 0) or 0 - raise TypeError( - f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);" - f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字") if isinstance(annotation, ast.Subscript): _base: ast.AST = annotation.value _bn: str = '' @@ -1418,11 +1413,6 @@ class ImportHandle(BaseHandle): IsCDefine = True elif 'typedef' in _GlobalMarkers: IsCTypedef = True - elif isinstance(Node.annotation, ast.Name): - if Node.annotation.id == 'CDefine': - IsCDefine = True - elif Node.annotation.id == 'CTypedef': - IsCTypedef = True if IsCTypedef: # 检查符号是否已存在且已正确解析(OriginalType 已设置),避免覆盖 @@ -1627,11 +1617,6 @@ class ImportHandle(BaseHandle): llvm_str = CTypeRegistry.NameToLLVM(value_node.id) if llvm_str: return llvm_str - elif isinstance(value_node, ast.BinOp) and isinstance(value_node.op, ast.BitOr): - Line: int = getattr(value_node, 'lineno', 0) or 0 - raise TypeError( - f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);" - f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字") elif isinstance(value_node, ast.Subscript): base_node: ast.AST = value_node.value base_name: str | None = ( @@ -1667,16 +1652,7 @@ class ImportHandle(BaseHandle): def _check_annotation_for_state(self, annotation: ast.AST) -> bool: Markers: tuple[str, ...] = tuple(getattr(annotation, 'Markers', None) or ()) - if 'export' in Markers or 'extern' in Markers or 'state' in Markers: - return True - # 兼容旧 AST:修饰词曾是联合注解的一翼 / 裸标记名。 - if isinstance(annotation, ast.Subscript): - return (AnnotationContainsName(annotation.value, 'CExport') or - AnnotationContainsName(annotation.value, 'CExtern') or - AnnotationContainsName(annotation.value, 'State')) - return (AnnotationContainsName(annotation, 'CExport') or - AnnotationContainsName(annotation, 'CExtern') or - AnnotationContainsName(annotation, 'State')) + return 'export' in Markers or 'extern' in Markers or 'state' in Markers def _check_decorators_for_state(self, Node: ast.FunctionDef) -> bool: """检查装饰器列表中是否包含 @CExport / @CExtern / @State(CExport 既能作返回值注解也能作装饰器)""" diff --git a/lib/vast/__init__.py b/lib/vast/__init__.py index 8c8cd45..c48799b 100644 --- a/lib/vast/__init__.py +++ b/lib/vast/__init__.py @@ -55,29 +55,38 @@ def _ParsePure(source: str, mode: str) -> AST: raise ValueError(f"invalid mode {mode!r}") -# C 加速解析器(vast_c 扩展):可用则优先,输出与 vast.parse 结构完全一致。 -# VAST_USE_C=0 禁用 C 路径;=strict 时 C 路径异常直接抛出(fail-fast)。 +# C 加速解析器(vast_c 扩展):必需依赖,输出与 vast.parse 结构完全一致。 +# VAST_USE_C=0 显式选择纯 Python;=strict 时 C 路径异常直接抛出(fail-fast)。 +# 扩展不可用或产物早于 vast_c.c 时直接抛错(提示重建),不做静默回退。 # -# 回退策略(响亮回退):C 路径抛异常时回退纯 Python,并向 stderr 打印一行可诊断 +# 运行时 C 路径抛异常时回退纯 Python(响亮回退):向 stderr 打印一行可诊断 # 信息(文件名 + 异常)。该回退**不会**改变产出——纯 Python 是本包语义基准, # 故绝不静默产出与纯 Python 不同的 AST。连续相同的(文件, 异常)只打印一次。 -_VAST_C_PARSE = None -_VAST_C_STALE = False +_VastCBuildHint: str = ( + "[TPC] 请重建 vast C 扩展:按 lib/vast_c/vast_c.c 头部注释的 gcc 命令" + "生成 lib/vast_c/_parser.pyd 后重试。") + +_VastCDir: str = _os.path.join(_os.path.dirname(_os.path.abspath(__file__)), '..', 'vast_c') +_VastCSrc: str = _os.path.join(_VastCDir, 'vast_c.c') try: - import glob as _glob - _vast_c_dir: str = _os.path.join(_os.path.dirname(_os.path.abspath(__file__)), '..', 'vast_c') - _vast_c_src: str = _os.path.join(_vast_c_dir, 'vast_c.c') - _vast_c_pyd: list[str] = _glob.glob(_os.path.join(_vast_c_dir, '_parser*.pyd')) - if _vast_c_pyd and _os.path.exists(_vast_c_src): - if max(_os.path.getmtime(_f) for _f in _vast_c_pyd) < _os.path.getmtime(_vast_c_src): - _VAST_C_STALE = True -except Exception: - _VAST_C_STALE = False -if not _VAST_C_STALE: - try: - from lib.vast_c import parse as _VAST_C_PARSE - except Exception: - _VAST_C_PARSE = None + _VastCPyd: list[str] = [ + _os.path.join(_VastCDir, _f) + for _f in _os.listdir(_VastCDir) + if _f.startswith('_parser') and _f.endswith('.pyd')] +except OSError: + _VastCPyd = [] +if _VastCPyd and _os.path.exists(_VastCSrc): + if max(_os.path.getmtime(_f) for _f in _VastCPyd) < _os.path.getmtime(_VastCSrc): + raise ImportError( + "[TPC] vast C 扩展 (_parser.pyd) 早于 vast_c.c,产物已过期。" + + _VastCBuildHint) + +try: + from lib.vast_c import parse as _VAST_C_PARSE +except Exception as _e: + raise ImportError( + f"[TPC] vast C 扩展不可用({type(_e).__name__}: {_e})。" + _VastCBuildHint + ) from _e _CFallbackSeen: set = set() diff --git a/lib/vast_c/_parser.pyd b/lib/vast_c/_parser.pyd index c41ca2c..0af9c16 100644 Binary files a/lib/vast_c/_parser.pyd and b/lib/vast_c/_parser.pyd differ