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