@@ -27,11 +27,22 @@ data Command = Theorem Name Raw
27 | Print Name
27 | Print Name
28 | Tac (Elab ())
28 | Tac (Elab ())
30−type ElabState = (ProofState, String)
30+data ElabState = ES ProofState String (Maybe ElabState)
31type Elab a = StateT ElabState TC a
32type Elab a = StateT ElabState TC a
33proof :: ElabState -> ProofState
34proof :: ElabState -> ProofState
34−proof = fst
35+proof (ES p _ _) = p
38+saveState = do e@(ES p s _) <- get
39+ put (ES p s (Just e))
42+loadState = do (ES p s e) <- get
45+ _ -> fail "Nothing to undo"
36erun :: FC -> Elab a -> Elab a
47erun :: FC -> Elab a -> Elab a
37erun f elab = do s <- get
48erun f elab = do s <- get
@@ -41,49 +52,49 @@ erun f elab = do s <- get
41 Error (At f e) -> lift $ Error (At f e)
52 Error (At f e) -> lift $ Error (At f e)
42 Error e -> lift $ Error (At f e)
53 Error e -> lift $ Error (At f e)
44−runElab :: Elab a -> ProofState -> TC (a, (ProofState, String))
55+runElab :: Elab a -> ProofState -> TC (a, ElabState)
45−runElab e ps = runStateT e (ps, "")
56+runElab e ps = runStateT e (ES ps "" Nothing)
47−execElab :: Elab a -> ProofState -> TC (ProofState, String)
58+execElab :: Elab a -> ProofState -> TC ElabState
48−execElab e ps = execStateT e (ps, "")
59+execElab e ps = execStateT e (ES ps "" Nothing)
50initElaborator :: Name -> Context -> Type -> ProofState
61initElaborator :: Name -> Context -> Type -> ProofState
51initElaborator = newProof
62initElaborator = newProof
53elaborate :: Context -> Name -> Type -> Elab a -> TC (a, String)
64elaborate :: Context -> Name -> Type -> Elab a -> TC (a, String)
54elaborate ctxt n ty elab = do let ps = initElaborator n ctxt ty
65elaborate ctxt n ty elab = do let ps = initElaborator n ctxt ty
55− (a, (ps', str)) <- runElab elab ps
66+ (a, ES ps' str _) <- runElab elab ps
56 return (a, str)
67 return (a, str)
58−processTactic' t = do (p, logs) <- get
69+processTactic' t = do ES p logs prev <- get
59 (p', log) <- lift $ processTactic t p
70 (p', log) <- lift $ processTactic t p
60− put (p', logs ++ log)
71+ put (ES p' (logs ++ log) prev)
63-- Some handy gadgets for pulling out bits of state
74-- Some handy gadgets for pulling out bits of state
65-- get the global context
76-- get the global context
66get_context :: Elab Context
77get_context :: Elab Context
67−get_context = do (p, _) <- get
78+get_context = do ES p _ _ <- get
68 return (context p)
79 return (context p)
70-- get the proof term
81-- get the proof term
71get_term :: Elab Term
82get_term :: Elab Term
72−get_term = do (p, _) <- get
83+get_term = do ES p _ _ <- get
73 return (pterm p)
84 return (pterm p)
75-- get the local context at the currently in focus hole
86-- get the local context at the currently in focus hole
76get_env :: Elab Env
87get_env :: Elab Env
77−get_env = do (p, _) <- get
88+get_env = do ES p _ _ <- get
78 lift $ envAtFocus p
89 lift $ envAtFocus p
80get_holes :: Elab [Name]
91get_holes :: Elab [Name]
81−get_holes = do (p, _) <- get
92+get_holes = do ES p _ _ <- get
82 return (holes p)
93 return (holes p)
84-- get the current goal type
95-- get the current goal type
85goal :: Elab Type
96goal :: Elab Type
86−goal = do (p, _) <- get
97+goal = do ES p _ _ <- get
87 b <- lift $ goalAtFocus p
98 b <- lift $ goalAtFocus p
88 return (binderTy b)
99 return (binderTy b)
@@ -96,12 +107,12 @@ get_type tm = do ctxt <- get_context
97-- get holes we've deferred for later definition
108-- get holes we've deferred for later definition
98get_deferred :: Elab [Name]
109get_deferred :: Elab [Name]
99−get_deferred = do (p, _) <- get
110+get_deferred = do ES p _ _ <- get
100 return (deferred p)
111 return (deferred p)
102-- given a desired hole name, return a unique hole name
113-- given a desired hole name, return a unique hole name
103unique_hole :: Name -> Elab Name
114unique_hole :: Name -> Elab Name
104−unique_hole n = do (p, _) <- get
115+unique_hole n = do ES p _ _ <- get
105 env <- get_env
116 env <- get_env
106 return (uniq n (holes p ++ map fst env))
117 return (uniq n (holes p ++ map fst env))
@@ -118,8 +129,8 @@ next (UN (x:xs)) = let (num', nm') = span isDigit (reverse x)
118 readN x = read x
129 readN x = read x
120elog :: String -> Elab ()
131elog :: String -> Elab ()
121−elog str = do (p, logs) <- get
132+elog str = do ES p logs prev <- get
122− put (p, logs ++ str ++ "\n")
133+ put (ES p (logs ++ str ++ "\n") prev)
124-- The primitives, from ProofState
135-- The primitives, from ProofState
@@ -191,7 +202,7 @@ proofstate = processTactic' ProofState
192qed :: Elab Term
203qed :: Elab Term
193qed = do processTactic' QED
204qed = do processTactic' QED
194− (p, _) <- get
205+ ES p _ _ <- get
195 return (pterm p)
206 return (pterm p)
197undo :: Elab ()
208undo :: Elab ()
@@ -205,11 +216,11 @@ prepare_apply fn imps =
205 env <- get_env
216 env <- get_env
206 -- let claims = getArgs ty imps
217 -- let claims = getArgs ty imps
207 claims <- doClaims (normalise ctxt env ty) imps []
218 claims <- doClaims (normalise ctxt env ty) imps []
208− (p, s) <- get
219+ ES p s prev <- get
209 -- reverse the claims we made so that args go left to right
220 -- reverse the claims we made so that args go left to right
210 let n = length (filter not imps)
221 let n = length (filter not imps)
211 let (h : hs) = holes p
222 let (h : hs) = holes p
212− put (p { holes = h : (reverse (take n hs) ++ drop n hs) }, s)
223+ put (ES (p { holes = h : (reverse (take n hs) ++ drop n hs) }) s prev)
213 return claims
224 return claims
215 doClaims (Bind n' (Pi t) sc) (i : is) claims =
226 doClaims (Bind n' (Pi t) sc) (i : is) claims =
@@ -232,10 +243,10 @@ apply fn imps =
232 -- *Don't* solve the arguments we're specifying by hand.
243 -- *Don't* solve the arguments we're specifying by hand.
233 -- (remove from unified list before calling end_unify)
244 -- (remove from unified list before calling end_unify)
234 let dontunify = map fst (filter (not.snd) (zip args imps))
245 let dontunify = map fst (filter (not.snd) (zip args imps))
235− (p, s) <- get
246+ ES p s prev <- get
236 let (n, hs) = unified p
247 let (n, hs) = unified p
237 let unify = (n, filter (\ (n, t) -> not (n `elem` dontunify)) hs)
248 let unify = (n, filter (\ (n, t) -> not (n `elem` dontunify)) hs)
238− put (p { unified = unify }, s)
249+ put (ES (p { unified = unify }) s prev)
239 end_unify
250 end_unify
240 return args
251 return args
@@ -262,7 +273,7 @@ apply_elab n args =
262 elabClaims [] = return ()
273 elabClaims [] = return ()
263 elabClaims ((n, Nothing) : xs) = elabClaims xs
274 elabClaims ((n, Nothing) : xs) = elabClaims xs
264 elabClaims ((n, Just elaboration) : xs) =
275 elabClaims ((n, Just elaboration) : xs) =
265− do (p, _) <- get
276+ do ES p _ _ <- get
266 focus n; elaboration; elabClaims xs
277 focus n; elaboration; elabClaims xs
268 mkMN n@(MN _ _) = n
279 mkMN n@(MN _ _) = n