2024-11-11 17:57:14 -08:00
|
|
|
{-# LANGUAGE BangPatterns #-}
|
2024-10-05 13:31:09 -07:00
|
|
|
module Check where
|
|
|
|
|
|
2024-11-11 17:57:14 -08:00
|
|
|
import Control.Monad.Except
|
|
|
|
|
import Data.List (intercalate, (!?))
|
2024-11-11 13:52:50 -08:00
|
|
|
|
2024-11-11 17:57:14 -08:00
|
|
|
import Control.Monad (unless)
|
2024-11-11 13:37:44 -08:00
|
|
|
import Expr
|
2024-11-11 17:57:14 -08:00
|
|
|
import Debug.Trace
|
2024-10-05 13:31:09 -07:00
|
|
|
|
|
|
|
|
type Context = [Expr]
|
|
|
|
|
|
2024-11-11 20:08:21 -08:00
|
|
|
data TypeCheckError = Err | SquareUntyped | UnboundVariable | NotASort Expr Int | ExpectedFunctionType Expr | NotEquivalent Expr Expr
|
2024-11-11 17:57:14 -08:00
|
|
|
deriving (Show)
|
|
|
|
|
|
|
|
|
|
type CheckResult = Either TypeCheckError
|
|
|
|
|
|
|
|
|
|
matchPi :: Expr -> CheckResult (Expr, Expr)
|
|
|
|
|
matchPi (Pi _ a b) = Right (a, b)
|
|
|
|
|
matchPi e = Left $ ExpectedFunctionType e
|
|
|
|
|
|
|
|
|
|
showContext :: Context -> String
|
|
|
|
|
showContext g = "[" ++ intercalate ", " (map show g) ++ "]"
|
|
|
|
|
|
2024-11-11 20:08:21 -08:00
|
|
|
-- TODO: Debug these problem cases
|
|
|
|
|
-- λ (S : *) (P : S -> *) (H : forall (x : S), P x) (y : S) => P y
|
2024-11-11 17:57:14 -08:00
|
|
|
findType :: Context -> Expr -> CheckResult Expr
|
2024-11-11 20:08:21 -08:00
|
|
|
findType _ Star = trace "star" $ Right Square
|
|
|
|
|
findType _ Square = trace "square" $ Left SquareUntyped
|
2024-11-11 17:57:14 -08:00
|
|
|
findType g (Var n _) = do
|
|
|
|
|
!_ <- trace ("var:\t" ++ showContext g ++ "\n n:\t" ++ show n) (Right Star)
|
|
|
|
|
t <- maybe (Left UnboundVariable) Right $ g !? fromInteger n
|
|
|
|
|
s <- findType g t
|
2024-11-11 20:08:21 -08:00
|
|
|
unless (isSort s) $ throwError $ NotASort s 32
|
2024-11-11 13:37:44 -08:00
|
|
|
pure t
|
2024-10-05 13:31:09 -07:00
|
|
|
findType g (App m n) = do
|
2024-11-11 17:57:14 -08:00
|
|
|
!_ <- trace ("app:\t" ++ showContext g ++ "\n m:\t" ++ show m ++ "\n n: \t" ++ show n) (Right Star)
|
|
|
|
|
(a, b) <- findType g m >>= matchPi
|
2024-11-11 13:37:44 -08:00
|
|
|
a' <- findType g n
|
2024-11-11 17:57:14 -08:00
|
|
|
unless (betaEquiv a a') $ throwError $ NotEquivalent a a'
|
2024-11-11 13:37:44 -08:00
|
|
|
pure $ subst n b
|
2024-11-11 17:57:14 -08:00
|
|
|
findType g (Abs x a m) = do
|
|
|
|
|
!_ <- trace ("abs:\t" ++ showContext g ++ "\n a:\t" ++ show a ++ "\n m:\t" ++ show m) (Right Star)
|
|
|
|
|
s1 <- findType g a
|
2024-11-11 20:08:21 -08:00
|
|
|
!_ <- trace ("back in abs:\t" ++ showContext g ++ "\n\t\t" ++ show a ++ " : " ++ show s1) (Right Star)
|
|
|
|
|
unless (isSort s1) $ throwError $ NotASort s1 43
|
2024-11-11 17:57:14 -08:00
|
|
|
b <- findType (incIndices a : map incIndices g) m
|
|
|
|
|
s2 <- findType g (Pi x a b)
|
2024-11-11 20:08:21 -08:00
|
|
|
unless (isSort s2) $ throwError $ NotASort s2 46
|
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
|
|
|
|
|
!_ <- trace ("pi:\t" ++ showContext g ++ "\n a:\t" ++ show a ++ "\n b:\t" ++ show b) (Right Star)
|
|
|
|
|
s1 <- findType g a
|
2024-11-11 20:08:21 -08:00
|
|
|
unless (isSort s1) $ throwError $ NotASort s1 51
|
2024-11-11 17:57:14 -08:00
|
|
|
s2 <- findType (incIndices a : map incIndices g) b
|
2024-11-11 20:08:21 -08:00
|
|
|
unless (isSort s2) $ throwError $ NotASort s2 53
|
2024-11-11 17:57:14 -08:00
|
|
|
pure s2
|