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.

517 lines
17 KiB

  1. {-# LANGUAGE BlockArguments #-}
  2. {-# LANGUAGE TupleSections #-}
  3. {-# LANGUAGE DeriveAnyClass #-}
  4. {-# LANGUAGE ScopedTypeVariables #-}
  5. {-# LANGUAGE DerivingStrategies #-}
  6. module Elab where
  7. import Control.Arrow (Arrow(first))
  8. import Control.Monad.Reader
  9. import Control.Exception
  10. import qualified Data.Map.Strict as Map
  11. import qualified Data.Sequence as Seq
  12. import qualified Data.Set as Set
  13. import qualified Data.Text as T
  14. import Data.Traversable
  15. import Data.Text (Text)
  16. import Data.Map (Map)
  17. import Data.Typeable
  18. import Data.Foldable
  19. import Elab.Eval.Formula (possible, truthAssignments)
  20. import Elab.WiredIn
  21. import Elab.Monad
  22. import Elab.Eval
  23. import qualified Presyntax.Presyntax as P
  24. import Prettyprinter
  25. import Syntax.Pretty
  26. import Syntax
  27. infer :: P.Expr -> ElabM (Term, NFType)
  28. infer (P.Span ex a b) = withSpan a b $ infer ex
  29. infer (P.Var t) = do
  30. name <- getNameFor t
  31. nft <- getNfType name
  32. pure (Ref name, nft)
  33. infer (P.App p f x) = do
  34. (f, f_ty) <- infer f
  35. porp <- isPiType p f_ty
  36. case porp of
  37. It'sProd d r w -> do
  38. x <- check x d
  39. x_nf <- eval x
  40. pure (App p (w f) x, r x_nf)
  41. It'sPath li le ri wp -> do
  42. x <- check x VI
  43. x_nf <- eval x
  44. pure (IElim (quote (fun li)) (quote le) (quote ri) (wp f) x, li x_nf)
  45. It'sPartial phi a w -> do
  46. x <- check x (VIsOne phi)
  47. pure (App P.Ex (w f) x, a)
  48. It'sPartialP phi a w -> do
  49. x <- check x (VIsOne phi)
  50. x_nf <- eval x
  51. pure (App P.Ex (w f) x, a @@ x_nf)
  52. infer (P.Proj1 x) = do
  53. (tm, ty) <- infer x
  54. (d, _, wp) <- isSigmaType ty
  55. pure (Proj1 (wp tm), d)
  56. infer (P.Proj2 x) = do
  57. (tm, ty) <- infer x
  58. tm_nf <- eval tm
  59. (_, r, wp) <- isSigmaType ty
  60. pure (Proj2 (wp tm), r (vProj1 tm_nf))
  61. infer exp = do
  62. t <- newMeta VType
  63. tm <- switch $ check exp t
  64. pure (tm, t)
  65. check :: P.Expr -> NFType -> ElabM Term
  66. check (P.Span ex a b) ty = withSpan a b $ check ex ty
  67. check (P.Lam p var body) (VPi p' dom (Closure _ rng)) | p == p' =
  68. assume (Bound var 0) dom $ \name ->
  69. Lam p name <$> check body (rng (VVar name))
  70. check tm (VPi P.Im dom (Closure var rng)) =
  71. assume var dom $ \name ->
  72. Lam P.Im name <$> check tm (rng (VVar name))
  73. check (P.Lam p v b) ty = do
  74. porp <- isPiType p =<< forceIO ty
  75. case porp of
  76. It'sProd d r wp ->
  77. assume (Bound v 0) d $ \name ->
  78. wp . Lam p name <$> check b (r (VVar name))
  79. It'sPath li le ri wp -> do
  80. tm <- assume (Bound v 0) VI $ \var ->
  81. Lam P.Ex var <$> check b (force (li (VVar var)))
  82. tm_nf <- eval tm
  83. unify (tm_nf @@ VI0) le
  84. `catchElab` (throwElab . WhenCheckingEndpoint le ri VI0)
  85. unify (tm_nf @@ VI1) ri
  86. `catchElab` (throwElab . WhenCheckingEndpoint le ri VI1)
  87. pure (wp (PathIntro (quote (fun li)) (quote le) (quote ri) tm))
  88. It'sPartial phi a wp ->
  89. assume (Bound v 0) (VIsOne phi) $ \var ->
  90. wp . Lam p var <$> check b a
  91. It'sPartialP phi a wp ->
  92. assume (Bound v 0) (VIsOne phi) $ \var ->
  93. wp . Lam p var <$> check b (a @@ VVar var)
  94. check (P.Pair a b) ty = do
  95. (d, r, wp) <- isSigmaType =<< forceIO ty
  96. a <- check a d
  97. a_nf <- eval a
  98. b <- check b (r a_nf)
  99. pure (wp (Pair a b))
  100. check (P.Pi p s d r) ty = do
  101. isSort ty
  102. d <- check d ty
  103. d_nf <- eval d
  104. assume (Bound s 0) d_nf \var -> do
  105. r <- check r ty
  106. pure (Pi p var d r)
  107. check (P.Sigma s d r) ty = do
  108. isSort ty
  109. d <- check d ty
  110. d_nf <- eval d
  111. assume (Bound s 0) d_nf \var -> do
  112. r <- check r ty
  113. pure (Sigma var d r)
  114. check (P.Let items body) ty = do
  115. checkLetItems mempty items \decs -> do
  116. body <- check body ty
  117. pure (Let decs body)
  118. check (P.LamSystem bs) ty = do
  119. (extent, dom) <- isPartialType ty
  120. let dom_q = quote dom
  121. eqns <- for (zip [(0 :: Int)..] bs) $ \(n, (formula, rhs)) -> do
  122. phi <- checkFormula (P.condF formula)
  123. rhses <-
  124. case P.condV formula of
  125. Just t -> assume (Bound t 0) (VIsOne phi) $ \var -> do
  126. env <- ask
  127. for (truthAssignments phi (getEnv env)) $ \e -> do
  128. let env' = env{ getEnv = e }
  129. (Just var,) <$> check rhs (eval' env' dom_q)
  130. Nothing -> do
  131. env <- ask
  132. for (truthAssignments phi (getEnv env)) $ \e -> do
  133. let env' = env{ getEnv = e }
  134. (Nothing,) <$> check rhs (eval' env' dom_q)
  135. pure (n, (phi, head rhses))
  136. unify extent (foldl ior VI0 (map (fst . snd) eqns))
  137. for_ eqns $ \(n, (formula, (binding, rhs))) -> do
  138. let
  139. k = case binding of
  140. Just v -> assume v (VIsOne formula) . const
  141. Nothing -> id
  142. k $ for_ eqns $ \(n', (formula', (binding, rhs'))) -> do
  143. let
  144. k = case binding of
  145. Just v -> assume v (VIsOne formula) . const
  146. Nothing -> id
  147. truth = possible mempty (iand formula formula')
  148. add [] = id
  149. add ((~(HVar x), True):xs) = redefine x VI VI1 . add xs
  150. add ((~(HVar x), False):xs) = redefine x VI VI0 . add xs
  151. k $ when ((n /= n') && fst truth) . add (Map.toList (snd truth)) $ do
  152. vl <- eval rhs
  153. vl' <- eval rhs'
  154. unify vl vl'
  155. `withNote` vsep [ pretty "These two cases must agree because they are both possible:"
  156. , indent 2 $ pretty '*' <+> prettyTm (quote formula) <+> operator (pretty "=>") <+> prettyTm rhs
  157. , indent 2 $ pretty '*' <+> prettyTm (quote formula') <+> operator (pretty "=>") <+> prettyTm rhs'
  158. ]
  159. `withNote` (pretty "Consider this face, where both are true:" <+> showFace (snd truth))
  160. name <- newName
  161. let
  162. mkB name (Just v, b) = App P.Ex (Lam P.Ex v b) (Ref name)
  163. mkB _ (Nothing, b) = b
  164. pure (Lam P.Ex name (System (Map.fromList (map (\(_, (x, y)) -> (quote x, mkB name y)) eqns))))
  165. check (P.LamCase pats) ty = do
  166. porp <- isPiType P.Ex ty
  167. case porp of
  168. It'sProd dom rng wp -> do
  169. name <- newName
  170. cases <- for pats $ \(pat, rhs) -> do
  171. checkPattern pat dom \pat wp pat_nf -> do
  172. rhs <- check rhs (rng pat_nf)
  173. pure (pat, wp rhs)
  174. let x = wp (Lam P.Ex name (Case (Ref name) cases))
  175. pure x
  176. _ -> do
  177. dom <- newMeta VTypeω
  178. n <- newName' (Bound (T.singleton 'x') 0)
  179. assume n dom \_ -> do
  180. rng <- newMeta VTypeω
  181. throwElab $ NotEqual (VPi P.Ex dom (Closure n (const rng))) ty
  182. check exp ty = do
  183. (tm, has) <- switch $ infer exp
  184. wp <- isConvertibleTo has ty
  185. pure (wp tm)
  186. checkPattern :: P.Pattern -> NFSort -> (Term -> (Term -> Term) -> Value -> ElabM a) -> ElabM a
  187. checkPattern (P.PCap var) dom cont = do
  188. name <- asks (Map.lookup var . nameMap)
  189. case name of
  190. Just name@(ConName _ _ skip arity) -> do
  191. unless (arity == 0) $ throwElab $ UnsaturatedCon name
  192. (ty, wp) <- instantiate =<< getNfType name
  193. unify ty dom
  194. wrap <- skipLams skip
  195. cont (Con name) wrap =<< eval (wp (Con name))
  196. Just name -> throwElab $ NotACon name
  197. Nothing -> assume (Bound var 0) dom \name -> cont (Ref name) (Lam P.Ex name) (VVar name)
  198. checkPattern (P.PCon var args) dom cont =
  199. do
  200. name <- asks (Map.lookup var . nameMap)
  201. case name of
  202. Just name@(ConName _ _ nskip arity) -> do
  203. unless (arity == length args) $ throwElab $ UnsaturatedCon name
  204. (ty, wp) <- instantiate =<< getNfType name
  205. _ <- isConvertibleTo (skipBinders arity ty) dom
  206. skip <- skipLams nskip
  207. bindNames args ty $ \names wrap ->
  208. cont (Con name) (skip . wrap) =<< eval (foldl (\x y -> App P.Ex x (Ref y)) (wp (Con name)) names)
  209. Just name -> throwElab $ NotACon name
  210. _ -> throwElab $ NotInScope (Bound var 0)
  211. where
  212. skipBinders :: Int -> NFType -> NFType
  213. skipBinders 0 t = t
  214. skipBinders n (VPi _ _ (Closure v r)) = skipBinders (n - 1) (r (VVar v))
  215. skipBinders _ _ = error $ "constructor type is wrong?"
  216. bindNames (n:ns) (VPi p d (Closure _ r)) k =
  217. assume (Bound n 0) d \n -> bindNames ns (r (VVar n)) \ns w ->
  218. k (n:ns) (Lam p n . w)
  219. bindNames [] _ k = k [] id
  220. bindNames xs t _ = error $ show (xs, t)
  221. instantiate :: NFType -> ElabM (NFType, Term -> Term)
  222. instantiate (VPi P.Im d (Closure _ k)) = do
  223. t <- newMeta d
  224. (ty, w) <- instantiate (k t)
  225. pure (ty, \inner -> App P.Im (w inner) (quote t))
  226. instantiate x = pure (x, id)
  227. skipLams :: Int -> ElabM (Term -> Term)
  228. skipLams 0 = pure id
  229. skipLams k = do
  230. n <- newName
  231. (Lam P.Im n . ) <$> skipLams (k - 1)
  232. checkLetItems :: Map Text (Maybe NFType) -> [P.LetItem] -> ([(Name, Term, Term)] -> ElabM a) -> ElabM a
  233. checkLetItems _ [] cont = cont []
  234. checkLetItems map (P.LetDecl v t:xs) cont = do
  235. t <- check t VTypeω
  236. t_nf <- eval t
  237. assume (Defined v 0) t_nf \_ ->
  238. checkLetItems (Map.insert v (Just t_nf) map) xs cont
  239. checkLetItems map (P.LetBind name rhs:xs) cont = do
  240. case Map.lookup name map of
  241. Nothing -> do
  242. (tm, ty) <- infer rhs
  243. tm_nf <- eval tm
  244. makeLetDef (Defined name 0) ty tm_nf \name' ->
  245. checkLetItems map xs \xs ->
  246. cont ((name', quote ty, tm):xs)
  247. Just Nothing -> throwElab $ Redefinition (Defined name 0)
  248. Just (Just ty_nf) -> do
  249. rhs <- check rhs ty_nf
  250. rhs_nf <- eval rhs
  251. makeLetDef (Defined name 0) ty_nf rhs_nf \name' ->
  252. checkLetItems (Map.insert name Nothing map) xs \xs ->
  253. cont ((name', quote ty_nf, rhs):xs)
  254. checkFormula :: P.Formula -> ElabM Value
  255. checkFormula P.FTop = pure VI1
  256. checkFormula P.FBot = pure VI0
  257. checkFormula (P.FAnd x y) = iand <$> checkFormula x <*> checkFormula y
  258. checkFormula (P.FOr x y) = ior <$> checkFormula x <*> checkFormula y
  259. checkFormula (P.FIs0 x) = do
  260. nm <- getNameFor x
  261. ty <- getNfType nm
  262. unify ty VI
  263. pure (inot (VVar nm))
  264. checkFormula (P.FIs1 x) = do
  265. nm <- getNameFor x
  266. ty <- getNfType nm
  267. unify ty VI
  268. pure (VVar nm)
  269. isSort :: NFType -> ElabM ()
  270. isSort t = isSort (force t) where
  271. isSort VType = pure ()
  272. isSort VTypeω = pure ()
  273. isSort vt@(VNe HMeta{} _) = unify vt VType
  274. isSort vt = throwElab $ NotEqual vt VType
  275. data ProdOrPath
  276. = It'sProd { prodDmn :: NFType
  277. , prodRng :: NFType -> NFType
  278. , prodWrap :: Term -> Term
  279. }
  280. | It'sPath { pathLine :: NFType -> NFType
  281. , pathLeft :: Value
  282. , pathRight :: Value
  283. , pathWrap :: Term -> Term
  284. }
  285. | It'sPartial { partialExtent :: NFEndp
  286. , partialDomain :: Value
  287. , partialWrap :: Term -> Term
  288. }
  289. | It'sPartialP { partialExtent :: NFEndp
  290. , partialDomain :: Value
  291. , partialWrap :: Term -> Term
  292. }
  293. isPiType :: P.Plicity -> NFType -> ElabM ProdOrPath
  294. isPiType p x = isPiType p (force x) where
  295. isPiType p (VPi p' d (Closure _ k)) | p == p' = pure (It'sProd d k id)
  296. isPiType P.Ex (VPath li le ri) = pure (It'sPath (li @@) le ri id)
  297. isPiType P.Ex (VPartial phi a) = pure (It'sPartial phi a id)
  298. isPiType P.Ex (VPartialP phi a) = pure (It'sPartialP phi a id)
  299. isPiType P.Ex (VPi P.Im d (Closure _ k)) = do
  300. meta <- newMeta d
  301. porp <- isPiType P.Ex (k meta)
  302. pure $ case porp of
  303. It'sProd d r w -> It'sProd d r (\f -> w (App P.Im f (quote meta)))
  304. It'sPath l x y w -> It'sPath l x y (\f -> w (App P.Im f (quote meta)))
  305. It'sPartial phi a w -> It'sPartial phi a (\f -> w (App P.Im f (quote meta)))
  306. It'sPartialP phi a w -> It'sPartialP phi a (\f -> w (App P.Im f (quote meta)))
  307. isPiType p t = do
  308. dom <- newMeta VType
  309. name <- newName
  310. assume name dom $ \name -> do
  311. rng <- newMeta VType
  312. wp <- isConvertibleTo t (VPi p dom (Closure name (const rng)))
  313. pure (It'sProd dom (const rng) wp)
  314. isSigmaType :: NFType -> ElabM (Value, NFType -> NFType, Term -> Term)
  315. isSigmaType t = isSigmaType (force t) where
  316. isSigmaType (VSigma d (Closure _ k)) = pure (d, k, id)
  317. isSigmaType t = do
  318. dom <- newMeta VType
  319. name <- newName
  320. assume name dom $ \name -> do
  321. rng <- newMeta VType
  322. wp <- isConvertibleTo t (VSigma dom (Closure name (const rng)))
  323. pure (dom, const rng, wp)
  324. isPartialType :: NFType -> ElabM (NFEndp, Value)
  325. isPartialType t = isPartialType (force t) where
  326. isPartialType (VPartial phi a) = pure (phi, a)
  327. isPartialType (VPartialP phi a) = pure (phi, a)
  328. isPartialType t = do
  329. phi <- newMeta VI
  330. dom <- newMeta (VPartial phi VType)
  331. unify t (VPartial phi dom)
  332. pure (phi, dom)
  333. checkStatement :: P.Statement -> ElabM a -> ElabM a
  334. checkStatement (P.SpanSt s a b) k = withSpan a b $ checkStatement s k
  335. checkStatement (P.Decl name ty) k = do
  336. ty <- check ty VTypeω
  337. ty_nf <- eval ty
  338. assumes (flip Defined 0 <$> name) ty_nf (const k)
  339. checkStatement (P.Postulate []) k = k
  340. checkStatement (P.Postulate ((name, ty):xs)) k = do
  341. ty <- check ty VTypeω
  342. ty_nf <- eval ty
  343. assume (Defined name 0) ty_nf \name ->
  344. local (\e -> e { definedNames = Set.insert name (definedNames e) }) (checkStatement (P.Postulate xs) k)
  345. checkStatement (P.Defn name rhs) k = do
  346. ty <- asks (Map.lookup name . nameMap)
  347. case ty of
  348. Nothing -> do
  349. (tm, ty) <- infer rhs
  350. tm_nf <- eval tm
  351. makeLetDef (Defined name 0) ty tm_nf (const k)
  352. Just nm -> do
  353. ty_nf <- getNfType nm
  354. t <- asks (Set.member nm . definedNames)
  355. when t $ throwElab (Redefinition (Defined name 0))
  356. rhs <- check rhs ty_nf
  357. rhs_nf <- evalFix (Defined name 0) ty_nf rhs
  358. makeLetDef (Defined name 0) ty_nf rhs_nf $ \name ->
  359. local (\e -> e { definedNames = Set.insert name (definedNames e) }) k
  360. checkStatement (P.Builtin winame var) k = do
  361. wi <-
  362. case Map.lookup winame wiredInNames of
  363. Just wi -> pure wi
  364. _ -> throwElab $ NoSuchPrimitive winame
  365. let
  366. check = do
  367. nm <- getNameFor var
  368. ty <- getNfType nm
  369. unify ty (wiType wi)
  370. `withNote` hsep [ pretty "Previous definition of", pretty nm, pretty "here" ]
  371. `seeAlso` nm
  372. env <- ask
  373. liftIO $
  374. runElab check env `catch` \(_ :: NotInScope) -> pure ()
  375. define (Defined var 0) (wiType wi) (wiValue wi) $ \name ->
  376. local (\e -> e { definedNames = Set.insert name (definedNames e) }) k
  377. checkStatement (P.ReplNf e) k = do
  378. (e, _) <- infer e
  379. e_nf <- eval e
  380. h <- asks commHook
  381. liftIO (h e_nf)
  382. k
  383. checkStatement (P.ReplTy e) k = do
  384. (_, ty) <- infer e
  385. h <- asks commHook
  386. liftIO (h ty)
  387. k
  388. checkStatement (P.Data name tele retk constrs) k =
  389. do
  390. checkTeleRetk True tele retk \kind tele undef -> do
  391. kind_nf <- eval kind
  392. defineInternal (Defined name 0) kind_nf (\name' -> VNe (HData name') mempty) \name' ->
  393. checkCons tele (VNe (HData name') (Seq.fromList (map makeProj tele))) constrs (local (markAsDef name' . undef) k)
  394. where
  395. makeProj (x, p, _) = PApp p (VVar x)
  396. markAsDef x e = e { definedNames = Set.insert x (definedNames e) }
  397. checkTeleRetk allKan [] retk cont = do
  398. t <- check retk VTypeω
  399. t_nf <- eval t
  400. when allKan $ unify t_nf VType
  401. cont t [] id
  402. checkTeleRetk allKan ((x, p, t):xs) retk cont = do
  403. (t, ty) <- infer t
  404. _ <- isConvertibleTo ty VTypeω
  405. let
  406. allKan' = case ty of
  407. VType -> allKan
  408. _ -> False
  409. t_nf <- eval t
  410. let rm nm e = e{ nameMap = Map.delete (getNameText nm) (nameMap e), getEnv = Map.delete nm (getEnv e) }
  411. assume (Bound x 0) t_nf $ \nm -> checkTeleRetk allKan' xs retk \k xs w -> cont (Pi p nm t k) ((nm, p, t_nf):xs) (rm nm . w)
  412. checkCons _ _et [] k = k
  413. checkCons n ret ((x, ty):xs) k = do
  414. t <- check ty VTypeω
  415. ty_nf <- eval t
  416. let
  417. (args, ret') = splitPi ty_nf
  418. closed = close n t
  419. n' = map (\(x, _, y) -> (x, P.Im, y)) n
  420. unify ret' ret
  421. closed_nf <- eval closed
  422. defineInternal (ConName x 0 (length n') (length args)) closed_nf (makeCon closed_nf mempty n' args) \_ -> checkCons n ret xs k
  423. close [] t = t
  424. close ((x, _, y):xs) t = Pi P.Im x (quote y) (close xs t)
  425. splitPi (VPi p y (Closure x k)) = first ((x, p, y):) $ splitPi (k (VVar x))
  426. splitPi t = ([], t)
  427. makeCon cty sp [] [] con = VNe (HCon cty con) sp
  428. makeCon cty sp ((nm, p, _):xs) ys con = VLam p $ Closure nm \a -> makeCon cty (sp Seq.:|> PApp p a) xs ys con
  429. makeCon cty sp [] ((nm, p, _):ys) con = VLam p $ Closure nm \a -> makeCon cty (sp Seq.:|> PApp p a) [] ys con
  430. evalFix :: Name -> NFType -> Term -> ElabM Value
  431. evalFix name nft term = do
  432. env <- ask
  433. pure . fix $ \val -> eval' env{ getEnv = Map.insert name (nft, val) (getEnv env) } term
  434. checkProgram :: [P.Statement] -> ElabM a -> ElabM a
  435. checkProgram [] k = k
  436. checkProgram (st:sts) k = checkStatement st $ checkProgram sts k
  437. newtype Redefinition = Redefinition { getRedefName :: Name }
  438. deriving (Show, Typeable, Exception)
  439. data WhenCheckingEndpoint = WhenCheckingEndpoint { leftEndp :: Value, rightEndp :: Value, whichIsWrong :: NFEndp, exc :: SomeException }
  440. deriving (Show, Typeable, Exception)
  441. data UnsaturatedCon = UnsaturatedCon { theConstr :: Name }
  442. deriving (Show, Typeable)
  443. deriving anyclass (Exception)
  444. data NotACon = NotACon { theNotConstr :: Name }
  445. deriving (Show, Typeable)
  446. deriving anyclass (Exception)