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