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