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.

382 lines
12 KiB

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