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