idris-0.9.3: src/Idris/Prover.hs
module Idris.Prover where
import Core.Elaborate hiding (Tactic(..))
import Core.TT
import Core.Evaluate
import Core.CaseTree
import Core.Typecheck
import Idris.AbsSyntax
import Idris.Delaborate
import Idris.ElabDecls
import Idris.ElabTerm
import Idris.Parser
import Idris.Error
import Idris.DataOpts
import System.Console.Haskeline
import Control.Monad.State
import Util.Pretty
prover :: Bool -> Name -> Idris ()
prover lit x =
do ctxt <- getContext
i <- get
case lookupTy Nothing x ctxt of
[t] -> if elem x (idris_metavars i)
then prove ctxt lit x t
else fail $ show x ++ " is not a metavariable"
_ -> fail "No such metavariable"
showProof :: Bool -> Name -> [String] -> String
showProof lit n ps
= bird ++ show n ++ " = proof {" ++ break ++
showSep break (map (\x -> " " ++ x ++ ";") ps) ++
break ++ "}\n"
where bird = if lit then "> " else ""
break = "\n" ++ bird
prove :: Context -> Bool -> Name -> Type -> Idris ()
prove ctxt lit n ty
= do let ps = initElaborator n ctxt ty
(tm, prf) <- ploop True ("-" ++ show n) [] (ES (ps, []) "" Nothing)
iLOG $ "Adding " ++ show tm
iputStrLn $ showProof lit n prf
i <- get
let proofs = proof_list i
put (i { proof_list = (n, prf) : proofs })
let tree = simpleCase False True (FC "proof" 0) [([], P Ref n ty, tm)]
logLvl 3 (show tree)
(ptm, pty) <- recheckC (FC "proof" 0) [] tm
ptm' <- applyOpts ptm
updateContext (addCasedef n True False True [([], P Ref n ty, ptm)]
[([], P Ref n ty, ptm')] ty)
solveDeferred n
elabStep :: ElabState [PDecl] -> ElabD a -> Idris (a, ElabState [PDecl])
elabStep st e = do case runStateT e st of
OK (a, st') -> return (a, st')
Error a -> do i <- get
fail (pshow i a)
dumpState :: IState -> ProofState -> IO ()
dumpState ist (PS nm [] _ tm _ _ _ _ _ _ _ _ _ _ _) =
putStrLn . render $ pretty nm <> colon <+> text "No more goals."
dumpState ist ps@(PS nm (h:hs) _ tm _ _ _ _ problems i _ _ ctxy _ _) = do
let OK ty = goalAtFocus ps
let OK env = envAtFocus ps
putStrLn . render $
prettyOtherGoals hs $$
prettyAssumptions env $$
prettyGoal ty
where
-- XXX
tPretty t = pretty $ delab ist t
prettyPs [] = empty
prettyPs ((MN _ "rewrite_rule", _) : bs) = prettyPs bs
prettyPs ((n, Let t v) : bs) =
nest nestingSize (pretty n <+> text "=" <+> tPretty v <> colon <+>
tPretty t $$ prettyPs bs)
prettyPs ((n, b) : bs) =
pretty n <+> colon <+> tPretty (binderTy b) $$ prettyPs bs
prettyG (Guess t v) = tPretty t <+> text "=?=" <+> tPretty v
prettyG b = tPretty $ binderTy b
prettyGoal ty =
text "---------- Goal: ----------" $$
pretty h <> colon $$ nest nestingSize (prettyG ty)
prettyAssumptions env =
if length env == 0 then
empty
else
text "---------- Assumptions: ----------" $$
nest nestingSize (prettyPs $ reverse env)
prettyOtherGoals hs =
if length hs == 0 then
empty
else
text "---------- Other goals: ----------" $$
pretty hs
lifte :: ElabState [PDecl] -> ElabD a -> Idris a
lifte st e = do (v, _) <- elabStep st e
return v
ploop :: Bool -> String -> [String] -> ElabState [PDecl] -> Idris (Term, [String])
ploop d prompt prf e
= do i <- get
when d $ liftIO $ dumpState i (proof e)
x <- lift $ getInputLine (prompt ++ "> ")
(cmd, step) <- case x of
Nothing -> fail "Abandoned"
Just input -> do return (parseTac i input, input)
case cmd of
Right Abandon -> fail "Abandoned"
_ -> return ()
(d, st, done, prf') <- idrisCatch
(case cmd of
Left err -> do iputStrLn (show err)
return (False, e, False, prf)
Right Undo ->
do (_, st) <- elabStep e loadState
return (True, st, False, init prf)
Right ProofState ->
return (True, e, False, prf)
Right ProofTerm ->
do tm <- lifte e get_term
iputStrLn $ "TT: " ++ show tm ++ "\n"
return (False, e, False, prf)
Right Qed -> do hs <- lifte e get_holes
when (not (null hs)) $ fail "Incomplete proof"
return (False, e, True, prf)
Right tac -> do (_, e) <- elabStep e saveState
(_, st) <- elabStep e (runTac True i tac)
return (True, st, False, prf ++ [step]))
(\err -> do iputStrLn (show err)
return (False, e, False, prf))
if done then do (tm, _) <- elabStep st get_term
return (tm, prf')
else ploop d prompt prf' st