5 | import Libraries.Data.List.SizeOf
7 | import Libraries.Data.VarSet
9 | import Libraries.Data.SnocList.SizeOf
15 | data Env : (tm : Scoped) -> Scope -> Type where
16 | Nil : Env tm Scope.empty
17 | (::) : Binder (tm vars) -> Env tm vars -> Env tm (x :: vars)
22 | empty : Env tm Scope.empty
26 | extend : (x : Name) -> Binder (tm vars) -> Env tm vars -> Env tm (x :: vars)
30 | (++) : {ns : _} -> Env Term ns -> Env Term vars -> Env Term (ns ++ vars)
31 | (++) (b :: bs) e = extend _ (map embed b) (bs ++ e)
35 | length : Env tm xs -> Nat
37 | length (_ :: xs) = S (length xs)
40 | lengthNoLet : Env tm xs -> Nat
42 | lengthNoLet (Let _ _ _ _ :: xs) = lengthNoLet xs
43 | lengthNoLet (_ :: xs) = S (lengthNoLet xs)
46 | lengthExplicitPi : Env tm xs -> Nat
47 | lengthExplicitPi [] = 0
48 | lengthExplicitPi (Pi _ _ Explicit _ :: rho) = S (lengthExplicitPi rho)
49 | lengthExplicitPi (_ :: rho) = lengthExplicitPi rho
52 | namesNoLet : {xs : _} -> Env tm xs -> List Name
54 | namesNoLet (Let _ _ _ _ :: xs) = namesNoLet xs
55 | namesNoLet {xs = x :: _} (_ :: env) = x :: namesNoLet env
58 | eraseLinear : Env tm vs -> Env tm vs
59 | eraseLinear [] = Env.empty
60 | eraseLinear (b :: bs)
61 | = if isLinear (multiplicity b)
62 | then setMultiplicity b erased :: eraseLinear bs
63 | else b :: eraseLinear bs
66 | getErased : {0 vs : _} -> Env tm vs -> List (Var vs)
67 | getErased env = go env [<] where
69 | go : Env tm vars -> SizeOf seen -> List (Var (seen <>> vars))
72 | = if isErased (multiplicity b)
73 | then mkVarChiply p :: go bs (p :< _)
77 | data IsDefined : Name -> Scope -> Type where
78 | MkIsDefined : {idx : Nat} -> RigCount -> (0 p : IsVar n idx vars) ->
82 | defined : {vars : _} ->
83 | (n : Name) -> Env Term vars ->
84 | Maybe (IsDefined n vars)
85 | defined n [] = Nothing
86 | defined {vars = x :: xs} n (b :: env)
87 | = case nameEq n x of
88 | Nothing => do MkIsDefined rig prf <- defined n env
89 | pure (MkIsDefined rig (Later prf))
90 | Just Refl => Just (MkIsDefined (multiplicity b) First)
95 | bindEnv : {vars : _} -> FC -> Env Term vars -> (tm : Term vars) -> ClosedTerm
96 | bindEnv loc [] tm = tm
97 | bindEnv loc (b :: env) tm
98 | = bindEnv loc env (Bind loc _ (PVar (binderLoc b)
101 | (binderType b)) tm)
103 | revOnto : (xs, vs : List a) -> reverseOnto xs vs = reverse vs ++ xs
104 | revOnto xs [] = Refl
105 | revOnto xs (v :: vs)
106 | = rewrite revOnto (v :: xs) vs in
107 | rewrite appendAssociative (reverse vs) [v] xs in
108 | rewrite revOnto [v] vs in Refl
115 | getBinderUnder : Weaken tm =>
116 | {vars : _} -> {idx : Nat} ->
118 | (0 p : IsVar x idx vars) -> Env tm vars ->
119 | Binder (tm (reverseOnto vars ns))
120 | getBinderUnder {idx = Z} {vars = v :: vs} ns First (b :: env)
121 | = rewrite revOnto vs (v :: ns) in map (weakenNs (reverse (mkSizeOf (v :: ns)))) b
122 | getBinderUnder {idx = S k} {vars = v :: vs} ns (Later lp) (b :: env)
123 | = getBinderUnder (v :: ns) lp env
126 | getBinder : Weaken tm =>
127 | {vars : _} -> {idx : Nat} ->
128 | (0 p : IsVar x idx vars) -> Env tm vars -> Binder (tm vars)
129 | getBinder el env = getBinderUnder Scope.empty el env
134 | getBinderLoc : {vars : _} -> {idx : Nat} -> (0 p : IsVar x idx vars) -> Env tm vars -> FC
135 | getBinderLoc {idx = Z} First (b :: _) = binderLoc b
136 | getBinderLoc {idx = S k} (Later p) (_ :: env) = getBinderLoc p env
142 | abstractEnvType : {vars : _} ->
143 | FC -> Env Term vars -> (tm : Term vars) -> ClosedTerm
144 | abstractEnvType fc [] tm = tm
145 | abstractEnvType fc (Let fc' c val ty :: env) tm
146 | = abstractEnvType fc env (Bind fc _ (Let fc' c val ty) tm)
147 | abstractEnvType fc (Pi fc' c e ty :: env) tm
148 | = abstractEnvType fc env (Bind fc _ (Pi fc' c e ty) tm)
149 | abstractEnvType fc (b :: env) tm
150 | = let bnd = Pi (binderLoc b) (multiplicity b) Explicit (binderType b)
151 | in abstractEnvType fc env (Bind fc _ bnd tm)
155 | abstractEnv : {vars : _} ->
156 | FC -> Env Term vars -> (tm : Term vars) -> ClosedTerm
157 | abstractEnv fc [] tm = tm
158 | abstractEnv fc (Let fc' c val ty :: env) tm
159 | = abstractEnv fc env (Bind fc _ (Let fc' c val ty) tm)
160 | abstractEnv fc (b :: env) tm
161 | = let bnd = Lam (binderLoc b) (multiplicity b) Explicit (binderType b)
162 | in abstractEnv fc env (Bind fc _ bnd tm)
166 | abstractFullEnvType : {vars : _} ->
167 | FC -> Env Term vars -> (tm : Term vars) -> ClosedTerm
168 | abstractFullEnvType fc [] tm = tm
169 | abstractFullEnvType fc (Pi fc' c e ty :: env) tm
170 | = abstractFullEnvType fc env (Bind fc _ (Pi fc' c e ty) tm)
171 | abstractFullEnvType fc (b :: env) tm
172 | = let bnd = Pi fc (multiplicity b) Explicit (binderType b)
173 | in abstractFullEnvType fc env (Bind fc _ bnd tm)
176 | mkExplicit : Env Term vs -> Env Term vs
177 | mkExplicit [] = Env.empty
178 | mkExplicit (Pi fc c _ ty :: env) = Pi fc c Explicit ty :: mkExplicit env
179 | mkExplicit (b :: env) = b :: mkExplicit env
182 | letToLam : Env Term vars -> Env Term vars
184 | letToLam (Let fc c val ty :: env) = Lam fc c Explicit ty :: letToLam env
185 | letToLam (b :: env) = b :: letToLam env
188 | findUsed : {vars : _} ->
189 | Env Term vars -> VarSet vars -> Term vars -> VarSet vars
190 | findUsed env used (Local fc r idx p)
191 | = let v := MkVar p in
194 | else assert_total (findUsedInBinder env (VarSet.insert v used)
196 | findUsed env used (Meta _ _ _ args)
197 | = findUsedArgs env used args
199 | findUsedArgs : Env Term vars -> VarSet vars -> List (Term vars) -> VarSet vars
200 | findUsedArgs env u [] = u
201 | findUsedArgs env u (a :: as)
202 | = findUsedArgs env (findUsed env u a) as
203 | findUsed env used (Bind fc x b tm)
205 | VarSet.dropFirst (findUsed (b :: env)
206 | (weaken {tm = VarSet} (findUsedInBinder env used b))
208 | findUsed env used (App fc fn arg)
209 | = findUsed env (findUsed env used fn) arg
210 | findUsed env used (As fc s a p)
211 | = findUsed env (findUsed env used a) p
212 | findUsed env used (TDelayed fc r tm)
213 | = findUsed env used tm
214 | findUsed env used (TDelay fc r ty tm)
215 | = findUsed env (findUsed env used ty) tm
216 | findUsed env used (TForce fc r tm)
217 | = findUsed env used tm
218 | findUsed env used (Erased fc (Dotted tm))
219 | = findUsed env used tm
220 | findUsed env used _ = used
222 | findUsedInBinder : {vars : _} ->
223 | Env Term vars -> VarSet vars ->
224 | Binder (Term vars) -> VarSet vars
225 | findUsedInBinder env used (Let _ _ val ty)
226 | = findUsed env (findUsed env used val) ty
227 | findUsedInBinder env used (PLet _ _ val ty)
228 | = findUsed env (findUsed env used val) ty
229 | findUsedInBinder env used b = findUsed env used (binderType b)
232 | findUsedLocs : {vars : _} ->
233 | Env Term vars -> Term vars -> VarSet vars
234 | findUsedLocs env tm = findUsed env VarSet.empty tm
236 | mkShrinkSub : {n : _} ->
237 | (vars : _) -> VarSet (n :: vars) ->
238 | (
newvars ** Thin newvars (n :: vars))
240 | = if first `VarSet.elem` els
241 | then (
_ ** Keep Refl)
242 | else (
_ ** Drop Refl)
243 | mkShrinkSub (x :: xs) els
244 | = let (
_ ** subRest)
= mkShrinkSub xs (VarSet.dropFirst els) in
245 | if first `VarSet.elem` els
246 | then (
_ ** Keep subRest)
247 | else (
_ ** Drop subRest)
249 | mkShrink : {vars : _} ->
251 | (
newvars ** Thin newvars vars)
252 | mkShrink {vars = []} xs = (
_ ** Refl)
253 | mkShrink {vars = v :: vs} xs = mkShrinkSub _ xs
258 | findSubEnv : {vars : _} ->
259 | Env Term vars -> Term vars ->
260 | (vars' : Scope ** Thin vars' vars)
261 | findSubEnv env tm = mkShrink (findUsedLocs env tm)
264 | shrinkEnv : Env Term vars -> Thin newvars vars -> Maybe (Env Term newvars)
265 | shrinkEnv env Refl = Just env
266 | shrinkEnv (b :: env) (Drop p) = shrinkEnv env p
267 | shrinkEnv (b :: env) (Keep p)
268 | = do env' <- shrinkEnv env p
269 | b' <- assert_total (shrinkBinder b p)
273 | mkEnvOnto : FC -> (xs : List Name) -> Env Term ys -> Env Term (xs ++ ys)
274 | mkEnvOnto fc [] vs = vs
275 | mkEnvOnto fc (n :: ns) vs
276 | = PVar fc top Explicit (Erased fc Placeholder)
277 | :: mkEnvOnto fc ns vs
283 | mkEnv : FC -> (vs : Scope) -> Env Term vs
285 | mkEnv fc (n :: ns) = PVar fc top Explicit (Erased fc Placeholder) :: mkEnv fc ns
292 | uniqifyEnv : {vars : _} ->
294 | (
vars' ** (Env Term vars', CompatibleVars vars vars'))
295 | uniqifyEnv env = uenv [] env
297 | next : Name -> Name
298 | next (MN n i) = MN n (i + 1)
299 | next (UN n) = MN (displayUserName n) 0
300 | next (NS ns n) = NS ns (next n)
301 | next n = MN (show n) 0
303 | uniqueLocal : List Name -> Name -> Name
311 | then assert_total (uniqueLocal vs (next n))
314 | uenv : {vars : _} ->
315 | List Name -> Env Term vars ->
316 | (
vars' ** (Env Term vars', CompatibleVars vars vars'))
317 | uenv used [] = (
[] ** ([], Pre))
318 | uenv used {vars = v :: vs} (b :: bs)
320 | then let v' = uniqueLocal used v
321 | (
vs' ** (env', compat))
= uenv (v' :: used) bs
322 | b' = map (compatNs compat) b in
323 | (
v' :: vs' ** (b' :: env', Ext compat))
324 | else let (
vs' ** (env', compat))
= uenv (v :: used) bs
325 | b' = map (compatNs compat) b in
326 | (
v :: vs' ** (b' :: env', Ext compat))
329 | allVars : {0 vars : _} -> Env Term vars -> List (Var vars)
330 | allVars env = go env [<] where
332 | go : {0 vars : _} -> Env Term vars ->
333 | {0 seen : SnocList Name} -> SizeOf seen ->
334 | List (Var (seen <>> vars))
336 | go (v :: vs) p = mkVarChiply p :: go vs (p :< _)
340 | allVarsNoLet : {0 vars : _} -> Env Term vars -> List (Var vars)
341 | allVarsNoLet env = go env [<] where
343 | go : {0 vars : _} -> Env Term vars ->
344 | {0 seen : SnocList Name} -> SizeOf seen ->
345 | List (Var (seen <>> vars))
347 | go (Let _ _ _ _ :: vs) p = go vs (p :< _)
348 | go (v :: vs) p = mkVarChiply p :: go vs (p :< _)
351 | close : FC -> String -> Env Term vars -> Term vars -> ClosedTerm
353 | = let (s, env) = mkSubstEnv 0 env in
354 | substs s env (rewrite appendNilRightNeutral vars in tm)
357 | mkSubstEnv : Int -> Env Term vs -> (SizeOf vs, SubstEnv vs Scope.empty)
358 | mkSubstEnv i [] = (zero, Subst.empty)
359 | mkSubstEnv i (v :: vs)
360 | = let (s, env) = mkSubstEnv (i + 1) vs in
361 | (suc s, Ref fc Bound (MN nm i) :: env)