on master help sign in
Improve elaboration efficiency by cutting down on excessive backtracking
commit265d9a4adc00310b242f94cde90e072e622e8ec5 authorEdwin Brady <ecb10@st-andrews.ac.uk> dateFri 11 Jan 2013, 17:47 (14 years ago) parent7a66adc
7 files changed+106−55
lib/Language/Reflection.idr+1 src/Core/Unify.hs+34−13 src/Idris/AbsSyntaxTree.hs+1 src/Idris/ElabTerm.hs+52−42 test/reg008/expected test/reg008/reg008.idr+15 test/reg008/run+3
lib/Language/Reflection.idr+1
@@ -10,6 +10,7 @@ data TT = Var TTName
1010 | App TTName TT TT
1111
1212data Tactic = Try Tactic Tactic
13+ | GoalType TTName Tactic -- only run if the goal has the right type
1314 | Refine TTName
1415 | Seq Tactic Tactic
1516 | Trivial
src/Core/Unify.hs+34−13
@@ -21,18 +21,21 @@ type Injs = [(TT Name, TT Name, TT Name)]
2121type Fails = [(TT Name, TT Name, Env, Err)]
2222
2323data UInfo = UI Int Injs Fails
24+ deriving Show
2425
2526unify :: Context -> Env -> TT Name -> TT Name -> TC ([(Name, TT Name)],
2627 Injs, Fails)
2728unify ctxt env topx topy =
2829-- trace ("Unifying " ++ show (topx, topy)) $
29− case runStateT (un' False [] topx topy) (UI 0 [] []) of
30− OK (v, UI _ inj []) -> return (filter notTrivial v, inj, [])
31− _ ->
30+ -- don't bother if topx and topy are different at the head
31+ case runStateT (un False [] topx topy) (UI 0 [] []) of
32+ OK (v, UI _ inj []) -> return (filter notTrivial v, inj, [])
33+-- Error e@(CantUnify False _ _ _ _ _) -> tfail e
34+ res ->
3235 let topxn = normalise ctxt env topx
3336 topyn = normalise ctxt env topy in
34−-- trace ("Unifying " ++ show (topx, topy) ++ "\n\n==>\n" ++ show (topxn, topyn) ++ "\n\n") $
35− case runStateT (un' False [] topxn topyn)
37+-- trace ("Unifying " ++ show (topx, topy) ++ "\n\n==>\n" ++ show (topxn, topyn) ++ "\n\n" ++ show res ++ "\n\n") $
38+ case runStateT (un False [] topxn topyn)
3639 (UI 0 [] []) of
3740 OK (v, UI _ inj fails) ->
3841 return (filter notTrivial v, inj, reverse fails)
@@ -41,6 +44,10 @@ unify ctxt env topx topy =
4144 notTrivial (x, P _ x' _) = x /= x'
4245 notTrivial _ = True
4346
47+ headDiff (P (DCon _ _) x _) (P (DCon _ _) y _) = x /= y
48+ headDiff (P (TCon _ _) x _) (P (TCon _ _) y _) = x /= y
49+ headDiff _ _ = False
50+
4451 injective (P (DCon _ _) _ _) = True
4552 injective (P (TCon _ _) _ _) = True
4653 injective (App f a) = injective f
@@ -59,6 +66,16 @@ unify ctxt env topx topy =
5966 then return r
6067 else do put (UI s i f); u2
6168
69+ un :: Bool -> [(Name, Name)] -> TT Name -> TT Name ->
70+ StateT UInfo
71+ TC [(Name, TT Name)]
72+ un fn names x y
73+ = let (xf, _) = unApply x
74+ (yf, _) = unApply y in
75+ if headDiff xf yf then unifyFail x y else
76+ uplus (un' fn names x y)
77+ (un' fn names (hnf ctxt env x) (hnf ctxt env y))
78+
6279 un' :: Bool -> [(Name, Name)] -> TT Name -> TT Name ->
6380 StateT UInfo
6481 TC [(Name, TT Name)]
@@ -102,10 +119,10 @@ unify ctxt env topx topy =
102119 (do hf <- un' True bnames fx fy
103120 let ax' = hnormalise hf ctxt env (substNames hf ax)
104121 let ay' = hnormalise hf ctxt env (substNames hf ay)
105− ha <- un' False bnames ax' ay'
122+ ha <- un False bnames ax' ay'
106123 sc 1
107124 combine bnames hf ha)
108− (do ha <- un' False bnames ax ay
125+ (do ha <- un False bnames ax ay
109126 let fx' = hnormalise ha ctxt env (substNames ha fx)
110127 let fy' = hnormalise ha ctxt env (substNames ha fy)
111128 hf <- un' False bnames fx' fy'
@@ -141,8 +158,9 @@ unify ctxt env topx topy =
141158 let r = recoverable x y
142159 let err = CantUnify r
143160 topx topy (CantUnify r x y (Msg "") [] s) (errEnv env) s
144− put (UI s i ((x, y, env, err) : f))
145− return [] -- lift $ tfail err
161+ if (not r) then lift $ tfail err
162+ else do put (UI s i ((x, y, env, err) : f))
163+ return [] -- lift $ tfail err
146164
147165 -- shortcut failure, if we *know* nothing can fix it
148166 unifyFail x y = do UI s i f <- get
@@ -198,12 +216,15 @@ unify ctxt env topx topy =
198216 recoverable (P (DCon _ _) x _) (P (DCon _ _) y _)
199217 | x == y = True
200218 | otherwise = False
201−-- recoverable (P (DCon _ _) x _) (P (TCon _ _) y _) = False
202−-- recoverable (P (TCon _ _) x _) (P (DCon _ _) y _) = False
219+ recoverable (P (TCon _ _) x _) (P (TCon _ _) y _)
220+ | x == y = True
221+ | otherwise = False
222+ recoverable (P (DCon _ _) x _) (P (TCon _ _) y _) = False
223+ recoverable (P (TCon _ _) x _) (P (DCon _ _) y _) = False
203224 recoverable p@(P _ n _) (App f a) = recoverable p f
204− recoverable (App f a) p@(P _ _ _) = recoverable f p
225+-- recoverable (App f a) p@(P _ _ _) = recoverable f p
205226 recoverable (App f a) (App f' a')
206− = recoverable f f' && recoverable a a'
227+ = recoverable f f' -- && recoverable a a'
207228 recoverable _ _ = True
208229
209230errEnv = map (\(x, b) -> (x, binderTy b))
src/Idris/AbsSyntaxTree.hs+1
@@ -473,6 +473,7 @@ data PTactic' t = Intro [Name] | Intros | Focus Name
473473 | Try (PTactic' t) (PTactic' t)
474474 | TSeq (PTactic' t) (PTactic' t)
475475 | ReflectTac t -- see Language.Reflection module
476+ | GoalType String (PTactic' t)
476477 | Qed | Abandon
477478 deriving (Show, Eq, Functor)
478479{-!
src/Idris/ElabTerm.hs+52−42
@@ -112,7 +112,8 @@ elab ist info pattern tcgen fn tm
112112 elab' ina (PResolveTC fc)
113113 | pattern = do c <- unique_hole (MN 0 "c")
114114 instanceArg c
115− | otherwise = try (resolveTC 2 fn ist)
115+ | otherwise = do g <- goal
116+ try (resolveTC 2 fn ist)
116117 (do c <- unique_hole (MN 0 "c")
117118 instanceArg c)
118119 elab' ina (PRefl fc t) = elab' ina (PApp fc (PRef fc eqCon) [pimp (MN 0 "a") Placeholder,
@@ -147,9 +148,7 @@ elab ist info pattern tcgen fn tm
147148 ctxt <- get_context
148149 let (tc, _) = unApply ty
149150 let as' = pruneByType tc ctxt as
150− let as'' = as' -- pruneAlt as'
151− try (tryAll (zip (map (elab' ina) as'') (map showHd as'')))
152− (tryAll (zip (map (elab' ina) as') (map showHd as')))
151+ tryAll (zip (map (elab' ina) as') (map showHd as'))
153152 where showHd (PApp _ h _) = show h
154153 showHd x = show x
155154 elab' ina (PAlternative False as)
@@ -290,24 +289,26 @@ elab ist info pattern tcgen fn tm
290289 ctxt <- get_context
291290 let guarded = isConName Nothing f ctxt
292291-- when True
293− tryWhen True
292+ (ns, committed) <- tryWhen True
294293 (do ns <- apply (Var f) (map isph args)
295− let (ns', eargs)
296− = unzip $
294+ return (ns, True)) -- commit to this branch here
295+ (do apply_elab f (map (toElab (ina || not isinf, guarded)) args)
296+ mkSpecialised ist fc f (map getTm args') tm
297+ solve
298+ return ([], False))
299+ when committed $
300+ do let (ns', eargs) = unzip $
297301 sortBy (\(_,x) (_,y) ->
298302 compare (priority x) (priority y))
299303 (zip ns args)
300− try
301− (elabArgs (ina || not isinf, guarded)
302− [] False ns' (map (\x -> (lazyarg x, getTm x)) eargs))
303− (elabArgs (ina || not isinf, guarded)
304− [] False (reverse ns')
305− (map (\x -> (lazyarg x, getTm x)) (reverse eargs)))
306− mkSpecialised ist fc f (map getTm args') tm
307− solve)
308− (do apply_elab f (map (toElab (ina || not isinf, guarded)) args)
309− mkSpecialised ist fc f (map getTm args') tm
310− solve)
304+ tryWhen True
305+ (elabArgs (ina || not isinf, guarded)
306+ [] False ns' (map (\x -> (lazyarg x, getTm x)) eargs))
307+ (elabArgs (ina || not isinf, guarded)
308+ [] False (reverse ns')
309+ (map (\x -> (lazyarg x, getTm x)) (reverse eargs)))
310+ mkSpecialised ist fc f (map getTm args') tm
311+ solve
311312-- ptm <- get_term
312313-- elog (show ptm)
313314 ivs' <- get_instances
@@ -405,10 +406,10 @@ elab ist info pattern tcgen fn tm
405406 failed' <- -- trace (show (n, t, hs, tm)) $
406407 case n `elem` hs of
407408 True ->
408− if r
409− then try (do focus n; elabE ina t; return failed)
410− (return ((n,(lazy, t)):failed))
411− else do focus n; elabE ina t; return failed
409+-- if r
410+-- then try (do focus n; elabE ina t; return failed)
411+-- (return ((n,(lazy, t)):failed))
412+ do focus n; elabE ina t; return failed
412413 False -> return failed
413414 elabArgs ina failed r ns args
414415
@@ -459,17 +460,17 @@ pruneByType (P _ n _) c as
459460pruneByType t _ as = as
460461
461462trivial :: IState -> ElabD ()
462−trivial ist = try (do elab ist toplevel False False (MN 0 "tac")
463+trivial ist = try' (do elab ist toplevel False False (MN 0 "tac")
463464 (PRefl (FC "prf" 0) Placeholder)
464− return ())
465− (do env <- get_env
466− tryAll (map fst env)
467− return ())
465+ return ())
466+ (do env <- get_env
467+ tryAll (map fst env)
468+ return ()) True
468469 where
469470 tryAll [] = fail "No trivial solution"
470− tryAll (x:xs) = try (elab ist toplevel False False
471+ tryAll (x:xs) = try' (elab ist toplevel False False
471472 (MN 0 "tac") (PRef (FC "prf" 0) x))
472− (tryAll xs)
473+ (tryAll xs) True
473474
474475findInstances :: IState -> Term -> [Name]
475476findInstances ist t
@@ -481,19 +482,19 @@ findInstances ist t
481482
482483resolveTC :: Int -> Name -> IState -> ElabD ()
483484resolveTC 0 fn ist = fail $ "Can't resolve type class"
484−resolveTC 1 fn ist = try (trivial ist) (resolveTC 0 fn ist)
485+resolveTC 1 fn ist = try' (trivial ist) (resolveTC 0 fn ist) True
485486resolveTC depth fn ist
486487 = do hnf_compute
487− try (trivial ist)
488− (do t <- goal
489− let insts = findInstances ist t
490− let (tc, ttypes) = unApply t
491− scopeOnly <- needsDefault t tc ttypes
492− tm <- get_term
488+ try' (trivial ist)
489+ (do t <- goal
490+ let insts = findInstances ist t
491+ let (tc, ttypes) = unApply t
492+ scopeOnly <- needsDefault t tc ttypes
493+ tm <- get_term
493494-- traceWhen (depth > 6) ("GOAL: " ++ show t ++ "\nTERM: " ++ show tm) $
494495-- (tryAll (map elabTC (map fst (ctxtAlist (tt_ctxt ist)))))
495− let depth' = if scopeOnly then 2 else depth
496− blunderbuss t depth' insts)
496+ let depth' = if scopeOnly then 2 else depth
497+ blunderbuss t depth' insts) True
497498 where
498499 elabTC n | n /= fn && tcname n = (resolve n depth, show n)
499500 | otherwise = (fail "Can't resolve", show n)
@@ -512,8 +513,8 @@ resolveTC depth fn ist
512513
513514 blunderbuss t d [] = lift $ tfail $ CantResolve t
514515 blunderbuss t d (n:ns)
515− | n /= fn && tcname n = try (resolve n d)
516− (blunderbuss t d ns)
516+ | n /= fn && tcname n = try' (resolve n d)
517+ (blunderbuss t d ns) True
517518 | otherwise = blunderbuss t d ns
518519
519520 resolve n depth
@@ -570,8 +571,8 @@ runTac autoSolve ist tac = do env <- get_env
570571 runT (Intro xs) = mapM_ (\x -> do attack; intro (Just x)) xs
571572 runT Intros = do g <- goal
572573 attack; intro (bname g)
573− try (runT Intros)
574− (return ())
574+ try' (runT Intros)
575+ (return ()) True
575576 where
576577 bname (Bind n _ _) = Just n
577578 bname _ = Nothing
@@ -653,6 +654,13 @@ runTac autoSolve ist tac = do env <- get_env
653654-- trace (show p ++ "\n\n") $
654655 return ()
655656 where tacticTy = tacm "Tactic"
657+ runT (GoalType n tac) = do g <- goal
658+ case unApply g of
659+ (P _ n' _, _) ->
660+ if nsroot n' == UN n
661+ then runT tac
662+ else fail "Wrong goal type"
663+ _ -> fail "Wrong goal type"
656664 runT x = fail $ "Not implemented " ++ show x
657665
658666 runReflected t = do t' <- reify t
@@ -670,6 +678,8 @@ runTac autoSolve ist tac = do env <- get_env
670678 reifyAp t [Constant (Str x)]
671679 | t == tacm "Refine" = return $ Refine (UN x) []
672680 reifyAp t [l, r] | t == tacm "Seq" = liftM2 TSeq (reify l) (reify r)
681+ reifyAp t [Constant (Str n), x]
682+ | t == tacm "GoalType" = liftM (GoalType n) (reify x)
673683 reifyAp f args = fail ("Unknown tactic " ++ show (f, args)) -- shouldn't happen
674684
675685solveAll = try (do solve; solveAll) (return ())
test/reg008/expectednew file

No changes to the content.

test/reg008/reg008.idrnew file+15
@@ -0,0 +1,15 @@
1+module NatCmp
2+
3+data Cmp : Nat -> Nat -> Type where
4+ cmpLT : (y : _) -> Cmp x (x + S y)
5+ cmpEQ : Cmp x x
6+ cmpGT : (x : _) -> Cmp (y + S x) y
7+
8+total cmp : (x, y : Nat) -> Cmp x y
9+cmp O O = cmpEQ
10+cmp O (S k) = cmpLT _
11+cmp (S k) O = cmpGT _
12+cmp (S x) (S y) with (cmp x y)
13+ cmp (S x) (S (x + (S k))) | cmpLT k = cmpLT k
14+ cmp (S x) (S x) | cmpEQ = cmpEQ
15+ cmp (S (y + (S k))) (S y) | cmpGT k = cmpGT k
test/reg008/runnew file+3
@@ -0,0 +1,3 @@
1+#!/bin/bash
2+idris $@ reg008.idr --check
3+rm -f *.ibc