feat(gen): P3 覆盖注解形态的属性/下标目标
- translate_annassign 原先对非 Name 目标直接 return 0,obj.f: T = v / rr[i]: T = v 整条语句被静默丢弃(既不报错也不写出) - 新增 _translate_lvalue_annassign:解析注解(先特化泛型)→ get_attribute_ptr / get_subscript_ptr 求左值指针 → 走同一处 P3 长命左值检查 → RHS 以注解为靶型求值 → coerce_to_type 后写出;const / volatile / f-string 逃逸与普通 Assign 同口径 - 所有失败路径 fail-fast,不再有静默丢语句
This commit is contained in:
1 parent
d926987d44
commit
ab30b264fc
1 file changed
+76
-1
@@ -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."""
|
||||
|
||||
Reference in new issue
Block a user