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.

624 lines
22 KiB

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