refactor: 删除保留性兼容兜底,仅保留新语法主路径

移除 len(list) 直读 __count__、list 方法裸模板回退、旧 C* 文本标记兼容、旧联合兼容;vast 扩展过期直接报错,已重建 _parser.pyd。
This commit is contained in:
TermiNexus committed 2026-10-18 19:22:32 +08:00
1 parent f8d84a1941
commit 109e71a477
13 files changed
+72 -232

No files matched your search

+8 -18
View File
@@ -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
+4 -7
View File
@@ -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"* 假结构体)会被缓存继续引用,源码修复不生效。
"""
+13 -23
View File
@@ -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] = {}
+3 -8
View File
@@ -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:
+14 -52
View File
@@ -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)
-6
View File
@@ -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
-14
View File
@@ -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。
-41
View File
@@ -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。
+1 -13
View File
@@ -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:]:
-6
View File
@@ -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
+1 -25
View File
@@ -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 既能作返回值注解也能作装饰器)"""
+28 -19
View File
@@ -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()
Binary file not shown.