Skip to content

Commit 0dcd550

Browse files
author
José Valim
committed
Fix a bug where unquote_splicing did not work on the left side of a stab op
1 parent 08e9faa commit 0dcd550

File tree

3 files changed

+26
-3
lines changed

3 files changed

+26
-3
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55
* bug fix
66
* [Dict] `Enum.to_list` and `Dict.to_list` now return the same results for dicts
7-
* [Record] Fix a bug where nested records cannot be defined
7+
* [Kernel] Fix a bug where `unquote_splicing` did not work on the left side of a stab op
88
* [Mix] Fix a bug where `mix deps.get` was not retrieving nested dependencies
9+
* [Record] Fix a bug where nested records cannot be defined
910

1011
* deprecations
1112

lib/elixir/src/elixir_parser.yrl

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,8 @@ stab_eol -> stab eol : '$1'.
215215

216216
stab_expr -> expr : '$1'.
217217
stab_expr -> stab_op stab_maybe_expr : build_op('$1', [], '$2').
218-
stab_expr -> call_args_no_parens stab_op stab_maybe_expr : build_op('$2', '$1', '$3').
219-
stab_expr -> call_args_parens_not_one stab_op stab_maybe_expr : build_op('$2', '$1', '$3').
218+
stab_expr -> call_args_no_parens stab_op stab_maybe_expr : build_op('$2', unwrap_splice('$1'), '$3').
219+
stab_expr -> call_args_parens_not_one stab_op stab_maybe_expr : build_op('$2', unwrap_splice('$1'), '$3').
220220

221221
stab_maybe_expr -> 'expr' : '$1'.
222222
stab_maybe_expr -> '$empty' : nil.
@@ -591,6 +591,18 @@ build_stab([], Marker, Temp, Acc) ->
591591
H = { Marker, build_block(lists:reverse(Temp)) },
592592
lists:reverse([H|Acc]).
593593

594+
%% Every time the parser sees a (unquote_splicing())
595+
%% it assumes that a block is being spliced, wrapping
596+
%% the splicing in a __block__. But in the stab cause,
597+
%% we can have (unquote_splicing(1,2,3)) -> :ok, in such
598+
%% case, we don't actually want the block, since it is
599+
%% an arg style call. unwrap_splice unwraps the splice
600+
%% from such blocks.
601+
unwrap_splice([{ '__block__', [], [{ unquote_splicing, _, _ }] = Splice }]) ->
602+
Splice;
603+
604+
unwrap_splice(Other) -> Other.
605+
594606
%% Errors
595607

596608
throw(Line, Error, Token) ->

lib/elixir/test/elixir/kernel/quote_test.exs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,16 @@ defmodule Kernel.QuoteTest do
102102
assert quote(do: [unquote_splicing(contents)|[1,2,3]]) == [1,2,3,1,2,3]
103103
end
104104

105+
test :splice_on_stab do
106+
{ fun, [] } =
107+
Code.eval_quoted(quote(do: fn(unquote_splicing([1,2,3])) -> :ok end), [])
108+
assert fun.(1,2,3) == :ok
109+
110+
{ fun, [] } =
111+
Code.eval_quoted(quote(do: fn(1, unquote_splicing([2,3])) -> :ok end), [])
112+
assert fun.(1,2,3) == :ok
113+
end
114+
105115
test :stab do
106116
assert { :->, _, [{[],_}] } = (quote do -> end)
107117
assert { :->, _, [{[],_}] } = (quote do: (->))

0 commit comments

Comments
 (0)