packages feed

ddc-source-tetra-0.4.3.1: DDC/Source/Tetra/Parser/Type.hs

{-# LANGUAGE TypeFamilies #-}
module DDC.Source.Tetra.Parser.Type
        ( pBind
        , pType
        , pTypeUnion
        , pTypeApp
        , pTypeAtomSP
        , pTyConSP
        , pTyConBound)
where
import DDC.Source.Tetra.Parser.Base     as S
import DDC.Source.Tetra.Exp.Source      as S
import DDC.Source.Tetra.Prim.TyConTetra as S
import DDC.Core.Lexer.Tokens            as K
import qualified DDC.Source.Tetra.Lexer as SL

import qualified DDC.Core.Tetra         as C
import qualified DDC.Control.Parser     as P
import qualified Data.Text              as T


-- | Parse a binder.
pBind :: Parser Bind
pBind
 = P.choice
        -- Named binders.
        [ do    (b, _)  <- pBindNameSP
                return  $  b
                
        -- Anonymous binders.
        , do    pSym SHat
                return  $  BAnon 
        
        -- Vacant binders.
        , do    pSym SUnderscore
                return  $  BNone ]
 <?> "a binder"


-- | Parse a type.
pType :: Parser Type
pType = pTypeUnion


-- | Parse a type union.
pTypeUnion :: Parser Type
pTypeUnion
 = do   t1      <- pTypeForall
        P.choice 
         [ -- Type sums.
           -- T2 + T3
           do   sp      <- pTokSP (KOp "+")
                t2      <- pTypeUnion
                return  $  TAnnot sp $ TUnion KEffect t1 t2

         , do   return t1 ]
 <?> "a type"


-- | Parse a quantified type.
pTypeForall :: Parser Type
pTypeForall
 = P.choice
         [ -- Universal quantification.
           -- [v1 v1 ... vn : T1]. T2
           do   pSym SSquareBra
                bs      <- P.many1 pBind
                sp      <- pTokSP (KOp ":")
                kBind   <- pTypeUnion
                pSym SSquareKet
                pSym SDot

                tBody   <- pTypeForall
                return  $ foldr (\b t   -> TAnnot sp 
                                        $  TApp (TCon (TyConForall kBind)) 
                                                (TAbs b kBind t)) 
                                tBody bs

           -- Body type
         , do   pTypeFun
         ]
 <?> "a type"


-- | Parse a function type.
pTypeFun :: Parser Type
pTypeFun
 = do   t1      <- pTypeApp
        P.choice 
         [ -- T1 ~> T2
           do   sp      <- pSym SArrowTilde
                t2      <- pTypeForall
                return  $  TAnnot sp $ TFun t1 t2

           -- T1 => T2
         , do   sp      <- pSym SArrowEquals
                t2      <- pTypeForall
                return  $  TAnnot sp $ TImpl t1 t2

           -- T1 -> T2
         , do   sp      <- pSym SArrowDashRight
                t2      <- pTypeForall
                return  $  TAnnot sp $ TFun  t1 t2

           -- Body type
         , do   return t1 
         ]
 <?> "an atomic type or type application"


-- | Parse a type application.
pTypeApp :: Parser Type
pTypeApp
 = do   ((t, _):ts)  <- P.many1 pTypeAtomSP
        return  $  foldl (\t1 (t2, sp) -> TAnnot sp (TApp t1 t2)) t ts
 <?> "an atomic type or type application"


-- | Parse a variable, constructor or parenthesised type.
pTypeAtomSP :: Parser (Type, SourcePos)
pTypeAtomSP
 = P.choice
        -- (~>) and (=>) and (->) and (TYPE2)
        [ -- (~>)
          do    sp      <- pTokSP $ KOpVar "~>"
                return  (TAnnot sp $ TCon  TyConFun,  sp)

          -- (=>)
        , do    sp      <- pTokSP $ KOpVar "=>"
                return  (TAnnot sp $ TCon (TyConPrim (PrimTypeTwCon TwConImpl)), sp)

          -- (->)
        , do    sp      <- pTokSP $ KOpVar "->"
                return  (TAnnot sp $ TCon TyConFun,  sp)

          -- (TYPE2)
        , do    sp      <- pSym SRoundBra
                t       <- pTypeUnion
                pSym SRoundKet
                return  (t, sp)

        -- Named type constructors
        , do    (tc, sp) <- pTyConSP 
                return  (TAnnot sp $ TCon tc, sp)
            
        -- Bottoms.
        , do    sp       <- pTokSP (KBuiltin BPure)
                return  (TAnnot sp $ TBot KEffect, sp)

        -- Bound occurrence of a variable.
        --  We don't know the kind of this variable yet, so fill in the
        --  field with the bottom element of computation kinds. This isn't
        --  really part of the language, but makes sense implentation-wise.
        , do    (u, sp) <- pBoundNameSP
                return  (TAnnot sp $ TVar u, sp)

        , do    (u, sp) <- pBoundIxSP
                return  (TAnnot sp $ TVar u, sp)
        ]
 <?> "an atomic type"


-- | Parse a type constructor.
pTyConSP :: Parser (TyCon, SourcePos)
pTyConSP  =   P.pTokMaybeSP f <?> "a type constructor"
 where f kk
        = case kk of
                -- Primitive Ambient TyCons.
                KA (KBuiltin (BSoCon c))
                 -> Just $ TyConPrim $ PrimTypeSoCon c

                KA (KBuiltin (BKiCon c))
                 -> Just $ TyConPrim $ PrimTypeKiCon c

                KA (KBuiltin (BTwCon c))
                 -> Just $ TyConPrim $ PrimTypeTwCon c

                KA (KBuiltin (BTcCon c))
                 -> Just $ TyConPrim $ PrimTypeTcCon c

                -- Primitive TyCons.
                KN (KCon (SL.NamePrimType tc))
                 -> Just $ TyConPrim tc

                -- User Bound TyCons.
                KN (KCon (SL.NameCon tx))
                 -> Just (TyConBound (TyConBoundName tx))

                _ -> Nothing


-- | Parse a bound type constructor.
--   Known primitive type constructors do not match.
pTyConBound :: Parser TyCon
pTyConBound  
        =   P.pTokMaybe f <?> "a bound type constructor"
 where  
        f :: Token SL.Name -> Maybe TyCon
        f (KN (KCon (SL.NameCon tx)))
         |  Nothing <- C.readPrimTyCon      (T.unpack tx)
         ,  Nothing <- S.readPrimTyConTetra (T.unpack tx)
         = Just (TyConBound (TyConBoundName tx))

        f _ = Nothing