src/HOL/Tools/induct_method.ML
changeset 8695 850e84526745
parent 8688 63b267d41b96
child 8815 187547eae4c5
equal deleted inserted replaced
8694:c1d0cc81f06c 8695:850e84526745
    14   val dest_local_rules: Proof.context ->
    14   val dest_local_rules: Proof.context ->
    15     {type_cases: (string * thm) list, set_cases: (string * thm) list,
    15     {type_cases: (string * thm) list, set_cases: (string * thm) list,
    16       type_induct: (string * thm) list, set_induct: (string * thm) list}
    16       type_induct: (string * thm) list, set_induct: (string * thm) list}
    17   val print_local_rules: Proof.context -> unit
    17   val print_local_rules: Proof.context -> unit
    18   val vars_of: term -> term list
    18   val vars_of: term -> term list
       
    19   val concls_of: thm -> term list
    19   val cases_type_global: string -> theory attribute
    20   val cases_type_global: string -> theory attribute
    20   val cases_set_global: string -> theory attribute
    21   val cases_set_global: string -> theory attribute
    21   val cases_type_local: string -> Proof.context attribute
    22   val cases_type_local: string -> Proof.context attribute
    22   val cases_set_local: string -> Proof.context attribute
    23   val cases_set_local: string -> Proof.context attribute
    23   val induct_type_global: string -> theory attribute
    24   val induct_type_global: string -> theory attribute
   139 
   140 
   140 
   141 
   141 
   142 
   142 (** misc utils **)
   143 (** misc utils **)
   143 
   144 
   144 (* terms *)
   145 (* thms and terms *)
       
   146 
       
   147 val concls_of = HOLogic.dest_conj o HOLogic.dest_Trueprop o Thm.concl_of;
   145 
   148 
   146 fun vars_of tm =        (*ordered left-to-right, preferring right!*)
   149 fun vars_of tm =        (*ordered left-to-right, preferring right!*)
   147   Term.foldl_aterms (fn (ts, t as Var _) => t :: ts | (ts, _) => ts) ([], tm)
   150   Term.foldl_aterms (fn (ts, t as Var _) => t :: ts | (ts, _) => ts) ([], tm)
   148   |> Library.distinct |> rev;
   151   |> Library.distinct |> rev;
   149 
   152 
   293 fun induct_tac (ctxt, (stripped, args)) facts =
   296 fun induct_tac (ctxt, (stripped, args)) facts =
   294   let
   297   let
   295     val sg = ProofContext.sign_of ctxt;
   298     val sg = ProofContext.sign_of ctxt;
   296     val cert = Thm.cterm_of sg;
   299     val cert = Thm.cterm_of sg;
   297 
   300 
       
   301     fun prep_var (x, Some t) = Some (cert x, cert t)
       
   302       | prep_var (_, None) = None;
       
   303 
   298     fun prep_inst (concl, ts) =
   304     fun prep_inst (concl, ts) =
   299       let val xs = vars_of concl; val n = length xs - length ts in
   305       let val xs = vars_of concl; val n = length xs - length ts in
   300         if n < 0 then error "More arguments given than in induction rule"
   306         if n < 0 then error "More variables than given than in induction rule"
   301         else map cert (Library.drop (n, xs)) ~~ map cert ts
   307         else mapfilter prep_var (Library.drop (n, xs) ~~ ts)
   302       end;
   308       end;
   303 
   309 
   304     fun inst_rule insts thm =
   310     fun inst_rule insts thm =
   305       Drule.cterm_instantiate (flat (map2 prep_inst
   311       let val concls = concls_of thm in
   306         (HOLogic.dest_conj (HOLogic.dest_Trueprop (Thm.concl_of thm)), insts))) thm;
   312         if length concls < length insts then
       
   313           error "More arguments than given than in induction rule"
       
   314         else Drule.cterm_instantiate (flat (map prep_inst (concls ~~ insts))) thm
       
   315       end;
   307 
   316 
   308     fun find_induct th =
   317     fun find_induct th =
   309       NetRules.may_unify (#2 (get_induct ctxt))
   318       NetRules.may_unify (#2 (get_induct ctxt))
   310         (Logic.strip_assums_concl (#prop (Thm.rep_thm th)));
   319         (Logic.strip_assums_concl (#prop (Thm.rep_thm th)));
   311 
   320 
   312     val rules =
   321     val rules =
   313       (case (args, facts) of
   322       (case (args, facts) of
   314         (([], None), []) => []
   323         (([], None), []) => []
   315       | ((insts, None), []) =>
   324       | ((insts, None), []) =>
   316           let val thms = map (induct_rule ctxt o last_elem) insts
   325           let val thms = map (induct_rule ctxt o last_elem o mapfilter I) insts
       
   326             handle Library.LIST _ => error "Unable to figure out type induction rule"
   317           in [(inst_rule insts (join_rules thms), RuleCases.get (#2 (hd thms)))] end
   327           in [(inst_rule insts (join_rules thms), RuleCases.get (#2 (hd thms)))] end
   318       | (([], None), th :: _) => map (RuleCases.add o #2) (find_induct th)
   328       | (([], None), th :: _) => map (RuleCases.add o #2) (find_induct th)
   319       | ((insts, None), th :: _) =>
   329       | ((insts, None), th :: _) =>
   320           (case find_induct th of	(*may instantiate first rule only!*)
   330           (case find_induct th of	(*may instantiate first rule only!*)
   321 	    (_, thm) :: _ => [(inst_rule insts thm, RuleCases.get thm)]
   331 	    (_, thm) :: _ => [(inst_rule insts thm, RuleCases.get thm)]
   390 val cases_rule = rule lookup_casesT lookup_casesS;
   400 val cases_rule = rule lookup_casesT lookup_casesS;
   391 val induct_rule = rule lookup_inductT lookup_inductS;
   401 val induct_rule = rule lookup_inductT lookup_inductS;
   392 
   402 
   393 val kind = (Args.$$$ typeN || Args.$$$ setN || Args.$$$ ruleN) -- Args.$$$ ":";
   403 val kind = (Args.$$$ typeN || Args.$$$ setN || Args.$$$ ruleN) -- Args.$$$ ":";
   394 val term = Scan.unless (Scan.lift kind) Args.local_term;
   404 val term = Scan.unless (Scan.lift kind) Args.local_term;
       
   405 val term_dummy = Scan.unless (Scan.lift kind)
       
   406   (Scan.lift (Args.$$$ "_") >> K None || Args.local_term >> Some);
   395 
   407 
   396 fun mode name =
   408 fun mode name =
   397   Scan.lift (Scan.optional (Args.$$$ name -- Args.$$$ ":" >> K true) false);
   409   Scan.lift (Scan.optional (Args.$$$ name -- Args.$$$ ":" >> K true) false);
   398 
   410 
   399 in
   411 in
   400 
   412 
   401 val cases_args =
   413 val cases_args = Method.syntax (mode simplifiedN -- (Scan.option term -- Scan.option cases_rule));
   402   Method.syntax (mode simplifiedN -- (Scan.option term -- Scan.option cases_rule));
   414 val induct_args = Method.syntax
   403 val induct_args =
   415   (mode strippedN -- (Args.and_list (Scan.repeat term_dummy) -- Scan.option induct_rule));
   404   Method.syntax (mode strippedN -- (Args.and_list (Scan.repeat1 term) -- Scan.option induct_rule));
       
   405 
   416 
   406 end;
   417 end;
   407 
   418 
   408 
   419 
   409 
   420