use libR_sys::*;
use crate::robj::GetSexp;
use crate::robj::Robj;
use crate::single_threaded;
#[doc(hidden)]
#[macro_export]
macro_rules! push_args {
($args: expr, $name: ident = $val : expr) => {
$args.push((stringify!($name), Robj::from($val)));
};
($args: expr, $name: ident = $val : expr, $($rest: tt)*) => {
$args.push((stringify!($name), Robj::from($val)));
push_args!($args, $($rest)*);
};
($args: expr, $val : expr) => {
$args.push(("", Robj::from($val)));
};
($args: expr, $val : expr, $($rest: tt)*) => {
$args.push(("", Robj::from($val)));
push_args!($args, $($rest)*);
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! args {
() => {
Vec::<(&str, Robj)>::new()
};
($($rest: tt)*) => {
{
let mut args = Vec::<(&str, Robj)>::new();
push_args!(args, $($rest)*);
args
}
};
}
#[doc(hidden)]
pub unsafe fn append_with_name(tail: SEXP, obj: Robj, name: &str) -> SEXP {
single_threaded(|| {
let mut name = Vec::from(name.as_bytes());
name.push(0);
let cons = Rf_cons(obj.get(), R_NilValue);
SET_TAG(
cons,
Rf_install(name.as_ptr() as *const std::os::raw::c_char),
);
SETCDR(tail, cons);
cons
})
}
#[doc(hidden)]
pub unsafe fn append(tail: SEXP, obj: Robj) -> SEXP {
let cons = Rf_cons(obj.get(), R_NilValue);
SETCDR(tail, cons);
cons
}
#[doc(hidden)]
pub unsafe fn make_lang(sym: &str) -> Robj {
let mut name = Vec::from(sym.as_bytes());
name.push(0);
let sexp =
single_threaded(|| Rf_lang1(Rf_install(name.as_ptr() as *const std::os::raw::c_char)));
Robj::from_sexp(sexp)
}
#[doc(hidden)]
#[macro_export]
macro_rules! append_lang {
($tail: ident, $name: ident = $val : expr) => {
$tail = append_with_name($tail, Robj::from($val), stringify!($name));
};
($tail: ident, $name: ident = $val : expr, $($rest: tt)*) => {
$tail = append_with_name($tail, Robj::from($val), stringify!($name));
append_lang!($tail, $($rest)*);
};
($tail: ident, $val : expr) => {
$tail = append($tail, Robj::from($val));
};
($tail: ident, $val : expr, $($rest: tt)*) => {
$tail = append($tail, Robj::from($val));
append_lang!($tail, $($rest)*);
};
}
#[macro_export]
macro_rules! lang {
($sym : expr) => {
unsafe {
make_lang($sym)
}
};
($sym : expr, $($rest: tt)*) => {
unsafe {
use extendr_api::robj::GetSexp;
let res = make_lang($sym);
let mut tail = res.get();
append_lang!(tail, $($rest)*);
let _ = tail;
res
}
};
}