packages feed

inch-0.1.0: src/Language/Inch/Check.lhs

> {-# LANGUAGE FlexibleContexts #-}

> module Language.Inch.Check where

> import Prelude hiding (all)
> import Control.Applicative
> import Control.Monad
> import Data.Monoid
> import Data.Foldable
> import Control.Monad.State

> import Language.Inch.BwdFwd
> import Language.Inch.Context
> import Language.Inch.Error
> import Language.Inch.Kit
> import Language.Inch.Kind hiding (All)
> import Language.Inch.Type
> import Language.Inch.PrettyPrinter
> import Language.Inch.Syntax


Set this to True in order to verify the context regularly:

> paranoid :: Bool
> paranoid = False

> traceContext :: MonadState ZipState m => String -> m ()
> traceContext s = getContext >>= \ g -> mtrace (s ++ "\n" ++ renderMe g)

> defines :: Context -> Var () k -> Bool
> defines B0                 _            = False
> defines (_ :< A (b := _))  a | a =?= b  = True
> defines (g :< _)           a            = defines g a

> goodCx :: Context -> Bool
> goodCx B0 = True
> goodCx (g :< e) = goodEntry g e && goodCx g

> goodEntry :: Context -> Entry -> Bool
> goodEntry g (A (a := d))      = not (g `defines` a) && goodTyDef g d
> goodEntry g (Constraint _ p)  = goodTy g p
> goodEntry g (Layer l _)       = goodLayer g l

> goodTyDef :: Context -> TyDef k -> Bool
> goodTyDef g (Some t)  = goodTy g t
> goodTyDef _ Hole      = True
> goodTyDef _ Fixed     = True
> goodTyDef _ Exists    = True

> goodFV :: FV t () => Context -> t -> Bool
> goodFV g = getAll . fvFoldMap (All . defines g)

> goodLayer :: Context -> TmLayer -> Bool
> goodLayer g (PatternTop (_ ::: s))  = goodTy g s
> goodLayer _ CaseTop                 = True
> goodLayer _ FunTop                  = True
> goodLayer _ GenMark                 = True
> goodLayer _ GuardTop                = True
> goodLayer g (LamBody (_ ::: t))     = goodTy g t
> goodLayer g (LetBindings bs)        = goodBindings g bs
> goodLayer g (LetBody bs)            = goodBindings g bs

> goodBindings :: Context -> Bindings -> Bool
> goodBindings g = all (maybe True (goodTy g) . fst)


> goodTy :: Context -> Type k -> Bool
> goodTy = goodFV

> goodDecl :: Context -> Declaration () -> Bool
> goodDecl g (SigDecl _ t)        = goodTy g t
> goodDecl _ (FunDecl _ _)        = True


> verifyContext :: Bool -> String -> Contextual ()
> verifyContext before s | paranoid = do
>     g <- getContext
>     unless (goodCx g) $ do
>         traceContext $ "verifyContext: failed " ++ (if before then "before " else "after ") ++ s
>         erk "Game over."
>     return ()
> verifyContext _ _ = return ()

> wrapVerify :: String -> Contextual t -> Contextual t
> wrapVerify s m = verifyContext True s *> m <* verifyContext False s



> assertContextEmpty :: Contextual ()
> assertContextEmpty = do
>     g <- getContext
>     case g of
>         B0  -> return ()
>         _   -> traceContext "assertContextEmpty" >> erk "Error: context is not empty"