inch-0.1.0: src/Language/Inch/Erase.lhs
> {-# LANGUAGE TypeOperators, MultiParamTypeClasses, TypeSynonymInstances,
> GADTs, TypeFamilies, UndecidableInstances, ImpredicativeTypes,
> TupleSections #-}
> module Language.Inch.Erase where
> import Control.Applicative hiding (Alternative)
> import Data.Traversable
> import Text.PrettyPrint.HughesPJ
> import Language.Inch.Error
> import Language.Inch.Kit
> import Language.Inch.Kind
> import Language.Inch.Type
> import Language.Inch.Syntax
> import Language.Inch.ModuleSyntax
> import Language.Inch.Context
> import Language.Inch.PrettyPrinter
> eraseKind :: Kind k -> Maybe (Ex Kind)
> eraseKind KSet = Just $ Ex KSet
> eraseKind KNum = Nothing
> eraseKind KConstraint = Just $ Ex KConstraint
> eraseKind (k :-> l) =
> case (eraseKind k, eraseKind l) of
> (_, Nothing) -> Nothing
> (Nothing, Just (Ex l')) -> Just $ Ex l'
> (Just (Ex k'), Just (Ex l')) -> Just $ Ex $ k' :-> l'
> willErase :: Kind k -> Bool
> willErase KSet = False
> willErase KNum = True
> willErase KConstraint = False
> willErase (_ :-> l) = willErase l
> eraseType :: Type k -> Contextual (Maybe TyKind)
> eraseType (TyVar (FVar a k)) = return (eraseKind k >>= \ (Ex l) ->
> Just (TK (TyVar (FVar a l)) l))
> eraseType (TyVar (BVar b)) = impossibleBVar b
> eraseType (TyCon c k) = return (eraseKind k >>= \ (Ex l) ->
> Just (TK (TyCon c l) l))
> eraseType (TySyn x t) = do
> mt <- eraseTypeSyn t
> case mt of
> Nothing -> return Nothing
> Just (Ex t') -> return . Just $ TK (TySyn x t') (getTySynKind t')
> eraseType (TyApp f s) = do
> k :-> _ <- return $ getTyKind f
> mtk <- eraseType f
> if willErase k
> then return mtk
> else case mtk of
> Just (TK f' (k'' :-> l'')) -> do
> Just (TK s' ks) <- eraseType s
> hetEq k'' ks (return (Just (TK (TyApp f' s') l'')))
> (erk "Kind mismatch")
> _ -> return Nothing
> eraseType Arr = return . Just $ TK Arr (KSet :-> KSet :-> KSet)
> eraseType (Bind Pi x KNum t) = do
> Just (TK t' KSet) <- eraseType $ unbindTy (FVar (N x (error "eraseType: erk") (UserVar Pi)) KNum) t
> return . Just $ TK (insertNumArrow t') KSet
> where
> insertNumArrow :: Ty a KSet -> Ty a KSet
> insertNumArrow (Bind All y k t') = Bind All y k (insertNumArrow t')
> insertNumArrow t' = tyInteger --> t'
> eraseType (Bind All x k t) =
> case eraseKind k of
> Just (Ex k') -> do
> an <- fresh SysVar x k Hole
> Just (TK t' l) <- eraseType (unbindTy an t)
> return . Just $ TK (Bind All x k' (bindTy (FVar (varName an) k') t')) l
> Nothing -> eraseType $ unbindTy (FVar (N x (error "eraseType: erk") (UserVar All)) k) t
> eraseType (Qual q t) = do
> q' <- eraseTo KConstraint q
> mtk <- eraseType t
> return $ (\ (TK t' k') -> TK (qual q' t') k') <$> mtk
> where
> qual :: Type KConstraint -> Type k -> Type k
> qual p u | isTrivial p = u
> | otherwise = Qual p u
> eraseType (TyComp _) = return . Just $ TK tyTrivial KConstraint
> eraseType _ = return Nothing
> eraseTypeSyn :: TypeSyn l -> Contextual (Maybe (Ex (TySyn ())))
> eraseTypeSyn (SynTy t) = do
> mtk <- eraseType t
> case mtk of
> Nothing -> return Nothing
> Just (TK t' _) -> return (Just (Ex (SynTy t')))
> eraseTypeSyn (SynAll x k t) = case eraseKind k of
> Nothing -> eraseTypeSyn $ unbindTySyn (FVar (N x (error "eraseTypeSyn: erk") (UserVar All)) k) t
> Just (Ex k') -> do
> a <- fresh SysVar x k Hole
> Just (Ex t') <- eraseTypeSyn (unbindTySyn a t)
> return . Just . Ex $ SynAll x k' (bindTySyn (FVar (varName a) k') t')
> eraseTo :: Kind l -> Type k -> Contextual (Type l)
> eraseTo l t = inLocation (text "when erasing" <+> prettyHigh (fogTy t)
> <+> text "to" <+> prettyHigh (fogKind l)) $ do
> Just (TK t' k') <- eraseType t
> hetEq k' l (return t')
> (errKindMismatch (fogTy t' ::: fogKind k') (fogKind l))
> eraseTm :: Term () -> Contextual (Term ())
> eraseTm (TmVar x) = pure $ TmVar x
> eraseTm (TmCon c) = pure $ TmCon c
> eraseTm (TmInt k) = pure $ TmInt k
> eraseTm (CharLit c) = pure $ CharLit c
> eraseTm (StrLit s) = pure $ StrLit s
> eraseTm (TmApp f s) = TmApp <$> eraseTm f <*> eraseTm s
> eraseTm (TmBrace n) = pure $ numToTm n
> eraseTm (Lam x b) = Lam x <$> eraseTm b
> eraseTm (NumLam n b) = do
> a <- fresh (UserVar Pi) n KNum Hole
> Lam n <$> eraseTm (unbindTm a b)
> eraseTm (Let ds t) = Let <$> traverse eraseDecl ds <*> eraseTm t
> eraseTm (Case t as) = Case <$> eraseTm t <*> traverse eraseCaseAlt as
> eraseTm (t :? ty) = do
> t' <- eraseTm t
> ty' <- eraseTo KSet ty
> return $ t' :? ty'
> numToTm :: Type KNum -> Term ()
> numToTm (TyVar x) = TmVar . fogVar $ x
> numToTm (TyInt i) = TmInt i
> numToTm (TyApp (UnOp o) m) = tmUnOp o (numToTm m)
> numToTm (TyApp (TyApp (BinOp o) m) n) = tmBinOp o (numToTm m) (numToTm n)
> numToTm t = error $ "numToTm: illegal type " ++ show t
> eraseCon :: Constructor -> Contextual Constructor
> eraseCon (c ::: t) = (c :::) <$> eraseTo KSet t
> eraseAlt :: Alternative () -> Contextual (Alternative ())
> eraseAlt (Alt ps gt) = do
> (ps', f) <- erasePatList ps
> gt' <- eraseGuardTerms (renameTypes1 f gt)
> return $ Alt ps' gt'
> eraseCaseAlt :: CaseAlternative () -> Contextual (CaseAlternative ())
> eraseCaseAlt (CaseAlt p gt) = do
> (p', f) <- erasePat p
> gt' <- eraseGuardTerms (renameTypes1 f gt)
> return $ CaseAlt p' gt'
> eraseGuardTerms :: GuardTerms () -> Contextual (GuardTerms ())
> eraseGuardTerms (Unguarded e ds) = Unguarded <$> eraseTm e
> <*> traverse eraseDecl ds
> eraseGuardTerms (Guarded gts ds) = Guarded <$> traverse er gts
> <*> traverse eraseDecl ds
> where er (g :*: t) = (eraseGuard g :*:) <$> eraseTm t
> eraseGuard :: Guard () -> Guard ()
> eraseGuard (NumGuard ps) = ExpGuard (map toTm ps)
> where
> toTm (P c m n) = tmComp c (numToTm m) (numToTm n)
> toTm (_ :=> _) = error "eraseGuard.toTm: implications are not allowed!"
> eraseGuard g = g
> erasePat :: Pattern a b -> Contextual (Pattern () (), forall k . Var b k -> Var a k)
> erasePat (PatVar v) = return (PatVar v, id)
> erasePat (PatCon c ps) = do
> (ps', f) <- erasePatList ps
> return (PatCon c ps', f)
> erasePat PatIgnore = return (PatIgnore, id)
> erasePat (PatBrace a 0) = do
> x <- fresh (UserVar Pi) a KNum Hole
> return (PatVar a, unbindVar (wkClosedVar x))
> erasePat (PatBrace a k) = do
> x <- fresh (UserVar Pi) a KNum Hole
> return (PatNPlusK a k, unbindVar (wkClosedVar x))
> erasePat (PatBraceK k) = return (PatIntLit k, id)
> erasePat (PatIntLit i) = return (PatIntLit i, id)
> erasePat (PatCharLit c) = return (PatCharLit c, id)
> erasePat (PatStrLit s) = return (PatStrLit s, id)
> erasePat (PatNPlusK n k) = return (PatNPlusK n k, id)
> erasePatList :: PatternList a b -> Contextual (PatternList () (), forall k . Var b k -> Var a k)
> erasePatList P0 = return (P0, id)
> erasePatList (p :! ps) = do
> (p', f) <- erasePat p
> (ps', g) <- erasePatList ps
> return (p' :! ps', f . g)
> eraseTopDecl :: TopDeclaration -> Contextual TopDeclaration
> eraseTopDecl (DataDecl s k cs ds) =
> case eraseKind k of
> Just (Ex k') -> do
> cs' <- traverse eraseCon cs
> return $ DataDecl s k' cs' ds
> Nothing -> error $ "eraseTopDecl: failed to erase kind " ++ show k
> eraseTopDecl (TypeDecl x t) = do
> mt <- eraseTypeSyn t
> case mt of
> Nothing -> return $ TypeDecl x (SynTy tyUnit)
> Just (Ex t') -> return $ TypeDecl x t'
> eraseTopDecl (CDecl x d) = CDecl x <$> eraseClassDecl d
> eraseTopDecl (IDecl x d) = IDecl x <$> eraseInstDecl d
> eraseTopDecl (Decl d) = Decl <$> eraseDecl d
> eraseClassDecl :: ClassDeclaration -> Contextual ClassDeclaration
> eraseClassDecl (ClassDecl vs ss ms) = do
> let vs' = filter (\ (VK _ k) -> not (willErase k)) vs
> ss' <- traverse (eraseTo KConstraint) ss
> ms' <- traverse (\ (mn ::: ty) -> (mn :::) <$> eraseTo KSet ty) ms
> return $ ClassDecl vs' ss' ms'
> eraseInstDecl :: InstDeclaration -> Contextual InstDeclaration
> eraseInstDecl (InstDecl ts cs zs) = do
> ts' <- eraseInstTypes ts
> cs' <- filter (not . isTrivial) <$> traverse (eraseTo KConstraint) cs
> zs' <- traverse (\ (n, as) -> (n,) <$> traverse eraseAlt as) zs
> return $ InstDecl ts' cs' zs'
> where
> eraseInstTypes :: [Ex (Ty ())] -> Contextual [Ex (Ty ())]
> eraseInstTypes [] = return []
> eraseInstTypes (Ex t:us) = do
> mtk <- eraseType t
> us' <- eraseInstTypes us
> case mtk of
> Nothing -> return us'
> Just (TK t' _) -> return (Ex t' : us')
> eraseDecl :: Declaration () -> Contextual (Declaration ())
> eraseDecl (FunDecl x ps) =
> FunDecl x <$> traverse eraseAlt ps
> eraseDecl (SigDecl x ty) = SigDecl x <$> eraseTo KSet ty
> eraseModule :: Module -> Contextual Module
> eraseModule (Mod mh is ds) = Mod mh is <$> traverse eraseTopDecl ds