Skip to content

Commit e193fd5

Browse files
committed
Refactor
1 parent e14608d commit e193fd5

1 file changed

Lines changed: 51 additions & 69 deletions

File tree

lib/elixir/lib/module/types/pattern.ex

Lines changed: 51 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,8 @@ defmodule Module.Types.Pattern do
230230

231231
defp of_precise_head([], guards, _expected, _previous, _tag, stack, context) do
232232
%{vars: vars} = context
233-
{guard_precise?, changed, context} = of_guards(guards, [], vars, stack, context)
234-
{[], guard_precise?, [], of_changed(changed, stack, context)}
233+
{guard_precise?, changed, context} = of_guards(guards, vars, stack, context)
234+
{[], guard_precise?, [], of_changed(Map.keys(changed), stack, context)}
235235
end
236236

237237
defp of_precise_head(patterns, guards, expected, previous, tag, stack, context) do
@@ -242,52 +242,39 @@ defmodule Module.Types.Pattern do
242242
of_pattern_args_zip(patterns, expected, 0, [], true, stack, context)
243243

244244
{pattern_info, context} = pop_pattern_info(context)
245-
{guard_precise?, changed, context} = of_guards(guards, [], vars, stack, context)
245+
{guard_precise?, changed, context} = of_guards(guards, vars, stack, context)
246246

247247
with {:ok, types} <-
248248
of_pattern_intersect(trees, 0, [], pattern_info, tag, stack, context),
249-
fork_types = types,
250-
fork_context = context,
251-
fork_changed = changed,
249+
# We compute the args types before we do the intersection with previous clauses
250+
args_types =
251+
(with [_ | _] <- previous,
252+
{:ok, _types, context} <-
253+
of_pattern_refine(types, changed, pattern_info, tag, stack, context) do
254+
trees_to_args_types(trees, stack, context)
255+
else
256+
_ -> nil
257+
end),
252258
{:ok, types} <-
253259
of_pattern_previous(types, previous, trees, pattern_info, tag, stack, context),
254-
{_types, changed, context} <-
260+
{:ok, _types, context} <-
255261
of_pattern_refine(types, changed, pattern_info, tag, stack, context) do
256-
args_types =
257-
if previous != [] do
258-
{_types, fork_changed, fork_context} =
259-
of_pattern_refine(fork_types, fork_changed, pattern_info, tag, stack, fork_context)
260-
261-
fork_context = of_changed(fork_changed, stack, fork_context)
262-
263-
Enum.map(trees, fn {tree, _, _} ->
264-
tree
265-
|> of_pattern_tree(stack, fork_context)
266-
|> upper_bound()
267-
end)
268-
else
269-
Enum.map(trees, fn {tree, _, _} ->
270-
tree
271-
|> of_pattern_tree(stack, context)
272-
|> upper_bound()
273-
end)
274-
end
275-
276-
{trees, pattern_precise? and guard_precise?, args_types,
277-
of_changed(changed, stack, context)}
262+
{trees, pattern_precise? and guard_precise?,
263+
args_types || trees_to_args_types(trees, stack, context), context}
278264
else
279265
{:error, context} ->
280-
args_types =
281-
Enum.map(trees, fn {tree, _, _} ->
282-
tree
283-
|> of_pattern_tree(stack, context)
284-
|> upper_bound()
285-
end)
286-
287-
{trees, false, args_types, context}
266+
{trees, false, trees_to_args_types(trees, stack, context), context}
288267
end
289268
end
290269

270+
defp trees_to_args_types(trees, stack, context) do
271+
Enum.map(trees, fn {tree, _, _} ->
272+
tree
273+
|> of_pattern_tree(stack, context)
274+
|> upper_bound()
275+
end)
276+
end
277+
291278
@doc """
292279
Computes the domain from the pattern tree and expected types.
293280
@@ -342,9 +329,9 @@ defmodule Module.Types.Pattern do
342329

343330
with {:ok, types} <-
344331
of_pattern_intersect(args, 0, [], pattern_info, tag, stack, context),
345-
{[type], changed, context} <-
346-
of_pattern_refine(types, pattern_info, tag, stack, context) do
347-
{type, of_changed(changed, stack, context)}
332+
{:ok, [type], context} <-
333+
of_pattern_refine(types, %{}, pattern_info, tag, stack, context) do
334+
{type, context}
348335
else
349336
{:error, context} -> {expected, context}
350337
end
@@ -361,16 +348,13 @@ defmodule Module.Types.Pattern do
361348

362349
{pattern_info, context} = pop_pattern_info(context)
363350
args = [{tree, expected, pattern}]
351+
{_precise?, changed, context} = of_guards(guards, vars, stack, context)
364352

365-
with {:ok, types} <- of_pattern_intersect(args, 0, [], pattern_info, tag, stack, context) do
366-
{_precise?, changed, context} = of_guards(guards, [], vars, stack, context)
367-
368-
with {_types, changed, context} <-
369-
of_pattern_refine(types, changed, pattern_info, tag, stack, context) do
370-
of_changed(changed, stack, context)
371-
else
372-
{:error, context} -> context
373-
end
353+
with {:ok, types} <-
354+
of_pattern_intersect(args, 0, [], pattern_info, tag, stack, context),
355+
{:ok, _types, context} <-
356+
of_pattern_refine(types, changed, pattern_info, tag, stack, context) do
357+
context
374358
else
375359
{:error, context} -> context
376360
end
@@ -394,7 +378,7 @@ defmodule Module.Types.Pattern do
394378
{:ok, Enum.reverse(acc)}
395379
end
396380

397-
defp of_pattern_refine(types, changed \\ [], pattern_info, tag, stack, context) do
381+
defp of_pattern_refine(types, changed, pattern_info, tag, stack, context) do
398382
pattern_info
399383
|> Enum.reverse()
400384
|> Enum.reduce({changed, context}, fn {version, _pinned, node}, {changed, context} ->
@@ -425,13 +409,13 @@ defmodule Module.Types.Pattern do
425409
throw(badpattern_error(expr, index, tag, stack, context))
426410
end
427411

428-
{[version | changed], context}
412+
{Map.put(changed, version, true), context}
429413
end)
430414
catch
431415
context -> {:error, error_vars(pattern_info, context)}
432416
else
433417
{changed, context} ->
434-
{types, changed, context}
418+
{:ok, types, of_changed(Map.keys(changed), stack, context)}
435419
end
436420

437421
defp error_vars(pattern_info, context) do
@@ -531,13 +515,11 @@ defmodule Module.Types.Pattern do
531515
end
532516
end
533517

534-
@doc """
535-
Receives the pattern tree and the context and returns a concrete type.
536-
"""
537-
def of_pattern_tree(descr, _stack, _context) when is_descr(descr),
518+
# Receives the pattern tree and the context and returns a concrete type.
519+
defp of_pattern_tree(descr, _stack, _context) when is_descr(descr),
538520
do: descr
539521

540-
def of_pattern_tree({:guard, name, polarity, guard, expr}, stack, context) do
522+
defp of_pattern_tree({:guard, name, polarity, guard, expr}, stack, context) do
541523
{type, _context} = of_guard(guard, term(), expr, stack, context)
542524

543525
# This logic mirrors the code in `Apply.compare`
@@ -553,25 +535,25 @@ defmodule Module.Types.Pattern do
553535
end
554536
end
555537

556-
def of_pattern_tree({:tuple, entries}, stack, context) do
538+
defp of_pattern_tree({:tuple, entries}, stack, context) do
557539
tuple(Enum.map(entries, &of_pattern_tree(&1, stack, context)))
558540
end
559541

560-
def of_pattern_tree({:open_map, static, dynamic}, stack, context) do
542+
defp of_pattern_tree({:open_map, static, dynamic}, stack, context) do
561543
dynamic =
562544
Enum.map(dynamic, fn {key, value} -> {key, of_pattern_tree(value, stack, context)} end)
563545

564546
open_map(static ++ dynamic)
565547
end
566548

567-
def of_pattern_tree({:closed_map, static, dynamic}, stack, context) do
549+
defp of_pattern_tree({:closed_map, static, dynamic}, stack, context) do
568550
dynamic =
569551
Enum.map(dynamic, fn {key, value} -> {key, of_pattern_tree(value, stack, context)} end)
570552

571553
closed_map(static ++ dynamic)
572554
end
573555

574-
def of_pattern_tree({:non_empty_list, [head | tail], suffix}, stack, context) do
556+
defp of_pattern_tree({:non_empty_list, [head | tail], suffix}, stack, context) do
575557
tail
576558
|> Enum.reduce(
577559
of_pattern_tree(head, stack, context),
@@ -580,20 +562,20 @@ defmodule Module.Types.Pattern do
580562
|> non_empty_list(of_pattern_tree(suffix, stack, context))
581563
end
582564

583-
def of_pattern_tree({:intersection, entries}, stack, context) do
565+
defp of_pattern_tree({:intersection, entries}, stack, context) do
584566
entries
585567
|> Enum.map(&of_pattern_tree(&1, stack, context))
586568
|> Enum.reduce(&intersection/2)
587569
end
588570

589-
def of_pattern_tree({:var, version}, _stack, context) do
571+
defp of_pattern_tree({:var, version}, _stack, context) do
590572
case context do
591573
%{vars: %{^version => %{type: type}}} -> type
592574
_ -> term()
593575
end
594576
end
595577

596-
def of_pattern_tree(:key, _stack, _context) do
578+
defp of_pattern_tree(:key, _stack, _context) do
597579
term()
598580
end
599581

@@ -1037,22 +1019,22 @@ defmodule Module.Types.Pattern do
10371019
@atom_true atom([true])
10381020
@atom_false atom([false])
10391021

1040-
defp of_guards([], changed, _vars, _stack, context) do
1041-
{true, changed, context}
1022+
defp of_guards([], _vars, _stack, context) do
1023+
{true, %{}, context}
10421024
end
10431025

1044-
defp of_guards(guards, changed, vars, stack, context) do
1026+
defp of_guards(guards, vars, stack, context) do
10451027
context =
10461028
init_pattern_info(context, %{
10471029
allow_empty?: false,
10481030
parent_version: nil,
10491031
vars: vars,
1050-
changed: Map.from_keys(changed, [])
1032+
changed: %{}
10511033
})
10521034

10531035
{precise?, context} = of_guards(guards, stack, context)
10541036
{%{vars: vars, changed: changed}, context} = pop_pattern_info(context)
1055-
{is_map(vars) and precise?, Map.keys(changed), context}
1037+
{is_map(vars) and precise?, changed, context}
10561038
end
10571039

10581040
defp of_guards([guard], stack, context) do

0 commit comments

Comments
 (0)