src/Tools/isac/Specify/appl.sml
author Walther Neuper <walther.neuper@jku.at>
Fri, 10 Apr 2020 16:16:09 +0200
changeset 59867 bb153a08645b
parent 59865 75a9d629ea53
child 59868 d77aa0992e0f
permissions -rw-r--r--
use "Rule" and "Rule_Set" for renaming identifiers
wneuper@59305
     1
(* Title:  Is a tacitc applicable ?
wneuper@59305
     2
           TODO: allocate these functions in appropriate structures
wneuper@59305
     3
   Author: Walther Neuper
wneuper@59305
     4
   (c) due to copyright terms
neuper@37936
     5
*)
wneuper@59272
     6
wneuper@59284
     7
signature APPLICABLE =
wneuper@59284
     8
sig
wneuper@59284
     9
  exception PTREE of string
walther@59735
    10
  datatype appl = Appl of Tactic.T | Notappl of string
walther@59846
    11
  val applicable_in : Pos.pos' -> Ctree.ctree -> Tactic.input -> appl
wneuper@59310
    12
(* ---- for tests only: shifted from below to remove the Warning "unused" at fun.def. --------- *)
walther@59846
    13
  val tac2tac_ : Ctree.ctree -> Pos.pos' -> Tactic.input -> Tactic.T
walther@59785
    14
(*/-------------------------------------------------------- ! aktivate for Test_Isac BEGIN ---\* )
wneuper@59285
    15
  val mk_set : 'a -> ctree -> pos -> term -> term -> term * term list
walther@59785
    16
( *\--- ! aktivate for Test_Isac END ----------------------------------------------------------/*)
wneuper@59284
    17
end
wneuper@59285
    18
wneuper@59284
    19
(**)
wneuper@59284
    20
structure Applicable(**): APPLICABLE(**) =
wneuper@59272
    21
struct
wneuper@59284
    22
(**)
wneuper@59276
    23
open Ctree
walther@59695
    24
open Pos
wneuper@59272
    25
walther@59851
    26
fun rew_info (Rule_Def.Repeat {erls, rew_ord = (rew_ord', _), calc = ca, ...}) =
wneuper@59285
    27
    (rew_ord', erls, ca)
walther@59851
    28
  | rew_info (Rule_Set.Seqence {erls, rew_ord = (rew_ord', _), calc = ca, ...}) =
wneuper@59285
    29
    (rew_ord', erls, ca)
walther@59850
    30
  | rew_info (Rule_Set.Rrls {erls, rew_ord = (rew_ord', _), calc = ca, ...}) =
wneuper@59285
    31
    (rew_ord', erls, ca)
walther@59867
    32
  | rew_info rls = error ("rew_info called with '" ^ Rule_Set.id rls ^ "'");
neuper@37906
    33
neuper@37906
    34
(*FIXME.3.4.03:re-organize from_pblobj_or_detail_thm after rls' --> rls*)
wneuper@59285
    35
fun from_pblobj_or_detail_thm _ p pt = 
neuper@52155
    36
  let 
walther@59838
    37
    val (pbl, p', rls') = parent_node pt p
neuper@52155
    38
  in 
neuper@52155
    39
    if pbl
neuper@52155
    40
    then 
neuper@52155
    41
      let 
neuper@52155
    42
        val thy' = get_obj g_domID pt p'
wneuper@59269
    43
        val {rew_ord', erls, ...} = Specify.get_met (get_obj g_metID pt p')              
neuper@52155
    44
	    in ("OK", thy', rew_ord', erls, false) end
neuper@52155
    45
     else 
neuper@52155
    46
      let
neuper@52155
    47
        val thy' = get_obj g_domID pt (par_pblobj pt p)
neuper@52155
    48
		    val (rew_ord', erls, _) = rew_info rls'
wneuper@59285
    49
		  in ("OK", thy', rew_ord', erls, false) end
neuper@52155
    50
  end;
neuper@37906
    51
(*FIXME.3.4.03:re-organize from_pblobj_or_detail_calc after rls' --> rls*)
neuper@37906
    52
fun from_pblobj_or_detail_calc scrop p pt = 
neuper@52155
    53
  let
walther@59838
    54
    val (pbl, p', rls') = parent_node pt p
neuper@52155
    55
  in
neuper@52155
    56
    if pbl
neuper@52155
    57
    then
neuper@52155
    58
      let
neuper@52155
    59
        val thy' = get_obj g_domID pt p'
wneuper@59285
    60
        val {calc = scr_isa_fns, ...} = Specify.get_met (get_obj g_metID pt p')
neuper@52155
    61
        val opt = assoc (scr_isa_fns, scrop)
neuper@52155
    62
	    in
neuper@52155
    63
	      case opt of
wneuper@59285
    64
	        SOME isa_fn => ("OK", thy', isa_fn)
walther@59853
    65
	      | NONE => ("applicable_in Calculate: unknown '" ^ scrop ^ "'", "", ("", Exec_Def.e_evalfn))
neuper@52155
    66
	    end
neuper@52155
    67
    else 
neuper@52155
    68
		  let
neuper@52155
    69
		    val thy' = get_obj g_domID pt (par_pblobj pt p);
wneuper@59285
    70
		    val (_, _,(*_,*)scr_isa_fns) = rew_info rls'(*rls*)
neuper@52155
    71
		  in
neuper@52155
    72
		    case assoc (scr_isa_fns, scrop) of
neuper@52155
    73
		      SOME isa_fn => ("OK",thy',isa_fn)
walther@59853
    74
		    | NONE => ("applicable_in Calculate: unknown '" ^ scrop ^ "'", "", ("", Exec_Def.e_evalfn))
neuper@52155
    75
		  end
neuper@52155
    76
  end;
neuper@37906
    77
wneuper@59285
    78
(*for Check_elementwise in applicable_in: [x=1,..] Assumptions -> (x,0<=x&..)*)
walther@59861
    79
fun mk_set _(*thy*) _ _ (Const ("List.list.Nil", _)) _ = (TermC.empty, [])
walther@59620
    80
  | mk_set _ pt p (Const ("ListC.UniversalList", _)) pred =
walther@59861
    81
    (TermC.empty, if pred <> Const ("Prog_Tac.Assumptions", HOLogic.boolT)
wneuper@59285
    82
	     then [pred] 
walther@59844
    83
	     else Ctree.get_assumptions pt (p, Res))
wneuper@59285
    84
  | mk_set _ pt p (Const ("List.list.Cons",_) $ eq $ _) pred =
wneuper@59285
    85
    let
wneuper@59285
    86
      val (bdv,_) = HOLogic.dest_eq eq;
wneuper@59601
    87
      val pred = if pred <> Const ("Prog_Tac.Assumptions", HOLogic.boolT)
wneuper@59285
    88
  		  then [pred] 
walther@59844
    89
  	    else Ctree.get_assumptions pt (p, Res)
wneuper@59285
    90
    in (bdv, pred) end
wneuper@59285
    91
  | mk_set _ _ _ l _ = 
walther@59861
    92
    error ("check_elementwise: no set " ^ UnparseC.term2str l);
neuper@37906
    93
wneuper@59285
    94
(* check a list (/set) of constants [c_1,..,c_n] for c_i:set (: in)*)
neuper@37906
    95
fun check_elementwise thy erls all_results (bdv, asm) =
wneuper@59285
    96
  let   (*bdv extracted from ~~~~~~~~~~~ in mk_set already*)
wneuper@59285
    97
	  fun check sub =
neuper@37906
    98
	    let val inst_ = map (subst_atomic [sub]) asm
wneuper@59380
    99
	    in case Rewrite.eval__true thy 1 inst_ [] erls of
wneuper@59285
   100
		    (asm', true) => ([HOLogic.mk_eq sub], asm')
wneuper@59285
   101
		  | (_, false) => ([],[])
neuper@37906
   102
	    end;
wneuper@59389
   103
  	val c' = TermC.isalist2list all_results
wneuper@59285
   104
  	val c'' = map (snd o HOLogic.dest_eq) c' (*assumes [x=1,x=2,..]*)
wneuper@59285
   105
  	val subs = map (pair bdv) c''
wneuper@59285
   106
  in
wneuper@59285
   107
    if asm = []
wneuper@59285
   108
    then (all_results, [])
wneuper@59390
   109
    else ((apfst ((TermC.list2isalist HOLogic.boolT) o flat)) o (apsnd flat) o split_list o (map check)) subs
wneuper@59285
   110
  end;
neuper@37906
   111
wneuper@59285
   112
(* for Tac-dummies in root-equ only: skip str until "("*)
wneuper@59285
   113
fun split_dummy str = 
wneuper@59285
   114
  let
wneuper@59285
   115
    fun scan s' [] = (implode s', "")
wneuper@59285
   116
      | scan s' (s :: ss) = if s = " " then (implode s', implode  ss)
wneuper@59285
   117
			  else scan (s' @ [s]) ss;
wneuper@59285
   118
  in ((scan []) o Symbol.explode) str end;
neuper@37906
   119
walther@59735
   120
datatype appl =
walther@59735
   121
  Appl of Tactic.T      (* tactic is applicable at a certain position in the Ctree *)
walther@59735
   122
| Notappl of string     (* tactic is NOT applicable                                *)
walther@59735
   123
wneuper@59578
   124
(* applicability of a tacic wrt. a calc-state (ctree, pos').
walther@59772
   125
   additionally used by find_next_step.
neuper@37906
   126
   tests for applicability are so expensive, that results (rewrites!)
wneuper@59285
   127
   are kept in the return-value of 'type tac_'                            *)
walther@59735
   128
fun applicable_in _ _ (Tactic.Init_Proof (ct', spec)) = Appl (Tactic.Init_Proof' (ct', spec))
wneuper@59571
   129
  | applicable_in (p, p_) pt Tactic.Model_Problem = 
neuper@41975
   130
      if not (is_pblobj (get_obj I pt p)) orelse p_ = Res
walther@59846
   131
      then Notappl ((Tactic.input_to_string Tactic.Model_Problem) ^ " not for pos " ^ (pos'2str (p, p_)))
neuper@41975
   132
      else 
neuper@41975
   133
        let 
wneuper@59285
   134
          val pI' = case get_obj I pt p of
wneuper@59285
   135
            PblObj {origin = (_, (_, pI', _),_), ...} => pI'
wneuper@59285
   136
          | _ => error "applicable_in Init_Proof: uncovered case get_obj"
wneuper@59285
   137
	        val {ppc, ...} = Specify.get_pbt pI'
wneuper@59271
   138
	        val pbl = Generate.init_pbl ppc
walther@59735
   139
        in Appl (Tactic.Model_Problem' (pI', pbl, [])) end
wneuper@59571
   140
  | applicable_in (p, p_) pt (Tactic.Refine_Tacitly pI) = 
neuper@41975
   141
      if not (is_pblobj (get_obj I pt p)) orelse p_ = Res
walther@59846
   142
      then Notappl ((Tactic.input_to_string (Tactic.Refine_Tacitly pI)) ^ " not for pos " ^ (pos'2str (p, p_)))
neuper@41975
   143
      else 
neuper@41975
   144
        let 
wneuper@59285
   145
          val oris = case get_obj I pt p of
wneuper@59285
   146
            PblObj {origin = (oris, _, _), ...} => oris
wneuper@59285
   147
          | _ => error "applicable_in Refine_Tacitly: uncovered case get_obj"
wneuper@59285
   148
        in
wneuper@59285
   149
          case Specify.refine_ori oris pI of
wneuper@59285
   150
	          SOME pblID => 
walther@59854
   151
	            Appl (Tactic.Refine_Tacitly' (pI, pblID, ThyC.e_domID, Celem.e_metID, [](*filled in specify*)))
walther@59846
   152
	        | NONE => Notappl ((Tactic.input_to_string (Tactic.Refine_Tacitly pI)) ^ " not applicable")
neuper@41975
   153
        end
wneuper@59571
   154
  | applicable_in (p, p_) pt (Tactic.Refine_Problem pI) = 
wneuper@59285
   155
    if not (is_pblobj (get_obj I pt p)) orelse p_ = Res                  
walther@59846
   156
    then Notappl ((Tactic.input_to_string (Tactic.Refine_Problem pI)) ^ " not for pos "^(pos'2str (p, p_)))
wneuper@59285
   157
    else
wneuper@59285
   158
      let
wneuper@59285
   159
        val (dI, dI', itms) = case get_obj I pt p of
wneuper@59285
   160
            PblObj {origin= (_, (dI, _, _), _), spec= (dI', _, _), probl = itms, ...}
wneuper@59285
   161
              => (dI, dI', itms)
wneuper@59285
   162
          | _ => error "applicable_in Refine_Problem: uncovered case get_obj"
walther@59854
   163
      	val thy = if dI' = ThyC.e_domID then dI else dI';
wneuper@59285
   164
      in
wneuper@59405
   165
        case Specify.refine_pbl (Celem.assoc_thy thy) pI itms of
walther@59846
   166
          NONE => Notappl ((Tactic.input_to_string (Tactic.Refine_Problem pI)) ^ " not applicable")
wneuper@59285
   167
	      | SOME (rf as (pI', _)) =>
wneuper@59285
   168
      	   if pI' = pI
walther@59846
   169
      	   then Notappl ((Tactic.input_to_string (Tactic.Refine_Problem pI)) ^ " not applicable")
walther@59735
   170
      	   else Appl (Tactic.Refine_Problem' rf)
neuper@37906
   171
    end
wneuper@59285
   172
  (*the specify-tacs have cterm' instead term: parse+error here!!!: see appl_add*)  
wneuper@59571
   173
  | applicable_in (p, p_) pt (Tactic.Add_Given ct') = 
wneuper@59285
   174
    if not (is_pblobj (get_obj I pt p)) orelse p_ = Res                  
walther@59846
   175
    then Notappl ((Tactic.input_to_string (Tactic.Add_Given ct')) ^ " not for pos " ^ pos'2str (p, p_))
walther@59735
   176
    else Appl (Tactic.Add_Given' (ct', [(*filled in specify_additem*)]))
wneuper@59285
   177
      (*Add_.. should reject (dsc //) (see fmz=[] in sqrt*)
wneuper@59571
   178
  | applicable_in (p, p_) pt (Tactic.Del_Given ct') =
wneuper@59285
   179
    if not (is_pblobj (get_obj I pt p)) orelse p_ = Res                  
walther@59846
   180
    then Notappl ((Tactic.input_to_string (Tactic.Del_Given ct')) ^ " not for pos " ^ pos'2str (p, p_))
walther@59735
   181
    else Appl (Tactic.Del_Given' ct')
wneuper@59571
   182
  | applicable_in (p, p_) pt (Tactic.Add_Find ct') =                   
wneuper@59285
   183
    if not (is_pblobj (get_obj I pt p)) orelse p_ = Res                  
walther@59846
   184
    then Notappl ((Tactic.input_to_string (Tactic.Add_Find ct')) ^ " not for pos " ^ pos'2str (p, p_))
walther@59735
   185
    else Appl (Tactic.Add_Find' (ct', [(*filled in specify_additem*)]))
wneuper@59571
   186
  | applicable_in (p, p_) pt (Tactic.Del_Find ct') =
wneuper@59285
   187
    if not (is_pblobj (get_obj I pt p)) orelse p_ = Res                  
walther@59846
   188
    then Notappl ((Tactic.input_to_string (Tactic.Del_Find ct')) ^ " not for pos " ^ pos'2str (p, p_))
walther@59735
   189
    else Appl (Tactic.Del_Find' ct')
wneuper@59571
   190
  | applicable_in (p, p_) pt (Tactic.Add_Relation ct') =               
wneuper@59285
   191
    if not (is_pblobj (get_obj I pt p)) orelse p_ = Res                  
walther@59846
   192
    then Notappl ((Tactic.input_to_string (Tactic.Add_Relation ct')) ^ " not for pos " ^ pos'2str (p, p_))
walther@59735
   193
    else Appl (Tactic.Add_Relation' (ct', [(*filled in specify_additem*)]))
wneuper@59571
   194
  | applicable_in (p, p_) pt (Tactic.Del_Relation ct') =
wneuper@59285
   195
    if not (is_pblobj (get_obj I pt p)) orelse p_ = Res                  
walther@59846
   196
    then Notappl ((Tactic.input_to_string (Tactic.Del_Relation ct')) ^ " not for pos " ^ pos'2str (p, p_))
walther@59735
   197
    else Appl (Tactic.Del_Relation' ct')
wneuper@59571
   198
  | applicable_in (p, p_) pt (Tactic.Specify_Theory dI) =              
wneuper@59285
   199
    if not (is_pblobj (get_obj I pt p)) orelse p_ = Res                  
walther@59846
   200
    then Notappl ((Tactic.input_to_string (Tactic.Specify_Theory dI)) ^ " not for pos " ^ pos'2str (p, p_))
walther@59735
   201
    else Appl (Tactic.Specify_Theory' dI)
wneuper@59571
   202
  | applicable_in (p, p_) pt (Tactic.Specify_Problem pID) = 
wneuper@59285
   203
    if not (is_pblobj (get_obj I pt p)) orelse p_ = Res                  
walther@59846
   204
    then Notappl ((Tactic.input_to_string (Tactic.Specify_Problem pID)) ^ " not for pos " ^ pos'2str (p, p_))
wneuper@59285
   205
    else
wneuper@59285
   206
      let
wneuper@59285
   207
		    val (oris, dI, pI, dI', pI', itms) = case get_obj I pt p of
wneuper@59285
   208
		      PblObj {origin = (oris, (dI, pI, _), _), spec = (dI', pI', _), probl = itms, ...}
wneuper@59285
   209
		        => (oris, dI, pI, dI', pI', itms)
wneuper@59285
   210
        | _ => error "applicable_in Specify_Problem: uncovered case get_obj"
walther@59854
   211
	      val thy = Celem.assoc_thy (if dI' = ThyC.e_domID then dI else dI');
wneuper@59285
   212
        val {ppc, where_, prls, ...} = Specify.get_pbt pID;
wneuper@59405
   213
        val pbl = if pI' = Celem.e_pblID andalso pI = Celem.e_pblID
wneuper@59285
   214
          then (false, (Generate.init_pbl ppc, []))
wneuper@59285
   215
          else Specify.match_itms_oris thy itms (ppc, where_, prls) oris;
wneuper@59285
   216
       in
walther@59735
   217
        Appl (Tactic.Specify_Problem' (pID, pbl))
wneuper@59285
   218
      end
wneuper@59571
   219
  | applicable_in (p, p_) pt (Tactic.Specify_Method mID) =              
wneuper@59285
   220
    if not (is_pblobj (get_obj I pt p)) orelse p_ = Res               
walther@59846
   221
    then Notappl ((Tactic.input_to_string (Tactic.Specify_Method mID)) ^ " not for pos " ^ pos'2str (p, p_))
walther@59735
   222
    else Appl (Tactic.Specify_Method' (mID, [(*filled in specify*)], [(*filled in specify*)]))
wneuper@59571
   223
  | applicable_in (p, p_) pt (Tactic.Apply_Method mI) =                
wneuper@59285
   224
    if not (is_pblobj (get_obj I pt p)) orelse p_ = Res                  
walther@59846
   225
    then Notappl ((Tactic.input_to_string (Tactic.Apply_Method mI)) ^ " not for pos " ^ pos'2str (p, p_))
wneuper@59285
   226
    else
wneuper@59285
   227
      let
wneuper@59285
   228
        val (dI, pI, probl, ctxt) = case get_obj I pt p of
wneuper@59285
   229
          PblObj {origin = (_, (dI, pI, _), _), probl, ctxt, ...} => (dI, pI, probl, ctxt)
wneuper@59285
   230
        | _ => error "applicable_in Apply_Method: uncovered case get_obj"
wneuper@59285
   231
        val {where_, ...} = Specify.get_pbt pI
wneuper@59316
   232
        val pres = map (Model.mk_env probl |> subst_atomic) where_
walther@59846
   233
        val ctxt = if ContextC.is_empty ctxt (*vvvvvvvvvvvvvv DO THAT EARLIER?!?*)
wneuper@59577
   234
          then Celem.assoc_thy dI |> Proof_Context.init_global |> ContextC.insert_assumptions pres
wneuper@59285
   235
          else ctxt
wneuper@59285
   236
       (*TODO.WN110416 here do evalprecond according to fun check_preconds'
walther@59735
   237
       and then decide on Notappl/Appl accordingly once more.
wneuper@59285
   238
       Implement after all tests are running, since this changes
wneuper@59285
   239
       overall system behavior*)
wneuper@59285
   240
    in
walther@59846
   241
      Appl (Tactic.Apply_Method' (mI, NONE, Istate_Def.empty (*filled in solve*), ctxt))
wneuper@59285
   242
    end
wneuper@59571
   243
  | applicable_in (p, p_) _ (Tactic.Check_Postcond pI) =
wneuper@59285
   244
      if member op = [Pbl, Met] p_                  
walther@59846
   245
      then Notappl ((Tactic.input_to_string (Tactic.Check_Postcond pI)) ^ " not for pos " ^ pos'2str (p, p_))
walther@59861
   246
      else Appl (Tactic.Check_Postcond' (pI, TermC.empty))
walther@59735
   247
  | applicable_in _ _ (Tactic.Take str) = Appl (Tactic.Take' (TermC.str2term str)) (* always applicable ?*)
walther@59735
   248
  | applicable_in _ _ (Tactic.Free_Solve) = Appl (Tactic.Free_Solve')        (* always applicable *)
wneuper@59571
   249
  | applicable_in (p, p_) pt (m as Tactic.Rewrite_Inst (subs, thm'')) = 
neuper@42394
   250
    if member op = [Pbl, Met] p_ 
walther@59846
   251
    then Notappl ((Tactic.input_to_string m)^" not for pos " ^ pos'2str (p, p_))
neuper@42394
   252
    else
neuper@42394
   253
      let 
neuper@42394
   254
        val pp = par_pblobj pt p;
wneuper@59405
   255
        val thy' = get_obj g_domID pt pp;
wneuper@59405
   256
        val thy = Celem.assoc_thy thy';
wneuper@59269
   257
        val {rew_ord' = ro', erls = erls, ...} = Specify.get_met (get_obj g_metID pt pp);
wneuper@59285
   258
        val (f, _) = case p_ of (*p 12.4.00 unnecessary*)
neuper@42394
   259
                      Frm => (get_obj g_form pt p, p)
neuper@42394
   260
                    | Res => ((fst o (get_obj g_result pt)) p, lev_on p)
wneuper@59285
   261
                    | _ => error ("applicable_in: call by " ^ pos'2str (p, p_));
neuper@42394
   262
      in 
neuper@42394
   263
        let
wneuper@59301
   264
          val subst = Selem.subs2subst thy subs;
wneuper@59285
   265
        in
walther@59857
   266
          case Rewrite.rewrite_inst_ thy (Rewrite_Ord.assoc_rew_ord ro') erls false subst (snd thm'') f of
wneuper@59285
   267
            SOME (f',asm) =>
walther@59735
   268
              Appl (Tactic.Rewrite_Inst' (thy', ro', erls, false, subst, thm'', f, (f', asm)))
walther@59735
   269
          | NONE => Notappl ((fst thm'')^" not applicable")
neuper@42394
   270
        end
walther@59735
   271
        handle _ => Notappl ("syntax error in "^(subs2str subs))
neuper@42394
   272
      end
wneuper@59571
   273
  | applicable_in (p, p_) pt (m as Tactic.Rewrite thm'') = 
wneuper@59285
   274
    if member op = [Pbl, Met] p_ 
walther@59846
   275
    then Notappl ((Tactic.input_to_string m)^" not for pos "^(pos'2str (p, p_)))
neuper@37906
   276
    else
wneuper@59285
   277
      let
wneuper@59285
   278
        val (msg, thy', ro, rls', _)= from_pblobj_or_detail_thm thm'' p pt;
wneuper@59405
   279
        val thy = Celem.assoc_thy thy';
wneuper@59285
   280
        val f = case p_ of
wneuper@59285
   281
          Frm => get_obj g_form pt p
wneuper@59285
   282
	      | Res => (fst o (get_obj g_result pt)) p
wneuper@59285
   283
	      | _ => error ("applicable_in Rewrite: call by " ^ pos'2str (p, p_));
wneuper@59285
   284
      in
wneuper@59285
   285
        if msg = "OK" 
wneuper@59285
   286
        then
walther@59857
   287
          case Rewrite.rewrite_ thy (Rewrite_Ord.assoc_rew_ord ro) rls' false (snd thm'') f of
walther@59735
   288
            SOME (f',asm) => Appl (Tactic.Rewrite' (thy', ro, rls', false, thm'', f, (f', asm)))
walther@59735
   289
          | NONE => Notappl ("'" ^ fst thm'' ^"' not applicable") 
walther@59735
   290
        else Notappl msg
wneuper@59285
   291
      end
wneuper@59571
   292
  | applicable_in (p, p_) pt (m as Tactic.Detail_Set_Inst (subs, rls)) = 
wneuper@59285
   293
    if member op = [Pbl, Met] p_ 
walther@59846
   294
    then Notappl ((Tactic.input_to_string m)^" not for pos "^(pos'2str (p, p_)))
wneuper@59285
   295
    else
wneuper@59285
   296
      let 
wneuper@59285
   297
        val pp = par_pblobj pt p;
wneuper@59285
   298
        val thy' = get_obj g_domID pt pp;
wneuper@59405
   299
        val thy = Celem.assoc_thy thy';
wneuper@59285
   300
        val f = case p_ of Frm => get_obj g_form pt p
wneuper@59285
   301
    		| Res => (fst o (get_obj g_result pt)) p
wneuper@59285
   302
    		| _ => error ("applicable_in: call by " ^ pos'2str (p, p_));
wneuper@59301
   303
        val subst = Selem.subs2subst thy subs
wneuper@59285
   304
      in 
wneuper@59380
   305
        case Rewrite.rewrite_set_inst_ thy false subst (assoc_rls rls) f of
wneuper@59285
   306
          SOME (f', asm)
walther@59735
   307
            => Appl (Tactic.Detail_Set_Inst' (thy', false, subst, assoc_rls rls, f, (f', asm)))
walther@59735
   308
        | NONE => Notappl (rls ^ " not applicable")
walther@59735
   309
        handle _ => Notappl ("syntax error in " ^ subs2str subs)
wneuper@59285
   310
      end
wneuper@59571
   311
  | applicable_in (p, p_) pt (m as Tactic.Rewrite_Set_Inst (subs, rls)) = 
wneuper@59285
   312
    if member op = [Pbl, Met] p_ 
walther@59846
   313
    then Notappl ((Tactic.input_to_string m)^" not for pos "^(pos'2str (p,p_)))
wneuper@59285
   314
    else
wneuper@59285
   315
      let 
wneuper@59285
   316
        val pp = par_pblobj pt p;
wneuper@59285
   317
        val thy' = get_obj g_domID pt pp;
wneuper@59405
   318
        val thy = Celem.assoc_thy thy';
wneuper@59285
   319
        val (f, _) = case p_ of
wneuper@59285
   320
          Frm => (get_obj g_form pt p, p)
wneuper@59285
   321
    	  | Res => ((fst o (get_obj g_result pt)) p, lev_on p)
wneuper@59285
   322
    	  | _ => error ("applicable_in: call by " ^ pos'2str (p, p_));
wneuper@59301
   323
    	  val subst = Selem.subs2subst thy subs;
wneuper@59285
   324
      in 
wneuper@59380
   325
        case Rewrite.rewrite_set_inst_ thy (*put_asm*)false subst (assoc_rls rls) f of
wneuper@59285
   326
          SOME (f',asm)
walther@59735
   327
            => Appl (Tactic.Rewrite_Set_Inst' (thy', false, subst, assoc_rls rls, f, (f', asm)))
walther@59735
   328
        | NONE => Notappl (rls ^ " not applicable")
walther@59735
   329
        handle _ => Notappl ("syntax error in " ^(subs2str subs))
wneuper@59285
   330
      end
wneuper@59571
   331
  | applicable_in (p, p_) pt (m as Tactic.Rewrite_Set rls) = 
wneuper@59285
   332
    if member op = [Pbl, Met] p_ 
walther@59846
   333
    then Notappl (Tactic.input_to_string m ^ " not for pos " ^ pos'2str (p, p_))
wneuper@59285
   334
    else
wneuper@59285
   335
      let 
wneuper@59285
   336
        val pp = par_pblobj pt p; 
wneuper@59285
   337
        val thy' = get_obj g_domID pt pp;
wneuper@59285
   338
        val (f, _) = case p_ of
wneuper@59285
   339
          Frm => (get_obj g_form pt p, p)
wneuper@59285
   340
    	  | Res => ((fst o (get_obj g_result pt)) p, lev_on p)
wneuper@59285
   341
    	  | _ => error ("applicable_in: call by " ^ pos'2str (p, p_));
wneuper@59285
   342
      in
wneuper@59405
   343
        case Rewrite.rewrite_set_ (Celem.assoc_thy thy') false (assoc_rls rls) f of
wneuper@59285
   344
          SOME (f', asm)
walther@59735
   345
            => Appl (Tactic.Rewrite_Set' (thy', false, assoc_rls rls, f, (f', asm)))
walther@59735
   346
          | NONE => Notappl (rls ^ " not applicable")
wneuper@59285
   347
      end
wneuper@59571
   348
  | applicable_in (p, p_) pt (m as Tactic.Detail_Set rls) =
wneuper@59285
   349
    if member op = [Pbl, Met] p_ 
walther@59846
   350
    then Notappl (Tactic.input_to_string m ^ " not for pos " ^ pos'2str (p, p_))
wneuper@59285
   351
    else
wneuper@59285
   352
    	let
wneuper@59285
   353
    	  val pp = par_pblobj pt p 
wneuper@59285
   354
    	  val thy' = get_obj g_domID pt pp
wneuper@59285
   355
    	  val f = case p_ of
wneuper@59285
   356
    			Frm => get_obj g_form pt p
wneuper@59285
   357
    		| Res => (fst o (get_obj g_result pt)) p
wneuper@59285
   358
    		| _ => error ("applicable_in: call by " ^ pos'2str (p, p_));
wneuper@59285
   359
    	in
wneuper@59405
   360
    	  case Rewrite.rewrite_set_ (Celem.assoc_thy thy') false (assoc_rls rls) f of
walther@59735
   361
    	    SOME (f',asm) => Appl (Tactic.Detail_Set' (thy', false, assoc_rls rls, f, (f', asm)))
walther@59735
   362
    	  | NONE => Notappl (rls^" not applicable")
wneuper@59285
   363
    	end
walther@59846
   364
  | applicable_in _ _ Tactic.End_Ruleset = error ("applicable_in: not impl. for " ^ Tactic.input_to_string Tactic.End_Ruleset)
wneuper@59571
   365
  | applicable_in (p, p_) pt (m as Tactic.Calculate op_) = 
wneuper@59285
   366
    if member op = [Pbl, Met] p_
walther@59846
   367
    then Notappl ((Tactic.input_to_string m)^" not for pos "^(pos'2str (p,p_)))
wneuper@59285
   368
    else
wneuper@59285
   369
      let 
wneuper@59285
   370
        val (msg,thy',isa_fn) = from_pblobj_or_detail_calc op_ p pt;
wneuper@59285
   371
        val f = case p_ of
wneuper@59285
   372
          Frm => get_obj g_form pt p
wneuper@59285
   373
    	  | Res => (fst o (get_obj g_result pt)) p
wneuper@59285
   374
      	| _ => error ("applicable_in: call by " ^ pos'2str (p, p_));
wneuper@59285
   375
      in
wneuper@59285
   376
        if msg = "OK"
wneuper@59285
   377
        then
wneuper@59405
   378
    	    case Rewrite.calculate_ (Celem.assoc_thy thy') isa_fn f of
wneuper@59285
   379
    	      SOME (f', (id, thm))
walther@59865
   380
    	        => Appl (Tactic.Calculate' (thy', op_, f, (f', (id, ThmC_Def.string_of_thmI thm))))
walther@59735
   381
    	    | NONE => Notappl ("'calculate "^op_^"' not applicable") 
walther@59735
   382
        else Notappl msg
wneuper@59285
   383
      end
wneuper@59285
   384
    (*Substitute combines two different kind of "substitution":
wneuper@59285
   385
      (1) subst_atomic: for ?a..?z
wneuper@59285
   386
      (2) Pattern.match: for solving equational systems (which raises exn for ?a..?z)*)
wneuper@59571
   387
  | applicable_in (p, p_) pt (m as Tactic.Substitute sube) = 
wneuper@59285
   388
      if member op = [Pbl, Met] p_ 
walther@59846
   389
      then Notappl (Tactic.input_to_string m ^ " not for pos " ^ pos'2str (p, p_))
neuper@42360
   390
      else 
neuper@42360
   391
        let
neuper@42360
   392
          val pp = par_pblobj pt p
wneuper@59405
   393
          val thy = Celem.assoc_thy (get_obj g_domID pt pp)
neuper@42360
   394
          val f = case p_ of
neuper@42360
   395
		        Frm => get_obj g_form pt p
neuper@42360
   396
		      | Res => (fst o (get_obj g_result pt)) p
wneuper@59285
   397
      	  | _ => error ("applicable_in: call by " ^ pos'2str (p, p_));
wneuper@59269
   398
		      val {rew_ord',erls,...} = Specify.get_met (get_obj g_metID pt pp)
wneuper@59301
   399
		      val subte = Selem.sube2subte sube
wneuper@59301
   400
		      val subst = Selem.sube2subst thy sube
walther@59857
   401
		      val ro = Rewrite_Ord.assoc_rew_ord rew_ord'
neuper@42360
   402
		    in
wneuper@59389
   403
		      if foldl and_ (true, map TermC.contains_Var subte)
wneuper@59285
   404
		      then (*1*)
neuper@42360
   405
		        let val f' = subst_atomic subst f
wneuper@59285
   406
		        in if f = f'
walther@59735
   407
		          then Notappl (Selem.sube2str sube^" not applicable")
walther@59735
   408
		          else Appl (Tactic.Substitute' (ro, erls, subte, f, f'))
neuper@42360
   409
		        end
wneuper@59285
   410
		      else (*2*)
wneuper@59380
   411
		        case Rewrite.rewrite_terms_ thy ro erls subte f of
walther@59735
   412
		          SOME (f', _) =>  Appl (Tactic.Substitute' (ro, erls, subte, f, f'))
walther@59735
   413
		        | NONE => Notappl (Selem.sube2str sube ^ " not applicable")
neuper@42360
   414
		    end
wneuper@59571
   415
  | applicable_in _ _ (Tactic.Apply_Assumption cts') = 
walther@59846
   416
    error ("applicable_in: not impl. for " ^ Tactic.input_to_string (Tactic.Apply_Assumption cts'))
wneuper@59559
   417
    (* 'logical' applicability wrt. script in locate_input_tactic: Inconsistent? *)
wneuper@59571
   418
  | applicable_in _ _ (Tactic.Take_Inst ct') =
walther@59846
   419
    error ("applicable_in: not impl. for " ^ Tactic.input_to_string (Tactic.Take_Inst ct'))
walther@59830
   420
  | applicable_in (p, p_) _ (m as Tactic.Subproblem (domID, pblID)) = 
walther@59830
   421
     if Pos.on_specification p_
walther@59830
   422
     then
walther@59846
   423
       Notappl (Tactic.input_to_string m ^ " not for pos " ^ pos'2str (p, p_))
walther@59829
   424
     else (*some fields filled later in LI*)
walther@59735
   425
       Appl (Tactic.Subproblem' ((domID, pblID, Celem.e_metID), [], 
walther@59861
   426
			   TermC.empty, [], ContextC.empty, Auto_Prog.subpbl domID pblID))
wneuper@59571
   427
  | applicable_in _ _ (Tactic.End_Subproblem) =
walther@59846
   428
    error ("applicable_in: not impl. for " ^ Tactic.input_to_string Tactic.End_Subproblem)
wneuper@59571
   429
  | applicable_in _ _ (Tactic.CAScmd ct') = 
walther@59846
   430
    error ("applicable_in: not impl. for " ^ Tactic.input_to_string (Tactic.CAScmd ct'))  
wneuper@59571
   431
  | applicable_in _ _ (Tactic.Split_And) = 
walther@59846
   432
    error ("applicable_in: not impl. for " ^ Tactic.input_to_string Tactic.Split_And)
wneuper@59571
   433
  | applicable_in _ _ (Tactic.Conclude_And) = 
walther@59846
   434
    error ("applicable_in: not impl. for " ^ Tactic.input_to_string Tactic.Conclude_And)
wneuper@59571
   435
  | applicable_in _ _ (Tactic.Split_Or) = 
walther@59846
   436
    error ("applicable_in: not impl. for " ^ Tactic.input_to_string Tactic.Split_Or)
wneuper@59571
   437
  | applicable_in _ _ (Tactic.Conclude_Or) = 
walther@59846
   438
    error ("applicable_in: not impl. for " ^ Tactic.input_to_string Tactic.Conclude_Or)
wneuper@59571
   439
  | applicable_in (p, p_) pt (Tactic.Begin_Trans) =
neuper@37906
   440
    let
wneuper@59285
   441
      val (f, _) = case p_ of   (*p 12.4.00 unnecessary, implizit Take in gen*)
wneuper@59285
   442
        Frm => (get_obj g_form pt p, (lev_on o lev_dn) p)
neuper@37906
   443
      | Res => ((fst o (get_obj g_result pt)) p, (lev_on o lev_dn o lev_on) p)
wneuper@59285
   444
      | _ => error ("applicable_in: call by " ^ pos'2str (p, p_));
walther@59735
   445
    in (Appl (Tactic.Begin_Trans' f))
walther@59861
   446
      handle _ => error ("applicable_in: Begin_Trans finds  syntaxerror in '" ^ UnparseC.term2str f ^ "'")
neuper@37906
   447
    end
wneuper@59571
   448
  | applicable_in (p, p_) pt (Tactic.End_Trans) = (*TODO: check parent branches*)
wneuper@59285
   449
    if p_ = Res 
walther@59735
   450
	  then Appl (Tactic.End_Trans' (get_obj g_result pt p))
walther@59735
   451
    else Notappl "'End_Trans' is not applicable at the beginning of a transitive sequence"
wneuper@59571
   452
  | applicable_in _ _ (Tactic.Begin_Sequ) = 
walther@59846
   453
    error ("applicable_in: not impl. for " ^ Tactic.input_to_string (Tactic.Begin_Sequ))
wneuper@59571
   454
  | applicable_in _ _ (Tactic.End_Sequ) = 
walther@59846
   455
    error ("applicable_in: not impl. for " ^ Tactic.input_to_string (Tactic.End_Sequ))
wneuper@59571
   456
  | applicable_in _ _ (Tactic.Split_Intersect) = 
walther@59846
   457
    error ("applicable_in: not impl. for " ^ Tactic.input_to_string (Tactic.Split_Intersect))
wneuper@59571
   458
  | applicable_in _ _ (Tactic.End_Intersect) = 
walther@59846
   459
    error ("applicable_in: not impl. for " ^ Tactic.input_to_string (Tactic.End_Intersect))
wneuper@59571
   460
  | applicable_in (p, p_) pt (m as Tactic.Check_elementwise pred) = 
walther@59722
   461
    if member op = [Pbl, Met] p_ 
walther@59846
   462
    then Notappl ((Tactic.input_to_string m) ^ " not for pos " ^ pos'2str (p, p_))
neuper@42394
   463
    else
neuper@42394
   464
      let 
neuper@42394
   465
        val pp = par_pblobj pt p; 
wneuper@59405
   466
        val thy' = get_obj g_domID pt pp;
wneuper@59405
   467
        val thy = Celem.assoc_thy thy'
neuper@42394
   468
        val metID = (get_obj g_metID pt pp)
walther@59722
   469
        val {crls, ...} =  Specify.get_met metID
wneuper@59285
   470
        val (f, asm) = case p_ of
wneuper@59285
   471
          Frm => (get_obj g_form pt p , [])
wneuper@59285
   472
        | Res => get_obj g_result pt p
wneuper@59285
   473
        | _ => error ("applicable_in: call by " ^ pos'2str (p, p_));
walther@59854
   474
        val vp = (ThyC.thy2ctxt thy, pred) |-> TermC.parseNEW |> the |> mk_set thy pt p f;
walther@59835
   475
      in
walther@59835
   476
        Appl (Tactic.Check_elementwise' (f, pred, (f, asm)))
neuper@42394
   477
      end
wneuper@59571
   478
  | applicable_in (p, p_) pt Tactic.Or_to_List = 
wneuper@59285
   479
    if member op = [Pbl, Met] p_ 
walther@59846
   480
    then Notappl ((Tactic.input_to_string Tactic.Or_to_List)^" not for pos "^(pos'2str (p,p_)))
wneuper@59285
   481
    else
wneuper@59285
   482
      let 
wneuper@59285
   483
        val f = case p_ of
wneuper@59285
   484
          Frm => get_obj g_form pt p
wneuper@59285
   485
    	  | Res => (fst o (get_obj g_result pt)) p
wneuper@59285
   486
        | _ => error ("applicable_in: call by " ^ pos'2str (p, p_));
walther@59603
   487
      in (let val ls = Prog_Expr.or2list f
walther@59735
   488
          in Appl (Tactic.Or_to_List' (f, ls)) end) 
walther@59861
   489
         handle _ => Notappl ("'Or_to_List' not applicable to " ^ UnparseC.term2str f)
wneuper@59285
   490
      end
wneuper@59571
   491
  | applicable_in _ _ Tactic.Collect_Trues = 
walther@59846
   492
    error ("applicable_in: not impl. for " ^ Tactic.input_to_string Tactic.Collect_Trues)
walther@59735
   493
  | applicable_in _ _ Tactic.Empty_Tac = Notappl "Empty_Tac is not applicable"
wneuper@59571
   494
  | applicable_in (p, p_) pt (Tactic.Tac id) =
wneuper@59285
   495
    let 
wneuper@59285
   496
      val pp = par_pblobj pt p; 
wneuper@59405
   497
      val thy' = get_obj g_domID pt pp;
wneuper@59405
   498
      val thy = Celem.assoc_thy thy';
wneuper@59285
   499
      val f = case p_ of
wneuper@59285
   500
         Frm => get_obj g_form pt p
wneuper@59285
   501
      | Pbl => error "applicable_in (p,Pbl) pt (Tac id): not at Pbl"
wneuper@59285
   502
  	  | Res => (fst o (get_obj g_result pt)) p
wneuper@59285
   503
      | _ => error ("applicable_in: call by " ^ pos'2str (p, p_));
wneuper@59285
   504
    in case id of
wneuper@59285
   505
      "subproblem_equation_dummy" =>
wneuper@59389
   506
  	  if TermC.is_expliceq f
walther@59861
   507
  	  then Appl (Tactic.Tac_ (thy, UnparseC.term2str f, id, "subproblem_equation_dummy (" ^ UnparseC.term2str f ^ ")"))
walther@59735
   508
  	  else Notappl "applicable only to equations made explicit"
wneuper@59285
   509
    | "solve_equation_dummy" =>
walther@59861
   510
  	  let val (id', f') = split_dummy (UnparseC.term2str f);
wneuper@59285
   511
  	  in
wneuper@59285
   512
  	    if id' <> "subproblem_equation_dummy"
walther@59735
   513
  	    then Notappl "no subproblem"
walther@59854
   514
  	    else if (ThyC.thy2ctxt thy, f') |-> TermC.parseNEW |> the |> TermC.is_expliceq
walther@59861
   515
  		    then Appl (Tactic.Tac_ (thy, UnparseC.term2str f, id, "[" ^ f' ^ "]"))
wneuper@59285
   516
  		    else error ("applicable_in: f= " ^ f')
wneuper@59285
   517
      end
walther@59861
   518
    | _ => Appl (Tactic.Tac_ (thy, UnparseC.term2str f, id, UnparseC.term2str f))
wneuper@59285
   519
    end
walther@59735
   520
  | applicable_in _ _ Tactic.End_Proof' = Appl Tactic.End_Proof''
walther@59846
   521
  | applicable_in _ _ m = error ("applicable_in called for " ^ Tactic.input_to_string m);
neuper@37906
   522
wneuper@59285
   523
fun tac2tac_ pt p m = 
wneuper@59285
   524
  case applicable_in p pt m of
walther@59735
   525
	  Appl m' => m' 
walther@59846
   526
  | Notappl _ => error ("tac2mstp': fails with" ^ Tactic.input_to_string m);
neuper@37906
   527
wneuper@59285
   528
end;