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.

446 lines
14 KiB

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