src/Pure/Isar/locale.ML
changeset 13394 b39347206719
parent 13375 7cbf2dea46d0
child 13399 c136276dc847
equal deleted inserted replaced
13393:bd976af8bf18 13394:b39347206719
    44   val cert_context_statement: string option -> context attribute element_i list ->
    44   val cert_context_statement: string option -> context attribute element_i list ->
    45     (term * (term list * term list)) list list -> context ->
    45     (term * (term list * term list)) list list -> context ->
    46     string option * context * context * (term * (term list * term list)) list list
    46     string option * context * context * (term * (term list * term list)) list list
    47   val print_locales: theory -> unit
    47   val print_locales: theory -> unit
    48   val print_locale: theory -> expr -> context attribute element list -> unit
    48   val print_locale: theory -> expr -> context attribute element list -> unit
    49   val add_locale: bstring option option -> bstring
    49   val add_locale: bool -> bstring -> expr -> context attribute element list -> theory -> theory
    50     -> expr -> context attribute element list -> theory -> theory
    50   val add_locale_i: bool -> bstring -> expr -> context attribute element_i list
    51   val add_locale_i: bstring option option -> bstring
    51     -> theory -> theory
    52     -> expr -> context attribute element_i list -> theory -> theory
       
    53   val smart_have_thmss: string -> (string * 'a) Library.option ->
    52   val smart_have_thmss: string -> (string * 'a) Library.option ->
    54     ((bstring * theory attribute list) * (thm list * theory attribute list) list) list ->
    53     ((bstring * theory attribute list) * (thm list * theory attribute list) list) list ->
    55     theory -> theory * (bstring * thm list) list
    54     theory -> theory * (bstring * thm list) list
    56   val have_thmss: string -> xstring ->
    55   val have_thmss: string -> xstring ->
    57     ((bstring * context attribute list) * (xstring * context attribute list) list) list ->
    56     ((bstring * context attribute list) * (xstring * context attribute list) list) list ->
    64   val setup: (theory -> theory) list
    63   val setup: (theory -> theory) list
    65 end;
    64 end;
    66 
    65 
    67 structure Locale: LOCALE =
    66 structure Locale: LOCALE =
    68 struct
    67 struct
    69 
       
    70 
    68 
    71 (** locale elements and expressions **)
    69 (** locale elements and expressions **)
    72 
    70 
    73 type context = ProofContext.context;
    71 type context = ProofContext.context;
    74 
    72 
   202   | rename_elem ren (Notes facts) = Notes (map (apsnd (map (apfst (map (rename_thm ren))))) facts);
   200   | rename_elem ren (Notes facts) = Notes (map (apsnd (map (apfst (map (rename_thm ren))))) facts);
   203 
   201 
   204 fun rename_facts prfx elem =
   202 fun rename_facts prfx elem =
   205   let
   203   let
   206     fun qualify (arg as ((name, atts), x)) =
   204     fun qualify (arg as ((name, atts), x)) =
   207       if prfx = "" orelse name = "" orelse NameSpace.is_qualified name then arg
   205       if prfx = "" orelse name = "" then arg
   208       else ((NameSpace.pack [prfx, name], atts), x);
   206       else ((NameSpace.pack [prfx, name], atts), x);
   209   in
   207   in
   210     (case elem of
   208     (case elem of
   211       Fixes fixes => Fixes fixes
   209       Fixes fixes => Fixes fixes
   212     | Assumes asms => Assumes (map qualify asms)
   210     | Assumes asms => Assumes (map qualify asms)
   543       err "Attempt to redefine variable");
   541       err "Attempt to redefine variable");
   544     (Term.add_frees (xs, b'), (Free (y, T), b') :: env, th :: ths)
   542     (Term.add_frees (xs, b'), (Free (y, T), b') :: env, th :: ths)
   545   end;
   543   end;
   546 
   544 
   547 fun eval_text _ _ _ (text, Fixes _) = text
   545 fun eval_text _ _ _ (text, Fixes _) = text
   548   | eval_text _ _ do_text ((spec, (xs, env, defs)), Assumes asms) =
   546   | eval_text _ _ is_ext ((((exts, exts'), (ints, ints')), (xs, env, defs)), Assumes asms) =
   549       let val ts = map (norm_term env) (flat (map (map #1 o #2) asms))
   547       let
   550       in (if do_text then spec @ ts else spec, (foldl Term.add_frees (xs, ts), env, defs)) end
   548         val ts = flat (map (map #1 o #2) asms);
       
   549         val ts' = map (norm_term env) ts;
       
   550         val spec' =
       
   551           if is_ext then ((exts @ ts, exts' @ ts'), (ints, ints'))
       
   552           else ((exts, exts'), (ints @ ts, ints' @ ts'));
       
   553       in (spec', (foldl Term.add_frees (xs, ts'), env, defs)) end
   551   | eval_text ctxt id _ ((spec, binds), Defines defs) =
   554   | eval_text ctxt id _ ((spec, binds), Defines defs) =
   552       (spec, foldl (bind_def ctxt id) (binds, map (#1 o #2) defs))
   555       (spec, foldl (bind_def ctxt id) (binds, map (#1 o #2) defs))
   553   | eval_text _ _ _ (text, Notes _) = text;
   556   | eval_text _ _ _ (text, Notes _) = text;
   554 
   557 
   555 fun closeup _ false elem = elem
   558 fun closeup _ false elem = elem
   623     val typing = unify_frozen ctxt 0
   626     val typing = unify_frozen ctxt 0
   624       (map (ProofContext.default_type raw_ctxt) xs)
   627       (map (ProofContext.default_type raw_ctxt) xs)
   625       (map (ProofContext.default_type ctxt) xs);
   628       (map (ProofContext.default_type ctxt) xs);
   626     val parms = param_types (xs ~~ typing);
   629     val parms = param_types (xs ~~ typing);
   627 
   630 
   628     val (text, elemss) =
   631     val (text, elemss) = finish_elemss ctxt parms do_close
   629       finish_elemss ctxt parms do_close (([], ([], [], [])), raw_elemss ~~ proppss);
   632       (((([], []), ([], [])), ([], [], [])), raw_elemss ~~ proppss);
   630   in ((parms, elemss, concl), text) end;
   633   in ((parms, elemss, concl), text) end;
   631 
   634 
   632 in
   635 in
   633 
   636 
   634 fun read_elemss x = prep_elemss read_fixes ProofContext.read_propp_schematic x;
   637 fun read_elemss x = prep_elemss read_fixes ProofContext.read_propp_schematic x;
   678 
   681 
   679     val (import_ids, raw_import_elemss) = flatten ([], Expr import);
   682     val (import_ids, raw_import_elemss) = flatten ([], Expr import);
   680     val raw_elemss = flat (#2 ((foldl_map flatten (import_ids, elements))));
   683     val raw_elemss = flat (#2 ((foldl_map flatten (import_ids, elements))));
   681     val ((parms, all_elemss, concl), (spec, (_, _, defs))) = prep_elemss do_close
   684     val ((parms, all_elemss, concl), (spec, (_, _, defs))) = prep_elemss do_close
   682       context fixed_params (raw_import_elemss @ raw_elemss) raw_concl;
   685       context fixed_params (raw_import_elemss @ raw_elemss) raw_concl;
   683 
       
   684     val xs = foldl Term.add_frees ([], spec);
       
   685     val xs' = parms |> mapfilter (fn (x, _) =>
       
   686       (case assoc_string (xs, x) of None => None | Some T => Some (x, T)));
       
   687 
   686 
   688     val n = length raw_import_elemss;
   687     val n = length raw_import_elemss;
   689     val (import_ctxt, (import_elemss, import_facts)) =
   688     val (import_ctxt, (import_elemss, import_facts)) =
   690       activate_facts prep_facts (context, take (n, all_elemss));
   689       activate_facts prep_facts (context, take (n, all_elemss));
   691     val (ctxt, (elemss, facts)) =
   690     val (ctxt, (elemss, facts)) =
   692       activate_facts prep_facts (import_ctxt, drop (n, all_elemss));
   691       activate_facts prep_facts (import_ctxt, drop (n, all_elemss));
   693   in
   692   in
   694     ((((import_ctxt, (import_elemss, import_facts)),
   693     ((((import_ctxt, (import_elemss, import_facts)),
   695       (ctxt, (elemss, facts))), (xs', spec, defs)), concl)
   694       (ctxt, (elemss, facts))), (parms, spec, defs)), concl)
   696   end;
   695   end;
   697 
   696 
   698 val gen_context = prep_context_statement intern_expr read_elemss get_facts;
   697 val gen_context = prep_context_statement intern_expr read_elemss get_facts;
   699 val gen_context_i = prep_context_statement (K I) cert_elemss get_facts_i;
   698 val gen_context_i = prep_context_statement (K I) cert_elemss get_facts_i;
   700 
   699 
   731 
   730 
   732 (* print locale *)
   731 (* print locale *)
   733 
   732 
   734 fun print_locale thy import body =
   733 fun print_locale thy import body =
   735   let
   734   let
   736     val sg = Theory.sign_of thy;
       
   737     val thy_ctxt = ProofContext.init thy;
   735     val thy_ctxt = ProofContext.init thy;
   738     val (((_, (import_elemss, _)), (ctxt, (elemss, _))), _) = read_context import body thy_ctxt;
   736     val (((_, (import_elemss, _)), (ctxt, (elemss, _))), _) = read_context import body thy_ctxt;
   739     val all_elems = flat (map #2 (import_elemss @ elemss));
   737     val all_elems = flat (map #2 (import_elemss @ elemss));
   740 
   738 
   741     val prt_typ = Pretty.quote o ProofContext.pretty_typ ctxt;
   739     val prt_typ = Pretty.quote o ProofContext.pretty_typ ctxt;
   832 (* predicate text *)
   830 (* predicate text *)
   833 
   831 
   834 local
   832 local
   835 
   833 
   836 val introN = "intro";
   834 val introN = "intro";
   837 val axiomsN = "axioms";
   835 val axiomsN = "_axioms";
   838 
   836 
   839 fun atomize_spec sign ts =
   837 fun atomize_spec sign ts =
   840   let
   838   let
   841     val t = Library.foldr1 Logic.mk_conjunction ts;
   839     val t = Library.foldr1 Logic.mk_conjunction ts;
   842     val body = ObjectLogic.atomize_term sign t;
   840     val body = ObjectLogic.atomize_term sign t;
   844   in
   842   in
   845     if bodyT = propT then (t, propT, Thm.reflexive (Thm.cterm_of sign t))
   843     if bodyT = propT then (t, propT, Thm.reflexive (Thm.cterm_of sign t))
   846     else (body, bodyT, ObjectLogic.atomize_rule sign (Thm.cterm_of sign t))
   844     else (body, bodyT, ObjectLogic.atomize_rule sign (Thm.cterm_of sign t))
   847   end;
   845   end;
   848 
   846 
   849 fun print_translation name xs thy =
   847 fun aprop_tr' n c = (c, fn args =>
   850   let
   848   if length args = n then Syntax.const "_aprop" $ Term.list_comb (Syntax.free c, args)
   851     val n = length xs;
   849   else raise Match);
   852     fun aprop_tr' c = (c, fn args =>
   850 
   853       if length args = n then Syntax.const "_aprop" $ Term.list_comb (Syntax.free c, args)
   851 fun def_pred bname parms defs ts ts' thy =
   854       else raise Match);
       
   855   in thy |> Theory.add_trfuns ([], [], map aprop_tr' (NameSpace.accesses' name), []) end;
       
   856 
       
   857 in
       
   858 
       
   859 fun define_pred bname loc (xs, ts, defs) elemss thy =
       
   860   let
   852   let
   861     val sign = Theory.sign_of thy;
   853     val sign = Theory.sign_of thy;
   862     val name = Sign.full_name sign bname;
   854     val name = Sign.full_name sign bname;
   863 
   855 
   864 
   856     val (body, bodyT, body_eq) = atomize_spec sign ts';
   865     (* predicate definition and syntax *)
   857     val env = Term.add_term_free_names (body, []);
   866 
   858     val xs = filter (fn (x, _) => x mem_string env) parms;
   867     val (body, bodyT, body_eq) = atomize_spec sign ts;
   859     val Ts = map #2 xs;
   868     val predT = map #2 xs ---> bodyT;
   860     val extraTs = (Term.term_tfrees body \\ foldr Term.add_typ_tfrees (Ts, []))
   869     val head = Term.list_comb (Const (name, predT), map Free xs);
   861       |> Library.sort_wrt #1 |> map TFree;
       
   862     val predT = extraTs ---> Ts ---> bodyT;
       
   863 
       
   864     val args = map Logic.mk_type extraTs @ map Free xs;
       
   865     val head = Term.list_comb (Const (name, predT), args);
   870     val statement = ObjectLogic.assert_propT sign head;
   866     val statement = ObjectLogic.assert_propT sign head;
   871 
   867 
   872     val (defs_thy, [pred_def]) =
   868     val (defs_thy, [pred_def]) =
   873       thy
   869       thy
   874       |> (if bodyT = propT then print_translation name xs else I)
   870       |> (if bodyT <> propT then I else
       
   871         Theory.add_trfuns ([], [], map (aprop_tr' (length args)) (NameSpace.accesses' name), []))
   875       |> Theory.add_consts_i [(bname, predT, Syntax.NoSyn)]
   872       |> Theory.add_consts_i [(bname, predT, Syntax.NoSyn)]
   876       |> PureThy.add_defs_i false [((Thm.def_name bname, Logic.mk_equals (head, body)), [])];
   873       |> PureThy.add_defs_i false [((Thm.def_name bname, Logic.mk_equals (head, body)), [])];
       
   874 
   877     val defs_sign = Theory.sign_of defs_thy;
   875     val defs_sign = Theory.sign_of defs_thy;
   878     val cert = Thm.cterm_of defs_sign;
   876     val cert = Thm.cterm_of defs_sign;
   879 
   877 
   880 
   878     val intro = Tactic.prove_standard defs_sign [] [] statement (fn _ =>
   881     (* introduction rule *)
       
   882 
       
   883     val intro = Tactic.prove_standard defs_sign (map #1 xs) ts statement (fn _ =>
       
   884       Tactic.rewrite_goals_tac [pred_def] THEN
   879       Tactic.rewrite_goals_tac [pred_def] THEN
   885       Tactic.compose_tac (false, body_eq RS Drule.equal_elim_rule1, 1) 1 THEN
   880       Tactic.compose_tac (false, body_eq RS Drule.equal_elim_rule1, 1) 1 THEN
   886       Tactic.compose_tac (false, Drule.conj_intr_list (map (Thm.assume o cert) ts), 0) 1);
   881       Tactic.compose_tac (false, Drule.conj_intr_list (map (Thm.assume o cert) ts'), 0) 1);
   887 
       
   888 
       
   889     (* derived axioms *)
       
   890 
   882 
   891     val conjuncts =
   883     val conjuncts =
   892       Thm.assume (cert statement)
   884       Thm.assume (cert statement)
   893       |> Tactic.rewrite_rule [pred_def]
   885       |> Tactic.rewrite_rule [pred_def]
   894       |> Thm.equal_elim (Thm.symmetric body_eq)
   886       |> Thm.equal_elim (Thm.symmetric body_eq)
   895       |> Drule.conj_elim_precise (length ts);
   887       |> Drule.conj_elim_precise (length ts);
   896 
   888     val axioms = (ts ~~ conjuncts) |> map (fn (t, ax) =>
   897     val assumes = elemss |> map (fn (("", _), es) =>
       
   898         flat (es |> map (fn Assumes asms => flat (map (map #1 o #2) asms) | _ => []))
       
   899       | _ => []) |> flat;
       
   900 
       
   901     val axioms = (assumes ~~ conjuncts) |> map (fn (t, ax) =>
       
   902       Tactic.prove defs_sign [] [] t (fn _ =>
   889       Tactic.prove defs_sign [] [] t (fn _ =>
   903         Tactic.rewrite_goals_tac defs THEN
   890         Tactic.rewrite_goals_tac defs THEN
   904         Tactic.compose_tac (false, ax, 0) 1));
   891         Tactic.compose_tac (false, ax, 0) 1));
   905 
   892   in (defs_thy, (statement, intro, axioms)) end;
   906     val implies_intr_assumes = Drule.implies_intr_list (map cert assumes);
   893 
   907     fun implies_elim_axioms th = Drule.implies_elim_list (implies_intr_assumes th) axioms;
   894 fun change_elem _ (axms, Assumes asms) =
   908 
   895       apsnd Notes ((axms, asms) |> foldl_map (fn (axs, (a, spec)) =>
   909     fun change_elem (axms, Assumes asms) =
   896         let val n = length spec
   910           apsnd Notes ((axms, asms) |> foldl_map (fn (axs, (a, spec)) =>
   897         in (Library.drop (n, axs), (a, [(Library.take (n, axs), [])])) end))
   911             let val n = length spec
   898   | change_elem f (axms, Notes facts) = (axms, Notes (map (apsnd (map (apfst (map f)))) facts))
   912             in (Library.drop (n, axs), (a, [(Library.take (n, axs), [])])) end))
   899   | change_elem _ e = e;
   913       | change_elem (axms, Notes facts) =
   900 
   914           (axms, Notes (facts |> map (apsnd (map (apfst (map implies_elim_axioms))))))
   901 fun change_elemss axioms elemss = (axioms, elemss) |> foldl_map
   915       | change_elem e = e;
   902   (fn (axms, (id as ("", _), es)) =>
   916 
   903     foldl_map (change_elem (Drule.satisfy_hyps axioms)) (axms, es) |> apsnd (pair id)
   917     val elemss' = ((axioms, elemss) |> foldl_map
   904   | x => x) |> #2;
   918       (fn (axms, (id as ("", _), es)) => foldl_map change_elem (axms, es) |> apsnd (pair id)
   905 
   919         | x => x) |> #2) @
   906 in
   920       [(("", []), [Assumes [((NameSpace.pack [loc, axiomsN], []), [(statement, ([], []))])]])];
   907 
   921   in
   908 fun define_preds bname (parms, ((exts, exts'), (ints, ints')), defs) elemss thy =
   922     defs_thy
   909   let
   923     |> have_thmss_qualified "" bname
   910     val (thy', (elemss', more_ts)) =
   924       [((introN, [ContextRules.intro_query_global None]), [([intro], [])])]
   911       if Library.null exts then (thy, (elemss, []))
   925     |> #1 |> rpair elemss'
   912       else
   926   end;
   913         let
       
   914           val aname = bname ^ axiomsN;
       
   915           val (def_thy, (statement, intro, axioms)) =
       
   916             thy |> def_pred aname parms defs exts exts';
       
   917           val elemss' = change_elemss axioms elemss @
       
   918             [(("", []), [Assumes [((aname, []), [(statement, ([], []))])]])];
       
   919         in
       
   920           def_thy |> have_thmss_qualified "" aname
       
   921             [((introN, [ContextRules.intro_query_global None]), [([intro], [])])]
       
   922           |> #1 |> rpair (elemss', [statement])
       
   923         end;
       
   924     val (thy'', view) =
       
   925       if Library.null more_ts andalso Library.null ints then (thy', None)
       
   926       else
       
   927         let
       
   928           val (def_thy, (statement, intro, axioms)) =
       
   929             thy' |> def_pred bname parms defs (ints @ more_ts) (ints' @ more_ts);
       
   930         in
       
   931           def_thy |> have_thmss_qualified "" bname
       
   932             [((introN, [ContextRules.intro_query_global None]), [([intro], [])])]
       
   933           |> #1 |> rpair (Some (statement, axioms))
       
   934         end;
       
   935   in (thy'', (elemss', view)) end;
   927 
   936 
   928 end;
   937 end;
   929 
   938 
   930 
   939 
   931 (* add_locale(_i) *)
   940 (* add_locale(_i) *)
   932 
   941 
   933 local
   942 local
   934 
   943 
   935 fun gen_add_locale prep_ctxt prep_expr pname bname raw_import raw_body thy =
   944 fun gen_add_locale prep_ctxt prep_expr do_pred bname raw_import raw_body thy =
   936   let
   945   let
   937     val sign = Theory.sign_of thy;
   946     val sign = Theory.sign_of thy;
   938     val name = Sign.full_name sign bname;
   947     val name = Sign.full_name sign bname;
   939     val _ = conditional (is_some (get_locale thy name)) (fn () =>
   948     val _ = conditional (is_some (get_locale thy name)) (fn () =>
   940       error ("Duplicate definition of locale " ^ quote name));
   949       error ("Duplicate definition of locale " ^ quote name));
   942     val thy_ctxt = ProofContext.init thy;
   951     val thy_ctxt = ProofContext.init thy;
   943     val (((import_ctxt, (import_elemss, _)), (body_ctxt, (body_elemss, _))), text) =
   952     val (((import_ctxt, (import_elemss, _)), (body_ctxt, (body_elemss, _))), text) =
   944       prep_ctxt raw_import raw_body thy_ctxt;
   953       prep_ctxt raw_import raw_body thy_ctxt;
   945     val elemss = import_elemss @ body_elemss;
   954     val elemss = import_elemss @ body_elemss;
   946 
   955 
   947     val (pred_thy, elemss') =
   956     val (pred_thy, (elemss', view)) =  (* FIXME use view *)
   948       if pname = Some None orelse Library.null (#1 text) then (thy, elemss)
   957       if do_pred then thy |> define_preds bname text elemss
   949       else if pname = None then thy |> define_pred (bname ^ "_axioms") bname text elemss
   958       else (thy, (elemss, None));
   950       else thy |> define_pred (the (the pname)) bname text elemss;
       
   951     val elems' = elemss' |> filter (equal "" o #1 o #1) |> map #2 |> flat;
       
   952 
       
   953     val pred_ctxt = ProofContext.init pred_thy;
   959     val pred_ctxt = ProofContext.init pred_thy;
   954     val (ctxt, (_, facts)) = activate_facts (K I) (pred_ctxt, elemss')
   960     val (ctxt, (_, facts)) = activate_facts (K I) (pred_ctxt, elemss')
   955     val export = ProofContext.export_standard ctxt pred_ctxt;
   961     val export = ProofContext.export_standard ctxt pred_ctxt;
   956   in
   962   in
   957     pred_thy
   963     pred_thy
   958     |> have_thmss_qualified "" name (facts |> filter #2 |> map (fn ((a, ths), _) =>
   964     |> have_thmss_qualified "" name (facts |> filter #2 |> map (fn ((a, ths), _) =>
   959       ((a, []), [(map export ths, [])]))) |> #1
   965       ((a, []), [(map export ths, [])]))) |> #1
   960     |> declare_locale name
   966     |> declare_locale name
   961     |> put_locale name (make_locale (prep_expr sign raw_import)
   967     |> put_locale name (make_locale (prep_expr sign raw_import)
   962         (map (fn e => (e, stamp ())) elems')
   968         (map (fn e => (e, stamp ())) (flat (map #2 (filter (equal "" o #1 o #1) elemss'))))
   963         (params_of elemss', map #1 (params_of body_elemss)))
   969         (params_of elemss', map #1 (params_of body_elemss)))
   964   end;
   970   end;
   965 
   971 
   966 in
   972 in
   967 
   973