Files
nixjit/evaluator/nixjit_eval/src/value/primop.rs
2025-08-15 23:14:21 +08:00

47 lines
1.4 KiB
Rust

//! 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<Self>, arg: Value, ctx: &mut impl EvalContext) -> Result<Value> {
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()))
}
}
}