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