refactor(tpv): 容器判断改基名精确比较(SpecTypeNameBaseIs)

TypeSpec 新增 SpecTypeNameBaseIs(name, base):基名 = 截断第一个 '[' 起的泛型实参后,取最后一个 '.' 之后(去模块名 / LLVM 注册名的模块 sha1 前缀),再精确比较;零分配,复用 _spec_name_eq。

4 处容器判断改写:StmtGenCifMixin:1133/1142/1498(读注解名)、CallGenDispatch:1685(读 LLVM 注册名)。原 strstr 子串匹配会误命中 MyDictHelper / playlist;副作用是 GSList 等用户类不再被误判为内置 list,改由 OOP __iter__/__next__ 路径处理。第 5 处 CallGenMixin:973 的 CPtr 属标记判断(SourceName 会丢掉联合里的标记),需先定标记语义,本次不动。
This commit is contained in:
TermiNexus committed 2026-09-12 10:10:14 +08:00
1 parent 19fca19ca7
commit ae63f4f6ab
3 files changed
+54 -6

No files matched your search

+7 -2
View File
@@ -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 方法路径",否则
+10 -4
View File
@@ -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
+37
View File
@@ -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(不表态)