summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichał Muskała <michal@muskala.eu>2018-07-24 17:12:26 +0200
committerMichał Muskała <michal@muskala.eu>2018-07-24 17:19:06 +0200
commitaeef759d1eef147fa1a0468d93aa6f5142888f3c (patch)
treefb4ec0e9ef60744c3a90acac28044543b325bc4d
parent21d052532af2e9babb78c552485cb3ea8f7ca0c7 (diff)
downloadelixir-mm/compiler-refactor.tar.gz
Fast-track quoting lists with disabled unquotemm/compiler-refactor
-rw-r--r--lib/elixir/src/elixir_quote.erl33
1 files changed, 25 insertions, 8 deletions
diff --git a/lib/elixir/src/elixir_quote.erl b/lib/elixir/src/elixir_quote.erl
index 3329dc55b..66e053a94 100644
--- a/lib/elixir/src/elixir_quote.erl
+++ b/lib/elixir/src/elixir_quote.erl
@@ -174,12 +174,12 @@ quote(Expr, Binding, Q, E) ->
} || {K, V} <- Binding],
TExprs = do_quote(Expr, Q, E),
- {'{}', [], ['__block__', [], Vars ++ [TExprs] ]}.
+ {'{}', [], ['__block__', [], Vars ++ [TExprs]]}.
%% Actual quoting and helpers
-do_quote({quote, _, Args} = Tuple, #elixir_quote{unquote=true} = Q, E) when length(Args) == 1; length(Args) == 2 ->
- do_quote_tuple(Tuple, Q#elixir_quote{unquote=false}, E);
+do_quote({quote, Meta, Args}, #elixir_quote{unquote=true} = Q, E) when length(Args) == 1; length(Args) == 2 ->
+ do_quote_tuple(quote, Meta, Args, Q#elixir_quote{unquote=false}, E);
do_quote({unquote, _Meta, [Expr]}, #elixir_quote{unquote=true}, _) ->
Expr;
@@ -241,8 +241,14 @@ do_quote({_, _, _} = Tuple, Q, E) ->
Annotated = annotate(Tuple, Q#elixir_quote.context),
do_quote_tuple(Annotated, Q, E);
-do_quote(List, Q, E) when is_list(List) ->
- do_quote_tail(lists:reverse(List), Q, E);
+do_quote([], _, _) ->
+ [];
+
+do_quote([H | T], #elixir_quote{unquote=false} = Q, E) ->
+ do_quote_simple_list(T, do_quote(H, Q, E), Q, E);
+
+do_quote([H | T], Q, E) ->
+ do_quote_tail(lists:reverse(T, [H]), Q, E);
do_quote(Other, _, _) ->
Other.
@@ -271,13 +277,18 @@ do_escape(Map, Q, E) when is_map(Map) ->
TT = do_quote(maps:to_list(Map), Q, E),
{'%{}', [], TT};
-do_escape(List, Q, E) when is_list(List) ->
+do_escape([], _, _) -> [];
+
+do_escape([H | T], #elixir_quote{unquote=false} = Q, E) ->
+ do_quote_simple_list(T, do_quote(H, Q, E), Q, E);
+
+do_escape([H | T], Q, E) ->
%% The improper case is inefficient, but improper lists are rare.
- try lists:reverse(List) of
+ try lists:reverse(T, [H]) of
L -> do_quote_tail(L, Q, E)
catch
_:_ ->
- {L, R} = reverse_improper(List, []),
+ {L, R} = reverse_improper(T, [H]),
TL = do_quote_splice(L, Q, E, [], []),
TR = do_quote(R, Q, E),
update_last(TL, fun(X) -> {'|', [], [X, TR]} end)
@@ -359,6 +370,12 @@ do_quote_tuple(Left, Meta, Right, Q, E) ->
TRight = do_quote(Right, Q, E),
{'{}', [], [TLeft, meta(Meta, Q), TRight]}.
+do_quote_simple_list([], Prev, _, _) -> [Prev];
+do_quote_simple_list([H | T], Prev, Q, E) ->
+ [Prev | do_quote_simple_list(T, do_quote(H, Q, E), Q, E)];
+do_quote_simple_list(Other, Prev, Q, E) ->
+ [{'|', [], [Prev, do_quote(Other, Q, E)]}].
+
do_quote_tail([{'|', Meta, [{unquote_splicing, _, [Left]}, Right]} | T], #elixir_quote{unquote=true} = Q, E) ->
%% Process the remaining entries on the list.
%% For [1, 2, 3, unquote_splicing(arg) | tail], this will quote