register_locale: produce stamps at the spot where elements are registered;
authorwenzelm
Thu, 26 Mar 2009 17:00:59 +0100
changeset 30725 c23a5b3cd1b9
parent 30724 2e54e89bcce7
child 30726 67388cc4ccb4
register_locale: produce stamps at the spot where elements are registered; tuned signature; misc internal tuning and simplification;
src/Pure/Isar/expression.ML
src/Pure/Isar/locale.ML
--- a/src/Pure/Isar/expression.ML	Thu Mar 26 15:20:50 2009 +0100
+++ b/src/Pure/Isar/expression.ML	Thu Mar 26 17:00:59 2009 +0100
@@ -203,7 +203,7 @@
 
 fun parse_concl prep_term ctxt concl =
   (map o map) (fn (t, ps) =>
-    (prep_term (ProofContext.set_mode ProofContext.mode_schematic ctxt) t, (* FIXME ?? *)
+    (prep_term (ProofContext.set_mode ProofContext.mode_schematic ctxt) t,
       map (prep_term (ProofContext.set_mode ProofContext.mode_pattern ctxt)) ps)) concl;
 
 
@@ -288,13 +288,13 @@
 fun closeup _ _ false elem = elem
   | closeup ctxt parms true elem =
       let
+        (* FIXME consider closing in syntactic phase -- before type checking *)
         fun close_frees t =
           let
             val rev_frees =
               Term.fold_aterms (fn Free (x, T) =>
                 if AList.defined (op =) parms x then I else insert (op =) (x, T) | _ => I) t [];
-          in Term.list_all_free (rev rev_frees, t) end; (* FIXME use fold Logic.all *)
-  (* FIXME consider closing in syntactic phase *)
+          in fold (Logic.all o Free) rev_frees t end;
 
         fun no_binds [] = []
           | no_binds _ = error "Illegal term bindings in context element";
@@ -325,9 +325,7 @@
   in (loc, morph) end;
 
 fun finish_elem ctxt parms do_close elem =
-  let
-    val elem' = finish_primitive parms (closeup ctxt parms do_close) elem;
-  in elem' end
+  finish_primitive parms (closeup ctxt parms do_close) elem;
 
 fun finish ctxt parms do_close insts elems =
   let
@@ -363,7 +361,7 @@
         val inst''' = insts'' |> List.last |> snd |> snd;
         val (morph, _) = inst_morph (parm_names, parm_types) (prfx, inst''') ctxt;
         val ctxt'' = Locale.activate_declarations thy (loc, morph) ctxt;
-      in (i+1, insts', ctxt'') end;
+      in (i + 1, insts', ctxt'') end;
 
     fun prep_elem insts raw_elem (elems, ctxt) =
       let
@@ -564,9 +562,7 @@
   in text' end;
 
 fun eval_elem ctxt elem text =
-  let
-    val text' = eval_text ctxt true elem text;
-  in text' end;
+  eval_text ctxt true elem text;
 
 fun eval ctxt deps elems =
   let
@@ -676,7 +672,7 @@
             thy'
             |> Sign.mandatory_path (Binding.name_of aname)
             |> PureThy.note_thmss Thm.internalK
-              [((Binding.name introN, []), [([intro], [Locale.unfold_attrib])])]
+              [((Binding.name introN, []), [([intro], [Locale.unfold_add])])]
             ||> Sign.restore_naming thy';
           in (SOME statement, SOME intro, axioms, thy'') end;
     val (b_pred, b_intro, b_axioms, thy'''') =
@@ -690,7 +686,7 @@
             thy'''
             |> Sign.mandatory_path (Binding.name_of pname)
             |> PureThy.note_thmss Thm.internalK
-                 [((Binding.name introN, []), [([intro], [Locale.intro_attrib])]),
+                 [((Binding.name introN, []), [([intro], [Locale.intro_add])]),
                   ((Binding.name axiomsN, []),
                     [(map (Drule.standard o Element.conclude_witness) axioms, [])])]
             ||> Sign.restore_naming thy''';
@@ -712,7 +708,7 @@
 fun defines_to_notes thy (Defines defs) =
       Notes (Thm.definitionK, map (fn (a, (def, _)) =>
         (a, [([Assumption.assume (cterm_of thy def)],
-          [(Attrib.internal o K) Locale.witness_attrib])])) defs)
+          [(Attrib.internal o K) Locale.witness_add])])) defs)
   | defines_to_notes _ e = e;
 
 fun gen_add_locale prep_decl
@@ -745,11 +741,11 @@
     val asm = if is_some b_statement then b_statement else a_statement;
 
     val notes =
-        if is_some asm
-        then [(Thm.internalK, [((Binding.suffix_name ("_" ^ axiomsN) bname, []),
-          [([Assumption.assume (cterm_of thy' (the asm))],
-            [(Attrib.internal o K) Locale.witness_attrib])])])]
-        else [];
+      if is_some asm
+      then [(Thm.internalK, [((Binding.suffix_name ("_" ^ axiomsN) bname, []),
+        [([Assumption.assume (cterm_of thy' (the asm))],
+          [(Attrib.internal o K) Locale.witness_add])])])]
+      else [];
 
     val notes' = body_elems |>
       map (defines_to_notes thy') |>
@@ -764,8 +760,7 @@
 
     val loc_ctxt = thy'
       |> Locale.register_locale bname (extraTs, params)
-          (asm, rev defs) (a_intro, b_intro) axioms ([], [])
-          (map (fn n => (n, stamp ())) notes |> rev) (map (fn d => (d, stamp ())) deps' |> rev)
+          (asm, rev defs) (a_intro, b_intro) axioms ([], []) (rev notes) (rev deps')
       |> TheoryTarget.init (SOME name)
       |> fold (fn (kind, facts) => LocalTheory.notes kind facts #> snd) notes';
 
@@ -792,11 +787,11 @@
 
     val ((propss, deps, export), goal_ctxt) = prep_expr expression target_ctxt;
 
-    fun after_qed witss = ProofContext.theory (
-      fold2 (fn (name, morph) => fn wits => Locale.add_dependency target
+    fun after_qed witss = ProofContext.theory
+      (fold2 (fn (name, morph) => fn wits => Locale.add_dependency target
         (name, morph $> Element.satisfy_morphism wits $> export)) deps witss #>
       (fn thy => fold_rev Locale.activate_global_facts
-          (Locale.get_registrations thy) thy));
+        (Locale.get_registrations thy) thy));
   in Element.witness_proof after_qed propss goal_ctxt end;
 
 in
--- a/src/Pure/Isar/locale.ML	Thu Mar 26 15:20:50 2009 +0100
+++ b/src/Pure/Isar/locale.ML	Thu Mar 26 17:00:59 2009 +0100
@@ -1,8 +1,7 @@
 (*  Title:      Pure/Isar/locale.ML
     Author:     Clemens Ballarin, TU Muenchen
 
-Locales -- Isar proof contexts as meta-level predicates, with local
-syntax and implicit structures.
+Locales -- managed Isar proof contexts, based on Pure predicates.
 
 Draws basic ideas from Florian Kammueller's original version of
 locales, but uses the richer infrastructure of Isar instead of the raw
@@ -34,9 +33,9 @@
     (string * sort) list * (binding * typ option * mixfix) list ->
     term option * term list ->
     thm option * thm option -> thm list ->
-    (declaration * stamp) list * (declaration * stamp) list ->
-    ((string * (Attrib.binding * (thm list * Attrib.src list) list) list) * stamp) list ->
-    ((string * morphism) * stamp) list -> theory -> theory
+    declaration list * declaration list ->
+    (string * (Attrib.binding * (thm list * Attrib.src list) list) list) list ->
+    (string * morphism) list -> theory -> theory
   val intern: theory -> xstring -> string
   val extern: theory -> string -> xstring
   val defined: theory -> string -> bool
@@ -64,16 +63,17 @@
   val init: string -> theory -> Proof.context
 
   (* Reasoning about locales *)
-  val witness_attrib: attribute
-  val intro_attrib: attribute
-  val unfold_attrib: attribute
+  val get_witnesses: Proof.context -> thm list
+  val get_intros: Proof.context -> thm list
+  val get_unfolds: Proof.context -> thm list
+  val witness_add: attribute
+  val intro_add: attribute
+  val unfold_add: attribute
   val intro_locales_tac: bool -> Proof.context -> thm list -> tactic
 
   (* Registrations *)
-  val add_registration: string * (morphism * morphism) ->
-    theory -> theory
-  val amend_registration: morphism -> string * morphism ->
-    theory -> theory
+  val add_registration: string * (morphism * morphism) -> theory -> theory
+  val amend_registration: morphism -> string * morphism -> theory -> theory
   val get_registrations: theory -> (string * morphism) list
 
   (* Diagnostic *)
@@ -81,27 +81,6 @@
   val print_locale: theory -> bool -> xstring -> unit
 end;
 
-
-(*** Theorem list extensible via attribute --- to control intro_locales_tac ***)
-
-(* FIXME: consider moving named_thms.ML up in the build hierarchy and using that *)
-functor ThmsFun() =
-struct
-
-structure Data = GenericDataFun
-(
-  type T = thm list;
-  val empty = [];
-  val extend = I;
-  fun merge _ = Thm.merge_thms;
-);
-
-val get = Data.get o Context.Proof;
-val add = Thm.declaration_attribute (Data.map o Thm.add_thm);
-
-end;
-
-
 structure Locale: LOCALE =
 struct
 
@@ -140,7 +119,7 @@
           merge (eq_snd op =) (notes, notes')),
             merge (eq_snd op =) (dependencies, dependencies')));
 
-structure LocalesData = TheoryDataFun
+structure Locales = TheoryDataFun
 (
   type T = locale NameSpace.table;
   val empty = NameSpace.empty_table;
@@ -149,26 +128,29 @@
   fun merge _ = NameSpace.join_tables (K merge_locale);
 );
 
-val intern = NameSpace.intern o #1 o LocalesData.get;
-val extern = NameSpace.extern o #1 o LocalesData.get;
-
-fun get_locale thy = Symtab.lookup (#2 (LocalesData.get thy));
+val intern = NameSpace.intern o #1 o Locales.get;
+val extern = NameSpace.extern o #1 o Locales.get;
 
-fun defined thy = is_some o get_locale thy;
+val get_locale = Symtab.lookup o #2 o Locales.get;
+val defined = Symtab.defined o #2 o Locales.get;
 
-fun the_locale thy name = case get_locale thy name
- of SOME (Loc loc) => loc
-  | NONE => error ("Unknown locale " ^ quote name);
+fun the_locale thy name =
+  (case get_locale thy name of
+    SOME (Loc loc) => loc
+  | NONE => error ("Unknown locale " ^ quote name));
 
 fun register_locale binding parameters spec intros axioms decls notes dependencies thy =
-  thy |> LocalesData.map (NameSpace.define (Sign.naming_of thy) (binding,
-    mk_locale ((parameters, spec, intros, axioms), ((decls, notes), dependencies))) #> snd);
+  thy |> Locales.map (NameSpace.define (Sign.naming_of thy)
+    (binding,
+      mk_locale ((parameters, spec, intros, axioms),
+        ((pairself (map (fn decl => (decl, stamp ()))) decls, map (fn n => (n, stamp ())) notes),
+          map (fn d => (d, stamp ())) dependencies))) #> snd);
 
 fun change_locale name =
-  LocalesData.map o apsnd o Symtab.map_entry name o map_locale o apsnd;
+  Locales.map o apsnd o Symtab.map_entry name o map_locale o apsnd;
 
 fun print_locales thy =
-  Pretty.strs ("locales:" :: map #1 (NameSpace.extern_table (LocalesData.get thy)))
+  Pretty.strs ("locales:" :: map #1 (NameSpace.extern_table (Locales.get thy)))
   |> Pretty.writeln;
 
 
@@ -181,12 +163,12 @@
 fun axioms_of thy = #axioms o the_locale thy;
 
 fun instance_of thy name morph = params_of thy name |>
-  map ((fn (b, T, _) => Free (Name.of_binding b, the T)) #> Morphism.term morph);
+  map (fn (b, T, _) => Morphism.term morph (Free (Name.of_binding b, the T)));
 
 fun specification_of thy = #spec o the_locale thy;
 
 fun declarations_of thy name = the_locale thy name |>
-  #decls |> apfst (map fst) |> apsnd (map fst);
+  #decls |> pairself (map fst);
 
 fun dependencies_of thy name = the_locale thy name |>
   #dependencies |> map fst;
@@ -206,7 +188,7 @@
 
 datatype 'a delayed = Ready of 'a | ToDo of ('a delayed * 'a delayed);
 
-structure IdentifiersData = GenericDataFun
+structure Identifiers = GenericDataFun
 (
   type T = identifiers delayed;
   val empty = Ready empty;
@@ -220,18 +202,17 @@
   | finish _ (Ready ids) = ids;
 
 val _ = Context.>> (Context.map_theory (Theory.at_begin (fn thy =>
-  (case IdentifiersData.get (Context.Theory thy) of
-    Ready _ => NONE |
-    ids => SOME (Context.theory_map (IdentifiersData.put (Ready (finish thy ids))) thy))
-  )));
+  (case Identifiers.get (Context.Theory thy) of
+    Ready _ => NONE
+  | ids => SOME (Context.theory_map (Identifiers.put (Ready (finish thy ids))) thy)))));
 
 fun get_global_idents thy =
-  let val (Ready ids) = (IdentifiersData.get o Context.Theory) thy in ids end;
-val put_global_idents = Context.theory_map o IdentifiersData.put o Ready;
+  let val (Ready ids) = (Identifiers.get o Context.Theory) thy in ids end;
+val put_global_idents = Context.theory_map o Identifiers.put o Ready;
 
 fun get_local_idents ctxt =
-  let val (Ready ids) = (IdentifiersData.get o Context.Proof) ctxt in ids end;
-val put_local_idents = Context.proof_map o IdentifiersData.put o Ready;
+  let val (Ready ids) = (Identifiers.get o Context.Proof) ctxt in ids end;
+val put_local_idents = Context.proof_map o Identifiers.put o Ready;
 
 end;
 
@@ -385,7 +366,7 @@
 
 (*** Registrations: interpretations in theories ***)
 
-structure RegistrationsData = TheoryDataFun
+structure Registrations = TheoryDataFun
 (
   type T = ((string * (morphism * morphism)) * stamp) list;
     (* FIXME mixins need to be stamped *)
@@ -398,17 +379,17 @@
 );
 
 val get_registrations =
-  RegistrationsData.get #> map fst #> map (apsnd op $>);
+  Registrations.get #> map fst #> map (apsnd op $>);
 
 fun add_registration (name, (base_morph, export)) thy =
   roundup thy (fn _ => fn (name', morph') =>
-    (RegistrationsData.map o cons) ((name', (morph', export)), stamp ()))
+    (Registrations.map o cons) ((name', (morph', export)), stamp ()))
     (name, base_morph) (get_global_idents thy, thy) |> snd
     (* FIXME |-> put_global_idents ?*);
 
 fun amend_registration morph (name, base_morph) thy =
   let
-    val regs = (RegistrationsData.get #> map fst) thy;
+    val regs = (Registrations.get #> map fst) thy;
     val base = instance_of thy name base_morph;
     fun match (name', (morph', _)) =
       name = name' andalso eq_list (op aconv) (base, instance_of thy name' morph');
@@ -418,7 +399,7 @@
         space_implode " " (map (quote o Syntax.string_of_term_global thy) base) ^ " available.")
       else ();
   in
-    RegistrationsData.map (nth_map (length regs - 1 - i)
+    Registrations.map (nth_map (length regs - 1 - i)
       (fn ((name, (base, export)), stamp) => ((name, (base $> morph, export)), stamp))) thy
   end;
 
@@ -463,6 +444,7 @@
 
 end;
 
+
 (* Dependencies *)
 
 fun add_dependency loc dep = (change_locale loc o apsnd) (cons (dep, stamp ()));
@@ -470,21 +452,36 @@
 
 (*** Reasoning about locales ***)
 
-(** Storage for witnesses, intro and unfold rules **)
+(* Storage for witnesses, intro and unfold rules *)
 
-structure Witnesses = ThmsFun();
-structure Intros = ThmsFun();
-structure Unfolds = ThmsFun();
+structure Thms = GenericDataFun
+(
+  type T = thm list * thm list * thm list;
+  val empty = ([], [], []);
+  val extend = I;
+  fun merge _ ((witnesses1, intros1, unfolds1), (witnesses2, intros2, unfolds2)) =
+   (Thm.merge_thms (witnesses1, witnesses2),
+    Thm.merge_thms (intros1, intros2),
+    Thm.merge_thms (unfolds1, unfolds2));
+);
 
-val witness_attrib = Witnesses.add;
-val intro_attrib = Intros.add;
-val unfold_attrib = Unfolds.add;
+val get_witnesses = #1 o Thms.get o Context.Proof;
+val get_intros = #2 o Thms.get o Context.Proof;
+val get_unfolds = #3 o Thms.get o Context.Proof;
 
-(** Tactic **)
+val witness_add =
+  Thm.declaration_attribute (fn th => Thms.map (fn (x, y, z) => (Thm.add_thm th x, y, z)));
+val intro_add =
+  Thm.declaration_attribute (fn th => Thms.map (fn (x, y, z) => (x, Thm.add_thm th y, z)));
+val unfold_add =
+  Thm.declaration_attribute (fn th => Thms.map (fn (x, y, z) => (x, y, Thm.add_thm th z)));
 
-fun intro_locales_tac eager ctxt facts st =
+
+(* Tactic *)
+
+fun intro_locales_tac eager ctxt =
   Method.intros_tac
-    (Witnesses.get ctxt @ Intros.get ctxt @ (if eager then Unfolds.get ctxt else [])) facts st;
+    (get_witnesses ctxt @ get_intros ctxt @ (if eager then get_unfolds ctxt else []));
 
 val _ = Context.>> (Context.map_theory
  (Method.setup (Binding.name "intro_locales") (Scan.succeed (METHOD o intro_locales_tac false))