|
1 | 1 | %% Implements Elixir quote. |
2 | 2 | -module(elixir_quote). |
3 | | --export([escape/2, erl_escape/3, erl_quote/4, linify/2, unquote/6]). |
| 3 | +-export([escape/2, erl_escape/3, erl_quote/4, linify/2, unquote/6, join/5]). |
4 | 4 | -include("elixir.hrl"). |
5 | 5 |
|
6 | 6 | %% Apply the line from site call on quoted contents. |
@@ -55,6 +55,13 @@ unquote(File, Line, _Meta, _Left, Right, _Args) -> |
55 | 55 | elixir_errors:syntax_error(Line, File, "expected unquote after dot with args to return an atom " |
56 | 56 | "or a quoted call, got: ~ts", ['Elixir.Macro':to_string(Right)]). |
57 | 57 |
|
| 58 | +join(_File, _Line, Left, Right, Rest) when is_list(Left), is_list(Right), is_list(Rest) -> |
| 59 | + Rest ++ Left ++ Right; |
| 60 | + |
| 61 | +join(_File, _Line, Left, Right, Rest) -> |
| 62 | + [H|T] = lists:reverse(Rest ++ Left), |
| 63 | + lists:reverse([{ '|', [], [H, Right] }|T]). |
| 64 | + |
58 | 65 | %% Escapes the given expression. It is similar to quote, but |
59 | 66 | %% lines are kept and hygiene mechanisms are disabled. |
60 | 67 | escape(Expr, Unquote) -> |
@@ -235,27 +242,16 @@ keystore(Key, Meta, Value) -> |
235 | 242 |
|
236 | 243 | %% Quote splicing |
237 | 244 |
|
238 | | -do_splice([{ '|', _, [{ unquote_splicing, _, [Left] }, Right] }|T], #elixir_quote{unquote=true} = Q, S) -> |
| 245 | +do_splice([{ '|', Meta, [{ unquote_splicing, _, [Left] }, Right] }|T], #elixir_quote{unquote=true} = Q, S) -> |
239 | 246 | %% Process the remaining entries on the list. |
240 | 247 | %% For [1, 2, 3, unquote_splicing(arg)|tail], this will quote |
241 | 248 | %% 1, 2 and 3, which could even be unquotes. |
242 | 249 | { TT, QT } = do_splice(T, Q, S, [], []), |
| 250 | + { TR, QR } = do_quote(Right, QT, S), |
243 | 251 |
|
244 | | - %% Now that we have [1,2,3], join it with the argument spliced. |
245 | | - %% This is done with a ++ operation executed at compilation time. |
246 | | - ListWithoutTail = do_splice_join(TT, Left), |
247 | | - |
248 | | - %% Let's add the tail, which is done with a ++ operation at runtime |
249 | | - %% unless Right is a list (which allows us to do it at compile time). |
250 | | - %% Since the LastWithoutTail was already quoted, wrap it inside an |
251 | | - %% unquote so it won't be quoted again. |
252 | | - case is_list(Right) of |
253 | | - true -> |
254 | | - { TR, QR } = do_quote(Right, QT, S), |
255 | | - { do_splice_join(ListWithoutTail, TR), QR }; |
256 | | - false -> |
257 | | - do_quote(do_splice_join({ unquote, [], [ListWithoutTail] }, Right), QT, S) |
258 | | - end; |
| 252 | + %% Do the joining at runtime when we are aware of the values. |
| 253 | + Args = [{ '__FILE__', [], nil }, ?line(Meta), Left, TR, TT], |
| 254 | + { { { '.', Meta, [elixir_quote, join] }, Meta, Args }, QR#elixir_quote{unquoted=true} }; |
259 | 255 |
|
260 | 256 | do_splice(List, Q, S) -> |
261 | 257 | do_splice(List, Q, S, [], []). |
|
0 commit comments