@@ -270,7 +270,7 @@ defmodule Module.Types.Descr do
270270 end
271271
272272 defp unwrap_domain_tuple ( % { tuple: bdd } = descr , transform ) when map_size ( descr ) == 1 do
273- tuple_normalize ( bdd ) |> Enum . map ( transform )
273+ tuple_bdd_to_dnf ( bdd ) |> Enum . map ( transform )
274274 end
275275
276276 defp unwrap_domain_tuple ( descr , _transform ) when descr == % { } , do: [ ]
@@ -604,6 +604,56 @@ defmodule Module.Types.Descr do
604604 defp empty_key? ( :tuple , value ) , do: tuple_empty? ( value )
605605 defp empty_key? ( _ , _value ) , do: false
606606
607+ @ doc """
608+ Returns if the type is a singleton.
609+ """
610+ def singleton? ( :term ) , do: false
611+ def singleton? ( descr ) , do: static_singleton? ( Map . get ( descr , :dynamic , descr ) )
612+
613+ defp static_singleton? ( :term ) , do: false
614+ defp static_singleton? ( % { optional: _ } ) , do: false
615+ defp static_singleton? ( % { list: _ } ) , do: false
616+ defp static_singleton? ( % { fun: _ } ) , do: false
617+ defp static_singleton? ( descr ) , do: each_singleton? ( descr , [ :atom , :bitmap , :map , :tuple ] , false )
618+
619+ defp each_singleton? ( descr , [ key | keys ] , acc ) do
620+ case descr do
621+ % { ^ key => value } ->
622+ case each_singleton? ( key , value ) do
623+ true when acc == true -> false
624+ true -> each_singleton? ( descr , keys , true )
625+ false -> false
626+ :empty -> each_singleton? ( descr , keys , acc )
627+ end
628+
629+ % { } ->
630+ each_singleton? ( descr , keys , acc )
631+ end
632+ end
633+
634+ defp each_singleton? ( _descr , [ ] , acc ) , do: acc
635+
636+ # Implement for each type
637+ defp each_singleton? ( :bitmap , bitmap ) , do: bitmap == @ bit_empty_list
638+
639+ defp each_singleton? ( :atom , atoms ) , do: match? ( { :union , set } when map_size ( set ) == 1 , atoms )
640+
641+ defp each_singleton? ( :tuple , bdd ) do
642+ case tuple_bdd_to_dnf ( bdd ) do
643+ [ ] -> :empty
644+ [ { :closed , entries } ] -> Enum . all? ( entries , & static_singleton? / 1 )
645+ _ -> false
646+ end
647+ end
648+
649+ defp each_singleton? ( :map , bdd ) do
650+ case map_bdd_to_dnf ( bdd ) do
651+ [ ] -> :empty
652+ [ { :closed , fields , _negs } ] -> Enum . all? ( fields , fn { _ , v } -> static_singleton? ( v ) end )
653+ _ -> false
654+ end
655+ end
656+
607657 @ doc """
608658 Converts a descr to its quoted representation.
609659
@@ -3850,15 +3900,6 @@ defmodule Module.Types.Descr do
38503900 end )
38513901 end
38523902
3853- # Use heuristics to normalize a map bdd for pretty printing.
3854- defp map_normalize ( bdd ) do
3855- map_bdd_to_dnf ( bdd )
3856- |> Enum . map ( fn { tag , fields , negs } ->
3857- map_eliminate_while_negs_decrease ( tag , fields , negs )
3858- end )
3859- |> map_fusion ( )
3860- end
3861-
38623903 # Continue to eliminate negations while length of list of negs decreases
38633904 defp map_eliminate_while_negs_decrease ( tag , fields , [ ] ) , do: { tag , fields , [ ] }
38643905
@@ -3950,7 +3991,12 @@ defmodule Module.Types.Descr do
39503991 end
39513992
39523993 defp map_to_quoted ( bdd , opts ) do
3953- map_normalize ( bdd )
3994+ bdd
3995+ |> map_bdd_to_dnf ( )
3996+ |> Enum . map ( fn { tag , fields , negs } ->
3997+ map_eliminate_while_negs_decrease ( tag , fields , negs )
3998+ end )
3999+ |> map_fusion ( )
39544000 |> Enum . map ( & map_each_to_quoted ( & 1 , opts ) )
39554001 end
39564002
@@ -4472,14 +4518,14 @@ defmodule Module.Types.Descr do
44724518 end
44734519
44744520 defp tuple_to_quoted ( bdd , opts ) do
4475- tuple_normalize ( bdd )
4521+ tuple_bdd_to_dnf ( bdd )
44764522 |> tuple_fusion ( )
44774523 |> Enum . map ( & tuple_literal_to_quoted ( & 1 , opts ) )
44784524 end
44794525
44804526 # Transforms a bdd into a union of tuples with no negations.
44814527 # Note: it is important to compose the results with tuple_dnf_union/2 to avoid duplicates
4482- defp tuple_normalize ( bdd ) do
4528+ defp tuple_bdd_to_dnf ( bdd ) do
44834529 bdd_to_dnf ( bdd )
44844530 |> Enum . reduce ( [ ] , fn { positive_tuples , negative_tuples } , acc ->
44854531 case non_empty_tuple_literals_intersection ( positive_tuples ) do
@@ -4639,7 +4685,7 @@ defmodule Module.Types.Descr do
46394685 end
46404686
46414687 defp tuple_get ( bdd , index ) do
4642- tuple_normalize ( bdd )
4688+ tuple_bdd_to_dnf ( bdd )
46434689 |> Enum . reduce ( none ( ) , fn
46444690 { tag , elements } , acc -> Enum . at ( elements , index , tuple_tag_to_type ( tag ) ) |> union ( acc )
46454691 end )
@@ -4670,7 +4716,7 @@ defmodule Module.Types.Descr do
46704716 end
46714717
46724718 defp process_tuples_values ( bdd ) do
4673- tuple_normalize ( bdd )
4719+ tuple_bdd_to_dnf ( bdd )
46744720 |> Enum . reduce ( none ( ) , fn { tag , elements } , acc ->
46754721 cond do
46764722 Enum . any? ( elements , & empty? / 1 ) -> none ( )
@@ -4808,7 +4854,7 @@ defmodule Module.Types.Descr do
48084854 defp tuple_of_size_at_least_static? ( descr , index ) do
48094855 case descr do
48104856 % { tuple: bdd } ->
4811- tuple_normalize ( bdd )
4857+ tuple_bdd_to_dnf ( bdd )
48124858 |> Enum . all? ( fn { _ , elements } -> length ( elements ) >= index end )
48134859
48144860 % { } ->
0 commit comments