1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
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
}
};
}