src/Tools/isac/Interpret/lucas-interpreter.sml
author Walther Neuper <walther.neuper@jku.at>
Tue, 24 Mar 2020 17:01:02 +0100
changeset 59836 f2dc395da0ff
parent 59833 9331e61f55dd
child 59837 efb749b79361
permissions -rw-r--r--
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
     4 *)
     5 
     6 signature LUCAS_INTERPRETER =
     7 sig
     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
    12     -> next_step_result
    13 
    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
    20 
    21   datatype input_term_result = Found_Step of Calc.T | Not_Derivable (**)
    22   val locate_input_term: Calc.T -> term -> input_term_result (**)
    23                         
    24   (* must reside here:
    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'
    27    *)
    28   val by_tactic: Tactic.T -> Istate.T * Proof.context -> Calc.T -> string * Chead.calcstate'
    29   val do_next: Calc.T -> string * Chead.calcstate'
    30 
    31 (* ---- for tests only: shifted from below to remove the Warning "unused" at fun.def. --------- *)
    32   datatype expr_val1 =
    33       Accept_Tac1 of Istate.pstate * Proof.context * Tactic.T
    34     | Reject_Tac1 of Istate.pstate * Proof.context * Tactic.T
    35     | Term_Val1 of term;
    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
    41 
    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'
    50 
    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
    55 
    56   val check_tac1: Calc.T * Proof.context * Tactic.T -> Istate.pstate -> term * term option -> expr_val1
    57 ( *\--- ! aktivate for Test_Isac END ----------------------------------------------------------/*)
    58 end
    59 
    60 (**)
    61 structure LI(**): LUCAS_INTERPRETER(**) =
    62 struct
    63 (**)
    64 open Ctree
    65 open Pos
    66 open TermC
    67 open Istate
    68 
    69 (*** auxiliary functions ***)
    70 
    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);
    76 
    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 ^ "\"")
    85 
    86 
    87 (*** determine a next tactic within a program ***)
    88 
    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*)
    91 
    92 (** scan to a Prog_Tac **)
    93 
    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               *)
   102 
   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) =
   105   let
   106     val m = LItool.tac_from_prog pt (Proof_Context.theory_of ctxt) prog_tac
   107   in
   108     case m of
   109       Tactic.Subproblem _ => (*might involve problem refinement etc*)
   110         let
   111           val m' = snd (Sub_Problem.tac_from_prog pt prog_tac)
   112         in
   113           Accept_Tac (m', ist |> set_subst_found (form_arg, Tactic.result m'), ctxt)
   114         end
   115     | _ =>
   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)
   120       | _ => Reject_Tac)
   121   end
   122 
   123 
   124 (*
   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.
   130 *)
   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)
   139 
   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
   144 
   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)
   153 
   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)
   158 
   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
   167 
   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)
   176 
   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
   181 
   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])
   185     else
   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)
   190 
   191 fun go_scan_up (pcc as (sc, _)) (ist as {path, act_arg, found_accept, ...}) = 
   192     if path = [R] (*root of the program body*)
   193     then
   194       if found_accept
   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
   201 
   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))
   212 
   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*), _) $ _) =
   216       let 
   217         val e2 = check_Seq_up ist sc
   218       in
   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)
   223       end
   224 
   225   | scan_up (pcc as (sc, cc)) ist (Const ("HOL.Let"(*1*), _) $ _) =
   226 	    let
   227         val (i, body) = check_Let_up ist sc
   228       in
   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)
   233 	    end
   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
   236 
   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) 
   240     then
   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)
   245     else
   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) 
   250     then
   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)
   255     else
   256       go_scan_up pcc ist
   257 
   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
   261 
   262   | scan_up pcc ist (Const ("Tactical.If"(*1*), _) $ _ $ _ $ _) = go_scan_up pcc ist
   263 
   264   | scan_up _ _ t = error ("scan_up not impl for " ^ Rule.term2str t)
   265 
   266 (* scan program until an applicable tactic is found *)
   267 fun scan_to_tactic (prog, cc) (Pstate (ist as {path, ...})) =
   268   if 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";
   272 
   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
   280           (true, p', _) => 
   281             let
   282               val (_, pblID, _) = get_obj g_spec pt p';
   283             in
   284               End_Program (Pstate ist, Tactic.Check_Postcond' (pblID, (prog_result, [(*???*)])))
   285             end
   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);
   290 
   291 
   292 (*** locate an input tactic within a program ***)
   293 
   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
   298 
   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";
   312 
   313 
   314 (** check a Prog_Tac: is it associated to Tactic ? **)
   315 
   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)
   323     | LItool.NotAss =>
   324       (case or of (* switch for Tactical.Or: 1st AssOnly, 2nd AssGen *)
   325          AssOnly => Term_Val1 act_arg
   326        | _(*ORundef*) =>
   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)
   330 
   331 (** scan to a Prog_Tac **)
   332 
   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)
   338 
   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
   343 
   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
   349      | goback => goback)
   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
   355      | goback => goback)
   356 
   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
   361      | Term_Val1 v =>
   362          scan_dn1 cct (ist |> path_down [R, D] |> upd_env'' (TermC.mk_Free (id, T), v)) b
   363      | goback => goback)
   364 
   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
   375 
   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
   378 	     Term_Val1 v =>
   379 	       (case scan_dn1 cct (ist |> path_down [L, R] |> set_subst' (a, v) |> set_or AssOnly) e2 of
   380 	          Term_Val1 v => 
   381 	            (case scan_dn1 cct (ist |> path_down [L, L, R] |> upd_env'' (a, v) |> set_or AssGen) e1 of
   382 	               Term_Val1 v => 
   383 	                 scan_dn1 cct (ist |> path_down [L, R] |> upd_env'' (a, v) |> set_or AssGen) e2
   384 	             | goback => goback)
   385 	        | goback => goback)
   386      | Reject_Tac1 _ => raise ERROR ("scan_dn1 Tactical.Or(*1*): must not return Reject_Tac1")
   387      | goback => goback)
   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
   391      | goback => goback)
   392 
   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
   397 
   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])
   400     else
   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)
   407 
   408 fun go_scan_up1 (pcct as (prog, _)) (ist as {path, act_arg, ...}) =
   409     if 1 < length path
   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
   415 
   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
   420     | goback => goback)
   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
   425      | goback => goback)
   426 
   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*), _) $ _ ) =
   431      let 
   432        val e2 = check_Seq_up ist prog (*comes from e1, goes to e2*)
   433      in
   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'
   437        | goback => goback 
   438      end
   439 
   440   | scan_up1 (pcct as (prog, cct as (cstate, _, _))) ist (Const ("HOL.Let"(*1*), _) $ _) =
   441     let 
   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) 
   447 	  end
   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
   450 
   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)
   454     then
   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)
   457 
   458       | Reject_Tac1 (ist', ctxt', tac') => scan_up1 (prog, (cstate, ctxt', tac')) ist' t
   459       | goback => goback
   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)
   464     then
   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
   468        | goback => goback
   469     else go_scan_up1 pcct ist
   470 
   471   | scan_up1 pcct ist (Const ("If", _) $ _ $ _ $ _) = go_scan_up1 pcct ist
   472 
   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)
   476 
   477   | scan_up1 pcct ist (Const ("Tactical.If",_) $ _ $ _ $ _) = go_scan_up1 pcct ist
   478 
   479   | scan_up1 _ _ t = error ("scan_up1 not impl for t= " ^ Rule.term2str t)
   480 
   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"
   486 
   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') =>
   491           if assoc
   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"
   497 
   498 
   499 (*** locate an input formula within a program ***)
   500 
   501 datatype input_term_result = Found_Step of Calc.T | Not_Derivable
   502 
   503 fun by_tactic (Tactic.Apply_Method' (mI, _, _, _)) (_, ctxt) (pt, pos as (p, _)) =
   504 (*OLD*)let
   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;
   517  (*OLD*)in 
   518  (*OLD*)  case ini of
   519  (*OLD*)    SOME t =>
   520  (*OLD*)    let
   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 *)
   524  (*OLD*)    in
   525  (*OLD*)     ("ok", ([(Tactic.Apply_Method mI, tac_, (pos, (is, ctxt)))], c, (pt, pos)))
   526  (*OLD*)    end
   527  (*OLD*)  | NONE =>
   528 (*OLD*)    let
   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)
   533 (*NEW*)    in
   534 (*NEW*)      case tac' of
   535 (*NEW*)        Tactic.Take' t =>
   536 (*NEW*)          let
   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 *)
   540 (*NEW*)          in
   541 (*NEW*)           ("ok", ([(Tactic.Apply_Method mI, tac_, (pos, (is, ctxt)))], c, (pt, pos)))
   542 (*NEW*)          end
   543 (*NEW*)      | tac as Tactic.Subproblem' (_, _, headline, _, _, _) =>
   544 (*NEW*)          let
   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 *)
   548 (*NEW*)            (**)
   549 (*NEW*)          in
   550 (*NEW*)           ("ok", ([(Tactic.Apply_Method mI, tac_, (pos, (ist', ctxt')))], c, (pt, pos)))
   551 (*NEW*)          end
   552 (*NEW*)      | tac =>
   553 (*NEW*)          raise ERROR ("LI.by_tactic..Apply_Method' does NOT expect " ^ Tactic.string_of tac)
   554 (*NEW*)    end
   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))
   559 (*OLD*)    end
   560 (*OLD*)end
   561   | by_tactic (Tactic.Check_Postcond' (pI, _)) _ (pt, pos as (p, _))  =
   562     let
   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);
   566       val prog_res =
   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)
   574 
   575 	    val tac = Tactic.Check_Postcond' (pI, (prog_res, asm))
   576     in
   577       if parent_pos = []
   578       then 
   579 	      let
   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))
   582 	      in
   583 	        ("ok", ([(Tactic.Check_Postcond pI, tac, ((parent_pos, Res), (is, ctxt)))], ps, (pt, (p, p_))))
   584 	      end
   585       else
   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))
   593         in
   594           ("ok", ([(Tactic.Check_Postcond pI, tac, ((parent_pos, Res), (is', ctxt')))], ps, (pt, (p, p_))))
   595         end
   596     end
   597   | by_tactic (Tactic.End_Proof'') _ ptp = ("end-of-calculation", ([], [], ptp))
   598   | by_tactic tac_ is (pt, pos) =
   599     let
   600       val pos = next_in_prog' pos
   601  	    val (pos', c, _, pt) = Generate.generate1 tac_ is (pt, pos);
   602     in
   603       ("ok", ([(Tactic.input_from_T tac_, tac_, (pos, is))], c, (pt, pos')))
   604     end
   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_))))
   609     else 
   610       let 
   611         val thy' = get_obj g_domID pt (par_pblobj pt p);
   612 	      val ((ist, ctxt), sc) = LItool.resume_prog thy' (p,p_) pt;
   613       in
   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) =>
   618              (case tac of
   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
   623              )
   624          | Helpless => ("helpless", Chead.e_calcstate')
   625       end;
   626 
   627 (*
   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.
   631 
   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'
   635 *)
   636 fun compare_step (tacis, c, ptp as (pt, pos as (p, p_))) ifo =
   637   let
   638     val fo =
   639       case p_ of
   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; (*<---------------*)
   646   in
   647     if found
   648     then
   649        let
   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
   653      else 
   654 	     if pos = ([], Pos.Res) (*TODO: we should stop earlier with trying subproblems *)
   655 	     then ("no derivation found", (tacis, c, ptp): Chead.calcstate') 
   656 	     else
   657          let
   658            val msg_cs' as (_, (tacis, c', ptp)) = do_next ptp; (*<---------------------*)
   659 		       val (_, (tacis, c'', ptp)) = case tacis of
   660 			       ((Tactic.Subproblem _, _, _) :: _) => 
   661 			         let
   662                  val ptp as (pt, (p, _)) = Chead.all_modspec ptp (*<--------------------*)
   663 				         val mI = Ctree.get_obj Ctree.g_metID pt p
   664 			         in
   665 			           by_tactic (Tactic.Apply_Method' (mI, NONE, e_istate, ContextC.e_ctxt))
   666 			             (e_istate, ContextC.e_ctxt) ptp
   667                end
   668 			     | _ => msg_cs';
   669 		     in compare_step (tacis, c @ c' @ c'', ptp) ifo end
   670   end
   671 
   672 (*
   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
   680 *)
   681 fun locate_input_term (pt, pos) tm =
   682      let                                                          
   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)
   685      in
   686    		case compare_step ([], [], (pt, pos_pred)) tm of
   687    		  ("no derivation found", _) => Not_Derivable
   688        | ("ok", (_, _, cstate)) => 
   689            Found_Step cstate
   690        | _ => raise ERROR "compare_step: uncovered case"
   691      end
   692 
   693 (**)end(**)