Skip to content

Commit 2da5326

Browse files
author
José Valim
committed
Allow quoting on aliases with calls
1 parent a835477 commit 2da5326

File tree

2 files changed

+23
-7
lines changed

2 files changed

+23
-7
lines changed

lib/elixir/src/elixir_quote.erl

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
%% Implements Elixir quote.
22
-module(elixir_quote).
3-
-export([escape/2, erl_escape/3, erl_quote/4, linify/2, unquote/5]).
3+
-export([escape/2, erl_escape/3, erl_quote/4, linify/2, unquote/6]).
44
-include("elixir.hrl").
55

66
%% Apply the line from site call on quoted contents.
@@ -24,22 +24,36 @@ do_linify(_, Else) -> Else.
2424

2525
%% Some expressions cannot be unquoted at compilation time.
2626
%% This function is responsible for doing runtime unquoting.
27-
unquote(_File, Meta, Left, { '__aliases__', _, Args }, nil) ->
27+
unquote(_File, _Line, Meta, Left, { '__aliases__', _, Args }, nil) ->
2828
{ '__aliases__', Meta, [Left|Args] };
2929

30-
unquote(_File, Meta, Left, Right, nil) when is_atom(Right) ->
30+
unquote(_File, _Line, Meta, Left, Right, nil) when is_atom(Right) ->
3131
case atom_to_list(Right) of
3232
"Elixir." ++ _ ->
3333
{ '__aliases__', Meta, [Left, Right] };
3434
_ ->
3535
{ { '.', Meta, [Left, Right] }, Meta, [] }
3636
end;
3737

38-
unquote(_File, Meta, Left, Right, Args) when is_atom(Right) ->
38+
unquote(_File, _Line, Meta, Left, { Right, _, Context }, nil) when is_atom(Right), is_atom(Context) ->
39+
{ { '.', Meta, [Left, Right] }, Meta, [] };
40+
41+
unquote(_File, _Line, Meta, Left, { Right, _, Args }, nil) when is_atom(Right) ->
42+
{ { '.', Meta, [Left, Right] }, Meta, Args };
43+
44+
unquote(File, Line, _Meta, _Left, Right, nil) ->
45+
elixir_errors:syntax_error(Line, File, "expected unquote after dot to return an atom, "
46+
"an alias or a quoted call, got: ~ts", ['Elixir.Macro':to_string(Right)]);
47+
48+
unquote(_File, _Line, Meta, Left, Right, Args) when is_atom(Right) ->
49+
{ { '.', Meta, [Left, Right] }, Meta, Args };
50+
51+
unquote(_File, _Line, Meta, Left, { Right, _, Context }, Args) when is_atom(Right), is_atom(Context) ->
3952
{ { '.', Meta, [Left, Right] }, Meta, Args };
4053

41-
unquote(File, Meta, _Left, _Right, _Args) ->
42-
elixir_errors:syntax_error(Meta, File, "expected unquote after dot to return an atom or an alias").
54+
unquote(File, Line, _Meta, _Left, Right, _Args) ->
55+
elixir_errors:syntax_error(Line, File, "expected unquote after dot with args to return an atom "
56+
"or a quoted call, got: ~ts", ['Elixir.Macro':to_string(Right)]).
4357

4458
%% Escapes the given expression. It is similar to quote, but
4559
%% lines are kept and hygiene mechanisms are disabled.
@@ -187,7 +201,7 @@ do_quote(Other, Q, _) ->
187201
%% Quote helpers
188202

189203
do_quote_call(Left, Meta, Expr, Args, Q, S) ->
190-
All = [meta(Meta, Q), Left, { unquote, Meta, [Expr] }, Args],
204+
All = [?line(Meta), meta(Meta, Q), Left, { unquote, Meta, [Expr] }, Args],
191205
{ TAll, TQ } = lists:mapfoldl(fun(X, Acc) -> do_quote(X, Acc, S) end, Q, All),
192206
{ { { '.', Meta, [elixir_quote, unquote] }, Meta, [{ '__FILE__', [], nil }|TAll] }, TQ }.
193207

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ defmodule Kernel.QuoteTest do
5353
assert quote(do: foo.unquote(:bar)) == quote(do: foo.bar)
5454
assert quote(do: foo.unquote(:bar)(1)) == quote(do: foo.bar(1))
5555
assert quote(do: foo.unquote(:bar)(1) do 2 + 3 end) == quote(do: foo.bar(1) do 2 + 3 end)
56+
assert quote(do: foo.unquote({ :bar, [], nil })) == quote(do: foo.bar)
57+
assert quote(do: foo.unquote({ :bar, [], [1,2] })) == quote(do: foo.bar(1,2))
5658

5759
assert Code.eval_quoted(quote(do: Foo.unquote(Bar))) == { Elixir.Foo.Bar, [] }
5860
assert Code.eval_quoted(quote(do: Foo.unquote(quote do: Bar))) == { Elixir.Foo.Bar, [] }

0 commit comments

Comments
 (0)