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.

514 lines
16 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. liftIO . print $ show pats
  171. cases <- for pats $ \(pat, rhs) -> do
  172. checkPattern pat dom \pat wp -> do
  173. pat_nf <- eval pat
  174. rhs <- check rhs (rng pat_nf)
  175. pure (pat, wp rhs)
  176. pure (wp (Lam P.Ex name (Case (Ref name) cases)))
  177. _ -> do
  178. dom <- newMeta VTypeω
  179. n <- newName' (Bound (T.singleton 'x') 0)
  180. assume n dom \_ -> do
  181. rng <- newMeta VTypeω
  182. throwElab $ NotEqual (VPi P.Ex dom (Closure n (const rng))) ty
  183. check exp ty = do
  184. (tm, has) <- switch $ infer exp
  185. wp <- isConvertibleTo has ty
  186. pure (wp tm)
  187. checkPattern :: P.Pattern -> NFSort -> (Term -> (Term -> Term) -> ElabM a) -> ElabM a
  188. checkPattern (P.PCap var) dom cont = do
  189. name <- asks (Map.lookup var . nameMap)
  190. case name of
  191. Just name@(ConName _ _ skip arity) -> do
  192. unless (arity == 0) $ throwElab $ UnsaturatedCon name
  193. ty <- instantiate =<< getNfType name
  194. _ <- isConvertibleTo ty dom
  195. wrap <- skipLams skip
  196. cont (Con name) wrap
  197. Just name -> throwElab $ NotACon name
  198. Nothing -> assume (Bound var 0) dom \name -> cont (Ref name) (Lam P.Ex name)
  199. checkPattern (P.PCon var args) dom cont =
  200. do
  201. name <- asks (Map.lookup var . nameMap)
  202. case name of
  203. Just name@(ConName _ _ nskip arity) -> do
  204. unless (arity == length args) $ throwElab $ UnsaturatedCon name
  205. ty <- instantiate =<< getNfType name
  206. _ <- isConvertibleTo (skipBinders arity ty) dom
  207. skip <- skipLams nskip
  208. bindNames args ty $ \_ wrap ->
  209. cont (Con name) (skip . wrap)
  210. Just name -> throwElab $ NotACon name
  211. _ -> throwElab $ NotInScope (Bound var 0)
  212. where
  213. skipBinders :: Int -> NFType -> NFType
  214. skipBinders 0 t = t
  215. skipBinders n (VPi _ _ (Closure v r)) = skipBinders (n - 1) (r (VVar v))
  216. skipBinders _ _ = error $ "constructor type is wrong?"
  217. bindNames (n:ns) (VPi p d (Closure _ r)) k =
  218. assume (Bound n 0) d \n -> bindNames ns (r (VVar n)) \ns w ->
  219. k (n:ns) (Lam p n . w)
  220. bindNames [] _ k = k [] id
  221. bindNames xs t _ = error $ show (xs, t)
  222. instantiate :: NFType -> ElabM NFType
  223. instantiate (VPi P.Im d (Closure _ k)) = do
  224. t <- newMeta d
  225. instantiate (k t)
  226. instantiate x = pure x
  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 -> do
  391. kind_nf <- eval kind
  392. defineInternal (Bound name 0) kind_nf (\name' -> VNe (HData name') mempty) \name' -> do
  393. checkCons tele (VNe (HData name') (Seq.fromList (map makeProj tele))) constrs k
  394. where
  395. makeProj (x, p, _) = PApp p (VVar x)
  396. checkTeleRetk allKan [] retk cont = do
  397. t <- check retk VTypeω
  398. t_nf <- eval t
  399. when allKan $ unify t_nf VType
  400. cont t []
  401. checkTeleRetk allKan ((x, p, t):xs) retk cont = do
  402. (t, ty) <- infer t
  403. _ <- isConvertibleTo ty VTypeω
  404. let
  405. allKan' = case ty of
  406. VType -> allKan
  407. _ -> False
  408. t_nf <- eval t
  409. assume (Bound x 0) t_nf $ \nm -> checkTeleRetk allKan' xs retk \k xs -> cont (Pi p nm t k) ((nm, p, t_nf):xs)
  410. checkCons _ _et [] k = k
  411. checkCons n ret ((x, ty):xs) k = do
  412. t <- check ty VTypeω
  413. ty_nf <- eval t
  414. let
  415. (args, ret') = splitPi ty_nf
  416. closed = close n t
  417. n' = map (\(x, _, y) -> (x, P.Im, y)) n
  418. unify ret' ret
  419. closed_nf <- eval closed
  420. defineInternal (ConName x 0 (length n') (length args)) closed_nf (makeCon closed_nf mempty n' args) \_ -> checkCons n ret xs k
  421. close [] t = t
  422. close ((x, _, y):xs) t = Pi P.Im x (quote y) (close xs t)
  423. splitPi (VPi p y (Closure x k)) = first ((x, p, y):) $ splitPi (k (VVar x))
  424. splitPi t = ([], t)
  425. makeCon cty sp [] [] con = VNe (HCon cty con) sp
  426. makeCon cty sp ((nm, p, _):xs) ys con = VLam p $ Closure nm \a -> makeCon cty (sp Seq.:|> PApp p a) xs ys con
  427. makeCon cty sp [] ((nm, p, _):ys) con = VLam p $ Closure nm \a -> makeCon cty (sp Seq.:|> PApp p a) [] ys con
  428. evalFix :: Name -> NFType -> Term -> ElabM Value
  429. evalFix name nft term = do
  430. env <- ask
  431. pure . fix $ \val -> eval' env{ getEnv = Map.insert name (nft, val) (getEnv env) } term
  432. checkProgram :: [P.Statement] -> ElabM a -> ElabM a
  433. checkProgram [] k = k
  434. checkProgram (st:sts) k = checkStatement st $ checkProgram sts k
  435. newtype Redefinition = Redefinition { getRedefName :: Name }
  436. deriving (Show, Typeable, Exception)
  437. data WhenCheckingEndpoint = WhenCheckingEndpoint { leftEndp :: Value, rightEndp :: Value, whichIsWrong :: NFEndp, exc :: SomeException }
  438. deriving (Show, Typeable, Exception)
  439. data UnsaturatedCon = UnsaturatedCon { theConstr :: Name }
  440. deriving (Show, Typeable)
  441. deriving anyclass (Exception)
  442. data NotACon = NotACon { theNotConstr :: Name }
  443. deriving (Show, Typeable)
  444. deriving anyclass (Exception)