use derive_more::Constructor; use crate::vm::VM; use super::Value; #[derive(Debug, Clone, Constructor)] pub struct PrimOp<'vm> { pub name: &'static str, arity: u8, func: fn(&'vm VM<'_>, Vec>) -> Value<'vm>, } impl PartialEq for PrimOp<'_> { fn eq(&self, _: &Self) -> bool { false } } impl<'vm> PrimOp<'vm> { pub fn call(self, vm: &'vm VM<'_>, args: Vec>) -> Value<'vm> { if (args.len() as u8) < self.arity { Value::PartialPrimOp(PartialPrimOp { name: self.name, arity: self.arity - args.len() as u8, args, func: self.func, }) } else if args.len() as u8 == self.arity { (self.func)(vm, args) } else { unimplemented!() } } } #[derive(Debug, Clone)] pub struct PartialPrimOp<'vm> { pub name: &'static str, arity: u8, args: Vec>, func: fn(&'vm VM<'_>, Vec>) -> Value<'vm>, } impl PartialEq for PartialPrimOp<'_> { fn eq(&self, _: &Self) -> bool { false } } impl<'vm> PartialPrimOp<'vm> { pub fn call(mut self, vm: &'vm VM<'_>, args: Vec>) -> Value<'vm> { let len = args.len() as u8; self.args.extend(args); if len < self.arity { Value::PartialPrimOp(PartialPrimOp { name: self.name, arity: self.arity - len, args: self.args, func: self.func, }) } else if len == self.arity { (self.func)(vm, self.args) } else { unimplemented!() } } }