src/Tools/isac/Interpret/lucas-interpreter.sml
author Walther Neuper <walther.neuper@jku.at>
Thu, 21 Nov 2019 15:31:32 +0100
changeset 59717 cc83c55e1c1c
parent 59716 190d4d8433ab
child 59718 bc4b000caa39
permissions -rw-r--r--
lucin: shift datatype, rename
     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 input_tactic_result =
     9       Safe_Step of Istate.T * Proof.context * Tactic.T
    10     | Unsafe_Step of Istate.T * Proof.context * Tactic.T
    11     | Not_Locatable of string
    12   val locate_input_tactic : Rule.program -> Ctree.state -> Istate.T -> Proof.context -> Tactic.T
    13     -> input_tactic_result
    14 
    15 (*datatype input_formula_result = FStep of calcstate' | Not_Derivable *)
    16   datatype input_formula_result =
    17     Step of Ctree.state * Istate.T * Proof.context
    18   | Not_Derivable of Chead.calcstate'
    19 (*val locate_input_formula : Ctree.state -> term -> input_formula_result *)
    20   val locate_input_formula : Rule.program -> Ctree.state -> Istate.T -> Proof.context -> term
    21     -> input_formula_result
    22 (*val begin_end_prog : ???*)
    23   val begin_end_prog : Tactic.T -> Istate.T * Proof.context -> Ctree.state ->
    24     (Tactic.input * Tactic.T * (Ctree.pos' * (Istate.T * Proof.context))) list * Ctree.pos' list * Ctree.state
    25 (*val do_solve_step : Ctree.state -> Ctree.state ???*)
    26   val do_solve_step : Ctree.state ->
    27     (Tactic.input * Tactic.T * (Ctree.pos' * (Istate.T * Proof.context))) list * Ctree.pos' list * Ctree.state
    28 
    29   datatype next_tactic_result =
    30       NStep of Ctree.state * Istate.T * Proof.context * tactic
    31     | Helpless | End_Program
    32 (*val determine_next_tactic :
    33     Rule.program -> Ctree.state -> Istate.T -> Proof.context -> next_tactic_result *)
    34   val determine_next_tactic: Rule.theory' * 'a -> Ctree.state -> Rule.program -> Istate.T * 'b
    35     -> Tactic.T * (Istate.T * Proof.context) * (term * Telem.safe)
    36 
    37 (* ---- for tests only: shifted from below to remove the Warning "unused" at fun.def. --------- *)
    38   datatype expr_val1 =
    39       Ackn_Tac1 of Istate.pstate * Proof.context * Tactic.T
    40     | Reject_Tac1 of Istate.pstate * Proof.context * Tactic.T
    41     | Term_Val1 of term;
    42   val assoc2str : expr_val1 -> string
    43 (*/-------------------------------------------------------- ! aktivate for Test_Isac BEGIN ---\* )
    44   val go : Celem.path -> term -> term
    45   val go_up: Celem.path -> term -> term
    46   val check_Let_up : Istate.pstate -> term -> term * term
    47   val check_Seq_up: Istate.pstate -> term -> term
    48   val compare_step : Generate.taci list * Ctree.pos' list * (Ctree.state) -> term -> string * Chead.calcstate'
    49 
    50   val scan_dn1: (Ctree.state * Proof.context * Tactic.T) -> Istate.pstate -> term -> expr_val1
    51   val scan_up1: term * (Ctree.state * Proof.context * Tactic.T) -> Istate.pstate -> term -> expr_val1;
    52   val go_scan_up1: term * (Ctree.state * Proof.context * Tactic.T) -> Istate.pstate -> expr_val1;
    53   val scan_to_tactic1: term * (Ctree.state * Proof.context * Tactic.T) -> Istate.T -> expr_val1
    54 
    55   datatype expr_val2 = Ackn_Tac2 of Tactic.T * Istate.pstate | Reject_Tac2 | Term_Val2 of term
    56   val scan_dn2: Ctree.state * Rule.theory'(*Proof.context*) -> Istate.pstate -> term -> expr_val2
    57   val scan_up2: term * (Ctree.state * Rule.theory') -> Istate.pstate -> term -> expr_val2
    58   val go_scan_up2: term * (Ctree.state * Rule.theory') -> Istate.pstate -> expr_val2
    59   val scan_to_tactic2: term * (Ctree.state * Rule.theory') -> Istate.T -> expr_val2
    60 ( *\--- ! aktivate for Test_Isac END ----------------------------------------------------------/*)
    61 end
    62 
    63 (**)
    64 structure LucinNEW(**): LUCAS_INTERPRETER(**) = (*LucinNEW \<rightarrow> Lucin after code re-arrangement*)
    65 struct
    66 (**)
    67 open Ctree
    68 open Pos
    69 open Celem
    70 open Istate
    71 
    72 (*** auxiliary functions ***)
    73 
    74 (*go to a location in a program and fetch the resective sub-term*)
    75 fun go [] t = t
    76   | go (D :: p) (Abs(_, _, body)) = go (p : Celem.path) body
    77   | go (L :: p) (t1 $ _) = go p t1
    78   | go (R :: p) (_ $ t2) = go p t2
    79   | go l _ = error ("go: no " ^ Celem.path2str l);
    80 fun go_up l t =
    81   if length l > 1 then go (drop_last l) t else raise ERROR ("go_up [] " ^ Rule.term2str t)
    82 
    83 fun check_Let_up ({path, ...}: pstate) prog =
    84   case go (drop_last path) prog of
    85     Const ("HOL.Let",_) $ _ $ (Abs (i, T, body)) => (TermC.mk_Free (i, T), body)
    86   | t => raise ERROR ("scan_up1..\"HOL.Let $ _\" with: \"" ^ Rule.term2str t ^ "\"")
    87 fun check_Seq_up  ({path, ...}: pstate) prog =
    88   case go (drop_last path) prog of
    89     Const ("Tactical.Chain",_) $ _ $ e2=> e2
    90   | t => raise ERROR ("scan_up1..\"Tactical.Chain $ _\" with: \"" ^ Rule.term2str t ^ "\"")
    91 
    92 
    93 (*** locate an input tactic within a program ***)
    94 
    95 datatype input_tactic_result =
    96     Safe_Step of Istate.T * Proof.context * Tactic.T
    97   | Unsafe_Step of Istate.T * Proof.context * Tactic.T
    98   | Not_Locatable of string
    99 
   100 datatype expr_val1 = (* "ExprVal" in the sense of denotational semantics        *)
   101   Reject_Tac1 of     (* tactic is found but NOT acknowledged, scan is continued *)
   102     Istate.pstate * Proof.context * Tactic.T (*TODO: revise Pstate {or,...},no args as Reject_Tac2*)
   103 | Ackn_Tac1 of       (* tactic is found and acknowledged, scan is stalled       *)
   104     Istate.pstate *  (* the current state, returned for resuming execution      *)
   105     Proof.context *  (* updated according to evaluation of Prog_Tac             *)
   106     Tactic.T         (* Prog_Tac is associated to Tactic.input                  *)
   107 | Term_Val1 of       (* Prog_Expr is found and evaluated, scan is continued     *)
   108 	  term             (* value of Prog_Expr, for updating environment            *)
   109 fun assoc2str (Ackn_Tac1 _) = "Ackn_Tac1"                                         
   110   | assoc2str (Term_Val1 _) = "Term_Val1"
   111   | assoc2str (Reject_Tac1 _) = "Reject_Tac1";
   112 
   113 
   114 (** scan to a Prog_Tac **)
   115 
   116 fun scan_dn1 cct ist (Const ("Tactical.Try"(*1*), _) $ e $ a) =
   117     (case scan_dn1 cct (ist |> path_down_form ([L, R], a)) e of goback => goback) 
   118   | scan_dn1 cct ist (Const ("Tactical.Try"(*2*), _) $ e) =
   119     (case scan_dn1 cct (ist |> path_down [R]) e of goback => goback)
   120 
   121   | scan_dn1 cct ist (Const ("Tactical.Repeat"(*1*), _) $ e $ a) =
   122     scan_dn1 cct (ist |> path_down_form ([L, R], a)) e
   123   | scan_dn1 cct ist (Const ("Tactical.Repeat"(*2*), _) $ e) =
   124     scan_dn1 cct (ist |> path_down [R]) e
   125 
   126   | scan_dn1 (cct as (cstate, _, _)) ist (Const ("Tactical.Chain"(*1*), _) $ e1 $ e2 $ a) =
   127     (case scan_dn1 cct (ist |> path_down_form ([L, L, R], a)) e1 of
   128 	     Term_Val1 v => scan_dn1 cct (ist |> path_down [L, R] |> set_subst' (a, v)) e2
   129      | Reject_Tac1 (ist', ctxt', tac') => scan_dn1 (cstate, ctxt', tac') (ist
   130         |> path_down_form ([L, R], a) |> trans_env_act ist') e2
   131      | goback => goback)
   132   | scan_dn1 (cct as (cstate, _, _)) ist (Const ("Tactical.Chain"(*2*), _) $e1 $ e2) =
   133     (case scan_dn1 cct (ist |> path_down [L, R]) e1 of
   134 	     Term_Val1 v => scan_dn1 cct (ist |> path_down [R] |> set_act v) e2
   135      | Reject_Tac1 (ist', ctxt', tac') =>
   136         scan_dn1 (cstate, ctxt', tac') (ist |> path_down [R] |> trans_env_act ist') e2
   137      | goback => goback)
   138 
   139   | scan_dn1 cct ist (Const ("HOL.Let", _) $ e $ (Abs (id, T, b))) =
   140     (case scan_dn1 cct (ist |> path_down [L, R]) e of
   141        Reject_Tac1 (ist', _, _) =>
   142          scan_dn1 cct (ist' |> path_down [R, D] |> upd_env (TermC.mk_Free (id, T)) |> trans_ass ist) b
   143      | Term_Val1 v =>
   144          scan_dn1 cct (ist |> path_down [R, D] |> upd_env'' (TermC.mk_Free (id, T), v)) b
   145      | goback => goback)
   146 
   147   | scan_dn1 cct (ist as {eval, act_arg, ...}) (Const ("Tactical.While"(*1*), _) $ c $ e $ a) =
   148     if Rewrite.eval_true_ "Isac_Knowledge" eval
   149       (subst_atomic (ist |> get_act_env |> Env.update' a) c)
   150     then scan_dn1 cct (ist |> path_down_form ([L, R], a)) e
   151     else Term_Val1 act_arg
   152   | scan_dn1 cct (ist as {eval, act_arg, ...}) (Const ("Tactical.While"(*2*),_) $ c $ e) =
   153     if Rewrite.eval_true_ "Isac_Knowledge" eval (subst_atomic (Env.update_opt' (get_subst ist)) c) 
   154     then scan_dn1 cct (ist |> path_down [R]) e
   155     else Term_Val1 act_arg
   156 
   157   | scan_dn1 cct (ist as {or = Aundef, ...}) (Const ("Tactical.Or"(*1*), _) $e1 $ e2 $ a) =
   158     (case scan_dn1 cct (ist |> path_down_form ([L, L, R], a) |> set_or AssOnly) e1 of
   159 	     Term_Val1 v =>
   160 	       (case scan_dn1 cct (ist |> path_down [L, R] |> set_subst' (a, v) |> set_or AssOnly) e2 of
   161 	          Term_Val1 v => 
   162 	            (case scan_dn1 cct (ist |> path_down [L, L, R] |> upd_env'' (a, v) |> set_or AssGen) e1 of
   163 	               Term_Val1 v => 
   164 	                 scan_dn1 cct (ist |> path_down [L, R] |> upd_env'' (a, v) |> set_or AssGen) e2
   165 	             | goback => goback)
   166 	        | goback => goback)
   167      | Reject_Tac1 _ => raise ERROR ("scan_dn1 Tactical.Or(*1*): must not return Reject_Tac1")
   168      | goback => goback)
   169   | scan_dn1 cct ist (Const ("Tactical.Or"(*2*), _) $e1 $ e2) =
   170     (case scan_dn1 cct (ist |> path_down [L, R]) e1 of
   171 	     Term_Val1 v => scan_dn1 cct (ist |> path_down [R] |> set_act v) e2
   172      | goback => goback)
   173 
   174   | scan_dn1 cct (ist as {eval, ...}) (Const ("Tactical.If", _) $ c $ e1 $ e2) =
   175     if Rewrite.eval_true_ "Isac_Knowledge" eval (subst_atomic (Env.update_opt' (get_subst ist)) c)
   176     then scan_dn1 cct (ist |> path_down [L, R]) e1
   177     else scan_dn1 cct (ist |> path_down [R]) e2
   178 
   179   | scan_dn1 ((pt, p), ctxt, tac) (ist as {eval, act_arg, or, ...}) t =
   180     if Tactical.contained_in t then raise TERM ("scan_dn1 expects Prog_Tac or Prog_Expr", [t])
   181     else
   182       case Lucin.handle_leaf "locate" (Context.theory_name (Rule.Isac"")) eval (get_subst ist) t of
   183   	     (a', Program.Expr _) => 
   184 (*--------------------------- eval_Prog_Expr -----*)
   185   	       Term_Val1 (Rewrite.eval_listexpr_ (Celem.assoc_thy "Isac_Knowledge") eval
   186   		       (subst_atomic (Env.update_opt'' (get_act_env ist, a')) t))
   187        | (a', Program.Tac stac) =>
   188 (*/------------ interprete_Prog_Tac -----*)
   189            case Lucin.associate pt ctxt (tac, stac) of
   190               (* HERE ----------------vvvv ContextC.insert_assumptions asm ctxt DONE -- 2nd in gen//*)
   191   	           Lucin.Ass      (m, v', ctxt) => Ackn_Tac1 (ist |> set_subst_true  (a', v'), ctxt, m)
   192              | Lucin.Ass_Weak (m, v', ctxt) => Ackn_Tac1 (ist |> set_subst_false (a', v'), ctxt, m)
   193   
   194              | Lucin.NotAss =>
   195                (case or of (* switch for Tactical.Or: 1st AssOnly, 2nd AssGen *)
   196                   AssOnly => Term_Val1 act_arg
   197                 | _(*Aundef*) =>
   198                    case Applicable.applicable_in p pt (Lucin.stac2tac pt (Celem.assoc_thy "Isac_Knowledge") stac) of
   199                       Chead.Appl m' => Reject_Tac1 (ist |> set_subst_false (a', Lucin.tac_2res m'), ctxt, tac)
   200                     | Chead.Notappl _ => Term_Val1 act_arg)
   201 (*------------- interprete_tactic ---//*)
   202       ;
   203 
   204 fun scan_up1 pcct ist (Const ("Tactical.Try"(*1*), _) $ _ $ _) = go_scan_up1 pcct ist
   205   | scan_up1 pcct ist (Const ("Tactical.Try"(*2*), _) $ _) = go_scan_up1 pcct ist
   206 
   207   | scan_up1 (pcct as (prog, cct as (cstate, _, _))) ist (t as Const ("Tactical.Repeat"(*1*), _) $ e $ a) =
   208     (case scan_dn1 cct (ist |> path_down_form ([L, R], a) |> set_or Aundef) e of 
   209       Term_Val1 v => go_scan_up1 pcct (ist |> set_act v |> set_form a)
   210     | Reject_Tac1 (ist', ctxt', tac') => scan_up1 (prog, (cstate, ctxt', tac')) ist' t
   211     | goback => goback)
   212   | scan_up1 (pcct as (prog, cct as (cstate, _, _))) ist (t as Const ("Tactical.Repeat"(*2*), _) $ e) =
   213     (case scan_dn1 cct (ist |> path_down [R] |> set_or Aundef) e of
   214        Term_Val1 v' => go_scan_up1 pcct (ist |> set_act v')
   215      | Reject_Tac1 (ist', ctxt', tac') => scan_up1 (prog, (cstate, ctxt', tac')) ist' t
   216      | goback => goback)
   217 
   218     (*all has been done in (*2*) below*)
   219   | scan_up1 pcct ist (Const ("Tactical.Chain"(*1*), _) $ _ $ _ $ _) = go_scan_up1 pcct ist
   220   | scan_up1 pcct ist (Const ("Tactical.Chain"(*2*), _) $ _ $ _) = go_scan_up1 pcct ist (*comes from e2*)
   221     (*comes from e1, goes to e2*)
   222   | scan_up1 (pcct as (prog, cct as (cstate, _, _))) ist (Const ("Tactical.Chain"(*3*), _) $ _ ) =
   223      let 
   224        val e2 = check_Seq_up ist prog
   225      in
   226        case scan_dn1 cct (ist |> path_up_down [R] |> set_or Aundef) e2 of
   227          Term_Val1 v => go_scan_up1 pcct (ist |> path_up |> set_act v)
   228        | Reject_Tac1 (ist', ctxt', tac') => go_scan_up1 (prog, (cstate, ctxt', tac')) ist'
   229        | goback => goback 
   230      end
   231 
   232   | scan_up1 (pcct as (prog, cct as (cstate, _, _))) ist (Const ("HOL.Let"(*1*), _) $ _) =
   233     let 
   234       val (i, body) = check_Let_up ist prog
   235     in case scan_dn1 cct (ist |> path_up_down [R, D] |> upd_env i |> set_or Aundef) body of
   236 	       Ackn_Tac1 iss => Ackn_Tac1 iss
   237 	     | Reject_Tac1 (ist', ctxt', tac') => go_scan_up1 (prog, (cstate, ctxt', tac')) ist'
   238 	     | Term_Val1 v => go_scan_up1 pcct (ist |> path_up |> set_act v) 
   239 	  end
   240   | scan_up1 pcct ist (Abs(*2*) _) = go_scan_up1 pcct ist
   241   | scan_up1 pcct ist (Const ("HOL.Let"(*3*), _) $ _ $ (Abs _)) = go_scan_up1 pcct ist
   242 
   243   | scan_up1 (pcct as (prog, cct as (cstate, _, _))) (ist as {eval, ...})
   244       (t as Const ("Tactical.While"(*1*),_) $ c $ e $ a) =
   245     if Rewrite.eval_true_ "Isac_Knowledge" eval (subst_atomic (Env.update' a (get_act_env ist)) c)
   246     then
   247       case scan_dn1 cct (ist |> path_down_form ([L, R], a) |> set_or Aundef) e of 
   248         Term_Val1 v => go_scan_up1 pcct (ist |> set_act v |> set_form a)
   249 
   250       | Reject_Tac1 (ist', ctxt', tac') => scan_up1 (prog, (cstate, ctxt', tac')) ist' t
   251       | goback => goback
   252     else go_scan_up1 pcct (ist |> set_form a)
   253   | scan_up1 (pcct as (prog, cct as (cstate, _, _))) (ist as {eval, ...})
   254       (t as Const ("Tactical.While"(*2*), _) $ c $ e) =
   255     if Rewrite.eval_true_ "Isac_Knowledge" eval (subst_atomic (Env.update_opt' (get_subst ist)) c)
   256     then
   257       case scan_dn1 cct (ist |> path_down [R] |> set_or Aundef) e of 
   258         Term_Val1 v => go_scan_up1 pcct (ist |> set_act v)
   259        | Reject_Tac1 (ist', ctxt', tac') => scan_up1 (prog, (cstate, ctxt', tac')) ist' t
   260        | goback => goback
   261     else go_scan_up1 pcct ist
   262 
   263   | scan_up1 pcct ist (Const ("If", _) $ _ $ _ $ _) = go_scan_up1 pcct ist
   264 
   265   | scan_up1 pcct ist (Const ("Tactical.Or"(*1*), _) $ _ $ _ $ _) = go_scan_up1 pcct ist
   266   | scan_up1 pcct ist (Const ("Tactical.Or"(*2*), _) $ _ $ _) = go_scan_up1 pcct ist
   267   | scan_up1 pcct ist (Const ("Tactical.Or"(*3*), _) $ _ ) = go_scan_up1 pcct (ist |> path_up)
   268 
   269   | scan_up1 pcct ist (Const ("Tactical.If",_) $ _ $ _ $ _) = go_scan_up1 pcct ist
   270 
   271   | scan_up1 _ _ t = error ("scan_up1 not impl for t= " ^ Rule.term2str t)
   272 and go_scan_up1 (pcct as (prog, _)) (ist as {path, act_arg, ...}) =
   273     if 1 < length path
   274     then scan_up1 pcct (ist |> path_up) (go (path_up' path) prog)
   275     else Term_Val1 act_arg
   276 
   277 fun scan_to_tactic1 (prog, (cctt as ((_, p), _, _))) (Istate.Pstate (ist as {path, ...})) =
   278     if path = [] orelse Pos.at_first_tactic(*RM prog path RM WITH determine_next_tactic IN solve*)p
   279     then scan_dn1 cctt (ist |> set_path [R] |> set_or Aundef) (Program.body_of prog)
   280     else go_scan_up1 (prog, cctt) ist
   281   | scan_to_tactic1 _ _ = raise ERROR "scan_to_tactic1: uncovered pattern in fun.def"
   282 
   283 (*locate an input tactic within a program*)
   284 fun locate_input_tactic (Rule.Prog prog) cstate istate ctxt tac =
   285     (case scan_to_tactic1 (prog, (cstate, ctxt, tac)) istate of
   286          Ackn_Tac1 ((ist as {assoc, ...}), ctxt, tac') =>
   287           if assoc
   288           then Safe_Step (Istate.Pstate ist, ctxt, tac')
   289  	        else Unsafe_Step (Istate.Pstate ist, ctxt, tac')
   290       | Reject_Tac1 _ => Not_Locatable (Tactic.tac_2str tac ^ " not locatable")
   291       | err => raise ERROR ("not-found-in-script: NotLocatable from " ^ @{make_string} err))
   292   | locate_input_tactic _ _ _ _ _ = raise ERROR "locate_input_tactic: uncovered case in definition"
   293 
   294 
   295 (*** determine a next tactic by executing the program ***)
   296 
   297   datatype next_tactic_result = NStep of Ctree.state * Istate.T * Proof.context * tactic
   298     | Helpless | End_Program
   299 
   300 (** scan to a Prog_Tac **)
   301 
   302 datatype expr_val2 = (* "ExprVal" in the sense of denotational semantics        *)
   303   Reject_Tac2        (* tactic is found but NOT acknowledged, scan is continued *)
   304 | Ackn_Tac2 of       (* tactic is found and acknowledged, scan is stalled       *)
   305     Tactic.T *       (* Prog_Tac is applicable_in cstate                        *)
   306     Istate.pstate    (* the current state, returned for resuming execution      *)
   307 | Term_Val2 of       (* Prog_Expr is found and evaluated, scan is continued     *)
   308     term;            (* value of Prog_Expr, for updating environment            *)
   309 
   310 (*
   311   scan_dn2, go_scan_up2, scan_up2 scan for determine_next_tactic.
   312   (1) scan_dn2 is recursive descent;
   313   (2) go_scan_up2 goes to the parent node and calls (3);
   314   (3) scan_up2 resumes according to the interpreter-state.
   315   Call of (2) means that there was an applicable Prog_Tac below
   316 *)
   317 fun scan_dn2 cc (ist as {act_arg, ...}) (Const ("Tactical.Try"(*1*), _) $ e $ a) =
   318     (case scan_dn2 cc (ist|> path_down_form ([L, R], a)) e of
   319       Reject_Tac2 => Term_Val2 act_arg
   320     | goback => goback)
   321   | scan_dn2 cc (ist as {act_arg, ...}) (Const ("Tactical.Try"(*2*), _) $ e) =
   322     (case scan_dn2 cc (ist |> path_down [R]) e of
   323       Reject_Tac2 => Term_Val2 act_arg
   324     | goback => goback)
   325 
   326   | scan_dn2 cc ist (Const ("Tactical.Repeat"(*1*), _) $ e $ a) = 
   327     scan_dn2 cc (ist |> path_down_form ([L, R], a)) e
   328   | scan_dn2 cc ist (Const ("Tactical.Repeat"(*2*), _) $ e) =
   329     scan_dn2 cc (ist |> path_down [R]) e
   330 
   331   | scan_dn2 cc ist (Const ("Tactical.Chain"(*1*), _) $ e1 $ e2 $ a) =
   332     (case scan_dn2 cc (ist |> path_down_form ([L, L, R], a)) e1 of
   333 	    Term_Val2 v => scan_dn2 cc (ist |> path_down_form ([L, R], a) |> set_act v) e2 (*UPD*)
   334     | goback => goback)
   335   | scan_dn2 cc ist (Const ("Tactical.Chain"(*2*), _) $ e1 $ e2) =
   336     (case scan_dn2 cc (ist |> path_down [L, R]) e1 of
   337 	    Term_Val2 v => scan_dn2 cc (ist |> path_down [R] |> set_act v) e2
   338     | goback => goback)
   339 
   340   | scan_dn2 cc ist (Const ("HOL.Let"(*1*), _) $ e $ (Abs (i, T, b))) =
   341      (case scan_dn2 cc (ist |> path_down [L, R]) e of
   342        Term_Val2 res => scan_dn2 cc (ist |> path_down [R, D] |> upd_env'' (Free (i, T), res)) b
   343      | goback => goback)
   344 
   345   | scan_dn2 (cc as (_, ctxt)) (ist as {eval, act_arg, ...}) (Const ("Tactical.While"(*1*), _) $ c $ e $ a) =
   346     if Rewrite.eval_true_ ctxt eval (subst_atomic (ist |> get_act_env |> Env.update' a) c)
   347     then scan_dn2 cc (ist |> path_down_form ([L, R], a)) e
   348     else Term_Val2 act_arg
   349   | scan_dn2 (cc as (_, ctxt)) (ist as {eval, act_arg, ...}) (Const ("Tactical.While"(*2*), _) $ c $ e) =
   350     if Rewrite.eval_true_ ctxt eval (subst_atomic (Env.update_opt' (get_subst ist)) c)
   351     then scan_dn2 cc (ist |> path_down [R]) e
   352     else Term_Val2 act_arg
   353 
   354   |scan_dn2 cc ist (Const ("Tactical.Or"(*1*), _) $e1 $ e2 $ a) =
   355     (case scan_dn2 cc (ist |> path_down_form ([L, L, R], a)) e1 of
   356 	    Ackn_Tac2 lme => Ackn_Tac2 lme
   357     | _ => scan_dn2 cc (ist |> path_down_form ([L, R], a)) e2)
   358   | scan_dn2 cc ist (Const ("Tactical.Or"(*2*), _) $e1 $ e2) =
   359     (case scan_dn2 cc (ist |> path_down [L, R]) e1 of
   360 	    Ackn_Tac2 lme => Ackn_Tac2 lme
   361     | _ => scan_dn2 cc (ist |> path_down [R]) e2)
   362 
   363   |  scan_dn2 (cc as (_, ctxt)) (ist as {eval, ...}) (Const ("Tactical.If"(*1*), _) $ c $ e1 $ e2) =
   364     if Rewrite.eval_true_ ctxt eval (subst_atomic (Env.update_opt' (get_subst ist)) c)
   365     then scan_dn2 cc (ist |> path_down [L, R]) e1
   366     else scan_dn2 cc (ist |> path_down [R]) e2
   367 
   368   | scan_dn2 ((pt, p), ctxt) (ist as {eval, ...}) t =
   369     if Tactical.contained_in t then raise TERM ("scan_dn2 expects Prog_Tac or Prog_Expr", [t])
   370     else
   371       case Lucin.handle_leaf "next  " ctxt eval (get_subst ist) t of
   372   	    (_, Program.Expr s) => Term_Val2 s
   373       | (a', Program.Tac stac) =>
   374   	    let
   375   	      val (m, m') = Lucin.stac2tac_ pt (Celem.assoc_thy ctxt) stac
   376         in
   377           case m of (*TODO?: make applicable_in..Subproblem analogous to other tacs ?refine problem?*)
   378     	      Tactic.Subproblem _ => Ackn_Tac2 (m', ist |> set_subst_reset (a', Lucin.tac_2res m'))
   379     	    | _ =>
   380             (case Applicable.applicable_in p pt m of
   381     		      Chead.Appl m' => Ackn_Tac2 (m', ist |> set_subst_reset (a', Lucin.tac_2res m'))
   382     		    | _ => Reject_Tac2)
   383   	    end
   384 
   385     (*makes Reject_Tac2 to Term_Val2*)
   386 fun scan_up2 pcc ist (Const ("Tactical.Try"(*1*), _) $ _ $ _) = go_scan_up2 pcc (ist |> set_appy Skip_)
   387   | scan_up2 pcc ist (Const ("Tactical.Try"(*2*), _) $ _) = go_scan_up2 pcc (ist |> set_appy Skip_)
   388 
   389   | scan_up2 (pcc as (_, cc)) ist (Const ("Tactical.Repeat"(*1*), _) $ e $ _) =
   390     (case scan_dn2 cc (ist |> path_down [L, R]) e of (* no appy_: there was already a stac below *)
   391       Ackn_Tac2 lr => Ackn_Tac2 lr
   392     | Reject_Tac2 =>  go_scan_up2 pcc (ist |> set_appy Skip_)
   393     | Term_Val2 v =>  go_scan_up2 pcc (ist |> set_act v |> set_appy Skip_))
   394     (*no appy_: there was already a stac below*)
   395   | scan_up2  (pcc as (_, cc)) ist (Const ("Tactical.Repeat"(*2*), _) $ e) =
   396     (case scan_dn2 cc (ist |> path_down [R]) e of
   397       Ackn_Tac2 lr => Ackn_Tac2 lr
   398     | Reject_Tac2 => go_scan_up2 pcc (ist |> set_appy Skip_)
   399     | Term_Val2 v => go_scan_up2 pcc (ist |> set_act v |> set_appy Skip_))
   400 
   401   | scan_up2 pcc ist (Const ("Tactical.Chain"(*1*), _) $ _ $ _ $ _) = go_scan_up2 pcc ist
   402   | scan_up2 pcc ist (Const ("Tactical.Chain"(*2*), _) $ _ $ _) = go_scan_up2 pcc ist
   403   | scan_up2 (pcc as (sc, cc)) (ist as {finish, ...}) (Const ("Tactical.Chain"(*3*), _) $ _) =
   404     if finish = Napp_
   405     then go_scan_up2 pcc (ist |> path_up)
   406     else (*Skip_*)
   407       let 
   408         val e2 = check_Seq_up ist sc
   409       in
   410         case scan_dn2 cc (ist |> path_up_down [R]) e2 of
   411           Ackn_Tac2 lr => Ackn_Tac2 lr
   412         | Reject_Tac2 => go_scan_up2 pcc (ist |> path_up)
   413         | Term_Val2 v => go_scan_up2 pcc (ist |> path_up |> set_act v |> set_appy Skip_)
   414       end
   415 
   416   | scan_up2 (pcc as (sc, cc)) (ist as {finish, ...}) (Const ("HOL.Let"(*1*), _) $ _) =
   417     if finish = Napp_
   418     then go_scan_up2 pcc (ist |> path_up)
   419     else (*Skip_*)
   420 	    let
   421         val (i, body) = check_Let_up ist sc
   422       in
   423         case scan_dn2 cc (ist |> path_up_down [R, D] |> upd_env i) body of
   424 	        Ackn_Tac2 lre => Ackn_Tac2 lre
   425 	      | Reject_Tac2 => go_scan_up2 pcc (ist |> path_up)
   426 	      | Term_Val2 v => go_scan_up2 pcc (ist |> path_up |> set_act v |> set_appy Skip_)
   427 	    end
   428   | scan_up2 pcc ist (Abs _(*2*)) =  go_scan_up2 pcc ist
   429   | scan_up2 pcc ist (Const ("HOL.Let"(*3*),_) $ _ $ (Abs _)) =
   430     go_scan_up2 pcc ist
   431 
   432     (*no appy_: never causes Reject_Tac2 -> Helpless*)
   433   | scan_up2 (pcc as (_, cc as (_, ctxt)))  (ist as {eval, ...}) (Const ("Tactical.While"(*1*), _) $ c $ e $ _) = 
   434     if Rewrite.eval_true_ ctxt eval (subst_atomic (Env.update_opt' (get_subst ist)) c) 
   435     then
   436       case scan_dn2 cc (ist |> path_down [L, R]) e of
   437   	     Ackn_Tac2 lr => Ackn_Tac2 lr
   438   	  | Reject_Tac2 => go_scan_up2 pcc (ist |> set_appy Skip_)
   439   	  | Term_Val2 v => go_scan_up2 pcc (ist |> set_act v |> set_appy Skip_)
   440     else
   441       go_scan_up2 pcc (ist |> set_appy Skip_)
   442     (*no appy_: never causes Reject_Tac2 - Helpless*)
   443   | scan_up2  (pcc as (_, cc as (_, ctxt))) (ist as {eval, ...}) (Const ("Tactical.While"(*2*), _) $ c $ e) = 
   444     if Rewrite.eval_true_ ctxt eval (subst_atomic (Env.update_opt' (get_subst ist)) c) 
   445     then
   446       case scan_dn2 cc (ist |> path_down [R]) e of
   447   	    Ackn_Tac2 lr => Ackn_Tac2 lr
   448   	  | Reject_Tac2 => go_scan_up2 pcc (ist |> set_appy Skip_)
   449   	  | Term_Val2 v => go_scan_up2 pcc (ist |> set_act v |> set_appy Skip_)
   450     else
   451       go_scan_up2 pcc (ist |> set_appy Skip_)
   452 
   453   | scan_up2 pcc ist (Const ("Tactical.Or"(*1*), _) $ _ $ _ $ _) = go_scan_up2 pcc ist
   454   | scan_up2 pcc ist (Const ("Tactical.Or"(*2*), _) $ _ $ _) = go_scan_up2 pcc ist
   455   | scan_up2 pcc ist (Const ("Tactical.Or"(*3*), _) $ _ ) = go_scan_up2 pcc ist
   456 
   457   | scan_up2 pcc ist (Const ("Tactical.If"(*1*), _) $ _ $ _ $ _) = go_scan_up2 pcc ist
   458 
   459   | scan_up2 _ _ t = error ("scan_up2 not impl for " ^ Rule.term2str t)
   460 and go_scan_up2 (pcc as (sc, _)) (ist as {path, act_arg, finish, ...}) = 
   461     if 1 < length path
   462     then 
   463       scan_up2 pcc (ist |> path_up) (go_up path sc)
   464     else (*interpreted to end*)
   465       if finish = Skip_ then Term_Val2 act_arg else Reject_Tac2
   466 
   467 fun scan_to_tactic2 (prog, cc) (Istate.Pstate (ist as {path, ...})) =
   468   if path = []
   469   then scan_dn2 cc (trans_scan_down2 ist) (Program.body_of prog)
   470   else go_scan_up2 (prog, cc) (trans_scan_up2 ist |> set_appy Skip_)
   471 | scan_to_tactic2 _ _ = raise ERROR "scan_to_tactic2: uncovered pattern";
   472 
   473 (*decide for the next applicable Prog_Tac*)
   474 fun determine_next_tactic (thy, _) (ptp as (pt, (p, _))) (Rule.Prog prog) (Istate.Pstate ist, _(*ctxt*)) =
   475    (case scan_to_tactic2 (prog, (ptp, thy)) (Istate.Pstate ist) of
   476       Term_Val2 v =>                                                        (* program finished *)
   477         (case par_pbl_det pt p of
   478 	        (true, p', _) => 
   479 	          let
   480 	            val (_, pblID, _) = get_obj g_spec pt p';
   481 	          in
   482               (Tactic.Check_Postcond' (pblID, (v, [(*assigned in next step*)])), 
   483 	              (Istate.e_istate, ContextC.e_ctxt), (v, Telem.Safe)) 
   484             end
   485 	      | _ =>
   486           (Tactic.End_Detail' (Rule.e_term,[])(*8.6.03*), (Istate.e_istate, ContextC.e_ctxt), (v, Telem.Safe)))
   487     | Reject_Tac2 =>
   488         (Tactic.Empty_Tac_, (Istate.e_istate, ContextC.e_ctxt), (Rule.e_term, Telem.Helpless_))(* helpless *)
   489     | Ackn_Tac2 (m', (ist as {act_arg, ...})) =>
   490         (m', (Pstate ist, ContextC.e_ctxt), (act_arg, Telem.Safe)))                  (* found next tac *)
   491   | determine_next_tactic _ _ _ (is, _) =
   492     error ("determine_next_tactic: not impl for " ^ (Istate.istate2str is));
   493 
   494 
   495 (*** locate an input formula in the program ***)
   496 
   497 datatype input_formula_result =
   498     Step of Ctree.state * Istate.T * Proof.context
   499   | Not_Derivable of Chead.calcstate'
   500 
   501 (* FIXME.WN050821 compare fun solve ... fun begin_end_prog
   502    begin_end_prog (Apply_Method'     vvv FIXME: get args in applicable_in *)
   503 fun begin_end_prog (Tactic.Apply_Method' (mI, _, _, ctxt)) _ (pt, pos as (p, _)) =
   504     let
   505       val {ppc, ...} = Specify.get_met mI;
   506       val (itms, oris, probl) = case get_obj I pt p of
   507         PblObj {meth = itms, origin = (oris, _, _), probl, ...} => (itms, oris, probl)
   508       | _ => error "begin_end_prog Apply_Method': uncovered case get_obj"
   509       val itms = if itms <> [] then itms else Chead.complete_metitms oris probl [] ppc
   510       val thy' = get_obj g_domID pt p;
   511       val thy = Celem.assoc_thy thy';
   512       val srls = Lucin.get_simplifier (pt, pos)
   513 (*//----------- hack for funpack: generalise handling of meths which extend problem items -----\\*)
   514 val itms =
   515   if mI = ["Biegelinien", "ausBelastung"]
   516   then itms @
   517     [(4, [1], true, "#Given", Model.Cor ((Const ("Biegelinie.Biegelinie", Type ("fun", [Type ("fun", [Type ("Real.real", []), Type ("Real.real", [])]), Type ("Input_Descript.una", [])])),
   518         [Free ("y", Type ("fun", [Type ("Real.real", []), Type ("Real.real", [])]))]),
   519       (Free ("id_fun", Type ("fun", [Type ("Real.real", []), Type ("Real.real", [])])),
   520         [Free ("y", Type ("fun", [Type ("Real.real", []), Type ("Real.real", [])]))] ))),
   521     (5, [1], true, "#Given", Model.Cor ((Const ("Biegelinie.AbleitungBiegelinie", Type ("fun", [Type ("fun", [Type ("Real.real", []), Type ("Real.real", [])]), Type ("Input_Descript.una", [])])),
   522         [Free ("dy", Type ("fun", [Type ("Real.real", []), Type ("Real.real", [])]))]),
   523       (Free ("id_abl", Type ("fun", [Type ("Real.real", []), Type ("Real.real", [])])),
   524         [Free ("dy", Type ("fun", [Type ("Real.real", []), Type ("Real.real", [])]))] )))]
   525   else itms
   526 (*\\----------- hack for funpack: generalise handling of meths which extend problem items -----//*)
   527      val (is, env, ctxt, scr) = case Lucin.init_pstate srls ctxt itms mI of
   528          (is as Istate.Pstate {env, ...}, ctxt, scr) => (is, env, ctxt, scr)
   529        | _ => error "begin_end_prog Apply_Method': uncovered case init_pstate"
   530      val ini = Lucin.init_form thy scr env;
   531    in 
   532      case ini of
   533        SOME t =>
   534        let
   535          val pos = ((lev_on o lev_dn) p, Frm)
   536 	       val tac_ = Tactic.Apply_Method' (mI, SOME t, is, ctxt);
   537 	       val (pos, c, _, pt) = Generate.generate1 thy tac_ (is, ctxt) pos pt (* implicit Take *)
   538        in
   539         ([(Tactic.Apply_Method mI, tac_, (pos, (is, ctxt)))], c, (pt, pos))
   540        end
   541      | NONE =>
   542        let
   543          val pt = update_env pt (fst pos) (SOME (is, ctxt))
   544 	       val (tacis, c, ptp) = do_solve_step (pt, pos)
   545        in (tacis @ [(Tactic.Apply_Method mI,
   546             Tactic.Apply_Method' (mI, NONE, Istate.e_istate, ctxt), (pos, (is, ctxt)))], c, ptp)
   547        end
   548     end
   549   | begin_end_prog (Tactic.Check_Postcond' (pI, _)) _ (pt, (p, p_))  =
   550     let
   551       val pp = par_pblobj pt p
   552       val asm = (case get_obj g_tac pt p of
   553 		    Tactic.Check_elementwise _ => (snd o (get_obj g_result pt)) p (*collects and instantiates asms*)
   554 		  | _ => get_assumptions_ pt (p, p_))
   555       val metID = get_obj g_metID pt pp;
   556       val {srls = srls, scr = sc, ...} = Specify.get_met metID;
   557       val (loc, pst, ctxt) = case get_loc pt (p, p_) of
   558         loc as (Istate.Pstate pst, ctxt) => (loc, pst, ctxt)
   559       | _ => error "begin_end_prog Check_Postcond': uncovered case get_loc"
   560       val thy' = get_obj g_domID pt pp;
   561       val thy = Celem.assoc_thy thy';
   562       val (_, _, (scval, _)) = determine_next_tactic (thy', srls) (pt, (p, p_)) sc loc;
   563     in
   564       if pp = []
   565       then 
   566 	      let
   567           val is = Istate.Pstate (pst |> Istate.set_act scval |> Istate.set_appy Istate.Skip_)
   568 	        val tac_ = Tactic.Check_Postcond' (pI, (scval, asm))
   569 	          (*extend Tactic.Check_Postcond' (pI, (scval, asm), scsaf) ^^^^^ *)
   570 	        val ((p, p_), ps, _, pt) = Generate.generate1 thy tac_ (is, ctxt) (pp, Res) pt;
   571 	      in ([(Tactic.Check_Postcond pI, tac_, ((pp, Res), (is, ctxt)))], ps, (pt, (p, p_))) end
   572       else
   573         let (*resume script of parent PblObj, transfer value of subpbl-script*)
   574           val ppp = par_pblobj pt (lev_up p);
   575 	        val thy' = get_obj g_domID pt ppp;
   576           val thy = Celem.assoc_thy thy';
   577 
   578           val (pst', ctxt') = case get_loc pt (pp, Frm) of
   579             (Istate.Pstate pst', ctxt') => (pst', ctxt')
   580           | _ => error "begin_end_prog Check_Postcond' script of parpbl: uncovered case get_loc"
   581 	        val ctxt'' = ContextC.from_subpbl_to_caller ctxt scval ctxt'
   582           val tac_ = Tactic.Check_Postcond' (pI, (scval, asm))
   583 	        val is = Istate.Pstate (pst' |> Istate.set_act scval |> Istate.set_appy Istate.Skip_)
   584           val ((p, p_), ps, _, pt) = Generate.generate1 thy tac_ (is, ctxt'') (pp, Res) pt;
   585         in ([(Tactic.Check_Postcond pI, tac_, ((pp, Res), (is, ctxt'')))], ps, (pt, (p, p_))) end
   586     end
   587   | begin_end_prog (Tactic.End_Proof'') _ ptp = ([], [], ptp)
   588   | begin_end_prog tac_ is (pt, pos) =
   589     let
   590       val pos = case pos of
   591  		   (p, Met) => ((lev_on o lev_dn) p, Frm) (* begin script        *)
   592  		  | (p, Res) => (lev_on p, Res)            (* somewhere in script *)
   593  		  | _ => pos
   594  	    val (pos', c, _, pt) = Generate.generate1 (Celem.assoc_thy "Isac_Knowledge") tac_ is pos pt;
   595     in
   596       ([(Tactic.input_from_T tac_, tac_, (pos, is))], c, (pt, pos'))
   597     end
   598 (*find the next tac from the script, begin_end_prog will update the ctree*)
   599 and do_solve_step (ptp as (pt, pos as (p, p_))) = (* WN1907: ?only for Begin_/End_Detail' DEL!!!*)
   600     if Celem.e_metID = get_obj g_metID pt (par_pblobj pt p)
   601     then ([], [], (pt, (p, p_)))
   602     else 
   603       let 
   604         val thy' = get_obj g_domID pt (par_pblobj pt p);
   605 	      val (srls, is, sc) = Lucin.from_pblobj_or_detail' thy' (p,p_) pt;
   606 	      val (tac_, is, (t, _)) = determine_next_tactic (thy', srls) (pt, pos) sc is;
   607 	      (* TODO here  ^^^  return finished/helpless/ok ?*)
   608 	    in case tac_ of
   609 		    Tactic.End_Detail' _ =>
   610           ([(Tactic.End_Detail, Tactic.End_Detail' (t, [(*FIXME.04*)]), (pos, is))], [], (pt, pos))
   611 	    | _ => begin_end_prog tac_        is                          ptp
   612       end;
   613 
   614 (*
   615   compare inform with ctree.form at current pos by nrls;
   616   if found, embed the derivation generated during comparison
   617   if not, let the mat-engine compute the next ctree.form.
   618 
   619   Code's structure is copied from complete_solve
   620   CAUTION: tacis in returned calcstate' do NOT construct resulting ptp --
   621            all_modspec etc. has to be inserted at Subproblem'
   622 *)
   623 fun compare_step ((tacis, c, ptp as (pt, pos as (p,p_))): Chead.calcstate') ifo =
   624   let
   625     val fo =
   626       case p_ of
   627         Pos.Frm => Ctree.get_obj Ctree.g_form pt p
   628 			| Pos.Res => (fst o (Ctree.get_obj Ctree.g_result pt)) p
   629 			| _ => Rule.e_term (*on PblObj is fo <> ifo*);
   630 	  val {nrls, ...} = Specify.get_met (Ctree.get_obj Ctree.g_metID pt (Ctree.par_pblobj pt p))
   631 	  val {rew_ord, erls, rules, ...} = Rule.rep_rls nrls
   632 	  val (found, der) = Inform.concat_deriv rew_ord erls rules fo ifo; (*<---------------*)
   633   in
   634     if found
   635     then
   636        let
   637          val tacis' = map (Inform.mk_tacis rew_ord erls) der;
   638 		     val (c', ptp) = Generate.embed_deriv tacis' ptp;
   639 	     in ("ok", (tacis (*@ tacis'?WN050408*), c @ c', ptp)) end
   640      else 
   641 	     if pos = ([], Pos.Res) (*TODO: we should stop earlier with trying subproblems *)
   642 	     then ("no derivation found", (tacis, c, ptp): Chead.calcstate') 
   643 	     else
   644          let
   645            val cs' as (tacis, c', ptp) = do_solve_step ptp; (*<---------------------*)
   646 		       val (tacis, c'', ptp) = case tacis of
   647 			       ((Tactic.Subproblem _, _, _)::_) => 
   648 			         let
   649                  val ptp as (pt, (p,_)) = Chead.all_modspec ptp (*<--------------------*)
   650 				         val mI = Ctree.get_obj Ctree.g_metID pt p
   651 			         in
   652 			           begin_end_prog (Tactic.Apply_Method' (mI, NONE, Istate.e_istate, ContextC.e_ctxt)) (Istate.e_istate, ContextC.e_ctxt) ptp
   653                end
   654 			     | _ => cs';
   655 		     in compare_step (tacis, c @ c' @ c'', ptp) ifo end
   656   end
   657 
   658 (*
   659   handle a user-input formula, which may be a CAS-command, too.
   660  * CAS-command: create a calchead, and do 1 step
   661  * formula, which is no CAS-command:
   662    compare iform with calc-tree.form at pos by equ_nrls and all subsequent pos;
   663    collect all the Prog_Tac applied by the way; ...???TODO?
   664    If "no derivation found" then check_error_patterns.
   665    ALTERNATIVE: check_error_patterns _within_ compare_step: seems too expensive
   666 *)
   667 (*                       vvvv           vvvvvv vvvv    NEW args for compare_step *)
   668 fun locate_input_formula (Rule.Prog _)  ((pt, pos) : Ctree.state) (_ : Istate.T) (_ : Proof.context) tm =
   669      let                                                          
   670    		val pos_pred = Ctree.lev_back' pos (*f_pred ---"step pos cs"---> f_succ in appendFormula*)
   671    		val _(*f_pred*) = Ctree.get_curr_formula (pt, pos_pred)
   672      in
   673        (*TODO: use prog, istate, ctxt in compare_step ...*)
   674    		case compare_step ([], [], (pt, pos_pred)) tm of
   675    		  ("no derivation found", calcstate') => Not_Derivable calcstate'
   676        | ("ok", (_, _, cstate as (pt', pos'))) => 
   677            Step (cstate, get_istate pt' pos', get_ctxt pt' pos')
   678        | _ => raise ERROR "compare_step: uncovered case"
   679      end
   680   | locate_input_formula _ _ _ _ _ = error ""
   681 
   682 (**)end(**)