2Module : Idris.Core.Elaborate
3Description : A high level language of tactic composition, for building elaborators from a high level language into the core theory.
6Maintainer : The Idris Community.
8This is our interface to proof construction, rather than ProofState,
9because this gives us a language to build derived tactics out of the
13{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, PatternGuards #-}
14module Idris.Core.Elaborate (
15 module Idris.Core.Elaborate
16 , module Idris.Core.ProofState
19import Idris.Core.Evaluate
20import Idris.Core.ProofState
21import Idris.Core.ProofTerm (bound_in, bound_in_term, getProofTerm, mkProofTerm,
24import Idris.Core.Typecheck
25import Idris.Core.Unify
27import Control.Monad.State.Strict
30data ElabState aux = ES (ProofState, aux) String (Maybe (ElabState aux))
33type Elab' aux a = StateT (ElabState aux) TC a
34type Elab a = Elab' () a
36proof :: ElabState aux -> ProofState
37proof (ES (p, _) _ _) = p
39-- Insert a 'proofSearchFail' error if necessary to shortcut any further
41proofFail :: Elab' aux a -> Elab' aux a
42proofFail e = do s <- get
44 OK (a, s') -> do put s'
46 Error err -> lift $ Error (ProofSearchFail err)
48explicit :: Name -> Elab' aux ()
49explicit n = do ES (p, a) s m <- get
50 let p' = p { dontunify = n : dontunify p }
53-- Add a name that's okay to use in proof search (typically either because
54-- it was given explicitly on the lhs, or intrduced as an explicit lambda
56addPSname :: Name -> Elab' aux ()
58 = do ES (p, a) s m <- get
59 let p' = p { psnames = n : psnames p }
61addPSname _ = return () -- can only use user given names
63getPSnames :: Elab' aux [Name]
64getPSnames = do ES (p, a) s m <- get
67saveState :: Elab' aux ()
68saveState = do e@(ES p s _) <- get
71loadState :: Elab' aux ()
72loadState = do (ES p s e) <- get
75 _ -> lift $ Error . Msg $ "Nothing to undo"
77getNameFrom :: Name -> Elab' aux Name
78getNameFrom n = do (ES (p, a) s e) <- get
80 let p' = p { nextname = next + 1 }
83 UN x -> MN (next+100) x
84 MN i x -> if i == 99999
87 NS (UN x) s -> MN (next+100) x
91setNextName :: Elab' aux ()
92setNextName = do env <- get_env
94 let pargs = map fst (getArgTys (ptype p))
95 initNextNameFrom (pargs ++ map fstEnv env)
97initNextNameFrom :: [Name] -> Elab' aux ()
98initNextNameFrom ns = do ES (p, a) s e <- get
99 let n' = maxName (nextname p) ns
100 put (ES (p { nextname = n' }, a) s e)
102 maxName m ((MN i _) : xs) = maxName (max m i) xs
103 maxName m (_ : xs) = maxName m xs
107-- | Transform the error returned by an elaboration script, preserving
108-- location information and proof search failure messages.
109transformErr :: (Err -> Err) -> Elab' aux a -> Elab' aux a
110transformErr f elab = do s <- get
111 case runStateT elab s of
112 OK (a, s') -> do put s'
114 Error e -> lift $ Error (rewriteErr e)
117 rewriteErr (At f e) = At f (rewriteErr e)
118 rewriteErr (ProofSearchFail e) = ProofSearchFail (rewriteErr e)
121errAt :: String -> Name -> Maybe Type -> Elab' aux a -> Elab' aux a
122errAt thing n ty = transformErr (Elaborating thing n ty)
125erunAux :: FC -> Elab' aux a -> Elab' aux (a, aux)
128 case runStateT elab s of
129 OK (a, s') -> do put s'
132 Error (ProofSearchFail (At f e))
133 -> lift $ Error (ProofSearchFail (At f e))
134 Error (At f e) -> lift $ Error (At f e)
135 Error e -> lift $ Error (At f e)
137erun :: FC -> Elab' aux a -> Elab' aux a
138erun f e = do (x, _) <- erunAux f e
141runElab :: aux -> Elab' aux a -> ProofState -> TC (a, ElabState aux)
142runElab a e ps = runStateT e (ES (ps, a) "" Nothing)
144execElab :: aux -> Elab' aux a -> ProofState -> TC (ElabState aux)
145execElab a e ps = execStateT e (ES (ps, a) "" Nothing)
147initElaborator :: Name -- ^ the name of what's to be elaborated
148 -> String -- ^ the current source file
149 -> Context -- ^ the current global context
150 -> Ctxt TypeInfo -- ^ the value of the idris_datatypes field of IState
151 -> Int -- ^ the value of the idris_name field of IState
152 -> Type -- ^ the goal type
154initElaborator = newProof
156elaborate :: String -> Context -> Ctxt TypeInfo -> Int -> Name -> Type -> aux -> Elab' aux a -> TC (a, String)
157elaborate tcns ctxt datatypes globalNames n ty d elab =
158 do let ps = initElaborator n tcns ctxt datatypes globalNames ty
159 (a, ES ps' str _) <- runElab d elab ps
162-- | Modify the auxiliary state
163updateAux :: (aux -> aux) -> Elab' aux ()
164updateAux f = do ES (ps, a) l p <- get
165 put (ES (ps, f a) l p)
167-- | Get the auxiliary state
168getAux :: Elab' aux aux
169getAux = do ES (ps, a) _ _ <- get
172-- | Set whether to show the unifier log
173unifyLog :: Bool -> Elab' aux ()
174unifyLog log = do ES (ps, a) l p <- get
175 put (ES (ps { unifylog = log }, a) l p)
177getUnifyLog :: Elab' aux Bool
178getUnifyLog = do ES (ps, a) l p <- get
181-- | Process a tactic within the current elaborator state
182processTactic' :: Tactic -> Elab' aux ()
183processTactic' t = do ES (p, a) logs prev <- get
184 (p', log) <- lift $ processTactic t p
185 put (ES (p', a) (logs ++ log) prev)
188updatePS :: (ProofState -> ProofState) -> Elab' aux ()
189updatePS f = do ES (ps, a) logs prev <- get
190 put $ ES (f ps, a) logs prev
192now_elaborating :: FC -> Name -> Name -> Elab' aux ()
193now_elaborating fc f a = updatePS (nowElaboratingPS fc f a)
194done_elaborating_app :: Name -> Elab' aux ()
195done_elaborating_app f = updatePS (doneElaboratingAppPS f)
196done_elaborating_arg :: Name -> Name -> Elab' aux ()
197done_elaborating_arg f a = updatePS (doneElaboratingArgPS f a)
198elaborating_app :: Elab' aux [(FC, Name, Name)]
199elaborating_app = do ES (ps, _) _ _ <- get
200 return $ map (\ (FailContext x y z) -> (x, y, z))
201 (while_elaborating ps)
203-- Some handy gadgets for pulling out bits of state
205-- | Get the global context
206get_context :: Elab' aux Context
207get_context = do ES p _ _ <- get
208 return $! (context (fst p))
210-- | Update the context.
211-- (should only be used for adding temporary definitions or all sorts of
212-- stuff could go wrong)
213set_context :: Context -> Elab' aux ()
214set_context ctxt = do ES (p, a) logs prev <- get
215 put (ES (p { context = ctxt }, a) logs prev)
217get_datatypes :: Elab' aux (Ctxt TypeInfo)
218get_datatypes = do ES p _ _ <- get
219 return $! (datatypes (fst p))
221set_datatypes :: Ctxt TypeInfo -> Elab' aux ()
222set_datatypes ds = do ES (p, a) logs prev <- get
223 put (ES (p { datatypes = ds }, a) logs prev)
225get_global_nextname :: Elab' aux Int
226get_global_nextname = do ES (ps, _) _ _ <- get
227 return (global_nextname ps)
229set_global_nextname :: Int -> Elab' aux ()
230set_global_nextname i = do ES (ps, a) logs prev <- get
231 put $ ES (ps { global_nextname = i}, a) logs prev
233-- | get the proof term
234get_term :: Elab' aux Term
235get_term = do ES p _ _ <- get
236 return $! (getProofTerm (pterm (fst p)))
238-- | modify the proof term
239update_term :: (Term -> Term) -> Elab' aux ()
240update_term f = do ES (p,a) logs prev <- get
241 let p' = p { pterm = mkProofTerm (f (getProofTerm (pterm p))) }
242 put (ES (p', a) logs prev)
244-- | get the local context at the currently in focus hole
245get_env :: Elab' aux Env
246get_env = do ES p _ _ <- get
247 lift $ envAtFocus (fst p)
249get_inj :: Elab' aux [Name]
250get_inj = do ES p _ _ <- get
251 return $! (injective (fst p))
253get_holes :: Elab' aux [Name]
254get_holes = do ES p _ _ <- get
255 return $! (holes (fst p))
257get_usedns :: Elab' aux [Name]
258get_usedns = do ES p _ _ <- get
259 let bs = bound_in (pterm (fst p)) ++
260 bound_in_term (ptype (fst p))
261 let nouse = holes (fst p) ++ bs ++ dontunify (fst p) ++ usedns (fst p)
264get_probs :: Elab' aux Fails
265get_probs = do ES p _ _ <- get
266 return $! (problems (fst p))
268-- | Return recently solved names (that is, the names solved since the
269-- last call to get_recents)
270get_recents :: Elab' aux [Name]
271get_recents = do ES (p, a) l prev <- get
272 put (ES (p { recents = [] }, a) l prev)
275-- | get the current goal type
276goal :: Elab' aux Type
277goal = do ES p _ _ <- get
278 b <- lift $ goalAtFocus (fst p)
279 return $! (binderTy b)
281is_guess :: Elab' aux Bool
282is_guess = do ES p _ _ <- get
283 b <- lift $ goalAtFocus (fst p)
285 Guess _ _ -> return True
288-- | Get the guess at the current hole, if there is one
289get_guess :: Elab' aux Term
290get_guess = do ES p _ _ <- get
291 b <- lift $ goalAtFocus (fst p)
293 Guess t v -> return $! v
294 _ -> fail "Not a guess"
296-- | Typecheck locally
297get_type :: Raw -> Elab' aux Type
298get_type tm = do ctxt <- get_context
300 (val, ty) <- lift $ check ctxt env tm
301 return $! (finalise ty)
303get_type_val :: Raw -> Elab' aux (Term, Type)
304get_type_val tm = do ctxt <- get_context
306 (val, ty) <- lift $ check ctxt env tm
307 return $! (finalise val, finalise ty)
309-- | get holes we've deferred for later definition
310get_deferred :: Elab' aux [Name]
311get_deferred = do ES p _ _ <- get
312 return $! (deferred (fst p))
314checkInjective :: (Term, Term, Term) -> Elab' aux ()
315checkInjective (tm, l, r) = do ctxt <- get_context
316 if isInj ctxt tm then return $! ()
317 else lift $ tfail (NotInjective tm l r)
318 where isInj ctxt (P _ n _)
319 | isConName n ctxt = True
320 isInj ctxt (App _ f a) = isInj ctxt f
321 isInj ctxt (Constant _) = True
322 isInj ctxt (TType _) = True
323 isInj ctxt (Bind _ (Pi _ _ _ _) sc) = True
326-- | get implementation argument names
327get_implementations :: Elab' aux [Name]
328get_implementations = do ES p _ _ <- get
329 return $! (implementations (fst p))
331-- | get auto argument names
332get_autos :: Elab' aux [(Name, ([FailContext], [Name]))]
333get_autos = do ES p _ _ <- get
334 return $! (autos (fst p))
336-- | given a desired hole name, return a unique hole name
337unique_hole :: Name -> Elab' aux Name
338unique_hole = unique_hole' False
340unique_hole' :: Bool -> Name -> Elab' aux Name
341unique_hole' reusable n
343 let bs = bound_in (pterm (fst p)) ++
344 bound_in_term (ptype (fst p))
345 let nouse = holes (fst p) ++ bs ++ dontunify (fst p) ++ usedns (fst p)
346 n' <- return $! uniqueNameCtxt (context (fst p)) n nouse
349 MN i _ -> when (i >= nextname p) $
350 put (ES (p { nextname = i + 1 }, a) s u)
354elog :: String -> Elab' aux ()
355elog str = do ES p logs prev <- get
356 put (ES p (logs ++ str ++ "\n") prev)
358getLog :: Elab' aux String
359getLog = do ES p logs _ <- get
362-- The primitives, from ProofState
364attack :: Elab' aux ()
365attack = processTactic' Attack
367claim :: Name -> Raw -> Elab' aux ()
368claim n t = processTactic' (Claim n t)
370claimFn :: Name -> Name -> Raw -> Elab' aux ()
371claimFn n bn t = processTactic' (ClaimFn n bn t)
373unifyGoal :: Raw -> Elab' aux ()
374unifyGoal t = processTactic' (UnifyGoal t)
376unifyTerms :: Raw -> Raw -> Elab' aux ()
377unifyTerms t1 t2 = processTactic' (UnifyTerms t1 t2)
379exact :: Raw -> Elab' aux ()
380exact t = processTactic' (Exact t)
382fill :: Raw -> Elab' aux ()
383fill t = processTactic' (Fill t)
385match_fill :: Raw -> Elab' aux ()
386match_fill t = processTactic' (MatchFill t)
388prep_fill :: Name -> [Name] -> Elab' aux ()
389prep_fill n ns = processTactic' (PrepFill n ns)
391complete_fill :: Elab' aux ()
392complete_fill = processTactic' CompleteFill
395solve = processTactic' Solve
397start_unify :: Name -> Elab' aux ()
398start_unify n = processTactic' (StartUnify n)
400end_unify :: Elab' aux ()
401end_unify = processTactic' EndUnify
403-- Clear the list of variables not to unify, and try to solve them
404unify_all :: Elab' aux ()
405unify_all = processTactic' UnifyAll
407regret :: Elab' aux ()
408regret = processTactic' Regret
410compute :: Elab' aux ()
411compute = processTactic' Compute
413computeLet :: Name -> Elab' aux ()
414computeLet n = processTactic' (ComputeLet n)
416simplify :: Elab' aux ()
417simplify = processTactic' Simplify
419whnf_compute :: Elab' aux ()
420whnf_compute = processTactic' WHNF_Compute
422whnf_compute_args :: Elab' aux ()
423whnf_compute_args = processTactic' WHNF_ComputeArgs
425eval_in :: Raw -> Elab' aux ()
426eval_in t = processTactic' (EvalIn t)
428check_in :: Raw -> Elab' aux ()
429check_in t = processTactic' (CheckIn t)
431intro :: Maybe Name -> Elab' aux ()
432intro n = processTactic' (Intro n)
434introTy :: Raw -> Maybe Name -> Elab' aux ()
435introTy ty n = processTactic' (IntroTy ty n)
437forall :: Name -> RigCount -> Maybe ImplicitInfo -> Raw -> Elab' aux ()
438forall n r i t = processTactic' (Forall n r i t)
440letbind :: Name -> RigCount -> Raw -> Raw -> Elab' aux ()
441letbind n rig t v = processTactic' (LetBind n rig t v)
443expandLet :: Name -> Term -> Elab' aux ()
444expandLet n v = processTactic' (ExpandLet n v)
446rewrite :: Raw -> Elab' aux ()
447rewrite tm = processTactic' (Rewrite tm)
449equiv :: Raw -> Elab' aux ()
450equiv tm = processTactic' (Equiv tm)
452-- | Turn the current hole into a pattern variable with the provided
453-- name, made unique if not the same as the head of the hole queue
454patvar :: Name -> Elab' aux ()
455patvar n@(SN _) = do apply (Var n) []; solve
456patvar n = do env <- get_env
458 if (n `elem` map fstEnv env) then do apply (Var n) []; solve
459 else do n' <- case hs of
460 (h : hs) -> if n == h then return n
463 processTactic' (PatVar n)
465-- | Turn the current hole into a pattern variable with the provided
466-- name, but don't make MNs unique.
467patvar' :: Name -> Elab' aux ()
468patvar' n@(SN _) = do apply (Var n) [] ; solve
469patvar' n = do env <- get_env
471 if (n `elem` map fstEnv env) then do apply (Var n) [] ; solve
472 else processTactic' (PatVar n)
474patbind :: Name -> RigCount -> Elab' aux ()
475patbind n r = processTactic' (PatBind n r)
477focus :: Name -> Elab' aux ()
478focus n = processTactic' (Focus n)
480movelast :: Name -> Elab' aux ()
481movelast n = processTactic' (MoveLast n)
483dotterm :: Elab' aux ()
484dotterm = do ES (p, a) s m <- get
489 do let outer = findOuter h [] tm
490 let p' = p { dotted = (h, outer) : dotted p }
491-- trace ("DOTTING " ++ show (h, outer) ++ "\n" ++
495 findOuter h env (P _ n _) | h == n = env
496 findOuter h env (Bind n b sc)
498 (findOuter h env (instantiate (P Bound n (binderTy b)) sc))
499 where foB (Guess t v) = union (findOuter h env t) (findOuter h (n:env) v)
500 foB (Let _ t v) = union (findOuter h env t) (findOuter h env v)
501 foB b = findOuter h env (binderTy b)
502 findOuter h env (App _ f a)
503 = union (findOuter h env f) (findOuter h env a)
504 findOuter h env _ = []
507get_dotterm :: Elab' aux [(Name, [Name])]
508get_dotterm = do ES (p, a) s m <- get
511-- | Set the zipper in the proof state to point at the current sub term
512-- (This currently happens automatically, so this will have no effect...)
513zipHere :: Elab' aux ()
514zipHere = do ES (ps, a) s m <- get
515 let pt' = refocus (Just (head (holes ps))) (pterm ps)
516 put (ES (ps { pterm = pt' }, a) s m)
518matchProblems :: Bool -> Elab' aux ()
519matchProblems all = processTactic' (MatchProblems all)
521unifyProblems :: Elab' aux ()
522unifyProblems = processTactic' UnifyProblems
524defer :: [Name] -> [Name] -> Name -> Elab' aux Name
526 = do n' <- unique_hole n
527 processTactic' (Defer ds ls n')
530deferType :: Name -> Raw -> [Name] -> Elab' aux ()
531deferType n ty ns = processTactic' (DeferType n ty ns)
533implementationArg :: Name -> Elab' aux ()
534implementationArg n = processTactic' (Implementation n)
536autoArg :: Name -> Elab' aux ()
537autoArg n = processTactic' (AutoArg n)
539setinj :: Name -> Elab' aux ()
540setinj n = processTactic' (SetInjective n)
542proofstate :: Elab' aux ()
543proofstate = processTactic' ProofState
545reorder_claims :: Name -> Elab' aux ()
546reorder_claims n = processTactic' (Reorder n)
549qed = do processTactic' QED
551 return $! (getProofTerm (pterm (fst p)))
554undo = processTactic' Undo
556-- | Prepare to apply a function by creating holes to be filled by the arguments
557prepare_apply :: Raw -- ^ The operation being applied
558 -> [Bool] -- ^ Whether arguments are implicit
559 -> Elab' aux [(Name, Name)] -- ^ The names of the arguments and their holes to be filled with elaborated argument values
560prepare_apply fn imps =
564 -- let claims = getArgs ty imps
565 -- claims <- mkClaims (normalise ctxt env ty) imps []
566 -- Count arguments to check if we need to normalise the type
567 let usety = if argsOK (finalise ty) imps
569 else normalise ctxt env (finalise ty)
570 claims <- -- trace (show (fn, imps, ty, map fst env, normalise ctxt env (finalise ty))) $
571 mkClaims usety imps [] (map fstEnv env)
572 ES (p, a) s prev <- get
573 -- reverse the claims we made so that args go left to right
574 let n = length (filter not imps)
575 let (h : hs) = holes p
576 put (ES (p { holes = h : (reverse (take n hs) ++ drop n hs) }, a) s prev)
579 argsOK :: Type -> [a] -> Bool
580 argsOK (Bind n (Pi _ _ _ _) sc) (i : is) = argsOK sc is
581 argsOK _ (i : is) = False
584 mkClaims :: Type -- ^ The type of the operation being applied
585 -> [Bool] -- ^ Whether the arguments are implicit
586 -> [(Name, Name)] -- ^ Accumulator for produced claims
587 -> [Name] -- ^ Hypotheses
588 -> Elab' aux [(Name, Name)] -- ^ The names of the arguments and their holes, resp.
589 mkClaims (Bind n' (Pi _ _ t_in _) sc) (i : is) claims hs =
590 do let t = rebind hs t_in
591 n <- getNameFrom (mkMN n')
592-- when (null claims) (start_unify n)
593 let sc' = instantiate (P Bound n t) sc
595 claim n (forgetEnv (map fstEnv env) t)
597 mkClaims sc' is ((n', n) : claims) hs
598 mkClaims t [] claims _ = return $! (reverse claims)
601 = do ctxt <- get_context
602 lift $ tfail $ TooManyArguments n
603 | otherwise = fail $ "Too many arguments for " ++ show fn
606 mkMN n@(UN x) = MN 99999 x
607 mkMN n@(SN s) = sMN 99999 (show s)
608 mkMN (NS n xs) = NS (mkMN n) xs
610 rebind hs (Bind n t sc)
611 | n `elem` hs = let n' = uniqueName n hs in
612 Bind n' (fmap (rebind hs) t) (rebind (n':hs) sc)
613 | otherwise = Bind n (fmap (rebind hs) t) (rebind (n:hs) sc)
614 rebind hs (App s f a) = App s (rebind hs f) (rebind hs a)
617-- | Apply an operator, solving some arguments by unification or matching.
618apply, match_apply :: Raw -- ^ The operator to apply
619 -> [(Bool, Int)] -- ^ For each argument, whether to
620 -- attempt to solve it and the
621 -- priority in which to do so
622 -> Elab' aux [(Name, Name)]
624match_apply = apply' match_fill
626apply' :: (Raw -> Elab' aux ()) -> Raw -> [(Bool, Int)] -> Elab' aux [(Name, Name)]
627apply' fillt fn imps =
628 do args <- prepare_apply fn (map fst imps)
629 -- _Don't_ solve the arguments we're specifying by hand.
630 -- (remove from unified list before calling end_unify)
632 ES (p, a) s prev <- get
633 let dont = if null imps
634 then head hs : dontunify p
635 else getNonUnify (head hs : dontunify p) imps args
636 let (n, hunis) = -- trace ("AVOID UNIFY: " ++ show (fn, dont)) $
638 let unify = -- trace ("Not done " ++ show hs) $
639 dropGiven dont hunis hs
640 let notunify = -- trace ("Not done " ++ show (hs, hunis)) $
641 keepGiven dont hunis hs
642 put (ES (p { dontunify = dont, unified = (n, unify),
643 notunified = notunify ++ notunified p }, a) s prev)
644 fillt (raw_apply fn (map (Var . snd) args))
648 ("Goal " ++ show g ++ " -- when elaborating " ++ show fn)
650 return $! (map (\(argName, argHole) -> (argName, updateUnify unify argHole)) args)
651 where updateUnify us n = case lookup n us of
655 getNonUnify acc [] _ = acc
656 getNonUnify acc _ [] = acc
657 getNonUnify acc ((i,_):is) ((a, t):as)
658 | i = getNonUnify acc is as
659 | otherwise = getNonUnify (t : acc) is as
662apply2 :: Raw -> [Maybe (Elab' aux ())] -> Elab' aux ()
664 do args <- prepare_apply fn (map isJust elabs)
665 fill (raw_apply fn (map (Var . snd) args))
666 elabArgs (map snd args) elabs
667 ES (p, a) s prev <- get
670 where elabArgs [] [] = return $! ()
671 elabArgs (n:ns) (Just e:es) = do focus n; e
673 elabArgs (n:ns) (_:es) = elabArgs ns es
675 isJust (Just _) = False
678apply_elab :: Name -> [Maybe (Int, Elab' aux ())] -> Elab' aux ()
680 do ty <- get_type (Var n)
683 claims <- doClaims (normalise ctxt env ty) args []
684 prep_fill n (map fst claims)
685 elabClaims [] False claims
689 doClaims (Bind n' (Pi _ _ t _) sc) (i : is) claims =
690 do n <- unique_hole (mkMN n')
691 when (null claims) (start_unify n)
692 let sc' = instantiate (P Bound n t) sc
695 Nothing -> return $! ()
696 Just _ -> -- don't solve by unification as there is an explicit value
697 do ES (p, a) s prev <- get
698 put (ES (p { dontunify = n : dontunify p }, a) s prev)
699 doClaims sc' is ((n, i) : claims)
700 doClaims t [] claims = return $! (reverse claims)
701 doClaims _ _ _ = fail $ "Wrong number of arguments for " ++ show n
703 elabClaims failed r []
704 | null failed = return $! ()
705 | otherwise = if r then elabClaims [] False failed
707 elabClaims failed r ((n, Nothing) : xs) = elabClaims failed r xs
708 elabClaims failed r (e@(n, Just (_, elaboration)) : xs)
709 | r = try (do ES p _ _ <- get
710 focus n; elaboration; elabClaims failed r xs)
711 (elabClaims (e : failed) r xs)
712 | otherwise = do ES p _ _ <- get
713 focus n; elaboration; elabClaims failed r xs
716 mkMN n@(UN x) = MN 0 x
717 mkMN (NS n ns) = NS (mkMN n) ns
719-- If the goal is not a Pi-type, invent some names and make it a pi type
720checkPiGoal :: Name -> Elab' aux ()
725 case (normalise ctxt env g) of
726 Bind _ (Pi _ _ _ _) _ -> return ()
727 _ -> do a <- getNameFrom (sMN 0 "__pargTy")
728 b <- getNameFrom (sMN 0 "__pretTy")
729 f <- getNameFrom (sMN 0 "pf")
732 claim f (RBind n (Pi RigW Nothing (Var a) RType) (Var b))
739simple_app :: Bool -> Elab' aux () -> Elab' aux () -> String -> Elab' aux ()
740simple_app infer fun arg str =
741 try (dep_app fun arg str)
742 (infer_app infer fun arg str)
744infer_app :: Bool -> Elab' aux () -> Elab' aux () -> String -> Elab' aux ()
745infer_app infer fun arg str =
746 do a <- getNameFrom (sMN 0 "__argTy")
747 b <- getNameFrom (sMN 0 "__retTy")
748 f <- getNameFrom (sMN 0 "f")
749 s <- getNameFrom (sMN 0 "is")
752 claim f (RBind (sMN 0 "_aX") (Pi RigW Nothing (Var a) RType) (Var b))
755 -- if 'infer' is set, we're assuming it's a simply typed application
756 -- so safe to unify with the goal type (as there'll be no dependencies)
757 when infer $ unifyGoal (Var b)
769 -- We don't need a and b in the hole queue any more since they were
770 -- just for checking f, so move them to the end. If they never end up
771 -- getting solved, we'll get an 'Incomplete term' error.
773 when (a `elem` hs) $ do movelast a
774 when (b `elem` hs) $ do movelast b
777dep_app :: Elab' aux () -> Elab' aux () -> String -> Elab' aux ()
779 do a <- getNameFrom (sMN 0 "__argTy")
780 b <- getNameFrom (sMN 0 "__retTy")
781 fty <- getNameFrom (sMN 0 "__fnTy")
782 f <- getNameFrom (sMN 0 "f")
783 s <- getNameFrom (sMN 0 "ds")
800 case normalise ctxt env fty of
801 -- if f gives a function type, unify our argument type with
802 -- f's expected argument type
803 Bind _ (Pi _ _ argty _) _ -> unifyGoal (forget argty)
804 -- Can't infer a type for 'f', so fail here (and drop back to
805 -- simply typed application where we infer the type for f)
806 _ -> fail "Can't make type"
812 -- We don't need a and b in the hole queue any more since they were
813 -- just for checking f, so move them to the end. If they never end up
814 -- getting solved, we'll get an 'Incomplete term' error.
816 when (a `elem` hs) $ do movelast a
817 when (b `elem` hs) $ do movelast b
820-- Abstract over an argument of unknown type, giving a name for the hole
821-- which we'll fill with the argument type too.
822arg :: Name -> RigCount -> Maybe ImplicitInfo -> Name -> Elab' aux ()
823arg n r i tyhole = do ty <- unique_hole tyhole
826 forall n r i (Var ty)
828-- try a tactic, if it adds any unification problem, return an error
829no_errors :: Elab' aux () -> Maybe Err -> Elab' aux ()
835 Just e -> -- update the error, if there is one.
836 case runStateT tac s of
837 Error _ -> lift $ Error e
838 OK (a, s') -> do put s'
842 if (length ps' > length ps) then
844 ((x, y, _, env, inerr, while, _) : _) ->
845 let (xp, yp) = getProvenance inerr
846 env' = map (\(x, rig, b) -> (x, binderTy b)) env in
849 Nothing -> CantUnify False (x, xp) (y, yp) inerr env' 0
853-- Try a tactic, if it fails, try another
854try :: Elab' aux a -> Elab' aux a -> Elab' aux a
855try t1 t2 = try' t1 t2 False
857handleError :: (Err -> Bool) -> Elab' aux a -> Elab' aux a -> Elab' aux a
861 case runStateT t1 s of
862 OK (v, s') -> do put s'
864 Error e1 -> if p e1 then
865 do case runStateT t2 s of
866 OK (v, s') -> do put s'; return $! v
867 Error e2 -> lift (tfail e2)
870try' :: Elab' aux a -> Elab' aux a -> Bool -> Elab' aux a
871try' t1 t2 proofSearch
875 ivs <- get_implementations
876 case prunStateT 999999 False ps Nothing t1 s of
877 OK ((v, _, _), s') -> do put s'
879 Error e1 -> traceWhen ulog ("try failed " ++ show e1) $
880 if recoverableErr e1 then
881 do case runStateT t2 s of
882 OK (v, s') -> do put s'; return $! v
883 Error e2 -> lift (tfail e2)
885 where recoverableErr err@(CantUnify r x y _ _ _)
886 = -- traceWhen r (show err) $
888 recoverableErr (CantSolveGoal _ _) = False
889 recoverableErr (CantResolveAlts _) = proofSearch
890 recoverableErr (ProofSearchFail (Msg _)) = True
891 recoverableErr (ProofSearchFail _) = False
892 recoverableErr (ElaboratingArg _ _ _ e) = recoverableErr e
893 recoverableErr (At _ e) = recoverableErr e
894 recoverableErr (ElabScriptDebug _ _ _) = False
895 recoverableErr _ = True
897tryCatch :: Elab' aux a -> (Err -> Elab' aux a) -> Elab' aux a
902-- case prunStateT 999999 False ps t1 s of
903 case runStateT t1 s of
904 OK (v, s') -> do put s'
906 Error e1 -> traceWhen ulog ("tryCatch failed " ++ show e1) $
907 case runStateT (t2 e1) s of
908 OK (v, s') -> do put s'
910 Error e2 -> lift (tfail e2)
912tryWhen :: Bool -> Elab' aux a -> Elab' aux a -> Elab' aux a
913tryWhen True a b = try a b
916-- Bool says whether it's okay to create new unification problems. If set
917-- to False, then the whole tactic fails if there are any new problems
918tryAll :: [(Elab' aux a, Name)] -> Elab' aux a
921tryAll' :: Bool -> [(Elab' aux a, Name)] -> Elab' aux a
922tryAll' _ [(x, _)] = x
923tryAll' constrok xs = doAll [] 999999 xs
925 cantResolve :: Elab' aux a
926 cantResolve = lift $ tfail $ CantResolveAlts (map snd xs)
928 noneValid :: Elab' aux a
929 noneValid = lift $ tfail $ NoValidAlts (map snd xs)
931 doAll :: [Elab' aux a] -> -- successes
932 Int -> -- most problems
933 [(Elab' aux a, Name)] -> -- still to try
935 doAll [res] pmax [] = res
936 doAll (_:_) pmax [] = cantResolve
937 doAll [] pmax [] = noneValid
938 doAll cs pmax ((x, msg):xs)
941 ivs <- get_implementations
943 case prunStateT pmax True ps (if constrok then Nothing
944 else Just ivs) x s of
945 OK ((v, newps, probs), s') ->
946 do let cs' = if (newps < pmax)
947 then [do put s'; return $! v]
948 else (do put s'; return $! v) : cs
951 Error err -> do put s
954-- Run an elaborator, and fail if any problems or constraints are introduced
959 -> Maybe [b] -- constraints left, if we're interested
960 -> Control.Monad.State.Strict.StateT
963 -> TC ((t1, Int, Idris.Core.Unify.Fails), ElabState t)
964prunStateT pmax zok ps ivs x s
965 = case runStateT x s of
966 OK (v, s'@(ES (p, _) _ _)) ->
967 let newps = length (problems p) - length ps
968 ibad = badImplementations (implementations p) ivs
969 newpmax = if newps < 0 then 0 else newps in
970 if (newpmax > pmax || (not zok && newps > 0)) -- length ps == 0 && newpmax > 0))
971 then case reverse (problems p) of
972 ((_,_,_,_,e,_,_):_) -> Error e
974 then Error (InternalMsg "Constraint introduced in disambiguation")
975 else OK ((v, newpmax, problems p), s')
978 badImplementations _ Nothing = False
979 badImplementations inow (Just ithen) = length inow > length ithen
981debugElaborator :: [ErrorReportPart] -> Elab' aux a
982debugElaborator msg = do ps <- fmap proof get
983 saveState -- so we don't need to remember the hole order
985 holeInfo <- mapM getHoleInfo hs
987 lift . Error $ ElabScriptDebug msg (getProofTerm (pterm ps)) holeInfo
988 where getHoleInfo :: Name -> Elab' aux (Name, Type, [(Name, Binder Type)])
989 getHoleInfo h = do focus h
992 return (h, g, envBinders env)
994qshow :: Fails -> String
995qshow fs = show (map (\ (x, y, _, _, _, _, _) -> (x, y)) fs)
998dumpprobs ((_,_,_,e):es) = show e ++ "\n" ++ dumpprobs es
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list