refactor: 删除保留性兼容兜底,仅保留新语法主路径
移除 len(list) 直读 __count__、list 方法裸模板回退、旧 C* 文本标记兼容、旧联合兼容;vast 扩展过期直接报错,已重建 _parser.pyd。
This commit is contained in:
1 parent
f8d84a1941
commit
109e71a477
13 files changed
+72
-232
No files matched your search
@@ -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
|
||||
|
||||
@@ -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"* 假结构体)会被缓存继续引用,源码修复不生效。
|
||||
"""
|
||||
|
||||
@@ -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] = {}
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in new issue
Block a user