perga/lib/Check.hs

52 lines
1.7 KiB
Haskell
Raw Normal View History

2024-11-17 18:33:14 -08:00
{-# LANGUAGE LambdaCase #-}
module Check (checkType) where
2024-10-05 13:31:09 -07:00
2024-11-17 01:57:53 -08:00
import Control.Monad (unless)
2024-11-14 22:02:04 -08:00
import Control.Monad.Except (MonadError (throwError))
2024-11-17 01:57:53 -08:00
import Control.Monad.Reader
import Data.List ((!?))
2024-11-17 18:33:14 -08:00
import Errors
import Eval (Env, betaEquiv, envLookup, isSort, subst, whnf)
import Expr (Expr (..), incIndices, occursFree)
2024-10-05 13:31:09 -07:00
type Context = [Expr]
2024-11-17 18:33:14 -08:00
matchPi :: Expr -> Expr -> ReaderT Env Result (Expr, Expr)
matchPi x mt =
whnf mt >>= \case
(Pi _ a b) -> pure (a, b)
t -> throwError $ ExpectedPiType x t
2024-11-11 17:57:14 -08:00
2024-11-17 18:33:14 -08:00
findType :: Context -> Expr -> ReaderT Env Result Expr
2024-11-17 01:57:53 -08:00
findType _ Star = pure Square
findType _ Square = throwError SquareUntyped
2024-11-12 00:00:51 -08:00
findType g (Var n x) = do
2024-11-17 01:57:53 -08:00
t <- maybe (throwError $ UnboundVariable x) pure $ g !? fromInteger n
2024-11-17 18:33:14 -08:00
(sSort, s) <- findType g t >>= isSort
unless sSort $ throwError $ NotASort t s
2024-11-11 13:37:44 -08:00
pure t
2024-11-17 18:33:14 -08:00
findType g (Free n) = envLookup n >>= findType g
2024-11-12 00:00:51 -08:00
findType g e@(App m n) = do
(a, b) <- findType g m >>= matchPi m
2024-11-11 13:37:44 -08:00
a' <- findType g n
2024-11-17 18:33:14 -08:00
equiv <- betaEquiv a a'
2024-11-17 01:57:53 -08:00
unless equiv $ throwError $ NotEquivalent a a' e
pure $ subst 0 n b
2024-11-11 17:57:14 -08:00
findType g (Abs x a m) = do
2024-11-17 18:33:14 -08:00
(s1Sort, s1) <- findType g a >>= isSort
unless s1Sort $ throwError $ NotASort a s1
2024-11-11 17:57:14 -08:00
b <- findType (incIndices a : map incIndices g) m
2024-11-17 18:33:14 -08:00
(s2Sort, s2) <- findType g (Pi x a b) >>= isSort
unless s2Sort $ throwError $ NotASort (Pi x a b) s2
2024-11-11 17:57:14 -08:00
pure $ if occursFree 0 b then Pi x a b else Pi "" a b
findType g (Pi _ a b) = do
2024-11-17 18:33:14 -08:00
(s1Sort, s1) <- findType g a >>= isSort
unless s1Sort $ throwError $ NotASort a s1
(s2Sort, s2) <- findType (incIndices a : map incIndices g) b >>= isSort
unless s2Sort $ throwError $ NotASort b s2
2024-11-11 17:57:14 -08:00
pure s2
2024-11-17 01:57:53 -08:00
2024-11-17 18:33:14 -08:00
checkType :: Env -> Expr -> Result Expr
checkType env t = runReaderT (findType [] t) env