87 |
87 |
88 type locale = |
88 type locale = |
89 {import: expr, (*dynamic import*) |
89 {import: expr, (*dynamic import*) |
90 elems: ((typ, term, thm list, context attribute) elem * stamp) list, (*static content*) |
90 elems: ((typ, term, thm list, context attribute) elem * stamp) list, (*static content*) |
91 params: (string * typ option) list * string list, (*all vs. local params*) |
91 params: (string * typ option) list * string list, (*all vs. local params*) |
92 text: (string * typ) list * term list} (*logical representation*) |
92 text: ((string * typ) list * term list) * ((string * typ) list * term list)}; (*predicate text*) |
93 |
93 |
94 fun make_locale import elems params text = |
94 fun make_locale import elems params text = |
95 {import = import, elems = elems, params = params, text = text}: locale; |
95 {import = import, elems = elems, params = params, text = text}: locale; |
96 |
96 |
97 |
97 |
273 val (unifier, _) = foldl unify ((Vartab.empty, maxidx''), Ts' ~~ Us'); |
273 val (unifier, _) = foldl unify ((Vartab.empty, maxidx''), Ts' ~~ Us'); |
274 val Vs = map (apsome (Envir.norm_type unifier)) Us'; |
274 val Vs = map (apsome (Envir.norm_type unifier)) Us'; |
275 val unifier' = Vartab.extend (unifier, frozen_tvars ctxt (mapfilter I Vs)); |
275 val unifier' = Vartab.extend (unifier, frozen_tvars ctxt (mapfilter I Vs)); |
276 in map (apsome (Envir.norm_type unifier')) Vs end; |
276 in map (apsome (Envir.norm_type unifier')) Vs end; |
277 |
277 |
278 fun params_of elemss = flat (map (snd o fst) elemss); |
278 fun params_of elemss = gen_distinct eq_fst (flat (map (snd o fst) elemss)); |
279 fun param_types ps = mapfilter (fn (_, None) => None | (x, Some T) => Some (x, T)) ps; |
279 fun param_types ps = mapfilter (fn (_, None) => None | (x, Some T) => Some (x, T)) ps; |
280 |
280 |
281 |
281 |
282 (* flatten expressions *) |
282 (* flatten expressions *) |
283 |
283 |
582 fun get_facts_i x = prep_facts (K I) x; |
582 fun get_facts_i x = prep_facts (K I) x; |
583 |
583 |
584 end; |
584 end; |
585 |
585 |
586 |
586 |
|
587 (* predicate_text *) |
|
588 |
|
589 local |
|
590 |
|
591 val norm_term = Envir.beta_norm oo Term.subst_atomic; |
|
592 |
|
593 (*assumes well-formedness according to ProofContext.cert_def*) |
|
594 fun abstract_def eq = |
|
595 let |
|
596 val body = Term.strip_all_body eq; |
|
597 val vars = map Free (Term.rename_wrt_term body (Term.strip_all_vars eq)); |
|
598 val (lhs, rhs) = Logic.dest_equals (Term.subst_bounds (vars, body)); |
|
599 val (f, xs) = Term.strip_comb lhs; |
|
600 in (Term.dest_Free f, Term.list_abs_free (map Term.dest_Free xs, rhs)) end; |
|
601 |
|
602 fun bind_def ctxt (name, ps) ((xs, ys, env), eq) = |
|
603 let |
|
604 val (y, b) = abstract_def eq; |
|
605 val b' = norm_term env b; |
|
606 fun err msg = err_in_locale ctxt (msg ^ ": " ^ quote (#1 y)) [(name, map fst ps)]; |
|
607 in |
|
608 conditional (y mem xs) (fn () => err "Attempt to define previously specified variable"); |
|
609 conditional (y mem ys) (fn () => err "Attempt to redefine variable"); |
|
610 (Term.add_frees (xs, b'), y :: ys, (Free y, b') :: env) |
|
611 end; |
|
612 |
|
613 fun eval_body _ _ (body, Fixes _) = body |
|
614 | eval_body _ _ (((xs, spec), (ys, env)), Assumes asms) = |
|
615 let val ts = map (norm_term env) (flat (map (map #1 o #2) asms)) |
|
616 in ((foldl Term.add_frees (xs, ts), spec @ ts), (ys, env)) end |
|
617 | eval_body ctxt id (((xs, spec), (ys, env)), Defines defs) = |
|
618 let val (xs', ys', env') = foldl (bind_def ctxt id) ((xs, ys, env), map (#1 o #2) defs) |
|
619 in ((xs', spec), (ys', env')) end |
|
620 | eval_body _ _ (body, Notes _) = body; |
|
621 |
|
622 fun eval_bodies ctxt = |
|
623 foldl (fn (body, (id, elems)) => foldl (eval_body ctxt id) (body, elems)); |
|
624 |
|
625 in |
|
626 |
|
627 fun predicate_text (ctxt1, elemss1) (ctxt2, elemss2) = |
|
628 let |
|
629 val parms1 = params_of elemss1; |
|
630 val parms2 = params_of elemss2; |
|
631 val all_parms = parms1 @ parms2; |
|
632 fun filter_parms xs = all_parms |> mapfilter (fn (p, _) => |
|
633 (case assoc_string (xs, p) of None => None | Some T => Some (p, T))); |
|
634 val body as ((xs1, ts1), _) = eval_bodies ctxt1 ((([], []), ([], [])), elemss1); |
|
635 val ((all_xs, all_ts), _) = eval_bodies ctxt2 (body, elemss2); |
|
636 val xs2 = Library.drop (length xs1, all_xs); |
|
637 val ts2 = Library.drop (length ts1, all_ts); |
|
638 in ((all_parms, (filter_parms all_xs, all_ts)), (parms2, (filter_parms xs2, ts2))) end; |
|
639 |
|
640 end; |
|
641 |
|
642 |
587 (* full context statements: import + elements + conclusion *) |
643 (* full context statements: import + elements + conclusion *) |
588 |
644 |
589 local |
645 local |
590 |
646 |
591 fun prep_context_statement prep_expr prep_elemss prep_facts |
647 fun prep_context_statement prep_expr prep_elemss prep_facts |
606 prep_elemss close context fixed_params (raw_import_elemss @ raw_elemss) raw_concl; |
662 prep_elemss close context fixed_params (raw_import_elemss @ raw_elemss) raw_concl; |
607 |
663 |
608 val n = length raw_import_elemss; |
664 val n = length raw_import_elemss; |
609 val (import_ctxt, import_elemss) = foldl_map activate (context, take (n, all_elemss)); |
665 val (import_ctxt, import_elemss) = foldl_map activate (context, take (n, all_elemss)); |
610 val (ctxt, elemss) = foldl_map activate (import_ctxt, drop (n, all_elemss)); |
666 val (ctxt, elemss) = foldl_map activate (import_ctxt, drop (n, all_elemss)); |
611 in (((import_ctxt, import_elemss), (ctxt, elemss)), concl) end; |
667 val text = predicate_text (import_ctxt, import_elemss) (ctxt, elemss); |
|
668 in ((((import_ctxt, import_elemss), (ctxt, elemss)), text), concl) end; |
612 |
669 |
613 val gen_context = prep_context_statement intern_expr read_elemss get_facts; |
670 val gen_context = prep_context_statement intern_expr read_elemss get_facts; |
614 val gen_context_i = prep_context_statement (K I) cert_elemss get_facts_i; |
671 val gen_context_i = prep_context_statement (K I) cert_elemss get_facts_i; |
615 |
672 |
616 fun gen_statement prep_locale prep_ctxt raw_locale elems concl ctxt = |
673 fun gen_statement prep_locale prep_ctxt raw_locale elems concl ctxt = |
618 val thy = ProofContext.theory_of ctxt; |
675 val thy = ProofContext.theory_of ctxt; |
619 val locale = apsome (prep_locale (Theory.sign_of thy)) raw_locale; |
676 val locale = apsome (prep_locale (Theory.sign_of thy)) raw_locale; |
620 val (fixed_params, import) = |
677 val (fixed_params, import) = |
621 (case locale of None => ([], empty) |
678 (case locale of None => ([], empty) |
622 | Some name => (param_types (#1 (#params (the_locale thy name))), Locale name)); |
679 | Some name => (param_types (#1 (#params (the_locale thy name))), Locale name)); |
623 val (((locale_ctxt, _), (elems_ctxt, _)), concl') = |
680 val ((((locale_ctxt, _), (elems_ctxt, _)), _), concl') = |
624 prep_ctxt false fixed_params import elems concl ctxt; |
681 prep_ctxt false fixed_params import elems concl ctxt; |
625 in (locale, locale_ctxt, elems_ctxt, concl') end; |
682 in (locale, locale_ctxt, elems_ctxt, concl') end; |
626 |
683 |
627 in |
684 in |
628 |
685 |
639 |
696 |
640 fun print_locale thy raw_expr = |
697 fun print_locale thy raw_expr = |
641 let |
698 let |
642 val sg = Theory.sign_of thy; |
699 val sg = Theory.sign_of thy; |
643 val thy_ctxt = ProofContext.init thy; |
700 val thy_ctxt = ProofContext.init thy; |
644 val (ctxt, elemss) = #1 (read_context raw_expr [] thy_ctxt); |
701 val (((ctxt, elemss), _), ((_, (pred_xs, pred_ts)), _)) = read_context raw_expr [] thy_ctxt; |
645 |
702 |
646 val prt_typ = Pretty.quote o ProofContext.pretty_typ ctxt; |
703 val prt_typ = Pretty.quote o ProofContext.pretty_typ ctxt; |
647 val prt_term = Pretty.quote o ProofContext.pretty_term ctxt; |
704 val prt_term = Pretty.quote o ProofContext.pretty_term ctxt; |
648 val prt_thm = Pretty.quote o ProofContext.pretty_thm ctxt; |
705 val prt_thm = Pretty.quote o ProofContext.pretty_thm ctxt; |
649 |
706 |
665 | items prfx (x :: xs) = Pretty.block [Pretty.str prfx, Pretty.brk 1, x] :: items " and" xs; |
722 | items prfx (x :: xs) = Pretty.block [Pretty.str prfx, Pretty.brk 1, x] :: items " and" xs; |
666 fun prt_elem (Fixes fixes) = items "fixes" (map prt_fix fixes) |
723 fun prt_elem (Fixes fixes) = items "fixes" (map prt_fix fixes) |
667 | prt_elem (Assumes asms) = items "assumes" (map prt_asm asms) |
724 | prt_elem (Assumes asms) = items "assumes" (map prt_asm asms) |
668 | prt_elem (Defines defs) = items "defines" (map prt_def defs) |
725 | prt_elem (Defines defs) = items "defines" (map prt_def defs) |
669 | prt_elem (Notes facts) = items "notes" (map prt_fact facts); |
726 | prt_elem (Notes facts) = items "notes" (map prt_fact facts); |
|
727 |
|
728 val prt_pred = |
|
729 if null pred_ts then Pretty.str "" |
|
730 else |
|
731 Library.foldr1 Logic.mk_conjunction pred_ts |
|
732 |> Thm.cterm_of sg |> ObjectLogic.atomize_cterm |> Thm.term_of |
|
733 |> curry Term.list_abs_free pred_xs |
|
734 |> prt_term; |
670 in |
735 in |
671 Pretty.big_list "context elements:" (map (Pretty.chunks o prt_elem) (flat (map #2 elemss))) |
736 [Pretty.big_list "context elements:" (map (Pretty.chunks o prt_elem) (flat (map #2 elemss))), |
672 |> Pretty.writeln |
737 Pretty.big_list "predicate text:" [prt_pred]] |> Pretty.chunks |> Pretty.writeln |
673 end; |
738 end; |
674 |
739 |
675 |
740 |
676 |
741 |
677 (** define locales **) |
742 (** define locales **) |
686 val name = Sign.full_name sign bname; |
751 val name = Sign.full_name sign bname; |
687 val _ = conditional (is_some (get_locale thy name)) (fn () => |
752 val _ = conditional (is_some (get_locale thy name)) (fn () => |
688 error ("Duplicate definition of locale " ^ quote name)); |
753 error ("Duplicate definition of locale " ^ quote name)); |
689 |
754 |
690 val thy_ctxt = ProofContext.init thy; |
755 val thy_ctxt = ProofContext.init thy; |
691 val ((import_ctxt, import_elemss), (body_ctxt, body_elemss)) = |
756 val (((import_ctxt, import_elemss), (body_ctxt, body_elemss)), |
|
757 ((all_parms, all_text), (body_parms, body_text))) = |
692 prep_context raw_import raw_body thy_ctxt; |
758 prep_context raw_import raw_body thy_ctxt; |
693 val import_parms = params_of import_elemss; |
759 val import = prep_expr sign raw_import; |
694 val import = (prep_expr sign raw_import); |
|
695 |
|
696 val elems = flat (map snd body_elemss); |
760 val elems = flat (map snd body_elemss); |
697 val body_parms = params_of body_elemss; |
|
698 val text = ([], []); (* FIXME *) |
|
699 in |
761 in |
700 thy |
762 thy |
701 |> declare_locale name |
763 |> declare_locale name |
702 |> put_locale name (make_locale import (map (fn e => (e, stamp ())) elems) |
764 |> put_locale name (make_locale import (map (fn e => (e, stamp ())) elems) |
703 (import_parms @ body_parms, map #1 body_parms) text) |
765 (all_parms, map fst body_parms) (all_text, body_text)) |
704 end; |
766 end; |
705 |
767 |
706 in |
768 in |
707 |
769 |
708 val add_locale = gen_add_locale read_context intern_expr; |
770 val add_locale = gen_add_locale read_context intern_expr; |
709 val add_locale_i = gen_add_locale cert_context (K I); |
771 val add_locale_i = gen_add_locale cert_context (K I); |
710 |
772 |
711 end; |
773 end; |
712 |
774 |
713 |
775 |
714 |
776 (* store results *) |
715 (** store results **) |
|
716 |
777 |
717 local |
778 local |
718 |
779 |
719 fun put_facts loc args thy = |
780 fun put_facts loc args thy = |
720 let |
781 let |
743 |
804 |
744 fun gen_have_thmss prep_locale get_thms kind raw_loc raw_args thy = |
805 fun gen_have_thmss prep_locale get_thms kind raw_loc raw_args thy = |
745 let |
806 let |
746 val thy_ctxt = ProofContext.init thy; |
807 val thy_ctxt = ProofContext.init thy; |
747 val loc = prep_locale (Theory.sign_of thy) raw_loc; |
808 val loc = prep_locale (Theory.sign_of thy) raw_loc; |
748 val loc_ctxt = #1 (#1 (cert_context (Locale loc) [] thy_ctxt)); |
809 val loc_ctxt = #1 (#1 (#1 (cert_context (Locale loc) [] thy_ctxt))); |
749 val args = map (apsnd (map (apfst (get_thms loc_ctxt)))) raw_args; |
810 val args = map (apsnd (map (apfst (get_thms loc_ctxt)))) raw_args; |
750 val export = Drule.local_standard o ProofContext.export_single loc_ctxt thy_ctxt; |
811 val export = Drule.local_standard o ProofContext.export_single loc_ctxt thy_ctxt; |
751 val results = map (map export o #2) (#2 (ProofContext.have_thmss_i args loc_ctxt)); |
812 val results = map (map export o #2) (#2 (ProofContext.have_thmss_i args loc_ctxt)); |
752 val args' = map (rpair [] o #1 o #1) args ~~ map (single o Thm.no_attributes) results; |
813 val args' = map (rpair [] o #1 o #1) args ~~ map (single o Thm.no_attributes) results; |
753 in |
814 in |