|
@ -1,3 +1,4 @@ |
|
|
|
|
|
{-# LANGUAGE LambdaCase #-} |
|
|
{-# LANGUAGE BlockArguments #-} |
|
|
{-# LANGUAGE BlockArguments #-} |
|
|
{-# LANGUAGE TupleSections #-} |
|
|
{-# LANGUAGE TupleSections #-} |
|
|
{-# LANGUAGE DeriveAnyClass #-} |
|
|
{-# LANGUAGE DeriveAnyClass #-} |
|
@ -30,6 +31,7 @@ import Prettyprinter |
|
|
|
|
|
|
|
|
import Syntax.Pretty |
|
|
import Syntax.Pretty |
|
|
import Syntax |
|
|
import Syntax |
|
|
|
|
|
import Debug.Trace |
|
|
|
|
|
|
|
|
infer :: P.Expr -> ElabM (Term, NFType) |
|
|
infer :: P.Expr -> ElabM (Term, NFType) |
|
|
infer (P.Span ex a b) = withSpan a b $ infer ex |
|
|
infer (P.Span ex a b) = withSpan a b $ infer ex |
|
@ -194,52 +196,108 @@ check (P.LamSystem bs) ty = do |
|
|
mkB _ (Nothing, b) = b |
|
|
mkB _ (Nothing, b) = b |
|
|
pure (Lam P.Ex name (System (Map.fromList (map (\(_, (x, y)) -> (quote x, mkB name y)) eqns)))) |
|
|
pure (Lam P.Ex name (System (Map.fromList (map (\(_, (x, y)) -> (quote x, mkB name y)) eqns)))) |
|
|
|
|
|
|
|
|
check (P.LamCase pats) ty = do |
|
|
|
|
|
porp <- isPiType P.Ex ty |
|
|
|
|
|
case porp of |
|
|
|
|
|
It'sProd dom rng wp -> do |
|
|
|
|
|
name <- newName |
|
|
|
|
|
cases <- for pats $ \(pat, rhs) -> do |
|
|
|
|
|
checkPattern pat dom \pat wp pat_nf -> do |
|
|
|
|
|
rhs <- check rhs (rng pat_nf) |
|
|
|
|
|
pure (pat, wp rhs) |
|
|
|
|
|
let x = wp (Lam P.Ex name (Case (Ref name) cases)) |
|
|
|
|
|
pure x |
|
|
|
|
|
_ -> do |
|
|
|
|
|
dom <- newMeta VTypeω |
|
|
|
|
|
n <- newName' (Bound (T.singleton 'x') 0) |
|
|
|
|
|
assume n dom \_ -> do |
|
|
|
|
|
rng <- newMeta VTypeω |
|
|
|
|
|
throwElab $ NotEqual (VPi P.Ex dom (Closure n (const rng))) ty |
|
|
|
|
|
|
|
|
check (P.LamCase pats) ty = |
|
|
|
|
|
do |
|
|
|
|
|
porp <- isPiType P.Ex ty |
|
|
|
|
|
case porp of |
|
|
|
|
|
It'sProd dom rng wp -> do |
|
|
|
|
|
name <- newName |
|
|
|
|
|
let range = Lam P.Ex name (quote (rng (VVar name))) |
|
|
|
|
|
|
|
|
|
|
|
cases <- checkPatterns range [] pats \partialPats (pat, rhs) -> do |
|
|
|
|
|
checkPattern pat dom \pat wp boundary pat_nf -> do |
|
|
|
|
|
rhs <- check rhs (rng pat_nf) |
|
|
|
|
|
case boundary of |
|
|
|
|
|
-- If we're checking a higher constructor then we need to |
|
|
|
|
|
-- compute what the case expression computed so far does |
|
|
|
|
|
-- with all the faces |
|
|
|
|
|
|
|
|
|
|
|
-- and make sure that the current case agrees with that |
|
|
|
|
|
-- boundary |
|
|
|
|
|
Just boundary -> do |
|
|
|
|
|
rhs_nf <- eval (wp rhs) |
|
|
|
|
|
cases <- partialPats |
|
|
|
|
|
|
|
|
|
|
|
let |
|
|
|
|
|
(ty, a, b) = case pat_nf of |
|
|
|
|
|
VNe (HCon ty (ConName _ _ a b)) _ -> (ty, a, b) |
|
|
|
|
|
VNe (HPCon _ ty (ConName _ _ a b)) _ -> (ty, a, b) |
|
|
|
|
|
_ -> undefined |
|
|
|
|
|
dummies <- replicateM ((a + b) - length (getBoundaryNames boundary)) newName |
|
|
|
|
|
let |
|
|
|
|
|
base = appDummies (VVar <$> dummies) ty rhs_nf |
|
|
|
|
|
sys = boundaryFormulas (drop a dummies ++ getBoundaryNames boundary) (getBoundaryMap boundary) |
|
|
|
|
|
|
|
|
|
|
|
for_ (Map.toList sys) \(formula, side) -> do |
|
|
|
|
|
let rhs = cases @@ side |
|
|
|
|
|
for_ (truthAssignments formula mempty) $ \i -> do |
|
|
|
|
|
let vl = foldl (\v n -> vApp P.Ex v (snd (i Map.! n))) base (getBoundaryNames boundary) |
|
|
|
|
|
unify vl rhs |
|
|
|
|
|
`withNote` vcat [ pretty "These must be the same because of the face" |
|
|
|
|
|
, indent 2 $ prettyTm (quote formula) <+> operator (pretty "=>") <+> prettyTm (quote (zonk side)) |
|
|
|
|
|
] |
|
|
|
|
|
`withNote` (pretty "Mandated by the constructor" <+> prettyTm (quote pat_nf)) |
|
|
|
|
|
_ -> pure () |
|
|
|
|
|
|
|
|
|
|
|
pure (pat, wp rhs) |
|
|
|
|
|
let x = wp (Lam P.Ex name (Case range (Ref name) cases)) |
|
|
|
|
|
pure x |
|
|
|
|
|
_ -> do |
|
|
|
|
|
dom <- newMeta VTypeω |
|
|
|
|
|
n <- newName' (Bound (T.singleton 'x') 0) |
|
|
|
|
|
assume n dom \_ -> do |
|
|
|
|
|
rng <- newMeta VTypeω |
|
|
|
|
|
throwElab $ NotEqual (VPi P.Ex dom (Closure n (const rng))) ty |
|
|
|
|
|
where |
|
|
|
|
|
checkPatterns _ acc [] _ = pure (reverse acc) |
|
|
|
|
|
checkPatterns rng acc (x:xs) k = do |
|
|
|
|
|
n <- newName |
|
|
|
|
|
(p, t) <- k (eval (Lam P.Ex n (Case rng (Ref n) acc))) x |
|
|
|
|
|
checkPatterns rng ((p, t):acc) xs k |
|
|
|
|
|
|
|
|
|
|
|
appDummies (v:vl) (VPi p _ (Closure _ r)) x = appDummies vl (r v) (vApp p x v) |
|
|
|
|
|
appDummies [] _ x = x |
|
|
|
|
|
appDummies vs t _ = error (show (vs, t)) |
|
|
|
|
|
|
|
|
|
|
|
boundaryFormulas [] (VSystem fs) = fs |
|
|
|
|
|
boundaryFormulas (x:xs) k = boundaryFormulas xs $ k @@ VVar x |
|
|
|
|
|
boundaryFormulas a b = error (show (a, b)) |
|
|
|
|
|
|
|
|
check exp ty = do |
|
|
check exp ty = do |
|
|
(tm, has) <- switch $ infer exp |
|
|
(tm, has) <- switch $ infer exp |
|
|
wp <- isConvertibleTo has ty |
|
|
wp <- isConvertibleTo has ty |
|
|
pure (wp tm) |
|
|
pure (wp tm) |
|
|
|
|
|
|
|
|
checkPattern :: P.Pattern -> NFSort -> (Term -> (Term -> Term) -> Value -> ElabM a) -> ElabM a |
|
|
|
|
|
|
|
|
checkPattern :: P.Pattern -> NFSort -> (Term -> (Term -> Term) -> Maybe Boundary -> Value -> ElabM a) -> ElabM a |
|
|
checkPattern (P.PCap var) dom cont = do |
|
|
checkPattern (P.PCap var) dom cont = do |
|
|
name <- asks (Map.lookup var . nameMap) |
|
|
name <- asks (Map.lookup var . nameMap) |
|
|
case name of |
|
|
case name of |
|
|
Just name@(ConName _ _ skip arity) -> do |
|
|
Just name@(ConName _ _ skip arity) -> do |
|
|
unless (arity == 0) $ throwElab $ UnsaturatedCon name |
|
|
unless (arity == 0) $ throwElab $ UnsaturatedCon name |
|
|
(ty, wp) <- instantiate =<< getNfType name |
|
|
|
|
|
|
|
|
(ty, wp, _) <- instantiate =<< getNfType name |
|
|
unify ty dom |
|
|
unify ty dom |
|
|
wrap <- skipLams skip |
|
|
wrap <- skipLams skip |
|
|
cont (Con name) wrap =<< eval (wp (Con name)) |
|
|
|
|
|
|
|
|
cont (Con name) wrap Nothing =<< eval (wp (Con name)) |
|
|
Just name -> throwElab $ NotACon name |
|
|
Just name -> throwElab $ NotACon name |
|
|
Nothing -> assume (Bound var 0) dom \name -> cont (Ref name) (Lam P.Ex name) (VVar name) |
|
|
|
|
|
|
|
|
Nothing -> assume (Bound var 0) dom \name -> cont (Ref name) (Lam P.Ex name) Nothing (VVar name) |
|
|
|
|
|
|
|
|
checkPattern (P.PCon var args) dom cont = |
|
|
checkPattern (P.PCon var args) dom cont = |
|
|
do |
|
|
do |
|
|
name <- asks (Map.lookup var . nameMap) |
|
|
name <- asks (Map.lookup var . nameMap) |
|
|
case name of |
|
|
case name of |
|
|
Just name@(ConName _ _ nskip arity) -> do |
|
|
Just name@(ConName _ _ nskip arity) -> do |
|
|
unless (arity == length args) $ throwElab $ UnsaturatedCon name |
|
|
unless (arity == length args) $ throwElab $ UnsaturatedCon name |
|
|
(ty, wp) <- instantiate =<< getNfType name |
|
|
|
|
|
|
|
|
(ty, wp, xs) <- instantiate =<< getNfType name |
|
|
_ <- isConvertibleTo (skipBinders arity ty) dom |
|
|
_ <- isConvertibleTo (skipBinders arity ty) dom |
|
|
|
|
|
|
|
|
skip <- skipLams nskip |
|
|
skip <- skipLams nskip |
|
|
|
|
|
t <- asks (Map.lookup name . boundaries) |
|
|
|
|
|
|
|
|
|
|
|
con <- quote <$> getValue name |
|
|
|
|
|
|
|
|
bindNames args ty $ \names wrap -> |
|
|
bindNames args ty $ \names wrap -> |
|
|
cont (Con name) (skip . wrap) =<< eval (foldl (\x y -> App P.Ex x (Ref y)) (wp (Con name)) names) |
|
|
|
|
|
|
|
|
cont (Con name) (skip . wrap) (instBoundary xs <$> t) =<< eval (foldl (\x y -> App P.Ex x (Ref y)) (wp con) names) |
|
|
|
|
|
|
|
|
Just name -> throwElab $ NotACon name |
|
|
Just name -> throwElab $ NotACon name |
|
|
_ -> throwElab $ NotInScope (Bound var 0) |
|
|
_ -> throwElab $ NotInScope (Bound var 0) |
|
|
where |
|
|
where |
|
@ -254,12 +312,15 @@ checkPattern (P.PCon var args) dom cont = |
|
|
bindNames [] _ k = k [] id |
|
|
bindNames [] _ k = k [] id |
|
|
bindNames xs t _ = error $ show (xs, t) |
|
|
bindNames xs t _ = error $ show (xs, t) |
|
|
|
|
|
|
|
|
instantiate :: NFType -> ElabM (NFType, Term -> Term) |
|
|
|
|
|
|
|
|
instBoundary :: [Value] -> Boundary -> Boundary |
|
|
|
|
|
instBoundary metas (Boundary x y) = Boundary x (foldl (vApp P.Ex) y metas) |
|
|
|
|
|
|
|
|
|
|
|
instantiate :: NFType -> ElabM (NFType, Term -> Term, [Value]) |
|
|
instantiate (VPi P.Im d (Closure _ k)) = do |
|
|
instantiate (VPi P.Im d (Closure _ k)) = do |
|
|
t <- newMeta d |
|
|
t <- newMeta d |
|
|
(ty, w) <- instantiate (k t) |
|
|
|
|
|
pure (ty, \inner -> App P.Im (w inner) (quote t)) |
|
|
|
|
|
instantiate x = pure (x, id) |
|
|
|
|
|
|
|
|
(ty, w, xs) <- instantiate (k t) |
|
|
|
|
|
pure (ty, \inner -> w (App P.Im inner (quote t)), t:xs) |
|
|
|
|
|
instantiate x = pure (x, id, []) |
|
|
|
|
|
|
|
|
skipLams :: Int -> ElabM (Term -> Term) |
|
|
skipLams :: Int -> ElabM (Term -> Term) |
|
|
skipLams 0 = pure id |
|
|
skipLams 0 = pure id |
|
@ -447,13 +508,17 @@ checkStatement (P.Data name tele retk constrs) k = |
|
|
do |
|
|
do |
|
|
checkTeleRetk True tele retk \kind tele undef -> do |
|
|
checkTeleRetk True tele retk \kind tele undef -> do |
|
|
kind_nf <- eval kind |
|
|
kind_nf <- eval kind |
|
|
defineInternal (Defined name 0) kind_nf (\name' -> VNe (HData name') mempty) \name' -> |
|
|
|
|
|
checkCons tele (VNe (HData name') (Seq.fromList (map makeProj tele))) constrs (local (markAsDef name' . undef) k) |
|
|
|
|
|
|
|
|
defineInternal (Defined name 0) kind_nf (\name' -> VNe (mkHead name') mempty) \name' -> |
|
|
|
|
|
checkCons tele (VNe (mkHead name') (Seq.fromList (map makeProj tele))) constrs (local (markAsDef name' . undef) k) |
|
|
where |
|
|
where |
|
|
makeProj (x, p, _) = PApp p (VVar x) |
|
|
makeProj (x, p, _) = PApp p (VVar x) |
|
|
|
|
|
|
|
|
markAsDef x e = e { definedNames = Set.insert x (definedNames e) } |
|
|
markAsDef x e = e { definedNames = Set.insert x (definedNames e) } |
|
|
|
|
|
|
|
|
|
|
|
mkHead name |
|
|
|
|
|
| any (\case { P.Path{} -> True; _ -> False}) constrs = HData True name |
|
|
|
|
|
| otherwise = HData False name |
|
|
|
|
|
|
|
|
checkTeleRetk allKan [] retk cont = do |
|
|
checkTeleRetk allKan [] retk cont = do |
|
|
t <- check retk VTypeω |
|
|
t <- check retk VTypeω |
|
|
t_nf <- eval t |
|
|
t_nf <- eval t |
|
@ -472,7 +537,7 @@ checkStatement (P.Data name tele retk constrs) k = |
|
|
|
|
|
|
|
|
checkCons _ _et [] k = k |
|
|
checkCons _ _et [] k = k |
|
|
|
|
|
|
|
|
checkCons n ret ((x, ty):xs) k = do |
|
|
|
|
|
|
|
|
checkCons n ret (P.Point x ty:xs) k = do |
|
|
t <- check ty VTypeω |
|
|
t <- check ty VTypeω |
|
|
ty_nf <- eval t |
|
|
ty_nf <- eval t |
|
|
let |
|
|
let |
|
@ -482,6 +547,34 @@ checkStatement (P.Data name tele retk constrs) k = |
|
|
unify ret' ret |
|
|
unify ret' ret |
|
|
closed_nf <- eval closed |
|
|
closed_nf <- eval closed |
|
|
defineInternal (ConName x 0 (length n') (length args)) closed_nf (makeCon closed_nf mempty n' args) \_ -> checkCons n ret xs k |
|
|
defineInternal (ConName x 0 (length n') (length args)) closed_nf (makeCon closed_nf mempty n' args) \_ -> checkCons n ret xs k |
|
|
|
|
|
|
|
|
|
|
|
checkCons n ret (P.Path name indices return faces:xs) k = do |
|
|
|
|
|
(con, closed_nf, value, boundary) <- assumes (flip Bound 0 <$> indices) VI \indices -> do |
|
|
|
|
|
t <- check return VTypeω |
|
|
|
|
|
ty_nf <- eval t |
|
|
|
|
|
let |
|
|
|
|
|
(args, ret') = splitPi ty_nf |
|
|
|
|
|
closed = close n (addArgs args (addInterval indices (quote ret'))) |
|
|
|
|
|
n' = map (\(x, _, y) -> (x, P.Im, y)) n |
|
|
|
|
|
|
|
|
|
|
|
addArgs = flip $ foldr (\(x, p, t) -> Pi p x (quote t)) |
|
|
|
|
|
addInterval = flip $ foldr (\n -> Pi P.Ex n I) |
|
|
|
|
|
|
|
|
|
|
|
envArgs ((x, _, y):xs) = assume x y . const . envArgs xs |
|
|
|
|
|
envArgs [] = id |
|
|
|
|
|
|
|
|
|
|
|
closed_nf <- eval closed |
|
|
|
|
|
unify ret' ret |
|
|
|
|
|
|
|
|
|
|
|
faces <- envArgs args $ for faces \(f, t) -> do |
|
|
|
|
|
phi <- checkFormula f |
|
|
|
|
|
t <- check t ret |
|
|
|
|
|
pure (quote phi, t) |
|
|
|
|
|
|
|
|
|
|
|
system <- eval $ foldr (\x -> Lam P.Ex x) (System (Map.fromList faces)) (map (\(x, _, _) -> x) n' ++ map (\(x, _, _) -> x) args ++ indices) |
|
|
|
|
|
|
|
|
|
|
|
pure (ConName name 0 (length n') (length args + length indices), closed_nf, makePCon closed_nf mempty n' args indices system, Boundary indices system) |
|
|
|
|
|
defineInternal con closed_nf value \name -> addBoundary name boundary $ checkCons n ret xs k |
|
|
|
|
|
|
|
|
close [] t = t |
|
|
close [] t = t |
|
|
close ((x, _, y):xs) t = Pi P.Im x (quote y) (close xs t) |
|
|
close ((x, _, y):xs) t = Pi P.Im x (quote y) (close xs t) |
|
@ -493,6 +586,11 @@ checkStatement (P.Data name tele retk constrs) k = |
|
|
makeCon cty sp ((nm, p, _):xs) ys con = VLam p $ Closure nm \a -> makeCon cty (sp Seq.:|> PApp p a) xs ys con |
|
|
makeCon cty sp ((nm, p, _):xs) ys con = VLam p $ Closure nm \a -> makeCon cty (sp Seq.:|> PApp p a) xs ys con |
|
|
makeCon cty sp [] ((nm, p, _):ys) con = VLam p $ Closure nm \a -> makeCon cty (sp Seq.:|> PApp p a) [] ys con |
|
|
makeCon cty sp [] ((nm, p, _):ys) con = VLam p $ Closure nm \a -> makeCon cty (sp Seq.:|> PApp p a) [] ys con |
|
|
|
|
|
|
|
|
|
|
|
makePCon cty sp [] [] [] sys con = VNe (HPCon sys cty con) sp |
|
|
|
|
|
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 |
|
|
|
|
|
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 |
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
evalFix :: Name -> NFType -> Term -> ElabM Value |
|
|
evalFix :: Name -> NFType -> Term -> ElabM Value |
|
|
evalFix name nft term = do |
|
|
evalFix name nft term = do |
|
|
env <- ask |
|
|
env <- ask |
|
|