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.

540 lines
18 KiB

  1. {-# LANGUAGE BlockArguments #-}
  2. {-# LANGUAGE LambdaCase #-}
  3. {-# LANGUAGE DeriveAnyClass #-}
  4. {-# LANGUAGE ScopedTypeVariables #-}
  5. {-# LANGUAGE ViewPatterns #-}
  6. {-# LANGUAGE TupleSections #-}
  7. module Elab.Eval where
  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.Sequence (Seq)
  15. import Data.Traversable
  16. import Data.Set (Set)
  17. import Data.Typeable
  18. import Data.Foldable
  19. import Data.IORef
  20. import Data.Maybe
  21. import Elab.Eval.Formula
  22. import Elab.Monad
  23. import GHC.Stack
  24. import Presyntax.Presyntax (Plicity(..))
  25. import Prettyprinter
  26. import Syntax.Pretty
  27. import Syntax
  28. import System.IO.Unsafe
  29. import {-# SOURCE #-} Elab.WiredIn
  30. import Debug.Trace
  31. import Data.List (sortOn)
  32. eval :: Term -> ElabM Value
  33. eval t = asks (flip eval' t)
  34. forceIO :: MonadIO m => Value -> m Value
  35. forceIO mv@(VNe (HMeta (mvCell -> cell)) args) = do
  36. solved <- liftIO $ readIORef cell
  37. case solved of
  38. Just vl -> forceIO (foldl applProj vl args)
  39. Nothing -> pure mv
  40. forceIO vl@(VSystem fs) =
  41. case Map.lookup VI1 fs of
  42. Just x -> forceIO x
  43. Nothing -> pure vl
  44. forceIO (GluedVl _ _ vl) = forceIO vl
  45. forceIO (VComp line phi u a0) = comp <$> forceIO line <*> forceIO phi <*> pure u <*> pure a0
  46. forceIO x = pure x
  47. applProj :: Value -> Projection -> Value
  48. applProj fun (PApp p arg) = vApp p fun arg
  49. applProj fun (PIElim l x y i) = ielim l x y fun i
  50. applProj fun (POuc a phi u) = outS a phi u fun
  51. applProj fun PProj1 = vProj1 fun
  52. applProj fun PProj2 = vProj2 fun
  53. force :: Value -> Value
  54. force = unsafePerformIO . forceIO
  55. -- everywhere force
  56. zonkIO :: Value -> IO Value
  57. zonkIO (VNe hd sp) = do
  58. sp' <- traverse zonkSp sp
  59. case hd of
  60. HMeta (mvCell -> cell) -> do
  61. solved <- liftIO $ readIORef cell
  62. case solved of
  63. Just vl -> zonkIO $ foldl applProj vl sp'
  64. Nothing -> pure $ VNe hd sp'
  65. hd -> pure $ VNe hd sp'
  66. zonkIO (GluedVl h sp vl) = GluedVl h <$> traverse zonkSp sp <*> zonkIO vl
  67. zonkIO (VLam p (Closure s k)) = pure $ VLam p (Closure s (zonk . k))
  68. zonkIO (VPi p d (Closure s k)) = VPi p <$> zonkIO d <*> pure (Closure s (zonk . k))
  69. zonkIO (VSigma d (Closure s k)) = VSigma <$> zonkIO d <*> pure (Closure s (zonk . k))
  70. zonkIO (VPair a b) = VPair <$> zonkIO a <*> zonkIO b
  71. zonkIO (VPath line x y) = VPath <$> zonkIO line <*> zonkIO x <*> zonkIO y
  72. zonkIO (VLine line x y f) = VLine <$> zonkIO line <*> zonkIO x <*> zonkIO y <*> zonkIO f
  73. -- Sorts
  74. zonkIO VType = pure VType
  75. zonkIO VTypeω = pure VTypeω
  76. zonkIO VI = pure VI
  77. zonkIO VI0 = pure VI0
  78. zonkIO VI1 = pure VI1
  79. zonkIO (VIAnd x y) = iand <$> zonkIO x <*> zonkIO y
  80. zonkIO (VIOr x y) = ior <$> zonkIO x <*> zonkIO y
  81. zonkIO (VINot x) = inot <$> zonkIO x
  82. zonkIO (VIsOne x) = VIsOne <$> zonkIO x
  83. zonkIO VItIsOne = pure VItIsOne
  84. zonkIO (VPartial x y) = VPartial <$> zonkIO x <*> zonkIO y
  85. zonkIO (VPartialP x y) = VPartialP <$> zonkIO x <*> zonkIO y
  86. zonkIO (VSystem fs) = do
  87. t <- for (Map.toList fs) $ \(a, b) -> (,) <$> zonkIO a <*> zonkIO b
  88. pure (mkVSystem (Map.fromList t))
  89. zonkIO (VSub a b c) = VSub <$> zonkIO a <*> zonkIO b <*> zonkIO c
  90. zonkIO (VInc a b c) = VInc <$> zonkIO a <*> zonkIO b <*> zonkIO c
  91. zonkIO (VComp a b c d) = comp <$> zonkIO a <*> zonkIO b <*> zonkIO c <*> zonkIO d
  92. zonkIO (VHComp a b c d) = hComp <$> zonkIO a <*> zonkIO b <*> zonkIO c <*> zonkIO d
  93. zonkIO (VGlueTy a phi ty e) = glueType <$> zonkIO a <*> zonkIO phi <*> zonkIO ty <*> zonkIO e
  94. zonkIO (VGlue a phi ty e t x) = glueElem <$> zonkIO a <*> zonkIO phi <*> zonkIO ty <*> zonkIO e <*> zonkIO t <*> zonkIO x
  95. zonkIO (VUnglue a phi ty e x) = unglue <$> zonkIO a <*> zonkIO phi <*> zonkIO ty <*> zonkIO e <*> zonkIO x
  96. zonkIO (VCase t x xs) = VCase <$> zonkIO t <*> zonkIO x <*> pure xs
  97. zonkSp :: Projection -> IO Projection
  98. zonkSp (PApp p x) = PApp p <$> zonkIO x
  99. zonkSp (PIElim l x y i) = PIElim <$> zonkIO l <*> zonkIO x <*> zonkIO y <*> zonkIO i
  100. zonkSp (POuc a phi u) = POuc <$> zonkIO a <*> zonkIO phi <*> zonkIO u
  101. zonkSp PProj1 = pure PProj1
  102. zonkSp PProj2 = pure PProj2
  103. mkVSystem :: Map.Map Value Value -> Value
  104. mkVSystem vals =
  105. let map' = Map.fromList (map (\(a, b) -> (force a, b)) (Map.toList vals)) in
  106. case Map.lookup VI1 map' of
  107. Just x -> x
  108. Nothing -> VSystem (Map.filterWithKey (\k _ -> k /= VI0) map')
  109. zonk :: Value -> Value
  110. zonk = unsafePerformIO . zonkIO
  111. eval' :: ElabEnv -> Term -> Value
  112. eval' env (Ref x) =
  113. case Map.lookup x (getEnv env) of
  114. Just (_, vl) -> vl
  115. _ -> VNe (HVar x) mempty
  116. eval' env (Con x) =
  117. case Map.lookup x (getEnv env) of
  118. Just (ty, _) -> VNe (HCon ty x) mempty
  119. Nothing -> error $ "constructor " ++ show x ++ " has no type in scope"
  120. eval' env (PCon sys x) =
  121. case Map.lookup x (getEnv env) of
  122. Just (ty, _) -> VNe (HPCon (eval' env sys) ty x) mempty
  123. Nothing -> error $ "constructor " ++ show x ++ " has no type in scope"
  124. eval' _ (Data n x) = VNe (HData n x) mempty
  125. eval' env (App p f x) = vApp p (eval' env f) (eval' env x)
  126. eval' env (Lam p s t) =
  127. VLam p $ Closure s $ \a ->
  128. eval' env { getEnv = Map.insert s (error "type of abs", a) (getEnv env) } t
  129. eval' env (Pi p s d t) =
  130. VPi p (eval' env d) $ Closure s $ \a ->
  131. eval' env { getEnv = (Map.insert s (error "type of abs", a) (getEnv env))} t
  132. eval' _ (Meta m) = VNe (HMeta m) mempty
  133. eval' env (Sigma s d t) =
  134. VSigma (eval' env d) $ Closure s $ \a ->
  135. eval' env { getEnv = Map.insert s (error "type of abs", a) (getEnv env) } t
  136. eval' e (Pair a b) = VPair (eval' e a) (eval' e b)
  137. eval' e (Proj1 a) = vProj1 (eval' e a)
  138. eval' e (Proj2 a) = vProj2 (eval' e a)
  139. eval' _ Type = VType
  140. eval' _ Typeω = VTypeω
  141. eval' _ I = VI
  142. eval' _ I0 = VI0
  143. eval' _ I1 = VI1
  144. eval' e (IAnd x y) = iand (eval' e x) (eval' e y)
  145. eval' e (IOr x y) = ior (eval' e x) (eval' e y)
  146. eval' e (INot x) = inot (eval' e x)
  147. eval' e (PathP l a b) = VPath (eval' e l) (eval' e a) (eval' e b)
  148. eval' e (IElim l x y f i) = ielim (eval' e l) (eval' e x) (eval' e y) (eval' e f) (eval' e i)
  149. eval' e (PathIntro p x y f) = VLine (eval' e p) (eval' e x) (eval' e y) (eval' e f)
  150. eval' e (IsOne i) = VIsOne (eval' e i)
  151. eval' _ ItIsOne = VItIsOne
  152. eval' e (Partial x y) = VPartial (eval' e x) (eval' e y)
  153. eval' e (PartialP x y) = VPartialP (eval' e x) (eval' e y)
  154. eval' e (System fs) = VSystem (Map.fromList $ map (\(x, y) -> (eval' e x, eval' e y)) $ Map.toList $ fs)
  155. eval' e (Sub a phi u) = VSub (eval' e a) (eval' e phi) (eval' e u)
  156. eval' e (Inc a phi u) = VInc (eval' e a) (eval' e phi) (eval' e u)
  157. eval' e (Ouc a phi u x) = outS (eval' e a) (eval' e phi) (eval' e u) (eval' e x)
  158. eval' e (Comp a phi u a0) = comp (eval' e a) (eval' e phi) (eval' e u) (eval' e a0)
  159. eval' e (HComp a phi u a0) = hComp (eval' e a) (eval' e phi) (eval' e u) (eval' e a0)
  160. eval' e (GlueTy a phi tys f) = glueType (eval' e a) (eval' e phi) (eval' e tys) (eval' e f)
  161. eval' e (Glue a phi tys eqvs t x) = glueElem (eval' e a) (eval' e phi) (eval' e tys) (eval' e eqvs) (eval' e t) (eval' e x)
  162. eval' e (Unglue a phi tys f x) = unglue (eval' e a) (eval' e phi) (eval' e tys) (eval' e f) (eval' e x)
  163. eval' e (Let ns x) =
  164. let env' = foldl (\newe (n, ty, x) -> newe { getEnv = Map.insert n (eval' newe ty, eval' newe x) (getEnv newe) }) e ns
  165. in eval' env' x
  166. eval' e (Case range sc xs) = evalCase e (eval' e range @@) (force (eval' e sc)) xs
  167. evalCase :: ElabEnv -> (Value -> Value) -> Value -> [(Term, Term)] -> Value
  168. evalCase _ _ sc [] = error $ "unmatched pattern for value: " ++ show (prettyTm (quote sc))
  169. evalCase env rng (VHComp a phi u a0) cases =
  170. comp (fun \i -> rng (v i)) phi (system \i is1 -> evalCase env rng (u @@ i @@ is1) cases)
  171. (VInc (rng a) phi (evalCase env rng (outS a0 phi (u @@ VI0) a0) cases))
  172. where
  173. v = Elab.WiredIn.fill a phi u a0
  174. evalCase env _ sc ((Ref _, k):_) = eval' env k @@ sc
  175. evalCase env rng (val@(VNe (HCon _ x) sp)) ((Con x', k):xs)
  176. | x == x' = foldl applProj (eval' env k) sp
  177. | otherwise = evalCase env rng val xs
  178. evalCase env rng (val@(VNe (HPCon _ _ x) sp)) ((Con x', k):xs)
  179. | x == x' = foldl applProj (eval' env k) sp
  180. | otherwise = evalCase env rng val xs
  181. evalCase _ rng sc xs = VCase (fun rng) sc xs
  182. vApp :: HasCallStack => Plicity -> Value -> Value -> Value
  183. vApp p (VLam p' k) arg
  184. | p == p' = clCont k arg
  185. | otherwise = error $ "wrong plicity " ++ show p ++ " vs " ++ show p' ++ " in app " ++ show (App p (quote (VLam p' k)) (quote arg))
  186. vApp p (VNe h sp) arg = VNe h (sp Seq.:|> PApp p arg)
  187. vApp p (GluedVl h sp vl) arg = GluedVl h (sp Seq.:|> PApp p arg) (vApp p vl arg)
  188. vApp p (VSystem fs) arg = VSystem (fmap (flip (vApp p) arg) fs)
  189. vApp p (VInc (VPi _ _ (Closure _ r)) phi f) arg = VInc (r (vApp p f arg)) phi (vApp p f arg)
  190. vApp _ x _ = error $ "can't apply " ++ show (prettyTm (quote x))
  191. (@@) :: HasCallStack => Value -> Value -> Value
  192. (@@) = vApp Ex
  193. infixl 9 @@
  194. vProj1 :: HasCallStack => Value -> Value
  195. vProj1 (VPair a _) = a
  196. vProj1 (VNe h sp) = VNe h (sp Seq.:|> PProj1)
  197. vProj1 (GluedVl h sp vl) = GluedVl h (sp Seq.:|> PProj1) (vProj1 vl)
  198. vProj1 (VSystem fs) = VSystem (fmap vProj1 fs)
  199. vProj1 (VInc (VSigma a _) b c) = VInc a b (vProj1 c)
  200. vProj1 x = error $ "can't proj1 " ++ show (prettyTm (quote x))
  201. vProj2 :: HasCallStack => Value -> Value
  202. vProj2 (VPair _ b) = b
  203. vProj2 (VNe h sp) = VNe h (sp Seq.:|> PProj2)
  204. vProj2 (GluedVl h sp vl) = GluedVl h (sp Seq.:|> PProj2) (vProj2 vl)
  205. vProj2 (VSystem fs) = VSystem (fmap vProj2 fs)
  206. vProj2 (VInc (VSigma _ (Closure _ r)) b c) = VInc (r (vProj1 c)) b (vProj2 c)
  207. vProj2 x = error $ "can't proj2 " ++ show (prettyTm (quote x))
  208. data NotEqual = NotEqual Value Value
  209. deriving (Show, Typeable, Exception)
  210. unify' :: HasCallStack => Value -> Value -> ElabM ()
  211. unify' topa topb = join $ go <$> forceIO topa <*> forceIO topb where
  212. go (VNe (HMeta mv) sp) rhs = solveMeta mv sp rhs
  213. go rhs (VNe (HMeta mv) sp) = solveMeta mv sp rhs
  214. go (VNe (HPCon s _ _) _) rhs
  215. | VSystem _ <- s = go (force s) rhs
  216. go lhs (VNe (HPCon s _ _) _)
  217. | VSystem _ <- s = go lhs (force s)
  218. go (VNe x a) (VNe x' a')
  219. | x == x', length a == length a' =
  220. traverse_ (uncurry unify'Spine) (Seq.zip a a')
  221. go (VLam p (Closure n k)) vl = do
  222. t <- VVar <$> newName' n
  223. unify' (k t) (vApp p vl t)
  224. go vl (VLam p (Closure n k)) = do
  225. t <- VVar <$> newName' n
  226. unify' (vApp p vl t) (k t)
  227. go (VPair a b) vl = unify' a (vProj1 vl) *> unify' b (vProj2 vl)
  228. go vl (VPair a b) = unify' (vProj1 vl) a *> unify' (vProj2 vl) b
  229. go (VPi p d (Closure _ k)) (VPi p' d' (Closure _ k')) | p == p' = do
  230. t <- VVar <$> newName
  231. unify' d d'
  232. unify' (k t) (k' t)
  233. go (VSigma d (Closure _ k)) (VSigma d' (Closure _ k')) = do
  234. t <- VVar <$> newName
  235. unify' d d'
  236. unify' (k t) (k' t)
  237. go VType VType = pure ()
  238. go VTypeω VTypeω = pure ()
  239. go VI VI = pure ()
  240. go (VPath l x y) (VPath l' x' y') = do
  241. unify' l l'
  242. unify' x x'
  243. unify' y y'
  244. go (VLine l x y p) p' = do
  245. n <- VVar <$> newName
  246. unify' (p @@ n) (ielim l x y p' n)
  247. go p' (VLine l x y p) = do
  248. n <- VVar <$> newName
  249. unify' (ielim l x y p' n) (p @@ n)
  250. go (VIsOne x) (VIsOne y) = unify' x y
  251. -- IsOne is proof-irrelevant:
  252. go VItIsOne _ = pure ()
  253. go _ VItIsOne = pure ()
  254. go (VPartial phi r) (VPartial phi' r') = unify' phi phi' *> unify' r r'
  255. go (VPartialP phi r) (VPartialP phi' r') = unify' phi phi' *> unify' r r'
  256. go (VSub a phi u) (VSub a' phi' u') = traverse_ (uncurry unify') [(a, a'), (phi, phi'), (u, u')]
  257. go (VInc a phi u) (VInc a' phi' u') = traverse_ (uncurry unify') [(a, a'), (phi, phi'), (u, u')]
  258. go (VComp a phi u a0) (VComp a' phi' u' a0') =
  259. traverse_ (uncurry unify') [(a, a'), (phi, phi'), (u, u'), (a0, a0')]
  260. go (VGlueTy _ (force -> VI1) u _0) rhs = unify' (u @@ VItIsOne) rhs
  261. go lhs (VGlueTy _ (force -> VI1) u _0) = unify' lhs (u @@ VItIsOne)
  262. go (VGlueTy a phi u a0) (VGlueTy a' phi' u' a0') =
  263. traverse_ (uncurry unify') [(a, a'), (phi, phi'), (u, u'), (a0, a0')]
  264. go (VGlue a phi u a0 t x) (VGlue a' phi' u' a0' t' x') =
  265. traverse_ (uncurry unify') [(a, a'), (phi, phi'), (u, u'), (a0, a0'), (t, t'), (x, x')]
  266. go (VSystem sys) rhs = goSystem unify' sys rhs
  267. go rhs (VSystem sys) = goSystem (flip unify') sys rhs
  268. go (VCase _ a b) (VCase _ a' b') = do
  269. unify' a a'
  270. let go a b = join $ unify' <$> eval (snd a) <*> eval (snd b)
  271. zipWithM_ go (sortOn fst b) (sortOn fst b')
  272. go x y
  273. | x == y = pure ()
  274. | otherwise =
  275. case (toDnf x, toDnf y) of
  276. (Just xs, Just ys) -> unify'Formula xs ys
  277. _ -> fail
  278. goSystem :: (Value -> Value -> ElabM ()) -> Map.Map Value Value -> Value -> ElabM ()
  279. goSystem k sys rhs = do
  280. let rhs_q = quote rhs
  281. env <- ask
  282. for_ (Map.toList sys) $ \(f, i) -> do
  283. let i_q = quote i
  284. for (truthAssignments f (getEnv env)) $ \e ->
  285. k (eval' env{getEnv = e} i_q) (eval' env{getEnv = e} rhs_q)
  286. fail = throwElab $ NotEqual topa topb
  287. unify'Spine (PApp a v) (PApp a' v')
  288. | a == a' = unify' v v'
  289. unify'Spine PProj1 PProj1 = pure ()
  290. unify'Spine PProj2 PProj2 = pure ()
  291. unify'Spine (PIElim _ _ _ i) (PIElim _ _ _ j) = unify' i j
  292. unify'Spine (POuc a phi u) (POuc a' phi' u') =
  293. traverse_ (uncurry unify') [(a, a'), (phi, phi'), (u, u')]
  294. unify'Spine _ _ = fail
  295. unify'Formula x y
  296. | compareDNFs x y = pure ()
  297. | otherwise = fail
  298. unify :: HasCallStack => Value -> Value -> ElabM ()
  299. unify a b = unify' a b -- `catchElab` \(_ :: SomeException) -> liftIO $ throwIO (NotEqual a b)
  300. isConvertibleTo :: Value -> Value -> ElabM (Term -> Term)
  301. isConvertibleTo a b = isConvertibleTo (force a) (force b) where
  302. VPi Im d (Closure _v k) `isConvertibleTo` ty = do
  303. meta <- newMeta d
  304. cont <- k meta `isConvertibleTo` ty
  305. pure (\f -> cont (App Im f (quote meta)))
  306. VType `isConvertibleTo` VTypeω = pure id
  307. VPi p d (Closure _ k) `isConvertibleTo` VPi p' d' (Closure _ k') | p == p' = do
  308. wp <- d' `isConvertibleTo` d
  309. n <- newName
  310. wp_n <- eval (Lam Ex n (wp (Ref n)))
  311. wp' <- k (VVar n) `isConvertibleTo` k' (wp_n @@ VVar n)
  312. pure (\f -> Lam p n (wp' (App p f (wp (Ref n)))))
  313. isConvertibleTo a b = do
  314. unify' a b
  315. pure id
  316. newMeta :: Value -> ElabM Value
  317. newMeta dom = do
  318. loc <- liftM2 (,) <$> asks currentFile <*> asks currentSpan
  319. n <- newName
  320. c <- liftIO $ newIORef Nothing
  321. let m = MV (getNameText n) c dom (flatten <$> loc)
  322. flatten (x, (y, z)) = (x, y, z)
  323. env <- asks getEnv
  324. t <- for (Map.toList env) $ \(n, _) -> pure $
  325. case n of
  326. Bound{} -> Just (PApp Ex (VVar n))
  327. _ -> Nothing
  328. pure (VNe (HMeta m) (Seq.fromList (catMaybes t)))
  329. newName :: MonadIO m => m Name
  330. newName = liftIO $ do
  331. x <- atomicModifyIORef _nameCounter $ \x -> (x + 1, x + 1)
  332. pure (Bound (T.pack (show x)) x)
  333. newName' :: Name -> ElabM Name
  334. newName' n = do
  335. ~(Bound _ x) <- newName
  336. pure (Bound (getNameText n) x)
  337. _nameCounter :: IORef Int
  338. _nameCounter = unsafePerformIO $ newIORef 0
  339. {-# NOINLINE _nameCounter #-}
  340. solveMeta :: MV -> Seq Projection -> Value -> ElabM ()
  341. solveMeta m@(mvCell -> cell) sp rhs = do
  342. env <- ask
  343. names <- tryElab $ checkSpine Set.empty sp
  344. case names of
  345. Right names -> do
  346. checkScope (Set.fromList names) rhs
  347. `withNote` hsep [prettyTm (quote (VNe (HMeta m) sp)), pretty '≡', prettyTm (quote rhs)]
  348. let tm = quote rhs
  349. lam = eval' env $ foldr (Lam Ex) tm names
  350. liftIO . atomicModifyIORef' cell $ \case
  351. Just _ -> error "filled cell in solvedMeta"
  352. Nothing -> (Just lam, ())
  353. Left (_ :: SpineProjection) -> do
  354. liftIO . atomicModifyIORef' (unsolvedMetas env) $ \x -> (, ()) $
  355. case Map.lookup m x of
  356. Just qs -> Map.insert m ((sp, rhs):qs) x
  357. Nothing -> Map.insert m [(sp, rhs)] x
  358. checkScope :: Set Name -> Value -> ElabM ()
  359. checkScope scope (VNe h sp) =
  360. do
  361. case h of
  362. HVar v@Bound{} ->
  363. unless (v `Set.member` scope) . throwElab $
  364. NotInScope v
  365. HVar{} -> pure ()
  366. HCon{} -> pure ()
  367. HPCon{} -> pure ()
  368. HMeta{} -> pure ()
  369. HData{} -> pure ()
  370. traverse_ checkProj sp
  371. where
  372. checkProj (PApp _ t) = checkScope scope t
  373. checkProj (PIElim l x y i) = traverse_ (checkScope scope) [l, x, y, i]
  374. checkProj (POuc a phi u) = traverse_ (checkScope scope) [a, phi, u]
  375. checkProj PProj1 = pure ()
  376. checkProj PProj2 = pure ()
  377. checkScope scope (GluedVl _ _p vl) = checkScope scope vl
  378. checkScope scope (VLam _ (Closure n k)) =
  379. checkScope (Set.insert n scope) (k (VVar n))
  380. checkScope scope (VPi _ d (Closure n k)) = do
  381. checkScope scope d
  382. checkScope (Set.insert n scope) (k (VVar n))
  383. checkScope scope (VSigma d (Closure n k)) = do
  384. checkScope scope d
  385. checkScope (Set.insert n scope) (k (VVar n))
  386. checkScope s (VPair a b) = traverse_ (checkScope s) [a, b]
  387. checkScope _ VType = pure ()
  388. checkScope _ VTypeω = pure ()
  389. checkScope _ VI = pure ()
  390. checkScope _ VI0 = pure ()
  391. checkScope _ VI1 = pure ()
  392. checkScope s (VIAnd x y) = traverse_ (checkScope s) [x, y]
  393. checkScope s (VIOr x y) = traverse_ (checkScope s) [x, y]
  394. checkScope s (VINot x) = checkScope s x
  395. checkScope s (VPath line a b) = traverse_ (checkScope s) [line, a, b]
  396. checkScope s (VLine _ _ _ line) = checkScope s line
  397. checkScope s (VIsOne x) = checkScope s x
  398. checkScope _ VItIsOne = pure ()
  399. checkScope s (VPartial x y) = traverse_ (checkScope s) [x, y]
  400. checkScope s (VPartialP x y) = traverse_ (checkScope s) [x, y]
  401. checkScope s (VSystem fs) =
  402. for_ (Map.toList fs) $ \(x, y) -> traverse_ (checkScope s) [x, y]
  403. checkScope s (VSub a b c) = traverse_ (checkScope s) [a, b, c]
  404. checkScope s (VInc a b c) = traverse_ (checkScope s) [a, b, c]
  405. checkScope s (VComp a phi u a0) = traverse_ (checkScope s) [a, phi, u, a0]
  406. checkScope s (VHComp a phi u a0) = traverse_ (checkScope s) [a, phi, u, a0]
  407. checkScope s (VGlueTy a phi ty eq) = traverse_ (checkScope s) [a, phi, ty, eq]
  408. checkScope s (VGlue a phi ty eq inv x) = traverse_ (checkScope s) [a, phi, ty, eq, inv, x]
  409. checkScope s (VUnglue a phi ty eq vl) = traverse_ (checkScope s) [a, phi, ty, eq, vl]
  410. checkScope s (VCase _ v _) = checkScope s v
  411. checkSpine :: Set Name -> Seq Projection -> ElabM [Name]
  412. checkSpine scope (PApp Ex (VVar n@Bound{}) Seq.:<| xs)
  413. | n `Set.member` scope = throwElab $ NonLinearSpine n
  414. | otherwise = (n:) <$> checkSpine scope xs
  415. checkSpine _ (p Seq.:<| _) = throwElab $ SpineProj p
  416. checkSpine _ Seq.Empty = pure []
  417. newtype NonLinearSpine = NonLinearSpine { getDupeName :: Name }
  418. deriving (Show, Typeable, Exception)
  419. newtype SpineProjection = SpineProj { getSpineProjection :: Projection }
  420. deriving (Show, Typeable, Exception)