Skip to content

Commit

Permalink
Fix parse tree for parentheses around !!
Browse files Browse the repository at this point in the history
Part of r-lib#296
  • Loading branch information
lionel- committed Nov 28, 2017
1 parent 3006add commit ea9c317
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 0 deletions.
6 changes: 6 additions & 0 deletions NEWS.md
Expand Up @@ -113,6 +113,12 @@
the first argument of an S3 method (which is necessarily evaluated
in order to detect which class to dispatch to). (#295, #300).

* Parentheses around `!!` are automatically removed. This is useful
for unquoting function names: `(!! sym("name"))(arg)`. If you need
the parenthesis wrapping, you can add a second layer since only one
layer is removed: `((!! x)) + 1` (#296).


## Breaking changes

* `is_node()` now returns `TRUE` for calls as well and `is_pairlist()`
Expand Down
13 changes: 13 additions & 0 deletions src/expr-interp.c
Expand Up @@ -39,6 +39,19 @@ static void poke_bang_bang_operand(sexp* bang, struct expansion_info* info) {
struct expansion_info which_bang_op(sexp* x) {
struct expansion_info info = init_expansion_info();

if (r_is_call(x, "(")) {
sexp* paren = r_node_cadr(x);
if (r_is_call(paren, "(")) {
return info;
}
struct expansion_info inner_info = which_bang_op(paren);
if (inner_info.op == OP_EXPAND_UQ) {
return inner_info;
} else {
return info;
}
}

if (!r_is_call(x, "!")) {
return info;
}
Expand Down
14 changes: 14 additions & 0 deletions tests/testthat/test-tidy-unquote.R
Expand Up @@ -225,6 +225,20 @@ test_that("`!!` works in prefixed calls", {
expect_identical(expr_interp(~base::`!!`(~list)()), quo(base::list()))
})

test_that("one layer of parentheses around !! is removed", {
foo <- "foo"
expect_identical(expr((!! foo)), "foo")
expect_identical(expr(((!! foo))), quote(("foo")))

expect_identical(expr((!! foo) + 1), quote("foo" + 1))
expect_identical(expr(((!! foo)) + 1), quote(("foo") + 1))

expect_identical(expr((!! sym(foo))(bar)), quote(foo(bar)))
expect_identical(expr(((!! sym(foo)))(bar)), quote((foo)(bar)))

expect_identical(exprs((!! foo), ((!! foo))), named_list("foo", quote(("foo"))))
})


# quosures -----------------------------------------------------------

Expand Down

0 comments on commit ea9c317

Please sign in to comment.