use std::rc::Rc; use derive_more::Constructor; use crate::error::Result; use crate::vm::VM; use super::Value; #[derive(Debug, Clone, Constructor)] pub struct PrimOp<'jit: 'vm, 'vm> { pub name: &'static str, arity: usize, func: fn(&'vm VM<'jit>, Vec>) -> Result>, } impl PartialEq for PrimOp<'_, '_> { fn eq(&self, _: &Self) -> bool { false } } impl<'jit, 'vm> PrimOp<'jit, 'vm> { pub fn call(&self, vm: &'vm VM<'jit>, args: Vec>) -> Result> { if (args.len()) < self.arity { Value::PartialPrimOp( PartialPrimOp { name: self.name, arity: self.arity - args.len(), args, func: self.func, } .into(), ) .ok() } else if args.len() == self.arity { (self.func)(vm, args) } else { unimplemented!() } } } #[derive(Debug, Clone)] pub struct PartialPrimOp<'jit: 'vm, 'vm> { pub name: &'static str, arity: usize, args: Vec>, func: fn(&'vm VM<'jit>, Vec>) -> Result>, } impl PartialEq for PartialPrimOp<'_, '_> { fn eq(&self, _: &Self) -> bool { false } } impl<'jit: 'vm, 'vm> PartialPrimOp<'jit, 'vm> { pub fn call(self: &Rc, vm: &'vm VM<'jit>, args: Vec>) -> Result> { let len = args.len(); let mut self_clone = self.clone(); let self_mut = Rc::make_mut(&mut self_clone); self_mut.args.extend(args); self_mut.arity -= len; if self_mut.arity > 0 { Value::PartialPrimOp(self_clone).ok() } else if self_mut.arity == 0 { let args = std::mem::replace(&mut self_mut.args, Vec::new()); (self.func)(vm, args) } else { unimplemented!() } } }