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