on 63ff875 help sign in
Idris-dev/src/Idris/Core/ProofState.hs
1107 lines 50 kB history raw
1{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, PatternGuards #-}
3{- Implements a proof state, some primitive tactics for manipulating
4 proofs, and some high level commands for introducing new theorems,
5 evaluation/checking inside the proof system, etc. --}
7module Idris.Core.ProofState(ProofState(..), newProof, envAtFocus, goalAtFocus,
8 Tactic(..), Goal(..), processTactic, nowElaboratingPS, doneElaboratingAppPS,
9 doneElaboratingArgPS, dropGiven, keepGiven, getProvenance) where
11import Idris.Core.Typecheck
12import Idris.Core.Evaluate
13import Idris.Core.TT
14import Idris.Core.Unify
15import Idris.Core.ProofTerm
17import Control.Monad.State.Strict
18import Control.Applicative hiding (empty)
19import Control.Arrow ((***))
20import Data.List
21import Debug.Trace
23import Util.Pretty hiding (fill)
25data ProofState = PS { thname :: Name,
26 holes :: [Name], -- ^ holes still to be solved
27 usedns :: [Name], -- ^ used names, don't use again
28 nextname :: Int, -- ^ name supply
29 pterm :: ProofTerm, -- ^ current proof term
30 ptype :: Type, -- ^ original goal
31 dontunify :: [Name], -- ^ explicitly given by programmer, leave it
32 unified :: (Name, [(Name, Term)]),
33 notunified :: [(Name, Term)],
34 dotted :: [(Name, [Name])], -- ^ dot pattern holes + environment
35 -- either hole or something in env must turn up in the 'notunified' list during elaboration
36 solved :: Maybe (Name, Term),
37 problems :: Fails,
38 injective :: [Name],
39 deferred :: [Name], -- ^ names we'll need to define
40 instances :: [Name], -- ^ instance arguments (for type classes)
41 autos :: [(Name, ([FailContext], [Name]))], -- ^ unsolved 'auto' implicits with their holes
42 psnames :: [Name], -- ^ Local names okay to use in proof search
43 previous :: Maybe ProofState, -- ^ for undo
44 context :: Context,
45 datatypes :: Ctxt TypeInfo,
46 plog :: String,
47 unifylog :: Bool,
48 done :: Bool,
49 recents :: [Name],
50 while_elaborating :: [FailContext]
51 }
53data Tactic = Attack
54 | Claim Name Raw
55 | ClaimFn Name Name Raw
56 | Reorder Name
57 | Exact Raw
58 | Fill Raw
59 | MatchFill Raw
60 | PrepFill Name [Name]
61 | CompleteFill
62 | Regret
63 | Solve
64 | StartUnify Name
65 | EndUnify
66 | UnifyAll
67 | Compute
68 | ComputeLet Name
69 | Simplify
70 | HNF_Compute
71 | EvalIn Raw
72 | CheckIn Raw
73 | Intro (Maybe Name)
74 | IntroTy Raw (Maybe Name)
75 | Forall Name (Maybe ImplicitInfo) Raw
76 | LetBind Name Raw Raw
77 | ExpandLet Name Term
78 | Rewrite Raw
79 | Induction Raw
80 | CaseTac Raw
81 | Equiv Raw
82 | PatVar Name
83 | PatBind Name
84 | Focus Name
85 | Defer [Name] Name
86 | DeferType Name Raw [Name]
87 | Instance Name
88 | AutoArg Name
89 | SetInjective Name
90 | MoveLast Name
91 | MatchProblems Bool
92 | UnifyProblems
93 | UnifyGoal Raw
94 | ProofState
95 | Undo
96 | QED
97 deriving Show
99-- Some utilites on proof and tactic states
101instance Show ProofState where
102 show ps | [] <- holes ps
103 = show (thname ps) ++ ": no more goals"
104 show ps | (h : hs) <- holes ps
105 = let tm = pterm ps
106 nm = thname ps
107 OK g = goal (Just h) tm
108 wkenv = premises g in
109 "Other goals: " ++ show hs ++ "\n" ++
110 showPs wkenv (reverse wkenv) ++ "\n" ++
111 "-------------------------------- (" ++ show nm ++
112 ") -------\n " ++
113 show h ++ " : " ++ showG wkenv (goalType g) ++ "\n"
114 where showPs env [] = ""
115 showPs env ((n, Let t v):bs)
116 = " " ++ show n ++ " : " ++
117 showEnv env ({- normalise ctxt env -} t) ++ " = " ++
118 showEnv env ({- normalise ctxt env -} v) ++
119 "\n" ++ showPs env bs
120 showPs env ((n, b):bs)
121 = " " ++ show n ++ " : " ++
122 showEnv env ({- normalise ctxt env -} (binderTy b)) ++
123 "\n" ++ showPs env bs
124 showG ps (Guess t v) = showEnv ps ({- normalise ctxt ps -} t) ++
125 " =?= " ++ showEnv ps v
126 showG ps b = showEnv ps (binderTy b)
128instance Pretty ProofState OutputAnnotation where
129 pretty ps | [] <- holes ps =
130 pretty (thname ps) <+> colon <+> text " no more goals."
131 pretty ps | (h : hs) <- holes ps =
132 let tm = pterm ps
133 OK g = goal (Just h) tm
134 nm = thname ps in
135 let wkEnv = premises g in
136 text "Other goals" <+> colon <+> pretty hs <+>
137 prettyPs wkEnv (reverse wkEnv) <+>
138 text "---------- " <+> text "Focussing on" <> colon <+> pretty nm <+> text " ----------" <+>
139 pretty h <+> colon <+> prettyGoal wkEnv (goalType g)
140 where
141 prettyGoal ps (Guess t v) =
142 prettyEnv ps t <+> text "=?=" <+> prettyEnv ps v
143 prettyGoal ps b = prettyEnv ps $ binderTy b
145 prettyPs env [] = empty
146 prettyPs env ((n, Let t v):bs) =
147 nest nestingSize (pretty n <+> colon <+>
148 prettyEnv env t <+> text "=" <+> prettyEnv env v <+>
149 nest nestingSize (prettyPs env bs))
150 prettyPs env ((n, b):bs) =
151 nest nestingSize (pretty n <+> colon <+> prettyEnv env (binderTy b) <+>
152 nest nestingSize (prettyPs env bs))
154holeName i = sMN i "hole"
156qshow :: Fails -> String
157qshow fs = show (map (\ (x, y, hs, env, _, _, t) -> (t, map fst env, x, y, hs)) fs)
159match_unify' :: Context -> Env ->
160 (TT Name, Maybe Provenance) ->
161 (TT Name, Maybe Provenance) ->
162 StateT TState TC [(Name, TT Name)]
163match_unify' ctxt env (topx, xfrom) (topy, yfrom) =
164 do ps <- get
165 let while = while_elaborating ps
166 let dont = dontunify ps
167 let inj = injective ps
168 traceWhen (unifylog ps)
169 ("Matching " ++ show (topx, topy) ++
170 " in " ++ show env ++
171 "\nHoles: " ++ show (holes ps)
172 ++ "\n"
173 ++ "\n" ++ show (getProofTerm (pterm ps)) ++ "\n\n"
174 ) $
175 case match_unify ctxt env (topx, xfrom) (topy, yfrom) inj (holes ps) while of
176 OK u -> traceWhen (unifylog ps)
177 ("Matched " ++ show u) $
178 do let (h, ns) = unified ps
179 put (ps { unified = (h, u ++ ns) })
180 return u
181 Error e -> traceWhen (unifylog ps)
182 ("No match " ++ show e) $
183 do put (ps { problems = (topx, topy, True,
184 env, e, while, Match) :
185 problems ps })
186 return []
187-- traceWhen (unifylog ps)
188-- ("Matched " ++ show (topx, topy) ++ " without " ++ show dont ++
189-- "\nSolved: " ++ show u
190-- ++ "\nCurrent problems:\n" ++ qshow (problems ps)
191-- -- ++ show (pterm ps)
192-- ++ "\n----------") $
194mergeSolutions :: Env -> [(Name, TT Name)] -> StateT TState TC [(Name, TT Name)]
195mergeSolutions env ns = merge [] ns
196 where
197 merge acc [] = return (reverse acc)
198 merge acc ((n, t) : ns)
199 | Just t' <- lookup n ns
200 = do ps <- get
201 let probs = problems ps
202 put (ps { problems = probs ++ [(t,t',True,env,
203 CantUnify True (t, Nothing) (t', Nothing) (Msg "") (errEnv env) 0,
204 [], Unify)] })
205 merge acc ns
206 | otherwise = merge ((n, t): acc) ns
208unify' :: Context -> Env ->
209 (TT Name, Maybe Provenance) ->
210 (TT Name, Maybe Provenance) ->
211 StateT TState TC [(Name, TT Name)]
212unify' ctxt env (topx, xfrom) (topy, yfrom) =
213 do ps <- get
214 let while = while_elaborating ps
215 let dont = dontunify ps
216 let inj = injective ps
217 (u, fails) <- traceWhen (unifylog ps)
218 ("Trying " ++ show (topx, topy) ++
219 "\nNormalised " ++ show (normalise ctxt env topx,
220 normalise ctxt env topy) ++
221 " in\n" ++ show env ++
222 "\nHoles: " ++ show (holes ps)
223 ++ "\nInjective: " ++ show (injective ps)
224 ++ "\n") $
225 lift $ unify ctxt env (topx, xfrom) (topy, yfrom) inj (holes ps)
226 (map fst (notunified ps)) while
227 let notu = filter (\ (n, t) -> case t of
228-- P _ _ _ -> False
229 _ -> n `elem` dont) u
230 traceWhen (unifylog ps)
231 ("Unified " ++ show (topx, topy) ++ " without " ++ show dont ++
232 "\nSolved: " ++ show u ++ "\nNew problems: " ++ qshow fails
233 ++ "\nNot unified:\n" ++ show (notunified ps)
234 ++ "\nCurrent problems:\n" ++ qshow (problems ps)
235-- ++ show (pterm ps)
236 ++ "\n----------") $
237 do let (h, ns) = unified ps
238 -- solve in results (maybe unify should do this itself...)
239 let u' = map (\(n, sol) -> (n, updateSolvedTerm u sol)) u
240 -- if a metavar has multiple solutions, make a new unification
241 -- problem for each.
242 uns <- mergeSolutions env (u' ++ ns)
243 ps <- get
244 let (ns', probs') = updateProblems ps uns (fails ++ problems ps)
245 let (notu', probs_notu) = mergeNotunified env (holes ps) (notu ++ notunified ps)
246 traceWhen (unifylog ps)
247 ("Now solved: " ++ show ns' ++
248 "\nNow problems: " ++ qshow (probs' ++ probs_notu) ++
249 "\nNow injective: " ++ show (updateInj u (injective ps))) $
250 put (ps { problems = probs' ++ probs_notu,
251 unified = (h, ns'),
252 injective = updateInj u (injective ps),
253 notunified = notu' })
254 return u
255 where updateInj ((n, a) : us) inj
256 | (P _ n' _, _) <- unApply a,
257 n `elem` inj = updateInj us (n':inj)
258 | (P _ n' _, _) <- unApply a,
259 n' `elem` inj = updateInj us (n:inj)
260 updateInj (_ : us) inj = updateInj us inj
261 updateInj [] inj = inj
263nowElaboratingPS :: FC -> Name -> Name -> ProofState -> ProofState
264nowElaboratingPS fc f arg ps = ps { while_elaborating = FailContext fc f arg : while_elaborating ps }
266dropUntil :: (a -> Bool) -> [a] -> [a]
267dropUntil p [] = []
268dropUntil p (x:xs) | p x = xs
269 | otherwise = dropUntil p xs
271doneElaboratingAppPS :: Name -> ProofState -> ProofState
272doneElaboratingAppPS f ps = let while = while_elaborating ps
273 while' = dropUntil (\ (FailContext _ f' _) -> f == f') while
274 in ps { while_elaborating = while' }
276doneElaboratingArgPS :: Name -> Name -> ProofState -> ProofState
277doneElaboratingArgPS f x ps = let while = while_elaborating ps
278 while' = dropUntil (\ (FailContext _ f' x') -> f == f' && x == x') while
279 in ps { while_elaborating = while' }
281getName :: Monad m => String -> StateT TState m Name
282getName tag = do ps <- get
283 let n = nextname ps
284 put (ps { nextname = n+1 })
285 return $ sMN n tag
287action :: Monad m => (ProofState -> ProofState) -> StateT TState m ()
288action a = do ps <- get
289 put (a ps)
291query :: Monad m => (ProofState -> r) -> StateT TState m r
292query q = do ps <- get
293 return $ q ps
295addLog :: Monad m => String -> StateT TState m ()
296addLog str = action (\ps -> ps { plog = plog ps ++ str ++ "\n" })
298newProof :: Name -> Context -> Ctxt TypeInfo -> Type -> ProofState
299newProof n ctxt datatypes ty =
300 let h = holeName 0
301 ty' = vToP ty
302 in PS n [h] [] 1 (mkProofTerm (Bind h (Hole ty')
303 (P Bound h ty'))) ty [] (h, []) [] []
304 Nothing [] []
305 [] [] [] []
306 Nothing ctxt datatypes "" False False [] []
308type TState = ProofState -- [TacticAction])
309type RunTactic = RunTactic' TState
311envAtFocus :: ProofState -> TC Env
312envAtFocus ps
313 | not $ null (holes ps) = do g <- goal (Just (head (holes ps))) (pterm ps)
314 return (premises g)
315 | otherwise = fail "No holes"
317goalAtFocus :: ProofState -> TC (Binder Type)
318goalAtFocus ps
319 | not $ null (holes ps) = do g <- goal (Just (head (holes ps))) (pterm ps)
320 return (goalType g)
321 | otherwise = Error . Msg $ "No goal in " ++ show (holes ps) ++ show (getProofTerm (pterm ps))
323tactic :: Hole -> RunTactic -> StateT TState TC ()
324tactic h f = do ps <- get
325 (tm', _) <- atHole h f (context ps) [] (pterm ps)
326 ps <- get -- might have changed while processing
327 put (ps { pterm = tm' })
329computeLet :: Context -> Name -> Term -> Term
330computeLet ctxt n tm = cl [] tm where
331 cl env (Bind n' (Let t v) sc)
332 | n' == n = let v' = normalise ctxt env v in
333 Bind n' (Let t v') sc
334 cl env (Bind n' b sc) = Bind n' (fmap (cl env) b) (cl ((n, b):env) sc)
335 cl env (App s f a) = App s (cl env f) (cl env a)
336 cl env t = t
338attack :: RunTactic
339attack ctxt env (Bind x (Hole t) sc)
340 = do h <- getName "hole"
341 action (\ps -> ps { holes = h : holes ps })
342 return $ Bind x (Guess t (newtm h)) sc
343 where
344 newtm h = Bind h (Hole t) (P Bound h t)
345attack ctxt env _ = fail "Not an attackable hole"
347claim :: Name -> Raw -> RunTactic
348claim n ty ctxt env t =
349 do (tyv, tyt) <- lift $ check ctxt env ty
350 lift $ isType ctxt env tyt
351 action (\ps -> let (g:gs) = holes ps in
352 ps { holes = g : n : gs } )
353 return $ Bind n (Hole tyv) t
355-- If the current goal is 'retty', make a claim which is a function that
356-- can compute a retty from argty (i.e a claim 'argty -> retty')
357claimFn :: Name -> Name -> Raw -> RunTactic
358claimFn n bn argty ctxt env t@(Bind x (Hole retty) sc) =
359 do (tyv, tyt) <- lift $ check ctxt env argty
360 lift $ isType ctxt env tyt
361 action (\ps -> let (g:gs) = holes ps in
362 ps { holes = g : n : gs } )
363 return $ Bind n (Hole (Bind bn (Pi Nothing tyv tyt) retty)) t
364claimFn _ _ _ ctxt env _ = fail "Can't make function type here"
366reorder_claims :: RunTactic
367reorder_claims ctxt env t
368 = -- trace (showSep "\n" (map show (scvs t))) $
369 let (bs, sc) = scvs t []
370 newbs = reverse (sortB (reverse bs)) in
371 traceWhen (bs /= newbs) (show bs ++ "\n ==> \n" ++ show newbs) $
372 return (bindAll newbs sc)
373 where scvs (Bind n b@(Hole _) sc) acc = scvs sc ((n, b):acc)
374 scvs sc acc = (reverse acc, sc)
376 sortB :: [(Name, Binder (TT Name))] -> [(Name, Binder (TT Name))]
377 sortB [] = []
378 sortB (x:xs) | all (noOcc x) xs = x : sortB xs
379 | otherwise = sortB (insertB x xs)
381 insertB x [] = [x]
382 insertB x (y:ys) | all (noOcc x) (y:ys) = x : y : ys
383 | otherwise = y : insertB x ys
385 noOcc (n, _) (_, Let t v) = noOccurrence n t && noOccurrence n v
386 noOcc (n, _) (_, Guess t v) = noOccurrence n t && noOccurrence n v
387 noOcc (n, _) (_, b) = noOccurrence n (binderTy b)
389focus :: Name -> RunTactic
390focus n ctxt env t = do action (\ps -> let hs = holes ps in
391 if n `elem` hs
392 then ps { holes = n : (hs \\ [n]) }
393 else ps)
394 ps <- get
395 return t
397movelast :: Name -> RunTactic
398movelast n ctxt env t = do action (\ps -> let hs = holes ps in
399 if n `elem` hs
400 then ps { holes = (hs \\ [n]) ++ [n] }
401 else ps)
402 return t
404instanceArg :: Name -> RunTactic
405instanceArg n ctxt env (Bind x (Hole t) sc)
406 = do action (\ps -> let hs = holes ps
407 is = instances ps in
408 ps { holes = (hs \\ [x]) ++ [x],
409 instances = x:is })
410 return (Bind x (Hole t) sc)
412autoArg :: Name -> RunTactic
413autoArg n ctxt env (Bind x (Hole t) sc)
414 = do action (\ps -> case lookup x (autos ps) of
415 Nothing ->
416 let hs = holes ps in
417 ps { holes = (hs \\ [x]) ++ [x],
418 autos = (x, (while_elaborating ps, refsIn t)) : autos ps }
419 Just _ -> ps)
420 return (Bind x (Hole t) sc)
422setinj :: Name -> RunTactic
423setinj n ctxt env (Bind x b sc)
424 = do action (\ps -> let is = injective ps in
425 ps { injective = n : is })
426 return (Bind x b sc)
428defer :: [Name] -> Name -> RunTactic
429defer dropped n ctxt env (Bind x (Hole t) (P nt x' ty)) | x == x' =
430 do let env' = filter (\(n, t) -> n `notElem` dropped) env
431 action (\ps -> let hs = holes ps in
432 ps { usedns = n : usedns ps,
433 holes = hs \\ [x] })
434 ps <- get
435 return (Bind n (GHole (length env') (psnames ps) (mkTy (reverse env') t))
436 (mkApp (P Ref n ty) (map getP (reverse env'))))
437 where
438 mkTy [] t = t
439 mkTy ((n,b) : bs) t = Bind n (Pi Nothing (binderTy b) (TType (UVar 0))) (mkTy bs t)
441 getP (n, b) = P Bound n (binderTy b)
443-- as defer, but build the type and application explicitly
444deferType :: Name -> Raw -> [Name] -> RunTactic
445deferType n fty_in args ctxt env (Bind x (Hole t) (P nt x' ty)) | x == x' =
446 do (fty, _) <- lift $ check ctxt env fty_in
447 action (\ps -> let hs = holes ps
448 ds = deferred ps in
449 ps { holes = hs \\ [x],
450 deferred = n : ds })
451 return (Bind n (GHole 0 [] fty)
452 (mkApp (P Ref n ty) (map getP args)))
453 where
454 getP n = case lookup n env of
455 Just b -> P Bound n (binderTy b)
456 Nothing -> error ("deferType can't find " ++ show n)
458regret :: RunTactic
459regret ctxt env (Bind x (Hole t) sc) | noOccurrence x sc =
460 do action (\ps -> let hs = holes ps in
461 ps { holes = hs \\ [x] })
462 return sc
463regret ctxt env (Bind x (Hole t) _)
464 = fail $ show x ++ " : " ++ show t ++ " is not solved..."
466unifyGoal :: Raw -> RunTactic
467unifyGoal tm ctxt env h@(Bind x b sc) =
468 do (tmv, _) <- lift $ check ctxt env tm
469 ns' <- unify' ctxt env (binderTy b, Nothing) (tmv, Nothing)
470 return h
472exact :: Raw -> RunTactic
473exact guess ctxt env (Bind x (Hole ty) sc) =
474 do (val, valty) <- lift $ check ctxt env guess
475 lift $ converts ctxt env valty ty
476 return $ Bind x (Guess ty val) sc
477exact _ _ _ _ = fail "Can't fill here."
479-- As exact, but attempts to solve other goals by unification
481fill :: Raw -> RunTactic
482fill guess ctxt env (Bind x (Hole ty) sc) =
483 do (val, valty) <- lift $ check ctxt env guess
484-- let valtyn = normalise ctxt env valty
485-- let tyn = normalise ctxt env ty
486 ns <- unify' ctxt env (valty, Just $ SourceTerm val)
487 (ty, Just (chkPurpose val ty))
488 ps <- get
489 let (uh, uns) = unified ps
490-- put (ps { unified = (uh, uns ++ ns) })
491-- addLog (show (uh, uns ++ ns))
492 return $ Bind x (Guess ty val) sc
493 where
494 -- some expected types show up commonly in errors and indicate a
495 -- specific problem.
496 -- argTy -> retTy suggests a function applied to too many arguments
497 chkPurpose val (Bind _ (Pi _ (P _ (MN _ _) _) _) (P _ (MN _ _) _))
498 = TooManyArgs val
499 chkPurpose _ _ = ExpectedType
500fill _ _ _ _ = fail "Can't fill here."
502-- As fill, but attempts to solve other goals by matching
504match_fill :: Raw -> RunTactic
505match_fill guess ctxt env (Bind x (Hole ty) sc) =
506 do (val, valty) <- lift $ check ctxt env guess
507-- let valtyn = normalise ctxt env valty
508-- let tyn = normalise ctxt env ty
509 ns <- match_unify' ctxt env (valty, Just $ SourceTerm val)
510 (ty, Just ExpectedType)
511 ps <- get
512 let (uh, uns) = unified ps
513-- put (ps { unified = (uh, uns ++ ns) })
514-- addLog (show (uh, uns ++ ns))
515 return $ Bind x (Guess ty val) sc
516match_fill _ _ _ _ = fail "Can't fill here."
518prep_fill :: Name -> [Name] -> RunTactic
519prep_fill f as ctxt env (Bind x (Hole ty) sc) =
520 do let val = mkApp (P Ref f Erased) (map (\n -> P Ref n Erased) as)
521 return $ Bind x (Guess ty val) sc
522prep_fill f as ctxt env t = fail $ "Can't prepare fill at " ++ show t
524complete_fill :: RunTactic
525complete_fill ctxt env (Bind x (Guess ty val) sc) =
526 do let guess = forget val
527 (val', valty) <- lift $ check ctxt env guess
528 ns <- unify' ctxt env (valty, Just $ SourceTerm val')
529 (ty, Just ExpectedType)
530 ps <- get
531 let (uh, uns) = unified ps
532-- put (ps { unified = (uh, uns ++ ns) })
533 return $ Bind x (Guess ty val) sc
534complete_fill ctxt env t = fail $ "Can't complete fill at " ++ show t
536-- When solving something in the 'dont unify' set, we should check
537-- that the guess we are solving it with unifies with the thing unification
538-- found for it, if anything.
540solve :: RunTactic
541solve ctxt env (Bind x (Guess ty val) sc)
542 = do ps <- get
543 let (uh, uns) = unified ps
544 dropdots <-
545 case lookup x (notunified ps) of
546 Just tm -> -- trace ("NEED MATCH: " ++ show (x, tm, val) ++ "\nIN " ++ show (pterm ps)) $
547 do match_unify' ctxt env (tm, Just InferredVal)
548 (val, Just GivenVal)
549 return [x]
550 _ -> return []
551 action (\ps -> ps { holes = traceWhen (unifylog ps) ("Dropping hole " ++ show x) $
552 holes ps \\ [x],
553 solved = Just (x, val),
554 dontunify = filter (/= x) (dontunify ps),
555 notunified = updateNotunified [(x,val)]
556 (notunified ps),
557 recents = x : recents ps,
558 instances = instances ps \\ [x],
559 dotted = dropUnified dropdots (dotted ps) })
560 let (locked, did) = tryLock (holes ps \\ [x]) (updsubst x val sc) in
561 return locked
562 where dropUnified ddots [] = []
563 dropUnified ddots ((x, es) : ds)
564 | x `elem` ddots || any (\e -> e `elem` ddots) es
565 = dropUnified ddots ds
566 | otherwise = (x, es) : dropUnified ddots ds
568 tryLock :: [Name] -> Term -> (Term, Bool)
569 tryLock hs tm@(App Complete _ _) = (tm, True)
570 tryLock hs tm@(App s f a) =
571 let (f', fl) = tryLock hs f
572 (a', al) = tryLock hs a in
573 if fl && al then (App Complete f' a', True)
574 else (App s f' a', False)
575 tryLock hs t@(P _ n _) = (t, not $ n `elem` hs)
576 tryLock hs t@(Bind n (Hole _) sc) = (t, False)
577 tryLock hs t@(Bind n (Guess _ _) sc) = (t, False)
578 tryLock hs t@(Bind n (Let ty val) sc)
579 = let (ty', tyl) = tryLock hs ty
580 (val', vall) = tryLock hs val
581 (sc', scl) = tryLock hs sc in
582 (Bind n (Let ty' val') sc', tyl && vall && scl)
583 tryLock hs t@(Bind n b sc)
584 = let (bt', btl) = tryLock hs (binderTy b)
585 (val', vall) = tryLock hs val
586 (sc', scl) = tryLock hs sc in
587 (Bind n (b { binderTy = bt' }) sc', btl && scl)
588 tryLock hs t = (t, True)
590solve _ _ h@(Bind x t sc)
591 = do ps <- get
592 case findType x sc of
593 Just t -> lift $ tfail (CantInferType (show t))
594 _ -> lift $ tfail (IncompleteTerm h)
595 where findType x (Bind n (Let t v) sc)
596 = findType x v `mplus` findType x sc
597 findType x (Bind n t sc)
598 | P _ x' _ <- binderTy t, x == x' = Just n
599 | otherwise = findType x sc
600 findType x _ = Nothing
602introTy :: Raw -> Maybe Name -> RunTactic
603introTy ty mn ctxt env (Bind x (Hole t) (P _ x' _)) | x == x' =
604 do let n = case mn of
605 Just name -> name
606 Nothing -> x
607 let t' = case t of
608 x@(Bind y (Pi _ s _) _) -> x
609 _ -> hnf ctxt env t
610 (tyv, tyt) <- lift $ check ctxt env ty
611-- ns <- lift $ unify ctxt env tyv t'
612 case t' of
613 Bind y (Pi _ s _) t -> let t' = updsubst y (P Bound n s) t in
614 do ns <- unify' ctxt env (s, Nothing) (tyv, Nothing)
615 ps <- get
616 let (uh, uns) = unified ps
617-- put (ps { unified = (uh, uns ++ ns) })
618 return $ Bind n (Lam tyv) (Bind x (Hole t') (P Bound x t'))
619 _ -> lift $ tfail $ CantIntroduce t'
620introTy ty n ctxt env _ = fail "Can't introduce here."
622intro :: Maybe Name -> RunTactic
623intro mn ctxt env (Bind x (Hole t) (P _ x' _)) | x == x' =
624 do let t' = case t of
625 x@(Bind y (Pi _ s _) _) -> x
626 _ -> hnf ctxt env t
627 case t' of
628 Bind y (Pi _ s _) t ->
629 let n = case mn of
630 Just name -> name
631 Nothing -> y
632 -- It's important that this be subst and not updsubst,
633 -- because we want to substitute even in portions of
634 -- terms that we know do not contain holes.
635 t' = subst y (P Bound n s) t
636 in return $ Bind n (Lam s) (Bind x (Hole t') (P Bound x t'))
637 _ -> lift $ tfail $ CantIntroduce t'
638intro n ctxt env _ = fail "Can't introduce here."
640forall :: Name -> Maybe ImplicitInfo -> Raw -> RunTactic
641forall n impl ty ctxt env (Bind x (Hole t) (P _ x' _)) | x == x' =
642 do (tyv, tyt) <- lift $ check ctxt env ty
643 unify' ctxt env (tyt, Nothing) (TType (UVar 0), Nothing)
644 unify' ctxt env (t, Nothing) (TType (UVar 0), Nothing)
645 return $ Bind n (Pi impl tyv (TType (UVar 0))) (Bind x (Hole t) (P Bound x t))
646forall n impl ty ctxt env _ = fail "Can't pi bind here"
648patvar :: Name -> RunTactic
649patvar n ctxt env (Bind x (Hole t) sc) =
650 do action (\ps -> ps { holes = traceWhen (unifylog ps) ("Dropping pattern hole " ++ show x) $
651 holes ps \\ [x],
652 solved = Just (x, P Bound n t),
653 dontunify = filter (/=x) (dontunify ps),
654 notunified = updateNotunified [(x,P Bound n t)]
655 (notunified ps),
656 injective = addInj n x (injective ps)
657 })
658 return $ Bind n (PVar t) (updsubst x (P Bound n t) sc)
659 where addInj n x ps | x `elem` ps = n : ps
660 | otherwise = ps
661patvar n ctxt env tm = fail $ "Can't add pattern var at " ++ show tm
663letbind :: Name -> Raw -> Raw -> RunTactic
664letbind n ty val ctxt env (Bind x (Hole t) (P _ x' _)) | x == x' =
665 do (tyv, tyt) <- lift $ check ctxt env ty
666 (valv, valt) <- lift $ check ctxt env val
667 lift $ isType ctxt env tyt
668 return $ Bind n (Let tyv valv) (Bind x (Hole t) (P Bound x t))
669letbind n ty val ctxt env _ = fail "Can't let bind here"
671expandLet :: Name -> Term -> RunTactic
672expandLet n v ctxt env tm =
673 return $ updsubst n v tm
675rewrite :: Raw -> RunTactic
676rewrite tm ctxt env (Bind x (Hole t) xp@(P _ x' _)) | x == x' =
677 do (tmv, tmt) <- lift $ check ctxt env tm
678 let tmt' = normalise ctxt env tmt
679 case unApply tmt' of
680 (P _ (UN q) _, [lt,rt,l,r]) | q == txt "=" ->
681 do let p = Bind rname (Lam lt) (mkP (P Bound rname lt) r l t)
682 let newt = mkP l r l t
683 let sc = forget $ (Bind x (Hole newt)
684 (mkApp (P Ref (sUN "replace") (TType (UVal 0)))
685 [lt, l, r, p, tmv, xp]))
686 (scv, sct) <- lift $ check ctxt env sc
687 return scv
688 _ -> lift $ tfail (NotEquality tmv tmt')
689 where rname = sMN 0 "replaced"
690rewrite _ _ _ _ = fail "Can't rewrite here"
692-- To make the P for rewrite, replace syntactic occurrences of l in ty with
693-- an x, and put \x : lt in front
694mkP :: TT Name -> TT Name -> TT Name -> TT Name -> TT Name
695mkP lt l r ty | l == ty = lt
696mkP lt l r (App s f a) = let f' = if (r /= f) then mkP lt l r f else f
697 a' = if (r /= a) then mkP lt l r a else a in
698 App s f' a'
699mkP lt l r (Bind n b sc)
700 = let b' = mkPB b
701 sc' = if (r /= sc) then mkP lt l r sc else sc in
702 Bind n b' sc'
703 where mkPB (Let t v) = let t' = if (r /= t) then mkP lt l r t else t
704 v' = if (r /= v) then mkP lt l r v else v in
705 Let t' v'
706 mkPB b = let ty = binderTy b
707 ty' = if (r /= ty) then mkP lt l r ty else ty in
708 b { binderTy = ty' }
709mkP lt l r x = x
711casetac :: Raw -> Bool -> RunTactic
712casetac tm induction ctxt env (Bind x (Hole t) (P _ x' _)) | x == x' = do
713 (tmv, tmt) <- lift $ check ctxt env tm
714 let tmt' = normalise ctxt env tmt
715 let (tacn, tacstr, tactt) = if induction
716 then (ElimN, "eliminator", "Induction")
717 else (CaseN, "case analysis", "Case analysis")
718 case unApply tmt' of
719 (P _ tnm _, tyargs) -> do
720 case lookupTy (SN (tacn tnm)) ctxt of
721 [elimTy] -> do
722 param_pos <- case lookupMetaInformation tnm ctxt of
723 [DataMI param_pos] -> return param_pos
724 m | length tyargs > 0 -> fail $ "Invalid meta information for " ++ show tnm ++ " where the metainformation is " ++ show m ++ " and definition is" ++ show (lookupDef tnm ctxt)
725 _ -> return []
726 let (params, indicies) = splitTyArgs param_pos tyargs
727 let args = getArgTys elimTy
728 let pmargs = take (length params) args
729 let args' = drop (length params) args
730 let propTy = head args'
731 let restargs = init $ tail args'
732 let consargs = take (length restargs - length indicies) $ restargs
733 let indxargs = drop (length restargs - length indicies) $ restargs
734 let scr = last $ tail args'
735 let indxnames = makeIndexNames indicies
736 currentNames <- query $ allTTNames . getProofTerm . pterm
737 let tmnm = case tm of
738 Var nm -> uniqueNameCtxt ctxt nm currentNames
739 _ -> uniqueNameCtxt ctxt (sMN 0 "iv") currentNames
740 let tmvar = P Bound tmnm tmt'
741 prop <- replaceIndicies indxnames indicies $ Bind tmnm (Lam tmt') (mkP tmvar tmv tmvar t)
742 consargs' <- query (\ps -> map (flip (uniqueNameCtxt (context ps)) (holes ps ++ allTTNames (getProofTerm (pterm ps))) *** uniqueBindersCtxt (context ps) (holes ps ++ allTTNames (getProofTerm (pterm ps)))) consargs)
743 let res = flip (foldr substV) params $ (substV prop $ bindConsArgs consargs' (mkApp (P Ref (SN (tacn tnm)) (TType (UVal 0)))
744 (params ++ [prop] ++ map makeConsArg consargs' ++ indicies ++ [tmv])))
745 action (\ps -> ps {holes = holes ps \\ [x],
746 recents = x : recents ps })
747 mapM_ addConsHole (reverse consargs')
748 let res' = forget $ res
749 (scv, sct) <- lift $ check ctxt env res'
750 let (scv', _) = specialise ctxt env [] scv
751 return scv'
752 [] -> lift $ tfail $ NoEliminator tacstr tmt'
753 xs -> lift $ tfail $ Msg $ "Multiple definitions found when searching for " ++ tacstr ++ "of " ++ show tnm
754 _ -> lift $ tfail $ NoEliminator (if induction then "induction" else "case analysis")
755 tmt'
756 where scname = sMN 0 "scarg"
757 makeConsArg (nm, ty) = P Bound nm ty
758 bindConsArgs ((nm, ty):args) v = Bind nm (Hole ty) $ bindConsArgs args v
759 bindConsArgs [] v = v
760 addConsHole (nm, ty) =
761 action (\ps -> ps { holes = nm : holes ps })
762 splitTyArgs param_pos tyargs =
763 let (params, indicies) = partition (flip elem param_pos . fst) . zip [0..] $ tyargs
764 in (map snd params, map snd indicies)
765 makeIndexNames = foldr (\_ nms -> (uniqueNameCtxt ctxt (sMN 0 "idx") nms):nms) []
766 replaceIndicies idnms idxs prop = foldM (\t (idnm, idx) -> do (idxv, idxt) <- lift $ check ctxt env (forget idx)
767 let var = P Bound idnm idxt
768 return $ Bind idnm (Lam idxt) (mkP var idxv var t)) prop $ zip idnms idxs
769casetac tm induction ctxt env _ = fail $ "Can't do " ++ (if induction then "induction" else "case analysis") ++ " here"
772equiv :: Raw -> RunTactic
773equiv tm ctxt env (Bind x (Hole t) sc) =
774 do (tmv, tmt) <- lift $ check ctxt env tm
775 lift $ converts ctxt env tmv t
776 return $ Bind x (Hole tmv) sc
777equiv tm ctxt env _ = fail "Can't equiv here"
779patbind :: Name -> RunTactic
780patbind n ctxt env (Bind x (Hole t) (P _ x' _)) | x == x' =
781 do let t' = case t of
782 x@(Bind y (PVTy s) t) -> x
783 _ -> hnf ctxt env t
784 case t' of
785 Bind y (PVTy s) t -> let t' = updsubst y (P Bound n s) t in
786 return $ Bind n (PVar s) (Bind x (Hole t') (P Bound x t'))
787 _ -> fail "Nothing to pattern bind"
788patbind n ctxt env _ = fail "Can't pattern bind here"
790compute :: RunTactic
791compute ctxt env (Bind x (Hole ty) sc) =
792 do return $ Bind x (Hole (normalise ctxt env ty)) sc
793compute ctxt env t = return t
795hnf_compute :: RunTactic
796hnf_compute ctxt env (Bind x (Hole ty) sc) =
797 do let ty' = hnf ctxt env ty in
798-- trace ("HNF " ++ show (ty, ty')) $
799 return $ Bind x (Hole ty') sc
800hnf_compute ctxt env t = return t
802-- reduce let bindings only
803simplify :: RunTactic
804simplify ctxt env (Bind x (Hole ty) sc) =
805 do return $ Bind x (Hole (fst (specialise ctxt env [] ty))) sc
806simplify ctxt env t = return t
808check_in :: Raw -> RunTactic
809check_in t ctxt env tm =
810 do (val, valty) <- lift $ check ctxt env t
811 addLog (showEnv env val ++ " : " ++ showEnv env valty)
812 return tm
814eval_in :: Raw -> RunTactic
815eval_in t ctxt env tm =
816 do (val, valty) <- lift $ check ctxt env t
817 let val' = normalise ctxt env val
818 let valty' = normalise ctxt env valty
819 addLog (showEnv env val ++ " : " ++
820 showEnv env valty ++
821-- " in " ++ show env ++
822 " ==>\n " ++
823 showEnv env val' ++ " : " ++
824 showEnv env valty')
825 return tm
827start_unify :: Name -> RunTactic
828start_unify n ctxt env tm = do -- action (\ps -> ps { unified = (n, []) })
829 return tm
831tmap f (a, b, c) = (f a, b, c)
833solve_unified :: RunTactic
834solve_unified ctxt env tm =
835 do ps <- get
836 let (_, ns) = unified ps
837 let unify = dropGiven (dontunify ps) ns (holes ps)
838 action (\ps -> ps { holes = traceWhen (unifylog ps) ("Dropping holes " ++ show (map fst unify)) $
839 holes ps \\ map fst unify,
840 recents = recents ps ++ map fst unify })
841 action (\ps -> ps { pterm = updateSolved unify (pterm ps) })
842 return (updateSolvedTerm unify tm)
844dropGiven du [] hs = []
845dropGiven du ((n, P Bound t ty) : us) hs
846 | n `elem` du && not (t `elem` du)
847 && n `elem` hs && t `elem` hs
848 = (t, P Bound n ty) : dropGiven du us hs
849dropGiven du (u@(n, _) : us) hs
850 | n `elem` du = dropGiven du us hs
851-- dropGiven du (u@(_, P a n ty) : us) | n `elem` du = dropGiven du us
852dropGiven du (u : us) hs = u : dropGiven du us hs
854keepGiven du [] hs = []
855keepGiven du ((n, P Bound t ty) : us) hs
856 | n `elem` du && not (t `elem` du)
857 && n `elem` hs && t `elem` hs
858 = keepGiven du us hs
859keepGiven du (u@(n, _) : us) hs
860 | n `elem` du = u : keepGiven du us hs
861keepGiven du (u : us) hs = keepGiven du us hs
863updateEnv [] e = e
864updateEnv ns [] = []
865updateEnv ns ((n, b) : env)
866 = (n, fmap (updateSolvedTerm ns) b) : updateEnv ns env
868updateProv ns (SourceTerm t) = SourceTerm $ updateSolvedTerm ns t
869updateProv ns p = p
871updateError [] err = err
872updateError ns (At f e) = At f (updateError ns e)
873updateError ns (Elaborating s n e) = Elaborating s n (updateError ns e)
874updateError ns (ElaboratingArg f a env e)
875 = ElaboratingArg f a env (updateError ns e)
876updateError ns (CantUnify b (l,lp) (r,rp) e xs sc)
877 = CantUnify b (updateSolvedTerm ns l, fmap (updateProv ns) lp)
878 (updateSolvedTerm ns r, fmap (updateProv ns) rp) (updateError ns e) xs sc
879updateError ns e = e
881updateRes ns [] = []
882updateRes ns ((x, t) : ts) = (x, updateSolvedTerm ns t) : updateRes ns ts
884solveInProblems x val [] = []
885solveInProblems x val ((l, r, env, err) : ps)
886 = ((psubst x val l, psubst x val r,
887 updateEnv [(x, val)] env, err) : solveInProblems x val ps)
889mergeNotunified :: Env -> [Name] -> [(Name, Term)] -> ([(Name, Term)], Fails)
890mergeNotunified env holes ns = mnu ns [] [] where
891 mnu [] ns_acc ps_acc = (reverse ns_acc, reverse ps_acc)
892 mnu ((n, t):ns) ns_acc ps_acc
893 | Just t' <- lookup n ns, t /= t'
894 = mnu ns ((n,t') : ns_acc)
895 ((t,t',True, env,CantUnify True (t, Nothing) (t', Nothing) (Msg "") [] 0, [],Match) : ps_acc)
896 | otherwise = mnu ns ((n,t) : ns_acc) ps_acc
898updateNotunified [] nu = nu
899updateNotunified ns nu = up nu where
900 up [] = []
901 up ((n, t) : nus) = let t' = updateSolvedTerm ns t in
902 ((n, t') : up nus)
904getProvenance :: Err -> (Maybe Provenance, Maybe Provenance)
905getProvenance (CantUnify _ (_, lp) (_, rp) _ _ _) = (lp, rp)
906getProvenance _ = (Nothing, Nothing)
908setReady (x, y, _, env, err, c, at) = (x, y, True, env, err, c, at)
910updateProblems :: ProofState -> [(Name, TT Name)] -> Fails
911 -> ([(Name, TT Name)], Fails)
912-- updateProblems ctxt [] ps inj holes = ([], ps)
913updateProblems ps updates probs = rec 10 updates probs
914 where
915 -- keep trying if we make progress, but not too many times...
916 rec 0 us fs = (us, fs)
917 rec n us fs = case up us [] fs of
918 res@(_, []) -> res
919 res@(us', _) | length us' == length us -> res
920 (us', fs') -> rec (n - 1) us' fs'
922 hs = holes ps
923 inj = injective ps
924 ctxt = context ps
925 ulog = unifylog ps
926 usupp = map fst (notunified ps)
927 dont = dontunify ps
929 up ns acc [] = (ns, map (updateNs ns) (reverse acc))
930 up ns acc (prob@(x, y, ready, env, err, while, um) : ps) =
931 let (x', newx) = updateSolvedTerm' ns x
932 (y', newy) = updateSolvedTerm' ns y
933 (lp, rp) = getProvenance err
934 err' = updateError ns err
935 env' = updateEnv ns env in
936 if newx || newy || ready ||
937 any (\n -> n `elem` inj) (refsIn x ++ refsIn y) then
938 case unify ctxt env' (x', lp) (y', rp) inj hs usupp while of
939 OK (v, []) -> traceWhen ulog ("DID " ++ show (x',y',ready,v,dont)) $
940 let v' = filter (\(n, _) -> n `notElem` dont) v in
941 up (ns ++ v') acc ps
942 e -> -- trace ("FAILED " ++ show (x',y',ready,e)) $
943 up ns ((x',y',False,env',err',while,um) : acc) ps
944 else -- trace ("SKIPPING " ++ show (x,y,ready)) $
945 up ns ((x',y', False, env',err', while, um) : acc) ps
947 updateNs ns (x, y, t, env, err, fc, fa)
948 = let (x', newx) = updateSolvedTerm' ns x
949 (y', newy) = updateSolvedTerm' ns y in
950 (x', y', newx || newy,
951 updateEnv ns env, updateError ns err, fc, fa)
953-- attempt to solve remaining problems with match_unify
954matchProblems :: Bool -> ProofState -> [(Name, TT Name)] -> Fails
955 -> ([(Name, TT Name)], Fails)
956matchProblems all ps updates probs = up updates probs where
957 hs = holes ps
958 inj = injective ps
959 ctxt = context ps
961 up ns [] = (ns, [])
962 up ns ((x, y, ready, env, err, while, um) : ps)
963 | all || um == Match =
964 let x' = updateSolvedTerm ns x
965 y' = updateSolvedTerm ns y
966 (lp, rp) = getProvenance err
967 err' = updateError ns err
968 env' = updateEnv ns env in
969 case match_unify ctxt env' (x', lp) (y', rp) inj hs while of
970 OK v -> -- trace ("Added " ++ show v ++ " from " ++ show (x', y')) $
971 up (ns ++ v) ps
972 _ -> let (ns', ps') = up ns ps in
973 (ns', (x', y', True, env', err', while, um) : ps')
974 up ns (p : ps) = let (ns', ps') = up ns ps in
975 (ns', p : ps')
977processTactic :: Tactic -> ProofState -> TC (ProofState, String)
978processTactic QED ps = case holes ps of
979 [] -> do let tm = {- normalise (context ps) [] -} getProofTerm (pterm ps)
980 (tm', ty', _) <- recheck (context ps) [] (forget tm) tm
981 return (ps { done = True, pterm = mkProofTerm tm' },
982 "Proof complete: " ++ showEnv [] tm')
983 _ -> fail "Still holes to fill."
984processTactic ProofState ps = return (ps, showEnv [] (getProofTerm (pterm ps)))
985processTactic Undo ps = case previous ps of
986 Nothing -> Error . Msg $ "Nothing to undo."
987 Just pold -> return (pold, "")
988processTactic EndUnify ps
989 = let (h, ns_in) = unified ps
990 ns = dropGiven (dontunify ps) ns_in (holes ps)
991 ns' = map (\ (n, t) -> (n, updateSolvedTerm ns t)) ns
992 (ns'', probs') = updateProblems ps ns' (problems ps)
993 tm' = updateSolved ns'' (pterm ps) in
994 traceWhen (unifylog ps) ("(EndUnify) Dropping holes: " ++ show (map fst ns'')) $
995 return (ps { pterm = tm',
996 unified = (h, []),
997 problems = probs',
998 notunified = updateNotunified ns'' (notunified ps),
999 recents = recents ps ++ map fst ns'',
1000 holes = holes ps \\ map fst ns'' }, "")
1001processTactic UnifyAll ps
1002 = let tm' = updateSolved (notunified ps) (pterm ps) in
1003 return (ps { pterm = tm',
1004 notunified = [],
1005 recents = recents ps ++ map fst (notunified ps),
1006 holes = holes ps \\ map fst (notunified ps) }, "")
1007processTactic (Reorder n) ps
1008 = do ps' <- execStateT (tactic (Just n) reorder_claims) ps
1009 return (ps' { previous = Just ps, plog = "" }, plog ps')
1010processTactic (ComputeLet n) ps
1011 = return (ps { pterm = mkProofTerm $
1012 computeLet (context ps) n
1013 (getProofTerm (pterm ps)) }, "")
1014processTactic UnifyProblems ps
1015 = do let (ns', probs') = updateProblems ps [] (map setReady (problems ps))
1016 pterm' = updateSolved ns' (pterm ps)
1017 traceWhen (unifylog ps) ("(UnifyProblems) Dropping holes: " ++ show (map fst ns')) $
1018 return (ps { pterm = pterm', solved = Nothing, problems = probs',
1019 previous = Just ps, plog = "",
1020 notunified = updateNotunified ns' (notunified ps),
1021 recents = recents ps ++ map fst ns',
1022 dotted = filter (notIn ns') (dotted ps),
1023 holes = holes ps \\ (map fst ns') }, plog ps)
1024 where notIn ns (h, _) = h `notElem` map fst ns
1025processTactic (MatchProblems all) ps
1026 = do let (ns', probs') = matchProblems all ps [] (map setReady (problems ps))
1027 (ns'', probs'') = matchProblems all ps ns' probs'
1028 pterm' = orderUpdateSolved ns'' (resetProofTerm (pterm ps))
1029 traceWhen (unifylog ps) ("(MatchProblems) Dropping holes: " ++ show ns'') $
1030 return (ps { pterm = pterm', solved = Nothing, problems = probs'',
1031 previous = Just ps, plog = "",
1032 notunified = updateNotunified ns'' (notunified ps),
1033 recents = recents ps ++ map fst ns'',
1034 holes = holes ps \\ (map fst ns'') }, plog ps)
1035 where
1036 orderUpdateSolved [] t = t
1037 orderUpdateSolved (n : ns) t = orderUpdateSolved ns (updateSolved [n] t)
1038processTactic t ps
1039 = case holes ps of
1040 [] -> case t of
1041 Focus _ -> return (ps, "") -- harmless to refocus when done, since
1042 -- 'focus' doesn't fail
1043 _ -> fail $ "Nothing to fill in."
1044 (h:_) -> do ps' <- execStateT (process t h) ps
1045 let (ns_in, probs')
1046 = case solved ps' of
1047 Just s -> traceWhen (unifylog ps)
1048 ("SOLVED " ++ show s ++ " " ++ show (dontunify ps')) $
1049 updateProblems ps' [s] (problems ps')
1050 _ -> ([], problems ps')
1051 -- rechecking problems may find more solutions, so
1052 -- apply them here
1053 let ns' = dropGiven (dontunify ps') ns_in (holes ps')
1054 let pterm'' = updateSolved ns' (pterm ps')
1055 traceWhen (unifylog ps)
1056 ("Updated problems after solve " ++ qshow probs' ++ "\n" ++
1057 "(Toplevel) Dropping holes: " ++ show (map fst ns') ++ "\n" ++
1058 "Holes were: " ++ show (holes ps')) $
1059 return (ps' { pterm = pterm'',
1060 solved = Nothing,
1061 problems = probs',
1062 notunified = updateNotunified ns' (notunified ps'),
1063 previous = Just ps, plog = "",
1064 recents = recents ps' ++ map fst ns',
1065 holes = holes ps' \\ (map fst ns')
1066 }, plog ps')
1068process :: Tactic -> Name -> StateT TState TC ()
1069process EndUnify _
1070 = do ps <- get
1071 let (h, _) = unified ps
1072 tactic (Just h) solve_unified
1073process t h = tactic (Just h) (mktac t)
1074 where mktac Attack = attack
1075 mktac (Claim n r) = claim n r
1076 mktac (ClaimFn n bn r) = claimFn n bn r
1077 mktac (Exact r) = exact r
1078 mktac (Fill r) = fill r
1079 mktac (MatchFill r) = match_fill r
1080 mktac (PrepFill n ns) = prep_fill n ns
1081 mktac CompleteFill = complete_fill
1082 mktac Solve = solve
1083 mktac (StartUnify n) = start_unify n
1084 mktac Compute = compute
1085 mktac Simplify = Idris.Core.ProofState.simplify
1086 mktac HNF_Compute = hnf_compute
1087 mktac (Intro n) = intro n
1088 mktac (IntroTy ty n) = introTy ty n
1089 mktac (Forall n i t) = forall n i t
1090 mktac (LetBind n t v) = letbind n t v
1091 mktac (ExpandLet n b) = expandLet n b
1092 mktac (Rewrite t) = rewrite t
1093 mktac (Induction t) = casetac t True
1094 mktac (CaseTac t) = casetac t False
1095 mktac (Equiv t) = equiv t
1096 mktac (PatVar n) = patvar n
1097 mktac (PatBind n) = patbind n
1098 mktac (CheckIn r) = check_in r
1099 mktac (EvalIn r) = eval_in r
1100 mktac (Focus n) = focus n
1101 mktac (Defer ns n) = defer ns n
1102 mktac (DeferType n t a) = deferType n t a
1103 mktac (Instance n) = instanceArg n
1104 mktac (AutoArg n) = autoArg n
1105 mktac (SetInjective n) = setinj n
1106 mktac (MoveLast n) = movelast n
1107 mktac (UnifyGoal r) = unifyGoal r