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:
1 parent
8d27747c7c
commit
f19d25782f
66 files changed
+2192
-3385
No files matched your search
+1
-1
@@ -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,
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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,
|
||||||
|
|||||||
@@ -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,12 +182,16 @@ 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):
|
||||||
|
_DecName = decorator.func.id
|
||||||
|
elif isinstance(decorator.func, ast.Attribute):
|
||||||
|
_DecName = decorator.func.attr
|
||||||
|
if _DecName == 'CReturn':
|
||||||
raise SyntaxError(
|
raise SyntaxError(
|
||||||
f"函数 '{node.name}':`@c.CReturn` 已移除:请改用返回注解 "
|
f"函数 '{node.name}':`CReturn` 不是内建标记;请改用返回注解 "
|
||||||
f"`-> tuple[ty1, ty2, ...]`(多返回值打包为 struct)"
|
f"`-> tuple[ty1, ty2, ...]`(多返回值打包为 struct)"
|
||||||
)
|
)
|
||||||
if node.returns:
|
if node.returns:
|
||||||
@@ -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'
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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] = {}
|
||||||
|
|||||||
@@ -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,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
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 / 平台宏。
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
@@ -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)
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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,13 +367,13 @@ 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)
|
||||||
if isinstance(arg.value, ast.Attribute):
|
and isinstance(arg.value, ast.Name)
|
||||||
if IsTModule(getattr(arg.value.value, 'id', ''), self.Trans.SymbolTable) and arg.value.attr == 'attr' and arg.attr == 'packed':
|
and arg.value.id == 'attr'
|
||||||
|
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:
|
||||||
@@ -496,7 +381,7 @@ class ClassHandle(BaseHandle):
|
|||||||
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
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
AttrName: str = expr.attr
|
||||||
return getattr(t.ASM_DESCR, AttrName, "")
|
return getattr(TypeSystem.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
|
|
||||||
return getattr(t.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
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
@@ -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):
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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,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,12 +390,9 @@ 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':
|
|
||||||
if node.func.attr == 'Deref':
|
|
||||||
return ir.IntType(64)
|
return ir.IntType(64)
|
||||||
if isinstance(node.func.value, ast.Name) and IsTModule(node.func.value.id, self.Trans.SymbolTable):
|
if func_name == 'CChar':
|
||||||
if node.func.attr == 'CChar':
|
|
||||||
return ir.PointerType(ir.IntType(8))
|
return ir.PointerType(ir.IntType(8))
|
||||||
return ir.IntType(32)
|
return ir.IntType(32)
|
||||||
elif isinstance(node, ast.Compare):
|
elif isinstance(node, ast.Compare):
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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,13 +1390,7 @@ 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 getattr(Node.annotation.value, 'id', None) == 't' and Node.annotation.attr == 'CDefine':
|
|
||||||
IsCDefine = True
|
|
||||||
elif getattr(Node.annotation.value, 'id', None) == 't' and Node.annotation.attr == 'CTypedef':
|
|
||||||
IsCTypedef = True
|
|
||||||
elif isinstance(Node.annotation, ast.Name):
|
|
||||||
if Node.annotation.id == 'CDefine':
|
if Node.annotation.id == 'CDefine':
|
||||||
IsCDefine = True
|
IsCDefine = True
|
||||||
elif Node.annotation.id == 'CTypedef':
|
elif Node.annotation.id == 'CTypedef':
|
||||||
@@ -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.attr == 'CVTable':
|
elif decorator.id == 'CVTable':
|
||||||
IsCVTable = True
|
IsCVTable = True
|
||||||
elif decorator.attr == 'NoVTable':
|
elif decorator.id == 'NoVTable':
|
||||||
IsNoVTable = True
|
IsNoVTable = True
|
||||||
elif decorator.attr == 'REnum':
|
elif decorator.id == 'REnum':
|
||||||
IsRenum = True
|
IsRenum = True
|
||||||
elif decorator.attr == 'CEnum' or decorator.attr == 'Enum':
|
elif decorator.id == 'CEnum' or decorator.id == '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)
|
||||||
if isinstance(arg.value, ast.Attribute):
|
and isinstance(arg.value, ast.Name)
|
||||||
if getattr(arg.value.value, 'id', None) == 't' and arg.value.attr == 'attr' and arg.attr == 'packed':
|
and arg.value.id == 'attr'
|
||||||
|
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]):
|
||||||
|
|||||||
@@ -350,20 +350,17 @@ 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
|
|
||||||
stmt.value.func.value.id == 'c' and
|
|
||||||
stmt.value.func.attr == 'NoBreak'):
|
|
||||||
return True
|
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):
|
||||||
@@ -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)
|
||||||
@@ -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,9 +95,8 @@ 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")
|
||||||
@@ -109,10 +107,10 @@ class CSpecialCallHandle(BaseHandle):
|
|||||||
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.attr == 'Addr' and target_arg.args:
|
elif target_arg.func.id == 'Addr' and target_arg.args:
|
||||||
target_ptr = self.HandleExprLlvm(target_arg)
|
target_ptr = self.HandleExprLlvm(target_arg)
|
||||||
elif isinstance(target_arg.func.value, ast.Name) and IsTModule(target_arg.func.value.id, self.Trans.SymbolTable):
|
else:
|
||||||
type_attr = target_arg.func.attr
|
type_attr = target_arg.func.id
|
||||||
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")
|
||||||
|
|||||||
@@ -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 = CTypeInfo()
|
||||||
Result.BaseType = TypeObj
|
Result.BaseType = TypeSystem.CVoid
|
||||||
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.BaseType = t.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
@@ -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"增量赋值与元素赋值,且不会降级为警告)"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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
@@ -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 ⇒
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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'
|
||||||
+31
-34
@@ -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):
|
if (isinstance(arg, ast.Attribute) and arg.attr == 'packed'
|
||||||
if isinstance(arg.value, ast.Attribute):
|
and isinstance(arg.value, ast.Name) and arg.value.id == 'attr'):
|
||||||
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
|
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(
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
+264
-322
File diff suppressed because it is too large.
Load diff
@@ -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
|
||||||
|
|||||||
@@ -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 点插桩(忽略白名单;体积/开销大)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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,15 +50,11 @@ 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
|
|
||||||
elif isinstance(decorator, ast.Name):
|
|
||||||
if decorator.id == 'NoVTable':
|
|
||||||
has_novtable = True
|
has_novtable = True
|
||||||
Gen._class_graph[Node.name] = {
|
Gen._class_graph[Node.name] = {
|
||||||
'bases': bases,
|
'bases': bases,
|
||||||
@@ -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,16 +289,8 @@ 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)
|
|
||||||
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)
|
self._HandleModuleLevelLLVMIR(call, Gen)
|
||||||
|
|
||||||
def _HandleModuleLevelLLVMIR(self, Node: ast.Call, Gen: LlvmCodeGenerator) -> None:
|
def _HandleModuleLevelLLVMIR(self, Node: ast.Call, Gen: LlvmCodeGenerator) -> None:
|
||||||
@@ -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)。于是同一类在本模块里出现
|
||||||
|
|||||||
@@ -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
|
|
||||||
annot_attr: str = NextNode.annotation.attr
|
|
||||||
if annot_id == 't' and NextNode.value:
|
|
||||||
if isinstance(NextNode.value, ast.Name):
|
|
||||||
ValueName: str = NextNode.value.id
|
ValueName: str = NextNode.value.id
|
||||||
if ValueName == ClassName:
|
if ValueName == ClassName:
|
||||||
# 检查是 CTypedef 还是 CPtr
|
# CPtr 表示指针变量,加入 TypedefAssignments,设置 IsPtr=True
|
||||||
if annot_attr == t.CPtr.__name__:
|
|
||||||
# t.CPtr 表示指针变量,加入 TypedefAssignments,设置 IsPtr=True
|
|
||||||
if ClassKey not in self.TypedefAssignments:
|
if ClassKey not in self.TypedefAssignments:
|
||||||
self.TypedefAssignments[ClassKey] = []
|
self.TypedefAssignments[ClassKey] = []
|
||||||
self.TypedefAssignments[ClassKey].append((TargetName, True))
|
self.TypedefAssignments[ClassKey].append((TargetName, True))
|
||||||
j += 1
|
j += 1
|
||||||
continue
|
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
|
||||||
@@ -316,7 +306,6 @@ class PythonParserMixin:
|
|||||||
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):
|
||||||
|
|||||||
+133
-208
@@ -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()
|
||||||
TypeObj: type | None = CTypeHelper.GetTModuleCType(TypeName)
|
if TypeName in ('CRef', 'CTempRef'):
|
||||||
if TypeObj is None:
|
|
||||||
TypeObj = getattr(t, TypeName, None)
|
|
||||||
if isinstance(TypeObj, type) and issubclass(TypeObj, t.CType) and TypeObj is not t.CType:
|
|
||||||
if TypeObj == t.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:
|
TypeObj: type | None = CTypeHelper.GetTModuleCType(TypeName)
|
||||||
|
if TypeObj is None:
|
||||||
|
TypeObj = getattr(TypeSystem, TypeName, None)
|
||||||
|
if isinstance(TypeObj, type) and issubclass(TypeObj, TypeSystem.CType) and TypeObj is not TypeSystem.CType:
|
||||||
|
if TypeObj == TypeSystem.CPtr:
|
||||||
|
Result: CTypeInfo = CTypeInfo()
|
||||||
|
Result.PtrCount = 1
|
||||||
|
Result.BaseType = TypeSystem.CVoid()
|
||||||
|
return Result
|
||||||
|
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,11 +706,9 @@ 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):
|
|
||||||
if Node.func.attr == 'Bit' and len(Node.args) > 0:
|
|
||||||
Result: CTypeInfo = CTypeInfo()
|
Result: CTypeInfo = CTypeInfo()
|
||||||
Result.BaseType = t.CInt()
|
Result.BaseType = TypeSystem.CInt()
|
||||||
Result.IsBitField = True
|
Result.IsBitField = True
|
||||||
if isinstance(Node.args[0], ast.Constant) and isinstance(Node.args[0].value, int):
|
if isinstance(Node.args[0], ast.Constant) and isinstance(Node.args[0].value, int):
|
||||||
Result.BitWidth = Node.args[0].value
|
Result.BitWidth = Node.args[0].value
|
||||||
@@ -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()
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
@@ -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 +0,0 @@
|
|||||||
"""类型系统与 C 语法定义 (t.py / c.py)"""
|
|
||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user