@@ -22,9 +22,11 @@ data ProofState = PS { thname :: Name,
22 nextname :: Int, -- name supply
22 nextname :: Int, -- name supply
23 pterm :: Term, -- current proof term
23 pterm :: Term, -- current proof term
24 ptype :: Type, -- original goal
24 ptype :: Type, -- original goal
25+ unified :: (Name, [(Name, Term)]),
25 defer :: [(Name, Type)], -- names we'll need to define
26 defer :: [(Name, Type)], -- names we'll need to define
26 previous :: Maybe ProofState, -- for undo
27 previous :: Maybe ProofState, -- for undo
27 context :: Context,
28 context :: Context,
28 done :: Bool
30 done :: Bool
@@ -38,6 +40,8 @@ data Tactic = Attack
38 | Fill Raw
40 | Fill Raw
42 | EvalIn Raw
46 | EvalIn Raw
43 | CheckIn Raw
47 | CheckIn Raw
@@ -55,14 +59,14 @@ data TacticAction = AddGoal Name -- add a new goal, solve immediately
55 | FocusGoal Name -- focus on this goal next
59 | FocusGoal Name -- focus on this goal next
56 | MoveGoal Name -- move this goal to the end of the hole queue
60 | MoveGoal Name -- move this goal to the end of the hole queue
57 | Solved Name
61 | Solved Name
58− | AlsoSolved Name Term -- goals solved by unification
62+ | AlsoSolved [(Name, Term)] -- variables solved by unification
59 | Log String
63 | Log String
61-- Some utilites on proof and tactic states
65-- Some utilites on proof and tactic states
63instance Show ProofState where
67instance Show ProofState where
64− show (PS nm [] _ tm _ _ _ _ _) = show nm ++ ": no more goals"
68+ show (PS nm [] _ tm _ _ _ _ _ _ _) = show nm ++ ": no more goals"
65− show (PS nm (h:hs) _ tm _ i _ ctxt _)
69+ show (PS nm (h:hs) _ tm _ _ i _ ctxt _ _)
66 = let OK g = goal (Just h) tm
70 = let OK g = goal (Just h) tm
67 wkenv = premises g in
71 wkenv = premises g in
68 showPs wkenv (reverse wkenv) ++ "\n" ++
72 showPs wkenv (reverse wkenv) ++ "\n" ++
@@ -93,21 +97,25 @@ hole _ = False
93holeName i = MN i "hole"
97holeName i = MN i "hole"
95getName :: Monad m => String -> StateT TState m Name
99getName :: Monad m => String -> StateT TState m Name
96−getName tag = do (n, ts) <- get
100+getName tag = do ps <- get
97− put (n+1, ts)
102+ put (ps { nextname = n+1 })
98 return $ MN n tag
103 return $ MN n tag
100−action :: Monad m => TacticAction -> StateT TState m ()
105+action :: Monad m => (ProofState -> ProofState) -> StateT TState m ()
101−action a = do (n, ts) <- get
106+action a = do ps <- get
102− put (n, a:ts)
107+ put (a ps)
109+addLog :: Monad m => String -> StateT TState m ()
110+addLog str = action (\ps -> ps { plog = plog ps ++ str ++ "\n" })
104newProof :: Name -> Context -> Type -> ProofState
112newProof :: Name -> Context -> Type -> ProofState
105newProof n ctxt ty = let h = holeName 0
113newProof n ctxt ty = let h = holeName 0
106 ty' = vToP ty in
114 ty' = vToP ty in
107− PS n [h] 1 (Bind h (Hole ty') (P Bound h ty')) ty []
115+ PS n [h] 1 (Bind h (Hole ty') (P Bound h ty')) ty (h, []) []
108− Nothing ctxt False
116+ Nothing ctxt "" False
110−type TState = (Int, [TacticAction])
118+type TState = ProofState -- [TacticAction])
111type RunTactic = Context -> Env -> Term -> StateT TState TC Term
119type RunTactic = Context -> Env -> Term -> StateT TState TC Term
112type Hole = Maybe Name -- Nothing = default hole, first in list in proof state
120type Hole = Maybe Name -- Nothing = default hole, first in list in proof state
@@ -134,27 +142,28 @@ goal h tm = g [] tm where
134 gb env (Guess t v) = g env t `mplus` g env v
142 gb env (Guess t v) = g env t `mplus` g env v
135 gb env t = g env (binderTy t)
143 gb env t = g env (binderTy t)
137−tactic :: Hole -> ProofState -> Context -> RunTactic -> StateT TState TC ProofState
145+tactic :: Hole -> RunTactic -> StateT TState TC ()
138−tactic h ps ctxt f = do let tm = pterm ps
146+tactic h f = do ps <- get
139− tm' <- atH [] tm
147+ tm' <- atH (context ps) [] (pterm ps)
148+ ps <- get -- might have changed while processing
140− return (ps { pterm = tm' })
149+ put (ps { pterm = tm' })
142− atH env binder@(Bind n b sc)
151+ atH c env binder@(Bind n b sc)
143− | hole b && same h n = f ctxt env binder
152+ | hole b && same h n = f c env binder
144 | otherwise
153 | otherwise
145− = pure Bind <*> pure n <*> atHb env b <*> atH ((n,b) : env) sc
154+ = pure Bind <*> pure n <*> atHb c env b <*> atH c ((n,b) : env) sc
146− atH env (App f a) = pure App <*> atH env f <*> atH env a
155+ atH c env (App f a) = pure App <*> atH c env f <*> atH c env a
147− atH env t = return t
156+ atH c env t = return t
149− atHb env (Let t v) = pure Let <*> atH env t <*> atH env v
158+ atHb c env (Let t v) = pure Let <*> atH c env t <*> atH c env v
150− atHb env (Guess t v) = pure Guess <*> atH env t <*> atH env v
159+ atHb c env (Guess t v) = pure Guess <*> atH c env t <*> atH c env v
151− atHb env t = do ty' <- atH env (binderTy t)
160+ atHb c env t = do ty' <- atH c env (binderTy t)
152− return $ t { binderTy = ty' }
161+ return $ t { binderTy = ty' }
154attack :: RunTactic
163attack :: RunTactic
155attack ctxt env (Bind x (Hole t) sc)
164attack ctxt env (Bind x (Hole t) sc)
156 = do h <- getName "hole"
165 = do h <- getName "hole"
157− action (AddGoal h)
166+ action (\ps -> ps { holes = h : holes ps })
158 return $ Bind x (Guess t (newtm h)) sc
167 return $ Bind x (Guess t (newtm h)) sc
160 newtm h = Bind h (Hole t) (P Bound h t)
169 newtm h = Bind h (Hole t) (P Bound h t)
@@ -164,15 +173,22 @@ claim :: Name -> Raw -> RunTactic
164claim n ty ctxt env t =
173claim n ty ctxt env t =
165 do (tyv, tyt) <- lift $ check ctxt env ty
174 do (tyv, tyt) <- lift $ check ctxt env ty
166 lift $ isSet ctxt env tyt
175 lift $ isSet ctxt env tyt
167− action (NextGoal n)
176+ action (\ps -> let (g:gs) = holes ps in
177+ ps { holes = g : n : gs } )
168 return $ Bind n (Hole tyv) t -- (weakenTm 1 t)
178 return $ Bind n (Hole tyv) t -- (weakenTm 1 t)
170focus :: Name -> RunTactic
180focus :: Name -> RunTactic
171−focus n ctxt env t = do action (FocusGoal n)
181+focus n ctxt env t = do action (\ps -> let hs = holes ps in
183+ then ps { holes = n : (hs \\ [n]) }
172 return t
185 return t
174movelast :: Name -> RunTactic
187movelast :: Name -> RunTactic
175−movelast n ctxt env t = do action (MoveGoal n)
188+movelast n ctxt env t = do action (\ps -> let hs = holes ps in
190+ then ps { holes = (hs \\ [n]) ++ [n] }
176 return t
192 return t
178-- Hmmm. YAGNI?
194-- Hmmm. YAGNI?
@@ -192,17 +208,16 @@ fill :: Raw -> RunTactic
192fill guess ctxt env (Bind x (Hole ty) sc) =
208fill guess ctxt env (Bind x (Hole ty) sc) =
193 do (val, valty) <- lift $ check ctxt env guess
209 do (val, valty) <- lift $ check ctxt env guess
194 ns <- lift $ unify ctxt env valty ty
210 ns <- lift $ unify ctxt env valty ty
195− solve_all ns
211+ ps <- get
212+ let (uh, uns) = unified ps
213+ put (ps { unified = (uh, uns ++ ns) })
214+ addLog (show (uh, uns ++ ns))
196 return $ Bind x (Guess ty val) sc
215 return $ Bind x (Guess ty val) sc
198− solve_all [] = return ()
199− solve_all ((n, tm): ns) = do action (AlsoSolved n tm)
201fill _ _ _ _ = fail "Can't fill here."
216fill _ _ _ _ = fail "Can't fill here."
203solve :: RunTactic
218solve :: RunTactic
204solve ctxt env (Bind x (Guess ty val) sc)
219solve ctxt env (Bind x (Guess ty val) sc)
205− | pureTerm val = do action (Solved x)
220+ | pureTerm val = do action (\ps -> ps { holes = holes ps \\ [x] })
206 return $ Bind x (Let ty val) sc -- instantiate val (pToV x sc)
221 return $ Bind x (Let ty val) sc -- instantiate val (pToV x sc)
207 | otherwise = fail "I see a hole in your solution."
222 | otherwise = fail "I see a hole in your solution."
208solve _ _ _ = fail "Not a guess."
223solve _ _ _ = fail "Not a guess."
@@ -236,7 +251,7 @@ compute ctxt env (Bind x (Hole ty) sc) =
236check_in :: Raw -> RunTactic
251check_in :: Raw -> RunTactic
237check_in t ctxt env tm =
252check_in t ctxt env tm =
238 do (val, valty) <- lift $ check ctxt env t
253 do (val, valty) <- lift $ check ctxt env t
239− action (Log (showEnv env val ++ " : " ++ showEnv env valty))
254+ addLog (showEnv env val ++ " : " ++ showEnv env valty)
240 return tm
255 return tm
242eval_in :: Raw -> RunTactic
257eval_in :: Raw -> RunTactic
@@ -244,14 +259,34 @@ eval_in t ctxt env tm =
244 do (val, valty) <- lift $ check ctxt env t
259 do (val, valty) <- lift $ check ctxt env t
245 let val' = normalise ctxt env val
260 let val' = normalise ctxt env val
246 let valty' = normalise ctxt env valty
261 let valty' = normalise ctxt env valty
247− action (Log (showEnv env val ++ " : " ++
262+ addLog (showEnv env val ++ " : " ++
248− showEnv env valty ++
263+ showEnv env valty ++
249-- " in " ++ show env ++
264-- " in " ++ show env ++
250− " ==>\n " ++
265+ " ==>\n " ++
251− showEnv env val' ++ " : " ++
266+ showEnv env val' ++ " : " ++
252− showEnv env valty'))
267+ showEnv env valty')
253 return tm
268 return tm
270+start_unify :: Name -> RunTactic
271+start_unify n ctxt env tm = do action (\ps -> ps { unified = (n, []) })
274+solve_unified :: RunTactic
275+solve_unified ctxt env tm =
277+ let (_, ns) = unified ps
278+ action (\ps -> ps { holes = holes ps \\ map fst ns })
279+ return (updateSolved ns tm)
281+ updateSolved xs (Bind n b@(Hole _) t)
282+ | Just v <- lookup n xs = instantiate v (pToV n (updateSolved xs t))
283+ updateSolved xs (Bind n b t)
284+ | otherwise = Bind n (fmap (updateSolved xs) b) (updateSolved xs t)
285+ updateSolved xs (App f a) = App (updateSolved xs f) (updateSolved xs a)
286+ updateSolved xs (P _ n _)
287+ | Just v <- lookup n xs = v
288+ updateSolved xs t = t
255-- shuffleHoles :: Term -> Term
290-- shuffleHoles :: Term -> Term
256-- shuffleHoles tm = shuffle [] tm
291-- shuffleHoles tm = shuffle [] tm
@@ -273,48 +308,22 @@ processTactic t ps
273 = case holes ps of
308 = case holes ps of
274 [] -> Error "Nothing to fill in."
309 [] -> Error "Nothing to fill in."
275 (h:_) -> do let n = nextname ps
310 (h:_) -> do let n = nextname ps
276− (ps', (n', actions)) <- runStateT (process t h ps) (n, [])
311+ ps' <- execStateT (process t h) ps
277− return (ps' { nextname = n',
278− pterm = updateSolved (getSolved actions) (pterm ps'),
279− holes = goals (holes ps') actions,
280− previous = Just ps },
312+ return (ps' { previous = Just ps, plog = "" }, plog ps')
283− logs (Log x : xs) = x ++ "\n" ++ logs xs
284− logs (_ : xs) = logs xs
287− goals g (AddGoal n : xs) = goals (n : g) xs
288− goals (g:gs) (NextGoal n : xs) = goals (g : n : gs) xs
289− goals g (FocusGoal n : xs)
290− | n `elem` g = goals (n : (g \\ [n])) xs
291− goals g (MoveGoal n : xs)
292− | n `elem` g = goals ((g \\ [n]) ++ [n]) xs
293− goals g (Solved n : xs) = goals (g \\ [n]) xs
294− goals g (AlsoSolved n tm : xs) = goals (g \\ [n]) xs
295− goals g (_ : xs) = goals g xs
298− getSolved (AlsoSolved n tm : xs) = (n, tm) : getSolved xs
299− getSolved (_ : xs) = getSolved xs
301− updateSolved xs (Bind n b@(Hole _) t)
302− | Just v <- lookup n xs = instantiate v (pToV n (updateSolved xs t))
303− updateSolved xs (Bind n b t)
304− | otherwise = Bind n (fmap (updateSolved xs) b) (updateSolved xs t)
305− updateSolved xs (App f a) = App (updateSolved xs f) (updateSolved xs a)
306− updateSolved xs (P _ n _)
307− | Just v <- lookup n xs = v
308− updateSolved xs t = t
310−process :: Tactic -> Name -> ProofState -> StateT TState TC ProofState
314+process :: Tactic -> Name -> StateT TState TC ()
311−process t h ps = tactic (Just h) ps (context ps) (mktac t)
315+process EndUnify _
317+ let (h, _) = unified ps
318+ tactic (Just h) solve_unified
319+process t h = tactic (Just h) (mktac t)
312 where mktac Attack = attack
320 where mktac Attack = attack
313 mktac (Claim n r) = claim n r
321 mktac (Claim n r) = claim n r
314 mktac (Exact r) = exact r
322 mktac (Exact r) = exact r
315 mktac (Fill r) = fill r
323 mktac (Fill r) = fill r
316 mktac Regret = regret
324 mktac Regret = regret
317 mktac Solve = solve
325 mktac Solve = solve
326+ mktac (StartUnify n) = start_unify n
318 mktac Compute = compute
327 mktac Compute = compute
319 mktac (Intro n) = intro n
328 mktac (Intro n) = intro n
320 mktac (Forall n t) = forall n t
329 mktac (Forall n t) = forall n t