wenzelm@18140: (* Title: Pure/Isar/element.ML wenzelm@18140: Author: Makarius wenzelm@18140: wenzelm@19777: Explicit data structures for some Isar language elements, with derived wenzelm@19777: logical operations. wenzelm@18140: *) wenzelm@18140: wenzelm@18140: signature ELEMENT = wenzelm@18140: sig wenzelm@19259: datatype ('typ, 'term) stmt = wenzelm@28084: Shows of (Attrib.binding * ('term * 'term list) list) list | haftmann@29578: Obtains of (binding * ((binding * 'typ option) list * 'term list)) list wenzelm@26336: type statement = (string, string) stmt wenzelm@26336: type statement_i = (typ, term) stmt wenzelm@18140: datatype ('typ, 'term, 'fact) ctxt = haftmann@29578: Fixes of (binding * 'typ option * mixfix) list | wenzelm@18140: Constrains of (string * 'typ) list | wenzelm@28084: Assumes of (Attrib.binding * ('term * 'term list) list) list | wenzelm@28084: Defines of (Attrib.binding * ('term * 'term list)) list | wenzelm@28084: Notes of string * (Attrib.binding * ('fact * Attrib.src list) list) list wenzelm@26336: type context = (string, string, Facts.ref) ctxt wenzelm@26336: type context_i = (typ, term, thm list) ctxt wenzelm@21581: val facts_map: (('typ, 'term, 'fact) ctxt -> ('a, 'b, 'c) ctxt) -> wenzelm@28084: (Attrib.binding * ('fact * Attrib.src list) list) list -> wenzelm@28084: (Attrib.binding * ('c * Attrib.src list) list) list wenzelm@29603: val map_ctxt: {binding: binding -> binding, typ: 'typ -> 'a, term: 'term -> 'b, wenzelm@29603: pattern: 'term -> 'b, fact: 'fact -> 'c, attrib: Attrib.src -> Attrib.src} -> wenzelm@29603: ('typ, 'term, 'fact) ctxt -> ('a, 'b, 'c) ctxt wenzelm@21528: val map_ctxt_attrib: (Attrib.src -> Attrib.src) -> wenzelm@21528: ('typ, 'term, 'fact) ctxt -> ('typ, 'term, 'fact) ctxt wenzelm@21481: val morph_ctxt: morphism -> context_i -> context_i wenzelm@19777: val pretty_stmt: Proof.context -> statement_i -> Pretty.T list wenzelm@19777: val pretty_ctxt: Proof.context -> context_i -> Pretty.T list wenzelm@19777: val pretty_statement: Proof.context -> string -> thm -> Pretty.T wenzelm@19777: type witness haftmann@29578: val prove_witness: Proof.context -> term -> tactic -> witness haftmann@29578: val witness_proof: (witness list list -> Proof.context -> Proof.context) -> haftmann@29578: term list list -> Proof.context -> Proof.state haftmann@29578: val witness_proof_eqs: (witness list list -> thm list -> Proof.context -> Proof.context) -> haftmann@29578: term list list -> term list -> Proof.context -> Proof.state haftmann@29578: val witness_local_proof: (witness list list -> Proof.state -> Proof.state) -> haftmann@29578: string -> term list list -> Proof.context -> bool -> Proof.state -> Proof.state ballarin@38108: val witness_local_proof_eqs: (witness list list -> thm list -> Proof.state -> Proof.state) -> ballarin@38108: string -> term list list -> term list -> Proof.context -> bool -> Proof.state -> ballarin@38108: Proof.state wenzelm@21481: val morph_witness: morphism -> witness -> witness wenzelm@19777: val conclude_witness: witness -> thm ballarin@22658: val pretty_witness: Proof.context -> witness -> Pretty.T wenzelm@18140: val instT_type: typ Symtab.table -> typ -> typ wenzelm@18140: val instT_term: typ Symtab.table -> term -> term wenzelm@18140: val instT_thm: theory -> typ Symtab.table -> thm -> thm wenzelm@21481: val instT_morphism: theory -> typ Symtab.table -> morphism wenzelm@18140: val inst_term: typ Symtab.table * term Symtab.table -> term -> term wenzelm@18140: val inst_thm: theory -> typ Symtab.table * term Symtab.table -> thm -> thm wenzelm@21481: val inst_morphism: theory -> typ Symtab.table * term Symtab.table -> morphism wenzelm@19777: val satisfy_thm: witness list -> thm -> thm wenzelm@21481: val satisfy_morphism: witness list -> morphism wenzelm@20264: val satisfy_facts: witness list -> wenzelm@28084: (Attrib.binding * (thm list * Attrib.src list) list) list -> wenzelm@28084: (Attrib.binding * (thm list * Attrib.src list) list) list haftmann@36674: val eq_morphism: theory -> thm list -> morphism option ballarin@29218: val transfer_morphism: theory -> morphism ballarin@38108: val generic_note_thmss: string -> (Attrib.binding * (thm list * Attrib.src list) list) list -> ballarin@38108: Context.generic -> (string * thm list) list * Context.generic wenzelm@30775: val init: context_i -> Context.generic -> Context.generic wenzelm@30777: val activate_i: context_i -> Proof.context -> context_i * Proof.context wenzelm@30777: val activate: (typ, term, Facts.ref) ctxt -> Proof.context -> context_i * Proof.context wenzelm@18140: end; wenzelm@18140: wenzelm@18140: structure Element: ELEMENT = wenzelm@18140: struct wenzelm@18140: wenzelm@19777: (** language elements **) wenzelm@19777: wenzelm@19777: (* statement *) wenzelm@19259: wenzelm@19259: datatype ('typ, 'term) stmt = wenzelm@28084: Shows of (Attrib.binding * ('term * 'term list) list) list | haftmann@29578: Obtains of (binding * ((binding * 'typ option) list * 'term list)) list; wenzelm@19259: wenzelm@19259: type statement = (string, string) stmt; wenzelm@19259: type statement_i = (typ, term) stmt; wenzelm@19259: wenzelm@19259: wenzelm@19777: (* context *) wenzelm@18140: wenzelm@18140: datatype ('typ, 'term, 'fact) ctxt = haftmann@29578: Fixes of (binding * 'typ option * mixfix) list | wenzelm@18140: Constrains of (string * 'typ) list | wenzelm@28084: Assumes of (Attrib.binding * ('term * 'term list) list) list | wenzelm@28084: Defines of (Attrib.binding * ('term * 'term list)) list | wenzelm@28084: Notes of string * (Attrib.binding * ('fact * Attrib.src list) list) list; wenzelm@18140: wenzelm@26336: type context = (string, string, Facts.ref) ctxt; wenzelm@18140: type context_i = (typ, term, thm list) ctxt; wenzelm@18140: wenzelm@21581: fun facts_map f facts = Notes ("", facts) |> f |> (fn Notes (_, facts') => facts'); wenzelm@21581: wenzelm@29603: fun map_ctxt {binding, typ, term, pattern, fact, attrib} = wenzelm@29603: fn Fixes fixes => Fixes (fixes |> map (fn (x, T, mx) => (binding x, Option.map typ T, mx))) wenzelm@28079: | Constrains xs => Constrains (xs |> map (fn (x, T) => wenzelm@42494: (Variable.check_name (binding (Binding.name x)), typ T))) wenzelm@18140: | Assumes asms => Assumes (asms |> map (fn ((a, atts), propps) => wenzelm@29603: ((binding a, map attrib atts), propps |> map (fn (t, ps) => (term t, map pattern ps))))) wenzelm@18140: | Defines defs => Defines (defs |> map (fn ((a, atts), (t, ps)) => wenzelm@29603: ((binding a, map attrib atts), (term t, map pattern ps)))) wenzelm@21440: | Notes (kind, facts) => Notes (kind, facts |> map (fn ((a, atts), bs) => haftmann@28965: ((binding a, map attrib atts), bs |> map (fn (ths, btts) => (fact ths, map attrib btts))))); wenzelm@18140: wenzelm@21528: fun map_ctxt_attrib attrib = wenzelm@29603: map_ctxt {binding = I, typ = I, term = I, pattern = I, fact = I, attrib = attrib}; wenzelm@21528: wenzelm@21481: fun morph_ctxt phi = map_ctxt haftmann@28965: {binding = Morphism.binding phi, wenzelm@21481: typ = Morphism.typ phi, wenzelm@21481: term = Morphism.term phi, wenzelm@29603: pattern = Morphism.term phi, wenzelm@21521: fact = Morphism.fact phi, wenzelm@21481: attrib = Args.morph_values phi}; wenzelm@18140: wenzelm@19808: wenzelm@18894: wenzelm@19259: (** pretty printing **) wenzelm@19259: wenzelm@19267: fun pretty_items _ _ [] = [] wenzelm@19267: | pretty_items keyword sep (x :: ys) = wenzelm@19267: Pretty.block [Pretty.keyword keyword, Pretty.brk 1, x] :: wenzelm@19267: map (fn y => Pretty.block [Pretty.str " ", Pretty.keyword sep, Pretty.brk 1, y]) ys; wenzelm@19259: haftmann@28862: fun pretty_name_atts ctxt (b, atts) sep = wenzelm@30219: if Binding.is_empty b andalso null atts then [] wenzelm@43547: else wenzelm@43547: [Pretty.block (Pretty.breaks wenzelm@43547: (Binding.pretty b :: Attrib.pretty_attribs ctxt atts @ [Pretty.str sep]))]; wenzelm@19259: wenzelm@19259: wenzelm@19259: (* pretty_stmt *) wenzelm@19259: wenzelm@19259: fun pretty_stmt ctxt = wenzelm@19259: let wenzelm@24920: val prt_typ = Pretty.quote o Syntax.pretty_typ ctxt; wenzelm@24920: val prt_term = Pretty.quote o Syntax.pretty_term ctxt; wenzelm@19267: val prt_terms = separate (Pretty.keyword "and") o map prt_term; wenzelm@19259: val prt_name_atts = pretty_name_atts ctxt; wenzelm@19259: wenzelm@19259: fun prt_show (a, ts) = wenzelm@19267: Pretty.block (Pretty.breaks (prt_name_atts a ":" @ prt_terms (map fst ts))); wenzelm@19259: wenzelm@28079: fun prt_var (x, SOME T) = Pretty.block wenzelm@30223: [Pretty.str (Binding.name_of x ^ " ::"), Pretty.brk 1, prt_typ T] wenzelm@30223: | prt_var (x, NONE) = Pretty.str (Binding.name_of x); wenzelm@26721: val prt_vars = separate (Pretty.keyword "and") o map prt_var; wenzelm@19259: wenzelm@19267: fun prt_obtain (_, ([], ts)) = Pretty.block (Pretty.breaks (prt_terms ts)) wenzelm@19259: | prt_obtain (_, (xs, ts)) = Pretty.block (Pretty.breaks wenzelm@19585: (prt_vars xs @ [Pretty.keyword "where"] @ prt_terms ts)); wenzelm@19259: in wenzelm@19267: fn Shows shows => pretty_items "shows" "and" (map prt_show shows) wenzelm@19267: | Obtains obtains => pretty_items "obtains" "|" (map prt_obtain obtains) wenzelm@19259: end; wenzelm@19259: wenzelm@18894: wenzelm@19259: (* pretty_ctxt *) wenzelm@19259: wenzelm@19259: fun pretty_ctxt ctxt = wenzelm@19259: let wenzelm@24920: val prt_typ = Pretty.quote o Syntax.pretty_typ ctxt; wenzelm@24920: val prt_term = Pretty.quote o Syntax.pretty_term ctxt; wenzelm@32091: val prt_thm = Pretty.backquote o Display.pretty_thm ctxt; wenzelm@19259: val prt_name_atts = pretty_name_atts ctxt; wenzelm@19259: wenzelm@19267: fun prt_mixfix NoSyn = [] wenzelm@42287: | prt_mixfix mx = [Pretty.brk 2, Mixfix.pretty_mixfix mx]; wenzelm@19267: wenzelm@30223: fun prt_fix (x, SOME T, mx) = Pretty.block (Pretty.str (Binding.name_of x ^ " ::") :: wenzelm@28079: Pretty.brk 1 :: prt_typ T :: Pretty.brk 1 :: prt_mixfix mx) wenzelm@30223: | prt_fix (x, NONE, mx) = Pretty.block (Pretty.str (Binding.name_of x) :: wenzelm@28079: Pretty.brk 1 :: prt_mixfix mx); haftmann@28965: fun prt_constrain (x, T) = prt_fix (Binding.name x, SOME T, NoSyn); wenzelm@18894: wenzelm@19259: fun prt_asm (a, ts) = wenzelm@19259: Pretty.block (Pretty.breaks (prt_name_atts a ":" @ map (prt_term o fst) ts)); wenzelm@19259: fun prt_def (a, (t, _)) = wenzelm@19259: Pretty.block (Pretty.breaks (prt_name_atts a ":" @ [prt_term t])); wenzelm@19259: wenzelm@19259: fun prt_fact (ths, []) = map prt_thm ths wenzelm@19259: | prt_fact (ths, atts) = Pretty.enclose "(" ")" wenzelm@21032: (Pretty.breaks (map prt_thm ths)) :: Attrib.pretty_attribs ctxt atts; wenzelm@19259: fun prt_note (a, ths) = wenzelm@19482: Pretty.block (Pretty.breaks (flat (prt_name_atts a "=" :: map prt_fact ths))); wenzelm@19259: in wenzelm@19267: fn Fixes fixes => pretty_items "fixes" "and" (map prt_fix fixes) wenzelm@19267: | Constrains xs => pretty_items "constrains" "and" (map prt_constrain xs) wenzelm@19267: | Assumes asms => pretty_items "assumes" "and" (map prt_asm asms) wenzelm@19267: | Defines defs => pretty_items "defines" "and" (map prt_def defs) wenzelm@21440: | Notes ("", facts) => pretty_items "notes" "and" (map prt_note facts) wenzelm@21440: | Notes (kind, facts) => pretty_items ("notes " ^ kind) "and" (map prt_note facts) wenzelm@19259: end; wenzelm@18894: wenzelm@19267: wenzelm@19267: (* pretty_statement *) wenzelm@19267: wenzelm@19267: local wenzelm@19267: wenzelm@41581: fun standard_elim th = wenzelm@41581: (case Object_Logic.elim_concl th of wenzelm@41581: SOME C => wenzelm@41581: let wenzelm@41581: val cert = Thm.cterm_of (Thm.theory_of_thm th); wenzelm@41581: val thesis = Var ((Auto_Bind.thesisN, Thm.maxidx_of th + 1), fastype_of C); wenzelm@41581: val th' = Thm.instantiate ([], [(cert C, cert thesis)]) th; wenzelm@41581: in (th', true) end wenzelm@41581: | NONE => (th, false)); wenzelm@41581: wenzelm@19267: fun thm_name kind th prts = wenzelm@19267: let val head = wenzelm@27865: if Thm.has_name_hint th then wenzelm@21965: Pretty.block [Pretty.command kind, wenzelm@30364: Pretty.brk 1, Pretty.str (Long_Name.base_name (Thm.get_name_hint th) ^ ":")] wenzelm@21965: else Pretty.command kind wenzelm@19267: in Pretty.block (Pretty.fbreaks (head :: prts)) end; wenzelm@19267: wenzelm@19267: fun obtain prop ctxt = wenzelm@19267: let wenzelm@41581: val ((ps, prop'), ctxt') = Variable.focus prop ctxt; wenzelm@42488: fun fix (x, T) = (Binding.name (Variable.revert_fixed ctxt' x), SOME T); wenzelm@42495: val xs = map (fix o #2) ps; wenzelm@42495: val As = Logic.strip_imp_prems prop'; wenzelm@41581: in ((Binding.empty, (xs, As)), ctxt') end; wenzelm@19267: wenzelm@19267: in wenzelm@19267: wenzelm@19267: fun pretty_statement ctxt kind raw_th = wenzelm@19267: let wenzelm@42360: val thy = Proof_Context.theory_of ctxt; wenzelm@20150: wenzelm@41581: val (th, is_elim) = standard_elim (Raw_Simplifier.norm_hhf raw_th); wenzelm@41581: val ((_, [th']), ctxt') = Variable.import true [th] (Variable.set_body true ctxt); wenzelm@20150: val prop = Thm.prop_of th'; wenzelm@20150: val (prems, concl) = Logic.strip_horn prop; wenzelm@35625: val concl_term = Object_Logic.drop_judgment thy concl; wenzelm@19267: wenzelm@20150: val fixes = fold_aterms (fn v as Free (x, T) => wenzelm@20150: if Variable.newly_fixed ctxt' ctxt x andalso not (v aconv concl_term) wenzelm@42488: then insert (op =) (Variable.revert_fixed ctxt' x, T) else I | _ => I) prop [] |> rev; wenzelm@20150: val (assumes, cases) = take_suffix (fn prem => wenzelm@20150: is_elim andalso concl aconv Logic.strip_assums_concl prem) prems; wenzelm@19267: in haftmann@28965: pretty_ctxt ctxt' (Fixes (map (fn (x, T) => (Binding.name x, SOME T, NoSyn)) fixes)) @ haftmann@28965: pretty_ctxt ctxt' (Assumes (map (fn t => (Attrib.empty_binding, [(t, [])])) assumes)) @ haftmann@28965: (if null cases then pretty_stmt ctxt' (Shows [(Attrib.empty_binding, [(concl, [])])]) wenzelm@26716: else wenzelm@42495: let val (clauses, ctxt'') = fold_map obtain cases ctxt' wenzelm@26716: in pretty_stmt ctxt'' (Obtains clauses) end) wenzelm@19267: end |> thm_name kind raw_th; wenzelm@19267: wenzelm@18140: end; wenzelm@19267: wenzelm@19777: wenzelm@19777: wenzelm@19777: (** logical operations **) wenzelm@19777: wenzelm@19777: (* witnesses -- hypotheses as protected facts *) wenzelm@19777: wenzelm@19777: datatype witness = Witness of term * thm; wenzelm@19777: haftmann@29578: val mark_witness = Logic.protect; haftmann@29578: fun witness_prop (Witness (t, _)) = t; wenzelm@44058: fun witness_hyps (Witness (_, th)) = Thm.hyps_of th; wenzelm@19777: fun map_witness f (Witness witn) = Witness (f witn); wenzelm@19777: wenzelm@21481: fun morph_witness phi = map_witness (fn (t, th) => (Morphism.term phi t, Morphism.thm phi th)); wenzelm@21481: wenzelm@20058: fun prove_witness ctxt t tac = haftmann@29578: Witness (t, Thm.close_derivation (Goal.prove ctxt [] [] (mark_witness t) (fn _ => wenzelm@25202: Tactic.rtac Drule.protectI 1 THEN tac))); wenzelm@19777: wenzelm@29603: haftmann@29578: local haftmann@29578: haftmann@29578: val refine_witness = wenzelm@30510: Proof.refine (Method.Basic (K (RAW_METHOD haftmann@29578: (K (ALLGOALS haftmann@29578: (CONJUNCTS (ALLGOALS wenzelm@32194: (CONJUNCTS (TRYALL (Tactic.rtac Drule.protectI)))))))))); wenzelm@25624: haftmann@29578: fun gen_witness_proof proof after_qed wit_propss eq_props = haftmann@29578: let haftmann@29578: val propss = (map o map) (fn prop => (mark_witness prop, [])) wit_propss haftmann@29578: @ [map (rpair []) eq_props]; haftmann@29578: fun after_qed' thmss = wenzelm@29603: let val (wits, eqs) = split_last ((map o map) Thm.close_derivation thmss); haftmann@29578: in after_qed ((map2 o map2) (curry Witness) wit_propss wits) eqs end; haftmann@29578: in proof after_qed' propss #> refine_witness #> Seq.hd end; haftmann@29578: ballarin@38108: fun proof_local cmd goal_ctxt int after_qed' propss = ballarin@38108: Proof.map_context (K goal_ctxt) wenzelm@42360: #> Proof.local_goal (Proof_Display.print_results int) (K I) Proof_Context.bind_propp_i ballarin@38108: cmd NONE after_qed' (map (pair Thm.empty_binding) propss); haftmann@41425: haftmann@29578: in haftmann@29578: haftmann@29578: fun witness_proof after_qed wit_propss = wenzelm@36323: gen_witness_proof (Proof.theorem NONE) (fn wits => fn _ => after_qed wits) haftmann@29578: wit_propss []; haftmann@29578: wenzelm@36323: val witness_proof_eqs = gen_witness_proof (Proof.theorem NONE); haftmann@29578: haftmann@29578: fun witness_local_proof after_qed cmd wit_propss goal_ctxt int = ballarin@38108: gen_witness_proof (proof_local cmd goal_ctxt int) haftmann@29578: (fn wits => fn _ => after_qed wits) wit_propss []; haftmann@29578: ballarin@38108: fun witness_local_proof_eqs after_qed cmd wit_propss eq_props goal_ctxt int = ballarin@38108: gen_witness_proof (proof_local cmd goal_ctxt int) after_qed wit_propss eq_props; haftmann@41425: wenzelm@29603: end; wenzelm@29603: wenzelm@19777: wenzelm@25302: fun compose_witness (Witness (_, th)) r = wenzelm@25302: let wenzelm@25302: val th' = Goal.conclude th; wenzelm@25302: val A = Thm.cprem_of r 1; ballarin@25739: in ballarin@25739: Thm.implies_elim ballarin@25739: (Conv.gconv_rule Drule.beta_eta_conversion 1 r) ballarin@25739: (Conv.fconv_rule Drule.beta_eta_conversion ballarin@25739: (Thm.instantiate (Thm.match (Thm.cprop_of th', A)) th')) ballarin@25739: end; wenzelm@25302: haftmann@29578: fun conclude_witness (Witness (_, th)) = wenzelm@41228: Thm.close_derivation (Raw_Simplifier.norm_hhf_protect (Goal.conclude th)); wenzelm@19777: ballarin@22658: fun pretty_witness ctxt witn = wenzelm@24920: let val prt_term = Pretty.quote o Syntax.pretty_term ctxt in ballarin@22658: Pretty.block (prt_term (witness_prop witn) :: wenzelm@39166: (if Config.get ctxt show_hyps then [Pretty.brk 2, Pretty.list "[" "]" ballarin@22658: (map prt_term (witness_hyps witn))] else [])) ballarin@22658: end; ballarin@22658: wenzelm@19777: wenzelm@19777: (* derived rules *) wenzelm@19777: wenzelm@20007: fun instantiate_tfrees thy subst th = wenzelm@19777: let wenzelm@19777: val certT = Thm.ctyp_of thy; wenzelm@20007: val idx = Thm.maxidx_of th + 1; wenzelm@20007: fun cert_inst (a, (S, T)) = (certT (TVar ((a, idx), S)), certT T); wenzelm@20007: wenzelm@20007: fun add_inst (a, S) insts = wenzelm@20007: if AList.defined (op =) insts a then insts wenzelm@20007: else (case AList.lookup (op =) subst a of NONE => insts | SOME T => (a, (S, T)) :: insts); wenzelm@20007: val insts = wenzelm@20007: Term.fold_types (Term.fold_atyps (fn TFree v => add_inst v | _ => I)) wenzelm@20007: (Thm.full_prop_of th) []; wenzelm@19777: in wenzelm@20007: th wenzelm@20007: |> Thm.generalize (map fst insts, []) idx wenzelm@20007: |> Thm.instantiate (map cert_inst insts, []) wenzelm@19777: end; wenzelm@19777: wenzelm@19777: fun instantiate_frees thy subst = wenzelm@19777: let val cert = Thm.cterm_of thy in wenzelm@19777: Drule.forall_intr_list (map (cert o Free o fst) subst) #> wenzelm@19777: Drule.forall_elim_list (map (cert o snd) subst) wenzelm@19777: end; wenzelm@19777: wenzelm@19777: fun hyps_rule rule th = wenzelm@21521: let val {hyps, ...} = Thm.crep_thm th in wenzelm@19777: Drule.implies_elim_list wenzelm@19777: (rule (Drule.implies_intr_list hyps th)) wenzelm@21521: (map (Thm.assume o Drule.cterm_rule rule) hyps) wenzelm@19777: end; wenzelm@19777: wenzelm@19777: wenzelm@19777: (* instantiate types *) wenzelm@19777: wenzelm@19777: fun instT_type env = wenzelm@19777: if Symtab.is_empty env then I wenzelm@19777: else Term.map_type_tfree (fn (x, S) => the_default (TFree (x, S)) (Symtab.lookup env x)); wenzelm@19777: wenzelm@19777: fun instT_term env = wenzelm@19777: if Symtab.is_empty env then I wenzelm@20548: else Term.map_types (instT_type env); wenzelm@19777: wenzelm@22691: fun instT_subst env th = (Thm.fold_terms o Term.fold_types o Term.fold_atyps) wenzelm@20304: (fn T as TFree (a, _) => wenzelm@20304: let val T' = the_default T (Symtab.lookup env a) wenzelm@20304: in if T = T' then I else insert (op =) (a, T') end wenzelm@20304: | _ => I) th []; wenzelm@19777: wenzelm@19777: fun instT_thm thy env th = wenzelm@19777: if Symtab.is_empty env then th wenzelm@19777: else wenzelm@19777: let val subst = instT_subst env th wenzelm@19777: in if null subst then th else th |> hyps_rule (instantiate_tfrees thy subst) end; wenzelm@19777: wenzelm@22672: fun instT_morphism thy env = wenzelm@24137: let val thy_ref = Theory.check_thy thy in wenzelm@22672: Morphism.morphism wenzelm@29603: {binding = I, wenzelm@22672: typ = instT_type env, wenzelm@22672: term = instT_term env, wenzelm@22672: fact = map (fn th => instT_thm (Theory.deref thy_ref) env th)} wenzelm@22672: end; wenzelm@19777: wenzelm@19777: wenzelm@19777: (* instantiate types and terms *) wenzelm@19777: wenzelm@19777: fun inst_term (envT, env) = wenzelm@19777: if Symtab.is_empty env then instT_term envT wenzelm@19777: else wenzelm@19777: let wenzelm@19777: val instT = instT_type envT; wenzelm@19777: fun inst (Const (x, T)) = Const (x, instT T) wenzelm@19777: | inst (Free (x, T)) = wenzelm@19777: (case Symtab.lookup env x of wenzelm@19777: NONE => Free (x, instT T) wenzelm@19777: | SOME t => t) wenzelm@19777: | inst (Var (xi, T)) = Var (xi, instT T) wenzelm@19777: | inst (b as Bound _) = b wenzelm@19777: | inst (Abs (x, T, t)) = Abs (x, instT T, inst t) wenzelm@19777: | inst (t $ u) = inst t $ inst u; wenzelm@19777: in Envir.beta_norm o inst end; wenzelm@19777: wenzelm@19777: fun inst_thm thy (envT, env) th = wenzelm@19777: if Symtab.is_empty env then instT_thm thy envT th wenzelm@19777: else wenzelm@19777: let wenzelm@19777: val substT = instT_subst envT th; wenzelm@22691: val subst = (Thm.fold_terms o Term.fold_aterms) wenzelm@20304: (fn Free (x, T) => wenzelm@19777: let wenzelm@19777: val T' = instT_type envT T; wenzelm@19777: val t = Free (x, T'); wenzelm@19777: val t' = the_default t (Symtab.lookup env x); wenzelm@20304: in if t aconv t' then I else insert (eq_fst (op =)) ((x, T'), t') end wenzelm@20304: | _ => I) th []; wenzelm@19777: in wenzelm@19777: if null substT andalso null subst then th wenzelm@19777: else th |> hyps_rule wenzelm@19777: (instantiate_tfrees thy substT #> wenzelm@19777: instantiate_frees thy subst #> wenzelm@22900: Conv.fconv_rule (Thm.beta_conversion true)) wenzelm@19777: end; wenzelm@19777: wenzelm@22672: fun inst_morphism thy envs = wenzelm@24137: let val thy_ref = Theory.check_thy thy in wenzelm@22672: Morphism.morphism wenzelm@29603: {binding = I, wenzelm@22672: typ = instT_type (#1 envs), wenzelm@22672: term = inst_term envs, wenzelm@22672: fact = map (fn th => inst_thm (Theory.deref thy_ref) envs th)} wenzelm@22672: end; wenzelm@19777: wenzelm@19777: wenzelm@19777: (* satisfy hypotheses *) wenzelm@19777: wenzelm@19777: fun satisfy_thm witns thm = thm |> fold (fn hyp => wenzelm@19777: (case find_first (fn Witness (t, _) => Thm.term_of hyp aconv t) witns of wenzelm@19777: NONE => I wenzelm@25302: | SOME w => Thm.implies_intr hyp #> compose_witness w)) (#hyps (Thm.crep_thm thm)); wenzelm@19777: wenzelm@29603: val satisfy_morphism = Morphism.thm_morphism o satisfy_thm; wenzelm@29603: val satisfy_facts = facts_map o morph_ctxt o satisfy_morphism; wenzelm@20264: wenzelm@20264: haftmann@29525: (* rewriting with equalities *) haftmann@29525: haftmann@36674: fun eq_morphism thy thms = if null thms then NONE else SOME (Morphism.morphism wenzelm@29603: {binding = I, wenzelm@29603: typ = I, wenzelm@41228: term = Raw_Simplifier.rewrite_term thy thms [], wenzelm@41228: fact = map (Raw_Simplifier.rewrite_rule thms)}); haftmann@29525: haftmann@29525: ballarin@29218: (* transfer to theory using closure *) ballarin@29218: ballarin@29218: fun transfer_morphism thy = wenzelm@29603: let val thy_ref = Theory.check_thy thy wenzelm@38709: in Morphism.thm_morphism (fn th => Thm.transfer (Theory.deref thy_ref) th) end; wenzelm@29603: ballarin@29218: ballarin@29218: wenzelm@30775: (** activate in context **) ballarin@28832: wenzelm@30775: (* init *) ballarin@28832: ballarin@38108: fun generic_note_thmss kind facts context = ballarin@38108: let ballarin@38108: val facts' = Attrib.map_facts (Attrib.attribute_i (Context.theory_of context)) facts; ballarin@38108: in ballarin@38108: context |> Context.mapping_result wenzelm@39557: (Global_Theory.note_thmss kind facts') wenzelm@42360: (Proof_Context.note_thmss kind facts') ballarin@38108: end; ballarin@38108: wenzelm@42360: fun init (Fixes fixes) = Context.map_proof (Proof_Context.add_fixes fixes #> #2) wenzelm@30775: | init (Constrains _) = I wenzelm@30775: | init (Assumes asms) = Context.map_proof (fn ctxt => ballarin@28832: let wenzelm@42360: val asms' = Attrib.map_specs (Attrib.attribute_i (Proof_Context.theory_of ctxt)) asms; wenzelm@30775: val (_, ctxt') = ctxt wenzelm@30775: |> fold Variable.auto_fixes (maps (map #1 o #2) asms') wenzelm@42360: |> Proof_Context.add_assms_i Assumption.assume_export asms'; wenzelm@30775: in ctxt' end) wenzelm@30775: | init (Defines defs) = Context.map_proof (fn ctxt => ballarin@28832: let wenzelm@42360: val defs' = Attrib.map_specs (Attrib.attribute_i (Proof_Context.theory_of ctxt)) defs; ballarin@28832: val asms = defs' |> map (fn ((name, atts), (t, ps)) => wenzelm@35624: let val ((c, _), t') = Local_Defs.cert_def ctxt t (* FIXME adapt ps? *) wenzelm@30434: in (t', ((Thm.def_binding_optional (Binding.name c) name, atts), [(t', ps)])) end); wenzelm@30775: val (_, ctxt') = ctxt wenzelm@30775: |> fold Variable.auto_fixes (map #1 asms) wenzelm@42360: |> Proof_Context.add_assms_i Local_Defs.def_export (map #2 asms); wenzelm@30775: in ctxt' end) ballarin@38108: | init (Notes (kind, facts)) = generic_note_thmss kind facts #> #2; wenzelm@30775: wenzelm@30775: wenzelm@30775: (* activate *) wenzelm@30775: wenzelm@30777: fun activate_i elem ctxt = ballarin@28832: let wenzelm@30777: val elem' = map_ctxt_attrib Args.assignable elem; wenzelm@30777: val ctxt' = Context.proof_map (init elem') ctxt; wenzelm@30777: in (map_ctxt_attrib Args.closure elem', ctxt') end; ballarin@28832: wenzelm@30777: fun activate raw_elem ctxt = wenzelm@30777: let val elem = raw_elem |> map_ctxt wenzelm@43842: {binding = I, wenzelm@29603: typ = I, wenzelm@29603: term = I, wenzelm@29603: pattern = I, wenzelm@42360: fact = Proof_Context.get_fact ctxt, wenzelm@42360: attrib = Attrib.intern_src (Proof_Context.theory_of ctxt)} wenzelm@30777: in activate_i elem ctxt end; ballarin@28832: wenzelm@19267: end;