diff --git a/App/lib/core/Gen/Call/CallGenMixin.vp b/App/lib/core/Gen/Call/CallGenMixin.vp index 6d2ac35..0b20f35 100644 --- a/App/lib/core/Gen/Call/CallGenMixin.vp +++ b/App/lib/core/Gen/Call/CallGenMixin.vp @@ -968,8 +968,9 @@ class CallGenMixin(CallGenBase.CallGenBase): ve_fp: GenTypes.VarEntry | t.CPtr = self.Gen.VarGen.lookup_var_entry( trans.SymTab, func_name) is_cptr_annot_fp: int = 0 - if ve_fp is not None and ve_fp.AnnotClassName is not None: - if string.strstr(ve_fp.AnnotClassName, "CPtr") is not None: + fp_annot: str = self.Gen.VarGen.var_annot_class_name(ve_fp) + if fp_annot is not None: + if string.strstr(fp_annot, "CPtr") is not None: is_cptr_annot_fp = 1 if is_cptr_annot_fp == 0: return self.Gen.CallGenLeafKit._translate_func_ptr_call(pool, builder, mod, fp_alloca, diff --git a/App/lib/core/Gen/GenTypes.vp b/App/lib/core/Gen/GenTypes.vp index 85824e0..bf63442 100644 --- a/App/lib/core/Gen/GenTypes.vp +++ b/App/lib/core/Gen/GenTypes.vp @@ -67,10 +67,11 @@ class VarEntry: Name: str Alloca: llvmlite.Value | t.CPtr Used: int - AnnotClassName: str # 原始类型注解的类名(str 别名在结构体字段中触发编译器 bug,改用显式联合类型) IsPtrElement: int # 标志: 1=注解为 bytes|t.CPtr 或 str|t.CPtr, 下标按 8 字节步长 - # TypeSpec(S3 条目双写;Debugger/_Type.md D4):由 add_var 用 SpecFromLLVMType - # 从 alloca.Ty 的 pointee 填充,PermPool 驻留 ⇒ 跨文件安全。当前尚无读取方。 + # TypeSpec(S3 起为**唯一类型承载**):由 add_var 用 SpecFromLLVMType 从 + # alloca.Ty 的 pointee 填充(PermPool 分配 ⇒ 跨文件安全),注解侧再由 + # set_var_annot_class_name 经 SpecWithSign / SpecWithSource 补整数符号性与 + # 注解来源名(Spec.SourceName,原 AnnotClassName 字段已并入)。 Spec: TSpec.TypeSpec | t.CPtr @@ -105,9 +106,10 @@ class FieldEntry: Index: int # 字段在结构体中的索引 Ty: llvmlite.LLVMType | t.CPtr # 字段的 LLVM 类型 DefaultVal: ast.AST | t.CPtr # 默认值 AST 节点(None=无默认值) - AnnotClassName: str # 原始类型注解的类名(str 别名在结构体字段中触发编译器 bug,改用显式联合类型) - # TypeSpec(S3 条目双写):由 add_field 用 SpecFromLLVMType 从 field_ty 填充, - # PermPool 驻留 ⇒ 跨 1b reset 安全(无需 DeepCopyType)。当前尚无读取方。 + # TypeSpec(S3 起为**唯一类型承载**):由 add_field 用 SpecFromLLVMType 从 + # field_ty 填充(PermPool 分配 ⇒ 跨 1b reset 安全,无需 DeepCopyType), + # 注解侧再经 SpecWithSign / SpecWithSource 补符号性与注解来源名 + # (Spec.SourceName,原 AnnotClassName 字段已并入)。 Spec: TSpec.TypeSpec | t.CPtr diff --git a/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp b/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp index ad0c024..26a94ab 100644 --- a/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp +++ b/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp @@ -1124,16 +1124,17 @@ class StmtGenCifMixin: if nm_lst.id is not None: ve_lst: GenTypes.VarEntry | t.CPtr = self.Gen.VarGen.lookup_var_entry( trans.SymTab, nm_lst.id) - if ve_lst is not None and ve_lst.AnnotClassName is not None: + 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(ve_lst.AnnotClassName, "dict") is not None: + if string.strstr(lst_annot, "dict") is not None: 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(ve_lst.AnnotClassName, "list") is not None: + if string.strstr(lst_annot, "list") is not None: lst_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value( builder, pool, trans.Module, iter_node, trans._funcs, trans._func_count, trans) @@ -1486,8 +1487,9 @@ class StmtGenCifMixin: if nm_s.id is not None and trans is not None: ve_s: GenTypes.VarEntry | t.CPtr = self.Gen.VarGen.lookup_var_entry( trans.SymTab, nm_s.id) - if ve_s is not None and ve_s.AnnotClassName is not None: - if string.strstr(ve_s.AnnotClassName, "list") is not None: + 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: return GenTypes.SEQ_KIND_LIST return GenTypes.SEQ_KIND_STR return 0 diff --git a/App/lib/core/Gen/StructGenMixin.vp b/App/lib/core/Gen/StructGenMixin.vp index 6992aeb..df060b1 100644 --- a/App/lib/core/Gen/StructGenMixin.vp +++ b/App/lib/core/Gen/StructGenMixin.vp @@ -372,12 +372,14 @@ class StructGenMixin: fe.Name = name_buf fe.Index = idx - # 1b 阶段(StdlibAlloc=1)字段类型/注解类名必须深拷贝到 stdlib: + # 1b 阶段(StdlibAlloc=1)字段类型必须深拷贝到 stdlib: # register_struct 已迁 Fields/Name/ModuleSha1/Ty(translate_class_def L2566 - # DeepCopyType),但字段级 Ty/AnnotClassName 仍存 pool 指针,本文件 - # reset_to(mark1) 回收后,跨文件读取(字段展平、多继承 this 调整、 - # AnnotClassName 回退、_apply_struct_defaults 的 build_gep_struct 用 fe.Ty - # 作 GEP 结果类型)解引用悬空内存 → 崩溃点漂移(json/string/builtins 之间)。 + # DeepCopyType),但字段级 Ty 仍存 pool 指针,本文件 reset_to(mark1) 回收后, + # 跨文件读取(字段展平、多继承 this 调整、_apply_struct_defaults 的 + # build_gep_struct 用 fe.Ty 作 GEP 结果类型)解引用悬空内存 → 崩溃点漂移 + # (json/string/builtins 之间)。 + # 注:注解类名(原 fe.AnnotClassName)已并入 Spec.SourceName,Spec 一律 + # PermPool 分配 ⇒ 天然跨 reset 存活,无需在此深拷贝。 if self.StdlibAlloc != 0: dp_pool_sg: memhub.MemBuddy | t.CPtr = CompilerFactory.factory.PermPool if dp_pool_sg is None: @@ -387,34 +389,31 @@ class StructGenMixin: fe.Ty = ty_copy else: fe.Ty = field_ty - if annot_class_name is not None: - annot_len: sizet = string.strlen(annot_class_name) - annot_buf: str = CompilerFactory.factory.PermPool.alloc(annot_len + 1) - if annot_buf is not None: - string.strcpy(annot_buf, annot_class_name) - fe.AnnotClassName = annot_buf # DefaultVal:跨文件结构体构造(_translate_struct_ctor→_apply_struct_defaults) # 在调用方文件翻译时读取字段默认值,原 pool AST 已 reset 回收 → 常量深拷贝 # 到 perm_pool(1a 每文件 reset 后 DefaultVal 同样必须跨文件存活) fe.DefaultVal = self._deep_copy_default_ast(dp_pool_sg, default_val) else: fe.Ty = field_ty - fe.AnnotClassName = annot_class_name fe.DefaultVal = default_val - # [S3 条目双写] 字段类型 Spec。与上方 Ty/AnnotClassName 的区别:TypeSpec - # 实例一律 PermPool 分配(驻留或独立副本)⇒ 天然跨 1b reset 存活, - # **无需** DeepCopyType。 + # [S3 条目双写] 字段类型 Spec(唯一类型承载,含注解来源名)。TypeSpec + # 实例一律 PermPool 分配(驻留或独立副本)⇒ 天然跨 1b reset 存活。 arena_f: TSpec.TypeSpecArena | t.CPtr = self.Gen.TypeGenBase.ensure_spec_arena() if arena_f is not None: fe.Spec = TSpec.SpecFromLLVMType(arena_f, field_ty) # [S4 注解侧填 Spec] 补字段 Spec 的符号性与注解来源名(annot_class_name - # 携带真实无符号性与注解书写形态名;LLVM 反推恒 TS_INT 且无名) - if fe.Spec is not None and annot_class_name is not None: - sign_f: int = self.Gen.TypeGenCType.spec_sign_of_annot(annot_class_name) - if sign_f != TSpec.TS_SIGN_UNKNOWN: - fe.Spec = TSpec.SpecWithSign(arena_f, fe.Spec, sign_f) - fe.Spec = TSpec.SpecWithSource(fe.Spec, annot_class_name) + # 携带真实无符号性与注解书写形态名;LLVM 反推恒 TS_INT 且无名)。 + # 类型信息缺失(Spec 为 None)时建 TS_UNKNOWN 承载注解名(不表态具体类型)。 + if annot_class_name is not None: + if fe.Spec is None: + fe.Spec = TSpec.NewTypeSpec(arena_f, TSpec.TS_UNKNOWN, 0, + TSpec.TS_SIGN_UNKNOWN) + if fe.Spec is not None: + sign_f: int = self.Gen.TypeGenCType.spec_sign_of_annot(annot_class_name) + if sign_f != TSpec.TS_SIGN_UNKNOWN: + fe.Spec = TSpec.SpecWithSign(arena_f, fe.Spec, sign_f) + fe.Spec = TSpec.SpecWithSource(fe.Spec, annot_class_name) struct_entry.FieldCount = idx + 1 return idx @@ -1711,15 +1710,11 @@ class StructGenMixin: return fe.DefaultVal def get_field_annot_class_name(self, fe: GenTypes.FieldEntry | t.CPtr) -> str: - """获取 FieldEntry 的原始类型注解类名,返回 None=未设置 + """获取 FieldEntry 的原始类型注解类名(Spec.SourceName),返回 None=未设置 - [S4 切读·类名块] Spec.SourceName 优先(注解侧由 SpecWithSource 填), - 未设置时回退旧字段 AnnotClassName。经此封装读取的调用点自动切读。 + [S4] 原 FieldEntry.AnnotClassName 字段已删除,注解名承载在 Spec.SourceName + (由 add_field 经 SpecWithSource 写入)。 """ if fe is None: return None - if fe.Spec is not None: - sn: str = TSpec.SpecSourceName(fe.Spec) - if sn is not None: - return sn - return fe.AnnotClassName + return TSpec.SpecSourceName(fe.Spec) diff --git a/App/lib/core/Gen/VarGenMixin.vp b/App/lib/core/Gen/VarGenMixin.vp index 8468c30..75ac0ae 100644 --- a/App/lib/core/Gen/VarGenMixin.vp +++ b/App/lib/core/Gen/VarGenMixin.vp @@ -115,49 +115,58 @@ class VarGenMixin: # ============================================================ # set_var_annot_class_name — 设置变量的原始类型注解类名 # - # 在函数参数定义后调用,存储原始类型注解的类名。 + # 在函数参数定义后调用,存储原始类型注解的类名(Spec.SourceName)。 # 方法调用检测时,当 alloca 类型是 Ptr(i8)(联合类型简化), - # 通过 AnnotClassName 查找实际结构体类型。 + # 通过 Spec.SourceName 查找实际结构体类型。 # ============================================================ def set_var_annot_class_name(self, symtab: GenTypes.SymbolTable | t.CPtr, name: str, class_name: str) -> int: - """设置变量的原始类型注解类名,返回 0=成功 / 1=失败""" + """设置变量的原始类型注解类名(写入 Spec.SourceName),返回 0=成功 / 1=失败 + + [S4] 原 VarEntry.AnnotClassName 字段已删除,注解名统一承载在 Spec.SourceName: + - 整数符号性:SpecFromLLVMType 反推恒 TS_INT(LLVM iN 不分符号), + 注解名携带真实无符号性(uint32/CUInt32T 等)→ 切 TS_INT→TS_UINT; + - 来源名:`X | t.CPtr` 简化为 Ptr(i8) 后 Spec 里没有类名,附上供 + 属性访问/方法分派恢复(消费点经 var_annot_class_name 读取)。 + 类型信息缺失(SpecFromLLVMType 不适用致 Spec 为 None)时建 TS_UNKNOWN + 承载注解名 —— TS_UNKNOWN 不表态任何具体类型,等价于原来的"Spec 缺失"。 + """ if symtab is None or name is None: return 1 entry: GenTypes.VarEntry | t.CPtr = self.lookup_var_entry(symtab, name) if entry is None: return 1 - entry.AnnotClassName = class_name - # [S4 注解侧填 Spec] 把注解来源名附到 Spec(SourceName)供消费点逐步切读: - # - 整数符号性:SpecFromLLVMType 反推恒 TS_INT(LLVM iN 不分符号), - # 注解名携带真实无符号性(uint32/CUInt32T 等)→ 切 TS_INT→TS_UINT; - # - 来源名:`X | t.CPtr` 简化为 Ptr(i8) 后 Spec 里没有类名,附上供 - # 属性访问/方法分派恢复。 - if entry.Spec is not None and class_name is not None: - sign: int = self.Gen.TypeGenCType.spec_sign_of_annot(class_name) - if sign != TSpec.TS_SIGN_UNKNOWN: - arena_sn: TSpec.TypeSpecArena | t.CPtr = self.Gen.TypeGenBase.ensure_spec_arena() - if arena_sn is not None: - entry.Spec = TSpec.SpecWithSign(arena_sn, entry.Spec, sign) - entry.Spec = TSpec.SpecWithSource(entry.Spec, class_name) + if class_name is None: + # 无注解名:不写入。原实现无条件 `entry.AnnotClassName = None` 会清空, + # 但 VarEntry 槽位不复用(add_var 只递增),首次设置时原值恒为 None, + # 故二者等价;重复调用且第二次为 None 的差异不存在于现有调用点。 + return 0 + arena_sn: TSpec.TypeSpecArena | t.CPtr = self.Gen.TypeGenBase.ensure_spec_arena() + if arena_sn is None: + return 1 + if entry.Spec is None: + entry.Spec = TSpec.NewTypeSpec(arena_sn, TSpec.TS_UNKNOWN, 0, + TSpec.TS_SIGN_UNKNOWN) + if entry.Spec is None: + return 1 + sign: int = self.Gen.TypeGenCType.spec_sign_of_annot(class_name) + if sign != TSpec.TS_SIGN_UNKNOWN: + entry.Spec = TSpec.SpecWithSign(arena_sn, entry.Spec, sign) + entry.Spec = TSpec.SpecWithSource(entry.Spec, class_name) return 0 # ============================================================ # var_annot_class_name - 变量条目注解类名的统一读取入口(S4 切读·类名块) # - # Spec.SourceName 优先(注解侧由 set_var_annot_class_name 经 SpecWithSource 填), - # 未设置时回退旧字段 AnnotClassName。变量侧类名恢复读取点统一走此入口。 + # 注解侧由 set_var_annot_class_name 经 SpecWithSource 写入 Spec.SourceName。 + # 变量侧类名恢复读取点统一走此入口。 # ============================================================ def var_annot_class_name(self, entry: GenTypes.VarEntry | t.CPtr) -> str: - """变量条目注解类名;未设置返回 None""" + """变量条目注解类名(Spec.SourceName);未设置返回 None""" if entry is None: return None - if entry.Spec is not None: - sn: str = TSpec.SpecSourceName(entry.Spec) - if sn is not None: - return sn - return entry.AnnotClassName + return TSpec.SpecSourceName(entry.Spec) # ============================================================ # set_var_ptr_element — 标记变量为"指针到 str/bytes"类型