1module Idris.Prover where
3import Idris.Core.Elaborate hiding (Tactic(..))
5import Idris.Core.Evaluate
6import Idris.Core.CaseTree
7import Idris.Core.Typecheck
10import Idris.Elab.Value
13import Idris.AbsSyntaxTree
14import Idris.Delaborate
15import Idris.Docs (getDocs, pprintDocs, pprintConstDocs)
18import Idris.Parser hiding (params)
21import Idris.Completion
22import qualified Idris.IdeSlave as IdeSlave
24import Idris.TypeSearch (searchByType)
26import Text.Trifecta.Result(Result(..))
28import System.IO (Handle, stdin, stdout, hPutStrLn)
29import System.Console.Haskeline
30import System.Console.Haskeline.History
31import Control.Monad.State.Strict
37prover :: Bool -> Name -> Idris ()
41 case lookupTy x ctxt of
42 [t] -> if elem x (map fst (idris_metavars i))
43 then prove (idris_optimisation i) ctxt lit x t
44 else ifail $ show x ++ " is not a metavariable"
45 _ -> fail "No such metavariable"
47showProof :: Bool -> Name -> [String] -> String
49 = bird ++ show n ++ " = proof" ++ break ++
50 showSep break (map (\x -> " " ++ x) ps) ++
52 where bird = if lit then "> " else ""
55proverSettings :: ElabState [PDecl] -> Settings Idris
56proverSettings e = setComplete (proverCompletion (assumptionNames e)) defaultSettings
58assumptionNames :: ElabState [PDecl] -> [String]
60 = case envAtFocus (proof e) of
63 names ((MN _ _, _) : bs) = names bs
64 names ((n, _) : bs) = show n : names bs
66prove :: Ctxt OptInfo -> Context -> Bool -> Name -> Type -> Idris ()
67prove opt ctxt lit n ty
68 = do let ps = initElaborator n ctxt ty
69 ideslavePutSExp "start-proof-mode" n
70 (tm, prf) <- ploop n True ("-" ++ show n) [] (ES (ps, []) "" Nothing) Nothing
71 iLOG $ "Adding " ++ show tm
73 case idris_outputmode i of
74 IdeSlave _ _ -> ideslavePutSExp "end-proof-mode" (n, showProof lit n prf)
75 _ -> iputStrLn $ showProof lit n prf
76 let proofs = proof_list i
77 putIState (i { proof_list = (n, prf) : proofs })
78 let tree = simpleCase False True False CompileTime (fileFC "proof") [] [] [([], P Ref n ty, tm)]
80 (ptm, pty) <- recheckC (fileFC "proof") [] tm
81 logLvl 5 ("Proof type: " ++ show pty ++ "\n" ++
82 "Expected type:" ++ show ty)
83 case converts ctxt [] ty pty of
85 Error e -> ierror (CantUnify False ty pty e [] 0)
87 ei <- getErasureInfo `fmap` getIState
88 updateContext (addCasedef n ei (CaseInfo True False) False False True False
89 [] [] -- argtys, inaccArgs
90 [Right (P Ref n ty, ptm)]
91 [([], P Ref n ty, ptm)]
92 [([], P Ref n ty, ptm)]
93 [([], P Ref n ty, ptm)]
94 [([], P Ref n ty, ptm')] ty)
96 case idris_outputmode i of
98 runIO . hPutStrLn h $ IdeSlave.convSExp "return" (IdeSlave.SymbolAtom "ok", "") n
101elabStep :: ElabState [PDecl] -> ElabD a -> Idris (a, ElabState [PDecl])
102elabStep st e = case runStateT eCheck st of
103 OK (a, st') -> return (a, st')
105 where eCheck = do res <- e
110 [] -> do tm <- get_term
112 lift $ check ctxt [] (forget tm)
114 ((_,_,_,e,_,_):_) -> lift $ Error e
116dumpState :: IState -> ProofState -> Idris ()
117dumpState ist (PS nm [] _ _ tm _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) =
118 do rendered <- iRender $ prettyName True False [] nm <> colon <+> text "No more goals."
120dumpState ist ps@(PS nm (h:hs) _ _ tm _ _ _ _ _ _ problems i _ _ ctxy _ _ _ _) = do
121 let OK ty = goalAtFocus ps
122 let OK env = envAtFocus ps
123 let state = prettyOtherGoals hs <> line <>
124 prettyAssumptions env <> line <>
125 prettyGoal (zip (assumptionNames env) (repeat False)) ty
126 rendered <- iRender state
130 ppo = ppOptionIst ist
132 tPretty bnd t = annotate (AnnTerm bnd t) .
133 pprintPTerm ppo bnd [] (idris_infixes ist) $
136 assumptionNames :: Env -> [Name]
137 assumptionNames = map fst
139 prettyPs :: [(Name, Bool)] -> Env -> Doc OutputAnnotation
140 prettyPs bnd [] = empty
141 prettyPs bnd ((n@(MN _ r), _) : bs)
142 | r == txt "rewrite_rule" = prettyPs ((n, False):bnd) bs
143 prettyPs bnd ((n@(MN _ _), _) : bs)
144 | not (n `elem` freeEnvNames bs) = prettyPs bnd bs
145 prettyPs bnd ((n, Let t v) : bs) =
146 line <> bindingOf n False <+> text "=" <+> tPretty bnd v <+> colon <+>
147 align (tPretty bnd t) <> prettyPs ((n, False):bnd) bs
148 prettyPs bnd ((n, b) : bs) =
149 line <> bindingOf n False <+> colon <+>
150 align (tPretty bnd (binderTy b)) <> prettyPs ((n, False):bnd) bs
152 prettyG bnd (Guess t v) = tPretty bnd t <+> text "=?=" <+> tPretty bnd v
153 prettyG bnd b = tPretty bnd $ binderTy b
156 text "---------- Goal: ----------" <$$>
157 bindingOf h False <+> colon <+> align (prettyG bnd ty)
159 prettyAssumptions env =
160 if length env == 0 then
163 text "---------- Assumptions: ----------" <>
164 nest nestingSize (prettyPs [] $ reverse env)
166 prettyOtherGoals hs =
167 if length hs == 0 then
170 text "---------- Other goals: ----------" <$$>
171 nest nestingSize (align . cat . punctuate (text ",") . map (flip bindingOf False) $ hs)
173 freeEnvNames :: Env -> [Name]
174 freeEnvNames = foldl (++) [] . map (\(n, b) -> freeNames (Bind n b Erased))
176lifte :: ElabState [PDecl] -> ElabD a -> Idris a
177lifte st e = do (v, _) <- elabStep st e
180receiveInput :: Handle -> ElabState [PDecl] -> Idris (Maybe String)
183 let inh = if h == stdout then stdin else h
184 len' <- runIO $ IdeSlave.getLen inh
186 Left err -> ierror err
188 l <- runIO $ IdeSlave.getNChar inh len ""
189 (sexp, id) <- case IdeSlave.parseMessage l of
190 Left err -> ierror err
191 Right (sexp, id) -> return (sexp, id)
192 putIState $ i { idris_outputmode = (IdeSlave id h) }
193 case IdeSlave.sexpToCommand sexp of
194 Just (IdeSlave.REPLCompletions prefix) ->
195 do (unused, compls) <- proverCompletion (assumptionNames e) (reverse prefix, "")
196 let good = IdeSlave.SexpList [IdeSlave.SymbolAtom "ok", IdeSlave.toSExp (map replacement compls, reverse unused)]
197 ideslavePutSExp "return" good
199 Just (IdeSlave.Interpret cmd) -> return (Just cmd)
200 Just (IdeSlave.TypeOf str) -> return (Just (":t " ++ str))
201 Just (IdeSlave.DocsFor str) -> return (Just (":doc " ++ str))
204ploop :: Name -> Bool -> String -> [String] -> ElabState [PDecl] -> Maybe History -> Idris (Term, [String])
205ploop fn d prompt prf e h
207 let autoSolve = opt_autoSolve (idris_options i)
208 when d $ dumpState i (proof e)
210 case idris_outputmode i of
212 runInputT (proverSettings e) $
213 -- Manually track the history so that we can use the proof state
215 Just history -> putHistory history
217 l <- getInputLine (prompt ++ "> ")
222 i <- receiveInput handle e
224 (cmd, step) <- case x of
225 Nothing -> do iPrintError ""; ifail "Abandoned"
226 Just input -> do return (parseTactic i input, input)
228 Success Abandon -> do iPrintError ""; ifail "Abandoned"
230 (d, st, done, prf', res) <- idrisCatch
232 Failure err -> return (False, e, False, prf, Left . Msg . show . fixColour (idris_colourRepl i) $ err)
233 Success Undo -> do (_, st) <- elabStep e loadState
234 return (True, st, False, init prf, Right $ iPrintResult "")
235 Success ProofState -> return (True, e, False, prf, Right $ iPrintResult "")
236 Success ProofTerm -> do tm <- lifte e get_term
237 iputStrLn $ "TT: " ++ show tm ++ "\n"
238 return (False, e, False, prf, Right $ iPrintResult "")
239 Success Qed -> do hs <- lifte e get_holes
240 when (not (null hs)) $ ifail "Incomplete proof"
241 iputStrLn "Proof completed!"
242 return (False, e, True, prf, Right $ iPrintResult "")
243 Success (TCheck (PRef _ n)) -> checkNameType n
244 Success (TCheck t) -> checkType t
245 Success (TEval t) -> evalTerm t e
246 Success (TDocStr x) -> docStr x
247 Success (TSearch t) -> search t
248 Success tac -> do (_, e) <- elabStep e saveState
249 (_, st) <- elabStep e (runTac autoSolve i fn tac)
250 return (True, st, False, prf ++ [step], Right $ iPrintResult ""))
251 (\err -> return (False, e, False, prf, Left err))
252 ideslavePutSExp "write-proof-state" (prf', length prf')
254 Left err -> do ist <- getIState
255 iRenderError $ pprintErr ist err
256 ploop fn d prompt prf' st h'
258 if done then do (tm, _) <- elabStep st get_term
261 ploop fn d prompt prf' st h'
262 where envCtxt env ctxt = foldl (\c (n, b) -> addTyDecl n Bound (binderTy b) c) ctxt env
268 let OK env = envAtFocus (proof e)
269 ctxt' = envCtxt env ctxt
270 bnd = map (\x -> (fst x, False)) env
271 ist' = ist { tt_ctxt = ctxt' }
273 -- Unlike the REPL, metavars have no special treatment, to
274 -- make it easier to see how to prove with them.
275 let action = case lookupNames n ctxt' of
276 [] -> iPrintError $ "No such variable " ++ show n
277 ts -> iPrintFunTypes bnd n (map (\n -> (n, pprintDelabTy ist' n)) ts)
279 return (False, e, False, prf, Right action))
280 (\err -> do putIState ist ; ierror err)
286 let OK env = envAtFocus (proof e)
287 ctxt' = envCtxt env ctxt
288 putIState ist { tt_ctxt = ctxt' }
289 (tm, ty) <- elabVal recinfo ERHS t
290 let ppo = ppOptionIst ist
291 ty' = normaliseC ctxt [] ty
292 infixes = idris_infixes ist
295 iPrintTermWithType (prettyImp ppo PType) type1Doc
296 _ -> let bnd = map (\x -> (fst x, False)) env in
297 iPrintTermWithType (pprintPTerm ppo bnd [] infixes (delab ist tm))
298 (pprintPTerm ppo bnd [] infixes (delab ist ty))
300 return (False, e, False, prf, Right action))
301 (\err -> do putIState ist { tt_ctxt = ctxt } ; ierror err)
303 evalTerm t e = withErrorReflection $
304 do ctxt <- getContext
307 let OK env = envAtFocus (proof e)
308 ctxt' = envCtxt env ctxt
309 ist' = ist { tt_ctxt = ctxt' }
310 bnd = map (\x -> (fst x, False)) env
312 (tm, ty) <- elabVal recinfo ERHS t
313 let tm' = force (normaliseAll ctxt' env tm)
314 ty' = force (normaliseAll ctxt' env ty)
315 ppo = ppOption (idris_options ist')
316 infixes = idris_infixes ist
317 tmDoc = pprintPTerm ppo bnd [] infixes (delab ist' tm')
318 tyDoc = pprintPTerm ppo bnd [] infixes (delab ist' ty')
319 action = iPrintTermWithType tmDoc tyDoc
321 return (False, e, False, prf, Right action))
322 (\err -> do putIState ist ; ierror err)
323 docStr :: Either Name Const -> Idris (Bool, ElabState [PDecl], Bool, [String], Either Err (Idris ()))
324 docStr (Left n) = do ist <- getIState
325 idrisCatch (case lookupCtxtName n (idris_docstrings ist) of
326 [] -> return (False, e, False, prf,
327 Left . Msg $ "No documentation for " ++ show n)
328 ns -> do toShow <- mapM (showDoc ist) ns
329 return (False, e, False, prf,
330 Right $ iRenderResult (vsep toShow)))
331 (\err -> do putIState ist ; ierror err)
332 where showDoc ist (n, d) = do doc <- getDocs n
333 return $ pprintDocs ist doc
334 docStr (Right c) = do ist <- getIState
335 return (False, e, False, prf, Right . iRenderResult $ pprintConstDocs ist c (constDocs c))
336 search t = return (False, e, False, prf, Right $ searchByType t)
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