0 | module TTImp.Elab.Utils
2 | import Core.Case.CaseTree
5 | import Core.Normalise
8 | import TTImp.Elab.Check
11 | import Libraries.Data.NatSet
12 | import Libraries.Data.VarSet
14 | import Libraries.Data.List.SizeOf
18 | detagSafe : {auto c : Ref Ctxt Defs} ->
19 | Defs -> ClosedNF -> Core Bool
20 | detagSafe defs (NTCon _ n _ args)
21 | = do Just (TCon _ _ _ _ _ _ (Just detags)) <- lookupDefExact n (gamma defs)
23 | args' <- traverse (evalClosure defs . snd) args
24 | pure $
NatSet.isEmpty detags || notErased 0 detags args'
28 | notErased : Nat -> NatSet -> List ClosedNF -> Bool
29 | notErased i ns [] = False
30 | notErased i ns (NErased _ Impossible :: rest)
31 | = notErased (i + 1) ns rest
32 | notErased i ns (_ :: rest)
33 | = elem i ns || notErased (i + 1) ns rest
34 | detagSafe defs _ = pure False
36 | findErasedFrom : {auto c : Ref Ctxt Defs} ->
37 | Defs -> Nat -> ClosedNF -> Core (NatSet, NatSet)
38 | findErasedFrom defs pos (NBind fc x (Pi _ c _ aty) scf)
42 | sc <- scf defs (toClosure defaultOpts Env.empty (Erased fc (ifThenElse (isErased c) Impossible Placeholder)))
43 | (erest, dtrest) <- findErasedFrom defs (1 + pos) sc
44 | let dt' = if !(detagSafe defs !(evalClosure defs aty))
45 | then (insert pos dtrest) else dtrest
46 | pure $
if isErased c
47 | then (insert pos erest, dt')
49 | findErasedFrom defs pos tm = pure (NatSet.empty, NatSet.empty)
54 | findErased : {auto c : Ref Ctxt Defs} ->
55 | ClosedTerm -> Core (NatSet, NatSet)
57 | = do defs <- get Ctxt
58 | tmnf <- nf defs Env.empty tm
59 | findErasedFrom defs 0 tmnf
62 | updateErasable : {auto c : Ref Ctxt Defs} ->
65 | = do defs <- get Ctxt
66 | Just gdef <- lookupCtxtExact n (gamma defs)
67 | | Nothing => pure ()
68 | (es, dtes) <- findErased (type gdef)
71 | safeErase := dtes } gdef
74 | wrapErrorC : List ElabOpt -> (Error -> Error) -> Core a -> Core a
76 | = if InCase `elem` opts
80 | plicit : Binder (Term vars) -> PiInfo RawImp
81 | plicit (Pi _ _ p _) = forgetDef p
82 | plicit (PVar _ _ p _) = forgetDef p
86 | bindNotReq : {vs : _} ->
87 | FC -> Int -> Env Term vs -> (sub : Thin pre vs) ->
88 | List (PiInfo RawImp, Name) ->
89 | Term vs -> (List (PiInfo RawImp, Name), Term pre)
90 | bindNotReq fc i [] Refl ns tm = (ns, embed tm)
91 | bindNotReq fc i (b :: env) Refl ns tm
92 | = let tmptm = subst (Ref fc Bound (MN "arg" i)) tm
93 | (ns', btm) = bindNotReq fc (1 + i) env Refl ns tmptm in
94 | (ns', refToLocal (MN "arg" i) _ btm)
95 | bindNotReq fc i (b :: env) (Keep p) ns tm
96 | = let tmptm = subst (Ref fc Bound (MN "arg" i)) tm
97 | (ns', btm) = bindNotReq fc (1 + i) env p ns tmptm in
98 | (ns', refToLocal (MN "arg" i) _ btm)
99 | bindNotReq {vs = n :: _} fc i (b :: env) (Drop p) ns tm
100 | = bindNotReq fc i env p ((plicit b, n) :: ns)
101 | (Bind fc _ (Pi (binderLoc b) (multiplicity b) Explicit (binderType b)) tm)
104 | bindReq : {vs : _} ->
105 | FC -> Env Term vs -> (sub : Thin pre vs) ->
106 | List (PiInfo RawImp, Name) ->
107 | Term pre -> Maybe (List (PiInfo RawImp, Name), List Name, ClosedTerm)
108 | bindReq {vs} fc env Refl ns tm
109 | = pure (ns, notLets [] _ env, abstractEnvType fc env tm)
111 | notLets : List Name -> (vars : Scope) -> Env Term vars -> List Name
112 | notLets acc [] _ = acc
113 | notLets acc (v :: vs) (b :: env) = if isLet b then notLets acc vs env
114 | else notLets (v :: acc) vs env
115 | bindReq {vs = n :: _} fc (b :: env) (Keep p) ns tm
116 | = do b' <- shrinkBinder b p
117 | bindReq fc env p ((plicit b, n) :: ns)
118 | (Bind fc _ (Pi (binderLoc b) (multiplicity b) Explicit (binderType b')) tm)
119 | bindReq fc (b :: env) (Drop p) ns tm
120 | = bindReq fc env p ns tm
126 | data ArgUsed = Used1
130 | record Usage (vs : Scope) where
131 | constructor MkUsage
132 | isUsedSet : VarSet vs
133 | isLocalSet : VarSet vs
135 | initUsed : Usage vs
137 | { isUsedSet = VarSet.empty
138 | , isLocalSet = VarSet.empty
141 | initUsedCase : SizeOf vs -> Usage vs
142 | initUsedCase p = MkUsage
143 | { isUsedSet = VarSet.empty
144 | , isLocalSet = maybe id VarSet.delete (last p) (VarSet.full p)
147 | setUsedVar : Var vs -> Usage vs -> Usage vs
148 | setUsedVar v us@(MkUsage isUsedSet isLocalSet)
150 | if v `VarSet.elem` isLocalSet then us
152 | else MkUsage { isUsedSet = VarSet.insert v isUsedSet
155 | isUsed : Var vs -> Usage vs -> Bool
156 | isUsed v us = v `VarSet.elem` isUsedSet us
158 | data Used : Type where
160 | setUsed : {auto u : Ref Used (Usage vars)} ->
161 | Var vars -> Core ()
162 | setUsed p = update Used $
setUsedVar p
164 | extendUsed : ArgUsed -> SizeOf inner -> Usage vars -> Usage (inner ++ vars)
165 | extendUsed LocalVar p (MkUsage iu il)
166 | = MkUsage (weakenNs {tm = VarSet} p iu) (append p (full p) il)
167 | extendUsed Used0 p (MkUsage iu il)
168 | = MkUsage (weakenNs {tm = VarSet} p iu) (weakenNs {tm = VarSet} p il)
169 | extendUsed Used1 p (MkUsage iu il)
170 | = MkUsage (append p (full p) iu) (weakenNs {tm = VarSet} p il)
172 | dropUsed : SizeOf inner -> Usage (inner ++ vars) -> Usage vars
173 | dropUsed p (MkUsage iu il) = MkUsage (VarSet.dropInner p iu) (dropInner p il)
175 | inExtended : ArgUsed -> SizeOf new ->
176 | {auto u : Ref Used (Usage vars)} ->
177 | (Ref Used (Usage (new ++ vars)) -> Core a) ->
179 | inExtended a new sc
180 | = do used <- get Used
181 | u' <- newRef Used (extendUsed a new used)
183 | put Used (dropUsed new !(get Used @{u'}))
186 | 0 InlineSafe : Scoped -> Type
188 | = {0 vars : Scope} -> {auto u : Ref Used (Usage vars)} ->
189 | tm vars -> Core Bool
191 | termsInlineSafe : InlineSafe (List . Term)
193 | termInlineSafe : InlineSafe Term
194 | termInlineSafe (Local fc isLet idx p)
195 | = let v := MkVar p in
196 | if isUsed v !(get Used)
200 | termInlineSafe (Meta fc x y xs)
201 | = termsInlineSafe xs
202 | termInlineSafe (Bind fc x b scope)
203 | = do bok <- binderInlineSafe b
205 | then inExtended LocalVar (suc zero) (\u' => termInlineSafe scope)
208 | binderInlineSafe : Binder (Term vars) -> Core Bool
209 | binderInlineSafe (Let _ _ val _) = termInlineSafe val
210 | binderInlineSafe _ = pure True
211 | termInlineSafe (App fc fn arg)
212 | = do fok <- termInlineSafe fn
214 | then termInlineSafe arg
216 | termInlineSafe (As fc x as pat) = termInlineSafe pat
217 | termInlineSafe (TDelayed fc x ty) = termInlineSafe ty
218 | termInlineSafe (TDelay fc x ty arg) = termInlineSafe arg
219 | termInlineSafe (TForce fc x val) = termInlineSafe val
220 | termInlineSafe _ = pure True
222 | termsInlineSafe [] = pure True
223 | termsInlineSafe (x :: xs)
224 | = do xok <- termInlineSafe x
226 | then termsInlineSafe xs
230 | caseInlineSafe : InlineSafe CaseTree
231 | caseInlineSafe (Case idx p scTy xs)
232 | = let v := MkVar p in
233 | if isUsed v !(get Used)
236 | caseAltsInlineSafe xs
237 | caseInlineSafe (STerm x tm) = termInlineSafe tm
238 | caseInlineSafe (Unmatched msg) = pure True
239 | caseInlineSafe Impossible = pure True
241 | caseAltsInlineSafe : InlineSafe (List . CaseAlt)
242 | caseAltsInlineSafe [] = pure True
243 | caseAltsInlineSafe (a :: as)
245 | True <- caseAltInlineSafe a
246 | | False => pure False
250 | caseAltsInlineSafe as
252 | caseAltInlineSafe : InlineSafe CaseAlt
253 | caseAltInlineSafe (ConCase x tag args sc)
255 | = inExtended Used0 (mkSizeOf args) (\u' => caseInlineSafe sc)
256 | caseAltInlineSafe (DelayCase ty arg sc)
258 | = inExtended Used0 (mkSizeOf [ty, arg]) (\u' => caseInlineSafe sc)
259 | caseAltInlineSafe (ConstCase x sc) = caseInlineSafe sc
260 | caseAltInlineSafe (DefaultCase sc) = caseInlineSafe sc
266 | inlineSafe : CaseTree vars -> Core Bool
268 | = do u <- newRef Used initUsed
272 | canInlineDef : {auto c : Ref Ctxt Defs} ->
275 | = do defs <- get Ctxt
276 | Just (PMDef _ _ _ rtree _) <- lookupDefExact n (gamma defs)
284 | canInlineCaseBlock : {auto c : Ref Ctxt Defs} ->
286 | canInlineCaseBlock n
287 | = do defs <- get Ctxt
288 | Just (PMDef _ vars _ rtree _) <- lookupDefExact n (gamma defs)
290 | u <- newRef Used (initUsedCase (mkSizeOf vars))
291 | caseInlineSafe rtree