prep. ONE tactic per step VISIBLE in calculation
note: there were exceptions: Take and Subproblem as
first tactics in a (sub-)calculation.
1 (* Title: Interpret/lucas-interpreter.sml
2 Author: Walther Neuper 2019
3 (c) due to copyright terms
6 signature LUCAS_INTERPRETER =
8 datatype next_step_result =
9 Next_Step of Istate.T * Proof.context * Tactic.T
10 | Helpless | End_Program of Istate.T (*TODO ?needed when..*)* Tactic.T
11 val find_next_step: Program.T -> Calc.T -> Istate.T -> Proof.context
14 datatype input_tactic_result =
15 Safe_Step of Istate.T * Proof.context * Tactic.T
16 | Unsafe_Step of Istate.T * Proof.context * Tactic.T
17 | Not_Locatable (*TODO rm..*) of string
18 val locate_input_tactic: Program.T -> Calc.T -> Istate.T -> Proof.context
19 -> Tactic.T -> input_tactic_result
21 datatype input_term_result = Found_Step of Calc.T | Not_Derivable (**)
22 val locate_input_term: Calc.T -> term -> input_term_result (**)
25 find_next_step calls do_next and is called by by_tactic;
26 by_tactic and do_next are mutually recursive via by_tactic..Apply_Method'
28 val by_tactic: Tactic.T -> Istate.T * Proof.context -> Calc.T -> string * Chead.calcstate'
29 val do_next: Calc.T -> string * Chead.calcstate'
31 (* ---- for tests only: shifted from below to remove the Warning "unused" at fun.def. --------- *)
33 Accept_Tac1 of Istate.pstate * Proof.context * Tactic.T
34 | Reject_Tac1 of Istate.pstate * Proof.context * Tactic.T
36 val assoc2str: expr_val1 -> string
37 (* ---- for Doc/Lucas-Interpreter ------------------------------------------------------------- *)
38 val check_Seq_up: Istate.pstate -> term -> term
39 datatype expr_val = Accept_Tac of Tactic.T * Istate.pstate * Proof.context
40 | Reject_Tac | Term_Val of term
42 val scan_dn: Calc.T * Proof.context -> Istate.pstate -> term -> expr_val
43 val scan_up: term * (Calc.T * Proof.context) -> Istate.pstate -> term -> expr_val
44 val go_scan_up: term * (Calc.T * Proof.context) -> Istate.pstate -> expr_val
45 val scan_to_tactic: term * (Calc.T * Proof.context) -> Istate.T -> expr_val
46 val check_tac: Calc.T * Proof.context -> Istate.pstate -> term * term option -> expr_val
47 (*/-------------------------------------------------------- ! aktivate for Test_Isac BEGIN ---\* )
48 val check_Let_up: Istate.pstate -> term -> term * term
49 val compare_step: Generate.taci list * Ctree.pos' list * (Calc.T) -> term -> string * Chead.calcstate'
51 val scan_dn1: (Calc.T * Proof.context * Tactic.T) -> Istate.pstate -> term -> expr_val1
52 val scan_up1: term * (Calc.T * Proof.context * Tactic.T) -> Istate.pstate -> term -> expr_val1;
53 val go_scan_up1: term * (Calc.T * Proof.context * Tactic.T) -> Istate.pstate -> expr_val1;
54 val scan_to_tactic1: term * (Calc.T * Proof.context * Tactic.T) -> Istate.T -> expr_val1
56 val check_tac1: Calc.T * Proof.context * Tactic.T -> Istate.pstate -> term * term option -> expr_val1
57 ( *\--- ! aktivate for Test_Isac END ----------------------------------------------------------/*)
61 structure LI(**): LUCAS_INTERPRETER(**) =
69 (*** auxiliary functions ***)
71 fun at_location [] t = t
72 | at_location (D :: p) (Abs(_, _, body)) = at_location (p : TermC.path) body
73 | at_location (L :: p) (t1 $ _) = at_location p t1
74 | at_location (R :: p) (_ $ t2) = at_location p t2
75 | at_location l _ = error ("at_location: no " ^ TermC.string_of_path l);
77 fun check_Let_up ({path, ...}: pstate) prog =
78 case at_location (drop_last path) prog of
79 Const ("HOL.Let",_) $ _ $ (Abs (i, T, body)) => (TermC.mk_Free (i, T), body)
80 | t => raise ERROR ("scan_up1..\"HOL.Let $ _\" with: \"" ^ Rule.term2str t ^ "\"")
81 fun check_Seq_up ({path, ...}: pstate) prog =
82 case at_location (drop_last path) prog of
83 Const ("Tactical.Chain",_) $ _ $ e2=> e2
84 | t => raise ERROR ("scan_up1..\"Tactical.Chain $ _\" with: \"" ^ Rule.term2str t ^ "\"")
87 (*** determine a next tactic within a program ***)
89 datatype next_step_result = Next_Step of Istate.T * Proof.context * Tactic.T
90 | Helpless | End_Program of Istate.T * Tactic.T (*contains prog_result, without asms*)
92 (** scan to a Prog_Tac **)
94 datatype expr_val = (* "ExprVal" in the sense of denotational semantics *)
95 Reject_Tac (* tactic is found but NOT acknowledged, scan is continued *)
96 | Accept_Tac of (* tactic is found and acknowledged, scan is stalled *)
97 Tactic.T * (* Prog_Tac is applicable_in cstate *)
98 Istate.pstate * (* created by application of Tactic.T, for resuming execution *)
99 Proof.context (* created by application of Tactic.T *)
100 | Term_Val of (* Prog_Expr is found and evaluated, scan is continued *)
101 term; (* value of Prog_Expr, for updating environment *)
103 (* check if a prog_tac found in a program is applicable_in *)
104 fun check_tac ((pt, p), ctxt) ist (prog_tac, form_arg) =
106 val m = LItool.tac_from_prog pt (Proof_Context.theory_of ctxt) prog_tac
109 Tactic.Subproblem _ => (*might involve problem refinement etc*)
111 val m' = snd (Sub_Problem.tac_from_prog pt prog_tac)
113 Accept_Tac (m', ist |> set_subst_found (form_arg, Tactic.result m'), ctxt)
116 (case Applicable.applicable_in p pt m of
117 Applicable.Appl m' =>
118 Accept_Tac (m', ist |> set_subst_found (form_arg, Tactic.result m'),
119 Tactic.insert_assumptions m' ctxt)
125 scan_dn, go_scan_up, scan_up scan for find_next_step.
126 (1) scan_dn is recursive descent depth first strictly from L to R;
127 (2) go_scan_up goes to the parent node and calls (3);
128 (3) scan_up resumes according to the interpreter-state.
129 Call of (2) means that there was an applicable Prog_Tac below = before.
131 fun scan_dn cc (ist as {act_arg, ...}) (Const ("Tactical.Try"(*1*), _) $ e $ a) =
132 (case scan_dn cc (ist|> path_down_form ([L, R], a)) e of
133 Reject_Tac => Term_Val act_arg
134 | (*Accept_Tac*) goback => goback)
135 | scan_dn cc (ist as {act_arg, ...}) (Const ("Tactical.Try"(*2*), _) $ e) =
136 (case scan_dn cc (ist |> path_down [R]) e of
137 Reject_Tac => Term_Val act_arg
138 | (*Accept_Tac*) goback => goback)
140 | scan_dn cc ist (Const ("Tactical.Repeat"(*1*), _) $ e $ a) =
141 scan_dn cc (ist |> path_down_form ([L, R], a)) e
142 | scan_dn cc ist (Const ("Tactical.Repeat"(*2*), _) $ e) =
143 scan_dn cc (ist |> path_down [R]) e
145 | scan_dn cc ist (Const ("Tactical.Chain"(*1*), _) $ e1 $ e2 $ a) =
146 (case scan_dn cc (ist |> path_down_form ([L, L, R], a)) e1 of
147 Term_Val v => scan_dn cc (ist |> path_down_form ([L, R], a) |> set_act v) e2
148 | (*Accept_Tac*) goback => goback)
149 | scan_dn cc ist (Const ("Tactical.Chain"(*2*), _) $ e1 $ e2) =
150 (case scan_dn cc (ist |> path_down [L, R]) e1 of
151 Term_Val v => scan_dn cc (ist |> path_down [R] |> set_act v) e2
152 | (*Accept_Tac*) goback => goback)
154 | scan_dn cc ist (Const ("HOL.Let"(*1*), _) $ e $ (Abs (i, T, b))) =
155 (case scan_dn cc (ist |> path_down [L, R]) e of
156 Term_Val res => scan_dn cc (ist |> path_down [R, D] |> upd_env'' (Free (i, T), res)) b
157 | (*Accept_Tac*) goback => goback)
159 | scan_dn (cc as (_, ctxt)) (ist as {eval, act_arg, ...}) (Const ("Tactical.While"(*1*), _) $ c $ e $ a) =
160 if Rewrite.eval_true_ (Proof_Context.theory_of ctxt) eval (subst_atomic (ist |> get_act_env |> Env.update' a) c)
161 then scan_dn cc (ist |> path_down_form ([L, R], a)) e
162 else Term_Val act_arg
163 | scan_dn (cc as (_, ctxt)) (ist as {eval, act_arg, ...}) (Const ("Tactical.While"(*2*), _) $ c $ e) =
164 if Rewrite.eval_true_ (Proof_Context.theory_of ctxt) eval (subst_atomic (Env.update_opt' (get_subst ist)) c)
165 then scan_dn cc (ist |> path_down [R]) e
166 else Term_Val act_arg
168 |scan_dn cc ist (Const ("Tactical.Or"(*1*), _) $e1 $ e2 $ a) =
169 (case scan_dn cc (ist |> path_down_form ([L, L, R], a)) e1 of
170 Accept_Tac lme => Accept_Tac lme
171 | _ => scan_dn cc (ist |> path_down_form ([L, R], a)) e2)
172 | scan_dn cc ist (Const ("Tactical.Or"(*2*), _) $e1 $ e2) =
173 (case scan_dn cc (ist |> path_down [L, R]) e1 of
174 Accept_Tac lme => Accept_Tac lme
175 | _ => scan_dn cc (ist |> path_down [R]) e2)
177 | scan_dn (cc as (_, ctxt)) (ist as {eval, ...}) (Const ("Tactical.If"(*1*), _) $ c $ e1 $ e2) =
178 if Rewrite.eval_true_ (Proof_Context.theory_of ctxt) eval (subst_atomic (Env.update_opt' (get_subst ist)) c)
179 then scan_dn cc (ist |> path_down [L, R]) e1
180 else scan_dn cc (ist |> path_down [R]) e2
182 | scan_dn (cc as (_, ctxt)) (ist as {eval, ...}) t =
183 if Tactical.contained_in t
184 then raise TERM ("scan_dn expects Prog_Tac or Prog_Expr", [t])
186 case LItool.check_leaf "next " ctxt eval (get_subst ist) t of
187 (Program.Expr s, _) => Term_Val s (*TODO?: include set_found here and drop those after call*)
188 | (Program.Tac prog_tac, form_arg) =>
189 check_tac cc ist (prog_tac, form_arg)
191 fun go_scan_up (pcc as (sc, _)) (ist as {path, act_arg, found_accept, ...}) =
192 if path = [R] (*root of the program body*)
195 then Term_Val act_arg
196 else raise ERROR "LItool.find_next_step without result"
197 else scan_up pcc (ist |> path_up) (go_up path sc)
198 (* scan is strictly to R, because at L there was an \<open>expr_val\<close> *)
199 and scan_up pcc ist (Const ("Tactical.Try"(*1*), _) $ _ $ _) = go_scan_up pcc ist
200 | scan_up pcc ist (Const ("Tactical.Try"(*2*), _) $ _) = go_scan_up pcc ist
202 | scan_up (pcc as (_, cc)) ist (Const ("Tactical.Repeat"(*1*), _) $ e $ _) =
203 (case scan_dn cc (ist |> path_down [L, R]) e of
204 Accept_Tac ict => Accept_Tac ict
205 | Reject_Tac => go_scan_up pcc ist
206 | Term_Val v => go_scan_up pcc (ist |> set_act v |> set_found))
207 | scan_up (pcc as (_, cc)) ist (Const ("Tactical.Repeat"(*2*), _) $ e) =
208 (case scan_dn cc (ist |> path_down [R]) e of
209 Accept_Tac ict => Accept_Tac ict
210 | Reject_Tac => go_scan_up pcc ist
211 | Term_Val v => go_scan_up pcc (ist |> set_act v |> set_found))
213 | scan_up pcc ist (Const ("Tactical.Chain"(*1*), _) $ _ $ _ $ _) = go_scan_up pcc ist
214 | scan_up pcc ist (Const ("Tactical.Chain"(*2*), _) $ _ $ _) = go_scan_up pcc ist
215 | scan_up (pcc as (sc, cc)) ist (Const ("Tactical.Chain"(*3*), _) $ _) =
217 val e2 = check_Seq_up ist sc
219 case scan_dn cc (ist |> path_up_down [R]) e2 of
220 Accept_Tac ict => Accept_Tac ict
221 | Reject_Tac => go_scan_up pcc (ist |> path_up)
222 | Term_Val v => go_scan_up pcc (ist |> path_up |> set_act v |> set_found)
225 | scan_up (pcc as (sc, cc)) ist (Const ("HOL.Let"(*1*), _) $ _) =
227 val (i, body) = check_Let_up ist sc
229 case scan_dn cc (ist |> path_up_down [R, D] |> upd_env i) body of
230 Accept_Tac ict => Accept_Tac ict
231 | Reject_Tac => go_scan_up pcc (ist |> path_up)
232 | Term_Val v => go_scan_up pcc (ist |> path_up |> set_act v |> set_found)
234 | scan_up pcc ist (Abs _(*2*)) = go_scan_up pcc ist
235 | scan_up pcc ist (Const ("HOL.Let"(*3*), _) $ _ $ (Abs _)) = go_scan_up pcc ist
237 | scan_up (pcc as (_, cc as (_, ctxt))) (ist as {eval, ...})
238 (Const ("Tactical.While"(*1*), _) $ c $ e $ _) =
239 if Rewrite.eval_true_ (Proof_Context.theory_of ctxt) eval (subst_atomic (Env.update_opt' (get_subst ist)) c)
241 case scan_dn cc (ist |> path_down [L, R]) e of
242 Accept_Tac ict => Accept_Tac ict
243 | Reject_Tac => go_scan_up pcc ist
244 | Term_Val v => go_scan_up pcc (ist |> set_act v |> set_found)
246 go_scan_up pcc (ist (*|> set_found*))
247 | scan_up (pcc as (_, cc as (_, ctxt))) (ist as {eval, ...})
248 (Const ("Tactical.While"(*2*), _) $ c $ e) =
249 if Rewrite.eval_true_ (Proof_Context.theory_of ctxt) eval (subst_atomic (Env.update_opt' (get_subst ist)) c)
251 case scan_dn cc (ist |> path_down [R]) e of
252 Accept_Tac ict => Accept_Tac ict
253 | Reject_Tac => go_scan_up pcc ist
254 | Term_Val v => go_scan_up pcc (ist |> set_act v |> set_found)
258 | scan_up pcc ist (Const ("Tactical.Or"(*1*), _) $ _ $ _ $ _) = go_scan_up pcc ist
259 | scan_up pcc ist (Const ("Tactical.Or"(*2*), _) $ _ $ _) = go_scan_up pcc ist
260 | scan_up pcc ist (Const ("Tactical.Or"(*3*), _) $ _ ) = go_scan_up pcc ist
262 | scan_up pcc ist (Const ("Tactical.If"(*1*), _) $ _ $ _ $ _) = go_scan_up pcc ist
264 | scan_up _ _ t = error ("scan_up not impl for " ^ Rule.term2str t)
266 (* scan program until an applicable tactic is found *)
267 fun scan_to_tactic (prog, cc) (Pstate (ist as {path, ...})) =
269 then scan_dn cc (trans_scan_dn ist) (Program.body_of prog)
270 else go_scan_up (prog, cc) (trans_scan_up ist)
271 | scan_to_tactic _ _ = raise ERROR "scan_to_tactic: uncovered pattern";
273 (* find the next applicable Prog_Tac in a prog *)
274 fun find_next_step (Rule.Prog prog) (ptp as(pt, (p, _))) (Pstate ist) ctxt =
275 (case scan_to_tactic (prog, (ptp, ctxt)) (Pstate ist) of
276 Accept_Tac (tac, ist, ctxt) =>
277 Next_Step (Pstate ist, Tactic.insert_assumptions tac ctxt, tac)
278 | Term_Val prog_result =>
279 (case par_pbl_det pt p of
282 val (_, pblID, _) = get_obj g_spec pt p';
284 End_Program (Pstate ist, Tactic.Check_Postcond' (pblID, (prog_result, [(*???*)])))
286 | _ => End_Program (Pstate ist, Tactic.End_Detail' (Rule.e_term,[])))
287 | Reject_Tac => Helpless)
288 | find_next_step _ _ ist _ =
289 raise ERROR ("find_next_step: not impl for " ^ istate2str ist);
292 (*** locate an input tactic within a program ***)
294 datatype input_tactic_result =
295 Safe_Step of Istate.T * Proof.context * Tactic.T
296 | Unsafe_Step of Istate.T * Proof.context * Tactic.T
297 | Not_Locatable of string
299 (*all functions ending with "1" are supposed to be replaced by those without "1"*)
300 datatype expr_val1 = (* "ExprVal" in the sense of denotational semantics *)
301 Reject_Tac1 of (* tactic is found but NOT acknowledged, scan is continued *)
302 Istate.pstate * Proof.context * Tactic.T (*TODO: revise Pstate {or,...},no args as Reject_Tac*)
303 | Accept_Tac1 of (* tactic is found and acknowledged, scan is stalled *)
304 Istate.pstate * (* the current state, returned for resuming execution *)
305 Proof.context * (* updated according to evaluation of Prog_Tac *)
306 Tactic.T (* Prog_Tac is associated to Tactic.input *)
307 | Term_Val1 of (* Prog_Expr is found and evaluated, scan is continued *)
308 term (* value of Prog_Expr, for updating environment *)
309 fun assoc2str (Accept_Tac1 _) = "Accept_Tac1"
310 | assoc2str (Term_Val1 _) = "Term_Val1"
311 | assoc2str (Reject_Tac1 _) = "Reject_Tac1";
314 (** check a Prog_Tac: is it associated to Tactic ? **)
316 fun check_tac1 ((pt, p), ctxt, tac) (ist as {act_arg, or, ...}) (prog_tac, form_arg) =
317 case LItool.associate pt ctxt (tac, prog_tac) of
318 (* HERE ----------------vvvv ContextC.insert_assumptions asm ctxt DONE -- 2nd in gen//*)
319 LItool.Ass (m, v', ctxt)
320 => Accept_Tac1 (ist |> set_subst_true (form_arg, v') |> set_found, ctxt, m)
321 | LItool.Ass_Weak (m, v', ctxt) (*the ONLY ones in locate_tac ^v^v^v^v^ *)
322 => Accept_Tac1 (ist |> set_subst_false (form_arg, v') |> set_found, ctxt, m)
324 (case or of (* switch for Tactical.Or: 1st AssOnly, 2nd AssGen *)
325 AssOnly => Term_Val1 act_arg
327 case Applicable.applicable_in p pt (LItool.tac_from_prog pt (Celem.assoc_thy "Isac_Knowledge") prog_tac) of
328 Applicable.Appl m' => Reject_Tac1 (ist |> set_subst_false (form_arg, Tactic.result m'), ctxt, tac)
329 | Applicable.Notappl _ => Term_Val1 act_arg)
331 (** scan to a Prog_Tac **)
333 (* scan is strictly first L, then R; tacticals have 2 args at maximum *)
334 fun scan_dn1 cct ist (Const ("Tactical.Try"(*1*), _) $ e $ a) =
335 (case scan_dn1 cct (ist |> path_down_form ([L, R], a)) e of goback => goback)
336 | scan_dn1 cct ist (Const ("Tactical.Try"(*2*), _) $ e) =
337 (case scan_dn1 cct (ist |> path_down [R]) e of goback => goback)
339 | scan_dn1 cct ist (Const ("Tactical.Repeat"(*1*), _) $ e $ a) =
340 scan_dn1 cct (ist |> path_down_form ([L, R], a)) e
341 | scan_dn1 cct ist (Const ("Tactical.Repeat"(*2*), _) $ e) =
342 scan_dn1 cct (ist |> path_down [R]) e
344 | scan_dn1 (cct as (cstate, _, _)) ist (Const ("Tactical.Chain"(*1*), _) $ e1 $ e2 $ a) =
345 (case scan_dn1 cct (ist |> path_down_form ([L, L, R], a)) e1 of
346 Term_Val1 v => scan_dn1 cct (ist |> path_down [L, R] |> set_subst' (a, v)) e2
347 | Reject_Tac1 (ist', ctxt', tac') => scan_dn1 (cstate, ctxt', tac') (ist
348 |> path_down_form ([L, R], a) |> trans_env_act ist') e2
350 | scan_dn1 (cct as (cstate, _, _)) ist (Const ("Tactical.Chain"(*2*), _) $e1 $ e2) =
351 (case scan_dn1 cct (ist |> path_down [L, R]) e1 of
352 Term_Val1 v => scan_dn1 cct (ist |> path_down [R] |> set_act v) e2
353 | Reject_Tac1 (ist', ctxt', tac') =>
354 scan_dn1 (cstate, ctxt', tac') (ist |> path_down [R] |> trans_env_act ist') e2
357 | scan_dn1 cct ist (Const ("HOL.Let", _) $ e $ (Abs (id, T, b))) =
358 (case scan_dn1 cct (ist |> path_down [L, R]) e of
359 Reject_Tac1 (ist', _, _) =>
360 scan_dn1 cct (ist' |> path_down [R, D] |> upd_env (TermC.mk_Free (id, T)) |> trans_ass ist) b
362 scan_dn1 cct (ist |> path_down [R, D] |> upd_env'' (TermC.mk_Free (id, T), v)) b
365 | scan_dn1 (cct as (_, ctxt, _)) (ist as {eval, act_arg, ...})
366 (Const ("Tactical.While"(*1*), _) $ c $ e $ a) =
367 if Rewrite.eval_true_ (Proof_Context.theory_of ctxt) eval (subst_atomic (ist |> get_act_env |> Env.update' a) c)
368 then scan_dn1 cct (ist |> path_down_form ([L, R], a)) e
369 else Term_Val1 act_arg
370 | scan_dn1 (cct as (_, ctxt, _)) (ist as {eval, act_arg, ...})
371 (Const ("Tactical.While"(*2*),_) $ c $ e) =
372 if Rewrite.eval_true_ (Proof_Context.theory_of ctxt) eval (subst_atomic (Env.update_opt' (get_subst ist)) c)
373 then scan_dn1 cct (ist |> path_down [R]) e
374 else Term_Val1 act_arg
376 | scan_dn1 cct (ist as {or = ORundef, ...}) (Const ("Tactical.Or"(*1*), _) $e1 $ e2 $ a) =
377 (case scan_dn1 cct (ist |> path_down_form ([L, L, R], a) |> set_or AssOnly) e1 of
379 (case scan_dn1 cct (ist |> path_down [L, R] |> set_subst' (a, v) |> set_or AssOnly) e2 of
381 (case scan_dn1 cct (ist |> path_down [L, L, R] |> upd_env'' (a, v) |> set_or AssGen) e1 of
383 scan_dn1 cct (ist |> path_down [L, R] |> upd_env'' (a, v) |> set_or AssGen) e2
386 | Reject_Tac1 _ => raise ERROR ("scan_dn1 Tactical.Or(*1*): must not return Reject_Tac1")
388 | scan_dn1 cct ist (Const ("Tactical.Or"(*2*), _) $e1 $ e2) =
389 (case scan_dn1 cct (ist |> path_down [L, R]) e1 of
390 Term_Val1 v => scan_dn1 cct (ist |> path_down [R] |> set_act v) e2
393 | scan_dn1 (cct as (_, ctxt, _)) (ist as {eval, ...}) (Const ("Tactical.If", _) $ c $ e1 $ e2) =
394 if Rewrite.eval_true_ (Proof_Context.theory_of ctxt) eval (subst_atomic (Env.update_opt' (get_subst ist)) c)
395 then scan_dn1 cct (ist |> path_down [L, R]) e1
396 else scan_dn1 cct (ist |> path_down [R]) e2
398 | scan_dn1 (cct as (_, ctxt, _)) (ist as {eval, ...}) t =
399 if Tactical.contained_in t then raise TERM ("scan_dn1 expects Prog_Tac or Prog_Expr", [t])
401 case LItool.check_leaf "locate" ctxt eval (get_subst ist) t of
402 (Program.Expr _, form_arg) =>
403 Term_Val1 (Rewrite.eval_prog_expr (Proof_Context.theory_of ctxt) eval
404 (subst_atomic (Env.update_opt'' (get_act_env ist, form_arg)) t))
405 | (Program.Tac prog_tac, form_arg) =>
406 check_tac1 cct ist (prog_tac, form_arg)
408 fun go_scan_up1 (pcct as (prog, _)) (ist as {path, act_arg, ...}) =
410 then scan_up1 pcct (ist |> path_up) (at_location (path_up' path) prog)
411 else Term_Val1 act_arg
412 (* scan is strictly to R, because at L there was a expr_val *)
413 and scan_up1 pcct ist (Const ("Tactical.Try"(*1*), _) $ _ $ _) = go_scan_up1 pcct ist
414 | scan_up1 pcct ist (Const ("Tactical.Try"(*2*), _) $ _) = go_scan_up1 pcct ist
416 | scan_up1 (pcct as (prog, cct as (cstate, _, _))) ist (t as Const ("Tactical.Repeat"(*1*), _) $ e $ a) =
417 (case scan_dn1 cct (ist |> path_down_form ([L, R], a) |> set_or ORundef) e of
418 Term_Val1 v => go_scan_up1 pcct (ist |> set_act v |> set_form a)
419 | Reject_Tac1 (ist', ctxt', tac') => scan_up1 (prog, (cstate, ctxt', tac')) ist' t
421 | scan_up1 (pcct as (prog, cct as (cstate, _, _))) ist (t as Const ("Tactical.Repeat"(*2*), _) $ e) =
422 (case scan_dn1 cct (ist |> path_down [R] |> set_or ORundef) e of
423 Term_Val1 v' => go_scan_up1 pcct (ist |> set_act v')
424 | Reject_Tac1 (ist', ctxt', tac') => scan_up1 (prog, (cstate, ctxt', tac')) ist' t
427 (*all has been done in (*2*) below*)
428 | scan_up1 pcct ist (Const ("Tactical.Chain"(*1*), _) $ _ $ _ $ _) = go_scan_up1 pcct ist
429 | scan_up1 pcct ist (Const ("Tactical.Chain"(*2*), _) $ _ $ _) = go_scan_up1 pcct ist (*comes from e2*)
430 | scan_up1 (pcct as (prog, cct as (cstate, _, _))) ist (Const ("Tactical.Chain"(*3*), _) $ _ ) =
432 val e2 = check_Seq_up ist prog (*comes from e1, goes to e2*)
434 case scan_dn1 cct (ist |> path_up_down [R] |> set_or ORundef) e2 of
435 Term_Val1 v => go_scan_up1 pcct (ist |> path_up |> set_act v)
436 | Reject_Tac1 (ist', ctxt', tac') => go_scan_up1 (prog, (cstate, ctxt', tac')) ist'
440 | scan_up1 (pcct as (prog, cct as (cstate, _, _))) ist (Const ("HOL.Let"(*1*), _) $ _) =
442 val (i, body) = check_Let_up ist prog
443 in case scan_dn1 cct (ist |> path_up_down [R, D] |> upd_env i |> set_or ORundef) body of
444 Accept_Tac1 iss => Accept_Tac1 iss
445 | Reject_Tac1 (ist', ctxt', tac') => go_scan_up1 (prog, (cstate, ctxt', tac')) ist'
446 | Term_Val1 v => go_scan_up1 pcct (ist |> path_up |> set_act v)
448 | scan_up1 pcct ist (Abs(*2*) _) = go_scan_up1 pcct ist
449 | scan_up1 pcct ist (Const ("HOL.Let"(*3*), _) $ _ $ (Abs _)) = go_scan_up1 pcct ist
451 | scan_up1 (pcct as (prog, cct as (cstate, ctxt, _))) (ist as {eval, ...})
452 (t as Const ("Tactical.While"(*1*),_) $ c $ e $ a) =
453 if Rewrite.eval_true_ (Proof_Context.theory_of ctxt) eval (subst_atomic (Env.update' a (get_act_env ist)) c)
455 case scan_dn1 cct (ist |> path_down_form ([L, R], a) |> set_or ORundef) e of
456 Term_Val1 v => go_scan_up1 pcct (ist |> set_act v |> set_form a)
458 | Reject_Tac1 (ist', ctxt', tac') => scan_up1 (prog, (cstate, ctxt', tac')) ist' t
460 else go_scan_up1 pcct (ist |> set_form a)
461 | scan_up1 (pcct as (prog, cct as (cstate, ctxt, _))) (ist as {eval, ...})
462 (t as Const ("Tactical.While"(*2*), _) $ c $ e) =
463 if Rewrite.eval_true_ (Proof_Context.theory_of ctxt) eval (subst_atomic (Env.update_opt' (get_subst ist)) c)
465 case scan_dn1 cct (ist |> path_down [R] |> set_or ORundef) e of
466 Term_Val1 v => go_scan_up1 pcct (ist |> set_act v)
467 | Reject_Tac1 (ist', ctxt', tac') => scan_up1 (prog, (cstate, ctxt', tac')) ist' t
469 else go_scan_up1 pcct ist
471 | scan_up1 pcct ist (Const ("If", _) $ _ $ _ $ _) = go_scan_up1 pcct ist
473 | scan_up1 pcct ist (Const ("Tactical.Or"(*1*), _) $ _ $ _ $ _) = go_scan_up1 pcct ist
474 | scan_up1 pcct ist (Const ("Tactical.Or"(*2*), _) $ _ $ _) = go_scan_up1 pcct ist
475 | scan_up1 pcct ist (Const ("Tactical.Or"(*3*), _) $ _ ) = go_scan_up1 pcct (ist |> path_up)
477 | scan_up1 pcct ist (Const ("Tactical.If",_) $ _ $ _ $ _) = go_scan_up1 pcct ist
479 | scan_up1 _ _ t = error ("scan_up1 not impl for t= " ^ Rule.term2str t)
481 fun scan_to_tactic1 (prog, (cctt as ((_, p), _, _))) (Pstate (ist as {path, ...})) =
482 if path = [] orelse Pos.at_first_tactic(*RM prog path RM WITH find_next_step IN solve*)p
483 then scan_dn1 cctt (ist |> set_path [R] |> set_or ORundef) (Program.body_of prog)
484 else go_scan_up1 (prog, cctt) ist
485 | scan_to_tactic1 _ _ = raise ERROR "scan_to_tactic1: uncovered pattern in fun.def"
487 (*locate an input tactic within a program*)
488 fun locate_input_tactic (Rule.Prog prog) cstate istate ctxt tac =
489 (case scan_to_tactic1 (prog, (cstate, ctxt, tac)) istate of
490 Accept_Tac1 ((ist as {assoc, ...}), ctxt, tac') =>
492 then Safe_Step (Pstate ist, ctxt, tac')
493 else Unsafe_Step (Pstate ist, ctxt, tac')
494 | Reject_Tac1 _ => Not_Locatable (Tactic.string_of tac ^ " not locatable")
495 | err => raise ERROR ("not-found-in-script: NotLocatable from " ^ @{make_string} err))
496 | locate_input_tactic _ _ _ _ _ = raise ERROR "locate_input_tactic: uncovered case in definition"
499 (*** locate an input formula within a program ***)
501 datatype input_term_result = Found_Step of Calc.T | Not_Derivable
503 fun by_tactic (Tactic.Apply_Method' (mI, _, _, _)) (_, ctxt) (pt, pos as (p, _)) =
505 (*OLD*) val (itms, (*l..*)oris, probl(*..l*)) = case get_obj I pt p of
506 (*OLD*) PblObj {meth = itms, origin = (oris, _, _), probl, ...} => (itms, oris, probl)
507 (*OLD*) | _ => error "LI.by_tactic Apply_Method': uncovered case get_obj"
508 (*OLD*) val {ppc, ...} = Specify.get_met mI;
509 (*OLD*) val itms = if itms <> [] then itms else Chead.complete_metitms oris probl [] ppc
510 (*OLD*) val itms = Specify.hack_until_review_Specify_1 mI itms
511 (*OLD*) val thy = Celem.assoc_thy (get_obj g_domID pt p);
512 (*OLD*) val srls = LItool.get_simplifier (pt, pos)
513 (*OLD*) val (is, env, ctxt, prog) = case LItool.init_pstate srls ctxt itms mI of
514 (*OLD*) (is as Pstate {env, ...}, ctxt, scr) => (is, env, ctxt, scr)
515 (*OLD*) | _ => error "LI.by_tactic Apply_Method': uncovered case init_pstate"
516 (*OLD*) val ini = LItool.init_form thy prog env;
521 (*OLD*) val pos = start_new_level pos
522 (*OLD*) val tac_ = Tactic.Apply_Method' (mI, SOME t, is, ctxt);
523 (*OLD*) val (pos, c, _, pt) = Generate.generate1 tac_ (is, ctxt) (pt, pos) (* implicit Take *)
525 (*OLD*) ("ok", ([(Tactic.Apply_Method mI, tac_, (pos, (is, ctxt)))], c, (pt, pos)))
529 (*NEW* ) val (tac', ist', ctxt') =
530 (*NEW*) case find_next_step prog (pt, (lev_dn p, Res)) is ctxt of
531 (*NEW*) Next_Step (ist, ctxt, tac) => (tac, ist, ctxt)
532 (*NEW*) | _ => raise ERROR ("LI.by_tactic..Apply_Method " ^ strs2str' mI)
535 (*NEW*) Tactic.Take' t =>
537 (*NEW*) val pos = start_new_level pos
538 (*NEW*) val tac_ = Tactic.Apply_Method' (mI, SOME t, ist', ctxt');
539 (*NEW*) val (pos, c, _, pt) = Generate.generate1 tac_ (ist', ctxt') (pt, pos) (* explicit Take *)
541 (*NEW*) ("ok", ([(Tactic.Apply_Method mI, tac_, (pos, (is, ctxt)))], c, (pt, pos)))
543 (*NEW*) | tac as Tactic.Subproblem' (_, _, headline, _, _, _) =>
545 (*NEW*) val pos = start_new_level pos
546 (*NEW*) val tac_ = Tactic.Apply_Method' (mI, SOME headline, ist', ctxt');
547 (*NEW*) val (pos, c, _, pt) = Generate.generate1 tac (ist', ctxt') (pt, pos) (* Subproblem *)
550 (*NEW*) ("ok", ([(Tactic.Apply_Method mI, tac_, (pos, (ist', ctxt')))], c, (pt, pos)))
553 (*NEW*) raise ERROR ("LI.by_tactic..Apply_Method' does NOT expect " ^ Tactic.string_of tac)
555 ( *OLD*) val pt = update_env pt (fst pos) (SOME (is, ctxt))
556 (*OLD*) val (_, (tacis, c, ptp)) = do_next (pt, pos)
557 (*OLD*) in ("ok", (tacis @ [(Tactic.Apply_Method mI,
558 (*OLD*) Tactic.Apply_Method' (mI, NONE, e_istate, ctxt), (pos, (is, ctxt)))], c, ptp))
561 | by_tactic (Tactic.Check_Postcond' (pI, _)) _ (pt, pos as (p, _)) =
563 val (ist, ctxt) = get_loc pt pos
564 val parent_pos = par_pblobj pt p
565 val {scr, ...} = Specify.get_met (get_obj g_metID pt parent_pos);
567 case find_next_step scr (pt, pos) ist ctxt of
568 Next_Step (_, _, Tactic.Check_elementwise' (_, _, (prog_res, _))) => prog_res
569 | End_Program (_, Tactic.Check_Postcond' (_, (prog_res, _))) => prog_res
570 | _ => raise ERROR ("Step_Solve.by_tactic Check_Postcond " ^ strs2str' pI)
571 val asm = (*?!? Rfun,Rrls rm case*)(case get_obj g_tac pt p of
572 Tactic.Check_elementwise _ => (snd o (get_obj g_result pt)) p
573 | _ => get_assumptions_ pt pos)
575 val tac = Tactic.Check_Postcond' (pI, (prog_res, asm))
580 val is = Pstate (ist |> the_pstate |> set_act prog_res |> set_found)
581 val ((p, p_), ps, _, pt) = Generate.generate1 tac (is, ctxt) (pt, (parent_pos, Res))
583 ("ok", ([(Tactic.Check_Postcond pI, tac, ((parent_pos, Res), (is, ctxt)))], ps, (pt, (p, p_))))
586 let (*resume program of parent PblObj, transfer value of Subproblem-program*)
587 val (ist_parent, ctxt_parent) = case get_loc pt (parent_pos, Frm) of
588 (Pstate i, c) => (i, c)
589 | _ => error "LI.by_tactic Check_Postcond': uncovered case get_loc"
590 val ctxt' = ContextC.from_subpbl_to_caller ctxt prog_res ctxt_parent
591 val is' = Pstate (ist_parent |> set_act prog_res |> set_found)
592 val ((p, p_), ps, _, pt) = Generate.generate1 tac (is', ctxt') (pt, (parent_pos, Res))
594 ("ok", ([(Tactic.Check_Postcond pI, tac, ((parent_pos, Res), (is', ctxt')))], ps, (pt, (p, p_))))
597 | by_tactic (Tactic.End_Proof'') _ ptp = ("end-of-calculation", ([], [], ptp))
598 | by_tactic tac_ is (pt, pos) =
600 val pos = next_in_prog' pos
601 val (pos', c, _, pt) = Generate.generate1 tac_ is (pt, pos);
603 ("ok", ([(Tactic.input_from_T tac_, tac_, (pos, is))], c, (pt, pos')))
605 (*find_next_step from program, by_tactic will update Ctree*)
606 and do_next (ptp as (pt, pos as (p, p_))) =
607 if Celem.e_metID = get_obj g_metID pt (par_pblobj pt p)
608 then ("helpless", ([], [], (pt, (p, p_))))
611 val thy' = get_obj g_domID pt (par_pblobj pt p);
612 val ((ist, ctxt), sc) = LItool.resume_prog thy' (p,p_) pt;
614 case find_next_step sc (pt, pos) ist ctxt of
615 Next_Step (ist, ctxt, tac) =>
616 by_tactic tac (ist, Tactic.insert_assumptions tac ctxt) ptp
617 | End_Program (ist, tac) =>
619 Tactic.End_Detail' res =>
620 ("ok", ([(Tactic.End_Detail,
621 Tactic.End_Detail' res, (pos, (ist, ctxt)))], [], ptp))
622 | _ => by_tactic tac (ist, ctxt) ptp
624 | Helpless => ("helpless", Chead.e_calcstate')
628 compare inform with ctree.form at current pos by nrls;
629 if found, embed the derivation generated during comparison
630 if not, let the mat-engine compute the next ctree.form.
632 Code's structure is copied from complete_solve
633 CAUTION: tacis in returned calcstate' do NOT construct resulting ptp --
634 all_modspec etc. has to be inserted at Subproblem'
636 fun compare_step (tacis, c, ptp as (pt, pos as (p, p_))) ifo =
640 Pos.Frm => Ctree.get_obj Ctree.g_form pt p
641 | Pos.Res => (fst o (Ctree.get_obj Ctree.g_result pt)) p
642 | _ => Rule.e_term (*on PblObj is fo <> ifo*);
643 val {nrls, ...} = Specify.get_met (Ctree.get_obj Ctree.g_metID pt (Ctree.par_pblobj pt p))
644 val {rew_ord, erls, rules, ...} = Rule.rep_rls nrls
645 val (found, der) = Error_Pattern.concat_deriv rew_ord erls rules fo ifo; (*<---------------*)
650 val tacis' = map (Error_Pattern.mk_tacis rew_ord erls) der;
651 val (c', ptp) = Generate.embed_deriv tacis' ptp;
652 in ("ok", (tacis (*@ tacis'?WN050408*), c @ c', ptp)) end
654 if pos = ([], Pos.Res) (*TODO: we should stop earlier with trying subproblems *)
655 then ("no derivation found", (tacis, c, ptp): Chead.calcstate')
658 val msg_cs' as (_, (tacis, c', ptp)) = do_next ptp; (*<---------------------*)
659 val (_, (tacis, c'', ptp)) = case tacis of
660 ((Tactic.Subproblem _, _, _) :: _) =>
662 val ptp as (pt, (p, _)) = Chead.all_modspec ptp (*<--------------------*)
663 val mI = Ctree.get_obj Ctree.g_metID pt p
665 by_tactic (Tactic.Apply_Method' (mI, NONE, e_istate, ContextC.e_ctxt))
666 (e_istate, ContextC.e_ctxt) ptp
669 in compare_step (tacis, c @ c' @ c'', ptp) ifo end
673 handle a user-input formula, which may be a CAS-command, too.
674 * CAS-command: create a calchead, and do 1 step
675 * formula, which is no CAS-command:
676 compare iform with calc-tree.form at pos by equ_nrls and all subsequent pos;
677 collect all the Prog_Tac applied by the way; ...???TODO?
678 If "no derivation found" then check_error_patterns.
679 ALTERNATIVE: check_error_patterns _within_ compare_step: seems too expensive
681 fun locate_input_term (pt, pos) tm =
683 val pos_pred = Pos.lev_back' pos (*f_pred ---"step pos cs"---> f_succ in appendFormula*)
684 val _(*f_pred*) = Ctree.get_curr_formula (pt, pos_pred)
686 case compare_step ([], [], (pt, pos_pred)) tm of
687 ("no derivation found", _) => Not_Derivable
688 | ("ok", (_, _, cstate)) =>
690 | _ => raise ERROR "compare_step: uncovered case"