module Clr.Resolver.BetterConversion (IsBetterConv) where
import Clr.Resolver.ImplicitConversions
import Clr.ListTuple
import Clr.Types
import Data.Kind
import GHC.TypeLits
import Data.Type.Bool
import Data.Type.Equality
type family IsBetterConv (s::Type) (t1::Type) (t2::Type) :: Bool where
IsBetterConv s t1 t2 = BestType s t1 t2 == 'Just t1
type family BestType (s::Type) (t1::Type) (t2::Type) :: Maybe Type where
BestType s t t = 'Nothing
BestType t1 t1 t2 = 'Just t1
BestType t2 t1 t2 = 'Just t2
BestType s t1 t2 = BestType' (ImplicitConvExists t1 t2) t1 (ImplicitConvExists t2 t1) t2
type family BestType' (b1::Bool) (t1::Type) (b2::Bool) (t2::Type) :: Maybe Type where
BestType' 'True t1 'False t2 = 'Just t1
BestType' 'False t1 'True t2 = 'Just t2
BestType' _ t1 _ t2 = (BestType'' t1 t2) <|> (BestType'' t2 t1)
type family BestType'' (t1::Type) (t2::Type) :: Maybe Type where
BestType'' (T "System.SByte" '[]) t2 = If (t2 `Elem` UNumAtLeastSByte) ('Just (T "System.SByte" '[])) 'Nothing
BestType'' (T "System.Int16" '[]) t2 = If (t2 `Elem` UNumAtLeastInt16) ('Just (T "System.Int16" '[])) 'Nothing
BestType'' (T "System.Int32" '[]) t2 = If (t2 `Elem` UNumAtLeastInt32) ('Just (T "System.Int32" '[])) 'Nothing
BestType'' (T "System.Int64" '[]) t2 = If (t2 `Elem` UNumAtLeastInt64) ('Just (T "System.Int64" '[])) 'Nothing
BestType'' t1 t2 = 'Nothing
type family (a::k) <|> (b::k) :: k
type family MaybeAlt (a::Maybe k) (b::Maybe k) :: Maybe k where
MaybeAlt 'Nothing x = x
MaybeAlt x 'Nothing = x
type instance a <|> b = MaybeAlt a b
type UNumAtLeastSByte = (T "System.Byte" '[]) ': UNumAtLeastInt32
type UNumAtLeastInt16 = (T "System.UInt16" '[]) ': UNumAtLeastInt32
type UNumAtLeastInt32 = (T "System.UInt32" '[]) ': UNumAtLeastInt64
type UNumAtLeastInt64 = '[ T "System.UInt64" '[] ]