Skip to content

Commit 909046b

Browse files
committed
Wrap for into body evaluation in try/catch
1 parent a53e851 commit 909046b

1 file changed

Lines changed: 51 additions & 43 deletions

File tree

lib/elixir/src/elixir_erl_for.erl

Lines changed: 51 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -166,55 +166,16 @@ build_into(Ann, Clauses, Expr, ?empty_map_set_pattern = _Into, Uniq, S) ->
166166
{ReduceExpr, SR} = build_reduce(Ann, Clauses, InnerFun, Expr, {nil, Ann}, Uniq, S),
167167
{?remote(Ann, 'Elixir.MapSet', new, [ReduceExpr]), SR};
168168
build_into(Ann, Clauses, Expr, Into, Uniq, S) ->
169-
{Fun, SF} = build_var(Ann, S),
170-
{Acc, SA} = build_var(Ann, SF),
171-
{Kind, SK} = build_var(Ann, SA),
172-
{Reason, SR} = build_var(Ann, SK),
173-
{Stack, ST} = build_var(Ann, SR),
174-
{Done, SD} = build_var(Ann, ST),
175-
{Ref, SRef} = build_var(Ann, SD),
176-
{Current, SC} = build_var(Ann, SRef),
177-
178-
InnerFun = fun(InnerExpr, InnerAcc) ->
179-
{block, Ann, [
180-
{match, Ann, Current, {call, Ann, Fun, [InnerAcc, pair(Ann, cont, InnerExpr)]}},
181-
?remote(Ann, erlang, put, [Ref, Current]),
182-
Current
183-
]}
184-
end,
169+
{Fun, SF} = build_var(Ann, S),
170+
{Acc, SA} = build_var(Ann, SF),
185171

186172
MatchExpr = {match, Ann,
187173
{tuple, Ann, [Acc, Fun]},
188174
?remote(Ann, 'Elixir.Collectable', into, [Into])
189175
},
190176

191-
{IntoReduceExpr, SN} = build_reduce(Ann, Clauses, InnerFun, Expr, Acc, Uniq, SC),
192-
RefExpr = {match, Ann, Ref, ?remote(Ann, erlang, make_ref, [])},
193-
194-
TryExpr =
195-
{'try', Ann,
196-
[IntoReduceExpr],
197-
[{clause, Ann,
198-
[Done],
199-
[],
200-
[
201-
?remote(Ann, erlang, erase, [Ref]),
202-
{call, Ann, Fun, [Done, {atom, Ann, done}]}
203-
]}],
204-
[stacktrace_clause(Ann, Fun, Ref, Kind, Reason, Stack)],
205-
[]},
206-
207-
{{block, Ann, [RefExpr, MatchExpr, ?remote(Ann, erlang, put, [Ref, Acc]), TryExpr]}, SN}.
208-
209-
stacktrace_clause(Ann, Fun, Ref, Kind, Reason, Stack) ->
210-
CurrentAcc = ?remote(Ann, erlang, get, [Ref]),
211-
{clause, Ann,
212-
[{tuple, Ann, [Kind, Reason, Stack]}],
213-
[],
214-
[
215-
{call, Ann, Fun, [CurrentAcc, {atom, Ann, halt}]},
216-
?remote(Ann, erlang, erase, [Ref]),
217-
?remote(Ann, erlang, raise, [Kind, Reason, Stack])]}.
177+
{IntoReduceExpr, SN} = build_into_reduce(Ann, Clauses, Expr, Acc, Fun, Uniq, SA),
178+
{{block, Ann, [MatchExpr, {call, Ann, Fun, [IntoReduceExpr, {atom, Ann, done}]}]}, SN}.
218179

219180
%% Helpers
220181

@@ -245,6 +206,53 @@ build_reduce(Ann, Clauses, InnerFun, Expr, Into, true, S) ->
245206
EnumReduceCall = build_reduce_each(Clauses, InnerExpr, NewInto, Acc, SU),
246207
{?remote(Ann, erlang, element, [{integer, Ann, 1}, EnumReduceCall]), SU}.
247208

209+
build_into_reduce(Ann, Clauses, Expr, Into, Fun, false, S) ->
210+
{Acc, SA} = build_var(Ann, S),
211+
{ProtectedExpr, SP} = build_into_try(Ann, Expr, Fun, Acc, SA),
212+
{build_reduce_each(Clauses, {call, Ann, Fun, [Acc, pair(Ann, cont, ProtectedExpr)]}, Into, Acc, SP), SP};
213+
build_into_reduce(Ann, Clauses, Expr, Into, Fun, true, S) ->
214+
%% Those variables are used only inside the anonymous function
215+
%% so we don't need to worry about returning the scope.
216+
{Acc, SA} = build_var(Ann, S),
217+
{Value, SV} = build_var(Ann, SA),
218+
{IntoAcc, SI} = build_var(Ann, SV),
219+
{UniqAcc, SU} = build_var(Ann, SI),
220+
221+
{ProtectedExpr, SP} = build_into_try(Ann, Expr, Fun, IntoAcc, SU),
222+
NewInto = {tuple, Ann, [Into, {map, Ann, []}]},
223+
AccTuple = {tuple, Ann, [IntoAcc, UniqAcc]},
224+
PutUniqExpr = {map, Ann, UniqAcc, [{map_field_assoc, Ann, Value, {atom, Ann, true}}]},
225+
226+
InnerExpr = {block, Ann, [
227+
{match, Ann, AccTuple, Acc},
228+
{match, Ann, Value, ProtectedExpr},
229+
{'case', Ann, UniqAcc, [
230+
{clause, Ann, [{map, Ann, [{map_field_exact, Ann, Value, {atom, Ann, true}}]}], [], [AccTuple]},
231+
{clause, Ann, [{map, Ann, []}], [], [{tuple, Ann, [{call, Ann, Fun, [IntoAcc, pair(Ann, cont, Value)]}, PutUniqExpr]}]}
232+
]}
233+
]},
234+
235+
EnumReduceCall = build_reduce_each(Clauses, InnerExpr, NewInto, Acc, SP),
236+
{?remote(Ann, erlang, element, [{integer, Ann, 1}, EnumReduceCall]), SP}.
237+
238+
build_into_try(Ann, Expr, Fun, Acc, S) ->
239+
{Value, SV} = build_var(Ann, S),
240+
{Kind, SK} = build_var(Ann, SV),
241+
{Reason, SR} = build_var(Ann, SK),
242+
{Stack, SS} = build_var(Ann, SR),
243+
244+
{{'try', Ann,
245+
[Expr],
246+
[{clause, Ann, [Value], [], [Value]}],
247+
[{clause, Ann,
248+
[{tuple, Ann, [Kind, Reason, Stack]}],
249+
[],
250+
[
251+
{call, Ann, Fun, [Acc, {atom, Ann, halt}]},
252+
?remote(Ann, erlang, raise, [Kind, Reason, Stack])
253+
]}],
254+
[]}, SS}.
255+
248256
build_reduce_each([{enum, Meta, Left, Right, Filters} | T], Expr, Arg, Acc, S) ->
249257
Ann = ?ann(Meta),
250258
True = build_reduce_each(T, Expr, Acc, Acc, S),

0 commit comments

Comments
 (0)