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#[doc(hidden)]
10#[macro_export]
11macro_rules! push_args {
12 ($args: expr, $name: ident = $val : expr) => {
13 $args.push((stringify!($name), Robj::from($val)));
14 };
15 ($args: expr, $name: ident = $val : expr, $($rest: tt)*) => {
16 $args.push((stringify!($name), Robj::from($val)));
17 push_args!($args, $($rest)*);
18 };
19 ($args: expr, $val : expr) => {
20 $args.push(("", Robj::from($val)));
21 };
22 ($args: expr, $val : expr, $($rest: tt)*) => {
23 $args.push(("", Robj::from($val)));
24 push_args!($args, $($rest)*);
25 };
26}
27
28#[doc(hidden)]
29#[macro_export]
30macro_rules! args {
31 () => {
32 Vec::<(&str, Robj)>::new()
33 };
34 ($($rest: tt)*) => {
35 {
36 let mut args = Vec::<(&str, Robj)>::new();
37 push_args!(args, $($rest)*);
38 args
39 }
40 };
41}
42
43#[doc(hidden)]
44pub unsafe fn append_with_name(tail: SEXP, obj: Robj, name: &str) -> SEXP {
45 single_threaded(|| {
46 let cons = Rf_cons(obj.get(), R_NilValue);
47 SET_TAG(cons, crate::make_symbol(name));
48 SETCDR(tail, cons);
49 cons
50 })
51}
52
53#[doc(hidden)]
54#[allow(clippy::not_unsafe_ptr_arg_deref)]
55pub fn append(tail: SEXP, obj: Robj) -> SEXP {
56 single_threaded(|| unsafe {
57 let cons = Rf_cons(obj.get(), R_NilValue);
58 SETCDR(tail, cons);
59 cons
60 })
61}
62
63#[doc(hidden)]
64pub fn make_lang(sym: &str) -> Robj {
65 unsafe { Robj::from_sexp(single_threaded(|| Rf_lang1(crate::make_symbol(sym)))) }
66}
67
68#[doc(hidden)]
70#[macro_export]
71macro_rules! append_lang {
72 ($tail: ident, $name: ident = $val : expr) => {
73 $tail = append_with_name($tail, Robj::from($val), stringify!($name));
74 };
75 ($tail: ident, $name: ident = $val : expr, $($rest: tt)*) => {
76 $tail = append_with_name($tail, Robj::from($val), stringify!($name));
77 append_lang!($tail, $($rest)*);
78 };
79 ($tail: ident, $val : expr) => {
80 $tail = append($tail, Robj::from($val));
81 };
82 ($tail: ident, $val : expr, $($rest: tt)*) => {
83 $tail = append($tail, Robj::from($val));
84 append_lang!($tail, $($rest)*);
85 };
86}
87
88#[macro_export]
103macro_rules! lang {
104 ($sym : expr) => {
105 #[allow(unused_unsafe)]
106 unsafe {
107 make_lang($sym)
108 }
109 };
110 ($sym : expr, $($rest: tt)*) => {
111 unsafe {
112 use $crate::robj::GetSexp;
113 let res = make_lang($sym);
114 let mut tail = res.get();
115 append_lang!(tail, $($rest)*);
116 let _ = tail;
117 res
118 }
119 };
120}