//! Defines the runtime representation of a partially applied primitive operation. use std::rc::Rc; use derive_more::Constructor; use nixjit_error::Result; use nixjit_ir::PrimOpId; use super::Value; use crate::EvalContext; pub type Args = smallvec::SmallVec<[Value; 2]>; /// Represents a partially applied primitive operation (builtin function). /// /// This struct holds the state of a primop that has received some, but not /// all, of its required arguments. #[derive(Debug, Clone, Constructor)] pub struct PrimOpApp { /// The number of remaining arguments the primop expects. arity: usize, /// The unique ID of the primop. id: PrimOpId, /// The arguments that have already been applied. args: Args, } impl PrimOpApp { /// Applies more arguments to a partially applied primop. /// /// If enough arguments are provided to satisfy the primop's arity, it is /// executed. Otherwise, it returns a new `PrimOpApp` with the combined /// arguments. pub fn call(self: Rc, arg: Value, ctx: &mut impl EvalContext) -> Result { let mut primop = Rc::unwrap_or_clone(self); if primop.arity == 1 { primop.args.push(arg); ctx.call_primop(primop.id, primop.args) } else { primop.args.push(arg); primop.arity -= 1; Ok(Value::PrimOpApp(primop.into())) } } }