use std::collections::HashMap; use std::rc::Rc; use derive_more::Constructor; use itertools::Itertools; use crate::bytecode::Func as BFunc; use crate::error::Result; use crate::ir; use crate::ty::internal::{Thunk, Value}; use crate::vm::{Env, VM}; #[derive(Debug, Clone)] pub enum Param { Ident(usize), Formals { formals: Vec<(usize, Option)>, ellipsis: bool, alias: Option, }, } impl From for Param { fn from(value: ir::Param) -> Self { match value { ir::Param::Ident(ident) => Param::Ident(ident), ir::Param::Formals { formals, ellipsis, alias, } => Param::Formals { formals: formals .into_iter() .map(|(sym, default)| (sym, default.map(|default| default.idx))) .collect(), ellipsis, alias, }, } } } pub type JITFunc<'vm> = unsafe extern "C" fn(vm: *mut VM<'_>, *mut Env<'vm>, *mut Value<'vm>) -> Value<'vm>; #[derive(Debug, Clone, Constructor)] pub struct Func<'vm> { pub func: &'vm BFunc, pub env: Rc>, pub compiled: Option>, } impl<'vm> Func<'vm> { pub fn call(&self, vm: &'vm VM<'_>, arg: Value<'vm>) -> Result> { use Param::*; let env = Rc::new(self.env.as_ref().clone()); match self.func.param.clone() { Ident(ident) => env.enter([(ident.into(), arg)].into_iter()), Formals { formals, ellipsis, alias, } => { let arg = arg.unwrap_attr_set(); let mut new = Vec::with_capacity(formals.len() + alias.iter().len()); if !ellipsis && arg .as_inner() .iter() .map(|(k, _)| k) .sorted() .ne(formals.iter().map(|(k, _)| k).sorted()) { todo!() } for (formal, default) in formals { let formal = formal.clone().into(); let arg = arg .select(formal) .or_else(|| { default.map(|idx| Value::Thunk(Thunk::new(vm.get_thunk(idx)).into())) }) .unwrap(); new.push((formal, arg)); } if let Some(alias) = alias { new.push((alias.clone().into(), Value::AttrSet(arg))); } env.enter(new.into_iter()); } } vm.eval(self.func.opcodes.iter().copied(), env) } } impl PartialEq for Func<'_> { fn eq(&self, _: &Self) -> bool { false } }