use derive_more::Constructor; use crate::vm::VM; use super::Value; #[derive(Debug, Clone, Constructor)] pub struct PrimOp { pub name: &'static str, arity: u8, func: fn(&VM, Vec) -> Value, } impl PartialEq for PrimOp { fn eq(&self, _: &Self) -> bool { false } } impl PrimOp { pub fn call(self, vm: &VM, args: Vec) -> Value { 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 { pub name: &'static str, arity: u8, args: Vec, func: fn(&VM, Vec) -> Value, } impl PartialEq for PartialPrimOp { fn eq(&self, _: &Self) -> bool { false } } impl PartialPrimOp { pub fn call(mut self, vm: &VM, args: Vec) -> Value { 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!() } } }