1 #include <rlang.h>
2 #include "dots.h"
3 #include "expr-interp.h"
4 #include "internal.h"
5 #include "utils.h"
6
7 sexp* rlang_ns_get(const char* name);
8 static bool should_auto_name(sexp* named);
9
10 static sexp* as_label_call = NULL;
r_as_label(sexp * x)11 static sexp* r_as_label(sexp* x) {
12 return r_eval_with_x(as_label_call, rlang_ns_env, x);
13 }
14
15 // Initialised at load time
16 static sexp* empty_spliced_arg = NULL;
17 static sexp* splice_box_attrib = NULL;
18 static sexp* quosures_attrib = NULL;
19
rlang_new_splice_box(sexp * x)20 sexp* rlang_new_splice_box(sexp* x) {
21 sexp* out = KEEP(r_new_vector(r_type_list, 1));
22 r_list_poke(out, 0, x);
23 r_poke_attrib(out, splice_box_attrib);
24 r_mark_object(out);
25 FREE(1);
26 return out;
27 }
is_splice_box(sexp * x)28 bool is_splice_box(sexp* x) {
29 return r_attrib(x) == splice_box_attrib;
30 }
rlang_is_splice_box(sexp * x)31 sexp* rlang_is_splice_box(sexp* x) {
32 return r_lgl(is_splice_box(x));
33 }
rlang_unbox(sexp * x)34 sexp* rlang_unbox(sexp* x) {
35 if (r_length(x) != 1) {
36 r_abort("Internal error: Expected a list of size 1 in `rlang_unbox()`.");
37 }
38 return r_list_get(x, 0);
39 }
40
41
42 enum dots_homonyms {
43 DOTS_HOMONYMS_KEEP = 0,
44 DOTS_HOMONYMS_FIRST,
45 DOTS_HOMONYMS_LAST,
46 DOTS_HOMONYMS_ERROR
47 };
48
49 struct dots_capture_info {
50 enum dots_capture_type type;
51 r_ssize count;
52 sexp* named;
53 bool needs_expansion;
54 int ignore_empty;
55 bool preserve_empty;
56 bool unquote_names;
57 enum dots_homonyms homonyms;
58 bool check_assign;
59 sexp* (*big_bang_coerce)(sexp*);
60 bool splice;
61 };
62
63 static int arg_match_ignore_empty(sexp* ignore_empty);
64 static enum dots_homonyms arg_match_homonyms(sexp* homonyms);
65
init_capture_info(enum dots_capture_type type,sexp * named,sexp * ignore_empty,sexp * preserve_empty,sexp * unquote_names,sexp * homonyms,sexp * check_assign,sexp * (* coercer)(sexp *),bool splice)66 struct dots_capture_info init_capture_info(enum dots_capture_type type,
67 sexp* named,
68 sexp* ignore_empty,
69 sexp* preserve_empty,
70 sexp* unquote_names,
71 sexp* homonyms,
72 sexp* check_assign,
73 sexp* (*coercer)(sexp*),
74 bool splice) {
75 struct dots_capture_info info;
76
77 info.type = type;
78 info.count = 0;
79 info.needs_expansion = false;
80 info.named = named;
81 info.ignore_empty = arg_match_ignore_empty(ignore_empty);
82 info.preserve_empty = r_lgl_get(preserve_empty, 0);
83 info.unquote_names = r_lgl_get(unquote_names, 0);
84 info.homonyms = arg_match_homonyms(homonyms);
85 info.check_assign = r_lgl_get(check_assign, 0);
86 info.big_bang_coerce = coercer;
87 info.splice = splice;
88
89 return info;
90 }
91
92
93 static bool has_glue = false;
rlang_glue_is_there()94 sexp* rlang_glue_is_there() {
95 has_glue = true;
96 return r_null;
97 }
98
has_curly(const char * str)99 static bool has_curly(const char* str) {
100 for (char c = *str; c != '\0'; ++str, c = *str) {
101 if (c == '{') {
102 return true;
103 }
104 }
105 return false;
106 }
107
require_glue()108 static void require_glue() {
109 sexp* call = KEEP(r_parse("is_installed('glue')"));
110 sexp* out = KEEP(r_eval(call, rlang_ns_env));
111
112 if (!r_is_bool(out)) {
113 r_abort("Internal error: Expected scalar logical from `requireNamespace()`.");
114 }
115 if (!r_lgl_get(out, 0)) {
116 r_abort("Can't use `{` symbols in LHS of `:=` if glue is not installed.");
117 }
118
119 FREE(2);
120 }
121
122 // Initialised at load time
123 static sexp* glue_unquote_fn = NULL;
124
glue_unquote(sexp * lhs,sexp * env)125 static sexp* glue_unquote(sexp* lhs, sexp* env) {
126 if (r_typeof(lhs) != r_type_character ||
127 r_length(lhs) != 1 ||
128 !has_curly(r_chr_get_c_string(lhs, 0))) {
129 return lhs;
130 }
131
132 if (!has_glue) {
133 require_glue();
134 }
135
136 sexp* glue_unquote_call = KEEP(r_call2(glue_unquote_fn, lhs));
137 lhs = r_eval(glue_unquote_call, env);
138 FREE(1);
139 return lhs;
140 }
141
def_unquote_name(sexp * expr,sexp * env)142 static sexp* def_unquote_name(sexp* expr, sexp* env) {
143 int n_kept = 0;
144 sexp* lhs = r_node_cadr(expr);
145
146 struct expansion_info info = which_expansion_op(lhs, true);
147
148 switch (info.op) {
149 case OP_EXPAND_NONE:
150 lhs = KEEP_N(glue_unquote(lhs, env), n_kept);
151 break;
152 case OP_EXPAND_UQ:
153 lhs = KEEP_N(r_eval(info.operand, env), n_kept);
154 break;
155 case OP_EXPAND_CURLY:
156 lhs = KEEP_N(rlang_enquo(info.operand, env), n_kept);
157 break;
158 case OP_EXPAND_UQS:
159 r_abort("The LHS of `:=` can't be spliced with `!!!`");
160 case OP_EXPAND_UQN:
161 r_abort("Internal error: Chained `:=` should have been detected earlier");
162 case OP_EXPAND_FIXUP:
163 r_abort("The LHS of `:=` must be a string or a symbol");
164 case OP_EXPAND_DOT_DATA:
165 r_abort("Can't use the `.data` pronoun on the LHS of `:=`");
166 }
167
168 // Unwrap quosures for convenience
169 if (rlang_is_quosure(lhs)) {
170 lhs = rlang_quo_get_expr_(lhs);
171 }
172
173 int err = 0;
174 lhs = r_new_symbol(lhs, &err);
175 if (err) {
176 r_abort("The LHS of `:=` must be a string or a symbol");
177 }
178
179 FREE(n_kept);
180 return lhs;
181 }
182
signal_retired_splice()183 void signal_retired_splice() {
184 const char* msg =
185 "Unquoting language objects with `!!!` is deprecated as of rlang 0.4.0.\n"
186 "Please use `!!` instead.\n"
187 "\n"
188 " # Bad:\n"
189 " dplyr::select(data, !!!enquo(x))\n"
190 "\n"
191 " # Good:\n"
192 " dplyr::select(data, !!enquo(x)) # Unquote single quosure\n"
193 " dplyr::select(data, !!!enquos(x)) # Splice list of quosures\n";
194 r_warn_deprecated(msg, msg);
195 }
196
dots_big_bang_coerce(sexp * x)197 static sexp* dots_big_bang_coerce(sexp* x) {
198 switch (r_typeof(x)) {
199 case r_type_null:
200 case r_type_pairlist:
201 case r_type_logical:
202 case r_type_integer:
203 case r_type_double:
204 case r_type_complex:
205 case r_type_character:
206 case r_type_raw:
207 if (r_is_object(x)) {
208 return r_eval_with_x(rlang_as_list_call, rlang_ns_env, x);
209 } else {
210 return r_vec_coerce(x, r_type_list);
211 }
212 case r_type_list:
213 if (r_is_object(x)) {
214 return r_eval_with_x(rlang_as_list_call, rlang_ns_env, x);
215 } else {
216 return x;
217 }
218 case r_type_s4:
219 return r_eval_with_x(rlang_as_list_call, rlang_ns_env, x);
220 case r_type_call:
221 if (r_is_symbol(r_node_car(x), "{")) {
222 return r_vec_coerce(r_node_cdr(x), r_type_list);
223 }
224 // else fallthrough
225 case r_type_symbol:
226 signal_retired_splice();
227 return r_new_list(x, NULL);
228
229 default:
230 r_abort(
231 "Can't splice an object of type `%s` because it is not a vector",
232 r_type_as_c_string(r_typeof(x))
233 );
234 }
235 }
236
237 // Also used in expr-interp.c
big_bang_coerce_pairlist(sexp * x,bool deep)238 sexp* big_bang_coerce_pairlist(sexp* x, bool deep) {
239 int n_protect = 0;
240
241 if (r_is_object(x)) {
242 x = KEEP_N(dots_big_bang_coerce(x), n_protect);
243 }
244
245 switch (r_typeof(x)) {
246 case r_type_null:
247 case r_type_pairlist:
248 x = r_clone(x);
249 break;
250 case r_type_logical:
251 case r_type_integer:
252 case r_type_double:
253 case r_type_complex:
254 case r_type_character:
255 case r_type_raw:
256 case r_type_list:
257 // Check for length because `Rf_coerceVector()` to pairlist fails
258 // with named empty vectors (#1045)
259 if (r_length(x)) {
260 x = r_vec_coerce(x, r_type_pairlist);
261 } else {
262 x = r_null;
263 }
264 break;
265 case r_type_call:
266 if (deep && r_is_symbol(r_node_car(x), "{")) {
267 x = r_node_cdr(x);
268 break;
269 }
270 // fallthrough
271 case r_type_symbol: {
272 if (deep) {
273 signal_retired_splice();
274 x = r_new_node(x, r_null);
275 break;
276 }
277 // fallthrough
278 }
279 default:
280 r_abort(
281 "Can't splice an object of type `%s` because it is not a vector",
282 r_type_as_c_string(r_typeof(x))
283 );
284 }
285
286 FREE(n_protect);
287 return x;
288 }
dots_big_bang_coerce_pairlist(sexp * x)289 static sexp* dots_big_bang_coerce_pairlist(sexp* x) {
290 return big_bang_coerce_pairlist(x, false);
291 }
292
dots_big_bang_value(struct dots_capture_info * capture_info,sexp * value,sexp * env,bool quosured)293 static sexp* dots_big_bang_value(struct dots_capture_info* capture_info,
294 sexp* value, sexp* env, bool quosured) {
295 value = KEEP(capture_info->big_bang_coerce(value));
296
297 r_ssize n = r_length(value);
298
299 if (quosured) {
300 if (r_is_shared(value)) {
301 sexp* tmp = r_clone(value);
302 FREE(1);
303 value = KEEP(tmp);
304 }
305
306 for (r_ssize i = 0; i < n; ++i) {
307 sexp* elt = r_list_get(value, i);
308 elt = forward_quosure(elt, env);
309 r_list_poke(value, i, elt);
310 }
311 }
312
313 // The dots_values() variant does not splice for performance
314 if (capture_info->splice) {
315 capture_info->needs_expansion = true;
316 capture_info->count += n;
317 }
318
319 value = rlang_new_splice_box(value);
320
321 FREE(1);
322 return value;
323 }
dots_big_bang(struct dots_capture_info * capture_info,sexp * expr,sexp * env,bool quosured)324 static sexp* dots_big_bang(struct dots_capture_info* capture_info,
325 sexp* expr, sexp* env, bool quosured) {
326 sexp* value = KEEP(r_eval(expr, env));
327 sexp* out = dots_big_bang_value(capture_info, value, env, quosured);
328 FREE(1);
329 return out;
330 }
331
should_ignore(int ignore_empty,r_ssize i,r_ssize n)332 static inline bool should_ignore(int ignore_empty, r_ssize i, r_ssize n) {
333 return ignore_empty == 1 || (i == n - 1 && ignore_empty == -1);
334 }
dot_get_expr(sexp * dot)335 static inline sexp* dot_get_expr(sexp* dot) {
336 return r_list_get(dot, 0);
337 }
dot_get_env(sexp * dot)338 static inline sexp* dot_get_env(sexp* dot) {
339 return r_list_get(dot, 1);
340 }
341
dots_unquote(sexp * dots,struct dots_capture_info * capture_info)342 static sexp* dots_unquote(sexp* dots, struct dots_capture_info* capture_info) {
343 capture_info->count = 0;
344 r_ssize n = r_length(dots);
345 bool unquote_names = capture_info->unquote_names;
346
347 // In the case of `dots_list()` we auto-name inputs eagerly while we
348 // still have access to the defused expression
349 bool needs_autoname =
350 capture_info->type == DOTS_VALUE &&
351 should_auto_name(capture_info->named);
352
353 sexp* node = dots;
354 for (r_ssize i = 0; node != r_null; ++i, node = r_node_cdr(node)) {
355 sexp* elt = r_node_car(node);
356 sexp* expr = dot_get_expr(elt);
357 sexp* env = dot_get_env(elt);
358
359 // Unquoting rearranges expressions
360 // FIXME: Only duplicate the call tree, not the leaves
361 expr = KEEP(r_copy(expr));
362
363 if (unquote_names && r_is_call(expr, ":=")) {
364 if (r_node_tag(node) != r_null) {
365 r_abort("Can't supply both `=` and `:=`");
366 }
367
368 sexp* nm = def_unquote_name(expr, env);
369 r_node_poke_tag(node, nm);
370 expr = r_node_cadr(r_node_cdr(expr));
371 }
372
373 if (capture_info->check_assign
374 && r_is_call(expr, "<-")
375 && r_peek_option("rlang_dots_disable_assign_warning") == r_null) {
376 r_warn(
377 "Using `<-` as argument is often a mistake.\n"
378 "Do you need to use `=` to match an argument?\n"
379 "\n"
380 "If you really want to use `<-`, please wrap in braces:\n"
381 "\n"
382 " # Bad:\n"
383 " fn(a <- 1)\n"
384 "\n"
385 " # Good:\n"
386 " fn(a = 1) # Match 1 to parameter `a`\n"
387 " fn({ a <- 1 }) # Assign 1 to variable `a`"
388 );
389 }
390
391 struct expansion_info info = which_expansion_op(expr, unquote_names);
392 enum dots_expansion_op dots_op = info.op + (EXPANSION_OP_MAX * capture_info->type);
393
394 sexp* name = r_node_tag(node);
395
396 // Ignore empty arguments
397 if (expr == r_syms_missing
398 && (name == r_null || name == r_empty_str)
399 && should_ignore(capture_info->ignore_empty, i, n)) {
400 capture_info->needs_expansion = true;
401 r_node_poke_car(node, empty_spliced_arg);
402 FREE(1);
403 continue;
404 }
405
406 switch (dots_op) {
407 case OP_EXPR_NONE:
408 case OP_EXPR_UQ:
409 case OP_EXPR_FIXUP:
410 case OP_EXPR_DOT_DATA:
411 case OP_EXPR_CURLY:
412 expr = call_interp_impl(expr, env, info);
413 capture_info->count += 1;
414 break;
415 case OP_EXPR_UQS:
416 expr = dots_big_bang(capture_info, info.operand, env, false);
417 break;
418 case OP_QUO_NONE:
419 case OP_QUO_UQ:
420 case OP_QUO_FIXUP:
421 case OP_QUO_DOT_DATA:
422 case OP_QUO_CURLY: {
423 expr = KEEP(call_interp_impl(expr, env, info));
424 expr = forward_quosure(expr, env);
425 FREE(1);
426 capture_info->count += 1;
427 break;
428 }
429 case OP_QUO_UQS: {
430 expr = dots_big_bang(capture_info, info.operand, env, true);
431 break;
432 }
433 case OP_VALUE_NONE:
434 case OP_VALUE_FIXUP:
435 case OP_VALUE_DOT_DATA: {
436 sexp* orig = expr;
437
438 if (expr == r_syms_missing) {
439 if (!capture_info->preserve_empty) {
440 r_abort("Argument %d is empty", i + 1);
441 }
442 } else if (env != r_empty_env) {
443 // Don't evaluate when `env` is the empty environment. This
444 // happens when the argument was forced (and thus already
445 // evaluated), for instance by lapply() or map().
446 expr = r_eval(expr, env);
447 }
448
449 r_keep_t i;
450 KEEP_HERE(expr, &i);
451
452 if (is_splice_box(expr)) {
453 // Coerce contents of splice boxes to ensure uniform type
454 expr = rlang_unbox(expr);
455 expr = dots_big_bang_value(capture_info, expr, env, false);
456 KEEP_AT(expr, i);
457 } else {
458 if (needs_autoname && r_node_tag(node) == r_null) {
459 sexp* label = KEEP(r_as_label(orig));
460 r_node_poke_tag(node, r_chr_as_symbol(label));
461 FREE(1);
462 }
463 capture_info->count += 1;
464 }
465
466 FREE(1);
467 break;
468 }
469 case OP_VALUE_UQ:
470 r_abort("Can't use `!!` in a non-quoting function");
471 case OP_VALUE_UQS: {
472 expr = dots_big_bang(capture_info, info.operand, env, false);
473 break;
474 }
475 case OP_VALUE_CURLY:
476 r_abort("Can't use `{{` in a non-quoting function");
477 case OP_EXPR_UQN:
478 case OP_QUO_UQN:
479 case OP_VALUE_UQN:
480 r_abort("`:=` can't be chained");
481 case OP_DOTS_MAX:
482 r_abort("Internal error: `OP_DOTS_MAX`");
483 }
484
485 r_node_poke_car(node, expr);
486 FREE(1);
487 }
488
489 return dots;
490 }
491
492
arg_match_ignore_empty(sexp * ignore_empty)493 static int arg_match_ignore_empty(sexp* ignore_empty) {
494 if (r_typeof(ignore_empty) != r_type_character || r_length(ignore_empty) == 0) {
495 r_abort("`.ignore_empty` must be a character vector");
496 }
497 const char* arg = r_chr_get_c_string(ignore_empty, 0);
498 switch(arg[0]) {
499 case 't': if (!strcmp(arg, "trailing")) return -1; else break;
500 case 'n': if (!strcmp(arg, "none")) return 0; else break;
501 case 'a': if (!strcmp(arg, "all")) return 1; else break;
502 }
503 r_abort("`.ignore_empty` must be one of: \"trailing\", \"none\", or \"all\"");
504 }
505
arg_match_homonyms(sexp * homonyms)506 static enum dots_homonyms arg_match_homonyms(sexp* homonyms) {
507 if (r_typeof(homonyms) != r_type_character || r_length(homonyms) == 0) {
508 r_abort("`.homonyms` must be a character vector");
509 }
510 const char* arg = r_chr_get_c_string(homonyms, 0);
511 switch(arg[0]) {
512 case 'k': if (!strcmp(arg, "keep")) return DOTS_HOMONYMS_KEEP; else break;
513 case 'f': if (!strcmp(arg, "first")) return DOTS_HOMONYMS_FIRST; else break;
514 case 'l': if (!strcmp(arg, "last")) return DOTS_HOMONYMS_LAST; else break;
515 case 'e': if (!strcmp(arg, "error")) return DOTS_HOMONYMS_ERROR; else break;
516 }
517 r_abort("`.homonyms` must be one of: \"keep\", \"first\", \"last\", or \"error\"");
518 }
519
warn_deprecated_width()520 static void warn_deprecated_width() {
521 const char* msg = "`.named` can no longer be a width";
522 r_warn_deprecated(msg, msg);
523 }
should_auto_name(sexp * named)524 static bool should_auto_name(sexp* named) {
525 if (r_length(named) != 1) {
526 goto error;
527 }
528
529 switch (r_typeof(named)) {
530 case r_type_logical:
531 return r_lgl_get(named, 0);
532 case r_type_integer:
533 warn_deprecated_width();
534 return INTEGER(named)[0];
535 case r_type_double:
536 if (r_is_integerish(named, -1, true)) {
537 warn_deprecated_width();
538 return REAL(named)[0];
539 }
540 // else fallthrough
541 default:
542 break;
543 }
544
545 error:
546 r_abort("`.named` must be a scalar logical");
547 }
548
549 static sexp* auto_name_call = NULL;
550
maybe_auto_name(sexp * x,sexp * named)551 static sexp* maybe_auto_name(sexp* x, sexp* named) {
552 sexp* names = r_names(x);
553
554 if (should_auto_name(named) && (names == r_null || r_chr_has(names, ""))) {
555 x = r_eval_with_x(auto_name_call, r_base_env, x);
556 }
557
558 return x;
559 }
560
any_name(sexp * x,bool splice)561 static bool any_name(sexp* x, bool splice) {
562 while (x != r_null) {
563 if (r_node_tag(x) != r_null) {
564 return true;
565 }
566
567 sexp* elt = r_node_car(x);
568
569 if (splice && is_splice_box(elt)) {
570 if (r_names(rlang_unbox(elt)) != r_null) {
571 return true;
572 }
573 }
574
575 x = r_node_cdr(x);
576 }
577
578 return false;
579 }
580
check_named_splice(sexp * node)581 static void check_named_splice(sexp* node) {
582 if (r_node_tag(node) != r_null) {
583 const char* msg = "`!!!` can't be supplied with a name. Only the operand's names are retained.";
584 r_stop_defunct(msg);
585 }
586 }
587
dots_as_list(sexp * dots,struct dots_capture_info * capture_info)588 sexp* dots_as_list(sexp* dots, struct dots_capture_info* capture_info) {
589 int n_protect = 0;
590
591 sexp* out = KEEP_N(r_new_vector(r_type_list, capture_info->count), n_protect);
592
593 // Add default empty names unless dots are captured by values
594 sexp* out_names = r_null;
595 if (capture_info->type != DOTS_VALUE || any_name(dots, capture_info->splice)) {
596 out_names = KEEP_N(r_new_vector(r_type_character, capture_info->count), n_protect);
597 r_push_names(out, out_names);
598 }
599
600 for (r_ssize i = 0, count = 0; dots != r_null; ++i, dots = r_node_cdr(dots)) {
601 sexp* elt = r_node_car(dots);
602
603 if (elt == empty_spliced_arg) {
604 continue;
605 }
606
607 if (capture_info->splice && is_splice_box(elt)) {
608 check_named_splice(dots);
609
610 elt = rlang_unbox(elt);
611 sexp* nms = r_names(elt);
612
613 r_ssize n = r_length(elt);
614 for (r_ssize i = 0; i < n; ++i) {
615 sexp* value = r_list_get(elt, i);
616 r_list_poke(out, count, value);
617
618 sexp* name = r_nms_get(nms, i);
619 if (name != r_empty_str) {
620 r_chr_poke(out_names, count, name);
621 }
622
623 ++count;
624 }
625 } else {
626 r_list_poke(out, count, elt);
627
628 sexp* name = r_node_tag(dots);
629 if (name != r_null) {
630 r_chr_poke(out_names, count, r_string(r_sym_get_c_string(name)));
631 }
632
633 ++count;
634 }
635 }
636
637 FREE(n_protect);
638 return out;
639 }
640
dots_as_pairlist(sexp * dots,struct dots_capture_info * capture_info)641 sexp* dots_as_pairlist(sexp* dots, struct dots_capture_info* capture_info) {
642 sexp* out = KEEP(r_new_node(r_null, dots));
643 sexp* prev = out;
644
645 while (dots != r_null) {
646 sexp* elt = r_node_car(dots);
647
648 if (elt == empty_spliced_arg) {
649 dots = r_node_cdr(dots);
650 r_node_poke_cdr(prev, dots);
651 continue;
652 }
653
654 if (capture_info->splice && is_splice_box(elt)) {
655 check_named_splice(dots);
656
657 elt = rlang_unbox(elt);
658 if (elt == r_null) {
659 dots = r_node_cdr(dots);
660 r_node_poke_cdr(prev, dots);
661 continue;
662 }
663
664 r_node_poke_cdr(prev, elt);
665
666 sexp* next = r_node_cdr(dots);
667 sexp* tail = r_pairlist_find_last(elt);
668 r_node_poke_cdr(tail, next);
669
670 prev = tail;
671 dots = next;
672 continue;
673 }
674
675 prev = dots;
676 dots = r_node_cdr(dots);
677 }
678
679 FREE(1);
680 return r_node_cdr(out);
681 }
682
683
dots_keep(sexp * dots,sexp * nms,bool first)684 static sexp* dots_keep(sexp* dots, sexp* nms, bool first) {
685 r_ssize n = r_length(dots);
686
687 sexp* dups = KEEP(r_nms_are_duplicated(nms, !first));
688 r_ssize out_n = n - r_lgl_sum(dups, false);
689
690 sexp* out = KEEP(r_new_vector(r_type_list, out_n));
691 sexp* out_nms = KEEP(r_new_vector(r_type_character, out_n));
692 r_push_names(out, out_nms);
693
694 sexp* const * p_nms = r_chr_deref_const(nms);
695 const int* p_dups = r_lgl_deref_const(dups);
696
697 for (r_ssize i = 0, out_i = 0; i < n; ++i) {
698 if (!p_dups[i]) {
699 r_list_poke(out, out_i, r_list_get(dots, i));
700 r_chr_poke(out_nms, out_i, p_nms[i]);
701 ++out_i;
702 }
703 }
704
705 FREE(3);
706 return out;
707 }
708
709 static sexp* abort_dots_homonyms_call = NULL;
dots_check_homonyms(sexp * dots,sexp * nms)710 static void dots_check_homonyms(sexp* dots, sexp* nms) {
711 sexp* dups = KEEP(r_nms_are_duplicated(nms, false));
712
713 if (r_lgl_sum(dups, false)) {
714 r_eval_with_xy(abort_dots_homonyms_call, r_base_env, dots, dups);
715 r_abort("Internal error: `dots_check_homonyms()` should have failed earlier");
716 }
717
718 FREE(1);
719 }
720
721
722 // From capture.c
723 sexp* capturedots(sexp* frame);
724
dots_capture(struct dots_capture_info * capture_info,sexp * frame_env)725 static sexp* dots_capture(struct dots_capture_info* capture_info, sexp* frame_env) {
726 sexp* dots = KEEP(capturedots(frame_env));
727 dots = dots_unquote(dots, capture_info);
728 FREE(1);
729 return dots;
730 }
731
732 sexp* rlang_unescape_character(sexp*);
733
dots_finalise(struct dots_capture_info * capture_info,sexp * dots)734 static sexp* dots_finalise(struct dots_capture_info* capture_info, sexp* dots) {
735 sexp* nms = r_names(dots);
736
737 if (capture_info->type == DOTS_VALUE && should_auto_name(capture_info->named)) {
738 if (nms == r_null) {
739 nms = r_new_vector(r_type_character, r_length(dots));
740 }
741 }
742 KEEP(nms);
743
744 if (nms != r_null) {
745 // Serialised unicode points might arise when unquoting lists
746 // because of the conversion to pairlist
747 nms = KEEP(rlang_unescape_character(nms));
748 r_poke_names(dots, nms);
749
750 dots = KEEP(maybe_auto_name(dots, capture_info->named));
751
752 switch (capture_info->homonyms) {
753 case DOTS_HOMONYMS_KEEP: break;
754 case DOTS_HOMONYMS_FIRST: dots = dots_keep(dots, nms, true); break;
755 case DOTS_HOMONYMS_LAST: dots = dots_keep(dots, nms, false); break;
756 case DOTS_HOMONYMS_ERROR: dots_check_homonyms(dots, nms); break;
757 }
758
759 FREE(2);
760 }
761
762 FREE(1);
763 return dots;
764 }
765
766
rlang_exprs_interp(sexp * frame_env,sexp * named,sexp * ignore_empty,sexp * unquote_names,sexp * homonyms,sexp * check_assign)767 sexp* rlang_exprs_interp(sexp* frame_env,
768 sexp* named,
769 sexp* ignore_empty,
770 sexp* unquote_names,
771 sexp* homonyms,
772 sexp* check_assign) {
773 struct dots_capture_info capture_info;
774 capture_info = init_capture_info(DOTS_EXPR,
775 named,
776 ignore_empty,
777 r_shared_true,
778 unquote_names,
779 homonyms,
780 check_assign,
781 &dots_big_bang_coerce,
782 true);
783
784 sexp* dots;
785 dots = KEEP(dots_capture(&capture_info, frame_env));
786 dots = KEEP(dots_as_list(dots, &capture_info));
787 dots = dots_finalise(&capture_info, dots);
788
789 FREE(2);
790 return dots;
791 }
rlang_quos_interp(sexp * frame_env,sexp * named,sexp * ignore_empty,sexp * unquote_names,sexp * homonyms,sexp * check_assign)792 sexp* rlang_quos_interp(sexp* frame_env,
793 sexp* named,
794 sexp* ignore_empty,
795 sexp* unquote_names,
796 sexp* homonyms,
797 sexp* check_assign) {
798 struct dots_capture_info capture_info;
799 capture_info = init_capture_info(DOTS_QUO,
800 named,
801 ignore_empty,
802 r_shared_true,
803 unquote_names,
804 homonyms,
805 check_assign,
806 &dots_big_bang_coerce,
807 true);
808
809 sexp* dots;
810 dots = KEEP(dots_capture(&capture_info, frame_env));
811 dots = KEEP(dots_as_list(dots, &capture_info));
812 dots = KEEP(dots_finalise(&capture_info, dots));
813
814 sexp* attrib = KEEP(r_new_node(r_names(dots), quosures_attrib));
815 r_node_poke_tag(attrib, r_syms_names);
816 r_poke_attrib(dots, attrib);
817 r_mark_object(dots);
818
819 FREE(4);
820 return dots;
821 }
822
is_spliced_bare_dots_value(sexp * x)823 static bool is_spliced_bare_dots_value(sexp* x) {
824 if (r_typeof(x) != r_type_list) {
825 return false;
826 }
827 if (is_splice_box(x)) {
828 return true;
829 }
830 if (r_is_object(x)) {
831 return false;
832 }
833 return true;
834 }
835
dots_values_impl(sexp * frame_env,sexp * named,sexp * ignore_empty,sexp * preserve_empty,sexp * unquote_names,sexp * homonyms,sexp * check_assign,bool splice)836 static sexp* dots_values_impl(sexp* frame_env,
837 sexp* named,
838 sexp* ignore_empty,
839 sexp* preserve_empty,
840 sexp* unquote_names,
841 sexp* homonyms,
842 sexp* check_assign,
843 bool splice) {
844 struct dots_capture_info capture_info;
845 capture_info = init_capture_info(DOTS_VALUE,
846 named,
847 ignore_empty,
848 preserve_empty,
849 unquote_names,
850 homonyms,
851 check_assign,
852 &dots_big_bang_coerce,
853 splice);
854 sexp* dots;
855 dots = KEEP(dots_capture(&capture_info, frame_env));
856
857 if (capture_info.needs_expansion) {
858 dots = KEEP(dots_as_list(dots, &capture_info));
859 } else {
860 dots = KEEP(r_vec_coerce(dots, r_type_list));
861 }
862
863 dots = dots_finalise(&capture_info, dots);
864
865 FREE(2);
866 return dots;
867 }
868
rlang_ext_dots_values(sexp * args)869 sexp* rlang_ext_dots_values(sexp* args) {
870 args = r_node_cdr(args);
871
872 sexp* env = r_node_car(args); args = r_node_cdr(args);
873 sexp* named = r_node_car(args); args = r_node_cdr(args);
874 sexp* ignore_empty = r_node_car(args); args = r_node_cdr(args);
875 sexp* preserve_empty = r_node_car(args); args = r_node_cdr(args);
876 sexp* unquote_names = r_node_car(args); args = r_node_cdr(args);
877 sexp* homonyms = r_node_car(args); args = r_node_cdr(args);
878 sexp* check_assign = r_node_car(args);
879
880 sexp* out = dots_values_impl(env,
881 named,
882 ignore_empty,
883 preserve_empty,
884 unquote_names,
885 homonyms,
886 check_assign,
887 false);
888
889 return out;
890 }
rlang_env_dots_values(sexp * env)891 sexp* rlang_env_dots_values(sexp* env) {
892 return dots_values_impl(env,
893 r_shared_false,
894 rlang_objs_trailing,
895 r_shared_false,
896 r_shared_true,
897 rlang_objs_keep,
898 r_shared_false,
899 false);
900 }
rlang_env_dots_list(sexp * env)901 sexp* rlang_env_dots_list(sexp* env) {
902 return dots_values_impl(env,
903 r_shared_false,
904 rlang_objs_trailing,
905 r_shared_false,
906 r_shared_true,
907 rlang_objs_keep,
908 r_shared_false,
909 true);
910 }
911
rlang_dots_list(sexp * frame_env,sexp * named,sexp * ignore_empty,sexp * preserve_empty,sexp * unquote_names,sexp * homonyms,sexp * check_assign)912 sexp* rlang_dots_list(sexp* frame_env,
913 sexp* named,
914 sexp* ignore_empty,
915 sexp* preserve_empty,
916 sexp* unquote_names,
917 sexp* homonyms,
918 sexp* check_assign) {
919 return dots_values_impl(frame_env,
920 named,
921 ignore_empty,
922 preserve_empty,
923 unquote_names,
924 homonyms,
925 check_assign,
926 true);
927 }
rlang_dots_flat_list(sexp * frame_env,sexp * named,sexp * ignore_empty,sexp * preserve_empty,sexp * unquote_names,sexp * homonyms,sexp * check_assign)928 sexp* rlang_dots_flat_list(sexp* frame_env,
929 sexp* named,
930 sexp* ignore_empty,
931 sexp* preserve_empty,
932 sexp* unquote_names,
933 sexp* homonyms,
934 sexp* check_assign) {
935
936 struct dots_capture_info capture_info;
937 capture_info = init_capture_info(DOTS_VALUE,
938 named,
939 ignore_empty,
940 preserve_empty,
941 unquote_names,
942 homonyms,
943 check_assign,
944 &dots_big_bang_coerce,
945 true);
946
947 sexp* dots;
948 dots = KEEP(dots_capture(&capture_info, frame_env));
949 dots = KEEP(r_vec_coerce(dots, r_type_list));
950
951 dots = KEEP(r_squash_if(dots, r_type_list, is_spliced_bare_dots_value, 1));
952 dots = dots_finalise(&capture_info, dots);
953
954 FREE(3);
955 return dots;
956 }
957
dots_values_node_impl(sexp * frame_env,sexp * named,sexp * ignore_empty,sexp * preserve_empty,sexp * unquote_names,sexp * homonyms,sexp * check_assign,bool splice)958 sexp* dots_values_node_impl(sexp* frame_env,
959 sexp* named,
960 sexp* ignore_empty,
961 sexp* preserve_empty,
962 sexp* unquote_names,
963 sexp* homonyms,
964 sexp* check_assign,
965 bool splice) {
966 struct dots_capture_info capture_info;
967 capture_info = init_capture_info(DOTS_VALUE,
968 named,
969 ignore_empty,
970 preserve_empty,
971 unquote_names,
972 homonyms,
973 check_assign,
974 &dots_big_bang_coerce_pairlist,
975 splice);
976
977 sexp* dots;
978 dots = KEEP(dots_capture(&capture_info, frame_env));
979
980 dots = KEEP(dots_as_pairlist(dots, &capture_info));
981
982 // dots = dots_finalise(&capture_info, dots);
983
984 FREE(2);
985 return dots;
986 }
rlang_dots_pairlist(sexp * frame_env,sexp * named,sexp * ignore_empty,sexp * preserve_empty,sexp * unquote_names,sexp * homonyms,sexp * check_assign)987 sexp* rlang_dots_pairlist(sexp* frame_env,
988 sexp* named,
989 sexp* ignore_empty,
990 sexp* preserve_empty,
991 sexp* unquote_names,
992 sexp* homonyms,
993 sexp* check_assign) {
994 return dots_values_node_impl(frame_env,
995 named,
996 ignore_empty,
997 preserve_empty,
998 unquote_names,
999 homonyms,
1000 check_assign,
1001 true);
1002 }
1003
rlang_init_dots(sexp * ns)1004 void rlang_init_dots(sexp* ns) {
1005 glue_unquote_fn = r_eval(r_sym("glue_unquote"), ns);
1006
1007 auto_name_call = r_parse("rlang:::quos_auto_name(x)");
1008 r_mark_precious(auto_name_call);
1009
1010 abort_dots_homonyms_call = r_parse("rlang:::abort_dots_homonyms(x, y)");
1011 r_mark_precious(abort_dots_homonyms_call);
1012
1013 {
1014 sexp* splice_box_class = KEEP(r_new_vector(r_type_character, 2));
1015 r_chr_poke(splice_box_class, 0, r_string("rlang_box_splice"));
1016 r_chr_poke(splice_box_class, 1, r_string("rlang_box"));
1017
1018 splice_box_attrib = r_pairlist(splice_box_class);
1019 r_mark_precious(splice_box_attrib);
1020 r_mark_shared(splice_box_attrib);
1021
1022 r_node_poke_tag(splice_box_attrib, r_syms_class);
1023 FREE(1);
1024 }
1025
1026 {
1027 sexp* list = KEEP(r_new_vector(r_type_list, 0));
1028 empty_spliced_arg = rlang_new_splice_box(list);
1029 r_mark_precious(empty_spliced_arg);
1030 r_mark_shared(empty_spliced_arg);
1031 FREE(1);
1032 }
1033
1034 {
1035 sexp* quosures_class = KEEP(r_new_vector(r_type_character, 2));
1036 r_chr_poke(quosures_class, 0, r_string("quosures"));
1037 r_chr_poke(quosures_class, 1, r_string("list"));
1038
1039 quosures_attrib = r_pairlist(quosures_class);
1040 r_mark_precious(quosures_attrib);
1041 r_mark_shared(quosures_attrib);
1042
1043 r_node_poke_tag(quosures_attrib, r_syms_class);
1044 FREE(1);
1045 }
1046
1047 as_label_call = r_parse("as_label(x)");
1048 r_mark_precious(as_label_call);
1049 }
1050