0 | module TTImp.ProcessDef
2 | import Core.Case.CaseBuilder
3 | import Core.Case.CaseTree
4 | import Core.Case.CaseTree.Pretty
8 | import Core.LinearCheck
10 | import Core.Termination
11 | import Core.Termination.CallGraph
12 | import Core.Transform
14 | import Core.UnifyState
16 | import Idris.REPL.Opts
18 | import Idris.Pretty.Annotations
20 | import TTImp.BindImplicits
22 | import TTImp.Elab.Binders
23 | import TTImp.Elab.Check
24 | import TTImp.Elab.Utils
25 | import TTImp.Impossible
26 | import TTImp.PartialEval
28 | import TTImp.TTImp.Functor
29 | import TTImp.ProcessType
31 | import TTImp.WithClause
37 | import Libraries.Data.NameMap
38 | import Libraries.Data.WithDefault
39 | import Libraries.Text.PrettyPrint.Prettyprinter
40 | import Libraries.Data.List.SizeOf
45 | mismatchNF : {auto c : Ref Ctxt Defs} ->
47 | Defs -> NF vars -> NF vars -> Core Bool
48 | mismatchNF defs (NTCon _ xn _ xargs) (NTCon _ yn _ yargs)
51 | else anyM (mismatch defs) (zipWith (curry $
mapHom snd) xargs yargs)
52 | mismatchNF defs (NDCon _ _ xt _ xargs) (NDCon _ _ yt _ yargs)
55 | else anyM (mismatch defs) (zipWith (curry $
mapHom snd) xargs yargs)
56 | mismatchNF defs (NPrimVal _ xc) (NPrimVal _ yc) = pure (xc /= yc)
57 | mismatchNF defs (NDelayed _ _ x) (NDelayed _ _ y) = mismatchNF defs x y
58 | mismatchNF defs (NDelay _ _ _ x) (NDelay _ _ _ y)
59 | = mismatchNF defs !(evalClosure defs x) !(evalClosure defs y)
62 | mismatchNF defs (NPrimVal {}) (NDCon {}) = pure True
63 | mismatchNF defs (NDCon {}) (NPrimVal {}) = pure True
64 | mismatchNF defs (NPrimVal {}) (NBind {}) = pure True
65 | mismatchNF defs (NBind {}) (NPrimVal {}) = pure True
66 | mismatchNF defs (NPrimVal {}) (NTCon {}) = pure True
67 | mismatchNF defs (NTCon {}) (NPrimVal {}) = pure True
68 | mismatchNF defs (NPrimVal {}) (NType {}) = pure True
69 | mismatchNF defs (NType {}) (NPrimVal {}) = pure True
72 | mismatchNF defs (NTCon {}) (NBind {}) = pure True
73 | mismatchNF defs (NBind {}) (NTCon {}) = pure True
74 | mismatchNF defs (NTCon {}) (NType {}) = pure True
75 | mismatchNF defs (NType {}) (NTCon {}) = pure True
78 | mismatchNF defs (NBind {}) (NType {}) = pure True
79 | mismatchNF defs (NType {}) (NBind {}) = pure True
81 | mismatchNF _ _ _ = pure False
83 | mismatch : {auto c : Ref Ctxt Defs} ->
85 | Defs -> (Closure vars, Closure vars) -> Core Bool
86 | mismatch defs (x, y)
87 | = mismatchNF defs !(evalClosure defs x) !(evalClosure defs y)
93 | impossibleOK : {auto c : Ref Ctxt Defs} ->
95 | Defs -> NF vars -> NF vars -> Core Bool
96 | impossibleOK defs (NTCon _ xn xa xargs) (NTCon _ yn ya yargs)
99 | else anyM (mismatch defs) (zipWith (curry $
mapHom snd) xargs yargs)
101 | impossibleOK defs (NDCon _ _ xt _ xargs) (NDCon _ _ yt _ yargs)
104 | else anyM (mismatch defs) (zipWith (curry $
mapHom snd) xargs yargs)
105 | impossibleOK defs (NPrimVal _ x) (NPrimVal _ y) = pure (x /= y)
108 | impossibleOK defs (NPrimVal {}) (NDCon {}) = pure True
109 | impossibleOK defs (NDCon {}) (NPrimVal {}) = pure True
110 | impossibleOK defs (NPrimVal {}) (NBind {}) = pure True
111 | impossibleOK defs (NBind {}) (NPrimVal {}) = pure True
112 | impossibleOK defs (NPrimVal {}) (NTCon {}) = pure True
113 | impossibleOK defs (NTCon {}) (NPrimVal {}) = pure True
114 | impossibleOK defs (NPrimVal {}) (NType {}) = pure True
115 | impossibleOK defs (NType {}) (NPrimVal {}) = pure True
118 | impossibleOK defs (NTCon {}) (NBind {}) = pure True
119 | impossibleOK defs (NBind {}) (NTCon {}) = pure True
120 | impossibleOK defs (NTCon {}) (NType {}) = pure True
121 | impossibleOK defs (NType {}) (NTCon {}) = pure True
124 | impossibleOK defs (NBind {}) (NType {}) = pure True
125 | impossibleOK defs (NType {}) (NBind {}) = pure True
127 | impossibleOK defs x y = pure False
130 | impossibleErrOK : {auto c : Ref Ctxt Defs} ->
131 | Defs -> Error -> Core Bool
132 | impossibleErrOK defs (CantConvert fc gam env l r)
133 | = do let defs = { gamma := gam } defs
134 | impossibleOK defs !(nf defs env l)
136 | impossibleErrOK defs (CantSolveEq fc gam env l r)
137 | = do let defs = { gamma := gam } defs
138 | impossibleOK defs !(nf defs env l)
140 | impossibleErrOK defs (CyclicMeta {}) = pure True
141 | impossibleErrOK defs (AllFailed errs)
142 | = allM (impossibleErrOK defs) (map snd errs)
143 | impossibleErrOK defs (WhenUnifying _ _ _ _ _ err)
144 | = impossibleErrOK defs err
145 | impossibleErrOK defs ImpossibleCase = pure True
146 | impossibleErrOK defs _ = pure False
154 | extendEnv : {vars : _} ->
155 | Env Term vars -> Thin inner vars ->
156 | NestedNames vars ->
157 | Term vars -> Term vars ->
160 | Env Term vars', NestedNames vars',
161 | Term vars', Term vars'))
162 | extendEnv env p nest (Bind _ n (PVar fc c pi tmty) sc) (Bind _ n' (PVTy {}) tysc) with (nameEq n n')
163 | extendEnv env p nest (Bind _ n (PVar fc c pi tmty) sc) (Bind _ n' (PVTy {}) tysc) | Nothing
164 | = throw (InternalError "Can't happen: names don't match in pattern type")
165 | extendEnv env p nest (Bind _ n (PVar fc c pi tmty) sc) (Bind _ n (PVTy {}) tysc) | (Just Refl)
166 | = extendEnv (PVar fc c pi tmty :: env) (Drop p) (weaken (dropName n nest)) sc tysc
167 | extendEnv env p nest (Bind _ n (PLet fc c tmval tmty) sc) (Bind _ n' (PLet {}) tysc) with (nameEq n n')
168 | extendEnv env p nest (Bind _ n (PLet fc c tmval tmty) sc) (Bind _ n' (PLet {}) tysc) | Nothing
169 | = throw (InternalError "Can't happen: names don't match in pattern type")
171 | extendEnv env p nest (Bind _ n (PLet fc c tmval tmty) sc) (Bind _ n (PLet {}) tysc) | (Just Refl)
172 | = extendEnv (Let fc c tmval tmty :: env) (Drop p) (weaken (dropName n nest)) sc tysc
173 | extendEnv env p nest tm ty
174 | = pure (
_ ** (p, env, nest, tm, ty))
182 | findLinear : {vars : _} ->
183 | {auto c : Ref Ctxt Defs} ->
184 | Bool -> Nat -> RigCount -> Term vars ->
185 | Core (List (Name, RigCount))
186 | findLinear top bound rig (Bind fc n b sc)
187 | = findLinear top (S bound) rig sc
188 | findLinear top bound rig (As fc _ _ p)
189 | = findLinear top bound rig p
190 | findLinear top bound rig tm
191 | = case getFnArgs tm of
192 | (Ref _ _ n, []) => pure []
194 | => do defs <- get Ctxt
195 | Just nty <- lookupTyExact n (gamma defs)
196 | | Nothing => pure []
197 | findLinArg (accessible nt rig) !(nf defs Env.empty nty) args
200 | accessible : NameType -> RigCount -> RigCount
201 | accessible Func r = if top then r else erased
204 | findLinArg : {vars : _} ->
205 | RigCount -> ClosedNF -> List (Term vars) ->
206 | Core (List (Name, RigCount))
207 | findLinArg rig ty@(NBind _ _ (Pi _ c _ _) _) (As fc u a p :: as)
210 | UseLeft => findLinArg rig ty (p :: as)
211 | UseRight => findLinArg rig ty (a :: as)
212 | else pure $
!(findLinArg rig ty [a]) ++ !(findLinArg rig ty (p :: as))
213 | findLinArg rig (NBind _ x (Pi _ c _ _) sc) (Local {name=a} fc _ idx prf :: as)
214 | = do defs <- get Ctxt
217 | then do sc' <- sc defs (toClosure defaultOpts Env.empty (Ref fc Bound x))
218 | pure $
(a, rigMult c rig) ::
219 | !(findLinArg rig sc' as)
220 | else do sc' <- sc defs (toClosure defaultOpts Env.empty (Ref fc Bound x))
221 | findLinArg rig sc' as
222 | findLinArg rig (NBind fc x (Pi _ c _ _) sc) (a :: as)
223 | = do defs <- get Ctxt
224 | pure $
!(findLinear False bound (c |*| rig) a) ++
225 | !(findLinArg rig !(sc defs (toClosure defaultOpts Env.empty (Ref fc Bound x))) as)
226 | findLinArg rig ty (a :: as)
227 | = pure $
!(findLinear False bound rig a) ++ !(findLinArg rig ty as)
228 | findLinArg _ _ [] = pure []
230 | setLinear : List (Name, RigCount) -> Term vars -> Term vars
231 | setLinear vs tm@(Bind fc x b sc)
232 | = if isPatternBinder b
233 | then let b' = maybe b (setMultiplicity b) (lookup x vs)
234 | in Bind fc x b' (setLinear vs sc)
237 | isPatternBinder : Binder a -> Bool
238 | isPatternBinder (PVar {}) = True
239 | isPatternBinder (PVTy {}) = True
240 | isPatternBinder (PLet {}) = True
241 | isPatternBinder _ = False
242 | setLinear vs tm = tm
248 | combineLinear : FC -> List (Name, RigCount) ->
249 | Core (List (Name, RigCount))
250 | combineLinear loc [] = pure []
251 | combineLinear loc ((n, count) :: cs)
252 | = case lookupAll n cs of
253 | [] => pure $
(n, count) :: !(combineLinear loc cs)
254 | counts => do count' <- combineAll count counts
255 | pure $
(n, count') ::
256 | !(combineLinear loc (filter notN cs))
258 | notN : (Name, RigCount) -> Bool
259 | notN (n', _) = n /= n'
261 | lookupAll : Name -> List (Name, RigCount) -> List RigCount
262 | lookupAll n [] = []
263 | lookupAll n ((n', c) :: cs)
264 | = if n == n' then c :: lookupAll n cs else lookupAll n cs
267 | combine : RigCount -> RigCount -> Core RigCount
268 | combine l r = if l |+| r == top && not (isErased $
l `glb` r) && (l `glb` r) /= top
269 | then throw (LinearUsed loc 2 n)
272 | else pure (l `lub` r)
274 | combineAll : RigCount -> List RigCount -> Core RigCount
275 | combineAll c [] = pure c
276 | combineAll c (c' :: cs)
277 | = do newc <- combine c c'
281 | checkLHS : {vars : _} ->
282 | {auto c : Ref Ctxt Defs} ->
283 | {auto m : Ref MD Metadata} ->
284 | {auto u : Ref UST UState} ->
285 | {auto s : Ref Syn SyntaxInfo} ->
286 | {auto o : Ref ROpts REPLOpts} ->
288 | (mult : RigCount) ->
289 | Int -> List ElabOpt -> NestedNames vars -> Env Term vars ->
292 | (
vars' ** (Thin vars vars',
293 | Env Term vars', NestedNames vars',
294 | Term vars', Term vars'))
)
295 | checkLHS {vars} trans mult n opts nest env fc lhs_in
296 | = do defs <- get Ctxt
297 | logRaw "declare.def.lhs" 30 "Raw LHS: " lhs_in
298 | lhs_raw <- if trans
300 | else lhsInCurrentNS nest lhs_in
301 | logRaw "declare.def.lhs" 30 "Raw LHS in current NS: " lhs_raw
303 | autoimp <- isUnboundImplicits
304 | setUnboundImplicits True
305 | (_, lhs_bound) <- bindNames False lhs_raw
306 | setUnboundImplicits autoimp
307 | logRaw "declare.def.lhs" 30 "Raw LHS with implicits bound" lhs_bound
310 | then pure lhs_bound
311 | else implicitsAs n defs vars lhs_bound
313 | logC "declare.def.lhs" 5 $
do pure $
"Checking LHS of " ++ show !(getFullName (Resolved n))
316 | log "declare.def.lhs" 10 $
show lhs
317 | logEnv "declare.def.lhs" 5 "In env" env
318 | let lhsMode = if trans
322 | wrapErrorC opts (InLHS fc !(getFullName (Resolved n))) $
323 | elabTerm n lhsMode opts nest env
324 | (IBindHere fc PATTERN lhs) Nothing
325 | logTerm "declare.def.lhs" 5 "Checked LHS term" lhstm
326 | lhsty <- getTerm lhstyg
329 | let lhsenv = letToLam env
334 | lhstm <- normaliseHoles defs lhsenv lhstm
335 | lhsty <- normaliseHoles defs env lhsty
336 | linvars_in <- findLinear True 0 linear lhstm
337 | logTerm "declare.def.lhs" 10 "Checked LHS term after normalise" lhstm
338 | log "declare.def.lhs" 5 $
"Linearity of names in " ++ show n ++ ": " ++
341 | linvars <- combineLinear fc linvars_in
342 | let lhstm_lin = setLinear linvars lhstm
343 | let lhsty_lin = setLinear linvars lhsty
345 | logTerm "declare.def.lhs" 3 "LHS term" lhstm_lin
346 | logTerm "declare.def.lhs" 5 "LHS type" lhsty_lin
347 | setHoleLHS (bindEnv fc env lhstm_lin)
349 | ext <- extendEnv env Refl nest lhstm_lin lhsty_lin
357 | hasEmptyPat : {vars : _} ->
358 | {auto c : Ref Ctxt Defs} ->
359 | Defs -> Env Term vars -> Term vars -> Core Bool
360 | hasEmptyPat defs env (Bind fc x b sc)
361 | = pure $
!(isEmpty defs env !(nf defs env (binderType b)))
362 | || !(hasEmptyPat defs (b :: env) sc)
363 | hasEmptyPat defs env _ = pure False
366 | applyEnv : {vars : _} ->
367 | {auto c : Ref Ctxt Defs} ->
368 | Env Term vars -> Name ->
369 | Core (Name, (Maybe Name, List (Var vars), FC -> NameType -> Term vars))
370 | applyEnv env withname
371 | = do n' <- resolveName withname
372 | pure (withname, (Just withname, reverse (allVarsNoLet env),
373 | \fc, nt => applyTo fc
374 | (Ref fc nt (Resolved n')) env))
379 | checkClause : {vars : _} ->
380 | {auto c : Ref Ctxt Defs} ->
381 | {auto m : Ref MD Metadata} ->
382 | {auto u : Ref UST UState} ->
383 | {auto s : Ref Syn SyntaxInfo} ->
384 | {auto o : Ref ROpts REPLOpts} ->
385 | (mult : RigCount) -> (vis : Visibility) ->
386 | (totreq : TotalReq) -> (hashit : Bool) ->
387 | Int -> List ElabOpt -> NestedNames vars -> Env Term vars ->
388 | ImpClause -> Core (Either RawImp Clause)
389 | checkClause mult vis totreq hashit n opts nest env (ImpossibleClause fc lhs)
390 | = do lhs_raw <- lhsInCurrentNS nest lhs
392 | (do autoimp <- isUnboundImplicits
393 | setUnboundImplicits True
394 | (_, lhs) <- bindNames False lhs_raw
395 | setUnboundImplicits autoimp
397 | log "declare.def.clause.impossible" 5 $
"Checking " ++ show lhs
398 | logEnv "declare.def.clause.impossible" 5 "In env" env
400 | elabTerm n (InLHS mult) opts nest env
401 | (IBindHere fc COVERAGE lhs) Nothing
403 | lhs <- normaliseHoles defs env lhstm
404 | if !(hasEmptyPat defs env lhs)
405 | then pure (Left lhs_raw)
406 | else throw (ValidCase fc env (Left lhs)))
409 | ValidCase {} => throw err
410 | _ => do defs <- get Ctxt
411 | if !(impossibleErrOK defs err)
412 | then pure (Left lhs_raw)
413 | else throw (ValidCase fc env (Right err)))
414 | checkClause {vars} mult vis totreq hashit n opts nest env (PatClause fc lhs_in rhs)
415 | = do (_, (
vars' ** (sub', env', nest', lhstm', lhsty'))
) <-
416 | checkLHS False mult n opts nest env fc lhs_in
417 | let rhsMode = if isErased mult then InType else InExpr
418 | log "declare.def.clause" 5 $
"Checking RHS " ++ show rhs
419 | logEnv "declare.def.clause" 5 "In env" env'
421 | rhstm <- logTime 3 ("Check RHS " ++ show fc) $
422 | wrapErrorC opts (InRHS fc !(getFullName (Resolved n))) $
423 | checkTermSub n rhsMode opts nest' env' env sub' rhs (gnf env' lhsty')
426 | logTerm "declare.def.clause" 3 "RHS term" rhstm
428 | do addHashWithNames lhstm'
429 | addHashWithNames rhstm
430 | log "module.hash" 15 "Adding hash for def."
436 | addLHS (getFC lhs_in) (length env) env' lhstm'
439 | pure (Right (MkClause env' lhstm' rhstm))
441 | checkClause {vars} mult vis totreq hashit n opts nest env
442 | (WithClause ifc lhs_in rig wval_raw mprf flags cs)
443 | = do (lhs, (
vars' ** (sub', env', nest', lhspat, reqty))
) <-
444 | checkLHS False mult n opts nest env ifc lhs_in
446 | = if isErased mult || isErased rig then InType else InExpr
448 | (wval, gwvalTy) <- wrapErrorC opts (InRHS ifc !(getFullName (Resolved n))) $
449 | elabTermSub n wmode opts nest' env' env sub' wval_raw Nothing
452 | logTerm "declare.def.clause.with" 5 "With value (at quantity \{show rig})" wval
453 | logTerm "declare.def.clause.with" 3 "Required type" reqty
454 | wvalTy <- getTerm gwvalTy
456 | wval <- normaliseHoles defs env' wval
457 | wvalTy <- normaliseHoles defs env' wvalTy
459 | let (
wevars ** withSub)
= keepOldEnv sub' (snd (findSubEnv env' wval))
460 | logTerm "declare.def.clause.with" 5 "With value type" wvalTy
461 | log "declare.def.clause.with" 5 $
"Using vars " ++ show wevars
463 | let Just wval = shrink wval withSub
464 | | Nothing => throw (InternalError "Impossible happened: With abstraction failure #1")
465 | let Just wvalTy = shrink wvalTy withSub
466 | | Nothing => throw (InternalError "Impossible happened: With abstraction failure #2")
469 | let Just wvalEnv = shrinkEnv env' withSub
470 | | Nothing => throw (InternalError "Impossible happened: With abstraction failure #3")
474 | (
wargs ** (scenv, var, binder))
<- bindWithArgs rig wvalTy ((,wval) <$> mprf) wvalEnv
476 | let bnr = bindNotReq vfc 0 env' withSub [] reqty
477 | let notreqns = fst bnr
478 | let notreqty = snd bnr
480 | rdefs <- if Syntactic `elem` flags
481 | then clearDefs defs
483 | wtyScope <- replace rdefs scenv !(nf rdefs scenv (weakenNs (mkSizeOf wargs) wval))
486 | (weakenNs (mkSizeOf wargs) notreqty))
487 | let bNotReq = binder wtyScope
494 | let env' = mkExplicit env'
496 | let Just (reqns, envns, wtype) = bindReq vfc env' withSub [] bNotReq
497 | | Nothing => throw (InternalError "Impossible happened: With abstraction failure #4")
503 | = map Just reqns ++
504 | Nothing :: map Just notreqns
506 | logTerm "declare.def.clause.with" 3 "With function type" wtype
507 | log "declare.def.clause.with" 5 $
"Argument names " ++ show wargNames
509 | wname <- genWithName !(prettyName !(toFullNames (Resolved n)))
510 | widx <- addDef wname ({flags $= (SetTotal totreq ::)}
511 | (newDef vfc wname (if isErased mult then erased else top)
512 | vars wtype (specified vis) None))
514 | let toWarg : Maybe (PiInfo RawImp, Name) -> List (Maybe Name, RawImp)
515 | := flip maybe (\pn => [(Nothing, IVar vfc (snd pn))]) $
516 | (Nothing, wval_raw) ::
520 | let fc = emptyFC in
521 | let refl = IVar fc (NS builtinNS (UN $
Basic "Refl")) in
522 | [(map snd mprf, INamedApp fc refl (UN $
Basic "x") wval_raw)]
524 | let rhs_in = gapply (IVar vfc wname)
525 | $
map (\ nm => (Nothing, IVar vfc nm)) envns
526 | ++ concatMap toWarg wargNames
528 | log "declare.def.clause.with" 3 $
"Applying to with argument " ++ show rhs_in
529 | rhs <- wrapErrorC opts (InRHS ifc !(getFullName (Resolved n))) $
530 | checkTermSub n wmode opts nest' env' env sub' rhs_in
534 | cs' <- traverse (mkClauseWith 1 wname wargNames lhs) cs
535 | log "declare.def.clause.with" 3 $
"With clauses: " ++ show cs'
538 | nestname <- applyEnv env wname
539 | let nest'' = { names $= (nestname ::) } nest
541 | let wdef = IDef ifc wname cs'
542 | processDecl [] nest'' env wdef
544 | pure (Right (MkClause env' lhspat rhs))
547 | vfc = virtualiseFC ifc
550 | (rig : RigCount) -> (wvalTy : Term xs) -> Maybe ((RigCount, Name), Term xs) ->
551 | (wvalEnv : Env Term xs) ->
553 | ** ( Env Term (ext ++ xs)
555 | , (Term (ext ++ xs) -> Term xs)
557 | bindWithArgs {xs} rig wvalTy Nothing wvalEnv =
559 | wargn = MN "warg" 0
563 | scenv : Env Term (wargs ++ xs)
564 | := Pi vfc top Explicit wvalTy :: wvalEnv
566 | var : Term (wargs ++ xs)
567 | := Local vfc (Just False) Z First
569 | binder : Term (wargs ++ xs) -> Term xs
570 | := Bind vfc wargn (Pi vfc rig Explicit wvalTy)
572 | in pure (
wargs ** (scenv, var, binder))
574 | bindWithArgs {xs} rig wvalTy (Just ((rigPrf, name), wval)) wvalEnv = do
577 | let eqName = NS builtinNS (UN $
Basic "Equal")
578 | Just (TCon ar _ _ _ _ _ _) <- lookupDefExact eqName (gamma defs)
579 | | _ => throw (InternalError "Cannot find builtin Equal")
580 | let eqTyCon = Ref vfc (TyCon ar) !(toResolvedNames eqName)
583 | wargn = MN "warg" 0
585 | wargs = [name, wargn]
587 | wvalTy' := weaken wvalTy
588 | eqTy : Term (MN "warg" 0 :: xs)
589 | := apply vfc eqTyCon
593 | , Local vfc (Just False) Z First
596 | scenv : Env Term (wargs ++ xs)
597 | := Pi vfc top Implicit eqTy
598 | :: Pi vfc top Explicit wvalTy
601 | var : Term (wargs ++ xs)
602 | := Local vfc (Just False) (S Z) (Later First)
604 | binder : Term (wargs ++ xs) -> Term xs
605 | := \ t => Bind vfc wargn (Pi vfc rig Explicit wvalTy)
606 | $
Bind vfc name (Pi vfc rigPrf Implicit eqTy) t
608 | pure (
wargs ** (scenv, var, binder))
613 | keepOldEnv : {0 outer : _} -> {vs : _} ->
614 | (outprf : Thin outer vs) -> Thin vs' vs ->
615 | (vs'' : Scope ** Thin vs'' vs)
616 | keepOldEnv {vs} Refl p = (
vs ** Refl)
617 | keepOldEnv {vs} p Refl = (
vs ** Refl)
618 | keepOldEnv (Drop p) (Drop p')
619 | = let (
_ ** rest)
= keepOldEnv p p' in
621 | keepOldEnv (Drop p) (Keep p')
622 | = let (
_ ** rest)
= keepOldEnv p p' in
624 | keepOldEnv (Keep p) (Drop p')
625 | = let (
_ ** rest)
= keepOldEnv p p' in
627 | keepOldEnv (Keep p) (Keep p')
628 | = let (
_ ** rest)
= keepOldEnv p p' in
634 | mkClauseWith : (drop : Nat) -> Name ->
635 | List (Maybe (PiInfo RawImp, Name)) ->
636 | RawImp -> ImpClause ->
638 | mkClauseWith drop wname wargnames lhs (PatClause ploc patlhs rhs)
639 | = do log "declare.def.clause.with" 20 "PatClause"
640 | newlhs <- getNewLHS ploc drop nest wname wargnames lhs patlhs
641 | newrhs <- withRHS ploc drop wname wargnames rhs lhs
642 | pure (PatClause ploc newlhs newrhs)
643 | mkClauseWith drop wname wargnames lhs (WithClause ploc patlhs rig wval prf flags ws)
644 | = do log "declare.def.clause.with" 20 "WithClause"
645 | newlhs <- getNewLHS ploc drop nest wname wargnames lhs patlhs
646 | newwval <- withRHS ploc drop wname wargnames wval lhs
647 | ws' <- traverse (mkClauseWith (S drop) wname wargnames lhs) ws
648 | pure (WithClause ploc newlhs rig newwval prf flags ws')
649 | mkClauseWith drop wname wargnames lhs (ImpossibleClause ploc patlhs)
650 | = do log "declare.def.clause.with" 20 "ImpossibleClause"
651 | newlhs <- getNewLHS ploc drop nest wname wargnames lhs patlhs
652 | pure (ImpossibleClause ploc newlhs)
656 | calcRefs : {auto c : Ref Ctxt Defs} ->
657 | (runtime : Bool) -> (aTotal : Name) -> (fn : Name) -> Core ()
659 | = do defs <- get Ctxt
660 | Just gdef <- lookupCtxtExact fn (gamma defs)
662 | let PMDef r cargs tree_ct tree_rt pats = definition gdef
664 | let refs : Maybe (NameMap Bool)
665 | = if rt then refersToRuntimeM gdef else refersToM gdef
667 | | Just _ => pure ()
668 | let tree : CaseTree cargs = if rt then tree_rt else tree_ct
669 | let metas = CaseTree.getMetas tree
670 | traverse_ addToSave (keys metas)
671 | let refs_all = addRefs at metas tree
672 | refs <- ifThenElse rt
673 | (dropErased (keys refs_all) refs_all)
675 | ignore $
ifThenElse rt
676 | (addDef fn ({ refersToRuntimeM := Just refs } gdef))
677 | (addDef fn ({ refersToM := Just refs } gdef))
678 | traverse_ (calcRefs rt at) (keys refs)
680 | dropErased : List Name -> NameMap Bool -> Core (NameMap Bool)
681 | dropErased [] refs = pure refs
682 | dropErased (n :: ns) refs
683 | = do defs <- get Ctxt
684 | Just gdef <- lookupCtxtExact n (gamma defs)
685 | | Nothing => dropErased ns refs
686 | if multiplicity gdef /= erased
687 | then dropErased ns refs
688 | else dropErased ns (delete n refs)
691 | mkRunTime : {auto c : Ref Ctxt Defs} ->
692 | {auto m : Ref MD Metadata} ->
693 | {auto u : Ref UST UState} ->
694 | {auto s : Ref Syn SyntaxInfo} ->
695 | {auto o : Ref ROpts REPLOpts} ->
696 | FC -> Name -> Core ()
698 | = do logC "compile.casetree" 5 $
do pure $
"Making run time definition for " ++ show !(toFullNames n)
700 | Just gdef <- lookupCtxtExact n (gamma defs)
702 | let cov = gdef.totality.isCovering
704 | when (not (isErased $
multiplicity gdef)) $
do
705 | let PMDef r cargs tree_ct _ pats = definition gdef
710 | pats' <- traverse (toErased (location gdef) (getSpec (flags gdef)))
713 | let clauses_init = map (toClause (location gdef)) pats'
714 | clauses <- case cov of
715 | MissingCases _ => do log "compile.casetree.missing" 5 $
"Adding uncovered error to \{show clauses_init}"
716 | pure $
addErrorCase clauses_init
717 | _ => pure clauses_init
719 | (
rargs ** (tree_rt, _))
<- getPMDef (location gdef) RunTime n ty clauses
720 | logC "compile.casetree" 5 $
do
721 | tree_rt <- toFullNames tree_rt
724 | , "Runtime tree for " ++ show (fullname gdef) ++ ":"
725 | , show (indent 2 $
prettyTree tree_rt)
727 | log "compile.casetree" 10 $
show tree_rt
728 | log "compile.casetree.measure" 15 $
show (measure tree_rt)
730 | let Just Refl = scopeEq cargs rargs
731 | | Nothing => throw (InternalError "WAT")
732 | ignore $
addDef n $
733 | { definition := PMDef r rargs tree_ct tree_rt pats
737 | when (caseName !(toFullNames n) && noInline (flags gdef)) $
738 | do inl <- canInlineCaseBlock n
740 | logC "compiler.inline.eval" 5 $
do pure "Marking \{show !(toFullNames n)} for inlining in runtime case tree."
741 | setFlag fc n Inline
744 | noInline : List DefFlag -> Bool
745 | noInline (Inline :: _) = False
746 | noInline (NoInline :: _) = False
747 | noInline (x :: xs) = noInline xs
750 | caseName : Name -> Bool
751 | caseName (CaseBlock {}) = True
752 | caseName (NS _ n) = caseName n
755 | mkCrash : {vars : _} -> String -> Term vars
757 | = apply fc (Ref fc Func (UN $
Basic "prim__crash"))
758 | [Erased fc Placeholder, PrimVal fc (Str msg)]
760 | matchAny : Term vars -> Term vars
761 | matchAny (App fc f a) = App fc (matchAny f) (Erased fc Placeholder)
764 | makeErrorClause : {vars : _} -> Env Term vars -> Term vars -> Clause
765 | makeErrorClause env lhs
766 | = MkClause env (matchAny lhs)
767 | (mkCrash ("Unhandled input for " ++ show n ++ " at " ++ show fc))
769 | addErrorCase : List Clause -> List Clause
770 | addErrorCase [] = []
771 | addErrorCase [MkClause env lhs rhs]
772 | = MkClause env lhs rhs :: makeErrorClause env lhs :: []
773 | addErrorCase (x :: xs) = x :: addErrorCase xs
775 | getSpec : List DefFlag -> Maybe (List (Name, Nat))
776 | getSpec [] = Nothing
777 | getSpec (PartialEval n :: _) = Just n
778 | getSpec (x :: xs) = getSpec xs
780 | toErased : FC -> Maybe (List (Name, Nat)) ->
781 | (
vars ** (Env Term vars, Term vars, Term vars))
->
782 | Core (
vars ** (Env Term vars, Term vars, Term vars))
783 | toErased fc spec (
_ ** (env, lhs, rhs))
784 | = do lhs_erased <- linearCheck fc linear True env lhs
786 | rhs' <- applyTransforms env rhs
787 | rhs' <- applySpecialise env spec rhs'
788 | rhs_erased <- linearCheck fc linear True env rhs'
789 | pure (
_ ** (env, lhs_erased, rhs_erased))
791 | toClause : FC -> (
vars ** (Env Term vars, Term vars, Term vars))
-> Clause
792 | toClause fc (
_ ** (env, lhs, rhs))
793 | = MkClause env lhs rhs
795 | compileRunTime : {auto c : Ref Ctxt Defs} ->
796 | {auto m : Ref MD Metadata} ->
797 | {auto u : Ref UST UState} ->
798 | {auto s : Ref Syn SyntaxInfo} ->
799 | {auto o : Ref ROpts REPLOpts} ->
800 | FC -> Name -> Core ()
801 | compileRunTime fc atotal
802 | = do defs <- get Ctxt
803 | traverse_ (mkRunTime fc) (toCompileCase defs)
804 | traverse_ (calcRefs True atotal) (toCompileCase defs)
806 | update Ctxt { toCompileCase := [] }
808 | toPats : Clause -> (
vs ** (Env Term vs, Term vs, Term vs))
809 | toPats (MkClause {vars} env lhs rhs)
810 | = (
_ ** (env, lhs, rhs))
812 | warnUnreachable : {auto c : Ref Ctxt Defs} ->
814 | warnUnreachable (MkClause env lhs rhs)
815 | = recordWarning (UnreachableClause (getLoc lhs) env lhs)
817 | isAlias : RawImp -> Maybe ((FC, Name)
818 | , List (FC, (FC, Name)))
820 | = do let (hd, apps) = getFnArgs lhs []
822 | args <- traverse (isExplicit >=> bitraverse pure isIBindVar) apps
825 | lookupOrAddAlias : {vars : _} ->
826 | {auto m : Ref MD Metadata} ->
827 | {auto c : Ref Ctxt Defs} ->
828 | {auto u : Ref UST UState} ->
829 | {auto s : Ref Syn SyntaxInfo} ->
830 | {auto o : Ref ROpts REPLOpts} ->
831 | List ElabOpt -> NestedNames vars -> Env Term vars -> FC ->
832 | Name -> List ImpClause -> Core (Maybe GlobalDef)
833 | lookupOrAddAlias eopts nest env fc n [cl@(PatClause _ lhs _)]
834 | = do defs <- get Ctxt
835 | log "declare.def.alias" 20 $
"Looking at \{show cl}"
836 | Nothing <- lookupCtxtExact n (gamma defs)
837 | | Just gdef => pure (Just gdef)
840 | let Just (hd, args) = isAlias lhs
841 | | Nothing => pure Nothing
843 | log "declare.def" 5 $
844 | "Missing type declaration for the alias "
846 | ++ ". Checking first whether it is a misspelling."
848 | Just (str, kept) <- getSimilarNames n
849 | | Nothing => pure []
851 | decls <- for kept $
\ (cand, vis, weight) => do
852 | Just gdef <- lookupCtxtExact cand (gamma defs)
853 | | Nothing => pure Nothing
854 | let None = definition gdef
855 | | _ => pure Nothing
856 | pure (Just (cand, vis, weight))
857 | pure $
showSimilarNames (currentNS defs) n str $
catMaybes decls
858 | | (x :: xs) => throw (MaybeMisspelling (NoDeclaration fc n) (x ::: xs))
860 | log "declare.def" 5 "Not a misspelling: go ahead and declare it!"
861 | processType eopts nest env fc top Public []
863 | $
Mk [fc, MkFCVal fc n] $
holeyType (map snd args)
865 | lookupCtxtExact n (gamma defs)
868 | holeyType : List (FC, Name) -> RawImp
869 | holeyType [] = Implicit fc False
870 | holeyType ((xfc, x) :: xs)
871 | = let xfc = virtualiseFC xfc in
872 | IPi xfc top Explicit (Just x) (Implicit xfc False)
875 | lookupOrAddAlias _ _ _ fc n _
876 | = do defs <- get Ctxt
877 | lookupCtxtExact n (gamma defs)
880 | processDef : {vars : _} ->
881 | {auto c : Ref Ctxt Defs} ->
882 | {auto m : Ref MD Metadata} ->
883 | {auto u : Ref UST UState} ->
884 | {auto s : Ref Syn SyntaxInfo} ->
885 | {auto o : Ref ROpts REPLOpts} ->
886 | List ElabOpt -> NestedNames vars -> Env Term vars -> FC ->
887 | Name -> List ImpClause -> Core ()
888 | processDef opts nest env fc n_in cs_in
889 | = do n <- inCurrentNS n_in
890 | withDefStacked n $
do
892 | Just gdef <- lookupOrAddAlias opts nest env fc n cs_in
893 | | Nothing => noDeclaration fc n
894 | let None = definition gdef
895 | | _ => throw (AlreadyDefined fc n)
901 | let hashit = (collapseDefault $
visibility gdef) == Public || (Inline `elem` gdef.flags)
902 | let mult = if isErased (multiplicity gdef)
905 | nidx <- resolveName n
909 | log "declare.def" 5 $
"Traversing clauses of " ++ show n ++ " with mult " ++ show mult
910 | let treq = fromMaybe !getDefaultTotalityOption (findSetTotal (flags gdef))
911 | cs <- withTotality treq $
912 | traverse (checkClause mult (collapseDefault $
visibility gdef) treq
913 | hashit nidx opts nest env) cs_in
915 | let pats = map toPats (rights cs)
917 | (
cargs ** (tree_ct, unreachable))
<-
918 | logTime 3 ("Building compile time case tree for " ++ show n) $
919 | getPMDef fc (CompileTime mult) n ty (rights cs)
921 | traverse_ warnUnreachable unreachable
923 | logC "declare.def" 2 $
924 | do t <- toFullNames tree_ct
925 | pure ("Case tree for " ++ show n ++ ": " ++ show t)
929 | let pi = case lookup n (userHoles defs) of
930 | Nothing => defaultPI
931 | Just e => { externalDecl := e } defaultPI
935 | ignore $
addDef (Resolved nidx)
936 | ({ definition := PMDef pi cargs tree_ct tree_ct pats
939 | when (collapseDefault (visibility gdef) == Public) $
940 | do let rmetas = getMetas tree_ct
941 | log "declare.def" 10 $
"Saving from " ++ show n ++ ": " ++ show (keys rmetas)
942 | traverse_ addToSave (keys rmetas)
943 | when (isUserName n && collapseDefault (visibility gdef) /= Private) $
944 | do let tymetas = getMetas (type gdef)
945 | traverse_ addToSave (keys tymetas)
949 | update Ctxt { toCompileCase $= (n ::) }
951 | atotal <- toResolvedNames (NS builtinNS (UN $
Basic "assert_total"))
952 | logTime 3 ("Building size change graphs " ++ show n) $
953 | when (not (InCase `elem` opts)) $
954 | do calcRefs False atotal (Resolved nidx)
955 | sc <- calculateSizeChange fc n
956 | setSizeChange fc n sc
957 | checkIfGuarded fc n
961 | cov <- logTime 3 ("Checking Coverage " ++ show n) $
checkCoverage nidx ty mult cs
962 | setCovering fc n cov
967 | when (not (elem InCase opts)) $
968 | compileRunTime fc atotal
972 | withTotality : TotalReq -> Lazy (Core a) -> Core a
973 | withTotality tot c = do
974 | defaultTotality <- getDefaultTotalityOption
975 | setDefaultTotalityOption tot
976 | x <- catch c (\error => do setDefaultTotalityOption defaultTotality
978 | setDefaultTotalityOption defaultTotality
982 | simplePat : forall vars . Term vars -> Bool
983 | simplePat (Local {}) = True
984 | simplePat (Erased {}) = True
985 | simplePat (As _ _ _ p) = simplePat p
986 | simplePat _ = False
991 | catchAll : Clause -> Bool
992 | catchAll (MkClause env lhs _)
993 | = all simplePat (getArgs lhs)
998 | checkImpossible : Int -> RigCount -> ClosedTerm ->
999 | Core (Maybe ClosedTerm)
1000 | checkImpossible n mult tm
1001 | = do itm <- unelabNoPatvars Env.empty tm
1002 | let itm = map rawName itm
1005 | log "declare.def.impossible" 3 $
"Checking for impossibility: " ++ show itm
1006 | autoimp <- isUnboundImplicits
1007 | setUnboundImplicits True
1008 | (_, lhstm) <- bindNames False itm
1009 | setUnboundImplicits autoimp
1010 | (lhstm, _) <- elabTerm n (InLHS mult) [] (MkNested []) Env.empty
1011 | (IBindHere fc COVERAGE lhstm) Nothing
1013 | lhs <- normaliseHoles defs Env.empty lhstm
1014 | if !(hasEmptyPat defs Env.empty lhs)
1015 | then do log "declare.def.impossible" 5 "Some empty pat"
1018 | else do log "declare.def.impossible" 5 "No empty pat"
1019 | empty <- clearDefs ctxt
1020 | rtm <- closeEnv empty !(nf empty Env.empty lhs)
1023 | (\err => do defs <- get Ctxt
1024 | if !(impossibleErrOK defs err)
1026 | log "declare.def.impossible" 5 "impossible because \{show err}"
1030 | closeEnv : Defs -> ClosedNF -> Core ClosedTerm
1031 | closeEnv defs (NBind _ x (PVar {}) sc)
1032 | = closeEnv defs !(sc defs (toClosure defaultOpts Env.empty (Ref fc Bound x)))
1033 | closeEnv defs nf = quote defs Env.empty nf
1035 | getClause : Either RawImp Clause -> Core (Maybe Clause)
1036 | getClause (Left rawlhs)
1037 | = catch (do lhsp <- getImpossibleTerm env nest rawlhs
1038 | log "declare.def.impossible" 3 $
"Generated impossible LHS: " ++ show lhsp
1039 | pure $
Just $
MkClause Env.empty lhsp (Erased (getFC rawlhs) Impossible))
1040 | (\e => do log "declare.def" 5 $
"Error in getClause " ++ show e
1041 | recordWarning $
GenericWarn (fromMaybe (getFC rawlhs) $
getErrorLoc e) (show e)
1043 | getClause (Right c) = pure (Just c)
1045 | checkCoverage : Int -> ClosedTerm -> RigCount ->
1046 | List (Either RawImp Clause) ->
1048 | checkCoverage n ty mult cs
1049 | = do covcs' <- traverse getClause cs
1050 | log "declare.def" 5 $
unlines
1052 | :: map ((" " ++) . show) !(traverse toFullNames covcs')
1053 | let covcs = mapMaybe id covcs'
1055 | getPMDef fc (CompileTime mult) (Resolved n) ty covcs
1056 | logC "declare.def" 3 $
do pure $
"Working from " ++ show !(toFullNames ctree)
1057 | missCase <- if any catchAll covcs
1058 | then do logC "declare.def" 3 $
do pure "Catch all case in \{show !(getFullName (Resolved n))}"
1060 | else getMissing fc (Resolved n) ty ctree
1062 | do mc <- traverse toFullNames missCase
1063 | pure ("Initially missing in " ++
1064 | show !(getFullName (Resolved n)) ++ ":\n" ++
1065 | showSep "\n" (map show mc))
1067 | missImp <- traverse (checkImpossible n mult) missCase
1070 | missMatch <- traverse (checkMatched (not $
isErased mult) covcs) (mapMaybe id missImp)
1073 | let miss = catMaybes missMatch
1075 | then do [] <- getNonCoveringRefs fc (Resolved n)
1076 | | ns => toFullNames (NonCoveringCall ns)
1078 | else pure (MissingCases miss)