src/Pure/Isar/locale.ML
changeset 20035 80c79876d2de
parent 20032 2087e5634598
child 20037 d4102c7cf051
equal deleted inserted replaced
20034:28fcbcf49fe5 20035:80c79876d2de
     5 Locales -- Isar proof contexts as meta-level predicates, with local
     5 Locales -- Isar proof contexts as meta-level predicates, with local
     6 syntax and implicit structures.
     6 syntax and implicit structures.
     7 
     7 
     8 Draws basic ideas from Florian Kammueller's original version of
     8 Draws basic ideas from Florian Kammueller's original version of
     9 locales, but uses the richer infrastructure of Isar instead of the raw
     9 locales, but uses the richer infrastructure of Isar instead of the raw
    10 meta-logic.  Furthermore, we provide structured import of contexts
    10 meta-logic.  Furthermore, structured import of contexts (with merge
    11 (with merge and rename operations), as well as type-inference of the
    11 and rename operations) are provided, as well as type-inference of the
    12 signature parts, and predicate definitions of the specification text.
    12 signature parts, and predicate definitions of the specification text.
    13 
    13 
    14 Interpretation enables the reuse of theorems of locales in other
    14 Interpretation enables the reuse of theorems of locales in other
    15 contexts, namely those defined by theories, structured proofs and
    15 contexts, namely those defined by theories, structured proofs and
    16 locales themselves.
    16 locales themselves.
    93     theory -> ((string * thm list) list * (string * thm list) list) * (Proof.context * theory)
    93     theory -> ((string * thm list) list * (string * thm list) list) * (Proof.context * theory)
    94   val add_thmss: string -> string ->
    94   val add_thmss: string -> string ->
    95     ((string * Attrib.src list) * (thm list * Attrib.src list) list) list ->
    95     ((string * Attrib.src list) * (thm list * Attrib.src list) list) list ->
    96     Proof.context ->
    96     Proof.context ->
    97     ((string * thm list) list * (string * thm list) list) * Proof.context
    97     ((string * thm list) list * (string * thm list) list) * Proof.context
    98   val add_term_syntax: string -> (Proof.context -> Proof.context) -> Proof.context -> Proof.context
    98   val add_term_syntax: string -> (Proof.context -> Proof.context) ->
       
    99     cterm list * Proof.context -> Proof.context
    99 
   100 
   100   val theorem: string -> Method.text option -> (thm list list -> theory -> theory) ->
   101   val theorem: string -> Method.text option -> (thm list list -> theory -> theory) ->
   101     string * Attrib.src list -> Element.context element list -> Element.statement ->
   102     string * Attrib.src list -> Element.context element list -> Element.statement ->
   102     theory -> Proof.state
   103     theory -> Proof.state
   103   val theorem_i: string -> Method.text option -> (thm list list -> theory -> theory) ->
   104   val theorem_i: string -> Method.text option -> (thm list list -> theory -> theory) ->
   545     val unifier' = Vartab.extend (unifier, frozen_tvars ctxt (map_filter I Vs));
   546     val unifier' = Vartab.extend (unifier, frozen_tvars ctxt (map_filter I Vs));
   546   in map (Option.map (Envir.norm_type unifier')) Vs end;
   547   in map (Option.map (Envir.norm_type unifier')) Vs end;
   547 
   548 
   548 fun params_of elemss = distinct (eq_fst (op = : string * string -> bool)) (maps (snd o fst) elemss);
   549 fun params_of elemss = distinct (eq_fst (op = : string * string -> bool)) (maps (snd o fst) elemss);
   549 fun params_of' elemss = distinct (eq_fst (op = : string * string -> bool)) (maps (snd o fst o fst) elemss);
   550 fun params_of' elemss = distinct (eq_fst (op = : string * string -> bool)) (maps (snd o fst o fst) elemss);
   550 fun params_syn_of syn elemss =
       
   551   distinct (eq_fst (op =)) (maps (snd o fst) elemss) |>
       
   552     map (apfst (fn x => (x, the (Symtab.lookup syn x))));
       
   553 
   551 
   554 
   552 
   555 (* CB: param_types has the following type:
   553 (* CB: param_types has the following type:
   556   ('a * 'b option) list -> ('a * 'b) list *)
   554   ('a * 'b option) list -> ('a * 'b) list *)
   557 fun param_types ps = map_filter (fn (_, NONE) => NONE | (x, SOME T) => SOME (x, T)) ps;
   555 fun param_types ps = map_filter (fn (_, NONE) => NONE | (x, SOME T) => SOME (x, T)) ps;
   622         fun inst ((((name, ps), mode), elems), env) =
   620         fun inst ((((name, ps), mode), elems), env) =
   623           (((name, map (apsnd (Option.map (Element.instT_type env))) ps),
   621           (((name, map (apsnd (Option.map (Element.instT_type env))) ps),
   624               map_mode (map (Element.instT_witness thy env)) mode),
   622               map_mode (map (Element.instT_witness thy env)) mode),
   625             map (Element.instT_ctxt thy env) elems);
   623             map (Element.instT_ctxt thy env) elems);
   626       in map inst (elemss ~~ envs) end;
   624       in map inst (elemss ~~ envs) end;
   627 
       
   628 (* like unify_elemss, but does not touch mode, additional
       
   629    parameter c_parms for enforcing further constraints (eg. syntax) *)
       
   630 (* FIXME avoid code duplication *)
       
   631 
       
   632 fun unify_elemss' _ _ [] [] = []
       
   633   | unify_elemss' _ [] [elems] [] = [elems]
       
   634   | unify_elemss' ctxt fixed_parms elemss c_parms =
       
   635       let
       
   636         val thy = ProofContext.theory_of ctxt;
       
   637         val envs =
       
   638           unify_parms ctxt fixed_parms (map (snd o fst o fst) elemss @ map single c_parms);
       
   639         fun inst ((((name, ps), (ps', mode)), elems), env) =
       
   640           (((name, map (apsnd (Option.map (Element.instT_type env))) ps), (ps', mode)),
       
   641            map (Element.instT_ctxt thy env) elems);
       
   642       in map inst (elemss ~~ Library.take (length elemss, envs)) end;
       
   643 
   625 
   644 
   626 
   645 fun renaming xs parms = zip_options parms xs
   627 fun renaming xs parms = zip_options parms xs
   646   handle Library.UnequalLengths =>
   628   handle Library.UnequalLengths =>
   647     error ("Too many arguments in renaming: " ^
   629     error ("Too many arguments in renaming: " ^
   800        where name is a locale name, ps a list of parameter names and axs
   782        where name is a locale name, ps a list of parameter names and axs
   801        a list of axioms relating to the identifier, axs is empty unless
   783        a list of axioms relating to the identifier, axs is empty unless
   802        identify at top level (top = true);
   784        identify at top level (top = true);
   803        parms is accumulated list of parameters *)
   785        parms is accumulated list of parameters *)
   804           let
   786           let
   805             val {axiom, import, params, ...} =
   787             val {axiom, import, params, ...} = the_locale thy name;
   806               the_locale thy name;
       
   807             val ps = map (#1 o #1) params;
   788             val ps = map (#1 o #1) params;
   808             val (ids', parms', _) = identify false import;
   789             val (ids', parms') = identify false import;
   809                 (* acyclic import dependencies *)
   790                 (* acyclic import dependencies *)
   810 
   791 
   811             val ids'' = ids' @ [((name, ps), ([], Assumed []))];
   792             val ids'' = ids' @ [((name, ps), ([], Assumed []))];
   812             val (_, ids''') = add_regs (name, map #1 params) ([], ids'');
   793             val (_, ids''') = add_regs (name, map #1 params) ([], ids'');
   813             val (_, ids4) = chop (length ids' + 1) ids''';
   794             val (_, ids4) = chop (length ids' + 1) ids''';
   814             val ids5 = ids' @ ids4 @ [((name, ps), ([], Assumed []))];
   795             val ids5 = ids' @ ids4 @ [((name, ps), ([], Assumed []))];
   815             val ids_ax = if top then fst (fold_map (axiomify ps) ids5 axiom) else ids5;
   796             val ids_ax = if top then fst (fold_map (axiomify ps) ids5 axiom) else ids5;
   816             val syn = Symtab.make (map (apfst fst) params);
   797             in (ids_ax, merge_lists parms' ps) end
   817             in (ids_ax, merge_lists parms' ps, syn) end
       
   818       | identify top (Rename (e, xs)) =
   798       | identify top (Rename (e, xs)) =
   819           let
   799           let
   820             val (ids', parms', syn') = identify top e;
   800             val (ids', parms') = identify top e;
   821             val ren = renaming xs parms'
   801             val ren = renaming xs parms'
   822               handle ERROR msg => err_in_locale' ctxt msg ids';
   802               handle ERROR msg => err_in_locale' ctxt msg ids';
   823 
   803 
   824             val ids'' = distinct (eq_fst (op =)) (map (rename_parms top ren) ids');
   804             val ids'' = distinct (eq_fst (op =)) (map (rename_parms top ren) ids');
   825             val parms'' = distinct (op =) (maps (#2 o #1) ids'');
   805             val parms'' = distinct (op =) (maps (#2 o #1) ids'');
   826             val syn'' = fold (Symtab.insert (op =))
   806           in (ids'', parms'') end
   827                 (map (Element.rename_var ren) (Symtab.dest syn')) Symtab.empty;
       
   828           in (ids'', parms'', syn'') end
       
   829       | identify top (Merge es) =
   807       | identify top (Merge es) =
   830           fold (fn e => fn (ids, parms, syn) =>
   808           fold (fn e => fn (ids, parms) =>
   831                    let
   809                    let
   832                      val (ids', parms', syn') = identify top e
   810                      val (ids', parms') = identify top e
   833                    in
   811                    in
   834                      (merge_alists ids ids',
   812                      (merge_alists ids ids', merge_lists parms parms')
   835                       merge_lists parms parms',
       
   836                       merge_syntax ctxt ids' (syn, syn'))
       
   837                    end)
   813                    end)
   838             es ([], [], Symtab.empty);
   814             es ([], []);
   839 
   815 
   840 
   816     fun inst_wit all_params (t, th) = let
   841     (* CB: enrich identifiers by parameter types and
       
   842        the corresponding elements (with renamed parameters),
       
   843        also takes care of parameter syntax *)
       
   844 
       
   845     fun eval syn ((name, xs), axs) =
       
   846       let
       
   847         val {params = ps, lparams = qs, elems, ...} = the_locale thy name;
       
   848         val ps' = map (apsnd SOME o #1) ps;
       
   849         fun lookup_syn x = (case Symtab.lookup syn x of SOME Structure => NONE | opt => opt);
       
   850         val ren = map #1 ps' ~~ map (fn x => (x, lookup_syn x)) xs;
       
   851         val (params', elems') =
       
   852           if null ren then (ps', map #1 elems)
       
   853           else (map (apfst (Element.rename ren)) ps',
       
   854             map (Element.rename_ctxt ren o #1) elems);
       
   855         val elems'' = elems' |> map (Element.map_ctxt
       
   856           {var = I, typ = I, term = I, fact = I, attrib = I,
       
   857             name = NameSpace.qualified (space_implode "_" xs)});
       
   858       in (((name, params'), axs), elems'') end;
       
   859 
       
   860     (* type constraint for renamed parameter with syntax *)
       
   861     fun mixfix_type mx =
       
   862       SOME (Type.freeze_type (#1 (TypeInfer.paramify_dummies (TypeInfer.mixfixT mx) 0)));
       
   863 
       
   864     (* compute identifiers and syntax, merge with previous ones *)
       
   865     val (ids, _, syn) = identify true expr;
       
   866     val idents = gen_rems (eq_fst (op =)) (ids, prev_idents);
       
   867     val syntax = merge_syntax ctxt ids (syn, prev_syntax);
       
   868     (* add types to params and unify them *)
       
   869     val raw_elemss = map (eval syntax) idents;
       
   870     val elemss = unify_elemss' ctxt [] raw_elemss (map (apsnd mixfix_type) (Symtab.dest syntax));
       
   871     (* replace params in ids by params from axioms,
       
   872        adjust types in mode *)
       
   873     val all_params' = params_of' elemss;
       
   874     val all_params = param_types all_params';
       
   875     val elemss' = map (fn (((name, _), (ps, mode)), elems) =>
       
   876          (((name, map (fn p => (p, AList.lookup (op =) all_params p)) ps), mode), elems))
       
   877          elemss;
       
   878     fun inst_th (t, th) = let
       
   879          val {hyps, prop, ...} = Thm.rep_thm th;
   817          val {hyps, prop, ...} = Thm.rep_thm th;
   880          val ps = map (apsnd SOME) (fold Term.add_frees (prop :: hyps) []);
   818          val ps = map (apsnd SOME) (fold Term.add_frees (prop :: hyps) []);
   881          val [env] = unify_parms ctxt all_params [ps];
   819          val [env] = unify_parms ctxt all_params [ps];
   882          val t' = Element.instT_term env t;
   820          val t' = Element.instT_term env t;
   883          val th' = Element.instT_thm thy env th;
   821          val th' = Element.instT_thm thy env th;
   884        in (t', th') end;
   822        in (t', th') end;
   885     val final_elemss = map (fn ((id, mode), elems) =>
   823 
   886          ((id, map_mode (map (Element.map_witness inst_th)) mode), elems)) elemss';
   824     fun eval all_params tenv syn ((name, params), (locale_params, mode)) =
   887 
   825       let
       
   826         val {params = ps_mx, elems = elems_stamped, ...} = the_locale thy name;
       
   827         val elems = map fst elems_stamped;
       
   828         val ps = map fst ps_mx;
       
   829         fun lookup_syn x = (case Symtab.lookup syn x of SOME Structure => NONE | opt => opt);
       
   830         val locale_params' = map (fn p => (p, Symtab.lookup tenv p |> the)) locale_params;
       
   831         val mode' = map_mode (map (Element.map_witness (inst_wit all_params))) mode;
       
   832         val ren = map fst ps ~~ map (fn p => (p, lookup_syn p)) params;
       
   833         val [env] = unify_parms ctxt all_params [map (apfst (Element.rename ren) o apsnd SOME) ps];
       
   834         val elems' = elems
       
   835               |> map (Element.rename_ctxt ren)
       
   836               |> map (Element.map_ctxt {var = I, typ = I, term = I, fact = I, attrib = I,
       
   837                    name = NameSpace.qualified (space_implode "_" params)})
       
   838               |> map (Element.instT_ctxt thy env)
       
   839       in (((name, map (apsnd SOME) locale_params'), mode'), elems') end;
       
   840 
       
   841     (* parameters, their types and syntax *)
       
   842     val (all_params', tenv, syn) = params_of_expr ctxt [] expr ([], Symtab.empty, Symtab.empty);
       
   843     val all_params = map (fn p => (p, Symtab.lookup tenv p |> the)) all_params';
       
   844     (* compute identifiers and syntax, merge with previous ones *)
       
   845     val (ids, _) = identify true expr;
       
   846     val idents = gen_rems (eq_fst (op =)) (ids, prev_idents);
       
   847     val syntax = merge_syntax ctxt ids (syn, prev_syntax);
       
   848     (* type-instantiate elements *)
       
   849     val final_elemss = map (eval all_params tenv syntax) idents;
   888   in ((prev_idents @ idents, syntax), final_elemss) end;
   850   in ((prev_idents @ idents, syntax), final_elemss) end;
   889 
   851 
   890 end;
   852 end;
   891 
   853 
   892 
   854 
  1420       context fixed_params
  1382       context fixed_params
  1421       (raw_import_params_elemss @ raw_import_elemss @ raw_incl_params_elemss @ raw_elemss) raw_concl;
  1383       (raw_import_params_elemss @ raw_import_elemss @ raw_incl_params_elemss @ raw_elemss) raw_concl;
  1422 
  1384 
  1423     (* replace extended ids (for axioms) by ids *)
  1385     (* replace extended ids (for axioms) by ids *)
  1424     val (import_ids', incl_ids) = chop (length import_ids) ids;
  1386     val (import_ids', incl_ids) = chop (length import_ids) ids;
  1425     val add_ids = import_params_ids @ import_ids' @ incl_params_ids @ incl_ids;
  1387     val all_ids = import_params_ids @ import_ids' @ incl_params_ids @ incl_ids;
  1426     val all_elemss' = map (fn (((_, ps), _), (((n, ps'), mode), elems)) =>
  1388     val all_elemss' = map (fn (((_, ps), _), (((n, ps'), mode), elems)) =>
  1427         (((n, map (fn p => (p, (the o AList.lookup (op =) ps') p)) ps), mode), elems))
  1389         (((n, map (fn p => (p, (the o AList.lookup (op =) ps') p)) ps), mode), elems))
  1428       (add_ids ~~ all_elemss);
  1390       (all_ids ~~ all_elemss);
  1429     (* CB: all_elemss and parms contain the correct parameter types *)
  1391     (* CB: all_elemss and parms contain the correct parameter types *)
  1430 
  1392 
  1431     val (ps, qs) = chop (length raw_import_params_elemss + length raw_import_elemss) all_elemss';
  1393     val (ps, qs) = chop (length raw_import_params_elemss + length raw_import_elemss) all_elemss';
  1432     val (import_ctxt, (import_elemss, _)) =
  1394     val (import_ctxt, (import_elemss, _)) =
  1433       activate_facts false prep_facts (context, ps);
  1395       activate_facts false prep_facts (context, ps);
  1559 
  1521 
  1560 
  1522 
  1561 (* term syntax *)
  1523 (* term syntax *)
  1562 
  1524 
  1563 fun add_term_syntax loc syn =
  1525 fun add_term_syntax loc syn =
  1564   syn #> ProofContext.map_theory (change_locale loc
  1526   snd #> syn #> ProofContext.map_theory (change_locale loc
  1565     (fn (axiom, import, elems, params, lparams, term_syntax, regs, intros) =>
  1527     (fn (axiom, import, elems, params, lparams, term_syntax, regs, intros) =>
  1566       (axiom, import, elems, params, lparams, (syn, stamp ()) :: term_syntax, regs, intros)));
  1528       (axiom, import, elems, params, lparams, (syn, stamp ()) :: term_syntax, regs, intros)));
  1567 
  1529 
  1568 fun init_term_syntax loc ctxt =
  1530 fun init_term_syntax loc ctxt =
  1569   fold_rev (fn (f, _) => fn ctxt' => f ctxt')
  1531   fold_rev (fn (f, _) => fn ctxt' => f ctxt')
  1578 (* theory/locale results *)
  1540 (* theory/locale results *)
  1579 
  1541 
  1580 fun theory_results kind prefix results ctxt thy =
  1542 fun theory_results kind prefix results ctxt thy =
  1581   let
  1543   let
  1582     val thy_ctxt = ProofContext.init thy;
  1544     val thy_ctxt = ProofContext.init thy;
  1583     val export = singleton (ProofContext.export_standard ctxt thy_ctxt);
  1545     val export = ProofContext.export_view [] ctxt thy_ctxt;
  1584     val facts = map (fn (name, ths) => ((name, []), [(map export ths, [])])) results;
  1546     val facts = map (fn (name, ths) => ((name, []), [(map export ths, [])])) results;
  1585   in thy |> PureThy.note_thmss_qualified kind prefix facts end;
  1547   in thy |> PureThy.note_thmss_qualified kind prefix facts end;
  1586 
  1548 
  1587 local
  1549 local
  1588 
  1550 
  1819     val ((((elemss', predicate as (predicate_statement, predicate_axioms), stmt'), intros),
  1781     val ((((elemss', predicate as (predicate_statement, predicate_axioms), stmt'), intros),
  1820           pred_thy), (import, regs)) =
  1782           pred_thy), (import, regs)) =
  1821       if do_predicate then
  1783       if do_predicate then
  1822         let
  1784         let
  1823           val (elemss', defns) = change_defines_elemss thy elemss [];
  1785           val (elemss', defns) = change_defines_elemss thy elemss [];
  1824           val elemss'' = elemss' @
  1786           val elemss'' = elemss' @ [(("", []), defns)];
  1825 (*
       
  1826               [(("", []), [Defines (map (fn t => (("", []), (t, []))) defs)])];
       
  1827 *)
       
  1828               [(("", []), defns)];
       
  1829           val (((elemss''', predicate as (_, axioms), stmt'), intros), thy') =
  1787           val (((elemss''', predicate as (_, axioms), stmt'), intros), thy') =
  1830             define_preds bname text elemss'' thy;
  1788             define_preds bname text elemss'' thy;
  1831           fun mk_regs elemss wits =
  1789           fun mk_regs elemss wits =
  1832             fold_map (fn (id, elems) => fn wts => let
  1790             fold_map (fn (id, elems) => fn wts => let
  1833                 val ts = List.concat (List.mapPartial (fn (Assumes asms) =>
  1791                 val ts = List.concat (List.mapPartial (fn (Assumes asms) =>
  1901     val atts = map (prep_src thy) raw_atts;
  1859     val atts = map (prep_src thy) raw_atts;
  1902     val ((concl_elems, concl), mk_stmt) = conclusion (prep_src thy) raw_concl;
  1860     val ((concl_elems, concl), mk_stmt) = conclusion (prep_src thy) raw_concl;
  1903     val thy_ctxt = ProofContext.init thy;
  1861     val thy_ctxt = ProofContext.init thy;
  1904     val elems = map (prep_elem thy) (raw_elems @ concl_elems);
  1862     val elems = map (prep_elem thy) (raw_elems @ concl_elems);
  1905     val (_, _, ctxt, propp) = prep_stmt NONE elems (map snd concl) thy_ctxt;
  1863     val (_, _, ctxt, propp) = prep_stmt NONE elems (map snd concl) thy_ctxt;
  1906     val ((stmt, facts), goal_ctxt) = mk_stmt (map fst concl ~~ propp) ctxt;
  1864     val ((stmt, facts), goal_ctxt) = ctxt
       
  1865       |> ProofContext.add_view thy_ctxt []
       
  1866       |> mk_stmt (map fst concl ~~ propp);
  1907   in
  1867   in
  1908     global_goal kind before_qed after_qed (SOME "") (name, atts) stmt goal_ctxt
  1868     global_goal kind before_qed after_qed (SOME "") (name, atts) stmt goal_ctxt
  1909     |> Proof.refine_insert facts
  1869     |> Proof.refine_insert facts
  1910   end;
  1870   end;
  1911 
  1871 
  1921     val names = map (fst o fst) concl;
  1881     val names = map (fst o fst) concl;
  1922 
  1882 
  1923     val thy_ctxt = init_term_syntax loc (ProofContext.init thy);
  1883     val thy_ctxt = init_term_syntax loc (ProofContext.init thy);
  1924     val (_, loc_ctxt, elems_ctxt, propp) =
  1884     val (_, loc_ctxt, elems_ctxt, propp) =
  1925       prep_stmt (SOME raw_loc) elems (map snd concl) thy_ctxt;
  1885       prep_stmt (SOME raw_loc) elems (map snd concl) thy_ctxt;
       
  1886     val elems_ctxt' = elems_ctxt
       
  1887       |> ProofContext.add_view loc_ctxt []
       
  1888       |> ProofContext.add_view thy_ctxt [];
       
  1889     val loc_ctxt' = loc_ctxt
       
  1890       |> ProofContext.add_view thy_ctxt [];
  1926 
  1891 
  1927     val ((stmt, facts), goal_ctxt) =
  1892     val ((stmt, facts), goal_ctxt) =
  1928       mk_stmt (map (apsnd (K []) o fst) concl ~~ propp) elems_ctxt;
  1893       elems_ctxt' |> mk_stmt (map (apsnd (K []) o fst) concl ~~ propp);
  1929 
  1894 
  1930     fun after_qed' results =
  1895     fun after_qed' results =
  1931       let val loc_results = results |> map
  1896       let val loc_results = results |> map
  1932           (ProofContext.export_standard goal_ctxt loc_ctxt) in
  1897           (ProofContext.export_standard goal_ctxt loc_ctxt') in
  1933         curry (locale_results kind loc ((names ~~ loc_attss) ~~ loc_results)) loc_ctxt
  1898         curry (locale_results kind loc ((names ~~ loc_attss) ~~ loc_results)) loc_ctxt
  1934         #-> (fn res =>
  1899         #-> (fn res =>
  1935           if name = "" andalso null loc_atts then I
  1900           if name = "" andalso null loc_atts then I
  1936           else #2 o locale_results kind loc [((name, loc_atts), maps #2 res)])
  1901           else #2 o locale_results kind loc [((name, loc_atts), maps #2 res)])
  1937         #> #2
  1902         #> #2