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, ptr_type};
9use cranelift::prelude::*;
10use cranelift_jit::{JITBuilder, JITModule};
11use cranelift_module::{DataDescription, DataId, 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<DataId>>,
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) struct_from_ptr_fn: Option<FuncId>,
35}
36
37pub(crate) struct PendingFn {
41 pub name: SmolStr,
42 pub symbol_id: u32,
43 pub fn_id: FuncId,
44 pub arg_tys: Vec<Type>,
45 pub ret_ty: Type,
46 pub body: Stmt,
47}
48
49impl JITRunTime {
50 fn expr(kind: ExprKind) -> Expr {
51 Expr::new(kind, Span::default())
52 }
53
54 fn stmt(kind: StmtKind) -> Stmt {
55 Stmt::new(kind, Span::default())
56 }
57
58 pub fn load(&mut self, code: Vec<u8>, arg_name: SmolStr) -> Result<(i64, Type)> {
59 let stmts = Compiler::parse_code(code)?;
60 self.compiler.clear();
61 self.compiler.symbols.add_module("__console".into());
62 let mut cap = Capture::default();
63 let body = Self::stmt(StmtKind::Block(self.compiler.compile_fn(&[arg_name], &mut vec![Type::Any], Self::stmt(StmtKind::Block(stmts)), &mut cap)?));
64 self.compiler.tys.push(Type::Any);
65 let ret_ty = self.compiler.infer_stmt(&body)?;
66 self.compiler.clear();
67 let fn_id = self.compile_fn(None, &[Type::Any], ret_ty.clone(), &body)?;
68 self.compiler.clear();
69 self.compiler.symbols.pop_module();
70 self.module.finalize_definitions()?;
71 Ok((self.module.get_finalized_function(fn_id) as i64, ret_ty))
72 }
73
74 pub fn import_code(&mut self, name: &str, code: Vec<u8>) -> Result<()> {
75 log::info!("import {}", name);
76 let _ = self.compiler.import_code(name, code)?;
77 Ok(())
78 }
79
80 #[cfg(feature = "ir-disassembly")]
81 pub fn disassemble_ir(&mut self, name: &str) -> Result<String> {
82 if let Some(ir) = self.ir_disassembly.get(name) {
83 return Ok(ir.clone());
84 }
85 let id = self.get_id(name)?;
86 let (_, symbol) = self.compiler.symbols.get_symbol(id)?;
87 if let Symbol::Fn { ty, .. } = symbol
88 && let Type::Fn { tys, .. } = ty
89 && tys.is_empty()
90 {
91 let _ = self.gen_fn(None, id, &[])?;
92 }
93 self.ir_disassembly.get(name).cloned().ok_or_else(|| anyhow!("未找到函数 {} 的 Cranelift IR;如果它需要参数,请先触发对应实例化", name))
94 }
95
96 pub fn get_fn_ptr(&mut self, name: &str, arg_tys: &[Type]) -> Result<(*const u8, Type)> {
97 let main_id = self.get_id(name)?;
98 let fn_info = self.gen_fn(None, main_id, arg_tys)?;
99 Ok((self.module.get_finalized_function(fn_info.get_id()?), fn_info.get_type()?))
100 }
101
102 pub fn get_const_value(&mut self, ctx: &mut BuildContext, idx: usize) -> Result<(Value, Type)> {
103 if self.consts.len() < idx + 1 {
104 self.consts.resize(idx + 1, None);
105 }
106 let id = if let Some(id) = self.consts.get(idx).cloned().unwrap_or(None) {
107 id
108 } else {
109 let id = self.module.declare_anonymous_data(true, false)?;
110 let mut desc = DataDescription::new();
111 let c = Box::new(self.compiler.consts[idx].deep_clone()); let ptr = Box::into_raw(c);
113 desc.define((ptr as i64).to_le_bytes().into());
114 self.module.define_data(id, &desc)?;
115 self.consts[idx] = Some(id);
116 id
117 };
118 let c = self.module.declare_data_in_func(id, &mut ctx.builder.func);
119 let addr = ctx.builder.ins().global_value(ptr_type(), c);
120 let value = ctx.builder.ins().load(ptr_type(), MemFlags::new(), addr, 0); Ok((self.call(ctx, self.get_method(&Type::Any, "clone")?, vec![value])?.0, Type::Any))
122 }
123
124 fn get_null_value(&mut self, ctx: &mut BuildContext) -> Result<(Value, Type)> {
125 let const_idx = self.compiler.get_const(Dynamic::Null);
126 self.get_const_value(ctx, const_idx)
127 }
128
129 pub fn get_dynamic(&self, expr: &Expr) -> Option<Dynamic> {
130 if let ExprKind::Const(idx) = &expr.kind { self.compiler.consts.get(*idx).cloned() } else { None }
131 }
132
133 pub fn get_method(&self, ty: &Type, name: &str) -> Result<FnInfo> {
134 self.compiler.get_field(ty, name).and_then(|(_, ty)| if let Type::Symbol { id, params: _ } = ty { self.get_fn(id, &[]) } else { Err(anyhow!("不是成员函数")) })
135 }
136
137 fn is_fn_field_type(&self, ty: &Type) -> bool {
138 match ty {
139 Type::Symbol { id, .. } => self.compiler.symbols.get_symbol(*id).map(|(_, symbol)| symbol.is_fn()).unwrap_or(false),
140 Type::Fn { .. } => true,
141 _ => false,
142 }
143 }
144
145 pub(crate) fn is_opaque_custom_ty(&self, ty: &Type) -> bool {
146 let ty = self.compiler.symbols.get_type(ty).unwrap_or_else(|_| ty.clone());
147 matches!(ty, Type::Struct { fields, .. } if !fields.is_empty() && fields.iter().all(|(_, field_ty)| self.is_fn_field_type(field_ty)))
148 }
149
150 pub(crate) fn is_aggregate_ty(&self, ty: &Type) -> bool {
151 (ty.is_struct() && !self.is_opaque_custom_ty(ty)) || ty.is_array()
152 }
153
154 pub fn get_id(&self, name: &str) -> Result<u32> {
155 self.compiler.symbols.get_id(name)
156 }
157
158 pub fn get_type(&mut self, name: &str, arg_tys: &[Type]) -> Result<Type> {
159 let id = self.get_id(name)?;
160 if self.compiler.symbols.symbols.get(name).map(|s| s.is_fn()).unwrap_or(false) {
161 return self.compiler.infer_fn(id, arg_tys);
162 }
163 self.compiler.symbols.get_type(&Type::Symbol { id, params: Vec::new() })
164 }
165
166 pub fn new<F: FnMut(&mut JITBuilder)>(mut f: F) -> Self {
167 let native_symbols = Arc::new(RwLock::new(HashMap::<String, usize>::new()));
168 let lookup_symbols = native_symbols.clone();
169 let mut builder = JITBuilder::new(cranelift_module::default_libcall_names()).unwrap();
170 builder.symbol_lookup_fn(Box::new(move |name| lookup_symbols.read().unwrap().get(name).copied().map(|ptr| ptr as *const u8)));
171 f(&mut builder);
172 let module = JITModule::new(builder);
173 PTR_TYPE.get_or_init(|| module.isa().pointer_type());
174 let fns = BTreeMap::<u32, FnVariant>::new();
175 Self {
176 compiler: Compiler::new(),
177 fns,
178 sigs: Vec::new(),
179 native_symbols,
180 owner: Weak::new(),
181 pending_fns: VecDeque::new(),
182 compile_depth: 0,
183 #[cfg(feature = "ir-disassembly")]
184 ir_disassembly: BTreeMap::new(),
185 module,
186 consts: Vec::new(),
187 scope_enter_fn: None,
188 scope_exit_void_fn: None,
189 scope_exit_dynamic_fn: None,
190 scope_exit_bytes_fn: None,
191 struct_alloc_fn: None,
192 struct_from_ptr_fn: None,
193 }
194 }
195
196 pub(crate) fn set_owner(&mut self, owner: Weak<Mutex<JITRunTime>>) {
197 self.owner = owner;
198 }
199
200 pub(crate) fn owner_context_ptr(&self) -> usize {
201 &self.owner as *const Weak<Mutex<JITRunTime>> as usize
202 }
203
204 fn unary(ctx: &mut BuildContext, left: (Value, Type), op: UnaryOp) -> Result<(Value, Type)> {
205 match op {
206 UnaryOp::Neg => {
207 if left.1.is_int() || left.1.is_uint() {
208 if left.1.width() == 8 {
209 let zero = ctx.builder.ins().iconst(types::I64, 0);
210 return Ok((ctx.builder.ins().isub(zero, left.0), Type::I64));
211 } else if left.1.width() == 4 {
212 let zero = ctx.builder.ins().iconst(types::I32, 0);
213 return Ok((ctx.builder.ins().isub(zero, left.0), Type::I32));
214 }
215 } else if left.1.is_float() {
216 return Ok((ctx.builder.ins().fneg(left.0), left.1));
217 }
218 }
219 UnaryOp::Not => {
220 if left.1.is_any() {
221 return Err(anyhow!("defer any-bool not handling"));
222 }
223 let zero = ctx.builder.ins().iconst(types::I8, 0);
224 let one = ctx.builder.ins().iconst(types::I8, 1);
225 let is_zero = ctx.builder.ins().icmp_imm(IntCC::Equal, left.0, 0);
226 return Ok((ctx.builder.ins().select(is_zero, one, zero), Type::Bool));
227 }
228 _ => {}
229 }
230 Err(anyhow!("未实现 {:?} {:?}", left, op))
231 }
232
233 pub(crate) fn call(&mut self, ctx: &mut BuildContext, fn_info: FnInfo, args: Vec<Value>) -> Result<(Value, Type)> {
234 match fn_info {
235 FnInfo::Call { fn_id, arg_tys: _, caps: _, ret, context } => {
236 let fn_ref = self.get_fn_ref(ctx, fn_id);
237 let args = self.add_context_arg(ctx, context, args);
238 let call_inst = ctx.builder.ins().call(fn_ref, &args);
239 if !ret.is_void() { Ok((ctx.builder.inst_results(call_inst)[0], ret)) } else { Err(anyhow!("没有返回值")) }
240 }
241 FnInfo::Inline { fn_ptr, arg_tys: _ } => fn_ptr(Some(ctx), args).map(|(v, t)| (v.unwrap(), t)),
242 }
243 }
244
245 pub(crate) fn scope_enter(&mut self, ctx: &mut BuildContext) -> Result<()> {
246 let fn_id = self.scope_enter_fn.ok_or_else(|| anyhow!("VM scope enter runtime is not registered"))?;
247 let fn_ref = self.get_fn_ref(ctx, fn_id);
248 ctx.builder.ins().call(fn_ref, &[]);
249 Ok(())
250 }
251
252 fn scope_exit_void(&mut self, ctx: &mut BuildContext) -> Result<()> {
253 let fn_id = self.scope_exit_void_fn.ok_or_else(|| anyhow!("VM scope exit runtime is not registered"))?;
254 let fn_ref = self.get_fn_ref(ctx, fn_id);
255 ctx.builder.ins().call(fn_ref, &[]);
256 Ok(())
257 }
258
259 fn return_value(&mut self, ctx: &mut BuildContext, value: Option<(Value, Type)>) -> Result<()> {
260 let ret_ty = ctx.ret_ty.clone();
261 if ret_ty.is_void() {
262 self.scope_exit_void(ctx)?;
263 ctx.builder.ins().return_(&[]);
264 return Ok(());
265 }
266
267 let Some((value, value_ty)) = value else {
268 self.scope_exit_void(ctx)?;
269 ctx.builder.ins().return_(&[]);
270 return Ok(());
271 };
272
273 if ret_ty.is_any() {
274 let value = self.convert(ctx, (value, value_ty), Type::Any)?;
275 let fn_id = self.scope_exit_dynamic_fn.ok_or_else(|| anyhow!("VM dynamic return runtime is not registered"))?;
276 let fn_ref = self.get_fn_ref(ctx, fn_id);
277 let call_inst = ctx.builder.ins().call(fn_ref, &[value]);
278 let promoted = ctx.builder.inst_results(call_inst)[0];
279 ctx.builder.ins().return_(&[promoted]);
280 } else if self.is_aggregate_ty(&ret_ty) {
281 let value = self.convert(ctx, (value, value_ty), ret_ty.clone())?;
282 let size = ctx.builder.ins().iconst(types::I64, ret_ty.width() as i64);
283 let fn_id = self.scope_exit_bytes_fn.ok_or_else(|| anyhow!("VM aggregate return runtime is not registered"))?;
284 let fn_ref = self.get_fn_ref(ctx, fn_id);
285 let call_inst = ctx.builder.ins().call(fn_ref, &[value, size]);
286 let promoted = ctx.builder.inst_results(call_inst)[0];
287 ctx.builder.ins().return_(&[promoted]);
288 } else {
289 let value = self.convert(ctx, (value, value_ty), ret_ty)?;
290 self.scope_exit_void(ctx)?;
291 ctx.builder.ins().return_(&[value]);
292 }
293 Ok(())
294 }
295
296 fn call_for_side_effect(&mut self, ctx: &mut BuildContext, fn_info: FnInfo, args: Vec<Value>) -> Result<()> {
297 match fn_info {
298 FnInfo::Call { fn_id, arg_tys: _, caps: _, ret: _, context } => {
299 let fn_ref = self.get_fn_ref(ctx, fn_id);
300 let args = self.add_context_arg(ctx, context, args);
301 ctx.builder.ins().call(fn_ref, &args);
302 Ok(())
303 }
304 FnInfo::Inline { fn_ptr, arg_tys: _ } => fn_ptr(Some(ctx), args).map(|_| ()),
305 }
306 }
307
308 fn add_context_arg(&mut self, ctx: &mut BuildContext, context: Option<usize>, mut args: Vec<Value>) -> Vec<Value> {
309 if let Some(context) = context {
310 let context = ctx.builder.ins().iconst(ptr_type(), context as i64);
311 args.insert(0, context);
312 }
313 args
314 }
315
316 pub(crate) fn short_circuit_logic(&mut self, ctx: &mut BuildContext, left: (Value, Type), op: BinaryOp, right: &Expr) -> Result<(Value, Type)> {
317 let is_any = left.1.is_any();
318 if is_any {
319 let left_cond = self.bool_value(ctx, left.clone())?;
320 let rhs_block = ctx.builder.create_block();
321 let short_block = ctx.builder.create_block();
322 let end_block = ctx.builder.create_block();
323 ctx.builder.append_block_param(end_block, ptr_type());
324
325 match op {
326 BinaryOp::And => {
327 ctx.builder.ins().brif(left_cond, rhs_block, &[], short_block, &[]);
328 }
329 BinaryOp::Or => {
330 ctx.builder.ins().brif(left_cond, short_block, &[], rhs_block, &[]);
331 }
332 _ => unreachable!(),
333 }
334
335 ctx.builder.switch_to_block(rhs_block);
336 let right = self.eval(ctx, right)?.get(ctx).unwrap();
337 let right_any = self.convert(ctx, right, Type::Any)?;
338 ctx.builder.ins().jump(end_block, &[cranelift::codegen::ir::BlockArg::Value(right_any)]);
339 ctx.builder.seal_block(rhs_block);
340
341 ctx.builder.switch_to_block(short_block);
342 ctx.builder.ins().jump(end_block, &[cranelift::codegen::ir::BlockArg::Value(left.0)]);
343 ctx.builder.seal_block(short_block);
344
345 ctx.builder.switch_to_block(end_block);
346 let result = ctx.builder.block_params(end_block)[0];
347 Ok((result, Type::Any))
348 } else {
349 let left = self.bool_value(ctx, left)?;
350 let rhs_block = ctx.builder.create_block();
351 let short_block = ctx.builder.create_block();
352 let end_block = ctx.builder.create_block();
353 ctx.builder.append_block_param(end_block, types::I8);
354
355 match op {
356 BinaryOp::And => {
357 ctx.builder.ins().brif(left, rhs_block, &[], short_block, &[]);
358 }
359 BinaryOp::Or => {
360 ctx.builder.ins().brif(left, short_block, &[], rhs_block, &[]);
361 }
362 _ => unreachable!(),
363 }
364
365 ctx.builder.switch_to_block(rhs_block);
366 let right = self.eval(ctx, right)?.get(ctx).unwrap();
367 let right = self.bool_value(ctx, right)?;
368 ctx.builder.ins().jump(end_block, &[cranelift::codegen::ir::BlockArg::Value(right)]);
369 ctx.builder.seal_block(rhs_block);
370
371 ctx.builder.switch_to_block(short_block);
372 let short_value = match op {
373 BinaryOp::And => ctx.builder.ins().iconst(types::I8, 0),
374 BinaryOp::Or => ctx.builder.ins().iconst(types::I8, 1),
375 _ => unreachable!(),
376 };
377 ctx.builder.ins().jump(end_block, &[cranelift::codegen::ir::BlockArg::Value(short_value)]);
378 ctx.builder.seal_block(short_block);
379
380 ctx.builder.switch_to_block(end_block);
381 let result = ctx.builder.block_params(end_block)[0];
382 Ok((result, Type::Bool))
383 }
384 }
385
386 fn struct_alloc(&mut self, ctx: &mut BuildContext, ty: &Type) -> Result<Value> {
387 let size = ctx.builder.ins().iconst(types::I64, ty.width() as i64);
388 let fn_id = self.struct_alloc_fn.ok_or_else(|| anyhow!("VM struct allocator runtime is not registered"))?;
389 let fn_ref = self.get_fn_ref(ctx, fn_id);
390 let call_inst = ctx.builder.ins().call(fn_ref, &[size]);
391 Ok(ctx.builder.inst_results(call_inst)[0])
392 }
393
394 fn store_struct_field(&mut self, ctx: &mut BuildContext, base: Value, idx: usize, field_ty: &Type, value: (Value, Type), struct_ty: &Type) -> Result<()> {
395 let offset = struct_ty.field_offset(idx).ok_or_else(|| anyhow!("结构字段索引越界 {}", idx))?;
396 let value = self.convert(ctx, value, field_ty.clone())?;
397 if field_ty.is_struct() || field_ty.is_array() {
398 let field_addr = ctx.builder.ins().iadd_imm(base, offset as i64);
399 self.copy_vec_element(ctx, field_addr, value, field_ty);
400 } else {
401 ctx.builder.ins().store(MemFlags::trusted(), value, base, offset as i32);
402 }
403 Ok(())
404 }
405
406 fn load_struct_field(&mut self, ctx: &mut BuildContext, base: Value, idx: usize, struct_ty: &Type) -> Result<(Value, Type)> {
407 if let Type::Struct { params: _, fields } = struct_ty {
408 let field_ty = fields.get(idx).map(|(_, ty)| ty).ok_or_else(|| anyhow!("结构字段索引越界 {}", idx))?;
409 let offset = struct_ty.field_offset(idx).ok_or_else(|| anyhow!("结构字段索引越界 {}", idx))?;
410 if field_ty.is_struct() || field_ty.is_array() {
411 return Ok((ctx.builder.ins().iadd_imm(base, offset as i64), field_ty.clone()));
412 }
413 let val = ctx.builder.ins().load(crate::get_type(field_ty)?, MemFlags::trusted(), base, offset as i32);
414 Ok((val, field_ty.clone()))
415 } else {
416 Err(anyhow!("不是结构体 {:?}", struct_ty))
417 }
418 }
419
420 fn struct_field_index(&self, struct_ty: &Type, right: &Expr) -> Result<usize> {
421 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()? };
422 if let Some(idx) = value.as_int() {
423 return usize::try_from(idx).map_err(|_| anyhow!("结构字段索引越界 {}", idx));
424 }
425 if value.is_str() {
426 return self.compiler.get_field(struct_ty, value.as_str()).map(|(idx, _)| idx);
427 }
428 Err(anyhow!("非立即数结构字段索引 {:?}", right))
429 }
430
431 fn vec_elem_ty(ty: &Type) -> Option<Type> {
432 if let Type::Vec(elem, 0) = ty { Some((**elem).clone()) } else { None }
433 }
434
435 fn array_elem_ty(ty: &Type) -> Option<Type> {
436 if let Type::Array(elem, _) = ty { Some((**elem).clone()) } else { None }
437 }
438
439 fn vec_index_addr(&mut self, ctx: &mut BuildContext, base: Value, idx: (Value, Type), elem_ty: &Type) -> Result<Value> {
440 let idx = self.convert(ctx, idx, Type::I64)?;
441 let width = ctx.builder.ins().iconst(types::I64, elem_ty.storage_width() as i64);
442 let offset = ctx.builder.ins().imul(idx, width);
443 Ok(ctx.builder.ins().iadd(base, offset))
444 }
445
446 fn array_index_addr(&mut self, ctx: &mut BuildContext, base: Value, idx: (Value, Type), elem_ty: &Type) -> Result<Value> {
447 self.vec_index_addr(ctx, base, idx, elem_ty)
448 }
449
450 fn load_array_index(&mut self, ctx: &mut BuildContext, base: Value, idx: (Value, Type), elem_ty: &Type) -> Result<(Value, Type)> {
451 let addr = self.array_index_addr(ctx, base, idx, elem_ty)?;
452 if elem_ty.is_struct() || elem_ty.is_array() {
453 Ok((addr, elem_ty.clone()))
454 } else {
455 let val = ctx.builder.ins().load(crate::get_type(elem_ty)?, MemFlags::trusted(), addr, 0);
456 Ok((val, elem_ty.clone()))
457 }
458 }
459
460 fn store_array_index(&mut self, ctx: &mut BuildContext, base: Value, idx: (Value, Type), elem_ty: &Type, value: (Value, Type)) -> Result<()> {
461 let addr = self.array_index_addr(ctx, base, idx, elem_ty)?;
462 let value = self.convert(ctx, value, elem_ty.clone())?;
463 if elem_ty.is_struct() || elem_ty.is_array() {
464 self.copy_vec_element(ctx, addr, value, elem_ty);
465 } else {
466 ctx.builder.ins().store(MemFlags::trusted(), value, addr, 0);
467 }
468 Ok(())
469 }
470
471 fn init_repeat_array(&mut self, ctx: &mut BuildContext, value: (Value, Type), len: u32) -> Result<(Value, Type)> {
472 let elem_ty = value.1.clone();
473 let array_ty = Type::Array(std::rc::Rc::new(elem_ty.clone()), len);
474 let base = self.struct_alloc(ctx, &array_ty)?;
475 for idx in 0..len {
476 let idx = (ctx.builder.ins().iconst(types::I64, idx as i64), Type::I64);
477 self.store_array_index(ctx, base, idx, &elem_ty, value.clone())?;
478 }
479 Ok((base, array_ty))
480 }
481
482 fn init_array_from_items(&mut self, ctx: &mut BuildContext, items: &[Expr], ty: &Type) -> Result<Value> {
483 let Type::Array(elem_ty, len) = ty else {
484 return Err(anyhow!("not an array type: {:?}", ty));
485 };
486 if items.len() != *len as usize {
487 return Err(anyhow!("array literal length {} does not match {}", items.len(), len));
488 }
489 let base = self.struct_alloc(ctx, ty)?;
490 for (idx, item) in items.iter().enumerate() {
491 let value = self.eval(ctx, item)?.get(ctx).ok_or(anyhow!("array item has no value"))?;
492 let idx = (ctx.builder.ins().iconst(types::I64, idx as i64), Type::I64);
493 self.store_array_index(ctx, base, idx, elem_ty, value)?;
494 }
495 Ok(base)
496 }
497
498 fn load_vec_index(&mut self, ctx: &mut BuildContext, base: Value, idx: (Value, Type), elem_ty: &Type) -> Result<(Value, Type)> {
499 let addr = self.vec_index_addr(ctx, base, idx, elem_ty)?;
500 if elem_ty.is_struct() {
501 Ok((addr, elem_ty.clone()))
502 } else {
503 let val = ctx.builder.ins().load(crate::get_type(elem_ty)?, MemFlags::trusted(), addr, 0);
504 Ok((val, elem_ty.clone()))
505 }
506 }
507
508 fn copy_vec_element(&mut self, ctx: &mut BuildContext, dst: Value, src: Value, elem_ty: &Type) {
509 let mut offset = 0u32;
510 let width = elem_ty.storage_width();
511 while offset < width {
512 let remaining = width - offset;
513 let (ty, size) = if remaining >= 8 {
514 (types::I64, 8)
515 } else if remaining >= 4 {
516 (types::I32, 4)
517 } else if remaining >= 2 {
518 (types::I16, 2)
519 } else {
520 (types::I8, 1)
521 };
522 let value = ctx.builder.ins().load(ty, MemFlags::trusted(), src, offset as i32);
523 ctx.builder.ins().store(MemFlags::trusted(), value, dst, offset as i32);
524 offset += size;
525 }
526 }
527
528 fn store_vec_index(&mut self, ctx: &mut BuildContext, base: Value, idx: (Value, Type), elem_ty: &Type, value: (Value, Type)) -> Result<()> {
529 let addr = self.vec_index_addr(ctx, base, idx, elem_ty)?;
530 let value = self.convert(ctx, value, elem_ty.clone())?;
531 if elem_ty.is_struct() {
532 self.copy_vec_element(ctx, addr, value, elem_ty);
533 } else {
534 ctx.builder.ins().store(MemFlags::trusted(), value, addr, 0);
535 }
536 Ok(())
537 }
538
539 fn swap_vec_index(&mut self, ctx: &mut BuildContext, base: Value, left: (Value, Type), right: (Value, Type), elem_ty: &Type) -> Result<()> {
540 let left_addr = self.vec_index_addr(ctx, base, left, elem_ty)?;
541 let right_addr = self.vec_index_addr(ctx, base, right, elem_ty)?;
542 let mut offset = 0u32;
543 let width = elem_ty.storage_width();
544 while offset < width {
545 let remaining = width - offset;
546 let (ty, size) = if remaining >= 8 {
547 (types::I64, 8)
548 } else if remaining >= 4 {
549 (types::I32, 4)
550 } else if remaining >= 2 {
551 (types::I16, 2)
552 } else {
553 (types::I8, 1)
554 };
555 let left_value = ctx.builder.ins().load(ty, MemFlags::trusted(), left_addr, offset as i32);
556 let right_value = ctx.builder.ins().load(ty, MemFlags::trusted(), right_addr, offset as i32);
557 ctx.builder.ins().store(MemFlags::trusted(), left_value, right_addr, offset as i32);
558 ctx.builder.ins().store(MemFlags::trusted(), right_value, left_addr, offset as i32);
559 offset += size;
560 }
561 Ok(())
562 }
563
564 fn init_struct_from_dynamic(&mut self, ctx: &mut BuildContext, value: (Value, Type), ty: &Type) -> Result<Value> {
565 let Type::Struct { params: _, fields } = ty else {
566 return Err(anyhow!("不是结构体 {:?}", ty));
567 };
568 let base = self.struct_alloc(ctx, ty)?;
569 for (idx, (_, field_ty)) in fields.iter().enumerate() {
570 let idx_val = ctx.builder.ins().iconst(types::I64, idx as i64);
571 let item = self.call(ctx, self.get_method(&Type::Any, "get_idx")?, vec![value.0, idx_val])?;
572 self.store_struct_field(ctx, base, idx, field_ty, item, ty)?;
573 }
574 Ok(base)
575 }
576
577 fn init_struct_from_items(&mut self, ctx: &mut BuildContext, items: &[Expr], ty: &Type) -> Result<Value> {
578 let Type::Struct { params: _, fields } = ty else {
579 return Err(anyhow!("not a struct type: {:?}", ty));
580 };
581 let base = self.struct_alloc(ctx, ty)?;
582 for (idx, item) in items.iter().enumerate() {
583 let Some((_, field_ty)) = fields.get(idx) else {
584 break;
585 };
586 let value = self.eval(ctx, item)?.get(ctx).ok_or(anyhow!("struct field has no value"))?;
587 self.store_struct_field(ctx, base, idx, field_ty, value, ty)?;
588 }
589 Ok(base)
590 }
591
592 fn expr_assigned_var(expr: &Expr) -> Option<(u32, Type)> {
593 if let ExprKind::Binary { left, op, right } = &expr.kind
594 && op.is_assign()
595 && let ExprKind::Var(idx) = left.kind
596 {
597 return Some((idx, right.get_type()));
598 }
599 None
600 }
601
602 fn declare_assigned_vars(&mut self, ctx: &mut BuildContext, stmt: &Stmt) -> Result<()> {
603 match &stmt.kind {
604 StmtKind::Expr(expr, _) => {
605 if let Some((idx, ty)) = Self::expr_assigned_var(expr) {
606 match ctx.get_var(idx).ok() {
607 Some(LocalVar::Variable { .. }) | Some(LocalVar::Closure { .. }) => {}
608 Some(LocalVar::Value { val, ty }) => {
609 ctx.set_var(idx, LocalVar::Value { val, ty })?;
610 }
611 Some(LocalVar::None) | None => {
612 let init = self.zero_value(ctx, &ty)?;
613 ctx.set_var(idx, init.into())?;
614 }
615 }
616 }
617 }
618 StmtKind::Block(stmts) => {
619 for stmt in stmts {
620 self.declare_assigned_vars(ctx, stmt)?;
621 }
622 }
623 StmtKind::If { then_body, else_body, .. } => {
624 self.declare_assigned_vars(ctx, then_body)?;
625 if let Some(else_body) = else_body {
626 self.declare_assigned_vars(ctx, else_body)?;
627 }
628 }
629 StmtKind::While { body, .. } | StmtKind::Loop(body) => {
630 self.declare_assigned_vars(ctx, body)?;
631 }
632 StmtKind::For { body, .. } => {
633 self.declare_assigned_vars(ctx, body)?;
634 }
635 _ => {}
636 }
637 Ok(())
638 }
639
640 fn zero_value(&mut self, ctx: &mut BuildContext, ty: &Type) -> Result<(Value, Type)> {
641 if self.is_aggregate_ty(ty) {
642 Ok((self.struct_alloc(ctx, ty)?, ty.clone()))
643 } else if ty.is_f32() {
644 Ok((ctx.builder.ins().f32const(0.0), ty.clone()))
645 } else if ty.is_f64() {
646 Ok((ctx.builder.ins().f64const(0.0), ty.clone()))
647 } else {
648 Ok((ctx.builder.ins().iconst(crate::get_type(ty)?, 0), ty.clone()))
649 }
650 }
651
652 fn assign(&mut self, ctx: &mut BuildContext, left: &Expr, value: LocalVar) -> Result<(Value, Type)> {
653 if let ExprKind::Var(idx) = &left.kind {
654 if value.is_closure() {
655 ctx.set_var(*idx, value)?;
656 return self.get_null_value(ctx);
657 }
658 let value_ty = value.get_ty();
659 if let Some(ty) = ctx.get_var_ty(*idx) {
660 if self.is_aggregate_ty(&ty) {
661 let dst = ctx.get_var(*idx)?.get(ctx).ok_or(anyhow!("aggregate variable has no value"))?.0;
662 let src = value.get(ctx).ok_or(anyhow!("aggregate assignment has no value"))?;
663 let src = self.convert(ctx, src, ty.clone())?;
664 self.copy_vec_element(ctx, dst, src, &ty);
665 } else if value_ty != ty {
666 if let Some(vt) = value.get(ctx) {
667 let val = self.convert(ctx, vt, ty.clone())?;
668 ctx.set_var(*idx, LocalVar::Value { val, ty })?;
669 } else if ty.is_any() {
670 let const_idx = self.compiler.get_const(Dynamic::Null);
671 let (val, ty) = self.get_const_value(ctx, const_idx)?;
672 ctx.set_var(*idx, LocalVar::Value { val, ty })?;
673 } else {
674 ctx.set_var(*idx, LocalVar::None)?;
675 }
676 } else {
677 ctx.set_var(*idx, value)?;
678 }
679 } else if self.is_aggregate_ty(&value_ty) {
680 let src = value.get(ctx).ok_or(anyhow!("aggregate initializer has no value"))?;
681 let dst = self.struct_alloc(ctx, &value_ty)?;
682 let src = self.convert(ctx, src, value_ty.clone())?;
683 self.copy_vec_element(ctx, dst, src, &value_ty);
684 ctx.set_var(*idx, LocalVar::Value { val: dst, ty: value_ty })?;
685 } else {
686 ctx.set_var(*idx, value)?;
687 }
688 let assigned = ctx.get_var(*idx)?;
689 if assigned.is_closure() {
690 return self.get_null_value(ctx);
691 }
692 let val = assigned.get(ctx).ok_or(anyhow!("assigned variable has no value"))?;
693 return Ok(val);
694 } else if left.is_idx() {
695 let value = value.get(ctx).unwrap();
696 let (left, _, right) = left.clone().binary().unwrap();
697 let left = self.eval(ctx, &left)?.get(ctx).ok_or(anyhow!("未知局部变量 {:?}", left))?;
698 if let Type::Struct { params: _, fields } = &left.1 {
699 let idx = self.struct_field_index(&left.1, &right)?;
700 let field_ty = fields.get(idx).map(|(_, ty)| ty.clone()).ok_or_else(|| anyhow!("结构字段索引越界 {}", idx))?;
701 self.store_struct_field(ctx, left.0, idx, &field_ty, value.clone(), &left.1)?;
702 return Ok(value);
703 }
704 if let Some(elem_ty) = Self::vec_elem_ty(&left.1) {
705 let idx = if right.is_value() {
706 let idx = right.clone().value()?.as_int().ok_or(anyhow!("Vec 索引必须是整数"))?;
707 (ctx.builder.ins().iconst(types::I64, idx), Type::I64)
708 } else {
709 self.eval(ctx, &right)?.get(ctx).ok_or(anyhow!("Vec 索引没有值"))?
710 };
711 self.store_vec_index(ctx, left.0, idx, &elem_ty, value.clone())?;
712 return Ok(value);
713 }
714 if let Some(elem_ty) = Self::array_elem_ty(&left.1) {
715 let idx = if right.is_value() {
716 let idx = right.clone().value()?.as_int().ok_or(anyhow!("array index must be integer"))?;
717 (ctx.builder.ins().iconst(types::I64, idx), Type::I64)
718 } else {
719 self.eval(ctx, &right)?.get(ctx).ok_or(anyhow!("array index has no value"))?
720 };
721 self.store_array_index(ctx, left.0, idx, &elem_ty, value.clone())?;
722 return Ok(value);
723 }
724 if right.is_value() {
725 let right_value = right.clone().value()?;
726 if let Some(idx) = right_value.as_int() {
727 let idx = ctx.builder.ins().iconst(types::I64, idx);
728 let f = self.get_method(&left.1, "set_idx")?;
729 let args = self.adjust_args(ctx, vec![left, (idx, Type::I64), value.clone()], f.arg_tys()?)?;
730 self.call_for_side_effect(ctx, f, args)?;
731 } else {
732 let key = ctx.get_const(&right_value)?;
733 let f = self.get_method(&left.1, "set_key")?;
734 let args = self.adjust_args(ctx, vec![left, key, value.clone()], f.arg_tys()?)?;
735 self.call_for_side_effect(ctx, f, args)?;
736 }
737 } else {
738 let right = self.eval(ctx, &right)?.get(ctx).unwrap();
739 if right.1.is_any() || right.1.is_str() {
740 let f = self.get_method(&left.1, "set_key")?;
741 let args = self.adjust_args(ctx, vec![left, right, value.clone()], f.arg_tys()?)?;
742 self.call_for_side_effect(ctx, f, args)?;
743 } else {
744 let f = self.get_method(&left.1, "set_idx")?;
745 let args = self.adjust_args(ctx, vec![left, right, value.clone()], f.arg_tys()?)?;
746 self.call_for_side_effect(ctx, f, args)?;
747 }
748 }
749 return Ok(value);
750 } else {
751 panic!("赋值给 {:?} {:?}", left, value)
752 }
753 }
754
755 fn closure_value(&self, ctx: &mut BuildContext, id: u32) -> Result<LocalVar> {
756 let captures = match self.compiler.symbols.get_symbol(id)?.1 {
757 Symbol::Fn { cap, .. } => cap.vars.iter().map(|idx| ctx.get_var(*idx as u32)?.get(ctx).ok_or_else(|| anyhow!("捕获变量 {} 没有值", idx))).collect::<Result<Vec<_>>>()?,
758 _ => Vec::new(),
759 };
760 Ok(LocalVar::Closure { id, captures })
761 }
762
763 pub(crate) fn call_fn(&mut self, ctx: &mut BuildContext, id: u32, obj: Option<Expr>, params: &Vec<Expr>) -> Result<LocalVar> {
764 self.call_fn_with_params(ctx, id, &[], obj, params)
765 }
766
767 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> {
768 self.call_fn_with_capture_values(ctx, id, generic_args, obj, params, None)
769 }
770
771 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> {
772 let fn_name = self.compiler.symbols.get_symbol(id).map(|(name, _)| name.clone())?;
773 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() };
774 for p in params {
775 args.push(self.eval(ctx, p)?.get(ctx).ok_or_else(|| anyhow!("函数 {} 的参数表达式没有值: {:?}", fn_name, p))?);
776 }
777 if let Some(captures) = &capture_values {
778 args.extend(captures.iter().cloned());
779 }
780 if fn_name.as_str().ends_with("Vec::swap")
781 && let Some((base, vec_ty)) = args.first().cloned()
782 && let Some(elem_ty) = Self::vec_elem_ty(&vec_ty)
783 {
784 let [_, left_idx, right_idx]: [(Value, Type); 3] = args.try_into().map_err(|_| anyhow!("Vec::swap 需要 self 和两个索引参数"))?;
785 self.swap_vec_index(ctx, base, left_idx, right_idx, &elem_ty)?;
786 return Ok(LocalVar::None);
787 }
788 let visible_arg_len = args.len() - capture_values.as_ref().map(|captures| captures.len()).unwrap_or(0);
789 let arg_tys: Vec<Type> = args.iter().take(visible_arg_len).map(|(_, ty)| ty.clone()).collect();
790 let fn_info = match if generic_args.is_empty() { self.get_fn(id, &arg_tys) } else { Err(anyhow!("generic function needs specialization")) } {
791 Ok(info) => info,
792 Err(_) => self.gen_fn_with_params(Some(ctx), id, &arg_tys, generic_args).map_err(|e| {
793 log::error!("{:?}", self.compiler.symbols.get_symbol(id));
794 e
795 })?,
796 };
797 match &fn_info {
798 FnInfo::Call { fn_id: _, arg_tys: want_tys, caps, ret, context: _ } => {
799 let mut args = self.adjust_args(ctx, args, want_tys)?;
800 if capture_values.is_none() {
801 for c in caps {
802 args.push(ctx.get_var(*c as u32)?.get(ctx).unwrap().0);
803 }
804 }
805 if ret.is_void() {
806 self.call_for_side_effect(ctx, fn_info, args)?;
807 Ok(LocalVar::None)
808 } else {
809 self.call(ctx, fn_info, args).map(|r| r.into())
810 }
811 }
812 _ => panic!("不可能编译出 inline 函数"),
813 }
814 }
815
816 pub(crate) fn eval(&mut self, ctx: &mut BuildContext, expr: &Expr) -> Result<LocalVar> {
817 match &expr.kind {
818 ExprKind::Value(v) => Ok(ctx.get_const(v)?.into()),
819 ExprKind::Var(idx) => {
820 let v = ctx.get_var(*idx)?;
821 Ok(v)
822 }
823 ExprKind::Unary { op, value } => {
824 let v = self.eval(ctx, value)?.get(ctx).unwrap();
825 if op == &UnaryOp::Not {
826 let cond = self.bool_value(ctx, v)?;
827 let zero = ctx.builder.ins().iconst(types::I8, 0);
828 let one = ctx.builder.ins().iconst(types::I8, 1);
829 let is_zero = ctx.builder.ins().icmp_imm(IntCC::Equal, cond, 0);
830 Ok((ctx.builder.ins().select(is_zero, one, zero), Type::Bool).into())
831 } else {
832 Ok(Self::unary(ctx, v, op.clone())?.into())
833 }
834 }
835 ExprKind::Binary { left, op, right } => {
836 if op == &BinaryOp::Assign {
837 match self.eval(ctx, right) {
838 Ok(value) => self.assign(ctx, left, value).map(|v| v.into()),
839 Err(e) => {
840 log::error!("assign error {:?}", e);
841 Err(e)
842 }
843 }
844 } else {
845 let assign_expr = if op.is_assign() { Some(left.clone()) } else { None };
846 let left = match self.eval(ctx, left)?.get(ctx) {
847 Some(left) => left,
848 None if matches!(op, BinaryOp::And | BinaryOp::Or) => self.get_null_value(ctx)?,
849 None => return Err(anyhow!("binary left has no value: {:?}", left)),
850 };
851 if op == &BinaryOp::Idx {
852 let left_ty = self.compiler.symbols.get_type(&left.1).unwrap_or_else(|_| left.1.clone());
853 let left = (left.0, left_ty);
854 if let Type::Struct { params: _, fields: _ } = &left.1 {
855 let idx = self.struct_field_index(&left.1, right)?;
856 return self.load_struct_field(ctx, left.0, idx, &left.1).map(|r| r.into());
857 }
858 if let Some(elem_ty) = Self::vec_elem_ty(&left.1) {
859 let idx = if right.is_value() {
860 let idx = right.clone().value()?.as_int().ok_or(anyhow!("Vec 索引必须是整数"))?;
861 (ctx.builder.ins().iconst(types::I64, idx), Type::I64)
862 } else {
863 self.eval(ctx, right)?.get(ctx).ok_or(anyhow!("Vec 索引没有值"))?
864 };
865 return self.load_vec_index(ctx, left.0, idx, &elem_ty).map(|r| r.into());
866 }
867 if let Some(elem_ty) = Self::array_elem_ty(&left.1) {
868 let idx = if right.is_value() {
869 let idx = right.clone().value()?.as_int().ok_or(anyhow!("array index must be integer"))?;
870 (ctx.builder.ins().iconst(types::I64, idx), Type::I64)
871 } else {
872 self.eval(ctx, right)?.get(ctx).ok_or(anyhow!("array index has no value"))?
873 };
874 return self.load_array_index(ctx, left.0, idx, &elem_ty).map(|r| r.into());
875 }
876 if right.is_value() {
877 let right_value = right.clone().value()?;
878 if let Some(idx) = right_value.as_int() {
879 let idx = ctx.builder.ins().iconst(types::I64, idx);
880 self.call(ctx, self.get_method(&left.1, "get_idx")?, vec![left.0, idx]).map(|r| r.into())
881 } else {
882 let key = ctx.get_const(&right_value)?;
883 self.call(ctx, self.get_method(&left.1, "get_key")?, vec![left.0, key.0]).map(|r| r.into())
884 }
885 } else if let ExprKind::Range { start, stop, inclusive } = &right.kind {
886 let start = self.eval(ctx, start)?.get(ctx).ok_or(anyhow!("range start has no value"))?;
887 let start = self.convert(ctx, start, Type::I64)?;
888 let stop = self.eval(ctx, stop)?.get(ctx).ok_or(anyhow!("range stop has no value"))?;
889 let stop = self.convert(ctx, stop, Type::Any)?;
890 let inclusive = ctx.builder.ins().iconst(types::I8, i64::from(*inclusive));
891 self.call(ctx, self.get_method(&left.1, "slice")?, vec![left.0, start, stop, inclusive]).map(|r| r.into())
892 } else {
893 let right = self.eval(ctx, right)?.get(ctx).ok_or(anyhow!("非Value {:?}", right))?;
894 if right.1.is_any() || right.1.is_str() {
895 let right = self.convert(ctx, right, Type::Any)?;
896 self.call(ctx, self.get_method(&left.1, "get_key")?, vec![left.0, right]).map(|r| r.into())
897 } else {
898 let right = self.convert(ctx, right, Type::I64)?;
899 self.call(ctx, self.get_method(&left.1, "get_idx")?, vec![left.0, right]).map(|r| r.into())
900 }
901 }
902 } else {
903 let result = self.binary(ctx, left, op.clone(), right)?.into();
904 if let Some(expr) = assign_expr { self.assign(ctx, &expr, result).map(|r| r.into()) } else { Ok(result.into()) }
905 }
906 }
907 }
908 ExprKind::Call { obj, params } => {
909 if let ExprKind::AssocId { id, params: generic_args } = &obj.kind {
910 self.call_fn_with_params(ctx, *id, generic_args, None, params)
911 } else if let ExprKind::Id(id, obj) = &obj.kind {
912 self.call_fn(ctx, *id, obj.as_ref().map(|o| *o.clone()), params)
913 } else if obj.is_value() {
914 return Ok(LocalVar::None);
916 } else {
917 if obj.is_idx() {
918 let (left, _, right) = obj.clone().binary().unwrap();
919 let left = self.eval(ctx, &left)?.get(ctx).ok_or(anyhow!("obj {:?}", obj))?;
920 let ty = self.compiler.symbols.get_type(&left.1)?;
921 if let Some(name) = self.get_dynamic(&right) {
922 if name.as_str() == "swap"
923 && let Some(elem_ty) = Self::vec_elem_ty(&ty)
924 {
925 let [left_idx, right_idx]: [(Value, Type); 2] =
926 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 需要两个索引参数"))?;
927 self.swap_vec_index(ctx, left.0, left_idx, right_idx, &elem_ty)?;
928 return Ok(LocalVar::None);
929 }
930 let mut args = vec![left];
931 for p in params {
932 args.push(self.eval(ctx, p)?.get(ctx).ok_or_else(|| anyhow!("动态方法 {:?} 的参数表达式没有值: {:?}", name, p))?);
933 }
934 let (_, method_ty) = self.compiler.get_field(&ty, name.as_str())?;
935 let Type::Symbol { id, .. } = method_ty else {
936 return Err(anyhow!("不是成员函数"));
937 };
938 let arg_tys: Vec<Type> = args.iter().map(|(_, ty)| ty.clone()).collect();
939 let method = self.get_fn(id, &arg_tys).or_else(|_| self.gen_fn_with_params(Some(ctx), id, &arg_tys, &[]))?;
940 let args = self.adjust_args(ctx, args, method.arg_tys()?)?;
941 self.call(ctx, method, args).map(|r| r.into())
942 } else {
943 self.eval(ctx, obj)
944 }
945 } else {
946 let val = self.eval(ctx, obj)?;
947 if let LocalVar::Closure { id, captures } = val {
948 return self.call_fn_with_capture_values(ctx, id, &[], None, params, Some(captures));
949 }
950 panic!("暂未实现 {:?}", val)
951 }
952 }
953 }
954 ExprKind::Typed { value, ty } => {
955 if let Type::Struct { params: _, fields: _ } = ty
956 && let ExprKind::List(items) = &value.kind
957 {
958 return Ok((self.init_struct_from_items(ctx, items, ty)?, ty.clone()).into());
959 }
960 if let Type::Array(_, _) = ty
961 && let ExprKind::List(items) = &value.kind
962 {
963 return Ok((self.init_array_from_items(ctx, items, ty)?, ty.clone()).into());
964 }
965 let evaluated = self.eval(ctx, value)?;
966 if evaluated.is_closure() {
967 return Ok(evaluated);
968 }
969 let vt = if let Some(vt) = evaluated.get(ctx) {
970 vt
971 } else if ty.is_any() {
972 let idx = self.compiler.get_const(Dynamic::Null);
973 self.get_const_value(ctx, idx)?
974 } else {
975 return Ok(LocalVar::None);
976 };
977 if let Type::Struct { params: _, fields: _ } = ty
978 && !self.is_opaque_custom_ty(ty)
979 {
980 if &vt.1 == ty {
981 Ok(vt.into())
982 } else if vt.1.is_any() {
983 Ok((self.init_struct_from_dynamic(ctx, vt, ty)?, ty.clone()).into())
984 } else {
985 Err(anyhow!("cannot convert {:?} to {:?}", vt.1, ty))
986 }
987 } else if &vt.1 != ty {
988 Ok((self.convert(ctx, vt, ty.clone())?, ty.clone()).into())
989 } else {
990 Ok(vt.into())
991 }
992 }
993 ExprKind::List(_) => Err(anyhow!("未实现 {:?}", expr)),
994 ExprKind::Repeat { value, len } => {
995 let value = self.eval(ctx, value)?.get(ctx).ok_or(anyhow!("repeat value has no value"))?;
996 let Type::ConstInt(len) = len else {
997 return Err(anyhow!("repeat length must be a compile-time integer"));
998 };
999 let len = u32::try_from(*len).map_err(|_| anyhow!("repeat length out of range"))?;
1000 self.init_repeat_array(ctx, value, len).map(|r| r.into())
1001 }
1002 ExprKind::Const(idx) => self.get_const_value(ctx, *idx).map(|v| v.into()),
1003 ExprKind::Id(id, _) => self.closure_value(ctx, *id),
1004 ExprKind::AssocId { id, .. } => self.closure_value(ctx, *id),
1005 expr => {
1006 panic!("未实现 {:?}", expr)
1008 }
1009 }
1010 }
1011
1012 fn gen_loop(&mut self, ctx: &mut BuildContext, cond: Option<&Expr>, body: &Stmt, f: Option<impl FnMut(&mut BuildContext)>) -> Result<()> {
1013 let loop_block = ctx.builder.create_block();
1014 let end_block = ctx.builder.create_block();
1015 if let Some(cond) = cond {
1016 let start_block = ctx.builder.create_block();
1017 ctx.builder.ins().jump(start_block, &[]);
1018 ctx.builder.switch_to_block(start_block);
1019 let cond = self.eval(ctx, cond)?.get(ctx).unwrap();
1020 let cond = self.bool_value(ctx, cond)?;
1021 let continue_block = if f.is_some() { ctx.builder.create_block() } else { start_block };
1022 ctx.builder.ins().brif(cond, loop_block, &[], end_block, &[]);
1023 ctx.builder.switch_to_block(loop_block);
1024 let body_terminated = self.gen_stmt(ctx, body, Some(end_block), Some(continue_block))?;
1025 if !body_terminated {
1026 ctx.builder.ins().jump(continue_block, &[]);
1027 }
1028 ctx.builder.seal_block(loop_block);
1029 f.map(|mut f| {
1030 ctx.builder.switch_to_block(continue_block);
1031 f(ctx);
1032 ctx.builder.ins().jump(start_block, &[]);
1033 ctx.builder.seal_block(continue_block);
1034 });
1035 } else {
1036 ctx.builder.ins().jump(loop_block, &[]);
1037 ctx.builder.switch_to_block(loop_block);
1038 let body_terminated = self.gen_stmt(ctx, body, Some(end_block), Some(loop_block))?;
1039 if !body_terminated {
1040 ctx.builder.ins().jump(loop_block, &[]);
1041 }
1042 ctx.builder.seal_block(loop_block);
1043 }
1044 ctx.builder.switch_to_block(end_block);
1045 Ok(())
1046 }
1047
1048 pub(crate) fn gen_stmt(&mut self, ctx: &mut BuildContext, stmt: &Stmt, break_block: Option<Block>, continue_block: Option<Block>) -> Result<bool> {
1049 match &stmt.kind {
1050 StmtKind::Expr(expr, _) => {
1051 let _ = self.eval(ctx, expr)?;
1052 }
1053 StmtKind::Break => {
1054 ctx.builder.ins().jump(break_block.unwrap(), &[]);
1055 return Ok(true);
1056 }
1057 StmtKind::Continue => {
1058 ctx.builder.ins().jump(continue_block.unwrap(), &[]);
1059 return Ok(true);
1060 }
1061 StmtKind::Return(expr) => {
1062 if let Some(expr) = expr {
1063 let value = self.eval(ctx, expr)?;
1064 let value = value.get(ctx);
1065 self.return_value(ctx, value)?;
1066 } else {
1067 self.return_value(ctx, None)?;
1068 }
1069 return Ok(true);
1070 }
1071 StmtKind::If { cond, then_body, else_body } => {
1072 self.declare_assigned_vars(ctx, then_body)?;
1073 if let Some(else_body) = else_body {
1074 self.declare_assigned_vars(ctx, else_body)?;
1075 }
1076 let then_block = ctx.builder.create_block();
1077 let cond = self.eval(ctx, cond)?.get(ctx).ok_or(anyhow!("未知的条件 {:?}", cond))?;
1078 let cond = self.bool_value(ctx, cond)?;
1079 let mut end_block = None;
1080 if let Some(else_body) = else_body {
1081 let else_block = ctx.builder.create_block();
1082 ctx.builder.ins().brif(cond, then_block, &[], else_block, &[]);
1083 ctx.builder.switch_to_block(then_block);
1084 if !self.gen_stmt(ctx, then_body, break_block, continue_block)? {
1085 let block = ctx.builder.create_block();
1086 ctx.builder.ins().jump(block, &[]);
1087 end_block = Some(block);
1088 }
1089 ctx.builder.switch_to_block(else_block);
1090 if !self.gen_stmt(ctx, else_body, break_block, continue_block)? {
1091 if end_block.is_none() {
1092 end_block = Some(ctx.builder.create_block());
1093 }
1094 ctx.builder.ins().jump(end_block.unwrap(), &[]);
1095 }
1096 ctx.builder.seal_block(else_block);
1097 } else {
1098 let block = ctx.builder.create_block();
1099 ctx.builder.ins().brif(cond, then_block, &[], block, &[]);
1100 end_block = Some(block);
1101 ctx.builder.switch_to_block(then_block);
1102 if !self.gen_stmt(ctx, then_body, break_block, continue_block)? {
1103 ctx.builder.ins().jump(end_block.unwrap(), &[]); }
1105 }
1106 if let Some(block) = end_block {
1107 ctx.builder.switch_to_block(block);
1108 }
1109 ctx.builder.seal_block(then_block);
1110 return Ok(end_block.is_none());
1111 }
1112 StmtKind::Block(stmts) => {
1113 for (idx, stmt) in stmts.iter().enumerate() {
1114 let r = self.gen_stmt(ctx, stmt, break_block, continue_block)?;
1115 if idx == stmts.len() - 1 {
1116 return Ok(r);
1117 }
1118 }
1119 }
1120 StmtKind::While { cond, body } => {
1121 self.declare_assigned_vars(ctx, body)?;
1122 let no_loop: Option<fn(&mut BuildContext)> = None;
1123 self.gen_loop(ctx, Some(cond), body, no_loop)?;
1124 }
1125 StmtKind::Loop(body) => {
1126 self.declare_assigned_vars(ctx, body)?;
1127 let no_loop: Option<fn(&mut BuildContext)> = None;
1128 self.gen_loop(ctx, None, body, no_loop)?;
1129 }
1130 StmtKind::For { pat, range, body } => {
1131 if let ExprKind::Range { start, stop, inclusive } = &range.kind {
1132 if let PatternKind::Var { idx, .. } = &pat.kind {
1133 let start = self.eval(ctx, start)?;
1134 ctx.set_var(*idx, start)?;
1135 self.declare_assigned_vars(ctx, body)?;
1136 let op = if *inclusive { BinaryOp::Le } else { BinaryOp::Lt };
1137 let cond = Self::expr(ExprKind::Binary { left: Box::new(Self::expr(ExprKind::Var(*idx))), op, right: Box::new(stop.as_ref().clone()) });
1138 self.gen_loop(
1139 ctx,
1140 Some(&cond),
1141 body,
1142 Some(|ctx: &mut BuildContext| {
1143 let v = ctx.get_var(*idx).unwrap().get(ctx).unwrap();
1144 let step = if v.1 == Type::I64 {
1145 ctx.builder.ins().iconst(types::I64, 1)
1146 } else if v.1 == Type::I32 {
1147 ctx.builder.ins().iconst(types::I32, 1)
1148 } else {
1149 panic!("{:?} 不能作为增量", v.1)
1150 };
1151 let vt = (ctx.builder.ins().iadd(v.0, step), v.1).into();
1152 let _ = ctx.set_var(*idx, vt);
1153 }),
1154 )?;
1155 }
1156 } else if let PatternKind::Var { idx, .. } = &pat.kind {
1157 let vt = self.eval(ctx, range)?.get(ctx).unwrap();
1158 if vt.1.is_any() {
1159 let iter = self.call(ctx, self.get_method(&vt.1, "iter")?, vec![vt.0])?;
1160 let next = self.get_method(&vt.1, "next")?;
1161 let next_id = next.get_id()?;
1162 let start = self.call(ctx, next, vec![iter.0])?;
1163 ctx.set_var(*idx, start.into())?;
1164 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))) });
1165 self.gen_loop(
1166 ctx,
1167 Some(&cond),
1168 body,
1169 Some(|ctx: &mut BuildContext| {
1170 let fn_ref = ctx.get_fn_ref(next_id).unwrap();
1171 let call_inst = ctx.builder.ins().call(fn_ref, &[iter.0]);
1172 let ret = ctx.builder.inst_results(call_inst)[0];
1173 let _ = ctx.set_var(*idx, (ret, Type::Any).into());
1174 }),
1175 )?;
1176 }
1177 } else if let PatternKind::Tuple(pats) = &pat.kind {
1178 let vt = self.eval(ctx, range)?.get(ctx).unwrap();
1179 if vt.1.is_any() && pats.len() == 2 {
1180 let iter = self.call(ctx, self.get_method(&vt.1, "iter")?, vec![vt.0])?;
1182 let next = self.get_method(&vt.1, "next")?;
1183 let next_id = next.get_id()?;
1184 let get_idx = self.get_method(&vt.1, "get_idx")?.get_id()?;
1185
1186 let start = self.call(ctx, next, vec![iter.0])?;
1187 let key_idx = ctx.builder.ins().iconst(types::I64, 0);
1188 let key = self.call(ctx, self.get_method(&start.1, "get_idx")?, vec![start.0, key_idx])?;
1189 let value_idx = ctx.builder.ins().iconst(types::I64, 1);
1190 let value = self.call(ctx, self.get_method(&start.1, "get_idx")?, vec![start.0, value_idx])?;
1191 ctx.set_var(pats[0].var().unwrap(), key.into())?;
1192 ctx.set_var(pats[1].var().unwrap(), value.into())?;
1193 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))) });
1194 self.gen_loop(
1195 ctx,
1196 Some(&cond),
1197 body,
1198 Some(|ctx: &mut BuildContext| {
1199 let fn_ref = ctx.get_fn_ref(next_id).unwrap();
1200 let call_inst = ctx.builder.ins().call(fn_ref, &[iter.0]);
1201 let ret = ctx.builder.inst_results(call_inst)[0];
1202
1203 let fn_ref = ctx.get_fn_ref(get_idx).unwrap();
1204 let call_inst = ctx.builder.ins().call(fn_ref, &[ret, key_idx]);
1205 let key_ret = ctx.builder.inst_results(call_inst)[0];
1206 let call_inst = ctx.builder.ins().call(fn_ref, &[ret, value_idx]);
1207 let value_ret = ctx.builder.inst_results(call_inst)[0];
1208
1209 let _ = ctx.set_var(pats[0].var().unwrap(), (key_ret, Type::Any).into());
1210 let _ = ctx.set_var(pats[1].var().unwrap(), (value_ret, Type::Any).into());
1211 }),
1212 )?;
1213 }
1214 }
1215 }
1216 _ => {
1217 panic!("未实现 {:?}", stmt)
1218 }
1219 }
1220 Ok(false)
1221 }
1222}