1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
|
-- | An abstraction for representing type constructors. This is a very
-- simplified version of `Data.Typeable`, which we don't use directly
-- to avoid compatibility headaches.
module Data.GI.CodeGen.Type
( Type(..) -- Reexported for convenience.
, BasicType(..)
, TypeRep
, con
, con0
, typeShow
, typeConName
, io
, ptr
, funptr
, maybeT
) where
#if !MIN_VERSION_base(4,11,0)
import Data.Monoid ((<>))
#endif
import qualified Data.Text as T
import Data.Text (Text)
import Data.GI.GIR.BasicTypes (Type(..), BasicType(..))
-- | A fully applied type.
data TypeRep = TypeRep { typeCon :: TypeCon
, typeConArgs :: [TypeRep]
} deriving (Eq)
-- | A type constructor. We single out some specific constructors
-- since they have special syntax in their Haskell representation.
data TypeCon = TupleCon
| ListCon
| TextualCon Text
deriving (Eq)
-- | Give a valid Haskell source representation of the given
-- `TypeRep`.
typeShow :: TypeRep -> Text
typeShow (TypeRep TupleCon args) =
"(" <> T.intercalate ", " (map typeShow args) <> ")"
typeShow (TypeRep ListCon args) =
"[" <> T.intercalate ", " (map typeShow args) <> "]"
typeShow (TypeRep (TextualCon con) args) =
T.intercalate " " (con : map (parenthesize . typeShow) args)
where parenthesize :: Text -> Text
parenthesize s = if T.any (== ' ') s
then "(" <> s <> ")"
else s
-- | Return a textual representation of the type constructor for the
-- given `TypeRep`.
typeConName :: TypeRep -> Text
typeConName (TypeRep TupleCon _) = "(,)"
typeConName (TypeRep ListCon _) = "[,]"
typeConName (TypeRep (TextualCon s) _) = s
-- | Type constructor applied to the given types.
con :: Text -> [TypeRep] -> TypeRep
con "[]" xs = TypeRep {typeCon = ListCon, typeConArgs = xs }
con "(,)" xs = TypeRep {typeCon = TupleCon, typeConArgs = xs }
con s xs = TypeRep {typeCon = TextualCon s, typeConArgs = xs}
-- | A shorthand for a type constructor taking no arguments.
con0 :: Text -> TypeRep
con0 c = con c []
-- | Embed in the `IO` monad.
io :: TypeRep -> TypeRep
io t = "IO" `con` [t]
-- | A `Ptr` to the type.
ptr :: TypeRep -> TypeRep
ptr t = "Ptr" `con` [t]
-- | A `FunPtr` to the type.
funptr :: TypeRep -> TypeRep
funptr t = "FunPtr" `con` [t]
-- | Embed in the `Maybe` monad.
maybeT :: TypeRep -> TypeRep
maybeT t = "Maybe" `con` [t]
|