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:
1 parent
19fca19ca7
commit
ae63f4f6ab
3 files changed
+54
-6
No files matched your search
@@ -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,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
|
||||
|
||||
@@ -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(不表态)
|
||||
|
||||
Reference in new issue
Block a user