src/HOL/Tools/Function/function.ML
changeset 34232 36a2a3029fd3
parent 34231 da4d7d40f2f9
child 34950 1f5e55eb821c
equal deleted inserted replaced
34231:da4d7d40f2f9 34232:36a2a3029fd3
     5 Isar commands.
     5 Isar commands.
     6 *)
     6 *)
     7 
     7 
     8 signature FUNCTION =
     8 signature FUNCTION =
     9 sig
     9 sig
    10     include FUNCTION_DATA
    10   include FUNCTION_DATA
    11 
    11 
    12     val add_function :  (binding * typ option * mixfix) list
    12   val add_function: (binding * typ option * mixfix) list ->
    13                        -> (Attrib.binding * term) list
    13     (Attrib.binding * term) list -> Function_Common.function_config ->
    14                        -> Function_Common.function_config
    14     local_theory -> Proof.state
    15                        -> local_theory
    15 
    16                        -> Proof.state
    16   val add_function_cmd: (binding * string option * mixfix) list ->
    17     val add_function_cmd :  (binding * string option * mixfix) list
    17     (Attrib.binding * string) list -> Function_Common.function_config ->
    18                       -> (Attrib.binding * string) list
    18     local_theory -> Proof.state
    19                       -> Function_Common.function_config
    19 
    20                       -> local_theory
    20   val termination_proof : term option -> local_theory -> Proof.state
    21                       -> Proof.state
    21   val termination_proof_cmd : string option -> local_theory -> Proof.state
    22 
    22 
    23     val termination_proof : term option -> local_theory -> Proof.state
    23   val setup : theory -> theory
    24     val termination_proof_cmd : string option -> local_theory -> Proof.state
    24   val get_congs : Proof.context -> thm list
    25 
    25 
    26     val setup : theory -> theory
    26   val get_info : Proof.context -> term -> info
    27     val get_congs : Proof.context -> thm list
       
    28 
       
    29     val get_info : Proof.context -> term -> info
       
    30 end
    27 end
    31 
    28 
    32 
    29 
    33 structure Function : FUNCTION =
    30 structure Function : FUNCTION =
    34 struct
    31 struct
    35 
    32 
    36 open Function_Lib
    33 open Function_Lib
    37 open Function_Common
    34 open Function_Common
    38 
    35 
    39 val simp_attribs = map (Attrib.internal o K)
    36 val simp_attribs = map (Attrib.internal o K)
    40     [Simplifier.simp_add,
    37   [Simplifier.simp_add,
    41      Code.add_default_eqn_attribute,
    38    Code.add_default_eqn_attribute,
    42      Nitpick_Simps.add]
    39    Nitpick_Simps.add]
    43 
    40 
    44 val psimp_attribs = map (Attrib.internal o K)
    41 val psimp_attribs = map (Attrib.internal o K)
    45     [Simplifier.simp_add,
    42   [Simplifier.simp_add,
    46      Nitpick_Psimps.add]
    43    Nitpick_Psimps.add]
    47 
    44 
    48 fun mk_defname fixes = fixes |> map (fst o fst) |> space_implode "_"
    45 fun mk_defname fixes = fixes |> map (fst o fst) |> space_implode "_"
    49 
    46 
    50 fun add_simps fnames post sort extra_qualify label mod_binding moreatts simps lthy =
    47 fun add_simps fnames post sort extra_qualify label mod_binding moreatts
    51     let
    48   simps lthy =
    52       val spec = post simps
    49   let
    53                    |> map (apfst (apsnd (fn ats => moreatts @ ats)))
    50     val spec = post simps
    54                    |> map (apfst (apfst extra_qualify))
    51       |> map (apfst (apsnd (fn ats => moreatts @ ats)))
    55 
    52       |> map (apfst (apfst extra_qualify))
    56       val (saved_spec_simps, lthy) =
    53 
    57         fold_map Local_Theory.note spec lthy
    54     val (saved_spec_simps, lthy) =
    58 
    55       fold_map Local_Theory.note spec lthy
    59       val saved_simps = maps snd saved_spec_simps
    56 
    60       val simps_by_f = sort saved_simps
    57     val saved_simps = maps snd saved_spec_simps
    61 
    58     val simps_by_f = sort saved_simps
    62       fun add_for_f fname simps =
    59 
    63         Local_Theory.note
    60     fun add_for_f fname simps =
    64           ((mod_binding (Binding.qualify true fname (Binding.name label)), []), simps)
    61       Local_Theory.note
    65         #> snd
    62         ((mod_binding (Binding.qualify true fname (Binding.name label)), []), simps)
    66     in
    63       #> snd
    67       (saved_simps,
    64   in
    68        fold2 add_for_f fnames simps_by_f lthy)
    65     (saved_simps, fold2 add_for_f fnames simps_by_f lthy)
    69     end
    66   end
    70 
    67 
    71 fun gen_add_function is_external prep default_constraint fixspec eqns config lthy =
    68 fun gen_add_function is_external prep default_constraint fixspec eqns config lthy =
    72     let
    69   let
    73       val constrn_fxs = map (fn (b, T, mx) => (b, SOME (the_default default_constraint T), mx))
    70     val constrn_fxs = map (fn (b, T, mx) => (b, SOME (the_default default_constraint T), mx))
    74       val ((fixes0, spec0), ctxt') = prep (constrn_fxs fixspec) eqns lthy
    71     val ((fixes0, spec0), ctxt') = prep (constrn_fxs fixspec) eqns lthy
    75       val fixes = map (apfst (apfst Binding.name_of)) fixes0;
    72     val fixes = map (apfst (apfst Binding.name_of)) fixes0;
    76       val spec = map (fn (bnd, prop) => (bnd, [prop])) spec0;
    73     val spec = map (fn (bnd, prop) => (bnd, [prop])) spec0;
    77       val (eqs, post, sort_cont, cnames) = get_preproc lthy config ctxt' fixes spec
    74     val (eqs, post, sort_cont, cnames) = get_preproc lthy config ctxt' fixes spec
    78 
    75 
    79       val defname = mk_defname fixes
    76     val defname = mk_defname fixes
    80       val FunctionConfig {partials, ...} = config
    77     val FunctionConfig {partials, ...} = config
    81 
    78 
    82       val ((goalstate, cont), lthy) =
    79     val ((goalstate, cont), lthy) =
    83           Function_Mutual.prepare_function_mutual config defname fixes eqs lthy
    80       Function_Mutual.prepare_function_mutual config defname fixes eqs lthy
    84 
    81 
    85       fun afterqed [[proof]] lthy =
    82     fun afterqed [[proof]] lthy =
       
    83       let
       
    84         val FunctionResult {fs, R, psimps, trsimps,  simple_pinducts,
       
    85           termination, domintros, cases, ...} =
       
    86           cont (Thm.close_derivation proof)
       
    87 
       
    88         val fnames = map (fst o fst) fixes
       
    89         fun qualify n = Binding.name n
       
    90           |> Binding.qualify true defname
       
    91         val conceal_partial = if partials then I else Binding.conceal
       
    92 
       
    93         val addsmps = add_simps fnames post sort_cont
       
    94 
       
    95         val (((psimps', pinducts'), (_, [termination'])), lthy) =
       
    96           lthy
       
    97           |> addsmps (conceal_partial o Binding.qualify false "partial")
       
    98                "psimps" conceal_partial psimp_attribs psimps
       
    99           ||> fold_option (snd oo addsmps I "simps" I simp_attribs) trsimps
       
   100           ||>> Local_Theory.note ((conceal_partial (qualify "pinduct"),
       
   101                  [Attrib.internal (K (Rule_Cases.case_names cnames)),
       
   102                   Attrib.internal (K (Rule_Cases.consumes 1)),
       
   103                   Attrib.internal (K (Induct.induct_pred ""))]), simple_pinducts)
       
   104           ||>> Local_Theory.note ((Binding.conceal (qualify "termination"), []), [termination])
       
   105           ||> (snd o Local_Theory.note ((qualify "cases",
       
   106                  [Attrib.internal (K (Rule_Cases.case_names cnames))]), [cases]))
       
   107           ||> fold_option (snd oo curry Local_Theory.note (qualify "domintros", [])) domintros
       
   108 
       
   109         val info = { add_simps=addsmps, case_names=cnames, psimps=psimps',
       
   110           pinducts=snd pinducts', simps=NONE, inducts=NONE, termination=termination',
       
   111           fs=fs, R=R, defname=defname, is_partial=true }
       
   112 
       
   113         val _ =
       
   114           if not is_external then ()
       
   115           else Specification.print_consts lthy (K false) (map fst fixes)
       
   116       in
       
   117         lthy
       
   118         |> Local_Theory.declaration false (add_function_data o morph_function_data info)
       
   119       end
       
   120   in
       
   121     lthy
       
   122     |> Proof.theorem_i NONE afterqed [[(Logic.unprotect (concl_of goalstate), [])]]
       
   123     |> Proof.refine (Method.primitive_text (fn _ => goalstate)) |> Seq.hd
       
   124   end
       
   125 
       
   126 val add_function =
       
   127   gen_add_function false Specification.check_spec (TypeInfer.anyT HOLogic.typeS)
       
   128 val add_function_cmd = gen_add_function true Specification.read_spec "_::type"
       
   129 
       
   130 fun gen_termination_proof prep_term raw_term_opt lthy =
       
   131   let
       
   132     val term_opt = Option.map (prep_term lthy) raw_term_opt
       
   133     val info = the (case term_opt of
       
   134                       SOME t => (import_function_data t lthy
       
   135                         handle Option.Option =>
       
   136                           error ("Not a function: " ^ quote (Syntax.string_of_term lthy t)))
       
   137                     | NONE => (import_last_function lthy handle Option.Option => error "Not a function"))
       
   138 
       
   139       val { termination, fs, R, add_simps, case_names, psimps,
       
   140         pinducts, defname, ...} = info
       
   141       val domT = domain_type (fastype_of R)
       
   142       val goal = HOLogic.mk_Trueprop
       
   143                    (HOLogic.mk_all ("x", domT, mk_acc domT R $ Free ("x", domT)))
       
   144       fun afterqed [[totality]] lthy =
    86         let
   145         let
    87           val FunctionResult {fs, R, psimps, trsimps,  simple_pinducts, termination,
   146           val totality = Thm.close_derivation totality
    88                             domintros, cases, ...} =
   147           val remove_domain_condition =
    89           cont (Thm.close_derivation proof)
   148             full_simplify (HOL_basic_ss addsimps [totality, True_implies_equals])
    90 
   149           val tsimps = map remove_domain_condition psimps
    91           val fnames = map (fst o fst) fixes
   150           val tinduct = map remove_domain_condition pinducts
       
   151 
    92           fun qualify n = Binding.name n
   152           fun qualify n = Binding.name n
    93             |> Binding.qualify true defname
   153             |> Binding.qualify true defname
    94           val conceal_partial = if partials then I else Binding.conceal
       
    95 
       
    96           val addsmps = add_simps fnames post sort_cont
       
    97 
       
    98           val (((psimps', pinducts'), (_, [termination'])), lthy) =
       
    99             lthy
       
   100             |> addsmps (conceal_partial o Binding.qualify false "partial")
       
   101                  "psimps" conceal_partial psimp_attribs psimps
       
   102             ||> fold_option (snd oo addsmps I "simps" I simp_attribs) trsimps
       
   103             ||>> Local_Theory.note ((conceal_partial (qualify "pinduct"),
       
   104                    [Attrib.internal (K (Rule_Cases.case_names cnames)),
       
   105                     Attrib.internal (K (Rule_Cases.consumes 1)),
       
   106                     Attrib.internal (K (Induct.induct_pred ""))]), simple_pinducts)
       
   107             ||>> Local_Theory.note ((Binding.conceal (qualify "termination"), []), [termination])
       
   108             ||> (snd o Local_Theory.note ((qualify "cases",
       
   109                    [Attrib.internal (K (Rule_Cases.case_names cnames))]), [cases]))
       
   110             ||> fold_option (snd oo curry Local_Theory.note (qualify "domintros", [])) domintros
       
   111 
       
   112           val info = { add_simps=addsmps, case_names=cnames, psimps=psimps',
       
   113             pinducts=snd pinducts', simps=NONE, inducts=NONE, termination=termination',
       
   114             fs=fs, R=R, defname=defname, is_partial=true }
       
   115 
       
   116           val _ =
       
   117             if not is_external then ()
       
   118             else Specification.print_consts lthy (K false) (map fst fixes)
       
   119         in
   154         in
   120           lthy
   155           lthy
   121           |> Local_Theory.declaration false (add_function_data o morph_function_data info)
   156           |> add_simps I "simps" I simp_attribs tsimps
       
   157           ||>> Local_Theory.note
       
   158              ((qualify "induct",
       
   159                [Attrib.internal (K (Rule_Cases.case_names case_names))]),
       
   160               tinduct)
       
   161           |-> (fn (simps, (_, inducts)) =>
       
   162             let val info' = { is_partial=false, defname=defname, add_simps=add_simps,
       
   163               case_names=case_names, fs=fs, R=R, psimps=psimps, pinducts=pinducts,
       
   164               simps=SOME simps, inducts=SOME inducts, termination=termination }
       
   165             in
       
   166               Local_Theory.declaration false (add_function_data o morph_function_data info')
       
   167             end)
   122         end
   168         end
   123     in
   169   in
   124       lthy
   170     lthy
   125         |> Proof.theorem_i NONE afterqed [[(Logic.unprotect (concl_of goalstate), [])]]
   171     |> ProofContext.note_thmss ""
   126         |> Proof.refine (Method.primitive_text (fn _ => goalstate)) |> Seq.hd
   172        [((Binding.empty, [Context_Rules.rule_del]), [([allI], [])])] |> snd
   127     end
   173     |> ProofContext.note_thmss ""
   128 
   174        [((Binding.empty, [Context_Rules.intro_bang (SOME 1)]), [([allI], [])])] |> snd
   129 val add_function = gen_add_function false Specification.check_spec (TypeInfer.anyT HOLogic.typeS)
   175     |> ProofContext.note_thmss ""
   130 val add_function_cmd = gen_add_function true Specification.read_spec "_::type"
   176        [((Binding.name "termination", [Context_Rules.intro_bang (SOME 0)]),
   131 
   177          [([Goal.norm_result termination], [])])] |> snd
   132 fun gen_termination_proof prep_term raw_term_opt lthy =
   178     |> Proof.theorem_i NONE afterqed [[(goal, [])]]
   133     let
   179   end
   134       val term_opt = Option.map (prep_term lthy) raw_term_opt
       
   135       val info = the (case term_opt of
       
   136                         SOME t => (import_function_data t lthy
       
   137                           handle Option.Option =>
       
   138                             error ("Not a function: " ^ quote (Syntax.string_of_term lthy t)))
       
   139                       | NONE => (import_last_function lthy handle Option.Option => error "Not a function"))
       
   140 
       
   141         val { termination, fs, R, add_simps, case_names, psimps,
       
   142           pinducts, defname, ...} = info
       
   143         val domT = domain_type (fastype_of R)
       
   144         val goal = HOLogic.mk_Trueprop
       
   145                      (HOLogic.mk_all ("x", domT, mk_acc domT R $ Free ("x", domT)))
       
   146         fun afterqed [[totality]] lthy =
       
   147           let
       
   148             val totality = Thm.close_derivation totality
       
   149             val remove_domain_condition =
       
   150               full_simplify (HOL_basic_ss addsimps [totality, True_implies_equals])
       
   151             val tsimps = map remove_domain_condition psimps
       
   152             val tinduct = map remove_domain_condition pinducts
       
   153 
       
   154             fun qualify n = Binding.name n
       
   155               |> Binding.qualify true defname
       
   156           in
       
   157             lthy
       
   158             |> add_simps I "simps" I simp_attribs tsimps
       
   159             ||>> Local_Theory.note
       
   160                ((qualify "induct",
       
   161                  [Attrib.internal (K (Rule_Cases.case_names case_names))]),
       
   162                 tinduct)
       
   163             |-> (fn (simps, (_, inducts)) =>
       
   164               let val info' = { is_partial=false, defname=defname, add_simps=add_simps,
       
   165                 case_names=case_names, fs=fs, R=R, psimps=psimps, pinducts=pinducts,
       
   166                 simps=SOME simps, inducts=SOME inducts, termination=termination }
       
   167               in
       
   168                 Local_Theory.declaration false (add_function_data o morph_function_data info')
       
   169               end)
       
   170           end
       
   171     in
       
   172       lthy
       
   173       |> ProofContext.note_thmss ""
       
   174          [((Binding.empty, [Context_Rules.rule_del]), [([allI], [])])] |> snd
       
   175       |> ProofContext.note_thmss ""
       
   176          [((Binding.empty, [Context_Rules.intro_bang (SOME 1)]), [([allI], [])])] |> snd
       
   177       |> ProofContext.note_thmss ""
       
   178          [((Binding.name "termination", [Context_Rules.intro_bang (SOME 0)]),
       
   179            [([Goal.norm_result termination], [])])] |> snd
       
   180       |> Proof.theorem_i NONE afterqed [[(goal, [])]]
       
   181     end
       
   182 
   180 
   183 val termination_proof = gen_termination_proof Syntax.check_term
   181 val termination_proof = gen_termination_proof Syntax.check_term
   184 val termination_proof_cmd = gen_termination_proof Syntax.read_term
   182 val termination_proof_cmd = gen_termination_proof Syntax.read_term
   185 
   183 
   186 
   184 
   187 (* Datatype hook to declare datatype congs as "function_congs" *)
   185 (* Datatype hook to declare datatype congs as "function_congs" *)
   188 
   186 
   189 
   187 
   190 fun add_case_cong n thy =
   188 fun add_case_cong n thy =
   191     Context.theory_map (Function_Ctx_Tree.map_function_congs (Thm.add_thm
   189   let
   192                           (Datatype.the_info thy n
   190     val cong = #case_cong (Datatype.the_info thy n)
   193                            |> #case_cong
   191       |> safe_mk_meta_eq
   194                            |> safe_mk_meta_eq)))
   192   in
   195                        thy
   193     Context.theory_map
       
   194       (Function_Ctx_Tree.map_function_congs (Thm.add_thm cong)) thy
       
   195   end
   196 
   196 
   197 val setup_case_cong = Datatype.interpretation (K (fold add_case_cong))
   197 val setup_case_cong = Datatype.interpretation (K (fold add_case_cong))
   198 
   198 
   199 
   199 
   200 (* setup *)
   200 (* setup *)