{-# LANGUAGE GADTs, ScopedTypeVariables, DataKinds, KindSignatures,
TypeFamilies, TypeOperators, MultiParamTypeClasses, ConstraintKinds,
UndecidableInstances, FlexibleInstances, TypeApplications,
DefaultSignatures, PolyKinds, AllowAmbiguousTypes #-}
module Data.GI.Base.Attributes (
AttrInfo(..),
AttrOpTag(..),
AttrOp(..),
AttrOpAllowed,
AttrGetC,
AttrSetC,
AttrConstructC,
AttrClearC,
get,
set,
clear,
AttrLabelProxy(..)
) where
import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.GI.Base.GValue (GValueConstruct)
import Data.GI.Base.Overloading (HasAttributeList, ResolveAttribute)
import Data.Proxy (Proxy(..))
import GHC.TypeLits
import GHC.Exts (Constraint)
import GHC.OverloadedLabels (IsLabel(..))
infixr 0 :=,:~,:=>,:~>
data AttrLabelProxy (a :: Symbol) = AttrLabelProxy
#if MIN_VERSION_base(4,10,0)
instance a ~ x => IsLabel x (AttrLabelProxy a) where
fromLabel :: AttrLabelProxy a
fromLabel = AttrLabelProxy a
forall (a :: Symbol). AttrLabelProxy a
AttrLabelProxy
#else
instance a ~ x => IsLabel x (AttrLabelProxy a) where
fromLabel _ = AttrLabelProxy
#endif
class AttrInfo (info :: *) where
type AttrAllowedOps info :: [AttrOpTag]
type AttrBaseTypeConstraint info :: * -> Constraint
type AttrGetType info
type AttrSetTypeConstraint info :: * -> Constraint
type AttrSetTypeConstraint info = (~) (AttrGetType info)
type AttrTransferTypeConstraint info :: * -> Constraint
type AttrTransferTypeConstraint info = (~) (AttrTransferType info)
type AttrTransferType info :: *
type AttrTransferType info = AttrGetType info
type AttrLabel info :: Symbol
type AttrOrigin info
attrGet :: AttrBaseTypeConstraint info o =>
o -> IO (AttrGetType info)
default attrGet ::
CheckNotElem 'AttrGet (AttrAllowedOps info)
(GetNotProvidedError info) =>
o -> IO (AttrGetType info)
attrGet = o -> IO (AttrGetType info)
forall a. HasCallStack => a
undefined
attrSet :: (AttrBaseTypeConstraint info o,
AttrSetTypeConstraint info b) =>
o -> b -> IO ()
default attrSet ::
CheckNotElem 'AttrSet (AttrAllowedOps info)
(SetNotProvidedError info) =>
o -> b -> IO ()
attrSet = o -> b -> IO ()
forall a. HasCallStack => a
undefined
attrClear :: AttrBaseTypeConstraint info o =>
o -> IO ()
default attrClear ::
CheckNotElem 'AttrClear (AttrAllowedOps info)
(ClearNotProvidedError info) =>
o -> IO ()
attrClear = o -> IO ()
forall a. HasCallStack => a
undefined
attrConstruct :: (AttrBaseTypeConstraint info o,
AttrSetTypeConstraint info b) =>
b -> IO (GValueConstruct o)
default attrConstruct ::
CheckNotElem 'AttrConstruct (AttrAllowedOps info)
(ConstructNotProvidedError info) =>
b -> IO (GValueConstruct o)
attrConstruct = b -> IO (GValueConstruct o)
forall a. HasCallStack => a
undefined
attrTransfer :: forall o b. (AttrBaseTypeConstraint info o,
AttrTransferTypeConstraint info b) =>
Proxy o -> b -> IO (AttrTransferType info)
default attrTransfer :: forall o b. (AttrBaseTypeConstraint info o,
AttrTransferTypeConstraint info b,
b ~ AttrGetType info,
b ~ AttrTransferType info) =>
Proxy o -> b -> IO (AttrTransferType info)
attrTransfer Proxy o
_ = b -> IO (AttrTransferType info)
forall (m :: * -> *) a. Monad m => a -> m a
return
type family TypeOriginInfo definingType useType :: ErrorMessage where
TypeOriginInfo definingType definingType =
'Text "‘" ':<>: 'ShowType definingType ':<>: 'Text "’"
TypeOriginInfo definingType useType =
'Text "‘" ':<>: 'ShowType useType ':<>:
'Text "’ (inherited from parent type ‘" ':<>:
'ShowType definingType ':<>: 'Text "’)"
type family AttrOpIsAllowed (tag :: AttrOpTag) (ops :: [AttrOpTag]) (label :: Symbol) (definingType :: *) (useType :: *) :: Constraint where
AttrOpIsAllowed tag '[] label definingType useType =
TypeError ('Text "Attribute ‘" ':<>: 'Text label ':<>:
'Text "’ for type " ':<>:
TypeOriginInfo definingType useType ':<>:
'Text " is not " ':<>:
'Text (AttrOpText tag) ':<>: 'Text ".")
AttrOpIsAllowed tag (tag ': ops) label definingType useType = ()
AttrOpIsAllowed tag (other ': ops) label definingType useType = AttrOpIsAllowed tag ops label definingType useType
type family AttrOpAllowed (tag :: AttrOpTag) (info :: *) (useType :: *) :: Constraint where
AttrOpAllowed tag info useType =
AttrOpIsAllowed tag (AttrAllowedOps info) (AttrLabel info) (AttrOrigin info) useType
type family OpNotProvidedError (info :: o) (op :: AttrOpTag) (methodName :: Symbol) :: ErrorMessage where
OpNotProvidedError info op methodName =
'Text "The attribute ‘" ':<>: 'Text (AttrLabel info) ':<>:
'Text "’ for type ‘" ':<>:
'ShowType (AttrOrigin info) ':<>:
'Text "’ is declared as " ':<>:
'Text (AttrOpText op) ':<>:
'Text ", but no implementation of ‘" ':<>:
'Text methodName ':<>:
'Text "’ has been provided."
':$$: 'Text "Either provide an implementation of ‘" ':<>:
'Text methodName ':<>:
'Text "’ or remove ‘" ':<>:
'ShowType op ':<>:
'Text "’ from ‘AttrAllowedOps’."
type family ClearNotProvidedError (info :: o) :: ErrorMessage where
ClearNotProvidedError info = OpNotProvidedError info 'AttrClear "attrClear"
type family GetNotProvidedError (info :: o) :: ErrorMessage where
GetNotProvidedError info = OpNotProvidedError info 'AttrGet "attrGet"
type family SetNotProvidedError (info :: o) :: ErrorMessage where
SetNotProvidedError info = OpNotProvidedError info 'AttrSet "attrSet"
type family ConstructNotProvidedError (info :: o) :: ErrorMessage where
ConstructNotProvidedError info = OpNotProvidedError info 'AttrConstruct "attrConstruct"
type family CheckNotElem (a :: k) (as :: [k]) (msg :: ErrorMessage) :: Constraint where
CheckNotElem a '[] msg = ()
CheckNotElem a (a ': rest) msg = TypeError msg
CheckNotElem a (other ': rest) msg = CheckNotElem a rest msg
data AttrOpTag = AttrGet
| AttrSet
| AttrConstruct
| AttrClear
deriving (AttrOpTag -> AttrOpTag -> Bool
(AttrOpTag -> AttrOpTag -> Bool)
-> (AttrOpTag -> AttrOpTag -> Bool) -> Eq AttrOpTag
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AttrOpTag -> AttrOpTag -> Bool
$c/= :: AttrOpTag -> AttrOpTag -> Bool
== :: AttrOpTag -> AttrOpTag -> Bool
$c== :: AttrOpTag -> AttrOpTag -> Bool
Eq, Eq AttrOpTag
Eq AttrOpTag
-> (AttrOpTag -> AttrOpTag -> Ordering)
-> (AttrOpTag -> AttrOpTag -> Bool)
-> (AttrOpTag -> AttrOpTag -> Bool)
-> (AttrOpTag -> AttrOpTag -> Bool)
-> (AttrOpTag -> AttrOpTag -> Bool)
-> (AttrOpTag -> AttrOpTag -> AttrOpTag)
-> (AttrOpTag -> AttrOpTag -> AttrOpTag)
-> Ord AttrOpTag
AttrOpTag -> AttrOpTag -> Bool
AttrOpTag -> AttrOpTag -> Ordering
AttrOpTag -> AttrOpTag -> AttrOpTag
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: AttrOpTag -> AttrOpTag -> AttrOpTag
$cmin :: AttrOpTag -> AttrOpTag -> AttrOpTag
max :: AttrOpTag -> AttrOpTag -> AttrOpTag
$cmax :: AttrOpTag -> AttrOpTag -> AttrOpTag
>= :: AttrOpTag -> AttrOpTag -> Bool
$c>= :: AttrOpTag -> AttrOpTag -> Bool
> :: AttrOpTag -> AttrOpTag -> Bool
$c> :: AttrOpTag -> AttrOpTag -> Bool
<= :: AttrOpTag -> AttrOpTag -> Bool
$c<= :: AttrOpTag -> AttrOpTag -> Bool
< :: AttrOpTag -> AttrOpTag -> Bool
$c< :: AttrOpTag -> AttrOpTag -> Bool
compare :: AttrOpTag -> AttrOpTag -> Ordering
$ccompare :: AttrOpTag -> AttrOpTag -> Ordering
$cp1Ord :: Eq AttrOpTag
Ord, Int -> AttrOpTag
AttrOpTag -> Int
AttrOpTag -> [AttrOpTag]
AttrOpTag -> AttrOpTag
AttrOpTag -> AttrOpTag -> [AttrOpTag]
AttrOpTag -> AttrOpTag -> AttrOpTag -> [AttrOpTag]
(AttrOpTag -> AttrOpTag)
-> (AttrOpTag -> AttrOpTag)
-> (Int -> AttrOpTag)
-> (AttrOpTag -> Int)
-> (AttrOpTag -> [AttrOpTag])
-> (AttrOpTag -> AttrOpTag -> [AttrOpTag])
-> (AttrOpTag -> AttrOpTag -> [AttrOpTag])
-> (AttrOpTag -> AttrOpTag -> AttrOpTag -> [AttrOpTag])
-> Enum AttrOpTag
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: AttrOpTag -> AttrOpTag -> AttrOpTag -> [AttrOpTag]
$cenumFromThenTo :: AttrOpTag -> AttrOpTag -> AttrOpTag -> [AttrOpTag]
enumFromTo :: AttrOpTag -> AttrOpTag -> [AttrOpTag]
$cenumFromTo :: AttrOpTag -> AttrOpTag -> [AttrOpTag]
enumFromThen :: AttrOpTag -> AttrOpTag -> [AttrOpTag]
$cenumFromThen :: AttrOpTag -> AttrOpTag -> [AttrOpTag]
enumFrom :: AttrOpTag -> [AttrOpTag]
$cenumFrom :: AttrOpTag -> [AttrOpTag]
fromEnum :: AttrOpTag -> Int
$cfromEnum :: AttrOpTag -> Int
toEnum :: Int -> AttrOpTag
$ctoEnum :: Int -> AttrOpTag
pred :: AttrOpTag -> AttrOpTag
$cpred :: AttrOpTag -> AttrOpTag
succ :: AttrOpTag -> AttrOpTag
$csucc :: AttrOpTag -> AttrOpTag
Enum, AttrOpTag
AttrOpTag -> AttrOpTag -> Bounded AttrOpTag
forall a. a -> a -> Bounded a
maxBound :: AttrOpTag
$cmaxBound :: AttrOpTag
minBound :: AttrOpTag
$cminBound :: AttrOpTag
Bounded, Int -> AttrOpTag -> ShowS
[AttrOpTag] -> ShowS
AttrOpTag -> String
(Int -> AttrOpTag -> ShowS)
-> (AttrOpTag -> String)
-> ([AttrOpTag] -> ShowS)
-> Show AttrOpTag
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AttrOpTag] -> ShowS
$cshowList :: [AttrOpTag] -> ShowS
show :: AttrOpTag -> String
$cshow :: AttrOpTag -> String
showsPrec :: Int -> AttrOpTag -> ShowS
$cshowsPrec :: Int -> AttrOpTag -> ShowS
Show)
type family AttrOpText (tag :: AttrOpTag) :: Symbol where
AttrOpText 'AttrGet = "gettable"
AttrOpText 'AttrSet = "settable"
AttrOpText 'AttrConstruct = "constructible"
AttrOpText 'AttrClear = "nullable"
type AttrSetC info obj attr value = (HasAttributeList obj,
info ~ ResolveAttribute attr obj,
AttrInfo info,
AttrBaseTypeConstraint info obj,
AttrOpAllowed 'AttrSet info obj,
(AttrSetTypeConstraint info) value)
type AttrConstructC info obj attr value = (HasAttributeList obj,
info ~ ResolveAttribute attr obj,
AttrInfo info,
AttrBaseTypeConstraint info obj,
AttrOpAllowed 'AttrConstruct info obj,
(AttrSetTypeConstraint info) value)
data AttrOp obj (tag :: AttrOpTag) where
(:=) :: (HasAttributeList obj,
info ~ ResolveAttribute attr obj,
AttrInfo info,
AttrBaseTypeConstraint info obj,
AttrOpAllowed tag info obj,
(AttrSetTypeConstraint info) b) =>
AttrLabelProxy (attr :: Symbol) -> b -> AttrOp obj tag
(:=>) :: (HasAttributeList obj,
info ~ ResolveAttribute attr obj,
AttrInfo info,
AttrBaseTypeConstraint info obj,
AttrOpAllowed tag info obj,
(AttrSetTypeConstraint info) b) =>
AttrLabelProxy (attr :: Symbol) -> IO b -> AttrOp obj tag
(:~) :: (HasAttributeList obj,
info ~ ResolveAttribute attr obj,
AttrInfo info,
AttrBaseTypeConstraint info obj,
tag ~ 'AttrSet,
AttrOpAllowed 'AttrSet info obj,
AttrOpAllowed 'AttrGet info obj,
(AttrSetTypeConstraint info) b,
a ~ (AttrGetType info)) =>
AttrLabelProxy (attr :: Symbol) -> (a -> b) -> AttrOp obj tag
(:~>) :: (HasAttributeList obj,
info ~ ResolveAttribute attr obj,
AttrInfo info,
AttrBaseTypeConstraint info obj,
tag ~ 'AttrSet,
AttrOpAllowed 'AttrSet info obj,
AttrOpAllowed 'AttrGet info obj,
(AttrSetTypeConstraint info) b,
a ~ (AttrGetType info)) =>
AttrLabelProxy (attr :: Symbol) -> (a -> IO b) -> AttrOp obj tag
(:&=) :: (HasAttributeList obj,
info ~ ResolveAttribute attr obj,
AttrInfo info,
AttrBaseTypeConstraint info obj,
AttrOpAllowed tag info obj,
(AttrTransferTypeConstraint info) b,
AttrSetTypeConstraint info (AttrTransferType info)) =>
AttrLabelProxy (attr :: Symbol) -> b -> AttrOp obj tag
set :: forall o m. MonadIO m => o -> [AttrOp o 'AttrSet] -> m ()
set :: o -> [AttrOp o 'AttrSet] -> m ()
set o
obj = IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ())
-> ([AttrOp o 'AttrSet] -> IO ()) -> [AttrOp o 'AttrSet] -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (AttrOp o 'AttrSet -> IO ()) -> [AttrOp o 'AttrSet] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ AttrOp o 'AttrSet -> IO ()
app
where
app :: AttrOp o 'AttrSet -> IO ()
app :: AttrOp o 'AttrSet -> IO ()
app ((AttrLabelProxy attr
_attr :: AttrLabelProxy label) := b
x) =
o -> b -> IO ()
forall info o b.
(AttrInfo info, AttrBaseTypeConstraint info o,
AttrSetTypeConstraint info b) =>
o -> b -> IO ()
attrSet @(ResolveAttribute label o) o
obj b
x
app ((AttrLabelProxy attr
_attr :: AttrLabelProxy label) :=> IO b
x) =
IO b
x IO b -> (b -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= o -> b -> IO ()
forall info o b.
(AttrInfo info, AttrBaseTypeConstraint info o,
AttrSetTypeConstraint info b) =>
o -> b -> IO ()
attrSet @(ResolveAttribute label o) o
obj
app ((AttrLabelProxy attr
_attr :: AttrLabelProxy label) :~ a -> b
f) =
o -> IO (AttrGetType (ResolveAttribute attr o))
forall info o.
(AttrInfo info, AttrBaseTypeConstraint info o) =>
o -> IO (AttrGetType info)
attrGet @(ResolveAttribute label o) o
obj IO a -> (a -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
\a
v -> o -> b -> IO ()
forall info o b.
(AttrInfo info, AttrBaseTypeConstraint info o,
AttrSetTypeConstraint info b) =>
o -> b -> IO ()
attrSet @(ResolveAttribute label o) o
obj (a -> b
f a
v)
app ((AttrLabelProxy attr
_attr :: AttrLabelProxy label) :~> a -> IO b
f) =
o -> IO (AttrGetType (ResolveAttribute attr o))
forall info o.
(AttrInfo info, AttrBaseTypeConstraint info o) =>
o -> IO (AttrGetType info)
attrGet @(ResolveAttribute label o) o
obj IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> IO b
f IO b -> (b -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
o -> b -> IO ()
forall info o b.
(AttrInfo info, AttrBaseTypeConstraint info o,
AttrSetTypeConstraint info b) =>
o -> b -> IO ()
attrSet @(ResolveAttribute label o) o
obj
app ((AttrLabelProxy attr
_attr :: AttrLabelProxy label) :&= b
x) =
Proxy o -> b -> IO (AttrTransferType (ResolveAttribute attr o))
forall info o b.
(AttrInfo info, AttrBaseTypeConstraint info o,
AttrTransferTypeConstraint info b) =>
Proxy o -> b -> IO (AttrTransferType info)
attrTransfer @(ResolveAttribute label o) (Proxy o
forall k (t :: k). Proxy t
Proxy @o) b
x IO (AttrTransferType info)
-> (AttrTransferType info -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
o -> AttrTransferType info -> IO ()
forall info o b.
(AttrInfo info, AttrBaseTypeConstraint info o,
AttrSetTypeConstraint info b) =>
o -> b -> IO ()
attrSet @(ResolveAttribute label o) o
obj
type AttrGetC info obj attr result = (HasAttributeList obj,
info ~ ResolveAttribute attr obj,
AttrInfo info,
(AttrBaseTypeConstraint info) obj,
AttrOpAllowed 'AttrGet info obj,
result ~ AttrGetType info)
get :: forall info attr obj result m.
(AttrGetC info obj attr result, MonadIO m) =>
obj -> AttrLabelProxy (attr :: Symbol) -> m result
get :: obj -> AttrLabelProxy attr -> m result
get obj
o AttrLabelProxy attr
_ = IO result -> m result
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO result -> m result) -> IO result -> m result
forall a b. (a -> b) -> a -> b
$ obj -> IO (AttrGetType info)
forall info o.
(AttrInfo info, AttrBaseTypeConstraint info o) =>
o -> IO (AttrGetType info)
attrGet @info obj
o
type AttrClearC info obj attr = (HasAttributeList obj,
info ~ ResolveAttribute attr obj,
AttrInfo info,
(AttrBaseTypeConstraint info) obj,
AttrOpAllowed 'AttrClear info obj)
clear :: forall info attr obj m.
(AttrClearC info obj attr, MonadIO m) =>
obj -> AttrLabelProxy (attr :: Symbol) -> m ()
clear :: obj -> AttrLabelProxy attr -> m ()
clear obj
o AttrLabelProxy attr
_ = IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ obj -> IO ()
forall info o.
(AttrInfo info, AttrBaseTypeConstraint info o) =>
o -> IO ()
attrClear @info obj
o