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.

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