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.

185 lines
4.6 KiB

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