Skip to content

Commit fdf96ad

Browse files
committed
Prune binding from env and on literals
1 parent c80f8b6 commit fdf96ad

File tree

3 files changed

+34
-25
lines changed

3 files changed

+34
-25
lines changed

lib/elixir/src/elixir.erl

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,11 @@ eval_forms(Tree, Binding, OrigE, Opts) ->
277277
{Erl, NewErlS, NewExS, NewE} = quoted_to_erl(Tree, ErlS, ExS, E),
278278

279279
case Erl of
280-
{atom, _, Atom} ->
281-
{Atom, Binding, NewE};
280+
{Literal, _, Literal} when Literal == atom; Literal == float; Literal == integer ->
281+
if
282+
Prune -> {Literal, [], NewE};
283+
true -> {Literal, Binding, NewE}
284+
end;
282285

283286
_ ->
284287
Exprs =
@@ -289,8 +292,12 @@ eval_forms(Tree, Binding, OrigE, Opts) ->
289292

290293
ExternalHandler = eval_external_handler(NewE),
291294
{value, Value, NewBinding} = erl_eval:exprs(Exprs, ErlBinding, none, ExternalHandler),
295+
292296
PruneBefore = if Prune -> length(Binding); true -> 0 end,
293-
{Value, elixir_erl_var:dump_binding(NewBinding, NewErlS, NewExS, PruneBefore), NewE}
297+
{DumpedBinding, DumpedVars} =
298+
elixir_erl_var:dump_binding(NewBinding, NewErlS, NewExS, PruneBefore),
299+
300+
{Value, DumpedBinding, NewE#{versioned_vars := DumpedVars}}
294301
end.
295302

296303
%% TODO: Remove conditional once we require Erlang/OTP 25+.
@@ -365,10 +372,10 @@ quoted_to_erl(Quoted, E) ->
365372
quoted_to_erl(Quoted, ErlS, ExS, E).
366373

367374
quoted_to_erl(Quoted, ErlS, ExS, Env) ->
368-
{Expanded, #elixir_ex{vars={ReadVars, _}} = NewExS, NewEnv} =
375+
{Expanded, NewExS, NewEnv} =
369376
elixir_expand:expand(Quoted, ExS, Env),
370377
{Erl, NewErlS} = elixir_erl_pass:translate(Expanded, erl_anno:new(?key(Env, line)), ErlS),
371-
{Erl, NewErlS, NewExS, NewEnv#{versioned_vars := ReadVars}}.
378+
{Erl, NewErlS, NewExS, NewEnv}.
372379

373380
%% Converts a given string (charlist) into quote expression
374381

lib/elixir/src/elixir_erl_var.erl

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,23 +106,25 @@ dump_binding(Binding, ErlS, ExS, PruneBefore) ->
106106
#elixir_ex{vars={ExVars, _}, unused={Unused, _}} = ExS,
107107

108108
maps:fold(fun
109-
({Var, Kind} = Pair, Version, Acc)
110-
% The variable has to have an atom context
111-
% and it must be versioned after the original
112-
% binding or be a used part of the original binding
113-
when is_atom(Kind), (Version >= PruneBefore orelse map_get({Pair, Version}, Unused) == false) ->
109+
%% If the variable is part of the pruning (usually the input binding)
110+
%% and is unused, we removed it from vars.
111+
(Pair, Version, {B, V})
112+
when Version < PruneBefore, map_get({Pair, Version}, Unused) /= false ->
113+
{B, maps:remove(Pair, V)};
114+
115+
({Var, Kind} = Pair, Version, {B, V}) when is_atom(Kind) ->
114116
Key = case Kind of
115117
nil -> Var;
116118
_ -> Pair
117119
end,
118120

119121
ErlName = maps:get(Version, ErlVars),
120122
Value = find_binding(ErlName, Binding),
121-
[{Key, Value} | Acc];
123+
{[{Key, Value} | B], V};
122124

123125
(_, _, Acc) ->
124126
Acc
125-
end, [], ExVars).
127+
end, {[], ExVars}, ExVars).
126128

127129
find_binding(ErlName, Binding = #{}) ->
128130
case Binding of

lib/elixir/test/elixir/code_test.exs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -181,29 +181,29 @@ defmodule CodeTest do
181181
env = Code.env_for_eval(__ENV__)
182182

183183
fun = fn quoted, binding ->
184-
{_, binding, _} = Code.eval_quoted_with_env(quoted, binding, env, prune_binding: true)
185-
binding
184+
{_, binding, env} = Code.eval_quoted_with_env(quoted, binding, env, prune_binding: true)
185+
{binding, Macro.Env.vars(env)}
186186
end
187187

188-
assert fun.(quote(do: 123), []) == []
189-
assert fun.(quote(do: 123), x: 2, y: 3) == []
188+
assert fun.(quote(do: 123), []) == {[], []}
189+
assert fun.(quote(do: 123), x: 2, y: 3) == {[], []}
190190

191-
assert fun.(quote(do: var!(x) = 1), []) == [x: 1]
192-
assert fun.(quote(do: var!(x) = 1), x: 2, y: 3) == [x: 1]
191+
assert fun.(quote(do: var!(x) = 1), []) == {[x: 1], [x: nil]}
192+
assert fun.(quote(do: var!(x) = 1), x: 2, y: 3) == {[x: 1], [x: nil]}
193193

194-
assert fun.(quote(do: var!(x, :foo) = 1), []) == [{{:x, :foo}, 1}]
195-
assert fun.(quote(do: var!(x, :foo) = 1), x: 2, y: 3) == [{{:x, :foo}, 1}]
194+
assert fun.(quote(do: var!(x, :foo) = 1), []) == {[{{:x, :foo}, 1}], [x: :foo]}
195+
assert fun.(quote(do: var!(x, :foo) = 1), x: 2, y: 3) == {[{{:x, :foo}, 1}], [x: :foo]}
196196

197197
assert fun.(quote(do: var!(x, :foo) = 1), [{{:x, :foo}, 2}, {{:y, :foo}, 3}]) ==
198-
[{{:x, :foo}, 1}]
198+
{[{{:x, :foo}, 1}], [x: :foo]}
199199

200-
assert fun.(quote(do: fn -> var!(x, :foo) = 1 end), []) == []
201-
assert fun.(quote(do: fn -> var!(x, :foo) = 1 end), x: 1, y: 2) == []
200+
assert fun.(quote(do: fn -> var!(x, :foo) = 1 end), []) == {[], []}
201+
assert fun.(quote(do: fn -> var!(x, :foo) = 1 end), x: 1, y: 2) == {[], []}
202202

203-
assert fun.(quote(do: fn -> var!(x) end), x: 2, y: 3) == [x: 2]
203+
assert fun.(quote(do: fn -> var!(x) end), x: 2, y: 3) == {[x: 2], [x: nil]}
204204

205205
assert fun.(quote(do: fn -> var!(x, :foo) end), [{{:x, :foo}, 2}, {{:y, :foo}, 3}]) ==
206-
[{{:x, :foo}, 2}]
206+
{[{{:x, :foo}, 2}], [x: :foo]}
207207
end
208208

209209
test "compile_file/1" do

0 commit comments

Comments
 (0)