From 82558bd86b68ae3fd138189fa0b04ba6ef8cdf64 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Tue, 8 Sep 2026 21:30:56 +0800 Subject: [PATCH] =?UTF-8?q?fix(tpv-expr):=20list=20=E5=86=85=E7=BD=AE?= =?UTF-8?q?=E5=86=85=E8=81=94=E6=8C=89=E5=85=83=E7=B4=A0=E5=8E=9F=E5=9E=8B?= =?UTF-8?q?=E7=B1=BB=20load=EF=BC=8C=E6=94=AF=E6=8C=81=E9=93=BE=E5=BC=8F?= =?UTF-8?q?=20get(0).method()=20=E5=88=86=E6=B4=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/lib/core/Gen/Expr/ExprGenName.vp | 92 ++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 4 deletions(-) diff --git a/App/lib/core/Gen/Expr/ExprGenName.vp b/App/lib/core/Gen/Expr/ExprGenName.vp index 0adb948..f1c8678 100644 --- a/App/lib/core/Gen/Expr/ExprGenName.vp +++ b/App/lib/core/Gen/Expr/ExprGenName.vp @@ -461,12 +461,96 @@ class ExprGenName(ExprGenBase.ExprGenBase): return llvmlite.Ptr(pool, i8_ty_d) if string.strstr(struct_name, "list[CPtr]") is not None: return llvmlite.Ptr(pool, i8_ty_d) - # 未知 list[T] 元素类型(如 list[Foo]、list[AST|t.CPtr]):元素存储为 - # 8 字节槽(指针或 8 字节整数),回退 Ptr(i8) 位宽一致(load 8 字节), - # 由 AnnotClassName/特化恢复机制保证语义。禁止 fail-fast(误杀合法 - # 自定义类元素列表的下标访问)。 + # 未知 list[T] 元素类型(自定义结构体元素,如 + # list[rowptr[7565e081d88517ac.AST]] / list[sha1.Foo|t.CPtr]): + # 元素槽存对象指针(8 字节)。从元素类型文本还原对象指针 LLVM 类型 + # Ptr(%Struct),使 list.get/__getitem__/pop 内联返回值的 LLVM 类型 + # 携带元素原型类——链式方法调用(mod.children.get(0).kind())的接收者 + # 才能经 LLVM 类型解析出类名 AST(T29 修复);否则统一 Ptr(i8) 丢失 + # 类名,.kind() 被当未绑定外部函数(AstTest NewAstTest fatal: 'kind' + # 根因:list 元素类名没有沿 get(0) 调用结果值类型传播到后续分派)。 + elem_obj_ty_l: llvmlite.LLVMType | t.CPtr = \ + self._list_elem_obj_ty_from_struct_name(pool, struct_name) + if elem_obj_ty_l is not None: + return elem_obj_ty_l + # 结构体未注册(依赖模块未就绪等):回退 Ptr(i8)(8 字节槽位宽一致, + # load 值正确),由 AnnotClassName/方法分派回退机制保证语义。 + # 禁止 fail-fast(误杀合法自定义类元素列表的访问)。 return llvmlite.Ptr(pool, i8_ty_d) # ============================================================ + # _list_elem_obj_ty_from_struct_name — 从 list 特化类型名还原元素对象指针类型 + # + # struct_name 形如 "{_list_sha1}.list[rowptr[{sha1}.AST]]" 或 + # "{_list_sha1}.list[{sha1}.AST|t.CPtr]"(联合元素)。取 '[' 与最后 ']' + # 之间的元素描述文本:剥 rowptr[...] 包装、按 '|' 联合分段、去首尾空白, + # 逐段按已注册结构体还原(元素类带模块 SHA1 前缀时 find_struct 走 + # find_struct_by_module 精确匹配,规避跨模块同名歧义);命中返回 + # llvmlite.Ptr(entry.Ty)(list 元素槽 8 字节存对象指针)。全部未命中 + # 返回 None(调用方回退 Ptr(i8) 旧行为,不影响已支持的内置元素)。 + # ============================================================ + def _list_elem_obj_ty_from_struct_name(self, pool: memhub.MemBuddy | t.CPtr, + struct_name: str) -> llvmlite.LLVMType | t.CPtr: + """从 list 特化类型名还原元素对象指针 LLVM 类型,失败返回 None""" + if pool is None or struct_name is None: + return None + lb_e: str = string.strchr(struct_name, '[') + if lb_e is None: + return None + rb_e: str = string.strrchr(struct_name, ']') + if rb_e is None: + return None + elen_e: t.CSizeT = t.CSizeT(t.CUInt64T(rb_e) - t.CUInt64T(lb_e)) - 1 + if elen_e == 0 or elen_e > 512: + return None + elem_buf_e: str = pool.alloc(elen_e + 1) + if elem_buf_e is None: + return None + string.strncpy(elem_buf_e, lb_e + 1, elen_e) + elem_buf_e[elen_e] = '\0' + # 剥 rowptr[...] 包装(元素声明为对象指针,如 rowptr[sha1.AST]) + cur_e: str = elem_buf_e + if string.strncmp(cur_e, "rowptr[", 7) == 0: + cur_e = cur_e + 7 + # 按 '|' 联合分段(A|B),段内去首尾空白/尾部 ']'/引号;段文本直接 + # 交给 find_struct(内置名 CPtr/str/int 等不注册 struct → 天然返回 + # None 跳过;带 "sha1.Class" 前缀走模块归属精确匹配) + total_e: t.CSizeT = string.strlen(cur_e) + seg_s_e: t.CSizeT = 0 + i_e: t.CSizeT = 0 + while i_e <= total_e: + hit_e: int = 0 + if i_e == total_e: + hit_e = 1 + elif cur_e[i_e] == '|': + hit_e = 1 + if hit_e == 0: + i_e += 1 + continue + b_e: t.CSizeT = i_e + a_e: t.CSizeT = seg_s_e + while b_e > a_e and (cur_e[b_e - 1] == ' ' or cur_e[b_e - 1] == ']' \ + or cur_e[b_e - 1] == '\'' or cur_e[b_e - 1] == '"'): + b_e -= 1 + while a_e < b_e and (cur_e[a_e] == ' ' or cur_e[a_e] == '\'' \ + or cur_e[a_e] == '"'): + a_e += 1 + if b_e > a_e: + seg_len_e: t.CSizeT = b_e - a_e + if seg_len_e < 256: + seg_buf_e: str = pool.alloc(seg_len_e + 1) + if seg_buf_e is not None: + string.strncpy(seg_buf_e, cur_e + a_e, seg_len_e) + seg_buf_e[seg_len_e] = '\0' + s_entry_e: GenTypes.StructEntry | t.CPtr = \ + self.Gen.StructGen.find_struct(seg_buf_e) + if s_entry_e is not None and s_entry_e.Ty is not None: + return llvmlite.Ptr(pool, s_entry_e.Ty) + if i_e == total_e: + break + seg_s_e = i_e + 1 + i_e += 1 + return None + # ============================================================ # list_setitem_inline — 内联生成 list[T] __setitem__ 逻辑 # # 直接存储 rhs_val 到元素地址 (coerce 为 i8* 后 store)