|
|
@ -1,6 +1,7 @@ |
|
|
|
{-# LANGUAGE LambdaCase #-} |
|
|
|
{-# LANGUAGE DeriveAnyClass #-} |
|
|
|
{-# LANGUAGE ScopedTypeVariables #-} |
|
|
|
{-# LANGUAGE ViewPatterns #-} |
|
|
|
module Elab.Eval where |
|
|
|
|
|
|
|
import Control.Monad.Reader |
|
|
@ -31,21 +32,24 @@ import Syntax |
|
|
|
import System.IO.Unsafe |
|
|
|
|
|
|
|
import {-# SOURCE #-} Elab.WiredIn |
|
|
|
import GHC.Stack |
|
|
|
|
|
|
|
eval :: Term -> ElabM Value |
|
|
|
eval t = asks (flip eval' t) |
|
|
|
|
|
|
|
forceIO :: MonadIO m => Value -> m Value |
|
|
|
forceIO vl@(VNe (HMeta (MV _ cell)) args) = do |
|
|
|
forceIO mv@(VNe (HMeta (MV id cell)) args) = do |
|
|
|
solved <- liftIO $ readIORef cell |
|
|
|
case solved of |
|
|
|
Just vl -> forceIO $ foldl applProj vl args |
|
|
|
Nothing -> pure vl |
|
|
|
Nothing -> pure mv |
|
|
|
forceIO (VComp line phi u a0) = comp line <$> forceIO phi <*> pure u <*> pure a0 |
|
|
|
forceIO x = pure x |
|
|
|
|
|
|
|
applProj :: Value -> Projection -> Value |
|
|
|
applProj fun (PApp p arg) = vApp p fun arg |
|
|
|
applProj fun (PIElim l x y i) = ielim l x y fun i |
|
|
|
applProj fun (POuc a phi u) = outS a phi u fun |
|
|
|
applProj fun PProj1 = vProj1 fun |
|
|
|
applProj fun PProj2 = vProj2 fun |
|
|
|
|
|
|
@ -66,6 +70,7 @@ zonkIO (VNe hd sp) = do |
|
|
|
where |
|
|
|
zonkSp (PApp p x) = PApp p <$> zonkIO x |
|
|
|
zonkSp (PIElim l x y i) = PIElim <$> zonkIO l <*> zonkIO x <*> zonkIO y <*> zonkIO i |
|
|
|
zonkSp (POuc a phi u) = POuc <$> zonkIO a <*> zonkIO phi <*> zonkIO u |
|
|
|
zonkSp PProj1 = pure PProj1 |
|
|
|
zonkSp PProj2 = pure PProj2 |
|
|
|
zonkIO (VLam p (Closure s k)) = pure $ VLam p (Closure s (zonk . k)) |
|
|
@ -74,7 +79,7 @@ zonkIO (VSigma d (Closure s k)) = VSigma <$> zonkIO d <*> pure (Closure s (zonk |
|
|
|
zonkIO (VPair a b) = VPair <$> zonkIO a <*> zonkIO b |
|
|
|
|
|
|
|
zonkIO (VPath line x y) = VPath <$> zonkIO line <*> zonkIO x <*> zonkIO y |
|
|
|
zonkIO (VLine line f) = VLine <$> zonkIO line <*> zonkIO f |
|
|
|
zonkIO (VLine line x y f) = VLine <$> zonkIO line <*> zonkIO x <*> zonkIO y <*> zonkIO f |
|
|
|
|
|
|
|
-- Sorts |
|
|
|
zonkIO VType = pure VType |
|
|
@ -95,15 +100,18 @@ zonkIO VItIsOne = pure VItIsOne |
|
|
|
|
|
|
|
zonkIO (VPartial x y) = VPartial <$> zonkIO x <*> zonkIO y |
|
|
|
zonkIO (VPartialP x y) = VPartialP <$> zonkIO x <*> zonkIO y |
|
|
|
zonkIO (VSystem fs) = |
|
|
|
do |
|
|
|
t <- for (Map.toList fs) $ \(a, b) -> (,) <$> zonkIO a <*> zonkIO b |
|
|
|
pure (mkVSystem (Map.fromList t)) |
|
|
|
where |
|
|
|
mkVSystem map = |
|
|
|
case Map.lookup VI1 map of |
|
|
|
Just x -> x |
|
|
|
Nothing -> VSystem map |
|
|
|
zonkIO (VSystem fs) = do |
|
|
|
t <- for (Map.toList fs) $ \(a, b) -> (,) <$> zonkIO a <*> zonkIO b |
|
|
|
pure (mkVSystem (Map.fromList t)) |
|
|
|
zonkIO (VSub a b c) = VSub <$> zonkIO a <*> zonkIO b <*> zonkIO c |
|
|
|
zonkIO (VInc a b c) = VInc <$> zonkIO a <*> zonkIO b <*> zonkIO c |
|
|
|
zonkIO (VComp a b c d) = comp <$> zonkIO a <*> zonkIO b <*> zonkIO c <*> zonkIO d |
|
|
|
|
|
|
|
mkVSystem :: Map.Map Value Value -> Value |
|
|
|
mkVSystem map = |
|
|
|
case Map.lookup VI1 map of |
|
|
|
Just x -> x |
|
|
|
Nothing -> VSystem (Map.filterWithKey (\k _ -> k /= VI0) map) |
|
|
|
|
|
|
|
zonk :: Value -> Value |
|
|
|
zonk = unsafePerformIO . zonkIO |
|
|
@ -112,7 +120,7 @@ eval' :: ElabEnv -> Term -> Value |
|
|
|
eval' env (Ref x) = |
|
|
|
case Map.lookup x (getEnv env) of |
|
|
|
Just (_, vl) -> vl |
|
|
|
_ -> error "variable not in scope when evaluating" |
|
|
|
_ -> VVar x |
|
|
|
eval' env (App p f x) = vApp p (eval' env f) (eval' env x) |
|
|
|
|
|
|
|
eval' env (Lam p s t) = |
|
|
@ -146,7 +154,7 @@ eval' e (INot x) = inot (eval' e x) |
|
|
|
|
|
|
|
eval' e (PathP l a b) = VPath (eval' e l) (eval' e a) (eval' e b) |
|
|
|
eval' e (IElim l x y f i) = ielim (eval' e l) (eval' e x) (eval' e y) (eval' e f) (eval' e i) |
|
|
|
eval' e (PathIntro p f) = VLine (eval' e p) (eval' e f) |
|
|
|
eval' e (PathIntro p x y f) = VLine (eval' e p) (eval' e x) (eval' e y) (eval' e f) |
|
|
|
|
|
|
|
eval' e (IsOne i) = VIsOne (eval' e i) |
|
|
|
eval' e (IsOne1 i) = VIsOne1 (eval' e i) |
|
|
@ -157,31 +165,40 @@ eval' e (Partial x y) = VPartial (eval' e x) (eval' e y) |
|
|
|
eval' e (PartialP x y) = VPartialP (eval' e x) (eval' e y) |
|
|
|
eval' e (System fs) = VSystem (Map.fromList $ map (\(x, y) -> (eval' e x, eval' e y)) $ Map.toList $ fs) |
|
|
|
|
|
|
|
vApp :: Plicity -> Value -> Value -> Value |
|
|
|
eval' e (Sub a phi u) = VSub (eval' e a) (eval' e phi) (eval' e u) |
|
|
|
eval' e (Inc a phi u) = VInc (eval' e a) (eval' e phi) (eval' e u) |
|
|
|
eval' e (Ouc a phi u x) = outS (eval' e a) (eval' e phi) (eval' e u) (eval' e x) |
|
|
|
|
|
|
|
eval' e (Comp a phi u a0) = comp (eval' e a) (eval' e phi) (eval' e u) (eval' e a0) |
|
|
|
|
|
|
|
vApp :: HasCallStack => Plicity -> Value -> Value -> Value |
|
|
|
vApp p (VLam p' k) arg |
|
|
|
| p == p' = clCont k arg |
|
|
|
| otherwise = error $ "wrong plicity " ++ show p ++ " vs " ++ show p' ++ " in app " ++ show (App p (quote (VLam p' k)) (quote arg)) |
|
|
|
vApp p (VNe h sp) arg = VNe h (sp Seq.:|> PApp p arg) |
|
|
|
vApp p (VSystem fs) arg = VSystem (fmap (flip (vApp p) arg) fs) |
|
|
|
vApp _ x _ = error $ "can't apply " ++ show x |
|
|
|
|
|
|
|
(@@) :: Value -> Value -> Value |
|
|
|
(@@) :: HasCallStack => Value -> Value -> Value |
|
|
|
(@@) = vApp Ex |
|
|
|
infixl 9 @@ |
|
|
|
|
|
|
|
vProj1 :: Value -> Value |
|
|
|
vProj1 (VPair a _) = a |
|
|
|
vProj1 (VNe h sp) = VNe h (sp Seq.:|> PProj1) |
|
|
|
vProj1 (VSystem fs) = VSystem (fmap vProj1 fs) |
|
|
|
vProj1 x = error $ "can't proj1 " ++ show x |
|
|
|
|
|
|
|
vProj2 :: Value -> Value |
|
|
|
vProj2 (VPair _ b) = b |
|
|
|
vProj2 (VNe h sp) = VNe h (sp Seq.:|> PProj2) |
|
|
|
vProj2 (VSystem fs) = VSystem (fmap vProj2 fs) |
|
|
|
vProj2 x = error $ "can't proj2 " ++ show x |
|
|
|
|
|
|
|
data NotEqual = NotEqual Value Value |
|
|
|
deriving (Show, Typeable, Exception) |
|
|
|
|
|
|
|
unify' :: Value -> Value -> ElabM () |
|
|
|
unify' :: HasCallStack => Value -> Value -> ElabM () |
|
|
|
unify' topa topb = join $ go <$> forceIO topa <*> forceIO topb where |
|
|
|
go (VNe (HMeta mv) sp) rhs = solveMeta mv sp rhs |
|
|
|
go rhs (VNe (HMeta mv) sp) = solveMeta mv sp rhs |
|
|
@ -189,18 +206,23 @@ unify' topa topb = join $ go <$> forceIO topa <*> forceIO topb where |
|
|
|
go (VNe x a) (VNe x' a') |
|
|
|
| x == x', length a == length a' = |
|
|
|
traverse_ (uncurry unify'Spine) (Seq.zip a a') |
|
|
|
| x == HVar (Bound (T.pack "y")), x' == HVar (Bound (T.pack "A")) = error "what" |
|
|
|
|
|
|
|
go (VNe _hd (_ Seq.:|> PIElim _l x y i)) rhs = |
|
|
|
go lhs@(VNe _hd (_ Seq.:|> PIElim _l x y i)) rhs = |
|
|
|
case force i of |
|
|
|
VI0 -> unify' x rhs |
|
|
|
VI1 -> unify' y rhs |
|
|
|
_ -> fail |
|
|
|
_ -> case rhs of |
|
|
|
VSystem sys -> goSystem (flip unify') sys lhs |
|
|
|
_ -> fail |
|
|
|
|
|
|
|
go rhs (VNe _hd (_ Seq.:|> PIElim _l x y i)) = |
|
|
|
go lhs rhs@(VNe _hd (_ Seq.:|> PIElim _l x y i)) = |
|
|
|
case force i of |
|
|
|
VI0 -> unify' rhs x |
|
|
|
VI1 -> unify' rhs y |
|
|
|
_ -> fail |
|
|
|
VI0 -> unify' lhs x |
|
|
|
VI1 -> unify' lhs y |
|
|
|
_ -> case lhs of |
|
|
|
VSystem sys -> goSystem unify' sys rhs |
|
|
|
_ -> fail |
|
|
|
|
|
|
|
go (VLam p (Closure _ k)) vl = do |
|
|
|
t <- VVar . Bound <$> newName |
|
|
@ -233,13 +255,13 @@ unify' topa topb = join $ go <$> forceIO topa <*> forceIO topb where |
|
|
|
unify' x x' |
|
|
|
unify' y y' |
|
|
|
|
|
|
|
go (VLine l p) p' = do |
|
|
|
go (VLine l x y p) p' = do |
|
|
|
n <- VVar . Bound <$> newName |
|
|
|
unify (p @@ n) (ielim l (l @@ VI0) (l @@ VI1) p' n) |
|
|
|
unify (p @@ n) (ielim l x y p' n) |
|
|
|
|
|
|
|
go p' (VLine l p) = do |
|
|
|
go p' (VLine l x y p) = do |
|
|
|
n <- VVar . Bound <$> newName |
|
|
|
unify (ielim l (l @@ VI0) (l @@ VI1) p' n) (p @@ n) |
|
|
|
unify (ielim l x y p' n) (p @@ n) |
|
|
|
|
|
|
|
go (VIsOne x) (VIsOne y) = unify' x y |
|
|
|
|
|
|
@ -254,12 +276,30 @@ unify' topa topb = join $ go <$> forceIO topa <*> forceIO topb where |
|
|
|
go (VPartial phi r) (VPartial phi' r') = unify' phi phi' *> unify r r' |
|
|
|
go (VPartialP phi r) (VPartialP phi' r') = unify' phi phi' *> unify r r' |
|
|
|
|
|
|
|
go (VSub a phi u) (VSub a' phi' u') = traverse_ (uncurry unify') [(a, a'), (phi, phi'), (u, u')] |
|
|
|
go (VInc a phi u) (VInc a' phi' u') = traverse_ (uncurry unify') [(a, a'), (phi, phi'), (u, u')] |
|
|
|
|
|
|
|
go (VComp a phi u a0) (VComp a' phi' u' a0') = |
|
|
|
traverse_ (uncurry unify') [(a, a'), (phi, phi'), (u, u'), (a0, a0')] |
|
|
|
|
|
|
|
go (VSystem sys) rhs = goSystem unify' sys rhs |
|
|
|
go rhs (VSystem sys) = goSystem (flip unify') sys rhs |
|
|
|
|
|
|
|
go x y = |
|
|
|
case (toDnf x, toDnf y) of |
|
|
|
(Just xs, Just ys) -> unify'Formula xs ys |
|
|
|
_ -> fail |
|
|
|
|
|
|
|
fail = liftIO . throwIO $ NotEqual topa topb |
|
|
|
goSystem :: (Value -> Value -> ElabM ()) -> Map.Map Value Value -> Value -> ElabM () |
|
|
|
goSystem k sys rhs = do |
|
|
|
let rhs_q = quote rhs |
|
|
|
env <- ask |
|
|
|
for_ (Map.toList sys) $ \(f, i) -> do |
|
|
|
let i_q = quote i |
|
|
|
for (truthAssignments f (getEnv env)) $ \e -> |
|
|
|
k (eval' env{getEnv = e} i_q) (eval' env{getEnv = e} rhs_q) |
|
|
|
|
|
|
|
fail = throwElab $ NotEqual topa topb |
|
|
|
|
|
|
|
unify'Spine (PApp a v) (PApp a' v') |
|
|
|
| a == a' = unify' v v' |
|
|
@ -268,6 +308,8 @@ unify' topa topb = join $ go <$> forceIO topa <*> forceIO topb where |
|
|
|
unify'Spine PProj2 PProj2 = pure () |
|
|
|
|
|
|
|
unify'Spine (PIElim _ _ _ i) (PIElim _ _ _ j) = unify' i j |
|
|
|
unify'Spine (POuc a phi u) (POuc a' phi' u') = |
|
|
|
traverse_ (uncurry unify') [(a, a'), (phi, phi'), (u, u')] |
|
|
|
|
|
|
|
unify'Spine _ _ = fail |
|
|
|
|
|
|
@ -275,7 +317,7 @@ unify' topa topb = join $ go <$> forceIO topa <*> forceIO topb where |
|
|
|
| compareDNFs x y = pure () |
|
|
|
| otherwise = fail |
|
|
|
|
|
|
|
unify :: Value -> Value -> ElabM () |
|
|
|
unify :: HasCallStack => Value -> Value -> ElabM () |
|
|
|
unify a b = unify' a b `catchElab` \(_ :: NotEqual) -> liftIO $ throwIO (NotEqual a b) |
|
|
|
|
|
|
|
isConvertibleTo :: Value -> Value -> ElabM (Term -> Term) |
|
|
@ -338,7 +380,7 @@ checkScope scope (VNe h sp) = |
|
|
|
do |
|
|
|
case h of |
|
|
|
HVar v@Bound{} -> |
|
|
|
unless (v `Set.member` scope) . liftIO . throwIO $ |
|
|
|
unless (v `Set.member` scope) . throwElab $ |
|
|
|
NotInScope v |
|
|
|
HVar{} -> pure () |
|
|
|
HMeta{} -> pure () |
|
|
@ -346,6 +388,7 @@ checkScope scope (VNe h sp) = |
|
|
|
where |
|
|
|
checkProj (PApp _ t) = checkScope scope t |
|
|
|
checkProj (PIElim l x y i) = traverse_ (checkScope scope) [l, x, y, i] |
|
|
|
checkProj (POuc a phi u) = traverse_ (checkScope scope) [a, phi, u] |
|
|
|
checkProj PProj1 = pure () |
|
|
|
checkProj PProj2 = pure () |
|
|
|
|
|
|
@ -374,7 +417,7 @@ checkScope s (VIOr x y) = traverse_ (checkScope s) [x, y] |
|
|
|
checkScope s (VINot x) = checkScope s x |
|
|
|
|
|
|
|
checkScope s (VPath line a b) = traverse_ (checkScope s) [line, a, b] |
|
|
|
checkScope s (VLine _ line) = checkScope s line |
|
|
|
checkScope s (VLine _ _ _ line) = checkScope s line |
|
|
|
|
|
|
|
checkScope s (VIsOne x) = checkScope s x |
|
|
|
checkScope s (VIsOne1 x) = checkScope s x |
|
|
@ -386,15 +429,19 @@ checkScope s (VPartialP x y) = traverse_ (checkScope s) [x, y] |
|
|
|
checkScope s (VSystem fs) = |
|
|
|
for_ (Map.toList fs) $ \(x, y) -> traverse_ (checkScope s) [x, y] |
|
|
|
|
|
|
|
checkScope s (VSub a b c) = traverse_ (checkScope s) [a, b, c] |
|
|
|
checkScope s (VInc a b c) = traverse_ (checkScope s) [a, b, c] |
|
|
|
checkScope s (VComp a phi u a0) = traverse_ (checkScope s) [a, phi, u, a0] |
|
|
|
|
|
|
|
checkSpine :: Set Name -> Seq Projection -> ElabM [T.Text] |
|
|
|
checkSpine scope (PApp Ex (VVar n@(Bound t)) Seq.:<| xs) |
|
|
|
| n `Set.member` scope = liftIO . throwIO $ NonLinearSpine n |
|
|
|
| n `Set.member` scope = throwElab $ NonLinearSpine n |
|
|
|
| otherwise = (t:) <$> checkSpine scope xs |
|
|
|
checkSpine _ (p Seq.:<| _) = liftIO . throwIO $ SpineProj p |
|
|
|
checkSpine _ (p Seq.:<| _) = throwElab $ SpineProj p |
|
|
|
checkSpine _ Seq.Empty = pure [] |
|
|
|
|
|
|
|
newtype NonLinearSpine = NonLinearSpine { getDupeName :: Name } |
|
|
|
deriving (Show, Typeable, Exception) |
|
|
|
|
|
|
|
newtype SpineProjection = SpineProj { getSpineProjection :: Projection } |
|
|
|
deriving (Show, Typeable, Exception) |
|
|
|
deriving (Show, Typeable, Exception) |