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.

622 lines
22 KiB

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