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
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import vast as ast
|
||||
import copy
|
||||
import re
|
||||
from typing import List
|
||||
|
||||
@@ -581,6 +582,20 @@ class DeclarationGenerator:
|
||||
struct_type_name: str = f'%"{self.module_sha1}.{class_name}"' if self.module_sha1 else f'%struct.{class_name}'
|
||||
struct_decl: str = f'{struct_type_name} = type {{ {", ".join(member_types)} }}'
|
||||
decls.append(struct_decl)
|
||||
# 嵌套类 / 嵌套 struct:定义端以扁平名 `{外类}_{内类}` 发射(见 HandlesClassDef.
|
||||
# _EmitNestedClassDefs),此处同步产出同名完整类型声明 —— 否则跨模块引用
|
||||
# `外类.内类` 只会得到一个 opaque 前向声明(指针可用、字段偏移全失效)。
|
||||
# deepcopy 后改名再递归:本函数所有名字都派生自 node.name,改名即全链路一致;
|
||||
# 判断/枚举/联合等分支在递归时会各自按内层类自身的基类重新分派。
|
||||
for _nested_item in getattr(node, 'body', None) or []:
|
||||
if not isinstance(_nested_item, ast.ClassDef):
|
||||
continue
|
||||
_nested_inner: str | None = getattr(_nested_item, 'name', None)
|
||||
if not _nested_inner:
|
||||
continue
|
||||
_nested_node: ast.ClassDef = copy.deepcopy(_nested_item)
|
||||
_nested_node.name = f'{class_name}_{_nested_inner}'
|
||||
decls.extend(self._generate_class_decl(_nested_node))
|
||||
if is_cpython_object or is_cvtable:
|
||||
new_func_name: str = f'{class_name}.__before_init__'
|
||||
if self.module_sha1:
|
||||
@@ -1265,6 +1280,16 @@ class DeclarationGenerator:
|
||||
module_name = annotation.value.id
|
||||
elif isinstance(annotation.value, ast.Attribute) and hasattr(annotation.value, 'attr'):
|
||||
module_name = annotation.value.attr
|
||||
# 嵌套类 / 嵌套 struct:限定名 `外类.内类`(module_name 是**类名**而非模块名)。
|
||||
# 定义端以扁平名 `{外类}_{内类}` 发射(见 HandlesClassDef._EmitNestedClassDefs),
|
||||
# 故此处按扁平名拼类型;命中与否由 struct_names 里是否存在该扁平名裁决
|
||||
# (不存在即维持下方既有路径,不改变任何既有类型名)。
|
||||
if module_name and module_name != 't' and module_name != 'c':
|
||||
NestedName: str = f'{module_name}_{attr_name}'
|
||||
if NestedName in self.struct_names:
|
||||
NestedSha1: str | None = self.struct_sha1_map.get(NestedName, self.module_sha1)
|
||||
NestedStr: str = f'%"{NestedSha1}.{NestedName}"' if NestedSha1 else f'%struct.{NestedName}'
|
||||
return NestedStr if embedded else f'{NestedStr}*'
|
||||
if (module_name == 't' and attr_name == 'State') or attr_name == 'State':
|
||||
return ''
|
||||
if (module_name == 't' and attr_name == 'Callable') or attr_name == 'Callable':
|
||||
|
||||
Reference in new issue
Block a user