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