alms-0.6.0: src/AST/Type.hs
{-# LANGUAGE TypeFamilies #-}
module AST.Type (
-- * Types
Quant(..), Type'(..), Type, TyPat'(..), TyPat,
-- ** Constructors
tyApp, tyVar, tyFun, tyQu, tyMu, tyRow, tyAnti,
tpVar, tpApp, tpRow, tpAnti,
TyAppN(..),
-- * Built-in types
tyUnit, tyRowEnd, tyVariant, tyRecord, tyRowDots, tyRowMap, tyRowHole,
tyTuple, tyUn, tyAf,
-- ** Type construtor names
tnUnit, tnRowEnd, tnVariant, tnRecord, tnRowDots, tnRowMap, tnRowHole,
tnTuple, tnUn, tnAf,
-- ** Convenience constructors
tyArr, tyLol,
tyAll, tyEx,
tyRecordAdditive, tyRecordMultiplicative,
-- * Miscellany
dumpType
) where
import Util
import Meta.DeriveNotable
import AST.Notable
import AST.Anti
import AST.Kind
import AST.Ident
import qualified Syntax.Strings as Strings
import Prelude ()
import Data.Generics (Typeable, Data)
-- | Type quantifers
data Quant = Forall | Exists | QuantAnti Anti
deriving (Typeable, Data, Eq, Ord)
type Type i = Located Type' i
type TyPat i = Located TyPat' i
-- | Types are parameterized by [@i@], the type of information
-- associated with each tycon
data Type' i
= TyApp (QTypId i) [Type i]
| TyVar (TyVar i)
| TyFun (Type i) (Maybe (QExp i)) (Type i)
| TyQu Quant (TyVar i) (Type i)
| TyMu (TyVar i) (Type i)
| TyRow (Uid i) (Type i) (Type i)
| TyAnti Anti
deriving (Typeable, Data)
-- | Type patterns for defining type operators
data TyPat' i
-- | type variables
= TpVar (TyVar i) Variance
-- | type constructor applications
| TpApp (QTypId i) [TyPat i]
-- | each element of a row
| TpRow (TyVar i) Variance
-- | antiquotes
| TpAnti Anti
deriving (Typeable, Data)
deriveNotable ''Type
deriveNotable ''TyPat
-- | Convenience constructors for qualified types
tyAll, tyEx :: TyVar i -> Type i -> Type i
tyAll = tyQu Forall
tyEx = tyQu Exists
tyArr :: Type i -> Type i -> Type i
tyArr = tyFun <-> Nothing
tyLol :: Type i -> Type i -> Type i
tyLol = tyFun <-> Just maxBound
infixr 8 `tyArr`, `tyLol`
instance Show Quant where
show Forall = Strings.all
show Exists = Strings.ex
show (QuantAnti a) = show a
---
--- Built-in types
---
-- | Names of built-in types
tnUnit, tnRowEnd, tnVariant, tnRecord, tnRowDots, tnRowMap, tnRowHole,
tnTuple, tnUn, tnAf :: String
tnUnit = "INTERNALS.PrimTypes.unit"
tnRowEnd = "INTERNALS.PrimTypes.rowend"
tnVariant = "INTERNALS.PrimTypes.variant"
tnRecord = "INTERNALS.PrimTypes.record"
tnRowDots = "rowdots#"
tnRowMap = "rowmap#"
tnRowHole = "rowhole#"
tnTuple = "INTERNALS.PrimTypes.*"
tnUn = "INTERNALS.PrimTypes.unlimited"
tnAf = "INTERNALS.PrimTypes.affine"
--- Convenience constructors
-- Types
-- | Class defining variadic function 'tyAppN' for constructing
-- type constructor applications.
class TyApp' r i ⇒ TyAppN n r i | r → i where
tyAppN ∷ n → r
instance TyApp' r i ⇒ TyAppN (Path (ModId i) (TypId i)) r i where
tyAppN ql = tyApp' ql []
instance TyApp' r i ⇒ TyAppN (TypId i) r i where
tyAppN l = tyApp' (J [] l) []
instance (Tag i, TyApp' r i) ⇒ TyAppN String r i where
tyAppN s = tyApp' (qident s) []
-- | Helper class for @TyApp'@.
class TyApp' r i | r → i where
tyApp' ∷ QTypId i → [Type i] → r
instance TyApp' (Type i) i where
tyApp' = tyApp
instance (TyApp' r i, a ~ Type i) ⇒ TyApp' (a → r) i where
tyApp' ql ts t = tyApp' ql (ts++[t])
tyUnit :: Tag i => Type i
tyUnit = tyAppN tnUnit
tyRowEnd :: Tag i => Type i
tyRowEnd = tyAppN tnRowEnd
tyVariant :: Tag i => Type i -> Type i
tyVariant = tyAppN tnVariant
tyRecord :: Tag i => Type i -> Type i -> Type i
tyRecord = tyAppN tnRecord
tyRowDots :: Tag i => Type i -> Type i
tyRowDots = tyAppN tnRowDots
tyRowMap :: Tag i => Type i -> Type i -> Type i
tyRowMap = tyAppN tnRowMap
tyRowHole :: Tag i => Type i -> Type i
tyRowHole = tyAppN tnRowHole
tyTuple :: Tag i => Type i -> Type i -> Type i
tyTuple = tyAppN tnTuple
tyUn :: Tag i => Type i
tyUn = tyAppN tnUn
tyAf :: Tag i => Type i
tyAf = tyAppN tnAf
tyRecordAdditive, tyRecordMultiplicative :: Tag i => Type i -> Type i
tyRecordAdditive = tyRecord tyAf
tyRecordMultiplicative = tyRecord tyUn
---
--- Debugging
---
-- | Noisy type printer for debugging
dumpType :: Tag i => Int -> Type i -> IO ()
dumpType i0 nt0 = do
putStr (replicate i0 ' ')
noIndent i0 nt0
where
noIndent i nt@(N _ t0) =
case t0 of
TyApp n ps -> do
putStrLn $ show n ++ " {"
mapM_ (dumpType (i + 2)) ps
putStrLn (replicate i ' ' ++ "}")
TyFun dom mq cod -> do
putStrLn $ case mq of
Just q -> "-[" ++ dumpQExp q ++ "]> {"
Nothing -> "-> {"
dumpType (i + 2) dom
dumpType (i + 2) cod
putStrLn (replicate i ' ' ++ "}")
TyVar tv -> print tv
TyQu u a t -> do
print $ show u ++ " " ++ show a ++ ". {"
dumpType (i + 2) t
putStrLn (replicate i ' ' ++ "}")
TyMu a t -> do
print $ "mu " ++ show a ++ ". {"
dumpType (i + 2) t
putStrLn (replicate i ' ' ++ "}")
TyRow _ _ _ -> do
putStr "ro"
dumpRow (i + 2) 'w' nt
TyAnti a -> do
print a
--
dumpRow i c (N _ (TyRow n t1 t2)) = do
let lab = show n
putStr (c:' ':lab++": ")
noIndent (i + length lab + 4) t1
putStr (replicate i ' ')
dumpRow i '|' t2
dumpRow i c t = do
putStr (c:" ")
noIndent (i + 2) t
--
dumpQExp (N _ q0) = case q0 of
QeLit ql → show ql
QeVar tv → show tv
QeJoin qe1 qe2 → dumpQExp qe1 ++ ',' : dumpQExp qe2
QeAnti _ → "ANTI"