use super::*;
#[derive(PartialEq, Clone)]
pub struct Function {
pub(crate) robj: Robj,
}
impl Function {
pub fn from_parts(formals: Pairlist, body: Language, env: Environment) -> Result<Self> {
unsafe {
let sexp = Rf_allocSExp(CLOSXP);
let robj = Robj::from_sexp(sexp);
SET_FORMALS(sexp, formals.get());
SET_BODY(sexp, body.get());
SET_CLOENV(sexp, env.get());
Ok(Function { robj })
}
}
pub fn call(&self, args: Pairlist) -> Result<Robj> {
unsafe {
let call = Robj::from_sexp(Rf_lcons(self.get(), args.get()));
call.eval()
}
}
pub fn formals(&self) -> Option<Pairlist> {
unsafe {
if self.rtype() == Rtype::Function {
let sexp = self.robj.get();
Some(Robj::from_sexp(FORMALS(sexp)).try_into().unwrap())
} else {
None
}
}
}
pub fn body(&self) -> Option<Robj> {
unsafe {
if self.rtype() == Rtype::Function {
let sexp = self.robj.get();
Some(Robj::from_sexp(BODY(sexp)))
} else {
None
}
}
}
pub fn environment(&self) -> Option<Environment> {
unsafe {
if self.rtype() == Rtype::Function {
let sexp = self.robj.get();
Some(
Robj::from_sexp(CLOENV(sexp))
.try_into()
.expect("Should be an environment"),
)
} else {
None
}
}
}
}
impl std::fmt::Debug for Function {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.deparse().unwrap())
}
}