on master help sign in
Merge pull request #1926 from david-christiansen/new-tactic-reflection
2127664David Christiansen
CHANGELOG+3
@@ -2,6 +2,9 @@ New in 0.9.17:
2--------------
2--------------
3* The --ideslave command line option has been replaced with a --ide-mode
3* The --ideslave command line option has been replaced with a --ide-mode
4 command line option with the same semantics.
4 command line option with the same semantics.
5+* A new tactic "claim N TY" that introduces a new hole named N with type TY
6+* A new tactic "unfocus" that moves the current hole to the bottom of the
7+ hole stack
5
8
6New in 0.9.16:
9New in 0.9.16:
7--------------
10--------------
idris.cabal+3
@@ -497,6 +497,9 @@ Extra-source-files:
497 test/proof004/run
497 test/proof004/run
498 test/proof004/*.idr
498 test/proof004/*.idr
499 test/proof004/expected
499 test/proof004/expected
500+ test/proof008/run
501+ test/proof008/*.idr
502+ test/proof008/expected
500
503
501 test/quasiquote001/run
504 test/quasiquote001/run
502 test/quasiquote001/*.idr
505 test/quasiquote001/*.idr
libs/prelude/Language/Reflection.idr+7
@@ -213,6 +213,10 @@ data Tactic =
213 Refine TTName |
213 Refine TTName |
214 ||| Apply both tactics in sequence
214 ||| Apply both tactics in sequence
215 Seq Tactic Tactic |
215 Seq Tactic Tactic |
216+ ||| Introduce a new hole with a particular type
217+ Claim TTName TT |
218+ ||| Move the current hole to the end
219+ Unfocus |
216 ||| Intelligently construct the proof target from the context
220 ||| Intelligently construct the proof target from the context
217 Trivial |
221 Trivial |
218 ||| Build a proof by applying contructors up to a maximum depth
222 ||| Build a proof by applying contructors up to a maximum depth
@@ -472,6 +476,8 @@ instance Quotable Tactic where
472 quote (Try tac tac') = `(Try ~(quote tac) ~(quote tac'))
476 quote (Try tac tac') = `(Try ~(quote tac) ~(quote tac'))
473 quote (GoalType x tac) = `(GoalType ~(quote x) ~(quote tac))
477 quote (GoalType x tac) = `(GoalType ~(quote x) ~(quote tac))
474 quote (Refine n) = `(Refine ~(quote n))
478 quote (Refine n) = `(Refine ~(quote n))
479+ quote (Claim n ty) = `(Claim ~(quote n) ~(quote ty))
480+ quote Unfocus = `(Unfocus)
475 quote (Seq tac tac') = `(Seq ~(quote tac) ~(quote tac'))
481 quote (Seq tac tac') = `(Seq ~(quote tac) ~(quote tac'))
476 quote Trivial = `(Trivial)
482 quote Trivial = `(Trivial)
477 quote (Search x) = `(Search ~(quote x))
483 quote (Search x) = `(Search ~(quote x))
@@ -494,3 +500,4 @@ instance Quotable Tactic where
494 quote Skip = `(Skip)
500 quote Skip = `(Skip)
495 quote (Fail xs) = `(Fail ~(quote xs))
501 quote (Fail xs) = `(Fail ~(quote xs))
496 quote SourceFC = `(SourceFC)
502 quote SourceFC = `(SourceFC)
503+
src/Idris/AbsSyntaxTree.hs+2
@@ -830,6 +830,8 @@ data PTactic' t = Intro [Name] | Intros | Focus Name
830 | Induction t
830 | Induction t
831 | CaseTac t
831 | CaseTac t
832 | Equiv t
832 | Equiv t
833+ | Claim Name t
834+ | Unfocus
833 | MatchRefine Name
835 | MatchRefine Name
834 | LetTac Name t | LetTacTy Name t t
836 | LetTac Name t | LetTacTy Name t t
835 | Exact t | Compute | Trivial | TCInstance
837 | Exact t | Compute | Trivial | TCInstance
src/Idris/Core/ProofState.hs+18−18
@@ -23,23 +23,23 @@ import Debug.Trace
23import Util.Pretty hiding (fill)
23import Util.Pretty hiding (fill)
24
24
25data ProofState = PS { thname :: Name,
25data ProofState = PS { thname :: Name,
26− holes :: [Name], -- holes still to be solved
26+ holes :: [Name], -- ^ holes still to be solved
27− usedns :: [Name], -- used names, don't use again
27+ usedns :: [Name], -- ^ used names, don't use again
28− nextname :: Int, -- name supply
28+ nextname :: Int, -- ^ name supply
29− pterm :: ProofTerm, -- current proof term
29+ pterm :: ProofTerm, -- ^ current proof term
30− ptype :: Type, -- original goal
30+ ptype :: Type, -- ^ original goal
31− dontunify :: [Name], -- explicitly given by programmer, leave it
31+ dontunify :: [Name], -- ^ explicitly given by programmer, leave it
32 unified :: (Name, [(Name, Term)]),
32 unified :: (Name, [(Name, Term)]),
33 notunified :: [(Name, Term)],
33 notunified :: [(Name, Term)],
34− dotted :: [(Name, [Name])], -- dot pattern holes + environment
34+ dotted :: [(Name, [Name])], -- ^ dot pattern holes + environment
35− -- either hole or something in env must turn up in the 'notunified' list during elaboration
35+ -- either hole or something in env must turn up in the 'notunified' list during elaboration
36 solved :: Maybe (Name, Term),
36 solved :: Maybe (Name, Term),
37 problems :: Fails,
37 problems :: Fails,
38 injective :: [Name],
38 injective :: [Name],
39− deferred :: [Name], -- names we'll need to define
39+ deferred :: [Name], -- ^ names we'll need to define
40− instances :: [Name], -- instance arguments (for type classes)
40+ instances :: [Name], -- ^ instance arguments (for type classes)
41− autos :: [(Name, [Name])], -- unsolved 'auto' implicits with their holes
41+ autos :: [(Name, [Name])], -- ^ unsolved 'auto' implicits with their holes
42− previous :: Maybe ProofState, -- for undo
42+ previous :: Maybe ProofState, -- ^ for undo
43 context :: Context,
43 context :: Context,
44 plog :: String,
44 plog :: String,
45 unifylog :: Bool,
45 unifylog :: Bool,
@@ -290,12 +290,12 @@ addLog str = action (\ps -> ps { plog = plog ps ++ str ++ "\n" })
290
290
291newProof :: Name -> Context -> Type -> ProofState
291newProof :: Name -> Context -> Type -> ProofState
292newProof n ctxt ty = let h = holeName 0
292newProof n ctxt ty = let h = holeName 0
293− ty' = vToP ty in
293+ ty' = vToP ty
294− PS n [h] [] 1 (mkProofTerm (Bind h (Hole ty')
294+ in PS n [h] [] 1 (mkProofTerm (Bind h (Hole ty')
295− (P Bound h ty'))) ty [] (h, []) [] []
295+ (P Bound h ty'))) ty [] (h, []) [] []
296− Nothing [] []
296+ Nothing [] []
297− [] [] []
297+ [] [] []
298− Nothing ctxt "" False False [] []
298+ Nothing ctxt "" False False [] []
299
299
300type TState = ProofState -- [TacticAction])
300type TState = ProofState -- [TacticAction])
301type RunTactic = RunTactic' TState
301type RunTactic = RunTactic' TState
src/Idris/Core/ProofTerm.hs+37−14
@@ -1,8 +1,9 @@
1{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, PatternGuards #-}
1{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, PatternGuards #-}
2
2
3−{- Implements a proof state, some primitive tactics for manipulating
3+{- | Implements a proof state, some primitive tactics for manipulating
4− proofs, and some high level commands for introducing new theorems,
4+proofs, and some high level commands for introducing new theorems,
5− evaluation/checking inside the proof system, etc. --}
5+evaluation/checking inside the proof system, etc.
6+-}
6
7
7module Idris.Core.ProofTerm(ProofTerm, Goal(..), mkProofTerm, getProofTerm,
8module Idris.Core.ProofTerm(ProofTerm, Goal(..), mkProofTerm, getProofTerm,
8 updateSolved, updateSolvedTerm, updateSolvedTerm',
9 updateSolved, updateSolvedTerm, updateSolvedTerm',
@@ -18,6 +19,7 @@ import Control.Monad.State.Strict
18import Data.List
19import Data.List
19import Debug.Trace
20import Debug.Trace
20
21
22+-- | A zipper over terms, in order to efficiently update proof terms.
21data TermPath = Top
23data TermPath = Top
22 | AppL TermPath Term
24 | AppL TermPath Term
23 | AppR Term TermPath
25 | AppR Term TermPath
@@ -25,6 +27,7 @@ data TermPath = Top
25 | InScope Name (Binder Term) TermPath
27 | InScope Name (Binder Term) TermPath
26 deriving Show
28 deriving Show
27
29
30+-- | A zipper over binders, because terms and binders are mutually defined.
28data BinderPath = Binder (Binder TermPath)
31data BinderPath = Binder (Binder TermPath)
29 | LetT TermPath Term
32 | LetT TermPath Term
30 | LetV Term TermPath
33 | LetV Term TermPath
@@ -32,6 +35,8 @@ data BinderPath = Binder (Binder TermPath)
32 | GuessV Term TermPath
35 | GuessV Term TermPath
33 deriving Show
36 deriving Show
34
37
38+-- | Replace the top of a term path with another term path. In other
39+-- words, "graft" one term path into another.
35replaceTop :: TermPath -> TermPath -> TermPath
40replaceTop :: TermPath -> TermPath -> TermPath
36replaceTop p Top = p
41replaceTop p Top = p
37replaceTop p (AppL l t) = AppL (replaceTop p l) t
42replaceTop p (AppL l t) = AppL (replaceTop p l) t
@@ -45,6 +50,7 @@ replaceTop p (InBind n bp sc) = InBind n (replaceTopB p bp) sc
45 replaceTopB p (GuessV t v) = GuessV t (replaceTop p v)
50 replaceTopB p (GuessV t v) = GuessV t (replaceTop p v)
46replaceTop p (InScope n b sc) = InScope n b (replaceTop p sc)
51replaceTop p (InScope n b sc) = InScope n b (replaceTop p sc)
47
52
53+-- | Build a term from a zipper, given something to put in the hole.
48rebuildTerm :: Term -> TermPath -> Term
54rebuildTerm :: Term -> TermPath -> Term
49rebuildTerm tm Top = tm
55rebuildTerm tm Top = tm
50rebuildTerm tm (AppL p a) = App (rebuildTerm tm p) a
56rebuildTerm tm (AppL p a) = App (rebuildTerm tm p) a
@@ -52,6 +58,7 @@ rebuildTerm tm (AppR f p) = App f (rebuildTerm tm p)
52rebuildTerm tm (InScope n b p) = Bind n b (rebuildTerm tm p)
58rebuildTerm tm (InScope n b p) = Bind n b (rebuildTerm tm p)
53rebuildTerm tm (InBind n bp sc) = Bind n (rebuildBinder tm bp) sc
59rebuildTerm tm (InBind n bp sc) = Bind n (rebuildBinder tm bp) sc
54
60
61+-- | Build a binder from a zipper, given something to put in the hole.
55rebuildBinder :: Term -> BinderPath -> Binder Term
62rebuildBinder :: Term -> BinderPath -> Binder Term
56rebuildBinder tm (Binder p) = fmap (rebuildTerm tm) p
63rebuildBinder tm (Binder p) = fmap (rebuildTerm tm) p
57rebuildBinder tm (LetT p t) = Let (rebuildTerm tm p) t
64rebuildBinder tm (LetT p t) = Let (rebuildTerm tm p) t
@@ -59,6 +66,9 @@ rebuildBinder tm (LetV v p) = Let v (rebuildTerm tm p)
59rebuildBinder tm (GuessT p t) = Guess (rebuildTerm tm p) t
66rebuildBinder tm (GuessT p t) = Guess (rebuildTerm tm p) t
60rebuildBinder tm (GuessV v p) = Guess v (rebuildTerm tm p)
67rebuildBinder tm (GuessV v p) = Guess v (rebuildTerm tm p)
61
68
69+-- | Find the binding of a hole in a term. If present, return the path
70+-- to the hole's binding, the environment extended by the binders that
71+-- are crossed, and the actual binding term.
62findHole :: Name -> Env -> Term -> Maybe (TermPath, Env, Term)
72findHole :: Name -> Env -> Term -> Maybe (TermPath, Env, Term)
63findHole n env t = fh' env Top t where
73findHole n env t = fh' env Top t where
64 fh' env path tm@(Bind x h sc)
74 fh' env path tm@(Bind x h sc)
@@ -80,7 +90,7 @@ findHole n env t = fh' env Top t where
80 fhB env path b
90 fhB env path b
81 | Just (p, env', tm) <- fh' env path (binderTy b)
91 | Just (p, env', tm) <- fh' env path (binderTy b)
82 = Just (Binder (fmap (\_ -> p) b), env', tm)
92 = Just (Binder (fmap (\_ -> p) b), env', tm)
83− fhB _ _ _ = Nothing
93+ fhB _ _ _ = Nothing
84
94
85data ProofTerm = PT { -- wholeterm :: Term,
95data ProofTerm = PT { -- wholeterm :: Term,
86 path :: TermPath,
96 path :: TermPath,
@@ -92,13 +102,17 @@ data ProofTerm = PT { -- wholeterm :: Term,
92type RunTactic' a = Context -> Env -> Term -> StateT a TC Term
102type RunTactic' a = Context -> Env -> Term -> StateT a TC Term
93type Hole = Maybe Name -- Nothing = default hole, first in list in proof state
103type Hole = Maybe Name -- Nothing = default hole, first in list in proof state
94
104
105+-- | Refocus the proof term zipper on a particular hole, if it
106+-- exists. If not, return the original proof term.
95refocus :: Hole -> ProofTerm -> ProofTerm
107refocus :: Hole -> ProofTerm -> ProofTerm
96refocus h t = let res = refocus' h t in res
108refocus h t = let res = refocus' h t in res
97-- trace ("OLD: " ++ show t ++ "\n" ++
109-- trace ("OLD: " ++ show t ++ "\n" ++
98-- "REFOCUSSED " ++ show h ++ ": " ++ show res) res
110-- "REFOCUSSED " ++ show h ++ ": " ++ show res) res
99refocus' (Just n) pt@(PT path env tm ups)
111refocus' (Just n) pt@(PT path env tm ups)
112+ -- First look for the hole in the proof term as-is
100 | Just (p', env', tm') <- findHole n env tm
113 | Just (p', env', tm') <- findHole n env tm
101 = PT (replaceTop p' path) env' tm' ups
114 = PT (replaceTop p' path) env' tm' ups
115+ -- Next apply the updates, and look for the hole in the resulting term
102 | Just (p', env', tm') <- findHole n [] (rebuildTerm tm (updateSolvedPath ups path))
116 | Just (p', env', tm') <- findHole n [] (rebuildTerm tm (updateSolvedPath ups path))
103 = PT p' env' tm' []
117 = PT p' env' tm' []
104 | otherwise = pt
118 | otherwise = pt
@@ -118,27 +132,32 @@ same :: Eq a => Maybe a -> a -> Bool
118same Nothing n = True
132same Nothing n = True
119same (Just x) n = x == n
133same (Just x) n = x == n
120
134
135+-- | Is a particular binder a hole or a guess?
121hole :: Binder b -> Bool
136hole :: Binder b -> Bool
122hole (Hole _) = True
137hole (Hole _) = True
123hole (Guess _ _) = True
138hole (Guess _ _) = True
124hole _ = False
139hole _ = False
125
140
141+-- | Given a list of solved holes, fill out the solutions in a term
126−updateSolvedTerm :: [(Name, Term)] -> Term -> Term
142+updateSolvedTerm :: [(Name, Term)] -> Term -> Term
127updateSolvedTerm xs x = fst $ updateSolvedTerm' xs x
143updateSolvedTerm xs x = fst $ updateSolvedTerm' xs x
128
144
145+-- | Given a list of solved holes, fill out the solutions in a
146+-- term. Return whether updates were performed, to facilitate sharing
147+-- when there are no updates.
148+updateSolvedTerm' :: [(Name, Term)] -> Term -> (Term, Bool)
129updateSolvedTerm' [] x = (x, False)
149updateSolvedTerm' [] x = (x, False)
130−updateSolvedTerm' xs x = -- updateSolved' xs x where
150+updateSolvedTerm' xs x = updateSolved' xs x where
131−-- This version below saves allocations, because it doesn't need to reallocate
151+ -- This version below saves allocations, because it doesn't need to reallocate
132−-- the term if there are no updates to do.
152+ -- the term if there are no updates to do.
133−-- The Bool is ugly, and probably 'Maybe' would be less ugly, but >>= is
153+ -- The Bool is ugly, and probably 'Maybe' would be less ugly, but >>= is
134−-- the wrong combinator. Feel free to tidy up as long as it's still as cheap :).
154+ -- the wrong combinator. Feel free to tidy up as long as it's still as cheap :).
135− updateSolved' xs x where
136 updateSolved' [] x = (x, False)
155 updateSolved' [] x = (x, False)
137 updateSolved' xs (Bind n (Hole ty) t)
156 updateSolved' xs (Bind n (Hole ty) t)
138− | Just v <- lookup n xs
157+ | Just v <- lookup n xs
139 = case xs of
158 = case xs of
140 [_] -> (subst n v t, True) -- some may be Vs! Can't assume
159 [_] -> (subst n v t, True) -- some may be Vs! Can't assume
141− -- explicit names
160+ -- explicit names
142 _ -> let (t', _) = updateSolved' xs t in
161 _ -> let (t', _) = updateSolved' xs t in
143 (subst n v t', True)
162 (subst n v t', True)
144 updateSolved' xs tm@(Bind n b t)
163 updateSolved' xs tm@(Bind n b t)
@@ -146,7 +165,7 @@ updateSolvedTerm' xs x = -- updateSolved' xs x where
146 (b', ub) = updateSolvedB' xs b in
165 (b', ub) = updateSolvedB' xs b in
147 if ut || ub then (Bind n b' t', True)
166 if ut || ub then (Bind n b' t', True)
148 else (tm, False)
167 else (tm, False)
149− updateSolved' xs t@(App f a)
168+ updateSolved' xs t@(App f a)
150 = let (f', uf) = updateSolved' xs f
169 = let (f', uf) = updateSolved' xs f
151 (a', ua) = updateSolved' xs a in
170 (a', ua) = updateSolved' xs a in
152 if uf || ua then (App f' a', True)
171 if uf || ua then (App f' a', True)
@@ -176,10 +195,14 @@ updateSolvedTerm' xs x = -- updateSolved' xs x where
176 noneOfB ns b = noneOf ns (binderTy b)
195 noneOfB ns b = noneOf ns (binderTy b)
177 noneOf ns _ = True
196 noneOf ns _ = True
178
197
198+-- | Apply solutions to an environment.
199+updateEnv :: [(Name, Term)] -> Env -> Env
179updateEnv [] e = e
200updateEnv [] e = e
180updateEnv ns [] = []
201updateEnv ns [] = []
181updateEnv ns ((n, b) : env) = (n, fmap (updateSolvedTerm ns) b) : updateEnv ns env
202updateEnv ns ((n, b) : env) = (n, fmap (updateSolvedTerm ns) b) : updateEnv ns env
182
203
204+-- | Fill out solved holes in a term zipper.
205+updateSolvedPath :: [(Name, Term)] -> TermPath -> TermPath
183updateSolvedPath [] t = t
206updateSolvedPath [] t = t
184updateSolvedPath ns Top = Top
207updateSolvedPath ns Top = Top
185updateSolvedPath ns (AppL p r) = AppL (updateSolvedPath ns p) (updateSolvedTerm ns r)
208updateSolvedPath ns (AppL p r) = AppL (updateSolvedPath ns p) (updateSolvedTerm ns r)
src/Idris/DeepSeq.hs+2
@@ -250,6 +250,7 @@ instance (NFData t) => NFData (PTactic' t) where
250 rnf (Induction x1) = rnf x1 `seq` ()
250 rnf (Induction x1) = rnf x1 `seq` ()
251 rnf (CaseTac x1) = rnf x1 `seq` ()
251 rnf (CaseTac x1) = rnf x1 `seq` ()
252 rnf (Equiv x1) = rnf x1 `seq` ()
252 rnf (Equiv x1) = rnf x1 `seq` ()
253+ rnf (Claim x1 x2) = rnf x1 `seq` rnf x2 `seq` ()
253 rnf (MatchRefine x1) = rnf x1 `seq` ()
254 rnf (MatchRefine x1) = rnf x1 `seq` ()
254 rnf (LetTac x1 x2) = rnf x1 `seq` rnf x2 `seq` ()
255 rnf (LetTac x1 x2) = rnf x1 `seq` rnf x2 `seq` ()
255 rnf (LetTacTy x1 x2 x3) = rnf x1 `seq` rnf x2 `seq` rnf x3 `seq` ()
256 rnf (LetTacTy x1 x2 x3) = rnf x1 `seq` rnf x2 `seq` rnf x3 `seq` ()
@@ -280,6 +281,7 @@ instance (NFData t) => NFData (PTactic' t) where
280 rnf Skip = ()
281 rnf Skip = ()
281 rnf (TFail x1) = rnf x1 `seq` ()
282 rnf (TFail x1) = rnf x1 `seq` ()
282 rnf SourceFC = ()
283 rnf SourceFC = ()
284+ rnf Unfocus = ()
283
285
284instance NFData ErrorReportPart where
286instance NFData ErrorReportPart where
285 rnf (TermPart x1) = rnf x1 `seq` ()
287 rnf (TermPart x1) = rnf x1 `seq` ()
src/Idris/ElabQuasiquote.hs+1
@@ -36,6 +36,7 @@ extractTUnquotes n (GoalType s tac)
36 return (GoalType s tac', ex)
36 return (GoalType s tac', ex)
37extractTUnquotes n (TCheck t) = extract1 n TCheck t
37extractTUnquotes n (TCheck t) = extract1 n TCheck t
38extractTUnquotes n (TEval t) = extract1 n TEval t
38extractTUnquotes n (TEval t) = extract1 n TEval t
39+extractTUnquotes n (Claim name t) = extract1 n (Claim name) t
39extractTUnquotes n tac = return (tac, []) -- the rest don't contain PTerms
40extractTUnquotes n tac = return (tac, []) -- the rest don't contain PTerms
40
41
41extractPArgUnquotes :: Int -> PArg -> Elab' aux (PArg, [(Name, PTerm)])
42extractPArgUnquotes :: Int -> PArg -> Elab' aux (PArg, [(Name, PTerm)])
src/Idris/ElabTerm.hs+14
@@ -1506,6 +1506,12 @@ runTac autoSolve ist perhapsFC fn tac
1506 when autoSolve solveAll
1506 when autoSolve solveAll
1507 runT DoUnify = do unify_all
1507 runT DoUnify = do unify_all
1508 when autoSolve solveAll
1508 when autoSolve solveAll
1509+ runT (Claim n tm) = do tmHole <- getNameFrom (sMN 0 "newGoal")
1510+ claim tmHole RType
1511+ claim n (Var tmHole)
1512+ focus tmHole
1513+ elab ist toplevel ERHS [] (sMN 0 "tac") tm
1514+ focus n
1509 runT (Equiv tm) -- let bind tm, then
1515 runT (Equiv tm) -- let bind tm, then
1510 = do attack
1516 = do attack
1511 tyn <- getNameFrom (sMN 0 "ety")
1517 tyn <- getNameFrom (sMN 0 "ety")
@@ -1566,6 +1572,10 @@ runTac autoSolve ist perhapsFC fn tac
1566 = do proofSearch' ist rec False depth prover top fn hints
1572 = do proofSearch' ist rec False depth prover top fn hints
1567 when autoSolve solveAll
1573 when autoSolve solveAll
1568 runT (Focus n) = focus n
1574 runT (Focus n) = focus n
1575+ runT Unfocus = do hs <- get_holes
1576+ case hs of
1577+ [] -> return ()
1578+ (h : _) -> movelast h
1569 runT Solve = solve
1579 runT Solve = solve
1570 runT (Try l r) = do try' (runT l) (runT r) True
1580 runT (Try l r) = do try' (runT l) (runT r) True
1571 runT (TSeq l r) = do runT l; runT r
1581 runT (TSeq l r) = do runT l; runT r
@@ -1710,6 +1720,7 @@ reify _ (P _ n _) | n == reflm "Solve" = return Solve
1710reify _ (P _ n _) | n == reflm "Compute" = return Compute
1720reify _ (P _ n _) | n == reflm "Compute" = return Compute
1711reify _ (P _ n _) | n == reflm "Skip" = return Skip
1721reify _ (P _ n _) | n == reflm "Skip" = return Skip
1712reify _ (P _ n _) | n == reflm "SourceFC" = return SourceFC
1722reify _ (P _ n _) | n == reflm "SourceFC" = return SourceFC
1723+reify _ (P _ n _) | n == reflm "Unfocus" = return Unfocus
1713reify ist t@(App _ _)
1724reify ist t@(App _ _)
1714 | (P _ f _, args) <- unApply t = reifyApp ist f args
1725 | (P _ f _, args) <- unApply t = reifyApp ist f args
1715reify _ t = fail ("Unknown tactic " ++ show t)
1726reify _ t = fail ("Unknown tactic " ++ show t)
@@ -1721,6 +1732,9 @@ reifyApp _ t [Constant (I i)]
1721reifyApp _ t [x]
1732reifyApp _ t [x]
1722 | t == reflm "Refine" = do n <- reifyTTName x
1733 | t == reflm "Refine" = do n <- reifyTTName x
1723 return $ Refine n []
1734 return $ Refine n []
1735+reifyApp ist t [n, ty] | t == reflm "Claim" = do n' <- reifyTTName n
1736+ goal <- reifyTT ty
1737+ return $ Claim n' (delab ist goal)
1724reifyApp ist t [l, r] | t == reflm "Seq" = liftM2 TSeq (reify ist l) (reify ist r)
1738reifyApp ist t [l, r] | t == reflm "Seq" = liftM2 TSeq (reify ist l) (reify ist r)
1725reifyApp ist t [Constant (Str n), x]
1739reifyApp ist t [Constant (Str n), x]
1726 | t == reflm "GoalType" = liftM (GoalType n) (reify ist x)
1740 | t == reflm "GoalType" = liftM (GoalType n) (reify ist x)
src/Idris/ParseExpr.hs+6−1
@@ -1251,10 +1251,15 @@ tactics =
1251 [ (["intro"], Nothing, const $ -- FIXME syntax for intro (fresh name)
1251 [ (["intro"], Nothing, const $ -- FIXME syntax for intro (fresh name)
1252 do ns <- sepBy (spaced name) (lchar ','); return $ Intro ns)
1252 do ns <- sepBy (spaced name) (lchar ','); return $ Intro ns)
1253 , noArgs ["intros"] Intros
1253 , noArgs ["intros"] Intros
1254+ , noArgs ["unfocus"] Unfocus
1254 , (["refine"], Just ExprTArg, const $
1255 , (["refine"], Just ExprTArg, const $
1255 do n <- spaced fnName
1256 do n <- spaced fnName
1256 imps <- many imp
1257 imps <- many imp
1257 return $ Refine n imps)
1258 return $ Refine n imps)
1259+ , (["claim"], Nothing, \syn ->
1260+ do n <- indentPropHolds gtProp *> name
1261+ goal <- indentPropHolds gtProp *> expr syn
1262+ return $ Claim n goal)
1258 , (["mrefine"], Just ExprTArg, const $
1263 , (["mrefine"], Just ExprTArg, const $
1259 do n <- spaced fnName
1264 do n <- spaced fnName
1260 return $ MatchRefine n)
1265 return $ MatchRefine n)
@@ -1329,7 +1334,7 @@ tactics =
1329
1334
1330
1335
1331tactic :: SyntaxInfo -> IdrisParser PTactic
1336tactic :: SyntaxInfo -> IdrisParser PTactic
1332−tactic syn = choice [ do choice (map reserved names); parser syn
1337+tactic syn = choice [ do choice (map reserved names); parser syn
1333 | (names, _, parser) <- tactics ]
1338 | (names, _, parser) <- tactics ]
1334 <|> do lchar '{'
1339 <|> do lchar '{'
1335 t <- tactic syn;
1340 t <- tactic syn;
test/proof008/ClaimAndUnfocus.idrnew file+17
@@ -0,0 +1,17 @@
1+module ClaimAndUnfocus
2+
3+foo : Nat -> Nat
4+foo = ?foo_rhs
5+
6+---------- Proofs ----------
7+
8+ClaimAndUnfocus.foo_rhs = proof
9+ claim bar Nat -> Nat -> Nat
10+ unfocus
11+ intro x
12+ exact bar x x
13+ intro x,y
14+ refine plus
15+ refine x
16+ refine y
17+
test/proof008/expectednew file

No changes to the content.

test/proof008/runnew file+3
@@ -0,0 +1,3 @@
1+#!/usr/bin/env bash
2+idris --check $@ ClaimAndUnfocus.idr
3+rm -f *.ibc