diff --git a/App/lib/core/Gen/AssignGenMixin.vp b/App/lib/core/Gen/AssignGenMixin.vp index 02dc840..9bca80d 100644 --- a/App/lib/core/Gen/AssignGenMixin.vp +++ b/App/lib/core/Gen/AssignGenMixin.vp @@ -1580,7 +1580,10 @@ novirtual class AssignGenMixin: if aa is None: return 0 target: ast.AST* = aa.target - if target is None or target.kind() != ast.ASTKind.Name: return 0 + if target is None: return 0 + # 属性/下标目标(`obj.f: T = v` / `arr[i]: T = v`):走独立路径——不建局部变量,而是按注解 + # 类型对既有存储做一次"带 P3 长命左值检查"的写出。原先这里直接 return 0,整条语句被**静默丢弃**。 + if target.kind() != ast.ASTKind.Name: return self._translate_lvalue_annassign(trans, aa, target) nm: ast.Name* = ast.Name*(target) if nm.id is None: return 0 @@ -2000,6 +2003,78 @@ novirtual class AssignGenMixin: return 0 + # _translate_lvalue_annassign - 注解赋值的**属性/下标目标**:`obj.f: T = v` / `arr[i]: T = v`。 + # 与 Name 目标同口径:注解是源码级权威类型(RHS 以它为靶型求值);并且必须过 P3 + # "长命左值不得接收本帧栈地址"的检查(= propagate_life 的非 Name 分支)。 + # 存储目标复用既有左值指针求解:Attribute → get_attribute_ptr,Subscript → get_subscript_ptr。 + def _translate_lvalue_annassign(self, trans: HT.Translator*, aa: ast.AnnAssign*, target: ast.AST*) -> int: + """注解赋值的属性/下标目标;0=完成""" + if trans is None or aa is None or target is None: return 0 + tk: int = target.kind() + if tk != ast.ASTKind.Attribute and tk != ast.ASTKind.Subscript: + self.Gen.TypeGenErr.fatal_error(target, "the target of an annotated assignment must be a variable, an attribute or a subscript", "SyntaxError") + return 0 + pool: memhub.MemBuddy* = trans.Pool + builder: mlirlite.IRBuilder* = trans._cur_builder + mod: mlirlite.LLVMModule* = trans.Module + annot: ast.AST* = aa.annotation + if annot is None: + self.Gen.TypeGenErr.fatal_error(aa, "AnnAssign is missing a type annotation", "SyntaxError") + return 0 + # 与 Name 路径同口径解析注解:先特化泛型(避免 list[X] 退化成裸 list*),解析失败即 fail-fast。 + self.Gen.TypeGenResolve.reject_ref_marker_position(annot, trans._imported_modules, "an annotated assignment to an attribute/subscript") + self._prespecialize_generic_annotation(trans, pool, annot) + ann_ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, annot, trans._imported_modules, trans._from_imports, trans, 0) + if ann_ty is None: + self.Gen.TypeGenErr.fatal_error(aa, "cannot resolve the annotation type of an annotated assignment to an attribute/subscript", "TypeError") + return 0 + if self.Gen.StmtGenDecl._is_void_type(ann_ty) != 0: + self.Gen.TypeGenErr.fatal_error(aa, "cannot assign to an attribute/subscript of void type (void may only be used for void* and typedef aliases)", "TypeError") + return 0 + # 左值存储指针:属性/下标各走既有求解器。失败一律 fail-fast——绝不静默丢掉整条语句。 + is_attr: int = 0 + ptr: mlirlite.Value* = None + if tk == ast.ASTKind.Attribute: + is_attr = 1 + at_lv: ast.Attribute* = ast.Attribute*(target) + if at_lv.attr is not None and self.Gen.ExprGenAttr.attr_field_is_const(pool, trans, target) != 0: + self.const_assign_fail(target, "field assignment", at_lv.attr, self.Gen.ExprGenAttr.attr_field_decl_src(pool, trans, target)) + ptr = self.Gen.ExprGenAttr.get_attribute_ptr(builder, pool, mod, target, trans) + else: + ptr = self.Gen.ExprGenName.get_subscript_ptr(builder, pool, mod, target, trans) + if ptr is None or ptr.Ty is None or ptr.Ty.Pointee == 0: + self.Gen.TypeGenErr.fatal_error(target, "cannot resolve the storage of the annotated assignment target (the attribute/subscript pointer or its element type is missing)", "TypeError") + return 0 + target_ty: mlirlite.LLVMType* = ptr.Ty.Pointee + # P3:左值存储比右值长命时,右值不得交出本帧栈地址(如 `h.p: T* = &local`)。 + self._fail_if_lvalue_outlives_rhs(trans, target, aa.value, target_ty) + # 与普通 Assign 同口径:f-string 结果是函数内临时量,写出即悬垂。 + if aa.value is not None: + if is_attr != 0: GenApi.fail_if_fstring_escape(aa.value, "field assignment") + else: GenApi.fail_if_fstring_escape(aa.value, "element assignment") + # RHS 以注解靶型求值(CurAssignAnnot/CurAssignNode 供裸泛型构造推断;求值完即复位,不跨语句泄漏)。 + trans.CurAssignAnnot = annot + trans.CurAssignNode = aa.value + rhs_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, aa.value, None, 0, trans, ann_ty, "annotated assignment to an attribute/subscript") + trans.CurAssignAnnot = None + trans.CurAssignNode = None + if rhs_val is None: + self.Gen.TypeGenErr.fatal_error(aa, "the right-hand side of the annotated assignment to an attribute/subscript could not be translated", "TypeError") + return 0 + store_val: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, target_ty, aa, trans) + if store_val is None: + self.Gen.TypeGenErr.fatal_error(aa, "type coercion failed for the annotated assignment to an attribute/subscript", "TypeError") + return 0 + # t.CVolatile 字段 / rawptr[t.CVolatile|T] 基址:写出同样带 volatile。 + vol_lv: int = 0 + if is_attr != 0: + vol_lv = self.Gen.ExprGenAttr.attr_field_is_volatile(pool, trans, target) + else: + sub_lv: ast.Subscript* = ast.Subscript*(target) + if sub_lv.value is not None: vol_lv = self.Gen.ExprGenAttr.base_pointee_is_volatile(pool, trans, sub_lv.value) + mlirlite.build_store(builder, store_val, ptr, vol_lv) + return 0 + # translate_assign - handle an Assign statement; returns the number of new variables def translate_assign(self, trans: HT.Translator*, node: ast.AST*) -> int: """Translate an Assign statement; return the number of new variables."""