1 #include <rlang.h>
2 #include "../internal/utils.h"
3 
4 
5 // attrs.c
6 
rlang_poke_attrib(sexp * x,sexp * attrs)7 sexp* rlang_poke_attrib(sexp* x, sexp* attrs) {
8   SET_ATTRIB(x, attrs);
9   return x;
10 }
11 
12 
13 // cnd.c
14 
rlang_cnd_signal(sexp * cnd)15 sexp* rlang_cnd_signal(sexp* cnd) {
16   r_cnd_signal(cnd);
17   return r_null;
18 }
19 
rlang_cnd_type(sexp * cnd)20 sexp* rlang_cnd_type(sexp* cnd) {
21   enum r_condition_type type = r_cnd_type(cnd);
22   switch (type) {
23   case r_cnd_type_condition: return r_chr("condition");
24   case r_cnd_type_message: return r_chr("message");
25   case r_cnd_type_warning: return r_chr("warning");
26   case r_cnd_type_error: return r_chr("error");
27   case r_cnd_type_interrupt: return r_chr("interrupt");
28   default: r_abort("Internal error: Unhandled `r_condition_type`");
29   }
30 }
31 
rlang_interrupt()32 sexp* rlang_interrupt() {
33   r_interrupt();
34   return r_null;
35 }
36 
37 
38 // env.c
39 
rlang_env_poke_parent(sexp * env,sexp * new_parent)40 sexp* rlang_env_poke_parent(sexp* env, sexp* new_parent) {
41   if (R_IsNamespaceEnv(env)) {
42     r_abort("Can't change the parent of a namespace environment");
43   }
44   if (R_IsPackageEnv(env)) {
45     r_abort("Can't change the parent of a package environment");
46   }
47   if (R_EnvironmentIsLocked(env)) {
48     r_abort("Can't change the parent of a locked environment");
49   }
50   if (env == r_global_env) {
51     r_abort("Can't change the parent of the global environment");
52   }
53   if (env == r_base_env) {
54     r_abort("Can't change the parent of the base environment");
55   }
56   if (env == r_empty_env) {
57     r_abort("Can't change the parent of the empty environment");
58   }
59 
60   SET_ENCLOS(env, new_parent);
61   return env;
62 }
63 
rlang_env_frame(sexp * env)64 sexp* rlang_env_frame(sexp* env) {
65   return FRAME(env);
66 }
rlang_env_hash_table(sexp * env)67 sexp* rlang_env_hash_table(sexp* env) {
68   return HASHTAB(env);
69 }
70 
rlang_env_inherits(sexp * env,sexp * ancestor)71 sexp* rlang_env_inherits(sexp* env, sexp* ancestor) {
72   return r_lgl(r_env_inherits(env, ancestor, r_empty_env));
73 }
74 
rlang_env_bind_list(sexp * env,sexp * names,sexp * data)75 sexp* rlang_env_bind_list(sexp* env, sexp* names, sexp* data) {
76   if (r_typeof(env) != r_type_environment) {
77     r_abort("Internal error: `env` must be an environment.");
78   }
79   if (r_typeof(names) != r_type_character) {
80     r_abort("Internal error: `names` must be a character vector.");
81   }
82   if (r_typeof(data) != r_type_list) {
83     r_abort("Internal error: `data` must be a list.");
84   }
85 
86   r_ssize n = r_length(data);
87   if (n != r_length(names)) {
88     r_abort("Internal error: `data` and `names` must have the same length.");
89   }
90 
91   sexp* const * p_names = r_chr_deref_const(names);
92 
93   for (r_ssize i = 0; i < n; ++i) {
94     Rf_defineVar(r_str_as_symbol(p_names[i]), r_list_get(data, i), env);
95   }
96 
97   return r_null;
98 }
99 
rlang_env_browse(sexp * env,sexp * value)100 sexp* rlang_env_browse(sexp* env, sexp* value) {
101   if (r_typeof(env) != r_type_environment) {
102     r_abort("`env` must be an environment.");
103   }
104   if (!r_is_bool(value)) {
105     r_abort("`value` must be a single logical value.");
106   }
107 
108   sexp* old = r_lgl(RDEBUG(env));
109   SET_RDEBUG(env, r_lgl_get(value, 0));
110   return old;
111 }
112 
rlang_env_is_browsed(sexp * env)113 sexp* rlang_env_is_browsed(sexp* env) {
114   if (r_typeof(env) != r_type_environment) {
115     r_abort("`env` must be an environment.");
116   }
117   return r_lgl(RDEBUG(env));
118 }
119 
rlang_ns_registry_env()120 sexp* rlang_ns_registry_env() {
121   return R_NamespaceRegistry;
122 }
123 
124 
125 // eval.c
126 
rlang_ext2_eval(sexp * call,sexp * op,sexp * args,sexp * env)127 sexp* rlang_ext2_eval(sexp* call, sexp* op, sexp* args, sexp* env) {
128   args = r_node_cdr(args);
129   return Rf_eval(r_node_car(args), r_node_cadr(args));
130 }
131 
rlang_eval_top(sexp * expr,sexp * env)132 sexp* rlang_eval_top(sexp* expr, sexp* env) {
133   int jumped = 0;
134   sexp* out = R_tryEval(expr, env, &jumped);
135 
136   if (jumped) {
137     r_abort("Top level jump");
138   } else {
139     return out;
140   }
141 }
142 
143 // fn.c
144 
rlang_is_function(sexp * x)145 sexp* rlang_is_function(sexp* x) {
146   return r_shared_lgl(r_is_function(x));
147 }
148 
rlang_is_closure(sexp * x)149 sexp* rlang_is_closure(sexp* x) {
150   return r_shared_lgl(r_is_closure(x));
151 }
152 
rlang_is_primitive(sexp * x)153 sexp* rlang_is_primitive(sexp* x) {
154   return r_shared_lgl(r_is_primitive(x));
155 }
rlang_is_primitive_lazy(sexp * x)156 sexp* rlang_is_primitive_lazy(sexp* x) {
157   return r_shared_lgl(r_is_primitive_lazy(x));
158 }
rlang_is_primitive_eager(sexp * x)159 sexp* rlang_is_primitive_eager(sexp* x) {
160   return r_shared_lgl(r_is_primitive_eager(x));
161 }
162 
163 
164 // formula.c
165 
rlang_is_formula(sexp * x,sexp * scoped,sexp * lhs)166 sexp* rlang_is_formula(sexp* x, sexp* scoped, sexp* lhs) {
167   int scoped_int = r_as_optional_bool(scoped);
168   int lhs_int = r_as_optional_bool(lhs);
169 
170   bool out = r_is_formula(x, scoped_int, lhs_int);
171   return r_lgl(out);
172 }
173 
rlang_is_formulaish(sexp * x,sexp * scoped,sexp * lhs)174 sexp* rlang_is_formulaish(sexp* x, sexp* scoped, sexp* lhs) {
175   int scoped_int = r_as_optional_bool(scoped);
176   int lhs_int = r_as_optional_bool(lhs);
177 
178   bool out = r_is_formulaish(x, scoped_int, lhs_int);
179   return r_lgl(out);
180 }
181 
182 
183 // parse.c
184 
rlang_call_has_precedence(sexp * x,sexp * y,sexp * side)185 sexp* rlang_call_has_precedence(sexp* x, sexp* y, sexp* side) {
186   bool has_predence;
187   if (side == r_null) {
188     has_predence = r_call_has_precedence(x, y);
189   } else if (r_is_string(side, "lhs")) {
190     has_predence = r_lhs_call_has_precedence(x, y);
191   } else if (r_is_string(side, "rhs")) {
192     has_predence = r_rhs_call_has_precedence(x, y);
193   } else {
194     r_abort("`side` must be NULL, \"lhs\" or \"rhs\"");
195   }
196   return r_lgl(has_predence);
197 }
198 
rlang_which_operator(sexp * call)199 sexp* rlang_which_operator(sexp* call) {
200   const char* op = r_op_as_c_string(r_which_operator(call));
201   return r_chr(op);
202 }
203 
204 
205 // node.c
206 
rlang_node_car(sexp * x)207 sexp* rlang_node_car(sexp* x) {
208   return CAR(x);
209 }
rlang_node_cdr(sexp * x)210 sexp* rlang_node_cdr(sexp* x) {
211   return CDR(x);
212 }
rlang_node_caar(sexp * x)213 sexp* rlang_node_caar(sexp* x) {
214   return CAAR(x);
215 }
rlang_node_cadr(sexp * x)216 sexp* rlang_node_cadr(sexp* x) {
217   return CADR(x);
218 }
rlang_node_cdar(sexp * x)219 sexp* rlang_node_cdar(sexp* x) {
220   return CDAR(x);
221 }
rlang_node_cddr(sexp * x)222 sexp* rlang_node_cddr(sexp* x) {
223   return CDDR(x);
224 }
rlang_node_tail(sexp * x)225 sexp* rlang_node_tail(sexp* x) {
226   while (CDR(x) != r_null)
227     x = CDR(x);
228   return x;
229 }
230 
rlang_node_poke_car(sexp * x,sexp * newcar)231 sexp* rlang_node_poke_car(sexp* x, sexp* newcar) {
232   SETCAR(x, newcar);
233   return x;
234 }
rlang_node_poke_cdr(sexp * x,sexp * newcdr)235 sexp* rlang_node_poke_cdr(sexp* x, sexp* newcdr) {
236   SETCDR(x, newcdr);
237   return x;
238 }
rlang_node_poke_caar(sexp * x,sexp * newcaar)239 sexp* rlang_node_poke_caar(sexp* x, sexp* newcaar) {
240   SETCAR(CAR(x), newcaar);
241   return x;
242 }
rlang_node_poke_cadr(sexp * x,sexp * newcar)243 sexp* rlang_node_poke_cadr(sexp* x, sexp* newcar) {
244   SETCADR(x, newcar);
245   return x;
246 }
rlang_node_poke_cdar(sexp * x,sexp * newcdar)247 sexp* rlang_node_poke_cdar(sexp* x, sexp* newcdar) {
248   SETCDR(CAR(x), newcdar);
249   return x;
250 }
rlang_node_poke_cddr(sexp * x,sexp * newcdr)251 sexp* rlang_node_poke_cddr(sexp* x, sexp* newcdr) {
252   SETCDR(CDR(x), newcdr);
253   return x;
254 }
255 
rlang_node_tag(sexp * x)256 sexp* rlang_node_tag(sexp* x) {
257   return TAG(x);
258 }
rlang_node_poke_tag(sexp * x,sexp * tag)259 sexp* rlang_node_poke_tag(sexp* x, sexp* tag) {
260   SET_TAG(x, tag);
261   return x;
262 }
263 
rlang_on_exit(sexp * expr,sexp * frame)264 sexp* rlang_on_exit(sexp* expr, sexp* frame) {
265   r_on_exit(expr, frame);
266   return r_null;
267 }
268 
269 
270 // lang.h
271 
rlang_new_call_node(sexp * car,sexp * cdr)272 sexp* rlang_new_call_node(sexp* car, sexp* cdr) {
273   return Rf_lcons(car, cdr);
274 }
275 
276 
277 // quo.h
278 
279 #include "../internal/quo.h"
280 
rlang_quo_is_missing(sexp * quo)281 sexp* rlang_quo_is_missing(sexp* quo) {
282   check_quosure(quo);
283   return r_lgl(quo_is_missing(quo));
284 }
rlang_quo_is_symbol(sexp * quo)285 sexp* rlang_quo_is_symbol(sexp* quo) {
286   check_quosure(quo);
287   return r_lgl(quo_is_symbol(quo));
288 }
rlang_quo_is_call(sexp * quo)289 sexp* rlang_quo_is_call(sexp* quo) {
290   check_quosure(quo);
291   return r_lgl(quo_is_call(quo));
292 }
rlang_quo_is_symbolic(sexp * quo)293 sexp* rlang_quo_is_symbolic(sexp* quo) {
294   check_quosure(quo);
295   return r_lgl(quo_is_symbolic(quo));
296 }
rlang_quo_is_null(sexp * quo)297 sexp* rlang_quo_is_null(sexp* quo) {
298   check_quosure(quo);
299   return r_lgl(quo_is_null(quo));
300 }
301 
302 
303 // sexp.h
304 
rlang_length(sexp * x)305 sexp* rlang_length(sexp* x) {
306   return r_int(r_length(x));
307 }
rlang_true_length(sexp * x)308 sexp* rlang_true_length(sexp* x) {
309   return r_int(XTRUELENGTH(x));
310 }
311 
rlang_is_reference(sexp * x,sexp * y)312 sexp* rlang_is_reference(sexp* x, sexp* y) {
313   return r_lgl(x == y);
314 }
315 
rlang_missing_arg()316 sexp* rlang_missing_arg() {
317   return R_MissingArg;
318 }
319 
rlang_duplicate(sexp * x,sexp * shallow)320 sexp* rlang_duplicate(sexp* x, sexp* shallow) {
321   return r_duplicate(x, r_lgl_get(shallow, 0));
322 }
323 
rlang_sexp_address(sexp * x)324 sexp* rlang_sexp_address(sexp* x) {
325   static char str[1000];
326   snprintf(str, 1000, "%p", (void*) x);
327   return Rf_mkString(str);
328 }
329 
rlang_poke_type(sexp * x,sexp * type)330 sexp* rlang_poke_type(sexp* x, sexp* type) {
331   SET_TYPEOF(x, Rf_str2type(r_chr_get_c_string(type, 0)));
332   return x;
333 }
334 
rlang_mark_object(sexp * x)335 sexp* rlang_mark_object(sexp* x) {
336   SET_OBJECT(x, 1);
337   return x;
338 }
rlang_unmark_object(sexp * x)339 sexp* rlang_unmark_object(sexp* x) {
340   SET_OBJECT(x, 0);
341   return x;
342 }
343 
rlang_get_promise(sexp * x,sexp * env)344 sexp* rlang_get_promise(sexp* x, sexp* env) {
345   switch (r_typeof(x)) {
346   case r_type_promise:
347     return x;
348   case r_type_character:
349     if (r_length(x) == 1) {
350       x = r_sym(r_chr_get_c_string(x, 0));
351     } else {
352       goto error;
353     }
354     // fallthrough
355   case r_type_symbol: {
356       sexp* prom = r_env_find_anywhere(env, x);
357       if (r_typeof(prom) == r_type_promise) {
358         return prom;
359       }
360       // fallthrough
361     }
362   error:
363   default:
364     r_abort("`x` must be or refer to a local promise");
365   }
366 }
367 
rlang_promise_expr(sexp * x,sexp * env)368 sexp* rlang_promise_expr(sexp* x, sexp* env) {
369   sexp* prom = rlang_get_promise(x, env);
370   return PREXPR(prom);
371 }
rlang_promise_env(sexp * x,sexp * env)372 sexp* rlang_promise_env(sexp* x, sexp* env) {
373   sexp* prom = rlang_get_promise(x, env);
374   return PRENV(prom);
375 }
rlang_promise_value(sexp * x,sexp * env)376 sexp* rlang_promise_value(sexp* x, sexp* env) {
377   sexp* prom = rlang_get_promise(x, env);
378   sexp* value = PRVALUE(prom);
379   if (value == r_syms_unbound) {
380     return r_sym("R_UnboundValue");
381   } else {
382     return value;
383   }
384 }
385 
rlang_attrib(sexp * x)386 sexp* rlang_attrib(sexp* x) {
387   return ATTRIB(x);
388 }
389 
390 // Picks up symbols from parent environment to avoid bumping namedness
391 // during promise resolution
rlang_named(sexp * x,sexp * env)392 sexp* rlang_named(sexp* x, sexp* env) {
393   int n_protect = 0;
394 
395   x = PROTECT(Rf_findVarInFrame3(env, x, FALSE));
396   ++n_protect;
397 
398   if (TYPEOF(x) == PROMSXP) {
399     x = PROTECT(Rf_eval(x, env));
400     ++n_protect;
401   }
402 
403   UNPROTECT(n_protect);
404   return Rf_ScalarInteger(NAMED(x));
405 }
406 
rlang_find_var(sexp * env,sexp * sym)407 sexp* rlang_find_var(sexp* env, sexp* sym) {
408   return Rf_findVar(sym, env);
409 }
410 
rlang_chr_get(sexp * x,sexp * i)411 sexp* rlang_chr_get(sexp* x, sexp* i) {
412   if (r_typeof(i) != r_type_integer || r_length(i) != 1) {
413     r_abort("`i` must be an integer value.");
414   }
415 
416   int c_i = r_int_get(i, 0);
417   if (c_i < 0 || c_i >= r_length(x)) {
418     r_abort("`i` is out of bound. Note that `r_chr_get()` takes zero-based locations.");
419   }
420 
421   return r_chr_get(x, c_i);
422 }
423 
424 
425 // vec.h
426 
rlang_vec_alloc(sexp * type,sexp * n)427 sexp* rlang_vec_alloc(sexp* type, sexp* n) {
428   return Rf_allocVector(Rf_str2type(r_chr_get_c_string(type, 0)), r_int_get(n, 0));
429 }
rlang_vec_coerce(sexp * x,sexp * type)430 sexp* rlang_vec_coerce(sexp* x, sexp* type) {
431   return Rf_coerceVector(x, Rf_str2type(r_chr_get_c_string(type, 0)));
432 }
433 
434 // TODO: C-level check for scalar integerish
r_as_int(sexp * x)435 int r_as_int(sexp* x) {
436   switch(r_typeof(x)) {
437   case r_type_integer: return *INTEGER(x);
438   case r_type_double: return (int) *REAL(x);
439   default: r_abort("Internal error: Expected integerish input");
440   }
441 }
442 
rlang_vec_poke_n(sexp * x,sexp * offset,sexp * y,sexp * from,sexp * n)443 sexp* rlang_vec_poke_n(sexp* x, sexp* offset,
444                        sexp* y, sexp* from, sexp* n) {
445   r_ssize offset_size = r_as_ssize(offset) - 1;
446   r_ssize from_size = r_as_ssize(from) - 1;
447   r_ssize n_size = r_as_ssize(n);
448 
449   r_vec_poke_n(x, offset_size, y, from_size, n_size);
450   return x;
451 }
452 
rlang_vec_poke_range(sexp * x,sexp * offset,sexp * y,sexp * from,sexp * to)453 sexp* rlang_vec_poke_range(sexp* x, sexp* offset,
454                            sexp* y, sexp* from, sexp* to) {
455   r_ssize offset_size = r_as_ssize(offset) - 1;
456   r_ssize from_size = r_as_ssize(from) - 1;
457   r_ssize to_size = r_as_ssize(to) - 1;
458 
459   r_vec_poke_range(x, offset_size, y, from_size, to_size);
460   return x;
461 }
462 
463 
464 // vec-list.h
465 
validate_n(sexp * n)466 static r_ssize validate_n(sexp* n) {
467   if (n == r_null) {
468     return -1;
469   }
470 
471   switch (r_typeof(n)) {
472   case r_type_integer:
473   case r_type_double:
474     if (r_length(n) == 1) {
475       break;
476     }
477     // fallthrough
478   default:
479     r_abort("`n` must be NULL or a scalar integer");
480   }
481 
482   return r_as_ssize(n);
483 }
484 
validate_finite(sexp * finite)485 static int validate_finite(sexp* finite) {
486   switch (r_typeof(finite)) {
487   case r_type_null:
488     return -1;
489   case r_type_integer:
490   case r_type_double:
491     finite = r_vec_coerce(finite, r_type_logical);
492   case r_type_logical: {
493     int value = r_lgl_get(finite, 0);
494     if (value != NA_LOGICAL) {
495       return r_lgl_get(finite, 0);
496     } // else fallthrough
497   }
498   default:
499     r_abort("`finite` must be NULL or a scalar logical");
500   }
501 }
502 
rlang_is_finite(sexp * x)503 sexp* rlang_is_finite(sexp* x) {
504   return r_shared_lgl(r_is_finite(x));
505 }
506 
rlang_is_list(sexp * x,sexp * n_)507 sexp* rlang_is_list(sexp* x, sexp* n_) {
508   r_ssize n = validate_n(n_);
509   return r_shared_lgl(r_is_list(x, n));
510 }
511 
rlang_is_atomic(sexp * x,sexp * n_)512 sexp* rlang_is_atomic(sexp* x, sexp* n_) {
513   r_ssize n = validate_n(n_);
514   return r_shared_lgl(r_is_atomic(x, n));
515 }
rlang_is_vector(sexp * x,sexp * n_)516 sexp* rlang_is_vector(sexp* x, sexp* n_) {
517   r_ssize n = validate_n(n_);
518   return r_shared_lgl(r_is_vector(x, n));
519 }
520 
rlang_is_logical(sexp * x,sexp * n_)521 sexp* rlang_is_logical(sexp* x, sexp* n_) {
522   r_ssize n = validate_n(n_);
523   return r_shared_lgl(r_is_logical(x, n));
524 }
rlang_is_integer(sexp * x,sexp * n_)525 sexp* rlang_is_integer(sexp* x, sexp* n_) {
526   r_ssize n = validate_n(n_);
527   return r_shared_lgl(r_is_integer(x, n, -1));
528 }
rlang_is_double(sexp * x,sexp * n_,sexp * finite_)529 sexp* rlang_is_double(sexp* x, sexp* n_, sexp* finite_) {
530   r_ssize n = validate_n(n_);
531   int finite = validate_finite(finite_);
532   return r_shared_lgl(r_is_double(x, n, finite));
533 }
rlang_is_integerish(sexp * x,sexp * n_,sexp * finite_)534 sexp* rlang_is_integerish(sexp* x, sexp* n_, sexp* finite_) {
535   r_ssize n = validate_n(n_);
536   int finite = validate_finite(finite_);
537   return r_shared_lgl(r_is_integerish(x, n, finite));
538 }
539 
rlang_is_character(sexp * x,sexp * n_)540 sexp* rlang_is_character(sexp* x, sexp* n_) {
541   r_ssize n = validate_n(n_);
542   return r_shared_lgl(r_is_character(x, n));
543 }
rlang_is_raw(sexp * x,sexp * n_)544 sexp* rlang_is_raw(sexp* x, sexp* n_) {
545   r_ssize n = validate_n(n_);
546   return r_shared_lgl(r_is_raw(x, n));
547 }
548 
rlang_is_string(sexp * x,sexp * string)549 sexp* rlang_is_string(sexp* x, sexp* string) {
550   if (r_typeof(x) != r_type_character || r_length(x) != 1) {
551     return r_shared_false;
552   }
553 
554   sexp* value = r_chr_get(x, 0);
555 
556   if (value == NA_STRING) {
557     return r_shared_false;
558   }
559 
560   if (string == r_null) {
561     return r_shared_true;
562   }
563 
564   if (!rlang_is_string(string, r_null)) {
565     r_abort("`string` must be `NULL` or a string");
566   }
567 
568   bool out = false;
569   r_ssize n = r_length(string);
570   sexp* const * p_string = r_chr_deref_const(string);
571 
572   for (r_ssize i = 0; i < n; ++i) {
573     if (p_string[i] == value) {
574       out = true;
575       break;
576     }
577   }
578 
579   return r_shared_lgl(out);
580 }
581