47 lines
1.4 KiB
Rust
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()))
|
|
}
|
|
}
|
|
}
|