Skip to content

Commit f02f90f

Browse files
author
José Valim
committed
Merge pull request #1648 from pminten/quote-improper-lists
Allow Macro.escape([1|2])
2 parents 3768087 + c739199 commit f02f90f

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

lib/elixir/src/elixir_quote.erl

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,18 @@ do_quote(Tuple, #elixir_quote{escape=true} = Q, S) when is_tuple(Tuple) ->
195195
{ TT, TQ } = do_quote(tuple_to_list(Tuple), Q, S),
196196
{ { '{}', [], TT }, TQ };
197197

198+
do_quote(List, #elixir_quote{escape=true} = Q, S) when is_list(List) ->
199+
% The improper case is pretty inefficient, but improper lists are hopefully
200+
% rare.
201+
case reverse_improper(List) of
202+
{ L } -> do_splice(L, Q, S);
203+
{ L, R } ->
204+
{ TL, QL } = do_splice(L, Q, S, [], []),
205+
{ TR, QR } = do_quote(R, QL, S),
206+
{ update_last(TL, fun(X) -> { '|', [], [X, TR] } end), QR }
207+
end;
198208
do_quote(List, Q, S) when is_list(List) ->
199-
do_splice(lists:reverse(List), Q, S);
209+
do_splice(lists:reverse(List), Q, S);
200210

201211
do_quote(Other, Q, _) ->
202212
{ Other, Q }.
@@ -229,6 +239,16 @@ meta(Meta, #elixir_quote{line=nil}) ->
229239
meta(Meta, #elixir_quote{line=Line}) ->
230240
keystore(line, Meta, Line).
231241

242+
reverse_improper(L) -> reverse_improper(L, []).
243+
244+
reverse_improper([], Acc) -> { Acc };
245+
reverse_improper([H|T], Acc) when is_list(T) -> reverse_improper(T, [H|Acc]);
246+
reverse_improper([H|T], Acc) -> { [H|Acc], T }.
247+
248+
update_last([], _) -> [];
249+
update_last([H], F) -> [F(H)];
250+
update_last([H|T], F) -> [H|update_last(T,F)].
251+
232252
keyfind(Key, Meta) ->
233253
lists:keyfind(Key, 1, Meta).
234254
keydelete(Key, Meta) ->

lib/elixir/test/elixir/macro_test.exs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ defmodule MacroTest do
3939
test :escape_works_recursively do
4040
assert [1,{:{}, [], [:a,:b,:c]}, 3] == Macro.escape([1, { :a, :b, :c }, 3])
4141
end
42+
43+
test :escape_improper do
44+
assert [{:|, [], [1,2]}] == Macro.escape([1|2])
45+
assert [1,{:|, [], [2,3]}] == Macro.escape([1,2|3])
46+
end
4247

4348
test :escape_with_unquote do
4449
contents = quote unquote: false, do: unquote(1)

0 commit comments

Comments
 (0)