extendr_api/
lang_macros.rs
1use 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)]
54pub unsafe fn append(tail: SEXP, obj: Robj) -> SEXP {
55 single_threaded(|| {
56 let cons = Rf_cons(obj.get(), R_NilValue);
57 SETCDR(tail, cons);
58 cons
59 })
60}
61
62#[doc(hidden)]
63pub unsafe fn make_lang(sym: &str) -> Robj {
64 Robj::from_sexp(single_threaded(|| Rf_lang1(crate::make_symbol(sym))))
65}
66
67#[doc(hidden)]
69#[macro_export]
70macro_rules! append_lang {
71 ($tail: ident, $name: ident = $val : expr) => {
72 $tail = append_with_name($tail, Robj::from($val), stringify!($name));
73 };
74 ($tail: ident, $name: ident = $val : expr, $($rest: tt)*) => {
75 $tail = append_with_name($tail, Robj::from($val), stringify!($name));
76 append_lang!($tail, $($rest)*);
77 };
78 ($tail: ident, $val : expr) => {
79 $tail = append($tail, Robj::from($val));
80 };
81 ($tail: ident, $val : expr, $($rest: tt)*) => {
82 $tail = append($tail, Robj::from($val));
83 append_lang!($tail, $($rest)*);
84 };
85}
86
87#[macro_export]
102macro_rules! lang {
103 ($sym : expr) => {
104 unsafe {
105 make_lang($sym)
106 }
107 };
108 ($sym : expr, $($rest: tt)*) => {
109 unsafe {
110 use extendr_api::robj::GetSexp;
111 let res = make_lang($sym);
112 let mut tail = res.get();
113 append_lang!(tail, $($rest)*);
114 let _ = tail;
115 res
116 }
117 };
118}