feat(struct): 嵌套 class/struct 发射为独立结构体 {外类}_{内类}
用户 2026-10-01 定:struct 内允许叠加 struct(与 class 内写 class 同口径)。
此前类体里的嵌套 ClassDef 在两个编译器里都被**静默丢弃**(字段遍历只认 AnnAssign、
方法遍历只认 FunctionDef),现按既有 REnum/union 嵌套命名先例发射为独立结构体。
命名与引用口径(双端同源):内层结构体 = {外类}_{内类}(多层递归 A_B_C);
引用两种写法都可用 —— 限定名 `外类.内类`、扁平名 `外类_内类`。
- HandlesClassDef.py:新增 _EmitNestedClassDefs(deepcopy + 改名后递归
_EmitClassLlvm,deepcopy 避免污染源码 AST)+ _RegisterNestedClassName
(SymbolTable 登记裸名/点号名/扁平名,对齐 REnum 变体的三键先例)。
- TypeAnnotationResolver.py:_from_node_attribute 增加嵌套分支 —— 限定名按**扁平名**
取条目并让 Name/BaseType 都是扁平名(否则会拼出 t.CStruct(name='内类'),
与声明端 `%"{sha}.外类_内类"` 不同源 ⇒ 布局分叉)。
- DeclarationGenerator.py:_get_type_str 支持 `外类.内类` → `%"{sha}.外类_内类"`;
_generate_class_decl 递归产出嵌套类型的完整声明(否则跨模块只拿到 opaque,
指针可用但字段偏移全失效)。
- Phase1Generator.py / Phase2Translator.py:跨模块注册表按扁平名登记嵌套类。
Phase2Translator 原先用 ast.walk 把嵌套类按**短名**登记(占住平坦命名空间、
与定义端不同源),改为递归扁平名。
实测(TPC 侧):嵌套类名字登记 {A_B, A_C, A_C_D};`x: A.B` → CTypeInfo(A_B);
声明端 `%"cafe.A" = type { i32, %"cafe.A_B" }` + `%"cafe.A_B" = type { i32 }`
+ 多层 `%"cafe.A_C_D" = type { i32 }`。
已知缺口(下一步):TransPyV 侧跨模块走 .vpi,VpiReader 只登记顶层类 ⇒ 跨模块引用
嵌套类型仍需在 VpiReader 侧补登记(同模块路径已通)。
This commit is contained in:
1 parent
a8f6ca006d
commit
5eef845e5b
5 files changed
+159
-3
No files matched your search
@@ -1384,7 +1384,7 @@ class Phase2Translator:
|
||||
_, tree = parse_python_file(pyi_path)
|
||||
if tree is None:
|
||||
continue
|
||||
for node in ast.walk(tree):
|
||||
for node in ast.iter_child_nodes(tree):
|
||||
# 每类只登记一次,**先扫到的为准**:判据必须是**类名**。
|
||||
# 原实现写成 `if sha1_key in struct_sha1_map` —— 用模块 SHA1 去查一张
|
||||
# 按**类名**建的表,判据恒假 ⇒ 实际是"后扫到的覆盖先扫到的",
|
||||
@@ -1392,10 +1392,33 @@ class Phase2Translator:
|
||||
# includes/ast/tokens.vp 各有一个 `class Keyword`,定义端拿到的前缀
|
||||
# 可能是**另一个模块**的 sha1 ⇒ 同一类出现两个 struct 实例、
|
||||
# `__before_init__` 声明与调用点分叉)。
|
||||
if isinstance(node, ast.ClassDef) and node.name not in struct_sha1_map:
|
||||
struct_sha1_map[node.name] = sha1_key
|
||||
if isinstance(node, ast.ClassDef):
|
||||
# 嵌套类按扁平名 `{外类}_{内类}` 登记(与定义端
|
||||
# HandlesClassDef._EmitNestedClassDefs、Phase1Generator.
|
||||
# _RegisterNestedStructNames 同源)。此前用 ast.walk 会把嵌套类按
|
||||
# **短名** `Inner` 登记 —— 既占住平坦命名空间,又与定义端的
|
||||
# `外类_内类` 不同源(跨模块前缀分裂)。
|
||||
self._RegisterStructSha1Rec(node, node.name, sha1_key, struct_sha1_map)
|
||||
return struct_sha1_map
|
||||
|
||||
def _RegisterStructSha1Rec(self, Node, FlatName: str, Sha1Key: str,
|
||||
StructSha1Map: dict) -> None:
|
||||
"""递归登记"类名 → 定义模块 SHA1"(嵌套类用扁平名 `{外类}_{内类}`)"""
|
||||
if not FlatName:
|
||||
return
|
||||
if FlatName not in StructSha1Map:
|
||||
StructSha1Map[FlatName] = Sha1Key
|
||||
Body = getattr(Node, 'body', None)
|
||||
if not Body:
|
||||
return
|
||||
for Item in Body:
|
||||
if not isinstance(Item, ast.ClassDef):
|
||||
continue
|
||||
InnerName: str | None = getattr(Item, 'name', None)
|
||||
if not InnerName:
|
||||
continue
|
||||
self._RegisterStructSha1Rec(Item, f'{FlatName}_{InnerName}', Sha1Key, StructSha1Map)
|
||||
|
||||
def run(self) -> None:
|
||||
"""扫描源目录,翻译并生成 .ll 含代码文件(导入遍历)"""
|
||||
import sys as _sys
|
||||
|
||||
Reference in new issue
Block a user