{-# LANGUAGE CPP #-}
-- Copyright 2019 Google LLC
--
-- Use of this source code is governed by a BSD-style
-- license that can be found in the LICENSE file or at
-- https://developers.google.com/open-source/licenses/bsd

-- | This module provides combinators for constructing Haskell types.
module GHC.SourceGen.Type
    ( HsType'
    , tyPromotedVar
    , stringTy
    , numTy
    , listTy
    , listPromotedTy
    , tuplePromotedTy
    , (-->)
    , forall'
    , HsTyVarBndr'
    , (==>)
    , kindedVar
    ) where

import Data.String (fromString)
#if MIN_VERSION_ghc(9,0,0)
import GHC.Hs.Type
import GHC.Parser.Annotation
#else
import GHC.Hs.Type
#endif

#if MIN_VERSION_ghc(9,4,0)
import Language.Haskell.Syntax.Extension
#endif

import GHC.SourceGen.Syntax.Internal
import GHC.SourceGen.Lit.Internal (noSourceText)
import GHC.SourceGen.Name.Internal
import GHC.SourceGen.Type.Internal

-- | A promoted name, for example from the @DataKinds@ extension.
tyPromotedVar :: RdrNameStr -> HsType'
tyPromotedVar :: RdrNameStr -> HsType'
tyPromotedVar = (EpAnn [AddEpAnn] -> PromotionFlag -> LocatedN RdrName -> HsType')
-> PromotionFlag -> LocatedN RdrName -> HsType'
forall ann a. (EpAnn ann -> a) -> a
withEpAnnNotUsed XTyVar GhcPs -> PromotionFlag -> LIdP GhcPs -> HsType'
EpAnn [AddEpAnn] -> PromotionFlag -> LocatedN RdrName -> HsType'
forall pass.
XTyVar pass -> PromotionFlag -> LIdP pass -> HsType pass
HsTyVar PromotionFlag
promoted (LocatedN RdrName -> HsType')
-> (RdrNameStr -> LocatedN RdrName) -> RdrNameStr -> HsType'
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RdrNameStr -> LocatedN RdrName
typeRdrName

stringTy :: String -> HsType'
stringTy :: String -> HsType'
stringTy = (NoExtField -> HsTyLit GhcPs -> HsType')
-> HsTyLit GhcPs -> HsType'
forall a. (NoExtField -> a) -> a
noExt XTyLit GhcPs -> HsTyLit GhcPs -> HsType'
NoExtField -> HsTyLit GhcPs -> HsType'
forall pass. XTyLit pass -> HsTyLit pass -> HsType pass
HsTyLit (HsTyLit GhcPs -> HsType')
-> (String -> HsTyLit GhcPs) -> String -> HsType'
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SourceText -> FastString -> HsTyLit GhcPs)
-> FastString -> HsTyLit GhcPs
forall a. (SourceText -> a) -> a
noSourceText XStrTy GhcPs -> FastString -> HsTyLit GhcPs
SourceText -> FastString -> HsTyLit GhcPs
forall pass. XStrTy pass -> FastString -> HsTyLit pass
HsStrTy (FastString -> HsTyLit GhcPs)
-> (String -> FastString) -> String -> HsTyLit GhcPs
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> FastString
forall a. IsString a => String -> a
fromString

numTy :: Integer -> HsType'
numTy :: Integer -> HsType'
numTy = (NoExtField -> HsTyLit GhcPs -> HsType')
-> HsTyLit GhcPs -> HsType'
forall a. (NoExtField -> a) -> a
noExt XTyLit GhcPs -> HsTyLit GhcPs -> HsType'
NoExtField -> HsTyLit GhcPs -> HsType'
forall pass. XTyLit pass -> HsTyLit pass -> HsType pass
HsTyLit (HsTyLit GhcPs -> HsType')
-> (Integer -> HsTyLit GhcPs) -> Integer -> HsType'
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SourceText -> Integer -> HsTyLit GhcPs)
-> Integer -> HsTyLit GhcPs
forall a. (SourceText -> a) -> a
noSourceText XNumTy GhcPs -> Integer -> HsTyLit GhcPs
SourceText -> Integer -> HsTyLit GhcPs
forall pass. XNumTy pass -> Integer -> HsTyLit pass
HsNumTy

listTy :: HsType' -> HsType'
listTy :: HsType' -> HsType'
listTy = (EpAnn AnnParen
 -> GenLocated (SrcSpanAnn AnnListItem) HsType' -> HsType')
-> GenLocated (SrcSpanAnn AnnListItem) HsType' -> HsType'
forall ann a. (EpAnn ann -> a) -> a
withEpAnnNotUsed XListTy GhcPs -> LHsType GhcPs -> HsType'
EpAnn AnnParen
-> GenLocated (SrcSpanAnn AnnListItem) HsType' -> HsType'
forall pass. XListTy pass -> LHsType pass -> HsType pass
HsListTy (GenLocated (SrcSpanAnn AnnListItem) HsType' -> HsType')
-> (HsType' -> GenLocated (SrcSpanAnn AnnListItem) HsType')
-> HsType'
-> HsType'
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HsType' -> GenLocated (SrcSpanAnn AnnListItem) HsType'
forall a ann. a -> GenLocated (SrcSpanAnn ann) a
mkLocated

listPromotedTy :: [HsType'] -> HsType'
-- Lists of two or more elements don't need the explicit tick (`'`).
-- But for consistency, just always add it.
listPromotedTy :: [HsType'] -> HsType'
listPromotedTy = ([GenLocated (SrcSpanAnn AnnListItem) HsType'] -> HsType')
-> [GenLocated (SrcSpanAnn AnnListItem) HsType'] -> HsType'
forall a. a -> a
withPlaceHolder ((EpAnn [AddEpAnn]
 -> PromotionFlag
 -> [GenLocated (SrcSpanAnn AnnListItem) HsType']
 -> HsType')
-> PromotionFlag
-> [GenLocated (SrcSpanAnn AnnListItem) HsType']
-> HsType'
forall ann a. (EpAnn ann -> a) -> a
withEpAnnNotUsed XExplicitListTy GhcPs
-> PromotionFlag -> [LHsType GhcPs] -> HsType'
EpAnn [AddEpAnn]
-> PromotionFlag
-> [GenLocated (SrcSpanAnn AnnListItem) HsType']
-> HsType'
forall pass.
XExplicitListTy pass
-> PromotionFlag -> [LHsType pass] -> HsType pass
HsExplicitListTy PromotionFlag
promoted) ([GenLocated (SrcSpanAnn AnnListItem) HsType'] -> HsType')
-> ([HsType'] -> [GenLocated (SrcSpanAnn AnnListItem) HsType'])
-> [HsType']
-> HsType'
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (HsType' -> GenLocated (SrcSpanAnn AnnListItem) HsType')
-> [HsType'] -> [GenLocated (SrcSpanAnn AnnListItem) HsType']
forall a b. (a -> b) -> [a] -> [b]
map HsType' -> GenLocated (SrcSpanAnn AnnListItem) HsType'
forall a ann. a -> GenLocated (SrcSpanAnn ann) a
mkLocated

tuplePromotedTy :: [HsType'] -> HsType'
tuplePromotedTy :: [HsType'] -> HsType'
tuplePromotedTy = ([GenLocated (SrcSpanAnn AnnListItem) HsType'] -> HsType')
-> [GenLocated (SrcSpanAnn AnnListItem) HsType'] -> HsType'
forall a. a -> a
withPlaceHolders ((EpAnn [AddEpAnn]
 -> [GenLocated (SrcSpanAnn AnnListItem) HsType'] -> HsType')
-> [GenLocated (SrcSpanAnn AnnListItem) HsType'] -> HsType'
forall ann a. (EpAnn ann -> a) -> a
withEpAnnNotUsed XExplicitTupleTy GhcPs -> [LHsType GhcPs] -> HsType'
EpAnn [AddEpAnn]
-> [GenLocated (SrcSpanAnn AnnListItem) HsType'] -> HsType'
forall pass. XExplicitTupleTy pass -> [LHsType pass] -> HsType pass
HsExplicitTupleTy) ([GenLocated (SrcSpanAnn AnnListItem) HsType'] -> HsType')
-> ([HsType'] -> [GenLocated (SrcSpanAnn AnnListItem) HsType'])
-> [HsType']
-> HsType'
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (HsType' -> GenLocated (SrcSpanAnn AnnListItem) HsType')
-> [HsType'] -> [GenLocated (SrcSpanAnn AnnListItem) HsType']
forall a b. (a -> b) -> [a] -> [b]
map HsType' -> GenLocated (SrcSpanAnn AnnListItem) HsType'
forall a ann. a -> GenLocated (SrcSpanAnn ann) a
mkLocated

-- | A function type.
--
-- > a -> b
-- > =====
-- > var "a" --> var "b"
(-->) :: HsType' -> HsType' -> HsType'
HsType'
a --> :: HsType' -> HsType' -> HsType'
--> HsType'
b = (EpAnn NoEpAnns
 -> HsArrow GhcPs
 -> GenLocated (SrcSpanAnn AnnListItem) HsType'
 -> GenLocated (SrcSpanAnn AnnListItem) HsType'
 -> HsType')
-> HsArrow GhcPs
-> GenLocated (SrcSpanAnn AnnListItem) HsType'
-> GenLocated (SrcSpanAnn AnnListItem) HsType'
-> HsType'
forall ann a. (EpAnn ann -> a) -> a
withEpAnnNotUsed XFunTy GhcPs
-> HsArrow GhcPs -> LHsType GhcPs -> LHsType GhcPs -> HsType'
EpAnn NoEpAnns
-> HsArrow GhcPs
-> GenLocated (SrcSpanAnn AnnListItem) HsType'
-> GenLocated (SrcSpanAnn AnnListItem) HsType'
-> HsType'
forall pass.
XFunTy pass
-> HsArrow pass -> LHsType pass -> LHsType pass -> HsType pass
HsFunTy
#if MIN_VERSION_ghc(9,4,0)
         (LHsUniToken "->" "\8594" GhcPs -> HsArrow GhcPs
forall pass. LHsUniToken "->" "\8594" pass -> HsArrow pass
HsUnrestrictedArrow LHsUniToken "->" "\8594" GhcPs
GenLocated TokenLocation (HsUniToken "->" "\8594")
forall (t :: Symbol) (u :: Symbol).
GenLocated TokenLocation (HsUniToken t u)
mkUniToken)
#elif MIN_VERSION_ghc(9,0,0)
         (HsUnrestrictedArrow NormalSyntax)
#endif
         (LHsType GhcPs -> LHsType GhcPs
parenthesizeTypeForFun (LHsType GhcPs -> LHsType GhcPs) -> LHsType GhcPs -> LHsType GhcPs
forall a b. (a -> b) -> a -> b
$ HsType' -> GenLocated (SrcSpanAnn AnnListItem) HsType'
forall a ann. a -> GenLocated (SrcSpanAnn ann) a
mkLocated HsType'
a) (HsType' -> GenLocated (SrcSpanAnn AnnListItem) HsType'
forall a ann. a -> GenLocated (SrcSpanAnn ann) a
mkLocated HsType'
b)

infixr 0 -->

-- | A type variable binding.
--
-- > forall a . T a
-- > =====
-- > forall' [bvar "a"] $ var "T" @@ var "a"
forall' :: [HsTyVarBndrS'] -> HsType' -> HsType'
forall' :: [HsTyVarBndrS'] -> HsType' -> HsType'
forall' [HsTyVarBndrS']
ts = (NoExtField
 -> [GenLocated (SrcSpanAnn AnnListItem) HsTyVarBndrS']
 -> GenLocated (SrcSpanAnn AnnListItem) HsType'
 -> HsType')
-> [GenLocated (SrcSpanAnn AnnListItem) HsTyVarBndrS']
-> GenLocated (SrcSpanAnn AnnListItem) HsType'
-> HsType'
forall a. (NoExtField -> a) -> a
noExt NoExtField
-> [GenLocated (SrcSpanAnn AnnListItem) HsTyVarBndrS']
-> GenLocated (SrcSpanAnn AnnListItem) HsType'
-> HsType'
forall {p :: Pass}.
NoExtField
-> [GenLocated
      (SrcSpanAnn AnnListItem) (HsTyVarBndr Specificity (GhcPass p))]
-> GenLocated (SrcSpanAnn AnnListItem) (HsType (GhcPass p))
-> HsType (GhcPass p)
hsForAllTy ((HsTyVarBndrS'
 -> GenLocated (SrcSpanAnn AnnListItem) HsTyVarBndrS')
-> [HsTyVarBndrS']
-> [GenLocated (SrcSpanAnn AnnListItem) HsTyVarBndrS']
forall a b. (a -> b) -> [a] -> [b]
map HsTyVarBndrS' -> GenLocated (SrcSpanAnn AnnListItem) HsTyVarBndrS'
forall a ann. a -> GenLocated (SrcSpanAnn ann) a
mkLocated [HsTyVarBndrS']
ts) (GenLocated (SrcSpanAnn AnnListItem) HsType' -> HsType')
-> (HsType' -> GenLocated (SrcSpanAnn AnnListItem) HsType')
-> HsType'
-> HsType'
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HsType' -> GenLocated (SrcSpanAnn AnnListItem) HsType'
forall a ann. a -> GenLocated (SrcSpanAnn ann) a
mkLocated
  where
#if MIN_VERSION_ghc(9,2,0)
    hsForAllTy :: NoExtField
-> [GenLocated
      (SrcSpanAnn AnnListItem) (HsTyVarBndr Specificity (GhcPass p))]
-> GenLocated (SrcSpanAnn AnnListItem) (HsType (GhcPass p))
-> HsType (GhcPass p)
hsForAllTy NoExtField
x = XForAllTy (GhcPass p)
-> HsForAllTelescope (GhcPass p)
-> LHsType (GhcPass p)
-> HsType (GhcPass p)
forall pass.
XForAllTy pass
-> HsForAllTelescope pass -> LHsType pass -> HsType pass
HsForAllTy XForAllTy (GhcPass p)
NoExtField
x (HsForAllTelescope (GhcPass p)
 -> GenLocated (SrcSpanAnn AnnListItem) (HsType (GhcPass p))
 -> HsType (GhcPass p))
-> ([GenLocated
       (SrcSpanAnn AnnListItem) (HsTyVarBndr Specificity (GhcPass p))]
    -> HsForAllTelescope (GhcPass p))
-> [GenLocated
      (SrcSpanAnn AnnListItem) (HsTyVarBndr Specificity (GhcPass p))]
-> GenLocated (SrcSpanAnn AnnListItem) (HsType (GhcPass p))
-> HsType (GhcPass p)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (EpAnn (AddEpAnn, AddEpAnn)
 -> [GenLocated
       (SrcSpanAnn AnnListItem) (HsTyVarBndr Specificity (GhcPass p))]
 -> HsForAllTelescope (GhcPass p))
-> [GenLocated
      (SrcSpanAnn AnnListItem) (HsTyVarBndr Specificity (GhcPass p))]
-> HsForAllTelescope (GhcPass p)
forall ann a. (EpAnn ann -> a) -> a
withEpAnnNotUsed EpAnn (AddEpAnn, AddEpAnn)
-> [LHsTyVarBndr Specificity (GhcPass p)]
-> HsForAllTelescope (GhcPass p)
EpAnn (AddEpAnn, AddEpAnn)
-> [GenLocated
      (SrcSpanAnn AnnListItem) (HsTyVarBndr Specificity (GhcPass p))]
-> HsForAllTelescope (GhcPass p)
forall (p :: Pass).
EpAnn (AddEpAnn, AddEpAnn)
-> [LHsTyVarBndr Specificity (GhcPass p)]
-> HsForAllTelescope (GhcPass p)
mkHsForAllInvisTele
#elif MIN_VERSION_ghc(9,0,0)
    hsForAllTy x = HsForAllTy x . mkHsForAllInvisTele
#elif MIN_VERSION_ghc(8,10,0)
    fvf = ForallInvis -- "Invisible" forall, i.e., with a dot
    hsForAllTy x = HsForAllTy x fvf
#else
    hsForAllTy = HsForAllTy
#endif

-- | Qualify a type with constraints.
--
-- > (F x, G x) => x
-- > =====
-- > [var "F" @@ var "x", var "G" @@ var "x"] ==> var "x"
(==>) :: [HsType'] -> HsType' -> HsType'
==> :: [HsType'] -> HsType' -> HsType'
(==>) [HsType']
cs = XRec GhcPs [LHsType GhcPs] -> LHsType GhcPs -> HsType'
hsQualTy ([GenLocated (SrcSpanAnn AnnListItem) HsType']
-> GenLocated
     (SrcSpanAnn AnnContext)
     [GenLocated (SrcSpanAnn AnnListItem) HsType']
forall a ann. a -> GenLocated (SrcSpanAnn ann) a
mkLocated ((HsType' -> GenLocated (SrcSpanAnn AnnListItem) HsType')
-> [HsType'] -> [GenLocated (SrcSpanAnn AnnListItem) HsType']
forall a b. (a -> b) -> [a] -> [b]
map HsType' -> GenLocated (SrcSpanAnn AnnListItem) HsType'
forall a ann. a -> GenLocated (SrcSpanAnn ann) a
mkLocated [HsType']
cs)) (GenLocated (SrcSpanAnn AnnListItem) HsType' -> HsType')
-> (HsType' -> GenLocated (SrcSpanAnn AnnListItem) HsType')
-> HsType'
-> HsType'
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HsType' -> GenLocated (SrcSpanAnn AnnListItem) HsType'
forall a ann. a -> GenLocated (SrcSpanAnn ann) a
mkLocated
  where
#if MIN_VERSION_ghc(9,4,0)
    hsQualTy :: XRec GhcPs [LHsType GhcPs] -> LHsType GhcPs -> HsType'
hsQualTy = (NoExtField
 -> XRec GhcPs [LHsType GhcPs] -> LHsType GhcPs -> HsType')
-> XRec GhcPs [LHsType GhcPs] -> LHsType GhcPs -> HsType'
forall a. (NoExtField -> a) -> a
noExt XQualTy GhcPs
-> XRec GhcPs [LHsType GhcPs] -> LHsType GhcPs -> HsType'
NoExtField
-> XRec GhcPs [LHsType GhcPs] -> LHsType GhcPs -> HsType'
forall pass.
XQualTy pass -> LHsContext pass -> LHsType pass -> HsType pass
HsQualTy 
#elif MIN_VERSION_ghc(9,2,0)
    hsQualTy = noExt HsQualTy . Just
#else
    hsQualTy = noExt HsQualTy
#endif

infixr 0 ==>

-- | A type variable with a kind signature.
--
-- > x :: A
-- > =====
-- > kindedVar "x" (var "A")
kindedVar :: OccNameStr -> HsType' -> HsTyVarBndr'
kindedVar :: OccNameStr -> HsType' -> HsTyVarBndr'
kindedVar OccNameStr
v HsType'
t = (EpAnn [AddEpAnn]
 -> ()
 -> LocatedN RdrName
 -> GenLocated (SrcSpanAnn AnnListItem) HsType'
 -> HsTyVarBndr')
-> ()
-> LocatedN RdrName
-> GenLocated (SrcSpanAnn AnnListItem) HsType'
-> HsTyVarBndr'
forall ann a. (EpAnn ann -> a) -> a
withEpAnnNotUsed XKindedTyVar GhcPs
-> () -> LIdP GhcPs -> LHsType GhcPs -> HsTyVarBndr'
EpAnn [AddEpAnn]
-> ()
-> LocatedN RdrName
-> GenLocated (SrcSpanAnn AnnListItem) HsType'
-> HsTyVarBndr'
forall flag pass.
XKindedTyVar pass
-> flag -> LIdP pass -> LHsKind pass -> HsTyVarBndr flag pass
KindedTyVar
#if MIN_VERSION_ghc(9,0,0)
                ()
#endif
                (RdrNameStr -> LocatedN RdrName
typeRdrName (RdrNameStr -> LocatedN RdrName) -> RdrNameStr -> LocatedN RdrName
forall a b. (a -> b) -> a -> b
$ OccNameStr -> RdrNameStr
UnqualStr OccNameStr
v) (HsType' -> GenLocated (SrcSpanAnn AnnListItem) HsType'
forall a ann. a -> GenLocated (SrcSpanAnn ann) a
mkLocated HsType'
t)