diff --git a/App/lib/core/Gen/Call/CallGenDispatch.vp b/App/lib/core/Gen/Call/CallGenDispatch.vp index da3cd55..79eab10 100644 --- a/App/lib/core/Gen/Call/CallGenDispatch.vp +++ b/App/lib/core/Gen/Call/CallGenDispatch.vp @@ -14,7 +14,8 @@ import sys import viperlib import w32.fileio as fileio import lib.core.VLogger as VLogger -import lib.core.Gen.Translator as HT +import lib.core.Gen.Translator as HT +import lib.core.Gen.Type.TypeSpec as TSpec import lib.Stub.StubMerger as StubMerger import lib.core.CompilerFactory as CompilerFactory from . import CallGenBase @@ -1676,8 +1677,12 @@ class CallGenDispatch(CallGenBase.CallGenBase): lm_conf_nm: str = None if lm_conf_ty is not None: lm_conf_nm = llvmlite.get_struct_name(lm_conf_ty) + # [S4] 容器基名**精确**比较:此处读的是 LLVM 注册名,含模块 sha1 + # 前缀(如 "e94ef9e139461915.list[ast.ASTptr]");SpecTypeNameBaseIs + # 会去前缀、截断泛型实参后精确比 "list"(原 strstr 子串会误命中 + # playlist 之类的类名)。 if lm_conf_nm is not None and \ - string.strstr(lm_conf_nm, "list") is None: + TSpec.SpecTypeNameBaseIs(lm_conf_nm, "list") == 0: return None # list 内置分支命中标记:void 方法(set/clear)成功处理后返回 # None,必须置位 hit_box 区分"已识别为 list 方法路径",否则 diff --git a/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp b/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp index 26a94ab..f4e16ca 100644 --- a/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp +++ b/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp @@ -10,7 +10,8 @@ import stdlib import stdio import viperlib import lib.core.VLogger as VLogger -import lib.core.Gen.Translator as HT +import lib.core.Gen.Translator as HT +import lib.core.Gen.Type.TypeSpec as TSpec import lib.core.CompilerFactory as CompilerFactory import lib.Projectrans.Config as Config # ============================================================ @@ -1127,14 +1128,18 @@ class StmtGenCifMixin: lst_annot: str = self.Gen.VarGen.var_annot_class_name(ve_lst) if lst_annot is not None: # dict 容器变量:按 __count__/__keys__ 布局迭代(__iter__ 协议内联) - if string.strstr(lst_annot, "dict") is not None: + # [S4] 容器基名精确比较(SpecTypeNameBaseIs):原 strstr("dict") 子串匹配 + # 会误命中任何含 "dict" 的类名(如 MyDictHelper)。 + if TSpec.SpecTypeNameBaseIs(lst_annot, "dict") != 0: lst_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value( builder, pool, trans.Module, iter_node, trans._funcs, trans._func_count, trans) if lst_val is not None and lst_val.Ty is not None \ and self.Gen.ExprGenBase.is_ptr_type(lst_val.Ty) != 0: return self._handle_dict_iter(trans, for_node, var_name, lst_val) - if string.strstr(lst_annot, "list") is not None: + # [S4] 同上:原 strstr("list") 会误命中 playlist / GSList 等; + # 非 list 基名的用户类改由下方 OOP __iter__/__next__ 路径处理(更正确)。 + if TSpec.SpecTypeNameBaseIs(lst_annot, "list") != 0: lst_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value( builder, pool, trans.Module, iter_node, trans._funcs, trans._func_count, trans) @@ -1489,7 +1494,8 @@ class StmtGenCifMixin: trans.SymTab, nm_s.id) sq_annot: str = self.Gen.VarGen.var_annot_class_name(ve_s) if sq_annot is not None: - if string.strstr(sq_annot, "list") is not None: + # [S4] 容器基名精确比较(原 strstr("list") 子串匹配会误命中 playlist 等) + if TSpec.SpecTypeNameBaseIs(sq_annot, "list") != 0: return GenTypes.SEQ_KIND_LIST return GenTypes.SEQ_KIND_STR return 0 diff --git a/App/lib/core/Gen/Type/TypeSpec.vp b/App/lib/core/Gen/Type/TypeSpec.vp index 0dec71c..3dd6262 100644 --- a/App/lib/core/Gen/Type/TypeSpec.vp +++ b/App/lib/core/Gen/Type/TypeSpec.vp @@ -106,6 +106,43 @@ def _spec_name_eq(text: str, start: sizet, end: sizet, lit: str) -> int: return 1 +# ============================================================ +# SpecTypeNameBaseIs - 类型名的「容器基名」是否精确等于 base(零分配) +# +# 基名 = 先截断第一个 '[' 起的泛型实参,再取**最后一个 '.' 之后**的部分 +# (去模块名 / LLVM 注册名的模块 sha1 前缀)。例: +# "e94ef9e139461915.list[ast.ASTptr]" → "list" +# "list[ast.AST | t.CPtr]" → "list" +# "memhub.MemBuddy" → "MemBuddy"(≠ list/dict) +# +# 用途:替换容器种类判断里的 strstr 子串匹配(Debugger/_Type.md D20)—— +# `strstr("dict")` 会误命中 `MyDictHelper`,`strstr("list")` 会误命中 `playlist`。 +# 返回 1=是 / 0=否(含名字为空、无法提取基名的情形)。 +# ============================================================ +def SpecTypeNameBaseIs(name: str, base: str) -> int: + """类型名的容器基名是否精确等于 base(1=是 / 0=否)""" + if name is None or base is None: + return 0 + n: sizet = string.strlen(name) + if n == 0: + return 0 + # 基名上界:第一个 '['(泛型实参起点;无 '[' 则到串尾) + end: sizet = n + lb: str = string.strchr(name, '[') + if lb is not None: + end = t.CSizeT(t.CUInt64T(lb) - t.CUInt64T(name)) + # 基名下界:上界之前最后一个 '.' 之后(去模块名 / 模块 sha1 前缀) + start: sizet = 0 + dot: str = string.strchr(name, '.') + while dot is not None: + off: sizet = t.CSizeT(t.CUInt64T(dot) - t.CUInt64T(name)) + if off >= end: + break + start = off + 1 + dot = string.strchr(dot + 1, '.') + return _spec_name_eq(name, start, end, base) + + # ============================================================ # SpecSignFromTypeNameSpan - 按名字切片精确判定符号性(零分配) # 返回 TS_SIGN_UNSIGNED / TS_SIGN_SIGNED / TS_SIGN_UNKNOWN(不表态)