Skip to main content

vm/
rt.rs

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