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