|
7 | 7 |
|
8 | 8 | use libr::*;
|
9 | 9 |
|
| 10 | +use crate::exec::RFunction; |
| 11 | +use crate::exec::RFunctionExt; |
10 | 12 | use crate::object::RObject;
|
11 |
| -use crate::protect::RProtect; |
12 | 13 | use crate::r_symbol;
|
13 | 14 | use crate::utils::r_typeof;
|
14 | 15 |
|
@@ -39,42 +40,32 @@ impl RCall {
|
39 | 40 |
|
40 | 41 | pub fn build(&self) -> RObject {
|
41 | 42 | unsafe {
|
42 |
| - let mut protect = RProtect::new(); |
43 |
| - |
44 |
| - // Now, build the actual call to be evaluated |
45 |
| - let size = (1 + self.arguments.len()) as R_xlen_t; |
46 |
| - let call = protect.add(Rf_allocVector(LANGSXP, size)); |
47 |
| - SET_TAG(call, R_NilValue); |
48 |
| - SETCAR(call, self.function.sexp); |
| 43 | + let call = RObject::new(Rf_lcons(self.function.sexp, R_NilValue)); |
| 44 | + let mut tail = call.sexp; |
49 | 45 |
|
50 | 46 | // Append arguments to the call
|
51 |
| - let mut slot = CDR(call); |
52 | 47 | for argument in self.arguments.iter() {
|
53 |
| - // Quote language objects by default |
54 |
| - // FIXME: Shouldn't this be done by the caller? |
55 |
| - let mut sexp = argument.value.sexp; |
56 |
| - if matches!(r_typeof(sexp), LANGSXP | SYMSXP | EXPRSXP) { |
57 |
| - let quote = protect.add(Rf_lang3( |
58 |
| - r_symbol!("::"), |
59 |
| - r_symbol!("base"), |
60 |
| - r_symbol!("quote"), |
61 |
| - )); |
62 |
| - sexp = protect.add(Rf_lang2(quote, sexp)); |
63 |
| - } |
| 48 | + SETCDR(tail, Rf_cons(argument.value.sexp, R_NilValue)); |
64 | 49 |
|
65 |
| - SETCAR(slot, sexp); |
| 50 | + tail = CDR(tail); |
66 | 51 | if !argument.name.is_empty() {
|
67 |
| - SET_TAG(slot, r_symbol!(argument.name)); |
| 52 | + SET_TAG(tail, r_symbol!(argument.name)); |
68 | 53 | }
|
69 |
| - |
70 |
| - slot = CDR(slot); |
71 | 54 | }
|
72 | 55 |
|
73 |
| - RObject::new(call) |
| 56 | + call |
74 | 57 | }
|
75 | 58 | }
|
76 | 59 | }
|
77 | 60 |
|
| 61 | +pub fn r_expr_quote(x: impl Into<SEXP>) -> RObject { |
| 62 | + let x = x.into(); |
| 63 | + match r_typeof(x) { |
| 64 | + SYMSXP | LANGSXP => return RFunction::new("base", "quote").add(x).call.build(), |
| 65 | + _ => return x.into(), |
| 66 | + } |
| 67 | +} |
| 68 | + |
78 | 69 | pub struct RArgument {
|
79 | 70 | pub name: String,
|
80 | 71 | pub value: RObject,
|
|
0 commit comments