src/Pure/Isar/method.ML
changeset 20335 b5eca86ef9cc
parent 20289 ba7a7c56bed5
child 21579 abd2b4386a63
equal deleted inserted replaced
20334:60157137a0eb 20335:b5eca86ef9cc
    48   val rule: thm list -> method
    48   val rule: thm list -> method
    49   val erule: int -> thm list -> method
    49   val erule: int -> thm list -> method
    50   val drule: int -> thm list -> method
    50   val drule: int -> thm list -> method
    51   val frule: int -> thm list -> method
    51   val frule: int -> thm list -> method
    52   val iprover_tac: Proof.context -> int option -> int -> tactic
    52   val iprover_tac: Proof.context -> int option -> int -> tactic
    53   val bires_inst_tac: bool -> Proof.context -> (indexname * string) list ->
       
    54     thm -> int -> tactic
       
    55   val set_tactic: (Proof.context -> thm list -> tactic) -> unit
    53   val set_tactic: (Proof.context -> thm list -> tactic) -> unit
    56   val tactic: string -> Proof.context -> method
    54   val tactic: string -> Proof.context -> method
    57   type src
    55   type src
    58   datatype text =
    56   datatype text =
    59     Basic of (Proof.context -> method) |
    57     Basic of (Proof.context -> method) |
   335   SELECT_GOAL (DEEPEN (2, the_default 20 opt_lim) (intprover_tac ctxt [] 0) 4 1);
   333   SELECT_GOAL (DEEPEN (2, the_default 20 opt_lim) (intprover_tac ctxt [] 0) 4 1);
   336 
   334 
   337 end;
   335 end;
   338 
   336 
   339 
   337 
   340 (* rule_tac etc. -- refer to dynamic goal state!! *)   (* FIXME cleanup!! *)
       
   341 
       
   342 fun bires_inst_tac bires_flag ctxt insts thm =
       
   343   let
       
   344     val thy = ProofContext.theory_of ctxt;
       
   345     (* Separate type and term insts *)
       
   346     fun has_type_var ((x, _), _) = (case Symbol.explode x of
       
   347           "'"::cs => true | cs => false);
       
   348     val Tinsts = List.filter has_type_var insts;
       
   349     val tinsts = filter_out has_type_var insts;
       
   350     (* Tactic *)
       
   351     fun tac i st =
       
   352       let
       
   353         (* Preprocess state: extract environment information:
       
   354            - variables and their types
       
   355            - type variables and their sorts
       
   356            - parameters and their types *)
       
   357         val (types, sorts) = types_sorts st;
       
   358     (* Process type insts: Tinsts_env *)
       
   359     fun absent xi = error
       
   360           ("No such variable in theorem: " ^ Syntax.string_of_vname xi);
       
   361     val (rtypes, rsorts) = types_sorts thm;
       
   362     fun readT (xi, s) =
       
   363         let val S = case rsorts xi of SOME S => S | NONE => absent xi;
       
   364             val T = Sign.read_typ (thy, sorts) s;
       
   365             val U = TVar (xi, S);
       
   366         in if Sign.typ_instance thy (T, U) then (U, T)
       
   367            else error
       
   368              ("Instantiation of " ^ Syntax.string_of_vname xi ^ " fails")
       
   369         end;
       
   370     val Tinsts_env = map readT Tinsts;
       
   371     (* Preprocess rule: extract vars and their types, apply Tinsts *)
       
   372     fun get_typ xi =
       
   373       (case rtypes xi of
       
   374            SOME T => typ_subst_atomic Tinsts_env T
       
   375          | NONE => absent xi);
       
   376     val (xis, ss) = Library.split_list tinsts;
       
   377     val Ts = map get_typ xis;
       
   378         val (_, _, Bi, _) = dest_state(st,i)
       
   379         val params = Logic.strip_params Bi
       
   380                              (* params of subgoal i as string typ pairs *)
       
   381         val params = rev(Term.rename_wrt_term Bi params)
       
   382                            (* as they are printed: bound variables with *)
       
   383                            (* the same name are renamed during printing *)
       
   384         fun types' (a, ~1) = (case AList.lookup (op =) params a of
       
   385                 NONE => types (a, ~1)
       
   386               | some => some)
       
   387           | types' xi = types xi;
       
   388         fun internal x = is_some (types' (x, ~1));
       
   389         val used = Drule.add_used thm (Drule.add_used st []);
       
   390         val (ts, envT) =
       
   391           ProofContext.read_termTs_schematic ctxt internal types' sorts used (ss ~~ Ts);
       
   392         val envT' = map (fn (ixn, T) =>
       
   393           (TVar (ixn, the (rsorts ixn)), T)) envT @ Tinsts_env;
       
   394         val cenv =
       
   395           map
       
   396             (fn (xi, t) =>
       
   397               pairself (Thm.cterm_of thy) (Var (xi, fastype_of t), t))
       
   398             (distinct
       
   399               (fn ((x1, t1), (x2, t2)) => x1 = x2 andalso t1 aconv t2)
       
   400               (xis ~~ ts));
       
   401         (* Lift and instantiate rule *)
       
   402         val {maxidx, ...} = rep_thm st;
       
   403         val paramTs = map #2 params
       
   404         and inc = maxidx+1
       
   405         fun liftvar (Var ((a,j), T)) =
       
   406               Var((a, j+inc), paramTs ---> Logic.incr_tvar inc T)
       
   407           | liftvar t = raise TERM("Variable expected", [t]);
       
   408         fun liftterm t = list_abs_free
       
   409               (params, Logic.incr_indexes(paramTs,inc) t)
       
   410         fun liftpair (cv,ct) =
       
   411               (cterm_fun liftvar cv, cterm_fun liftterm ct)
       
   412         val lifttvar = pairself (ctyp_of thy o Logic.incr_tvar inc);
       
   413         val rule = Drule.instantiate
       
   414               (map lifttvar envT', map liftpair cenv)
       
   415               (Thm.lift_rule (Thm.cprem_of st i) thm)
       
   416       in
       
   417         if i > nprems_of st then no_tac st
       
   418         else st |>
       
   419           compose_tac (bires_flag, rule, nprems_of thm) i
       
   420       end
       
   421            handle TERM (msg,_)   => (warning msg; no_tac st)
       
   422                 | THM  (msg,_,_) => (warning msg; no_tac st);
       
   423   in tac end;
       
   424 
       
   425 local
       
   426 
       
   427 fun gen_inst _ tac _ (quant, ([], thms)) =
       
   428       METHOD (fn facts => quant (insert_tac facts THEN' tac thms))
       
   429   | gen_inst inst_tac _ ctxt (quant, (insts, [thm])) =
       
   430       METHOD (fn facts =>
       
   431         quant (insert_tac facts THEN' inst_tac ctxt insts thm))
       
   432   | gen_inst _ _ _ _ = error "Cannot have instantiations with multiple rules";
       
   433 
       
   434 in
       
   435 
       
   436 val res_inst_meth = gen_inst (bires_inst_tac false) Tactic.resolve_tac;
       
   437 
       
   438 val eres_inst_meth = gen_inst (bires_inst_tac true) Tactic.eresolve_tac;
       
   439 
       
   440 val cut_inst_meth =
       
   441   gen_inst
       
   442     (fn ctxt => fn insts => bires_inst_tac false ctxt insts o Tactic.make_elim_preserve)
       
   443     Tactic.cut_rules_tac;
       
   444 
       
   445 val dres_inst_meth =
       
   446   gen_inst
       
   447     (fn ctxt => fn insts => bires_inst_tac true ctxt insts o Tactic.make_elim_preserve)
       
   448     Tactic.dresolve_tac;
       
   449 
       
   450 val forw_inst_meth =
       
   451   gen_inst
       
   452     (fn ctxt => fn insts => fn rule =>
       
   453        bires_inst_tac false ctxt insts (Tactic.make_elim_preserve rule) THEN'
       
   454        assume_tac)
       
   455     Tactic.forward_tac;
       
   456 
       
   457 fun subgoal_tac ctxt sprop =
       
   458   DETERM o bires_inst_tac false ctxt [(("psi", 0), sprop)] cut_rl;
       
   459 
       
   460 fun subgoals_tac ctxt sprops = EVERY' (map (subgoal_tac ctxt) sprops);
       
   461 
       
   462 fun thin_tac ctxt s =
       
   463   bires_inst_tac true ctxt [(("V", 0), s)] thin_rl;
       
   464 
       
   465 end;
       
   466 
       
   467 
       
   468 (* ML tactics *)
   338 (* ML tactics *)
   469 
   339 
   470 val tactic_ref = ref ((fn _ => raise Match): Proof.context -> thm list -> tactic);
   340 val tactic_ref = ref ((fn _ => raise Match): Proof.context -> thm list -> tactic);
   471 fun set_tactic f = tactic_ref := f;
   341 fun set_tactic f = tactic_ref := f;
   472 
   342 
   668 (* tactic syntax *)
   538 (* tactic syntax *)
   669 
   539 
   670 fun nat_thms_args f = uncurry f oo
   540 fun nat_thms_args f = uncurry f oo
   671   (#2 oo syntax (Scan.lift (Scan.optional (Args.parens Args.nat) 0) -- Attrib.thms));
   541   (#2 oo syntax (Scan.lift (Scan.optional (Args.parens Args.nat) 0) -- Attrib.thms));
   672 
   542 
   673 val insts =
       
   674   Scan.optional
       
   675     (Args.enum1 "and" (Scan.lift (Args.name -- (Args.$$$ "=" |-- Args.!!! Args.name))) --|
       
   676       Scan.lift (Args.$$$ "in")) [] -- Attrib.thms;
       
   677 
       
   678 fun inst_args f src ctxt = f ctxt (#2 (syntax (Args.goal_spec HEADGOAL -- insts) src ctxt));
       
   679 
       
   680 val insts_var =
       
   681   Scan.optional
       
   682     (Args.enum1 "and" (Scan.lift (Args.var -- (Args.$$$ "=" |-- Args.!!! Args.name))) --|
       
   683       Scan.lift (Args.$$$ "in")) [] -- Attrib.thms;
       
   684 
       
   685 fun inst_args_var f src ctxt =
       
   686   f ctxt (#2 (syntax (Args.goal_spec HEADGOAL -- insts_var) src ctxt));
       
   687 
       
   688 fun goal_args' args tac src ctxt = #2 (syntax (Args.goal_spec HEADGOAL -- args >>
   543 fun goal_args' args tac src ctxt = #2 (syntax (Args.goal_spec HEADGOAL -- args >>
   689   (fn (quant, s) => SIMPLE_METHOD' quant (tac s))) src ctxt);
   544   (fn (quant, s) => SIMPLE_METHOD' quant (tac s))) src ctxt);
   690 
   545 
   691 fun goal_args args tac = goal_args' (Scan.lift args) tac;
   546 fun goal_args args tac = goal_args' (Scan.lift args) tac;
   692 
   547 
   693 fun goal_args_ctxt' args tac src ctxt =
   548 fun goal_args_ctxt' args tac src ctxt =
   694   #2 (syntax (Args.goal_spec HEADGOAL -- args >>
   549   #2 (syntax (Args.goal_spec HEADGOAL -- args >>
   695   (fn (quant, s) => SIMPLE_METHOD' quant (tac ctxt s))) src ctxt);
   550   (fn (quant, s) => SIMPLE_METHOD' quant (tac ctxt s))) src ctxt);
   696 
   551 
   697 fun goal_args_ctxt args tac = goal_args_ctxt' (Scan.lift args) tac;
   552 fun goal_args_ctxt args tac = goal_args_ctxt' (Scan.lift args) tac;
   698 
       
   699 
       
   700 (* misc tactic emulations *)
       
   701 
       
   702 val subgoal_meth = goal_args_ctxt (Scan.repeat1 Args.name) subgoals_tac;
       
   703 val thin_meth = goal_args_ctxt Args.name thin_tac;
       
   704 val rename_meth = goal_args (Scan.repeat1 Args.name) Tactic.rename_params_tac;
       
   705 val rotate_meth = goal_args (Scan.optional Args.int 1) Tactic.rotate_tac;
       
   706 
   553 
   707 
   554 
   708 (* theory setup *)
   555 (* theory setup *)
   709 
   556 
   710 val _ = Context.add_setup (add_methods
   557 val _ = Context.add_setup (add_methods
   724   ("drule", nat_thms_args drule, "apply rule in destruct manner (improper)"),
   571   ("drule", nat_thms_args drule, "apply rule in destruct manner (improper)"),
   725   ("frule", nat_thms_args frule, "apply rule in forward manner (improper)"),
   572   ("frule", nat_thms_args frule, "apply rule in forward manner (improper)"),
   726   ("this", no_args this, "apply current facts as rules"),
   573   ("this", no_args this, "apply current facts as rules"),
   727   ("fact", thms_ctxt_args fact, "composition by facts from context"),
   574   ("fact", thms_ctxt_args fact, "composition by facts from context"),
   728   ("assumption", ctxt_args assumption, "proof by assumption, preferring facts"),
   575   ("assumption", ctxt_args assumption, "proof by assumption, preferring facts"),
   729   ("rule_tac", inst_args_var res_inst_meth, "apply rule (dynamic instantiation)"),
   576   ("rename_tac", goal_args (Scan.repeat1 Args.name) Tactic.rename_params_tac,
   730   ("erule_tac", inst_args_var eres_inst_meth, "apply rule in elimination manner (dynamic instantiation)"),
   577     "rename parameters of goal (dynamic instantiation)"),
   731   ("drule_tac", inst_args_var dres_inst_meth, "apply rule in destruct manner (dynamic instantiation)"),
   578   ("rotate_tac", goal_args (Scan.optional Args.int 1) Tactic.rotate_tac,
   732   ("frule_tac", inst_args_var forw_inst_meth, "apply rule in forward manner (dynamic instantiation)"),
   579     "rotate assumptions of goal"),
   733   ("cut_tac", inst_args_var cut_inst_meth, "cut rule (dynamic instantiation)"),
       
   734   ("subgoal_tac", subgoal_meth, "insert subgoal (dynamic instantiation)"),
       
   735   ("thin_tac", thin_meth, "remove premise (dynamic instantiation)"),
       
   736   ("rename_tac", rename_meth, "rename parameters of goal (dynamic instantiation)"),
       
   737   ("rotate_tac", rotate_meth, "rotate assumptions of goal"),
       
   738   ("tactic", simple_args Args.name tactic, "ML tactic as proof method")]);
   580   ("tactic", simple_args Args.name tactic, "ML tactic as proof method")]);
   739 
   581 
   740 
   582 
   741 (*final declarations of this structure!*)
   583 (*final declarations of this structure!*)
   742 val unfold = unfold_meth;
   584 val unfold = unfold_meth;