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 |
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 |
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 |