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.

337 lines
9.9 KiB

  1. {-# LANGUAGE TupleSections #-}
  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.Traversable
  9. import Data.Typeable
  10. import Data.Foldable
  11. import Elab.Eval.Formula (possible, truthAssignments)
  12. import Elab.WiredIn
  13. import Elab.Monad
  14. import Elab.Eval
  15. import qualified Presyntax.Presyntax as P
  16. import Prettyprinter
  17. import Syntax
  18. import Syntax.Pretty
  19. import qualified Data.Text as T
  20. infer :: P.Expr -> ElabM (Term, NFType)
  21. infer (P.Span ex a b) = withSpan a b $ infer ex
  22. infer (P.Var t) = do
  23. name <- getNameFor t
  24. nft <- getNfType name
  25. pure (Ref name, nft)
  26. infer (P.App p f x) = do
  27. (f, f_ty) <- infer f
  28. porp <- isPiType p f_ty
  29. case porp of
  30. It'sProd d r w -> do
  31. x <- check x d
  32. x_nf <- eval x
  33. pure (App p (w f) x, r x_nf)
  34. It'sPath li le ri wp -> do
  35. x <- check x VI
  36. x_nf <- eval x
  37. pure (IElim (quote (fun li)) (quote le) (quote ri) (wp f) x, li x_nf)
  38. It'sPartial phi a w -> do
  39. x <- check x (VIsOne phi)
  40. pure (App P.Ex (w f) x, a)
  41. It'sPartialP phi a w -> do
  42. x <- check x (VIsOne phi)
  43. x_nf <- eval x
  44. pure (App P.Ex (w f) x, a @@ x_nf)
  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 = withSpan a b $ check ex ty
  60. check (P.Lam p var body) (VPi p' dom (Closure _ rng)) | p == p' =
  61. assume (Bound var) dom $
  62. Lam p var <$> check body (rng (VVar (Bound var)))
  63. check tm (VPi P.Im dom (Closure var rng)) =
  64. assume (Bound var) dom $
  65. Lam P.Im var <$> check tm (rng (VVar (Bound var)))
  66. check (P.Lam p v b) ty = do
  67. porp <- isPiType p =<< forceIO ty
  68. case porp of
  69. It'sProd d r wp ->
  70. assume (Bound v) d $
  71. wp . Lam p v <$> check b (r (VVar (Bound v)))
  72. It'sPath li le ri wp -> do
  73. tm <- assume (Bound v) VI $
  74. Lam P.Ex v <$> check b (force (li (VVar (Bound v))))
  75. tm_nf <- eval tm
  76. unify (tm_nf @@ VI0) le
  77. `catchElab` (throwElab . WhenCheckingEndpoint le ri VI0)
  78. unify (tm_nf @@ VI1) ri
  79. `catchElab` (throwElab . WhenCheckingEndpoint le ri VI1)
  80. pure (wp (PathIntro (quote (fun li)) (quote le) (quote ri) tm))
  81. It'sPartial phi a wp ->
  82. assume (Bound v) (VIsOne phi) $
  83. wp . Lam p v <$> check b a
  84. It'sPartialP phi a wp ->
  85. assume (Bound v) (VIsOne phi) $
  86. wp . Lam p v <$> check b (a @@ VVar (Bound v))
  87. check (P.Pair a b) ty = do
  88. (d, r, wp) <- isSigmaType =<< forceIO ty
  89. a <- check a d
  90. a_nf <- eval a
  91. b <- check b (r a_nf)
  92. pure (wp (Pair a b))
  93. check (P.Pi p s d r) ty = do
  94. isSort ty
  95. d <- check d ty
  96. d_nf <- eval d
  97. assume (Bound s) d_nf $ do
  98. r <- check r ty
  99. pure (Pi p s d r)
  100. check (P.Sigma s d r) ty = do
  101. isSort ty
  102. d <- check d ty
  103. d_nf <- eval d
  104. assume (Bound s) d_nf $ do
  105. r <- check r ty
  106. pure (Sigma s d r)
  107. check (P.LamSystem bs) ty = do
  108. (extent, dom) <- isPartialType ty
  109. let dom_q = quote dom
  110. eqns <- for (zip [(0 :: Int)..] bs) $ \(n, (formula, rhs)) -> do
  111. phi <- checkFormula (P.condF formula)
  112. rhses <-
  113. case P.condV formula of
  114. Just t -> assume (Bound t) (VIsOne phi) $ do
  115. env <- ask
  116. for (truthAssignments phi (getEnv env)) $ \e -> do
  117. let env' = env{ getEnv = e }
  118. check rhs (eval' env' dom_q)
  119. Nothing -> do
  120. env <- ask
  121. for (truthAssignments phi (getEnv env)) $ \e -> do
  122. let env' = env{ getEnv = e }
  123. check rhs (eval' env' dom_q)
  124. pure (n, (phi, (P.condV formula, head rhses)))
  125. unify extent (foldl ior VI0 (map (fst . snd) eqns))
  126. for_ eqns $ \(n, (formula, (binding, rhs))) -> do
  127. let
  128. k = case binding of
  129. Just v -> assume (Bound v) (VIsOne formula)
  130. Nothing -> id
  131. k $ for_ eqns $ \(n', (formula', (binding, rhs'))) -> do
  132. let
  133. k = case binding of
  134. Just v -> assume (Bound v) (VIsOne formula)
  135. Nothing -> id
  136. truth = possible mempty (iand formula formula')
  137. add [] = id
  138. add ((~(HVar x), True):xs) = define x VI VI1 . add xs
  139. add ((~(HVar x), False):xs) = define x VI VI0 . add xs
  140. k $ when ((n /= n') && fst truth) . add (Map.toList (snd truth)) $ do
  141. vl <- eval rhs
  142. vl' <- eval rhs'
  143. unify vl vl'
  144. `withNote` vsep [ pretty "These two cases must agree because they are both possible:"
  145. , indent 2 $ pretty '*' <+> prettyTm (quote formula) <+> operator (pretty "=>") <+> prettyTm rhs
  146. , indent 2 $ pretty '*' <+> prettyTm (quote formula') <+> operator (pretty "=>") <+> prettyTm rhs'
  147. ]
  148. `withNote` (pretty "Consider this face, where both are true:" <+> showFace (snd truth))
  149. name <- newName
  150. let
  151. mkB name (Just v, b) = App P.Ex (Lam P.Ex v b) (Ref name)
  152. mkB _ (Nothing, b) = b
  153. pure (Lam P.Ex name (System (Map.fromList (map (\(_, (x, y)) -> (quote x, mkB (Bound name) y)) eqns))))
  154. check exp ty = do
  155. (tm, has) <- switch $ infer exp
  156. wp <- isConvertibleTo has ty
  157. pure (wp tm)
  158. checkFormula :: P.Formula -> ElabM Value
  159. checkFormula P.FTop = pure VI1
  160. checkFormula P.FBot = pure VI0
  161. checkFormula (P.FAnd x y) = iand <$> checkFormula x <*> checkFormula y
  162. checkFormula (P.FOr x y) = ior <$> checkFormula x <*> checkFormula y
  163. checkFormula (P.FIs0 x) = do
  164. nm <- getNameFor x
  165. ty <- getNfType nm
  166. unify ty VI
  167. pure (inot (VVar nm))
  168. checkFormula (P.FIs1 x) = do
  169. nm <- getNameFor x
  170. ty <- getNfType nm
  171. unify ty VI
  172. pure (VVar nm)
  173. isSort :: NFType -> ElabM ()
  174. isSort VType = pure ()
  175. isSort VTypeω = pure ()
  176. isSort vt@(VNe HMeta{} _) = unify vt VType
  177. isSort vt = throwElab $ NotEqual vt VType
  178. data ProdOrPath
  179. = It'sProd { prodDmn :: NFType
  180. , prodRng :: NFType -> NFType
  181. , prodWrap :: Term -> Term
  182. }
  183. | It'sPath { pathLine :: NFType -> NFType
  184. , pathLeft :: Value
  185. , pathRight :: Value
  186. , pathWrap :: Term -> Term
  187. }
  188. | It'sPartial { partialExtent :: NFEndp
  189. , partialDomain :: Value
  190. , partialWrap :: Term -> Term
  191. }
  192. | It'sPartialP { partialExtent :: NFEndp
  193. , partialDomain :: Value
  194. , partialWrap :: Term -> Term
  195. }
  196. isPiType :: P.Plicity -> NFType -> ElabM ProdOrPath
  197. isPiType p (VPi p' d (Closure _ k)) | p == p' = pure (It'sProd d k id)
  198. isPiType P.Ex (VPath li le ri) = pure (It'sPath (li @@) le ri id)
  199. isPiType P.Ex (VPartial phi a) = pure (It'sPartial phi a id)
  200. isPiType P.Ex (VPartialP phi a) = pure (It'sPartialP phi a id)
  201. isPiType P.Ex (VPi P.Im d (Closure _ k)) = do
  202. meta <- newMeta d
  203. porp <- isPiType P.Ex (k meta)
  204. pure $ case porp of
  205. It'sProd d r w -> It'sProd d r (\f -> w (App P.Im f (quote meta)))
  206. It'sPath l x y w -> It'sPath l x y (\f -> w (App P.Im f (quote meta)))
  207. It'sPartial phi a w -> It'sPartial phi a (\f -> w (App P.Im f (quote meta)))
  208. It'sPartialP phi a w -> It'sPartialP phi a (\f -> w (App P.Im f (quote meta)))
  209. isPiType p t = do
  210. dom <- newMeta VType
  211. name <- newName
  212. assume (Bound name) dom $ do
  213. rng <- newMeta VType
  214. wp <- isConvertibleTo t (VPi p dom (Closure name (const rng)))
  215. pure (It'sProd dom (const rng) wp)
  216. isSigmaType :: NFType -> ElabM (Value, NFType -> NFType, Term -> Term)
  217. isSigmaType (VSigma d (Closure _ k)) = pure (d, k, id)
  218. isSigmaType t = do
  219. dom <- newMeta VType
  220. name <- newName
  221. assume (Bound name) dom $ do
  222. rng <- newMeta VType
  223. wp <- isConvertibleTo t (VSigma dom (Closure name (const rng)))
  224. pure (dom, const rng, wp)
  225. isPartialType :: NFType -> ElabM (NFEndp, Value)
  226. isPartialType (VPartial phi a) = pure (phi, a)
  227. isPartialType (VPartialP phi a) = pure (phi, a)
  228. isPartialType t = do
  229. phi <- newMeta VI
  230. dom <- newMeta (VPartial phi VType)
  231. unify t (VPartial phi dom)
  232. pure (phi, dom)
  233. checkStatement :: P.Statement -> ElabM a -> ElabM a
  234. checkStatement (P.SpanSt s a b) k = withSpan a b $ checkStatement s k
  235. checkStatement (P.Decl name ty) k = do
  236. ty <- check ty VTypeω
  237. ty_nf <- eval ty
  238. assumes (Defined <$> name) ty_nf k
  239. checkStatement (P.Defn name rhs) k = do
  240. ty <- asks (Map.lookup (Defined name) . getEnv)
  241. case ty of
  242. Nothing -> do
  243. (tm, ty) <- infer rhs
  244. tm_nf <- eval tm
  245. define (Defined name) ty tm_nf k
  246. Just (ty_nf, nm) -> do
  247. case nm of
  248. VVar (Defined n') | n' == name -> pure ()
  249. _ -> throwElab $ Redefinition (Defined name)
  250. rhs <- check rhs ty_nf
  251. rhs_nf <- eval rhs
  252. define (Defined name) ty_nf rhs_nf k
  253. checkStatement (P.Builtin winame var) k = do
  254. wi <-
  255. case Map.lookup winame wiredInNames of
  256. Just wi -> pure wi
  257. _ -> throwElab $ NoSuchPrimitive winame
  258. let
  259. check = do
  260. nm <- getNameFor var
  261. ty <- getNfType nm
  262. unify ty (wiType wi)
  263. `withNote` hsep [ pretty "Previous definition of", pretty nm, pretty "here" ]
  264. `seeAlso` nm
  265. env <- ask
  266. liftIO $
  267. runElab check env `catch` \(_ :: NotInScope) -> pure ()
  268. define (Defined var) (wiType wi) (wiValue wi) k
  269. checkStatement (P.ReplNf e) k = do
  270. (e, _) <- infer e
  271. e_nf <- eval e
  272. h <- asks commHook
  273. liftIO (h e_nf)
  274. k
  275. checkStatement (P.ReplTy e) k = do
  276. (_, ty) <- infer e
  277. h <- asks commHook
  278. liftIO (h ty)
  279. k
  280. checkProgram :: [P.Statement] -> ElabM a -> ElabM a
  281. checkProgram [] k = k
  282. checkProgram (st:sts) k = checkStatement st $ checkProgram sts k
  283. newtype Redefinition = Redefinition { getRedefName :: Name }
  284. deriving (Show, Typeable, Exception)
  285. data WhenCheckingEndpoint = WhenCheckingEndpoint { leftEndp :: Value, rightEndp :: Value, whichIsWrong :: NFEndp, exc :: SomeException }
  286. deriving (Show, Typeable, Exception)