{-# LANGUAGE TypeOperators, KindSignatures, DataKinds, PolyKinds,
TypeFamilies, UndecidableInstances, EmptyDataDecls,
MultiParamTypeClasses, FlexibleInstances, ConstraintKinds,
AllowAmbiguousTypes, FlexibleContexts, ScopedTypeVariables,
TypeApplications, OverloadedStrings #-}
module Data.GI.Base.Overloading
(
ParentTypes
, HasParentTypes
, IsDescendantOf
, asA
, AttributeList
, HasAttributeList
, ResolveAttribute
, HasAttribute
, HasAttr
, SignalList
, ResolveSignal
, HasSignal
, MethodResolutionFailed
, UnsupportedMethodError
, OverloadedMethodInfo(..)
, OverloadedMethod(..)
, MethodProxy(..)
, ResolvedSymbolInfo(..)
, resolveMethod
) where
import Data.Coerce (coerce)
import Data.Kind (Type)
import GHC.Exts (Constraint)
import GHC.TypeLits
import Data.GI.Base.BasicTypes (ManagedPtrNewtype, ManagedPtr(..))
import Data.Text (Text)
import qualified Data.Text as T
type family FindElement (m :: Symbol) (ms :: [(Symbol, Type)])
(typeError :: ErrorMessage) :: Type where
FindElement m '[] typeError = TypeError typeError
FindElement m ('(m, o) ': ms) typeError = o
FindElement m ('(m', o) ': ms) typeError = FindElement m ms typeError
type family CheckForAncestorType t (a :: Type) (as :: [Type]) :: Constraint where
CheckForAncestorType t a '[] = TypeError ('Text "Required ancestor ‘"
':<>: 'ShowType a
':<>: 'Text "’ not found for type ‘"
':<>: 'ShowType t ':<>: 'Text "’.")
CheckForAncestorType t a (a ': as) = ()
CheckForAncestorType t a (b ': as) = CheckForAncestorType t a as
type family IsDescendantOf (parent :: Type) (descendant :: Type) :: Constraint where
IsDescendantOf d d = ()
IsDescendantOf p d = CheckForAncestorType d p (ParentTypes d)
type family ParentTypes a :: [Type]
class HasParentTypes (o :: Type)
instance {-# OVERLAPPABLE #-}
TypeError ('Text "Type ‘" ':<>: 'ShowType a ':<>:
'Text "’ does not have any known parent types.")
=> HasParentTypes a
asA :: (ManagedPtrNewtype a, ManagedPtrNewtype b,
HasParentTypes b, IsDescendantOf a b)
=> b -> (ManagedPtr a -> a) -> a
asA :: b -> (ManagedPtr a -> a) -> a
asA b
obj ManagedPtr a -> a
_constructor = b -> a
coerce b
obj
type family AttributeList a :: [(Symbol, Type)]
class HasAttributeList a
instance {-# OVERLAPPABLE #-}
TypeError ('Text "Type ‘" ':<>: 'ShowType a ':<>:
'Text "’ does not have any known attributes.")
=> HasAttributeList a
type family ResolveAttribute (s :: Symbol) (o :: Type) :: Type where
ResolveAttribute s o = FindElement s (AttributeList o)
('Text "Unknown attribute ‘" ':<>:
'Text s ':<>: 'Text "’ for object ‘" ':<>:
'ShowType o ':<>: 'Text "’.")
type family IsElem (e :: Symbol) (es :: [(Symbol, Type)]) (success :: k)
(failure :: ErrorMessage) :: k where
IsElem e '[] success failure = TypeError failure
IsElem e ( '(e, t) ': es) success failure = success
IsElem e ( '(other, t) ': es) s f = IsElem e es s f
type family HasAttribute (attr :: Symbol) (o :: Type) :: Constraint where
HasAttribute attr o = IsElem attr (AttributeList o)
(() :: Constraint)
('Text "Attribute ‘" ':<>: 'Text attr ':<>:
'Text "’ not found for type ‘" ':<>:
'ShowType o ':<>: 'Text "’.")
class HasAttr (attr :: Symbol) (o :: Type)
instance HasAttribute attr o => HasAttr attr o
type family SignalList a :: [(Symbol, Type)]
type family ResolveSignal (s :: Symbol) (o :: Type) :: Type where
ResolveSignal s o = FindElement s (SignalList o)
('Text "Unknown signal ‘" ':<>:
'Text s ':<>: 'Text "’ for object ‘" ':<>:
'ShowType o ':<>: 'Text "’.")
type family HasSignal (s :: Symbol) (o :: Type) :: Constraint where
HasSignal s o = IsElem s (SignalList o)
(() :: Constraint)
('Text "Signal ‘" ':<>: 'Text s ':<>:
'Text "’ not found for type ‘" ':<>:
'ShowType o ':<>: 'Text "’.")
type family UnsupportedMethodError (s :: Symbol) (o :: Type) :: Type where
UnsupportedMethodError s o =
TypeError ('Text "Unsupported method ‘" ':<>:
'Text s ':<>: 'Text "’ for object ‘" ':<>:
'ShowType o ':<>: 'Text "’.")
type family MethodResolutionFailed (method :: Symbol) (o :: Type) where
MethodResolutionFailed m o =
TypeError ('Text "Unknown method ‘" ':<>:
'Text m ':<>: 'Text "’ for type ‘" ':<>:
'ShowType o ':<>: 'Text "’.")
class OverloadedMethod i o s where
overloadedMethod :: o -> s
data ResolvedSymbolInfo = ResolvedSymbolInfo {
ResolvedSymbolInfo -> Text
resolvedSymbolName :: Text
, ResolvedSymbolInfo -> Text
resolvedSymbolURL :: Text
}
instance Show ResolvedSymbolInfo where
show :: ResolvedSymbolInfo -> String
show ResolvedSymbolInfo
info = Text -> String
T.unpack (Text
"\ESC]8;;" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ResolvedSymbolInfo -> Text
resolvedSymbolURL ResolvedSymbolInfo
info
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\ESC\\" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ResolvedSymbolInfo -> Text
resolvedSymbolName ResolvedSymbolInfo
info
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\ESC]8;;\ESC\\")
class OverloadedMethodInfo i o where
overloadedMethodInfo :: Maybe ResolvedSymbolInfo
data MethodProxy (info :: Type) (obj :: Type) = MethodProxy
resolveMethod :: forall info obj. (OverloadedMethodInfo info obj) =>
obj -> MethodProxy info obj -> Maybe ResolvedSymbolInfo
resolveMethod :: obj -> MethodProxy info obj -> Maybe ResolvedSymbolInfo
resolveMethod obj
_o MethodProxy info obj
_p = OverloadedMethodInfo info obj => Maybe ResolvedSymbolInfo
forall k k (i :: k) (o :: k).
OverloadedMethodInfo i o =>
Maybe ResolvedSymbolInfo
overloadedMethodInfo @info @obj