src/Pure/tactic.ML
changeset 1458 fd510875fb71
parent 1209 03dc596b3a18
child 1460 5a6f2aabd538
equal deleted inserted replaced
1457:ad856378ad62 1458:fd510875fb71
     1 (*  Title: 	tactic
     1 (*  Title:      tactic
     2     ID:         $Id$
     2     ID:         $Id$
     3     Author: 	Lawrence C Paulson, Cambridge University Computer Laboratory
     3     Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
     4     Copyright   1991  University of Cambridge
     4     Copyright   1991  University of Cambridge
     5 
     5 
     6 Tactics 
     6 Tactics 
     7 *)
     7 *)
     8 
     8 
    81   end
    81   end
    82 end;
    82 end;
    83 
    83 
    84 
    84 
    85 functor TacticFun (structure Logic: LOGIC and Drule: DRULE and 
    85 functor TacticFun (structure Logic: LOGIC and Drule: DRULE and 
    86 		   Tactical: TACTICAL and Net: NET
    86                    Tactical: TACTICAL and Net: NET
    87 	  sharing Drule.Thm = Tactical.Thm) : TACTIC = 
    87           sharing Drule.Thm = Tactical.Thm) : TACTIC = 
    88 struct
    88 struct
    89 structure Tactical = Tactical;
    89 structure Tactical = Tactical;
    90 structure Thm = Tactical.Thm;
    90 structure Thm = Tactical.Thm;
    91 structure Net = Net;
    91 structure Net = Net;
    92 structure Sequence = Thm.Sequence;
    92 structure Sequence = Thm.Sequence;
    95 in
    95 in
    96 
    96 
    97 (*Discover what goal is chosen:  SOMEGOAL(trace_goalno_tac tac) *)
    97 (*Discover what goal is chosen:  SOMEGOAL(trace_goalno_tac tac) *)
    98 fun trace_goalno_tac tf i = Tactic (fn state => 
    98 fun trace_goalno_tac tf i = Tactic (fn state => 
    99     case Sequence.pull(tapply(tf i, state)) of
    99     case Sequence.pull(tapply(tf i, state)) of
   100 	None    => Sequence.null
   100         None    => Sequence.null
   101       | seqcell => (prs("Subgoal " ^ string_of_int i ^ " selected\n"); 
   101       | seqcell => (prs("Subgoal " ^ string_of_int i ^ " selected\n"); 
   102     			 Sequence.seqof(fn()=> seqcell)));
   102                          Sequence.seqof(fn()=> seqcell)));
   103 
   103 
   104 fun string_of (a,0) = a
   104 fun string_of (a,0) = a
   105   | string_of (a,i) = a ^ "_" ^ string_of_int i;
   105   | string_of (a,i) = a ^ "_" ^ string_of_int i;
   106 
   106 
   107 (*convert all Vars in a theorem to Frees*)
   107 (*convert all Vars in a theorem to Frees*)
   108 fun freeze th =
   108 fun freeze th =
   109   let val fth = freezeT th
   109   let val fth = freezeT th
   110       val {prop,sign,...} = rep_thm fth
   110       val {prop,sign,...} = rep_thm fth
   111       fun mk_inst (Var(v,T)) = 
   111       fun mk_inst (Var(v,T)) = 
   112 	  (cterm_of sign (Var(v,T)),
   112           (cterm_of sign (Var(v,T)),
   113 	   cterm_of sign (Free(string_of v, T)))
   113            cterm_of sign (Free(string_of v, T)))
   114       val insts = map mk_inst (term_vars prop)
   114       val insts = map mk_inst (term_vars prop)
   115   in  instantiate ([],insts) fth  end;
   115   in  instantiate ([],insts) fth  end;
   116 
   116 
   117 (*Makes a rule by applying a tactic to an existing rule*)
   117 (*Makes a rule by applying a tactic to an existing rule*)
   118 fun rule_by_tactic (Tactic tf) rl =
   118 fun rule_by_tactic (Tactic tf) rl =
   119     case Sequence.pull(tf (freeze (standard rl))) of
   119     case Sequence.pull(tf (freeze (standard rl))) of
   120 	None        => raise THM("rule_by_tactic", 0, [rl])
   120         None        => raise THM("rule_by_tactic", 0, [rl])
   121       | Some(rl',_) => standard rl';
   121       | Some(rl',_) => standard rl';
   122  
   122  
   123 (*** Basic tactics ***)
   123 (*** Basic tactics ***)
   124 
   124 
   125 (*Makes a tactic whose effect on a state is given by thmfun: thm->thm seq.*)
   125 (*Makes a tactic whose effect on a state is given by thmfun: thm->thm seq.*)
   126 fun PRIMSEQ thmfun = Tactic (fn state => thmfun state
   126 fun PRIMSEQ thmfun = Tactic (fn state => thmfun state
   127 			                 handle THM _ => Sequence.null);
   127                                          handle THM _ => Sequence.null);
   128 
   128 
   129 (*Makes a tactic whose effect on a state is given by thmfun: thm->thm.*)
   129 (*Makes a tactic whose effect on a state is given by thmfun: thm->thm.*)
   130 fun PRIMITIVE thmfun = PRIMSEQ (Sequence.single o thmfun);
   130 fun PRIMITIVE thmfun = PRIMSEQ (Sequence.single o thmfun);
   131 
   131 
   132 (*** The following fail if the goal number is out of range:
   132 (*** The following fail if the goal number is out of range:
   162 
   162 
   163 (*Like forward_tac, but deletes the assumption after use.*)
   163 (*Like forward_tac, but deletes the assumption after use.*)
   164 fun dresolve_tac rls = eresolve_tac (map make_elim rls);
   164 fun dresolve_tac rls = eresolve_tac (map make_elim rls);
   165 
   165 
   166 (*Shorthand versions: for resolution with a single theorem*)
   166 (*Shorthand versions: for resolution with a single theorem*)
   167 fun rtac rl = resolve_tac [rl];
   167 fun rtac rl = rtac rl ;
   168 fun etac rl = eresolve_tac [rl];
   168 fun etac rl = etac rl ;
   169 fun dtac rl = dresolve_tac [rl];
   169 fun dtac rl = dtac rl ;
   170 val atac = assume_tac;
   170 val atac = assume_tac;
   171 
   171 
   172 (*Use an assumption or some rules ... A popular combination!*)
   172 (*Use an assumption or some rules ... A popular combination!*)
   173 fun ares_tac rules = assume_tac  ORELSE'  resolve_tac rules;
   173 fun ares_tac rules = assume_tac  ORELSE'  resolve_tac rules;
   174 
   174 
   183 
   183 
   184 (*Lift and instantiate a rule wrt the given state and subgoal number *)
   184 (*Lift and instantiate a rule wrt the given state and subgoal number *)
   185 fun lift_inst_rule (state, i, sinsts, rule) =
   185 fun lift_inst_rule (state, i, sinsts, rule) =
   186 let val {maxidx,sign,...} = rep_thm state
   186 let val {maxidx,sign,...} = rep_thm state
   187     val (_, _, Bi, _) = dest_state(state,i)
   187     val (_, _, Bi, _) = dest_state(state,i)
   188     val params = Logic.strip_params Bi	        (*params of subgoal i*)
   188     val params = Logic.strip_params Bi          (*params of subgoal i*)
   189     val params = rev(rename_wrt_term Bi params) (*as they are printed*)
   189     val params = rev(rename_wrt_term Bi params) (*as they are printed*)
   190     val paramTs = map #2 params
   190     val paramTs = map #2 params
   191     and inc = maxidx+1
   191     and inc = maxidx+1
   192     fun liftvar (Var ((a,j), T)) = Var((a, j+inc), paramTs---> incr_tvar inc T)
   192     fun liftvar (Var ((a,j), T)) = Var((a, j+inc), paramTs---> incr_tvar inc T)
   193       | liftvar t = raise TERM("Variable expected", [t]);
   193       | liftvar t = raise TERM("Variable expected", [t]);
   194     fun liftterm t = list_abs_free (params, 
   194     fun liftterm t = list_abs_free (params, 
   195 				    Logic.incr_indexes(paramTs,inc) t)
   195                                     Logic.incr_indexes(paramTs,inc) t)
   196     (*Lifts instantiation pair over params*)
   196     (*Lifts instantiation pair over params*)
   197     fun liftpair (cv,ct) = (cterm_fun liftvar cv, cterm_fun liftterm ct)
   197     fun liftpair (cv,ct) = (cterm_fun liftvar cv, cterm_fun liftterm ct)
   198     fun lifttvar((a,i),ctyp) =
   198     fun lifttvar((a,i),ctyp) =
   199 	let val {T,sign} = rep_ctyp ctyp
   199         let val {T,sign} = rep_ctyp ctyp
   200 	in  ((a,i+inc), ctyp_of sign (incr_tvar inc T)) end
   200         in  ((a,i+inc), ctyp_of sign (incr_tvar inc T)) end
   201     val rts = types_sorts rule and (types,sorts) = types_sorts state
   201     val rts = types_sorts rule and (types,sorts) = types_sorts state
   202     fun types'(a,~1) = (case assoc(params,a) of None => types(a,~1) | sm => sm)
   202     fun types'(a,~1) = (case assoc(params,a) of None => types(a,~1) | sm => sm)
   203       | types'(ixn) = types ixn;
   203       | types'(ixn) = types ixn;
   204     val used = add_term_tvarnames
   204     val used = add_term_tvarnames
   205                   (#prop(rep_thm state) $ #prop(rep_thm rule),[])
   205                   (#prop(rep_thm state) $ #prop(rep_thm rule),[])
   213      subgoal.  Fails if "i" is out of range.  ***)
   213      subgoal.  Fails if "i" is out of range.  ***)
   214 
   214 
   215 (*compose version: arguments are as for bicompose.*)
   215 (*compose version: arguments are as for bicompose.*)
   216 fun compose_inst_tac sinsts (bires_flg, rule, nsubgoal) i =
   216 fun compose_inst_tac sinsts (bires_flg, rule, nsubgoal) i =
   217   STATE ( fn state => 
   217   STATE ( fn state => 
   218 	   compose_tac (bires_flg, lift_inst_rule (state, i, sinsts, rule),
   218            compose_tac (bires_flg, lift_inst_rule (state, i, sinsts, rule),
   219 			nsubgoal) i
   219                         nsubgoal) i
   220 	   handle TERM (msg,_) => (writeln msg;  no_tac)
   220            handle TERM (msg,_) => (writeln msg;  no_tac)
   221 		| THM  (msg,_,_) => (writeln msg;  no_tac) );
   221                 | THM  (msg,_,_) => (writeln msg;  no_tac) );
   222 
   222 
   223 (*"Resolve" version.  Note: res_inst_tac cannot behave sensibly if the
   223 (*"Resolve" version.  Note: res_inst_tac cannot behave sensibly if the
   224   terms that are substituted contain (term or type) unknowns from the
   224   terms that are substituted contain (term or type) unknowns from the
   225   goal, because it is unable to instantiate goal unknowns at the same time.
   225   goal, because it is unable to instantiate goal unknowns at the same time.
   226 
   226 
   240   increment revcut_rl instead.*)
   240   increment revcut_rl instead.*)
   241 fun make_elim_preserve rl = 
   241 fun make_elim_preserve rl = 
   242   let val {maxidx,...} = rep_thm rl
   242   let val {maxidx,...} = rep_thm rl
   243       fun cvar ixn = cterm_of Sign.proto_pure (Var(ixn,propT));
   243       fun cvar ixn = cterm_of Sign.proto_pure (Var(ixn,propT));
   244       val revcut_rl' = 
   244       val revcut_rl' = 
   245 	  instantiate ([],  [(cvar("V",0), cvar("V",maxidx+1)),
   245           instantiate ([],  [(cvar("V",0), cvar("V",maxidx+1)),
   246 			     (cvar("W",0), cvar("W",maxidx+1))]) revcut_rl
   246                              (cvar("W",0), cvar("W",maxidx+1))]) revcut_rl
   247       val arg = (false, rl, nprems_of rl)
   247       val arg = (false, rl, nprems_of rl)
   248       val [th] = Sequence.list_of_s (bicompose false arg 1 revcut_rl')
   248       val [th] = Sequence.list_of_s (bicompose false arg 1 revcut_rl')
   249   in  th  end
   249   in  th  end
   250   handle Bind => raise THM("make_elim_preserve", 1, [rl]);
   250   handle Bind => raise THM("make_elim_preserve", 1, [rl]);
   251 
   251 
   260 
   260 
   261 (*** Applications of cut_rl ***)
   261 (*** Applications of cut_rl ***)
   262 
   262 
   263 (*Used by metacut_tac*)
   263 (*Used by metacut_tac*)
   264 fun bires_cut_tac arg i =
   264 fun bires_cut_tac arg i =
   265     resolve_tac [cut_rl] i  THEN  biresolve_tac arg (i+1) ;
   265     rtac cut_rl i  THEN  biresolve_tac arg (i+1) ;
   266 
   266 
   267 (*The conclusion of the rule gets assumed in subgoal i,
   267 (*The conclusion of the rule gets assumed in subgoal i,
   268   while subgoal i+1,... are the premises of the rule.*)
   268   while subgoal i+1,... are the premises of the rule.*)
   269 fun metacut_tac rule = bires_cut_tac [(false,rule)];
   269 fun metacut_tac rule = bires_cut_tac [(false,rule)];
   270 
   270 
   271 (*Recognizes theorems that are not rules, but simple propositions*)
   271 (*Recognizes theorems that are not rules, but simple propositions*)
   272 fun is_fact rl =
   272 fun is_fact rl =
   273     case prems_of rl of
   273     case prems_of rl of
   274 	[] => true  |  _::_ => false;
   274         [] => true  |  _::_ => false;
   275 
   275 
   276 (*"Cut" all facts from theorem list into the goal as assumptions. *)
   276 (*"Cut" all facts from theorem list into the goal as assumptions. *)
   277 fun cut_facts_tac ths i =
   277 fun cut_facts_tac ths i =
   278     EVERY (map (fn th => metacut_tac th i) (filter is_fact ths));
   278     EVERY (map (fn th => metacut_tac th i) (filter is_fact ths));
   279 
   279 
   285 
   285 
   286 
   286 
   287 (**** Indexing and filtering of theorems ****)
   287 (**** Indexing and filtering of theorems ****)
   288 
   288 
   289 (*Returns the list of potentially resolvable theorems for the goal "prem",
   289 (*Returns the list of potentially resolvable theorems for the goal "prem",
   290 	using the predicate  could(subgoal,concl).
   290         using the predicate  could(subgoal,concl).
   291   Resulting list is no longer than "limit"*)
   291   Resulting list is no longer than "limit"*)
   292 fun filter_thms could (limit, prem, ths) =
   292 fun filter_thms could (limit, prem, ths) =
   293   let val pb = Logic.strip_assums_concl prem;   (*delete assumptions*)
   293   let val pb = Logic.strip_assums_concl prem;   (*delete assumptions*)
   294       fun filtr (limit, []) = []
   294       fun filtr (limit, []) = []
   295 	| filtr (limit, th::ths) =
   295         | filtr (limit, th::ths) =
   296 	    if limit=0 then  []
   296             if limit=0 then  []
   297 	    else if could(pb, concl_of th)  then th :: filtr(limit-1, ths)
   297             else if could(pb, concl_of th)  then th :: filtr(limit-1, ths)
   298 	    else filtr(limit,ths)
   298             else filtr(limit,ths)
   299   in  filtr(limit,ths)  end;
   299   in  filtr(limit,ths)  end;
   300 
   300 
   301 
   301 
   302 (*** biresolution and resolution using nets ***)
   302 (*** biresolution and resolution using nets ***)
   303 
   303 
   318 val orderlist = untaglist o sort (fn(x,y)=> #1 x < #1 y); 
   318 val orderlist = untaglist o sort (fn(x,y)=> #1 x < #1 y); 
   319 
   319 
   320 (*insert one tagged brl into the pair of nets*)
   320 (*insert one tagged brl into the pair of nets*)
   321 fun insert_tagged_brl (kbrl as (k,(eres,th)), (inet,enet)) =
   321 fun insert_tagged_brl (kbrl as (k,(eres,th)), (inet,enet)) =
   322     if eres then 
   322     if eres then 
   323 	case prems_of th of
   323         case prems_of th of
   324 	    prem::_ => (inet, Net.insert_term ((prem,kbrl), enet, K false))
   324             prem::_ => (inet, Net.insert_term ((prem,kbrl), enet, K false))
   325 	  | [] => error"insert_tagged_brl: elimination rule with no premises"
   325           | [] => error"insert_tagged_brl: elimination rule with no premises"
   326     else (Net.insert_term ((concl_of th, kbrl), inet, K false), enet);
   326     else (Net.insert_term ((concl_of th, kbrl), inet, K false), enet);
   327 
   327 
   328 (*build a pair of nets for biresolution*)
   328 (*build a pair of nets for biresolution*)
   329 fun build_netpair netpair brls = 
   329 fun build_netpair netpair brls = 
   330     foldr insert_tagged_brl (taglist 1 brls, netpair);
   330     foldr insert_tagged_brl (taglist 1 brls, netpair);
   364 fun filt_resolution_from_net_tac match pred net =
   364 fun filt_resolution_from_net_tac match pred net =
   365   SUBGOAL
   365   SUBGOAL
   366     (fn (prem,i) =>
   366     (fn (prem,i) =>
   367       let val krls = Net.unify_term net (Logic.strip_assums_concl prem)
   367       let val krls = Net.unify_term net (Logic.strip_assums_concl prem)
   368       in 
   368       in 
   369 	 if pred krls  
   369          if pred krls  
   370          then PRIMSEQ
   370          then PRIMSEQ
   371 		(biresolution match (map (pair false) (orderlist krls)) i)
   371                 (biresolution match (map (pair false) (orderlist krls)) i)
   372          else no_tac
   372          else no_tac
   373       end);
   373       end);
   374 
   374 
   375 (*Resolve the subgoal using the rules (making a net) unless too flexible,
   375 (*Resolve the subgoal using the rules (making a net) unless too flexible,
   376    which means more than maxr rules are unifiable.      *)
   376    which means more than maxr rules are unifiable.      *)
   412 fun rewrite_tac defs = PRIMITIVE(rewrite_rule defs);
   412 fun rewrite_tac defs = PRIMITIVE(rewrite_rule defs);
   413 
   413 
   414 (*Rewrite subgoals only, not main goal. *)
   414 (*Rewrite subgoals only, not main goal. *)
   415 fun rewrite_goals_tac defs = PRIMITIVE (rewrite_goals_rule defs);
   415 fun rewrite_goals_tac defs = PRIMITIVE (rewrite_goals_rule defs);
   416 
   416 
   417 fun rewtac def = rewrite_goals_tac [def];
   417 fun rewtac def = rewtac def;
   418 
   418 
   419 
   419 
   420 (*** Tactic for folding definitions, handling critical pairs ***)
   420 (*** Tactic for folding definitions, handling critical pairs ***)
   421 
   421 
   422 (*The depth of nesting in a term*)
   422 (*The depth of nesting in a term*)
   449 fun rename_tac str i = 
   449 fun rename_tac str i = 
   450   let val cs = explode str 
   450   let val cs = explode str 
   451   in  
   451   in  
   452   if !Logic.auto_rename 
   452   if !Logic.auto_rename 
   453   then (writeln"Note: setting Logic.auto_rename := false"; 
   453   then (writeln"Note: setting Logic.auto_rename := false"; 
   454 	Logic.auto_rename := false)
   454         Logic.auto_rename := false)
   455   else ();
   455   else ();
   456   case #2 (take_prefix (is_letdig orf is_blank) cs) of
   456   case #2 (take_prefix (is_letdig orf is_blank) cs) of
   457       [] => PRIMITIVE (rename_params_rule (scanwords is_letdig cs, i))
   457       [] => PRIMITIVE (rename_params_rule (scanwords is_letdig cs, i))
   458     | c::_ => error ("Illegal character: " ^ c)
   458     | c::_ => error ("Illegal character: " ^ c)
   459   end;
   459   end;