less prototype, less bad code implementation of CCHM type theory
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
4.2 KiB

  1. {-# LANGUAGE TupleSections, OverloadedStrings #-}
  2. {-# LANGUAGE DeriveAnyClass #-}
  3. module Elab where
  4. import Control.Monad.Reader
  5. import Control.Exception
  6. import qualified Data.Map.Strict as Map
  7. import Data.Typeable
  8. import Elab.Monad
  9. import Elab.Eval
  10. import qualified Presyntax.Presyntax as P
  11. import Syntax
  12. infer :: P.Expr -> ElabM (Term, NFType)
  13. infer (P.Span ex a b) = do
  14. env <- ask
  15. liftIO $
  16. runElab (infer ex) env
  17. `catches` [ Handler $ \e@WhileChecking{} -> throwIO e
  18. , Handler $ \e -> throwIO (WhileChecking a b e)
  19. ]
  20. infer (P.Var t) = do
  21. name <- getNameFor t
  22. case name of
  23. Builtin _ wi -> elabWiredIn wi name
  24. _ -> do
  25. nft <- getNfType name
  26. pure (Ref name, nft)
  27. infer (P.App p f x) = do
  28. (f, f_ty) <- infer f
  29. (d, r, w) <- isPiType p f_ty
  30. x <- check x d
  31. x_nf <- eval x
  32. pure (App p (w f) x, r x_nf)
  33. infer (P.Pi p s d r) = do
  34. d <- check d VType
  35. d_nf <- eval d
  36. assume (Bound s) d_nf $ do
  37. r <- check r VType
  38. pure (Pi p s d r, VType)
  39. infer (P.Sigma s d r) = do
  40. d <- check d VType
  41. d_nf <- eval d
  42. assume (Bound s) d_nf $ do
  43. r <- check r VType
  44. pure (Sigma s d r, VType)
  45. infer (P.Proj1 x) = do
  46. (tm, ty) <- infer x
  47. (d, _, wp) <- isSigmaType ty
  48. pure (Proj1 (wp tm), d)
  49. infer (P.Proj2 x) = do
  50. (tm, ty) <- infer x
  51. tm_nf <- eval tm
  52. (_, r, wp) <- isSigmaType ty
  53. pure (Proj2 (wp tm), r (vProj1 tm_nf))
  54. infer exp = do
  55. t <- newMeta VType
  56. tm <- switch $ check exp t
  57. pure (tm, t)
  58. check :: P.Expr -> NFType -> ElabM Term
  59. check (P.Span ex a b) ty = do
  60. env <- ask
  61. liftIO $
  62. runElab (check ex ty) env
  63. `catches` [ Handler $ \e@WhileChecking{} -> throwIO e
  64. , Handler $ \e -> throwIO (WhileChecking a b e)
  65. ]
  66. check (P.Lam p var body) (VPi p' dom (Closure _ rng)) | p == p' =
  67. assume (Bound var) dom $
  68. Lam p var <$> check body (rng (VVar (Bound var)))
  69. check tm (VPi P.Im dom (Closure var rng)) =
  70. assume (Bound var) dom $
  71. Lam P.Im var <$> check tm (rng (VVar (Bound var)))
  72. check (P.Lam p v b) ty = do
  73. (d, r, wp) <- isPiType p ty
  74. assume (Bound v) d $
  75. wp . Lam P.Im v <$> check b (r (VVar (Bound v)))
  76. check (P.Pair a b) ty = do
  77. (d, r, wp) <- isSigmaType ty
  78. a <- check a d
  79. a_nf <- eval a
  80. b <- check b (r a_nf)
  81. pure (wp (Pair a b))
  82. check exp ty = do
  83. (tm, has) <- switch $ infer exp
  84. unify has ty
  85. pure tm
  86. elabWiredIn :: WiredIn -> Name -> ElabM (Term, NFType)
  87. elabWiredIn WiType _ = pure (Type, VType)
  88. isPiType :: P.Plicity -> NFType -> ElabM (Value, NFType -> NFType, Term -> Term)
  89. isPiType p (VPi p' d (Closure _ k)) | p == p' = pure (d, k, id)
  90. isPiType p t = do
  91. dom <- newMeta VType
  92. name <- newName
  93. assume (Bound name) dom $ do
  94. rng <- newMeta VType
  95. wp <- isConvertibleTo t (VPi p dom (Closure name (const rng)))
  96. pure (dom, const rng, wp)
  97. isSigmaType :: NFType -> ElabM (Value, NFType -> NFType, Term -> Term)
  98. isSigmaType (VSigma d (Closure _ k)) = pure (d, k, id)
  99. isSigmaType t = do
  100. dom <- newMeta VType
  101. name <- newName
  102. assume (Bound name) dom $ do
  103. rng <- newMeta VType
  104. wp <- isConvertibleTo t (VSigma dom (Closure name (const rng)))
  105. pure (dom, const rng, wp)
  106. identityTy :: NFType
  107. identityTy = VPi P.Im VType (Closure "A" $ \t -> VPi P.Ex t (Closure "_" (const t)))
  108. checkStatement :: P.Statement -> ElabM a -> ElabM a
  109. checkStatement (P.Decl name ty) k = do
  110. ty <- check ty VType
  111. ty_nf <- eval ty
  112. assume (Defined name) ty_nf k
  113. checkStatement (P.Defn name rhs) k = do
  114. ty <- asks (Map.lookup (Defined name) . getEnv)
  115. case ty of
  116. Nothing -> do
  117. (tm, ty) <- infer rhs
  118. tm_nf <- eval tm
  119. define (Defined name) ty tm_nf k
  120. Just (ty_nf, nm) -> do
  121. unless (nm == VVar (Defined name)) . liftIO . throwIO $
  122. Redefinition (Defined name)
  123. rhs <- check rhs ty_nf
  124. rhs_nf <- eval rhs
  125. define (Defined name) ty_nf rhs_nf k
  126. checkProgram :: [P.Statement] -> ElabM ElabEnv
  127. checkProgram [] = ask
  128. checkProgram (st:sts) = checkStatement st $ checkProgram sts
  129. newtype Redefinition = Redefinition { getRedefName :: Name }
  130. deriving (Show, Typeable, Exception)
  131. data WhileChecking = WhileChecking { startPos :: P.Posn, endPos :: P.Posn, exc :: SomeException }
  132. deriving (Show, Typeable, Exception)