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.

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