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::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 smol_str::SmolStr;
15use std::sync::{Arc, Mutex, RwLock, Weak};
16
17pub struct JITRunTime {
18 pub compiler: Compiler,
19 pub fns: BTreeMap<u32, FnVariant>,
20 pub sigs: Vec<(Vec<Type>, Signature, Type)>,
21 pub native_symbols: Arc<RwLock<HashMap<String, usize>>>,
22 pub(crate) owner: Weak<Mutex<JITRunTime>>,
23 pub(crate) pending_fns: VecDeque<PendingFn>,
24 pub(crate) compile_depth: usize,
25 #[cfg(feature = "ir-disassembly")]
26 pub ir_disassembly: BTreeMap<SmolStr, String>,
27 pub module: JITModule,
28 pub consts: Vec<Option<usize>>,
29 pub(crate) scope_enter_fn: Option<FuncId>,
30 pub(crate) scope_exit_void_fn: Option<FuncId>,
31 pub(crate) scope_exit_dynamic_fn: Option<FuncId>,
32 pub(crate) scope_exit_bytes_fn: Option<FuncId>,
33 pub(crate) struct_alloc_fn: Option<FuncId>,
34 pub(crate) repeat_fill_fn: Option<FuncId>,
35 pub(crate) strcat_fn: Option<FuncId>,
36 pub(crate) strcat_i64_fn: Option<FuncId>,
37 pub(crate) strcat_assign_fn: Option<FuncId>,
38 pub(crate) spawn_ptr_fn: Option<FuncId>,
39 pub(crate) struct_from_ptr_fn: Option<FuncId>,
40 pub(crate) array_from_ptr_fn: Option<FuncId>,
41 pub(crate) array_to_ptr_fn: Option<FuncId>,
42}
43
44pub(crate) struct PendingFn {
48 pub name: SmolStr,
49 pub symbol_id: u32,
50 pub fn_id: FuncId,
51 pub arg_tys: Vec<Type>,
52 pub ret_ty: Type,
53 pub local_type_hints: Vec<Option<Type>>,
54 pub body: Stmt,
55}
56
57impl JITRunTime {
58 fn expr(kind: ExprKind) -> Expr {
59 Expr::new(kind, Span::default())
60 }
61
62 fn stmt(kind: StmtKind) -> Stmt {
63 Stmt::new(kind, Span::default())
64 }
65
66 pub(crate) fn type_ptr_const(ctx: &mut BuildContext, ty: &Type) -> Value {
67 let ty_ptr = Box::into_raw(Box::new(ty.clone()));
68 ctx.builder.ins().iconst(ptr_type(), ty_ptr as i64)
69 }
70
71 pub fn load(&mut self, code: Vec<u8>, arg_name: SmolStr) -> Result<(i64, Type)> {
72 let stmts = Compiler::parse_code(code)?;
73 self.compiler.resolve_imports(&stmts, None)?;
74 self.compiler.clear();
75 self.compiler.symbols.add_module("__console".into());
76 let mut cap = Capture::default();
77 let body = Self::stmt(StmtKind::Block(self.compiler.compile_fn(&[arg_name], &mut vec![Type::Any], Self::stmt(StmtKind::Block(stmts)), &mut cap)?));
78 self.compiler.tys.push(Type::Any);
79 let ret_ty = self.compiler.infer_stmt(&body)?;
80 self.compiler.clear();
81 let fn_id = self.compile_fn(None, &[Type::Any], ret_ty.clone(), &body)?;
82 self.compiler.clear();
83 self.compiler.symbols.pop_module();
84 self.module.finalize_definitions()?;
85 Ok((self.module.get_finalized_function(fn_id) as i64, ret_ty))
86 }
87
88 pub fn import_code(&mut self, name: &str, code: Vec<u8>) -> Result<()> {
89 log::info!("import {}", name);
90 let _ = self.compiler.import_code(name, code)?;
91 Ok(())
92 }
93
94 #[cfg(feature = "ir-disassembly")]
95 pub fn disassemble_ir(&mut self, name: &str) -> Result<String> {
96 if let Some(ir) = self.ir_disassembly.get(name) {
97 return Ok(ir.clone());
98 }
99 let id = self.get_id(name)?;
100 let (_, symbol) = self.compiler.symbols.get_symbol(id)?;
101 if let Symbol::Fn { ty, .. } = symbol
102 && let Type::Fn { tys, .. } = ty
103 && tys.is_empty()
104 {
105 let _ = self.gen_fn(None, id, &[])?;
106 }
107 self.ir_disassembly.get(name).cloned().ok_or_else(|| anyhow!("未找到函数 {} 的 Cranelift IR;如果它需要参数,请先触发对应实例化", name))
108 }
109
110 pub fn get_fn_ptr(&mut self, name: &str, arg_tys: &[Type]) -> Result<(*const u8, Type)> {
111 let main_id = self.get_id(name)?;
112 let fn_info = self.gen_fn(None, main_id, arg_tys)?;
113 Ok((self.module.get_finalized_function(fn_info.get_id()?), fn_info.get_type()?))
114 }
115
116 pub fn get_fn_ptr_with_params(&mut self, name: &str, arg_tys: &[Type], generic_args: &[Type]) -> Result<(*const u8, Type)> {
117 let main_id = self.get_id(name)?;
118 let fn_info = self.gen_fn_with_params(None, main_id, arg_tys, generic_args)?;
119 Ok((self.module.get_finalized_function(fn_info.get_id()?), fn_info.get_type()?))
120 }
121
122 pub fn get_const_value(&mut self, ctx: &mut BuildContext, idx: usize) -> Result<(Value, Type)> {
123 if self.consts.len() < idx + 1 {
124 self.consts.resize(idx + 1, None);
125 }
126 let ptr = if let Some(ptr) = self.consts.get(idx).cloned().unwrap_or(None) {
127 ptr
128 } else {
129 let c = Box::new(self.compiler.consts[idx].deep_clone()); let ptr = Box::into_raw(c) as usize;
131 self.consts[idx] = Some(ptr);
132 ptr
133 };
134 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 };
136 Ok((self.call(ctx, self.get_method(&Type::Any, "clone")?, vec![value])?.0, ty))
137 }
138
139 fn get_null_value(&mut self, ctx: &mut BuildContext) -> Result<(Value, Type)> {
140 let const_idx = self.compiler.get_const(Dynamic::Null);
141 self.get_const_value(ctx, const_idx)
142 }
143
144 pub fn get_dynamic(&self, expr: &Expr) -> Option<Dynamic> {
145 if let ExprKind::Const(idx) = &expr.kind { self.compiler.consts.get(*idx).cloned() } else { None }
146 }
147
148 pub fn get_method(&self, ty: &Type, name: &str) -> Result<FnInfo> {
149 self.compiler.get_field(ty, name).and_then(|(_, ty)| if let Type::Symbol { id, params: _ } = ty { self.get_fn(id, &[]) } else { Err(anyhow!("不是成员函数")) })
150 }
151
152 fn is_fn_field_type(&self, ty: &Type) -> bool {
153 match ty {
154 Type::Symbol { id, .. } => self.compiler.symbols.get_symbol(*id).map(|(_, symbol)| symbol.is_fn()).unwrap_or(false),
155 Type::Fn { .. } => true,
156 _ => false,
157 }
158 }
159
160 pub(crate) fn is_opaque_custom_ty(&self, ty: &Type) -> bool {
161 let ty = self.compiler.symbols.get_type(ty).unwrap_or_else(|_| ty.clone());
162 matches!(ty, Type::Struct { fields, .. } if !fields.is_empty() && fields.iter().all(|(_, field_ty)| self.is_fn_field_type(field_ty)))
163 }
164
165 pub(crate) fn is_aggregate_ty(&self, ty: &Type) -> bool {
166 (ty.is_struct() && !self.is_opaque_custom_ty(ty)) || ty.is_array()
167 }
168
169 pub fn get_id(&self, name: &str) -> Result<u32> {
170 self.compiler.symbols.get_id(name)
171 }
172
173 pub fn get_type(&mut self, name: &str, arg_tys: &[Type]) -> Result<Type> {
174 let id = self.get_id(name)?;
175 if self.compiler.symbols.symbols.get(name).map(|s| s.is_fn()).unwrap_or(false) {
176 return self.compiler.infer_fn(id, arg_tys);
177 }
178 self.compiler.symbols.get_type(&Type::Symbol { id, params: Vec::new() })
179 }
180
181 pub fn new<F: FnMut(&mut JITBuilder)>(mut f: F) -> Self {
182 let native_symbols = Arc::new(RwLock::new(HashMap::<String, usize>::new()));
183 let lookup_symbols = native_symbols.clone();
184 let mut builder = JITBuilder::new(cranelift_module::default_libcall_names()).unwrap();
185 builder.symbol_lookup_fn(Box::new(move |name| lookup_symbols.read().unwrap().get(name).copied().map(|ptr| ptr as *const u8)));
186 f(&mut builder);
187 let module = JITModule::new(builder);
188 PTR_TYPE.get_or_init(|| module.isa().pointer_type());
189 let fns = BTreeMap::<u32, FnVariant>::new();
190 Self {
191 compiler: Compiler::new(),
192 fns,
193 sigs: Vec::new(),
194 native_symbols,
195 owner: Weak::new(),
196 pending_fns: VecDeque::new(),
197 compile_depth: 0,
198 #[cfg(feature = "ir-disassembly")]
199 ir_disassembly: BTreeMap::new(),
200 module,
201 consts: Vec::new(),
202 scope_enter_fn: None,
203 scope_exit_void_fn: None,
204 scope_exit_dynamic_fn: None,
205 scope_exit_bytes_fn: None,
206 struct_alloc_fn: None,
207 repeat_fill_fn: None,
208 strcat_fn: None,
209 strcat_i64_fn: None,
210 strcat_assign_fn: None,
211 spawn_ptr_fn: None,
212 struct_from_ptr_fn: None,
213 array_from_ptr_fn: None,
214 array_to_ptr_fn: None,
215 }
216 }
217
218 pub(crate) fn set_owner(&mut self, owner: Weak<Mutex<JITRunTime>>) {
219 self.owner = owner;
220 }
221
222 pub(crate) fn owner_context_ptr(&self) -> usize {
223 &self.owner as *const Weak<Mutex<JITRunTime>> as usize
224 }
225
226 fn unary(ctx: &mut BuildContext, left: (Value, Type), op: UnaryOp) -> Result<(Value, Type)> {
227 match op {
228 UnaryOp::Neg => {
229 if left.1.is_int() || left.1.is_uint() {
230 if left.1.width() == 8 {
231 let zero = ctx.builder.ins().iconst(types::I64, 0);
232 return Ok((ctx.builder.ins().isub(zero, left.0), Type::I64));
233 } else if left.1.width() == 4 {
234 let zero = ctx.builder.ins().iconst(types::I32, 0);
235 return Ok((ctx.builder.ins().isub(zero, left.0), Type::I32));
236 }
237 } else if left.1.is_float() {
238 return Ok((ctx.builder.ins().fneg(left.0), left.1));
239 }
240 }
241 UnaryOp::Not => {
242 if left.1.is_int() || left.1.is_uint() {
243 let all_ones = ctx.builder.ins().iconst(get_type(&left.1)?, -1);
244 return Ok((ctx.builder.ins().bxor(left.0, all_ones), left.1));
245 }
246 let zero = ctx.builder.ins().iconst(types::I8, 0);
247 let one = ctx.builder.ins().iconst(types::I8, 1);
248 let cond = if left.1.is_bool() {
249 left.0
250 } else if left.1.is_f32() {
251 let zero = ctx.builder.ins().f32const(0.0);
252 ctx.builder.ins().fcmp(FloatCC::NotEqual, left.0, zero)
253 } else if left.1.is_f64() {
254 let zero = ctx.builder.ins().f64const(0.0);
255 ctx.builder.ins().fcmp(FloatCC::NotEqual, left.0, zero)
256 } else {
257 return Err(anyhow!("未实现 {:?} {:?}", left, op));
258 };
259 let is_zero = ctx.builder.ins().icmp_imm(IntCC::Equal, cond, 0);
260 return Ok((ctx.builder.ins().select(is_zero, one, zero), Type::Bool));
261 }
262 _ => {}
263 }
264 Err(anyhow!("未实现 {:?} {:?}", left, op))
265 }
266
267 pub(crate) fn call(&mut self, ctx: &mut BuildContext, fn_info: FnInfo, args: Vec<Value>) -> Result<(Value, Type)> {
268 match fn_info {
269 FnInfo::Call { fn_id, arg_tys: _, caps: _, ret, context } => {
270 let fn_ref = self.get_fn_ref(ctx, fn_id);
271 let args = self.add_context_arg(ctx, context, args);
272 let call_inst = ctx.builder.ins().call(fn_ref, &args);
273 if !ret.is_void() { Ok((ctx.builder.inst_results(call_inst)[0], ret)) } else { Err(anyhow!("没有返回值")) }
274 }
275 FnInfo::Inline { fn_ptr, arg_tys: _ } => fn_ptr(Some(ctx), args).map(|(v, t)| (v.unwrap(), t)),
276 }
277 }
278
279 pub(crate) fn scope_enter(&mut self, ctx: &mut BuildContext) -> Result<()> {
280 let fn_id = self.scope_enter_fn.ok_or_else(|| anyhow!("VM scope enter runtime is not registered"))?;
281 let fn_ref = self.get_fn_ref(ctx, fn_id);
282 ctx.builder.ins().call(fn_ref, &[]);
283 Ok(())
284 }
285
286 fn scope_exit_void(&mut self, ctx: &mut BuildContext) -> Result<()> {
287 let fn_id = self.scope_exit_void_fn.ok_or_else(|| anyhow!("VM scope exit runtime is not registered"))?;
288 let fn_ref = self.get_fn_ref(ctx, fn_id);
289 ctx.builder.ins().call(fn_ref, &[]);
290 Ok(())
291 }
292
293 fn return_value(&mut self, ctx: &mut BuildContext, value: Option<(Value, Type)>) -> Result<()> {
294 let ret_ty = ctx.ret_ty.clone();
295 if ret_ty.is_void() {
296 self.scope_exit_void(ctx)?;
297 ctx.builder.ins().return_(&[]);
298 return Ok(());
299 }
300
301 let Some((value, value_ty)) = value else {
302 self.scope_exit_void(ctx)?;
303 ctx.builder.ins().return_(&[]);
304 return Ok(());
305 };
306
307 if ret_ty.is_any() || ret_ty.is_str() || matches!(ret_ty, Type::Map | Type::List(_) | Type::Iter) {
308 let value = self.convert(ctx, (value, value_ty), Type::Any)?;
309 let fn_id = self.scope_exit_dynamic_fn.ok_or_else(|| anyhow!("VM dynamic return runtime is not registered"))?;
310 let fn_ref = self.get_fn_ref(ctx, fn_id);
311 let call_inst = ctx.builder.ins().call(fn_ref, &[value]);
312 let promoted = ctx.builder.inst_results(call_inst)[0];
313 ctx.builder.ins().return_(&[promoted]);
314 } else if self.is_aggregate_ty(&ret_ty) {
315 let value = self.convert(ctx, (value, value_ty), ret_ty.clone())?;
316 let size = ctx.builder.ins().iconst(types::I64, ret_ty.width() as i64);
317 let fn_id = self.scope_exit_bytes_fn.ok_or_else(|| anyhow!("VM aggregate return runtime is not registered"))?;
318 let fn_ref = self.get_fn_ref(ctx, fn_id);
319 let call_inst = ctx.builder.ins().call(fn_ref, &[value, size]);
320 let promoted = ctx.builder.inst_results(call_inst)[0];
321 ctx.builder.ins().return_(&[promoted]);
322 } else {
323 let value = self.convert(ctx, (value, value_ty), ret_ty)?;
324 self.scope_exit_void(ctx)?;
325 ctx.builder.ins().return_(&[value]);
326 }
327 Ok(())
328 }
329
330 fn call_for_side_effect(&mut self, ctx: &mut BuildContext, fn_info: FnInfo, args: Vec<Value>) -> Result<()> {
331 match fn_info {
332 FnInfo::Call { fn_id, arg_tys: _, caps: _, ret: _, context } => {
333 let fn_ref = self.get_fn_ref(ctx, fn_id);
334 let args = self.add_context_arg(ctx, context, args);
335 ctx.builder.ins().call(fn_ref, &args);
336 Ok(())
337 }
338 FnInfo::Inline { fn_ptr, arg_tys: _ } => fn_ptr(Some(ctx), args).map(|_| ()),
339 }
340 }
341
342 fn add_context_arg(&mut self, ctx: &mut BuildContext, context: Option<usize>, mut args: Vec<Value>) -> Vec<Value> {
343 if let Some(context) = context {
344 let context = ctx.builder.ins().iconst(ptr_type(), context as i64);
345 args.insert(0, context);
346 }
347 args
348 }
349
350 pub(crate) fn short_circuit_logic(&mut self, ctx: &mut BuildContext, left: (Value, Type), op: BinaryOp, right: &Expr) -> Result<(Value, Type)> {
351 let left = self.bool_value(ctx, left)?;
352 let rhs_block = ctx.builder.create_block();
353 let short_block = ctx.builder.create_block();
354 let end_block = ctx.builder.create_block();
355 ctx.builder.append_block_param(end_block, types::I8);
356
357 match op {
358 BinaryOp::And => {
359 ctx.builder.ins().brif(left, rhs_block, &[], short_block, &[]);
360 }
361 BinaryOp::Or => {
362 ctx.builder.ins().brif(left, short_block, &[], rhs_block, &[]);
363 }
364 _ => unreachable!(),
365 }
366
367 ctx.builder.switch_to_block(rhs_block);
368 let right = self.eval(ctx, right)?.get(ctx).unwrap();
369 let right = self.bool_value(ctx, right)?;
370 ctx.builder.ins().jump(end_block, &[cranelift::codegen::ir::BlockArg::Value(right)]);
371 ctx.builder.seal_block(rhs_block);
372
373 ctx.builder.switch_to_block(short_block);
374 let short_value = match op {
375 BinaryOp::And => ctx.builder.ins().iconst(types::I8, 0),
376 BinaryOp::Or => ctx.builder.ins().iconst(types::I8, 1),
377 _ => unreachable!(),
378 };
379 ctx.builder.ins().jump(end_block, &[cranelift::codegen::ir::BlockArg::Value(short_value)]);
380 ctx.builder.seal_block(short_block);
381
382 ctx.builder.switch_to_block(end_block);
383 let result = ctx.builder.block_params(end_block)[0];
384 Ok((result, Type::Bool))
385 }
386
387 fn struct_alloc(&mut self, ctx: &mut BuildContext, ty: &Type) -> Result<Value> {
388 let size = ctx.builder.ins().iconst(types::I64, ty.width() as i64);
389 let fn_id = self.struct_alloc_fn.ok_or_else(|| anyhow!("VM struct allocator runtime is not registered"))?;
390 let fn_ref = self.get_fn_ref(ctx, fn_id);
391 let call_inst = ctx.builder.ins().call(fn_ref, &[size]);
392 Ok(ctx.builder.inst_results(call_inst)[0])
393 }
394
395 fn store_struct_field(&mut self, ctx: &mut BuildContext, base: Value, idx: usize, field_ty: &Type, value: (Value, Type), struct_ty: &Type) -> Result<()> {
396 let offset = struct_ty.field_offset(idx).ok_or_else(|| anyhow!("结构字段索引越界 {}", idx))?;
397 let value = self.convert(ctx, value, field_ty.clone())?;
398 if field_ty.is_struct() || field_ty.is_array() {
399 let field_addr = ctx.builder.ins().iadd_imm(base, offset as i64);
400 self.copy_vec_element(ctx, field_addr, value, field_ty);
401 } else {
402 ctx.builder.ins().store(MemFlags::trusted(), value, base, offset as i32);
403 }
404 Ok(())
405 }
406
407 fn load_struct_field(&mut self, ctx: &mut BuildContext, base: Value, idx: usize, struct_ty: &Type) -> Result<(Value, Type)> {
408 if let Type::Struct { params: _, fields } = struct_ty {
409 let field_ty = fields.get(idx).map(|(_, ty)| ty).ok_or_else(|| anyhow!("结构字段索引越界 {}", idx))?;
410 let offset = struct_ty.field_offset(idx).ok_or_else(|| anyhow!("结构字段索引越界 {}", idx))?;
411 if field_ty.is_struct() || field_ty.is_array() {
412 return Ok((ctx.builder.ins().iadd_imm(base, offset as i64), field_ty.clone()));
413 }
414 let val = ctx.builder.ins().load(crate::get_type(field_ty)?, MemFlags::trusted(), base, offset as i32);
415 Ok((val, field_ty.clone()))
416 } else {
417 Err(anyhow!("不是结构体 {:?}", struct_ty))
418 }
419 }
420
421 fn struct_field_index(&self, struct_ty: &Type, right: &Expr) -> Result<usize> {
422 let value = if let ExprKind::Const(idx) = right.kind { self.compiler.consts.get(idx).cloned().ok_or_else(|| anyhow!("missing const {}", idx))? } else { right.clone().value()? };
423 if let Some(idx) = value.as_int() {
424 return usize::try_from(idx).map_err(|_| anyhow!("结构字段索引越界 {}", idx));
425 }
426 if value.is_str() {
427 return self.compiler.get_field(struct_ty, value.as_str()).map(|(idx, _)| idx);
428 }
429 Err(anyhow!("非立即数结构字段索引 {:?}", right))
430 }
431
432 fn vec_elem_ty(ty: &Type) -> Option<Type> {
433 if let Type::Vec(elem, 0) = ty { Some((**elem).clone()) } else { None }
434 }
435
436 fn array_elem_ty(ty: &Type) -> Option<Type> {
437 if let Type::Array(elem, _) = ty { Some((**elem).clone()) } else { None }
438 }
439
440 fn vec_index_addr(&mut self, ctx: &mut BuildContext, base: Value, idx: (Value, Type), elem_ty: &Type) -> Result<Value> {
441 let idx = self.convert(ctx, idx, Type::I64)?;
442 let width = ctx.builder.ins().iconst(types::I64, elem_ty.storage_width() as i64);
443 let offset = ctx.builder.ins().imul(idx, width);
444 Ok(ctx.builder.ins().iadd(base, offset))
445 }
446
447 fn array_index_addr(&mut self, ctx: &mut BuildContext, base: Value, idx: (Value, Type), elem_ty: &Type) -> Result<Value> {
448 self.vec_index_addr(ctx, base, idx, elem_ty)
449 }
450
451 fn load_array_index(&mut self, ctx: &mut BuildContext, base: Value, idx: (Value, Type), elem_ty: &Type) -> Result<(Value, Type)> {
452 let addr = self.array_index_addr(ctx, base, idx, elem_ty)?;
453 if elem_ty.is_struct() || elem_ty.is_array() {
454 Ok((addr, elem_ty.clone()))
455 } else {
456 let val = ctx.builder.ins().load(crate::get_type(elem_ty)?, MemFlags::trusted(), addr, 0);
457 Ok((val, elem_ty.clone()))
458 }
459 }
460
461 fn store_array_index(&mut self, ctx: &mut BuildContext, base: Value, idx: (Value, Type), elem_ty: &Type, value: (Value, Type)) -> Result<()> {
462 let addr = self.array_index_addr(ctx, base, idx, elem_ty)?;
463 let value = self.convert(ctx, value, elem_ty.clone())?;
464 if elem_ty.is_struct() || elem_ty.is_array() {
465 self.copy_vec_element(ctx, addr, value, elem_ty);
466 } else {
467 let value = LocalVar::normalize_for_var(ctx, value, elem_ty);
468 ctx.builder.ins().store(MemFlags::trusted(), value, addr, 0);
469 }
470 Ok(())
471 }
472
473 fn init_repeat_array(&mut self, ctx: &mut BuildContext, value: (Value, Type), len: u32) -> Result<(Value, Type)> {
474 let elem_ty = value.1.clone();
475 let array_ty = Type::Array(std::rc::Rc::new(elem_ty.clone()), len);
476 let base = self.struct_alloc(ctx, &array_ty)?;
477 if let Some(pattern) = self.repeat_fill_pattern(ctx, value.0, &elem_ty) {
478 let fn_id = self.repeat_fill_fn.ok_or_else(|| anyhow!("VM repeat fill runtime is not registered"))?;
479 let fn_ref = self.get_fn_ref(ctx, fn_id);
480 let width = ctx.builder.ins().iconst(types::I64, elem_ty.storage_width() as i64);
481 let len = ctx.builder.ins().iconst(types::I64, len as i64);
482 ctx.builder.ins().call(fn_ref, &[base, pattern, width, len]);
483 return Ok((base, array_ty));
484 }
485 for idx in 0..len {
486 let idx = (ctx.builder.ins().iconst(types::I64, idx as i64), Type::I64);
487 self.store_array_index(ctx, base, idx, &elem_ty, value.clone())?;
488 }
489 Ok((base, array_ty))
490 }
491
492 fn repeat_fill_pattern(&mut self, ctx: &mut BuildContext, value: Value, ty: &Type) -> Option<Value> {
493 if matches!(ty, Type::Bool) || ty.is_int() || ty.is_uint() {
494 return Some(if ty.storage_width() < 8 { ctx.builder.ins().uextend(types::I64, value) } else { value });
495 }
496 if ty.is_f32() {
497 let flags = MemFlags::new().with_endianness(cranelift::codegen::ir::Endianness::Little);
498 let bits = ctx.builder.ins().bitcast(types::I32, flags, value);
499 return Some(ctx.builder.ins().uextend(types::I64, bits));
500 }
501 if ty.is_f64() {
502 let flags = MemFlags::new().with_endianness(cranelift::codegen::ir::Endianness::Little);
503 return Some(ctx.builder.ins().bitcast(types::I64, flags, value));
504 }
505 None
506 }
507
508 fn init_array_from_items(&mut self, ctx: &mut BuildContext, items: &[Expr], ty: &Type) -> Result<Value> {
509 let Type::Array(elem_ty, len) = ty else {
510 return Err(anyhow!("not an array type: {:?}", ty));
511 };
512 if items.len() != *len as usize {
513 return Err(anyhow!("array literal length {} does not match {}", items.len(), len));
514 }
515 let base = self.struct_alloc(ctx, ty)?;
516 for (idx, item) in items.iter().enumerate() {
517 let value = self.eval(ctx, item)?.get(ctx).ok_or(anyhow!("array item has no value"))?;
518 let idx = (ctx.builder.ins().iconst(types::I64, idx as i64), Type::I64);
519 self.store_array_index(ctx, base, idx, elem_ty, value)?;
520 }
521 Ok(base)
522 }
523
524 pub(crate) fn any_to_array(&mut self, ctx: &mut BuildContext, value: Value, ty: &Type) -> Result<Value> {
525 let Type::Array(_, _) = ty else {
526 return Err(anyhow!("not an array type: {:?}", ty));
527 };
528 let base = self.struct_alloc(ctx, ty)?;
529 let ty_ptr = Self::type_ptr_const(ctx, ty);
530 let fn_id = self.array_to_ptr_fn.ok_or_else(|| anyhow!("VM array assignment runtime is not registered"))?;
531 let fn_ref = self.get_fn_ref(ctx, fn_id);
532 ctx.builder.ins().call(fn_ref, &[base, value, ty_ptr]);
533 Ok(base)
534 }
535
536 fn load_vec_index(&mut self, ctx: &mut BuildContext, base: Value, idx: (Value, Type), elem_ty: &Type) -> Result<(Value, Type)> {
537 let addr = self.vec_index_addr(ctx, base, idx, elem_ty)?;
538 if elem_ty.is_struct() {
539 Ok((addr, elem_ty.clone()))
540 } else {
541 let val = ctx.builder.ins().load(crate::get_type(elem_ty)?, MemFlags::trusted(), addr, 0);
542 Ok((val, elem_ty.clone()))
543 }
544 }
545
546 fn copy_vec_element(&mut self, ctx: &mut BuildContext, dst: Value, src: Value, elem_ty: &Type) {
547 let mut offset = 0u32;
548 let width = elem_ty.storage_width();
549 while offset < width {
550 let remaining = width - offset;
551 let (ty, size) = if remaining >= 8 {
552 (types::I64, 8)
553 } else if remaining >= 4 {
554 (types::I32, 4)
555 } else if remaining >= 2 {
556 (types::I16, 2)
557 } else {
558 (types::I8, 1)
559 };
560 let value = ctx.builder.ins().load(ty, MemFlags::trusted(), src, offset as i32);
561 ctx.builder.ins().store(MemFlags::trusted(), value, dst, offset as i32);
562 offset += size;
563 }
564 }
565
566 fn store_vec_index(&mut self, ctx: &mut BuildContext, base: Value, idx: (Value, Type), elem_ty: &Type, value: (Value, Type)) -> Result<()> {
567 let addr = self.vec_index_addr(ctx, base, idx, elem_ty)?;
568 let value = self.convert(ctx, value, elem_ty.clone())?;
569 if elem_ty.is_struct() {
570 self.copy_vec_element(ctx, addr, value, elem_ty);
571 } else {
572 let value = LocalVar::normalize_for_var(ctx, value, elem_ty);
573 ctx.builder.ins().store(MemFlags::trusted(), value, addr, 0);
574 }
575 Ok(())
576 }
577
578 fn swap_vec_index(&mut self, ctx: &mut BuildContext, base: Value, left: (Value, Type), right: (Value, Type), elem_ty: &Type) -> Result<()> {
579 let left_addr = self.vec_index_addr(ctx, base, left, elem_ty)?;
580 let right_addr = self.vec_index_addr(ctx, base, right, elem_ty)?;
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 left_value = ctx.builder.ins().load(ty, MemFlags::trusted(), left_addr, offset as i32);
595 let right_value = ctx.builder.ins().load(ty, MemFlags::trusted(), right_addr, offset as i32);
596 ctx.builder.ins().store(MemFlags::trusted(), left_value, right_addr, offset as i32);
597 ctx.builder.ins().store(MemFlags::trusted(), right_value, left_addr, offset as i32);
598 offset += size;
599 }
600 Ok(())
601 }
602
603 fn init_struct_from_dynamic(&mut self, ctx: &mut BuildContext, value: (Value, Type), ty: &Type) -> Result<Value> {
604 let Type::Struct { params: _, fields } = ty else {
605 return Err(anyhow!("不是结构体 {:?}", ty));
606 };
607 let base = self.struct_alloc(ctx, ty)?;
608 for (idx, (_, field_ty)) in fields.iter().enumerate() {
609 let idx_val = ctx.builder.ins().iconst(types::I64, idx as i64);
610 let item = self.call(ctx, self.get_method(&Type::Any, "get_idx")?, vec![value.0, idx_val])?;
611 self.store_struct_field(ctx, base, idx, field_ty, item, ty)?;
612 }
613 Ok(base)
614 }
615
616 fn init_struct_from_items(&mut self, ctx: &mut BuildContext, items: &[Expr], ty: &Type) -> Result<Value> {
617 let Type::Struct { params: _, fields } = ty else {
618 return Err(anyhow!("not a struct type: {:?}", ty));
619 };
620 let base = self.struct_alloc(ctx, ty)?;
621 for (idx, item) in items.iter().enumerate() {
622 let Some((_, field_ty)) = fields.get(idx) else {
623 break;
624 };
625 let value = self.eval(ctx, item)?.get(ctx).ok_or(anyhow!("struct field has no value"))?;
626 self.store_struct_field(ctx, base, idx, field_ty, value, ty)?;
627 }
628 Ok(base)
629 }
630
631 fn expr_assigned_var(expr: &Expr) -> Option<(u32, Type)> {
632 if let ExprKind::Binary { left, op, right } = &expr.kind
633 && op.is_assign()
634 && let ExprKind::Var(idx) = left.kind
635 {
636 return Some((idx, right.get_type()));
637 }
638 None
639 }
640
641 fn declare_assigned_vars(&mut self, ctx: &mut BuildContext, stmt: &Stmt) -> Result<()> {
642 match &stmt.kind {
643 StmtKind::Expr(expr, _) => {
644 if let Some((idx, ty)) = Self::expr_assigned_var(expr) {
645 match ctx.get_var(idx).ok() {
646 Some(LocalVar::Variable { .. }) | Some(LocalVar::Closure { .. }) => {}
647 Some(LocalVar::Value { val, ty }) => {
648 ctx.set_var(idx, LocalVar::Value { val, ty })?;
649 }
650 Some(LocalVar::None) | None => {
651 let init = self.zero_value(ctx, &ty)?;
652 ctx.set_var(idx, init.into())?;
653 }
654 }
655 }
656 }
657 StmtKind::Block(stmts) => {
658 for stmt in stmts {
659 self.declare_assigned_vars(ctx, stmt)?;
660 }
661 }
662 StmtKind::If { then_body, else_body, .. } => {
663 self.declare_assigned_vars(ctx, then_body)?;
664 if let Some(else_body) = else_body {
665 self.declare_assigned_vars(ctx, else_body)?;
666 }
667 }
668 StmtKind::While { body, .. } | StmtKind::Loop(body) => {
669 self.declare_assigned_vars(ctx, body)?;
670 }
671 StmtKind::For { body, .. } => {
672 self.declare_assigned_vars(ctx, body)?;
673 }
674 _ => {}
675 }
676 Ok(())
677 }
678
679 fn zero_value(&mut self, ctx: &mut BuildContext, ty: &Type) -> Result<(Value, Type)> {
680 if self.is_aggregate_ty(ty) {
681 Ok((self.struct_alloc(ctx, ty)?, ty.clone()))
682 } else if ty.is_f32() {
683 Ok((ctx.builder.ins().f32const(0.0), ty.clone()))
684 } else if ty.is_f64() {
685 Ok((ctx.builder.ins().f64const(0.0), ty.clone()))
686 } else {
687 Ok((ctx.builder.ins().iconst(crate::get_type(ty)?, 0), ty.clone()))
688 }
689 }
690
691 fn assign(&mut self, ctx: &mut BuildContext, left: &Expr, value: LocalVar) -> Result<(Value, Type)> {
692 if let ExprKind::Var(idx) = &left.kind {
693 if value.is_closure() {
694 ctx.set_var(*idx, value)?;
695 return self.get_null_value(ctx);
696 }
697 let value_ty = value.get_ty();
698 if let Some(ty) = ctx.get_var_ty(*idx) {
699 if self.is_aggregate_ty(&ty) {
700 let dst = ctx.get_var(*idx)?.get(ctx).ok_or(anyhow!("aggregate variable has no value"))?.0;
701 let src = value.get(ctx).ok_or(anyhow!("aggregate assignment has no value"))?;
702 let src = self.convert(ctx, src, ty.clone())?;
703 self.copy_vec_element(ctx, dst, src, &ty);
704 } else if value_ty != ty {
705 if let Some(vt) = value.get(ctx) {
706 let val = self.convert(ctx, vt, ty.clone())?;
707 ctx.set_var(*idx, LocalVar::Value { val, ty })?;
708 } else if ty.is_any() {
709 let const_idx = self.compiler.get_const(Dynamic::Null);
710 let (val, ty) = self.get_const_value(ctx, const_idx)?;
711 ctx.set_var(*idx, LocalVar::Value { val, ty })?;
712 } else {
713 ctx.set_var(*idx, LocalVar::None)?;
714 }
715 } else {
716 ctx.set_var(*idx, value)?;
717 }
718 } else if self.is_aggregate_ty(&value_ty) {
719 let src = value.get(ctx).ok_or(anyhow!("aggregate initializer has no value"))?;
720 let dst = self.struct_alloc(ctx, &value_ty)?;
721 let src = self.convert(ctx, src, value_ty.clone())?;
722 self.copy_vec_element(ctx, dst, src, &value_ty);
723 ctx.set_var(*idx, LocalVar::Value { val: dst, ty: value_ty })?;
724 } else {
725 ctx.set_var(*idx, value)?;
726 }
727 let assigned = ctx.get_var(*idx)?;
728 if assigned.is_closure() {
729 return self.get_null_value(ctx);
730 }
731 let val = assigned.get(ctx).ok_or(anyhow!("assigned variable has no value"))?;
732 return Ok(val);
733 } else if left.is_idx() {
734 let value = value.get(ctx).unwrap();
735 let (left, _, right) = left.clone().binary().unwrap();
736 let left = self.eval(ctx, &left)?.get(ctx).ok_or(anyhow!("未知局部变量 {:?}", left))?;
737 if let Type::Struct { params: _, fields } = &left.1 {
738 let idx = self.struct_field_index(&left.1, &right)?;
739 let field_ty = fields.get(idx).map(|(_, ty)| ty.clone()).ok_or_else(|| anyhow!("结构字段索引越界 {}", idx))?;
740 self.store_struct_field(ctx, left.0, idx, &field_ty, value.clone(), &left.1)?;
741 return Ok(value);
742 }
743 if let Some(elem_ty) = Self::vec_elem_ty(&left.1) {
744 let idx = if right.is_value() {
745 let idx = right.clone().value()?.as_int().ok_or(anyhow!("Vec 索引必须是整数"))?;
746 (ctx.builder.ins().iconst(types::I64, idx), Type::I64)
747 } else {
748 self.eval(ctx, &right)?.get(ctx).ok_or(anyhow!("Vec 索引没有值"))?
749 };
750 self.store_vec_index(ctx, left.0, idx, &elem_ty, value.clone())?;
751 return Ok(value);
752 }
753 if let Some(elem_ty) = Self::array_elem_ty(&left.1) {
754 let idx = if right.is_value() {
755 let idx = right.clone().value()?.as_int().ok_or(anyhow!("array index must be integer"))?;
756 (ctx.builder.ins().iconst(types::I64, idx), Type::I64)
757 } else {
758 self.eval(ctx, &right)?.get(ctx).ok_or(anyhow!("array index has no value"))?
759 };
760 self.store_array_index(ctx, left.0, idx, &elem_ty, value.clone())?;
761 return Ok(value);
762 }
763 if right.is_value() {
764 let right_value = right.clone().value()?;
765 if let Some(idx) = right_value.as_int() {
766 let idx = ctx.builder.ins().iconst(types::I64, idx);
767 if let Type::List(elem_ty) = &left.1
768 && let Some((fn_name, value_ty)) = Self::list_set_idx_shortcut(elem_ty)
769 {
770 let stored = self.convert(ctx, value.clone(), value_ty.clone())?;
771 let set_idx_fn = self.get_fn(self.get_id(fn_name)?, &[Type::Any, Type::I64, value_ty])?;
772 self.call_for_side_effect(ctx, set_idx_fn, vec![left.0, idx, stored])?;
773 return Ok(value);
774 }
775 let f = self.get_method(&left.1, "set_idx")?;
776 let args = self.adjust_args(ctx, vec![left, (idx, Type::I64), value.clone()], f.arg_tys()?)?;
777 self.call_for_side_effect(ctx, f, args)?;
778 } else {
779 let key = ctx.get_const(&right_value)?;
780 let f = self.get_method(&left.1, "set_key")?;
781 let args = self.adjust_args(ctx, vec![left, key, value.clone()], f.arg_tys()?)?;
782 self.call_for_side_effect(ctx, f, args)?;
783 }
784 } else {
785 let right = self.eval(ctx, &right)?.get(ctx).unwrap();
786 if right.1.is_any() || right.1.is_str() {
787 let f = self.get_method(&left.1, "set_key")?;
788 let args = self.adjust_args(ctx, vec![left, right, value.clone()], f.arg_tys()?)?;
789 self.call_for_side_effect(ctx, f, args)?;
790 } else {
791 if let Type::List(elem_ty) = &left.1
792 && let Some((fn_name, value_ty)) = Self::list_set_idx_shortcut(elem_ty)
793 {
794 let idx = self.convert(ctx, right.clone(), Type::I64)?;
795 let stored = self.convert(ctx, value.clone(), value_ty.clone())?;
796 let set_idx_fn = self.get_fn(self.get_id(fn_name)?, &[Type::Any, Type::I64, value_ty])?;
797 self.call_for_side_effect(ctx, set_idx_fn, vec![left.0, idx, stored])?;
798 return Ok(value);
799 }
800 let f = self.get_method(&left.1, "set_idx")?;
801 let args = self.adjust_args(ctx, vec![left, right, value.clone()], f.arg_tys()?)?;
802 self.call_for_side_effect(ctx, f, args)?;
803 }
804 }
805 return Ok(value);
806 } else {
807 panic!("赋值给 {:?} {:?}", left, value)
808 }
809 }
810
811 fn assignment_target_ty(&mut self, ctx: &mut BuildContext, left: &Expr) -> Option<Type> {
812 if let ExprKind::Var(idx) = &left.kind {
813 return ctx.get_var_ty(*idx).filter(|ty| !ty.is_any()).or_else(|| ctx.local_type_hint(*idx));
814 }
815 None
816 }
817
818 fn empty_typed_list(ty: &Type) -> Option<Dynamic> {
819 let Type::List(elem_ty) = ty else {
820 return None;
821 };
822 match elem_ty.as_ref() {
823 Type::Bool | Type::U8 => Some(Dynamic::list(Vec::new())),
824 Type::I8 => Some(Dynamic::VecI8(Default::default())),
825 Type::U16 => Some(Dynamic::VecU16(Default::default())),
826 Type::I16 => Some(Dynamic::VecI16(Default::default())),
827 Type::U32 => Some(Dynamic::VecU32(Default::default())),
828 Type::I32 => Some(Dynamic::VecI32(Default::default())),
829 Type::F32 => Some(Dynamic::VecF32(Default::default())),
830 Type::U64 => Some(Dynamic::VecU64(Vec::new())),
831 Type::I64 => Some(Dynamic::VecI64(Vec::new())),
832 Type::F64 => Some(Dynamic::VecF64(Vec::new())),
833 Type::Str => Some(Dynamic::list(Vec::new())),
834 _ => None,
835 }
836 }
837
838 fn list_push_shortcut(elem_ty: &Type) -> Option<(&'static str, Type)> {
839 match elem_ty {
840 Type::Bool => Some(("Any::push_bool", Type::Bool)),
841 Type::U8 => Some(("Any::push_u8", Type::U8)),
842 Type::I8 => Some(("Any::push_i8", Type::I8)),
843 Type::U16 => Some(("Any::push_u16", Type::U16)),
844 Type::I16 => Some(("Any::push_i16", Type::I16)),
845 Type::U32 => Some(("Any::push_u32", Type::U32)),
846 Type::I32 => Some(("Any::push_i32", Type::I32)),
847 Type::F32 => Some(("Any::push_f32", Type::F32)),
848 Type::U64 => Some(("Any::push_u64", Type::U64)),
849 Type::I64 => Some(("Any::push_i64", Type::I64)),
850 Type::F64 => Some(("Any::push_f64", Type::F64)),
851 Type::Str => Some(("Any::push_str", Type::Str)),
852 _ => None,
853 }
854 }
855
856 fn list_get_idx_shortcut(elem_ty: &Type) -> Option<(&'static str, Type)> {
857 match elem_ty {
858 Type::Bool => Some(("Any::get_idx_bool", Type::Bool)),
859 Type::U8 => Some(("Any::get_idx_u8", Type::U8)),
860 Type::I8 => Some(("Any::get_idx_i8", Type::I8)),
861 Type::U16 => Some(("Any::get_idx_u16", Type::U16)),
862 Type::I16 => Some(("Any::get_idx_i16", Type::I16)),
863 Type::U32 => Some(("Any::get_idx_u32", Type::U32)),
864 Type::I32 => Some(("Any::get_idx_i32", Type::I32)),
865 Type::F32 => Some(("Any::get_idx_f32", Type::F32)),
866 Type::U64 => Some(("Any::get_idx_u64", Type::U64)),
867 Type::I64 => Some(("Any::get_idx_i64", Type::I64)),
868 Type::F64 => Some(("Any::get_idx_f64", Type::F64)),
869 Type::Str => Some(("Any::get_idx_str", Type::Str)),
870 _ => None,
871 }
872 }
873
874 fn list_set_idx_shortcut(elem_ty: &Type) -> Option<(&'static str, Type)> {
875 match elem_ty {
876 Type::Bool => Some(("Any::set_idx_bool", Type::Bool)),
877 Type::U8 => Some(("Any::set_idx_u8", Type::U8)),
878 Type::I8 => Some(("Any::set_idx_i8", Type::I8)),
879 Type::U16 => Some(("Any::set_idx_u16", Type::U16)),
880 Type::I16 => Some(("Any::set_idx_i16", Type::I16)),
881 Type::U32 => Some(("Any::set_idx_u32", Type::U32)),
882 Type::I32 => Some(("Any::set_idx_i32", Type::I32)),
883 Type::F32 => Some(("Any::set_idx_f32", Type::F32)),
884 Type::U64 => Some(("Any::set_idx_u64", Type::U64)),
885 Type::I64 => Some(("Any::set_idx_i64", Type::I64)),
886 Type::F64 => Some(("Any::set_idx_f64", Type::F64)),
887 Type::Str => Some(("Any::set_idx_str", Type::Str)),
888 _ => None,
889 }
890 }
891
892 fn expr_is_empty_list(&self, expr: &Expr) -> bool {
893 match &expr.kind {
894 ExprKind::Value(value) => value.is_list() && value.len() == 0,
895 ExprKind::Const(idx) => self.compiler.consts.get(*idx).is_some_and(|value| value.is_list() && value.len() == 0),
896 ExprKind::Typed { value, .. } => self.expr_is_empty_list(value),
897 _ => false,
898 }
899 }
900
901 fn closure_value(&self, ctx: &mut BuildContext, id: u32) -> Result<LocalVar> {
902 let captures = match self.compiler.symbols.get_symbol(id)?.1 {
903 Symbol::Fn { cap, .. } => cap.vars.iter().map(|idx| ctx.get_var(*idx as u32)?.get(ctx).ok_or_else(|| anyhow!("捕获变量 {} 没有值", idx))).collect::<Result<Vec<_>>>()?,
904 _ => Vec::new(),
905 };
906 Ok(LocalVar::Closure { id, captures })
907 }
908
909 fn is_spawn_fn_name(name: &str) -> bool {
910 name == "spawn" || name == "std::spawn"
911 }
912
913 fn spawn_arg_pack_len(&self, expr: &Expr) -> Option<usize> {
914 match &expr.kind {
915 ExprKind::Tuple(items) | ExprKind::List(items) => Some(items.len()),
916 ExprKind::Value(value) => value.is_list().then(|| value.len()),
917 ExprKind::Const(idx) => self.compiler.consts.get(*idx).and_then(|value| value.is_list().then(|| value.len())),
918 ExprKind::Typed { value, .. } => self.spawn_arg_pack_len(value),
919 _ => None,
920 }
921 }
922
923 fn eval_spawn_arg_pack(&mut self, ctx: &mut BuildContext, expr: &Expr) -> Result<(Value, Type)> {
924 let (ExprKind::Tuple(items) | ExprKind::List(items)) = &expr.kind else {
925 return self.eval(ctx, expr)?.get(ctx).ok_or_else(|| anyhow!("spawn closure args expression has no value"));
926 };
927 let idx = self.compiler.get_const(Dynamic::list(vec![Dynamic::Null; items.len()]));
928 let (list, _) = self.get_const_value(ctx, idx)?;
929 for (idx, item) in items.iter().enumerate() {
930 let value = self.eval(ctx, item)?.get(ctx).ok_or_else(|| anyhow!("spawn closure arg has no value: {:?}", item))?;
931 let value = self.convert(ctx, value, Type::Any)?;
932 let idx = ctx.builder.ins().iconst(types::I64, idx as i64);
933 let set_idx = self.get_fn(self.get_id("Any::set_idx")?, &[Type::Any, Type::I64, Type::Any])?;
934 self.call_for_side_effect(ctx, set_idx, vec![list, idx, value])?;
935 }
936 Ok((list, Type::Any))
937 }
938
939 fn spawn_closure(&mut self, ctx: &mut BuildContext, id: u32, captures: Vec<(Value, Type)>, args_expr: &Expr) -> Result<LocalVar> {
940 if !captures.is_empty() {
941 return Err(anyhow!("spawn closure does not support captures yet"));
942 }
943 let arg_len = self.spawn_arg_pack_len(args_expr).ok_or_else(|| anyhow!("spawn closure args must be a tuple argument pack"))?;
944 if arg_len > 8 {
945 return Err(anyhow!("spawn supports at most 8 args, got {}", arg_len));
946 }
947 let arg_tys = vec![Type::Any; arg_len];
948 let fn_info = self.gen_fn_with_params(Some(ctx), id, &arg_tys, &[])?;
949 let FnInfo::Call { fn_id, ret, .. } = fn_info else {
950 return Err(anyhow!("spawn closure target must be compiled function"));
951 };
952 let args = self.eval_spawn_arg_pack(ctx, args_expr)?;
953 let args = self.convert(ctx, args, Type::Any)?;
954 let fn_ref = self.get_fn_ref(ctx, fn_id);
955 let fn_addr = ctx.builder.ins().func_addr(ptr_type(), fn_ref);
956 let ret_ty = Self::type_ptr_const(ctx, &ret);
957 let spawn_ptr = self.spawn_ptr_fn.ok_or_else(|| anyhow!("VM spawn ptr runtime is not registered"))?;
958 let spawn_ref = self.get_fn_ref(ctx, spawn_ptr);
959 let call_inst = ctx.builder.ins().call(spawn_ref, &[fn_addr, ret_ty, args]);
960 Ok((ctx.builder.inst_results(call_inst)[0], Type::Bool).into())
961 }
962
963 pub(crate) fn call_fn(&mut self, ctx: &mut BuildContext, id: u32, obj: Option<Expr>, params: &Vec<Expr>) -> Result<LocalVar> {
964 self.call_fn_with_params(ctx, id, &[], obj, params)
965 }
966
967 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> {
968 self.call_fn_with_capture_values(ctx, id, generic_args, obj, params, None)
969 }
970
971 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> {
972 let fn_name = self.compiler.symbols.get_symbol(id).map(|(name, _)| name.clone())?;
973 if capture_values.is_none()
974 && generic_args.is_empty()
975 && obj.is_none()
976 && Self::is_spawn_fn_name(fn_name.as_str())
977 && let [target, args] = params.as_slice()
978 && let LocalVar::Closure { id, captures } = self.eval(ctx, target)?
979 {
980 return self.spawn_closure(ctx, id, captures, args);
981 }
982 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() };
983 for p in params {
984 args.push(self.eval(ctx, p)?.get(ctx).ok_or_else(|| anyhow!("函数 {} 的参数表达式没有值: {:?}", fn_name, p))?);
985 }
986 if let Some(captures) = &capture_values {
987 args.extend(captures.iter().cloned());
988 }
989 if let [list, value] = args.as_slice()
990 && fn_name.as_str() == "Any::push"
991 && let Type::List(elem_ty) = &list.1
992 && let Some((fn_name, value_ty)) = Self::list_push_shortcut(elem_ty)
993 {
994 let value = self.convert(ctx, (value.0, value.1.clone()), value_ty.clone())?;
995 let push_fn = self.get_fn(self.get_id(fn_name)?, &[Type::Any, value_ty])?;
996 self.call_for_side_effect(ctx, push_fn, vec![list.0, value])?;
997 return Ok(LocalVar::None);
998 }
999 if let [list, idx] = args.as_slice()
1000 && fn_name.as_str() == "Any::get_idx"
1001 && let Type::List(elem_ty) = &list.1
1002 && let Some((fn_name, _ret_ty)) = Self::list_get_idx_shortcut(elem_ty)
1003 {
1004 let idx = self.convert(ctx, (idx.0, idx.1.clone()), Type::I64)?;
1005 let get_idx_fn = self.get_fn(self.get_id(fn_name)?, &[Type::Any, Type::I64])?;
1006 return self.call(ctx, get_idx_fn, vec![list.0, idx]).map(|value| value.into());
1007 }
1008 if fn_name.as_str().ends_with("Vec::swap")
1009 && let Some((base, vec_ty)) = args.first().cloned()
1010 && let Some(elem_ty) = Self::vec_elem_ty(&vec_ty)
1011 {
1012 let [_, left_idx, right_idx]: [(Value, Type); 3] = args.try_into().map_err(|_| anyhow!("Vec::swap 需要 self 和两个索引参数"))?;
1013 self.swap_vec_index(ctx, base, left_idx, right_idx, &elem_ty)?;
1014 return Ok(LocalVar::None);
1015 }
1016 let visible_arg_len = args.len() - capture_values.as_ref().map(|captures| captures.len()).unwrap_or(0);
1017 let arg_tys: Vec<Type> = args.iter().take(visible_arg_len).map(|(_, ty)| ty.clone()).collect();
1018 let fn_info = match if generic_args.is_empty() { self.get_fn(id, &arg_tys) } else { Err(anyhow!("generic function needs specialization")) } {
1019 Ok(info) => info,
1020 Err(_) => self.gen_fn_with_params(Some(ctx), id, &arg_tys, generic_args).map_err(|e| {
1021 log::error!("{:?}", self.compiler.symbols.get_symbol(id));
1022 e
1023 })?,
1024 };
1025 match &fn_info {
1026 FnInfo::Call { fn_id: _, arg_tys: want_tys, caps, ret, context: _ } => {
1027 let mut args = self.adjust_args(ctx, args, want_tys)?;
1028 if capture_values.is_none() {
1029 for c in caps {
1030 args.push(ctx.get_var(*c as u32)?.get(ctx).unwrap().0);
1031 }
1032 }
1033 if ret.is_void() {
1034 self.call_for_side_effect(ctx, fn_info, args)?;
1035 Ok(LocalVar::None)
1036 } else {
1037 self.call(ctx, fn_info, args).map(|r| r.into())
1038 }
1039 }
1040 _ => panic!("不可能编译出 inline 函数"),
1041 }
1042 }
1043
1044 pub(crate) fn eval(&mut self, ctx: &mut BuildContext, expr: &Expr) -> Result<LocalVar> {
1045 self.eval_with_expected(ctx, expr, None)
1046 }
1047
1048 fn eval_with_expected(&mut self, ctx: &mut BuildContext, expr: &Expr, expected: Option<&Type>) -> Result<LocalVar> {
1049 if let Some(ty) = expected
1050 && self.expr_is_empty_list(expr)
1051 && let Some(value) = Self::empty_typed_list(ty)
1052 {
1053 let idx = self.compiler.get_const(value);
1054 let (val, _) = self.get_const_value(ctx, idx)?;
1055 return Ok(LocalVar::Value { val, ty: ty.clone() });
1056 }
1057 match &expr.kind {
1058 ExprKind::Value(v) => Ok(ctx.get_const(v)?.into()),
1059 ExprKind::Var(idx) => {
1060 let v = ctx.get_var(*idx)?;
1061 Ok(v)
1062 }
1063 ExprKind::Unary { op, value } => {
1064 let v = self.eval(ctx, value)?.get(ctx).unwrap();
1065 if op == &UnaryOp::Not && v.1.is_any() {
1066 let cond = self.bool_value(ctx, v)?;
1067 let zero = ctx.builder.ins().iconst(types::I8, 0);
1068 let one = ctx.builder.ins().iconst(types::I8, 1);
1069 let is_zero = ctx.builder.ins().icmp_imm(IntCC::Equal, cond, 0);
1070 Ok((ctx.builder.ins().select(is_zero, one, zero), Type::Bool).into())
1071 } else {
1072 Ok(Self::unary(ctx, v, op.clone())?.into())
1073 }
1074 }
1075 ExprKind::Binary { left, op, right } => {
1076 if op == &BinaryOp::Assign {
1077 let expected = self.assignment_target_ty(ctx, left);
1078 match self.eval_with_expected(ctx, right, expected.as_ref()) {
1079 Ok(value) => self.assign(ctx, left, value).map(|v| v.into()),
1080 Err(e) => {
1081 log::error!("assign error {:?}", e);
1082 Err(e)
1083 }
1084 }
1085 } else {
1086 let assign_expr = if op.is_assign() { Some(left.clone()) } else { None };
1087 let assign_expected = if op.is_assign() { self.assignment_target_ty(ctx, left) } else { None };
1088 let left = match self.eval(ctx, left)?.get(ctx) {
1089 Some(left) => left,
1090 None => return Err(anyhow!("binary left has no value: {:?}", left)),
1091 };
1092 if op == &BinaryOp::Idx {
1093 let left_ty = self.compiler.symbols.get_type(&left.1).unwrap_or_else(|_| left.1.clone());
1094 let left = (left.0, left_ty);
1095 if let Type::Struct { params: _, fields: _ } = &left.1 {
1096 let idx = self.struct_field_index(&left.1, right)?;
1097 return self.load_struct_field(ctx, left.0, idx, &left.1).map(|r| r.into());
1098 }
1099 if let Some(elem_ty) = Self::vec_elem_ty(&left.1) {
1100 let idx = if right.is_value() {
1101 let idx = right.clone().value()?.as_int().ok_or(anyhow!("Vec 索引必须是整数"))?;
1102 (ctx.builder.ins().iconst(types::I64, idx), Type::I64)
1103 } else {
1104 self.eval(ctx, right)?.get(ctx).ok_or(anyhow!("Vec 索引没有值"))?
1105 };
1106 return self.load_vec_index(ctx, left.0, idx, &elem_ty).map(|r| r.into());
1107 }
1108 if let Some(elem_ty) = Self::array_elem_ty(&left.1) {
1109 let idx = if right.is_value() {
1110 let idx = right.clone().value()?.as_int().ok_or(anyhow!("array index must be integer"))?;
1111 (ctx.builder.ins().iconst(types::I64, idx), Type::I64)
1112 } else {
1113 self.eval(ctx, right)?.get(ctx).ok_or(anyhow!("array index has no value"))?
1114 };
1115 return self.load_array_index(ctx, left.0, idx, &elem_ty).map(|r| r.into());
1116 }
1117 if right.is_value() {
1118 let right_value = right.clone().value()?;
1119 if let Some(idx) = right_value.as_int() {
1120 let idx = ctx.builder.ins().iconst(types::I64, idx);
1121 self.call(ctx, self.get_method(&left.1, "get_idx")?, vec![left.0, idx]).map(|r| r.into())
1122 } else {
1123 let key = ctx.get_const(&right_value)?;
1124 self.call(ctx, self.get_method(&left.1, "get_key")?, vec![left.0, key.0]).map(|r| r.into())
1125 }
1126 } else if let ExprKind::Range { start, stop, inclusive } = &right.kind {
1127 let start = self.eval(ctx, start)?.get(ctx).ok_or(anyhow!("range start has no value"))?;
1128 let start = self.convert(ctx, start, Type::I64)?;
1129 let stop = self.eval(ctx, stop)?.get(ctx).ok_or(anyhow!("range stop has no value"))?;
1130 let stop = self.convert(ctx, stop, Type::Any)?;
1131 let inclusive = ctx.builder.ins().iconst(types::I8, i64::from(*inclusive));
1132 self.call(ctx, self.get_method(&left.1, "slice")?, vec![left.0, start, stop, inclusive]).map(|r| r.into())
1133 } else {
1134 let right = self.eval(ctx, right)?.get(ctx).ok_or(anyhow!("非Value {:?}", right))?;
1135 if right.1.is_any() || right.1.is_str() {
1136 let right = self.convert(ctx, right, Type::Any)?;
1137 self.call(ctx, self.get_method(&left.1, "get_key")?, vec![left.0, right]).map(|r| r.into())
1138 } else {
1139 let right = self.convert(ctx, right, Type::I64)?;
1140 if let Type::List(elem_ty) = &left.1
1141 && let Some((fn_name, _ret_ty)) = Self::list_get_idx_shortcut(elem_ty)
1142 {
1143 let get_idx_fn = self.get_fn(self.get_id(fn_name)?, &[Type::Any, Type::I64])?;
1144 return self.call(ctx, get_idx_fn, vec![left.0, right]).map(|r| r.into());
1145 }
1146 self.call(ctx, self.get_method(&left.1, "get_idx")?, vec![left.0, right]).map(|r| r.into())
1147 }
1148 }
1149 } else {
1150 let result = self.binary_with_expected(ctx, left, op.clone(), right, assign_expected.as_ref().or(expected))?.into();
1151 if let Some(expr) = assign_expr { self.assign(ctx, &expr, result).map(|r| r.into()) } else { Ok(result.into()) }
1152 }
1153 }
1154 }
1155 ExprKind::Call { obj, params } => {
1156 if let ExprKind::AssocId { id, params: generic_args } = &obj.kind {
1157 self.call_fn_with_params(ctx, *id, generic_args, None, params)
1158 } else if let ExprKind::Id(id, obj) = &obj.kind {
1159 self.call_fn(ctx, *id, obj.as_ref().map(|o| *o.clone()), params)
1160 } else if obj.is_value() {
1161 return Ok(LocalVar::None);
1163 } else {
1164 if obj.is_idx() {
1165 let (left, _, right) = obj.clone().binary().unwrap();
1166 let left = self.eval(ctx, &left)?.get(ctx).ok_or(anyhow!("obj {:?}", obj))?;
1167 let ty = self.compiler.symbols.get_type(&left.1)?;
1168 if let Some(name) = self.get_dynamic(&right) {
1169 if name.as_str() == "swap"
1170 && let Some(elem_ty) = Self::vec_elem_ty(&ty)
1171 {
1172 let [left_idx, right_idx]: [(Value, Type); 2] =
1173 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 需要两个索引参数"))?;
1174 self.swap_vec_index(ctx, left.0, left_idx, right_idx, &elem_ty)?;
1175 return Ok(LocalVar::None);
1176 }
1177 let mut args = vec![left];
1178 for p in params {
1179 args.push(self.eval(ctx, p)?.get(ctx).ok_or_else(|| anyhow!("动态方法 {:?} 的参数表达式没有值: {:?}", name, p))?);
1180 }
1181 let (_, method_ty) = self.compiler.get_field(&ty, name.as_str())?;
1182 let Type::Symbol { id, .. } = method_ty else {
1183 return Err(anyhow!("不是成员函数"));
1184 };
1185 let arg_tys: Vec<Type> = args.iter().map(|(_, ty)| ty.clone()).collect();
1186 let method = self.get_fn(id, &arg_tys).or_else(|_| self.gen_fn_with_params(Some(ctx), id, &arg_tys, &[]))?;
1187 let args = self.adjust_args(ctx, args, method.arg_tys()?)?;
1188 self.call(ctx, method, args).map(|r| r.into())
1189 } else {
1190 self.eval(ctx, obj)
1191 }
1192 } else {
1193 let val = self.eval(ctx, obj)?;
1194 if let LocalVar::Closure { id, captures } = val {
1195 return self.call_fn_with_capture_values(ctx, id, &[], None, params, Some(captures));
1196 }
1197 panic!("暂未实现 {:?}", val)
1198 }
1199 }
1200 }
1201 ExprKind::Typed { value, ty } => {
1202 if let Type::Struct { params: _, fields: _ } = ty
1203 && let ExprKind::List(items) = &value.kind
1204 {
1205 return Ok((self.init_struct_from_items(ctx, items, ty)?, ty.clone()).into());
1206 }
1207 if let Type::Array(_, _) = ty
1208 && let ExprKind::List(items) = &value.kind
1209 {
1210 return Ok((self.init_array_from_items(ctx, items, ty)?, ty.clone()).into());
1211 }
1212 let evaluated = self.eval(ctx, value)?;
1213 if evaluated.is_closure() {
1214 return Ok(evaluated);
1215 }
1216 let vt = if let Some(vt) = evaluated.get(ctx) {
1217 vt
1218 } else if ty.is_any() {
1219 let idx = self.compiler.get_const(Dynamic::Null);
1220 self.get_const_value(ctx, idx)?
1221 } else {
1222 return Ok(LocalVar::None);
1223 };
1224 if let Type::Struct { params: _, fields: _ } = ty
1225 && !self.is_opaque_custom_ty(ty)
1226 {
1227 if &vt.1 == ty {
1228 Ok(vt.into())
1229 } else if vt.1.is_any() {
1230 Ok((self.init_struct_from_dynamic(ctx, vt, ty)?, ty.clone()).into())
1231 } else {
1232 Err(anyhow!("cannot convert {:?} to {:?}", vt.1, ty))
1233 }
1234 } else if &vt.1 != ty {
1235 Ok((self.convert(ctx, vt, ty.clone())?, ty.clone()).into())
1236 } else {
1237 Ok(vt.into())
1238 }
1239 }
1240 ExprKind::List(_) => Err(anyhow!("未实现 {:?}", expr)),
1241 ExprKind::Repeat { value, len } => {
1242 let value = self.eval(ctx, value)?.get(ctx).ok_or(anyhow!("repeat value has no value"))?;
1243 let Type::ConstInt(len) = len else {
1244 return Err(anyhow!("repeat length must be a compile-time integer"));
1245 };
1246 let len = u32::try_from(*len).map_err(|_| anyhow!("repeat length out of range"))?;
1247 self.init_repeat_array(ctx, value, len).map(|r| r.into())
1248 }
1249 ExprKind::Const(idx) => self.get_const_value(ctx, *idx).map(|v| v.into()),
1250 ExprKind::Id(id, _) => self.closure_value(ctx, *id),
1251 ExprKind::AssocId { id, .. } => self.closure_value(ctx, *id),
1252 expr => {
1253 panic!("未实现 {:?}", expr)
1255 }
1256 }
1257 }
1258
1259 fn gen_loop(&mut self, ctx: &mut BuildContext, cond: Option<&Expr>, body: &Stmt, f: Option<impl FnMut(&mut BuildContext)>) -> Result<()> {
1260 let loop_block = ctx.builder.create_block();
1261 let end_block = ctx.builder.create_block();
1262 if let Some(cond) = cond {
1263 let start_block = ctx.builder.create_block();
1264 ctx.builder.ins().jump(start_block, &[]);
1265 ctx.builder.switch_to_block(start_block);
1266 let cond = self.eval(ctx, cond)?.get(ctx).unwrap();
1267 let cond = self.bool_value(ctx, cond)?;
1268 let continue_block = if f.is_some() { ctx.builder.create_block() } else { start_block };
1269 ctx.builder.ins().brif(cond, loop_block, &[], end_block, &[]);
1270 ctx.builder.switch_to_block(loop_block);
1271 let body_terminated = self.gen_stmt(ctx, body, Some(end_block), Some(continue_block))?;
1272 if !body_terminated {
1273 ctx.builder.ins().jump(continue_block, &[]);
1274 }
1275 ctx.builder.seal_block(loop_block);
1276 f.map(|mut f| {
1277 ctx.builder.switch_to_block(continue_block);
1278 f(ctx);
1279 ctx.builder.ins().jump(start_block, &[]);
1280 ctx.builder.seal_block(continue_block);
1281 });
1282 } else {
1283 ctx.builder.ins().jump(loop_block, &[]);
1284 ctx.builder.switch_to_block(loop_block);
1285 let body_terminated = self.gen_stmt(ctx, body, Some(end_block), Some(loop_block))?;
1286 if !body_terminated {
1287 ctx.builder.ins().jump(loop_block, &[]);
1288 }
1289 ctx.builder.seal_block(loop_block);
1290 }
1291 ctx.builder.switch_to_block(end_block);
1292 Ok(())
1293 }
1294
1295 pub(crate) fn gen_stmt(&mut self, ctx: &mut BuildContext, stmt: &Stmt, break_block: Option<Block>, continue_block: Option<Block>) -> Result<bool> {
1296 match &stmt.kind {
1297 StmtKind::Expr(expr, _) => {
1298 let _ = self.eval(ctx, expr)?;
1299 }
1300 StmtKind::Break => {
1301 ctx.builder.ins().jump(break_block.unwrap(), &[]);
1302 return Ok(true);
1303 }
1304 StmtKind::Continue => {
1305 ctx.builder.ins().jump(continue_block.unwrap(), &[]);
1306 return Ok(true);
1307 }
1308 StmtKind::Return(expr) => {
1309 if let Some(expr) = expr {
1310 let value = self.eval(ctx, expr)?;
1311 let value = value.get(ctx);
1312 self.return_value(ctx, value)?;
1313 } else {
1314 self.return_value(ctx, None)?;
1315 }
1316 return Ok(true);
1317 }
1318 StmtKind::If { cond, then_body, else_body } => {
1319 self.declare_assigned_vars(ctx, then_body)?;
1320 if let Some(else_body) = else_body {
1321 self.declare_assigned_vars(ctx, else_body)?;
1322 }
1323 let then_block = ctx.builder.create_block();
1324 let cond = self.eval(ctx, cond)?.get(ctx).ok_or(anyhow!("未知的条件 {:?}", cond))?;
1325 let cond = self.bool_value(ctx, cond)?;
1326 let mut end_block = None;
1327 if let Some(else_body) = else_body {
1328 let else_block = ctx.builder.create_block();
1329 ctx.builder.ins().brif(cond, then_block, &[], else_block, &[]);
1330 ctx.builder.switch_to_block(then_block);
1331 if !self.gen_stmt(ctx, then_body, break_block, continue_block)? {
1332 let block = ctx.builder.create_block();
1333 ctx.builder.ins().jump(block, &[]);
1334 end_block = Some(block);
1335 }
1336 ctx.builder.switch_to_block(else_block);
1337 if !self.gen_stmt(ctx, else_body, break_block, continue_block)? {
1338 if end_block.is_none() {
1339 end_block = Some(ctx.builder.create_block());
1340 }
1341 ctx.builder.ins().jump(end_block.unwrap(), &[]);
1342 }
1343 ctx.builder.seal_block(else_block);
1344 } else {
1345 let block = ctx.builder.create_block();
1346 ctx.builder.ins().brif(cond, then_block, &[], block, &[]);
1347 end_block = Some(block);
1348 ctx.builder.switch_to_block(then_block);
1349 if !self.gen_stmt(ctx, then_body, break_block, continue_block)? {
1350 ctx.builder.ins().jump(end_block.unwrap(), &[]); }
1352 }
1353 if let Some(block) = end_block {
1354 ctx.builder.switch_to_block(block);
1355 }
1356 ctx.builder.seal_block(then_block);
1357 return Ok(end_block.is_none());
1358 }
1359 StmtKind::Block(stmts) => {
1360 for (idx, stmt) in stmts.iter().enumerate() {
1361 let r = self.gen_stmt(ctx, stmt, break_block, continue_block)?;
1362 if idx == stmts.len() - 1 {
1363 return Ok(r);
1364 }
1365 }
1366 }
1367 StmtKind::While { cond, body } => {
1368 self.declare_assigned_vars(ctx, body)?;
1369 let no_loop: Option<fn(&mut BuildContext)> = None;
1370 self.gen_loop(ctx, Some(cond), body, no_loop)?;
1371 }
1372 StmtKind::Loop(body) => {
1373 self.declare_assigned_vars(ctx, body)?;
1374 let no_loop: Option<fn(&mut BuildContext)> = None;
1375 self.gen_loop(ctx, None, body, no_loop)?;
1376 }
1377 StmtKind::For { pat, range, body } => {
1378 if let ExprKind::Range { start, stop, inclusive } = &range.kind {
1379 if let PatternKind::Var { idx, .. } = &pat.kind {
1380 let start = self.eval(ctx, start)?;
1381 ctx.set_var(*idx, start)?;
1382 self.declare_assigned_vars(ctx, body)?;
1383 let op = if *inclusive { BinaryOp::Le } else { BinaryOp::Lt };
1384 let cond = Self::expr(ExprKind::Binary { left: Box::new(Self::expr(ExprKind::Var(*idx))), op, right: Box::new(stop.as_ref().clone()) });
1385 self.gen_loop(
1386 ctx,
1387 Some(&cond),
1388 body,
1389 Some(|ctx: &mut BuildContext| {
1390 let v = ctx.get_var(*idx).unwrap().get(ctx).unwrap();
1391 let step = if v.1 == Type::I64 {
1392 ctx.builder.ins().iconst(types::I64, 1)
1393 } else if v.1 == Type::I32 {
1394 ctx.builder.ins().iconst(types::I32, 1)
1395 } else {
1396 panic!("{:?} 不能作为增量", v.1)
1397 };
1398 let vt = (ctx.builder.ins().iadd(v.0, step), v.1).into();
1399 let _ = ctx.set_var(*idx, vt);
1400 }),
1401 )?;
1402 }
1403 } else if let PatternKind::Var { idx, .. } = &pat.kind {
1404 let vt = self.eval(ctx, range)?.get(ctx).unwrap();
1405 if vt.1.is_any() {
1406 let iter = self.call(ctx, self.get_method(&vt.1, "iter")?, vec![vt.0])?;
1407 let next = self.get_method(&vt.1, "next")?;
1408 let next_id = next.get_id()?;
1409 let start = self.call(ctx, next, vec![iter.0])?;
1410 ctx.set_var(*idx, start.into())?;
1411 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))) });
1412 self.gen_loop(
1413 ctx,
1414 Some(&cond),
1415 body,
1416 Some(|ctx: &mut BuildContext| {
1417 let fn_ref = ctx.get_fn_ref(next_id).unwrap();
1418 let call_inst = ctx.builder.ins().call(fn_ref, &[iter.0]);
1419 let ret = ctx.builder.inst_results(call_inst)[0];
1420 let _ = ctx.set_var(*idx, (ret, Type::Any).into());
1421 }),
1422 )?;
1423 }
1424 } else if let PatternKind::Tuple(pats) = &pat.kind {
1425 let vt = self.eval(ctx, range)?.get(ctx).unwrap();
1426 if vt.1.is_any() && pats.len() == 2 {
1427 let iter = self.call(ctx, self.get_method(&vt.1, "iter")?, vec![vt.0])?;
1429 let next = self.get_method(&vt.1, "next")?;
1430 let next_id = next.get_id()?;
1431 let get_idx = self.get_method(&vt.1, "get_idx")?.get_id()?;
1432
1433 let start = self.call(ctx, next, vec![iter.0])?;
1434 let key_idx = ctx.builder.ins().iconst(types::I64, 0);
1435 let key = self.call(ctx, self.get_method(&start.1, "get_idx")?, vec![start.0, key_idx])?;
1436 let value_idx = ctx.builder.ins().iconst(types::I64, 1);
1437 let value = self.call(ctx, self.get_method(&start.1, "get_idx")?, vec![start.0, value_idx])?;
1438 ctx.set_var(pats[0].var().unwrap(), key.into())?;
1439 ctx.set_var(pats[1].var().unwrap(), value.into())?;
1440 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))) });
1441 self.gen_loop(
1442 ctx,
1443 Some(&cond),
1444 body,
1445 Some(|ctx: &mut BuildContext| {
1446 let fn_ref = ctx.get_fn_ref(next_id).unwrap();
1447 let call_inst = ctx.builder.ins().call(fn_ref, &[iter.0]);
1448 let ret = ctx.builder.inst_results(call_inst)[0];
1449
1450 let fn_ref = ctx.get_fn_ref(get_idx).unwrap();
1451 let call_inst = ctx.builder.ins().call(fn_ref, &[ret, key_idx]);
1452 let key_ret = ctx.builder.inst_results(call_inst)[0];
1453 let call_inst = ctx.builder.ins().call(fn_ref, &[ret, value_idx]);
1454 let value_ret = ctx.builder.inst_results(call_inst)[0];
1455
1456 let _ = ctx.set_var(pats[0].var().unwrap(), (key_ret, Type::Any).into());
1457 let _ = ctx.set_var(pats[1].var().unwrap(), (value_ret, Type::Any).into());
1458 }),
1459 )?;
1460 }
1461 }
1462 }
1463 _ => {
1464 panic!("未实现 {:?}", stmt)
1465 }
1466 }
1467 Ok(false)
1468 }
1469}