use r_derive::*;
use crate::callable::core::*;
use crate::context::Context;
use crate::formals;
use crate::lang::*;
use crate::object::*;
#[doc(alias = "parent")]
#[builtin(sym = "parent")]
#[derive(Debug, Clone, PartialEq)]
pub struct PrimitiveParent;
formals!(PrimitiveParent, "(x,)");
impl Callable for PrimitiveParent {
fn call(&self, args: ExprList, stack: &mut CallStack) -> EvalResult {
let (vals, _) = self.match_arg_exprs(args, stack)?;
let mut vals = Obj::List(vals);
let x = vals.try_get_named("x");
if let Ok(Obj::Promise(_, Expr::Missing, _)) | Err(_) = x {
return Ok(stack
.env()
.parent
.clone()
.map_or(Obj::Null, Obj::Environment));
};
match vals.try_get_named("x")?.force(stack)?.environment() {
Some(e) => Ok(e.parent.clone().map_or(Obj::Null, Obj::Environment)),
None => Ok(Obj::Null),
}
}
}
#[cfg(test)]
mod test {
use crate::{r, r_expect};
#[test]
fn no_args() {
r_expect! {
parent(environment()) == parent()
}
}
#[test]
fn function_parent_env() {
r_expect! {{"
x <- function() { }
parent(x) == parent()
"}}
}
#[test]
fn nested_function_parent_env() {
r_expect! {{"
x <- function() { function() {} }
parent(x()) == environment(x)
"}}
}
}