diff --git a/App/lib/core/Gen/MatchGenMixin.vp b/App/lib/core/Gen/MatchGenMixin.vp index 9c65c7e..2d6772d 100644 --- a/App/lib/core/Gen/MatchGenMixin.vp +++ b/App/lib/core/Gen/MatchGenMixin.vp @@ -572,12 +572,25 @@ novirtual class MatchGenMixin: llvmlite.build_switch(builder, tag_val, default_bb, sw_head, sw_count) # 6. 查找 REnum 结构体类型(用于变体字段绑定的 GEP) + # 两条健壮性要求——否则 renum_entry/renum_ty 取不到,step 7 的变体字段绑定会被 + # **整段静默跳过** ⇒ case 绑定名在 body 里未定义(NameError:__types.vp + # `_TypePrintDepth` 的 `bits` 根因,真因因此藏到下游): + # (1) 名字:变体表与 struct 注册都按**裸类名**(ClassDef.name),而 renum_name + # 来自注解书写形态(Spec.SourceName,Attribute 可带模块限定名,如 + # "c93534fe43c0ee56.LLVMType")⇒ 精确查找可能失配 → 回退 tag_cls_bare。 + # (2) 条目有效性:find_struct 是"首注册命中",可能命中 D30 重注册时被就地 + # 中和的旧 entry(Ty=None)⇒ 扫表取 Ty 有效者。 renum_entry: GenTypes.StructEntry* = None renum_ty: llvmlite.LLVMType* = None se: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(renum_name) - if se is not None: + if se is not None and se.Ty is not None: renum_entry = se renum_ty = se.Ty + else: + se_v: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_entry_with_ty(renum_name, tag_cls_bare) + if se_v is not None: + renum_entry = se_v + renum_ty = se_v.Ty # 7. 第二遍:翻译每个 case body i = 0 @@ -607,9 +620,32 @@ novirtual class MatchGenMixin: self.Gen.VarGen.enter_scope(trans.SymTab, SCOPE_MATCH) # 变体字段绑定(MatchClass) - if pat is not None and pat.kind() == ast.ASTKind.MatchClass \ - and renum_entry is not None and renum_ty is not None: - self._bind_variant_fields(pat, renum_name, renum_entry, renum_ty, subject_ptr, trans, pool, builder) + if pat is not None and pat.kind() == ast.ASTKind.MatchClass: + if renum_entry is not None and renum_ty is not None: + self._bind_variant_fields(pat, renum_name, renum_entry, renum_ty, subject_ptr, trans, pool, builder) + elif (self.Gen.ClassGenEnum._is_renum_class_name(tag_cls_bare) != 0 + or self.Gen.ClassGenEnum._is_renum_class_name(renum_name) != 0 + or self.Gen.ClassGenEnum._is_renum_by_entry(tag_cls_bare) != 0 + or self.Gen.ClassGenEnum._is_renum_by_entry(renum_name) != 0): + # 走到这里 ⇒ 分派判定为 REnum match(同一组判据至少一条为真),而 + # MatchClass 却拿不到可用的 struct entry/类型:此前**静默跳过**绑定 + # ⇒ 绑定名在 body 里未定义,最终报 NameError(__types.vp `bits`), + # 真因被藏到下游。此处 fail-fast 并打印现场,便于定位是"变体表缺该类" + # 还是"条目被中和/Ty 缺失"。 + ent_nm: str = "None" + ent_fc: int = -1 + if renum_entry is not None: + ent_nm = renum_entry.Name + ent_fc = renum_entry.FieldCount + ty_present: int = 0 + if renum_ty is not None: + ty_present = 1 + self.Gen.TypeGenErr.fatal_error(pat, + f"REnum match 变体字段绑定失败:class='{tag_cls_bare}'(查表名='{renum_name}')" + f" entry='{ent_nm}' FieldCount={ent_fc} ty_present={ty_present};" + f"变体表已登记该类,说明结构体条目或 Ty 缺失(已不再静默跳过绑定," + f"否则绑定名未定义只会在下游报 NameError)", + "InternalCompilerError") # 翻译 case body body_list: list[ast.AST*]* = mc.children diff --git a/App/lib/core/Gen/StructGenMixin.vp b/App/lib/core/Gen/StructGenMixin.vp index 47429ad..a5aa914 100644 --- a/App/lib/core/Gen/StructGenMixin.vp +++ b/App/lib/core/Gen/StructGenMixin.vp @@ -733,6 +733,32 @@ novirtual class StructGenMixin: s_rm = StubMergerStore.LookupSha1ByModNameSuffix(mod_name) return s_rm + def find_struct_entry_with_ty(self, name: str, alt_name: str) -> GenTypes.StructEntry*: + """按名字(含备选名)查**带有效 Ty** 的结构体条目;找不到返回 None。 + + 为什么需要它:`find_struct` 的语义是"首注册命中"。D30 的 REnum 重注册把旧 + entry **就地中和**(`Name[0]='\\0'` / `Ty=None` / `FieldCount=0`)后再追加新 + entry;若名索引/线性扫描先命中那条已中和的旧条目,调用方拿到的 `Ty` 是 None —— + 依赖 `Ty` 的代码(如 match 的 REnum 变体字段绑定)会**静默跳过**,症状表现为 + case 绑定名未定义(NameError,真因被藏到下游)。本函数跳过 `Ty` 无效的同名条目, + 返回首个 `Ty` 有效的同名(或备选名)条目;都没有则返回 None,由调用方决定报错。 + + name / alt_name:主名与备选名(如模块限定名与裸类名),任一命中即可。 + """ + if self.StructTable is None: + return None + for i in range(self.StructCount): + entry: GenTypes.StructEntry* = self._get_struct_entry(i) + if entry is None or entry.Name is None or entry.Ty is None: + continue + if entry.Name[0] == '\0': + continue + if string.strcmp(entry.Name, name) == 0: + return entry + if alt_name is not None and string.strcmp(entry.Name, alt_name) == 0: + return entry + return None + def find_struct(self, name: str) -> GenTypes.StructEntry*: """按类名查找结构体,返回 StructEntry 或 None