on master help sign in
Beginning theorem prover interface
commit551548c56724f3b90c78f7017fe18ba1bbe57568 authorEdwin Brady <eb@cs.st-andrews.ac.uk> dateSat 29 Oct 2011, 23:28 (15 years ago) parent7c4f79c
11 files changed+148−17
miniidris.cabal+1−1 src/Core/Elaborate.hs+5−1 src/Core/ProofState.hs+4−4 src/Idris/AbsSyntax.hs+10−1 src/Idris/Delaborate.hs+7 src/Idris/ElabDecls.hs+11−3 src/Idris/Error.hs−7 src/Idris/Parser.hs+16 src/Idris/Prover.hs+91 src/Idris/REPL.hs+2 src/Idris/REPLParser.hs+1
miniidris.cabal+1−1
@@ -28,7 +28,7 @@ Executable miniidris
2828 Idris.AbsSyntax, Idris.Parser, Idris.REPL,
2929 Idris.REPLParser, Idris.ElabDecls, Idris.Error,
3030 Idris.Delaborate, Idris.Primitives, Idris.Imports,
31− Idris.Compiler
31+ Idris.Compiler, Idris.Prover
3232
3333 Paths_miniidris
3434
src/Core/Elaborate.hs+5−1
@@ -30,6 +30,9 @@ data Command = Theorem Name Raw
3030type ElabState = (ProofState, String)
3131type Elab a = StateT ElabState TC a
3232
33+proof :: ElabState -> ProofState
34+proof = fst
35+
3336erun :: FC -> Elab a -> Elab a
3437erun f elab = do s <- get
3538 case runStateT elab s of
@@ -81,7 +84,8 @@ get_holes = do (p, _) <- get
8184-- get the current goal type
8285goal :: Elab Type
8386goal = do (p, _) <- get
84− lift $ goalAtFocus p
87+ b <- lift $ goalAtFocus p
88+ return (binderTy b)
8589
8690-- typecheck locally
8791get_type :: Raw -> Elab Type
src/Core/ProofState.hs+4−4
@@ -5,7 +5,7 @@
55 evaluation/checking inside the proof system, etc. --}
66
77module Core.ProofState(ProofState(..), newProof, envAtFocus, goalAtFocus,
8− Tactic(..), processTactic) where
8+ Tactic(..), Goal(..), processTactic) where
99
1010import Core.Typecheck
1111import Core.Evaluate
@@ -124,10 +124,10 @@ envAtFocus ps
124124 return (premises g)
125125 | otherwise = fail "No holes"
126126
127−goalAtFocus :: ProofState -> TC Type
127+goalAtFocus :: ProofState -> TC (Binder Type)
128128goalAtFocus ps
129129 | not $ null (holes ps) = do g <- goal (Just (head (holes ps))) (pterm ps)
130− return (binderTy (goalType g))
130+ return (goalType g)
131131
132132goal :: Hole -> Term -> TC Goal
133133goal h tm = g [] tm where
@@ -195,7 +195,7 @@ defer n ctxt env (Bind x (Hole t) (P nt x' ty)) | x == x' =
195195 do action (\ps -> let hs = holes ps in
196196 ps { holes = hs \\ [x] })
197197 return (Bind n (GHole (mkTy (reverse env) t))
198− (mkApp (P nt n ty) (map getP (reverse env))))
198+ (mkApp (P Ref n ty) (map getP (reverse env))))
199199 where
200200 mkTy [] t = t
201201 mkTy ((n,b) : bs) t = Bind n (Pi (binderTy b)) (mkTy bs t)
src/Idris/AbsSyntax.hs+10−1
@@ -47,6 +47,7 @@ idrisInit = IState emptyContext [] emptyContext emptyContext
4747-- global state (hence the IO inner monad).
4848type Idris a = StateT IState IO a
4949
50+
5051getContext :: Idris Context
5152getContext = do i <- get; return (tt_ctxt i)
5253
@@ -118,7 +119,7 @@ setTypeCase t = do i <- get
118119
119120data Command = Quit | Help | Eval PTerm
120121 | Compile String
121− | Metavars
122+ | Metavars | Prove Name
122123 | TTShell
123124 | LogLvl Int | Spec PTerm | HNF PTerm
124125 | NOP
@@ -216,6 +217,14 @@ data PTerm = PQuote Raw
216217 | PElabError String -- error to report on elaboration
217218 deriving Eq
218219
220+data PTactic = Intro [Name]
221+ | Refine Name
222+ | Exact PTerm
223+ | Solve
224+ | Attack
225+ | Qed
226+ deriving (Show, Eq)
227+
219228data PDo = DoExp FC PTerm
220229 | DoBind FC Name PTerm
221230 | DoLet FC Name PTerm
src/Idris/Delaborate.hs+7
@@ -46,3 +46,10 @@ delab ist tm = de [] tm
4646 imp (PImp l n _) arg = PImp l n arg
4747 imp (PExp l _) arg = PExp l arg
4848
49+pshow :: IState -> Err -> String
50+pshow i (Msg s) = s
51+pshow i (CantUnify x y e) = "Can't unify " ++ show (delab i x)
52+ ++ " with " ++ show (delab i y)
53+ -- ++ "\n\t(" ++ pshow i e ++ ")"
54+pshow i (At f e) = show f ++ ":" ++ pshow i e
55+
src/Idris/ElabDecls.hs+11−3
@@ -9,7 +9,7 @@ import Idris.Imports
99import Paths_miniidris
1010
1111import Core.TT
12−import Core.Elaborate
12+import Core.Elaborate hiding (Tactic(..))
1313import Core.Evaluate
1414import Core.Typecheck
1515import Core.CaseTree
@@ -122,13 +122,14 @@ elabClause info fc (PClause fname lhs withs rhs whereblock)
122122 ((rhs', defer), _) <-
123123 tclift $ elaborate ctxt (MN 0 "patRHS") clhsty
124124 (do pbinds lhs_tm
125− (_, d) <- erun fc (build winfo False rhs)
125+ (_, _) <- erun fc (build winfo False rhs)
126126 psolve lhs_tm
127127 tt <- get_term
128− return (tt, d))
128+ return $ runState (collectDeferred tt) [])
129129 logLvl 2 $ "---> " ++ show rhs'
130130 when (not (null defer)) $ iLOG $ "DEFERRED " ++ show defer
131131 addDeferred defer
132+ ctxt <- getContext
132133 (crhs, crhsty) <- tclift $ recheck ctxt [] rhs'
133134 return (clhs, crhs)
134135 where
@@ -418,4 +419,11 @@ collectDeferred (Bind n b t) = do b' <- cdb b
418419collectDeferred (App f a) = liftM2 App (collectDeferred f) (collectDeferred a)
419420collectDeferred t = return t
420421
422+-- Running tactics directly
423+
424+runTac :: PTactic -> Elab ()
425+runTac (Intro xs) = mapM_ (\x -> do attack; intro x) xs
426+runTac (Exact tm) = elab toplevel False tm
427+runTac Solve = solve
428+runTac x = fail $ "Not implemented " ++ show x
421429
src/Idris/Error.hs−7
@@ -23,13 +23,6 @@ liftCatch catchError m h =
2323idrisCatch :: Idris a -> (IOError -> Idris a) -> Idris a
2424idrisCatch op handler = liftCatch catch op handler
2525
26−pshow :: IState -> Err -> String
27−pshow i (Msg s) = s
28−pshow i (CantUnify x y e) = "Can't unify " ++ show (delab i x)
29− ++ " with " ++ show (delab i y)
30− -- ++ "\n\t(" ++ pshow i e ++ ")"
31−pshow i (At f e) = show f ++ ":" ++ pshow i e
32−
3326tclift :: Show a => TC a -> Idris a
3427tclift tc = case tc of
3528 OK v -> return v
src/Idris/Parser.hs+16
@@ -74,6 +74,7 @@ loadSource f = do iLOG ("Reading " ++ f)
7474 return ()
7575
7676parseExpr i = runParser (pFullExpr defaultSyntax) i "(input)"
77+parseTac i = runParser (pTactic defaultSyntax) i "(proof)"
7778
7879parseImports :: FilePath -> String -> Idris ([String], String, SourcePos)
7980parseImports fname input
@@ -584,6 +585,21 @@ pWhereblock syn = do reserved "where"; lchar '{'
584585 lchar '}';
585586 return $ concat ds
586587
588+pTactic :: SyntaxInfo -> IParser PTactic
589+pTactic syn = do reserved "intro"; ns <- sepBy pName (lchar ',')
590+ return $ Intro ns
591+ <|> do reserved "refine"; n <- pName
592+ return $ Refine n
593+ <|> do reserved "exact"; t <- pExpr syn;
594+ i <- getState
595+ return $ Exact (desugar syn i t)
596+ <|> do reserved "solve"
597+ return Solve
598+ <|> do reserved "attack"
599+ return Attack
600+ <|> do reserved "qed"
601+ return Qed
602+
587603-- Dealing with implicit arguments
588604
589605implicit :: SyntaxInfo -> Name -> PTerm -> IParser PTerm
src/Idris/Prover.hsnew file+91
@@ -0,0 +1,91 @@
1+module Idris.Prover where
2+
3+import Core.Elaborate hiding (Tactic(..))
4+import Core.TT
5+import Core.Evaluate
6+import Core.CaseTree
7+import Core.Typecheck
8+
9+import Idris.AbsSyntax
10+import Idris.Delaborate
11+import Idris.ElabDecls
12+import Idris.Parser
13+import Idris.Error
14+
15+import System.Console.Readline
16+import Control.Monad.State
17+
18+prover :: Name -> Idris ()
19+prover x = do ctxt <- getContext
20+ i <- get
21+ case lookupTy x ctxt of
22+ Just t -> if elem x (idris_metavars i)
23+ then prove ctxt x t
24+ else fail $ show x ++ " is not a metavariable"
25+ _ -> fail "No such metavariable"
26+
27+prove :: Context -> Name -> Type -> Idris ()
28+prove ctxt n ty
29+ = do let ps = initElaborator n ctxt ty
30+ tm <- ploop True ("-" ++ show n) (ps, "")
31+ iLOG $ "Adding " ++ show tm
32+ let tree = simpleCase False [(P Ref n ty, tm)]
33+ logLvl 3 (show tree)
34+ (ptm, pty) <- tclift $ recheck ctxt [] tm
35+ updateContext (addCasedef n False [(P Ref n ty, ptm)] ty)
36+ solveDeferred n
37+
38+elabStep :: ElabState -> Elab a -> Idris (a, ElabState)
39+elabStep st e = do case runStateT e st of
40+ OK (a, st') -> return (a, st')
41+ Error a -> do i <- get
42+ fail (pshow i a)
43+
44+dumpState :: IState -> ProofState -> IO ()
45+dumpState ist (PS nm [] _ tm _ _ _ _ _ _ _) = putStrLn $ (show nm) ++ ": no more goals"
46+dumpState ist ps@(PS nm (h:hs) _ tm _ _ i _ cyxy _ _)
47+ = do let OK ty = goalAtFocus ps
48+ let OK env = envAtFocus ps
49+ putStrLn $ "Other goals: " ++ show hs ++ "\n"
50+ putStr $ showPs (reverse env)
51+ putStrLn $ "---------------------------------- (" ++ show nm
52+ ++ ") --------"
53+ putStrLn $ show h ++ " : " ++ showG ty ++ "\n"
54+ where
55+ tshow t = show (delab ist t)
56+
57+ showPs [] = ""
58+ showPs ((n, Let t v) : bs)
59+ = " " ++ show n ++ " : " ++
60+ tshow t ++ " = " ++ tshow v ++ "\n" ++ showPs bs
61+ showPs ((n, b) : bs)
62+ = " " ++ show n ++ " : " ++
63+ tshow (binderTy b) ++ "\n" ++ showPs bs
64+
65+ showG (Guess t v) = tshow t ++ " =?= " ++ tshow v
66+ showG b = tshow (binderTy b)
67+
68+ploop :: Bool -> String -> ElabState -> Idris Term
69+ploop d prompt e
70+ = do i <- get
71+ when d $ lift $ dumpState i (proof e)
72+ x <- lift $ readline (prompt ++ "> ")
73+ cmd <- case x of
74+ Nothing -> fail "Abandoned"
75+ Just input -> do lift $ addHistory input
76+ return (parseTac i input)
77+ (d, st, done) <- idrisCatch
78+ (case cmd of
79+ Left err -> do iputStrLn (show err)
80+ return (False, e, False)
81+ Right Qed -> do (hs, _) <- elabStep e get_holes
82+ when (not (null hs)) $ fail "Incomplete proof"
83+ return (False, e, True)
84+ Right tac -> do (_, st) <- elabStep e (runTac tac)
85+ return (True, st, False))
86+ (\err -> do iputStrLn (report err)
87+ return (False, e, False))
88+ if done then do (tm, _) <- elabStep st get_term
89+ return tm
90+ else ploop d prompt st
91+
src/Idris/REPL.hs+2
@@ -8,6 +8,7 @@ import Idris.ElabDecls
88import Idris.Error
99import Idris.Delaborate
1010import Idris.Compiler
11+import Idris.Prover
1112
1213import Core.Evaluate
1314import Core.ProofShell
@@ -55,6 +56,7 @@ process (Spec t) = do (tm, ty) <- elabVal toplevel t
5556 ist <- get
5657 let tm' = specialise ctxt (idris_statics ist) tm
5758 iputStrLn (show (delab ist tm'))
59+process (Prove n) = prover n
5860process (HNF t) = do (tm, ty) <- elabVal toplevel t
5961 ctxt <- getContext
6062 ist <- get
src/Idris/REPLParser.hs+1
@@ -25,6 +25,7 @@ pCmd = try (do cmd ["q", "quit"]; eof; return Quit)
2525 <|> try (do cmd ["ttshell"]; eof; return TTShell)
2626 <|> try (do cmd ["c", "compile"]; f <- identifier; eof; return (Compile f))
2727 <|> try (do cmd ["m", "metavars"]; eof; return Metavars)
28+ <|> try (do cmd ["p", "prove"]; n <- pName; eof; return (Prove n))
2829 <|> try (do cmd ["log"]; i <- natural; eof; return (LogLvl (fromIntegral i)))
2930 <|> try (do cmd ["spec"]; t <- pFullExpr defaultSyntax; return (Spec t))
3031 <|> try (do cmd ["hnf"]; t <- pFullExpr defaultSyntax; return (HNF t))