WIP: quantity polymorphism #44

Draft
rhi wants to merge 9 commits from qpoly into 🐉
34 changed files with 2314 additions and 1369 deletions

View file

@ -3,15 +3,19 @@ module Quox.Context
import Quox.Syntax.Shift
import Quox.Pretty
import Quox.Name
import Quox.NatExtra
import Quox.PrettyValExtra
import Data.DPair
import Data.Nat
import Data.Singleton
import Quox.SingletonExtra
import Data.SnocList
import Data.SnocVect
import Data.Vect
import Control.Monad.Identity
import Derive.Prelude
%language ElabReflection
%default total
@ -45,6 +49,10 @@ public export
BContext : Nat -> Type
BContext = Context' BindName
public export
BTelescope : Nat -> Nat -> Type
BTelescope = Telescope' BindName
public export
unsnoc : Context tm (S n) -> (Context tm n, tm n)
@ -109,21 +117,31 @@ fromSnocVect [<] = [<]
fromSnocVect (sx :< x) = fromSnocVect sx :< x
public export
tabulateLT : (n : Nat) -> ((i : Nat) -> (0 p : i `LT` n) => tm i) ->
Context tm n
tabulateLT 0 f = [<]
tabulateLT (S k) f =
tabulateLT k (\i => f i @{lteSuccRight %search}) :< f k @{reflexive}
export
tabulateVar : (n : Nat) -> (Var n -> a) -> Context' a n
tabulateVar 0 f = [<]
tabulateVar (S k) f = tabulateVar k (f . VS) :< f VZ
public export
tabulate : ((n : Nat) -> tm n) -> (n : Nat) -> Context tm n
tabulate f n = tabulateLT n (\i => f i)
-- [todo] fixup argument order lol
export
allVars : (n : Nat) -> Context' (Var n) n
allVars n = tabulateVar n id
public export
replicate : (n : Nat) -> a -> Context' a n
replicate n x = tabulate (const x) n
replicate n x = tabulateVar n $ const x
public export
replicateLTE : from `LTE'` to => a -> Telescope' a from to
replicateLTE @{LTERefl} x = [<]
replicateLTE @{LTESuccR _} x = replicateLTE x :< x
public export
replicateTel : (from, to : Nat) -> a ->
Either (from `GT` to) (Telescope' a from to)
replicateTel from to x = case isLTE' from to of
Yes lte => Right $ replicateLTE x
No nlte => Left $ notLTEImpliesGT $ nlte . fromLTE
public export
@ -278,12 +296,16 @@ lengthPrf [<] = Element 0 Refl
lengthPrf (tel :< _) =
let len = lengthPrf tel in Element (S len.fst) (cong S len.snd)
export
public export
lengthPrfSing : Telescope _ from to -> Singleton from -> Singleton to
lengthPrfSing tel (Val from) =
let Element len prf = lengthPrf tel in
rewrite sym prf in
Val (len + from)
public export
lengthPrf0 : Context _ to -> Singleton to
lengthPrf0 ctx =
let Element len prf = lengthPrf ctx in
rewrite sym prf `trans` plusZeroRightNeutral len in
[|len|]
lengthPrf0 ctx = lengthPrfSing ctx (Val 0)
public export %inline
length : Telescope {} -> Nat
@ -330,14 +352,30 @@ export %inline
(forall n. Eq (tm n)) => Eq (Telescope tm from to) where
(==) = foldLazy @{All} .: zipWithLazy (==)
export %inline
(forall n. DecEq (tm n)) => DecEq (Telescope tm from to) where
decEq [<] [<] = Yes Refl
decEq (xs :< x) (ys :< y) = do
let Yes Refl = decEq xs ys
| No n => No $ \case Refl => n Refl
let Yes Refl = decEq x y
| No n => No $ \case Refl => n Refl
Yes Refl
decEq [<] (_ :< _) = No $ \case _ impossible
decEq (_ :< _) [<] = No $ \case _ impossible
export %inline
(forall n. Ord (tm n)) => Ord (Telescope tm from to) where
compare = foldLazy .: zipWithLazy compare
export %inline
(forall n. Show (tm n)) => Show (Telescope tm from to) where
showPrec d = showPrec d . toSnocList
where Show (Exists tm) where showPrec d t = showPrec d t.snd
showPrec d = showPrec d . toSnocList where
Show (Exists tm) where showPrec d t = showPrec d t.snd
export %inline
(forall n. PrettyVal (tm n)) => PrettyVal (Telescope tm from to) where
prettyVal xs = prettyVal $ toSnocList' $ map prettyVal xs
parameters {opts : LayoutOpts} {0 tm : Nat -> Type}
@ -364,5 +402,68 @@ parameters {opts : LayoutOpts} {0 tm : Nat -> Type}
namespace BContext
export
toNames : BContext n -> SnocList BaseName
toNames : BTelescope {} -> SnocList BaseName
toNames = foldl (\xs, x => xs :< x.val) [<]
public export
record NameContexts q d n where
constructor MkNameContexts
{auto qtyLen : Singleton q}
{auto dimLen : Singleton d}
{auto termLen : Singleton n}
qnames : BContext q
dnames : BContext d
tnames : BContext n
%runElab deriveIndexed "NameContexts" [Show]
namespace NameContexts
export
MkNameContexts' : (qnames : BContext q) -> (dnames : BContext d) ->
(tnames : BContext n) -> NameContexts q d n
MkNameContexts' {qnames, dnames, tnames} =
MkNameContexts {
qnames, dnames, tnames,
qtyLen = lengthPrf0 qnames,
dimLen = lengthPrf0 dnames,
termLen = lengthPrf0 tnames
}
export
fromQNames : BContext q -> NameContexts q 0 0
fromQNames qnames =
MkNameContexts qnames [<] [<] {qtyLen = lengthPrf0 qnames}
export %inline
empty : NameContexts 0 0 0
empty = fromQNames [<]
export
extendQtyN' : BTelescope q q' -> NameContexts q d n -> NameContexts q' d n
extendQtyN' xs = {qnames $= (. xs), qtyLen $= lengthPrfSing xs}
export
extendDimN' : BTelescope d d' -> NameContexts q d n -> NameContexts q d' n
extendDimN' xs = {dnames $= (. xs), dimLen $= lengthPrfSing xs}
export
extendDimN : {s : Nat} -> BContext s ->
NameContexts q d n -> NameContexts q (s + d) n
extendDimN xs = {dnames $= (++ toSnocVect' xs), dimLen $= map (s +)}
export
extendDim : BindName -> NameContexts q d n -> NameContexts q (S d) n
extendDim i = extendDimN [< i]
export
extendTermN' : BTelescope n n' -> NameContexts q d n -> NameContexts q d n'
extendTermN' xs = {tnames $= (. xs), termLen $= lengthPrfSing xs}
export
extendTermN : {s : Nat} -> BContext s ->
NameContexts q d n -> NameContexts q d (s + n)
extendTermN xs = {tnames $= (++ toSnocVect' xs), termLen $= map (s +)}
export
extendTerm : BindName -> NameContexts q d n -> NameContexts q d (S n)
extendTerm x = extendTermN [< x]

View file

@ -47,6 +47,12 @@ Yes _ && No n2 = No $ n2 . snd
No n1 && _ = No $ n1 . fst
public export
map : p <=> q -> Dec p -> Dec q
map (MkEquivalence l r) (Yes y) = Yes $ l y
map (MkEquivalence l r) (No n) = No $ n . r
public export
reflectToDec : p `Reflects` b -> Dec p
reflectToDec (RTrue y) = Yes y

View file

@ -12,14 +12,16 @@ import Decidable.Decidable
public export
data DefBody =
Concrete (Term 0 0)
| Postulate
data DefBody : (q : Nat) -> Type where
MonoDef : Term 0 0 0 -> DefBody 0
PolyDef : (0 nz : IsSucc q) => Term q 0 0 -> DefBody q
Postulate : DefBody q
namespace DefBody
public export
(.term0) : DefBody -> Maybe (Term 0 0)
(Concrete t).term0 = Just t
(.term0) : DefBody q -> Maybe (Term q 0 0)
(MonoDef t).term0 = Just t
(PolyDef t).term0 = Just t
(Postulate).term0 = Nothing
@ -27,59 +29,76 @@ public export
record Definition where
constructor MkDef
qty : GQty
type0 : Term 0 0
body0 : DefBody
{qlen : Nat}
qargs : BContext qlen
type0 : Term qlen 0 0
body0 : DefBody qlen
scheme : Maybe String
isMain : Bool
loc_ : Loc
public export %inline
mkPostulate : GQty -> (type0 : Term 0 0) -> Maybe String -> Bool -> Loc ->
Definition
mkPostulate qty type0 scheme isMain loc_ =
MkDef {qty, type0, body0 = Postulate, scheme, isMain, loc_}
mkPostulate : GQty -> BContext q -> Term q 0 0 ->
Maybe String -> Bool -> Loc -> Definition
mkPostulate qty qargs type0 scheme isMain loc_ =
let Val q = lengthPrf0 qargs in
MkDef {qty, qargs, type0, body0 = Postulate, scheme, isMain, loc_}
public export %inline
mkDef : GQty -> (type0, term0 : Term 0 0) -> Maybe String -> Bool -> Loc ->
Definition
mkDef qty type0 term0 scheme isMain loc_ =
MkDef {qty, type0, body0 = Concrete term0, scheme, isMain, loc_}
mkDef : GQty -> BContext q -> (type0, term0 : Term q 0 0) -> Maybe String ->
Bool -> Loc -> Definition
mkDef qty qargs type0 term0 scheme isMain loc_ =
case (lengthPrf0 qargs) of
Val 0 =>
MkDef {qty, qargs, type0, body0 = MonoDef term0, scheme, isMain, loc_}
Val (S _) =>
MkDef {qty, qargs, type0, body0 = PolyDef term0, scheme, isMain, loc_}
export Located Definition where def.loc = def.loc_
export Relocatable Definition where setLoc loc = {loc_ := loc}
public export
record Poly (0 tm : TermLike) d n where
constructor P
qlen : Nat
type : tm qlen d n
parameters {d, n : Nat}
public export %inline
(.type) : Definition -> Term d n
g.type = g.type0 // shift0 d // shift0 n
(.type) : Definition -> Poly Term d n
def.type = P def.qlen $ def.type0 // shift0 d // shift0 n
public export %inline
(.typeAt) : Definition -> Universe -> Term d n
g.typeAt u = displace u g.type
(.typeAt) : Definition -> Universe -> Poly Term d n
def.typeAt u = {type $= displace u} def.type
public export %inline
(.term) : Definition -> Maybe (Term d n)
g.term = g.body0.term0 <&> \t => t // shift0 d // shift0 n
(.term) : Definition -> Maybe (Poly Term d n)
def.term = def.body0.term0 <&> \t => P def.qlen $ t // shift0 d // shift0 n
public export %inline
(.termAt) : Definition -> Universe -> Maybe (Term d n)
g.termAt u = displace u <$> g.term
(.termAt) : Definition -> Universe -> Maybe (Poly Term d n)
def.termAt u = {type $= displace u} <$> def.term
public export %inline
toElim : Definition -> Universe -> Maybe $ Elim d n
toElim def u = pure $ Ann !(def.termAt u) (def.typeAt u) def.loc
toElim : Definition -> Universe -> Maybe (Poly Elim d n)
toElim def u = do
tm <- def.body0.term0; let ty = def.type0
pure $ P def.qlen $ Ann tm ty def.loc // shift0 d // shift0 n
public export
(.typeWith) : Definition -> Singleton d -> Singleton n -> Term d n
g.typeWith (Val d) (Val n) = g.type
(.typeWith) : Definition -> Singleton d -> Singleton n -> Poly Term d n
def.typeWith (Val d) (Val n) = def.type
public export
(.typeWithAt) : Definition -> Singleton d -> Singleton n -> Universe -> Term d n
g.typeWithAt d n u = displace u $ g.typeWith d n
(.typeWithAt) : Definition -> Singleton d -> Singleton n ->
Universe -> Poly Term d n
def.typeWithAt (Val d) (Val n) u = def.typeAt u
public export
(.termWith) : Definition -> Singleton d -> Singleton n -> Maybe (Term d n)
(.termWith) : Definition -> Singleton d -> Singleton n -> Maybe (Poly Term d n)
g.termWith (Val d) (Val n) = g.term
@ -108,20 +127,28 @@ DefsState : Type -> Type
DefsState = StateL DEFS Definitions
public export %inline
lookupElim : {d, n : Nat} -> Name -> Universe -> Definitions -> Maybe (Elim d n)
lookupElim : {d, n : Nat} ->
Name -> Universe -> Definitions -> Maybe (Poly Elim d n)
lookupElim x u defs = toElim !(lookup x defs) u
public export %inline
lookupElim0 : Name -> Universe -> Definitions -> Maybe (Elim 0 0)
lookupElim0 : Name -> Universe -> Definitions -> Maybe (Poly Elim 0 0)
lookupElim0 = lookupElim
export
prettyQBinders : {opts : LayoutOpts} -> BContext q -> Eff Pretty (Doc opts)
prettyQBinders [<] = pure empty
prettyQBinders qnames =
qbrackets . separateTight !commaD =<< traverse prettyQBind (toList' qnames)
export
prettyDef : {opts : LayoutOpts} -> Name -> Definition -> Eff Pretty (Doc opts)
prettyDef name def = withPrec Outer $ do
qty <- prettyQty def.qty.qty
qty <- prettyQConst def.qty.qconst
dot <- dotD
name <- prettyFree name
qargs <- prettyQBinders def.qargs
colon <- colonD
type <- prettyTerm [<] [<] def.type
hangDSingle (hsep [hcat [qty, dot, name], colon]) type
type <- prettyTerm (fromQNames def.qargs) def.type0
hangDSingle (hsep [hcat [qty, dot, name, qargs], colon]) type

View file

@ -7,12 +7,12 @@ import Quox.Syntax
parameters (k : Universe)
namespace Term
export doDisplace : Term d n -> Term d n
export doDisplaceS : ScopeTermN s d n -> ScopeTermN s d n
export doDisplaceDS : DScopeTermN s d n -> DScopeTermN s d n
export doDisplace : Term q d n -> Term q d n
export doDisplaceS : ScopeTermN s q d n -> ScopeTermN s q d n
export doDisplaceDS : DScopeTermN s q d n -> DScopeTermN s q d n
namespace Elim
export doDisplace : Elim d n -> Elim d n
export doDisplace : Elim q d n -> Elim q d n
namespace Term
doDisplace (TYPE l loc) = TYPE (k + l) loc
@ -41,6 +41,8 @@ parameters (k : Universe)
CloT (Sub (doDisplace t) (assert_total $ map doDisplace th))
doDisplace (DCloT (Sub t th)) =
DCloT (Sub (doDisplace t) th)
doDisplace (QCloT (SubR t th)) =
QCloT (SubR (doDisplace t) th)
doDisplaceS (S names (Y body)) = S names $ Y $ doDisplace body
doDisplaceS (S names (N body)) = S names $ N $ doDisplace body
@ -80,16 +82,18 @@ parameters (k : Universe)
CloE (Sub (doDisplace e) (assert_total $ map doDisplace th))
doDisplace (DCloE (Sub e th)) =
DCloE (Sub (doDisplace e) th)
doDisplace (QCloE (SubR e th)) =
QCloE (SubR (doDisplace e) th)
namespace Term
export
displace : Universe -> Term d n -> Term d n
displace : Universe -> Term q d n -> Term q d n
displace 0 t = t
displace u t = doDisplace u t
namespace Elim
export
displace : Universe -> Elim d n -> Elim d n
displace : Universe -> Elim q d n -> Elim q d n
displace 0 t = t
displace u t = doDisplace u t

View file

@ -62,7 +62,7 @@ export %inline [AndM] {n : Nat} -> Monoid (FreeVars n) where neutral = all
private
self : {n : Nat} -> Context' (FreeVars n) n
self = tabulate (\i => FV $ tabulate (== i) n) n
self = tabulateVar n $ \i => FV $ tabulateVar n (== i)
export
shift : forall from, to. Shift from to -> FreeVars from -> FreeVars to
@ -74,13 +74,12 @@ shift by (FV xs) = FV $ shift' by xs where
export
fromSet : {n : Nat} -> SortedSet (Var n) -> FreeVars n
fromSet vs = FV $ tabulateLT n $ \i => contains (V i) vs
fromSet vs = FV $ tabulateVar n $ \i => contains i vs
export
toSet : {n : Nat} -> FreeVars n -> SortedSet (Var n)
toSet (FV vs) =
foldl_ (\s, i => maybe s (\i => insert i s) i) empty $
zipWith (\i, b => guard b $> i) (tabulateLT n V) vs
toSet (FV vs) = SortedSet.fromList $ fold $
Context.zipWith (\i, b => i <$ guard b) (allVars n) vs
public export
@ -89,7 +88,7 @@ interface HasFreeVars (0 tm : Nat -> Type) where
fv : {n : Nat} -> tm n -> FreeVars n
public export
interface HasFreeDVars (0 tm : TermLike) where
interface HasFreeDVars (0 tm : Nat -> Nat -> Type) where
constructor HFDV
fdv : {d, n : Nat} -> tm d n -> FreeVars d
@ -102,7 +101,7 @@ fdvWith : HasFreeDVars tm => Singleton d -> Singleton n -> tm d n -> FreeVars d
fdvWith (Val d) (Val n) = fdv
export
Fdv : (0 tm : TermLike) -> {n : Nat} ->
Fdv : (0 tm : _) -> {n : Nat} ->
HasFreeDVars tm => HasFreeVars (\d => tm d n)
Fdv tm @{HFDV fdv} = HFV fdv
@ -140,7 +139,7 @@ where
fdv (S _ (N body)) = fdv body
export
fvD : {0 tm : TermLike} -> {n : Nat} -> (forall d. HasFreeVars (tm d)) =>
fvD : {0 tm : _} -> {n : Nat} -> (forall d. HasFreeVars (tm d)) =>
Scoped s (\d => tm d n) d -> FreeVars n
fvD (S _ (Y body)) = fv body
fvD (S _ (N body)) = fv body
@ -175,11 +174,10 @@ where
foldMap (uncurry guardM) (zipWith (,) (fv term).vars (fdvEach subst))
export HasFreeVars (Term d)
export HasFreeVars (Elim d)
export HasFreeVars (Term q d)
export HasFreeVars (Elim q d)
export
HasFreeVars (Term d) where
HasFreeVars (Term q d) where
fv (TYPE {}) = none
fv (IOState {}) = none
fv (Pi {arg, res, _}) = fv arg <+> fv res
@ -201,9 +199,9 @@ HasFreeVars (Term d) where
fv (E e) = fv e
fv (CloT s) = fv s
fv (DCloT s) = fv s.term
fv (QCloT s) = fv s.term
export
HasFreeVars (Elim d) where
HasFreeVars (Elim q d) where
fv (F {}) = none
fv (B i _) = only i
fv (App {fun, arg, _}) = fv fun <+> fv arg
@ -225,12 +223,13 @@ HasFreeVars (Elim d) where
fv ty <+> fv ret <+> fv def <+> foldMap (\x => fv x.snd) (toList arms)
fv (CloE s) = fv s
fv (DCloE s) = fv s.term
fv (QCloE s) = fv s.term
private
expandDShift : {d1 : Nat} -> Shift d1 d2 -> Loc -> Context' (Dim d2) d1
expandDShift by loc = tabulateLT d1 (\i => BV i loc // by)
expandDShift by loc = tabulateVar d1 (\i => B i loc // by)
private
expandDSubst : {d1 : Nat} -> DSubst d1 d2 -> Loc -> Context' (Dim d2) d1
@ -254,11 +253,10 @@ fdvSubst : {d, n : Nat} -> (Located2 tm, HasFreeDVars tm) =>
fdvSubst (Sub t th) = let Val from = getFrom th in fdvSubst' t th
export HasFreeDVars Term
export HasFreeDVars Elim
export HasFreeDVars (Term q)
export HasFreeDVars (Elim q)
export
HasFreeDVars Term where
HasFreeDVars (Term q) where
fdv (TYPE {}) = none
fdv (IOState {}) = none
fdv (Pi {arg, res, _}) = fdv arg <+> fdvT res
@ -280,9 +278,9 @@ HasFreeDVars Term where
fdv (E e) = fdv e
fdv (CloT s) = fdv s @{WithSubst}
fdv (DCloT s) = fdvSubst s
fdv (QCloT s) = fdv s.term
export
HasFreeDVars Elim where
HasFreeDVars (Elim q) where
fdv (F {}) = none
fdv (B {}) = none
fdv (App {fun, arg, _}) = fdv fun <+> fdv arg
@ -299,12 +297,13 @@ HasFreeDVars Elim where
fdv fun <+> fv arg
fdv (Ann {tm, ty, _}) =
fdv tm <+> fdv ty
fdv (Coe {ty, p, q, val, _}) =
fdv @{DScope} ty <+> fv p <+> fv q <+> fdv val
fdv (Comp {ty, p, q, val, r, zero, one, _}) =
fdv ty <+> fv p <+> fv q <+> fdv val <+>
fdv (Coe {ty, p, p', val, _}) =
fdv @{DScope} ty <+> fv p <+> fv p' <+> fdv val
fdv (Comp {ty, p, p', val, r, zero, one, _}) =
fdv ty <+> fv p <+> fv p' <+> fdv val <+>
fv r <+> fdv @{DScope} zero <+> fdv @{DScope} one
fdv (TypeCase {ty, ret, arms, def, _}) =
fdv ty <+> fdv ret <+> fdv def <+> foldMap (\x => fdvT x.snd) (toList arms)
fdv (CloE s) = fdv s @{WithSubst}
fdv (DCloE s) = fdvSubst s
fdv (QCloE s) = fdv s.term

View file

@ -125,7 +125,9 @@ extendOr l1 l2 = (l1 `extendL` l2) `or` l2
public export
interface Located a where (.loc) : a -> Loc
interface Located a where
constructor MkLocated
(.loc) : a -> Loc
public export
0 Located1 : (a -> Type) -> Type
@ -136,7 +138,13 @@ public export
Located2 f = forall x, y. Located (f x y)
public export
interface Located a => Relocatable a where setLoc : Loc -> a -> a
0 Located3 : (a -> b -> c -> Type) -> Type
Located3 f = forall x, y, z. Located (f x y z)
public export
interface Located a => Relocatable a where
constructor MkRelocatable
setLoc : Loc -> a -> a
public export
0 Relocatable1 : (a -> Type) -> Type
@ -146,6 +154,10 @@ public export
0 Relocatable2 : (a -> b -> Type) -> Type
Relocatable2 f = forall x, y. Relocatable (f x y)
public export
0 Relocatable3 : (a -> b -> c -> Type) -> Type
Relocatable3 f = forall x, y, z. Relocatable (f x y z)
export
locs : Located a => Foldable t => t a -> Loc

View file

@ -5,6 +5,7 @@ import Data.Nat.Division
import Data.SnocList
import Data.Vect
import Data.String
import Quox.Decidable
%default total
@ -14,26 +15,53 @@ data LTE' : Nat -> Nat -> Type where
LTERefl : LTE' n n
LTESuccR : LTE' m n -> LTE' m (S n)
%builtin Natural LTE'
%name LTE' p, q
public export %hint
lteZero' : {n : Nat} -> LTE' 0 n
lteZero' {n = 0} = LTERefl
lteZero' {n = S n} = LTESuccR lteZero'
%transform "NatExtra.lteZero'" lteZero' {n} = believe_me n
public export %hint
lteSucc' : LTE' m n -> LTE' (S m) (S n)
lteSucc' LTERefl = LTERefl
lteSucc' (LTESuccR p) = LTESuccR $ lteSucc' p
%transform "NatExtra.lteSucc'" lteSucc' p = believe_me p
public export
fromLte : {n : Nat} -> LTE m n -> LTE' m n
fromLte LTEZero = lteZero'
fromLte (LTESucc p) = lteSucc' $ fromLte p
fromLTE : {n : Nat} -> LTE m n -> LTE' m n
fromLTE LTEZero = lteZero'
fromLTE (LTESucc p) = lteSucc' $ fromLTE p
-- %transform "NatExtra.fromLTE"
-- fromLTE {n} p = believe_me (n `minus` believe_me p)
public export
toLte : {n : Nat} -> m `LTE'` n -> m `LTE` n
toLte LTERefl = reflexive
toLte (LTESuccR p) = lteSuccRight (toLte p)
toLTE : {m : Nat} -> m `LTE'` n -> m `LTE` n
toLTE LTERefl = reflexive
toLTE (LTESuccR p) = lteSuccRight (toLTE p)
-- %transform "NatExtra.toLTE" toLTE {m} p = believe_me m
public export
lteLTE' : {m, n : Nat} -> LTE m n <=> LTE' m n
lteLTE' = MkEquivalence fromLTE toLTE
public export
isLTE' : (m, n : Nat) -> Dec (LTE' m n)
isLTE' m n = map lteLTE' $ isLTE m n
public export
data LT' : Nat -> Nat -> Type where
LTZero : LT' 0 (S n)
LTSucc : LT' m n -> LT' (S m) (S n)
%builtin Natural LT'
%name LT' p, q
public export
Transitive Nat LT' where
transitive LTZero (LTSucc q) = LTZero
transitive (LTSucc p) (LTSucc q) = LTSucc $ transitive p q
private

View file

@ -13,6 +13,10 @@ data No : Pred Bool where
export Uninhabited (No True) where uninhabited _ impossible
export Eq (No p) where _ == _ = True
export Ord (No p) where compare _ _ = EQ
export Show (No p) where showPrec _ _ = "Ah"
export %inline
soNo : So b -> No b -> Void
soNo Oh Ah impossible

View file

@ -50,7 +50,7 @@ dropInner' (LTESuccR p) = Drop $ dropInner' $ force p
public export
dropInner : {n : Nat} -> LTE m n -> OPE m n
dropInner = dropInner' . fromLte
dropInner = dropInner' . fromLTE
public export
dropInnerN : (m : Nat) -> OPE n (m + n)

189
lib/Quox/Polynomial.idr Normal file
View file

@ -0,0 +1,189 @@
module Quox.Polynomial
import public Quox.Syntax.Subst
import public Quox.Context
import public Quox.Semiring
import Data.Maybe
import Data.SortedMap
import Data.Singleton
import Quox.PrettyValExtra
%default total
%hide Prelude.toList
public export
Monom : Nat -> Type
Monom = Context' Nat
export %inline
mZero : {n : Nat} -> Monom n
mZero = replicate n 0
export %inline
mIsZero : Monom n -> Bool
mIsZero = all (== 0)
private
PolyBody : Type -> Nat -> Type
PolyBody coeff scope = SortedMap (Monom scope) coeff
private %inline
getScope : PolyBody coeff scope -> Maybe (Singleton scope)
getScope p = lengthPrf0 . fst <$> leftMost p
export
data Polynomial : (coeff : Type) -> (scope : Nat) -> Type where
Const : (k : coeff) -> Polynomial coeff scope
Many : (p : PolyBody coeff scope) -> Polynomial coeff scope
%name Polynomial p, q
-- the Const constructor exists so that `pconst` (and by extension, `one`, and
-- the TimesMonoid instance) doesn't need to know the scope size
export %inline
toConst' : List (Monom scope, coeff) -> Maybe coeff
toConst' [(m, k)] = k <$ guard (mIsZero m)
toConst' _ = Nothing
export %inline
toConst : PolyBody coeff scope -> Maybe coeff
toConst = toConst' . toList
export %inline
toTrimmedList : AddMonoid v => SortedMap k v -> List (k, v)
toTrimmedList = List.filter (not . isZero . snd) . toList
export %inline
toList : {scope : Nat} -> AddMonoid coeff =>
Polynomial coeff scope -> List (Monom scope, coeff)
toList (Const k) = [(mZero, k)]
toList (Many p) = toTrimmedList p
private %inline
addBody : AddMonoid coeff =>
PolyBody coeff scope -> PolyBody coeff scope -> PolyBody coeff scope
addBody = mergeWith (+.)
export %inline
fromList : AddMonoid coeff =>
List (Monom scope, coeff) -> Polynomial coeff scope
fromList xs = case toConst' xs of
Just k => Const k
Nothing => Many $ foldl add1 empty xs
where
add1 : PolyBody coeff scope -> (Monom scope, coeff) -> PolyBody coeff scope
add1 p (x, k) = p `addBody` singleton x k
export %inline
(AddMonoid coeff, Eq coeff) => Eq (Polynomial coeff scope) where
Const x == Const y = x == y
Const x == Many q = maybe False (== x) $ toConst q
Many p == Const y = maybe False (== y) $ toConst p
Many p == Many q = toTrimmedList p == toTrimmedList q
export %inline
(AddMonoid coeff, Ord coeff) => Ord (Polynomial coeff scope) where
compare (Const x) (Const y) = compare x y
compare (Const x) (Many q) = maybe LT (compare x) $ toConst q
compare (Many p) (Const y) = maybe GT (flip compare y) $ toConst p
compare (Many p) (Many q) = compare (toTrimmedList p) (toTrimmedList q)
export %inline
{scope : Nat} -> (AddMonoid coeff, Show coeff) =>
Show (Polynomial coeff scope) where
showPrec d p = showCon d "fromList" $ showArg (toList p)
export %inline
{scope : Nat} -> (AddMonoid coeff, PrettyVal coeff) =>
PrettyVal (Polynomial coeff scope) where
prettyVal p = Con "fromList" [prettyVal $ toList p]
export %inline
pconst : a -> Polynomial a n
pconst = Const
export %inline
(.at) : AddMonoid a => Polynomial a n -> Monom n -> a
(Const k).at m = if mIsZero m then k else zero
(Many p).at m = fromMaybe zero $ lookup m p
export %inline
(.at0) : AddMonoid a => Polynomial a n -> a
(Const k).at0 = k
(Many p).at0 = fromMaybe zero $ do
(m, k) <- leftMost p
guard $ mIsZero m
pure k
private %inline
addConstMany : AddMonoid coeff =>
coeff -> PolyBody coeff scope -> Polynomial coeff scope
addConstMany k p = case getScope p of
Nothing => Const k
Just (Val _) => Many $ p `addBody` singleton mZero k
export %inline
AddMonoid a => AddMonoid (Polynomial a n) where
zero = Const zero
isZero (Const k) = isZero k
isZero (Many p) = maybe False isZero $ toConst p
Const j +. Const k = Const $ j +. k
Const j +. Many q = addConstMany j q
Many p +. Const k = addConstMany k p
Many p +. Many q = Many $ p `addBody` q
export %inline
Semiring a => TimesMonoid (Polynomial a n) where
one = pconst one
Const j *. Const k = Const $ j *. k
Const j *. Many q = Many $ map (j *.) q
Many p *. Const k = Many $ map (*. k) p
Many p *. Many q = fromList $ do
(xs, i) <- toList p
(ys, j) <- toList q
let k = i *. j
guard $ not $ isZero k
pure (zipWith (+) xs ys, i *. j)
export %inline
Semiring a => VecSpace a (Polynomial a n) where
x *: xs = Const x *. xs
private
shiftMonom : Shift from to -> Monom from -> Monom to
shiftMonom SZ m = m
shiftMonom (SS by) m = shiftMonom by m :< 0
export
CanShift (Polynomial coeff) where
Const k // _ = Const k
Many p // by =
let xs = mapFst (shiftMonom by) <$> toList p in
Many $ fromList xs
export
TimesMonoid a => FromVarR (Polynomial a) where
fromVarR i l {n} =
let m = tabulateVar n $ \j => if i == j then 1 else 0 in
Many $ singleton m one
private
substMonom : Semiring a => {from, to : Nat} ->
Subst (Polynomial a) from to -> Monom from -> a -> Polynomial a to
substMonom th m k = sproduct {init = pconst k} $
zipWith (\i, p => getR th i noLoc ^. p) (allVars from) m
export
Semiring a => CanSubstSelfR (Polynomial a) where
Const k //? _ = Const k
Many p //? th = ssum $ map (uncurry $ substMonom th) $ toList p

View file

@ -37,9 +37,10 @@ data PPrec
public export
data HL
= Delim
| Free | TVar | TVarErr
| Dim | DVar | DVarErr
| Qty | Universe
| Free | TVar
| Dim | DVar
| Qty | QVar
| Universe
| Syntax
| Constant
%runElab derive "HL" [Eq, Ord, Show]
@ -79,11 +80,10 @@ toSGR : HL -> List SGR
toSGR Delim = []
toSGR Free = [SetForeground BrightBlue]
toSGR TVar = [SetForeground BrightYellow]
toSGR TVarErr = [SetForeground BrightYellow, SetStyle SingleUnderline]
toSGR Dim = [SetForeground BrightGreen]
toSGR DVar = [SetForeground BrightGreen]
toSGR DVarErr = [SetForeground BrightGreen, SetStyle SingleUnderline]
toSGR Qty = [SetForeground BrightMagenta]
toSGR QVar = [SetForeground BrightMagenta]
toSGR Universe = [SetForeground BrightRed]
toSGR Syntax = [SetForeground BrightCyan]
toSGR Constant = [SetForeground BrightRed]
@ -97,11 +97,10 @@ toClass : HL -> String
toClass Delim = "dl"
toClass Free = "fr"
toClass TVar = "tv"
toClass TVarErr = "tv err"
toClass Dim = "dc"
toClass DVar = "dv"
toClass DVarErr = "dv err"
toClass Qty = "qt"
toClass QVar = "qv"
toClass Universe = "un"
toClass Syntax = "sy"
toClass Constant = "co"
@ -209,6 +208,10 @@ parameters {opts : LayoutOpts} {auto _ : Foldable t}
separateTight : Doc opts -> t (Doc opts) -> Doc opts
separateTight d = sep . exceptLast (<+> d) . toList
export
sepSingleTight : Doc opts -> t (Doc opts) -> Doc opts
sepSingleTight d = sepSingle . exceptLast (<+> d) . toList
export
hseparateTight : Doc opts -> t (Doc opts) -> Doc opts
hseparateTight d = hsep . exceptLast (<+> d) . toList
@ -242,6 +245,10 @@ export %inline
withPrec : PPrec -> Eff Pretty a -> Eff Pretty a
withPrec = localAt_ PREC
export %inline
qbrackets : {opts : LayoutOpts} -> Doc opts -> Eff Pretty (Doc opts)
qbrackets doc = tightDelims !(ifUnicode "" ".{") !(ifUnicode "" "}") doc
export
prettyName : Name -> Doc opts
@ -263,12 +270,16 @@ export
prettyDBind : {opts : LayoutOpts} -> BindName -> Eff Pretty (Doc opts)
prettyDBind = hl DVar . prettyBind'
export
prettyQBind : {opts : LayoutOpts} -> BindName -> Eff Pretty (Doc opts)
prettyQBind = hl QVar . prettyBind'
export %inline
typeD, ioStateD, arrowD, darrowD, timesD, lamD, eqndD, dlamD, annD, natD,
stringD, eqD, colonD, commaD, semiD, atD, caseD, typecaseD, returnD, ofD, dotD,
zeroD, succD, coeD, compD, undD, cstD, pipeD, fstD, sndD, letD, inD :
zeroD, succD, coeD, compD, undD, cstD, pipeD, fstD, sndD, letD, inD,
qplusD, qtimesD :
{opts : LayoutOpts} -> Eff Pretty (Doc opts)
typeD = hl Syntax . text =<< ifUnicode "" "Type"
ioStateD = hl Syntax $ text "IOState"
@ -302,6 +313,8 @@ fstD = hl Syntax $ text "fst"
sndD = hl Syntax $ text "snd"
letD = hl Syntax $ text "let"
inD = hl Syntax $ text "in"
qplusD = hl Syntax $ text "+"
qtimesD = hl Syntax . text =<< ifUnicode "·" "*"
export
@ -315,7 +328,7 @@ prettyApp ind f args =
export
prettyAppD : {opts : LayoutOpts} -> Doc opts -> List (Doc opts) ->
Eff Pretty (Doc opts)
prettyAppD f args = pure $ prettyApp !(askAt INDENT) f args
prettyAppD f args = parensIfM App $ prettyApp !(askAt INDENT) f args
export
@ -345,7 +358,7 @@ prettyBounds (MkBounds l1 c1 l2 c2) =
export
prettyLoc : {opts : LayoutOpts} -> Loc -> Eff Pretty (Doc opts)
prettyLoc (L NoLoc) =
hcat <$> sequence [hl TVarErr "no location", colonD]
hcat <$> sequence [hl TVar "no location", colonD]
prettyLoc (L (YesLoc file b)) =
hcat <$> sequence [hl Free $ text file, colonD, prettyBounds b]

122
lib/Quox/Semiring.idr Normal file
View file

@ -0,0 +1,122 @@
module Quox.Semiring
import Quox.Context
import public Quox.NatExtra
import Data.Bool.Decidable
import Quox.No
%hide Nat.isZero
export infixl 8 +.
export infixl 9 *., *:, :*
export infixr 10 ^.
public export
interface AddMonoid a where
zero : a
isZero : a -> Bool
(+.) : a -> a -> a
public export
interface TimesMonoid a where
one : a
(*.) : a -> a -> a
public export
0 Semiring : Type -> Type
Semiring a = (AddMonoid a, TimesMonoid a)
public export
interface (Semiring base, AddMonoid vec) => VecSpace base vec | vec where
(*:) : base -> vec -> vec
(:*) : vec -> base -> vec
x *: xs = xs :* x
xs :* x = x *: xs
namespace Foldable
public export %inline %tcinline
ssum : AddMonoid a => Foldable t => {default zero init : a} -> t a -> a
ssum = foldl (+.) init
public export %inline %tcinline
sproduct : TimesMonoid a => Foldable t => {default one init : a} -> t a -> a
sproduct = foldl (*.) init
namespace Context
public export %inline %tcinline
ssum : AddMonoid a => {default zero init : a} ->
Telescope' a from to -> a
ssum = foldl_ (+.) zero
public export %inline %tcinline
sproduct : TimesMonoid a => {default one init : a} ->
Telescope' a from to -> a
sproduct = foldl_ (*.) one
public export
(^.) : TimesMonoid a => a -> Nat -> a
x ^. 0 = one
x ^. S k = x *. x^.k
export %inline
[NumAdd] Eq a => Num a => AddMonoid a where
zero = 0; (+.) = (+); isZero = (== 0)
export %inline
[NumTimes] Num a => TimesMonoid a where
one = 1; (*.) = (*)
export %inline %hint
NatAM : AddMonoid Nat
NatAM = NumAdd
export %inline %hint
NatTM : TimesMonoid Nat
NatTM = NumTimes
export %inline %hint
IntegerAM : AddMonoid Integer
IntegerAM = NumAdd
export %inline %hint
IntegerTM : TimesMonoid Integer
IntegerTM = NumTimes
export %inline %hint
IntAM : AddMonoid Int
IntAM = NumAdd
export %inline %hint
IntTM : TimesMonoid Int
IntTM = NumTimes
export %inline
(from `LTE'` to, AddMonoid a) => AddMonoid (Telescope' a from to) where
zero = replicateLTE zero
(+.) = zipWith (+.)
isZero = all isZero
export %inline
(from `LTE'` to, Semiring a) => VecSpace a (Telescope' a from to) where
x *: xs = map (x *.) xs
public export
interface AddMonoid a => MonoAddMonoid a where
0 zeroPlus : (x, y : a) ->
No (isZero x) -> No (isZero y) -> No (isZero (x +. y))
export
MonoAddMonoid Nat where
zeroPlus (S _) (S _) Ah Ah = Ah
public export
0 MonoAddSemiring : Type -> Type
MonoAddSemiring a = (MonoAddMonoid a, TimesMonoid a)

View file

@ -0,0 +1,11 @@
module Quox.SingletonExtra
import public Data.Singleton
public export
map : (f : a -> b) -> Singleton x -> Singleton (f x)
map f x = [|f x|]
public export
(<$>) : (f : a -> b) -> Singleton x -> Singleton (f x)
(<$>) = map

View file

@ -21,7 +21,7 @@ builtinDesc Main = "a function declared as #[main]"
public export
builtinTypeDoc : {opts : LayoutOpts} -> Builtin -> Eff Pretty (Doc opts)
builtinTypeDoc Main =
prettyTerm [<] [<] $
Pi One (IOState noLoc)
prettyTerm empty $
Pi {q = 0} (one noLoc) (IOState noLoc)
(SN $ Sig (Enum (fromList [!(ifUnicode "𝑎" "a")]) noLoc)
(SN (IOState noLoc)) noLoc) noLoc

View file

@ -84,7 +84,11 @@ DSubst : Nat -> Nat -> Type
DSubst = Subst Dim
public export FromVar Dim where fromVarLoc = B
public export
FromVarR Dim where fromVarR = B
public export
FromVar Dim where fromVar = B; fromVarSame _ _ = Refl
export
@ -92,10 +96,16 @@ CanShift Dim where
K e loc // _ = K e loc
B i loc // by = B (i // by) loc
private
substDim : Dim from -> Lazy (DSubst from to) -> Dim to
substDim (K e loc) _ = K e loc
substDim (B i loc) th = get th i loc
export
CanSubstSelf Dim where
K e loc // _ = K e loc
B i loc // th = getLoc th i loc
CanSubstSelfR Dim where (//?) = substDim
export
CanSubstSelf Dim where (//) = substDim; substSame _ _ = Refl
export Uninhabited (B i loc1 = K e loc2) where uninhabited _ impossible

View file

@ -4,10 +4,14 @@
||| it's worth in a language that has other stuff going on too
module Quox.Syntax.Qty
import public Quox.Polynomial
import Quox.Name
import Quox.Syntax.Subst
import Quox.Pretty
import Quox.Decidable
import Quox.PrettyValExtra
import Data.DPair
import Data.Singleton
import Derive.Prelude
%default total
@ -20,61 +24,124 @@ import Derive.Prelude
||| - 1: a variable is used exactly once at run time
||| - ω (or #): don't care. an ω variable *can* also be used 0/1 time
public export
data Qty = Zero | One | Any
%runElab derive "Qty" [Eq, Ord, Show, PrettyVal]
%name Qty.Qty pi, rh
data QConst = Zero | One | Any
%runElab derive "QConst" [Eq, Ord, Show, PrettyVal]
%name QConst q, r
export
prettyQty : {opts : _} -> Qty -> Eff Pretty (Doc opts)
prettyQty Zero = hl Qty $ text "0"
prettyQty One = hl Qty $ text "1"
prettyQty Any = hl Qty =<< ifUnicode (text "ω") (text "#")
prettyQConst : {opts : _} -> QConst -> Eff Pretty (Doc opts)
prettyQConst Zero = hl Qty $ text "0"
prettyQConst One = hl Qty $ text "1"
prettyQConst Any = hl Qty =<< ifUnicode (text "ω") (text "#")
||| prints in a form that can be a suffix of "case"
public export
prettySuffix : {opts : _} -> Qty -> Eff Pretty (Doc opts)
prettySuffix = prettyQty
-- ||| prints in a form that can be a suffix of "case"
-- public export
-- prettySuffix : {opts : _} -> Qty -> Eff Pretty (Doc opts)
-- prettySuffix = prettyQty
namespace QConst
||| e.g. if in the expression `(s, t)`, the variable `x` is
||| used π times in `s` and ρ times in `t`, then it's used
||| (π + ρ) times in the whole expression
public export
(+) : Qty -> Qty -> Qty
Zero + rh = rh
pi + Zero = pi
_ + _ = Any
plus : QConst -> QConst -> QConst
plus Zero rh = rh
plus pi Zero = pi
plus _ _ = Any
||| e.g. if a function `f` uses its argument π times,
||| and `f x` occurs in a σ context, then `x` is used `πσ` times overall
public export
(*) : Qty -> Qty -> Qty
Zero * _ = Zero
_ * Zero = Zero
One * rh = rh
pi * One = pi
Any * Any = Any
times : QConst -> QConst -> QConst
times Zero _ = Zero
times _ Zero = Zero
times One rh = rh
times pi One = pi
times Any Any = Any
-- ||| "π ρ"
-- |||
-- ||| returns a quantity τ with π ≤ τ and ρ ≤ τ.
-- ||| if π = ρ, then it's that, otherwise it's ω.
-- public export
-- lub : QConst -> QConst -> QConst
-- lub p q = if p == q then p else Any
export %inline
AddMonoid QConst where zero = Zero; (+.) = plus; isZero = (== Zero)
export %inline
TimesMonoid QConst where one = One; (*.) = times
public export
record Qty n where
constructor Q
value : Polynomial QConst n
loc : Loc
%runElab deriveIndexed "Qty" [Eq, Ord]
export %hint
ShowQty : {n : Nat} -> Show (Qty n)
ShowQty = deriveShow
export %hint
PrettyValQty : {n : Nat} -> PrettyVal (Qty n)
PrettyValQty = derivePrettyVal
export
zero, one, any : {n : Nat} -> Loc -> Qty n
zero = Q zero
one = Q one
any = Q $ pconst Any
export
(+) : Qty n -> Qty n -> Qty n
Q xs l1 + Q ys l2 = Q (xs +. ys) (l1 `or` l2)
export
(*) : Qty n -> Qty n -> Qty n
Q xs l1 * Q ys l2 = Q (xs *. ys) (l1 `or` l2)
export
isAny : Qty n -> Bool
isAny (Q pi _) = pi.at0 == Any
export
lub : {n : Nat} -> Qty n -> Qty n -> Qty n
lub pi rh = if pi == rh then pi else any pi.loc
||| "π ≤ ρ"
|||
||| if a variable is bound with quantity ρ, then it can be used with a total
||| if a variable is bound with quantity ρ, then it can be used with an actual
||| quantity π as long as π ≤ ρ. for example, an ω variable can be used any
||| number of times, so π ≤ ω for any π.
public export
compat : Qty -> Qty -> Bool
compat pi Any = True
compat pi rh = pi == rh
compat : Qty n -> Qty n -> Bool
compat pi rh = isAny rh || pi == rh
||| "π ρ"
|||
||| returns a quantity τ with π ≤ τ and ρ ≤ τ.
||| if π = ρ, then it's that, otherwise it's ω.
public export
lub : Qty -> Qty -> Qty
lub p q = if p == q then p else Any
private
toVarString : BContext n -> Monom n -> List BindName
toVarString ns ds = fold $ zipWith replicate ds ns
private
prettyTerm : {opts : LayoutOpts} ->
BContext n -> Monom n -> QConst -> Eff Pretty (Doc opts)
prettyTerm ns ds pi = do
pi <- prettyQConst pi
xs <- traverse prettyQBind (toVarString ns ds)
pure $ separateTight !qtimesD $ pi :: xs
export
prettyQty : {opts : LayoutOpts} -> BContext n -> Qty n -> Eff Pretty (Doc opts)
prettyQty ns (Q q _) =
let Val _ = lengthPrf0 ns in
separateLoose !qplusD <$>
traverse (uncurry $ prettyTerm ns) (toList q)
||| to maintain subject reduction, only 0 or 1 can occur
||| for the subject of a typing judgment. see @qtt, §2.3 for more detail
@ -87,9 +154,8 @@ data SQty = SZero | SOne
|||
||| σ ⨴ π is 0 if either of σ or π are, otherwise it is σ.
public export
subjMult : SQty -> Qty -> SQty
subjMult _ Zero = SZero
subjMult sg _ = sg
subjMult : SQty -> Qty n -> SQty
subjMult sg pi = if isZero pi.value then SZero else sg
||| it doesn't make much sense for a top level declaration to have a
@ -100,12 +166,6 @@ data GQty = GZero | GAny
%runElab derive "GQty" [Eq, Ord, Show, PrettyVal]
%name GQty rh
public export
toGlobal : Qty -> Maybe GQty
toGlobal Zero = Just GZero
toGlobal Any = Just GAny
toGlobal One = Nothing
||| when checking a definition, a 0 definition is checked at 0,
||| but an ω definition is checked at 1 since ω isn't a subject quantity
public export %inline
@ -114,18 +174,6 @@ globalToSubj GZero = SZero
globalToSubj GAny = SOne
public export
DecEq Qty where
decEq Zero Zero = Yes Refl
decEq Zero One = No $ \case _ impossible
decEq Zero Any = No $ \case _ impossible
decEq One Zero = No $ \case _ impossible
decEq One One = Yes Refl
decEq One Any = No $ \case _ impossible
decEq Any Zero = No $ \case _ impossible
decEq Any One = No $ \case _ impossible
decEq Any Any = Yes Refl
public export
DecEq SQty where
decEq SZero SZero = Yes Refl
@ -143,12 +191,48 @@ DecEq GQty where
namespace SQty
public export %inline
(.qty) : SQty -> Qty
(SZero).qty = Zero
(SOne).qty = One
toQty : {n : Nat} -> Loc -> SQty -> Qty n
toQty loc SZero = zero loc
toQty loc SOne = one loc
public export %inline
(.qconst) : SQty -> QConst
(SZero).qconst = Zero
(SOne).qconst = One
namespace GQty
public export %inline
(.qty) : GQty -> Qty
(GZero).qty = Zero
(GAny).qty = Any
toQty : {n : Nat} -> Loc -> GQty -> Qty n
toQty loc GZero = zero loc
toQty loc GAny = any loc
public export %inline
(.qconst) : GQty -> QConst
(GZero).qconst = Zero
(GAny).qconst = Any
export
prettySQty : {opts : _} -> SQty -> Eff Pretty (Doc opts)
prettySQty sg = prettyQConst sg.qconst
export
prettyGQty : {opts : _} -> GQty -> Eff Pretty (Doc opts)
prettyGQty pi = prettyQConst pi.qconst
public export
QSubst : Nat -> Nat -> Type
QSubst = Subst Qty
export
FromVarR Qty where
fromVarR i loc = Q (fromVarR i loc) loc
export
CanShift Qty where
Q p loc // by = Q (p // by) loc
export
CanSubstSelfR Qty where
Q q loc //? th = Q (q //? map (.value) th) loc

View file

@ -42,24 +42,46 @@ export Ord (f to) => Ord (Subst f from to) where compare = compare `on` repr
export Show (f to) => Show (Subst f from to) where show = show . repr
export infixl 8 //
export infixl 8 //?, //
public export
interface FromVar term => CanSubstSelf term where
interface FromVarR term => CanSubstSelfR term where
(//?) : {from, to : Nat} ->
term from -> Lazy (Subst term from to) -> term to
public export
interface (FromVar term, CanSubstSelfR term) => CanSubstSelf term where
(//) : term from -> Lazy (Subst term from to) -> term to
0 substSame : (t : term from) -> (th : Subst term from to) ->
t //? th === t // th
public export
getLoc : FromVar term => Subst term from to -> Var from -> Loc -> term to
getLoc (Shift by) i loc = fromVarLoc (shift by i) loc
getLoc (t ::: th) VZ _ = t
getLoc (t ::: th) (VS i) loc = getLoc th i loc
getR : {to : Nat} -> FromVarR term =>
Subst term from to -> Var from -> Loc -> term to
getR (Shift by) i loc = fromVarR (shift by i) loc
getR (t ::: th) VZ _ = t
getR (t ::: th) (VS i) loc = getR th i loc
public export
get : FromVar term => Subst term from to -> Var from -> Loc -> term to
get (Shift by) i loc = fromVar (shift by i) loc
get (t ::: th) VZ _ = t
get (t ::: th) (VS i) loc = get th i loc
public export
CanSubstSelf Var where
i // Shift by = shift by i
VZ // (t ::: th) = t
VS i // (t ::: th) = i // th
substVar : Var from -> Lazy (Subst Var from to) -> Var to
substVar i (Shift by) = shift by i
substVar VZ (t ::: th) = t
substVar (VS i) (t ::: th) = substVar i th
public export
CanSubstSelfR Var where (//?) = substVar
public export
CanSubstSelf Var where (//) = substVar; substSame _ _ = Refl
public export %inline
@ -71,6 +93,16 @@ shift0 : (by : Nat) -> Subst env 0 by
shift0 by = rewrite sym $ plusZeroRightNeutral by in Shift $ fromNat by
export infixr 9 .?
public export
(.?) : CanSubstSelfR f => {from, mid, to : Nat} ->
Subst f from mid -> Subst f mid to -> Subst f from to
Shift by .? Shift bz = Shift $ by . bz
Shift SZ .? ph = ph
Shift (SS by) .? (t ::: th) = Shift by .? th
(t ::: th) .? ph = (t //? ph) ::: (th .? ph)
public export
(.) : CanSubstSelf f => Subst f from mid -> Subst f mid to -> Subst f from to
Shift by . Shift bz = Shift $ by . bz
@ -78,6 +110,7 @@ Shift SZ . ph = ph
Shift (SS by) . (t ::: th) = Shift by . th
(t ::: th) . ph = (t // ph) ::: (th . ph)
public export %inline
id : Subst f n n
id = shift 0
@ -95,11 +128,20 @@ map f (Shift by) = Shift by
map f (t ::: th) = f t ::: map f th
public export %inline
push : CanSubstSelf f => Loc -> Subst f from to -> Subst f (S from) (S to)
push loc th = fromVarLoc VZ loc ::: (th . shift 1)
public export
pushNR : {from, to : Nat} -> CanSubstSelfR f => (s : Nat) -> Loc ->
Subst f from to -> Subst f (s + from) (s + to)
pushNR 0 _ th = th
pushNR (S s) loc th =
rewrite plusSuccRightSucc s from in
rewrite plusSuccRightSucc s to in
pushNR s loc $ fromVarR VZ loc ::: (th .? shift 1)
public export %inline
pushR : {from, to : Nat} -> CanSubstSelfR f =>
Loc -> Subst f from to -> Subst f (S from) (S to)
pushR = pushNR 1
-- [fixme] a better way to do this?
public export
pushN : CanSubstSelf f => (s : Nat) -> Loc ->
Subst f from to -> Subst f (s + from) (s + to)
@ -107,7 +149,11 @@ pushN 0 _ th = th
pushN (S s) loc th =
rewrite plusSuccRightSucc s from in
rewrite plusSuccRightSucc s to in
pushN s loc $ fromVarLoc VZ loc ::: (th . shift 1)
pushN s loc $ fromVar VZ loc ::: (th . shift 1)
public export %inline
push : CanSubstSelf f => Loc -> Subst f from to -> Subst f (S from) (S to)
push = pushN 1
public export
drop1 : Subst f (S from) to -> Subst f from to
@ -167,3 +213,30 @@ export %hint
ShowWithSubst : (Show (env n), forall n. Show (tm n)) =>
Show (WithSubst tm env n)
ShowWithSubst = deriveShow
public export
record WithSubstR tm env n where
constructor SubR
{from : Nat}
term : tm from
subst : Lazy (Subst env from n)
export
(Eq (env n), forall n. Eq (tm n)) => Eq (WithSubstR tm env n) where
SubR {from = m1} t1 s1 == SubR {from = m2} t2 s2 =
case decEq m1 m2 of
Yes Refl => t1 == t2 && s1 == s2
No _ => False
export
(Ord (env n), forall n. Ord (tm n)) => Ord (WithSubstR tm env n) where
SubR {from = m1} t1 s1 `compare` SubR {from = m2} t2 s2 =
case cmp m1 m2 of
CmpLT _ => LT
CmpEQ => compare (t1, s1) (t2, s2)
CmpGT _ => GT
export %hint
ShowWithSubstR : (Show (env n), forall n. Show (tm n)) =>
Show (WithSubstR tm env n)
ShowWithSubstR = deriveShow

View file

@ -32,11 +32,11 @@ import Derive.Prelude
public export
TermLike : Type
TermLike = Nat -> Nat -> Type
TermLike = (q, d, n : Nat) -> Type
public export
TSubstLike : Type
TSubstLike = Nat -> Nat -> Nat -> Type
TSubstLike = (q, d, n1, n2 : Nat) -> Type
public export
Universe : Type
@ -50,156 +50,162 @@ TagVal = String
mutual
public export
TSubst : TSubstLike
TSubst d = Subst $ \n => Elim d n
TSubst q d = Subst $ \n => Elim q d n
||| first argument `d` is dimension scope size;
||| second `n` is term scope size
public export
data Term : (d, n : Nat) -> Type where
data Term : (q, d, n : Nat) -> Type where
||| type of types
TYPE : (l : Universe) -> (loc : Loc) -> Term d n
TYPE : (l : Universe) -> (loc : Loc) -> Term q d n
||| IO state token. this is a builtin because otherwise #[main] being a
||| builtin makes no sense
IOState : (loc : Loc) -> Term d n
IOState : (loc : Loc) -> Term q d n
||| function type
Pi : (qty : Qty) -> (arg : Term d n) ->
(res : ScopeTerm d n) -> (loc : Loc) -> Term d n
Pi : (qty : Qty q) -> (arg : Term q d n) ->
(res : ScopeTerm q d n) -> (loc : Loc) -> Term q d n
||| function term
Lam : (body : ScopeTerm d n) -> (loc : Loc) -> Term d n
Lam : (body : ScopeTerm q d n) -> (loc : Loc) -> Term q d n
||| pair type
Sig : (fst : Term d n) -> (snd : ScopeTerm d n) -> (loc : Loc) -> Term d n
Sig : (fst : Term q d n) -> (snd : ScopeTerm q d n) -> (loc : Loc) ->
Term q d n
||| pair value
Pair : (fst, snd : Term d n) -> (loc : Loc) -> Term d n
Pair : (fst, snd : Term q d n) -> (loc : Loc) -> Term q d n
||| enumeration type
Enum : (cases : SortedSet TagVal) -> (loc : Loc) -> Term d n
Enum : (cases : SortedSet TagVal) -> (loc : Loc) -> Term q d n
||| enumeration value
Tag : (tag : TagVal) -> (loc : Loc) -> Term d n
Tag : (tag : TagVal) -> (loc : Loc) -> Term q d n
||| equality type
Eq : (ty : DScopeTerm d n) -> (l, r : Term d n) -> (loc : Loc) -> Term d n
Eq : (ty : DScopeTerm q d n) -> (l, r : Term q d n) -> (loc : Loc) ->
Term q d n
||| equality term
DLam : (body : DScopeTerm d n) -> (loc : Loc) -> Term d n
DLam : (body : DScopeTerm q d n) -> (loc : Loc) -> Term q d n
||| natural numbers (temporary until 𝐖 gets added)
NAT : (loc : Loc) -> Term d n
Nat : (val : Nat) -> (loc : Loc) -> Term d n
Succ : (p : Term d n) -> (loc : Loc) -> Term d n
NAT : (loc : Loc) -> Term q d n
Nat : (val : Nat) -> (loc : Loc) -> Term q d n
Succ : (p : Term q d n) -> (loc : Loc) -> Term q d n
||| strings
STRING : (loc : Loc) -> Term d n
Str : (str : String) -> (loc : Loc) -> Term d n
STRING : (loc : Loc) -> Term q d n
Str : (str : String) -> (loc : Loc) -> Term q d n
||| "box" (package a value up with a certain quantity)
BOX : (qty : Qty) -> (ty : Term d n) -> (loc : Loc) -> Term d n
Box : (val : Term d n) -> (loc : Loc) -> Term d n
BOX : (qty : Qty q) -> (ty : Term q d n) -> (loc : Loc) -> Term q d n
Box : (val : Term q d n) -> (loc : Loc) -> Term q d n
Let : (qty : Qty) -> (rhs : Elim d n) ->
(body : ScopeTerm d n) -> (loc : Loc) -> Term d n
Let : (qty : Qty q) -> (rhs : Elim q d n) ->
(body : ScopeTerm q d n) -> (loc : Loc) -> Term q d n
||| elimination
E : (e : Elim d n) -> Term d n
E : (e : Elim q d n) -> Term q d n
||| term closure/suspended substitution
CloT : WithSubst (Term d) (Elim d) n -> Term d n
CloT : WithSubst (Term q d) (Elim q d) n -> Term q d n
||| dimension closure/suspended substitution
DCloT : WithSubst (\d => Term d n) Dim d -> Term d n
DCloT : WithSubst (\d => Term q d n) Dim d -> Term q d n
||| quantity closure/suspended substitution
QCloT : WithSubstR (\q => Term q d n) Qty q -> Term q d n
%name Term s, t, r
||| first argument `d` is dimension scope size, second `n` is term scope size
public export
data Elim : (d, n : Nat) -> Type where
data Elim : (q, d, n : Nat) -> Type where
||| free variable, possibly with a displacement (see @crude, or @mugen for a
||| more abstract and formalised take)
|||
||| e.g. if f : ★₀ → ★₁, then f¹ : ★₁ → ★₂
F : (x : Name) -> (u : Universe) -> (loc : Loc) -> Elim d n
F : (x : Name) -> (u : Universe) -> (loc : Loc) -> Elim q d n
||| bound variable
B : (i : Var n) -> (loc : Loc) -> Elim d n
B : (i : Var n) -> (loc : Loc) -> Elim q d n
||| term application
App : (fun : Elim d n) -> (arg : Term d n) -> (loc : Loc) -> Elim d n
App : (fun : Elim q d n) -> (arg : Term q d n) -> (loc : Loc) -> Elim q d n
||| pair destruction
|||
||| `CasePair 𝜋 𝑒 ([𝑟], 𝐴) ([𝑥, 𝑦], 𝑡)` is
||| `𝐜𝐚𝐬𝐞 𝜋 · 𝑒 𝐫𝐞𝐭𝐮𝐫𝐧 𝑟𝐴 𝐨𝐟 { (𝑥, 𝑦) ⇒ 𝑡 }`
CasePair : (qty : Qty) -> (pair : Elim d n) ->
(ret : ScopeTerm d n) ->
(body : ScopeTermN 2 d n) ->
CasePair : (qty : Qty q) -> (pair : Elim q d n) ->
(ret : ScopeTerm q d n) ->
(body : ScopeTermN 2 q d n) ->
(loc : Loc) ->
Elim d n
Elim q d n
||| first element of a pair. only works in non-linear contexts.
Fst : (pair : Elim d n) -> (loc : Loc) -> Elim d n
Fst : (pair : Elim q d n) -> (loc : Loc) -> Elim q d n
||| second element of a pair. only works in non-linear contexts.
Snd : (pair : Elim d n) -> (loc : Loc) -> Elim d n
Snd : (pair : Elim q d n) -> (loc : Loc) -> Elim q d n
||| enum matching
CaseEnum : (qty : Qty) -> (tag : Elim d n) ->
(ret : ScopeTerm d n) ->
(arms : CaseEnumArms d n) ->
CaseEnum : (qty : Qty q) -> (tag : Elim q d n) ->
(ret : ScopeTerm q d n) ->
(arms : CaseEnumArms q d n) ->
(loc : Loc) ->
Elim d n
Elim q d n
||| nat matching
CaseNat : (qty, qtyIH : Qty) -> (nat : Elim d n) ->
(ret : ScopeTerm d n) ->
(zero : Term d n) ->
(succ : ScopeTermN 2 d n) ->
CaseNat : (qty, qtyIH : Qty q) -> (nat : Elim q d n) ->
(ret : ScopeTerm q d n) ->
(zero : Term q d n) ->
(succ : ScopeTermN 2 q d n) ->
(loc : Loc) ->
Elim d n
Elim q d n
||| unboxing
CaseBox : (qty : Qty) -> (box : Elim d n) ->
(ret : ScopeTerm d n) ->
(body : ScopeTerm d n) ->
CaseBox : (qty : Qty q) -> (box : Elim q d n) ->
(ret : ScopeTerm q d n) ->
(body : ScopeTerm q d n) ->
(loc : Loc) ->
Elim d n
Elim q d n
||| dim application
DApp : (fun : Elim d n) -> (arg : Dim d) -> (loc : Loc) -> Elim d n
DApp : (fun : Elim q d n) -> (arg : Dim d) -> (loc : Loc) -> Elim q d n
||| type-annotated term
Ann : (tm, ty : Term d n) -> (loc : Loc) -> Elim d n
Ann : (tm, ty : Term q d n) -> (loc : Loc) -> Elim q d n
||| coerce a value along a type equality, or show its coherence
||| [@xtt; §2.1.1]
Coe : (ty : DScopeTerm d n) -> (p, q : Dim d) ->
(val : Term d n) -> (loc : Loc) -> Elim d n
Coe : (ty : DScopeTerm q d n) -> (p, p' : Dim d) ->
(val : Term q d n) -> (loc : Loc) -> Elim q d n
||| "generalised composition" [@xtt; §2.1.2]
Comp : (ty : Term d n) -> (p, q : Dim d) ->
(val : Term d n) -> (r : Dim d) ->
(zero, one : DScopeTerm d n) -> (loc : Loc) -> Elim d n
Comp : (ty : Term q d n) -> (p, p' : Dim d) ->
(val : Term q d n) -> (r : Dim d) ->
(zero, one : DScopeTerm q d n) -> (loc : Loc) -> Elim q d n
||| match on types. needed for b.s. of coercions [@xtt; §2.2]
TypeCase : (ty : Elim d n) -> (ret : Term d n) ->
(arms : TypeCaseArms d n) -> (def : Term d n) ->
TypeCase : (ty : Elim q d n) -> (ret : Term q d n) ->
(arms : TypeCaseArms q d n) -> (def : Term q d n) ->
(loc : Loc) ->
Elim d n
Elim q d n
||| term closure/suspended substitution
CloE : WithSubst (Elim d) (Elim d) n -> Elim d n
CloE : WithSubst (Elim q d) (Elim q d) n -> Elim q d n
||| dimension closure/suspended substitution
DCloE : WithSubst (\d => Elim d n) Dim d -> Elim d n
DCloE : WithSubst (\d => Elim q d n) Dim d -> Elim q d n
||| quantity closure/suspended substitution
QCloE : WithSubstR (\q => Elim q d n) Qty q -> Elim q d n
%name Elim e, f
public export
CaseEnumArms : TermLike
CaseEnumArms d n = SortedMap TagVal (Term d n)
CaseEnumArms q d n = SortedMap TagVal (Term q d n)
public export
TypeCaseArms : TermLike
TypeCaseArms d n = SortedDMap TyConKind (\k => TypeCaseArmBody k d n)
TypeCaseArms q d n = SortedDMap TyConKind (\k => TypeCaseArmBody k q d n)
public export
TypeCaseArm : TermLike
TypeCaseArm d n = (k ** TypeCaseArmBody k d n)
TypeCaseArm q d n = (k ** TypeCaseArmBody k q d n)
public export
TypeCaseArmBody : TyConKind -> TermLike
@ -208,35 +214,27 @@ mutual
public export
ScopeTermN, DScopeTermN : Nat -> TermLike
ScopeTermN s d n = Scoped s (Term d) n
DScopeTermN s d n = Scoped s (\d => Term d n) d
ScopeTermN s q d n = Scoped s (Term q d) n
DScopeTermN s q d n = Scoped s (\d => Term q d n) d
public export
ScopeTerm, DScopeTerm : TermLike
ScopeTerm = ScopeTermN 1
DScopeTerm = DScopeTermN 1
mutual
export %hint
EqTerm : Eq (Term d n)
EqTerm = assert_total {a = Eq (Term d n)} deriveEq
export %hint EqTerm : Eq (Term q d n)
export %hint EqElim : Eq (Elim q d n)
EqTerm = assert_total {a = Eq (Term q d n)} deriveEq
EqElim = assert_total {a = Eq (Elim q d n)} deriveEq
export %hint
EqElim : Eq (Elim d n)
EqElim = assert_total {a = Eq (Elim d n)} deriveEq
mutual
export %hint
ShowTerm : Show (Term d n)
ShowTerm = assert_total {a = Show (Term d n)} deriveShow
export %hint
ShowElim : Show (Elim d n)
ShowElim = assert_total {a = Show (Elim d n)} deriveShow
-- export %hint ShowTerm : {q, d, n : Nat} -> Show (Term q d n)
-- export %hint ShowElim : {q, d, n : Nat} -> Show (Elim q d n)
-- ShowTerm = assert_total {a = Show (Term q d n)} deriveShow
-- ShowElim = assert_total {a = Show (Elim q d n)} deriveShow
export
Located (Elim d n) where
Located (Elim q d n) where
(F _ _ loc).loc = loc
(B _ loc).loc = loc
(App _ _ loc).loc = loc
@ -253,9 +251,10 @@ Located (Elim d n) where
(TypeCase _ _ _ _ loc).loc = loc
(CloE (Sub e _)).loc = e.loc
(DCloE (Sub e _)).loc = e.loc
(QCloE (SubR e _)).loc = e.loc
export
Located (Term d n) where
Located (Term q d n) where
(TYPE _ loc).loc = loc
(IOState loc).loc = loc
(Pi _ _ _ loc).loc = loc
@ -277,6 +276,7 @@ Located (Term d n) where
(E e).loc = e.loc
(CloT (Sub t _)).loc = t.loc
(DCloT (Sub t _)).loc = t.loc
(QCloT (SubR t _)).loc = t.loc
export
Located1 f => Located (ScopedBody s f n) where
@ -289,7 +289,7 @@ Located1 f => Located (Scoped s f n) where
export
Relocatable (Elim d n) where
Relocatable (Elim q d n) where
setLoc loc (F x u _) = F x u loc
setLoc loc (B i _) = B i loc
setLoc loc (App fun arg _) = App fun arg loc
@ -317,9 +317,11 @@ Relocatable (Elim d n) where
CloE $ Sub (setLoc loc term) subst
setLoc loc (DCloE (Sub term subst)) =
DCloE $ Sub (setLoc loc term) subst
setLoc loc (QCloE (SubR term subst)) =
QCloE $ SubR (setLoc loc term) subst
export
Relocatable (Term d n) where
Relocatable (Term q d n) where
setLoc loc (TYPE l _) = TYPE l loc
setLoc loc (IOState _) = IOState loc
setLoc loc (Pi qty arg res _) = Pi qty arg res loc
@ -341,6 +343,7 @@ Relocatable (Term d n) where
setLoc loc (E e) = E $ setLoc loc e
setLoc loc (CloT (Sub term subst)) = CloT $ Sub (setLoc loc term) subst
setLoc loc (DCloT (Sub term subst)) = DCloT $ Sub (setLoc loc term) subst
setLoc loc (QCloT (SubR term subst)) = QCloT $ SubR (setLoc loc term) subst
export
Relocatable1 f => Relocatable (ScopedBody s f n) where
@ -354,93 +357,93 @@ Relocatable1 f => Relocatable (Scoped s f n) where
||| more convenient Pi
public export %inline
PiY : (qty : Qty) -> (x : BindName) ->
(arg : Term d n) -> (res : Term d (S n)) -> (loc : Loc) -> Term d n
PiY : (qty : Qty q) -> (x : BindName) ->
(arg : Term q d n) -> (res : Term q d (S n)) -> (loc : Loc) -> Term q d n
PiY {qty, x, arg, res, loc} = Pi {qty, arg, res = SY [< x] res, loc}
||| more convenient Lam
public export %inline
LamY : (x : BindName) -> (body : Term d (S n)) -> (loc : Loc) -> Term d n
LamY : (x : BindName) -> (body : Term q d (S n)) -> (loc : Loc) -> Term q d n
LamY {x, body, loc} = Lam {body = SY [< x] body, loc}
public export %inline
LamN : (body : Term d n) -> (loc : Loc) -> Term d n
LamN : (body : Term q d n) -> (loc : Loc) -> Term q d n
LamN {body, loc} = Lam {body = SN body, loc}
||| non dependent function type
public export %inline
Arr : (qty : Qty) -> (arg, res : Term d n) -> (loc : Loc) -> Term d n
Arr : (qty : Qty q) -> (arg, res : Term q d n) -> (loc : Loc) -> Term q d n
Arr {qty, arg, res, loc} = Pi {qty, arg, res = SN res, loc}
||| more convenient Sig
public export %inline
SigY : (x : BindName) -> (fst : Term d n) ->
(snd : Term d (S n)) -> (loc : Loc) -> Term d n
SigY : (x : BindName) -> (fst : Term q d n) ->
(snd : Term q d (S n)) -> (loc : Loc) -> Term q d n
SigY {x, fst, snd, loc} = Sig {fst, snd = SY [< x] snd, loc}
||| non dependent pair type
public export %inline
And : (fst, snd : Term d n) -> (loc : Loc) -> Term d n
And : (fst, snd : Term q d n) -> (loc : Loc) -> Term q d n
And {fst, snd, loc} = Sig {fst, snd = SN snd, loc}
||| more convenient Eq
public export %inline
EqY : (i : BindName) -> (ty : Term (S d) n) ->
(l, r : Term d n) -> (loc : Loc) -> Term d n
EqY : (i : BindName) -> (ty : Term q (S d) n) ->
(l, r : Term q d n) -> (loc : Loc) -> Term q d n
EqY {i, ty, l, r, loc} = Eq {ty = SY [< i] ty, l, r, loc}
||| more convenient DLam
public export %inline
DLamY : (i : BindName) -> (body : Term (S d) n) -> (loc : Loc) -> Term d n
DLamY : (i : BindName) -> (body : Term q (S d) n) -> (loc : Loc) -> Term q d n
DLamY {i, body, loc} = DLam {body = SY [< i] body, loc}
public export %inline
DLamN : (body : Term d n) -> (loc : Loc) -> Term d n
DLamN : (body : Term q d n) -> (loc : Loc) -> Term q d n
DLamN {body, loc} = DLam {body = SN body, loc}
||| non dependent equality type
public export %inline
Eq0 : (ty, l, r : Term d n) -> (loc : Loc) -> Term d n
Eq0 : (ty, l, r : Term q d n) -> (loc : Loc) -> Term q d n
Eq0 {ty, l, r, loc} = Eq {ty = SN ty, l, r, loc}
||| same as `F` but as a term
public export %inline
FT : Name -> Universe -> Loc -> Term d n
FT : Name -> Universe -> Loc -> Term q d n
FT x u loc = E $ F x u loc
||| same as `B` but as a term
public export %inline
BT : Var n -> (loc : Loc) -> Term d n
BT : Var n -> (loc : Loc) -> Term q d n
BT i loc = E $ B i loc
||| abbreviation for a bound variable like `BV 4` instead of
||| `B (VS (VS (VS (VS VZ))))`
public export %inline
BV : (i : Nat) -> (0 _ : LT i n) => (loc : Loc) -> Elim d n
BV : (i : Nat) -> (0 _ : LT i n) => (loc : Loc) -> Elim q d n
BV i loc = B (V i) loc
||| same as `BV` but as a term
public export %inline
BVT : (i : Nat) -> (0 _ : LT i n) => (loc : Loc) -> Term d n
BVT : (i : Nat) -> (0 _ : LT i n) => (loc : Loc) -> Term q d n
BVT i loc = E $ BV i loc
public export %inline
Zero : Loc -> Term d n
Zero : Loc -> Term q d n
Zero = Nat 0
public export %inline
enum : List TagVal -> Loc -> Term d n
enum : List TagVal -> Loc -> Term q d n
enum ts loc = Enum (SortedSet.fromList ts) loc
public export %inline
typeCase : Elim d n -> Term d n ->
List (TypeCaseArm d n) -> Term d n -> Loc -> Elim d n
typeCase : Elim q d n -> Term q d n ->
List (TypeCaseArm q d n) -> Term q d n -> Loc -> Elim q d n
typeCase ty ret arms def loc = TypeCase ty ret (fromList arms) def loc
public export %inline
typeCase1Y : Elim d n -> Term d n ->
(k : TyConKind) -> BContext (arity k) -> Term d (arity k + n) ->
typeCase1Y : Elim q d n -> Term q d n ->
(k : TyConKind) -> BContext (arity k) -> Term q d (arity k + n) ->
(loc : Loc) ->
{default (NAT loc) def : Term d n} ->
Elim d n
{default (NAT loc) def : Term q d n} ->
Elim q d n
typeCase1Y ty ret k ns body loc = typeCase ty ret [(k ** SY ns body)] def loc

View file

@ -5,6 +5,7 @@ import Quox.Syntax.Term.Subst
import Quox.Context
import Quox.Pretty
import Quox.SingletonExtra
import Data.Vect
import Derive.Prelude
@ -13,21 +14,23 @@ import Derive.Prelude
export
prettyUniverse : {opts : _} -> Universe -> Eff Pretty (Doc opts)
prettyUniverse : {opts : LayoutOpts} -> Universe -> Eff Pretty (Doc opts)
prettyUniverse = hl Universe . text . show
export
prettyTerm : {opts : _} -> BContext d -> BContext n -> Term d n ->
Eff Pretty (Doc opts)
prettyTerm : {opts : LayoutOpts} ->
NameContexts q d n -> Term q d n -> Eff Pretty (Doc opts)
export
prettyElim : {opts : _} -> BContext d -> BContext n -> Elim d n ->
Eff Pretty (Doc opts)
prettyElim : {opts : LayoutOpts} ->
NameContexts q d n -> Elim q d n -> Eff Pretty (Doc opts)
private
BTelescope : Nat -> Nat -> Type
BTelescope = Telescope' BindName
export
prettyQty : {opts : LayoutOpts} ->
NameContexts q d n -> Qty q -> Eff Pretty (Doc opts)
prettyQty names pi = let Val q = names.qtyLen in prettyQty names.qnames pi
private
@ -40,109 +43,111 @@ superscript = pack . map sup . unpack where
private
PiBind : Nat -> Nat -> Type
PiBind d n = (Qty, BindName, Term d n)
PiBind : TermLike
PiBind q d n = (Qty q, BindName, Term q d n)
private
pbname : PiBind d n -> BindName
pbname : PiBind q d n -> BindName
pbname (_, x, _) = x
private
record SplitPi d n where
record SplitPi q d n where
constructor MkSplitPi
{0 inner : Nat}
binds : Telescope (PiBind d) n inner
cod : Term d inner
binds : Telescope (PiBind q d) n inner
cod : Term q d inner
private
splitPi : Telescope (PiBind d) n n' -> Term d n' -> SplitPi d n
splitPi binds (Pi qty arg res _) =
splitPi : {q : Nat} ->
Telescope (PiBind q d) n n' -> Term q d n' -> SplitPi q d n
splitPi binds cod@(Pi qty arg res _) =
splitPi (binds :< (qty, res.name, arg)) $
assert_smaller res $ pushSubsts' res.term
assert_smaller cod $ pushSubsts' res.term
splitPi binds cod = MkSplitPi {binds, cod}
private
prettyPiBind1 : {opts : _} ->
Qty -> BindName -> BContext d -> BContext n -> Term d n ->
prettyPiBind1 : {opts : LayoutOpts} ->
NameContexts q d n -> Qty q -> BindName -> Term q d n ->
Eff Pretty (Doc opts)
prettyPiBind1 pi (BN Unused _) dnames tnames s =
prettyPiBind1 names pi (BN Unused _) s =
hcat <$> sequence
[prettyQty pi, dotD,
withPrec Arg $ assert_total prettyTerm dnames tnames s]
prettyPiBind1 pi x dnames tnames s = hcat <$> sequence
[prettyQty pi, dotD,
[prettyQty names pi, dotD,
withPrec Arg $ assert_total prettyTerm names s]
prettyPiBind1 names pi x s =
hcat <$> sequence
[prettyQty names pi, dotD,
hl Delim $ text "(",
hsep <$> sequence
[prettyTBind x, hl Delim $ text ":",
withPrec Outer $ assert_total prettyTerm dnames tnames s],
withPrec Outer $ assert_total prettyTerm names s],
hl Delim $ text ")"]
private
prettyPiBinds : {opts : _} ->
BContext d -> BContext n ->
Telescope (PiBind d) n n' ->
prettyPiBinds : {opts : LayoutOpts} ->
NameContexts q d n ->
Telescope (PiBind q d) n n' ->
Eff Pretty (SnocList (Doc opts))
prettyPiBinds _ _ [<] = pure [<]
prettyPiBinds dnames tnames (binds :< (q, x, t)) =
let tnames' = tnames . map pbname binds in
[|prettyPiBinds dnames tnames binds :<
prettyPiBind1 q x dnames tnames' t|]
prettyPiBinds _ [<] = pure [<]
prettyPiBinds names (binds :< (q, x, t)) =
let names' = extendTermN' (map pbname binds) names in
[|prettyPiBinds names binds :<
prettyPiBind1 names' q x t|]
private
SigBind : Nat -> Nat -> Type
SigBind d n = (BindName, Term d n)
SigBind : TermLike
SigBind q d n = (BindName, Term q d n)
private
record SplitSig d n where
record SplitSig q d n where
constructor MkSplitSig
{0 inner : Nat}
binds : Telescope (SigBind d) n inner
last : Term d inner
binds : Telescope (SigBind q d) n inner
last : Term q d inner
private
splitSig : Telescope (SigBind d) n n' -> Term d n' -> SplitSig d n
splitSig : {q : Nat} ->
Telescope (SigBind q d) n n' -> Term q d n' -> SplitSig q d n
splitSig binds (Sig fst snd _) =
splitSig (binds :< (snd.name, fst)) $
assert_smaller snd $ pushSubsts' snd.term
splitSig binds last = MkSplitSig {binds, last}
private
prettySigBind1 : {opts : _} ->
BindName -> BContext d -> BContext n -> Term d n ->
prettySigBind1 : {opts : LayoutOpts} ->
NameContexts q d n -> BindName -> Term q d n ->
Eff Pretty (Doc opts)
prettySigBind1 (BN Unused _) dnames tnames s =
withPrec InTimes $ assert_total prettyTerm dnames tnames s
prettySigBind1 x dnames tnames s = hcat <$> sequence
prettySigBind1 names (BN Unused _) s =
withPrec InTimes $ assert_total prettyTerm names s
prettySigBind1 names x s = hcat <$> sequence
[hl Delim $ text "(",
hsep <$> sequence
[prettyTBind x, hl Delim $ text ":",
withPrec Outer $ assert_total prettyTerm dnames tnames s],
withPrec Outer $ assert_total prettyTerm names s],
hl Delim $ text ")"]
private
prettySigBinds : {opts : _} ->
BContext d -> BContext n ->
Telescope (SigBind d) n n' ->
prettySigBinds : {opts : LayoutOpts} ->
NameContexts q d n -> Telescope (SigBind q d) n n' ->
Eff Pretty (SnocList (Doc opts))
prettySigBinds _ _ [<] = pure [<]
prettySigBinds dnames tnames (binds :< (x, t)) =
let tnames' = tnames . map fst binds in
[|prettySigBinds dnames tnames binds :<
prettySigBind1 x dnames tnames' t|]
prettySigBinds _ [<] = pure [<]
prettySigBinds names (binds :< (x, t)) =
let names' = extendTermN' (map fst binds) names in
[|prettySigBinds names binds :<
prettySigBind1 names' x t|]
private
prettyTypeLine : {opts : _} ->
BContext d -> BContext n ->
DScopeTerm d n ->
prettyTypeLine : {opts : LayoutOpts} ->
NameContexts q d n -> DScopeTerm q d n ->
Eff Pretty (Doc opts)
prettyTypeLine dnames tnames (S _ (N body)) =
withPrec Arg (prettyTerm dnames tnames body)
prettyTypeLine dnames tnames (S [< i] (Y body)) =
prettyTypeLine names (S _ (N body)) =
withPrec Arg (prettyTerm names body)
prettyTypeLine names (S [< i] (Y body)) =
parens =<< do
let names' = extendDim i names
i' <- prettyDBind i
ty' <- withPrec Outer $ prettyTerm (dnames :< i) tnames body
ty' <- withPrec Outer $ prettyTerm names' body
pure $ sep [hsep [i', !darrowD], ty']
@ -155,16 +160,16 @@ NameChunks : Type
NameChunks = SnocList (NameSort, SnocList BindName)
private
record SplitLams d n where
record SplitLams q d n where
constructor MkSplitLams
{0 dinner, ninner : Nat}
dnames : BTelescope d dinner
tnames : BTelescope n ninner
chunks : NameChunks
body : Term dinner ninner
body : Term q dinner ninner
private
splitLams : Term d n -> SplitLams d n
splitLams : {q : Nat} -> Term q d n -> SplitLams q d n
splitLams s = go [<] [<] [<] (pushSubsts' s)
where
push : NameSort -> BindName -> NameChunks -> NameChunks
@ -175,7 +180,7 @@ where
go : BTelescope d d' -> BTelescope n n' ->
SnocList (NameSort, SnocList BindName) ->
Term d' n' -> SplitLams d n
Term q d' n' -> SplitLams q d n
go dnames tnames chunks (Lam b _) =
go dnames (tnames :< b.name) (push T b.name chunks) $
assert_smaller b $ pushSubsts' b.term
@ -187,28 +192,31 @@ where
private
splitTuple : SnocList (Term d n) -> Term d n -> SnocList (Term d n)
splitTuple : {q : Nat} ->
SnocList (Term q d n) -> Term q d n -> SnocList (Term q d n)
splitTuple ss p@(Pair t1 t2 _) =
splitTuple (ss :< t1) $ assert_smaller p $ pushSubsts' t2
splitTuple ss t = ss :< t
private
prettyTArg : {opts : _} -> BContext d -> BContext n ->
Term d n -> Eff Pretty (Doc opts)
prettyTArg dnames tnames s =
withPrec Arg $ assert_total prettyTerm dnames tnames s
prettyTArg : {opts : LayoutOpts} ->
NameContexts q d n -> Term q d n -> Eff Pretty (Doc opts)
prettyTArg names s =
withPrec Arg $ assert_total prettyTerm names s
private
prettyDArg : {opts : _} -> BContext d -> Dim d -> Eff Pretty (Doc opts)
prettyDArg dnames p = [|atD <+> withPrec Arg (prettyDim dnames p)|]
prettyDArg : {opts : LayoutOpts} ->
NameContexts _ d _ -> Dim d -> Eff Pretty (Doc opts)
prettyDArg names p = [|atD <+> withPrec Arg (prettyDim names.dnames p)|]
private
splitApps : Elim d n -> (Elim d n, List (Either (Dim d) (Term d n)))
splitApps : {q : Nat} ->
Elim q d n -> (Elim q d n, List (Either (Dim d) (Term q d n)))
splitApps e = go [] (pushSubsts' e)
where
go : List (Either (Dim d) (Term d n)) -> Elim d n ->
(Elim d n, List (Either (Dim d) (Term d n)))
go : List (Either (Dim d) (Term q d n)) -> Elim q d n ->
(Elim q d n, List (Either (Dim d) (Term q d n)))
go xs e@(App f s _) =
go (Right s :: xs) $ assert_smaller e $ pushSubsts' f
go xs e@(DApp f p _) =
@ -216,49 +224,53 @@ where
go xs s = (s, xs)
private
prettyDTApps : {opts : _} ->
BContext d -> BContext n ->
Elim d n -> List (Either (Dim d) (Term d n)) ->
prettyDTApps : {opts : LayoutOpts} ->
NameContexts q d n ->
Elim q d n -> List (Either (Dim d) (Term q d n)) ->
Eff Pretty (Doc opts)
prettyDTApps dnames tnames f xs = do
f <- withPrec Arg $ assert_total prettyElim dnames tnames f
xs <- for xs $ either (prettyDArg dnames) (prettyTArg dnames tnames)
parensIfM App =<< prettyAppD f xs
prettyDTApps names f xs = do
f <- withPrec Arg $ assert_total prettyElim names f
xs <- for xs $ either (prettyDArg names) (prettyTArg names)
prettyAppD f xs
private
record CaseArm opts d n where
record CaseArm opts q d n where
constructor MkCaseArm
pat : Doc opts
dbinds : BTelescope d dinner -- 🍴
tbinds : BTelescope n ninner
body : Term dinner ninner
body : Term q dinner ninner
parameters {opts : LayoutOpts} (dnames : BContext d) (tnames : BContext n)
private
prettyCaseArm : CaseArm opts d n -> Eff Pretty (Doc opts)
prettyCaseArm (MkCaseArm pat dbinds tbinds body) = do
body <- withPrec Outer $ assert_total
prettyTerm (dnames . dbinds) (tnames . tbinds) body
prettyCaseArm : {opts : LayoutOpts} ->
NameContexts q d n -> CaseArm opts q d n ->
Eff Pretty (Doc opts)
prettyCaseArm names (MkCaseArm pat dbinds tbinds body) = do
let names' = extendDimN' dbinds $ extendTermN' tbinds names
body <- withPrec Outer $ assert_total prettyTerm names' body
header <- (pat <++>) <$> darrowD
pure $ ifMultiline (header <++> body) (vsep [header, !(indentD body)])
private
prettyCaseBody : List (CaseArm opts d n) -> Eff Pretty (List (Doc opts))
prettyCaseBody xs = traverse prettyCaseArm xs
prettyCaseBody : {opts : LayoutOpts} ->
NameContexts q d n -> List (CaseArm opts q d n) ->
Eff Pretty (List (Doc opts))
prettyCaseBody names xs = traverse (prettyCaseArm names) xs
private
prettyCompPat : {opts : _} -> DimConst -> BindName -> Eff Pretty (Doc opts)
prettyCompPat : {opts : LayoutOpts} ->
DimConst -> BindName -> Eff Pretty (Doc opts)
prettyCompPat e x = [|prettyDimConst e <++> prettyDBind x|]
private
prettyCompArm : {opts : _} -> BContext d -> BContext n ->
DimConst -> DScopeTerm d n -> Eff Pretty (Doc opts)
prettyCompArm dnames tnames e s = prettyCaseArm dnames tnames $
prettyCompArm : {opts : LayoutOpts} -> NameContexts q d n ->
DimConst -> DScopeTerm q d n -> Eff Pretty (Doc opts)
prettyCompArm names e s = prettyCaseArm names $
MkCaseArm !(prettyCompPat e s.name) [< s.name] [<] s.term
private
layoutComp : {opts : _} ->
layoutComp : {opts : LayoutOpts} ->
(typq : List (Doc opts)) -> (val, r : Doc opts) ->
(arms : List (Doc opts)) -> Eff Pretty (Doc opts)
layoutComp typq val r arms = do
@ -273,32 +285,33 @@ layoutComp typq val r arms = do
export
prettyEnum : {opts : _} -> List String -> Eff Pretty (Doc opts)
prettyEnum : {opts : LayoutOpts} -> List String -> Eff Pretty (Doc opts)
prettyEnum cases =
tightBraces =<<
fillSeparateTight !commaD <$>
traverse (hl Constant . Doc.text . quoteTag) cases
private
prettyCaseRet : {opts : _} ->
BContext d -> BContext n ->
ScopeTerm d n -> Eff Pretty (Doc opts)
prettyCaseRet dnames tnames body = withPrec Outer $ case body of
S _ (N tm) => assert_total prettyTerm dnames tnames tm
prettyCaseRet : {opts : LayoutOpts} ->
NameContexts q d n -> ScopeTerm q d n -> Eff Pretty (Doc opts)
prettyCaseRet names body = withPrec Outer $ case body of
S _ (N tm) => assert_total prettyTerm names tm
S [< x] (Y tm) => do
let names' = extendTerm x names
header <- [|prettyTBind x <++> darrowD|]
body <- assert_total prettyTerm dnames (tnames :< x) tm
body <- assert_total prettyTerm names' tm
hangDSingle header body
private
prettyCase_ : {opts : _} ->
BContext d -> BContext n ->
Doc opts -> Elim d n -> ScopeTerm d n -> List (CaseArm opts d n) ->
prettyCase_ : {opts : LayoutOpts} ->
NameContexts q d n ->
Doc opts -> Elim q d n -> ScopeTerm q d n ->
List (CaseArm opts q d n) ->
Eff Pretty (Doc opts)
prettyCase_ dnames tnames intro head ret body = do
head <- withPrec Outer $ assert_total prettyElim dnames tnames head
ret <- prettyCaseRet dnames tnames ret
bodys <- prettyCaseBody dnames tnames body
prettyCase_ names intro head ret body = do
head <- withPrec Outer $ assert_total prettyElim names head
ret <- prettyCaseRet names ret
bodys <- prettyCaseBody names body
return <- returnD; of_ <- ofD
lb <- hl Delim "{"; rb <- hl Delim "}"; semi <- semiD
ind <- askAt INDENT
@ -308,25 +321,27 @@ prettyCase_ dnames tnames intro head ret body = do
indent ind $ vseparateTight semi bodys, rb])
private
prettyCase : {opts : _} ->
BContext d -> BContext n ->
Qty -> Elim d n -> ScopeTerm d n -> List (CaseArm opts d n) ->
prettyCase : {opts : LayoutOpts} ->
NameContexts q d n ->
Qty q -> Elim q d n -> ScopeTerm q d n ->
List (CaseArm opts q d n) ->
Eff Pretty (Doc opts)
prettyCase dnames tnames qty head ret body =
prettyCase_ dnames tnames ![|caseD <+> prettyQty qty|] head ret body
prettyCase names qty head ret body =
prettyCase_ names ![|caseD <+> prettyQty names qty|] head ret body
private
LetBinder : Nat -> Nat -> Type
LetBinder d n = (Qty, BindName, Elim d n)
LetBinder : TermLike
LetBinder q d n = (Qty q, BindName, Elim q d n)
private
LetExpr : Nat -> Nat -> Nat -> Type
LetExpr d n n' = (Telescope (LetBinder d) n n', Term d n')
LetExpr : (q, d, n, n' : Nat) -> Type
LetExpr q d n n' = (Telescope (LetBinder q d) n n', Term q d n')
-- [todo] factor out this and the untyped version somehow
export
splitLet : Telescope (LetBinder d) n n' -> Term d n' -> Exists (LetExpr d n)
splitLet : Telescope (LetBinder q d) n n' -> Term q d n' ->
Exists (LetExpr q d n)
splitLet ys t@(Let qty rhs body _) =
splitLet (ys :< (qty, body.name, rhs)) (assert_smaller t body.term)
splitLet ys t =
@ -334,38 +349,40 @@ splitLet ys t =
private covering
prettyLets : {opts : LayoutOpts} ->
BContext d -> BContext a -> Telescope (LetBinder d) a b ->
NameContexts q d a -> Telescope (LetBinder q d) a b ->
Eff Pretty (SnocList (Doc opts))
prettyLets dnames xs lets = snd <$> go lets where
peelAnn : forall d, n. Elim d n -> Maybe (Term d n, Term d n)
prettyLets (MkNameContexts qnames dnames tnames) lets = snd <$> go lets where
peelAnn : forall d, n. Elim q d n -> Maybe (Term q d n, Term q d n)
peelAnn (Ann tm ty _) = Just (tm, ty)
peelAnn e = Nothing
letHeader : Qty -> BindName -> Eff Pretty (Doc opts)
letHeader : Qty q -> BindName -> Eff Pretty (Doc opts)
letHeader qty x = do
lett <- [|letD <+> prettyQty qty|]
lett <- [|letD <+> prettyQty qnames qty|]
x <- prettyTBind x
pure $ lett <++> x
letBody : forall n. BContext n ->
Doc opts -> Elim d n -> Eff Pretty (Doc opts)
letBody tnames hdr e = case peelAnn e of
Doc opts -> Elim q d n -> Eff Pretty (Doc opts)
letBody tnames hdr e =
let names = MkNameContexts' qnames dnames tnames in
case peelAnn e of
Just (tm, ty) => do
ty <- withPrec Outer $ assert_total prettyTerm dnames tnames ty
tm <- withPrec Outer $ assert_total prettyTerm dnames tnames tm
ty <- withPrec Outer $ assert_total prettyTerm names ty
tm <- withPrec Outer $ assert_total prettyTerm names tm
colon <- colonD; eq <- cstD; d <- askAt INDENT
pure $ hangSingle d (hangSingle d hdr (colon <++> ty)) (eq <++> tm)
Nothing => do
e <- withPrec Outer $ assert_total prettyElim dnames tnames e
e <- withPrec Outer $ assert_total prettyElim names e
eq <- cstD; d <- askAt INDENT
inn <- inD
pure $ ifMultiline
(hsep [hdr, eq, e, inn])
(vsep [hdr, indent d $ hsep [eq, e, inn]])
go : forall b. Telescope (LetBinder d) a b ->
go : forall b. Telescope (LetBinder q d) a b ->
Eff Pretty (BContext b, SnocList (Doc opts))
go [<] = pure (xs, [<])
go [<] = pure (tnames, [<])
go (lets :< (qty, x, rhs)) = do
(ys, docs) <- go lets
doc <- letBody ys !(letHeader qty x) rhs
@ -385,7 +402,7 @@ toTel [<] = [<]
toTel (ctx :< x) = toTel ctx :< x
private
prettyTyCasePat : {opts : _} ->
prettyTyCasePat : {opts : LayoutOpts} ->
(k : TyConKind) -> BContext (arity k) ->
Eff Pretty (Doc opts)
prettyTyCasePat KTYPE [<] = typeD
@ -402,13 +419,14 @@ prettyTyCasePat KString [<] = stringD
prettyTyCasePat KBOX [< a] = bracks =<< prettyTBind a
prettyLambda : {opts : _} -> BContext d -> BContext n ->
Term d n -> Eff Pretty (Doc opts)
prettyLambda dnames tnames s =
parensIfM Outer =<< do
let MkSplitLams {dnames = ds, tnames = ts, chunks, body} = splitLams s
hangDSingle !(header chunks)
!(assert_total prettyTerm (dnames . ds) (tnames . ts) body)
prettyLambda : {opts : LayoutOpts} ->
NameContexts q d n -> Term q d n -> Eff Pretty (Doc opts)
prettyLambda names s =
let Val q = names.qtyLen
MkSplitLams {dnames = ds, tnames = ts, chunks, body} = splitLams s
names' = extendDimN' ds $ extendTermN' ts names in
parensIfM Outer =<<
hangDSingle !(header chunks) !(assert_total prettyTerm names' body)
where
introChar : NameSort -> Eff Pretty (Doc opts)
introChar T = lamD
@ -426,198 +444,207 @@ where
header cs = sep <$> traverse (\(s, xs) => header1 s (toList xs)) (toList cs)
prettyDisp : {opts : _} -> Universe -> Eff Pretty (Maybe (Doc opts))
prettyDisp : {opts : LayoutOpts} -> Universe -> Eff Pretty (Maybe (Doc opts))
prettyDisp 0 = pure Nothing
prettyDisp u = map Just $ hl Universe =<<
ifUnicode (text $ superscript $ show u) (text $ "^" ++ show u)
prettyTerm dnames tnames (TYPE l _) = do
prettyTerm names (TYPE l _) = do
type <- hl Syntax . text =<< ifUnicode "" "Type"
level <- prettyDisp l
pure $ maybe type (type <+>) level
prettyTerm dnames tnames (IOState _) =
prettyTerm _ (IOState _) =
ioStateD
prettyTerm dnames tnames (Pi qty arg res _) =
parensIfM Outer =<< do
let MkSplitPi {binds, cod} = splitPi [< (qty, res.name, arg)] res.term
prettyTerm names (Pi qty arg res _) = do
let Val q = names.qtyLen
MkSplitPi {binds, cod} = splitPi [< (qty, res.name, arg)] res.term
arr <- arrowD
lines <- map (<++> arr) <$> prettyPiBinds dnames tnames binds
let tnames = tnames . map pbname binds
cod <- withPrec Outer $ prettyTerm dnames tnames (assert_smaller res cod)
pure $ sepSingle $ toList $ lines :< cod
lines <- map (<++> arr) <$> prettyPiBinds names binds
let names' = extendTermN' (map pbname binds) names
cod <- withPrec Outer $ prettyTerm names' (assert_smaller res cod)
parensIfM Outer $ sepSingle $ toList $ lines :< cod
prettyTerm dnames tnames s@(Lam {}) =
prettyLambda dnames tnames s
prettyTerm names s@(Lam {}) =
prettyLambda names s
prettyTerm dnames tnames (Sig fst snd _) =
parensIfM Times =<< do
let MkSplitSig {binds, last} = splitSig [< (snd.name, fst)] snd.term
prettyTerm names (Sig tfst tsnd _) = do
let Val q = names.qtyLen
MkSplitSig {binds, last} = splitSig [< (tsnd.name, tfst)] tsnd.term
times <- timesD
lines <- map (<++> times) <$> prettySigBinds dnames tnames binds
let tnames = tnames . map Builtin.fst binds
last <- withPrec InTimes $
prettyTerm dnames tnames (assert_smaller snd last)
pure $ sepSingle $ toList $ lines :< last
lines <- map (<++> times) <$> prettySigBinds names binds
let names' = extendTermN' (map fst binds) names
last <- withPrec InTimes $ prettyTerm names' (assert_smaller tsnd last)
parensIfM Times $ sepSingle $ toList $ lines :< last
prettyTerm dnames tnames p@(Pair fst snd _) =
parens =<< do
let elems = splitTuple [< fst] snd
prettyTerm names p@(Pair s t _) = do
let Val q = names.qtyLen
elems = splitTuple [< s] t
lines <- for elems $ \t =>
withPrec Outer $ prettyTerm dnames tnames $ assert_smaller p t
pure $ separateTight !commaD lines
withPrec Outer $ prettyTerm names $ assert_smaller p t
parens $ separateTight !commaD lines
prettyTerm dnames tnames (Enum cases _) =
prettyTerm _ (Enum cases _) =
prettyEnum $ SortedSet.toList cases
prettyTerm dnames tnames (Tag tag _) =
prettyTerm _ (Tag tag _) =
prettyTag tag
prettyTerm dnames tnames (Eq (S _ (N ty)) l r _) =
parensIfM Eq =<< do
l <- withPrec InEq $ prettyTerm dnames tnames l
r <- withPrec InEq $ prettyTerm dnames tnames r
ty <- withPrec InEq $ prettyTerm dnames tnames ty
pure $ sep [l <++> !eqndD, r <++> !colonD, ty]
prettyTerm names (Eq (S _ (N ty)) l r _) = do
l <- withPrec InEq $ prettyTerm names l
r <- withPrec InEq $ prettyTerm names r
ty <- withPrec InEq $ prettyTerm names ty
parensIfM Eq $ sep [l <++> !eqndD, r <++> !colonD, ty]
prettyTerm dnames tnames (Eq ty l r _) =
parensIfM App =<< do
ty <- prettyTypeLine dnames tnames ty
l <- withPrec Arg $ prettyTerm dnames tnames l
r <- withPrec Arg $ prettyTerm dnames tnames r
prettyTerm names (Eq ty l r _) = do
ty <- prettyTypeLine names ty
l <- withPrec Arg $ prettyTerm names l
r <- withPrec Arg $ prettyTerm names r
prettyAppD !eqD [ty, l, r]
prettyTerm dnames tnames s@(DLam {}) =
prettyLambda dnames tnames s
prettyTerm names s@(DLam {}) =
prettyLambda names s
prettyTerm dnames tnames (NAT _) = natD
prettyTerm dnames tnames (Nat n _) = hl Syntax $ pshow n
prettyTerm dnames tnames (Succ p _) =
parensIfM App =<<
prettyAppD !succD [!(withPrec Arg $ prettyTerm dnames tnames p)]
prettyTerm _ (NAT _) = natD
prettyTerm _ (Nat n _) = hl Syntax $ pshow n
prettyTerm names (Succ p _) =
prettyAppD !succD [!(withPrec Arg $ prettyTerm names p)]
prettyTerm dnames tnames (STRING _) = stringD
prettyTerm dnames tnames (Str s _) = prettyStrLit s
prettyTerm _ (STRING _) = stringD
prettyTerm _ (Str s _) = prettyStrLit s
prettyTerm dnames tnames (BOX qty ty _) =
prettyTerm names (BOX qty ty _) =
bracks . hcat =<<
sequence [prettyQty qty, dotD,
withPrec Outer $ prettyTerm dnames tnames ty]
sequence [prettyQty names qty, dotD,
withPrec Outer $ prettyTerm names ty]
prettyTerm dnames tnames (Box val _) =
bracks =<< withPrec Outer (prettyTerm dnames tnames val)
prettyTerm names (Box val _) =
bracks =<< withPrec Outer (prettyTerm names val)
prettyTerm dnames tnames (Let qty rhs body _) = do
prettyTerm names (Let qty rhs body _) = do
let Evidence _ (lets, body) = splitLet [< (qty, body.name, rhs)] body.term
heads <- prettyLets dnames tnames lets
let tnames = tnames . map (\(_, x, _) => x) lets
body <- withPrec Outer $ assert_total prettyTerm dnames tnames body
heads <- prettyLets names lets
let names' = extendTermN' (map (fst . snd) lets) names
body <- withPrec Outer $ assert_total prettyTerm names' body
let lines = toList $ heads :< body
pure $ ifMultiline (hsep lines) (vsep lines)
prettyTerm dnames tnames (E e) =
case the (Elim d n) (pushSubsts' e) of
Ann tm _ _ => assert_total prettyTerm dnames tnames tm
_ => assert_total prettyElim dnames tnames e
prettyTerm names (E e) = do
-- [fixme] do this stuff somewhere else!!!
let Val q = names.qtyLen
case pushSubsts' e {tm = Elim} of
Ann tm _ _ => assert_total prettyTerm names tm
_ => assert_total prettyElim names e
prettyTerm dnames tnames t0@(CloT (Sub t ph)) =
prettyTerm dnames tnames $ assert_smaller t0 $ pushSubstsWith' id ph t
prettyTerm names t0@(CloT (Sub t ph)) = do
let Val q = names.qtyLen
prettyTerm names $ assert_smaller t0 $ pushSubstsWith' id id ph t
prettyTerm dnames tnames t0@(DCloT (Sub t ph)) =
prettyTerm dnames tnames $ assert_smaller t0 $ pushSubstsWith' ph id t
prettyTerm names t0@(DCloT (Sub t ph)) = do
let Val q = names.qtyLen
prettyTerm names $ assert_smaller t0 $ pushSubstsWith' id ph id t
prettyElim dnames tnames (F x u _) = do
prettyTerm names t0@(QCloT (SubR t ph)) = do
let Val q = names.qtyLen
prettyTerm names $ assert_smaller t0 $ pushSubstsWith' ph id id t
prettyElim names (F x u _) = do
x <- prettyFree x
u <- prettyDisp u
pure $ maybe x (x <+>) u
prettyElim dnames tnames (B i _) =
prettyTBind $ tnames !!! i
prettyElim names (B i _) =
prettyTBind $ names.tnames !!! i
prettyElim dnames tnames e@(App {}) =
let (f, xs) = splitApps e in
prettyDTApps dnames tnames f xs
prettyElim names e@(App {}) = do
let Val q = names.qtyLen
(f, xs) = splitApps e
prettyDTApps names f xs
prettyElim dnames tnames (CasePair qty pair ret body _) = do
prettyElim names (CasePair qty pair ret body _) = do
let [< x, y] = body.names
pat <- parens . hsep =<< sequence
[[|prettyTBind x <+> commaD|], prettyTBind y]
prettyCase dnames tnames qty pair ret
pat <- parens $ !(prettyTBind x) <+> !commaD <++> !(prettyTBind y)
prettyCase names qty pair ret
[MkCaseArm pat [<] [< x, y] body.term]
prettyElim dnames tnames (Fst pair _) =
parensIfM App =<< do
pair <- prettyTArg dnames tnames (E pair)
prettyElim names (Fst pair _) = do
pair <- prettyTArg names (E pair)
prettyAppD !fstD [pair]
prettyElim dnames tnames (Snd pair _) =
parensIfM App =<< do
pair <- prettyTArg dnames tnames (E pair)
prettyElim names (Snd pair _) = do
pair <- prettyTArg names (E pair)
prettyAppD !sndD [pair]
prettyElim dnames tnames (CaseEnum qty tag ret arms _) = do
prettyElim names (CaseEnum qty tag ret arms _) = do
arms <- for (SortedMap.toList arms) $ \(tag, body) =>
pure $ MkCaseArm !(prettyTag tag) [<] [<] body
prettyCase dnames tnames qty tag ret arms
prettyCase names qty tag ret arms
prettyElim dnames tnames (CaseNat qty qtyIH nat ret zero succ _) = do
prettyElim names (CaseNat qty qtyIH nat ret zero succ _) = do
let zarm = MkCaseArm !zeroD [<] [<] zero
[< p, ih] = succ.names
spat0 <- [|succD <++> prettyTBind p|]
ihpat0 <- map hcat $ sequence [prettyQty qtyIH, dotD, prettyTBind ih]
ihpat0 <- map hcat $ sequence [prettyQty names qtyIH, dotD, prettyTBind ih]
spat <- if ih.val == Unused
then pure spat0
else pure $ hsep [spat0 <+> !commaD, ihpat0]
else pure $ spat0 <+> !commaD <++> ihpat0
let sarm = MkCaseArm spat [<] [< p, ih] succ.term
prettyCase dnames tnames qty nat ret [zarm, sarm]
prettyCase names qty nat ret [zarm, sarm]
prettyElim dnames tnames (CaseBox qty box ret body _) = do
prettyElim names (CaseBox qty box ret body _) = do
pat <- bracks =<< prettyTBind body.name
let arm = MkCaseArm pat [<] [< body.name] body.term
prettyCase dnames tnames qty box ret [arm]
prettyCase names qty box ret [arm]
prettyElim dnames tnames e@(DApp {}) =
let (f, xs) = splitApps e in
prettyDTApps dnames tnames f xs
prettyElim names e@(DApp {}) = do
let Val q = names.qtyLen
(f, xs) = splitApps e
prettyDTApps names f xs
prettyElim dnames tnames (Ann tm ty _) =
case the (Term d n) (pushSubsts' tm) of
E e => assert_total prettyElim dnames tnames e
prettyElim names (Ann tm ty _) = do
-- [fixme] do this stuff somewhere else!!!
let Val q = names.qtyLen
case pushSubsts' tm {tm = Term} of
E e => assert_total prettyElim names e
_ => do
tm <- withPrec AnnL $ assert_total prettyTerm dnames tnames tm
ty <- withPrec Outer $ assert_total prettyTerm dnames tnames ty
tm <- withPrec AnnL $ assert_total prettyTerm names tm
ty <- withPrec Outer $ assert_total prettyTerm names ty
parensIfM Outer =<< hangDSingle (tm <++> !annD) ty
prettyElim dnames tnames (Coe ty p q val _) =
parensIfM App =<< do
ty <- prettyTypeLine dnames tnames ty
p <- prettyDArg dnames p
q <- prettyDArg dnames q
val <- prettyTArg dnames tnames val
prettyAppD !coeD [ty, sep [p, q], val]
prettyElim names (Coe ty p p' val _) = do
ty <- prettyTypeLine names ty
p <- prettyDArg names p
p' <- prettyDArg names p'
val <- prettyTArg names val
prettyAppD !coeD [ty, p <++> p', val]
prettyElim dnames tnames e@(Comp ty p q val r zero one _) =
parensIfM App =<< do
ty <- assert_total $ prettyTypeLine dnames tnames $ SN ty
pq <- sep <$> sequence [prettyDArg dnames p, prettyDArg dnames q]
val <- prettyTArg dnames tnames val
r <- prettyDArg dnames r
arm0 <- [|prettyCompArm dnames tnames Zero zero <+> semiD|]
arm1 <- prettyCompArm dnames tnames One one
prettyElim names e@(Comp ty p p' val r zero one _) = do
ty <- assert_total $ prettyTypeLine names $ SN ty
pp <- [|prettyDArg names p <++> prettyDArg names p'|]
val <- prettyTArg names val
r <- prettyDArg names r
arm0 <- [|prettyCompArm names Zero zero <+> semiD|]
arm1 <- prettyCompArm names One one
ind <- askAt INDENT
layoutComp [ty, pq] val r [arm0, arm1]
parensIfM App =<< layoutComp [ty, pp] val r [arm0, arm1]
prettyElim dnames tnames (TypeCase ty ret arms def _) = do
prettyElim names (TypeCase ty ret arms def _) = do
arms <- for (toList arms) $ \(k ** body) => do
pat <- prettyTyCasePat k body.names
pure $ MkCaseArm pat [<] (toTel body.names) body.term
let darm = MkCaseArm !undD [<] [<] def
prettyCase_ dnames tnames !typecaseD ty (SN ret) $ arms ++ [darm]
prettyCase_ names !typecaseD ty (SN ret) $ arms ++ [darm]
prettyElim dnames tnames e0@(CloE (Sub e ph)) =
prettyElim dnames tnames $ assert_smaller e0 $ pushSubstsWith' id ph e
prettyElim names e0@(CloE (Sub e ph)) = do
let Val q = names.qtyLen
prettyElim names $ assert_smaller e0 $ pushSubstsWith' id id ph e
prettyElim dnames tnames e0@(DCloE (Sub e ph)) =
prettyElim dnames tnames $ assert_smaller e0 $ pushSubstsWith' ph id e
prettyElim names e0@(DCloE (Sub e ph)) = do
let Val q = names.qtyLen
prettyElim names $ assert_smaller e0 $ pushSubstsWith' id ph id e
prettyElim names e0@(QCloE (SubR e ph)) = do
let Val q = names.qtyLen
prettyElim names $ assert_smaller e0 $ pushSubstsWith' ph id id e

View file

@ -6,10 +6,42 @@ import Data.SnocVect
%default total
namespace CanQSubst
public export
interface CanQSubst (0 tm : TermLike) where
(//) : {q1, q2 : Nat} -> tm q1 d n -> Lazy (QSubst q1 q2) -> tm q2 d n
||| does the minimal reasonable work:
||| - deletes the closure around an atomic constant like `TYPE`
||| - deletes an identity substitution
||| - composes (lazily) with an existing top-level dim-closure
||| - otherwise, wraps in a new closure
export
CanQSubst Term where
s // Shift SZ = s
TYPE l loc // _ = TYPE l loc
QCloT (SubR s ph) // th = QCloT $ SubR s $ ph .? th
s // th = QCloT $ SubR s th
||| does the minimal reasonable work:
||| - deletes the closure around a term variable
||| - deletes an identity substitution
||| - composes (lazily) with an existing top-level dim-closure
||| - immediately looks up bound variables in a
||| top-level sequence of dimension applications
||| - otherwise, wraps in a new closure
export
CanQSubst Elim where
e // Shift SZ = e
F x u loc // _ = F x u loc -- [todo] q args
B i loc // _ = B i loc
QCloE (SubR e ph) // th = QCloE $ SubR e $ ph .? th
e // th = QCloE $ SubR e th
namespace CanDSubst
public export
interface CanDSubst (0 tm : TermLike) where
(//) : tm d1 n -> Lazy (DSubst d1 d2) -> tm d2 n
(//) : tm q d1 n -> Lazy (DSubst d1 d2) -> tm q d2 n
||| does the minimal reasonable work:
||| - deletes the closure around an atomic constant like `TYPE`
@ -24,7 +56,7 @@ CanDSubst Term where
s // th = DCloT $ Sub s th
private
subDArgs : Elim d1 n -> DSubst d1 d2 -> Elim d2 n
subDArgs : Elim q d1 n -> DSubst d1 d2 -> Elim q d2 n
subDArgs (DApp f d loc) th = DApp (subDArgs f th) (d // th) loc
subDArgs e th = DCloE $ Sub e th
@ -44,25 +76,61 @@ CanDSubst Elim where
DCloE (Sub e ph) // th = DCloE $ Sub e $ ph . th
e // th = DCloE $ Sub e th
namespace QSubst.ScopeTermN
export %inline
(//) : {q1, q2 : Nat} -> ScopeTermN s q1 d n -> Lazy (QSubst q1 q2) ->
ScopeTermN s q2 d n
S ns (Y body) // th = S ns $ Y $ body // th
S ns (N body) // th = S ns $ N $ body // th
namespace DSubst.ScopeTermN
export %inline
(//) : ScopeTermN s d1 n -> Lazy (DSubst d1 d2) ->
ScopeTermN s d2 n
(//) : ScopeTermN s q d1 n -> Lazy (DSubst d1 d2) ->
ScopeTermN s q d2 n
S ns (Y body) // th = S ns $ Y $ body // th
S ns (N body) // th = S ns $ N $ body // th
namespace QSubst.DScopeTermN
export %inline
(//) : {q1, q2 : Nat} -> DScopeTermN s q1 d n -> Lazy (QSubst q1 q2) ->
DScopeTermN s q2 d n
S ns (Y body) // th = S ns $ Y $ body // th
S ns (N body) // th = S ns $ N $ body // th
namespace DSubst.DScopeTermN
export %inline
(//) : {s : Nat} ->
DScopeTermN s d1 n -> Lazy (DSubst d1 d2) ->
DScopeTermN s d2 n
DScopeTermN s q d1 n -> Lazy (DSubst d1 d2) ->
DScopeTermN s q d2 n
S ns (Y body) // th = S ns $ Y $ body // pushN s (locs $ toList' ns) th
S ns (N body) // th = S ns $ N $ body // th
export %inline FromVar (Elim d) where fromVarLoc = B
export %inline FromVar (Term d) where fromVarLoc = E .: fromVarLoc
export %inline
FromVarR (Elim q d) where fromVarR = B
export %inline
FromVar (Elim q d) where fromVar = B; fromVarSame _ _ = Refl
export %inline
FromVarR (Term q d) where fromVarR = E .: fromVarR
export %inline
FromVar (Term q d) where fromVar = E .: fromVar; fromVarSame _ _ = Refl
export
CanSubstSelf (Elim q d)
private
tsubstElim : Elim q d from -> Lazy (TSubst q d from to) -> Elim q d to
tsubstElim (F x u loc) _ = F x u loc
tsubstElim (B i loc) th = get th i loc
tsubstElim (CloE (Sub e ph)) th = assert_total CloE $ Sub e $ ph . th
tsubstElim e th =
case force th of
Shift SZ => e
th => CloE $ Sub e th
||| does the minimal reasonable work:
||| - deletes the closure around a *free* name
@ -70,19 +138,15 @@ export %inline FromVar (Term d) where fromVarLoc = E .: fromVarLoc
||| - composes (lazily) with an existing top-level closure
||| - immediately looks up a bound variable
||| - otherwise, wraps in a new closure
CanSubstSelfR (Elim q d) where (//?) = tsubstElim
export
CanSubstSelf (Elim d) where
F x u loc // _ = F x u loc
B i loc // th = getLoc th i loc
CloE (Sub e ph) // th = assert_total CloE $ Sub e $ ph . th
e // th = case force th of
Shift SZ => e
th => CloE $ Sub e th
CanSubstSelf (Elim q d) where (//) = tsubstElim; substSame _ _ = Refl
namespace CanTSubst
public export
interface CanTSubst (0 tm : TermLike) where
(//) : tm d n1 -> Lazy (TSubst d n1 n2) -> tm d n2
(//) : tm q d n1 -> Lazy (TSubst q d n1 n2) -> tm q d n2
||| does the minimal reasonable work:
||| - deletes the closure around an atomic constant like `TYPE`
@ -102,69 +166,89 @@ CanTSubst Term where
namespace ScopeTermN
export %inline
(//) : {s : Nat} ->
ScopeTermN s d n1 -> Lazy (TSubst d n1 n2) ->
ScopeTermN s d n2
ScopeTermN s q d n1 -> Lazy (TSubst q d n1 n2) ->
ScopeTermN s q d n2
S ns (Y body) // th = S ns $ Y $ body // pushN s (locs $ toList' ns) th
S ns (N body) // th = S ns $ N $ body // th
namespace DScopeTermN
export %inline
(//) : {s : Nat} ->
DScopeTermN s d n1 -> Lazy (TSubst d n1 n2) -> DScopeTermN s d n2
DScopeTermN s q d n1 -> Lazy (TSubst q d n1 n2) ->
DScopeTermN s q d n2
S ns (Y body) // th = S ns $ Y $ body // map (// shift s) th
S ns (N body) // th = S ns $ N $ body // th
export %inline CanShift (Term d) where s // by = s // Shift by
export %inline CanShift (Elim d) where e // by = e // Shift by
export %inline CanShift (Term q d) where s // by = s // Shift by
export %inline CanShift (Elim q d) where e // by = e // Shift by
export %inline CanShift (flip Term n) where s // by = s // Shift by
export %inline CanShift (flip Elim n) where e // by = e // Shift by
-- -- from is not accessible in this context
-- export %inline CanShift (\q => Term q d n) where s // by = s // Shift by
-- export %inline CanShift (\q => Elim q d n) where e // by = e // Shift by
export %inline CanShift (\d => Term q d n) where s // by = s // Shift by
export %inline CanShift (\d => Elim q d n) where e // by = e // Shift by
export %inline
{s : Nat} -> CanShift (ScopeTermN s d) where
{s : Nat} -> CanShift (ScopeTermN s q d) where
b // by = b // Shift by
export %inline
comp : DSubst d1 d2 -> TSubst d1 n1 mid -> TSubst d2 mid n2 -> TSubst d2 n1 n2
comp th ps ph = map (// th) ps . ph
comp : {q1, q2 : Nat} ->
QSubst q1 q2 -> DSubst d1 d2 ->
TSubst q1 d1 n1 mid -> TSubst q2 d2 mid n2 -> TSubst q2 d2 n1 n2
comp th ph ps ps' = map (\t => t // th // ph) ps . ps'
-- export %inline
-- compD : DSubst d1 d2 -> TSubst q d1 n1 mid ->
-- TSubst q d2 mid n2 -> TSubst q d2 n1 n2
-- compD th ps ph = map (// th) ps . ph
-- export %inline
-- compQ : {q1, q2 : Nat} -> QSubst q1 q2 -> TSubst q1 d n1 mid ->
-- TSubst q2 d mid n2 -> TSubst q2 d n1 n2
-- compQ th ps ph = map (// th) ps . ph
public export %inline
dweakT : (by : Nat) -> Term d n -> Term (by + d) n
dweakT : (by : Nat) -> Term q d n -> Term q (by + d) n
dweakT by t = t // shift by
public export %inline
dweakS : (by : Nat) -> ScopeTermN s d n -> ScopeTermN s (by + d) n
dweakS : (by : Nat) -> ScopeTermN s q d n -> ScopeTermN s q (by + d) n
dweakS by t = t // shift by
public export %inline
dweakDS : {s : Nat} -> (by : Nat) ->
DScopeTermN s d n -> DScopeTermN s (by + d) n
DScopeTermN s q d n -> DScopeTermN s q (by + d) n
dweakDS by t = t // shift by
public export %inline
dweakE : (by : Nat) -> Elim d n -> Elim (by + d) n
dweakE : (by : Nat) -> Elim q d n -> Elim q (by + d) n
dweakE by t = t // shift by
public export %inline
weakT : (by : Nat) -> Term d n -> Term d (by + n)
weakT : (by : Nat) -> Term q d n -> Term q d (by + n)
weakT by t = t // shift by
public export %inline
weakS : {s : Nat} -> (by : Nat) -> ScopeTermN s d n -> ScopeTermN s d (by + n)
weakS : {s : Nat} -> (by : Nat) ->
ScopeTermN s q d n -> ScopeTermN s q d (by + n)
weakS by t = t // shift by
public export %inline
weakDS : {s : Nat} -> (by : Nat) ->
DScopeTermN s d n -> DScopeTermN s d (by + n)
DScopeTermN s q d n -> DScopeTermN s q d (by + n)
weakDS by t = t // shift by
public export %inline
weakE : (by : Nat) -> Elim d n -> Elim d (by + n)
weakE : (by : Nat) -> Elim q d n -> Elim q d (by + n)
weakE by t = t // shift by
-- no weakQ etc because no first-class binder to push under
parameters {auto _ : CanShift f} {s : Nat}
export %inline
@ -188,69 +272,74 @@ namespace ScopeTermN
t.term0 = getTerm0 t.body
export %inline
subN : ScopeTermN s d n -> SnocVect s (Elim d n) -> Term d n
subN : ScopeTermN s q d n -> SnocVect s (Elim q d n) -> Term q d n
subN (S _ (Y body)) es = body // fromSnocVect es
subN (S _ (N body)) _ = body
export %inline
sub1 : ScopeTerm d n -> Elim d n -> Term d n
sub1 : ScopeTerm q d n -> Elim q d n -> Term q d n
sub1 t e = subN t [< e]
export %inline
dsubN : DScopeTermN s d n -> SnocVect s (Dim d) -> Term d n
dsubN : DScopeTermN s q d n -> SnocVect s (Dim d) -> Term q d n
dsubN (S _ (Y body)) ps = body // fromSnocVect ps
dsubN (S _ (N body)) _ = body
export %inline
dsub1 : DScopeTerm d n -> Dim d -> Term d n
dsub1 : DScopeTerm q d n -> Dim d -> Term q d n
dsub1 t p = dsubN t [< p]
public export %inline
(.zero) : (body : DScopeTerm d n) -> {default body.loc loc : Loc} -> Term d n
(.zero) : (body : DScopeTerm q d n) -> {default body.loc loc : Loc} ->
Term q d n
body.zero = dsub1 body $ K Zero loc
public export %inline
(.one) : (body : DScopeTerm d n) -> {default body.loc loc : Loc} -> Term d n
(.one) : (body : DScopeTerm q d n) -> {default body.loc loc : Loc} ->
Term q d n
body.one = dsub1 body $ K One loc
public export
0 CloTest : TermLike -> Type
CloTest tm = forall d, n. tm d n -> Bool
CloTest tm = forall q, d, n. tm q d n -> Bool
public export
interface PushSubsts (0 tm : TermLike) (0 isClo : CloTest tm) | tm where
pushSubstsWith : DSubst d1 d2 -> TSubst d2 n1 n2 ->
tm d1 n1 -> Subset (tm d2 n2) (No . isClo)
pushSubstsWith : {q1, q2 : Nat} ->
QSubst q1 q2 -> DSubst d1 d2 -> TSubst q2 d2 n1 n2 ->
tm q1 d1 n1 -> Subset (tm q2 d2 n2) (No . isClo)
public export
0 NotClo : {isClo : CloTest tm} -> PushSubsts tm isClo => Pred (tm d n)
0 NotClo : {isClo : CloTest tm} -> PushSubsts tm isClo => Pred (tm q d n)
NotClo = No . isClo
public export
0 NonClo : (tm : TermLike) -> {isClo : CloTest tm} ->
PushSubsts tm isClo => TermLike
NonClo tm d n = Subset (tm d n) NotClo
NonClo tm q d n = Subset (tm q d n) NotClo
public export %inline
nclo : {isClo : CloTest tm} -> (0 _ : PushSubsts tm isClo) =>
(t : tm d n) -> (0 nc : NotClo t) => NonClo tm d n
(t : tm q d n) -> (0 nc : NotClo t) => NonClo tm q d n
nclo t = Element t nc
parameters {0 isClo : CloTest tm} {auto _ : PushSubsts tm isClo}
||| if the input term has any top-level closures, push them under one layer of
||| syntax
export %inline
pushSubsts : tm d n -> NonClo tm d n
pushSubsts s = pushSubstsWith id id s
pushSubsts : {q : Nat} -> tm q d n -> NonClo tm q d n
pushSubsts s = pushSubstsWith id id id s
export %inline
pushSubstsWith' : DSubst d1 d2 -> TSubst d2 n1 n2 -> tm d1 n1 -> tm d2 n2
pushSubstsWith' th ph x = fst $ pushSubstsWith th ph x
pushSubstsWith' : {q1, q2 : Nat} ->
QSubst q1 q2 -> DSubst d1 d2 -> TSubst q2 d2 n1 n2 ->
tm q1 d1 n1 -> tm q2 d2 n2
pushSubstsWith' th ph ps x = fst $ pushSubstsWith th ph ps x
export %inline
pushSubsts' : tm d n -> tm d n
pushSubsts' : {q : Nat} -> tm q d n -> tm q d n
pushSubsts' s = fst $ pushSubsts s
mutual
@ -258,6 +347,7 @@ mutual
isCloT : CloTest Term
isCloT (CloT {}) = True
isCloT (DCloT {}) = True
isCloT (QCloT {}) = True
isCloT (E e) = isCloE e
isCloT _ = False
@ -265,92 +355,118 @@ mutual
isCloE : CloTest Elim
isCloE (CloE {}) = True
isCloE (DCloE {}) = True
isCloE (QCloE {}) = True
isCloE _ = False
export
PushSubsts Elim Subst.isCloE where
pushSubstsWith th ph (F x u loc) =
pushSubstsWith th ph ps (F x u loc) =
nclo $ F x u loc
pushSubstsWith th ph (B i loc) =
let res = getLoc ph i loc in
pushSubstsWith th ph ps (B i loc) =
let res = get ps i loc in
case nchoose $ isCloE res of
Left yes => assert_total pushSubsts res
Right no => Element res no
pushSubstsWith th ph (App f s loc) =
nclo $ App (f // th // ph) (s // th // ph) loc
pushSubstsWith th ph (CasePair pi p r b loc) =
nclo $ CasePair pi (p // th // ph) (r // th // ph) (b // th // ph) loc
pushSubstsWith th ph (Fst pair loc) =
nclo $ Fst (pair // th // ph) loc
pushSubstsWith th ph (Snd pair loc) =
nclo $ Snd (pair // th // ph) loc
pushSubstsWith th ph (CaseEnum pi t r arms loc) =
nclo $ CaseEnum pi (t // th // ph) (r // th // ph)
(map (\b => b // th // ph) arms) loc
pushSubstsWith th ph (CaseNat pi pi' n r z s loc) =
nclo $ CaseNat pi pi' (n // th // ph) (r // th // ph)
(z // th // ph) (s // th // ph) loc
pushSubstsWith th ph (CaseBox pi x r b loc) =
nclo $ CaseBox pi (x // th // ph) (r // th // ph) (b // th // ph) loc
pushSubstsWith th ph (DApp f d loc) =
nclo $ DApp (f // th // ph) (d // th) loc
pushSubstsWith th ph (Ann s a loc) =
nclo $ Ann (s // th // ph) (a // th // ph) loc
pushSubstsWith th ph (Coe ty p q val loc) =
nclo $ Coe (ty // th // ph) (p // th) (q // th) (val // th // ph) loc
pushSubstsWith th ph (Comp ty p q val r zero one loc) =
nclo $ Comp (ty // th // ph) (p // th) (q // th)
(val // th // ph) (r // th)
(zero // th // ph) (one // th // ph) loc
pushSubstsWith th ph (TypeCase ty ret arms def loc) =
nclo $ TypeCase (ty // th // ph) (ret // th // ph)
(map (\t => t // th // ph) arms) (def // th // ph) loc
pushSubstsWith th ph (CloE (Sub e ps)) =
pushSubstsWith th (comp th ps ph) e
pushSubstsWith th ph (DCloE (Sub e ps)) =
pushSubstsWith (ps . th) ph e
pushSubstsWith th ph ps (App f s loc) =
nclo $ App (f // th // ph // ps) (s // th // ph // ps) loc
pushSubstsWith th ph ps (CasePair pi p r b loc) =
nclo $ CasePair (pi //? th)
(p // th // ph // ps)
(r // th // ph // ps)
(b // th // ph // ps) loc
pushSubstsWith th ph ps (Fst pair loc) =
nclo $ Fst (pair // th // ph // ps) loc
pushSubstsWith th ph ps (Snd pair loc) =
nclo $ Snd (pair // th // ph // ps) loc
pushSubstsWith th ph ps (CaseEnum pi t r arms loc) =
nclo $ CaseEnum (pi //? th)
(t // th // ph // ps)
(r // th // ph // ps)
(map (\b => b // th // ph // ps) arms) loc
pushSubstsWith th ph ps (CaseNat pi pi' n r z s loc) =
nclo $ CaseNat (pi //? th) (pi' //? th)
(n // th // ph // ps)
(r // th // ph // ps)
(z // th // ph // ps)
(s // th // ph // ps) loc
pushSubstsWith th ph ps (CaseBox pi x r b loc) =
nclo $ CaseBox (pi //? th)
(x // th // ph // ps)
(r // th // ph // ps)
(b // th // ph // ps) loc
pushSubstsWith th ph ps (DApp f d loc) =
nclo $ DApp (f // th // ph // ps) (d // ph) loc
pushSubstsWith th ph ps (Ann s a loc) =
nclo $ Ann (s // th // ph // ps) (a // th // ph // ps) loc
pushSubstsWith th ph ps (Coe ty p q val loc) =
nclo $ Coe
(ty // th // ph // ps)
(p // ph) (q // ph)
(val // th // ph // ps) loc
pushSubstsWith th ph ps (Comp ty p q val r zero one loc) =
nclo $ Comp (ty // th // ph // ps) (p // ph) (q // ph)
(val // th // ph // ps) (r // ph)
(zero // th // ph // ps) (one // th // ph // ps) loc
pushSubstsWith th ph ps (TypeCase ty ret arms def loc) =
nclo $ TypeCase (ty // th // ph // ps) (ret // th // ph // ps)
(map (\t => t // th // ph // ps) arms) (def // th // ph // ps) loc
pushSubstsWith th ph ps (CloE (Sub e ps')) =
pushSubstsWith th ph (comp th ph ps' ps) e
pushSubstsWith th ph ps (DCloE (Sub e ph')) =
pushSubstsWith th (ph' . ph) ps e
pushSubstsWith th ph ps (QCloE (SubR e th')) =
pushSubstsWith (th' .? th) ph ps e
export
PushSubsts Term Subst.isCloT where
pushSubstsWith th ph (TYPE l loc) =
pushSubstsWith th ph ps (TYPE l loc) =
nclo $ TYPE l loc
pushSubstsWith th ph (IOState loc) =
pushSubstsWith _ _ _ (IOState loc) =
nclo $ IOState loc
pushSubstsWith th ph (Pi qty a body loc) =
nclo $ Pi qty (a // th // ph) (body // th // ph) loc
pushSubstsWith th ph (Lam body loc) =
nclo $ Lam (body // th // ph) loc
pushSubstsWith th ph (Sig a b loc) =
nclo $ Sig (a // th // ph) (b // th // ph) loc
pushSubstsWith th ph (Pair s t loc) =
nclo $ Pair (s // th // ph) (t // th // ph) loc
pushSubstsWith th ph (Enum tags loc) =
pushSubstsWith th ph ps (Pi qty a body loc) =
nclo $ Pi (qty //? th)
(a // th // ph // ps)
(body // th // ph // ps) loc
pushSubstsWith th ph ps (Lam body loc) =
nclo $ Lam (body // th // ph // ps) loc
pushSubstsWith th ph ps (Sig a b loc) =
nclo $ Sig (a // th // ph // ps) (b // th // ph // ps) loc
pushSubstsWith th ph ps (Pair s t loc) =
nclo $ Pair (s // th // ph // ps) (t // th // ph // ps) loc
pushSubstsWith th ph ps (Enum tags loc) =
nclo $ Enum tags loc
pushSubstsWith th ph (Tag tag loc) =
pushSubstsWith th ph ps (Tag tag loc) =
nclo $ Tag tag loc
pushSubstsWith th ph (Eq ty l r loc) =
nclo $ Eq (ty // th // ph) (l // th // ph) (r // th // ph) loc
pushSubstsWith th ph (DLam body loc) =
nclo $ DLam (body // th // ph) loc
pushSubstsWith _ _ (NAT loc) =
pushSubstsWith th ph ps (Eq ty l r loc) =
nclo $ Eq
(ty // th // ph // ps)
(l // th // ph // ps)
(r // th // ph // ps) loc
pushSubstsWith th ph ps (DLam body loc) =
nclo $ DLam (body // th // ph // ps) loc
pushSubstsWith _ _ _ (NAT loc) =
nclo $ NAT loc
pushSubstsWith _ _ (Nat n loc) =
pushSubstsWith _ _ _ (Nat n loc) =
nclo $ Nat n loc
pushSubstsWith th ph (Succ n loc) =
nclo $ Succ (n // th // ph) loc
pushSubstsWith _ _ (STRING loc) =
pushSubstsWith th ph ps (Succ n loc) =
nclo $ Succ (n // th // ph // ps) loc
pushSubstsWith _ _ _ (STRING loc) =
nclo $ STRING loc
pushSubstsWith _ _ (Str s loc) =
pushSubstsWith _ _ _ (Str s loc) =
nclo $ Str s loc
pushSubstsWith th ph (BOX pi ty loc) =
nclo $ BOX pi (ty // th // ph) loc
pushSubstsWith th ph (Box val loc) =
nclo $ Box (val // th // ph) loc
pushSubstsWith th ph (E e) =
let Element e nc = pushSubstsWith th ph e in nclo $ E e
pushSubstsWith th ph (Let qty rhs body loc) =
nclo $ Let qty (rhs // th // ph) (body // th // ph) loc
pushSubstsWith th ph (CloT (Sub s ps)) =
pushSubstsWith th (comp th ps ph) s
pushSubstsWith th ph (DCloT (Sub s ps)) =
pushSubstsWith (ps . th) ph s
pushSubstsWith th ph ps (BOX pi ty loc) =
nclo $ BOX (pi //? th) (ty // th // ph // ps) loc
pushSubstsWith th ph ps (Box val loc) =
nclo $ Box (val // th // ph // ps) loc
pushSubstsWith th ph ps (E e) =
let Element e nc = pushSubstsWith th ph ps e in nclo $ E e
pushSubstsWith th ph ps (Let qty rhs body loc) =
nclo $ Let (qty //? th)
(rhs // th // ph // ps)
(body // th // ph // ps) loc
pushSubstsWith th ph ps (CloT (Sub s ps')) =
pushSubstsWith th ph (comp th ph ps' ps) s
pushSubstsWith th ph ps (DCloT (Sub s ph')) =
pushSubstsWith th (ph' . ph) ps s
pushSubstsWith th ph ps (QCloT (SubR s th')) =
pushSubstsWith (th' .? th) ph ps s

View file

@ -29,20 +29,20 @@ tightenDScope f p (S names (N body)) = S names . N <$> f p body
mutual
private
tightenT : OPE n1 n2 -> Term d n2 -> Maybe (Term d n1)
tightenT : {q : Nat} -> OPE n1 n2 -> Term q d n2 -> Maybe (Term q d n1)
tightenT p s =
let Element s' _ = pushSubsts s in
tightenT' p $ assert_smaller s s'
private
tightenE : OPE n1 n2 -> Elim d n2 -> Maybe (Elim d n1)
tightenE : {q : Nat} -> OPE n1 n2 -> Elim q d n2 -> Maybe (Elim q d n1)
tightenE p e =
let Element e' _ = pushSubsts e in
tightenE' p $ assert_smaller e e'
private
tightenT' : OPE n1 n2 -> (t : Term d n2) -> (0 nt : NotClo t) =>
Maybe (Term d n1)
tightenT' : {q : Nat} -> OPE n1 n2 -> (t : Term q d n2) -> (0 nt : NotClo t) =>
Maybe (Term q d n1)
tightenT' p (TYPE l loc) = pure $ TYPE l loc
tightenT' p (IOState loc) = pure $ IOState loc
tightenT' p (Pi qty arg res loc) =
@ -81,8 +81,9 @@ mutual
E <$> assert_total tightenE p e
private
tightenE' : OPE n1 n2 -> (e : Elim d n2) -> (0 ne : NotClo e) =>
Maybe (Elim d n1)
tightenE' : {q : Nat} ->
OPE n1 n2 -> (e : Elim q d n2) -> (0 ne : NotClo e) =>
Maybe (Elim q d n1)
tightenE' p (F x u loc) =
pure $ F x u loc
tightenE' p (B i loc) =
@ -140,34 +141,35 @@ mutual
<*> pure loc
export
tightenS : {s : Nat} -> OPE m n ->
ScopeTermN s f n -> Maybe (ScopeTermN s f m)
tightenS : {q, s : Nat} -> OPE m n ->
ScopeTermN s q d n -> Maybe (ScopeTermN s q d m)
tightenS = assert_total $ tightenScope tightenT
export
tightenDS : OPE m n -> DScopeTermN s f n -> Maybe (DScopeTermN s f m)
tightenDS = assert_total $ tightenDScope tightenT {f = \n, d => Term d n}
tightenDS : {q : Nat} ->
OPE m n -> DScopeTermN s q d n -> Maybe (DScopeTermN s q d m)
tightenDS = assert_total $ tightenDScope tightenT {f = \n, d => Term q d n}
export Tighten (Elim d) where tighten p e = tightenE p e
export Tighten (Term d) where tighten p t = tightenT p t
export {q : Nat} -> Tighten (Elim q d) where tighten p e = tightenE p e
export {q : Nat} -> Tighten (Term q d) where tighten p t = tightenT p t
mutual
export
dtightenT : OPE d1 d2 -> Term d2 n -> Maybe (Term d1 n)
dtightenT : {q : Nat} -> OPE d1 d2 -> Term q d2 n -> Maybe (Term q d1 n)
dtightenT p s =
let Element s' _ = pushSubsts s in
dtightenT' p $ assert_smaller s s'
export
dtightenE : OPE d1 d2 -> Elim d2 n -> Maybe (Elim d1 n)
dtightenE : {q : Nat} -> OPE d1 d2 -> Elim q d2 n -> Maybe (Elim q d1 n)
dtightenE p e =
let Element e' _ = pushSubsts e in
dtightenE' p $ assert_smaller e e'
private
dtightenT' : OPE d1 d2 -> (t : Term d2 n) -> (0 nt : NotClo t) =>
Maybe (Term d1 n)
dtightenT' : {q : Nat} -> OPE d1 d2 -> (t : Term q d2 n) -> (0 nt : NotClo t) =>
Maybe (Term q d1 n)
dtightenT' p (TYPE l loc) =
pure $ TYPE l loc
dtightenT' p (IOState loc) =
@ -208,8 +210,8 @@ mutual
E <$> assert_total dtightenE p e
export
dtightenE' : OPE d1 d2 -> (e : Elim d2 n) -> (0 ne : NotClo e) =>
Maybe (Elim d1 n)
dtightenE' : {q : Nat} -> OPE d1 d2 -> (e : Elim q d2 n) -> (0 ne : NotClo e) =>
Maybe (Elim q d1 n)
dtightenE' p (F x u loc) =
pure $ F x u loc
dtightenE' p (B i loc) =
@ -258,17 +260,18 @@ mutual
(traverse (dtightenS p) arms) (dtightenT p def) (pure loc)|]
export
dtightenS : OPE d1 d2 -> ScopeTermN s d2 n -> Maybe (ScopeTermN s d1 n)
dtightenS = assert_total $ tightenDScope dtightenT {f = Term}
dtightenS : {q : Nat} -> OPE d1 d2 -> ScopeTermN s q d2 n ->
Maybe (ScopeTermN s q d1 n)
dtightenS = assert_total $ tightenDScope dtightenT {f = Term q}
export
dtightenDS : {s : Nat} -> OPE d1 d2 ->
DScopeTermN s d2 n -> Maybe (DScopeTermN s d1 n)
dtightenDS : {q, s : Nat} -> OPE d1 d2 ->
DScopeTermN s q d2 n -> Maybe (DScopeTermN s q d1 n)
dtightenDS = assert_total $ tightenScope dtightenT
export Tighten (\d => Term d n) where tighten p t = dtightenT p t
export Tighten (\d => Elim d n) where tighten p e = dtightenE p e
export {q : Nat} -> Tighten (\d => Term q d n) where tighten p t = dtightenT p t
export {q : Nat} -> Tighten (\d => Elim q d n) where tighten p e = dtightenE p e
parameters {auto _ : Tighten f} {s : Nat}
@ -300,59 +303,64 @@ ST : Tighten f => {s : Nat} -> BContext s -> f (s + n) -> Scoped s f n
ST names body = squeeze' $ SY names body
public export %inline
DST : {s : Nat} -> BContext s -> Term (s + d) n -> DScopeTermN s d n
DST names body = dsqueeze' {f = Term} $ SY names body
DST : {s, q : Nat} -> BContext s -> Term q (s + d) n -> DScopeTermN s q d n
DST names body = dsqueeze' {f = Term q} $ SY names body
public export %inline
PiT : (qty : Qty) -> (x : BindName) ->
(arg : Term d n) -> (res : Term d (S n)) -> (loc : Loc) -> Term d n
PiT : {q : Nat} -> (qty : Qty q) -> (x : BindName) ->
(arg : Term q d n) -> (res : Term q d (S n)) -> (loc : Loc) -> Term q d n
PiT {qty, x, arg, res, loc} = Pi {qty, arg, res = ST [< x] res, loc}
public export %inline
LamT : (x : BindName) -> (body : Term d (S n)) -> (loc : Loc) -> Term d n
LamT : {q : Nat} ->
(x : BindName) -> (body : Term q d (S n)) -> (loc : Loc) -> Term q d n
LamT {x, body, loc} = Lam {body = ST [< x] body, loc}
public export %inline
SigT : (x : BindName) -> (fst : Term d n) ->
(snd : Term d (S n)) -> (loc : Loc) -> Term d n
SigT : {q : Nat} -> (x : BindName) -> (fst : Term q d n) ->
(snd : Term q d (S n)) -> (loc : Loc) -> Term q d n
SigT {x, fst, snd, loc} = Sig {fst, snd = ST [< x] snd, loc}
public export %inline
EqT : (i : BindName) -> (ty : Term (S d) n) ->
(l, r : Term d n) -> (loc : Loc) -> Term d n
EqT : {q : Nat} -> (i : BindName) -> (ty : Term q (S d) n) ->
(l, r : Term q d n) -> (loc : Loc) -> Term q d n
EqT {i, ty, l, r, loc} = Eq {ty = DST [< i] ty, l, r, loc}
public export %inline
DLamT : (i : BindName) -> (body : Term (S d) n) -> (loc : Loc) -> Term d n
DLamT : {q : Nat} ->
(i : BindName) -> (body : Term q (S d) n) -> (loc : Loc) -> Term q d n
DLamT {i, body, loc} = DLam {body = DST [< i] body, loc}
public export %inline
CoeT : (i : BindName) -> (ty : Term (S d) n) ->
(p, q : Dim d) -> (val : Term d n) -> (loc : Loc) -> Elim d n
CoeT {i, ty, p, q, val, loc} = Coe {ty = DST [< i] ty, p, q, val, loc}
CoeT : {q : Nat} -> (i : BindName) -> (ty : Term q (S d) n) ->
(p, p' : Dim d) -> (val : Term q d n) -> (loc : Loc) -> Elim q d n
CoeT {i, ty, p, p', val, loc} = Coe {ty = DST [< i] ty, p, p', val, loc}
public export %inline
typeCase1T : Elim d n -> Term d n ->
(k : TyConKind) -> BContext (arity k) -> Term d (arity k + n) ->
typeCase1T : {q : Nat} ->
Elim q d n -> Term q d n ->
(k : TyConKind) -> BContext (arity k) -> Term q d (arity k + n) ->
(loc : Loc) ->
{default (NAT loc) def : Term d n} ->
Elim d n
{default (NAT loc) def : Term q d n} ->
Elim q d n
typeCase1T ty ret k ns body loc {def} =
typeCase ty ret [(k ** ST ns body)] def loc
public export %inline
CompH' : (ty : DScopeTerm d n) -> (p, q : Dim d) -> (val : Term d n) ->
(r : Dim d) -> (zero, one : DScopeTerm d n) -> (loc : Loc) -> Elim d n
CompH' {ty, p, q, val, r, zero, one, loc} =
CompH' : {q : Nat} ->
(ty : DScopeTerm q d n) -> (p, p' : Dim d) -> (val : Term q d n) ->
(r : Dim d) -> (zero, one : DScopeTerm q d n) -> (loc : Loc) ->
Elim q d n
CompH' {ty, p, p', val, r, zero, one, loc} =
let ty' = DST ty.names $ ty.term // (B VZ ty.name.loc ::: shift 2) in
Comp {
ty = dsub1 ty q, p, q,
val = E $ Coe ty p q val val.loc, r,
ty = dsub1 ty p', p, p',
val = E $ Coe ty p p' val val.loc, r,
zero = DST zero.names $ E $
Coe ty' (B VZ zero.loc) (weakD 1 q) zero.term zero.loc,
Coe ty' (B VZ zero.loc) (weakD 1 p') zero.term zero.loc,
one = DST one.names $ E $
Coe ty' (B VZ one.loc) (weakD 1 q) one.term one.loc,
Coe ty' (B VZ one.loc) (weakD 1 p') one.term one.loc,
loc
}
@ -365,12 +373,12 @@ CompH' {ty, p, q, val, r, zero, one, loc} =
||| 1 j ⇒ coe [i ⇒ A] @j @q t₁
||| }
public export %inline
CompH : (i : BindName) -> (ty : Term (S d) n) ->
(p, q : Dim d) -> (val : Term d n) -> (r : Dim d) ->
(j0 : BindName) -> (zero : Term (S d) n) ->
(j1 : BindName) -> (one : Term (S d) n) ->
CompH : {q : Nat} -> (i : BindName) -> (ty : Term q (S d) n) ->
(p, p' : Dim d) -> (val : Term q d n) -> (r : Dim d) ->
(j0 : BindName) -> (zero : Term q (S d) n) ->
(j1 : BindName) -> (one : Term q (S d) n) ->
(loc : Loc) ->
Elim d n
CompH {i, ty, p, q, val, r, j0, zero, j1, one, loc} =
CompH' {ty = DST [< i] ty, p, q, val, r,
Elim q d n
CompH {i, ty, p, p', val, r, j0, zero, j1, one, loc} =
CompH' {ty = DST [< i] ty, p, p', val, r,
zero = DST [< j0] zero, one = DST [< j1] one, loc}

View file

@ -21,22 +21,22 @@ TTName = TT.Name
public export
CheckResult' : Nat -> Type
CheckResult' : Nat -> Nat -> Type
CheckResult' = QOutput
public export
CheckResult : DimEq d -> Nat -> Type
CheckResult eqs n = IfConsistent eqs $ CheckResult' n
CheckResult : DimEq d -> Nat -> Nat -> Type
CheckResult eqs q n = IfConsistent eqs $ CheckResult' q n
public export
record InferResult' d n where
record InferResult' q d n where
constructor InfRes
type : Term d n
qout : QOutput n
type : Term q d n
qout : QOutput q n
public export
InferResult : DimEq d -> TermLike
InferResult eqs d n = IfConsistent eqs $ InferResult' d n
InferResult eqs q d n = IfConsistent eqs $ InferResult' q d n
export
@ -45,21 +45,22 @@ lookupFree x loc defs = maybe (throw $ NotInScope loc x) pure $ lookup x defs
public export
substCasePairRet : BContext 2 -> Term d n -> ScopeTerm d n -> Term d (2 + n)
substCasePairRet : BContext 2 -> Term q d n -> ScopeTerm q d n ->
Term q d (2 + n)
substCasePairRet [< x, y] dty retty =
let tm = Pair (BVT 1 x.loc) (BVT 0 y.loc) $ x.loc `extendL` y.loc
arg = Ann tm (dty // fromNat 2) tm.loc in
retty.term // (arg ::: shift 2)
public export
substCaseSuccRet : BContext 2 -> ScopeTerm d n -> Term d (2 + n)
substCaseSuccRet : BContext 2 -> ScopeTerm q d n -> Term q d (2 + n)
substCaseSuccRet [< p, ih] retty =
let loc = p.loc `extendL` ih.loc
arg = Ann (Succ (BVT 1 p.loc) p.loc) (NAT p.loc) loc in
retty.term // (arg ::: shift 2)
public export
substCaseBoxRet : BindName -> Term d n -> ScopeTerm d n -> Term d (S n)
substCaseBoxRet : BindName -> Term q d n -> ScopeTerm q d n -> Term q d (S n)
substCaseBoxRet x dty retty =
let arg = Ann (Box (BVT 0 x.loc) x.loc) (weakT 1 dty) x.loc in
retty.term // (arg ::: shift 1)
@ -68,15 +69,15 @@ substCaseBoxRet x dty retty =
private
0 ExpectErrorConstructor : Type
ExpectErrorConstructor =
forall d, n. Loc -> NameContexts d n -> Term d n -> Error
forall q, d, n. Loc -> NameContexts q d n -> Term q d n -> Error
parameters (defs : Definitions)
{auto _ : (Has ErrorEff fs, Has NameGen fs, Has Log fs)}
namespace TyContext
parameters (ctx : TyContext d n) (sg : SQty) (loc : Loc)
parameters (ctx : TyContext q d n) (sg : SQty) (loc : Loc)
export covering
whnf : {0 isRedex : RedexTest tm} -> CanWhnf tm isRedex =>
tm d n -> Eff fs (NonRedex tm d n defs (toWhnfContext ctx) sg)
tm q d n -> Eff fs (NonRedex tm q d n defs (toWhnfContext ctx) sg)
whnf tm = do
let Val n = ctx.termLen; Val d = ctx.dimLen
res <- lift $ runExcept $ whnf defs (toWhnfContext ctx) sg tm
@ -84,7 +85,7 @@ parameters (defs : Definitions)
private covering %macro
expect : ExpectErrorConstructor -> TTImp -> TTImp ->
Elab (Term d n -> Eff fs a)
Elab (Term q d n -> Eff fs a)
expect err pat rhs = Prelude.do
match <- check `(\case ~(pat) => Just ~(rhs); _ => Nothing)
pure $ \term => do
@ -92,54 +93,54 @@ parameters (defs : Definitions)
maybe (throw $ err loc ctx.names term) pure $ match $ fst res
export covering %inline
expectTYPE : Term d n -> Eff fs Universe
expectTYPE : Term q d n -> Eff fs Universe
expectTYPE = expect ExpectedTYPE `(TYPE {l, _}) `(l)
export covering %inline
expectPi : Term d n -> Eff fs (Qty, Term d n, ScopeTerm d n)
expectPi : Term q d n -> Eff fs (Qty q, Term q d n, ScopeTerm q d n)
expectPi = expect ExpectedPi `(Pi {qty, arg, res, _}) `((qty, arg, res))
export covering %inline
expectSig : Term d n -> Eff fs (Term d n, ScopeTerm d n)
expectSig : Term q d n -> Eff fs (Term q d n, ScopeTerm q d n)
expectSig = expect ExpectedSig `(Sig {fst, snd, _}) `((fst, snd))
export covering %inline
expectEnum : Term d n -> Eff fs (SortedSet TagVal)
expectEnum : Term q d n -> Eff fs (SortedSet TagVal)
expectEnum = expect ExpectedEnum `(Enum {cases, _}) `(cases)
export covering %inline
expectEq : Term d n -> Eff fs (DScopeTerm d n, Term d n, Term d n)
expectEq : Term q d n -> Eff fs (DScopeTerm q d n, Term q d n, Term q d n)
expectEq = expect ExpectedEq `(Eq {ty, l, r, _}) `((ty, l, r))
export covering %inline
expectNAT : Term d n -> Eff fs ()
expectNAT : Term q d n -> Eff fs ()
expectNAT = expect ExpectedNAT `(NAT {}) `(())
export covering %inline
expectSTRING : Term d n -> Eff fs ()
expectSTRING : Term q d n -> Eff fs ()
expectSTRING = expect ExpectedSTRING `(STRING {}) `(())
export covering %inline
expectBOX : Term d n -> Eff fs (Qty, Term d n)
expectBOX : Term q d n -> Eff fs (Qty q, Term q d n)
expectBOX = expect ExpectedBOX `(BOX {qty, ty, _}) `((qty, ty))
export covering %inline
expectIOState : Term d n -> Eff fs ()
expectIOState : Term q d n -> Eff fs ()
expectIOState = expect ExpectedIOState `(IOState {}) `(())
namespace EqContext
parameters (ctx : EqContext n) (sg : SQty) (loc : Loc)
parameters (ctx : EqContext q n) (sg : SQty) (loc : Loc)
export covering
whnf : {0 isRedex : RedexTest tm} -> CanWhnf tm isRedex =>
tm 0 n -> Eff fs (NonRedex tm 0 n defs (toWhnfContext ctx) sg)
tm q 0 n -> Eff fs (NonRedex tm q 0 n defs (toWhnfContext ctx) sg)
whnf tm = do
res <- lift $ runExcept $ whnf defs (toWhnfContext ctx) sg tm
rethrow res
private covering %macro
expect : ExpectErrorConstructor -> TTImp -> TTImp ->
Elab (Term 0 n -> Eff fs a)
Elab (Term q 0 n -> Eff fs a)
expect err pat rhs = do
match <- check `(\case ~(pat) => Just ~(rhs); _ => Nothing)
pure $ \term => do
@ -148,37 +149,37 @@ parameters (defs : Definitions)
maybe (throw $ err loc ctx.names t0) pure $ match $ fst res
export covering %inline
expectTYPE : Term 0 n -> Eff fs Universe
expectTYPE : Term q 0 n -> Eff fs Universe
expectTYPE = expect ExpectedTYPE `(TYPE {l, _}) `(l)
export covering %inline
expectPi : Term 0 n -> Eff fs (Qty, Term 0 n, ScopeTerm 0 n)
expectPi : Term q 0 n -> Eff fs (Qty q, Term q 0 n, ScopeTerm q 0 n)
expectPi = expect ExpectedPi `(Pi {qty, arg, res, _}) `((qty, arg, res))
export covering %inline
expectSig : Term 0 n -> Eff fs (Term 0 n, ScopeTerm 0 n)
expectSig : Term q 0 n -> Eff fs (Term q 0 n, ScopeTerm q 0 n)
expectSig = expect ExpectedSig `(Sig {fst, snd, _}) `((fst, snd))
export covering %inline
expectEnum : Term 0 n -> Eff fs (SortedSet TagVal)
expectEnum : Term q 0 n -> Eff fs (SortedSet TagVal)
expectEnum = expect ExpectedEnum `(Enum {cases, _}) `(cases)
export covering %inline
expectEq : Term 0 n -> Eff fs (DScopeTerm 0 n, Term 0 n, Term 0 n)
expectEq : Term q 0 n -> Eff fs (DScopeTerm q 0 n, Term q 0 n, Term q 0 n)
expectEq = expect ExpectedEq `(Eq {ty, l, r, _}) `((ty, l, r))
export covering %inline
expectNAT : Term 0 n -> Eff fs ()
expectNAT : Term q 0 n -> Eff fs ()
expectNAT = expect ExpectedNAT `(NAT {}) `(())
export covering %inline
expectSTRING : Term 0 n -> Eff fs ()
expectSTRING : Term q 0 n -> Eff fs ()
expectSTRING = expect ExpectedSTRING `(STRING {}) `(())
export covering %inline
expectBOX : Term 0 n -> Eff fs (Qty, Term 0 n)
expectBOX : Term q 0 n -> Eff fs (Qty q, Term q 0 n)
expectBOX = expect ExpectedBOX `(BOX {qty, ty, _}) `((qty, ty))
export covering %inline
expectIOState : Term 0 n -> Eff fs ()
expectIOState : Term q 0 n -> Eff fs ()
expectIOState = expect ExpectedIOState `(IOState {}) `(())

View file

@ -3,7 +3,7 @@ module Quox.Typing.Context
import Quox.Syntax
import Quox.Context
import Quox.Pretty
import public Data.Singleton
import public Quox.SingletonExtra
import Derive.Prelude
%default total
@ -11,48 +11,60 @@ import Derive.Prelude
public export
QContext : Nat -> Type
QContext = Context' Qty
QContext : (q, n : Nat) -> Type
QContext q n = Context' (Qty q) n
public export
record LocalVar d n where
record LocalVar q d n where
constructor MkLocal
type : Term d n
term : Maybe (Term d n) -- if from a `let`
%runElab deriveIndexed "LocalVar" [Show]
type : Term q d n
term : Maybe (Term q d n) -- if from a `let`
-- %runElab deriveIndexed "LocalVar" [Show]
export
[LocateVarType] Located (LocalVar q d n) where x.loc = x.type.loc
namespace LocalVar
export %inline
letVar : (type, term : Term d n) -> LocalVar d n
letVar : (type, term : Term q d n) -> LocalVar q d n
letVar type term = MkLocal {type, term = Just term}
export %inline
lamVar : (type : Term d n) -> LocalVar d n
lamVar : (type : Term q d n) -> LocalVar q d n
lamVar type = MkLocal {type, term = Nothing}
export %inline
mapVar : (Term d n -> Term d' n') -> LocalVar d n -> LocalVar d' n'
mapVar : (Term q d n -> Term q' d' n') -> LocalVar q d n -> LocalVar q' d' n'
mapVar f = {type $= f, term $= map f}
export %inline
subD : DSubst d1 d2 -> LocalVar d1 n -> LocalVar d2 n
subQ : {q1, q2 : Nat} -> QSubst q1 q2 -> LocalVar q1 d n -> LocalVar q2 d n
subQ th = mapVar (// th)
export %inline
weakQ : {q : Nat} -> LocalVar q d n -> LocalVar (S q) d n
weakQ = subQ $ shift 1
export %inline
subD : DSubst d1 d2 -> LocalVar q d1 n -> LocalVar q d2 n
subD th = mapVar (// th)
export %inline
weakD : LocalVar d n -> LocalVar (S d) n
weakD : LocalVar q d n -> LocalVar q (S d) n
weakD = subD $ shift 1
export %inline CanShift (LocalVar d) where l // by = mapVar (// by) l
export %inline CanDSubst LocalVar where l // by = mapVar (// by) l
export %inline CanTSubst LocalVar where l // by = mapVar (// by) l
export %inline CanShift (LocalVar q d) where l // by = mapVar (// by) l
export %inline CanQSubst LocalVar where l // th = mapVar (// th) l
export %inline CanDSubst LocalVar where l // th = mapVar (// th) l
export %inline CanTSubst LocalVar where l // th = mapVar (// th) l
public export
TContext : TermLike
TContext d = Context (LocalVar d)
TContext q d = Context (LocalVar q d)
public export
QOutput : Nat -> Type
QOutput = Context' Qty
QOutput : (q, n : Nat) -> Type
QOutput = QContext
public export
DimAssign : Nat -> Type
@ -60,48 +72,54 @@ DimAssign = Context' DimConst
public export
record TyContext d n where
record TyContext q d n where
constructor MkTyContext
{auto qtyLen : Singleton q}
{auto dimLen : Singleton d}
{auto termLen : Singleton n}
qnames : BContext q -- only used for printing
dctx : DimEq d
dnames : BContext d -- only used for printing
tctx : TContext d n
tctx : TContext q d n
tnames : BContext n -- only used for printing
qtys : QContext n -- only used for printing
qtys : QContext q n -- only used for printing
%name TyContext ctx
%runElab deriveIndexed "TyContext" [Show]
-- %runElab deriveIndexed "TyContext" [Show]
public export
record EqContext n where
record EqContext q n where
constructor MkEqContext
{auto qtyLen : Singleton q}
{dimLen : Nat}
{auto termLen : Singleton n}
qnames : BContext q -- only used for printing
dassign : DimAssign dimLen -- only used for printing
dnames : BContext dimLen -- only used for printing
tctx : TContext 0 n
tctx : TContext q 0 n
tnames : BContext n -- only used for printing
qtys : QContext n -- only used for printing
qtys : QContext q n -- only used for printing
%name EqContext ctx
%runElab deriveIndexed "EqContext" [Show]
-- %runElab deriveIndexed "EqContext" [Show]
public export
record WhnfContext d n where
record WhnfContext q d n where
constructor MkWhnfContext
{auto qtyLen : Singleton q}
{auto dimLen : Singleton d}
{auto termLen : Singleton n}
qnames : BContext q -- only used for printing
dnames : BContext d
tnames : BContext n
tctx : TContext d n
tctx : TContext q d n
%name WhnfContext ctx
%runElab deriveIndexed "WhnfContext" [Show]
-- %runElab deriveIndexed "WhnfContext" [Show]
namespace TContext
export %inline
zeroFor : Context tm n -> QOutput n
zeroFor ctx = Zero <$ ctx
zeroFor : {q : Nat} -> Located1 tm => Context tm n -> QOutput q n
zeroFor = map $ \x => zero x.loc
public export
extendLen : Telescope a n1 n2 -> Singleton n1 -> Singleton n2
@ -110,38 +128,40 @@ extendLen (tel :< _) x = [|S $ extendLen tel x|]
public export
CtxExtension : Nat -> Nat -> Nat -> Type
CtxExtension d = Telescope ((Qty, BindName,) . Term d)
CtxExtension : (q, d, n1, n2 : Nat) -> Type
CtxExtension q d = Telescope $ \n => (Qty q, BindName, Term q d n)
public export
CtxExtension0 : Nat -> Nat -> Nat -> Type
CtxExtension0 d = Telescope ((BindName,) . Term d)
CtxExtension0 : (q, d, n1, n2 : Nat) -> Type
CtxExtension0 q d = Telescope $ \n => (BindName, Term q d n)
public export
CtxExtensionLet : Nat -> Nat -> Nat -> Type
CtxExtensionLet d = Telescope ((Qty, BindName,) . LocalVar d)
CtxExtensionLet : (q, d, n1, n2 : Nat) -> Type
CtxExtensionLet q d = Telescope $ \n => (Qty q, BindName, LocalVar q d n)
public export
CtxExtensionLet0 : Nat -> Nat -> Nat -> Type
CtxExtensionLet0 d = Telescope ((BindName,) . LocalVar d)
CtxExtensionLet0 : (q, d, n1, n2 : Nat) -> Type
CtxExtensionLet0 q d = Telescope $ \n => (BindName, LocalVar q d n)
namespace TyContext
public export %inline
empty : TyContext 0 0
empty : TyContext 0 0 0
empty = MkTyContext {
dctx = new, dnames = [<], tctx = [<], tnames = [<], qtys = [<]
qnames = [<], dctx = new, dnames = [<], tctx = [<], tnames = [<], qtys = [<]
}
public export %inline
null : TyContext d n -> Bool
null ctx = null ctx.dnames && null ctx.tnames
null : TyContext q d n -> Bool
null ctx = null ctx.qnames && null ctx.dnames && null ctx.tnames
export %inline
extendTyLetN : CtxExtensionLet d n1 n2 -> TyContext d n1 -> TyContext d n2
extendTyLetN xss (MkTyContext {termLen, dctx, dnames, tctx, tnames, qtys}) =
extendTyLetN : CtxExtensionLet q d n1 n2 ->
TyContext q d n1 -> TyContext q d n2
extendTyLetN xss
(MkTyContext {termLen, qnames, dctx, dnames, tctx, tnames, qtys}) =
let (qs, xs, ls) = unzip3 xss in
MkTyContext {
dctx, dnames,
qnames, dctx, dnames,
termLen = extendLen xss termLen,
tctx = tctx . ls,
tnames = tnames . xs,
@ -149,63 +169,78 @@ namespace TyContext
}
export %inline
extendTyN : CtxExtension d n1 n2 -> TyContext d n1 -> TyContext d n2
extendTyN : CtxExtension q d n1 n2 -> TyContext q d n1 -> TyContext q d n2
extendTyN = extendTyLetN . map (\(q, x, s) => (q, x, lamVar s))
export %inline
extendTyLetN0 : CtxExtensionLet0 d n1 n2 -> TyContext d n1 -> TyContext d n2
extendTyLetN0 xss = extendTyLetN (map (Zero,) xss)
extendTyLetN0 : CtxExtensionLet0 q d n1 n2 ->
TyContext q d n1 -> TyContext q d n2
extendTyLetN0 xss ctx =
let Val q = ctx.qtyLen in
extendTyLetN (map (\(x, t) => (zero x.loc, x, t)) xss) ctx
export %inline
extendTyN0 : CtxExtension0 d n1 n2 -> TyContext d n1 -> TyContext d n2
extendTyN0 xss = extendTyN (map (Zero,) xss)
extendTyN0 : CtxExtension0 q d n1 n2 ->
TyContext q d n1 -> TyContext q d n2
extendTyN0 xss ctx =
let Val q = ctx.qtyLen in
extendTyN (map (\(x, t) => (zero x.loc, x, t)) xss) ctx
export %inline
extendTyLet : Qty -> BindName -> Term d n -> Term d n ->
TyContext d n -> TyContext d (S n)
extendTyLet : Qty q -> BindName -> Term q d n -> Term q d n ->
TyContext q d n -> TyContext q d (S n)
extendTyLet q x s e = extendTyLetN [< (q, x, letVar s e)]
export %inline
extendTy : Qty -> BindName -> Term d n -> TyContext d n -> TyContext d (S n)
extendTy : Qty q -> BindName -> Term q d n ->
TyContext q d n -> TyContext q d (S n)
extendTy q x s = extendTyN [< (q, x, s)]
export %inline
extendTy0 : BindName -> Term d n -> TyContext d n -> TyContext d (S n)
extendTy0 = extendTy Zero
extendTy0 : BindName -> Term q d n ->
TyContext q d n -> TyContext q d (S n)
extendTy0 x t ctx = let Val q = ctx.qtyLen in extendTy (zero x.loc) x t ctx
export %inline
extendDim : BindName -> TyContext d n -> TyContext (S d) n
extendDim x (MkTyContext {dimLen, dctx, dnames, tctx, tnames, qtys}) =
extendDim : BindName -> TyContext q d n -> TyContext q (S d) n
extendDim x (MkTyContext {dimLen, dctx, dnames, qnames, tctx, tnames, qtys}) =
MkTyContext {
dctx = dctx :<? Nothing,
dnames = dnames :< x,
dimLen = [|S dimLen|],
tctx = map weakD tctx,
tnames, qtys
qnames, tnames, qtys
}
export %inline
eqDim : Dim d -> Dim d -> TyContext d n -> TyContext d n
eqDim p q = {dctx $= set p q, dimLen $= id, termLen $= id}
eqDim : Dim d -> Dim d -> TyContext q d n -> TyContext q d n
eqDim p q = {dctx $= set p q}
export
toWhnfContext : TyContext d n -> WhnfContext d n
toWhnfContext (MkTyContext {dnames, tnames, tctx, _}) =
MkWhnfContext {dnames, tnames, tctx}
toWhnfContext : TyContext q d n -> WhnfContext q d n
toWhnfContext (MkTyContext {qnames, dnames, tnames, tctx, _}) =
MkWhnfContext {qnames, dnames, tnames, tctx}
public export
(.names) : TyContext q d n -> NameContexts q d n
(MkTyContext {qnames, dnames, tnames, _}).names =
MkNameContexts {qnames, dnames, tnames}
namespace QOutput
export %inline
(+) : QOutput n -> QOutput n -> QOutput n
(+) : QOutput q n -> QOutput q n -> QOutput q n
(+) = zipWith (+)
export %inline
(*) : Qty -> QOutput n -> QOutput n
(*) : Qty q -> QOutput q n -> QOutput q n
(*) pi = map (pi *)
export %inline
zeroFor : TyContext _ n -> QOutput n
zeroFor ctx = zeroFor ctx.tctx
zeroFor : TyContext q _ n -> QOutput q n
zeroFor ctx =
let Val q = ctx.qtyLen in
zeroFor ctx.tctx @{LocateVarType}
export
@ -214,8 +249,10 @@ makeDAssign (Shift SZ) = [<]
makeDAssign (K e _ ::: th) = makeDAssign th :< e
export
makeEqContext' : {d : Nat} -> TyContext d n -> DSubst d 0 -> EqContext n
makeEqContext' : {d : Nat} -> TyContext q d n -> DSubst d 0 -> EqContext q n
makeEqContext' ctx th = MkEqContext {
qtyLen = ctx.qtyLen,
qnames = ctx.qnames,
termLen = ctx.termLen,
dassign = makeDAssign th,
dnames = ctx.dnames,
@ -225,134 +262,160 @@ makeEqContext' ctx th = MkEqContext {
}
export
makeEqContext : TyContext d n -> DSubst d 0 -> EqContext n
makeEqContext : TyContext q d n -> DSubst d 0 -> EqContext q n
makeEqContext ctx@(MkTyContext {dnames, _}) th =
let Val d = lengthPrf0 dnames in makeEqContext' ctx th
namespace EqContext
public export %inline
empty : EqContext 0
empty : EqContext 0 0
empty = MkEqContext {
dassign = [<], dnames = [<], tctx = [<], tnames = [<], qtys = [<]
qnames = [<], dassign = [<], dnames = [<],
tctx = [<], tnames = [<], qtys = [<]
}
public export %inline
null : EqContext n -> Bool
null ctx = null ctx.dnames && null ctx.tnames
null : EqContext q n -> Bool
null ctx = null ctx.qnames && null ctx.dnames && null ctx.tnames
export %inline
extendTyLetN : CtxExtensionLet 0 n1 n2 -> EqContext n1 -> EqContext n2
extendTyLetN xss (MkEqContext {termLen, dassign, dnames, tctx, tnames, qtys}) =
extendTyLetN : CtxExtensionLet q 0 n1 n2 -> EqContext q n1 -> EqContext q n2
extendTyLetN xss
(MkEqContext {termLen, qnames, dassign, dnames, tctx, tnames, qtys}) =
let (qs, xs, ls) = unzip3 xss in
MkEqContext {
termLen = extendLen xss termLen,
tctx = tctx . ls,
tnames = tnames . xs,
qtys = qtys . qs,
dassign, dnames
dassign, dnames, qnames
}
export %inline
extendTyN : CtxExtension 0 n1 n2 -> EqContext n1 -> EqContext n2
extendTyN : CtxExtension q 0 n1 n2 -> EqContext q n1 -> EqContext q n2
extendTyN = extendTyLetN . map (\(q, x, s) => (q, x, lamVar s))
export %inline
extendTyLetN0 : CtxExtensionLet0 0 n1 n2 -> EqContext n1 -> EqContext n2
extendTyLetN0 xss = extendTyLetN (map (Zero,) xss)
extendTyLetN0 : CtxExtensionLet0 q 0 n1 n2 -> EqContext q n1 -> EqContext q n2
extendTyLetN0 xss ctx =
let Val q = ctx.qtyLen in
extendTyLetN (map (\(x, t) => (zero x.loc, x, t)) xss) ctx
export %inline
extendTyN0 : CtxExtension0 0 n1 n2 -> EqContext n1 -> EqContext n2
extendTyN0 xss = extendTyN (map (Zero,) xss)
extendTyN0 : CtxExtension0 q 0 n1 n2 -> EqContext q n1 -> EqContext q n2
extendTyN0 xss ctx =
let Val q = ctx.qtyLen in
extendTyN (map (\(x, t) => (zero x.loc, x, t)) xss) ctx
export %inline
extendTyLet : Qty -> BindName -> Term 0 n -> Term 0 n ->
EqContext n -> EqContext (S n)
extendTyLet : Qty q -> BindName -> Term q 0 n -> Term q 0 n ->
EqContext q n -> EqContext q (S n)
extendTyLet q x s e = extendTyLetN [< (q, x, letVar s e)]
export %inline
extendTy : Qty -> BindName -> Term 0 n -> EqContext n -> EqContext (S n)
extendTy : Qty q -> BindName -> Term q 0 n ->
EqContext q n -> EqContext q (S n)
extendTy q x s = extendTyN [< (q, x, s)]
export %inline
extendTy0 : BindName -> Term 0 n -> EqContext n -> EqContext (S n)
extendTy0 = extendTy Zero
extendTy0 : BindName -> Term q 0 n -> EqContext q n -> EqContext q (S n)
extendTy0 x t ctx = let Val q = ctx.qtyLen in extendTy (zero x.loc) x t ctx
export %inline
extendDim : BindName -> DimConst -> EqContext n -> EqContext n
extendDim x e (MkEqContext {dassign, dnames, tctx, tnames, qtys}) =
extendDim : BindName -> DimConst -> EqContext q n -> EqContext q n
extendDim x e (MkEqContext {dassign, dnames, qnames, tctx, tnames, qtys}) =
MkEqContext {dassign = dassign :< e, dnames = dnames :< x,
tctx, tnames, qtys}
qnames, tctx, tnames, qtys}
export
toTyContext : (e : EqContext n) -> TyContext e.dimLen n
toTyContext (MkEqContext {dimLen, dassign, dnames, tctx, tnames, qtys}) =
toTyContext : (e : EqContext q n) -> TyContext q e.dimLen n
toTyContext
(MkEqContext {dimLen, dassign, dnames, qnames, tctx, tnames, qtys}) =
MkTyContext {
dctx = fromGround dnames dassign,
tctx = map (subD $ shift0 dimLen) tctx,
dnames, tnames, qtys
dnames, qnames, tnames, qtys
}
export
toWhnfContext : (ectx : EqContext n) -> WhnfContext 0 n
toWhnfContext (MkEqContext {tnames, tctx, _}) =
MkWhnfContext {dnames = [<], tnames, tctx}
toWhnfContext : (ectx : EqContext q n) -> WhnfContext q 0 n
toWhnfContext (MkEqContext {qnames, tnames, tctx, _}) =
MkWhnfContext {dnames = [<], qnames, tnames, tctx}
export
injElim : WhnfContext d n -> Elim 0 0 -> Elim d n
injElim : WhnfContext q d n -> Elim q 0 0 -> Elim q d n
injElim ctx e =
let Val d = ctx.dimLen; Val n = ctx.termLen in
e // shift0 d // shift0 n
public export
(.names) : (e : EqContext q n) -> NameContexts q e.dimLen n
(MkEqContext {qnames, dnames, tnames, _}).names =
MkNameContexts {qnames, dnames, tnames}
public export
(.names0) : EqContext q n -> NameContexts q 0 n
(MkEqContext {qnames, tnames, _}).names0 =
MkNameContexts {qnames, dnames = [<], tnames}
namespace WhnfContext
public export %inline
empty : WhnfContext 0 0
empty = MkWhnfContext [<] [<] [<]
empty : WhnfContext 0 0 0
empty = MkWhnfContext [<] [<] [<] [<]
export
extendTy' : BindName -> LocalVar d n -> WhnfContext d n -> WhnfContext d (S n)
extendTy' x var (MkWhnfContext {termLen, dnames, tnames, tctx}) =
extendTy' : BindName -> LocalVar q d n ->
WhnfContext q d n -> WhnfContext q d (S n)
extendTy' x var (MkWhnfContext {termLen, qnames, dnames, tnames, tctx}) =
MkWhnfContext {
dnames,
dnames, qnames,
termLen = [|S termLen|],
tnames = tnames :< x,
tctx = tctx :< var
}
export %inline
extendTy : BindName -> Term d n -> WhnfContext d n -> WhnfContext d (S n)
extendTy : BindName -> Term q d n ->
WhnfContext q d n -> WhnfContext q d (S n)
extendTy x ty ctx = extendTy' x (lamVar ty) ctx
export %inline
extendTyLet : BindName -> (type, term : Term d n) ->
WhnfContext d n -> WhnfContext d (S n)
extendTyLet : BindName -> (type, term : Term q d n) ->
WhnfContext q d n -> WhnfContext q d (S n)
extendTyLet x type term ctx = extendTy' x (letVar {type, term}) ctx
export
extendDimN : {s : Nat} -> BContext s -> WhnfContext d n ->
WhnfContext (s + d) n
extendDimN ns (MkWhnfContext {dnames, tnames, tctx, dimLen}) =
extendDimN : {s : Nat} -> BContext s -> WhnfContext q d n ->
WhnfContext q (s + d) n
extendDimN ns (MkWhnfContext {qnames, dnames, tnames, tctx, dimLen}) =
MkWhnfContext {
dimLen = [|Val s + dimLen|],
dnames = dnames ++ toSnocVect' ns,
tctx = map (subD $ shift s) tctx,
tnames
qnames, tnames
}
export
extendDim : BindName -> WhnfContext d n -> WhnfContext (S d) n
extendDim : BindName -> WhnfContext q d n -> WhnfContext q (S d) n
extendDim i = extendDimN [< i]
public export
(.names) : WhnfContext q d n -> NameContexts q d n
(MkWhnfContext {qnames, dnames, tnames, _}).names =
MkNameContexts {qnames, dnames, tnames}
private
prettyTContextElt : {opts : _} ->
BContext d -> BContext n ->
Doc opts -> BindName -> LocalVar d n ->
NameContexts q d n ->
Doc opts -> BindName -> LocalVar q d n ->
Eff Pretty (Doc opts)
prettyTContextElt dnames tnames q x s = do
prettyTContextElt names q x s = do
let Val _ = lengthPrf0 names.qnames
dot <- dotD
x <- prettyTBind x; colon <- colonD
ty <- withPrec Outer $ prettyTerm dnames tnames s.type; eq <- cstD
tm <- traverse (withPrec Outer . prettyTerm dnames tnames) s.term
ty <- withPrec Outer $ prettyTerm names s.type; eq <- cstD
tm <- traverse (withPrec Outer . prettyTerm names) s.term
d <- askAt INDENT
let qx = hcat [q, dot, x]
pure $ case tm of
@ -364,39 +427,37 @@ prettyTContextElt dnames tnames q x s = do
private
prettyTContext' : {opts : _} ->
BContext d -> Context' (Doc opts) n -> BContext n ->
TContext d n -> Eff Pretty (SnocList (Doc opts))
prettyTContext' _ [<] [<] [<] = pure [<]
prettyTContext' dnames (qtys :< q) (tnames :< x) (tys :< t) =
[|prettyTContext' dnames qtys tnames tys :<
prettyTContextElt dnames tnames q x t|]
NameContexts q d n -> Context' (Doc opts) n ->
TContext q d n -> Eff Pretty (SnocList (Doc opts))
prettyTContext' _ [<] [<] = pure [<]
prettyTContext' names (qtys :< q) (tys :< t) =
let names' = {tnames $= tail, termLen $= map pred} names in
[|prettyTContext' names' qtys tys :<
prettyTContextElt names' q (head names.tnames) t|]
export
prettyTContext : {opts : _} ->
BContext d -> QContext n -> BContext n ->
TContext d n -> Eff Pretty (Doc opts)
prettyTContext dnames qtys tnames tys = do
comma <- commaD
qtys <- traverse prettyQty qtys
sepSingle . exceptLast (<+> comma) . toList <$>
prettyTContext' dnames qtys tnames tys
NameContexts q d n -> QContext q n ->
TContext q d n -> Eff Pretty (Doc opts)
prettyTContext names qtys tys = do
qtys <- traverse (prettyQty names.qnames) qtys
sepSingleTight !commaD . toList <$> prettyTContext' names qtys tys
export
prettyTyContext : {opts : _} -> TyContext d n -> Eff Pretty (Doc opts)
prettyTyContext (MkTyContext dctx dnames tctx tnames qtys) =
case dctx of
C [<] => prettyTContext dnames qtys tnames tctx
prettyTyContext : {opts : _} -> TyContext q d n -> Eff Pretty (Doc opts)
prettyTyContext ctx = case ctx.dctx of
C [<] => prettyTContext ctx.names ctx.qtys ctx.tctx
_ => pure $
sepSingle [!(prettyDimEq dnames dctx) <++> !pipeD,
!(prettyTContext dnames qtys tnames tctx)]
sepSingle [!(prettyDimEq ctx.dnames ctx.dctx) <++> !pipeD,
!(prettyTContext ctx.names ctx.qtys ctx.tctx)]
export
prettyEqContext : {opts : _} -> EqContext n -> Eff Pretty (Doc opts)
prettyEqContext : {opts : _} -> EqContext q n -> Eff Pretty (Doc opts)
prettyEqContext ctx = prettyTyContext $ toTyContext ctx
export
prettyWhnfContext : {opts : _} -> WhnfContext d n -> Eff Pretty (Doc opts)
prettyWhnfContext : {opts : _} -> WhnfContext q d n -> Eff Pretty (Doc opts)
prettyWhnfContext ctx =
let Val n = ctx.termLen in
sepSingle . exceptLast (<+> comma) . toList <$>
prettyTContext' ctx.dnames (replicate n "_") ctx.tnames ctx.tctx
sepSingleTight !commaD . toList <$>
prettyTContext' ctx.names (replicate n "_") ctx.tctx

View file

@ -17,108 +17,64 @@ import Derive.Prelude
%default total
public export
record NameContexts d n where
constructor MkNameContexts
dnames : BContext d
tnames : BContext n
%runElab deriveIndexed "NameContexts" [Show]
namespace NameContexts
export
empty : NameContexts 0 0
empty = MkNameContexts [<] [<]
export
extendDimN : BContext s -> NameContexts d n -> NameContexts (s + d) n
extendDimN xs = {dnames $= (++ toSnocVect' xs)}
export
extendDim : BindName -> NameContexts d n -> NameContexts (S d) n
extendDim i = extendDimN [< i]
namespace TyContext
public export
(.names) : TyContext d n -> NameContexts d n
(MkTyContext {dnames, tnames, _}).names =
MkNameContexts {dnames, tnames}
namespace EqContext
public export
(.names) : (e : EqContext n) -> NameContexts e.dimLen n
(MkEqContext {dnames, tnames, _}).names =
MkNameContexts {dnames, tnames}
public export
(.names0) : EqContext n -> NameContexts 0 n
(MkEqContext {tnames, _}).names0 =
MkNameContexts {dnames = [<], tnames}
namespace WhnfContext
public export
(.names) : WhnfContext d n -> NameContexts d n
(MkWhnfContext {dnames, tnames, _}).names =
MkNameContexts {dnames, tnames}
public export
data Error
= ExpectedTYPE Loc (NameContexts d n) (Term d n)
| ExpectedPi Loc (NameContexts d n) (Term d n)
| ExpectedSig Loc (NameContexts d n) (Term d n)
| ExpectedEnum Loc (NameContexts d n) (Term d n)
| ExpectedEq Loc (NameContexts d n) (Term d n)
| ExpectedNAT Loc (NameContexts d n) (Term d n)
| ExpectedSTRING Loc (NameContexts d n) (Term d n)
| ExpectedBOX Loc (NameContexts d n) (Term d n)
| ExpectedIOState Loc (NameContexts d n) (Term d n)
= ExpectedTYPE Loc (NameContexts q d n) (Term q d n)
| ExpectedPi Loc (NameContexts q d n) (Term q d n)
| ExpectedSig Loc (NameContexts q d n) (Term q d n)
| ExpectedEnum Loc (NameContexts q d n) (Term q d n)
| ExpectedEq Loc (NameContexts q d n) (Term q d n)
| ExpectedNAT Loc (NameContexts q d n) (Term q d n)
| ExpectedSTRING Loc (NameContexts q d n) (Term q d n)
| ExpectedBOX Loc (NameContexts q d n) (Term q d n)
| ExpectedIOState Loc (NameContexts q d n) (Term q d n)
| BadUniverse Loc Universe Universe
| TagNotIn Loc TagVal (SortedSet TagVal)
| BadCaseEnum Loc (SortedSet TagVal) (SortedSet TagVal)
| BadQtys Loc String (TyContext d n) (List (QOutput n, Term d n))
| BadQtys Loc String (TyContext q d n) (List (QOutput q n, Term q d n))
-- first term arg of ClashT is the type
| ClashT Loc (EqContext n) EqMode (Term 0 n) (Term 0 n) (Term 0 n)
| ClashTy Loc (EqContext n) EqMode (Term 0 n) (Term 0 n)
| ClashE Loc (EqContext n) EqMode (Elim 0 n) (Elim 0 n)
| ClashT Loc (EqContext q n) EqMode (Term q 0 n) (Term q 0 n) (Term q 0 n)
| ClashTy Loc (EqContext q n) EqMode (Term q 0 n) (Term q 0 n)
| ClashE Loc (EqContext q n) EqMode (Elim q 0 n) (Elim q 0 n)
| ClashU Loc EqMode Universe Universe
| ClashQ Loc Qty Qty
| ClashQ Loc (BContext q) (Qty q) (Qty q)
| NotInScope Loc Name
| NotType Loc (TyContext d n) (Term d n)
| WrongType Loc (EqContext n) (Term 0 n) (Term 0 n)
| NotType Loc (TyContext q d n) (Term q d n)
| WrongType Loc (EqContext q n) (Term q 0 n) (Term q 0 n)
| WrongBuiltinType Builtin Error
| ExpectedSingleEnum Loc (NameContexts d n) (Term d n)
| ExpectedSingleEnum Loc (NameContexts q d n) (Term q d n)
| MissingEnumArm Loc TagVal (List TagVal)
-- extra context
| WhileChecking
(TyContext d n) SQty
(Term d n) -- term
(Term d n) -- type
(TyContext q d n) SQty
(Term q d n) -- term
(Term q d n) -- type
Error
| WhileCheckingTy
(TyContext d n)
(Term d n)
(TyContext q d n)
(Term q d n)
(Maybe Universe)
Error
| WhileInferring
(TyContext d n) SQty
(Elim d n)
(TyContext q d n) SQty
(Elim q d n)
Error
| WhileComparingT
(EqContext n) EqMode SQty
(Term 0 n) -- type
(Term 0 n) (Term 0 n) -- lhs/rhs
(EqContext q n) EqMode SQty
(Term q 0 n) -- type
(Term q 0 n) (Term q 0 n) -- lhs/rhs
Error
| WhileComparingE
(EqContext n) EqMode SQty
(Elim 0 n) (Elim 0 n)
(EqContext q n) EqMode SQty
(Elim q 0 n) (Elim q 0 n)
Error
%name Error err
%runElab derive "Error" [Show]
-- %runElab derive "Error" [Show]
public export
ErrorEff : Type -> Type
@ -144,7 +100,7 @@ Located Error where
(ClashTy loc _ _ _ _).loc = loc
(ClashE loc _ _ _ _).loc = loc
(ClashU loc _ _ _).loc = loc
(ClashQ loc _ _).loc = loc
(ClashQ loc _ _ _).loc = loc
(NotInScope loc _).loc = loc
(NotType loc _ _).loc = loc
(WrongType loc _ _ _).loc = loc
@ -192,14 +148,15 @@ expect : Has (Except e) fs =>
(a -> a -> e) -> (a -> a -> Bool) -> a -> a -> Eff fs ()
expect err cmp x y = unless (x `cmp` y) $ throw $ err x y
parameters {auto _ : Has ErrorEff fs} (loc : Loc)
parameters {auto _ : Has ErrorEff fs} (loc : Loc) (ctx : BContext q)
export %inline
expectEqualQ : Qty -> Qty -> Eff fs ()
expectEqualQ = expect (ClashQ loc) (==)
expectEqualQ : Qty q -> Qty q -> Eff fs ()
expectEqualQ = expect (ClashQ loc ctx) (==)
-- [fixme] probably replace (==)
export %inline
expectCompatQ : Qty -> Qty -> Eff fs ()
expectCompatQ = expect (ClashQ loc) compat
expectCompatQ : Qty q -> Qty q -> Eff fs ()
expectCompatQ = expect (ClashQ loc ctx) compat
export %inline
expectModeU : EqMode -> Universe -> Universe -> Eff fs ()
@ -225,8 +182,8 @@ isTypeInUniverse (Just k) = "is a type in universe \{show k}"
private
filterSameQtys : BContext n -> List (QOutput n, z) ->
Exists $ \n' => (BContext n', List (QOutput n', z))
filterSameQtys : BContext n -> List (QOutput q n, z) ->
Exists $ \n' => (BContext n', List (QOutput q n', z))
filterSameQtys [<] qts = Evidence 0 ([<], qts)
filterSameQtys (ns :< n) qts =
let (qs, qts) = unzip $ map (\(qs :< q, t) => (q, qs, t)) qts
@ -236,27 +193,29 @@ filterSameQtys (ns :< n) qts =
then Evidence l (ns, qts)
else Evidence (S l) (ns :< n, zipWith (\(qs, t), q => (qs :< q, t)) qts qs)
where
allSame : List Qty -> Bool
allSame : List (Qty q) -> Bool
allSame [] = True
allSame (q :: qs) = all (== q) qs
private
printCaseQtys : {opts : _} -> TyContext d n ->
BContext n' -> List (QOutput n', Term d n) ->
printCaseQtys : {opts : _} -> TyContext q d n ->
BContext n' -> List (QOutput q n', Term q d n) ->
Eff Pretty (List (Doc opts))
printCaseQtys ctx ns qts =
let Evidence _ (ns, qts) = filterSameQtys ns qts in
traverse (line ns) qts
where
line : BContext l -> (QOutput l, Term d n) -> Eff Pretty (Doc opts)
line ns (qs, t) = map (("-" <++>) . sep) $ sequence
line : BContext l -> (QOutput q l, Term q d n) -> Eff Pretty (Doc opts)
line ns (qs, t) =
let Val q = ctx.qtyLen; names = ctx.names in
map (("-" <++>) . sep) $ sequence
[hangDSingle "the term"
!(prettyTerm ctx.dnames ctx.tnames t),
!(prettyTerm names t),
hangDSingle "uses variables" $
separateTight !commaD $ toSnocList' !(traverse prettyTBind ns),
hangDSingle "with quantities" $
separateTight !commaD $ toSnocList' !(traverse prettyQty qs)]
separateTight !commaD $ toSnocList' !(traverse (prettyQty names) qs)]
parameters {opts : LayoutOpts} (showContext : Bool)
export
@ -268,11 +227,11 @@ parameters {opts : LayoutOpts} (showContext : Bool)
else pure doc
export %inline
inTContext : TyContext d n -> Doc opts -> Eff Pretty (Doc opts)
inTContext : TyContext q d n -> Doc opts -> Eff Pretty (Doc opts)
inTContext ctx = inContext' (null ctx) ctx prettyTyContext
export %inline
inEContext : EqContext n -> Doc opts -> Eff Pretty (Doc opts)
inEContext : EqContext q n -> Doc opts -> Eff Pretty (Doc opts)
inEContext ctx = inContext' (null ctx) ctx prettyEqContext
export
@ -280,43 +239,43 @@ parameters {opts : LayoutOpts} (showContext : Bool)
prettyErrorNoLoc err0 = case err0 of
ExpectedTYPE _ ctx s =>
hangDSingle "expected a type universe, but got"
!(prettyTerm ctx.dnames ctx.tnames s)
!(prettyTerm ctx s)
ExpectedPi _ ctx s =>
hangDSingle "expected a function type, but got"
!(prettyTerm ctx.dnames ctx.tnames s)
!(prettyTerm ctx s)
ExpectedSig _ ctx s =>
hangDSingle "expected a pair type, but got"
!(prettyTerm ctx.dnames ctx.tnames s)
!(prettyTerm ctx s)
ExpectedEnum _ ctx s =>
hangDSingle "expected an enumeration type, but got"
!(prettyTerm ctx.dnames ctx.tnames s)
!(prettyTerm ctx s)
ExpectedEq _ ctx s =>
hangDSingle "expected an equality type, but got"
!(prettyTerm ctx.dnames ctx.tnames s)
!(prettyTerm ctx s)
ExpectedNAT _ ctx s =>
hangDSingle
("expected the type" <++>
!(prettyTerm [<] [<] $ NAT noLoc) <+> ", but got")
!(prettyTerm ctx.dnames ctx.tnames s)
!(prettyTerm ctx $ NAT noLoc) <+> ", but got")
!(prettyTerm ctx s)
ExpectedSTRING _ ctx s =>
hangDSingle
("expected the type" <++>
!(prettyTerm [<] [<] $ STRING noLoc) <+> ", but got")
!(prettyTerm ctx.dnames ctx.tnames s)
!(prettyTerm ctx $ STRING noLoc) <+> ", but got")
!(prettyTerm ctx s)
ExpectedBOX _ ctx s =>
hangDSingle "expected a box type, but got"
!(prettyTerm ctx.dnames ctx.tnames s)
!(prettyTerm ctx s)
ExpectedIOState _ ctx s =>
hangDSingle "expected IOState, but got"
!(prettyTerm ctx.dnames ctx.tnames s)
!(prettyTerm ctx s)
BadUniverse _ k l => pure $
sep ["the universe level" <++> !(prettyUniverse k),
@ -324,57 +283,58 @@ parameters {opts : LayoutOpts} (showContext : Bool)
TagNotIn _ tag set =>
hangDSingle (hsep ["the tag", !(prettyTag tag), "is not contained in"])
!(prettyTerm [<] [<] $ Enum set noLoc)
!(prettyTerm empty $ Enum set noLoc)
BadCaseEnum _ head body => sep <$> sequence
[hangDSingle "case expression has head of type"
!(prettyTerm [<] [<] $ Enum head noLoc),
!(prettyTerm empty $ Enum head noLoc),
hangDSingle "but cases for"
!(prettyTerm [<] [<] $ Enum body noLoc)]
!(prettyTerm empty $ Enum body noLoc)]
BadQtys _ what ctx arms =>
hangDSingle (text "inconsistent variable usage in \{what}") $
sep !(printCaseQtys ctx ctx.tnames arms)
ClashT _ ctx mode ty s t =>
let names = ctx.names0 in
inEContext ctx . sep =<< sequence
[hangDSingle "the term" !(prettyTerm [<] ctx.tnames s),
hangDSingle (text "is not \{prettyMode mode}")
!(prettyTerm [<] ctx.tnames t),
hangDSingle "at type" !(prettyTerm [<] ctx.tnames ty)]
[hangDSingle "the term" !(prettyTerm names s),
hangDSingle (text "is not \{prettyMode mode}") !(prettyTerm names t),
hangDSingle "at type" !(prettyTerm names ty)]
ClashTy _ ctx mode a b =>
let names = ctx.names0 in
inEContext ctx . sep =<< sequence
[hangDSingle "the type" !(prettyTerm [<] ctx.tnames a),
hangDSingle (text "is not \{prettyMode mode}")
!(prettyTerm [<] ctx.tnames b)]
[hangDSingle "the type" !(prettyTerm names a),
hangDSingle (text "is not \{prettyMode mode}") !(prettyTerm names b)]
ClashE _ ctx mode e f =>
let names = ctx.names0 in
inEContext ctx . sep =<< sequence
[hangDSingle "the term" !(prettyElim [<] ctx.tnames e),
hangDSingle (text "is not \{prettyMode mode}")
!(prettyElim [<] ctx.tnames f)]
[hangDSingle "the term" !(prettyElim names e),
hangDSingle (text "is not \{prettyMode mode}") !(prettyElim names f)]
ClashU _ mode k l => pure $
sep ["the universe level" <++> !(prettyUniverse k),
text "is not \{prettyModeU mode}" <++> !(prettyUniverse l)]
ClashQ _ pi rh => pure $
sep ["the quantity" <++> !(prettyQty pi),
"is not equal to" <++> !(prettyQty rh)]
ClashQ _ ctx pi rh => pure $
sep ["the quantity" <++> !(prettyQty ctx pi),
"is not equal to" <++> !(prettyQty ctx rh)]
NotInScope _ x => pure $
hsep [!(prettyFree x), "is not in scope"]
NotType _ ctx s =>
inTContext ctx . sep =<< sequence
[hangDSingle "the term" !(prettyTerm ctx.dnames ctx.tnames s),
[hangDSingle "the term" !(prettyTerm ctx.names s),
pure "is not a type"]
WrongType _ ctx ty s =>
let names = ctx.names0 in
inEContext ctx . sep =<< sequence
[hangDSingle "the term" !(prettyTerm [<] ctx.tnames s),
hangDSingle "cannot have type" !(prettyTerm [<] ctx.tnames ty)]
[hangDSingle "the term" !(prettyTerm names s),
hangDSingle "cannot have type" !(prettyTerm names ty)]
WrongBuiltinType b err => pure $
vappend
@ -384,24 +344,25 @@ parameters {opts : LayoutOpts} (showContext : Bool)
ExpectedSingleEnum _ ctx s =>
hangDSingle "expected an enumeration type with one case, but got"
!(prettyTerm ctx.dnames ctx.tnames s)
!(prettyTerm ctx s)
MissingEnumArm _ tag tags => pure $
sep [hsep ["the tag", !(prettyTag tag), "is not contained in"],
!(prettyTerm [<] [<] $ Enum (fromList tags) noLoc)]
!(prettyTerm empty $ Enum (fromList tags) noLoc)]
WhileChecking ctx sg s a err =>
let names = ctx.names in
[|vappendBlank
(inTContext ctx . sep =<< sequence
[hangDSingle "while checking" !(prettyTerm ctx.dnames ctx.tnames s),
hangDSingle "has type" !(prettyTerm ctx.dnames ctx.tnames a),
hangDSingle "with quantity" !(prettyQty sg.qty)])
[hangDSingle "while checking" !(prettyTerm names s),
hangDSingle "has type" !(prettyTerm names a),
hangDSingle "with quantity" !(prettyQConst sg.qconst)])
(prettyErrorNoLoc err)|]
WhileCheckingTy ctx a k err =>
[|vappendBlank
(inTContext ctx . sep =<< sequence
[hangDSingle "while checking" !(prettyTerm ctx.dnames ctx.tnames a),
[hangDSingle "while checking" !(prettyTerm ctx.names a),
pure $ text $ isTypeInUniverse k])
(prettyErrorNoLoc err)|]
@ -409,27 +370,27 @@ parameters {opts : LayoutOpts} (showContext : Bool)
[|vappendBlank
(inTContext ctx . sep =<< sequence
[hangDSingle "while inferring the type of"
!(prettyElim ctx.dnames ctx.tnames e),
hangDSingle "with quantity" !(prettyQty sg.qty)])
!(prettyElim ctx.names e),
hangDSingle "with quantity" !(prettyQConst sg.qconst)])
(prettyErrorNoLoc err)|]
WhileComparingT ctx mode sg a s t err =>
let names = ctx.names0 in
[|vappendBlank
(inEContext ctx . sep =<< sequence
[hangDSingle "while checking that" !(prettyTerm [<] ctx.tnames s),
hangDSingle (text "is \{prettyMode mode}")
!(prettyTerm [<] ctx.tnames t),
hangDSingle "at type" !(prettyTerm [<] ctx.tnames a),
hangDSingle "with quantity" !(prettyQty sg.qty)])
[hangDSingle "while checking that" !(prettyTerm names s),
hangDSingle (text "is \{prettyMode mode}") !(prettyTerm names t),
hangDSingle "at type" !(prettyTerm names a),
hangDSingle "with quantity" !(prettyQConst sg.qconst)])
(prettyErrorNoLoc err)|]
WhileComparingE ctx mode sg e f err =>
let names = ctx.names0 in
[|vappendBlank
(inEContext ctx . sep =<< sequence
[hangDSingle "while checking that" !(prettyElim [<] ctx.tnames e),
hangDSingle (text "is \{prettyMode mode}")
!(prettyElim [<] ctx.tnames f),
hangDSingle "with quantity" !(prettyQty sg.qty)])
[hangDSingle "while checking that" !(prettyElim names e),
hangDSingle (text "is \{prettyMode mode}") !(prettyElim names f),
hangDSingle "with quantity" !(prettyQConst sg.qconst)])
(prettyErrorNoLoc err)|]
where

View file

@ -255,49 +255,66 @@ USubst : Nat -> Nat -> Type
USubst = Subst Term
public export FromVar Term where fromVarLoc = B
public export %inline
FromVarR Term where fromVarR = B
public export %inline
FromVar Term where fromVar = B; fromVarSame _ _ = Refl
public export
CanSubstSelf Term where
s // th = case s of
export
CanSubstSelf Term
substTerm : Term from -> Lazy (USubst from to) -> Term to
substTerm s th = case s of
F x loc =>
F x loc
B i loc =>
getLoc th i loc
get th i loc
Lam x body loc =>
Lam x (assert_total $ body // push x.loc th) loc
Lam x (assert_total substTerm body $ push x.loc th) loc
App fun arg loc =>
App (fun // th) (arg // th) loc
App (substTerm fun th) (substTerm arg th) loc
Pair fst snd loc =>
Pair (fst // th) (snd // th) loc
Pair (substTerm fst th) (substTerm snd th) loc
Fst pair loc =>
Fst (pair // th) loc
Fst (substTerm pair th) loc
Snd pair loc =>
Snd (pair // th) loc
Snd (substTerm pair th) loc
Tag tag loc =>
Tag tag loc
CaseEnum tag cases loc =>
CaseEnum (tag // th) (map (assert_total mapSnd (// th)) cases) loc
CaseEnum (substTerm tag th)
(map (mapSnd (\b => assert_total substTerm b th)) cases) loc
Absurd loc =>
Absurd loc
Nat n loc =>
Nat n loc
Succ nat loc =>
Succ (nat // th) loc
Succ (substTerm nat th) loc
CaseNat nat zer suc loc =>
CaseNat (nat // th) (zer // th) (assert_total substSuc suc th) loc
CaseNat (substTerm nat th)
(substTerm zer th)
(assert_total substSuc suc th) loc
Str s loc =>
Str s loc
Let u x rhs body loc =>
Let u x (rhs // th) (assert_total $ body // push x.loc th) loc
Let u x (substTerm rhs th)
(assert_total substTerm body $ push x.loc th) loc
Erased loc =>
Erased loc
where
substSuc : forall from, to.
CaseNatSuc from -> USubst from to -> CaseNatSuc to
substSuc (NSRec x ih t) th = NSRec x ih $ t // pushN 2 x.loc th
substSuc (NSNonrec x t) th = NSNonrec x $ t // push x.loc th
CaseNatSuc from -> Lazy (USubst from to) -> CaseNatSuc to
substSuc (NSRec x ih t) th = NSRec x ih $ substTerm t $ pushN 2 x.loc th
substSuc (NSNonrec x t) th = NSNonrec x $ substTerm t $ push x.loc th
export
CanSubstSelfR Term where (//?) = substTerm
export
CanSubstSelf Term where (//) = substTerm; substSame _ _ = Refl
public export
subN : SnocVect s (Term n) -> Term (s + n) -> Term n

View file

@ -138,21 +138,25 @@ export
weakIsSpec p i = toNatInj $ trans (weakCorrect p i) (sym $ weakSpecCorrect p i)
||| inject a variable (with a source location) into some kind of term. in this
||| case, the scope size may be needed at run time
public export
interface FromVar f where %inline fromVarLoc : Var n -> Loc -> f n
interface FromVarR f where
%inline fromVarR : {n : Nat} -> Var n -> Loc -> f n
||| inject a variable (with a source location) into some kind of term, without
||| needing the scope size
public export
interface FromVarR f => FromVar f where
%inline fromVar : Var n -> Loc -> f n
0 fromVarSame : (i : Var n) -> (l : Loc) -> fromVarR i l === fromVar i l
public export FromVar Var where fromVarLoc x _ = x
public export
FromVarR Var where fromVarR x _ = x
export
tabulateV : {0 tm : Nat -> Type} -> (forall n. Var n -> tm n) ->
(n : Nat) -> Vect n (tm n)
tabulateV f 0 = []
tabulateV f (S n) = f VZ :: tabulateV (f . VS) n
export
allVars : (n : Nat) -> Vect n (Var n)
allVars n = tabulateV id n
public export
FromVar Var where fromVar x _ = x; fromVarSame _ _ = Refl
public export

View file

@ -9,140 +9,147 @@ import Quox.Whnf.TypeCase
private
coeScoped : {s : Nat} -> DScopeTerm d n -> Dim d -> Dim d -> Loc ->
ScopeTermN s d n -> ScopeTermN s d n
coeScoped ty p q loc (S names (N body)) =
S names $ N $ E $ Coe ty p q body loc
coeScoped ty p q loc (S names (Y body)) =
ST names $ E $ Coe (weakDS s ty) p q body loc
coeScoped : {s, q : Nat} -> DScopeTerm q d n -> Dim d -> Dim d -> Loc ->
ScopeTermN s q d n -> ScopeTermN s q d n
coeScoped ty p p' loc (S names (N body)) =
S names $ N $ E $ Coe ty p p' body loc
coeScoped ty p p' loc (S names (Y body)) =
ST names $ E $ Coe (weakDS s ty) p p' body loc
where
weakDS : (by : Nat) -> DScopeTerm d n -> DScopeTerm d (by + n)
weakDS : (by : Nat) -> DScopeTerm q d n -> DScopeTerm q d (by + n)
weakDS by (S names (Y body)) = S names $ Y $ weakT by body
weakDS by (S names (N body)) = S names $ N $ weakT by body
parameters {auto _ : CanWhnf Term Interface.isRedexT}
{auto _ : CanWhnf Elim Interface.isRedexE}
(defs : Definitions) (ctx : WhnfContext d n) (sg : SQty)
||| reduce a function application `App (Coe ty p q val) s loc`
(defs : Definitions) (ctx : WhnfContext q d n) (sg : SQty)
||| reduce a function application `App (Coe ty p p' val) s loc`
export covering
piCoe : (ty : DScopeTerm d n) -> (p, q : Dim d) ->
(val, s : Term d n) -> Loc ->
Eff Whnf (Subset (Elim d n) (No . isRedexE defs ctx sg))
piCoe sty@(S [< i] ty) p q val s loc = do
-- (coe [i ⇒ π.(x : A) → B] @p @q t) s ⇝
-- coe [i ⇒ B[𝒔i/x] @p @q ((t ∷ (π.(x : A) → B)p/i) 𝒔p)
-- where 𝒔j ≔ coe [i ⇒ A] @q @j s
piCoe : (ty : DScopeTerm q d n) -> (p, p' : Dim d) ->
(val, s : Term q d n) -> Loc ->
Eff Whnf (Subset (Elim q d n) (No . isRedexE defs ctx sg))
piCoe sty@(S [< i] ty) p p' val s loc = do
-- (coe [i ⇒ π.(x : A) → B] @p @p' t) s ⇝
-- coe [i ⇒ B[𝒔i/x] @p @p' ((t ∷ (π.(x : A) → B)p/i) 𝒔p)
-- where 𝒔j ≔ coe [i ⇒ A] @p' @j s
--
-- type-case is used to expose A,B if the type is neutral
let ctx1 = extendDim i ctx
Element ty tynf <- whnf defs ctx1 SZero $ getTerm ty
(arg, res) <- tycasePi defs ctx1 ty
let s0 = CoeT i arg q p s s.loc
let Val q = ctx.qtyLen
s0 = CoeT i arg p' p s s.loc
body = E $ App (Ann val (ty // one p) val.loc) (E s0) loc
s1 = CoeT i (arg // (BV 0 i.loc ::: shift 2)) (weakD 1 q) (BV 0 i.loc)
s1 = CoeT i (arg // (BV 0 i.loc ::: shift 2))
(weakD 1 p') (BV 0 i.loc)
(s // shift 1) s.loc
whnf defs ctx sg $ CoeT i (sub1 res s1) p q body loc
whnf defs ctx sg $ CoeT i (sub1 res s1) p p' body loc
||| reduce a pair elimination `CasePair pi (Coe ty p q val) ret body loc`
||| reduce a pair elimination `CasePair pi (Coe ty p p' val) ret body loc`
export covering
sigCoe : (qty : Qty) ->
(ty : DScopeTerm d n) -> (p, q : Dim d) -> (val : Term d n) ->
(ret : ScopeTerm d n) -> (body : ScopeTermN 2 d n) -> Loc ->
Eff Whnf (Subset (Elim d n) (No . isRedexE defs ctx sg))
sigCoe qty sty@(S [< i] ty) p q val ret body loc = do
-- caseπ (coe [i ⇒ (x : A) × B] @p @q s) return z ⇒ C of { (a, b) ⇒ e }
sigCoe : (qty : Qty q) ->
(ty : DScopeTerm q d n) -> (p, p' : Dim d) -> (val : Term q d n) ->
(ret : ScopeTerm q d n) -> (body : ScopeTermN 2 q d n) -> Loc ->
Eff Whnf (Subset (Elim q d n) (No . isRedexE defs ctx sg))
sigCoe qty sty@(S [< i] ty) p p' val ret body loc = do
-- caseπ (coe [i ⇒ (x : A) × B] @p @p' s) return z ⇒ C of { (a, b) ⇒ e }
-- ⇝
-- caseπ s ∷ ((x : A) × B)p/i return z ⇒ C
-- of { (a, b) ⇒
-- e[(coe [i ⇒ A] @p @q a)/a,
-- (coe [i ⇒ B[(coe [j ⇒ Aj/i] @p @i a)/x]] @p @q b)/b] }
-- e[(coe [i ⇒ A] @p @p' a)/a,
-- (coe [i ⇒ B[(coe [j ⇒ Aj/i] @p @i a)/x]] @p @p' b)/b] }
--
-- type-case is used to expose A,B if the type is neutral
let ctx1 = extendDim i ctx
Element ty tynf <- whnf defs ctx1 SZero $ getTerm ty
(tfst, tsnd) <- tycaseSig defs ctx1 ty
let [< x, y] = body.names
a' = CoeT i (weakT 2 tfst) p q (BVT 1 x.loc) x.loc
let Val q = ctx.qtyLen
[< x, y] = body.names
a' = CoeT i (weakT 2 tfst) p p' (BVT 1 x.loc) x.loc
tsnd' = tsnd.term //
(CoeT i (weakT 2 $ tfst // (B VZ tsnd.loc ::: shift 2))
(weakD 1 p) (B VZ i.loc) (BVT 1 tsnd.loc) y.loc ::: shift 2)
b' = CoeT i tsnd' p q (BVT 0 y.loc) y.loc
b' = CoeT i tsnd' p p' (BVT 0 y.loc) y.loc
whnf defs ctx sg $ CasePair qty (Ann val (ty // one p) val.loc) ret
(ST body.names $ body.term // (a' ::: b' ::: shift 2)) loc
||| reduce a pair projection `Fst (Coe ty p q val) loc`
||| reduce a pair projection `Fst (Coe ty p p' val) loc`
export covering
fstCoe : (ty : DScopeTerm d n) -> (p, q : Dim d) -> (val : Term d n) ->
Loc -> Eff Whnf (Subset (Elim d n) (No . isRedexE defs ctx sg))
fstCoe sty@(S [< i] ty) p q val loc = do
-- fst (coe (𝑖 ⇒ (x : A) × B) @p @q s)
fstCoe : (ty : DScopeTerm q d n) -> (p, p' : Dim d) -> (val : Term q d n) ->
Loc -> Eff Whnf (Subset (Elim q d n) (No . isRedexE defs ctx sg))
fstCoe sty@(S [< i] ty) p p' val loc = do
-- fst (coe (𝑖 ⇒ (x : A) × B) @p @p' s)
-- ⇝
-- coe (𝑖 ⇒ A) @p @q (fst (s ∷ (x : Ap/𝑖) × Bp/𝑖))
-- coe (𝑖 ⇒ A) @p @p' (fst (s ∷ (x : Ap/𝑖) × Bp/𝑖))
--
-- type-case is used to expose A,B if the type is neutral
let ctx1 = extendDim i ctx
Element ty tynf <- whnf defs ctx1 SZero $ getTerm ty
(tfst, _) <- tycaseSig defs ctx1 ty
let Val q = ctx.qtyLen
whnf defs ctx sg $
Coe (ST [< i] tfst) p q
Coe (ST [< i] tfst) p p'
(E (Fst (Ann val (ty // one p) val.loc) val.loc)) loc
||| reduce a pair projection `Snd (Coe ty p q val) loc`
export covering
sndCoe : (ty : DScopeTerm d n) -> (p, q : Dim d) -> (val : Term d n) ->
Loc -> Eff Whnf (Subset (Elim d n) (No . isRedexE defs ctx sg))
sndCoe sty@(S [< i] ty) p q val loc = do
-- snd (coe (𝑖 ⇒ (x : A) × B) @p @q s)
sndCoe : (ty : DScopeTerm q d n) -> (p, p' : Dim d) -> (val : Term q d n) ->
Loc -> Eff Whnf (Subset (Elim q d n) (No . isRedexE defs ctx sg))
sndCoe sty@(S [< i] ty) p p' val loc = do
-- snd (coe (𝑖 ⇒ (x : A) × B) @p @p' s)
-- ⇝
-- coe (𝑖 ⇒ B[coe (𝑗 ⇒ A𝑗/𝑖) @p @𝑖 (fst (s ∷ (x : A) × B))/x]) @p @q
-- coe (𝑖 ⇒ B[coe (𝑗 ⇒ A𝑗/𝑖) @p @𝑖 (fst (s ∷ (x : A) × B))/x]) @p @p'
-- (snd (s ∷ (x : Ap/𝑖) × Bp/𝑖))
--
-- type-case is used to expose A,B if the type is neutral
let ctx1 = extendDim i ctx
Element ty tynf <- whnf defs ctx1 SZero $ getTerm ty
(tfst, tsnd) <- tycaseSig defs ctx1 ty
let Val q = ctx.qtyLen
whnf defs ctx sg $
Coe (ST [< i] $ sub1 tsnd $
Coe (ST [< !(fresh i)] $ tfst // (BV 0 i.loc ::: shift 2))
(weakD 1 p) (BV 0 loc)
(E (Fst (Ann (dweakT 1 val) ty val.loc) val.loc)) loc)
p q
p p'
(E (Snd (Ann val (ty // one p) val.loc) val.loc))
loc
||| reduce a dimension application `DApp (Coe ty p q val) r loc`
export covering
eqCoe : (ty : DScopeTerm d n) -> (p, q : Dim d) -> (val : Term d n) ->
eqCoe : (ty : DScopeTerm q d n) -> (p, p' : Dim d) -> (val : Term q d n) ->
(r : Dim d) -> Loc ->
Eff Whnf (Subset (Elim d n) (No . isRedexE defs ctx sg))
eqCoe sty@(S [< j] ty) p q val r loc = do
-- (coe [j ⇒ Eq [i ⇒ A] L R] @p @q eq) @r
Eff Whnf (Subset (Elim q d n) (No . isRedexE defs ctx sg))
eqCoe sty@(S [< j] ty) p p' val r loc = do
-- (coe [j ⇒ Eq [i ⇒ A] L R] @p @p' eq) @r
-- ⇝
-- comp [j ⇒ Ar/i] @p @q ((eq ∷ (Eq [i ⇒ A] L R)p/j) @r)
-- comp [j ⇒ Ar/i] @p @p' ((eq ∷ (Eq [i ⇒ A] L R)p/j) @r)
-- @r { 0 j ⇒ L; 1 j ⇒ R }
let ctx1 = extendDim j ctx
Element ty tynf <- whnf defs ctx1 SZero $ getTerm ty
(a0, a1, a, s, t) <- tycaseEq defs ctx1 ty
let a' = dsub1 a (weakD 1 r)
let Val q = ctx.qtyLen
a' = dsub1 a (weakD 1 r)
val' = E $ DApp (Ann val (ty // one p) val.loc) r loc
whnf defs ctx sg $ CompH j a' p q val' r j s j t loc
whnf defs ctx sg $ CompH j a' p p' val' r j s j t loc
||| reduce a pair elimination `CaseBox pi (Coe ty p q val) ret body`
export covering
boxCoe : (qty : Qty) ->
(ty : DScopeTerm d n) -> (p, q : Dim d) -> (val : Term d n) ->
(ret : ScopeTerm d n) -> (body : ScopeTerm d n) -> Loc ->
Eff Whnf (Subset (Elim d n) (No . isRedexE defs ctx sg))
boxCoe qty sty@(S [< i] ty) p q val ret body loc = do
-- caseπ (coe [i ⇒ [ρ. A]] @p @q s) return z ⇒ C of { [a] ⇒ e }
boxCoe : (qty : Qty q) ->
(ty : DScopeTerm q d n) -> (p, p' : Dim d) -> (val : Term q d n) ->
(ret : ScopeTerm q d n) -> (body : ScopeTerm q d n) -> Loc ->
Eff Whnf (Subset (Elim q d n) (No . isRedexE defs ctx sg))
boxCoe qty sty@(S [< i] ty) p p' val ret body loc = do
-- caseπ (coe [i ⇒ [ρ. A]] @p @p' s) return z ⇒ C of { [a] ⇒ e }
-- ⇝
-- caseπ s ∷ [ρ. A]p/i return z ⇒ C of { [a] ⇒ e[(coe [i ⇒ A] p q a)/a] }
-- caseπ s ∷ [ρ. A]p/i return z ⇒ C of { [a] ⇒ e[(coe [i ⇒ A] p p' a)/a] }
let ctx1 = extendDim i ctx
Val q = ctx.qtyLen
Element ty tynf <- whnf defs ctx1 SZero $ getTerm ty
ta <- tycaseBOX defs ctx1 ty
let xloc = body.name.loc
let a' = CoeT i (weakT 1 ta) p q (BVT 0 xloc) xloc
let a' = CoeT i (weakT 1 ta) p p' (BVT 0 xloc) xloc
whnf defs ctx sg $ CaseBox qty (Ann val (ty // one p) val.loc) ret
(ST body.names $ body.term // (a' ::: shift 1)) loc
@ -150,14 +157,14 @@ parameters {auto _ : CanWhnf Term Interface.isRedexT}
-- new params block to call the above functions at different `n`
parameters {auto _ : CanWhnf Term Interface.isRedexT}
{auto _ : CanWhnf Elim Interface.isRedexE}
(defs : Definitions) (ctx : WhnfContext d n) (sg : SQty)
(defs : Definitions) (ctx : WhnfContext q d n) (sg : SQty)
||| pushes a coercion inside a whnf-ed term
export covering
pushCoe : BindName ->
(ty : Term (S d) n) -> (p, q : Dim d) -> (s : Term d n) -> Loc ->
(0 pc : So (canPushCoe sg ty s)) =>
Eff Whnf (NonRedex Elim d n defs ctx sg)
pushCoe i ty p q s loc =
(ty : Term q (S d) n) -> (p, p' : Dim d) -> (s : Term q d n) ->
Loc -> (0 pc : So (canPushCoe sg ty s)) =>
Eff Whnf (NonRedex Elim q d n defs ctx sg)
pushCoe i ty p p' s loc =
case ty of
-- (coe ★ᵢ @_ @_ s) ⇝ (s ∷ ★ᵢ)
TYPE l tyLoc =>
@ -169,40 +176,40 @@ parameters {auto _ : CanWhnf Term Interface.isRedexT}
-- η expand, then simplify the Coe/App in the body
--
-- (coe (𝑖 ⇒ π.(x : A) → B) @p @q s)
-- (coe (𝑖 ⇒ π.(x : A) → B) @p @p' s)
-- ⇝
-- (λ y ⇒ (coe (𝑖 ⇒ π.(x : A) → B) @p @q s) y) ∷ (π.(x : A) → B)q/𝑖
-- ⇝ ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
-- (λ y ⇒ ⋯) ∷ (π.(x : A) → B)q/𝑖 -- see `piCoe`
-- (λ y ⇒ (coe (𝑖 ⇒ π.(x : A) → B) @p @p' s) y) ∷ (π.(x : A) → B)p'/𝑖
-- ⇝ ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
-- (λ y ⇒ ⋯) ∷ (π.(x : A) → B)p'/𝑖 -- see `piCoe`
--
-- do the piCoe step here because otherwise equality checking keeps
-- doing the η forever
Pi {arg, res = S [< x] _, _} => do
let ctx' = extendTy x (arg // one p) ctx
body <- piCoe defs ctx' sg
(weakDS 1 $ SY [< i] ty) p q (weakT 1 s) (BVT 0 loc) loc
(weakDS 1 $ SY [< i] ty) p p' (weakT 1 s) (BVT 0 loc) loc
whnf defs ctx sg $
Ann (LamY x (E body.fst) loc) (ty // one q) loc
Ann (LamY x (E body.fst) loc) (ty // one p') loc
-- no η!!!
-- push into a pair constructor, otherwise still stuck
--
-- s̃𝑘 ≔ coe (𝑗 ⇒ A𝑗/𝑖) @p @𝑘 s
-- -----------------------------------------------
-- (coe (𝑖 ⇒ (x : A) × B) @p @q (s, t))
-- (coe (𝑖 ⇒ (x : A) × B) @p @p' (s, t))
-- ⇝
-- (s̃q, coe (𝑖 ⇒ B[s̃𝑖/x]) @p @q t)
-- ∷ ((x : A) × B)q/𝑖
-- (s̃p', coe (𝑖 ⇒ B[s̃𝑖/x]) @p @p' t)
-- ∷ ((x : A) × B)p'/𝑖
Sig tfst tsnd tyLoc => do
let Pair fst snd sLoc = s
fst' = CoeT i tfst p q fst fst.loc
let Val q = ctx.qtyLen
Pair fst snd sLoc = s
fst' = CoeT i tfst p p' fst fst.loc
fstInSnd =
CoeT !(fresh i)
(tfst // (BV 0 loc ::: shift 2))
(weakD 1 p) (BV 0 loc) (dweakT 1 fst) fst.loc
snd' = CoeT i (sub1 tsnd fstInSnd) p q snd snd.loc
snd' = CoeT i (sub1 tsnd fstInSnd) p p' snd snd.loc
whnf defs ctx sg $
Ann (Pair (E fst') (E snd') sLoc) (ty // one q) loc
Ann (Pair (E fst') (E snd') sLoc) (ty // one p') loc
-- (coe {𝐚̄} @_ @_ s) ⇝ (s ∷ {𝐚̄})
Enum cases tyLoc =>
@ -210,21 +217,21 @@ parameters {auto _ : CanWhnf Term Interface.isRedexT}
-- η expand/simplify, same as for Π
--
-- (coe (𝑖 ⇒ Eq (𝑗 ⇒ A) l r) @p @q s)
-- (coe (𝑖 ⇒ Eq (𝑗 ⇒ A) l r) @p @p' s)
-- ⇝
-- (δ 𝑘 ⇒ (coe (𝑖 ⇒ Eq (𝑗 ⇒ A) l r) @p @q s) @𝑘) ∷ (Eq (𝑗 ⇒ A) l r)q/𝑖
-- ⇝ ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
-- (δ 𝑘 ⇒ ⋯) ∷ (Eq (𝑗 ⇒ A) l r)q/𝑖 -- see `eqCoe`
-- (δ 𝑘 ⇒ (coe (𝑖 ⇒ Eq (𝑗 ⇒ A) l r) @p @p' s) @𝑘) ∷ (Eq (𝑗 ⇒ A) l r)p'/𝑖
-- ⇝ ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
-- (δ 𝑘 ⇒ ⋯) ∷ (Eq (𝑗 ⇒ A) l r)p'/𝑖 -- see `eqCoe`
--
-- do the eqCoe step here because otherwise equality checking keeps
-- doing the η forever
Eq {ty = S [< j] _, _} => do
let ctx' = extendDim j ctx
body <- eqCoe defs ctx' sg
(dweakDS 1 $ S [< i] $ Y ty) (weakD 1 p) (weakD 1 q)
(dweakDS 1 $ S [< i] $ Y ty) (weakD 1 p) (weakD 1 p')
(dweakT 1 s) (BV 0 loc) loc
whnf defs ctx sg $
Ann (DLamY i (E body.fst) loc) (ty // one q) loc
Ann (DLamY i (E body.fst) loc) (ty // one p') loc
-- (coe @_ @_ s) ⇝ (s ∷ )
NAT tyLoc =>
@ -236,17 +243,17 @@ parameters {auto _ : CanWhnf Term Interface.isRedexT}
-- η expand/simplify
--
-- (coe (𝑖 ⇒ [π.A]) @p @q s)
-- (coe (𝑖 ⇒ [π.A]) @p @p' s)
-- ⇝
-- [case coe (𝑖 ⇒ [π.A]) @p @q s return Aq/𝑖 of {[x] ⇒ x}]
-- [case coe (𝑖 ⇒ [π.A]) @p @p' s return Ap'/𝑖 of {[x] ⇒ x}]
-- ⇝
-- [case1 s ∷ [π.A]p/𝑖 ⋯] ∷ [π.A]q/𝑖 -- see `boxCoe`
-- [case1 s ∷ [π.A]p/𝑖 ⋯] ∷ [π.A]p'/𝑖 -- see `boxCoe`
--
-- do the eqCoe step here because otherwise equality checking keeps
-- do the boxCoe step here because otherwise equality checking keeps
-- doing the η forever
BOX qty inner tyLoc => do
body <- boxCoe defs ctx sg qty
(SY [< i] ty) p q s
(SN $ inner // one q)
(SY [< i] ty) p p' s
(SN $ inner // one p')
(SY [< !(mnb "inner" loc)] (BVT 0 loc)) loc
whnf defs ctx sg $ Ann (Box (E body.fst) loc) (ty // one q) loc
whnf defs ctx sg $ Ann (Box (E body.fst) loc) (ty // one p') loc

View file

@ -15,46 +15,44 @@ export covering
computeElimType :
CanWhnf Term Interface.isRedexT =>
CanWhnf Elim Interface.isRedexE =>
(defs : Definitions) -> (ctx : WhnfContext d n) -> (0 sg : SQty) ->
(e : Elim d n) -> (0 ne : No (isRedexE defs ctx sg e)) =>
Eff Whnf (Term d n)
(defs : Definitions) -> (ctx : WhnfContext q d n) -> (0 sg : SQty) ->
(e : Elim q d n) -> (0 ne : No (isRedexE defs ctx sg e)) =>
Eff Whnf (Term q d n)
||| computes a type and then reduces it to whnf
export covering
computeWhnfElimType0 :
CanWhnf Term Interface.isRedexT =>
CanWhnf Elim Interface.isRedexE =>
(defs : Definitions) -> (ctx : WhnfContext d n) -> (0 sg : SQty) ->
(e : Elim d n) -> (0 ne : No (isRedexE defs ctx sg e)) =>
Eff Whnf (Term d n)
(defs : Definitions) -> (ctx : WhnfContext q d n) -> (0 sg : SQty) ->
(e : Elim q d n) -> (0 ne : No (isRedexE defs ctx sg e)) =>
Eff Whnf (Term q d n)
private covering
computeElimTypeNoLog, computeWhnfElimType0NoLog :
CanWhnf Term Interface.isRedexT =>
CanWhnf Elim Interface.isRedexE =>
(defs : Definitions) -> WhnfContext d n -> (0 sg : SQty) ->
(e : Elim d n) -> (0 ne : No (isRedexE defs ctx sg e)) =>
Eff Whnf (Term d n)
(defs : Definitions) -> WhnfContext q d n -> (0 sg : SQty) ->
(e : Elim q d n) -> (0 ne : No (isRedexE defs ctx sg e)) =>
Eff Whnf (Term q d n)
computeElimTypeNoLog defs ctx sg e =
case e of
F x u loc => do
let Just def = lookup x defs
| Nothing => throw $ NotInScope loc x
pure $ def.typeWithAt ctx.dimLen ctx.termLen u
let polyTy = def.typeWithAt ctx.dimLen ctx.termLen u
Val q = ctx.qtyLen
pure $ polyTy.type // ?freeQSubst
B i _ =>
pure (ctx.tctx !! i).type
B i _ => pure (ctx.tctx !! i).type
App f s loc =>
case !(computeWhnfElimType0NoLog defs ctx sg f {ne = noOr1 ne}) of
Pi {arg, res, _} => pure $ sub1 res $ Ann s arg loc
ty => throw $ ExpectedPi loc ctx.names ty
CasePair {pair, ret, _} =>
pure $ sub1 ret pair
Fst pair loc =>
case !(computeWhnfElimType0NoLog defs ctx sg pair {ne = noOr1 ne}) of
Sig {fst, _} => pure fst
@ -65,46 +63,34 @@ computeElimTypeNoLog defs ctx sg e =
Sig {snd, _} => pure $ sub1 snd $ Fst pair loc
ty => throw $ ExpectedSig loc ctx.names ty
CaseEnum {tag, ret, _} =>
pure $ sub1 ret tag
CaseNat {nat, ret, _} =>
pure $ sub1 ret nat
CaseBox {box, ret, _} =>
pure $ sub1 ret box
CasePair {pair, ret, _} => pure $ sub1 ret pair
CaseEnum {tag, ret, _} => pure $ sub1 ret tag
CaseNat {nat, ret, _} => pure $ sub1 ret nat
CaseBox {box, ret, _} => pure $ sub1 ret box
DApp {fun = f, arg = p, loc} =>
case !(computeWhnfElimType0NoLog defs ctx sg f {ne = noOr1 ne}) of
Eq {ty, _} => pure $ dsub1 ty p
t => throw $ ExpectedEq loc ctx.names t
Ann {ty, _} =>
pure ty
Coe {ty, q, _} =>
pure $ dsub1 ty q
Comp {ty, _} =>
pure ty
TypeCase {ret, _} =>
pure ret
Ann {ty, _} => pure ty
Coe {ty, p', _} => pure $ dsub1 ty p'
Comp {ty, _} => pure ty
TypeCase {ret, _} => pure ret
computeElimType defs ctx sg e {ne} = do
let Val n = ctx.termLen
sayMany "whnf" e.loc
[90 :> "computeElimType",
95 :> hsep ["ctx =", runPretty $ prettyWhnfContext ctx],
90 :> hsep ["e =", runPretty $ prettyElim ctx.dnames ctx.tnames e]]
90 :> hsep ["e =", runPretty $ prettyElim ctx.names e]]
res <- computeElimTypeNoLog defs ctx sg e {ne}
say "whnf" 91 e.loc $
hsep ["computeElimType ⇝",
runPretty $ prettyTerm ctx.dnames ctx.tnames res]
hsep ["computeElimType ⇝", runPretty $ prettyTerm ctx.names res]
pure res
computeWhnfElimType0 defs ctx sg e =
computeElimType defs ctx sg e >>= whnf0 defs ctx SZero
whnf0 defs ctx SZero !(computeElimType defs ctx sg e)
computeWhnfElimType0NoLog defs ctx sg e {ne} =
computeElimTypeNoLog defs ctx sg e {ne} >>= whnf0 defs ctx SZero
whnf0 defs ctx SZero !(computeElimTypeNoLog defs ctx sg e {ne})

View file

@ -20,14 +20,15 @@ Whnf = [Except Error, NameGen, Log]
public export
0 RedexTest : TermLike -> Type
RedexTest tm =
{0 d, n : Nat} -> Definitions -> WhnfContext d n -> SQty -> tm d n -> Bool
{0 q, d, n : Nat} ->
Definitions -> WhnfContext q d n -> SQty -> tm q d n -> Bool
public export
interface CanWhnf (0 tm : TermLike) (0 isRedex : RedexTest tm) | tm
where
whnf, whnfNoLog :
(defs : Definitions) -> (ctx : WhnfContext d n) -> (q : SQty) ->
tm d n -> Eff Whnf (Subset (tm d n) (No . isRedex defs ctx q))
(defs : Definitions) -> (ctx : WhnfContext q d n) -> (sg : SQty) ->
tm q d n -> Eff Whnf (Subset (tm q d n) (No . isRedex defs ctx sg))
-- having isRedex be part of the class header, and needing to be explicitly
-- quantified on every use since idris can't infer its type, is a little ugly.
-- but none of the alternatives i've thought of so far work. e.g. in some
@ -36,26 +37,27 @@ where
public export %inline
whnf0, whnfNoLog0 :
{0 isRedex : RedexTest tm} -> CanWhnf tm isRedex =>
Definitions -> WhnfContext d n -> SQty -> tm d n -> Eff Whnf (tm d n)
Definitions -> WhnfContext q d n -> SQty -> tm q d n -> Eff Whnf (tm q d n)
whnf0 defs ctx q t = fst <$> whnf defs ctx q t
whnfNoLog0 defs ctx q t = fst <$> whnfNoLog defs ctx q t
public export
0 IsRedex, NotRedex : {isRedex : RedexTest tm} -> CanWhnf tm isRedex =>
Definitions -> WhnfContext d n -> SQty -> Pred (tm d n)
Definitions -> WhnfContext q d n -> SQty ->
Pred (tm q d n)
IsRedex defs ctx q = So . isRedex defs ctx q
NotRedex defs ctx q = No . isRedex defs ctx q
public export
0 NonRedex : (tm : TermLike) -> {isRedex : RedexTest tm} ->
CanWhnf tm isRedex => (d, n : Nat) ->
Definitions -> WhnfContext d n -> SQty -> Type
NonRedex tm d n defs ctx q = Subset (tm d n) (NotRedex defs ctx q)
CanWhnf tm isRedex => (q, d, n : Nat) ->
Definitions -> WhnfContext q d n -> SQty -> Type
NonRedex tm q d n defs ctx sg = Subset (tm q d n) (NotRedex defs ctx sg)
public export %inline
nred : {0 isRedex : RedexTest tm} -> (0 _ : CanWhnf tm isRedex) =>
(t : tm d n) -> (0 nr : NotRedex defs ctx q t) =>
NonRedex tm d n defs ctx q
(t : tm q d n) -> (0 nr : NotRedex defs ctx sg t) =>
NonRedex tm q d n defs ctx sg
nred t = Element t nr
@ -97,7 +99,7 @@ isNatHead _ = False
||| a natural constant, with or without an annotation
public export %inline
isNatConst : Term d n -> Bool
isNatConst : Term {} -> Bool
isNatConst (Nat {}) = True
isNatConst (E (Ann (Nat {}) _ _)) = True
isNatConst _ = False
@ -145,6 +147,7 @@ isTyCon (Let {}) = False
isTyCon (E {}) = False
isTyCon (CloT {}) = False
isTyCon (DCloT {}) = False
isTyCon (QCloT {}) = False
||| a syntactic type, or a neutral
public export %inline
@ -195,6 +198,7 @@ canPushCoe sg (Let {}) _ = False
canPushCoe sg (E {}) _ = False
canPushCoe sg (CloT {}) _ = False
canPushCoe sg (DCloT {}) _ = False
canPushCoe sg (QCloT {}) _ = False
mutual
@ -238,15 +242,16 @@ mutual
isRedexE defs ctx sg (Ann {tm, ty, _}) =
isE tm || isRedexT defs ctx sg tm || isRedexT defs ctx SZero ty
isRedexE defs ctx sg (Coe {ty = S _ (N _), _}) = True
isRedexE defs ctx sg (Coe {ty = S [< i] (Y ty), p, q, val, _}) =
isRedexE defs ctx sg (Coe {ty = S [< i] (Y ty), p, p', val, _}) =
isRedexT defs (extendDim i ctx) SZero ty ||
canPushCoe sg ty val || isYes (p `decEqv` q)
isRedexE defs ctx sg (Comp {ty, p, q, r, _}) =
isYes (p `decEqv` q) || isK r
canPushCoe sg ty val || isYes (p `decEqv` p')
isRedexE defs ctx sg (Comp {ty, p, p', r, _}) =
isYes (p `decEqv` p') || isK r
isRedexE defs ctx sg (TypeCase {ty, ret, _}) =
isRedexE defs ctx sg ty || isRedexT defs ctx sg ret || isAnnTyCon ty
isRedexE _ _ _ (CloE {}) = True
isRedexE _ _ _ (DCloE {}) = True
isRedexE _ _ _ (QCloE {}) = True
||| a reducible term
|||
@ -260,6 +265,7 @@ mutual
isRedexT : RedexTest Term
isRedexT _ _ _ (CloT {}) = True
isRedexT _ _ _ (DCloT {}) = True
isRedexT _ _ _ (QCloT {}) = True
isRedexT _ _ _ (Let {}) = True
isRedexT defs ctx sg (E {e, _}) = isAnn e || isRedexE defs ctx sg e
isRedexT _ _ _ (Succ p {}) = isNatConst p

View file

@ -19,19 +19,19 @@ export covering CanWhnf Elim Interface.isRedexE
private %inline
whnfDefault :
{0 isRedex : RedexTest tm} ->
(CanWhnf tm isRedex, Located2 tm) =>
(CanWhnf tm isRedex, Located3 tm) =>
String ->
(forall d, n. WhnfContext d n -> tm d n -> Eff Pretty LogDoc) ->
(forall d, n. WhnfContext q d n -> tm q d n -> Eff Pretty LogDoc) ->
(defs : Definitions) ->
(ctx : WhnfContext d n) ->
(ctx : WhnfContext q d n) ->
(sg : SQty) ->
(s : tm d n) ->
Eff Whnf (Subset (tm d n) (No . isRedex defs ctx sg))
(s : tm q d n) ->
Eff Whnf (Subset (tm q d n) (No . isRedex defs ctx sg))
whnfDefault name ppr defs ctx sg s = do
sayMany "whnf" s.loc
[10 :> "whnf",
95 :> hsep ["ctx =", runPretty $ prettyWhnfContext ctx],
95 :> hsep ["sg =", runPretty $ prettyQty sg.qty],
95 :> hsep ["sg =", runPretty $ prettyQConst sg.qconst],
10 :> hsep [text name, "=", runPretty $ ppr ctx s]]
res <- whnfNoLog defs ctx sg s
say "whnf" 11 s.loc $ hsep ["whnf ⇝", runPretty $ ppr ctx res.fst]
@ -39,10 +39,10 @@ whnfDefault name ppr defs ctx sg s = do
covering
CanWhnf Elim Interface.isRedexE where
whnf = whnfDefault "e" $ \ctx, e => prettyElim ctx.dnames ctx.tnames e
whnf = whnfDefault "e" $ \ctx, e => prettyElim ctx.names e
whnfNoLog defs ctx sg (F x u loc) with (lookupElim0 x u defs) proof eq
_ | Just y = whnf defs ctx sg $ setLoc loc $ injElim ctx y
_ | Just y = whnf defs ctx sg $ setLoc loc $ ?whnfFreeQSubst
_ | Nothing = pure $ Element (F x u loc) $ rewrite eq in Ah
whnfNoLog defs ctx sg (B i loc) with (ctx.tctx !! i) proof eq1
@ -186,8 +186,8 @@ CanWhnf Elim Interface.isRedexE where
whnf defs ctx sg $
Ann (endsOr (setLoc appLoc l) (setLoc appLoc r) (dsub1 body p) p)
(dsub1 ty p) appLoc
Coe ty p' q' val _ =>
eqCoe defs ctx sg ty p' q' val p appLoc
Coe ty r r' val _ =>
eqCoe defs ctx sg ty r r' val p appLoc
Right ndlh => case p of
K e _ => do
Eq {l, r, ty, _} <- computeWhnfElimType0 defs ctx sg f
@ -206,36 +206,37 @@ CanWhnf Elim Interface.isRedexE where
Element a anf <- whnf defs ctx SZero a
pure $ Element (Ann s a annLoc) (ne `orNo` snf `orNo` anf)
whnfNoLog defs ctx sg (Coe sty p q val coeLoc) =
whnfNoLog defs ctx sg (Coe sty p p' val coeLoc) = do
-- 𝑖 ∉ fv(A)
-- -------------------------------
-- coe (𝑖 ⇒ A) @p @q s ⇝ s ∷ A
-- coe (𝑖 ⇒ A) @p @p' s ⇝ s ∷ A
--
-- [fixme] needs a real equality check between A0/𝑖 and A1/𝑖
case dsqueeze sty {f = Term} of
let Val q = ctx.qtyLen
case dsqueeze sty {f = Term q} of
([< i], Left ty) =>
case p `decEqv` q of
case p `decEqv` p' of
-- coe (𝑖 ⇒ A) @p @p s ⇝ (s ∷ Ap/𝑖)
Yes _ => whnf defs ctx sg $ Ann val (dsub1 sty p) coeLoc
No npq => do
Element ty tynf <- whnf defs (extendDim i ctx) SZero ty
case nchoose $ canPushCoe sg ty val of
Left pc => pushCoe defs ctx sg i ty p q val coeLoc
Right npc => pure $ Element (Coe (SY [< i] ty) p q val coeLoc)
Left pc => pushCoe defs ctx sg i ty p p' val coeLoc
Right npc => pure $ Element (Coe (SY [< i] ty) p p' val coeLoc)
(tynf `orNo` npc `orNo` notYesNo npq)
(_, Right ty) =>
whnf defs ctx sg $ Ann val ty coeLoc
whnfNoLog defs ctx sg (Comp ty p q val r zero one compLoc) =
case p `decEqv` q of
whnfNoLog defs ctx sg (Comp ty p p' val r zero one compLoc) =
case p `decEqv` p' of
-- comp [A] @p @p s @r { ⋯ } ⇝ s ∷ A
Yes y => whnf defs ctx sg $ Ann val ty compLoc
No npq => case r of
-- comp [A] @p @q s @0 { 0 𝑗 ⇒ t₀; ⋯ } ⇝ t₀q/𝑗 ∷ A
K Zero _ => whnf defs ctx sg $ Ann (dsub1 zero q) ty compLoc
-- comp [A] @p @q s @1 { 1 𝑗 ⇒ t₁; ⋯ } ⇝ t₁q/𝑗 ∷ A
K One _ => whnf defs ctx sg $ Ann (dsub1 one q) ty compLoc
B {} => pure $ Element (Comp ty p q val r zero one compLoc)
-- comp [A] @p @p' s @0 { 0 𝑗 ⇒ t₀; ⋯ } ⇝ t₀p'/𝑗 ∷ A
K Zero _ => whnf defs ctx sg $ Ann (dsub1 zero p') ty compLoc
-- comp [A] @p @p' s @1 { 1 𝑗 ⇒ t₁; ⋯ } ⇝ t₁p'/𝑗 ∷ A
K One _ => whnf defs ctx sg $ Ann (dsub1 one p') ty compLoc
B {} => pure $ Element (Comp ty p p' val r zero one compLoc)
(notYesNo npq `orNo` Ah)
whnfNoLog defs ctx sg (TypeCase ty ret arms def tcLoc) =
@ -248,17 +249,23 @@ CanWhnf Elim Interface.isRedexE where
reduceTypeCase defs ctx ty u ret arms def tcLoc
Right nt => pure $ Element (TypeCase ty ret arms def tcLoc)
(tynf `orNo` retnf `orNo` nt)
No _ =>
throw $ ClashQ tcLoc sg.qty Zero
No _ => do
let Val q = ctx.qtyLen
throw $ ClashQ tcLoc ctx.qnames (toQty tcLoc sg) (zero tcLoc)
whnfNoLog defs ctx sg (CloE (Sub el th)) =
whnfNoLog defs ctx sg $ pushSubstsWith' id th el
whnfNoLog defs ctx sg (DCloE (Sub el th)) =
whnfNoLog defs ctx sg $ pushSubstsWith' th id el
whnfNoLog defs ctx sg (CloE (Sub el th)) = do
let Val q = ctx.qtyLen
whnfNoLog defs ctx sg $ pushSubstsWith' id id th el
whnfNoLog defs ctx sg (DCloE (Sub el th)) = do
let Val q = ctx.qtyLen
whnfNoLog defs ctx sg $ pushSubstsWith' id th id el
whnfNoLog defs ctx sg (QCloE (SubR el th)) = do
let Val q = ctx.qtyLen
whnfNoLog defs ctx sg $ pushSubstsWith' th id id el
covering
CanWhnf Term Interface.isRedexT where
whnf = whnfDefault "e" $ \ctx, s => prettyTerm ctx.dnames ctx.tnames s
whnf = whnfDefault "e" $ \ctx, s => prettyTerm ctx.names s
whnfNoLog _ _ _ t@(TYPE {}) = pure $ nred t
whnfNoLog _ _ _ t@(IOState {}) = pure $ nred t
@ -294,7 +301,14 @@ CanWhnf Term Interface.isRedexT where
Left _ => let Ann {tm, _} = e in pure $ Element tm $ noOr1 $ noOr2 enf
Right na => pure $ Element (E e) $ na `orNo` enf
whnfNoLog defs ctx sg (CloT (Sub tm th)) =
whnfNoLog defs ctx sg $ pushSubstsWith' id th tm
whnfNoLog defs ctx sg (DCloT (Sub tm th)) =
whnfNoLog defs ctx sg $ pushSubstsWith' th id tm
whnfNoLog defs ctx sg (CloT (Sub tm th)) = do
let Val q = ctx.qtyLen
whnfNoLog defs ctx sg $ pushSubstsWith' id id th tm
whnfNoLog defs ctx sg (DCloT (Sub tm th)) = do
let Val q = ctx.qtyLen
whnfNoLog defs ctx sg $ pushSubstsWith' id th id tm
whnfNoLog defs ctx sg (QCloT (SubR tm th)) = do
let Val q = ctx.qtyLen
whnfNoLog defs ctx sg $ pushSubstsWith' th id id tm

View file

@ -8,42 +8,43 @@ import Data.SnocVect
private
tycaseRhs : (k : TyConKind) -> TypeCaseArms d n ->
Maybe (ScopeTermN (arity k) d n)
tycaseRhs : (k : TyConKind) -> TypeCaseArms q d n ->
Maybe (ScopeTermN (arity k) q d n)
tycaseRhs k arms = lookupPrecise k arms
private
tycaseRhsDef : Term d n -> (k : TyConKind) -> TypeCaseArms d n ->
ScopeTermN (arity k) d n
tycaseRhsDef : (def : Term q d n) -> (k : TyConKind) -> TypeCaseArms q d n ->
ScopeTermN (arity k) q d n
tycaseRhsDef def k arms = fromMaybe (SN def) $ tycaseRhs k arms
private
tycaseRhs0 : (k : TyConKind) -> TypeCaseArms d n ->
(0 eq : arity k = 0) => Maybe (Term d n)
tycaseRhs0 : (k : TyConKind) -> TypeCaseArms q d n ->
(0 eq : arity k = 0) => Maybe (Term q d n)
tycaseRhs0 k arms = map (.term0) $ rewrite sym eq in tycaseRhs k arms
private
tycaseRhsDef0 : Term d n -> (k : TyConKind) -> TypeCaseArms d n ->
(0 eq : arity k = 0) => Term d n
tycaseRhsDef0 : (def : Term q d n) -> (k : TyConKind) -> TypeCaseArms q d n ->
(0 eq : arity k = 0) => Term q d n
tycaseRhsDef0 def k arms = fromMaybe def $ tycaseRhs0 k arms
parameters {auto _ : CanWhnf Term Interface.isRedexT}
{auto _ : CanWhnf Elim Interface.isRedexE}
(defs : Definitions) (ctx : WhnfContext d n)
(defs : Definitions) (ctx : WhnfContext q d n)
||| for π.(x : A) → B, returns (A, B);
||| for an elim returns a pair of type-cases that will reduce to that;
||| for other intro forms error
export covering
tycasePi : (t : Term d n) -> (0 tnf : No (isRedexT defs ctx SZero t)) =>
Eff Whnf (Term d n, ScopeTerm d n)
tycasePi : (t : Term q d n) -> (0 tnf : No (isRedexT defs ctx SZero t)) =>
Eff Whnf (Term q d n, ScopeTerm q d n)
tycasePi (Pi {arg, res, _}) = pure (arg, res)
tycasePi (E e) {tnf} = do
ty <- computeElimType defs ctx SZero e {ne = noOr2 tnf}
let loc = e.loc
let Val q = ctx.qtyLen
loc = e.loc
narg = mnb "Arg" loc; nret = mnb "Ret" loc
arg = E $ typeCase1Y e ty KPi [< !narg, !nret] (BVT 1 loc) loc
res' = typeCase1Y e (Arr Zero arg ty loc) KPi [< !narg, !nret]
res' = typeCase1Y e (Arr (zero loc) arg ty loc) KPi [< !narg, !nret]
(BVT 0 loc) loc
res = ST [< !narg] $ E $ App (weakE 1 res') (BVT 0 loc) loc
pure (arg, res)
@ -53,15 +54,16 @@ parameters {auto _ : CanWhnf Term Interface.isRedexT}
||| for an elim returns a pair of type-cases that will reduce to that;
||| for other intro forms error
export covering
tycaseSig : (t : Term d n) -> (0 tnf : No (isRedexT defs ctx SZero t)) =>
Eff Whnf (Term d n, ScopeTerm d n)
tycaseSig : (t : Term q d n) -> (0 tnf : No (isRedexT defs ctx SZero t)) =>
Eff Whnf (Term q d n, ScopeTerm q d n)
tycaseSig (Sig {fst, snd, _}) = pure (fst, snd)
tycaseSig (E e) {tnf} = do
ty <- computeElimType defs ctx SZero e {ne = noOr2 tnf}
let loc = e.loc
let Val q = ctx.qtyLen
loc = e.loc
nfst = mnb "Fst" loc; nsnd = mnb "Snd" loc
fst = E $ typeCase1Y e ty KSig [< !nfst, !nsnd] (BVT 1 loc) loc
snd' = typeCase1Y e (Arr Zero fst ty loc) KSig [< !nfst, !nsnd]
snd' = typeCase1Y e (Arr (zero loc) fst ty loc) KSig [< !nfst, !nsnd]
(BVT 0 loc) loc
snd = ST [< !nfst] $ E $ App (weakE 1 snd') (BVT 0 loc) loc
pure (fst, snd)
@ -71,8 +73,8 @@ parameters {auto _ : CanWhnf Term Interface.isRedexT}
||| for an elim returns a type-case that will reduce to that;
||| for other intro forms error
export covering
tycaseBOX : (t : Term d n) -> (0 tnf : No (isRedexT defs ctx SZero t)) =>
Eff Whnf (Term d n)
tycaseBOX : (t : Term q d n) -> (0 tnf : No (isRedexT defs ctx SZero t)) =>
Eff Whnf (Term q d n)
tycaseBOX (BOX {ty, _}) = pure ty
tycaseBOX (E e) {tnf} = do
ty <- computeElimType defs ctx SZero e {ne = noOr2 tnf}
@ -83,12 +85,14 @@ parameters {auto _ : CanWhnf Term Interface.isRedexT}
||| for an elim returns five type-cases that will reduce to that;
||| for other intro forms error
export covering
tycaseEq : (t : Term d n) -> (0 tnf : No (isRedexT defs ctx SZero t)) =>
Eff Whnf (Term d n, Term d n, DScopeTerm d n, Term d n, Term d n)
tycaseEq : (t : Term q d n) -> (0 tnf : No (isRedexT defs ctx SZero t)) =>
Eff Whnf (Term q d n, Term q d n, DScopeTerm q d n,
Term q d n, Term q d n)
tycaseEq (Eq {ty, l, r, _}) = pure (ty.zero, ty.one, ty, l, r)
tycaseEq (E e) {tnf} = do
ty <- computeElimType defs ctx SZero e {ne = noOr2 tnf}
let loc = e.loc
let Val q = ctx.qtyLen
loc = e.loc
names = traverse' (\x => mnb x loc) [< "A0", "A1", "A", "L", "R"]
a0 = E $ typeCase1Y e ty KEq !names (BVT 4 loc) loc
a1 = E $ typeCase1Y e ty KEq !names (BVT 3 loc) loc
@ -104,10 +108,10 @@ parameters {auto _ : CanWhnf Term Interface.isRedexT}
||| `reduceTypeCase A i Q arms def _` reduces an expression
||| `type-case A ∷ ★ᵢ return Q of { arms; _ ⇒ def }`
export covering
reduceTypeCase : (ty : Term d n) -> (u : Universe) -> (ret : Term d n) ->
(arms : TypeCaseArms d n) -> (def : Term d n) ->
reduceTypeCase : (ty : Term q d n) -> (u : Universe) -> (ret : Term q d n) ->
(arms : TypeCaseArms q d n) -> (def : Term q d n) ->
(0 _ : So (isTyCon ty)) => Loc ->
Eff Whnf (Subset (Elim d n) (No . isRedexE defs ctx SZero))
Eff Whnf (Subset (Elim q d n) (No . isRedexE defs ctx SZero))
reduceTypeCase ty u ret arms def loc = case ty of
-- (type-case ★ᵢ ∷ _ return Q of { ★ ⇒ s; ⋯ }) ⇝ s ∷ Q
TYPE {} =>
@ -120,9 +124,10 @@ parameters {auto _ : CanWhnf Term Interface.isRedexT}
-- (type-case π.(x : A) → B ∷ ★ᵢ return Q of { (a → b) ⇒ s; ⋯ }) ⇝
-- s[(A ∷ ★ᵢ)/a, ((λ x ⇒ B) ∷ 0.A → ★ᵢ)/b] ∷ Q
Pi {arg, res, loc = piLoc, _} =>
let arg' = Ann arg (TYPE u arg.loc) arg.loc
let Val q = ctx.qtyLen
arg' = Ann arg (TYPE u arg.loc) arg.loc
res' = Ann (Lam res res.loc)
(Arr Zero arg (TYPE u arg.loc) arg.loc) res.loc
(Arr (zero loc) arg (TYPE u arg.loc) arg.loc) res.loc
in
whnf defs ctx SZero $
Ann (subN (tycaseRhsDef def KPi arms) [< arg', res']) ret loc
@ -130,9 +135,10 @@ parameters {auto _ : CanWhnf Term Interface.isRedexT}
-- (type-case (x : A) × B ∷ ★ᵢ return Q of { (a × b) ⇒ s; ⋯ }) ⇝
-- s[(A ∷ ★ᵢ)/a, ((λ x ⇒ B) ∷ 0.A → ★ᵢ)/b] ∷ Q
Sig {fst, snd, loc = sigLoc, _} =>
let fst' = Ann fst (TYPE u fst.loc) fst.loc
let Val q = ctx.qtyLen
fst' = Ann fst (TYPE u fst.loc) fst.loc
snd' = Ann (Lam snd snd.loc)
(Arr Zero fst (TYPE u fst.loc) fst.loc) snd.loc
(Arr (zero loc) fst (TYPE u fst.loc) fst.loc) snd.loc
in
whnf defs ctx SZero $
Ann (subN (tycaseRhsDef def KSig arms) [< fst', snd']) ret loc

View file

@ -21,6 +21,8 @@ modules =
Quox.No,
Quox.Log,
Quox.Loc,
Quox.Semiring,
Quox.Polynomial,
Quox.Var,
Quox.Scoped,
Quox.OPE,

View file

@ -26,6 +26,15 @@ ToInfo Failure where
("expected", show f.expected),
("got", show f.got)]
private
testFreeVars1 : {d : Nat} -> HasFreeVars f =>
(f d -> String) -> f d -> FreeVars' d -> Test
testFreeVars1 lbl tm dims =
test (lbl tm) $ do
let dims = FV dims; dims' = fv tm
unless (dims == dims') $ Left $ Fail Dim dims dims'
Right ()
private
testFreeVars : {d, n : Nat} -> (HasFreeVars (f d), HasFreeDVars f) =>
(f d n -> String) -> f d n -> FreeVars' d -> FreeVars' n -> Test
@ -45,6 +54,22 @@ private
prettyWith : (a -> Eff Pretty Doc80) -> a -> String
prettyWith f = trim . render _ . runPretty . f
parameters {d : Nat} (ds : BContext d)
private
withContext1 : Doc80 -> Eff Pretty Doc80
withContext1 doc =
if null ds then pure $ hsep ["", doc]
else pure $ sep [hsep [!(ctx1 ds), ""], doc]
where
ctx1 : forall k. BContext k -> Eff Pretty Doc80
ctx1 [<] = pure "·"
ctx1 ctx = fillSeparateTight !commaD . toList' <$>
traverse' (pure . prettyBind') ctx
private
testFreeVarsD : Dim d -> FreeVars' d -> Test
testFreeVarsD = testFreeVars1 $ prettyWith $ withContext1 <=< prettyDim ds
parameters {d, n : Nat} (ds : BContext d) (ts : BContext n)
private
withContext : Doc80 -> Eff Pretty Doc80
@ -67,7 +92,13 @@ parameters {d, n : Nat} (ds : BContext d) (ts : BContext n)
export
tests : Test
tests = "free variables" :- [
tests = "free variables (fv/fdv)" :- [
testFreeVarsD [<] (^K Zero) [<],
testFreeVarsD [<"i", "j"] (^K Zero) [<False, False],
testFreeVarsD [<"i", "j"] (^BV 0) [<False, True],
testFreeVarsD [<"i", "j"] (^BV 1) [<True, False],
testFreeVarsD [<"i", "j", "k", "l"] (^BV 2) [<False, True, False, False],
testFreeVarsT [<] [<] (^TYPE 0) [<] [<],
testFreeVarsT [<"i", "j"] [<] (^TYPE 0) [<False, False] [<],
testFreeVarsT [<] [<"x", "y"] (^TYPE 0) [<] [<False, False],
@ -98,6 +129,10 @@ tests = "free variables" :- [
testFreeVarsT [<"i","j"] [<] (^DLamY "k" (E $ ^DApp (^F "eq" 0) (^BV 0)))
[<False,False] [<],
testFreeVarsT [<"i","j"] [<] (^DLamY "k" (E $ ^DApp (^F "eq" 0) (^BV 2)))
[<True,False] [<],
testFreeVarsT [<"i","j"] [<] (^DLamY "i" (E $ ^DApp (^F "eq" 0) (^BV 0)))
[<False,False] [<],
testFreeVarsT [<"i","j"] [<] (^DLamN (E $ ^DApp (^F "eq" 0) (^BV 0)))
[<False,True] [<],

8
tests/Tests/Qty.idr Normal file
View file

@ -0,0 +1,8 @@
module Tests.Qty
import TAP
import Quox.Syntax.Qty
import PrettyExtra