src/Pure/Isar/locale.ML
changeset 12063 4c16bdee47d4
parent 12058 cc182b43dd55
child 12070 c72fe1edc9e7
equal deleted inserted replaced
12062:feed7bb2a607 12063:4c16bdee47d4
     2     ID:         $Id$
     2     ID:         $Id$
     3     Author:     Markus Wenzel, TU Muenchen
     3     Author:     Markus Wenzel, TU Muenchen
     4     License:    GPL (GNU GENERAL PUBLIC LICENSE)
     4     License:    GPL (GNU GENERAL PUBLIC LICENSE)
     5 
     5 
     6 Locales -- Isar proof contexts as meta-level predicates, with local
     6 Locales -- Isar proof contexts as meta-level predicates, with local
     7 syntax and implicit structures.
     7 syntax and implicit structures.  Draws basic ideas from Florian
       
     8 Kammueller's original version of locales, but uses the rich
       
     9 infrastructure of Isar instead of the raw meta-logic.
     8 
    10 
     9 TODO:
    11 TODO:
    10   - reset scope context on qed of legacy goal (!??);
    12   - 'print_locales' command (also PG menu?);
    11   - implicit closure of ``loose'' free vars;
    13   - cert_elem (do *not* cert_def, yet) (!?);
    12   - avoid dynamic scoping of facts/atts
    14   - ensure unique defines;
    13     (use thms_closure for globals, even within att expressions);
    15   - local syntax (mostly in ProofContext);
    14   - scope of implicit fixed in elementents vs. locales (!??);
       
    15   - remove scope stuff;
       
    16 *)
    16 *)
    17 
    17 
    18 signature BASIC_LOCALE =
    18 signature BASIC_LOCALE =
    19 sig
    19 sig
    20   val print_locales: theory -> unit
    20   val print_locales: theory -> unit
       
    21   val print_locale: theory -> xstring -> unit
    21 end;
    22 end;
    22 
    23 
    23 signature LOCALE =
    24 signature LOCALE =
    24 sig
    25 sig
    25   include BASIC_LOCALE
    26   include BASIC_LOCALE
    34   type 'att element
    35   type 'att element
    35   type 'att element_i
    36   type 'att element_i
    36   type locale
    37   type locale
    37   val intern: Sign.sg -> xstring -> string
    38   val intern: Sign.sg -> xstring -> string
    38   val cond_extern: Sign.sg -> string -> xstring
    39   val cond_extern: Sign.sg -> string -> xstring
    39   val intern_att: ('att -> context attribute) ->
    40   val attribute: ('att -> context attribute) ->
    40     ('typ, 'term, 'thm, 'att) elem -> ('typ, 'term, 'thm, context attribute) elem
    41     ('typ, 'term, 'thm, 'att) elem -> ('typ, 'term, 'thm, context attribute) elem
    41   val activate_elements: context attribute element list -> context -> context
    42   val activate_elements: context attribute element list -> context -> context
    42   val activate_elements_i: context attribute element_i list -> context -> context
    43   val activate_elements_i: context attribute element_i list -> context -> context
    43   val activate_locale: xstring -> context -> context
    44   val activate_locale: xstring -> context -> context
    44   val activate_locale_i: string -> context -> context
    45   val activate_locale_i: string -> context -> context
    45 (*
    46   val add_locale: bstring -> xstring list -> context attribute element list -> theory -> theory
    46   val add_locale: bstring -> xstring option -> (string * string * mixfix) list ->
    47   val add_locale_i: bstring -> xstring list -> context attribute element_i list -> theory -> theory
    47     ((string * context attribute list) * string) list ->
    48   val store_thm: string -> (string * thm) * context attribute list -> theory -> theory
    48     ((string * context attribute list) * string) list -> theory -> theory
       
    49   val add_locale_i: bstring -> xstring option -> (string * typ * mixfix) list ->
       
    50     ((string * context attribute list) * term) list ->
       
    51     ((string * context attribute list) * term) list -> theory -> theory
       
    52   val read_prop_schematic: Sign.sg -> string -> cterm
       
    53 *)
       
    54   val setup: (theory -> theory) list
    49   val setup: (theory -> theory) list
    55 end;
    50 end;
    56 
    51 
    57 structure Locale: LOCALE =
    52 structure Locale: LOCALE =
    58 struct
    53 struct
    71   Notes of ((string * 'att list) * ('fact * 'att list) list) list |
    66   Notes of ((string * 'att list) * ('fact * 'att list) list) list |
    72   Uses of expression;
    67   Uses of expression;
    73 
    68 
    74 type 'att element = (string, string, string, 'att) elem;
    69 type 'att element = (string, string, string, 'att) elem;
    75 type 'att element_i = (typ, term, thm list, 'att) elem;
    70 type 'att element_i = (typ, term, thm list, 'att) elem;
    76 type locale = (thm -> string) * string list * context attribute element_i list;
    71 type locale = {imports: string list, elements: context attribute element_i list, closed: bool};
       
    72 
       
    73 fun make_locale imports elements closed =
       
    74   {imports = imports, elements = elements, closed = closed}: locale;
    77 
    75 
    78 
    76 
    79 fun fixes_of_elem (Fixes fixes) = map #1 fixes
    77 fun fixes_of_elem (Fixes fixes) = map #1 fixes
    80   | fixes_of_elem _ = [];
    78   | fixes_of_elem _ = [];
    81 
    79 
    82 fun frees_of_elem _ = [];  (* FIXME *)
    80 fun frees_of_elem _ = [];  (* FIXME *)
    83 
    81 
       
    82 (*fun close_locale {imports, elements, closed = _} = make_locale imports elements true;*)
       
    83 fun close_locale x = x;   (* FIXME tmp *)
       
    84 
    84 
    85 
    85 
    86 
    86 (** theory data **)
    87 (** theory data **)
    87 
    88 
    88 (* data kind 'Pure/locales' *)
    89 (* data kind 'Pure/locales' *)
    89 
       
    90 type locale_data =
       
    91   {space: NameSpace.T,
       
    92     locales: locale Symtab.table,
       
    93     scope: ((string * locale) list * context option) ref};
       
    94 
       
    95 fun make_locale_data space locales scope =
       
    96   {space = space, locales = locales, scope = scope}: locale_data;
       
    97 
       
    98 val empty_scope = ([], None);
       
    99 
    90 
   100 structure LocalesArgs =
    91 structure LocalesArgs =
   101 struct
    92 struct
   102   val name = "Isar/locales";
    93   val name = "Isar/locales";
   103   type T = locale_data;
    94   type T = NameSpace.T * locale Symtab.table;
   104 
    95 
   105   val empty = make_locale_data NameSpace.empty Symtab.empty (ref empty_scope);
    96   val empty = (NameSpace.empty, Symtab.empty);
   106   fun copy {space, locales, scope = ref r} = make_locale_data space locales (ref r);
    97   val copy = I;
   107   fun prep_ext {space, locales, scope = _} = make_locale_data space locales (ref empty_scope);
    98   fun prep_ext (space, locales) = (space, Symtab.map close_locale locales);
   108   fun merge ({space = space1, locales = locales1, scope = _},
    99   fun merge ((space1, locales1), (space2, locales2)) =
   109     {space = space2, locales = locales2, scope = _}) =
   100       (NameSpace.merge (space1, space2), Symtab.merge (K true) (locales1, locales2));
   110       make_locale_data (NameSpace.merge (space1, space2))
   101 
   111         (Symtab.merge (K true) (locales1, locales2)) (ref empty_scope);
   102   fun print _ (space, locales) =
   112 
       
   113   fun print _ {space, locales, scope = _} =
       
   114     Pretty.strs ("locales:" :: map (NameSpace.cond_extern space o #1) (Symtab.dest locales))
   103     Pretty.strs ("locales:" :: map (NameSpace.cond_extern space o #1) (Symtab.dest locales))
   115     |> Pretty.writeln;
   104     |> Pretty.writeln;
   116 end;
   105 end;
   117 
   106 
   118 structure LocalesData = TheoryDataFun(LocalesArgs);
   107 structure LocalesData = TheoryDataFun(LocalesArgs);
   119 val print_locales = LocalesData.print;
   108 val print_locales = LocalesData.print;
   120 
   109 
   121 val intern = NameSpace.intern o #space o LocalesData.get_sg;
   110 val intern = NameSpace.intern o #1 o LocalesData.get_sg;
   122 val cond_extern = NameSpace.cond_extern o #space o LocalesData.get_sg;
   111 val cond_extern = NameSpace.cond_extern o #1 o LocalesData.get_sg;
   123 
   112 
   124 
   113 
   125 (* access locales *)
   114 (* access locales *)
   126 
   115 
   127 fun get_locale_sg sg name = Symtab.lookup (#locales (LocalesData.get_sg sg), name);
   116 fun declare_locale name =
   128 val get_locale = get_locale_sg o Theory.sign_of;
   117   LocalesData.map (apfst (fn space => (NameSpace.extend (space, [name]))));
   129 
   118 
   130 fun put_locale (name, locale) = LocalesData.map (fn {space, locales, scope} =>
   119 fun put_locale name locale =
   131   make_locale_data (NameSpace.extend (space, [name]))
   120   LocalesData.map (apsnd (fn locales => Symtab.update ((name, locale), locales)));
   132     (Symtab.update ((name, locale), locales)) scope);
   121 
       
   122 fun get_locale thy name = Symtab.lookup (#2 (LocalesData.get thy), name);
   133 
   123 
   134 fun the_locale thy name =
   124 fun the_locale thy name =
   135   (case get_locale thy name of
   125   (case get_locale thy name of
   136     Some loc => loc
   126     Some loc => loc
   137   | None => error ("Unknown locale " ^ quote name));
   127   | None => error ("Unknown locale " ^ quote name));
   138 
   128 
   139 
   129 
   140 (* access scope *)
       
   141 
       
   142 fun get_scope_sg sg =
       
   143   if Sign.eq_sg (sg, Theory.sign_of ProtoPure.thy) then empty_scope
       
   144   else ! (#scope (LocalesData.get_sg sg));
       
   145 
       
   146 val get_scope = get_scope_sg o Theory.sign_of;
       
   147 val nonempty_scope_sg = not o null o #1 o get_scope_sg;
       
   148 
       
   149 fun change_scope f thy =
       
   150   let val {scope, ...} = LocalesData.get thy
       
   151   in scope := f (! scope); thy end;
       
   152 
       
   153 fun print_scope thy =
       
   154   Pretty.writeln (Pretty.strs ("current scope:" ::
       
   155     rev (map (cond_extern (Theory.sign_of thy) o #1) (#1 (get_scope thy)))));
       
   156 
       
   157 
       
   158 (* print locales *)    (* FIXME activate local syntax *)
   130 (* print locales *)    (* FIXME activate local syntax *)
   159 
   131 
   160 fun pretty_locale thy xname =
   132 fun pretty_locale thy xname =
   161   let
   133   let
   162     val sg = Theory.sign_of thy;
   134     val sg = Theory.sign_of thy;
   163     val name = intern sg xname;
   135     val name = intern sg xname;
   164     val (_, ancestors, elements) = the_locale thy name;
   136     val {imports, elements, closed = _} = the_locale thy name;
   165 
   137 
   166     val prt_typ = Pretty.quote o Sign.pretty_typ sg;
   138     val prt_typ = Pretty.quote o Sign.pretty_typ sg;
   167     val prt_term = Pretty.quote o Sign.pretty_term sg;
   139     val prt_term = Pretty.quote o Sign.pretty_term sg;
   168 
   140 
   169     fun prt_syn syn =
   141     fun prt_syn syn =
   189       | prt_elem (Defines defs) = Pretty.big_list "defines" (map prt_def defs)
   161       | prt_elem (Defines defs) = Pretty.big_list "defines" (map prt_def defs)
   190       | prt_elem (Notes facts) = Pretty.big_list "notes" (map prt_fact facts)
   162       | prt_elem (Notes facts) = Pretty.big_list "notes" (map prt_fact facts)
   191       | prt_elem (Uses _) = Pretty.str "FIXME";
   163       | prt_elem (Uses _) = Pretty.str "FIXME";
   192 
   164 
   193     val prt_header = Pretty.block (Pretty.str ("locale " ^ cond_extern sg name ^ " =") ::
   165     val prt_header = Pretty.block (Pretty.str ("locale " ^ cond_extern sg name ^ " =") ::
   194        (if null ancestors then [] else
   166        (if null imports then [] else
   195        (flat (separate [Pretty.str "+", Pretty.brk 1] (map (single o Pretty.str) ancestors)) @
   167        (flat (separate [Pretty.str "+", Pretty.brk 1] (map (single o Pretty.str) imports)) @
   196          [Pretty.str "+"])));
   168          [Pretty.str "+"])));
   197   in Pretty.block (Pretty.fbreaks (prt_header :: map prt_elem elements)) end;
   169   in Pretty.block (Pretty.fbreaks (prt_header :: map prt_elem elements)) end;
   198 
   170 
   199 val print_locale = Pretty.writeln oo pretty_locale;
   171 val print_locale = Pretty.writeln oo pretty_locale;
   200 
   172 
   201 
   173 
   202 (** internalization of theorems and attributes **)
   174 
   203 
   175 (** internalize elements **)
   204 fun int_att attrib (x, srcs) = (x, map attrib srcs);
   176 
   205 
   177 (* read_elem *)
   206 fun intern_att _ (Fixes fixes) = Fixes fixes
       
   207   | intern_att attrib (Assumes asms) = Assumes (map (apfst (int_att attrib)) asms)
       
   208   | intern_att attrib (Defines defs) = Defines (map (apfst (int_att attrib)) defs)
       
   209   | intern_att attrib (Notes facts) =
       
   210       Notes (map (apfst (int_att attrib) o apsnd (map (int_att attrib))) facts)
       
   211   | intern_att _ (Uses FIXME) = Uses FIXME;
       
   212 
       
   213 
       
   214 
       
   215 (** activate locales **)
       
   216 
       
   217 fun close_frees ctxt t =
       
   218   let val frees = rev (filter_out (ProofContext.is_fixed ctxt o #1) (Drule.add_frees ([], t)))
       
   219   in Term.list_all_free (frees, t) end;
       
   220 
   178 
   221 fun read_elem ctxt =
   179 fun read_elem ctxt =
   222  fn (Fixes fixes) =>
   180  fn Fixes fixes =>
   223       let val vars =
   181       let val vars =
   224         #2 (foldl_map ProofContext.read_vars (ctxt, map (fn (x, T, _) => ([x], T)) fixes))
   182         #2 (foldl_map ProofContext.read_vars (ctxt, map (fn (x, T, _) => ([x], T)) fixes))
   225       in Fixes (map2 (fn (([x'], T'), (_, _, mx)) => (x', T', mx)) (vars, fixes)) end
   183       in Fixes (map2 (fn (([x'], T'), (_, _, mx)) => (x', T', mx)) (vars, fixes)) end
   226   | (Assumes asms) =>
   184   | Assumes asms =>
   227       Assumes (map #1 asms ~~ #2 (ProofContext.read_propp (ctxt, map #2 asms)))
   185       Assumes (map #1 asms ~~ #2 (ProofContext.read_propp (ctxt, map #2 asms)))
   228   | (Defines defs) =>
   186   | Defines defs =>
   229       let val propps =
   187       let val propps =
   230         #2 (ProofContext.read_propp (ctxt, map (fn (_, (t, ps)) => [(t, (ps, []))]) defs))
   188         #2 (ProofContext.read_propp (ctxt, map (fn (_, (t, ps)) => [(t, (ps, []))]) defs))
   231       in Defines (map #1 defs ~~ map (fn [(t', (ps', []))] => (t', ps')) propps) end
   189       in Defines (map #1 defs ~~ map (fn [(t', (ps', []))] => (t', ps')) propps) end
   232   | (Notes facts) =>
   190   | Notes facts =>
   233       Notes (map (apsnd (map (apfst (ProofContext.get_thms ctxt)))) facts)
   191       Notes (map (apsnd (map (apfst (ProofContext.get_thms ctxt)))) facts)
   234   | (Uses FIXME) => Uses FIXME;
   192   | Uses FIXME => Uses FIXME;
   235 
   193 
       
   194 
       
   195 (* prepare attributes *)
       
   196 
       
   197 local fun int_att attrib (x, srcs) = (x, map attrib srcs) in
       
   198 
       
   199 fun attribute _ (Fixes fixes) = Fixes fixes
       
   200   | attribute attrib (Assumes asms) = Assumes (map (apfst (int_att attrib)) asms)
       
   201   | attribute attrib (Defines defs) = Defines (map (apfst (int_att attrib)) defs)
       
   202   | attribute attrib (Notes facts) =
       
   203       Notes (map (apfst (int_att attrib) o apsnd (map (int_att attrib))) facts)
       
   204   | attribute _ (Uses FIXME) = Uses FIXME;
       
   205 
       
   206 end;
       
   207 
       
   208 
       
   209 
       
   210 (** activate locales **)
       
   211 
       
   212 (* activatation primitive *)
   236 
   213 
   237 fun activate (ctxt, Fixes fixes) =
   214 fun activate (ctxt, Fixes fixes) =
   238       ProofContext.fix_direct (map (fn (x, T, FIXME) => ([x], T)) fixes) ctxt
   215       ProofContext.fix_direct (map (fn (x, T, FIXME) => ([x], T)) fixes) ctxt
   239   | activate (ctxt, Assumes asms) =
   216   | activate (ctxt, Assumes asms) =
   240       ctxt |> ProofContext.fix_frees (flat (map (map #1 o #2) asms))
   217       ctxt |> ProofContext.fix_frees (flat (map (map #1 o #2) asms))
   242   | activate (ctxt, Defines defs) = #1 (ProofContext.assume_i ProofContext.export_def
   219   | activate (ctxt, Defines defs) = #1 (ProofContext.assume_i ProofContext.export_def
   243       (map (fn (a, (t, ps)) => (a, [(ProofContext.cert_def ctxt t, (ps, []))])) defs) ctxt)
   220       (map (fn (a, (t, ps)) => (a, [(ProofContext.cert_def ctxt t, (ps, []))])) defs) ctxt)
   244   | activate (ctxt, Notes facts) = #1 (ProofContext.have_thmss facts ctxt)
   221   | activate (ctxt, Notes facts) = #1 (ProofContext.have_thmss facts ctxt)
   245   | activate (ctxt, Uses FIXME) = ctxt;
   222   | activate (ctxt, Uses FIXME) = ctxt;
   246 
   223 
   247 fun read_activate (ctxt, elem) =
   224 
   248   let val elem' = read_elem ctxt elem
   225 (* activate operations *)
   249   in (activate (ctxt, elem'), elem') end;
       
   250 
   226 
   251 fun activate_elements_i elems ctxt = foldl activate (ctxt, elems);
   227 fun activate_elements_i elems ctxt = foldl activate (ctxt, elems);
   252 fun activate_elements elems ctxt = foldl (#1 o read_activate) (ctxt, elems);
   228 fun activate_elements elems ctxt =
   253 
   229   foldl ((fn (ctxt, elem) => activate (ctxt, read_elem ctxt elem))) (ctxt, elems);
   254 fun with_locale f name ctxt =
   230 
       
   231 fun activate_locale_elements (ctxt, name) =
   255   let
   232   let
   256     val thy = ProofContext.theory_of ctxt;
   233     val thy = ProofContext.theory_of ctxt;
   257     val locale = the_locale thy name;
   234     val {elements, ...} = the_locale thy name;    (*exception ERROR*)
   258   in
   235   in
   259     f locale ctxt handle ProofContext.CONTEXT (msg, c) =>
   236     activate_elements_i elements ctxt handle ProofContext.CONTEXT (msg, c) =>
   260       raise ProofContext.CONTEXT (msg ^ "\nThe error(s) above occurred in locale " ^
   237       raise ProofContext.CONTEXT (msg ^ "\nThe error(s) above occurred in locale " ^
   261         quote (cond_extern (Theory.sign_of thy) name), c)
   238         quote (cond_extern (Theory.sign_of thy) name), c)
   262   end;
   239   end;
   263 
   240 
   264 val activate_locale_elements = with_locale (activate_elements_i o #3);
       
   265 
       
   266 fun activate_locale_ancestors name ctxt =
       
   267   foldl (fn (c, es) => activate_locale_elements es c)
       
   268     (ctxt, #2 (the_locale (ProofContext.theory_of ctxt) name));
       
   269 
       
   270 fun activate_locale_i name ctxt =
   241 fun activate_locale_i name ctxt =
   271   ctxt |> activate_locale_ancestors name |> activate_locale_elements name;
   242   activate_locale_elements (foldl activate_locale_elements
       
   243     (ctxt, #imports (the_locale (ProofContext.theory_of ctxt) name)), name);
   272 
   244 
   273 fun activate_locale xname ctxt =
   245 fun activate_locale xname ctxt =
   274   activate_locale_i (intern (ProofContext.sign_of ctxt) xname) ctxt;
   246   activate_locale_i (intern (ProofContext.sign_of ctxt) xname) ctxt;
   275 
   247 
   276 
   248 
   277 
   249 
   278 (* FIXME
       
   279 (** define locales **)
   250 (** define locales **)
   280 
   251 
   281 (* concrete syntax *)
   252 (* closeup dangling frees *)
   282 
   253 
   283 fun mark_syn c = "\\<^locale>" ^ c;
   254 fun close_frees_wrt ctxt t =
   284 
   255   let val frees = rev (filter_out (ProofContext.is_fixed ctxt o #1) (Drule.add_frees ([], t)))
   285 fun mk_loc_tr c ts = list_comb (Free (c, dummyT), ts);
   256   in curry Term.list_all_free frees end;
   286 
   257 
   287 
   258 fun closeup ctxt (Assumes asms) = Assumes (asms |> map (fn (a, propps) =>
   288 (* add_locale *)
   259       (a, propps |> map (fn (t, (ps1, ps2)) =>
   289 
   260         let val close = close_frees_wrt ctxt t in (close t, (map close ps1, map close ps2)) end))))
   290 fun gen_add_locale prep_typ prep_term bname bpar raw_fixes raw_assumes raw_defs thy =
   261   | closeup ctxt (Defines defs) = Defines (defs |> map (fn (a, (t, ps)) =>
   291   let val sign = Theory.sign_of thy;
   262       let
   292 
   263         val t' = ProofContext.cert_def ctxt t;
       
   264         val close = close_frees_wrt ctxt t';
       
   265       in (a, (close t', map close ps)) end))
       
   266   | closeup ctxt elem = elem;
       
   267 
       
   268 
       
   269 (* add_locale(_i) *)
       
   270 
       
   271 fun gen_add_locale prep_locale prep_elem bname raw_imports raw_elems thy =
       
   272   let
       
   273     val sign = Theory.sign_of thy;
   293     val name = Sign.full_name sign bname;
   274     val name = Sign.full_name sign bname;
   294 
   275     val _ =
   295     val (envSb, old_loc_fixes, _) =
   276       if is_none (get_locale thy name) then () else
   296                     case bpar of
   277       error ("Duplicate definition of locale " ^ quote name);
   297                        Some loc => (get_defaults thy loc)
   278 
   298                      | None      => ([],[],[]);
   279     val imports = map (prep_locale sign) raw_imports;
   299 
   280     val imports_ctxt = foldl activate_locale_elements (ProofContext.init thy, imports);
   300     val old_nosyn = case bpar of
   281     fun prep (ctxt, raw_elem) =
   301                        Some loc => #nosyn(#2(the_locale thy loc))
   282       let val elem = closeup ctxt (prep_elem ctxt raw_elem)
   302                      | None      => [];
   283       in (activate (ctxt, elem), elem) end;
   303 
   284     val (locale_ctxt, elems) = foldl_map prep (imports_ctxt, raw_elems);
   304     (* Get the full name of the parent *)
   285   in
   305     val parent = case bparent of
   286     thy
   306                        Some loc => Some(#1(the_locale thy loc))
   287     |> declare_locale name
   307                      | None      => None;
   288     |> put_locale name (make_locale imports elems false)
   308 
   289   end;
   309      (* prepare locale fixes *)
   290 
   310 
   291 val add_locale = gen_add_locale intern read_elem;
   311     fun prep_const (envS, (raw_c, raw_T, raw_mx)) =
   292 val add_locale_i = gen_add_locale (K I) (K I);
   312       let
   293 
   313         val c = Syntax.const_name raw_c raw_mx;
   294 
   314         val c_syn = mark_syn c;
   295 
       
   296 (** store results **)    (* FIXME test atts!? *)
       
   297 
       
   298 fun store_thm name ((a, th), atts) thy =
       
   299   let
       
   300     val note = Notes [((a, atts), [([Thm.name_thm (a, th)], [])])];
       
   301     val {imports, elements, closed} = the_locale thy name;
       
   302   in
       
   303     if closed then error ("Cannot store results in closed locale: " ^ quote name)
       
   304     else thy |> put_locale name (make_locale imports (elements @ [note]) closed)
       
   305   end;
       
   306 
       
   307 
       
   308 (* FIXME old
       
   309 
   315         val mx = Syntax.fix_mixfix raw_c raw_mx;
   310         val mx = Syntax.fix_mixfix raw_c raw_mx;
   316         val (envS', T) = prep_typ sign (envS, raw_T) handle ERROR =>
   311         val (envS', T) = prep_typ sign (envS, raw_T) handle ERROR =>
   317           error ("The error(s) above occured in locale constant " ^ quote c);
   312           error ("The error(s) above occured in locale constant " ^ quote c);
   318         val trfun = if mx = Syntax.NoSyn then None else Some (c_syn, mk_loc_tr c);
   313         val trfun = if mx = Syntax.NoSyn then None else Some (c_syn, mk_loc_tr c);
   319       in (envS', ((c, T), (c_syn, T, mx), trfun)) end;
   314       in (envS', ((c, T), (c_syn, T, mx), trfun)) end;
   323     val loc_fixes = old_loc_fixes @ loc_fixes;
   318     val loc_fixes = old_loc_fixes @ loc_fixes;
   324     val loc_syn = map #2 loc_fixes_syn;
   319     val loc_syn = map #2 loc_fixes_syn;
   325     val nosyn = old_nosyn @ (map (#1 o #1) (filter (fn x => (#3(#2 x)) = NoSyn) loc_fixes_syn));
   320     val nosyn = old_nosyn @ (map (#1 o #1) (filter (fn x => (#3(#2 x)) = NoSyn) loc_fixes_syn));
   326     val loc_trfuns = mapfilter #3 loc_fixes_syn;
   321     val loc_trfuns = mapfilter #3 loc_fixes_syn;
   327 
   322 
   328 
       
   329     (* 1st stage: syntax_thy *)
       
   330 
       
   331     val syntax_thy =
   323     val syntax_thy =
   332       thy
   324       thy
   333       |> Theory.add_modesyntax_i ("", true) loc_syn
   325       |> Theory.add_modesyntax_i ("", true) loc_syn
   334       |> Theory.add_trfuns ([], loc_trfuns, [], []);
   326       |> Theory.add_trfuns ([], loc_trfuns, [], []);
   335 
       
   336     val syntax_sign = Theory.sign_of syntax_thy;
       
   337 
       
   338 
       
   339     (* prepare assumes and defs *)
       
   340 
       
   341     fun prep_axiom (env, (a, raw_t)) =
       
   342       let
       
   343         val (env', t) = prep_term syntax_sign (env, (a, raw_t)) handle ERROR =>
       
   344           error ("The error(s) above occured in locale rule / definition " ^ quote a);
       
   345       in (env', (a, t)) end;
       
   346 
       
   347     val ((envS1, envT1, used1), loc_assumes) =
       
   348       foldl_map prep_axiom ((envS0, loc_fixes, map fst envS0), raw_assumes);
       
   349     val (defaults, loc_defs) =
       
   350         foldl_map prep_axiom ((envS1, envT1, used1), raw_defs);
       
   351 
       
   352     val old_loc_fixes = collect_fixes syntax_sign;
       
   353     val new_loc_fixes = (map #1 loc_fixes);
       
   354     val all_loc_fixes = old_loc_fixes @ new_loc_fixes;
       
   355 
       
   356     val (defaults, loc_defs_terms) =
       
   357         foldl_map (abs_over_free all_loc_fixes) (defaults, loc_defs);
       
   358     val loc_defs_thms =
       
   359         map (apsnd (prep_hyps (map #1 loc_fixes) syntax_sign)) loc_defs_terms;
       
   360     val (defaults, loc_thms_terms) =
       
   361         foldl_map (abs_over_free all_loc_fixes) (defaults, loc_assumes);
       
   362     val loc_thms = map (apsnd (prep_hyps (map #1 loc_fixes) syntax_sign))
       
   363                        (loc_thms_terms)
       
   364                    @ loc_defs_thms;
       
   365 
       
   366 
       
   367     (* error messages *)
       
   368 
       
   369     fun locale_error msg = error (msg ^ "\nFor locale " ^ quote name);
       
   370 
       
   371     val err_dup_locale =
       
   372       if is_none (get_locale thy name) then []
       
   373       else ["Duplicate definition of locale " ^ quote name];
       
   374 
   327 
   375     (* check if definientes are locale constants
   328     (* check if definientes are locale constants
   376        (in the same locale, so no redefining!) *)
   329        (in the same locale, so no redefining!) *)
   377     val err_def_head =
   330     val err_def_head =
   378       let fun peal_appl t =
   331       let fun peal_appl t =
   399                 locale_error ("Definitions must use the == relation")
   352                 locale_error ("Definitions must use the == relation")
   400           val check = foldl compare_var_sides (true, loc_defs)
   353           val check = foldl compare_var_sides (true, loc_defs)
   401       in if check then []
   354       in if check then []
   402          else ["nonfixed variable on right hand side of a locale definition in locale " ^ quote name]
   355          else ["nonfixed variable on right hand side of a locale definition in locale " ^ quote name]
   403       end;
   356       end;
   404 
       
   405     val errs = err_dup_locale @ err_def_head @ err_var_rhs;
       
   406   in
       
   407     if null errs then ()
       
   408     else error (cat_lines errs);
       
   409 
       
   410     syntax_thy
       
   411     |> put_locale (name,
       
   412                    make_locale parent loc_fixes nosyn loc_thms_terms
       
   413                                         loc_defs_terms   loc_thms defaults)
       
   414   end;
       
   415 
       
   416 
       
   417 val add_locale = gen_add_locale read_typ read_axm;
       
   418 val add_locale_i = gen_add_locale cert_typ cert_axm;
       
   419 
       
   420 
       
   421 
       
   422 (*
       
   423 (** support for legacy proof scripts (cf. goals.ML) **)     (* FIXME move to goals.ML (!?) *)
       
   424 
       
   425 (* hyps_in_scope *)
       
   426 
       
   427 fun hyps_in_scope sg hyps =
       
   428   let val locs = map #2 (#1 (get_scope_sg sg))
       
   429   in gen_subset Term.aconv (hyps, map #2 (flat (map #assumes locs @ map #defines locs))) end;
       
   430 
       
   431 
       
   432 (* get theorems *)
       
   433 
       
   434 fun thmx get_local get_global name =
       
   435   let val thy = Context.the_context () in
       
   436     (case #2 (get_scope thy) of
       
   437       None => get_global thy name
       
   438     | Some ctxt => get_local ctxt name)
       
   439   end;
       
   440 
       
   441 val thm = thmx ProofContext.get_thm PureThy.get_thm;
       
   442 val thms = thmx ProofContext.get_thms PureThy.get_thms;
       
   443 
       
   444 
       
   445 (** scope operations -- for old-style goals **)  (* FIXME move to goals.ML (!?) *)
       
   446 
       
   447 (* open *)
       
   448 
       
   449 local
       
   450 
       
   451 fun is_open thy name = exists (equal name o #1) (#1 (get_scope thy));
       
   452 
       
   453 fun open_loc thy name =
       
   454   let
       
   455     val (ancestors, elements) = the_locale thy name;
       
   456   in
       
   457     (case #parent locale of None => thy
       
   458     | Some par =>
       
   459         if is_open thy par then thy
       
   460         else (writeln ("Opening locale " ^ quote par ^ "(required by " ^ quote name ^ ")");
       
   461           open_loc name thy))
       
   462     |> change_scope (fn (locs, _) => ((name, locale) :: locs, None))
       
   463   end;
       
   464 
       
   465 in
       
   466 
       
   467 fun open_locale xname thy =
       
   468   let val name = intern (Theory.sign_of thy) xname in
       
   469     if is_open thy name then (warning ("Locale " ^ quote name ^ " already open"); thy)
       
   470     else open_loc name thy
       
   471   end;
       
   472 
       
   473 end;
       
   474 
       
   475 
       
   476 (* close *)
       
   477 
       
   478 fun close_locale xname thy =
       
   479   let val name = intern_locale (Theory.sign_of thy) xname in
       
   480     thy |> change_scope (fn ([], _) => error "Currently no open locales"
       
   481     | ((name', _) :: locs, _) =>
       
   482         if name <> name' then error ("Locale " ^ quote name ^ " not at top of scope")
       
   483         else (locs, None))
       
   484   end;
       
   485 
       
   486 
       
   487 (* implicit context versions *)
       
   488 
       
   489 fun Open_locale xname = (open_locale xname (Context.the_context ()); ());
       
   490 fun Close_locale xname = (close_locale xname (Context.the_context ()); ());
       
   491 fun Print_scope () = (print_scope (Context.the_context ()); ());
       
   492 *)
   357 *)
   493 
   358 
   494 
   359 
   495 (** locale theory setup **)
   360 (** locale theory setup **)
   496 *)
   361 
   497 val setup =
   362 val setup =
   498  [LocalesData.init];
   363  [LocalesData.init];
   499 
   364 
   500 end;
   365 end;
   501 
   366