extendr_api/
lang_macros.rs1use crate::robj::GetSexp;
5use crate::robj::Robj;
6use crate::single_threaded;
7use extendr_ffi::{R_NilValue, Rf_cons, Rf_lang1, SETCDR, SET_TAG, SEXP};
8
9#[doc(hidden)]
10pub unsafe fn append_with_name(tail: SEXP, obj: Robj, name: &str) -> SEXP {
11 single_threaded(|| {
12 let cons = Rf_cons(obj.get(), R_NilValue);
13 SET_TAG(cons, crate::make_symbol(name));
14 SETCDR(tail, cons);
15 cons
16 })
17}
18
19#[doc(hidden)]
20#[allow(clippy::not_unsafe_ptr_arg_deref)]
21pub fn append(tail: SEXP, obj: Robj) -> SEXP {
22 single_threaded(|| unsafe {
23 let cons = Rf_cons(obj.get(), R_NilValue);
24 SETCDR(tail, cons);
25 cons
26 })
27}
28
29#[doc(hidden)]
30pub fn make_lang(sym: &str) -> Robj {
31 unsafe { Robj::from_sexp(single_threaded(|| Rf_lang1(crate::make_symbol(sym)))) }
32}
33
34#[doc(hidden)]
36#[macro_export]
37macro_rules! append_lang {
38 ($tail: ident, $name: ident = $val : expr) => {
39 $tail = $crate::append_with_name($tail, $crate::Robj::from($val), stringify!($name));
40 };
41 ($tail: ident, $name: ident = $val : expr, $($rest: tt)*) => {
42 $tail = $crate::append_with_name($tail, $crate::Robj::from($val), stringify!($name));
43 $crate::append_lang!($tail, $($rest)*);
44 };
45 ($tail: ident, $val : expr) => {
46 $tail = $crate::append($tail, $crate::Robj::from($val));
47 };
48 ($tail: ident, $val : expr, $($rest: tt)*) => {
49 $tail = $crate::append($tail, $crate::Robj::from($val));
50 $crate::append_lang!($tail, $($rest)*);
51 };
52}
53
54#[macro_export]
69macro_rules! lang {
70 ($sym : expr) => {
71 $crate::make_lang($sym)
72 };
73 ($sym : expr, $($rest: tt)*) => {
74 unsafe {
75 use $crate::robj::GetSexp;
76 let res = $crate::make_lang($sym);
77 let mut tail = res.get();
78 $crate::append_lang!(tail, $($rest)*);
79 let _ = tail;
80 res
81 }
82 };
83}