refactor(tpc): 退役 t/c 模块并将定宽类型升级为内建

删除 lib/includes/t.py、c.py,类型模型迁入 lib/core/TypeSystem.py;移除 IsTModule/_T_MODULE_NAMES 等名称判据,语法糖与内部标记统一为裸名;builtins 的 sizet/intN/uintN/fast/least/uchar/short/long 等改为编译器内建短名。
This commit is contained in:
TermiNexus committed 2026-10-18 13:00:58 +08:00
1 parent 8d27747c7c
commit f19d25782f
66 files changed
+2242 -3435

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""ProjectTrans.py - 工程级 TransPyC 翻译器""" """ProjectTrans.py - 工程级 TransPyC 翻译器"""
import lib._bootstrap # noqa: F401 设置 sys.path(项目根 + lib/includes) import lib._bootstrap # noqa: F401 设置 sys.path(项目根 + lib)
from lib.Projectrans import ( from lib.Projectrans import (
compute_sha1, _check_annotation_for_export, sha1_file, compute_sha1, _check_annotation_for_export, sha1_file,
+5 -8
View File
@@ -11,7 +11,7 @@ TransPyC 已用自身实现以下组件,证明其作为系统级语言的成
- **自研 LLVM IR 生成库** —— [includes/llvmlite/](includes/llvmlite/)(~1,500 LOC),用 TransPyC 自己写的 IR 文本生成器,18/18 测试通过 - **自研 LLVM IR 生成库** —— [includes/llvmlite/](includes/llvmlite/)(~1,500 LOC),用 TransPyC 自己写的 IR 文本生成器,18/18 测试通过
- **zlib 移植** —— [Test/ZlibTest/](Test/ZlibTest/),完整 deflate/inflate/huffman/checksum(~1,900 LOC) - **zlib 移植** —— [Test/ZlibTest/](Test/ZlibTest/),完整 deflate/inflate/huffman/checksum(~1,900 LOC)
- **Win32 FFI 绑定** —— [includes/w32/](includes/w32/),file/memory/process/sync/console 全覆盖 - **Win32 FFI 绑定** —— [includes/w32/](includes/w32/),file/memory/process/sync/console 全覆盖
- **泛型容器** —— [includes/linkedlist.vp](includes/linkedlist.vp),`@t.NoVTable` + PEP 695 递归泛型继承 `class GNode(GSListNode[GNode])` - **泛型容器** —— [includes/linkedlist.vp](includes/linkedlist.vp),`@NoVTable` + PEP 695 递归泛型继承 `class GNode(GSListNode[GNode])`
## 核心设计理念 ## 核心设计理念
@@ -37,8 +37,6 @@ Viper 语言通过两个核心模块提供类型和操作支持:
| 模块 | 用途 | 导入方式 | | 模块 | 用途 | 导入方式 |
|------|------|----------| |------|------|----------|
| `t` | 类型定义系统 | `import t` |
| `c` | C 语言操作指令 | `import c` |
## 快速上手 ## 快速上手
@@ -48,7 +46,6 @@ Viper 语言通过两个核心模块提供类型和操作支持:
4. **写第一个程序**: 4. **写第一个程序**:
```python ```python
import t, c
from stdint import * from stdint import *
import stdio import stdio
@@ -61,12 +58,12 @@ def main() -> CInt | CExport:
| 文件 | 内容 | | 文件 | 内容 |
|------|------| |------|------|
| [01-overview.md](wiki/01-overview.md) | 语言概述、两阶段编译流程、SHA1 命名空间、`t.CDefine`/`t.CExport`/`t.CInline` 深度解析 | | [01-overview.md](wiki/01-overview.md) | 语言概述、两阶段编译流程、SHA1 命名空间、`CDefine`/`CExport`/`CInline` 深度解析 |
| [02-type-system.md](wiki/02-type-system.md) | 类型系统(基本类型、指针、数组、结构体、联合体、枚举、typedef、`__attribute__`) | | [02-type-system.md](wiki/02-type-system.md) | 类型系统(基本类型、指针、数组、结构体、联合体、枚举、typedef、`__attribute__`) |
| [03-variables.md](wiki/03-variables.md) | 变量声明与赋值(含 `t.CDefine` 常量) | | [03-variables.md](wiki/03-variables.md) | 变量声明与赋值(含 `CDefine` 常量) |
| [04-functions.md](wiki/04-functions.md) | 函数定义与调用(含 `t.CExport`、`t.CInline`、`t.CDefine` 函数、`-> tuple[...]` 多返回值) | | [04-functions.md](wiki/04-functions.md) | 函数定义与调用(含 `CExport`、`CInline`、`CDefine` 函数、`-> tuple[...]` 多返回值) |
| [05-classes.md](wiki/05-classes.md) | 类与数据布局(结构体、联合体、枚举、typedef、位域) | | [05-classes.md](wiki/05-classes.md) | 类与数据布局(结构体、联合体、枚举、typedef、位域) |
| [06-oop.md](wiki/06-oop.md) | 面向对象与运算符重载(`@t.Object`、`@t.CVTable`、`@t.NoVTable`、继承、dunder 方法) | | [06-oop.md](wiki/06-oop.md) | 面向对象与运算符重载(`@Object`、`@CVTable`、`@NoVTable`、继承、dunder 方法) |
| [07-control-flow.md](wiki/07-control-flow.md) | 控制流(条件、循环、match) | | [07-control-flow.md](wiki/07-control-flow.md) | 控制流(条件、循环、match) |
| [08-c-operations.md](wiki/08-c-operations.md) | C 语言操作(指针、内联汇编、FFI 外部函数声明、LLVM IR 内联) | | [08-c-operations.md](wiki/08-c-operations.md) | C 语言操作(指针、内联汇编、FFI 外部函数声明、LLVM IR 内联) |
| [09-exceptions.md](wiki/09-exceptions.md) | 异常处理 | | [09-exceptions.md](wiki/09-exceptions.md) | 异常处理 |
+1 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""StubGen - C/H/Py 文件到 Python 存根文件生成器(工程化版本)""" """StubGen - C/H/Py 文件到 Python 存根文件生成器(工程化版本)"""
import lib._bootstrap # noqa: F401 设置 sys.path(项目根 + lib/includes) import lib._bootstrap # noqa: F401 设置 sys.path(项目根 + lib)
from lib.StubGen import StubGenConfig, PythonToStubConverter, StubGen, main from lib.StubGen import StubGenConfig, PythonToStubConverter, StubGen, main
+1 -1
View File
@@ -4,7 +4,7 @@
背景(为什么需要这个门禁) 背景(为什么需要这个门禁)
Viper 前端 = TPC 自研 vast(`lib/vast`)+ **唯一展开点** Viper 前端 = TPC 自研 vast(`lib/vast`)+ **唯一展开点**
`lib/core/SymbolUtils.ExpandSoftKeywords`(`fn/fun/func/function` → `def`; `lib/core/SymbolUtils.ExpandSoftKeywords`(`fn/fun/func/function` → `def`;
`enum X:` 块 → `class X(t.CEnum):`,两者均同行替换、行号不变)。 `enum X:` 块 → `class X(CEnum):`,两者均同行替换、行号不变)。
凡把 **Viper 源码文本**交给 `ast.parse` / `vast.parse` 的入口都必须先过这一层; 凡把 **Viper 源码文本**交给 `ast.parse` / `vast.parse` 的入口都必须先过这一层;
漏过者的失败形态是**静默降级**,不是报错:`includes/ast/base.vp:168` 的 漏过者的失败形态是**静默降级**,不是报错:`includes/ast/base.vp:168` 的
`enum ASTFlag:` 曾让整个 base.vp 的声明(含顶层 `_init_ast`)一个都不注册, `enum ASTFlag:` 曾让整个 base.vp 的声明(含顶层 `_init_ast`)一个都不注册,
+12 -12
View File
@@ -17,18 +17,18 @@
(如 "%s.__iter__" 之类的字符串与三引号注释块不再命中)。 (如 "%s.__iter__" 之类的字符串与三引号注释块不再命中)。
5) 类成员表按族隔离: 基类先在**本族**找, 再找**支撑族**(''), 最后全局唯一名; 5) 类成员表按族隔离: 基类先在**本族**找, 再找**支撑族**(''), 最后全局唯一名;
同一基类名跨族重复时报 AMBIG(宁可 UNRESOLVED 也不猜)。 同一基类名跨族重复时报 AMBIG(宁可 UNRESOLVED 也不猜)。
6) `t.REnum`(tagged union)派生类: 变体字段合并进父类成员集 6) `REnum`(tagged union)派生类: 变体字段合并进父类成员集
(VPC 允许在父类指针上访问变体字段, 不合并会产生大量误报)。 (VPC 允许在父类指针上访问变体字段, 不合并会产生大量误报)。
前端 = **TPC 自研 vast**(`lib/vast`,与 StubGen/Converter.py 用的 `import vast as ast` 前端 = **TPC 自研 vast**(`lib/vast`,与 StubGen/Converter.py 用的 `import vast as ast`
是同一源文件; 不可用 CPython `ast`, 否则含 `list[X*]` 等 vast 专有写法的文件会整体 是同一源文件; 不可用 CPython `ast`, 否则含 `list[X*]` 等 vast 专有写法的文件会整体
SyntaxError 被跳过)。vast 与 CPython ast 的差异及本脚本的适配: SyntaxError 被跳过)。vast 与 CPython ast 的差异及本脚本的适配:
A) `X*` / `X**` 被 vast 脱糖成 `X | t.CPtr`(`**` 加两层), 其中合成的 A) `X*` / `X**` 被 vast 脱糖成 `X | CPtr`(`**` 加两层), 其中合成的
`t.CPtr` Attribute 节点**连 lineno 属性都没有**(编译器内部脱糖产物, 不是源码里的 `CPtr` Attribute 节点**连 lineno 属性都没有**(编译器内部脱糖产物, 不是源码里的
访问; 全树实测 555 个, 全部是 ('t','CPtr'))=> 计入 Uses 时用 访问; 全树实测 555 个, 全部是 ('CPtr'))=> 计入 Uses 时用
`getattr(Node,'lineno',None) is not None` 排除。 `getattr(Node,'lineno',None) is not None` 排除。
B) vast 的 SyntaxError 可能不带 lineno(C 路径)=> 从报文 `at line N` 兜底提取。 B) vast 的 SyntaxError 可能不带 lineno(C 路径)=> 从报文 `at line N` 兜底提取。
C) vast 的装饰器 `@t.NoVTable` 的 col_offset 是 `@` 的位置(CPython 是其后 1 列); C) vast 的装饰器 `@NoVTable` 的 col_offset 是 `@` 的位置(CPython 是其后 1 列);
该 Attribute 的接收者 `t` 不是族指针, 判据不受影响。 该 Attribute 的接收者 `t` 不是族指针, 判据不受影响。
D) 其余节点类名/属性名/walk/iter_child_nodes 与 CPython ast 同构(已逐节点对照)。 D) 其余节点类名/属性名/walk/iter_child_nodes 与 CPython ast 同构(已逐节点对照)。
@@ -86,7 +86,7 @@ DefaultIncludesDir = os.path.join(RepoRoot, 'includes')
DefaultOutFile = os.path.join(RepoRoot, 'Debugger', 'ScanAstFieldMiss.txt') DefaultOutFile = os.path.join(RepoRoot, 'Debugger', 'ScanAstFieldMiss.txt')
# ---- 前端: TPC 自研 vast(非 CPython ast)。需要 TransPyC 包根在 sys.path, # ---- 前端: TPC 自研 vast(非 CPython ast)。需要 TransPyC 包根在 sys.path,
# lib._bootstrap 会再补齐 lib/ 与 lib/includes(使 `import vast` 可用)。 # lib._bootstrap 会再补齐 lib/(使 `import vast` 可用)。
if TpcRoot not in sys.path: if TpcRoot not in sys.path:
sys.path.insert(0, TpcRoot) sys.path.insert(0, TpcRoot)
from lib import vast as ast # noqa: E402 from lib import vast as ast # noqa: E402
@@ -105,8 +105,8 @@ ClassFields = {}
ClassMethods = {} ClassMethods = {}
ClassBase = {} ClassBase = {}
ClassLoc = {} # 裸类名 -> [族, ...](用于跨族基类解析) ClassLoc = {} # 裸类名 -> [族, ...](用于跨族基类解析)
EnumClass = {} # (族, 类名) -> 1 表示 t.REnum/t.CEnum 派生(变体字段合并) EnumClass = {} # (族, 类名) -> 1 表示 REnum/CEnum 派生(变体字段合并)
REnumClass = {} # (族, 类名) -> 1 表示 t.REnum 派生(额外有编译器内建 .kind()) REnumClass = {} # (族, 类名) -> 1 表示 REnum 派生(额外有编译器内建 .kind())
MemberCache = {} MemberCache = {}
FamilyFields = {} # 族 -> 该族所有字段并集(OTHER/NOWHERE 判定用) FamilyFields = {} # 族 -> 该族所有字段并集(OTHER/NOWHERE 判定用)
@@ -190,7 +190,7 @@ def ParseSrc(Src, Path):
"""vast 前端解析入口(全脚本单一前端; 失败抛异常, 由调用方记账)。 """vast 前端解析入口(全脚本单一前端; 失败抛异常, 由调用方记账)。
`.vp` 源码须先过 Viper 软关键字层(`lib/core/SymbolUtils.ExpandSoftKeywords`: `.vp` 源码须先过 Viper 软关键字层(`lib/core/SymbolUtils.ExpandSoftKeywords`:
`fn/fun/func/function` → `def`、`enum X:` → `class X(t.CEnum):`),与 `fn/fun/func/function` → `def`、`enum X:` → `class X(CEnum):`),与
`StubGen/Converter.py` / `Shell/TransPyC.py` 等既有前端入口同口径。 `StubGen/Converter.py` / `Shell/TransPyC.py` 等既有前端入口同口径。
否则含 `enum` 的 `.vp`(如 `includes/ast/base.vp:168`)会在此整体 SyntaxError, 否则含 `enum` 的 `.vp`(如 `includes/ast/base.vp:168`)会在此整体 SyntaxError,
被 `LoadInclude` 的正则兜底或 `RunScan` 的 `parsefail` 记成"解析失败"——两者 被 `LoadInclude` 的正则兜底或 `RunScan` 的 `parsefail` 记成"解析失败"——两者
@@ -336,7 +336,7 @@ def Member(Fam, Name):
# 2. 类型推导: 从注解 / cast 调用里取 (族, 类名) # 2. 类型推导: 从注解 / cast 调用里取 (族, 类名)
# ============================================================ # ============================================================
def AnnClass(Ann): def AnnClass(Ann):
"""注解里若为 rawptr[<族>.<X>](可被 `| t.CPtr` 包裹)返回 (族, X), 否则 None。""" """注解里若为 rawptr[<族>.<X>](可被 `| CPtr` 包裹)返回 (族, X), 否则 None。"""
if Ann is None: if Ann is None:
return None return None
if isinstance(Ann, ast.BinOp) and isinstance(Ann.op, ast.BitOr): if isinstance(Ann, ast.BinOp) and isinstance(Ann.op, ast.BitOr):
@@ -464,8 +464,8 @@ def Walk(Node, Sc):
Walk(S, CS) Walk(S, CS)
return return
if isinstance(Node, ast.Attribute): if isinstance(Node, ast.Attribute):
# 只收源码里真实存在的属性访问: vast 脱糖 `X*` 会合成 `t.CPtr` Attribute, # 只收源码里真实存在的属性访问: vast 脱糖 `X*` 会合成 `CPtr` Attribute,
# 该节点**连 lineno 属性都没有**(全树 555 个, 全为 ('t','CPtr')), 不是源码 # 该节点**连 lineno 属性都没有**(全树 555 个, 全为 CPtr 下标), 不是源码
# 访问、也不能参与位置比较 => 用 getattr 显式排除。 # 访问、也不能参与位置比较 => 用 getattr 显式排除。
if isinstance(Node.value, ast.Name) and getattr(Node, 'lineno', None) is not None: if isinstance(Node.value, ast.Name) and getattr(Node, 'lineno', None) is not None:
Uses.append((Node, Sc)) Uses.append((Node, Sc))
+1 -1
View File
@@ -1,6 +1,6 @@
# TransPyC 入口程序 # TransPyC 入口程序
# 拆分后的模块位于 lib/Shell/ 目录下 # 拆分后的模块位于 lib/Shell/ 目录下
import lib._bootstrap # noqa: F401 设置 sys.path(项目根 + lib/includes) import lib._bootstrap # noqa: F401 设置 sys.path(项目根 + lib)
from lib.Shell import ( from lib.Shell import (
SerializeSymbolTable, deSerializeSymbolTable, SerializeSymbolTable, deSerializeSymbolTable,
+102 -129
View File
@@ -7,8 +7,8 @@ from typing import List
import llvmlite.ir as ir import llvmlite.ir as ir
from lib.includes import t from lib.core import TypeSystem
from lib.includes.t import CTypeRegistry from lib.core.TypeSystem import CTypeRegistry
from lib.core.SymbolUtils import ( from lib.core.SymbolUtils import (
IsListAnnotation, AnnotationContainsName, IsCPtrSubscriptNode, IsCPtrNode, IsListAnnotation, AnnotationContainsName, IsCPtrSubscriptNode, IsCPtrNode,
IsRawPtrSubscriptNode, IsPtrSubscriptNode, ResolveGenericTypeArgStr, IsRawPtrSubscriptNode, IsPtrSubscriptNode, ResolveGenericTypeArgStr,
@@ -53,13 +53,13 @@ class DeclarationGenerator:
# HandlesClassDef._generic_class_templates 同源(ClassDef 的 type_params # HandlesClassDef._generic_class_templates 同源(ClassDef 的 type_params
# 标记),generate() 里从本模块 pyi 与 class_def_map 收集 # 标记),generate() 里从本模块 pyi 与 class_def_map 收集
self._generic_class_names: set[str] = set() self._generic_class_names: set[str] = set()
# t/c 导入名表(from t import CInt as myint → 'myint' → ('t','CInt')), # 内建类型导入名表(CInt as myint → 'myint' → CInt),
# 与定义端 Trans._t_c_imported_names 同口径,供泛型实参串解析使用 # 与定义端 Trans._from_import_aliases 同口径,供泛型实参串解析使用
self._t_c_imported_names: dict[str, tuple[str, str]] = {} self._from_import_aliases: dict[str, tuple[str, str]] = {}
# 跨模块类定义映射:{class_name: ClassDef_node},供 _get_inherited_members # 跨模块类定义映射:{class_name: ClassDef_node},供 _get_inherited_members
# 查找其他模块定义的父类(如 exprs.py 的 Name(AST) 查找 base.py 的 AST) # 查找其他模块定义的父类(如 exprs.py 的 Name(AST) 查找 base.py 的 AST)
self._cross_module_class_defs: dict[str, ast.ClassDef] = class_def_map or {} self._cross_module_class_defs: dict[str, ast.ClassDef] = class_def_map or {}
t.configure_platform(self.target_triple) TypeSystem.configure_platform(self.target_triple)
def generate(self, pyi_content: str, src_path: str) -> str: def generate(self, pyi_content: str, src_path: str) -> str:
# 传 src_path:解析失败时报错/回退诊断才带得上来源(否则 vast 记为 <unknown>, # 传 src_path:解析失败时报错/回退诊断才带得上来源(否则 vast 记为 <unknown>,
@@ -83,20 +83,9 @@ class DeclarationGenerator:
if global_typedef_map: if global_typedef_map:
self.typedef_map.update(global_typedef_map) self.typedef_map.update(global_typedef_map)
# 构建 t/c 类型别名映射(from t import CInt as myint) # 类型标记按裸名直接识别、不依赖导入:别名映射表保持为空。
self._t_alias_map: dict[str, type] = {} self._t_alias_map: dict[str, type] = {}
self._t_c_imported_names: dict[str, tuple[str, str]] = {} self._from_import_aliases: dict[str, tuple[str, str]] = {}
for node in ast.iter_child_nodes(tree):
if isinstance(node, ast.ImportFrom):
if node.module in ('t', 'c'):
for alias in node.names:
name: str = alias.name
asname: str = alias.asname or name
self._t_c_imported_names[asname] = (node.module, name)
if node.module == 't':
t_cls: type | None = getattr(t, name, None)
if isinstance(t_cls, type) and issubclass(t_cls, t.CType):
self._t_alias_map[asname] = t_cls
for node in ast.iter_child_nodes(tree): for node in ast.iter_child_nodes(tree):
if isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name): if isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name):
@@ -112,6 +101,8 @@ class DeclarationGenerator:
is_typedef = True is_typedef = True
elif isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.left, ast.Attribute) and hasattr(node.annotation.left, 'attr') and node.annotation.left.attr == 'CTypedef': elif isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.left, ast.Attribute) and hasattr(node.annotation.left, 'attr') and node.annotation.left.attr == 'CTypedef':
is_typedef = True is_typedef = True
elif isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.left, ast.Name) and node.annotation.left.id == 'CTypedef':
is_typedef = True
if is_typedef: if is_typedef:
if node.value: if node.value:
self.typedef_map[var_name] = node.value self.typedef_map[var_name] = node.value
@@ -191,14 +182,18 @@ class DeclarationGenerator:
MultiRetTypes: list[ast.AST] = [] MultiRetTypes: list[ast.AST] = []
if node.decorator_list: if node.decorator_list:
for decorator in node.decorator_list: for decorator in node.decorator_list:
# fail-fast:`@c.CReturn` 装饰器已移除,任何地方出现都必须报错, # fail-fast:`CReturn` 不是内建标记;多返回值请改用 `-> tuple[ty1, ty2, ...]`。
# 不得静默忽略或改写;多返回值请改用 `-> tuple[ty1, ty2, ...]`。 _DecName: str = ''
if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute): if isinstance(decorator, ast.Call):
if decorator.func.attr == 'CReturn': if isinstance(decorator.func, ast.Name):
raise SyntaxError( _DecName = decorator.func.id
f"函数 '{node.name}':`@c.CReturn` 已移除:请改用返回注解 " elif isinstance(decorator.func, ast.Attribute):
f"`-> tuple[ty1, ty2, ...]`(多返回值打包为 struct)" _DecName = decorator.func.attr
) if _DecName == 'CReturn':
raise SyntaxError(
f"函数 '{node.name}':`CReturn` 不是内建标记;请改用返回注解 "
f"`-> tuple[ty1, ty2, ...]`(多返回值打包为 struct)"
)
if node.returns: if node.returns:
if isinstance(node.returns, ast.Subscript) and isinstance(node.returns.value, ast.Name) and node.returns.value.id == 'tuple': 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 slice_node: ast.AST = node.returns.slice
@@ -245,7 +240,7 @@ class DeclarationGenerator:
return self._check_annotation_for_export(node.returns) return self._check_annotation_for_export(node.returns)
def _check_annotation_for_export(self, annotation: ast.AST | None) -> bool: def _check_annotation_for_export(self, annotation: ast.AST | None) -> bool:
"""递归检查类型注解中是否包含 CExport 或 t.State""" """递归检查类型注解中是否包含 CExport 或 State"""
return bool(annotation) and (AnnotationContainsName(annotation, 'CExport') or AnnotationContainsName(annotation, 'State')) return bool(annotation) and (AnnotationContainsName(annotation, 'CExport') or AnnotationContainsName(annotation, 'State'))
def _generate_global_decl(self, node: ast.AnnAssign) -> str | None: def _generate_global_decl(self, node: ast.AnnAssign) -> str | None:
@@ -254,8 +249,8 @@ class DeclarationGenerator:
return None return None
var_name: str = node.target.id var_name: str = node.target.id
# CDefine 是编译期常量,不是变量:stub 里**不得**生成 external global。 # CDefine 是编译期常量,不是变量:stub 里**不得**生成 external global。
# `define X: T = V` 会展开为注解 `T | t.CDefine`,故判据必须能识别**联合形态**—— # `define X: T = V` 会展开为注解 `T | CDefine`,故判据必须能识别**联合形态**——
# 原判据只认裸 `t.CDefine`(注解为单个 Attribute),联合注解会漏判 → # 原判据只认裸 `CDefine`(注解为单个 Attribute),联合注解会漏判 →
# stub 出现 `@X = external global i32` → 其他模块引用它时变成未定义符号(链接失败), # stub 出现 `@X = external global i32` → 其他模块引用它时变成未定义符号(链接失败),
# 且会遮住跨模块 CDefine 常量回退(同名全局优先于常量)。与 _check_annotation_for_export # 且会遮住跨模块 CDefine 常量回退(同名全局优先于常量)。与 _check_annotation_for_export
# 一样用递归判据。 # 一样用递归判据。
@@ -267,11 +262,13 @@ class DeclarationGenerator:
return None return None
if isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.left, ast.Attribute) and hasattr(node.annotation.left, 'attr') and node.annotation.left.attr == 'CTypedef': if isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.left, ast.Attribute) and hasattr(node.annotation.left, 'attr') and node.annotation.left.attr == 'CTypedef':
return None return None
if isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.left, ast.Name) and node.annotation.left.id == 'CTypedef':
return None
if isinstance(node.annotation, ast.List): if isinstance(node.annotation, ast.List):
for elt in node.annotation.elts: 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 in ('CTypedef', 'Callable'):
return None return None
if isinstance(elt, ast.Subscript) and isinstance(elt.value, ast.Attribute) and isinstance(elt.value.value, ast.Name) and elt.value.value.id == 't' and elt.value.attr == 'Callable': if isinstance(elt, ast.Subscript) and isinstance(elt.value, ast.Name) and elt.value.id == 'Callable':
return None return None
VarType: str = self._get_type_str(node.annotation) VarType: str = self._get_type_str(node.annotation)
if VarType.startswith('[0 x ') and node.value: if VarType.startswith('[0 x ') and node.value:
@@ -305,28 +302,28 @@ class DeclarationGenerator:
Returns: Returns:
'enum' | 'union' | 'renum' | 'struct' | 'ctype_marker' | None 'enum' | 'union' | 'renum' | 'struct' | 'ctype_marker' | None
""" """
# 1) 查 t 别名映射(from t import CEnum as en) # 1) 查内建类型别名映射
if base_name in self._t_alias_map: if base_name in self._t_alias_map:
t_cls: type = self._t_alias_map[base_name] t_cls: type = self._t_alias_map[base_name]
if issubclass(t_cls, (t.CEnum, t.REnum)): if issubclass(t_cls, (TypeSystem.CEnum, TypeSystem.REnum)):
return 'renum' if issubclass(t_cls, t.REnum) else 'enum' return 'renum' if issubclass(t_cls, TypeSystem.REnum) else 'enum'
if issubclass(t_cls, t.CUnion): if issubclass(t_cls, TypeSystem.CUnion):
return 'union' return 'union'
if issubclass(t_cls, t.CStruct): if issubclass(t_cls, TypeSystem.CStruct):
return 'struct' return 'struct'
# CType 及其子类(CChar/CInt/CVoid/CPtr 等)是"类型强转"标记, # CType 及其子类(CChar/CInt/CVoid/CPtr 等)是"类型强转"标记,
# 不应被编译为真实结构体,也不应被生成 stub 声明。 # 不应被编译为真实结构体,也不应被生成 stub 声明。
if issubclass(t_cls, t.CType): if issubclass(t_cls, TypeSystem.CType):
return 'ctype_marker' return 'ctype_marker'
# 2) 直接查 t 模块属性 # 2) 直接查内建类型类
t_cls: type | None = getattr(t, base_name, None) t_cls: type | None = getattr(TypeSystem, base_name, None)
if isinstance(t_cls, type) and issubclass(t_cls, t.CType): if isinstance(t_cls, type) and issubclass(t_cls, TypeSystem.CType):
if issubclass(t_cls, (t.CEnum, t.REnum)): if issubclass(t_cls, (TypeSystem.CEnum, TypeSystem.REnum)):
return 'renum' if issubclass(t_cls, t.REnum) else 'enum' return 'renum' if issubclass(t_cls, TypeSystem.REnum) else 'enum'
if issubclass(t_cls, t.CUnion): if issubclass(t_cls, TypeSystem.CUnion):
return 'union' return 'union'
if issubclass(t_cls, t.CStruct): if issubclass(t_cls, TypeSystem.CStruct):
return 'struct' return 'struct'
# CType 及其子类是"类型强转"标记,不编译为结构体。 # CType 及其子类是"类型强转"标记,不编译为结构体。
return 'ctype_marker' return 'ctype_marker'
@@ -453,15 +450,7 @@ class DeclarationGenerator:
is_novtable: bool = False is_novtable: bool = False
if hasattr(node, 'decorator_list') and node.decorator_list: if hasattr(node, 'decorator_list') and node.decorator_list:
for decorator in node.decorator_list: for decorator in node.decorator_list:
if isinstance(decorator, ast.Attribute): if isinstance(decorator, ast.Name):
if getattr(decorator.value, 'id', None) == 't':
if decorator.attr == 'CVTable':
is_cvtable = True
elif decorator.attr == 'Object':
is_cpython_object = True
elif decorator.attr == 'NoVTable':
is_novtable = True
elif isinstance(decorator, ast.Name):
if decorator.id == 'CVTable': if decorator.id == 'CVTable':
is_cvtable = True is_cvtable = True
elif decorator.id == 'Object': elif decorator.id == 'Object':
@@ -485,7 +474,7 @@ class DeclarationGenerator:
base_name = base.value.id base_name = base.value.id
if base_name and not self._is_marker_base(base_name): if base_name and not self._is_marker_base(base_name):
has_parent_class = True has_parent_class = True
# 检查父类是否为 @t.NoVTable(非多态继承) # 检查父类是否为 @NoVTable(非多态继承)
_p_node: ast.ClassDef | None = None _p_node: ast.ClassDef | None = None
for n in ast.iter_child_nodes(self._pyi_tree): for n in ast.iter_child_nodes(self._pyi_tree):
if isinstance(n, ast.ClassDef) and n.name == base_name: if isinstance(n, ast.ClassDef) and n.name == base_name:
@@ -495,16 +484,14 @@ class DeclarationGenerator:
_p_node = self._cross_module_class_defs.get(base_name) _p_node = self._cross_module_class_defs.get(base_name)
if _p_node is not None and hasattr(_p_node, 'decorator_list') and _p_node.decorator_list: if _p_node is not None and hasattr(_p_node, 'decorator_list') and _p_node.decorator_list:
for dec in _p_node.decorator_list: for dec in _p_node.decorator_list:
if isinstance(dec, ast.Attribute) and getattr(dec.value, 'id', None) == 't' and dec.attr == 'NoVTable': if isinstance(dec, ast.Name) and dec.id == 'NoVTable':
parent_is_novtable = True
elif isinstance(dec, ast.Name) and dec.id == 'NoVTable':
parent_is_novtable = True parent_is_novtable = True
break break
# 仅当非 NoVTable 且父类非 NoVTable 时才因继承启用 CVTable # 仅当非 NoVTable 且父类非 NoVTable 时才因继承启用 CVTable
# (@t.NoVTable 标记的类及其子类不使用 vtable,字段展平嵌入) # (@NoVTable 标记的类及其子类不使用 vtable,字段展平嵌入)
if has_parent_class and not is_cvtable and not is_novtable and not parent_is_novtable: if has_parent_class and not is_cvtable and not is_novtable and not parent_is_novtable:
is_cvtable = True is_cvtable = True
# 方法级 virtual(`virtual def m(...)` ⇒ 方法装饰器 @t.CVTable)触发类级 vtable: # 方法级 virtual(`virtual def m(...)` ⇒ 方法装饰器 @CVTable)触发类级 vtable:
# 与 HandlesClassDef._resolve_class_flags / VPC _detect_vtable_status 的 # 与 HandlesClassDef._resolve_class_flags / VPC _detect_vtable_status 的
# `_has_any_func_cvtable` 分支逐条对齐(类级 NoVTable / 无真实父类)。 # `_has_any_func_cvtable` 分支逐条对齐(类级 NoVTable / 无真实父类)。
# 必须在此同步:定义模块按 IsCVTable 在 struct 首部放 vptr,若 stub 不同步, # 必须在此同步:定义模块按 IsCVTable 在 struct 首部放 vptr,若 stub 不同步,
@@ -535,9 +522,7 @@ class DeclarationGenerator:
_base_node = self._cross_module_class_defs.get(base_name) _base_node = self._cross_module_class_defs.get(base_name)
if _base_node is not None and hasattr(_base_node, 'decorator_list') and _base_node.decorator_list: if _base_node is not None and hasattr(_base_node, 'decorator_list') and _base_node.decorator_list:
for dec in _base_node.decorator_list: for dec in _base_node.decorator_list:
if isinstance(dec, ast.Attribute) and getattr(dec.value, 'id', None) == 't' and dec.attr == 'CVTable': if isinstance(dec, ast.Name) and dec.id == 'CVTable':
base_has_vtable = True
elif isinstance(dec, ast.Name) and dec.id == 'CVTable':
base_has_vtable = True base_has_vtable = True
if base_has_vtable: if base_has_vtable:
break break
@@ -836,14 +821,14 @@ class DeclarationGenerator:
init_len = len(item.value.value) + 1 init_len = len(item.value.value) + 1
VarType = f'[{init_len} x {elem_type}]' VarType = f'[{init_len} x {elem_type}]'
else: else:
# 固定大小数组: t.CArray[elem_type, count] → [count x elem_type] # 固定大小数组: CArray[elem_type, count] → [count x elem_type]
if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2: if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2:
elem_type = self._get_type_str(slice_node.elts[0], embedded=True) elem_type = self._get_type_str(slice_node.elts[0], embedded=True)
count_val: int = self._get_const_int(slice_node.elts[1]) count_val: int = self._get_const_int(slice_node.elts[1])
if count_val > 0: if count_val > 0:
VarType = f'[{count_val} x {elem_type}]' VarType = f'[{count_val} x {elem_type}]'
elif isinstance(slice_node, (ast.Attribute, ast.Name, ast.Subscript)): elif isinstance(slice_node, (ast.Attribute, ast.Name, ast.Subscript)):
# 单参数 t.CArray[elem_type] → 指针模式 # 单参数 CArray[elem_type] → 指针模式
elem_type = self._get_type_str(slice_node, embedded=True) elem_type = self._get_type_str(slice_node, embedded=True)
VarType = f'{elem_type}*' VarType = f'{elem_type}*'
member_types.append(VarType) member_types.append(VarType)
@@ -910,15 +895,7 @@ class DeclarationGenerator:
is_novtable: bool = False is_novtable: bool = False
if hasattr(node, 'decorator_list') and node.decorator_list: if hasattr(node, 'decorator_list') and node.decorator_list:
for decorator in node.decorator_list: for decorator in node.decorator_list:
if isinstance(decorator, ast.Attribute): if isinstance(decorator, ast.Name):
if getattr(decorator.value, 'id', None) == 't':
if decorator.attr == 'CVTable':
is_cvtable = True
elif decorator.attr == 'Object':
is_cpython_object = True
elif decorator.attr == 'NoVTable':
is_novtable = True
elif isinstance(decorator, ast.Name):
if decorator.id == 'CVTable': if decorator.id == 'CVTable':
is_cvtable = True is_cvtable = True
elif decorator.id == 'Object': elif decorator.id == 'Object':
@@ -951,9 +928,7 @@ class DeclarationGenerator:
_base_node = self._cross_module_class_defs.get(base_name) _base_node = self._cross_module_class_defs.get(base_name)
if _base_node is not None and hasattr(_base_node, 'decorator_list') and _base_node.decorator_list: if _base_node is not None and hasattr(_base_node, 'decorator_list') and _base_node.decorator_list:
for dec in _base_node.decorator_list: for dec in _base_node.decorator_list:
if isinstance(dec, ast.Attribute) and getattr(dec.value, 'id', None) == 't' and dec.attr == 'CVTable': if isinstance(dec, ast.Name) and dec.id == 'CVTable':
base_has_vtable = True
elif isinstance(dec, ast.Name) and dec.id == 'CVTable':
base_has_vtable = True base_has_vtable = True
if base_has_vtable: if base_has_vtable:
break break
@@ -1071,7 +1046,7 @@ class DeclarationGenerator:
替换策略:使用 i8*(不透明指针)代替 T*,而非具体类型指针。 替换策略:使用 i8*(不透明指针)代替 T*,而非具体类型指针。
原因:跨模块场景中,具体类型指针的 SHA1 前缀可能与导入模块不一致, 原因:跨模块场景中,具体类型指针的 SHA1 前缀可能与导入模块不一致,
导致 TransPyC 类型转换失败。i8* 作为通用指针类型,可安全赋值给 导致 TransPyC 类型转换失败。i8* 作为通用指针类型,可安全赋值给
任何 Class | t.CPtr 注解的变量,运行时行为与 T* 相同(都是指针)。 任何 Class | CPtr 注解的变量,运行时行为与 T* 相同(都是指针)。
Args: Args:
member_types: 基类成员类型字符串列表 member_types: 基类成员类型字符串列表
@@ -1139,28 +1114,28 @@ class DeclarationGenerator:
return len(type_str) - len(type_str.rstrip('*')) return len(type_str) - len(type_str.rstrip('*'))
def _merge_cptr_subscript(self, base_type: str, cptr_sub_type: str) -> str: def _merge_cptr_subscript(self, base_type: str, cptr_sub_type: str) -> str:
"""base | t.CPtr[T] → Ptr^N(base_type),N = t.CPtr[T] 段自身指针层数。 """base | CPtr[T] → Ptr^N(base_type),N = CPtr[T] 段自身指针层数。
与定义侧 VPC TypeGenResolve.vp:2610-2639 同口径:数 CPtr 侧已解析类型的 与定义侧 VPC TypeGenResolve.vp:2610-2639 同口径:数 CPtr 侧已解析类型的
外层 Ptr 嵌套层 N(TypeGenResolve.vp:2616-2632),再给另一侧**纯外包** 外层 Ptr 嵌套层 N(TypeGenResolve.vp:2616-2632),再给另一侧**纯外包**
N 层 Ptr(TypeGenResolve.vp:2633-2639,对 struct 基类型亦不吸收)。 N 层 Ptr(TypeGenResolve.vp:2633-2639,对 struct 基类型亦不吸收)。
与 LLVMTypeMapper._resolve_bitor 的 IsCPtrSubscriptNode 分支(_add_pointer_levels 与 LLVMTypeMapper._resolve_bitor 的 IsCPtrSubscriptNode 分支(_add_pointer_levels
逐层追加)同口径,对同一批形态两处结果一致。 逐层追加)同口径,对同一批形态两处结果一致。
注:裸 | t.CPtr(非下标标记)仍走上方的 %"..."* 吸收分支,与本节无关。 注:裸 | CPtr(非下标标记)仍走上方的 %"..."* 吸收分支,与本节无关。
""" """
return base_type + '*' * self._ptr_level_of(cptr_sub_type) return base_type + '*' * self._ptr_level_of(cptr_sub_type)
def _ptr_subscript_type_str(self, annotation: ast.Subscript) -> str: def _ptr_subscript_type_str(self, annotation: ast.Subscript) -> str:
"""指针下标(rawptr[T] / t.CPtr[T] / 裸名 CPtr[T],判据见 """指针下标(rawptr[T] / CPtr[T] / 裸名 CPtr[T],判据见
SymbolUtils.IsPtrSubscriptNode)→ LLVM 类型串。 SymbolUtils.IsPtrSubscriptNode)→ LLVM 类型串。
与定义端同源:SymbolUtils.DesugarPtrSubscriptToUnion 把三者折叠为等价 与定义端同源:SymbolUtils.DesugarPtrSubscriptToUnion 把三者折叠为等价
联合写法 `T | t.CPtr` 后交 HandlesTypeMerge.MergeTypes,指针层数由 联合写法 `T | CPtr` 后交 HandlesTypeMerge.MergeTypes,指针层数由
_MergeAllComponentTypes 的"struct 基类型吸收一层 CPtr"决定 —— 裸类引用 _MergeAllComponentTypes 的"struct 基类型吸收一层 CPtr"决定 —— 裸类引用
的非 embedded 形式本身即指针('%"sha1.X"*'),再包一层会被吸收 → 结果 的非 embedded 形式本身即指针('%"sha1.X"*'),再包一层会被吸收 → 结果
就是该指针本身;其余类型(标量 / 已是指针的 typedef / 泛型容器特化 / 就是该指针本身;其余类型(标量 / 已是指针的 typedef / 泛型容器特化 /
联合写法 / 嵌套指针下标)逐层外包。rawptr[...] 与 t.CPtr[...] 共用本条 联合写法 / 嵌套指针下标)逐层外包。rawptr[...] 与 CPtr[...] 共用本条
规则(此前 t.CPtr[list[X]] 在此得 list[X]**、rawptr[list[X]] 得 规则(此前 CPtr[list[X]] 在此得 list[X]**、rawptr[list[X]] 得
list[X]*,同一指针语义两种结果)。 list[X]*,同一指针语义两种结果)。
""" """
inner: ast.AST = annotation.slice inner: ast.AST = annotation.slice
@@ -1172,20 +1147,20 @@ class DeclarationGenerator:
return f'{inner_type}*' return f'{inner_type}*'
def _is_bare_class_ref_annotation(self, inner: ast.AST, inner_type: str) -> bool: def _is_bare_class_ref_annotation(self, inner: ast.AST, inner_type: str) -> bool:
"""节点是否为"裸类引用"(本身即指针 → 吸收一层 t.CPtr)。 """节点是否为"裸类引用"(本身即指针 → 吸收一层 CPtr)。
与 _get_type_str 的既有约定一致:类引用的**非** embedded 形式本身就是 与 _get_type_str 的既有约定一致:类引用的**非** embedded 形式本身就是
指针('%"sha1.X"*'),所以 `AST | t.CPtr` 合并后仍是该指针(定义端 指针('%"sha1.X"*'),所以 `AST | CPtr` 合并后仍是该指针(定义端
_MergeAllComponentTypes 的 struct 吸收)。联合写法(ast.BinOp)与指针 _MergeAllComponentTypes 的 struct 吸收)。联合写法(ast.BinOp)与指针
下标(rawptr[...] / t.CPtr[...])不是裸类引用——它们已自带指针层数, 下标(rawptr[...] / CPtr[...])不是裸类引用——它们已自带指针层数,
须逐层外包(rawptr[Node] | t.CPtr → Node**、ast.AST | t.CPtr | t.CPtr 须逐层外包(rawptr[Node] | CPtr → Node**、ast.AST | CPtr | CPtr
→ AST**,与定义端整体拉平后只吸收一次 CPtr 一致)。 → AST**,与定义端整体拉平后只吸收一次 CPtr 一致)。
**例外:纯装饰器标记联合**。`t.CExtern | X` / `t.CExport | X` / `t.State | X` **例外:纯装饰器标记联合**。`CExtern | X` / `CExport | X` / `State | X`
(vpi 记录的模块级全局就是这种写法,见 lib.Phase.Phase1.__init__.vpi 的 (vpi 记录的模块级全局就是这种写法,见 lib.Phase.Phase1.__init__.vpi 的
`_mbuddy: t.CExtern | memhub.MemBuddy | t.CPtr`)里标记侧展开为**空串** `_mbuddy: CExtern | memhub.MemBuddy | CPtr`)里标记侧展开为**空串**
(CTypeRegistry.NameToLLVM('CExtern') == ''),该联合语义上仍是 X 这一个 (CTypeRegistry.NameToLLVM('CExtern') == ''),该联合语义上仍是 X 这一个
裸类引用,故 `t.CExtern | X | t.CPtr` 必须与 `X | t.CPtr` 同判(吸收)—— 裸类引用,故 `CExtern | X | CPtr` 必须与 `X | CPtr` 同判(吸收)——
对齐 VPC TypeGenResolve 的第 3 条语义「ActualType | DecoratorMarker → 对齐 VPC TypeGenResolve 的第 3 条语义「ActualType | DecoratorMarker →
ActualType」。漏此判据时联合被当成"已自带指针层数的左值"而多外包一层: ActualType」。漏此判据时联合被当成"已自带指针层数的左值"而多外包一层:
声明端 `%"sha1.X"**` 与定义端 `%"sha1.X"*` 差一层,消费模块里 声明端 `%"sha1.X"**` 与定义端 `%"sha1.X"*` 差一层,消费模块里
@@ -1219,6 +1194,10 @@ class DeclarationGenerator:
return 'void' return 'void'
if annotation.id in ('str', 'bytes'): if annotation.id in ('str', 'bytes'):
return 'i8*' return 'i8*'
# 值引用参数标记(CRef = `&T`、CTempRef = `&temp T`,非真实类):按
# CPtr 同形的一层指针(i8*)参与联合合并(`T | CRef` → T*)。
if annotation.id in ('CRef', 'CTempRef'):
return 'i8*'
llvm_type: str | None = CTypeRegistry.NameToLLVM(annotation.id) llvm_type: str | None = CTypeRegistry.NameToLLVM(annotation.id)
if llvm_type is not None: if llvm_type is not None:
return llvm_type return llvm_type
@@ -1249,7 +1228,7 @@ class DeclarationGenerator:
if annotation.id in self.typedef_map: if annotation.id in self.typedef_map:
resolved_str: str = self._get_type_str(self.typedef_map[annotation.id], embedded=embedded) resolved_str: str = self._get_type_str(self.typedef_map[annotation.id], embedded=embedded)
return resolved_str return resolved_str
# 检查 t 类型别名(from t import CInt as myint) # 检查内建类型别名
if annotation.id in self._t_alias_map: if annotation.id in self._t_alias_map:
t_cls: type = self._t_alias_map[annotation.id] t_cls: type = self._t_alias_map[annotation.id]
llvm: str | None = CTypeRegistry.CTypeToLLVM(t_cls) llvm: str | None = CTypeRegistry.CTypeToLLVM(t_cls)
@@ -1262,10 +1241,6 @@ class DeclarationGenerator:
from lib.core.TypeAnnotationResolver import TypeAnnotationResolver as _DG_TAR from lib.core.TypeAnnotationResolver import TypeAnnotationResolver as _DG_TAR
_dg_bv: str | None = _DG_TAR.builtins_typedef_value(annotation.id) _dg_bv: str | None = _DG_TAR.builtins_typedef_value(annotation.id)
if _dg_bv: if _dg_bv:
if _dg_bv.startswith('t.'):
_dg_llvm: str | None = CTypeRegistry.NameToLLVM(_dg_bv[2:])
if _dg_llvm:
return _dg_llvm
_dg_node: ast.AST | None = None _dg_node: ast.AST | None = None
try: try:
_dg_node = ast.parse(_dg_bv, '<DeclarationGenerator:type_expr>', mode='eval').body _dg_node = ast.parse(_dg_bv, '<DeclarationGenerator:type_expr>', mode='eval').body
@@ -1280,8 +1255,8 @@ class DeclarationGenerator:
return f'{sname}*' return f'{sname}*'
elif isinstance(annotation, ast.Attribute): elif isinstance(annotation, ast.Attribute):
attr_name: str = annotation.attr if hasattr(annotation, 'attr') else '' attr_name: str = annotation.attr if hasattr(annotation, 'attr') else ''
# 值引用参数标记(CRef = `&T`、CTempRef = `&temp T`,非真实类):按 t.CPtr # 值引用参数标记(CRef = `&T`、CTempRef = `&temp T`,非真实类):按 CPtr
# 同形的「一层指针 = i8*」参与联合合并(`T | t.CRef` → T*),保证跨模块 # 同形的「一层指针 = i8*」参与联合合并(`T | CRef` → T*),保证跨模块
# .vpi 声明端类型与定义端 _ctype_to_llvm 一致。 # .vpi 声明端类型与定义端 _ctype_to_llvm 一致。
if attr_name in ('CRef', 'CTempRef'): if attr_name in ('CRef', 'CTempRef'):
return 'i8*' return 'i8*'
@@ -1295,15 +1270,15 @@ class DeclarationGenerator:
# 定义端以扁平名 `{外类}_{内类}` 发射(见 HandlesClassDef._EmitNestedClassDefs), # 定义端以扁平名 `{外类}_{内类}` 发射(见 HandlesClassDef._EmitNestedClassDefs),
# 故此处按扁平名拼类型;命中与否由 struct_names 里是否存在该扁平名裁决 # 故此处按扁平名拼类型;命中与否由 struct_names 里是否存在该扁平名裁决
# (不存在即维持下方既有路径,不改变任何既有类型名)。 # (不存在即维持下方既有路径,不改变任何既有类型名)。
if module_name and module_name != 't' and module_name != 'c': if module_name:
NestedName: str = f'{module_name}_{attr_name}' NestedName: str = f'{module_name}_{attr_name}'
if NestedName in self.struct_names: if NestedName in self.struct_names:
NestedSha1: str | None = self.struct_sha1_map.get(NestedName, self.module_sha1) NestedSha1: str | None = self.struct_sha1_map.get(NestedName, self.module_sha1)
NestedStr: str = f'%"{NestedSha1}.{NestedName}"' if NestedSha1 else f'%struct.{NestedName}' NestedStr: str = f'%"{NestedSha1}.{NestedName}"' if NestedSha1 else f'%struct.{NestedName}'
return NestedStr if embedded else f'{NestedStr}*' return NestedStr if embedded else f'{NestedStr}*'
if (module_name == 't' and attr_name == 'State') or attr_name == 'State': if attr_name == 'State':
return '' return ''
if (module_name == 't' and attr_name == 'Callable') or attr_name == 'Callable': if attr_name == 'Callable':
return 'i8*' return 'i8*'
llvm_type: str | None = CTypeRegistry.NameToLLVM(attr_name) llvm_type: str | None = CTypeRegistry.NameToLLVM(attr_name)
if llvm_type is not None: if llvm_type is not None:
@@ -1348,23 +1323,23 @@ class DeclarationGenerator:
return right_type if right_type not in ('', 'void') else (left_type or right_type) return right_type if right_type not in ('', 'void') else (left_type or right_type)
if right_type in ('', 'void'): if right_type in ('', 'void'):
return left_type return left_type
# t.CPtr (i8*) 与 left 合并:对齐 Phase 2 _MergeAllComponentTypes 的 # CPtr (i8*) 与 left 合并:对齐 Phase 2 _MergeAllComponentTypes 的
# "first CPtr absorption" 语义:struct | t.CPtr → struct*(吸收,struct 变量默认是指针)。 # "first CPtr absorption" 语义:struct | CPtr → struct*(吸收,struct 变量默认是指针)。
# 但对于本身已是指针的类型(如 bytes=str=i8*),bytes | t.CPtr → i8**(不吸收)。 # 但对于本身已是指针的类型(如 bytes=str=i8*),bytes | CPtr → i8**(不吸收)。
# 例外:LLVM 聚合数组([N x T],字符串以 '[' 开头)不可再外包指针层 → i8*。 # 例外:LLVM 聚合数组([N x T],字符串以 '[' 开头)不可再外包指针层 → i8*。
# 注:具名泛型特化(%"mod.list[X]"*)**不**走此回退——stub 已由 # 注:具名泛型特化(%"mod.list[X]"*)**不**走此回退——stub 已由
# _collect_undefined_type_decls 为其补 opaque 声明,保留名字才能与 define 端 # _collect_undefined_type_decls 为其补 opaque 声明,保留名字才能与 define 端
# 的 %"mod.list[ast.ASTptr]"* 逐字一致(原 `'[' in left_type` 会把 # 的 %"mod.list[ast.ASTptr]"* 逐字一致(原 `'[' in left_type` 会把
# list[X] | t.CPtr 一并退化成 i8*,与定义端 %"mod.list[X]"* 不一致)。 # list[X] | CPtr 一并退化成 i8*,与定义端 %"mod.list[X]"* 不一致)。
if right_type == 'i8*': if right_type == 'i8*':
if left_type[:1] == '[': if left_type[:1] == '[':
return 'i8*' return 'i8*'
if left_type in ('', 'void'): if left_type in ('', 'void'):
return 'i8*' return 'i8*'
# 吸收仅对"裸类引用"成立(其非 embedded 形式本身即指针): # 吸收仅对"裸类引用"成立(其非 embedded 形式本身即指针):
# ast.AST | t.CPtr → %"sha1.AST"*。已自带指针层数的左值 # ast.AST | CPtr → %"sha1.AST"*。已自带指针层数的左值
# (rawptr[...] / t.CPtr[...] 下标 / 联合写法)须逐层外包: # (rawptr[...] / CPtr[...] 下标 / 联合写法)须逐层外包:
# rawptr[Node] | t.CPtr → Node**、ast.AST | t.CPtr | t.CPtr → AST** # rawptr[Node] | CPtr → Node**、ast.AST | CPtr | CPtr → AST**
# ——与定义端 _CollectAllOperandTypes 整体拉平、只吸收一次 CPtr # ——与定义端 _CollectAllOperandTypes 整体拉平、只吸收一次 CPtr
# (_MergeAllComponentTypes 的 base_ptr_count>0 分支)一致。 # (_MergeAllComponentTypes 的 base_ptr_count>0 分支)一致。
if self._is_bare_class_ref_annotation(annotation.left, left_type): if self._is_bare_class_ref_annotation(annotation.left, left_type):
@@ -1372,20 +1347,20 @@ class DeclarationGenerator:
if '*' in left_type: if '*' in left_type:
return f'{left_type}*' return f'{left_type}*'
return f'{left_type}*' return f'{left_type}*'
# X | t.CPtr[T](T 为下标段,非裸标记):CPtr 侧贡献自身指针层数 N, # X | CPtr[T](T 为下标段,非裸标记):CPtr 侧贡献自身指针层数 N,
# 另一侧外包 N 层(Ptr^N(X));左右两侧写法对称(定义侧 VPC # 另一侧外包 N 层(Ptr^N(X));左右两侧写法对称(定义侧 VPC
# TypeGenResolve.vp:2604-2609 亦两侧皆判)。必须先于下方 # TypeGenResolve.vp:2604-2609 亦两侧皆判)。必须先于下方
# "'*' in left_type → 直接返回左值":否则左值本身已是指针 # "'*' in left_type → 直接返回左值":否则左值本身已是指针
# (BYTEPTR⇒i8*)时会吞掉右段层数(BYTEPTR | t.CPtr[t.CPtr] 改前得 i8*)。 # (BYTEPTR⇒i8*)时会吞掉右段层数(BYTEPTR | CPtr[CPtr] 改前得 i8*)。
# LLVM 聚合([N x T] / { ... })不可再外包指针层,保持既有行为(只报不改)。 # LLVM 聚合([N x T] / { ... })不可再外包指针层,保持既有行为(只报不改)。
if IsCPtrSubscriptNode(annotation.right) and left_type[:1] not in ('[', '{'): if IsCPtrSubscriptNode(annotation.right) and left_type[:1] not in ('[', '{'):
return self._merge_cptr_subscript(left_type, right_type) return self._merge_cptr_subscript(left_type, right_type)
if IsCPtrSubscriptNode(annotation.left) and right_type[:1] not in ('[', '{'): if IsCPtrSubscriptNode(annotation.left) and right_type[:1] not in ('[', '{'):
return self._merge_cptr_subscript(right_type, left_type) return self._merge_cptr_subscript(right_type, left_type)
# t.CPtr 裸标记在左侧(t.CPtr | X):与右侧写法(X | t.CPtr,见上) # CPtr 裸标记在左侧(CPtr | X):与右侧写法(X | CPtr,见上)
# 完全对称。缺此分支时左值 i8* 会吞掉右侧的指针层数: # 完全对称。缺此分支时左值 i8* 会吞掉右侧的指针层数:
# t.CPtr | rawptr[Node] 声明端曾得 i8*,而定义端为 %"sha1.Node"**(差一层)。 # CPtr | rawptr[Node] 声明端曾得 i8*,而定义端为 %"sha1.Node"**(差一层)。
# 仅对裸标记 t.CPtr 生效(left 为 t.CPtr[T] 下标走上一条分支; # 仅对裸标记 CPtr 生效(left 为 CPtr[T] 下标走上一条分支;
# str/bytes 等其它 i8* 左值不受影响)。 # str/bytes 等其它 i8* 左值不受影响)。
if IsCPtrNode(annotation.left) and right_type[:1] not in ('[', '{'): if IsCPtrNode(annotation.left) and right_type[:1] not in ('[', '{'):
if self._is_bare_class_ref_annotation(annotation.right, right_type): if self._is_bare_class_ref_annotation(annotation.right, right_type):
@@ -1397,24 +1372,24 @@ class DeclarationGenerator:
return right_type return right_type
return left_type return left_type
elif isinstance(annotation, ast.Subscript): elif isinstance(annotation, ast.Subscript):
# 指针下标(rawptr[T] / t.CPtr[T] / 裸名 CPtr[T] / 导入别名 X[T],以及带 # 指针下标(rawptr[T] / CPtr[T] / 裸名 CPtr[T] / 导入别名 X[T],以及带
# 模块前缀书写的 X.CPtr[T])≡ 源码联合写法 `T | t.CPtr`:与定义端 # 模块前缀书写的 X.CPtr[T])≡ 源码联合写法 `T | CPtr`:与定义端
# **同一判据**(SymbolUtils.IsPtrSubscriptNode,别名经本模块的 # **同一判据**(SymbolUtils.IsPtrSubscriptNode,别名经本模块的
# _t_c_imported_names 表解析 X→CPtr)+ 同一层数规则 # _from_import_aliases 表解析 X→CPtr)+ 同一层数规则
# (_ptr_subscript_type_str:裸类引用吸收一层、其余逐层外包),内层 T # (_ptr_subscript_type_str:裸类引用吸收一层、其余逐层外包),内层 T
# 照常解析(跨模块类由 struct_sha1_map 补 SHA1 前缀)。此前 rawptr[T] # 照常解析(跨模块类由 struct_sha1_map 补 SHA1 前缀)。此前 rawptr[T]
# 在此退化成 i8*,t.CPtr[T] 走的是"embedded + 追加一层"的独立分支: # 在此退化成 i8*,CPtr[T] 走的是"embedded + 追加一层"的独立分支:
# 非同一规则,且对泛型容器特化多出一层(t.CPtr[list[X]] 得 list[X]**, # 非同一规则,且对泛型容器特化多出一层(CPtr[list[X]] 得 list[X]**,
# 而 rawptr[list[X]] 得 list[X]*)。 # 而 rawptr[list[X]] 得 list[X]*)。
ValueIsCPtr: bool = ( ValueIsCPtr: bool = (
(isinstance(annotation.value, ast.Attribute) and annotation.value.attr == 'CPtr') (isinstance(annotation.value, ast.Attribute) and annotation.value.attr == 'CPtr')
or (isinstance(annotation.value, ast.Name) and annotation.value.id == 'CPtr') or (isinstance(annotation.value, ast.Name) and annotation.value.id == 'CPtr')
) )
if (IsPtrSubscriptNode(annotation, TCAliasMap=self._t_c_imported_names) if (IsPtrSubscriptNode(annotation, TCAliasMap=self._from_import_aliases)
or (ValueIsCPtr and isinstance(annotation.slice, (ast.Attribute, ast.Name, ast.Subscript)))): or (ValueIsCPtr and isinstance(annotation.slice, (ast.Attribute, ast.Name, ast.Subscript)))):
return self._ptr_subscript_type_str(annotation) return self._ptr_subscript_type_str(annotation)
# 内建裸名函数指针构造子 callable[...] / Callable[...]:与 Attribute 分支的 # 内建裸名函数指针构造子 callable[...] / Callable[...]:与 Attribute 分支的
# t.Callable[...] 逐点等价(同为 i8*)。缺此分支时落到下方 Name 泛型特化 / # Callable[...] 逐点等价(同为 i8*)。缺此分支时落到下方 Name 泛型特化 /
# 兜底返回 'i32'(现场 Repl.vp:307 `ReplFragFn: callable[[rawptr], int]` # 兜底返回 'i32'(现场 Repl.vp:307 `ReplFragFn: callable[[rawptr], int]`
# 声明成 i32 全局 ⇒ 赋 i8* 触发「指针隐式转整数」)。 # 声明成 i32 全局 ⇒ 赋 i8* 触发「指针隐式转整数」)。
if isinstance(annotation.value, ast.Name) and (annotation.value.id == 'callable' or annotation.value.id == 'Callable'): if isinstance(annotation.value, ast.Name) and (annotation.value.id == 'callable' or annotation.value.id == 'Callable'):
@@ -1424,10 +1399,10 @@ class DeclarationGenerator:
return f'[{self._get_const_int(annotation.slice)} x i8]' return f'[{self._get_const_int(annotation.slice)} x i8]'
if isinstance(annotation.slice, ast.Constant) and isinstance(annotation.slice.value, int): if isinstance(annotation.slice, ast.Constant) and isinstance(annotation.slice.value, int):
return f'[{annotation.slice.value} x {base}]' return f'[{annotation.slice.value} x {base}]'
# 处理 t.CArray[elem_type, count] / rawarray[elem_type, count] / array[elem_type, count] # 处理 CArray[elem_type, count] / rawarray[elem_type, count] / array[elem_type, count]
# 注解 → [count x elem_type] # 注解 → [count x elem_type]
# 支持 t.CArray (ast.Attribute)、CArray/rawarray/array (ast.Name) 三种写法 # 支持 CArray (ast.Attribute)、CArray/rawarray/array (ast.Name) 三种写法
# (array 为本轮新增的内建软关键字,与 t.CArray 逐点等价) # (array 为本轮新增的内建软关键字,与 CArray 逐点等价)
ValueIsCArray: bool = ( ValueIsCArray: bool = (
(isinstance(annotation.value, ast.Attribute) and annotation.value.attr == 'CArray') (isinstance(annotation.value, ast.Attribute) and annotation.value.attr == 'CArray')
or (isinstance(annotation.value, ast.Name) and annotation.value.id in ('CArray', 'rawarray', 'array')) or (isinstance(annotation.value, ast.Name) and annotation.value.id in ('CArray', 'rawarray', 'array'))
@@ -1442,7 +1417,7 @@ class DeclarationGenerator:
# count 为 None 或 0 → 零长度数组(外部符号) # count 为 None 或 0 → 零长度数组(外部符号)
return f'[0 x {ElemType}]' return f'[0 x {ElemType}]'
elif isinstance(SliceNode, (ast.Attribute, ast.Name, ast.Subscript)): elif isinstance(SliceNode, (ast.Attribute, ast.Name, ast.Subscript)):
# 单参数 t.CArray[elem_type]:与 t.CArray[elem_type, None] 语义统一为 # 单参数 CArray[elem_type]:与 CArray[elem_type, None] 语义统一为
# "长度自动推导数组"。此处无初始化字面量可推导 → 与 ,None 分支同用 # "长度自动推导数组"。此处无初始化字面量可推导 → 与 ,None 分支同用
# [0 x elem] 占位,真实长度由 _generate_global_decl 按初始化字面量 # [0 x elem] 占位,真实长度由 _generate_global_decl 按初始化字面量
# (List 长度 / str 长度+1) 修正。 # (List 长度 / str 长度+1) 修正。
@@ -1462,7 +1437,7 @@ class DeclarationGenerator:
# 实参串走 SymbolUtils.ResolveGenericTypeArgStr(与定义端 # 实参串走 SymbolUtils.ResolveGenericTypeArgStr(与定义端
# _mangle_generic_class_name 同一规则源):此前只认 Name / Name-Tuple # _mangle_generic_class_name 同一规则源):此前只认 Name / Name-Tuple
# 实参,Attribute(ast.AST)/ Subscript(rawptr[...])/ BinOp # 实参,Attribute(ast.AST)/ Subscript(rawptr[...])/ BinOp
# (X | t.CPtr)/ 混合 Tuple 一律退回未特化的 %"...list"*, # (X | CPtr)/ 混合 Tuple 一律退回未特化的 %"...list"*,
# 与 define 端发射的 %"<mod>.list[ast.ASTptr]" 不一致 # 与 define 端发射的 %"<mod>.list[ast.ASTptr]" 不一致
# (Undefined method / 签名错位)。 # (Undefined method / 签名错位)。
# 内建容器(non_struct_types)之外,**用户泛型类**同样特化:判据 # 内建容器(non_struct_types)之外,**用户泛型类**同样特化:判据
@@ -1482,7 +1457,7 @@ class DeclarationGenerator:
gc_mangled: list[str] = [ gc_mangled: list[str] = [
ResolveGenericTypeArgStr( ResolveGenericTypeArgStr(
gc_node, gc_node,
TCAliasMap=self._t_c_imported_names, TCAliasMap=self._from_import_aliases,
StructSha1Map=self.struct_sha1_map) StructSha1Map=self.struct_sha1_map)
for gc_node in gc_nodes] for gc_node in gc_nodes]
gc_spec: str = gc_name + '[' + ']['.join(gc_mangled) + ']' gc_spec: str = gc_name + '[' + ']['.join(gc_mangled) + ']'
@@ -1496,7 +1471,7 @@ class DeclarationGenerator:
gc_sha1: str | None = self.struct_sha1_map.get(gc_name, self.module_sha1) gc_sha1: str | None = self.struct_sha1_map.get(gc_name, self.module_sha1)
gc_sname: str = f'%"{gc_sha1}.{gc_spec}"' if gc_sha1 else f'%struct.{gc_spec}' gc_sname: str = f'%"{gc_sha1}.{gc_spec}"' if gc_sha1 else f'%struct.{gc_spec}'
# 一律以指针引用(不区分 embedded):定义端对嵌入式泛型容器 # 一律以指针引用(不区分 embedded):定义端对嵌入式泛型容器
# (字段 / t.CArray 元素)用不透明指针(实测字段 i8*,见 # (字段 / CArray 元素)用不透明指针(实测字段 i8*,见
# FieldForms/FieldBox/FieldOrder),嵌入 unsized opaque # FieldForms/FieldBox/FieldOrder),嵌入 unsized opaque
# 结构体值会让字段/元素偏移错位;非 embedded(参数/返回) # 结构体值会让字段/元素偏移错位;非 embedded(参数/返回)
# 亦与定义端同为指针 # 亦与定义端同为指针
@@ -1539,9 +1514,7 @@ class DeclarationGenerator:
return f'{sname}*' return f'{sname}*'
return 'i8*' return 'i8*'
elif isinstance(annotation, ast.Call): elif isinstance(annotation, ast.Call):
if isinstance(annotation.func, ast.Name) and annotation.func.id == 'callable': if isinstance(annotation.func, ast.Name) and annotation.func.id in ('callable', 'Callable'):
return 'i8*'
if isinstance(annotation.func, ast.Attribute) and annotation.func.attr == 'Callable':
return 'i8*' return 'i8*'
return 'i32' return 'i32'
+9 -7
View File
@@ -11,7 +11,7 @@ from lib.Projectrans.DeclarationGenerator import DeclarationGenerator
from lib.core.VLogger import get_logger as _vlog from lib.core.VLogger import get_logger as _vlog
from lib.core.SymbolUtils import ExpandSoftKeywords from lib.core.SymbolUtils import ExpandSoftKeywords
from lib.constants.config import mode as _ConfigMode from lib.constants.config import mode as _ConfigMode
from lib.includes import t from lib.core import TypeSystem
from StubGen import PythonToStubConverter from StubGen import PythonToStubConverter
# 全局缓存目录(不被 --clean 清除),用于缓存库文件的 .pyi / .stub.ll / .doc.json # 全局缓存目录(不被 --clean 清除),用于缓存库文件的 .pyi / .stub.ll / .doc.json
@@ -387,6 +387,8 @@ class Phase1Generator:
is_typedef = True is_typedef = True
elif isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.left, ast.Attribute) and hasattr(node.annotation.left, 'attr') and node.annotation.left.attr == 'CTypedef': elif isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.left, ast.Attribute) and hasattr(node.annotation.left, 'attr') and node.annotation.left.attr == 'CTypedef':
is_typedef = True is_typedef = True
elif isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.left, ast.Name) and node.annotation.left.id == 'CTypedef':
is_typedef = True
if is_typedef and node.value and var_name not in typedef_map: if is_typedef and node.value and var_name not in typedef_map:
typedef_map[var_name] = node.value typedef_map[var_name] = node.value
except Exception as _e: except Exception as _e:
@@ -687,13 +689,13 @@ class Phase1Generator:
exception_names: set[str] = set() exception_names: set[str] = set()
struct_sha1_map: dict[str, str] = {} struct_sha1_map: dict[str, str] = {}
class_def_map: dict[str, ast.ClassDef] = {} class_def_map: dict[str, ast.ClassDef] = {}
# 预先收集所有 CType 子类名称(来自 t 模块和别名映射), # 预先收集所有 CType 子类名称(来自内建类型模型),
# 用于在 struct 注册表中跳过"类型强转"标记类。 # 用于在 struct 注册表中跳过"类型强转"标记类。
ctype_marker_names: set[str] = set() ctype_marker_names: set[str] = set()
for attr_name in dir(t): for attr_name in dir(TypeSystem):
t_cls: type | None = getattr(t, attr_name, None) t_cls: type | None = getattr(TypeSystem, attr_name, None)
if isinstance(t_cls, type) and issubclass(t_cls, t.CType) and t_cls is not t.CType: if isinstance(t_cls, type) and issubclass(t_cls, TypeSystem.CType) and t_cls is not TypeSystem.CType:
if not issubclass(t_cls, (t.CEnum, t.REnum, t.CUnion, t.CStruct)): if not issubclass(t_cls, (TypeSystem.CEnum, TypeSystem.REnum, TypeSystem.CUnion, TypeSystem.CStruct)):
ctype_marker_names.add(t_cls.__name__) ctype_marker_names.add(t_cls.__name__)
ctype_marker_names.add(attr_name) ctype_marker_names.add(attr_name)
valid_sha1_keys: set[str] = set(self.sha1_map.keys()) valid_sha1_keys: set[str] = set(self.sha1_map.keys())
@@ -742,7 +744,7 @@ class Phase1Generator:
elif base.id in ctype_marker_names: elif base.id in ctype_marker_names:
is_ctype_marker = True is_ctype_marker = True
break break
# 也检查装饰器形式 @t.CEnum / @t.REnum # 也检查装饰器形式 @CEnum / @REnum
if not is_enum and not is_renum and not is_exception and not is_ctype_marker and hasattr(node, 'decorator_list') and node.decorator_list: if not is_enum and not is_renum and not is_exception and not is_ctype_marker and hasattr(node, 'decorator_list') and node.decorator_list:
for deco in node.decorator_list: for deco in node.decorator_list:
deco_attr: str | None = None deco_attr: str | None = None
+13 -16
View File
@@ -17,7 +17,7 @@ from lib.core.VLogger import get_logger as _vlog
from lib.constants.config import mode as _config_mode from lib.constants.config import mode as _config_mode
from lib.core.Handles.HandlesBase import CTypeInfo from lib.core.Handles.HandlesBase import CTypeInfo
from lib.core.SymbolData import ModuleSymbols from lib.core.SymbolData import ModuleSymbols
from lib.includes import t from lib.core import TypeSystem
from lib.core.SymbolUtils import AnnotationContainsName, ExpandSoftKeywords, DefineDeclIntTypeFromAnnotation from lib.core.SymbolUtils import AnnotationContainsName, ExpandSoftKeywords, DefineDeclIntTypeFromAnnotation
from lib.core.SymbolUtils import ClassHasFuncLevelCVTable, IsVtableSlotMethod 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, _check_annotation_for_export, find_reachable_files_from_entries, topological_sort_files, parse_python_file
@@ -609,11 +609,11 @@ def _ExtractCDefineConstantsFromPyi(pyi_path: str, all_dc: dict[str, object],
"""从 .pyi 文件中提取 CDefine 常量到 all_dc。文件不存在时静默跳过。 """从 .pyi 文件中提取 CDefine 常量到 all_dc。文件不存在时静默跳过。
治本修复:原实现只支持 ast.Constant 和 float() 调用, 治本修复:原实现只支持 ast.Constant 和 float() 调用,
无法处理 t.CUnsignedLong(-11)(ast.Call)和 无法处理 CUnsignedLong(-11)(ast.Call)和
FOREGROUND_GREEN | FOREGROUND_INTENSITY(ast.BinOp)等复杂表达式。 FOREGROUND_GREEN | FOREGROUND_INTENSITY(ast.BinOp)等复杂表达式。
现使用 ConstEvaluator.eval_full 统一求值,支持: 现使用 ConstEvaluator.eval_full 统一求值,支持:
- ast.Constant: 简单常量 (0x0002) - ast.Constant: 简单常量 (0x0002)
- ast.Call: 类型构造 (t.CUnsignedLong(-11)) - ast.Call: 类型构造 (CUnsignedLong(-11))
- ast.BinOp: 位运算 (FOREGROUND_RED | FOREGROUND_GREEN) - ast.BinOp: 位运算 (FOREGROUND_RED | FOREGROUND_GREEN)
- ast.UnaryOp: 一元运算 (-11) - ast.UnaryOp: 一元运算 (-11)
- ast.Name: 引用其他 CDefine 常量 - ast.Name: 引用其他 CDefine 常量
@@ -643,10 +643,10 @@ def _ExtractCDefineConstantsFromPyi(pyi_path: str, all_dc: dict[str, object],
if AnnotationContainsName(node.annotation, 'CDefine') and node.value: if AnnotationContainsName(node.annotation, 'CDefine') and node.value:
val: object = ConstEvaluator.eval_full(node.value, ctx) val: object = ConstEvaluator.eval_full(node.value, ctx)
if val is None and isinstance(node.value, ast.Call) and len(node.value.args) == 1: if val is None and isinstance(node.value, ast.Call) and len(node.value.args) == 1:
# 类型构造的**裸别名**形态(如 `DWORD(-11)`,非 `t.CUnsignedLong(-11)`): # 类型构造的**裸别名**形态(如 `DWORD(-11)`,非 `CUnsignedLong(-11)`):
# eval_full 只认 `t.X(...)` / `from t import X`(见 ConstEvaluator # eval_full 只认 `X(...)` / `from t import X`(见 ConstEvaluator
# _eval_compile_time_call),裸 typedef 别名既不在 _t_module 也不在 # _eval_compile_time_call),裸 typedef 别名既不在 _t_module 也不在
# mock ctx 的 _t_type_symbols 里 → 返回 None → 该常量被整条丢弃。 # mock ctx 的 _builtin_type_symbols 里 → 返回 None → 该常量被整条丢弃。
# 现场:win32file.vp 的 STD_INPUT/OUTPUT/ERROR_HANDLE 是全仓**唯一**用 # 现场:win32file.vp 的 STD_INPUT/OUTPUT/ERROR_HANDLE 是全仓**唯一**用
# 别名构造写的 define → 唯独这三个进不了 _all_define_constants,导致 # 别名构造写的 define → 唯独这三个进不了 _all_define_constants,导致
# 模块属性访问 `wf.STD_ERROR_HANDLE` 解析落空、退化成未定义的全局符号 # 模块属性访问 `wf.STD_ERROR_HANDLE` 解析落空、退化成未定义的全局符号
@@ -668,7 +668,7 @@ def _CountUnresolvedTypedefs(module_symbols: object) -> int:
"""该模块"有值注解却解析不出类型"的 typedef 个数(供声明阶段判断是否要下一轮)。 """该模块"有值注解却解析不出类型"的 typedef 个数(供声明阶段判断是否要下一轮)。
typedef 右侧可以引用**其它模块**的 typedef:例 win32base 的 typedef 右侧可以引用**其它模块**的 typedef:例 win32base 的
`HANDLE: t.CTypedef = VOIDPTR`(VOIDPTR 在 stdint)——本模块先 stage 时右侧 `HANDLE: CTypedef = VOIDPTR`(VOIDPTR 在 stdint)——本模块先 stage 时右侧
解析为空(original_type_kind/original_class 均为 None),要等依赖模块入表后 解析为空(original_type_kind/original_class 均为 None),要等依赖模块入表后
重 stage 才能补全。返回 0 表示本模块声明已完整(不再需要重跑)。 重 stage 才能补全。返回 0 表示本模块声明已完整(不再需要重跑)。
""" """
@@ -3132,7 +3132,7 @@ class Phase2Translator:
sys.exit(1) sys.exit(1)
def _precollect_vtable_state(self) -> None: def _precollect_vtable_state(self) -> None:
"""预扫描 includes .py 文件,收集 @t.CVTable 类的虚表信息。 """预扫描 includes .py 文件,收集 @CVTable 类的虚表信息。
并行编译(ProcessPoolExecutor)创建独立内存的 worker 进程, 并行编译(ProcessPoolExecutor)创建独立内存的 worker 进程,
vtable 状态必须预收集并通过 pickle 共享。 vtable 状态必须预收集并通过 pickle 共享。
@@ -3150,7 +3150,7 @@ class Phase2Translator:
code, tree = parse_python_file(py_path) code, tree = parse_python_file(py_path)
# 字符串预过滤:不含 CVTable 的文件跳过 AST 遍历。 # 字符串预过滤:不含 CVTable 的文件跳过 AST 遍历。
# `virtual class` / `virtual def` 修饰符在源码里写的是 `virtual` # `virtual class` / `virtual def` 修饰符在源码里写的是 `virtual`
# (AST 上才变成 @t.CVTable 装饰器),故预过滤必须同时放行 # (AST 上才变成 @CVTable 装饰器),故预过滤必须同时放行
# `virtual`/`novirtual`,否则含修饰符的 includes 类会被整段跳过—— # `virtual`/`novirtual`,否则含修饰符的 includes 类会被整段跳过——
# 静默不预收集虚表状态(与本题"不得静默丢弃修饰符"同族问题)。 # 静默不预收集虚表状态(与本题"不得静默丢弃修饰符"同族问题)。
if tree is None or ('CVTable' not in code and 'virtual' not in code): if tree is None or ('CVTable' not in code and 'virtual' not in code):
@@ -3161,10 +3161,7 @@ class Phase2Translator:
continue continue
has_cvtable: bool = False has_cvtable: bool = False
for dec in node.decorator_list: for dec in node.decorator_list:
if isinstance(dec, ast.Attribute): if isinstance(dec, ast.Name):
if getattr(dec.value, 'id', None) == 't' and dec.attr == 'CVTable':
has_cvtable = True
elif isinstance(dec, ast.Name):
if dec.id == 'CVTable': if dec.id == 'CVTable':
has_cvtable = True has_cvtable = True
# 方法级 virtual 触发类级 vtable(与 # 方法级 virtual 触发类级 vtable(与
@@ -3199,7 +3196,7 @@ class Phase2Translator:
# 构造函数不放入 vtable(避免子类与基类 vtable 大小不一致破坏多态分派) # 构造函数不放入 vtable(避免子类与基类 vtable 大小不一致破坏多态分派)
if method_name in ('__new__', '__init__', '__before_init__'): if method_name in ('__new__', '__init__', '__before_init__'):
continue continue
# 方法级修饰符:`novirtual def`(⇒ @t.NoVTable)不进槽; # 方法级修饰符:`novirtual def`(⇒ @NoVTable)不进槽;
# 判据唯一源 = SymbolUtils.IsVtableSlotMethod,与 # 判据唯一源 = SymbolUtils.IsVtableSlotMethod,与
# HandlesClassDef / VPC _should_method_be_virtual 同口径。 # HandlesClassDef / VPC _should_method_be_virtual 同口径。
if not IsVtableSlotMethod(item, class_level_cvtable): if not IsVtableSlotMethod(item, class_level_cvtable):
@@ -4370,7 +4367,7 @@ class Phase2Translator:
info.IsInline = True info.IsInline = True
info.InlineBody = node.body info.InlineBody = node.body
info.InlineParams = [arg.arg for arg in node.args.args] info.InlineParams = [arg.arg for arg in node.args.args]
info.Storage = t.CInline() info.Storage = TypeSystem.CInline()
self.inline_func_symbols[func_name] = info self.inline_func_symbols[func_name] = info
self.inline_func_symbols[sym_key] = info self.inline_func_symbols[sym_key] = info
except Exception as _e: except Exception as _e:
@@ -4440,7 +4437,7 @@ class Phase2Translator:
# ① 声明阶段(全部模块;多轮直到"本轮没有新增可解析的声明") # ① 声明阶段(全部模块;多轮直到"本轮没有新增可解析的声明")
# 单轮仍会与模块顺序有关:typedef 右侧可以引用**其它模块**的 typedef, # 单轮仍会与模块顺序有关:typedef 右侧可以引用**其它模块**的 typedef,
# 例 win32base 的 `HANDLE: t.CTypedef = VOIDPTR`,VOIDPTR 在 stdint # 例 win32base 的 `HANDLE: CTypedef = VOIDPTR`,VOIDPTR 在 stdint
# ⇒ 本模块先 stage 时右侧解析为空;下一轮把它重 stage 一遍(重 stage 覆盖 # ⇒ 本模块先 stage 时右侧解析为空;下一轮把它重 stage 一遍(重 stage 覆盖
# 登记,条目随依赖入表而变完整)。无进展即停,最多再跑一轮。 # 登记,条目随依赖入表而变完整)。无进展即停,最多再跑一轮。
_stage_map: dict[tuple[str, str], ModuleSymbols] = {} _stage_map: dict[tuple[str, str], ModuleSymbols] = {}
+2 -2
View File
@@ -41,7 +41,7 @@ _FILE_AST_CACHE: dict[str, tuple[float, str, ast.Module]] = {}
def _check_annotation_for_export(annotation: ast.AST | None) -> bool: def _check_annotation_for_export(annotation: ast.AST | None) -> bool:
"""递归检查类型注解中是否包含 CExport/CExtern/State(t.State = t.CExtern | t.CExport)""" """递归检查类型注解中是否包含 CExport/CExtern/State(State = CExtern | CExport)"""
if not annotation: if not annotation:
return False return False
return (AnnotationContainsName(annotation, 'CExport') or return (AnnotationContainsName(annotation, 'CExport') or
@@ -78,7 +78,7 @@ def parse_python_file(filepath: str) -> tuple[str, ast.Module] | tuple[str, None
except Exception: except Exception:
return ('', None) return ('', None)
try: try:
# 软关键字/语法糖展开:fn/fun/func/function -> def、enum 块 -> class X(t.CEnum) # 软关键字/语法糖展开:fn/fun/func/function -> def、enum 块 -> class X(CEnum)
# (均同行替换,行号不变),供 ast.parse 使用。 # (均同行替换,行号不变),供 ast.parse 使用。
# 注意 content 保持原始文本返回(compute_sha1 必须与 Phase1 一致), # 注意 content 保持原始文本返回(compute_sha1 必须与 Phase1 一致),
# 仅 tree 基于展开后的代码解析。 # 仅 tree 基于展开后的代码解析。
+1 -1
View File
@@ -1,5 +1,5 @@
"""Projectrans 包 - 工程级 TransPyC 翻译器""" """Projectrans 包 - 工程级 TransPyC 翻译器"""
import lib._bootstrap # noqa: F401 设置 sys.path(项目根 + lib/includes) import lib._bootstrap # noqa: F401 设置 sys.path(项目根 + lib)
from lib.core.VLogger import Logger, LogLevel, set_logger from lib.core.VLogger import Logger, LogLevel, set_logger
+3 -5
View File
@@ -8,8 +8,7 @@ import datetime
import tempfile import tempfile
import subprocess import subprocess
from typing import Any from typing import Any
from lib.includes import c from lib.core import TypeSystem
from lib.includes import t
from lib.constants.config import ( from lib.constants.config import (
DEFAULT_INPUT_FILE, DEFAULT_OUTPUT_FILE, DEFAULT_INPUT_FILE, DEFAULT_OUTPUT_FILE,
DEFAULT_COMPILE_COMMAND, DEFAULT_COMPILE_COMMAND,
@@ -549,14 +548,13 @@ class TransPyC:
if isinstance(_node, ast.Import): if isinstance(_node, ast.Import):
for _alias in _node.names: for _alias in _node.names:
_name: str = _alias.name _name: str = _alias.name
if _name in ('c', 't'): # t / c 库已退役:不再跳过,按常规模块登记
continue
self.translator._ImportedModules.add(_name) self.translator._ImportedModules.add(_name)
if _alias.asname: if _alias.asname:
self.translator.SymbolTable.import_aliases[_alias.asname] = _name self.translator.SymbolTable.import_aliases[_alias.asname] = _name
elif isinstance(_node, ast.ImportFrom): elif isinstance(_node, ast.ImportFrom):
_module_name: str | None = _node.module _module_name: str | None = _node.module
if _module_name and _module_name not in ('c', 't'): if _module_name:
self.translator._ImportedModules.add(_module_name) self.translator._ImportedModules.add(_module_name)
for _alias in _node.names: for _alias in _node.names:
if _alias.asname: if _alias.asname:
+63 -80
View File
@@ -88,19 +88,12 @@ class PythonToStubConverter:
StubLines.append('"""') StubLines.append('"""')
StubLines.append('') StubLines.append('')
# 解析 Python 代码,检查是否已经导入了 t 和 c(AST 与下方主解析复用,避免重复 parse) # 解析 Python 代码,供下方主循环复用(避免重复 parse)。
HasImportT: bool = False # stub 头部不注入 import 行;内建标记按裸名使用,无需导入。
HasImportC: bool = False tree: ast.Module | None = None
try: try:
# 传来源名:解析失败时 vast 的报错/回退诊断才带得上模块名(否则记为 <unknown>) # 传来源名:解析失败时 vast 的报错/回退诊断才带得上模块名(否则记为 <unknown>)
tree: ast.Module = ast.parse(PyContent, f'{ModuleName}.vp') tree = ast.parse(PyContent, f'{ModuleName}.vp')
for node in tree.body:
if isinstance(node, ast.Import):
for alias in node.names:
if alias.name == 't':
HasImportT = True
elif alias.name == 'c':
HasImportC = True
except SyntaxError: except SyntaxError:
# 语法错误:同一内容两次解析结果必然相同,与主循环 fail-fast 行为一致 # 语法错误:同一内容两次解析结果必然相同,与主循环 fail-fast 行为一致
raise raise
@@ -108,16 +101,6 @@ class PythonToStubConverter:
# 非语法类解析异常:保持原语义(第一遍吞掉,主循环重新解析后向上传播) # 非语法类解析异常:保持原语义(第一遍吞掉,主循环重新解析后向上传播)
tree = None tree = None
# 添加默认导入(如果源代码中没有)
if not HasImportT:
StubLines.append('import t')
if not HasImportC:
StubLines.append('import c')
if not HasImportT or not HasImportC:
StubLines.append('')
StubLines.append('')
# 解析 Python 代码,提取类型定义(复用上方的 parse 结果) # 解析 Python 代码,提取类型定义(复用上方的 parse 结果)
try: try:
if tree is None: if tree is None:
@@ -130,7 +113,7 @@ class PythonToStubConverter:
if isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name): if isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name):
TypeStr: str = PythonToStubConverter._GetTypeString(node.annotation) TypeStr: str = PythonToStubConverter._GetTypeString(node.annotation)
# 检查是否是 Postdefinition 类型 # 检查是否是 Postdefinition 类型
if 't.Postdefinition' in TypeStr: if 'Postdefinition' in TypeStr:
# 提取引用的类名 # 提取引用的类名
ClassName: str | None = PythonToStubConverter._ExtractPostdefClass(node.annotation) ClassName: str | None = PythonToStubConverter._ExtractPostdefClass(node.annotation)
if ClassName: if ClassName:
@@ -167,10 +150,10 @@ class PythonToStubConverter:
CurrentType = 'variable' CurrentType = 'variable'
# 跳过 Postdefinition 变量(已经在类中处理) # 跳过 Postdefinition 变量(已经在类中处理)
TypeStr = PythonToStubConverter._GetTypeString(node.annotation) TypeStr = PythonToStubConverter._GetTypeString(node.annotation)
if 't.Postdefinition' in TypeStr: if 'Postdefinition' in TypeStr:
continue continue
# 检查是否带有 t.CStatic 标志,如果有则不排除 # 检查是否带有 CStatic 标志,如果有则不排除
HasStatic: bool = 't.CStatic' in TypeStr HasStatic: bool = 'CStatic' in TypeStr
# 检查变量是否应该被排除 # 检查变量是否应该被排除
ShouldExclude: bool = False ShouldExclude: bool = False
if isinstance(node.target, ast.Name) and not HasStatic: if isinstance(node.target, ast.Name) and not HasStatic:
@@ -210,7 +193,7 @@ class PythonToStubConverter:
StubLines.append('') StubLines.append('')
StubLines.append(ImportStr) StubLines.append(ImportStr)
elif isinstance(node, ast.Expr): elif isinstance(node, ast.Expr):
# 处理模块级别的宏调用,如 c.CUndef(...) / c.CPragma(...) # 处理模块级别的宏调用,如 CUndef(...) / CPragma(...)
ExprStr: str = PythonToStubConverter._GetExprString(node.value) ExprStr: str = PythonToStubConverter._GetExprString(node.value)
if ExprStr: if ExprStr:
CurrentType = 'macro' CurrentType = 'macro'
@@ -364,8 +347,8 @@ class PythonToStubConverter:
else: else:
lines.append(f'{MemberIndent}{item.target.id}: {TypeStr}') lines.append(f'{MemberIndent}{item.target.id}: {TypeStr}')
continue continue
# 检查是否是宏变量(类型包含 t.CDefine) # 检查是否是宏变量(类型包含 CDefine)
if 't.CDefine' in TypeStr: if 'CDefine' in TypeStr:
# 检查宏变量是否应该被排除 # 检查宏变量是否应该被排除
if isinstance(item.target, ast.Name): if isinstance(item.target, ast.Name):
MacroName: str = item.target.id MacroName: str = item.target.id
@@ -400,7 +383,7 @@ class PythonToStubConverter:
if count_expr and count_expr != 'None': if count_expr and count_expr != 'None':
has_size = True has_size = True
elem_type_str: str = PythonToStubConverter._GetTypeString(slice_node.elts[0]) elem_type_str: str = PythonToStubConverter._GetTypeString(slice_node.elts[0])
FinalTypeStr = f't.CArray[{elem_type_str}, {count_expr}]' FinalTypeStr = f'CArray[{elem_type_str}, {count_expr}]'
if not has_size: if not has_size:
elem_type_str = PythonToStubConverter._GetTypeString(slice_node if not isinstance(slice_node, ast.Tuple) else slice_node.elts[0]) elem_type_str = PythonToStubConverter._GetTypeString(slice_node if not isinstance(slice_node, ast.Tuple) else slice_node.elts[0])
init_len: int = 0 init_len: int = 0
@@ -410,9 +393,9 @@ class PythonToStubConverter:
elif isinstance(item.value, ast.Constant) and isinstance(item.value.value, str): elif isinstance(item.value, ast.Constant) and isinstance(item.value.value, str):
init_len = len(item.value.value) + 1 init_len = len(item.value.value) + 1
if init_len > 0: if init_len > 0:
FinalTypeStr = f't.CArray[{elem_type_str}, {init_len}]' FinalTypeStr = f'CArray[{elem_type_str}, {init_len}]'
else: else:
FinalTypeStr = f't.CArray[{elem_type_str}, None]' FinalTypeStr = f'CArray[{elem_type_str}, None]'
if item.value is not None and isinstance(item.value, ast.Constant): if item.value is not None and isinstance(item.value, ast.Constant):
try: try:
value_repr: str = ast.unparse(item.value) value_repr: str = ast.unparse(item.value)
@@ -426,7 +409,7 @@ class PythonToStubConverter:
FuncStub: list[str] = PythonToStubConverter._ConvertFunction(item, indent=indent+1, SourceLines=SourceLines, class_name=node.name) FuncStub: list[str] = PythonToStubConverter._ConvertFunction(item, indent=indent+1, SourceLines=SourceLines, class_name=node.name)
lines.extend(FuncStub) lines.extend(FuncStub)
elif isinstance(item, ast.Expr): elif isinstance(item, ast.Expr):
# 处理宏调用,如 c.CUndef(...) / c.CPragma(...) # 处理宏调用,如 CUndef(...) / CPragma(...)
ExprStr: str = PythonToStubConverter._GetExprString(item.value) ExprStr: str = PythonToStubConverter._GetExprString(item.value)
if ExprStr: if ExprStr:
lines.append(f'{IndentStr} {ExprStr}') lines.append(f'{IndentStr} {ExprStr}')
@@ -443,9 +426,9 @@ class PythonToStubConverter:
FilteredLines: list[str] = [] FilteredLines: list[str] = []
for line in NestedClassLines: for line in NestedClassLines:
# 跳过宏守卫相关行 # 跳过宏守卫相关行
if line.strip().startswith('c.CIfndef(') or line.strip().startswith('c.CEndif()'): if line.strip().startswith('CIfndef(') or line.strip().startswith('CEndif()'):
continue continue
if ': t.CDefine' in line and '__' in line: if ': CDefine' in line and '__' in line:
continue continue
FilteredLines.append(line) FilteredLines.append(line)
lines.extend(FilteredLines) lines.extend(FilteredLines)
@@ -467,11 +450,11 @@ class PythonToStubConverter:
lines: list[str] = [] lines: list[str] = []
IndentStr: str = ' ' * indent IndentStr: str = ' ' * indent
# 检查是否是宏函数(返回类型包含 t.CDefine) # 检查是否是宏函数(返回类型包含 CDefine)
is_macro_func: bool = False is_macro_func: bool = False
if node.returns: if node.returns:
ReturnType: str = PythonToStubConverter._GetTypeString(node.returns) ReturnType: str = PythonToStubConverter._GetTypeString(node.returns)
if 't.CDefine' in ReturnType: if 'CDefine' in ReturnType:
is_macro_func = True is_macro_func = True
# 如果是宏函数,检查是否应该被排除 # 如果是宏函数,检查是否应该被排除
@@ -558,11 +541,11 @@ class PythonToStubConverter:
ParamStr: str = ', '.join(params) ParamStr: str = ', '.join(params)
# 返回类型 - 保持原始类型(不添加t.State) # 返回类型 - 保持原始类型(不添加 State)
if node.returns: if node.returns:
ReturnType = PythonToStubConverter._GetTypeString(node.returns) ReturnType = PythonToStubConverter._GetTypeString(node.returns)
else: else:
ReturnType = 't.CInt' ReturnType = 'CInt'
TypeParamStr: str = '' TypeParamStr: str = ''
if hasattr(node, 'type_params') and node.type_params: if hasattr(node, 'type_params') and node.type_params:
@@ -579,8 +562,8 @@ class PythonToStubConverter:
if isinstance(node.target, ast.Name): if isinstance(node.target, ast.Name):
VarName: str = node.target.id VarName: str = node.target.id
TypeStr: str = PythonToStubConverter._GetTypeString(node.annotation) TypeStr: str = PythonToStubConverter._GetTypeString(node.annotation)
# 检查是否是宏变量(类型包含 t.CDefine) # 检查是否是宏变量(类型包含 CDefine)
if 't.CDefine' in TypeStr: if 'CDefine' in TypeStr:
# 检查宏变量是否应该被排除 # 检查宏变量是否应该被排除
if PythonToStubConverter._ShouldExcludeMacro(VarName): if PythonToStubConverter._ShouldExcludeMacro(VarName):
return lines # 返回空列表,排除该宏 return lines # 返回空列表,排除该宏
@@ -593,15 +576,15 @@ class PythonToStubConverter:
else: else:
lines.append(f'{VarName}: {TypeStr}') lines.append(f'{VarName}: {TypeStr}')
return lines return lines
# 非宏变量:不加 t.State # 非宏变量:不加 State
# 含有 typedef 的变量不加 extern,普通变量需要加 extern # 含有 typedef 的变量不加 extern,普通变量需要加 extern
has_typedef: bool = 't.CTypedef' in TypeStr or 'CTypedef' in TypeStr has_typedef: bool = 'CTypedef' in TypeStr or 'CTypedef' in TypeStr
if has_typedef and node.value is not None: if has_typedef and node.value is not None:
ValueTypeStr: str = PythonToStubConverter._GetTypeString(node.value) ValueTypeStr: str = PythonToStubConverter._GetTypeString(node.value)
lines.append(f'{VarName}: {TypeStr} = {ValueTypeStr}') lines.append(f'{VarName}: {TypeStr} = {ValueTypeStr}')
else: else:
if not has_typedef and 't.CExtern' not in TypeStr and 't.CStatic' not in TypeStr: if not has_typedef and 'CExtern' not in TypeStr and 'CStatic' not in TypeStr:
TypeStr = f't.CExtern | {TypeStr}' TypeStr = f'CExtern | {TypeStr}'
lines.append(f'{VarName}: {TypeStr}') lines.append(f'{VarName}: {TypeStr}')
return lines return lines
@@ -623,7 +606,7 @@ class PythonToStubConverter:
if inferred_type: if inferred_type:
lines.append(f'{VarName}: {inferred_type}') lines.append(f'{VarName}: {inferred_type}')
else: else:
lines.append(f'{VarName}: t.CInt') lines.append(f'{VarName}: CInt')
return lines return lines
@@ -632,33 +615,33 @@ class PythonToStubConverter:
"""从值推断 C 类型""" """从值推断 C 类型"""
if isinstance(value, ast.Constant): if isinstance(value, ast.Constant):
if isinstance(value.value, int): if isinstance(value.value, int):
return 't.CInt' return 'CInt'
elif isinstance(value.value, float): elif isinstance(value.value, float):
return 't.CDouble' return 'CDouble'
elif isinstance(value.value, str): elif isinstance(value.value, str):
return 't.CCharPtr' return 'CCharPtr'
elif isinstance(value.value, bool): elif isinstance(value.value, bool):
return 't.CInt' return 'CInt'
elif isinstance(value, ast.List): elif isinstance(value, ast.List):
return 't.CVoidPtr' return 'CVoidPtr'
elif isinstance(value, ast.Dict): elif isinstance(value, ast.Dict):
return 't.CVoidPtr' return 'CVoidPtr'
elif isinstance(value, ast.Name): elif isinstance(value, ast.Name):
return 't.CInt' return 'CInt'
elif isinstance(value, ast.BinOp): elif isinstance(value, ast.BinOp):
left_type: str | None = PythonToStubConverter._InferTypeFromValue(value.left) left_type: str | None = PythonToStubConverter._InferTypeFromValue(value.left)
if left_type: if left_type:
return left_type return left_type
return 't.CInt' return 'CInt'
elif isinstance(value, ast.Call): elif isinstance(value, ast.Call):
# 函数调用返回值,假设为指针类型 # 函数调用返回值,假设为指针类型
if isinstance(value.func, ast.Name): if isinstance(value.func, ast.Name):
func_name: str = value.func.id func_name: str = value.func.id
if func_name == 'malloc': if func_name == 'malloc':
return 't.CVoidPtr' return 'CVoidPtr'
elif func_name in ('ctypes.cast', 'cast'): elif func_name in ('ctypes.cast', 'cast'):
return 't.CVoidPtr' return 'CVoidPtr'
return 't.CVoidPtr' return 'CVoidPtr'
return None return None
@staticmethod @staticmethod
@@ -668,19 +651,19 @@ class PythonToStubConverter:
支持集与 VPC(ViperC/App/lib/Stub/StubGen/Converter.vp 的 _PyiTypeStr) 支持集与 VPC(ViperC/App/lib/Stub/StubGen/Converter.vp 的 _PyiTypeStr)
等价:Name/Attribute/Subscript/BinOp/UnaryOp/Compare/BoolOp/Constant/ 等价:Name/Attribute/Subscript/BinOp/UnaryOp/Compare/BoolOp/Constant/
List/Call(VPC 另支持裸 Tuple,本侧仅在 Subscript.slice 位置接受 Tuple)。 List/Call(VPC 另支持裸 Tuple,本侧仅在 Subscript.slice 位置接受 Tuple)。
未支持的节点种类与运算符在此 fail-fast(不自造 't.CVoid' 回落)。 未支持的节点种类与运算符在此 fail-fast(不自造 'CVoid' 回落)。
""" """
# 无注解(None):调用方未提供注解,沿用原语义返回 't.CVoid'; # 无注解(None):调用方未提供注解,沿用原语义返回 'CVoid';
# 这不是"未知节点"——未知节点走函数尾 fail-fast。 # 这不是"未知节点"——未知节点走函数尾 fail-fast。
if annotation is None: if annotation is None:
return 't.CVoid' return 'CVoid'
if isinstance(annotation, ast.Name): if isinstance(annotation, ast.Name):
return annotation.id return annotation.id
elif isinstance(annotation, ast.Attribute): elif isinstance(annotation, ast.Attribute):
if isinstance(annotation.value, ast.Name): if isinstance(annotation.value, ast.Name):
return f'{annotation.value.id}.{annotation.attr}' return f'{annotation.value.id}.{annotation.attr}'
else: else:
# 处理嵌套属性访问,如 t.attr.packed # 处理嵌套属性访问,如 attr.packed
ParentStr: str = PythonToStubConverter._GetTypeString(annotation.value) ParentStr: str = PythonToStubConverter._GetTypeString(annotation.value)
return f'{ParentStr}.{annotation.attr}' return f'{ParentStr}.{annotation.attr}'
elif isinstance(annotation, ast.Subscript): elif isinstance(annotation, ast.Subscript):
@@ -692,20 +675,20 @@ class PythonToStubConverter:
SliceStr = PythonToStubConverter._GetTypeString(annotation.slice) SliceStr = PythonToStubConverter._GetTypeString(annotation.slice)
return f'{base}[{SliceStr}]' return f'{base}[{SliceStr}]'
elif isinstance(annotation, ast.BinOp): elif isinstance(annotation, ast.BinOp):
# 处理 BinOp,如 t.CExtern | fd_table.__set_default__(...) # 处理 BinOp,如 CExtern | fd_table.__set_default__(...)
left: ast.AST = annotation.left left: ast.AST = annotation.left
right: ast.AST = annotation.right right: ast.AST = annotation.right
# 值引用参数标记:联合形态 `T | t.CRef`(ref)/ `T | t.CTempRef`(temp) # 值引用参数标记:联合形态 `T | CRef`(ref)/ `T | CTempRef`(temp)
# 还原为源码写法 `&T` / `&temp T`,使跨模块 .vpi 往返保留取址模式。 # 还原为源码写法 `&T` / `&temp T`,使跨模块 .vpi 往返保留取址模式。
if isinstance(annotation.op, ast.BitOr): if isinstance(annotation.op, ast.BitOr):
_ref_kind: str | None = None _ref_kind: str | None = None
_type_side: ast.AST | None = None _type_side: ast.AST | None = None
if isinstance(right, ast.Attribute) and right.attr in ('CRef', 'CTempRef'): if isinstance(right, ast.Name) and right.id in ('CRef', 'CTempRef'):
_ref_kind = right.attr _ref_kind = right.id
_type_side = left _type_side = left
elif isinstance(left, ast.Attribute) and left.attr in ('CRef', 'CTempRef'): elif isinstance(left, ast.Name) and left.id in ('CRef', 'CTempRef'):
_ref_kind = left.attr _ref_kind = left.id
_type_side = right _type_side = right
if _ref_kind is not None and _type_side is not None: if _ref_kind is not None and _type_side is not None:
_inner: str = PythonToStubConverter._GetTypeString(_type_side) _inner: str = PythonToStubConverter._GetTypeString(_type_side)
@@ -790,7 +773,7 @@ class PythonToStubConverter:
elements: list[str] = [PythonToStubConverter._GetTypeString(elem) for elem in annotation.elts] elements: list[str] = [PythonToStubConverter._GetTypeString(elem) for elem in annotation.elts]
return f'[{", ".join(elements)}]' return f'[{", ".join(elements)}]'
elif isinstance(annotation, ast.Call): elif isinstance(annotation, ast.Call):
# 处理函数调用形式的类型注解,如 t.Postdefinition(xxa) 或 callable(t.CVoid, app_id = t.CInt) # 处理函数调用形式的类型注解,如 Postdefinition(xxa) 或 callable(CVoid, app_id = CInt)
# 如果是 __set_default__ 调用,只返回函数名部分 # 如果是 __set_default__ 调用,只返回函数名部分
if isinstance(annotation.func, ast.Attribute) and annotation.func.attr in ('__set_default__', '__set_default'): if isinstance(annotation.func, ast.Attribute) and annotation.func.attr in ('__set_default__', '__set_default'):
return PythonToStubConverter._GetTypeString(annotation.func.value) return PythonToStubConverter._GetTypeString(annotation.func.value)
@@ -807,8 +790,8 @@ class PythonToStubConverter:
else: else:
return f'{FuncStr}({ArgsStr})' return f'{FuncStr}({ArgsStr})'
# 未知/未支持的注解节点 fail-fast(与 VPC StubGen 的 _PyiTypeStr 同语义、 # 未知/未支持的注解节点 fail-fast(与 VPC StubGen 的 _PyiTypeStr 同语义、
# 同文案、同类型):静默回落 't.CVoid' 会把错误类型写进 stub 签名——实例: # 同文案、同类型):静默回落 'CVoid' 会把错误类型写进 stub 签名——实例:
# 源里的 t.Callable[[], int] 曾写成 t.Callable[int, int](见 # 源里的 Callable[[], int] 曾写成 Callable[int, int](见
# ViperApps/ViperOS/VKernel/__vpcbuild__/temp/0b/0bb176432facf634.vpi:23), # ViperApps/ViperOS/VKernel/__vpcbuild__/temp/0b/0bb176432facf634.vpi:23),
# 下游按错误签名解析且无任何提示。 # 下游按错误签名解析且无任何提示。
# 归因信息:节点 kind + 行号;文件归因由调用方在日志里带上 # 归因信息:节点 kind + 行号;文件归因由调用方在日志里带上
@@ -822,10 +805,10 @@ class PythonToStubConverter:
def _ExtractPostdefClass(annotation: ast.AST) -> str | None: def _ExtractPostdefClass(annotation: ast.AST) -> str | None:
"""从 Postdefinition 类型注解中提取类名 """从 Postdefinition 类型注解中提取类名
例如:t.Postdefinition(__buddy_system) -> '__buddy_system' 例如:Postdefinition(__buddy_system) -> '__buddy_system'
t.Postdefinition(xxx) | t.CTypedef -> 'xxx' Postdefinition(xxx) | CTypedef -> 'xxx'
""" """
# 处理 BinOp (如: t.Postdefinition(xxx) | t.CTypedef) # 处理 BinOp (如: Postdefinition(xxx) | CTypedef)
if isinstance(annotation, ast.BinOp): if isinstance(annotation, ast.BinOp):
# 递归检查左操作数 # 递归检查左操作数
left_result: str | None = PythonToStubConverter._ExtractPostdefClass(annotation.left) left_result: str | None = PythonToStubConverter._ExtractPostdefClass(annotation.left)
@@ -837,10 +820,10 @@ class PythonToStubConverter:
return right_result return right_result
return None return None
# 处理函数调用 (如: t.Postdefinition(__buddy_system)) # 处理函数调用 (如: Postdefinition(__buddy_system))
if isinstance(annotation, ast.Call): if isinstance(annotation, ast.Call):
FuncStr: str = PythonToStubConverter._GetTypeString(annotation.func) FuncStr: str = PythonToStubConverter._GetTypeString(annotation.func)
if FuncStr == 't.Postdefinition' and annotation.args: if FuncStr == 'Postdefinition' and annotation.args:
# 提取第一个参数 # 提取第一个参数
first_arg: ast.AST = annotation.args[0] first_arg: ast.AST = annotation.args[0]
if isinstance(first_arg, ast.Name): if isinstance(first_arg, ast.Name):
@@ -964,7 +947,7 @@ class PythonToStubConverter:
return f'{decorator.value.id}.{decorator.attr}' return f'{decorator.value.id}.{decorator.attr}'
return decorator.attr return decorator.attr
elif isinstance(decorator, ast.Call): elif isinstance(decorator, ast.Call):
# 处理带参数的装饰器,如 @c.Attribute(t.attr.packed) # 处理带参数的装饰器,如 @Attribute(attr.packed)
FuncStr: str = PythonToStubConverter._GetDecoratorString(decorator.func) FuncStr: str = PythonToStubConverter._GetDecoratorString(decorator.func)
ArgsStr: str = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in decorator.args]) ArgsStr: str = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in decorator.args])
return f'{FuncStr}({ArgsStr})' return f'{FuncStr}({ArgsStr})'
@@ -974,8 +957,8 @@ class PythonToStubConverter:
def _GetExprString(expr: ast.AST) -> str: def _GetExprString(expr: ast.AST) -> str:
"""获取表达式字符串(用于宏调用)""" """获取表达式字符串(用于宏调用)"""
if isinstance(expr, ast.Call): if isinstance(expr, ast.Call):
# 处理函数调用,如 c.CUndef(...), c.CPragma(...) # 处理函数调用,如 CUndef(...), CPragma(...)
# (旧的 c.CIf/c.CElif/c.CElse 已删除:cif/celif/celse 由 _ProcessIfMacro 渲染) # (旧的 CIf/CElif/CElse 已删除:cif/celif/celse 由 _ProcessIfMacro 渲染)
FuncStr: str = PythonToStubConverter._GetDecoratorString(expr.func) FuncStr: str = PythonToStubConverter._GetDecoratorString(expr.func)
if FuncStr and ('CEndif' in FuncStr or 'CUndef' in FuncStr or 'CPragma' in FuncStr): if FuncStr and ('CEndif' in FuncStr or 'CUndef' in FuncStr or 'CPragma' in FuncStr):
ArgsStr: str = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in expr.args]) ArgsStr: str = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in expr.args])
@@ -984,9 +967,9 @@ class PythonToStubConverter:
@staticmethod @staticmethod
def _RestoreDefinedMarkers(node: ast.AST) -> ast.AST: def _RestoreDefinedMarkers(node: ast.AST) -> ast.AST:
"""把内部标记 c.@CIfdef(N) 递归还原为 defined(N) 调用(供 stub 文本渲染)。 """把内部标记 @CIfdef(N) 递归还原为 defined(N) 调用(供 stub 文本渲染)。
cif/celif 条件的 desugar 会把 defined(NAME) 变成 c.@CIfdef(NAME) 标记调用; cif/celif 条件的 desugar 会把 defined(NAME) 变成 @CIfdef(NAME) 标记调用;
生成 .vpi 文本时必须还原为用户可写的 defined(NAME),否则存根不可再解析。 生成 .vpi 文本时必须还原为用户可写的 defined(NAME),否则存根不可再解析。
""" """
if isinstance(node, ast.Call): if isinstance(node, ast.Call):
@@ -1011,7 +994,7 @@ class PythonToStubConverter:
@staticmethod @staticmethod
def _CifConditionText(test: ast.AST) -> str | None: def _CifConditionText(test: ast.AST) -> str | None:
"""cif/celif 条件文本:内部标记 c.@CIf(EXPR) → EXPR;c.@CIfdef(N) → defined(N)。 """cif/celif 条件文本:内部标记 @CIf(EXPR) → EXPR;@CIfdef(N) → defined(N)。
返回 None 表示 test 不是 cif 族标记(普通 if 的运行时条件)。 返回 None 表示 test 不是 cif 族标记(普通 if 的运行时条件)。
""" """
+1 -1
View File
@@ -1,6 +1,6 @@
"""TransPyC 编译器核心库 """TransPyC 编译器核心库
任何 ``import lib.*`` 都会先触发 _bootstrap(sys.path 设置: 任何 ``import lib.*`` 都会先触发 _bootstrap(sys.path 设置:
项目根 + lib 目录 + lib/includes),保证 ``import vast`` 直接可用。 项目根 + lib 目录),保证 ``import vast`` 直接可用。
""" """
import lib._bootstrap # noqa: F401 import lib._bootstrap # noqa: F401
+1 -5
View File
@@ -2,7 +2,7 @@
在首次导入时一次性设置好编译器运行所需的 sys.path: 在首次导入时一次性设置好编译器运行所需的 sys.path:
- 项目根目录:让 ``import TransPyC``、``from StubGen import``、动态 importlib 能解析 - 项目根目录:让 ``import TransPyC``、``from StubGen import``、动态 importlib 能解析
- lib/includes:让用户注解模块中的 ``import t`` / ``import c`` 能解析 (lib 目录加入 sys.path,使 ``import vast`` 直接可用。)
入口点(TransPyC.py / Projectrans.py)应在最开头 ``import lib._bootstrap``。 入口点(TransPyC.py / Projectrans.py)应在最开头 ``import lib._bootstrap``。
lib 内部模块也可 ``import lib._bootstrap`` 作为安全网,重复导入是无副作用的 no-op。 lib 内部模块也可 ``import lib._bootstrap`` 作为安全网,重复导入是无副作用的 no-op。
@@ -25,16 +25,12 @@ def _bootstrap() -> None:
_LibDir: str = os.path.dirname(os.path.abspath(__file__)) _LibDir: str = os.path.dirname(os.path.abspath(__file__))
# 项目根目录 = lib 的父目录 # 项目根目录 = lib 的父目录
_ProjectRoot: str = os.path.dirname(_LibDir) _ProjectRoot: str = os.path.dirname(_LibDir)
# lib/includes 目录(编译器内部类型系统 t.py / c.py)
_IncludesDir: str = os.path.join(_LibDir, 'includes')
if _ProjectRoot not in sys.path: if _ProjectRoot not in sys.path:
sys.path.insert(0, _ProjectRoot) sys.path.insert(0, _ProjectRoot)
if _LibDir not in sys.path: if _LibDir not in sys.path:
# lib 目录入 path:使 vast 包(lib/vast/)可直接 import vast # lib 目录入 path:使 vast 包(lib/vast/)可直接 import vast
sys.path.append(_LibDir) sys.path.append(_LibDir)
if _IncludesDir not in sys.path:
sys.path.append(_IncludesDir)
# ============================================================ # ============================================================
# LLVM IR 兼容性补丁:llvmlite 不允许 void* 指针类型 # LLVM IR 兼容性补丁:llvmlite 不允许 void* 指针类型
+25 -40
View File
@@ -20,9 +20,9 @@ from typing import Any, Callable, Optional, TYPE_CHECKING
import llvmlite.ir as ir import llvmlite.ir as ir
from lib.core.Handles.HandlesBase import CTypeInfo from lib.core.Handles.HandlesBase import CTypeInfo
# 治本修复:导入 t 模块和 CType 基类,用于类型构造调用求值(如 t.CUnsignedLong(-11)) # 导入 TypeSystem 与 CType 基类,用于类型构造调用求值(如 CUnsignedLong(-11))
from lib.includes import t as _t_module from lib.core import TypeSystem as _t_module
from lib.includes.t import CType as _CType_base from lib.core.TypeSystem import CType as _CType_base
if TYPE_CHECKING: if TYPE_CHECKING:
from lib.core.LlvmCodeGenerator import LlvmCodeGenerator from lib.core.LlvmCodeGenerator import LlvmCodeGenerator
@@ -50,40 +50,33 @@ class ConstEvaluator:
return info.DefineValue return info.DefineValue
return None return None
if isinstance(node, ast.Attribute): if isinstance(node, ast.Attribute):
# 先尝试 t.CSizeT().Size 模式(类型构造调用 + .Size 属性) # 先尝试 CSizeT().Size 模式(类型构造调用 + .Size 属性)
size_val = ConstEvaluator._eval_ctype_size_attr(node) size_val = ConstEvaluator._eval_ctype_size_attr(node)
if size_val is not None: if size_val is not None:
return size_val return size_val
return ConstEvaluator._eval_attribute_define(node, symtab) return ConstEvaluator._eval_attribute_define(node, symtab)
# 治本修复:支持 t.CUnsignedLong(-11) 等类型构造调用 # 治本修复:支持 CUnsignedLong(-11) 等类型构造调用
if isinstance(node, ast.Call): if isinstance(node, ast.Call):
return ConstEvaluator._eval_ctype_ctor_call(node, symtab) return ConstEvaluator._eval_ctype_ctor_call(node, symtab)
return ConstEvaluator._eval_arith(node, lambda n: ConstEvaluator.eval_with_symtab(n, symtab)) return ConstEvaluator._eval_arith(node, lambda n: ConstEvaluator.eval_with_symtab(n, symtab))
@staticmethod @staticmethod
def _eval_ctype_ctor_call(node: ast.Call, symtab: Any) -> Optional[Any]: def _eval_ctype_ctor_call(node: ast.Call, symtab: Any) -> Optional[Any]:
"""求值类型构造调用,如 t.CUnsignedLong(-11)、CInt(42)。 """求值类型构造调用,如 CUnsignedLong(-11)、CInt(42)。
在无 ctx(EvalContext)的场景下,通过 symtab 和 t 模块直接求值。 在无 ctx(EvalContext)的场景下,通过 symtab 和 TypeSystem 直接求值。
按类型的 Size 和 IsSigned 应用位掩码。 按类型的 Size 和 IsSigned 应用位掩码。
""" """
func: ast.expr = node.func func: ast.expr = node.func
func_name: str | None = None func_name: str | None = None
module_name: str | None = None if isinstance(func, ast.Name):
if isinstance(func, ast.Attribute):
if isinstance(func.value, ast.Name):
module_name = func.value.id
func_name = func.attr
elif isinstance(func, ast.Name):
func_name = func.id func_name = func.id
ctype_cls: Any = None ctype_cls: Any = None
if module_name == 't' and func_name: if func_name:
ctype_cls = getattr(_t_module, func_name, None)
elif func_name and not module_name:
ctype_cls = getattr(_t_module, func_name, None) ctype_cls = getattr(_t_module, func_name, None)
if ctype_cls is None and symtab: if ctype_cls is None and symtab:
t_type_syms = getattr(symtab, '_t_type_symbols', {}) t_type_syms = getattr(symtab, '_builtin_type_symbols', {})
cls_candidate = t_type_syms.get(func_name) cls_candidate = t_type_syms.get(func_name)
if cls_candidate is not None: if cls_candidate is not None:
ctype_cls = cls_candidate ctype_cls = cls_candidate
@@ -176,7 +169,7 @@ class ConstEvaluator:
# Attribute — 查 define_constants / SymbolTable / 平台宏 # Attribute — 查 define_constants / SymbolTable / 平台宏
if isinstance(node, ast.Attribute): if isinstance(node, ast.Attribute):
# 先尝试 t.CSizeT().Size 模式(类型构造调用 + .Size 属性) # 先尝试 CSizeT().Size 模式(类型构造调用 + .Size 属性)
size_val = ConstEvaluator._eval_ctype_size_attr(node) size_val = ConstEvaluator._eval_ctype_size_attr(node)
if size_val is not None: if size_val is not None:
return size_val return size_val
@@ -210,7 +203,7 @@ class ConstEvaluator:
@staticmethod @staticmethod
def _eval_compile_time_call(node: ast.Call, ctx: 'EvalContext') -> Optional[Any]: def _eval_compile_time_call(node: ast.Call, ctx: 'EvalContext') -> Optional[Any]:
"""处理编译时函数调用,如 ctraits.isptr(x)、t.CUnsignedLong(-11)""" """处理编译时函数调用,如 ctraits.isptr(x)、CUnsignedLong(-11)"""
func: ast.expr = node.func func: ast.expr = node.func
func_name: str | None = None func_name: str | None = None
module_name: str | None = None module_name: str | None = None
@@ -222,7 +215,7 @@ class ConstEvaluator:
elif isinstance(func, ast.Name): elif isinstance(func, ast.Name):
func_name = func.id func_name = func.id
# c.@CIfdef(NAME) / c.@CIfndef(NAME):defined(NAME) 的解析期 desugar 标记,编译期返回 0/1。 # @CIfdef(NAME) / @CIfndef(NAME):defined(NAME) 的解析期 desugar 标记,编译期返回 0/1。
# 仅出现在 cif/celif 条件内(解析器保证),故此处只做宏定义判定。 # 仅出现在 cif/celif 条件内(解析器保证),故此处只做宏定义判定。
if func_name == '@CIfdef': if func_name == '@CIfdef':
if node.args: if node.args:
@@ -251,7 +244,7 @@ class ConstEvaluator:
is_isptr = True is_isptr = True
elif func_name == 'isptr' and not module_name: elif func_name == 'isptr' and not module_name:
# 检查是否通过 from ctraits import isptr 导入 # 检查是否通过 from ctraits import isptr 导入
t_c_imported = getattr(ctx.translator, '_t_c_imported_names', {}) if ctx.translator else {} t_c_imported = getattr(ctx.translator, '_from_import_aliases', {}) if ctx.translator else {}
if func_name in t_c_imported: if func_name in t_c_imported:
src_module, _ = t_c_imported[func_name] src_module, _ = t_c_imported[func_name]
if src_module == 'ctraits': if src_module == 'ctraits':
@@ -286,24 +279,19 @@ class ConstEvaluator:
except Exception: except Exception:
return None return None
# 治本修复:支持 t.CUnsignedLong(-11) 等类型构造调用 # 治本修复:支持 CUnsignedLong(-11) 等类型构造调用
# 当 t.CUnsignedLong(value) / CUnsignedInt(value) / CInt(value) 等被用作常量表达式时, # 当 CUnsignedLong(value) / CUnsignedInt(value) / CInt(value) 等被用作常量表达式时,
# 求值参数并返回(按类型的无符号/有符号语义应用位掩码)。 # 求值参数并返回(按类型的无符号/有符号语义应用位掩码)。
# 这修复了 stdint.py 中 INFINITE = t.CUnsignedLong(-1) 等常量无法被求值的问题。 # 这修复了 stdint.py 中 INFINITE = CUnsignedLong(-1) 等常量无法被求值的问题。
is_ctype_ctor: bool = False is_ctype_ctor: bool = False
ctype_cls: Any = None ctype_cls: Any = None
if module_name == 't' and func_name: if func_name and not module_name:
ctype_cls = getattr(_t_module, func_name, None) ctype_cls = getattr(_t_module, func_name, None)
if ctype_cls is not None and isinstance(ctype_cls, type) and issubclass(ctype_cls, _CType_base): if ctype_cls is not None and isinstance(ctype_cls, type) and issubclass(ctype_cls, _CType_base):
is_ctype_ctor = True is_ctype_ctor = True
elif func_name and not module_name: # 也检查 _builtin_type_symbols(符号表中的内建类型符号)
# from t import CUnsignedLong 形式
ctype_cls = getattr(_t_module, func_name, None)
if ctype_cls is not None and isinstance(ctype_cls, type) and issubclass(ctype_cls, _CType_base):
is_ctype_ctor = True
# 也检查 _t_type_symbols(符号表中的 t 模块类型符号)
if not is_ctype_ctor and ctx.symtab: if not is_ctype_ctor and ctx.symtab:
t_type_syms = getattr(ctx.symtab, '_t_type_symbols', {}) t_type_syms = getattr(ctx.symtab, '_builtin_type_symbols', {})
cls_candidate = t_type_syms.get(func_name) cls_candidate = t_type_syms.get(func_name)
if cls_candidate is not None and isinstance(cls_candidate, type) and issubclass(cls_candidate, _CType_base): if cls_candidate is not None and isinstance(cls_candidate, type) and issubclass(cls_candidate, _CType_base):
ctype_cls = cls_candidate ctype_cls = cls_candidate
@@ -418,10 +406,9 @@ class ConstEvaluator:
@staticmethod @staticmethod
def _eval_ctype_size_attr(node: ast.Attribute) -> Optional[int]: def _eval_ctype_size_attr(node: ast.Attribute) -> Optional[int]:
"""求值 t.CSizeT().Size 等类型构造调用 + .Size 属性模式。 """求值 CSizeT().Size 等类型构造调用 + .Size 属性模式。
匹配 AST 形态: Attribute(attr='Size', value=Call(func=Attribute(value=Name(id='t'), attr='CSizeT'))) 匹配 AST 形态: Attribute(attr='Size', value=Call(func=Name(id='CSizeT'))).
或直接 Call(func=Name(id='CSizeT'))(from t import CSizeT 后的使用方式)。
返回类型大小(位数),如 CSizeT().Size 返回 64(64 位平台)。 返回类型大小(位数),如 CSizeT().Size 返回 64(64 位平台)。
""" """
if node.attr != 'Size': if node.attr != 'Size':
@@ -433,15 +420,13 @@ class ConstEvaluator:
return None return None
func: ast.expr = call_node.func func: ast.expr = call_node.func
type_name: str | None = None type_name: str | None = None
if isinstance(func, ast.Attribute) and isinstance(func.value, ast.Name) and func.value.id == 't': if isinstance(func, ast.Name):
type_name = func.attr
elif isinstance(func, ast.Name):
type_name = func.id type_name = func.id
if not type_name: if not type_name:
return None return None
# 延迟导入避免循环依赖 # 延迟导入避免循环依赖
try: try:
from lib.includes.t import CTypeRegistry from lib.core.TypeSystem import CTypeRegistry
except Exception: except Exception:
return None return None
cls = CTypeRegistry.GetClassByName(type_name) cls = CTypeRegistry.GetClassByName(type_name)
@@ -566,7 +551,7 @@ class EvalContext:
return None return None
def is_macro_defined(self, name: str) -> bool: def is_macro_defined(self, name: str) -> bool:
"""判定宏 NAME 是否已定义(供 defined(NAME) / c.@CIfdef 标记使用)。 """判定宏 NAME 是否已定义(供 defined(NAME) / @CIfdef 标记使用)。
来源与 HandlesIf._is_macro_defined 同口径:Gen._define_constants / 来源与 HandlesIf._is_macro_defined 同口径:Gen._define_constants /
_DefineConstants / SymbolTable.is_define / 平台宏。 _DefineConstants / SymbolTable.is_define / 平台宏。
+59 -61
View File
@@ -8,7 +8,7 @@ import llvmlite.ir as ir
from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo
from lib.core.VLogger import get_logger as _vlog from lib.core.VLogger import get_logger as _vlog
from lib.constants.config import mode as _config_mode from lib.constants.config import mode as _config_mode
from lib.includes import t from lib.core import TypeSystem
from lib.core.SymbolUtils import ( from lib.core.SymbolUtils import (
IsListAnnotation, ParseListAnnotation, FindStructNameInAnnotationWithContext, IsListAnnotation, ParseListAnnotation, FindStructNameInAnnotationWithContext,
AnnotationContainsName, IsCPtrNode, RequireDefineConstStorable, AnnotationContainsName, IsCPtrNode, RequireDefineConstStorable,
@@ -19,7 +19,7 @@ from lib.core.SymbolUtils import (
def _IsGenericTpName(name: str) -> bool: def _IsGenericTpName(name: str) -> bool:
"""判断名称是否为泛型类型参数(单字母大写,如 T/U/V) """判断名称是否为泛型类型参数(单字母大写,如 T/U/V)
用于 _is_struct_ptr_union 判定:elem_ptr: T | t.CPtr = t.CPtr(...) 用于 _is_struct_ptr_union 判定:elem_ptr: T | CPtr = CPtr(...)
(_list.vp 泛型方法体,T 未解析)时按 8 字节指针槽处理,避免 (_list.vp 泛型方法体,T 未解析)时按 8 字节指针槽处理,避免
var_struct_class 误注册 llvmlite.Value 后 elem_ptr[0] cast 到 Value* var_struct_class 误注册 llvmlite.Value 后 elem_ptr[0] cast 到 Value*
与函数声明 i8* 不匹配(8fbba llc 报错根因)。标量 T(如 int)退化为 与函数声明 i8* 不匹配(8fbba llc 报错根因)。标量 T(如 int)退化为
@@ -30,17 +30,17 @@ def _IsGenericTpName(name: str) -> bool:
return len(name) == 1 and name.isalpha() and name.isupper() return len(name) == 1 and name.isalpha() and name.isupper()
# 指针/未知**占位**类名(非真实类):联合注解 rawptr[T] / X | t.CPtr 折叠后, # 指针/未知**占位**类名(非真实类):联合注解 rawptr[T] / X | CPtr 折叠后,
# var_struct_class 里可能落进这些占位名(它们可能恰好也在 Gen.structs 里,如 # var_struct_class 里可能落进这些占位名(它们可能恰好也在 Gen.structs 里,如
# 'rawptr')。占位名不表态具体类 ⇒ 不得登记为「注解声明类」的权威值,否则会挡住 # 'rawptr')。占位名不表态具体类 ⇒ 不得登记为「注解声明类」的权威值,否则会挡住
# "无注解赋值从右值推断类名"的正常路径(如 `p: t.CPtr = Point()` 之后 `p.x` 需要 # "无注解赋值从右值推断类名"的正常路径(如 `p: CPtr = Point()` 之后 `p.x` 需要
# Point)。形态三种(见本文件 L753 的同类判据):裸 'rawptr'、带模块前缀 # Point)。形态三种(见本文件 L753 的同类判据):裸 'rawptr'、带模块前缀
# 'sha1.rawptr'、下标式 'rawptr[X]';CPtr 一族的裸名/限定名同样计入。 # 'sha1.rawptr'、下标式 'rawptr[X]';CPtr 一族的裸名/限定名同样计入。
_PTR_MARKER_CLASS_NAMES: frozenset[str] = frozenset({ _PTR_MARKER_CLASS_NAMES: frozenset[str] = frozenset({
'rawptr', 't.rawptr', 'c.rawptr', 'rawptr', 'rawptr',
'CPtr', 't.CPtr', 'c.CPtr', 'CPtr', 'CPtr', 'CPtr',
'CAutoPtr', 't.CAutoPtr', 'CAutoPtr', 'CAutoPtr',
'CRef', 't.CRef', 'CTempRef', 't.CTempRef', 'CRef', 'CRef', 'CTempRef', 'CTempRef',
}) })
@@ -291,7 +291,7 @@ class AnnAssignHandle(BaseHandle):
from lib.core.LLVMCG.FuncGen import FailFastError from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError( raise FailFastError(
f"隐式窄化禁止:{Value.type.width} 位整数不能隐式赋给 {TargetType.width} 位类型" f"隐式窄化禁止:{Value.type.width} 位整数不能隐式赋给 {TargetType.width} 位类型"
f"(会丢高位);请显式转换(如 int32(x) / t.CInt32T(x) )或把目标类型加宽" f"(会丢高位);请显式转换(如 int32(x) / CInt32T(x) )或把目标类型加宽"
f"{Gen._DescribeValueNode(Node)}" f"{Gen._DescribeValueNode(Node)}"
) )
else: else:
@@ -304,7 +304,7 @@ class AnnAssignHandle(BaseHandle):
from lib.core.LLVMCG.FuncGen import FailFastError from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError( raise FailFastError(
f"指针隐式转换已禁止({Reason}):不能把指针类型 {Value.type} 隐式转为 {TargetType};" f"指针隐式转换已禁止({Reason}):不能把指针类型 {Value.type} 隐式转为 {TargetType};"
f"如需转换请显式 cast(如 t.CPtr(...))" f"如需转换请显式 cast(如 CPtr(...))"
f"{Gen._DescribeValueNode(Node)}" f"{Gen._DescribeValueNode(Node)}"
) )
Value = Gen.builder.bitcast(Value, TargetType, name="ptr_bitcast") Value = Gen.builder.bitcast(Value, TargetType, name="ptr_bitcast")
@@ -316,7 +316,7 @@ class AnnAssignHandle(BaseHandle):
from lib.core.LLVMCG.FuncGen import FailFastError from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError( raise FailFastError(
f"指针隐式转整数已禁止:不能把指针类型 {Value.type} 赋给整数类型 {TargetType};" f"指针隐式转整数已禁止:不能把指针类型 {Value.type} 赋给整数类型 {TargetType};"
f"如需转换请显式 cast(如 t.CUInt64T(p) / t.CInt(p))" f"如需转换请显式 cast(如 CUInt64T(p) / CInt(p))"
f"{Gen._DescribeValueNode(Node)}" f"{Gen._DescribeValueNode(Node)}"
) )
Gen._store(Value, Ptr) Gen._store(Value, Ptr)
@@ -357,7 +357,7 @@ class AnnAssignHandle(BaseHandle):
2. alloca + __before_init__ + __new__(pool) + __before_init__ + __init__(pool) 2. alloca + __before_init__ + __new__(pool) + __before_init__ + __init__(pool)
3. 对每个元素调用 append(elem) 3. 对每个元素调用 append(elem)
4. 将堆指针存入变量 4. 将堆指针存入变量
list_sub 是从注解中提取的 list[...] Subscript 节点(支持 list[T] 和 list[T] | t.CPtr) list_sub 是从注解中提取的 list[...] Subscript 节点(支持 list[T] 和 list[T] | CPtr)
""" """
# 1. 解析元素类型 # 1. 解析元素类型
slice_node: ast.expr = list_sub.slice slice_node: ast.expr = list_sub.slice
@@ -461,10 +461,10 @@ class AnnAssignHandle(BaseHandle):
Gen.builder.call(append_func, adjusted_append, name=f"append_{VarName}_{i}") Gen.builder.call(append_func, adjusted_append, name=f"append_{VarName}_{i}")
# 10. 创建变量并存储堆指针 # 10. 创建变量并存储堆指针
# 判断变量类型:list[T] | t.CPtr → i8*;list[T] → Ptr(StructType) # 判断变量类型:list[T] | CPtr → i8*;list[T] → Ptr(StructType)
is_cptr_union: bool = isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr) is_cptr_union: bool = isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr)
if is_cptr_union: if is_cptr_union:
# list[T] | t.CPtr → 变量类型为 i8* # list[T] | CPtr → 变量类型为 i8*
i8_ptr_type: ir.PointerType = ir.PointerType(ir.IntType(8)) i8_ptr_type: ir.PointerType = ir.PointerType(ir.IntType(8))
var: ir.AllocaInstr = Gen._allocaEntry(i8_ptr_type, name=VarName) var: ir.AllocaInstr = Gen._allocaEntry(i8_ptr_type, name=VarName)
# bitcast heap_ptr (Ptr(StructType)) → i8* # bitcast heap_ptr (Ptr(StructType)) → i8*
@@ -502,9 +502,9 @@ class AnnAssignHandle(BaseHandle):
_VarName: str = Node.target.id _VarName: str = Node.target.id
_DeclCls: str | None = Gen.var_struct_class.get(_VarName) _DeclCls: str | None = Gen.var_struct_class.get(_VarName)
# 只把**真实类名**记为权威:指针/未知标记名(rawptr/CPtr/... 这些是联合 # 只把**真实类名**记为权威:指针/未知标记名(rawptr/CPtr/... 这些是联合
# 注解 `rawptr[T]`/`X | t.CPtr` 折叠后的占位名,可能恰好在 Gen.structs 里) # 注解 `rawptr[T]`/`X | CPtr` 折叠后的占位名,可能恰好在 Gen.structs 里)
# 不表态具体类,若一并记为权威会挡住"无注解赋值从右值推断类名"的正常路径 # 不表态具体类,若一并记为权威会挡住"无注解赋值从右值推断类名"的正常路径
# (如 `p: t.CPtr = Point()` 之后 `p.x` 需要 Point)。 # (如 `p: CPtr = Point()` 之后 `p.x` 需要 Point)。
if _DeclCls and not _IsPtrMarkerClassName(_DeclCls): if _DeclCls and not _IsPtrMarkerClassName(_DeclCls):
_M: dict = getattr(Gen, 'var_annotated_class', None) _M: dict = getattr(Gen, 'var_annotated_class', None)
if _M is None: if _M is None:
@@ -538,7 +538,7 @@ class AnnAssignHandle(BaseHandle):
TypeInfo: CTypeInfo | None = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.annotation) TypeInfo: CTypeInfo | None = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.annotation)
if TypeInfo is None: if TypeInfo is None:
TypeInfo = CTypeInfo() TypeInfo = CTypeInfo()
TypeInfo.BaseType = t.CInt() TypeInfo.BaseType = TypeSystem.CInt()
IsPtr: bool = TypeInfo.IsPtr IsPtr: bool = TypeInfo.IsPtr
if TypeInfo.IsDefine: if TypeInfo.IsDefine:
if Node.value and isinstance(Node.value, ast.Constant): if Node.value and isinstance(Node.value, ast.Constant):
@@ -555,7 +555,7 @@ class AnnAssignHandle(BaseHandle):
self.Trans.SymbolTable.insert(VarName, info) self.Trans.SymbolTable.insert(VarName, info)
Gen._record_var_signedness(VarName, TypeInfo.IsUInt) Gen._record_var_signedness(VarName, TypeInfo.IsUInt)
elif Node.value: elif Node.value:
# 非 Constant 表达式:尝试编译期求值(如 t.CSizeT().Size // 8) # 非 Constant 表达式:尝试编译期求值(如 CSizeT().Size // 8)
from lib.core.ConstEvaluator import ConstEvaluator, EvalContext from lib.core.ConstEvaluator import ConstEvaluator, EvalContext
ctx = EvalContext(Gen=Gen, symtab=self.Trans.SymbolTable, translator=self.Trans) ctx = EvalContext(Gen=Gen, symtab=self.Trans.SymbolTable, translator=self.Trans)
eval_val = ConstEvaluator.eval_full(Node.value, ctx) eval_val = ConstEvaluator.eval_full(Node.value, ctx)
@@ -572,7 +572,7 @@ class AnnAssignHandle(BaseHandle):
Gen._record_var_signedness(VarName, TypeInfo.IsUInt) Gen._record_var_signedness(VarName, TypeInfo.IsUInt)
return return
if TypeInfo.IsStr or (isinstance(Node.annotation, ast.Name) and Node.annotation.id == 'str'): if TypeInfo.IsStr or (isinstance(Node.annotation, ast.Name) and Node.annotation.id == 'str'):
# 仅指针层数 <= 1 才算裸 str/bytes(i8*),可以压平:`str | t.CPtr` / # 仅指针层数 <= 1 才算裸 str/bytes(i8*),可以压平:`str | CPtr` /
# `str*` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 指针数组), # `str*` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 指针数组),
# 压平会让局部变量比模块级同名全局槽少一层指针 # 压平会让局部变量比模块级同名全局槽少一层指针
# (全局走 HandlesAssign._EmitGlobalAnnAssignLlvm 的 FromNode,得到 i8**), # (全局走 HandlesAssign._EmitGlobalAnnAssignLlvm 的 FromNode,得到 i8**),
@@ -581,19 +581,19 @@ class AnnAssignHandle(BaseHandle):
# `IsStr and PtrCount <= 1` 同一条规则源。 # `IsStr and PtrCount <= 1` 同一条规则源。
if TypeInfo.PtrCount <= 1: if TypeInfo.PtrCount <= 1:
TypeInfo = CTypeInfo() TypeInfo = CTypeInfo()
TypeInfo.BaseType = t.CChar() TypeInfo.BaseType = TypeSystem.CChar()
TypeInfo.PtrCount = 1 TypeInfo.PtrCount = 1
IsPtr = True IsPtr = True
# FakeDuck: 为 str 变量创建影子结构体 a__meta__ (栈上, per-instance) # FakeDuck: 为 str 变量创建影子结构体 a__meta__ (栈上, per-instance)
# a 保持为 char* 用于 printf; a__meta__ 存储 __data__ 和 __mbuddy__ 字段 # a 保持为 char* 用于 printf; a__meta__ 存储 __data__ 和 __mbuddy__ 字段
# 仅对 str 类型创建,bytes 和 t.CChar|t.CPtr 不创建 # 仅对 str 类型创建,bytes 和 CChar|CPtr 不创建
if '_str' in Gen.structs and isinstance(Node.annotation, ast.Name) and Node.annotation.id == 'str': if '_str' in Gen.structs and isinstance(Node.annotation, ast.Name) and Node.annotation.id == 'str':
_meta_name: str = f"{VarName}__meta__" _meta_name: str = f"{VarName}__meta__"
_meta_var: ir.AllocaInstr = Gen._allocaEntry(Gen.structs['_str'], name=_meta_name) _meta_var: ir.AllocaInstr = Gen._allocaEntry(Gen.structs['_str'], name=_meta_name)
Gen.variables[_meta_name] = _meta_var Gen.variables[_meta_name] = _meta_var
# 标记指针到 str/bytes 的变量 (BinOp 注解如 str | t.CPtr) # 标记指针到 str/bytes 的变量 (BinOp 注解如 str | CPtr)
# elem_ptr[0] 应加载/存储 8 字节 (指针), 而非 1 字节 (字符) # elem_ptr[0] 应加载/存储 8 字节 (指针), 而非 1 字节 (字符)
# 仅当注解包含 str 或 bytes 时设置(t.CChar | t.CPtr 不应设置,它是纯字符指针) # 仅当注解包含 str 或 bytes 时设置(CChar | CPtr 不应设置,它是纯字符指针)
if isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr): if isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr):
if AnnotationContainsName(Node.annotation, 'str') or AnnotationContainsName(Node.annotation, 'bytes'): if AnnotationContainsName(Node.annotation, 'str') or AnnotationContainsName(Node.annotation, 'bytes'):
Gen.var_ptr_element[VarName] = True Gen.var_ptr_element[VarName] = True
@@ -608,7 +608,7 @@ class AnnAssignHandle(BaseHandle):
) )
if parse_result.is_pointer: if parse_result.is_pointer:
# 单参数 list[type] → 指针 # 单参数 list[type] → 指针
# 但如果有列表字面量初始化值 [a, b, c],则按数组 t.CArray[type, N] 处理 # 但如果有列表字面量初始化值 [a, b, c],则按数组 CArray[type, N] 处理
if not (Node.value and isinstance(Node.value, ast.List)): if not (Node.value and isinstance(Node.value, ast.List)):
VarType: ir.Type = ir.PointerType(ElemType) VarType: ir.Type = ir.PointerType(ElemType)
var: ir.AllocaInstr = Gen._allocaEntry(VarType, name=VarName) var: ir.AllocaInstr = Gen._allocaEntry(VarType, name=VarName)
@@ -652,7 +652,7 @@ class AnnAssignHandle(BaseHandle):
return return
# list[T] 泛型类注解 + list 字面量值 → 构造 list[T] 对象 + append 序列 # list[T] 泛型类注解 + list 字面量值 → 构造 list[T] 对象 + append 序列
# (list[str] = ["a", "b"] 不应走 C 数组路径,而应构造 list[str] 对象) # (list[str] = ["a", "b"] 不应走 C 数组路径,而应构造 list[str] 对象)
# 支持两种注解形式:list[T] 和 list[T] | t.CPtr # 支持两种注解形式:list[T] 和 list[T] | CPtr
list_sub: ast.Subscript | None = None list_sub: ast.Subscript | None = None
if (isinstance(Node.annotation, ast.Subscript) if (isinstance(Node.annotation, ast.Subscript)
and isinstance(Node.annotation.value, ast.Name) and isinstance(Node.annotation.value, ast.Name)
@@ -676,8 +676,8 @@ class AnnAssignHandle(BaseHandle):
return return
# Only fall back to the left operand when the union neither resolved a base # Only fall back to the left operand when the union neither resolved a base
# type nor accumulated multi-level pointers. A pointer-marker based union # type nor accumulated multi-level pointers. A pointer-marker based union
# (`t.CPtr*` = `t.CPtr | t.CPtr` => CVoid/2) is already a fully resolved # (`CPtr*` = `CPtr | CPtr` => CVoid/2) is already a fully resolved
# multi-level pointer; falling back to its left operand (`t.CPtr` => 1 layer) # multi-level pointer; falling back to its left operand (`CPtr` => 1 layer)
# used to silently degrade it to i8*. Keep PtrCount > 1 untouched. # used to silently degrade it to i8*. Keep PtrCount > 1 untouched.
if (TypeInfo.IsVoid and TypeInfo.PtrCount <= 1 if (TypeInfo.IsVoid and TypeInfo.PtrCount <= 1
and isinstance(Node.annotation, ast.BinOp)): and isinstance(Node.annotation, ast.BinOp)):
@@ -685,7 +685,7 @@ class AnnAssignHandle(BaseHandle):
Node.annotation, self.Trans, Gen) Node.annotation, self.Trans, Gen)
if found: if found:
TypeInfo = CTypeInfo() TypeInfo = CTypeInfo()
TypeInfo.BaseType = t.CStruct(name=found) TypeInfo.BaseType = TypeSystem.CStruct(name=found)
TypeInfo.PtrCount = 1 TypeInfo.PtrCount = 1
IsPtr = True IsPtr = True
elif isinstance(Node.annotation.left, ast.Attribute): elif isinstance(Node.annotation.left, ast.Attribute):
@@ -694,7 +694,7 @@ class AnnAssignHandle(BaseHandle):
TypeInfo = AttrTypeInfo TypeInfo = AttrTypeInfo
TypeInfo.PtrCount = max(TypeInfo.PtrCount, 1) TypeInfo.PtrCount = max(TypeInfo.PtrCount, 1)
IsPtr = True IsPtr = True
# 对于局部变量声明 s: TestStruct(不带 | t.CPtr),应为栈上结构体而非指针 # 对于局部变量声明 s: TestStruct(不带 | CPtr),应为栈上结构体而非指针
# GetCTypeInfo 默认设置 PtrCount=1,但纯结构体名注解应为值类型 # GetCTypeInfo 默认设置 PtrCount=1,但纯结构体名注解应为值类型
if (isinstance(Node.annotation, ast.Name) if (isinstance(Node.annotation, ast.Name)
and Node.annotation.id in Gen.structs and Node.annotation.id in Gen.structs
@@ -724,7 +724,7 @@ class AnnAssignHandle(BaseHandle):
if isinstance(VarType, ir.VoidType): if isinstance(VarType, ir.VoidType):
VarType = ir.IntType(32) VarType = ir.IntType(32)
IsUnsigned: bool = TypeInfo.IsUInt IsUnsigned: bool = TypeInfo.IsUInt
# 修复 3: BinOp 注解(如 ast.Arguments | t.CPtr)的 var_struct_class 设置 # 修复 3: BinOp 注解(如 ast.Arguments | CPtr)的 var_struct_class 设置
# TypeInfo.Name 由 _HandleSubscript 设置(特化名如 list[sha1.ASTptr])或 # TypeInfo.Name 由 _HandleSubscript 设置(特化名如 list[sha1.ASTptr])或
# GetCTypeInfo 设置(普通结构体名),经 _MergeCTypeInfoInto 传播后保留。 # GetCTypeInfo 设置(普通结构体名),经 _MergeCTypeInfoInto 传播后保留。
# 此处确保 BinOp 注解的变量也能被 _get_var_class 识别,避免方法调用分派 # 此处确保 BinOp 注解的变量也能被 _get_var_class 识别,避免方法调用分派
@@ -734,7 +734,7 @@ class AnnAssignHandle(BaseHandle):
if VarName not in Gen.var_struct_class: if VarName not in Gen.var_struct_class:
Gen.var_struct_class[VarName] = TypeInfo.Name Gen.var_struct_class[VarName] = TypeInfo.Name
Gen.global_struct_class[VarName] = TypeInfo.Name Gen.global_struct_class[VarName] = TypeInfo.Name
# 联合指针注解(X | t.CPtr)短名回退:resolver 对模块限定 struct # 联合指针注解(X | CPtr)短名回退:resolver 对模块限定 struct
# 段(如 llvmlite.Value)无法精确 in Gen.structs(键可能是 'Value' # 段(如 llvmlite.Value)无法精确 in Gen.structs(键可能是 'Value'
# 或带 sha1 前缀),Name 常退化为指针别名 'rawptr'(被注册成 opaque # 或带 sha1 前缀),Name 常退化为指针别名 'rawptr'(被注册成 opaque
# struct)→ 变量 var_struct_class 登记为 rawptr → 字段访问 # struct)→ 变量 var_struct_class 登记为 rawptr → 字段访问
@@ -744,7 +744,7 @@ class AnnAssignHandle(BaseHandle):
and isinstance(Node.annotation.op, ast.BitOr)): and isinstance(Node.annotation.op, ast.BitOr)):
_union_struct_name2: str | None = FindStructNameInAnnotationWithContext( _union_struct_name2: str | None = FindStructNameInAnnotationWithContext(
Node.annotation, self.Trans, Gen) Node.annotation, self.Trans, Gen)
# resolver 对模块限定 struct 联合(llvmlite.Value | t.CPtr)常给出 # resolver 对模块限定 struct 联合(llvmlite.Value | CPtr)常给出
# 指针占位名(如 '{sha1}.rawptr')且该占位恰好注册在 Gen.structs, # 指针占位名(如 '{sha1}.rawptr')且该占位恰好注册在 Gen.structs,
# 使上方 TypeInfo.Name in Gen.structs 通过并登记错误类名 → 字段 # 使上方 TypeInfo.Name in Gen.structs 通过并登记错误类名 → 字段
# 访问 "属性 'Next' 在类 'rawptr' 中找不到"。凡短名命中真实类 # 访问 "属性 'Next' 在类 'rawptr' 中找不到"。凡短名命中真实类
@@ -754,7 +754,7 @@ class AnnAssignHandle(BaseHandle):
Gen.var_struct_class[VarName] = _union_struct_name2 Gen.var_struct_class[VarName] = _union_struct_name2
if getattr(Gen, 'global_struct_class', None) is not None: if getattr(Gen, 'global_struct_class', None) is not None:
Gen.global_struct_class[VarName] = _union_struct_name2 Gen.global_struct_class[VarName] = _union_struct_name2
# Subscript rawptr[X] / t.CPtr[X] 注解的本地结构指针变量(如 # Subscript rawptr[X] / CPtr[X] 注解的本地结构指针变量(如
# includes/ast/parser.vp _fix_store_ctx 里 `tp: rawptr[Tuple] = # includes/ast/parser.vp _fix_store_ctx 里 `tp: rawptr[Tuple] =
# (rawptr[Tuple])(node)`,随后 `tp_elts = tp.elts`):TypeMerge 的 # (rawptr[Tuple])(node)`,随后 `tp_elts = tp.elts`):TypeMerge 的
# builtins 分支把 rawptr[X] 折叠为 i8*(PtrCount=1/CVoid),既不登记 # builtins 分支把 rawptr[X] 折叠为 i8*(PtrCount=1/CVoid),既不登记
@@ -771,7 +771,7 @@ class AnnAssignHandle(BaseHandle):
_rst_nm = _rst_v.id _rst_nm = _rst_v.id
elif isinstance(_rst_v, ast.Attribute) and isinstance(_rst_v.value, ast.Name): elif isinstance(_rst_v, ast.Attribute) and isinstance(_rst_v.value, ast.Name):
_rst_nm = f'{_rst_v.value.id}.{_rst_v.attr}' _rst_nm = f'{_rst_v.value.id}.{_rst_v.attr}'
if _rst_nm in ('rawptr', 't.CPtr'): if _rst_nm in ('rawptr', 'CPtr'):
_rst_sub = Node.annotation _rst_sub = Node.annotation
if _rst_sub is not None: if _rst_sub is not None:
_rst_sl: ast.AST = _rst_sub.slice _rst_sl: ast.AST = _rst_sub.slice
@@ -804,19 +804,17 @@ class AnnAssignHandle(BaseHandle):
Gen.var_struct_class[VarName] = _rst_tk Gen.var_struct_class[VarName] = _rst_tk
if getattr(Gen, 'global_struct_class', None) is not None: if getattr(Gen, 'global_struct_class', None) is not None:
Gen.global_struct_class[VarName] = _rst_tk Gen.global_struct_class[VarName] = _rst_tk
# 检测指针到指针缓冲区变量:注解为 StructName | t.CPtr,且赋值来自 t.CPtr(...) 调用。 # 检测指针到指针缓冲区变量:注解为 StructName | CPtr,且赋值来自 CPtr(...) 调用。
# 这种变量(如 list[T].__getitem__ 中的 elem_ptr: T | t.CPtr = t.CPtr(...)) # 这种变量(如 list[T].__getitem__ 中的 elem_ptr: T | CPtr = CPtr(...))
# 实际指向存储结构体指针的缓冲区(T=AST|t.CPtr 时特化为 AST*,缓冲区存 AST* 数组)。 # 实际指向存储结构体指针的缓冲区(T=AST|CPtr 时特化为 AST*,缓冲区存 AST* 数组)。
# [index] 应 bitcast 为 AST** 后 GEP 指针数组再 load,而非 GEP 结构体数组。 # [index] 应 bitcast 为 AST** 后 GEP 指针数组再 load,而非 GEP 结构体数组。
# 泛型特化将 T|t.CPtr 降级为 StructName|t.CPtr(丢失一层指针),故通过赋值来源区分: # 泛型特化将 T|CPtr 降级为 StructName|CPtr(丢失一层指针),故通过赋值来源区分:
# elem_ptr 的值是 t.CPtr(buf + idx*elem_size)(原始指针运算,缓冲区内容未知), # elem_ptr 的值是 CPtr(buf + idx*elem_size)(原始指针运算,缓冲区内容未知),
# pts 的值是 (Point|t.CPtr)(...)(类型转换,明确指向 Point 结构体)。 # pts 的值是 (Point|CPtr)(...)(类型转换,明确指向 Point 结构体)。
_is_cptr_assign: bool = ( _is_cptr_assign: bool = (
isinstance(Node.value, ast.Call) isinstance(Node.value, ast.Call)
and isinstance(Node.value.func, ast.Attribute) and isinstance(Node.value.func, ast.Name)
and isinstance(Node.value.func.value, ast.Name) and Node.value.func.id == 'CPtr'
and Node.value.func.value.id == 't'
and Node.value.func.attr == 'CPtr'
) )
_is_struct_ptr_union: bool = ( _is_struct_ptr_union: bool = (
isinstance(Node.annotation, ast.BinOp) isinstance(Node.annotation, ast.BinOp)
@@ -932,9 +930,9 @@ class AnnAssignHandle(BaseHandle):
var: ir.AllocaInstr = Gen._allocaEntry(VarType, name=VarName) var: ir.AllocaInstr = Gen._allocaEntry(VarType, name=VarName)
if InitValue and isinstance(InitValue.type, ir.PointerType): if InitValue and isinstance(InitValue.type, ir.PointerType):
pointee: ir.Type = InitValue.type.pointee pointee: ir.Type = InitValue.type.pointee
# 当 InitValue 是 i8* (t.CPtr) 且注解是 Gen.structs 中的结构体名时, # 当 InitValue 是 i8* (CPtr) 且注解是 Gen.structs 中的结构体名时,
# bitcast 为对应的结构体指针,以便正确存储和设置 var_struct_class # bitcast 为对应的结构体指针,以便正确存储和设置 var_struct_class
# 例如: sub: dict = sub_p (sub_p 是 t.CPtr) # 例如: sub: dict = sub_p (sub_p 是 CPtr)
if (isinstance(pointee, ir.IntType) and pointee.width == 8 if (isinstance(pointee, ir.IntType) and pointee.width == 8
and isinstance(Node.annotation, ast.Name) and isinstance(Node.annotation, ast.Name)
and Node.annotation.id in Gen.structs): and Node.annotation.id in Gen.structs):
@@ -961,10 +959,10 @@ class AnnAssignHandle(BaseHandle):
Gen.global_struct_class[VarName] = Node.annotation.id Gen.global_struct_class[VarName] = Node.annotation.id
Gen._record_var_signedness(VarName, IsUnsigned) Gen._record_var_signedness(VarName, IsUnsigned)
return return
# 方向判定用:取注解一侧的泛型基名(`Base[...]` 或 `Base[...] | t.CPtr` # 方向判定用:取注解一侧的泛型基名(`Base[...]` 或 `Base[...] | CPtr`
# 形态中的 Base)。此判据**不依赖泛型模板注册表**(list/dict 等内建 # 形态中的 Base)。此判据**不依赖泛型模板注册表**(list/dict 等内建
# 容器可能未登记),只做结构性识别;仅 Name 形态可识别,属性链 # 容器可能未登记),只做结构性识别;仅 Name 形态可识别,属性链
# (如 t.CPtr[...])不参与。 # (如 CPtr[...])不参与。
_ann_gen_base: str | None = None _ann_gen_base: str | None = None
_ann_sub_side: ast.expr | None = None _ann_sub_side: ast.expr | None = None
if isinstance(Node.annotation, ast.Subscript): if isinstance(Node.annotation, ast.Subscript):
@@ -983,7 +981,7 @@ class AnnAssignHandle(BaseHandle):
if isinstance(_ann_base_v, ast.Name): if isinstance(_ann_base_v, ast.Name):
_ann_gen_base = _ann_base_v.id _ann_gen_base = _ann_base_v.id
# 「反向重建」方向判定(其二,见下方 _rb_is_upcast)所需的**注解侧 # 「反向重建」方向判定(其二,见下方 _rb_is_upcast)所需的**注解侧
# 被指类**:注解被 TypeMerge 折叠成 i8*(rawptr[X] / t.CPtr[X],见 # 被指类**:注解被 TypeMerge 折叠成 i8*(rawptr[X] / CPtr[X],见
# 上方 635-684)时 VarType.pointee 不是结构体,此时用该处恢复进 # 上方 635-684)时 VarType.pointee 不是结构体,此时用该处恢复进
# var_struct_class 的 X —— 那正是注解写明的被指类。 # var_struct_class 的 X —— 那正是注解写明的被指类。
_ann_pointee: ir.Type | None = None _ann_pointee: ir.Type | None = None
@@ -1006,13 +1004,13 @@ class AnnAssignHandle(BaseHandle):
if _IsGenericTpName(_cn_short): if _IsGenericTpName(_cn_short):
continue continue
# rawptr 占位 struct('rawptr' / '{sha1}.rawptr' / 'rawptr[...]')是 # rawptr 占位 struct('rawptr' / '{sha1}.rawptr' / 'rawptr[...]')是
# 模块限定联合 X | t.CPtr 被 resolver 退化的产物(无真实字段), # 模块限定联合 X | CPtr 被 resolver 退化的产物(无真实字段),
# 绝不能覆盖注解已解析出的真实类名(如 Value)→ env_size_val.Next # 绝不能覆盖注解已解析出的真实类名(如 Value)→ env_size_val.Next
# 报 "属性在类 'rawptr' 中找不到"(FuncGenMixin.vp L307 根因)。 # 报 "属性在类 'rawptr' 中找不到"(FuncGenMixin.vp L307 根因)。
if CN == 'rawptr' or CN.endswith('.rawptr') or CN.startswith('rawptr['): if CN == 'rawptr' or CN.endswith('.rawptr') or CN.startswith('rawptr['):
continue continue
if pointee is ST or pointee == ST: if pointee is ST or pointee == ST:
# 若注解是泛型特化(如 ndarray[t.CDouble] | t.CPtr), # 若注解是泛型特化(如 ndarray[CDouble] | CPtr),
# 构造正确的特化名(如 ndarray[double]),而非用 opaque 基础名 # 构造正确的特化名(如 ndarray[double]),而非用 opaque 基础名
resolved_cn: str = CN resolved_cn: str = CN
if isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr) and '[' not in CN: if isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr) and '[' not in CN:
@@ -1041,7 +1039,7 @@ class AnnAssignHandle(BaseHandle):
# RHS 构造出精确特化 ⇒ 用 RHS 反向升级」(见 L765 注释)。 # RHS 构造出精确特化 ⇒ 用 RHS 反向升级」(见 L765 注释)。
# 但 RHS 的 pointee 若为**裸泛型基类**(丢类型实参,如 # 但 RHS 的 pointee 若为**裸泛型基类**(丢类型实参,如
# {sha1}.list)而注解一侧本身就是带类型实参的泛型 # {sha1}.list)而注解一侧本身就是带类型实参的泛型
# (`Base[...]` 或 `Base[...] | t.CPtr`),以 RHS 重建 # (`Base[...]` 或 `Base[...] | CPtr`),以 RHS 重建
# alloca 会把注解已解析出的特化类型覆盖成裸基类 → 之后 # alloca 会把注解已解析出的特化类型覆盖成裸基类 → 之后
# .get() 按错误元素类型分派(list[int].get 返回 i32)→ # .get() 按错误元素类型分派(list[int].get 返回 i32)→
# inttoptr 截断指针 → 读垃圾 AST 节点崩溃 # inttoptr 截断指针 → 读垃圾 AST 节点崩溃
@@ -1098,7 +1096,7 @@ class AnnAssignHandle(BaseHandle):
from lib.core.LLVMCG.FuncGen import FailFastError from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError( raise FailFastError(
f"指针隐式转换已禁止({Reason}):不能用指针类型 {InitValue.type} 初始化 " f"指针隐式转换已禁止({Reason}):不能用指针类型 {InitValue.type} 初始化 "
f"{VarName}: {VarType};如需转换请显式 cast(如 t.CPtr(...))" f"{VarName}: {VarType};如需转换请显式 cast(如 CPtr(...))"
f"{Gen._DescribeValueNode(Node.value)}" f"{Gen._DescribeValueNode(Node.value)}"
) )
InitValue = Gen.builder.bitcast(InitValue, VarType, name=f"cast_{VarName}") InitValue = Gen.builder.bitcast(InitValue, VarType, name=f"cast_{VarName}")
@@ -1110,7 +1108,7 @@ class AnnAssignHandle(BaseHandle):
from lib.core.LLVMCG.FuncGen import FailFastError from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError( raise FailFastError(
f"指针隐式转整数已禁止:不能用指针类型 {InitValue.type} 初始化整数变量 " f"指针隐式转整数已禁止:不能用指针类型 {InitValue.type} 初始化整数变量 "
f"{VarName}: {VarType};如需转换请显式 cast(如 t.CUInt64T(p) / t.CInt(p))" f"{VarName}: {VarType};如需转换请显式 cast(如 CUInt64T(p) / CInt(p))"
f"{Gen._DescribeValueNode(Node.value)}" f"{Gen._DescribeValueNode(Node.value)}"
) )
# 大端局部变量:存储时 bswap # 大端局部变量:存储时 bswap
@@ -1150,7 +1148,7 @@ class AnnAssignHandle(BaseHandle):
found_struct: str | None = FindStructNameInAnnotationWithContext( found_struct: str | None = FindStructNameInAnnotationWithContext(
Node.annotation, self.Trans, Gen) Node.annotation, self.Trans, Gen)
# 若 FindStructNameInAnnotation 仅返回裸模板名(如 'ndarray'),但注解中 # 若 FindStructNameInAnnotation 仅返回裸模板名(如 'ndarray'),但注解中
# 含泛型特化(如 numpy.ndarray[t.CDouble]),用 LLVM 类型名构造特化名 # 含泛型特化(如 numpy.ndarray[CDouble]),用 LLVM 类型名构造特化名
# (如 'ndarray[double]')。main.py 的 Gen.structs 可能只有 opaque 'ndarray', # (如 'ndarray[double]')。main.py 的 Gen.structs 可能只有 opaque 'ndarray',
# 但 numpy 模块已特化 ndarray[double],方法调用通过 sha1 前缀查找。 # 但 numpy 模块已特化 ndarray[double],方法调用通过 sha1 前缀查找。
if found_struct and '[' not in found_struct: if found_struct and '[' not in found_struct:
@@ -1196,7 +1194,7 @@ class AnnAssignHandle(BaseHandle):
self.Trans.VarScopes[-1][VarName] = TypeInfo self.Trans.VarScopes[-1][VarName] = TypeInfo
else: else:
DefaultInfo: CTypeInfo = CTypeInfo() DefaultInfo: CTypeInfo = CTypeInfo()
DefaultInfo.BaseType = t.CInt DefaultInfo.BaseType = TypeSystem.CInt
self.Trans.VarScopes[-1][VarName] = DefaultInfo self.Trans.VarScopes[-1][VarName] = DefaultInfo
elif isinstance(Node.target, ast.Attribute): elif isinstance(Node.target, ast.Attribute):
if isinstance(Node.target.value, ast.Name) and Node.target.value.id == 'self': if isinstance(Node.target.value, ast.Name) and Node.target.value.id == 'self':
@@ -1206,16 +1204,16 @@ class AnnAssignHandle(BaseHandle):
if IsListAnnotation(Node.annotation): if IsListAnnotation(Node.annotation):
slice_node: ast.AST = Node.annotation.slice slice_node: ast.AST = Node.annotation.slice
if isinstance(slice_node, ast.Name): if isinstance(slice_node, ast.Name):
AttrVarType = f't.CArray[{slice_node.id}]' AttrVarType = f'CArray[{slice_node.id}]'
elif isinstance(slice_node, ast.Tuple): elif isinstance(slice_node, ast.Tuple):
elts: str = ', '.join(getattr(e, 'id', str(e)) for e in slice_node.elts) elts: str = ', '.join(getattr(e, 'id', str(e)) for e in slice_node.elts)
AttrVarType = f't.CArray[{elts}]' AttrVarType = f'CArray[{elts}]'
elif isinstance(slice_node, ast.Attribute): elif isinstance(slice_node, ast.Attribute):
# 还原 t.xxx 形式(如 t.CInt、t.CArray) # 还原模块限定类型名(如 ns.CInt)
if isinstance(slice_node.value, ast.Name): if isinstance(slice_node.value, ast.Name):
AttrVarType = f't.CArray[{slice_node.value.id}.{slice_node.attr}]' AttrVarType = f'CArray[{slice_node.value.id}.{slice_node.attr}]'
else: else:
AttrVarType = f't.CArray[{ast.unparse(slice_node)}]' AttrVarType = f'CArray[{ast.unparse(slice_node)}]'
if AttrVarType is None: if AttrVarType is None:
AttrTypeInfo: CTypeInfo | None = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable) AttrTypeInfo: CTypeInfo | None = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable)
if AttrTypeInfo: if AttrTypeInfo:
+59 -66
View File
@@ -9,9 +9,9 @@ from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta
from lib.core.VLogger import get_logger as _vlog from lib.core.VLogger import get_logger as _vlog
from lib.core.ConstEvaluator import ConstEvaluator, EvalContext from lib.core.ConstEvaluator import ConstEvaluator, EvalContext
from lib.constants.config import mode as _config_mode from lib.constants.config import mode as _config_mode
from lib.includes import t from lib.core import TypeSystem
from lib.includes.t import CTypeRegistry from lib.core.TypeSystem import CTypeRegistry
from lib.core.SymbolUtils import IsTModule, ParseListAnnotation, AnnotationContainsName from lib.core.SymbolUtils import ParseListAnnotation, AnnotationContainsName
class AssignHandle(BaseHandle): class AssignHandle(BaseHandle):
def __init__(self, translator: "Translator") -> None: def __init__(self, translator: "Translator") -> None:
@@ -62,7 +62,7 @@ class AssignHandle(BaseHandle):
if Gen._IsVarConst(VarName): if Gen._IsVarConst(VarName):
_vlog().error(Gen._ConstAssignMessage("赋值", VarName)) _vlog().error(Gen._ConstAssignMessage("赋值", VarName))
sys.exit(1) sys.exit(1)
if isinstance(Node.value, ast.Attribute) and isinstance(Node.value.value, ast.Name) and IsTModule(Node.value.value.id, self.Trans.SymbolTable): if isinstance(Node.value, ast.Attribute) and isinstance(Node.value.value, ast.Name) :
AttrName: str = Node.value.attr AttrName: str = Node.value.attr
Gen.var_type_info[VarName] = {'type': 't_type', 'name': AttrName} Gen.var_type_info[VarName] = {'type': 't_type', 'name': AttrName}
Gen.var_type_assignments.setdefault(VarName, []).append({'type': 't_type', 'name': AttrName}) Gen.var_type_assignments.setdefault(VarName, []).append({'type': 't_type', 'name': AttrName})
@@ -201,7 +201,7 @@ class AssignHandle(BaseHandle):
# 【右值形态判定】只有"取地址形态"的右值才需要自动解一层引用:Name/Attribute/ # 【右值形态判定】只有"取地址形态"的右值才需要自动解一层引用:Name/Attribute/
# Subscript 的求值结果是**存储地址**(变量 alloca / 字段地址 /"对象即指针"), # Subscript 的求值结果是**存储地址**(变量 alloca / 字段地址 /"对象即指针"),
# 赋给指针变量时必须 load 出内层指针。而 Call(显式 cast 如 `str*(addr)`、 # 赋给指针变量时必须 load 出内层指针。而 Call(显式 cast 如 `str*(addr)`、
# `t.CPtr(x)`,以及构造/普通函数调用)与其它表达式给出的是**值本身**, # `CPtr(x)`,以及构造/普通函数调用)与其它表达式给出的是**值本身**,
# 再 load 会多解一层 → 静默取到野指针(现场 includes/argparse.vp 的 # 再 load 会多解一层 → 静默取到野指针(现场 includes/argparse.vp 的
# `entry = str*(uint64(argv) + idx*8)`:i8** 右值被多解一次,entry 变成 # `entry = str*(uint64(argv) + idx*8)`:i8** 右值被多解一次,entry 变成
# argv[idx] 本身,随后 entry[0] 去读字符串头 8 字节 → ASan access-violation)。 # argv[idx] 本身,随后 entry[0] 去读字符串头 8 字节 → ASan access-violation)。
@@ -312,7 +312,7 @@ class AssignHandle(BaseHandle):
# 【联合返回注解的被指类恢复】RHS 是调用、且值的 LLVM 类型是**通用指针** # 【联合返回注解的被指类恢复】RHS 是调用、且值的 LLVM 类型是**通用指针**
# (i8*/i8**,pointee 不是结构体)时,上面那块类名推断整块失效 —— 现场 # (i8*/i8**,pointee 不是结构体)时,上面那块类名推断整块失效 —— 现场
# `parts = s1.split(',')`:`split` 的返回注解 `list[str]*` ≡ # `parts = s1.split(',')`:`split` 的返回注解 `list[str]*` ≡
# `list[str] | t.CPtr`(只读探针确认二者 AST 逐字同形)被映射成 i8* # `list[str] | CPtr`(只读探针确认二者 AST 逐字同形)被映射成 i8*
# ⇒ 类名丢失 ⇒ 随后 `parts[0]` 不走 `list[str].__getitem__` 而按通用 # ⇒ 类名丢失 ⇒ 随后 `parts[0]` 不走 `list[str].__getitem__` 而按通用
# 指针/字节索引 ⇒ 得到整数 ⇒ 赋给 `str` 时报"整数隐式转指针已禁止" # 指针/字节索引 ⇒ 得到整数 ⇒ 赋给 `str` 时报"整数隐式转指针已禁止"
# (真因在 4 行之前,报文完全指不到)。此处从被调者的**返回注解** # (真因在 4 行之前,报文完全指不到)。此处从被调者的**返回注解**
@@ -586,7 +586,7 @@ class AssignHandle(BaseHandle):
f"解引用赋值 '*' 的操作数必须是指针类型(类型推断退化," f"解引用赋值 '*' 的操作数必须是指针类型(类型推断退化,"
f"实际 {Ptr.type}){Gen._get_node_info()}" f"实际 {Ptr.type}){Gen._get_node_info()}"
) )
# `*a = *b` is the c.Load form: copy the raw bytes (width = target # `*a = *b` is the Load form: copy the raw bytes (width = target
# pointee), never convert the value. Without it a bit-pun such as # pointee), never convert the value. Without it a bit-pun such as
# `*&bits = *&dbl` degrades to fptosi/trunc and loses the IEEE bits. # `*&bits = *&dbl` degrades to fptosi/trunc and loses the IEEE bits.
if isinstance(Node.value, ast.UnaryOp) and isinstance(Node.value.op, ast.Deref): if isinstance(Node.value, ast.UnaryOp) and isinstance(Node.value.op, ast.Deref):
@@ -642,10 +642,10 @@ class AssignHandle(BaseHandle):
if FuncDef.decorator_list: if FuncDef.decorator_list:
for decorator in FuncDef.decorator_list: for decorator in FuncDef.decorator_list:
if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute): if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute):
# fail-fast:`@c.CReturn` 已移除,扫到即报错。 # fail-fast:`@CReturn` 已移除,扫到即报错。
if decorator.func.attr == 'CReturn': if decorator.func.attr == 'CReturn':
raise SyntaxError( raise SyntaxError(
f"函数 '{FuncName}':`@c.CReturn` 已移除:请改用返回注解 " f"函数 '{FuncName}':`@CReturn` 已移除:请改用返回注解 "
f"`-> tuple[ty1, ty2, ...]`(多返回值打包为 struct)" f"`-> tuple[ty1, ty2, ...]`(多返回值打包为 struct)"
f"{Gen._get_node_info()}" f"{Gen._get_node_info()}"
) )
@@ -772,7 +772,7 @@ class AssignHandle(BaseHandle):
ReturnTypeInfo: CTypeInfo | None = CTypeInfo.FromNode(MultiRetTypes[j], self.Trans.SymbolTable) ReturnTypeInfo: CTypeInfo | None = CTypeInfo.FromNode(MultiRetTypes[j], self.Trans.SymbolTable)
if ReturnTypeInfo is None: if ReturnTypeInfo is None:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CInt() ReturnTypeInfo.BaseType = TypeSystem.CInt()
VarType = Gen._ctype_to_llvm(ReturnTypeInfo) VarType = Gen._ctype_to_llvm(ReturnTypeInfo)
elif ret_type and isinstance(ret_type, ir.LiteralStructType) and j < len(ret_type.elements): elif ret_type and isinstance(ret_type, ir.LiteralStructType) and j < len(ret_type.elements):
VarType = ret_type.elements[j] VarType = ret_type.elements[j]
@@ -1265,7 +1265,7 @@ class AssignHandle(BaseHandle):
# 同一套 `_DescribeMemberSlot`):槽类型的两条独立来源 # 同一套 `_DescribeMemberSlot`):槽类型的两条独立来源
# (class_members 声明侧 / struct body 布局侧)不一致时,值会被 # (class_members 声明侧 / struct body 布局侧)不一致时,值会被
# 写进类型完全不同的槽(现场:`self.Gen.TypeGenCType. # 写进类型完全不同的槽(现场:`self.Gen.TypeGenCType.
# LastBuiltinsTypedefResult = "t.CPtr"` 落到 i32 槽 → 指针隐式 # LastBuiltinsTypedefResult = "CPtr"` 落到 i32 槽 → 指针隐式
# 转整数 fail-fast);报文里逐项列出两侧数据即可直接判定谁退化 # 转整数 fail-fast);报文里逐项列出两侧数据即可直接判定谁退化
# (此处目标形态是 `对象.字段 = 值`,Base 侧同理取 ObjVal 所指布局)。 # (此处目标形态是 `对象.字段 = 值`,Base 侧同理取 ObjVal 所指布局)。
try: try:
@@ -1367,15 +1367,13 @@ class AssignHandle(BaseHandle):
self._StoreWithCoerce(Value, MemberPtr) self._StoreWithCoerce(Value, MemberPtr)
return return
elif isinstance(Target.value, ast.Call): elif isinstance(Target.value, ast.Call):
# Check if this is c.Deref(...) — we need the pointer, not the Loaded value # Check if this is Deref(...) — we need the pointer, not the Loaded value
ObjVal: ir.Value | None = None ObjVal: ir.Value | None = None
is_cderef: bool = (isinstance(Target.value.func, ast.Attribute) and is_cderef: bool = (isinstance(Target.value.func, ast.Name) and
isinstance(Target.value.func.value, ast.Name) and Target.value.func.id == 'Deref' and
Target.value.func.value.id == 'c' and
Target.value.func.attr == 'Deref' and
Target.value.args) Target.value.args)
if is_cderef: if is_cderef:
# Get the pointer from c.Deref argument, don't Load the value # Get the pointer from Deref argument, don't Load the value
deref_arg: ast.expr = Target.value.args[0] deref_arg: ast.expr = Target.value.args[0]
inner_val: ir.Value | None = self.HandleExprLlvm(deref_arg) inner_val: ir.Value | None = self.HandleExprLlvm(deref_arg)
if inner_val and isinstance(inner_val.type, ir.PointerType): if inner_val and isinstance(inner_val.type, ir.PointerType):
@@ -1481,7 +1479,7 @@ class AssignHandle(BaseHandle):
obj_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(Target.value) obj_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(Target.value)
idx_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(Target.slice) idx_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(Target.slice)
if obj_val and idx_val: if obj_val and idx_val:
# 处理 obj_val 为 i8(整数)的情况:联合类型 | t.CPtr 降级后可能被 load 为 i8 # 处理 obj_val 为 i8(整数)的情况:联合类型 | CPtr 降级后可能被 load 为 i8
if isinstance(obj_val.type, ir.IntType) and obj_val.type.width == 8: if isinstance(obj_val.type, ir.IntType) and obj_val.type.width == 8:
obj_val = Gen.builder.inttoptr(obj_val, ir.PointerType(ir.IntType(8)), name=f"i8_to_ptr_{ClassName}") obj_val = Gen.builder.inttoptr(obj_val, ir.PointerType(ir.IntType(8)), name=f"i8_to_ptr_{ClassName}")
if BaseHandle._is_char_pointer(obj_val): if BaseHandle._is_char_pointer(obj_val):
@@ -1497,7 +1495,7 @@ class AssignHandle(BaseHandle):
IndexVal: ir.Value | None = self.HandleExprLlvm(Target.slice) IndexVal: ir.Value | None = self.HandleExprLlvm(Target.slice)
if not ValueVal or not IndexVal: if not ValueVal or not IndexVal:
return return
# 当变量本身是二级指针(如 elem_ptr: T | t.CPtr = AST**), # 当变量本身是二级指针(如 elem_ptr: T | CPtr = AST**),
# 且存储的值也是指针时,elem_ptr[i] = item 应直接存储指针(8 字节), # 且存储的值也是指针时,elem_ptr[i] = item 应直接存储指针(8 字节),
# 而非解引用后复制结构体(如 48 字节的 AST),避免对象切片 # 而非解引用后复制结构体(如 48 字节的 AST),避免对象切片
if isinstance(Target.value, ast.Name): if isinstance(Target.value, ast.Name):
@@ -1552,7 +1550,7 @@ class AssignHandle(BaseHandle):
and isinstance(Target.value, ast.Name) and isinstance(Target.value, ast.Name)
and (Gen.var_ptr_element.get(Target.value.id, False) and (Gen.var_ptr_element.get(Target.value.id, False)
or Gen.global_var_ptr_element.get(Target.value.id, False))): or Gen.global_var_ptr_element.get(Target.value.id, False))):
# 指针到 str/bytes 的变量 (BinOp 注解如 str | t.CPtr) # 指针到 str/bytes 的变量 (BinOp 注解如 str | CPtr)
# elem_ptr 是 i8* 但实际指向 i8* (字符串指针), elem_ptr[0] = item 应存储 8 字节 # elem_ptr 是 i8* 但实际指向 i8* (字符串指针), elem_ptr[0] = item 应存储 8 字节
CastedPtrPtr: ir.Value = Gen.builder.bitcast(ValueVal, ir.PointerType(ir.PointerType(ir.IntType(8))), name="cast_pp_str_store") CastedPtrPtr: ir.Value = Gen.builder.bitcast(ValueVal, ir.PointerType(ir.PointerType(ir.IntType(8))), name="cast_pp_str_store")
if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64:
@@ -1564,7 +1562,7 @@ class AssignHandle(BaseHandle):
ElemPtr: ir.Value = Gen.builder.gep(ValueVal, [IndexVal], name=f"subscript{_PVSuffix}") ElemPtr: ir.Value = Gen.builder.gep(ValueVal, [IndexVal], name=f"subscript{_PVSuffix}")
# fail-fast:rawptr[T](基座是指针存储)的元素为对象 T、而 RHS 是指向 T # fail-fast:rawptr[T](基座是指针存储)的元素为对象 T、而 RHS 是指向 T
# 的指针时,下游 _StoreWithCoerce/_coerce_value 会静默 load 整对象再按 # 的指针时,下游 _StoreWithCoerce/_coerce_value 会静默 load 整对象再按
# sizeof(T) 存储(写 sizeof(T) 而非 8 字节指针)。数组槽(t.CArray[T,N]) # sizeof(T) 存储(写 sizeof(T) 而非 8 字节指针)。数组槽(CArray[T,N])
# 本就按 sizeof(T) 布局,整对象赋值合法 ⇒ 由 IsArrayBase 排除。 # 本就按 sizeof(T) 布局,整对象赋值合法 ⇒ 由 IsArrayBase 排除。
self._RejectWholeObjectCopyIntoPtrSlot( self._RejectWholeObjectCopyIntoPtrSlot(
Target, Value, ElemPtr, isinstance(pointee, ir.ArrayType)) Target, Value, ElemPtr, isinstance(pointee, ir.ArrayType))
@@ -1639,10 +1637,10 @@ class AssignHandle(BaseHandle):
# 越界 sizeof(T)-8 字节,写穿相邻块(MemBuddy 空闲链表被写穿的静默降级根因)。 # 越界 sizeof(T)-8 字节,写穿相邻块(MemBuddy 空闲链表被写穿的静默降级根因)。
# #
# 不拦(判据刻意收窄,避免误伤): # 不拦(判据刻意收窄,避免误伤):
# · 数组槽 t.CArray[T,N](IsArrayBase=True):元素槽本就按 sizeof(T) 布局, # · 数组槽 CArray[T,N](IsArrayBase=True):元素槽本就按 sizeof(T) 布局,
# `v[i] = T(...)`(构造函数返回临时对象地址)是合法的整对象复制; # `v[i] = T(...)`(构造函数返回临时对象地址)是合法的整对象复制;
# · 元素是标量(rawptr[int]):ElemPtr 元素不是结构体; # · 元素是标量(rawptr[int]):ElemPtr 元素不是结构体;
# · 元素本身是指针(rawptr[rawptr[T]] / X|t.CPtr):元素类型是 Ptr; # · 元素本身是指针(rawptr[rawptr[T]] / X|CPtr):元素类型是 Ptr;
# · RHS 所指类型与元素类型不一致(非本形态)。 # · RHS 所指类型与元素类型不一致(非本形态)。
# 与 VPC AssignGenMixin._reject_whole_object_copy_into_ptr_slot 同口径。 # 与 VPC AssignGenMixin._reject_whole_object_copy_into_ptr_slot 同口径。
# ============================================================ # ============================================================
@@ -1682,8 +1680,8 @@ class AssignHandle(BaseHandle):
f"而不是按指针写 {PtrSize} 字节。若该地址实际按 8 字节槽存放指针" f"而不是按指针写 {PtrSize} 字节。若该地址实际按 8 字节槽存放指针"
f"(如 rawptr[T] 缓冲/空闲链表),每写一个元素就越界 {Over} 字节," f"(如 rawptr[T] 缓冲/空闲链表),每写一个元素就越界 {Over} 字节,"
f"直接写穿相邻块。修法:把指针槽的基座类型写成指针元素形态" f"直接写穿相邻块。修法:把指针槽的基座类型写成指针元素形态"
f"(`rawptr[T] | t.CPtr` 或 `rawptr[rawptr[T]]`)后再赋值;" f"(`rawptr[T] | CPtr` 或 `rawptr[rawptr[T]]`)后再赋值;"
f"或把基座显式转为 t.CPtr(无类型指针)后按 8 字节指针语义写入。{SrcInfo}") f"或把基座显式转为 CPtr(无类型指针)后按 8 字节指针语义写入。{SrcInfo}")
def _DescribeMemberSlot(self, Gen: "Translator.LlvmGen", ClassName: str | None, def _DescribeMemberSlot(self, Gen: "Translator.LlvmGen", ClassName: str | None,
FieldName: str, Offset: int, SelfPtr: ir.Value, FieldName: str, Offset: int, SelfPtr: ir.Value,
@@ -1785,7 +1783,7 @@ class AssignHandle(BaseHandle):
from lib.core.LLVMCG.FuncGen import FailFastError from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError( raise FailFastError(
f"指针隐式转换已禁止({Reason}):不能把指针类型 {Value.type} 隐式转为 {TargetType};" f"指针隐式转换已禁止({Reason}):不能把指针类型 {Value.type} 隐式转为 {TargetType};"
f"如需转换请显式 cast(如 t.CPtr(...))" f"如需转换请显式 cast(如 CPtr(...))"
f"{Gen._DescribeValueNode(Node)}" f"{Gen._DescribeValueNode(Node)}"
) )
Value = Gen.builder.bitcast(Value, TargetType, name="ptr_bitcast") Value = Gen.builder.bitcast(Value, TargetType, name="ptr_bitcast")
@@ -1842,11 +1840,10 @@ class AssignHandle(BaseHandle):
if Info: if Info:
if Info.IsTypedef: if Info.IsTypedef:
return return
# 模块级全局 t.attr.* 属性(注解联合形态 `T | t.attr.section("...")`): # 模块级全局 attr.* 属性(注解联合形态 `T | attr.section("...")`):
# 先解析(空/缺段名、非正整数字面量 aligned → fail-fast 终止),再在各 # 先解析(空/缺段名、非正整数字面量 aligned → fail-fast 终止),再在各
# 全局创建点用 _ApplyGlobalAttrs 施加。此前 TPC 全局路径完全没有 # 全局创建点用 _ApplyGlobalAttrs 施加。函数侧 section 只来自装饰器
# section/align/weak 代码(函数侧 section 只来自装饰器,见 # (见 HandlesFunctions.py:1361-1362 → :1767)。
# HandlesFunctions.py:1361-1362 → :1767)。
GlobalAttrs: dict[str, Any] = self._ExtractGlobalAttrs(Node, Gen) GlobalAttrs: dict[str, Any] = self._ExtractGlobalAttrs(Node, Gen)
parse_result = ParseListAnnotation(Node.annotation) parse_result = ParseListAnnotation(Node.annotation)
if parse_result: if parse_result:
@@ -1856,7 +1853,7 @@ class AssignHandle(BaseHandle):
check_func_ptr=True, void_fallback_width=32, fallback_to_cint=True, check_func_ptr=True, void_fallback_width=32, fallback_to_cint=True,
) )
if parse_result.is_pointer: if parse_result.is_pointer:
# 单参数 t.CArray[T]:与 t.CArray[T, None] 统一为"长度自动推导数组"。 # 单参数 CArray[T]:与 CArray[T, None] 统一为"长度自动推导数组"。
# 有可推导初值(列表字面量 / 字符串字面量)时不再生成裸指针,而是落入 # 有可推导初值(列表字面量 / 字符串字面量)时不再生成裸指针,而是落入
# 下方数组路径:由 ParseArrayCount(count_node=None) 从字面量推导长度、 # 下方数组路径:由 ParseArrayCount(count_node=None) 从字面量推导长度、
# 字节内联到变量自身(与类成员 DeclarationGenerator.py:775-784、 # 字节内联到变量自身(与类成员 DeclarationGenerator.py:775-784、
@@ -1932,9 +1929,9 @@ class AssignHandle(BaseHandle):
TypeInfo: CTypeInfo | None = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable) TypeInfo: CTypeInfo | None = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable)
IsCDefine: bool = False IsCDefine: bool = False
if TypeInfo and TypeInfo.BaseType: if TypeInfo and TypeInfo.BaseType:
if isinstance(TypeInfo.BaseType, t._CTypedef): if isinstance(TypeInfo.BaseType, TypeSystem._CTypedef):
return return
if isinstance(TypeInfo.BaseType, t.CDefine): if isinstance(TypeInfo.BaseType, TypeSystem.CDefine):
IsCDefine = True IsCDefine = True
if not IsCDefine and self._IsTypedefAnnotation(Node.annotation): if not IsCDefine and self._IsTypedefAnnotation(Node.annotation):
IsCDefine = True IsCDefine = True
@@ -1956,11 +1953,11 @@ class AssignHandle(BaseHandle):
return return
if TypeInfo is None: if TypeInfo is None:
TypeInfo = CTypeInfo() TypeInfo = CTypeInfo()
TypeInfo.BaseType = t.CInt() TypeInfo.BaseType = TypeSystem.CInt()
VarType: ir.Type = Gen._ctype_to_llvm(TypeInfo) VarType: ir.Type = Gen._ctype_to_llvm(TypeInfo)
if isinstance(VarType, ir.VoidType): if isinstance(VarType, ir.VoidType):
VarType = ir.IntType(32) VarType = ir.IntType(32)
# t.State 标记的模块级全局(`extern 名字: 类型` 的展开产物,见 # State 标记的模块级全局(`extern 名字: 类型` 的展开产物,见
# SymbolUtils._ExpandExportExternVar):**只声明不定义**(external linkage), # SymbolUtils._ExpandExportExternVar):**只声明不定义**(external linkage),
# 符号定义在外部(C 库 / 汇编 / 其它翻译单元),本模块不得再生成定义 # 符号定义在外部(C 库 / 汇编 / 其它翻译单元),本模块不得再生成定义
# (否则 ld.lld duplicate symbol)。与 import 侧 # (否则 ld.lld duplicate symbol)。与 import 侧
@@ -1976,7 +1973,7 @@ class AssignHandle(BaseHandle):
return return
# const / volatile 模块级全局登记(统一登记入口,持久层 global_*)。 # const / volatile 模块级全局登记(统一登记入口,持久层 global_*)。
# 局限(明确记录,见 Debugger/type-descriptors.md 已知差异):本分支只覆盖 # 局限(明确记录,见 Debugger/type-descriptors.md 已知差异):本分支只覆盖
# 标量/指针型全局;数组(t.CArray[...])与结构体型全局在更早的分支 # 标量/指针型全局;数组(CArray[...])与结构体型全局在更早的分支
# (上方 1568-1627)已 return,不在此登记 —— 全仓普查无这类带 const/ # (上方 1568-1627)已 return,不在此登记 —— 全仓普查无这类带 const/
# volatile 注解的全局,故无可观测差异。 # volatile 注解的全局,故无可观测差异。
Gen.RegisterVarQualifiers(VarName, TypeInfo, Node.annotation, IsGlobal=True) Gen.RegisterVarQualifiers(VarName, TypeInfo, Node.annotation, IsGlobal=True)
@@ -2032,7 +2029,7 @@ class AssignHandle(BaseHandle):
Gen.global_struct_class[VarName] = TypeInfo.Name Gen.global_struct_class[VarName] = TypeInfo.Name
return return
GlobalVar: ir.GlobalVariable = ir.GlobalVariable(Gen.module, VarType, name=VarName) GlobalVar: ir.GlobalVariable = ir.GlobalVariable(Gen.module, VarType, name=VarName)
# 全局变量指针元素标志:bytes|t.CPtr 或 str|t.CPtr 注解的变量, # 全局变量指针元素标志:bytes|CPtr 或 str|CPtr 注解的变量,
# 使 var[index] 使用 8 字节指针步长(而非 1 字节字符步长) # 使 var[index] 使用 8 字节指针步长(而非 1 字节字符步长)
if isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr): if isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr):
if AnnotationContainsName(Node.annotation, 'str') or AnnotationContainsName(Node.annotation, 'bytes'): if AnnotationContainsName(Node.annotation, 'str') or AnnotationContainsName(Node.annotation, 'bytes'):
@@ -2051,7 +2048,7 @@ class AssignHandle(BaseHandle):
GlobalVar.initializer = self._BuildStringPtrInitializer(Gen, VarName, Node.value.value) GlobalVar.initializer = self._BuildStringPtrInitializer(Gen, VarName, Node.value.value)
Gen.variables[VarName] = GlobalVar Gen.variables[VarName] = GlobalVar
elif isinstance(VarType, ir.PointerType) and isinstance(VarType.pointee, ir.FunctionType) and isinstance(Node.value, ast.Name): elif isinstance(VarType, ir.PointerType) and isinstance(VarType.pointee, ir.FunctionType) and isinstance(Node.value, ast.Name):
# 函数指针赋值:f3: t.Callable[[int], int] = f # 函数指针赋值:f3: Callable[[int], int] = f
RefName: str = Node.value.id RefName: str = Node.value.id
SymInfo: Any = self.Trans.SymbolTable.lookup(RefName) SymInfo: Any = self.Trans.SymbolTable.lookup(RefName)
if SymInfo and (SymInfo.IsFunction or SymInfo.IsFuncPtr): if SymInfo and (SymInfo.IsFunction or SymInfo.IsFuncPtr):
@@ -2079,7 +2076,7 @@ class AssignHandle(BaseHandle):
if init_val: if init_val:
GlobalVar.initializer = init_val GlobalVar.initializer = init_val
elif isinstance(VarType, ir.BaseStructType) or (isinstance(Node.value, ast.Constant) and Node.value.value is None): elif isinstance(VarType, ir.BaseStructType) or (isinstance(Node.value, ast.Constant) and Node.value.value is None):
# None 初值全局(如各 Handles 模块的 _g_gen: t.CVoid|t.CPtr = None): # None 初值全局(如各 Handles 模块的 _g_gen: CVoid|CPtr = None):
# 多模块同名定义用 common linkage 让链接器合并(避免 # 多模块同名定义用 common linkage 让链接器合并(避免
# ld.lld duplicate symbol)。common 无 initializer,合并为零值, # ld.lld duplicate symbol)。common 无 initializer,合并为零值,
# 符合 None(=null) 语义。 # 符合 None(=null) 语义。
@@ -2097,17 +2094,16 @@ class AssignHandle(BaseHandle):
Gen.variables[VarName] = GlobalVar Gen.variables[VarName] = GlobalVar
# ====================================================================== # ======================================================================
# 模块级全局的 t.attr.* 属性(注解联合形态 `T | t.attr.section("...")`) # 模块级全局的 attr.* 属性(注解联合形态 `T | attr.section("...")`)
# #
# 镜像 ViperC(Viper 自举侧)已有实现: # 与 ViperC(Viper 自举侧)实现对应:
# TranslatorGenMixin._scan_global_tattr / _extract_global_attr_section / # TranslatorGenMixin._scan_global_tattr / _extract_global_attr_section /
# _extract_global_attr_aligned / _extract_global_attr_weak(.vp:590-651) # _extract_global_attr_aligned / _extract_global_attr_weak(.vp:590-651)
# + ClassGenBase._tattr_name(.vp:341-358)+ _class_has_tattr 的 # + ClassGenBase._tattr_name(.vp:341-358)+ _class_has_tattr 的
# `c.Attribute(t.attr.xxx)` 解包(.vp:359-394)。 # `Attribute(attr.xxx)` 解包(.vp:359-394)。
# TPC(Python 侧)此前完全没有全局 section/align/weak 代码。
# ====================================================================== # ======================================================================
def _TAttrName(self, node: ast.AST | None) -> str | None: def _TAttrName(self, node: ast.AST | None) -> str | None:
"""从 t.attr.<name> / t.attr.<name>(args) 节点提取最外层属性名。 """从 attr.<name> / attr.<name>(args) 节点提取最外层属性名。
对应 ViperC ClassGenBase._tattr_name:Call → 递归取 func; 对应 ViperC ClassGenBase._tattr_name:Call → 递归取 func;
Attribute → 取 attr。 Attribute → 取 attr。
@@ -2119,12 +2115,12 @@ class AssignHandle(BaseHandle):
return None return None
def _ScanGlobalTAttr(self, node: ast.AST | None, want_name: str) -> ast.AST | None: def _ScanGlobalTAttr(self, node: ast.AST | None, want_name: str) -> ast.AST | None:
"""在全局变量注解中查找 t.attr.<want_name> 节点,命中返回该节点。 """在全局变量注解中查找 attr.<want_name> 节点,命中返回该节点。
注解形态是 BinOp(BitOr) 左深链(`A | B | C` = BinOp(BinOp(A,B),C)), 注解形态是 BinOp(BitOr) 左深链(`A | B | C` = BinOp(BinOp(A,B),C)),
递归左右子节点。命中节点形态:Call(t.attr.aligned(16))或 递归左右子节点。命中节点形态:Call(attr.aligned(16))或
Attribute(t.attr.weak)。同时兼容包装写法 Attribute(attr.weak)。同时兼容包装写法
`T | c.Attribute(t.attr.section("..."))`(解包参考 ViperC `T | Attribute(attr.section("..."))`(解包参考 ViperC
ClassGenBase._class_has_tattr,.vp:375-389)。 ClassGenBase._class_has_tattr,.vp:375-389)。
""" """
if node is None: if node is None:
@@ -2134,12 +2130,10 @@ class AssignHandle(BaseHandle):
if hit_left is not None: if hit_left is not None:
return hit_left return hit_left
return self._ScanGlobalTAttr(node.right, want_name) return self._ScanGlobalTAttr(node.right, want_name)
# 包装写法:c.Attribute(t.attr.xxx / t.attr.xxx(...)) → 拆 args 再扫 # 包装写法:Attribute(attr.xxx / attr.xxx(...)) → 拆 args 再扫
# (与 HandlesFunctions.py:1354 装饰器侧同一判据:func.attr=='Attribute' # (与 HandlesFunctions.py 装饰器侧同一判据:func.id == 'Attribute')
# 且 func.value 为 Name('c')) if (isinstance(node, ast.Call) and isinstance(node.func, ast.Name)
if (isinstance(node, ast.Call) and isinstance(node.func, ast.Attribute) and node.func.id == 'Attribute'):
and node.func.attr == 'Attribute'
and isinstance(node.func.value, ast.Name) and node.func.value.id == 'c'):
for arg in node.args: for arg in node.args:
hit_arg: ast.AST | None = self._ScanGlobalTAttr(arg, want_name) hit_arg: ast.AST | None = self._ScanGlobalTAttr(arg, want_name)
if hit_arg is not None: if hit_arg is not None:
@@ -2151,7 +2145,7 @@ class AssignHandle(BaseHandle):
@staticmethod @staticmethod
def _TAttrArgStr(node: ast.AST | None) -> str | None: def _TAttrArgStr(node: ast.AST | None) -> str | None:
"""取 t.attr.<name>("...") 的字符串字面量参数(缺参/非字面量返回 None)。""" """取 attr.<name>("...") 的字符串字面量参数(缺参/非字面量返回 None)。"""
if isinstance(node, ast.Call) and node.args: if isinstance(node, ast.Call) and node.args:
arg0: ast.AST = node.args[0] arg0: ast.AST = node.args[0]
if isinstance(arg0, ast.Constant) and isinstance(arg0.value, str): if isinstance(arg0, ast.Constant) and isinstance(arg0.value, str):
@@ -2160,7 +2154,7 @@ class AssignHandle(BaseHandle):
@staticmethod @staticmethod
def _TAttrAlignInt(node: ast.AST | None) -> int | None: def _TAttrAlignInt(node: ast.AST | None) -> int | None:
"""取 t.attr.aligned(N) 的整数字面量 N(缺参/非字面量返回 None)。 """取 attr.aligned(N) 的整数字面量 N(缺参/非字面量返回 None)。
对应 ViperC ClassGenBase._tattr_aligned_int(.vp:395-415)。 对应 ViperC ClassGenBase._tattr_aligned_int(.vp:395-415)。
""" """
@@ -2172,7 +2166,7 @@ class AssignHandle(BaseHandle):
return None return None
def _RaiseGlobalAttrError(self, Msg: str, Node: ast.AST, Gen: "Translator.LlvmGen", VarName: str) -> None: def _RaiseGlobalAttrError(self, Msg: str, Node: ast.AST, Gen: "Translator.LlvmGen", VarName: str) -> None:
"""fail-fast:全局 t.attr.* 属性非法(缺/空段名、非正整数字面量 aligned)。 """fail-fast:全局 attr.* 属性非法(缺/空段名、非正整数字面量 aligned)。
定位串(文件:行:列)与报错出口对齐 HandlesBase._RaiseUnresolvedExpr 定位串(文件:行:列)与报错出口对齐 HandlesBase._RaiseUnresolvedExpr
(HandlesBase.py:552-615)——错误信息含源码位置后 sys.exit(1)。 (HandlesBase.py:552-615)——错误信息含源码位置后 sys.exit(1)。
@@ -2195,7 +2189,7 @@ class AssignHandle(BaseHandle):
sys.exit(1) sys.exit(1)
def _ExtractGlobalAttrs(self, Node: ast.AnnAssign, Gen: "Translator.LlvmGen") -> dict[str, Any]: def _ExtractGlobalAttrs(self, Node: ast.AnnAssign, Gen: "Translator.LlvmGen") -> dict[str, Any]:
"""从模块级全局注解提取 t.attr.section/aligned/weak。 """从模块级全局注解提取 attr.section/aligned/weak。
返回 {'section': str|None, 'align': int, 'weak': bool}。 返回 {'section': str|None, 'align': int, 'weak': bool}。
非法值(空/缺段名、非正整数 aligned)→ fail-fast 终止(对齐 ViperC 非法值(空/缺段名、非正整数 aligned)→ fail-fast 终止(对齐 ViperC
@@ -2209,7 +2203,7 @@ class AssignHandle(BaseHandle):
sec_val: str | None = self._TAttrArgStr(sec_node) sec_val: str | None = self._TAttrArgStr(sec_node)
if not sec_val: if not sec_val:
self._RaiseGlobalAttrError( self._RaiseGlobalAttrError(
"t.attr.section(...) 段名缺失或为空(空段名会生成非法的 section \"\")", "attr.section(...) 段名缺失或为空(空段名会生成非法的 section \"\")",
sec_node, Gen, VarName) sec_node, Gen, VarName)
Attrs['section'] = sec_val Attrs['section'] = sec_val
align_node: ast.AST | None = self._ScanGlobalTAttr(Ann, 'aligned') align_node: ast.AST | None = self._ScanGlobalTAttr(Ann, 'aligned')
@@ -2217,7 +2211,7 @@ class AssignHandle(BaseHandle):
align_val: int | None = self._TAttrAlignInt(align_node) align_val: int | None = self._TAttrAlignInt(align_node)
if align_val is None or align_val <= 0: if align_val is None or align_val <= 0:
self._RaiseGlobalAttrError( self._RaiseGlobalAttrError(
"t.attr.aligned(N) 需要正整数字面量 N", align_node, Gen, VarName) "attr.aligned(N) 需要正整数字面量 N", align_node, Gen, VarName)
Attrs['align'] = align_val Attrs['align'] = align_val
if self._ScanGlobalTAttr(Ann, 'weak') is not None: if self._ScanGlobalTAttr(Ann, 'weak') is not None:
Attrs['weak'] = True Attrs['weak'] = True
@@ -2261,7 +2255,7 @@ class AssignHandle(BaseHandle):
return ir.Constant(var_type, int(value_node.value)) return ir.Constant(var_type, int(value_node.value))
elif isinstance(value_node.value, str): elif isinstance(value_node.value, str):
return None return None
# Handle type constructor calls like t.CDouble(1e-9), t.CFloat(3.14), t.CInt(42) # Handle type constructor calls like CDouble(1e-9), CFloat(3.14), CInt(42)
if isinstance(value_node, ast.Call): if isinstance(value_node, ast.Call):
inner_val: ir.Constant | None = self._eval_type_ctor_const(value_node, var_type, Gen) inner_val: ir.Constant | None = self._eval_type_ctor_const(value_node, var_type, Gen)
if inner_val is not None: if inner_val is not None:
@@ -2298,12 +2292,11 @@ class AssignHandle(BaseHandle):
return None return None
def _eval_type_ctor_const(self, call_node: ast.Call, var_type: ir.Type, Gen: "Translator.LlvmGen") -> ir.Constant | None: def _eval_type_ctor_const(self, call_node: ast.Call, var_type: ir.Type, Gen: "Translator.LlvmGen") -> ir.Constant | None:
"""Try to evaluate t.CDouble(val), t.CFloat(val), t.CInt(val) etc. as a compile-time constant.""" """Try to evaluate CDouble(val), CFloat(val), CInt(val) etc. as a compile-time constant."""
if not isinstance(call_node.func, ast.Attribute): if not isinstance(call_node.func, ast.Name):
return None return None
if not isinstance(call_node.func.value, ast.Name): ctor_cls: type | None = getattr(TypeSystem, call_node.func.id, None)
return None if not isinstance(ctor_cls, type) or not issubclass(ctor_cls, TypeSystem.CType):
if call_node.func.value.id != 't':
return None return None
if not call_node.args or len(call_node.args) != 1: if not call_node.args or len(call_node.args) != 1:
return None return None
+2 -2
View File
@@ -6,7 +6,7 @@ if TYPE_CHECKING:
import vast as ast import vast as ast
import llvmlite.ir as ir import llvmlite.ir as ir
from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, EXCEPTION_CODE_MAP from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, EXCEPTION_CODE_MAP
from lib.includes import t from lib.core import TypeSystem
class AsyncFunctionHandle(BaseHandle): class AsyncFunctionHandle(BaseHandle):
@@ -634,7 +634,7 @@ class AsyncFunctionHandle(BaseHandle):
TypeInfo: CTypeInfo | None = self.Trans.TypeMergeHandler.GetCTypeInfo(stmt.annotation) TypeInfo: CTypeInfo | None = self.Trans.TypeMergeHandler.GetCTypeInfo(stmt.annotation)
if TypeInfo is None: if TypeInfo is None:
TypeInfo = CTypeInfo() TypeInfo = CTypeInfo()
TypeInfo.BaseType = t.CInt() TypeInfo.BaseType = TypeSystem.CInt()
if self.Trans.VarScopes: if self.Trans.VarScopes:
self.Trans.VarScopes[-1][target] = TypeInfo self.Trans.VarScopes[-1][target] = TypeInfo
Gen._record_var_signedness(target, False) Gen._record_var_signedness(target, False)
+2 -2
View File
@@ -27,11 +27,11 @@ class AugAssignHandle(BaseHandle):
"""解析 global 变量的 LLVM 类型:优先用模块级 AnnAssign 的注解类型。 """解析 global 变量的 LLVM 类型:优先用模块级 AnnAssign 的注解类型。
问题场景:函数内 `_g_alloc_count += 1`(global 声明),模块级注解为 问题场景:函数内 `_g_alloc_count += 1`(global 声明),模块级注解为
`_g_alloc_count: t.CSizeT`(i64)。若不查模块级注解类型,此处会用 RHS 字面量 `_g_alloc_count: CSizeT`(i64)。若不查模块级注解类型,此处会用 RHS 字面量
类型(i32)自动建 i32 全局,与模块内其他读取/写入(i64)类型不匹配, 类型(i32)自动建 i32 全局,与模块内其他读取/写入(i64)类型不匹配,
产生 "Operands must be the same type, got (i64, i32)" 类错误。 产生 "Operands must be the same type, got (i64, i32)" 类错误。
模块级 AnnAssign 已通过 _EmitGlobalAnnAssignLlvm 创建 LLVM 全局, 模块级 AnnAssign 已通过 _EmitGlobalAnnAssignLlvm 创建 LLVM 全局,
但注解无初始值(如 `_g_alloc_max: t.CSizeT = 0`)时 initializer 为空、 但注解无初始值(如 `_g_alloc_max: CSizeT = 0`)时 initializer 为空、
Gen.module.globals 中无该符号,故需在此兜底解析注解类型。 Gen.module.globals 中无该符号,故需在此兜底解析注解类型。
""" """
module_ann: dict = getattr(Gen, '_module_ann_types', None) module_ann: dict = getattr(Gen, '_module_ann_types', None)
+103 -95
View File
@@ -10,8 +10,8 @@ from enum import IntFlag, auto
from llvmlite import ir as _ir from llvmlite import ir as _ir
from lib.constants import config as _config from lib.constants import config as _config
from lib.includes import t from lib.core import TypeSystem
from lib.includes.t import CTypeRegistry from lib.core.TypeSystem import CTypeRegistry
from lib.core.TypeSpec import TypeSpec, SymbolMeta, FIELD_ROUTES from lib.core.TypeSpec import TypeSpec, SymbolMeta, FIELD_ROUTES
from lib.core.SymbolUtils import ( from lib.core.SymbolUtils import (
IsPtrSubscriptNode, IsListAnnotation, IsCPtrMarkerNode, IsPtrSubscriptNode, IsListAnnotation, IsCPtrMarkerNode,
@@ -66,20 +66,20 @@ class CTypeInfo:
C 类型信息对象 - 统一符号表条目和类型计算 C 类型信息对象 - 统一符号表条目和类型计算
设计原则: 设计原则:
- BaseType 是 CType 实例(来自 t 模块),永远不使用硬编码字符串 - BaseType 是 CType 实例(内建类型),永远不使用硬编码字符串
- 描述符分为两种: - 描述符分为两种:
- VarConst/VarVolatile: 变量本身(指针)的限定符,如 int * const - VarConst/VarVolatile: 变量本身(指针)的限定符,如 int * const
- DataConst/DataVolatile: 指向数据的限定符,如 const int * - DataConst/DataVolatile: 指向数据的限定符,如 const int *
属性(类型计算): 属性(类型计算):
- BaseType: t.CType - 基础类型实例 (如 t.CInt(), t.CVoid()) - BaseType: CType - 基础类型实例 (如 CInt(), CVoid())
- PtrCount: int - 指针层数 - PtrCount: int - 指针层数
- VarConst: bool - 变量本身(指针)是否 const,如 int * const - VarConst: bool - 变量本身(指针)是否 const,如 int * const
- VarVolatile: bool - 变量本身(指针)是否 volatile - VarVolatile: bool - 变量本身(指针)是否 volatile
- DataConst: bool - 指向的数据是否 const,如 const int * - DataConst: bool - 指向的数据是否 const,如 const int *
- DataVolatile: bool - 指向的数据是否 volatile - DataVolatile: bool - 指向的数据是否 volatile
- ArrayDims: List[str] - 数组维度 - ArrayDims: List[str] - 数组维度
- Storage: t.CType - 存储类 (static, extern 等) - Storage: CType - 存储类 (static, extern 等)
- IsFuncPtr: bool - 是否函数指针 - IsFuncPtr: bool - 是否函数指针
- FuncPtrParams: List[Tuple[str, CTypeInfo]] - 函数指针参数列表,每个元素是 (参数名, 参数类型) - FuncPtrParams: List[Tuple[str, CTypeInfo]] - 函数指针参数列表,每个元素是 (参数名, 参数类型)
- FuncPtrReturn: CTypeInfo - 函数指针返回类型 - FuncPtrReturn: CTypeInfo - 函数指针返回类型
@@ -127,17 +127,17 @@ class CTypeInfo:
@property @property
def BaseType(self) -> t.CType | tuple | None: def BaseType(self) -> TypeSystem.CType | tuple | None:
return self._ts._base_type return self._ts._base_type
@BaseType.setter @BaseType.setter
def BaseType(self, value: t.CType | type | tuple | List | None) -> None: def BaseType(self, value: TypeSystem.CType | type | tuple | List | None) -> None:
"""设置 BaseType,接受以下类型: """设置 BaseType,接受以下类型:
- None: 清空 - None: 清空
- t.CType 实例: 单个类型,自动设置 IsStruct/IsEnum/IsUnion 标志 - CType 实例: 单个类型,自动设置 IsStruct/IsEnum/IsUnion 标志
- type (CType 子类): 如 t.CStruct,自动实例化 - type (CType 子类): 如 CStruct,自动实例化
- tuple/list of t.CType: 多个组合类型 - tuple/list of CType: 多个组合类型
""" """
ts: TypeSpec = self._ts ts: TypeSpec = self._ts
sm: SymbolMeta = self._sm sm: SymbolMeta = self._sm
@@ -153,62 +153,62 @@ class CTypeInfo:
if isinstance(value, (tuple, list)): if isinstance(value, (tuple, list)):
ts._base_type = tuple(value) ts._base_type = tuple(value)
for v in value: for v in value:
if isinstance(v, t.CStruct): if isinstance(v, TypeSystem.CStruct):
sm.is_struct = True sm.is_struct = True
elif isinstance(v, t.CEnum): elif isinstance(v, TypeSystem.CEnum):
sm.is_enum = True sm.is_enum = True
elif isinstance(v, t.CUnion): elif isinstance(v, TypeSystem.CUnion):
sm.is_union = True sm.is_union = True
elif isinstance(v, t.REnum): elif isinstance(v, TypeSystem.REnum):
sm.is_renum = True sm.is_renum = True
sm.is_enum = True sm.is_enum = True
return return
if isinstance(value, type) and issubclass(value, t.CType): if isinstance(value, type) and issubclass(value, TypeSystem.CType):
ts._base_type = value() ts._base_type = value()
return return
if isinstance(value, t.CType): if isinstance(value, TypeSystem.CType):
ts._base_type = value ts._base_type = value
if isinstance(value, t.CStruct): if isinstance(value, TypeSystem.CStruct):
sm.is_struct = True sm.is_struct = True
sm.is_enum = False sm.is_enum = False
sm.is_union = False sm.is_union = False
sm.is_renum = False sm.is_renum = False
elif isinstance(value, t.REnum): elif isinstance(value, TypeSystem.REnum):
sm.is_renum = True sm.is_renum = True
sm.is_enum = True sm.is_enum = True
sm.is_struct = False sm.is_struct = False
sm.is_union = False sm.is_union = False
elif isinstance(value, t.CEnum): elif isinstance(value, TypeSystem.CEnum):
sm.is_enum = True sm.is_enum = True
sm.is_struct = False sm.is_struct = False
sm.is_union = False sm.is_union = False
sm.is_renum = False sm.is_renum = False
elif isinstance(value, t.CUnion): elif isinstance(value, TypeSystem.CUnion):
sm.is_union = True sm.is_union = True
sm.is_struct = False sm.is_struct = False
sm.is_enum = False sm.is_enum = False
sm.is_renum = False sm.is_renum = False
return return
raise TypeError(f"BaseType must be t.CType instance, type subclass, or tuple of t.CType, got {type(value)}") raise TypeError(f"BaseType must be CType instance, type subclass, or tuple of CType, got {type(value)}")
@property @property
def TypeCls(self) -> type | None: def TypeCls(self) -> type | None:
"""获取 CType 类(从 BaseType 推断)""" """获取 CType 类(从 BaseType 推断)"""
bt: t.CType | tuple | None = self._ts._base_type bt: TypeSystem.CType | tuple | None = self._ts._base_type
if bt: if bt:
return type(bt) return type(bt)
sm: SymbolMeta = self._sm sm: SymbolMeta = self._sm
if sm.is_struct: if sm.is_struct:
return t.CStruct return TypeSystem.CStruct
if sm.is_enum: if sm.is_enum:
return t.CEnum return TypeSystem.CEnum
if sm.is_union: if sm.is_union:
return t.CUnion return TypeSystem.CUnion
if sm.is_typedef: if sm.is_typedef:
return t._CTypedef return TypeSystem._CTypedef
return None return None
@property @property
@@ -217,37 +217,37 @@ class CTypeInfo:
@property @property
def IsVoid(self) -> bool: def IsVoid(self) -> bool:
return isinstance(self._ts._base_type, t.CVoid) return isinstance(self._ts._base_type, TypeSystem.CVoid)
@property @property
def IsStr(self) -> bool: def IsStr(self) -> bool:
return isinstance(self._ts._base_type, t.CChar) and self._ts.ptr_count > 0 return isinstance(self._ts._base_type, TypeSystem.CChar) and self._ts.ptr_count > 0
@property @property
def IsInt(self) -> bool: def IsInt(self) -> bool:
bt: t.CType | tuple | None = self._ts._base_type bt: TypeSystem.CType | tuple | None = self._ts._base_type
return isinstance(bt, t.CType) and getattr(bt, 'IsSigned', None) is not None and bt.IsSigned is True and not isinstance(bt, t.CVoid) return isinstance(bt, TypeSystem.CType) and getattr(bt, 'IsSigned', None) is not None and bt.IsSigned is True and not isinstance(bt, TypeSystem.CVoid)
@property @property
def IsUInt(self) -> bool: def IsUInt(self) -> bool:
bt: t.CType | tuple | None = self._ts._base_type bt: TypeSystem.CType | tuple | None = self._ts._base_type
return isinstance(bt, t.CType) and getattr(bt, 'IsSigned', None) is False return isinstance(bt, TypeSystem.CType) and getattr(bt, 'IsSigned', None) is False
@property @property
def IsFloat(self) -> bool: def IsFloat(self) -> bool:
bt: t.CType | tuple | None = self._ts._base_type bt: TypeSystem.CType | tuple | None = self._ts._base_type
return isinstance(bt, t.CType) and getattr(bt, 'IsSigned', None) is None and getattr(bt, 'Size', 0) in (32, 64, 128) and not isinstance(bt, t.CVoid) return isinstance(bt, TypeSystem.CType) and getattr(bt, 'IsSigned', None) is None and getattr(bt, 'Size', 0) in (32, 64, 128) and not isinstance(bt, TypeSystem.CVoid)
def ToString(self) -> str: def ToString(self) -> str:
ts: TypeSpec = self._ts ts: TypeSpec = self._ts
sm: SymbolMeta = self._sm sm: SymbolMeta = self._sm
bt: t.CType | tuple | None = ts._base_type bt: TypeSystem.CType | tuple | None = ts._base_type
if ts.is_func_ptr: if ts.is_func_ptr:
return 'Callable' return 'Callable'
parts: list[str] = [] parts: list[str] = []
if ts.storage and not isinstance(ts.storage, t.CExport): if ts.storage and not isinstance(ts.storage, TypeSystem.CExport):
parts.append(type(ts.storage).__name__) parts.append(type(ts.storage).__name__)
if ts.data_const or ts.data_volatile: if ts.data_const or ts.data_volatile:
@@ -265,9 +265,9 @@ class CTypeInfo:
elif bt: elif bt:
if isinstance(bt, str): if isinstance(bt, str):
base_name = bt base_name = bt
elif isinstance(bt, type) and issubclass(bt, t.CType): elif isinstance(bt, type) and issubclass(bt, TypeSystem.CType):
base_name = bt.__name__ base_name = bt.__name__
elif isinstance(bt, t.CType): elif isinstance(bt, TypeSystem.CType):
# 对命名的 CType(CStruct/CEnum/CUnion/REnum),优先使用其 name 属性 # 对命名的 CType(CStruct/CEnum/CUnion/REnum),优先使用其 name 属性
# 否则回退到类名(如 'CInt'、'CChar') # 否则回退到类名(如 'CInt'、'CChar')
_named: str | None = getattr(bt, 'name', None) _named: str | None = getattr(bt, 'name', None)
@@ -320,13 +320,13 @@ class CTypeInfo:
"""从类型名字符串创建 CTypeInfo(兼容旧 API)""" """从类型名字符串创建 CTypeInfo(兼容旧 API)"""
info: CTypeInfo = CTypeInfo() info: CTypeInfo = CTypeInfo()
if TypeName.startswith('struct '): if TypeName.startswith('struct '):
info.BaseType = t.CStruct(name=TypeName[7:].strip()) if TypeName[7:].strip() else t.CStruct() info.BaseType = TypeSystem.CStruct(name=TypeName[7:].strip()) if TypeName[7:].strip() else TypeSystem.CStruct()
elif TypeName.startswith('enum '): elif TypeName.startswith('enum '):
info.BaseType = t.CEnum(name=TypeName[5:].strip()) if TypeName[5:].strip() else t.CEnum() info.BaseType = TypeSystem.CEnum(name=TypeName[5:].strip()) if TypeName[5:].strip() else TypeSystem.CEnum()
elif TypeName.startswith('union '): elif TypeName.startswith('union '):
info.BaseType = t.CUnion(name=TypeName[6:].strip()) if TypeName[6:].strip() else t.CUnion() info.BaseType = TypeSystem.CUnion(name=TypeName[6:].strip()) if TypeName[6:].strip() else TypeSystem.CUnion()
else: else:
info.BaseType = t.CStruct(name=TypeName) info.BaseType = TypeSystem.CStruct(name=TypeName)
return info return info
# LLVM primitive type name → (CTypeClass, PtrCount) mapping # LLVM primitive type name → (CTypeClass, PtrCount) mapping
@@ -338,16 +338,16 @@ class CTypeInfo:
if cls._LLVM_PRIMITIVE_MAP is not None: if cls._LLVM_PRIMITIVE_MAP is not None:
return cls._LLVM_PRIMITIVE_MAP return cls._LLVM_PRIMITIVE_MAP
cls._LLVM_PRIMITIVE_MAP = { cls._LLVM_PRIMITIVE_MAP = {
'void': (t.CVoid, 0), 'void': (TypeSystem.CVoid, 0),
'i1': (t.CInt, 0), 'i1': (TypeSystem.CInt, 0),
'i8': (t.CChar, 0), 'i8': (TypeSystem.CChar, 0),
'i16': (t.CShort, 0), 'i16': (TypeSystem.CShort, 0),
'i32': (t.CInt, 0), 'i32': (TypeSystem.CInt, 0),
'i64': (t.CLong, 0), 'i64': (TypeSystem.CLong, 0),
'i128': (t.CInt, 0), 'i128': (TypeSystem.CInt, 0),
'float': (t.CFloat, 0), 'float': (TypeSystem.CFloat, 0),
'double': (t.CDouble, 0), 'double': (TypeSystem.CDouble, 0),
'fp128': (t.CFloat128T, 0), 'fp128': (TypeSystem.CFloat128T, 0),
} }
return cls._LLVM_PRIMITIVE_MAP return cls._LLVM_PRIMITIVE_MAP
@@ -401,7 +401,7 @@ class CTypeInfo:
@staticmethod @staticmethod
def VoidTypeInfo() -> "CTypeInfo": def VoidTypeInfo() -> "CTypeInfo":
info: CTypeInfo = CTypeInfo() info: CTypeInfo = CTypeInfo()
info.BaseType = t.CVoid() info.BaseType = TypeSystem.CVoid()
return info return info
def ToLLVM(self, Gen: LlvmCodeGenerator) -> _ir.Type: def ToLLVM(self, Gen: LlvmCodeGenerator) -> _ir.Type:
@@ -429,14 +429,17 @@ class CTypeHelper:
@staticmethod @staticmethod
def GetTModuleCType(TypeName: str) -> type | None: def GetTModuleCType(TypeName: str) -> type | None:
alias: type | None = TypeSystem.BUILTIN_TYPE_ALIASES.get(TypeName)
if alias is not None:
return alias
result: type | None = CTypeRegistry.GetClassByName(TypeName) result: type | None = CTypeRegistry.GetClassByName(TypeName)
if result is not None: if result is not None:
return result return result
TypeClass: type | None = getattr(t, TypeName, None) TypeClass: type | None = getattr(TypeSystem, TypeName, None)
if TypeClass and isinstance(TypeClass, type) and issubclass(TypeClass, t.CType): if TypeClass and isinstance(TypeClass, type) and issubclass(TypeClass, TypeSystem.CType):
return TypeClass return TypeClass
FallbackClass: type | None = getattr(t, f'_{TypeName}', None) FallbackClass: type | None = getattr(TypeSystem, f'_{TypeName}', None)
if FallbackClass and isinstance(FallbackClass, type) and issubclass(FallbackClass, t.CType): if FallbackClass and isinstance(FallbackClass, type) and issubclass(FallbackClass, TypeSystem.CType):
return FallbackClass return FallbackClass
return None return None
@@ -449,7 +452,7 @@ class CTypeHelper:
if cls: if cls:
return cls.__name__ return cls.__name__
return type_or_name return type_or_name
elif isinstance(type_or_name, type) and issubclass(type_or_name, t.CType): elif isinstance(type_or_name, type) and issubclass(type_or_name, TypeSystem.CType):
return type_or_name.__name__ return type_or_name.__name__
return '' return ''
@@ -458,8 +461,8 @@ class BuiltinTypeMap:
""" """
内置类型映射表 - 字符串到 (CType类, PtrCount) 的映射 内置类型映射表 - 字符串到 (CType类, PtrCount) 的映射
用法:BuiltinTypeMap.Get('int') -> (t.CInt, 0) 用法:BuiltinTypeMap.Get('int') -> (CInt, 0)
BuiltinTypeMap.Get('BYTEPTR') -> (t.CUnsignedChar, 1) BuiltinTypeMap.Get('BYTEPTR') -> (CUnsignedChar, 1)
""" """
_map: dict[str, tuple[type, int]] | None = None _map: dict[str, tuple[type, int]] | None = None
@@ -475,7 +478,7 @@ class BuiltinTypeMap:
# C 头文件 stub 生成器使用独立的硬编码表(CTypeMapper._CNAME_TO_PY)。 # C 头文件 stub 生成器使用独立的硬编码表(CTypeMapper._CNAME_TO_PY)。
for pyname, ctype_cls in CTypeRegistry._name_to_class.items(): for pyname, ctype_cls in CTypeRegistry._name_to_class.items():
pos: frozenset = getattr(ctype_cls, 'position', frozenset()) pos: frozenset = getattr(ctype_cls, 'position', frozenset())
if t.CType.POINTER in pos and t.CType.BASE not in pos: if TypeSystem.CType.POINTER in pos and TypeSystem.CType.BASE not in pos:
cls._map[pyname] = (ctype_cls, 1) cls._map[pyname] = (ctype_cls, 1)
else: else:
cls._map[pyname] = (ctype_cls, 0) cls._map[pyname] = (ctype_cls, 0)
@@ -483,28 +486,33 @@ class BuiltinTypeMap:
# 包含 Python 内置类型名(int/float/bool)和 C 类型名速记(char/short/long 等)。 # 包含 Python 内置类型名(int/float/bool)和 C 类型名速记(char/short/long 等)。
_SPECIAL: dict[str, tuple[type, int]] = { _SPECIAL: dict[str, tuple[type, int]] = {
# Python 内置类型名 # Python 内置类型名
'str': (t.CChar, 1), 'bytes': (t.CChar, 1), 'str': (TypeSystem.CChar, 1), 'bytes': (TypeSystem.CChar, 1),
'int': (t.CInt, 0), 'float': (t.CFloat, 0), 'bool': (t.CBool, 0), 'int': (TypeSystem.CInt, 0), 'float': (TypeSystem.CFloat, 0), 'bool': (TypeSystem.CBool, 0),
# C 类型名速记 # C 类型名速记
'char': (t.CChar, 0), 'short': (t.CShort, 0), 'char': (TypeSystem.CChar, 0), 'short': (TypeSystem.CShort, 0),
'long': (t.CLong, 0), 'long long': (t.CLongLong, 0), 'long': (TypeSystem.CLong, 0), 'long long': (TypeSystem.CLongLong, 0),
'double': (t.CDouble, 0), 'double': (TypeSystem.CDouble, 0),
'unsigned': (t.CUnsigned, 0), 'unsigned': (TypeSystem.CUnsigned, 0),
'signed': (t.CInt, 0), 'signed int': (t.CInt, 0), 'signed': (TypeSystem.CInt, 0), 'signed int': (TypeSystem.CInt, 0),
'signed char': (t.CSignedChar, 0), 'signed char': (TypeSystem.CSignedChar, 0),
'void': (t.CVoid, 0), 'Void': (t.CVoid, 0), 'void': (TypeSystem.CVoid, 0), 'Void': (TypeSystem.CVoid, 0),
} }
for k, v in _SPECIAL.items(): for k, v in _SPECIAL.items():
if k not in cls._map: if k not in cls._map:
cls._map[k] = v cls._map[k] = v
_FLOAT_ALIASES: dict[str, tuple[type, int]] = { _FLOAT_ALIASES: dict[str, tuple[type, int]] = {
'FLOAT8': (t.CFloat8T, 0), 'FLOAT16': (t.CFloat16T, 0), 'FLOAT8': (TypeSystem.CFloat8T, 0), 'FLOAT16': (TypeSystem.CFloat16T, 0),
'FLOAT32': (t.CFloat32T, 0), 'FLOAT64': (t.CFloat64T, 0), 'FLOAT32': (TypeSystem.CFloat32T, 0), 'FLOAT64': (TypeSystem.CFloat64T, 0),
'FLOAT128': (t.CFloat128T, 0), 'FLOAT128': (TypeSystem.CFloat128T, 0),
} }
for k, v in _FLOAT_ALIASES.items(): for k, v in _FLOAT_ALIASES.items():
if k not in cls._map: if k not in cls._map:
cls._map[k] = v cls._map[k] = v
# 内建短名(int8/sizet/uchar/...):源码直接书写,不依赖任何 typedef。
for _alias_name, _alias_cls in TypeSystem.BUILTIN_TYPE_ALIASES.items():
_pos: frozenset = getattr(_alias_cls, 'position', frozenset())
_ptr: int = 1 if TypeSystem.CType.POINTER in _pos and TypeSystem.CType.BASE not in _pos else 0
cls._map[_alias_name] = (_alias_cls, _ptr)
return cls._map return cls._map
@classmethod @classmethod
@@ -882,16 +890,16 @@ class BaseHandle:
return member_ptr return member_ptr
return None return None
def _IsTModuleType(self, TypeName: str) -> bool: def _IsBuiltinTypeName(self, TypeName: str) -> bool:
if TypeName in ('t', 'State', 'Bit', 'Anonymous', 'Postdefinition'): if TypeName in ('State', 'Bit', 'Anonymous', 'Postdefinition'):
return True return True
TypeClass: type | None = getattr(t, TypeName, None) TypeClass: type | None = getattr(TypeSystem, TypeName, None)
if TypeClass and isinstance(TypeClass, type): if TypeClass and isinstance(TypeClass, type):
if issubclass(TypeClass, t.CType): if issubclass(TypeClass, TypeSystem.CType):
return True return True
FallbackClass: type | None = getattr(t, f'_{TypeName}', None) FallbackClass: type | None = getattr(TypeSystem, f'_{TypeName}', None)
if FallbackClass and isinstance(FallbackClass, type): if FallbackClass and isinstance(FallbackClass, type):
if issubclass(FallbackClass, t.CType): if issubclass(FallbackClass, TypeSystem.CType):
return True return True
return False return False
@@ -936,7 +944,7 @@ class BaseHandle:
# 回退到 CInt # 回退到 CInt
if elem_type_info is None and fallback_to_cint: if elem_type_info is None and fallback_to_cint:
elem_type_info = CTypeInfo() elem_type_info = CTypeInfo()
elem_type_info.BaseType = t.CInt() elem_type_info.BaseType = TypeSystem.CInt()
elem_type: Any = Gen._ctype_to_llvm(elem_type_info) elem_type: Any = Gen._ctype_to_llvm(elem_type_info)
if isinstance(elem_type, _ir.VoidType): if isinstance(elem_type, _ir.VoidType):
@@ -1019,11 +1027,11 @@ class BaseHandle:
"""解析注解类型,BinOp(BitOr) 优先使用 MergeTypes,其他使用 FromNode。 """解析注解类型,BinOp(BitOr) 优先使用 MergeTypes,其他使用 FromNode。
统一处理函数返回类型和参数类型的 BinOp 联合类型解析。 统一处理函数返回类型和参数类型的 BinOp 联合类型解析。
指针下标(rawptr[T] 内置裸指针 / t.CPtr[T] / 裸名 CPtr[T],三者等价 指针下标(rawptr[T] 内置裸指针 / CPtr[T] / 裸名 CPtr[T],三者等价
`T | t.CPtr`)同样交给 TypeMerge 解析:内层 T 走通用类型解析(含跨模块 `T | CPtr`)同样交给 TypeMerge 解析:内层 T 走通用类型解析(含跨模块
类经 Gen.structs 反查 SHA1 前缀),指针层数与源码 `T | t.CPtr` 一致; 类经 Gen.structs 反查 SHA1 前缀),指针层数与源码 `T | CPtr` 一致;
若交给 CTypeInfo.FromNode(TypeAnnotationResolver)解析, 若交给 CTypeInfo.FromNode(TypeAnnotationResolver)解析,
rawptr[ast.AST] 会退化成 CVoid/1(i8*)、t.CPtr[ast.AST] 亦退化成 rawptr[ast.AST] 会退化成 CVoid/1(i8*)、CPtr[ast.AST] 亦退化成
CVoid/1(其 Subscript-CPtr 分支不带 Gen.structs 反查),与 declare 端 CVoid/1(其 Subscript-CPtr 分支不带 Gen.structs 反查),与 declare 端
%"<sha1>.AST"* 分裂。 %"<sha1>.AST"* 分裂。
命中泛型模板的泛型容器下标(list[X] / rawptr[list[X]] 等)同样交 命中泛型模板的泛型容器下标(list[X] / rawptr[list[X]] 等)同样交
@@ -1059,7 +1067,7 @@ class BaseHandle:
def _ResolveStackArrayElementFallback( def _ResolveStackArrayElementFallback(
self, annotation: ast.expr, Fallback: CTypeInfo | None) -> CTypeInfo | None: self, annotation: ast.expr, Fallback: CTypeInfo | None) -> CTypeInfo | None:
"""固定数组注解(`t.CArray[T, N]` / `[N]T`)元素类型兜底解析。 """固定数组注解(`CArray[T, N]` / `[N]T`)元素类型兜底解析。
CTypeInfo.FromNode(TypeAnnotationResolver 的 IsListAnnotation 分支)只 CTypeInfo.FromNode(TypeAnnotationResolver 的 IsListAnnotation 分支)只
会用自身解析元素类型:元素命中泛型模板时(list[X] / list[rawptr[X]])解 会用自身解析元素类型:元素命中泛型模板时(list[X] / list[rawptr[X]])解
@@ -1071,7 +1079,7 @@ class BaseHandle:
(ResolveAnnotationType 递归,泛型容器因此走 TypeMerge 特化,跨模块类 (ResolveAnnotationType 递归,泛型容器因此走 TypeMerge 特化,跨模块类
经 Gen.structs 反查 SHA1)解析元素,再套上数组维度(维度序与 经 Gen.structs 反查 SHA1)解析元素,再套上数组维度(维度序与
TypeAnnotationResolver 的 `insert(0, count)` 一致)。 TypeAnnotationResolver 的 `insert(0, count)` 一致)。
元素可解析的形态(t.CArray[t.CInt, 8] / t.CArray[Node, 4] / 嵌套 CArray) 元素可解析的形态(CArray[CInt, 8] / CArray[Node, 4] / 嵌套 CArray)
保持 FromNode 结果原样,避免改动既有布局。 保持 FromNode 结果原样,避免改动既有布局。
""" """
if isinstance(Fallback, CTypeInfo) and Fallback.BaseType is not None: if isinstance(Fallback, CTypeInfo) and Fallback.BaseType is not None:
@@ -1092,7 +1100,7 @@ class BaseHandle:
return Result return Result
def _ResolveAttributeAnnotationType(self, annotation: ast.Attribute) -> CTypeInfo | None: def _ResolveAttributeAnnotationType(self, annotation: ast.Attribute) -> CTypeInfo | None:
"""Attribute 注解(`t.CInt` / `ast.AST` / `<sha1>.CLS`)解析。 """Attribute 注解(`CInt` / `ast.AST` / `<sha1>.CLS`)解析。
先走 CTypeInfo.FromNode(TypeAnnotationResolver,覆盖 t/c 内建与已在本模块 先走 CTypeInfo.FromNode(TypeAnnotationResolver,覆盖 t/c 内建与已在本模块
SymbolTable 注册的类):其 BaseType 已解析时语义不变。 SymbolTable 注册的类):其 BaseType 已解析时语义不变。
@@ -1103,7 +1111,7 @@ class BaseHandle:
SymbolUtils._ResolveAttributeArgStr 同一条"类名 → SHA1"规则)。 SymbolUtils._ResolveAttributeArgStr 同一条"类名 → SHA1"规则)。
不修此路时跨模块类 Attribute(`rawptr[<sha1>.CLS]` 脱糖后的 不修此路时跨模块类 Attribute(`rawptr[<sha1>.CLS]` 脱糖后的
`<sha1>.CLS | t.CPtr`、泛型 T 替换出的裸 `<sha1>.CLS`、`list[ast.AST]` `<sha1>.CLS | CPtr`、泛型 T 替换出的裸 `<sha1>.CLS`、`list[ast.AST]`
特化的 `append(item: T)`)在定义端判为"无法识别的参数类型注解"抛 特化的 `append(item: T)`)在定义端判为"无法识别的参数类型注解"抛
SyntaxError,被上层 broad except 吞掉后退化为 i32/i8*,而声明端给 SyntaxError,被上层 broad except 吞掉后退化为 i32/i8*,而声明端给
`%"<sha1>.CLS"*`,字段/签名两侧不一致。 `%"<sha1>.CLS"*`,字段/签名两侧不一致。
@@ -1143,7 +1151,7 @@ class BaseHandle:
info: CTypeInfo | None = merger.MergeTypes(annotation) info: CTypeInfo | None = merger.MergeTypes(annotation)
if info is not None and isinstance(info, CTypeInfo): if info is not None and isinstance(info, CTypeInfo):
return info return info
# 指针下标参数注解(rawptr[T] / t.CPtr[T] / 裸名 CPtr[T],含 # 指针下标参数注解(rawptr[T] / CPtr[T] / 裸名 CPtr[T],含
# rawptr[list[X]] 等容器:_SubscriptHitsGenericTemplate 也命中,但统一交 # rawptr[list[X]] 等容器:_SubscriptHitsGenericTemplate 也命中,但统一交
# ResolveAnnotationType 处理更简单——它已把指针下标路由到 TypeMerge)。 # ResolveAnnotationType 处理更简单——它已把指针下标路由到 TypeMerge)。
if IsPtrSubscriptNode(annotation, self.Trans.SymbolTable): if IsPtrSubscriptNode(annotation, self.Trans.SymbolTable):
@@ -1171,7 +1179,7 @@ class BaseHandle:
def _SubscriptHitsGenericTemplate(self, annotation: ast.Subscript) -> bool: def _SubscriptHitsGenericTemplate(self, annotation: ast.Subscript) -> bool:
"""判断 Subscript 是否命中泛型模板:裸模板名(list[X]/GSList[X]), """判断 Subscript 是否命中泛型模板:裸模板名(list[X]/GSList[X]),
或 rawptr/t.CPtr 裸指针 typedef 内嵌模板名(rawptr[list[X]] 等)。""" 或 rawptr/CPtr 裸指针 typedef 内嵌模板名(rawptr[list[X]] 等)。"""
tpls: Any = getattr(getattr(self.Trans, 'ClassHandler', None), '_generic_class_templates', None) tpls: Any = getattr(getattr(self.Trans, 'ClassHandler', None), '_generic_class_templates', None)
if not tpls: if not tpls:
return False return False
@@ -1239,7 +1247,7 @@ class BaseHandle:
**不再静默兜底**(原实现:注解解析返回 None → i32;_ctype_to_llvm 得 void → i8*; **不再静默兜底**(原实现:注解解析返回 None → i32;_ctype_to_llvm 得 void → i8*;
任何异常 → i32 + TypeInfo=None)。这些兜底会把"注解没解析出来"伪装成一个 任何异常 → i32 + TypeInfo=None)。这些兜底会把"注解没解析出来"伪装成一个
具体类型,下游于是报出与真因无关的错——实测:`free_lists: uint64*`(脱糖为 具体类型,下游于是报出与真因无关的错——实测:`free_lists: uint64*`(脱糖为
`uint64 | t.CPtr`)在解析异常时被当成 **i32**,`self.free_lists = base`(i8*) `uint64 | CPtr`)在解析异常时被当成 **i32**,`self.free_lists = base`(i8*)
便误报"指针隐式转整数已禁止"。类型信息缺失一律响亮失败。 便误报"指针隐式转整数已禁止"。类型信息缺失一律响亮失败。
非 AnnAssign/Name 目标时返回 None。 非 AnnAssign/Name 目标时返回 None。
""" """
@@ -1283,7 +1291,7 @@ class BaseHandle:
f"Name={getattr(TypeInfo, 'Name', None)})—— 拒绝静默退化为 i8*" f"Name={getattr(TypeInfo, 'Name', None)})—— 拒绝静默退化为 i8*"
) )
# 「内层是类引用却解析成通用指针」fail-fast(降级源头定位): # 「内层是类引用却解析成通用指针」fail-fast(降级源头定位):
# `rawptr[Mod.Class]` / `Mod.Class | t.CPtr` 的语义是"指向该类",内层若确实是 # `rawptr[Mod.Class]` / `Mod.Class | CPtr` 的语义是"指向该类",内层若确实是
# 已定义类,解析结果必须带该类 BaseType;退化成 void 基座(i8* / 多一层 i8**) # 已定义类,解析结果必须带该类 BaseType;退化成 void 基座(i8* / 多一层 i8**)
# 就是类型信息被丢掉 —— 该值一旦进 class_members 就会被冻进 struct body # 就是类型信息被丢掉 —— 该值一旦进 class_members 就会被冻进 struct body
# (llvmlite set_body 只能设一次),后期只修表不修体(现场:Generator 第 3/11 # (llvmlite set_body 只能设一次),后期只修表不修体(现场:Generator 第 3/11
@@ -1337,16 +1345,16 @@ class BaseHandle:
只拦"必属类型信息丢失"的组合:内层节点(Name / Attribute)的名字在 只拦"必属类型信息丢失"的组合:内层节点(Name / Attribute)的名字在
`Gen.structs`(本模块已建)或 `Gen._struct_sha1_map`(预扫描的类→模块映射) `Gen.structs`(本模块已建)或 `Gen._struct_sha1_map`(预扫描的类→模块映射)
中有类定义,而解析出的 `BaseType` 是 `t.CVoid` **且没有任何类身份** 中有类定义,而解析出的 `BaseType` 是 `CVoid` **且没有任何类身份**
(IsStruct / IsRenum / IsEnum / Name 全空)。其余一律放行 (IsStruct / IsRenum / IsEnum / Name 全空)。其余一律放行
(`rawptr[rawptr]` 这类本就 void 基座的多层指针、模块名、泛型特化实参等)。 (`rawptr[rawptr]` 这类本就 void 基座的多层指针、模块名、泛型特化实参等)。
""" """
if Info is None or Info.BaseType is None: if Info is None or Info.BaseType is None:
return return
if not (Info.BaseType is t.CVoid or isinstance(Info.BaseType, t.CVoid)): if not (Info.BaseType is TypeSystem.CVoid or isinstance(Info.BaseType, TypeSystem.CVoid)):
return return
# 只要还带着任何"类身份"(IsStruct / IsRenum / IsEnum / Name),就不是信息丢失: # 只要还带着任何"类身份"(IsStruct / IsRenum / IsEnum / Name),就不是信息丢失:
# REnum 类型条目本身 BaseType=None,`T | t.CPtr` 合并后会被默认填成 CVoid,但 # REnum 类型条目本身 BaseType=None,`T | CPtr` 合并后会被默认填成 CVoid,但
# IsRenum/IsStruct/Name 齐备,_ctype_to_llvm 仍能解析出 %<sha1>.T* —— 误判会 # IsRenum/IsStruct/Name 齐备,_ctype_to_llvm 仍能解析出 %<sha1>.T* —— 误判会
# 把合法注解(如 REnum 变体载荷 `Pointee: rawptr[LLVMType]`)打成致命错误。 # 把合法注解(如 REnum 变体载荷 `Pointee: rawptr[LLVMType]`)打成致命错误。
if (getattr(Info, 'IsStruct', False) or getattr(Info, 'IsRenum', False) if (getattr(Info, 'IsStruct', False) or getattr(Info, 'IsRenum', False)
+3 -4
View File
@@ -19,7 +19,7 @@ class BodyHandle(BaseHandle):
Gen._set_node_info(Node) Gen._set_node_info(Node)
try: try:
if isinstance(Node, ast.Expr): if isinstance(Node, ast.Expr):
# `fallthrough`(vast 关键字已脱糖为 c.NoBreak())是 switch 的 # `fallthrough`(vast 关键字已脱糖为 NoBreak())是 switch 的
# 标记语句,本身不产出 IR,语义由 HandlesMatch 消费(case 体因此 # 标记语句,本身不产出 IR,语义由 HandlesMatch 消费(case 体因此
# 不自动跳出 switch);合法位置**只有 switch 的 case 体内**, # 不自动跳出 switch);合法位置**只有 switch 的 case 体内**,
# match(完全禁止 fallthrough)或 switch 之外一律 fail-fast。 # match(完全禁止 fallthrough)或 switch 之外一律 fail-fast。
@@ -101,12 +101,11 @@ class BodyHandle(BaseHandle):
@staticmethod @staticmethod
def _IsNoBreakMarkerStmt(Node: ast.stmt) -> bool: def _IsNoBreakMarkerStmt(Node: ast.stmt) -> bool:
"""是否 `c.NoBreak()` 标记语句(`fallthrough` 软关键字的脱糖形态)""" """是否 `NoBreak()` 标记语句(`fallthrough` 软关键字的脱糖形态)"""
if not isinstance(Node, ast.Expr) or not isinstance(Node.value, ast.Call): if not isinstance(Node, ast.Expr) or not isinstance(Node.value, ast.Call):
return False return False
Fn: ast.expr = Node.value.func Fn: ast.expr = Node.value.func
return (isinstance(Fn, ast.Attribute) and isinstance(Fn.value, ast.Name) return isinstance(Fn, ast.Name) and Fn.id == 'NoBreak'
and Fn.value.id == 'c' and Fn.attr == 'NoBreak')
def HandleExprLlvm(self, Node: ast.expr, VarType: ir.Type | None = None, def HandleExprLlvm(self, Node: ast.expr, VarType: ir.Type | None = None,
ConstWidthHint: int | None = None) -> ir.Value | None: ConstWidthHint: int | None = None) -> ir.Value | None:
+100 -215
View File
@@ -10,17 +10,17 @@ import llvmlite.ir as ir
from lib.core.Exportable import EnumMember as ExportEnumMember from lib.core.Exportable import EnumMember as ExportEnumMember
from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta
from lib.core.SymbolUtils import ( from lib.core.SymbolUtils import (
IsTModule, FindStructNameInAnnotationWithContext, MangleTypeArgByRegistry, FindStructNameInAnnotationWithContext, MangleTypeArgByRegistry,
EnumClassIntWidth, EnumClassIntWidth,
EnumBodyMemberNames, EnumMemberCountMismatchError, EnumBodyMemberNames, EnumMemberCountMismatchError,
ClassHasFuncLevelCVTable, IsVtableSlotMethod) ClassHasFuncLevelCVTable, IsVtableSlotMethod)
from lib.core.VLogger import get_logger as _vlog from lib.core.VLogger import get_logger as _vlog
from lib.constants.config import mode as _config_mode from lib.constants.config import mode as _config_mode
from lib.includes import t from lib.core import TypeSystem
from lib.includes.t import CTypeRegistry from lib.core.TypeSystem import CTypeRegistry
# 枚举成员不允许的指针形态名:t.CPtr 家族(CPtr/CAutoPtr,后者继承 # 枚举成员不允许的指针形态名:CPtr 家族(CPtr/CAutoPtr,后者继承
# CPtr)、值引用标记(CRef/CTempRef,`&T`/`&temp T`)、内建 rawptr(= t.CPtr)、 # CPtr)、值引用标记(CRef/CTempRef,`&T`/`&temp T`)、内建 rawptr(= CPtr)、
# str/bytes(= i8*)。枚举值是整数常量,指针成员语义不成立,命中即明确报错 # str/bytes(= i8*)。枚举值是整数常量,指针成员语义不成立,命中即明确报错
# (不静默当 int)。 # (不静默当 int)。
_ENUM_PTR_ANNOTATION_NAMES: frozenset[str] = frozenset({ _ENUM_PTR_ANNOTATION_NAMES: frozenset[str] = frozenset({
@@ -115,8 +115,8 @@ class ClassHandle(BaseHandle):
- ast.Name:'AST'(未注册类)或 'sha1.AST'(旧式点号名)→ 去前缀; - ast.Name:'AST'(未注册类)或 'sha1.AST'(旧式点号名)→ 去前缀;
- ast.Attribute:'sha1.AST' 经 _make_replacement_node/_make_name_node - ast.Attribute:'sha1.AST' 经 _make_replacement_node/_make_name_node
产出的 Attribute 链(Name('sha1').AST)→ attr 名。 产出的 Attribute 链(Name('sha1').AST)→ attr 名。
其余(Union `X | t.CPtr`、Subscript `list[T]`、内建)→ None,不追加 其余(Union `X | CPtr`、Subscript `list[T]`、内建)→ None,不追加
指针层(已显式写了 `| t.CPtr` 的注解不再重复加层)。 指针层(已显式写了 `| CPtr` 的注解不再重复加层)。
""" """
if isinstance(Node, ast.Name): if isinstance(Node, ast.Name):
Name: str = Node.id Name: str = Node.id
@@ -177,24 +177,24 @@ class ClassHandle(BaseHandle):
# 都不在类表里 → 天然判为值类型,无需名表。 # 都不在类表里 → 天然判为值类型,无需名表。
# 历史教训(名表判据的代价,保留以便回归时理解):`str` 曾漏在 # 历史教训(名表判据的代价,保留以便回归时理解):`str` 曾漏在
# "非类类型名"集合外 → `list[str]` 的类型参数被误判为类类型,特化后 # "非类类型名"集合外 → `list[str]` 的类型参数被误判为类类型,特化后
# 方法签名被额外包一层 `| t.CPtr`(append/set 形参 i8**、get/pop 返回 # 方法签名被额外包一层 `| CPtr`(append/set 形参 i8**、get/pop 返回
# i8**)→ 调用点多解一层 load(读字符串首 8 字节)→ ASan 崩溃。 # i8**)→ 调用点多解一层 load(读字符串首 8 字节)→ ASan 崩溃。
# 注意 _BUILTIN_TYPE_NAMES 本身仍保留:它用于 type_map 替换 # 注意 _BUILTIN_TYPE_NAMES 本身仍保留:它用于 type_map 替换
# 与 _t_c_imported_names 注册,不能把 'str' 并进去 # 与 _from_import_aliases 注册,不能把 'str' 并进去
# (否则 HandlesTypeMerge 会把注解 `str` 当 `t.str` 解析)。 # (否则 HandlesTypeMerge 会把注解 `str` 当内建类型名参与替换)。
type_map: dict[str, str] = {} type_map: dict[str, str] = {}
for i, tp_name in enumerate(type_param_names): for i, tp_name in enumerate(type_param_names):
if type_names and i < len(type_names): if type_names and i < len(type_names):
tn: str = type_names[i] tn: str = type_names[i]
# 判断是否为 t 模块内建类型(裸名或 't.' 前缀,如 'CInt'/'t.CInt'): # 判断是否为内建类型名(如 'CInt'):
# 内建类型必须用源码名(type_name)替换 T(t.CInt → i32),否则 # 内建类型必须用源码名(type_name)替换 T(CInt → i32),否则
# 用 mangled type_arg(如 'i32')替换会产生 'i32.__sizeof__' 这类 # 用 mangled type_arg(如 'i32')替换会产生 'i32.__sizeof__' 这类
# 源码中不存在的名称([FATAL][__sizeof__] 类型 'i32' 无法解析)。 # 源码中不存在的名称([FATAL][__sizeof__] 类型 'i32' 无法解析)。
# 真正的类类型参数(如 'AST'/'ast.AST')才用 mangled type_arg # 真正的类类型参数(如 'AST'/'ast.AST')才用 mangled type_arg
# (带 sha1 前缀 + ptr 后缀),避免模板内部嵌套注解被替换成裸短名 # (带 sha1 前缀 + ptr 后缀),避免模板内部嵌套注解被替换成裸短名
# 后重新特化出只有 declare、无方法体的错误特化(list[AST].__len__ # 后重新特化出只有 declare、无方法体的错误特化(list[AST].__len__
# undefined symbol 根因)。_make_replacement_node 会把 mangled 名 # undefined symbol 根因)。_make_replacement_node 会把 mangled 名
# 还原为 'sha1.AST | t.CPtr',重新解析时拼回一致的 mangled 名。 # 还原为 'sha1.AST | CPtr',重新解析时拼回一致的 mangled 名。
tn_bare: str = tn.split('.')[-1] if '.' in tn else tn tn_bare: str = tn.split('.')[-1] if '.' in tn else tn
if tn_bare in _BUILTIN_TYPE_NAMES: if tn_bare in _BUILTIN_TYPE_NAMES:
type_map[tp_name] = tn type_map[tp_name] = tn
@@ -204,11 +204,11 @@ class ClassHandle(BaseHandle):
type_map[tp_name] = tn type_map[tp_name] = tn
else: else:
type_map[tp_name] = type_args[i] type_map[tp_name] = type_args[i]
# 检测哪些类型参数在原始类型实参中带有指针语义(| t.CPtr / rawptr[T]) # 检测哪些类型参数在原始类型实参中带有指针语义(| CPtr / rawptr[T])
# 当 type_arg 以 '*' 结尾(mangling 把每个 CPtr 层渲染为一层 '*')且对应的 # 当 type_arg 以 '*' 结尾(mangling 把每个 CPtr 层渲染为一层 '*')且对应的
# type_name(去模块前缀后)不是内建类型名时,说明调用方写了 # type_name(去模块前缀后)不是内建类型名时,说明调用方写了
# list[AST | t.CPtr] / list[rawptr[AST]]。注意用 tn_bare 判断: # list[AST | CPtr] / list[rawptr[AST]]。注意用 tn_bare 判断:
# 't.CPtr' 去前缀后是 'CPtr'(内建),不算类类型参数。 # 'CPtr' 去前缀后是 'CPtr'(内建),不算类类型参数。
cptr_params: set[str] = set() cptr_params: set[str] = set()
for i, tp_name in enumerate(type_param_names): for i, tp_name in enumerate(type_param_names):
type_arg: str = type_args[i] type_arg: str = type_args[i]
@@ -218,8 +218,8 @@ class ClassHandle(BaseHandle):
if tn_bare_c not in _BUILTIN_TYPE_NAMES: if tn_bare_c not in _BUILTIN_TYPE_NAMES:
cptr_params.add(tp_name) cptr_params.add(tp_name)
# Bug 2 修复:识别特化为 class 类型的类型参数 # Bug 2 修复:识别特化为 class 类型的类型参数
# 这类参数在方法签名中是裸 T(无 | t.CPtr),特化后为裸 ClassName(值类型) # 这类参数在方法签名中是裸 T(无 | CPtr),特化后为裸 ClassName(值类型)
# 需要加 | t.CPtr 使其成为指针类型(class 实例应按指针传递) # 需要加 | CPtr 使其成为指针类型(class 实例应按指针传递)
# 判据 = "是否有类定义"(_HasClassDefinition),存**裸名**:注解侧的 # 判据 = "是否有类定义"(_HasClassDefinition),存**裸名**:注解侧的
# 比较也用裸名(T 替换后的 'sha1.Param' 去前缀)——此前存带模块前缀的 # 比较也用裸名(T 替换后的 'sha1.Param' 去前缀)——此前存带模块前缀的
# tn(如 'ast.AST')而比较用裸名 'AST',前缀形态永不命中。 # tn(如 'ast.AST')而比较用裸名 'AST',前缀形态永不命中。
@@ -229,142 +229,40 @@ class ClassHandle(BaseHandle):
tn_bare_cls: str = tn.split('.')[-1] if '.' in tn else tn tn_bare_cls: str = tn.split('.')[-1] if '.' in tn else tn
if self._HasClassDefinition(tn_bare_cls, Gen): if self._HasClassDefinition(tn_bare_cls, Gen):
class_type_names.add(tn_bare_cls) class_type_names.add(tn_bare_cls)
# 仅对 t 模块内建类型名注册 _t_c_imported_names(如 CInt -> ('t','CInt'))
# 类名(如 AST)不应注册为 t.AST,否则会污染名称解析
if type_names:
if not hasattr(self.Trans, '_t_c_imported_names'):
self.Trans._t_c_imported_names = {}
for tn in type_names:
if tn in _BUILTIN_TYPE_NAMES and tn not in self.Trans._t_c_imported_names:
self.Trans._t_c_imported_names[tn] = ('t', tn)
SpecNode: ast.ClassDef = copy.deepcopy(Node)
SpecNode.type_params = []
SpecNode.name = spec_name
for item in SpecNode.body:
if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name):
if item.annotation:
item.annotation = self.Trans.FunctionHandler._replace_type_in_annotation(item.annotation, type_map, cptr_params)
elif isinstance(item, ast.FunctionDef):
for arg in item.args.args:
if arg.annotation:
arg.annotation = self.Trans.FunctionHandler._replace_type_in_annotation(arg.annotation, type_map, cptr_params)
# class 类型参数加指针语义:T -> GNode -> GNode | t.CPtr
# T 替换后的真实形态是 Attribute 链('<sha1>.GNode' →
# Name('<sha1>').GNode,见 _make_replacement_node/_make_name_node),
# 不是 ast.Name:此前只认 ast.Name → 方法形参漏加 | t.CPtr,
# 特化后按值结构体传参(被调者栈帧副本地址入链 → 悬垂写)。
raw_name: str | None = self._BareClassAnnotationName(arg.annotation)
if raw_name is not None and raw_name in class_type_names:
arg.annotation = ast.BinOp(
left=arg.annotation,
op=ast.BitOr(),
right=ast.Attribute(value=ast.Name(id='t', ctx=ast.Load()), attr='CPtr', ctx=ast.Load())
)
if item.returns:
item.returns = self.Trans.FunctionHandler._replace_type_in_annotation(item.returns, type_map, cptr_params)
# 返回类型也加指针语义(同一裸名判据,形态同上)
raw_name: str | None = self._BareClassAnnotationName(item.returns)
if raw_name is not None and raw_name in class_type_names:
item.returns = ast.BinOp(
left=item.returns,
op=ast.BitOr(),
right=ast.Attribute(value=ast.Name(id='t', ctx=ast.Load()), attr='CPtr', ctx=ast.Load())
)
self.Trans.FunctionHandler._apply_type_map_to_body(item.body, type_map, cptr_params)
saved_builder: ir.IRBuilder = Gen.builder
saved_func: ir.Function = Gen.func
saved_variables: dict = dict(Gen.variables) if Gen.variables else {}
saved_direct_values: dict = dict(Gen._direct_values) if Gen._direct_values else {}
saved_var_type_info: dict = dict(Gen.var_type_info) if Gen.var_type_info else {}
saved_var_signedness: dict = dict(Gen.var_signedness) if Gen.var_signedness else {}
saved_global_vars: set = set(Gen.global_vars) if Gen.global_vars else set()
saved_var_scopes: list = [dict(s) for s in self.Trans.VarScopes] if self.Trans.VarScopes else []
saved_block: ir.Block | None = None
if Gen.builder and Gen.builder.block and not Gen.builder.block.is_terminated:
saved_block = Gen.builder.block
# 切换 module_sha1 为泛型模板定义模块的 SHA1,
# 使结构体类型名和方法定义名都用定义模块的 SHA1 前缀,
# 与调用端 _struct_sha1_map 查到的 SHA1 一致。
template_sha1: str | None = template.get('sha1')
if not template_sha1:
# 模板注册表缺 sha1 时回退到"模板类定义模块"(_struct_sha1_map 即
# 类名 → 定义模块表,Phase2 从各 .vpi 扫描构建):与声明端
# DeclarationGenerator._get_type_str 的泛型前缀、调用点
# Gen._struct_sha1_map[spec_name] 同一条规则源;否则 declare/define
# 两侧前缀分裂(使用方模块 vs 模板模块)→ 跨模块 undefined symbol。
template_sha1 = Gen._struct_sha1_map.get(ClassName)
saved_gen_sha1: str | None = getattr(Gen, 'module_sha1', None)
saved_trans_sha1: str | None = getattr(self.Trans, '_module_sha1', None)
if template_sha1:
Gen.module_sha1 = template_sha1
self.Trans._module_sha1 = template_sha1
try:
self._EmitClassLlvm(SpecNode, Gen, declare_only=declare_only)
finally:
# 确保 Gen 状态恢复,即使 _EmitClassLlvm 抛出异常
Gen.builder = saved_builder
if saved_block is not None and Gen.builder is not None:
Gen.builder.position_at_end(saved_block)
Gen.func = saved_func
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
self.Trans.VarScopes = saved_var_scopes
# 恢复原始 module_sha1
Gen.module_sha1 = saved_gen_sha1
self.Trans._module_sha1 = saved_trans_sha1
Gen._generic_class_specializations[spec_key] = (spec_name, declare_only)
# 缓存 type_args/type_names,供后续 declare_only=False 完整特化补发方法体使用
# (如 _HandleMethodCallLlvm 中发现方法未定义时触发)
if not hasattr(Gen, '_generic_class_spec_type_info'):
Gen._generic_class_spec_type_info = {}
Gen._generic_class_spec_type_info[spec_key] = (list(type_args), list(type_names) if type_names else None)
if not hasattr(self.Trans, '_generic_class_specializations'):
self.Trans._generic_class_specializations = {}
self.Trans._generic_class_specializations[spec_key] = spec_name
# 用模板定义模块的 SHA1 注册到 _struct_sha1_map,与方法定义端一致
if template_sha1:
Gen._struct_sha1_map[spec_name] = template_sha1
elif hasattr(self.Trans, '_module_sha1') and self.Trans._module_sha1:
Gen._struct_sha1_map[spec_name] = self.Trans._module_sha1
return spec_name
def _resolve_base_kind(self, base_name: str, Gen: LlvmGeneratorMixin) -> str | None: def _resolve_base_kind(self, base_name: str, Gen: LlvmGeneratorMixin) -> str | None:
"""解析基类名称的类型种类 """解析基类名称的类型种类
查询顺序: 查询顺序:
1. _t_type_symbols(from t import CEnum as en) 1. _builtin_type_symbols(内建类型符号)
2. t 模块属性(t.CEnum / t.CUnion / t.CStruct / t.REnum) 2. TypeSystem 内建类型属性(CEnum / CUnion / CStruct / REnum)
3. 返回 None 表示不是已知标记基类 3. 返回 None 表示不是已知标记基类
Returns: Returns:
'enum' | 'union' | 'renum' | 'struct' | None 'enum' | 'union' | 'renum' | 'struct' | None
""" """
# 1) 查 _t_type_symbols(别名导入) # 1) 查 _builtin_type_symbols(别名导入)
symtab: object = self.Trans.SymbolTable symtab: object = self.Trans.SymbolTable
cls: type | None = symtab._t_type_symbols.get(base_name) cls: type | None = symtab._builtin_type_symbols.get(base_name)
if cls is not None: if cls is not None:
if issubclass(cls, (t.CEnum, t.REnum)): if issubclass(cls, (TypeSystem.CEnum, TypeSystem.REnum)):
return 'renum' if issubclass(cls, t.REnum) else 'enum' return 'renum' if issubclass(cls, TypeSystem.REnum) else 'enum'
if issubclass(cls, t.CUnion): if issubclass(cls, TypeSystem.CUnion):
return 'union' return 'union'
if issubclass(cls, t.CStruct): if issubclass(cls, TypeSystem.CStruct):
return 'struct' return 'struct'
# CType 及其子类(CChar/CInt/CVoid/CPtr 等)是"类型强转"标记, # CType 及其子类(CChar/CInt/CVoid/CPtr 等)是"类型强转"标记,
# 不应被编译为真实结构体。 # 不应被编译为真实结构体。
if issubclass(cls, t.CType): if issubclass(cls, TypeSystem.CType):
return 'ctype_marker' return 'ctype_marker'
# 2) 查 t 模块属性(直接引用 t.CEnum 等) # 2) 查 TypeSystem 内建类型属性(直接引用 CEnum 等)
t_cls: type | None = getattr(t, base_name, None) t_cls: type | None = getattr(TypeSystem, base_name, None)
if isinstance(t_cls, type) and issubclass(t_cls, t.CType): if isinstance(t_cls, type) and issubclass(t_cls, TypeSystem.CType):
if issubclass(t_cls, (t.CEnum, t.REnum)): if issubclass(t_cls, (TypeSystem.CEnum, TypeSystem.REnum)):
return 'renum' if issubclass(t_cls, t.REnum) else 'enum' return 'renum' if issubclass(t_cls, TypeSystem.REnum) else 'enum'
if issubclass(t_cls, t.CUnion): if issubclass(t_cls, TypeSystem.CUnion):
return 'union' return 'union'
if issubclass(t_cls, t.CStruct): if issubclass(t_cls, TypeSystem.CStruct):
return 'struct' return 'struct'
# CType 及其子类是"类型强转"标记,不编译为结构体。 # CType 及其子类是"类型强转"标记,不编译为结构体。
return 'ctype_marker' return 'ctype_marker'
@@ -373,7 +271,7 @@ class ClassHandle(BaseHandle):
@staticmethod @staticmethod
def _is_classname_ctype_marker(class_name: str) -> bool: def _is_classname_ctype_marker(class_name: str) -> bool:
"""检查类名是否是 t.CType 的"类型强转"标记子类。 """检查类名是否是 CType 的"类型强转"标记子类。
只有 position 不含 BASE 的纯修饰符/标记类型(CPtr/CVolatile/CConst/ 只有 position 不含 BASE 的纯修饰符/标记类型(CPtr/CVolatile/CConst/
CInline/CStatic/CExtern/CExport/CRegister/CAuto/_CTypedef/CTypeDefault 等) CInline/CStatic/CExtern/CExport/CRegister/CAuto/_CTypedef/CTypeDefault 等)
@@ -382,22 +280,22 @@ class ClassHandle(BaseHandle):
需要直接按类名检查。 需要直接按类名检查。
注意:CTypeRegistry.GetClassByName 会跳过 CType 本身和 CTypeDefault, 注意:CTypeRegistry.GetClassByName 会跳过 CType 本身和 CTypeDefault,
所以这里直接用 getattr(t, name) 检查 t 模块属性。 所以这里直接用 getattr(TypeSystem, name) 检查内建类型属性。
Returns: Returns:
True 如果 class_name 是 CType 标记子类名(应跳过编译) True 如果 class_name 是 CType 标记子类名(应跳过编译)
""" """
if not class_name: if not class_name:
return False return False
# 直接查 t 模块属性(CTypeRegistry._build 会跳过 CType/CTypeDefault/BigEndian/LittleEndian) # 直接查 TypeSystem 内建类型属性(CTypeRegistry._build 会跳过 CType/CTypeDefault/BigEndian/LittleEndian)
t_cls: type | None = getattr(t, class_name, None) t_cls: type | None = getattr(TypeSystem, class_name, None)
if not isinstance(t_cls, type) or not issubclass(t_cls, t.CType): if not isinstance(t_cls, type) or not issubclass(t_cls, TypeSystem.CType):
return False return False
if issubclass(t_cls, (t.CStruct, t.CEnum, t.REnum, t.CUnion)): if issubclass(t_cls, (TypeSystem.CStruct, TypeSystem.CEnum, TypeSystem.REnum, TypeSystem.CUnion)):
return False return False
# 基本类型(position 含 BASE 且 Size > 0)有具体大小,不应跳过 # 基本类型(position 含 BASE 且 Size > 0)有具体大小,不应跳过
# CVoid 虽含 BASE 但 Size=0,CType Size=None,仍需跳过 # CVoid 虽含 BASE 但 Size=0,CType Size=None,仍需跳过
if t.CType.BASE in t_cls.position: if TypeSystem.CType.BASE in t_cls.position:
try: try:
inst = t_cls() inst = t_cls()
size_val = getattr(inst, 'Size', None) size_val = getattr(inst, 'Size', None)
@@ -410,8 +308,7 @@ class ClassHandle(BaseHandle):
def _resolve_decorator_kind(self, Node: ast.ClassDef, Gen: LlvmGeneratorMixin) -> str | None: def _resolve_decorator_kind(self, Node: ast.ClassDef, Gen: LlvmGeneratorMixin) -> str | None:
"""从装饰器列表中解析结构体类型种类 """从装饰器列表中解析结构体类型种类
支持 @t.CStruct, @t.CUnion, @t.CEnum, @t.REnum 支持 @CStruct, @CUnion, @CEnum, @REnum(内建标记按裸名书写)
也支持 from t import CStruct 等别名形式
Returns: Returns:
'enum' | 'union' | 'renum' | 'struct' | None 'enum' | 'union' | 'renum' | 'struct' | None
@@ -421,32 +318,28 @@ class ClassHandle(BaseHandle):
symtab: object = self.Trans.SymbolTable symtab: object = self.Trans.SymbolTable
for decorator in Node.decorator_list: for decorator in Node.decorator_list:
attr_name: str | None = None attr_name: str | None = None
# @t.CStruct 形式 # 内建标记按裸名书写(@CStruct / @CUnion / ...)
if isinstance(decorator, ast.Attribute) and isinstance(decorator.value, ast.Name): if isinstance(decorator, ast.Name):
if IsTModule(decorator.value.id, symtab): cls: type | None = getattr(TypeSystem, decorator.id, None)
attr_name = decorator.attr if cls is None and hasattr(symtab, '_builtin_type_symbols'):
# @CStruct 形式 (from t import CStruct) cls = symtab._builtin_type_symbols.get(decorator.id)
elif isinstance(decorator, ast.Name): if cls is not None and isinstance(cls, type) and issubclass(cls, TypeSystem.CType):
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__ attr_name = cls.__name__
if attr_name: if attr_name:
# 查 _t_type_symbols 和 t 模块属性以确定种类 # 查 _builtin_type_symbols 和 TypeSystem 内建类型属性以确定种类
resolved_cls: type | None = None resolved_cls: type | None = None
if hasattr(symtab, '_t_type_symbols'): if hasattr(symtab, '_builtin_type_symbols'):
resolved_cls = symtab._t_type_symbols.get(attr_name) resolved_cls = symtab._builtin_type_symbols.get(attr_name)
if resolved_cls is None: if resolved_cls is None:
resolved_cls = getattr(t, attr_name, None) resolved_cls = getattr(TypeSystem, attr_name, None)
if resolved_cls is not None and isinstance(resolved_cls, type): if resolved_cls is not None and isinstance(resolved_cls, type):
if issubclass(resolved_cls, t.REnum): if issubclass(resolved_cls, TypeSystem.REnum):
return 'renum' return 'renum'
if issubclass(resolved_cls, t.CEnum): if issubclass(resolved_cls, TypeSystem.CEnum):
return 'enum' return 'enum'
if issubclass(resolved_cls, t.CUnion): if issubclass(resolved_cls, TypeSystem.CUnion):
return 'union' return 'union'
if issubclass(resolved_cls, t.CStruct): if issubclass(resolved_cls, TypeSystem.CStruct):
return 'struct' return 'struct'
return None return None
@@ -466,15 +359,7 @@ class ClassHandle(BaseHandle):
IsNoVTable: bool = False IsNoVTable: bool = False
if hasattr(Node, 'decorator_list') and Node.decorator_list: if hasattr(Node, 'decorator_list') and Node.decorator_list:
for decorator in Node.decorator_list: for decorator in Node.decorator_list:
if isinstance(decorator, ast.Attribute): if isinstance(decorator, ast.Name):
if hasattr(decorator.value, 'id') and IsTModule(decorator.value.id, self.Trans.SymbolTable):
if decorator.attr == 'Object':
IsCpythonObject = True
elif decorator.attr == 'CVTable':
IsCVTable = True
elif decorator.attr == 'NoVTable':
IsNoVTable = True
elif isinstance(decorator, ast.Name):
if decorator.id == 'Object': if decorator.id == 'Object':
IsCpythonObject = True IsCpythonObject = True
elif decorator.id == 'CVTable': elif decorator.id == 'CVTable':
@@ -482,21 +367,21 @@ class ClassHandle(BaseHandle):
elif decorator.id == 'NoVTable': elif decorator.id == 'NoVTable':
IsNoVTable = True IsNoVTable = True
elif isinstance(decorator, ast.Call): elif isinstance(decorator, ast.Call):
# 检测 @c.Attribute(t.attr.packed) # 检测 @Attribute(attr.packed)
if isinstance(decorator.func, ast.Attribute): if isinstance(decorator.func, ast.Name) and decorator.func.id == 'Attribute':
if getattr(decorator.func.value, 'id', None) == 'c' and decorator.func.attr == 'Attribute': for arg in decorator.args:
for arg in decorator.args: if (isinstance(arg, ast.Attribute)
if isinstance(arg, ast.Attribute): and isinstance(arg.value, ast.Name)
if isinstance(arg.value, ast.Attribute): and arg.value.id == 'attr'
if IsTModule(getattr(arg.value.value, 'id', ''), self.Trans.SymbolTable) and arg.value.attr == 'attr' and arg.attr == 'packed': and arg.attr == 'packed'):
Gen.class_packed.add(ClassName) Gen.class_packed.add(ClassName)
class_graph: dict = Gen._class_graph class_graph: dict = Gen._class_graph
if class_graph.get(ClassName, {}).get('has_methods', False) and not IsNoVTable: if class_graph.get(ClassName, {}).get('has_methods', False) and not IsNoVTable:
if not IsCpythonObject: if not IsCpythonObject:
IsCpythonObject = True IsCpythonObject = True
# 多继承支持(与 VPC _detect_vtable_status 对齐):不再因"作为其他类的基类" # 多继承支持(与 VPC _detect_vtable_status 对齐):不再因"作为其他类的基类"
# 自动启用 vtable。vtable 状态统一由继承链决定(见下方 HasParentClass 判定): # 自动启用 vtable。vtable 状态统一由继承链决定(见下方 HasParentClass 判定):
# 类自身无 @t.CVTable 时,父类有 vtable → 子类有;父类无 vtable → 子类静态。 # 类自身无 @CVTable 时,父类有 vtable → 子类有;父类无 vtable → 子类静态。
# 否则基类(如 C(A,B) 中的 A/B)被自动加 vptr 后,其字段区在子类中的偏移 # 否则基类(如 C(A,B) 中的 A/B)被自动加 vptr 后,其字段区在子类中的偏移
# 与自身布局不一致,继承方法按自身布局读 self 会字段错位。 # 与自身布局不一致,继承方法按自身布局读 self 会字段错位。
HasParentClass: bool = False HasParentClass: bool = False
@@ -512,7 +397,7 @@ class ClassHandle(BaseHandle):
base_name = base.attr base_name = base.attr
if base_name: if base_name:
kind: str | None = self._resolve_base_kind(base_name, Gen) kind: str | None = self._resolve_base_kind(base_name, Gen)
if kind is not None or base_name in t._MARKER_BASES: if kind is not None or base_name in TypeSystem._MARKER_BASES:
continue # 标记基类,跳过 continue # 标记基类,跳过
# 多继承:收集所有真实父类(声明顺序),不再 break # 多继承:收集所有真实父类(声明顺序),不再 break
ParentClasses.append(base_name) ParentClasses.append(base_name)
@@ -520,7 +405,7 @@ class ClassHandle(BaseHandle):
ParentClassName = base_name ParentClassName = base_name
if base_name in class_graph or base_name in Gen.class_members or base_name in Gen.structs: if base_name in class_graph or base_name in Gen.class_members or base_name in Gen.structs:
HasParentClass = True HasParentClass = True
# 检测父类是否有 @t.NoVTable 标记(非多态继承) # 检测父类是否有 @NoVTable 标记(非多态继承)
if class_graph.get(base_name, {}).get('has_novtable', False): if class_graph.get(base_name, {}).get('has_novtable', False):
ParentIsNoVTable = True ParentIsNoVTable = True
# 跨模块父类:检查 _cross_module_novtable 集合 # 跨模块父类:检查 _cross_module_novtable 集合
@@ -531,7 +416,7 @@ class ClassHandle(BaseHandle):
# 父类有 vtable → 子类启用;父类无 vtable → 子类不启用(静态); # 父类有 vtable → 子类启用;父类无 vtable → 子类不启用(静态);
# 父类 vtable 状态未知(跨模块/未注册)→ 保守启用。 # 父类 vtable 状态未知(跨模块/未注册)→ 保守启用。
# 沿继承链追溯父类的 vtable 状态(支持空中间基类 Stmt/ExprNode): # 沿继承链追溯父类的 vtable 状态(支持空中间基类 Stmt/ExprNode):
# Stmt/ExprNode 无方法但 @t.CVTable,跨模块加载时 _has_methods_prescan=False # Stmt/ExprNode 无方法但 @CVTable,跨模块加载时 _has_methods_prescan=False
# 未注册 class_vtable,若只查直接父类会误判子类为静态类 → # 未注册 class_vtable,若只查直接父类会误判子类为静态类 →
# __before_init__ base=0 不写 vtable → 实例 vtable 为 null → 虚调用段错误。 # __before_init__ base=0 不写 vtable → 实例 vtable 为 null → 虚调用段错误。
# 修复:沿 class_parent 链向上查,任一祖先有 vtable 即判定子类有 vtable。 # 修复:沿 class_parent 链向上查,任一祖先有 vtable 即判定子类有 vtable。
@@ -552,7 +437,7 @@ class ClassHandle(BaseHandle):
or ParentClassName in Gen.structs) or ParentClassName in Gen.structs)
if parent_has_vtable or not parent_known: if parent_has_vtable or not parent_known:
IsCVTable = True IsCVTable = True
# 方法级 virtual(`virtual def m(...)` ⇒ 方法装饰器 @t.CVTable)触发类级 vtable: # 方法级 virtual(`virtual def m(...)` ⇒ 方法装饰器 @CVTable)触发类级 vtable:
# 与 VPC ClassGenBase._detect_vtable_status 的三条 `_has_any_func_cvtable` # 与 VPC ClassGenBase._detect_vtable_status 的三条 `_has_any_func_cvtable`
# 分支逐条对齐(类级 NoVTable / 父类 NoVTable / 无真实父类)。 # 分支逐条对齐(类级 NoVTable / 父类 NoVTable / 无真实父类)。
# 注意"父类已知且无 vtable" **不**触发(VPC 同分支返回 0)—— # 注意"父类已知且无 vtable" **不**触发(VPC 同分支返回 0)——
@@ -575,7 +460,7 @@ class ClassHandle(BaseHandle):
ancestor_bases: list = ancestor_info.get('bases', []) ancestor_bases: list = ancestor_info.get('bases', [])
next_ancestor: str | None = None next_ancestor: str | None = None
for ab in ancestor_bases: for ab in ancestor_bases:
if ab not in t._MARKER_BASES and ab not in visited: if ab not in TypeSystem._MARKER_BASES and ab not in visited:
next_ancestor = ab next_ancestor = ab
break break
ancestor = next_ancestor ancestor = next_ancestor
@@ -661,14 +546,14 @@ class ClassHandle(BaseHandle):
""" """
MemberNode: CTypeInfo = CTypeInfo() MemberNode: CTypeInfo = CTypeInfo()
MemberNode.Name = NestedName MemberNode.Name = NestedName
MemberNode.BaseType = t.CStruct(name=NestedName) MemberNode.BaseType = TypeSystem.CStruct(name=NestedName)
MemberNode.IsStruct = True MemberNode.IsStruct = True
self.Trans.SymbolTable.insert(NestedName, MemberNode) self.Trans.SymbolTable.insert(NestedName, MemberNode)
self.Trans.SymbolTable.insert(f'{ClassName}.{InnerName}', MemberNode) self.Trans.SymbolTable.insert(f'{ClassName}.{InnerName}', MemberNode)
def _EmitClassLlvm(self, Node: ast.ClassDef, Gen: LlvmGeneratorMixin, declare_only: bool = False) -> None: def _EmitClassLlvm(self, Node: ast.ClassDef, Gen: LlvmGeneratorMixin, declare_only: bool = False) -> None:
ClassName: str = Node.name ClassName: str = Node.name
# t.CType 及其子类(CChar/CInt/CVoid/CPtr/CTypeDefault 等)是"类型强转"标记, # CType 及其子类(CChar/CInt/CVoid/CPtr/CTypeDefault 等)是"类型强转"标记,
# 不应被编译为真实结构体。CType 基类本身无 bases,base 检测无法触发, # 不应被编译为真实结构体。CType 基类本身无 bases,base 检测无法触发,
# 此处在方法入口直接按类名跳过。 # 此处在方法入口直接按类名跳过。
if self._is_classname_ctype_marker(ClassName): if self._is_classname_ctype_marker(ClassName):
@@ -682,7 +567,7 @@ class ClassHandle(BaseHandle):
IsCenum: bool = False IsCenum: bool = False
IsCunion: bool = False IsCunion: bool = False
IsRenum: bool = False IsRenum: bool = False
# 先检查装饰器形式(@t.CStruct / @t.CEnum / @t.CUnion / @t.REnum) # 先检查装饰器形式(@CStruct / @CEnum / @CUnion / @REnum)
deco_kind: str | None = self._resolve_decorator_kind(Node, Gen) deco_kind: str | None = self._resolve_decorator_kind(Node, Gen)
if deco_kind == 'enum': if deco_kind == 'enum':
IsCenum = True IsCenum = True
@@ -690,7 +575,7 @@ class ClassHandle(BaseHandle):
IsCunion = True IsCunion = True
elif deco_kind == 'renum': elif deco_kind == 'renum':
IsRenum = True IsRenum = True
# 再检查基类继承形式(class X(t.CStruct):),与装饰器合并 # 再检查基类继承形式(class X(CStruct):),与装饰器合并
if not IsCenum and not IsCunion and not IsRenum and Node.bases: if not IsCenum and not IsCunion and not IsRenum and Node.bases:
for base in Node.bases: for base in Node.bases:
base_name: str | None = None base_name: str | None = None
@@ -752,7 +637,7 @@ class ClassHandle(BaseHandle):
if m.split('.')[-1] not in ('__new__', '__init__', '__before_init__') if m.split('.')[-1] not in ('__new__', '__init__', '__before_init__')
] ]
# 当前文件定义的类是权威定义,覆盖之前导入阶段可能添加的外部声明。 # 当前文件定义的类是权威定义,覆盖之前导入阶段可能添加的外部声明。
# 关键:如果本地类是 @t.NoVTable 但同名导入类有 vtable(名称冲突), # 关键:如果本地类是 @NoVTable 但同名导入类有 vtable(名称冲突),
# 必须清除 vtable 状态,否则 _generate_structs 会错误添加 vtable 指针。 # 必须清除 vtable 状态,否则 _generate_structs 会错误添加 vtable 指针。
if IsNoVTable: if IsNoVTable:
Gen.class_vtable.discard(ClassName) Gen.class_vtable.discard(ClassName)
@@ -1001,7 +886,7 @@ class ClassHandle(BaseHandle):
# 由 HandlesImports.py:2647/2654 与 FuncGen.py:1057 触发;该分支不受 # 由 HandlesImports.py:2647/2654 与 FuncGen.py:1057 触发;该分支不受
# "字段收集中"保护,见 HandlesImports.py:3299 的 `not force` 豁免)。 # "字段收集中"保护,见 HandlesImports.py:3299 的 `not force` 豁免)。
# 此时本循环后面的 `append` 会把**嵌套帧已经登记过的同一字段**再写一条 —— # 此时本循环后面的 `append` 会把**嵌套帧已经登记过的同一字段**再写一条 ——
# 现场:AST 的最后一个字段 `children: list[rawptr[AST]] | t.CPtr` 是全类唯一 # 现场:AST 的最后一个字段 `children: list[rawptr[AST]] | CPtr` 是全类唯一
# 触发泛型特化的注解,处理它时嵌套帧重填了 AST 表(7 项),本循环恢复后 # 触发泛型特化的注解,处理它时嵌套帧重填了 AST 表(7 项),本循环恢复后
# 又追加一次 `children` ⇒ 表 8 项 / 去重 7 项,重名条目 `children@7`; # 又追加一次 `children` ⇒ 表 8 项 / 去重 7 项,重名条目 `children@7`;
# 该表又被祖先块展平**原样拷贝**给 AST 的每个子类(_FlattenInherited 只按 # 该表又被祖先块展平**原样拷贝**给 AST 的每个子类(_FlattenInherited 只按
@@ -1033,7 +918,7 @@ class ClassHandle(BaseHandle):
element_class: str | None = FindStructNameInAnnotationWithContext( element_class: str | None = FindStructNameInAnnotationWithContext(
item.annotation, self.Trans, Gen) item.annotation, self.Trans, Gen)
# Fallback: FindStructNameInAnnotation 不处理 Subscript slice 为 BinOp 的情况 # Fallback: FindStructNameInAnnotation 不处理 Subscript slice 为 BinOp 的情况
# (如 list[AST | t.CPtr] | t.CPtr),使用 TypeInfo.Name 作为回退。 # (如 list[AST | CPtr] | CPtr),使用 TypeInfo.Name 作为回退。
# TypeInfo.Name 由 _HandleSubscript 设置为特化名(如 'list[sha1.AST*]'), # TypeInfo.Name 由 _HandleSubscript 设置为特化名(如 'list[sha1.AST*]'),
# 经 _MergeCTypeInfoInto 传播后保留。 # 经 _MergeCTypeInfoInto 传播后保留。
if not element_class and TypeInfo.IsStruct and TypeInfo.Name and TypeInfo.Name in Gen.structs: if not element_class and TypeInfo.IsStruct and TypeInfo.Name and TypeInfo.Name in Gen.structs:
@@ -1042,7 +927,7 @@ class ClassHandle(BaseHandle):
if ClassName not in Gen.class_member_element_class: if ClassName not in Gen.class_member_element_class:
Gen.class_member_element_class[ClassName] = {} Gen.class_member_element_class[ClassName] = {}
Gen.class_member_element_class[ClassName][VarName] = element_class Gen.class_member_element_class[ClassName][VarName] = element_class
# 泛型特化结构体指针字段(如 GSList[BasicBlock] | t.CPtr): # 泛型特化结构体指针字段(如 GSList[BasicBlock] | CPtr):
# 记录特化名,供后续 _try_access_opaque_generic_member 在所有候选特化版本 # 记录特化名,供后续 _try_access_opaque_generic_member 在所有候选特化版本
# 都有目标字段(如 Head/Tail/Count)时选择正确特化版本。 # 都有目标字段(如 Head/Tail/Count)时选择正确特化版本。
# 现有 i8* 分支不覆盖结构体指针字段,这里补充。 # 现有 i8* 分支不覆盖结构体指针字段,这里补充。
@@ -1095,7 +980,7 @@ class ClassHandle(BaseHandle):
else: else:
# rawptr[裸结构](如 rawptr[Token]):跨模块 stub 会把自引用/类内 # rawptr[裸结构](如 rawptr[Token]):跨模块 stub 会把自引用/类内
# 指针字段退化为 i8*,链式成员访问(a.b.c)需 element_class 恢复 # 指针字段退化为 i8*,链式成员访问(a.b.c)需 element_class 恢复
# struct 身份走 char*→struct cast。HEAD 态 `Token | t.CPtr` 联合 # struct 身份走 char*→struct cast。HEAD 态 `Token | CPtr` 联合
# 由上方 BinOp 分支登记;rawptr 重构后此分支补齐(阻塞 A 根因)。 # 由上方 BinOp 分支登记;rawptr 重构后此分支补齐(阻塞 A 根因)。
# 与 HandlesImports 的 rawptr 分支对称。 # 与 HandlesImports 的 rawptr 分支对称。
_slc_name_c: str | None = None _slc_name_c: str | None = None
@@ -1169,7 +1054,7 @@ class ClassHandle(BaseHandle):
# `base + 表内下标`(FuncGen._get_member_offset)⇒ 落到**类型完全不同的槽**。 # `base + 表内下标`(FuncGen._get_member_offset)⇒ 落到**类型完全不同的槽**。
# 现场:TypeGenCType 重复声明 5 个父类已有字段后,继承字段 # 现场:TypeGenCType 重复声明 5 个父类已有字段后,继承字段
# LastBuiltinsTypedefResult(下标 32)前移为 27 = CTypedefNameIdxBuilt(i32) # LastBuiltinsTypedefResult(下标 32)前移为 27 = CTypedefNameIdxBuilt(i32)
# ⇒ `self.Gen.TypeGenCType.LastBuiltinsTypedefResult = "t.CPtr"` 报 # ⇒ `self.Gen.TypeGenCType.LastBuiltinsTypedefResult = "CPtr"` 报
# "指针隐式转整数已禁止:不能把指针类型 i8* 赋给整数类型 i32"。 # "指针隐式转整数已禁止:不能把指针类型 i8* 赋给整数类型 i32"。
# ② 父类方法按**父类布局**访问该名字的槽、子类方法按**自有槽**访问 ⇒ 同名两槽 # ② 父类方法按**父类布局**访问该名字的槽、子类方法按**自有槽**访问 ⇒ 同名两槽
# split-brain(一侧写、另一侧读),运行期静默错值。 # split-brain(一侧写、另一侧读),运行期静默错值。
@@ -1255,8 +1140,8 @@ class ClassHandle(BaseHandle):
# vtable 大小不一致导致虚分派索引偏移。__before_init__ 由 TPC # vtable 大小不一致导致虚分派索引偏移。__before_init__ 由 TPC
# 自动生成,不会出现在 FunctionDef 中,此处一并防御。 # 自动生成,不会出现在 FunctionDef 中,此处一并防御。
# #
# 方法级修饰符(`novirtual def m(...)` ⇒ @t.NoVTable / # 方法级修饰符(`novirtual def m(...)` ⇒ @NoVTable /
# `virtual def m(...)` ⇒ @t.CVTable):是否占槽按 # `virtual def m(...)` ⇒ @CVTable):是否占槽按
# SymbolUtils.IsVtableSlotMethod 判定——与 VPC # SymbolUtils.IsVtableSlotMethod 判定——与 VPC
# ClassGenBase._should_method_be_virtual 同判据(**唯一规则源**), # ClassGenBase._should_method_be_virtual 同判据(**唯一规则源**),
# 故 TPC/VPC 的虚表槽位顺序与数量逐槽一致(含"类级 NoVTable + # 故 TPC/VPC 的虚表槽位顺序与数量逐槽一致(含"类级 NoVTable +
@@ -1596,7 +1481,7 @@ class ClassHandle(BaseHandle):
f"`self.{VarName} = {_val_txt}` 的取值形态推不出成员类型" f"`self.{VarName} = {_val_txt}` 的取值形态推不出成员类型"
f"——拒绝静默当成 i32(那会把错误推到下游:写指针值时报" f"——拒绝静默当成 i32(那会把错误推到下游:写指针值时报"
f"「指针隐式转整数已禁止」)。请在类体声明该字段并给注解" f"「指针隐式转整数已禁止」)。请在类体声明该字段并给注解"
f"(如 `{VarName}: t.CInt32T` / `{VarName}: t.CPtr`)," f"(如 `{VarName}: CInt32T` / `{VarName}: CPtr`),"
f"或在赋值处给出可定型的取值。" f"或在赋值处给出可定型的取值。"
f"位置 {_src_f}:{_ln_f}:{_col_f}") f"位置 {_src_f}:{_ln_f}:{_col_f}")
_vlog().compile_error(_msg_f, _src_f, _ln_f, _code_f) _vlog().compile_error(_msg_f, _src_f, _ln_f, _code_f)
@@ -1664,18 +1549,18 @@ class ClassHandle(BaseHandle):
variant_names: list[str] = [] variant_names: list[str] = []
# 预注册 REnum opaque 结构体到 Gen.structs 和 SymbolTable, # 预注册 REnum opaque 结构体到 Gen.structs 和 SymbolTable,
# 使自引用成员(如 LLVMType | t.CPtr)在收集成员时能正确解析为 %LLVMType*。 # 使自引用成员(如 LLVMType | CPtr)在收集成员时能正确解析为 %LLVMType*。
# 若不预注册,GetCTypeInfo 找不到 LLVMType → 回退到 IsEnum → i32 → | t.CPtr → i32*(错误)。 # 若不预注册,GetCTypeInfo 找不到 LLVMType → 回退到 IsEnum → i32 → | CPtr → i32*(错误)。
PreRenumType: ir.IdentifiedStructType = ir.IdentifiedStructType(Gen.module, ClassName) PreRenumType: ir.IdentifiedStructType = ir.IdentifiedStructType(Gen.module, ClassName)
Gen.structs[ClassName] = PreRenumType Gen.structs[ClassName] = PreRenumType
PreTypeInfo: CTypeInfo = CTypeInfo() PreTypeInfo: CTypeInfo = CTypeInfo()
PreTypeInfo.Name = ClassName PreTypeInfo.Name = ClassName
PreTypeInfo.BaseType = t.REnum(ClassName) PreTypeInfo.BaseType = TypeSystem.REnum(ClassName)
PreTypeInfo.IsRenum = True PreTypeInfo.IsRenum = True
PreTypeInfo.IsEnum = True PreTypeInfo.IsEnum = True
# REnum 在内存布局上是 struct({ i32 __tag, <max_payload> }), # REnum 在内存布局上是 struct({ i32 __tag, <max_payload> }),
# 必须设置 IsStruct=True 才能让 HandlesTypeMerge 的 CPtr 吸收逻辑生效: # 必须设置 IsStruct=True 才能让 HandlesTypeMerge 的 CPtr 吸收逻辑生效:
# `REnumType | t.CPtr` 应得到 REnumType*(PtrCount=1)而非 REnumType**(PtrCount=2)。 # `REnumType | CPtr` 应得到 REnumType*(PtrCount=1)而非 REnumType**(PtrCount=2)。
# 否则 include-imported 函数返回类型会出现双指针,与声明单指针不匹配 → 运行时崩溃。 # 否则 include-imported 函数返回类型会出现双指针,与声明单指针不匹配 → 运行时崩溃。
PreTypeInfo.IsStruct = True PreTypeInfo.IsStruct = True
PreTypeInfo.RenumVariants = [] PreTypeInfo.RenumVariants = []
@@ -1795,7 +1680,7 @@ class ClassHandle(BaseHandle):
Gen.class_member_signeds[NestedStructName][mname] = None Gen.class_member_signeds[NestedStructName][mname] = None
MemberNode: CTypeInfo = CTypeInfo() MemberNode: CTypeInfo = CTypeInfo()
MemberNode.Name = VariantName MemberNode.Name = VariantName
MemberNode.BaseType = t.CEnum(ClassName) MemberNode.BaseType = TypeSystem.CEnum(ClassName)
MemberNode.value = tag_value MemberNode.value = tag_value
MemberNode.EnumName = ClassName MemberNode.EnumName = ClassName
MemberNode.Lineno = lineno MemberNode.Lineno = lineno
@@ -1814,9 +1699,9 @@ class ClassHandle(BaseHandle):
与 VPC 侧 ClassGenEnum._enum_member_annotation_is_ptr 同口径。枚举值是 与 VPC 侧 ClassGenEnum._enum_member_annotation_is_ptr 同口径。枚举值是
整数常量,指针成员语义不成立,必须明确报错(fail-fast)而非静默接受: 整数常量,指针成员语义不成立,必须明确报错(fail-fast)而非静默接受:
此前 TPC 完全忽略成员注解,`Name: t.CPtr` 会被当成普通 i32 成员放行。 `Name: CPtr` 不能被当成普通 i32 成员放行。
指针标记既按名字匹配(含 str/bytes = i8*、rawptr = t.CPtr),也按 指针标记既按名字匹配(含 str/bytes = i8*、rawptr = CPtr),也按
from t import CPtr as P 这类别名经 _t_type_symbols 还原后判定。 _builtin_type_symbols 中的内建类型符号判定。
""" """
if annotation is None: if annotation is None:
return False return False
@@ -1836,11 +1721,11 @@ class ClassHandle(BaseHandle):
return True return True
symtab: object = self.Trans.SymbolTable symtab: object = self.Trans.SymbolTable
resolved: type | None = None resolved: type | None = None
if hasattr(symtab, '_t_type_symbols'): if hasattr(symtab, '_builtin_type_symbols'):
resolved = symtab._t_type_symbols.get(name) resolved = symtab._builtin_type_symbols.get(name)
if resolved is None: if resolved is None:
resolved = getattr(t, name, None) resolved = getattr(TypeSystem, name, None)
if isinstance(resolved, type) and issubclass(resolved, t.CPtr): if isinstance(resolved, type) and issubclass(resolved, TypeSystem.CPtr):
return True return True
return False return False
@@ -1885,7 +1770,7 @@ class ClassHandle(BaseHandle):
EnumWidth: int = self._EnumClassIntWidth(Node) EnumWidth: int = self._EnumClassIntWidth(Node)
EnumTypeInfo: CTypeInfo = CTypeInfo() EnumTypeInfo: CTypeInfo = CTypeInfo()
EnumTypeInfo.Name = ClassName EnumTypeInfo.Name = ClassName
EnumTypeInfo.BaseType = t.CEnum(ClassName) EnumTypeInfo.BaseType = TypeSystem.CEnum(ClassName)
EnumTypeInfo.IsEnum = True EnumTypeInfo.IsEnum = True
EnumTypeInfo.set('enum_width', EnumWidth) EnumTypeInfo.set('enum_width', EnumWidth)
self.Trans.SymbolTable.insert(ClassName, EnumTypeInfo) self.Trans.SymbolTable.insert(ClassName, EnumTypeInfo)
@@ -1922,7 +1807,7 @@ class ClassHandle(BaseHandle):
next_enum_value += 1 next_enum_value += 1
MemberNode: CTypeInfo = CTypeInfo() MemberNode: CTypeInfo = CTypeInfo()
MemberNode.Name = VarName MemberNode.Name = VarName
MemberNode.BaseType = t.CEnum(ClassName) MemberNode.BaseType = TypeSystem.CEnum(ClassName)
MemberNode.value = value MemberNode.value = value
MemberNode.EnumName = ClassName MemberNode.EnumName = ClassName
MemberNode.Lineno = item.lineno MemberNode.Lineno = item.lineno
@@ -1938,7 +1823,7 @@ class ClassHandle(BaseHandle):
elif isinstance(item, ast.AnnAssign): elif isinstance(item, ast.AnnAssign):
if isinstance(item.target, ast.Name): if isinstance(item.target, ast.Name):
VarName = item.target.id VarName = item.target.id
# [枚举规格 fail-fast] 成员不允许指针类型(t.CPtr 家族 / # [枚举规格 fail-fast] 成员不允许指针类型(CPtr 家族 /
# rawptr[...] / str / bytes / 联合里夹带指针)——此前成员注解 # rawptr[...] / str / bytes / 联合里夹带指针)——此前成员注解
# 被整体忽略,指针成员被静默当 i32 放行。 # 被整体忽略,指针成员被静默当 i32 放行。
if self._EnumMemberAnnotationIsPtr(item.annotation): if self._EnumMemberAnnotationIsPtr(item.annotation):
@@ -1971,7 +1856,7 @@ class ClassHandle(BaseHandle):
next_enum_value += 1 next_enum_value += 1
MemberNode: CTypeInfo = CTypeInfo() MemberNode: CTypeInfo = CTypeInfo()
MemberNode.Name = VarName MemberNode.Name = VarName
MemberNode.BaseType = t.CEnum(ClassName) MemberNode.BaseType = TypeSystem.CEnum(ClassName)
MemberNode.value = value MemberNode.value = value
MemberNode.EnumName = ClassName MemberNode.EnumName = ClassName
MemberNode.Lineno = item.lineno MemberNode.Lineno = item.lineno
+2 -2
View File
@@ -17,7 +17,7 @@ class DeleteHandle(BaseHandle):
obj_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(target.value) obj_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(target.value)
idx_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(target.slice) idx_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(target.slice)
if obj_val and idx_val: if obj_val and idx_val:
# 处理 obj_val 为 i8(整数)的情况:联合类型 | t.CPtr 降级后可能被 load 为 i8 # 处理 obj_val 为 i8(整数)的情况:联合类型 | CPtr 降级后可能被 load 为 i8
if isinstance(obj_val.type, ir.IntType) and obj_val.type.width == 8: if isinstance(obj_val.type, ir.IntType) and obj_val.type.width == 8:
obj_val = Gen.builder.inttoptr(obj_val, ir.PointerType(ir.IntType(8)), name=f"i8_to_ptr_{ClassName}") obj_val = Gen.builder.inttoptr(obj_val, ir.PointerType(ir.IntType(8)), name=f"i8_to_ptr_{ClassName}")
if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8:
@@ -28,7 +28,7 @@ class DeleteHandle(BaseHandle):
if ClassName and Gen._has_function(f'{ClassName}.__delete__'): if ClassName and Gen._has_function(f'{ClassName}.__delete__'):
obj_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(target) obj_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(target)
if obj_val: if obj_val:
# 处理 obj_val 为 i8(整数)的情况:联合类型 | t.CPtr 降级后可能被 load 为 i8 # 处理 obj_val 为 i8(整数)的情况:联合类型 | CPtr 降级后可能被 load 为 i8
if isinstance(obj_val.type, ir.IntType) and obj_val.type.width == 8: if isinstance(obj_val.type, ir.IntType) and obj_val.type.width == 8:
obj_val = Gen.builder.inttoptr(obj_val, ir.PointerType(ir.IntType(8)), name=f"i8_to_ptr_{ClassName}") obj_val = Gen.builder.inttoptr(obj_val, ir.PointerType(ir.IntType(8)), name=f"i8_to_ptr_{ClassName}")
if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8:
+5 -5
View File
@@ -8,7 +8,7 @@ import re
import llvmlite.ir as ir import llvmlite.ir as ir
from lib.core.Handles.HandlesBase import BaseHandle from lib.core.Handles.HandlesBase import BaseHandle
from lib.constants.config import mode as _config_mode from lib.constants.config import mode as _config_mode
from lib.includes.t import CTypeRegistry as _CR from lib.core.TypeSystem import CTypeRegistry as _CR
from lib.core.SymbolUtils import (RequireDefineUseWidthAt, RequireIntLiteralStorable, RequireNameDefined, from lib.core.SymbolUtils import (RequireDefineUseWidthAt, RequireIntLiteralStorable, RequireNameDefined,
RequireExplicitWidthLiteral, RequireExplicitWidthLiteral,
DefineDeclTypeValue, GlobalDeclShadowsDefine) DefineDeclTypeValue, GlobalDeclShadowsDefine)
@@ -234,7 +234,7 @@ class ExprHandle(BaseHandle):
from lib.core.LLVMCG.FuncGen import FailFastError from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError( raise FailFastError(
f"指针隐式转整数已禁止:数组字面量第 {i} 个元素是指针类型 {elem_val.type}," f"指针隐式转整数已禁止:数组字面量第 {i} 个元素是指针类型 {elem_val.type},"
f"但目标元素类型是 i8;如需转换请显式 cast(如 t.CUInt64T(p) / t.CInt(p))" f"但目标元素类型是 i8;如需转换请显式 cast(如 CUInt64T(p) / CInt(p))"
f"{Gen._DescribeValueNode(elem)}" f"{Gen._DescribeValueNode(elem)}"
) )
elif elem_type == 'i32': elif elem_type == 'i32':
@@ -249,7 +249,7 @@ class ExprHandle(BaseHandle):
from lib.core.LLVMCG.FuncGen import FailFastError from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError( raise FailFastError(
f"指针隐式转整数已禁止:数组字面量第 {i} 个元素是指针类型 {elem_val.type}," f"指针隐式转整数已禁止:数组字面量第 {i} 个元素是指针类型 {elem_val.type},"
f"但目标元素类型是 i32;如需转换请显式 cast(如 t.CUInt64T(p) / t.CInt(p))" f"但目标元素类型是 i32;如需转换请显式 cast(如 CUInt64T(p) / CInt(p))"
f"{Gen._DescribeValueNode(elem)}" f"{Gen._DescribeValueNode(elem)}"
) )
elif elem_type == 'i16': elif elem_type == 'i16':
@@ -415,7 +415,7 @@ class ExprHandle(BaseHandle):
Gen: LlvmCodeGenerator = self.Trans.LlvmGen Gen: LlvmCodeGenerator = self.Trans.LlvmGen
VarName: str = Node.id VarName: str = Node.id
# 治本修复:不把 module.globals 的 initializer 注入 _define_constants。 # 治本修复:不把 module.globals 的 initializer 注入 _define_constants。
# 原因:CDefine(t.CDefine 注解)在 AnnAssign/Assign 处理时已注册到 # 原因:CDefine(CDefine 注解)在 AnnAssign/Assign 处理时已注册到
# _define_constants 且不创建 LLVM global(不在 module.globals); # _define_constants 且不创建 LLVM global(不在 module.globals);
# module.globals 里全是可变全局变量(如 _sha1_store_count,有 += 写入), # module.globals 里全是可变全局变量(如 _sha1_store_count,有 += 写入),
# 若把其 initializer 当常量传播,会导致 range(_sha1_store_count) 被求值成 # 若把其 initializer 当常量传播,会导致 range(_sha1_store_count) 被求值成
@@ -604,7 +604,7 @@ class ExprHandle(BaseHandle):
if isinstance(g, ir.Function): if isinstance(g, ir.Function):
Gen.functions[VarName] = g Gen.functions[VarName] = g
return Gen.builder.bitcast(g, ir.IntType(8).as_pointer(), name=f"funcptr_{VarName}") return Gen.builder.bitcast(g, ir.IntType(8).as_pointer(), name=f"funcptr_{VarName}")
t_c_imported: dict[str, tuple[str, str]] = getattr(self.Trans, '_t_c_imported_names', {}) t_c_imported: dict[str, tuple[str, str]] = getattr(self.Trans, '_from_import_aliases', {})
if VarName in t_c_imported: if VarName in t_c_imported:
src_module: str src_module: str
src_name: str src_name: str
+14 -25
View File
@@ -7,8 +7,7 @@ if TYPE_CHECKING:
from lib.core.translator import Translator from lib.core.translator import Translator
from lib.core.LlvmCodeGenerator import LlvmCodeGenerator from lib.core.LlvmCodeGenerator import LlvmCodeGenerator
from lib.core.Handles.HandlesBase import BaseHandle from lib.core.Handles.HandlesBase import BaseHandle
from lib.core.SymbolUtils import IsTModule from lib.core import TypeSystem
from lib.includes import t
# --------------------------------------------------------------- # ---------------------------------------------------------------
# asm 模板重写用的正则**预编译**(性能:避免每次 `re.sub(字面量, ...)` 都要做 # asm 模板重写用的正则**预编译**(性能:避免每次 `re.sub(字面量, ...)` 都要做
@@ -212,14 +211,16 @@ class ExprAsmHandle(BaseHandle):
def _intrinsic_marker(expr: ast.AST) -> str | None: def _intrinsic_marker(expr: ast.AST) -> str | None:
"""识别内建操作数标记调用,返回规范名或 None """识别内建操作数标记调用,返回规范名或 None
支持两种等价写法(裸名写法省去 c. 前缀): 规范名为裸名写法:
- 内联汇编:c.AsmInp / c.AsmOut ↔ asminp / asmout - 内联汇编:AsmInp / AsmOut(小写 asminp / asmout 等价)
- LLVM IR:c.LInp / c.LOut ↔ irinp / irout - LLVM IR:LInp / LOut(小写 irinp / irout 等价)
""" """
if not isinstance(expr, ast.Call): if not isinstance(expr, ast.Call):
return None return None
func: ast.AST = expr.func func: ast.AST = expr.func
if isinstance(func, ast.Name): if isinstance(func, ast.Name):
if func.id in ('AsmInp', 'AsmOut', 'LInp', 'LOut'):
return func.id
if func.id == 'asminp': if func.id == 'asminp':
return 'AsmInp' return 'AsmInp'
if func.id == 'asmout': if func.id == 'asmout':
@@ -229,11 +230,6 @@ class ExprAsmHandle(BaseHandle):
if func.id == 'irout': if func.id == 'irout':
return 'LOut' return 'LOut'
return None return None
if isinstance(func, ast.Attribute):
if isinstance(func.value, ast.Name) and func.value.id == 'c':
if func.attr in ('AsmInp', 'AsmOut', 'LInp', 'LOut'):
return func.attr
return None
return None return None
def _process_joined_str_template(self, node: ast.AST, out_input_ops: list[Any], out_input_constraints: list[str], def _process_joined_str_template(self, node: ast.AST, out_input_ops: list[Any], out_input_constraints: list[str],
@@ -281,8 +277,7 @@ class ExprAsmHandle(BaseHandle):
out_output_constraints.append(c) out_output_constraints.append(c)
raw_parts.append(('output', len(out_output_ops) - 1)) raw_parts.append(('output', len(out_output_ops) - 1))
elif not (isinstance(expr, ast.Call) and isinstance(expr.func, ast.Attribute)): elif not (isinstance(expr, ast.Call) and isinstance(expr.func, ast.Attribute)):
# 非 c.* 属性调用的表达式按普通输入操作数处理(保持原行为: # 非标记的属性调用不收集,其余表达式按普通输入操作数处理
# c.* 属性调用中非 AsmInp/AsmOut 的形态不收集)
fallback: Any = self.HandleExprLlvm(expr) fallback: Any = self.HandleExprLlvm(expr)
if fallback and isinstance(fallback.type, ir.IntType): if fallback and isinstance(fallback.type, ir.IntType):
out_input_ops.append(fallback) out_input_ops.append(fallback)
@@ -583,16 +578,10 @@ class ExprAsmHandle(BaseHandle):
return left_val + right_val return left_val + right_val
elif isinstance(expr, ast.Attribute): elif isinstance(expr, ast.Attribute):
if isinstance(expr.value, ast.Attribute): if isinstance(expr.value, ast.Name) and expr.value.id == 'ASM_DESCR':
if (isinstance(expr.value.value, ast.Name) and # 裸名 ASM_DESCR.XXX
IsTModule(expr.value.value.id, self.Trans.SymbolTable) and
expr.value.attr == 'ASM_DESCR'):
AttrName: str = expr.attr
return getattr(t.ASM_DESCR, AttrName, "")
elif isinstance(expr.value, ast.Name) and (expr.value.id == 'ASM_DESCR' or IsTModule(expr.value.id, self.Trans.SymbolTable)):
# 裸名 ASM_DESCR.XXX:省去 t. 前缀的等价写法
AttrName: str = expr.attr AttrName: str = expr.attr
return getattr(t.ASM_DESCR, AttrName, "") return getattr(TypeSystem.ASM_DESCR, AttrName, "")
elif isinstance(expr, ast.Constant): elif isinstance(expr, ast.Constant):
return expr.value return expr.value
@@ -602,9 +591,9 @@ class ExprAsmHandle(BaseHandle):
def _infer_expr_llvm_type(self, expr: ast.AST) -> ir.Type | None: def _infer_expr_llvm_type(self, expr: ast.AST) -> ir.Type | None:
if isinstance(expr, ast.Name): if isinstance(expr, ast.Name):
type_name: str = expr.id type_name: str = expr.id
if hasattr(t, type_name): if hasattr(TypeSystem, type_name):
ctype: Any = getattr(t, type_name) ctype: Any = getattr(TypeSystem, type_name)
if isinstance(ctype, type) and issubclass(ctype, t.CType): if isinstance(ctype, type) and issubclass(ctype, TypeSystem.CType):
size: Any = getattr(ctype, 'Size', None) size: Any = getattr(ctype, 'Size', None)
if size is not None: if size is not None:
return ir.IntType(size) return ir.IntType(size)
@@ -613,6 +602,6 @@ class ExprAsmHandle(BaseHandle):
elif type_name == 'CDouble': elif type_name == 'CDouble':
return ir.DoubleType() return ir.DoubleType()
elif isinstance(expr, ast.Attribute): elif isinstance(expr, ast.Attribute):
if isinstance(expr.value, ast.Name) and IsTModule(expr.value.id, self.Trans.SymbolTable): if isinstance(expr.value, ast.Name) :
return self._infer_expr_llvm_type(ast.Name(id=expr.attr, ctx=ast.Load())) return self._infer_expr_llvm_type(ast.Name(id=expr.attr, ctx=ast.Load()))
return None return None
+23 -25
View File
@@ -459,8 +459,8 @@ class ExprAttrHandle(BaseHandle):
"""模块限定全局读取归一化:类指针全局的「多一层」元素类型还原为对象指针 """模块限定全局读取归一化:类指针全局的「多一层」元素类型还原为对象指针
`Mod.g`(g 为模块级全局)的取值统一经 _lookup_module_global:注解为 `Mod.g`(g 为模块级全局)的取值统一经 _lookup_module_global:注解为
`X | t.CPtr` 的模块级全局(如 GenApi._g_gen: rawptr[Generator.Generator]、 `X | CPtr` 的模块级全局(如 GenApi._g_gen: rawptr[Generator.Generator]、
VLogger.logger: Logger | t.CPtr)在本编译器里物化成「比对象多一层」的 VLogger.logger: Logger | CPtr)在本编译器里物化成「比对象多一层」的
元素类型 T**(写入端见 main.vp `GenApi._g_gen = gen`:bitcast T*→T** 后 元素类型 T**(写入端见 main.vp `GenApi._g_gen = gen`:bitcast T*→T** 后
直接存值,未取地址)⇒ 其位形就是对象指针 T*,静态类型多了一层。 直接存值,未取地址)⇒ 其位形就是对象指针 T*,静态类型多了一层。
裸名形态(`g.Field`)由 _handle_attr_name 的既有同款补偿 bitcast 处理; 裸名形态(`g.Field`)由 _handle_attr_name 的既有同款补偿 bitcast 处理;
@@ -471,7 +471,7 @@ class ExprAttrHandle(BaseHandle):
调用接收者 None 而静默丢调用(VpiReader.vp:4066 调用接收者 None 而静默丢调用(VpiReader.vp:4066
`GenApi._g_gen.ClassGenBase._collect_parents(...)`)。此处做同款逆运算: `GenApi._g_gen.ClassGenBase._collect_parents(...)`)。此处做同款逆运算:
只改静态类型、不改位形(bitcast 不产指令)。 只改静态类型、不改位形(bitcast 不产指令)。
判据限定「pointee 仍是指向结构体的指针」⇒ `str | t.CPtr` 一类真双层指针 判据限定「pointee 仍是指向结构体的指针」⇒ `str | CPtr` 一类真双层指针
全局(@_argv / @_g_pyi_cdef_names = i8**,实参直传 i8** 形参)不受影响。 全局(@_argv / @_g_pyi_cdef_names = i8**,实参直传 i8** 形参)不受影响。
""" """
if not isinstance(Val, ir.Value) or not isinstance(Val.type, ir.PointerType): if not isinstance(Val, ir.Value) or not isinstance(Val.type, ir.PointerType):
@@ -1283,13 +1283,11 @@ class ExprAttrHandle(BaseHandle):
def _handle_attr_call_result(self, Node: ast.Attribute) -> ir.Value | None: def _handle_attr_call_result(self, Node: ast.Attribute) -> ir.Value | None:
"""处理 func().attr 属性访问""" """处理 func().attr 属性访问"""
Gen: LlvmCodeGenerator = self.Trans.LlvmGen Gen: LlvmCodeGenerator = self.Trans.LlvmGen
# Check if this is c.Deref(...) — we need the pointer, not the Loaded value # Check if this is Deref(...) — we need the pointer, not the Loaded value
ObjVal: Any = None ObjVal: Any = None
is_cderef: bool = (isinstance(Node.value, ast.Call) and is_cderef: bool = (isinstance(Node.value, ast.Call) and
isinstance(Node.value.func, ast.Attribute) and isinstance(Node.value.func, ast.Name) and
isinstance(Node.value.func.value, ast.Name) and Node.value.func.id == 'Deref' and
Node.value.func.value.id == 'c' and
Node.value.func.attr == 'Deref' and
Node.value.args) Node.value.args)
if is_cderef: if is_cderef:
deref_arg: ast.expr = Node.value.args[0] deref_arg: ast.expr = Node.value.args[0]
@@ -1301,15 +1299,15 @@ class ExprAttrHandle(BaseHandle):
ObjVal = inner_val ObjVal = inner_val
if ObjVal is None: if ObjVal is None:
ObjVal = self.HandleExprLlvm(Node.value) ObjVal = self.HandleExprLlvm(Node.value)
# 联合类型转换 (X | t.CPtr)(arg) 的属性访问(治本修复): # 联合类型转换 (X | CPtr)(arg) 的属性访问(治本修复):
# TPC 联合转换对非 CType 类(如 ast.Name / ast.Call)目标类型解析失败, # TPC 联合转换对非 CType 类(如 ast.Name / ast.Call)目标类型解析失败,
# 结果可能退回 Ptr(i8) 或错误类型,导致下方 find_struct_by_pointee 失败、 # 结果可能退回 Ptr(i8) 或错误类型,导致下方 find_struct_by_pointee 失败、
# 属性访问被静默丢弃——((ast.Name|t.CPtr)(ov)).id 编译后 store 0 次 # 属性访问被静默丢弃——((ast.Name|CPtr)(ov)).id 编译后 store 0 次
# (with 语句 asname 未绑定、pool 未定义根因)。从联合 BinOp 提取真实 # (with 语句 asname 未绑定、pool 未定义根因)。从联合 BinOp 提取真实
# 基础类并 bitcast 到 Ptr(类) 再访问成员。 # 基础类并 bitcast 到 Ptr(类) 再访问成员。
# #
# 该形态的每个 return None 都改成 fail-fast(见 _FailFastAttrCallBase): # 该形态的每个 return None 都改成 fail-fast(见 _FailFastAttrCallBase):
# `(T | t.CPtr)(x)` 只可能来自指针强转(parser 把 `(T*)x` / `T*(x)` 统一 # `(T | CPtr)(x)` 只可能来自指针强转(parser 把 `(T*)x` / `T*(x)` 统一
# 产成该 Call),返回 None 会让调用方只报"表达式编译期求值为空",看不出是 # 产成该 Call),返回 None 会让调用方只报"表达式编译期求值为空",看不出是
# 类名没被当成类、结构体不透明、还是成员偏移取不到(现场:ViperC # 类名没被当成类、结构体不透明、还是成员偏移取不到(现场:ViperC
# ExprGenBase.vp:360 `v = (ast.Expr*(node)).value`,而同一函数前三条 # ExprGenBase.vp:360 `v = (ast.Expr*(node)).value`,而同一函数前三条
@@ -1370,9 +1368,9 @@ class ExprAttrHandle(BaseHandle):
def _FailFastAttrCallBase(self, Stage: str, Node: ast.Attribute, Gen: Any, def _FailFastAttrCallBase(self, Stage: str, Node: ast.Attribute, Gen: Any,
IsUnionCastBase: bool, UnionCls: str | None, IsUnionCastBase: bool, UnionCls: str | None,
ObjVal: Any) -> None: ObjVal: Any) -> None:
"""`(T | t.CPtr)(x).attr` 属性访问失败时的 fail-fast(非该形态时静默返回,行为不变)。 """`(T | CPtr)(x).attr` 属性访问失败时的 fail-fast(非该形态时静默返回,行为不变)。
`(T | t.CPtr)(x)` 只可能来自指针强转(parser 把 `(T*)x` / `(T*)(x)` / `T*(x)` `(T | CPtr)(x)` 只可能来自指针强转(parser 把 `(T*)x` / `(T*)(x)` / `T*(x)`
统一产成该 Call),其属性访问必须有值产出。此前一律 `return None`,调用方只能 统一产成该 Call),其属性访问必须有值产出。此前一律 `return None`,调用方只能
报"赋值表达式 'value'(Attribute 形态)编译期求值为空",把"类名没被当成类 / 报"赋值表达式 'value'(Attribute 形态)编译期求值为空",把"类名没被当成类 /
结构体不透明 / 成员偏移取不到"三种完全不同的根因混成一条报文 结构体不透明 / 成员偏移取不到"三种完全不同的根因混成一条报文
@@ -1427,10 +1425,10 @@ class ExprAttrHandle(BaseHandle):
return f"<查询异常 {type(_E).__name__}: {_E}>" return f"<查询异常 {type(_E).__name__}: {_E}>"
def _extract_union_base_class(self, NodeFunc: ast.BinOp) -> str | None: def _extract_union_base_class(self, NodeFunc: ast.BinOp) -> str | None:
"""从 (X | t.CPtr) 联合 BinOp 提取第一个非指针/非修饰符的类名 """从 (X | CPtr) 联合 BinOp 提取第一个非指针/非修饰符的类名
X 可以是任意类(如 ast.Name / ast.Call / memhub.MemPool),不限于 X 可以是任意类(如 ast.Name / ast.Call / memhub.MemPool),不限于
t.CType 子类——联合转换 (X | t.CPtr)(arg) 的属性访问需要真实类名 CType 子类——联合转换 (X | CPtr)(arg) 的属性访问需要真实类名
才能 bitcast 到 Ptr(类) 并定位成员偏移。 才能 bitcast 到 Ptr(类) 并定位成员偏移。
""" """
if not isinstance(NodeFunc, ast.BinOp) or not isinstance(NodeFunc.op, ast.BitOr): if not isinstance(NodeFunc, ast.BinOp) or not isinstance(NodeFunc.op, ast.BitOr):
@@ -1528,7 +1526,7 @@ class ExprAttrHandle(BaseHandle):
if isinstance(Node.value, ast.Name): if isinstance(Node.value, ast.Name):
VarName: str = Node.value.id VarName: str = Node.value.id
# 处理 t/c import 的别名重定向 # 处理 t/c import 的别名重定向
t_c_imported: Any = getattr(self.Trans, '_t_c_imported_names', {}) t_c_imported: Any = getattr(self.Trans, '_from_import_aliases', {})
if VarName != 'self' and VarName in t_c_imported: if VarName != 'self' and VarName in t_c_imported:
src_module: str src_module: str
src_name: str src_name: str
@@ -1561,7 +1559,7 @@ class ExprAttrHandle(BaseHandle):
def _HandleSubscriptLlvm(self, Node: ast.Subscript) -> ir.Value | None: def _HandleSubscriptLlvm(self, Node: ast.Subscript) -> ir.Value | None:
Gen: LlvmCodeGenerator = self.Trans.LlvmGen Gen: LlvmCodeGenerator = self.Trans.LlvmGen
# pointee-volatile(rawptr[t.CVolatile | T])基址:下标 GEP 名带基址名, # pointee-volatile(rawptr[CVolatile | T])基址:下标 GEP 名带基址名,
# 顶层 _load/_store 经 BaseGen._IsPtrVolatile 回查登记名,使其 load/store # 顶层 _load/_store 经 BaseGen._IsPtrVolatile 回查登记名,使其 load/store
# 带 LLVM volatile。基址名取不到时后缀为空 ⇒ GEP 名仍是 "subscript", # 带 LLVM volatile。基址名取不到时后缀为空 ⇒ GEP 名仍是 "subscript",
# 既有代码 IR 逐字节不变。 # 既有代码 IR 逐字节不变。
@@ -1575,7 +1573,7 @@ class ExprAttrHandle(BaseHandle):
obj_val: Any = self.HandleExprLlvm(Node.value) obj_val: Any = self.HandleExprLlvm(Node.value)
idx_val: Any = self.HandleExprLlvm(Node.slice) idx_val: Any = self.HandleExprLlvm(Node.slice)
if obj_val and idx_val: if obj_val and idx_val:
# 处理 obj_val 为 i8(整数)的情况:联合类型 | t.CPtr 降级后可能被 load 为 i8 # 处理 obj_val 为 i8(整数)的情况:联合类型 | CPtr 降级后可能被 load 为 i8
# 需要先 inttoptr 转换为 i8*,再 bitcast 到目标 struct 指针 # 需要先 inttoptr 转换为 i8*,再 bitcast 到目标 struct 指针
if isinstance(obj_val.type, ir.IntType) and obj_val.type.width == 8: if isinstance(obj_val.type, ir.IntType) and obj_val.type.width == 8:
obj_val = Gen.builder.inttoptr(obj_val, ir.PointerType(ir.IntType(8)), name=f"i8_to_ptr_{ClassName}") obj_val = Gen.builder.inttoptr(obj_val, ir.PointerType(ir.IntType(8)), name=f"i8_to_ptr_{ClassName}")
@@ -1609,13 +1607,13 @@ class ExprAttrHandle(BaseHandle):
ptr: Any = Gen.builder.gep(i8_ptr, [IndexVal], name="int_subscript_ptr") ptr: Any = Gen.builder.gep(i8_ptr, [IndexVal], name="int_subscript_ptr")
return Gen._load(ptr, name="int_subscript_val") return Gen._load(ptr, name="int_subscript_val")
return None return None
# 当变量本身是二级指针(如 elem_ptr: T | t.CPtr = AST**), # 当变量本身是二级指针(如 elem_ptr: T | CPtr = AST**),
# 但 HandleExprLlvm 已自动 load 返回 AST*(一级指针), # 但 HandleExprLlvm 已自动 load 返回 AST*(一级指针),
# 需要检查 Gen.variables 中的原始 alloca 类型, # 需要检查 Gen.variables 中的原始 alloca 类型,
# 若是二级指针且存储的是结构体指针,应 bitcast ValueVal 为 AST** 后 GEP 再 load, # 若是二级指针且存储的是结构体指针,应 bitcast ValueVal 为 AST** 后 GEP 再 load,
# 避免 GEP AST 结构体数组返回错误的 AST*(指向存储位置而非实际对象)。 # 避免 GEP AST 结构体数组返回错误的 AST*(指向存储位置而非实际对象)。
# 仅当 var_ptr_element 标记为 True 时触发(由 AnnAssign 检测 (S|t.CPtr)|t.CPtr 注解设置), # 仅当 var_ptr_element 标记为 True 时触发(由 AnnAssign 检测 (S|CPtr)|CPtr 注解设置),
# 防止 pts: Point | t.CPtr(简单结构体指针)错误走二级指针路径。 # 防止 pts: Point | CPtr(简单结构体指针)错误走二级指针路径。
if (isinstance(Node.value, ast.Name) if (isinstance(Node.value, ast.Name)
and isinstance(ValueVal.type, ir.PointerType) and isinstance(ValueVal.type, ir.PointerType)
and isinstance(ValueVal.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType))): and isinstance(ValueVal.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType))):
@@ -1659,7 +1657,7 @@ class ExprAttrHandle(BaseHandle):
return self._load_arr_elem_with_bswap(Gen, ElemPtr, arr_byte_order) return self._load_arr_elem_with_bswap(Gen, ElemPtr, arr_byte_order)
else: else:
if isinstance(pointee, ir.IntType) and pointee.width == 8: if isinstance(pointee, ir.IntType) and pointee.width == 8:
# 指针槽变量优先(8fbba 修复):T|t.CPtr 指针槽(elem_ptr 指向 # 指针槽变量优先(8fbba 修复):T|CPtr 指针槽(elem_ptr 指向
# 8 字节指针数组,如 _list.vp 泛型方法体)→ i8** load i8*。 # 8 字节指针数组,如 _list.vp 泛型方法体)→ i8** load i8*。
# 必须放在 _infer_element_struct_class 之前——泛型 T 未解析时 # 必须放在 _infer_element_struct_class 之前——泛型 T 未解析时
# var_struct_class 误注册 llvmlite.Value,若先推断 elem_class # var_struct_class 误注册 llvmlite.Value,若先推断 elem_class
@@ -1682,7 +1680,7 @@ class ExprAttrHandle(BaseHandle):
if isinstance(pointee, ir.IntType): if isinstance(pointee, ir.IntType):
return self._load_arr_elem_with_bswap(Gen, ElemPtr, arr_byte_order) return self._load_arr_elem_with_bswap(Gen, ElemPtr, arr_byte_order)
return ElemPtr return ElemPtr
# 指针到 str/bytes 的变量 (BinOp 注解如 str | t.CPtr) # 指针到 str/bytes 的变量 (BinOp 注解如 str | CPtr)
# elem_ptr 是 i8* 但实际指向 i8* (字符串指针), elem_ptr[0] 应加载 8 字节 # elem_ptr 是 i8* 但实际指向 i8* (字符串指针), elem_ptr[0] 应加载 8 字节
if isinstance(Node.value, ast.Name): if isinstance(Node.value, ast.Name):
_ptr_elem_flag = (getattr(Gen, 'var_ptr_element', {}).get(Node.value.id, False) _ptr_elem_flag = (getattr(Gen, 'var_ptr_element', {}).get(Node.value.id, False)
@@ -1795,7 +1793,7 @@ class ExprAttrHandle(BaseHandle):
ElemPtr = Gen.builder.gep(ValueVal, [IndexVal], name=f"subscript_ptr{_PVSuffix}") ElemPtr = Gen.builder.gep(ValueVal, [IndexVal], name=f"subscript_ptr{_PVSuffix}")
return ElemPtr return ElemPtr
else: else:
# 指针到 str/bytes 的变量 (BinOp 注解如 str | t.CPtr, bytes | t.CPtr) # 指针到 str/bytes 的变量 (BinOp 注解如 str | CPtr, bytes | CPtr)
# elem_ptr 是 i8* 但实际指向 i8* (指针数组), 应按 8 字节步长 GEP # elem_ptr 是 i8* 但实际指向 i8* (指针数组), 应按 8 字节步长 GEP
if isinstance(Node.value, ast.Name): if isinstance(Node.value, ast.Name):
_ptr_elem_flag: bool = (getattr(Gen, 'var_ptr_element', {}).get(Node.value.id, False) _ptr_elem_flag: bool = (getattr(Gen, 'var_ptr_element', {}).get(Node.value.id, False)
@@ -2015,7 +2013,7 @@ class ExprAttrHandle(BaseHandle):
return MemberPtr return MemberPtr
elif isinstance(Node.value, ast.Call): elif isinstance(Node.value, ast.Call):
# 指针强转基座(`(ast.Call*(vinner)).IsVolatile = 1`):`T*(x)` 被 vast 的 # 指针强转基座(`(ast.Call*(vinner)).IsVolatile = 1`):`T*(x)` 被 vast 的
# _ConsumePtrSuffixCall 解析为 `(T | t.CPtr)(x)` 强转调用,结果类型是联合 # _ConsumePtrSuffixCall 解析为 `(T | CPtr)(x)` 强转调用,结果类型是联合
# 简化后的 i8*(struct 身份丢失),故须从强转注解(func 是 BitOr 联合) # 简化后的 i8*(struct 身份丢失),故须从强转注解(func 是 BitOr 联合)
# 提真实类名,bitcast/inttoptr 回 Ptr(类) 后 GEP 成员。 # 提真实类名,bitcast/inttoptr 回 Ptr(类) 后 GEP 成员。
# 与读取侧 _handle_attr_call_result 的联合分支(_extract_union_base_class) # 与读取侧 _handle_attr_call_result 的联合分支(_extract_union_base_class)
+15 -29
View File
@@ -8,17 +8,14 @@ import llvmlite.ir as ir
from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo
from lib.core.VLogger import get_logger as _vlog from lib.core.VLogger import get_logger as _vlog
from lib.constants.config import mode as _config_mode from lib.constants.config import mode as _config_mode
from lib.includes.t import CTypeRegistry from lib.core.TypeSystem import CTypeRegistry
from lib.includes import t as _t from lib.core import TypeSystem as _t
from lib.core.SymbolUtils import IsTModule
# len() 参数形态不支持时的共享提示语(与 ViperC App/lib/core/Gen/Call/ # len() 参数形态不支持时的共享提示语(与 ViperC App/lib/core/Gen/Call/
# CallGenDispatch.vp 的 len() 分支同口径,措辞逐字一致,便于用户对照两侧报文)。 # CallGenDispatch.vp 的 len() 分支同口径,措辞逐字一致,便于用户对照两侧报文)。
_LEN_SUPPORTED_HINT: str = ( _LEN_SUPPORTED_HINT: str = (
"len() 只支持定长数组/数组指针(t.CArray[T, N])、i8*(str/bytes)或带 __len__ 的结构体;" "len() 只支持定长数组/数组指针(CArray[T, N])、i8*(str/bytes)或带 __len__ 的结构体;"
"非 i8 裸指针/标量指针没有长度语义:字符串请用 str/bytes,需要元素个数请自行记录长度," "非 i8 裸指针/标量指针没有长度语义:字符串请用 str/bytes,需要元素个数请自行记录长度,"
"或改用 t.CPtr[元素] 并显式维护元素计数" "或改用 CPtr[元素] 并显式维护元素计数"
) )
@@ -48,9 +45,9 @@ class ExprBuiltinHandle(BaseHandle):
return None return None
FuncName: str = Node.func.id FuncName: str = Node.func.id
# Two-arg scalar alias form (int(v, t.CPtr) / char / bool / float / double) # Two-arg scalar alias form (int(v, CPtr) / char / bool / float / double)
# is a pointer wrap, not a scalar cast: route it to the same exit as the # is a pointer wrap, not a scalar cast: route it to the same exit as the
# attribute form t.CInt(v, t.CPtr). Ignoring the CPtr mark would degrade # attribute form CInt(v, CPtr). Ignoring the CPtr mark would degrade
# it to a bare trunc, e.g. includes/argparse.vp get_bool() reading a # it to a bare trunc, e.g. includes/argparse.vp get_bool() reading a
# pointer's low 32 bits instead of the stored value. # pointer's low 32 bits instead of the stored value.
if (len(Node.args) >= 2 and FuncName in ('int', 'char', 'bool', 'float', 'double') if (len(Node.args) >= 2 and FuncName in ('int', 'char', 'bool', 'float', 'double')
@@ -106,7 +103,7 @@ class ExprBuiltinHandle(BaseHandle):
return ir.Constant(ir.IntType(32), 0) return ir.Constant(ir.IntType(32), 0)
elif FuncName == 'char': elif FuncName == 'char':
# char(x) → i8(与 int()/bool()/float()/double() 并列的内建标量强转; # char(x) → i8(与 int()/bool()/float()/double() 并列的内建标量强转;
# char = t.CChar = i8) # char = CChar = i8)
if Node.args: if Node.args:
Val = self.HandleExprLlvm(Node.args[0]) Val = self.HandleExprLlvm(Node.args[0])
if Val: if Val:
@@ -184,7 +181,7 @@ class ExprBuiltinHandle(BaseHandle):
str_val = Gen.builder.call(Gen._get_function(f'{ClassName}.__str__'), [arg_val], name=f"call_{ClassName}.__str__") str_val = Gen.builder.call(Gen._get_function(f'{ClassName}.__str__'), [arg_val], name=f"call_{ClassName}.__str__")
return str_val return str_val
return arg_val return arg_val
# str 是类型名(= t.CChar* = i8*),str(x) ≡ (str)(x) 类型转换: # str 是类型名(= CChar* = i8*),str(x) ≡ (str)(x) 类型转换:
# 整型(u64/sizet 地址、char 码)→ inttoptr,与 VPC # 整型(u64/sizet 地址、char 码)→ inttoptr,与 VPC
# CallGenDispatch._tc_h3_stdarg_cast 的 str 分支同语义 # CallGenDispatch._tc_h3_stdarg_cast 的 str 分支同语义
# (CallGenCtor._translate_t_type_cast 的「整数 → 指针: inttoptr」)。 # (CallGenCtor._translate_t_type_cast 的「整数 → 指针: inttoptr」)。
@@ -194,7 +191,7 @@ class ExprBuiltinHandle(BaseHandle):
return Gen.builder.inttoptr(arg_val, ir.IntType(8).as_pointer(), name="str_int2ptr") return Gen.builder.inttoptr(arg_val, ir.IntType(8).as_pointer(), name="str_int2ptr")
return ir.Constant(ir.IntType(8).as_pointer(), None) return ir.Constant(ir.IntType(8).as_pointer(), None)
elif FuncName == 'bytes': elif FuncName == 'bytes':
# bytes() — 类型转换为 i8* 指针 (等同于 t.CPtr / str) # bytes() — 类型转换为 i8* 指针 (等同于 CPtr / str)
# bytes(int_addr) → inttoptr; bytes(ptr) → bitcast # bytes(int_addr) → inttoptr; bytes(ptr) → bitcast
if Node.args: if Node.args:
arg_val = self.HandleExprLlvm(Node.args[0]) arg_val = self.HandleExprLlvm(Node.args[0])
@@ -366,7 +363,7 @@ class ExprBuiltinHandle(BaseHandle):
"""运行时:读对象头部 vtable 指针,与集合中每个 vtable 地址比较""" """运行时:读对象头部 vtable 指针,与集合中每个 vtable 地址比较"""
ObjPtr: ir.Value = ObjVal ObjPtr: ir.Value = ObjVal
if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType):
# 二级指针(变量 alloca / 联合 Class|t.CPtr)→ 先 load 出对象指针 # 二级指针(变量 alloca / 联合 Class|CPtr)→ 先 load 出对象指针
ObjPtr = Gen._load(ObjVal, name="isinstance_load") ObjPtr = Gen._load(ObjVal, name="isinstance_load")
if not isinstance(ObjPtr.type, ir.PointerType): if not isinstance(ObjPtr.type, ir.PointerType):
return self._IsinstanceCompileTime(Gen, ObjVal, '') return self._IsinstanceCompileTime(Gen, ObjVal, '')
@@ -562,8 +559,6 @@ class ExprBuiltinHandle(BaseHandle):
if isinstance(arg_node, ast.Call): if isinstance(arg_node, ast.Call):
if isinstance(arg_node.func, ast.Name): if isinstance(arg_node.func, ast.Name):
return arg_node.func.id in ('CChar', 'CUInt8T', 'CInt8T') return arg_node.func.id in ('CChar', 'CUInt8T', 'CInt8T')
if isinstance(arg_node.func, ast.Attribute):
return arg_node.func.attr in ('CChar', 'CUInt8T', 'CInt8T')
return False return False
def _is_val_unsigned(self, arg_node: ast.AST, val: ir.Value) -> bool: def _is_val_unsigned(self, arg_node: ast.AST, val: ir.Value) -> bool:
@@ -667,7 +662,7 @@ class ExprBuiltinHandle(BaseHandle):
offset = Gen._get_member_offset(len_member, bare_cls, _STl) offset = Gen._get_member_offset(len_member, bare_cls, _STl)
len_ptr = Gen.builder.gep(self_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=f"{obj_name}_{len_member}_ptr") len_ptr = Gen.builder.gep(self_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=f"{obj_name}_{len_member}_ptr")
return Gen._load(len_ptr, name=f"{obj_name}_{len_member}") return Gen._load(len_ptr, name=f"{obj_name}_{len_member}")
# 修复 stdint.vp 崩溃(0xC0000005)根因:`list[X] | t.CPtr` 联合字段 # 修复 stdint.vp 崩溃(0xC0000005)根因:`list[X] | CPtr` 联合字段
# 的 LLVM 类型退化为 i8*,_HandleLenLlvm 无法识别为 list,fall through # 的 LLVM 类型退化为 i8*,_HandleLenLlvm 无法识别为 list,fall through
# 到 strlen 分支 → 对 list 对象指针执行 strlen → 垃圾长度 → 越界 get # 到 strlen 分支 → 对 list 对象指针执行 strlen → 垃圾长度 → 越界 get
# → 垃圾指针 → strcmp 崩。此处按字段静态类型(class_member_element_class # → 垃圾指针 → strcmp 崩。此处按字段静态类型(class_member_element_class
@@ -818,7 +813,7 @@ class ExprBuiltinHandle(BaseHandle):
elif isinstance(Node, ast.Attribute): elif isinstance(Node, ast.Attribute):
type_name = Node.attr type_name = Node.attr
else: else:
# 非 名称/属性 的 sizeof 目标(如 sizeof(a + b)、sizeof(t.CArray[int,4])): # 非 名称/属性 的 sizeof 目标(如 sizeof(a + b)、sizeof(CArray[int,4])):
# 曾静默返回 0 → 下游 alloc(0) 返回 NULL。fail-fast。 # 曾静默返回 0 → 下游 alloc(0) 返回 NULL。fail-fast。
raise ValueError( raise ValueError(
f"[FATAL][__sizeof__] sizeof 的目标 {type(Node).__name__}" f"[FATAL][__sizeof__] sizeof 的目标 {type(Node).__name__}"
@@ -1193,9 +1188,9 @@ class ExprBuiltinHandle(BaseHandle):
解析顺序(与注解解析同一规则源,避免各处手抄一份而漏项): 解析顺序(与注解解析同一规则源,避免各处手抄一份而漏项):
1) str/bytes/CPtr → i8*;类名(Gen.structs)→ 该类指针 1) str/bytes/CPtr → i8*;类名(Gen.structs)→ 该类指针
2) CTypeRegistry.GetClassByName/ResolveName(t.* 类型类与 C 基本类型名) 2) CTypeRegistry.GetClassByName/ResolveName(CType 类型类与 C 基本类型名)
3) CTypeInfo.FromNode:builtins/库/符号表 typedef(uint64/int64/sizet/ 3) CTypeInfo.FromNode:builtins/库/符号表 typedef(uint64/int64/sizet/
size_t…)、`T*` 指针后缀(parser 已展开为 `T | t.CPtr`)等 size_t…)、`T*` 指针后缀(parser 已展开为 `T | CPtr`)等
fail-fast:以上均解析不出 LLVM 类型时直接报错终止,**绝不回退 i32**。 fail-fast:以上均解析不出 LLVM 类型时直接报错终止,**绝不回退 i32**。
回退 i32 的后果不是"精度差一点"而是**读错变参槽**:Win64 变参槽固定 8 字节, 回退 i32 的后果不是"精度差一点"而是**读错变参槽**:Win64 变参槽固定 8 字节,
@@ -1236,16 +1231,7 @@ class ExprBuiltinHandle(BaseHandle):
else: else:
base = ir.PointerType(base) base = ir.PointerType(base)
target_type = base target_type = base
elif isinstance(type_arg, ast.Attribute): # 常规分支未命中:走注解解析同一规则源(typedef / `T*` 指针后缀 / 联合类型组合写法)。
if isinstance(type_arg.value, ast.Name) and IsTModule(type_arg.value.id, self.Trans.SymbolTable):
attr_name: str = type_arg.attr
ctype_cls: type | None = CTypeRegistry.GetClassByName(attr_name)
if ctype_cls is not None:
llvm_str: str | None = CTypeRegistry.CTypeToLLVM(ctype_cls)
resolved: ir.Type | None = Gen._type_str_to_llvm(llvm_str)
if resolved:
target_type = resolved
# 常规分支未命中:走注解解析同一规则源(typedef / `T*` 指针后缀 / t.* 组合写法)。
# 该规则源对未收录的名字会退化成 `%"{mod}.名"*` 假结构体(CStruct),故显式判掉。 # 该规则源对未收录的名字会退化成 `%"{mod}.名"*` 假结构体(CStruct),故显式判掉。
if target_type is None: if target_type is None:
type_info: CTypeInfo | None = CTypeInfo.FromNode(type_arg, self.Trans.SymbolTable) type_info: CTypeInfo | None = CTypeInfo.FromNode(type_arg, self.Trans.SymbolTable)
+151 -268
View File
@@ -10,10 +10,10 @@ import llvmlite.ir as ir
from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta
from lib.core.VLogger import get_logger as _vlog from lib.core.VLogger import get_logger as _vlog
from lib.constants.config import mode as _config_mode from lib.constants.config import mode as _config_mode
from lib.includes import t from lib.core import TypeSystem
from lib.includes.t import CTypeRegistry from lib.core.TypeSystem import CTypeRegistry
from lib.core.SymbolUtils import ( from lib.core.SymbolUtils import (
IsTModule, ExtractTypeNameFromBinOp, IsPtrSubscriptNode, DesugarPtrSubscriptToUnion, ExtractTypeNameFromBinOp, IsPtrSubscriptNode, DesugarPtrSubscriptToUnion,
ResolveTypeArgStr, GenericArgRawName, ResolveTypeArgStr, GenericArgRawName,
ClassHasFuncLevelCVTable, IsVtableSlotMethod) ClassHasFuncLevelCVTable, IsVtableSlotMethod)
from lib.core.Handles.HandlesExpr import DefineUseWidthFromLLVMType from lib.core.Handles.HandlesExpr import DefineUseWidthFromLLVMType
@@ -23,20 +23,11 @@ from lib.vast.ExprParser import NEW_SRC_MEMGR
# len() 参数形态不支持时的共享提示语(与 ViperC App/lib/core/Gen/Call/ # len() 参数形态不支持时的共享提示语(与 ViperC App/lib/core/Gen/Call/
# CallGenDispatch.vp 的 len() 分支同口径,措辞逐字一致,便于用户对照两侧报文)。 # CallGenDispatch.vp 的 len() 分支同口径,措辞逐字一致,便于用户对照两侧报文)。
_LEN_SUPPORTED_HINT: str = ( _LEN_SUPPORTED_HINT: str = (
"len() 只支持定长数组/数组指针(t.CArray[T, N])、i8*(str/bytes)或带 __len__ 的结构体;" "len() 只支持定长数组/数组指针(CArray[T, N])、i8*(str/bytes)或带 __len__ 的结构体;"
"非 i8 裸指针/标量指针没有长度语义:字符串请用 str/bytes,需要元素个数请自行记录长度," "非 i8 裸指针/标量指针没有长度语义:字符串请用 str/bytes,需要元素个数请自行记录长度,"
"或改用 t.CPtr[元素] 并显式维护元素计数" "或改用 CPtr[元素] 并显式维护元素计数"
) )
# 已删除的用户可见 CIf 族(c.CIf / c.CIfdef / c.CIfndef / c.CElif / c.CElse / c.CEndif):
# 用户再写即在调用点 FailFast,指向原生 cif/celif/celse 与 defined(NAME)(英文报文,
# 与 ViperC CallGenDispatch.vp 同口径)。内部标记 c.@CIf 族不受影响。
_REMOVED_CIF_CALL_MSG: str = (
"c.CIf / c.CIfdef / c.CIfndef / c.CElif / c.CElse / c.CEndif were removed; use the cif / "
"celif / celse statements together with the defined(NAME) predicate instead "
"(e.g. `cif defined(NAME):` ... `celif ...:` ... `celse:` ...)")
# PROF 热点:_EmitLLVMIRInstruction 对每条 IR 模板都要做多次 re.match / re.split, # PROF 热点:_EmitLLVMIRInstruction 对每条 IR 模板都要做多次 re.match / re.split,
# 未预编译的模块级入口每次都要「模式串哈希 → re 缓存查找 → 未命中就重新编译」, # 未预编译的模块级入口每次都要「模式串哈希 → re 缓存查找 → 未命中就重新编译」,
# 512 条缓存被打穿后开销巨大。这些模式全是字面量 → 提升为模块级预编译常量。 # 512 条缓存被打穿后开销巨大。这些模式全是字面量 → 提升为模块级预编译常量。
@@ -83,9 +74,9 @@ def _safe_ptr_type(ty: ir.Type) -> ir.Type:
def _BinOpContainsCPtr(node: ast.AST) -> bool: def _BinOpContainsCPtr(node: ast.AST) -> bool:
"""递归检查 BinOp(BitOr) 联合类型中是否含 t.CPtr(指针标记)""" """递归检查 BinOp(BitOr) 联合类型中是否含 CPtr(指针标记)"""
if isinstance(node, ast.Attribute): if isinstance(node, ast.Name):
return node.attr == 'CPtr' return node.id == 'CPtr'
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
return _BinOpContainsCPtr(node.left) or _BinOpContainsCPtr(node.right) return _BinOpContainsCPtr(node.left) or _BinOpContainsCPtr(node.right)
return False return False
@@ -338,7 +329,7 @@ class ExprCallHandle(BaseHandle):
def _ConstantToIrValue(raw: object, param_type: ir.Type, Gen: LlvmGeneratorMixin) -> ir.Value | None: def _ConstantToIrValue(raw: object, param_type: ir.Type, Gen: LlvmGeneratorMixin) -> ir.Value | None:
"""把全局默认参数表里的 Python 常量转成形参类型的 IR 常量。 """把全局默认参数表里的 Python 常量转成形参类型的 IR 常量。
只处理整数/布尔(跨模块默认值里最常见,如 cap: t.CSizeT = 4096)。字符串等 只处理整数/布尔(跨模块默认值里最常见,如 cap: CSizeT = 4096)。字符串等
常量需要在调用点引用定义模块的全局对象,无法安全重建 → 返回 None,调用点 常量需要在调用点引用定义模块的全局对象,无法安全重建 → 返回 None,调用点
退回原有零值填充(与修复前行为一致)。 退回原有零值填充(与修复前行为一致)。
""" """
@@ -398,7 +389,7 @@ class ExprCallHandle(BaseHandle):
"""函数指针间接调用前的 arity 校验(fail-fast,紧邻 builder.call 之前)。 """函数指针间接调用前的 arity 校验(fail-fast,紧邻 builder.call 之前)。
期望形参个数取自 FnPtr 的静态 LLVM 函数类型的形参表:来源是函数指针槽 期望形参个数取自 FnPtr 的静态 LLVM 函数类型的形参表:来源是函数指针槽
(模块级/局部 t.Callable[...] 注解)的 CTypeInfo.FuncPtrParams → (模块级/局部 Callable[...] 注解)的 CTypeInfo.FuncPtrParams →
CTypeInfo.ToLLVM/_ctype_to_llvm → ir.FunctionType(ret, params);变参位由 CTypeInfo.ToLLVM/_ctype_to_llvm → ir.FunctionType(ret, params);变参位由
FunctionType.var_arg 承载。不校验时,实参个数少于形参个数会让 llvmlite FunctionType.var_arg 承载。不校验时,实参个数少于形参个数会让 llvmlite
CallInstr 按形参个数索引 args[i] 抛裸 `IndexError: list index out of range` CallInstr 按形参个数索引 args[i] 抛裸 `IndexError: list index out of range`
@@ -440,7 +431,7 @@ class ExprCallHandle(BaseHandle):
if IsVariadic else f" {Expected} 个形参") if IsVariadic else f" {Expected} 个形参")
raise Exception( raise Exception(
f"[TransPyC] 函数指针调用实参个数不匹配: '{FuncName}' 期望{ExpectText}," f"[TransPyC] 函数指针调用实参个数不匹配: '{FuncName}' 期望{ExpectText},"
f"实际传入 {Actual} 个实参;请检查该函数指针(t.Callable[...] 注解槽)的" f"实际传入 {Actual} 个实参;请检查该函数指针(Callable[...] 注解槽)的"
f"形参表是否与调用处实参个数一致。位置 {Loc}" f"形参表是否与调用处实参个数一致。位置 {Loc}"
f"{(',源码: ' + SourceLine) if SourceLine else ''}" f"{(',源码: ' + SourceLine) if SourceLine else ''}"
) )
@@ -531,15 +522,50 @@ class ExprCallHandle(BaseHandle):
ModulePath: str | None = None ModulePath: str | None = None
if isinstance(Node.func, ast.Name): if isinstance(Node.func, ast.Name):
FuncName = Node.func.id FuncName = Node.func.id
# __asm__(...) 语法糖:等价 c.Asm(...)(裸名调用,无需 import c) # __asm__(...) 语法糖:等价 Asm(...)(裸名调用,无需 import c)
if FuncName == '__asm__': if FuncName == '__asm__':
return self.Trans.ExprAsmHandle._HandleAsmLlvm(Node) return self.Trans.ExprAsmHandle._HandleAsmLlvm(Node)
# __llvmir__(...) 语法糖:等价 c.LLVMIR(...) # __llvmir__(...) 语法糖:等价 LLVMIR(...)
if FuncName == '__llvmir__': if FuncName == '__llvmir__':
return self._HandleLLVMIRLlvm(Node) return self._HandleLLVMIRLlvm(Node)
# irinp/irout 等价 c.LInp/c.LOut(仅作模板占位符,独立调用返回 0) # irinp/irout 等价 LInp/LOut(仅作模板占位符,独立调用返回 0)
if FuncName in ('irinp', 'irout'): if FuncName in ('irinp', 'irout'):
return ir.Constant(ir.IntType(32), 0) return ir.Constant(ir.IntType(32), 0)
# 内建语法糖调用(裸名):Asm / Addr / Deref / DerefAs / Set / Load /
# PtrToInt / CError / AsmInp / AsmOut / LLVMIR / LInp / LOut /
# CPragma / CUndef 不是普通函数,优先于符号查找。
if FuncName == 'Asm':
return self.Trans.ExprAsmHandle._HandleAsmLlvm(Node)
if FuncName == 'Addr':
return self.Trans.CSpecialCallHandle._HandleCAddrLlvm(Node)
if FuncName == 'Set':
return self.Trans.CSpecialCallHandle._HandleCSetLlvm(Node)
if FuncName == 'Load':
return self.Trans.CSpecialCallHandle._HandleCLoadLlvm(Node)
if FuncName == 'Deref':
return self.Trans.CSpecialCallHandle._HandleCDerefLlvm(Node)
if FuncName == 'DerefAs':
return self._HandleCDerefAsLlvm(Node)
if FuncName == 'PtrToInt':
return self.Trans.CSpecialCallHandle._HandleCPtrToIntLlvm(Node)
if FuncName in ('AsmInp', 'AsmOut', 'LInp', 'LOut'):
return ir.Constant(ir.IntType(32), 0)
if FuncName == 'LLVMIR':
return self._HandleLLVMIRLlvm(Node)
if FuncName in ('CPragma', 'CUndef'):
return ir.Constant(ir.IntType(1), 1)
if FuncName == 'CError':
msg = "compile-time error"
if Node.args:
arg = Node.args[0]
if isinstance(arg, ast.Constant) and isinstance(arg.value, str):
msg = arg.value
lineno = getattr(Node, 'lineno', 0)
# 注入行偏移还原:AST 行号含 _inject_auto_imports 注入的 N 行
_line_offset: int = int(getattr(self.Trans, '_line_offset', 0) or 0)
if _line_offset > 0 and lineno > _line_offset:
lineno -= _line_offset
raise Exception(f"#error: {msg} (line {lineno})")
# M1 协程:普通函数调用 async 函数 → create_<name>()(返回帧指针) # M1 协程:普通函数调用 async 函数 → create_<name>()(返回帧指针)
if hasattr(self.Trans, 'AsyncHandler') and self.Trans.AsyncHandler._IsAsyncFunc(FuncName): if hasattr(self.Trans, 'AsyncHandler') and self.Trans.AsyncHandler._IsAsyncFunc(FuncName):
return self.Trans.AsyncHandler._HandleAsyncCreateCallLlvm(Node, FuncName) return self.Trans.AsyncHandler._HandleAsyncCreateCallLlvm(Node, FuncName)
@@ -588,12 +614,12 @@ class ExprCallHandle(BaseHandle):
ClassName = Gen.var_struct_class.get(FuncName) ClassName = Gen.var_struct_class.get(FuncName)
if ClassName and Gen._has_function(f'{ClassName}.__call__'): if ClassName and Gen._has_function(f'{ClassName}.__call__'):
return self._HandleInstanceCallLlvm(Node, FuncName, ClassName) return self._HandleInstanceCallLlvm(Node, FuncName, ClassName)
t_c_imported = getattr(self.Trans, '_t_c_imported_names', {}) t_c_imported = getattr(self.Trans, '_from_import_aliases', {})
if FuncName in t_c_imported: if FuncName in t_c_imported:
src_module, src_name = t_c_imported[FuncName] src_module, src_name = t_c_imported[FuncName]
virtual_node = self._make_virtual_attr_call(Node, src_module, src_name) virtual_node = self._make_virtual_attr_call(Node, src_module, src_name)
return self._HandleCallLlvm(virtual_node) return self._HandleCallLlvm(virtual_node)
# 检查是否是全局变量中的函数指针(t.Callable 类型在模块级定义) # 检查是否是全局变量中的函数指针(Callable 类型在模块级定义)
if FuncName not in Gen.variables and FuncName in Gen.global_vars: if FuncName not in Gen.variables and FuncName in Gen.global_vars:
Gen._Load_var(FuncName) Gen._Load_var(FuncName)
if FuncName not in Gen.variables and FuncName in Gen.module.globals: if FuncName not in Gen.variables and FuncName in Gen.module.globals:
@@ -605,7 +631,7 @@ class ExprCallHandle(BaseHandle):
# 检查是否是闭包变量(lambda 赋值给变量后调用) # 检查是否是闭包变量(lambda 赋值给变量后调用)
if FuncName in Gen.variables and Gen.variables[FuncName] is not None: if FuncName in Gen.variables and Gen.variables[FuncName] is not None:
VarPtr = Gen.variables[FuncName] VarPtr = Gen.variables[FuncName]
# 检查是否是函数指针变量(t.Callable 类型),直接加载并调用 # 检查是否是函数指针变量(Callable 类型),直接加载并调用
if isinstance(VarPtr, ir.GlobalVariable) and isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, ir.PointerType) and isinstance(VarPtr.type.pointee.pointee, ir.FunctionType): if isinstance(VarPtr, ir.GlobalVariable) and isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, ir.PointerType) and isinstance(VarPtr.type.pointee.pointee, ir.FunctionType):
fn_ptr = Gen._load(VarPtr, name=f"Load_fn_{FuncName}") fn_ptr = Gen._load(VarPtr, name=f"Load_fn_{FuncName}")
args = [] args = []
@@ -625,8 +651,8 @@ class ExprCallHandle(BaseHandle):
args.append(ArgVal) args.append(ArgVal)
self._CheckFuncPtrArity(Node, fn_ptr, args, FuncName, Gen) self._CheckFuncPtrArity(Node, fn_ptr, args, FuncName, Gen)
return Gen.builder.call(fn_ptr, args, name=f"call_{FuncName}") return Gen.builder.call(fn_ptr, args, name=f"call_{FuncName}")
# 处理 t.CPtr (i8*) 函数指针调用 # 处理 CPtr (i8*) 函数指针调用
# 当函数被赋值给 t.CPtr 变量时,原始函数类型退化为 i8* # 当函数被赋值给 CPtr 变量时,原始函数类型退化为 i8*
# 检查是否是闭包变量(通过 _closure_var_types 追踪) # 检查是否是闭包变量(通过 _closure_var_types 追踪)
if isinstance(closure_ptr.type, ir.PointerType) and isinstance(closure_ptr.type.pointee, ir.IntType) and closure_ptr.type.pointee.width == 8: if isinstance(closure_ptr.type, ir.PointerType) and isinstance(closure_ptr.type.pointee, ir.IntType) and closure_ptr.type.pointee.width == 8:
ClosureInfo: tuple[ir.Type, list[ir.Type]] | None = Gen._closure_var_types.get(FuncName) ClosureInfo: tuple[ir.Type, list[ir.Type]] | None = Gen._closure_var_types.get(FuncName)
@@ -700,10 +726,10 @@ class ExprCallHandle(BaseHandle):
# TypeGenResolve.vp:921)。落到下方 typedef 表判据必然 miss ⇒ 误报 # TypeGenResolve.vp:921)。落到下方 typedef 表判据必然 miss ⇒ 误报
# "Undefined function: 'rawptr'"(ViperC/App/lib/core/Gen/ # "Undefined function: 'rawptr'"(ViperC/App/lib/core/Gen/
# StructGenMixin.vp `vt_ptr: rawptr = rawptr(*(uint64*)(default_val))` 根因)。 # StructGenMixin.vp `vt_ptr: rawptr = rawptr(*(uint64*)(default_val))` 根因)。
# 单独 rawptr 等价 t.CPtr(void* → i8*):目标类型取内置 rawptr 的权威 # 单独 rawptr 等价 CPtr(void* → i8*):目标类型取内置 rawptr 的权威
# CTypeInfo(_builtin_rawptr_info,与注解侧同源),转换复用 (rawptr[X])(x) # CTypeInfo(_builtin_rawptr_info,与注解侧同源),转换复用 (rawptr[X])(x)
# / (t.CPtr)(x) 的 _emit_rawptr_cast——不新造第二套 rawptr 表示。 # / (CPtr)(x) 的 _emit_rawptr_cast——不新造第二套 rawptr 表示。
# 不照抄 uchar 的做法(往 builtins.vp 加 `uchar: t.CTypedef = ...`): # 不照抄 uchar 的做法(往 builtins.vp 加 `uchar: CTypedef = ...`):
# rawptr 不是普通 typedef 名而是内置语法,VPC register_ctypedef 显式拒绝 # rawptr 不是普通 typedef 名而是内置语法,VPC register_ctypedef 显式拒绝
# 重定义(TypeGenCType.vp:157-160)、TPC builtins_typedef_value 亦硬编码 # 重定义(TypeGenCType.vp:157-160)、TPC builtins_typedef_value 亦硬编码
# 返回内置值(TypeAnnotationResolver.py:313-314)⇒ 该声明不生效。 # 返回内置值(TypeAnnotationResolver.py:313-314)⇒ 该声明不生效。
@@ -715,7 +741,7 @@ class ExprCallHandle(BaseHandle):
return self._emit_rawptr_cast(Node, Gen, _rawptr_target) return self._emit_rawptr_cast(Node, Gen, _rawptr_target)
# builtins 隐式 CTypedef 作为类型转换调用(uint64(x)/int64(x)/size_t(x) 等, # builtins 隐式 CTypedef 作为类型转换调用(uint64(x)/int64(x)/size_t(x) 等,
# builtins.vp 声明、无需 import,不注册进 SymbolTable):常规 miss 后在此 # builtins.vp 声明、无需 import,不注册进 SymbolTable):常规 miss 后在此
# 尝试 typedef cast(uint64(buf) = t.CUInt64T(buf)),否则报 # 尝试 typedef cast(uint64(buf) = CUInt64T(buf)),否则报
# "Undefined function: 'uint64'"(includes/ast/base.vp bootstrap 根因)。 # "Undefined function: 'uint64'"(includes/ast/base.vp bootstrap 根因)。
_td_diag: str = '' _td_diag: str = ''
try: try:
@@ -729,18 +755,18 @@ class ExprCallHandle(BaseHandle):
if FuncName in _td_table: if FuncName in _td_table:
# from_type_name 对裸 typedef 名(uint64 等)解析不出真实类型类 # from_type_name 对裸 typedef 名(uint64 等)解析不出真实类型类
# (BuiltinTypeMap 无此键,CreateFromTypeName 落空成空 CType), # (BuiltinTypeMap 无此键,CreateFromTypeName 落空成空 CType),
# 因此改走权威 typedef 值:'t.CUInt64T' → CTypeRegistry.NameToLLVM # 因此改走权威 typedef 值:'CUInt64T' → CTypeRegistry.NameToLLVM
# → 'i64'(与 DeclarationGenerator 的 stub 兜底同机制)。 # → 'i64'(与 DeclarationGenerator 的 stub 兜底同机制)。
_bv_td: str | None = _TAR_TD.builtins_typedef_value(FuncName) _bv_td: str | None = _TAR_TD.builtins_typedef_value(FuncName)
_lls_td: str | None = None _lls_td: str | None = None
if _bv_td: if _bv_td:
_nm_td: str = _bv_td[2:] if _bv_td.startswith('t.') else _bv_td _nm_td: str = _bv_td
from lib.includes.t import CTypeRegistry as _CR_TD from lib.core.TypeSystem import CTypeRegistry as _CR_TD
_lls_td = _CR_TD.NameToLLVM(_nm_td) _lls_td = _CR_TD.NameToLLVM(_nm_td)
if not _lls_td: if not _lls_td:
# 声明值本身也是短别名(新语法:`typedef short = int16`、 # 声明值本身也是短别名(新语法:`typedef short = int16`、
# `typedef longlong = int64`)⇒ 单步 NameToLLVM(不认短别名) # `typedef longlong = int64`)⇒ 单步 NameToLLVM(不认短别名)
# 落空。改走权威链式解析(builtins.vp 声明 → 逐级展开到 t.C*), # 落空。改走权威链式解析(builtins.vp 声明 → 逐级展开到 C* 类型),
# 与注解位置 LLVMTypeMapper._resolve_name 同一来源。 # 与注解位置 LLVMTypeMapper._resolve_name 同一来源。
_td_info = _TAR_TD._lookup_builtins_typedef(FuncName, self.Trans.SymbolTable) _td_info = _TAR_TD._lookup_builtins_typedef(FuncName, self.Trans.SymbolTable)
if _td_info is not None and _td_info.BaseType: if _td_info is not None and _td_info.BaseType:
@@ -749,9 +775,7 @@ class ExprCallHandle(BaseHandle):
if len(Node.args) >= 2: if len(Node.args) >= 2:
_p2b: ast.AST = Node.args[1] _p2b: ast.AST = Node.args[1]
_p2b_cptr: bool = ( _p2b_cptr: bool = (
(isinstance(_p2b, ast.Attribute) and _p2b.attr == 'CPtr' isinstance(_p2b, ast.Name) and _p2b.id == 'CPtr'
and isinstance(_p2b.value, ast.Name) and _p2b.value.id in ('t', 'c')) or
(isinstance(_p2b, ast.Name) and _p2b.id == 'CPtr')
) )
if _p2b_cptr: if _p2b_cptr:
if isinstance(_tg_td2, ir.PointerType): if isinstance(_tg_td2, ir.PointerType):
@@ -761,18 +785,16 @@ class ExprCallHandle(BaseHandle):
if _lls_td: if _lls_td:
_tg_td: ir.Type = Gen._ctype_to_llvm(_lls_td) _tg_td: ir.Type = Gen._ctype_to_llvm(_lls_td)
if isinstance(_tg_td, (ir.IntType, ir.FloatType, ir.DoubleType, ir.PointerType)): if isinstance(_tg_td, (ir.IntType, ir.FloatType, ir.DoubleType, ir.PointerType)):
# 双参数形式 uint8(s, t.CPtr) / int64(v, CPtr):第二参是 # 双参数形式 uint8(s, CPtr) / int64(v, CPtr):第二参是
# CPtr 标记 → 指针包装(等价旧写法 t.CUInt8T(s, t.CPtr), # CPtr 标记 → 指针包装(等价旧写法 CUInt8T(s, CPtr),
# 对齐 Attribute 形式 t.CXXX(v, t.CPtr) 的 IsPtr_cast 语义)。 # 对齐 CXXX(v, CPtr) 的 IsPtr_cast 语义)。
# 单参形式 uint64(buf) 才是标量转换。忽略第二参会把 # 单参形式 uint64(buf) 才是标量转换。忽略第二参会把
# hashlib/__sha1.vp 的 data 编译成标量 → 运行时 sha1 # hashlib/__sha1.vp 的 data 编译成标量 → 运行时 sha1
# transform 读越界崩溃。 # transform 读越界崩溃。
if len(Node.args) >= 2: if len(Node.args) >= 2:
_p2_td: ast.AST = Node.args[1] _p2_td: ast.AST = Node.args[1]
_p2_cptr: bool = ( _p2_cptr: bool = (
(isinstance(_p2_td, ast.Attribute) and _p2_td.attr == 'CPtr' isinstance(_p2_td, ast.Name) and _p2_td.id == 'CPtr'
and isinstance(_p2_td.value, ast.Name) and _p2_td.value.id in ('t', 'c')) or
(isinstance(_p2_td, ast.Name) and _p2_td.id == 'CPtr')
) )
if _p2_cptr: if _p2_cptr:
if isinstance(_tg_td, ir.PointerType): if isinstance(_tg_td, ir.PointerType):
@@ -789,15 +811,13 @@ class ExprCallHandle(BaseHandle):
# Handle list[int](mb) syntax — generic class constructor with explicit type args # Handle list[int](mb) syntax — generic class constructor with explicit type args
# Handle xxx[T](x) syntax — generic function call with explicit type args # Handle xxx[T](x) syntax — generic function call with explicit type args
sub: ast.Subscript = Node.func sub: ast.Subscript = Node.func
# (rawptr[X])(expr) / (t.CPtr[X])(expr):内建裸指针转换(无泛型模板)。 # (rawptr[X])(expr) / (CPtr[X])(expr):内建裸指针转换(无泛型模板)。
# 不拦截 → 泛型模板查不到 → 落 L850 "Unsupported call expression" # 不拦截 → 泛型模板查不到 → 落 L850 "Unsupported call expression"
# (StubMergerCollect.vp L271 bootstrap 根因)。 # (StubMergerCollect.vp L271 bootstrap 根因)。
_sub_nm: str | None = None _sub_nm: str | None = None
if isinstance(sub.value, ast.Name): if isinstance(sub.value, ast.Name):
_sub_nm = sub.value.id _sub_nm = sub.value.id
elif isinstance(sub.value, ast.Attribute) and isinstance(sub.value.value, ast.Name) and sub.value.value.id == 't' and sub.value.attr == 'CPtr': if _sub_nm in ('rawptr', 'CPtr'):
_sub_nm = 't.CPtr'
if _sub_nm in ('rawptr', 't.CPtr'):
return self._HandleSubscriptPtrCastLlvm(Node, sub) return self._HandleSubscriptPtrCastLlvm(Node, sub)
if isinstance(sub.value, ast.Name): if isinstance(sub.value, ast.Name):
FuncName: str = sub.value.id FuncName: str = sub.value.id
@@ -815,13 +835,13 @@ class ExprCallHandle(BaseHandle):
spec_name = self._ResolveGenericSlice(Node.func.value) spec_name = self._ResolveGenericSlice(Node.func.value)
if spec_name: if spec_name:
return self._HandleSizeofLlvm(ast.Name(id=spec_name, ctx=ast.Load())) return self._HandleSizeofLlvm(ast.Name(id=spec_name, ctx=ast.Load()))
# 对于 BinOp/BitOr 联合类型(如 AST | t.CPtr), # 对于 BinOp/BitOr 联合类型(如 AST | CPtr),
# sizeof 应返回指针大小 8,而非结构体大小 # sizeof 应返回指针大小 8,而非结构体大小
# 必须在 HandleExprLlvm 之前检查,避免对类型名求值产生副作用 # 必须在 HandleExprLlvm 之前检查,避免对类型名求值产生副作用
if isinstance(Node.func.value, ast.BinOp) and isinstance(Node.func.value.op, ast.BitOr): if isinstance(Node.func.value, ast.BinOp) and isinstance(Node.func.value.op, ast.BitOr):
if self._AnnotationContainsCPtr(Node.func.value): if self._AnnotationContainsCPtr(Node.func.value):
return ir.Constant(ir.IntType(64), 8) return ir.Constant(ir.IntType(64), 8)
# 对于 ast.Attribute(如 ast.ClassDef.__sizeof__() / t.CInt.__sizeof__()), # 对于 ast.Attribute(如 ast.ClassDef.__sizeof__() / CInt.__sizeof__()),
# 直接调用 _HandleSizeofLlvm,不走 HandleExprLlvm # 直接调用 _HandleSizeofLlvm,不走 HandleExprLlvm
# 因为 ast.Attribute 在 sizeof 上下文中一定是类型名,不是变量 # 因为 ast.Attribute 在 sizeof 上下文中一定是类型名,不是变量
if isinstance(Node.func.value, ast.Attribute): if isinstance(Node.func.value, ast.Attribute):
@@ -879,7 +899,7 @@ class ExprCallHandle(BaseHandle):
# 统一获取模块 SHA1,用于跨模块类型引用(确保用源模块的 SHA1 而非当前模块) # 统一获取模块 SHA1,用于跨模块类型引用(确保用源模块的 SHA1 而非当前模块)
# 放在 ModulePath 和 alias 解析之后,供所有 _HandleClassNewLlvm/_ensure_struct_declared 调用点使用 # 放在 ModulePath 和 alias 解析之后,供所有 _HandleClassNewLlvm/_ensure_struct_declared 调用点使用
_ctor_module_sha1: str | None = None _ctor_module_sha1: str | None = None
if ModulePath and ModulePath not in {'t', 'c'}: if ModulePath:
_ctor_sha1_map: dict[str, str] = getattr(Gen, 'ModuleSha1Map', {}) _ctor_sha1_map: dict[str, str] = getattr(Gen, 'ModuleSha1Map', {})
_ctor_module_sha1 = _ctor_sha1_map.get(ModulePath) _ctor_module_sha1 = _ctor_sha1_map.get(ModulePath)
if not _ctor_module_sha1 and '.' in ModulePath: if not _ctor_module_sha1 and '.' in ModulePath:
@@ -927,50 +947,14 @@ class ExprCallHandle(BaseHandle):
if (is_instance_var or _is_chained_instance) and not is_class_name: if (is_instance_var or _is_chained_instance) and not is_class_name:
return self._HandleMethodCallLlvm(Node) return self._HandleMethodCallLlvm(Node)
FuncAttr = Node.func.attr FuncAttr = Node.func.attr
# c 模块的特殊语法设施(Addr/Deref/DerefAs/Set/Load/Asm 等)必须优先处理, # 语法糖调用一律使用裸内建名;t./c. 前缀在调用点直接报错。
# 即使它们在 Gen.structs 中(c.py 的类会被声明为结构体但不应被实例化)。 if ModulePath in ('t', 'c'):
# c.py 是语法部分,不应被编译,其中的类是编译器语法设施。 raise TypeError(
# 必须在 Gen.structs 检查之前处理,否则 c.Deref/c.DerefAs 会被 f"[TPC] 类型注解/调用不再接受 '{ModulePath}.' 前缀;"
# _HandleClassNewLlvm 当成普通类实例化(根因:HandlesExprCall.py:497)。 f"请直接写裸内建名,如 {FuncAttr}(...)")
if ModulePath == 'c':
if FuncAttr == 'Asm':
return self.Trans.ExprAsmHandle._HandleAsmLlvm(Node)
elif FuncAttr == 'Addr':
return self.Trans.CSpecialCallHandle._HandleCAddrLlvm(Node)
elif FuncAttr == 'Set':
return self.Trans.CSpecialCallHandle._HandleCSetLlvm(Node)
elif FuncAttr == 'Load':
return self.Trans.CSpecialCallHandle._HandleCLoadLlvm(Node)
elif FuncAttr == 'Deref':
return self.Trans.CSpecialCallHandle._HandleCDerefLlvm(Node)
elif FuncAttr == 'DerefAs':
return self._HandleCDerefAsLlvm(Node)
elif FuncAttr == 'PtrToInt':
return self.Trans.CSpecialCallHandle._HandleCPtrToIntLlvm(Node)
elif FuncAttr in ('CIf', 'CIfdef', 'CIfndef', 'CElif', 'CElse', 'CEndif'):
from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError(_REMOVED_CIF_CALL_MSG)
elif FuncAttr == 'CError':
msg = "compile-time error"
if Node.args:
arg = Node.args[0]
if isinstance(arg, ast.Constant) and isinstance(arg.value, str):
msg = arg.value
lineno = getattr(Node, 'lineno', 0)
# 注入行偏移还原:AST 行号含 _inject_auto_imports 注入的 N 行
_line_offset: int = int(getattr(self.Trans, '_line_offset', 0) or 0)
if _line_offset > 0 and lineno > _line_offset:
lineno -= _line_offset
raise Exception(f"#error: {msg} (line {lineno})")
elif FuncAttr in ('AsmInp', 'AsmOut'):
return ir.Constant(ir.IntType(32), 0)
elif FuncAttr == 'LLVMIR':
return self._HandleLLVMIRLlvm(Node)
elif FuncAttr in ('LInp', 'LOut'):
return ir.Constant(ir.IntType(32), 0)
# stdarg 模块的变参糖:stdarg.arg / stdarg.va_arg / stdarg.va_start / # stdarg 模块的变参糖:stdarg.arg / stdarg.va_arg / stdarg.va_start /
# stdarg.va_end 命中与裸名同名内建**完全相同**的处理(stdarg 是编译器 # stdarg.va_end 命中与裸名同名内建**完全相同**的处理(stdarg 是编译器
# 拦截的糖模块,不是真符号,与 c 模块的语法设施同一口径)。仅当 # 拦截的糖模块,不是真符号,与内建语法糖同一口径)。仅当
# ModulePath 恰为 'stdarg' 时进入,不会抢掉其它模块/用户模块的调用。 # ModulePath 恰为 'stdarg' 时进入,不会抢掉其它模块/用户模块的调用。
if ModulePath == 'stdarg': if ModulePath == 'stdarg':
if FuncAttr == 'arg': if FuncAttr == 'arg':
@@ -1101,11 +1085,6 @@ class ExprCallHandle(BaseHandle):
result = self._HandleClassNewLlvm(Node, FuncAttr, module_sha1=_ctor_module_sha1) result = self._HandleClassNewLlvm(Node, FuncAttr, module_sha1=_ctor_module_sha1)
if result is not None: if result is not None:
return result return result
if ModulePath == 't':
MethodResult_t = self._HandleMethodCallLlvm(Node)
if MethodResult_t is not None:
return MethodResult_t
raise Exception(f"Undefined method: 't.{FuncAttr}'")
if isinstance(Node.func.value, ast.Attribute): if isinstance(Node.func.value, ast.Attribute):
inner_attr = Node.func.value.attr inner_attr = Node.func.value.attr
if inner_attr in Gen.structs or self.Trans.SymbolTable.is_struct(inner_attr): if inner_attr in Gen.structs or self.Trans.SymbolTable.is_struct(inner_attr):
@@ -1122,7 +1101,7 @@ class ExprCallHandle(BaseHandle):
MethodResult = self._HandleMethodCallLlvm(Node) MethodResult = self._HandleMethodCallLlvm(Node)
IsZeroResult = isinstance(MethodResult, ir.Constant) and isinstance(MethodResult.type, ir.IntType) and MethodResult.constant == 0 IsZeroResult = isinstance(MethodResult, ir.Constant) and isinstance(MethodResult.type, ir.IntType) and MethodResult.constant == 0
if IsZeroResult and FuncAttr is not None: if IsZeroResult and FuncAttr is not None:
mangled_name = Gen._mangle_func_name(FuncAttr, ModulePath if ModulePath and ModulePath != 't' else None) mangled_name = Gen._mangle_func_name(FuncAttr, ModulePath if ModulePath else None)
if Gen._has_function(mangled_name): if Gen._has_function(mangled_name):
CallArgs = [] CallArgs = []
for ArgIdx, arg in enumerate(Node.args, start=1): for ArgIdx, arg in enumerate(Node.args, start=1):
@@ -1141,7 +1120,7 @@ class ExprCallHandle(BaseHandle):
IsKnown = (LastPart in imported or LastPart in self.Trans.SymbolTable.import_aliases or IsKnown = (LastPart in imported or LastPart in self.Trans.SymbolTable.import_aliases or
LastPart in ModuleSha1Map) LastPart in ModuleSha1Map)
# 最后尝试: 用 FuncAttr 直接查找 Gen.functions(_find_function 会遍历 SHA1 前缀) # 最后尝试: 用 FuncAttr 直接查找 Gen.functions(_find_function 会遍历 SHA1 前缀)
if FuncAttr and ModulePath and ModulePath not in {'t', 'c'}: if FuncAttr and ModulePath:
# _ctor_module_sha1 已在函数顶部统一获取,此处无需重复 # _ctor_module_sha1 已在函数顶部统一获取,此处无需重复
# 先检查 FuncAttr 是否是函数/变量,如果是则跳过 struct 声明 # 先检查 FuncAttr 是否是函数/变量,如果是则跳过 struct 声明
_attr_sym = self.Trans.SymbolTable.lookup(FuncAttr) _attr_sym = self.Trans.SymbolTable.lookup(FuncAttr)
@@ -1206,7 +1185,7 @@ class ExprCallHandle(BaseHandle):
return self._check_eh_return(result, FuncAttr, Gen, called_func=func_decl) return self._check_eh_return(result, FuncAttr, Gen, called_func=func_decl)
if ModulePath and IsKnown: if ModulePath and IsKnown:
raise Exception(f"Undefined symbol: '{ModulePath}.{FuncAttr}'") raise Exception(f"Undefined symbol: '{ModulePath}.{FuncAttr}'")
if ModulePath and ModulePath not in {'t', 'c'} and not IsKnown: if ModulePath and not IsKnown:
raise Exception(f"Unknown module: '{ModulePath}' (undefined symbol: '{ModulePath}.{FuncAttr}')") raise Exception(f"Unknown module: '{ModulePath}' (undefined symbol: '{ModulePath}.{FuncAttr}')")
if not ModulePath and FuncAttr: if not ModulePath and FuncAttr:
raise Exception(f"Undefined method: '{FuncAttr}'") raise Exception(f"Undefined method: '{FuncAttr}'")
@@ -1550,10 +1529,8 @@ class ExprCallHandle(BaseHandle):
parts.append(value.value) parts.append(value.value)
elif isinstance(value, ast.FormattedValue): elif isinstance(value, ast.FormattedValue):
expr = value.value expr = value.value
# c.LInp/c.LOut 与裸名 irinp/irout 等价(见 _intrinsic_marker) # LInp/LOut 与裸名 irinp/irout 等价(见 _intrinsic_marker)
_marker: str | None = self.Trans.ExprAsmHandle._intrinsic_marker(expr) _marker: str | None = self.Trans.ExprAsmHandle._intrinsic_marker(expr)
_is_c_qualified: bool = (isinstance(expr, ast.Call) and isinstance(expr.func, ast.Attribute)
and isinstance(expr.func.value, ast.Name) and expr.func.value.id == 'c')
if _marker == 'LInp': if _marker == 'LInp':
if expr.args: if expr.args:
val = self.HandleExprLlvm(expr.args[0]) val = self.HandleExprLlvm(expr.args[0])
@@ -1574,8 +1551,8 @@ class ExprCallHandle(BaseHandle):
all_ops.append(('out', len(output_targets) - 1)) all_ops.append(('out', len(output_targets) - 1))
parts.append(f'%__OP{operand_seq}__') parts.append(f'%__OP{operand_seq}__')
operand_seq += 1 operand_seq += 1
elif not _is_c_qualified: else:
# c.* 中非 LInp/LOut 的形态不收集(保持原行为) # 非标记表达式按普通输入操作数处理
fallback = self.HandleExprLlvm(expr) fallback = self.HandleExprLlvm(expr)
if fallback: if fallback:
input_ops.append(fallback) input_ops.append(fallback)
@@ -1902,14 +1879,14 @@ class ExprCallHandle(BaseHandle):
Gen = self.Trans.LlvmGen Gen = self.Trans.LlvmGen
# 解析 import 别名: 如 window -> vpsdk.window # 解析 import 别名: 如 window -> vpsdk.window
if ModulePath and ModulePath not in ('c', 't'): if ModulePath:
ModulePath = self.Trans.SymbolTable.resolve_alias(ModulePath) ModulePath = self.Trans.SymbolTable.resolve_alias(ModulePath)
is_user_module = (ModulePath and ModulePath not in ('c', 't') and is_user_module = (ModulePath and
(ModulePath in Gen.ModuleSha1Map or (ModulePath in Gen.ModuleSha1Map or
ModulePath in getattr(self.Trans, '_ImportedModules', set()) or ModulePath in getattr(self.Trans, '_ImportedModules', set()) or
ModulePath in self.Trans.SymbolTable.import_aliases)) ModulePath in self.Trans.SymbolTable.import_aliases))
if ModulePath and ModulePath not in ('c', 't') and not is_user_module: if ModulePath and not is_user_module:
is_user_module = (ModulePath in Gen.ModuleSha1Map or is_user_module = (ModulePath in Gen.ModuleSha1Map or
ModulePath.split('.')[-1] in Gen.ModuleSha1Map or ModulePath.split('.')[-1] in Gen.ModuleSha1Map or
ModulePath.split('.')[-1] in getattr(self.Trans, '_ImportedModules', set())) ModulePath.split('.')[-1] in getattr(self.Trans, '_ImportedModules', set()))
@@ -1922,7 +1899,7 @@ class ExprCallHandle(BaseHandle):
# 插入了 IsModuleAlias 的 AliasInfo,据此识别并补全完整路径,使 # 插入了 IsModuleAlias 的 AliasInfo,据此识别并补全完整路径,使
# `X.get_perm_pool()` 正确解析为模块函数({sha1}.get_perm_pool)而非 # `X.get_perm_pool()` 正确解析为模块函数({sha1}.get_perm_pool)而非
# 类方法({sha1}.X.get_perm_pool,链接 undefined symbol)。 # 类方法({sha1}.X.get_perm_pool,链接 undefined symbol)。
if ModulePath and ModulePath not in ('c', 't') and not is_user_module: if ModulePath and not is_user_module:
_al_last = ModulePath.split('.')[-1] _al_last = ModulePath.split('.')[-1]
_al_sym = self.Trans.SymbolTable.lookup(_al_last) _al_sym = self.Trans.SymbolTable.lookup(_al_last)
if _al_sym and getattr(_al_sym, 'IsModuleAlias', False): if _al_sym and getattr(_al_sym, 'IsModuleAlias', False):
@@ -1934,7 +1911,7 @@ class ExprCallHandle(BaseHandle):
if is_user_module: if is_user_module:
mangled_name = Gen._mangle_func_name(func_name, ModulePath) mangled_name = Gen._mangle_func_name(func_name, ModulePath)
sym_info = self.LookupFunctionSymbol(func_name, module_path=ModulePath) sym_info = self.LookupFunctionSymbol(func_name, module_path=ModulePath)
is_inline = sym_info and (sym_info.IsInline or isinstance(sym_info.Storage, t.CInline)) is_inline = sym_info and (sym_info.IsInline or isinstance(sym_info.Storage, TypeSystem.CInline))
if is_inline and sym_info.InlineBody: if is_inline and sym_info.InlineBody:
self._HandleInlineExpandLlvm(Node, sym_info) self._HandleInlineExpandLlvm(Node, sym_info)
return ir.Constant(ir.IntType(32), 1) return ir.Constant(ir.IntType(32), 1)
@@ -2015,43 +1992,6 @@ class ExprCallHandle(BaseHandle):
return self._HandleClosureCallLlvm(Node, func_name) return self._HandleClosureCallLlvm(Node, func_name)
return None return None
if ModulePath == 'c':
if func_name == 'Asm':
return self.Trans.ExprAsmHandle._HandleAsmLlvm(Node)
elif func_name == 'Addr':
return self.Trans.CSpecialCallHandle._HandleCAddrLlvm(Node)
elif func_name == 'Set':
return self.Trans.CSpecialCallHandle._HandleCSetLlvm(Node)
elif func_name == 'Load':
return self.Trans.CSpecialCallHandle._HandleCLoadLlvm(Node)
elif func_name == 'Deref':
return self.Trans.CSpecialCallHandle._HandleCDerefLlvm(Node)
elif func_name == 'DerefAs':
return self._HandleCDerefAsLlvm(Node)
elif func_name == 'PtrToInt':
return self.Trans.CSpecialCallHandle._HandleCPtrToIntLlvm(Node)
elif func_name in ('CIf', 'CIfdef', 'CIfndef', 'CElif', 'CElse', 'CEndif'):
from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError(_REMOVED_CIF_CALL_MSG)
elif func_name == 'CError':
msg = "compile-time error"
if Node.args:
arg = Node.args[0]
if isinstance(arg, ast.Constant) and isinstance(arg.value, str):
msg = arg.value
lineno = getattr(Node, 'lineno', 0)
# 注入行偏移还原:AST 行号含 _inject_auto_imports 注入的 N 行
_line_offset: int = int(getattr(self.Trans, '_line_offset', 0) or 0)
if _line_offset > 0 and lineno > _line_offset:
lineno -= _line_offset
raise Exception(f"#error: {msg} (line {lineno})")
elif func_name in ('AsmInp', 'AsmOut'):
return ir.Constant(ir.IntType(32), 0)
elif func_name == 'LLVMIR':
return self._HandleLLVMIRLlvm(Node)
elif func_name in ('LInp', 'LOut'):
return ir.Constant(ir.IntType(32), 0)
win32_apis = { win32_apis = {
'SetConsoleOutputCP': (ir.IntType(32), [ir.IntType(32)]), 'SetConsoleOutputCP': (ir.IntType(32), [ir.IntType(32)]),
'SetConsoleCP': (ir.IntType(32), [ir.IntType(32)]), 'SetConsoleCP': (ir.IntType(32), [ir.IntType(32)]),
@@ -2148,13 +2088,13 @@ class ExprCallHandle(BaseHandle):
if target_type_str and type_info.IsPtr and not IsPtr: if target_type_str and type_info.IsPtr and not IsPtr:
if '*' not in target_type_str: if '*' not in target_type_str:
target_type_str += ' *' target_type_str += ' *'
if isinstance(type_info.Storage, t.CExport) or isinstance(type_info.Storage, t.CExtern): if isinstance(type_info.Storage, TypeSystem.CExport) or isinstance(type_info.Storage, TypeSystem.CExtern):
pass pass
if type_info.IsState: if type_info.IsState:
Gen._export_funcs.add('_type_union_cast') Gen._export_funcs.add('_type_union_cast')
else: else:
# Fallback 路径:MergeTypes 失败(返回 None 或抛异常)时,手动从 BinOp 提取类型信息 # Fallback 路径:MergeTypes 失败(返回 None 或抛异常)时,手动从 BinOp 提取类型信息
# 处理 (BaseType | t.CPtr) 这种模式,手动解析为 "{BaseType} *" # 处理 (BaseType | CPtr) 这种模式,手动解析为 "{BaseType} *"
_vlog().warning( _vlog().warning(
f"_HandleTypeUnionCastLlvm: MergeTypes 未返回 CTypeInfo " f"_HandleTypeUnionCastLlvm: MergeTypes 未返回 CTypeInfo "
f"(type_info={type_info!r}, exception={MergeException!r}),启用 fallback 手动解析" f"(type_info={type_info!r}, exception={MergeException!r}),启用 fallback 手动解析"
@@ -2162,8 +2102,8 @@ class ExprCallHandle(BaseHandle):
target_type_str = self._ExtractTypeStrFromUnionBinOp(Node.func) target_type_str = self._ExtractTypeStrFromUnionBinOp(Node.func)
if not target_type_str: if not target_type_str:
# fail-fast(原为 _vlog().warning + return None): # fail-fast(原为 _vlog().warning + return None):
# `(T | t.CPtr)(x)` 只可能来自指针强转——parser 把 `(T*)x` / `(T*)(x)` / # `(T | CPtr)(x)` 只可能来自指针强转——parser 把 `(T*)x` / `(T*)(x)` /
# `T*(x)`(含 `**`)统一产成 func = `T | t.CPtr` 的 Call(见 # `T*(x)`(含 `**`)统一产成 func = `T | CPtr` 的 Call(见
# vast/ExprParser._ConsumePtrSuffixCall、vast_c.c ConsumePtrSuffixCall)。 # vast/ExprParser._ConsumePtrSuffixCall、vast_c.c ConsumePtrSuffixCall)。
# 该形态必须有值产出;返回 None 会让调用方把整条表达式当"编译期求值为空" # 该形态必须有值产出;返回 None 会让调用方把整条表达式当"编译期求值为空"
# 丢掉(现场:ViperC ExprGenBase.vp:360 `v = (ast.Expr*(node)).value` # 丢掉(现场:ViperC ExprGenBase.vp:360 `v = (ast.Expr*(node)).value`
@@ -2246,12 +2186,12 @@ class ExprCallHandle(BaseHandle):
def _ExtractTypeStrFromUnionBinOp(self, NodeFunc: ast.AST) -> str | None: def _ExtractTypeStrFromUnionBinOp(self, NodeFunc: ast.AST) -> str | None:
"""Fallback:从类型联合 BinOp 手动提取类型字符串。 """Fallback:从类型联合 BinOp 手动提取类型字符串。
处理 (BaseType | t.CPtr) 这种模式,手动解析为 "{BaseType} *"。 处理 (BaseType | CPtr) 这种模式,手动解析为 "{BaseType} *"。
支持嵌套的 | 操作(如 (t.CInt | t.CPtr) | t.CStatic)。 支持嵌套的 | 操作(如 (CInt | CPtr) | CStatic)。
策略: 策略:
- 递归展平所有 | 操作数 - 递归展平所有 | 操作数
- t.CPtr 视为指针修饰符(生成 "{BaseType} *" 格式) - CPtr 视为指针修饰符(生成 "{BaseType} *" 格式)
- 其他 CType 子类作为基础类型(取第一个) - 其他 CType 子类作为基础类型(取第一个)
- 跳过存储类/限定符修饰符(CExport/CExtern/CStatic/CConst/CVolatile/CInline 等) - 跳过存储类/限定符修饰符(CExport/CExtern/CStatic/CConst/CVolatile/CInline 等)
""" """
@@ -2279,7 +2219,7 @@ class ExprCallHandle(BaseHandle):
CollectOperands(NodeFunc) CollectOperands(NodeFunc)
HasCPtr = False # 是否包含 t.CPtr(指针修饰符) HasCPtr = False # 是否包含 CPtr(指针修饰符)
BaseTypeName = None # 基础类型名(如 "CInt"、"CChar") BaseTypeName = None # 基础类型名(如 "CInt"、"CChar")
for Operand in Operands: for Operand in Operands:
@@ -2291,7 +2231,7 @@ class ExprCallHandle(BaseHandle):
else: else:
continue continue
# t.CPtr 是指针修饰符,单独处理(增加一层 *) # CPtr 是指针修饰符,单独处理(增加一层 *)
if AttrName == 'CPtr': if AttrName == 'CPtr':
HasCPtr = True HasCPtr = True
continue continue
@@ -2300,9 +2240,9 @@ class ExprCallHandle(BaseHandle):
if AttrName in StorageQualifierNames: if AttrName in StorageQualifierNames:
continue continue
# 通过 t 模块获取类型类,验证是否为 CType 子类 # 通过 TypeSystem 获取类型类,验证是否为 CType 子类
TypeClass = getattr(t, AttrName, None) TypeClass = getattr(TypeSystem, AttrName, None)
if not (isinstance(TypeClass, type) and issubclass(TypeClass, t.CType)): if not (isinstance(TypeClass, type) and issubclass(TypeClass, TypeSystem.CType)):
# 非 CType 类,跳过 # 非 CType 类,跳过
continue continue
@@ -2313,7 +2253,7 @@ class ExprCallHandle(BaseHandle):
if not BaseTypeName: if not BaseTypeName:
return None return None
# 包含 t.CPtr 时,生成 "{BaseType} *" 格式 # 包含 CPtr 时,生成 "{BaseType} *" 格式
# _CType2LLVM 已验证能解析 "CInt *" → i32*(ir.PointerType(ir.IntType(32))) # _CType2LLVM 已验证能解析 "CInt *" → i32*(ir.PointerType(ir.IntType(32)))
if HasCPtr: if HasCPtr:
return f"{BaseTypeName} *" return f"{BaseTypeName} *"
@@ -2499,11 +2439,11 @@ class ExprCallHandle(BaseHandle):
return ArgVal return ArgVal
def _HandleSubscriptPtrCastLlvm(self, Node: ast.Call, sub: ast.Subscript) -> ir.Value: def _HandleSubscriptPtrCastLlvm(self, Node: ast.Call, sub: ast.Subscript) -> ir.Value:
"""(rawptr[X])(expr) / (t.CPtr[X])(expr) 内建指针转换:expr → X* """(rawptr[X])(expr) / (CPtr[X])(expr) 内建指针转换:expr → X*
rawptr 是编译器内建裸指针语法(无 SymbolTable typedef 条目、无泛型模板), rawptr 是编译器内建裸指针语法(无 SymbolTable typedef 条目、无泛型模板),
此前 Subscript 调用仅查泛型模板 → 落空后报 "Unsupported call expression" 此前 Subscript 调用仅查泛型模板 → 落空后报 "Unsupported call expression"
(StubMergerCollect.vp `(rawptr[FileEntry])(t.CVoid(...))` bootstrap 根因)。 (StubMergerCollect.vp `(rawptr[FileEntry])(CVoid(...))` bootstrap 根因)。
目标类型经 TypeMergeHandler.GetCTypeInfo 解析 Subscript 类型节点获得。 目标类型经 TypeMergeHandler.GetCTypeInfo 解析 Subscript 类型节点获得。
""" """
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
@@ -2819,14 +2759,10 @@ class ExprCallHandle(BaseHandle):
@staticmethod @staticmethod
def _has_cvtable_decorator(node: ast.ClassDef) -> bool: def _has_cvtable_decorator(node: ast.ClassDef) -> bool:
"""检查 ClassDef 是否有 @t.CVTable 装饰器(或 @CVTable)""" """检查 ClassDef 是否有 @CVTable 装饰器(或 @CVTable)"""
for decorator in node.decorator_list: for decorator in node.decorator_list:
if isinstance(decorator, ast.Attribute) and getattr(decorator.value, 'id', None) == 't' and decorator.attr == 'CVTable':
return True
if isinstance(decorator, ast.Call): if isinstance(decorator, ast.Call):
inner = decorator.func inner = decorator.func
if isinstance(inner, ast.Attribute) and getattr(inner.value, 'id', None) == 't' and inner.attr == 'CVTable':
return True
if isinstance(inner, ast.Name) and inner.id == 'CVTable': if isinstance(inner, ast.Name) and inner.id == 'CVTable':
return True return True
if isinstance(decorator, ast.Name) and decorator.id == 'CVTable': if isinstance(decorator, ast.Name) and decorator.id == 'CVTable':
@@ -2835,16 +2771,14 @@ class ExprCallHandle(BaseHandle):
@staticmethod @staticmethod
def _has_novtable_decorator(node: ast.ClassDef) -> bool: def _has_novtable_decorator(node: ast.ClassDef) -> bool:
"""检查 ClassDef 是否有 @t.NoVTable 装饰器""" """检查 ClassDef 是否有 @NoVTable 装饰器"""
for decorator in node.decorator_list: for decorator in node.decorator_list:
if isinstance(decorator, ast.Attribute) and getattr(decorator.value, 'id', None) == 't' and decorator.attr == 'NoVTable':
return True
if isinstance(decorator, ast.Name) and decorator.id == 'NoVTable': if isinstance(decorator, ast.Name) and decorator.id == 'NoVTable':
return True return True
return False return False
def _try_register_vtable_ondemand(self, ClassName: str, class_sha1: str, Gen: "LlvmGeneratorMixin") -> None: def _try_register_vtable_ondemand(self, ClassName: str, class_sha1: str, Gen: "LlvmGeneratorMixin") -> None:
"""按需 vtable 注册:从 .pyi stub 检查 @t.CVTable 并注册到 vtable 集合。 """按需 vtable 注册:从 .pyi stub 检查 @CVTable 并注册到 vtable 集合。
沿继承链递归收集方法,保证 vtable 布局与 prescan 的 _EmitClassLlvm 一致: 沿继承链递归收集方法,保证 vtable 布局与 prescan 的 _EmitClassLlvm 一致:
- 基类方法在前(固定索引,保证多态分派正确) - 基类方法在前(固定索引,保证多态分派正确)
@@ -2852,9 +2786,9 @@ class ExprCallHandle(BaseHandle):
- 子类覆盖的方法放在父类的位置(用子类实现) - 子类覆盖的方法放在父类的位置(用子类实现)
与 prescan 的 _resolve_class_flags 逻辑一致: 与 prescan 的 _resolve_class_flags 逻辑一致:
- 类自身有 @t.CVTable → 注册 - 类自身有 @CVTable → 注册
- 类自身有 @t.NoVTable → 不注册 - 类自身有 @NoVTable → 不注册
- 类继承 @t.CVTable 基类(且无 @t.NoVTable)→ 注册(自动启用 CVTable) - 类继承 @CVTable 基类(且无 @NoVTable)→ 注册(自动启用 CVTable)
""" """
try: try:
import_handler = self.Trans.ImportHandler import_handler = self.Trans.ImportHandler
@@ -2976,7 +2910,7 @@ class ExprCallHandle(BaseHandle):
pass # 父类是 NoVTable,不继承 vtable pass # 父类是 NoVTable,不继承 vtable
# 继承链统一 vtable(与 _resolve_class_flags 一致): # 继承链统一 vtable(与 _resolve_class_flags 一致):
# 类自身无 @t.CVTable 时,第一个父类有 vtable → 子类启用; # 类自身无 @CVTable 时,第一个父类有 vtable → 子类启用;
# 父类无 vtable → 子类静态;父类信息未知 → 保守启用。 # 父类无 vtable → 子类静态;父类信息未知 → 保守启用。
if not is_cvtable and not is_novtable and first_parent_vtable is not None: if not is_cvtable and not is_novtable and first_parent_vtable is not None:
if first_parent_vtable: if first_parent_vtable:
@@ -2985,8 +2919,8 @@ class ExprCallHandle(BaseHandle):
# VtableByClassLevel:**忽略方法级 CVTable 标记**算出的 vtable 状态 # VtableByClassLevel:**忽略方法级 CVTable 标记**算出的 vtable 状态
# (= 类级 CVTable / 继承链判定)——供槽位筛选与"方法级触发"共用。 # (= 类级 CVTable / 继承链判定)——供槽位筛选与"方法级触发"共用。
_VtByClassLevel: bool = is_cvtable _VtByClassLevel: bool = is_cvtable
# 方法级修饰符筛选:`novirtual def`(⇒ @t.NoVTable)不进槽; # 方法级修饰符筛选:`novirtual def`(⇒ @NoVTable)不进槽;
# `virtual def`(⇒ @t.CVTable)进槽。判据唯一源 = IsVtableSlotMethod # `virtual def`(⇒ @CVTable)进槽。判据唯一源 = IsVtableSlotMethod
# (与定义端 HandlesClassDef / VPC _should_method_be_virtual 同口径), # (与定义端 HandlesClassDef / VPC _should_method_be_virtual 同口径),
# 故跨模块虚表槽序与定义模块逐槽一致。 # 故跨模块虚表槽序与定义模块逐槽一致。
self_methods: list[str] = [] self_methods: list[str] = []
@@ -3064,7 +2998,7 @@ class ExprCallHandle(BaseHandle):
避免链接时 undefined reference。 避免链接时 undefined reference。
触发场景:numpy 模块内部函数(如 np_sum)调用 a.sum(), 触发场景:numpy 模块内部函数(如 np_sum)调用 a.sum(),
其中 a 的类型注解 ndarray[t.CDouble] | t.CPtr 在类型解析时 其中 a 的类型注解 ndarray[CDouble] | CPtr 在类型解析时
只触发了 declare_only=True 特化(创建 struct + __before_init__), 只触发了 declare_only=True 特化(创建 struct + __before_init__),
方法体(fill/delete/dot/sum/...)未被编译。 方法体(fill/delete/dot/sum/...)未被编译。
""" """
@@ -3307,7 +3241,7 @@ class ExprCallHandle(BaseHandle):
return self._HandleStaticMethodCallLlvm(Node, ClassName, MethodName) return self._HandleStaticMethodCallLlvm(Node, ClassName, MethodName)
if FuncMeta.CLASS_METHOD in SymInfo.MetaList: if FuncMeta.CLASS_METHOD in SymInfo.MetaList:
return self._HandleStaticMethodCallLlvm(Node, ClassName, MethodName) return self._HandleStaticMethodCallLlvm(Node, ClassName, MethodName)
if isinstance(Node.func.value, ast.Name) and IsTModule(Node.func.value.id, self.Trans.SymbolTable): if isinstance(Node.func.value, ast.Name) :
result = self.Trans.TSpecialCallHandle._HandleTSpecialCallLlvm(Node) result = self.Trans.TSpecialCallHandle._HandleTSpecialCallLlvm(Node)
if result is not None: if result is not None:
return result return result
@@ -3322,8 +3256,7 @@ class ExprCallHandle(BaseHandle):
target_bits = 0 target_bits = 0
is_float = getattr(ctype_inst, 'IsSigned', False) is None and target_bits > 0 if ctype_inst else False is_float = getattr(ctype_inst, 'IsSigned', False) is None and target_bits > 0 if ctype_inst else False
IsPtr_cast = len(Node.args) >= 2 and ( IsPtr_cast = len(Node.args) >= 2 and (
(isinstance(Node.args[1], ast.Attribute) and Node.args[1].attr == 'CPtr' and isinstance(Node.args[1].value, ast.Name) and IsTModule(Node.args[1].value.id, self.Trans.SymbolTable)) or isinstance(Node.args[1], ast.Name) and Node.args[1].id == 'CPtr'
(isinstance(Node.args[1], ast.Name) and Node.args[1].id == 'CPtr')
) )
if Node.args: if Node.args:
ArgNode = Node.args[0] ArgNode = Node.args[0]
@@ -3376,52 +3309,6 @@ class ExprCallHandle(BaseHandle):
SymInfo = self.Trans.SymbolTable[MethodName] SymInfo = self.Trans.SymbolTable[MethodName]
if SymInfo.IsTypedef: if SymInfo.IsTypedef:
return self._HandleTypedefCastLlvm(Node, MethodName) return self._HandleTypedefCastLlvm(Node, MethodName)
if isinstance(Node.func.value, ast.Name) and Node.func.value.id == 'c':
if MethodName == 'Asm':
return self.Trans.ExprAsmHandle._HandleAsmLlvm(Node)
if MethodName == 'Addr':
return self.Trans.CSpecialCallHandle._HandleCAddrLlvm(Node)
elif MethodName == 'Set':
return self.Trans.CSpecialCallHandle._HandleCSetLlvm(Node)
elif MethodName == 'Load':
return self.Trans.CSpecialCallHandle._HandleCLoadLlvm(Node)
elif MethodName == 'Deref':
return self.Trans.CSpecialCallHandle._HandleCDerefLlvm(Node)
elif MethodName == 'DerefAs':
return self._HandleCDerefAsLlvm(Node)
elif MethodName == 'PtrToInt':
return self.Trans.CSpecialCallHandle._HandleCPtrToIntLlvm(Node)
elif MethodName in ('CIf', 'CIfdef', 'CIfndef', 'CElif'):
from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError(_REMOVED_CIF_CALL_MSG)
elif MethodName == 'CError':
msg = "compile-time error"
if Node.args:
arg = Node.args[0]
if isinstance(arg, ast.Constant) and isinstance(arg.value, str):
msg = arg.value
else:
try:
val = self.HandleExprLlvm(arg)
if isinstance(val, str):
msg = val
except Exception as _e:
if _config_mode == "strict":
raise
_vlog().warning(f"处理函数调用失败: {_e}", "Exception")
lineno = getattr(Node, 'lineno', 0)
# 注入行偏移还原:AST 行号含 _inject_auto_imports 注入的 N 行
_line_offset: int = int(getattr(self.Trans, '_line_offset', 0) or 0)
if _line_offset > 0 and lineno > _line_offset:
lineno -= _line_offset
raise Exception(f"#error: {msg} (line {lineno})")
elif MethodName in ('CElse', 'CEndif'):
from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError(_REMOVED_CIF_CALL_MSG)
elif MethodName in ('CPragma', 'CUndef'):
return ir.Constant(ir.IntType(1), 1)
elif MethodName in ('LLVMIR', 'LInp', 'LOut'):
return None
ObjVal = self.HandleExprLlvm(Node.func.value) ObjVal = self.HandleExprLlvm(Node.func.value)
if not ObjVal: if not ObjVal:
return None return None
@@ -3801,7 +3688,7 @@ class ExprCallHandle(BaseHandle):
CallArgs[target_idx] = ArgVal CallArgs[target_idx] = ArgVal
# 按需 vtable 注册:当 ClassName 不在 vtable 集合中但有 class_sha1 时, # 按需 vtable 注册:当 ClassName 不在 vtable 集合中但有 class_sha1 时,
# 从 .pyi stub 检查 @t.CVTable 装饰器并注册。 # 从 .pyi stub 检查 @CVTable 装饰器并注册。
# 修复场景:list[str].__new__ 中 pool.alloc(48) 编译时, # 修复场景:list[str].__new__ 中 pool.alloc(48) 编译时,
# MemManager 可能因导入时序问题未注册到当前 Gen 的 vtable 集合, # MemManager 可能因导入时序问题未注册到当前 Gen 的 vtable 集合,
# 导致生成 call_(直接调用)而非 vcall_(虚分派),运行时段错误。 # 导致生成 call_(直接调用)而非 vcall_(虚分派),运行时段错误。
@@ -3818,8 +3705,8 @@ class ExprCallHandle(BaseHandle):
# class_methods)与 struct body 可能因并行 include 翻译时序撕裂—— # class_methods)与 struct body 可能因并行 include 翻译时序撕裂——
# _try_register_vtable_ondemand 只注册元数据不具化 body,若此时 struct # _try_register_vtable_ondemand 只注册元数据不具化 body,若此时 struct
# 仍 opaque,下方 GEP [0,0] 取 vtable 指针会抛 llvmlite 裸 TypeError # 仍 opaque,下方 GEP [0,0] 取 vtable 指针会抛 llvmlite 裸 TypeError
# (典型:list[AST|t.CPtr].append 中 self.__pool__.alloc(...), # (典型:list[AST|CPtr].append 中 self.__pool__.alloc(...),
# __pool__ 类型 memhub.MemManager|t.CPtr,MemManager 已进 vtable 集合 # __pool__ 类型 memhub.MemManager|CPtr,MemManager 已进 vtable 集合
# 但 struct body 未从 stub 具化)。 # 但 struct body 未从 stub 具化)。
# 此处先主动具化(stub + class_members 双路径),仍失败则 fail-fast # 此处先主动具化(stub + class_members 双路径),仍失败则 fail-fast
# 暴露上游 stub 加载时序问题,而非静默崩溃。 # 暴露上游 stub 加载时序问题,而非静默崩溃。
@@ -4182,7 +4069,7 @@ class ExprCallHandle(BaseHandle):
offset = Gen._get_member_offset(len_member, bare_cls) offset = Gen._get_member_offset(len_member, bare_cls)
len_ptr = Gen.builder.gep(self_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=f"self_{len_member}_ptr") len_ptr = Gen.builder.gep(self_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=f"self_{len_member}_ptr")
return Gen._load(len_ptr, name=f"self_{len_member}") return Gen._load(len_ptr, name=f"self_{len_member}")
# 修复 stdint.vp 崩溃(0xC0000005)根因:`list[X] | t.CPtr` 联合字段 # 修复 stdint.vp 崩溃(0xC0000005)根因:`list[X] | CPtr` 联合字段
# 的 LLVM 类型退化为 i8*,_HandleLenLlvm 无法识别为 list,fall through # 的 LLVM 类型退化为 i8*,_HandleLenLlvm 无法识别为 list,fall through
# 到 strlen 分支 → 对 list 对象指针执行 strlen → 垃圾长度 → 越界 get # 到 strlen 分支 → 对 list 对象指针执行 strlen → 垃圾长度 → 越界 get
# → 垃圾指针 → strcmp 崩。此处按字段静态类型(class_member_element_class # → 垃圾指针 → strcmp 崩。此处按字段静态类型(class_member_element_class
@@ -4307,21 +4194,21 @@ class ExprCallHandle(BaseHandle):
规则本体在 SymbolUtils.ResolveTypeArgStr(定义端/声明端唯一规则源, 规则本体在 SymbolUtils.ResolveTypeArgStr(定义端/声明端唯一规则源,
声明端 DeclarationGenerator 的泛型分支亦调用同一函数),此处仅注入 声明端 DeclarationGenerator 的泛型分支亦调用同一函数),此处仅注入
翻译器上下文: 翻译器上下文:
- t/c 导入别名表(from t import CInt as myint → 't.CInt') - t/c 导入别名表(from t import CInt as myint → 'CInt')
- 跨模块结构体 SHA1 表(ast.Name/Attribute 命中 → '{sha1}.{名}',与普通签名一致) - 跨模块结构体 SHA1 表(ast.Name/Attribute 命中 → '{sha1}.{名}',与普通签名一致)
""" """
Gen = self.Trans.LlvmGen Gen = self.Trans.LlvmGen
StructSha1Map: dict[str, str] = getattr(Gen, '_struct_sha1_map', {}) if Gen is not None else {} StructSha1Map: dict[str, str] = getattr(Gen, '_struct_sha1_map', {}) if Gen is not None else {}
return ResolveTypeArgStr( return ResolveTypeArgStr(
node, node,
TCAliasMap=getattr(self.Trans, '_t_c_imported_names', {}), TCAliasMap=getattr(self.Trans, '_from_import_aliases', {}),
StructSha1Map=StructSha1Map) StructSha1Map=StructSha1Map)
def _get_raw_type_name(self, node: ast.AST) -> str: def _get_raw_type_name(self, node: ast.AST) -> str:
"""获取类型节点的原始名称(不带模块前缀),用于泛型 T 替换。 """获取类型节点的原始名称(不带模块前缀),用于泛型 T 替换。
ast.Name → sn.id (如 'AST', 'CInt') ast.Name → sn.id (如 'AST', 'CInt')
ast.Attribute → sn.attr (如 t.CInt → 'CInt') ast.Attribute → sn.attr (如 CInt → 'CInt')
ast.BinOp → 左侧的原始名称 (如 AST | CPtr → 'AST') ast.BinOp → 左侧的原始名称 (如 AST | CPtr → 'AST')
""" """
if isinstance(node, ast.Name): if isinstance(node, ast.Name):
@@ -4336,14 +4223,14 @@ class ExprCallHandle(BaseHandle):
"""解析泛型 slice 中的单个类型参数节点,返回 (type_arg, type_name) 或 None。 """解析泛型 slice 中的单个类型参数节点,返回 (type_arg, type_name) 或 None。
type_arg: 用于 mangling,走**唯一规则源** _resolve_type_arg_str type_arg: 用于 mangling,走**唯一规则源** _resolve_type_arg_str
(内层与参数注解同解析:'AST | t.CPtr' / 'rawptr[AST]' → (内层与参数注解同解析:'AST | CPtr' / 'rawptr[AST]' →
'{sha1}.AST*'、裸类名 'AST' → '{sha1}.AST'、标量按 '{sha1}.AST*'、裸类名 'AST' → '{sha1}.AST'、标量按
NormalizeGenericArgName 归一) NormalizeGenericArgName 归一)
type_name: 用于替换泛型类型参数 T(原始源码名,如 'AST' / 'CInt', type_name: 用于替换泛型类型参数 T(原始源码名,如 'AST' / 'CInt',
_specialize_generic_class 会自动给类名加 | t.CPtr) _specialize_generic_class 会自动给类名加 | CPtr)
指针下标 rawptr[T] 先折叠成等价的 `T | t.CPtr` 再解析, 指针下标 rawptr[T] 先折叠成等价的 `T | CPtr` 再解析,
与源码联合写法得到同一 (type_arg, type_name):否则 list[rawptr[ast.AST]] 与源码联合写法得到同一 (type_arg, type_name):否则 list[rawptr[ast.AST]]
会拼出 'rawptr[ast.AST]' 实参串(内层未混淆)→ 与 list[ast.AST | t.CPtr] 会拼出 'rawptr[ast.AST]' 实参串(内层未混淆)→ 与 list[ast.AST | CPtr]
的 '<sha1>.AST*' 分裂成两个特化名(结构体/方法声明/调用点三端不一致)。 的 '<sha1>.AST*' 分裂成两个特化名(结构体/方法声明/调用点三端不一致)。
""" """
if IsPtrSubscriptNode(sn, self.Trans.SymbolTable): if IsPtrSubscriptNode(sn, self.Trans.SymbolTable):
@@ -4353,16 +4240,14 @@ class ExprCallHandle(BaseHandle):
# `list[X]`/`rawptr[X]` 内层收敛到同一名字); # `list[X]`/`rawptr[X]` 内层收敛到同一名字);
# type_name 保留源码名供 T 替换与内建/类类型判定(两张表收拢在 SymbolUtils) # type_name 保留源码名供 T 替换与内建/类类型判定(两张表收拢在 SymbolUtils)
return (self._resolve_type_arg_str(sn), GenericArgRawName(sn.id)) return (self._resolve_type_arg_str(sn), GenericArgRawName(sn.id))
# BinOp (如 AST | CPtr) 或 Attribute (如 t.CPtr / t.CInt) # BinOp (如 AST | CPtr) 或 Attribute (如 mod.CInt)
type_str: str = self._resolve_type_arg_str(sn) type_str: str = self._resolve_type_arg_str(sn)
# type_name 保留模块前缀(如 't.CUnsignedChar'),避免 T(0) 替换为 # type_name 保留源码名(如 'CUnsignedChar'),避免 T(0) 替换为
# CUnsignedChar(0) 后因 CUnsignedChar 不在顶层作用域而报 # CUnsignedChar(0) 后因 CUnsignedChar 不在顶层作用域而报
# "Undefined function: 'CUnsignedChar'"。 # "Undefined function: 'CUnsignedChar'"。
# t.CPtr 特殊处理:保留 't.CPtr' 带前缀(2026-08-19 根修:此前裸 # CPtr 同样保留 'CPtr':作为 type_map['T'] 替换进模板(item: T →
# 'CPtr' 作为 type_map['T'] 替换进模板(item: T → item: CPtr)时, # item: CPtr)时需要可解析;指针参数识别由 _BUILTIN_TYPE_NAMES 的
# CPtr 不在顶层作用域 → 方法声明注册失败 → "Undefined method # tn_bare 检测('CPtr'→'CPtr')。
# 'append' in class 'list[CPtr]'"。带前缀 't.CPtr' 可解析。
# 指针参数识别改由 _BUILTIN_TYPE_NAMES 的 tn_bare 检测('t.CPtr'→'CPtr')。
if isinstance(sn, ast.Attribute) and isinstance(sn.value, ast.Name): if isinstance(sn, ast.Attribute) and isinstance(sn.value, ast.Name):
raw_name: str = f'{sn.value.id}.{sn.attr}' raw_name: str = f'{sn.value.id}.{sn.attr}'
else: else:
@@ -4371,9 +4256,7 @@ class ExprCallHandle(BaseHandle):
@staticmethod @staticmethod
def _IsCPtrMark(Node: ast.AST) -> bool: def _IsCPtrMark(Node: ast.AST) -> bool:
"""`t.CPtr` / 裸名 `CPtr` 标记节点。""" """判断节点是否为 `CPtr` 标记(裸名)。"""
if isinstance(Node, ast.Attribute):
return Node.attr == 'CPtr'
if isinstance(Node, ast.Name): if isinstance(Node, ast.Name):
return Node.id == 'CPtr' return Node.id == 'CPtr'
return False return False
@@ -4381,8 +4264,8 @@ class ExprCallHandle(BaseHandle):
def _CallReturnClass(self, Node: ast.Call, Gen: LlvmGeneratorMixin) -> str | None: def _CallReturnClass(self, Node: ast.Call, Gen: LlvmGeneratorMixin) -> str | None:
"""调用结果的**被指类名**:从被调者的返回注解恢复。 """调用结果的**被指类名**:从被调者的返回注解恢复。
背景:`list[str]*` ≡ `list[str] | t.CPtr`(只读探针已确认二者 AST 逐字同形, 背景:`list[str]*` ≡ `list[str] | CPtr`(只读探针已确认二者 AST 逐字同形,
都是 `BinOp(BitOr, Subscript(...), Attribute(t.CPtr))`)这类返回注解在 LLVM 层 都是 `BinOp(BitOr, Subscript(...), Attribute(CPtr))`)这类返回注解在 LLVM 层
被映射成通用指针 `i8*`,类名随之丢失 ⇒ 调用点只能按通用指针处理 被映射成通用指针 `i8*`,类名随之丢失 ⇒ 调用点只能按通用指针处理
(`parts = s1.split(',')` 之后 `parts[0]` 退化成按字节索引、得到整数,赋给 (`parts = s1.split(',')` 之后 `parts[0]` 退化成按字节索引、得到整数,赋给
`str` 时报"整数隐式转指针已禁止",真因在 4 行之前)。 `str` 时报"整数隐式转指针已禁止",真因在 4 行之前)。
@@ -4414,11 +4297,11 @@ class ExprCallHandle(BaseHandle):
return None return None
def _ClassFromAnnotation(self, Ann: ast.AST, Gen: LlvmGeneratorMixin) -> str | None: def _ClassFromAnnotation(self, Ann: ast.AST, Gen: LlvmGeneratorMixin) -> str | None:
"""从注解恢复"类名(含泛型特化名)":剔除 `| t.CPtr` 侧与指针层后取核类型。 """从注解恢复"类名(含泛型特化名)":剔除 `| CPtr` 侧与指针层后取核类型。
- `list[str] | t.CPtr` / `list[str]*` → `list[str]`(泛型特化名,与 - `list[str] | CPtr` / `list[str]*` → `list[str]`(泛型特化名,与
HandlesAnnAssign:1012-1034 的构名方式一致); HandlesAnnAssign:1012-1034 的构名方式一致);
- `Foo | t.CPtr` / `Foo*` → `Foo`; - `Foo | CPtr` / `Foo*` → `Foo`;
- 核类型名必须能在 `Gen.structs` / `Gen.class_members` 命中(含 sha1 前缀 - 核类型名必须能在 `Gen.structs` / `Gen.class_members` 命中(含 sha1 前缀
全名的短名归一),否则返回 None(类型信息不完整时不硬塞名字)。 全名的短名归一),否则返回 None(类型信息不完整时不硬塞名字)。
""" """
@@ -4502,7 +4385,7 @@ class ExprCallHandle(BaseHandle):
f"泛型类注解 '{ast.unparse(Sub)}' 无法解析全部类型实参:" f"泛型类注解 '{ast.unparse(Sub)}' 无法解析全部类型实参:"
f"需要 {len(type_param_names)} 个,仅解析出 {len(type_args)} 个;" f"需要 {len(type_param_names)} 个,仅解析出 {len(type_args)} 个;"
f"禁止按 int 兜底。") f"禁止按 int 兜底。")
# 类型注解解析(如 Float64Array: t.CTypedef = ndarray[t.CDouble]) # 类型注解解析(如 Float64Array: CTypedef = ndarray[CDouble])
# 只需 struct 定义,不需方法体;使用 declare_only=True 避免过早触发 # 只需 struct 定义,不需方法体;使用 declare_only=True 避免过早触发
# 完整特化(此时被引用的函数如 printf 可能尚未由 from X import Y 注册, # 完整特化(此时被引用的函数如 printf 可能尚未由 from X import Y 注册,
# 导致 "Undefined function" 错误)。完整特化由后续类实例化 # 导致 "Undefined function" 错误)。完整特化由后续类实例化
@@ -4512,9 +4395,9 @@ class ExprCallHandle(BaseHandle):
@staticmethod @staticmethod
def _AnnotationContainsCPtr(Node: ast.AST) -> bool: def _AnnotationContainsCPtr(Node: ast.AST) -> bool:
"""检查类型注解 AST 是否包含 t.CPtr(即是否为指针类型)""" """检查类型注解 AST 是否包含 CPtr(即是否为指针类型)"""
if isinstance(Node, ast.Attribute): if isinstance(Node, ast.Name):
if Node.attr == 'CPtr': if Node.id == 'CPtr':
return True return True
if isinstance(Node, ast.BinOp) and isinstance(Node.op, ast.BitOr): if isinstance(Node, ast.BinOp) and isinstance(Node.op, ast.BitOr):
return (ExprCallHandle._AnnotationContainsCPtr(Node.left) return (ExprCallHandle._AnnotationContainsCPtr(Node.left)
@@ -4558,17 +4441,17 @@ class ExprCallHandle(BaseHandle):
elif isinstance(Node, ast.Attribute): elif isinstance(Node, ast.Attribute):
type_name = Node.attr type_name = Node.attr
elif isinstance(Node, ast.BinOp) and isinstance(Node.op, ast.BitOr): elif isinstance(Node, ast.BinOp) and isinstance(Node.op, ast.BitOr):
# 联合类型(如 X | t.CPtr):VPC 注解中 | = and,带 t.CPtr 的联合 # 联合类型(如 X | CPtr):VPC 注解中 | = and,带 CPtr 的联合
# 是指针类型(X* 或 i8*),sizeof = 8(指针大小)。 # 是指针类型(X* 或 i8*),sizeof = 8(指针大小)。
# list[T].__init__ 的 T.__sizeof__() 特化后 T 被还原为 'X | t.CPtr' # list[T].__init__ 的 T.__sizeof__() 特化后 T 被还原为 'X | CPtr'
# (_make_replacement_node),此前落到 else 返回 0 → elem_size=0 → # (_make_replacement_node),此前落到 else 返回 0 → elem_size=0 →
# 所有元素存取同槽(get(0)==get(1),list[对象] join 误报根因)。 # 所有元素存取同槽(get(0)==get(1),list[对象] join 误报根因)。
if _BinOpContainsCPtr(Node): if _BinOpContainsCPtr(Node):
return ir.Constant(ir.IntType(64), 8) return ir.Constant(ir.IntType(64), 8)
# 不带 t.CPtr 的联合(A | B)无法确定尺寸:曾静默返回 0 → # 不带 CPtr 的联合(A | B)无法确定尺寸:曾静默返回 0 →
# 下游 elem_size=0 → alloc(0) 返回 NULL / 所有元素存取同槽。fail-fast。 # 下游 elem_size=0 → alloc(0) 返回 NULL / 所有元素存取同槽。fail-fast。
raise ValueError( raise ValueError(
f"[FATAL][__sizeof__] 联合类型 '{ast.unparse(Node)}' 不含 t.CPtr," f"[FATAL][__sizeof__] 联合类型 '{ast.unparse(Node)}' 不含 CPtr,"
f"无法确定尺寸,拒绝静默返回 0(会导致 alloc(0)/元素同槽)" f"无法确定尺寸,拒绝静默返回 0(会导致 alloc(0)/元素同槽)"
) )
else: else:
@@ -4604,10 +4487,10 @@ class ExprCallHandle(BaseHandle):
size_bits = getattr(ctype_inst, 'Size', 0) or 0 size_bits = getattr(ctype_inst, 'Size', 0) or 0
size_bytes = size_bits // 8 size_bytes = size_bits // 8
# POINTER 类型(CPtr 等)Size 为 None/0 → 指针大小 8。 # POINTER 类型(CPtr 等)Size 为 None/0 → 指针大小 8。
# 根因:t.CPtr.__sizeof__() 返回 0 → list[t.CPtr] # 根因:CPtr.__sizeof__() 返回 0 → list[CPtr]
# elem_size=0 → append 全写同槽/alloc(0) → 崩溃。 # elem_size=0 → append 全写同槽/alloc(0) → 崩溃。
if getattr(ctype_inst, 'HasPosition', None) \ if getattr(ctype_inst, 'HasPosition', None) \
and ctype_inst.HasPosition(t.CType.POINTER) \ and ctype_inst.HasPosition(TypeSystem.CType.POINTER) \
and size_bytes == 0: and size_bytes == 0:
size_bytes = 8 size_bytes = 8
return ir.Constant(ir.IntType(64), size_bytes) return ir.Constant(ir.IntType(64), size_bytes)
@@ -4936,10 +4819,10 @@ class ExprCallHandle(BaseHandle):
return ir.Constant(ir.IntType(32), 0) return ir.Constant(ir.IntType(32), 0)
def _HandleCDerefAsLlvm(self, Node: ast.Call) -> ir.Value | None: def _HandleCDerefAsLlvm(self, Node: ast.Call) -> ir.Value | None:
"""c.DerefAs(p, v):bitcast **指针** p 到 typeof(v)* 后按值存 v(`*(T*(p)) = v`)。 """DerefAs(p, v):bitcast **指针** p 到 typeof(v)* 后按值存 v(`*(T*(p)) = v`)。
与 ViperC CallGenCBuiltin.translate_c_derefas 逐字同口径: 与 ViperC CallGenCBuiltin.translate_c_derefas 逐字同口径:
- 单参形式(len<2)是**解引用读取**(等同 c.Deref(p)); - 单参形式(len<2)是**解引用读取**(等同 Deref(p));
- 双参:p、v 均为指针且 p 的 pointee 是结构体且与 v 的 pointee **同一**时, - 双参:p、v 均为指针且 p 的 pointee 是结构体且与 v 的 pointee **同一**时,
按整对象拷贝(load v 指向的对象 + bitcast p + store);否则 bitcast p 到 按整对象拷贝(load v 指向的对象 + bitcast p + store);否则 bitcast p 到
typeof(v)* 后按值 store v。 typeof(v)* 后按值 store v。
@@ -5435,7 +5318,7 @@ class ExprCallHandle(BaseHandle):
obj_val = self.HandleExprLlvm(Node.value) obj_val = self.HandleExprLlvm(Node.value)
idx_val = self.HandleExprLlvm(Node.slice) idx_val = self.HandleExprLlvm(Node.slice)
if obj_val and idx_val: if obj_val and idx_val:
# 处理 obj_val 为 i8(整数)的情况:联合类型 | t.CPtr 降级后可能被 load 为 i8 # 处理 obj_val 为 i8(整数)的情况:联合类型 | CPtr 降级后可能被 load 为 i8
if isinstance(obj_val.type, ir.IntType) and obj_val.type.width == 8: if isinstance(obj_val.type, ir.IntType) and obj_val.type.width == 8:
obj_val = Gen.builder.inttoptr(obj_val, ir.PointerType(ir.IntType(8)), name=f"i8_to_ptr_{ClassName}") obj_val = Gen.builder.inttoptr(obj_val, ir.PointerType(ir.IntType(8)), name=f"i8_to_ptr_{ClassName}")
if self._is_char_pointer(obj_val): if self._is_char_pointer(obj_val):
+2 -2
View File
@@ -207,7 +207,7 @@ class ExprLambdaHandle(BaseHandle):
from lib.core.LLVMCG.FuncGen import FailFastError from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError( raise FailFastError(
f"指针隐式转整数已禁止:条件表达式两分支类型不一致({BodyVal.type} / {result_type});" f"指针隐式转整数已禁止:条件表达式两分支类型不一致({BodyVal.type} / {result_type});"
f"如需转换请显式 cast(如 t.CUInt64T(p) / t.CInt(p))" f"如需转换请显式 cast(如 CUInt64T(p) / CInt(p))"
f"{Gen._DescribeValueNode(Node.body)}" f"{Gen._DescribeValueNode(Node.body)}"
) )
Gen.builder.branch(MergeBB) Gen.builder.branch(MergeBB)
@@ -239,7 +239,7 @@ class ExprLambdaHandle(BaseHandle):
from lib.core.LLVMCG.FuncGen import FailFastError from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError( raise FailFastError(
f"指针隐式转整数已禁止:条件表达式两分支类型不一致({OrelseVal.type} / {result_type});" f"指针隐式转整数已禁止:条件表达式两分支类型不一致({OrelseVal.type} / {result_type});"
f"如需转换请显式 cast(如 t.CUInt64T(p) / t.CInt(p))" f"如需转换请显式 cast(如 CUInt64T(p) / CInt(p))"
f"{Gen._DescribeValueNode(Node.orelse)}" f"{Gen._DescribeValueNode(Node.orelse)}"
) )
Gen.builder.branch(MergeBB) Gen.builder.branch(MergeBB)
+1 -1
View File
@@ -365,7 +365,7 @@ class ExprOpsHandle(BaseHandle):
if RightVal: if RightVal:
ClassName: str | None = self.Trans.ExprHandler._get_var_class(Node.comparators[0], Gen) ClassName: str | None = self.Trans.ExprHandler._get_var_class(Node.comparators[0], Gen)
if ClassName and Gen._has_function(f'{ClassName}.__contains__'): if ClassName and Gen._has_function(f'{ClassName}.__contains__'):
# 处理 RightVal 为 i8(整数)的情况:联合类型 | t.CPtr 降级后可能被 load 为 i8 # 处理 RightVal 为 i8(整数)的情况:联合类型 | CPtr 降级后可能被 load 为 i8
if isinstance(RightVal.type, ir.IntType) and RightVal.type.width == 8: if isinstance(RightVal.type, ir.IntType) and RightVal.type.width == 8:
RightVal = Gen.builder.inttoptr(RightVal, ir.PointerType(ir.IntType(8)), name=f"i8_to_ptr_{ClassName}") RightVal = Gen.builder.inttoptr(RightVal, ir.PointerType(ir.IntType(8)), name=f"i8_to_ptr_{ClassName}")
if isinstance(RightVal.type, ir.PointerType) and isinstance(RightVal.type.pointee, ir.IntType) and RightVal.type.pointee.width == 8: if isinstance(RightVal.type, ir.PointerType) and isinstance(RightVal.type.pointee, ir.IntType) and RightVal.type.pointee.width == 8:
+5 -11
View File
@@ -5,9 +5,6 @@ if TYPE_CHECKING:
from lib.core.LlvmCodeGenerator import LlvmCodeGenerator from lib.core.LlvmCodeGenerator import LlvmCodeGenerator
import vast as ast import vast as ast
import llvmlite.ir as ir import llvmlite.ir as ir
from lib.core.SymbolUtils import IsTModule
class ExprUtils: class ExprUtils:
def __init__(self, translator: "Translator") -> None: def __init__(self, translator: "Translator") -> None:
self.Trans: Translator = translator self.Trans: Translator = translator
@@ -194,7 +191,7 @@ class ExprUtils:
if not Gen._has_function(FullMethodName): if not Gen._has_function(FullMethodName):
# 泛型特化 fallback:当 ClassName 是 opaque 基础名(如 'ndarray')且 # 泛型特化 fallback:当 ClassName 是 opaque 基础名(如 'ndarray')且
# 无直接匹配方法时,遍历 Gen.structs 查找以 'ClassName[' 开头的特化版本 # 无直接匹配方法时,遍历 Gen.structs 查找以 'ClassName[' 开头的特化版本
# (如 'ndarray[double]')。注解 'numpy.ndarray | t.CPtr' 未指定类型参数时, # (如 'ndarray[double]')。注解 'numpy.ndarray | CPtr' 未指定类型参数时,
# var_struct_class 仅记录裸模板名,但方法只在特化版本中定义。 # var_struct_class 仅记录裸模板名,但方法只在特化版本中定义。
# 选择策略:优先选 obj_val.type.pointee 实际匹配的特化;否则选第一个有方法的特化。 # 选择策略:优先选 obj_val.type.pointee 实际匹配的特化;否则选第一个有方法的特化。
if '[' not in ClassName: if '[' not in ClassName:
@@ -393,13 +390,10 @@ class ExprUtils:
return ir.IntType(32) return ir.IntType(32)
if func_name == 'float' or func_name == 'double': if func_name == 'float' or func_name == 'double':
return ir.DoubleType() return ir.DoubleType()
elif isinstance(node.func, ast.Attribute): if func_name == 'Deref':
if isinstance(node.func.value, ast.Name) and node.func.value.id == 'c': return ir.IntType(64)
if node.func.attr == 'Deref': if func_name == 'CChar':
return ir.IntType(64) return ir.PointerType(ir.IntType(8))
if isinstance(node.func.value, ast.Name) and IsTModule(node.func.value.id, self.Trans.SymbolTable):
if node.func.attr == 'CChar':
return ir.PointerType(ir.IntType(8))
return ir.IntType(32) return ir.IntType(32)
elif isinstance(node, ast.Compare): elif isinstance(node, ast.Compare):
return ir.IntType(1) return ir.IntType(1)
+7 -11
View File
@@ -111,12 +111,10 @@ class ForHandle(BaseHandle):
if StepVal is None: if StepVal is None:
StepVal = ir.Constant(EndVal.type, 1) StepVal = ir.Constant(EndVal.type, 1)
if not IsRange: if not IsRange:
# 检测 c.Addr(x) 模式:按原始变量类型迭代(for i64 in i64* 语义) # 检测 Addr(x) 模式:按原始变量类型迭代(for i64 in i64* 语义)
if (isinstance(Node.iter, ast.Call) if (isinstance(Node.iter, ast.Call)
and isinstance(Node.iter.func, ast.Attribute) and isinstance(Node.iter.func, ast.Name)
and isinstance(Node.iter.func.value, ast.Name) and Node.iter.func.id == 'Addr'
and Node.iter.func.value.id == 'c'
and Node.iter.func.attr == 'Addr'
and Node.iter.args): and Node.iter.args):
AddrArg: ast.expr = Node.iter.args[0] AddrArg: ast.expr = Node.iter.args[0]
if isinstance(AddrArg, ast.Name) and AddrArg.id in Gen.variables: if isinstance(AddrArg, ast.Name) and AddrArg.id in Gen.variables:
@@ -547,7 +545,7 @@ class ForHandle(BaseHandle):
def _HandleForPtrLlvm(self, Node: ast.For, PtrVal: ir.Value, ElemType: ir.IntType) -> None: def _HandleForPtrLlvm(self, Node: ast.For, PtrVal: ir.Value, ElemType: ir.IntType) -> None:
"""通用指针迭代:按 ElemType 大小逐元素迭代,终止条件为元素值 == 0 """通用指针迭代:按 ElemType 大小逐元素迭代,终止条件为元素值 == 0
适用于 for i in c.Addr(u) where u: i32/i64 等非 i8 整数类型。 适用于 for i in Addr(u) where u: i32/i64 等非 i8 整数类型。
""" """
Gen: "Translator.LlvmGen" = self.Trans.LlvmGen Gen: "Translator.LlvmGen" = self.Trans.LlvmGen
if not isinstance(Node.target, ast.Name): if not isinstance(Node.target, ast.Name):
@@ -750,12 +748,10 @@ class ForHandle(BaseHandle):
if isinstance(arg, ast.Call) and isinstance(arg.func, ast.Name) and arg.func.id == 'range': if isinstance(arg, ast.Call) and isinstance(arg.func, ast.Name) and arg.func.id == 'range':
return self._zip_setup_range(arg, target_name, Gen) return self._zip_setup_range(arg, target_name, Gen)
# Case 2: c.Addr(x) — 指针/数组迭代 # Case 2: Addr(x) — 指针/数组迭代
if (isinstance(arg, ast.Call) if (isinstance(arg, ast.Call)
and isinstance(arg.func, ast.Attribute) and isinstance(arg.func, ast.Name)
and isinstance(arg.func.value, ast.Name) and arg.func.id == 'Addr'
and arg.func.value.id == 'c'
and arg.func.attr == 'Addr'
and arg.args): and arg.args):
AddrArg: ast.expr = arg.args[0] AddrArg: ast.expr = arg.args[0]
if isinstance(AddrArg, ast.Name) and AddrArg.id in Gen.variables: if isinstance(AddrArg, ast.Name) and AddrArg.id in Gen.variables:
+133 -145
View File
@@ -9,25 +9,25 @@ import traceback
import llvmlite.ir as ir import llvmlite.ir as ir
from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta
from lib.core.SymbolUtils import ( from lib.core.SymbolUtils import (
IsTModule, FindStructNameInAnnotationWithContext, AnnotationContainsName, FindStructNameInAnnotationWithContext, AnnotationContainsName,
IsPtrSubscriptNode, DesugarPtrSubscriptToUnion, FindAutoAddrMode) IsPtrSubscriptNode, DesugarPtrSubscriptToUnion, FindAutoAddrMode)
from lib.core.VLogger import get_logger as _vlog from lib.core.VLogger import get_logger as _vlog
from lib.constants.config import mode as _config_mode from lib.constants.config import mode as _config_mode
from lib.includes import t from lib.core import TypeSystem
from lib.includes.t import CTypeRegistry from lib.core.TypeSystem import CTypeRegistry
# t 模块存储类标记装饰器名称集合 # 内建存储类标记装饰器名称集合
_T_STORAGE_DECORATORS = frozenset({'CExport', 'CExtern', 'CStatic', 'State', 'CInline', 'TLS'}) _T_STORAGE_DECORATORS = frozenset({'CExport', 'CExtern', 'CStatic', 'State', 'CInline', 'TLS'})
# `@c.CReturn` 装饰器已移除;任何地方遇到都必须 fail-fast,不得静默忽略或改写。 # `@CReturn` 装饰器已移除;任何地方遇到都必须 fail-fast,不得静默忽略或改写。
_CRETURN_REMOVED_HINT: str = ( _CRETURN_REMOVED_HINT: str = (
"`@c.CReturn` 已移除:请改用返回注解 `-> tuple[ty1, ty2, ...]`(多返回值打包为 struct)" "`@CReturn` 已移除:请改用返回注解 `-> tuple[ty1, ty2, ...]`(多返回值打包为 struct)"
) )
def _RejectCReturnDecorator(node: ast.AST, decorators: list[ast.AST]) -> None: def _RejectCReturnDecorator(node: ast.AST, decorators: list[ast.AST]) -> None:
"""扫到 `@c.CReturn` 装饰器即 fail-fast 报错(该装饰器已移除)。""" """扫到 `@CReturn` 装饰器即 fail-fast 报错(该装饰器已移除)。"""
for decorator in decorators: for decorator in decorators:
if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute): if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute):
if decorator.func.attr == 'CReturn': if decorator.func.attr == 'CReturn':
@@ -53,9 +53,9 @@ def _RejectRefReturnAnnotation(node: ast.AST) -> None:
def _IsVoidOrDeclAnnotation(Annot: ast.AST) -> bool: def _IsVoidOrDeclAnnotation(Annot: ast.AST) -> bool:
"""判断函数返回注解是否为 void 或 extern/export 声明型辅助符号。 """判断函数返回注解是否为 void 或 extern/export 声明型辅助符号。
void:None / t.CVoid,含 `|` 联合形式(注解中 `|` 表示 and), void:None / CVoid,含 `|` 联合形式(注解中 `|` 表示 and),
如 `-> t.CVoid | t.CExport`(sprintf 先例)→ 掉出末尾 ret void 合法。 如 `-> CVoid | CExport`(sprintf 先例)→ 掉出末尾 ret void 合法。
声明型辅助符号:t.State(extern)/ t.CExport(export)/ t.CExtern—— 声明型辅助符号:State(extern)/ CExport(export)/ CExtern——
此类函数返回注解被改写为 `<原类型> | 辅助符号` 且 body 为空(extern 声明), 此类函数返回注解被改写为 `<原类型> | 辅助符号` 且 body 为空(extern 声明),
掉出末尾是正常形态,必须豁免 fail-fast。 掉出末尾是正常形态,必须豁免 fail-fast。
""" """
@@ -71,9 +71,9 @@ def _IsVoidOrDeclAnnotation(Annot: ast.AST) -> bool:
def _IsVoidOrDeclAnnotation(Annot: ast.AST) -> bool: def _IsVoidOrDeclAnnotation(Annot: ast.AST) -> bool:
"""判断函数返回注解是否为 void 或 extern/export 声明型辅助符号。 """判断函数返回注解是否为 void 或 extern/export 声明型辅助符号。
void:None / t.CVoid,含 `|` 联合形式(注解中 `|` 表示 and), void:None / CVoid,含 `|` 联合形式(注解中 `|` 表示 and),
如 `-> t.CVoid | t.CExport`(sprintf 先例)→ 掉出末尾 ret void 合法。 如 `-> CVoid | CExport`(sprintf 先例)→ 掉出末尾 ret void 合法。
声明型辅助符号:t.State(extern)/ t.CExport(export)/ t.CExtern—— 声明型辅助符号:State(extern)/ CExport(export)/ CExtern——
此类函数返回注解被改写为 `<原类型> | 辅助符号` 且 body 为空(extern 声明), 此类函数返回注解被改写为 `<原类型> | 辅助符号` 且 body 为空(extern 声明),
掉出末尾是正常形态,必须豁免 fail-fast。 掉出末尾是正常形态,必须豁免 fail-fast。
""" """
@@ -114,10 +114,10 @@ class FunctionHandle(BaseHandle):
return meta return meta
def _extract_decorator_storage_flags(self, Node: ast.FunctionDef) -> dict[str, bool]: def _extract_decorator_storage_flags(self, Node: ast.FunctionDef) -> dict[str, bool]:
"""从装饰器列表中提取 t 模块存储类标记 """从装饰器列表中提取内建存储类标记
支持 @t.CExport, @t.CExtern, @t.CStatic, @t.State, @t.CInline 支持 @CExport, @CExtern, @CStatic, @State, @CInline
也支持 from t import CExport 等别名形式 内建标记按裸名书写,如 @CExport。
Returns: Returns:
dict with keys: 'is_export', 'is_extern', 'is_static', 'is_state', 'is_inline' dict with keys: 'is_export', 'is_extern', 'is_static', 'is_state', 'is_inline'
@@ -131,16 +131,12 @@ class FunctionHandle(BaseHandle):
symtab: object = self.Trans.SymbolTable symtab: object = self.Trans.SymbolTable
for decorator in Node.decorator_list: for decorator in Node.decorator_list:
attr_name: str | None = None attr_name: str | None = None
# @t.CExport 形式 # 内建标记按裸名书写(@CExport / @CStatic / ...)
if isinstance(decorator, ast.Attribute) and isinstance(decorator.value, ast.Name): if isinstance(decorator, ast.Name):
if IsTModule(decorator.value.id, symtab): cls: type | None = getattr(TypeSystem, decorator.id, None)
attr_name = decorator.attr if cls is None and hasattr(symtab, '_builtin_type_symbols'):
# @CExport 形式 (from t import CExport) cls = symtab._builtin_type_symbols.get(decorator.id)
elif isinstance(decorator, ast.Name): if cls is not None and isinstance(cls, type) and issubclass(cls, TypeSystem.CType):
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__ attr_name = cls.__name__
if attr_name and attr_name in _T_STORAGE_DECORATORS: if attr_name and attr_name in _T_STORAGE_DECORATORS:
if attr_name == 'CExport': if attr_name == 'CExport':
@@ -157,18 +153,15 @@ class FunctionHandle(BaseHandle):
@staticmethod @staticmethod
def _is_t_storage_decorator(decorator: ast.AST, symtab: object) -> bool: def _is_t_storage_decorator(decorator: ast.AST, symtab: object) -> bool:
"""检查装饰器是否是 t 模块存储类标记(用于排除 behavior_decorators)""" """检查装饰器是否是内建存储类标记(用于排除 behavior_decorators)"""
attr_name: str | None = None attr_name: str | None = None
if isinstance(decorator, ast.Attribute) and isinstance(decorator.value, ast.Name): if isinstance(decorator, ast.Name):
if IsTModule(decorator.value.id, symtab): cls: type | None = getattr(TypeSystem, decorator.id, None)
attr_name = decorator.attr if cls is None and hasattr(symtab, '_builtin_type_symbols'):
elif isinstance(decorator, ast.Name): cls = symtab._builtin_type_symbols.get(decorator.id)
cls: type | None = getattr(t, decorator.id, None) if cls is not None and isinstance(cls, type) and issubclass(cls, TypeSystem.CType):
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__ attr_name = cls.__name__
elif decorator.id in _T_STORAGE_DECORATORS and hasattr(t, decorator.id): elif decorator.id in _T_STORAGE_DECORATORS and hasattr(TypeSystem, decorator.id):
# TLS 是普通函数标记,不是 CType 子类 # TLS 是普通函数标记,不是 CType 子类
attr_name = decorator.id attr_name = decorator.id
return attr_name in _T_STORAGE_DECORATORS if attr_name else False return attr_name in _T_STORAGE_DECORATORS if attr_name else False
@@ -335,9 +328,7 @@ class FunctionHandle(BaseHandle):
if not isinstance(value, ast.Attribute) or value.attr != 'llvm': if not isinstance(value, ast.Attribute) or value.attr != 'llvm':
return None return None
inner: ast.AST = value.value inner: ast.AST = value.value
if not isinstance(inner, ast.Attribute) or inner.attr != 'attr': if not isinstance(inner, ast.Name) or inner.id != 'attr':
return None
if not isinstance(inner.value, ast.Name) or inner.value.id != 't':
return None return None
return node.attr return node.attr
@@ -507,7 +498,7 @@ class FunctionHandle(BaseHandle):
var_info: Any = self.Trans.SymbolTable.lookup(var_name) var_info: Any = self.Trans.SymbolTable.lookup(var_name)
if var_info and isinstance(var_info, dict): if var_info and isinstance(var_info, dict):
var_type: str = var_info.get('type', '') var_type: str = var_info.get('type', '')
if var_type.startswith('list[') or var_type.startswith('List[') or var_type.startswith('t.CArray['): if var_type.startswith('list[') or var_type.startswith('List[') or var_type.startswith('CArray['):
inner: str = var_type[var_type.index('[') + 1:var_type.rindex(']')] inner: str = var_type[var_type.index('[') + 1:var_type.rindex(']')]
parts: list[str] = inner.split(',') parts: list[str] = inner.split(',')
elem_type_str: str = parts[0].strip() elem_type_str: str = parts[0].strip()
@@ -540,14 +531,14 @@ class FunctionHandle(BaseHandle):
if Node.returns: if Node.returns:
if MultiRetTypes: if MultiRetTypes:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CVoid() ReturnTypeInfo.BaseType = TypeSystem.CVoid()
else: else:
try: try:
if 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):
ReturnTypeInfo = getattr(self.Trans, 'TypeMergeHandler', None) and self.Trans.TypeMergeHandler.MergeTypes(Node.returns) ReturnTypeInfo = getattr(self.Trans, 'TypeMergeHandler', None) and self.Trans.TypeMergeHandler.MergeTypes(Node.returns)
if not isinstance(ReturnTypeInfo, CTypeInfo): if not isinstance(ReturnTypeInfo, CTypeInfo):
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CVoid() ReturnTypeInfo.BaseType = TypeSystem.CVoid()
if ((ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState) if ((ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState)
or (ReturnTypeInfo.PtrCount >= 2 and ReturnTypeInfo.BaseType is None)): or (ReturnTypeInfo.PtrCount >= 2 and ReturnTypeInfo.BaseType is None)):
def _FindNonVoidCTypeInfo(node: ast.AST) -> Any: def _FindNonVoidCTypeInfo(node: ast.AST) -> Any:
@@ -574,9 +565,9 @@ class FunctionHandle(BaseHandle):
ReturnTypeInfo = found ReturnTypeInfo = found
if ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState: if ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CInt() ReturnTypeInfo.BaseType = TypeSystem.CInt()
# define 宏函数(返回注解含 t.CDefine,如 `int | t.CDefine`): # define 宏函数(返回注解含 CDefine,如 `int | CDefine`):
# 标记为编译期内联宏(alwaysinline),对齐裸 `-> t.CDefine` 路径 # 标记为编译期内联宏(alwaysinline),对齐裸 `-> CDefine` 路径
# (合并路径丢失 IsDefine 时仍能命中) # (合并路径丢失 IsDefine 时仍能命中)
if AnnotationContainsName(Node.returns, 'CDefine'): if AnnotationContainsName(Node.returns, 'CDefine'):
if not hasattr(self, '_cdefine_funcs'): if not hasattr(self, '_cdefine_funcs'):
@@ -587,7 +578,7 @@ class FunctionHandle(BaseHandle):
if isinstance(Node.returns, ast.Name) and Node.returns.id in ('str', 'bytes'): if isinstance(Node.returns, ast.Name) and Node.returns.id in ('str', 'bytes'):
is_str_type = True is_str_type = True
# 走 ResolveAnnotationType 而非 CTypeInfo.FromNode:指针下标 # 走 ResolveAnnotationType 而非 CTypeInfo.FromNode:指针下标
# 返回注解(rawptr[T] / t.CPtr[T])需走 TypeMerge 通用解析, # 返回注解(rawptr[T] / CPtr[T])需走 TypeMerge 通用解析,
# 否则内层跨模块类解析不出 → CVoid/1(i8*)。 # 否则内层跨模块类解析不出 → CVoid/1(i8*)。
ReturnTypeInfo = self.ResolveAnnotationType(Node.returns) ReturnTypeInfo = self.ResolveAnnotationType(Node.returns)
if ReturnTypeInfo and ReturnTypeInfo.IsDefine: if ReturnTypeInfo and ReturnTypeInfo.IsDefine:
@@ -597,28 +588,28 @@ class FunctionHandle(BaseHandle):
ReturnTypeInfo.PtrCount = 1 if inferred[1] else 0 ReturnTypeInfo.PtrCount = 1 if inferred[1] else 0
else: else:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CInt() ReturnTypeInfo.BaseType = TypeSystem.CInt()
if not hasattr(self, '_cdefine_funcs'): if not hasattr(self, '_cdefine_funcs'):
self._cdefine_funcs = set() self._cdefine_funcs = set()
self._cdefine_funcs.add(FuncName) self._cdefine_funcs.add(FuncName)
elif ReturnTypeInfo and ReturnTypeInfo.IsState: elif ReturnTypeInfo and ReturnTypeInfo.IsState:
if ReturnTypeInfo.PtrCount > 0 or (ReturnTypeInfo.BaseType and not isinstance(ReturnTypeInfo.BaseType, t.CVoid)): if ReturnTypeInfo.PtrCount > 0 or (ReturnTypeInfo.BaseType and not isinstance(ReturnTypeInfo.BaseType, TypeSystem.CVoid)):
pass pass
else: else:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CVoid() ReturnTypeInfo.BaseType = TypeSystem.CVoid()
if ReturnTypeInfo is None: if ReturnTypeInfo is None:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CVoid() ReturnTypeInfo.BaseType = TypeSystem.CVoid()
# 仅指针层数 <=1 才算裸 str/bytes(i8*)。 # 仅指针层数 <=1 才算裸 str/bytes(i8*)。
# `str | t.CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),不能压平。 # `str | CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),不能压平。
if is_str_type or (ReturnTypeInfo.IsStr and ReturnTypeInfo.PtrCount <= 1): if is_str_type or (ReturnTypeInfo.IsStr and ReturnTypeInfo.PtrCount <= 1):
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CChar() ReturnTypeInfo.BaseType = TypeSystem.CChar()
ReturnTypeInfo.PtrCount = 1 ReturnTypeInfo.PtrCount = 1
# 检查泛型类返回类型 (如 list[str]) # 检查泛型类返回类型 (如 list[str])
# 注意:_from_node_subscript 对未识别的泛型下标(如 list[str])返回空 CTypeInfo(BaseType=None), # 注意:_from_node_subscript 对未识别的泛型下标(如 list[str])返回空 CTypeInfo(BaseType=None),
# 此时 IsVoid 为 False(因为 IsVoid 仅检查 t.CVoid 实例),需额外检测 BaseType is None # 此时 IsVoid 为 False(因为 IsVoid 仅检查 CVoid 实例),需额外检测 BaseType is None
if (isinstance(Node.returns, ast.Subscript) if (isinstance(Node.returns, ast.Subscript)
and isinstance(Node.returns.value, ast.Name) and isinstance(Node.returns.value, ast.Name)
and hasattr(self.Trans.ClassHandler, '_generic_class_templates') and hasattr(self.Trans.ClassHandler, '_generic_class_templates')
@@ -652,17 +643,17 @@ class FunctionHandle(BaseHandle):
ret_class, ret_type_args, Gen, type_names=ret_type_names, declare_only=True) ret_class, ret_type_args, Gen, type_names=ret_type_names, declare_only=True)
if spec_name2 and spec_name2 in Gen.structs: if spec_name2 and spec_name2 in Gen.structs:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CStruct(name=spec_name2) ReturnTypeInfo.BaseType = TypeSystem.CStruct(name=spec_name2)
ReturnTypeInfo.PtrCount = 1 ReturnTypeInfo.PtrCount = 1
if (ReturnTypeInfo.IsVoid or ReturnTypeInfo.BaseType is None) and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState: if (ReturnTypeInfo.IsVoid or ReturnTypeInfo.BaseType is None) and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CInt() ReturnTypeInfo.BaseType = TypeSystem.CInt()
except Exception: # 回退:设置默认返回类型为 CInt except Exception: # 回退:设置默认返回类型为 CInt
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CInt() ReturnTypeInfo.BaseType = TypeSystem.CInt()
else: else:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CInt() ReturnTypeInfo.BaseType = TypeSystem.CInt()
inferred: Any = self._infer_return_type_from_body(Node, Gen, ClassName) inferred: Any = self._infer_return_type_from_body(Node, Gen, ClassName)
if inferred: if inferred:
ReturnTypeInfo = CTypeInfo.FromTypeName(inferred[0]) ReturnTypeInfo = CTypeInfo.FromTypeName(inferred[0])
@@ -670,7 +661,7 @@ class FunctionHandle(BaseHandle):
IsPtr = ReturnTypeInfo.IsPtr if ReturnTypeInfo else False IsPtr = ReturnTypeInfo.IsPtr if ReturnTypeInfo else False
ReturnType: ir.Type = Gen._ctype_to_llvm(ReturnTypeInfo) ReturnType: ir.Type = Gen._ctype_to_llvm(ReturnTypeInfo)
# 此处原有 "Ptr(Ptr(Struct)) → Ptr(Struct)" 的压层(历史遗留):会把已解析的 # 此处原有 "Ptr(Ptr(Struct)) → Ptr(Struct)" 的压层(历史遗留):会把已解析的
# 多层指针返回类型(`-> rawptr[rawptr[X]]` / `-> X | t.CPtr | t.CPtr`) # 多层指针返回类型(`-> rawptr[rawptr[X]]` / `-> X | CPtr | CPtr`)
# 与泛型特化方法返回(`list[X**]` 的 get/pop/__getitem__/__next__)少算一层, # 与泛型特化方法返回(`list[X**]` 的 get/pop/__getitem__/__next__)少算一层,
# 与同函数的形参(`append(item: T)` 保留 `X**`)、声明端 # 与同函数的形参(`append(item: T)` 保留 `X**`)、声明端
# DeclarationGenerator._get_type_str 的 BinOp 分支(同样不压层,见 # DeclarationGenerator._get_type_str 的 BinOp 分支(同样不压层,见
@@ -703,14 +694,14 @@ class FunctionHandle(BaseHandle):
for i, ReturnTypeNode in enumerate(MultiRetTypes): for i, ReturnTypeNode in enumerate(MultiRetTypes):
ReturnTypeInfo = CTypeInfo.FromNode(ReturnTypeNode, self.Trans.SymbolTable) ReturnTypeInfo = CTypeInfo.FromNode(ReturnTypeNode, self.Trans.SymbolTable)
# 仅指针层数 <=1 才算裸 str/bytes(i8*)。 # 仅指针层数 <=1 才算裸 str/bytes(i8*)。
# `str | t.CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),不能压平。 # `str | CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),不能压平。
if ReturnTypeInfo and ReturnTypeInfo.IsStr and ReturnTypeInfo.PtrCount <= 1: if ReturnTypeInfo and ReturnTypeInfo.IsStr and ReturnTypeInfo.PtrCount <= 1:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CChar() ReturnTypeInfo.BaseType = TypeSystem.CChar()
ReturnTypeInfo.PtrCount = 1 ReturnTypeInfo.PtrCount = 1
if ReturnTypeInfo is None: if ReturnTypeInfo is None:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CInt() ReturnTypeInfo.BaseType = TypeSystem.CInt()
RetType: ir.Type = Gen._ctype_to_llvm(ReturnTypeInfo) RetType: ir.Type = Gen._ctype_to_llvm(ReturnTypeInfo)
MultiRetLlvmTypes.append(RetType) MultiRetLlvmTypes.append(RetType)
ReturnType = ir.LiteralStructType(MultiRetLlvmTypes) ReturnType = ir.LiteralStructType(MultiRetLlvmTypes)
@@ -727,20 +718,20 @@ class FunctionHandle(BaseHandle):
ParamTypeInfo = self.ResolveParamAnnotation(Arg.annotation) ParamTypeInfo = self.ResolveParamAnnotation(Arg.annotation)
if ParamTypeInfo is None: if ParamTypeInfo is None:
ParamTypeInfo = CTypeInfo() ParamTypeInfo = CTypeInfo()
ParamTypeInfo.BaseType = t.CInt() ParamTypeInfo.BaseType = TypeSystem.CInt()
IsPtr = ParamTypeInfo.IsPtr IsPtr = ParamTypeInfo.IsPtr
if ParamTypeInfo and getattr(ParamTypeInfo, 'IsCpythonObject', False) and not IsPtr: if ParamTypeInfo and getattr(ParamTypeInfo, 'IsCpythonObject', False) and not IsPtr:
IsPtr = True IsPtr = True
ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1) ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1)
# 仅当指针层数 <=1 时才压平为 i8*(裸 str/bytes)。 # 仅当指针层数 <=1 时才压平为 i8*(裸 str/bytes)。
# `str | t.CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组), # `str | CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),
# 不能压平,否则形参类型错误导致 _adjust_args 多 load 一层崩溃。 # 不能压平,否则形参类型错误导致 _adjust_args 多 load 一层崩溃。
if (ParamTypeInfo.IsStr and ParamTypeInfo.PtrCount <= 1) or (isinstance(Arg.annotation, ast.Name) and Arg.annotation.id in ('str', 'bytes')): if (ParamTypeInfo.IsStr and ParamTypeInfo.PtrCount <= 1) or (isinstance(Arg.annotation, ast.Name) and Arg.annotation.id in ('str', 'bytes')):
ParamTypeInfo = CTypeInfo() ParamTypeInfo = CTypeInfo()
ParamTypeInfo.BaseType = t.CChar() ParamTypeInfo.BaseType = TypeSystem.CChar()
ParamTypeInfo.PtrCount = 1 ParamTypeInfo.PtrCount = 1
IsPtr = True IsPtr = True
# C 语言中数组参数退化为指针:t.CArray[type, N] → type* # C 语言中数组参数退化为指针:CArray[type, N] → type*
if ParamTypeInfo.ArrayDims: if ParamTypeInfo.ArrayDims:
ParamTypeInfo.ArrayDims = [] ParamTypeInfo.ArrayDims = []
ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1) ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1)
@@ -751,7 +742,7 @@ class FunctionHandle(BaseHandle):
AnnStr: str = ast.unparse(Arg.annotation) if hasattr(ast, 'unparse') else str(Arg.annotation) AnnStr: str = ast.unparse(Arg.annotation) if hasattr(ast, 'unparse') else str(Arg.annotation)
raise SyntaxError( raise SyntaxError(
f"无法识别的参数类型注解: '{AnnStr}'(在函数 '{Node.name}' 的参数 '{Arg.arg}' 上)。" f"无法识别的参数类型注解: '{AnnStr}'(在函数 '{Node.name}' 的参数 '{Arg.arg}' 上)。"
f"请使用有效的 VPC 类型(如 t.CPtr、ast.AST 或已注册的结构体)。" f"请使用有效的 VPC 类型(如 CPtr、ast.AST 或已注册的结构体)。"
) )
ParamTypeStr: Any = ParamTypeInfo ParamTypeStr: Any = ParamTypeInfo
except SyntaxError: except SyntaxError:
@@ -759,7 +750,7 @@ class FunctionHandle(BaseHandle):
except Exception as e: except Exception as e:
ParamType = ir.IntType(32) ParamType = ir.IntType(32)
ParamTypeStr = CTypeInfo() ParamTypeStr = CTypeInfo()
ParamTypeStr.BaseType = t.CInt() ParamTypeStr.BaseType = TypeSystem.CInt()
else: else:
if ClassName and Arg.arg != 'self': if ClassName and Arg.arg != 'self':
op_method_names: list[str] = ['__add__', '__sub__', '__mul__', '__truediv__', '__floordiv__', '__mod__', '__pow__', op_method_names: list[str] = ['__add__', '__sub__', '__mul__', '__truediv__', '__floordiv__', '__mod__', '__pow__',
@@ -774,13 +765,13 @@ class FunctionHandle(BaseHandle):
else: else:
ParamType = ir.IntType(32) ParamType = ir.IntType(32)
ParamTypeStr = CTypeInfo() ParamTypeStr = CTypeInfo()
ParamTypeStr.BaseType = t.CInt() ParamTypeStr.BaseType = TypeSystem.CInt()
ParamTypes.append(ParamType) ParamTypes.append(ParamType)
ParamNames.append(Arg.arg) ParamNames.append(Arg.arg)
ParamTypeStrs.append(ParamTypeStr) ParamTypeStrs.append(ParamTypeStr)
# 自动取址模式(由注解读出,不依赖 BaseType 类型): # 自动取址模式(由注解读出,不依赖 BaseType 类型):
# 'ref' = &T、'temp' = &temp T(合成联合 T | t.CRef / t.CTempRef), # 'ref' = &T、'temp' = &temp T(合成联合 T | CRef / CTempRef),
# 'always' = t.CAutoPtr。经 Gen._auto_addr_params 供调用点分流。 # 'always' = CAutoPtr。经 Gen._auto_addr_params 供调用点分流。
auto_mode: str | None = FindAutoAddrMode(Arg.annotation) auto_mode: str | None = FindAutoAddrMode(Arg.annotation)
auto_addr_modes.append(auto_mode) auto_addr_modes.append(auto_mode)
if self._apply_struct_self_cls_types(ParamTypes, ParamNames, IsMethod, IsClassMethod, ResolvedClassName, Gen): if self._apply_struct_self_cls_types(ParamTypes, ParamNames, IsMethod, IsClassMethod, ResolvedClassName, Gen):
@@ -861,21 +852,21 @@ class FunctionHandle(BaseHandle):
def _make_replacement_node(self, replacement: str) -> ast.AST: def _make_replacement_node(self, replacement: str) -> ast.AST:
"""将 type_map 中的替换字符串转换为 AST 节点。 """将 type_map 中的替换字符串转换为 AST 节点。
mangled 名称如 '<sha1>.AST*' 需要还原为 AST | t.CPtr 结构, mangled 名称如 '<sha1>.AST*' 需要还原为 AST | CPtr 结构,
否则类型解析会丢失 PtrCount 信息。 否则类型解析会丢失 PtrCount 信息。
含点号的名称(如 '<sha1>.AST')需解析为 ast.Attribute 链。 含点号的名称(如 '<sha1>.AST')需解析为 ast.Attribute 链。
下标形态('rawptr[ast.AST]' / 'list[AST]' 等)必须整体解析为 Subscript: 下标形态('rawptr[ast.AST]' / 'list[AST]' 等)必须整体解析为 Subscript:
_make_name_node 只按 '.' 切分会把 'rawptr[ast.AST]' 拆成 _make_name_node 只按 '.' 切分会把 'rawptr[ast.AST]' 拆成
Name('rawptr[ast') + Attribute('AST]'),两段都不是有效类型名 → Name('rawptr[ast') + Attribute('AST]'),两段都不是有效类型名 →
参数/返回注解解析为空 → VoidType → "无法识别的参数类型注解"。 参数/返回注解解析为空 → VoidType → "无法识别的参数类型注解"。
指针下标(rawptr[T] / t.CPtr[T])再折叠为等价的 `T | t.CPtr`,与源码 指针下标(rawptr[T] / CPtr[T])再折叠为等价的 `T | CPtr`,与源码
联合写法同解析路径(对齐 VPC TypeGenResolve._parse_type_string 的 '[' 联合写法同解析路径(对齐 VPC TypeGenResolve._parse_type_string 的 '['
分支 + ClassGenGeneric._clone_annotation 的 T 替换)。 分支 + ClassGenGeneric._clone_annotation 的 T 替换)。
内层为已混淆名(数字开头,如 'rawptr[7565e081d88517ac.AST]')时 内层为已混淆名(数字开头,如 'rawptr[7565e081d88517ac.AST]')时
ast.parse 无法解析(数字开头的令牌),改用手工拆 base/slice(同 VPC ast.parse 无法解析(数字开头的令牌),改用手工拆 base/slice(同 VPC
TypeGenResolve._parse_type_string 的数字开头手工拆分分支)。 TypeGenResolve._parse_type_string 的数字开头手工拆分分支)。
尾部 '*'(泛型实参 '<sha1>.Node*' / '<sha1>.Node**',来自 rawptr[T] / 尾部 '*'(泛型实参 '<sha1>.Node*' / '<sha1>.Node**',来自 rawptr[T] /
t.CPtr 的逐层 mangling)逐层还原为 `Node | t.CPtr [| t.CPtr]` → 对应 CPtr 的逐层 mangling)逐层还原为 `Node | CPtr [| CPtr]` → 对应
层数指针;只剥一层会把 'Node*' 当结构体名建出 phantom opaque 层数指针;只剥一层会把 'Node*' 当结构体名建出 phantom opaque
(item 类型与特化名 '<sha1>.Node**' 的语义不一致)。 (item 类型与特化名 '<sha1>.Node**' 的语义不一致)。
尾部 'ptr'(旧规则 mangling,如 'Nodeptr' / 'ast.ASTptr')保留兼容: 尾部 'ptr'(旧规则 mangling,如 'Nodeptr' / 'ast.ASTptr')保留兼容:
@@ -886,9 +877,8 @@ class FunctionHandle(BaseHandle):
BaseName: str = replacement[:len(replacement) - StarCount] BaseName: str = replacement[:len(replacement) - StarCount]
base_node: ast.AST base_node: ast.AST
if BaseName in ('i8', 'void', 'void*'): if BaseName in ('i8', 'void', 'void*'):
# i8*(void*)在源码侧写作 t.CPtr;再叠加 StarCount-1 层 # i8*(void*)在源码侧写作 CPtr;再叠加 StarCount-1 层
base_node = ast.Attribute( base_node = ast.Name(id='CPtr', ctx=ast.Load())
value=ast.Name(id='t', ctx=ast.Load()), attr='CPtr', ctx=ast.Load())
StarCount -= 1 StarCount -= 1
else: else:
base_node = self._make_name_node(BaseName) base_node = self._make_name_node(BaseName)
@@ -897,9 +887,7 @@ class FunctionHandle(BaseHandle):
node = ast.BinOp( node = ast.BinOp(
left=node, left=node,
op=ast.BitOr(), op=ast.BitOr(),
right=ast.Attribute( right=ast.Name(id='CPtr', ctx=ast.Load()),
value=ast.Name(id='t', ctx=ast.Load()),
attr='CPtr', ctx=ast.Load()),
) )
return node return node
if replacement.endswith('ptr'): if replacement.endswith('ptr'):
@@ -914,9 +902,7 @@ class FunctionHandle(BaseHandle):
node = ast.BinOp( node = ast.BinOp(
left=node, left=node,
op=ast.BitOr(), op=ast.BitOr(),
right=ast.Attribute( right=ast.Name(id='CPtr', ctx=ast.Load()),
value=ast.Name(id='t', ctx=ast.Load()),
attr='CPtr', ctx=ast.Load()),
) )
return node return node
if '[' in replacement: if '[' in replacement:
@@ -1054,21 +1040,21 @@ class FunctionHandle(BaseHandle):
if isinstance(node, ast.Call): if isinstance(node, ast.Call):
if isinstance(node.func, ast.Name) and node.func.id in type_map: if isinstance(node.func, ast.Name) and node.func.id in type_map:
replacement: str = type_map[node.func.id] replacement: str = type_map[node.func.id]
# 使用 _make_replacement_node 处理含点号的类型名(如 't.CUnsignedChar'), # 使用 _make_replacement_node 处理含点号的类型名(如 'CUnsignedChar'),
# 避免 T(0) 替换为 CUnsignedChar(0) 后因 CUnsignedChar 不在顶层作用域 # 避免 T(0) 替换为 CUnsignedChar(0) 后因 CUnsignedChar 不在顶层作用域
# 而报 "Undefined function: 'CUnsignedChar'" # 而报 "Undefined function: 'CUnsignedChar'"
node.func = self._make_replacement_node(replacement) node.func = self._make_replacement_node(replacement)
elif isinstance(node.func, ast.Attribute): elif isinstance(node.func, ast.Attribute):
if isinstance(node.func.value, ast.Name) and node.func.value.id in type_map: if isinstance(node.func.value, ast.Name) and node.func.value.id in type_map:
replacement: str = type_map[node.func.value.id] replacement: str = type_map[node.func.value.id]
# 指针类型参数(如 list[AST | t.CPtr] 中的 T)在表达式上下文中 # 指针类型参数(如 list[AST | CPtr] 中的 T)在表达式上下文中
# 需替换为 BinOp(AST | t.CPtr),使 __sizeof__ 等处理器能正确识别 # 需替换为 BinOp(AST | CPtr),使 __sizeof__ 等处理器能正确识别
# 指针语义并直接返回 8,避免触发 struct 加载和重入编译 # 指针语义并直接返回 8,避免触发 struct 加载和重入编译
if cptr_params and node.func.value.id in cptr_params: if cptr_params and node.func.value.id in cptr_params:
node.func.value = ast.BinOp( node.func.value = ast.BinOp(
left=self._make_name_node(replacement), left=self._make_name_node(replacement),
op=ast.BitOr(), op=ast.BitOr(),
right=ast.Attribute(value=ast.Name(id='t', ctx=ast.Load()), attr='CPtr', ctx=ast.Load()) right=ast.Name(id='CPtr', ctx=ast.Load())
) )
else: else:
node.func.value = self._make_name_node(replacement) node.func.value = self._make_name_node(replacement)
@@ -1083,7 +1069,7 @@ class FunctionHandle(BaseHandle):
node.value = ast.BinOp( node.value = ast.BinOp(
left=self._make_name_node(replacement), left=self._make_name_node(replacement),
op=ast.BitOr(), op=ast.BitOr(),
right=ast.Attribute(value=ast.Name(id='t', ctx=ast.Load()), attr='CPtr', ctx=ast.Load()) right=ast.Name(id='CPtr', ctx=ast.Load())
) )
else: else:
node.value = ast.Name(id=replacement, ctx=ast.Load()) node.value = ast.Name(id=replacement, ctx=ast.Load())
@@ -1153,7 +1139,7 @@ class FunctionHandle(BaseHandle):
RetTypeInfo = self.Trans.TypeMergeHandler.MergeTypes(Node.returns) RetTypeInfo = self.Trans.TypeMergeHandler.MergeTypes(Node.returns)
else: else:
RetTypeInfo = CTypeInfo.FromNode(Node.returns, self.Trans.SymbolTable) RetTypeInfo = CTypeInfo.FromNode(Node.returns, self.Trans.SymbolTable)
if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, t.CExport): if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, TypeSystem.CExport):
has_cexport = True has_cexport = True
except Exception as _e: except Exception as _e:
if _config_mode == "strict": if _config_mode == "strict":
@@ -1235,19 +1221,19 @@ class FunctionHandle(BaseHandle):
try: try:
RetTypeInfo: Any = None RetTypeInfo: Any = None
RetTypeInfo = self.ResolveAnnotationType(Node.returns) RetTypeInfo = self.ResolveAnnotationType(Node.returns)
if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, t.CExport) and not RetTypeInfo.IsState: if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, TypeSystem.CExport) and not RetTypeInfo.IsState:
Gen._export_funcs.add(FuncName) Gen._export_funcs.add(FuncName)
IsUserMarkedExport = True IsUserMarkedExport = True
if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, t.CExtern): if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, TypeSystem.CExtern):
Gen._export_funcs.add(FuncName) Gen._export_funcs.add(FuncName)
IsUserMarkedExport = True IsUserMarkedExport = True
if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.IsState: if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.IsState:
Gen._export_funcs.add(FuncName) # t.State 标记的函数必须保持原始名称,以便链接器解析 Gen._export_funcs.add(FuncName) # State 标记的函数必须保持原始名称,以便链接器解析
IsUserMarkedExport = True IsUserMarkedExport = True
except Exception as _e: except Exception as _e:
if _config_mode == "strict": if _config_mode == "strict":
self.Trans.LogWarning(f"异常被忽略: {_e}") self.Trans.LogWarning(f"异常被忽略: {_e}")
# 装饰器形式的存储类标记(@t.CExport / @t.CExtern / @t.State 等) # 装饰器形式的存储类标记(@CExport / @CExtern / @State 等)
deco_flags: dict[str, bool] = self._extract_decorator_storage_flags(Node) 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']: if deco_flags['is_export'] or deco_flags['is_extern'] or deco_flags['is_state']:
Gen._export_funcs.add(FuncName) Gen._export_funcs.add(FuncName)
@@ -1401,11 +1387,11 @@ class FunctionHandle(BaseHandle):
# 另含**编译期生命期标注**(P2):@life(willFree(...)) 与 @willFree(...) 是纯标注, # 另含**编译期生命期标注**(P2):@life(willFree(...)) 与 @willFree(...) 是纯标注,
# 没有运行时装饰器函数;不排除会生成 wrapper 去调用不存在的 @life/@willFree, # 没有运行时装饰器函数;不排除会生成 wrapper 去调用不存在的 @life/@willFree,
# 并把被装饰的 extern def(如 stdlib.free)变成本模块 internal 声明(llc 报 linkage 错)。 # 并把被装饰的 extern def(如 stdlib.free)变成本模块 internal 声明(llc 报 linkage 错)。
_BUILTIN_DECORATORS = {'staticmethod', 'property', 'classmethod', 'life', 'willFree'} _BUILTIN_DECORATORS = {'staticmethod', 'property', 'classmethod', 'life', 'willFree', 'Attribute'}
_symtab: object = self.Trans.SymbolTable _symtab: object = self.Trans.SymbolTable
if Node.decorator_list: if Node.decorator_list:
for decorator in Node.decorator_list: for decorator in Node.decorator_list:
# 跳过 t 模块存储类标记装饰器(@t.CExport / @CExport 等) # 跳过内建存储类标记装饰器(@CExport / @CStatic 等)
if self._is_t_storage_decorator(decorator, _symtab): if self._is_t_storage_decorator(decorator, _symtab):
continue continue
# 识别自定义行为装饰器:@name(ast.Name 形式) # 识别自定义行为装饰器:@name(ast.Name 形式)
@@ -1426,13 +1412,13 @@ class FunctionHandle(BaseHandle):
deco_info['kwargs'][kw.arg] = kw.value.value deco_info['kwargs'][kw.arg] = kw.value.value
behavior_decorators.append(deco_info) behavior_decorators.append(deco_info)
continue continue
if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute): if isinstance(decorator, ast.Call):
if decorator.func.attr == 'CReturn': if isinstance(decorator.func, ast.Attribute) and decorator.func.attr == 'CReturn':
_RejectCReturnDecorator(Node, [decorator]) _RejectCReturnDecorator(Node, [decorator])
elif decorator.func.attr == 'Attribute' and isinstance(decorator.func.value, ast.Name) and decorator.func.value.id == 'c': elif isinstance(decorator.func, ast.Name) and decorator.func.id == 'Attribute':
for arg in decorator.args: for arg in decorator.args:
if isinstance(arg, ast.Call) and isinstance(arg.func, ast.Attribute): 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': if isinstance(arg.func.value, ast.Name) and arg.func.value.id == 'attr':
attr_name = arg.func.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)] 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)] int_args = [a.value for a in arg.args if isinstance(a, ast.Constant) and isinstance(a.value, int)]
@@ -1445,28 +1431,30 @@ class FunctionHandle(BaseHandle):
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'): 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: if not arg.args:
fn_attrs[attr_name] = True 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): elif (isinstance(arg.func.value, ast.Attribute) and arg.func.value.attr == 'llvm'
and isinstance(arg.func.value.value, ast.Name) and arg.func.value.value.id == 'attr'):
llvm_attr_name = arg.func.attr llvm_attr_name = arg.func.attr
if llvm_attr_name in self._LLVM_ATTR_NAMES: if llvm_attr_name in self._LLVM_ATTR_NAMES:
fn_attrs[f'llvm.{llvm_attr_name}'] = True fn_attrs[f'llvm.{llvm_attr_name}'] = True
elif isinstance(arg, ast.Attribute): 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': if isinstance(arg.value, ast.Name) and arg.value.id == 'attr':
attr_name = arg.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'): 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 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): elif (isinstance(arg.value, ast.Attribute) and arg.value.attr == 'llvm'
and isinstance(arg.value.value, ast.Name) and arg.value.value.id == 'attr'):
llvm_attr_name = arg.attr llvm_attr_name = arg.attr
if llvm_attr_name in self._LLVM_ATTR_NAMES: if llvm_attr_name in self._LLVM_ATTR_NAMES:
fn_attrs[f'llvm.{llvm_attr_name}'] = True fn_attrs[f'llvm.{llvm_attr_name}'] = True
# 检查 @t.TLS 装饰器(一次性初始化标记) # 检查 @TLS 装饰器(一次性初始化标记)
is_tls_func: bool = False is_tls_func: bool = False
if Node.decorator_list: if Node.decorator_list:
for decorator in Node.decorator_list: for decorator in Node.decorator_list:
if isinstance(decorator, ast.Attribute) and isinstance(decorator.value, ast.Name): if isinstance(decorator, ast.Attribute) and isinstance(decorator.value, ast.Name):
if IsTModule(decorator.value.id, _symtab) and decorator.attr == 'TLS': if decorator.attr == 'TLS':
is_tls_func = True is_tls_func = True
break break
elif isinstance(decorator, ast.Name) and decorator.id == 'TLS' and hasattr(t, 'TLS'): elif isinstance(decorator, ast.Name) and decorator.id == 'TLS' and hasattr(TypeSystem, 'TLS'):
is_tls_func = True is_tls_func = True
break break
if Node.returns: if Node.returns:
@@ -1488,7 +1476,7 @@ class FunctionHandle(BaseHandle):
try: try:
rt_info = CTypeInfo.FromNode(Node.returns, self.Trans.SymbolTable) rt_info = CTypeInfo.FromNode(Node.returns, self.Trans.SymbolTable)
# 仅指针层数 <=1 才算裸 str/bytes(i8*)。 # 仅指针层数 <=1 才算裸 str/bytes(i8*)。
# `str | t.CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组), # `str | CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),
# 不能压平,否则返回类型错误。 # 不能压平,否则返回类型错误。
if rt_info and rt_info.IsStr and rt_info.PtrCount <= 1: if rt_info and rt_info.IsStr and rt_info.PtrCount <= 1:
is_str_return = True is_str_return = True
@@ -1498,19 +1486,19 @@ class FunctionHandle(BaseHandle):
if is_str_return: if is_str_return:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CChar() ReturnTypeInfo.BaseType = TypeSystem.CChar()
ReturnTypeInfo.PtrCount = 1 ReturnTypeInfo.PtrCount = 1
elif Node.returns: elif Node.returns:
if MultiRetTypes: if MultiRetTypes:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CVoid() ReturnTypeInfo.BaseType = TypeSystem.CVoid()
else: else:
try: try:
if 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):
ReturnTypeInfo = getattr(self.Trans, 'TypeMergeHandler', None) and self.Trans.TypeMergeHandler.MergeTypes(Node.returns) ReturnTypeInfo = getattr(self.Trans, 'TypeMergeHandler', None) and self.Trans.TypeMergeHandler.MergeTypes(Node.returns)
if not isinstance(ReturnTypeInfo, CTypeInfo): if not isinstance(ReturnTypeInfo, CTypeInfo):
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CVoid() ReturnTypeInfo.BaseType = TypeSystem.CVoid()
if ((ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState) if ((ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState)
or (ReturnTypeInfo.PtrCount >= 2 and ReturnTypeInfo.BaseType is None)): or (ReturnTypeInfo.PtrCount >= 2 and ReturnTypeInfo.BaseType is None)):
def _FindNonVoidCTypeInfo(node): def _FindNonVoidCTypeInfo(node):
@@ -1537,9 +1525,9 @@ class FunctionHandle(BaseHandle):
ReturnTypeInfo = found ReturnTypeInfo = found
if ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState: if ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CInt() ReturnTypeInfo.BaseType = TypeSystem.CInt()
# define 宏函数(返回注解含 t.CDefine,如 `int | t.CDefine`): # define 宏函数(返回注解含 CDefine,如 `int | CDefine`):
# 标记为编译期内联宏(alwaysinline),对齐裸 `-> t.CDefine` 路径 # 标记为编译期内联宏(alwaysinline),对齐裸 `-> CDefine` 路径
if AnnotationContainsName(Node.returns, 'CDefine'): if AnnotationContainsName(Node.returns, 'CDefine'):
if not hasattr(self, '_cdefine_funcs'): if not hasattr(self, '_cdefine_funcs'):
self._cdefine_funcs = set() self._cdefine_funcs = set()
@@ -1549,7 +1537,7 @@ class FunctionHandle(BaseHandle):
if isinstance(Node.returns, ast.Name) and Node.returns.id in ('str', 'bytes'): if isinstance(Node.returns, ast.Name) and Node.returns.id in ('str', 'bytes'):
is_str_type = True is_str_type = True
# 与 _GetFunctionSignatureLlvm 同口径:指针下标返回注解 # 与 _GetFunctionSignatureLlvm 同口径:指针下标返回注解
# (rawptr[T] / t.CPtr[T])走 ResolveAnnotationType 的 # (rawptr[T] / CPtr[T])走 ResolveAnnotationType 的
# TypeMerge 通用解析,避免内层跨模块类退化为 i8*。 # TypeMerge 通用解析,避免内层跨模块类退化为 i8*。
ReturnTypeInfo = self.ResolveAnnotationType(Node.returns) ReturnTypeInfo = self.ResolveAnnotationType(Node.returns)
if ReturnTypeInfo and ReturnTypeInfo.IsDefine: if ReturnTypeInfo and ReturnTypeInfo.IsDefine:
@@ -1559,24 +1547,24 @@ class FunctionHandle(BaseHandle):
ReturnTypeInfo.PtrCount = 1 if inferred[1] else 0 ReturnTypeInfo.PtrCount = 1 if inferred[1] else 0
else: else:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CInt() ReturnTypeInfo.BaseType = TypeSystem.CInt()
if not hasattr(self, '_cdefine_funcs'): if not hasattr(self, '_cdefine_funcs'):
self._cdefine_funcs = set() self._cdefine_funcs = set()
self._cdefine_funcs.add(FuncName) self._cdefine_funcs.add(FuncName)
elif ReturnTypeInfo and ReturnTypeInfo.IsState: elif ReturnTypeInfo and ReturnTypeInfo.IsState:
pass # t.State is a modifier, preserve the actual return type pass # State is a modifier, preserve the actual return type
if ReturnTypeInfo is None: if ReturnTypeInfo is None:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CVoid() ReturnTypeInfo.BaseType = TypeSystem.CVoid()
# 仅指针层数 <=1 才算裸 str/bytes(i8*)。 # 仅指针层数 <=1 才算裸 str/bytes(i8*)。
# `str | t.CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),不能压平。 # `str | CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),不能压平。
if is_str_type or (ReturnTypeInfo.IsStr and ReturnTypeInfo.PtrCount <= 1): if is_str_type or (ReturnTypeInfo.IsStr and ReturnTypeInfo.PtrCount <= 1):
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CChar() ReturnTypeInfo.BaseType = TypeSystem.CChar()
ReturnTypeInfo.PtrCount = 1 ReturnTypeInfo.PtrCount = 1
# 检查泛型类返回类型 (如 list[str]) # 检查泛型类返回类型 (如 list[str])
# 注意:_from_node_subscript 对未识别的泛型下标(如 list[str])返回空 CTypeInfo(BaseType=None), # 注意:_from_node_subscript 对未识别的泛型下标(如 list[str])返回空 CTypeInfo(BaseType=None),
# 此时 IsVoid 为 False(因为 IsVoid 仅检查 t.CVoid 实例),需额外检测 BaseType is None # 此时 IsVoid 为 False(因为 IsVoid 仅检查 CVoid 实例),需额外检测 BaseType is None
if (isinstance(Node.returns, ast.Subscript) if (isinstance(Node.returns, ast.Subscript)
and isinstance(Node.returns.value, ast.Name) and isinstance(Node.returns.value, ast.Name)
and hasattr(self.Trans.ClassHandler, '_generic_class_templates') and hasattr(self.Trans.ClassHandler, '_generic_class_templates')
@@ -1609,17 +1597,17 @@ class FunctionHandle(BaseHandle):
ret_class, ret_type_args, Gen, type_names=ret_type_names, declare_only=True) ret_class, ret_type_args, Gen, type_names=ret_type_names, declare_only=True)
if spec_name2 and spec_name2 in Gen.structs: if spec_name2 and spec_name2 in Gen.structs:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CStruct(name=spec_name2) ReturnTypeInfo.BaseType = TypeSystem.CStruct(name=spec_name2)
ReturnTypeInfo.PtrCount = 1 ReturnTypeInfo.PtrCount = 1
if (ReturnTypeInfo.IsVoid or ReturnTypeInfo.BaseType is None) and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState: if (ReturnTypeInfo.IsVoid or ReturnTypeInfo.BaseType is None) and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CInt() ReturnTypeInfo.BaseType = TypeSystem.CInt()
except Exception: # 回退:设置默认返回类型为 CInt except Exception: # 回退:设置默认返回类型为 CInt
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CInt() ReturnTypeInfo.BaseType = TypeSystem.CInt()
else: else:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CInt() ReturnTypeInfo.BaseType = TypeSystem.CInt()
inferred = self._infer_return_type_from_body(Node, Gen, ClassName) inferred = self._infer_return_type_from_body(Node, Gen, ClassName)
if inferred: if inferred:
ReturnTypeInfo = CTypeInfo.FromTypeName(inferred[0]) ReturnTypeInfo = CTypeInfo.FromTypeName(inferred[0])
@@ -1650,20 +1638,20 @@ class FunctionHandle(BaseHandle):
ParamTypeInfo = self.ResolveParamAnnotation(Arg.annotation) ParamTypeInfo = self.ResolveParamAnnotation(Arg.annotation)
if ParamTypeInfo is None: if ParamTypeInfo is None:
ParamTypeInfo = CTypeInfo() ParamTypeInfo = CTypeInfo()
ParamTypeInfo.BaseType = t.CInt() ParamTypeInfo.BaseType = TypeSystem.CInt()
IsPtr = ParamTypeInfo.IsPtr IsPtr = ParamTypeInfo.IsPtr
if ParamTypeInfo and getattr(ParamTypeInfo, 'IsCpythonObject', False) and not IsPtr: if ParamTypeInfo and getattr(ParamTypeInfo, 'IsCpythonObject', False) and not IsPtr:
IsPtr = True IsPtr = True
ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1) ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1)
# 仅当指针层数 <=1 时才压平为 i8*(裸 str/bytes)。 # 仅当指针层数 <=1 时才压平为 i8*(裸 str/bytes)。
# `str | t.CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组), # `str | CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),
# 不能压平,否则形参类型错误导致 _adjust_args 多 load 一层崩溃。 # 不能压平,否则形参类型错误导致 _adjust_args 多 load 一层崩溃。
if (ParamTypeInfo.IsStr and ParamTypeInfo.PtrCount <= 1) or (isinstance(Arg.annotation, ast.Name) and Arg.annotation.id in ('str', 'bytes')): if (ParamTypeInfo.IsStr and ParamTypeInfo.PtrCount <= 1) or (isinstance(Arg.annotation, ast.Name) and Arg.annotation.id in ('str', 'bytes')):
ParamTypeInfo = CTypeInfo() ParamTypeInfo = CTypeInfo()
ParamTypeInfo.BaseType = t.CChar() ParamTypeInfo.BaseType = TypeSystem.CChar()
ParamTypeInfo.PtrCount = 1 ParamTypeInfo.PtrCount = 1
IsPtr = True IsPtr = True
# C 语言中数组参数退化为指针:t.CArray[type, N] → type* # C 语言中数组参数退化为指针:CArray[type, N] → type*
if ParamTypeInfo.ArrayDims: if ParamTypeInfo.ArrayDims:
ParamTypeInfo.ArrayDims = [] ParamTypeInfo.ArrayDims = []
ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1) ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1)
@@ -1674,7 +1662,7 @@ class FunctionHandle(BaseHandle):
AnnStr: str = ast.unparse(Arg.annotation) if hasattr(ast, 'unparse') else str(Arg.annotation) AnnStr: str = ast.unparse(Arg.annotation) if hasattr(ast, 'unparse') else str(Arg.annotation)
raise SyntaxError( raise SyntaxError(
f"无法识别的参数类型注解: '{AnnStr}'(在函数 '{Node.name}' 的参数 '{Arg.arg}' 上)。" f"无法识别的参数类型注解: '{AnnStr}'(在函数 '{Node.name}' 的参数 '{Arg.arg}' 上)。"
f"请使用有效的 VPC 类型(如 t.CPtr、ast.AST 或已注册的结构体)。" f"请使用有效的 VPC 类型(如 CPtr、ast.AST 或已注册的结构体)。"
) )
if ParamTypeInfo and ParamTypeInfo.IsFuncPtr: if ParamTypeInfo and ParamTypeInfo.IsFuncPtr:
ParamType = ir.IntType(8).as_pointer() ParamType = ir.IntType(8).as_pointer()
@@ -1684,15 +1672,15 @@ class FunctionHandle(BaseHandle):
except Exception: # 回退:参数类型解析失败时使用默认 i32 except Exception: # 回退:参数类型解析失败时使用默认 i32
ParamType = ir.IntType(32) ParamType = ir.IntType(32)
ParamTypeInfo = CTypeInfo() ParamTypeInfo = CTypeInfo()
ParamTypeInfo.BaseType = t.CInt() ParamTypeInfo.BaseType = TypeSystem.CInt()
else: else:
ParamType = ir.IntType(32) ParamType = ir.IntType(32)
ParamTypeInfo = CTypeInfo() ParamTypeInfo = CTypeInfo()
ParamTypeInfo.BaseType = t.CInt() ParamTypeInfo.BaseType = TypeSystem.CInt()
ParamTypes.append(ParamType) ParamTypes.append(ParamType)
ParamNames.append(Arg.arg) ParamNames.append(Arg.arg)
ParamTypeStrs.append(ParamTypeInfo) ParamTypeStrs.append(ParamTypeInfo)
# 自动取址模式(由注解读出):'ref' = &T、'temp' = &temp T、'always' = t.CAutoPtr # 自动取址模式(由注解读出):'ref' = &T、'temp' = &temp T、'always' = CAutoPtr
auto_mode_emit: str | None = FindAutoAddrMode(Arg.annotation) auto_mode_emit: str | None = FindAutoAddrMode(Arg.annotation)
auto_addr_modes_emit.append(auto_mode_emit) auto_addr_modes_emit.append(auto_mode_emit)
Gen._record_var_signedness(Arg.arg, ParamIsUnsigned) Gen._record_var_signedness(Arg.arg, ParamIsUnsigned)
@@ -1712,14 +1700,14 @@ class FunctionHandle(BaseHandle):
for i, ReturnTypeNode in enumerate(MultiRetTypes): for i, ReturnTypeNode in enumerate(MultiRetTypes):
ReturnTypeInfo = CTypeInfo.FromNode(ReturnTypeNode, self.Trans.SymbolTable) ReturnTypeInfo = CTypeInfo.FromNode(ReturnTypeNode, self.Trans.SymbolTable)
# 仅指针层数 <=1 才算裸 str/bytes(i8*)。 # 仅指针层数 <=1 才算裸 str/bytes(i8*)。
# `str | t.CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),不能压平。 # `str | CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),不能压平。
if ReturnTypeInfo and ReturnTypeInfo.IsStr and ReturnTypeInfo.PtrCount <= 1: if ReturnTypeInfo and ReturnTypeInfo.IsStr and ReturnTypeInfo.PtrCount <= 1:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CChar() ReturnTypeInfo.BaseType = TypeSystem.CChar()
ReturnTypeInfo.PtrCount = 1 ReturnTypeInfo.PtrCount = 1
if ReturnTypeInfo is None: if ReturnTypeInfo is None:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CInt() ReturnTypeInfo.BaseType = TypeSystem.CInt()
RetType = Gen._ctype_to_llvm(ReturnTypeInfo) RetType = Gen._ctype_to_llvm(ReturnTypeInfo)
MultiRetLlvmTypes.append(RetType) MultiRetLlvmTypes.append(RetType)
ReturnType = ir.LiteralStructType(MultiRetLlvmTypes) ReturnType = ir.LiteralStructType(MultiRetLlvmTypes)
@@ -1762,12 +1750,12 @@ class FunctionHandle(BaseHandle):
try: try:
RetTypeInfo = None RetTypeInfo = None
RetTypeInfo = self.ResolveAnnotationType(Node.returns) RetTypeInfo = self.ResolveAnnotationType(Node.returns)
if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, t.CInline): if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, TypeSystem.CInline):
IsInlineFunc = True IsInlineFunc = True
if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, t.CExport) and not RetTypeInfo.IsState: if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, TypeSystem.CExport) and not RetTypeInfo.IsState:
Gen._export_funcs.add(FuncName) Gen._export_funcs.add(FuncName)
IsUserMarkedExport = True IsUserMarkedExport = True
if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, t.CExtern): if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, TypeSystem.CExtern):
IsExternFunc = True IsExternFunc = True
Gen._export_funcs.add(FuncName) Gen._export_funcs.add(FuncName)
IsUserMarkedExport = True IsUserMarkedExport = True
@@ -1778,7 +1766,7 @@ class FunctionHandle(BaseHandle):
except Exception as _e: except Exception as _e:
if _config_mode == "strict": if _config_mode == "strict":
self.Trans.LogWarning(f"异常被忽略: {_e}") self.Trans.LogWarning(f"异常被忽略: {_e}")
# 装饰器形式的存储类标记(@t.CExport / @t.CExtern / @t.CStatic / @t.State / @t.CInline) # 装饰器形式的存储类标记(@CExport / @CExtern / @CStatic / @State / @CInline)
deco_flags: dict[str, bool] = self._extract_decorator_storage_flags(Node) deco_flags: dict[str, bool] = self._extract_decorator_storage_flags(Node)
if deco_flags['is_inline']: if deco_flags['is_inline']:
IsInlineFunc = True IsInlineFunc = True
@@ -1955,7 +1943,7 @@ class FunctionHandle(BaseHandle):
saved_var_struct_class = dict(Gen.var_struct_class) if Gen.var_struct_class else {} saved_var_struct_class = dict(Gen.var_struct_class) if Gen.var_struct_class else {}
saved_global_struct_class = dict(Gen.global_struct_class) if getattr(Gen, 'global_struct_class', None) else {} saved_global_struct_class = dict(Gen.global_struct_class) if getattr(Gen, 'global_struct_class', None) else {}
# 函数内部定义的变量会在赋值时添加到 var_type_info 中 # 函数内部定义的变量会在赋值时添加到 var_type_info 中
# 这样函数内部定义的元类型变量(如 a = t.CInt32T)就能被正确处理 # 这样函数内部定义的元类型变量(如 a = CInt32T)就能被正确处理
for stmt in Node.body: for stmt in Node.body:
if isinstance(stmt, ast.Global): if isinstance(stmt, ast.Global):
self.Trans.ForHandler._RegisterGlobalNames(stmt.names, Gen) self.Trans.ForHandler._RegisterGlobalNames(stmt.names, Gen)
@@ -1989,7 +1977,7 @@ class FunctionHandle(BaseHandle):
var = Gen._allocaEntry(param.type, name=param_name) var = Gen._allocaEntry(param.type, name=param_name)
Gen._store(param, var) Gen._store(param, var)
Gen.variables[param_name] = var Gen.variables[param_name] = var
# 为联合类型注解(如 Function | t.CPtr)的参数设置 var_struct_class, # 为联合类型注解(如 Function | CPtr)的参数设置 var_struct_class,
# 确保编译器能正确生成 GEP 访问结构体成员(如 func.Blocks、func.Params) # 确保编译器能正确生成 GEP 访问结构体成员(如 func.Blocks、func.Params)
for i, arg in enumerate(Node.args.args): for i, arg in enumerate(Node.args.args):
if arg.annotation and isinstance(arg.annotation, ast.BinOp) and isinstance(arg.annotation.op, ast.BitOr): if arg.annotation and isinstance(arg.annotation, ast.BinOp) and isinstance(arg.annotation.op, ast.BitOr):
@@ -1997,13 +1985,13 @@ class FunctionHandle(BaseHandle):
if param_name in Gen.variables: if param_name in Gen.variables:
# 若 L1650-1657 已根据 param.type.pointee 匹配到正确的特化名 # 若 L1650-1657 已根据 param.type.pointee 匹配到正确的特化名
# (如 ndarray[double]),不覆盖:FindStructNameInAnnotation 对 # (如 ndarray[double]),不覆盖:FindStructNameInAnnotation 对
# 泛型注解 ndarray[t.CDouble] 会构造 ndarray[CDouble](与实际 # 泛型注解 ndarray[CDouble] 会构造 ndarray[CDouble](与实际
# ndarray[double] 不匹配),回退到裸模板类名 ndarray(opaque), # ndarray[double] 不匹配),回退到裸模板类名 ndarray(opaque),
# 导致方法调用查找 ndarray.sum 而非 ndarray[double].sum。 # 导致方法调用查找 ndarray.sum 而非 ndarray[double].sum。
if param_name in Gen.var_struct_class: if param_name in Gen.var_struct_class:
_existing_ps: str = Gen.var_struct_class[param_name] _existing_ps: str = Gen.var_struct_class[param_name]
# 指针占位名(rawptr / {sha1}.rawptr / rawptr[...])是模块限定 # 指针占位名(rawptr / {sha1}.rawptr / rawptr[...])是模块限定
# struct 联合(llvmlite.Function | t.CPtr)被 resolver 退化 # struct 联合(llvmlite.Function | CPtr)被 resolver 退化
# 的产物,必须允许 FindStructNameInAnnotation 短名修正 # 的产物,必须允许 FindStructNameInAnnotation 短名修正
# (否则 func.IsVarArg → "属性在类 'rawptr' 中找不到")。 # (否则 func.IsVarArg → "属性在类 'rawptr' 中找不到")。
if not (_existing_ps == 'rawptr' or '.rawptr' in _existing_ps if not (_existing_ps == 'rawptr' or '.rawptr' in _existing_ps
@@ -2013,7 +2001,7 @@ class FunctionHandle(BaseHandle):
arg.annotation, self.Trans, Gen) arg.annotation, self.Trans, Gen)
if found_struct: if found_struct:
Gen.var_struct_class[param_name] = found_struct Gen.var_struct_class[param_name] = found_struct
# 普通类注解形参(非 BinOp 联合):rawptr[X] / t.CPtr[X] / X / t.X # 普通类注解形参(非 BinOp 联合):rawptr[X] / CPtr[X] / X / X
# 一律按"声明类"登记 var_struct_class。避免按 param.type.pointee 匹配 # 一律按"声明类"登记 var_struct_class。避免按 param.type.pointee 匹配
# 到泛型父特化(如 class Function(GSListNode[Function]) 的形参 func 被 # 到泛型父特化(如 class Function(GSListNode[Function]) 的形参 func 被
# 登记成 GSListNode[Function],其 struct 仅含 Next → func.Blocks 访问 # 登记成 GSListNode[Function],其 struct 仅含 Next → func.Blocks 访问
@@ -2092,7 +2080,7 @@ class FunctionHandle(BaseHandle):
# 用 _direct_values 注册,Name 解析时直接返回 va_list 指针(i8*), # 用 _direct_values 注册,Name 解析时直接返回 va_list 指针(i8*),
# 不走 variables 的 load 路径(否则会把 i8* 当 char* 加载一个字节) # 不走 variables 的 load 路径(否则会把 i8* 当 char* 加载一个字节)
Gen._direct_values[vararg_name] = va_list_ptr Gen._direct_values[vararg_name] = va_list_ptr
# @t.TLS 一次性初始化检查:首次调用执行函数体,后续调用直接返回 # @TLS 一次性初始化检查:首次调用执行函数体,后续调用直接返回
if is_tls_func: if is_tls_func:
flag_name: str = f"__tls_init_done_{FuncName}" flag_name: str = f"__tls_init_done_{FuncName}"
flag_global = None flag_global = None
@@ -2190,13 +2178,13 @@ class FunctionHandle(BaseHandle):
# - 末句是控制流(If/Match/While/For/Try/With)→ 掉出合法(隐式返回 # - 末句是控制流(If/Match/While/For/Try/With)→ 掉出合法(隐式返回
# 规则:末句控制流 → unreachable;match/if 合成 after 块机械掉出, # 规则:末句控制流 → unreachable;match/if 合成 after 块机械掉出,
# 所有 arm 已 terminated 属正常) # 所有 arm 已 terminated 属正常)
# - 末句是普通语句 → 真掉出末尾;-> None / -> t.CVoid 视为 Void 合法, # - 末句是普通语句 → 真掉出末尾;-> None / -> CVoid 视为 Void 合法,
# 无注解 → C 风格过程(ConstZero,保持现状);其余注解报错 # 无注解 → C 风格过程(ConstZero,保持现状);其余注解报错
_last_stmt = Node.body[-1] if Node.body else None _last_stmt = Node.body[-1] if Node.body else None
_is_ret_or_ctrl_tail: bool = isinstance(_last_stmt, ( _is_ret_or_ctrl_tail: bool = isinstance(_last_stmt, (
ast.Return, ast.If, ast.Match, ast.While, ast.For, ast.Try, ast.With)) ast.Return, ast.If, ast.Match, ast.While, ast.For, ast.Try, ast.With))
if Node.returns is not None and not _is_ret_or_ctrl_tail: if Node.returns is not None and not _is_ret_or_ctrl_tail:
# void(None / t.CVoid,含 | 联合)/ extern|export 声明型辅助符号 # void(None / CVoid,含 | 联合)/ extern|export 声明型辅助符号
# (State / CExport / CExtern)→ 掉出合法,不 fail-fast # (State / CExport / CExtern)→ 掉出合法,不 fail-fast
if not _IsVoidOrDeclAnnotation(Node.returns): if not _IsVoidOrDeclAnnotation(Node.returns):
raise Exception( raise Exception(
+10 -5
View File
@@ -23,16 +23,21 @@ class IfHandle(BaseHandle):
return None return None
def _is_cif_call(self, node: ast.expr) -> bool: def _is_cif_call(self, node: ast.expr) -> bool:
"""判定 If.test 是否为 cif/celif 的内部标记调用(c.@CIf 族,解析期合成)。 """判定 If.test 是否为 cif/celif 的内部标记调用(@CIf 族,解析期合成)。
标记属性名带前导 '@'(词法器不可产出),故用户写的 c.CIf(...) 不会命中。 标记名带前导 '@'(词法器不可产出),故用户写的 CIf(...) 不会命中。
""" """
if isinstance(node, ast.Call): if isinstance(node, ast.Call):
if isinstance(node.func, ast.Attribute):
if isinstance(node.func.value, ast.Name) and node.func.value.id == 'c':
return node.func.attr in ('@CIf', '@CIfdef', '@CIfndef')
if isinstance(node.func, ast.Name): if isinstance(node.func, ast.Name):
return node.func.id in ('@CIf', '@CIfdef', '@CIfndef') return node.func.id in ('@CIf', '@CIfdef', '@CIfndef')
if (isinstance(node.func, ast.Attribute)
and isinstance(node.func.value, ast.Name)
and node.func.value.id == 'c'
and node.func.attr in ('CIf', 'CIfdef', 'CIfndef', 'CElif', 'CElse', 'CEndif')):
from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError(
f"`c.{node.func.attr}` 不是内建标记:cif/celif 条件请使用 "
f"`cif` / `celif` 语句与 `defined(NAME)` 谓词")
return False return False
def _resolve_macro_name(self, arg: ast.expr) -> str | None: def _resolve_macro_name(self, arg: ast.expr) -> str | None:
+83 -130
View File
@@ -12,15 +12,15 @@ import llvmlite.ir as ir
from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta
from lib.core.VLogger import get_logger as _vlog from lib.core.VLogger import get_logger as _vlog
from lib.constants.config import mode as _config_mode from lib.constants.config import mode as _config_mode
from lib.includes import t from lib.core import TypeSystem
from lib.includes.t import CTypeRegistry from lib.core.TypeSystem import CTypeRegistry
from lib.core.SymbolUtils import ParseListAnnotation, ExtractTypeNameFromBinOp, AnnotationContainsName, FindStructNameInAnnotationWithContext, FindAutoAddrMode from lib.core.SymbolUtils import ParseListAnnotation, ExtractTypeNameFromBinOp, AnnotationContainsName, FindStructNameInAnnotationWithContext, FindAutoAddrMode
from lib.core.SymbolUtils import EnumClassIntWidth, ExpandSoftKeywords from lib.core.SymbolUtils import EnumClassIntWidth, ExpandSoftKeywords
from lib.core.SymbolUtils import ClassHasFuncLevelCVTable, IsVtableSlotMethod from lib.core.SymbolUtils import ClassHasFuncLevelCVTable, IsVtableSlotMethod
# 注解里的存储类 / 限定符标记:这些名字**不是类名**(联合注解里与指针类混写, # 注解里的存储类 / 限定符标记:这些名字**不是类名**(联合注解里与指针类混写,
# 如 `t.CExtern | rawptr[CompilerFactory]`),提取"指针指向的类"时必须滤掉。 # 如 `CExtern | rawptr[CompilerFactory]`),提取"指针指向的类"时必须滤掉。
_MARKER_ANNOT_NAMES: frozenset[str] = frozenset({ _MARKER_ANNOT_NAMES: frozenset[str] = frozenset({
'CExtern', 'CExport', 'CStatic', 'CInline', 'CConst', 'CVolatile', 'CRegister', 'CExtern', 'CExport', 'CStatic', 'CInline', 'CConst', 'CVolatile', 'CRegister',
'CAuto', 'CDefine', 'CTypedef', 'CPostdefinition', 'CPtr', 'CArrayPtr', 'CVoid', 'CAuto', 'CDefine', 'CTypedef', 'CPostdefinition', 'CPtr', 'CArrayPtr', 'CVoid',
@@ -99,7 +99,7 @@ def _HasRealParentClass(Node: ast.ClassDef) -> bool:
def _VtableByClassLevelForImport(Node: ast.ClassDef, Gen: object) -> bool: def _VtableByClassLevelForImport(Node: ast.ClassDef, Gen: object) -> bool:
"""跨模块导入类的 VtableByClassLevel(忽略方法级 CVTable 标记的 vtable 状态)。 """跨模块导入类的 VtableByClassLevel(忽略方法级 CVTable 标记的 vtable 状态)。
与 HandlesClassDef._resolve_class_flags 的口径一致:类级 @t.CVTable 或 与 HandlesClassDef._resolve_class_flags 的口径一致:类级 @CVTable 或
"有真实父类且父类不是 NoVTable" ⇒ True。供 SymbolUtils.IsVtableSlotMethod "有真实父类且父类不是 NoVTable" ⇒ True。供 SymbolUtils.IsVtableSlotMethod
判定方法是否占虚表槽(唯一的判据源),使导入侧的虚表槽序与定义模块逐槽相同。 判定方法是否占虚表槽(唯一的判据源),使导入侧的虚表槽序与定义模块逐槽相同。
""" """
@@ -472,14 +472,11 @@ class ImportHandle(BaseHandle):
self.Trans._ImportedModules = set() self.Trans._ImportedModules = set()
for alias in Node.names: for alias in Node.names:
name = alias.name name = alias.name
if name in ('c', 't'): # 内建标记按裸名书写(CPtr / CInt / CDefine ...),不再有 t / c 模块。
if alias.asname: if name in ('t', 'c'):
self.Trans.SymbolTable.import_aliases[alias.asname] = name raise TypeError(
AliasInfo = CTypeInfo() f"不支持 `import {name}`:请直接使用内建裸名标记"
AliasInfo.IsModuleAlias = True f"(如 CPtr、CInt、CDefine、Asm)")
AliasInfo.ResolvedModule = name
self.Trans.SymbolTable.insert(alias.asname, AliasInfo)
continue
self.Trans._ImportedModules.add(name) self.Trans._ImportedModules.add(name)
if alias.asname: if alias.asname:
self.Trans.SymbolTable.import_aliases[alias.asname] = name self.Trans.SymbolTable.import_aliases[alias.asname] = name
@@ -529,9 +526,9 @@ class ImportHandle(BaseHandle):
if name not in _dt_map: if name not in _dt_map:
_dt_map[name] = all_dt[name] _dt_map[name] = all_dt[name]
continue continue
if not hasattr(self.Trans, '_t_c_imported_names'): if not hasattr(self.Trans, '_from_import_aliases'):
self.Trans._t_c_imported_names = {} self.Trans._from_import_aliases = {}
self.Trans._t_c_imported_names[asname] = (module, name) self.Trans._from_import_aliases[asname] = (module, name)
if name in Gen.functions: if name in Gen.functions:
Gen.functions[asname] = Gen.functions[name] Gen.functions[asname] = Gen.functions[name]
if name in Gen.structs: if name in Gen.structs:
@@ -567,24 +564,11 @@ class ImportHandle(BaseHandle):
def _EmitImportFromDeclarationsLlvm(self, Node: ast.ImportFrom, Gen: LlvmGeneratorMixin) -> None: def _EmitImportFromDeclarationsLlvm(self, Node: ast.ImportFrom, Gen: LlvmGeneratorMixin) -> None:
module = Node.module if Node.module else '' module = Node.module if Node.module else ''
if module in ('c', 't'): # 内建标记按裸名书写,不存在可导入的 t / c 模块。
if not getattr(self.Trans, '_ImportedModules', None): if module in ('t', 'c'):
self.Trans._ImportedModules = set() raise TypeError(
self.Trans._ImportedModules.add(module) f"不支持 `from {module} import ...`:请直接使用内建裸名标记"
if not hasattr(self.Trans, '_t_c_imported_names'): f"(如 CPtr、CInt、CDefine、Asm)")
self.Trans._t_c_imported_names = {}
# 注册 t/c 类型别名到 _t_type_symbols(CType 子类)
t_type_syms = self.Trans.SymbolTable._t_type_symbols
for alias in Node.names:
name = alias.name
asname = alias.asname or name
self.Trans._t_c_imported_names[asname] = (module, name)
# 仅注册 CType 子类(CEnum/CUnion/CStruct/REnum 等)
if module == 't':
cls = getattr(t, name, None)
if isinstance(cls, type) and issubclass(cls, t.CType):
t_type_syms[asname] = cls
return
if not getattr(self.Trans, '_ImportedModules', None): if not getattr(self.Trans, '_ImportedModules', None):
self.Trans._ImportedModules = set() self.Trans._ImportedModules = set()
current_module = self._get_current_module_name() current_module = self._get_current_module_name()
@@ -1271,8 +1255,8 @@ class ImportHandle(BaseHandle):
def _AnnotationStructName(self, annotation: ast.AST) -> str | None: def _AnnotationStructName(self, annotation: ast.AST) -> str | None:
"""从注解里提取「指针指向的类」短名(递归,0 判定返回 None) """从注解里提取「指针指向的类」短名(递归,0 判定返回 None)
覆盖形态:`X` / `mod.X` / `rawptr[X]` / `t.CPtr[X]` / 联合 `A | B`(两翼都试)。 覆盖形态:`X` / `mod.X` / `rawptr[X]` / `CPtr[X]` / 联合 `A | B`(两翼都试)。
存储类与限定符标记(`t.CExtern` / `t.CExport` / `t.CPtr` 等)不算类名, 存储类与限定符标记(`CExtern` / `CExport` / `CPtr` 等)不算类名,
由 `_MARKER_ANNOT_NAMES` 过滤;返回的是**短名**,调用方再解析成 由 `_MARKER_ANNOT_NAMES` 过滤;返回的是**短名**,调用方再解析成
`Gen.structs` 真实键。 `Gen.structs` 真实键。
""" """
@@ -1301,9 +1285,7 @@ class ImportHandle(BaseHandle):
return None return None
return annotation.id return annotation.id
if isinstance(annotation, ast.Attribute): if isinstance(annotation, ast.Attribute):
# `mod.Class`:mod 为 t/c 时是内建标记/内建类型名,不作为类的键 # `mod.Class`:属性名是内建标记/内建类型名时,不作为类的键
if isinstance(annotation.value, ast.Name) and annotation.value.id in ('t', 'c'):
return None
if annotation.attr in _MARKER_ANNOT_NAMES: if annotation.attr in _MARKER_ANNOT_NAMES:
return None return None
return annotation.attr return annotation.attr
@@ -1339,7 +1321,7 @@ class ImportHandle(BaseHandle):
is_string_val = False is_string_val = False
TypeInfo = None TypeInfo = None
# 【跨模块模块级变量的**类登记**】`CTypeInfo.FromNode` 对 # 【跨模块模块级变量的**类登记**】`CTypeInfo.FromNode` 对
# `X | t.CPtr` / `rawptr[X]` 注解只给出指针占位(rawptr[X] 折叠成 i8*), # `X | CPtr` / `rawptr[X]` 注解只给出指针占位(rawptr[X] 折叠成 i8*),
# 且本函数**只算类型、不登记变量类** → 消费侧 `Mod.Var.Field` 链在 # 且本函数**只算类型、不登记变量类** → 消费侧 `Mod.Var.Field` 链在
# `_get_var_class` 里解析为空:StructGenMixin.vp:139 "属性访问未能解析出 # `_get_var_class` 里解析为空:StructGenMixin.vp:139 "属性访问未能解析出
# 目标类型/成员"、CallGenLeafKit.vp:589 / ClassGenVTable.vp:99 误报 # 目标类型/成员"、CallGenLeafKit.vp:589 / ClassGenVTable.vp:99 误报
@@ -1365,7 +1347,7 @@ class ImportHandle(BaseHandle):
if Node.annotation: if Node.annotation:
parse_result = ParseListAnnotation(Node.annotation) parse_result = ParseListAnnotation(Node.annotation)
if parse_result and not parse_result.is_pointer: if parse_result and not parse_result.is_pointer:
# t.CArray[type, count] 数组声明 # CArray[type, count] 数组声明
elem_type_node = parse_result.elem_type_node elem_type_node = parse_result.elem_type_node
count_node = parse_result.count_node count_node = parse_result.count_node
ElemTypeInfo = CTypeInfo.FromNode(elem_type_node, self.Trans.SymbolTable) ElemTypeInfo = CTypeInfo.FromNode(elem_type_node, self.Trans.SymbolTable)
@@ -1408,17 +1390,11 @@ class ImportHandle(BaseHandle):
# 检查是否是 CDefine 常量或 CTypedef 类型别名 # 检查是否是 CDefine 常量或 CTypedef 类型别名
IsCDefine = False IsCDefine = False
IsCTypedef = False IsCTypedef = False
if Node.annotation: if isinstance(Node.annotation, ast.Name):
if isinstance(Node.annotation, ast.Attribute): if Node.annotation.id == 'CDefine':
if getattr(Node.annotation.value, 'id', None) == 't' and Node.annotation.attr == 'CDefine': IsCDefine = True
IsCDefine = True elif Node.annotation.id == 'CTypedef':
elif getattr(Node.annotation.value, 'id', None) == 't' and Node.annotation.attr == 'CTypedef': IsCTypedef = True
IsCTypedef = True
elif isinstance(Node.annotation, ast.Name):
if Node.annotation.id == 'CDefine':
IsCDefine = True
elif Node.annotation.id == 'CTypedef':
IsCTypedef = True
if IsCTypedef: if IsCTypedef:
# 检查符号是否已存在且已正确解析(OriginalType 已设置),避免覆盖 # 检查符号是否已存在且已正确解析(OriginalType 已设置),避免覆盖
@@ -1432,13 +1408,13 @@ class ImportHandle(BaseHandle):
else: else:
ValueTypeInfo = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.value) ValueTypeInfo = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.value)
if isinstance(ValueTypeInfo, CTypeInfo) and (ValueTypeInfo.BaseType or ValueTypeInfo.PtrCount > 0): if isinstance(ValueTypeInfo, CTypeInfo) and (ValueTypeInfo.BaseType or ValueTypeInfo.PtrCount > 0):
# GetCTypeInfo 对 t.CInt 等 Attribute 返回的 BaseType 可能是 CType 基类实例 # GetCTypeInfo 对 CInt 等 Attribute 返回的 BaseType 可能是 CType 基类实例
# (而非具体子类如 CInt),导致 _resolve_typedef_int_width 无法解析位宽。 # (而非具体子类如 CInt),导致 _resolve_typedef_int_width 无法解析位宽。
# 此时从 Node.value 提取类型名,设置 OriginalType 为字符串, # 此时从 Node.value 提取类型名,设置 OriginalType 为字符串,
# 让 _resolve_typedef_int_width 通过 CTypeRegistry.GetClassByName 解析。 # 让 _resolve_typedef_int_width 通过 CTypeRegistry.GetClassByName 解析。
if ValueTypeInfo.BaseType and type(ValueTypeInfo.BaseType) is t.CType: if ValueTypeInfo.BaseType and type(ValueTypeInfo.BaseType) is TypeSystem.CType:
if isinstance(Node.value, ast.Attribute) and getattr(Node.value.value, 'id', None) == 't': if isinstance(Node.value, ast.Name):
type_name: str = Node.value.attr type_name: str = Node.value.id
resolved_cls = CTypeRegistry.GetClassByName(type_name) resolved_cls = CTypeRegistry.GetClassByName(type_name)
if resolved_cls is not None: if resolved_cls is not None:
ValueTypeInfo.OriginalType = type_name ValueTypeInfo.OriginalType = type_name
@@ -1488,7 +1464,7 @@ class ImportHandle(BaseHandle):
self._RegisterCDefineSymbol(FullName, DefineValue, Node.lineno, ModulePath or 'unknown') self._RegisterCDefineSymbol(FullName, DefineValue, Node.lineno, ModulePath or 'unknown')
return # 不再继续生成 LLVM 全局变量 return # 不再继续生成 LLVM 全局变量
# t.State 标记的全局变量:只声明不定义(external linkage),避免 DSO/non-DSO 重定义 # State 标记的全局变量:只声明不定义(external linkage),避免 DSO/non-DSO 重定义
if TypeInfo and TypeInfo.IsState: if TypeInfo and TypeInfo.IsState:
if VarName not in Gen.module.globals: if VarName not in Gen.module.globals:
gv = ir.GlobalVariable(Gen.module, var_type, name=VarName) gv = ir.GlobalVariable(Gen.module, var_type, name=VarName)
@@ -1612,22 +1588,13 @@ class ImportHandle(BaseHandle):
if info.IsDefine and info.DefineValue is not None: if info.IsDefine and info.DefineValue is not None:
return info.DefineValue return info.DefineValue
elif isinstance(value_node, ast.Call): elif isinstance(value_node, ast.Call):
if isinstance(value_node.func, ast.Attribute): if isinstance(value_node.func, ast.Name):
if getattr(value_node.func.value, 'id', None) == 't':
if value_node.args:
return self._ExtractConstValue(value_node.args[0])
elif isinstance(value_node.func, ast.Name):
if value_node.args: if value_node.args:
return self._ExtractConstValue(value_node.args[0]) return self._ExtractConstValue(value_node.args[0])
return None return None
def _ExtractTypedefOriginalType(self, value_node: ast.AST) -> str | None: def _ExtractTypedefOriginalType(self, value_node: ast.AST) -> str | None:
if isinstance(value_node, ast.Attribute): if isinstance(value_node, ast.Name):
if getattr(value_node.value, 'id', None) == 't':
llvm_str = CTypeRegistry.NameToLLVM(value_node.attr)
if llvm_str:
return llvm_str
elif isinstance(value_node, ast.Name):
llvm_str = CTypeRegistry.NameToLLVM(value_node.id) llvm_str = CTypeRegistry.NameToLLVM(value_node.id)
if llvm_str: if llvm_str:
return llvm_str return llvm_str
@@ -1642,12 +1609,7 @@ class ImportHandle(BaseHandle):
if parts: if parts:
return '|'.join(parts) return '|'.join(parts)
elif isinstance(value_node, ast.Call): elif isinstance(value_node, ast.Call):
if isinstance(value_node.func, ast.Attribute): if isinstance(value_node.func, ast.Name):
if getattr(value_node.func.value, 'id', None) == 't':
llvm_str = CTypeRegistry.NameToLLVM(value_node.func.attr)
if llvm_str:
return llvm_str
elif isinstance(value_node.func, ast.Name):
llvm_str = CTypeRegistry.NameToLLVM(value_node.func.id) llvm_str = CTypeRegistry.NameToLLVM(value_node.func.id)
if llvm_str: if llvm_str:
return llvm_str return llvm_str
@@ -1656,7 +1618,7 @@ class ImportHandle(BaseHandle):
def _RegisterCDefineSymbol(self, FullName: str, DefineValue: object, lineno: int, FilePath: str) -> None: def _RegisterCDefineSymbol(self, FullName: str, DefineValue: object, lineno: int, FilePath: str) -> None:
"""Register CDefine constant to SymbolTable""" """Register CDefine constant to SymbolTable"""
# 防御:新值为 None 但已存在非 None 值时保留旧值。 # 防御:新值为 None 但已存在非 None 值时保留旧值。
# 翻译期间声明发射调用 _ExtractConstValue(不支持 ast.Attribute 形式如 t.CSizeT().Size), # 翻译期间声明发射调用 _ExtractConstValue(不支持 ast.Attribute 形式如 CSizeT().Size),
# 会返回 None 并覆盖共享符号表中已由 ConstEvaluator 正确求值的值(如 8)。 # 会返回 None 并覆盖共享符号表中已由 ConstEvaluator 正确求值的值(如 8)。
# 共享符号表在 _build_shared_symbol_data 阶段已正确求值,此处不应覆盖。 # 共享符号表在 _build_shared_symbol_data 阶段已正确求值,此处不应覆盖。
if DefineValue is None: if DefineValue is None:
@@ -1677,7 +1639,7 @@ class ImportHandle(BaseHandle):
AnnotationContainsName(annotation, 'State')) AnnotationContainsName(annotation, 'State'))
def _check_decorators_for_state(self, Node: ast.FunctionDef) -> bool: def _check_decorators_for_state(self, Node: ast.FunctionDef) -> bool:
"""检查装饰器列表中是否包含 @t.CExport / @t.CExtern / @t.State(t.CExport 既能作返回值注解也能作装饰器)""" """检查装饰器列表中是否包含 @CExport / @CExtern / @State(CExport 既能作返回值注解也能作装饰器)"""
if not Node.decorator_list: if not Node.decorator_list:
return False return False
for decorator in Node.decorator_list: for decorator in Node.decorator_list:
@@ -1690,8 +1652,8 @@ class ImportHandle(BaseHandle):
def _EmitExternalFuncDeclLlvm(self, Node: ast.FunctionDef, Gen: LlvmGeneratorMixin, is_class_method: bool = False, source_module_name: str | None = None, register_module_name: str | None = None, reexport_module_names: list[str] | None = None) -> None: def _EmitExternalFuncDeclLlvm(self, Node: ast.FunctionDef, Gen: LlvmGeneratorMixin, is_class_method: bool = False, source_module_name: str | None = None, register_module_name: str | None = None, reexport_module_names: list[str] | None = None) -> None:
FuncName = Node.name FuncName = Node.name
if (Node.returns and self._check_annotation_for_state(Node.returns)) or self._check_decorators_for_state(Node): if (Node.returns and self._check_annotation_for_state(Node.returns)) or self._check_decorators_for_state(Node):
Gen._export_funcs.add(FuncName) # t.State 标记的外部 C 函数必须保持原始名称,以便链接器解析 Gen._export_funcs.add(FuncName) # State 标记的外部 C 函数必须保持原始名称,以便链接器解析
if source_module_name and source_module_name not in ('c', 't'): if source_module_name:
_src_sha1 = Gen.ModuleSha1Map.get(source_module_name) _src_sha1 = Gen.ModuleSha1Map.get(source_module_name)
if not _src_sha1: if not _src_sha1:
_init_name = f"{source_module_name}.__init__" _init_name = f"{source_module_name}.__init__"
@@ -1719,10 +1681,10 @@ class ImportHandle(BaseHandle):
if Node.decorator_list: if Node.decorator_list:
for decorator in Node.decorator_list: for decorator in Node.decorator_list:
if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute): if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute):
# fail-fast:`@c.CReturn` 已移除,扫到即报错。 # fail-fast:`@CReturn` 已移除,扫到即报错。
if decorator.func.attr == 'CReturn': if decorator.func.attr == 'CReturn':
raise SyntaxError( raise SyntaxError(
f"函数 '{FuncName}':`@c.CReturn` 已移除:请改用返回注解 " f"函数 '{FuncName}':`@CReturn` 已移除:请改用返回注解 "
f"`-> tuple[ty1, ty2, ...]`(多返回值打包为 struct)" f"`-> tuple[ty1, ty2, ...]`(多返回值打包为 struct)"
) )
IsPtr = False IsPtr = False
@@ -1731,14 +1693,14 @@ class ImportHandle(BaseHandle):
try: try:
ReturnTypeInfo = self.ResolveAnnotationType(Node.returns) ReturnTypeInfo = self.ResolveAnnotationType(Node.returns)
# 仅指针层数 <=1 才算裸 str/bytes(i8*)。 # 仅指针层数 <=1 才算裸 str/bytes(i8*)。
# `str | t.CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),不能压平。 # `str | CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),不能压平。
if ReturnTypeInfo and ReturnTypeInfo.IsStr and ReturnTypeInfo.PtrCount <= 1: if ReturnTypeInfo and ReturnTypeInfo.IsStr and ReturnTypeInfo.PtrCount <= 1:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CChar() ReturnTypeInfo.BaseType = TypeSystem.CChar()
ReturnTypeInfo.PtrCount = 1 ReturnTypeInfo.PtrCount = 1
if ReturnTypeInfo is None: if ReturnTypeInfo is None:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CInt() ReturnTypeInfo.BaseType = TypeSystem.CInt()
IsPtr = ReturnTypeInfo.IsPtr IsPtr = ReturnTypeInfo.IsPtr
except RecursionError: except RecursionError:
# 家族口径(HandlesBase.py:1060-1068):RecursionError 是类型解析链成环的 # 家族口径(HandlesBase.py:1060-1068):RecursionError 是类型解析链成环的
@@ -1750,10 +1712,10 @@ class ImportHandle(BaseHandle):
if not (isinstance(e, AttributeError) and "'NoneType'" in str(e)): if not (isinstance(e, AttributeError) and "'NoneType'" in str(e)):
_vlog().warning(f"HandlesImports: 忽略异常 {e}", exc_info=e) _vlog().warning(f"HandlesImports: 忽略异常 {e}", exc_info=e)
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CInt() ReturnTypeInfo.BaseType = TypeSystem.CInt()
else: else:
ReturnTypeInfo = CTypeInfo() ReturnTypeInfo = CTypeInfo()
ReturnTypeInfo.BaseType = t.CInt() ReturnTypeInfo.BaseType = TypeSystem.CInt()
ReturnType = Gen._ctype_to_llvm(ReturnTypeInfo) ReturnType = Gen._ctype_to_llvm(ReturnTypeInfo)
if (isinstance(ReturnType, ir.VoidType) or (isinstance(ReturnType, ir.PointerType) and isinstance(ReturnType.pointee, ir.VoidType))) and Node.returns: if (isinstance(ReturnType, ir.VoidType) or (isinstance(ReturnType, ir.PointerType) and isinstance(ReturnType.pointee, ir.VoidType))) and Node.returns:
RetAnnName = None RetAnnName = None
@@ -1772,7 +1734,7 @@ class ImportHandle(BaseHandle):
elif IsPtr or RetAnnName: elif IsPtr or RetAnnName:
ReturnType = ir.PointerType(ir.IntType(8)) ReturnType = ir.PointerType(ir.IntType(8))
# __new__ 方法应返回类指针类型(堆分配替换),与 _GetFunctionSignatureLlvm/_EmitFunctionLlvm 保持一致 # __new__ 方法应返回类指针类型(堆分配替换),与 _GetFunctionSignatureLlvm/_EmitFunctionLlvm 保持一致
# .pyi 生成器对无返回类型注解的 __new__ 默认使用 t.CInt,这里修正为 ClassName* # .pyi 生成器对无返回类型注解的 __new__ 默认使用 CInt,这里修正为 ClassName*
if '.__new__' in FuncName: if '.__new__' in FuncName:
_np = FuncName.split('.') _np = FuncName.split('.')
if len(_np[0]) == 16 and all(_c in '0123456789abcdef' for _c in _np[0]): if len(_np[0]) == 16 and all(_c in '0123456789abcdef' for _c in _np[0]):
@@ -1830,20 +1792,20 @@ class ImportHandle(BaseHandle):
ParamTypeInfo = self.ResolveAnnotationType(Arg.annotation) ParamTypeInfo = self.ResolveAnnotationType(Arg.annotation)
if ParamTypeInfo is None: if ParamTypeInfo is None:
ParamTypeInfo = CTypeInfo() ParamTypeInfo = CTypeInfo()
ParamTypeInfo.BaseType = t.CInt() ParamTypeInfo.BaseType = TypeSystem.CInt()
ParamIsPtr = ParamTypeInfo.IsPtr ParamIsPtr = ParamTypeInfo.IsPtr
if i == 0 and is_method and Arg.arg == 'self' and class_is_cpython: if i == 0 and is_method and Arg.arg == 'self' and class_is_cpython:
ParamIsPtr = True ParamIsPtr = True
ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1) ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1)
# 仅当指针层数 <=1 时才压平为 i8*(裸 str/bytes)。 # 仅当指针层数 <=1 时才压平为 i8*(裸 str/bytes)。
# `str | t.CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组), # `str | CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),
# 不能压平,否则形参类型错误导致 _adjust_args 多 load 一层崩溃。 # 不能压平,否则形参类型错误导致 _adjust_args 多 load 一层崩溃。
if (ParamTypeInfo.IsStr and ParamTypeInfo.PtrCount <= 1) or (isinstance(Arg.annotation, ast.Name) and Arg.annotation.id in ('str', 'bytes')): if (ParamTypeInfo.IsStr and ParamTypeInfo.PtrCount <= 1) or (isinstance(Arg.annotation, ast.Name) and Arg.annotation.id in ('str', 'bytes')):
ParamTypeInfo = CTypeInfo() ParamTypeInfo = CTypeInfo()
ParamTypeInfo.BaseType = t.CChar() ParamTypeInfo.BaseType = TypeSystem.CChar()
ParamTypeInfo.PtrCount = 1 ParamTypeInfo.PtrCount = 1
ParamIsPtr = True ParamIsPtr = True
# C 语言中数组参数退化为指针:t.CArray[type, N] → type* # C 语言中数组参数退化为指针:CArray[type, N] → type*
if ParamTypeInfo.ArrayDims: if ParamTypeInfo.ArrayDims:
ParamTypeInfo.ArrayDims = [] ParamTypeInfo.ArrayDims = []
ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1) ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1)
@@ -1877,10 +1839,10 @@ class ImportHandle(BaseHandle):
_is_export = False _is_export = False
if isinstance(ReturnTypeInfo, CTypeInfo) and ReturnTypeInfo.IsState: if isinstance(ReturnTypeInfo, CTypeInfo) and ReturnTypeInfo.IsState:
_is_export = True _is_export = True
if isinstance(ReturnTypeInfo, CTypeInfo) and ReturnTypeInfo.Storage and isinstance(ReturnTypeInfo.Storage, t.CExport) and not ReturnTypeInfo.IsState: if isinstance(ReturnTypeInfo, CTypeInfo) and ReturnTypeInfo.Storage and isinstance(ReturnTypeInfo.Storage, TypeSystem.CExport) and not ReturnTypeInfo.IsState:
Gen._export_funcs.add(FuncName) Gen._export_funcs.add(FuncName)
_is_export = True _is_export = True
if isinstance(ReturnTypeInfo, CTypeInfo) and ReturnTypeInfo.Storage and isinstance(ReturnTypeInfo.Storage, t.CExtern): if isinstance(ReturnTypeInfo, CTypeInfo) and ReturnTypeInfo.Storage and isinstance(ReturnTypeInfo.Storage, TypeSystem.CExtern):
Gen._export_funcs.add(FuncName) Gen._export_funcs.add(FuncName)
_is_export = True _is_export = True
if not _is_export: if not _is_export:
@@ -1931,7 +1893,7 @@ class ImportHandle(BaseHandle):
if existing.MetaList == FuncMeta.NONE and func_meta != FuncMeta.NONE: if existing.MetaList == FuncMeta.NONE and func_meta != FuncMeta.NONE:
existing.MetaList = func_meta existing.MetaList = func_meta
# 同时注册带模块前缀的符号,以便 module.func_name 查找能命中 # 同时注册带模块前缀的符号,以便 module.func_name 查找能命中
if source_module_name and source_module_name not in ('c', 't'): if source_module_name:
FullSymKey = f"{source_module_name}.{FuncName}" FullSymKey = f"{source_module_name}.{FuncName}"
if not self.Trans.SymbolTable.has(FullSymKey): if not self.Trans.SymbolTable.has(FullSymKey):
FullFuncInfo = CTypeInfo() FullFuncInfo = CTypeInfo()
@@ -1999,28 +1961,19 @@ class ImportHandle(BaseHandle):
break break
if not IsCenum and not IsRenum and getattr(Node, 'decorator_list', None): if not IsCenum and not IsRenum and getattr(Node, 'decorator_list', None):
for decorator in Node.decorator_list: for decorator in Node.decorator_list:
if isinstance(decorator, ast.Attribute): if isinstance(decorator, ast.Name):
if getattr(decorator.value, 'id', None) == 't': if decorator.id == 'Object':
if decorator.attr == 'Object': IsCpythonObject = True
IsCpythonObject = True elif decorator.id == 'CVTable':
elif decorator.attr == 'CVTable': IsCVTable = True
IsCVTable = True elif decorator.id == 'NoVTable':
elif decorator.attr == 'NoVTable': IsNoVTable = True
IsNoVTable = True elif decorator.id == 'REnum':
elif decorator.attr == 'REnum': IsRenum = True
IsRenum = True elif decorator.id == 'CEnum' or decorator.id == 'Enum':
elif decorator.attr == 'CEnum' or decorator.attr == 'Enum': IsCenum = True
IsCenum = True
elif isinstance(decorator, ast.Call): elif isinstance(decorator, ast.Call):
if isinstance(decorator.func, ast.Attribute): if isinstance(decorator.func, ast.Name):
if getattr(decorator.func.value, 'id', None) == 't':
if decorator.func.attr == 'Object':
IsCpythonObject = True
elif decorator.func.attr == 'CVTable':
IsCVTable = True
elif decorator.func.attr == 'NoVTable':
IsNoVTable = True
elif isinstance(decorator.func, ast.Name):
if decorator.func.id == 'Object': if decorator.func.id == 'Object':
IsCpythonObject = True IsCpythonObject = True
elif decorator.func.id == 'CVTable': elif decorator.func.id == 'CVTable':
@@ -2031,14 +1984,14 @@ class ImportHandle(BaseHandle):
if getattr(Node, 'decorator_list', None): if getattr(Node, 'decorator_list', None):
for decorator in Node.decorator_list: for decorator in Node.decorator_list:
if isinstance(decorator, ast.Call): if isinstance(decorator, ast.Call):
if isinstance(decorator.func, ast.Attribute): if isinstance(decorator.func, ast.Name) and decorator.func.id == 'Attribute':
if getattr(decorator.func.value, 'id', None) == 'c' and decorator.func.attr == 'Attribute': for arg in decorator.args:
for arg in decorator.args: if (isinstance(arg, ast.Attribute)
if isinstance(arg, ast.Attribute): and isinstance(arg.value, ast.Name)
if isinstance(arg.value, ast.Attribute): and arg.value.id == 'attr'
if getattr(arg.value.value, 'id', None) == 't' and arg.value.attr == 'attr' and arg.attr == 'packed': and arg.attr == 'packed'):
IsPacked = True IsPacked = True
# 方法级 virtual(`virtual def m(...)` ⇒ 方法装饰器 @t.CVTable)触发类级 vtable: # 方法级 virtual(`virtual def m(...)` ⇒ 方法装饰器 @CVTable)触发类级 vtable:
# 与 HandlesClassDef._resolve_class_flags / VPC _detect_vtable_status 的 # 与 HandlesClassDef._resolve_class_flags / VPC _detect_vtable_status 的
# `_has_any_func_cvtable` 分支对齐(跨模块这里只能判"类级 NoVTable / # `_has_any_func_cvtable` 分支对齐(跨模块这里只能判"类级 NoVTable /
# 无真实父类"两种可判定形态;父类 vtable 状态由 .pyi 按需注册路径解析)。 # 无真实父类"两种可判定形态;父类 vtable 状态由 .pyi 按需注册路径解析)。
@@ -2088,7 +2041,7 @@ class ImportHandle(BaseHandle):
if IsCenum: if IsCenum:
EnumTypeNode = CTypeInfo() EnumTypeNode = CTypeInfo()
EnumTypeNode.Name = ClassName EnumTypeNode.Name = ClassName
EnumTypeNode.BaseType = t.CEnum(ClassName) EnumTypeNode.BaseType = TypeSystem.CEnum(ClassName)
EnumTypeNode.IsEnum = True EnumTypeNode.IsEnum = True
# [跨模块枚举宽度] 读侧重推导:.vpi/.pyi 保留成员注解(`Name: T`), # [跨模块枚举宽度] 读侧重推导:.vpi/.pyi 保留成员注解(`Name: T`),
# 故在本处按"最宽成员类型"重算(与定义端 HandlesClassDef 同一规则源 # 故在本处按"最宽成员类型"重算(与定义端 HandlesClassDef 同一规则源
@@ -2123,7 +2076,7 @@ class ImportHandle(BaseHandle):
next_enum_value += 1 next_enum_value += 1
MemberNode = CTypeInfo() MemberNode = CTypeInfo()
MemberNode.Name = VarName MemberNode.Name = VarName
MemberNode.BaseType = t.CEnum(ClassName) MemberNode.BaseType = TypeSystem.CEnum(ClassName)
MemberNode.value = value MemberNode.value = value
MemberNode.EnumName = ClassName MemberNode.EnumName = ClassName
MemberNode.Lineno = item.lineno MemberNode.Lineno = item.lineno
@@ -2141,7 +2094,7 @@ class ImportHandle(BaseHandle):
RenumTypeNode.IsRenum = True RenumTypeNode.IsRenum = True
RenumTypeNode.IsEnum = True # 兼容 IsEnum 检查 RenumTypeNode.IsEnum = True # 兼容 IsEnum 检查
# REnum 在内存布局上是 struct,必须设置 IsStruct=True 才能让 # REnum 在内存布局上是 struct,必须设置 IsStruct=True 才能让
# HandlesTypeMerge 的 CPtr 吸收逻辑生效(REnumType | t.CPtr = REnumType*) # HandlesTypeMerge 的 CPtr 吸收逻辑生效(REnumType | CPtr = REnumType*)
RenumTypeNode.IsStruct = True RenumTypeNode.IsStruct = True
if module_name: if module_name:
FullName = f"{module_name}.{ClassName}" FullName = f"{module_name}.{ClassName}"
@@ -2314,8 +2267,8 @@ class ImportHandle(BaseHandle):
# 会被解析为 opaque struct,LLVM 报 "invalid type for function argument"。 # 会被解析为 opaque struct,LLVM 报 "invalid type for function argument"。
# 字段(AnnAssign)仍正常加载,确保继承字段(如 GSListNode.Next)可被展平。 # 字段(AnnAssign)仍正常加载,确保继承字段(如 GSListNode.Next)可被展平。
if not IsGenericClass: if not IsGenericClass:
# 虚表槽筛选:方法级 `novirtual def`(⇒ @t.NoVTable)不进槽、方法级 # 虚表槽筛选:方法级 `novirtual def`(⇒ @NoVTable)不进槽、方法级
# `virtual def`(⇒ @t.CVTable)进槽——判据为 SymbolUtils.IsVtableSlotMethod # `virtual def`(⇒ @CVTable)进槽——判据为 SymbolUtils.IsVtableSlotMethod
# (唯一规则源,与定义端 HandlesClassDef / VPC _should_method_be_virtual 同口径), # (唯一规则源,与定义端 HandlesClassDef / VPC _should_method_be_virtual 同口径),
# 保证跨模块虚表槽序与定义模块逐槽一致。 # 保证跨模块虚表槽序与定义模块逐槽一致。
_VtByClassLevel: bool = _VtableByClassLevelForImport(Node, Gen) _VtByClassLevel: bool = _VtableByClassLevelForImport(Node, Gen)
@@ -2404,7 +2357,7 @@ class ImportHandle(BaseHandle):
if VarName not in {m[0] for m in Gen.class_members[ClassName]}: if VarName not in {m[0] for m in Gen.class_members[ClassName]}:
Gen.class_members[ClassName].append((VarName, MemberType)) Gen.class_members[ClassName].append((VarName, MemberType))
Gen.class_member_bitfields[ClassName][VarName] = 0 Gen.class_member_bitfields[ClassName][VarName] = 0
# 与 HandlesClassDef 对齐:联合类型字段(如 `list[str] | t.CPtr`) # 与 HandlesClassDef 对齐:联合类型字段(如 `list[str] | CPtr`)
# 记录泛型特化名到 class_member_element_class。否则跨模块 import # 记录泛型特化名到 class_member_element_class。否则跨模块 import
# 的类(如 TypeGenBase.CTypedefNames)缺此记录,_HandleLenLlvm # 的类(如 TypeGenBase.CTypedefNames)缺此记录,_HandleLenLlvm
# 无法识别字段为 list → len() 误编译为 strlen → stdint 崩溃。 # 无法识别字段为 list → len() 误编译为 strlen → stdint 崩溃。
@@ -2468,7 +2421,7 @@ class ImportHandle(BaseHandle):
else: else:
# rawptr[裸结构](如 rawptr[Token]):跨模块 stub 会把自引用/类内 # rawptr[裸结构](如 rawptr[Token]):跨模块 stub 会把自引用/类内
# 指针字段退化为 i8*,链式成员访问(a.b.c)需 element_class 恢复 # 指针字段退化为 i8*,链式成员访问(a.b.c)需 element_class 恢复
# struct 身份走 char*→struct cast。HEAD 态 `Token | t.CPtr` 联合 # struct 身份走 char*→struct cast。HEAD 态 `Token | CPtr` 联合
# 由上方 BinOp 分支登记;rawptr 重构后此分支补齐(阻塞 A 根因)。 # 由上方 BinOp 分支登记;rawptr 重构后此分支补齐(阻塞 A 根因)。
# 与 HandlesClassDef 的 rawptr 分支对称。 # 与 HandlesClassDef 的 rawptr 分支对称。
_slc_name_s: str | None = None _slc_name_s: str | None = None
@@ -2874,7 +2827,7 @@ class ImportHandle(BaseHandle):
_mn: str = _m.split('.')[-1] if '.' in _m else _m _mn: str = _m.split('.')[-1] if '.' in _m else _m
_child_method_map[_mn] = _m _child_method_map[_mn] = _m
# 从 .vpi 的 FunctionDef 补充子类方法映射(覆盖方法可能尚未注册)。 # 从 .vpi 的 FunctionDef 补充子类方法映射(覆盖方法可能尚未注册)。
# 方法级 `novirtual def`(⇒ @t.NoVTable)不占槽,**不得**用它覆盖父类槽位 # 方法级 `novirtual def`(⇒ @NoVTable)不占槽,**不得**用它覆盖父类槽位
# ——与 VPC _collect_vtable_methods 的 child_nvt 分支同口径(子类标记 # ——与 VPC _collect_vtable_methods 的 child_nvt 分支同口径(子类标记
# NoVTable 时槽位仍指向实际定义类的实现)。 # NoVTable 时槽位仍指向实际定义类的实现)。
_VtByClassLevelC: bool = _VtableByClassLevelForImport(Node, Gen) _VtByClassLevelC: bool = _VtableByClassLevelForImport(Node, Gen)
@@ -3908,7 +3861,7 @@ class ImportHandle(BaseHandle):
func_type = self._parse_llvm_declare(stripped, Gen) func_type = self._parse_llvm_declare(stripped, Gen)
if func_type is not None: if func_type is not None:
# __new__ 方法应返回类指针类型(堆分配替换),与 _GetFunctionSignatureLlvm/_EmitFunctionLlvm 保持一致 # __new__ 方法应返回类指针类型(堆分配替换),与 _GetFunctionSignatureLlvm/_EmitFunctionLlvm 保持一致
# .stub.ll 由 .pyi 生成,.pyi 生成器对无返回类型注解的 __new__ 默认使用 t.CInt,这里修正为 ClassName* # .stub.ll 由 .pyi 生成,.pyi 生成器对无返回类型注解的 __new__ 默认使用 CInt,这里修正为 ClassName*
if '.__new__' in func_name: if '.__new__' in func_name:
_np = func_name.split('.') _np = func_name.split('.')
if len(_np[0]) == 16 and all(_c in '0123456789abcdef' for _c in _np[0]): if len(_np[0]) == 16 and all(_c in '0123456789abcdef' for _c in _np[0]):
+6 -9
View File
@@ -350,21 +350,18 @@ class MatchHandle(BaseHandle):
if not HasDefault: if not HasDefault:
Gen.builder.position_at_start(DefaultBB) Gen.builder.position_at_start(DefaultBB)
Gen.builder.branch(AfterBB) Gen.builder.branch(AfterBB)
elif not any(isinstance(c.pattern, ast.MatchAs) and c.pattern.pattern is None for c in Node.cases) and not any(isinstance(c.pattern, ast.MatchSequence) for c in Node.cases): elif not any(isinstance(pattern, ast.MatchAs) and c.pattern.pattern is None for c in Node.cases) and not any(isinstance(pattern, ast.MatchSequence) for c in Node.cases):
Gen.builder.position_at_start(DefaultBB) Gen.builder.position_at_start(DefaultBB)
Gen.builder.branch(AfterBB) Gen.builder.branch(AfterBB)
Gen.builder.position_at_start(AfterBB) Gen.builder.position_at_start(AfterBB)
@staticmethod @staticmethod
def _HasNoBreakMarker(Stmts: list[ast.stmt]) -> bool: def _HasNoBreakMarker(Stmts: list[ast.stmt]) -> bool:
"""case 体(含其嵌套 body/orelse)是否含 `fallthrough` 标记(c.NoBreak())""" """case 体(含其嵌套 body/orelse)是否含 `fallthrough` 标记(NoBreak())"""
for stmt in Stmts: for stmt in Stmts:
if isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Call): if isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Call):
if isinstance(stmt.value.func, ast.Attribute): if isinstance(stmt.value.func, ast.Name) and stmt.value.func.id == 'NoBreak':
if (isinstance(stmt.value.func.value, ast.Name) and return True
stmt.value.func.value.id == 'c' and
stmt.value.func.attr == 'NoBreak'):
return True
NestedBody: Any = getattr(stmt, 'body', None) NestedBody: Any = getattr(stmt, 'body', None)
if NestedBody and isinstance(NestedBody, list) and MatchHandle._HasNoBreakMarker(NestedBody): if NestedBody and isinstance(NestedBody, list) and MatchHandle._HasNoBreakMarker(NestedBody):
return True return True
@@ -398,7 +395,7 @@ class MatchHandle(BaseHandle):
def _FallThroughTarget(CaseBBs: list[ir.Block], CaseIdx: int, AfterBB: ir.Block) -> ir.Block: def _FallThroughTarget(CaseBBs: list[ir.Block], CaseIdx: int, AfterBB: ir.Block) -> ir.Block:
"""fallthrough 的落点:下一个 case 的 body(无后继槽位时落到 AfterBB) """fallthrough 的落点:下一个 case 的 body(无后继槽位时落到 AfterBB)
`fallthrough`(vast 关键字,脱糖为 c.NoBreak())表示"本 case 不自动 `fallthrough`(vast 关键字,脱糖为 NoBreak())表示"本 case 不自动
跳出 switch",直接落到下一个 case 的 body(对齐 C 的 [[fallthrough]])。 跳出 switch",直接落到下一个 case 的 body(对齐 C 的 [[fallthrough]])。
""" """
NextIdx: int = CaseIdx + 1 NextIdx: int = CaseIdx + 1
@@ -603,7 +600,7 @@ class MatchHandle(BaseHandle):
if not HasDefault: if not HasDefault:
Gen.builder.position_at_start(DefaultBB) Gen.builder.position_at_start(DefaultBB)
Gen.builder.branch(AfterBB) Gen.builder.branch(AfterBB)
elif not any(isinstance(c.pattern, ast.MatchAs) and c.pattern.pattern is None for c in Node.cases) and not any(isinstance(c.pattern, ast.MatchSequence) for c in Node.cases): elif not any(isinstance(pattern, ast.MatchAs) and c.pattern.pattern is None for c in Node.cases) and not any(isinstance(pattern, ast.MatchSequence) for c in Node.cases):
Gen.builder.position_at_start(DefaultBB) Gen.builder.position_at_start(DefaultBB)
Gen.builder.branch(AfterBB) Gen.builder.branch(AfterBB)
Gen.builder.position_at_start(AfterBB) Gen.builder.position_at_start(AfterBB)
+39 -43
View File
@@ -6,8 +6,7 @@ if TYPE_CHECKING:
from lib.core.translator import Translator from lib.core.translator import Translator
from lib.core.Translator.LlvmGenerator import LlvmGeneratorMixin from lib.core.Translator.LlvmGenerator import LlvmGeneratorMixin
from lib.core.Handles.HandlesBase import BaseHandle from lib.core.Handles.HandlesBase import BaseHandle
from lib.includes.t import CTypeRegistry from lib.core.TypeSystem import CTypeRegistry
from lib.core.SymbolUtils import IsTModule
from lib.core.VLogger import get_logger as _vlog from lib.core.VLogger import get_logger as _vlog
from lib.constants.config import mode as _config_mode from lib.constants.config import mode as _config_mode
@@ -66,14 +65,14 @@ class CSpecialCallHandle(BaseHandle):
var_ptr = Gen.variables[VarName] var_ptr = Gen.variables[VarName]
if isinstance(var_ptr.type, ir.PointerType): if isinstance(var_ptr.type, ir.PointerType):
# For pointer-to-pointer allocas (var_ptr is T**): # For pointer-to-pointer allocas (var_ptr is T**):
# - If T is a named struct (@t.Object class), the variable semantically # - If T is a named struct (@Object class), the variable semantically
# IS the struct, so c.Addr should return the struct pointer value. # IS the struct, so Addr should return the struct pointer value.
# - If T is a primitive pointer type (e.g., i8*), the variable semantically # - If T is a primitive pointer type (e.g., i8*), the variable semantically
# holds a pointer, so c.Addr should return &var (alloca address). # holds a pointer, so Addr should return &var (alloca address).
if isinstance(var_ptr.type.pointee, ir.PointerType): if isinstance(var_ptr.type.pointee, ir.PointerType):
pointee = var_ptr.type.pointee.pointee pointee = var_ptr.type.pointee.pointee
if isinstance(pointee, ir.IdentifiedStructType): if isinstance(pointee, ir.IdentifiedStructType):
# @t.Object class variable — return Loaded struct pointer # @Object class variable — return Loaded struct pointer
ArgVal = self.HandleExprLlvm(Arg) ArgVal = self.HandleExprLlvm(Arg)
if ArgVal and isinstance(ArgVal.type, ir.PointerType): if ArgVal and isinstance(ArgVal.type, ir.PointerType):
return Gen.builder.bitcast(ArgVal, ir.IntType(8).as_pointer(), name="addr_as_i8ptr") return Gen.builder.bitcast(ArgVal, ir.IntType(8).as_pointer(), name="addr_as_i8ptr")
@@ -96,23 +95,22 @@ class CSpecialCallHandle(BaseHandle):
target_arg: ast.expr = Node.args[0] target_arg: ast.expr = Node.args[0]
value_arg: ast.expr = Node.args[1] value_arg: ast.expr = Node.args[1]
target_ptr: ir.Value | None = None target_ptr: ir.Value | None = None
if isinstance(target_arg, ast.Call) and isinstance(target_arg.func, ast.Attribute): if isinstance(target_arg, ast.Call) and isinstance(target_arg.func, ast.Name):
if isinstance(target_arg.func.value, ast.Name) and target_arg.func.value.id == 'c': if target_arg.func.id == 'Deref' and target_arg.args:
if target_arg.func.attr == 'Deref' and target_arg.args: deref_arg = target_arg.args[0]
deref_arg = target_arg.args[0] if isinstance(deref_arg, ast.Name) and deref_arg.id in Gen.variables and Gen.variables[deref_arg.id] is not None:
if isinstance(deref_arg, ast.Name) and deref_arg.id in Gen.variables and Gen.variables[deref_arg.id] is not None: target_ptr = Gen._load(Gen.variables[deref_arg.id], name="deref_load_ptr")
target_ptr = Gen._load(Gen.variables[deref_arg.id], name="deref_load_ptr") else:
else: inner_value = self.HandleExprLlvm(deref_arg)
inner_value = self.HandleExprLlvm(deref_arg) if inner_value:
if inner_value: if isinstance(inner_value.type, ir.PointerType):
if isinstance(inner_value.type, ir.PointerType): if isinstance(inner_value.type.pointee, ir.PointerType):
if isinstance(inner_value.type.pointee, ir.PointerType): inner_value = Gen._load(inner_value, name="cast_deref")
inner_value = Gen._load(inner_value, name="cast_deref") target_ptr = inner_value
target_ptr = inner_value elif target_arg.func.id == 'Addr' and target_arg.args:
elif target_arg.func.attr == 'Addr' and target_arg.args: target_ptr = self.HandleExprLlvm(target_arg)
target_ptr = self.HandleExprLlvm(target_arg) else:
elif isinstance(target_arg.func.value, ast.Name) and IsTModule(target_arg.func.value.id, self.Trans.SymbolTable): type_attr = target_arg.func.id
type_attr = target_arg.func.attr
resolved_cname = self.Trans.TSpecialCallHandle._ResolveTAttrToCName(type_attr) resolved_cname = self.Trans.TSpecialCallHandle._ResolveTAttrToCName(type_attr)
if target_arg.args and resolved_cname is not None: if target_arg.args and resolved_cname is not None:
inner_val = self.HandleExprLlvm(target_arg.args[0]) inner_val = self.HandleExprLlvm(target_arg.args[0])
@@ -155,7 +153,7 @@ class CSpecialCallHandle(BaseHandle):
def EmitRawCopyLlvm(self, DstPtr: ir.Value, SrcPtr: ir.Value, Gen: LlvmGeneratorMixin, def EmitRawCopyLlvm(self, DstPtr: ir.Value, SrcPtr: ir.Value, Gen: LlvmGeneratorMixin,
NamePrefix: str = "rawcopy") -> bool: NamePrefix: str = "rawcopy") -> bool:
"""Emit `*dst = *src` as a raw byte copy (c.Load semantics); False if unusable. """Emit `*dst = *src` as a raw byte copy (Load semantics); False if unusable.
The width comes from the destination pointee and the source pointer is The width comes from the destination pointee and the source pointer is
bitcast to it, so this reinterprets memory instead of converting values bitcast to it, so this reinterprets memory instead of converting values
@@ -179,8 +177,8 @@ class CSpecialCallHandle(BaseHandle):
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
if len(Node.args) < 2: if len(Node.args) < 2:
return ir.Constant(ir.IntType(32), 0) return ir.Constant(ir.IntType(32), 0)
# c.Load(a, b) 语义: *a = *b(a 是目标,b 是源) # Load(a, b) 语义: *a = *b(a 是目标,b 是源)
# wiki 文档: c.Load(ptr, value) -> *ptr = *value; # wiki 文档: Load(ptr, value) -> *ptr = *value;
dst_val: ir.Value | None = self.HandleExprLlvm(Node.args[0]) dst_val: ir.Value | None = self.HandleExprLlvm(Node.args[0])
src_val: ir.Value | None = self.HandleExprLlvm(Node.args[1]) src_val: ir.Value | None = self.HandleExprLlvm(Node.args[1])
if not src_val or not dst_val: if not src_val or not dst_val:
@@ -188,13 +186,13 @@ class CSpecialCallHandle(BaseHandle):
if not isinstance(src_val.type, ir.PointerType) or not isinstance(dst_val.type, ir.PointerType): if not isinstance(src_val.type, ir.PointerType) or not isinstance(dst_val.type, ir.PointerType):
return ir.Constant(ir.IntType(32), 0) return ir.Constant(ir.IntType(32), 0)
pointee = dst_val.type.pointee pointee = dst_val.type.pointee
# c.Addr 统一返回 i8* 通用指针,丢失原始类型信息。 # Addr 统一返回 i8* 通用指针,丢失原始类型信息。
# 若 dst 是 c.Addr(var),从 var 的 alloca 类型推断真实 pointee(如 i64), # 若 dst 是 Addr(var),从 var 的 alloca 类型推断真实 pointee(如 i64),
# 否则 c.Load 只会按 i8 加载 1 字节(IEEE 754 double→u64 位重解释 bug)。 # 否则 Load 只会按 i8 加载 1 字节(IEEE 754 double→u64 位重解释 bug)。
if (isinstance(pointee, ir.IntType) and pointee.width == 8 if (isinstance(pointee, ir.IntType) and pointee.width == 8
and isinstance(Node.args[0], ast.Call) and isinstance(Node.args[0], ast.Call)
and isinstance(Node.args[0].func, ast.Attribute) and isinstance(Node.args[0].func, ast.Name)
and Node.args[0].func.attr == 'Addr' and Node.args[0].func.id == 'Addr'
and Node.args[0].args and Node.args[0].args
and isinstance(Node.args[0].args[0], ast.Name)): and isinstance(Node.args[0].args[0], ast.Name)):
var_name = Node.args[0].args[0].id var_name = Node.args[0].args[0].id
@@ -210,11 +208,11 @@ class CSpecialCallHandle(BaseHandle):
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
if not Node.args: if not Node.args:
return ir.Constant(ir.IntType(64), 0) return ir.Constant(ir.IntType(64), 0)
# 检测嵌套 c.Deref(c.Deref(...)):设置标志让内层 Deref 加载为指针 # 检测嵌套 Deref(Deref(...)):设置标志让内层 Deref 加载为指针
IsNestedDeref: bool = ( IsNestedDeref: bool = (
isinstance(Node.args[0], ast.Call) isinstance(Node.args[0], ast.Call)
and isinstance(Node.args[0].func, ast.Attribute) and isinstance(Node.args[0].func, ast.Name)
and Node.args[0].func.attr == 'Deref' and Node.args[0].func.id == 'Deref'
) )
if IsNestedDeref: if IsNestedDeref:
Gen._nested_deref_load_ptr = True Gen._nested_deref_load_ptr = True
@@ -236,11 +234,11 @@ class CSpecialCallHandle(BaseHandle):
if Loaded is not None: if Loaded is not None:
return Loaded return Loaded
# 读取宽度只由指针的 pointee 类型决定(_load 按 arg_val.type.pointee # 读取宽度只由指针的 pointee 类型决定(_load 按 arg_val.type.pointee
# 加载一个元素):pointee 是 i8(t.CPtr / void* / str / bytes)即恒读 # 加载一个元素):pointee 是 i8(CPtr / void* / str / bytes)即恒读
# 1 字节,不再按赋值目标注解反推宽度——那会让同一处 c.Deref(i8*) 的 # 1 字节,不再按赋值目标注解反推宽度——那会让同一处 Deref(i8*) 的
# 读取宽度取决于它是否恰好出现在带注解赋值的 RHS 里。需要 4/8 字节等 # 读取宽度取决于它是否恰好出现在带注解赋值的 RHS 里。需要 4/8 字节等
# 更宽读取时,由调用点显式给出元素类型指针后再解引用 # 更宽读取时,由调用点显式给出元素类型指针后再解引用
# (c.Deref((int | t.CPtr)(p)) / c.Deref(t.CUInt64T(p, t.CPtr)))。 # (Deref((int | CPtr)(p)) / Deref(CUInt64T(p, CPtr)))。
Loaded = Gen._load(arg_val, name="deref") Loaded = Gen._load(arg_val, name="deref")
if Loaded is not None: if Loaded is not None:
return Loaded return Loaded
@@ -295,9 +293,7 @@ class TSpecialCallHandle(BaseHandle):
IsPtr_cast = False IsPtr_cast = False
if len(Node.args) >= 2: if len(Node.args) >= 2:
second_arg = Node.args[1] second_arg = Node.args[1]
if isinstance(second_arg, ast.Attribute) and isinstance(second_arg.value, ast.Name) and IsTModule(second_arg.value.id, self.Trans.SymbolTable) and second_arg.attr == 'CPtr': if isinstance(second_arg, ast.Name) and second_arg.id == 'CPtr':
IsPtr_cast = True
elif isinstance(second_arg, ast.Name) and second_arg.id == 'CPtr':
IsPtr_cast = True IsPtr_cast = True
if IsPtr_cast: if IsPtr_cast:
return self._HandleTPtrCastLlvm(Node, attr) return self._HandleTPtrCastLlvm(Node, attr)
@@ -317,8 +313,8 @@ class TSpecialCallHandle(BaseHandle):
ptr_count: int = 0 ptr_count: int = 0
for i in range(1, len(Node.args)): for i in range(1, len(Node.args)):
type_arg = Node.args[i] type_arg = Node.args[i]
if isinstance(type_arg, ast.Attribute) and isinstance(type_arg.value, ast.Name) and IsTModule(type_arg.value.id, self.Trans.SymbolTable): if isinstance(type_arg, ast.Name):
type_attr = type_arg.attr type_attr = type_arg.id
_PREFIX_MAP: dict[str, str] = { _PREFIX_MAP: dict[str, str] = {
'CUnsigned': 'unsigned', 'CSigned': 'signed', 'CUnsigned': 'unsigned', 'CSigned': 'signed',
'CConst': 'const', 'CVolatile': 'volatile', 'CConst': 'const', 'CVolatile': 'volatile',
@@ -344,7 +340,7 @@ class TSpecialCallHandle(BaseHandle):
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
if attr in ('CChar', 'CUnsignedChar'): if attr in ('CChar', 'CUnsignedChar'):
first_arg = Node.args[0] first_arg = Node.args[0]
if isinstance(first_arg, ast.Call) and isinstance(first_arg.func, ast.Attribute) and isinstance(first_arg.func.value, ast.Name) and IsTModule(first_arg.func.value.id, self.Trans.SymbolTable) and first_arg.func.attr == 'CInt' and first_arg.args: if isinstance(first_arg, ast.Call) and isinstance(first_arg.func, ast.Name) and first_arg.func.id == 'CInt' and first_arg.args:
inner_val = self.HandleExprLlvm(first_arg.args[0]) inner_val = self.HandleExprLlvm(first_arg.args[0])
if isinstance(inner_val.type, ir.PointerType): if isinstance(inner_val.type, ir.PointerType):
return Gen.builder.bitcast(inner_val, ir.PointerType(ir.IntType(8)), name=f"c{attr.lower()}_ptr_from_cint") return Gen.builder.bitcast(inner_val, ir.PointerType(ir.IntType(8)), name=f"c{attr.lower()}_ptr_from_cint")
+171 -229
View File
@@ -5,10 +5,10 @@ if TYPE_CHECKING:
from typing import List from typing import List
from lib.core.Handles.HandlesBase import BaseHandle, CTypeHelper, CTypeInfo from lib.core.Handles.HandlesBase import BaseHandle, CTypeHelper, CTypeInfo
from lib.core.SymbolUtils import ( from lib.core.SymbolUtils import (
IsTModule, IsListAnnotation, IsPtrSubscriptNode, IsCPtrMarkerNode, IsListAnnotation, IsPtrSubscriptNode, IsCPtrMarkerNode,
DesugarPtrSubscriptToUnion) DesugarPtrSubscriptToUnion)
from lib.includes import t from lib.core import TypeSystem
import lib._bootstrap # noqa: F401 设置 sys.path(项目根 + lib/includes) import lib._bootstrap # noqa: F401 设置 sys.path(项目根 + lib)
import vast as ast import vast as ast
@@ -17,7 +17,7 @@ class HandlesTypeMerge(BaseHandle):
def _MakeVoidCTypeInfo(self) -> CTypeInfo: def _MakeVoidCTypeInfo(self) -> CTypeInfo:
Info = CTypeInfo() Info = CTypeInfo()
Info.BaseType = t.CVoid Info.BaseType = TypeSystem.CVoid
return Info return Info
@staticmethod @staticmethod
@@ -49,7 +49,7 @@ class HandlesTypeMerge(BaseHandle):
if isinstance(Node, ast.Name): if isinstance(Node, ast.Name):
TypeName = Node.id TypeName = Node.id
t_c_imported = getattr(self.Trans, '_t_c_imported_names', {}) t_c_imported = getattr(self.Trans, '_from_import_aliases', {})
if TypeName in t_c_imported: if TypeName in t_c_imported:
src_module, src_name = t_c_imported[TypeName] src_module, src_name = t_c_imported[TypeName]
virtual_attr = ast.Attribute( virtual_attr = ast.Attribute(
@@ -59,10 +59,47 @@ class HandlesTypeMerge(BaseHandle):
) )
ast.copy_location(virtual_attr, Node) ast.copy_location(virtual_attr, Node)
return self.GetCTypeInfo(virtual_attr) return self.GetCTypeInfo(virtual_attr)
if TypeName in ('CRef', 'CTempRef'):
Info = CTypeInfo()
Info.PtrCount = 1
Info.BaseType = TypeSystem.CVoid
return Info
BuiltinCls: type | None = CTypeHelper.GetTModuleCType(TypeName)
if BuiltinCls is not None and BuiltinCls is not TypeSystem.CType:
Info = CTypeInfo()
if BuiltinCls == TypeSystem.CArrayPtr:
Info.IsArrayPtr = True
Info.BaseType = TypeSystem.CVoid
return Info
if BuiltinCls == TypeSystem.CPtr:
Info.PtrCount = 1
Info.BaseType = TypeSystem.CVoid
return Info
if BuiltinCls == TypeSystem.CConst:
Info.DataConst = True
Info.BaseType = TypeSystem.CVoid
return Info
if BuiltinCls == TypeSystem.CVolatile:
Info.DataVolatile = True
Info.BaseType = TypeSystem.CVoid
return Info
if BuiltinCls in (TypeSystem.CInline, TypeSystem.CStatic,
TypeSystem.CExtern, TypeSystem.CExport):
Info.Storage = BuiltinCls()
Info.BaseType = TypeSystem.CVoid
return Info
if BuiltinCls in (TypeSystem.BigEndian, TypeSystem.LittleEndian):
Info.BaseType = TypeSystem.CInt()
Info.ByteOrder = 'big' if BuiltinCls == TypeSystem.BigEndian else 'little'
return Info
Info.BaseType = BuiltinCls
if issubclass(BuiltinCls, TypeSystem.CDefine):
Info.IsDefine = True
return Info
Entry = self.Trans.SymbolTable.lookup(TypeName) Entry = self.Trans.SymbolTable.lookup(TypeName)
if Entry and Entry.IsTypedef: if Entry and Entry.IsTypedef:
if isinstance(Entry, CTypeInfo) and Entry.BaseType: if isinstance(Entry, CTypeInfo) and Entry.BaseType:
if not isinstance(Entry.BaseType, (t._CTypedef,)) or Entry.PtrCount > 0: if not isinstance(Entry.BaseType, (TypeSystem._CTypedef,)) or Entry.PtrCount > 0:
Result = Entry.Copy() Result = Entry.Copy()
Result.IsTypedef = True Result.IsTypedef = True
Result.Name = TypeName Result.Name = TypeName
@@ -91,7 +128,7 @@ class HandlesTypeMerge(BaseHandle):
return Resolved return Resolved
return Entry return Entry
# REnum 优先于 IsEnum 处理(REnum 同时有 IsEnum=True 和 IsStruct=True) # REnum 优先于 IsEnum 处理(REnum 同时有 IsEnum=True 和 IsStruct=True)
# 必须设置 Name 和 PtrCount=1,否则 BinOp `LLVMType | t.CPtr` 合并后丢失 REnum 语义 # 必须设置 Name 和 PtrCount=1,否则 BinOp `LLVMType | CPtr` 合并后丢失 REnum 语义
if isinstance(Entry, CTypeInfo) and Entry.IsRenum: if isinstance(Entry, CTypeInfo) and Entry.IsRenum:
Result = Entry.Copy() Result = Entry.Copy()
Result.Name = TypeName Result.Name = TypeName
@@ -107,14 +144,14 @@ class HandlesTypeMerge(BaseHandle):
# 建出结构体的类(跨模块 import 的类)。 # 建出结构体的类(跨模块 import 的类)。
# 只查①漏②时的现场:`rawptr[Constant]`(includes/ast/exprs.vp:59 的 # 只查①漏②时的现场:`rawptr[Constant]`(includes/ast/exprs.vp:59 的
# accessor,`class Constant` 声明在同文件更后面)在导入侧解析时该名先命中 # accessor,`class Constant` 声明在同文件更后面)在导入侧解析时该名先命中
# 平坦符号表里的枚举成员 `Constant: t.State`(ast/base.vp)→ 走下方 # 平坦符号表里的枚举成员 `Constant: State`(ast/base.vp)→ 走下方
# `Entry.IsEnum` 分支返回枚举 → 与 t.CPtr 合并后经 _ctype_to_llvm 的 # `Entry.IsEnum` 分支返回枚举 → 与 CPtr 合并后经 _ctype_to_llvm 的
# IsEnum 分支(枚举名未登记 ⇒ 宽度退化为 i32)得 **i32\***,与调用点实参 # IsEnum 分支(枚举名未登记 ⇒ 宽度退化为 i32)得 **i32\***,与调用点实参
# %"<exprs_sha1>.Constant"* 分裂 → FuncGen._adjust_args fail-fast。 # %"<exprs_sha1>.Constant"* 分裂 → FuncGen._adjust_args fail-fast。
# 查②后 BaseType=CStruct('Constant'),_get_or_create_struct 会按 # 查②后 BaseType=CStruct('Constant'),_get_or_create_struct 会按
# `_struct_sha1_map` 拼出 `"<sha1>.Constant"`(BaseGen.py:527-528), # `_struct_sha1_map` 拼出 `"<sha1>.Constant"`(BaseGen.py:527-528),
# 与声明端/实参同一结构体对象。 # 与声明端/实参同一结构体对象。
# 但必须排除**枚举类型本身**(如 `class ASTKind(t.CEnum)` 的注解 `x: ASTKind`): # 但必须排除**枚举类型本身**(如 `class ASTKind(CEnum)` 的注解 `x: ASTKind`):
# _struct_sha1_map 是按 .vpi 里全部 ClassDef 建的,枚举类也在其中;若一并 # _struct_sha1_map 是按 .vpi 里全部 ClassDef 建的,枚举类也在其中;若一并
# 当结构体,枚举注解会被建成 opaque struct,与 i32 错位 # 当结构体,枚举注解会被建成 opaque struct,与 i32 错位
# (现场:'IntType' object has no attribute 'is_opaque')。 # (现场:'IntType' object has no attribute 'is_opaque')。
@@ -132,7 +169,7 @@ class HandlesTypeMerge(BaseHandle):
TypeName in _Gen.structs TypeName in _Gen.structs
or TypeName in getattr(_Gen, '_struct_sha1_map', {})): or TypeName in getattr(_Gen, '_struct_sha1_map', {})):
Result = CTypeInfo() Result = CTypeInfo()
Result.BaseType = t.CStruct(name=TypeName) Result.BaseType = TypeSystem.CStruct(name=TypeName)
Result.IsStruct = True Result.IsStruct = True
Result.Name = TypeName Result.Name = TypeName
Result.PtrCount = 1 Result.PtrCount = 1
@@ -141,19 +178,19 @@ class HandlesTypeMerge(BaseHandle):
return Entry.Copy() return Entry.Copy()
if isinstance(Entry, dict) and Entry.get('IsEnum'): if isinstance(Entry, dict) and Entry.get('IsEnum'):
Result = CTypeInfo() Result = CTypeInfo()
Result.BaseType = t.CEnum(TypeName) Result.BaseType = TypeSystem.CEnum(TypeName)
Result.IsEnum = True Result.IsEnum = True
return Result return Result
# 检测结构体类型 (CTypeInfo with IsStruct=True, 来自 _InsertClassSymbol) # 检测结构体类型 (CTypeInfo with IsStruct=True, 来自 _InsertClassSymbol)
if isinstance(Entry, CTypeInfo) and Entry.IsStruct: if isinstance(Entry, CTypeInfo) and Entry.IsStruct:
Result = Entry.Copy() Result = Entry.Copy()
if Result.BaseType is None: if Result.BaseType is None:
Result.BaseType = t.CStruct(name=TypeName) Result.BaseType = TypeSystem.CStruct(name=TypeName)
Result.Name = TypeName Result.Name = TypeName
Result.PtrCount = 1 # struct 变量默认为指针 Result.PtrCount = 1 # struct 变量默认为指针
return Result return Result
# [builtins 最后匹配] 常规路径全部 miss 后查 includes/builtins.vp 的 # [builtins 最后匹配] 常规路径全部 miss 后查 includes/builtins.vp 的
# CTypedef(size_t → t.CSizeT、rawptr → t.CPtr 内置等),对齐 # CTypedef(size_t → CSizeT、rawptr → CPtr 内置等),对齐
# TypeAnnotationResolver._from_node_name 兜底,避免裸名被误判为 # TypeAnnotationResolver._from_node_name 兜底,避免裸名被误判为
# 命名结构体(main2.vp `a: size_t` → alloca %...size_t 根因)。 # 命名结构体(main2.vp `a: size_t` → alloca %...size_t 根因)。
try: try:
@@ -184,6 +221,10 @@ class HandlesTypeMerge(BaseHandle):
else: else:
return self._MakeVoidCTypeInfo() return self._MakeVoidCTypeInfo()
if ModulePath in ('t', 'c'):
raise TypeError(
f"[TPC] 类型注解不再接受 \"{ModulePath}.\" 模块前缀;"
f"请直接写内建类型名(如 CPtr、CInt、CArray)。")
# 解析 import 别名: 如 import fat32_types as types -> types -> fat32_types # 解析 import 别名: 如 import fat32_types as types -> types -> fat32_types
if ModulePath: if ModulePath:
import_aliases = self.Trans.SymbolTable.import_aliases import_aliases = self.Trans.SymbolTable.import_aliases
@@ -200,79 +241,6 @@ class HandlesTypeMerge(BaseHandle):
if getattr(self.Trans, 'DebugFile', None): if getattr(self.Trans, 'DebugFile', None):
self.Trans.DebugPrint(f"[GetCTypeInfo-Attribute] 查询: '{TypeName}' ModulePath: {ModulePath}") self.Trans.DebugPrint(f"[GetCTypeInfo-Attribute] 查询: '{TypeName}' ModulePath: {ModulePath}")
if ModulePath == 't' and TypeName == 'State':
Info = CTypeInfo()
Info.BaseType = t.CVoid
Info.IsState = True
return Info
if ModulePath == 't' or (ModulePath and ModulePath.startswith('t.')):
# 值引用参数标记(CRef = `&T`、CTempRef = `&temp T`,非真实类):与
# t.CPtr 同形的「一层指针」,使 `T | t.CRef` 合并为 T*(pointer 层 +1)。
if TypeName in ('CRef', 'CTempRef'):
Info = CTypeInfo()
Info.PtrCount = 1
Info.BaseType = t.CVoid
return Info
if self._IsTModuleType(TypeName):
TypeClass = CTypeHelper.GetTModuleCType(TypeName) or getattr(t, TypeName, None)
if TypeClass == t.CArrayPtr:
Info = CTypeInfo()
Info.IsArrayPtr = True
Info.BaseType = t.CVoid
return Info
elif TypeClass == t.CPtr:
Info = CTypeInfo()
Info.PtrCount = 1
Info.BaseType = t.CVoid
return Info
elif TypeClass == t.CConst:
Info = CTypeInfo()
Info.DataConst = True
Info.BaseType = t.CVoid
return Info
elif TypeClass == t.CVolatile:
Info = CTypeInfo()
Info.DataVolatile = True
Info.BaseType = t.CVoid
return Info
elif TypeClass == t.CInline:
Info = CTypeInfo()
Info.Storage = t.CInline()
Info.BaseType = t.CVoid
return Info
elif TypeClass == t.CStatic:
Info = CTypeInfo()
Info.Storage = t.CStatic()
Info.BaseType = t.CVoid
return Info
elif TypeClass == t.CExtern:
Info = CTypeInfo()
Info.Storage = t.CExtern()
Info.BaseType = t.CVoid
return Info
elif TypeClass == t.CExport:
Info = CTypeInfo()
Info.Storage = t.CExport()
Info.BaseType = t.CVoid
return Info
elif TypeClass in (t.BigEndian, t.LittleEndian):
Info = CTypeInfo()
Info.BaseType = t.CInt()
Info.ByteOrder = 'big' if TypeClass == t.BigEndian else 'little'
return Info
elif TypeClass:
Info = CTypeInfo()
Info.BaseType = TypeClass
# 治本修复:t.CDefine 注解必须设置 IsDefine=True,
# 否则预扫描 (LlvmGenerator.py) 和主处理 (HandlesAnnAssign.py)
# 都无法识别 CDefine 常量,导致 FOREGROUND_GREEN 等解析为 0
if isinstance(TypeClass, type) and issubclass(TypeClass, t.CDefine):
Info.IsDefine = True
return Info
elif CTypeHelper.GetCName(TypeName):
return self._MakeCTypeInfoFromName(CTypeHelper.GetCName(TypeName))
FullName = f"{ModulePath}.{TypeName}" if ModulePath else TypeName FullName = f"{ModulePath}.{TypeName}" if ModulePath else TypeName
# 优先检查 Gen.structs:类名与枚举成员名冲突时(如 Import 既是 ASTKind.Import # 优先检查 Gen.structs:类名与枚举成员名冲突时(如 Import 既是 ASTKind.Import
@@ -281,7 +249,7 @@ class HandlesTypeMerge(BaseHandle):
_Gen = getattr(self.Trans, 'LlvmGen', None) _Gen = getattr(self.Trans, 'LlvmGen', None)
if _Gen and TypeName in _Gen.structs: if _Gen and TypeName in _Gen.structs:
Result = CTypeInfo() Result = CTypeInfo()
Result.BaseType = t.CStruct(name=TypeName) Result.BaseType = TypeSystem.CStruct(name=TypeName)
Result.IsStruct = True Result.IsStruct = True
Result.Name = TypeName Result.Name = TypeName
Result.PtrCount = 1 Result.PtrCount = 1
@@ -299,7 +267,7 @@ class HandlesTypeMerge(BaseHandle):
# 与声明端 %"<sha1>.CLS"* 分裂。 # 与声明端 %"<sha1>.CLS"* 分裂。
if _Gen is not None and TypeName in getattr(_Gen, '_struct_sha1_map', {}): if _Gen is not None and TypeName in getattr(_Gen, '_struct_sha1_map', {}):
Result = CTypeInfo() Result = CTypeInfo()
Result.BaseType = t.CStruct(name=TypeName) Result.BaseType = TypeSystem.CStruct(name=TypeName)
Result.IsStruct = True Result.IsStruct = True
Result.Name = TypeName Result.Name = TypeName
Result.PtrCount = 1 Result.PtrCount = 1
@@ -308,7 +276,7 @@ class HandlesTypeMerge(BaseHandle):
Entry = self.Trans.SymbolTable.lookup(TypeName) Entry = self.Trans.SymbolTable.lookup(TypeName)
if Entry and Entry.IsTypedef: if Entry and Entry.IsTypedef:
if isinstance(Entry, CTypeInfo) and Entry.BaseType: if isinstance(Entry, CTypeInfo) and Entry.BaseType:
if not isinstance(Entry.BaseType, (t._CTypedef,)) or Entry.PtrCount > 0: if not isinstance(Entry.BaseType, (TypeSystem._CTypedef,)) or Entry.PtrCount > 0:
Result = Entry.Copy() Result = Entry.Copy()
Result.IsTypedef = True Result.IsTypedef = True
Result.Name = TypeName Result.Name = TypeName
@@ -336,7 +304,7 @@ class HandlesTypeMerge(BaseHandle):
Resolved.Name = TypeName Resolved.Name = TypeName
return Resolved return Resolved
Result = CTypeInfo() Result = CTypeInfo()
Result.BaseType = t._CTypedef(TypeName) Result.BaseType = TypeSystem._CTypedef(TypeName)
Result.IsTypedef = True Result.IsTypedef = True
Result.Name = TypeName Result.Name = TypeName
return Result return Result
@@ -344,7 +312,7 @@ class HandlesTypeMerge(BaseHandle):
# If BaseType is None but this is a class/struct, set BaseType to CStruct # If BaseType is None but this is a class/struct, set BaseType to CStruct
Result = Entry.Copy() Result = Entry.Copy()
if Result.BaseType is None: if Result.BaseType is None:
Result.BaseType = t.CStruct(name=TypeName) Result.BaseType = TypeSystem.CStruct(name=TypeName)
Result.IsStruct = True Result.IsStruct = True
# struct 变量默认为指针(与 ast.Name 路径一致,见 line 121) # struct 变量默认为指针(与 ast.Name 路径一致,见 line 121)
# 同时确保 Name 字段被设置,供 ToString() 使用 # 同时确保 Name 字段被设置,供 ToString() 使用
@@ -363,7 +331,7 @@ class HandlesTypeMerge(BaseHandle):
ReturnType = ReturnTypeInfo ReturnType = ReturnTypeInfo
else: else:
ReturnType = CTypeInfo() ReturnType = CTypeInfo()
ReturnType.BaseType = t.CVoid() ReturnType.BaseType = TypeSystem.CVoid()
ParamTypes = [] ParamTypes = []
ParamNames = [] ParamNames = []
@@ -399,70 +367,44 @@ class HandlesTypeMerge(BaseHandle):
Info.FuncPtrParams = list(zip(ParamNames, ParamTypes)) Info.FuncPtrParams = list(zip(ParamNames, ParamTypes))
return Info return Info
if isinstance(Node.func, ast.Name):
BuiltinCls: type | None = CTypeHelper.GetTModuleCType(Node.func.id)
if BuiltinCls is not None and BuiltinCls is not TypeSystem.CType:
if BuiltinCls == TypeSystem.State:
Info = CTypeInfo()
Info.IsState = True
return Info
if BuiltinCls == TypeSystem.Bit:
Width: int = 1
if Node.args and isinstance(Node.args[0], ast.Constant):
Width = Node.args[0].value
Info = CTypeInfo()
Info.IsBitField = True
Info.BitWidth = Width
Info.BaseType = TypeSystem.CInt
return Info
Info = CTypeInfo()
Info.BaseType = BuiltinCls
return Info
if isinstance(Node.func, ast.Attribute) and isinstance(Node.func.value, ast.Name): if isinstance(Node.func, ast.Attribute) and isinstance(Node.func.value, ast.Name):
ModuleName = Node.func.value.id ModuleName = Node.func.value.id
TypeName = Node.func.attr TypeName = Node.func.attr
if ModuleName == 't' and CTypeHelper.GetTModuleCType(TypeName) == t._CTypedef and Node.args:
TypeArg = Node.args[0]
if isinstance(TypeArg, ast.Name):
return TypeArg.id
elif isinstance(TypeArg, ast.Attribute):
AttrModule = TypeArg.value.id if isinstance(TypeArg.value, ast.Name) else None
AttrName = TypeArg.attr
if AttrModule == 't' and getattr(t, AttrName, None):
TypeObj = getattr(t, AttrName)
if isinstance(TypeObj, type) and issubclass(TypeObj, t.CType):
return TypeObj.__name__
return AttrName
elif isinstance(TypeArg, ast.Constant):
return str(TypeArg.value)
if ModuleName in self.Trans._UserTypeModules:
module = self.Trans._UserTypeModules[ModuleName]
if getattr(module, TypeName, None):
TypeObj = getattr(module, TypeName)
if isinstance(TypeObj, type):
if issubclass(TypeObj, t.CType):
return TypeObj.__name__
if ModuleName == 't':
TypeObj = CTypeHelper.GetTModuleCType(TypeName)
if TypeObj is None:
TypeObj = getattr(t, TypeName, None)
if isinstance(TypeObj, type) and issubclass(TypeObj, t.CType):
Result = CTypeInfo()
Result.BaseType = TypeObj
return Result
if ModuleName == 't' and TypeName == 'State':
Result = CTypeInfo()
Result.IsState = True
return Result
if ModuleName == 't' and TypeName == 'Bit':
if Node.args and isinstance(Node.args[0], ast.Constant):
BitWidth = Node.args[0].value
Result = CTypeInfo()
Result.IsBitField = True
Result.BitWidth = BitWidth
Result.BaseType = t.CInt
return Result
Result = CTypeInfo() Result = CTypeInfo()
Result.BaseType = t.CVoid Result.BaseType = TypeSystem.CVoid
return Result return Result
elif isinstance(Node, ast.Subscript): elif isinstance(Node, ast.Subscript):
if (isinstance(Node.value, ast.Attribute) if (isinstance(Node.value, ast.Attribute)
and isinstance(Node.value.value, ast.Name) and isinstance(Node.value.value, ast.Name)
and IsTModule(Node.value.value.id, self.Trans.SymbolTable)
and Node.value.attr == 'Bit'): and Node.value.attr == 'Bit'):
if isinstance(Node.slice, ast.Constant) and isinstance(Node.slice.value, int): if isinstance(Node.slice, ast.Constant) and isinstance(Node.slice.value, int):
Result = CTypeInfo() Result = CTypeInfo()
Result.IsBitField = True Result.IsBitField = True
Result.BitWidth = Node.slice.value Result.BitWidth = Node.slice.value
Result.BaseType = t.CInt Result.BaseType = TypeSystem.CInt
return Result return Result
return self._HandleSubscript(Node) return self._HandleSubscript(Node)
@@ -488,21 +430,21 @@ class HandlesTypeMerge(BaseHandle):
"""澶勭悊 Subscript 鑺傜偣锛屼娇鐢?CTypeInfo 鏍戝舰缁撴瀯鍒嗘瀽 AST """澶勭悊 Subscript 鑺傜偣锛屼娇鐢?CTypeInfo 鏍戝舰缁撴瀯鍒嗘瀽 AST
例如? 例如?
t.CVoid[5] -> void *[5] CVoid[5] -> void *[5]
t.CPtr[t.CPtr[t.CPtr]][5][6] -> void ***[5][6] CPtr[CPtr[CPtr]][5][6] -> void ***[5][6]
t.CArrayPtr[t.CArrayPtr] -> void *(*)[] CArrayPtr[CArrayPtr] -> void *(*)[]
t.CPtr[t.CArrayPtr[t.CArrayPtr]] -> void *(*(*))[] CPtr[CArrayPtr[CArrayPtr]] -> void *(*(*))[]
""" """
# 指针下标(rawptr[T] 内置裸指针 / t.CPtr[T] 下标指针,含裸名 CPtr[T]) # 指针下标(rawptr[T] 内置裸指针 / CPtr[T] 下标指针,含裸名 CPtr[T])
# 折叠为等价的联合写法 `T | t.CPtr` 后交给 MergeTypes 统一解析:内层 T # 折叠为等价的联合写法 `T | CPtr` 后交给 MergeTypes 统一解析:内层 T
# 因此走通用解析路径(含跨模块类经 Gen.structs 反查 SHA1 前缀),指针 # 因此走通用解析路径(含跨模块类经 Gen.structs 反查 SHA1 前缀),指针
# 层数与源码 `T | t.CPtr` 完全一致(此前 t.CPtr[ast.AST] 在此得 # 层数与源码 `T | CPtr` 完全一致(此前 CPtr[ast.AST] 在此得
# AST**(比 declare/`AST | t.CPtr` 多一层)、rawptr[ast.AST] 退化为 # AST**(比 declare/`AST | CPtr` 多一层)、rawptr[ast.AST] 退化为
# CVoid/1 → i8*)。 # CVoid/1 → i8*)。
if IsPtrSubscriptNode(Node, self.Trans.SymbolTable): if IsPtrSubscriptNode(Node, self.Trans.SymbolTable):
return self.MergeTypes(DesugarPtrSubscriptToUnion(Node, self.Trans.SymbolTable)) return self.MergeTypes(DesugarPtrSubscriptToUnion(Node, self.Trans.SymbolTable))
# 判据自洽守卫(fail-fast):base 是指针标记(`rawptr` / `t.CPtr` / 裸名 # 判据自洽守卫(fail-fast):base 是指针标记(`rawptr` / `CPtr` / 裸名
# `CPtr` / 别名 `X[...]`,见 IsPtrSubscriptNode)却被上面那条判据漏掉 ⇒ # `CPtr` / 别名 `X[...]`,见 IsPtrSubscriptNode)却被上面那条判据漏掉 ⇒
# 两处判据分裂(内部不变量被破坏)。历史行为是落到下方 CollectAll 当成 # 两处判据分裂(内部不变量被破坏)。历史行为是落到下方 CollectAll 当成
# 「数组下标」解析,**静默**产出"基座 void + 多层指针"(如 i8**),与 # 「数组下标」解析,**静默**产出"基座 void + 多层指针"(如 i8**),与
@@ -526,7 +468,7 @@ class HandlesTypeMerge(BaseHandle):
if isinstance(value_node, ast.Attribute): if isinstance(value_node, ast.Attribute):
VtInfo = self.GetCTypeInfo(value_node) VtInfo = self.GetCTypeInfo(value_node)
if isinstance(value_node, ast.Attribute) and value_node.attr == 'Callable' and isinstance(value_node.value, ast.Name) and IsTModule(value_node.value.id, self.Trans.SymbolTable): if isinstance(value_node, ast.Attribute) and value_node.attr == 'Callable' and isinstance(value_node.value, ast.Name) :
if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2: if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2:
params_list = slice_node.elts[0] params_list = slice_node.elts[0]
return_node = slice_node.elts[1] return_node = slice_node.elts[1]
@@ -549,7 +491,7 @@ class HandlesTypeMerge(BaseHandle):
ReturnType = ReturnTypeInfo ReturnType = ReturnTypeInfo
else: else:
ReturnType = CTypeInfo() ReturnType = CTypeInfo()
ReturnType.BaseType = t.CVoid() ReturnType.BaseType = TypeSystem.CVoid()
Info = CTypeInfo() Info = CTypeInfo()
Info.IsFuncPtr = True Info.IsFuncPtr = True
Info.FuncPtrReturn = ReturnType Info.FuncPtrReturn = ReturnType
@@ -592,23 +534,23 @@ class HandlesTypeMerge(BaseHandle):
ResultInfo.ArrayPtr.IsArrayPtr = True ResultInfo.ArrayPtr.IsArrayPtr = True
elif VtInfo and VtInfo.PtrCount == 1 and not VtInfo.ArrayPtr: elif VtInfo and VtInfo.PtrCount == 1 and not VtInfo.ArrayPtr:
ResultInfo = CTypeInfo() ResultInfo = CTypeInfo()
ResultInfo.BaseType = t.CVoid ResultInfo.BaseType = TypeSystem.CVoid
ResultInfo.PtrCount = 1 ResultInfo.PtrCount = 1
if isinstance(slice_node, ast.Subscript): if isinstance(slice_node, ast.Subscript):
inner_info = CollectAll(slice_node) inner_info = CollectAll(slice_node)
if inner_info and inner_info.PtrCount > 0: if inner_info and inner_info.PtrCount > 0:
ResultInfo.PtrCount += inner_info.PtrCount ResultInfo.PtrCount += inner_info.PtrCount
if inner_info.BaseType and not isinstance(inner_info.BaseType, t.CVoid): if inner_info.BaseType and not isinstance(inner_info.BaseType, TypeSystem.CVoid):
ResultInfo.BaseType = inner_info.BaseType ResultInfo.BaseType = inner_info.BaseType
elif inner_info and inner_info.ArrayPtr: elif inner_info and inner_info.ArrayPtr:
ResultInfo.ArrayPtr = inner_info ResultInfo.ArrayPtr = inner_info
elif inner_info and inner_info.BaseType and not isinstance(inner_info.BaseType, t.CVoid): elif inner_info and inner_info.BaseType and not isinstance(inner_info.BaseType, TypeSystem.CVoid):
ResultInfo.BaseType = inner_info.BaseType ResultInfo.BaseType = inner_info.BaseType
elif isinstance(slice_node, ast.Attribute): elif isinstance(slice_node, ast.Attribute):
SliceVtInfo = self.GetCTypeInfo(slice_node) SliceVtInfo = self.GetCTypeInfo(slice_node)
if SliceVtInfo and SliceVtInfo.PtrCount == 1 and not SliceVtInfo.ArrayPtr: if SliceVtInfo and SliceVtInfo.PtrCount == 1 and not SliceVtInfo.ArrayPtr:
ResultInfo.PtrCount = 2 ResultInfo.PtrCount = 2
if SliceVtInfo.BaseType and not isinstance(SliceVtInfo.BaseType, t.CVoid): if SliceVtInfo.BaseType and not isinstance(SliceVtInfo.BaseType, TypeSystem.CVoid):
ResultInfo.BaseType = SliceVtInfo.BaseType ResultInfo.BaseType = SliceVtInfo.BaseType
elif SliceVtInfo and SliceVtInfo.IsArrayPtr: elif SliceVtInfo and SliceVtInfo.IsArrayPtr:
inner = CTypeInfo() inner = CTypeInfo()
@@ -616,13 +558,13 @@ class HandlesTypeMerge(BaseHandle):
ResultInfo.ArrayPtr = inner ResultInfo.ArrayPtr = inner
elif SliceVtInfo and SliceVtInfo.ArrayPtr: elif SliceVtInfo and SliceVtInfo.ArrayPtr:
ResultInfo.ArrayPtr = SliceVtInfo ResultInfo.ArrayPtr = SliceVtInfo
elif SliceVtInfo and SliceVtInfo.BaseType and not isinstance(SliceVtInfo.BaseType, t.CVoid): elif SliceVtInfo and SliceVtInfo.BaseType and not isinstance(SliceVtInfo.BaseType, TypeSystem.CVoid):
ResultInfo.BaseType = SliceVtInfo.BaseType ResultInfo.BaseType = SliceVtInfo.BaseType
elif isinstance(slice_node, ast.Name): elif isinstance(slice_node, ast.Name):
SliceType = getattr(t, slice_node.id, None) SliceType = getattr(TypeSystem, slice_node.id, None)
if SliceType == t.CPtr: if SliceType == TypeSystem.CPtr:
ResultInfo.PtrCount += 1 ResultInfo.PtrCount += 1
elif SliceType == t.CArrayPtr: elif SliceType == TypeSystem.CArrayPtr:
inner = CTypeInfo() inner = CTypeInfo()
inner.ArrayPtr = CTypeInfo() inner.ArrayPtr = CTypeInfo()
ResultInfo.ArrayPtr = inner ResultInfo.ArrayPtr = inner
@@ -632,7 +574,7 @@ class HandlesTypeMerge(BaseHandle):
merged = self.MergeTypes(slice_node) merged = self.MergeTypes(slice_node)
if merged: if merged:
ResultInfo.PtrCount += merged.PtrCount ResultInfo.PtrCount += merged.PtrCount
if merged.BaseType and not isinstance(merged.BaseType, t.CVoid): if merged.BaseType and not isinstance(merged.BaseType, TypeSystem.CVoid):
ResultInfo.BaseType = merged.BaseType ResultInfo.BaseType = merged.BaseType
if merged.ArrayPtr: if merged.ArrayPtr:
ResultInfo.ArrayPtr = merged.ArrayPtr ResultInfo.ArrayPtr = merged.ArrayPtr
@@ -657,10 +599,10 @@ class HandlesTypeMerge(BaseHandle):
if isinstance(slice_node, ast.Constant): if isinstance(slice_node, ast.Constant):
ResultInfo.ArrayDims.append(str(slice_node.value)) ResultInfo.ArrayDims.append(str(slice_node.value))
elif isinstance(slice_node, ast.Name): elif isinstance(slice_node, ast.Name):
SliceType = getattr(t, slice_node.id, None) SliceType = getattr(TypeSystem, slice_node.id, None)
if SliceType == t.CPtr: if SliceType == TypeSystem.CPtr:
ResultInfo.PtrCount += 1 ResultInfo.PtrCount += 1
elif SliceType == t.CArrayPtr: elif SliceType == TypeSystem.CArrayPtr:
ResultInfo.ArrayPtr = CTypeInfo() ResultInfo.ArrayPtr = CTypeInfo()
else: else:
ResultInfo.ArrayDims.append(slice_node.id) ResultInfo.ArrayDims.append(slice_node.id)
@@ -670,13 +612,13 @@ class HandlesTypeMerge(BaseHandle):
SliceVtInfo = self.GetCTypeInfo(slice_node) SliceVtInfo = self.GetCTypeInfo(slice_node)
if SliceVtInfo and SliceVtInfo.PtrCount >= 1 and not SliceVtInfo.ArrayPtr: if SliceVtInfo and SliceVtInfo.PtrCount >= 1 and not SliceVtInfo.ArrayPtr:
ResultInfo.PtrCount += SliceVtInfo.PtrCount ResultInfo.PtrCount += SliceVtInfo.PtrCount
if SliceVtInfo.BaseType and not isinstance(SliceVtInfo.BaseType, t.CVoid): if SliceVtInfo.BaseType and not isinstance(SliceVtInfo.BaseType, TypeSystem.CVoid):
ResultInfo.BaseType = SliceVtInfo.BaseType ResultInfo.BaseType = SliceVtInfo.BaseType
elif SliceVtInfo and SliceVtInfo.IsArrayPtr: elif SliceVtInfo and SliceVtInfo.IsArrayPtr:
NewInfo = CTypeInfo() NewInfo = CTypeInfo()
NewInfo.ArrayPtr = ResultInfo NewInfo.ArrayPtr = ResultInfo
ResultInfo = NewInfo ResultInfo = NewInfo
elif SliceVtInfo and SliceVtInfo.BaseType and not isinstance(SliceVtInfo.BaseType, t.CVoid): elif SliceVtInfo and SliceVtInfo.BaseType and not isinstance(SliceVtInfo.BaseType, TypeSystem.CVoid):
ResultInfo.BaseType = SliceVtInfo.BaseType ResultInfo.BaseType = SliceVtInfo.BaseType
elif isinstance(slice_node, ast.Subscript): elif isinstance(slice_node, ast.Subscript):
InnerNode = CollectAll(slice_node) InnerNode = CollectAll(slice_node)
@@ -690,10 +632,10 @@ class HandlesTypeMerge(BaseHandle):
elif isinstance(slice_node, ast.Constant): elif isinstance(slice_node, ast.Constant):
ResultInfo.ArrayDims.append(str(slice_node.value)) ResultInfo.ArrayDims.append(str(slice_node.value))
elif isinstance(slice_node, ast.Name): elif isinstance(slice_node, ast.Name):
SliceType = getattr(t, slice_node.id, None) SliceType = getattr(TypeSystem, slice_node.id, None)
if SliceType == t.CPtr: if SliceType == TypeSystem.CPtr:
ResultInfo.PtrCount += 1 ResultInfo.PtrCount += 1
elif SliceType == t.CArrayPtr: elif SliceType == TypeSystem.CArrayPtr:
ResultInfo.ArrayPtr = CTypeInfo() ResultInfo.ArrayPtr = CTypeInfo()
else: else:
ResultInfo.ArrayDims.append(slice_node.id) ResultInfo.ArrayDims.append(slice_node.id)
@@ -708,18 +650,18 @@ class HandlesTypeMerge(BaseHandle):
if not isinstance(slice_node, ast.Tuple): if not isinstance(slice_node, ast.Tuple):
ElementType = self._GetCTypeInfoInternal(slice_node) ElementType = self._GetCTypeInfoInternal(slice_node)
if ElementType and isinstance(ElementType, CTypeInfo): if ElementType and isinstance(ElementType, CTypeInfo):
ResultInfo.BaseType = ElementType.BaseType if ElementType.BaseType else t.CVoid() ResultInfo.BaseType = ElementType.BaseType if ElementType.BaseType else TypeSystem.CVoid()
ResultInfo.PtrCount = ElementType.PtrCount + 1 ResultInfo.PtrCount = ElementType.PtrCount + 1
ResultInfo.IsFuncPtr = ElementType.IsFuncPtr ResultInfo.IsFuncPtr = ElementType.IsFuncPtr
ResultInfo.FuncPtrReturn = ElementType.FuncPtrReturn ResultInfo.FuncPtrReturn = ElementType.FuncPtrReturn
ResultInfo.FuncPtrParams = ElementType.FuncPtrParams ResultInfo.FuncPtrParams = ElementType.FuncPtrParams
else: else:
ResultInfo.BaseType = t.CVoid() ResultInfo.BaseType = TypeSystem.CVoid()
ResultInfo.PtrCount = 1 ResultInfo.PtrCount = 1
elif isinstance(slice_node, ast.Tuple) and len(slice_node.elts) >= 1: elif isinstance(slice_node, ast.Tuple) and len(slice_node.elts) >= 1:
ElementType = self._GetCTypeInfoInternal(slice_node.elts[0]) ElementType = self._GetCTypeInfoInternal(slice_node.elts[0])
if ElementType and isinstance(ElementType, CTypeInfo): if ElementType and isinstance(ElementType, CTypeInfo):
ResultInfo.BaseType = ElementType.BaseType if ElementType.BaseType else t.CVoid() ResultInfo.BaseType = ElementType.BaseType if ElementType.BaseType else TypeSystem.CVoid()
ResultInfo.PtrCount = ElementType.PtrCount ResultInfo.PtrCount = ElementType.PtrCount
ResultInfo.IsFuncPtr = ElementType.IsFuncPtr ResultInfo.IsFuncPtr = ElementType.IsFuncPtr
ResultInfo.FuncPtrReturn = ElementType.FuncPtrReturn ResultInfo.FuncPtrReturn = ElementType.FuncPtrReturn
@@ -764,14 +706,14 @@ class HandlesTypeMerge(BaseHandle):
slice_res = self.Trans.ExprCallHandle._resolve_generic_slice_type(slice_node) slice_res = self.Trans.ExprCallHandle._resolve_generic_slice_type(slice_node)
type_arg_str = slice_res[0] if slice_res else self.Trans.ExprCallHandle._resolve_type_arg_str(slice_node) type_arg_str = slice_res[0] if slice_res else self.Trans.ExprCallHandle._resolve_type_arg_str(slice_node)
full_spec_name: str = f'{value_node.id}[{type_arg_str}]' full_spec_name: str = f'{value_node.id}[{type_arg_str}]'
ResultInfo.BaseType = t.CStruct(name=full_spec_name) ResultInfo.BaseType = TypeSystem.CStruct(name=full_spec_name)
ResultInfo.Name = full_spec_name ResultInfo.Name = full_spec_name
ResultInfo.IsStruct = True ResultInfo.IsStruct = True
ResultInfo.PtrCount = 1 ResultInfo.PtrCount = 1
# 触发泛型特化发射:确保特化的方法被发射 + struct sha1 注册 # 触发泛型特化发射:确保特化的方法被发射 + struct sha1 注册
# 与局部变量 AnnAssign 路径一致;否则函数参数注解路径 # 与局部变量 AnnAssign 路径一致;否则函数参数注解路径
# 只构建 mangled 名,方法调用分派时 class_sha1=None 导致 # 只构建 mangled 名,方法调用分派时 class_sha1=None 导致
# "Undefined method" 错误(如 lst.__len__() 在 list[T] | t.CPtr 参数上) # "Undefined method" 错误(如 lst.__len__() 在 list[T] | CPtr 参数上)
# _specialize_generic_class 内部有 spec_key 去重,重复调用安全 # _specialize_generic_class 内部有 spec_key 去重,重复调用安全
if hasattr(self.Trans, 'ExprCallHandle') and self.Trans.ExprCallHandle is not None: if hasattr(self.Trans, 'ExprCallHandle') and self.Trans.ExprCallHandle is not None:
self.Trans.ExprCallHandle._ResolveGenericSlice(node) self.Trans.ExprCallHandle._ResolveGenericSlice(node)
@@ -801,14 +743,14 @@ class HandlesTypeMerge(BaseHandle):
_ig_res = self.Trans.ExprCallHandle._resolve_generic_slice_type(_ig_elt) _ig_res = self.Trans.ExprCallHandle._resolve_generic_slice_type(_ig_elt)
_ig_args.append(_ig_res[0] if _ig_res else self.Trans.ExprCallHandle._resolve_type_arg_str(_ig_elt)) _ig_args.append(_ig_res[0] if _ig_res else self.Trans.ExprCallHandle._resolve_type_arg_str(_ig_elt))
_ig_spec: str = f'{_inner_gsub.value.id}[' + ']['.join(_ig_args) + ']' _ig_spec: str = f'{_inner_gsub.value.id}[' + ']['.join(_ig_args) + ']'
ResultInfo.BaseType = t.CStruct(name=_ig_spec) ResultInfo.BaseType = TypeSystem.CStruct(name=_ig_spec)
ResultInfo.Name = _ig_spec ResultInfo.Name = _ig_spec
ResultInfo.IsStruct = True ResultInfo.IsStruct = True
ResultInfo.PtrCount = 1 ResultInfo.PtrCount = 1
self.Trans.ExprCallHandle._ResolveGenericSlice(_inner_gsub) self.Trans.ExprCallHandle._ResolveGenericSlice(_inner_gsub)
return ResultInfo return ResultInfo
# [builtins 最后匹配] base 为 builtins 指针 typedef # [builtins 最后匹配] base 为 builtins 指针 typedef
# (rawptr → t.CPtr):rawptr[X] 等价 X*(对齐 VPC # (rawptr → CPtr):rawptr[X] 等价 X*(对齐 VPC
# Subscript 语义),委托 TypeAnnotationResolver 统一解析, # Subscript 语义),委托 TypeAnnotationResolver 统一解析,
# 避免被误当作 'rawptr[X]' 结构体/数组维度处理。 # 避免被误当作 'rawptr[X]' 结构体/数组维度处理。
try: try:
@@ -823,10 +765,10 @@ class HandlesTypeMerge(BaseHandle):
if isinstance(slice_node, ast.Constant): if isinstance(slice_node, ast.Constant):
ResultInfo.ArrayDims.append(str(slice_node.value)) ResultInfo.ArrayDims.append(str(slice_node.value))
elif isinstance(slice_node, ast.Name): elif isinstance(slice_node, ast.Name):
SliceType = getattr(t, slice_node.id, None) SliceType = getattr(TypeSystem, slice_node.id, None)
if SliceType == t.CPtr: if SliceType == TypeSystem.CPtr:
ResultInfo.PtrCount += 1 ResultInfo.PtrCount += 1
elif SliceType == t.CArrayPtr: elif SliceType == TypeSystem.CArrayPtr:
ResultInfo.ArrayPtr = CTypeInfo() ResultInfo.ArrayPtr = CTypeInfo()
else: else:
ResultInfo.ArrayDims.append(slice_node.id) ResultInfo.ArrayDims.append(slice_node.id)
@@ -849,7 +791,7 @@ class HandlesTypeMerge(BaseHandle):
result.ArrayPtr = CTypeInfo() result.ArrayPtr = CTypeInfo()
return result return result
elif VtInfo and VtInfo.PtrCount == 1 and not VtInfo.ArrayPtr: elif VtInfo and VtInfo.PtrCount == 1 and not VtInfo.ArrayPtr:
result.BaseType = t.CVoid result.BaseType = TypeSystem.CVoid
result.PtrCount = 1 result.PtrCount = 1
return result return result
elif VtInfo and VtInfo.BaseType: elif VtInfo and VtInfo.BaseType:
@@ -870,10 +812,10 @@ class HandlesTypeMerge(BaseHandle):
"""递归收集所有操作数的类型(用于一次性合并)""" """递归收集所有操作数的类型(用于一次性合并)"""
Types = [] Types = []
# 指针下标(rawptr[T] / t.CPtr[T])先折叠成等价的 `T | t.CPtr`:使 # 指针下标(rawptr[T] / CPtr[T])先折叠成等价的 `T | CPtr`:使
# `rawptr[T] | t.CPtr` 与 `T | t.CPtr | t.CPtr` 拉平成同一组操作数 # `rawptr[T] | CPtr` 与 `T | CPtr | CPtr` 拉平成同一组操作数
# (否则折叠结果作为单个 Subscript 操作数参与合并,指针层数少算一层); # (否则折叠结果作为单个 Subscript 操作数参与合并,指针层数少算一层);
# t.CPtr[T] 与 rawptr[T] 同一条规则(见 SymbolUtils.IsPtrSubscriptNode)。 # CPtr[T] 与 rawptr[T] 同一条规则(见 SymbolUtils.IsPtrSubscriptNode)。
if IsPtrSubscriptNode(Node, self.Trans.SymbolTable): if IsPtrSubscriptNode(Node, self.Trans.SymbolTable):
Node = DesugarPtrSubscriptToUnion(Node, self.Trans.SymbolTable) Node = DesugarPtrSubscriptToUnion(Node, self.Trans.SymbolTable)
@@ -890,12 +832,12 @@ class HandlesTypeMerge(BaseHandle):
if isinstance(Node, ast.Call): if isinstance(Node, ast.Call):
if isinstance(Node.func, ast.Name) and Node.func.id == 'callable': if isinstance(Node.func, ast.Name) and Node.func.id == 'callable':
return self.GetCTypeInfo(Node) return self.GetCTypeInfo(Node)
elif isinstance(Node.func, ast.Attribute) and CTypeHelper.GetTModuleCType(Node.func.attr) == t._CTypedef: elif isinstance(Node.func, ast.Attribute) and CTypeHelper.GetTModuleCType(Node.func.attr) == TypeSystem._CTypedef:
return self.GetCTypeInfo(Node) return self.GetCTypeInfo(Node)
elif isinstance(Node.func, ast.Attribute) and Node.func.attr == 'Bit': elif isinstance(Node.func, ast.Attribute) and Node.func.attr == 'Bit':
if Node.args and isinstance(Node.args[0], ast.Constant): if Node.args and isinstance(Node.args[0], ast.Constant):
Result = CTypeInfo() Result = CTypeInfo()
Result.BaseType = t.CInt Result.BaseType = TypeSystem.CInt
Result.IsBitField = True Result.IsBitField = True
Result.BitWidth = Node.args[0].value Result.BitWidth = Node.args[0].value
return Result return Result
@@ -903,11 +845,11 @@ class HandlesTypeMerge(BaseHandle):
elif isinstance(Node, ast.Subscript): elif isinstance(Node, ast.Subscript):
if (isinstance(Node.value, ast.Attribute) if (isinstance(Node.value, ast.Attribute)
and isinstance(Node.value.value, ast.Name) and isinstance(Node.value.value, ast.Name)
and IsTModule(Node.value.value.id, self.Trans.SymbolTable)
and Node.value.attr == 'Bit'): and Node.value.attr == 'Bit'):
if isinstance(Node.slice, ast.Constant) and isinstance(Node.slice.value, int): if isinstance(Node.slice, ast.Constant) and isinstance(Node.slice.value, int):
Result = CTypeInfo() Result = CTypeInfo()
Result.BaseType = t.CInt Result.BaseType = TypeSystem.CInt
Result.IsBitField = True Result.IsBitField = True
Result.BitWidth = Node.slice.value Result.BitWidth = Node.slice.value
return Result return Result
@@ -916,7 +858,7 @@ class HandlesTypeMerge(BaseHandle):
return self.GetCTypeInfo(Node) return self.GetCTypeInfo(Node)
def MergeTypes(self, Node: ast.BinOp): def MergeTypes(self, Node: ast.BinOp):
"""处理类型组合,如 t.CInt | t.CPtr ?t.CStatic | t.CInt """处理类型组合,如 CInt | CPtr ?CStatic | CInt
这是 | 运算符的类型合并处理函数 这是 | 运算符的类型合并处理函数
收集所有操作数,一次性合? 收集所有操作数,一次性合?
@@ -935,15 +877,15 @@ class HandlesTypeMerge(BaseHandle):
LeftParts = [] LeftParts = []
current = Node.left current = Node.left
while isinstance(current, ast.Attribute): while isinstance(current, ast.Attribute):
attr_type = getattr(t, current.attr, None) attr_type = getattr(TypeSystem, current.attr, None)
if attr_type and isinstance(attr_type, type) and issubclass(attr_type, t.CType): if attr_type and isinstance(attr_type, type) and issubclass(attr_type, TypeSystem.CType):
LeftParts.insert(0, attr_type) LeftParts.insert(0, attr_type)
current = current.value current = current.value
if isinstance(current, ast.Name): if isinstance(current, ast.Name):
name_type = getattr(t, current.id, None) name_type = getattr(TypeSystem, current.id, None)
if name_type and isinstance(name_type, type) and issubclass(name_type, t.CType): if name_type and isinstance(name_type, type) and issubclass(name_type, TypeSystem.CType):
LeftParts.insert(0, name_type) LeftParts.insert(0, name_type)
if LeftParts and LeftParts[-1] == t._CTypedef: if LeftParts and LeftParts[-1] == TypeSystem._CTypedef:
for type_item in AllTypes: for type_item in AllTypes:
if isinstance(type_item, CTypeInfo) and type_item.IsFuncPtr: if isinstance(type_item, CTypeInfo) and type_item.IsFuncPtr:
type_item.IsTypedef = True type_item.IsTypedef = True
@@ -956,7 +898,7 @@ class HandlesTypeMerge(BaseHandle):
if isinstance(AllTypes[-1], CTypeInfo): if isinstance(AllTypes[-1], CTypeInfo):
Result.BaseType = AllTypes[-1].BaseType Result.BaseType = AllTypes[-1].BaseType
else: else:
Result.BaseType = t.CInt Result.BaseType = TypeSystem.CInt
Result.IsTypedef = True Result.IsTypedef = True
return Result return Result
@@ -968,37 +910,37 @@ class HandlesTypeMerge(BaseHandle):
return CTypeInfo() return CTypeInfo()
Result = CTypeInfo() Result = CTypeInfo()
# 统计 t.CPtr(CVoid + PtrCount=1)的个数,用于正确累加指针层数 # 统计 CPtr(CVoid + PtrCount=1)的个数,用于正确累加指针层数
# 因为 (AST | t.CPtr) | t.CPtr 展开后会包含多个 t.CPtr,每个都需要累加 # 因为 (AST | CPtr) | CPtr 展开后会包含多个 CPtr,每个都需要累加
cptr_count: int = 0 cptr_count: int = 0
for TypeItem in Types: for TypeItem in Types:
if TypeItem is None: if TypeItem is None:
continue continue
if TypeItem.IsDefine: if TypeItem.IsDefine:
# t.CDefine 标记在 | 合并中传播(对齐 IsState): # CDefine 标记在 | 合并中传播(对齐 IsState):
# `int | t.CDefine`(define 宏函数返回注解)合并后仍保持 # `int | CDefine`(define 宏函数返回注解)合并后仍保持
# IsDefine=True,下游才能识别为编译期宏(alwaysinline/#define) # IsDefine=True,下游才能识别为编译期宏(alwaysinline/#define)
Result.IsDefine = True Result.IsDefine = True
if TypeItem.IsState: if TypeItem.IsState:
Result.IsState = True Result.IsState = True
if not Result.Storage: if not Result.Storage:
Result.Storage = t.CExport() Result.Storage = TypeSystem.CExport()
continue continue
if TypeItem.IsBitField: if TypeItem.IsBitField:
Result.BaseType = t.CInt Result.BaseType = TypeSystem.CInt
Result.IsBitField = True Result.IsBitField = True
Result.BitWidth = TypeItem.BitWidth Result.BitWidth = TypeItem.BitWidth
return Result return Result
if TypeItem.IsFuncPtr: if TypeItem.IsFuncPtr:
Result.BaseType = t.CVoid Result.BaseType = TypeSystem.CVoid
Result.IsFuncPtr = True Result.IsFuncPtr = True
Result.FuncPtrParams = TypeItem.FuncPtrParams Result.FuncPtrParams = TypeItem.FuncPtrParams
Result.FuncPtrReturn = TypeItem.FuncPtrReturn Result.FuncPtrReturn = TypeItem.FuncPtrReturn
return Result return Result
if TypeItem.IsTypedef: if TypeItem.IsTypedef:
if TypeItem.BaseType and (not isinstance(TypeItem.BaseType, (t._CTypedef,)) or TypeItem.PtrCount > 0): if TypeItem.BaseType and (not isinstance(TypeItem.BaseType, (TypeSystem._CTypedef,)) or TypeItem.PtrCount > 0):
if Result.BaseType is None or isinstance(Result.BaseType, (t.CVoid, t._CTypedef)): if Result.BaseType is None or isinstance(Result.BaseType, (TypeSystem.CVoid, TypeSystem._CTypedef)):
Result.BaseType = TypeItem.BaseType Result.BaseType = TypeItem.BaseType
Result.Name = TypeItem.Name Result.Name = TypeItem.Name
Result.IsTypedef = True Result.IsTypedef = True
@@ -1011,9 +953,9 @@ class HandlesTypeMerge(BaseHandle):
if TypeItem.OriginalType: if TypeItem.OriginalType:
Result.OriginalType = TypeItem.OriginalType Result.OriginalType = TypeItem.OriginalType
continue continue
# 统计 t.CPtr(CVoid + PtrCount>0) # 统计 CPtr(CVoid + PtrCount>0)
# 注意: t.CPtr[t.CPtr] 的 PtrCount=2(双重指针),需要完整累加 # 注意: CPtr[CPtr] 的 PtrCount=2(双重指针),需要完整累加
if TypeItem.PtrCount > 0 and TypeItem.BaseType and (TypeItem.BaseType is t.CVoid or isinstance(TypeItem.BaseType, t.CVoid)): if TypeItem.PtrCount > 0 and TypeItem.BaseType and (TypeItem.BaseType is TypeSystem.CVoid or isinstance(TypeItem.BaseType, TypeSystem.CVoid)):
cptr_count += TypeItem.PtrCount cptr_count += TypeItem.PtrCount
# BaseType 保持不变,只计数,后续统一累加 # BaseType 保持不变,只计数,后续统一累加
if TypeItem.IsRenum and TypeItem.Name: if TypeItem.IsRenum and TypeItem.Name:
@@ -1025,29 +967,29 @@ class HandlesTypeMerge(BaseHandle):
continue continue
self._MergeCTypeInfoInto(Result, TypeItem) self._MergeCTypeInfoInto(Result, TypeItem)
# 对所有 t.CPtr 统一累加指针层数 # 对所有 CPtr 统一累加指针层数
# 仅对 struct 类型吸收第一个 CPtr(struct 变量默认是指针,AST | t.CPtr = AST*)。 # 仅对 struct 类型吸收第一个 CPtr(struct 变量默认是指针,AST | CPtr = AST*)。
# 对于本身已是指针的类型(如 bytes=CChar*),bytes | t.CPtr = i8**(不吸收)。 # 对于本身已是指针的类型(如 bytes=CChar*),bytes | CPtr = i8**(不吸收)。
base_ptr_count: int = Result.PtrCount base_ptr_count: int = Result.PtrCount
Result.PtrCount += cptr_count Result.PtrCount += cptr_count
if Result.IsStruct and base_ptr_count > 0 and cptr_count > 0: if Result.IsStruct and base_ptr_count > 0 and cptr_count > 0:
Result.PtrCount -= 1 Result.PtrCount -= 1
if Result.BaseType is None: if Result.BaseType is None:
Result.BaseType = t.CVoid Result.BaseType = TypeSystem.CVoid
return Result return Result
def _MergeCTypeInfoInto(self, Target: CTypeInfo, Source: CTypeInfo): def _MergeCTypeInfoInto(self, Target: CTypeInfo, Source: CTypeInfo):
if Source.PtrCount > 0 and Source.BaseType and (Source.BaseType is t.CVoid or isinstance(Source.BaseType, t.CVoid)): if Source.PtrCount > 0 and Source.BaseType and (Source.BaseType is TypeSystem.CVoid or isinstance(Source.BaseType, TypeSystem.CVoid)):
# t.CPtr 的处理已提升到 _MergeAllComponentTypes 中统一计数累加, # CPtr 的处理已提升到 _MergeAllComponentTypes 中统一计数累加,
# 此处保留仅作为兜底(从其他路径直接调用 _MergeCTypeInfoInto 时) # 此处保留仅作为兜底(从其他路径直接调用 _MergeCTypeInfoInto 时)
if Target.PtrCount < Source.PtrCount: if Target.PtrCount < Source.PtrCount:
Target.PtrCount = Source.PtrCount Target.PtrCount = Source.PtrCount
elif Source.PtrCount > 0 and Source.BaseType and Source.BaseType is not t.CVoid and not isinstance(Source.BaseType, t.CVoid): elif Source.PtrCount > 0 and Source.BaseType and Source.BaseType is not TypeSystem.CVoid and not isinstance(Source.BaseType, TypeSystem.CVoid):
if Target.BaseType is None or Target.BaseType is t.CVoid or isinstance(Target.BaseType, t.CVoid): if Target.BaseType is None or Target.BaseType is TypeSystem.CVoid or isinstance(Target.BaseType, TypeSystem.CVoid):
Target.BaseType = Source.BaseType Target.BaseType = Source.BaseType
# 当 Target 已有 PtrCount(来自之前的 t.CPtr),累加而非替换 # 当 Target 已有 PtrCount(来自之前的 CPtr),累加而非替换
Target.PtrCount = Source.PtrCount + Target.PtrCount Target.PtrCount = Source.PtrCount + Target.PtrCount
elif Target.PtrCount == 0: elif Target.PtrCount == 0:
Target.PtrCount = Source.PtrCount Target.PtrCount = Source.PtrCount
@@ -1055,25 +997,25 @@ class HandlesTypeMerge(BaseHandle):
Target.PtrCount = Source.PtrCount Target.PtrCount = Source.PtrCount
elif Source.PtrCount > Target.PtrCount: elif Source.PtrCount > Target.PtrCount:
Target.PtrCount = Source.PtrCount Target.PtrCount = Source.PtrCount
if Source.BaseType and Source.BaseType is not t.CVoid and not isinstance(Source.BaseType, (t.CVoid, t._CTypedef)): if Source.BaseType and Source.BaseType is not TypeSystem.CVoid and not isinstance(Source.BaseType, (TypeSystem.CVoid, TypeSystem._CTypedef)):
if Target.BaseType is None: if Target.BaseType is None:
Target.BaseType = Source.BaseType Target.BaseType = Source.BaseType
elif (Target.BaseType is t.CVoid or isinstance(Target.BaseType, t.CVoid)) and Target.PtrCount == 0: elif (Target.BaseType is TypeSystem.CVoid or isinstance(Target.BaseType, TypeSystem.CVoid)) and Target.PtrCount == 0:
Target.BaseType = Source.BaseType Target.BaseType = Source.BaseType
elif (Source.BaseType is t.CVoid or isinstance(Source.BaseType, t.CVoid)) and Target.BaseType is None: elif (Source.BaseType is TypeSystem.CVoid or isinstance(Source.BaseType, TypeSystem.CVoid)) and Target.BaseType is None:
Target.BaseType = Source.BaseType Target.BaseType = Source.BaseType
# Struct 名称保留:BinOp `list[AST | t.CPtr] | t.CPtr` 合并时, # Struct 名称保留:BinOp `list[AST | CPtr] | CPtr` 合并时,
# _HandleSubscript 已在 Source.Name 设置了特化名(如 'list[5dab8cb390496d22.ASTptr]'), # _HandleSubscript 已在 Source.Name 设置了特化名(如 'list[5dab8cb390496d22.ASTptr]'),
# 合并后 Target.Name 必须保留此名称,否则 class_member_element_class # 合并后 Target.Name 必须保留此名称,否则 class_member_element_class
# 无法获取正确的特化类名 → 方法分派 fallback 到错误的类 # 无法获取正确的特化类名 → 方法分派 fallback 到错误的类
if Source.IsStruct and Source.Name and not Target.Name: if Source.IsStruct and Source.Name and not Target.Name:
Target.Name = Source.Name Target.Name = Source.Name
# 【IsStruct 必须随 Name 一起传播】`_MergeAllComponentTypes` 的 # 【IsStruct 必须随 Name 一起传播】`_MergeAllComponentTypes` 的
# "struct 吸收第一个 t.CPtr"规则(见该函数 :1022-1027 的注释: # "struct 吸收第一个 CPtr"规则(见该函数 :1022-1027 的注释:
# struct 变量默认是指针 ⇒ `AST | t.CPtr = AST*`)以 `Result.IsStruct` 为**闸门**: # struct 变量默认是指针 ⇒ `AST | CPtr = AST*`)以 `Result.IsStruct` 为**闸门**:
# 此前本函数只复制 Name、从不置 IsStruct ⇒ 闸门恒假 ⇒ 闸门后的 # 此前本函数只复制 Name、从不置 IsStruct ⇒ 闸门恒假 ⇒ 闸门后的
# `Result.PtrCount -= 1` 永不执行 ⇒ 「类 + CPtr」的联合(如 # `Result.PtrCount -= 1` 永不执行 ⇒ 「类 + CPtr」的联合(如
# `list[str] | t.CPtr`)合并后指针层数**多算一层**(得 `list[str]**`,应为 # `list[str] | CPtr`)合并后指针层数**多算一层**(得 `list[str]**`,应为
# `list[str]*`)⇒ 调用点/字段拿到的值类型 pointee 是指针而不是结构体 ⇒ # `list[str]*`)⇒ 调用点/字段拿到的值类型 pointee 是指针而不是结构体 ⇒
# 类名在下游被当作通用指针处理(现场:`parts = s1.split(',')` 的返回值 # 类名在下游被当作通用指针处理(现场:`parts = s1.split(',')` 的返回值
# pointee 非结构体 ⇒ HandlesAssign 的类名推断整块跳过 ⇒ 随后 `parts[0]` # pointee 非结构体 ⇒ HandlesAssign 的类名推断整块跳过 ⇒ 随后 `parts[0]`
@@ -1081,7 +1023,7 @@ class HandlesTypeMerge(BaseHandle):
# 语义上这两个标志同源(合并结果就是那个 struct),故成对传播。 # 语义上这两个标志同源(合并结果就是那个 struct),故成对传播。
if Source.IsStruct: if Source.IsStruct:
Target.IsStruct = True Target.IsStruct = True
# REnum 标志和名称保留(BinOp `LLVMType | t.CPtr` 合并时不能丢失 REnum 语义) # REnum 标志和名称保留(BinOp `LLVMType | CPtr` 合并时不能丢失 REnum 语义)
# 同时传播 IsStruct=True,让 CPtr 吸收逻辑生效(REnum 在内存布局上是 struct) # 同时传播 IsStruct=True,让 CPtr 吸收逻辑生效(REnum 在内存布局上是 struct)
if Source.IsRenum and Source.Name: if Source.IsRenum and Source.Name:
Target.IsRenum = True Target.IsRenum = True
@@ -1090,14 +1032,14 @@ class HandlesTypeMerge(BaseHandle):
if not Target.Name: if not Target.Name:
Target.Name = Source.Name Target.Name = Source.Name
if Source.IsTypedef and Source.Name: if Source.IsTypedef and Source.Name:
if Source.BaseType and (not isinstance(Source.BaseType, (t._CTypedef,)) or Source.PtrCount > 0): if Source.BaseType and (not isinstance(Source.BaseType, (TypeSystem._CTypedef,)) or Source.PtrCount > 0):
if Target.BaseType is None or isinstance(Target.BaseType, (t.CVoid, t._CTypedef)): if Target.BaseType is None or isinstance(Target.BaseType, (TypeSystem.CVoid, TypeSystem._CTypedef)):
Target.BaseType = Source.BaseType Target.BaseType = Source.BaseType
Target.IsTypedef = True Target.IsTypedef = True
Target.Name = Source.Name Target.Name = Source.Name
if Source.OriginalType: if Source.OriginalType:
Target.OriginalType = Source.OriginalType Target.OriginalType = Source.OriginalType
elif Target.BaseType is None or isinstance(Target.BaseType, (t.CVoid, t._CTypedef)): elif Target.BaseType is None or isinstance(Target.BaseType, (TypeSystem.CVoid, TypeSystem._CTypedef)):
if Source.OriginalType: if Source.OriginalType:
if isinstance(Source.OriginalType, CTypeInfo) and Source.OriginalType.BaseType: if isinstance(Source.OriginalType, CTypeInfo) and Source.OriginalType.BaseType:
Target.BaseType = Source.OriginalType.BaseType Target.BaseType = Source.OriginalType.BaseType
@@ -1110,10 +1052,10 @@ class HandlesTypeMerge(BaseHandle):
Target.Name = Source.Name Target.Name = Source.Name
Target.OriginalType = Source.OriginalType Target.OriginalType = Source.OriginalType
else: else:
Target.BaseType = t.CStruct(name=Source.Name) Target.BaseType = TypeSystem.CStruct(name=Source.Name)
Target.IsStruct = True Target.IsStruct = True
else: else:
Target.BaseType = t.CStruct(name=Source.Name) Target.BaseType = TypeSystem.CStruct(name=Source.Name)
Target.IsStruct = True Target.IsStruct = True
if Source.ArrayPtr: if Source.ArrayPtr:
if Target.ArrayPtr is None: if Target.ArrayPtr is None:
+23 -23
View File
@@ -4,8 +4,8 @@ import vast as ast
import os import os
import re import re
import llvmlite.ir as ir import llvmlite.ir as ir
from lib.includes import t as _t from lib.core import TypeSystem as _t
from lib.includes.t import CTypeRegistry from lib.core.TypeSystem import CTypeRegistry
from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo, BuiltinTypeMap from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo, BuiltinTypeMap
from lib.core.SymbolUtils import EnumIntWidth, _ENUM_DEFAULT_INT_WIDTH from lib.core.SymbolUtils import EnumIntWidth, _ENUM_DEFAULT_INT_WIDTH
from lib.constants.config import DEFAULT_HOTSPOT_CALLEES from lib.constants.config import DEFAULT_HOTSPOT_CALLEES
@@ -351,7 +351,7 @@ class BaseGenMixin:
self.loop_break_targets: list[ir.Block] = [] self.loop_break_targets: list[ir.Block] = []
self.loop_continue_targets: list[ir.Block] = [] self.loop_continue_targets: list[ir.Block] = []
# 当前是否正处于 switch 的 case 语句体内(True=是)。供 `fallthrough` # 当前是否正处于 switch 的 case 语句体内(True=是)。供 `fallthrough`
# 标记语句(vast 脱糖为 c.NoBreak())判定合法性:只在 switch 的 case 体内 # 标记语句(vast 脱糖为 NoBreak())判定合法性:只在 switch 的 case 体内
# 合法;写进 match(完全禁止 fallthrough)或 switch 之外一律 fail-fast。 # 合法;写进 match(完全禁止 fallthrough)或 switch 之外一律 fail-fast。
self.in_switch_case: bool = False self.in_switch_case: bool = False
self.eh_jmp_buf_stack: list[ir.Value] = [] self.eh_jmp_buf_stack: list[ir.Value] = []
@@ -370,7 +370,7 @@ class BaseGenMixin:
self.var_annotated_class: dict[str, str] = {} self.var_annotated_class: dict[str, str] = {}
self.var_ptr_element: dict[str, bool] = {} self.var_ptr_element: dict[str, bool] = {}
# 全局变量的指针元素标志(持久,不受函数重置影响) # 全局变量的指针元素标志(持久,不受函数重置影响)
# 用于全局变量 _argv: bytes | t.CPtr 等,使 _argv[index] 使用 8 字节指针步长 # 用于全局变量 _argv: bytes | CPtr 等,使 _argv[index] 使用 8 字节指针步长
self.global_var_ptr_element: dict[str, bool] = {} self.global_var_ptr_element: dict[str, bool] = {}
self.class_provides: dict[str, list[str]] = {} self.class_provides: dict[str, list[str]] = {}
self.class_requires: dict[str, list[str]] = {} self.class_requires: dict[str, list[str]] = {}
@@ -381,7 +381,7 @@ class BaseGenMixin:
# 函数参数自动取地址模式: func_name -> [None, None, 'ref', 'temp', 'always', ...] # 函数参数自动取地址模式: func_name -> [None, None, 'ref', 'temp', 'always', ...]
# 'ref': &T — 实参非指针左值取址,右值 fail-fast # 'ref': &T — 实参非指针左值取址,右值 fail-fast
# 'temp': &temp T — 实参非指针时在调用方建同型临时再取址 # 'temp': &temp T — 实参非指针时在调用方建同型临时再取址
# 'always': t.CAutoPtr — 无条件取地址 # 'always': CAutoPtr — 无条件取地址
self._auto_addr_params: dict[str, list[str | None]] = {} self._auto_addr_params: dict[str, list[str | None]] = {}
self.global_struct_class: dict[str, str] = {} self.global_struct_class: dict[str, str] = {}
self.var_type_info: dict[str, Any] = {} self.var_type_info: dict[str, Any] = {}
@@ -392,7 +392,7 @@ class BaseGenMixin:
# 函数作用域层(随函数出栈清空,清零点 HandlesFunctions 函数出口): # 函数作用域层(随函数出栈清空,清零点 HandlesFunctions 函数出口):
# var_const_flags 变量(局部/形参)自身 const # var_const_flags 变量(局部/形参)自身 const
# var_volatile_flags 变量自身 volatile # var_volatile_flags 变量自身 volatile
# var_pointee_volatile_flags 变量所指物 volatile(rawptr[t.CVolatile|T]) # var_pointee_volatile_flags 变量所指物 volatile(rawptr[CVolatile|T])
# 模块级层(模块存活期持久): # 模块级层(模块存活期持久):
# global_* 模块级同名三类 # global_* 模块级同名三类
# 类字段层(模块存活期持久): # 类字段层(模块存活期持久):
@@ -699,14 +699,14 @@ class BaseGenMixin:
# 而非创建为 opaque 结构体(否则包含 Any 字段的结构体会变成 unsized)。 # 而非创建为 opaque 结构体(否则包含 Any 字段的结构体会变成 unsized)。
if clean_name == 'Any': if clean_name == 'Any':
return ir.IntType(8).as_pointer() return ir.IntType(8).as_pointer()
# t.CType 的基本类型子类(CInt/CChar/CSizeT/CLong/CFloat/CDouble 等, # CType 的基本类型子类(CInt/CChar/CSizeT/CLong/CFloat/CDouble 等,
# position 含 BASE 且 Size>0)有具体 LLVM 类型,应直接返回对应的 # position 含 BASE 且 Size>0)有具体 LLVM 类型,应直接返回对应的
# ir.IntType/ir.FloatType/ir.DoubleType,而非创建结构体。 # ir.IntType/ir.FloatType/ir.DoubleType,而非创建结构体。
# _is_ctype_marker_name 对这些类型返回 False(不跳过),需要在此处拦截。 # _is_ctype_marker_name 对这些类型返回 False(不跳过),需要在此处拦截。
_basic_llvm_type: ir.Type | None = self._try_resolve_ctype_basic(clean_name) _basic_llvm_type: ir.Type | None = self._try_resolve_ctype_basic(clean_name)
if _basic_llvm_type is not None: if _basic_llvm_type is not None:
return _basic_llvm_type return _basic_llvm_type
# t.CType 及其子类是"类型强转"标记,不应被编译为真实结构体。 # CType 及其子类是"类型强转"标记,不应被编译为真实结构体。
# 动态检查 t 模块中所有 CType 子类名(排除 CStruct/CEnum/CUnion/REnum 子类, # 动态检查 t 模块中所有 CType 子类名(排除 CStruct/CEnum/CUnion/REnum 子类,
# 因为用户定义的结构体类继承自它们,需要被创建为结构体)。 # 因为用户定义的结构体类继承自它们,需要被创建为结构体)。
if self._is_ctype_marker_name(clean_name): if self._is_ctype_marker_name(clean_name):
@@ -718,12 +718,12 @@ class BaseGenMixin:
# HandlesTypeMerge 的 Name/Attribute 分支、DeclarationGenerator 的 # HandlesTypeMerge 的 Name/Attribute 分支、DeclarationGenerator 的
# `attr_name in struct_names` 同一条规则源): # `attr_name in struct_names` 同一条规则源):
# _struct_sha1_map / class_sha1_map 已登记该名为**类**时,即便平坦符号表 # _struct_sha1_map / class_sha1_map 已登记该名为**类**时,即便平坦符号表
# 条目是**同名枚举成员**(如 ast/base.vp 的 `Constant: t.State` 与 # 条目是**同名枚举成员**(如 ast/base.vp 的 `Constant: State` 与
# ast/exprs.vp 的 `class Constant` 同名;谁后插入谁占住裸名),也必须建成 # ast/exprs.vp 的 `class Constant` 同名;谁后插入谁占住裸名),也必须建成
# 结构体。否则此处返回 i32 ⇒ 上游 PtrCount=1 叠加后变成 i32*, # 结构体。否则此处返回 i32 ⇒ 上游 PtrCount=1 叠加后变成 i32*,
# 与调用点实参 %"<sha1>.Constant"* 分裂(现场:constant_get_str_val 的 # 与调用点实参 %"<sha1>.Constant"* 分裂(现场:constant_get_str_val 的
# 形参 i32*)。类型注解语境下枚举**成员**从不是类型,判据只能是"是否有类定义"。 # 形参 i32*)。类型注解语境下枚举**成员**从不是类型,判据只能是"是否有类定义"。
# 必须排除**枚举类型本身**(如 `class ASTKind(t.CEnum)`):_struct_sha1_map # 必须排除**枚举类型本身**(如 `class ASTKind(CEnum)`):_struct_sha1_map
# 是按 .vpi 里全部 ClassDef 建的,枚举类也在其中 —— 若一并当结构体,枚举 # 是按 .vpi 里全部 ClassDef 建的,枚举类也在其中 —— 若一并当结构体,枚举
# 注解(kind() 返回值等)会被建为 opaque struct,引发 i32 ↔ 结构体错位 # 注解(kind() 返回值等)会被建为 opaque struct,引发 i32 ↔ 结构体错位
# ('IntType' object has no attribute 'is_opaque' 现场)。 # ('IntType' object has no attribute 'is_opaque' 现场)。
@@ -880,7 +880,7 @@ class BaseGenMixin:
pass pass
return 0 # 标记为 typedef,但位宽为 0(非整数) return 0 # 标记为 typedef,但位宽为 0(非整数)
# t.CType 及其子类是"类型强转"标记,不应被创建为结构体。 # CType 及其子类是"类型强转"标记,不应被创建为结构体。
# 动态检查 t 模块中所有 CType 子类名(排除 CStruct/CEnum/CUnion/REnum 子类)。 # 动态检查 t 模块中所有 CType 子类名(排除 CStruct/CEnum/CUnion/REnum 子类)。
# 返回 0 标记为 typedef,使 _get_or_create_struct 走 typedef 路径返回 i8。 # 返回 0 标记为 typedef,使 _get_or_create_struct 走 typedef 路径返回 i8。
if self._is_ctype_marker_name(name): if self._is_ctype_marker_name(name):
@@ -890,7 +890,7 @@ class BaseGenMixin:
@staticmethod @staticmethod
def _is_ctype_marker_name(name: str) -> bool: def _is_ctype_marker_name(name: str) -> bool:
"""检查名称是否是 t.CType 的"类型强转"标记子类名。 """检查名称是否是 CType 的"类型强转"标记子类名。
只有 position 不含 BASE 的纯修饰符/标记类型(CPtr/CVolatile/CConst/ 只有 position 不含 BASE 的纯修饰符/标记类型(CPtr/CVolatile/CConst/
CInline/CStatic/CExtern/CExport/CRegister/CAuto/_CTypedef/CTypeDefault 等) CInline/CStatic/CExtern/CExport/CRegister/CAuto/_CTypedef/CTypeDefault 等)
@@ -900,7 +900,7 @@ class BaseGenMixin:
CStruct/CEnum/CUnion/REnum 的用户子类是合法结构体,需要被创建。 CStruct/CEnum/CUnion/REnum 的用户子类是合法结构体,需要被创建。
注意:CTypeRegistry.GetClassByName 会跳过 CType 本身和 CTypeDefault, 注意:CTypeRegistry.GetClassByName 会跳过 CType 本身和 CTypeDefault,
所以这里直接用 getattr(t, name) 检查 t 模块属性。 所以这里直接用 getattr(TypeSystem, name) 检查 t 模块属性。
Returns: Returns:
True 如果 name 是 CType 标记子类名(应跳过结构体创建) True 如果 name 是 CType 标记子类名(应跳过结构体创建)
@@ -932,7 +932,7 @@ class BaseGenMixin:
return True return True
def _try_resolve_ctype_basic(self, name: str) -> ir.Type | None: def _try_resolve_ctype_basic(self, name: str) -> ir.Type | None:
"""尝试将 t.CType 的基本类型子类名解析为对应的 LLVM 基本类型。 """尝试将 CType 的基本类型子类名解析为对应的 LLVM 基本类型。
仅对 t 模块内的 CType 基本类型子类(CInt/CChar/CSizeT/CLong/CFloat/ 仅对 t 模块内的 CType 基本类型子类(CInt/CChar/CSizeT/CLong/CFloat/
CDouble 等,即 position 含 BASE 且 Size>0)生效,返回对应的 CDouble 等,即 position 含 BASE 且 Size>0)生效,返回对应的
@@ -1328,8 +1328,8 @@ class BaseGenMixin:
(translator._line_offset = N);而 `Gen._current_source_lines` 是**磁盘** (translator._line_offset = N);而 `Gen._current_source_lines` 是**磁盘**
原文 ⇒ 任何"AST 行号 + 源码行"的输出都必须先减 N,否则印出的源码是下一行。 原文 ⇒ 任何"AST 行号 + 源码行"的输出都必须先减 N,否则印出的源码是下一行。
本渲染器此前漏还原,于是同一次 fail-fast 里出现两套矛盾行号 本渲染器此前漏还原,于是同一次 fail-fast 里出现两套矛盾行号
(现场:真实错误在 TypeGenResolve.vp:1141 `= "t.CPtr"`, (现场:真实错误在 TypeGenResolve.vp:1141 `= "CPtr"`,
_get_node_info 印 1142 且源码取到 1142 行的 `return "t.CPtr"`, _get_node_info 印 1142 且源码取到 1142 行的 `return "CPtr"`,
而 _ErrorStack 帧印的是正确的 1141/1140)。 而 _ErrorStack 帧印的是正确的 1141/1140)。
""" """
if Lineno <= 0: if Lineno <= 0:
@@ -1368,7 +1368,7 @@ class BaseGenMixin:
回退当前语句上下文(_get_node_info 风格),不再固定打印外层 Assign。 回退当前语句上下文(_get_node_info 风格),不再固定打印外层 Assign。
关键 ②:**行号必须先还原为磁盘行号**(_DiskLineno)——节点行号含文件头 关键 ②:**行号必须先还原为磁盘行号**(_DiskLineno)——节点行号含文件头
自动注入 import 的偏移,直接用来读源码会读到下一行(现场:真实错误行 自动注入 import 的偏移,直接用来读源码会读到下一行(现场:真实错误行
1141,这里印成 1142 且源码显示出 1142 行的 `return "t.CPtr"`)。 1141,这里印成 1142 且源码显示出 1142 行的 `return "CPtr"`)。
""" """
if Node is None: if Node is None:
return self._get_node_info() return self._get_node_info()
@@ -1403,14 +1403,14 @@ class BaseGenMixin:
"""注解解析结果是否为「变量自身 const」的对象(C 语义下的 const 对象)。 """注解解析结果是否为「变量自身 const」的对象(C 语义下的 const 对象)。
判据(两侧统一):`(DataConst or VarConst)` 且 `PtrCount == 0`。 判据(两侧统一):`(DataConst or VarConst)` 且 `PtrCount == 0`。
`t.CConst` 在本仓库解析为 **DataConst**(t 模块分支:HandlesTypeMerge.py:192-196、 `CConst` 在本仓库解析为 **DataConst**(t 模块分支:HandlesTypeMerge.py:192-196、
TypeAnnotationResolver.py:382-389),其字段语义是「指向的数据 const」 TypeAnnotationResolver.py:382-389),其字段语义是「指向的数据 const」
(HandlesBase.py:76-77)。因此: (HandlesBase.py:76-77)。因此:
- 非指针类型(PtrCount==0):该限定退化为「该对象自身 const」⇒ - 非指针类型(PtrCount==0):该限定退化为「该对象自身 const」⇒
`a: const int` / `a: t.CConst | int` 的 a 禁止赋值/增量赋值/元素赋值; `a: const int` / `a: CConst | int` 的 a 禁止赋值/增量赋值/元素赋值;
- 指针类型(PtrCount>=1):限定只作用于 pointee ⇒ `const T *p` 的 p - 指针类型(PtrCount>=1):限定只作用于 pointee ⇒ `const T *p` 的 p
仍可重新赋值(C 语义),**不**登记为 const 变量。 仍可重新赋值(C 语义),**不**登记为 const 变量。
后者就是全仓既有两处 `t.CConst | T | t.CPtr` 局部变量(fat32_types.vp:1591 后者就是全仓既有两处 `CConst | T | CPtr` 局部变量(fat32_types.vp:1591
`buf_ptr`、elf.vp:509 `cmp_name`)在其作用域内被重新赋值却合法的原因。 `buf_ptr`、elf.vp:509 `cmp_name`)在其作用域内被重新赋值却合法的原因。
""" """
if Info is None: if Info is None:
@@ -1441,7 +1441,7 @@ class BaseGenMixin:
@staticmethod @staticmethod
def _AnnotationHasPointeeVolatile(Annotation: Any) -> bool: def _AnnotationHasPointeeVolatile(Annotation: Any) -> bool:
"""注解是否为 `rawptr[t.CVolatile | T]`(volatile 指针指向物,等价 C 的 volatile T*)。 """注解是否为 `rawptr[CVolatile | T]`(volatile 指针指向物,等价 C 的 volatile T*)。
与 ViperC TypeGenErr.has_pointee_volatile_marker 同口径:只看 `rawptr[...]` 与 ViperC TypeGenErr.has_pointee_volatile_marker 同口径:只看 `rawptr[...]`
的下标实参子树里有没有 CVolatile;多级指针(slice 仍是 Subscript)明确不支持。 的下标实参子树里有没有 CVolatile;多级指针(slice 仍是 Subscript)明确不支持。
@@ -1463,7 +1463,7 @@ class BaseGenMixin:
IsParam=True 时 **const 判据沿用形参的历史条件** `DataConst or VarConst` IsParam=True 时 **const 判据沿用形参的历史条件** `DataConst or VarConst`
(不看指针层数):这是「形参保持现状 + 不得放宽任何既有 fail-fast」两条 (不看指针层数):这是「形参保持现状 + 不得放宽任何既有 fail-fast」两条
硬约束下的唯一选择——把形参也改成指针感知判据虽然更合 C 语义,但会**放宽** 硬约束下的唯一选择——把形参也改成指针感知判据虽然更合 C 语义,但会**放宽**
既有形参检查(`fmt: t.CConst | str` 这类指针形参不再登记),从约束上不允许。 既有形参检查(`fmt: CConst | str` 这类指针形参不再登记),从约束上不允许。
该历史条件对 `const T*` 形参过严,但全仓 462 个 .vp 普查(见 该历史条件对 `const T*` 形参过严,但全仓 462 个 .vp 普查(见
Debugger/type-descriptors.md)表明**零个形参在其函数体内被重新赋值**, Debugger/type-descriptors.md)表明**零个形参在其函数体内被重新赋值**,
故这处差异在既有代码上不可观测。非形参的三种声明一律用指针感知判据 故这处差异在既有代码上不可观测。非形参的三种声明一律用指针感知判据
@@ -1606,7 +1606,7 @@ class BaseGenMixin:
return ( return (
f"不能对 const 变量 '{Name}' {Kind}{self._get_node_info()}" f"不能对 const 变量 '{Name}' {Kind}{self._get_node_info()}"
f"(声明处类型(含 const):{DeclType};" f"(声明处类型(含 const):{DeclType};"
f"修法:删掉该声明里的 `const` 描述符 / `t.CConst`,或改为声明时一次赋值、" f"修法:删掉该声明里的 `const` 描述符 / `CConst`,或改为声明时一次赋值、"
f"之后只用非 const 的副本/中间量;const 对象在其作用域内禁止赋值、" f"之后只用非 const 的副本/中间量;const 对象在其作用域内禁止赋值、"
f"增量赋值与元素赋值,且不会降级为警告)" f"增量赋值与元素赋值,且不会降级为警告)"
) )
+5 -5
View File
@@ -183,7 +183,7 @@ class ExprGenMixin:
# 见 HandlesExprOps / HandlesAugAssign)。此前这里又用 self._last_var_name # 见 HandlesExprOps / HandlesAugAssign)。此前这里又用 self._last_var_name
# 判一次,而它只是“最近见过的变量名”,可能是**上一条表达式残留的别的变量**: # 判一次,而它只是“最近见过的变量名”,可能是**上一条表达式残留的别的变量**:
# b: int64 = -196608 # b: int64 = -196608
# b >> 1 # 若残留名恰好是某个无符号变量(t.CSizeT 等) ⇒ 误判无符号 ⇒ lshr # b >> 1 # 若残留名恰好是某个无符号变量(CSizeT 等) ⇒ 误判无符号 ⇒ lshr
# 结果:负数右移变大正数(IntWidthTest Test 5/6 的 FAIL 即此)。 # 结果:负数右移变大正数(IntWidthTest Test 5/6 的 FAIL 即此)。
shift_ops: dict[str, Any] = { shift_ops: dict[str, Any] = {
'>>': self.builder.lshr if is_unsigned else self.builder.ashr, '>>': self.builder.lshr if is_unsigned else self.builder.ashr,
@@ -197,7 +197,7 @@ class ExprGenMixin:
} }
# 整数操作数宽度对齐:两个操作数都是整数但位宽不同时, # 整数操作数宽度对齐:两个操作数都是整数但位宽不同时,
# 统一扩展到较大位宽(低位宽操作数 zext/sext)。 # 统一扩展到较大位宽(低位宽操作数 zext/sext)。
# 触发场景:`_g_alloc_count: t.CSizeT = 0`(i64 全局)在函数内 # 触发场景:`_g_alloc_count: CSizeT = 0`(i64 全局)在函数内
# `_g_alloc_count += 1`,RHS 整数字面量是 i32,不扩展会报 # `_g_alloc_count += 1`,RHS 整数字面量是 i32,不扩展会报
# "Operands must be the same type, got (i64, i32)"。 # "Operands must be the same type, got (i64, i32)"。
if (op in ops or op in shift_ops or op in bit_ops or op in cmp_ops): if (op in ops or op in shift_ops or op in bit_ops or op in cmp_ops):
@@ -340,7 +340,7 @@ class ExprGenMixin:
from lib.core.LLVMCG.FuncGen import FailFastError from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError( raise FailFastError(
f"指针隐式转换已禁止({Reason}):函数 {self.func.name} 声明返回 {ret_type}," f"指针隐式转换已禁止({Reason}):函数 {self.func.name} 声明返回 {ret_type},"
f"但 return 的是指针类型 {value.type};如需转换请显式 cast(如 t.CPtr(...))" f"但 return 的是指针类型 {value.type};如需转换请显式 cast(如 CPtr(...))"
f"{self._DescribeValueNode(Node)}" f"{self._DescribeValueNode(Node)}"
) )
value = self.builder.bitcast(value, ret_type, name="ret_cast") value = self.builder.bitcast(value, ret_type, name="ret_cast")
@@ -351,7 +351,7 @@ class ExprGenMixin:
from lib.core.LLVMCG.FuncGen import FailFastError from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError( raise FailFastError(
f"指针隐式转整数已禁止:函数 {self.func.name} 声明返回 {ret_type}," f"指针隐式转整数已禁止:函数 {self.func.name} 声明返回 {ret_type},"
f"但 return 的是指针类型 {value.type};如需转换请显式 cast(如 t.CUInt64T(p) / t.CInt(p))" f"但 return 的是指针类型 {value.type};如需转换请显式 cast(如 CUInt64T(p) / CInt(p))"
f"{self._DescribeValueNode(Node)}" f"{self._DescribeValueNode(Node)}"
) )
elif isinstance(value.type.pointee, ret_type.__class__) and not isinstance(value.type.pointee, ir.IntType): elif isinstance(value.type.pointee, ret_type.__class__) and not isinstance(value.type.pointee, ir.IntType):
@@ -364,7 +364,7 @@ class ExprGenMixin:
from lib.core.LLVMCG.FuncGen import FailFastError from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError( raise FailFastError(
f"指针隐式转整数已禁止:函数 {self.func.name} 声明返回 {ret_type}," f"指针隐式转整数已禁止:函数 {self.func.name} 声明返回 {ret_type},"
f"但 return 的是指针类型 {Loaded.type};如需转换请显式 cast(如 t.CUInt64T(p) / t.CInt(p))" f"但 return 的是指针类型 {Loaded.type};如需转换请显式 cast(如 CUInt64T(p) / CInt(p))"
f"{self._DescribeValueNode(Node)}" f"{self._DescribeValueNode(Node)}"
) )
elif isinstance(ret_type, ir.IntType) and isinstance(value.type, ir.IntType): elif isinstance(ret_type, ir.IntType) and isinstance(value.type, ir.IntType):
+15 -15
View File
@@ -82,7 +82,7 @@ class FuncGenMixin:
IsVtableSlot:该方法是否占用虚表槽(class_methods 即 vtable 槽序唯一真源)。 IsVtableSlot:该方法是否占用虚表槽(class_methods 即 vtable 槽序唯一真源)。
默认 True 与既有语义逐字一致;False 用于方法级 `novirtual def`(⇒ 方法装饰器 默认 True 与既有语义逐字一致;False 用于方法级 `novirtual def`(⇒ 方法装饰器
@t.NoVTable)——此时只保证类的方法容器存在,**不**把它排进槽序,使 TPC 与 @NoVTable)——此时只保证类的方法容器存在,**不**把它排进槽序,使 TPC 与
VPC(ClassGenBase._should_method_be_virtual 排除该项)的虚表布局逐槽相同。 VPC(ClassGenBase._should_method_be_virtual 排除该项)的虚表布局逐槽相同。
""" """
if ClassName not in self.class_methods: if ClassName not in self.class_methods:
@@ -109,7 +109,7 @@ class FuncGenMixin:
- 'ref'(&T):实参已是指针 → 原样传;非指针左值 → 传该左值地址; - 'ref'(&T):实参已是指针 → 原样传;非指针左值 → 传该左值地址;
非指针且非左值(字面量/表达式结果)→ fail-fast(禁止静默降级)。 非指针且非左值(字面量/表达式结果)→ fail-fast(禁止静默降级)。
- 'temp'(&temp T):实参已是指针 → 原样传;否则在 entry 块建同型临时 + store + 传地址。 - 'temp'(&temp T):实参已是指针 → 原样传;否则在 entry 块建同型临时 + store + 传地址。
- 'always'(t.CAutoPtr):无条件取址(保持既有语义)。 - 'always'(CAutoPtr):无条件取址(保持既有语义)。
非指针左值的地址取自实参 load 指令的指针操作数(`load(p)` ⇒ p 即左值地址), 非指针左值的地址取自实参 load 指令的指针操作数(`load(p)` ⇒ p 即左值地址),
因为调用点实参已按 rvalue 求值(标量变量的 load 结果)。 因为调用点实参已按 rvalue 求值(标量变量的 load 结果)。
@@ -149,11 +149,11 @@ class FuncGenMixin:
return new_args return new_args
def _adjust_args(self, args: list[ir.Value], func: ir.Function) -> list[ir.Value]: def _adjust_args(self, args: list[ir.Value], func: ir.Function) -> list[ir.Value]:
# 自动取址(&T=ref / &temp T=temp / t.CAutoPtr=always)的**唯一汇聚点**: # 自动取址(&T=ref / &temp T=temp / CAutoPtr=always)的**唯一汇聚点**:
# 任何类型强转之前先做一次取址适配,于是 direct / vtable 虚分派 / 构造 / # 任何类型强转之前先做一次取址适配,于是 direct / vtable 虚分派 / 构造 /
# 静态方法 / __call__ / 下标赋值 / c.Addr 构造 / 闭包 / 泛型 / 方法兜底等 # 静态方法 / __call__ / 下标赋值 / Addr 构造 / 闭包 / 泛型 / 方法兜底等
# **所有**调用路径都自动获得取址能力,无需在每个调用点手写。 # **所有**调用路径都自动获得取址能力,无需在每个调用点手写。
# 为什么只能在这里做:'always'(t.CAutoPtr)不幂等——它无条件 # 为什么只能在这里做:'always'(CAutoPtr)不幂等——它无条件
# alloca+store+传地址,重复应用会把指针再包一层;原先散落在各调用点的 # alloca+store+传地址,重复应用会把指针再包一层;原先散落在各调用点的
# 显式 Gen._apply_auto_addr(...) 与本汇聚点重复 ⇒ 已全部删除,由本处唯一负责。 # 显式 Gen._apply_auto_addr(...) 与本汇聚点重复 ⇒ 已全部删除,由本处唯一负责。
# 查表键统一为**真实发射出的函数名** func.name(登记侧逐字写入同名键)。 # 查表键统一为**真实发射出的函数名** func.name(登记侧逐字写入同名键)。
@@ -237,7 +237,7 @@ class FuncGenMixin:
raise FailFastError( raise FailFastError(
f"指针隐式转换已禁止({Reason}):调用 {func.name} 第 {i} 个实参" f"指针隐式转换已禁止({Reason}):调用 {func.name} 第 {i} 个实参"
f" {arg.type} 不能隐式转为形参 {param.type};如需转换请显式 cast" f" {arg.type} 不能隐式转为形参 {param.type};如需转换请显式 cast"
f"(如 t.CPtr(...)){self._DescribeValueNode()}") f"(如 CPtr(...)){self._DescribeValueNode()}")
adjusted.append(self.builder.bitcast(arg, param.type, name=f"cast_arg_{i}")) adjusted.append(self.builder.bitcast(arg, param.type, name=f"cast_arg_{i}"))
else: else:
if isinstance(arg.type, ir.PointerType) and isinstance(param.type, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): if isinstance(arg.type, ir.PointerType) and isinstance(param.type, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)):
@@ -345,9 +345,9 @@ class FuncGenMixin:
与 StructGen.py:442-450 的父链传播同源——vtable 沿继承链携带,子类 struct 布局为 与 StructGen.py:442-450 的父链传播同源——vtable 沿继承链携带,子类 struct 布局为
[vtable?] + [基类字段…] + [自身字段…]。只认 class_vtable / [vtable?] + [基类字段…] + [自身字段…]。只认 class_vtable /
_cross_module_vtable_classes(装饰器集合)会漏掉源码未写 @t.CVTable 的跨模块 _cross_module_vtable_classes(装饰器集合)会漏掉源码未写 @CVTable 的跨模块
AST 节点类(ast.Try / ast.Match / ast.ExceptHandler…):它们有方法、继承自 AST 节点类(ast.Try / ast.Match / ast.ExceptHandler…):它们有方法、继承自
@t.CVTable 的 AST,struct 首元素确实是 vtable 指针,但 StructGen.py:415 在 @CVTable 的 AST,struct 首元素确实是 vtable 指针,但 StructGen.py:415 在
"struct body 已从 stub 完整加载"时直接 continue,永不把它们登记进集合 "struct body 已从 stub 完整加载"时直接 continue,永不把它们登记进集合
(实测 ViperC/temp/_shared_sym.json 的 class_vtable/cross_module_vtable 仅有 (实测 ViperC/temp/_shared_sym.json 的 class_vtable/cross_module_vtable 仅有
{AST, MemManager, Module})。此时 base 静默取 0 → 该类字段偏移整体前移 1 {AST, MemManager, Module})。此时 base 静默取 0 → 该类字段偏移整体前移 1
@@ -370,7 +370,7 @@ class FuncGenMixin:
- 统一短名解析(治本修复 2026-08-10):struct/class_members/class_vtable/ - 统一短名解析(治本修复 2026-08-10):struct/class_members/class_vtable/
class_parent 均以短名注册(跨模块加载 HandlesImports L1604),而调用方 class_parent 均以短名注册(跨模块加载 HandlesImports L1604),而调用方
可能传入带 sha1 前缀的全名(如 "f47f88ae6545965a.Import")。 可能传入带 sha1 前缀的全名(如 "f47f88ae6545965a.Import")。
- rawptr[X] / t.CPtr[X] 指针包装归一:rawptr[X] 是内建裸指针类型 - rawptr[X] / CPtr[X] 指针包装归一:rawptr[X] 是内建裸指针类型
(X*),非真实类——接收者注解/类型名为 'rawptr[AST]' 时字段访问 (X*),非真实类——接收者注解/类型名为 'rawptr[AST]' 时字段访问
(child.parent)应作用于内层 struct X,否则查 class_members 全 miss (child.parent)应作用于内层 struct X,否则查 class_members 全 miss
→ fast-fail "属性 'parent' 在类 'rawptr[AST]' 中找不到(struct=opaque)" → fast-fail "属性 'parent' 在类 'rawptr[AST]' 中找不到(struct=opaque)"
@@ -379,7 +379,7 @@ class FuncGenMixin:
if not ClassName: if not ClassName:
return ClassName return ClassName
_Cls: str = self._extract_short_name(ClassName) _Cls: str = self._extract_short_name(ClassName)
if _Cls.startswith('rawptr[') or _Cls.startswith('t.CPtr['): if _Cls.startswith('rawptr[') or _Cls.startswith('CPtr['):
_lb: int = _Cls.find('[') _lb: int = _Cls.find('[')
if _Cls.endswith(']') and _lb > 0: if _Cls.endswith(']') and _lb > 0:
_inner: str = _Cls[_lb + 1:-1].strip() _inner: str = _Cls[_lb + 1:-1].strip()
@@ -411,7 +411,7 @@ class FuncGenMixin:
字段默认值、继承方法 this 调整等)都必须走本方法,禁止各自直查 字段默认值、继承方法 this 调整等)都必须走本方法,禁止各自直查
`class_vtable`/`_cross_module_vtable_classes`——旧实现只认这两个装饰器集合, `class_vtable`/`_cross_module_vtable_classes`——旧实现只认这两个装饰器集合,
跨模块 AST 节点类(ast.Try/ast.Match/ast.ExceptHandler…)源码未写 跨模块 AST 节点类(ast.Try/ast.Match/ast.ExceptHandler…)源码未写
@t.CVTable 且 StructGen 在"struct body 已从 stub 加载"时提前 continue, @CVTable 且 StructGen 在"struct body 已从 stub 加载"时提前 continue,
永不把它们登记进集合,于是 base 只能靠"成员表长度 == struct 元素数 - 1" 永不把它们登记进集合,于是 base 只能靠"成员表长度 == struct 元素数 - 1"
这个长度启发式救回;成员表未展平/尚未加载时启发式失效 ⇒ base 静默取 0 这个长度启发式救回;成员表未展平/尚未加载时启发式失效 ⇒ base 静默取 0
⇒ 该类所有字段偏移整体前移 1(ast.ExceptHandler.children 落到 ⇒ 该类所有字段偏移整体前移 1(ast.ExceptHandler.children 落到
@@ -517,10 +517,10 @@ class FuncGenMixin:
# 【只在长度不齐(_Delta != 0)时校准】_Delta == 0 表示"成员表项数 == body # 【只在长度不齐(_Delta != 0)时校准】_Delta == 0 表示"成员表项数 == body
# 槽数":定义端 body 由成员表生成、跨模块端 body(.stub.ll)与 .vpi 同源 # 槽数":定义端 body 由成员表生成、跨模块端 body(.stub.ll)与 .vpi 同源
# (同一声明顺序),长度相等即**逐位对齐**,base 必为 0。此时再用严格类型 # (同一声明顺序),长度相等即**逐位对齐**,base 必为 0。此时再用严格类型
# 比较挑 b 反而会误判——声明侧的联合类型(如 `list[str] | t.CPtr`)可能被记成 # 比较挑 b 反而会误判——声明侧的联合类型(如 `list[str] | CPtr`)可能被记成
# 折叠后的 i8*,而 body 槽仍是具体指针(`%list[str]*`):b=0 丢掉这些匹配, # 折叠后的 i8*,而 body 槽仍是具体指针(`%list[str]*`):b=0 丢掉这些匹配,
# 某个平移 b 却能靠指针槽互相撞分拿到更高分。 # 某个平移 b 却能靠指针槽互相撞分拿到更高分。
# 现场(2026-09-30):TypeGenMixin(41 成员 / 41 槽 / @t.NoVTable,_Delta=0) # 现场(2026-09-30):TypeGenMixin(41 成员 / 41 槽 / @NoVTable,_Delta=0)
# base 被抬到 2 ⇒ `SubTypeGen.Gen = self`(Gen 声明 Generator*、正确槽 0) # base 被抬到 2 ⇒ `SubTypeGen.Gen = self`(Gen 声明 Generator*、正确槽 0)
# 落到槽 40(TypeSpecArena*)⇒ "指针隐式转换已禁止(非基本类型(结构体/类/联合))"。 # 落到槽 40(TypeSpecArena*)⇒ "指针隐式转换已禁止(非基本类型(结构体/类/联合))"。
# _Delta != 0 的既有现场(ast.Constant 的 `cnst.lineno` 落到 pool 槽等)不受影响, # _Delta != 0 的既有现场(ast.Constant 的 `cnst.lineno` 落到 pool 槽等)不受影响,
@@ -631,7 +631,7 @@ class FuncGenMixin:
# 此处检测冲突,加载正确模块的 class_members 并以 sha1 前缀全名缓存。 # 此处检测冲突,加载正确模块的 class_members 并以 sha1 前缀全名缓存。
_ResolvedClass: str = ClassName if ClassName else '' _ResolvedClass: str = ClassName if ClassName else ''
if ClassName: if ClassName:
# 类键归一(短名 + rawptr[X]/t.CPtr[X] 展开)统一走 _NormalizeMemberClass, # 类键归一(短名 + rawptr[X]/CPtr[X] 展开)统一走 _NormalizeMemberClass,
# 与 _member_base 的 base 判定共用同一归一,禁止各写一份。 # 与 _member_base 的 base 判定共用同一归一,禁止各写一份。
ClassName = self._NormalizeMemberClass(ClassName) ClassName = self._NormalizeMemberClass(ClassName)
_ResolvedClass = ClassName _ResolvedClass = ClassName
@@ -835,7 +835,7 @@ class FuncGenMixin:
if (not _PairOk and isinstance(_mtEff, ir.PointerType) if (not _PairOk and isinstance(_mtEff, ir.PointerType)
and isinstance(_etP, ir.PointerType)): and isinstance(_etP, ir.PointerType)):
# 联合类型字段在成员表里存成通用指针(如 AST.children = # 联合类型字段在成员表里存成通用指针(如 AST.children =
# `list[rawptr[AST]] | t.CPtr` ⇒ i8*),而 body 槽是具体指针 # `list[rawptr[AST]] | CPtr` ⇒ i8*),而 body 槽是具体指针
# (`%"...list[...]"*`):严格串比较会在这条**断链**,其后的 # (`%"...list[...]"*`):严格串比较会在这条**断链**,其后的
# 所有条目都不再消费槽位(cursor 不动)⇒ 目标字段全部退化成 # 所有条目都不再消费槽位(cursor 不动)⇒ 目标字段全部退化成
# "base + 表内下标"(现场:ExceptHandler.name 表内下标 9 ⇒ # "base + 表内下标"(现场:ExceptHandler.name 表内下标 9 ⇒
+15 -17
View File
@@ -182,7 +182,7 @@ class MemoryOpsMixin:
@staticmethod @staticmethod
def _IsGenericPtrType(typ: Any) -> bool: def _IsGenericPtrType(typ: Any) -> bool:
"""通用指针(t.CPtr / void*):指针链末端为 i8(i8* / i8** / ... 均算)。""" """通用指针(CPtr / void*):指针链末端为 i8(i8* / i8** / ... 均算)。"""
if not isinstance(typ, ir.PointerType): if not isinstance(typ, ir.PointerType):
return False return False
p: Any = typ.pointee p: Any = typ.pointee
@@ -274,18 +274,18 @@ class MemoryOpsMixin:
"""值节点是否为「显式指针 cast」调用(用户规则:显式转换一律放行)。 """值节点是否为「显式指针 cast」调用(用户规则:显式转换一律放行)。
形式(TPC 解析产物的共同点 = ast.Call 且 func 是**指针类型表达式**): 形式(TPC 解析产物的共同点 = ast.Call 且 func 是**指针类型表达式**):
- `t.CPtr(x)` / 别名 `CPtr(x)` / `c.CPtr(x)` - `CPtr(x)`
- `rawptr[T](x)` / `t.CPtr[T](x)` / 裸名 `CPtr[T](x)` - `rawptr[T](x)` / `CPtr[T](x)` / 裸名 `CPtr[T](x)`
- `(T*)x` / `(T*)(x)` / `T*(x)`(含 `**` 两层;ExprParser 把三种写法统一 - `(T*)x` / `(T*)(x)` / `T*(x)`(含 `**` 两层;ExprParser 把三种写法统一
产成 Call(func = `T | t.CPtr`)) 产成 Call(func = `T | CPtr`))
- 裸 `rawptr(x)`(≡ t.CPtr) - 裸 `rawptr(x)`(≡ CPtr)
非 cast 调用(构造函数 / 普通函数,如 `MemBuddy(x)`、`list[X](...)`)不命中 非 cast 调用(构造函数 / 普通函数,如 `MemBuddy(x)`、`list[X](...)`)不命中
⇒ 仍按隐式转换规则判定。只判 func 节点形状,不做类型解析(不与 Gen 耦合)。 ⇒ 仍按隐式转换规则判定。只判 func 节点形状,不做类型解析(不与 Gen 耦合)。
必要性:`includes/_list.vp:60` 的 `elem_ptr: T | t.CPtr = t.CPtr(地址)` 在 必要性:`includes/_list.vp:60` 的 `elem_ptr: T | CPtr = CPtr(地址)` 在
`list[X*]` 特化下 T | t.CPtr = `X**`(T 本身是指针),而 `t.CPtr(...)` 的值是 `list[X*]` 特化下 T | CPtr = `X**`(T 本身是指针),而 `CPtr(...)` 的值是
`i8*`——层数不同被判"隐式转换已禁止",与报错自己给的"如需转换请显式 cast `i8*`——层数不同被判"隐式转换已禁止",与报错自己给的"如需转换请显式 cast
(如 t.CPtr(...))"建议自相矛盾。显式 cast 一律放行后按 bitcast 重解释。 (如 CPtr(...))"建议自相矛盾。显式 cast 一律放行后按 bitcast 重解释。
""" """
if not isinstance(Node, ast.Call): if not isinstance(Node, ast.Call):
return False return False
@@ -294,8 +294,6 @@ class MemoryOpsMixin:
AnnotationContainsName) AnnotationContainsName)
if IsCPtrNode(Func) or IsPtrSubscriptNode(Func): if IsCPtrNode(Func) or IsPtrSubscriptNode(Func):
return True return True
if isinstance(Func, ast.Attribute) and Func.attr == 'CPtr':
return True
if isinstance(Func, ast.Name) and Func.id in ('CPtr', 'rawptr'): if isinstance(Func, ast.Name) and Func.id in ('CPtr', 'rawptr'):
return True return True
if isinstance(Func, ast.BinOp) and isinstance(Func.op, ast.BitOr): if isinstance(Func, ast.BinOp) and isinstance(Func.op, ast.BitOr):
@@ -307,7 +305,7 @@ class MemoryOpsMixin:
"""隐式转换判据:返回 (Allowed, Reason)。 """隐式转换判据:返回 (Allowed, Reason)。
规则(用户决定,与 ViperC 同口径): 规则(用户决定,与 ViperC 同口径):
① 通用指针(t.CPtr/i8*)为通配:与任何 T* **双向**互转放行(须同级)。 ① 通用指针(CPtr/i8*)为通配:与任何 T* **双向**互转放行(须同级)。
② T* → U*(皆非通用):允许 ⇔ 被指类型 T → U 无损;非基本类型 ② T* → U*(皆非通用):允许 ⇔ 被指类型 T → U 无损;非基本类型
(结构体/类/联合)一律不允许 ⇒ Foo*→Bar* 禁止;**例外**有二: (结构体/类/联合)一律不允许 ⇒ Foo*→Bar* 禁止;**例外**有二:
继承上转 Derived* → Base*(目标被指类型是源被指类型的基类,含多级) 继承上转 Derived* → Base*(目标被指类型是源被指类型的基类,含多级)
@@ -319,7 +317,7 @@ class MemoryOpsMixin:
由 _CtorCallStructType 单独放行(本判据只给出「禁」的结论)。 由 _CtorCallStructType 单独放行(本判据只给出「禁」的结论)。
④ 完全相同类型不算转换 ⇒ 放行。 ④ 完全相同类型不算转换 ⇒ 放行。
⑤ **显式 cast 一律放行**(用户规则「显式转换都可以」):值侧节点本身是写明的 ⑤ **显式 cast 一律放行**(用户规则「显式转换都可以」):值侧节点本身是写明的
指针转换调用(t.CPtr(x) / rawptr[T](x) / (T*)x ...,见 指针转换调用(CPtr(x) / rawptr[T](x) / (T*)x ...,见
_IsExplicitPtrCastNode)⇒ 目标类型即程序员指定的转换目标,调用方按 _IsExplicitPtrCastNode)⇒ 目标类型即程序员指定的转换目标,调用方按
bitcast 重解释,不做层数/被指类型判定。 bitcast 重解释,不做层数/被指类型判定。
Reason 供报文说明「哪一级不允许 + 原因(非基本类型/有损/层数不同)」。 Reason 供报文说明「哪一级不允许 + 原因(非基本类型/有损/层数不同)」。
@@ -667,7 +665,7 @@ class MemoryOpsMixin:
from lib.core.LLVMCG.FuncGen import FailFastError from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError( raise FailFastError(
f"隐式窄化禁止:{val.type.width} 位整数不能隐式赋给 {target_type.width} 位类型" f"隐式窄化禁止:{val.type.width} 位整数不能隐式赋给 {target_type.width} 位类型"
f"(会丢高位);请显式转换(如 int32(x) / t.CInt32T(x))或把目标类型加宽" f"(会丢高位);请显式转换(如 int32(x) / CInt32T(x))或把目标类型加宽"
f"{self._DescribeValueNode(Node)}" f"{self._DescribeValueNode(Node)}"
) )
elif val.type.width == 1: elif val.type.width == 1:
@@ -686,7 +684,7 @@ class MemoryOpsMixin:
from lib.core.LLVMCG.FuncGen import FailFastError from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError( raise FailFastError(
f"指针隐式转换已禁止({Reason}):不能把指针类型 {val.type} 隐式转为 {target_type};" f"指针隐式转换已禁止({Reason}):不能把指针类型 {val.type} 隐式转为 {target_type};"
f"如需转换请显式 cast(如 t.CPtr(...))" f"如需转换请显式 cast(如 CPtr(...))"
f"{self._DescribeValueNode(Node)}" f"{self._DescribeValueNode(Node)}"
) )
return self.builder.bitcast(val, target_type, name="ptr_bitcast_store") return self.builder.bitcast(val, target_type, name="ptr_bitcast_store")
@@ -702,7 +700,7 @@ class MemoryOpsMixin:
from lib.core.LLVMCG.FuncGen import FailFastError from lib.core.LLVMCG.FuncGen import FailFastError
raise FailFastError( raise FailFastError(
f"指针隐式转整数已禁止:不能把指针类型 {val.type} 赋给整数类型 {target_type};" f"指针隐式转整数已禁止:不能把指针类型 {val.type} 赋给整数类型 {target_type};"
f"如需转换请显式 cast(如 t.CUInt64T(p) / t.CInt(p))" f"如需转换请显式 cast(如 CUInt64T(p) / CInt(p))"
f"{self._DescribeValueNode(Node)}" f"{self._DescribeValueNode(Node)}"
) )
if isinstance(target_type, ir.FloatType) and isinstance(val.type, ir.DoubleType): if isinstance(target_type, ir.FloatType) and isinstance(val.type, ir.DoubleType):
@@ -730,7 +728,7 @@ class MemoryOpsMixin:
if isinstance(val.type, ir.PointerType) and not isinstance(target_type, ir.PointerType): if isinstance(val.type, ir.PointerType) and not isinstance(target_type, ir.PointerType):
# 规则③:非基本类型 T 与 T* 之间的隐式转换(Foo ↔ Foo*)一律禁止—— # 规则③:非基本类型 T 与 T* 之间的隐式转换(Foo ↔ Foo*)一律禁止——
# 指针→非指针值的隐式 load(结构体/数组按值回读)属类型信息缺失, # 指针→非指针值的隐式 load(结构体/数组按值回读)属类型信息缺失,
# 须显式解引用(c.Deref(p) / *p)或显式强转。基本标量目标已在上方 # 须显式解引用(Deref(p) / *p)或显式强转。基本标量目标已在上方
# 「指针隐式转整数」分支 fail-fast,此处只兜非基本类型。 # 「指针隐式转整数」分支 fail-fast,此处只兜非基本类型。
# **唯一例外=「构造物化」**:右值来自该类型的构造调用时放行,如 # **唯一例外=「构造物化」**:右值来自该类型的构造调用时放行,如
# `p: Point = Point()`、`*slot = LLVMType.Struct(...)`(参照 GCC 构造 # `p: Point = Point()`、`*slot = LLVMType.Struct(...)`(参照 GCC 构造
@@ -746,7 +744,7 @@ class MemoryOpsMixin:
raise FailFastError( raise FailFastError(
f"非基本类型的值/指针隐式转换已禁止(构造物化除外,{Reason3}):" f"非基本类型的值/指针隐式转换已禁止(构造物化除外,{Reason3}):"
f"不能把指针类型 {val.type} 隐式转为值类型 {target_type};" f"不能把指针类型 {val.type} 隐式转为值类型 {target_type};"
f"如需解引用请显式 c.Deref(p) / *p,或显式强转" f"如需解引用请显式 Deref(p) / *p,或显式强转"
f"{self._DescribeValueNode(Node)}" f"{self._DescribeValueNode(Node)}"
) )
if val.type.pointee == target_type: if val.type.pointee == target_type:
+3 -3
View File
@@ -4,7 +4,7 @@ import re
import vast as ast import vast as ast
import llvmlite.ir as ir import llvmlite.ir as ir
from llvmlite.ir.values import _Undefined from llvmlite.ir.values import _Undefined
from lib.includes import t as _t from lib.core import TypeSystem as _t
from lib.core.VLogger import get_logger as _vlog from lib.core.VLogger import get_logger as _vlog
# vtable 槽类型 `i8*` 的共享实例:llvmlite 的类型是不可变值语义(`_TypedPointerType` # vtable 槽类型 `i8*` 的共享实例:llvmlite 的类型是不可变值语义(`_TypedPointerType`
@@ -774,7 +774,7 @@ class StructGenMixin:
# 优先从 stub.ll 加载完整定义。set_body 只能对 opaque struct 调用一次, # 优先从 stub.ll 加载完整定义。set_body 只能对 opaque struct 调用一次,
# 若用不完整 class_members 设置 body,后续无法修正,会导致 GEP 越界。 # 若用不完整 class_members 设置 body,后续无法修正,会导致 GEP 越界。
# 但本地定义的类(_classes_in_progress)不从 stub 加载,因为 stub 可能 # 但本地定义的类(_classes_in_progress)不从 stub 加载,因为 stub 可能
# 来自同名导入类,其 vtable 状态与本地定义不同(@t.NoVTable 冲突) # 来自同名导入类,其 vtable 状态与本地定义不同(@NoVTable 冲突)
import_handler: Any = self._import_handler_ref import_handler: Any = self._import_handler_ref
if import_handler is not None and ClassName not in self._classes_in_progress: if import_handler is not None and ClassName not in self._classes_in_progress:
try: try:
@@ -924,7 +924,7 @@ class StructGenMixin:
needs_fix = True needs_fix = True
elif isinstance(gv.initializer, ir.Constant): elif isinstance(gv.initializer, ir.Constant):
if isinstance(gv.initializer.constant, list): if isinstance(gv.initializer.constant, list):
if any(hasattr(c, 'constant') and isinstance(c.constant, _Undefined) for c in gv.initializer.constant): if any(hasattr(c, 'constant') and isinstance(constant, _Undefined) for c in gv.initializer.constant):
needs_fix = True needs_fix = True
if not needs_fix: if not needs_fix:
continue continue
+11 -16
View File
@@ -4,13 +4,11 @@ import vast as ast
import re import re
import logging import logging
import llvmlite.ir as ir import llvmlite.ir as ir
from lib.includes import t as _t from lib.core import TypeSystem as _t
from lib.includes.t import CTypeRegistry from lib.core.TypeSystem import CTypeRegistry
from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo, BuiltinTypeMap from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo, BuiltinTypeMap
from lib.constants.config import mode as _config_mode from lib.constants.config import mode as _config_mode
from lib.core.VLogger import get_logger as _vlog from lib.core.VLogger import get_logger as _vlog
from lib.core.SymbolUtils import IsTModule
# `_type_str_to_llvm_impl` / `_type_str_to_llvm_base` 解析类型字符串用的**预编译**正则 # `_type_str_to_llvm_impl` / `_type_str_to_llvm_base` 解析类型字符串用的**预编译**正则
# (性能:类型字符串解析在热路径上频繁调用,字面量正则预编译避免 re 缓存查找与编译开销)。 # (性能:类型字符串解析在热路径上频繁调用,字面量正则预编译避免 re 缓存查找与编译开销)。
_RE_ARRAY_DIM: re.Pattern[str] = re.compile(r'\[(\d+)\]') _RE_ARRAY_DIM: re.Pattern[str] = re.compile(r'\[(\d+)\]')
@@ -73,7 +71,7 @@ class TypeConvertMixin:
return _enum_result return _enum_result
# REnum 类型:通过 Name 查找或创建结构体(BaseType 可能为 None) # REnum 类型:通过 Name 查找或创建结构体(BaseType 可能为 None)
# 这对 BinOp `LLVMType | t.CPtr` 合并后的 CTypeInfo 至关重要 # 这对 BinOp `LLVMType | CPtr` 合并后的 CTypeInfo 至关重要
if type_info.IsRenum and type_info.Name: if type_info.IsRenum and type_info.Name:
if type_info.Name in self.structs: if type_info.Name in self.structs:
base: ir.Type = self.structs[type_info.Name] base: ir.Type = self.structs[type_info.Name]
@@ -220,9 +218,6 @@ class TypeConvertMixin:
if len(parts) < 2: if len(parts) < 2:
return None return None
module_name: str = parts[0] module_name: str = parts[0]
# 跳过 t/c 等内建模块
if module_name in {'t', 'c'}:
return None
# 从 ModuleSha1Map 查找 SHA1(支持完整路径名和短名) # 从 ModuleSha1Map 查找 SHA1(支持完整路径名和短名)
sha1_map: dict[str, str] = getattr(self, 'ModuleSha1Map', {}) sha1_map: dict[str, str] = getattr(self, 'ModuleSha1Map', {})
source_sha1: str | None = sha1_map.get(module_name) source_sha1: str | None = sha1_map.get(module_name)
@@ -351,8 +346,8 @@ class TypeConvertMixin:
type_str = type_str[:-1].strip() type_str = type_str[:-1].strip()
if ptr_depth > 0: if ptr_depth > 0:
IsPtr = True IsPtr = True
# [builtins 最后匹配] typedef 下标字符串(rawptr[AST] / t.CPtr[AST]): # [builtins 最后匹配] typedef 下标字符串(rawptr[AST] / CPtr[AST]):
# base 为 builtins 指针 typedef(rawptr → t.CPtr)时等价"指向切片类型", # base 为 builtins 指针 typedef(rawptr → CPtr)时等价"指向切片类型",
# 直接转 arg*,防止 stub/ToString 字符串化产物被误建为 'rawptr[AST]' # 直接转 arg*,防止 stub/ToString 字符串化产物被误建为 'rawptr[AST]'
# phantom 结构体(class_members 为空 → 属性访问 fail-fast KeyError)。 # phantom 结构体(class_members 为空 → 属性访问 fail-fast KeyError)。
_sub_m: re.Match | None = _RE_SUBSCRIPT_TYPE.fullmatch(type_str) _sub_m: re.Match | None = _RE_SUBSCRIPT_TYPE.fullmatch(type_str)
@@ -366,7 +361,7 @@ class TypeConvertMixin:
_is_ptr_td = True _is_ptr_td = True
except Exception: except Exception:
_is_ptr_td = False _is_ptr_td = False
if not _is_ptr_td and _sub_base in ('CPtr', 't.CPtr', 'c.CPtr'): if not _is_ptr_td and _sub_base in ('CPtr', 'CPtr', 'CPtr'):
_is_ptr_td = True _is_ptr_td = True
if _is_ptr_td and _sub_arg: if _is_ptr_td and _sub_arg:
_sub_inner: ir.Type = self._type_str_to_llvm(_sub_arg, True) _sub_inner: ir.Type = self._type_str_to_llvm(_sub_arg, True)
@@ -461,7 +456,7 @@ class TypeConvertMixin:
# 文件无需 import 即用):未注册进当前模块 SymbolTable → 常规路径 miss 后 # 文件无需 import 即用):未注册进当前模块 SymbolTable → 常规路径 miss 后
# 落 unknown 被建 %{mod}.int64 opaque → "TypeError: i64 != %int64*" # 落 unknown 被建 %{mod}.int64 opaque → "TypeError: i64 != %int64*"
# (ClassGenGeneric._clone_annotation / ast.Constant.__new__ int_val 根因)。 # (ClassGenGeneric._clone_annotation / ast.Constant.__new__ int_val 根因)。
# 按 builtins.vp 权威定义(int64 → t.CInt64T → i64)展开。 # 按 builtins.vp 权威定义(int64 → CInt64T → i64)展开。
try: try:
from lib.core.TypeAnnotationResolver import TypeAnnotationResolver as _TAR3 from lib.core.TypeAnnotationResolver import TypeAnnotationResolver as _TAR3
_builtin_val_tc: str | None = _TAR3.builtins_typedef_value(type_str) _builtin_val_tc: str | None = _TAR3.builtins_typedef_value(type_str)
@@ -497,7 +492,7 @@ class TypeConvertMixin:
return opaque return opaque
if _Entry and _Entry.IsStruct: if _Entry and _Entry.IsStruct:
# 结构体类型(来自 _InsertClassSymbol):必须返回结构体类型而非 i32, # 结构体类型(来自 _InsertClassSymbol):必须返回结构体类型而非 i32,
# 否则 (ast.Import | t.CPtr) 联合转换会得到 i32* 导致字段访问 GEP 偏移错误 # 否则 (ast.Import | CPtr) 联合转换会得到 i32* 导致字段访问 GEP 偏移错误
if type_str in self.structs: if type_str in self.structs:
if IsPtr: if IsPtr:
return ir.PointerType(self.structs[type_str]) return ir.PointerType(self.structs[type_str])
@@ -653,7 +648,7 @@ class TypeConvertMixin:
# 未知类型:可能是跨模块结构体(如 'Import' 来自 ast 模块)。 # 未知类型:可能是跨模块结构体(如 'Import' 来自 ast 模块)。
# 尝试通过 _get_or_create_struct 创建/查找结构体, # 尝试通过 _get_or_create_struct 创建/查找结构体,
# 该方法内部会检查 typedef/enum 等并返回正确类型。 # 该方法内部会检查 typedef/enum 等并返回正确类型。
# 必须在 fallback 到 i32 之前执行,否则 (ast.Import | t.CPtr) 联合转换 # 必须在 fallback 到 i32 之前执行,否则 (ast.Import | CPtr) 联合转换
# 会得到 i32* 导致字段访问 GEP 偏移错误(AccessViolation 崩溃)。 # 会得到 i32* 导致字段访问 GEP 偏移错误(AccessViolation 崩溃)。
_cand_sha1: str | None = self._get_source_sha1_from_type_str(type_str) _cand_sha1: str | None = self._get_source_sha1_from_type_str(type_str)
candidate: ir.Type = self._get_or_create_struct(type_str, source_sha1=_cand_sha1) candidate: ir.Type = self._get_or_create_struct(type_str, source_sha1=_cand_sha1)
@@ -782,8 +777,8 @@ class TypeConvertMixin:
# 直接调用: rdrand64() # 直接调用: rdrand64()
func_name = func_node.id func_name = func_node.id
elif isinstance(func_node, ast.Attribute): elif isinstance(func_node, ast.Attribute):
# t.CUInt64T(x) 等类型转换调用 # CUInt64T(x) 等类型转换调用
if hasattr(func_node.value, 'id') and IsTModule(func_node.value.id, self.SymbolTable): if hasattr(func_node.value, 'id') :
if self._is_type_unsigned(func_node.attr): if self._is_type_unsigned(func_node.attr):
return True return True
# module.func() 形式的调用 # module.func() 形式的调用
+31 -32
View File
@@ -19,17 +19,17 @@ if TYPE_CHECKING:
from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper, BuiltinTypeMap from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper, BuiltinTypeMap
from lib.core.SymbolUtils import ( from lib.core.SymbolUtils import (
IsTModule, IsListAnnotation, IsCPtrNode, IsCPtrSubscriptNode, IsListAnnotation, IsCPtrNode, IsCPtrSubscriptNode,
IsRawPtrSubscriptNode, EnumIntWidth, IsRawPtrSubscriptNode, EnumIntWidth,
ResolveGenericClassSpecName, GetStructSha1MapFromSymtab, GetTCAliasMapFromSymtab) ResolveGenericClassSpecName, GetStructSha1MapFromSymtab, GetTCAliasMapFromSymtab)
from lib.includes import t as _t from lib.core import TypeSystem as _t
from lib.includes.t import CTypeRegistry from lib.core.TypeSystem import CTypeRegistry
# typedef 值位置的类型限定符标记:它们自身不是类型(名下有 const/volatile 语义, # typedef 值位置的类型限定符标记:它们自身不是类型(名下有 const/volatile 语义,
# 由注解解析器累积),在 typedef 值里只修饰 `|` 另一侧。历史写法 # 由注解解析器累积),在 typedef 值里只修饰 `|` 另一侧。历史写法
# `t.CConst | char | t.CPtr` 恰好被 `char` 一侧掩盖;新语法 `const str` # `CConst | char | CPtr` 恰好被 `char` 一侧掩盖;新语法 `const str`
# (= `t.CConst | str`)暴露了这一点,故显式判为"无类型信息"。 # (= `CConst | str`)暴露了这一点,故显式判为"无类型信息"。
_TYPEDEF_VALUE_QUALIFIERS: frozenset[str] = frozenset({'CConst', 'CVolatile'}) _TYPEDEF_VALUE_QUALIFIERS: frozenset[str] = frozenset({'CConst', 'CVolatile'})
@@ -59,7 +59,7 @@ class LLVMTypeMapper:
def __init__(self, symtab: SymbolTable): def __init__(self, symtab: SymbolTable):
self._symtab = symtab self._symtab = symtab
# 本模块声明的类型名(由 TypeResolver.resolve 注入)。函数签名里的裸类引用 # 本模块声明的类型名(由 TypeResolver.resolve 注入)。函数签名里的裸类引用
# (rawptr[X] / X / t.CPtr[X])依赖它解析成类指针:缺了它,X 落到 # (rawptr[X] / X / CPtr[X])依赖它解析成类指针:缺了它,X 落到
# _resolve_name 的解析失败分支,rawptr[X] 会退化成 i32*(类信息丢失)。 # _resolve_name 的解析失败分支,rawptr[X] 会退化成 i32*(类信息丢失)。
self._ClassNames: set[str] = set() self._ClassNames: set[str] = set()
# 本模块枚举名 → 存储位宽(bit);按登记的宽度物化(默认 32,与改前同值) # 本模块枚举名 → 存储位宽(bit);按登记的宽度物化(默认 32,与改前同值)
@@ -143,7 +143,7 @@ class LLVMTypeMapper:
if returns_node is None: if returns_node is None:
return 'i32' return 'i32'
if isinstance(returns_node, ast.BinOp) and isinstance(returns_node.op, ast.BitOr): if isinstance(returns_node, ast.BinOp) and isinstance(returns_node.op, ast.BitOr):
# 统一走 CPtr 感知的联合解析(int | t.CPtr → i32*、str | t.CPtr → i8**) # 统一走 CPtr 感知的联合解析(int | CPtr → i32*、str | CPtr → i8**)
return self._resolve_bitor(returns_node) return self._resolve_bitor(returns_node)
result: str = self.get_llvm_type_str(returns_node) result: str = self.get_llvm_type_str(returns_node)
return result if result else 'i32' return result if result else 'i32'
@@ -153,7 +153,7 @@ class LLVMTypeMapper:
末尾的「不许静默变 i32」守卫:`Subscript` / 联合(`|`)形态的形参注解若解析结果 末尾的「不许静默变 i32」守卫:`Subscript` / 联合(`|`)形态的形参注解若解析结果
是 `'i32'`,只可能是**解析失败后的兜底** —— 合法的下标注解是容器 / 泛型 / 定长数组 是 `'i32'`,只可能是**解析失败后的兜底** —— 合法的下标注解是容器 / 泛型 / 定长数组
(解析出指针、数组或结构体指针),合法的联合写法是 `T | t.CPtr` 这类指针叠加,都 (解析出指针、数组或结构体指针),合法的联合写法是 `T | CPtr` 这类指针叠加,都
不会是 i32。该串会被 `_InsertFuncSymbol` 原样存进符号表(`FuncPtrParams`),再由 不会是 i32。该串会被 `_InsertFuncSymbol` 原样存进符号表(`FuncPtrParams`),再由
`BuildLLVMFuncTypeFromSig` 物化成形参类型 —— 一旦是 i32,调用点就在 `_adjust_args` `BuildLLVMFuncTypeFromSig` 物化成形参类型 —— 一旦是 i32,调用点就在 `_adjust_args`
报「实参 %X* 不能隐式转为 i32」,把真因(**注解没解析出来**)掩盖成"调用点类型 报「实参 %X* 不能隐式转为 i32」,把真因(**注解没解析出来**)掩盖成"调用点类型
@@ -193,7 +193,7 @@ class LLVMTypeMapper:
# 短别名 / 内建速记(char/int/int64/uchar/str…):与注解位置 # 短别名 / 内建速记(char/int/int64/uchar/str…):与注解位置
# `_resolve_name` 同源。缺此分支时 typedef 值里的裸名解析为空, # `_resolve_name` 同源。缺此分支时 typedef 值里的裸名解析为空,
# 整条 typedef 随之解析失败(现场:w32/win32base.vp 的 # 整条 typedef 随之解析失败(现场:w32/win32base.vp 的
# `LPCSTR: t.CTypedef = t.CConst | char | t.CPtr` ⇒ LPCSTR 不登记, # `LPCSTR: CTypedef = CConst | char | CPtr` ⇒ LPCSTR 不登记,
# 用到处报「裸名 LPCSTR 无法解析为类型」)。 # 用到处报「裸名 LPCSTR 无法解析为类型」)。
_binfo: CTypeInfo | None = self._lookup_builtins_typedef(node.id) _binfo: CTypeInfo | None = self._lookup_builtins_typedef(node.id)
if _binfo is None: if _binfo is None:
@@ -211,14 +211,14 @@ class LLVMTypeMapper:
return _nm + (' *' * (_binfo.PtrCount or 0)) return _nm + (' *' * (_binfo.PtrCount or 0))
return '' return ''
if isinstance(node, ast.Attribute): if isinstance(node, ast.Attribute):
if isinstance(node.value, ast.Name) and IsTModule(node.value.id): if isinstance(node.value, ast.Name) :
# 直接判断属性名是否为 CPtr(消除对 CName=='*' 的依赖) # 直接判断属性名是否为 CPtr(消除对 CName=='*' 的依赖)
if node.attr == 'CPtr': if node.attr == 'CPtr':
return 'ptr' return 'ptr'
if node.attr in _TYPEDEF_VALUE_QUALIFIERS: if node.attr in _TYPEDEF_VALUE_QUALIFIERS:
# 类型限定符标记(const/volatile)本身不是类型:它只修饰 `|` 另一侧。 # 类型限定符标记(const/volatile)本身不是类型:它只修饰 `|` 另一侧。
# 旧写法 `t.CConst | char | t.CPtr` 靠 char 一侧掩盖了这一点;一旦写成 # 旧写法 `CConst | char | CPtr` 靠 char 一侧掩盖了这一点;一旦写成
# `t.CConst | str`(`const str`),把 'CConst' 当基类型会得到 'CConst *', # `CConst | str`(`const str`),把 'CConst' 当基类型会得到 'CConst *',
# 于是别名登记失败、所有使用处报「裸名 … 无法解析为类型」。 # 于是别名登记失败、所有使用处报「裸名 … 无法解析为类型」。
return '' return ''
CName: str | None = CTypeHelper.GetCName(node.attr) CName: str | None = CTypeHelper.GetCName(node.attr)
@@ -356,10 +356,10 @@ class LLVMTypeMapper:
# --- 同名冲突:平坦条目被 define / 枚举成员 / 函数占位时找回类型 ---- # --- 同名冲突:平坦条目被 define / 枚举成员 / 函数占位时找回类型 ----
# 平坦表(无前缀)一个名字只能留一个条目,而不同模块可能用**不同类型种类** # 平坦表(无前缀)一个名字只能留一个条目,而不同模块可能用**不同类型种类**
# 声明同名符号(谁后插入谁占住裸名),两个真实例子: # 声明同名符号(谁后插入谁占住裸名),两个真实例子:
# · stdint.vp:9 `INT: t.CTypedef = t.CInt` vs argparse.vp:33 # · stdint.vp:9 `INT: CTypedef = CInt` vs argparse.vp:33
# `define INT = 1`(sig 里是 `INT: t.CDefine = 1`)—— 注解 `oflag: INT` # `define INT = 1`(sig 里是 `INT: CDefine = 1`)—— 注解 `oflag: INT`
# · llvmlite/__function.vp:77 `class Function` vs ast/tokens.vp:95 # · llvmlite/__function.vp:77 `class Function` vs ast/tokens.vp:95
# 枚举成员 `Function: t.State` —— 注解 `func: rawptr[Function]` # 枚举成员 `Function: State` —— 注解 `func: rawptr[Function]`
# 注解位置只可能是 typedef / 类 / 枚举 ⇒ 平坦条目不是这三种时,跨命名空间 # 注解位置只可能是 typedef / 类 / 枚举 ⇒ 平坦条目不是这三种时,跨命名空间
# (各模块的声明登记在 _namespaces[模块名] 下)再找同名条目。 # (各模块的声明登记在 _namespaces[模块名] 下)再找同名条目。
_cand_sym: CTypeInfo | None _cand_sym: CTypeInfo | None
@@ -390,7 +390,7 @@ class LLVMTypeMapper:
# (`CInt | CExport` → i32)。与 _resolve_attribute 的 marker 分支、 # (`CInt | CExport` → i32)。与 _resolve_attribute 的 marker 分支、
# TypeAnnotationResolver._ResolveNameNode 的 STORAGE_CLASS/TYPE_QUALIFIER # TypeAnnotationResolver._ResolveNameNode 的 STORAGE_CLASS/TYPE_QUALIFIER
# 判定同口径。缺此分支时裸名标记会落到下方 fail-fast —— 而带前缀写作 # 判定同口径。缺此分支时裸名标记会落到下方 fail-fast —— 而带前缀写作
# `t.CExport` 时却能通过(走 Attribute 路径),同一语义两种写法结果不同。 # `CExport` 时却能通过(走 Attribute 路径),同一语义两种写法结果不同。
# 现场:Test/AstTest `def main() -> CInt | CExport`(第 108 行)。 # 现场:Test/AstTest `def main() -> CInt | CExport`(第 108 行)。
_marker_cls: object = getattr(_t, node.id, None) _marker_cls: object = getattr(_t, node.id, None)
if (isinstance(_marker_cls, type) and _marker_cls is not _t.CType if (isinstance(_marker_cls, type) and _marker_cls is not _t.CType
@@ -450,11 +450,11 @@ class LLVMTypeMapper:
if elem_types: if elem_types:
return '{ ' + ', '.join(elem_types) + ' }' return '{ ' + ', '.join(elem_types) + ' }'
if IsCPtrSubscriptNode(node): if IsCPtrSubscriptNode(node):
# t.CPtr[T] → Ptr(resolve(T))(对齐 VPC Subscript 分支 # CPtr[T] → Ptr(resolve(T))(对齐 VPC Subscript 分支
# TypeGenResolve.vp:2769-2790;void 首层归一化为 i8*) # TypeGenResolve.vp:2769-2790;void 首层归一化为 i8*)
return self._add_pointer_level(self.get_llvm_type_str(node.slice)) return self._add_pointer_level(self.get_llvm_type_str(node.slice))
if IsRawPtrSubscriptNode(node): if IsRawPtrSubscriptNode(node):
# rawptr[T](内置裸指针下标)≡ `T | t.CPtr`:与定义端 TypeMerge 的 # rawptr[T](内置裸指针下标)≡ `T | CPtr`:与定义端 TypeMerge 的
# 合并语义同口径(裸类引用自身即指针,吸收这一层;其余逐层外包)。 # 合并语义同口径(裸类引用自身即指针,吸收这一层;其余逐层外包)。
# 此前只认 IsCPtrSubscriptNode → rawptr[T] 落到下方 warn 并退化成 i32。 # 此前只认 IsCPtrSubscriptNode → rawptr[T] 落到下方 warn 并退化成 i32。
return self._rawptr_subscript_type_str(node) return self._rawptr_subscript_type_str(node)
@@ -486,14 +486,14 @@ class LLVMTypeMapper:
def _resolve_bitor(self, node: ast.BinOp) -> str: def _resolve_bitor(self, node: ast.BinOp) -> str:
"""解析 ast.BinOp(BitOr) 节点(CPtr 感知的指针层级叠加)。 """解析 ast.BinOp(BitOr) 节点(CPtr 感知的指针层级叠加)。
T | t.CPtr 一侧为 t.CPtr 标记时,另一侧追加一层 '*': T | CPtr 一侧为 CPtr 标记时,另一侧追加一层 '*':
int | t.CPtr → i32* (原逻辑误降级为 i8*) int | CPtr → i32* (原逻辑误降级为 i8*)
str | t.CPtr → i8** (原逻辑误降级为 i8*) str | CPtr → i8** (原逻辑误降级为 i8*)
(int | t.CPtr) | t.CPtr → i32**(嵌套递归叠加) (int | CPtr) | CPtr → i32**(嵌套递归叠加)
T | t.CPtr[...] 一侧为下标指针类型时,另一侧叠加该下标的指针层级 N T | CPtr[...] 一侧为下标指针类型时,另一侧叠加该下标的指针层级 N
(N = 1 + 切片自身层数,不含 struct 吸收,对齐 VPC BinOp 下标分支 (N = 1 + 切片自身层数,不含 struct 吸收,对齐 VPC BinOp 下标分支
TypeGenResolve.vp:2596-2639): TypeGenResolve.vp:2596-2639):
t.CUInt8T | t.CPtr[t.CPtr] → i8**(原逻辑误降级为首段 i8) CUInt8T | CPtr[CPtr] → i8**(原逻辑误降级为首段 i8)
""" """
left: str = self.get_llvm_type_str(node.left) left: str = self.get_llvm_type_str(node.left)
right: str = self.get_llvm_type_str(node.right) right: str = self.get_llvm_type_str(node.right)
@@ -503,7 +503,7 @@ class LLVMTypeMapper:
return self._add_pointer_level(left) return self._add_pointer_level(left)
if left_is_cptr: if left_is_cptr:
return self._add_pointer_level(right) return self._add_pointer_level(right)
# t.CPtr[...] 下标指针标记:X | t.CPtr[...] → Ptr^N(X) # CPtr[...] 下标指针标记:X | CPtr[...] → Ptr^N(X)
if IsCPtrSubscriptNode(node.right): if IsCPtrSubscriptNode(node.right):
return self._add_pointer_levels(left, self._cptr_subscript_ptr_level(node.right)) return self._add_pointer_levels(left, self._cptr_subscript_ptr_level(node.right))
if IsCPtrSubscriptNode(node.left): if IsCPtrSubscriptNode(node.left):
@@ -531,9 +531,9 @@ class LLVMTypeMapper:
def _rawptr_subscript_type_str(self, node: ast.Subscript) -> str: def _rawptr_subscript_type_str(self, node: ast.Subscript) -> str:
"""rawptr[T](内置裸指针下标)→ LLVM 类型串。 """rawptr[T](内置裸指针下标)→ LLVM 类型串。
与定义端同口径(`T | t.CPtr` 的合并):裸类引用('%struct.X*' / 与定义端同口径(`T | CPtr` 的合并):裸类引用('%struct.X*' /
'%"sha1.X"*' / 泛型特化等以 '%' 开头的结构指针)自身即指针,吸收这一层; '%"sha1.X"*' / 泛型特化等以 '%' 开头的结构指针)自身即指针,吸收这一层;
其余(标量、已是指针的 typedef、联合写法、嵌套 rawptr / t.CPtr 下标) 其余(标量、已是指针的 typedef、联合写法、嵌套 rawptr / CPtr 下标)
逐层外包(void → i8*)。 逐层外包(void → i8*)。
""" """
inner: ast.AST = node.slice inner: ast.AST = node.slice
@@ -553,10 +553,10 @@ class LLVMTypeMapper:
return result return result
def _cptr_subscript_ptr_level(self, node: ast.AST) -> int: def _cptr_subscript_ptr_level(self, node: ast.AST) -> int:
"""t.CPtr[T] 下标指针标记贡献的指针层级 N(= 1 + 切片自身层数)。 """CPtr[T] 下标指针标记贡献的指针层级 N(= 1 + 切片自身层数)。
复用定义侧解析器 TypeAnnotationResolver.from_node(其 _from_node_subscript 复用定义侧解析器 TypeAnnotationResolver.from_node(其 _from_node_subscript
已实现 t.CPtr[T] → Ptr(T) 的层级叠加,见 TypeAnnotationResolver.py:756-783), 已实现 CPtr[T] → Ptr(T) 的层级叠加,见 TypeAnnotationResolver.py:756-783),
与 HandlesTypeMerge._HandleSubscript(HandlesTypeMerge.py:512-531)同口径。 与 HandlesTypeMerge._HandleSubscript(HandlesTypeMerge.py:512-531)同口径。
调用前须经 IsCPtrSubscriptNode 判据过滤,故 PtrCount 至少为 1。 调用前须经 IsCPtrSubscriptNode 判据过滤,故 PtrCount 至少为 1。
""" """
@@ -565,8 +565,7 @@ class LLVMTypeMapper:
def _resolve_call(self, node: ast.Call) -> str: def _resolve_call(self, node: ast.Call) -> str:
"""解析 ast.Call 节点""" """解析 ast.Call 节点"""
if isinstance(node.func, ast.Attribute): if isinstance(node.func, ast.Name):
if hasattr(node.func.value, 'id') and IsTModule(node.func.value.id): return self.get_llvm_type_str(node.func)
return self.get_llvm_type_str(ast.Attribute(value=ast.Name(id='t'), attr=node.func.attr))
self._symtab.diagnostics.warn('', 0, "无法解析 Call 类型,回退到 i32") self._symtab.diagnostics.warn('', 0, "无法解析 Call 类型,回退到 i32")
return 'i32' return 'i32'
+33 -36
View File
@@ -10,9 +10,9 @@ from lib.core.SymbolData import (
FuncSymbolData, DefineSymbolData, AnonymousTypeData FuncSymbolData, DefineSymbolData, AnonymousTypeData
) )
from lib.core.Handles.HandlesBase import CTypeInfo from lib.core.Handles.HandlesBase import CTypeInfo
from lib.core.SymbolUtils import AnnotationContainsTType, CheckAnnotationHasCInline, IsTModule, AnnotationContainsName from lib.core.SymbolUtils import AnnotationContainsMarker, CheckAnnotationHasCInline, AnnotationContainsName
from lib.core.SymbolUtils import EnumClassIntWidth, _ENUM_DEFAULT_INT_WIDTH from lib.core.SymbolUtils import EnumClassIntWidth, _ENUM_DEFAULT_INT_WIDTH
from lib.includes import t from lib.core import TypeSystem
class ASTSymbolExtractor: class ASTSymbolExtractor:
@@ -62,7 +62,7 @@ class ASTSymbolExtractor:
member_type: CTypeInfo | None = CTypeInfo.FromNode(item.annotation, self._symtab) member_type: CTypeInfo | None = CTypeInfo.FromNode(item.annotation, self._symtab)
if member_type is None: if member_type is None:
member_type = CTypeInfo() member_type = CTypeInfo()
member_type.BaseType = t.CInt() member_type.BaseType = TypeSystem.CInt()
is_ptr: bool = member_type.IsPtr is_ptr: bool = member_type.IsPtr
if isinstance(item.annotation, ast.BinOp): if isinstance(item.annotation, ast.BinOp):
if AnnotationContainsName(item.annotation, 'CPtr'): if AnnotationContainsName(item.annotation, 'CPtr'):
@@ -71,24 +71,24 @@ class ASTSymbolExtractor:
elif isinstance(item, ast.ClassDef): elif isinstance(item, ast.ClassDef):
is_anonymous: bool = any( is_anonymous: bool = any(
any(AnnotationContainsTType(base, 'Anonymous') for base in item.bases) any(AnnotationContainsMarker(base, 'Anonymous') for base in item.bases)
) if item.bases else False ) if item.bases else False
if is_anonymous: if is_anonymous:
is_union: bool = any( is_union: bool = any(
any(AnnotationContainsTType(base, 'CUnion') for base in item.bases) any(AnnotationContainsMarker(base, 'CUnion') for base in item.bases)
) )
# 也检查装饰器形式 @t.CUnion # 也检查装饰器形式 @CUnion
if not is_union and hasattr(item, 'decorator_list') and item.decorator_list: if not is_union and hasattr(item, 'decorator_list') and item.decorator_list:
for deco in item.decorator_list: for deco in item.decorator_list:
if isinstance(deco, ast.Attribute) and hasattr(deco.value, 'id') and IsTModule(deco.value.id, self._symtab) and deco.attr == 'CUnion': if isinstance(deco, ast.Attribute) and hasattr(deco.value, 'id') and deco.attr == 'CUnion':
is_union = True is_union = True
break break
elif isinstance(deco, ast.Name): elif isinstance(deco, ast.Name):
cls2: type | None = getattr(t, deco.id, None) cls2: type | None = getattr(TypeSystem, deco.id, None)
if cls2 is None and hasattr(self._symtab, '_t_type_symbols'): if cls2 is None and hasattr(self._symtab, '_builtin_type_symbols'):
cls2 = self._symtab._t_type_symbols.get(deco.id) cls2 = self._symtab._builtin_type_symbols.get(deco.id)
if cls2 is not None and isinstance(cls2, type) and issubclass(cls2, t.CUnion): if cls2 is not None and isinstance(cls2, type) and issubclass(cls2, TypeSystem.CUnion):
is_union = True is_union = True
break break
@@ -129,8 +129,7 @@ class ASTSymbolExtractor:
if hasattr(node, 'decorator_list') and node.decorator_list: if hasattr(node, 'decorator_list') and node.decorator_list:
for decorator in node.decorator_list: for decorator in node.decorator_list:
if isinstance(decorator, ast.Attribute): if isinstance(decorator, ast.Attribute):
if (hasattr(decorator.value, 'id') and if (hasattr(decorator.value, 'id') ):
IsTModule(decorator.value.id, self._symtab)):
if decorator.attr == 'Object': if decorator.attr == 'Object':
is_cpython_object = True is_cpython_object = True
elif decorator.attr == 'CUnion': elif decorator.attr == 'CUnion':
@@ -143,44 +142,42 @@ class ASTSymbolExtractor:
type_kind = 'struct' type_kind = 'struct'
elif isinstance(decorator, ast.Name): elif isinstance(decorator, ast.Name):
# from t import CStruct / CUnion / CEnum / REnum # from t import CStruct / CUnion / CEnum / REnum
cls: type | None = getattr(t, decorator.id, None) cls: type | None = getattr(TypeSystem, decorator.id, None)
if cls is None and hasattr(self._symtab, '_t_type_symbols'): if cls is None and hasattr(self._symtab, '_builtin_type_symbols'):
cls = self._symtab._t_type_symbols.get(decorator.id) cls = self._symtab._builtin_type_symbols.get(decorator.id)
if cls is not None and isinstance(cls, type) and issubclass(cls, t.CType): if cls is not None and isinstance(cls, type) and issubclass(cls, TypeSystem.CType):
if issubclass(cls, t.CUnion): if issubclass(cls, TypeSystem.CUnion):
type_kind = 'union' type_kind = 'union'
elif issubclass(cls, t.REnum): elif issubclass(cls, TypeSystem.REnum):
type_kind = 'renum' type_kind = 'renum'
elif issubclass(cls, t.CEnum): elif issubclass(cls, TypeSystem.CEnum):
type_kind = 'enum' type_kind = 'enum'
elif issubclass(cls, t.CStruct): elif issubclass(cls, TypeSystem.CStruct):
type_kind = 'struct' type_kind = 'struct'
elif decorator.id == 'Object': elif decorator.id == 'Object':
is_cpython_object = True is_cpython_object = True
elif isinstance(decorator, ast.Call): elif isinstance(decorator, ast.Call):
if isinstance(decorator.func, ast.Attribute): if isinstance(decorator.func, ast.Name) and decorator.func.id == 'Attribute':
if hasattr(decorator.func.value, 'id') and decorator.func.value.id == 'c' and decorator.func.attr == 'Attribute': for arg in decorator.args:
for arg in decorator.args: if (isinstance(arg, ast.Attribute) and arg.attr == 'packed'
if isinstance(arg, ast.Attribute): and isinstance(arg.value, ast.Name) and arg.value.id == 'attr'):
if isinstance(arg.value, ast.Attribute): is_packed = True
if hasattr(arg.value.value, 'id') and IsTModule(arg.value.value.id, self._symtab) and arg.value.attr == 'attr' and arg.attr == 'packed':
is_packed = True
# 检查基类 # 检查基类
for base in node.bases: for base in node.bases:
if AnnotationContainsTType(base, 'CUnion'): if AnnotationContainsMarker(base, 'CUnion'):
type_kind = 'union' type_kind = 'union'
break break
elif AnnotationContainsTType(base, 'CEnum'): elif AnnotationContainsMarker(base, 'CEnum'):
type_kind = 'enum' type_kind = 'enum'
break break
elif AnnotationContainsTType(base, 'REnum'): elif AnnotationContainsMarker(base, 'REnum'):
type_kind = 'renum' type_kind = 'renum'
break break
elif AnnotationContainsTType(base, 'CStruct'): elif AnnotationContainsMarker(base, 'CStruct'):
type_kind = 'struct' type_kind = 'struct'
break break
elif AnnotationContainsTType(base, 'Object'): elif AnnotationContainsMarker(base, 'Object'):
is_cpython_object = True is_cpython_object = True
type_kind = 'struct' type_kind = 'struct'
break break
@@ -275,9 +272,9 @@ class ASTSymbolExtractor:
def _extract_ann_assign(self, node: ast.AnnAssign, result: ModuleSymbols) -> None: def _extract_ann_assign(self, node: ast.AnnAssign, result: ModuleSymbols) -> None:
"""从 AnnAssign 节点提取 typedef 或 define 数据""" """从 AnnAssign 节点提取 typedef 或 define 数据"""
var_name: str = node.target.id var_name: str = node.target.id
has_cdefine: bool = AnnotationContainsTType(node.annotation, 'CDefine') if node.annotation else False has_cdefine: bool = AnnotationContainsMarker(node.annotation, 'CDefine') if node.annotation else False
has_postdef: bool = AnnotationContainsTType(node.annotation, 'Postdefinition') if node.annotation else False has_postdef: bool = AnnotationContainsMarker(node.annotation, 'Postdefinition') if node.annotation else False
has_ctypedef: bool = AnnotationContainsTType(node.annotation, 'CTypedef') if node.annotation else False has_ctypedef: bool = AnnotationContainsMarker(node.annotation, 'CTypedef') if node.annotation else False
if has_cdefine: if has_cdefine:
result.defines.append(DefineSymbolData( result.defines.append(DefineSymbolData(
+5 -5
View File
@@ -2,7 +2,7 @@ from __future__ import annotations
from typing import Any, Dict, Optional from typing import Any, Dict, Optional
from lib.core.Handles.HandlesBase import CTypeInfo from lib.core.Handles.HandlesBase import CTypeInfo
from lib.includes import t from lib.core import TypeSystem
class SymbolNode: class SymbolNode:
@@ -168,11 +168,11 @@ class SymbolNode:
if resolved and resolved.BaseType: if resolved and resolved.BaseType:
CTypeMember = resolved CTypeMember = resolved
else: else:
CTypeMember.BaseType = t.CInt() CTypeMember.BaseType = TypeSystem.CInt()
except Exception: except Exception:
CTypeMember.BaseType = t.CInt() CTypeMember.BaseType = TypeSystem.CInt()
else: else:
CTypeMember.BaseType = t.CInt() CTypeMember.BaseType = TypeSystem.CInt()
if IsPtr and not CTypeMember.IsPtr: if IsPtr and not CTypeMember.IsPtr:
CTypeMember.PtrCount = max(CTypeMember.PtrCount, 1) CTypeMember.PtrCount = max(CTypeMember.PtrCount, 1)
node.attributes.Members[MemberName] = CTypeMember node.attributes.Members[MemberName] = CTypeMember
@@ -206,7 +206,7 @@ class SymbolNode:
@classmethod @classmethod
def CreateAnonymous(cls, name: str, IsUnion: bool, members: dict, lineno: int = 0, file: str = '') -> SymbolNode: def CreateAnonymous(cls, name: str, IsUnion: bool, members: dict, lineno: int = 0, file: str = '') -> SymbolNode:
"""创建匿名类型节点(工厂函数)""" """创建匿名类型节点(工厂函数)"""
NodeType: type = t.CUnion if IsUnion else t.CStruct NodeType: type = TypeSystem.CUnion if IsUnion else TypeSystem.CStruct
node: SymbolNode = cls(name=name, NodeType=NodeType, lineno=lineno, file=file) node: SymbolNode = cls(name=name, NodeType=NodeType, lineno=lineno, file=file)
node.attributes = CTypeInfo() node.attributes = CTypeInfo()
node.attributes.Name = name node.attributes.Name = name
+30 -30
View File
@@ -7,7 +7,7 @@ import vast as ast
import traceback import traceback
from lib.core.Handles.HandlesBase import CTypeInfo from lib.core.Handles.HandlesBase import CTypeInfo
from lib.includes import t from lib.core import TypeSystem
from lib.core.VLogger import get_logger as _vlog from lib.core.VLogger import get_logger as _vlog
from lib.core.DiagnosticCollector import DiagnosticCollector from lib.core.DiagnosticCollector import DiagnosticCollector
from lib.core.LLVMTypeMapper import LLVMTypeMapper, TypeNameUnresolvedError from lib.core.LLVMTypeMapper import LLVMTypeMapper, TypeNameUnresolvedError
@@ -27,7 +27,7 @@ class SymbolTable:
self.translator: Translator = translator self.translator: Translator = translator
self._symbols: dict[str, CTypeInfo] = {} self._symbols: dict[str, CTypeInfo] = {}
self._namespaces: dict[str, dict[str, CTypeInfo]] = {} # 模块名 -> 符号字典 self._namespaces: dict[str, dict[str, CTypeInfo]] = {} # 模块名 -> 符号字典
self._t_type_symbols: dict[str, type] = {} # 别名 -> t.CType 子类 (from t import CEnum as en) self._builtin_type_symbols: dict[str, type] = {} # 别名 -> CType 子类 (from t import CEnum as en)
self.diagnostics: DiagnosticCollector = DiagnosticCollector() self.diagnostics: DiagnosticCollector = DiagnosticCollector()
self._type_mapper: LLVMTypeMapper = LLVMTypeMapper(self) self._type_mapper: LLVMTypeMapper = LLVMTypeMapper(self)
self.import_aliases: dict[str, str] = {} # 别名 -> 模块路径 self.import_aliases: dict[str, str] = {} # 别名 -> 模块路径
@@ -50,7 +50,7 @@ class SymbolTable:
def clear(self) -> None: def clear(self) -> None:
self._symbols.clear() self._symbols.clear()
self._namespaces.clear() self._namespaces.clear()
self._t_type_symbols.clear() self._builtin_type_symbols.clear()
self.import_aliases.clear() self.import_aliases.clear()
def get(self, name: str, default: CTypeInfo | None = None) -> CTypeInfo | None: def get(self, name: str, default: CTypeInfo | None = None) -> CTypeInfo | None:
@@ -110,7 +110,7 @@ class SymbolTable:
解析顺序: 解析顺序:
1. 直接匹配 _symbols 1. 直接匹配 _symbols
2. 如果包含 '.',解析第一个段为别名后查找剩余路径 2. 如果包含 '.',解析第一个段为别名后查找剩余路径
3. 查 _t_type_symbols(t/c 类型别名,返回模拟 CTypeInfo) 3. 查 _builtin_type_symbols(t/c 类型别名,返回模拟 CTypeInfo)
""" """
if name in self._symbols: if name in self._symbols:
return self._symbols[name] return self._symbols[name]
@@ -136,18 +136,18 @@ class SymbolTable:
return None return None
def _lookup_t_type(self, name: str) -> CTypeInfo | None: def _lookup_t_type(self, name: str) -> CTypeInfo | None:
"""在 _t_type_symbols 中查找 t/c 类型别名,返回模拟 CTypeInfo""" """在 _builtin_type_symbols 中查找 t/c 类型别名,返回模拟 CTypeInfo"""
cls: type | None = self._t_type_symbols.get(name) cls: type | None = self._builtin_type_symbols.get(name)
if cls is None: if cls is None:
return None return None
info: CTypeInfo = CTypeInfo() info: CTypeInfo = CTypeInfo()
info.Name = name info.Name = name
info.BaseType = cls() info.BaseType = cls()
if issubclass(cls, (t.CEnum, t.REnum)): if issubclass(cls, (TypeSystem.CEnum, TypeSystem.REnum)):
info.IsEnum = True info.IsEnum = True
elif issubclass(cls, t.CUnion): elif issubclass(cls, TypeSystem.CUnion):
info.IsUnion = True info.IsUnion = True
elif issubclass(cls, t.CStruct): elif issubclass(cls, TypeSystem.CStruct):
info.IsStruct = True info.IsStruct = True
return info return info
@@ -227,20 +227,20 @@ class SymbolTable:
} }
if self.import_aliases: if self.import_aliases:
result['__import_aliases__'] = dict(self.import_aliases) result['__import_aliases__'] = dict(self.import_aliases)
if self._t_type_symbols: if self._builtin_type_symbols:
result['__t_type_symbols__'] = { result['__builtin_type_symbols__'] = {
name: cls.__name__ for name, cls in self._t_type_symbols.items() name: cls.__name__ for name, cls in self._builtin_type_symbols.items()
} }
return result return result
@staticmethod @staticmethod
def _SerializeBaseType(base_type: t.CType | tuple | list | str | None) -> dict | str: def _SerializeBaseType(base_type: TypeSystem.CType | tuple | list | str | None) -> dict | str:
"""将 BaseType 序列化为可重建的格式""" """将 BaseType 序列化为可重建的格式"""
if isinstance(base_type, t.CType): if isinstance(base_type, TypeSystem.CType):
return {'class': type(base_type).__name__} return {'class': type(base_type).__name__}
if isinstance(base_type, (tuple, list)): if isinstance(base_type, (tuple, list)):
return {'classes': [type(b).__name__ for b in base_type if isinstance(b, t.CType)]} return {'classes': [type(b).__name__ for b in base_type if isinstance(b, TypeSystem.CType)]}
return str(base_type) return str(base_type)
@staticmethod @staticmethod
@@ -248,20 +248,20 @@ class SymbolTable:
"""从序列化格式恢复 BaseType""" """从序列化格式恢复 BaseType"""
if isinstance(data, dict): if isinstance(data, dict):
if 'class' in data: if 'class' in data:
cls: type | None = getattr(t, data['class'], None) cls: type | None = getattr(TypeSystem, data['class'], None)
if cls and isinstance(cls, type) and issubclass(cls, t.CType): if cls and isinstance(cls, type) and issubclass(cls, TypeSystem.CType):
return cls() return cls()
elif 'classes' in data: elif 'classes' in data:
types: list[t.CType] = [] types: list[TypeSystem.CType] = []
for cname in data['classes']: for cname in data['classes']:
cls: type | None = getattr(t, cname, None) cls: type | None = getattr(TypeSystem, cname, None)
if cls and isinstance(cls, type) and issubclass(cls, t.CType): if cls and isinstance(cls, type) and issubclass(cls, TypeSystem.CType):
types.append(cls()) types.append(cls())
if types: if types:
return tuple(types) return tuple(types)
elif isinstance(data, str): elif isinstance(data, str):
cls: type | None = getattr(t, data, None) cls: type | None = getattr(TypeSystem, data, None)
if cls and isinstance(cls, type) and issubclass(cls, t.CType): if cls and isinstance(cls, type) and issubclass(cls, TypeSystem.CType):
return cls() return cls()
return None return None
@@ -270,9 +270,9 @@ class SymbolTable:
self._symbols.clear() self._symbols.clear()
self._namespaces.clear() self._namespaces.clear()
self.import_aliases.clear() self.import_aliases.clear()
self._t_type_symbols.clear() self._builtin_type_symbols.clear()
_SPECIAL_KEYS: frozenset[str] = frozenset({'__namespaces__', '__import_aliases__', '__t_type_symbols__'}) _SPECIAL_KEYS: frozenset[str] = frozenset({'__namespaces__', '__import_aliases__', '__builtin_type_symbols__'})
for name, attrs in symbols.items(): for name, attrs in symbols.items():
if name in _SPECIAL_KEYS: if name in _SPECIAL_KEYS:
@@ -296,12 +296,12 @@ class SymbolTable:
self.import_aliases.update(aliases_data) self.import_aliases.update(aliases_data)
# 恢复 t 类型别名 # 恢复 t 类型别名
t_type_data: dict[str, str] | None = symbols.get('__t_type_symbols__') t_type_data: dict[str, str] | None = symbols.get('__builtin_type_symbols__')
if t_type_data: if t_type_data:
for name, cls_name in t_type_data.items(): for name, cls_name in t_type_data.items():
cls: type | None = getattr(t, cls_name, None) cls: type | None = getattr(TypeSystem, cls_name, None)
if cls and isinstance(cls, type) and issubclass(cls, t.CType): if cls and isinstance(cls, type) and issubclass(cls, TypeSystem.CType):
self._t_type_symbols[name] = cls self._builtin_type_symbols[name] = cls
def _CTypeInfoFromDict(self, name: str, attrs: dict[str, Any]) -> CTypeInfo: def _CTypeInfoFromDict(self, name: str, attrs: dict[str, Any]) -> CTypeInfo:
"""从旧 dict 格式创建 CTypeInfo(兼容旧代码)""" """从旧 dict 格式创建 CTypeInfo(兼容旧代码)"""
@@ -378,7 +378,7 @@ class SymbolTable:
# 两阶段加载(顺序无关):声明阶段 / 签名阶段 # 两阶段加载(顺序无关):声明阶段 / 签名阶段
# #
# 为什么要拆:签名解析(Pass 2 的函数部分)会通过符号表查找**其它模块**的 # 为什么要拆:签名解析(Pass 2 的函数部分)会通过符号表查找**其它模块**的
# 类型名(裸名 typedef,如 posix 的 `INT | t.State`;跨模块类,如 # 类型名(裸名 typedef,如 posix 的 `INT | State`;跨模块类,如
# `rawptr[Constant]`)。单模块逐个「提取→解析→插入」时,这些名字要求依赖模块 # `rawptr[Constant]`)。单模块逐个「提取→解析→插入」时,这些名字要求依赖模块
# **恰好先被加载**(Phase2Translator 按 os.listdir 字典序加载 ⇒ posix 排在 # **恰好先被加载**(Phase2Translator 按 os.listdir 字典序加载 ⇒ posix 排在
# stdint 之前,`INT` 找不到)。旧口径把它静默降级成 i32,所以顺序依赖不可见; # stdint 之前,`INT` 找不到)。旧口径把它静默降级成 i32,所以顺序依赖不可见;
@@ -578,7 +578,7 @@ class SymbolTable:
info.IsVariadic = IsVariadic info.IsVariadic = IsVariadic
info.IsInline = IsInline info.IsInline = IsInline
if IsInline: if IsInline:
info.Storage = t.CInline() info.Storage = TypeSystem.CInline()
info.Lineno = lineno info.Lineno = lineno
info.file = FilePath info.file = FilePath
self._symbols[FullName] = info self._symbols[FullName] = info
+16 -17
View File
@@ -10,8 +10,7 @@ from lib.core.SymbolData import (
) )
from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper, BuiltinTypeMap from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper, BuiltinTypeMap
from lib.core.LLVMTypeMapper import LLVMTypeMapper, TypeNameUnresolvedError from lib.core.LLVMTypeMapper import LLVMTypeMapper, TypeNameUnresolvedError
from lib.core.SymbolUtils import IsTModule from lib.core import TypeSystem
from lib.includes import t
class TypeResolver: class TypeResolver:
@@ -109,12 +108,12 @@ class TypeResolver:
original_type_kind: str = 'struct' original_type_kind: str = 'struct'
if original_class in self._symtab: if original_class in self._symtab:
orig_type_info: CTypeInfo = self._symtab[original_class] orig_type_info: CTypeInfo = self._symtab[original_class]
if orig_type_info.type_cls in (t.CStruct, t.CEnum, t.CUnion): if orig_type_info.type_cls in (TypeSystem.CStruct, TypeSystem.CEnum, TypeSystem.CUnion):
if orig_type_info.type_cls is t.CStruct: if orig_type_info.type_cls is TypeSystem.CStruct:
original_type_kind = 'struct' original_type_kind = 'struct'
elif orig_type_info.type_cls is t.CEnum: elif orig_type_info.type_cls is TypeSystem.CEnum:
original_type_kind = 'enum' original_type_kind = 'enum'
elif orig_type_info.type_cls is t.CUnion: elif orig_type_info.type_cls is TypeSystem.CUnion:
original_type_kind = 'union' original_type_kind = 'union'
td.original_type_kind = original_type_kind td.original_type_kind = original_type_kind
td.original_class = original_class td.original_class = original_class
@@ -149,7 +148,7 @@ class TypeResolver:
def _resolve_typedef_from_value(self, td: TypedefSymbolData): def _resolve_typedef_from_value(self, td: TypedefSymbolData):
"""从值表达式解析 typedef 类型 """从值表达式解析 typedef 类型
BinOp(如 UINT | t.CPtr)优先于 _find_base_type 处理, BinOp(如 UINT | CPtr)优先于 _find_base_type 处理,
因为 _find_base_type 是静态方法无法解析 Name 引用(如 UINT)。 因为 _find_base_type 是静态方法无法解析 Name 引用(如 UINT)。
""" """
if not td.value: if not td.value:
@@ -182,13 +181,13 @@ class TypeResolver:
value_base_type: str | None = self._find_base_type(td.value) value_base_type: str | None = self._find_base_type(td.value)
_PTR_MODIFIERS: frozenset[str] = frozenset({'CPtr', 'CArrayPtr', 'CConst', 'CVolatile', 'CInline', 'CStatic', 'CExtern'}) _PTR_MODIFIERS: frozenset[str] = frozenset({'CPtr', 'CArrayPtr', 'CConst', 'CVolatile', 'CInline', 'CStatic', 'CExtern'})
# 裸 t.CPtr(无 `|` 联合、无 `[T]` 下标):_find_base_type 把 node.attr == 'CPtr' # 裸 CPtr(无 `|` 联合、无 `[T]` 下标):_find_base_type 把 node.attr == 'CPtr'
# 归一化为指针标记 'ptr'(拼写与 _PTR_MODIFIERS 的 'CPtr' 不一致 ⇒ 下方守卫命不中), # 归一化为指针标记 'ptr'(拼写与 _PTR_MODIFIERS 的 'CPtr' 不一致 ⇒ 下方守卫命不中),
# 若让 'ptr' 落进 original_class,经 _InsertTypedefSymbol 存入 symtab.OriginalType 后 # 若让 'ptr' 落进 original_class,经 _InsertTypedefSymbol 存入 symtab.OriginalType 后
# 会被 CTypeInfo.FromTypeName 当成 CStruct('ptr'),最终 _get_or_create_struct # 会被 CTypeInfo.FromTypeName 当成 CStruct('ptr'),最终 _get_or_create_struct
# 建出 %"<模块sha>.ptr" 不透明结构体(VLogger._console_handle: win32base.HANDLE # 建出 %"<模块sha>.ptr" 不透明结构体(VLogger._console_handle: win32base.HANDLE
# 报 "cannot store i8* to %"...ptr"*" 的根因)。按指针语义展开为 'void *', # 报 "cannot store i8* to %"...ptr"*" 的根因)。按指针语义展开为 'void *',
# 与改前 `t.CPtr` 联合分支等价(_InsertTypedefSymbol 同样把 # 与改前 `CPtr` 联合分支等价(_InsertTypedefSymbol 同样把
# 'CVoid *' 归一化为 'void *')。 # 'CVoid *' 归一化为 'void *')。
if value_base_type == 'ptr': if value_base_type == 'ptr':
td.original_type_kind = 'typedef' td.original_type_kind = 'typedef'
@@ -223,12 +222,12 @@ class TypeResolver:
# 最后兜底:builtins.vp 的短别名(int8/uint64/uchar/ushort/sizet…) # 最后兜底:builtins.vp 的短别名(int8/uint64/uchar/ushort/sizet…)
# 与内建速记(int/char/float/bool/str…)。 # 与内建速记(int/char/float/bool/str…)。
# `_find_base_type` 只认 `t.X`(ast.Attribute)形态,裸名根本走不到上面 # `_find_base_type` 只认 `X`(ast.Attribute)形态,裸名根本走不到上面
# 的 GetCName 分支 ⇒ `X: t.CTypedef = int64` 这类声明此前整条解析失败, # 的 GetCName 分支 ⇒ `X: CTypedef = int64` 这类声明此前整条解析失败,
# X 不登记进符号表,用到处报「裸名 X 无法解析为类型」 # X 不登记进符号表,用到处报「裸名 X 无法解析为类型」
# (现场:includes/posix.vp 的 off_t、stdint.vp 的 INT)。 # (现场:includes/posix.vp 的 off_t、stdint.vp 的 INT)。
# 此分支与注解位置 LLVMTypeMapper._resolve_name 的来源一致,产物形态也 # 此分支与注解位置 LLVMTypeMapper._resolve_name 的来源一致,产物形态也
# 与 `t.CInt64T` 分支逐字相同(original_class 存 t.C 类名)。 # 与 `CInt64T` 分支逐字相同(original_class 存 t.C 类名)。
builtin_info: CTypeInfo | None = self._type_mapper._lookup_builtins_typedef(ref_name) builtin_info: CTypeInfo | None = self._type_mapper._lookup_builtins_typedef(ref_name)
if builtin_info is None: if builtin_info is None:
_entry: tuple[type, int] | None = BuiltinTypeMap.Get(ref_name) _entry: tuple[type, int] | None = BuiltinTypeMap.Get(ref_name)
@@ -239,7 +238,7 @@ class TypeResolver:
if builtin_info is not None and builtin_info.BaseType: if builtin_info is not None and builtin_info.BaseType:
_bt: object = builtin_info.BaseType _bt: object = builtin_info.BaseType
# BaseType 可能是 t.C 类名(str)、CType 子类,或 CType **实例** # BaseType 可能是 t.C 类名(str)、CType 子类,或 CType **实例**
# (_lookup_builtins_typedef 走的是 t.CInt64T() 实例); # (_lookup_builtins_typedef 走的是 CInt64T() 实例);
# CTypeHelper.GetCName 只认前两种 ⇒ 实例取 type(x).__name__。 # CTypeHelper.GetCName 只认前两种 ⇒ 实例取 type(x).__name__。
if isinstance(_bt, str): if isinstance(_bt, str):
_cname: str = _bt _cname: str = _bt
@@ -258,7 +257,7 @@ class TypeResolver:
def _resolve_type_expr(self, node: ast.AST) -> str: def _resolve_type_expr(self, node: ast.AST) -> str:
"""解析类型表达式为 C 类型名字符串,优先查本模块已解析的 typedef """解析类型表达式为 C 类型名字符串,优先查本模块已解析的 typedef
解决同模块 typedef 间引用(如 UINTPTR = UINT | t.CPtr 中的 UINT) 解决同模块 typedef 间引用(如 UINTPTR = UINT | CPtr 中的 UINT)
在 TypeResolver 阶段尚未插入 symtab 的问题。 在 TypeResolver 阶段尚未插入 symtab 的问题。
""" """
if isinstance(node, ast.Name): if isinstance(node, ast.Name):
@@ -342,12 +341,12 @@ class TypeResolver:
def _find_base_type(node: ast.AST | None) -> str | None: def _find_base_type(node: ast.AST | None) -> str | None:
"""从注解 AST 节点中查找基础类型名称""" """从注解 AST 节点中查找基础类型名称"""
if isinstance(node, ast.Attribute): if isinstance(node, ast.Attribute):
if hasattr(node.value, 'id') and IsTModule(node.value.id): if hasattr(node.value, 'id') :
if node.attr == 'CPtr': if node.attr == 'CPtr':
return 'ptr' return 'ptr'
return node.attr return node.attr
elif isinstance(node, ast.Subscript): elif isinstance(node, ast.Subscript):
if isinstance(node.value, ast.Attribute) and isinstance(node.value.value, ast.Name) and IsTModule(node.value.value.id) and node.value.attr == 'Callable': if isinstance(node.value, ast.Attribute) and isinstance(node.value.value, ast.Name) and node.value.attr == 'Callable':
return 'Callable' return 'Callable'
elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
left_result: str | None = TypeResolver._find_base_type(node.left) left_result: str | None = TypeResolver._find_base_type(node.left)
@@ -378,7 +377,7 @@ class TypeResolver:
"""从注解 AST 节点中查找 Postdefinition 参数""" """从注解 AST 节点中查找 Postdefinition 参数"""
if isinstance(node, ast.Call): if isinstance(node, ast.Call):
if isinstance(node.func, ast.Attribute): if isinstance(node.func, ast.Attribute):
if hasattr(node.func.value, 'id') and IsTModule(node.func.value.id) and node.func.attr == 'Postdefinition': if hasattr(node.func.value, 'id') and node.func.attr == 'Postdefinition':
if node.args and isinstance(node.args[0], ast.Name): if node.args and isinstance(node.args[0], ast.Name):
return node.args[0].id return node.args[0].id
elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
+265 -323
View File
File diff suppressed because it is too large. Load diff
+15 -15
View File
@@ -6,12 +6,12 @@ import importlib
import types import types
from typing import Any from typing import Any
import lib._bootstrap # noqa: F401 设置 sys.path(项目根 + lib/includes) import lib._bootstrap # noqa: F401 设置 sys.path(项目根 + lib)
from lib.core.Handles.HandlesBase import CTypeInfo from lib.core.Handles.HandlesBase import CTypeInfo
from lib.core.SymbolUtils import IsTModule, AnnotationContainsName, ExpandSoftKeywords from lib.core.SymbolUtils import AnnotationContainsName, ExpandSoftKeywords
from lib.includes import t from lib.core import TypeSystem
from lib.includes.t import CType, CEnum from lib.core.TypeSystem import CType, CEnum
from lib.constants.config import mode as _config_mode from lib.constants.config import mode as _config_mode
from lib.core.VLogger import get_logger as _vlog from lib.core.VLogger import get_logger as _vlog
@@ -47,7 +47,7 @@ class AnnotationLoaderMixin:
# 注册枚举类型 # 注册枚举类型
EnumNode: CTypeInfo = CTypeInfo() EnumNode: CTypeInfo = CTypeInfo()
EnumNode.Name = AttrName EnumNode.Name = AttrName
EnumNode.BaseType = t.CEnum() EnumNode.BaseType = TypeSystem.CEnum()
EnumNode.IsEnum = True EnumNode.IsEnum = True
EnumNode.set('enum_class', attr) EnumNode.set('enum_class', attr)
EnumNode.set('source', 'annotation_module') EnumNode.set('source', 'annotation_module')
@@ -71,7 +71,7 @@ class AnnotationLoaderMixin:
if isinstance(member, int): if isinstance(member, int):
MemberNode: CTypeInfo = CTypeInfo() MemberNode: CTypeInfo = CTypeInfo()
MemberNode.Name = MemberName MemberNode.Name = MemberName
MemberNode.BaseType = t.CEnum(AttrName) MemberNode.BaseType = TypeSystem.CEnum(AttrName)
MemberNode.value = member MemberNode.value = member
MemberNode.EnumName = AttrName MemberNode.EnumName = AttrName
MemberNode.library_name = lib_name MemberNode.library_name = lib_name
@@ -230,10 +230,10 @@ class AnnotationLoaderMixin:
self.SymbolTable.insert(FullName, TypeInfo) self.SymbolTable.insert(FullName, TypeInfo)
count += 1 count += 1
# 再次遍历 AST,查找注解文件中的 typedef 语句(AnnAssign with t.CTypedef) # 再次遍历 AST,查找注解文件中的 typedef 语句(AnnAssign with CTypedef)
# 注意:必须在类定义处理完之后再处理 typedef # 注意:必须在类定义处理完之后再处理 typedef
typedef_annots: list[tuple[str, str]] = [] typedef_annots: list[tuple[str, str]] = []
# 查找 CEnum 成员变量(AnnAssign with t.CEnum | t.State 或 t.CEnum) # 查找 CEnum 成员变量(AnnAssign with CEnum | State 或 CEnum)
cEnumMembers: list[tuple[str, int | None]] = [] cEnumMembers: list[tuple[str, int | None]] = []
try: try:
with open(ModuleName, 'r', encoding='utf-8') as f: with open(ModuleName, 'r', encoding='utf-8') as f:
@@ -241,7 +241,7 @@ class AnnotationLoaderMixin:
ann_content = ExpandSoftKeywords(ann_content) ann_content = ExpandSoftKeywords(ann_content)
ann_tree: ast.Module = ast.parse(ann_content, ModuleName) ann_tree: ast.Module = ast.parse(ann_content, ModuleName)
for node in ann_tree.body: for node in ann_tree.body:
# 检测 xxx: t.CEnum 形式的枚举成员变量 # 检测 xxx: CEnum 形式的枚举成员变量
if isinstance(node, ast.AnnAssign): if isinstance(node, ast.AnnAssign):
if isinstance(node.target, ast.Name) and node.annotation: if isinstance(node.target, ast.Name) and node.annotation:
TargetName: str = node.target.id TargetName: str = node.target.id
@@ -252,8 +252,8 @@ class AnnotationLoaderMixin:
if AnnotationContainsName(node.annotation, 'CEnum'): if AnnotationContainsName(node.annotation, 'CEnum'):
IsCenum = True IsCenum = True
elif isinstance(node.annotation, ast.Attribute): elif isinstance(node.annotation, ast.Attribute):
# 直接是 t.CEnum # 直接是 CEnum
if node.annotation.attr == t.CEnum.__name__: if node.annotation.attr == TypeSystem.CEnum.__name__:
IsCenum = True IsCenum = True
if IsCenum: if IsCenum:
@@ -273,7 +273,7 @@ class AnnotationLoaderMixin:
# 注册枚举成员 # 注册枚举成员
MemberNode: CTypeInfo = CTypeInfo() MemberNode: CTypeInfo = CTypeInfo()
MemberNode.Name = TargetName MemberNode.Name = TargetName
MemberNode.BaseType = t.CEnum(TypePrefix) MemberNode.BaseType = TypeSystem.CEnum(TypePrefix)
MemberNode.value = value MemberNode.value = value
MemberNode.EnumName = TypePrefix MemberNode.EnumName = TypePrefix
MemberNode.library_name = TypePrefix MemberNode.library_name = TypePrefix
@@ -288,14 +288,14 @@ class AnnotationLoaderMixin:
ann_content = ExpandSoftKeywords(ann_content) ann_content = ExpandSoftKeywords(ann_content)
ann_tree: ast.Module = ast.parse(ann_content, ModuleName) ann_tree: ast.Module = ast.parse(ann_content, ModuleName)
for node in ann_tree.body: for node in ann_tree.body:
# 检测 xxx: t.CTypedef = xxx 形式的 typedef 语句 # 检测 xxx: CTypedef = xxx 形式的 typedef 语句
if isinstance(node, ast.AnnAssign): if isinstance(node, ast.AnnAssign):
if isinstance(node.target, ast.Name) and node.annotation and node.value: if isinstance(node.target, ast.Name) and node.annotation and node.value:
TargetName: str = node.target.id TargetName: str = node.target.id
# 检查注解是否是 t.CTypedef # 检查注解是否是 CTypedef
if isinstance(node.annotation, ast.Attribute): if isinstance(node.annotation, ast.Attribute):
if isinstance(node.annotation.value, ast.Name): if isinstance(node.annotation.value, ast.Name):
if IsTModule(node.annotation.value.id) and node.annotation.attr == 'CTypedef': if node.annotation.attr == 'CTypedef':
# 检查值是否是 Name # 检查值是否是 Name
if isinstance(node.value, ast.Name): if isinstance(node.value, ast.Name):
original_name: str = node.value.id original_name: str = node.value.id
+1 -1
View File
@@ -75,7 +75,7 @@ class BaseTranslatorMixin:
# 以下属性原先在外部懒注入,此处显式初始化以避免 hasattr/getattr 动态反射 # 以下属性原先在外部懒注入,此处显式初始化以避免 hasattr/getattr 动态反射
self.config: Any = None self.config: Any = None
self._ImportedModules: set[str] | None = None self._ImportedModules: set[str] | None = None
self._t_c_imported_names: dict = {} self._from_import_aliases: dict = {}
# 调用点热点统计(--hotspot-sites):None=未启用(零影响),否则为调用点计数落盘文件路径 # 调用点热点统计(--hotspot-sites):None=未启用(零影响),否则为调用点计数落盘文件路径
self.HotspotSitesFile: str | None = None self.HotspotSitesFile: str | None = None
# 是否对全部直接 call 点插桩(忽略白名单;体积/开销大) # 是否对全部直接 call 点插桩(忽略白名单;体积/开销大)
+2 -2
View File
@@ -123,8 +123,8 @@ class ConstEvalMixin:
if byte_order == 'big' and isinstance(ElemType, ir.IntType) and ElemType.width in (16, 32, 64): if byte_order == 'big' and isinstance(ElemType, ir.IntType) and ElemType.width in (16, 32, 64):
swapped: list[ir.Constant] = [] swapped: list[ir.Constant] = []
for c in constants: for c in constants:
if isinstance(c, ir.Constant) and isinstance(c.type, ir.IntType) and isinstance(c.constant, int): if isinstance(c, ir.Constant) and isinstance(type, ir.IntType) and isinstance(constant, int):
swapped_val: int = self._bswap_constant_value(int(c.constant), ElemType.width) swapped_val: int = self._bswap_constant_value(int(constant), ElemType.width)
swapped.append(ir.Constant(ElemType, swapped_val)) swapped.append(ir.Constant(ElemType, swapped_val))
else: else:
swapped.append(c) swapped.append(c)
+20 -33
View File
@@ -7,12 +7,12 @@ import llvmlite.ir as ir
from lib.core.LlvmCodeGenerator import LlvmCodeGenerator from lib.core.LlvmCodeGenerator import LlvmCodeGenerator
from lib.core.Handles.HandlesBase import CTypeInfo from lib.core.Handles.HandlesBase import CTypeInfo
from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo, CTypeHelper from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo, CTypeHelper
from lib.includes import t from lib.core import TypeSystem
from lib.constants.config import mode as _config_mode from lib.constants.config import mode as _config_mode
from lib.core.VLogger import get_logger as _vlog from lib.core.VLogger import get_logger as _vlog
from lib.core.DecoratorPass import run as _run_decorator_pass from lib.core.DecoratorPass import run as _run_decorator_pass
from lib.core.SymbolUtils import ( from lib.core.SymbolUtils import (
IsTModule, AnnotationContainsName, RequireDefineConstStorable, AnnotationContainsName, RequireDefineConstStorable,
DefineIntWidthOf, DefineIntSignednessOf, DefineIntWidthOf, DefineIntSignednessOf,
) )
# 治本修复:导入 ConstEvaluator 用于预扫描 CDefine 常量的复杂表达式求值 # 治本修复:导入 ConstEvaluator 用于预扫描 CDefine 常量的复杂表达式求值
@@ -50,16 +50,12 @@ class LlvmGeneratorMixin:
elif hasattr(base, 'attr'): elif hasattr(base, 'attr'):
bases.append(base.attr) bases.append(base.attr)
has_methods: bool = any(isinstance(item, ast.FunctionDef) for item in Node.body) has_methods: bool = any(isinstance(item, ast.FunctionDef) for item in Node.body)
# 检测 @t.NoVTable 装饰器(非多态继承基类标记) # 检测 @NoVTable 装饰器(非多态继承基类标记)
has_novtable: bool = False has_novtable: bool = False
if hasattr(Node, 'decorator_list') and Node.decorator_list: if hasattr(Node, 'decorator_list') and Node.decorator_list:
for decorator in Node.decorator_list: for decorator in Node.decorator_list:
if isinstance(decorator, ast.Attribute): if isinstance(decorator, ast.Name) and decorator.id == 'NoVTable':
if getattr(decorator.value, 'id', None) == 't' and decorator.attr == 'NoVTable': has_novtable = True
has_novtable = True
elif isinstance(decorator, ast.Name):
if decorator.id == 'NoVTable':
has_novtable = True
Gen._class_graph[Node.name] = { Gen._class_graph[Node.name] = {
'bases': bases, 'bases': bases,
'has_methods': has_methods, 'has_methods': has_methods,
@@ -78,7 +74,7 @@ class LlvmGeneratorMixin:
def _extract_const_value(node: ast.AST) -> int | str | float | None: def _extract_const_value(node: ast.AST) -> int | str | float | None:
"""求值 CDefine 常量表达式,支持 Constant、BinOp、UnaryOp、Name(引用其他 define)、Call(类型构造)。 """求值 CDefine 常量表达式,支持 Constant、BinOp、UnaryOp、Name(引用其他 define)、Call(类型构造)。
治本修复:原 _extract_call_const_val 只支持 t.XxxType(Constant) 形式, 治本修复:原 _extract_call_const_val 只支持 XxxType(Constant) 形式,
无法处理 FOREGROUND_WHITE = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE 无法处理 FOREGROUND_WHITE = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
等引用其他 CDefine 的 BinOp 表达式,导致依赖常量无法被预扫描。 等引用其他 CDefine 的 BinOp 表达式,导致依赖常量无法被预扫描。
现使用 ConstEvaluator.eval_with_symtab 统一求值。 现使用 ConstEvaluator.eval_with_symtab 统一求值。
@@ -89,10 +85,10 @@ class LlvmGeneratorMixin:
return ConstEvaluator.eval_with_symtab(node, self.SymbolTable) return ConstEvaluator.eval_with_symtab(node, self.SymbolTable)
def _is_cdefine_type(TypeInfo: CTypeInfo | None) -> bool: def _is_cdefine_type(TypeInfo: CTypeInfo | None) -> bool:
"""判断 CTypeInfo 是否对应 t.CDefine 注解""" """判断 CTypeInfo 是否对应 CDefine 注解"""
return bool(TypeInfo and TypeInfo.BaseType and return bool(TypeInfo and TypeInfo.BaseType and
((isinstance(TypeInfo.BaseType, type) and issubclass(TypeInfo.BaseType, t.CDefine)) ((isinstance(TypeInfo.BaseType, type) and issubclass(TypeInfo.BaseType, TypeSystem.CDefine))
or isinstance(TypeInfo.BaseType, t.CDefine) or TypeInfo.IsDefine)) or isinstance(TypeInfo.BaseType, TypeSystem.CDefine) or TypeInfo.IsDefine))
def _register_cdefine_constant(NameNode: ast.Name, Annotation: ast.expr, Value: ast.expr) -> None: def _register_cdefine_constant(NameNode: ast.Name, Annotation: ast.expr, Value: ast.expr) -> None:
"""注册 CDefine 编译期常量(_define_constants + SymbolTable)""" """注册 CDefine 编译期常量(_define_constants + SymbolTable)"""
@@ -128,13 +124,13 @@ class LlvmGeneratorMixin:
for Node in ast.iter_child_nodes(Tree): for Node in ast.iter_child_nodes(Tree):
if isinstance(Node, ast.AnnAssign) and isinstance(Node.target, ast.Name) and Node.value: if isinstance(Node, ast.AnnAssign) and isinstance(Node.target, ast.Name) and Node.value:
TypeInfo: CTypeInfo | None = self.TypeMergeHandler.GetCTypeInfo(Node.annotation) TypeInfo: CTypeInfo | None = self.TypeMergeHandler.GetCTypeInfo(Node.annotation)
# 治本修复:检查 BaseType 是否为 t.CDefine 实例/子类,或 IsDefine 标志 # 治本修复:检查 BaseType 是否为 CDefine 实例/子类,或 IsDefine 标志
# IsDefine 由 GetCTypeInfo 对 t.CDefine 注解自动设置 # IsDefine 由 GetCTypeInfo 对 CDefine 注解自动设置
if _is_cdefine_type(TypeInfo): if _is_cdefine_type(TypeInfo):
_register_cdefine_constant(Node.target, Node.annotation, Node.value) _register_cdefine_constant(Node.target, Node.annotation, Node.value)
elif isinstance(Node, ast.ClassDef): elif isinstance(Node, ast.ClassDef):
# 类体 CDefine 常量(2026-08-10):供方法内裸名(如 Mixin 的 # 类体 CDefine 常量(2026-08-10):供方法内裸名(如 Mixin 的
# ISINSTANCE_CLASS_MAX/MRO_MAX: t.CDefine = N)编译期解析为常量值。 # ISINSTANCE_CLASS_MAX/MRO_MAX: CDefine = N)编译期解析为常量值。
# 原预扫描只用 iter_child_nodes 扫顶层,类体常量不注册 → 方法内 # 原预扫描只用 iter_child_nodes 扫顶层,类体常量不注册 → 方法内
# 裸名解析为 0 → pool.alloc(8*0) 失败(VPC 编译测试 SUBS-NONE)。 # 裸名解析为 0 → pool.alloc(8*0) 失败(VPC 编译测试 SUBS-NONE)。
for _citem in Node.body: for _citem in Node.body:
@@ -152,7 +148,7 @@ class LlvmGeneratorMixin:
if _config_mode == "strict": if _config_mode == "strict":
raise raise
_vlog().warning(f"解析类型注释失败: {_e}", "Exception") _vlog().warning(f"解析类型注释失败: {_e}", "Exception")
if TypeInfo and TypeInfo.BaseType and ((isinstance(TypeInfo.BaseType, type) and issubclass(TypeInfo.BaseType, t.CDefine)) or isinstance(TypeInfo.BaseType, t.CDefine)): if TypeInfo and TypeInfo.BaseType and ((isinstance(TypeInfo.BaseType, type) and issubclass(TypeInfo.BaseType, TypeSystem.CDefine)) or isinstance(TypeInfo.BaseType, TypeSystem.CDefine)):
val: int | str | float | None = _extract_const_value(Node.value) val: int | str | float | None = _extract_const_value(Node.value)
if val is not None: if val is not None:
if not hasattr(Gen, '_define_constants'): if not hasattr(Gen, '_define_constants'):
@@ -293,17 +289,9 @@ class LlvmGeneratorMixin:
return return
call: ast.Call = Node.value call: ast.Call = Node.value
if isinstance(call.func, ast.Name): if isinstance(call.func, ast.Name):
# 模块级裸名 __llvmir__(...) 等价 c.LLVMIR(...) # 模块级 LLVMIR(...) 注入内联 LLVM IR
if call.func.id == '__llvmir__': if call.func.id in ('LLVMIR', '__llvmir__'):
self._HandleModuleLevelLLVMIR(call, Gen) self._HandleModuleLevelLLVMIR(call, Gen)
return
if not isinstance(call.func, ast.Attribute):
return
if not isinstance(call.func.value, ast.Name) or call.func.value.id != 'c':
return
func_name: str = call.func.attr
if func_name == 'LLVMIR':
self._HandleModuleLevelLLVMIR(call, Gen)
def _HandleModuleLevelLLVMIR(self, Node: ast.Call, Gen: LlvmCodeGenerator) -> None: def _HandleModuleLevelLLVMIR(self, Node: ast.Call, Gen: LlvmCodeGenerator) -> None:
if not Node.args: if not Node.args:
@@ -414,14 +402,13 @@ class LlvmGeneratorMixin:
if isinstance(Node, ast.Import): if isinstance(Node, ast.Import):
for alias in Node.names: for alias in Node.names:
name: str = alias.name name: str = alias.name
if name in ('c', 't'): # 按常规模块登记(内建标记为裸名,无需 import)
continue
self._ImportedModules.add(name) self._ImportedModules.add(name)
if alias.asname: if alias.asname:
self.SymbolTable.import_aliases[alias.asname] = name self.SymbolTable.import_aliases[alias.asname] = name
elif isinstance(Node, ast.ImportFrom): elif isinstance(Node, ast.ImportFrom):
module_name: str | None = Node.module module_name: str | None = Node.module
if module_name and module_name not in ('c', 't'): if module_name:
self._ImportedModules.add(module_name) self._ImportedModules.add(module_name)
for alias in Node.names: for alias in Node.names:
if alias.asname: if alias.asname:
@@ -493,7 +480,7 @@ class LlvmGeneratorMixin:
TypeInfo: CTypeInfo | None = self.TypeMergeHandler.GetCTypeInfo(item.annotation) TypeInfo: CTypeInfo | None = self.TypeMergeHandler.GetCTypeInfo(item.annotation)
if TypeInfo is None: if TypeInfo is None:
TypeInfo = CTypeInfo() TypeInfo = CTypeInfo()
TypeInfo.BaseType = t.CInt() TypeInfo.BaseType = TypeSystem.CInt()
IsPtr: bool = TypeInfo.IsPtr IsPtr: bool = TypeInfo.IsPtr
if not IsPtr: if not IsPtr:
if isinstance(item.annotation, ast.BinOp) and isinstance(item.annotation.op, ast.BitOr): if isinstance(item.annotation, ast.BinOp) and isinstance(item.annotation.op, ast.BitOr):
@@ -502,7 +489,7 @@ class LlvmGeneratorMixin:
dims: list[int] = [] dims: list[int] = []
if hasattr(item.annotation, 'slice') and isinstance(item.annotation.slice, ast.Constant): if hasattr(item.annotation, 'slice') and isinstance(item.annotation.slice, ast.Constant):
if isinstance(item.annotation.value, ast.Name): if isinstance(item.annotation.value, ast.Name):
if IsTModule(item.annotation.value.id, self.SymbolTable): if item.annotation.value.id == 'CArray':
if hasattr(item.annotation, 'slice'): if hasattr(item.annotation, 'slice'):
try: try:
dims.append(int(item.annotation.slice.value)) dims.append(int(item.annotation.slice.value))
@@ -720,7 +707,7 @@ class LlvmGeneratorMixin:
# 每个类建 struct,IR 名前缀取自 `class_sha1_map`(空)→ `_struct_sha1_map` # 每个类建 struct,IR 名前缀取自 `class_sha1_map`(空)→ `_struct_sha1_map`
# (Phase2 扫描各 .vpi 得到的"裸类名 → 定义模块 SHA1")。两张表都按**裸类名** # (Phase2 扫描各 .vpi 得到的"裸类名 → 定义模块 SHA1")。两张表都按**裸类名**
# 索引,两个模块各定义同名类时只能留一个:现场 includes/ast/astaux.vp 的 # 索引,两个模块各定义同名类时只能留一个:现场 includes/ast/astaux.vp 的
# `class Keyword(AST)` 与 includes/ast/tokens.vp 的 `class Keyword(t.CEnum)` # `class Keyword(AST)` 与 includes/ast/tokens.vp 的 `class Keyword(CEnum)`
# 同名,`_build_struct_sha1_map` 的"每类只登记一次"判据误用了 sha1 键(恒假、 # 同名,`_build_struct_sha1_map` 的"每类只登记一次"判据误用了 sha1 键(恒假、
# 实为后扫到的覆盖先扫到的)⇒ astaux 自己那份被命名成 # 实为后扫到的覆盖先扫到的)⇒ astaux 自己那份被命名成
# `%"fef783da4d24330d.Keyword"`(= tokens 的 sha1)。于是同一类在本模块里出现 # `%"fef783da4d24330d.Keyword"`(= tokens 的 sha1)。于是同一类在本模块里出现
+36 -47
View File
@@ -6,8 +6,8 @@ import struct
from lib.utils.helpers import DetectFileType from lib.utils.helpers import DetectFileType
from lib.core.Handles.HandlesBase import CTypeInfo from lib.core.Handles.HandlesBase import CTypeInfo
from lib.core.SymbolUtils import IsTModule, AnnotationContainsName, ExpandSoftKeywords from lib.core.SymbolUtils import AnnotationContainsName, ExpandSoftKeywords
from lib.includes import t from lib.core import TypeSystem
from lib.constants.config import mode as _ConfigMode from lib.constants.config import mode as _ConfigMode
from lib.core.VLogger import get_logger as _vlog from lib.core.VLogger import get_logger as _vlog
@@ -116,18 +116,18 @@ class PythonParserMixin:
j += 1 j += 1
continue continue
elif isinstance(NextNode, ast.AnnAssign): elif isinstance(NextNode, ast.AnnAssign):
# 检测 xxx: t.Postdefinition(yyy) 或 xxx: t.CTypedef = xxx 或 xxx: t.CPtr = xxx # 检测 xxx: Postdefinition(yyy) 或 xxx: CTypedef = xxx 或 xxx: CPtr = xxx
if isinstance(NextNode.target, ast.Name): if isinstance(NextNode.target, ast.Name):
TargetName: str = NextNode.target.id TargetName: str = NextNode.target.id
# 先处理新格式:t.Postdefinition(...) # 先处理新格式:Postdefinition(...)
annotation: ast.expr | None = NextNode.annotation annotation: ast.expr | None = NextNode.annotation
PostdefNode: ast.Call | None = None PostdefNode: ast.Call | None = None
# 递归搜索整个注解树,找到 t.Postdefinition(...) 调用 # 递归搜索整个注解树,找到 Postdefinition(...) 调用
def find_PostdefNode(node: ast.AST) -> ast.Call | None: def find_PostdefNode(node: ast.AST) -> ast.Call | None:
if isinstance(node, ast.Call): if isinstance(node, ast.Call):
if isinstance(node.func, ast.Attribute): if isinstance(node.func, ast.Attribute):
if hasattr(node.func.value, 'id') and IsTModule(node.func.value.id, self.SymbolTable) and node.func.attr == 'Postdefinition': if hasattr(node.func.value, 'id') and node.func.attr == 'Postdefinition':
return node return node
elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
LeftResult: ast.Call | None = find_PostdefNode(node.left) LeftResult: ast.Call | None = find_PostdefNode(node.left)
@@ -139,12 +139,11 @@ class PythonParserMixin:
return None return None
PostdefNode = find_PostdefNode(annotation) PostdefNode = find_PostdefNode(annotation)
# 检查是否找到 t.Postdefinition(...) 调用 # 检查是否找到 Postdefinition(...) 调用
if PostdefNode: if PostdefNode:
if (isinstance(PostdefNode.func, ast.Attribute) and if (isinstance(PostdefNode.func, ast.Attribute) and
hasattr(PostdefNode.func, 'value') and hasattr(PostdefNode.func, 'value') and
hasattr(PostdefNode.func.value, 'id') and hasattr(PostdefNode.func.value, 'id') and
IsTModule(PostdefNode.func.value.id, self.SymbolTable) and
PostdefNode.func.attr == 'Postdefinition' and PostdefNode.func.attr == 'Postdefinition' and
PostdefNode.args): PostdefNode.args):
# 检查第一个参数是否是当前类名 # 检查第一个参数是否是当前类名
@@ -164,7 +163,7 @@ class PythonParserMixin:
dimensions.append(DimExpr) dimensions.append(DimExpr)
# 如果没有从 Postdefinition 参数中获取维度,尝试从类型注解中的 Subscript 获取 # 如果没有从 Postdefinition 参数中获取维度,尝试从类型注解中的 Subscript 获取
# 例如:memory_block_t[MAX_ORDER + 1] | t.CPtr # 例如:memory_block_t[MAX_ORDER + 1] | CPtr
if not dimensions: if not dimensions:
def extract_subscript_dims(node: ast.AST) -> list[ast.expr]: def extract_subscript_dims(node: ast.AST) -> list[ast.expr]:
"""递归提取 Subscript 节点的维度""" """递归提取 Subscript 节点的维度"""
@@ -180,7 +179,7 @@ class PythonParserMixin:
# 递归提取更外层的维度 # 递归提取更外层的维度
dims.extend(extract_subscript_dims(node.value)) dims.extend(extract_subscript_dims(node.value))
elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
# 处理 Type | t.CPtr 的情况,检查左侧 # 处理 Type | CPtr 的情况,检查左侧
dims.extend(extract_subscript_dims(node.left)) dims.extend(extract_subscript_dims(node.left))
return dims return dims
@@ -196,7 +195,7 @@ class PythonParserMixin:
value = NextNode.value value = NextNode.value
# 添加到对应的 assignments # 添加到对应的 assignments
# 对于 t.Postdefinition(...),只有包含 CTypedef 或 CPtr 时才视为 typedef 类型 # 对于 Postdefinition(...),只有包含 CTypedef 或 CPtr 时才视为 typedef 类型
if HasCtypedef or IsPtr: if HasCtypedef or IsPtr:
if ClassKey not in self.TypedefAssignments: if ClassKey not in self.TypedefAssignments:
self.TypedefAssignments[ClassKey] = [] self.TypedefAssignments[ClassKey] = []
@@ -229,8 +228,8 @@ class PythonParserMixin:
# (2026-09-30)】原调用指向的方法全仓无定义 ⇒ 一旦命中即 # (2026-09-30)】原调用指向的方法全仓无定义 ⇒ 一旦命中即
# `AttributeError`(与 ClassHandle._PreRegisterClassMembers # `AttributeError`(与 ClassHandle._PreRegisterClassMembers
# 同族:死调用,非"未走到")。 # 同族:死调用,非"未走到")。
# 现状核实:`__set_default__` 在 TransPyC/lib 内只有 # `__set_default__` 在 TransPyC/lib 内只有
# t.py 的定义与 StubGen/Converter 的"剥离该调用、保留类型", # StubGen/Converter 的"剥离该调用、保留类型",
# **没有任何消费端**读取它的 kwargs;includes 全仓亦无源使用。 # **没有任何消费端**读取它的 kwargs;includes 全仓亦无源使用。
# 因此这里既不调用幽灵方法,也不静默丢弃源码语义:明确报未支持, # 因此这里既不调用幽灵方法,也不静默丢弃源码语义:明确报未支持,
# 语义(字段默认值如何落到 class_member_defaults)确定后再实现。 # 语义(字段默认值如何落到 class_member_defaults)确定后再实现。
@@ -240,26 +239,19 @@ class PythonParserMixin:
f"拒绝静默丢弃该默认值语义)") f"拒绝静默丢弃该默认值语义)")
j += 1 j += 1
continue continue
# 再处理旧格式:xxx: t.CTypedef = xxx 或 xxx: t.CPtr = xxx # 再处理 xxx: CPtr = xxx:typedef 不合并进结构体定义,
# 注意:这种格式的 typedef 不应该被合并到结构体定义中, # 而应生成独立的 typedef 语句,故不添加到 TypedefAssignments
# 而应该生成独立的 typedef 语句,所以不添加到 TypedefAssignments elif (NextNode.annotation and isinstance(NextNode.annotation, ast.Name)
elif NextNode.annotation and isinstance(NextNode.annotation, ast.Attribute): and NextNode.annotation.id == TypeSystem.CPtr.__name__):
if isinstance(NextNode.annotation.value, ast.Name): if NextNode.value and isinstance(NextNode.value, ast.Name):
annot_id: str = NextNode.annotation.value.id ValueName: str = NextNode.value.id
annot_attr: str = NextNode.annotation.attr if ValueName == ClassName:
if annot_id == 't' and NextNode.value: # CPtr 表示指针变量,加入 TypedefAssignments,设置 IsPtr=True
if isinstance(NextNode.value, ast.Name): if ClassKey not in self.TypedefAssignments:
ValueName: str = NextNode.value.id self.TypedefAssignments[ClassKey] = []
if ValueName == ClassName: self.TypedefAssignments[ClassKey].append((TargetName, True))
# 检查是 CTypedef 还是 CPtr j += 1
if annot_attr == t.CPtr.__name__: continue
# t.CPtr 表示指针变量,加入 TypedefAssignments,设置 IsPtr=True
if ClassKey not in self.TypedefAssignments:
self.TypedefAssignments[ClassKey] = []
self.TypedefAssignments[ClassKey].append((TargetName, True))
j += 1
continue
# 注意:t.CTypedef 不在这里处理,由 HandlesAnnAssign 生成独立的 typedef 语句
# 如果不是特殊赋值,停止收集 # 如果不是特殊赋值,停止收集
break break
@@ -287,20 +279,18 @@ class PythonParserMixin:
IsCenum = True IsCenum = True
break break
# 检测是否有 @t.Object 装饰器或继承自 t.Object # 检测是否有 @Object 装饰器或继承自 Object
IsCpythonObject: bool = False IsCpythonObject: bool = False
if hasattr(node, 'decorator_list') and node.decorator_list: if hasattr(node, 'decorator_list') and node.decorator_list:
for decorator in node.decorator_list: for decorator in node.decorator_list:
if isinstance(decorator, ast.Attribute): if isinstance(decorator, ast.Attribute):
if (hasattr(decorator.value, 'id') and if (hasattr(decorator.value, 'id') and
IsTModule(decorator.value.id, self.SymbolTable) and
decorator.attr == 'Object'): decorator.attr == 'Object'):
IsCpythonObject = True IsCpythonObject = True
break break
elif isinstance(decorator, ast.Call): elif isinstance(decorator, ast.Call):
if isinstance(decorator.func, ast.Attribute): if isinstance(decorator.func, ast.Attribute):
if (hasattr(decorator.func.value, 'id') and if (hasattr(decorator.func.value, 'id') and
IsTModule(decorator.func.value.id, self.SymbolTable) and
decorator.func.attr == 'Object'): decorator.func.attr == 'Object'):
IsCpythonObject = True IsCpythonObject = True
break break
@@ -315,8 +305,7 @@ class PythonParserMixin:
if not IsCpythonObject and hasattr(node, 'bases') and node.bases: if not IsCpythonObject and hasattr(node, 'bases') and node.bases:
for base in node.bases: for base in node.bases:
if isinstance(base, ast.Attribute): if isinstance(base, ast.Attribute):
if (hasattr(base.value, 'id') and if (hasattr(base.value, 'id') and
IsTModule(base.value.id, self.SymbolTable) and
base.attr == 'Object'): base.attr == 'Object'):
IsCpythonObject = True IsCpythonObject = True
break break
@@ -348,7 +337,7 @@ class PythonParserMixin:
continue continue
MemberNode: CTypeInfo = CTypeInfo() MemberNode: CTypeInfo = CTypeInfo()
MemberNode.Name = MemberName MemberNode.Name = MemberName
MemberNode.BaseType = t.CEnum(ClassName) MemberNode.BaseType = TypeSystem.CEnum(ClassName)
# 提取枚举值:优先用显式赋值,否则自动编号 # 提取枚举值:优先用显式赋值,否则自动编号
if ItemValue is not None and isinstance(ItemValue, ast.Constant) and isinstance(ItemValue.value, int): if ItemValue is not None and isinstance(ItemValue, ast.Constant) and isinstance(ItemValue.value, int):
MemberNode.value = ItemValue.value MemberNode.value = ItemValue.value
@@ -377,7 +366,7 @@ class PythonParserMixin:
TypeInfo: CTypeInfo | None = self.TypeMergeHandler.GetCTypeInfo(item.annotation) TypeInfo: CTypeInfo | None = self.TypeMergeHandler.GetCTypeInfo(item.annotation)
if TypeInfo is None: if TypeInfo is None:
TypeInfo = CTypeInfo() TypeInfo = CTypeInfo()
TypeInfo.BaseType = t.CInt() TypeInfo.BaseType = TypeSystem.CInt()
IsPtr: bool = TypeInfo.IsPtr IsPtr: bool = TypeInfo.IsPtr
if not IsPtr: if not IsPtr:
if isinstance(item.annotation, ast.BinOp) and isinstance(item.annotation.op, ast.BitOr): if isinstance(item.annotation, ast.BinOp) and isinstance(item.annotation.op, ast.BitOr):
@@ -386,7 +375,7 @@ class PythonParserMixin:
dims: list[int] = [] dims: list[int] = []
if hasattr(item.annotation, 'slice') and isinstance(item.annotation.slice, ast.Constant): if hasattr(item.annotation, 'slice') and isinstance(item.annotation.slice, ast.Constant):
if isinstance(item.annotation.value, ast.Name): if isinstance(item.annotation.value, ast.Name):
if IsTModule(item.annotation.value.id, self.SymbolTable): if item.annotation.value.id == 'CArray':
if hasattr(item.annotation, 'slice'): if hasattr(item.annotation, 'slice'):
try: try:
dims.append(int(item.annotation.slice.value)) dims.append(int(item.annotation.slice.value))
@@ -421,17 +410,17 @@ class PythonParserMixin:
elif isinstance(node, ast.AnnAssign): elif isinstance(node, ast.AnnAssign):
if isinstance(node.target, ast.Name): if isinstance(node.target, ast.Name):
VarName: str = node.target.id VarName: str = node.target.id
# 检查是否是 t.CTypedef 格式,如果是则跳过(由 HandleClassDef 处理) # 检查是否是 CTypedef 格式,如果是则跳过(由 HandleClassDef 处理)
is_ctypedef: bool = False is_ctypedef: bool = False
if node.annotation: if node.annotation:
if isinstance(node.annotation, ast.Attribute): if isinstance(node.annotation, ast.Attribute):
if isinstance(node.annotation.value, ast.Name): if isinstance(node.annotation.value, ast.Name):
if IsTModule(node.annotation.value.id, self.SymbolTable) and node.annotation.attr == 'CTypedef': if node.annotation.attr == 'CTypedef':
is_ctypedef = True is_ctypedef = True
elif isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.op, ast.BitOr): elif isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.op, ast.BitOr):
def _has_ctype(ann: ast.AST) -> bool: def _has_ctype(ann: ast.AST) -> bool:
if isinstance(ann, ast.Attribute): if isinstance(ann, ast.Attribute):
return hasattr(ann.value, 'id') and IsTModule(ann.value.id) and ann.attr == 'CTypedef' return hasattr(ann.value, 'id') and ann.attr == 'CTypedef'
if isinstance(ann, ast.BinOp) and isinstance(ann.op, ast.BitOr): if isinstance(ann, ast.BinOp) and isinstance(ann.op, ast.BitOr):
return _has_ctype(ann.left) or _has_ctype(ann.right) return _has_ctype(ann.left) or _has_ctype(ann.right)
if isinstance(ann, ast.Subscript): if isinstance(ann, ast.Subscript):
+138 -213
View File
@@ -9,9 +9,9 @@ from typing import TYPE_CHECKING
from lib.core.Handles.HandlesBase import CTypeInfo, BuiltinTypeMap, CTypeHelper from lib.core.Handles.HandlesBase import CTypeInfo, BuiltinTypeMap, CTypeHelper
from lib.core.ConstEvaluator import ConstEvaluator from lib.core.ConstEvaluator import ConstEvaluator
from lib.core.SymbolUtils import ( from lib.core.SymbolUtils import (
IsTModule, IsTModulePath, IsListAnnotation, IsListAnnotation,
ResolveGenericClassSpecName, GetStructSha1MapFromSymtab, GetTCAliasMapFromSymtab) ResolveGenericClassSpecName, GetStructSha1MapFromSymtab, GetTCAliasMapFromSymtab)
from lib.includes import t from lib.core import TypeSystem
from lib.constants.config import mode as _config_mode from lib.constants.config import mode as _config_mode
if TYPE_CHECKING: if TYPE_CHECKING:
@@ -30,16 +30,16 @@ class TypeAnnotationResolver:
"""从 AST 节点解析类型注解,独立于 CTypeInfo 数据模型。""" """从 AST 节点解析类型注解,独立于 CTypeInfo 数据模型。"""
# 编译器内置语法:rawptr(TPC/VPC 双端内置,不可重定义) # 编译器内置语法:rawptr(TPC/VPC 双端内置,不可重定义)
# rawptr[T] 固定表示"裸指针,指向原始类型 T"(等价 t.CPtr[T]); # rawptr[T] 固定表示"裸指针,指向原始类型 T"(等价 CPtr[T]);
# 单独 rawptr 等价 t.CPtr(void*)。 # 单独 rawptr 等价 CPtr(void*)。
_BUILTIN_ROWPTR_NAME: str = 'rawptr' _BUILTIN_ROWPTR_NAME: str = 'rawptr'
_BUILTIN_ROWPTR_VALUE: str = 't.CPtr' _BUILTIN_ROWPTR_VALUE: str = 'CPtr'
@classmethod @classmethod
def _builtin_rawptr_info(cls) -> CTypeInfo: def _builtin_rawptr_info(cls) -> CTypeInfo:
"""返回内置 rawptr 的 CTypeInfo(t.CPtr 语义:BaseType=CVoid, PtrCount=1)""" """返回内置 rawptr 的 CTypeInfo(CPtr 语义:BaseType=CVoid, PtrCount=1)"""
info: CTypeInfo = CTypeInfo() info: CTypeInfo = CTypeInfo()
info.BaseType = t.CVoid() info.BaseType = TypeSystem.CVoid()
info.PtrCount = 1 info.PtrCount = 1
return info return info
@@ -113,7 +113,7 @@ class TypeAnnotationResolver:
# from_imports 注入,故需按源文件扫描兜底。 # from_imports 注入,故需按源文件扫描兜底。
# 必须同时兼容两种等价写法: # 必须同时兼容两种等价写法:
# - 语法糖 `typedef 名字 = 类型`(builtins.vp 现用形态) # - 语法糖 `typedef 名字 = 类型`(builtins.vp 现用形态)
# - 注解形态 `名字: t.CTypedef = 类型`(stdint.vp 等库模块) # - 注解形态 `名字: CTypedef = 类型`(stdint.vp 等库模块)
# 只认注解形态时语法糖声明全被跳过 → 兜底表为空 → 裸名退化为 # 只认注解形态时语法糖声明全被跳过 → 兜底表为空 → 裸名退化为
# `%"{mod}.名字"*` 假结构体(sizet 曾被当成结构体,BinOp 报 # `%"{mod}.名字"*` 假结构体(sizet 曾被当成结构体,BinOp 报
# "Operands must be the same type, got (%"…sizet"*, i64)")。 # "Operands must be the same type, got (%"…sizet"*, i64)")。
@@ -124,7 +124,7 @@ class TypeAnnotationResolver:
# 既有 `_resolve_builtins_type_str` 的 `depth`/`visited` 只在自身递归内传递; # 既有 `_resolve_builtins_type_str` 的 `depth`/`visited` 只在自身递归内传递;
# 而复合值(含 `|` / `[`)分支会经 `from_node` 重新进入 # 而复合值(含 `|` / `[`)分支会经 `from_node` 重新进入
# `_from_node_name → _lookup_builtins_typedef`,把 depth/visited 归零 ⇒ 该方向 # `_from_node_name → _lookup_builtins_typedef`,把 depth/visited 归零 ⇒ 该方向
# 可绕过环检测无限递归(A = B | t.CPtr、B = A 一类声明)。此计数器覆盖 # 可绕过环检测无限递归(A = B | CPtr、B = A 一类声明)。此计数器覆盖
# `_lookup_builtins_typedef → _resolve_builtins_type_str → from_node → …` 全程, # `_lookup_builtins_typedef → _resolve_builtins_type_str → from_node → …` 全程,
# 超上限即判为成环并 fail-fast(不再沿链继续)。合法链通常 ≤ 4 层。 # 超上限即判为成环并 fail-fast(不再沿链继续)。合法链通常 ≤ 4 层。
_BUILTINS_CHAIN_MAX_DEPTH: int = 32 _BUILTINS_CHAIN_MAX_DEPTH: int = 32
@@ -153,11 +153,11 @@ class TypeAnnotationResolver:
def _NormalizeTypedefRhsText(text: str) -> str: def _NormalizeTypedefRhsText(text: str) -> str:
"""把 typedef 右值的 C 式写法归一成规范 `|` 联合文本(供**文本回退路径**使用)。 """把 typedef 右值的 C 式写法归一成规范 `|` 联合文本(供**文本回退路径**使用)。
磁盘原文里 `X: t.CTypedef = const str` / `= const uint16*` 的右值带描述符与指针 磁盘原文里 `X: CTypedef = const str` / `= const uint16*` 的右值带描述符与指针
后缀,而本路径(_parse_typedef_line → _resolve_builtins_type_str)按表达式文本解析, 后缀,而本路径(_parse_typedef_line → _resolve_builtins_type_str)按表达式文本解析,
故先归一: 故先归一:
- 前导 `const` / `volatile`(可组合) → `t.CConst` / `t.CVolatile` 前缀; - 前导 `const` / `volatile`(可组合) → `CConst` / `CVolatile` 前缀;
- 末尾 `*` / `**` 串 → 逐层 `| t.CPtr`。 - 末尾 `*` / `**` 串 → 逐层 `| CPtr`。
不含上述形态的文本原样返回(幂等)。无算术语义风险:typedef 右值不含乘法。 不含上述形态的文本原样返回(幂等)。无算术语义风险:typedef 右值不含乘法。
""" """
s: str = text.strip() s: str = text.strip()
@@ -168,7 +168,7 @@ class TypeAnnotationResolver:
m: re.Match | None = re.match(r'^(const|volatile)\s+', s) m: re.Match | None = re.match(r'^(const|volatile)\s+', s)
if m is None: if m is None:
break break
markers.append('t.CConst' if m.group(1) == 'const' else 't.CVolatile') markers.append('CConst' if m.group(1) == 'const' else 'CVolatile')
s = s[m.end():].lstrip() s = s[m.end():].lstrip()
ptrs: int = 0 ptrs: int = 0
while s.endswith('*'): while s.endswith('*'):
@@ -176,23 +176,23 @@ class TypeAnnotationResolver:
ptrs += 1 ptrs += 1
if not markers and ptrs == 0: if not markers and ptrs == 0:
return text return text
parts: list[str] = markers + [s] + ['t.CPtr'] * ptrs parts: list[str] = markers + [s] + ['CPtr'] * ptrs
return ' | '.join(p for p in parts if p) return ' | '.join(p for p in parts if p)
@staticmethod @staticmethod
def _parse_typedef_line(stripped: str) -> tuple[str, str] | None: def _parse_typedef_line(stripped: str) -> tuple[str, str] | None:
"""单行源码文本 → typedef 声明 (名字, 类型值);非 typedef 行返回 None """单行源码文本 → typedef 声明 (名字, 类型值);非 typedef 行返回 None
兼容 `typedef 名字 = 类型`(语法糖)与 `名字: t.CTypedef = 类型`(注解)。 兼容 `typedef 名字 = 类型`(语法糖)与 `名字: CTypedef = 类型`(注解)。
右值的 C 式写法(`const T` / `T*`)经 _NormalizeTypedefRhsText 归一为 `|` 联合。 右值的 C 式写法(`const T` / `T*`)经 _NormalizeTypedefRhsText 归一为 `|` 联合。
""" """
m: re.Match | None = TypeAnnotationResolver._TYPEDEF_SUGAR_RE.match(stripped) m: re.Match | None = TypeAnnotationResolver._TYPEDEF_SUGAR_RE.match(stripped)
if m is not None: if m is not None:
return m.group(1), TypeAnnotationResolver._NormalizeTypedefRhsText(m.group(2)) return m.group(1), TypeAnnotationResolver._NormalizeTypedefRhsText(m.group(2))
if ':' not in stripped or 't.CTypedef' not in stripped: if ':' not in stripped or 'CTypedef' not in stripped:
return None return None
name, _, rest = stripped.partition(':') name, _, rest = stripped.partition(':')
if 't.CTypedef' not in rest: if 'CTypedef' not in rest:
return None return None
value: str = rest.partition('=')[2].strip() value: str = rest.partition('=')[2].strip()
name = name.strip() name = name.strip()
@@ -262,7 +262,7 @@ class TypeAnnotationResolver:
def _scan_library_typedef(cls, mod: str, attr: str) -> str | None: def _scan_library_typedef(cls, mod: str, attr: str) -> str | None:
"""查库模块源中 typedef 声明,返回类型值(权威定义)或 None """查库模块源中 typedef 声明,返回类型值(权威定义)或 None
兼容 `typedef 名字 = 类型`(语法糖)与 `名字: t.CTypedef = 类型`(注解)。 兼容 `typedef 名字 = 类型`(语法糖)与 `名字: CTypedef = 类型`(注解)。
""" """
path: str | None = TypeAnnotationResolver._find_include_file(mod) path: str | None = TypeAnnotationResolver._find_include_file(mod)
if path is None: if path is None:
@@ -286,10 +286,10 @@ class TypeAnnotationResolver:
def _resolve_builtins_type_str(cls, type_str: str, aliases: dict[str, str], def _resolve_builtins_type_str(cls, type_str: str, aliases: dict[str, str],
SymbolTable, depth: int = 0, SymbolTable, depth: int = 0,
visited: frozenset[str] | None = None) -> CTypeInfo | None: visited: frozenset[str] | None = None) -> CTypeInfo | None:
"""解析 builtins typedef 值(支持 t.XXX / mod.attr / 裸名;mod 支持 import 别名) """解析 builtins typedef 值(支持 XXX / mod.attr / 裸名;mod 支持 import 别名)
Args: Args:
type_str: typedef 值(如 t.CPtr / __stdint.size_t / CSizeT / sizet) type_str: typedef 值(如 CPtr / __stdint.size_t / CSizeT / sizet)
aliases: builtins.vp 的 import 别名表(__stdint → stdint) aliases: builtins.vp 的 import 别名表(__stdint → stdint)
depth: 递归深度守卫(防 typedef 值自引用成环) depth: 递归深度守卫(防 typedef 值自引用成环)
visited: 本次展开链上已展开的 typedef 名(环检测)。命中环/自引用返回 visited: 本次展开链上已展开的 typedef 名(环检测)。命中环/自引用返回
@@ -317,17 +317,6 @@ class TypeAnnotationResolver:
mod = mod.strip() mod = mod.strip()
attr = attr.strip() attr = attr.strip()
real_mod: str = aliases.get(mod, mod) real_mod: str = aliases.get(mod, mod)
# t/c 内建命名空间:**优先按内建类名直接解析**,不依赖调用方 SymbolTable
# 的装配进度(import 注册阶段 t 尚未入表 ⇒ 原先返回 None,被上层误归因为
# "自引用/循环引用";实测 builtins typedef 'sizet' → 't.CSizeT' 即卡在此处)。
if real_mod in ('t', 'c'):
_bi: CTypeInfo | None = TypeAnnotationResolver.from_type_name(attr)
if _bi is not None:
return _bi
node = TypeAnnotationResolver._parse_type_expr(type_str)
if node is not None:
return TypeAnnotationResolver.from_node(node, SymbolTable)
return None
# 库模块权威 typedef(stdint.size_t → 读 stdint.vp 扫描) # 库模块权威 typedef(stdint.size_t → 读 stdint.vp 扫描)
lib_val: str | None = TypeAnnotationResolver._scan_library_typedef(real_mod, attr) lib_val: str | None = TypeAnnotationResolver._scan_library_typedef(real_mod, attr)
if lib_val is not None: if lib_val is not None:
@@ -341,8 +330,8 @@ class TypeAnnotationResolver:
# 裸名:名字本身即类型(t/C 类名、BuiltinTypeMap 的 C 速记名、裸 LLVM 标量名) # 裸名:名字本身即类型(t/C 类名、BuiltinTypeMap 的 C 速记名、裸 LLVM 标量名)
# → 直接解析;否则它可能是**另一个 typedef 的引用**,沿 builtins typedef 表 # → 直接解析;否则它可能是**另一个 typedef 的引用**,沿 builtins typedef 表
# 继续展开到基础类型。 # 继续展开到基础类型。
# 依据:stdint.vp 的 `size_t/SIZE_T: t.CTypedef = sizet` 与 builtins.vp 的 # 依据:stdint.vp 的 `size_t/SIZE_T: CTypedef = sizet` 与 builtins.vp 的
# `size_t/uzt: t.CTypedef = sizet` 都是"别名 → 权威名 → t 类型"的链式写法, # `size_t/uzt: CTypedef = sizet` 都是"别名 → 权威名 → t 类型"的链式写法,
# 与 VPC resolve_typedef_or_map 的 CTypedef 表递归(TypeGenResolve.vp:723-734) # 与 VPC resolve_typedef_or_map 的 CTypedef 表递归(TypeGenResolve.vp:723-734)
# 同口径。此前裸名一律走 from_type_name:链中名字命中不到基础类型时退化成 # 同口径。此前裸名一律走 from_type_name:链中名字命中不到基础类型时退化成
# %"{mod}.{名}"* 假结构体(sizet/size_t → "Type of #N arg mismatch: # %"{mod}.{名}"* 假结构体(sizet/size_t → "Type of #N arg mismatch:
@@ -355,7 +344,7 @@ class TypeAnnotationResolver:
return TypeAnnotationResolver.from_type_name(type_str) return TypeAnnotationResolver.from_type_name(type_str)
seen: frozenset[str] = visited or frozenset() seen: frozenset[str] = visited or frozenset()
if type_str in seen or chain == type_str: if type_str in seen or chain == type_str:
# 自引用/环(如 `sizet: t.CTypedef = sizet`):无信息可展开,返回 None # 自引用/环(如 `sizet: CTypedef = sizet`):无信息可展开,返回 None
return None return None
return TypeAnnotationResolver._resolve_builtins_type_str( return TypeAnnotationResolver._resolve_builtins_type_str(
chain, aliases, SymbolTable, depth + 1, seen | {type_str}) chain, aliases, SymbolTable, depth + 1, seen | {type_str})
@@ -375,8 +364,8 @@ class TypeAnnotationResolver:
return True return True
cls: type | None = CTypeHelper.GetTModuleCType(name) cls: type | None = CTypeHelper.GetTModuleCType(name)
if cls is None: if cls is None:
cls = getattr(t, name, None) cls = getattr(TypeSystem, name, None)
return isinstance(cls, type) and issubclass(cls, t.CType) and cls is not t.CType return isinstance(cls, type) and issubclass(cls, TypeSystem.CType) and cls is not TypeSystem.CType
@staticmethod @staticmethod
def _parse_type_expr(text: str) -> ast.AST | None: def _parse_type_expr(text: str) -> ast.AST | None:
@@ -394,7 +383,7 @@ class TypeAnnotationResolver:
@classmethod @classmethod
def builtins_typedef_value(cls, TypeName: str) -> str | None: def builtins_typedef_value(cls, TypeName: str) -> str | None:
"""返回 builtins.vp 中 CTypedef 声明的原始类型值(如 rawptr → 't.CPtr') """返回 builtins.vp 中 CTypedef 声明的原始类型值(如 rawptr → 'CPtr')
供 stub 生成 / 类型字符串消费端判断"base[arg]"下标是否为 builtins 指针 供 stub 生成 / 类型字符串消费端判断"base[arg]"下标是否为 builtins 指针
typedef(rawptr[AST] → AST*),防止字符串化产物被误建为 phantom 结构体。 typedef(rawptr[AST] → AST*),防止字符串化产物被误建为 phantom 结构体。
@@ -438,7 +427,7 @@ class TypeAnnotationResolver:
f"builtins typedef 解析链成环或过深(>{cls._BUILTINS_CHAIN_MAX_DEPTH} 层)," f"builtins typedef 解析链成环或过深(>{cls._BUILTINS_CHAIN_MAX_DEPTH} 层),"
f"解析 '{TypeName}' 时终止:includes/builtins.vp 中相关 typedef 声明" f"解析 '{TypeName}' 时终止:includes/builtins.vp 中相关 typedef 声明"
f"(含 `|` / `[...]` 复合值)互相引用成环。请改为指向真实基础类型" f"(含 `|` / `[...]` 复合值)互相引用成环。请改为指向真实基础类型"
f"(如 t.CSizeT),或断开环上引用。") f"(如 CSizeT),或断开环上引用。")
cls._builtins_failure_cache[TypeName] = _err cls._builtins_failure_cache[TypeName] = _err
raise ValueError(_err) raise ValueError(_err)
data: dict = cls._scan_builtins() data: dict = cls._scan_builtins()
@@ -447,13 +436,13 @@ class TypeAnnotationResolver:
return None return None
info: CTypeInfo | None = cls._resolve_builtins_type_str(type_str, data['aliases'], SymbolTable) info: CTypeInfo | None = cls._resolve_builtins_type_str(type_str, data['aliases'], SymbolTable)
if info is None: if info is None:
# 不再一律归因"自引用/循环引用"(那正是把 t.CSizeT 解析失败误报成环、 # 不再一律归因"自引用/循环引用"(那正是把 CSizeT 解析失败误报成环、
# 把人引向错误方向的根因):把声明值与该值解析失败的形态如实报出。 # 把人引向错误方向的根因):把声明值与该值解析失败的形态如实报出。
_err = ( _err = (
f"builtins typedef '{TypeName}' 无法解析到基础类型:includes/builtins.vp " f"builtins typedef '{TypeName}' 无法解析到基础类型:includes/builtins.vp "
f"声明 '{TypeName}: t.CTypedef = {type_str}',其值 '{type_str}' 解析失败" f"声明 '{TypeName}: CTypedef = {type_str}',其值 '{type_str}' 解析失败"
f"(既不是内建类型名,也不是链上可展开的 typedef)。" f"(既不是内建类型名,也不是链上可展开的 typedef)。"
f"请把该声明指向真实类型(如 t.CSizeT),或确认该类型名存在。") f"请把该声明指向真实类型(如 CSizeT),或确认该类型名存在。")
cls._builtins_failure_cache[TypeName] = _err cls._builtins_failure_cache[TypeName] = _err
raise ValueError(_err) raise ValueError(_err)
return info return info
@@ -494,21 +483,21 @@ class TypeAnnotationResolver:
_R: CTypeInfo = _Cand.Copy() _R: CTypeInfo = _Cand.Copy()
_R.IsTypedef = True _R.IsTypedef = True
if _R.BaseType is None: if _R.BaseType is None:
_R.BaseType = t._CTypedef(TypeName) _R.BaseType = TypeSystem._CTypedef(TypeName)
return _R return _R
if getattr(_Cand, 'IsStruct', False) or getattr(_Cand, 'IsRenum', False): if getattr(_Cand, 'IsStruct', False) or getattr(_Cand, 'IsRenum', False):
# 结构体表示与本文件既有 promotion(_from_node_name / _from_node_attribute # 结构体表示与本文件既有 promotion(_from_node_name / _from_node_attribute
# 的 `BaseType = t.CStruct(name=...); IsStruct = True`)**逐字同口径**: # 的 `BaseType = CStruct(name=...); IsStruct = True`)**逐字同口径**:
# 类引用不额外加指针层(PtrCount 保持 0)——本文件里 `rawptr[X]` 的层数 # 类引用不额外加指针层(PtrCount 保持 0)——本文件里 `rawptr[X]` 的层数
# 由 rawptr 分支自己 +1,若此处再加一层会得到 `X**`。 # 由 rawptr 分支自己 +1,若此处再加一层会得到 `X**`。
_R = CTypeInfo() _R = CTypeInfo()
_R.BaseType = t.CStruct(name=TypeName) _R.BaseType = TypeSystem.CStruct(name=TypeName)
_R.IsStruct = True _R.IsStruct = True
_R.Name = TypeName _R.Name = TypeName
return _R return _R
if getattr(_Cand, 'IsEnum', False): if getattr(_Cand, 'IsEnum', False):
_R = CTypeInfo() _R = CTypeInfo()
_R.BaseType = t.CInt() _R.BaseType = TypeSystem.CInt()
_R.IsEnum = True _R.IsEnum = True
_R.Name = TypeName _R.Name = TypeName
return _R return _R
@@ -518,39 +507,44 @@ class TypeAnnotationResolver:
def _from_node_name(Node: ast.Name, SymbolTable: dict | SymbolTable) -> CTypeInfo: def _from_node_name(Node: ast.Name, SymbolTable: dict | SymbolTable) -> CTypeInfo:
"""处理 ast.Name 节点""" """处理 ast.Name 节点"""
TypeName: str = Node.id TypeName: str = Node.id
# 编译器内置语法 rawptr(不可重定义):单独 rawptr 等价 t.CPtr(void*), # 编译器内置语法 rawptr(不可重定义):单独 rawptr 等价 CPtr(void*),
# 优先于 SymbolTable/任何 typedef 声明。 # 优先于 SymbolTable/任何 typedef 声明。
if TypeName == TypeAnnotationResolver._BUILTIN_ROWPTR_NAME: if TypeName == TypeAnnotationResolver._BUILTIN_ROWPTR_NAME:
return TypeAnnotationResolver._builtin_rawptr_info() return TypeAnnotationResolver._builtin_rawptr_info()
if TypeName in ('CRef', 'CTempRef'):
Result: CTypeInfo = CTypeInfo()
Result.PtrCount = 1
Result.BaseType = TypeSystem.CVoid()
return Result
TypeObj: type | None = CTypeHelper.GetTModuleCType(TypeName) TypeObj: type | None = CTypeHelper.GetTModuleCType(TypeName)
if TypeObj is None: if TypeObj is None:
TypeObj = getattr(t, TypeName, None) TypeObj = getattr(TypeSystem, TypeName, None)
if isinstance(TypeObj, type) and issubclass(TypeObj, t.CType) and TypeObj is not t.CType: if isinstance(TypeObj, type) and issubclass(TypeObj, TypeSystem.CType) and TypeObj is not TypeSystem.CType:
if TypeObj == t.CPtr: if TypeObj == TypeSystem.CPtr:
Result: CTypeInfo = CTypeInfo() Result: CTypeInfo = CTypeInfo()
Result.PtrCount = 1 Result.PtrCount = 1
Result.BaseType = t.CVoid() Result.BaseType = TypeSystem.CVoid()
return Result return Result
if TypeObj == t.State: if TypeObj == TypeSystem.State:
Result: CTypeInfo = CTypeInfo() Result: CTypeInfo = CTypeInfo()
Result.IsState = True Result.IsState = True
Result.BaseType = t.CVoid() Result.BaseType = TypeSystem.CVoid()
return Result return Result
Inst: t.CType = TypeObj() Inst: TypeSystem.CType = TypeObj()
Result: CTypeInfo = CTypeInfo() Result: CTypeInfo = CTypeInfo()
Result.Name = type(Inst).__name__ Result.Name = type(Inst).__name__
# 存储类修饰符(CExtern, CExport, CInline, CThreadLocal 等): # 存储类修饰符(CExtern, CExport, CInline, CThreadLocal 等):
# position 含 STORAGE_CLASS 且不含 BASE → 纯修饰符,无实际类型 # position 含 STORAGE_CLASS 且不含 BASE → 纯修饰符,无实际类型
if t.CType.STORAGE_CLASS in TypeObj.position and t.CType.BASE not in TypeObj.position: if TypeSystem.CType.STORAGE_CLASS in TypeObj.position and TypeSystem.CType.BASE not in TypeObj.position:
Result.BaseType = t.CVoid() Result.BaseType = TypeSystem.CVoid()
Result.Storage = Inst Result.Storage = Inst
return Result return Result
# 类型限定符(CConst, CVolatile 等) # 类型限定符(CConst, CVolatile 等)
if t.CType.TYPE_QUALIFIER in TypeObj.position and t.CType.BASE not in TypeObj.position: if TypeSystem.CType.TYPE_QUALIFIER in TypeObj.position and TypeSystem.CType.BASE not in TypeObj.position:
Result.BaseType = t.CVoid() Result.BaseType = TypeSystem.CVoid()
if TypeObj == t.CConst: if TypeObj == TypeSystem.CConst:
Result.DataConst = True Result.DataConst = True
elif TypeObj == t.CVolatile: elif TypeObj == TypeSystem.CVolatile:
Result.DataVolatile = True Result.DataVolatile = True
return Result return Result
Result.BaseType = TypeObj Result.BaseType = TypeObj
@@ -572,7 +566,7 @@ class TypeAnnotationResolver:
if Entry: if Entry:
if isinstance(Entry, CTypeInfo): if isinstance(Entry, CTypeInfo):
if Entry.IsTypedef: if Entry.IsTypedef:
if Entry.BaseType and (not isinstance(Entry.BaseType, (t._CTypedef,)) or Entry.PtrCount > 0): if Entry.BaseType and (not isinstance(Entry.BaseType, (TypeSystem._CTypedef,)) or Entry.PtrCount > 0):
Result = Entry.Copy() Result = Entry.Copy()
Result.IsTypedef = True Result.IsTypedef = True
Result.Name = TypeName Result.Name = TypeName
@@ -614,18 +608,18 @@ class TypeAnnotationResolver:
return Entry return Entry
if Entry.IsEnum: if Entry.IsEnum:
Result = CTypeInfo() Result = CTypeInfo()
Result.BaseType = t.CInt() Result.BaseType = TypeSystem.CInt()
Result.IsEnum = True Result.IsEnum = True
Result.Name = TypeName Result.Name = TypeName
return Result return Result
if Entry.IsExceptionClass: if Entry.IsExceptionClass:
Result = CTypeInfo() Result = CTypeInfo()
Result.BaseType = t.CInt() Result.BaseType = TypeSystem.CInt()
Result.IsExceptionClass = True Result.IsExceptionClass = True
Result.Name = TypeName Result.Name = TypeName
return Result return Result
if Entry.BaseType is None and (Entry.IsStruct or Entry.Name): if Entry.BaseType is None and (Entry.IsStruct or Entry.Name):
Entry.BaseType = t.CStruct(name=TypeName) Entry.BaseType = TypeSystem.CStruct(name=TypeName)
Entry.IsStruct = True Entry.IsStruct = True
if (Entry.BaseType is None and not Entry.IsStruct and not Entry.IsEnum if (Entry.BaseType is None and not Entry.IsStruct and not Entry.IsEnum
and not Entry.IsTypedef and not Entry.IsCpythonObject and not Entry.Name): and not Entry.IsTypedef and not Entry.IsCpythonObject and not Entry.Name):
@@ -665,13 +659,13 @@ class TypeAnnotationResolver:
Result.Name = TypeName Result.Name = TypeName
return Result return Result
Result = CTypeInfo() Result = CTypeInfo()
Result.BaseType = t._CTypedef(TypeName) Result.BaseType = TypeSystem._CTypedef(TypeName)
Result.IsTypedef = True Result.IsTypedef = True
Result.Name = TypeName Result.Name = TypeName
return Result return Result
# 检查 t 类型别名(from t import CInt as myint) # 检查 t 类型别名(from t import CInt as myint)
if hasattr(SymbolTable, '_t_type_symbols'): if hasattr(SymbolTable, '_builtin_type_symbols'):
t_cls = SymbolTable._t_type_symbols.get(TypeName) t_cls = SymbolTable._builtin_type_symbols.get(TypeName)
if t_cls is not None: if t_cls is not None:
Result = CTypeInfo() Result = CTypeInfo()
Result.BaseType = t_cls Result.BaseType = t_cls
@@ -679,7 +673,7 @@ class TypeAnnotationResolver:
# 特殊处理 str 类型,它应该是 char*(指针) # 特殊处理 str 类型,它应该是 char*(指针)
if TypeName in ('str', 'bytes'): if TypeName in ('str', 'bytes'):
Result = CTypeInfo() Result = CTypeInfo()
Result.BaseType = t.CChar() Result.BaseType = TypeSystem.CChar()
Result.PtrCount = 1 Result.PtrCount = 1
return Result return Result
# [builtins 最后匹配] 常规路径全部 miss 后的最终兜底: # [builtins 最后匹配] 常规路径全部 miss 后的最终兜底:
@@ -712,17 +706,15 @@ class TypeAnnotationResolver:
if _config_mode == "strict": if _config_mode == "strict":
warnings.warn(f"异常被忽略: {_e}") warnings.warn(f"异常被忽略: {_e}")
return Result return Result
if isinstance(Node.func, ast.Attribute): if isinstance(Node.func, ast.Name) and Node.func.id == 'Bit' and len(Node.args) > 0:
if isinstance(Node.func.value, ast.Name) and IsTModule(Node.func.value.id, SymbolTable): Result: CTypeInfo = CTypeInfo()
if Node.func.attr == 'Bit' and len(Node.args) > 0: Result.BaseType = TypeSystem.CInt()
Result: CTypeInfo = CTypeInfo() Result.IsBitField = True
Result.BaseType = t.CInt() if isinstance(Node.args[0], ast.Constant) and isinstance(Node.args[0].value, int):
Result.IsBitField = True Result.BitWidth = Node.args[0].value
if isinstance(Node.args[0], ast.Constant) and isinstance(Node.args[0].value, int): else:
Result.BitWidth = Node.args[0].value Result.BitWidth = 1
else: return Result
Result.BitWidth = 1
return Result
return CTypeInfo() return CTypeInfo()
@staticmethod @staticmethod
@@ -736,10 +728,10 @@ class TypeAnnotationResolver:
Result.IsState = True Result.IsState = True
NonStateInfo: CTypeInfo = LeftInfo if not LeftInfo.IsState else RightInfo NonStateInfo: CTypeInfo = LeftInfo if not LeftInfo.IsState else RightInfo
StateInfo: CTypeInfo = LeftInfo if LeftInfo.IsState else RightInfo StateInfo: CTypeInfo = LeftInfo if LeftInfo.IsState else RightInfo
if NonStateInfo.BaseType and (not isinstance(NonStateInfo.BaseType, (t._CTypedef,)) or NonStateInfo.PtrCount > 0): if NonStateInfo.BaseType and (not isinstance(NonStateInfo.BaseType, (TypeSystem._CTypedef,)) or NonStateInfo.PtrCount > 0):
Result.BaseType = NonStateInfo.BaseType Result.BaseType = NonStateInfo.BaseType
elif NonStateInfo.IsTypedef and NonStateInfo.Name: elif NonStateInfo.IsTypedef and NonStateInfo.Name:
if NonStateInfo.BaseType and (not isinstance(NonStateInfo.BaseType, (t._CTypedef,)) or NonStateInfo.PtrCount > 0): if NonStateInfo.BaseType and (not isinstance(NonStateInfo.BaseType, (TypeSystem._CTypedef,)) or NonStateInfo.PtrCount > 0):
Result.BaseType = NonStateInfo.BaseType Result.BaseType = NonStateInfo.BaseType
Result.PtrCount = NonStateInfo.PtrCount Result.PtrCount = NonStateInfo.PtrCount
Result.IsTypedef = True Result.IsTypedef = True
@@ -747,20 +739,20 @@ class TypeAnnotationResolver:
if NonStateInfo.OriginalType: if NonStateInfo.OriginalType:
Result.OriginalType = NonStateInfo.OriginalType Result.OriginalType = NonStateInfo.OriginalType
else: else:
Result.BaseType = t.CStruct(name=NonStateInfo.Name) Result.BaseType = TypeSystem.CStruct(name=NonStateInfo.Name)
Result.IsStruct = True Result.IsStruct = True
Result.IsTypedef = True Result.IsTypedef = True
Result.Name = NonStateInfo.Name Result.Name = NonStateInfo.Name
if NonStateInfo.OriginalType: if NonStateInfo.OriginalType:
Result.OriginalType = NonStateInfo.OriginalType Result.OriginalType = NonStateInfo.OriginalType
else: else:
Result.BaseType = t.CVoid() Result.BaseType = TypeSystem.CVoid()
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount) Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
if not Result.Storage: if not Result.Storage:
Result.Storage = t.CExport() Result.Storage = TypeSystem.CExport()
if LeftInfo.Storage and not isinstance(LeftInfo.Storage, t.CExport): if LeftInfo.Storage and not isinstance(LeftInfo.Storage, TypeSystem.CExport):
Result.Storage = LeftInfo.Storage Result.Storage = LeftInfo.Storage
elif RightInfo.Storage and not isinstance(RightInfo.Storage, t.CExport): elif RightInfo.Storage and not isinstance(RightInfo.Storage, TypeSystem.CExport):
Result.Storage = RightInfo.Storage Result.Storage = RightInfo.Storage
if LeftInfo.DataConst or RightInfo.DataConst: if LeftInfo.DataConst or RightInfo.DataConst:
Result.DataConst = True Result.DataConst = True
@@ -770,37 +762,37 @@ class TypeAnnotationResolver:
if LeftInfo.IsPtr or RightInfo.IsPtr: if LeftInfo.IsPtr or RightInfo.IsPtr:
Result = CTypeInfo() Result = CTypeInfo()
# 当双方都是指针时(如 (AST | t.CPtr) | t.CPtr),PtrCount 应相加 # 当双方都是指针时(如 (AST | CPtr) | CPtr),PtrCount 应相加
# 而非取 max,否则 AST** 会被折叠为 AST*,导致对象切片问题 # 而非取 max,否则 AST** 会被折叠为 AST*,导致对象切片问题
if LeftInfo.IsPtr and RightInfo.IsPtr: if LeftInfo.IsPtr and RightInfo.IsPtr:
Result.PtrCount = LeftInfo.PtrCount + RightInfo.PtrCount Result.PtrCount = LeftInfo.PtrCount + RightInfo.PtrCount
# BaseType 优先取非 void 侧(如 AST),而非 t.CPtr 的 void # BaseType 优先取非 void 侧(如 AST),而非 CPtr 的 void
if LeftInfo.BaseType and not isinstance(LeftInfo.BaseType, t.CVoid): if LeftInfo.BaseType and not isinstance(LeftInfo.BaseType, TypeSystem.CVoid):
Result.BaseType = LeftInfo.BaseType Result.BaseType = LeftInfo.BaseType
elif RightInfo.BaseType and not isinstance(RightInfo.BaseType, t.CVoid): elif RightInfo.BaseType and not isinstance(RightInfo.BaseType, TypeSystem.CVoid):
Result.BaseType = RightInfo.BaseType Result.BaseType = RightInfo.BaseType
else: else:
Result.BaseType = t.CUnsignedChar() Result.BaseType = TypeSystem.CUnsignedChar()
else: else:
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount) Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
NonPtrInfo = LeftInfo if not LeftInfo.IsPtr else RightInfo NonPtrInfo = LeftInfo if not LeftInfo.IsPtr else RightInfo
PtrInfo = RightInfo if RightInfo.IsPtr else LeftInfo PtrInfo = RightInfo if RightInfo.IsPtr else LeftInfo
if NonPtrInfo.BaseType and (not isinstance(NonPtrInfo.BaseType, (t._CTypedef,)) or NonPtrInfo.PtrCount > 0): if NonPtrInfo.BaseType and (not isinstance(NonPtrInfo.BaseType, (TypeSystem._CTypedef,)) or NonPtrInfo.PtrCount > 0):
Result.BaseType = NonPtrInfo.BaseType Result.BaseType = NonPtrInfo.BaseType
elif NonPtrInfo.IsTypedef and NonPtrInfo.Name: elif NonPtrInfo.IsTypedef and NonPtrInfo.Name:
if NonPtrInfo.BaseType and (not isinstance(NonPtrInfo.BaseType, (t._CTypedef,)) or NonPtrInfo.PtrCount > 0): if NonPtrInfo.BaseType and (not isinstance(NonPtrInfo.BaseType, (TypeSystem._CTypedef,)) or NonPtrInfo.PtrCount > 0):
Result.BaseType = NonPtrInfo.BaseType Result.BaseType = NonPtrInfo.BaseType
Result.IsTypedef = True Result.IsTypedef = True
Result.Name = NonPtrInfo.Name Result.Name = NonPtrInfo.Name
if NonPtrInfo.OriginalType: if NonPtrInfo.OriginalType:
Result.OriginalType = NonPtrInfo.OriginalType Result.OriginalType = NonPtrInfo.OriginalType
else: else:
Result.BaseType = t.CStruct(name=NonPtrInfo.Name) Result.BaseType = TypeSystem.CStruct(name=NonPtrInfo.Name)
Result.IsStruct = True Result.IsStruct = True
elif PtrInfo.BaseType and (not isinstance(PtrInfo.BaseType, (t._CTypedef,)) or PtrInfo.PtrCount > 0): elif PtrInfo.BaseType and (not isinstance(PtrInfo.BaseType, (TypeSystem._CTypedef,)) or PtrInfo.PtrCount > 0):
Result.BaseType = PtrInfo.BaseType Result.BaseType = PtrInfo.BaseType
else: else:
Result.BaseType = t.CUnsignedChar() Result.BaseType = TypeSystem.CUnsignedChar()
if LeftInfo.DataConst or RightInfo.DataConst: if LeftInfo.DataConst or RightInfo.DataConst:
Result.DataConst = True Result.DataConst = True
if LeftInfo.VarConst or RightInfo.VarConst: if LeftInfo.VarConst or RightInfo.VarConst:
@@ -819,9 +811,9 @@ class TypeAnnotationResolver:
Result = CTypeInfo() Result = CTypeInfo()
BaseTypeSide = LeftInfo if not LeftInfo.DataConst else RightInfo BaseTypeSide = LeftInfo if not LeftInfo.DataConst else RightInfo
QualSide = LeftInfo if LeftInfo.DataConst else RightInfo QualSide = LeftInfo if LeftInfo.DataConst else RightInfo
Result.BaseType = BaseTypeSide.BaseType if BaseTypeSide.BaseType and (not isinstance(BaseTypeSide.BaseType, t.CVoid) or BaseTypeSide.PtrCount > 0) else QualSide.BaseType Result.BaseType = BaseTypeSide.BaseType if BaseTypeSide.BaseType and (not isinstance(BaseTypeSide.BaseType, TypeSystem.CVoid) or BaseTypeSide.PtrCount > 0) else QualSide.BaseType
if not Result.BaseType: if not Result.BaseType:
Result.BaseType = t.CInt() Result.BaseType = TypeSystem.CInt()
Result.DataConst = True Result.DataConst = True
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount) Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
if LeftInfo.VarConst or RightInfo.VarConst: if LeftInfo.VarConst or RightInfo.VarConst:
@@ -838,9 +830,9 @@ class TypeAnnotationResolver:
Result = CTypeInfo() Result = CTypeInfo()
BaseTypeSide = LeftInfo if not LeftInfo.DataVolatile else RightInfo BaseTypeSide = LeftInfo if not LeftInfo.DataVolatile else RightInfo
QualSide = LeftInfo if LeftInfo.DataVolatile else RightInfo QualSide = LeftInfo if LeftInfo.DataVolatile else RightInfo
Result.BaseType = BaseTypeSide.BaseType if BaseTypeSide.BaseType and (not isinstance(BaseTypeSide.BaseType, t.CVoid) or BaseTypeSide.PtrCount > 0) else QualSide.BaseType Result.BaseType = BaseTypeSide.BaseType if BaseTypeSide.BaseType and (not isinstance(BaseTypeSide.BaseType, TypeSystem.CVoid) or BaseTypeSide.PtrCount > 0) else QualSide.BaseType
if not Result.BaseType: if not Result.BaseType:
Result.BaseType = t.CInt() Result.BaseType = TypeSystem.CInt()
Result.DataVolatile = True Result.DataVolatile = True
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount) Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
if LeftInfo.VarConst or RightInfo.VarConst: if LeftInfo.VarConst or RightInfo.VarConst:
@@ -855,15 +847,15 @@ class TypeAnnotationResolver:
Result = CTypeInfo() Result = CTypeInfo()
BaseTypeSide = LeftInfo if not LeftInfo.Storage else RightInfo BaseTypeSide = LeftInfo if not LeftInfo.Storage else RightInfo
StorageSide = LeftInfo if LeftInfo.Storage else RightInfo StorageSide = LeftInfo if LeftInfo.Storage else RightInfo
# CExtern | CExport 等价于 t.State:两边都有 Storage 时设置 IsState # CExtern | CExport 等价于 State:两边都有 Storage 时设置 IsState
if BaseTypeSide.IsState or StorageSide.IsState or (LeftInfo.Storage and RightInfo.Storage): if BaseTypeSide.IsState or StorageSide.IsState or (LeftInfo.Storage and RightInfo.Storage):
Result.IsState = True Result.IsState = True
Result.BaseType = t.CVoid() Result.BaseType = TypeSystem.CVoid()
Result.Storage = LeftInfo.Storage if LeftInfo.Storage else RightInfo.Storage Result.Storage = LeftInfo.Storage if LeftInfo.Storage else RightInfo.Storage
return Result return Result
Result.BaseType = BaseTypeSide.BaseType if BaseTypeSide.BaseType and (not isinstance(BaseTypeSide.BaseType, t.CVoid) or BaseTypeSide.PtrCount > 0) else StorageSide.BaseType Result.BaseType = BaseTypeSide.BaseType if BaseTypeSide.BaseType and (not isinstance(BaseTypeSide.BaseType, TypeSystem.CVoid) or BaseTypeSide.PtrCount > 0) else StorageSide.BaseType
if not Result.BaseType: if not Result.BaseType:
Result.BaseType = t.CInt() Result.BaseType = TypeSystem.CInt()
Result.Storage = LeftInfo.Storage if LeftInfo.Storage else RightInfo.Storage Result.Storage = LeftInfo.Storage if LeftInfo.Storage else RightInfo.Storage
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount) Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
if LeftInfo.DataConst or RightInfo.DataConst: if LeftInfo.DataConst or RightInfo.DataConst:
@@ -872,32 +864,32 @@ class TypeAnnotationResolver:
Result.VarConst = True Result.VarConst = True
return Result return Result
# 检查是否有位域类型 (t.Bit) # 检查是否有位域类型 (Bit)
if LeftInfo.IsBitField: if LeftInfo.IsBitField:
Result = CTypeInfo() Result = CTypeInfo()
Result.BaseType = LeftInfo.BaseType if LeftInfo.BaseType else t.CInt() Result.BaseType = LeftInfo.BaseType if LeftInfo.BaseType else TypeSystem.CInt()
Result.IsBitField = True Result.IsBitField = True
Result.BitWidth = LeftInfo.BitWidth Result.BitWidth = LeftInfo.BitWidth
return Result return Result
if RightInfo.IsBitField: if RightInfo.IsBitField:
Result = CTypeInfo() Result = CTypeInfo()
Result.BaseType = RightInfo.BaseType if RightInfo.BaseType else t.CInt() Result.BaseType = RightInfo.BaseType if RightInfo.BaseType else TypeSystem.CInt()
Result.IsBitField = True Result.IsBitField = True
Result.BitWidth = RightInfo.BitWidth Result.BitWidth = RightInfo.BitWidth
return Result return Result
# 处理字节序类型 (t.BigEndian, t.LittleEndian) # 处理字节序类型 (BigEndian, LittleEndian)
# 合并两侧:保留非字节序侧的实际类型(如 CUInt64T),取字节序侧的 ByteOrder # 合并两侧:保留非字节序侧的实际类型(如 CUInt64T),取字节序侧的 ByteOrder
if LeftInfo.ByteOrder or RightInfo.ByteOrder: if LeftInfo.ByteOrder or RightInfo.ByteOrder:
Result = CTypeInfo() Result = CTypeInfo()
ByteOrderSide: CTypeInfo = LeftInfo if LeftInfo.ByteOrder else RightInfo ByteOrderSide: CTypeInfo = LeftInfo if LeftInfo.ByteOrder else RightInfo
OtherSide: CTypeInfo = RightInfo if LeftInfo.ByteOrder else LeftInfo OtherSide: CTypeInfo = RightInfo if LeftInfo.ByteOrder else LeftInfo
if OtherSide.BaseType and (not isinstance(OtherSide.BaseType, (t._CTypedef,)) or OtherSide.PtrCount > 0): if OtherSide.BaseType and (not isinstance(OtherSide.BaseType, (TypeSystem._CTypedef,)) or OtherSide.PtrCount > 0):
Result.BaseType = OtherSide.BaseType Result.BaseType = OtherSide.BaseType
elif ByteOrderSide.BaseType and (not isinstance(ByteOrderSide.BaseType, (t._CTypedef,)) or ByteOrderSide.PtrCount > 0): elif ByteOrderSide.BaseType and (not isinstance(ByteOrderSide.BaseType, (TypeSystem._CTypedef,)) or ByteOrderSide.PtrCount > 0):
Result.BaseType = ByteOrderSide.BaseType Result.BaseType = ByteOrderSide.BaseType
else: else:
Result.BaseType = t.CInt() Result.BaseType = TypeSystem.CInt()
Result.ByteOrder = LeftInfo.ByteOrder or RightInfo.ByteOrder Result.ByteOrder = LeftInfo.ByteOrder or RightInfo.ByteOrder
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount) Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
return Result return Result
@@ -915,7 +907,7 @@ class TypeAnnotationResolver:
return Result return Result
if LeftInfo.IsTypedef and RightInfo.BaseType: if LeftInfo.IsTypedef and RightInfo.BaseType:
if LeftInfo.BaseType and (not isinstance(LeftInfo.BaseType, (t._CTypedef,)) or LeftInfo.PtrCount > 0): if LeftInfo.BaseType and (not isinstance(LeftInfo.BaseType, (TypeSystem._CTypedef,)) or LeftInfo.PtrCount > 0):
Result = LeftInfo.Copy() Result = LeftInfo.Copy()
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount) Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
if RightInfo.Storage: if RightInfo.Storage:
@@ -923,7 +915,7 @@ class TypeAnnotationResolver:
return Result return Result
return RightInfo return RightInfo
if RightInfo.IsTypedef and LeftInfo.BaseType: if RightInfo.IsTypedef and LeftInfo.BaseType:
if RightInfo.BaseType and (not isinstance(RightInfo.BaseType, (t._CTypedef,)) or RightInfo.PtrCount > 0): if RightInfo.BaseType and (not isinstance(RightInfo.BaseType, (TypeSystem._CTypedef,)) or RightInfo.PtrCount > 0):
Result = RightInfo.Copy() Result = RightInfo.Copy()
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount) Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
if LeftInfo.Storage: if LeftInfo.Storage:
@@ -942,9 +934,9 @@ class TypeAnnotationResolver:
"""处理 ast.Subscript 节点""" """处理 ast.Subscript 节点"""
base: ast.AST = Node.value base: ast.AST = Node.value
if isinstance(base, ast.Attribute): if isinstance(base, ast.Attribute):
if isinstance(base.value, ast.Name) and IsTModule(base.value.id, SymbolTable) and base.attr == 'Bit': if isinstance(base.value, ast.Name) and base.attr == 'Bit':
Result: CTypeInfo = CTypeInfo() Result: CTypeInfo = CTypeInfo()
Result.BaseType = t.CInt() Result.BaseType = TypeSystem.CInt()
Result.IsBitField = True Result.IsBitField = True
if isinstance(Node.slice, ast.Constant) and isinstance(Node.slice.value, int): if isinstance(Node.slice, ast.Constant) and isinstance(Node.slice.value, int):
Result.BitWidth = Node.slice.value Result.BitWidth = Node.slice.value
@@ -972,14 +964,14 @@ class TypeAnnotationResolver:
else: else:
Result.PtrCount += 1 Result.PtrCount += 1
else: else:
# 单参数 t.CArray[T](= t.CArray[T, None]):长度自动推导数组。 # 单参数 CArray[T](= CArray[T, None]):长度自动推导数组。
# 指针位置语义为"元素指针" Ptr(T),需在元素类型上再加一层指针。 # 指针位置语义为"元素指针" Ptr(T),需在元素类型上再加一层指针。
# 与裸名 CArray[T](HandlesTypeMerge.CollectAll 的 # 与裸名 CArray[T](HandlesTypeMerge.CollectAll 的
# `ElementType.PtrCount + 1`)、stub 侧(LLVMTypeMapper # `ElementType.PtrCount + 1`)、stub 侧(LLVMTypeMapper
# IsListAnnotation 的 `elem_type + '*'`)、声明端 # IsListAnnotation 的 `elem_type + '*'`)、声明端
# (DeclarationGenerator `[0 x T]` → _decay_array_to_ptr = T*) # (DeclarationGenerator `[0 x T]` → _decay_array_to_ptr = T*)
# 以及 VPC(TypeGenResolve 单参 → Ptr(elem_ty))同口径。 # 以及 VPC(TypeGenResolve 单参 → Ptr(elem_ty))同口径。
# 此前缺这一层:t.CArray[str] 得 i8*(即 str 本身), # 此前缺这一层:CArray[str] 得 i8*(即 str 本身),
# result[k] 退化成 i8 → 写字符串指针触发 ptr→int fail-fast。 # result[k] 退化成 i8 → 写字符串指针触发 ptr→int fail-fast。
Result.PtrCount += 1 Result.PtrCount += 1
if ElemInfo.IsPtr and not ElemInfo.ArrayDims: if ElemInfo.IsPtr and not ElemInfo.ArrayDims:
@@ -987,7 +979,7 @@ class TypeAnnotationResolver:
return Result return Result
# 函数指针构造子的两种书写形态逐点等价(对齐 VPC # 函数指针构造子的两种书写形态逐点等价(对齐 VPC
# TypeGenResolve._IsCallableSubscriptValue): # TypeGenResolve._IsCallableSubscriptValue):
# t.Callable[...] / c.Callable[...] → 模块限定 Attribute # Callable[...] / Callable[...] → 模块限定 Attribute
# callable[...] / Callable[...] → 内建裸名(无需 import) # callable[...] / Callable[...] → 内建裸名(无需 import)
# 裸名形态此前落进下方泛型特化兜底(ResolveGenericClassSpecName)未命中 ⇒ # 裸名形态此前落进下方泛型特化兜底(ResolveGenericClassSpecName)未命中 ⇒
# 空 CTypeInfo ⇒ 槽位类型退化 i32(现场 Repl.vp:307 # 空 CTypeInfo ⇒ 槽位类型退化 i32(现场 Repl.vp:307
@@ -1005,9 +997,9 @@ class TypeAnnotationResolver:
# 裸名只在注解位置当函数指针构造子(非类型位置仍是普通标识符) # 裸名只在注解位置当函数指针构造子(非类型位置仍是普通标识符)
IsBareCallable = True IsBareCallable = True
if isinstance(base, ast.Attribute) or IsBareCallable: if isinstance(base, ast.Attribute) or IsBareCallable:
if (not IsBareCallable) and parts and IsTModule(parts[0], SymbolTable) and parts[-1] == t.CPtr.__name__: if (not IsBareCallable) and parts and parts[-1] == TypeSystem.CPtr.__name__:
Result: CTypeInfo = CTypeInfo() Result: CTypeInfo = CTypeInfo()
Result.BaseType = t.CVoid() Result.BaseType = TypeSystem.CVoid()
Result.PtrCount = 1 Result.PtrCount = 1
slice_node: ast.AST = Node.slice slice_node: ast.AST = Node.slice
if isinstance(slice_node, ast.Subscript): if isinstance(slice_node, ast.Subscript):
@@ -1015,25 +1007,25 @@ class TypeAnnotationResolver:
if InnerInfo: if InnerInfo:
if InnerInfo.PtrCount > 0: if InnerInfo.PtrCount > 0:
Result.PtrCount += InnerInfo.PtrCount Result.PtrCount += InnerInfo.PtrCount
if InnerInfo.BaseType and not isinstance(InnerInfo.BaseType, t.CVoid): if InnerInfo.BaseType and not isinstance(InnerInfo.BaseType, TypeSystem.CVoid):
Result.BaseType = InnerInfo.BaseType Result.BaseType = InnerInfo.BaseType
elif isinstance(slice_node, ast.Attribute): elif isinstance(slice_node, ast.Attribute):
SliceInfo: CTypeInfo = TypeAnnotationResolver.from_node(slice_node, SymbolTable) SliceInfo: CTypeInfo = TypeAnnotationResolver.from_node(slice_node, SymbolTable)
if SliceInfo: if SliceInfo:
if SliceInfo.IsPtr: if SliceInfo.IsPtr:
Result.PtrCount += SliceInfo.PtrCount Result.PtrCount += SliceInfo.PtrCount
elif SliceInfo.BaseType and not isinstance(SliceInfo.BaseType, t.CVoid): elif SliceInfo.BaseType and not isinstance(SliceInfo.BaseType, TypeSystem.CVoid):
Result.BaseType = SliceInfo.BaseType Result.BaseType = SliceInfo.BaseType
elif isinstance(slice_node, ast.Name): elif isinstance(slice_node, ast.Name):
SliceType: type | None = getattr(t, slice_node.id, None) SliceType: type | None = getattr(TypeSystem, slice_node.id, None)
if SliceType == t.CPtr: if SliceType == TypeSystem.CPtr:
Result.PtrCount += 1 Result.PtrCount += 1
else: else:
SliceInfo = TypeAnnotationResolver.from_node(slice_node, SymbolTable) SliceInfo = TypeAnnotationResolver.from_node(slice_node, SymbolTable)
if SliceInfo and SliceInfo.BaseType and not isinstance(SliceInfo.BaseType, t.CVoid): if SliceInfo and SliceInfo.BaseType and not isinstance(SliceInfo.BaseType, TypeSystem.CVoid):
Result.BaseType = SliceInfo.BaseType Result.BaseType = SliceInfo.BaseType
return Result return Result
if IsBareCallable or (parts and IsTModule(parts[0], SymbolTable) and parts[-1] == 'Callable'): if IsBareCallable or (parts and parts[-1] == 'Callable'):
Result = CTypeInfo() Result = CTypeInfo()
Result.IsFuncPtr = True Result.IsFuncPtr = True
slice_node = Node.slice slice_node = Node.slice
@@ -1047,14 +1039,14 @@ class TypeAnnotationResolver:
ParamTypeInfo = TypeAnnotationResolver.from_node(elt, SymbolTable) ParamTypeInfo = TypeAnnotationResolver.from_node(elt, SymbolTable)
if ParamTypeInfo: if ParamTypeInfo:
ParamTypes.append(('', ParamTypeInfo)) ParamTypes.append(('', ParamTypeInfo))
# 空参数表 `t.Callable[[], R]` 语义 = 零形参:LLVM 端即 `R ()*`, # 空参数表 `Callable[[], R]` 语义 = 零形参:LLVM 端即 `R ()*`,
# 调用点按零实参间接 call。此前在此注入 void 占位形参 → 得 # 调用点按零实参间接 call。此前在此注入 void 占位形参 → 得
# `R (void)*`(void 作形参本身不是合法 LLVM 函数类型),调用点 # `R (void)*`(void 作形参本身不是合法 LLVM 函数类型),调用点
# 实参个数(0) 与形参个数(1) 不符 → llvmlite CallInstr # 实参个数(0) 与形参个数(1) 不符 → llvmlite CallInstr
# `arg = args[i]` IndexError(Repl.vp 模块级 t.Callable 槽 # `arg = args[i]` IndexError(Repl.vp 模块级 Callable 槽
# `ReplFragFn()` 翻译崩溃根因);与本文件另三处 Callable 形态 # `ReplFragFn()` 翻译崩溃根因);与本文件另三处 Callable 形态
# (:378 / :422 / :471)的 `FuncPtrParams = []` 口径统一。 # (:378 / :422 / :471)的 `FuncPtrParams = []` 口径统一。
# 非 List 形态(遗留写法 t.Callable[A, R])保留原 void 占位行为。 # 非 List 形态(遗留写法 Callable[A, R])保留原 void 占位行为。
if not ParamTypes and not _ParamsIsList: if not ParamTypes and not _ParamsIsList:
ParamTypes.append(('', TypeAnnotationResolver.from_type_name('void'))) ParamTypes.append(('', TypeAnnotationResolver.from_type_name('void')))
Result.FuncPtrParams = ParamTypes Result.FuncPtrParams = ParamTypes
@@ -1062,7 +1054,7 @@ class TypeAnnotationResolver:
Result.FuncPtrReturn = ReturnTypeInfo if ReturnTypeInfo else CTypeInfo.VoidTypeInfo() Result.FuncPtrReturn = ReturnTypeInfo if ReturnTypeInfo else CTypeInfo.VoidTypeInfo()
return Result return Result
# [builtins 最后匹配] 裸名 builtins typedef 下标(rawptr[int] → Ptr(int)): # [builtins 最后匹配] 裸名 builtins typedef 下标(rawptr[int] → Ptr(int)):
# 与 VPC Subscript 分支同口径——base 是 builtins typedef(rawptr → t.CPtr), # 与 VPC Subscript 分支同口径——base 是 builtins typedef(rawptr → CPtr),
# 结果 = 切片类型外包 base 的指针层数。 # 结果 = 切片类型外包 base 的指针层数。
if isinstance(base, ast.Name): if isinstance(base, ast.Name):
base_info: CTypeInfo | None = TypeAnnotationResolver._lookup_builtins_typedef(base.id, SymbolTable) base_info: CTypeInfo | None = TypeAnnotationResolver._lookup_builtins_typedef(base.id, SymbolTable)
@@ -1070,16 +1062,16 @@ class TypeAnnotationResolver:
slice_node = Node.slice slice_node = Node.slice
SliceInfo = TypeAnnotationResolver.from_node(slice_node, SymbolTable) SliceInfo = TypeAnnotationResolver.from_node(slice_node, SymbolTable)
Result = CTypeInfo() Result = CTypeInfo()
Result.BaseType = SliceInfo.BaseType if (SliceInfo and SliceInfo.BaseType) else t.CVoid() Result.BaseType = SliceInfo.BaseType if (SliceInfo and SliceInfo.BaseType) else TypeSystem.CVoid()
Result.PtrCount = (SliceInfo.PtrCount if SliceInfo else 0) + base_info.PtrCount Result.PtrCount = (SliceInfo.PtrCount if SliceInfo else 0) + base_info.PtrCount
return Result return Result
# 泛型类下标(单/多参):list[str] / dict[str][int] / 用户泛型 Box[Node]。 # 泛型类下标(单/多参):list[str] / dict[str][int] / 用户泛型 Box[Node]。
# 特化名与声明端(DeclarationGenerator 泛型分支)同口径,见 # 特化名与声明端(DeclarationGenerator 泛型分支)同口径,见
# SymbolUtils.ResolveGenericClassSpecName。此前单参泛型下标在下方直接落到 # SymbolUtils.ResolveGenericClassSpecName。此前单参泛型下标在下方直接落到
# "未知类型"空 CTypeInfo ⇒ 形参/成员类型退化成 i32 或 void 指针链 # "未知类型"空 CTypeInfo ⇒ 形参/成员类型退化成 i32 或 void 指针链
# (现场:type_args: list[str]* 的形参 i32;CTypedefNames: list[str] | t.CPtr → i8*)。 # (现场:type_args: list[str]* 的形参 i32;CTypedefNames: list[str] | CPtr → i8*)。
# 表示口径与本文件既有结构体 promotion 逐字一致(BaseType=CStruct + IsStruct + # 表示口径与本文件既有结构体 promotion 逐字一致(BaseType=CStruct + IsStruct +
# Name,PtrCount 保持 0):`X | t.CPtr` 由 _from_node_binop 取 max → 1 层, # Name,PtrCount 保持 0):`X | CPtr` 由 _from_node_binop 取 max → 1 层,
# `rawptr[X]` 由上方分支 +1 → 1 层,均与 declare 侧 %"{sha}.X[*]"* 一致。 # `rawptr[X]` 由上方分支 +1 → 1 层,均与 declare 侧 %"{sha}.X[*]"* 一致。
_Spec: str | None = ResolveGenericClassSpecName( _Spec: str | None = ResolveGenericClassSpecName(
Node, SymbolTable, Node, SymbolTable,
@@ -1087,7 +1079,7 @@ class TypeAnnotationResolver:
GetTCAliasMapFromSymtab(SymbolTable)) GetTCAliasMapFromSymtab(SymbolTable))
if _Spec: if _Spec:
Result = CTypeInfo() Result = CTypeInfo()
Result.BaseType = t.CStruct(name=_Spec) Result.BaseType = TypeSystem.CStruct(name=_Spec)
Result.IsStruct = True Result.IsStruct = True
Result.Name = _Spec Result.Name = _Spec
return Result return Result
@@ -1116,6 +1108,10 @@ class TypeAnnotationResolver:
else: else:
return CTypeInfo() return CTypeInfo()
if isinstance(Current, ast.Name) and Current.id in ("t", "c"):
raise TypeError(
f"[TPC] 类型注解不再接受 \"{Current.id}.\" 模块前缀;"
f"请直接写内建类型名(如 CPtr、CInt、CArray)。")
# 解析 import 别名: 如 import vpsdk.window as window -> window -> vpsdk.window # 解析 import 别名: 如 import vpsdk.window as window -> window -> vpsdk.window
if ModulePath: if ModulePath:
resolved: bool = False resolved: bool = False
@@ -1130,77 +1126,6 @@ class TypeAnnotationResolver:
if resolved_name: if resolved_name:
ModulePath = resolved_name ModulePath = resolved_name
if ModulePath and IsTModulePath(ModulePath):
# 值引用参数标记(CRef = `&T`、CTempRef = `&temp T`):非真实类,仅按名字
# 识别为「一层指针」(与 t.CPtr 同形),使联合形态 `T | t.CRef` 解析为 T*、
# `void | t.CRef` 解析为 void*(i8*)。模式语义(ref/temp)由注解侧识别。
if TypeName in ('CRef', 'CTempRef'):
Info: CTypeInfo = CTypeInfo()
Info.PtrCount = 1
Info.BaseType = t.CVoid
return Info
TypeClass: type | None = CTypeHelper.GetTModuleCType(TypeName)
if TypeClass is None:
TypeClass = getattr(t, TypeName, None)
if TypeClass is not None and TypeClass.HasPosition(t.CType.POINTER):
Info: CTypeInfo = CTypeInfo()
Info.PtrCount = 1
if TypeClass == t.CArrayPtr:
Info.IsArrayPtr = True
Info.BaseType = t.CVoid
return Info
if TypeClass is not None and TypeClass.IsStorageClass():
Info: CTypeInfo = CTypeInfo()
Info.Storage = TypeClass()
if TypeClass == t.State:
Info.IsState = True
Info.BaseType = t.CVoid()
return Info
if TypeClass is not None and TypeClass.IsTypeQualifier():
Info: CTypeInfo = CTypeInfo()
if TypeClass == t.CConst:
Info.DataConst = True
elif TypeClass == t.CVolatile:
Info.DataVolatile = True
return Info
if TypeClass is not None and TypeClass in (t.BigEndian, t.LittleEndian):
Result: CTypeInfo = CTypeInfo()
Result.BaseType = t.CInt()
Result.ByteOrder = 'big' if TypeClass == t.BigEndian else 'little'
return Result
if (TypeClass is not None
and isinstance(TypeClass, type)
and issubclass(TypeClass, t.CType)
and TypeClass is not t.CType
and TypeClass.HasPosition(t.CType.BASE)):
if TypeClass == t.State:
Result: CTypeInfo = CTypeInfo()
Result.IsState = True
Result.BaseType = t.CVoid()
return Result
Inst: t.CType = TypeClass()
Result: CTypeInfo = CTypeInfo()
Result.BaseType = TypeClass
Result.Name = type(Inst).__name__
if hasattr(Inst, 'IsSigned'):
Result.IsSigned = Inst.IsSigned
return Result
CNAME: str | None = CTypeHelper.GetCName(TypeName)
if CNAME:
return TypeAnnotationResolver.from_type_name(CNAME)
# 处理字节序类型
if TypeName == 'BigEndian':
Result = CTypeInfo()
Result.BaseType = t.CInt()
Result.ByteOrder = 'big'
return Result
if TypeName == 'LittleEndian':
Result = CTypeInfo()
Result.BaseType = t.CInt()
Result.ByteOrder = 'little'
return Result
FullName: str = f"{ModulePath}.{TypeName}" if ModulePath else TypeName FullName: str = f"{ModulePath}.{TypeName}" if ModulePath else TypeName
if TypeName in SymbolTable: if TypeName in SymbolTable:
@@ -1208,24 +1133,24 @@ class TypeAnnotationResolver:
if Entry and Entry.IsTypedef: if Entry and Entry.IsTypedef:
Resolved: CTypeInfo = Entry.Copy() Resolved: CTypeInfo = Entry.Copy()
if Resolved.BaseType is None: if Resolved.BaseType is None:
Resolved.BaseType = t._CTypedef(TypeName) Resolved.BaseType = TypeSystem._CTypedef(TypeName)
return Resolved return Resolved
if Entry and Entry.IsEnum: if Entry and Entry.IsEnum:
Result: CTypeInfo = CTypeInfo() Result: CTypeInfo = CTypeInfo()
Result.BaseType = t.CInt() Result.BaseType = TypeSystem.CInt()
Result.IsEnum = True Result.IsEnum = True
Result.Name = TypeName Result.Name = TypeName
return Result return Result
if Entry and Entry.IsExceptionClass: if Entry and Entry.IsExceptionClass:
Result: CTypeInfo = CTypeInfo() Result: CTypeInfo = CTypeInfo()
Result.BaseType = t.CInt() Result.BaseType = TypeSystem.CInt()
Result.IsExceptionClass = True Result.IsExceptionClass = True
Result.Name = TypeName Result.Name = TypeName
return Result return Result
if Entry: if Entry:
Result: CTypeInfo = Entry.Copy() Result: CTypeInfo = Entry.Copy()
if Result.BaseType is None and (Result.IsStruct or Result.IsCpythonObject or Result.Name): if Result.BaseType is None and (Result.IsStruct or Result.IsCpythonObject or Result.Name):
Result.BaseType = t.CStruct(name=TypeName) Result.BaseType = TypeSystem.CStruct(name=TypeName)
Result.IsStruct = True Result.IsStruct = True
if (Result.BaseType is None and not Result.IsStruct and not Result.IsEnum if (Result.BaseType is None and not Result.IsStruct and not Result.IsEnum
and not Result.IsTypedef and not Result.IsCpythonObject and not Result.Name): and not Result.IsTypedef and not Result.IsCpythonObject and not Result.Name):
@@ -1251,7 +1176,7 @@ class TypeAnnotationResolver:
# 命名口径见 HandlesClassDef._EmitNestedClassDefs —— 嵌套类以扁平名 # 命名口径见 HandlesClassDef._EmitNestedClassDefs —— 嵌套类以扁平名
# `{外类}_{内类}` 发射,并由 _RegisterNestedClassName 把扁平名与 `外类.内类` # `{外类}_{内类}` 发射,并由 _RegisterNestedClassName 把扁平名与 `外类.内类`
# 一并插入 SymbolTable。本分支按**扁平名**取条目:BaseType/Name 必须是扁平名 # 一并插入 SymbolTable。本分支按**扁平名**取条目:BaseType/Name 必须是扁平名
# (若走下方 FullName 分支,会按短名拼出 `t.CStruct(name='Inner')`,与 # (若走下方 FullName 分支,会按短名拼出 `CStruct(name='Inner')`,与
# 声明端的 `%"{sha}.外类_内类"` 不同源 ⇒ 布局/字段偏移分叉)。 # 声明端的 `%"{sha}.外类_内类"` 不同源 ⇒ 布局/字段偏移分叉)。
if ModulePath and TypeName: if ModulePath and TypeName:
NestedKey: str = f"{ModulePath}_{TypeName}" NestedKey: str = f"{ModulePath}_{TypeName}"
@@ -1261,7 +1186,7 @@ class TypeAnnotationResolver:
Result = NestedEntry.Copy() Result = NestedEntry.Copy()
Result.Name = NestedKey Result.Name = NestedKey
if Result.BaseType is None: if Result.BaseType is None:
Result.BaseType = t.CStruct(name=NestedKey) Result.BaseType = TypeSystem.CStruct(name=NestedKey)
Result.IsStruct = True Result.IsStruct = True
return Result return Result
@@ -1269,7 +1194,7 @@ class TypeAnnotationResolver:
Info: CTypeInfo = SymbolTable[FullName] Info: CTypeInfo = SymbolTable[FullName]
if Info and Info.IsTypedef: if Info and Info.IsTypedef:
# 优先用 BaseType 解析(如 VOIDPTR 已解析为 BaseType=CVoid, PtrCount=1) # 优先用 BaseType 解析(如 VOIDPTR 已解析为 BaseType=CVoid, PtrCount=1)
if Info.BaseType and (not isinstance(Info.BaseType, (t._CTypedef,)) or Info.PtrCount > 0): if Info.BaseType and (not isinstance(Info.BaseType, (TypeSystem._CTypedef,)) or Info.PtrCount > 0):
Result = Info.Copy() Result = Info.Copy()
Result.IsTypedef = True Result.IsTypedef = True
Result.Name = FullName Result.Name = FullName
@@ -1304,14 +1229,14 @@ class TypeAnnotationResolver:
return Resolved return Resolved
# 回退:保持原逻辑但设置 Name = FullName(供后续 TypeConvert 查找) # 回退:保持原逻辑但设置 Name = FullName(供后续 TypeConvert 查找)
Result: CTypeInfo = CTypeInfo() Result: CTypeInfo = CTypeInfo()
Result.BaseType = t._CTypedef(TypeName) Result.BaseType = TypeSystem._CTypedef(TypeName)
Result.IsTypedef = True Result.IsTypedef = True
Result.Name = FullName Result.Name = FullName
return Result return Result
if Info: if Info:
Result: CTypeInfo = Info.Copy() Result: CTypeInfo = Info.Copy()
if Result.BaseType is None and (Result.IsStruct or Result.IsCpythonObject or Result.Name): if Result.BaseType is None and (Result.IsStruct or Result.IsCpythonObject or Result.Name):
Result.BaseType = t.CStruct(name=TypeName) Result.BaseType = TypeSystem.CStruct(name=TypeName)
Result.IsStruct = True Result.IsStruct = True
return Result return Result
return CTypeInfo() return CTypeInfo()
+8 -8
View File
@@ -20,7 +20,7 @@ from typing import TYPE_CHECKING, List, Dict, Tuple, Any, Optional
if TYPE_CHECKING: if TYPE_CHECKING:
from lib.core.Handles.HandlesBase import CTypeInfo from lib.core.Handles.HandlesBase import CTypeInfo
from lib.includes import t from lib.core import TypeSystem
class SymbolKind(enum.Enum): class SymbolKind(enum.Enum):
@@ -135,14 +135,14 @@ class TypeSpec:
) )
def __init__(self): def __init__(self):
self._base_type: t.CType | tuple | None = None # t.CType 实例或 tuple self._base_type: TypeSystem.CType | tuple | None = None # CType 实例或 tuple
self.ptr_count: int = 0 self.ptr_count: int = 0
self.var_const: bool = False self.var_const: bool = False
self.var_volatile: bool = False self.var_volatile: bool = False
self.data_const: bool = False self.data_const: bool = False
self.data_volatile: bool = False self.data_volatile: bool = False
self.array_dims: List[str] = [] self.array_dims: List[str] = []
self.storage: t.CType | None = None # t.CType (CStatic/CExtern/CExport 等) self.storage: TypeSystem.CType | None = None # CType (CStatic/CExtern/CExport 等)
self.is_func_ptr: bool = False self.is_func_ptr: bool = False
self.func_ptr_params: List[Tuple[str, CTypeInfo]] = [] # (参数名, CTypeInfo) self.func_ptr_params: List[Tuple[str, CTypeInfo]] = [] # (参数名, CTypeInfo)
self.func_param_names: List[str] = [] self.func_param_names: List[str] = []
@@ -158,11 +158,11 @@ class TypeSpec:
self.is_signed: Optional[bool] = None # None = 未设置, True/False = 有符号/无符号 self.is_signed: Optional[bool] = None # None = 未设置, True/False = 有符号/无符号
@property @property
def base_type(self) -> t.CType | tuple | None: def base_type(self) -> TypeSystem.CType | tuple | None:
return self._base_type return self._base_type
@base_type.setter @base_type.setter
def base_type(self, value: t.CType | tuple | None): def base_type(self, value: TypeSystem.CType | tuple | None):
"""设置 BaseType,与 CTypeInfo.BaseType setter 逻辑一致(不含 kind 副作用)""" """设置 BaseType,与 CTypeInfo.BaseType setter 逻辑一致(不含 kind 副作用)"""
if value is None: if value is None:
self._base_type = None self._base_type = None
@@ -172,16 +172,16 @@ class TypeSpec:
self._base_type = tuple(value) self._base_type = tuple(value)
return return
if isinstance(value, type) and issubclass(value, t.CType): if isinstance(value, type) and issubclass(value, TypeSystem.CType):
self._base_type = value() self._base_type = value()
return return
if isinstance(value, t.CType): if isinstance(value, TypeSystem.CType):
self._base_type = value self._base_type = value
return return
raise TypeError( raise TypeError(
f"base_type must be t.CType instance, type subclass, or tuple of t.CType, got {type(value)}" f"base_type must be CType instance, type subclass, or tuple of CType, got {type(value)}"
) )
def copy(self) -> TypeSpec: def copy(self) -> TypeSpec:
+168 -27
View File
@@ -1,13 +1,14 @@
# 类型定义模块 """TPC 内建类型模型。
源码注解只使用内建类型名(`CPtr`、`CInt`、`CArray` 等);本模块是这些名字在
编译器内部的唯一表示,包含类型元属性、平台位宽和类型注册表。
"""
from __future__ import annotations from __future__ import annotations
import sys import sys
import types import types
from typing import Any, ClassVar, Optional, TypeVar, Generic, TypeAlias, Callable from typing import Any, ClassVar, Optional, TypeVar, Generic, TypeAlias, Callable
from lib.constants.config import mode as _ConfigMode
from lib.core.VLogger import get_logger as _vlog
# ============================================================================= # =============================================================================
# 类型映射常量 # 类型映射常量
@@ -129,7 +130,7 @@ class CType:
return [self, other] return [self, other]
def __set_default__(self, **kwargs: Any) -> CTypeDefault: def __set_default__(self, **kwargs: Any) -> CTypeDefault:
"""设置默认值/初始值,用于 static/global 变量的初始化 """设置默认值/初始值,用于 static/global 变量的初始化。
Args: Args:
**kwargs: 成员名称和值的键值对 **kwargs: 成员名称和值的键值对
@@ -342,7 +343,7 @@ def CVTable() -> None:
def NoVTable() -> None: def NoVTable() -> None:
"""标记类为非多态继承基类:被子类继承时字段直接展平嵌入,不生成 vtable,避免 vtable 开销。 """标记类为非多态继承基类:被子类继承时字段直接展平嵌入,不生成 vtable,避免 vtable 开销。
区别于 @t.CVTable(启用多态 vtable)。对应 C++ 的非多态继承(struct A : B {} 无 virtual)。""" 区别于 @CVTable(启用多态 vtable)。对应 C++ 的非多态继承(struct A : B {} 无 virtual)。"""
pass pass
def TLS() -> None: def TLS() -> None:
@@ -467,6 +468,118 @@ class CUInt64T(CType):
self.IsSigned: bool = False self.IsSigned: bool = False
self.Size: int = 64 self.Size: int = 64
class CIntFast8T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = 8
class CIntFast16T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = 16
class CIntFast32T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = 32
class CIntFast64T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = 64
class CUIntFast8T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 8
class CUIntFast16T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 16
class CUIntFast32T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 32
class CUIntFast64T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 64
class CIntLeast8T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = 8
class CIntLeast16T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = 16
class CIntLeast32T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = 32
class CIntLeast64T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = True
self.Size: int = 64
class CUIntLeast8T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 8
class CUIntLeast16T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 16
class CUIntLeast32T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 32
class CUIntLeast64T(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None:
super().__init__(value)
self.IsSigned: bool = False
self.Size: int = 64
class CIntPtrT(CType): class CIntPtrT(CType):
position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None: def __init__(self, value: Any = None) -> None:
@@ -540,9 +653,9 @@ class CAutoPtr(CPtr):
super().__init__(value) super().__init__(value)
class CTypeDefault(CType): class CTypeDefault(CType):
"""用于存储 C 类型默认值/初始化的包装类 """用于存储 C 类型默认值/初始化的包装类。
当使用 t.CStatic.__set_default__(open=mouse_open, ...) 时创建 当使用 CStatic.__set_default__(open=mouse_open, ...) 时创建。
""" """
def __init__(self, BaseType: Any, **kwargs: Any) -> None: def __init__(self, BaseType: Any, **kwargs: Any) -> None:
super().__init__() super().__init__()
@@ -560,8 +673,9 @@ class CArrayPtr(CType):
class CArray(CType): class CArray(CType):
"""栈上固定数组类型注解。 """栈上固定数组类型注解。
用法: names: t.CArray[VOIDPTR, 32] # void*[32]
data: t.CArray[t.CInt, 64] # int[64] 用法: names: CArray[rawptr, 32] # void*[32]
data: CArray[int, 64] # int[64]
第一个参数为元素类型,第二个参数为数组大小(整数或常量名)。""" 第一个参数为元素类型,第二个参数为数组大小(整数或常量名)。"""
position: ClassVar[frozenset[str]] = frozenset({CType.ARRAY}) position: ClassVar[frozenset[str]] = frozenset({CType.ARRAY})
def __init__(self, value: Any = None) -> None: def __init__(self, value: Any = None) -> None:
@@ -570,13 +684,11 @@ class CArray(CType):
return cls return cls
class CDefine(CType): class CDefine(CType):
"""编译期常量定义标记(X: t.CDefine = 64)。 """编译期常量定义标记(`X: CDefine = 64`)。
Size/IsSigned 覆盖为 32 位有符号整数(2026-08-10 修复):基类 __init__ Size/IsSigned 固定为 32 位有符号整数:基类会把两者置 None,推导结果为
将 Size/IsSigned 置 None,导致 CTypeToLLVM(CDefine) 推导为 'void', `void`,使类字段注解在结构体中生成非法 void 成员。语义上 CDefine 常量
类字段注解 t.CDefine(如 Mixin 的常量声明)在 stub 生成时变成 void, 即为 int;超大值由 TypeConvert 按 DefineValue 升 i64。
LLVM struct 含 void 报 "void type only allowed for function results"。
语义上 CDefine 常量即为 int;超大值由 TypeConvert 按 DefineValue 升 i64。
""" """
position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) position: ClassVar[frozenset[str]] = frozenset({CType.BASE})
def __init__(self, value: Any = None) -> None: def __init__(self, value: Any = None) -> None:
@@ -595,8 +707,8 @@ class State(CType):
@staticmethod @staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 t.State() 调用""" """处理 State() 调用"""
return ['t.State'] return ['State']
class Postdefinition: class Postdefinition:
def __init__(self, c: Any) -> None: def __init__(self, c: Any) -> None:
@@ -614,7 +726,7 @@ class BigEndian(CType):
用法示例: 用法示例:
class MyStruct: class MyStruct:
a: t.CInt | t.BigEndian # 大端序存储的整数 a: CInt | BigEndian # 大端序存储的整数
""" """
IsSigned: ClassVar[bool] = True IsSigned: ClassVar[bool] = True
Size: ClassVar[int] = 32 Size: ClassVar[int] = 32
@@ -628,7 +740,7 @@ class LittleEndian(CType):
用法示例: 用法示例:
class MyStruct: class MyStruct:
b: t.CInt | t.LittleEndian # 小端序存储的整数 b: CInt | LittleEndian # 小端序存储的整数
""" """
IsSigned: ClassVar[bool] = True IsSigned: ClassVar[bool] = True
Size: ClassVar[int] = 32 Size: ClassVar[int] = 32
@@ -991,7 +1103,7 @@ class attr:
"""LLVM 函数属性描述符 """LLVM 函数属性描述符
用于在返回类型注解中指定 LLVM 函数属性。 用于在返回类型注解中指定 LLVM 函数属性。
例如: def foo() -> t.CInt | t.attr.llvm.nobuiltin | t.attr.llvm.nounwind: 例如: def foo() -> CInt | attr.llvm.nobuiltin | attr.llvm.nounwind:
""" """
# 以下空类仅作为类型注解占位符使用,由 HandlesFunctions._GetAttrLLVMName # 以下空类仅作为类型注解占位符使用,由 HandlesFunctions._GetAttrLLVMName
@@ -1011,13 +1123,34 @@ class attr:
class inaccessiblemem_or_argmemonly: pass class inaccessiblemem_or_argmemonly: pass
# 内建类型的源码书写名:这些名字由编译器直接识别,不依赖任何导入或 typedef。
BUILTIN_TYPE_ALIASES: dict[str, type] = {
'sizet': CSizeT, 'size_t': CSizeT,
'int8': CInt8T, 'int16': CInt16T, 'int32': CInt32T, 'int64': CInt64T,
'uint8': CUInt8T, 'uint16': CUInt16T, 'uint32': CUInt32T, 'uint64': CUInt64T,
'intfast8': CIntFast8T, 'intfast16': CIntFast16T,
'intfast32': CIntFast32T, 'intfast64': CIntFast64T,
'uintfast8': CUIntFast8T, 'uintfast16': CUIntFast16T,
'uintfast32': CUIntFast32T, 'uintfast64': CUIntFast64T,
'intleast8': CIntLeast8T, 'intleast16': CIntLeast16T,
'intleast32': CIntLeast32T, 'intleast64': CIntLeast64T,
'uintleast8': CUIntLeast8T, 'uintleast16': CUIntLeast16T,
'uintleast32': CUIntLeast32T, 'uintleast64': CUIntLeast64T,
'uchar': CUnsignedChar,
'short': CInt16T, 'ushort': CUInt16T, 'uint': CUnsignedInt,
'long': CInt32T, 'ulong': CUInt32T,
'longlong': CInt64T, 'ulonglong': CUInt64T,
'ptrdifft': CPtrDiffT,
}
class CTypeRegistry: class CTypeRegistry:
"""基于 CType 元属性的类型注册表,替代手动映射表 """基于 CType 元属性的类型注册表,替代手动映射表
利用 CType 子类的 position/IsSigned/Size 元属性自动推导: 利用 CType 子类的 position/IsSigned/Size 元属性自动推导:
- LLVM IR 类型字符串 (如 'i32', 'double', 'i8*') - LLVM IR 类型字符串 (如 'i32', 'double', 'i8*')
- C 类型名称 (如 'int', 'unsigned char', 'long long') - C 类型名称 (如 'int', 'unsigned char', 'long long')
- Python CType 类引用 (如 t.CInt32T) - Python CType 类引用 (如 CInt32T)
""" """
_name_to_class: ClassVar[Optional[dict[str, type]]] = None _name_to_class: ClassVar[Optional[dict[str, type]]] = None
@@ -1052,7 +1185,7 @@ class CTypeRegistry:
@classmethod @classmethod
def GetClassByName(cls, name: str) -> Optional[type]: def GetClassByName(cls, name: str) -> Optional[type]:
"""根据 Python 类名获取 CType 类 (如 'CInt32T' -> t.CInt32T)""" """根据 Python 类名获取 CType 类 (如 'CInt32T' -> CInt32T)"""
cls._build() cls._build()
return cls._name_to_class.get(name) return cls._name_to_class.get(name)
@@ -1114,6 +1247,9 @@ class CTypeRegistry:
未知类型返回 None。 未知类型返回 None。
""" """
cls._build() cls._build()
alias: Optional[type] = BUILTIN_TYPE_ALIASES.get(name)
if alias is not None:
return cls.CTypeToLLVM(alias)
mod: Optional[types.ModuleType] = sys.modules.get(__name__) mod: Optional[types.ModuleType] = sys.modules.get(__name__)
if mod and hasattr(mod, name): if mod and hasattr(mod, name):
obj: Any = getattr(mod, name) obj: Any = getattr(mod, name)
@@ -1126,17 +1262,22 @@ class CTypeRegistry:
"""解析类型名到 (CType类, 指针层级) """解析类型名到 (CType类, 指针层级)
支持的格式: 支持的格式:
- Python 类名: 'CInt32T' -> (t.CInt32T, 0) - Python 类名: 'CInt32T' -> (CInt32T, 0)
- C 基本类型名/Python 内置名: 'int' -> (t.CInt, 0), 'bool' -> (t.CBool, 0) - C 基本类型名/Python 内置名: 'int' -> (CInt, 0), 'bool' -> (CBool, 0)
注意:stdint.h 类型名(int8_t/uint8_t/size_t/intptr_t 等)和 注意:stdint.h 类型名(int8_t/uint8_t/size_t/intptr_t 等)和
Win32 大写别名(INT8/UINT8/BYTE/DWORD/FLOAT8 等)由 stdint.py Win32 大写别名(INT8/UINT8/BYTE/DWORD/FLOAT8 等)由 stdint.py
通过 t.CTypedef 提供,用户 `from stdint import *` 后即可使用。 通过 CTypedef 提供,用户 `from stdint import *` 后即可使用。
指针必须使用 t.CPtr[T] 显式表达(如 t.CPtr[t.CInt]), 指针必须使用 CPtr[T] 显式表达(如 CPtr[CInt]),
本方法不再做 PTR 后缀的隐式类型推断,以避免违反类型自由原则。 本方法不再做 PTR 后缀的隐式类型推断,以避免违反类型自由原则。
""" """
cls._build() cls._build()
alias: Optional[type] = BUILTIN_TYPE_ALIASES.get(name)
if alias is not None:
pos: frozenset[str] = getattr(alias, 'position', frozenset())
ptr_level: int = 1 if CType.POINTER in pos and CType.BASE not in pos else 0
return (alias, ptr_level)
direct: Optional[type] = cls._name_to_class.get(name) direct: Optional[type] = cls._name_to_class.get(name)
if direct is not None: if direct is not None:
pos: frozenset[str] = getattr(direct, 'position', frozenset()) pos: frozenset[str] = getattr(direct, 'position', frozenset())
+40 -45
View File
@@ -48,40 +48,40 @@ class CTypeMapper:
# 不再依赖运行时 CTypeRegistry._cname_to_class(该映射已删除)。 # 不再依赖运行时 CTypeRegistry._cname_to_class(该映射已删除)。
_CNAME_TO_PY: dict[str, str] = { _CNAME_TO_PY: dict[str, str] = {
# 基本类型 # 基本类型
'char': 't.CChar', 'int': 't.CInt', 'short': 't.CShort', 'char': 'CChar', 'int': 'CInt', 'short': 'CShort',
'long': 't.CLong', 'long long': 't.CLongLong', 'long': 'CLong', 'long long': 'CLongLong',
'float': 't.CFloat', 'double': 't.CDouble', 'void': 't.CVoid', 'float': 'CFloat', 'double': 'CDouble', 'void': 'CVoid',
# unsigned / signed 变体 # unsigned / signed 变体
'unsigned': 't.CUnsigned', 'unsigned char': 't.CUnsignedChar', 'unsigned': 'CUnsigned', 'unsigned char': 'CUnsignedChar',
'unsigned int': 't.CUnsignedInt', 'unsigned short': 't.CUnsignedShort', 'unsigned int': 'CUnsignedInt', 'unsigned short': 'CUnsignedShort',
'unsigned long': 't.CUnsignedLong', 'unsigned long': 'CUnsignedLong',
'unsigned long long': 't.CUnsignedLongLong', 'unsigned long long': 'CUnsignedLongLong',
'signed char': 't.CSignedChar', 'signed char': 'CSignedChar',
# bool / size_t # bool / size_t
'bool': 't.CBool', '_Bool': 't.CBool', 'size_t': 't.CSizeT', 'bool': 'CBool', '_Bool': 'CBool', 'size_t': 'CSizeT',
'ssize_t': 't.CLong', 'ssize_t': 'CLong',
# stdint 固定宽度类型 # stdint 固定宽度类型
'int8_t': 't.CInt8T', 'int16_t': 't.CInt16T', 'int8_t': 'CInt8T', 'int16_t': 'CInt16T',
'int32_t': 't.CInt32T', 'int64_t': 't.CInt64T', 'int32_t': 'CInt32T', 'int64_t': 'CInt64T',
'uint8_t': 't.CUInt8T', 'uint16_t': 't.CUInt16T', 'uint8_t': 'CUInt8T', 'uint16_t': 'CUInt16T',
'uint32_t': 't.CUInt32T', 'uint64_t': 't.CUInt64T', 'uint32_t': 'CUInt32T', 'uint64_t': 'CUInt64T',
'intptr_t': 't.CIntPtrT', 'uintptr_t': 't.CUIntPtrT', 'intptr_t': 'CIntPtrT', 'uintptr_t': 'CUIntPtrT',
'ptrdiff_t': 't.CPtrDiffT', 'ptrdiff_t': 'CPtrDiffT',
# 宽字符 / 字符类型 # 宽字符 / 字符类型
'wchar_t': 't.CWCharT', 'char8_t': 't.CChar8T', 'wchar_t': 'CWCharT', 'char8_t': 'CChar8T',
'char16_t': 't.CChar16T', 'char32_t': 't.CChar32T', 'char16_t': 'CChar16T', 'char32_t': 'CChar32T',
# 浮点特化类型 # 浮点特化类型
'float8_t': 't.CFloat8T', 'float16_t': 't.CFloat16T', 'float8_t': 'CFloat8T', 'float16_t': 'CFloat16T',
'float32_t': 't.CFloat32T', 'float64_t': 't.CFloat64T', 'float32_t': 'CFloat32T', 'float64_t': 'CFloat64T',
'float128_t': 't.CFloat128T', 'float128_t': 'CFloat128T',
# signed 速记 # signed 速记
'signed': 't.CInt', 'signed int': 't.CInt', 'signed': 'CInt', 'signed int': 'CInt',
'signed short': 't.CShort', 'signed long': 't.CLong', 'signed short': 'CShort', 'signed long': 'CLong',
} }
@classmethod @classmethod
def _ResolveCNameToPyType(cls, c_type: str) -> str: def _ResolveCNameToPyType(cls, c_type: str) -> str:
"""将 C 类型名解析为 Python 类型字符串(如 'int' → 't.CInt') """将 C 类型名解析为 Python 类型字符串(如 'int' → 'CInt')
使用硬编码映射表,不再依赖 CTypeRegistry._cname_to_class。 使用硬编码映射表,不再依赖 CTypeRegistry._cname_to_class。
未识别的类型原样返回(用于 struct/union/enum/typedef 用户自定义名)。 未识别的类型原样返回(用于 struct/union/enum/typedef 用户自定义名)。
@@ -110,7 +110,7 @@ class CTypeMapper:
PtrSuffix: str = '' PtrSuffix: str = ''
if IsPtr or c_type.endswith('*'): if IsPtr or c_type.endswith('*'):
PtrSuffix = ' | t.CPtr' PtrSuffix = ' | CPtr'
c_type = c_type.rstrip('*').strip() c_type = c_type.rstrip('*').strip()
if c_type.startswith('struct '): if c_type.startswith('struct '):
@@ -125,7 +125,7 @@ class CTypeMapper:
result: str = PyType + PtrSuffix result: str = PyType + PtrSuffix
if IsArray: if IsArray:
result += ' | t.CArrayPtr' result += ' | CArrayPtr'
return result return result
@@ -603,7 +603,7 @@ class PythonStubGenerator:
def generate(self, ModuleName: str | None = None) -> str: def generate(self, ModuleName: str | None = None) -> str:
self.OutputLines = [] self.OutputLines = []
self._AddHeader(ModuleName) self._AddHeader(ModuleName)
self._GenerateImports() # stub 头部只放模块文档;内建标记按裸名使用,无需 import。
self._GenerateDefines() self._GenerateDefines()
self._GenerateFuncPtrTypedefs() self._GenerateFuncPtrTypedefs()
self._GenerateSimpleTypedefs() self._GenerateSimpleTypedefs()
@@ -622,11 +622,6 @@ class PythonStubGenerator:
self.OutputLines.append('"""') self.OutputLines.append('"""')
self.OutputLines.append('') self.OutputLines.append('')
def _GenerateImports(self) -> None:
self.OutputLines.append('import t')
self.OutputLines.append('import c')
self.OutputLines.append('')
def _GenerateDefines(self) -> None: def _GenerateDefines(self) -> None:
if not self.parser.defines: if not self.parser.defines:
return return
@@ -634,9 +629,9 @@ class PythonStubGenerator:
Name: str = define['name'] Name: str = define['name']
Value: str | None = define['value'] Value: str | None = define['value']
if Value is not None: if Value is not None:
self.OutputLines.append(f'{Name}: t.CDefine = {Value}') self.OutputLines.append(f'{Name}: CDefine = {Value}')
else: else:
self.OutputLines.append(f'{Name}: t.CDefine') self.OutputLines.append(f'{Name}: CDefine')
self.OutputLines.append('') self.OutputLines.append('')
def _GenerateFuncPtrTypedefs(self) -> None: def _GenerateFuncPtrTypedefs(self) -> None:
@@ -648,7 +643,7 @@ class PythonStubGenerator:
for p in Info['params']: for p in Info['params']:
ParamTypes.append(CTypeMapper.MapType(p['type'])) ParamTypes.append(CTypeMapper.MapType(p['type']))
ParamStr: str = ', '.join(ParamTypes) if ParamTypes else '' ParamStr: str = ', '.join(ParamTypes) if ParamTypes else ''
self.OutputLines.append(f'{Name}: t.CTypedef = t.Callable[[{ParamStr}], {RetType}]') self.OutputLines.append(f'{Name}: CTypedef = Callable[[{ParamStr}], {RetType}]')
self.OutputLines.append('') self.OutputLines.append('')
def _GenerateSimpleTypedefs(self) -> None: def _GenerateSimpleTypedefs(self) -> None:
@@ -658,15 +653,15 @@ class PythonStubGenerator:
AliasName: str = td['name'] AliasName: str = td['name']
BaseType: str = td['base'] BaseType: str = td['base']
PyType: str = CTypeMapper.MapType(BaseType) PyType: str = CTypeMapper.MapType(BaseType)
self.OutputLines.append(f'{AliasName}: t.CTypedef | {PyType}') self.OutputLines.append(f'{AliasName}: CTypedef | {PyType}')
self.OutputLines.append('') self.OutputLines.append('')
def _GenerateStructs(self) -> None: def _GenerateStructs(self) -> None:
if not self.parser.structs: if not self.parser.structs:
return return
for StructName, StructInfo in self.parser.structs.items(): for StructName, StructInfo in self.parser.structs.items():
self.OutputLines.append(f'@c.Attribute(t.attr.packed)') self.OutputLines.append(f'@Attribute(attr.packed)')
self.OutputLines.append(f'class {StructName}(t.CStruct):') self.OutputLines.append(f'class {StructName}(CStruct):')
if StructInfo['members']: if StructInfo['members']:
for member in StructInfo['members']: for member in StructInfo['members']:
MemberName: str = member['name'] MemberName: str = member['name']
@@ -677,7 +672,7 @@ class PythonStubGenerator:
if IsArray and ArraySize is not None: if IsArray and ArraySize is not None:
self.OutputLines.append(f' {MemberName}: list[{PyType}, {ArraySize}]') self.OutputLines.append(f' {MemberName}: list[{PyType}, {ArraySize}]')
elif IsArray: elif IsArray:
self.OutputLines.append(f' {MemberName}: {PyType} | t.CArrayPtr') self.OutputLines.append(f' {MemberName}: {PyType} | CArrayPtr')
else: else:
self.OutputLines.append(f' {MemberName}: {PyType}') self.OutputLines.append(f' {MemberName}: {PyType}')
else: else:
@@ -688,8 +683,8 @@ class PythonStubGenerator:
if not self.parser.unions: if not self.parser.unions:
return return
for UnionName, UnionInfo in self.parser.unions.items(): for UnionName, UnionInfo in self.parser.unions.items():
self.OutputLines.append(f'@c.Attribute(t.attr.packed)') self.OutputLines.append(f'@Attribute(attr.packed)')
self.OutputLines.append(f'class {UnionName}(t.CUnion):') self.OutputLines.append(f'class {UnionName}(CUnion):')
if UnionInfo['members']: if UnionInfo['members']:
for member in UnionInfo['members']: for member in UnionInfo['members']:
PyType: str = CTypeMapper.MapType(member['type'], IsPtr=member.get('IsPtr', False)) PyType: str = CTypeMapper.MapType(member['type'], IsPtr=member.get('IsPtr', False))
@@ -702,16 +697,16 @@ class PythonStubGenerator:
if not self.parser.enums: if not self.parser.enums:
return return
for EnumName, EnumInfo in self.parser.enums.items(): for EnumName, EnumInfo in self.parser.enums.items():
self.OutputLines.append(f'class __{EnumName.lower()}(t.CEnum):') self.OutputLines.append(f'class __{EnumName.lower()}(CEnum):')
if EnumInfo['values']: if EnumInfo['values']:
for value in EnumInfo['values']: for value in EnumInfo['values']:
if value['value'] is not None: if value['value'] is not None:
self.OutputLines.append(f' {value["name"]}: t.CDefine = {value["value"]}') self.OutputLines.append(f' {value["name"]}: CDefine = {value["value"]}')
else: else:
self.OutputLines.append(f' {value["name"]}: t.CDefine') self.OutputLines.append(f' {value["name"]}: CDefine')
else: else:
self.OutputLines.append(' pass') self.OutputLines.append(' pass')
self.OutputLines.append(f'{EnumName}: t.CTypedef = __{EnumName.lower()}') self.OutputLines.append(f'{EnumName}: CTypedef = __{EnumName.lower()}')
self.OutputLines.append('') self.OutputLines.append('')
def _GenerateVariables(self) -> None: def _GenerateVariables(self) -> None:
-1
View File
@@ -1 +0,0 @@
"""类型系统与 C 语法定义 (t.py / c.py)"""
-634
View File
@@ -1,634 +0,0 @@
# C语法定义模块
from __future__ import annotations
import vast as ast
import logging
from typing import Any, Optional
from . import t
from lib.constants.config import mode as _config_mode
def _to_str(node: Any) -> str:
if node is None:
return ''
if isinstance(node, str):
return node
if isinstance(node, list):
return ' && '.join([_to_str(n) for n in node])
NodeType: str = type(node).__name__
if NodeType == 'Constant':
return node.value
elif NodeType == 'ID':
return node.name
elif NodeType == 'BinaryOp':
left: str = _to_str(node.left)
right: str = _to_str(node.right)
return f'{left} {node.op} {right}'
elif NodeType == 'UnaryOp':
expr: str = _to_str(node.expr)
return f'{node.op}{expr}'
else:
return repr(node)
class Asm:
@staticmethod
def _parse_asm_descr(expr: ast.AST) -> str:
"""递归解析AST节点,确保获取t.ASM_DESCR的实际值,支持|组合
处理场景:
1. t.ASM_DESCR.XXX → 取属性值
2. t.ASM_DESCR.XXX | t.ASM_DESCR.YYY → 拼接两个值
3. 常量字符串 → 直接返回
"""
# 场景1:位或组合(XXX | YYY)
if isinstance(expr, ast.BinOp):
left_val: str = Asm._parse_asm_descr(expr.left)
right_val: str = Asm._parse_asm_descr(expr.right)
return left_val + right_val
# 场景2:t.ASM_DESCR.XXX 多层属性访问
elif isinstance(expr, ast.Attribute):
# 第一步:判断是否是 t.ASM_DESCR 的属性
if isinstance(expr.value, ast.Attribute):
# 内层是 t.ASM_DESCR
if (isinstance(expr.value.value, ast.Name) and
expr.value.value.id == 't' and
expr.value.attr == 'ASM_DESCR'):
# 取 t.ASM_DESCR.XXX 的实际值
AttrName: str = expr.attr
if hasattr(t.ASM_DESCR, AttrName):
return getattr(t.ASM_DESCR, AttrName, "")
# 兼容 t.XXX 简化写法(如果有的话)
elif isinstance(expr.value, ast.Name) and expr.value.id == 't':
AttrName: str = expr.attr
if hasattr(t.ASM_DESCR, AttrName):
return getattr(t.ASM_DESCR, AttrName, "")
# 场景3:直接传常量(如 "r"、"cc")
elif isinstance(expr, ast.Constant):
return expr.value
# 其他场景返回空
return ""
@staticmethod
def _extract_val_expr(translator: Any, expr_node: ast.AST) -> str:
"""从AST表达式节点提取值表达式的字符串形式"""
val_ExprNode: Any = translator.HandleExpr(expr_node)[0]
if isinstance(val_ExprNode, str):
return val_ExprNode
try:
return str(val_ExprNode)
except Exception as _e:
if _config_mode == "strict":
logging.warning(f"异常被忽略: {_e}")
return ''
@staticmethod
def _parse_asm_template(translator: Any, args: list[ast.AST]) -> tuple[str, list[tuple[str, str]], list[tuple[str, str]], int]:
"""解析f-string或常量模板字符串,返回(asm_code, output_ops, input_ops, operand_seq)"""
output_ops: list[tuple[str, str]] = []
input_ops: list[tuple[str, str]] = []
operand_seq: int = 0
asm_code: str = ""
first_arg: ast.AST = args[0]
if isinstance(first_arg, ast.JoinedStr):
asm_parts: list[str] = []
for part in first_arg.values:
if isinstance(part, ast.Constant):
asm_parts.append(part.value)
elif isinstance(part, ast.FormattedValue):
expr: ast.AST = part.value
if isinstance(expr, ast.Call) and isinstance(expr.func, ast.Attribute) and expr.func.value.id == 'c':
# 解析内联的AsmInp/AsmOut
call_node: ast.Call = expr
val_expr: str = Asm._extract_val_expr(translator, call_node.args[0]) if len(call_node.args)>=1 else ""
constraint: str = Asm._parse_asm_descr(call_node.args[1]) if len(call_node.args)>=2 else ""
if call_node.func.attr == 'AsmOut':
output_ops.append((val_expr, constraint))
asm_parts.append(f"%{operand_seq}")
operand_seq += 1
elif call_node.func.attr == 'AsmInp':
input_ops.append((val_expr, constraint))
asm_parts.append(f"%{operand_seq}")
operand_seq += 1
else:
asm_parts.append(translator.HandleExpr(expr)[0])
asm_code = ''.join(asm_parts)
elif isinstance(first_arg, ast.Constant):
asm_code = first_arg.value
return asm_code, output_ops, input_ops, operand_seq
@staticmethod
def _parse_asm_operands(translator: Any, args: list[ast.AST], keywords: list[ast.keyword], output_ops: list[tuple[str, str]], input_ops: list[tuple[str, str]], operand_seq: int) -> tuple[list[tuple[str, str]], list[tuple[str, str]], int]:
"""解析位置参数和关键字参数中的输出/输入操作数"""
def parse_operand(arg: ast.AST) -> Optional[tuple[str, str, str]]:
"""解析 AsmInp/AsmOut 参数"""
if isinstance(arg, ast.Call) and isinstance(arg.func, ast.Attribute) and arg.func.value.id == 'c':
call_node: ast.Call = arg
val_expr: str = Asm._extract_val_expr(translator, call_node.args[0]) if len(call_node.args)>=1 else ""
constraint: str = Asm._parse_asm_descr(call_node.args[1]) if len(call_node.args)>=2 else ""
if call_node.func.attr == 'AsmOut':
return ('out', val_expr, constraint)
elif call_node.func.attr == 'AsmInp':
return ('in', val_expr, constraint)
return None
# 处理位置参数中的操作数
for arg in args[1:]:
result: Optional[tuple[str, str, str]] = parse_operand(arg)
if result:
direction, val_expr, constraint = result
if direction == 'out':
output_ops.append((val_expr, constraint))
operand_seq += 1
elif direction == 'in':
input_ops.append((val_expr, constraint))
operand_seq += 1
# 处理关键字参数中的操作数
for kw in keywords:
if kw.arg == 'out':
# 处理 out 关键字参数 (输出操作数)
if isinstance(kw.value, ast.List):
for elt in kw.value.elts:
result = parse_operand(elt)
if result and result[0] == 'out':
output_ops.append((result[1], result[2]))
operand_seq += 1
elif isinstance(kw.value, ast.Call):
result = parse_operand(kw.value)
if result and result[0] == 'out':
output_ops.append((result[1], result[2]))
operand_seq += 1
elif kw.arg == 'inp' or kw.arg == 'inputs':
# 处理 inp/inputs 关键字参数 (输入操作数,追加到f-string中已有输入之后)
if isinstance(kw.value, ast.List):
for elt in kw.value.elts:
if isinstance(elt, ast.Tuple):
# 处理列表中的 (value, constraint) 元组格式
if len(elt.elts) >= 2:
val_expr: str = Asm._extract_val_expr(translator, elt.elts[0]) if len(elt.elts) >= 1 else ""
constraint: str = Asm._parse_asm_descr(elt.elts[1])
input_ops.append((val_expr, constraint))
operand_seq += 1
else:
result = parse_operand(elt)
if result and result[0] == 'in':
input_ops.append((result[1], result[2]))
operand_seq += 1
elif isinstance(kw.value, ast.Call):
result = parse_operand(kw.value)
if result and result[0] == 'in':
input_ops.append((result[1], result[2]))
operand_seq += 1
elif isinstance(kw.value, ast.Tuple):
# 处理 (value, constraint) 元组格式
if len(kw.value.elts) >= 2:
val_expr: str = Asm._extract_val_expr(translator, kw.value.elts[0]) if len(kw.value.elts) >= 1 else ""
constraint: str = Asm._parse_asm_descr(kw.value.elts[1])
input_ops.append((val_expr, constraint))
operand_seq += 1
return output_ops, input_ops, operand_seq
@staticmethod
def _parse_asm_clobbers(args: list[ast.AST], keywords: list[ast.keyword]) -> list[str]:
"""解析位置参数和关键字参数中的破坏列表"""
clobbers: list[str] = []
# 处理位置参数中的破坏列表
for arg in args[1:]:
if isinstance(arg, ast.List):
# 解析破坏列表(支持|组合)
for elt in arg.elts:
clobber_val: str = Asm._parse_asm_descr(elt)
if clobber_val:
clobbers.append(clobber_val)
# 处理关键字参数中的破坏列表
for kw in keywords:
if kw.arg == 'op':
# 处理 op 关键字参数 (clobber,破坏列表)
if isinstance(kw.value, ast.List):
for elt in kw.value.elts:
clobber_val: str = Asm._parse_asm_descr(elt)
if clobber_val:
clobbers.append(clobber_val)
elif kw.arg == 'clobber':
# 处理 clobber 关键字参数
if isinstance(kw.value, ast.List):
for elt in kw.value.elts:
clobber_val: str = Asm._parse_asm_descr(elt)
if clobber_val:
clobbers.append(clobber_val)
return clobbers
@staticmethod
def _generate_asm_code(asm_code: str, output_ops: list[tuple[str, str]], input_ops: list[tuple[str, str]], clobbers: list[str], asm_format: str) -> list[str]:
"""格式化汇编代码并生成最终的__asm__代码字符串"""
# 格式化汇编代码
asm_lines: list[str] = [line.strip() for line in asm_code.split('\n') if line.strip()]
formatted_asm: str = '\n '.join([f'"{line}\\n"' for line in asm_lines])
# 拼接约束字符串
# 输出约束:如果约束已包含 = 或 +,直接使用;否则添加 =
def format_constraint(constraint: str, is_output: bool = True) -> str:
if not constraint:
return ""
# 如果约束已包含修饰符,直接返回
if '=' in constraint or '+' in constraint:
return constraint
# 否则添加适当的修饰符
return ('=' if is_output else '') + constraint
out_const: str = ', '.join([f'"{format_constraint(c, True)}"({v})' for v, c in output_ops]) if output_ops else ""
in_const: str = ', '.join([f'"{format_constraint(c, False)}"({v})' for v, c in input_ops]) if input_ops else ""
clobber_const: str = ', '.join([f'"{x}"' for x in clobbers]) if clobbers else ""
# 构建约束部分:确保冒号格式正确
constraint_parts: list[str] = []
# 输出约束
if output_ops:
constraint_parts.append(f': {out_const}')
elif input_ops or clobbers:
constraint_parts.append(':')
# 输入约束
if input_ops:
constraint_parts.append(f': {in_const}')
elif clobbers:
constraint_parts.append(':')
# 破坏列表
if clobbers:
constraint_parts.append(f': {clobber_const}')
constraint_str: str = ' '.join(constraint_parts)
# 生成最终代码
if asm_format == 'ARM':
# ARM 使用 .arch 指令和不同的内联汇编语法
final_asm: str = f'__asm__ __volatile__ (\n {formatted_asm} {constraint_str});'
elif asm_format == 'AT&T':
# AT&T 语法不需要额外标记,GCC 默认就是 AT&T
final_asm = f'__asm__ __volatile__ (\n {formatted_asm} {constraint_str});'
else:
# Intel 语法需要 .intel_syntax 指令
final_asm = f'__asm__ __volatile__ (".intel_syntax noprefix\\n\\t"\n {formatted_asm} ".att_syntax prefix" {constraint_str});'
return [final_asm]
@staticmethod
def HandleCall(translator: Any, args: list[ast.AST], keywords: list[ast.keyword]) -> list[str]:
if not args:
return ['__asm__ volatile ("nop");']
# 解析模板
asm_code: str
output_ops: list[tuple[str, str]]
input_ops: list[tuple[str, str]]
operand_seq: int
asm_code, output_ops, input_ops, operand_seq = Asm._parse_asm_template(translator, args)
# 解析操作数
output_ops, input_ops, operand_seq = Asm._parse_asm_operands(
translator, args, keywords, output_ops, input_ops, operand_seq)
# 解析破坏列表
clobbers: list[str] = Asm._parse_asm_clobbers(args, keywords)
# 解析汇编格式
asm_format: str = 'Intel'
for kw in keywords:
if kw.arg == 'format':
if isinstance(kw.value, ast.Constant) and isinstance(kw.value.value, str):
asm_format = kw.value.value
# 生成最终代码
return Asm._generate_asm_code(asm_code, output_ops, input_ops, clobbers, asm_format)
class AsmInp:
def __init__(self, value: Any, constraint: Any) -> None:
self.value: Any = value
self.constraint: Any = constraint
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[Any]:
return []
class AsmOut:
def __init__(self, value: Any, constraint: Any) -> None:
self.value: Any = value
self.constraint: Any = constraint
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[Any]:
return []
class NoBreak:
""" switch 分支无break """
pass
class Break:
""" switch 分支提前break """
pass
class Load:
"""解引用a写入b,等价于 *b = *a,无拷贝副作用"""
def __init__(self, src: Any, dst: Any) -> None:
self.src: Any = src
self.dst: Any = dst
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
if len(args) >= 2:
src: Any = translator.HandleExpr(args[0])[0]
dst: Any = translator.HandleExpr(args[1])[0]
return [f'*({dst}) = *({src})']
return []
class Addr:
"""取地址"""
def __init__(self, addr: Any) -> None:
self.addr: Any = addr
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.Addr() 调用"""
if args:
expr: Any = translator.HandleExpr(args[0])[0]
if isinstance(expr, str):
return [f'&{expr}']
return [f'&{_to_str(expr)}']
return ['0']
class Deref:
"""解引用"""
def __init__(self, ptr: Any) -> None:
self.ptr: Any = ptr
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.Deref() 调用"""
if args:
expr: Any = translator.HandleExpr(args[0])[0]
if hasattr(expr, 'op') and expr.op == '*':
return [expr]
return [f'*({_to_str(expr)})']
return ['0']
class DerefAs:
"""解引用写入,等价于 *ptr = value"""
def __init__(self, ptr: Any, value: Any) -> None:
self.ptr: Any = ptr
self.value: Any = value
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.DerefAs() 调用"""
if len(args) >= 2:
ptr: Any = translator.HandleExpr(args[0])[0]
val: Any = translator.HandleExpr(args[1])[0]
return [f'*({_to_str(ptr)}) = {_to_str(val)}']
return []
class Set:
"""设置值"""
def __init__(self, key: Any, value: Any) -> None:
self.key: Any = key
self.value: Any = value
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.Set() 调用"""
if len(args) >= 2:
target: Any = translator.HandleExpr(args[0])[0]
value: Any = translator.HandleExpr(args[1])[0]
return [f'{_to_str(target)} = {_to_str(value)}']
return []
class CReturn:
"""【已移除】多返回值装饰器(墓碑)。
该类已移除:源码中写 `@c.CReturn(...)` 会被编译器**报错**(fail-fast),
不会静默忽略或改写。多返回值请改用返回注解 `-> tuple[ty1, ty2, ...]`
(返回多个值的函数打包为 struct 返回,调用处用元组解包接收)。
"""
def __init__(self, *ReturnTypes: Any) -> None:
self.ReturnTypes: tuple[Any, ...] = ReturnTypes
def __call__(self, func: Any) -> Any:
"""装饰器调用"""
# 将返回类型信息附加到函数上
func._CreturnTypes = self.ReturnTypes
return func
class CDefine:
"""#define 宏定义"""
def __init__(self, name: Any, value: Any) -> None:
self.name: Any = name
self.value: Any = value
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.CDefine() 调用"""
if len(args) >= 1:
if isinstance(args[0], ast.Constant):
name: Any = args[0].value
else:
name = 'MACRO'
if len(args) >= 2:
value: Any = translator.HandleExpr(args[1])[0]
return ['#define ' + str(name) + ' ' + _to_str(value)]
return ['#define ' + str(name)]
return []
class CError:
"""#error 错误信息"""
def __init__(self, condition: Any) -> None:
self.condition: Any = condition
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.CError() 调用"""
if args:
# 如果是字符串常量,保留引号
if isinstance(args[0], ast.Constant) and isinstance(args[0].value, str):
return ['#error "' + args[0].value + '"']
else:
condition: Any = translator.HandleExpr(args[0])[0]
return ['#error ' + _to_str(condition)]
return ['#error "Error: Condition is not met."']
class TokenPast:
"""## 连接符"""
def __init__(self, left: Any, right: Any) -> None:
self.left: Any = left
self.right: Any = right
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[Any]:
"""处理 c.TokenPast() 调用"""
if len(args) >= 2:
# 处理左操作数 - 去掉引号
if isinstance(args[0], ast.Constant):
left: str = str(args[0].value)
elif isinstance(args[0], ast.Name):
left = args[0].id
else:
left = _to_str(translator.HandleExpr(args[0])[0])
# 处理右操作数 - 去掉引号
if isinstance(args[1], ast.Constant):
right: str = str(args[1].value)
elif isinstance(args[1], ast.Name):
right = args[1].id
else:
right = _to_str(translator.HandleExpr(args[1])[0])
# 返回字符串,但用特殊标记包装,让 _AstNodeToStr 能正确处理
result: str = left + ' ## ' + right
# 使用一个特殊的类来包装结果,让 _AstNodeToStr 直接返回其值
class TokenPastResult:
def __init__(self, value: str) -> None:
self.value: str = value
def __str__(self) -> str:
return self.value
return [TokenPastResult(result)]
return ['']
class CUndef:
"""#undef 取消宏定义"""
def __init__(self, name: Any) -> None:
self.name: Any = name
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.CUndef(name) 调用"""
if args:
arg: Any = args[0]
if isinstance(arg, str):
name: str = arg
elif isinstance(arg, ast.Name):
name = arg.id
elif isinstance(arg, ast.Constant):
name = str(arg.value)
else:
name = str(arg)
return [f'#undef {name}']
return ['#undef']
class LLVMIR:
"""内联 LLVM IR(无返回值,直接嵌入原始 IR 文本)
用法: c.LLVMIR(f"add i32 {c.LInp(a)}, {c.LInp(b)}")
或: c.LLVMIR(f"{c.LOut(result)} = add i32 {c.LInp(a)}, {c.LInp(b)}")
c.LInp(expr) - 输入操作数,替换为 expr 的 LLVM 值引用文本(%x 或常量)
c.LOut(expr) - 输出操作数:为 expr 变量分配唯一 SSA 寄存器 %llvmirN,
模板嵌入后自动追加 store 写回变量 alloca
"""
def __init__(self, ir_template: Any, ret_type: Any = None) -> None:
self.ir_template: Any = ir_template
self.ret_type: Any = ret_type
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
return ['/* LLVMIR */']
class LInp:
"""LLVM IR 输入操作数标记
用法: c.LInp(expr) - 标记 expr 为输入操作数
在 c.LLVMIR 的 f-string 中使用,翻译后替换为 %N 形式的操作数引用
"""
def __init__(self, value: Any) -> None:
self.value: Any = value
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[Any]:
return []
class LOut:
"""LLVM IR 输出操作数标记
用法: c.LOut(expr) - 标记 expr 为输出操作数
在 c.LLVMIR 的 f-string 中使用,翻译后替换为 %N 形式的操作数引用
"""
def __init__(self, value: Any) -> None:
self.value: Any = value
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[Any]:
return []
class CPragma:
"""#pragma 指令
用于生成 C 语言的 #pragma 指令。
例如:c.CPragma("GCC diagnostic push") 生成 #pragma GCC diagnostic push
"""
def __init__(self, directive: Any) -> None:
self.directive: Any = directive
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.CPragma() 调用"""
if args:
arg: Any = args[0]
if isinstance(arg, ast.Constant):
directive: Any = arg.value
else:
expr: Any = translator.HandleExpr(arg)[0]
directive = _to_str(expr)
return [f'#pragma {directive}']
return ['#pragma']
# C 库类字典,用于 HandleCSpecialCall
Library_C = {
'Asm': Asm,
'Load': Load,
'Addr': Addr,
'Deref': Deref,
'Set': Set,
'AsmInp': AsmInp,
'AsmOut': AsmOut,
'CDefine': CDefine,
'CUndef': CUndef,
'CError': CError,
'TokenPast': TokenPast,
'CReturn': CReturn,
'CPragma': CPragma,
'LLVMIR': LLVMIR,
'LInp': LInp,
'LOut': LOut,
}
class Attribute:
"""函数/变量属性装饰器"""
def __init__(self, *attrs: Any) -> None:
self.attrs: tuple[Any, ...] = attrs
def __call__(self, func: Any) -> Any:
# 将属性附加到函数上
func._c_attributes = self.attrs
return func
+28 -31
View File
@@ -69,7 +69,7 @@ _HEX_ALPHABET: str = '0123456789abcdefABCDEF'
#(内部标记 c.@CIf 族由解析期合成,不走此处)。 #(内部标记 c.@CIf 族由解析期合成,不走此处)。
_REMOVED_CIF_NAMES: frozenset[str] = frozenset({ _REMOVED_CIF_NAMES: frozenset[str] = frozenset({
'CIf', 'CIfdef', 'CIfndef', 'CElif', 'CElse', 'CEndif', 'CIf', 'CIfdef', 'CIfndef', 'CElif', 'CElse', 'CEndif',
'c.CIf', 'c.CIfdef', 'c.CIfndef', 'c.CElif', 'c.CElse', 'c.CEndif', 'CIf', 'CIfdef', 'CIfndef', 'CElif', 'CElse', 'CEndif',
}) })
@@ -110,9 +110,9 @@ class TokenStream:
self._PeekCacheIdx: int = -1 self._PeekCacheIdx: int = -1
self._PeekCacheTok: Token | None = None self._PeekCacheTok: Token | None = None
# 类型注解解析模式:为 True 时 '*' / '**' 按 C 风格指针后缀处理 # 类型注解解析模式:为 True 时 '*' / '**' 按 C 风格指针后缀处理
# (int* → int | t.CPtr、int** → 嵌套两层),不按乘法/幂运算消费。 # (int* → int | CPtr、int** → 嵌套两层),不按乘法/幂运算消费。
self._InTypeAnnotation: bool = False self._InTypeAnnotation: bool = False
# 下标实参嵌套层数:'[' 实参内是表达式位置(t.CArray[T, A * B] 的尺寸), # 下标实参嵌套层数:'[' 实参内是表达式位置(CArray[T, A * B] 的尺寸),
# 此处的 '*' 在有右操作数时按乘法解析(见 _ParseTerm / _AtOperandAfterStarRun)。 # 此处的 '*' 在有右操作数时按乘法解析(见 _ParseTerm / _AtOperandAfterStarRun)。
self._SubscriptArgs: int = 0 self._SubscriptArgs: int = 0
# Tail token of the last consumed C-style pointer suffix ('*' / '**'). # Tail token of the last consumed C-style pointer suffix ('*' / '**').
@@ -463,13 +463,13 @@ class ExprParserMixin(TokenStream):
op_type: type | None = None op_type: type | None = None
if tok.Type == OP: if tok.Type == OP:
if tok.Value == '*' and self._AtPtrSuffix(left): if tok.Value == '*' and self._AtPtrSuffix(left):
# C 风格指针后缀('*' 一层);展开为 base | t.CPtr 后继续。 # C 风格指针后缀('*' 一层);展开为 base | CPtr 后继续。
left = self._ConsumePtrSuffix(left) left = self._ConsumePtrSuffix(left)
continue continue
if self._InTypeAnnotation and tok.Value == '*': if self._InTypeAnnotation and tok.Value == '*':
# 注解模式:'*' 后已无操作数(']' / ',' / ')' / ':' / '=' / 行尾 / ';') # 注解模式:'*' 后已无操作数(']' / ',' / ')' / ':' / '=' / 行尾 / ';')
# 时它是 C 风格指针后缀标记,交上方判据与 _ParseTypeAnnotation 统一消费; # 时它是 C 风格指针后缀标记,交上方判据与 _ParseTypeAnnotation 统一消费;
# 但下标实参内的尺寸表达式(t.CArray[T, A * B])'*' 后仍有操作数, # 但下标实参内的尺寸表达式(CArray[T, A * B])'*' 后仍有操作数,
# 必须按乘法继续——否则下标收尾报 `expected ']'`。 # 必须按乘法继续——否则下标收尾报 `expected ']'`。
if not (self._SubscriptArgs > 0 and self._AtOperandAfterStarRun()): if not (self._SubscriptArgs > 0 and self._AtOperandAfterStarRun()):
break break
@@ -535,7 +535,7 @@ class ExprParserMixin(TokenStream):
tok: Token = self._Peek() tok: Token = self._Peek()
if tok.Type == OP and tok.Value in ('*', '**') and self._AtPtrSuffixCall(node): if tok.Type == OP and tok.Value in ('*', '**') and self._AtPtrSuffixCall(node):
# `T*(x)` / `T**(x)` 指针后缀强转:解析为 cast 调用(与 # `T*(x)` / `T**(x)` 指针后缀强转:解析为 cast 调用(与
# `(T | t.CPtr)(x)` 同形)。在 trailer 循环里消费,故其后的 # `(T | CPtr)(x)` 同形)。在 trailer 循环里消费,故其后的
# `.attr` / `[i]` / `(…)` 仍由本循环继续挂接(如 # `.attr` / `[i]` / `(…)` 仍由本循环继续挂接(如
# `ast.Attribute*(expr_root).value`)。 # `ast.Attribute*(expr_root).value`)。
node = self._ConsumePtrSuffixCall(node, start) node = self._ConsumePtrSuffixCall(node, start)
@@ -628,7 +628,7 @@ class ExprParserMixin(TokenStream):
- `defined(NAME)`:仅 cif/celif 条件内合法(`self._InCIfCond`), - `defined(NAME)`:仅 cif/celif 条件内合法(`self._InCIfCond`),
desugar 为内部标记调用 `c.@CIfdef(NAME)`;其余位置 FailFast。 desugar 为内部标记调用 `c.@CIfdef(NAME)`;其余位置 FailFast。
- `c.CIf` / `c.CIfdef` / `c.CIfndef`(及裸名):已删除,FailFast 指向新语法。 - `CIf` / `CIfdef` / `CIfndef`(及裸名):已删除,FailFast 指向新语法。
""" """
callee: str = self._CallCalleeName(node.func) callee: str = self._CallCalleeName(node.func)
if callee in _REMOVED_CIF_NAMES: if callee in _REMOVED_CIF_NAMES:
@@ -646,8 +646,7 @@ class ExprParserMixin(TokenStream):
f"'defined' expects exactly one macro name (e.g. defined(MAX_SIZE)), " f"'defined' expects exactly one macro name (e.g. defined(MAX_SIZE)), "
f"at line {start.Line}") f"at line {start.Line}")
marker: N.Call = N.Call( marker: N.Call = N.Call(
func=N.Attribute(value=N.Name(id='c', ctx=N.Load()), func=N.Name(id='CIfdef', ctx=N.Load()),
attr='@CIfdef', ctx=N.Load()),
args=[node.args[0]], keywords=[]) args=[node.args[0]], keywords=[])
self._FixLoc(marker, start) self._FixLoc(marker, start)
return marker return marker
@@ -666,8 +665,8 @@ class ExprParserMixin(TokenStream):
def _ParseSliceList(self) -> N.AST: def _ParseSliceList(self) -> N.AST:
"""解析下标列表:a[1] / a[1:2] / a[1:2:3] / a[1,2] / a[...] / a[::] """解析下标列表:a[1] / a[1:2] / a[1:2:3] / a[1,2] / a[...] / a[::]
下标实参内是**表达式**位置(如 `t.CArray[T, A * B]` 的尺寸),此处的 '*' 下标实参内是**表达式**位置(如 `CArray[T, A * B]` 的尺寸),此处的 '*'
应按乘法解析;同时 `t.CArray[str*, 4]` 的指针后缀仍要成立——两者由 应按乘法解析;同时 `CArray[str*, 4]` 的指针后缀仍要成立——两者由
`_AtOperandAfterStarRun`('*' 后是否还有操作数)区分,故此处登记已进入实参。 `_AtOperandAfterStarRun`('*' 后是否还有操作数)区分,故此处登记已进入实参。
""" """
self._SubscriptArgs += 1 self._SubscriptArgs += 1
@@ -1301,7 +1300,7 @@ class ExprParserMixin(TokenStream):
first: N.expr = self.ParseExpr() first: N.expr = self.ParseExpr()
# Paren-less C cast `(T*)x`: the inner expression ends with a pointer suffix # Paren-less C cast `(T*)x`: the inner expression ends with a pointer suffix
# (_Prev() is that suffix's tail token) and the operand follows ')'. Same # (_Prev() is that suffix's tail token) and the operand follows ')'. Same
# product as `(T*)(x)` / `T*(x)`: a Call whose func is `T | t.CPtr`. # product as `(T*)(x)` / `T*(x)`: a Call whose func is `T | CPtr`.
is_ptr_cast: bool = self._PtrSuffixTail is not None and self._AtOp(')') and self._Prev() is self._PtrSuffixTail is_ptr_cast: bool = self._PtrSuffixTail is not None and self._AtOp(')') and self._Prev() is self._PtrSuffixTail
self._SkipNL() self._SkipNL()
# 生成器表达式 (x for ...) # 生成器表达式 (x for ...)
@@ -1692,8 +1691,8 @@ class ExprParserMixin(TokenStream):
注解模式开启后,'_ParseTerm'/'_ParsePower' 不再把 '*' / '**' 当 注解模式开启后,'_ParseTerm'/'_ParsePower' 不再把 '*' / '**' 当
乘法/幂运算消费,而由本方法统一循环消费并展开为嵌套联合类型: 乘法/幂运算消费,而由本方法统一循环消费并展开为嵌套联合类型:
int* → int | t.CPtr (i32*) int* → int | CPtr (i32*)
int** → (int | t.CPtr) | t.CPtr (i32**) int** → (int | CPtr) | CPtr (i32**)
int****** → 6 层嵌套 (i32******) int****** → 6 层嵌套 (i32******)
展开为 BinOp(BitOr) 链后,TPC/VPC 现有类型解析(TypeAnnotationResolver 展开为 BinOp(BitOr) 链后,TPC/VPC 现有类型解析(TypeAnnotationResolver
@@ -1702,11 +1701,11 @@ class ExprParserMixin(TokenStream):
无法解析的后缀形态**响亮失败**(SyntaxError,含 行:列 + 源码片段 + 形态 + 无法解析的后缀形态**响亮失败**(SyntaxError,含 行:列 + 源码片段 + 形态 +
正确写法示例),绝不静默丢弃:注解末尾若仍遗留未被 `_AtPtrSuffix` 接受的 正确写法示例),绝不静默丢弃:注解末尾若仍遗留未被 `_AtPtrSuffix` 接受的
'*'/'**'(如 `a: int * 2` / `a: int* | t.CPtr`),判据拒绝消费即终止编译 '*'/'**'(如 `a: int * 2` / `a: int* | CPtr`),判据拒绝消费即终止编译
(历史事故:静默退化会产出错误的指针层数)。 (历史事故:静默退化会产出错误的指针层数)。
值引用参数注解(仅形参位有效):前导 `&` 为 ref 模式、`&temp` 为 temp 模式, 值引用参数注解(仅形参位有效):前导 `&` 为 ref 模式、`&temp` 为 temp 模式,
合成联合形态 `T | t.CRef` / `T | t.CTempRef` 承载(CRef/CTempRef 非真实类, 合成联合形态 `T | CRef` / `T | CTempRef` 承载(CRef/CTempRef 非真实类,
仅按名字识别;语义侧见 HandlesFunctions / FuncGen)。表达式位的 `&x` 不受影响。 仅按名字识别;语义侧见 HandlesFunctions / FuncGen)。表达式位的 `&x` 不受影响。
""" """
ref_mode: str | None = None ref_mode: str | None = None
@@ -1757,9 +1756,9 @@ class ExprParserMixin(TokenStream):
f"{tok.Value!r} 前面不是可加后缀的类型(Name / Attribute / Subscript)," f"{tok.Value!r} 前面不是可加后缀的类型(Name / Attribute / Subscript),"
f"或其后不是后缀的合法结束位置(注解结尾,或 ']' / ',' / ')' / ':' / '=')。" f"或其后不是后缀的合法结束位置(注解结尾,或 ']' / ',' / ')' / ':' / '=')。"
f"源码片段 {snippet!r}。" f"源码片段 {snippet!r}。"
f"期望形态:`T*`(1 层)/ `T**`(2 层),T 可为裸名 / t.X / mod.Type / " f"期望形态:`T*`(1 层)/ `T**`(2 层),T 可为裸名 / X / mod.Type / "
f"rawptr[T] / t.CPtr[T]。" f"rawptr[T] / CPtr[T]。"
f"正确示例:`a: t.CPtr*` / `a: rawptr*` / `a: t.X**` / " f"正确示例:`a: CPtr*` / `a: rawptr*` / `a: X**` / "
f"`a: rawptr[ast.AST*]` / `def f(p: int*) -> int**`。" f"`a: rawptr[ast.AST*]` / `def f(p: int*) -> int**`。"
) )
if ref_mode is not None: if ref_mode is not None:
@@ -1767,13 +1766,12 @@ class ExprParserMixin(TokenStream):
return expr return expr
def _MakeRefMarker(self, base: N.expr, mode: str, tok: Token) -> N.expr: def _MakeRefMarker(self, base: N.expr, mode: str, tok: Token) -> N.expr:
"""构造值引用标记联合:`base | t.CRef`(ref)/ `base | t.CTempRef`(temp)。 """构造值引用标记联合:`base | CRef`(ref)/ `base | CTempRef`(temp)。
CRef / CTempRef 非真实类,仅作为注解 AST 内的名字标记(语义侧按名字识别)。 CRef / CTempRef 非真实类,仅作为注解 AST 内的名字标记(语义侧按名字识别)。
""" """
marker: N.expr = N.Attribute( marker: N.expr = N.Name(
value=N.Name(id='t', ctx=N.Load()), id='CRef' if mode == 'ref' else 'CTempRef',
attr='CRef' if mode == 'ref' else 'CTempRef',
ctx=N.Load()) ctx=N.Load())
node: N.BinOp = N.BinOp(left=base, op=N.BitOr(), right=marker) node: N.BinOp = N.BinOp(left=base, op=N.BitOr(), right=marker)
self._FixLoc(node, tok) self._FixLoc(node, tok)
@@ -1796,7 +1794,7 @@ class ExprParserMixin(TokenStream):
判据(两条同时成立): 判据(两条同时成立):
1. base 是"类型原子"形态(Name / Attribute / Subscript)—— 即 ``ast.AST``、 1. base 是"类型原子"形态(Name / Attribute / Subscript)—— 即 ``ast.AST``、
``t.CArray[X, N]``、``rawptr[X]`` 之类; ``CArray[X, N]``、``rawptr[X]`` 之类;
2. 该 '*'/'**' 串(可跨括号内换行 NL)之后紧跟"无右操作数"位置: 2. 该 '*'/'**' 串(可跨括号内换行 NL)之后紧跟"无右操作数"位置:
``]`` / ``,`` / ``)`` / ``:`` / ``=``(全局),或注解模式下的 ``]`` / ``,`` / ``)`` / ``:`` / ``=``(全局),或注解模式下的
NEWLINE / NL / ENDMARKER / ``;``。 NEWLINE / NL / ENDMARKER / ``;``。
@@ -1830,7 +1828,7 @@ class ExprParserMixin(TokenStream):
return False return False
def _ConsumePtrSuffix(self, expr: N.expr) -> N.expr: def _ConsumePtrSuffix(self, expr: N.expr) -> N.expr:
"""消费连续的 C 风格指针后缀('*' 一层 / '**' 两层),展开为 base | t.CPtr 链。""" """消费连续的 C 风格指针后缀('*' 一层 / '**' 两层),展开为 base | CPtr 链。"""
while True: while True:
tok: Token = self._Peek() tok: Token = self._Peek()
if tok.Type == OP and tok.Value == '*': if tok.Type == OP and tok.Value == '*':
@@ -1864,7 +1862,7 @@ class ExprParserMixin(TokenStream):
与 `_AtPtrSuffix` 互补:后者判「'*' 后是无右操作数位置」(']' / ',' / ')' / 与 `_AtPtrSuffix` 互补:后者判「'*' 后是无右操作数位置」(']' / ',' / ')' /
':' / '=' / 行尾 / ';' ⇒ 指针后缀),本方法判其反面('*' 后是 NAME / NUMBER / ':' / '=' / 行尾 / ';' ⇒ 指针后缀),本方法判其反面('*' 后是 NAME / NUMBER /
STRING / FSTRING 或 '(' / '[' / '{' / 一元前缀 ⇒ 乘法)。用于下标实参内区分 STRING / FSTRING 或 '(' / '[' / '{' / 一元前缀 ⇒ 乘法)。用于下标实参内区分
`t.CArray[T, A * B]`(乘法)与 `t.CArray[T*, 4]`(指针后缀)。 `CArray[T, A * B]`(乘法)与 `CArray[T*, 4]`(指针后缀)。
""" """
j: int = 0 j: int = 0
while True: while True:
@@ -1923,17 +1921,16 @@ class ExprParserMixin(TokenStream):
def _ConsumePtrSuffixCall(self, base: N.expr, start: Token) -> N.expr: def _ConsumePtrSuffixCall(self, base: N.expr, start: Token) -> N.expr:
"""把已认定为 `T*(...)` 的指针后缀强转解析为**调用**。 """把已认定为 `T*(...)` 的指针后缀强转解析为**调用**。
产物与既有强转形态 `(T | t.CPtr)(...)` 逐字同形:同为 `ast.Call` 产物与既有强转形态 `(T | CPtr)(...)` 逐字同形:同为 `ast.Call`
(func = `T` 展开的 `base | t.CPtr` 链,args/keywords = 括号实参), (func = `T` 展开的 `base | CPtr` 链,args/keywords = 括号实参),
不新造第二套 cast 表示。 不新造第二套 cast 表示。
""" """
func: N.expr = self._ConsumePtrSuffix(base) func: N.expr = self._ConsumePtrSuffix(base)
return self._ParseCallTail(func, start) return self._ParseCallTail(func, start)
def _MakePtrType(self, base: N.expr, tok: Token) -> N.expr: def _MakePtrType(self, base: N.expr, tok: Token) -> N.expr:
"""构造一层指针包装:base | t.CPtr。""" """构造一层指针包装:base | CPtr。"""
cptr: N.expr = N.Attribute(value=N.Name(id='t', ctx=N.Load()), cptr: N.expr = N.Name(id='CPtr', ctx=N.Load())
attr='CPtr', ctx=N.Load())
node: N.BinOp = N.BinOp(left=base, op=N.BitOr(), right=cptr) node: N.BinOp = N.BinOp(left=base, op=N.BitOr(), right=cptr)
self._FixLoc(node, tok) self._FixLoc(node, tok)
return node return node
+58 -68
View File
@@ -28,8 +28,8 @@ from lib.vast.Tokenizer import (
# 语法:`virtual class` / `novirtual class` / `virtual def` / `novirtual def` # 语法:`virtual class` / `novirtual class` / `virtual def` / `novirtual def`
# (修饰符写在 class/def **之前**,允许与修饰对象同行,也允许各占一行)。 # (修饰符写在 class/def **之前**,允许与修饰对象同行,也允许各占一行)。
# #
# 语义:与既有装饰器**同一套表示**——virtual → `@t.CVTable`, # 语义:与既有装饰器**同一套表示**——virtual → `@CVTable`,
# novirtual → `@t.NoVTable`。本层只"合成装饰器节点",不新增第二套表示: # novirtual → `@NoVTable`。本层只"合成装饰器节点",不新增第二套表示:
# - 类级:CVTable 强制有 vtable / NoVTable 强制无 vtable # - 类级:CVTable 强制有 vtable / NoVTable 强制无 vtable
# (TPC:HandlesClassDef._resolve_class_flags 读 ClassDef.decorator_list # (TPC:HandlesClassDef._resolve_class_flags 读 ClassDef.decorator_list
# 的 CVTable/NoVTable;VPC:ClassGenBase._detect_vtable_status) # 的 CVTable/NoVTable;VPC:ClassGenBase._detect_vtable_status)
@@ -62,7 +62,7 @@ _VIRTUAL_EXAMPLE: str = (
'novirtual class B: novirtual def helper(self) -> int: ...' 'novirtual class B: novirtual def helper(self) -> int: ...'
) )
# tls 修饰符(软关键字):`tls def f(...)` ⇒ 合成既有装饰器 `@t.TLS` # tls 修饰符(软关键字):`tls def f(...)` ⇒ 合成既有装饰器 `@TLS`
#(一次性初始化守卫,见 HandlesFunctions 的 TLS 分支)。与 virtual/novirtual 同一套 #(一次性初始化守卫,见 HandlesFunctions 的 TLS 分支)。与 virtual/novirtual 同一套
# "软关键字 + 合成既有装饰器"表示,不新增第二套语义;只在语句起始且后随 def 时生效, # "软关键字 + 合成既有装饰器"表示,不新增第二套语义;只在语句起始且后随 def 时生效,
# 故 `tls: local = local()` / `tls.set(...)` 等把 tls 当标识符的写法逐字不变。 # 故 `tls: local = local()` / `tls.set(...)` 等把 tls 当标识符的写法逐字不变。
@@ -75,8 +75,8 @@ _TLS_KEYWORD: str = 'tls'
# 语义(用户 2026-10-01 定):与 class 同形,但**只能表示数据类型**: # 语义(用户 2026-10-01 定):与 class 同形,但**只能表示数据类型**:
# - 禁止 virtual / novirtual 修饰(见 _ParseVirtualModified 的显式拦截); # - 禁止 virtual / novirtual 修饰(见 _ParseVirtualModified 的显式拦截);
# - 禁止类体内定义 def(见 _ParseStructDef 的 fail-fast); # - 禁止类体内定义 def(见 _ParseStructDef 的 fail-fast);
# - 解析期合成 `@t.NoVTable` 装饰器 + 追加 `t.CStruct` 标记基类, # - 解析期合成 `@NoVTable` 装饰器 + 追加 `CStruct` 标记基类,
# 与手写 `@t.NoVTable class X(t.CStruct):` 逐字段同形 ⇒ 下游 # 与手写 `@NoVTable class X(CStruct):` 逐字段同形 ⇒ 下游
# (HandlesClassDef._resolve_class_flags / _MARKER_BASES)零新增判据。 # (HandlesClassDef._resolve_class_flags / _MARKER_BASES)零新增判据。
# - 允许出现在 REnum 内部(REnum 变体本就是嵌套 ClassDef),也允许 struct 内 # - 允许出现在 REnum 内部(REnum 变体本就是嵌套 ClassDef),也允许 struct 内
# 再写 struct(与 class 内写 class 同口径)。 # 再写 struct(与 class 内写 class 同口径)。
@@ -93,7 +93,7 @@ _STRUCT_EXAMPLE: str = (
# 解析时 desugar 为 is_switch=True 的 N.Match。 # 解析时 desugar 为 is_switch=True 的 N.Match。
_SWITCH_KEYWORD: str = 'switch' _SWITCH_KEYWORD: str = 'switch'
# fallthrough 关键字(硬):仅在 switch 的 case 体内合法,脱糖为 `c.NoBreak()` # fallthrough 关键字(硬):仅在 switch 的 case 体内合法,脱糖为 `NoBreak()`
# 标记调用(switch 生成侧据此让 case 体不自动跳出 switch,落到下一个 case)。 # 标记调用(switch 生成侧据此让 case 体不自动跳出 switch,落到下一个 case)。
_FALLTHROUGH_KEYWORD: str = 'fallthrough' _FALLTHROUGH_KEYWORD: str = 'fallthrough'
@@ -107,13 +107,13 @@ _FALLTHROUGH_KEYWORD: str = 'fallthrough'
# celif E: → 同链下一个 If(test=c.@CIf(E), ...)(挂在上一支 orelse) # celif E: → 同链下一个 If(test=c.@CIf(E), ...)(挂在上一支 orelse)
# celse: → 普通 orelse # celse: → 普通 orelse
# defined(N) → c.@CIfdef(N) 标记调用 # defined(N) → c.@CIfdef(N) 标记调用
# 标记(c.@CIf / c.@CIfdef)是内部表示:用户写 c.CIf(...) 在 ExprParser 处报错。 # 标记(c.@CIf / c.@CIfdef)是内部表示:用户写 CIf(...) 在 ExprParser 处报错。
_CIF_KEYWORD: str = 'cif' _CIF_KEYWORD: str = 'cif'
_CELIF_KEYWORD: str = 'celif' _CELIF_KEYWORD: str = 'celif'
_CELSE_KEYWORD: str = 'celse' _CELSE_KEYWORD: str = 'celse'
# 内部 CIf 族标记:desugar 产出的调用名(用户不可写)。 # 内部 CIf 族标记:desugar 产出的调用名(用户不可写)。
# 与 Viper 侧解析器(includes/ast/parser.vp 的 _MakeCifMarker)同拼写:属性名带前导 '@', # 与 Viper 侧解析器(includes/ast/parser.vp 的 _MakeCifMarker)同拼写:属性名带前导 '@',
# 词法器无法产出该拼写,故用户写的 c.CIf(...) 永远不会命中此标记(会被 ExprParser 拒绝)。 # 词法器无法产出该拼写,故用户写的 CIf(...) 永远不会命中此标记(会被 ExprParser 拒绝)。
_CIF_MARKER: str = '@CIf' _CIF_MARKER: str = '@CIf'
_CIFDEF_MARKER: str = '@CIfdef' _CIFDEF_MARKER: str = '@CIfdef'
# cif 语句起始判定:语句起始 NAME('cif') 后紧跟这些运算符时按普通语句(赋值/注解) # cif 语句起始判定:语句起始 NAME('cif') 后紧跟这些运算符时按普通语句(赋值/注解)
@@ -166,10 +166,10 @@ class Parser(ExprParserMixin):
tok: Token = self._Peek() tok: Token = self._Peek()
if tok.Type == NAME: if tok.Type == NAME:
v: str = tok.Value v: str = tok.Value
# extern 函数声明(FFI,等价 t.State)——必须在软关键字 def 分派之前 # extern 函数声明(FFI,等价 State)——必须在软关键字 def 分派之前
if v == 'extern': if v == 'extern':
return self._ParseExternDef() return self._ParseExternDef()
# export 函数声明(等价 t.CExport,裸名导出不增加 SHA1 头)—— # export 函数声明(等价 CExport,裸名导出不增加 SHA1 头)——
# 必须在软关键字 def 分派之前 # 必须在软关键字 def 分派之前
if v == 'export': if v == 'export':
return self._ParseExportDef() return self._ParseExportDef()
@@ -177,25 +177,25 @@ class Parser(ExprParserMixin):
# 仅 `static def 名字` 形态判定为函数定义——判据必须同时要求第二个 token # 仅 `static def 名字` 形态判定为函数定义——判据必须同时要求第二个 token
# 是 `def`,故 `static = 5` / `static x = 5` 不会被误吃成函数定义。 # 是 `def`,故 `static = 5` / `static x = 5` 不会被误吃成函数定义。
# 变量形式 `static 名字: 类型 = 值` 不在本层处理,由 SymbolUtils 的前置 # 变量形式 `static 名字: 类型 = 值` 不在本层处理,由 SymbolUtils 的前置
# 修饰符展开统一脱糖为 `名字: t.CStatic | 类型 = 值`。 # 修饰符展开统一脱糖为 `名字: CStatic | 类型 = 值`。
if (v == 'static' and self._Peek(1).Type == NAME if (v == 'static' and self._Peek(1).Type == NAME
and self._Peek(1).Value == 'def'): and self._Peek(1).Value == 'def'):
return self._ParseStaticDef() return self._ParseStaticDef()
# define 宏函数定义(与 def 语义一致,返回注解自动追加 t.CDefine # define 宏函数定义(与 def 语义一致,返回注解自动追加 CDefine
# 标记为宏函数;软关键字:仅"define + 标识符"形态才判定为函数定义, # 标记为宏函数;软关键字:仅"define + 标识符"形态才判定为函数定义,
# 变量名/调用(define = 5、define(x))不受影响)——必须在软关键字 # 变量名/调用(define = 5、define(x))不受影响)——必须在软关键字
# def 分派之前 # def 分派之前
if v == 'define' and self._Peek(1).Type == NAME: if v == 'define' and self._Peek(1).Type == NAME:
return self._ParseDefineDef() return self._ParseDefineDef()
# virtual / novirtual 修饰符(软关键字):只在"语句起始 + 紧跟 class/def" # virtual / novirtual 修饰符(软关键字):只在"语句起始 + 紧跟 class/def"
# 时生效,合成既有装饰器 @t.CVTable / @t.NoVTable(见 _ParseVirtualModified)。 # 时生效,合成既有装饰器 @CVTable / @NoVTable(见 _ParseVirtualModified)。
# 放在 def/class 分派之前:修饰符必须先被消费,class/def 才能照常分派。 # 放在 def/class 分派之前:修饰符必须先被消费,class/def 才能照常分派。
# 与软关键字 fn→def 的先后关系:`.vp` 源码在进入本解析器之前已过 # 与软关键字 fn→def 的先后关系:`.vp` 源码在进入本解析器之前已过
# SymbolUtils.ExpandSoftKeywords(fn/fun/func/function → def), # SymbolUtils.ExpandSoftKeywords(fn/fun/func/function → def),
# 故 `virtual fn m()` 在此已是 `virtual def m()`;本层只认 class/def。 # 故 `virtual fn m()` 在此已是 `virtual def m()`;本层只认 class/def。
if v in _VIRTUAL_MARKERS: if v in _VIRTUAL_MARKERS:
return self._ParseVirtualModified() return self._ParseVirtualModified()
# tls 修饰符(软关键字):语句起始 + 紧跟 def 时生效,合成既有装饰器 @t.TLS。 # tls 修饰符(软关键字):语句起始 + 紧跟 def 时生效,合成既有装饰器 @TLS。
if v == _TLS_KEYWORD and self._IsTlsDefStart(): if v == _TLS_KEYWORD and self._IsTlsDefStart():
return self._ParseTlsModified() return self._ParseTlsModified()
# 软关键字函数定义:fn/fun/func/function + 标识符 # 软关键字函数定义:fn/fun/func/function + 标识符
@@ -242,7 +242,7 @@ class Parser(ExprParserMixin):
if v == _SWITCH_KEYWORD: if v == _SWITCH_KEYWORD:
return self._ParseSwitch() return self._ParseSwitch()
# fallthrough 关键字(硬):仅在 switch 的 case 体内合法,脱糖为 # fallthrough 关键字(硬):仅在 switch 的 case 体内合法,脱糖为
# `c.NoBreak()` 标记调用,由 switch 生成侧消费(case 体因此不自动 # `NoBreak()` 标记调用,由 switch 生成侧消费(case 体因此不自动
# 跳出 switch)。合法位置由生成侧判定:写进 match 或 switch 之外 # 跳出 switch)。合法位置由生成侧判定:写进 match 或 switch 之外
# 一律 FailFastError。 # 一律 FailFastError。
if v == _FALLTHROUGH_KEYWORD: if v == _FALLTHROUGH_KEYWORD:
@@ -289,7 +289,7 @@ class Parser(ExprParserMixin):
# fallthrough 关键字(语句级) # fallthrough 关键字(语句级)
# ================================================================== # ==================================================================
def _ParseFallThrough(self) -> N.stmt: def _ParseFallThrough(self) -> N.stmt:
"""`fallthrough` 脱糖为 `c.NoBreak()`(switch 生成侧识别的 fallthrough 标记) """`fallthrough` 脱糖为 `NoBreak()`(switch 生成侧识别的 fallthrough 标记)
合法位置只有 switch 的 case 体;写进 match 或 switch 之外由生成侧 合法位置只有 switch 的 case 体;写进 match 或 switch 之外由生成侧
(HandlesMatch / HandlesBody)fail-fast。 (HandlesMatch / HandlesBody)fail-fast。
@@ -297,8 +297,7 @@ class Parser(ExprParserMixin):
tok: Token = self._Peek() tok: Token = self._Peek()
self._Next() self._Next()
marker: N.Call = N.Call( marker: N.Call = N.Call(
func=N.Attribute(value=N.Name(id='c', ctx=N.Load()), func=N.Name(id='NoBreak', ctx=N.Load()),
attr='NoBreak', ctx=N.Load()),
args=[], keywords=[]) args=[], keywords=[])
node: N.Expr = N.Expr(value=marker) node: N.Expr = N.Expr(value=marker)
self._FixLoc(node, tok) self._FixLoc(node, tok)
@@ -423,9 +422,9 @@ class Parser(ExprParserMixin):
@staticmethod @staticmethod
def _IsCTypedefAnnotation(annotation: N.expr | None) -> bool: def _IsCTypedefAnnotation(annotation: N.expr | None) -> bool:
"""注解是否为 typedef 标记(裸 `CTypedef` / `t.CTypedef` / 含它的 `|` 联合)。 """注解是否为 typedef 标记(裸 `CTypedef` / `CTypedef` / 含它的 `|` 联合)。
用于把 typedef 的右值按**类型位置**解析(`X: t.CTypedef = const uint16*` 用于把 typedef 的右值按**类型位置**解析(`X: CTypedef = const uint16*`
里的 `*` 后缀由 _ParseTypeAnnotation 消费,与注解位同一规则;描述符 里的 `*` 后缀由 _ParseTypeAnnotation 消费,与注解位同一规则;描述符
`const`/`volatile` 已由 SymbolUtils._ExpandTypeDescriptors 在文本层展开)。 `const`/`volatile` 已由 SymbolUtils._ExpandTypeDescriptors 在文本层展开)。
仅按标记名判定,不依赖 import 别名表(与 VPC `_IsCTypedefAnnotation` 同口径)。 仅按标记名判定,不依赖 import 别名表(与 VPC `_IsCTypedefAnnotation` 同口径)。
@@ -447,7 +446,7 @@ class Parser(ExprParserMixin):
注意:仅当目标为简单 Name/Attribute/Subscript 且后随 ':' 时匹配; 注意:仅当目标为简单 Name/Attribute/Subscript 且后随 ':' 时匹配;
元组/列表解包不做注解(返回 None 走普通路径)。 元组/列表解包不做注解(返回 None 走普通路径)。
`t.CTypedef` 注解的右值是**类型**而非一般表达式(`const str` / `uint16*`), `CTypedef` 注解的右值是**类型**而非一般表达式(`const str` / `uint16*`),
故走 `_ParseTypeAnnotation`(与注解位同一路径,支持 C 式指针后缀)。 故走 `_ParseTypeAnnotation`(与注解位同一路径,支持 C 式指针后缀)。
""" """
start: Token = self._Peek() start: Token = self._Peek()
@@ -725,7 +724,7 @@ class Parser(ExprParserMixin):
# `@deco` 与 `virtual class`/`virtual def` 组合:合成标记追加在既有装饰器之后 # `@deco` 与 `virtual class`/`virtual def` 组合:合成标记追加在既有装饰器之后
return self._ParseVirtualModified(decorators=decorator_list) return self._ParseVirtualModified(decorators=decorator_list)
if tok.Type == NAME and tok.Value == _TLS_KEYWORD and self._IsTlsDefStart(): if tok.Type == NAME and tok.Value == _TLS_KEYWORD and self._IsTlsDefStart():
# `@deco` 与 `tls def` 组合:合成 @t.TLS 追加在既有装饰器之后 # `@deco` 与 `tls def` 组合:合成 @TLS 追加在既有装饰器之后
return self._ParseTlsModified(decorators=decorator_list) return self._ParseTlsModified(decorators=decorator_list)
raise SyntaxError(f"decorator must be followed by def/class, got {tok.Value!r}") raise SyntaxError(f"decorator must be followed by def/class, got {tok.Value!r}")
@@ -760,9 +759,9 @@ class Parser(ExprParserMixin):
def _ParseVirtualModified(self, decorators: list[N.expr] | None = None) -> N.stmt: def _ParseVirtualModified(self, decorators: list[N.expr] | None = None) -> N.stmt:
"""`virtual class` / `novirtual class` / `virtual def` / `novirtual def`。 """`virtual class` / `novirtual class` / `virtual def` / `novirtual def`。
合成 `@t.CVTable` / `@t.NoVTable` 装饰器后交给 _ParseClassDef / 合成 `@CVTable` / `@NoVTable` 装饰器后交给 _ParseClassDef /
_ParseFunctionDef,产出与**手写同名装饰器**逐字段同形的 AST _ParseFunctionDef,产出与**手写同名装饰器**逐字段同形的 AST
(decorator_list 多一个 Attribute(Name('t', Load), 'CVTable'|'NoVTable', Load)), (decorator_list 多一个 Name('CVTable'|'NoVTable', Load)),
故下游(_resolve_class_flags / _should_method_be_virtual 同族判据)零新增分支。 故下游(_resolve_class_flags / _should_method_be_virtual 同族判据)零新增分支。
非法形态**响亮失败**(不静默丢修饰符): 非法形态**响亮失败**(不静默丢修饰符):
@@ -786,7 +785,7 @@ class Parser(ExprParserMixin):
# 单独报文(而不是落到通用"后随非 class/def")以便直接给出修法。 # 单独报文(而不是落到通用"后随非 class/def")以便直接给出修法。
raise self._StructSyntaxError( raise self._StructSyntaxError(
f'{mod.Value} struct 非法:struct 禁止 virtual/novirtual 修饰', mod, f'{mod.Value} struct 非法:struct 禁止 virtual/novirtual 修饰', mod,
'struct 天然无虚表(解析期已合成 @t.NoVTable),请直接写 `struct X:`;' 'struct 天然无虚表(解析期已合成 @NoVTable),请直接写 `struct X:`;'
'需要虚表语义请改用 class。') '需要虚表语义请改用 class。')
raise self._VirtualSyntaxError( raise self._VirtualSyntaxError(
f"{mod.Value!r} 后随 {nxt_text}(非 class/def)", mod, f"{mod.Value!r} 后随 {nxt_text}(非 class/def)", mod,
@@ -799,8 +798,7 @@ class Parser(ExprParserMixin):
f'{mod.Value} def 描述的是「类体内方法的虚/非虚」,' f'{mod.Value} def 描述的是「类体内方法的虚/非虚」,'
f'模块级 / 函数体 / 分支体内没有可归属的类。') f'模块级 / 函数体 / 分支体内没有可归属的类。')
self._Next() # 消费修饰符 self._Next() # 消费修饰符
deco: N.expr = N.Attribute(value=N.Name(id='t', ctx=N.Load()), deco: N.expr = N.Name(id=marker, ctx=N.Load())
attr=marker, ctx=N.Load())
self._FixLoc(deco, mod) self._FixLoc(deco, mod)
deco_list: list[N.expr] = list(decorators or []) deco_list: list[N.expr] = list(decorators or [])
deco_list.append(deco) deco_list.append(deco)
@@ -824,16 +822,15 @@ class Parser(ExprParserMixin):
return False return False
def _ParseTlsModified(self, decorators: list[N.expr] | None = None) -> N.stmt: def _ParseTlsModified(self, decorators: list[N.expr] | None = None) -> N.stmt:
"""`tls def f(...)`:消费 tls,合成 `@t.TLS` 后交给 _ParseFunctionDef。 """`tls def f(...)`:消费 tls,合成 `@TLS` 后交给 _ParseFunctionDef。
与手写 `@t.TLS` 逐字段同形(decorator_list 追加 与手写 `@TLS` 逐字段同形(decorator_list 追加
Attribute(Name('t', Load), 'TLS', Load)),故下游一次性初始化的守卫生成路径 Name('TLS', Load)),故下游一次性初始化的守卫生成路径
(HandlesFunctions 的 TLS 分支)零新增判据。tls 对方法与模块级函数同样生效。 (HandlesFunctions 的 TLS 分支)零新增判据。tls 对方法与模块级函数同样生效。
""" """
mod: Token = self._Peek() # tls mod: Token = self._Peek() # tls
self._Next() # 消费修饰符 self._Next() # 消费修饰符
deco: N.expr = N.Attribute(value=N.Name(id='t', ctx=N.Load()), deco: N.expr = N.Name(id='TLS', ctx=N.Load())
attr='TLS', ctx=N.Load())
self._FixLoc(deco, mod) self._FixLoc(deco, mod)
deco_list: list[N.expr] = list(decorators or []) deco_list: list[N.expr] = list(decorators or [])
deco_list.append(deco) deco_list.append(deco)
@@ -852,7 +849,7 @@ class Parser(ExprParserMixin):
f"[TPC] struct 定义非法({detail}):行 {tok.Line} 列 {tok.Col}," f"[TPC] struct 定义非法({detail}):行 {tok.Line} 列 {tok.Col},"
f"源码片段 {self._SourceLine(tok.Line).strip()!r}。" f"源码片段 {self._SourceLine(tok.Line).strip()!r}。"
f"struct 与 class 同形,但**只能表示数据类型**:" f"struct 与 class 同形,但**只能表示数据类型**:"
f"① 禁止 virtual / novirtual 修饰(struct 天然无虚表,已内置 @t.NoVTable);" f"① 禁止 virtual / novirtual 修饰(struct 天然无虚表,已内置 @NoVTable);"
f"② 禁止在 struct 内定义 def(需要方法请改用 class);" f"② 禁止在 struct 内定义 def(需要方法请改用 class);"
f"③ 允许在 REnum 内作为变体、也允许 struct 内再写 struct。" f"③ 允许在 REnum 内作为变体、也允许 struct 内再写 struct。"
f"正确示例:{_STRUCT_EXAMPLE}。" f"正确示例:{_STRUCT_EXAMPLE}。"
@@ -862,28 +859,26 @@ class Parser(ExprParserMixin):
) )
def _ParseStructDef(self, decorators: list[N.expr] | None = None) -> N.ClassDef: def _ParseStructDef(self, decorators: list[N.expr] | None = None) -> N.ClassDef:
"""`struct X:` / `struct X(Base):` → 与 `@t.NoVTable class X(t.CStruct):` """`struct X:` / `struct X(Base):` → 与 `@NoVTable class X(CStruct):`
逐字段同形的 ClassDef(与 VPC 的 _parse_structdef 同口径)。 逐字段同形的 ClassDef(与 VPC 的 _parse_structdef 同口径)。
实现:复用 _ParseClassDef 的完整解析路径(类型参数 / 基类 / 关键字实参 / 实现:复用 _ParseClassDef 的完整解析路径(类型参数 / 基类 / 关键字实参 /
类体套件),只在**解析前后**补三件事: 类体套件),只在**解析前后**补三件事:
· 解析前把合成的 `@t.NoVTable` 追加进装饰器列表(与 virtual/novirtual · 解析前把合成的 `@NoVTable` 追加进装饰器列表(与 virtual/novirtual
同款表示)⇒ 类级强制无虚表,即使父类带虚表; 同款表示)⇒ 类级强制无虚表,即使父类带虚表;
· 解析后把 `t.CStruct` 标记基类**追加**到 bases 末尾(不提位用户基类, · 解析后把 `CStruct` 标记基类**追加**到 bases 末尾(不提位用户基类,
真实父类解析顺序不变)⇒ 数据类语义(_MARKER_BASES 认它,不当真实父类); 真实父类解析顺序不变)⇒ 数据类语义(_MARKER_BASES 认它,不当真实父类);
· 解析后校验类体**直接子节点**里没有 def —— struct 只能表示数据类型。 · 解析后校验类体**直接子节点**里没有 def —— struct 只能表示数据类型。
_ParseClassDef 的首个 `_Next()` 消费的正是 `struct` 关键字本身,故本函数 _ParseClassDef 的首个 `_Next()` 消费的正是 `struct` 关键字本身,故本函数
不预先消费,行号/列号与写法均继承自该 token。 不预先消费,行号/列号与写法均继承自该 token。
""" """
start: Token = self._Peek() # struct(由 _ParseClassDef 的 _Next() 消费) start: Token = self._Peek() # struct(由 _ParseClassDef 的 _Next() 消费)
deco: N.expr = N.Attribute(value=N.Name(id='t', ctx=N.Load()), deco: N.expr = N.Name(id='NoVTable', ctx=N.Load())
attr='NoVTable', ctx=N.Load())
self._FixLoc(deco, start) self._FixLoc(deco, start)
deco_list: list[N.expr] = list(decorators or []) deco_list: list[N.expr] = list(decorators or [])
deco_list.append(deco) deco_list.append(deco)
node: N.ClassDef = self._ParseClassDef(decorators=deco_list) node: N.ClassDef = self._ParseClassDef(decorators=deco_list)
marker_base: N.expr = N.Attribute(value=N.Name(id='t', ctx=N.Load()), marker_base: N.expr = N.Name(id='CStruct', ctx=N.Load())
attr='CStruct', ctx=N.Load())
self._FixLoc(marker_base, start) self._FixLoc(marker_base, start)
node.bases.append(marker_base) node.bases.append(marker_base)
for item in node.body: for item in node.body:
@@ -926,7 +921,7 @@ class Parser(ExprParserMixin):
return node return node
def _ParseExternDef(self, decorators: list[N.expr] | None = None) -> N.FunctionDef: def _ParseExternDef(self, decorators: list[N.expr] | None = None) -> N.FunctionDef:
"""解析 extern 函数声明(FFI,与 t.State 作用相当)。 """解析 extern 函数声明(FFI,与 State 作用相当)。
允许语法(均声明不定义,不生成函数体): 允许语法(均声明不定义,不生成函数体):
extern def A(x: int) -> int: pass extern def A(x: int) -> int: pass
@@ -934,7 +929,7 @@ class Parser(ExprParserMixin):
extern def A(x: int) -> int extern def A(x: int) -> int
extern A(x: int) -> int extern A(x: int) -> int
产出标准 FunctionDef 节点,返回注解改写为 ``<原类型> | t.State`` 产出标准 FunctionDef 节点,返回注解改写为 ``<原类型> | State``
以复用 TPC 的 IsState 路径;并设自定义属性 ``Extern = True`` 以复用 TPC 的 IsState 路径;并设自定义属性 ``Extern = True``
供 Unparser 还原 extern 语法。 供 Unparser 还原 extern 语法。
""" """
@@ -960,9 +955,8 @@ class Parser(ExprParserMixin):
type_comment=None, type_params=type_params, type_comment=None, type_params=type_params,
) )
node.Extern = True node.Extern = True
# 返回注解改写为 <原类型> | t.State,使 TPC 识别为 State 函数(仅声明) # 返回注解改写为 <原类型> | State,使 TPC 识别为 State 函数(仅声明)
state_attr: N.expr = N.Attribute(value=N.Name(id='t', ctx=N.Load()), state_attr: N.expr = N.Name(id='State', ctx=N.Load())
attr='State', ctx=N.Load())
if returns is not None: if returns is not None:
node.returns = N.BinOp(left=returns, op=N.BitOr(), right=state_attr) node.returns = N.BinOp(left=returns, op=N.BitOr(), right=state_attr)
else: else:
@@ -971,7 +965,7 @@ class Parser(ExprParserMixin):
return node return node
def _ParseExportDef(self, decorators: list[N.expr] | None = None) -> N.FunctionDef: def _ParseExportDef(self, decorators: list[N.expr] | None = None) -> N.FunctionDef:
"""解析 export 函数声明(等价 t.CExport,导出裸名、不加模块 SHA1 头)。 """解析 export 函数声明(等价 CExport,导出裸名、不加模块 SHA1 头)。
允许语法(与 extern 对称,配不配 def 都一样): 允许语法(与 extern 对称,配不配 def 都一样):
export def A(x: int) -> int: pass export def A(x: int) -> int: pass
@@ -979,7 +973,7 @@ class Parser(ExprParserMixin):
export def A(x: int) -> int export def A(x: int) -> int
export A(x: int) -> int export A(x: int) -> int
产出标准 FunctionDef 节点,返回注解改写为 ``<原类型> | t.CExport`` 产出标准 FunctionDef 节点,返回注解改写为 ``<原类型> | CExport``
以复用 TPC 的 CExport 路径(符号名不增加 SHA1 前缀);并设自定义 以复用 TPC 的 CExport 路径(符号名不增加 SHA1 前缀);并设自定义
属性 ``Export = True`` 供 Unparser 还原 export 语法。 属性 ``Export = True`` 供 Unparser 还原 export 语法。
""" """
@@ -1005,10 +999,9 @@ class Parser(ExprParserMixin):
type_comment=None, type_params=type_params, type_comment=None, type_params=type_params,
) )
node.Export = True node.Export = True
# 返回注解改写为 <原类型> | t.CExport,使 TPC 识别为 CExport 函数 # 返回注解改写为 <原类型> | CExport,使 TPC 识别为 CExport 函数
# (导出裸名,不增加模块 SHA1 头;有条件情况下导出) # (导出裸名,不增加模块 SHA1 头;有条件情况下导出)
export_attr: N.expr = N.Attribute(value=N.Name(id='t', ctx=N.Load()), export_attr: N.expr = N.Name(id='CExport', ctx=N.Load())
attr='CExport', ctx=N.Load())
if returns is not None: if returns is not None:
node.returns = N.BinOp(left=returns, op=N.BitOr(), right=export_attr) node.returns = N.BinOp(left=returns, op=N.BitOr(), right=export_attr)
else: else:
@@ -1017,7 +1010,7 @@ class Parser(ExprParserMixin):
return node return node
def _ParseStaticDef(self, decorators: list[N.expr] | None = None) -> N.FunctionDef: def _ParseStaticDef(self, decorators: list[N.expr] | None = None) -> N.FunctionDef:
"""解析 static 函数定义(等价 ``@t.CStatic``,与 ViperC 的 """解析 static 函数定义(等价 ``@CStatic``,与 ViperC 的
`_ParseStaticModified` 同源)。 `_ParseStaticModified` 同源)。
允许语法(与 export/extern 对称,配不配 def 都一样): 允许语法(与 export/extern 对称,配不配 def 都一样):
@@ -1025,11 +1018,11 @@ class Parser(ExprParserMixin):
static A(x: int) -> int: ... static A(x: int) -> int: ...
与 export/extern 的**两处不同**: 与 export/extern 的**两处不同**:
- **不改写返回注解**(不追加 `| t.CStatic` / `| t.State`):CStatic 是 - **不改写返回注解**(不追加 `| CStatic` / `| State`):CStatic 是
函数属性,由下面的合成装饰器承载,返回类型语义逐字不变; 函数属性,由下面的合成装饰器承载,返回类型语义逐字不变;
- **合成 `@t.CStatic` 装饰器**追加在既有装饰器之后,产出与**手写 - **合成 `@CStatic` 装饰器**追加在既有装饰器之后,产出与**手写
`@t.CStatic`** 逐字段同形(decorator_list 多一个 `@CStatic`** 逐字段同形(decorator_list 多一个
Attribute(Name('t', Load), 'CStatic', Load)),下游零新增判据。 Name('CStatic', Load)),下游零新增判据。
另设自定义属性 ``Static = True`` 供 Unparser 还原 static 语法 另设自定义属性 ``Static = True`` 供 Unparser 还原 static 语法
(镜像 Extern/Export;因 FunctionDef 的 __slots__ 槽位未含 Static 且 (镜像 Extern/Export;因 FunctionDef 的 __slots__ 槽位未含 Static 且
@@ -1051,9 +1044,8 @@ class Parser(ExprParserMixin):
if self._AtOp(':'): if self._AtOp(':'):
self._Next() self._Next()
body = self._ParseSuite() body = self._ParseSuite()
# 合成 @t.CStatic 装饰器(追加在既有装饰器之后) # 合成 @CStatic 装饰器(追加在既有装饰器之后)
static_attr: N.expr = N.Attribute(value=N.Name(id='t', ctx=N.Load()), static_attr: N.expr = N.Name(id='CStatic', ctx=N.Load())
attr='CStatic', ctx=N.Load())
self._FixLoc(static_attr, start) self._FixLoc(static_attr, start)
deco_list: list[N.expr] = list(decorators or []) deco_list: list[N.expr] = list(decorators or [])
deco_list.append(static_attr) deco_list.append(static_attr)
@@ -1066,7 +1058,7 @@ class Parser(ExprParserMixin):
# 注:FunctionDef 是 __slots__ 类(见 vast/Nodes.py 的 _FUNC_ATTRS,当前槽位 # 注:FunctionDef 是 __slots__ 类(见 vast/Nodes.py 的 _FUNC_ATTRS,当前槽位
# 为 Extern/Export/Define,未含 Static)——补槽位需改第三个文件(本次不许可), # 为 Extern/Export/Define,未含 Static)——补槽位需改第三个文件(本次不许可),
# 故仅在槽位存在时设置,避免 AttributeError 中断解析;下游对 static 函数的 # 故仅在槽位存在时设置,避免 AttributeError 中断解析;下游对 static 函数的
# 识别靠上面合成的 @t.CStatic 装饰器(HandlesFunctions 的存储类装饰器分支), # 识别靠上面合成的 @CStatic 装饰器(HandlesFunctions 的存储类装饰器分支),
# 与 virtual/novirtual 仅合成装饰器同构。 # 与 virtual/novirtual 仅合成装饰器同构。
if hasattr(type(node), 'Static'): if hasattr(type(node), 'Static'):
node.Static = True node.Static = True
@@ -1080,8 +1072,8 @@ class Parser(ExprParserMixin):
define A(x: int) -> int: ... define A(x: int) -> int: ...
define A(x: int): ... define A(x: int): ...
产出标准 FunctionDef 节点,返回注解改写为 ``<原类型> | t.CDefine`` 产出标准 FunctionDef 节点,返回注解改写为 ``<原类型> | CDefine``
(无显式返回注解时单独 ``t.CDefine``),使 TPC/VPC 复用既有的 (无显式返回注解时单独 ``CDefine``),使 TPC/VPC 复用既有的
CDefine 宏函数识别路径(StubGen 原样保留生成 C #define、 CDefine 宏函数识别路径(StubGen 原样保留生成 C #define、
alwaysinline 内联);并设自定义属性 ``Define = True`` 供 alwaysinline 内联);并设自定义属性 ``Define = True`` 供
Unparser 还原 define 语法。 Unparser 还原 define 语法。
@@ -1104,10 +1096,9 @@ class Parser(ExprParserMixin):
type_comment=None, type_params=type_params, type_comment=None, type_params=type_params,
) )
node.Define = True node.Define = True
# 返回注解改写为 <原类型> | t.CDefine,使下游识别为宏函数 # 返回注解改写为 <原类型> | CDefine,使下游识别为宏函数
# (StubGen 保留原样输出 C #define;TPC 标记 alwaysinline 内联) # (StubGen 保留原样输出 C #define;TPC 标记 alwaysinline 内联)
define_attr: N.expr = N.Attribute(value=N.Name(id='t', ctx=N.Load()), define_attr: N.expr = N.Name(id='CDefine', ctx=N.Load())
attr='CDefine', ctx=N.Load())
if returns is not None: if returns is not None:
node.returns = N.BinOp(left=returns, op=N.BitOr(), right=define_attr) node.returns = N.BinOp(left=returns, op=N.BitOr(), right=define_attr)
else: else:
@@ -1298,7 +1289,7 @@ class Parser(ExprParserMixin):
return node return node
# ================================================================== # ==================================================================
# cif / celif / celse 编译期条件编译(软关键字,desugar 到 c.CIf 标记) # cif / celif / celse 编译期条件编译(软关键字,desugar 到 CIf 标记)
# ================================================================== # ==================================================================
def _IsCIfStatementStart(self) -> bool: def _IsCIfStatementStart(self) -> bool:
"""语句起始 NAME('cif') 是否按 cif 语句解析。 """语句起始 NAME('cif') 是否按 cif 语句解析。
@@ -1312,9 +1303,8 @@ class Parser(ExprParserMixin):
return True return True
def _MakeCIfMarkerCall(self, attr: str, expr: N.expr, start: Token) -> N.Call: def _MakeCIfMarkerCall(self, attr: str, expr: N.expr, start: Token) -> N.Call:
"""构造内部标记调用 `c.<attr>(expr)`(用户不可写;cif/defined 的 desugar)。""" """构造内部标记调用 `<attr>(expr)`(用户不可写;cif/defined 的 desugar)。"""
func: N.Attribute = N.Attribute( func: N.Name = N.Name(id=attr, ctx=N.Load())
value=N.Name(id='c', ctx=N.Load()), attr=attr, ctx=N.Load())
self._FixLoc(func, start) self._FixLoc(func, start)
call: N.Call = N.Call(func=func, args=[expr], keywords=[]) call: N.Call = N.Call(func=func, args=[expr], keywords=[])
self._FixLoc(call, start) self._FixLoc(call, start)
+7 -10
View File
@@ -1,6 +1,6 @@
"""vast.unparser - AST 还原为源码字符串(与 ast.unparse 语义一致) """vast.unparser - AST 还原为源码字符串(与 ast.unparse 语义一致)
TPC 编译器多处用 ``ast.unparse`` 提取类型注解字符串(如 ``t.CArray[...]``、 TPC 编译器多处用 ``ast.unparse`` 提取类型注解字符串(如 ``CArray[...]``、
``list[i32, N]``、数组维度、默认值文本等)。本模块实现全部节点类型的 ``list[i32, N]``、数组维度、默认值文本等)。本模块实现全部节点类型的
源码还原,保证 ``import vast as ast`` 后这些调用零修改。 源码还原,保证 ``import vast as ast`` 后这些调用零修改。
""" """
@@ -88,22 +88,19 @@ class Unparser:
ret: str = '' ret: str = ''
returns: N.expr | None = node.returns returns: N.expr | None = node.returns
if is_extern and isinstance(returns, N.BinOp) and isinstance(returns.op, N.BitOr): if is_extern and isinstance(returns, N.BinOp) and isinstance(returns.op, N.BitOr):
# 还原 extern 原始注解:去掉改写时追加的 | t.State # 还原 extern 原始注解:去掉改写时追加的 | State
right: N.expr = returns.right right: N.expr = returns.right
if (isinstance(right, N.Attribute) and right.attr == 'State' if isinstance(right, N.Name) and right.id == 'State':
and isinstance(right.value, N.Name) and right.value.id == 't'):
returns = returns.left returns = returns.left
if is_export and isinstance(returns, N.BinOp) and isinstance(returns.op, N.BitOr): if is_export and isinstance(returns, N.BinOp) and isinstance(returns.op, N.BitOr):
# 还原 export 原始注解:去掉改写时追加的 | t.CExport # 还原 export 原始注解:去掉改写时追加的 | CExport
right = returns.right right = returns.right
if (isinstance(right, N.Attribute) and right.attr == 'CExport' if isinstance(right, N.Name) and right.id == 'CExport':
and isinstance(right.value, N.Name) and right.value.id == 't'):
returns = returns.left returns = returns.left
if is_define and isinstance(returns, N.BinOp) and isinstance(returns.op, N.BitOr): if is_define and isinstance(returns, N.BinOp) and isinstance(returns.op, N.BitOr):
# 还原 define 原始注解:去掉改写时追加的 | t.CDefine # 还原 define 原始注解:去掉改写时追加的 | CDefine
right = returns.right right = returns.right
if (isinstance(right, N.Attribute) and right.attr == 'CDefine' if isinstance(right, N.Name) and right.id == 'CDefine':
and isinstance(right.value, N.Name) and right.value.id == 't'):
returns = returns.left returns = returns.left
if returns is not None: if returns is not None:
ret = f' -> {self._expr(returns)}' ret = f' -> {self._expr(returns)}'
+33 -83
View File
@@ -3067,7 +3067,7 @@ static PyObject *ParseCallTail(Parser *P, PyObject *Func, Token *Start) {
return Node; return Node;
} }
/* 被调用者限定名:Name('X')→'X';Attribute(Name('c'),'X')→'c.X';否则 NULL(无异常)。 */ /* 被调用者限定名:Name('X')→'X';Attribute(Name('M'),'X')→'M.X';否则 NULL(无异常)。 */
static PyObject *MakeCifMarkerCall(Parser *P, const char *AttrName, PyObject *Expr, Token *Start); static PyObject *MakeCifMarkerCall(Parser *P, const char *AttrName, PyObject *Expr, Token *Start);
static PyObject *CalleeQualName(PyObject *Func) { static PyObject *CalleeQualName(PyObject *Func) {
if (NodeIs(Func, "Name")) { if (NodeIs(Func, "Name")) {
@@ -5600,36 +5600,20 @@ static PyObject *ParseFunctionDef(Parser *P, int IsAsync, PyObject *Decorators)
return Node; return Node;
} }
/* 构造 t.Attr 注解节点:Attribute(value=Name('t', Load), attr=AttrName, ctx=Load) */ /* 构造内建 attr 注解节点:Name(AttrName, Load) */
static PyObject *MakeTAttrNode(Parser *P, const char *AttrName) { static PyObject *MakeTAttrNode(Parser *P, const char *AttrName) {
PyObject *Load = MakeCtx(P, "Load"); PyObject *Load = MakeCtx(P, "Load");
PyObject *TName = PyUnicode_FromString("t"); PyObject *AttrStr = AttrName ? PyUnicode_FromString(AttrName) : NULL;
if (Load == NULL || TName == NULL) { if (Load == NULL || AttrStr == NULL) {
Py_XDECREF(Load); Py_XDECREF(Load);
Py_XDECREF(TName);
return NULL;
}
PyObject *ArgvN[2] = { TName, Load };
PyObject *TNode = NewNode(P, "Name", ArgvN, 2);
Py_DECREF(TName);
Py_DECREF(Load);
if (TNode == NULL) {
return NULL;
}
PyObject *Load2 = MakeCtx(P, "Load");
PyObject *AttrStr = PyUnicode_FromString(AttrName);
if (Load2 == NULL || AttrStr == NULL) {
Py_XDECREF(TNode);
Py_XDECREF(Load2);
Py_XDECREF(AttrStr); Py_XDECREF(AttrStr);
return NULL; return NULL;
} }
PyObject *ArgvA[3] = { TNode, AttrStr, Load2 }; PyObject *ArgvN[2] = { AttrStr, Load };
PyObject *AttrNode = NewNode(P, "Attribute", ArgvA, 3); PyObject *Node = NewNode(P, "Name", ArgvN, 2);
Py_DECREF(TNode);
Py_DECREF(AttrStr); Py_DECREF(AttrStr);
Py_DECREF(Load2); Py_DECREF(Load);
return AttrNode; return Node;
} }
/* extern/export 函数声明(FFI/裸名导出,对齐 vast Parser._ParseExternDef/_ParseExportDef)。 /* extern/export 函数声明(FFI/裸名导出,对齐 vast Parser._ParseExternDef/_ParseExportDef)。
@@ -6245,54 +6229,37 @@ static int IsCIfStatementStart(Parser *P) {
return 1; return 1;
} }
/* 构造内部标记调用 `c.<AttrName>(Expr)`(用户不可写)。 */ /* 构造内部标记调用 `<AttrName>(Expr)`。 */
static PyObject *MakeCifMarkerCall(Parser *P, const char *AttrName, PyObject *Expr, Token *Start) { static PyObject *MakeCifMarkerCall(Parser *P, const char *AttrName, PyObject *Expr, Token *Start) {
PyObject *Load1 = MakeCtx(P, "Load"); PyObject *Load = MakeCtx(P, "Load");
PyObject *IdC = Load1 ? PyUnicode_FromString("c") : NULL; PyObject *AttrStr = Load ? PyUnicode_FromString(AttrName) : NULL;
if (Load1 == NULL || IdC == NULL) { if (Load == NULL || AttrStr == NULL) {
Py_XDECREF(Load1); Py_XDECREF(Load);
Py_XDECREF(IdC);
return NULL;
}
PyObject *NameArgv[2] = { IdC, Load1 };
PyObject *NameNode = NewNode(P, "Name", NameArgv, 2);
Py_DECREF(IdC);
Py_DECREF(Load1);
if (NameNode == NULL) {
return NULL;
}
FixLoc(P, NameNode, Start);
PyObject *Load2 = MakeCtx(P, "Load");
PyObject *AttrStr = Load2 ? PyUnicode_FromString(AttrName) : NULL;
if (Load2 == NULL || AttrStr == NULL) {
Py_XDECREF(Load2);
Py_XDECREF(AttrStr); Py_XDECREF(AttrStr);
Py_DECREF(NameNode);
return NULL; return NULL;
} }
PyObject *AttrArgv[3] = { NameNode, AttrStr, Load2 }; PyObject *NameArgv[2] = { AttrStr, Load };
PyObject *AttrNode = NewNode(P, "Attribute", AttrArgv, 3); PyObject *FnNode = NewNode(P, "Name", NameArgv, 2);
Py_DECREF(AttrStr); Py_DECREF(AttrStr);
Py_DECREF(Load2); Py_DECREF(Load);
Py_DECREF(NameNode); if (FnNode == NULL) {
if (AttrNode == NULL) {
return NULL; return NULL;
} }
FixLoc(P, AttrNode, Start); FixLoc(P, FnNode, Start);
PyObject *Args = NewList(); PyObject *Args = NewList();
PyObject *Kw = NewList(); PyObject *Kw = NewList();
if (Args == NULL || Kw == NULL) { if (Args == NULL || Kw == NULL) {
Py_XDECREF(Args); Py_XDECREF(Args);
Py_XDECREF(Kw); Py_XDECREF(Kw);
Py_DECREF(AttrNode); Py_DECREF(FnNode);
return NULL; return NULL;
} }
PyList_Append(Args, Expr); PyList_Append(Args, Expr);
PyObject *CallArgv[3] = { AttrNode, Args, Kw }; PyObject *CallArgv[3] = { FnNode, Args, Kw };
PyObject *CallNode = NewNode(P, "Call", CallArgv, 3); PyObject *CallNode = NewNode(P, "Call", CallArgv, 3);
Py_DECREF(Args); Py_DECREF(Args);
Py_DECREF(Kw); Py_DECREF(Kw);
Py_DECREF(AttrNode); Py_DECREF(FnNode);
if (CallNode == NULL) { if (CallNode == NULL) {
return NULL; return NULL;
} }
@@ -7114,54 +7081,37 @@ static PyObject *ParseSwitch(Parser *P) {
return Node; return Node;
} }
/* `fallthrough` 脱糖为 `c.NoBreak()`(switch 生成侧识别的 fallthrough 标记) */ /* `fallthrough` 脱糖为 `NoBreak()`(switch 生成侧识别的 fallthrough 标记) */
static PyObject *ParseFallThrough(Parser *P) { static PyObject *ParseFallThrough(Parser *P) {
Token *Start = NextTok(P); /* fallthrough */ Token *Start = NextTok(P); /* fallthrough */
PyObject *Load1 = MakeCtx(P, "Load"); PyObject *Load1 = MakeCtx(P, "Load");
PyObject *IdC = Load1 ? PyUnicode_FromString("c") : NULL; PyObject *NameStr = Load1 ? PyUnicode_FromString("NoBreak") : NULL;
if (Load1 == NULL || IdC == NULL) { if (Load1 == NULL || NameStr == NULL) {
Py_XDECREF(Load1); Py_XDECREF(Load1);
Py_XDECREF(IdC); Py_XDECREF(NameStr);
return NULL; return NULL;
} }
PyObject *NameArgv[2] = { IdC, Load1 }; PyObject *NameArgv[2] = { NameStr, Load1 };
PyObject *NameNode = NewNode(P, "Name", NameArgv, 2); PyObject *FnNode = NewNode(P, "Name", NameArgv, 2);
Py_DECREF(IdC); Py_DECREF(NameStr);
Py_DECREF(Load1); Py_DECREF(Load1);
if (NameNode == NULL) { if (FnNode == NULL) {
return NULL; return NULL;
} }
FixLoc(P, NameNode, Start); FixLoc(P, FnNode, Start);
PyObject *Load2 = MakeCtx(P, "Load");
PyObject *AttrStr = Load2 ? PyUnicode_FromString("NoBreak") : NULL;
if (Load2 == NULL || AttrStr == NULL) {
Py_XDECREF(Load2);
Py_XDECREF(AttrStr);
Py_DECREF(NameNode);
return NULL;
}
PyObject *AttrArgv[3] = { NameNode, AttrStr, Load2 };
PyObject *AttrNode = NewNode(P, "Attribute", AttrArgv, 3);
Py_DECREF(AttrStr);
Py_DECREF(Load2);
Py_DECREF(NameNode);
if (AttrNode == NULL) {
return NULL;
}
FixLoc(P, AttrNode, Start);
PyObject *Args = NewList(); PyObject *Args = NewList();
PyObject *Keywords = NewList(); PyObject *Keywords = NewList();
if (Args == NULL || Keywords == NULL) { if (Args == NULL || Keywords == NULL) {
Py_XDECREF(Args); Py_XDECREF(Args);
Py_XDECREF(Keywords); Py_XDECREF(Keywords);
Py_DECREF(AttrNode); Py_DECREF(FnNode);
return NULL; return NULL;
} }
PyObject *CallArgv[3] = { AttrNode, Args, Keywords }; PyObject *CallArgv[3] = { FnNode, Args, Keywords };
PyObject *CallNode = NewNode(P, "Call", CallArgv, 3); PyObject *CallNode = NewNode(P, "Call", CallArgv, 3);
Py_DECREF(Args); Py_DECREF(Args);
Py_DECREF(Keywords); Py_DECREF(Keywords);
Py_DECREF(AttrNode); Py_DECREF(FnNode);
if (CallNode == NULL) { if (CallNode == NULL) {
return NULL; return NULL;
} }