增加 JIT REPL
This commit is contained in:
1 parent
9910e05760
commit
a5ceb3d4eb
56 files changed
+7621
-584
No files matched your search
@@ -125,7 +125,7 @@ class AssignGenMixin:
|
||||
cl: rawptr[ast.Call] = rawptr[ast.Call](val_node)
|
||||
# 必须先把属性赋给显式类型为 list[...] | t.CPtr 的局部变量再调用 __len__(),
|
||||
# 否则编译器无法识别属性返回的 list 类型,GEP base 会变成 i32 0 导致 llc 报错
|
||||
cl_args_list: rawptr[list[rawptr[ast.AST]]] = cl.args
|
||||
cl_args_list: list[ast.AST*]* = cl.args
|
||||
if cl_args_list is not None and len(cl_args_list) > 0:
|
||||
first_arg: rawptr[ast.AST] = cl_args_list.get(0)
|
||||
arg_val: int64 = self.extract_cdefine_int_value(first_arg)
|
||||
@@ -167,7 +167,7 @@ class AssignGenMixin:
|
||||
if val_node is not None and val_node.kind() == ast.ASTKind.Call:
|
||||
cl_cd: rawptr[ast.Call] = rawptr[ast.Call](val_node)
|
||||
if cl_cd is not None and cl_cd.args is not None:
|
||||
cl_args_cd: rawptr[list[rawptr[ast.AST]]] = cl_cd.args
|
||||
cl_args_cd: list[ast.AST*]* = cl_cd.args
|
||||
if len(cl_args_cd) > 0:
|
||||
first_arg_cd: rawptr[ast.AST] = cl_args_cd.get(0)
|
||||
if first_arg_cd is not None and first_arg_cd.kind() == ast.ASTKind.Constant:
|
||||
@@ -640,7 +640,7 @@ class AssignGenMixin:
|
||||
lst: rawptr[ast.List] = rawptr[ast.List](list_node)
|
||||
if lst is None or lst.elts is None:
|
||||
return 1
|
||||
elts: rawptr[list[rawptr[ast.AST]]] = lst.elts
|
||||
elts: list[ast.AST*]* = lst.elts
|
||||
elts_count: sizet = len(elts)
|
||||
|
||||
# 特例:单个字符串字面量初始化字符数组([N x i8],N = strlen+1)
|
||||
@@ -839,8 +839,17 @@ class AssignGenMixin:
|
||||
if target_ty is None:
|
||||
# fail-fast: 字段类型信息缺失,禁止兜底 i32
|
||||
self.Gen.TypeGenErr.fatal_error(target, "字段类型信息缺失", "TypeError")
|
||||
# t.CVolatile 字段:+= 的 load 与 store 均带 volatile 限定符
|
||||
vol_fa: int = self.Gen.ExprGenAttr.attr_field_is_volatile(pool, trans, target)
|
||||
# rawptr[t.CVolatile|T] 基址(volatile 指针指向物):经其访问的
|
||||
# 字段 += 的 load/store 亦带 volatile(两来源取或)。
|
||||
at_aug: rawptr[ast.Attribute] = rawptr[ast.Attribute](target)
|
||||
if at_aug is not None:
|
||||
if self.Gen.ExprGenAttr.base_pointee_is_volatile(
|
||||
pool, trans, at_aug.value) != 0:
|
||||
vol_fa = 1
|
||||
cur_val: rawptr[llvmlite.Value] = llvmlite.build_load(
|
||||
builder, target_ty, field_ptr)
|
||||
builder, target_ty, field_ptr, vol_fa)
|
||||
if cur_val is None:
|
||||
# fail-fast: 属性当前值加载失败
|
||||
self.Gen.TypeGenErr.fatal_error(target, "无法加载 attribute 当前值", "TypeError")
|
||||
@@ -864,7 +873,7 @@ class AssignGenMixin:
|
||||
if result is None:
|
||||
# fail-fast: 类型对齐失败
|
||||
self.Gen.TypeGenErr.fatal_error(target, "类型对齐失败", "TypeError")
|
||||
llvmlite.build_store(builder, result, field_ptr)
|
||||
llvmlite.build_store(builder, result, field_ptr, vol_fa)
|
||||
return 0
|
||||
|
||||
# Subscript 目标: self.state[i] += x / arr[i] += x
|
||||
@@ -888,8 +897,15 @@ class AssignGenMixin:
|
||||
if target_ty is None:
|
||||
# fail-fast: 元素类型信息缺失,禁止兜底 i32
|
||||
self.Gen.TypeGenErr.fatal_error(target, "元素类型信息缺失", "TypeError")
|
||||
# rawptr[t.CVolatile|T] 基址(volatile 指针指向物):p[i] += 的
|
||||
# load/store 均带 volatile。仅基址可解析到 VarEntry/FieldEntry 时为 1。
|
||||
vol_sa: int = 0
|
||||
sub_aug: rawptr[ast.Subscript] = rawptr[ast.Subscript](target)
|
||||
if sub_aug is not None:
|
||||
vol_sa = self.Gen.ExprGenAttr.base_pointee_is_volatile(
|
||||
pool, trans, sub_aug.value)
|
||||
cur_val: rawptr[llvmlite.Value] = llvmlite.build_load(
|
||||
builder, target_ty, elem_ptr)
|
||||
builder, target_ty, elem_ptr, vol_sa)
|
||||
if cur_val is None:
|
||||
# fail-fast: 元素当前值加载失败
|
||||
self.Gen.TypeGenErr.fatal_error(target, "无法加载 subscript 元素当前值", "TypeError")
|
||||
@@ -913,7 +929,7 @@ class AssignGenMixin:
|
||||
if result is None:
|
||||
# fail-fast: 类型对齐失败
|
||||
self.Gen.TypeGenErr.fatal_error(target, "类型对齐失败", "TypeError")
|
||||
llvmlite.build_store(builder, result, elem_ptr)
|
||||
llvmlite.build_store(builder, result, elem_ptr, vol_sa)
|
||||
return 0
|
||||
|
||||
if tk != ast.ASTKind.Name:
|
||||
@@ -925,6 +941,17 @@ class AssignGenMixin:
|
||||
if nm is None or nm.id is None:
|
||||
return 0
|
||||
|
||||
# REPL 模式(M2/M3)会话变量增强赋值:读槽 → 二元运算 → 写槽 → 写结果区。
|
||||
# 未登记的会话名返回 0(继续原路径 → 明确的"无法加载…当前值"报错)。
|
||||
# 守卫 trans.ReplCtx:非 REPL 恒 None ⇒ 本分支整体不经过。
|
||||
# 作用域用 repl_in_frag_entry_scope(M3):被提升的会话函数体内 `x += 1`
|
||||
# 按普通局部变量路径处理(不写会话槽)。
|
||||
if trans.ReplCtx is not None \
|
||||
and self.Gen.VarGen.repl_in_frag_entry_scope(trans) != 0:
|
||||
if self.Gen.VarGen.repl_try_augassign(
|
||||
trans, nm.id, aug.op, aug.value, node) != 0:
|
||||
return 0
|
||||
|
||||
pool: rawptr[memhub.MemBuddy] = trans.Pool
|
||||
builder: rawptr[llvmlite.IRBuilder] = trans._cur_builder
|
||||
mod: rawptr[llvmlite.LLVMModule] = trans.Module
|
||||
@@ -936,6 +963,10 @@ class AssignGenMixin:
|
||||
elif GenApi.is_nonlocal_name(trans, nm.id) != 0:
|
||||
scope_type = 2
|
||||
|
||||
# t.CVolatile 变量:+= 的 load 与 store 均带 volatile 限定符
|
||||
vol_aa: int = self.Gen.VarGen.var_is_volatile(
|
||||
self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id))
|
||||
|
||||
# 2. 加载当前值
|
||||
cur_val: rawptr[llvmlite.Value] = None
|
||||
target_alloca: rawptr[llvmlite.Value] = None
|
||||
@@ -949,7 +980,7 @@ class AssignGenMixin:
|
||||
# fail-fast: 变量类型信息缺失,禁止兜底 i32
|
||||
self.Gen.TypeGenErr.fatal_error(target, "变量类型信息缺失", "TypeError")
|
||||
target_ty = target_alloca.Ty.Pointee
|
||||
cur_val = llvmlite.build_load(builder, target_ty, target_alloca)
|
||||
cur_val = llvmlite.build_load(builder, target_ty, target_alloca, vol_aa)
|
||||
elif scope_type == 2:
|
||||
# nonlocal 变量(通过闭包 env)
|
||||
cur_val = self.Gen.StmtGenDecl.load_nonlocal_var(trans, nm.id)
|
||||
@@ -963,7 +994,7 @@ class AssignGenMixin:
|
||||
# fail-fast: 变量类型信息缺失,禁止兜底 i32
|
||||
self.Gen.TypeGenErr.fatal_error(target, "变量类型信息缺失", "TypeError")
|
||||
target_ty = target_alloca.Ty.Pointee
|
||||
cur_val = llvmlite.build_load(builder, target_ty, target_alloca)
|
||||
cur_val = llvmlite.build_load(builder, target_ty, target_alloca, vol_aa)
|
||||
|
||||
if cur_val is None:
|
||||
# fail-fast: 目标变量当前值加载失败
|
||||
@@ -996,7 +1027,7 @@ class AssignGenMixin:
|
||||
if scope_type == 1:
|
||||
# global 变量
|
||||
if target_alloca is not None:
|
||||
llvmlite.build_store(builder, result, target_alloca)
|
||||
llvmlite.build_store(builder, result, target_alloca, vol_aa)
|
||||
elif scope_type == 2:
|
||||
# nonlocal 变量
|
||||
nl_ptr: rawptr[llvmlite.Value] = self.Gen.StmtGenDecl.get_nonlocal_var_ptr(
|
||||
@@ -1006,7 +1037,7 @@ class AssignGenMixin:
|
||||
else:
|
||||
# 普通局部变量
|
||||
if target_alloca is not None:
|
||||
llvmlite.build_store(builder, result, target_alloca)
|
||||
llvmlite.build_store(builder, result, target_alloca, vol_aa)
|
||||
|
||||
return 0
|
||||
|
||||
@@ -1176,6 +1207,15 @@ class AssignGenMixin:
|
||||
if self.is_ctypedef_annotation(aa.annotation) != 0:
|
||||
return 0
|
||||
|
||||
# REPL 模式(M2/M3):片段**入口**函数本体内的 AnnAssign 一律走会话槽(见
|
||||
# translate_annassign 的会话分支),此处不得预建局部 alloca——否则局部名
|
||||
# 会遮蔽同名会话变量(此后读 `x` 命中空局部槽,槽值丢失)。
|
||||
# 被提升的会话函数体内不走该分支(那里按普通局部声明预建 alloca)。
|
||||
# CDefine/CTypedef 两个分支在本次返回之前,其行为不变。
|
||||
if trans.ReplCtx is not None \
|
||||
and self.Gen.VarGen.repl_in_frag_entry_scope(trans) != 0:
|
||||
return 0
|
||||
|
||||
# global/nonlocal 变量不需要局部 alloca
|
||||
if GenApi.is_global_name(trans, nm.id) != 0:
|
||||
return 0
|
||||
@@ -1252,6 +1292,18 @@ class AssignGenMixin:
|
||||
if self._is_ptr_element_annotation(annot) != 0:
|
||||
self.Gen.VarGen.set_var_ptr_element(
|
||||
trans.SymTab, nm.id)
|
||||
# t.CVolatile:声明期即标记该变量的 load/store 带 volatile。
|
||||
# 覆盖「无初值声明」`x: t.CVolatile | T`(有初值路径
|
||||
# translate_annassign 亦会登记,幂等)。动机:volatile 禁优化器
|
||||
# 把忙等循环的重复 load 提升/消除,不能依赖优化器保序。
|
||||
if self.Gen.TypeGenErr.has_decorator_marker(
|
||||
annot, "CVolatile", 0) != 0:
|
||||
self.Gen.VarGen.set_var_volatile(trans.SymTab, nm.id)
|
||||
# rawptr[t.CVolatile | T](volatile 指针指向物,等价 C 的
|
||||
# volatile T*):解引用(p[i]/p.field/c.Deref(p))的 load/store
|
||||
# 带 volatile。声明期登记,覆盖「无初值声明」。
|
||||
if self.Gen.TypeGenErr.has_pointee_volatile_marker(annot) != 0:
|
||||
self.Gen.VarGen.set_var_pointee_volatile(trans.SymTab, nm.id)
|
||||
return 0
|
||||
return 0
|
||||
|
||||
@@ -1401,6 +1453,20 @@ class AssignGenMixin:
|
||||
self.Gen.TypeGenCType.register_ctypedef(pool_ct, nm.id, ctd_str)
|
||||
return 0
|
||||
|
||||
# REPL 模式(M2/M3)会话变量:片段**入口**函数本体内的带注解声明/赋值
|
||||
# (`x: int = 5` 定义并定型;`x: int` 仅定型)。注解先解析并定型条目,
|
||||
# 定型后的槽类型再作为 RHS 的 target_ty(与普通 AnnAssign 的 P1-A 同口径)。
|
||||
# 守卫 trans.ReplCtx:非 REPL 恒 None ⇒ 本分支整体不经过。
|
||||
# 被提升的会话函数体内不走该分支(`x: int = 5` 是局部声明,Python 语义)。
|
||||
if trans.ReplCtx is not None \
|
||||
and self.Gen.VarGen.repl_in_frag_entry_scope(trans) != 0:
|
||||
rp_e: rawptr[GenTypes.ReplVarEntry] = \
|
||||
self.Gen.VarGen.repl_ensure_entry(trans, nm.id, aa)
|
||||
if rp_e is not None:
|
||||
self.Gen.VarGen.repl_try_annassign(
|
||||
trans, nm.id, aa.annotation, aa.value, aa)
|
||||
return 0
|
||||
|
||||
pool: rawptr[memhub.MemBuddy] = trans.Pool
|
||||
builder: rawptr[llvmlite.IRBuilder] = trans._cur_builder
|
||||
mod: rawptr[llvmlite.LLVMModule] = trans.Module
|
||||
@@ -1434,7 +1500,12 @@ class AssignGenMixin:
|
||||
callable_ret: rawptr[llvmlite.LLVMType] = self.Gen.TypeGenErr.try_extract_callable_ret(
|
||||
pool, annot, trans._imported_modules, trans._from_imports, trans)
|
||||
if callable_ret is not None:
|
||||
self.Gen.CallGenLeafKit.register_func_ptr_sig(nm.id, callable_ret)
|
||||
# 返回值:0=成功/同名同类型幂等命中;非 0 已在 register_func_ptr_sig
|
||||
# 内部 fatal_error(表满/同名不同类型/表分配失败)终止编译。此处分支
|
||||
# 仅为防御——报错通道异常时不带着未登记的签名继续翻译。
|
||||
if self.Gen.CallGenLeafKit.register_func_ptr_sig(
|
||||
pool, nm.id, callable_ret, aa) != 0:
|
||||
return 0
|
||||
|
||||
# global 变量:写入模块作用域中的全局变量
|
||||
if GenApi.is_global_name(trans, nm.id) != 0:
|
||||
@@ -1447,12 +1518,12 @@ class AssignGenMixin:
|
||||
aa_glob_ty: rawptr[llvmlite.LLVMType] = None
|
||||
if mod_alloca.Ty is not None:
|
||||
aa_glob_ty = mod_alloca.Ty.Pointee
|
||||
# 供 c.Deref(i8*) 推断读取宽度 / 裸名泛型构造从注解推断类型实参:
|
||||
# 与主分支(普通局部变量路径)同一口径——必须在翻译 RHS 之前写入
|
||||
# CurAssignAnnot/CurAssignNode。四处(主分支 / 本 global 分支 /
|
||||
# 下方 mod_glob 分支 / 下方 nonlocal 分支)必须同步,否则
|
||||
# `x: int = c.Deref(p)` 的读取宽度与 `s: Stack[int] = Stack()`
|
||||
# 的类型实参推断都会拿不到注解。
|
||||
# 供裸名泛型构造从注解推断类型实参(消费者见 CallGenCtor.vp 的
|
||||
# CurAssignNode 判定):与主分支(普通局部变量路径)同一口径——
|
||||
# 必须在翻译 RHS 之前写入 CurAssignAnnot/CurAssignNode。四处
|
||||
# (主分支 / 本 global 分支 / 下方 mod_glob 分支 / 下方 nonlocal
|
||||
# 分支)必须同步,否则 `s: Stack[int] = Stack()` 的类型实参推断
|
||||
# 会拿不到注解。
|
||||
trans.CurAssignAnnot = aa.annotation
|
||||
trans.CurAssignNode = aa.value
|
||||
rhs_val: rawptr[llvmlite.Value] = self.Gen.ExprGen.translate_value(
|
||||
@@ -1493,11 +1564,13 @@ class AssignGenMixin:
|
||||
target_ty = mod_alloca.Ty.Pointee
|
||||
if target_ty is not None:
|
||||
rhs_val = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, target_ty, node, trans)
|
||||
llvmlite.build_store(builder, rhs_val, mod_alloca)
|
||||
# t.CVolatile(global 声明)全局:初始化 store 带 volatile 限定符
|
||||
vol_gaa: int = self.Gen.VarGen.var_is_volatile(
|
||||
self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id))
|
||||
llvmlite.build_store(builder, rhs_val, mod_alloca, vol_gaa)
|
||||
# 清除赋值上下文(防残留):与主分支清空时机同款。四处(主分支 /
|
||||
# 本 global 分支 / 下方 mod_glob 分支 / 下方 nonlocal 分支)必须同步清除,
|
||||
# 否则残留注解会让后续 while 条件/比较等处的 c.Deref 被误判读取宽度
|
||||
# (i8* 按 i32* 读 4 字节),也会污染裸名泛型构造的类型实参推断
|
||||
# 否则残留注解会污染后续语句里裸名泛型构造的类型实参推断
|
||||
trans.CurAssignAnnot = None
|
||||
trans.CurAssignNode = None
|
||||
return 0
|
||||
@@ -1515,12 +1588,11 @@ class AssignGenMixin:
|
||||
nl_target_ty: rawptr[llvmlite.LLVMType] = None
|
||||
if nl_ptr is not None and nl_ptr.Ty is not None:
|
||||
nl_target_ty = nl_ptr.Ty.Pointee
|
||||
# 供 c.Deref(i8*) 推断读取宽度 / 裸名泛型构造从注解推断类型实参:
|
||||
# 与主分支、上方 global 分支、下方 mod_glob 分支同一口径——必须在
|
||||
# 翻译 RHS 之前写入 CurAssignAnnot/CurAssignNode。四处(主分支 /
|
||||
# global / mod_glob / 本 nonlocal 分支)必须同步,否则
|
||||
# `nonlocal x: int = c.Deref(p)` 的读取宽度与
|
||||
# `nonlocal s: Stack[int] = Stack()` 的类型实参推断都会拿不到注解。
|
||||
# 供裸名泛型构造从注解推断类型实参:与主分支、上方 global 分支、
|
||||
# 下方 mod_glob 分支同一口径——必须在翻译 RHS 之前写入
|
||||
# CurAssignAnnot/CurAssignNode。四处(主分支 / global / mod_glob /
|
||||
# 本 nonlocal 分支)必须同步,否则
|
||||
# `nonlocal s: Stack[int] = Stack()` 的类型实参推断会拿不到注解。
|
||||
trans.CurAssignAnnot = aa.annotation
|
||||
trans.CurAssignNode = aa.value
|
||||
rhs_val: rawptr[llvmlite.Value] = self.Gen.ExprGen.translate_value(
|
||||
@@ -1542,9 +1614,8 @@ class AssignGenMixin:
|
||||
builder, rhs_val, nl_target_ty, node)
|
||||
llvmlite.build_store(builder, rhs_coerced, nl_ptr)
|
||||
# 清除赋值上下文(防残留):与主分支清空时机同款。四处(主分支 /
|
||||
# global / mod_glob / 本 nonlocal 分支)必须同步清除,否则残留注解会让
|
||||
# 后续 while 条件/比较等处的 c.Deref 被误判读取宽度(i8* 按 i32* 读 4
|
||||
# 字节),也会污染裸名泛型构造的类型实参推断
|
||||
# global / mod_glob / 本 nonlocal 分支)必须同步清除,否则残留注解会
|
||||
# 污染后续语句里裸名泛型构造的类型实参推断
|
||||
trans.CurAssignAnnot = None
|
||||
trans.CurAssignNode = None
|
||||
return 0
|
||||
@@ -1568,11 +1639,10 @@ class AssignGenMixin:
|
||||
mg_val_ty: rawptr[llvmlite.LLVMType] = None
|
||||
if mod_glob.Ty is not None:
|
||||
mg_val_ty = mod_glob.Ty.Pointee
|
||||
# 供 c.Deref(i8*) 推断读取宽度 / 裸名泛型构造从注解推断类型实参:
|
||||
# 与主分支、上方 global 分支同一口径——翻译 RHS 前写入
|
||||
# CurAssignAnnot/CurAssignNode。模块级 `s: Stack[int] = Stack()`
|
||||
# 走的就是本分支,四处(主分支 / global / 本 mod_glob 分支 /
|
||||
# 上方 nonlocal 分支)必须同步。
|
||||
# 供裸名泛型构造从注解推断类型实参:与主分支、上方 global 分支
|
||||
# 同一口径——翻译 RHS 前写入 CurAssignAnnot/CurAssignNode。
|
||||
# 模块级 `s: Stack[int] = Stack()` 走的就是本分支,四处(主分支 /
|
||||
# global / 本 mod_glob 分支 / 上方 nonlocal 分支)必须同步。
|
||||
trans.CurAssignAnnot = aa.annotation
|
||||
trans.CurAssignNode = aa.value
|
||||
rhs_val_mg: rawptr[llvmlite.Value] = self.Gen.ExprGen.translate_value(
|
||||
@@ -1613,11 +1683,13 @@ class AssignGenMixin:
|
||||
target_ty_mg = mod_glob.Ty.Pointee
|
||||
if target_ty_mg is not None:
|
||||
rhs_val_mg = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val_mg, target_ty_mg, node)
|
||||
llvmlite.build_store(builder, rhs_val_mg, mod_glob)
|
||||
# t.CVolatile 模块级全局:初始化 store 带 volatile 限定符
|
||||
vol_mga: int = self.Gen.VarGen.var_is_volatile(
|
||||
self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id))
|
||||
llvmlite.build_store(builder, rhs_val_mg, mod_glob, vol_mga)
|
||||
# 清除赋值上下文(防残留):与主分支清空时机同款。四处(主分支 /
|
||||
# 上方 global 分支 / 本 mod_glob 分支 / 上方 nonlocal 分支)必须同步清除,
|
||||
# 否则残留注解会让后续语句的 c.Deref 被误判读取宽度,并污染裸名泛型
|
||||
# 构造的类型实参推断
|
||||
# 否则残留注解会污染后续语句里裸名泛型构造的类型实参推断
|
||||
trans.CurAssignAnnot = None
|
||||
trans.CurAssignNode = None
|
||||
return 0
|
||||
@@ -1759,9 +1831,8 @@ class AssignGenMixin:
|
||||
self._init_global_array_from_list(
|
||||
builder, pool, mod, alloca, aa.value, trans)
|
||||
else:
|
||||
# 供 c.Deref(i8*) 推断读取宽度:v: int = c.Deref(p) → 读 i32
|
||||
# CurAssignNode 记录 RHS 节点:translate_c_deref 据此判定 Deref
|
||||
# 是否为赋值直接 RHS(对齐 TPC _infer_deref_target_type)。
|
||||
# 供裸名泛型构造从注解推断类型实参(消费者见 CallGenCtor.vp 的
|
||||
# CurAssignNode 判定:`s: Stack[int] = Stack()` 用注解里的 int 特化)。
|
||||
# 注意:本主分支(普通局部变量)、上方 global 分支、mod_glob 分支、
|
||||
# nonlocal 分支四处的 set/clear 必须同步(模块级 AnnAssign 走
|
||||
# mod_glob;闭包内 AnnAssign 走 nonlocal)。
|
||||
@@ -1854,7 +1925,19 @@ class AssignGenMixin:
|
||||
target_ty = alloca.Ty.Pointee
|
||||
if target_ty is not None:
|
||||
rhs_val = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, target_ty, node, trans)
|
||||
llvmlite.build_store(builder, rhs_val, alloca)
|
||||
# t.CVolatile 局部变量:标记 VarEntry 并让本次 store 带 volatile
|
||||
vol_laa: int = 0
|
||||
if aa.annotation is not None and nm.id is not None:
|
||||
if self.Gen.TypeGenErr.has_decorator_marker(
|
||||
aa.annotation, "CVolatile", 0) != 0:
|
||||
self.Gen.VarGen.set_var_volatile(trans.SymTab, nm.id)
|
||||
vol_laa = 1
|
||||
# rawptr[t.CVolatile | T](volatile 指针指向物):登记
|
||||
# PointeeVolatile;本 store 写的是指针变量自身,不影响。
|
||||
if self.Gen.TypeGenErr.has_pointee_volatile_marker(
|
||||
aa.annotation) != 0:
|
||||
self.Gen.VarGen.set_var_pointee_volatile(trans.SymTab, nm.id)
|
||||
llvmlite.build_store(builder, rhs_val, alloca, vol_laa)
|
||||
# FakeDuck: 初始化影子结构体 __data__ 字段 = 初始字符串指针
|
||||
# (对齐 TPC HandlesAnnAssign.py: 仅当有初值时写入 __data__)
|
||||
if fd_str_ty is not None and fd_meta_alloca is not None:
|
||||
@@ -1868,8 +1951,8 @@ class AssignGenMixin:
|
||||
if fd_data_ptr is not None:
|
||||
llvmlite.build_store(builder, rhs_val, fd_data_ptr)
|
||||
# 清除赋值上下文(防残留):CurAssignAnnot/CurAssignNode 只在该
|
||||
# AnnAssign 的 RHS 翻译期间有效,否则后续 while 条件/比较等处的
|
||||
# c.Deref 会被残留注解误判读取宽度(i8* 被 bitcast i32* 读 4 字节)。
|
||||
# AnnAssign 的 RHS 翻译期间有效,否则后续语句里裸名泛型构造的类型
|
||||
# 实参推断会拿到残留注解。
|
||||
# 四处(本主分支 / global / mod_glob / nonlocal)必须同步清除。
|
||||
trans.CurAssignAnnot = None
|
||||
trans.CurAssignNode = None
|
||||
@@ -1911,7 +1994,7 @@ class AssignGenMixin:
|
||||
VLogger.error("cast failed", "ASGN")
|
||||
return 0
|
||||
|
||||
targets: rawptr[list[rawptr[ast.AST]]] = asgn.targets
|
||||
targets: list[ast.AST*]* = asgn.targets
|
||||
if targets is None:
|
||||
VLogger.error("targets is None", "ASGN")
|
||||
return 0
|
||||
@@ -1923,7 +2006,7 @@ class AssignGenMixin:
|
||||
|
||||
# 翻译 RHS 值
|
||||
# 无注解赋值无目标类型可推断,清空 CurAssignAnnot/CurAssignNode
|
||||
# (防残留误判 c.Deref 宽度)
|
||||
# (防残留污染裸名泛型构造的类型实参推断)
|
||||
trans.CurAssignAnnot = None
|
||||
trans.CurAssignNode = None
|
||||
# P1-A(上下文位宽传播):单 Name 目标且其存储类型已知时,把存储类型作为
|
||||
@@ -1943,6 +2026,16 @@ class AssignGenMixin:
|
||||
trans.SymTab, asg_nm0.id)
|
||||
if asg_slot is not None and asg_slot.Ty is not None:
|
||||
asg_target_ty = asg_slot.Ty.Pointee
|
||||
elif trans.ReplCtx is not None \
|
||||
and self.Gen.VarGen.repl_in_frag_entry_scope(trans) != 0:
|
||||
# REPL 模式(M2/M3):已定型的会话变量也用槽类型做 target_ty
|
||||
# (与 P1-A 同口径;未定型则维持 None,由 RHS 类型定型)。
|
||||
# 只在片段入口函数生效(被提升的会话函数体内同名赋值是局部变量)
|
||||
asg_re: rawptr[GenTypes.ReplVarEntry] = \
|
||||
self.Gen.VarGen.repl_find_entry(trans.ReplCtx, asg_nm0.id)
|
||||
if asg_re is not None \
|
||||
and asg_re.Kind != GenTypes.REPL_KIND_UNTYPED:
|
||||
asg_target_ty = self.Gen.VarGen.repl_slot_ty(pool, asg_re)
|
||||
rhs_val: rawptr[llvmlite.Value] = self.Gen.ExprGen.translate_value(
|
||||
builder, pool, mod, asgn.value, None, 0, trans, asg_target_ty)
|
||||
if rhs_val is None:
|
||||
@@ -2008,7 +2101,7 @@ class AssignGenMixin:
|
||||
# store + GEP 逐字段 load → store 到各 Name 目标。
|
||||
if tk == ast.ASTKind.Tuple:
|
||||
tgt_tup: rawptr[ast.Tuple] = rawptr[ast.Tuple](target)
|
||||
tgt_elts: rawptr[list[rawptr[ast.AST]]] = tgt_tup.elts
|
||||
tgt_elts: list[ast.AST*]* = tgt_tup.elts
|
||||
# 守卫:rhs 不是 struct(tuple 打包)时跳过本 target
|
||||
if tgt_elts is None or rhs_val is None or rhs_val.Ty is None:
|
||||
continue
|
||||
@@ -2084,7 +2177,14 @@ class AssignGenMixin:
|
||||
if elem_ptr.Ty is not None and elem_ptr.Ty.Pointee is not None:
|
||||
store_val = self.Gen.ExprGenBase.coerce_to_type(
|
||||
builder, rhs_val, elem_ptr.Ty.Pointee, node, trans)
|
||||
llvmlite.build_store(builder, store_val, elem_ptr)
|
||||
# rawptr[t.CVolatile|T] 基址(volatile 指针指向物):p[i] = v
|
||||
# 的 store 带 volatile。仅基址可解析到条目时为 1(否则文本不变)。
|
||||
vol_sw: int = 0
|
||||
sub_wr: rawptr[ast.Subscript] = rawptr[ast.Subscript](target)
|
||||
if sub_wr is not None:
|
||||
vol_sw = self.Gen.ExprGenAttr.base_pointee_is_volatile(
|
||||
pool, trans, sub_wr.value)
|
||||
llvmlite.build_store(builder, store_val, elem_ptr, vol_sw)
|
||||
continue
|
||||
# get_subscript_ptr 返回 None: 尝试 __setitem__ 运算符重载
|
||||
# 适用于自定义类(如 hashtable[key]=val → hashtable.__setitem__(key, val))
|
||||
@@ -2262,7 +2362,17 @@ class AssignGenMixin:
|
||||
if field_ptr.Ty is not None and field_ptr.Ty.Pointee is not None:
|
||||
store_val = self.Gen.ExprGenBase.coerce_to_type(
|
||||
builder, rhs_val, field_ptr.Ty.Pointee, node, trans)
|
||||
llvmlite.build_store(builder, store_val, field_ptr)
|
||||
# t.CVolatile 字段:store 带 volatile 限定符
|
||||
vol_fw: int = self.Gen.ExprGenAttr.attr_field_is_volatile(
|
||||
pool, trans, target)
|
||||
# rawptr[t.CVolatile|T] 基址(volatile 指针指向物):p.field = v
|
||||
# 的 store 亦带 volatile(两来源取或)。
|
||||
at_wr: rawptr[ast.Attribute] = rawptr[ast.Attribute](target)
|
||||
if at_wr is not None:
|
||||
if self.Gen.ExprGenAttr.base_pointee_is_volatile(
|
||||
pool, trans, at_wr.value) != 0:
|
||||
vol_fw = 1
|
||||
llvmlite.build_store(builder, store_val, field_ptr, vol_fw)
|
||||
continue
|
||||
# 守卫:field_ptr 为 None → 构造详细错误信息
|
||||
attr_node: rawptr[ast.Attribute] = rawptr[ast.Attribute](target)
|
||||
@@ -2333,7 +2443,12 @@ class AssignGenMixin:
|
||||
target_ty = mod_alloca.Ty.Pointee
|
||||
if target_ty is not None:
|
||||
rhs_val = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, target_ty, node, trans)
|
||||
llvmlite.build_store(builder, rhs_val, mod_alloca)
|
||||
# t.CVolatile 全局:store 带 volatile 限定符
|
||||
vol_gas: int = 0
|
||||
if nm.id is not None:
|
||||
vol_gas = self.Gen.VarGen.var_is_volatile(
|
||||
self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id))
|
||||
llvmlite.build_store(builder, rhs_val, mod_alloca, vol_gas)
|
||||
continue
|
||||
|
||||
# nonlocal 变量:通过闭包 env 写入
|
||||
@@ -2362,6 +2477,20 @@ class AssignGenMixin:
|
||||
llvmlite.build_store(builder, rhs_coerced, nl_ptr)
|
||||
continue
|
||||
|
||||
# REPL 模式(M2/M3)会话变量:片段**入口**函数本体内的 Name 目标即
|
||||
# 会话变量(首次出现=定义:申请槽位 + 按 RHS 定型 + 写槽 + 写结果区)。
|
||||
# 守卫 trans.ReplCtx(非 REPL 恒 None ⇒ 本分支整体不经过);
|
||||
# repl_in_frag_entry_scope 排除被提升的会话函数体与片段内嵌套函数体
|
||||
# (那些仍用普通局部 alloca:Python 局部语义 + 防形参同名串味)。
|
||||
if trans.ReplCtx is not None \
|
||||
and self.Gen.VarGen.repl_in_frag_entry_scope(trans) != 0:
|
||||
rp_entry: rawptr[GenTypes.ReplVarEntry] = \
|
||||
self.Gen.VarGen.repl_ensure_entry(trans, nm.id, target)
|
||||
if rp_entry is not None:
|
||||
self.Gen.VarGen.repl_try_assign(
|
||||
trans, nm.id, rhs_val, asgn.value, node)
|
||||
continue
|
||||
|
||||
# 拦截:函数内对模块级全局变量赋值但没 global 声明
|
||||
# 否则静默创建局部变量遮蔽全局,全局保持 null 导致运行时崩溃
|
||||
# (_mbuddy = mb 缺 global 声明即此类 bug:Int32 解引用 null 崩溃)
|
||||
@@ -2387,7 +2516,10 @@ class AssignGenMixin:
|
||||
if alloca.Ty is not None and alloca.Ty.Pointee is not None:
|
||||
store_val = self.Gen.ExprGenBase.coerce_to_type(
|
||||
builder, rhs_val, alloca.Ty.Pointee, node, trans)
|
||||
llvmlite.build_store(builder, store_val, alloca)
|
||||
# t.CVolatile 局部变量:store 带 volatile 限定符
|
||||
vol_las: int = self.Gen.VarGen.var_is_volatile(
|
||||
self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id))
|
||||
llvmlite.build_store(builder, store_val, alloca, vol_las)
|
||||
# lambda 表达式赋给变量:注册为闭包变量名,
|
||||
# 调用分派(is_closure_name)才走闭包间接调用路径;
|
||||
# 否则 i8** alloca 被 _is_func_ptr_alloca 误判为
|
||||
|
||||
Reference in new issue
Block a user