@@ -5878,6 +5878,23 @@ defmodule Module.Types.Descr do
58785878
58795879 ## Optimize differences
58805880
5881+ defp bdd_difference ( bdd_leaf ( _ , _ ) = a1 , bdd_leaf ( _ , _ ) = a2 , leaf_compare ) do
5882+ case leaf_compare . ( a1 , a2 , :none ) do
5883+ :disjoint -> a1
5884+ :subtype -> :bdd_bot
5885+ { :one_key_difference , a_diff , _ } -> a_diff
5886+ :none -> bdd_difference ( a1 , a2 )
5887+ end
5888+ end
5889+
5890+ defp bdd_difference ( bdd1 , bdd2 , leaf_compare ) when is_tuple ( bdd1 ) and is_tuple ( bdd2 ) do
5891+ bdd_difference ( bdd_expand ( bdd1 ) , bdd_expand ( bdd2 ) , bdd1 , bdd2 , leaf_compare )
5892+ end
5893+
5894+ defp bdd_difference ( bdd1 , bdd2 , _leaf_compare ) do
5895+ bdd_difference ( bdd1 , bdd2 )
5896+ end
5897+
58815898 # We have two formulas for differences.
58825899 #
58835900 # ## When D1 = bottom
@@ -5906,93 +5923,65 @@ defmodule Module.Types.Descr do
59065923 #
59075924 # ((U1 and not a2) or (D1 and not D2)) and not U2 and not D2
59085925 #
5909- defp bdd_difference ( bdd_leaf ( _ , _ ) = a1 , bdd_leaf ( _ , _ ) = a2 , leaf_compare ) do
5910- case leaf_compare . ( a1 , a2 , :none ) do
5911- :disjoint -> a1
5912- :subtype -> :bdd_bot
5913- { :one_key_difference , a_diff , _ } -> a_diff
5914- :none -> bdd_difference ( a1 , a2 )
5915- end
5916- end
5926+ defp bdd_difference ( { a1 , :bdd_top , u1 , :bdd_bot } , { a2 , c2 , u2 , d2 } , bdd1 , bdd2 , leaf_compare ) do
5927+ type = if c2 == :bdd_top , do: :none , else: :intersection
59175928
5918- defp bdd_difference ( bdd1 , bdd2 , leaf_compare ) when is_tuple ( bdd1 ) and is_tuple ( bdd2 ) do
5919- # TODO: Use bdd_expand on Erlang/OTP 28.
5920- # We write the case by hand to address a bug in Erlang/OTP 27.0
5921- { a1 , c1 , u1 , d1 } =
5922- case bdd1 do
5923- bdd_leaf ( _ , _ ) -> { bdd1 , :bdd_top , :bdd_bot , :bdd_bot }
5924- _ -> bdd1
5925- end
5926-
5927- { a2 , c2 , u2 , d2 } =
5928- case bdd2 do
5929- bdd_leaf ( _ , _ ) -> { bdd2 , :bdd_top , :bdd_bot , :bdd_bot }
5930- _ -> bdd2
5931- end
5932-
5933- cond do
5934- d1 == :bdd_bot and c1 == :bdd_top ->
5935- type = if c2 == :bdd_top , do: :none , else: :intersection
5936-
5937- case leaf_compare . ( a1 , a2 , type ) do
5938- :disjoint ->
5939- a1
5940- |> bdd_difference ( d2 , leaf_compare )
5941- |> bdd_difference ( u2 , leaf_compare )
5942- |> bdd_union ( bdd_difference ( u1 , bdd2 , leaf_compare ) )
5943-
5944- :subtype ->
5945- a1
5946- |> bdd_difference ( c2 , leaf_compare )
5947- |> bdd_difference ( u2 , leaf_compare )
5948- |> bdd_union ( bdd_difference ( u1 , bdd2 , leaf_compare ) )
5949-
5950- { :one_key_difference , a_diff , a_int } ->
5951- bdd_union (
5952- a_diff |> bdd_difference ( d2 , leaf_compare ) |> bdd_difference ( u2 , leaf_compare ) ,
5953- a_int |> bdd_difference ( c2 , leaf_compare ) |> bdd_difference ( u2 , leaf_compare )
5954- )
5955- |> bdd_union ( bdd_difference ( u1 , bdd2 , leaf_compare ) )
5956-
5957- :none ->
5958- bdd_difference ( bdd1 , bdd2 )
5959- end
5929+ case leaf_compare . ( a1 , a2 , type ) do
5930+ :disjoint ->
5931+ a1
5932+ |> bdd_difference ( d2 , leaf_compare )
5933+ |> bdd_difference ( u2 , leaf_compare )
5934+ |> bdd_union ( bdd_difference ( u1 , bdd2 , leaf_compare ) )
5935+
5936+ :subtype ->
5937+ a1
5938+ |> bdd_difference ( c2 , leaf_compare )
5939+ |> bdd_difference ( u2 , leaf_compare )
5940+ |> bdd_union ( bdd_difference ( u1 , bdd2 , leaf_compare ) )
5941+
5942+ { :one_key_difference , a_diff , a_int } ->
5943+ bdd_union (
5944+ a_diff |> bdd_difference ( d2 , leaf_compare ) |> bdd_difference ( u2 , leaf_compare ) ,
5945+ a_int |> bdd_difference ( c2 , leaf_compare ) |> bdd_difference ( u2 , leaf_compare )
5946+ )
5947+ |> bdd_union ( bdd_difference ( u1 , bdd2 , leaf_compare ) )
59605948
5961- c2 == :bdd_top ->
5962- type = if d1 == :bdd_bot , do: :none , else: :union
5949+ :none ->
5950+ bdd_difference ( bdd1 , bdd2 )
5951+ end
5952+ end
59635953
5964- case leaf_compare . ( a1 , a2 , type ) do
5965- :disjoint ->
5966- bdd_difference ( u1 , a2 , leaf_compare )
5967- |> bdd_union ( bdd_difference ( { a1 , c1 , :bdd_bot , d1 } , a2 ) )
5968- |> bdd_difference ( d2 , leaf_compare )
5969- |> bdd_difference ( u2 , leaf_compare )
5970-
5971- :subtype ->
5972- bdd_union (
5973- bdd_difference ( u1 , a2 , leaf_compare ) ,
5974- bdd_difference ( d1 , a2 , leaf_compare )
5975- )
5976- |> bdd_difference ( d2 , leaf_compare )
5977- |> bdd_difference ( u2 , leaf_compare )
5954+ defp bdd_difference ( { a1 , c1 , u1 , d1 } , { a2 , :bdd_top , u2 , d2 } , bdd1 , bdd2 , leaf_compare ) do
5955+ type = if d1 == :bdd_bot , do: :none , else: :union
59785956
5979- { :one_key_difference , a_diff , a_union } ->
5980- bdd_intersection ( a_diff , c1 )
5981- |> bdd_union ( bdd_difference ( u1 , a2 , leaf_compare ) )
5982- |> bdd_union ( bdd_difference ( d1 , a_union , leaf_compare ) )
5983- |> bdd_difference ( d2 , leaf_compare )
5984- |> bdd_difference ( u2 , leaf_compare )
5957+ case leaf_compare . ( a1 , a2 , type ) do
5958+ :disjoint ->
5959+ bdd_difference ( u1 , a2 , leaf_compare )
5960+ |> bdd_union ( bdd_difference ( { a1 , c1 , :bdd_bot , d1 } , a2 ) )
5961+ |> bdd_difference ( d2 , leaf_compare )
5962+ |> bdd_difference ( u2 , leaf_compare )
5963+
5964+ :subtype ->
5965+ bdd_union (
5966+ bdd_difference ( u1 , a2 , leaf_compare ) ,
5967+ bdd_difference ( d1 , a2 , leaf_compare )
5968+ )
5969+ |> bdd_difference ( d2 , leaf_compare )
5970+ |> bdd_difference ( u2 , leaf_compare )
59855971
5986- :none ->
5987- bdd_difference ( bdd1 , bdd2 )
5988- end
5972+ { :one_key_difference , a_diff , a_union } ->
5973+ bdd_intersection ( a_diff , c1 )
5974+ |> bdd_union ( bdd_difference ( u1 , a2 , leaf_compare ) )
5975+ |> bdd_union ( bdd_difference ( d1 , a_union , leaf_compare ) )
5976+ |> bdd_difference ( d2 , leaf_compare )
5977+ |> bdd_difference ( u2 , leaf_compare )
59895978
5990- true ->
5979+ :none ->
59915980 bdd_difference ( bdd1 , bdd2 )
59925981 end
59935982 end
59945983
5995- defp bdd_difference ( bdd1 , bdd2 , _leaf_compare ) do
5984+ defp bdd_difference ( _ , _ , bdd1 , bdd2 , _leaf_compare ) do
59965985 bdd_difference ( bdd1 , bdd2 )
59975986 end
59985987
0 commit comments