Skip to content

Commit f0e97d0

Browse files
committed
Solve bootstrap issues on dynamic options to quote
1 parent 03d412f commit f0e97d0

File tree

2 files changed

+48
-48
lines changed

2 files changed

+48
-48
lines changed

lib/elixir/src/elixir_expand.erl

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -178,20 +178,8 @@ expand({quote, Meta, [Opts, Do]}, S, E) when is_list(Do) ->
178178
false -> file_error(Meta, E, ?MODULE, {missing_option, 'quote', [do]})
179179
end,
180180

181-
{Binding, DefaultUnquote, ToExpandOpts} =
182-
case is_list(Opts) andalso lists:keytake(bind_quoted, 1, Opts) of
183-
{value, {bind_quoted, BQ}, BQOpts} ->
184-
case is_list(BQ) andalso
185-
lists:all(fun({Key, _}) when is_atom(Key) -> true; (_) -> false end, BQ) of
186-
true -> {BQ, false, BQOpts};
187-
false -> file_error(Meta, E, ?MODULE, {invalid_bind_quoted_for_quote, BQ})
188-
end;
189-
false ->
190-
{[], true, Opts}
191-
end,
192-
193-
ValidKeys = [context, location, line, file, unquote, bind_quoted, generated],
194-
{EOpts, ST, ET} = expand_opts(Meta, quote, ValidKeys, ToExpandOpts, S, E),
181+
ValidOpts = [context, location, line, file, unquote, bind_quoted, generated],
182+
{EOpts, ST, ET} = expand_opts(Meta, quote, ValidOpts, Opts, S, E),
195183

196184
Context = proplists:get_value(context, EOpts, case ?key(E, module) of
197185
nil -> 'Elixir';
@@ -205,12 +193,44 @@ expand({quote, Meta, [Opts, Do]}, S, E) when is_list(Do) ->
205193
{proplists:get_value(file, EOpts, nil), proplists:get_value(line, EOpts, false)}
206194
end,
207195

196+
{Binding, DefaultUnquote} = case lists:keyfind(bind_quoted, 1, EOpts) of
197+
{bind_quoted, BQ} ->
198+
case is_list(BQ) andalso
199+
lists:all(fun({Key, _}) when is_atom(Key) -> true; (_) -> false end, BQ) of
200+
true -> {BQ, false};
201+
false -> file_error(Meta, E, ?MODULE, {invalid_bind_quoted_for_quote, BQ})
202+
end;
203+
false ->
204+
{[], true}
205+
end,
206+
208207
Unquote = proplists:get_value(unquote, EOpts, DefaultUnquote),
209208
Generated = proplists:get_value(generated, EOpts, false),
210209

211-
{Q, Prelude} = elixir_quote:build(Meta, Line, File, Context, Unquote, Generated, ET),
212-
Quoted = elixir_quote:quote(Meta, Exprs, Binding, Q, Prelude),
213-
expand(Quoted, ST, ET);
210+
{Q, QContext, QPrelude} = elixir_quote:build(Meta, Line, File, Context, Unquote, Generated, ET),
211+
{EPrelude, SP, EP} = expand(QPrelude, ST, ET),
212+
{EContext, SC, EC} = expand(QContext, SP, EP),
213+
Quoted = elixir_quote:quote(Exprs, Q),
214+
{EQuoted, ES, EQ} = expand(Quoted, SC, EC),
215+
216+
EBinding =
217+
[{'{}', [],
218+
['=', [], [
219+
{'{}', [], [K, Meta, EContext]},
220+
V
221+
]
222+
]} || {K, V} <- Binding],
223+
224+
EBindingQuoted =
225+
case EBinding of
226+
[] -> EQuoted;
227+
_ -> {'{}', [], ['__block__', [], EBinding ++ [EQuoted]]}
228+
end,
229+
230+
case EPrelude of
231+
[] -> {EBindingQuoted, ES, EQ};
232+
_ -> {{'__block__', [], EPrelude ++ [EBindingQuoted]}, ES, EQ}
233+
end;
214234

215235
expand({quote, Meta, [_, _]}, _S, E) ->
216236
file_error(Meta, E, ?MODULE, {invalid_args, 'quote'});

lib/elixir/src/elixir_quote.erl

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
-module(elixir_quote).
2-
-export([escape/3, linify/3, linify_with_context_counter/3, build/7, quote/5, has_unquotes/1, fun_to_quoted/1]).
2+
-export([escape/3, linify/3, linify_with_context_counter/3, build/7, quote/2, has_unquotes/1, fun_to_quoted/1]).
33
-export([dot/5, tail_list/3, list/2, validate_runtime/2]). %% Quote callbacks
44

55
-include("elixir.hrl").
@@ -202,24 +202,24 @@ bad_escape(Arg) ->
202202

203203
build(Meta, Line, File, Context, Unquote, Generated, E) ->
204204
Acc0 = [],
205-
{ELine, Acc1} = validate_compile(Meta, line, Line, Acc0),
206-
{EFile, Acc2} = validate_compile(Meta, file, File, Acc1),
207-
{EContext, Acc3} = validate_compile(Meta, context, Context, Acc2),
205+
{VLine, Acc1} = validate_compile(Meta, line, Line, Acc0),
206+
{VFile, Acc2} = validate_compile(Meta, file, File, Acc1),
207+
{VContext, Acc3} = validate_compile(Meta, context, Context, Acc2),
208208
validate_runtime(unquote, Unquote),
209209
validate_runtime(generated, Generated),
210210

211211
Q = #elixir_quote{
212212
op=add_context,
213213
aliases_hygiene=E,
214214
imports_hygiene=E,
215-
line=ELine,
216-
file=EFile,
215+
line=VLine,
216+
file=VFile,
217217
unquote=Unquote,
218-
context=EContext,
218+
context=VContext,
219219
generated=Generated
220220
},
221221

222-
{Q, Acc3}.
222+
{Q, VContext, Acc3}.
223223

224224
validate_compile(_Meta, line, Value, Acc) when is_boolean(Value) ->
225225
{Value, Acc};
@@ -255,31 +255,11 @@ is_valid(context, Context) -> is_atom(Context) andalso (Context /= nil);
255255
is_valid(generated, Generated) -> is_boolean(Generated);
256256
is_valid(unquote, Unquote) -> is_boolean(Unquote).
257257

258-
quote(_Meta, {unquote_splicing, _, [_]}, _Binding, #elixir_quote{unquote=true}, _) ->
258+
quote({unquote_splicing, _, [_]}, #elixir_quote{unquote=true}) ->
259259
argument_error(<<"unquote_splicing only works inside arguments and block contexts, "
260260
"wrap it in parens if you want it to work with one-liners">>);
261-
262-
quote(Meta, Expr, Binding, Q, Prelude) ->
263-
Context = Q#elixir_quote.context,
264-
265-
Vars = [{'{}', [],
266-
['=', [], [
267-
{'{}', [], [K, Meta, Context]},
268-
V
269-
]]
270-
} || {K, V} <- Binding],
271-
272-
Quoted = do_quote(Expr, Q),
273-
274-
WithVars = case Vars of
275-
[] -> Quoted;
276-
_ -> {'{}', [], ['__block__', [], Vars ++ [Quoted]]}
277-
end,
278-
279-
case Prelude of
280-
[] -> WithVars;
281-
_ -> {'__block__', [], Prelude ++ [WithVars]}
282-
end.
261+
quote(Expr, Q) ->
262+
do_quote(Expr, Q).
283263

284264
%% quote/unquote
285265

0 commit comments

Comments
 (0)