Skip to main content

vm/
rt.rs

1use compiler::{Capture, Compiler, Symbol};
2use dynamic::{Dynamic, Type};
3use parser::{BinaryOp, Expr, ExprKind, PatternKind, Span, Stmt, StmtKind, UnaryOp};
4use std::collections::{BTreeMap, HashMap, VecDeque};
5
6use crate::context::{ListFastPath, LocalVar};
7
8use super::{FnInfo, FnVariant, PTR_TYPE, context::BuildContext, get_type, ptr_type};
9use cranelift::prelude::*;
10use cranelift_jit::{JITBuilder, JITModule};
11use cranelift_module::{FuncId, Module};
12
13use anyhow::{Result, anyhow};
14use parking_lot::RwLock;
15use smol_str::SmolStr;
16use std::sync::{Arc, Weak};
17
18/// VM 运行时注册的内置函数 ID。原先是 15 个独立的 `Option<FuncId>` 字段(`xxx_fn`),
19/// 全部依赖 `_fn` 后缀区分,same_concept_multi_field 气味;现在统一为一个 enum,
20/// 编译期保证命名空间、调用方代码更易读、新增 builtin 只需 enum 加一行。
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22pub enum BuiltinFn {
23    ScopeEnter,
24    ScopeExitVoid,
25    ScopeExitDynamic,
26    ScopeExitBytes,
27    StructAlloc,
28    RepeatFill,
29    Strcat,
30    StrcatI64,
31    StrcatAssign,
32    CallbackNew,
33    CallbackCall,
34    SpawnPtr,
35    StructFromPtr,
36    ArrayFromPtr,
37    ArrayToPtr,
38    ArithFault,
39}
40
41impl BuiltinFn {
42    /// 注册时用的 Cranelift 符号名。
43    /// 保留与原先 15 个独立字段的命名一致性,只改了字段 -> 集合里的 key。
44    fn symbol_name(self) -> &'static str {
45        match self {
46            Self::ScopeEnter => "__vm_scope_enter",
47            Self::ScopeExitVoid => "__vm_scope_exit_void",
48            Self::ScopeExitDynamic => "__vm_scope_exit_dynamic",
49            Self::ScopeExitBytes => "__vm_scope_exit_bytes",
50            Self::StructAlloc => "__vm_struct_alloc",
51            Self::RepeatFill => "__vm_repeat_fill",
52            Self::Strcat => "__vm_strcat",
53            Self::StrcatI64 => "__vm_strcat_i64",
54            Self::StrcatAssign => "__vm_strcat_assign",
55            Self::CallbackNew => "__vm_callback_new",
56            Self::CallbackCall => "__vm_callback_call",
57            Self::SpawnPtr => "__vm_spawn_ptr",
58            Self::StructFromPtr => "__vm_struct_from_ptr",
59            Self::ArrayFromPtr => "__vm_array_from_ptr",
60            Self::ArrayToPtr => "__vm_array_to_ptr",
61            Self::ArithFault => "__vm_arith_fault",
62        }
63    }
64
65    /// 未注册时的错误信息,与原先 31 处调用点的 `anyhow!(...)` 消息一致。
66    fn unregistered_msg(self) -> &'static str {
67        match self {
68            Self::ScopeEnter => "VM scope enter runtime is not registered",
69            Self::ScopeExitVoid => "VM scope exit runtime is not registered",
70            Self::ScopeExitDynamic => "VM dynamic return runtime is not registered",
71            Self::ScopeExitBytes => "VM aggregate return runtime is not registered",
72            Self::StructAlloc => "VM struct allocator runtime is not registered",
73            Self::RepeatFill => "VM repeat fill runtime is not registered",
74            Self::Strcat => "VM strcat runtime is not registered",
75            Self::StrcatI64 => "VM strcat i64 runtime is not registered",
76            Self::StrcatAssign => "VM strcat assign runtime is not registered",
77            Self::CallbackNew => "VM callback runtime is not registered",
78            Self::CallbackCall => "VM callback call runtime is not registered",
79            Self::SpawnPtr => "VM spawn ptr runtime is not registered",
80            Self::StructFromPtr => "VM struct Dynamic runtime is not registered",
81            Self::ArrayFromPtr => "VM array Dynamic runtime is not registered",
82            Self::ArrayToPtr => "VM array assignment runtime is not registered",
83            Self::ArithFault => "VM arith fault runtime is not registered",
84        }
85    }
86}
87
88/// 15 个内建函数的 FuncId 表,取代原先 `scope_enter_fn` ... `arith_fault_fn` 这 15 个
89/// `Option<FuncId>` 字段。新增 builtin 只需 `BuiltinFn` enum 加一行 + 写入这里。
90#[derive(Default, Debug, Clone)]
91pub struct BuiltinFnRegistry {
92    map: HashMap<BuiltinFn, FuncId>,
93}
94
95impl BuiltinFnRegistry {
96    pub(crate) fn register(&mut self, which: BuiltinFn, id: FuncId) {
97        self.map.insert(which, id);
98    }
99
100    pub fn get(&self, which: BuiltinFn) -> Option<FuncId> {
101        self.map.get(&which).copied()
102    }
103
104    pub fn get_or_err(&self, which: BuiltinFn) -> Result<FuncId> {
105        self.get(which).ok_or_else(|| anyhow!("{}", which.unregistered_msg()))
106    }
107}
108
109pub struct JITRunTime {
110    pub compiler: Compiler,
111    pub fns: BTreeMap<u32, FnVariant>,
112    pub sigs: Vec<(Vec<Type>, Signature, Type)>,
113    pub native_symbols: Arc<RwLock<HashMap<String, usize>>>,
114    pub(crate) owner: Weak<RwLock<JITRunTime>>,
115    pub(crate) pending_fns: VecDeque<PendingFn>,
116    pub(crate) compile_depth: usize,
117    inline_depth: usize,
118    inline_budget: usize,
119    inline_stack: Vec<u32>,
120    native_fn_cache: Vec<(SmolStr, Vec<Type>, FnInfo)>,
121    #[cfg(feature = "ir-disassembly")]
122    pub ir_disassembly: BTreeMap<SmolStr, String>,
123    pub module: JITModule,
124    pub consts: Vec<Option<usize>>,
125    /// 15 个 VM builtin runtime 函数的 FuncId 表,见 [`BuiltinFnRegistry`]。
126    /// 取代原先 15 个独立的 `Option<FuncId>` 字段(同概念多字段气味)。
127    pub(crate) builtin_fns: BuiltinFnRegistry,
128}
129
130// TODO(memory): 函数调用期间为 VM 内部临时 Any/struct 分配引入 arena。
131// 临时值进入 arena,返回值 promote 给 Rust 调用方;否则需要完整 drop 插桩,
132// 覆盖表达式丢弃、变量覆盖、函数出口、break/continue/return 等路径。
133pub(crate) struct PendingFn {
134    pub name: SmolStr,
135    pub symbol_id: u32,
136    pub fn_id: FuncId,
137    pub arg_tys: Vec<Type>,
138    pub ret_ty: Type,
139    pub local_type_hints: Vec<Option<Type>>,
140    pub body: Stmt,
141}
142
143impl JITRunTime {
144    fn expr(kind: ExprKind) -> Expr {
145        Expr::new(kind, Span::default())
146    }
147
148    fn stmt(kind: StmtKind) -> Stmt {
149        Stmt::new(kind, Span::default())
150    }
151
152    pub(crate) fn type_ptr_const(ctx: &mut BuildContext, ty: &Type) -> Value {
153        let ty_ptr = Box::into_raw(Box::new(ty.clone()));
154        ctx.builder.ins().iconst(ptr_type(), ty_ptr as i64)
155    }
156
157    pub fn load(&mut self, code: Vec<u8>, arg_name: SmolStr) -> Result<(i64, Type)> {
158        let stmts = Compiler::parse_code(code)?;
159        self.compiler.resolve_imports(&stmts, None)?;
160        self.compiler.clear();
161        self.compiler.sym_tab.symbols.add_module("__console".into());
162        let mut cap = Capture::default();
163        let body = Self::stmt(StmtKind::Block(self.compiler.compile_fn(&[arg_name], &mut vec![Type::Any], Self::stmt(StmtKind::Block(stmts)), &mut cap)?));
164        self.compiler.sym_tab.tys.push(Type::Any);
165        let ret_ty = self.compiler.infer_stmt(&body)?;
166        self.compiler.clear();
167        let fn_id = self.compile_fn(None, &[Type::Any], ret_ty.clone(), &body)?;
168        self.compiler.clear();
169        self.compiler.sym_tab.symbols.pop_module();
170        self.module.finalize_definitions()?;
171        Ok((self.module.get_finalized_function(fn_id) as i64, ret_ty))
172    }
173
174    pub fn import_code(&mut self, name: &str, code: Vec<u8>) -> Result<()> {
175        log::debug!("import {}", name);
176        let _ = self.compiler.import_code(name, code)?;
177        Ok(())
178    }
179
180    pub fn import_source(&mut self, name: &str, source: &str) -> Result<()> {
181        self.import_code(name, source.as_bytes().to_vec())
182    }
183
184    #[cfg(feature = "ir-disassembly")]
185    pub fn disassemble_ir(&mut self, name: &str) -> Result<String> {
186        if let Some(ir) = self.ir_disassembly.get(name) {
187            return Ok(ir.clone());
188        }
189        let id = self.get_id(name)?;
190        let (_, symbol) = self.compiler.sym_tab.symbols.get_symbol(id)?;
191        if let Symbol::Fn { ty, .. } = symbol
192            && let Type::Fn { tys, .. } = ty
193            && tys.is_empty()
194        {
195            let _ = self.gen_fn(None, id, &[])?;
196        }
197        self.ir_disassembly.get(name).cloned().ok_or_else(|| anyhow!("未找到函数 {} 的 Cranelift IR;如果它需要参数,请先触发对应实例化", name))
198    }
199
200    pub fn get_fn_ptr(&mut self, name: &str, arg_tys: &[Type]) -> Result<(*const u8, Type)> {
201        let main_id = self.get_id(name)?;
202        let fn_info = self.gen_fn(None, main_id, arg_tys)?;
203        Ok((self.module.get_finalized_function(fn_info.get_id()?), fn_info.get_type()?))
204    }
205
206    pub fn get_fn_ptr_with_params(&mut self, name: &str, arg_tys: &[Type], generic_args: &[Type]) -> Result<(*const u8, Type)> {
207        let main_id = self.get_id(name)?;
208        let fn_info = self.gen_fn_with_params(None, main_id, arg_tys, generic_args)?;
209        Ok((self.module.get_finalized_function(fn_info.get_id()?), fn_info.get_type()?))
210    }
211
212    pub fn get_const_value(&mut self, ctx: &mut BuildContext, idx: usize) -> Result<(Value, Type)> {
213        if self.consts.len() < idx + 1 {
214            self.consts.resize(idx + 1, None);
215        }
216        let ptr = if let Some(ptr) = self.consts.get(idx).cloned().unwrap_or(None) {
217            ptr
218        } else {
219            let c = Box::new(self.compiler.sym_tab.consts[idx].deep_clone()); //深度拷贝 避免常量被污染
220            let ptr = Box::into_raw(c) as usize;
221            self.consts[idx] = Some(ptr);
222            ptr
223        };
224        let value = ctx.builder.ins().iconst(ptr_type(), ptr as i64); //需要生成副本 避免被释放
225        let ty = if self.compiler.sym_tab.consts[idx].is_str() { Type::Str } else { Type::Any };
226        Ok((self.call(ctx, self.get_method(&Type::Any, "clone")?, vec![value])?.0, ty))
227    }
228
229    fn get_null_value(&mut self, ctx: &mut BuildContext) -> Result<(Value, Type)> {
230        let const_idx = self.compiler.get_const(Dynamic::Null);
231        self.get_const_value(ctx, const_idx)
232    }
233
234    pub fn get_dynamic(&self, expr: &Expr) -> Option<Dynamic> {
235        match &expr.kind {
236            ExprKind::Value(value) => Some(value.clone()),
237            ExprKind::Const(idx) => self.compiler.sym_tab.consts.get_index(*idx).map(|(_, v)| v.clone()),
238            _ => None,
239        }
240    }
241
242    fn compile_error(&self, ctx: &BuildContext, span: Span, message: impl AsRef<str>) -> anyhow::Error {
243        if let Some(fn_name) = &ctx.fn_name { anyhow!("{}", self.compiler.format_source_span(fn_name.as_str(), span, message.as_ref())) } else { anyhow!("{}", message.as_ref()) }
244    }
245
246    pub fn get_method(&self, ty: &Type, name: &str) -> Result<FnInfo> {
247        let method_ty = if matches!(ty, Type::Map | Type::List(_) | Type::Iter) { Type::Any } else { ty.clone() };
248        self.compiler.get_field(&method_ty, name).and_then(|(_, ty)| if let Type::Symbol { id, params: _ } = ty { self.get_fn(id, &[]) } else { Err(anyhow!("不是成员函数")) })
249    }
250
251    fn is_fn_field_type(&self, ty: &Type) -> bool {
252        match ty {
253            Type::Symbol { id, .. } => self.compiler.sym_tab.symbols.get_symbol(*id).map(|(_, symbol)| symbol.is_fn()).unwrap_or(false),
254            Type::Fn { .. } => true,
255            _ => false,
256        }
257    }
258
259    pub(crate) fn is_opaque_custom_ty(&self, ty: &Type) -> bool {
260        let ty = self.compiler.sym_tab.symbols.get_type(ty).unwrap_or_else(|_| ty.clone());
261        matches!(ty, Type::Struct { fields, .. } if !fields.is_empty() && fields.iter().all(|(_, field_ty)| self.is_fn_field_type(field_ty)))
262    }
263
264    pub(crate) fn is_aggregate_ty(&self, ty: &Type) -> bool {
265        (ty.is_struct() && !self.is_opaque_custom_ty(ty)) || ty.is_array()
266    }
267
268    pub fn get_id(&self, name: &str) -> Result<u32> {
269        self.compiler.sym_tab.symbols.get_id(name)
270    }
271
272    fn get_native_fn_cached(&mut self, name: &'static str, arg_tys: &[Type]) -> Result<FnInfo> {
273        if let Some((_, _, fn_info)) = self.native_fn_cache.iter().find(|(cached_name, cached_tys, _)| cached_name.as_str() == name && cached_tys.as_slice() == arg_tys) {
274            return Ok(fn_info.clone());
275        }
276        let fn_info = self.get_fn(self.get_id(name)?, arg_tys)?;
277        self.native_fn_cache.push((SmolStr::new(name), arg_tys.to_vec(), fn_info.clone()));
278        Ok(fn_info)
279    }
280
281    pub fn get_type(&mut self, name: &str, arg_tys: &[Type]) -> Result<Type> {
282        let id = self.get_id(name)?;
283        if self.compiler.sym_tab.symbols.symbols.get(name).map(|s| s.is_fn()).unwrap_or(false) {
284            return self.compiler.infer_fn(id, arg_tys);
285        }
286        self.compiler.sym_tab.symbols.get_type(&Type::Symbol { id, params: Vec::new() })
287    }
288
289    pub fn new<F: FnMut(&mut JITBuilder)>(mut f: F) -> Self {
290        let native_symbols = Arc::new(RwLock::new(HashMap::<String, usize>::new()));
291        let lookup_symbols = native_symbols.clone();
292        let mut builder = JITBuilder::new(cranelift_module::default_libcall_names()).unwrap();
293        builder.symbol_lookup_fn(Box::new(move |name| lookup_symbols.read().get(name).copied().map(|ptr| ptr as *const u8)));
294        f(&mut builder);
295        let module = JITModule::new(builder);
296        PTR_TYPE.get_or_init(|| module.isa().pointer_type());
297        let fns = BTreeMap::<u32, FnVariant>::new();
298        Self {
299            compiler: Compiler::new(),
300            fns,
301            sigs: Vec::new(),
302            native_symbols,
303            owner: Weak::new(),
304            pending_fns: VecDeque::new(),
305            compile_depth: 0,
306            inline_depth: 0,
307            inline_budget: 256,
308            inline_stack: Vec::new(),
309            native_fn_cache: Vec::new(),
310            #[cfg(feature = "ir-disassembly")]
311            ir_disassembly: BTreeMap::new(),
312            module,
313            consts: Vec::new(),
314            builtin_fns: BuiltinFnRegistry::default(),
315        }
316    }
317
318    pub(crate) fn set_owner(&mut self, owner: Weak<RwLock<JITRunTime>>) {
319        self.owner = owner;
320    }
321
322    pub(crate) fn owner_context_ptr(&self) -> usize {
323        &self.owner as *const Weak<RwLock<JITRunTime>> as usize
324    }
325
326    fn unary(ctx: &mut BuildContext, left: (Value, Type), op: UnaryOp) -> Result<(Value, Type)> {
327        match op {
328            UnaryOp::Neg => {
329                if left.1.is_int() || left.1.is_uint() {
330                    let (int_ty, result_ty) = match left.1.width() {
331                        8 => (types::I64, Type::I64),
332                        4 => (types::I32, Type::I32),
333                        2 => (types::I16, Type::I16),
334                        _ => (types::I8, Type::I8),
335                    };
336                    let zero = ctx.builder.ins().iconst(int_ty, 0);
337                    return Ok((ctx.builder.ins().isub(zero, left.0), result_ty));
338                } else if left.1.is_float() {
339                    return Ok((ctx.builder.ins().fneg(left.0), left.1));
340                }
341            }
342            UnaryOp::Not => {
343                if left.1.is_int() || left.1.is_uint() {
344                    let all_ones = ctx.builder.ins().iconst(get_type(&left.1)?, -1);
345                    return Ok((ctx.builder.ins().bxor(left.0, all_ones), left.1));
346                }
347                let zero = ctx.builder.ins().iconst(types::I8, 0);
348                let one = ctx.builder.ins().iconst(types::I8, 1);
349                let cond = if left.1.is_bool() {
350                    left.0
351                } else if left.1.is_f32() {
352                    let zero = ctx.builder.ins().f32const(0.0);
353                    ctx.builder.ins().fcmp(FloatCC::NotEqual, left.0, zero)
354                } else if left.1.is_f64() {
355                    let zero = ctx.builder.ins().f64const(0.0);
356                    ctx.builder.ins().fcmp(FloatCC::NotEqual, left.0, zero)
357                } else {
358                    return Err(anyhow!("未实现 {:?} {:?}", left, op));
359                };
360                let is_zero = ctx.builder.ins().icmp_imm(IntCC::Equal, cond, 0);
361                return Ok((ctx.builder.ins().select(is_zero, one, zero), Type::Bool));
362            }
363            _ => {}
364        }
365        Err(anyhow!("未实现 {:?} {:?}", left, op))
366    }
367
368    pub(crate) fn call(&mut self, ctx: &mut BuildContext, fn_info: FnInfo, args: Vec<Value>) -> Result<(Value, Type)> {
369        match fn_info {
370            FnInfo::Call { fn_id, arg_tys: _, caps: _, ret, context } => {
371                let fn_ref = self.get_fn_ref(ctx, fn_id);
372                let args = self.add_context_arg(ctx, context, args);
373                let call_inst = ctx.builder.ins().call(fn_ref, &args);
374                if !ret.is_void() { Ok((ctx.builder.inst_results(call_inst)[0], ret)) } else { Err(anyhow!("没有返回值")) }
375            }
376            FnInfo::Inline { fn_ptr, arg_tys: _ } => fn_ptr(Some(ctx), args).and_then(|(v, t)| v.map(|value| (value, t)).ok_or_else(|| anyhow!("inlined native callback returned no value"))),
377        }
378    }
379
380    pub(crate) fn scope_enter(&mut self, ctx: &mut BuildContext) -> Result<()> {
381        let fn_id = self.builtin_fns.get_or_err(BuiltinFn::ScopeEnter)?;
382        let fn_ref = self.get_fn_ref(ctx, fn_id);
383        ctx.builder.ins().call(fn_ref, &[]);
384        Ok(())
385    }
386
387    fn scope_exit_void(&mut self, ctx: &mut BuildContext) -> Result<()> {
388        let fn_id = self.builtin_fns.get_or_err(BuiltinFn::ScopeExitVoid)?;
389        let fn_ref = self.get_fn_ref(ctx, fn_id);
390        ctx.builder.ins().call(fn_ref, &[]);
391        Ok(())
392    }
393
394    fn return_value(&mut self, ctx: &mut BuildContext, value: Option<(Value, Type)>) -> Result<()> {
395        let ret_ty = ctx.ret_ty.clone();
396        if ret_ty.is_void() {
397            self.scope_exit_void(ctx)?;
398            ctx.builder.ins().return_(&[]);
399            return Ok(());
400        }
401
402        let Some((value, value_ty)) = value else {
403            self.scope_exit_void(ctx)?;
404            ctx.builder.ins().return_(&[]);
405            return Ok(());
406        };
407
408        if ret_ty.is_any() || ret_ty.is_str() || matches!(ret_ty, Type::Map | Type::List(_) | Type::Iter) {
409            let value = self.convert(ctx, (value, value_ty), Type::Any)?;
410            let fn_id = self.builtin_fns.get_or_err(BuiltinFn::ScopeExitDynamic)?;
411            let fn_ref = self.get_fn_ref(ctx, fn_id);
412            let call_inst = ctx.builder.ins().call(fn_ref, &[value]);
413            let promoted = ctx.builder.inst_results(call_inst)[0];
414            ctx.builder.ins().return_(&[promoted]);
415        } else if self.is_aggregate_ty(&ret_ty) {
416            let value = self.convert(ctx, (value, value_ty), ret_ty.clone())?;
417            let size = ctx.builder.ins().iconst(types::I64, ret_ty.width() as i64);
418            let ty_ptr = Self::type_ptr_const(ctx, &ret_ty);
419            let fn_id = self.builtin_fns.get_or_err(BuiltinFn::ScopeExitBytes)?;
420            let fn_ref = self.get_fn_ref(ctx, fn_id);
421            let call_inst = ctx.builder.ins().call(fn_ref, &[value, size, ty_ptr]);
422            let promoted = ctx.builder.inst_results(call_inst)[0];
423            ctx.builder.ins().return_(&[promoted]);
424        } else {
425            let value = self.convert(ctx, (value, value_ty), ret_ty)?;
426            self.scope_exit_void(ctx)?;
427            ctx.builder.ins().return_(&[value]);
428        }
429        Ok(())
430    }
431
432    fn call_for_side_effect(&mut self, ctx: &mut BuildContext, fn_info: FnInfo, args: Vec<Value>) -> Result<()> {
433        match fn_info {
434            FnInfo::Call { fn_id, arg_tys: _, caps: _, ret: _, context } => {
435                let fn_ref = self.get_fn_ref(ctx, fn_id);
436                let args = self.add_context_arg(ctx, context, args);
437                ctx.builder.ins().call(fn_ref, &args);
438                Ok(())
439            }
440            FnInfo::Inline { fn_ptr, arg_tys: _ } => fn_ptr(Some(ctx), args).map(|_| ()),
441        }
442    }
443
444    fn add_context_arg(&mut self, ctx: &mut BuildContext, context: Option<usize>, mut args: Vec<Value>) -> Vec<Value> {
445        if let Some(context) = context {
446            let context = ctx.builder.ins().iconst(ptr_type(), context as i64);
447            args.insert(0, context);
448        }
449        args
450    }
451
452    pub(crate) fn short_circuit_logic(&mut self, ctx: &mut BuildContext, left: (Value, Type), op: BinaryOp, right: &Expr) -> Result<(Value, Type)> {
453        let left = self.bool_value(ctx, left)?;
454        let rhs_block = ctx.builder.create_block();
455        let short_block = ctx.builder.create_block();
456        let end_block = ctx.builder.create_block();
457        ctx.builder.append_block_param(end_block, types::I8);
458
459        match op {
460            BinaryOp::And => {
461                ctx.builder.ins().brif(left, rhs_block, &[], short_block, &[]);
462            }
463            BinaryOp::Or => {
464                ctx.builder.ins().brif(left, short_block, &[], rhs_block, &[]);
465            }
466            _ => unreachable!(),
467        }
468
469        ctx.builder.switch_to_block(rhs_block);
470        let right = match self.eval(ctx, right)?.get(ctx) {
471            Some(right) => self.bool_value(ctx, right)?,
472            None => ctx.builder.ins().iconst(types::I8, 0),
473        };
474        ctx.builder.ins().jump(end_block, &[cranelift::codegen::ir::BlockArg::Value(right)]);
475        ctx.builder.seal_block(rhs_block);
476
477        ctx.builder.switch_to_block(short_block);
478        let short_value = match op {
479            BinaryOp::And => ctx.builder.ins().iconst(types::I8, 0),
480            BinaryOp::Or => ctx.builder.ins().iconst(types::I8, 1),
481            _ => unreachable!(),
482        };
483        ctx.builder.ins().jump(end_block, &[cranelift::codegen::ir::BlockArg::Value(short_value)]);
484        ctx.builder.seal_block(short_block);
485
486        ctx.builder.switch_to_block(end_block);
487        let result = ctx.builder.block_params(end_block)[0];
488        Ok((result, Type::Bool))
489    }
490
491    fn struct_alloc(&mut self, ctx: &mut BuildContext, ty: &Type) -> Result<Value> {
492        let size = ctx.builder.ins().iconst(types::I64, ty.width() as i64);
493        let fn_id = self.builtin_fns.get_or_err(BuiltinFn::StructAlloc)?;
494        let fn_ref = self.get_fn_ref(ctx, fn_id);
495        let call_inst = ctx.builder.ins().call(fn_ref, &[size]);
496        Ok(ctx.builder.inst_results(call_inst)[0])
497    }
498
499    fn store_struct_field(&mut self, ctx: &mut BuildContext, base: Value, idx: usize, field_ty: &Type, value: (Value, Type), struct_ty: &Type) -> Result<()> {
500        let offset = struct_ty.field_offset(idx).ok_or_else(|| anyhow!("结构字段索引越界 {}", idx))?;
501        let value = self.convert(ctx, value, field_ty.clone())?;
502        if field_ty.is_struct() || field_ty.is_array() {
503            let field_addr = ctx.builder.ins().iadd_imm(base, offset as i64);
504            self.copy_vec_element(ctx, field_addr, value, field_ty);
505        } else {
506            ctx.builder.ins().store(MemFlags::trusted(), value, base, offset as i32);
507        }
508        Ok(())
509    }
510
511    fn load_struct_field(&mut self, ctx: &mut BuildContext, base: Value, idx: usize, struct_ty: &Type) -> Result<(Value, Type)> {
512        if let Type::Struct { params: _, fields } = struct_ty {
513            let field_ty = fields.get(idx).map(|(_, ty)| ty).ok_or_else(|| anyhow!("结构字段索引越界 {}", idx))?;
514            let offset = struct_ty.field_offset(idx).ok_or_else(|| anyhow!("结构字段索引越界 {}", idx))?;
515            if field_ty.is_struct() || field_ty.is_array() {
516                return Ok((ctx.builder.ins().iadd_imm(base, offset as i64), field_ty.clone()));
517            }
518            let val = ctx.builder.ins().load(crate::get_type(field_ty)?, MemFlags::trusted(), base, offset as i32);
519            Ok((val, field_ty.clone()))
520        } else {
521            Err(anyhow!("不是结构体 {:?}", struct_ty))
522        }
523    }
524
525    fn struct_field_index(&self, struct_ty: &Type, right: &Expr) -> Result<usize> {
526        let value = if let ExprKind::Const(idx) = right.kind { self.compiler.sym_tab.consts.get_index(idx).map(|(_, v)| v.clone()).ok_or_else(|| anyhow!("missing const {}", idx))? } else { right.clone().value()? };
527        if let Some(idx) = value.as_int() {
528            return usize::try_from(idx).map_err(|_| anyhow!("结构字段索引越界 {}", idx));
529        }
530        if value.is_str() {
531            return self.compiler.get_field(struct_ty, value.as_str()).map(|(idx, _)| idx);
532        }
533        Err(anyhow!("非立即数结构字段索引 {:?}", right))
534    }
535
536    fn vec_elem_ty(ty: &Type) -> Option<Type> {
537        if let Type::Vec(elem, 0) = ty { Some((**elem).clone()) } else { None }
538    }
539
540    fn array_elem_ty(ty: &Type) -> Option<Type> {
541        if let Type::Array(elem, _) = ty { Some((**elem).clone()) } else { None }
542    }
543
544    fn vec_index_addr(&mut self, ctx: &mut BuildContext, base: Value, idx: (Value, Type), elem_ty: &Type) -> Result<Value> {
545        let idx = self.convert(ctx, idx, Type::I64)?;
546        let width = ctx.builder.ins().iconst(types::I64, elem_ty.storage_width() as i64);
547        let offset = ctx.builder.ins().imul(idx, width);
548        Ok(ctx.builder.ins().iadd(base, offset))
549    }
550
551    fn array_index_addr(&mut self, ctx: &mut BuildContext, base: Value, idx: (Value, Type), elem_ty: &Type) -> Result<Value> {
552        self.vec_index_addr(ctx, base, idx, elem_ty)
553    }
554
555    fn load_array_index(&mut self, ctx: &mut BuildContext, base: Value, idx: (Value, Type), elem_ty: &Type) -> Result<(Value, Type)> {
556        let addr = self.array_index_addr(ctx, base, idx, elem_ty)?;
557        if elem_ty.is_struct() || elem_ty.is_array() {
558            Ok((addr, elem_ty.clone()))
559        } else {
560            let val = ctx.builder.ins().load(crate::get_type(elem_ty)?, MemFlags::trusted(), addr, 0);
561            Ok((val, elem_ty.clone()))
562        }
563    }
564
565    fn store_array_index(&mut self, ctx: &mut BuildContext, base: Value, idx: (Value, Type), elem_ty: &Type, value: (Value, Type)) -> Result<()> {
566        let addr = self.array_index_addr(ctx, base, idx, elem_ty)?;
567        let value = self.convert(ctx, value, elem_ty.clone())?;
568        if elem_ty.is_struct() || elem_ty.is_array() {
569            self.copy_vec_element(ctx, addr, value, elem_ty);
570        } else {
571            let value = LocalVar::normalize_for_var(ctx, value, elem_ty);
572            ctx.builder.ins().store(MemFlags::trusted(), value, addr, 0);
573        }
574        Ok(())
575    }
576
577    fn init_repeat_array(&mut self, ctx: &mut BuildContext, value: (Value, Type), len: u32) -> Result<(Value, Type)> {
578        let elem_ty = value.1.clone();
579        let array_ty = Type::Array(std::rc::Rc::new(elem_ty.clone()), len);
580        let base = self.struct_alloc(ctx, &array_ty)?;
581        if let Some(pattern) = self.repeat_fill_pattern(ctx, value.0, &elem_ty) {
582            let fn_id = self.builtin_fns.get_or_err(BuiltinFn::RepeatFill)?;
583            let fn_ref = self.get_fn_ref(ctx, fn_id);
584            let width = ctx.builder.ins().iconst(types::I64, elem_ty.storage_width() as i64);
585            let len = ctx.builder.ins().iconst(types::I64, len as i64);
586            ctx.builder.ins().call(fn_ref, &[base, pattern, width, len]);
587            return Ok((base, array_ty));
588        }
589        for idx in 0..len {
590            let idx = (ctx.builder.ins().iconst(types::I64, idx as i64), Type::I64);
591            self.store_array_index(ctx, base, idx, &elem_ty, value.clone())?;
592        }
593        Ok((base, array_ty))
594    }
595
596    fn repeat_fill_pattern(&mut self, ctx: &mut BuildContext, value: Value, ty: &Type) -> Option<Value> {
597        if matches!(ty, Type::Bool) || ty.is_int() || ty.is_uint() {
598            return Some(if ty.storage_width() < 8 { ctx.builder.ins().uextend(types::I64, value) } else { value });
599        }
600        if ty.is_f32() {
601            let flags = MemFlags::new().with_endianness(cranelift::codegen::ir::Endianness::Little);
602            let bits = ctx.builder.ins().bitcast(types::I32, flags, value);
603            return Some(ctx.builder.ins().uextend(types::I64, bits));
604        }
605        if ty.is_f64() {
606            let flags = MemFlags::new().with_endianness(cranelift::codegen::ir::Endianness::Little);
607            return Some(ctx.builder.ins().bitcast(types::I64, flags, value));
608        }
609        None
610    }
611
612    fn init_array_from_items(&mut self, ctx: &mut BuildContext, items: &[Expr], ty: &Type) -> Result<Value> {
613        let Type::Array(elem_ty, len) = ty else {
614            return Err(anyhow!("not an array type: {:?}", ty));
615        };
616        if items.len() != *len as usize {
617            return Err(anyhow!("array literal length {} does not match {}", items.len(), len));
618        }
619        let base = self.struct_alloc(ctx, ty)?;
620        for (idx, item) in items.iter().enumerate() {
621            let value = self.eval(ctx, item)?.get(ctx).ok_or(anyhow!("array item has no value"))?;
622            let idx = (ctx.builder.ins().iconst(types::I64, idx as i64), Type::I64);
623            self.store_array_index(ctx, base, idx, elem_ty, value)?;
624        }
625        Ok(base)
626    }
627
628    pub(crate) fn any_to_array(&mut self, ctx: &mut BuildContext, value: Value, ty: &Type) -> Result<Value> {
629        let Type::Array(_, _) = ty else {
630            return Err(anyhow!("not an array type: {:?}", ty));
631        };
632        let base = self.struct_alloc(ctx, ty)?;
633        let ty_ptr = Self::type_ptr_const(ctx, ty);
634        let fn_id = self.builtin_fns.get_or_err(BuiltinFn::ArrayToPtr)?;
635        let fn_ref = self.get_fn_ref(ctx, fn_id);
636        ctx.builder.ins().call(fn_ref, &[base, value, ty_ptr]);
637        Ok(base)
638    }
639
640    fn load_vec_index(&mut self, ctx: &mut BuildContext, base: Value, idx: (Value, Type), elem_ty: &Type) -> Result<(Value, Type)> {
641        let addr = self.vec_index_addr(ctx, base, idx, elem_ty)?;
642        if elem_ty.is_struct() {
643            Ok((addr, elem_ty.clone()))
644        } else {
645            let val = ctx.builder.ins().load(crate::get_type(elem_ty)?, MemFlags::trusted(), addr, 0);
646            Ok((val, elem_ty.clone()))
647        }
648    }
649
650    fn copy_vec_element(&mut self, ctx: &mut BuildContext, dst: Value, src: Value, elem_ty: &Type) {
651        let mut offset = 0u32;
652        let width = elem_ty.storage_width();
653        while offset < width {
654            let remaining = width - offset;
655            let (ty, size) = if remaining >= 8 {
656                (types::I64, 8)
657            } else if remaining >= 4 {
658                (types::I32, 4)
659            } else if remaining >= 2 {
660                (types::I16, 2)
661            } else {
662                (types::I8, 1)
663            };
664            let value = ctx.builder.ins().load(ty, MemFlags::trusted(), src, offset as i32);
665            ctx.builder.ins().store(MemFlags::trusted(), value, dst, offset as i32);
666            offset += size;
667        }
668    }
669
670    fn store_vec_index(&mut self, ctx: &mut BuildContext, base: Value, idx: (Value, Type), elem_ty: &Type, value: (Value, Type)) -> Result<()> {
671        let addr = self.vec_index_addr(ctx, base, idx, elem_ty)?;
672        let value = self.convert(ctx, value, elem_ty.clone())?;
673        if elem_ty.is_struct() {
674            self.copy_vec_element(ctx, addr, value, elem_ty);
675        } else {
676            let value = LocalVar::normalize_for_var(ctx, value, elem_ty);
677            ctx.builder.ins().store(MemFlags::trusted(), value, addr, 0);
678        }
679        Ok(())
680    }
681
682    fn swap_vec_index(&mut self, ctx: &mut BuildContext, base: Value, left: (Value, Type), right: (Value, Type), elem_ty: &Type) -> Result<()> {
683        let left_addr = self.vec_index_addr(ctx, base, left, elem_ty)?;
684        let right_addr = self.vec_index_addr(ctx, base, right, elem_ty)?;
685        let mut offset = 0u32;
686        let width = elem_ty.storage_width();
687        while offset < width {
688            let remaining = width - offset;
689            let (ty, size) = if remaining >= 8 {
690                (types::I64, 8)
691            } else if remaining >= 4 {
692                (types::I32, 4)
693            } else if remaining >= 2 {
694                (types::I16, 2)
695            } else {
696                (types::I8, 1)
697            };
698            let left_value = ctx.builder.ins().load(ty, MemFlags::trusted(), left_addr, offset as i32);
699            let right_value = ctx.builder.ins().load(ty, MemFlags::trusted(), right_addr, offset as i32);
700            ctx.builder.ins().store(MemFlags::trusted(), left_value, right_addr, offset as i32);
701            ctx.builder.ins().store(MemFlags::trusted(), right_value, left_addr, offset as i32);
702            offset += size;
703        }
704        Ok(())
705    }
706
707    fn init_struct_from_dynamic(&mut self, ctx: &mut BuildContext, value: (Value, Type), ty: &Type) -> Result<Value> {
708        let Type::Struct { params: _, fields } = ty else {
709            return Err(anyhow!("不是结构体 {:?}", ty));
710        };
711        let base = self.struct_alloc(ctx, ty)?;
712        for (idx, (_, field_ty)) in fields.iter().enumerate() {
713            let idx_val = ctx.builder.ins().iconst(types::I64, idx as i64);
714            let item = self.call(ctx, self.get_method(&Type::Any, "get_idx")?, vec![value.0, idx_val])?;
715            self.store_struct_field(ctx, base, idx, field_ty, item, ty)?;
716        }
717        Ok(base)
718    }
719
720    fn init_struct_from_items(&mut self, ctx: &mut BuildContext, items: &[Expr], ty: &Type) -> Result<Value> {
721        let Type::Struct { params: _, fields } = ty else {
722            return Err(anyhow!("not a struct type: {:?}", ty));
723        };
724        let base = self.struct_alloc(ctx, ty)?;
725        for (idx, item) in items.iter().enumerate() {
726            let Some((_, field_ty)) = fields.get(idx) else {
727                return Err(anyhow!("struct initializer has too many fields (field index {} out of bounds, type has {} fields)", idx, fields.len()));
728            };
729            let value = self.eval(ctx, item)?.get(ctx).ok_or(anyhow!("struct field has no value"))?;
730            self.store_struct_field(ctx, base, idx, field_ty, value, ty)?;
731        }
732        Ok(base)
733    }
734
735    fn expr_assigned_var(expr: &Expr) -> Option<(u32, Type)> {
736        if let ExprKind::Binary { left, op, right } = &expr.kind
737            && op.is_assign()
738            && let ExprKind::Var(idx) = left.kind
739        {
740            return Some((idx, right.get_type()));
741        }
742        None
743    }
744
745    fn declare_assigned_vars(&mut self, ctx: &mut BuildContext, stmt: &Stmt) -> Result<()> {
746        match &stmt.kind {
747            StmtKind::Expr(expr, _) => {
748                if let Some((idx, ty)) = Self::expr_assigned_var(expr) {
749                    match ctx.get_var(idx).ok() {
750                        Some(LocalVar::Variable { .. }) | Some(LocalVar::Closure { .. }) => {}
751                        Some(LocalVar::Value { val, ty }) => {
752                            ctx.set_var(idx, LocalVar::Value { val, ty })?;
753                        }
754                        Some(LocalVar::None) | None => {
755                            let init = self.zero_value(ctx, &ty)?;
756                            ctx.set_var(idx, init.into())?;
757                        }
758                    }
759                }
760            }
761            StmtKind::Block(stmts) => {
762                for stmt in stmts {
763                    self.declare_assigned_vars(ctx, stmt)?;
764                }
765            }
766            StmtKind::If { then_body, else_body, .. } => {
767                self.declare_assigned_vars(ctx, then_body)?;
768                if let Some(else_body) = else_body {
769                    self.declare_assigned_vars(ctx, else_body)?;
770                }
771            }
772            StmtKind::While { body, .. } | StmtKind::Loop(body) => {
773                self.declare_assigned_vars(ctx, body)?;
774            }
775            StmtKind::For { body, .. } => {
776                self.declare_assigned_vars(ctx, body)?;
777            }
778            _ => {}
779        }
780        Ok(())
781    }
782
783    fn zero_value(&mut self, ctx: &mut BuildContext, ty: &Type) -> Result<(Value, Type)> {
784        if self.is_aggregate_ty(ty) {
785            Ok((self.struct_alloc(ctx, ty)?, ty.clone()))
786        } else if ty.is_f32() {
787            Ok((ctx.builder.ins().f32const(0.0), ty.clone()))
788        } else if ty.is_f64() {
789            Ok((ctx.builder.ins().f64const(0.0), ty.clone()))
790        } else {
791            Ok((ctx.builder.ins().iconst(crate::get_type(ty)?, 0), ty.clone()))
792        }
793    }
794
795    fn assign(&mut self, ctx: &mut BuildContext, left: &Expr, value: LocalVar) -> Result<(Value, Type)> {
796        if let ExprKind::Var(idx) = &left.kind {
797            if value.is_closure() {
798                ctx.set_var(*idx, value)?;
799                return self.get_null_value(ctx);
800            }
801            let value_ty = value.get_ty();
802            if let Some(ty) = ctx.get_var_ty(*idx) {
803                if self.is_aggregate_ty(&ty) {
804                    let dst = ctx.get_var(*idx)?.get(ctx).ok_or(anyhow!("aggregate variable has no value"))?.0;
805                    let src = value.get(ctx).ok_or(anyhow!("aggregate assignment has no value"))?;
806                    let src = self.convert(ctx, src, ty.clone())?;
807                    self.copy_vec_element(ctx, dst, src, &ty);
808                } else if value_ty != ty {
809                    if let Some(vt) = value.get(ctx) {
810                        let val = self.convert(ctx, vt, ty.clone())?;
811                        ctx.set_var(*idx, LocalVar::Value { val, ty })?;
812                    } else if ty.is_any() {
813                        let const_idx = self.compiler.get_const(Dynamic::Null);
814                        let (val, ty) = self.get_const_value(ctx, const_idx)?;
815                        ctx.set_var(*idx, LocalVar::Value { val, ty })?;
816                    } else {
817                        ctx.set_var(*idx, LocalVar::None)?;
818                    }
819                } else {
820                    ctx.set_var(*idx, value)?;
821                }
822            } else if self.is_aggregate_ty(&value_ty) {
823                let src = value.get(ctx).ok_or(anyhow!("aggregate initializer has no value"))?;
824                let dst = self.struct_alloc(ctx, &value_ty)?;
825                let src = self.convert(ctx, src, value_ty.clone())?;
826                self.copy_vec_element(ctx, dst, src, &value_ty);
827                ctx.set_var(*idx, LocalVar::Value { val: dst, ty: value_ty })?;
828            } else {
829                ctx.set_var(*idx, value)?;
830            }
831            let assigned = ctx.get_var(*idx)?;
832            if assigned.is_closure() {
833                return self.get_null_value(ctx);
834            }
835            let val = assigned.get(ctx).ok_or(anyhow!("assigned variable has no value"))?;
836            return Ok(val);
837        } else if left.is_idx() {
838            let value = match value {
839                LocalVar::Closure { id, captures } => self.callback_value(ctx, id, captures)?,
840                value => value,
841            };
842            let value = value.get(ctx).ok_or_else(|| anyhow!("idx assignment rhs has no value: left={:?}", left))?;
843            let (left, _, right) = left.clone().binary().unwrap();
844            let left = self.eval(ctx, &left)?.get(ctx).ok_or(anyhow!("未知局部变量 {:?}", left))?;
845            if let Type::Struct { params: _, fields } = &left.1 {
846                let idx = self.struct_field_index(&left.1, &right)?;
847                let field_ty = fields.get(idx).map(|(_, ty)| ty.clone()).ok_or_else(|| anyhow!("结构字段索引越界 {}", idx))?;
848                self.store_struct_field(ctx, left.0, idx, &field_ty, value.clone(), &left.1)?;
849                return Ok(value);
850            }
851            if let Some(elem_ty) = Self::vec_elem_ty(&left.1) {
852                let idx = if right.is_value() {
853                    let idx = right.clone().value()?.as_int().ok_or(anyhow!("Vec 索引必须是整数"))?;
854                    (ctx.builder.ins().iconst(types::I64, idx), Type::I64)
855                } else {
856                    self.eval(ctx, &right)?.get(ctx).ok_or(anyhow!("Vec 索引没有值"))?
857                };
858                self.store_vec_index(ctx, left.0, idx, &elem_ty, value.clone())?;
859                return Ok(value);
860            }
861            if let Some(elem_ty) = Self::array_elem_ty(&left.1) {
862                let idx = if right.is_value() {
863                    let idx = right.clone().value()?.as_int().ok_or(anyhow!("array index must be integer"))?;
864                    (ctx.builder.ins().iconst(types::I64, idx), Type::I64)
865                } else {
866                    self.eval(ctx, &right)?.get(ctx).ok_or(anyhow!("array index has no value"))?
867                };
868                self.store_array_index(ctx, left.0, idx, &elem_ty, value.clone())?;
869                return Ok(value);
870            }
871            if right.is_value() {
872                let right_value = right.clone().value()?;
873                if let Some(idx) = right_value.as_int() {
874                    let idx = ctx.builder.ins().iconst(types::I64, idx);
875                    if self.intrinsic_list_set_idx(ctx, left.clone(), (idx, Type::I64), value.clone())? {
876                        return Ok(value);
877                    }
878                    let f = self.get_method(&left.1, "set_idx")?;
879                    let args = self.adjust_args(ctx, vec![left, (idx, Type::I64), value.clone()], f.arg_tys()?)?;
880                    self.call_for_side_effect(ctx, f, args)?;
881                } else {
882                    let key = ctx.get_const(&right_value)?;
883                    let f = self.get_method(&left.1, "set_key")?;
884                    let args = self.adjust_args(ctx, vec![left, key, value.clone()], f.arg_tys()?)?;
885                    self.call_for_side_effect(ctx, f, args)?;
886                }
887            } else {
888                let right = self.eval(ctx, &right)?.get(ctx).ok_or_else(|| self.compile_error(ctx, right.span, "赋值右侧表达式无值"))?;
889                if right.1.is_any() || right.1.is_str() {
890                    let f = self.get_method(&left.1, "set_key")?;
891                    let args = self.adjust_args(ctx, vec![left, right, value.clone()], f.arg_tys()?)?;
892                    self.call_for_side_effect(ctx, f, args)?;
893                } else {
894                    if self.intrinsic_list_set_idx(ctx, left.clone(), right.clone(), value.clone())? {
895                        return Ok(value);
896                    }
897                    let f = self.get_method(&left.1, "set_idx")?;
898                    let args = self.adjust_args(ctx, vec![left, right, value.clone()], f.arg_tys()?)?;
899                    self.call_for_side_effect(ctx, f, args)?;
900                }
901            }
902            return Ok(value);
903        } else {
904            anyhow::bail!("赋值给不支持的目标: {:?} {:?}", left, value)
905        }
906    }
907
908    fn assignment_target_ty(&mut self, ctx: &mut BuildContext, left: &Expr) -> Option<Type> {
909        if let ExprKind::Var(idx) = &left.kind {
910            return ctx.get_var_ty(*idx).filter(|ty| !ty.is_any()).or_else(|| ctx.local_type_hint(*idx));
911        }
912        None
913    }
914
915    fn empty_typed_list(ty: &Type) -> Option<Dynamic> {
916        let Type::List(elem_ty) = ty else {
917            return None;
918        };
919        match elem_ty.as_ref() {
920            Type::Bool | Type::U8 => Some(Dynamic::list(Vec::new())),
921            Type::I8 => Some(Dynamic::VecI8(Default::default())),
922            Type::U16 => Some(Dynamic::VecU16(Default::default())),
923            Type::I16 => Some(Dynamic::VecI16(Default::default())),
924            Type::U32 => Some(Dynamic::VecU32(Default::default())),
925            Type::I32 => Some(Dynamic::VecI32(Default::default())),
926            Type::F32 => Some(Dynamic::VecF32(Default::default())),
927            Type::U64 => Some(Dynamic::VecU64(Vec::new())),
928            Type::I64 => Some(Dynamic::VecI64(Vec::new())),
929            Type::F64 => Some(Dynamic::VecF64(Vec::new())),
930            Type::Str => Some(Dynamic::list(Vec::new())),
931            _ => None,
932        }
933    }
934
935    fn list_push_shortcut(elem_ty: &Type) -> Option<(&'static str, Type)> {
936        match elem_ty {
937            Type::Bool => Some(("Any::push_bool", Type::Bool)),
938            Type::U8 => Some(("Any::push_u8", Type::U8)),
939            Type::I8 => Some(("Any::push_i8", Type::I8)),
940            Type::U16 => Some(("Any::push_u16", Type::U16)),
941            Type::I16 => Some(("Any::push_i16", Type::I16)),
942            Type::U32 => Some(("Any::push_u32", Type::U32)),
943            Type::I32 => Some(("Any::push_i32", Type::I32)),
944            Type::F32 => Some(("Any::push_f32", Type::F32)),
945            Type::U64 => Some(("Any::push_u64", Type::U64)),
946            Type::I64 => Some(("Any::push_i64", Type::I64)),
947            Type::F64 => Some(("Any::push_f64", Type::F64)),
948            Type::Str => Some(("Any::push_str", Type::Str)),
949            _ => None,
950        }
951    }
952
953    fn list_get_idx_shortcut(elem_ty: &Type) -> Option<(&'static str, Type, Type)> {
954        match elem_ty {
955            Type::Bool => Some(("Any::get_idx_bool_i64", Type::I64, Type::Bool)),
956            Type::U8 => Some(("Any::get_idx_u8_i64", Type::I64, Type::U8)),
957            Type::I8 => Some(("Any::get_idx_i8_i64", Type::I64, Type::I8)),
958            Type::U16 => Some(("Any::get_idx_u16_i64", Type::I64, Type::U16)),
959            Type::I16 => Some(("Any::get_idx_i16_i64", Type::I64, Type::I16)),
960            Type::U32 => Some(("Any::get_idx_u32", Type::U32, Type::U32)),
961            Type::I32 => Some(("Any::get_idx_i32", Type::I32, Type::I32)),
962            Type::F32 => Some(("Any::get_idx_f32", Type::F32, Type::F32)),
963            Type::U64 => Some(("Any::get_idx_u64", Type::U64, Type::U64)),
964            Type::I64 => Some(("Any::get_idx_i64", Type::I64, Type::I64)),
965            Type::F64 => Some(("Any::get_idx_f64", Type::F64, Type::F64)),
966            Type::Str => Some(("Any::get_idx_str", Type::Str, Type::Str)),
967            _ => None,
968        }
969    }
970
971    fn list_data_ptr_shortcut(elem_ty: &Type) -> Option<(&'static str, Type)> {
972        match elem_ty {
973            Type::U64 => Some(("Any::data_ptr_u64", Type::U64)),
974            Type::I64 => Some(("Any::data_ptr_i64", Type::I64)),
975            Type::F64 => Some(("Any::data_ptr_f64", Type::F64)),
976            _ => None,
977        }
978    }
979
980    fn list_set_idx_shortcut(elem_ty: &Type) -> Option<(&'static str, Type)> {
981        match elem_ty {
982            Type::Bool => Some(("Any::set_idx_bool", Type::Bool)),
983            Type::U8 => Some(("Any::set_idx_u8", Type::U8)),
984            Type::I8 => Some(("Any::set_idx_i8", Type::I8)),
985            Type::U16 => Some(("Any::set_idx_u16", Type::U16)),
986            Type::I16 => Some(("Any::set_idx_i16", Type::I16)),
987            Type::U32 => Some(("Any::set_idx_u32", Type::U32)),
988            Type::I32 => Some(("Any::set_idx_i32", Type::I32)),
989            Type::F32 => Some(("Any::set_idx_f32", Type::F32)),
990            Type::U64 => Some(("Any::set_idx_u64", Type::U64)),
991            Type::I64 => Some(("Any::set_idx_i64", Type::I64)),
992            Type::F64 => Some(("Any::set_idx_f64", Type::F64)),
993            Type::Str => Some(("Any::set_idx_str", Type::Str)),
994            _ => None,
995        }
996    }
997
998    fn intrinsic_list_get_idx(&mut self, ctx: &mut BuildContext, list: (Value, Type), idx: (Value, Type)) -> Result<Option<(Value, Type)>> {
999        let Type::List(elem_ty) = &list.1 else {
1000            return Ok(None);
1001        };
1002        let Some((fn_name, abi_ret_ty, value_ty)) = Self::list_get_idx_shortcut(elem_ty) else {
1003            return Ok(None);
1004        };
1005        let idx = self.convert(ctx, idx, Type::I64)?;
1006        let get_idx_fn = self.get_native_fn_cached(fn_name, &[Type::Any, Type::I64])?;
1007        let value = self.call(ctx, get_idx_fn, vec![list.0, idx])?;
1008        if value_ty.is_bool() {
1009            let is_true = ctx.builder.ins().icmp_imm(IntCC::NotEqual, value.0, 0);
1010            let zero = ctx.builder.ins().iconst(types::I8, 0);
1011            let one = ctx.builder.ins().iconst(types::I8, 1);
1012            return Ok(Some((ctx.builder.ins().select(is_true, one, zero), Type::Bool)));
1013        }
1014        if value.1 != value_ty {
1015            let narrowed = self.convert(ctx, (value.0, abi_ret_ty), value_ty.clone())?;
1016            return Ok(Some((narrowed, value_ty)));
1017        }
1018        Ok(Some(value))
1019    }
1020
1021    fn intrinsic_list_fast_path_get_idx(&mut self, ctx: &mut BuildContext, var_idx: u32, list: (Value, Type), idx: (Value, Type)) -> Result<Option<(Value, Type)>> {
1022        let Some(fast_path) = ctx.list_fast_path(var_idx) else {
1023            return Ok(None);
1024        };
1025        let Type::List(elem_ty) = &list.1 else {
1026            return Ok(None);
1027        };
1028        if elem_ty.as_ref() != &fast_path.elem_ty {
1029            return Ok(None);
1030        }
1031        let idx = self.convert(ctx, idx, Type::I64)?;
1032        let offset = ctx.builder.ins().imul_imm(idx, fast_path.elem_ty.width() as i64);
1033        let addr = ctx.builder.ins().iadd(fast_path.data, offset);
1034        let value = ctx.builder.ins().load(get_type(&fast_path.elem_ty)?, MemFlags::trusted(), addr, 0);
1035        Ok(Some((value, fast_path.elem_ty)))
1036    }
1037
1038    fn intrinsic_list_set_idx(&mut self, ctx: &mut BuildContext, list: (Value, Type), idx: (Value, Type), value: (Value, Type)) -> Result<bool> {
1039        let Type::List(elem_ty) = &list.1 else {
1040            return Ok(false);
1041        };
1042        let Some((fn_name, value_ty)) = Self::list_set_idx_shortcut(elem_ty) else {
1043            return Ok(false);
1044        };
1045        let idx = self.convert(ctx, idx, Type::I64)?;
1046        let stored = self.convert(ctx, value, value_ty.clone())?;
1047        let set_idx_fn = self.get_native_fn_cached(fn_name, &[Type::Any, Type::I64, value_ty])?;
1048        self.call_for_side_effect(ctx, set_idx_fn, vec![list.0, idx, stored])?;
1049        Ok(true)
1050    }
1051
1052    fn try_intrinsic_collection_call(&mut self, ctx: &mut BuildContext, fn_name: &str, args: &[(Value, Type)]) -> Result<Option<LocalVar>> {
1053        if let [list, value] = args
1054            && fn_name == "Any::push"
1055            && let Type::List(elem_ty) = &list.1
1056            && let Some((fn_name, value_ty)) = Self::list_push_shortcut(elem_ty)
1057        {
1058            let value = self.convert(ctx, (value.0, value.1.clone()), value_ty.clone())?;
1059            let push_fn = self.get_native_fn_cached(fn_name, &[Type::Any, value_ty])?;
1060            self.call_for_side_effect(ctx, push_fn, vec![list.0, value])?;
1061            return Ok(Some(LocalVar::None));
1062        }
1063
1064        if let [list, idx] = args
1065            && fn_name == "Any::get_idx"
1066            && let Some(value) = self.intrinsic_list_get_idx(ctx, (list.0, list.1.clone()), (idx.0, idx.1.clone()))?
1067        {
1068            return Ok(Some(value.into()));
1069        }
1070
1071        Ok(None)
1072    }
1073
1074    fn expr_is_empty_list(&self, expr: &Expr) -> bool {
1075        match &expr.kind {
1076            ExprKind::Value(value) => value.is_list() && value.len() == 0,
1077            ExprKind::Const(idx) => self.compiler.sym_tab.consts.get_index(*idx).is_some_and(|(_, value)| value.is_list() && value.len() == 0),
1078            ExprKind::Typed { value, .. } => self.expr_is_empty_list(value),
1079            _ => false,
1080        }
1081    }
1082
1083    fn expr_uses_var(expr: &Expr, var_idx: u32) -> bool {
1084        match &expr.kind {
1085            ExprKind::Var(idx) => *idx == var_idx,
1086            ExprKind::Typed { value, .. } | ExprKind::Unary { value, .. } | ExprKind::Generic { obj: value, .. } => Self::expr_uses_var(value, var_idx),
1087            ExprKind::Stmt(stmt) => Self::stmt_uses_var(stmt, var_idx),
1088            ExprKind::Binary { left, right, .. } | ExprKind::Range { start: left, stop: right, .. } => Self::expr_uses_var(left, var_idx) || Self::expr_uses_var(right, var_idx),
1089            ExprKind::Tuple(items) | ExprKind::List(items) => items.iter().any(|item| Self::expr_uses_var(item, var_idx)),
1090            ExprKind::Repeat { value, .. } => Self::expr_uses_var(value, var_idx),
1091            ExprKind::Dict(items) => items.iter().any(|(_, value)| Self::expr_uses_var(value, var_idx)),
1092            ExprKind::Id(_, obj) => obj.as_deref().is_some_and(|obj| Self::expr_uses_var(obj, var_idx)),
1093            ExprKind::Call { obj, params } => Self::expr_uses_var(obj, var_idx) || params.iter().any(|param| Self::expr_uses_var(param, var_idx)),
1094            ExprKind::Closure { body, .. } => Self::stmt_uses_var(body, var_idx),
1095            _ => false,
1096        }
1097    }
1098
1099    fn stmt_uses_var(stmt: &Stmt, var_idx: u32) -> bool {
1100        match &stmt.kind {
1101            StmtKind::Let { value, .. } => Self::stmt_uses_var(value, var_idx),
1102            StmtKind::Expr(expr, _) | StmtKind::Return(Some(expr)) => Self::expr_uses_var(expr, var_idx),
1103            StmtKind::Block(stmts) => stmts.iter().any(|stmt| Self::stmt_uses_var(stmt, var_idx)),
1104            StmtKind::While { cond, body } => Self::expr_uses_var(cond, var_idx) || Self::stmt_uses_var(body, var_idx),
1105            StmtKind::Loop(body) => Self::stmt_uses_var(body, var_idx),
1106            StmtKind::For { range, body, .. } => Self::expr_uses_var(range, var_idx) || Self::stmt_uses_var(body, var_idx),
1107            StmtKind::If { cond, then_body, else_body } => Self::expr_uses_var(cond, var_idx) || Self::stmt_uses_var(then_body, var_idx) || else_body.as_deref().is_some_and(|body| Self::stmt_uses_var(body, var_idx)),
1108            StmtKind::Fn { body, .. } | StmtKind::Impl { body, .. } => Self::stmt_uses_var(body, var_idx),
1109            StmtKind::Static { value, .. } => value.as_ref().is_some_and(|value| Self::expr_uses_var(value, var_idx)),
1110            StmtKind::Const { value, .. } => Self::expr_uses_var(value, var_idx),
1111            _ => false,
1112        }
1113    }
1114
1115    fn expr_reads_list_index(expr: &Expr, var_idx: u32) -> bool {
1116        match &expr.kind {
1117            ExprKind::Binary { left, op: BinaryOp::Idx, right } if matches!(left.kind, ExprKind::Var(idx) if idx == var_idx) => !Self::expr_uses_var(right, var_idx),
1118            ExprKind::Typed { value, .. } | ExprKind::Unary { value, .. } | ExprKind::Generic { obj: value, .. } => Self::expr_reads_list_index(value, var_idx),
1119            ExprKind::Stmt(stmt) => Self::stmt_reads_list_index(stmt, var_idx),
1120            ExprKind::Binary { left, right, .. } | ExprKind::Range { start: left, stop: right, .. } => Self::expr_reads_list_index(left, var_idx) || Self::expr_reads_list_index(right, var_idx),
1121            ExprKind::Tuple(items) | ExprKind::List(items) => items.iter().any(|item| Self::expr_reads_list_index(item, var_idx)),
1122            ExprKind::Repeat { value, .. } => Self::expr_reads_list_index(value, var_idx),
1123            ExprKind::Dict(items) => items.iter().any(|(_, value)| Self::expr_reads_list_index(value, var_idx)),
1124            ExprKind::Id(_, obj) => obj.as_deref().is_some_and(|obj| Self::expr_reads_list_index(obj, var_idx)),
1125            ExprKind::Call { obj, params } => Self::expr_reads_list_index(obj, var_idx) || params.iter().any(|param| Self::expr_reads_list_index(param, var_idx)),
1126            _ => false,
1127        }
1128    }
1129
1130    fn stmt_reads_list_index(stmt: &Stmt, var_idx: u32) -> bool {
1131        match &stmt.kind {
1132            StmtKind::Let { value, .. } => Self::stmt_reads_list_index(value, var_idx),
1133            StmtKind::Expr(expr, _) | StmtKind::Return(Some(expr)) => Self::expr_reads_list_index(expr, var_idx),
1134            StmtKind::Block(stmts) => stmts.iter().any(|stmt| Self::stmt_reads_list_index(stmt, var_idx)),
1135            StmtKind::If { cond, then_body, else_body } => {
1136                Self::expr_reads_list_index(cond, var_idx) || Self::stmt_reads_list_index(then_body, var_idx) || else_body.as_deref().is_some_and(|body| Self::stmt_reads_list_index(body, var_idx))
1137            }
1138            _ => false,
1139        }
1140    }
1141
1142    fn expr_allows_list_fast_path(expr: &Expr, var_idx: u32) -> bool {
1143        match &expr.kind {
1144            ExprKind::Var(idx) => *idx != var_idx,
1145            ExprKind::Binary { left, op, right } if op.is_assign() => !Self::expr_uses_var(left, var_idx) && Self::expr_allows_list_fast_path(right, var_idx),
1146            ExprKind::Binary { left, op: BinaryOp::Idx, right } if matches!(left.kind, ExprKind::Var(idx) if idx == var_idx) => !Self::expr_uses_var(right, var_idx),
1147            ExprKind::Typed { value, .. } | ExprKind::Unary { value, .. } | ExprKind::Generic { obj: value, .. } => Self::expr_allows_list_fast_path(value, var_idx),
1148            ExprKind::Stmt(stmt) => Self::stmt_allows_list_fast_path(stmt, var_idx),
1149            ExprKind::Binary { left, right, .. } | ExprKind::Range { start: left, stop: right, .. } => Self::expr_allows_list_fast_path(left, var_idx) && Self::expr_allows_list_fast_path(right, var_idx),
1150            ExprKind::Tuple(items) | ExprKind::List(items) => items.iter().all(|item| Self::expr_allows_list_fast_path(item, var_idx)),
1151            ExprKind::Repeat { value, .. } => Self::expr_allows_list_fast_path(value, var_idx),
1152            ExprKind::Dict(items) => items.iter().all(|(_, value)| Self::expr_allows_list_fast_path(value, var_idx)),
1153            ExprKind::Id(_, obj) => obj.as_deref().map(|obj| Self::expr_allows_list_fast_path(obj, var_idx)).unwrap_or(true),
1154            ExprKind::Call { obj, params } => Self::expr_allows_list_fast_path(obj, var_idx) && params.iter().all(|param| Self::expr_allows_list_fast_path(param, var_idx)),
1155            ExprKind::Closure { .. } => false,
1156            _ => true,
1157        }
1158    }
1159
1160    fn stmt_allows_list_fast_path(stmt: &Stmt, var_idx: u32) -> bool {
1161        match &stmt.kind {
1162            StmtKind::Let { value, .. } => Self::stmt_allows_list_fast_path(value, var_idx),
1163            StmtKind::Expr(expr, _) | StmtKind::Return(Some(expr)) => Self::expr_allows_list_fast_path(expr, var_idx),
1164            StmtKind::Block(stmts) => stmts.iter().all(|stmt| Self::stmt_allows_list_fast_path(stmt, var_idx)),
1165            StmtKind::If { cond, then_body, else_body } => {
1166                Self::expr_allows_list_fast_path(cond, var_idx) && Self::stmt_allows_list_fast_path(then_body, var_idx) && else_body.as_deref().map(|body| Self::stmt_allows_list_fast_path(body, var_idx)).unwrap_or(true)
1167            }
1168            _ => false,
1169        }
1170    }
1171
1172    fn push_loop_list_fast_paths(&mut self, ctx: &mut BuildContext, body: &Stmt) -> Result<usize> {
1173        let saved_len = ctx.list_fast_path_len();
1174        for var_idx in 0..ctx.vars.len() as u32 {
1175            if !Self::stmt_reads_list_index(body, var_idx) || !Self::stmt_allows_list_fast_path(body, var_idx) {
1176                continue;
1177            }
1178            let Some(Type::List(elem_ty)) = ctx.local_type_hint(var_idx) else {
1179                continue;
1180            };
1181            let Some((ptr_fn_name, elem_ty)) = Self::list_data_ptr_shortcut(elem_ty.as_ref()) else {
1182                continue;
1183            };
1184            let Some(list) = ctx.get_var(var_idx)?.get(ctx) else {
1185                continue;
1186            };
1187            let data_ptr_fn = self.get_native_fn_cached(ptr_fn_name, &[Type::Any])?;
1188            let data = self.call(ctx, data_ptr_fn, vec![list.0])?;
1189            ctx.push_list_fast_path(ListFastPath { var_idx, elem_ty, data: data.0 });
1190        }
1191        Ok(saved_len)
1192    }
1193
1194    fn closure_value(&self, ctx: &mut BuildContext, id: u32) -> Result<LocalVar> {
1195        let (name, symbol) = self.compiler.sym_tab.symbols.get_symbol(id)?;
1196        let captures = match symbol {
1197            Symbol::Fn { cap, .. } => cap
1198                .vars
1199                .iter()
1200                .map(|idx| {
1201                    let var = ctx.get_var(*idx as u32).map_err(|err| anyhow!("闭包 {} 捕获变量失败: idx={}, cap.vars={:?}, {}", name, idx, cap.vars, err))?;
1202                    var.get(ctx).ok_or_else(|| anyhow!("闭包 {} 捕获变量没有值: idx={}, cap.vars={:?}", name, idx, cap.vars))
1203                })
1204                .collect::<Result<Vec<_>>>()?,
1205            _ => Vec::new(),
1206        };
1207        Ok(LocalVar::Closure { id, captures })
1208    }
1209
1210    fn is_spawn_fn_name(name: &str) -> bool {
1211        name == "spawn" || name == "std::spawn"
1212    }
1213
1214    fn spawn_arg_pack_len(&self, expr: &Expr) -> Option<usize> {
1215        match &expr.kind {
1216            ExprKind::Tuple(items) | ExprKind::List(items) => Some(items.len()),
1217            ExprKind::Value(value) => value.is_list().then(|| value.len()),
1218            ExprKind::Const(idx) => self.compiler.sym_tab.consts.get_index(*idx).and_then(|(_, value)| value.is_list().then(|| value.len())),
1219            ExprKind::Typed { value, .. } => self.spawn_arg_pack_len(value),
1220            _ => None,
1221        }
1222    }
1223
1224    fn eval_spawn_arg_pack(&mut self, ctx: &mut BuildContext, expr: &Expr) -> Result<(Value, Type)> {
1225        let (ExprKind::Tuple(items) | ExprKind::List(items)) = &expr.kind else {
1226            return self.eval(ctx, expr)?.get(ctx).ok_or_else(|| anyhow!("spawn closure args expression has no value"));
1227        };
1228        if items.is_empty() {
1229            let idx = self.compiler.get_const(Dynamic::Null);
1230            return self.get_const_value(ctx, idx);
1231        }
1232        let values = items.iter().map(|item| self.eval(ctx, item)?.get(ctx).ok_or_else(|| anyhow!("spawn closure arg has no value: {:?}", item))).collect::<Result<Vec<_>>>()?;
1233        self.dynamic_list_from_values(ctx, values)
1234    }
1235
1236    fn dynamic_list_from_values(&mut self, ctx: &mut BuildContext, values: Vec<(Value, Type)>) -> Result<(Value, Type)> {
1237        let idx = self.compiler.get_const(Dynamic::list(vec![Dynamic::Null; values.len()]));
1238        let (list, _) = self.get_const_value(ctx, idx)?;
1239        for (idx, value) in values.into_iter().enumerate() {
1240            let value = self.convert(ctx, value, Type::Any)?;
1241            let idx = ctx.builder.ins().iconst(types::I64, idx as i64);
1242            let set_idx = self.get_fn(self.get_id("Any::set_idx")?, &[Type::Any, Type::I64, Type::Any])?;
1243            self.call_for_side_effect(ctx, set_idx, vec![list, idx, value])?;
1244        }
1245        Ok((list, Type::Any))
1246    }
1247
1248    fn callback_value(&mut self, ctx: &mut BuildContext, id: u32, captures: Vec<(Value, Type)>) -> Result<LocalVar> {
1249        let explicit_arg_len = match self.compiler.sym_tab.symbols.get_symbol(id)?.1 {
1250            Symbol::Fn { ty: Type::Fn { tys, .. }, .. } => tys.len(),
1251            _ => 0,
1252        };
1253        if explicit_arg_len > 16 {
1254            return Err(anyhow!("native callback closure supports at most 16 explicit args"));
1255        }
1256        if explicit_arg_len + captures.len() > 24 {
1257            return Err(anyhow!("native callback closure supports at most 24 args including captures, got {}", explicit_arg_len + captures.len()));
1258        }
1259        let explicit_arg_tys = vec![Type::Any; explicit_arg_len];
1260        let capture_tys = vec![Type::Any; captures.len()];
1261        let fn_info = self.gen_fn_with_capture_tys(Some(ctx), id, &explicit_arg_tys, &[], Some(&capture_tys))?;
1262        let FnInfo::Call { fn_id, ret, .. } = fn_info else {
1263            return Err(anyhow!("callback target must be compiled function"));
1264        };
1265        let captures = if captures.is_empty() {
1266            let idx = self.compiler.get_const(Dynamic::Null);
1267            self.get_const_value(ctx, idx)?
1268        } else {
1269            self.dynamic_list_from_values(ctx, captures)?
1270        };
1271        let fn_ref = self.get_fn_ref(ctx, fn_id);
1272        let fn_addr = ctx.builder.ins().func_addr(ptr_type(), fn_ref);
1273        let ret_ty = Self::type_ptr_const(ctx, &ret);
1274        let explicit_arg_len = ctx.builder.ins().iconst(types::I64, explicit_arg_len as i64);
1275        let callback_new = self.builtin_fns.get_or_err(BuiltinFn::CallbackNew)?;
1276        let callback_new_ref = self.get_fn_ref(ctx, callback_new);
1277        let call_inst = ctx.builder.ins().call(callback_new_ref, &[fn_addr, ret_ty, explicit_arg_len, captures.0]);
1278        Ok((ctx.builder.inst_results(call_inst)[0], Type::Any).into())
1279    }
1280
1281    fn call_dynamic_callback(&mut self, ctx: &mut BuildContext, callback: (Value, Type), params: &Vec<Expr>) -> Result<LocalVar> {
1282        if !callback.1.is_any() && !callback.1.is_fn() {
1283            anyhow::bail!("call target is not a callback: {:?}", callback.1);
1284        }
1285        let mut args = Vec::with_capacity(params.len());
1286        for param in params {
1287            let value = self.eval(ctx, param)?;
1288            let value = match value {
1289                LocalVar::Closure { id, captures } => self.callback_value(ctx, id, captures)?.get(ctx).ok_or_else(|| anyhow!("callback 参数没有值: {:?}", param))?,
1290                value => value.get(ctx).ok_or_else(|| anyhow!("callback 参数表达式没有值: {:?}", param))?,
1291            };
1292            args.push(value);
1293        }
1294        let args = self.dynamic_list_from_values(ctx, args)?;
1295        let callback_call = self.builtin_fns.get_or_err(BuiltinFn::CallbackCall)?;
1296        let callback_call_ref = self.get_fn_ref(ctx, callback_call);
1297        let call_inst = ctx.builder.ins().call(callback_call_ref, &[callback.0, args.0]);
1298        Ok((ctx.builder.inst_results(call_inst)[0], Type::Any).into())
1299    }
1300
1301    fn spawn_closure(&mut self, ctx: &mut BuildContext, id: u32, captures: Vec<(Value, Type)>, args_expr: &Expr) -> Result<LocalVar> {
1302        if !captures.is_empty() {
1303            return Err(anyhow!("spawn closure does not support captures yet"));
1304        }
1305        let arg_len = self.spawn_arg_pack_len(args_expr).ok_or_else(|| anyhow!("spawn closure args must be a tuple argument pack"))?;
1306        if arg_len > 16 {
1307            return Err(anyhow!("spawn supports at most 16 args, got {}", arg_len));
1308        }
1309        let arg_tys = vec![Type::Any; arg_len];
1310        let fn_info = self.gen_fn_with_params(Some(ctx), id, &arg_tys, &[])?;
1311        let FnInfo::Call { fn_id, ret, .. } = fn_info else {
1312            return Err(anyhow!("spawn closure target must be compiled function"));
1313        };
1314        let args = self.eval_spawn_arg_pack(ctx, args_expr)?;
1315        let args = self.convert(ctx, args, Type::Any)?;
1316        let fn_ref = self.get_fn_ref(ctx, fn_id);
1317        let fn_addr = ctx.builder.ins().func_addr(ptr_type(), fn_ref);
1318        let ret_ty = Self::type_ptr_const(ctx, &ret);
1319        let spawn_ptr = self.builtin_fns.get_or_err(BuiltinFn::SpawnPtr)?;
1320        let spawn_ref = self.get_fn_ref(ctx, spawn_ptr);
1321        let call_inst = ctx.builder.ins().call(spawn_ref, &[fn_addr, ret_ty, args]);
1322        Ok((ctx.builder.inst_results(call_inst)[0], Type::Bool).into())
1323    }
1324
1325    fn inline_call_obj_weight(&self, obj: &Expr) -> Option<usize> {
1326        match &obj.kind {
1327            ExprKind::Id(_, None) | ExprKind::AssocId { .. } => Some(0),
1328            ExprKind::Id(_, Some(receiver)) => self.inline_expr_weight(receiver),
1329            _ => self.inline_expr_weight(obj),
1330        }
1331    }
1332
1333    fn inline_expr_weight(&self, expr: &Expr) -> Option<usize> {
1334        match &expr.kind {
1335            ExprKind::Typed { value, .. } | ExprKind::Unary { value, .. } => self.inline_expr_weight(value)?.checked_add(1),
1336            ExprKind::Binary { left, right, .. } => {
1337                let weight = 1usize.checked_add(self.inline_expr_weight(left)?)?;
1338                weight.checked_add(self.inline_expr_weight(right)?)
1339            }
1340            ExprKind::Generic { obj, .. } => self.inline_expr_weight(obj)?.checked_add(1),
1341            ExprKind::Tuple(items) | ExprKind::List(items) => self.inline_expr_items_weight(items),
1342            ExprKind::Repeat { value, .. } => self.inline_expr_weight(value)?.checked_add(1),
1343            ExprKind::Dict(items) => {
1344                let mut weight = 1usize;
1345                for (_, value) in items {
1346                    weight = weight.checked_add(self.inline_expr_weight(value)?)?;
1347                }
1348                Some(weight)
1349            }
1350            ExprKind::Range { start, stop, .. } => {
1351                let weight = 1usize.checked_add(self.inline_expr_weight(start)?)?;
1352                weight.checked_add(self.inline_expr_weight(stop)?)
1353            }
1354            ExprKind::Call { obj, params } => {
1355                let mut weight = 1usize.checked_add(self.inline_call_obj_weight(obj)?)?;
1356                for param in params {
1357                    weight = weight.checked_add(self.inline_expr_weight(param)?)?;
1358                }
1359                Some(weight)
1360            }
1361            ExprKind::Stmt(_) | ExprKind::Closure { .. } | ExprKind::Id(_, _) | ExprKind::AssocId { .. } => None,
1362            _ => Some(1),
1363        }
1364    }
1365
1366    fn inline_expr_items_weight<'a>(&self, items: impl IntoIterator<Item = &'a Expr>) -> Option<usize> {
1367        let mut weight = 1usize;
1368        for item in items {
1369            weight = weight.checked_add(self.inline_expr_weight(item)?)?;
1370        }
1371        Some(weight)
1372    }
1373
1374    fn inline_stmt_weight(&self, stmt: &Stmt) -> Option<usize> {
1375        match &stmt.kind {
1376            StmtKind::Expr(expr, _) | StmtKind::Return(Some(expr)) => self.inline_expr_weight(expr)?.checked_add(1),
1377            StmtKind::Block(stmts) => {
1378                let mut weight = 1usize;
1379                for stmt in stmts {
1380                    weight = weight.checked_add(self.inline_stmt_weight(stmt)?)?;
1381                }
1382                Some(weight)
1383            }
1384            StmtKind::If { cond, then_body, else_body } => {
1385                let mut weight = 1usize.checked_add(self.inline_expr_weight(cond)?)?;
1386                weight = weight.checked_add(self.inline_stmt_weight(then_body)?)?;
1387                if let Some(else_body) = else_body {
1388                    weight = weight.checked_add(self.inline_stmt_weight(else_body)?)?;
1389                }
1390                Some(weight)
1391            }
1392            StmtKind::While { body, .. } | StmtKind::Loop(body) | StmtKind::For { body, .. } => {
1393                if Self::inline_stmt_contains_return(body) {
1394                    None
1395                } else {
1396                    self.inline_stmt_weight(body)?.checked_add(16)
1397                }
1398            }
1399            _ => None,
1400        }
1401    }
1402
1403    fn inline_stmt_contains_return(stmt: &Stmt) -> bool {
1404        match &stmt.kind {
1405            StmtKind::Return(_) => true,
1406            StmtKind::Block(stmts) => stmts.iter().any(Self::inline_stmt_contains_return),
1407            StmtKind::If { then_body, else_body, .. } => Self::inline_stmt_contains_return(then_body) || else_body.as_deref().is_some_and(Self::inline_stmt_contains_return),
1408            StmtKind::While { body, .. } | StmtKind::Loop(body) | StmtKind::For { body, .. } => Self::inline_stmt_contains_return(body),
1409            _ => false,
1410        }
1411    }
1412
1413    fn inline_stmt_returns_value(stmt: &Stmt) -> bool {
1414        match &stmt.kind {
1415            StmtKind::Return(Some(_)) => true,
1416            StmtKind::Expr(_, close) => !*close,
1417            StmtKind::Block(stmts) => {
1418                for stmt in stmts {
1419                    if Self::inline_stmt_returns_value(stmt) {
1420                        return true;
1421                    }
1422                }
1423                false
1424            }
1425            StmtKind::If { then_body, else_body: Some(else_body), .. } => Self::inline_stmt_returns_value(then_body) && Self::inline_stmt_returns_value(else_body),
1426            _ => false,
1427        }
1428    }
1429
1430    fn inline_return_types(stmt: &Stmt, out: &mut Vec<Type>) {
1431        match &stmt.kind {
1432            StmtKind::Return(Some(expr)) => out.push(expr.get_type()),
1433            StmtKind::Expr(expr, close) if !*close => out.push(expr.get_type()),
1434            StmtKind::Block(stmts) => stmts.iter().for_each(|stmt| Self::inline_return_types(stmt, out)),
1435            StmtKind::If { then_body, else_body, .. } => {
1436                Self::inline_return_types(then_body, out);
1437                if let Some(else_body) = else_body {
1438                    Self::inline_return_types(else_body, out);
1439                }
1440            }
1441            _ => {}
1442        }
1443    }
1444
1445    fn inline_return_ty(fn_name: &str, ret_ty: &Type, body: &Stmt) -> Type {
1446        if !ret_ty.is_any() || !fn_name.starts_with("__closure_") {
1447            return ret_ty.clone();
1448        }
1449        let mut return_tys = Vec::new();
1450        Self::inline_return_types(body, &mut return_tys);
1451        let Some(first) = return_tys.first() else {
1452            return ret_ty.clone();
1453        };
1454        if first.is_any() || return_tys.iter().any(|ty| ty != first) { ret_ty.clone() } else { first.clone() }
1455    }
1456
1457    fn gen_inline_return(&mut self, ctx: &mut BuildContext, ret_ty: &Type, exit_block: Block, value: Option<&Expr>) -> Result<()> {
1458        let value = value.ok_or_else(|| anyhow!("inline non-void function returned without value"))?;
1459        let value = self.eval(ctx, value)?.get(ctx).ok_or_else(|| anyhow!("inline return expression has no value: {:?}", value))?;
1460        let value = if value.1 != *ret_ty { self.convert(ctx, value, ret_ty.clone())? } else { value.0 };
1461        ctx.builder.ins().jump(exit_block, &[cranelift::codegen::ir::BlockArg::Value(value)]);
1462        Ok(())
1463    }
1464
1465    fn gen_inline_stmt(&mut self, ctx: &mut BuildContext, stmt: &Stmt, ret_ty: &Type, exit_block: Block) -> Result<bool> {
1466        match &stmt.kind {
1467            StmtKind::Expr(expr, close) => {
1468                if *close {
1469                    let _ = self.eval(ctx, expr)?;
1470                    Ok(false)
1471                } else {
1472                    self.gen_inline_return(ctx, ret_ty, exit_block, Some(expr))?;
1473                    Ok(true)
1474                }
1475            }
1476            StmtKind::Return(expr) => {
1477                self.gen_inline_return(ctx, ret_ty, exit_block, expr.as_ref())?;
1478                Ok(true)
1479            }
1480            StmtKind::Block(stmts) => {
1481                for stmt in stmts {
1482                    if self.gen_inline_stmt(ctx, stmt, ret_ty, exit_block)? {
1483                        return Ok(true);
1484                    }
1485                }
1486                Ok(false)
1487            }
1488            StmtKind::If { cond, then_body, else_body } => {
1489                self.declare_assigned_vars(ctx, then_body)?;
1490                if let Some(else_body) = else_body {
1491                    self.declare_assigned_vars(ctx, else_body)?;
1492                }
1493                let then_block = ctx.builder.create_block();
1494                let cond = self.eval(ctx, cond)?.get(ctx).ok_or(anyhow!("未知的条件 {:?}", cond))?;
1495                let cond = self.bool_value(ctx, cond)?;
1496                let mut end_block = None;
1497                if let Some(else_body) = else_body {
1498                    let else_block = ctx.builder.create_block();
1499                    ctx.builder.ins().brif(cond, then_block, &[], else_block, &[]);
1500                    ctx.builder.switch_to_block(then_block);
1501                    if !self.gen_inline_stmt(ctx, then_body, ret_ty, exit_block)? {
1502                        let block = ctx.builder.create_block();
1503                        ctx.builder.ins().jump(block, &[]);
1504                        end_block = Some(block);
1505                    }
1506                    ctx.builder.switch_to_block(else_block);
1507                    if !self.gen_inline_stmt(ctx, else_body, ret_ty, exit_block)? {
1508                        if end_block.is_none() {
1509                            end_block = Some(ctx.builder.create_block());
1510                        }
1511                        ctx.builder.ins().jump(end_block.unwrap(), &[]);
1512                    }
1513                    ctx.builder.seal_block(else_block);
1514                } else {
1515                    let block = ctx.builder.create_block();
1516                    ctx.builder.ins().brif(cond, then_block, &[], block, &[]);
1517                    end_block = Some(block);
1518                    ctx.builder.switch_to_block(then_block);
1519                    if !self.gen_inline_stmt(ctx, then_body, ret_ty, exit_block)? {
1520                        ctx.builder.ins().jump(end_block.unwrap(), &[]);
1521                    }
1522                }
1523                if let Some(block) = end_block {
1524                    ctx.builder.switch_to_block(block);
1525                }
1526                ctx.builder.seal_block(then_block);
1527                Ok(end_block.is_none())
1528            }
1529            _ => self.gen_stmt(ctx, stmt, None, None),
1530        }
1531    }
1532
1533    fn try_inline_call(&mut self, ctx: &mut BuildContext, id: u32, generic_args: &[Type], args: &[(Value, Type)], capture_len: usize) -> Result<Option<LocalVar>> {
1534        if self.inline_depth >= 4 || self.inline_stack.contains(&id) || !generic_args.is_empty() || capture_len != 0 {
1535            return Ok(None);
1536        }
1537        let (fn_name, symbol) = self.compiler.sym_tab.symbols.get_symbol(id).map(|(name, symbol)| (name.clone(), symbol.clone()))?;
1538        let Symbol::Fn { ty: Type::Fn { tys, .. }, generic_params, cap, body, .. } = symbol else {
1539            return Ok(None);
1540        };
1541        if !generic_params.is_empty() || !cap.vars.is_empty() || tys.len() != args.len() {
1542            return Ok(None);
1543        }
1544        let body = body.as_ref().clone();
1545        if !Self::inline_stmt_returns_value(&body) {
1546            return Ok(None);
1547        };
1548        let Some(weight) = self.inline_stmt_weight(&body) else {
1549            return Ok(None);
1550        };
1551        if weight > 64 || weight > self.inline_budget {
1552            return Ok(None);
1553        }
1554
1555        let arg_tys: Vec<Type> = args.iter().map(|(_, ty)| ty.clone()).collect();
1556        let ret_ty = self.compiler.infer_fn_with_params(id, &arg_tys, generic_args)?;
1557        if ret_ty.is_void() {
1558            return Ok(None);
1559        }
1560        let inline_ret_ty = Self::inline_return_ty(fn_name.as_str(), &ret_ty, &body);
1561        let local_type_hints = self.compiler.inferred_local_type_hints(id, generic_args, &arg_tys);
1562        let mut inline_vars = Vec::with_capacity(args.len());
1563        for (value, ty) in args.iter().cloned() {
1564            inline_vars.push(LocalVar::Value { val: value, ty });
1565        }
1566
1567        let saved_vars = std::mem::replace(&mut ctx.vars, inline_vars);
1568        let saved_hints = std::mem::replace(&mut ctx.local_type_hints, local_type_hints);
1569        self.inline_stack.push(id);
1570        self.inline_depth += 1;
1571        self.inline_budget -= weight;
1572        let result = (|| -> Result<LocalVar> {
1573            let exit_block = ctx.builder.create_block();
1574            ctx.builder.append_block_param(exit_block, get_type(&inline_ret_ty)?);
1575            let terminated = self.gen_inline_stmt(ctx, &body, &inline_ret_ty, exit_block)?;
1576            if !terminated {
1577                return Err(anyhow!("inline candidate did not return on all paths: {}", fn_name));
1578            }
1579            ctx.builder.switch_to_block(exit_block);
1580            ctx.builder.seal_block(exit_block);
1581            Ok(LocalVar::Value { val: ctx.builder.block_params(exit_block)[0], ty: inline_ret_ty })
1582        })();
1583        self.inline_budget += weight;
1584        self.inline_depth -= 1;
1585        self.inline_stack.pop();
1586        ctx.local_type_hints = saved_hints;
1587        ctx.vars = saved_vars;
1588        result.map(Some)
1589    }
1590
1591    pub(crate) fn call_fn(&mut self, ctx: &mut BuildContext, id: u32, obj: Option<Expr>, params: &Vec<Expr>) -> Result<LocalVar> {
1592        self.call_fn_with_params(ctx, id, &[], obj, params)
1593    }
1594
1595    pub(crate) fn call_fn_with_params(&mut self, ctx: &mut BuildContext, id: u32, generic_args: &[Type], obj: Option<Expr>, params: &Vec<Expr>) -> Result<LocalVar> {
1596        self.call_fn_with_capture_values(ctx, id, generic_args, obj, params, None)
1597    }
1598
1599    pub(crate) fn call_fn_with_capture_values(&mut self, ctx: &mut BuildContext, id: u32, generic_args: &[Type], obj: Option<Expr>, params: &Vec<Expr>, capture_values: Option<Vec<(Value, Type)>>) -> Result<LocalVar> {
1600        let fn_name = self.compiler.sym_tab.symbols.get_symbol(id).map(|(name, _)| name.clone())?;
1601        let has_receiver = obj.is_some();
1602        if capture_values.is_none()
1603            && generic_args.is_empty()
1604            && obj.is_none()
1605            && Self::is_spawn_fn_name(fn_name.as_str())
1606            && let [target, args] = params.as_slice()
1607            && let LocalVar::Closure { id, captures } = self.eval(ctx, target)?
1608        {
1609            return self.spawn_closure(ctx, id, captures, args);
1610        }
1611        let mut args: Vec<(Value, Type)> = if let Some(obj) = obj { vec![self.eval(ctx, &obj)?.get(ctx).ok_or_else(|| anyhow!("函数 {} 的接收者表达式没有值: {:?}", fn_name, obj))?] } else { Vec::new() };
1612        for p in params {
1613            let value = self.eval(ctx, p)?;
1614            let value = match value {
1615                LocalVar::Closure { id, captures } => self.callback_value(ctx, id, captures)?.get(ctx).ok_or_else(|| anyhow!("函数 {} 的 callback 参数没有值: {:?}", fn_name, p))?,
1616                value => value.get(ctx).ok_or_else(|| anyhow!("函数 {} 的参数表达式没有值: {:?}", fn_name, p))?,
1617            };
1618            args.push(value);
1619        }
1620        if let Some(captures) = &capture_values {
1621            args.extend(captures.iter().cloned());
1622        }
1623        if let Some(value) = self.try_intrinsic_collection_call(ctx, fn_name.as_str(), &args)? {
1624            return Ok(value);
1625        }
1626        if fn_name.as_str().ends_with("Vec::swap")
1627            && let Some((base, vec_ty)) = args.first().cloned()
1628            && let Some(elem_ty) = Self::vec_elem_ty(&vec_ty)
1629        {
1630            let [_, left_idx, right_idx]: [(Value, Type); 3] = args.try_into().map_err(|_| anyhow!("Vec::swap 需要 self 和两个索引参数"))?;
1631            self.swap_vec_index(ctx, base, left_idx, right_idx, &elem_ty)?;
1632            return Ok(LocalVar::None);
1633        }
1634        let visible_arg_len = args.len() - capture_values.as_ref().map(|captures| captures.len()).unwrap_or(0);
1635        let arg_tys: Vec<Type> = args.iter().take(visible_arg_len).map(|(_, ty)| ty.clone()).collect();
1636        if !has_receiver && let Some(inlined) = self.try_inline_call(ctx, id, generic_args, &args, args.len() - visible_arg_len)? {
1637            return Ok(inlined);
1638        }
1639        let fn_info = match if generic_args.is_empty() { self.get_fn(id, &arg_tys) } else { Err(anyhow!("generic function needs specialization")) } {
1640            Ok(info) => info,
1641            Err(_) => self.gen_fn_with_params(Some(ctx), id, &arg_tys, generic_args).map_err(|e| {
1642                log::error!("{:?}", self.compiler.sym_tab.symbols.get_symbol(id));
1643                e
1644            })?,
1645        };
1646        match &fn_info {
1647            FnInfo::Call { fn_id: _, arg_tys: want_tys, caps, ret, context: _ } => {
1648                let mut args = self.adjust_args(ctx, args, want_tys)?;
1649                if capture_values.is_none() {
1650                    for c in caps {
1651                        args.push(ctx.get_var(*c as u32)?.get(ctx).ok_or_else(|| anyhow!("闭包捕获的变量 {} 未初始化", c))?.0);
1652                    }
1653                }
1654                if ret.is_void() {
1655                    self.call_for_side_effect(ctx, fn_info, args)?;
1656                    Ok(LocalVar::None)
1657                } else {
1658                    self.call(ctx, fn_info, args).map(|r| r.into())
1659                }
1660            }
1661            _ => panic!("不可能编译出 inline 函数"),
1662        }
1663    }
1664
1665    pub(crate) fn eval(&mut self, ctx: &mut BuildContext, expr: &Expr) -> Result<LocalVar> {
1666        self.eval_with_expected(ctx, expr, None)
1667    }
1668
1669    fn eval_with_expected(&mut self, ctx: &mut BuildContext, expr: &Expr, expected: Option<&Type>) -> Result<LocalVar> {
1670        if let Some(ty) = expected
1671            && self.expr_is_empty_list(expr)
1672            && let Some(value) = Self::empty_typed_list(ty)
1673        {
1674            let idx = self.compiler.get_const(value);
1675            let (val, _) = self.get_const_value(ctx, idx)?;
1676            return Ok(LocalVar::Value { val, ty: ty.clone() });
1677        }
1678        match &expr.kind {
1679            ExprKind::Value(v) => Ok(ctx.get_const(v)?.into()),
1680            ExprKind::Var(idx) => {
1681                let v = ctx.get_var(*idx)?;
1682                Ok(v)
1683            }
1684            ExprKind::Unary { op, value } => {
1685                let v = self.eval(ctx, value)?.get(ctx).ok_or_else(|| self.compile_error(ctx, value.span, "一元运算符的操作数无值(可能是未初始化或非表达式)"))?;
1686                if op == &UnaryOp::Not && v.1.is_any() {
1687                    let cond = self.bool_value(ctx, v)?;
1688                    let zero = ctx.builder.ins().iconst(types::I8, 0);
1689                    let one = ctx.builder.ins().iconst(types::I8, 1);
1690                    let is_zero = ctx.builder.ins().icmp_imm(IntCC::Equal, cond, 0);
1691                    Ok((ctx.builder.ins().select(is_zero, one, zero), Type::Bool).into())
1692                } else {
1693                    Ok(Self::unary(ctx, v, op.clone())?.into())
1694                }
1695            }
1696            ExprKind::Binary { left, op, right } => {
1697                if op == &BinaryOp::Assign {
1698                    let expected = self.assignment_target_ty(ctx, left);
1699                    match self.eval_with_expected(ctx, right, expected.as_ref()) {
1700                        Ok(value) => self.assign(ctx, left, value).map(|v| v.into()),
1701                        Err(e) => {
1702                            let err = self.compile_error(ctx, right.span, format!("赋值右侧编译失败: {e:#}"));
1703                            log::error!("{err:#}");
1704                            Err(err)
1705                        }
1706                    }
1707                } else {
1708                    if matches!(op, BinaryOp::And | BinaryOp::Or) {
1709                        let left = match self.eval(ctx, left)?.get(ctx) {
1710                            Some(left) => left,
1711                            None => {
1712                                let false_value = ctx.builder.ins().iconst(types::I8, 0);
1713                                (false_value, Type::Bool)
1714                            }
1715                        };
1716                        return self.short_circuit_logic(ctx, left, op.clone(), right).map(Into::into);
1717                    }
1718                    let assign_expr = if op.is_assign() { Some(left.clone()) } else { None };
1719                    let assign_expected = if op.is_assign() { self.assignment_target_ty(ctx, left) } else { None };
1720                    let left_var_idx = if let ExprKind::Var(idx) = &left.kind { Some(*idx) } else { None };
1721                    let left = match self.eval(ctx, left)?.get(ctx) {
1722                        Some(left) => left,
1723                        None => return Err(anyhow!("binary left has no value: {:?}", left)),
1724                    };
1725                    if op == &BinaryOp::Idx {
1726                        let left_ty = self.compiler.sym_tab.symbols.get_type(&left.1).unwrap_or_else(|_| left.1.clone());
1727                        let left = (left.0, left_ty);
1728                        if let Type::Struct { params: _, fields: _ } = &left.1 {
1729                            let idx = self.struct_field_index(&left.1, right)?;
1730                            return self.load_struct_field(ctx, left.0, idx, &left.1).map(|r| r.into());
1731                        }
1732                        if let Some(elem_ty) = Self::vec_elem_ty(&left.1) {
1733                            let idx = if right.is_value() {
1734                                let idx = right.clone().value()?.as_int().ok_or(anyhow!("Vec 索引必须是整数"))?;
1735                                (ctx.builder.ins().iconst(types::I64, idx), Type::I64)
1736                            } else {
1737                                self.eval(ctx, right)?.get(ctx).ok_or(anyhow!("Vec 索引没有值"))?
1738                            };
1739                            return self.load_vec_index(ctx, left.0, idx, &elem_ty).map(|r| r.into());
1740                        }
1741                        if let Some(elem_ty) = Self::array_elem_ty(&left.1) {
1742                            let idx = if right.is_value() {
1743                                let idx = right.clone().value()?.as_int().ok_or(anyhow!("array index must be integer"))?;
1744                                (ctx.builder.ins().iconst(types::I64, idx), Type::I64)
1745                            } else {
1746                                self.eval(ctx, right)?.get(ctx).ok_or(anyhow!("array index has no value"))?
1747                            };
1748                            return self.load_array_index(ctx, left.0, idx, &elem_ty).map(|r| r.into());
1749                        }
1750                        if right.is_value() {
1751                            let right_value = right.clone().value()?;
1752                            if let Some(idx) = right_value.as_int() {
1753                                let idx = ctx.builder.ins().iconst(types::I64, idx);
1754                                if let Some(var_idx) = left_var_idx
1755                                    && let Some(value) = self.intrinsic_list_fast_path_get_idx(ctx, var_idx, left.clone(), (idx, Type::I64))?
1756                                {
1757                                    return Ok(value.into());
1758                                }
1759                                if let Some(value) = self.intrinsic_list_get_idx(ctx, left.clone(), (idx, Type::I64))? {
1760                                    return Ok(value.into());
1761                                }
1762                                self.call(ctx, self.get_method(&left.1, "get_idx")?, vec![left.0, idx]).map(|r| r.into())
1763                            } else {
1764                                let key = ctx.get_const(&right_value)?;
1765                                self.call(ctx, self.get_method(&left.1, "get_key")?, vec![left.0, key.0]).map(|r| r.into())
1766                            }
1767                        } else if let ExprKind::Range { start, stop, inclusive } = &right.kind {
1768                            let start = self.eval(ctx, start)?.get(ctx).ok_or(anyhow!("range start has no value"))?;
1769                            let start = self.convert(ctx, start, Type::I64)?;
1770                            let stop = self.eval(ctx, stop)?.get(ctx).ok_or(anyhow!("range stop has no value"))?;
1771                            let stop = self.convert(ctx, stop, Type::Any)?;
1772                            let inclusive = ctx.builder.ins().iconst(types::I8, i64::from(*inclusive));
1773                            self.call(ctx, self.get_method(&left.1, "slice")?, vec![left.0, start, stop, inclusive]).map(|r| r.into())
1774                        } else {
1775                            let right = self.eval(ctx, right)?.get(ctx).ok_or(anyhow!("非Value {:?}", right))?;
1776                            if right.1.is_any() || right.1.is_str() {
1777                                let right = self.convert(ctx, right, Type::Any)?;
1778                                self.call(ctx, self.get_method(&left.1, "get_key")?, vec![left.0, right]).map(|r| r.into())
1779                            } else {
1780                                let right = self.convert(ctx, right, Type::I64)?;
1781                                if let Some(var_idx) = left_var_idx
1782                                    && let Some(value) = self.intrinsic_list_fast_path_get_idx(ctx, var_idx, left.clone(), (right, Type::I64))?
1783                                {
1784                                    return Ok(value.into());
1785                                }
1786                                if let Some(value) = self.intrinsic_list_get_idx(ctx, left.clone(), (right, Type::I64))? {
1787                                    return Ok(value.into());
1788                                }
1789                                self.call(ctx, self.get_method(&left.1, "get_idx")?, vec![left.0, right]).map(|r| r.into())
1790                            }
1791                        }
1792                    } else {
1793                        let result = self.binary_with_expected(ctx, left, op.clone(), right, assign_expected.as_ref().or(expected))?.into();
1794                        if let Some(expr) = assign_expr { self.assign(ctx, &expr, result).map(|r| r.into()) } else { Ok(result.into()) }
1795                    }
1796                }
1797            }
1798            ExprKind::Call { obj, params } => {
1799                if let ExprKind::AssocId { id, params: generic_args } = &obj.kind {
1800                    self.call_fn_with_params(ctx, *id, generic_args, None, params)
1801                } else if let ExprKind::Id(id, obj) = &obj.kind {
1802                    self.call_fn(ctx, *id, obj.as_ref().map(|o| *o.clone()), params)
1803                } else if obj.is_value() {
1804                    //直接忽略掉的代码 编译期就可以忽略
1805                    return Ok(LocalVar::None);
1806                } else {
1807                    if obj.is_idx() {
1808                        let (left, _, right) = obj.clone().binary().unwrap();
1809                        let left = self.eval(ctx, &left)?.get(ctx).ok_or(anyhow!("obj {:?}", obj))?;
1810                        let ty = self.compiler.sym_tab.symbols.get_type(&left.1)?;
1811                        if let Some(name) = self.get_dynamic(&right) {
1812                            if name.as_str() == "swap"
1813                                && let Some(elem_ty) = Self::vec_elem_ty(&ty)
1814                            {
1815                                let [left_idx, right_idx]: [(Value, Type); 2] =
1816                                    params.iter().map(|p| self.eval(ctx, p)?.get(ctx).ok_or(anyhow!("Vec::swap 参数没有值"))).collect::<Result<Vec<_>>>()?.try_into().map_err(|_| anyhow!("Vec::swap 需要两个索引参数"))?;
1817                                self.swap_vec_index(ctx, left.0, left_idx, right_idx, &elem_ty)?;
1818                                return Ok(LocalVar::None);
1819                            }
1820                            let mut args = vec![left];
1821                            for p in params {
1822                                args.push(self.eval(ctx, p)?.get(ctx).ok_or_else(|| anyhow!("动态方法 {:?} 的参数表达式没有值: {:?}", name, p))?);
1823                            }
1824                            let (_, method_ty) = self.compiler.get_field(&ty, name.as_str()).map_err(|e| self.compile_error(ctx, obj.span, format!("类型 {:?} 没有成员方法 `{}`: {e:#}", ty, name.as_str())))?;
1825                            let Type::Symbol { id, .. } = method_ty else {
1826                                return Err(self.compile_error(ctx, obj.span, format!("`{:?}.{}` 不是成员函数", ty, name.as_str())));
1827                            };
1828                            let arg_tys: Vec<Type> = args.iter().map(|(_, ty)| ty.clone()).collect();
1829                            let method = self.get_fn(id, &arg_tys).or_else(|_| self.gen_fn_with_params(Some(ctx), id, &arg_tys, &[]))?;
1830                            let args = self.adjust_args(ctx, args, method.arg_tys()?)?;
1831                            self.call(ctx, method, args).map(|r| r.into())
1832                        } else {
1833                            self.eval(ctx, obj)
1834                        }
1835                    } else {
1836                        let val = self.eval(ctx, obj)?;
1837                        if let LocalVar::Closure { id, captures } = val {
1838                            return self.call_fn_with_capture_values(ctx, id, &[], None, params, Some(captures));
1839                        }
1840                        let val_debug = format!("{:?}", val);
1841                        if let Some(callback) = val.get(ctx)
1842                            && (callback.1.is_any() || callback.1.is_fn())
1843                        {
1844                            return self.call_dynamic_callback(ctx, callback, params);
1845                        }
1846                        anyhow::bail!("暂未实现: {}", val_debug)
1847                    }
1848                }
1849            }
1850            ExprKind::Typed { value, ty } => {
1851                if let Type::Struct { params: _, fields: _ } = ty
1852                    && let ExprKind::List(items) = &value.kind
1853                {
1854                    return Ok((self.init_struct_from_items(ctx, items, ty)?, ty.clone()).into());
1855                }
1856                if let Type::Array(_, _) = ty
1857                    && let ExprKind::List(items) = &value.kind
1858                {
1859                    return Ok((self.init_array_from_items(ctx, items, ty)?, ty.clone()).into());
1860                }
1861                let evaluated = self.eval(ctx, value)?;
1862                if evaluated.is_closure() {
1863                    return Ok(evaluated);
1864                }
1865                let vt = if let Some(vt) = evaluated.get(ctx) {
1866                    vt
1867                } else if ty.is_any() {
1868                    let idx = self.compiler.get_const(Dynamic::Null);
1869                    self.get_const_value(ctx, idx)?
1870                } else {
1871                    return Ok(LocalVar::None);
1872                };
1873                if let Type::Struct { params: _, fields: _ } = ty
1874                    && !self.is_opaque_custom_ty(ty)
1875                {
1876                    if &vt.1 == ty {
1877                        Ok(vt.into())
1878                    } else if vt.1.is_any() {
1879                        Ok((self.init_struct_from_dynamic(ctx, vt, ty)?, ty.clone()).into())
1880                    } else {
1881                        Err(anyhow!("cannot convert {:?} to {:?}", vt.1, ty))
1882                    }
1883                } else if &vt.1 != ty {
1884                    Ok((self.convert(ctx, vt, ty.clone())?, ty.clone()).into())
1885                } else {
1886                    Ok(vt.into())
1887                }
1888            }
1889            ExprKind::Tuple(items) | ExprKind::List(items) => {
1890                // Tuple / List 字面量求值成一个 Dynamic::List(元素按 Any 装入)。
1891                // 这样 `let (a, b) = fn()` 的解构(被 desugar 成 a = fn()[0])就能
1892                // 通过 Any::get_idx 取到元素。空 tuple/list 取 null。
1893                if items.is_empty() {
1894                    let idx = self.compiler.get_const(Dynamic::Null);
1895                    self.get_const_value(ctx, idx).map(|v| v.into())
1896                } else {
1897                    let values = items.iter().map(|item| self.eval(ctx, item)?.get(ctx).ok_or_else(|| anyhow!("tuple/list item has no value: {:?}", item))).collect::<Result<Vec<_>>>()?;
1898                    self.dynamic_list_from_values(ctx, values).map(|r| r.into())
1899                }
1900            }
1901            ExprKind::Repeat { value, len } => {
1902                let value = self.eval(ctx, value)?.get(ctx).ok_or(anyhow!("repeat value has no value"))?;
1903                let Type::ConstInt(len) = len else {
1904                    return Err(anyhow!("repeat length must be a compile-time integer"));
1905                };
1906                let len = u32::try_from(*len).map_err(|_| anyhow!("repeat length out of range"))?;
1907                self.init_repeat_array(ctx, value, len).map(|r| r.into())
1908            }
1909            ExprKind::Const(idx) => self.get_const_value(ctx, *idx).map(|v| v.into()),
1910            ExprKind::Id(id, _) => self.closure_value(ctx, *id),
1911            ExprKind::AssocId { id, .. } => self.closure_value(ctx, *id),
1912            expr => {
1913                //结构就是一块固定大小 的内存(或者是动态大小 最后一个数据成员可扩展 跟 C 结构一样)
1914                anyhow::bail!("未实现: {:?}", expr)
1915            }
1916        }
1917    }
1918
1919    fn gen_loop(&mut self, ctx: &mut BuildContext, cond: Option<&Expr>, body: &Stmt, f: Option<impl FnMut(&mut BuildContext)>) -> Result<()> {
1920        let loop_block = ctx.builder.create_block();
1921        let end_block = ctx.builder.create_block();
1922        if let Some(cond) = cond {
1923            let start_block = ctx.builder.create_block();
1924            ctx.builder.ins().jump(start_block, &[]);
1925            ctx.builder.switch_to_block(start_block);
1926            let cond = self.eval(ctx, cond)?.get(ctx).ok_or_else(|| self.compile_error(ctx, cond.span, "while 条件无值(必须是可求值的表达式)"))?;
1927            let cond = self.bool_value(ctx, cond)?;
1928            let continue_block = if f.is_some() { ctx.builder.create_block() } else { start_block };
1929            ctx.builder.ins().brif(cond, loop_block, &[], end_block, &[]);
1930            ctx.builder.switch_to_block(loop_block);
1931            let body_terminated = self.gen_stmt(ctx, body, Some(end_block), Some(continue_block))?;
1932            if !body_terminated {
1933                ctx.builder.ins().jump(continue_block, &[]);
1934            }
1935            ctx.builder.seal_block(loop_block);
1936            f.map(|mut f| {
1937                ctx.builder.switch_to_block(continue_block);
1938                f(ctx);
1939                ctx.builder.ins().jump(start_block, &[]);
1940                ctx.builder.seal_block(continue_block);
1941            });
1942        } else {
1943            ctx.builder.ins().jump(loop_block, &[]);
1944            ctx.builder.switch_to_block(loop_block);
1945            let body_terminated = self.gen_stmt(ctx, body, Some(end_block), Some(loop_block))?;
1946            if !body_terminated {
1947                ctx.builder.ins().jump(loop_block, &[]);
1948            }
1949            ctx.builder.seal_block(loop_block);
1950        }
1951        ctx.builder.switch_to_block(end_block);
1952        Ok(())
1953    }
1954
1955    pub(crate) fn gen_stmt(&mut self, ctx: &mut BuildContext, stmt: &Stmt, break_block: Option<Block>, continue_block: Option<Block>) -> Result<bool> {
1956        match &stmt.kind {
1957            StmtKind::Expr(expr, _) => {
1958                let _ = self.eval(ctx, expr)?;
1959            }
1960            StmtKind::Break => {
1961                ctx.builder.ins().jump(break_block.unwrap(), &[]);
1962                return Ok(true);
1963            }
1964            StmtKind::Continue => {
1965                ctx.builder.ins().jump(continue_block.unwrap(), &[]);
1966                return Ok(true);
1967            }
1968            StmtKind::Return(expr) => {
1969                if let Some(expr) = expr {
1970                    let value = self.eval(ctx, expr)?;
1971                    let value = match value {
1972                        LocalVar::Closure { id, captures } => self.callback_value(ctx, id, captures)?.get(ctx),
1973                        value => value.get(ctx),
1974                    };
1975                    self.return_value(ctx, value)?;
1976                } else {
1977                    self.return_value(ctx, None)?;
1978                }
1979                return Ok(true);
1980            }
1981            StmtKind::If { cond, then_body, else_body } => {
1982                self.declare_assigned_vars(ctx, then_body)?;
1983                if let Some(else_body) = else_body {
1984                    self.declare_assigned_vars(ctx, else_body)?;
1985                }
1986                let then_block = ctx.builder.create_block();
1987                let cond = self.eval(ctx, cond)?.get(ctx).ok_or(anyhow!("未知的条件 {:?}", cond))?;
1988                let cond = self.bool_value(ctx, cond)?;
1989                let mut end_block = None;
1990                if let Some(else_body) = else_body {
1991                    let else_block = ctx.builder.create_block();
1992                    ctx.builder.ins().brif(cond, then_block, &[], else_block, &[]);
1993                    ctx.builder.switch_to_block(then_block);
1994                    if !self.gen_stmt(ctx, then_body, break_block, continue_block)? {
1995                        let block = ctx.builder.create_block();
1996                        ctx.builder.ins().jump(block, &[]);
1997                        end_block = Some(block);
1998                    }
1999                    ctx.builder.switch_to_block(else_block);
2000                    if !self.gen_stmt(ctx, else_body, break_block, continue_block)? {
2001                        if end_block.is_none() {
2002                            end_block = Some(ctx.builder.create_block());
2003                        }
2004                        ctx.builder.ins().jump(end_block.unwrap(), &[]);
2005                    }
2006                    ctx.builder.seal_block(else_block);
2007                } else {
2008                    let block = ctx.builder.create_block();
2009                    ctx.builder.ins().brif(cond, then_block, &[], block, &[]);
2010                    end_block = Some(block);
2011                    ctx.builder.switch_to_block(then_block);
2012                    if !self.gen_stmt(ctx, then_body, break_block, continue_block)? {
2013                        ctx.builder.ins().jump(end_block.unwrap(), &[]); //如果不是返回指令 增加跳转到 end_block
2014                    }
2015                }
2016                if let Some(block) = end_block {
2017                    ctx.builder.switch_to_block(block);
2018                }
2019                ctx.builder.seal_block(then_block);
2020                return Ok(end_block.is_none());
2021            }
2022            StmtKind::Block(stmts) => {
2023                for (idx, stmt) in stmts.iter().enumerate() {
2024                    let r = self.gen_stmt(ctx, stmt, break_block, continue_block)?;
2025                    if idx == stmts.len() - 1 {
2026                        return Ok(r);
2027                    }
2028                }
2029            }
2030            StmtKind::While { cond, body } => {
2031                self.declare_assigned_vars(ctx, body)?;
2032                let no_loop: Option<fn(&mut BuildContext)> = None;
2033                self.gen_loop(ctx, Some(cond), body, no_loop)?;
2034            }
2035            StmtKind::Loop(body) => {
2036                self.declare_assigned_vars(ctx, body)?;
2037                let no_loop: Option<fn(&mut BuildContext)> = None;
2038                self.gen_loop(ctx, None, body, no_loop)?;
2039            }
2040            StmtKind::For { pat, range, body } => {
2041                if let ExprKind::Range { start, stop, inclusive } = &range.kind {
2042                    if let PatternKind::Var { idx, .. } = &pat.kind {
2043                        let start = self.eval(ctx, start)?.get(ctx).ok_or(anyhow!("range start has no value"))?;
2044                        let stop = self.eval(ctx, stop)?.get(ctx).ok_or(anyhow!("range stop has no value"))?;
2045                        let range_ty = if start.1.is_any() && stop.1.is_any() {
2046                            Type::I64
2047                        } else if start.1.is_any() {
2048                            stop.1.clone()
2049                        } else if stop.1.is_any() {
2050                            start.1.clone()
2051                        } else {
2052                            start.1.clone() + stop.1.clone()
2053                        };
2054                        if !range_ty.is_int() && !range_ty.is_uint() {
2055                            anyhow::bail!("for range bounds must be integer, got {:?}", range_ty);
2056                        }
2057                        let start = self.convert(ctx, start, range_ty.clone())?;
2058                        let stop = self.convert(ctx, stop, range_ty.clone())?;
2059                        ctx.set_var(*idx, (start, range_ty.clone()).into())?;
2060                        self.declare_assigned_vars(ctx, body)?;
2061                        let list_fast_path_len = self.push_loop_list_fast_paths(ctx, body)?;
2062
2063                        let start_block = ctx.builder.create_block();
2064                        let body_block = ctx.builder.create_block();
2065                        let continue_block = ctx.builder.create_block();
2066                        let end_block = ctx.builder.create_block();
2067                        ctx.builder.ins().jump(start_block, &[]);
2068
2069                        ctx.builder.switch_to_block(start_block);
2070                        let current = ctx.get_var(*idx)?.get(ctx).ok_or(anyhow!("range loop variable has no value"))?;
2071                        let cond = if range_ty.is_uint() {
2072                            let op = if *inclusive { IntCC::UnsignedLessThanOrEqual } else { IntCC::UnsignedLessThan };
2073                            ctx.builder.ins().icmp(op, current.0, stop)
2074                        } else {
2075                            let op = if *inclusive { IntCC::SignedLessThanOrEqual } else { IntCC::SignedLessThan };
2076                            ctx.builder.ins().icmp(op, current.0, stop)
2077                        };
2078                        ctx.builder.ins().brif(cond, body_block, &[], end_block, &[]);
2079
2080                        ctx.builder.switch_to_block(body_block);
2081                        let body_terminated = self.gen_stmt(ctx, body, Some(end_block), Some(continue_block))?;
2082                        if !body_terminated {
2083                            ctx.builder.ins().jump(continue_block, &[]);
2084                        }
2085                        ctx.builder.seal_block(body_block);
2086
2087                        ctx.builder.switch_to_block(continue_block);
2088                        let current = ctx.get_var(*idx)?.get(ctx).ok_or(anyhow!("range loop variable has no value"))?;
2089                        let step = match &range_ty {
2090                            Type::I64 | Type::U64 => ctx.builder.ins().iconst(types::I64, 1),
2091                            Type::I32 | Type::U32 => ctx.builder.ins().iconst(types::I32, 1),
2092                            Type::I16 | Type::U16 => ctx.builder.ins().iconst(types::I16, 1),
2093                            Type::I8 | Type::U8 => ctx.builder.ins().iconst(types::I8, 1),
2094                            _ => unreachable!(),
2095                        };
2096                        let next = ctx.builder.ins().iadd(current.0, step);
2097                        ctx.set_var(*idx, (next, range_ty).into())?;
2098                        ctx.builder.ins().jump(start_block, &[]);
2099                        ctx.builder.seal_block(continue_block);
2100                        ctx.builder.seal_block(start_block);
2101                        ctx.builder.switch_to_block(end_block);
2102                        ctx.truncate_list_fast_paths(list_fast_path_len);
2103                    }
2104                } else if let PatternKind::Var { idx, .. } = &pat.kind {
2105                    let vt = self.eval(ctx, range)?.get(ctx).ok_or_else(|| self.compile_error(ctx, range.span, "for 循环的迭代对象无值"))?;
2106                    if let Type::List(_) = &vt.1 {
2107                        let len_fn = self.get_native_fn_cached("Any::len", &[Type::Any])?;
2108                        let len = self.call(ctx, len_fn, vec![vt.0])?;
2109                        let len = self.convert(ctx, len.into(), Type::I64)?;
2110                        let zero = ctx.builder.ins().iconst(types::I64, 0);
2111                        let first = if let Some(first) = self.intrinsic_list_get_idx(ctx, vt.clone(), (zero, Type::I64))? {
2112                            first
2113                        } else {
2114                            let get_idx_fn = self.get_native_fn_cached("Any::get_idx", &[Type::Any, Type::I64])?;
2115                            self.call(ctx, get_idx_fn, vec![vt.0, zero])?
2116                        };
2117                        ctx.set_var(*idx, first.into())?;
2118                        self.declare_assigned_vars(ctx, body)?;
2119
2120                        let index_var = ctx.builder.declare_var(types::I64);
2121                        ctx.builder.def_var(index_var, zero);
2122                        let start_block = ctx.builder.create_block();
2123                        let body_block = ctx.builder.create_block();
2124                        let continue_block = ctx.builder.create_block();
2125                        let end_block = ctx.builder.create_block();
2126                        ctx.builder.ins().jump(start_block, &[]);
2127                        ctx.builder.switch_to_block(start_block);
2128                        let index = ctx.builder.use_var(index_var);
2129                        let cond = ctx.builder.ins().icmp(IntCC::SignedLessThan, index, len);
2130                        ctx.builder.ins().brif(cond, body_block, &[], end_block, &[]);
2131
2132                        ctx.builder.switch_to_block(body_block);
2133                        let item = if let Some(item) = self.intrinsic_list_get_idx(ctx, vt.clone(), (index, Type::I64))? {
2134                            item
2135                        } else {
2136                            let get_idx_fn = self.get_native_fn_cached("Any::get_idx", &[Type::Any, Type::I64])?;
2137                            self.call(ctx, get_idx_fn, vec![vt.0, index])?
2138                        };
2139                        ctx.set_var(*idx, item.into())?;
2140                        let body_terminated = self.gen_stmt(ctx, body, Some(end_block), Some(continue_block))?;
2141                        if !body_terminated {
2142                            ctx.builder.ins().jump(continue_block, &[]);
2143                        }
2144                        ctx.builder.seal_block(body_block);
2145
2146                        ctx.builder.switch_to_block(continue_block);
2147                        let index = ctx.builder.use_var(index_var);
2148                        let one = ctx.builder.ins().iconst(types::I64, 1);
2149                        let next_index = ctx.builder.ins().iadd(index, one);
2150                        ctx.builder.def_var(index_var, next_index);
2151                        ctx.builder.ins().jump(start_block, &[]);
2152                        ctx.builder.seal_block(continue_block);
2153                        ctx.builder.seal_block(start_block);
2154                        ctx.builder.switch_to_block(end_block);
2155                    } else if vt.1.is_any() {
2156                        let iter = self.call(ctx, self.get_method(&vt.1, "iter")?, vec![vt.0])?;
2157                        let next = self.get_method(&vt.1, "next")?;
2158                        let next_id = next.get_id()?;
2159                        let start = self.call(ctx, next, vec![iter.0])?;
2160                        ctx.set_var(*idx, start.into())?;
2161                        let cond = Self::expr(ExprKind::Binary { left: Box::new(Self::expr(ExprKind::Var(*idx))), op: BinaryOp::Ne, right: Box::new(Self::expr(ExprKind::Value(Dynamic::Null))) });
2162                        self.gen_loop(
2163                            ctx,
2164                            Some(&cond),
2165                            body,
2166                            Some(|ctx: &mut BuildContext| {
2167                                let fn_ref = ctx.get_fn_ref(next_id).unwrap();
2168                                let call_inst = ctx.builder.ins().call(fn_ref, &[iter.0]);
2169                                let ret = ctx.builder.inst_results(call_inst)[0];
2170                                let _ = ctx.set_var(*idx, (ret, Type::Any).into());
2171                            }),
2172                        )?;
2173                    }
2174                } else if let PatternKind::Tuple(pats) = &pat.kind {
2175                    let vt = self.eval(ctx, range)?.get(ctx).ok_or_else(|| self.compile_error(ctx, range.span, "for 循环的迭代对象无值"))?;
2176                    if vt.1.is_any() && pats.len() == 2 {
2177                        //暂时只处理 kv
2178                        let iter = self.call(ctx, self.get_method(&vt.1, "iter")?, vec![vt.0])?;
2179                        let next_pair = self.get_method(&vt.1, "next_pair")?;
2180                        let next_id = next_pair.get_id()?;
2181                        let get_idx = self.get_method(&vt.1, "get_idx")?.get_id()?;
2182
2183                        let start = self.call(ctx, next_pair, vec![iter.0])?;
2184                        let key_idx = ctx.builder.ins().iconst(types::I64, 0);
2185                        let key = self.call(ctx, self.get_method(&start.1, "get_idx")?, vec![start.0, key_idx])?;
2186                        let value_idx = ctx.builder.ins().iconst(types::I64, 1);
2187                        let value = self.call(ctx, self.get_method(&start.1, "get_idx")?, vec![start.0, value_idx])?;
2188                        ctx.set_var(pats[0].var().unwrap(), key.into())?;
2189                        ctx.set_var(pats[1].var().unwrap(), value.into())?;
2190                        let cond = Self::expr(ExprKind::Binary { left: Box::new(Self::expr(ExprKind::Var(pats[0].var().unwrap()))), op: BinaryOp::Ne, right: Box::new(Self::expr(ExprKind::Value(Dynamic::Null))) });
2191                        self.gen_loop(
2192                            ctx,
2193                            Some(&cond),
2194                            body,
2195                            Some(|ctx: &mut BuildContext| {
2196                                let fn_ref = ctx.get_fn_ref(next_id).unwrap();
2197                                let call_inst = ctx.builder.ins().call(fn_ref, &[iter.0]);
2198                                let ret = ctx.builder.inst_results(call_inst)[0];
2199
2200                                let fn_ref = ctx.get_fn_ref(get_idx).unwrap();
2201                                let call_inst = ctx.builder.ins().call(fn_ref, &[ret, key_idx]);
2202                                let key_ret = ctx.builder.inst_results(call_inst)[0];
2203                                let call_inst = ctx.builder.ins().call(fn_ref, &[ret, value_idx]);
2204                                let value_ret = ctx.builder.inst_results(call_inst)[0];
2205
2206                                let _ = ctx.set_var(pats[0].var().unwrap(), (key_ret, Type::Any).into());
2207                                let _ = ctx.set_var(pats[1].var().unwrap(), (value_ret, Type::Any).into());
2208                            }),
2209                        )?;
2210                    }
2211                }
2212            }
2213            _ => {
2214                anyhow::bail!("未实现: {:?}", stmt)
2215            }
2216        }
2217        Ok(false)
2218    }
2219}
2220
2221#[cfg(test)]
2222mod tests {
2223    use super::*;
2224
2225    fn expr(kind: ExprKind) -> Expr {
2226        Expr::new(kind, Span::default())
2227    }
2228
2229    #[test]
2230    fn inline_weight_rejects_symbol_id_values_but_allows_call_targets() {
2231        let vm = JITRunTime::new(|_| {});
2232        let id_value = expr(ExprKind::Id(1, None));
2233
2234        assert_eq!(vm.inline_expr_weight(&id_value), None);
2235
2236        let call = expr(ExprKind::Call { obj: Box::new(id_value), params: vec![expr(ExprKind::Value(Dynamic::from(1i64)))] });
2237        assert_eq!(vm.inline_expr_weight(&call), Some(2));
2238    }
2239}