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"