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