src/Pure/Isar/locale.ML
changeset 12529 d99716a53f59
parent 12514 4bdbc5a977f6
child 12532 7e51804da8f4
equal deleted inserted replaced
12528:b8bc541a4544 12529:d99716a53f59
     1 (*  Title:      Pure/Isar/locale.ML
     1 (*  Title:      Pure/Isar/locale.ML
     2     ID:         $Id$
     2     ID:         $Id$
     3     Author:     Markus Wenzel, TU Muenchen
     3     Author:     Markus Wenzel, TU München
     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.  Draws some basic ideas from Florian
     7 syntax and implicit structures.
     8 Kammüller's original version of locales, but uses the richer
     8 
     9 infrastructure of Isar instead of the raw meta-logic.
     9 Draws some basic ideas from Florian Kammüller's original version of
       
    10 locales, but uses the richer infrastructure of Isar instead of the raw
       
    11 meta-logic.  Furthermore, we provide structured import of contexts
       
    12 (with merge and rename operations), as well as type-inference of the
       
    13 signature parts.
    10 *)
    14 *)
    11 
    15 
    12 signature LOCALE =
    16 signature LOCALE =
    13 sig
    17 sig
    14   type context
    18   type context
    30   val intern: Sign.sg -> xstring -> string
    34   val intern: Sign.sg -> xstring -> string
    31   val cond_extern: Sign.sg -> string -> xstring
    35   val cond_extern: Sign.sg -> string -> xstring
    32   val the_locale: theory -> string -> locale
    36   val the_locale: theory -> string -> locale
    33   val attribute: ('att -> context attribute) -> ('typ, 'term, 'thm, 'att) elem_expr
    37   val attribute: ('att -> context attribute) -> ('typ, 'term, 'thm, 'att) elem_expr
    34     -> ('typ, 'term, 'thm, context attribute) elem_expr
    38     -> ('typ, 'term, 'thm, context attribute) elem_expr
    35   val activate_context: expr * context attribute element list -> context -> context * context
    39   val read_context_statement: xstring option -> context attribute element list ->
    36   val activate_context_i: expr * context attribute element_i list -> context -> context * context
    40     (string * (string list * string list)) list list -> context ->
       
    41     string option * context * context * (term * (term list * term list)) list list
       
    42   val cert_context_statement: string option -> context attribute element_i list ->
       
    43     (term * (term list * term list)) list list -> context ->
       
    44     string option * context * context * (term * (term list * term list)) list list
    37   val add_locale: bstring -> expr -> context attribute element list -> theory -> theory
    45   val add_locale: bstring -> expr -> context attribute element list -> theory -> theory
    38   val add_locale_i: bstring -> expr -> context attribute element_i list -> theory -> theory
    46   val add_locale_i: bstring -> expr -> context attribute element_i list -> theory -> theory
    39   val print_locales: theory -> unit
    47   val print_locales: theory -> unit
    40   val print_locale: theory -> expr -> unit
    48   val print_locale: theory -> expr -> unit
    41   val add_thmss: string -> ((string * thm list) * context attribute list) list -> theory -> theory
    49   val add_thmss: string -> ((string * thm list) * context attribute list) list -> theory -> theory
    43 end;
    51 end;
    44 
    52 
    45 structure Locale: LOCALE =
    53 structure Locale: LOCALE =
    46 struct
    54 struct
    47 
    55 
       
    56 
    48 (** locale elements and expressions **)
    57 (** locale elements and expressions **)
    49 
    58 
    50 type context = ProofContext.context;
    59 type context = ProofContext.context;
    51 
    60 
    52 datatype ('typ, 'term, 'fact, 'att) elem =
    61 datatype ('typ, 'term, 'fact, 'att) elem =
   124 
   133 
   125 (* diagnostics *)
   134 (* diagnostics *)
   126 
   135 
   127 fun err_in_locale ctxt msg ids =
   136 fun err_in_locale ctxt msg ids =
   128   let
   137   let
   129     fun prt_id (name, parms) = [Pretty.block (Pretty.breaks (map Pretty.str (name :: parms)))];
   138     val sign = ProofContext.sign_of ctxt;
       
   139     fun prt_id (name, parms) =
       
   140       [Pretty.block (Pretty.breaks (map Pretty.str (cond_extern sign name :: parms)))];
   130     val prt_ids = flat (separate [Pretty.str " +", Pretty.brk 1] (map prt_id ids));
   141     val prt_ids = flat (separate [Pretty.str " +", Pretty.brk 1] (map prt_id ids));
   131     val err_msg =
   142     val err_msg =
   132       if null ids then msg
   143       if forall (equal "" o #1) ids then msg
   133       else msg ^ "\n" ^ Pretty.string_of (Pretty.block
   144       else msg ^ "\n" ^ Pretty.string_of (Pretty.block
   134         (Pretty.str "The error(s) above occurred in locale:" :: Pretty.brk 1 :: prt_ids));
   145         (Pretty.str "The error(s) above occurred in locale:" :: Pretty.brk 1 :: prt_ids));
   135   in raise ProofContext.CONTEXT (err_msg, ctxt) end;
   146   in raise ProofContext.CONTEXT (err_msg, ctxt) end;
   136 
   147 
   137 
   148 
   138 
   149 
   139 (** operations on locale elements **)
   150 (** primitives **)
   140 
       
   141 (* misc utilities *)
       
   142 
       
   143 fun frozen_tvars ctxt Ts =
       
   144   let
       
   145     val tvars = rev (foldl Term.add_tvarsT ([], Ts));
       
   146     val tfrees = map TFree
       
   147       (Term.invent_type_names (ProofContext.used_types ctxt) (length tvars) ~~ map #2 tvars);
       
   148   in map #1 tvars ~~ tfrees end;
       
   149 
       
   150 fun fixes_of_elemss elemss = flat (map (snd o fst) elemss);
       
   151 
       
   152 
       
   153 (* prepare elements *)
       
   154 
       
   155 datatype fact = Int of thm list | Ext of string;
       
   156 
       
   157 local
       
   158 
       
   159 fun prep_name ctxt (name, atts) =
       
   160   if NameSpace.is_qualified name then
       
   161     raise ProofContext.CONTEXT ("Illegal qualified name: " ^ quote name, ctxt)
       
   162   else (name, atts);
       
   163 
       
   164 fun prep_elem prep_vars prep_propp prep_thms ctxt =
       
   165  fn Fixes fixes =>
       
   166       let val vars = snd (foldl_map prep_vars (ctxt, map (fn (x, T, _) => ([x], T)) fixes))
       
   167       in Fixes (map (fn (([x'], T'), (_, _, mx)) => (x', T', mx)) (vars ~~ fixes)) end
       
   168   | Assumes asms =>
       
   169       Assumes (map (prep_name ctxt o #1) asms ~~ snd (prep_propp (ctxt, map #2 asms)))
       
   170   | Defines defs =>
       
   171       let val propps = snd (prep_propp (ctxt, map (fn (_, (t, ps)) => [(t, (ps, []))]) defs)) in
       
   172         Defines (map (prep_name ctxt o #1) defs ~~ map (fn [(t', (ps', []))] => (t', ps')) propps)
       
   173       end
       
   174   | Notes facts =>
       
   175       Notes (map (fn (a, bs) => (prep_name ctxt a, map (apfst (prep_thms ctxt)) bs)) facts);
       
   176 
       
   177 in
       
   178 
       
   179 fun read_elem x = prep_elem ProofContext.read_vars ProofContext.read_propp (K I) x;
       
   180 fun cert_elem x = prep_elem ProofContext.cert_vars ProofContext.cert_propp (K I) x;
       
   181 fun int_facts x = prep_elem I I (K Int) x;
       
   182 fun ext_facts x = prep_elem I I (K Ext) x;
       
   183 fun get_facts x = prep_elem I I
       
   184   (fn ctxt => (fn Int ths => ths | Ext name => ProofContext.get_thms ctxt name)) x;
       
   185 
       
   186 fun read_expr ctxt (Locale xname) = Locale (intern (ProofContext.sign_of ctxt) xname)
       
   187   | read_expr ctxt (Merge exprs) = Merge (map (read_expr ctxt) exprs)
       
   188   | read_expr ctxt (Rename (expr, xs)) = Rename (read_expr ctxt expr, xs);
       
   189 
       
   190 end;
       
   191 
       
   192 
       
   193 (* internalize attributes *)
       
   194 
       
   195 local fun read_att attrib (x, srcs) = (x, map attrib srcs) in
       
   196 
       
   197 fun attribute _ (Elem (Fixes fixes)) = Elem (Fixes fixes)
       
   198   | attribute attrib (Elem (Assumes asms)) = Elem (Assumes (map (apfst (read_att attrib)) asms))
       
   199   | attribute attrib (Elem (Defines defs)) = Elem (Defines (map (apfst (read_att attrib)) defs))
       
   200   | attribute attrib (Elem (Notes facts)) =
       
   201       Elem (Notes (map (apfst (read_att attrib) o apsnd (map (read_att attrib))) facts))
       
   202   | attribute _ (Expr expr) = Expr expr;
       
   203 
       
   204 end;
       
   205 
       
   206 
   151 
   207 (* renaming *)
   152 (* renaming *)
   208 
   153 
   209 fun rename ren x = if_none (assoc_string (ren, x)) x;
   154 fun rename ren x = if_none (assoc_string (ren, x)) x;
   210 
   155 
   230       |> Drule.forall_elim_list (cert_vars xs)
   175       |> Drule.forall_elim_list (cert_vars xs)
   231       |> Thm.instantiate ([], cert_vars xs ~~ cert_frees xs')
   176       |> Thm.instantiate ([], cert_vars xs ~~ cert_frees xs')
   232       |> (fn th' => Drule.implies_elim_list th' (map (Thm.assume o cert o rename_term ren) hyps))
   177       |> (fn th' => Drule.implies_elim_list th' (map (Thm.assume o cert o rename_term ren) hyps))
   233   end;
   178   end;
   234 
   179 
   235 fun rename_elem ren (Fixes fixes) = Fixes (map (fn (x, T, mx) =>
   180 fun rename_elem ren (Fixes fixes) = Fixes (fixes |> map (fn (x, T, mx) =>
   236       (rename ren x, T, if mx = None then mx else Some Syntax.NoSyn)) fixes)    (*drops syntax!*)
   181       let val x' = rename ren x in
       
   182         if x = x' then (x, T, mx)
       
   183         else (x', T, if mx = None then mx else Some Syntax.NoSyn)    (*drop syntax*)
       
   184       end))
   237   | rename_elem ren (Assumes asms) = Assumes (map (apsnd (map (fn (t, (ps, qs)) =>
   185   | rename_elem ren (Assumes asms) = Assumes (map (apsnd (map (fn (t, (ps, qs)) =>
   238       (rename_term ren t, (map (rename_term ren) ps, map (rename_term ren) qs))))) asms)
   186       (rename_term ren t, (map (rename_term ren) ps, map (rename_term ren) qs))))) asms)
   239   | rename_elem ren (Defines defs) = Defines (map (apsnd (fn (t, ps) =>
   187   | rename_elem ren (Defines defs) = Defines (map (apsnd (fn (t, ps) =>
   240       (rename_term ren t, map (rename_term ren) ps))) defs)
   188       (rename_term ren t, map (rename_term ren) ps))) defs)
   241   | rename_elem ren (Notes facts) = Notes (map (apsnd (map (apfst (map (rename_thm ren))))) facts);
   189   | rename_elem ren (Notes facts) = Notes (map (apsnd (map (apfst (map (rename_thm ren))))) facts);
   242 
   190 
   243 fun qualify_elem prfx elem =
   191 fun rename_facts prfx elem =
   244   let
   192   let
   245     fun qualify (arg as ((name, atts), x)) =
   193     fun qualify (arg as ((name, atts), x)) =
   246       if name = "" then arg
   194       if name = "" then arg
   247       else ((NameSpace.pack (filter_out (equal "") (prfx @ [name])), atts), x);
   195       else ((NameSpace.pack (filter_out (equal "") (prfx @ [name])), atts), x);
   248   in
   196   in
   288   | inst_elem env (Defines defs) = Defines (map (apsnd (fn (t, ps) =>
   236   | inst_elem env (Defines defs) = Defines (map (apsnd (fn (t, ps) =>
   289       (inst_term env t, map (inst_term env) ps))) defs)
   237       (inst_term env t, map (inst_term env) ps))) defs)
   290   | inst_elem env (Notes facts) = Notes (map (apsnd (map (apfst (map (inst_thm env))))) facts);
   238   | inst_elem env (Notes facts) = Notes (map (apsnd (map (apfst (map (inst_thm env))))) facts);
   291 
   239 
   292 
   240 
   293 (* evaluation *)
   241 
       
   242 (** structured contexts: rename + merge + implicit type instantiation **)
       
   243 
       
   244 (* parameter types *)
       
   245 
       
   246 fun frozen_tvars ctxt Ts =
       
   247   let
       
   248     val tvars = rev (foldl Term.add_tvarsT ([], Ts));
       
   249     val tfrees = map TFree
       
   250       (Term.invent_type_names (ProofContext.used_types ctxt) (length tvars) ~~ map #2 tvars);
       
   251   in map #1 tvars ~~ tfrees end;
       
   252 
       
   253 
       
   254 fun unify_frozen ctxt maxidx Ts Us =
       
   255   let
       
   256     val FIXME = (PolyML.print "unify_frozen 1"; PolyML.print (Ts, Us));
       
   257     val tsig = Sign.tsig_of (ProofContext.sign_of ctxt);
       
   258     fun unify (env, (Some T, Some U)) = Type.unify tsig env (U, T)
       
   259       | unify (env, _) = env;
       
   260     fun paramify (i, None) = (i, None)
       
   261       | paramify (i, Some T) = apsnd Some (Type.paramify_dummies (i, T));
       
   262 
       
   263     val (maxidx', Ts') = foldl_map paramify (maxidx, Ts);
       
   264     val (maxidx'', Us') = foldl_map paramify (maxidx, Us);
       
   265     val FIXME = (PolyML.print "unify_frozen 2"; PolyML.print (Ts', Us'));
       
   266     val (unifier, _) = foldl unify ((Vartab.empty, maxidx''), Ts' ~~ Us');
       
   267     val Vs = map (apsome (Envir.norm_type unifier)) Us';
       
   268     val unifier' = Vartab.extend (unifier, frozen_tvars ctxt (mapfilter I Vs));
       
   269     val Vs' = map (apsome (Envir.norm_type unifier')) Vs;
       
   270     val FIXME = (PolyML.print "unify_frozen 3"; PolyML.print Vs');
       
   271   in Vs' end;
       
   272 
       
   273 
       
   274 fun params_of elemss = flat (map (snd o fst) elemss);
       
   275 fun param_types ps = mapfilter (fn (_, None) => None | (x, Some T) => Some (x, T)) ps;
       
   276 
       
   277 
       
   278 (* flatten expressions *)
   294 
   279 
   295 local
   280 local
   296 
       
   297 fun unify_parms ctxt raw_parmss =
       
   298   let
       
   299     val tsig = Sign.tsig_of (ProofContext.sign_of ctxt);
       
   300     val maxidx = length raw_parmss;
       
   301     val idx_parmss = (0 upto maxidx - 1) ~~ raw_parmss;
       
   302 
       
   303     fun varify i = Term.map_type_tfree (fn (a, S) => TVar ((a, i), S));
       
   304     fun varify_parms (i, ps) =
       
   305       mapfilter (fn (_, None) => None | (x, Some T) => Some (x, varify i T)) ps;
       
   306     val parms = flat (map varify_parms idx_parmss);
       
   307 
       
   308     fun unify T ((env, maxidx), U) = Type.unify tsig maxidx env (U, T);  (*should never fail*)
       
   309     fun unify_list (envir, T :: Us) = foldl (unify T) (envir, Us)
       
   310       | unify_list (envir, []) = envir;
       
   311     val (unifier, _) = foldl unify_list
       
   312       ((Vartab.empty, maxidx), map #2 (Symtab.dest (Symtab.make_multi parms)));
       
   313 
       
   314     val parms' = map (apsnd (Envir.norm_type unifier)) (gen_distinct eq_fst parms);
       
   315     val unifier' = Vartab.extend (unifier, frozen_tvars ctxt (map #2 parms'));
       
   316 
       
   317     fun inst_parms (i, ps) =
       
   318       foldr Term.add_typ_tfrees (mapfilter snd ps, [])
       
   319       |> mapfilter (fn (a, S) =>
       
   320           let val T = Envir.norm_type unifier' (TVar ((a, i), S))
       
   321           in if T = TFree (a, S) then None else Some ((a, S), T) end);
       
   322   in map inst_parms idx_parmss end;
       
   323 
   281 
   324 fun unique_parms ctxt elemss =
   282 fun unique_parms ctxt elemss =
   325   let
   283   let
   326     val param_decls =
   284     val param_decls =
   327       flat (map (fn ((name, (ps, qs)), _) => map (rpair (name, ps)) qs) elemss)
   285       flat (map (fn ((name, (ps, qs)), _) => map (rpair (name, ps)) qs) elemss)
   331       Some (q, ids) => err_in_locale ctxt ("Multiple declaration of parameter " ^ quote q)
   289       Some (q, ids) => err_in_locale ctxt ("Multiple declaration of parameter " ^ quote q)
   332           (map (apsnd (map fst)) ids)
   290           (map (apsnd (map fst)) ids)
   333     | None => map (apfst (apsnd #1)) elemss)
   291     | None => map (apfst (apsnd #1)) elemss)
   334   end;
   292   end;
   335 
   293 
   336 fun inst_types _ [elems] = [elems]
   294 fun unify_parms ctxt fixed_parms raw_parmss =
   337   | inst_types ctxt elemss =
   295   let
       
   296     val tsig = Sign.tsig_of (ProofContext.sign_of ctxt);
       
   297     val maxidx = length raw_parmss;
       
   298     val idx_parmss = (0 upto maxidx - 1) ~~ raw_parmss;
       
   299 
       
   300     fun varify i = Term.map_type_tfree (fn (a, S) => TVar ((a, i), S));
       
   301     fun varify_parms (i, ps) = map (apsnd (varify i)) (param_types ps);
       
   302     val parms = fixed_parms @ flat (map varify_parms idx_parmss);
       
   303 
       
   304     fun unify T ((env, maxidx), U) = Type.unify tsig (env, maxidx) (U, T)
       
   305       handle Type.TUNIFY => raise TYPE ("unify_parms: failed to unify types", [U, T], []);
       
   306     fun unify_list (envir, T :: Us) = foldl (unify T) (envir, Us)
       
   307       | unify_list (envir, []) = envir;
       
   308     val (unifier, _) = foldl unify_list
       
   309       ((Vartab.empty, maxidx), map #2 (Symtab.dest (Symtab.make_multi parms)));
       
   310 
       
   311     val parms' = map (apsnd (Envir.norm_type unifier)) (gen_distinct eq_fst parms);
       
   312     val unifier' = Vartab.extend (unifier, frozen_tvars ctxt (map #2 parms'));
       
   313 
       
   314     fun inst_parms (i, ps) =
       
   315       foldr Term.add_typ_tfrees (mapfilter snd ps, [])
       
   316       |> mapfilter (fn (a, S) =>
       
   317           let val T = Envir.norm_type unifier' (TVar ((a, i), S))
       
   318           in if T = TFree (a, S) then None else Some ((a, S), T) end);
       
   319   in map inst_parms idx_parmss end;
       
   320 
       
   321 in
       
   322 
       
   323 fun unify_elemss _ _ [] = []
       
   324   | unify_elemss _ [] [elems] = [elems]
       
   325   | unify_elemss ctxt fixed_parms elemss =
   338       let
   326       let
   339         val envs = unify_parms ctxt (map (#2 o #1) elemss);
   327         val envs = unify_parms ctxt fixed_parms (map (#2 o #1) elemss);
   340         fun inst (((name, ps), elems), env) =
   328         fun inst (((name, ps), elems), env) =
   341           ((name, map (apsnd (apsome (inst_type env))) ps), map (inst_elem env) elems);
   329           ((name, map (apsnd (apsome (inst_type env))) ps), map (inst_elem env) elems);
   342       in map inst (elemss ~~ envs) end;
   330       in map inst (elemss ~~ envs) end;
   343 
   331 
   344 in
   332 fun flatten_expr ctxt expr =
   345 
       
   346 fun eval_expr ctxt expr =
       
   347   let
   333   let
   348     val thy = ProofContext.theory_of ctxt;
   334     val thy = ProofContext.theory_of ctxt;
   349 
   335 
   350     fun renaming (Some x :: xs) (y :: ys) = (y, x) :: renaming xs ys
   336     fun renaming (Some x :: xs) (y :: ys) = (y, x) :: renaming xs ys
   351       | renaming (None :: xs) (y :: ys) = renaming xs ys
   337       | renaming (None :: xs) (y :: ys) = renaming xs ys
   384         val ren = filter_out (op =) (map #1 ps ~~ xs);
   370         val ren = filter_out (op =) (map #1 ps ~~ xs);
   385         val (params', elems') =
   371         val (params', elems') =
   386           if null ren then ((ps, qs), map #1 elems)
   372           if null ren then ((ps, qs), map #1 elems)
   387           else ((map (apfst (rename ren)) ps, map (rename ren) qs),
   373           else ((map (apfst (rename ren)) ps, map (rename ren) qs),
   388             map (rename_elem ren o #1) elems);
   374             map (rename_elem ren o #1) elems);
   389         val elems'' = map (qualify_elem [NameSpace.base name, space_implode "_" xs]) elems';
   375         val elems'' = map (rename_facts [NameSpace.base name, space_implode "_" xs]) elems';
   390       in ((name, params'), elems'') end;
   376       in ((name, params'), elems'') end;
   391 
   377 
   392     val raw_elemss = unique_parms ctxt (map eval (#1 (identify (([], []), expr))));
   378     val raw_elemss = unique_parms ctxt (map eval (#1 (identify (([], []), expr))));
   393     val elemss = inst_types ctxt raw_elemss;
   379     val elemss = unify_elemss ctxt [] raw_elemss;
   394   in elemss end;
   380   in elemss end;
   395 
   381 
   396 end;
   382 end;
   397 
   383 
   398 
   384 
   399 
   385 (* activate elements *)
   400 (** activation **)
   386 
   401 
   387 fun declare_fixes (s: string) fixes = (PolyML.print s; PolyML.print fixes;
   402 (* internalize elems *)
   388   ProofContext.add_syntax fixes o
       
   389   ProofContext.fix_direct (map (fn (x, T, _) => ([x], T)) fixes));
   403 
   390 
   404 local
   391 local
   405 
   392 
   406 fun perform_elems f named_elems = ProofContext.qualified (fn context =>
   393 fun activate_elem (Fixes fixes) = declare_fixes "activate_elem" fixes
   407   foldl (fn (ctxt, ((name, ps), es)) =>
       
   408     foldl (fn (c, e) => f e c) (ctxt, es) handle ProofContext.CONTEXT (msg, ctxt) =>
       
   409       err_in_locale ctxt msg [(name, map fst ps)]) (context, named_elems));
       
   410 
       
   411 in
       
   412 
       
   413 fun declare_elem gen =
       
   414   let
       
   415     val gen_typ = if gen then Term.map_type_tfree (Type.param []) else I;
       
   416     val gen_term = if gen then Term.map_term_types gen_typ else I;
       
   417 
       
   418     fun declare (Fixes fixes) = ProofContext.add_syntax fixes o
       
   419           ProofContext.fix_direct (map (fn (x, T, _) => ([x], apsome gen_typ T)) fixes)
       
   420       | declare (Assumes asms) = (fn ctxt => #1 (ProofContext.bind_propp_i
       
   421           (ctxt, map (map (fn (t, (ps, ps')) =>
       
   422             (gen_term t, (map gen_term ps, map gen_term ps'))) o #2) asms)))
       
   423       | declare (Defines defs) = (fn ctxt => #1 (ProofContext.bind_propp_i
       
   424           (ctxt, map (fn (_, (t, ps)) => [(gen_term t, (map gen_term ps, []))]) defs)))
       
   425       | declare (Notes _) = I;
       
   426   in declare end;
       
   427 
       
   428 fun activate_elem (Fixes fixes) = ProofContext.add_syntax fixes o
       
   429       ProofContext.fix_direct (map (fn (x, T, _) => ([x], T)) fixes)
       
   430   | activate_elem (Assumes asms) =
   394   | activate_elem (Assumes asms) =
   431       #1 o ProofContext.assume_i ProofContext.export_assume asms o
   395       #1 o ProofContext.assume_i ProofContext.export_assume asms o
   432       ProofContext.fix_frees (flat (map (map #1 o #2) asms))
   396       ProofContext.fix_frees (flat (map (map #1 o #2) asms))
   433   | activate_elem (Defines defs) = (fn ctxt => #1 (ProofContext.assume_i ProofContext.export_def
   397   | activate_elem (Defines defs) = (fn ctxt => #1 (ProofContext.assume_i ProofContext.export_def
   434       (map (fn ((name, atts), (t, ps)) =>
   398       (map (fn ((name, atts), (t, ps)) =>
   435         let val (c, t') = ProofContext.cert_def ctxt t
   399         let val (c, t') = ProofContext.cert_def ctxt t
   436         in ((if name = "" then Thm.def_name c else name, atts), [(t', (ps, []))]) end) defs) ctxt))
   400         in ((if name = "" then Thm.def_name c else name, atts), [(t', (ps, []))]) end) defs) ctxt))
   437   | activate_elem (Notes facts) = #1 o ProofContext.have_thmss facts;
   401   | activate_elem (Notes facts) = #1 o ProofContext.have_thmss facts;
   438 
   402 
   439 fun declare_elemss gen = perform_elems (declare_elem gen);
   403 in
   440 fun activate_elemss x = perform_elems activate_elem x;
   404 
   441 
   405 fun activate_elems ((name, ps), elems) = ProofContext.qualified (fn ctxt =>
   442 end;
   406   foldl (fn (c, e) => activate_elem e c) (ctxt, elems) handle ProofContext.CONTEXT (msg, ctxt) =>
   443 
   407     err_in_locale ctxt msg [(name, map fst ps)]);
   444 
   408 
   445 (* context specifications: import expression + external elements *)
   409 end;
       
   410 
       
   411 
       
   412 
       
   413 (** prepare context elements **)
       
   414 
       
   415 (* expressions *)
       
   416 
       
   417 fun intern_expr sg (Locale xname) = Locale (intern sg xname)
       
   418   | intern_expr sg (Merge exprs) = Merge (map (intern_expr sg) exprs)
       
   419   | intern_expr sg (Rename (expr, xs)) = Rename (intern_expr sg expr, xs);
       
   420 
       
   421 
       
   422 (* parameters *)
   446 
   423 
   447 local
   424 local
       
   425 
       
   426 fun prep_fixes prep_vars ctxt fixes =
       
   427   let val vars = snd (foldl_map prep_vars (ctxt, map (fn (x, T, _) => ([x], T)) fixes))
       
   428   in map (fn (([x'], T'), (_, _, mx)) => (x', T', mx)) (vars ~~ fixes) end;
       
   429 
       
   430 in
       
   431 
       
   432 fun read_fixes x = prep_fixes ProofContext.read_vars x;
       
   433 fun cert_fixes x = prep_fixes ProofContext.cert_vars x;
       
   434 
       
   435 end;
       
   436 
       
   437 
       
   438 (* propositions and bindings *)
       
   439 
       
   440 datatype ('a, 'b) int_ext = Int of 'a | Ext of 'b;
       
   441 
       
   442 local
       
   443 
       
   444 fun declare_int_elem i (ctxt, Fixes fixes) =
       
   445       (ctxt |> declare_fixes "declare_int_elem" (map (fn (x, T, mx) =>
       
   446         (x, apsome (Term.map_type_tfree (Type.param i)) T, mx)) fixes), [])
       
   447   | declare_int_elem _ (ctxt, _) = (ctxt, []);
       
   448 
       
   449 fun declare_ext_elem prep_fixes (ctxt, Fixes fixes) =
       
   450       (ctxt |> declare_fixes "declare_ext_elem" (prep_fixes ctxt fixes), [])
       
   451   | declare_ext_elem _ (ctxt, Assumes asms) = (ctxt, map #2 asms)
       
   452   | declare_ext_elem _ (ctxt, Defines defs) = (ctxt, map (fn (_, (t, ps)) => [(t, (ps, []))]) defs)
       
   453   | declare_ext_elem _ (ctxt, Notes facts) = (ctxt, []);
       
   454 
       
   455 fun declare_elems prep_fixes ((ctxt, i), ((name, ps), elems)) =
       
   456   let val (ctxt', propps) =
       
   457     (case elems of
       
   458       Int es => foldl_map (declare_int_elem i) (ctxt, es)
       
   459     | Ext es => foldl_map (declare_ext_elem prep_fixes) (ctxt, es))
       
   460     handle ProofContext.CONTEXT (msg, ctxt) => err_in_locale ctxt msg [(name, map fst ps)]
       
   461   in ((ctxt', i + 1), propps) end;
       
   462 
   448 
   463 
   449 fun close_frees ctxt t =
   464 fun close_frees ctxt t =
   450   let val frees = rev (filter_out (ProofContext.is_fixed ctxt o #1) (Term.add_frees ([], t)))
   465   let val frees = rev (filter_out (ProofContext.is_fixed ctxt o #1) (Term.add_frees ([], t)))
   451   in Term.list_all_free (frees, t) end;
   466   in Term.list_all_free (frees, t) end;
   452 
   467 
   453 (*quantify dangling frees, strip term bindings*)
       
   454 fun closeup ctxt (Assumes asms) = Assumes (asms |> map (fn (a, propps) =>
   468 fun closeup ctxt (Assumes asms) = Assumes (asms |> map (fn (a, propps) =>
   455       (a, map (fn (t, _) => (close_frees ctxt t, ([], []))) propps)))
   469       (a, map (fn (t, _) => (close_frees ctxt t, ([], []))) propps)))
   456   | closeup ctxt (Defines defs) = Defines (defs |> map (fn (a, (t, _)) =>
   470   | closeup ctxt (Defines defs) = Defines (defs |> map (fn (a, (t, _)) =>
   457       (a, (close_frees ctxt (#2 (ProofContext.cert_def ctxt t)), []))))
   471       (a, (close_frees ctxt (#2 (ProofContext.cert_def ctxt t)), []))))
   458   | closeup ctxt elem = elem;
   472   | closeup ctxt elem = elem;
   459 
   473 
   460 fun fixes_of_elem (Fixes fixes) = map (fn (x, T, _) => (x, T)) fixes
   474 fun finish_elem parms _ (Fixes fixes, _) = Ext (Fixes (map (fn (x, _, mx) =>
   461   | fixes_of_elem _ = [];
   475       (x, assoc_string (parms, x), mx)) fixes))
   462 
   476   | finish_elem _ close (Assumes asms, propp) = Ext (close (Assumes (map #1 asms ~~ propp)))
   463 fun prepare_context prep_expr prep_elem1 prep_elem2 close (import, elements) context =
   477   | finish_elem _ close (Defines defs, propp) =
   464   let
   478       Ext (close (Defines (map #1 defs ~~ map (fn [(t, (ps, []))] => (t, ps)) propp)))
   465     fun declare_expr (c, raw_expr) =
   479   | finish_elem _ _ (Notes facts, _) = Ext (Notes facts);
       
   480 
       
   481 fun finish_elems ctxt parms close (((name, ps), elems), propps) =
       
   482   let
       
   483     val elems' =
       
   484       (case elems of
       
   485         Int es => map Int (#2 (hd (unify_elemss ctxt parms [((name, ps), es)])))
       
   486       | Ext es => map2 (finish_elem parms close) (es, propps));
       
   487     val ps' = map (fn (x, _) => (x, assoc (parms, x))) ps;
       
   488   in ((name, ps'), elems') end;
       
   489 
       
   490 
       
   491 fun prep_elemss prep_fixes prepp do_close context fixed_params raw_elemss raw_concl =
       
   492   let
       
   493     val ((raw_ctxt, maxidx), raw_proppss) =
       
   494       foldl_map (declare_elems prep_fixes) ((context, 0), raw_elemss);
       
   495     val raw_propps = map flat raw_proppss;
       
   496     val raw_propp = flat raw_propps;
       
   497     val (ctxt, all_propp) =
       
   498       prepp (ProofContext.declare_terms (map Free fixed_params) raw_ctxt, raw_concl @ raw_propp);
       
   499     val ctxt = ProofContext.declare_terms (flat (map (map fst) all_propp)) ctxt;
       
   500 
       
   501     val all_propp' = map2 (op ~~)
       
   502       (#1 (#2 (ProofContext.bind_propp_schematic_i (ctxt, all_propp))), map (map snd) all_propp);
       
   503     val n = length raw_concl;
       
   504     val concl = take (n, all_propp');
       
   505     val propp = drop (n, all_propp');
       
   506     val propps = unflat raw_propps propp;
       
   507     val proppss = map2 (uncurry unflat) (raw_proppss, propps);
       
   508 
       
   509     val xs = map #1 (params_of raw_elemss);
       
   510     val typing = unify_frozen ctxt maxidx
       
   511       (map (ProofContext.default_type raw_ctxt) xs)
       
   512       (map (ProofContext.default_type ctxt) xs);
       
   513     val parms = param_types (xs ~~ typing);
       
   514 
       
   515     val close = if do_close then closeup ctxt else I;
       
   516     val elemss = map2 (finish_elems ctxt parms close) (raw_elemss, proppss);
       
   517   in (parms, elemss, concl) end;
       
   518 
       
   519 in
       
   520 
       
   521 fun read_elemss x = prep_elemss read_fixes ProofContext.read_propp_schematic x;
       
   522 fun cert_elemss x = prep_elemss cert_fixes ProofContext.cert_propp_schematic x;
       
   523 
       
   524 end;
       
   525 
       
   526 
       
   527 (* facts *)
       
   528 
       
   529 local
       
   530 
       
   531 fun prep_name ctxt (name, atts) =
       
   532   if NameSpace.is_qualified name then
       
   533     raise ProofContext.CONTEXT ("Illegal qualified name: " ^ quote name, ctxt)
       
   534   else (name, atts);
       
   535 
       
   536 fun prep_facts _ _ (Int elem) = elem
       
   537   | prep_facts _ _ (Ext (Fixes fixes)) = Fixes fixes
       
   538   | prep_facts _ ctxt (Ext (Assumes asms)) = Assumes (map (apfst (prep_name ctxt)) asms)
       
   539   | prep_facts _ ctxt (Ext (Defines defs)) = Defines (map (apfst (prep_name ctxt)) defs)
       
   540   | prep_facts get ctxt (Ext (Notes facts)) = Notes (facts |> map (fn (a, bs) =>
       
   541       (prep_name ctxt a, map (apfst (get ctxt)) bs)));
       
   542 
       
   543 in
       
   544 
       
   545 fun get_facts x = prep_facts ProofContext.get_thms x;
       
   546 fun get_facts_i x = prep_facts (K I) x;
       
   547 
       
   548 end;
       
   549 
       
   550 
       
   551 (* attributes *)
       
   552 
       
   553 local fun read_att attrib (x, srcs) = (x, map attrib srcs) in
       
   554 
       
   555 fun attribute _ (Elem (Fixes fixes)) = Elem (Fixes fixes)
       
   556   | attribute attrib (Elem (Assumes asms)) = Elem (Assumes (map (apfst (read_att attrib)) asms))
       
   557   | attribute attrib (Elem (Defines defs)) = Elem (Defines (map (apfst (read_att attrib)) defs))
       
   558   | attribute attrib (Elem (Notes facts)) =
       
   559       Elem (Notes (map (apfst (read_att attrib) o apsnd (map (read_att attrib))) facts))
       
   560   | attribute _ (Expr expr) = Expr expr;
       
   561 
       
   562 end;
       
   563 
       
   564 
       
   565 
       
   566 (** prepare context statements: import + elements + conclusion **)
       
   567 
       
   568 local
       
   569 
       
   570 fun prep_context_statement prep_expr prep_elemss prep_facts
       
   571     close fixed_params import elements raw_concl context =
       
   572   let
       
   573     val sign = ProofContext.sign_of context;
       
   574     fun flatten (Elem (Fixes fixes)) = [(("", map (rpair None o #1) fixes), Ext [Fixes fixes])]
       
   575       | flatten (Elem elem) = [(("", []), Ext [elem])]
       
   576       | flatten (Expr expr) = map (apsnd Int) (flatten_expr context (prep_expr sign expr));
       
   577 
       
   578     val raw_import_elemss = flatten (Expr import);
       
   579     val raw_elemss = flat (map flatten elements);
       
   580     val (parms, all_elemss, concl) =
       
   581       prep_elemss close context fixed_params (raw_import_elemss @ raw_elemss) raw_concl;
       
   582 
       
   583     fun activate_facts (ctxt, ((name, ps), raw_elems)) =
   466       let
   584       let
   467         val expr = prep_expr c raw_expr;
   585         val elems = map (prep_facts ctxt) raw_elems;
   468         val named_elemss = eval_expr c expr;
       
   469       in (c |> declare_elemss true named_elemss, named_elemss) end;
       
   470 
       
   471     fun declare_element (c, Elem raw_elem) =
       
   472           let
       
   473             val elem = (if close then closeup c else I) (prep_elem2 c (prep_elem1 c raw_elem));
       
   474             val res = [(("", fixes_of_elem elem), [elem])];
       
   475           in (c |> declare_elemss false res, res) end
       
   476       | declare_element (c, Expr raw_expr) =
       
   477           apsnd (map (apsnd (map (int_facts c)))) (declare_expr (c, raw_expr));
       
   478 
       
   479     fun activate_elems (c, ((name, ps), raw_elems)) =
       
   480       let
       
   481         val elems = map (get_facts c) raw_elems;
       
   482         val res = ((name, ps), elems);
   586         val res = ((name, ps), elems);
   483       in (c |> activate_elemss [res], res) end;
   587       in (ctxt |> activate_elems res, res) end;
   484 
   588 
   485     val (import_ctxt, import_elemss) = declare_expr (context, import);
   589     val n = length raw_import_elemss;
   486     val (ctxt, elemss) = apsnd flat (foldl_map declare_element (import_ctxt, elements));
   590     val (import_ctxt, import_elemss) = foldl_map activate_facts (context, take (n, all_elemss));
   487     val type_env = frozen_tvars ctxt (mapfilter (ProofContext.default_type ctxt o #1)
   591     val (ctxt, elemss) = foldl_map activate_facts (import_ctxt, drop (n, all_elemss));
   488       (fixes_of_elemss import_elemss @ fixes_of_elemss elemss));
   592   in (((import_ctxt, import_elemss), (ctxt, elemss)), concl) end;
   489 
   593 
   490     fun inst_elems ((name, ps), elems) = ((name, ps), elems);    (* FIXME *)
   594 val gen_context = prep_context_statement intern_expr read_elemss get_facts;
   491 
   595 val gen_context_i = prep_context_statement (K I) cert_elemss get_facts_i;
   492     val import_elemss' = map inst_elems import_elemss;
   596 
   493     val import_ctxt' = context |> activate_elemss import_elemss';
   597 fun gen_statement prep_locale prep_ctxt raw_locale elems concl ctxt =
   494     val (ctxt', elemss') = foldl_map activate_elems (import_ctxt', map inst_elems elemss);
   598   let
   495   in ((import_ctxt', import_elemss'), (ctxt', elemss')) end;
   599     val thy = ProofContext.theory_of ctxt;
   496 
   600     val locale = apsome (prep_locale (Theory.sign_of thy)) raw_locale;
   497 val prep_context = prepare_context read_expr read_elem ext_facts;
   601     val (fixed_params, import) =
   498 val prep_context_i = prepare_context (K I) cert_elem int_facts;
   602       (case locale of None => ([], empty)
       
   603       | Some name => (param_types (#1 (#params (the_locale thy name))), Locale name));
       
   604     val (((locale_ctxt, _), (elems_ctxt, _)), concl') =
       
   605       prep_ctxt false fixed_params import elems concl ctxt;
       
   606   in (locale, locale_ctxt, elems_ctxt, concl') end;
   499 
   607 
   500 in
   608 in
   501 
   609 
   502 val read_context = prep_context true;
   610 fun read_context x y z = #1 (gen_context true [] x y [] z);
   503 val cert_context = prep_context_i true;
   611 fun cert_context x y z = #1 (gen_context_i true [] x y [] z);
   504 val activate_context = pairself fst oo prep_context false;
   612 val read_context_statement = gen_statement intern gen_context;
   505 val activate_context_i = pairself fst oo prep_context_i false;
   613 val cert_context_statement = gen_statement (K I) gen_context_i;
   506 fun activate_locale name = #1 o activate_context_i (Locale name, []);
       
   507 
   614 
   508 end;
   615 end;
   509 
   616 
   510 
   617 
   511 
   618 
   513 
   620 
   514 fun print_locale thy raw_expr =
   621 fun print_locale thy raw_expr =
   515   let
   622   let
   516     val sg = Theory.sign_of thy;
   623     val sg = Theory.sign_of thy;
   517     val thy_ctxt = ProofContext.init thy;
   624     val thy_ctxt = ProofContext.init thy;
   518     val (ctxt, elemss) = #1 (read_context (raw_expr, []) thy_ctxt);
   625     val (ctxt, elemss) = #1 (read_context raw_expr [] thy_ctxt);
   519 
   626 
   520     val prt_typ = Pretty.quote o ProofContext.pretty_typ ctxt;
   627     val prt_typ = Pretty.quote o ProofContext.pretty_typ ctxt;
   521     val prt_term = Pretty.quote o ProofContext.pretty_term ctxt;
   628     val prt_term = Pretty.quote o ProofContext.pretty_term ctxt;
   522     val prt_thm = Pretty.quote o ProofContext.pretty_thm ctxt;
   629     val prt_thm = Pretty.quote o ProofContext.pretty_thm ctxt;
   523 
   630 
   561     val _ = conditional (is_some (get_locale thy name)) (fn () =>
   668     val _ = conditional (is_some (get_locale thy name)) (fn () =>
   562       error ("Duplicate definition of locale " ^ quote name));
   669       error ("Duplicate definition of locale " ^ quote name));
   563 
   670 
   564     val thy_ctxt = ProofContext.init thy;
   671     val thy_ctxt = ProofContext.init thy;
   565     val ((import_ctxt, import_elemss), (body_ctxt, body_elemss)) =
   672     val ((import_ctxt, import_elemss), (body_ctxt, body_elemss)) =
   566       prep_context (raw_import, raw_body) thy_ctxt;
   673       prep_context raw_import raw_body thy_ctxt;
   567     val import_parms = fixes_of_elemss import_elemss;
   674     val import_parms = params_of import_elemss;
   568     val import = (prep_expr thy_ctxt raw_import);
   675     val import = (prep_expr sign raw_import);
   569 
   676 
   570     val elems = flat (map snd body_elemss);
   677     val elems = flat (map snd body_elemss);
   571     val body_parms = fixes_of_elemss body_elemss;
   678     val body_parms = params_of body_elemss;
   572     val text = ([], []);  (* FIXME *)
   679     val text = ([], []);  (* FIXME *)
   573   in
   680   in
   574     thy
   681     thy
   575     |> declare_locale name
   682     |> declare_locale name
   576     |> put_locale name (make_locale import (map (fn e => (e, stamp ())) elems)
   683     |> put_locale name (make_locale import (map (fn e => (e, stamp ())) elems)
   577       (import_parms @ body_parms, map #1 body_parms) text)
   684       (import_parms @ body_parms, map #1 body_parms) text)
   578   end;
   685   end;
   579 
   686 
   580 in
   687 in
   581 
   688 
   582 val add_locale = gen_add_locale read_context read_expr;
   689 val add_locale = gen_add_locale read_context intern_expr;
   583 val add_locale_i = gen_add_locale cert_context (K I);
   690 val add_locale_i = gen_add_locale cert_context (K I);
   584 
   691 
   585 end;
   692 end;
   586 
   693 
   587 
   694 
   592   let
   699   let
   593     val {import, params, elems, text} = the_locale thy name;
   700     val {import, params, elems, text} = the_locale thy name;
   594     val note = Notes (map (fn ((a, ths), atts) =>
   701     val note = Notes (map (fn ((a, ths), atts) =>
   595       ((a, atts), [(map (curry Thm.name_thm a) ths, [])])) args);
   702       ((a, atts), [(map (curry Thm.name_thm a) ths, [])])) args);
   596   in
   703   in
   597     thy |> ProofContext.init |> activate_locale name |> activate_elem note;  (*test attributes!*)
   704     thy |> ProofContext.init
       
   705     |> cert_context_statement (Some name) [Elem note] [];    (*test attributes!*)
   598     thy |> put_locale name (make_locale import (elems @ [(note, stamp ())]) params text)
   706     thy |> put_locale name (make_locale import (elems @ [(note, stamp ())]) params text)
   599   end;
   707   end;
   600 
   708 
   601 
   709 
   602 
   710