From c3f554f1f553dee2ab1de955a31c0ca55b83205b Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Thu, 1 Oct 2026 23:30:15 +0800 Subject: [PATCH] =?UTF-8?q?feat(struct):=20=E5=B5=8C=E5=A5=97=20class/stru?= =?UTF-8?q?ct=20=E5=8F=91=E5=B0=84=E4=B8=BA=E7=8B=AC=E7=AB=8B=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E4=BD=93=20{=E5=A4=96=E7=B1=BB}=5F{=E5=86=85=E7=B1=BB?= =?UTF-8?q?}?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户 2026-10-01 定:struct 内允许叠加 struct(与 class 内写 class 同口径)。 此前类体里的嵌套 ClassDef 被**静默丢弃**(字段循环只认 AnnAssign、 _translate_oop_methods 只认 FunctionDef),现按 TPC 侧 union/renum 的 `{ClassName}_{Nested}` 命名先例发射为独立结构体,与 TPC 提交 5eef845e 同源。 - ClassGenDef.vp:新增 _translate_nested_classdefs —— 在 enum/union/renum/泛型/ 异常分派之后、existing 检查之前(所有提前 return 之前,故 declare_only=1/0 都递归) 遍历类体 ClassDef 子节点,把子节点 name 临时改写为扁平名后递归 translate_class_def(本模块所有名字派生点都读 cd.name ⇒ 改名即全链路一致)。 两个护栏:扁平名分配在 PermPool(跨 Phase 存活);递归后还原 CurDefModuleSha1/ CurDefClassName(内层 mark_module_class 会覆盖,否则外层字段解析误判当前定义类)。 - TypeGenResolve.vp:新增 _resolve_nested_class_type 并在 Attribute 分支的 "base 不是模块" 出口前接上 —— 限定名 `外类.内类` 按扁平名查结构体表即可命中 (裸名 `外类_内类` 走既有 Name 分支天然命中)。判据两道:base 是已知类 (find_struct 命中,或正处于该类的定义窗口内);扁平名条目存在且 Ty 非空。 引用两种写法都可用:`外类.内类`、`外类_内类`;多层嵌套递归为 A_B_C。 --- App/lib/core/Gen/Class/ClassGenDef.vp | 74 ++++++++++++++++++++++++- App/lib/core/Gen/Type/TypeGenResolve.vp | 54 ++++++++++++++++++ 2 files changed, 127 insertions(+), 1 deletion(-) diff --git a/App/lib/core/Gen/Class/ClassGenDef.vp b/App/lib/core/Gen/Class/ClassGenDef.vp index 95aa0d9..b8ca19f 100644 --- a/App/lib/core/Gen/Class/ClassGenDef.vp +++ b/App/lib/core/Gen/Class/ClassGenDef.vp @@ -83,6 +83,15 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): if self.Gen.ClassGenBase._is_exception_class_def(cd) == 1: return self.Gen.ClassGenBase._register_exception_class_def(trans, cd) + # 嵌套类 / 嵌套 struct:类体里再写 class / struct 此前被**静默丢弃** + # (字段循环只认 AnnAssign、_translate_oop_methods 只认 FunctionDef), + # 现按既有扁平命名先例发射为独立结构体 `{外类}_{内类}`(与 TPC 的 + # union/renum 嵌套命名 `{ClassName}_{Nested}` 同源)。 + # 放在此处(enum/union/renum/泛型/异常分派之后、existing 检查之前): + # 位于**所有提前 return 之前**,故 declare_only=1/0 两条路径都会递归; + # 而 REnum/union 的嵌套类已由各自分支按"变体"处理并提前 return,不会重复发射。 + self._translate_nested_classdefs(trans, cd) + # 检查是否已注册(用 SHA1 区分跨模块同名类) existing: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(class_name, trans.ModuleSha1) # 空类注册不完整检测:existing FieldCount==0 但源类体声明了字段(vpi 注入/注册缺陷)。 @@ -650,4 +659,67 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): # ============================================================ self.Gen.ClassGenVTable._translate_oop_methods(trans, cd, struct_ty, class_name) - return 0 \ No newline at end of file + return 0 + + # ============================================================ + # _translate_nested_classdefs - 递归翻译类体内的嵌套 class / struct + # + # 命名与引用口径(用户 2026-10-01 定,与 TPC union/renum 嵌套命名同源): + # · 内层结构体 IR 名 = `{sha1}.{外类}_{内类}`(sha1 = 与外层相同的定义模块); + # · 引用两种写法都可:限定名 `外类.内类`(Attribute 兜底,见 TypeGenResolve) + # 与扁平名 `外类_内类`(裸名直查结构体表即可命中); + # · 多层嵌套自然递归为 `A_B_C`(递归时子节点名已被改写为 A_B)。 + # 实现选择"临时改写子节点 name 再递归"而非另写发射器:本模块所有名字派生点 + # (IR 名 {sha}.{名}、register_struct/add_field、AnnotClassName、方法符号名 + # `{类}.{方法}` 的 mangling、mark_module_class 键)都读 cd.name ⇒ 改名即全链路 + # 一致,且复用继承展平/packed/OOP/vtable 等全部既有逻辑,零新增判据。 + # 两个必须的护栏: + # ① 扁平名字符串分配在 PermPool —— 它要跨 Phase(1a/1b)存活,trans.Pool 会随 + # mark/reset 回收成悬空串(后续 strcmp 读悬空内存)。 + # ② 递归返回后**还原"正在定义类"窗口**(CurDefModuleSha1/CurDefClassName 会被 + # 内层 mark_module_class 覆盖)——不还原会让外层随后的字段注解解析误判 + # "当前定义类"(规则 5.5 的自引用窗口据此判定,误判会冻结裸名票名)。 + # ============================================================ + def _translate_nested_classdefs(self, trans: HT.Translator*, + cd: ast.ClassDef*) -> None: + """把本类体内的嵌套 ClassDef 逐个按 `{外类}_{内类}` 递归翻译""" + if trans is None or cd is None or cd.name is None: + return + children: list[ast.AST*]* = cd.children + if children is None: + return + cn: sizet = len(children) + ci: sizet = 0 + while ci < cn: + child_ast: ast.AST* = children.get(ci) + ci += 1 + if child_ast is None: + continue + if child_ast.kind() != ast.ASTKind.ClassDef: + continue + child: ast.ClassDef* = ast.ClassDef*(child_ast) + if child is None or child.name is None: + continue + # 扁平名 `{外类}_{内类}`(优先 PermPool:名字要跨 Phase 存活; + # PermPool 缺失时退回本遍池,行为与旧路径一致) + flat_pool: memhub.MemBuddy* = CompilerFactory.factory.PermPool + if flat_pool is None: + flat_pool = trans.Pool + if flat_pool is None: + continue + outer_len: sizet = string.strlen(cd.name) + inner_len: sizet = string.strlen(child.name) + flat_len: sizet = outer_len + 1 + inner_len + flat_buf: str = flat_pool.alloc(flat_len + 1) + if flat_buf is None: + continue + viperlib.snprintf(flat_buf, flat_len + 1, "%s_%s", cd.name, child.name) + # 改写子节点名 → 递归(内部一律以扁平名注册/发射) + old_name: str = child.name + child.name = flat_buf + saved_def_sha1: str = self.Gen.StructGen.CurDefModuleSha1 + saved_def_cls: str = self.Gen.StructGen.CurDefClassName + self.translate_class_def(trans, child_ast) + self.Gen.StructGen.CurDefModuleSha1 = saved_def_sha1 + self.Gen.StructGen.CurDefClassName = saved_def_cls + child.name = old_name \ No newline at end of file diff --git a/App/lib/core/Gen/Type/TypeGenResolve.vp b/App/lib/core/Gen/Type/TypeGenResolve.vp index 12e142f..2fb568d 100644 --- a/App/lib/core/Gen/Type/TypeGenResolve.vp +++ b/App/lib/core/Gen/Type/TypeGenResolve.vp @@ -279,6 +279,51 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): string.strncpy(b, nm, sizet(hexn)) b[sizet(hexn)] = '\0' return b + # ============================================================ + # _resolve_nested_class_type - 限定名 `外类.内类` → 嵌套类结构体类型 + # + # 命名口径:嵌套 class / struct 由 ClassGenDef._translate_nested_classdefs 以 + # 扁平名 `{外类}_{内类}` 发射为独立结构体(与 TPC union/renum 的 + # `{ClassName}_{Nested}` 同源),故 `外类.内类` 只要拼出扁平名查结构体表即可。 + # + # 判据(两道,缺一不可,避免把 `模块.类` 误判成嵌套): + # ① base 名是**已知类**:`find_struct(base)` 命中,**或**正处在 base 自己的 + # 定义窗口内(CurDefClassName == base)——后者覆盖"类体内部自引用自己嵌套类" + # (此刻外层 struct 尚未 register_struct,字段注解解析早于注册)。 + # ② 扁平名条目存在且 Ty 非空(先按本模块归属精确匹配,再退回裸名)。 + # 两条都不满足即返回 None,交由调用方既有的"未解析"路径处理(绝不静默兜底)。 + # ============================================================ + def _resolve_nested_class_type(self, pool: memhub.MemBuddy*, + outer_name: str, + inner_name: str, + trans: HT.Translator*) -> llvmlite.LLVMType*: + """`外类.内类` → 嵌套类 Ty;无证据返回 None""" + if pool is None or outer_name is None or inner_name is None: + return None + # ① base 必须是已知类(或正定义中的本类) + outer_known: int = 0 + if self.Gen.StructGen.find_struct(outer_name) is not None: + outer_known = 1 + if outer_known == 0: + cur_cls: str = self.Gen.StructGen.CurDefClassName + if cur_cls is not None and string.strcmp(cur_cls, outer_name) == 0: + outer_known = 1 + if outer_known == 0: + return None + # ② 扁平名 `外类_内类` + flat_len: sizet = string.strlen(outer_name) + 1 + string.strlen(inner_name) + flat_buf: str = pool.alloc(flat_len + 1) + if flat_buf is None: + return None + viperlib.snprintf(flat_buf, flat_len + 1, "%s_%s", outer_name, inner_name) + if trans is not None and trans.ModuleSha1 is not None: + own_e: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(flat_buf, trans.ModuleSha1) + if own_e is not None and own_e.Ty is not None: + return own_e.Ty + any_e: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(flat_buf) + if any_e is not None and any_e.Ty is not None: + return any_e.Ty + return None def _repl_opaque_class_ty(self, pool: memhub.MemBuddy*, mod_sha1: str, cls_name: str) -> llvmlite.LLVMType*: @@ -2965,6 +3010,15 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if lib_td_v is not None: td_known = 1 if td_known == 0: + # 嵌套类 / 嵌套 struct:限定名 `外类.内类`(base 是**类名** + # 而非模块名)。到达此处已确定 base 既非 t/c、非 SHA1 + # 前缀、非已导入模块、非库 typedef ⇒ 原本必然返回 None, + # 故新增"扁平名 `外类_内类` 命中即返回"不会覆盖任何既有 + # 成功路径(命名口径见 ClassGenDef._translate_nested_classdefs)。 + nested_ty_q: llvmlite.LLVMType* = \ + self._resolve_nested_class_type(pool, val_name.id, at.attr, trans) + if nested_ty_q is not None: + return nested_ty_q return None # [阶段1b] 库 typedef 动态表优先(正常库分析):attr 是库声明 # 的 typedef 名(如 stdint.INT/BYTE)且表已注册 → 递归展开走库