use std::rc::Rc; use derive_more::Constructor; use nixjit_error::Result; use super::Value; use crate::EvalContext; #[derive(Debug, Clone, Constructor)] pub struct PrimOp { pub name: &'static str, arity: usize, func: fn(Vec>, &Ctx) -> Result>, } impl PrimOp { pub fn call(&self, args: Vec>, ctx: &Ctx) -> Result> { if args.len() > self.arity { todo!() } if self.arity > args.len() { Value::PrimOpApp(Rc::new(PrimOpApp { name: self.name, arity: self.arity - args.len(), args, func: self.func, })) .ok() } else { (self.func)(args, ctx) } } } #[derive(Debug)] pub struct PrimOpApp { pub name: &'static str, arity: usize, args: Vec>, func: fn(Vec>, &Ctx) -> Result>, } impl Clone for PrimOpApp { fn clone(&self) -> Self { Self { name: self.name, arity: self.arity, args: self.args.clone(), func: self.func, } } } impl PrimOpApp { pub fn call(self: &mut Rc, args: Vec>, ctx: &Ctx) -> 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::PrimOpApp(self.clone()).ok(); }; ret } }