Merge commit 'upstream/8.0pl3+8.1beta.2' into 8.1
Samuel Mimram
17 years ago
281 | 281 | tactics/extraargs.cmi: lib/util.cmi interp/topconstr.cmi kernel/term.cmi \ |
282 | 282 | proofs/tacexpr.cmo tactics/setoid_replace.cmi pretyping/rawterm.cmi \ |
283 | 283 | proofs/proof_type.cmi parsing/pcoq.cmi kernel/names.cmi |
284 | tactics/extratactics.cmi: interp/topconstr.cmi kernel/term.cmi \ | |
284 | tactics/extratactics.cmi: lib/util.cmi interp/topconstr.cmi kernel/term.cmi \ | |
285 | 285 | proofs/tacexpr.cmo pretyping/rawterm.cmi proofs/proof_type.cmi \ |
286 | 286 | parsing/pcoq.cmi kernel/names.cmi interp/genarg.cmi |
287 | 287 | tactics/hiddentac.cmi: kernel/term.cmi tactics/tacticals.cmi \ |
428 | 428 | contrib/funind/functional_principles_proofs.cmi: kernel/term.cmi \ |
429 | 429 | proofs/tacmach.cmi kernel/names.cmi |
430 | 430 | contrib/funind/functional_principles_types.cmi: kernel/term.cmi \ |
431 | proofs/tacmach.cmi pretyping/rawterm.cmi kernel/names.cmi | |
432 | contrib/funind/indfun_common.cmi: kernel/term.cmi pretyping/rawterm.cmi \ | |
433 | lib/pp.cmi kernel/names.cmi library/libnames.cmi | |
431 | proofs/tacmach.cmi pretyping/rawterm.cmi kernel/names.cmi \ | |
432 | library/libnames.cmi kernel/entries.cmi | |
433 | contrib/funind/indfun_common.cmi: kernel/term.cmi proofs/tacexpr.cmo \ | |
434 | pretyping/rawterm.cmi lib/pp.cmi kernel/names.cmi library/libnames.cmi \ | |
435 | kernel/entries.cmi library/decl_kinds.cmo | |
434 | 436 | contrib/funind/rawtermops.cmi: lib/util.cmi pretyping/rawterm.cmi \ |
435 | 437 | kernel/names.cmi library/libnames.cmi |
436 | 438 | contrib/funind/rawterm_to_relation.cmi: interp/topconstr.cmi \ |
479 | 481 | contrib/subtac/subtac_errors.cmi: lib/util.cmi lib/pp.cmi |
480 | 482 | contrib/subtac/subtac_interp_fixpoint.cmi: lib/util.cmi interp/topconstr.cmi \ |
481 | 483 | lib/pp.cmi kernel/names.cmi library/libnames.cmi |
482 | contrib/subtac/subtac.cmi: toplevel/vernacexpr.cmo lib/util.cmi \ | |
483 | interp/topconstr.cmi kernel/names.cmi | |
484 | contrib/subtac/subtac.cmi: toplevel/vernacexpr.cmo lib/util.cmi | |
484 | 485 | contrib/subtac/subtac_pretyping.cmi: interp/topconstr.cmi kernel/term.cmi \ |
485 | 486 | kernel/sign.cmi pretyping/pretyping.cmi kernel/names.cmi \ |
486 | 487 | library/global.cmi pretyping/evd.cmi kernel/environ.cmi |
539 | 540 | ide/coqide.cmo: toplevel/vernacexpr.cmo lib/util.cmi ide/undo.cmi \ |
540 | 541 | lib/system.cmi ide/preferences.cmi lib/pp.cmi proofs/pfedit.cmi \ |
541 | 542 | ide/ideutils.cmi ide/highlight.cmo ide/find_phrase.cmo \ |
542 | ide/coq_commands.cmo ide/coq.cmi ide/command_windows.cmi \ | |
543 | ide/blaster_window.cmo ide/coqide.cmi | |
543 | config/coq_config.cmi ide/coq_commands.cmo ide/coq.cmi \ | |
544 | ide/command_windows.cmi ide/blaster_window.cmo ide/coqide.cmi | |
544 | 545 | ide/coqide.cmx: toplevel/vernacexpr.cmx lib/util.cmx ide/undo.cmx \ |
545 | 546 | lib/system.cmx ide/preferences.cmx lib/pp.cmx proofs/pfedit.cmx \ |
546 | 547 | ide/ideutils.cmx ide/highlight.cmx ide/find_phrase.cmx \ |
547 | ide/coq_commands.cmx ide/coq.cmx ide/command_windows.cmx \ | |
548 | ide/blaster_window.cmx ide/coqide.cmi | |
548 | config/coq_config.cmx ide/coq_commands.cmx ide/coq.cmx \ | |
549 | ide/command_windows.cmx ide/blaster_window.cmx ide/coqide.cmi | |
549 | 550 | ide/coq.cmo: toplevel/vernacexpr.cmo toplevel/vernacentries.cmi \ |
550 | 551 | toplevel/vernac.cmi lib/util.cmi pretyping/termops.cmi kernel/term.cmi \ |
551 | 552 | proofs/tacmach.cmi tactics/tacinterp.cmi lib/system.cmi \ |
2180 | 2181 | kernel/names.cmi library/nameops.cmi toplevel/mltop.cmi \ |
2181 | 2182 | library/library.cmi library/libnames.cmi library/lib.cmi \ |
2182 | 2183 | library/global.cmi library/declaremods.cmi kernel/declarations.cmi \ |
2183 | toplevel/coqinit.cmi config/coq_config.cmi toplevel/cerrors.cmi \ | |
2184 | toplevel/coqtop.cmi | |
2184 | toplevel/coqinit.cmi config/coq_config.cmi interp/constrintern.cmi \ | |
2185 | toplevel/cerrors.cmi toplevel/coqtop.cmi | |
2185 | 2186 | toplevel/coqtop.cmx: kernel/vm.cmx toplevel/vernac.cmx kernel/vconv.cmx \ |
2186 | 2187 | lib/util.cmx toplevel/usage.cmx toplevel/toplevel.cmx lib/system.cmx \ |
2187 | 2188 | library/states.cmx lib/profile.cmx lib/pp.cmx lib/options.cmx \ |
2188 | 2189 | kernel/names.cmx library/nameops.cmx toplevel/mltop.cmx \ |
2189 | 2190 | library/library.cmx library/libnames.cmx library/lib.cmx \ |
2190 | 2191 | library/global.cmx library/declaremods.cmx kernel/declarations.cmx \ |
2191 | toplevel/coqinit.cmx config/coq_config.cmx toplevel/cerrors.cmx \ | |
2192 | toplevel/coqtop.cmi | |
2192 | toplevel/coqinit.cmx config/coq_config.cmx interp/constrintern.cmx \ | |
2193 | toplevel/cerrors.cmx toplevel/coqtop.cmi | |
2193 | 2194 | toplevel/discharge.cmo: lib/util.cmi pretyping/termops.cmi kernel/term.cmi \ |
2194 | 2195 | kernel/sign.cmi kernel/names.cmi kernel/inductive.cmi kernel/entries.cmi \ |
2195 | 2196 | kernel/declarations.cmi kernel/cooking.cmi toplevel/discharge.cmi |
2850 | 2851 | pretyping/tacred.cmi proofs/tacmach.cmi tactics/tacinterp.cmi \ |
2851 | 2852 | kernel/sign.cmi pretyping/reductionops.cmi contrib/recdef/recdef.cmo \ |
2852 | 2853 | pretyping/rawterm.cmi proofs/proof_type.cmi parsing/printer.cmi \ |
2853 | lib/pp.cmi lib/options.cmi kernel/names.cmi library/nameops.cmi \ | |
2854 | library/libnames.cmi contrib/funind/indfun_common.cmi \ | |
2855 | tactics/hiddentac.cmi library/global.cmi interp/genarg.cmi \ | |
2856 | pretyping/evd.cmi tactics/equality.cmi kernel/environ.cmi \ | |
2857 | kernel/entries.cmi tactics/elim.cmi tactics/eauto.cmi \ | |
2858 | kernel/declarations.cmi interp/coqlib.cmi kernel/closure.cmi \ | |
2859 | toplevel/cerrors.cmi contrib/funind/functional_principles_proofs.cmi | |
2854 | lib/pp.cmi proofs/pfedit.cmi lib/options.cmi library/nametab.cmi \ | |
2855 | kernel/names.cmi library/nameops.cmi library/libnames.cmi \ | |
2856 | contrib/funind/indfun_common.cmi tactics/hiddentac.cmi library/global.cmi \ | |
2857 | interp/genarg.cmi pretyping/evd.cmi tactics/equality.cmi \ | |
2858 | kernel/environ.cmi kernel/entries.cmi tactics/elim.cmi tactics/eauto.cmi \ | |
2859 | kernel/declarations.cmi library/decl_kinds.cmo interp/coqlib.cmi \ | |
2860 | toplevel/command.cmi kernel/closure.cmi toplevel/cerrors.cmi \ | |
2861 | contrib/funind/functional_principles_proofs.cmi | |
2860 | 2862 | contrib/funind/functional_principles_proofs.cmx: lib/util.cmx \ |
2861 | 2863 | pretyping/typing.cmx pretyping/termops.cmx kernel/term.cmx \ |
2862 | 2864 | tactics/tactics.cmx tactics/tacticals.cmx proofs/tactic_debug.cmx \ |
2863 | 2865 | pretyping/tacred.cmx proofs/tacmach.cmx tactics/tacinterp.cmx \ |
2864 | 2866 | kernel/sign.cmx pretyping/reductionops.cmx contrib/recdef/recdef.cmx \ |
2865 | 2867 | pretyping/rawterm.cmx proofs/proof_type.cmx parsing/printer.cmx \ |
2866 | lib/pp.cmx lib/options.cmx kernel/names.cmx library/nameops.cmx \ | |
2867 | library/libnames.cmx contrib/funind/indfun_common.cmx \ | |
2868 | tactics/hiddentac.cmx library/global.cmx interp/genarg.cmx \ | |
2869 | pretyping/evd.cmx tactics/equality.cmx kernel/environ.cmx \ | |
2870 | kernel/entries.cmx tactics/elim.cmx tactics/eauto.cmx \ | |
2871 | kernel/declarations.cmx interp/coqlib.cmx kernel/closure.cmx \ | |
2872 | toplevel/cerrors.cmx contrib/funind/functional_principles_proofs.cmi | |
2873 | contrib/funind/functional_principles_types.cmo: toplevel/vernacexpr.cmo \ | |
2874 | toplevel/vernacentries.cmi lib/util.cmi pretyping/typing.cmi \ | |
2875 | pretyping/termops.cmi kernel/term.cmi tactics/tactics.cmi \ | |
2876 | tactics/tacticals.cmi pretyping/tacred.cmi proofs/tacmach.cmi \ | |
2877 | tactics/tacinterp.cmi lib/system.cmi proofs/proof_type.cmi \ | |
2878 | parsing/printer.cmi pretyping/pretyping.cmi parsing/ppconstr.cmi \ | |
2879 | lib/pp.cmi proofs/pfedit.cmi lib/options.cmi kernel/names.cmi \ | |
2868 | lib/pp.cmx proofs/pfedit.cmx lib/options.cmx library/nametab.cmx \ | |
2869 | kernel/names.cmx library/nameops.cmx library/libnames.cmx \ | |
2870 | contrib/funind/indfun_common.cmx tactics/hiddentac.cmx library/global.cmx \ | |
2871 | interp/genarg.cmx pretyping/evd.cmx tactics/equality.cmx \ | |
2872 | kernel/environ.cmx kernel/entries.cmx tactics/elim.cmx tactics/eauto.cmx \ | |
2873 | kernel/declarations.cmx library/decl_kinds.cmx interp/coqlib.cmx \ | |
2874 | toplevel/command.cmx kernel/closure.cmx toplevel/cerrors.cmx \ | |
2875 | contrib/funind/functional_principles_proofs.cmi | |
2876 | contrib/funind/functional_principles_types.cmo: lib/util.cmi \ | |
2877 | pretyping/typing.cmi pretyping/termops.cmi kernel/term.cmi \ | |
2878 | tactics/tactics.cmi tactics/tacticals.cmi pretyping/tacred.cmi \ | |
2879 | proofs/tacmach.cmi tactics/tacinterp.cmi lib/system.cmi kernel/sign.cmi \ | |
2880 | pretyping/rawterm.cmi proofs/proof_type.cmi parsing/printer.cmi \ | |
2881 | pretyping/pretyping.cmi parsing/ppconstr.cmi lib/pp.cmi proofs/pfedit.cmi \ | |
2882 | lib/options.cmi library/nametab.cmi kernel/names.cmi library/nameops.cmi \ | |
2880 | 2883 | library/libnames.cmi pretyping/indrec.cmi \ |
2881 | 2884 | contrib/funind/indfun_common.cmi tactics/hiddentac.cmi library/global.cmi \ |
2882 | 2885 | contrib/funind/functional_principles_proofs.cmi pretyping/evd.cmi \ |
2883 | 2886 | kernel/environ.cmi kernel/entries.cmi library/declare.cmi \ |
2884 | 2887 | kernel/declarations.cmi library/decl_kinds.cmo toplevel/command.cmi \ |
2885 | kernel/closure.cmi toplevel/cerrors.cmi \ | |
2886 | contrib/funind/functional_principles_types.cmi | |
2887 | contrib/funind/functional_principles_types.cmx: toplevel/vernacexpr.cmx \ | |
2888 | toplevel/vernacentries.cmx lib/util.cmx pretyping/typing.cmx \ | |
2889 | pretyping/termops.cmx kernel/term.cmx tactics/tactics.cmx \ | |
2890 | tactics/tacticals.cmx pretyping/tacred.cmx proofs/tacmach.cmx \ | |
2891 | tactics/tacinterp.cmx lib/system.cmx proofs/proof_type.cmx \ | |
2892 | parsing/printer.cmx pretyping/pretyping.cmx parsing/ppconstr.cmx \ | |
2893 | lib/pp.cmx proofs/pfedit.cmx lib/options.cmx kernel/names.cmx \ | |
2888 | kernel/closure.cmi contrib/funind/functional_principles_types.cmi | |
2889 | contrib/funind/functional_principles_types.cmx: lib/util.cmx \ | |
2890 | pretyping/typing.cmx pretyping/termops.cmx kernel/term.cmx \ | |
2891 | tactics/tactics.cmx tactics/tacticals.cmx pretyping/tacred.cmx \ | |
2892 | proofs/tacmach.cmx tactics/tacinterp.cmx lib/system.cmx kernel/sign.cmx \ | |
2893 | pretyping/rawterm.cmx proofs/proof_type.cmx parsing/printer.cmx \ | |
2894 | pretyping/pretyping.cmx parsing/ppconstr.cmx lib/pp.cmx proofs/pfedit.cmx \ | |
2895 | lib/options.cmx library/nametab.cmx kernel/names.cmx library/nameops.cmx \ | |
2894 | 2896 | library/libnames.cmx pretyping/indrec.cmx \ |
2895 | 2897 | contrib/funind/indfun_common.cmx tactics/hiddentac.cmx library/global.cmx \ |
2896 | 2898 | contrib/funind/functional_principles_proofs.cmx pretyping/evd.cmx \ |
2897 | 2899 | kernel/environ.cmx kernel/entries.cmx library/declare.cmx \ |
2898 | 2900 | kernel/declarations.cmx library/decl_kinds.cmx toplevel/command.cmx \ |
2899 | kernel/closure.cmx toplevel/cerrors.cmx \ | |
2900 | contrib/funind/functional_principles_types.cmi | |
2901 | kernel/closure.cmx contrib/funind/functional_principles_types.cmi | |
2901 | 2902 | contrib/funind/indfun_common.cmo: lib/util.cmi pretyping/termops.cmi \ |
2902 | kernel/term.cmi pretyping/rawterm.cmi lib/pp.cmi library/nametab.cmi \ | |
2903 | kernel/names.cmi library/libnames.cmi library/global.cmi \ | |
2904 | kernel/declarations.cmi interp/coqlib.cmi \ | |
2905 | contrib/funind/indfun_common.cmi | |
2903 | kernel/term.cmi library/summary.cmi proofs/refiner.cmi \ | |
2904 | pretyping/reductionops.cmi pretyping/rawterm.cmi proofs/proof_type.cmi \ | |
2905 | parsing/printer.cmi lib/pp.cmi proofs/pfedit.cmi lib/options.cmi \ | |
2906 | library/nametab.cmi kernel/names.cmi library/nameops.cmi \ | |
2907 | kernel/mod_subst.cmi library/libobject.cmi library/libnames.cmi \ | |
2908 | library/lib.cmi library/global.cmi pretyping/evd.cmi \ | |
2909 | pretyping/evarutil.cmi kernel/entries.cmi library/declare.cmi \ | |
2910 | kernel/declarations.cmi library/decl_kinds.cmo interp/coqlib.cmi \ | |
2911 | kernel/closure.cmi contrib/funind/indfun_common.cmi | |
2906 | 2912 | contrib/funind/indfun_common.cmx: lib/util.cmx pretyping/termops.cmx \ |
2907 | kernel/term.cmx pretyping/rawterm.cmx lib/pp.cmx library/nametab.cmx \ | |
2908 | kernel/names.cmx library/libnames.cmx library/global.cmx \ | |
2909 | kernel/declarations.cmx interp/coqlib.cmx \ | |
2910 | contrib/funind/indfun_common.cmi | |
2913 | kernel/term.cmx library/summary.cmx proofs/refiner.cmx \ | |
2914 | pretyping/reductionops.cmx pretyping/rawterm.cmx proofs/proof_type.cmx \ | |
2915 | parsing/printer.cmx lib/pp.cmx proofs/pfedit.cmx lib/options.cmx \ | |
2916 | library/nametab.cmx kernel/names.cmx library/nameops.cmx \ | |
2917 | kernel/mod_subst.cmx library/libobject.cmx library/libnames.cmx \ | |
2918 | library/lib.cmx library/global.cmx pretyping/evd.cmx \ | |
2919 | pretyping/evarutil.cmx kernel/entries.cmx library/declare.cmx \ | |
2920 | kernel/declarations.cmx library/decl_kinds.cmx interp/coqlib.cmx \ | |
2921 | kernel/closure.cmx contrib/funind/indfun_common.cmi | |
2911 | 2922 | contrib/funind/indfun_main.cmo: toplevel/vernacinterp.cmi lib/util.cmi \ |
2912 | 2923 | interp/topconstr.cmi pretyping/termops.cmi kernel/term.cmi \ |
2913 | tactics/tactics.cmi tactics/tacticals.cmi proofs/tacmach.cmi \ | |
2914 | tactics/tacinterp.cmi proofs/tacexpr.cmo kernel/sign.cmi \ | |
2915 | proofs/refiner.cmi pretyping/rawterm.cmi parsing/pptactic.cmi \ | |
2916 | parsing/ppconstr.cmi lib/pp.cmi parsing/pcoq.cmi kernel/names.cmi \ | |
2917 | library/nameops.cmi parsing/lexer.cmi contrib/funind/invfun.cmo \ | |
2918 | pretyping/indrec.cmi contrib/funind/indfun_common.cmi \ | |
2919 | contrib/funind/indfun.cmo tactics/hiddentac.cmi interp/genarg.cmi \ | |
2920 | contrib/funind/functional_principles_types.cmi tactics/equality.cmi \ | |
2921 | parsing/egrammar.cmi toplevel/cerrors.cmi | |
2924 | tactics/tacticals.cmi proofs/tacmach.cmi tactics/tacinterp.cmi \ | |
2925 | proofs/tacexpr.cmo proofs/refiner.cmi pretyping/rawterm.cmi \ | |
2926 | proofs/proof_type.cmi parsing/printer.cmi parsing/pptactic.cmi \ | |
2927 | parsing/ppconstr.cmi lib/pp.cmi parsing/pcoq.cmi library/nametab.cmi \ | |
2928 | kernel/names.cmi library/nameops.cmi parsing/lexer.cmi \ | |
2929 | contrib/funind/invfun.cmo contrib/funind/indfun_common.cmi \ | |
2930 | contrib/funind/indfun.cmo interp/genarg.cmi \ | |
2931 | contrib/funind/functional_principles_types.cmi parsing/egrammar.cmi \ | |
2932 | toplevel/cerrors.cmi | |
2922 | 2933 | contrib/funind/indfun_main.cmx: toplevel/vernacinterp.cmx lib/util.cmx \ |
2923 | 2934 | interp/topconstr.cmx pretyping/termops.cmx kernel/term.cmx \ |
2935 | tactics/tacticals.cmx proofs/tacmach.cmx tactics/tacinterp.cmx \ | |
2936 | proofs/tacexpr.cmx proofs/refiner.cmx pretyping/rawterm.cmx \ | |
2937 | proofs/proof_type.cmx parsing/printer.cmx parsing/pptactic.cmx \ | |
2938 | parsing/ppconstr.cmx lib/pp.cmx parsing/pcoq.cmx library/nametab.cmx \ | |
2939 | kernel/names.cmx library/nameops.cmx parsing/lexer.cmx \ | |
2940 | contrib/funind/invfun.cmx contrib/funind/indfun_common.cmx \ | |
2941 | contrib/funind/indfun.cmx interp/genarg.cmx \ | |
2942 | contrib/funind/functional_principles_types.cmx parsing/egrammar.cmx \ | |
2943 | toplevel/cerrors.cmx | |
2944 | contrib/funind/indfun.cmo: toplevel/vernacexpr.cmo lib/util.cmi \ | |
2945 | interp/topconstr.cmi pretyping/termops.cmi kernel/term.cmi \ | |
2946 | tactics/tactics.cmi tactics/tacticals.cmi proofs/tacmach.cmi \ | |
2947 | tactics/tacinterp.cmi proofs/tacexpr.cmo library/states.cmi \ | |
2948 | kernel/sign.cmi contrib/recdef/recdef.cmo \ | |
2949 | contrib/funind/rawterm_to_relation.cmi pretyping/rawterm.cmi \ | |
2950 | parsing/printer.cmi parsing/ppconstr.cmi lib/pp.cmi lib/options.cmi \ | |
2951 | interp/notation.cmi kernel/names.cmi library/nameops.cmi \ | |
2952 | library/libnames.cmi contrib/funind/invfun.cmo pretyping/indrec.cmi \ | |
2953 | contrib/funind/indfun_common.cmi library/impargs.cmi \ | |
2954 | tactics/hiddentac.cmi library/global.cmi \ | |
2955 | contrib/funind/functional_principles_types.cmi \ | |
2956 | contrib/funind/functional_principles_proofs.cmi pretyping/evd.cmi \ | |
2957 | tactics/equality.cmi kernel/environ.cmi kernel/declarations.cmi \ | |
2958 | library/decl_kinds.cmo interp/constrintern.cmi interp/constrextern.cmi \ | |
2959 | toplevel/command.cmi toplevel/cerrors.cmi | |
2960 | contrib/funind/indfun.cmx: toplevel/vernacexpr.cmx lib/util.cmx \ | |
2961 | interp/topconstr.cmx pretyping/termops.cmx kernel/term.cmx \ | |
2924 | 2962 | tactics/tactics.cmx tactics/tacticals.cmx proofs/tacmach.cmx \ |
2925 | tactics/tacinterp.cmx proofs/tacexpr.cmx kernel/sign.cmx \ | |
2926 | proofs/refiner.cmx pretyping/rawterm.cmx parsing/pptactic.cmx \ | |
2927 | parsing/ppconstr.cmx lib/pp.cmx parsing/pcoq.cmx kernel/names.cmx \ | |
2928 | library/nameops.cmx parsing/lexer.cmx contrib/funind/invfun.cmx \ | |
2929 | pretyping/indrec.cmx contrib/funind/indfun_common.cmx \ | |
2930 | contrib/funind/indfun.cmx tactics/hiddentac.cmx interp/genarg.cmx \ | |
2931 | contrib/funind/functional_principles_types.cmx tactics/equality.cmx \ | |
2932 | parsing/egrammar.cmx toplevel/cerrors.cmx | |
2933 | contrib/funind/indfun.cmo: toplevel/vernacexpr.cmo lib/util.cmi \ | |
2934 | interp/topconstr.cmi kernel/term.cmi proofs/tacmach.cmi \ | |
2935 | library/states.cmi contrib/recdef/recdef.cmo \ | |
2936 | contrib/funind/rawterm_to_relation.cmi pretyping/rawterm.cmi \ | |
2937 | parsing/ppconstr.cmi lib/pp.cmi lib/options.cmi interp/notation.cmi \ | |
2938 | kernel/names.cmi library/nameops.cmi library/libnames.cmi \ | |
2939 | pretyping/indrec.cmi contrib/funind/indfun_common.cmi library/impargs.cmi \ | |
2940 | library/global.cmi contrib/funind/functional_principles_types.cmi \ | |
2941 | contrib/funind/functional_principles_proofs.cmi pretyping/evd.cmi \ | |
2942 | kernel/environ.cmi kernel/declarations.cmi library/decl_kinds.cmo \ | |
2943 | interp/constrintern.cmi interp/constrextern.cmi toplevel/command.cmi \ | |
2944 | toplevel/cerrors.cmi | |
2945 | contrib/funind/indfun.cmx: toplevel/vernacexpr.cmx lib/util.cmx \ | |
2946 | interp/topconstr.cmx kernel/term.cmx proofs/tacmach.cmx \ | |
2947 | library/states.cmx contrib/recdef/recdef.cmx \ | |
2963 | tactics/tacinterp.cmx proofs/tacexpr.cmx library/states.cmx \ | |
2964 | kernel/sign.cmx contrib/recdef/recdef.cmx \ | |
2948 | 2965 | contrib/funind/rawterm_to_relation.cmx pretyping/rawterm.cmx \ |
2949 | parsing/ppconstr.cmx lib/pp.cmx lib/options.cmx interp/notation.cmx \ | |
2950 | kernel/names.cmx library/nameops.cmx library/libnames.cmx \ | |
2951 | pretyping/indrec.cmx contrib/funind/indfun_common.cmx library/impargs.cmx \ | |
2952 | library/global.cmx contrib/funind/functional_principles_types.cmx \ | |
2966 | parsing/printer.cmx parsing/ppconstr.cmx lib/pp.cmx lib/options.cmx \ | |
2967 | interp/notation.cmx kernel/names.cmx library/nameops.cmx \ | |
2968 | library/libnames.cmx contrib/funind/invfun.cmx pretyping/indrec.cmx \ | |
2969 | contrib/funind/indfun_common.cmx library/impargs.cmx \ | |
2970 | tactics/hiddentac.cmx library/global.cmx \ | |
2971 | contrib/funind/functional_principles_types.cmx \ | |
2953 | 2972 | contrib/funind/functional_principles_proofs.cmx pretyping/evd.cmx \ |
2954 | kernel/environ.cmx kernel/declarations.cmx library/decl_kinds.cmx \ | |
2955 | interp/constrintern.cmx interp/constrextern.cmx toplevel/command.cmx \ | |
2956 | toplevel/cerrors.cmx | |
2957 | contrib/funind/invfun.cmo: lib/util.cmi kernel/term.cmi tactics/tactics.cmi \ | |
2958 | tactics/tacticals.cmi proofs/tacmach.cmi contrib/funind/tacinvutils.cmi \ | |
2959 | kernel/sign.cmi pretyping/rawterm.cmi lib/pp.cmi kernel/names.cmi \ | |
2960 | library/libnames.cmi contrib/funind/indfun_common.cmi \ | |
2961 | tactics/hiddentac.cmi library/global.cmi tactics/extratactics.cmi \ | |
2962 | tactics/equality.cmi kernel/declarations.cmi | |
2963 | contrib/funind/invfun.cmx: lib/util.cmx kernel/term.cmx tactics/tactics.cmx \ | |
2964 | tactics/tacticals.cmx proofs/tacmach.cmx contrib/funind/tacinvutils.cmx \ | |
2965 | kernel/sign.cmx pretyping/rawterm.cmx lib/pp.cmx kernel/names.cmx \ | |
2966 | library/libnames.cmx contrib/funind/indfun_common.cmx \ | |
2967 | tactics/hiddentac.cmx library/global.cmx tactics/extratactics.cmx \ | |
2968 | tactics/equality.cmx kernel/declarations.cmx | |
2973 | tactics/equality.cmx kernel/environ.cmx kernel/declarations.cmx \ | |
2974 | library/decl_kinds.cmx interp/constrintern.cmx interp/constrextern.cmx \ | |
2975 | toplevel/command.cmx toplevel/cerrors.cmx | |
2976 | contrib/funind/invfun.cmo: toplevel/vernacentries.cmi lib/util.cmi \ | |
2977 | pretyping/typing.cmi pretyping/termops.cmi kernel/term.cmi \ | |
2978 | tactics/tauto.cmo tactics/tactics.cmi tactics/tacticals.cmi \ | |
2979 | proofs/tactic_debug.cmi proofs/tacmach.cmi tactics/tacinterp.cmi \ | |
2980 | proofs/tacexpr.cmo kernel/sign.cmi lib/rtree.cmi \ | |
2981 | pretyping/reductionops.cmi pretyping/rawterm.cmi parsing/printer.cmi \ | |
2982 | parsing/ppconstr.cmi lib/pp.cmi proofs/pfedit.cmi kernel/names.cmi \ | |
2983 | library/nameops.cmi library/libnames.cmi tactics/inv.cmi \ | |
2984 | kernel/inductive.cmi pretyping/indrec.cmi \ | |
2985 | contrib/funind/indfun_common.cmi tactics/hiddentac.cmi library/global.cmi \ | |
2986 | interp/genarg.cmi pretyping/evd.cmi tactics/equality.cmi \ | |
2987 | kernel/environ.cmi kernel/entries.cmi kernel/declarations.cmi \ | |
2988 | library/decl_kinds.cmo interp/coqlib.cmi toplevel/command.cmi \ | |
2989 | kernel/closure.cmi toplevel/cerrors.cmi | |
2990 | contrib/funind/invfun.cmx: toplevel/vernacentries.cmx lib/util.cmx \ | |
2991 | pretyping/typing.cmx pretyping/termops.cmx kernel/term.cmx \ | |
2992 | tactics/tauto.cmx tactics/tactics.cmx tactics/tacticals.cmx \ | |
2993 | proofs/tactic_debug.cmx proofs/tacmach.cmx tactics/tacinterp.cmx \ | |
2994 | proofs/tacexpr.cmx kernel/sign.cmx lib/rtree.cmx \ | |
2995 | pretyping/reductionops.cmx pretyping/rawterm.cmx parsing/printer.cmx \ | |
2996 | parsing/ppconstr.cmx lib/pp.cmx proofs/pfedit.cmx kernel/names.cmx \ | |
2997 | library/nameops.cmx library/libnames.cmx tactics/inv.cmx \ | |
2998 | kernel/inductive.cmx pretyping/indrec.cmx \ | |
2999 | contrib/funind/indfun_common.cmx tactics/hiddentac.cmx library/global.cmx \ | |
3000 | interp/genarg.cmx pretyping/evd.cmx tactics/equality.cmx \ | |
3001 | kernel/environ.cmx kernel/entries.cmx kernel/declarations.cmx \ | |
3002 | library/decl_kinds.cmx interp/coqlib.cmx toplevel/command.cmx \ | |
3003 | kernel/closure.cmx toplevel/cerrors.cmx | |
2969 | 3004 | contrib/funind/rawtermops.cmo: lib/util.cmi proofs/tactic_debug.cmi \ |
2970 | 3005 | tactics/tacinterp.cmi pretyping/rawterm.cmi parsing/printer.cmi \ |
2971 | 3006 | parsing/ppconstr.cmi lib/pp.cmi kernel/names.cmi library/nameops.cmi \ |
3558 | 3593 | interp/genarg.cmi pretyping/evd.cmi pretyping/evarutil.cmi \ |
3559 | 3594 | contrib/subtac/eterm.cmi kernel/environ.cmi kernel/entries.cmi \ |
3560 | 3595 | lib/dyn.cmi library/declare.cmi kernel/declarations.cmi \ |
3561 | library/decl_kinds.cmo interp/constrintern.cmi toplevel/command.cmi \ | |
3562 | kernel/closure.cmi contrib/subtac/subtac_command.cmi | |
3596 | library/decl_kinds.cmo interp/coqlib.cmi interp/constrintern.cmi \ | |
3597 | toplevel/command.cmi kernel/closure.cmi contrib/subtac/subtac_command.cmi | |
3563 | 3598 | contrib/subtac/subtac_command.cmx: toplevel/vernacexpr.cmx lib/util.cmx \ |
3564 | 3599 | pretyping/typing.cmx interp/topconstr.cmx pretyping/termops.cmx \ |
3565 | 3600 | kernel/term.cmx tactics/tactics.cmx tactics/tacticals.cmx \ |
3578 | 3613 | interp/genarg.cmx pretyping/evd.cmx pretyping/evarutil.cmx \ |
3579 | 3614 | contrib/subtac/eterm.cmx kernel/environ.cmx kernel/entries.cmx \ |
3580 | 3615 | lib/dyn.cmx library/declare.cmx kernel/declarations.cmx \ |
3581 | library/decl_kinds.cmx interp/constrintern.cmx toplevel/command.cmx \ | |
3582 | kernel/closure.cmx contrib/subtac/subtac_command.cmi | |
3616 | library/decl_kinds.cmx interp/coqlib.cmx interp/constrintern.cmx \ | |
3617 | toplevel/command.cmx kernel/closure.cmx contrib/subtac/subtac_command.cmi | |
3583 | 3618 | contrib/subtac/subtac_errors.cmo: lib/util.cmi parsing/printer.cmi lib/pp.cmi \ |
3584 | 3619 | contrib/subtac/subtac_errors.cmi |
3585 | 3620 | contrib/subtac/subtac_errors.cmx: lib/util.cmx parsing/printer.cmx lib/pp.cmx \ |
3611 | 3646 | contrib/subtac/subtac.cmo: toplevel/vernacexpr.cmo lib/util.cmi \ |
3612 | 3647 | kernel/typeops.cmi kernel/type_errors.cmi pretyping/termops.cmi \ |
3613 | 3648 | kernel/term.cmi contrib/subtac/subtac_utils.cmi \ |
3614 | contrib/subtac/subtac_pretyping.cmi \ | |
3615 | contrib/subtac/subtac_interp_fixpoint.cmi \ | |
3616 | contrib/subtac/subtac_errors.cmi contrib/subtac/subtac_command.cmi \ | |
3617 | contrib/subtac/subtac_coercion.cmi kernel/sign.cmi \ | |
3618 | pretyping/reductionops.cmi pretyping/recordops.cmi pretyping/rawterm.cmi \ | |
3619 | parsing/printer.cmi pretyping/pretype_errors.cmi parsing/ppconstr.cmi \ | |
3620 | lib/pp.cmi proofs/pfedit.cmi pretyping/pattern.cmi lib/options.cmi \ | |
3621 | library/nametab.cmi kernel/names.cmi library/library.cmi \ | |
3649 | contrib/subtac/subtac_pretyping.cmi contrib/subtac/subtac_errors.cmi \ | |
3650 | contrib/subtac/subtac_command.cmi contrib/subtac/subtac_coercion.cmi \ | |
3651 | kernel/sign.cmi pretyping/reductionops.cmi pretyping/recordops.cmi \ | |
3652 | pretyping/rawterm.cmi parsing/printer.cmi pretyping/pretype_errors.cmi \ | |
3653 | parsing/ppconstr.cmi lib/pp.cmi proofs/pfedit.cmi pretyping/pattern.cmi \ | |
3654 | lib/options.cmi library/nametab.cmi kernel/names.cmi library/library.cmi \ | |
3622 | 3655 | library/libnames.cmi library/lib.cmi toplevel/himsg.cmi \ |
3623 | 3656 | library/global.cmi pretyping/evd.cmi pretyping/evarutil.cmi \ |
3624 | 3657 | pretyping/evarconv.cmi contrib/subtac/eterm.cmi kernel/environ.cmi \ |
3628 | 3661 | contrib/subtac/subtac.cmx: toplevel/vernacexpr.cmx lib/util.cmx \ |
3629 | 3662 | kernel/typeops.cmx kernel/type_errors.cmx pretyping/termops.cmx \ |
3630 | 3663 | kernel/term.cmx contrib/subtac/subtac_utils.cmx \ |
3631 | contrib/subtac/subtac_pretyping.cmx \ | |
3632 | contrib/subtac/subtac_interp_fixpoint.cmx \ | |
3633 | contrib/subtac/subtac_errors.cmx contrib/subtac/subtac_command.cmx \ | |
3634 | contrib/subtac/subtac_coercion.cmx kernel/sign.cmx \ | |
3635 | pretyping/reductionops.cmx pretyping/recordops.cmx pretyping/rawterm.cmx \ | |
3636 | parsing/printer.cmx pretyping/pretype_errors.cmx parsing/ppconstr.cmx \ | |
3637 | lib/pp.cmx proofs/pfedit.cmx pretyping/pattern.cmx lib/options.cmx \ | |
3638 | library/nametab.cmx kernel/names.cmx library/library.cmx \ | |
3664 | contrib/subtac/subtac_pretyping.cmx contrib/subtac/subtac_errors.cmx \ | |
3665 | contrib/subtac/subtac_command.cmx contrib/subtac/subtac_coercion.cmx \ | |
3666 | kernel/sign.cmx pretyping/reductionops.cmx pretyping/recordops.cmx \ | |
3667 | pretyping/rawterm.cmx parsing/printer.cmx pretyping/pretype_errors.cmx \ | |
3668 | parsing/ppconstr.cmx lib/pp.cmx proofs/pfedit.cmx pretyping/pattern.cmx \ | |
3669 | lib/options.cmx library/nametab.cmx kernel/names.cmx library/library.cmx \ | |
3639 | 3670 | library/libnames.cmx library/lib.cmx toplevel/himsg.cmx \ |
3640 | 3671 | library/global.cmx pretyping/evd.cmx pretyping/evarutil.cmx \ |
3641 | 3672 | pretyping/evarconv.cmx contrib/subtac/eterm.cmx kernel/environ.cmx \ |
3808 | 3839 | parsing/egrammar.cmx toplevel/cerrors.cmx |
3809 | 3840 | contrib/xml/xml.cmo: contrib/xml/xml.cmi |
3810 | 3841 | contrib/xml/xml.cmx: contrib/xml/xml.cmi |
3811 | doc/refman/euclid.cmo: doc/refman/euclid.cmi | |
3812 | doc/refman/euclid.cmx: doc/refman/euclid.cmi | |
3813 | doc/refman/heapsort.cmo: doc/refman/heapsort.cmi | |
3814 | doc/refman/heapsort.cmx: doc/refman/heapsort.cmi | |
3815 | 3842 | ide/utils/config_file.cmo: ide/utils/config_file.cmi |
3816 | 3843 | ide/utils/config_file.cmx: ide/utils/config_file.cmi |
3817 | 3844 | ide/utils/configwin_html_config.cmo: ide/utils/configwin_types.cmo \ |
3963 | 3990 | tools/coq-tex.cmo: |
3964 | 3991 | tools/coq-tex.cmx: |
3965 | 3992 | coq_fix_code.o: kernel/byterun/coq_fix_code.c \ |
3966 | /usr/local/lib/ocaml/caml/config.h \ | |
3967 | /usr/local/lib/ocaml/caml/compatibility.h \ | |
3968 | /usr/local/lib/ocaml/caml/misc.h /usr/local/lib/ocaml/caml/mlvalues.h \ | |
3969 | /usr/local/lib/ocaml/caml/fail.h /usr/local/lib/ocaml/caml/memory.h \ | |
3993 | /user/jforest/home//lib/ocaml/caml/config.h \ | |
3994 | /user/jforest/home//lib/ocaml/caml/compatibility.h \ | |
3995 | /user/jforest/home//lib/ocaml/caml/misc.h \ | |
3996 | /user/jforest/home//lib/ocaml/caml/config.h \ | |
3997 | /user/jforest/home//lib/ocaml/caml/mlvalues.h \ | |
3998 | /user/jforest/home//lib/ocaml/caml/misc.h \ | |
3999 | /user/jforest/home//lib/ocaml/caml/fail.h \ | |
4000 | /user/jforest/home//lib/ocaml/caml/mlvalues.h \ | |
4001 | /user/jforest/home//lib/ocaml/caml/memory.h \ | |
3970 | 4002 | kernel/byterun/coq_instruct.h kernel/byterun/coq_fix_code.h |
3971 | 4003 | coq_interp.o: kernel/byterun/coq_interp.c kernel/byterun/coq_gc.h \ |
3972 | /usr/local/lib/ocaml/caml/mlvalues.h \ | |
3973 | /usr/local/lib/ocaml/caml/compatibility.h \ | |
3974 | /usr/local/lib/ocaml/caml/config.h /usr/local/lib/ocaml/caml/misc.h \ | |
3975 | /usr/local/lib/ocaml/caml/alloc.h kernel/byterun/coq_instruct.h \ | |
3976 | kernel/byterun/coq_fix_code.h kernel/byterun/coq_memory.h \ | |
3977 | /usr/local/lib/ocaml/caml/fail.h /usr/local/lib/ocaml/caml/memory.h \ | |
3978 | kernel/byterun/coq_values.h kernel/byterun/coq_jumptbl.h | |
4004 | /user/jforest/home//lib/ocaml/caml/mlvalues.h \ | |
4005 | /user/jforest/home//lib/ocaml/caml/compatibility.h \ | |
4006 | /user/jforest/home//lib/ocaml/caml/config.h \ | |
4007 | /user/jforest/home//lib/ocaml/caml/misc.h \ | |
4008 | /user/jforest/home//lib/ocaml/caml/alloc.h \ | |
4009 | /user/jforest/home//lib/ocaml/caml/mlvalues.h \ | |
4010 | kernel/byterun/coq_instruct.h kernel/byterun/coq_fix_code.h \ | |
4011 | kernel/byterun/coq_memory.h /user/jforest/home//lib/ocaml/caml/config.h \ | |
4012 | /user/jforest/home//lib/ocaml/caml/fail.h \ | |
4013 | /user/jforest/home//lib/ocaml/caml/misc.h \ | |
4014 | /user/jforest/home//lib/ocaml/caml/memory.h kernel/byterun/coq_values.h \ | |
4015 | kernel/byterun/coq_jumptbl.h | |
3979 | 4016 | coq_memory.o: kernel/byterun/coq_memory.c kernel/byterun/coq_gc.h \ |
3980 | /usr/local/lib/ocaml/caml/mlvalues.h \ | |
3981 | /usr/local/lib/ocaml/caml/compatibility.h \ | |
3982 | /usr/local/lib/ocaml/caml/config.h /usr/local/lib/ocaml/caml/misc.h \ | |
3983 | /usr/local/lib/ocaml/caml/alloc.h kernel/byterun/coq_instruct.h \ | |
3984 | kernel/byterun/coq_fix_code.h kernel/byterun/coq_memory.h \ | |
3985 | /usr/local/lib/ocaml/caml/fail.h /usr/local/lib/ocaml/caml/memory.h | |
4017 | /user/jforest/home//lib/ocaml/caml/mlvalues.h \ | |
4018 | /user/jforest/home//lib/ocaml/caml/compatibility.h \ | |
4019 | /user/jforest/home//lib/ocaml/caml/config.h \ | |
4020 | /user/jforest/home//lib/ocaml/caml/misc.h \ | |
4021 | /user/jforest/home//lib/ocaml/caml/alloc.h \ | |
4022 | /user/jforest/home//lib/ocaml/caml/mlvalues.h \ | |
4023 | kernel/byterun/coq_instruct.h kernel/byterun/coq_fix_code.h \ | |
4024 | kernel/byterun/coq_memory.h /user/jforest/home//lib/ocaml/caml/config.h \ | |
4025 | /user/jforest/home//lib/ocaml/caml/fail.h \ | |
4026 | /user/jforest/home//lib/ocaml/caml/misc.h \ | |
4027 | /user/jforest/home//lib/ocaml/caml/memory.h | |
3986 | 4028 | coq_values.o: kernel/byterun/coq_values.c kernel/byterun/coq_fix_code.h \ |
3987 | /usr/local/lib/ocaml/caml/mlvalues.h \ | |
3988 | /usr/local/lib/ocaml/caml/compatibility.h \ | |
3989 | /usr/local/lib/ocaml/caml/config.h /usr/local/lib/ocaml/caml/misc.h \ | |
3990 | kernel/byterun/coq_instruct.h kernel/byterun/coq_memory.h \ | |
3991 | /usr/local/lib/ocaml/caml/fail.h /usr/local/lib/ocaml/caml/memory.h \ | |
3992 | kernel/byterun/coq_values.h /usr/local/lib/ocaml/caml/alloc.h | |
4029 | /user/jforest/home//lib/ocaml/caml/mlvalues.h \ | |
4030 | /user/jforest/home//lib/ocaml/caml/compatibility.h \ | |
4031 | /user/jforest/home//lib/ocaml/caml/config.h \ | |
4032 | /user/jforest/home//lib/ocaml/caml/misc.h kernel/byterun/coq_instruct.h \ | |
4033 | kernel/byterun/coq_memory.h /user/jforest/home//lib/ocaml/caml/config.h \ | |
4034 | /user/jforest/home//lib/ocaml/caml/fail.h \ | |
4035 | /user/jforest/home//lib/ocaml/caml/mlvalues.h \ | |
4036 | /user/jforest/home//lib/ocaml/caml/misc.h \ | |
4037 | /user/jforest/home//lib/ocaml/caml/memory.h kernel/byterun/coq_values.h \ | |
4038 | /user/jforest/home//lib/ocaml/caml/alloc.h | |
3993 | 4039 | coq_fix_code.d.o: kernel/byterun/coq_fix_code.c \ |
3994 | /usr/local/lib/ocaml/caml/config.h \ | |
3995 | /usr/local/lib/ocaml/caml/compatibility.h \ | |
3996 | /usr/local/lib/ocaml/caml/misc.h /usr/local/lib/ocaml/caml/mlvalues.h \ | |
3997 | /usr/local/lib/ocaml/caml/fail.h /usr/local/lib/ocaml/caml/memory.h \ | |
4040 | /user/jforest/home//lib/ocaml/caml/config.h \ | |
4041 | /user/jforest/home//lib/ocaml/caml/compatibility.h \ | |
4042 | /user/jforest/home//lib/ocaml/caml/misc.h \ | |
4043 | /user/jforest/home//lib/ocaml/caml/config.h \ | |
4044 | /user/jforest/home//lib/ocaml/caml/mlvalues.h \ | |
4045 | /user/jforest/home//lib/ocaml/caml/misc.h \ | |
4046 | /user/jforest/home//lib/ocaml/caml/fail.h \ | |
4047 | /user/jforest/home//lib/ocaml/caml/mlvalues.h \ | |
4048 | /user/jforest/home//lib/ocaml/caml/memory.h \ | |
3998 | 4049 | kernel/byterun/coq_instruct.h kernel/byterun/coq_fix_code.h |
3999 | 4050 | coq_interp.d.o: kernel/byterun/coq_interp.c kernel/byterun/coq_gc.h \ |
4000 | /usr/local/lib/ocaml/caml/mlvalues.h \ | |
4001 | /usr/local/lib/ocaml/caml/compatibility.h \ | |
4002 | /usr/local/lib/ocaml/caml/config.h /usr/local/lib/ocaml/caml/misc.h \ | |
4003 | /usr/local/lib/ocaml/caml/alloc.h kernel/byterun/coq_instruct.h \ | |
4004 | kernel/byterun/coq_fix_code.h kernel/byterun/coq_memory.h \ | |
4005 | /usr/local/lib/ocaml/caml/fail.h /usr/local/lib/ocaml/caml/memory.h \ | |
4006 | kernel/byterun/coq_values.h kernel/byterun/coq_jumptbl.h | |
4051 | /user/jforest/home//lib/ocaml/caml/mlvalues.h \ | |
4052 | /user/jforest/home//lib/ocaml/caml/compatibility.h \ | |
4053 | /user/jforest/home//lib/ocaml/caml/config.h \ | |
4054 | /user/jforest/home//lib/ocaml/caml/misc.h \ | |
4055 | /user/jforest/home//lib/ocaml/caml/alloc.h \ | |
4056 | /user/jforest/home//lib/ocaml/caml/mlvalues.h \ | |
4057 | kernel/byterun/coq_instruct.h kernel/byterun/coq_fix_code.h \ | |
4058 | kernel/byterun/coq_memory.h /user/jforest/home//lib/ocaml/caml/config.h \ | |
4059 | /user/jforest/home//lib/ocaml/caml/fail.h \ | |
4060 | /user/jforest/home//lib/ocaml/caml/misc.h \ | |
4061 | /user/jforest/home//lib/ocaml/caml/memory.h kernel/byterun/coq_values.h \ | |
4062 | kernel/byterun/coq_jumptbl.h | |
4007 | 4063 | coq_memory.d.o: kernel/byterun/coq_memory.c kernel/byterun/coq_gc.h \ |
4008 | /usr/local/lib/ocaml/caml/mlvalues.h \ | |
4009 | /usr/local/lib/ocaml/caml/compatibility.h \ | |
4010 | /usr/local/lib/ocaml/caml/config.h /usr/local/lib/ocaml/caml/misc.h \ | |
4011 | /usr/local/lib/ocaml/caml/alloc.h kernel/byterun/coq_instruct.h \ | |
4012 | kernel/byterun/coq_fix_code.h kernel/byterun/coq_memory.h \ | |
4013 | /usr/local/lib/ocaml/caml/fail.h /usr/local/lib/ocaml/caml/memory.h | |
4064 | /user/jforest/home//lib/ocaml/caml/mlvalues.h \ | |
4065 | /user/jforest/home//lib/ocaml/caml/compatibility.h \ | |
4066 | /user/jforest/home//lib/ocaml/caml/config.h \ | |
4067 | /user/jforest/home//lib/ocaml/caml/misc.h \ | |
4068 | /user/jforest/home//lib/ocaml/caml/alloc.h \ | |
4069 | /user/jforest/home//lib/ocaml/caml/mlvalues.h \ | |
4070 | kernel/byterun/coq_instruct.h kernel/byterun/coq_fix_code.h \ | |
4071 | kernel/byterun/coq_memory.h /user/jforest/home//lib/ocaml/caml/config.h \ | |
4072 | /user/jforest/home//lib/ocaml/caml/fail.h \ | |
4073 | /user/jforest/home//lib/ocaml/caml/misc.h \ | |
4074 | /user/jforest/home//lib/ocaml/caml/memory.h | |
4014 | 4075 | coq_values.d.o: kernel/byterun/coq_values.c kernel/byterun/coq_fix_code.h \ |
4015 | /usr/local/lib/ocaml/caml/mlvalues.h \ | |
4016 | /usr/local/lib/ocaml/caml/compatibility.h \ | |
4017 | /usr/local/lib/ocaml/caml/config.h /usr/local/lib/ocaml/caml/misc.h \ | |
4018 | kernel/byterun/coq_instruct.h kernel/byterun/coq_memory.h \ | |
4019 | /usr/local/lib/ocaml/caml/fail.h /usr/local/lib/ocaml/caml/memory.h \ | |
4020 | kernel/byterun/coq_values.h /usr/local/lib/ocaml/caml/alloc.h | |
4076 | /user/jforest/home//lib/ocaml/caml/mlvalues.h \ | |
4077 | /user/jforest/home//lib/ocaml/caml/compatibility.h \ | |
4078 | /user/jforest/home//lib/ocaml/caml/config.h \ | |
4079 | /user/jforest/home//lib/ocaml/caml/misc.h kernel/byterun/coq_instruct.h \ | |
4080 | kernel/byterun/coq_memory.h /user/jforest/home//lib/ocaml/caml/config.h \ | |
4081 | /user/jforest/home//lib/ocaml/caml/fail.h \ | |
4082 | /user/jforest/home//lib/ocaml/caml/mlvalues.h \ | |
4083 | /user/jforest/home//lib/ocaml/caml/misc.h \ | |
4084 | /user/jforest/home//lib/ocaml/caml/memory.h kernel/byterun/coq_values.h \ | |
4085 | /user/jforest/home//lib/ocaml/caml/alloc.h |
179 | 179 | theories/ZArith/ZArith_base.vo: theories/ZArith/ZArith_base.v theories/NArith/BinPos.vo theories/NArith/BinNat.vo theories/ZArith/BinInt.vo theories/ZArith/Zcompare.vo theories/ZArith/Zorder.vo theories/ZArith/Zeven.vo theories/ZArith/Zmin.vo theories/ZArith/Zmax.vo theories/ZArith/Zminmax.vo theories/ZArith/Zabs.vo theories/ZArith/Znat.vo theories/ZArith/auxiliary.vo theories/ZArith/ZArith_dec.vo theories/ZArith/Zbool.vo theories/ZArith/Zmisc.vo theories/ZArith/Wf_Z.vo theories/ZArith/Zhints.vo |
180 | 180 | theories/ZArith/Zbool.vo: theories/ZArith/Zbool.v theories/ZArith/BinInt.vo theories/ZArith/Zeven.vo theories/ZArith/Zorder.vo theories/ZArith/Zcompare.vo theories/ZArith/ZArith_dec.vo theories/Bool/Sumbool.vo |
181 | 181 | theories/ZArith/Zbinary.vo: theories/ZArith/Zbinary.v theories/Bool/Bvector.vo theories/ZArith/ZArith.vo theories/ZArith/Zpower.vo contrib/omega/Omega.vo |
182 | theories/ZArith/Znumtheory.vo: theories/ZArith/Znumtheory.v theories/ZArith/ZArith_base.vo contrib/ring/ZArithRing.vo theories/ZArith/Zcomplements.vo theories/ZArith/Zdiv.vo | |
182 | theories/ZArith/Znumtheory.vo: theories/ZArith/Znumtheory.v theories/ZArith/ZArith_base.vo contrib/ring/ZArithRing.vo theories/ZArith/Zcomplements.vo theories/ZArith/Zdiv.vo theories/NArith/Ndigits.vo theories/Arith/Wf_nat.vo | |
183 | 183 | theories/ZArith/Int.vo: theories/ZArith/Int.v theories/ZArith/ZArith.vo contrib/romega/ROmega.vo |
184 | 184 | theories/Setoids/Setoid.vo: theories/Setoids/Setoid.v theories/Relations/Relation_Definitions.vo |
185 | 185 | theories/Lists/MonoList.vo: theories/Lists/MonoList.v theories/Arith/Le.vo |
273 | 273 | theories/Reals/RIneq.vo: theories/Reals/RIneq.v theories/Reals/Raxioms.vo contrib/ring/ZArithRing.vo contrib/omega/Omega.vo contrib/field/Field.vo |
274 | 274 | theories/Reals/DiscrR.vo: theories/Reals/DiscrR.v theories/Reals/RIneq.vo contrib/omega/Omega.vo |
275 | 275 | theories/Reals/Rbase.vo: theories/Reals/Rbase.v theories/Reals/Rdefinitions.vo theories/Reals/Raxioms.vo theories/Reals/RIneq.vo theories/Reals/DiscrR.vo |
276 | theories/Reals/R_Ifp.vo: theories/Reals/R_Ifp.v theories/Reals/Rbase.vo contrib/omega/Omega.vo | |
277 | theories/Reals/Rbasic_fun.vo: theories/Reals/Rbasic_fun.v theories/Reals/Rbase.vo theories/Reals/R_Ifp.vo contrib/fourier/Fourier.vo | |
278 | theories/Reals/R_sqr.vo: theories/Reals/R_sqr.v theories/Reals/Rbase.vo theories/Reals/Rbasic_fun.vo | |
279 | theories/Reals/SplitAbsolu.vo: theories/Reals/SplitAbsolu.v theories/Reals/Rbasic_fun.vo | |
280 | theories/Reals/SplitRmult.vo: theories/Reals/SplitRmult.v theories/Reals/Rbase.vo | |
281 | theories/Reals/ArithProp.vo: theories/Reals/ArithProp.v theories/Reals/Rbase.vo theories/Reals/Rbasic_fun.vo theories/Arith/Even.vo theories/Arith/Div2.vo | |
282 | theories/Reals/Rfunctions.vo: theories/Reals/Rfunctions.v theories/Reals/Rbase.vo theories/Reals/R_Ifp.vo theories/Reals/Rbasic_fun.vo theories/Reals/R_sqr.vo theories/Reals/SplitAbsolu.vo theories/Reals/SplitRmult.vo theories/Reals/ArithProp.vo contrib/omega/Omega.vo theories/ZArith/Zpower.vo | |
283 | theories/Reals/Rseries.vo: theories/Reals/Rseries.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Logic/Classical.vo theories/Arith/Compare.vo | |
284 | theories/Reals/SeqProp.vo: theories/Reals/SeqProp.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/Rseries.vo theories/Logic/Classical.vo theories/Arith/Max.vo | |
285 | theories/Reals/Rcomplete.vo: theories/Reals/Rcomplete.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/Rseries.vo theories/Reals/SeqProp.vo theories/Arith/Max.vo | |
286 | theories/Reals/PartSum.vo: theories/Reals/PartSum.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/Rseries.vo theories/Reals/Rcomplete.vo theories/Arith/Max.vo | |
287 | theories/Reals/AltSeries.vo: theories/Reals/AltSeries.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/Rseries.vo theories/Reals/SeqProp.vo theories/Reals/PartSum.vo theories/Arith/Max.vo | |
288 | theories/Reals/Binomial.vo: theories/Reals/Binomial.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/PartSum.vo | |
289 | theories/Reals/Rsigma.vo: theories/Reals/Rsigma.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/Rseries.vo theories/Reals/PartSum.vo | |
290 | theories/Reals/Rprod.vo: theories/Reals/Rprod.v theories/Arith/Compare.vo theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/Rseries.vo theories/Reals/PartSum.vo theories/Reals/Binomial.vo | |
291 | theories/Reals/Cauchy_prod.vo: theories/Reals/Cauchy_prod.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/Rseries.vo theories/Reals/PartSum.vo | |
292 | theories/Reals/Alembert.vo: theories/Reals/Alembert.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/Rseries.vo theories/Reals/SeqProp.vo theories/Reals/PartSum.vo theories/Arith/Max.vo | |
293 | theories/Reals/SeqSeries.vo: theories/Reals/SeqSeries.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Arith/Max.vo theories/Reals/Rseries.vo theories/Reals/SeqProp.vo theories/Reals/Rcomplete.vo theories/Reals/PartSum.vo theories/Reals/AltSeries.vo theories/Reals/Binomial.vo theories/Reals/Rsigma.vo theories/Reals/Rprod.vo theories/Reals/Cauchy_prod.vo theories/Reals/Alembert.vo | |
294 | theories/Reals/Rtrigo_fun.vo: theories/Reals/Rtrigo_fun.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/SeqSeries.vo | |
295 | theories/Reals/Rtrigo_def.vo: theories/Reals/Rtrigo_def.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/SeqSeries.vo theories/Reals/Rtrigo_fun.vo theories/Arith/Max.vo | |
296 | theories/Reals/Rtrigo_alt.vo: theories/Reals/Rtrigo_alt.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/SeqSeries.vo theories/Reals/Rtrigo_def.vo | |
297 | theories/Reals/Cos_rel.vo: theories/Reals/Cos_rel.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/SeqSeries.vo theories/Reals/Rtrigo_def.vo | |
298 | theories/Reals/Cos_plus.vo: theories/Reals/Cos_plus.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/SeqSeries.vo theories/Reals/Rtrigo_def.vo theories/Reals/Cos_rel.vo theories/Arith/Max.vo | |
299 | theories/Reals/Rtrigo.vo: theories/Reals/Rtrigo.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/SeqSeries.vo theories/Reals/Rtrigo_fun.vo theories/Reals/Rtrigo_def.vo theories/Reals/Rtrigo_alt.vo theories/Reals/Cos_rel.vo theories/Reals/Cos_plus.vo theories/ZArith/ZArith_base.vo theories/ZArith/Zcomplements.vo theories/Logic/Classical_Prop.vo | |
300 | theories/Reals/Rlimit.vo: theories/Reals/Rlimit.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Logic/Classical_Prop.vo contrib/fourier/Fourier.vo | |
301 | theories/Reals/Rderiv.vo: theories/Reals/Rderiv.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/Rlimit.vo contrib/fourier/Fourier.vo theories/Logic/Classical_Prop.vo theories/Logic/Classical_Pred_Type.vo contrib/omega/Omega.vo | |
302 | theories/Reals/RList.vo: theories/Reals/RList.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo | |
303 | theories/Reals/Ranalysis1.vo: theories/Reals/Ranalysis1.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/Rlimit.vo theories/Reals/Rderiv.vo | |
304 | theories/Reals/Ranalysis2.vo: theories/Reals/Ranalysis2.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/Ranalysis1.vo | |
305 | theories/Reals/Ranalysis3.vo: theories/Reals/Ranalysis3.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/Ranalysis1.vo theories/Reals/Ranalysis2.vo | |
306 | theories/Reals/Rtopology.vo: theories/Reals/Rtopology.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/Ranalysis1.vo theories/Reals/RList.vo theories/Logic/Classical_Prop.vo theories/Logic/Classical_Pred_Type.vo | |
307 | theories/Reals/MVT.vo: theories/Reals/MVT.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/Ranalysis1.vo theories/Reals/Rtopology.vo | |
308 | theories/Reals/PSeries_reg.vo: theories/Reals/PSeries_reg.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/SeqSeries.vo theories/Reals/Ranalysis1.vo theories/Arith/Max.vo theories/Arith/Even.vo | |
309 | theories/Reals/Exp_prop.vo: theories/Reals/Exp_prop.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/SeqSeries.vo theories/Reals/Rtrigo.vo theories/Reals/Ranalysis1.vo theories/Reals/PSeries_reg.vo theories/Arith/Div2.vo theories/Arith/Even.vo theories/Arith/Max.vo | |
310 | theories/Reals/Rtrigo_reg.vo: theories/Reals/Rtrigo_reg.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/SeqSeries.vo theories/Reals/Rtrigo.vo theories/Reals/Ranalysis1.vo theories/Reals/PSeries_reg.vo | |
311 | theories/Reals/Rsqrt_def.vo: theories/Reals/Rsqrt_def.v theories/Bool/Sumbool.vo theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/SeqSeries.vo theories/Reals/Ranalysis1.vo | |
312 | theories/Reals/R_sqrt.vo: theories/Reals/R_sqrt.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/Rsqrt_def.vo | |
313 | theories/Reals/Rtrigo_calc.vo: theories/Reals/Rtrigo_calc.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/SeqSeries.vo theories/Reals/Rtrigo.vo theories/Reals/R_sqrt.vo | |
314 | theories/Reals/Rgeom.vo: theories/Reals/Rgeom.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/SeqSeries.vo theories/Reals/Rtrigo.vo theories/Reals/R_sqrt.vo | |
315 | theories/Reals/Sqrt_reg.vo: theories/Reals/Sqrt_reg.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/Ranalysis1.vo theories/Reals/R_sqrt.vo | |
316 | theories/Reals/Ranalysis4.vo: theories/Reals/Ranalysis4.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/SeqSeries.vo theories/Reals/Rtrigo.vo theories/Reals/Ranalysis1.vo theories/Reals/Ranalysis3.vo theories/Reals/Exp_prop.vo | |
317 | theories/Reals/Rpower.vo: theories/Reals/Rpower.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/SeqSeries.vo theories/Reals/Rtrigo.vo theories/Reals/Ranalysis1.vo theories/Reals/Exp_prop.vo theories/Reals/Rsqrt_def.vo theories/Reals/R_sqrt.vo theories/Reals/MVT.vo theories/Reals/Ranalysis4.vo | |
318 | theories/Reals/Ranalysis.vo: theories/Reals/Ranalysis.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/Rtrigo.vo theories/Reals/SeqSeries.vo theories/Reals/Ranalysis1.vo theories/Reals/Ranalysis2.vo theories/Reals/Ranalysis3.vo theories/Reals/Rtopology.vo theories/Reals/MVT.vo theories/Reals/PSeries_reg.vo theories/Reals/Exp_prop.vo theories/Reals/Rtrigo_reg.vo theories/Reals/Rsqrt_def.vo theories/Reals/R_sqrt.vo theories/Reals/Rtrigo_calc.vo theories/Reals/Rgeom.vo theories/Reals/RList.vo theories/Reals/Sqrt_reg.vo theories/Reals/Ranalysis4.vo theories/Reals/Rpower.vo | |
319 | theories/Reals/NewtonInt.vo: theories/Reals/NewtonInt.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/SeqSeries.vo theories/Reals/Rtrigo.vo theories/Reals/Ranalysis.vo | |
320 | theories/Reals/RiemannInt_SF.vo: theories/Reals/RiemannInt_SF.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/Ranalysis.vo theories/Logic/Classical_Prop.vo | |
321 | theories/Reals/RiemannInt.vo: theories/Reals/RiemannInt.v theories/Reals/Rfunctions.vo theories/Reals/SeqSeries.vo theories/Reals/Ranalysis.vo theories/Reals/Rbase.vo theories/Reals/RiemannInt_SF.vo theories/Logic/Classical_Prop.vo theories/Logic/Classical_Pred_Type.vo theories/Arith/Max.vo | |
322 | theories/Reals/Integration.vo: theories/Reals/Integration.v theories/Reals/NewtonInt.vo theories/Reals/RiemannInt_SF.vo theories/Reals/RiemannInt.vo | |
323 | theories/Reals/Reals.vo: theories/Reals/Reals.v theories/Reals/Rbase.vo theories/Reals/Rfunctions.vo theories/Reals/SeqSeries.vo theories/Reals/Rtrigo.vo theories/Reals/Ranalysis.vo theories/Reals/Integration.vo | |
324 | 276 | theories/Sorting/Heap.vo: theories/Sorting/Heap.v theories/Lists/List.vo theories/Sets/Multiset.vo theories/Sorting/Permutation.vo theories/Relations/Relations.vo theories/Sorting/Sorting.vo |
325 | 277 | theories/Sorting/Permutation.vo: theories/Sorting/Permutation.v theories/Relations/Relations.vo theories/Lists/List.vo theories/Sets/Multiset.vo theories/Arith/Arith.vo |
326 | 278 | theories/Sorting/Sorting.vo: theories/Sorting/Sorting.v theories/Lists/List.vo theories/Sets/Multiset.vo theories/Sorting/Permutation.vo theories/Relations/Relations.vo |
331 | 283 | theories/QArith/Qring.vo: theories/QArith/Qring.v contrib/ring/Ring.vo contrib/ring/Setoid_ring.vo theories/QArith/QArith_base.vo |
332 | 284 | theories/QArith/Qreals.vo: theories/QArith/Qreals.v theories/Reals/Rbase.vo theories/QArith/QArith_base.vo |
333 | 285 | theories/QArith/QArith.vo: theories/QArith/QArith.v theories/QArith/QArith_base.vo theories/QArith/Qring.vo theories/QArith/Qreduction.vo |
286 | theories/QArith/Qcanon.vo: theories/QArith/Qcanon.v theories/QArith/QArith.vo theories/Logic/Eqdep_dec.vo contrib/field/Field.vo | |
334 | 287 | contrib/omega/OmegaLemmas.vo: contrib/omega/OmegaLemmas.v theories/ZArith/ZArith_base.vo |
335 | 288 | contrib/omega/Omega.vo: contrib/omega/Omega.v theories/ZArith/ZArith_base.vo contrib/omega/OmegaLemmas.vo theories/ZArith/Zhints.vo |
336 | 289 | contrib/romega/ReflOmegaCore.vo: contrib/romega/ReflOmegaCore.v theories/Arith/Arith.vo theories/Lists/List.vo theories/Bool/Bool.vo theories/ZArith/ZArith_base.vo contrib/omega/OmegaLemmas.vo theories/Logic/Decidable.vo |
352 | 305 | contrib/field/Field.vo: contrib/field/Field.v contrib/field/Field_Compl.vo contrib/field/Field_Theory.vo contrib/field/Field_Tactic.vo |
353 | 306 | contrib/fourier/Fourier_util.vo: contrib/fourier/Fourier_util.v theories/Reals/Rbase.vo |
354 | 307 | contrib/fourier/Fourier.vo: contrib/fourier/Fourier.v contrib/ring/quote.cmo contrib/ring/ring.cmo contrib/fourier/fourier.cmo contrib/fourier/fourierR.cmo contrib/field/field.cmo contrib/fourier/Fourier_util.vo contrib/field/Field.vo theories/Reals/DiscrR.vo |
355 | contrib/subtac/FixSub.vo: contrib/subtac/FixSub.v theories/Init/Wf.vo | |
308 | contrib/subtac/FixSub.vo: contrib/subtac/FixSub.v theories/Init/Wf.vo theories/Arith/Wf_nat.vo theories/Arith/Lt.vo | |
356 | 309 | contrib/subtac/Utils.vo: contrib/subtac/Utils.v |
357 | 310 | contrib/rtauto/Bintree.vo: contrib/rtauto/Bintree.v theories/Lists/List.vo theories/NArith/BinPos.vo |
358 | 311 | contrib/rtauto/Rtauto.vo: contrib/rtauto/Rtauto.v theories/Lists/List.vo contrib/rtauto/Bintree.vo theories/Bool/Bool.vo theories/NArith/BinPos.vo |
9 | 9 | |
10 | 10 | - No more support for version 7 syntax and for translation to version 8 syntax. |
11 | 11 | - In fixpoints, the { struct ... } annotation is not mandatory any more when |
12 | only one of the arguments has an inductive type (doc TODO) | |
13 | - Added disjunctive patterns in match-with patterns (doc TODO) | |
14 | - Support for primitive interpretation of string literals (doc TODO) | |
15 | - Extended support for Unicode ranges (doc TODO) | |
12 | only one of the arguments has an inductive type | |
13 | - Added disjunctive patterns in match-with patterns | |
14 | - Support for primitive interpretation of string literals | |
15 | - Extended support for Unicode ranges | |
16 | 16 | |
17 | 17 | Vernacular commands |
18 | 18 | |
19 | - Added "Print Ltac qualid" to print a user defined tactic (doc TODO) | |
19 | - Added "Print Ltac qualid" to print a user defined tactic. | |
20 | 20 | - Added "Print Rewrite HintDb" to print the content of a DB used by |
21 | autorewrite (doc TODO) | |
22 | - Added "Print Canonical Projections" (doc TODO) | |
23 | - Added "Example" as synonym of "Definition" (doc TODO) | |
24 | - Added "Property", "Proposition" and "Corollary" as extra synonyms of "Lemma" | |
25 | (doc TODO) | |
21 | autorewrite. | |
22 | - Added "Print Canonical Projections". | |
23 | - Added "Example" as synonym of "Definition". | |
24 | - Added "Proposition" and "Corollary" as extra synonyms of "Lemma". | |
26 | 25 | - New command "Whelp" to send requests to the Helm database of proofs |
27 | formalized in the Calculus of Inductive Constructions (doc TODO) | |
26 | formalized in the Calculus of Inductive Constructions. | |
28 | 27 | - Command "functional induction" has been re-implemented from the new |
29 | "definition" command. | |
28 | "Function" command. | |
30 | 29 | |
31 | 30 | Ltac and tactic syntactic extensions |
32 | 31 | |
33 | - New primitive "external" for communication with tool external to Coq | |
34 | (doc TODO). | |
32 | - New primitive "external" for communication with tool external to Coq. | |
35 | 33 | - New semantics for "match t with": if a clause returns a |
36 | 34 | tactic, it is now applied to the current goal. If it fails, the next |
37 | 35 | clause or next matching subterm is tried (i.e. it behaves as "match |
38 | goal with" does) (doc TODO). | |
36 | goal with" does). The keyword "lazymatch" can be used to delay the | |
37 | evaluation of tactics occurring in matching clauses. | |
39 | 38 | - Hint base names can be parametric in auto and trivial. |
40 | 39 | - Occurrence values can be parametric in unfold, pattern, etc. |
41 | 40 | - Added entry constr_may_eval for tactic extensions. |
42 | 41 | - Low-priority term printer made available in ML-written tactic extensions. |
43 | - "Tactic Notation" extended to allow notations of tacticals (doc TODO). | |
42 | - "Tactic Notation" extended to allow notations of tacticals. | |
44 | 43 | |
45 | 44 | Tactics |
46 | 45 | |
56 | 55 | - "rewrite ... in" now accepts a clause as place where to rewrite instead of |
57 | 56 | juste a simple hypothesis name. For instance: |
58 | 57 | rewrite H in H1,H2 |- * means rewrite H in H1; rewrite H in H2; rewrite H |
59 | rewrite H in * |- will do try rewrite H in Hi for all hypothesis Hi <> H | |
60 | (doc TODO). | |
61 | - Added "clear - id" to clear all hypotheses except the ones depending in id | |
62 | (doc TODO). | |
58 | rewrite H in * |- will do try rewrite H in Hi for all hypothesis Hi <> H. | |
63 | 59 | - Added "dependent rewrite term" and "dependent rewrite term in hyp" (doc TODO) |
60 | - Added "autorewrite with ... in hyp [using ...]". | |
61 | - Tactic "replace" now accepts a "by" tactic clause. | |
62 | - Added "clear - id" to clear all hypotheses except the ones depending in id. | |
64 | 63 | - The argument of Declare Left Step and Declare Right Step is now a term |
65 | (it used to be a reference) (doc TODO). | |
64 | (it used to be a reference). | |
66 | 65 | - Omega now handles arbitrary precision integers. |
67 | 66 | - Several bug fixes in Reflexive Omega (romega). |
68 | 67 | - Idtac can now be left implicit in a [...|...] construct: for instance, |
69 | [ foo | | bar ] stands for [ foo | idtac | bar ] (doc TODO). | |
70 | - Added "autorewrite with ... in hyp [using ...]" (doc TODO). | |
68 | [ foo | | bar ] stands for [ foo | idtac | bar ]. | |
71 | 69 | - Fixed a "fold" bug (non critical but possible source of incompatibilities). |
72 | 70 | - Added classical_left and classical_right which transforms |- A \/ B into |
73 | 71 | ~B |- A and ~A |- B respectively. |
74 | 72 | - Added command "Declare Implicit Tactic" to set up a default tactic to be |
75 | used to solve unresolved subterms of term arguments of tactics (doc TODO). | |
73 | used to solve unresolved subterms of term arguments of tactics. | |
76 | 74 | - Better support for coercions to Sortclass in tactics expecting type |
77 | 75 | arguments. |
78 | - Tactic "assert" now accepts "as" intro patterns and "by" tactic clauses | |
79 | (doc TODO). | |
80 | - Tactic "replace" now accepts a "by" tactic clause (doc TODO). | |
81 | - New tactic "pose proof" that generalizes "assert (id:=p)" with intro patterns | |
82 | (doc TODO). | |
83 | - New introduction pattern "?" for letting Coq choose a name (doc TODO). | |
84 | - Added "eassumption" (doc TODO). | |
85 | - Added option 'using lemmas' to auto, trivial and eauto (doc TODO). | |
76 | - Tactic "assert" now accepts "as" intro patterns and "by" tactic clauses. | |
77 | - New tactic "pose proof" that generalizes "assert (id:=p)" with intro patterns. | |
78 | - New introduction pattern "?" for letting Coq choose a name. | |
79 | - Added "eassumption". | |
80 | - Added option 'using lemmas' to auto, trivial and eauto. | |
81 | - Tactic "congruence" is now complete for its intended scope (ground | |
82 | equalities and inequalities with constructors). Furthermore, it | |
83 | tries to equates goal and hypotheses. | |
84 | - New tactic "rtauto" solves pure propositional logic and gives a | |
85 | reflective version of the available proof. | |
86 | 86 | - Numbering of "pattern", "unfold", "simpl", ... occurrences in "match |
87 | 87 | with" made consistent with the printing of the return clause after |
88 | 88 | the term to match in the "match-with" construct (use "Set Printing All" |
89 | 89 | to see hidden occurrences). |
90 | 90 | - Generalization of induction "induction x1...xn using scheme" where |
91 | 91 | scheme is an induction principle with complex predicates (like the |
92 | ones generated by function induction) (doc TODO). | |
92 | ones generated by function induction). | |
93 | 93 | - Some small Ltac tactics has been added to the standard library |
94 | 94 | (file Tactics.v): |
95 | 95 | * f_equal : instead of using the different f_equalX lemmas |
110 | 110 | |
111 | 111 | Modules |
112 | 112 | |
113 | - Added "Locate Module qualid" to get the full path of a module (TODO doc). | |
114 | - Module/Declare Module syntax made more uniform (doc TODO). | |
113 | - Added "Locate Module qualid" to get the full path of a module. | |
114 | - Module/Declare Module syntax made more uniform. | |
115 | 115 | - Added syntactic sugar "Declare Module Export/Import" and |
116 | "Module Export/Import" (doc TODO). | |
116 | "Module Export/Import". | |
117 | 117 | - Added syntactic sugar "Module M(Export/Import X Y: T)" and |
118 | 118 | "Module Type M(Export/Import X Y: T)" |
119 | (only for interactive definitions) (doc TODO) | |
119 | (only for interactive definitions) | |
120 | 120 | - Construct "with" generalized to module paths: |
121 | 121 | T with (Definition|Module) M1.M2....Mn.l := l' (doc TODO). |
122 | 122 | |
126 | 126 | - Added insertion of spaces by default in recursive notations w/o separators. |
127 | 127 | - No more automatic printing box in case of user-provided printing "format". |
128 | 128 | - New notation "exists! x:A, P" for unique existence. |
129 | - Notations for specific numerals now compatible with generic notations of | |
130 | numerals (e.g. "1" can be used to denote the unit of a group without | |
131 | hiding 1%nat) | |
129 | 132 | |
130 | 133 | Libraries |
131 | 134 | |
133 | 136 | - New library FSets+FMaps of finite sets and maps. |
134 | 137 | - New library QArith on rational numbers. |
135 | 138 | - Small extension of Zmin.V, new Zmax.v, new Zminmax.v. |
136 | - Reworking of the files on classical logic and description principles | |
137 | (possible incompatibilities). | |
139 | - Reworking and extension of the files on classical logic and | |
140 | description principles (possible incompatibilities) | |
138 | 141 | - Few other improvements in ZArith potentially exceptionally breaking the |
139 | 142 | compatibility (useless hypothesys of Zgt_square_simpl and |
140 | 143 | Zlt_square_simpl removed; fixed names mentioning letter O instead of |
143 | 146 | - Znumtheory now contains a gcd function that can compute within Coq. |
144 | 147 | - More lemmas stated on Type in Wf.v, removal of redundant Fix_F. |
145 | 148 | - Change of the internal names of lemmas in OmegaLemmas. |
149 | - Acc in Wf.v and clos_refl_trans in Relation_Operators.v now rely on | |
150 | the allowance for recursively non uniform parameters (possible | |
151 | source of incompatibilities: explicit pattern-matching on these | |
152 | types may require to remove the occurrence associated to their | |
153 | recursively non uniform parameter). | |
146 | 154 | - Coq.List.In_dec has been set transparent (this may exceptionally break |
147 | 155 | proof scripts, set it locally opaque for compatibility). |
148 | 156 | - More on permutations of lists in List.v and Permutation.v. |
168 | 176 | "make clean" |
169 | 177 | - New environment variable COQREMOTEBROWSER to set the command invoked |
170 | 178 | to start the remote browser both in Coq and coqide. Standard syntax: |
171 | "%s" is the placeholder for the URL (doc TODO) | |
179 | "%s" is the placeholder for the URL. | |
172 | 180 | |
173 | 181 | |
174 | 182 | Changes from V8.0beta to V8.0 |
0 | Potential sources of incompatibilities between Coq V8.0 and V8.1 | |
1 | ---------------------------------------------------------------- | |
2 | ||
3 | (see also file CHANGES) | |
4 | ||
5 | - Inductive types in Type are now polymorphic over their parameters in | |
6 | Type. This may affect the naming of introduction hypotheses if such | |
7 | an inductive type in Type is used on small types such as Prop or | |
8 | Set: the hypothesis names suffix will default to H instead of X. As | |
9 | a matter of fact, it is recommended to systematically name the | |
10 | hypotheses that are later refered to in the proof script. | |
11 | ||
12 | - Some bug fixes may lead to incompatibilities. This is e.g. the case | |
13 | of inversion on Type which failed to rewrite some hypotheses as it | |
14 | did on Prop/Set. | |
15 | ||
16 | - Add Morphism for the Prop/iff setoid now requires a proof of | |
17 | biimplication instead of a proof of implication. | |
18 | ||
19 | - The order of arguments in compatibility morphisms changed: the | |
20 | premises and the parameters are now interleaved while the whole | |
21 | bunch of parameters used to come first. | |
22 | ||
23 | - A few changes in the library (as mentioned in the CHANGES file) may | |
24 | imply the need for local adaptations. | |
25 | ||
26 | - Occurrence numbering order for unfold, pattern, etc changed for the | |
27 | match construction: occurrences in the return clause now come after | |
28 | the occurrences in the term matched; this was the opposite before. | |
29 | ||
30 | - For changes in the ML interfaces, see file dev/doc/changes.txt in | |
31 | the main archive. |
5 | 5 | # # GNU Lesser General Public License Version 2.1 # |
6 | 6 | ####################################################################### |
7 | 7 | |
8 | # $Id: Makefile 8933 2006-06-09 14:08:38Z herbelin $ | |
8 | # $Id: Makefile 8989 2006-06-25 22:17:49Z letouzey $ | |
9 | 9 | |
10 | 10 | |
11 | 11 | # Makefile for Coq |
873 | 873 | QARITHVO=\ |
874 | 874 | theories/QArith/QArith_base.vo theories/QArith/Qreduction.vo \ |
875 | 875 | theories/QArith/Qring.vo theories/QArith/Qreals.vo \ |
876 | theories/QArith/QArith.vo | |
876 | theories/QArith/QArith.vo theories/QArith/Qcanon.vo | |
877 | 877 | |
878 | 878 | LISTSVO=\ |
879 | 879 | theories/Lists/MonoList.vo \ |
29 | 29 | best_compiler=opt |
30 | 30 | |
31 | 31 | local=false |
32 | src_spec=no | |
33 | prefix_spec=no | |
32 | 34 | bindir_spec=no |
33 | 35 | libdir_spec=no |
34 | 36 | mandir_spec=no |
43 | 45 | coqide_spec=no |
44 | 46 | with_geoproof=true |
45 | 47 | |
46 | COQTOP=`pwd` | |
48 | # COQTOP=`pwd` | |
47 | 49 | |
48 | 50 | |
49 | 51 | # Parse command-line arguments |
51 | 53 | while : ; do |
52 | 54 | case "$1" in |
53 | 55 | "") break;; |
54 | -prefix|--prefix) bindir_spec=yes | |
55 | bindir=$2/bin | |
56 | libdir_spec=yes | |
57 | libdir=$2/lib/coq | |
58 | mandir_spec=yes | |
59 | mandir=$2/man | |
60 | coqdocdir_spec=yes | |
61 | coqdocdir=$2/share/texmf/tex/latex/misc | |
56 | -prefix|--prefix) prefix_spec=yes | |
57 | prefix="$2" | |
62 | 58 | shift;; |
63 | 59 | -local|--local) local=true |
64 | bindir_spec=yes | |
65 | bindir=$COQTOP/bin | |
66 | libdir_spec=yes | |
67 | libdir=$COQTOP | |
68 | mandir_spec=yes | |
69 | mandir=$COQTOP/man | |
70 | emacslib_spec=yes | |
71 | emacslib=$COQTOP/tools/emacs | |
72 | coqdocdir_spec=yes | |
73 | coqdocdir=$COQTOP/tools/coqdoc | |
74 | fsets_opt=yes | |
75 | fsets=all | |
76 | 60 | reals_opt=yes |
77 | 61 | reals=all;; |
78 | -src|--src) COQTOP=$2 | |
62 | -src|--src) src_spec=yes | |
63 | COQTOP="$2" | |
79 | 64 | shift;; |
80 | 65 | -bindir|--bindir) bindir_spec=yes |
81 | bindir=$2 | |
66 | bindir="$2" | |
82 | 67 | shift;; |
83 | 68 | -libdir|--libdir) libdir_spec=yes |
84 | libdir=$2 | |
69 | libdir="$2" | |
85 | 70 | shift;; |
86 | 71 | -mandir|--mandir) mandir_spec=yes |
87 | mandir=$2 | |
72 | mandir="$2" | |
88 | 73 | shift;; |
89 | 74 | -emacslib|--emacslib) emacslib_spec=yes |
90 | emacslib=$2 | |
75 | emacslib="$2" | |
91 | 76 | shift;; |
92 | 77 | -emacs |--emacs) emacs_spec=yes |
93 | emacs=$2 | |
78 | emacs="$2" | |
94 | 79 | shift;; |
95 | 80 | -coqdocdir|--coqdocdir) coqdocdir_spec=yes |
96 | coqdocdir=$2 | |
81 | coqdocdir="$2" | |
97 | 82 | shift;; |
98 | 83 | -arch|--arch) arch_spec=yes |
99 | 84 | arch=$2 |
124 | 109 | shift |
125 | 110 | done |
126 | 111 | |
112 | if [ $prefix_spec = yes -a $local = true ] ; then | |
113 | echo "Options -prefix and -local are incompatible" | |
114 | echo "Configure script failed!" | |
115 | exit 1 | |
116 | fi | |
127 | 117 | |
128 | 118 | # compile date |
129 | 119 | DATEPGM=`which date` |
159 | 149 | yes) ARCH=$arch |
160 | 150 | esac |
161 | 151 | |
162 | # bindir, libdir, mandir, etc. | |
163 | ||
164 | case $ARCH in | |
165 | win32) | |
166 | bindir_def=C:\\coq\\bin | |
167 | libdir_def=C:\\coq\\lib | |
168 | mandir_def=C:\\coq\\man | |
169 | emacslib_def=C:\\coq\\emacs;; | |
170 | *) | |
171 | bindir_def=/usr/local/bin | |
172 | libdir_def=/usr/local/lib/coq | |
173 | mandir_def=/usr/local/man | |
174 | emacslib_def=/usr/share/emacs/site-lisp | |
175 | coqdocdir_def=/usr/share/texmf/tex/latex/misc;; | |
176 | esac | |
177 | ||
178 | emacs_def=emacs | |
179 | ||
180 | case $bindir_spec in | |
181 | no) echo "Where should I install the Coq binaries [$bindir_def] ?" | |
182 | read BINDIR | |
183 | ||
184 | case $BINDIR in | |
185 | "") BINDIR=$bindir_def;; | |
186 | *) true;; | |
187 | esac;; | |
188 | yes) BINDIR=$bindir;; | |
189 | esac | |
190 | ||
191 | case $libdir_spec in | |
192 | no) echo "Where should I install the Coq library [$libdir_def] ?" | |
193 | read LIBDIR | |
194 | ||
195 | case $LIBDIR in | |
196 | "") LIBDIR=$libdir_def;; | |
197 | *) true;; | |
198 | esac;; | |
199 | yes) LIBDIR=$libdir;; | |
200 | esac | |
201 | ||
202 | case $mandir_spec in | |
203 | no) echo "Where should I install the Coq man pages [$mandir_def] ?" | |
204 | read MANDIR | |
205 | ||
206 | case $MANDIR in | |
207 | "") MANDIR=$mandir_def;; | |
208 | *) true;; | |
209 | esac;; | |
210 | yes) MANDIR=$mandir;; | |
211 | esac | |
212 | ||
213 | case $emacslib_spec in | |
214 | no) echo "Where should I install the Coq Emacs mode [$emacslib_def] ?" | |
215 | read EMACSLIB | |
216 | ||
217 | case $EMACSLIB in | |
218 | "") EMACSLIB=$emacslib_def;; | |
219 | *) true;; | |
220 | esac;; | |
221 | yes) EMACSLIB=$emacslib;; | |
222 | esac | |
223 | ||
224 | case $coqdocdir_spec in | |
225 | no) echo "Where should I install Coqdoc TeX/LaTeX files [$coqdocdir_def] ?" | |
226 | read COQDOCDIR | |
227 | ||
228 | case $COQDOCDIR in | |
229 | "") COQDOCDIR=$coqdocdir_def;; | |
230 | *) true;; | |
231 | esac;; | |
232 | yes) COQDOCDIR=$coqdocdir;; | |
233 | esac | |
234 | ||
235 | case $fsets_opt in | |
236 | no) echo "Should I compile the complete theory of finite sets [Y/N, default is Y] ?" | |
237 | read fsets_ans | |
238 | ||
239 | case $fsets_ans in | |
240 | "N"|"n"|"No"|"NO"|"no") | |
241 | fsets=basic;; | |
242 | *) fsets=all;; | |
243 | esac;; | |
244 | yes) true;; | |
245 | esac | |
246 | ||
247 | case $reals_opt in | |
248 | no) echo "Should I compile the complete theory of real analysis [Y/N, default is Y] ?" | |
249 | read reals_ans | |
250 | ||
251 | case $reals_ans in | |
252 | "N"|"n"|"No"|"NO"|"no") | |
253 | reals=basic;; | |
254 | *) reals=all;; | |
255 | esac;; | |
256 | yes) true;; | |
257 | esac | |
258 | ||
259 | # case $emacs_spec in | |
260 | # no) echo "Which Emacs command should I use to compile coq.el [$emacs_def] ?" | |
261 | # read EMACS | |
262 | ||
263 | # case $EMACS in | |
264 | # "") EMACS=$emacs_def;; | |
265 | # *) true;; | |
266 | # esac;; | |
267 | # yes) EMACS=$emacs;; | |
268 | # esac | |
269 | ||
270 | # OS dependent libraries | |
271 | ||
272 | case $ARCH in | |
273 | sun4*) OS=`uname -r` | |
274 | case $OS in | |
275 | 5*) OS="Sun Solaris $OS" | |
276 | OSDEPLIBS="-cclib -lunix -cclib -lnsl -cclib -lsocket";; | |
277 | *) OS="Sun OS $OS" | |
278 | OSDEPLIBS="-cclib -lunix" | |
279 | esac;; | |
280 | alpha) OSDEPLIBS="-cclib -lunix";; | |
281 | win32) OS="Win32" | |
282 | OSDEPLIBS="-cclib -lunix";; | |
283 | *) OSDEPLIBS="-cclib -lunix" | |
284 | esac | |
285 | ||
286 | 152 | # executable extension |
287 | 153 | |
288 | 154 | case $ARCH in |
290 | 156 | *) EXE="" |
291 | 157 | esac |
292 | 158 | |
159 | # strip command | |
160 | ||
161 | case $ARCH in | |
162 | win32) | |
163 | # true -> strip : it exists under cygwin ! | |
164 | STRIPCOMMAND="strip";; | |
165 | *) | |
166 | if [ "$coq_profile_flag" = "-p" ] ; then | |
167 | STRIPCOMMAND="true" | |
168 | else | |
169 | STRIPCOMMAND="strip" | |
170 | fi | |
171 | esac | |
172 | ||
173 | ######################################### | |
293 | 174 | # Objective Caml programs |
294 | 175 | |
295 | 176 | CAMLC=`which $bytecamlc` |
370 | 251 | # *) |
371 | 252 | # CAMLP4LIB=${CAMLLIB}/camlp4 |
372 | 253 | #esac |
254 | ||
255 | # OS dependent libraries | |
256 | ||
257 | case $ARCH in | |
258 | sun4*) OS=`uname -r` | |
259 | case $OS in | |
260 | 5*) OS="Sun Solaris $OS" | |
261 | OSDEPLIBS="-cclib -lunix -cclib -lnsl -cclib -lsocket";; | |
262 | *) OS="Sun OS $OS" | |
263 | OSDEPLIBS="-cclib -lunix" | |
264 | esac;; | |
265 | alpha) OSDEPLIBS="-cclib -lunix";; | |
266 | win32) OS="Win32" | |
267 | OSDEPLIBS="-cclib -lunix";; | |
268 | *) OSDEPLIBS="-cclib -lunix" | |
269 | esac | |
373 | 270 | |
374 | 271 | # lablgtk2 and CoqIDE |
375 | 272 | |
422 | 319 | # "") MKTEXLSR=true;; |
423 | 320 | #esac |
424 | 321 | |
322 | ########################################### | |
323 | # bindir, libdir, mandir, etc. | |
324 | ||
325 | canonical_pwd () { | |
326 | ocaml 2>&1 1>/dev/null <<EOF | |
327 | prerr_endline(Sys.getcwd());; | |
328 | EOF | |
329 | } | |
330 | ||
331 | case $src_spec in | |
332 | no) COQTOP=`canonical_pwd` | |
333 | esac | |
334 | ||
335 | case $ARCH in | |
336 | win32) | |
337 | bindir_def='C:\coq\bin' | |
338 | libdir_def='C:\coq\lib' | |
339 | mandir_def='C:\coq\man' | |
340 | emacslib_def='C:\coq\emacs' | |
341 | coqdocdir_def='C:\coq\latex';; | |
342 | *) | |
343 | bindir_def=/usr/local/bin | |
344 | libdir_def=/usr/local/lib/coq | |
345 | mandir_def=/usr/local/man | |
346 | emacslib_def=/usr/share/emacs/site-lisp | |
347 | coqdocdir_def=/usr/share/texmf/tex/latex/misc;; | |
348 | esac | |
349 | ||
350 | emacs_def=emacs | |
351 | ||
352 | case $bindir_spec/$prefix_spec/$local in | |
353 | yes/*/*) BINDIR=$bindir ;; | |
354 | */yes/*) BINDIR=$prefix/bin ;; | |
355 | */*/true) BINDIR=$COQTOP/bin ;; | |
356 | *) echo "Where should I install the Coq binaries [$bindir_def] ?" | |
357 | read BINDIR | |
358 | case $BINDIR in | |
359 | "") BINDIR=$bindir_def;; | |
360 | *) true;; | |
361 | esac;; | |
362 | esac | |
363 | ||
364 | case $libdir_spec/$prefix_spec/$local in | |
365 | yes/*/*) LIBDIR=$libdir;; | |
366 | */yes/*) | |
367 | case $ARCH in | |
368 | win32) LIBDIR=$prefix ;; | |
369 | *) LIBDIR=$prefix/lib/coq ;; | |
370 | esac ;; | |
371 | */*/true) LIBDIR=$COQTOP ;; | |
372 | *) echo "Where should I install the Coq library [$libdir_def] ?" | |
373 | read LIBDIR | |
374 | case $LIBDIR in | |
375 | "") LIBDIR=$libdir_def;; | |
376 | *) true;; | |
377 | esac;; | |
378 | esac | |
379 | ||
380 | case $mandir_spec/$prefix_spec/$local in | |
381 | yes/*/*) MANDIR=$mandir;; | |
382 | */yes/*) MANDIR=$prefix/man ;; | |
383 | */*/true) MANDIR=$COQTOP/man ;; | |
384 | *) echo "Where should I install the Coq man pages [$mandir_def] ?" | |
385 | read MANDIR | |
386 | case $MANDIR in | |
387 | "") MANDIR=$mandir_def;; | |
388 | *) true;; | |
389 | esac;; | |
390 | esac | |
391 | ||
392 | case $emacslib_spec/$prefix_spec/$local in | |
393 | yes/*/*) EMACSLIB=$emacslib;; | |
394 | */yes/*) | |
395 | case $ARCH in | |
396 | win32) EMACSLIB=$prefix/emacs ;; | |
397 | *) EMACSLIB=$prefix/share/emacs/site-lisp ;; | |
398 | esac ;; | |
399 | */*/true) EMACSLIB=$COQTOP/tools/emacs ;; | |
400 | *) echo "Where should I install the Coq Emacs mode [$emacslib_def] ?" | |
401 | read EMACSLIB | |
402 | case $EMACSLIB in | |
403 | "") EMACSLIB=$emacslib_def;; | |
404 | *) true;; | |
405 | esac;; | |
406 | esac | |
407 | ||
408 | case $coqdocdir_spec/$prefix_spec/$local in | |
409 | yes/*/*) COQDOCDIR=$coqdocdir;; | |
410 | */yes/*) | |
411 | case $ARCH in | |
412 | win32) COQDOCDIR=$prefix/latex ;; | |
413 | *) COQDOCDIR=$prefix/share/emacs/site-lisp ;; | |
414 | esac ;; | |
415 | */*/true) COQDOCDIR=$COQTOP/tools/coqdoc ;; | |
416 | *) echo "Where should I install Coqdoc TeX/LaTeX files [$coqdocdir_def] ?" | |
417 | read COQDOCDIR | |
418 | case $COQDOCDIR in | |
419 | "") COQDOCDIR=$coqdocdir_def;; | |
420 | *) true;; | |
421 | esac;; | |
422 | esac | |
423 | ||
424 | case $reals_opt in | |
425 | no) echo "Should I compile the complete theory of real analysis [Y/N, default is Y] ?" | |
426 | read reals_ans | |
427 | ||
428 | case $reals_ans in | |
429 | "N"|"n"|"No"|"NO"|"no") | |
430 | reals=basic;; | |
431 | *) reals=all;; | |
432 | esac;; | |
433 | yes) true;; | |
434 | esac | |
435 | ||
436 | # case $emacs_spec in | |
437 | # no) echo "Which Emacs command should I use to compile coq.el [$emacs_def] ?" | |
438 | # read EMACS | |
439 | ||
440 | # case $EMACS in | |
441 | # "") EMACS=$emacs_def;; | |
442 | # *) true;; | |
443 | # esac;; | |
444 | # yes) EMACS=$emacs;; | |
445 | # esac | |
446 | ||
447 | ########################################### | |
425 | 448 | # Summary of the configuration |
426 | 449 | |
427 | 450 | echo "" |
459 | 482 | # Building the $COQTOP/config/coq_config.ml file |
460 | 483 | ##################################################### |
461 | 484 | |
462 | # damned backslashes under M$Windows | |
463 | case $ARCH in | |
464 | win32) | |
465 | CAMLLIB=`echo $CAMLLIB |sed -e 's|\\\|\\\\\\\|g'` | |
466 | BINDIR=`echo $BINDIR |sed -e 's|\\\|\\\\\\\|g'` | |
467 | LIBDIR=`echo $LIBDIR |sed -e 's|\\\|\\\\\\\|g'` | |
468 | MANDIR=`echo $MANDIR |sed -e 's|\\\|\\\\\\\|g'` | |
469 | EMACSLIB=`echo $EMACSLIB |sed -e 's|\\\|\\\\\\\|g'` | |
470 | ;; | |
471 | esac | |
485 | # An escaped version of a variable | |
486 | escape_var () { | |
487 | ocaml 2>&1 1>/dev/null <<EOF | |
488 | prerr_endline(String.escaped(Sys.getenv"$VAR"));; | |
489 | EOF | |
490 | } | |
491 | ||
492 | export COQTOP BINDIR LIBDIR CAMLLIB | |
493 | ESCCOQTOP="`VAR=COQTOP escape_var`" | |
494 | ESCBINDIR="`VAR=BINDIR escape_var`" | |
495 | ESCLIBDIR="`VAR=LIBDIR escape_var`" | |
496 | ESCCAMLLIB="`VAR=CAMLLIB escape_var`" | |
497 | ESCCAMLP4LIB="$ESCCAMLLIB"/camlp4 | |
472 | 498 | |
473 | 499 | mlconfig_file=$COQTOP/config/coq_config.ml |
474 | 500 | rm -f $mlconfig_file |
476 | 502 | (* DO NOT EDIT THIS FILE: automatically generated by ../configure *) |
477 | 503 | |
478 | 504 | let local = $local |
479 | let bindir = "$BINDIR" | |
480 | let coqlib = "$LIBDIR" | |
481 | let coqtop = "$COQTOP" | |
482 | let camllib = "$CAMLLIB" | |
483 | let camlp4lib = "$CAMLP4LIB" | |
505 | let bindir = "$ESCBINDIR" | |
506 | let coqlib = "$ESCLIBDIR" | |
507 | let coqtop = "$ESCCOQTOP" | |
508 | let camllib = "$ESCCAMLLIB" | |
509 | let camlp4lib = "$ESCCAMLP4LIB" | |
484 | 510 | let best = "$best_compiler" |
485 | 511 | let arch = "$ARCH" |
486 | 512 | let osdeplibs = "$OSDEPLIBS" |
521 | 547 | # damned backslashes under M$Windows (bis) |
522 | 548 | case $ARCH in |
523 | 549 | win32) |
524 | BINDIR=`echo $BINDIR |sed -e 's|\\\|\\\\\\\|g'` | |
525 | LIBDIR=`echo $LIBDIR |sed -e 's|\\\|\\\\\\\|g'` | |
526 | MANDIR=`echo $MANDIR |sed -e 's|\\\|\\\\\\\|g'` | |
527 | EMACSLIB=`echo $EMACSLIB |sed -e 's|\\\|\\\\\\\|g'` | |
550 | ESCCOQTOP=`echo $COQTOP |sed -e 's|\\\|\\\\\\\|g'` | |
551 | ESCBINDIR=`echo $BINDIR |sed -e 's|\\\|\\\\\\\|g'` | |
552 | ESCLIBDIR=`echo $LIBDIR |sed -e 's|\\\|\\\\\\\|g'` | |
553 | ESCMANDIR=`echo $MANDIR |sed -e 's|\\\|\\\\\\\|g'` | |
554 | ESCEMACSLIB=`echo $EMACSLIB |sed -e 's|\\\|\\\\\\\|g'` | |
555 | ESCCOQDOCDIR=`echo $COQDOCDIR |sed -e 's|\\\|\\\\\\\|g'` | |
556 | ESCCAMLP4BIN=`echo $CAMLP4BIN |sed -e 's|\\\|\\\\\\\|g'` | |
528 | 557 | ;; |
558 | *) | |
559 | ESCCOQTOP="$COQTOP" | |
560 | ESCBINDIR="$BINDIR" | |
561 | ESCLIBDIR="$LIBDIR" | |
562 | ESCMANDIR="$MANDIR" | |
563 | ESCEMACSLIB="$EMACSLIB" | |
564 | ESCCOQDOCDIR="$COQDOCDIR" | |
565 | ESCCAMLP4BIN="$CAMLP4BIN" ;; | |
529 | 566 | esac |
530 | 567 | |
531 | 568 | sed -e "s|LOCALINSTALLATION|$local|" \ |
532 | -e "s|COQTOPDIRECTORY|$COQTOP|" \ | |
569 | -e "s|COQTOPDIRECTORY|$ESCCOQTOP|" \ | |
533 | 570 | -e "s|COQVERSION|$VERSION|" \ |
534 | -e "s|BINDIRDIRECTORY|$BINDIR|" \ | |
535 | -e "s|COQLIBDIRECTORY|$LIBDIR|" \ | |
536 | -e "s|MANDIRDIRECTORY|$MANDIR|" \ | |
537 | -e "s|EMACSLIBDIRECTORY|$EMACSLIB|" \ | |
571 | -e "s|BINDIRDIRECTORY|$ESCBINDIR|" \ | |
572 | -e "s|COQLIBDIRECTORY|$ESCLIBDIR|" \ | |
573 | -e "s|MANDIRDIRECTORY|$ESCMANDIR|" \ | |
574 | -e "s|EMACSLIBDIRECTORY|$ESCEMACSLIB|" \ | |
538 | 575 | -e "s|EMACSCOMMAND|$EMACS|" \ |
539 | -e "s|COQDOCDIRECTORY|$COQDOCDIR|" \ | |
576 | -e "s|COQDOCDIRECTORY|$ESCCOQDOCDIR|" \ | |
540 | 577 | -e "s|MKTEXLSRCOMMAND|$MKTEXLSR|" \ |
541 | 578 | -e "s|ARCHITECTURE|$ARCH|" \ |
542 | 579 | -e "s|OSDEPENDENTLIBS|$OSDEPLIBS|" \ |
543 | 580 | -e "s|OSDEPENDENTP4OPTFLAGS|$OSDEPP4OPTFLAGS|" \ |
544 | 581 | -e "s|CAMLLIBDIRECTORY|$CAMLLIB|" \ |
545 | 582 | -e "s|CAMLTAG|$CAMLTAG|" \ |
546 | -e "s|CAMLP4BINDIRECTORY|$CAMLP4BIN|" \ | |
583 | -e "s|CAMLP4BINDIRECTORY|$ESCCAMLP4BIN|" \ | |
547 | 584 | -e "s|CAMLP4LIBDIRECTORY|$CAMLP4LIB|" \ |
548 | 585 | -e "s|CAMLP4TOOL|$camlp4o|" \ |
549 | 586 | -e "s|CAMLP4COMPATFLAGS|$CAMLP4COMPAT|" \ |
601 | 638 | echo "*Warning* To compile the system for a new architecture" |
602 | 639 | echo " don't forget to do a 'make archclean' before './configure'." |
603 | 640 | |
604 | # $Id: configure 8932 2006-06-09 09:29:03Z notin $ | |
641 | # $Id: configure 8961 2006-06-15 15:22:05Z notin $ |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (*i $Id: extraction.ml 8931 2006-06-09 07:43:37Z letouzey $ i*) | |
8 | (*i $Id: extraction.ml 9032 2006-07-07 16:30:34Z herbelin $ i*) | |
9 | 9 | |
10 | 10 | (*i*) |
11 | 11 | open Util |
405 | 405 | List.iter |
406 | 406 | (option_iter |
407 | 407 | (fun kn -> if Cset.mem kn !projs then add_projection n kn)) |
408 | (lookup_structure ip).s_PROJ | |
408 | (lookup_projections ip) | |
409 | 409 | with Not_found -> () |
410 | 410 | end; |
411 | 411 | Record field_glob |
15 | 15 | open Libnames |
16 | 16 | |
17 | 17 | let msgnl = Pp.msgnl |
18 | ||
19 | let do_observe () = | |
20 | Tacinterp.get_debug () <> Tactic_debug.DebugOff | |
21 | ||
18 | ||
22 | 19 | |
23 | 20 | let observe strm = |
24 | 21 | if do_observe () |
172 | 169 | then isConstruct (fst (destApp t)) |
173 | 170 | else false |
174 | 171 | |
175 | ||
176 | let nf_betaiotazeta = Reductionops.local_strong Reductionops.whd_betaiotazeta | |
177 | ||
172 | let nf_betaiotazeta = (* Reductionops.local_strong Reductionops.whd_betaiotazeta *) | |
173 | let clos_norm_flags flgs env sigma t = | |
174 | Closure.norm_val (Closure.create_clos_infos flgs env) (Closure.inject (Reductionops.nf_evar sigma t)) in | |
175 | clos_norm_flags Closure.betaiotazeta Environ.empty_env Evd.empty | |
176 | ||
178 | 177 | |
179 | 178 | let change_eq env sigma hyp_id (context:Sign.rel_context) x t end_of_type = |
180 | 179 | let nochange msg = |
230 | 229 | end_of_type_with_pop |
231 | 230 | sub'' |
232 | 231 | in |
233 | (* let new_end_of_type = *) | |
234 | (* Intmap.fold *) | |
235 | (* (fun i t end_of_type -> lift 1 (substnl [t] (i-1) end_of_type)) *) | |
236 | (* sub *) | |
237 | (* end_of_type_with_pop *) | |
238 | (* in *) | |
239 | 232 | let old_context_length = List.length context + 1 in |
240 | 233 | let witness_fun = |
241 | 234 | mkLetIn(Anonymous,make_refl_eq t1_typ t1,t, |
555 | 548 | g |
556 | 549 | |
557 | 550 | |
551 | let my_orelse tac1 tac2 g = | |
552 | try | |
553 | tac1 g | |
554 | with e -> | |
555 | (* observe (str "using snd tac since : " ++ Cerrors.explain_exn e); *) | |
556 | tac2 g | |
557 | ||
558 | 558 | let instanciate_hyps_with_args (do_prove:identifier list -> tactic) hyps args_id = |
559 | 559 | let args = Array.of_list (List.map mkVar args_id) in |
560 | 560 | let instanciate_one_hyp hid = |
561 | tclORELSE | |
561 | my_orelse | |
562 | 562 | ( (* we instanciate the hyp if possible *) |
563 | 563 | fun g -> |
564 | 564 | let prov_hid = pf_get_new_id hid g in |
747 | 747 | (build_proof_aux do_finalize dyn_infos) g |
748 | 748 | and build_proof_args do_finalize dyn_infos (* f_args' args *) :tactic = |
749 | 749 | fun g -> |
750 | (* if Tacinterp.get_debug () <> Tactic_debug.DebugOff *) | |
751 | (* then msgnl (str "build_proof_args with " ++ *) | |
752 | (* pr_lconstr_env (pf_env g) f_args' *) | |
753 | (* ); *) | |
754 | 750 | let (f_args',args) = dyn_infos.info in |
755 | 751 | let tac : tactic = |
756 | 752 | fun g -> |
811 | 807 | types : types; |
812 | 808 | offset : int; |
813 | 809 | nb_realargs : int; |
814 | body_with_param : constr | |
810 | body_with_param : constr; | |
811 | num_in_block : int | |
815 | 812 | } |
816 | 813 | |
817 | 814 | |
837 | 834 | exception Not_Rec |
838 | 835 | |
839 | 836 | let generalize_non_dep hyp g = |
837 | (* observe (str "rec id := " ++ Ppconstr.pr_id hyp); *) | |
840 | 838 | let hyps = [hyp] in |
841 | 839 | let env = Global.env () in |
842 | 840 | let hyp_typ = pf_type_of g (mkVar hyp) in |
843 | 841 | let to_revert,_ = |
844 | Environ. fold_named_context_reverse (fun (clear,keep) (hyp,_,_ as decl) -> | |
842 | Environ.fold_named_context_reverse (fun (clear,keep) (hyp,_,_ as decl) -> | |
845 | 843 | if List.mem hyp hyps |
846 | 844 | or List.exists (occur_var_in_decl env hyp) keep |
847 | 845 | or occur_var env hyp hyp_typ |
852 | 850 | in |
853 | 851 | (* observe (str "to_revert := " ++ prlist_with_sep spc Ppconstr.pr_id to_revert); *) |
854 | 852 | tclTHEN |
855 | (observe_tac "h_generalize" (h_generalize (List.map mkVar to_revert))) | |
853 | (observe_tac "h_generalize" (h_generalize (List.map mkVar to_revert) )) | |
856 | 854 | (observe_tac "thin" (thin to_revert)) |
857 | 855 | g |
858 | 856 | |
863 | 861 | (generalize (List.map mkVar idl)) |
864 | 862 | (thin idl) |
865 | 863 | |
866 | ||
867 | let do_replace params rec_arg_num rev_args_id fun_to_replace body = | |
868 | fun g -> | |
869 | let nb_intro_to_do = nb_prod (pf_concl g) in | |
864 | let generate_equation_lemma fnames f fun_num nb_params nb_args rec_args_num = | |
865 | (* observe (str "nb_args := " ++ str (string_of_int nb_args)); *) | |
866 | (* observe (str "nb_params := " ++ str (string_of_int nb_params)); *) | |
867 | (* observe (str "rec_args_num := " ++ str (string_of_int (rec_args_num + 1) )); *) | |
868 | let f_def = Global.lookup_constant (destConst f) in | |
869 | let eq_lhs = mkApp(f,Array.init (nb_params + nb_args) (fun i -> mkRel(nb_params + nb_args - i))) in | |
870 | let f_body = | |
871 | force (out_some f_def.const_body) | |
872 | in | |
873 | let params,f_body_with_params = decompose_lam_n nb_params f_body in | |
874 | let (_,num),(_,_,bodies) = destFix f_body_with_params in | |
875 | let fnames_with_params = | |
876 | let params = Array.init nb_params (fun i -> mkRel(nb_params - i)) in | |
877 | let fnames = List.rev (Array.to_list (Array.map (fun f -> mkApp(f,params)) fnames)) in | |
878 | fnames | |
879 | in | |
880 | (* observe (str "fnames_with_params " ++ prlist_with_sep fnl pr_lconstr fnames_with_params); *) | |
881 | (* observe (str "body " ++ pr_lconstr bodies.(num)); *) | |
882 | let f_body_with_params_and_other_fun = substl fnames_with_params bodies.(num) in | |
883 | (* observe (str "f_body_with_params_and_other_fun " ++ pr_lconstr f_body_with_params_and_other_fun); *) | |
884 | let eq_rhs = nf_betaiotazeta (mkApp(compose_lam params f_body_with_params_and_other_fun,Array.init (nb_params + nb_args) (fun i -> mkRel(nb_params + nb_args - i)))) in | |
885 | (* observe (str "eq_rhs " ++ pr_lconstr eq_rhs); *) | |
886 | let type_ctxt,type_of_f = Sign.decompose_prod_n_assum (nb_params + nb_args) f_def.const_type in | |
887 | let eqn = mkApp(Lazy.force eq,[|type_of_f;eq_lhs;eq_rhs|]) in | |
888 | let lemma_type = it_mkProd_or_LetIn ~init:eqn type_ctxt in | |
889 | let f_id = id_of_label (con_label (destConst f)) in | |
890 | let prove_replacement = | |
891 | tclTHENSEQ | |
892 | [ | |
893 | tclDO (nb_params + rec_args_num + 1) intro; | |
894 | observe_tac "" (fun g -> | |
895 | let rec_id = pf_nth_hyp_id g 1 in | |
896 | tclTHENSEQ | |
897 | [observe_tac "generalize_non_dep in generate_equation_lemma" (generalize_non_dep rec_id); | |
898 | observe_tac "h_case" (h_case(mkVar rec_id,Rawterm.NoBindings)); | |
899 | intros_reflexivity] g | |
900 | ) | |
901 | ] | |
902 | in | |
903 | Command.start_proof | |
904 | (*i The next call to mk_equation_id is valid since we are constructing the lemma | |
905 | Ensures by: obvious | |
906 | i*) | |
907 | (mk_equation_id f_id) | |
908 | (Decl_kinds.Global,(Decl_kinds.Proof Decl_kinds.Theorem)) | |
909 | lemma_type | |
910 | (fun _ _ -> ()); | |
911 | Pfedit.by (prove_replacement); | |
912 | Command.save_named false | |
913 | ||
914 | ||
915 | ||
916 | ||
917 | let do_replace params rec_arg_num rev_args_id f fun_num all_funs g = | |
918 | let equation_lemma = | |
919 | try | |
920 | let finfos = find_Function_infos (destConst f) in | |
921 | mkConst (out_some finfos.equation_lemma) | |
922 | with (Not_found | Failure "out_some" as e) -> | |
923 | let f_id = id_of_label (con_label (destConst f)) in | |
924 | (*i The next call to mk_equation_id is valid since we will construct the lemma | |
925 | Ensures by: obvious | |
926 | i*) | |
927 | let equation_lemma_id = (mk_equation_id f_id) in | |
928 | generate_equation_lemma all_funs f fun_num (List.length params) (List.length rev_args_id) rec_arg_num; | |
929 | let _ = | |
930 | match e with | |
931 | | Failure "out_some" -> | |
932 | let finfos = find_Function_infos (destConst f) in | |
933 | update_Function | |
934 | {finfos with | |
935 | equation_lemma = Some (match Nametab.locate (make_short_qualid equation_lemma_id) with | |
936 | ConstRef c -> c | |
937 | | _ -> Util.anomaly "Not a constant" | |
938 | ) | |
939 | } | |
940 | | _ -> () | |
941 | ||
942 | in | |
943 | Tacinterp.constr_of_id (pf_env g) equation_lemma_id | |
944 | in | |
945 | let nb_intro_to_do = nb_prod (pf_concl g) in | |
870 | 946 | tclTHEN |
871 | 947 | (tclDO nb_intro_to_do intro) |
872 | 948 | ( |
873 | 949 | fun g' -> |
874 | 950 | let just_introduced = nLastHyps nb_intro_to_do g' in |
875 | 951 | let just_introduced_id = List.map (fun (id,_,_) -> id) just_introduced in |
876 | let old_rev_args_id = rev_args_id in | |
877 | let rev_args_id = just_introduced_id@rev_args_id in | |
878 | let to_replace = | |
879 | Reductionops.nf_betaiota (substl (List.map mkVar rev_args_id) fun_to_replace ) | |
880 | and by = | |
881 | Reductionops.nf_betaiota (applist(body,List.rev_map mkVar rev_args_id)) | |
882 | in | |
883 | (* observe (str "to_replace := " ++ pr_lconstr_env (pf_env g') to_replace); *) | |
884 | (* observe (str "by := " ++ pr_lconstr_env (pf_env g') by); *) | |
885 | let prove_replacement = | |
886 | let rec_id = List.nth (List.rev old_rev_args_id) (rec_arg_num) in | |
887 | observe_tac "prove_replacement" | |
888 | (tclTHENSEQ | |
889 | [ | |
890 | revert just_introduced_id; | |
891 | keep ((List.map id_of_decl params)@ old_rev_args_id); | |
892 | generalize_non_dep rec_id; | |
893 | observe_tac "h_case" (h_case(mkVar rec_id,Rawterm.NoBindings)); | |
894 | intros_reflexivity | |
895 | ] | |
896 | ) | |
897 | in | |
898 | tclTHENS | |
899 | (observe_tac "replacement" (Equality.replace to_replace by)) | |
900 | [ revert just_introduced_id; | |
901 | tclSOLVE [prove_replacement]] | |
902 | g' | |
952 | tclTHEN (Equality.rewriteLR equation_lemma) (revert just_introduced_id) g' | |
903 | 953 | ) |
904 | 954 | g |
905 | ||
906 | ||
907 | 955 | |
908 | 956 | let prove_princ_for_struct interactive_proof fun_num fnames all_funs _nparams : tactic = |
909 | 957 | fun g -> |
1010 | 1058 | nb_realargs = |
1011 | 1059 | List.length |
1012 | 1060 | (fst (decompose_lam bodies.(i))) - fix_offset; |
1013 | body_with_param = bodies_with_all_params.(i) | |
1061 | body_with_param = bodies_with_all_params.(i); | |
1062 | num_in_block = i | |
1014 | 1063 | } |
1015 | 1064 | ) |
1016 | 1065 | typess |
1026 | 1075 | let app_f = mkApp(f,first_args) in |
1027 | 1076 | let pte_args = (Array.to_list first_args)@[app_f] in |
1028 | 1077 | let app_pte = applist(mkVar (Nameops.out_name pte),pte_args) in |
1029 | let body_with_param = | |
1078 | let body_with_param,num = | |
1030 | 1079 | let body = get_body fnames.(i) in |
1031 | 1080 | let body_with_full_params = |
1032 | 1081 | Reductionops.nf_betaiota ( |
1042 | 1091 | (Array.to_list all_funs_with_full_params)) |
1043 | 1092 | bs.(num), |
1044 | 1093 | List.rev_map var_of_decl princ_params)) |
1045 | ) | |
1094 | ),num | |
1046 | 1095 | | _ -> error "Not a mutual block" |
1047 | 1096 | in |
1048 | 1097 | let info = |
1049 | 1098 | {infos with |
1050 | 1099 | types = compose_prod type_args app_pte; |
1051 | body_with_param = body_with_param | |
1100 | body_with_param = body_with_param; | |
1101 | num_in_block = num | |
1052 | 1102 | } |
1053 | 1103 | in |
1054 | 1104 | (* observe (str "binding " ++ Ppconstr.pr_id (Nameops.out_name pte) ++ *) |
1117 | 1167 | tclTHENSEQ |
1118 | 1168 | [ |
1119 | 1169 | observe_tac "do_replace" |
1120 | (do_replace princ_info.params fix_info.idx args_id | |
1121 | (List.hd (List.rev pte_args)) fix_body); | |
1170 | (do_replace | |
1171 | full_params | |
1172 | (fix_info.idx + List.length princ_params) | |
1173 | (args_id@(List.map (fun (id,_,_) -> Nameops.out_name id ) princ_params)) | |
1174 | (all_funs.(fix_info.num_in_block)) | |
1175 | fix_info.num_in_block | |
1176 | all_funs | |
1177 | ); | |
1178 | (* observe_tac "do_replace" *) | |
1179 | (* (do_replace princ_info.params fix_info.idx args_id *) | |
1180 | (* (List.hd (List.rev pte_args)) fix_body); *) | |
1122 | 1181 | let do_prove = |
1123 | 1182 | build_proof |
1124 | 1183 | interactive_proof |
1132 | 1191 | nb_rec_hyps = List.length branches |
1133 | 1192 | } |
1134 | 1193 | in |
1135 | clean_goal_with_heq | |
1194 | observe_tac "cleaning" (clean_goal_with_heq | |
1136 | 1195 | (Idmap.map prove_rec_hyp ptes_to_fix) |
1137 | 1196 | do_prove |
1138 | dyn_infos | |
1197 | dyn_infos) | |
1139 | 1198 | in |
1140 | (* observe (str "branches := " ++ *) | |
1141 | (* prlist_with_sep spc (fun decl -> Ppconstr.pr_id (id_of_decl decl)) princ_info.branches); *) | |
1199 | (* observe (str "branches := " ++ *) | |
1200 | (* prlist_with_sep spc (fun decl -> Ppconstr.pr_id (id_of_decl decl)) princ_info.branches ++ fnl () ++ *) | |
1201 | (* str "args := " ++ prlist_with_sep spc Ppconstr.pr_id args_id *) | |
1202 | ||
1203 | (* ); *) | |
1142 | 1204 | observe_tac "instancing" (instanciate_hyps_with_args prove_tac |
1143 | 1205 | (List.rev_map id_of_decl princ_info.branches) |
1144 | 1206 | (List.rev args_id)) |
15 | 15 | Tacmach.tactic |
16 | 16 | |
17 | 17 | |
18 | val is_pte : rel_declaration -> bool | |
19 | val do_observe : unit -> bool | |
18 | (* val is_pte : rel_declaration -> bool *) |
18 | 18 | exception Toberemoved |
19 | 19 | |
20 | 20 | |
21 | ||
22 | ||
21 | let pr_elim_scheme el = | |
22 | let env = Global.env () in | |
23 | let msg = str "params := " ++ Printer.pr_rel_context env el.params in | |
24 | let env = Environ.push_rel_context el.params env in | |
25 | let msg = msg ++ fnl () ++ str "predicates := "++ Printer.pr_rel_context env el.predicates in | |
26 | let env = Environ.push_rel_context el.predicates env in | |
27 | let msg = msg ++ fnl () ++ str "branches := " ++ Printer.pr_rel_context env el.branches in | |
28 | let env = Environ.push_rel_context el.branches env in | |
29 | let msg = msg ++ fnl () ++ str "args := " ++ Printer.pr_rel_context env el.args in | |
30 | let env = Environ.push_rel_context el.args env in | |
31 | msg ++ fnl () ++ str "concl := " ++ pr_lconstr_env env el.concl | |
32 | ||
33 | ||
34 | let observe s = | |
35 | if do_observe () | |
36 | then Pp.msgnl s | |
37 | ||
38 | ||
39 | let pr_elim_scheme el = | |
40 | let env = Global.env () in | |
41 | let msg = str "params := " ++ Printer.pr_rel_context env el.params in | |
42 | let env = Environ.push_rel_context el.params env in | |
43 | let msg = msg ++ fnl () ++ str "predicates := "++ Printer.pr_rel_context env el.predicates in | |
44 | let env = Environ.push_rel_context el.predicates env in | |
45 | let msg = msg ++ fnl () ++ str "branches := " ++ Printer.pr_rel_context env el.branches in | |
46 | let env = Environ.push_rel_context el.branches env in | |
47 | let msg = msg ++ fnl () ++ str "args := " ++ Printer.pr_rel_context env el.args in | |
48 | let env = Environ.push_rel_context el.args env in | |
49 | msg ++ fnl () ++ str "concl := " ++ pr_lconstr_env env el.concl | |
50 | ||
51 | ||
52 | let observe s = | |
53 | if do_observe () | |
54 | then Pp.msgnl s | |
23 | 55 | |
24 | 56 | (* |
25 | 57 | Transform an inductive induction principle into |
28 | 60 | let compute_new_princ_type_from_rel rel_to_fun sorts princ_type = |
29 | 61 | let princ_type_info = compute_elim_sig princ_type in |
30 | 62 | let env = Global.env () in |
63 | let env_with_params = Environ.push_rel_context princ_type_info.params env in | |
64 | let tbl = Hashtbl.create 792 in | |
65 | let rec change_predicates_names (avoid:identifier list) (predicates:Sign.rel_context) : Sign.rel_context = | |
66 | match predicates with | |
67 | | [] -> [] | |
68 | |(Name x,v,t)::predicates -> | |
69 | let id = Nameops.next_ident_away x avoid in | |
70 | Hashtbl.add tbl id x; | |
71 | (Name id,v,t)::(change_predicates_names (id::avoid) predicates) | |
72 | | (Anonymous,_,_)::_ -> anomaly "Anonymous property binder " | |
73 | in | |
74 | let avoid = (Termops.ids_of_context env_with_params ) in | |
75 | let princ_type_info = | |
76 | { princ_type_info with | |
77 | predicates = change_predicates_names avoid princ_type_info.predicates | |
78 | } | |
79 | in | |
80 | (* observe (str "starting princ_type := " ++ pr_lconstr_env env princ_type); *) | |
81 | (* observe (str "princ_infos : " ++ pr_elim_scheme princ_type_info); *) | |
31 | 82 | let change_predicate_sort i (x,_,t) = |
32 | 83 | let new_sort = sorts.(i) in |
33 | 84 | let args,_ = decompose_prod t in |
36 | 87 | then List.tl args |
37 | 88 | else args |
38 | 89 | in |
39 | x,None,compose_prod real_args (mkSort new_sort) | |
90 | Nameops.out_name x,None,compose_prod real_args (mkSort new_sort) | |
40 | 91 | in |
41 | 92 | let new_predicates = |
42 | 93 | list_map_i |
44 | 95 | 0 |
45 | 96 | princ_type_info.predicates |
46 | 97 | in |
47 | let env_with_params_and_predicates = | |
48 | Environ.push_rel_context | |
49 | new_predicates | |
50 | (Environ.push_rel_context | |
51 | princ_type_info.params | |
52 | env | |
53 | ) | |
54 | in | |
98 | let env_with_params_and_predicates = List.fold_right Environ.push_named new_predicates env_with_params in | |
55 | 99 | let rel_as_kn = |
56 | 100 | fst (match princ_type_info.indref with |
57 | 101 | | Some (Libnames.IndRef ind) -> ind |
58 | | _ -> failwith "Not a valid predicate" | |
102 | | _ -> error "Not a valid predicate" | |
59 | 103 | ) |
104 | in | |
105 | let ptes_vars = List.map (fun (id,_,_) -> id) new_predicates in | |
106 | let is_pte = | |
107 | let set = List.fold_right Idset.add ptes_vars Idset.empty in | |
108 | fun t -> | |
109 | match kind_of_term t with | |
110 | | Var id -> Idset.mem id set | |
111 | | _ -> false | |
60 | 112 | in |
61 | 113 | let pre_princ = |
62 | 114 | it_mkProd_or_LetIn |
71 | 123 | ) |
72 | 124 | princ_type_info.branches |
73 | 125 | in |
126 | let pre_princ = substl (List.map mkVar ptes_vars) pre_princ in | |
74 | 127 | let is_dom c = |
75 | 128 | match kind_of_term c with |
76 | 129 | | Ind((u,_)) -> u = rel_as_kn |
107 | 160 | | Prod(x,t,b) -> |
108 | 161 | compute_new_princ_type_for_binder remove mkProd env x t b |
109 | 162 | | Lambda(x,t,b) -> |
110 | compute_new_princ_type_for_binder remove mkLambda env x t b | |
163 | compute_new_princ_type_for_binder remove mkLambda env x t b | |
111 | 164 | | Ind _ | Construct _ when is_dom pre_princ -> raise Toberemoved |
112 | 165 | | App(f,args) when is_dom f -> |
113 | 166 | let var_to_be_removed = destRel (array_last args) in |
114 | 167 | let num = get_fun_num f in |
115 | 168 | raise (Toberemoved_with_rel (var_to_be_removed,mk_replacement pre_princ num args)) |
116 | 169 | | App(f,args) -> |
117 | let is_pte = | |
118 | match kind_of_term f with | |
119 | | Rel n -> | |
120 | is_pte (Environ.lookup_rel n env) | |
121 | | _ -> false | |
122 | in | |
123 | 170 | let args = |
124 | if is_pte && remove | |
171 | if is_pte f && remove | |
125 | 172 | then array_get_start args |
126 | 173 | else args |
127 | 174 | in |
137 | 184 | compute_new_princ_type_for_letin remove env x v t b |
138 | 185 | | _ -> pre_princ,[] |
139 | 186 | in |
140 | (* observennl ( *) | |
141 | (* match kind_of_term pre_princ with *) | |
142 | (* | Prod _ -> *) | |
143 | (* str "compute_new_princ_type for "++ *) | |
187 | (* let _ = match kind_of_term pre_princ with *) | |
188 | (* | Prod _ -> *) | |
189 | (* observe(str "compute_new_princ_type for "++ *) | |
144 | 190 | (* pr_lconstr_env env pre_princ ++ *) |
145 | 191 | (* str" is "++ *) |
146 | (* pr_lconstr_env env new_princ_type ++ fnl () *) | |
147 | (* | _ -> str "" *) | |
148 | (* ); *) | |
192 | (* pr_lconstr_env env new_princ_type ++ fnl ()) *) | |
193 | (* | _ -> () in *) | |
149 | 194 | res |
150 | 195 | |
151 | 196 | and compute_new_princ_type_for_binder remove bind_fun env x t b = |
155 | 200 | let new_x : name = get_name (ids_of_context env) x in |
156 | 201 | let new_env = Environ.push_rel (x,None,t) env in |
157 | 202 | let new_b,binders_to_remove_from_b = compute_new_princ_type remove new_env b in |
158 | if List.exists (eq_constr (mkRel 1)) binders_to_remove_from_b | |
159 | then (pop new_b),filter_map (eq_constr (mkRel 1)) pop binders_to_remove_from_b | |
160 | else | |
161 | ( | |
162 | bind_fun(new_x,new_t,new_b), | |
163 | list_union_eq | |
164 | eq_constr | |
165 | binders_to_remove_from_t | |
166 | (List.map pop binders_to_remove_from_b) | |
167 | ) | |
168 | ||
169 | with | |
170 | | Toberemoved -> | |
171 | (* msgnl (str "Decl of "++Ppconstr.pr_name x ++ str " is removed "); *) | |
172 | let new_b,binders_to_remove_from_b = compute_new_princ_type remove env (substnl [dummy_var] 1 b) in | |
203 | if List.exists (eq_constr (mkRel 1)) binders_to_remove_from_b | |
204 | then (pop new_b),filter_map (eq_constr (mkRel 1)) pop binders_to_remove_from_b | |
205 | else | |
206 | ( | |
207 | bind_fun(new_x,new_t,new_b), | |
208 | list_union_eq | |
209 | eq_constr | |
210 | binders_to_remove_from_t | |
211 | (List.map pop binders_to_remove_from_b) | |
212 | ) | |
213 | ||
214 | with | |
215 | | Toberemoved -> | |
216 | (* observe (str "Decl of "++Ppconstr.pr_name x ++ str " is removed "); *) | |
217 | let new_b,binders_to_remove_from_b = compute_new_princ_type remove env (substnl [dummy_var] 1 b) in | |
173 | 218 | new_b, List.map pop binders_to_remove_from_b |
174 | 219 | | Toberemoved_with_rel (n,c) -> |
175 | (* msgnl (str "Decl of "++Ppconstr.pr_name x ++ str " is removed "); *) | |
176 | let new_b,binders_to_remove_from_b = compute_new_princ_type remove env (substnl [c] n b) in | |
220 | (* observe (str "Decl of "++Ppconstr.pr_name x ++ str " is removed "); *) | |
221 | let new_b,binders_to_remove_from_b = compute_new_princ_type remove env (substnl [c] n b) in | |
177 | 222 | new_b, list_add_set_eq eq_constr (mkRel n) (List.map pop binders_to_remove_from_b) |
178 | 223 | end |
179 | 224 | and compute_new_princ_type_for_letin remove env x v t b = |
183 | 228 | let new_v,binders_to_remove_from_v = compute_new_princ_type remove env v in |
184 | 229 | let new_x : name = get_name (ids_of_context env) x in |
185 | 230 | let new_env = Environ.push_rel (x,Some v,t) env in |
186 | let new_b,binders_to_remove_from_b = compute_new_princ_type remove new_env b in | |
231 | let new_b,binders_to_remove_from_b = compute_new_princ_type remove new_env b in | |
187 | 232 | if List.exists (eq_constr (mkRel 1)) binders_to_remove_from_b |
188 | 233 | then (pop new_b),filter_map (eq_constr (mkRel 1)) pop binders_to_remove_from_b |
189 | 234 | else |
197 | 242 | |
198 | 243 | with |
199 | 244 | | Toberemoved -> |
200 | (* msgnl (str "Decl of "++Ppconstr.pr_name x ++ str " is removed "); *) | |
245 | (* observe (str "Decl of "++Ppconstr.pr_name x ++ str " is removed "); *) | |
201 | 246 | let new_b,binders_to_remove_from_b = compute_new_princ_type remove env (substnl [dummy_var] 1 b) in |
202 | 247 | new_b, List.map pop binders_to_remove_from_b |
203 | 248 | | Toberemoved_with_rel (n,c) -> |
204 | (* msgnl (str "Decl of "++Ppconstr.pr_name x ++ str " is removed "); *) | |
249 | (* observe (str "Decl of "++Ppconstr.pr_name x ++ str " is removed "); *) | |
205 | 250 | let new_b,binders_to_remove_from_b = compute_new_princ_type remove env (substnl [c] n b) in |
206 | 251 | new_b, list_add_set_eq eq_constr (mkRel n) (List.map pop binders_to_remove_from_b) |
207 | 252 | end |
208 | 253 | and compute_new_princ_type_with_acc remove env e (c_acc,to_remove_acc) = |
209 | let new_e,to_remove_from_e = compute_new_princ_type remove env e | |
210 | in | |
211 | new_e::c_acc,list_union_eq eq_constr to_remove_from_e to_remove_acc | |
254 | let new_e,to_remove_from_e = compute_new_princ_type remove env e | |
255 | in | |
256 | new_e::c_acc,list_union_eq eq_constr to_remove_from_e to_remove_acc | |
212 | 257 | in |
213 | 258 | (* observe (str "Computing new principe from " ++ pr_lconstr_env env_with_params_and_predicates pre_princ); *) |
214 | 259 | let pre_res,_ = |
215 | compute_new_princ_type princ_type_info.indarg_in_concl env_with_params_and_predicates pre_princ in | |
260 | compute_new_princ_type princ_type_info.indarg_in_concl env_with_params_and_predicates pre_princ | |
261 | in | |
262 | let pre_res = | |
263 | replace_vars | |
264 | (list_map_i (fun i id -> (id, mkRel i)) 1 ptes_vars) | |
265 | (lift (List.length ptes_vars) pre_res) | |
266 | in | |
216 | 267 | it_mkProd_or_LetIn |
217 | ~init:(it_mkProd_or_LetIn ~init:pre_res new_predicates) | |
268 | ~init:(it_mkProd_or_LetIn | |
269 | ~init:pre_res (List.map (fun (id,t,b) -> Name(Hashtbl.find tbl id), t,b) | |
270 | new_predicates) | |
271 | ) | |
218 | 272 | princ_type_info.params |
219 | 273 | |
220 | 274 | |
245 | 299 | let pp_dur time time' = |
246 | 300 | str (string_of_float (System.time_difference time time')) |
247 | 301 | |
248 | (* End of things to be removed latter : just here to compare | |
249 | saving proof with and without normalizing the proof | |
250 | *) | |
251 | ||
252 | let qed () = Command.save_named true | |
302 | (* let qed () = save_named true *) | |
253 | 303 | let defined () = Command.save_named false |
254 | let generate_functional_principle | |
304 | ||
305 | ||
306 | ||
307 | ||
308 | ||
309 | let build_functional_principle interactive_proof old_princ_type sorts funs i proof_tac hook = | |
310 | (* First we get the type of the old graph principle *) | |
311 | let mutr_nparams = (compute_elim_sig old_princ_type).nparams in | |
312 | (* let time1 = System.get_time () in *) | |
313 | let new_principle_type = | |
314 | compute_new_princ_type_from_rel | |
315 | (Array.map mkConst funs) | |
316 | sorts | |
317 | old_princ_type | |
318 | in | |
319 | (* let time2 = System.get_time () in *) | |
320 | (* Pp.msgnl (str "computing principle type := " ++ System.fmt_time_difference time1 time2); *) | |
321 | (* observe (str "new_principle_type : " ++ pr_lconstr new_principle_type); *) | |
322 | let new_princ_name = | |
323 | next_global_ident_away true (id_of_string "___________princ_________") [] | |
324 | in | |
325 | begin | |
326 | Command.start_proof | |
327 | new_princ_name | |
328 | (Decl_kinds.Global,(Decl_kinds.Proof Decl_kinds.Theorem)) | |
329 | new_principle_type | |
330 | (hook new_principle_type) | |
331 | ; | |
332 | (* let _tim1 = System.get_time () in *) | |
333 | Pfedit.by (proof_tac (Array.map mkConst funs) mutr_nparams); | |
334 | (* let _tim2 = System.get_time () in *) | |
335 | (* begin *) | |
336 | (* let dur1 = System.time_difference tim1 tim2 in *) | |
337 | (* Pp.msgnl (str ("Time to compute proof: ") ++ str (string_of_float dur1)); *) | |
338 | (* end; *) | |
339 | get_proof_clean true | |
340 | end | |
341 | ||
342 | ||
343 | ||
344 | let generate_functional_principle | |
255 | 345 | interactive_proof |
256 | old_princ_type sorts new_princ_name funs i proof_tac | |
257 | = | |
258 | let f = funs.(i) in | |
259 | let type_sort = Termops.new_sort_in_family InType in | |
260 | let new_sorts = | |
261 | match sorts with | |
346 | old_princ_type sorts new_princ_name funs i proof_tac | |
347 | = | |
348 | let f = funs.(i) in | |
349 | let type_sort = Termops.new_sort_in_family InType in | |
350 | let new_sorts = | |
351 | match sorts with | |
262 | 352 | | None -> Array.make (Array.length funs) (type_sort) |
263 | 353 | | Some a -> a |
264 | 354 | in |
265 | (* First we get the type of the old graph principle *) | |
266 | let mutr_nparams = (compute_elim_sig old_princ_type).nparams in | |
267 | (* First we get the type of the old graph principle *) | |
268 | let new_principle_type = | |
269 | compute_new_princ_type_from_rel | |
270 | (Array.map mkConst funs) | |
271 | new_sorts | |
272 | old_princ_type | |
273 | in | |
274 | (* observe (str "new_principle_type : " ++ pr_lconstr new_principle_type); *) | |
275 | 355 | let base_new_princ_name,new_princ_name = |
276 | 356 | match new_princ_name with |
277 | 357 | | Some (id) -> id,id |
279 | 359 | let id_of_f = id_of_label (con_label f) in |
280 | 360 | id_of_f,Indrec.make_elimination_ident id_of_f (family_of_sort type_sort) |
281 | 361 | in |
282 | let names = ref [new_princ_name] in | |
283 | let hook _ _ = | |
284 | if sorts = None | |
362 | let names = ref [new_princ_name] in | |
363 | let hook new_principle_type _ _ = | |
364 | if sorts = None | |
285 | 365 | then |
286 | (* let id_of_f = id_of_label (con_label f) in *) | |
287 | let register_with_sort fam_sort = | |
288 | let s = Termops.new_sort_in_family fam_sort in | |
289 | let name = Indrec.make_elimination_ident base_new_princ_name fam_sort in | |
290 | let value = | |
291 | change_property_sort s new_principle_type new_princ_name | |
366 | (* let id_of_f = id_of_label (con_label f) in *) | |
367 | let register_with_sort fam_sort = | |
368 | let s = Termops.new_sort_in_family fam_sort in | |
369 | let name = Indrec.make_elimination_ident base_new_princ_name fam_sort in | |
370 | let value = change_property_sort s new_principle_type new_princ_name in | |
371 | (* Pp.msgnl (str "new principle := " ++ pr_lconstr value); *) | |
372 | let ce = | |
373 | { const_entry_body = value; | |
374 | const_entry_type = None; | |
375 | const_entry_opaque = false; | |
376 | const_entry_boxed = Options.boxed_definitions() | |
377 | } | |
378 | in | |
379 | ignore( | |
380 | Declare.declare_constant | |
381 | name | |
382 | (Entries.DefinitionEntry ce, | |
383 | Decl_kinds.IsDefinition (Decl_kinds.Scheme) | |
384 | ) | |
385 | ); | |
386 | names := name :: !names | |
292 | 387 | in |
293 | (* Pp.msgnl (str "new principle := " ++ pr_lconstr value); *) | |
294 | let ce = | |
295 | { const_entry_body = value; | |
296 | const_entry_type = None; | |
297 | const_entry_opaque = false; | |
298 | const_entry_boxed = Options.boxed_definitions() | |
299 | } | |
300 | in | |
301 | ignore( | |
302 | Declare.declare_constant | |
303 | name | |
304 | (Entries.DefinitionEntry ce, | |
305 | Decl_kinds.IsDefinition (Decl_kinds.Scheme) | |
306 | ) | |
307 | ); | |
308 | names := name :: !names | |
309 | in | |
310 | register_with_sort InProp; | |
311 | register_with_sort InSet | |
312 | in | |
313 | begin | |
314 | Command.start_proof | |
315 | new_princ_name | |
316 | (Decl_kinds.Global,(Decl_kinds.Proof Decl_kinds.Theorem)) | |
317 | new_principle_type | |
318 | hook | |
319 | ; | |
320 | try | |
321 | let _tim1 = System.get_time () in | |
322 | Pfedit.by (proof_tac (Array.map mkConst funs) mutr_nparams); | |
323 | let _tim2 = System.get_time () in | |
324 | (* begin *) | |
325 | (* let dur1 = System.time_difference tim1 tim2 in *) | |
326 | (* Pp.msgnl (str ("Time to compute proof: ") ++ str (string_of_float dur1)); *) | |
327 | (* end; *) | |
328 | let do_save = not (do_observe ()) && not interactive_proof in | |
329 | let _ = | |
330 | try | |
331 | (* Vernacentries.show_script (); *) | |
332 | Options.silently defined (); | |
333 | let _dur2 = System.time_difference _tim2 (System.get_time ()) in | |
334 | (* Pp.msgnl (str ("Time to check proof: ") ++ str (string_of_float dur2)); *) | |
335 | Options.if_verbose | |
336 | (fun () -> | |
337 | Pp.msgnl ( | |
338 | prlist_with_sep | |
339 | (fun () -> str" is defined " ++ fnl ()) | |
340 | Ppconstr.pr_id | |
341 | (List.rev !names) ++ str" is defined " | |
342 | ) | |
343 | ) | |
344 | () | |
345 | with e when do_save -> | |
346 | msg_warning | |
347 | ( | |
348 | Cerrors.explain_exn e | |
349 | ); | |
350 | if not (do_observe ()) | |
351 | then begin Vernacentries.interp (Vernacexpr.VernacAbort None);raise e end | |
352 | in | |
353 | () | |
354 | ||
355 | (* let tim3 = Sys.time () in *) | |
356 | (* Pp.msgnl (str ("Time to save proof: ") ++ str (string_of_float (tim3 -. tim2))); *) | |
357 | ||
358 | with | |
359 | | e -> | |
360 | msg_warning | |
361 | ( | |
362 | Cerrors.explain_exn e | |
363 | ); | |
364 | if not ( do_observe ()) | |
365 | then begin Vernacentries.interp (Vernacexpr.VernacAbort None);raise e end | |
366 | end | |
367 | ||
368 | ||
388 | register_with_sort InProp; | |
389 | register_with_sort InSet | |
390 | in | |
391 | let (id,(entry,g_kind,hook)) = | |
392 | build_functional_principle interactive_proof old_princ_type new_sorts funs i proof_tac hook | |
393 | in | |
394 | save false new_princ_name entry g_kind hook | |
395 | (* defined () *) | |
369 | 396 | |
370 | 397 | |
371 | 398 | exception Not_Rec |
440 | 467 | l_const |
441 | 468 | |
442 | 469 | exception No_graph_found |
443 | ||
444 | let make_scheme fas = | |
470 | exception Found_type of int | |
471 | ||
472 | let make_scheme (fas : (constant*Rawterm.rawsort) list) : Entries.definition_entry list = | |
445 | 473 | let env = Global.env () |
446 | 474 | and sigma = Evd.empty in |
447 | let id_to_constr id = | |
448 | Tacinterp.constr_of_id env id | |
449 | in | |
450 | let funs = | |
451 | List.map | |
452 | (fun (_,f,_) -> | |
453 | try id_to_constr f | |
454 | with Not_found -> | |
455 | Util.error ("Cannot find "^ string_of_id f) | |
456 | ) | |
457 | fas | |
458 | in | |
459 | let first_fun = destConst (List.hd funs) in | |
460 | let funs_mp,funs_dp,first_fun_id = Names.repr_con first_fun in | |
461 | let first_fun_rel_id = mk_rel_id (id_of_label first_fun_id) in | |
475 | let funs = List.map fst fas in | |
476 | let first_fun = List.hd funs in | |
477 | ||
478 | ||
479 | let funs_mp,funs_dp,_ = Names.repr_con first_fun in | |
462 | 480 | let first_fun_kn = |
463 | 481 | try |
464 | (* Fixme: take into account funs_mp and funs_dp *) | |
465 | fst (destInd (id_to_constr first_fun_rel_id)) | |
466 | with Not_found -> raise No_graph_found | |
482 | fst (find_Function_infos first_fun).graph_ind | |
483 | with Not_found -> raise No_graph_found | |
467 | 484 | in |
468 | 485 | let this_block_funs_indexes = get_funs_constant funs_mp funs_dp first_fun in |
469 | 486 | let this_block_funs = Array.map fst this_block_funs_indexes in |
471 | 488 | let funs_indexes = |
472 | 489 | let this_block_funs_indexes = Array.to_list this_block_funs_indexes in |
473 | 490 | List.map |
474 | (function const -> List.assoc (destConst const) this_block_funs_indexes) | |
491 | (function const -> List.assoc const this_block_funs_indexes) | |
475 | 492 | funs |
476 | 493 | in |
477 | 494 | let ind_list = |
483 | 500 | ) |
484 | 501 | funs_indexes |
485 | 502 | in |
486 | let l_schemes = List.map (Typing.type_of env sigma ) (Indrec.build_mutual_indrec env sigma ind_list) in | |
503 | let l_schemes = | |
504 | List.map | |
505 | (Typing.type_of env sigma) | |
506 | (Indrec.build_mutual_indrec env sigma ind_list) | |
507 | in | |
487 | 508 | let i = ref (-1) in |
488 | 509 | let sorts = |
489 | List.rev_map (fun (_,_,x) -> | |
510 | List.rev_map (fun (_,x) -> | |
490 | 511 | Termops.new_sort_in_family (Pretyping.interp_elimination_sort x) |
491 | 512 | ) |
492 | 513 | fas |
493 | 514 | in |
494 | let princ_names = List.map (fun (x,_,_) -> x) fas in | |
495 | let _ = List.map2 | |
496 | (fun princ_name scheme_type -> | |
497 | incr i; | |
498 | (* observe (str "Generating " ++ Ppconstr.pr_id princ_name ++str " with " ++ *) | |
499 | (* pr_lconstr scheme_type ++ str " and " ++ (fun a -> prlist_with_sep spc (fun c -> pr_lconstr (mkConst c)) (Array.to_list a)) this_block_funs *) | |
500 | (* ); *) | |
501 | generate_functional_principle | |
502 | false | |
503 | scheme_type | |
504 | (Some (Array.of_list sorts)) | |
505 | (Some princ_name) | |
506 | this_block_funs | |
507 | !i | |
508 | (prove_princ_for_struct false !i (Array.of_list (List.map destConst funs))) | |
515 | (* We create the first priciple by tactic *) | |
516 | let first_type,other_princ_types = | |
517 | match l_schemes with | |
518 | s::l_schemes -> s,l_schemes | |
519 | | _ -> anomaly "" | |
520 | in | |
521 | let (_,(const,_,_)) = | |
522 | build_functional_principle false | |
523 | first_type | |
524 | (Array.of_list sorts) | |
525 | this_block_funs | |
526 | 0 | |
527 | (prove_princ_for_struct false 0 (Array.of_list funs)) | |
528 | (fun _ _ _ -> ()) | |
529 | in | |
530 | incr i; | |
531 | (* The others are just deduced *) | |
532 | if other_princ_types = [] | |
533 | then | |
534 | [const] | |
535 | else | |
536 | let other_fun_princ_types = | |
537 | let funs = Array.map mkConst this_block_funs in | |
538 | let sorts = Array.of_list sorts in | |
539 | List.map (compute_new_princ_type_from_rel funs sorts) other_princ_types | |
540 | in | |
541 | let first_princ_body,first_princ_type = const.Entries.const_entry_body, const.Entries.const_entry_type in | |
542 | let ctxt,fix = Sign.decompose_lam_assum first_princ_body in (* the principle has for forall ...., fix .*) | |
543 | let (idxs,_),(_,ta,_ as decl) = destFix fix in | |
544 | let other_result = | |
545 | List.map (* we can now compute the other principles *) | |
546 | (fun scheme_type -> | |
547 | incr i; | |
548 | observe (Printer.pr_lconstr scheme_type); | |
549 | let type_concl = snd (Sign.decompose_prod_assum scheme_type) in | |
550 | let applied_f = List.hd (List.rev (snd (decompose_app type_concl))) in | |
551 | let f = fst (decompose_app applied_f) in | |
552 | try (* we search the number of the function in the fix block (name of the function) *) | |
553 | Array.iteri | |
554 | (fun j t -> | |
555 | let t = snd (Sign.decompose_prod_assum t) in | |
556 | let applied_g = List.hd (List.rev (snd (decompose_app t))) in | |
557 | let g = fst (decompose_app applied_g) in | |
558 | if eq_constr f g | |
559 | then raise (Found_type j); | |
560 | observe (Printer.pr_lconstr f ++ str " <> " ++ | |
561 | Printer.pr_lconstr g) | |
562 | ||
563 | ) | |
564 | ta; | |
565 | (* If we reach this point, the two principle are not mutually recursive | |
566 | We fall back to the previous method | |
567 | *) | |
568 | let (_,(const,_,_)) = | |
569 | build_functional_principle | |
570 | false | |
571 | (List.nth other_princ_types (!i - 1)) | |
572 | (Array.of_list sorts) | |
573 | this_block_funs | |
574 | !i | |
575 | (prove_princ_for_struct false !i (Array.of_list funs)) | |
576 | (fun _ _ _ -> ()) | |
577 | in | |
578 | const | |
579 | with Found_type i -> | |
580 | let princ_body = | |
581 | Termops.it_mkLambda_or_LetIn ~init:(mkFix((idxs,i),decl)) ctxt | |
582 | in | |
583 | {const with | |
584 | Entries.const_entry_body = princ_body; | |
585 | Entries.const_entry_type = Some scheme_type | |
586 | } | |
587 | ) | |
588 | other_fun_princ_types | |
589 | in | |
590 | const::other_result | |
591 | ||
592 | let build_scheme fas = | |
593 | (* (fun (f,_) -> *) | |
594 | (* try Libnames.constr_of_global (Nametab.global f) *) | |
595 | (* with Not_found -> *) | |
596 | (* Util.error ("Cannot find "^ Libnames.string_of_reference f) *) | |
597 | (* ) *) | |
598 | (* fas *) | |
599 | ||
600 | let bodies_types = | |
601 | make_scheme | |
602 | (List.map | |
603 | (fun (_,f,sort) -> | |
604 | let f_as_constant = | |
605 | try | |
606 | match Nametab.global f with | |
607 | | Libnames.ConstRef c -> c | |
608 | | _ -> Util.error "Functional Scheme can only be used with functions" | |
609 | with Not_found -> | |
610 | Util.error ("Cannot find "^ Libnames.string_of_reference f) | |
611 | in | |
612 | (f_as_constant,sort) | |
613 | ) | |
614 | fas | |
615 | ) | |
616 | in | |
617 | List.iter2 | |
618 | (fun (princ_id,_,_) def_entry -> | |
619 | ignore (Declare.declare_constant | |
620 | princ_id | |
621 | (Entries.DefinitionEntry def_entry,Decl_kinds.IsProof Decl_kinds.Theorem)); | |
622 | Options.if_verbose (fun id -> Pp.msgnl (Ppconstr.pr_id id ++ str " is defined")) princ_id | |
509 | 623 | ) |
510 | princ_names | |
511 | l_schemes | |
512 | in | |
513 | () | |
514 | ||
515 | let make_case_scheme fa = | |
624 | fas | |
625 | bodies_types | |
626 | ||
627 | ||
628 | ||
629 | let build_case_scheme fa = | |
516 | 630 | let env = Global.env () |
517 | 631 | and sigma = Evd.empty in |
518 | let id_to_constr id = | |
519 | Tacinterp.constr_of_id env id | |
520 | in | |
521 | let funs = (fun (_,f,_) -> id_to_constr f) fa in | |
632 | (* let id_to_constr id = *) | |
633 | (* Tacinterp.constr_of_id env id *) | |
634 | (* in *) | |
635 | let funs = (fun (_,f,_) -> | |
636 | try Libnames.constr_of_global (Nametab.global f) | |
637 | with Not_found -> | |
638 | Util.error ("Cannot find "^ Libnames.string_of_reference f)) fa in | |
522 | 639 | let first_fun = destConst funs in |
523 | let funs_mp,funs_dp,first_fun_id = Names.repr_con first_fun in | |
524 | let first_fun_rel_id = mk_rel_id (id_of_label first_fun_id) in | |
525 | let first_fun_kn = | |
526 | (* Fixme: take into accour funs_mp and funs_dp *) | |
527 | fst (destInd (id_to_constr first_fun_rel_id)) | |
528 | in | |
640 | ||
641 | let funs_mp,funs_dp,_ = Names.repr_con first_fun in | |
642 | let first_fun_kn = try fst (find_Function_infos first_fun).graph_ind with Not_found -> raise No_graph_found in | |
643 | ||
644 | ||
645 | ||
529 | 646 | let this_block_funs_indexes = get_funs_constant funs_mp funs_dp first_fun in |
530 | 647 | let this_block_funs = Array.map fst this_block_funs_indexes in |
531 | 648 | let prop_sort = InProp in |
0 | 0 | open Names |
1 | 1 | open Term |
2 | ||
3 | ||
2 | 4 | val generate_functional_principle : |
3 | 5 | (* do we accept interactive proving *) |
4 | 6 | bool -> |
18 | 20 | (constr array -> int -> Tacmach.tactic) -> |
19 | 21 | unit |
20 | 22 | |
21 | ||
22 | ||
23 | 23 | val compute_new_princ_type_from_rel : constr array -> sorts array -> |
24 | 24 | types -> types |
25 | 25 | |
26 | 26 | |
27 | 27 | exception No_graph_found |
28 | 28 | |
29 | val make_scheme : (identifier*identifier*Rawterm.rawsort) list -> unit | |
30 | val make_case_scheme : (identifier*identifier*Rawterm.rawsort) -> unit | |
29 | val make_scheme : (constant*Rawterm.rawsort) list -> Entries.definition_entry list | |
30 | ||
31 | val build_scheme : (identifier*Libnames.reference*Rawterm.rawsort) list -> unit | |
32 | val build_case_scheme : (identifier*Libnames.reference*Rawterm.rawsort) -> unit | |
33 |
5 | 5 | open Libnames |
6 | 6 | open Rawterm |
7 | 7 | open Declarations |
8 | ||
9 | let is_rec_info scheme_info = | |
10 | let test_branche min acc (_,_,br) = | |
11 | acc || ( | |
12 | let new_branche = | |
13 | Sign.it_mkProd_or_LetIn mkProp (fst (Sign.decompose_prod_assum br)) in | |
14 | let free_rels_in_br = Termops.free_rels new_branche in | |
15 | let max = min + scheme_info.Tactics.npredicates in | |
16 | Util.Intset.exists (fun i -> i >= min && i< max) free_rels_in_br | |
17 | ) | |
18 | in | |
19 | Util.list_fold_left_i test_branche 1 false (List.rev scheme_info.Tactics.branches) | |
20 | ||
21 | ||
22 | let choose_dest_or_ind scheme_info = | |
23 | if is_rec_info scheme_info | |
24 | then Tactics.new_induct | |
25 | else Tactics.new_destruct | |
26 | ||
27 | ||
28 | let functional_induction with_clean c princl pat = | |
29 | let f,args = decompose_app c in | |
30 | fun g -> | |
31 | let princ,bindings, princ_type = | |
32 | match princl with | |
33 | | None -> (* No principle is given let's find the good one *) | |
34 | begin | |
35 | match kind_of_term f with | |
36 | | Const c' -> | |
37 | let princ_option = | |
38 | let finfo = (* we first try to find out a graph on f *) | |
39 | try find_Function_infos c' | |
40 | with Not_found -> | |
41 | errorlabstrm "" (str "Cannot find induction information on "++Printer.pr_lconstr (mkConst c') ) | |
42 | in | |
43 | match Tacticals.elimination_sort_of_goal g with | |
44 | | InProp -> finfo.prop_lemma | |
45 | | InSet -> finfo.rec_lemma | |
46 | | InType -> finfo.rect_lemma | |
47 | in | |
48 | let princ = (* then we get the principle *) | |
49 | try mkConst (out_some princ_option ) | |
50 | with Failure "out_some" -> | |
51 | (*i If there is not default lemma defined then, we cross our finger and try to | |
52 | find a lemma named f_ind (or f_rec, f_rect) i*) | |
53 | let princ_name = | |
54 | Indrec.make_elimination_ident | |
55 | (id_of_label (con_label c')) | |
56 | (Tacticals.elimination_sort_of_goal g) | |
57 | in | |
58 | try | |
59 | mkConst(const_of_id princ_name ) | |
60 | with Not_found -> (* This one is neither defined ! *) | |
61 | errorlabstrm "" (str "Cannot find induction principle for " | |
62 | ++Printer.pr_lconstr (mkConst c') ) | |
63 | in | |
64 | (princ,Rawterm.NoBindings, Tacmach.pf_type_of g princ) | |
65 | | _ -> raise (UserError("",str "functional induction must be used with a function" )) | |
66 | ||
67 | end | |
68 | | Some ((princ,binding)) -> | |
69 | princ,binding,Tacmach.pf_type_of g princ | |
70 | in | |
71 | let princ_infos = Tactics.compute_elim_sig princ_type in | |
72 | let args_as_induction_constr = | |
73 | let c_list = | |
74 | if princ_infos.Tactics.farg_in_concl | |
75 | then [c] else [] | |
76 | in | |
77 | List.map (fun c -> Tacexpr.ElimOnConstr c) (args@c_list) | |
78 | in | |
79 | let princ' = Some (princ,bindings) in | |
80 | let princ_vars = | |
81 | List.fold_right | |
82 | (fun a acc -> | |
83 | try Idset.add (destVar a) acc | |
84 | with _ -> acc | |
85 | ) | |
86 | args | |
87 | Idset.empty | |
88 | in | |
89 | let old_idl = List.fold_right Idset.add (Tacmach.pf_ids_of_hyps g) Idset.empty in | |
90 | let old_idl = Idset.diff old_idl princ_vars in | |
91 | let subst_and_reduce g = | |
92 | let idl = | |
93 | map_succeed | |
94 | (fun id -> | |
95 | if Idset.mem id old_idl then failwith "subst_and_reduce"; | |
96 | id | |
97 | ) | |
98 | (Tacmach.pf_ids_of_hyps g) | |
99 | in | |
100 | let flag = | |
101 | Rawterm.Cbv | |
102 | {Rawterm.all_flags | |
103 | with Rawterm.rDelta = false; | |
104 | } | |
105 | in | |
106 | if with_clean | |
107 | then | |
108 | Tacticals.tclTHEN | |
109 | (Tacticals.tclMAP (fun id -> Tacticals.tclTRY (Equality.subst [id])) idl ) | |
110 | (Hiddentac.h_reduce flag Tacticals.allClauses) | |
111 | g | |
112 | else Tacticals.tclIDTAC g | |
113 | ||
114 | in | |
115 | Tacticals.tclTHEN | |
116 | (choose_dest_or_ind | |
117 | princ_infos | |
118 | args_as_induction_constr | |
119 | princ' | |
120 | pat) | |
121 | subst_and_reduce | |
122 | g | |
123 | ||
124 | ||
125 | ||
8 | 126 | |
9 | 127 | type annot = |
10 | 128 | Struct of identifier |
119 | 237 | (fun_args,rt') |
120 | 238 | |
121 | 239 | |
240 | let derive_inversion fix_names = | |
241 | try | |
242 | Invfun.derive_correctness | |
243 | Functional_principles_types.make_scheme | |
244 | functional_induction | |
245 | (List.map (fun id -> destConst (Tacinterp.constr_of_id (Global.env ()) id)) fix_names) | |
246 | (*i The next call to mk_rel_id is valid since we have just construct the graph | |
247 | Ensures by : register_built | |
248 | i*) | |
249 | (List.map (fun id -> destInd (Tacinterp.constr_of_id (Global.env ()) (mk_rel_id id))) fix_names) | |
250 | with e -> | |
251 | msg_warning (str "Cannot define correction of function and graph" ++ Cerrors.explain_exn e) | |
252 | ||
122 | 253 | let generate_principle |
123 | 254 | do_built fix_rec_l recdefs interactive_proof parametrize |
124 | (continue_proof : int -> Names.constant array -> Term.constr array -> int -> Tacmach.tactic) = | |
255 | (continue_proof : int -> Names.constant array -> Term.constr array -> int -> Tacmach.tactic) : unit = | |
125 | 256 | let names = List.map (function (name,_,_,_,_) -> name) fix_rec_l in |
126 | 257 | let fun_bodies = List.map2 prepare_body fix_rec_l recdefs in |
127 | 258 | let funs_args = List.map fst fun_bodies in |
132 | 263 | if do_built |
133 | 264 | then |
134 | 265 | begin |
266 | (*i The next call to mk_rel_id is valid since we have just construct the graph | |
267 | Ensures by : do_built | |
268 | i*) | |
135 | 269 | let f_R_mut = Ident (dummy_loc,mk_rel_id (List.nth names 0)) in |
136 | 270 | let ind_kn = |
137 | 271 | fst (locate_with_msg |
148 | 282 | in |
149 | 283 | let funs_kn = Array.of_list (List.map fname_kn fix_rec_l) in |
150 | 284 | let _ = |
151 | Util.list_map_i | |
285 | list_map_i | |
152 | 286 | (fun i x -> |
153 | 287 | let princ = destConst (Indrec.lookup_eliminator (ind_kn,i) (InProp)) in |
154 | 288 | let princ_type = |
166 | 300 | 0 |
167 | 301 | fix_rec_l |
168 | 302 | in |
303 | Array.iter add_Function funs_kn; | |
169 | 304 | () |
170 | 305 | end |
171 | 306 | with e -> |
209 | 344 | if List.length names = 1 then 1 |
210 | 345 | else error "Recursive argument must be specified" |
211 | 346 | | Some wf_arg -> |
212 | Util.list_index (Name wf_arg) names | |
347 | list_index (Name wf_arg) names | |
213 | 348 | in |
214 | 349 | let unbounded_eq = |
215 | 350 | let f_app_args = |
235 | 370 | (generate_correction_proof_wf f_ref tcc_lemma_ref is_mes |
236 | 371 | functional_ref eq_ref rec_arg_num rec_arg_type nb_args relation |
237 | 372 | ); |
238 | Command.save_named true | |
373 | derive_inversion [fname] | |
239 | 374 | with e -> |
240 | 375 | (* No proof done *) |
241 | 376 | () |
332 | 467 | (Topconstr.names_of_local_assums args) |
333 | 468 | in |
334 | 469 | let annot = |
335 | try Some (Util.list_index (Name id) names - 1), Topconstr.CStructRec | |
470 | try Some (list_index (Name id) names - 1), Topconstr.CStructRec | |
336 | 471 | with Not_found -> raise (UserError("",str "Cannot find argument " ++ Ppconstr.pr_id id)) |
337 | 472 | in |
338 | 473 | (name,annot,args,types,body),(None:Vernacexpr.decl_notation) |
339 | 474 | | (name,None,args,types,body),recdef -> |
340 | 475 | let names = (Topconstr.names_of_local_assums args) in |
341 | 476 | if is_one_rec recdef && List.length names > 1 then |
342 | Util.user_err_loc | |
343 | (Util.dummy_loc,"Function", | |
477 | user_err_loc | |
478 | (dummy_loc,"Function", | |
344 | 479 | Pp.str "the recursive argument needs to be specified in Function") |
345 | 480 | else |
346 | 481 | (name,(Some 0, Topconstr.CStructRec),args,types,body),(None:Vernacexpr.decl_notation) |
363 | 498 | interactive_proof |
364 | 499 | true |
365 | 500 | (Functional_principles_proofs.prove_princ_for_struct interactive_proof); |
366 | true | |
367 | ||
501 | if register_built then derive_inversion fix_names; | |
502 | true; | |
368 | 503 | in |
369 | 504 | () |
370 | 505 | |
396 | 531 | | CApp(loc,(pf,b),bl) -> |
397 | 532 | CApp(loc,(pf,add_args id new_args b), List.map (fun (e,o) -> add_args id new_args e,o) bl) |
398 | 533 | | CCases(loc,b_option,cel,cal) -> |
399 | CCases(loc,Util.option_map (add_args id new_args) b_option, | |
400 | List.map (fun (b,(na,b_option)) -> add_args id new_args b,(na,Util.option_map (add_args id new_args) b_option)) cel, | |
534 | CCases(loc,option_map (add_args id new_args) b_option, | |
535 | List.map (fun (b,(na,b_option)) -> add_args id new_args b,(na,option_map (add_args id new_args) b_option)) cel, | |
401 | 536 | List.map (fun (loc,cpl,e) -> (loc,cpl,add_args id new_args e)) cal |
402 | 537 | ) |
403 | 538 | | CLetTuple(loc,nal,(na,b_option),b1,b2) -> |
404 | CLetTuple(loc,nal,(na,Util.option_map (add_args id new_args) b_option), | |
539 | CLetTuple(loc,nal,(na,option_map (add_args id new_args) b_option), | |
405 | 540 | add_args id new_args b1, |
406 | 541 | add_args id new_args b2 |
407 | 542 | ) |
408 | 543 | |
409 | 544 | | CIf(loc,b1,(na,b_option),b2,b3) -> |
410 | 545 | CIf(loc,add_args id new_args b1, |
411 | (na,Util.option_map (add_args id new_args) b_option), | |
546 | (na,option_map (add_args id new_args) b_option), | |
412 | 547 | add_args id new_args b2, |
413 | 548 | add_args id new_args b3 |
414 | 549 | ) |
425 | 560 | |
426 | 561 | |
427 | 562 | |
428 | let make_graph (id:identifier) = | |
429 | let c_body = | |
430 | try | |
431 | let c = const_of_id id in | |
432 | Global.lookup_constant c | |
433 | with Not_found -> | |
434 | raise (UserError ("",str "Cannot find " ++ Ppconstr.pr_id id) ) | |
435 | in | |
436 | ||
563 | let make_graph (f_ref:global_reference) = | |
564 | let c,c_body = | |
565 | match f_ref with | |
566 | | ConstRef c -> | |
567 | begin try c,Global.lookup_constant c | |
568 | with Not_found -> | |
569 | raise (UserError ("",str "Cannot find " ++ Printer.pr_lconstr (mkConst c)) ) | |
570 | end | |
571 | | _ -> raise (UserError ("", str "Not a function reference") ) | |
572 | ||
573 | in | |
437 | 574 | match c_body.const_body with |
438 | 575 | | None -> error "Cannot build a graph over an axiom !" |
439 | 576 | | Some b -> |
493 | 630 | (fun n (nal,t'') -> |
494 | 631 | n+List.length nal) n nal_ta' |
495 | 632 | in |
496 | assert (n'<= n); | |
633 | (* assert (n'<= n); *) | |
497 | 634 | chop_n_arrow (n - n') t' |
498 | 635 | | _ -> anomaly "Not enough products" |
499 | 636 | else t |
510 | 647 | let l = |
511 | 648 | List.map |
512 | 649 | (fun (id,(n,recexp),bl,t,b) -> |
513 | (* let nal = *) | |
514 | (* List.flatten *) | |
515 | (* (List.map *) | |
516 | (* (function *) | |
517 | (* | Topconstr.LocalRawDef (na,_)-> [] *) | |
518 | (* | Topconstr.LocalRawAssum (nal,_) -> nal *) | |
519 | (* ) *) | |
520 | (* (nal_tas@bl) *) | |
521 | (* ) *) | |
522 | (* in *) | |
523 | 650 | let bl' = |
524 | 651 | List.flatten |
525 | 652 | (List.map |
538 | 665 | (List.map |
539 | 666 | (function |
540 | 667 | | Topconstr.LocalRawDef (na,_)-> [] |
541 | | Topconstr.LocalRawAssum (nal,_) -> List.map (fun (loc,n) -> CRef(Libnames.Ident(loc, Nameops.out_name n))) nal | |
668 | | Topconstr.LocalRawAssum (nal,_) -> | |
669 | List.map (fun (loc,n) -> CRef(Libnames.Ident(loc, Nameops.out_name n))) nal | |
542 | 670 | ) |
543 | 671 | nal_tas |
544 | 672 | ) |
550 | 678 | in |
551 | 679 | l |
552 | 680 | | _ -> |
681 | let id = id_of_label (con_label c) in | |
553 | 682 | [(id,None,nal_tas,t,b)] |
554 | 683 | in |
555 | (* List.iter (fun (id,rec_arg,bl,t,b) -> *) | |
556 | (* Pp.msgnl *) | |
557 | (* (Ppconstr.pr_id id ++ *) | |
558 | (* Ppconstr.pr_binders bl ++ *) | |
559 | (* begin match rec_arg with *) | |
560 | (* | Some (Struct id) -> str " { struct " ++ Ppconstr.pr_id id ++ str " }" *) | |
561 | (* | _ -> (mt ()) *) | |
562 | (* end ++ *) | |
563 | (* str " : " ++ Ppconstr.pr_lconstr_expr t ++ *) | |
564 | (* str " := " ++ *) | |
565 | (* Ppconstr.pr_lconstr_expr b *) | |
566 | (* ) *) | |
567 | (* ) *) | |
568 | (* expr_list; *) | |
569 | do_generate_principle false false expr_list | |
684 | do_generate_principle false false expr_list; | |
685 | (* We register the infos *) | |
686 | let mp,dp,_ = repr_con c in | |
687 | List.iter (fun (id,_,_,_,_) -> add_Function (make_con mp dp (label_of_id id))) expr_list | |
688 | ||
689 | ||
570 | 690 | (* let make_graph _ = assert false *) |
571 | 691 | |
572 | 692 | let do_generate_principle = do_generate_principle true |
693 | ||
694 |
4 | 4 | |
5 | 5 | let mk_prefix pre id = id_of_string (pre^(string_of_id id)) |
6 | 6 | let mk_rel_id = mk_prefix "R_" |
7 | let mk_correct_id id = Nameops.add_suffix id "_correct" | |
8 | let mk_complete_id id = Nameops.add_suffix id "_complete" | |
9 | let mk_equation_id id = Nameops.add_suffix id "_equation" | |
7 | 10 | |
8 | 11 | let msgnl m = |
9 | 12 | () |
10 | 13 | |
11 | 14 | let invalid_argument s = raise (Invalid_argument s) |
12 | ||
13 | (* let idtbl = Hashtbl.create 29 *) | |
14 | (* let reset_name () = Hashtbl.clear idtbl *) | |
15 | ||
16 | (* let fresh_id s = *) | |
17 | (* try *) | |
18 | (* let id = Hashtbl.find idtbl s in *) | |
19 | (* incr id; *) | |
20 | (* id_of_string (s^(string_of_int !id)) *) | |
21 | (* with Not_found -> *) | |
22 | (* Hashtbl.add idtbl s (ref (-1)); *) | |
23 | (* id_of_string s *) | |
24 | ||
25 | (* let fresh_name s = Name (fresh_id s) *) | |
26 | (* let get_name ?(default="H") = function *) | |
27 | (* | Anonymous -> fresh_name default *) | |
28 | (* | Name n -> Name n *) | |
29 | ||
30 | 15 | |
31 | 16 | |
32 | 17 | let fresh_id avoid s = Termops.next_global_ident_away true (id_of_string s) avoid |
158 | 143 | let eq = lazy(coq_constant "eq") |
159 | 144 | let refl_equal = lazy(coq_constant "refl_equal") |
160 | 145 | |
161 | ||
162 | (* (\************************************************\) *) | |
163 | (* (\* Should be removed latter *\) *) | |
164 | (* (\* Comes from new induction (cf Pierre) *\) *) | |
165 | (* (\************************************************\) *) | |
166 | ||
167 | (* open Sign *) | |
168 | (* open Term *) | |
169 | ||
170 | (* type elim_scheme = *) | |
171 | ||
172 | (* (\* { (\\* lists are in reverse order! *\\) *\) *) | |
173 | (* (\* params: rel_context; (\\* (prm1,tprm1);(prm2,tprm2)...(prmp,tprmp) *\\) *\) *) | |
174 | (* (\* predicates: rel_context; (\\* (Qq, (Tq_1 -> Tq_2 ->...-> Tq_nq)), (Q1,...) *\\) *\) *) | |
175 | (* (\* branches: rel_context; (\\* branchr,...,branch1 *\\) *\) *) | |
176 | (* (\* args: rel_context; (\\* (xni, Ti_ni) ... (x1, Ti_1) *\\) *\) *) | |
177 | (* (\* indarg: rel_declaration option; (\\* Some (H,I prm1..prmp x1...xni) if present, None otherwise *\\) *\) *) | |
178 | (* (\* concl: types; (\\* Qi x1...xni HI, some prmis may not be present *\\) *\) *) | |
179 | (* (\* indarg_in_concl:bool; (\\* true if HI appears at the end of conclusion (dependent scheme) *\\) *\) *) | |
180 | (* (\* } *\) *) | |
181 | ||
182 | ||
183 | ||
184 | (* let occur_rel n c = *) | |
185 | (* let res = not (noccurn n c) in *) | |
186 | (* res *) | |
187 | ||
188 | (* let list_filter_firsts f l = *) | |
189 | (* let rec list_filter_firsts_aux f acc l = *) | |
190 | (* match l with *) | |
191 | (* | e::l' when f e -> list_filter_firsts_aux f (acc@[e]) l' *) | |
192 | (* | _ -> acc,l *) | |
193 | (* in *) | |
194 | (* list_filter_firsts_aux f [] l *) | |
195 | ||
196 | (* let count_rels_from n c = *) | |
197 | (* let rels = Termops.free_rels c in *) | |
198 | (* let cpt,rg = ref 0, ref n in *) | |
199 | (* while Util.Intset.mem !rg rels do *) | |
200 | (* cpt:= !cpt+1; rg:= !rg+1; *) | |
201 | (* done; *) | |
202 | (* !cpt *) | |
203 | ||
204 | (* let count_nonfree_rels_from n c = *) | |
205 | (* let rels = Termops.free_rels c in *) | |
206 | (* if Util.Intset.exists (fun x -> x >= n) rels then *) | |
207 | (* let cpt,rg = ref 0, ref n in *) | |
208 | (* while not (Util.Intset.mem !rg rels) do *) | |
209 | (* cpt:= !cpt+1; rg:= !rg+1; *) | |
210 | (* done; *) | |
211 | (* !cpt *) | |
212 | (* else raise Not_found *) | |
213 | ||
214 | (* (\* cuts a list in two parts, first of size n. Size must be greater than n *\) *) | |
215 | (* let cut_list n l = *) | |
216 | (* let rec cut_list_aux acc n l = *) | |
217 | (* if n<=0 then acc,l *) | |
218 | (* else match l with *) | |
219 | (* | [] -> assert false *) | |
220 | (* | e::l' -> cut_list_aux (acc@[e]) (n-1) l' in *) | |
221 | (* let res = cut_list_aux [] n l in *) | |
222 | (* res *) | |
223 | ||
224 | (* let exchange_hd_prod subst_hd t = *) | |
225 | (* let hd,args= decompose_app t in mkApp (subst_hd,Array.of_list args) *) | |
226 | ||
227 | (* let compute_elim_sig elimt = *) | |
228 | (* (\* conclusion is the final (Qi ...) *\) *) | |
229 | (* let hyps,conclusion = decompose_prod_assum elimt in *) | |
230 | (* (\* ccl is conclusion where Qi (that is rel <something>) is replaced *) | |
231 | (* by a constant (Prop) to avoid it being counted as an arg or *) | |
232 | (* parameter in the following. *\) *) | |
233 | (* let ccl = exchange_hd_prod mkProp conclusion in *) | |
234 | (* (\* indarg is the inductive argument if it exists. If it exists it is *) | |
235 | (* the last hyp before the conclusion, so it is the first element of *) | |
236 | (* hyps. To know the first elmt is an inductive arg, we check if the *) | |
237 | (* it appears in the conclusion (as rel 1). If yes, then it is not *) | |
238 | (* an inductive arg, otherwise it is. There is a pathological case *) | |
239 | (* with False_inf where Qi is rel 1, so we first get rid of Qi in *) | |
240 | (* ccl. *\) *) | |
241 | (* (\* if last arg of ccl is an application then this a functional ind *) | |
242 | (* principle *\) let last_arg_ccl = *) | |
243 | (* try List.hd (List.rev (snd (decompose_app ccl))) *) | |
244 | (* with Failure "hd" -> mkProp in (\* dummy constr that is not an app *) | |
245 | (* *\) let hyps',indarg,dep = *) | |
246 | (* if isApp last_arg_ccl *) | |
247 | (* then *) | |
248 | (* hyps,None , false (\* no HI at all *\) *) | |
249 | (* else *) | |
250 | (* try *) | |
251 | (* if noccurn 1 ccl (\* rel 1 does not occur in ccl *\) *) | |
252 | (* then *) | |
253 | (* List.tl hyps , Some (List.hd hyps), false (\* it does not *) | |
254 | (* occur in concl *\) else *) | |
255 | (* List.tl hyps , Some (List.hd hyps) , true (\* it does occur in concl *\) *) | |
256 | (* with Failure s -> Util.error "cannot recognise an induction schema" *) | |
257 | (* in *) | |
258 | ||
259 | (* (\* Arguments [xni...x1] must appear in the conclusion, so we count *) | |
260 | (* successive rels appearing in conclusion **Qi is not considered a *) | |
261 | (* rel** *\) let nargs = count_rels_from *) | |
262 | (* (match indarg with *) | |
263 | (* | None -> 1 *) | |
264 | (* | Some _ -> 2) ccl in *) | |
265 | (* let args,hyps'' = cut_list nargs hyps' in *) | |
266 | (* let rel_is_pred (_,_,c) = isSort (snd(decompose_prod_assum c)) in *) | |
267 | (* let branches,hyps''' = *) | |
268 | (* list_filter_firsts (function x -> not (rel_is_pred x)) hyps'' *) | |
269 | (* in *) | |
270 | (* (\* Now we want to know which hyps remaining are predicates and which *) | |
271 | (* are parameters *\) *) | |
272 | (* (\* We rebuild *) | |
273 | ||
274 | (* forall (x1:Ti_1) (xni:Ti_ni) (HI:I prm1..prmp x1...xni), DUMMY *) | |
275 | (* x1...xni HI ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ *) | |
276 | (* optional *) | |
277 | (* opt *) | |
278 | ||
279 | (* Free rels appearing in this term are parameters. We catch all of *) | |
280 | (* them if HI is present. In this case the number of parameters is *) | |
281 | (* the number of free rels. Otherwise (principle generated by *) | |
282 | (* functional induction or by hand) WE GUESS that all parameters *) | |
283 | (* appear in Ti_js, IS THAT TRUE??. *) | |
284 | ||
285 | (* TODO: if we want to generalize to the case where arges are merged *) | |
286 | (* with branches (?) and/or where several predicates are cited in *) | |
287 | (* the conclusion, we should do something more precise than just *) | |
288 | (* counting free rels. *) | |
289 | (* *\) *) | |
290 | (* let concl_with_indarg = *) | |
291 | (* match indarg with *) | |
292 | (* | None -> ccl *) | |
293 | (* | Some c -> it_mkProd_or_LetIn ccl [c] in *) | |
294 | (* let concl_with_args = it_mkProd_or_LetIn concl_with_indarg args in *) | |
295 | (* (\* let nparams2 = Util.Intset.cardinal (Termops.free_rels concl_with_args) in *\) *) | |
296 | (* let nparams = *) | |
297 | (* try List.length (hyps'''@branches) - count_nonfree_rels_from 1 *) | |
298 | (* concl_with_args with Not_found -> 0 in *) | |
299 | (* let preds,params = cut_list (List.length hyps''' - nparams) hyps''' in *) | |
300 | (* let elimscheme = { *) | |
301 | (* params = params; *) | |
302 | (* predicates = preds; *) | |
303 | (* branches = branches; *) | |
304 | (* args = args; *) | |
305 | (* indarg = indarg; *) | |
306 | (* concl = conclusion; *) | |
307 | (* indarg_in_concl = dep; *) | |
308 | (* } *) | |
309 | (* in *) | |
310 | (* elimscheme *) | |
311 | ||
312 | (* let get_params elimt = *) | |
313 | (* (compute_elim_sig elimt).params *) | |
314 | (* (\************************************************\) *) | |
315 | (* (\* end of Should be removed latter *\) *) | |
316 | (* (\* Comes from new induction (cf Pierre) *\) *) | |
317 | (* (\************************************************\) *) | |
318 | ||
146 | (*****************************************************************) | |
147 | (* Copy of the standart save mechanism but without the much too *) | |
148 | (* slow reduction function *) | |
149 | (*****************************************************************) | |
150 | open Declarations | |
151 | open Entries | |
152 | open Decl_kinds | |
153 | open Declare | |
154 | let definition_message id = | |
155 | Options.if_verbose message ((string_of_id id) ^ " is defined") | |
156 | ||
157 | ||
158 | let save with_clean id const (locality,kind) hook = | |
159 | let {const_entry_body = pft; | |
160 | const_entry_type = tpo; | |
161 | const_entry_opaque = opacity } = const in | |
162 | let l,r = match locality with | |
163 | | Local when Lib.sections_are_opened () -> | |
164 | let k = logical_kind_of_goal_kind kind in | |
165 | let c = SectionLocalDef (pft, tpo, opacity) in | |
166 | let _ = declare_variable id (Lib.cwd(), c, k) in | |
167 | (Local, VarRef id) | |
168 | | Local -> | |
169 | let k = logical_kind_of_goal_kind kind in | |
170 | let kn = declare_constant id (DefinitionEntry const, k) in | |
171 | (Global, ConstRef kn) | |
172 | | Global -> | |
173 | let k = logical_kind_of_goal_kind kind in | |
174 | let kn = declare_constant id (DefinitionEntry const, k) in | |
175 | (Global, ConstRef kn) in | |
176 | if with_clean then Pfedit.delete_current_proof (); | |
177 | hook l r; | |
178 | definition_message id | |
179 | ||
180 | ||
181 | ||
182 | ||
183 | let extract_pftreestate pts = | |
184 | let pfterm,subgoals = Refiner.extract_open_pftreestate pts in | |
185 | let tpfsigma = Refiner.evc_of_pftreestate pts in | |
186 | let exl = Evarutil.non_instantiated tpfsigma in | |
187 | if subgoals <> [] or exl <> [] then | |
188 | Util.errorlabstrm "extract_proof" | |
189 | (if subgoals <> [] then | |
190 | str "Attempt to save an incomplete proof" | |
191 | else | |
192 | str "Attempt to save a proof with existential variables still non-instantiated"); | |
193 | let env = Global.env_of_context (Refiner.proof_of_pftreestate pts).Proof_type.goal.Evd.evar_hyps in | |
194 | env,tpfsigma,pfterm | |
195 | ||
196 | ||
197 | let nf_betaiotazeta = | |
198 | let clos_norm_flags flgs env sigma t = | |
199 | Closure.norm_val (Closure.create_clos_infos flgs env) (Closure.inject (Reductionops.nf_evar sigma t)) in | |
200 | clos_norm_flags Closure.betaiotazeta | |
201 | ||
202 | let nf_betaiota = | |
203 | let clos_norm_flags flgs env sigma t = | |
204 | Closure.norm_val (Closure.create_clos_infos flgs env) (Closure.inject (Reductionops.nf_evar sigma t)) in | |
205 | clos_norm_flags Closure.betaiota | |
206 | ||
207 | let cook_proof do_reduce = | |
208 | let pfs = Pfedit.get_pftreestate () | |
209 | (* and ident = Pfedit.get_current_proof_name () *) | |
210 | and (ident,strength,concl,hook) = Pfedit.current_proof_statement () in | |
211 | let env,sigma,pfterm = extract_pftreestate pfs in | |
212 | let pfterm = | |
213 | if do_reduce | |
214 | then nf_betaiota env sigma pfterm | |
215 | else pfterm | |
216 | in | |
217 | (ident, | |
218 | ({ const_entry_body = pfterm; | |
219 | const_entry_type = Some concl; | |
220 | const_entry_opaque = false; | |
221 | const_entry_boxed = false}, | |
222 | strength, hook)) | |
223 | ||
224 | ||
225 | let new_save_named opacity = | |
226 | let id,(const,persistence,hook) = cook_proof true in | |
227 | let const = { const with const_entry_opaque = opacity } in | |
228 | save true id const persistence hook | |
229 | ||
230 | let get_proof_clean do_reduce = | |
231 | let result = cook_proof do_reduce in | |
232 | Pfedit.delete_current_proof (); | |
233 | result | |
234 | ||
235 | ||
236 | ||
237 | ||
238 | (**********************) | |
239 | ||
240 | type function_info = | |
241 | { | |
242 | function_constant : constant; | |
243 | graph_ind : inductive; | |
244 | equation_lemma : constant option; | |
245 | correctness_lemma : constant option; | |
246 | completeness_lemma : constant option; | |
247 | rect_lemma : constant option; | |
248 | rec_lemma : constant option; | |
249 | prop_lemma : constant option; | |
250 | } | |
251 | ||
252 | ||
253 | type function_db = function_info list | |
254 | ||
255 | let function_table = ref ([] : function_db) | |
256 | ||
257 | ||
258 | let rec do_cache_info finfo = function | |
259 | | [] -> raise Not_found | |
260 | | (finfo'::finfos as l) -> | |
261 | if finfo' == finfo then l | |
262 | else if finfo'.function_constant = finfo.function_constant | |
263 | then finfo::finfos | |
264 | else | |
265 | let res = do_cache_info finfo finfos in | |
266 | if res == finfos then l else finfo'::l | |
267 | ||
268 | ||
269 | let cache_Function (_,(finfos)) = | |
270 | let new_tbl = | |
271 | try do_cache_info finfos !function_table | |
272 | with Not_found -> finfos::!function_table | |
273 | in | |
274 | if new_tbl != !function_table | |
275 | then function_table := new_tbl | |
276 | ||
277 | let load_Function _ = cache_Function | |
278 | let open_Function _ = cache_Function | |
279 | let subst_Function (_,subst,finfos) = | |
280 | let do_subst_con c = fst (Mod_subst.subst_con subst c) | |
281 | and do_subst_ind (kn,i) = (Mod_subst.subst_kn subst kn,i) | |
282 | in | |
283 | let function_constant' = do_subst_con finfos.function_constant in | |
284 | let graph_ind' = do_subst_ind finfos.graph_ind in | |
285 | let equation_lemma' = Util.option_smartmap do_subst_con finfos.equation_lemma in | |
286 | let correctness_lemma' = Util.option_smartmap do_subst_con finfos.correctness_lemma in | |
287 | let completeness_lemma' = Util.option_smartmap do_subst_con finfos.completeness_lemma in | |
288 | let rect_lemma' = Util.option_smartmap do_subst_con finfos.rect_lemma in | |
289 | let rec_lemma' = Util.option_smartmap do_subst_con finfos.rec_lemma in | |
290 | let prop_lemma' = Util.option_smartmap do_subst_con finfos.prop_lemma in | |
291 | if function_constant' == finfos.function_constant && | |
292 | graph_ind' == finfos.graph_ind && | |
293 | equation_lemma' == finfos.equation_lemma && | |
294 | correctness_lemma' == finfos.correctness_lemma && | |
295 | completeness_lemma' == finfos.completeness_lemma && | |
296 | rect_lemma' == finfos.rect_lemma && | |
297 | rec_lemma' == finfos.rec_lemma && | |
298 | prop_lemma' == finfos.prop_lemma | |
299 | then finfos | |
300 | else | |
301 | { function_constant = function_constant'; | |
302 | graph_ind = graph_ind'; | |
303 | equation_lemma = equation_lemma' ; | |
304 | correctness_lemma = correctness_lemma' ; | |
305 | completeness_lemma = completeness_lemma' ; | |
306 | rect_lemma = rect_lemma' ; | |
307 | rec_lemma = rec_lemma'; | |
308 | prop_lemma = prop_lemma'; | |
309 | } | |
310 | ||
311 | let classify_Function (_,infos) = Libobject.Substitute infos | |
312 | ||
313 | let export_Function infos = Some infos | |
314 | ||
315 | ||
316 | let discharge_Function (_,finfos) = | |
317 | let function_constant' = Lib.discharge_con finfos.function_constant | |
318 | and graph_ind' = Lib.discharge_inductive finfos.graph_ind | |
319 | and equation_lemma' = Util.option_smartmap Lib.discharge_con finfos.equation_lemma | |
320 | and correctness_lemma' = Util.option_smartmap Lib.discharge_con finfos.correctness_lemma | |
321 | and completeness_lemma' = Util.option_smartmap Lib.discharge_con finfos.completeness_lemma | |
322 | and rect_lemma' = Util.option_smartmap Lib.discharge_con finfos.rect_lemma | |
323 | and rec_lemma' = Util.option_smartmap Lib.discharge_con finfos.rec_lemma | |
324 | and prop_lemma' = Util.option_smartmap Lib.discharge_con finfos.prop_lemma | |
325 | in | |
326 | if function_constant' == finfos.function_constant && | |
327 | graph_ind' == finfos.graph_ind && | |
328 | equation_lemma' == finfos.equation_lemma && | |
329 | correctness_lemma' == finfos.correctness_lemma && | |
330 | completeness_lemma' == finfos.completeness_lemma && | |
331 | rect_lemma' == finfos.rect_lemma && | |
332 | rec_lemma' == finfos.rec_lemma && | |
333 | prop_lemma' == finfos.prop_lemma | |
334 | then Some finfos | |
335 | else | |
336 | Some { function_constant = function_constant' ; | |
337 | graph_ind = graph_ind' ; | |
338 | equation_lemma = equation_lemma' ; | |
339 | correctness_lemma = correctness_lemma' ; | |
340 | completeness_lemma = completeness_lemma'; | |
341 | rect_lemma = rect_lemma'; | |
342 | rec_lemma = rec_lemma'; | |
343 | prop_lemma = prop_lemma' ; | |
344 | } | |
345 | ||
346 | open Term | |
347 | let pr_info f_info = | |
348 | str "function_constant := " ++ Printer.pr_lconstr (mkConst f_info.function_constant)++ fnl () ++ | |
349 | str "function_constant_type := " ++ | |
350 | (try Printer.pr_lconstr (Global.type_of_global (ConstRef f_info.function_constant)) with _ -> mt ()) ++ fnl () ++ | |
351 | str "equation_lemma := " ++ (Util.option_fold_right (fun v acc -> Printer.pr_lconstr (mkConst v)) f_info.equation_lemma (mt ()) ) ++ fnl () ++ | |
352 | str "completeness_lemma :=" ++ (Util.option_fold_right (fun v acc -> Printer.pr_lconstr (mkConst v)) f_info.completeness_lemma (mt ()) ) ++ fnl () ++ | |
353 | str "correctness_lemma := " ++ (Util.option_fold_right (fun v acc -> Printer.pr_lconstr (mkConst v)) f_info.correctness_lemma (mt ()) ) ++ fnl () ++ | |
354 | str "rect_lemma := " ++ (Util.option_fold_right (fun v acc -> Printer.pr_lconstr (mkConst v)) f_info.rect_lemma (mt ()) ) ++ fnl () ++ | |
355 | str "rec_lemma := " ++ (Util.option_fold_right (fun v acc -> Printer.pr_lconstr (mkConst v)) f_info.rec_lemma (mt ()) ) ++ fnl () ++ | |
356 | str "prop_lemma := " ++ (Util.option_fold_right (fun v acc -> Printer.pr_lconstr (mkConst v)) f_info.prop_lemma (mt ()) ) ++ fnl () ++ | |
357 | str "graph_ind := " ++ Printer.pr_lconstr (mkInd f_info.graph_ind) ++ fnl () | |
358 | ||
359 | let pr_table l = | |
360 | Util.prlist_with_sep fnl pr_info l | |
361 | ||
362 | let in_Function,out_Function = | |
363 | Libobject.declare_object | |
364 | {(Libobject.default_object "FUNCTIONS_DB") with | |
365 | Libobject.cache_function = cache_Function; | |
366 | Libobject.load_function = load_Function; | |
367 | Libobject.classify_function = classify_Function; | |
368 | Libobject.subst_function = subst_Function; | |
369 | Libobject.export_function = export_Function; | |
370 | Libobject.discharge_function = discharge_Function | |
371 | (* Libobject.open_function = open_Function; *) | |
372 | } | |
373 | ||
374 | ||
375 | ||
376 | (* Synchronisation with reset *) | |
377 | let freeze () = | |
378 | let tbl = !function_table in | |
379 | (* Pp.msgnl (str "freezing function_table : " ++ pr_table tbl); *) | |
380 | tbl | |
381 | ||
382 | let unfreeze l = | |
383 | (* Pp.msgnl (str "unfreezing function_table : " ++ pr_table l); *) | |
384 | function_table := | |
385 | l | |
386 | let init () = | |
387 | (* Pp.msgnl (str "reseting function_table"); *) | |
388 | function_table := [] | |
389 | ||
390 | let _ = | |
391 | Summary.declare_summary "functions_db_sum" | |
392 | { Summary.freeze_function = freeze; | |
393 | Summary.unfreeze_function = unfreeze; | |
394 | Summary.init_function = init; | |
395 | Summary.survive_module = false; | |
396 | Summary.survive_section = false } | |
397 | ||
398 | let find_or_none id = | |
399 | try Some | |
400 | (match Nametab.locate (make_short_qualid id) with ConstRef c -> c | _ -> Util.anomaly "Not a constant" | |
401 | ) | |
402 | with Not_found -> None | |
403 | ||
404 | ||
405 | ||
406 | let find_Function_infos f = | |
407 | List.find (fun finfo -> finfo.function_constant = f) !function_table | |
408 | ||
409 | ||
410 | let find_Function_of_graph ind = | |
411 | List.find (fun finfo -> finfo.graph_ind = ind) !function_table | |
412 | ||
413 | let update_Function finfo = | |
414 | (* Pp.msgnl (pr_info finfo); *) | |
415 | Lib.add_anonymous_leaf (in_Function finfo) | |
416 | ||
417 | ||
418 | let add_Function f = | |
419 | let f_id = id_of_label (con_label f) in | |
420 | let equation_lemma = find_or_none (mk_equation_id f_id) | |
421 | and correctness_lemma = find_or_none (mk_correct_id f_id) | |
422 | and completeness_lemma = find_or_none (mk_complete_id f_id) | |
423 | and rect_lemma = find_or_none (Nameops.add_suffix f_id "_rect") | |
424 | and rec_lemma = find_or_none (Nameops.add_suffix f_id "_rec") | |
425 | and prop_lemma = find_or_none (Nameops.add_suffix f_id "_ind") | |
426 | and graph_ind = | |
427 | match Nametab.locate (make_short_qualid (mk_rel_id f_id)) | |
428 | with | IndRef ind -> ind | _ -> Util.anomaly "Not an inductive" | |
429 | in | |
430 | let finfos = | |
431 | { function_constant = f; | |
432 | equation_lemma = equation_lemma; | |
433 | completeness_lemma = completeness_lemma; | |
434 | correctness_lemma = correctness_lemma; | |
435 | rect_lemma = rect_lemma; | |
436 | rec_lemma = rec_lemma; | |
437 | prop_lemma = prop_lemma; | |
438 | graph_ind = graph_ind | |
439 | } | |
440 | in | |
441 | update_Function finfos | |
442 | ||
443 | let pr_table () = pr_table !function_table | |
444 | (*********************************) | |
445 | (* Debuging *) | |
446 | let function_debug = ref false | |
447 | open Goptions | |
448 | ||
449 | let function_debug_sig = | |
450 | { | |
451 | optsync = false; | |
452 | optname = "Function debug"; | |
453 | optkey = PrimaryTable("Function_debug"); | |
454 | optread = (fun () -> !function_debug); | |
455 | optwrite = (fun b -> function_debug := b) | |
456 | } | |
457 | ||
458 | let _ = declare_bool_option function_debug_sig | |
459 | ||
460 | ||
461 | let do_observe () = | |
462 | !function_debug = true | |
463 | ||
464 | ||
465 |
0 | 0 | open Names |
1 | 1 | open Pp |
2 | 2 | |
3 | (* | |
4 | The mk_?_id function build different name w.r.t. a function | |
5 | Each of their use is justified in the code | |
6 | *) | |
3 | 7 | val mk_rel_id : identifier -> identifier |
8 | val mk_correct_id : identifier -> identifier | |
9 | val mk_complete_id : identifier -> identifier | |
10 | val mk_equation_id : identifier -> identifier | |
11 | ||
4 | 12 | |
5 | 13 | val msgnl : std_ppcmds -> unit |
6 | 14 | |
38 | 46 | val const_of_id: identifier -> constant |
39 | 47 | |
40 | 48 | |
49 | (* [save_named] is a copy of [Command.save_named] but uses | |
50 | [nf_betaiotazeta] instead of [nf_betaiotaevar_preserving_vm_cast] | |
51 | ||
52 | ||
53 | ||
54 | DON'T USE IT if you cannot ensure that there is no VMcast in the proof | |
55 | ||
56 | *) | |
57 | ||
58 | (* val nf_betaiotazeta : Reductionops.reduction_function *) | |
59 | ||
60 | val new_save_named : bool -> unit | |
61 | ||
62 | val save : bool -> identifier -> Entries.definition_entry -> Decl_kinds.goal_kind -> | |
63 | Tacexpr.declaration_hook -> unit | |
64 | ||
65 | (* [get_proof_clean do_reduce] : returns the proof name, definition, kind and hook and | |
66 | abort the proof | |
67 | *) | |
68 | val get_proof_clean : bool -> | |
69 | Names.identifier * | |
70 | (Entries.definition_entry * Decl_kinds.goal_kind * | |
71 | Tacexpr.declaration_hook) | |
72 | ||
73 | ||
74 | ||
75 | ||
76 | (*****************) | |
77 | ||
78 | type function_info = | |
79 | { | |
80 | function_constant : constant; | |
81 | graph_ind : inductive; | |
82 | equation_lemma : constant option; | |
83 | correctness_lemma : constant option; | |
84 | completeness_lemma : constant option; | |
85 | rect_lemma : constant option; | |
86 | rec_lemma : constant option; | |
87 | prop_lemma : constant option; | |
88 | } | |
89 | ||
90 | val find_Function_infos : constant -> function_info | |
91 | val find_Function_of_graph : inductive -> function_info | |
92 | (* WARNING: To be used just after the graph definition !!! *) | |
93 | val add_Function : constant -> unit | |
94 | ||
95 | val update_Function : function_info -> unit | |
96 | ||
97 | ||
98 | (** debugging *) | |
99 | val pr_info : function_info -> Pp.std_ppcmds | |
100 | val pr_table : unit -> Pp.std_ppcmds | |
101 | ||
102 | ||
103 | val function_debug : bool ref | |
104 | val do_observe : unit -> bool |
13 | 13 | open Indfun |
14 | 14 | open Genarg |
15 | 15 | open Pcoq |
16 | open Tacticals | |
16 | 17 | |
17 | 18 | let pr_binding prc = function |
18 | 19 | | loc, Rawterm.NamedHyp id, c -> hov 1 (Ppconstr.pr_id id ++ str " := " ++ cut () ++ prc c) |
35 | 36 | let pr_fun_ind_using prc prlc _ opt_c = |
36 | 37 | match opt_c with |
37 | 38 | | None -> mt () |
38 | | Some c -> spc () ++ hov 2 (str "using" ++ spc () ++ pr_with_bindings prc prlc c) | |
39 | | Some (p,b) -> spc () ++ hov 2 (str "using" ++ spc () ++ pr_with_bindings prc prlc (p,b)) | |
40 | ||
39 | 41 | |
40 | 42 | ARGUMENT EXTEND fun_ind_using |
41 | 43 | TYPED AS constr_with_bindings_opt |
46 | 48 | |
47 | 49 | |
48 | 50 | TACTIC EXTEND newfuninv |
49 | [ "functional" "inversion" ident(hyp) ident(fname) fun_ind_using(princl)] -> | |
51 | [ "functional" "inversion" quantified_hypothesis(hyp) reference_opt(fname) ] -> | |
50 | 52 | [ |
51 | fun g -> | |
52 | let fconst = const_of_id fname in | |
53 | let princ = | |
54 | match princl with | |
55 | | None -> | |
56 | let f_ind_id = | |
57 | ( | |
58 | Indrec.make_elimination_ident | |
59 | fname | |
60 | (Tacticals.elimination_sort_of_goal g) | |
61 | ) | |
62 | in | |
63 | let princ = const_of_id f_ind_id in | |
64 | princ | |
65 | | Some princ -> destConst (fst princ) | |
66 | in | |
67 | Invfun.invfun hyp fconst princ g | |
53 | Invfun.invfun hyp fname | |
68 | 54 | ] |
69 | 55 | END |
70 | 56 | |
81 | 67 | END |
82 | 68 | |
83 | 69 | |
84 | let is_rec scheme_info = | |
85 | let test_branche min acc (_,_,br) = | |
86 | acc || | |
87 | (let new_branche = Sign.it_mkProd_or_LetIn mkProp (fst (Sign.decompose_prod_assum br)) in | |
88 | let free_rels_in_br = Termops.free_rels new_branche in | |
89 | let max = min + scheme_info.Tactics.npredicates in | |
90 | Util.Intset.exists (fun i -> i >= min && i< max) free_rels_in_br) | |
91 | in | |
92 | Util.list_fold_left_i test_branche 1 false (List.rev scheme_info.Tactics.branches) | |
93 | ||
94 | ||
95 | let choose_dest_or_ind scheme_info = | |
96 | if is_rec scheme_info | |
97 | then Tactics.new_induct | |
98 | else Tactics.new_destruct | |
99 | 70 | |
100 | 71 | |
101 | 72 | TACTIC EXTEND newfunind |
102 | 73 | ["functional" "induction" ne_constr_list(cl) fun_ind_using(princl) with_names(pat)] -> |
103 | [ | |
74 | [ | |
104 | 75 | let pat = |
105 | 76 | match pat with |
106 | 77 | | None -> IntroAnonymous |
111 | 82 | | [c] -> c |
112 | 83 | | c::cl -> applist(c,cl) |
113 | 84 | in |
114 | let f,args = decompose_app c in | |
115 | fun g -> | |
116 | let princ,bindings = | |
117 | match princl with | |
118 | | None -> (* No principle is given let's find the good one *) | |
119 | let fname = | |
120 | match kind_of_term f with | |
121 | | Const c' -> | |
122 | id_of_label (con_label c') | |
123 | | _ -> Util.error "Must be used with a function" | |
124 | in | |
125 | let princ_name = | |
126 | ( | |
127 | Indrec.make_elimination_ident | |
128 | fname | |
129 | (Tacticals.elimination_sort_of_goal g) | |
130 | ) | |
131 | in | |
132 | mkConst(const_of_id princ_name ),Rawterm.NoBindings | |
133 | | Some princ -> princ | |
134 | in | |
135 | let princ_type = Tacmach.pf_type_of g princ in | |
136 | let princ_infos = Tactics.compute_elim_sig princ_type in | |
137 | let args_as_induction_constr = | |
138 | let c_list = | |
139 | if princ_infos.Tactics.farg_in_concl | |
140 | then [c] else [] | |
141 | in | |
142 | List.map (fun c -> Tacexpr.ElimOnConstr c) (args@c_list) | |
143 | in | |
144 | let princ' = Some (princ,bindings) in | |
145 | let princ_vars = | |
146 | List.fold_right | |
147 | (fun a acc -> | |
148 | try Idset.add (destVar a) acc | |
149 | with _ -> acc | |
150 | ) | |
151 | args | |
152 | Idset.empty | |
153 | in | |
154 | let old_idl = List.fold_right Idset.add (Tacmach.pf_ids_of_hyps g) Idset.empty in | |
155 | let old_idl = Idset.diff old_idl princ_vars in | |
156 | let subst_and_reduce g = | |
157 | let idl = | |
158 | Util.map_succeed | |
159 | (fun id -> | |
160 | if Idset.mem id old_idl then failwith ""; | |
161 | id | |
162 | ) | |
163 | (Tacmach.pf_ids_of_hyps g) | |
164 | in | |
165 | let flag = | |
166 | Rawterm.Cbv | |
167 | {Rawterm.all_flags | |
168 | with Rawterm.rDelta = false; | |
169 | } | |
170 | in | |
171 | Tacticals.tclTHEN | |
172 | (Tacticals.tclMAP (fun id -> Tacticals.tclTRY (Equality.subst [id])) idl ) | |
173 | (Hiddentac.h_reduce flag Tacticals.allClauses) | |
174 | g | |
175 | in | |
176 | Tacticals.tclTHEN | |
177 | (choose_dest_or_ind | |
178 | princ_infos | |
179 | args_as_induction_constr | |
180 | princ' | |
181 | pat) | |
182 | subst_and_reduce | |
183 | g | |
184 | ] | |
85 | functional_induction true c princl pat ] | |
86 | END | |
87 | (***** debug only ***) | |
88 | TACTIC EXTEND snewfunind | |
89 | ["soft" "functional" "induction" ne_constr_list(cl) fun_ind_using(princl) with_names(pat)] -> | |
90 | [ | |
91 | let pat = | |
92 | match pat with | |
93 | | None -> IntroAnonymous | |
94 | | Some pat -> pat | |
95 | in | |
96 | let c = match cl with | |
97 | | [] -> assert false | |
98 | | [c] -> c | |
99 | | c::cl -> applist(c,cl) | |
100 | in | |
101 | functional_induction false c princl pat ] | |
185 | 102 | END |
186 | 103 | |
187 | 104 | |
212 | 129 | in |
213 | 130 | let check_exists_args an = |
214 | 131 | try |
215 | let id = match an with Struct id -> id | Wf(_,Some id) -> id | Mes(_,Some id) -> id | Wf(_,None) | Mes(_,None) -> failwith "check_exists_args" in | |
132 | let id = match an with | |
133 | | Struct id -> id | Wf(_,Some id) -> id | Mes(_,Some id) -> id | |
134 | | Wf(_,None) | Mes(_,None) -> failwith "check_exists_args" | |
135 | in | |
216 | 136 | (try ignore(Util.list_index (Name id) names - 1); annot |
217 | 137 | with Not_found -> Util.user_err_loc |
218 | 138 | (Util.dummy_loc,"Function", |
239 | 159 | |
240 | 160 | VERNAC COMMAND EXTEND Function |
241 | 161 | ["Function" rec_definitions2(recsl)] -> |
242 | [ do_generate_principle false recsl] | |
162 | [ | |
163 | do_generate_principle false recsl; | |
164 | ||
165 | ] | |
243 | 166 | END |
244 | 167 | |
245 | 168 | |
246 | 169 | VERNAC ARGUMENT EXTEND fun_scheme_arg |
247 | | [ ident(princ_name) ":=" "Induction" "for" ident(fun_name) "Sort" sort(s) ] -> [ (princ_name,fun_name,s) ] | |
170 | | [ ident(princ_name) ":=" "Induction" "for" reference(fun_name) "Sort" sort(s) ] -> [ (princ_name,fun_name,s) ] | |
248 | 171 | END |
249 | 172 | |
250 | 173 | VERNAC ARGUMENT EXTEND fun_scheme_args |
256 | 179 | ["Functional" "Scheme" fun_scheme_args(fas) ] -> |
257 | 180 | [ |
258 | 181 | try |
259 | Functional_principles_types.make_scheme fas | |
182 | Functional_principles_types.build_scheme fas | |
260 | 183 | with Functional_principles_types.No_graph_found -> |
261 | 184 | match fas with |
262 | 185 | | (_,fun_name,_)::_ -> |
263 | 186 | begin |
264 | make_graph fun_name; | |
265 | try Functional_principles_types.make_scheme fas | |
187 | make_graph (Nametab.global fun_name); | |
188 | try Functional_principles_types.build_scheme fas | |
266 | 189 | with Functional_principles_types.No_graph_found -> |
267 | 190 | Util.error ("Cannot generate induction principle(s)") |
268 | 191 | end |
269 | 192 | | _ -> assert false (* we can only have non empty list *) |
270 | 193 | ] |
271 | 194 | END |
272 | ||
195 | (***** debug only ***) | |
273 | 196 | |
274 | 197 | VERNAC COMMAND EXTEND NewFunctionalCase |
275 | 198 | ["Functional" "Case" fun_scheme_arg(fas) ] -> |
276 | 199 | [ |
277 | Functional_principles_types.make_case_scheme fas | |
200 | Functional_principles_types.build_case_scheme fas | |
278 | 201 | ] |
279 | 202 | END |
280 | 203 | |
281 | ||
204 | (***** debug only ***) | |
282 | 205 | VERNAC COMMAND EXTEND GenerateGraph |
283 | ["Generate" "graph" "for" ident(c)] -> [ make_graph c ] | |
284 | END | |
206 | ["Generate" "graph" "for" reference(c)] -> [ make_graph (Nametab.global c) ] | |
207 | END | |
208 | ||
209 | ||
210 | ||
211 | ||
212 | ||
213 | (* FINDUCTION *) | |
214 | ||
215 | (* comment this line to see debug msgs *) | |
216 | (* let msg x = () ;; let pr_lconstr c = str "" *) | |
217 | (* uncomment this to see debugging *) | |
218 | let prconstr c = msg (str" " ++ Printer.pr_lconstr c ++ str"\n") | |
219 | let prlistconstr lc = List.iter prconstr lc | |
220 | let prstr s = msg(str s) | |
221 | ||
222 | ||
223 | ||
224 | (** Information about an occurrence of a function call (application) | |
225 | inside a term. *) | |
226 | type fapp_info = { | |
227 | fname: constr; (** The function applied *) | |
228 | largs: constr list; (** List of arguments *) | |
229 | free: bool; (** [true] if all arguments are debruijn free *) | |
230 | max_rel: int; (** max debruijn index in the funcall *) | |
231 | onlyvars: bool (** [true] if all arguments are variables (and not debruijn) *) | |
232 | } | |
233 | ||
234 | ||
235 | (** [constr_head_match(a b c) a] returns true, false otherwise. *) | |
236 | let constr_head_match u t= | |
237 | if isApp u | |
238 | then | |
239 | let uhd,args= destApp u in | |
240 | uhd=t | |
241 | else false | |
242 | ||
243 | (** [hdMatchSub inu t] returns the list of occurrences of [t] in | |
244 | [inu]. DeBruijn are not pushed, so some of them may be unbound in | |
245 | the result. *) | |
246 | let rec hdMatchSub inu (test: constr -> bool) : fapp_info list = | |
247 | let subres = | |
248 | match kind_of_term inu with | |
249 | | Lambda (nm,tp,cstr) | Prod (nm,tp,cstr) -> | |
250 | hdMatchSub tp test @ hdMatchSub (lift 1 cstr) test | |
251 | | Fix (_,(lna,tl,bl)) -> (* not sure Fix is correct *) | |
252 | Array.fold_left | |
253 | (fun acc cstr -> acc @ hdMatchSub (lift (Array.length tl) cstr) test) | |
254 | [] bl | |
255 | | _ -> (* Cofix will be wrong *) | |
256 | fold_constr | |
257 | (fun l cstr -> | |
258 | l @ hdMatchSub cstr test) [] inu in | |
259 | if not (test inu) then subres | |
260 | else | |
261 | let f,args = decompose_app inu in | |
262 | let freeset = Termops.free_rels inu in | |
263 | let max_rel = try Util.Intset.max_elt freeset with Not_found -> -1 in | |
264 | {fname = f; largs = args; free = Util.Intset.is_empty freeset; | |
265 | max_rel = max_rel; onlyvars = List.for_all isVar args } | |
266 | ::subres | |
267 | ||
268 | ||
269 | (** [find_fapp test g] returns the list of [app_info] of all calls to | |
270 | functions that satisfy [test] in the conclusion of goal g. Trivial | |
271 | repetition (not modulo conversion) are deleted. *) | |
272 | let find_fapp (test:constr -> bool) g : fapp_info list = | |
273 | let pre_res = hdMatchSub (Tacmach.pf_concl g) test in | |
274 | let res = | |
275 | List.fold_right (fun x acc -> if List.mem x acc then acc else x::acc) pre_res [] in | |
276 | (prlistconstr (List.map (fun x -> applist (x.fname,x.largs)) res); | |
277 | res) | |
278 | ||
279 | ||
280 | ||
281 | (** [finduction id filter g] tries to apply functional induction on | |
282 | an occurence of function [id] in the conclusion of goal [g]. If | |
283 | [id]=[None] then calls to any function are selected. In any case | |
284 | [heuristic] is used to select the most pertinent occurrence. *) | |
285 | let finduction (oid:identifier option) (heuristic: fapp_info list -> fapp_info list) | |
286 | (nexttac:Proof_type.tactic) g = | |
287 | let test = match oid with | |
288 | | Some id -> | |
289 | let idconstr = mkConst (const_of_id id) in | |
290 | (fun u -> constr_head_match u idconstr) (* select only id *) | |
291 | | None -> (fun u -> isApp u) in (* select calls to any function *) | |
292 | let info_list = find_fapp test g in | |
293 | let ordered_info_list = heuristic info_list in | |
294 | prlistconstr (List.map (fun x -> applist (x.fname,x.largs)) ordered_info_list); | |
295 | if List.length ordered_info_list = 0 then Util.error "function not found in goal\n"; | |
296 | let taclist: Proof_type.tactic list = | |
297 | List.map | |
298 | (fun info -> | |
299 | (tclTHEN | |
300 | (functional_induction true (applist (info.fname, info.largs)) | |
301 | None IntroAnonymous) | |
302 | nexttac)) ordered_info_list in | |
303 | tclFIRST taclist g | |
304 | ||
305 | ||
306 | ||
307 | ||
308 | (** [chose_heuristic oi x] returns the heuristic for reordering | |
309 | (and/or forgetting some elts of) a list of occurrences of | |
310 | function calls infos to chose first with functional induction. *) | |
311 | let chose_heuristic (oi:int option) : fapp_info list -> fapp_info list = | |
312 | match oi with | |
313 | | Some i -> (fun l -> [ List.nth l (i-1) ]) (* occurrence was given by the user *) | |
314 | | None -> | |
315 | (* Default heuristic: keep only occurrence where all arguments | |
316 | are *bound* (meaning already introduced) variables *) | |
317 | (* TODO: put other funcalls at the end instead of deleting them *) | |
318 | let ordering x y = | |
319 | if x.free && x.onlyvars && y.free && y.onlyvars then 0 (* both pertinent *) | |
320 | else if x.free && x.onlyvars then -1 | |
321 | else if y.free && y.onlyvars then 1 | |
322 | else 0 (* both not pertinent *) | |
323 | in | |
324 | List.sort ordering | |
325 | ||
326 | ||
327 | TACTIC EXTEND finduction | |
328 | ["finduction" ident(id) natural_opt(oi)] -> | |
329 | [ | |
330 | match oi with | |
331 | | Some(n) when n<=0 -> Util.error "numerical argument must be > 0" | |
332 | | _ -> | |
333 | let heuristic = chose_heuristic oi in | |
334 | finduction (Some id) heuristic tclIDTAC | |
335 | ] | |
336 | END | |
337 | ||
338 | ||
339 | ||
340 | TACTIC EXTEND fauto | |
341 | [ "fauto" tactic(tac)] -> | |
342 | [ | |
343 | let heuristic = chose_heuristic None in | |
344 | finduction None heuristic (snd tac) | |
345 | ] | |
346 | | | |
347 | [ "fauto" ] -> | |
348 | [ | |
349 | let heuristic = chose_heuristic None in | |
350 | finduction None heuristic tclIDTAC | |
351 | ] | |
352 | ||
353 | END | |
354 |
0 | (************************************************************************) | |
1 | (* v * The Coq Proof Assistant / The Coq Development Team *) | |
2 | (* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *) | |
3 | (* \VV/ **************************************************************) | |
4 | (* // * This file is distributed under the terms of the *) | |
5 | (* * GNU Lesser General Public License Version 2.1 *) | |
6 | (************************************************************************) | |
7 | open Tacexpr | |
8 | open Declarations | |
0 | 9 | open Util |
1 | 10 | open Names |
2 | 11 | open Term |
3 | open Tacinvutils | |
4 | 12 | open Pp |
5 | 13 | open Libnames |
6 | 14 | open Tacticals |
8 | 16 | open Indfun_common |
9 | 17 | open Tacmach |
10 | 18 | open Sign |
11 | ||
12 | ||
13 | let tac_pattern l = | |
14 | (Hiddentac.h_reduce | |
15 | (Rawterm.Pattern l) | |
16 | Tacticals.onConcl | |
17 | ) | |
18 | ||
19 | ||
20 | let rec nb_prod x = | |
21 | let rec count n c = | |
22 | match kind_of_term c with | |
23 | Prod(_,_,t) -> count (n+1) t | |
24 | | LetIn(_,a,_,t) -> count n (subst1 a t) | |
25 | | Cast(c,_,_) -> count n c | |
26 | | _ -> n | |
27 | in count 0 x | |
28 | ||
29 | let intro_discr_until n tac : tactic = | |
30 | let rec intro_discr_until acc : tactic = | |
19 | open Hiddentac | |
20 | ||
21 | (* Some pretty printing function for debugging purpose *) | |
22 | ||
23 | let pr_binding prc = | |
24 | function | |
25 | | loc, Rawterm.NamedHyp id, c -> hov 1 (Ppconstr.pr_id id ++ str " := " ++ Pp.cut () ++ prc c) | |
26 | | loc, Rawterm.AnonHyp n, c -> hov 1 (int n ++ str " := " ++ Pp.cut () ++ prc c) | |
27 | ||
28 | let pr_bindings prc prlc = function | |
29 | | Rawterm.ImplicitBindings l -> | |
30 | brk (1,1) ++ str "with" ++ brk (1,1) ++ | |
31 | Util.prlist_with_sep spc prc l | |
32 | | Rawterm.ExplicitBindings l -> | |
33 | brk (1,1) ++ str "with" ++ brk (1,1) ++ | |
34 | Util.prlist_with_sep spc (fun b -> str"(" ++ pr_binding prlc b ++ str")") l | |
35 | | Rawterm.NoBindings -> mt () | |
36 | ||
37 | ||
38 | let pr_with_bindings prc prlc (c,bl) = | |
39 | prc c ++ hv 0 (pr_bindings prc prlc bl) | |
40 | ||
41 | ||
42 | ||
43 | let pr_constr_with_binding prc (c,bl) : Pp.std_ppcmds = | |
44 | pr_with_bindings prc prc (c,bl) | |
45 | ||
46 | let pr_elim_scheme el = | |
47 | let env = Global.env () in | |
48 | let msg = str "params := " ++ Printer.pr_rel_context env el.params in | |
49 | let env = Environ.push_rel_context el.params env in | |
50 | let msg = msg ++ fnl () ++ str "predicates := "++ Printer.pr_rel_context env el.predicates in | |
51 | let env = Environ.push_rel_context el.predicates env in | |
52 | let msg = msg ++ fnl () ++ str "branches := " ++ Printer.pr_rel_context env el.branches in | |
53 | let env = Environ.push_rel_context el.branches env in | |
54 | let msg = msg ++ fnl () ++ str "args := " ++ Printer.pr_rel_context env el.args in | |
55 | let env = Environ.push_rel_context el.args env in | |
56 | let msg = | |
57 | Util.option_fold_right | |
58 | (fun o msg -> msg ++ fnl () ++ str "indarg := " ++ Printer.pr_rel_context env [o]) | |
59 | el.indarg | |
60 | msg | |
61 | in | |
62 | let env = Util.option_fold_right (fun o env -> Environ.push_rel_context [o] env) el.indarg env in | |
63 | msg ++ fnl () ++ str "concl := " ++ Printer.pr_lconstr_env env el.concl | |
64 | ||
65 | (* The local debuging mechanism *) | |
66 | let msgnl = Pp.msgnl | |
67 | ||
68 | let observe strm = | |
69 | if do_observe () | |
70 | then Pp.msgnl strm | |
71 | else () | |
72 | ||
73 | let observennl strm = | |
74 | if do_observe () | |
75 | then begin Pp.msg strm;Pp.pp_flush () end | |
76 | else () | |
77 | ||
78 | ||
79 | let do_observe_tac s tac g = | |
80 | try let goal = begin try (Printer.pr_goal (sig_it g)) with _ -> assert false end in | |
81 | let v = tac g in msgnl (goal ++ fnl () ++ s ++(str " ")++(str "finished")); v | |
82 | with e -> | |
83 | let goal = begin try (Printer.pr_goal (sig_it g)) with _ -> assert false end in | |
84 | msgnl (str "observation "++ s++str " raised exception " ++ | |
85 | Cerrors.explain_exn e ++ str " on goal " ++ goal ); | |
86 | raise e;; | |
87 | ||
88 | ||
89 | let observe_tac s tac g = | |
90 | if do_observe () | |
91 | then do_observe_tac (str s) tac g | |
92 | else tac g | |
93 | ||
94 | (* [nf_zeta] $\zeta$-normalization of a term *) | |
95 | let nf_zeta = | |
96 | Reductionops.clos_norm_flags (Closure.RedFlags.mkflags [Closure.RedFlags.fZETA]) | |
97 | Environ.empty_env | |
98 | Evd.empty | |
99 | ||
100 | ||
101 | (* [id_to_constr id] finds the term associated to [id] in the global environment *) | |
102 | let id_to_constr id = | |
103 | try | |
104 | Tacinterp.constr_of_id (Global.env ()) id | |
105 | with Not_found -> | |
106 | raise (UserError ("",str "Cannot find " ++ Ppconstr.pr_id id)) | |
107 | ||
108 | (* [generate_type g_to_f f graph i] build the completeness (resp. correctness) lemma type if [g_to_f = true] | |
109 | (resp. g_to_f = false) where [graph] is the graph of [f] and is the [i]th function in the block. | |
110 | ||
111 | [generate_type true f i] returns | |
112 | \[\forall (x_1:t_1)\ldots(x_n:t_n), let fv := f x_1\ldots x_n in, forall res, | |
113 | graph\ x_1\ldots x_n\ res \rightarrow res = fv \] decomposed as the context and the conclusion | |
114 | ||
115 | [generate_type false f i] returns | |
116 | \[\forall (x_1:t_1)\ldots(x_n:t_n), let fv := f x_1\ldots x_n in, forall res, | |
117 | res = fv \rightarrow graph\ x_1\ldots x_n\ res\] decomposed as the context and the conclusion | |
118 | *) | |
119 | ||
120 | let generate_type g_to_f f graph i = | |
121 | (*i we deduce the number of arguments of the function and its returned type from the graph i*) | |
122 | let graph_arity = Inductive.type_of_inductive (Global.lookup_inductive (destInd graph)) in | |
123 | let ctxt,_ = decompose_prod_assum graph_arity in | |
124 | let fun_ctxt,res_type = | |
125 | match ctxt with | |
126 | | [] | [_] -> anomaly "Not a valid context" | |
127 | | (_,_,res_type)::fun_ctxt -> fun_ctxt,res_type | |
128 | in | |
129 | let nb_args = List.length fun_ctxt in | |
130 | let args_from_decl i decl = | |
131 | match decl with | |
132 | | (_,Some _,_) -> incr i; failwith "args_from_decl" | |
133 | | _ -> let j = !i in incr i;mkRel (nb_args - j + 1) | |
134 | in | |
135 | (*i We need to name the vars [res] and [fv] i*) | |
136 | let res_id = | |
137 | Termops.next_global_ident_away | |
138 | true | |
139 | (id_of_string "res") | |
140 | (map_succeed (function (Name id,_,_) -> id | (Anonymous,_,_) -> failwith "") fun_ctxt) | |
141 | in | |
142 | let fv_id = | |
143 | Termops.next_global_ident_away | |
144 | true | |
145 | (id_of_string "fv") | |
146 | (res_id::(map_succeed (function (Name id,_,_) -> id | (Anonymous,_,_) -> failwith "Anonymous!") fun_ctxt)) | |
147 | in | |
148 | (*i we can then type the argument to be applied to the function [f] i*) | |
149 | let args_as_rels = | |
150 | let i = ref 0 in | |
151 | Array.of_list ((map_succeed (args_from_decl i) (List.rev fun_ctxt))) | |
152 | in | |
153 | let args_as_rels = Array.map Termops.pop args_as_rels in | |
154 | (*i | |
155 | the hypothesis [res = fv] can then be computed | |
156 | We will need to lift it by one in order to use it as a conclusion | |
157 | i*) | |
158 | let res_eq_f_of_args = | |
159 | mkApp(Coqlib.build_coq_eq (),[|lift 2 res_type;mkRel 1;mkRel 2|]) | |
160 | in | |
161 | (*i | |
162 | The hypothesis [graph\ x_1\ldots x_n\ res] can then be computed | |
163 | We will need to lift it by one in order to use it as a conclusion | |
164 | i*) | |
165 | let graph_applied = | |
166 | let args_and_res_as_rels = | |
167 | let i = ref 0 in | |
168 | Array.of_list ((map_succeed (args_from_decl i) (List.rev ((Name res_id,None,res_type)::fun_ctxt))) ) | |
169 | in | |
170 | let args_and_res_as_rels = | |
171 | Array.mapi (fun i c -> if i <> Array.length args_and_res_as_rels - 1 then lift 1 c else c) args_and_res_as_rels | |
172 | in | |
173 | mkApp(graph,args_and_res_as_rels) | |
174 | in | |
175 | (*i The [pre_context] is the defined to be the context corresponding to | |
176 | \[\forall (x_1:t_1)\ldots(x_n:t_n), let fv := f x_1\ldots x_n in, forall res, \] | |
177 | i*) | |
178 | let pre_ctxt = | |
179 | (Name res_id,None,lift 1 res_type)::(Name fv_id,Some (mkApp(mkConst f,args_as_rels)),res_type)::fun_ctxt | |
180 | in | |
181 | (*i and we can return the solution depending on which lemma type we are defining i*) | |
182 | if g_to_f | |
183 | then (Anonymous,None,graph_applied)::pre_ctxt,(lift 1 res_eq_f_of_args) | |
184 | else (Anonymous,None,res_eq_f_of_args)::pre_ctxt,(lift 1 graph_applied) | |
185 | ||
186 | ||
187 | (* | |
188 | [find_induction_principle f] searches and returns the [body] and the [type] of [f_rect] | |
189 | ||
190 | WARNING: while convertible, [type_of body] and [type] can be non equal | |
191 | *) | |
192 | let find_induction_principle f = | |
193 | let f_as_constant = match kind_of_term f with | |
194 | | Const c' -> c' | |
195 | | _ -> error "Must be used with a function" | |
196 | in | |
197 | let infos = find_Function_infos f_as_constant in | |
198 | match infos.rect_lemma with | |
199 | | None -> raise Not_found | |
200 | | Some rect_lemma -> | |
201 | let rect_lemma = mkConst rect_lemma in | |
202 | let typ = Typing.type_of (Global.env ()) Evd.empty rect_lemma in | |
203 | rect_lemma,typ | |
204 | ||
205 | ||
206 | ||
207 | (* let fname = *) | |
208 | (* match kind_of_term f with *) | |
209 | (* | Const c' -> *) | |
210 | (* id_of_label (con_label c') *) | |
211 | (* | _ -> error "Must be used with a function" *) | |
212 | (* in *) | |
213 | ||
214 | (* let princ_name = *) | |
215 | (* ( *) | |
216 | (* Indrec.make_elimination_ident *) | |
217 | (* fname *) | |
218 | (* InType *) | |
219 | (* ) *) | |
220 | (* in *) | |
221 | (* let c = (\* mkConst(mk_from_const (destConst f) princ_name ) in *\) failwith "" in *) | |
222 | (* c,Typing.type_of (Global.env ()) Evd.empty c *) | |
223 | ||
224 | ||
225 | let rec generate_fresh_id x avoid i = | |
226 | if i == 0 | |
227 | then [] | |
228 | else | |
229 | let id = Termops.next_global_ident_away true x avoid in | |
230 | id::(generate_fresh_id x (id::avoid) (pred i)) | |
231 | ||
232 | ||
233 | (* [prove_fun_correct functional_induction funs_constr graphs_constr schemes lemmas_types_infos i ] | |
234 | is the tactic used to prove correctness lemma. | |
235 | ||
236 | [functional_induction] is the tactic defined in [indfun] (dependency problem) | |
237 | [funs_constr], [graphs_constr] [schemes] [lemmas_types_infos] are the mutually recursive functions | |
238 | (resp. graphs of the functions and principles and correctness lemma types) to prove correct. | |
239 | ||
240 | [i] is the indice of the function to prove correct | |
241 | ||
242 | The lemma to prove if suppose to have been generated by [generate_type] (in $\zeta$ normal form that is | |
243 | it looks like~: | |
244 | [\forall (x_1:t_1)\ldots(x_n:t_n), forall res, | |
245 | res = f x_1\ldots x_n in, \rightarrow graph\ x_1\ldots x_n\ res] | |
246 | ||
247 | ||
248 | The sketch of the proof is the following one~: | |
249 | \begin{enumerate} | |
250 | \item intros until $x_n$ | |
251 | \item $functional\ induction\ (f.(i)\ x_1\ldots x_n)$ using schemes.(i) | |
252 | \item for each generated branch intro [res] and [hres :res = f x_1\ldots x_n], rewrite [hres] and the | |
253 | apply the corresponding constructor of the corresponding graph inductive. | |
254 | \end{enumerate} | |
255 | ||
256 | *) | |
257 | let prove_fun_correct functional_induction funs_constr graphs_constr schemes lemmas_types_infos i : tactic = | |
258 | fun g -> | |
259 | (* first of all we recreate the lemmas types to be used as predicates of the induction principle | |
260 | that is~: | |
261 | \[fun (x_1:t_1)\ldots(x_n:t_n)=> fun fv => fun res => res = fv \rightarrow graph\ x_1\ldots x_n\ res\] | |
262 | *) | |
263 | let lemmas = | |
264 | Array.map | |
265 | (fun (_,(ctxt,concl)) -> | |
266 | match ctxt with | |
267 | | [] | [_] | [_;_] -> anomaly "bad context" | |
268 | | hres::res::(x,_,t)::ctxt -> | |
269 | Termops.it_mkLambda_or_LetIn | |
270 | ~init:(Termops.it_mkProd_or_LetIn ~init:concl [hres;res]) | |
271 | ((x,None,t)::ctxt) | |
272 | ) | |
273 | lemmas_types_infos | |
274 | in | |
275 | (* we the get the definition of the graphs block *) | |
276 | let graph_ind = destInd graphs_constr.(i) in | |
277 | let kn = fst graph_ind in | |
278 | let mib,_ = Global.lookup_inductive graph_ind in | |
279 | (* and the principle to use in this lemma in $\zeta$ normal form *) | |
280 | let f_principle,princ_type = schemes.(i) in | |
281 | let princ_type = nf_zeta princ_type in | |
282 | let princ_infos = Tactics.compute_elim_sig princ_type in | |
283 | (* The number of args of the function is then easilly computable *) | |
284 | let nb_fun_args = nb_prod (pf_concl g) - 2 in | |
285 | let args_names = generate_fresh_id (id_of_string "x") [] nb_fun_args in | |
286 | let ids = args_names@(pf_ids_of_hyps g) in | |
287 | (* Since we cannot ensure that the funcitonnal principle is defined in the | |
288 | environement and due to the bug #1174, we will need to pose the principle | |
289 | using a name | |
290 | *) | |
291 | let principle_id = Termops.next_global_ident_away true (id_of_string "princ") ids in | |
292 | let ids = principle_id :: ids in | |
293 | (* We get the branches of the principle *) | |
294 | let branches = List.rev princ_infos.branches in | |
295 | (* and built the intro pattern for each of them *) | |
296 | let intro_pats = | |
297 | List.map | |
298 | (fun (_,_,br_type) -> | |
299 | List.map | |
300 | (fun id -> Genarg.IntroIdentifier id) | |
301 | (generate_fresh_id (id_of_string "y") ids (List.length (fst (decompose_prod_assum br_type)))) | |
302 | ) | |
303 | branches | |
304 | in | |
305 | (* before building the full intro pattern for the principle *) | |
306 | let pat = Genarg.IntroOrAndPattern intro_pats in | |
307 | let eq_ind = Coqlib.build_coq_eq () in | |
308 | let eq_construct = mkConstruct((destInd eq_ind),1) in | |
309 | (* The next to referencies will be used to find out which constructor to apply in each branch *) | |
310 | let ind_number = ref 0 | |
311 | and min_constr_number = ref 0 in | |
312 | (* The tactic to prove the ith branch of the principle *) | |
313 | let prove_branche i g = | |
314 | (* We get the identifiers of this branch *) | |
315 | let this_branche_ids = | |
316 | List.fold_right | |
317 | (fun pat acc -> | |
318 | match pat with | |
319 | | Genarg.IntroIdentifier id -> Idset.add id acc | |
320 | | _ -> anomaly "Not an identifier" | |
321 | ) | |
322 | (List.nth intro_pats (pred i)) | |
323 | Idset.empty | |
324 | in | |
325 | (* and get the real args of the branch by unfolding the defined constant *) | |
326 | let pre_args,pre_tac = | |
327 | List.fold_right | |
328 | (fun (id,b,t) (pre_args,pre_tac) -> | |
329 | if Idset.mem id this_branche_ids | |
330 | then | |
331 | match b with | |
332 | | None -> (id::pre_args,pre_tac) | |
333 | | Some b -> | |
334 | (pre_args, | |
335 | tclTHEN (h_reduce (Rawterm.Unfold([[],EvalVarRef id])) allHyps) pre_tac | |
336 | ) | |
337 | ||
338 | else (pre_args,pre_tac) | |
339 | ) | |
340 | (pf_hyps g) | |
341 | ([],tclIDTAC) | |
342 | in | |
343 | (* | |
344 | We can then recompute the arguments of the constructor. | |
345 | For each [hid] introduced by this branch, if [hid] has type | |
346 | $forall res, res=fv -> graph.(j)\ x_1\ x_n res$ the corresponding arguments of the constructor are | |
347 | [ fv (hid fv (refl_equal fv)) ]. | |
348 | ||
349 | If [hid] has another type the corresponding argument of the constructor is [hid] | |
350 | *) | |
351 | let constructor_args = | |
352 | List.fold_right | |
353 | (fun hid acc -> | |
354 | let type_of_hid = pf_type_of g (mkVar hid) in | |
355 | match kind_of_term type_of_hid with | |
356 | | Prod(_,_,t') -> | |
357 | begin | |
358 | match kind_of_term t' with | |
359 | | Prod(_,t'',t''') -> | |
360 | begin | |
361 | match kind_of_term t'',kind_of_term t''' with | |
362 | | App(eq,args), App(graph',_) | |
363 | when | |
364 | (eq_constr eq eq_ind) && | |
365 | array_exists (eq_constr graph') graphs_constr -> | |
366 | ((mkApp(mkVar hid,[|args.(2);(mkApp(eq_construct,[|args.(0);args.(2)|]))|])) | |
367 | ::args.(2)::acc) | |
368 | | _ -> mkVar hid :: acc | |
369 | end | |
370 | | _ -> mkVar hid :: acc | |
371 | end | |
372 | | _ -> mkVar hid :: acc | |
373 | ) pre_args [] | |
374 | in | |
375 | (* in fact we must also add the parameters to the constructor args *) | |
376 | let constructor_args = | |
377 | let params_id = fst (list_chop princ_infos.nparams args_names) in | |
378 | (List.map mkVar params_id)@(List.rev constructor_args) | |
379 | in | |
380 | (* We then get the constructor corresponding to this branch and | |
381 | modifies the references has needed i.e. | |
382 | if the constructor is the last one of the current inductive then | |
383 | add one the number of the inductive to take and add the number of constructor of the previous | |
384 | graph to the minimal constructor number | |
385 | *) | |
386 | let constructor = | |
387 | let constructor_num = i - !min_constr_number in | |
388 | let length = Array.length (mib.Declarations.mind_packets.(!ind_number).Declarations.mind_consnames) in | |
389 | if constructor_num <= length | |
390 | then | |
391 | begin | |
392 | (kn,!ind_number),constructor_num | |
393 | end | |
394 | else | |
395 | begin | |
396 | incr ind_number; | |
397 | min_constr_number := !min_constr_number + length ; | |
398 | (kn,!ind_number),1 | |
399 | end | |
400 | in | |
401 | (* we can then build the final proof term *) | |
402 | let app_constructor = applist((mkConstruct(constructor)),constructor_args) in | |
403 | (* an apply the tactic *) | |
404 | let res,hres = | |
405 | match generate_fresh_id (id_of_string "z") (ids(* @this_branche_ids *)) 2 with | |
406 | | [res;hres] -> res,hres | |
407 | | _ -> assert false | |
408 | in | |
409 | observe (str "constructor := " ++ Printer.pr_lconstr_env (pf_env g) app_constructor); | |
410 | ( | |
411 | tclTHENSEQ | |
412 | [ | |
413 | (* unfolding of all the defined variables introduced by this branch *) | |
414 | observe_tac "unfolding" pre_tac; | |
415 | (* $zeta$ normalizing of the conclusion *) | |
416 | h_reduce | |
417 | (Rawterm.Cbv | |
418 | { Rawterm.all_flags with | |
419 | Rawterm.rDelta = false ; | |
420 | Rawterm.rConst = [] | |
421 | } | |
422 | ) | |
423 | onConcl; | |
424 | (* introducing the the result of the graph and the equality hypothesis *) | |
425 | observe_tac "introducing" (tclMAP h_intro [res;hres]); | |
426 | (* replacing [res] with its value *) | |
427 | observe_tac "rewriting res value" (Equality.rewriteLR (mkVar hres)); | |
428 | (* Conclusion *) | |
429 | observe_tac "exact" (h_exact app_constructor) | |
430 | ] | |
431 | ) | |
432 | g | |
433 | in | |
434 | (* end of branche proof *) | |
435 | let param_names = fst (list_chop princ_infos.nparams args_names) in | |
436 | let params = List.map mkVar param_names in | |
437 | let lemmas = Array.to_list (Array.map (fun c -> applist(c,params)) lemmas) in | |
438 | (* The bindings of the principle | |
439 | that is the params of the principle and the different lemma types | |
440 | *) | |
441 | let bindings = | |
442 | let params_bindings,avoid = | |
443 | List.fold_left2 | |
444 | (fun (bindings,avoid) (x,_,_) p -> | |
445 | let id = Termops.next_global_ident_away false (Nameops.out_name x) avoid in | |
446 | (dummy_loc,Rawterm.NamedHyp id,p)::bindings,id::avoid | |
447 | ) | |
448 | ([],[]) | |
449 | princ_infos.params | |
450 | (List.rev params) | |
451 | in | |
452 | let lemmas_bindings = | |
453 | List.rev (fst (List.fold_left2 | |
454 | (fun (bindings,avoid) (x,_,_) p -> | |
455 | let id = Termops.next_global_ident_away false (Nameops.out_name x) avoid in | |
456 | (dummy_loc,Rawterm.NamedHyp id,nf_zeta p)::bindings,id::avoid) | |
457 | ([],avoid) | |
458 | princ_infos.predicates | |
459 | (lemmas))) | |
460 | in | |
461 | Rawterm.ExplicitBindings (params_bindings@lemmas_bindings) | |
462 | in | |
463 | tclTHENSEQ | |
464 | [ observe_tac "intro args_names" (tclMAP h_intro args_names); | |
465 | observe_tac "principle" (forward | |
466 | (Some (h_exact f_principle)) | |
467 | (Genarg.IntroIdentifier principle_id) | |
468 | princ_type); | |
469 | tclTHEN_i | |
470 | (observe_tac "functional_induction" ( | |
471 | fun g -> | |
472 | observe | |
473 | (str "princ" ++ pr_constr_with_binding (Printer.pr_lconstr_env (pf_env g)) (mkVar principle_id,bindings)); | |
474 | functional_induction false (applist(funs_constr.(i),List.map mkVar args_names)) | |
475 | (Some (mkVar principle_id,bindings)) | |
476 | pat g | |
477 | )) | |
478 | (fun i g -> observe_tac ("proving branche "^string_of_int i) (prove_branche i) g ) | |
479 | ] | |
480 | g | |
481 | ||
482 | (* [generalize_depedent_of x hyp g] | |
483 | generalize every hypothesis which depends of [x] but [hyp] | |
484 | *) | |
485 | let generalize_depedent_of x hyp g = | |
486 | tclMAP | |
487 | (function | |
488 | | (id,None,t) when not (id = hyp) && | |
489 | (Termops.occur_var (pf_env g) x t) -> h_generalize [mkVar id] | |
490 | | _ -> tclIDTAC | |
491 | ) | |
492 | (pf_hyps g) | |
493 | g | |
494 | ||
495 | (* [prove_fun_complete funs graphs schemes lemmas_types_infos i] | |
496 | is the tactic used to prove completness lemma. | |
497 | ||
498 | [funcs], [graphs] [schemes] [lemmas_types_infos] are the mutually recursive functions | |
499 | (resp. definitions of the graphs of the functions, principles and correctness lemma types) to prove correct. | |
500 | ||
501 | [i] is the indice of the function to prove complete | |
502 | ||
503 | The lemma to prove if suppose to have been generated by [generate_type] (in $\zeta$ normal form that is | |
504 | it looks like~: | |
505 | [\forall (x_1:t_1)\ldots(x_n:t_n), forall res, | |
506 | graph\ x_1\ldots x_n\ res, \rightarrow res = f x_1\ldots x_n in] | |
507 | ||
508 | ||
509 | The sketch of the proof is the following one~: | |
510 | \begin{enumerate} | |
511 | \item intros until $H:graph\ x_1\ldots x_n\ res$ | |
512 | \item $elim\ H$ using schemes.(i) | |
513 | \item for each generated branch, intro the news hyptohesis, for each such hyptohesis [h], if [h] has | |
514 | type [x=?] with [x] a variable, then subst [x], | |
515 | if [h] has type [t=?] with [t] not a variable then rewrite [t] in the subterms, else | |
516 | if [h] is a match then destruct it, else do just introduce it, | |
517 | after all intros, the conclusion should be a reflexive equality. | |
518 | \end{enumerate} | |
519 | ||
520 | *) | |
521 | ||
522 | ||
523 | let prove_fun_complete funcs graphs schemes lemmas_types_infos i : tactic = | |
524 | fun g -> | |
525 | (* We compute the types of the different mutually recursive lemmas | |
526 | in $\zeta$ normal form | |
527 | *) | |
528 | let lemmas = | |
529 | Array.map | |
530 | (fun (_,(ctxt,concl)) -> nf_zeta (Termops.it_mkLambda_or_LetIn ~init:concl ctxt)) | |
531 | lemmas_types_infos | |
532 | in | |
533 | (* We get the constant and the principle corresponding to this lemma *) | |
534 | let f = funcs.(i) in | |
535 | let graph_principle = nf_zeta schemes.(i) in | |
536 | let princ_type = pf_type_of g graph_principle in | |
537 | let princ_infos = Tactics.compute_elim_sig princ_type in | |
538 | (* Then we get the number of argument of the function | |
539 | and compute a fresh name for each of them | |
540 | *) | |
541 | let nb_fun_args = nb_prod (pf_concl g) - 2 in | |
542 | let args_names = generate_fresh_id (id_of_string "x") [] nb_fun_args in | |
543 | let ids = args_names@(pf_ids_of_hyps g) in | |
544 | (* and fresh names for res H and the principle (cf bug bug #1174) *) | |
545 | let res,hres,graph_principle_id = | |
546 | match generate_fresh_id (id_of_string "z") ids 3 with | |
547 | | [res;hres;graph_principle_id] -> res,hres,graph_principle_id | |
548 | | _ -> assert false | |
549 | in | |
550 | let ids = res::hres::graph_principle_id::ids in | |
551 | (* we also compute fresh names for each hyptohesis of each branche of the principle *) | |
552 | let branches = List.rev princ_infos.branches in | |
553 | let intro_pats = | |
554 | List.map | |
555 | (fun (_,_,br_type) -> | |
556 | List.map | |
557 | (fun id -> id) | |
558 | (generate_fresh_id (id_of_string "y") ids (nb_prod br_type)) | |
559 | ) | |
560 | branches | |
561 | in | |
562 | let eq_ind = Coqlib.build_coq_eq () in | |
563 | (* We will need to change the function by its body | |
564 | using [f_equation] if it is recursive (that is the graph is infinite | |
565 | or unfold if the graph is finite | |
566 | *) | |
567 | let rewrite_tac j ids : tactic = | |
568 | let graph_def = graphs.(j) in | |
569 | if Rtree.is_infinite graph_def.mind_recargs | |
570 | then | |
571 | let eq_lemma = | |
572 | try out_some (find_Function_infos (destConst funcs.(j))).equation_lemma | |
573 | with Failure "out_some" | Not_found -> anomaly "Cannot find equation lemma" | |
574 | in | |
575 | tclTHENSEQ[ | |
576 | tclMAP h_intro ids; | |
577 | Equality.rewriteLR (mkConst eq_lemma); | |
578 | (* Don't forget to $\zeta$ normlize the term since the principles have been $\zeta$-normalized *) | |
579 | h_reduce | |
580 | (Rawterm.Cbv | |
581 | {Rawterm.all_flags | |
582 | with Rawterm.rDelta = false; | |
583 | }) | |
584 | onConcl | |
585 | ; | |
586 | h_generalize (List.map mkVar ids); | |
587 | thin ids | |
588 | ] | |
589 | else unfold_in_concl [([],Names.EvalConstRef (destConst f))] | |
590 | in | |
591 | (* [intros_with_rewrite] do the intros in each branch and treat each new hypothesis | |
592 | (unfolding, substituting, destructing cases \ldots) | |
593 | *) | |
594 | let rec intros_with_rewrite_aux : tactic = | |
595 | fun g -> | |
596 | match kind_of_term (pf_concl g) with | |
597 | | Prod(_,t,t') -> | |
598 | begin | |
599 | match kind_of_term t with | |
600 | | App(eq,args) when (eq_constr eq eq_ind) -> | |
601 | if isVar args.(1) | |
602 | then | |
603 | let id = pf_get_new_id (id_of_string "y") g in | |
604 | tclTHENSEQ [ h_intro id; | |
605 | generalize_depedent_of (destVar args.(1)) id; | |
606 | tclTRY (Equality.rewriteLR (mkVar id)); | |
607 | intros_with_rewrite | |
608 | ] | |
609 | g | |
610 | else | |
611 | begin | |
612 | let id = pf_get_new_id (id_of_string "y") g in | |
613 | tclTHENSEQ[ | |
614 | h_intro id; | |
615 | tclTRY (Equality.rewriteLR (mkVar id)); | |
616 | intros_with_rewrite | |
617 | ] g | |
618 | end | |
619 | | Ind _ when eq_constr t (Coqlib.build_coq_False ()) -> | |
620 | Tauto.tauto g | |
621 | | Case(_,_,v,_) -> | |
622 | tclTHENSEQ[ | |
623 | h_case (v,Rawterm.NoBindings); | |
624 | intros_with_rewrite | |
625 | ] g | |
626 | | LetIn _ -> | |
627 | tclTHENSEQ[ | |
628 | h_reduce | |
629 | (Rawterm.Cbv | |
630 | {Rawterm.all_flags | |
631 | with Rawterm.rDelta = false; | |
632 | }) | |
633 | onConcl | |
634 | ; | |
635 | intros_with_rewrite | |
636 | ] g | |
637 | | _ -> | |
638 | let id = pf_get_new_id (id_of_string "y") g in | |
639 | tclTHENSEQ [ h_intro id;intros_with_rewrite] g | |
640 | end | |
641 | | LetIn _ -> | |
642 | tclTHENSEQ[ | |
643 | h_reduce | |
644 | (Rawterm.Cbv | |
645 | {Rawterm.all_flags | |
646 | with Rawterm.rDelta = false; | |
647 | }) | |
648 | onConcl | |
649 | ; | |
650 | intros_with_rewrite | |
651 | ] g | |
652 | | _ -> tclIDTAC g | |
653 | and intros_with_rewrite g = | |
654 | observe_tac "intros_with_rewrite" intros_with_rewrite_aux g | |
655 | in | |
656 | (* The proof of each branche itself *) | |
657 | let ind_number = ref 0 in | |
658 | let min_constr_number = ref 0 in | |
659 | let prove_branche i g = | |
660 | (* we fist compute the inductive corresponding to the branch *) | |
661 | let this_ind_number = | |
662 | let constructor_num = i - !min_constr_number in | |
663 | let length = Array.length (graphs.(!ind_number).Declarations.mind_consnames) in | |
664 | if constructor_num <= length | |
665 | then !ind_number | |
666 | else | |
667 | begin | |
668 | incr ind_number; | |
669 | min_constr_number := !min_constr_number + length; | |
670 | !ind_number | |
671 | end | |
672 | in | |
673 | let this_branche_ids = List.nth intro_pats (pred i) in | |
674 | tclTHENSEQ[ | |
675 | (* we expand the definition of the function *) | |
676 | observe_tac "rewrite_tac" (rewrite_tac this_ind_number this_branche_ids); | |
677 | (* introduce hypothesis with some rewrite *) | |
678 | (intros_with_rewrite); | |
679 | (* The proof is complete *) | |
680 | observe_tac "reflexivity" (reflexivity) | |
681 | ] | |
682 | g | |
683 | in | |
684 | let params_names = fst (list_chop princ_infos.nparams args_names) in | |
685 | let params = List.map mkVar params_names in | |
686 | tclTHENSEQ | |
687 | [ tclMAP h_intro (args_names@[res;hres]); | |
688 | observe_tac "h_generalize" | |
689 | (h_generalize [mkApp(applist(graph_principle,params),Array.map (fun c -> applist(c,params)) lemmas)]); | |
690 | h_intro graph_principle_id; | |
691 | observe_tac "" (tclTHEN_i | |
692 | (observe_tac "elim" ((elim (mkVar hres,Rawterm.NoBindings) (Some (mkVar graph_principle_id,Rawterm.NoBindings))))) | |
693 | (fun i g -> prove_branche i g )) | |
694 | ] | |
695 | g | |
696 | ||
697 | ||
698 | ||
699 | ||
700 | let do_save () = Command.save_named false | |
701 | ||
702 | ||
703 | (* [derive_correctness make_scheme functional_induction funs graphs] create correctness and completeness | |
704 | lemmas for each function in [funs] w.r.t. [graphs] | |
705 | ||
706 | [make_scheme] is Functional_principle_types.make_scheme (dependency pb) and | |
707 | [functional_induction] is Indfun.functional_induction (same pb) | |
708 | *) | |
709 | ||
710 | let derive_correctness make_scheme functional_induction (funs: constant list) (graphs:inductive list) = | |
711 | let funs = Array.of_list funs and graphs = Array.of_list graphs in | |
712 | let funs_constr = Array.map mkConst funs in | |
713 | try | |
714 | let graphs_constr = Array.map mkInd graphs in | |
715 | let lemmas_types_infos = | |
716 | Util.array_map2_i | |
717 | (fun i f_constr graph -> | |
718 | let const_of_f = destConst f_constr in | |
719 | let (type_of_lemma_ctxt,type_of_lemma_concl) as type_info = | |
720 | generate_type false const_of_f graph i | |
721 | in | |
722 | let type_of_lemma = Termops.it_mkProd_or_LetIn ~init:type_of_lemma_concl type_of_lemma_ctxt in | |
723 | let type_of_lemma = nf_zeta type_of_lemma in | |
724 | observe (str "type_of_lemma := " ++ Printer.pr_lconstr type_of_lemma); | |
725 | type_of_lemma,type_info | |
726 | ) | |
727 | funs_constr | |
728 | graphs_constr | |
729 | in | |
730 | let schemes = | |
731 | (* The functional induction schemes are computed and not saved if there is more that one function | |
732 | if the block contains only one function we can safely reuse [f_rect] | |
733 | *) | |
734 | try | |
735 | if Array.length funs_constr <> 1 then raise Not_found; | |
736 | [| find_induction_principle funs_constr.(0) |] | |
737 | with Not_found -> | |
738 | Array.of_list | |
739 | (List.map | |
740 | (fun entry -> | |
741 | (entry.Entries.const_entry_body, out_some entry.Entries.const_entry_type ) | |
742 | ) | |
743 | (make_scheme (array_map_to_list (fun const -> const,Rawterm.RType None) funs)) | |
744 | ) | |
745 | in | |
746 | let proving_tac = | |
747 | prove_fun_correct functional_induction funs_constr graphs_constr schemes lemmas_types_infos | |
748 | in | |
749 | Array.iteri | |
750 | (fun i f_as_constant -> | |
751 | let f_id = id_of_label (con_label f_as_constant) in | |
752 | Command.start_proof | |
753 | (*i The next call to mk_correct_id is valid since we are constructing the lemma | |
754 | Ensures by: obvious | |
755 | i*) | |
756 | (mk_correct_id f_id) | |
757 | (Decl_kinds.Global,(Decl_kinds.Proof Decl_kinds.Theorem)) | |
758 | (fst lemmas_types_infos.(i)) | |
759 | (fun _ _ -> ()); | |
760 | Pfedit.by (observe_tac ("procve correctness ("^(string_of_id f_id)^")") (proving_tac i)); | |
761 | do_save (); | |
762 | let finfo = find_Function_infos f_as_constant in | |
763 | update_Function | |
764 | {finfo with | |
765 | correctness_lemma = Some (destConst (Tacinterp.constr_of_id (Global.env ())(mk_correct_id f_id))) | |
766 | } | |
767 | ||
768 | ) | |
769 | funs; | |
770 | let lemmas_types_infos = | |
771 | Util.array_map2_i | |
772 | (fun i f_constr graph -> | |
773 | let const_of_f = destConst f_constr in | |
774 | let (type_of_lemma_ctxt,type_of_lemma_concl) as type_info = | |
775 | generate_type true const_of_f graph i | |
776 | in | |
777 | let type_of_lemma = Termops.it_mkProd_or_LetIn ~init:type_of_lemma_concl type_of_lemma_ctxt in | |
778 | let type_of_lemma = nf_zeta type_of_lemma in | |
779 | observe (str "type_of_lemma := " ++ Printer.pr_lconstr type_of_lemma); | |
780 | type_of_lemma,type_info | |
781 | ) | |
782 | funs_constr | |
783 | graphs_constr | |
784 | in | |
785 | let kn,_ as graph_ind = destInd graphs_constr.(0) in | |
786 | let mib,mip = Global.lookup_inductive graph_ind in | |
787 | let schemes = | |
788 | Array.of_list | |
789 | (Indrec.build_mutual_indrec (Global.env ()) Evd.empty | |
790 | (Array.to_list | |
791 | (Array.mapi | |
792 | (fun i mip -> (kn,i),mib,mip,true,InType) | |
793 | mib.Declarations.mind_packets | |
794 | ) | |
795 | ) | |
796 | ) | |
797 | in | |
798 | let proving_tac = | |
799 | prove_fun_complete funs_constr mib.Declarations.mind_packets schemes lemmas_types_infos | |
800 | in | |
801 | Array.iteri | |
802 | (fun i f_as_constant -> | |
803 | let f_id = id_of_label (con_label f_as_constant) in | |
804 | Command.start_proof | |
805 | (*i The next call to mk_complete_id is valid since we are constructing the lemma | |
806 | Ensures by: obvious | |
807 | i*) | |
808 | (mk_complete_id f_id) | |
809 | (Decl_kinds.Global,(Decl_kinds.Proof Decl_kinds.Theorem)) | |
810 | (fst lemmas_types_infos.(i)) | |
811 | (fun _ _ -> ()); | |
812 | Pfedit.by (observe_tac ("prove completeness ("^(string_of_id f_id)^")") (proving_tac i)); | |
813 | do_save (); | |
814 | let finfo = find_Function_infos f_as_constant in | |
815 | update_Function | |
816 | {finfo with | |
817 | completeness_lemma = Some (destConst (Tacinterp.constr_of_id (Global.env ())(mk_complete_id f_id))) | |
818 | } | |
819 | ) | |
820 | funs; | |
821 | with e -> | |
822 | (* In case of problem, we reset all the lemmas *) | |
823 | (*i The next call to mk_correct_id is valid since we are erasing the lemmas | |
824 | Ensures by: obvious | |
825 | i*) | |
826 | let first_lemma_id = | |
827 | let f_id = id_of_label (con_label funs.(0)) in | |
828 | ||
829 | mk_correct_id f_id | |
830 | in | |
831 | ignore(try Vernacentries.vernac_reset_name (Util.dummy_loc,first_lemma_id) with _ -> ()); | |
832 | raise e | |
833 | ||
834 | ||
835 | ||
836 | ||
837 | ||
838 | (***********************************************) | |
839 | ||
840 | (* [revert_graph kn post_tac hid] transforme an hypothesis [hid] having type Ind(kn,num) t1 ... tn res | |
841 | when [kn] denotes a graph block into | |
842 | f_num t1... tn = res (by applying [f_complete] to the first type) before apply post_tac on the result | |
843 | ||
844 | if the type of hypothesis has not this form or if we cannot find the completeness lemma then we do nothing | |
845 | *) | |
846 | let revert_graph kn post_tac hid g = | |
847 | let typ = pf_type_of g (mkVar hid) in | |
848 | match kind_of_term typ with | |
849 | | App(i,args) when isInd i -> | |
850 | let ((kn',num) as ind') = destInd i in | |
851 | if kn = kn' | |
852 | then (* We have generated a graph hypothesis so that we must change it if we can *) | |
853 | let info = | |
854 | try find_Function_of_graph ind' | |
855 | with Not_found -> (* The graphs are mutually recursive but we cannot find one of them !*) | |
856 | anomaly "Cannot retrieve infos about a mutual block" | |
857 | in | |
858 | (* if we can find a completeness lemma for this function | |
859 | then we can come back to the functional form. If not, we do nothing | |
860 | *) | |
861 | match info.completeness_lemma with | |
862 | | None -> tclIDTAC g | |
863 | | Some f_complete -> | |
864 | let f_args,res = array_chop (Array.length args - 1) args in | |
865 | tclTHENSEQ | |
866 | [ | |
867 | h_generalize [applist(mkConst f_complete,(Array.to_list f_args)@[res.(0);mkVar hid])]; | |
868 | thin [hid]; | |
869 | h_intro hid; | |
870 | post_tac hid | |
871 | ] | |
872 | g | |
873 | ||
874 | else tclIDTAC g | |
875 | | _ -> tclIDTAC g | |
876 | ||
877 | ||
878 | (* | |
879 | [functional_inversion hid fconst f_correct ] is the functional version of [inversion] | |
880 | ||
881 | [hid] is the hypothesis to invert, [fconst] is the function to invert and [f_correct] | |
882 | is the correctness lemma for [fconst]. | |
883 | ||
884 | The sketch is the follwing~: | |
885 | \begin{enumerate} | |
886 | \item Transforms the hypothesis [hid] such that its type is now $res\ =\ f\ t_1 \ldots t_n$ | |
887 | (fails if it is not possible) | |
888 | \item replace [hid] with $R\_f t_1 \ldots t_n res$ using [f_correct] | |
889 | \item apply [inversion] on [hid] | |
890 | \item finally in each branch, replace each hypothesis [R\_f ..] by [f ...] using [f_complete] (whenever | |
891 | such a lemma exists) | |
892 | \end{enumerate} | |
893 | *) | |
894 | ||
895 | let functional_inversion kn hid fconst f_correct : tactic = | |
31 | 896 | fun g -> |
32 | if nb_prod (pf_concl g) <= n then tac (List.rev acc) g | |
33 | else | |
34 | tclTHEN | |
35 | intro | |
36 | (fun g' -> | |
37 | let id,_,t = pf_last_hyp g' in | |
38 | tclORELSE | |
39 | (tclABSTRACT None (Extratactics.h_discrHyp (Rawterm.NamedHyp id))) | |
40 | (intro_discr_until ((id,t)::acc)) | |
41 | g' | |
42 | ) | |
43 | g | |
897 | let old_ids = List.fold_right Idset.add (pf_ids_of_hyps g) Idset.empty in | |
898 | let type_of_h = pf_type_of g (mkVar hid) in | |
899 | match kind_of_term type_of_h with | |
900 | | App(eq,args) when eq_constr eq (Coqlib.build_coq_eq ()) -> | |
901 | let pre_tac,f_args,res = | |
902 | match kind_of_term args.(1),kind_of_term args.(2) with | |
903 | | App(f,f_args),_ when eq_constr f fconst -> | |
904 | ((fun hid -> h_symmetry (onHyp hid)),f_args,args.(2)) | |
905 | |_,App(f,f_args) when eq_constr f fconst -> | |
906 | ((fun hid -> tclIDTAC),f_args,args.(1)) | |
907 | | _ -> (fun hid -> tclFAIL 1 (mt ())),[||],args.(2) | |
908 | in | |
909 | tclTHENSEQ[ | |
910 | pre_tac hid; | |
911 | h_generalize [applist(f_correct,(Array.to_list f_args)@[res;mkVar hid])]; | |
912 | thin [hid]; | |
913 | h_intro hid; | |
914 | Inv.inv FullInversion Genarg.IntroAnonymous (Rawterm.NamedHyp hid); | |
915 | (fun g -> | |
916 | let new_ids = List.filter (fun id -> not (Idset.mem id old_ids)) (pf_ids_of_hyps g) in | |
917 | tclMAP (revert_graph kn pre_tac) (hid::new_ids) g | |
918 | ); | |
919 | ] g | |
920 | | _ -> tclFAIL 1 (mt ()) g | |
921 | ||
922 | ||
923 | ||
924 | let invfun qhyp f = | |
925 | let f = | |
926 | match f with | |
927 | | ConstRef f -> f | |
928 | | _ -> raise (Util.UserError("",str "Not a function")) | |
44 | 929 | in |
45 | intro_discr_until [] | |
46 | ||
47 | ||
48 | let rec discr_rew_in_H hypname idl : tactic = | |
49 | match idl with | |
50 | | [] -> (Extratactics.h_discrHyp (Rawterm.NamedHyp hypname)) | |
51 | | ((id,t)::idl') -> | |
52 | match kind_of_term t with | |
53 | | App(eq',[| _ ; arg1 ; _ |]) when eq_constr eq' (Lazy.force eq) -> | |
54 | begin | |
55 | let constr,_ = decompose_app arg1 in | |
56 | if isConstruct constr | |
57 | then | |
58 | (discr_rew_in_H hypname idl') | |
59 | else | |
60 | tclTHEN | |
61 | (tclTRY (Equality.general_rewrite_in true hypname (mkVar id))) | |
62 | (discr_rew_in_H hypname idl') | |
63 | end | |
64 | | _ -> discr_rew_in_H hypname idl' | |
65 | ||
66 | let finalize fname hypname idl : tactic = | |
67 | tclTRY ( | |
68 | (tclTHEN | |
69 | (Hiddentac.h_reduce | |
70 | (Rawterm.Unfold [[],EvalConstRef fname]) | |
71 | (Tacticals.onHyp hypname) | |
72 | ) | |
73 | (discr_rew_in_H hypname idl) | |
74 | )) | |
75 | ||
76 | let gen_fargs fargs : tactic = | |
77 | fun g -> | |
78 | generalize | |
79 | (List.map | |
80 | (fun arg -> | |
81 | let targ = pf_type_of g arg in | |
82 | let refl_arg = mkApp (Lazy.force refl_equal , [|targ ; arg|]) in | |
83 | refl_arg | |
84 | ) | |
85 | (Array.to_list fargs) | |
86 | ) | |
87 | g | |
88 | ||
89 | ||
90 | let invfun (hypname:identifier) fname princ : tactic= | |
91 | fun g -> | |
92 | let nprod_goal = nb_prod (pf_concl g) in | |
93 | let princ_info = | |
94 | let princ_type = | |
95 | (try (match (Global.lookup_constant princ) with | |
96 | {Declarations.const_type=t} -> t | |
97 | ) | |
98 | with _ -> assert false) | |
99 | in | |
100 | Tactics.compute_elim_sig princ_type | |
101 | in | |
102 | let _,_,typhyp = List.find (fun (id,_,_) -> hypname=id) (pf_hyps g) in | |
103 | let do_invert fargs appf : tactic = | |
104 | let frealargs = (snd (array_chop (List.length princ_info.params) fargs)) | |
105 | in | |
106 | let pat_args = | |
107 | (List.map (fun e -> ([Rawterm.ArgArg (-1)],e)) (Array.to_list frealargs)) @ [[],appf] | |
108 | in | |
109 | tclTHENSEQ | |
110 | [ | |
111 | gen_fargs frealargs; | |
112 | tac_pattern pat_args; | |
113 | Hiddentac.h_apply (mkConst princ,Rawterm.NoBindings); | |
114 | intro_discr_until nprod_goal (finalize fname hypname) | |
115 | ||
116 | ] | |
117 | in | |
118 | match kind_of_term typhyp with | |
119 | | App(eq',[| _ ; arg1 ; arg2 |]) when eq_constr eq' (Lazy.force eq) -> | |
120 | (* let valf = def_of_const (mkConst fname) in *) | |
121 | let eq_arg1 , eq_arg2 , good_eq_form , fargs = | |
122 | match kind_of_term arg1 , kind_of_term arg2 with | |
123 | | App(f, args),_ when eq_constr f (mkConst fname) -> | |
124 | arg1 , arg2 , tclIDTAC , args | |
125 | | _,App(f, args) when eq_constr f (mkConst fname) -> | |
126 | arg2 , arg1 , symmetry_in hypname , args | |
127 | | _ , _ -> error "inversion impossible" | |
128 | in | |
129 | tclTHEN | |
130 | good_eq_form | |
131 | (do_invert fargs eq_arg1) | |
132 | g | |
133 | | App(f',fargs) when eq_constr f' (mkConst fname) -> | |
134 | do_invert fargs typhyp g | |
135 | ||
136 | ||
137 | | _ -> error "inversion impossible" | |
138 | ||
930 | try | |
931 | let finfos = find_Function_infos f in | |
932 | let f_correct = mkConst(out_some finfos.correctness_lemma) | |
933 | and kn = fst finfos.graph_ind | |
934 | in | |
935 | Tactics.try_intros_until (fun hid -> functional_inversion kn hid (mkConst f) f_correct) qhyp | |
936 | with | |
937 | | Not_found -> error "No graph found" | |
938 | | Failure "out_some" -> error "Cannot use equivalence with graph!" | |
939 | ||
940 | ||
941 | let invfun qhyp f g = | |
942 | match f with | |
943 | | Some f -> invfun qhyp f g | |
944 | | None -> | |
945 | Tactics.try_intros_until | |
946 | (fun hid g -> | |
947 | let hyp_typ = pf_type_of g (mkVar hid) in | |
948 | match kind_of_term hyp_typ with | |
949 | | App(eq,args) when eq_constr eq (Coqlib.build_coq_eq ()) -> | |
950 | begin | |
951 | let f1,_ = decompose_app args.(1) in | |
952 | try | |
953 | if not (isConst f1) then failwith ""; | |
954 | let finfos = find_Function_infos (destConst f1) in | |
955 | let f_correct = mkConst(out_some finfos.correctness_lemma) | |
956 | and kn = fst finfos.graph_ind | |
957 | in | |
958 | functional_inversion kn hid f1 f_correct g | |
959 | with | Failure "" | Failure "out_some" | Not_found -> | |
960 | try | |
961 | let f2,_ = decompose_app args.(2) in | |
962 | if not (isConst f2) then failwith ""; | |
963 | let finfos = find_Function_infos (destConst f2) in | |
964 | let f_correct = mkConst(out_some finfos.correctness_lemma) | |
965 | and kn = fst finfos.graph_ind | |
966 | in | |
967 | functional_inversion kn hid f2 f_correct g | |
968 | with | |
969 | | Failure "" -> | |
970 | errorlabstrm "" (Ppconstr.pr_id hid ++ str " must contain at leat one function") | |
971 | | Failure "out_some" -> | |
972 | error "Cannot use equivalence with graph for any side of equality" | |
973 | | Not_found -> error "No graph found for any side of equality" | |
974 | end | |
975 | | _ -> errorlabstrm "" (Ppconstr.pr_id hid ++ str " must be an equality ") | |
976 | ) | |
977 | qhyp | |
978 | g |
8 | 8 | open Rawtermops |
9 | 9 | |
10 | 10 | let observe strm = |
11 | if Tacinterp.get_debug () <> Tactic_debug.DebugOff && false | |
11 | if do_observe () | |
12 | 12 | then Pp.msgnl strm |
13 | 13 | else () |
14 | 14 | let observennl strm = |
15 | if Tacinterp.get_debug () <> Tactic_debug.DebugOff &&false | |
15 | if do_observe () | |
16 | 16 | then Pp.msg strm |
17 | 17 | else () |
18 | 18 | |
43 | 43 | (* |
44 | 44 | The main part deals with building a list of raw constructor expressions |
45 | 45 | from the rhs of a fixpoint equation. |
46 | ||
47 | ||
48 | 46 | *) |
49 | ||
50 | ||
51 | 47 | |
52 | 48 | type 'a build_entry_pre_return = |
53 | 49 | { |
60 | 56 | result : 'a build_entry_pre_return list; |
61 | 57 | to_avoid : identifier list |
62 | 58 | } |
63 | ||
64 | 59 | |
65 | 60 | (* |
66 | 61 | [combine_results combine_fun res1 res2] combine two results [res1] and [res2] |
112 | 107 | let ids_of_binder = function |
113 | 108 | | LetIn Anonymous | Prod Anonymous | Lambda Anonymous -> [] |
114 | 109 | | LetIn (Name id) | Prod (Name id) | Lambda (Name id) -> [id] |
115 | (* | LetTuple(nal,_) -> *) | |
116 | (* map_succeed (function Name id -> id | _ -> failwith "ids_of_binder") nal *) | |
117 | 110 | |
118 | 111 | let rec change_vars_in_binder mapping = function |
119 | 112 | [] -> [] |
215 | 208 | (* Note that the binding context of [args] MUST be placed before the one of |
216 | 209 | the applied value in order to preserve possible type dependencies |
217 | 210 | *) |
218 | ||
219 | 211 | context = args.context@new_ctxt; |
220 | 212 | value = new_value; |
221 | 213 | } |
244 | 236 | ; |
245 | 237 | to_avoid = avoid |
246 | 238 | } |
247 | ||
248 | ||
239 | (************************************************* | |
240 | Some functions to deal with overlapping patterns | |
241 | **************************************************) | |
242 | ||
243 | let coq_True_ref = | |
244 | lazy (Coqlib.gen_reference "" ["Init";"Logic"] "True") | |
245 | ||
246 | let coq_False_ref = | |
247 | lazy (Coqlib.gen_reference "" ["Init";"Logic"] "False") | |
248 | ||
249 | (* | |
250 | [make_discr_match_el \[e1,...en\]] builds match e1,...,en with | |
251 | (the list of expresions on which we will do the matching) | |
252 | *) | |
249 | 253 | let make_discr_match_el = |
250 | 254 | List.map (fun e -> (e,(Anonymous,None))) |
251 | 255 | |
252 | let coq_True_ref = | |
253 | lazy (Coqlib.gen_reference "" ["Init";"Logic"] "True") | |
254 | ||
255 | let coq_False_ref = | |
256 | lazy (Coqlib.gen_reference "" ["Init";"Logic"] "False") | |
257 | ||
256 | (* | |
257 | [make_discr_match_brl i \[pat_1,...,pat_n\]] constructs a discrimination pattern matching on the ith expression. | |
258 | that is. | |
259 | match ?????? with \\ | |
260 | | pat_1 => False \\ | |
261 | | pat_{i-1} => False \\ | |
262 | | pat_i => True \\ | |
263 | | pat_{i+1} => False \\ | |
264 | \vdots | |
265 | | pat_n => False | |
266 | end | |
267 | *) | |
258 | 268 | let make_discr_match_brl i = |
259 | 269 | list_map_i |
260 | 270 | (fun j (_,idl,patl,_) -> |
263 | 273 | else (dummy_loc,idl,patl, mkRRef (Lazy.force coq_False_ref)) |
264 | 274 | ) |
265 | 275 | 0 |
266 | ||
276 | (* | |
277 | [make_discr_match brl el i] generates an hypothesis such that it reduce to true iff | |
278 | brl_{i} is the first branch matched by [el] | |
279 | ||
280 | Used when we want to simulate the coq pattern matching algorithm | |
281 | *) | |
267 | 282 | let make_discr_match brl = |
268 | 283 | fun el i -> |
269 | 284 | mkRCases(None, |
270 | 285 | make_discr_match_el el, |
271 | 286 | make_discr_match_brl i brl) |
272 | ||
273 | ||
274 | ||
275 | let rec make_pattern_eq_precond id e pat : identifier * (binder_type * Rawterm.rawconstr) list = | |
276 | match pat with | |
277 | | PatVar(_,Anonymous) -> assert false | |
278 | | PatVar(_,Name x) -> | |
279 | id,[Prod (Name x),mkRHole ();Prod Anonymous,raw_make_eq (mkRVar x) e] | |
280 | | PatCstr(_,constr,patternl,_) -> | |
281 | let new_id,new_patternl,patternl_eq_precond = | |
282 | List.fold_right | |
283 | (fun pat' (id,new_patternl,preconds) -> | |
284 | match pat' with | |
285 | | PatVar (_,Name id) -> (id,id::new_patternl,preconds) | |
286 | | _ -> | |
287 | let new_id = Nameops.lift_ident id in | |
288 | let new_id',pat'_precond = | |
289 | make_pattern_eq_precond new_id (mkRVar id) pat' | |
290 | in | |
291 | (new_id',id::new_patternl,preconds@pat'_precond) | |
292 | ) | |
293 | patternl | |
294 | (id,[],[]) | |
295 | in | |
296 | let cst_narg = | |
297 | Inductiveops.mis_constructor_nargs_env | |
298 | (Global.env ()) | |
299 | constr | |
300 | in | |
301 | let implicit_args = | |
302 | Array.to_list | |
303 | (Array.init | |
304 | (cst_narg - List.length patternl) | |
305 | (fun _ -> mkRHole ()) | |
306 | ) | |
307 | in | |
308 | let cst_as_term = | |
309 | mkRApp(mkRRef(Libnames.ConstructRef constr), | |
310 | implicit_args@(List.map mkRVar new_patternl) | |
311 | ) | |
312 | in | |
313 | let precond' = | |
314 | (Prod Anonymous, raw_make_eq cst_as_term e)::patternl_eq_precond | |
315 | in | |
316 | let precond'' = | |
317 | List.fold_right | |
318 | (fun id acc -> | |
319 | (Prod (Name id),(mkRHole ()))::acc | |
320 | ) | |
321 | new_patternl | |
322 | precond' | |
323 | in | |
324 | new_id,precond'' | |
325 | 287 | |
326 | 288 | let pr_name = function |
327 | 289 | | Name id -> Ppconstr.pr_id id |
328 | 290 | | Anonymous -> str "_" |
329 | 291 | |
330 | let make_pattern_eq_precond id e pat = | |
331 | let res = make_pattern_eq_precond id e pat in | |
332 | observe | |
333 | (prlist_with_sep spc | |
334 | (function (Prod na,t) -> | |
335 | str "forall " ++ pr_name na ++ str ":" ++ pr_rawconstr t | |
336 | | _ -> assert false | |
337 | ) | |
338 | (snd res) | |
339 | ); | |
340 | res | |
341 | ||
342 | ||
343 | let build_constructors_of_type msg ind' argl = | |
292 | (**********************************************************************) | |
293 | (* functions used to build case expression from lettuple and if ones *) | |
294 | (**********************************************************************) | |
295 | ||
296 | (* [build_constructors_of_type] construct the array of pattern of its inductive argument*) | |
297 | let build_constructors_of_type ind' argl = | |
344 | 298 | let (mib,ind) = Inductive.lookup_mind_specif (Global.env()) ind' in |
345 | 299 | let npar = mib.Declarations.mind_nparams in |
346 | 300 | Array.mapi (fun i _ -> |
365 | 319 | let pat_as_term = |
366 | 320 | mkRApp(mkRRef (ConstructRef(ind',i+1)),argl) |
367 | 321 | in |
368 | (* Pp.msgnl (str "new constructor := " ++ Printer.pr_rawconstr pat_as_term); *) | |
369 | 322 | cases_pattern_of_rawconstr Anonymous pat_as_term |
370 | 323 | ) |
371 | 324 | ind.Declarations.mind_consnames |
372 | 325 | |
373 | let find_constructors_of_raw_type msg t argl : Rawterm.cases_pattern array = | |
374 | let ind,args = raw_decompose_app t in | |
375 | match ind with | |
376 | | RRef(_,IndRef ind') -> | |
377 | (* let _,ind = Global.lookup_inductive ind' in *) | |
378 | build_constructors_of_type msg ind' argl | |
379 | | _ -> error msg | |
380 | ||
381 | ||
382 | ||
326 | (* [find_type_of] very naive attempts to discover the type of an if or a letin *) | |
383 | 327 | let rec find_type_of nb b = |
384 | 328 | let f,_ = raw_decompose_app b in |
385 | 329 | match f with |
411 | 355 | | _ -> raise (Invalid_argument "not a ref") |
412 | 356 | |
413 | 357 | |
414 | let rec build_entry_lc funnames avoid rt : rawconstr build_entry_return = | |
415 | (* Pp.msgnl (str " Entering : " ++ Printer.pr_rawconstr rt); *) | |
358 | ||
359 | ||
360 | (******************) | |
361 | (* Main functions *) | |
362 | (******************) | |
363 | ||
364 | ||
365 | ||
366 | let raw_push_named (na,raw_value,raw_typ) env = | |
367 | match na with | |
368 | | Anonymous -> env | |
369 | | Name id -> | |
370 | let value = Util.option_map (Pretyping.Default.understand Evd.empty env) raw_value in | |
371 | let typ = Pretyping.Default.understand_type Evd.empty env raw_typ in | |
372 | Environ.push_named (id,value,typ) env | |
373 | ||
374 | ||
375 | let add_pat_variables pat typ env : Environ.env = | |
376 | let rec add_pat_variables env pat typ : Environ.env = | |
377 | observe (str "new rel env := " ++ Printer.pr_rel_context_of env); | |
378 | ||
379 | match pat with | |
380 | | PatVar(_,na) -> Environ.push_rel (na,None,typ) env | |
381 | | PatCstr(_,c,patl,na) -> | |
382 | let Inductiveops.IndType(indf,indargs) = | |
383 | try Inductiveops.find_rectype env Evd.empty typ | |
384 | with Not_found -> assert false | |
385 | in | |
386 | let constructors = Inductiveops.get_constructors env indf in | |
387 | let constructor : Inductiveops.constructor_summary = List.find (fun cs -> cs.Inductiveops.cs_cstr = c) (Array.to_list constructors) in | |
388 | let cs_args_types :types list = List.map (fun (_,_,t) -> t) constructor.Inductiveops.cs_args in | |
389 | List.fold_left2 add_pat_variables env patl (List.rev cs_args_types) | |
390 | in | |
391 | let new_env = add_pat_variables env pat typ in | |
392 | let res = | |
393 | fst ( | |
394 | Sign.fold_rel_context | |
395 | (fun (na,v,t) (env,ctxt) -> | |
396 | match na with | |
397 | | Anonymous -> assert false | |
398 | | Name id -> | |
399 | let new_t = substl ctxt t in | |
400 | let new_v = option_map (substl ctxt) v in | |
401 | observe (str "for variable " ++ Ppconstr.pr_id id ++ fnl () ++ | |
402 | str "old type := " ++ Printer.pr_lconstr t ++ fnl () ++ | |
403 | str "new type := " ++ Printer.pr_lconstr new_t ++ fnl () ++ | |
404 | option_fold_right (fun v _ -> str "old value := " ++ Printer.pr_lconstr v ++ fnl ()) v (mt ()) ++ | |
405 | option_fold_right (fun v _ -> str "new value := " ++ Printer.pr_lconstr v ++ fnl ()) new_v (mt ()) | |
406 | ); | |
407 | (Environ.push_named (id,new_v,new_t) env,mkVar id::ctxt) | |
408 | ) | |
409 | (Environ.rel_context new_env) | |
410 | ~init:(env,[]) | |
411 | ) | |
412 | in | |
413 | observe (str "new var env := " ++ Printer.pr_named_context_of res); | |
414 | res | |
415 | ||
416 | ||
417 | ||
418 | ||
419 | let rec pattern_to_term_and_type env typ = function | |
420 | | PatVar(loc,Anonymous) -> assert false | |
421 | | PatVar(loc,Name id) -> | |
422 | mkRVar id | |
423 | | PatCstr(loc,constr,patternl,_) -> | |
424 | let cst_narg = | |
425 | Inductiveops.mis_constructor_nargs_env | |
426 | (Global.env ()) | |
427 | constr | |
428 | in | |
429 | let Inductiveops.IndType(indf,indargs) = | |
430 | try Inductiveops.find_rectype env Evd.empty typ | |
431 | with Not_found -> assert false | |
432 | in | |
433 | let constructors = Inductiveops.get_constructors env indf in | |
434 | let constructor = List.find (fun cs -> cs.Inductiveops.cs_cstr = constr) (Array.to_list constructors) in | |
435 | let cs_args_types :types list = List.map (fun (_,_,t) -> t) constructor.Inductiveops.cs_args in | |
436 | let _,cstl = Inductiveops.dest_ind_family indf in | |
437 | let csta = Array.of_list cstl in | |
438 | let implicit_args = | |
439 | Array.to_list | |
440 | (Array.init | |
441 | (cst_narg - List.length patternl) | |
442 | (fun i -> Detyping.detype false [] (Termops.names_of_rel_context env) csta.(i)) | |
443 | ) | |
444 | in | |
445 | let patl_as_term = | |
446 | List.map2 (pattern_to_term_and_type env) (List.rev cs_args_types) patternl | |
447 | in | |
448 | mkRApp(mkRRef(Libnames.ConstructRef constr), | |
449 | implicit_args@patl_as_term | |
450 | ) | |
451 | ||
452 | (* [build_entry_lc funnames avoid rt] construct the list (in fact a build_entry_return) | |
453 | of constructors corresponding to [rt] when replacing calls to [funnames] by calls to the | |
454 | corresponding graphs. | |
455 | ||
456 | ||
457 | The idea to transform a term [t] into a list of constructors [lc] is the following: | |
458 | \begin{itemize} | |
459 | \item if the term is a binder (bind x, body) then first compute [lc'] the list corresponding | |
460 | to [body] and add (bind x. _) to each elements of [lc] | |
461 | \item if the term has the form (g t1 ... ... tn) where g does not appears in (fnames) | |
462 | then compute [lc1] ... [lcn] the lists of constructors corresponding to [t1] ... [tn], | |
463 | then combine those lists and [g] as follows~: for each element [c1,...,cn] of [lc1\times...\times lcn], | |
464 | [g c1 ... cn] is an element of [lc] | |
465 | \item if the term has the form (f t1 .... tn) where [f] appears in [fnames] then | |
466 | compute [lc1] ... [lcn] the lists of constructors corresponding to [t1] ... [tn], | |
467 | then compute those lists and [f] as follows~: for each element [c1,...,cn] of [lc1\times...\times lcn] | |
468 | create a new variable [res] and [forall res, R_f c1 ... cn res] is in [lc] | |
469 | \item if the term is a cast just treat its body part | |
470 | \item | |
471 | if the term is a match, an if or a lettuple then compute the lists corresponding to each branch of the case | |
472 | and concatenate them (informally, each branch of a match produces a new constructor) | |
473 | \end{itemize} | |
474 | ||
475 | WARNING: The terms constructed here are only USING the rawconstr syntax but are highly bad formed. | |
476 | We must wait to have complete all the current calculi to set the recursive calls. | |
477 | At this point, each term [f t1 ... tn] (where f appears in [funnames]) is replaced by | |
478 | a pseudo term [forall res, res t1 ... tn, res]. A reconstruction phase is done later. | |
479 | We in fact not create a constructor list since then end of each constructor has not the expected form | |
480 | but only the value of the function | |
481 | *) | |
482 | ||
483 | ||
484 | let rec build_entry_lc env funnames avoid rt : rawconstr build_entry_return = | |
485 | observe (str " Entering : " ++ Printer.pr_rawconstr rt); | |
416 | 486 | match rt with |
417 | 487 | | RRef _ | RVar _ | REvar _ | RPatVar _ | RSort _ | RHole _ -> |
418 | mk_result [] rt avoid | |
488 | (* do nothing (except changing type of course) *) | |
489 | mk_result [] rt avoid | |
419 | 490 | | RApp(_,_,_) -> |
420 | 491 | let f,args = raw_decompose_app rt in |
421 | 492 | let args_res : (rawconstr list) build_entry_return = |
422 | List.fold_right | |
493 | List.fold_right (* create the arguments lists of constructors and combine them *) | |
423 | 494 | (fun arg ctxt_argsl -> |
424 | let arg_res = build_entry_lc funnames ctxt_argsl.to_avoid arg in | |
425 | combine_results combine_args arg_res ctxt_argsl | |
495 | let arg_res = build_entry_lc env funnames ctxt_argsl.to_avoid arg in | |
496 | combine_results combine_args arg_res ctxt_argsl | |
426 | 497 | ) |
427 | 498 | args |
428 | 499 | (mk_result [] [] avoid) |
430 | 501 | begin |
431 | 502 | match f with |
432 | 503 | | RVar(_,id) when Idset.mem id funnames -> |
504 | (* if we have [f t1 ... tn] with [f]$\in$[fnames] | |
505 | then we create a fresh variable [res], | |
506 | add [res] and its "value" (i.e. [res v1 ... vn]) to each | |
507 | pseudo constructor build for the arguments (i.e. a pseudo context [ctxt] and | |
508 | a pseudo value "v1 ... vn". | |
509 | The "value" of this branch is then simply [res] | |
510 | *) | |
511 | let rt_as_constr = Pretyping.Default.understand Evd.empty env rt in | |
512 | let rt_typ = Typing.type_of env Evd.empty rt_as_constr in | |
513 | let res_raw_type = Detyping.detype false [] (Termops.names_of_rel_context env) rt_typ in | |
433 | 514 | let res = fresh_id args_res.to_avoid "res" in |
434 | 515 | let new_avoid = res::args_res.to_avoid in |
435 | 516 | let res_rt = mkRVar res in |
437 | 518 | List.map |
438 | 519 | (fun arg_res -> |
439 | 520 | let new_hyps = |
440 | [Prod (Name res),mkRHole (); | |
521 | [Prod (Name res),res_raw_type; | |
441 | 522 | Prod Anonymous,mkRApp(res_rt,(mkRVar id)::arg_res.value)] |
442 | 523 | in |
443 | 524 | {context = arg_res.context@new_hyps; value = res_rt } |
446 | 527 | in |
447 | 528 | { result = new_result; to_avoid = new_avoid } |
448 | 529 | | RVar _ | REvar _ | RPatVar _ | RHole _ | RSort _ | RRef _ -> |
530 | (* if have [g t1 ... tn] with [g] not appearing in [funnames] | |
531 | then | |
532 | foreach [ctxt,v1 ... vn] in [args_res] we return | |
533 | [ctxt, g v1 .... vn] | |
534 | *) | |
449 | 535 | { |
450 | 536 | args_res with |
451 | 537 | result = |
454 | 540 | {args_res with value = mkRApp(f,args_res.value)}) |
455 | 541 | args_res.result |
456 | 542 | } |
457 | | RApp _ -> assert false (* we have collected all the app *) | |
543 | | RApp _ -> assert false (* we have collected all the app in [raw_decompose_app] *) | |
458 | 544 | | RLetIn(_,n,t,b) -> |
545 | (* if we have [(let x := v in b) t1 ... tn] , | |
546 | we discard our work and compute the list of constructor for | |
547 | [let x = v in (b t1 ... tn)] up to alpha conversion | |
548 | *) | |
459 | 549 | let new_n,new_b,new_avoid = |
460 | 550 | match n with |
461 | 551 | | Name id when List.exists (is_free_in id) args -> |
472 | 562 | | _ -> n,b,avoid |
473 | 563 | in |
474 | 564 | build_entry_lc |
565 | env | |
475 | 566 | funnames |
476 | 567 | avoid |
477 | 568 | (mkRLetIn(new_n,t,mkRApp(new_b,args))) |
478 | 569 | | RCases _ | RLambda _ | RIf _ | RLetTuple _ -> |
479 | let f_res = build_entry_lc funnames args_res.to_avoid f in | |
570 | (* we have [(match e1, ...., en with ..... end) t1 tn] | |
571 | we first compute the result from the case and | |
572 | then combine each of them with each of args one | |
573 | *) | |
574 | let f_res = build_entry_lc env funnames args_res.to_avoid f in | |
480 | 575 | combine_results combine_app f_res args_res |
481 | | RDynamic _ ->error "Not handled RDynamic" | |
576 | | RDynamic _ ->error "Not handled RDynamic" | |
482 | 577 | | RCast(_,b,_,_) -> |
483 | build_entry_lc funnames avoid (mkRApp(b,args)) | |
578 | (* for an applied cast we just trash the cast part | |
579 | and restart the work. | |
580 | ||
581 | WARNING: We need to restart since [b] itself should be an application term | |
582 | *) | |
583 | build_entry_lc env funnames avoid (mkRApp(b,args)) | |
484 | 584 | | RRec _ -> error "Not handled RRec" |
485 | 585 | | RProd _ -> error "Cannot apply a type" |
486 | end | |
586 | end (* end of the application treatement *) | |
587 | ||
487 | 588 | | RLambda(_,n,t,b) -> |
488 | let b_res = build_entry_lc funnames avoid b in | |
489 | let t_res = build_entry_lc funnames avoid t in | |
589 | (* we first compute the list of constructor | |
590 | corresponding to the body of the function, | |
591 | then the one corresponding to the type | |
592 | and combine the two result | |
593 | *) | |
594 | let t_res = build_entry_lc env funnames avoid t in | |
490 | 595 | let new_n = |
491 | 596 | match n with |
492 | 597 | | Name _ -> n |
493 | 598 | | Anonymous -> Name (Indfun_common.fresh_id [] "_x") |
494 | 599 | in |
600 | let new_env = raw_push_named (new_n,None,t) env in | |
601 | let b_res = build_entry_lc new_env funnames avoid b in | |
495 | 602 | combine_results (combine_lam new_n) t_res b_res |
496 | 603 | | RProd(_,n,t,b) -> |
497 | let b_res = build_entry_lc funnames avoid b in | |
498 | let t_res = build_entry_lc funnames avoid t in | |
604 | (* we first compute the list of constructor | |
605 | corresponding to the body of the function, | |
606 | then the one corresponding to the type | |
607 | and combine the two result | |
608 | *) | |
609 | let t_res = build_entry_lc env funnames avoid t in | |
610 | let new_env = raw_push_named (n,None,t) env in | |
611 | let b_res = build_entry_lc new_env funnames avoid b in | |
499 | 612 | combine_results (combine_prod n) t_res b_res |
500 | | RLetIn(_,n,t,b) -> | |
501 | let b_res = build_entry_lc funnames avoid b in | |
502 | let t_res = build_entry_lc funnames avoid t in | |
503 | combine_results (combine_letin n) t_res b_res | |
613 | | RLetIn(_,n,v,b) -> | |
614 | (* we first compute the list of constructor | |
615 | corresponding to the body of the function, | |
616 | then the one corresponding to the value [t] | |
617 | and combine the two result | |
618 | *) | |
619 | let v_res = build_entry_lc env funnames avoid v in | |
620 | let v_as_constr = Pretyping.Default.understand Evd.empty env v in | |
621 | let v_type = Typing.type_of env Evd.empty v_as_constr in | |
622 | let new_env = | |
623 | match n with | |
624 | Anonymous -> env | |
625 | | Name id -> Environ.push_named (id,Some v_as_constr,v_type) env | |
626 | in | |
627 | let b_res = build_entry_lc new_env funnames avoid b in | |
628 | combine_results (combine_letin n) v_res b_res | |
504 | 629 | | RCases(_,_,el,brl) -> |
630 | (* we create the discrimination function | |
631 | and treat the case itself | |
632 | *) | |
505 | 633 | let make_discr = make_discr_match brl in |
506 | build_entry_lc_from_case funnames make_discr el brl avoid | |
634 | build_entry_lc_from_case env funnames make_discr el brl avoid | |
507 | 635 | | RIf(_,b,(na,e_option),lhs,rhs) -> |
636 | let b_as_constr = Pretyping.Default.understand Evd.empty env b in | |
637 | let b_typ = Typing.type_of env Evd.empty b_as_constr in | |
638 | let (ind,_) = | |
639 | try Inductiveops.find_inductive env Evd.empty b_typ | |
640 | with Not_found -> | |
641 | errorlabstrm "" (str "Cannot find the inductive associated to " ++ | |
642 | Printer.pr_rawconstr b ++ str " in " ++ | |
643 | Printer.pr_rawconstr rt ++ str ". try again with a cast") | |
644 | in | |
645 | let case_pats = build_constructors_of_type ind [] in | |
646 | assert (Array.length case_pats = 2); | |
647 | let brl = | |
648 | list_map_i | |
649 | (fun i x -> (dummy_loc,[],[case_pats.(i)],x)) | |
650 | 0 | |
651 | [lhs;rhs] | |
652 | in | |
653 | let match_expr = | |
654 | mkRCases(None,[(b,(Anonymous,None))],brl) | |
655 | in | |
656 | (* Pp.msgnl (str "new case := " ++ Printer.pr_rawconstr match_expr); *) | |
657 | build_entry_lc env funnames avoid match_expr | |
658 | | RLetTuple(_,nal,_,b,e) -> | |
508 | 659 | begin |
509 | match b with | |
510 | | RCast(_,b,_,t) -> | |
511 | let msg = "If construction must be used with cast" in | |
512 | let case_pat = find_constructors_of_raw_type msg t [] in | |
513 | assert (Array.length case_pat = 2); | |
514 | let brl = | |
515 | list_map_i | |
516 | (fun i x -> (dummy_loc,[],[case_pat.(i)],x)) | |
517 | 0 | |
518 | [lhs;rhs] | |
519 | in | |
520 | let match_expr = | |
521 | mkRCases(None,[(b,(Anonymous,None))],brl) | |
522 | in | |
523 | (* Pp.msgnl (str "new case := " ++ Printer.pr_rawconstr match_expr); *) | |
524 | build_entry_lc funnames avoid match_expr | |
525 | | _ -> | |
526 | try | |
527 | let ind = find_type_of 2 b in | |
528 | let case_pat = build_constructors_of_type (str "") ind [] in | |
529 | let brl = | |
530 | list_map_i | |
531 | (fun i x -> (dummy_loc,[],[case_pat.(i)],x)) | |
532 | 0 | |
533 | [lhs;rhs] | |
534 | in | |
535 | let match_expr = | |
536 | mkRCases(None,[(b,(Anonymous,None))],brl) | |
537 | in | |
538 | (* Pp.msgnl (str "new case := " ++ Printer.pr_rawconstr match_expr); *) | |
539 | build_entry_lc funnames avoid match_expr | |
540 | with Invalid_argument s -> | |
541 | let msg = "If construction must be used with cast : "^ s in | |
542 | error msg | |
543 | ||
544 | end | |
545 | | RLetTuple(_,nal,_,b,e) -> | |
546 | begin | |
547 | let nal_as_rawconstr = | |
548 | List.map | |
549 | (function | |
550 | Name id -> mkRVar id | |
660 | let nal_as_rawconstr = | |
661 | List.map | |
662 | (function | |
663 | Name id -> mkRVar id | |
551 | 664 | | Anonymous -> mkRHole () |
552 | 665 | ) |
553 | nal | |
666 | nal | |
554 | 667 | in |
555 | match b with | |
556 | | RCast(_,b,_,t) -> | |
557 | let case_pat = | |
558 | find_constructors_of_raw_type | |
559 | "LetTuple construction must be used with cast" t nal_as_rawconstr in | |
560 | assert (Array.length case_pat = 1); | |
561 | let br = | |
562 | (dummy_loc,[],[case_pat.(0)],e) | |
563 | in | |
564 | let match_expr = mkRCases(None,[b,(Anonymous,None)],[br]) in | |
565 | build_entry_lc funnames avoid match_expr | |
566 | | _ -> | |
567 | try | |
568 | let ind = find_type_of 1 b in | |
569 | let case_pat = | |
570 | build_constructors_of_type | |
571 | (str "LetTuple construction must be used with cast") ind nal_as_rawconstr in | |
572 | let br = | |
573 | (dummy_loc,[],[case_pat.(0)],e) | |
574 | in | |
575 | let match_expr = mkRCases(None,[b,(Anonymous,None)],[br]) in | |
576 | build_entry_lc funnames avoid match_expr | |
577 | with Invalid_argument s -> | |
578 | let msg = "LetTuple construction must be used with cast : "^ s in | |
579 | error msg | |
580 | ||
668 | let b_as_constr = Pretyping.Default.understand Evd.empty env b in | |
669 | let b_typ = Typing.type_of env Evd.empty b_as_constr in | |
670 | let (ind,_) = | |
671 | try Inductiveops.find_inductive env Evd.empty b_typ | |
672 | with Not_found -> | |
673 | errorlabstrm "" (str "Cannot find the inductive associated to " ++ | |
674 | Printer.pr_rawconstr b ++ str " in " ++ | |
675 | Printer.pr_rawconstr rt ++ str ". try again with a cast") | |
676 | in | |
677 | let case_pats = build_constructors_of_type ind nal_as_rawconstr in | |
678 | assert (Array.length case_pats = 1); | |
679 | let br = | |
680 | (dummy_loc,[],[case_pats.(0)],e) | |
681 | in | |
682 | let match_expr = mkRCases(None,[b,(Anonymous,None)],[br]) in | |
683 | build_entry_lc env funnames avoid match_expr | |
684 | ||
581 | 685 | end |
582 | 686 | | RRec _ -> error "Not handled RRec" |
583 | 687 | | RCast(_,b,_,_) -> |
584 | build_entry_lc funnames avoid b | |
688 | build_entry_lc env funnames avoid b | |
585 | 689 | | RDynamic _ -> error "Not handled RDynamic" |
586 | and build_entry_lc_from_case funname make_discr | |
690 | and build_entry_lc_from_case env funname make_discr | |
587 | 691 | (el:tomatch_tuple) |
588 | 692 | (brl:Rawterm.cases_clauses) avoid : |
589 | 693 | rawconstr build_entry_return = |
590 | 694 | match el with |
591 | | [] -> assert false (* matched on Nothing !*) | |
695 | | [] -> assert false (* this case correspond to match <nothing> with .... !*) | |
592 | 696 | | el -> |
697 | (* this case correspond to | |
698 | match el with brl end | |
699 | we first compute the list of lists corresponding to [el] and | |
700 | combine them . | |
701 | Then for each elemeent of the combinations, | |
702 | we compute the result we compute one list per branch in [brl] and | |
703 | finally we just concatenate those list | |
704 | *) | |
593 | 705 | let case_resl = |
594 | 706 | List.fold_right |
595 | 707 | (fun (case_arg,_) ctxt_argsl -> |
596 | let arg_res = build_entry_lc funname avoid case_arg in | |
708 | let arg_res = build_entry_lc env funname avoid case_arg in | |
597 | 709 | combine_results combine_args arg_res ctxt_argsl |
598 | 710 | ) |
599 | 711 | el |
600 | 712 | (mk_result [] [] avoid) |
601 | 713 | in |
714 | (****** The next works only if the match is not dependent ****) | |
715 | let types = | |
716 | List.map (fun (case_arg,_) -> | |
717 | let case_arg_as_constr = Pretyping.Default.understand Evd.empty env case_arg in | |
718 | Typing.type_of env Evd.empty case_arg_as_constr | |
719 | ) el | |
720 | in | |
602 | 721 | let results = |
603 | 722 | List.map |
604 | (build_entry_lc_from_case_term funname (make_discr (List.map fst el)) [] brl case_resl.to_avoid) | |
723 | (build_entry_lc_from_case_term | |
724 | env types | |
725 | funname (make_discr (* (List.map fst el) *)) | |
726 | [] brl | |
727 | case_resl.to_avoid) | |
605 | 728 | case_resl.result |
606 | 729 | in |
607 | 730 | { |
610 | 733 | List.fold_left (fun acc r -> list_union acc r.to_avoid) [] results |
611 | 734 | } |
612 | 735 | |
613 | and build_entry_lc_from_case_term funname make_discr patterns_to_prevent brl avoid | |
736 | and build_entry_lc_from_case_term env types funname make_discr patterns_to_prevent brl avoid | |
614 | 737 | matched_expr = |
615 | 738 | match brl with |
616 | 739 | | [] -> (* computed_branches *) {result = [];to_avoid = avoid} |
617 | 740 | | br::brl' -> |
741 | (* alpha convertion to prevent name clashes *) | |
618 | 742 | let _,idl,patl,return = alpha_br avoid br in |
619 | let new_avoid = idl@avoid in | |
620 | (* let e_ctxt,el = (matched_expr.context,matched_expr.value) in *) | |
621 | (* if (List.length patl) <> (List.length el) *) | |
622 | (* then error ("Pattern matching on product: not yet implemented"); *) | |
743 | let new_avoid = idl@avoid in (* for now we can no more use idl as an indentifier *) | |
744 | (* building a list of precondition stating that we are not in this branch | |
745 | (will be used in the following recursive calls) | |
746 | *) | |
747 | let new_env = List.fold_right2 add_pat_variables patl types env in | |
623 | 748 | let not_those_patterns : (identifier list -> rawconstr -> rawconstr) list = |
624 | List.map | |
625 | (fun pat -> | |
749 | List.map2 | |
750 | (fun pat typ -> | |
626 | 751 | fun avoid pat'_as_term -> |
627 | 752 | let renamed_pat,_,_ = alpha_pat avoid pat in |
628 | 753 | let pat_ids = get_pattern_id renamed_pat in |
629 | List.fold_right | |
630 | (fun id acc -> mkRProd (Name id,mkRHole (),acc)) | |
754 | let env_with_pat_ids = add_pat_variables pat typ new_env in | |
755 | List.fold_right | |
756 | (fun id acc -> | |
757 | let typ_of_id = Typing.type_of env_with_pat_ids Evd.empty (mkVar id) in | |
758 | let raw_typ_of_id = | |
759 | Detyping.detype false [] (Termops.names_of_rel_context env_with_pat_ids) typ_of_id | |
760 | in | |
761 | mkRProd (Name id,raw_typ_of_id,acc)) | |
631 | 762 | pat_ids |
632 | 763 | (raw_make_neq pat'_as_term (pattern_to_term renamed_pat)) |
633 | 764 | ) |
634 | 765 | patl |
635 | in | |
766 | types | |
767 | in | |
768 | (* Checking if we can be in this branch | |
769 | (will be used in the following recursive calls) | |
770 | *) | |
636 | 771 | let unify_with_those_patterns : (cases_pattern -> bool*bool) list = |
637 | 772 | List.map |
638 | 773 | (fun pat pat' -> are_unifiable pat pat',eq_cases_pattern pat pat') |
639 | 774 | patl |
640 | 775 | in |
776 | (* | |
777 | we first compute the other branch result (in ordrer to keep the order of the matching | |
778 | as much as possible) | |
779 | *) | |
641 | 780 | let brl'_res = |
642 | 781 | build_entry_lc_from_case_term |
782 | env | |
783 | types | |
643 | 784 | funname |
644 | 785 | make_discr |
645 | 786 | ((unify_with_those_patterns,not_those_patterns)::patterns_to_prevent) |
647 | 788 | avoid |
648 | 789 | matched_expr |
649 | 790 | in |
791 | (* We know create the precondition of this branch i.e. | |
792 | ||
793 | 1- the list of variable appearing in the different patterns of this branch and | |
794 | the list of equation stating than el = patl (List.flatten ...) | |
795 | 2- If there exists a previous branch which pattern unify with the one of this branch | |
796 | then a discrimination precond stating that we are not in a previous branch (if List.exists ...) | |
797 | *) | |
650 | 798 | let those_pattern_preconds = |
651 | ( List.flatten | |
799 | (List.flatten | |
652 | 800 | ( |
653 | List.map2 | |
654 | (fun pat e -> | |
801 | list_map3 | |
802 | (fun pat e typ_as_constr -> | |
655 | 803 | let this_pat_ids = ids_of_pat pat in |
804 | let typ = Detyping.detype false [] (Termops.names_of_rel_context new_env) typ_as_constr in | |
656 | 805 | let pat_as_term = pattern_to_term pat in |
657 | 806 | List.fold_right |
658 | 807 | (fun id acc -> |
659 | 808 | if Idset.mem id this_pat_ids |
660 | then (Prod (Name id),mkRHole ())::acc | |
809 | then (Prod (Name id), | |
810 | let typ_of_id = Typing.type_of new_env Evd.empty (mkVar id) in | |
811 | let raw_typ_of_id = | |
812 | Detyping.detype false [] (Termops.names_of_rel_context new_env) typ_of_id | |
813 | in | |
814 | raw_typ_of_id | |
815 | )::acc | |
661 | 816 | else acc |
662 | 817 | |
663 | 818 | ) |
664 | 819 | idl |
665 | [(Prod Anonymous,raw_make_eq pat_as_term e)] | |
820 | [(Prod Anonymous,raw_make_eq ~typ pat_as_term e)] | |
666 | 821 | ) |
667 | 822 | patl |
668 | 823 | matched_expr.value |
824 | types | |
669 | 825 | ) |
670 | ) | |
826 | ) | |
671 | 827 | @ |
672 | (if List.exists (function (unifl,neql) -> | |
673 | let (unif,eqs) = | |
674 | List.split (List.map2 (fun x y -> x y) unifl patl) | |
675 | in | |
676 | List.for_all (fun x -> x) unif) patterns_to_prevent | |
677 | then | |
678 | let i = List.length patterns_to_prevent in | |
679 | [(Prod Anonymous,make_discr i )] | |
680 | else | |
681 | [] | |
682 | ) | |
683 | in | |
684 | let return_res = build_entry_lc funname new_avoid return in | |
828 | (if List.exists (function (unifl,_) -> | |
829 | let (unif,_) = | |
830 | List.split (List.map2 (fun x y -> x y) unifl patl) | |
831 | in | |
832 | List.for_all (fun x -> x) unif) patterns_to_prevent | |
833 | then | |
834 | let i = List.length patterns_to_prevent in | |
835 | let pats_as_constr = List.map2 (pattern_to_term_and_type new_env) types patl in | |
836 | [(Prod Anonymous,make_discr pats_as_constr i )] | |
837 | else | |
838 | [] | |
839 | ) | |
840 | in | |
841 | (* We compute the result of the value returned by the branch*) | |
842 | let return_res = build_entry_lc new_env funname new_avoid return in | |
843 | (* and combine it with the preconds computed for this branch *) | |
685 | 844 | let this_branch_res = |
686 | 845 | List.map |
687 | 846 | (fun res -> |
688 | { context = | |
689 | matched_expr.context@ | |
690 | (* ids@ *) | |
691 | those_pattern_preconds@res.context ; | |
847 | { context = matched_expr.context@those_pattern_preconds@res.context ; | |
692 | 848 | value = res.value} |
693 | 849 | ) |
694 | 850 | return_res.result |
701 | 857 | String.sub (string_of_id id) 0 3 = "res" |
702 | 858 | with Invalid_argument _ -> false |
703 | 859 | |
704 | (* rebuild the raw constructors expression. | |
860 | (* | |
861 | The second phase which reconstruct the real type of the constructor. | |
862 | rebuild the raw constructors expression. | |
705 | 863 | eliminates some meaningless equalities, applies some rewrites...... |
706 | 864 | *) |
707 | 865 | let rec rebuild_cons nb_args relname args crossed_types depth rt = |
721 | 879 | args new_crossed_types |
722 | 880 | (depth + 1) b |
723 | 881 | in |
882 | (*i The next call to mk_rel_id is valid since we are constructing the graph | |
883 | Ensures by: obvious | |
884 | i*) | |
885 | ||
724 | 886 | let new_t = |
725 | 887 | mkRApp(mkRVar(mk_rel_id this_relname),args'@[res_rt]) |
726 | 888 | in mkRProd(n,new_t,new_b), |
729 | 891 | assert false |
730 | 892 | end |
731 | 893 | | RApp(_,RRef(_,eq_as_ref),[_;RVar(_,id);rt]) |
732 | when eq_as_ref = Lazy.force Coqlib.coq_eq_ref | |
894 | when eq_as_ref = Lazy.force Coqlib.coq_eq_ref && n = Anonymous | |
733 | 895 | -> |
734 | 896 | let is_in_b = is_free_in id b in |
735 | 897 | let _keep_eq = |
747 | 909 | (depth + 1) subst_b |
748 | 910 | in |
749 | 911 | mkRProd(n,t,new_b),id_to_exclude |
750 | (* if keep_eq then *) | |
751 | (* mkRProd(n,t,new_b),id_to_exclude *) | |
752 | (* else new_b, Idset.add id id_to_exclude *) | |
912 | (* J.F:. keep this comment it explain how to remove some meaningless equalities | |
913 | if keep_eq then | |
914 | mkRProd(n,t,new_b),id_to_exclude | |
915 | else new_b, Idset.add id id_to_exclude | |
916 | *) | |
753 | 917 | | _ -> |
754 | 918 | let new_b,id_to_exclude = |
755 | 919 | rebuild_cons |
765 | 929 | end |
766 | 930 | | RLambda(_,n,t,b) -> |
767 | 931 | begin |
768 | (* let not_free_in_t id = not (is_free_in id t) in *) | |
769 | (* let new_crossed_types = t :: crossed_types in *) | |
770 | (* let new_b,id_to_exclude = rebuild_cons relname args new_crossed_types b in *) | |
771 | (* match n with *) | |
772 | (* | Name id when Idset.mem id id_to_exclude -> *) | |
773 | (* new_b, *) | |
774 | (* Idset.remove id (Idset.filter not_free_in_t id_to_exclude) *) | |
775 | (* | _ -> *) | |
776 | (* RProd(dummy_loc,n,t,new_b),Idset.filter not_free_in_t id_to_exclude *) | |
777 | 932 | let not_free_in_t id = not (is_free_in id t) in |
778 | 933 | let new_crossed_types = t :: crossed_types in |
779 | (* let new_b,id_to_exclude = rebuild_cons relname (args new_crossed_types b in *) | |
780 | 934 | match n with |
781 | 935 | | Name id -> |
782 | 936 | let new_b,id_to_exclude = |
837 | 991 | | _ -> mkRApp(mkRVar relname,args@[rt]),Idset.empty |
838 | 992 | |
839 | 993 | |
994 | (* debuging wrapper *) | |
840 | 995 | let rebuild_cons nb_args relname args crossed_types rt = |
841 | observennl (str "rebuild_cons : rt := "++ pr_rawconstr rt ++ | |
842 | str "nb_args := " ++ str (string_of_int nb_args)); | |
996 | (* observennl (str "rebuild_cons : rt := "++ pr_rawconstr rt ++ *) | |
997 | (* str "nb_args := " ++ str (string_of_int nb_args)); *) | |
843 | 998 | let res = |
844 | 999 | rebuild_cons nb_args relname args crossed_types 0 rt |
845 | 1000 | in |
846 | observe (str " leads to "++ pr_rawconstr (fst res)); | |
1001 | (* observe (str " leads to "++ pr_rawconstr (fst res)); *) | |
847 | 1002 | res |
848 | 1003 | |
1004 | ||
1005 | (* naive implementation of parameter detection. | |
1006 | ||
1007 | A parameter is an argument which is only preceded by parameters and whose | |
1008 | calls are all syntaxically equal. | |
1009 | ||
1010 | TODO: Find a valid way to deal with implicit arguments here! | |
1011 | *) | |
849 | 1012 | let rec compute_cst_params relnames params = function |
850 | 1013 | | RRef _ | RVar _ | REvar _ | RPatVar _ -> params |
851 | 1014 | | RApp(_,RVar(_,relname'),rtl) when Idset.mem relname' relnames -> |
899 | 1062 | in |
900 | 1063 | List.rev !l |
901 | 1064 | |
902 | (* (Topconstr.CProdN | |
903 | (dummy_loc, | |
904 | [[(dummy_loc,Anonymous)],returned_types.(i)], | |
905 | Topconstr.CSort(dummy_loc, RProp Null ) | |
906 | ) | |
907 | ) | |
908 | *) | |
909 | 1065 | let rec rebuild_return_type rt = |
910 | 1066 | match rt with |
911 | 1067 | | Topconstr.CProdN(loc,n,t') -> |
914 | 1070 | Topconstr.CArrow(loc,t,rebuild_return_type t') |
915 | 1071 | | Topconstr.CLetIn(loc,na,t,t') -> |
916 | 1072 | Topconstr.CLetIn(loc,na,t,rebuild_return_type t') |
917 | | _ -> Topconstr.CArrow(dummy_loc,rt,Topconstr.CSort(dummy_loc, RProp Null)) | |
918 | ||
919 | ||
920 | let build_inductive parametrize funnames (funsargs: (Names.name * rawconstr * bool) list list) returned_types (rtl:rawconstr list) = | |
1073 | | _ -> Topconstr.CArrow(dummy_loc,rt,Topconstr.CSort(dummy_loc,RType None)) | |
1074 | ||
1075 | ||
1076 | let build_inductive | |
1077 | parametrize funnames (funsargs: (Names.name * rawconstr * bool) list list) | |
1078 | returned_types | |
1079 | (rtl:rawconstr list) = | |
921 | 1080 | let _time1 = System.get_time () in |
922 | 1081 | (* Pp.msgnl (prlist_with_sep fnl Printer.pr_rawconstr rtl); *) |
923 | 1082 | let funnames_as_set = List.fold_right Idset.add funnames Idset.empty in |
924 | 1083 | let funnames = Array.of_list funnames in |
925 | 1084 | let funsargs = Array.of_list funsargs in |
926 | 1085 | let returned_types = Array.of_list returned_types in |
1086 | (* alpha_renaming of the body to prevent variable capture during manipulation *) | |
927 | 1087 | let rtl_alpha = List.map (function rt -> (alpha_rt [] rt) ) rtl in |
928 | 1088 | let rta = Array.of_list rtl_alpha in |
1089 | (*i The next call to mk_rel_id is valid since we are constructing the graph | |
1090 | Ensures by: obvious | |
1091 | i*) | |
929 | 1092 | let relnames = Array.map mk_rel_id funnames in |
930 | 1093 | let relnames_as_set = Array.fold_right Idset.add relnames Idset.empty in |
931 | let resa = Array.map (build_entry_lc funnames_as_set []) rta in | |
1094 | (* Construction of the pseudo constructors *) | |
1095 | let env = | |
1096 | Array.fold_right | |
1097 | (fun id env -> | |
1098 | Environ.push_named (id,None,Typing.type_of env Evd.empty (Tacinterp.constr_of_id env id)) env | |
1099 | ) | |
1100 | funnames | |
1101 | (Global.env ()) | |
1102 | in | |
1103 | let resa = Array.map (build_entry_lc env funnames_as_set []) rta in | |
1104 | (* and of the real constructors*) | |
932 | 1105 | let constr i res = |
933 | 1106 | List.map |
934 | 1107 | (function result (* (args',concl') *) -> |
935 | 1108 | let rt = compose_raw_context result.context result.value in |
936 | 1109 | let nb_args = List.length funsargs.(i) in |
937 | (* Pp.msgnl (str "raw constr " ++ pr_rawconstr rt); *) | |
1110 | (* let old_implicit_args = Impargs.is_implicit_args () *) | |
1111 | (* and old_strict_implicit_args = Impargs.is_strict_implicit_args () *) | |
1112 | (* and old_contextual_implicit_args = Impargs.is_contextual_implicit_args () in *) | |
1113 | (* let old_rawprint = !Options.raw_print in *) | |
1114 | (* Options.raw_print := true; *) | |
1115 | (* Impargs.make_implicit_args false; *) | |
1116 | (* Impargs.make_strict_implicit_args false; *) | |
1117 | (* Impargs.make_contextual_implicit_args false; *) | |
1118 | (* Pp.msgnl (str "raw constr " ++ pr_rawconstr rt); *) | |
1119 | (* Impargs.make_implicit_args old_implicit_args; *) | |
1120 | (* Impargs.make_strict_implicit_args old_strict_implicit_args; *) | |
1121 | (* Impargs.make_contextual_implicit_args old_contextual_implicit_args; *) | |
1122 | (* Options.raw_print := old_rawprint; *) | |
938 | 1123 | fst ( |
939 | 1124 | rebuild_cons nb_args relnames.(i) |
940 | (* (List.map *) | |
941 | (* (function *) | |
942 | (* (Anonymous,_,_) -> mkRVar(fresh_id res.to_avoid "x__") *) | |
943 | (* | Name id, _,_ -> mkRVar id *) | |
944 | (* ) *) | |
945 | (* funsargs.(i) *) | |
946 | (* ) *) | |
947 | 1125 | [] |
948 | 1126 | [] |
949 | 1127 | rt |
951 | 1129 | ) |
952 | 1130 | res.result |
953 | 1131 | in |
954 | let next_constructor_id = ref (-1) in | |
1132 | (* adding names to constructors *) | |
1133 | let next_constructor_id = ref (-1) in | |
955 | 1134 | let mk_constructor_id i = |
956 | 1135 | incr next_constructor_id; |
1136 | (*i The next call to mk_rel_id is valid since we are constructing the graph | |
1137 | Ensures by: obvious | |
1138 | i*) | |
957 | 1139 | id_of_string ((string_of_id (mk_rel_id funnames.(i)))^"_"^(string_of_int !next_constructor_id)) |
958 | 1140 | in |
959 | 1141 | let rel_constructors i rt : (identifier*rawconstr) list = |
1142 | next_constructor_id := (-1); | |
960 | 1143 | List.map (fun constr -> (mk_constructor_id i),constr) (constr i rt) |
961 | 1144 | in |
962 | 1145 | let rel_constructors = Array.mapi rel_constructors resa in |
1146 | (* Computing the set of parameters if asked *) | |
963 | 1147 | let rels_params = |
964 | 1148 | if parametrize |
965 | 1149 | then |
967 | 1151 | else [] |
968 | 1152 | in |
969 | 1153 | let nrel_params = List.length rels_params in |
970 | let rel_constructors = | |
1154 | let rel_constructors = (* Taking into account the parameters in constructors *) | |
971 | 1155 | Array.map (List.map |
972 | 1156 | (fun (id,rt) -> (id,snd (chop_rprod_n nrel_params rt)))) |
973 | 1157 | rel_constructors |
974 | 1158 | in |
975 | let rel_arity i funargs = | |
1159 | let rel_arity i funargs = (* Reduilding arities (with parameters) *) | |
976 | 1160 | let rel_first_args :(Names.name * Rawterm.rawconstr * bool ) list = |
977 | 1161 | (snd (list_chop nrel_params funargs)) |
978 | 1162 | in |
991 | 1175 | ) |
992 | 1176 | rel_first_args |
993 | 1177 | (rebuild_return_type returned_types.(i)) |
994 | (* (Topconstr.CProdN *) | |
995 | (* (dummy_loc, *) | |
996 | (* [[(dummy_loc,Anonymous)],returned_types.(i)], *) | |
997 | (* Topconstr.CSort(dummy_loc, RProp Null ) *) | |
998 | (* ) *) | |
999 | (* ) *) | |
1000 | in | |
1178 | in | |
1179 | (* We need to lift back our work topconstr but only with all information | |
1180 | We mimick a Set Printing All. | |
1181 | Then save the graphs and reset Printing options to their primitive values | |
1182 | *) | |
1001 | 1183 | let rel_arities = Array.mapi rel_arity funsargs in |
1002 | 1184 | let old_rawprint = !Options.raw_print in |
1003 | 1185 | Options.raw_print := true; |
1016 | 1198 | let ext_rels_constructors = |
1017 | 1199 | Array.map (List.map |
1018 | 1200 | (fun (id,t) -> |
1019 | false,((dummy_loc,id),Constrextern.extern_rawtype Idset.empty t) | |
1201 | false,((dummy_loc,id),Constrextern.extern_rawtype Idset.empty ((* zeta_normalize *) t)) | |
1020 | 1202 | )) |
1021 | rel_constructors | |
1203 | (rel_constructors) | |
1022 | 1204 | in |
1023 | 1205 | let rel_ind i ext_rel_constructors = |
1024 | 1206 | (dummy_loc,relnames.(i)), |
1029 | 1211 | in |
1030 | 1212 | let ext_rel_constructors = (Array.mapi rel_ind ext_rels_constructors) in |
1031 | 1213 | let rel_inds = Array.to_list ext_rel_constructors in |
1032 | let _ = | |
1033 | observe ( | |
1034 | str "Inductive" ++ spc () ++ | |
1035 | prlist_with_sep | |
1036 | (fun () -> fnl ()++spc () ++ str "with" ++ spc ()) | |
1037 | (function ((_,id),_,params,ar,constr) -> | |
1038 | Ppconstr.pr_id id ++ spc () ++ | |
1039 | Ppconstr.pr_binders params ++ spc () ++ | |
1040 | str ":" ++ spc () ++ | |
1041 | Ppconstr.pr_lconstr_expr ar ++ spc () ++ | |
1042 | prlist_with_sep | |
1043 | (fun _ -> fnl () ++ spc () ++ str "|" ++ spc ()) | |
1044 | (function (_,((_,id),t)) -> | |
1045 | Ppconstr.pr_id id ++ spc () ++ str ":" ++ spc () ++ | |
1046 | Ppconstr.pr_lconstr_expr t) | |
1047 | constr | |
1048 | ) | |
1049 | rel_inds | |
1050 | ) | |
1051 | in | |
1214 | (* let _ = *) | |
1215 | (* Pp.msgnl (\* observe *\) ( *) | |
1216 | (* str "Inductive" ++ spc () ++ *) | |
1217 | (* prlist_with_sep *) | |
1218 | (* (fun () -> fnl ()++spc () ++ str "with" ++ spc ()) *) | |
1219 | (* (function ((_,id),_,params,ar,constr) -> *) | |
1220 | (* Ppconstr.pr_id id ++ spc () ++ *) | |
1221 | (* Ppconstr.pr_binders params ++ spc () ++ *) | |
1222 | (* str ":" ++ spc () ++ *) | |
1223 | (* Ppconstr.pr_lconstr_expr ar ++ spc () ++ str ":=" ++ *) | |
1224 | (* prlist_with_sep *) | |
1225 | (* (fun _ -> fnl () ++ spc () ++ str "|" ++ spc ()) *) | |
1226 | (* (function (_,((_,id),t)) -> *) | |
1227 | (* Ppconstr.pr_id id ++ spc () ++ str ":" ++ spc () ++ *) | |
1228 | (* Ppconstr.pr_lconstr_expr t) *) | |
1229 | (* constr *) | |
1230 | (* ) *) | |
1231 | (* rel_inds *) | |
1232 | (* ) *) | |
1233 | (* in *) | |
1052 | 1234 | let old_implicit_args = Impargs.is_implicit_args () |
1053 | 1235 | and old_strict_implicit_args = Impargs.is_strict_implicit_args () |
1054 | 1236 | and old_contextual_implicit_args = Impargs.is_contextual_implicit_args () in |
0 | 0 | |
1 | (* val new_build_entry_lc : *) | |
2 | (* Names.identifier list -> *) | |
3 | (* (Names.name*Rawterm.rawconstr) list list -> *) | |
4 | (* Topconstr.constr_expr list -> *) | |
5 | (* Rawterm.rawconstr list -> *) | |
6 | (* unit *) | |
1 | ||
2 | (* | |
3 | [build_inductive parametrize funnames funargs returned_types bodies] | |
4 | constructs and saves the graphs of the functions [funnames] taking [funargs] as arguments | |
5 | and returning [returned_types] using bodies [bodies] | |
6 | *) | |
7 | 7 | |
8 | 8 | val build_inductive : |
9 | bool -> | |
10 | Names.identifier list -> | |
11 | (Names.name*Rawterm.rawconstr*bool) list list -> | |
12 | Topconstr.constr_expr list -> | |
13 | Rawterm.rawconstr list -> | |
9 | bool -> (* if true try to detect parameter. Always use it as true except for debug *) | |
10 | Names.identifier list -> (* The list of function name *) | |
11 | (Names.name*Rawterm.rawconstr*bool) list list -> (* The list of function args *) | |
12 | Topconstr.constr_expr list -> (* The list of function returned type *) | |
13 | Rawterm.rawconstr list -> (* the list of body *) | |
14 | 14 | unit |
15 | 15 |
17 | 17 | let mkRCases(rto,l,brl) = RCases(dummy_loc,rto,l,brl) |
18 | 18 | let mkRSort s = RSort(dummy_loc,s) |
19 | 19 | let mkRHole () = RHole(dummy_loc,Evd.BinderType Anonymous) |
20 | ||
20 | let mkRCast(b,t) = RCast(dummy_loc,b,CastCoerce,t) | |
21 | 21 | |
22 | 22 | (* |
23 | 23 | Some basic functions to decompose rawconstrs |
48 | 48 | |
49 | 49 | |
50 | 50 | (* [raw_make_eq t1 t2] build the rawconstr corresponding to [t2 = t1] *) |
51 | let raw_make_eq t1 t2 = | |
52 | mkRApp(mkRRef (Lazy.force Coqlib.coq_eq_ref),[mkRHole ();t2;t1]) | |
51 | let raw_make_eq ?(typ= mkRHole ()) t1 t2 = | |
52 | mkRApp(mkRRef (Lazy.force Coqlib.coq_eq_ref),[typ;t2;t1]) | |
53 | 53 | |
54 | 54 | (* [raw_make_neq t1 t2] build the rawconstr corresponding to [t1 <> t2] *) |
55 | 55 | let raw_make_neq t1 t2 = |
320 | 320 | List.map (alpha_rt excluded) args |
321 | 321 | ) |
322 | 322 | in |
323 | if Tacinterp.get_debug () <> Tactic_debug.DebugOff && false | |
323 | if Indfun_common.do_observe () && false | |
324 | 324 | then |
325 | 325 | Pp.msgnl (str "debug: alpha_rt(" ++ str "[" ++ |
326 | 326 | prlist_with_sep (fun _ -> str";") Ppconstr.pr_id excluded ++ |
385 | 385 | |
386 | 386 | |
387 | 387 | |
388 | let rec pattern_to_term = function | |
388 | let rec pattern_to_term = function | |
389 | 389 | | PatVar(loc,Anonymous) -> assert false |
390 | | PatVar(loc,Name id) -> | |
390 | | PatVar(loc,Name id) -> | |
391 | 391 | mkRVar id |
392 | | PatCstr(loc,constr,patternl,_) -> | |
393 | let cst_narg = | |
392 | | PatCstr(loc,constr,patternl,_) -> | |
393 | let cst_narg = | |
394 | 394 | Inductiveops.mis_constructor_nargs_env |
395 | 395 | (Global.env ()) |
396 | 396 | constr |
397 | 397 | in |
398 | let implicit_args = | |
399 | Array.to_list | |
400 | (Array.init | |
398 | let implicit_args = | |
399 | Array.to_list | |
400 | (Array.init | |
401 | 401 | (cst_narg - List.length patternl) |
402 | 402 | (fun _ -> mkRHole ()) |
403 | 403 | ) |
404 | 404 | in |
405 | let patl_as_term = | |
405 | let patl_as_term = | |
406 | 406 | List.map pattern_to_term patternl |
407 | 407 | in |
408 | 408 | mkRApp(mkRRef(Libnames.ConstructRef constr), |
409 | 409 | implicit_args@patl_as_term |
410 | 410 | ) |
411 | ||
412 | ||
411 | 413 | |
412 | 414 | let replace_var_by_term x_id term = |
413 | 415 | let rec replace_var_by_pattern rt = |
538 | 540 | in |
539 | 541 | ids_of_pat Idset.empty |
540 | 542 | |
543 | ||
544 | ||
545 | ||
546 | ||
547 | let zeta_normalize = | |
548 | let rec zeta_normalize_term rt = | |
549 | match rt with | |
550 | | RRef _ -> rt | |
551 | | RVar _ -> rt | |
552 | | REvar _ -> rt | |
553 | | RPatVar _ -> rt | |
554 | | RApp(loc,rt',rtl) -> | |
555 | RApp(loc, | |
556 | zeta_normalize_term rt', | |
557 | List.map zeta_normalize_term rtl | |
558 | ) | |
559 | | RLambda(loc,name,t,b) -> | |
560 | RLambda(loc, | |
561 | name, | |
562 | zeta_normalize_term t, | |
563 | zeta_normalize_term b | |
564 | ) | |
565 | | RProd(loc,name,t,b) -> | |
566 | RProd(loc, | |
567 | name, | |
568 | zeta_normalize_term t, | |
569 | zeta_normalize_term b | |
570 | ) | |
571 | | RLetIn(_,Name id,def,b) -> | |
572 | zeta_normalize_term (replace_var_by_term id def b) | |
573 | | RLetIn(loc,Anonymous,def,b) -> zeta_normalize_term b | |
574 | | RLetTuple(loc,nal,(na,rto),def,b) -> | |
575 | RLetTuple(loc, | |
576 | nal, | |
577 | (na,option_map zeta_normalize_term rto), | |
578 | zeta_normalize_term def, | |
579 | zeta_normalize_term b | |
580 | ) | |
581 | | RCases(loc,infos,el,brl) -> | |
582 | RCases(loc, | |
583 | infos, | |
584 | List.map (fun (e,x) -> (zeta_normalize_term e,x)) el, | |
585 | List.map zeta_normalize_br brl | |
586 | ) | |
587 | | RIf(loc,b,(na,e_option),lhs,rhs) -> | |
588 | RIf(loc, zeta_normalize_term b, | |
589 | (na,option_map zeta_normalize_term e_option), | |
590 | zeta_normalize_term lhs, | |
591 | zeta_normalize_term rhs | |
592 | ) | |
593 | | RRec _ -> raise (UserError("",str "Not handled RRec")) | |
594 | | RSort _ -> rt | |
595 | | RHole _ -> rt | |
596 | | RCast(loc,b,k,t) -> | |
597 | RCast(loc,zeta_normalize_term b,k,zeta_normalize_term t) | |
598 | | RDynamic _ -> raise (UserError("",str "Not handled RDynamic")) | |
599 | and zeta_normalize_br (loc,idl,patl,res) = | |
600 | (loc,idl,patl,zeta_normalize_term res) | |
601 | in | |
602 | zeta_normalize_term |
24 | 24 | val mkRCases : rawconstr option * tomatch_tuple * cases_clauses -> rawconstr |
25 | 25 | val mkRSort : rawsort -> rawconstr |
26 | 26 | val mkRHole : unit -> rawconstr (* we only build Evd.BinderType Anonymous holes *) |
27 | ||
27 | val mkRCast : rawconstr* rawconstr -> rawconstr | |
28 | 28 | (* |
29 | 29 | Some basic functions to decompose rawconstrs |
30 | 30 | These are analogous to the ones constrs |
35 | 35 | |
36 | 36 | |
37 | 37 | (* [raw_make_eq t1 t2] build the rawconstr corresponding to [t2 = t1] *) |
38 | val raw_make_eq : rawconstr -> rawconstr -> rawconstr | |
38 | val raw_make_eq : ?typ:rawconstr -> rawconstr -> rawconstr -> rawconstr | |
39 | 39 | (* [raw_make_neq t1 t2] build the rawconstr corresponding to [t1 <> t2] *) |
40 | 40 | val raw_make_neq : rawconstr -> rawconstr -> rawconstr |
41 | 41 | (* [raw_make_or P1 P2] build the rawconstr corresponding to [P1 \/ P2] *) |
105 | 105 | returns the set of variables appearing in a pattern |
106 | 106 | *) |
107 | 107 | val ids_of_pat : cases_pattern -> Names.Idset.t |
108 | ||
109 | ||
110 | (* | |
111 | removing let_in construction in a rawterm | |
112 | *) | |
113 | val zeta_normalize : Rawterm.rawconstr -> Rawterm.rawconstr |
0 | 0 | (*i camlp4deps: "parsing/grammar.cma" i*) |
1 | 1 | |
2 | 2 | (*s FunInv Tactic: inversion following the shape of a function. *) |
3 | (* Use: | |
4 | \begin{itemize} | |
5 | \item The Tacinv directory must be in the path (-I <path> option) | |
6 | \item use the bytecode version of coqtop or coqc (-byte option), or make a | |
7 | coqtop | |
8 | \item Do [Require Tacinv] to be able to use it. | |
9 | \item For syntax see Tacinv.v | |
10 | \end{itemize} | |
11 | *) | |
12 | ||
3 | ||
4 | (* Deprecated: see indfun_main.ml4 instead *) | |
5 | ||
6 | (* Don't delete this file yet, it may be used for other purposes *) | |
13 | 7 | |
14 | 8 | (*i*) |
15 | 9 | open Termops |
861 | 855 | (* |
862 | 856 | *** Local Variables: *** |
863 | 857 | *** compile-command: "make -C ../.. contrib/funind/tacinv.cmo" *** |
864 | *** tab-width: 1 *** | |
865 | 858 | *** tuareg-default-indent:1 *** |
866 | 859 | *** tuareg-begin-indent:1 *** |
867 | 860 | *** tuareg-let-indent:1 *** |
335 | 335 | | a::l -> CT_match_pattern_ne_list(xlate_match_pattern a, |
336 | 336 | List.map xlate_match_pattern l) |
337 | 337 | and translate_one_equation = function |
338 | (_,lp, a) -> CT_eqn ( xlate_match_pattern_ne_list lp, | |
339 | xlate_formula a) | |
338 | (_,[lp], a) -> CT_eqn (xlate_match_pattern_ne_list lp, xlate_formula a) | |
339 | | _ -> xlate_error "TODO: disjunctive multiple patterns" | |
340 | 340 | and |
341 | 341 | xlate_binder_ne_list = function |
342 | 342 | [] -> assert false |
977 | 977 | let id_opt = |
978 | 978 | match out_gen Extratactics.rawwit_in_arg_hyp id_opt with |
979 | 979 | | None -> ctv_ID_OPT_NONE |
980 | | Some id -> ctf_ID_OPT_SOME (xlate_ident id) | |
980 | | Some (_,id) -> ctf_ID_OPT_SOME (xlate_ident id) | |
981 | 981 | in |
982 | 982 | let tac_opt = |
983 | 983 | match out_gen (Extratactics.rawwit_by_arg_tac) tac_opt with |
2034 | 2034 | | VernacExtend (s, l) -> |
2035 | 2035 | CT_user_vernac |
2036 | 2036 | (CT_ident s, CT_varg_list (List.map coerce_genarg_to_VARG l)) |
2037 | | VernacDebug b -> xlate_error "Debug On/Off not supported" | |
2038 | 2037 | | VernacList((_, a)::l) -> |
2039 | 2038 | CT_coerce_COMMAND_LIST_to_COMMAND |
2040 | 2039 | (CT_command_list(xlate_vernac a, |
48 | 48 | | Tvar : nat -> term. |
49 | 49 | |
50 | 50 | Delimit Scope romega_scope with term. |
51 | Arguments Scope Tplus [romega_scope romega_scope]. | |
52 | Arguments Scope Tmult [romega_scope romega_scope]. | |
53 | Arguments Scope Tminus [romega_scope romega_scope]. | |
54 | Arguments Scope Topp [romega_scope romega_scope]. | |
55 | ||
51 | 56 | Infix "+" := Tplus : romega_scope. |
52 | 57 | Infix "*" := Tmult : romega_scope. |
53 | 58 | Infix "-" := Tminus : romega_scope. |
19 | 19 | End FixPoint. |
20 | 20 | |
21 | 21 | End Well_founded. |
22 | ||
23 | Require Import Wf_nat. | |
24 | Require Import Lt. | |
25 | ||
26 | Section Well_founded_measure. | |
27 | Variable A : Set. | |
28 | Variable f : A -> nat. | |
29 | Definition R := fun x y => f x < f y. | |
30 | ||
31 | Section FixPoint. | |
32 | ||
33 | Variable P : A -> Set. | |
34 | ||
35 | Variable F_sub : forall x:A, (forall y: { y : A | f y < f x }, P (proj1_sig y)) -> P x. | |
36 | ||
37 | Fixpoint Fix_measure_F_sub (x : A) (r : Acc lt (f x)) {struct r} : P x := | |
38 | F_sub x (fun y: { y : A | f y < f x} => Fix_measure_F_sub (proj1_sig y) | |
39 | (Acc_inv r (f (proj1_sig y)) (proj2_sig y))). | |
40 | ||
41 | Definition Fix_measure_sub (x : A) := Fix_measure_F_sub x (lt_wf (f x)). | |
42 | ||
43 | End FixPoint. | |
44 | ||
45 | End Well_founded_measure. |
33 | 33 | simpl ; auto. |
34 | 34 | Qed. |
35 | 35 | |
36 | Ltac destruct_one_pair := | |
37 | match goal with | |
38 | | [H : (ex _) |- _] => destruct H | |
39 | | [H : (ex2 _) |- _] => destruct H | |
40 | | [H : (sig _) |- _] => destruct H | |
41 | | [H : (_ /\ _) |- _] => destruct H | |
42 | end. | |
43 | ||
44 | Ltac destruct_exists := repeat (destruct_one_pair) . | |
45 |
15 | 15 | Array.of_list (List.rev (Array.to_list arr)) |
16 | 16 | |
17 | 17 | let trace s = |
18 | if !Options.debug then msgnl s | |
18 | if !Options.debug then (msgnl s; msgerr s) | |
19 | 19 | else () |
20 | 20 | |
21 | 21 | (** Utilities to find indices in lists *) |
36 | 36 | let subst_evars evs n t = |
37 | 37 | let evar_info id = |
38 | 38 | let rec aux i = function |
39 | (k, h, v) :: tl -> if k = id then (i, h, v) else aux (succ i) tl | |
39 | (k, h, v) :: tl -> | |
40 | trace (str "Searching for " ++ int id ++ str " found: " ++ int k); | |
41 | if k = id then (i, h, v) else aux (succ i) tl | |
40 | 42 | | [] -> raise Not_found |
41 | 43 | in |
42 | 44 | let (idx, hyps, v) = aux 0 evs in |
44 | 46 | in |
45 | 47 | let rec substrec depth c = match kind_of_term c with |
46 | 48 | | Evar (k, args) -> |
47 | (try | |
48 | let index, hyps = evar_info k in | |
49 | (try trace (str "Evar " ++ int k ++ str " found, applied to " ++ int (Array.length args) ++ str "arguments," ++ | |
50 | int (List.length hyps) ++ str " hypotheses"); with _ -> () ); | |
51 | ||
52 | let ex = mkRel (index + depth) in | |
53 | (* Evar arguments are created in inverse order, | |
54 | and we must not apply to defined ones (i.e. LetIn's) | |
55 | *) | |
56 | let args = | |
57 | let rec aux hyps args acc = | |
58 | match hyps, args with | |
59 | ((_, None, _) :: tlh), (c :: tla) -> | |
60 | aux tlh tla ((map_constr_with_binders succ substrec depth c) :: acc) | |
61 | | ((_, Some _, _) :: tlh), (_ :: tla) -> | |
62 | aux tlh tla acc | |
63 | | [], [] -> acc | |
64 | | _, _ -> failwith "subst_evars: invalid argument" | |
65 | in aux hyps (Array.to_list args) [] | |
66 | in | |
67 | mkApp (ex, Array.of_list args) | |
68 | with Not_found -> | |
69 | anomaly ("eterm: existential variable " ^ string_of_int k ^ " not found")) | |
49 | (let index, hyps = | |
50 | try evar_info k | |
51 | with Not_found -> | |
52 | anomaly ("eterm: existential variable " ^ string_of_int k ^ " not found") | |
53 | in | |
54 | (try trace (str "Evar " ++ int k ++ str " found, applied to " ++ int (Array.length args) ++ str "arguments," ++ | |
55 | int (List.length hyps) ++ str " hypotheses"); with _ -> () ); | |
56 | let ex = mkRel (index + depth) in | |
57 | (* Evar arguments are created in inverse order, | |
58 | and we must not apply to defined ones (i.e. LetIn's) | |
59 | *) | |
60 | let args = | |
61 | let rec aux hyps args acc = | |
62 | match hyps, args with | |
63 | ((_, None, _) :: tlh), (c :: tla) -> | |
64 | aux tlh tla ((map_constr_with_binders succ substrec depth c) :: acc) | |
65 | | ((_, Some _, _) :: tlh), (_ :: tla) -> | |
66 | aux tlh tla acc | |
67 | | [], [] -> acc | |
68 | | _, _ -> failwith "subst_evars: invalid argument" | |
69 | in aux hyps (Array.to_list args) [] | |
70 | in | |
71 | mkApp (ex, Array.of_list args)) | |
70 | 72 | | _ -> map_constr_with_binders succ substrec depth c |
71 | 73 | in |
72 | 74 | substrec 0 t |
105 | 107 | let eterm_term evm t tycon = |
106 | 108 | (* 'Serialize' the evars, we assume that the types of the existentials |
107 | 109 | refer to previous existentials in the list only *) |
108 | let evl = to_list evm in | |
110 | let evl = List.rev (to_list evm) in | |
111 | trace (str "Eterm, transformed to list"); | |
109 | 112 | let evts = |
110 | 113 | (* Remove existential variables in types and build the corresponding products *) |
111 | 114 | fold_right |
112 | 115 | (fun (id, ev) l -> |
116 | trace (str "Eterm: " ++ str "treating evar: " ++ int id); | |
113 | 117 | let hyps = Environ.named_context_of_val ev.evar_hyps in |
114 | 118 | let y' = (id, hyps, etype_of_evar l ev hyps) in |
115 | 119 | y' :: l) |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (* $Id: subtac.ml 8889 2006-06-01 20:23:56Z msozeau $ *) | |
8 | (* $Id: subtac.ml 8964 2006-06-20 13:52:21Z msozeau $ *) | |
9 | 9 | |
10 | 10 | open Global |
11 | 11 | open Pp |
42 | 42 | let require_library dirpath = |
43 | 43 | let qualid = (dummy_loc, qualid_of_dirpath (dirpath_of_string dirpath)) in |
44 | 44 | Library.require_library [qualid] None |
45 | ||
45 | (* | |
46 | 46 | let subtac_one_fixpoint env isevars (f, decl) = |
47 | 47 | let ((id, n, bl, typ, body), decl) = |
48 | 48 | Subtac_interp_fixpoint.rewrite_fixpoint env [] (f, decl) |
52 | 52 | Ppconstr.pr_constr_expr body) |
53 | 53 | with _ -> () |
54 | 54 | in ((id, n, bl, typ, body), decl) |
55 | ||
55 | *) | |
56 | 56 | |
57 | 57 | let subtac_fixpoint isevars l = |
58 | 58 | (* TODO: Copy command.build_recursive *) |
0 | 0 | val require_library : string -> unit |
1 | val subtac_one_fixpoint : | |
2 | 'a -> | |
3 | 'b -> | |
4 | (Names.identifier * (int * Topconstr.recursion_order_expr) * | |
5 | Topconstr.local_binder list * Topconstr.constr_expr * | |
6 | Topconstr.constr_expr) * | |
7 | 'c -> | |
8 | (Names.identifier * (int * Topconstr.recursion_order_expr) * | |
9 | Topconstr.local_binder list * Topconstr.constr_expr * | |
10 | Topconstr.constr_expr) * | |
11 | 'c | |
12 | 1 | val subtac_fixpoint : 'a -> 'b -> unit |
13 | 2 | val subtac : Util.loc * Vernacexpr.vernac_expr -> unit |
4 | 4 | (* // * This file is distributed under the terms of the *) |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | (* $Id: subtac_coercion.ml 8889 2006-06-01 20:23:56Z msozeau $ *) | |
7 | (* $Id: subtac_coercion.ml 8964 2006-06-20 13:52:21Z msozeau $ *) | |
8 | 8 | |
9 | 9 | open Util |
10 | 10 | open Names |
105 | 105 | : (Term.constr -> Term.constr) option |
106 | 106 | = |
107 | 107 | let x = nf_evar (evars_of !isevars) x and y = nf_evar (evars_of !isevars) y in |
108 | (try trace (str "Coerce called for " ++ (my_print_constr env x) ++ | |
108 | (try debug 1 (str "Coerce called for " ++ (my_print_constr env x) ++ | |
109 | 109 | str " and "++ my_print_constr env y ++ |
110 | 110 | str " with evars: " ++ spc () ++ |
111 | 111 | my_print_evardefs !isevars); |
112 | 112 | with _ -> ()); |
113 | 113 | let rec coerce_unify env x y = |
114 | (try trace (str "coerce_unify from " ++ (my_print_constr env x) ++ | |
114 | (try debug 1 (str "coerce_unify from " ++ (my_print_constr env x) ++ | |
115 | 115 | str " to "++ my_print_constr env y) |
116 | 116 | with _ -> ()); |
117 | 117 | try |
118 | 118 | isevars := the_conv_x_leq env x y !isevars; |
119 | (try (trace (str "Unified " ++ (my_print_constr env x) ++ | |
120 | str " and "++ my_print_constr env y)); | |
119 | (try debug 1 (str "Unified " ++ (my_print_constr env x) ++ | |
120 | str " and "++ my_print_constr env y); | |
121 | 121 | with _ -> ()); |
122 | 122 | None |
123 | 123 | with Reduction.NotConvertible -> coerce' env (hnf env isevars x) (hnf env isevars y) |
124 | 124 | and coerce' env x y : (Term.constr -> Term.constr) option = |
125 | 125 | let subco () = subset_coerce env isevars x y in |
126 | (try trace (str "coerce' from " ++ (my_print_constr env x) ++ | |
126 | (try debug 1 (str "coerce' from " ++ (my_print_constr env x) ++ | |
127 | 127 | str " to "++ my_print_constr env y); |
128 | 128 | with _ -> ()); |
129 | 129 | match (kind_of_term x, kind_of_term y) with |
369 | 369 | |
370 | 370 | let rec inh_conv_coerce_to_fail loc env isevars v t c1 = |
371 | 371 | (try |
372 | trace (str "inh_conv_coerce_to_fail called for " ++ | |
372 | debug 1 (str "inh_conv_coerce_to_fail called for " ++ | |
373 | 373 | Termops.print_constr_env env t ++ str " and "++ spc () ++ |
374 | 374 | Termops.print_constr_env env c1 ++ str " with evars: " ++ spc () ++ |
375 | 375 | Evd.pr_evar_defs isevars ++ str " in env: " ++ spc () ++ |
435 | 435 | (* Look for cj' obtained from cj by inserting coercions, s.t. cj'.typ = t *) |
436 | 436 | let inh_conv_coerce_to loc env isevars cj ((n, t) as tycon) = |
437 | 437 | (try |
438 | trace (str "Subtac_coercion.inh_conv_coerce_to called for " ++ | |
438 | debug 1 (str "Subtac_coercion.inh_conv_coerce_to called for " ++ | |
439 | 439 | Termops.print_constr_env env cj.uj_type ++ str " and "++ spc () ++ |
440 | 440 | Evarutil.pr_tycon_type env tycon ++ str " with evars: " ++ spc () ++ |
441 | 441 | Evd.pr_evar_defs isevars ++ str " in env: " ++ spc () ++ |
460 | 460 | |
461 | 461 | let inh_conv_coerces_to loc env isevars t ((abs, t') as tycon) = |
462 | 462 | (try |
463 | trace (str "Subtac_coercion.inh_conv_coerces_to called for " ++ | |
463 | debug 1 (str "Subtac_coercion.inh_conv_coerces_to called for " ++ | |
464 | 464 | Termops.print_constr_env env t ++ str " and "++ spc () ++ |
465 | 465 | Evarutil.pr_tycon_type env tycon ++ str " with evars: " ++ spc () ++ |
466 | 466 | Evd.pr_evar_defs isevars ++ str " in env: " ++ spc () ++ |
116 | 116 | |
117 | 117 | let list_chop_hd i l = match list_chop i l with |
118 | 118 | | (l1,x::l2) -> (l1,x,l2) |
119 | | _ -> assert false | |
119 | | (x :: [], l2) -> ([], x, []) | |
120 | | _ -> assert(false) | |
120 | 121 | |
121 | 122 | let collect_non_rec env = |
122 | 123 | let rec searchrec lnonrec lnamerec ldefrec larrec nrec = |
172 | 173 | | [] -> List.rev acc |
173 | 174 | in aux [] l |
174 | 175 | |
175 | let build_recursive (lnameargsardef:(fixpoint_expr * decl_notation) list) boxed = | |
176 | let lift_binders k n l = | |
177 | let rec aux n = function | |
178 | | (id, t, c) :: tl -> (id, option_map (liftn k n) t, liftn k n c) :: aux (pred n) tl | |
179 | | [] -> [] | |
180 | in aux n l | |
181 | ||
182 | let rec gen_rels = function | |
183 | 0 -> [] | |
184 | | n -> mkRel n :: gen_rels (pred n) | |
185 | ||
186 | let build_wellfounded (recname, n, bl,arityc,body) r measure notation boxed = | |
187 | let sigma = Evd.empty in | |
188 | let isevars = ref (Evd.create_evar_defs sigma) in | |
189 | let env = Global.env() in | |
190 | let pr c = my_print_constr env c in | |
191 | let prr = Printer.pr_rel_context env in | |
192 | let pr_rel env = Printer.pr_rel_context env in | |
193 | let _ = | |
194 | try debug 2 (str "Rewriting fixpoint: " ++ Ppconstr.pr_id recname ++ | |
195 | Ppconstr.pr_binders bl ++ str " : " ++ | |
196 | Ppconstr.pr_constr_expr arityc ++ str " := " ++ spc () ++ | |
197 | Ppconstr.pr_constr_expr body) | |
198 | with _ -> () | |
199 | in | |
200 | let env', binders_rel = interp_context isevars env bl in | |
201 | let after, ((argname, _, argtyp) as arg), before = list_chop_hd (succ n) binders_rel in | |
202 | let before_length, after_length = List.length before, List.length after in | |
203 | let argid = match argname with Name n -> n | _ -> assert(false) in | |
204 | let _liftafter = lift_binders 1 after_length after in | |
205 | let envwf = push_rel_context before env in | |
206 | let wf_rel, measure_fn = | |
207 | let rconstr = interp_constr isevars envwf r in | |
208 | if measure then | |
209 | let lt_rel = constr_of_global (Lazy.force lt_ref) in | |
210 | let name s = Name (id_of_string s) in | |
211 | mkLambda (name "x", argtyp, | |
212 | mkLambda (name "y", argtyp, | |
213 | mkApp (lt_rel, | |
214 | [| mkApp (rconstr, [| mkRel 2 |]) ; | |
215 | mkApp (rconstr, [| mkRel 1 |]) |]))), | |
216 | Some rconstr | |
217 | else rconstr, None | |
218 | in | |
219 | let wf_proof = mkApp (Lazy.force well_founded, [| argtyp ; wf_rel |]) | |
220 | in | |
221 | let argid' = id_of_string (string_of_id argid ^ "'") in | |
222 | let wfarg len = (Name argid', None, | |
223 | mkSubset (Name argid') argtyp | |
224 | (mkApp (wf_rel, [|mkRel 1; mkRel (len + 1)|]))) | |
225 | in | |
226 | let top_bl = after @ (arg :: before) in | |
227 | let intern_bl = after @ (wfarg 1 :: arg :: before) in | |
228 | let top_env = push_rel_context top_bl env in | |
229 | let intern_env = push_rel_context intern_bl env in | |
230 | let top_arity = interp_type isevars top_env arityc in | |
231 | (try debug 2 (str "Intern bl: " ++ prr intern_bl) with _ -> ()); | |
232 | let proj = (Lazy.force sig_).Coqlib.proj1 in | |
233 | let projection = | |
234 | mkApp (proj, [| argtyp ; | |
235 | (mkLambda (Name argid', argtyp, | |
236 | (mkApp (wf_rel, [|mkRel 1; mkRel 3|])))) ; | |
237 | mkRel 1 | |
238 | |]) | |
239 | in | |
240 | (try debug 2 (str "Top arity: " ++ my_print_constr top_env top_arity) with _ -> ()); | |
241 | let intern_arity = substnl [projection] after_length top_arity in | |
242 | (try debug 2 (str "Top arity after subst: " ++ my_print_constr intern_env intern_arity) with _ -> ()); | |
243 | let intern_before_env = push_rel_context before env in | |
244 | let intern_fun_bl = after @ [wfarg 1] in | |
245 | (try debug 2 (str "Intern fun bl: " ++ prr intern_fun_bl) with _ -> ()); | |
246 | let intern_fun_arity = intern_arity in | |
247 | (try debug 2 (str "Intern fun arity: " ++ | |
248 | my_print_constr intern_env intern_fun_arity) with _ -> ()); | |
249 | let intern_fun_arity_prod = it_mkProd_or_LetIn intern_fun_arity intern_fun_bl in | |
250 | let intern_fun_binder = (Name recname, None, intern_fun_arity_prod) in | |
251 | let fun_bl = after @ (intern_fun_binder :: [arg]) in | |
252 | (try debug 2 (str "Fun bl: " ++ pr_rel intern_before_env fun_bl ++ spc ()) with _ -> ()); | |
253 | let fun_env = push_rel_context fun_bl intern_before_env in | |
254 | let fun_arity = interp_type isevars fun_env arityc in | |
255 | let intern_body = interp_casted_constr isevars fun_env body fun_arity in | |
256 | let intern_body_lam = it_mkLambda_or_LetIn intern_body fun_bl in | |
257 | let _ = | |
258 | try debug 2 (str "Fun bl: " ++ prr fun_bl ++ spc () ++ | |
259 | str "Intern bl" ++ prr intern_bl ++ spc () ++ | |
260 | str "Top bl" ++ prr top_bl ++ spc () ++ | |
261 | str "Intern arity: " ++ pr intern_arity ++ | |
262 | str "Top arity: " ++ pr top_arity ++ spc () ++ | |
263 | str "Intern body " ++ pr intern_body_lam) | |
264 | with _ -> () | |
265 | in | |
266 | let _impl = | |
267 | if Impargs.is_implicit_args() | |
268 | then Impargs.compute_implicits top_env top_arity | |
269 | else [] | |
270 | in | |
271 | let prop = mkLambda (Name argid, argtyp, it_mkProd_or_LetIn top_arity after) in | |
272 | let fix_def = | |
273 | match measure_fn with | |
274 | None -> | |
275 | mkApp (constr_of_reference (Lazy.force fix_sub_ref), | |
276 | [| argtyp ; | |
277 | wf_rel ; | |
278 | make_existential dummy_loc intern_before_env isevars wf_proof ; | |
279 | prop ; | |
280 | intern_body_lam |]) | |
281 | | Some f -> | |
282 | mkApp (constr_of_reference (Lazy.force fix_measure_sub_ref), | |
283 | [| argtyp ; f ; prop ; | |
284 | intern_body_lam |]) | |
285 | in | |
286 | let def_appl = applist (fix_def, gen_rels (after_length + 1)) in | |
287 | let def = it_mkLambda_or_LetIn def_appl binders_rel in | |
288 | let typ = it_mkProd_or_LetIn top_arity binders_rel in | |
289 | debug 2 (str "Constructed def"); | |
290 | debug 2 (my_print_constr intern_before_env def); | |
291 | debug 2 (str "Type: " ++ my_print_constr env typ); | |
292 | let fullcoqc = Evarutil.nf_isevar !isevars def in | |
293 | let fullctyp = Evarutil.nf_isevar !isevars typ in | |
294 | let _ = try trace (str "After evar normalization: " ++ spc () ++ | |
295 | str "Coq term: " ++ my_print_constr env fullcoqc ++ spc () | |
296 | ++ str "Coq type: " ++ my_print_constr env fullctyp) | |
297 | with _ -> () | |
298 | in | |
299 | let evm = non_instanciated_map env isevars in | |
300 | let _ = try trace (str "Non instanciated evars map: " ++ Evd.pr_evar_map evm) with _ -> () in | |
301 | let evars_def, evars_typ, evars = Eterm.eterm_term evm fullcoqc (Some fullctyp) in | |
302 | let evars_typ = out_some evars_typ in | |
303 | (try trace (str "Building evars sum for : "); | |
304 | List.iter | |
305 | (fun (n, t) -> trace (str "Evar " ++ str (string_of_id n) ++ spc () ++ my_print_constr env t)) | |
306 | evars; | |
307 | with _ -> ()); | |
308 | let (sum_tac, sumg) = Subtac_utils.build_dependent_sum evars in | |
309 | (try trace (str "Evars sum: " ++ my_print_constr env sumg); | |
310 | trace (str "Evars type: " ++ my_print_constr env evars_typ); | |
311 | with _ -> ()); | |
312 | let proofid = id_of_string (string_of_id recname ^ "_evars_proof") in | |
313 | Command.start_proof proofid goal_proof_kind sumg | |
314 | (fun strength gr -> | |
315 | debug 2 (str "Proof finished"); | |
316 | let def = constr_of_global gr in | |
317 | let args = Subtac_utils.destruct_ex def sumg in | |
318 | let _, newdef = decompose_lam_n (List.length args) evars_def in | |
319 | let constr = Term.substl (List.rev args) newdef in | |
320 | debug 2 (str "Applied existentials : " ++ my_print_constr env constr); | |
321 | let ce = | |
322 | { const_entry_body = constr; | |
323 | const_entry_type = Some fullctyp; | |
324 | const_entry_opaque = false; | |
325 | const_entry_boxed = boxed} | |
326 | in | |
327 | let _constant = Declare.declare_constant | |
328 | recname (DefinitionEntry ce,IsDefinition Definition) | |
329 | in | |
330 | definition_message recname); | |
331 | trace (str "Started existentials proof"); | |
332 | Pfedit.by sum_tac; | |
333 | trace (str "Applied sum tac") | |
334 | ||
335 | let build_mutrec l boxed = | |
176 | 336 | let sigma = Evd.empty |
177 | 337 | and env0 = Global.env() |
178 | 338 | in |
179 | 339 | let lnameargsardef = |
180 | 340 | (*List.map (fun (f, d) -> Subtac_interp_fixpoint.rewrite_fixpoint env0 protos (f, d))*) |
181 | lnameargsardef | |
341 | l | |
182 | 342 | in |
183 | 343 | let lrecnames = List.map (fun ((f,_,_,_,_),_) -> f) lnameargsardef |
184 | 344 | and nv = List.map (fun ((_,n,_,_,_),_) -> n) lnameargsardef |
185 | 345 | in |
186 | (* Build the recursive context and notations for the recursive types *) | |
346 | (* Build the recursive context and notations for the recursive types *) | |
187 | 347 | let (rec_sign,rec_impls,arityl) = |
188 | 348 | List.fold_left |
189 | (fun (env,impls,arl) ((recname,(n, ro),bl,arityc,body),_) -> | |
190 | let isevars = ref (Evd.create_evar_defs sigma) in | |
191 | match ro with | |
192 | CStructRec -> | |
193 | let arityc = Command.generalize_constr_expr arityc bl in | |
194 | let arity = interp_type isevars env0 arityc in | |
195 | let impl = | |
196 | if Impargs.is_implicit_args() | |
197 | then Impargs.compute_implicits env0 arity | |
198 | else [] in | |
199 | let impls' =(recname,([],impl,compute_arguments_scope arity))::impls in | |
200 | (Environ.push_named (recname,None,arity) env, impls', (isevars, None, arity)::arl) | |
201 | | CWfRec r -> | |
202 | let n = out_some n in | |
203 | let _ = | |
204 | try trace (str "Rewriting fixpoint: " ++ Ppconstr.pr_id recname ++ | |
205 | Ppconstr.pr_binders bl ++ str " : " ++ | |
206 | Ppconstr.pr_constr_expr arityc ++ str " := " ++ spc () ++ | |
207 | Ppconstr.pr_constr_expr body) | |
208 | with _ -> () | |
209 | in | |
210 | let env', binders_rel = interp_context isevars env0 bl in | |
211 | let after, ((argname, _, argtyp) as arg), before = list_chop_hd n binders_rel in | |
212 | let argid = match argname with Name n -> n | _ -> assert(false) in | |
213 | let after' = List.map (fun (n, c, t) -> (n, option_map (lift 1) c, lift 1 t)) after in | |
214 | let envwf = push_rel_context before env0 in | |
215 | let wf_rel = interp_constr isevars envwf r in | |
216 | let accarg_id = id_of_string ("Acc_" ^ string_of_id argid) in | |
217 | let accarg = (Name accarg_id, None, mkApp (Lazy.force acc_inv, [| argtyp; wf_rel; mkRel 1 |])) in | |
218 | let argid' = id_of_string (string_of_id argid ^ "'") in | |
219 | let before_length, after_length = List.length before, List.length after in | |
220 | let full_length = before_length + 1 + after_length in | |
221 | let wfarg len = (Name argid, None, | |
222 | mkSubset (Name argid') argtyp | |
223 | (mkApp (wf_rel, [|mkRel 1; mkRel (len + 1)|]))) | |
224 | in | |
225 | let new_bl = after' @ (accarg :: arg :: before) | |
226 | and intern_bl = after @ (wfarg (before_length + 1) :: before) | |
227 | in | |
228 | let intern_env = push_rel_context intern_bl env0 in | |
229 | let env' = push_rel_context new_bl env0 in | |
230 | let arity = interp_type isevars intern_env arityc in | |
231 | let intern_arity = it_mkProd_or_LetIn arity intern_bl in | |
232 | let arity' = interp_type isevars env' arityc in | |
233 | let arity' = it_mkProd_or_LetIn arity' new_bl in | |
234 | let fun_bl = after @ ((Name recname, None, intern_arity) :: arg :: before) in | |
235 | let _ = | |
236 | let pr c = my_print_constr env c in | |
237 | let prr = Printer.pr_rel_context env in | |
238 | try trace (str "Fun bl: " ++ prr fun_bl ++ spc () ++ | |
239 | str "Intern bl" ++ prr intern_bl ++ spc () ++ | |
240 | str "Extern bl" ++ prr new_bl ++ spc () ++ | |
241 | str "Intern arity: " ++ pr intern_arity) | |
242 | with _ -> () | |
243 | in | |
244 | let impl = | |
245 | if Impargs.is_implicit_args() | |
246 | then Impargs.compute_implicits intern_env arity' | |
247 | else [] in | |
248 | let impls' = (recname,([],impl,compute_arguments_scope arity'))::impls in | |
249 | (Environ.push_named (recname,None,arity') env, impls', | |
250 | (isevars, Some (full_length - n, argtyp, wf_rel, fun_bl, intern_bl, intern_arity), arity')::arl)) | |
349 | (fun (env,impls,arl) ((recname, n, bl,arityc,body),_) -> | |
350 | let isevars = ref (Evd.create_evar_defs sigma) in | |
351 | let arityc = Command.generalize_constr_expr arityc bl in | |
352 | let arity = interp_type isevars env0 arityc in | |
353 | let impl = | |
354 | if Impargs.is_implicit_args() | |
355 | then Impargs.compute_implicits env0 arity | |
356 | else [] in | |
357 | let impls' =(recname,([],impl,compute_arguments_scope arity))::impls in | |
358 | (Environ.push_named (recname,None,arity) env, impls', (isevars, None, arity)::arl)) | |
251 | 359 | (env0,[],[]) lnameargsardef in |
252 | 360 | let arityl = List.rev arityl in |
253 | 361 | let notations = |
282 | 390 | |
283 | 391 | let (lnonrec,(namerec,defrec,arrec,nvrec)) = |
284 | 392 | collect_non_rec env0 lrecnames recdef arityl nv in |
285 | let nvrec' = Array.map (function (Some n,_) -> n | _ -> 0) nvrec in(* ignore rec order *) | |
286 | 393 | let declare arrec defrec = |
287 | 394 | let recvec = |
288 | 395 | Array.map (subst_vars (List.rev (Array.to_list namerec))) defrec in |
292 | 399 | my_print_constr env0 (recvec.(i))); |
293 | 400 | with _ -> ()); |
294 | 401 | let ce = |
295 | { const_entry_body = mkFix ((nvrec',i),recdecls); | |
402 | { const_entry_body = mkFix ((nvrec,i),recdecls); | |
296 | 403 | const_entry_type = Some arrec.(i); |
297 | 404 | const_entry_opaque = false; |
298 | 405 | const_entry_boxed = boxed} in |
383 | 490 | match sum with Some (sumtac, sumg) -> Some (id, kn, sumg, sumtac) | None -> None) |
384 | 491 | defs |
385 | 492 | in |
493 | match real_evars with | |
494 | [] -> declare (List.rev_map (fun (id, c, _) -> | |
495 | snd (decompose_lam_n recdefs c)) defs) | |
496 | | l -> | |
497 | ||
386 | 498 | Subtac_utils.and_tac real_evars |
387 | 499 | (fun f _ gr -> |
388 | 500 | let _ = trace (str "Got a proof of: " ++ pr_global gr ++ |
430 | 542 | Environ.NoBody -> trace (str "Constant has no body") |
431 | 543 | | Environ.Opaque -> trace (str "Constant is opaque") |
432 | 544 | ) |
545 | ||
546 | let out_n = function | |
547 | Some n -> n | |
548 | | None -> 0 | |
549 | ||
550 | let build_recursive (lnameargsardef:(fixpoint_expr * decl_notation) list) boxed = | |
551 | match lnameargsardef with | |
552 | | ((id, (n, CWfRec r), bl, typ, body), no) :: [] -> | |
553 | build_wellfounded (id, out_n n, bl, typ, body) r false no boxed | |
554 | | ((id, (n, CMeasureRec r), bl, typ, body), no) :: [] -> | |
555 | build_wellfounded (id, out_n n, bl, typ, body) r true no boxed | |
556 | | l -> | |
557 | let lnameargsardef = | |
558 | List.map (fun ((id, (n, ro), bl, typ, body), no) -> | |
559 | match ro with | |
560 | CStructRec -> (id, out_n n, bl, typ, body), no | |
561 | | CWfRec _ | CMeasureRec _ -> | |
562 | errorlabstrm "Subtac_command.build_recursive" | |
563 | (str "Well-founded fixpoints not allowed in mutually recursive blocks")) | |
564 | lnameargsardef | |
565 | in | |
566 | build_mutrec lnameargsardef boxed; | |
567 | assert(false) | |
433 | 568 | |
434 | 569 |
37 | 37 | constr_expr -> unsafe_judgment |
38 | 38 | val list_chop_hd : int -> 'a list -> 'a list * 'a * 'a list |
39 | 39 | val recursive_message : global_reference array -> std_ppcmds |
40 | ||
40 | 41 | val build_recursive : |
41 | 42 | (fixpoint_expr * decl_notation) list -> bool -> unit |
59 | 59 | |
60 | 60 | |
61 | 61 | let rec rewrite_rec_calls l c = c |
62 | ||
62 | (* | |
63 | 63 | let rewrite_fixpoint env l (f, decl) = |
64 | 64 | let (id, (n, ro), bl, typ, body) = f in |
65 | 65 | let body = rewrite_rec_calls l body in |
150 | 150 | Ppconstr.pr_constr_expr body') |
151 | 151 | in (id, (succ n, ro), bl', typ, body'), decl |
152 | 152 | |
153 | *) |
14 | 14 | val pr_binder_list : |
15 | 15 | (('a * Names.name) * Topconstr.constr_expr) list -> Pp.std_ppcmds |
16 | 16 | val rewrite_rec_calls : 'a -> 'b -> 'b |
17 | val rewrite_fixpoint : | |
18 | 'a -> | |
19 | 'b -> | |
20 | (Names.identifier * (int * Topconstr.recursion_order_expr) * | |
21 | Topconstr.local_binder list * Topconstr.constr_expr * | |
22 | Topconstr.constr_expr) * | |
23 | 'c -> | |
24 | (Names.identifier * (int * Topconstr.recursion_order_expr) * | |
25 | Topconstr.local_binder list * Topconstr.constr_expr * | |
26 | Topconstr.constr_expr) * | |
27 | 'c |
21 | 21 | let ex_pi1 = lazy (init_constant utils_module "ex_pi1") |
22 | 22 | let ex_pi2 = lazy (init_constant utils_module "ex_pi2") |
23 | 23 | |
24 | let make_ref s = Qualid (dummy_loc, (qualid_of_string s)) | |
25 | let well_founded_ref = make_ref "Init.Wf.Well_founded" | |
26 | let acc_ref = make_ref "Init.Wf.Acc" | |
27 | let acc_inv_ref = make_ref "Init.Wf.Acc_inv" | |
28 | let fix_sub_ref = make_ref "Coq.subtac.FixSub.Fix_sub" | |
29 | let lt_wf_ref = make_ref "Coq.Wf_nat.lt_wf" | |
24 | let make_ref l s = lazy (init_reference l s) | |
25 | let well_founded_ref = make_ref ["Init";"Wf"] "Well_founded" | |
26 | let acc_ref = make_ref ["Init";"Wf"] "Acc" | |
27 | let acc_inv_ref = make_ref ["Init";"Wf"] "Acc_inv" | |
28 | let fix_sub_ref = make_ref ["subtac";"FixSub"] "Fix_sub" | |
29 | let fix_measure_sub_ref = make_ref ["subtac";"FixSub"] "Fix_measure_sub" | |
30 | let lt_ref = make_ref ["Init";"Peano"] "lt" | |
31 | let lt_wf_ref = make_ref ["Wf_nat"] "lt_wf" | |
32 | ||
33 | let make_ref s = Qualid (dummy_loc, qualid_of_string s) | |
30 | 34 | let sig_ref = make_ref "Init.Specif.sig" |
31 | 35 | let proj1_sig_ref = make_ref "Init.Specif.proj1_sig" |
32 | 36 | let proj2_sig_ref = make_ref "Init.Specif.proj2_sig" |
81 | 85 | |
82 | 86 | let my_print_tycon_type = Evarutil.pr_tycon_type |
83 | 87 | |
88 | let debug_level = 2 | |
84 | 89 | |
85 | 90 | let debug n s = |
86 | if !Options.debug then | |
91 | if !Options.debug && n >= debug_level then | |
87 | 92 | msgnl s |
88 | 93 | else () |
89 | 94 | |
90 | 95 | let debug_msg n s = |
91 | if !Options.debug then s | |
96 | if !Options.debug && n >= debug_level then s | |
92 | 97 | else mt () |
93 | 98 | |
94 | 99 | let trace s = |
95 | if !Options.debug then msgnl s | |
100 | if !Options.debug && debug_level > 0 then msgnl s | |
96 | 101 | else () |
97 | 102 | |
98 | 103 | let wf_relations = Hashtbl.create 10 |
152 | 157 | let global_kind = Decl_kinds.IsDefinition Decl_kinds.Definition |
153 | 158 | let goal_kind = Decl_kinds.Global, Decl_kinds.DefinitionBody Decl_kinds.Definition |
154 | 159 | |
160 | let global_proof_kind = Decl_kinds.IsProof Decl_kinds.Lemma | |
161 | let goal_proof_kind = Decl_kinds.Global, Decl_kinds.Proof Decl_kinds.Lemma | |
162 | ||
155 | 163 | let global_fix_kind = Decl_kinds.IsDefinition Decl_kinds.Fixpoint |
156 | 164 | let goal_fix_kind = Decl_kinds.Global, Decl_kinds.DefinitionBody Decl_kinds.Fixpoint |
157 | 165 | |
163 | 171 | (n, t) :: tl -> |
164 | 172 | let t' = mkLambda (Name n, t, typ) in |
165 | 173 | trace (spc () ++ str ("treating evar " ^ string_of_id n)); |
166 | (try trace (str " assert: " ++ my_print_constr (Global.env ()) t) | |
174 | (try trace (str " assert: " ++ my_print_constr (Global.env ()) t) | |
167 | 175 | with _ -> ()); |
168 | 176 | let tac' = |
169 | 177 | tclTHENS (assert_tac true (Name n) t) |
182 | 190 | (_, hd) :: tl -> aux (intros, hd) tl |
183 | 191 | | [] -> raise (Invalid_argument "build_dependent_sum") |
184 | 192 | |
193 | let id x = x | |
194 | ||
195 | let build_dependent_sum l = | |
196 | let rec aux names conttac conttype = function | |
197 | (n, t) :: ((_ :: _) as tl) -> | |
198 | let hyptype = substl names t in | |
199 | trace (spc () ++ str ("treating evar " ^ string_of_id n)); | |
200 | (try trace (str " assert: " ++ my_print_constr (Global.env ()) hyptype) | |
201 | with _ -> ()); | |
202 | let tac = assert_tac true (Name n) hyptype in | |
203 | let conttac = | |
204 | (fun cont -> | |
205 | conttac | |
206 | (tclTHENS tac | |
207 | ([intros; | |
208 | (tclTHENSEQ | |
209 | [constructor_tac (Some 1) 1 | |
210 | (Rawterm.ImplicitBindings [mkVar n]); | |
211 | cont]); | |
212 | ]))) | |
213 | in | |
214 | let conttype = | |
215 | (fun typ -> | |
216 | let tex = mkLambda (Name n, t, typ) in | |
217 | conttype | |
218 | (mkApp (Lazy.force ex_ind, [| t; tex |]))) | |
219 | in | |
220 | aux (mkVar n :: names) conttac conttype tl | |
221 | | (n, t) :: [] -> | |
222 | (conttac intros, conttype t) | |
223 | | [] -> raise (Invalid_argument "build_dependent_sum") | |
224 | in aux [] id id (List.rev l) | |
225 | ||
185 | 226 | open Proof_type |
186 | 227 | open Tacexpr |
187 | 228 | |
250 | 291 | | _ -> [acc] |
251 | 292 | in aux ex ext |
252 | 293 | |
294 | open Rawterm | |
295 | ||
296 | ||
297 | let list_mapi f = | |
298 | let rec aux i = function | |
299 | hd :: tl -> f i hd :: aux (succ i) tl | |
300 | | [] -> [] | |
301 | in aux 0 | |
302 | ||
303 | let rewrite_cases_aux (loc, po, tml, eqns) = | |
304 | let tml = list_mapi (fun i (c, (n, opt)) -> c, | |
305 | ((match n with | |
306 | Name id -> (match c with | |
307 | | RVar (_, id') when id = id' -> | |
308 | Name (id_of_string (string_of_id id ^ "'")) | |
309 | | _ -> n) | |
310 | | Anonymous -> Name (id_of_string ("x" ^ string_of_int i))), | |
311 | opt)) tml | |
312 | in | |
313 | let mkHole = RHole (dummy_loc, InternalHole) in | |
314 | let mkeq c n = RApp (dummy_loc, RRef (dummy_loc, (Lazy.force eqind_ref)), | |
315 | [mkHole; c; n]) | |
316 | in | |
317 | let eqs_types = | |
318 | List.map | |
319 | (fun (c, (n, _)) -> | |
320 | let id = match n with Name id -> id | _ -> assert false in | |
321 | let heqid = id_of_string ("Heq" ^ string_of_id id) in | |
322 | Name heqid, mkeq c (RVar (dummy_loc, id))) | |
323 | tml | |
324 | in | |
325 | let po = | |
326 | List.fold_right | |
327 | (fun (n,t) acc -> | |
328 | RProd (dummy_loc, Anonymous, t, acc)) | |
329 | eqs_types (match po with | |
330 | Some e -> e | |
331 | | None -> mkHole) | |
332 | in | |
333 | let eqns = | |
334 | List.map (fun (loc, idl, cpl, c) -> | |
335 | let c' = | |
336 | List.fold_left | |
337 | (fun acc (n, t) -> | |
338 | RLambda (dummy_loc, n, mkHole, acc)) | |
339 | c eqs_types | |
340 | in (loc, idl, cpl, c')) | |
341 | eqns | |
342 | in | |
343 | let mk_refl_equal c = RApp (dummy_loc, RRef (dummy_loc, Lazy.force refl_equal_ref), | |
344 | [mkHole; c]) | |
345 | in | |
346 | let refls = List.map (fun (c, _) -> mk_refl_equal c) tml in | |
347 | let case = RCases (loc,Some po,tml,eqns) in | |
348 | let app = RApp (dummy_loc, case, refls) in | |
349 | app | |
350 | ||
351 | let rec rewrite_cases c = | |
352 | match c with | |
353 | RCases _ -> let c' = map_rawconstr rewrite_cases c in | |
354 | (match c' with | |
355 | | RCases (x, y, z, w) -> rewrite_cases_aux (x,y,z,w) | |
356 | | _ -> assert(false)) | |
357 | | _ -> map_rawconstr rewrite_cases c | |
358 | ||
359 | let rewrite_cases env c = | |
360 | let c' = rewrite_cases c in | |
361 | let _ = trace (str "Rewrote cases: " ++ spc () ++ my_print_rawconstr env c') in | |
362 | c' | |
253 | 363 | |
254 | 364 | let list_mapi f = |
255 | 365 | let rec aux i = function |
17 | 17 | val init_constant : string list -> string -> constr |
18 | 18 | val init_reference : string list -> string -> global_reference |
19 | 19 | val fixsub : constr lazy_t |
20 | val make_ref : string -> reference | |
21 | val well_founded_ref : reference | |
22 | val acc_ref : reference | |
23 | val acc_inv_ref : reference | |
24 | val fix_sub_ref : reference | |
25 | val lt_wf_ref : reference | |
20 | val well_founded_ref : global_reference lazy_t | |
21 | val acc_ref : global_reference lazy_t | |
22 | val acc_inv_ref : global_reference lazy_t | |
23 | val fix_sub_ref : global_reference lazy_t | |
24 | val fix_measure_sub_ref : global_reference lazy_t | |
25 | val lt_ref : global_reference lazy_t | |
26 | val lt_wf_ref : global_reference lazy_t | |
26 | 27 | val sig_ref : reference |
27 | 28 | val proj1_sig_ref : reference |
28 | 29 | val proj2_sig_ref : reference |
68 | 69 | val non_instanciated_map : env -> evar_defs ref -> evar_map |
69 | 70 | val global_kind : logical_kind |
70 | 71 | val goal_kind : locality_flag * goal_object_kind |
72 | val global_proof_kind : logical_kind | |
73 | val goal_proof_kind : locality_flag * goal_object_kind | |
71 | 74 | val global_fix_kind : logical_kind |
72 | 75 | val goal_fix_kind : locality_flag * goal_object_kind |
73 | 76 |
4 | 4 | |
5 | 5 | Program Definition myhd : forall { l : list A | length l <> 0 }, A := |
6 | 6 | fun l => |
7 | match l with | |
7 | match `l with | |
8 | 8 | | nil => _ |
9 | 9 | | hd :: tl => hd |
10 | 10 | end. |
11 | 11 | Proof. |
12 | destruct l ; simpl ; intro H ; rewrite <- H in n ; intuition. | |
12 | destruct l ; simpl ; intro H. | |
13 | rewrite H in n ; intuition. | |
13 | 14 | Defined. |
14 | 15 | |
15 | 16 | |
23 | 24 | | hd :: tl => tl |
24 | 25 | end. |
25 | 26 | Proof. |
26 | destruct l ; simpl ; intro H ; rewrite <- H in n ; intuition. | |
27 | destruct l ; simpl ; intro H ; rewrite H in n ; intuition. | |
27 | 28 | Defined. |
28 | 29 | |
29 | 30 | Extraction mytail. |
49 | 50 | | nil => l' |
50 | 51 | | hd :: tl => hd :: (append tl l') |
51 | 52 | end. |
52 | simpl. | |
53 | 53 | subst ; auto. |
54 | 54 | simpl ; rewrite (subset_simpl (append tl0 l')). |
55 | 55 | simpl ; subst. |
0 | Fixpoint f (a : nat) : nat := match a with 0 => 0 | |
1 | | S a' => g a a' | |
0 | Program Fixpoint f (a : nat) : nat := | |
1 | match a with | |
2 | | 0 => 0 | |
3 | | S a' => g a a' | |
2 | 4 | end |
3 | 5 | with g (a b : nat) { struct b } : nat := |
4 | match b with 0 => 0 | |
6 | match b with | |
7 | | 0 => 0 | |
5 | 8 | | S b' => f b' |
6 | end.⏎ | |
9 | end. | |
10 | ||
11 | Check f. | |
12 | Check g.⏎ |
11 | 11 | Defined. |
12 | 12 | |
13 | 13 | Extraction testsig. |
14 | Extraction sigS. | |
15 | Extract Inductive sigS => "" [ "" ]. | |
14 | Extraction sig. | |
15 | Extract Inductive sig => "" [ "" ]. | |
16 | 16 | Extraction testsig. |
17 | 17 | |
18 | 18 | Require Import Coq.Arith.Compare_dec. |
0 | Notation "( x & y )" := (@existS _ _ x y) : core_scope. | |
1 | Unset Printing All. | |
2 | Require Import Coq.Arith.Compare_dec. | |
3 | ||
4 | Require Import Coq.subtac.Utils. | |
5 | ||
6 | Fixpoint size (a : nat) : nat := | |
7 | match a with | |
8 | 0 => 1 | |
9 | | S n => S (size n) | |
10 | end. | |
11 | ||
12 | Program Fixpoint test_measure (a : nat) {measure a size} : nat := | |
13 | match a with | |
14 | | S (S n) => S (test_measure n) | |
15 | | x => x | |
16 | end. | |
17 | subst. | |
18 | unfold n0. | |
19 | auto with arith. | |
20 | Qed. | |
21 | ||
22 | Check test_measure. | |
23 | Print test_measure.⏎ |
0 | Notation "( x & y )" := (@existS _ _ x y) : core_scope. | |
1 | Unset Printing All. | |
2 | Require Import Coq.Arith.Compare_dec. | |
3 | ||
4 | Require Import Coq.subtac.Utils. | |
5 | ||
6 | Ltac one_simpl_hyp := | |
7 | match goal with | |
8 | | [H : (`exist _ _ _) = _ |- _] => simpl in H | |
9 | | [H : _ = (`exist _ _ _) |- _] => simpl in H | |
10 | | [H : (`exist _ _ _) < _ |- _] => simpl in H | |
11 | | [H : _ < (`exist _ _ _) |- _] => simpl in H | |
12 | | [H : (`exist _ _ _) <= _ |- _] => simpl in H | |
13 | | [H : _ <= (`exist _ _ _) |- _] => simpl in H | |
14 | | [H : (`exist _ _ _) > _ |- _] => simpl in H | |
15 | | [H : _ > (`exist _ _ _) |- _] => simpl in H | |
16 | | [H : (`exist _ _ _) >= _ |- _] => simpl in H | |
17 | | [H : _ >= (`exist _ _ _) |- _] => simpl in H | |
18 | end. | |
19 | ||
20 | Ltac one_simpl_subtac := | |
21 | destruct_exists ; | |
22 | repeat one_simpl_hyp ; simpl. | |
23 | ||
24 | Ltac simpl_subtac := do 3 one_simpl_subtac ; simpl. | |
25 | ||
26 | Require Import Omega. | |
27 | Require Import Wf_nat. | |
28 | ||
29 | Program Fixpoint euclid (a : nat) (b : { b : nat | b <> O }) {wf a lt} : | |
30 | { q : nat & { r : nat | a = b * q + r /\ r < b } } := | |
31 | if le_lt_dec b a then let (q', r) := euclid (a - b) b in | |
32 | (S q' & r) | |
33 | else (O & a). | |
34 | destruct b ; simpl_subtac. | |
35 | omega. | |
36 | simpl_subtac. | |
37 | assert(x0 * S q' = x0 + x0 * q'). | |
38 | rewrite <- mult_n_Sm. | |
39 | omega. | |
40 | rewrite H2 ; omega. | |
41 | simpl_subtac. | |
42 | split ; auto with arith. | |
43 | omega. | |
44 | apply lt_wf. | |
45 | Defined. | |
46 | ||
47 | Check euclid_evars_proof.⏎ |
473 | 473 | match r with |
474 | 474 | | Ln.IndRef kn | Ln.ConstructRef (kn,_) -> |
475 | 475 | let isrecord = |
476 | try let _ = Recordops.lookup_structure kn in true | |
476 | try let _ = Recordops.lookup_projections kn in true | |
477 | 477 | with Not_found -> false in |
478 | 478 | kind_of_inductive isrecord (fst kn) |
479 | 479 | | Ln.VarRef id -> kind_of_variable id |
12 | 12 | Printer: prterm -> pr_lconstr |
13 | 13 | Printer: prterm_env -> pr_lconstr_env |
14 | 14 | Ppconstr: pr_sort -> pr_rawsort |
15 | Evd: in_dom, etc got standard ocaml names (i.e. mem, etc) | |
16 | Pretyping: | |
17 | - understand_gen_tcc and understand_gen_ltac merged into understand_ltac | |
18 | - type_constraints can now say typed by a sort (use OfType to get the | |
19 | previous behavior) | |
20 | Library: import_library -> import_module | |
15 | 21 | |
16 | 22 | ** Constructors |
17 | 23 | |
18 | 24 | Declarations: mind_consnrealargs -> mind_consnrealdecls |
19 | 25 | NoRedun -> NoDup |
26 | Cast and RCast have an extra argument: you can recover the previous | |
27 | behavior by setting the extra argument to "CastConv DEFAULTcast" and | |
28 | "DEFAULTcast" respectively | |
29 | Names: "kernel_name" is now "constant" when argument of Term.Const | |
30 | Tacexpr: TacTrueCut and TacForward(false,_,_) merged into new TacAssert | |
31 | Tacexpr: TacForward(true,_,_) branched to TacLetTac | |
20 | 32 | |
21 | 33 | ** Modules |
22 | 34 | |
26 | 38 | module Symbols -> Notation |
27 | 39 | module Coqast, Ast, Esyntax, Termast, and all other modules related to old |
28 | 40 | syntax are removed |
41 | module Instantiate: integrated to Evd | |
42 | module Pretyping now a functor: use Pretyping.Default instead | |
29 | 43 | |
30 | 44 | ** Internal names |
31 | 45 | |
32 | 46 | OBJDEF and OBJDEF1 -> CANONICAL-STRUCTURE |
33 | 47 | |
48 | ** Tactic extensions | |
49 | ||
50 | - printers have an extra parameter which is a constr printer at high precedence | |
51 | - the tactic printers have an extra arg which is the expected precedence | |
52 | - level is now a precedence in declare_extra_tactic_pprule | |
53 | - "interp" functions now of types the actual arg type, not its encapsulation | |
54 | as a generic_argument | |
34 | 55 | |
35 | 56 | ========================================= |
36 | 57 | = CHANGES BETWEEN COQ V7.4 AND COQ V8.0 = |
109 | 109 | refman/RefMan-mod.v.tex refman/RefMan-tac.v.tex \ |
110 | 110 | refman/RefMan-cic.v.tex refman/RefMan-lib.v.tex \ |
111 | 111 | refman/RefMan-tacex.v.tex refman/RefMan-syn.v.tex \ |
112 | refman/RefMan-oth.v.tex \ | |
112 | refman/RefMan-oth.v.tex refman/RefMan-ltac.v.tex \ | |
113 | 113 | refman/Cases.v.tex refman/Coercion.v.tex refman/Extraction.v.tex \ |
114 | 114 | refman/Program.v.tex refman/Omega.v.tex refman/Polynom.v.tex \ |
115 | 115 | refman/Setoid.v.tex refman/Helm.tex # refman/Natural.v.tex |
118 | 118 | refman/headers.tex \ |
119 | 119 | refman/Reference-Manual.tex refman/RefMan-pre.tex \ |
120 | 120 | refman/RefMan-int.tex refman/RefMan-pro.tex \ |
121 | refman/RefMan-com.tex refman/RefMan-ltac.tex \ | |
121 | refman/RefMan-com.tex \ | |
122 | 122 | refman/RefMan-uti.tex refman/RefMan-ide.tex \ |
123 | 123 | refman/RefMan-add.tex refman/RefMan-modr.tex \ |
124 | 124 | $(REFMANCOQTEXFILES) \ |
160 | 160 | mkdir refman/html |
161 | 161 | cp $(REFMANPNGFILES) refman/html |
162 | 162 | (cd refman/html; hacha -o toc.html ../Reference-Manual.html) |
163 | cp refman/cover.html refman/html | |
163 | cp refman/cover.html refman/menu.html refman/html | |
164 | 164 | cp refman/index.html refman/html |
165 | ||
166 | refman-quick: | |
167 | (cd refman; \ | |
168 | $(PDFLATEX) Reference-Manual.tex; \ | |
169 | hevea -fix -exec xxdate.exe ./Reference-Manual.tex) | |
170 | ||
165 | 171 | |
166 | 172 | ###################################################################### |
167 | 173 | # Tutorial |
160 | 160 | \newcommand{\form}{\textrm{\textsl{form}}} |
161 | 161 | \newcommand{\entry}{\textrm{\textsl{entry}}} |
162 | 162 | \newcommand{\proditem}{\textrm{\textsl{production\_item}}} |
163 | \newcommand{\taclevel}{\textrm{\textsl{tactic\_level}}} | |
163 | 164 | \newcommand{\tacargtype}{\textrm{\textsl{tactic\_argument\_type}}} |
164 | 165 | \newcommand{\scope}{\textrm{\textsl{scope}}} |
165 | 166 | \newcommand{\optscope}{\textrm{\textsl{opt\_scope}}} |
181 | 182 | \newcommand{\name}{\textrm{\textsl{name}}} |
182 | 183 | \newcommand{\num}{\textrm{\textsl{num}}} |
183 | 184 | \newcommand{\pattern}{\textrm{\textsl{pattern}}} |
185 | \newcommand{\orpattern}{\textrm{\textsl{or\_pattern}}} | |
184 | 186 | \newcommand{\intropattern}{\textrm{\textsl{intro\_pattern}}} |
185 | 187 | \newcommand{\pat}{\textrm{\textsl{pat}}} |
186 | 188 | \newcommand{\pgs}{\textrm{\textsl{pgms}}} |
199 | 201 | \newcommand{\str}{\textrm{\textsl{string}}} |
200 | 202 | \newcommand{\subsequentletter}{\textrm{\textsl{subsequent\_letter}}} |
201 | 203 | \newcommand{\switch}{\textrm{\textsl{switch}}} |
204 | \newcommand{\messagetoken}{\textrm{\textsl{message\_token}}} | |
202 | 205 | \newcommand{\tac}{\textrm{\textsl{tactic}}} |
203 | 206 | \newcommand{\terms}{\textrm{\textsl{terms}}} |
204 | 207 | \newcommand{\term}{\textrm{\textsl{term}}} |
487 | 490 | {\begin{center}\begin{rulebox}} |
488 | 491 | {\end{rulebox}\end{center}} |
489 | 492 | |
490 | % $Id: macros.tex 8606 2006-02-23 13:58:10Z herbelin $ | |
493 | % $Id: macros.tex 9038 2006-07-11 13:53:53Z herbelin $ | |
491 | 494 | |
492 | 495 | |
493 | 496 | %%% Local Variables: |
0 | 0 | \achapter{Extended pattern-matching}\defaultheaders |
1 | \aauthor{Cristina Cornes} | |
1 | \aauthor{Cristina Cornes and Hugo Herbelin} | |
2 | 2 | |
3 | 3 | \label{Mult-match-full} |
4 | 4 | \ttindex{Cases} |
16 | 16 | letter. |
17 | 17 | |
18 | 18 | If a pattern has the form $(c~\vec{x})$ where $c$ is a constructor |
19 | symbol and $\vec{x}$ is a linear vector of variables, it is called | |
20 | {\em simple}: it is the kind of pattern recognized by the basic | |
21 | version of {\tt match}. If a pattern is | |
22 | not simple we call it {\em nested}. | |
19 | symbol and $\vec{x}$ is a linear vector of (distinct) variables, it is | |
20 | called {\em simple}: it is the kind of pattern recognized by the basic | |
21 | version of {\tt match}. On the opposite, if it is a variable $x$ or | |
22 | has the form $(c~\vec{p})$ with $p$ not only made of variables, the | |
23 | pattern is called {\em nested}. | |
23 | 24 | |
24 | 25 | A variable pattern matches any value, and the identifier is bound to |
25 | 26 | that value. The pattern ``\texttt{\_}'' (called ``don't care'' or |
26 | ``wildcard'' symbol) also matches any value, but does not bind anything. It | |
27 | may occur an arbitrary number of times in a pattern. Alias patterns | |
28 | written \texttt{(}{\sl pattern} \texttt{as} {\sl identifier}\texttt{)} are | |
29 | also accepted. This pattern matches the same values as {\sl pattern} | |
30 | does and {\sl identifier} is bound to the matched value. A list of | |
31 | patterns separated with commas | |
32 | is also considered as a pattern and is called {\em multiple | |
33 | pattern}. | |
27 | ``wildcard'' symbol) also matches any value, but does not bind | |
28 | anything. It may occur an arbitrary number of times in a | |
29 | pattern. Alias patterns written \texttt{(}{\sl pattern} \texttt{as} | |
30 | {\sl identifier}\texttt{)} are also accepted. This pattern matches the | |
31 | same values as {\sl pattern} does and {\sl identifier} is bound to the | |
32 | matched value. | |
33 | A pattern of the form {\pattern}{\tt |}{\pattern} is called | |
34 | disjunctive. A list of patterns separated with commas is also | |
35 | considered as a pattern and is called {\em multiple pattern}. However | |
36 | multiple patterns can only occur at the root of pattern-matching | |
37 | equations. Disjunctions of {\em multiple pattern} are allowed though. | |
34 | 38 | |
35 | 39 | Since extended {\tt match} expressions are compiled into the primitive |
36 | 40 | ones, the expressiveness of the theory remains the same. Once the |
37 | stage of parsing has finished only simple patterns remain. An easy way | |
38 | to see the result of the expansion is by printing the term with | |
39 | \texttt{Print} if the term is a constant, or using the command | |
41 | stage of parsing has finished only simple patterns remain. Re-nesting | |
42 | of pattern is performed at printing time. An easy way to see the | |
43 | result of the expansion is to toggle off the nesting performed at | |
44 | printing (use here {\tt Set Printing Matching}), then by printing the term | |
45 | with \texttt{Print} if the term is a constant, or using the command | |
40 | 46 | \texttt{Check}. |
41 | 47 | |
42 | 48 | The extended \texttt{match} still accepts an optional {\em elimination |
43 | 49 | predicate} given after the keyword \texttt{return}. Given a pattern |
44 | matching expression, if all the right hand sides of \texttt{=>} ({\em | |
50 | matching expression, if all the right-hand-sides of \texttt{=>} ({\em | |
45 | 51 | rhs} in short) have the same type, then this type can be sometimes |
46 | 52 | synthesized, and so we can omit the \texttt{return} part. Otherwise |
47 | 53 | the predicate after \texttt{return} has to be provided, like for the basic |
63 | 69 | end. |
64 | 70 | \end{coq_example} |
65 | 71 | |
66 | Using multiple patterns in the definition allows to write: | |
72 | \paragraph{Multiple patterns} | |
73 | ||
74 | Using multiple patterns in the definition of {\tt max} allows to write: | |
67 | 75 | |
68 | 76 | \begin{coq_example} |
69 | 77 | Reset max. |
88 | 96 | end). |
89 | 97 | \end{coq_example} |
90 | 98 | |
91 | We can also use ``\texttt{as} patterns'' to associate a name to a | |
99 | \paragraph{Aliasing subpatterns} | |
100 | ||
101 | We can also use ``\texttt{as} {\ident}'' to associate a name to a | |
92 | 102 | sub-pattern: |
93 | 103 | |
94 | 104 | \begin{coq_example} |
100 | 110 | | S n', S m' => S (max n' m') |
101 | 111 | end. |
102 | 112 | \end{coq_example} |
113 | ||
114 | \paragraph{Nested patterns} | |
103 | 115 | |
104 | 116 | Here is now an example of nested patterns: |
105 | 117 | |
156 | 168 | end. |
157 | 169 | \end{coq_example} |
158 | 170 | |
159 | ||
160 | 171 | Here the last pattern superposes with the first two. Because |
161 | 172 | of the priority rule, the last pattern |
162 | 173 | will be used only for values that do not match neither the first nor |
179 | 190 | end). |
180 | 191 | \end{coq_example} |
181 | 192 | |
193 | \paragraph{Disjunctive patterns} | |
194 | ||
195 | Multiple patterns that share the same right-hand-side can be | |
196 | factorized using the notation \nelist{\multpattern}{\tt |}. For instance, | |
197 | {\tt max} can be rewritten as follows: | |
198 | ||
199 | \begin{coq_eval} | |
200 | Reset max. | |
201 | \end{coq_eval} | |
202 | \begin{coq_example} | |
203 | Fixpoint max (n m:nat) {struct m} : nat := | |
204 | match n, m with | |
205 | | S n', S m' => S (max n' m') | |
206 | | 0, p | p, 0 => p | |
207 | end. | |
208 | \end{coq_example} | |
209 | ||
210 | Similarly, factorization of (non necessary multiple) patterns | |
211 | that share the same variables is possible by using the notation | |
212 | \nelist{\pattern}{\tt |}. Here is an example: | |
213 | ||
214 | \begin{coq_example} | |
215 | Definition filter_2_4 (n:nat) : nat := | |
216 | match n with | |
217 | | 2 as m | 4 as m => m | |
218 | | _ => 0 | |
219 | end. | |
220 | \end{coq_example} | |
221 | ||
222 | Here is another example using disjunctive subpatterns. | |
223 | ||
224 | \begin{coq_example} | |
225 | Definition filter_some_square_corners (p:nat*nat) : nat*nat := | |
226 | match p with | |
227 | | ((2 as m | 4 as m), (3 as n | 5 as n)) => (m,n) | |
228 | | _ => (0,0) | |
229 | end. | |
230 | \end{coq_example} | |
231 | ||
182 | 232 | \asection{About patterns of parametric types} |
183 | 233 | When matching objects of a parametric type, constructors in patterns |
184 | 234 | {\em do not expect} the parameter arguments. Their value is deduced |
185 | 235 | during expansion. |
186 | ||
187 | Consider for example the polymorphic lists: | |
236 | Consider for example the type of polymorphic lists: | |
188 | 237 | |
189 | 238 | \begin{coq_example} |
190 | 239 | Inductive List (A:Set) : Set := |
217 | 217 | written $x:=t:T$. We use brackets to write contexts. A |
218 | 218 | typical example is $[x:T;y:=u:U;z:V]$. Notice that the variables |
219 | 219 | declared in a context must be distinct. If $\Gamma$ declares some $x$, |
220 | we write $x \in\Gamma$. By writing $(x:T)\in\Gamma$ we mean that | |
220 | we write $x \in \Gamma$. By writing $(x:T) \in \Gamma$ we mean that | |
221 | 221 | either $x:T$ is an assumption in $\Gamma$ or that there exists some $t$ such |
222 | 222 | that $x:=t:T$ is a definition in $\Gamma$. If $\Gamma$ defines some |
223 | $x:=t:T$, we also write $(x:=t:T)\in\Gamma$. Contexts must be | |
223 | $x:=t:T$, we also write $(x:=t:T) \in \Gamma$. Contexts must be | |
224 | 224 | themselves {\em well formed}. For the rest of the chapter, the |
225 | 225 | notation $\Gamma::(y:T)$ (resp. $\Gamma::(y:=t:T)$) denotes the context |
226 | 226 | $\Gamma$ enriched with the declaration $y:T$ (resp. $y:=t:T$). The |
232 | 232 | |
233 | 233 | We define the inclusion of two contexts $\Gamma$ and $\Delta$ (written |
234 | 234 | as $\Gamma \subset \Delta$) as the property, for all variable $x$, |
235 | type $T$ and term $t$, if $(x:T) \in \Gamma$ then $(x:T)\in \Delta$ | |
236 | and if $(x:=t:T) \in \Gamma$ then $(x:=t:T)\in \Delta$. | |
235 | type $T$ and term $t$, if $(x:T) \in \Gamma$ then $(x:T) \in \Delta$ | |
236 | and if $(x:=t:T) \in \Gamma$ then $(x:=t:T) \in \Delta$. | |
237 | 237 | %We write |
238 | 238 | % $|\Delta|$ for the length of the context $\Delta$, that is for the number |
239 | 239 | % of declarations (assumptions or definitions) in $\Delta$. |
287 | 287 | \begin{description} |
288 | 288 | \item[W-E] \inference{\WF{[]}{[]}} |
289 | 289 | \item[W-S] % Ce n'est pas vrai : x peut apparaitre plusieurs fois dans Gamma |
290 | \inference{\frac{\WTEG{T}{s}~~~~s\in \Sort~~~~x \not\in | |
290 | \inference{\frac{\WTEG{T}{s}~~~~s \in \Sort~~~~x \not\in | |
291 | 291 | \Gamma % \cup E |
292 | 292 | } |
293 | 293 | {\WFE{\Gamma::(x:T)}}~~~~~ |
294 | 294 | \frac{\WTEG{t}{T}~~~~x \not\in |
295 | 295 | \Gamma % \cup E |
296 | 296 | }{\WFE{\Gamma::(x:=t:T)}}} |
297 | \item[Def] \inference{\frac{\WTEG{t}{T}~~~c \notin E\cup \Gamma} | |
297 | \item[Def] \inference{\frac{\WTEG{t}{T}~~~c \notin E \cup \Gamma} | |
298 | 298 | {\WF{E;\Def{\Gamma}{c}{t}{T}}{\Gamma}}} |
299 | \item[Assum] \inference{\frac{\WTEG{T}{s}~~~~s \in \Sort~~~~c \notin E \cup \Gamma} | |
300 | {\WF{E;\Assum{\Gamma}{c}{T}}{\Gamma}}} | |
299 | 301 | \item[Ax] \index{Typing rules!Ax} |
300 | 302 | \inference{\frac{\WFE{\Gamma}}{\WTEG{\Prop}{\Type(p)}}~~~~~ |
301 | 303 | \frac{\WFE{\Gamma}}{\WTEG{\Set}{\Type(q)}}} |
302 | 304 | \inference{\frac{\WFE{\Gamma}~~~~i<j}{\WTEG{\Type(i)}{\Type(j)}}} |
303 | 305 | \item[Var]\index{Typing rules!Var} |
304 | \inference{\frac{ \WFE{\Gamma}~~~~~(x:T)\in\Gamma~~\mbox{or}~~(x:=t:T)\in\Gamma~\mbox{for some $t$}}{\WTEG{x}{T}}} | |
306 | \inference{\frac{ \WFE{\Gamma}~~~~~(x:T) \in \Gamma~~\mbox{or}~~(x:=t:T) \in \Gamma~\mbox{for some $t$}}{\WTEG{x}{T}}} | |
305 | 307 | \item[Const] \index{Typing rules!Const} |
306 | \inference{\frac{\WFE{\Gamma}~~~~(c:T) \in E}{\WTEG{c}{T}}} | |
308 | \inference{\frac{\WFE{\Gamma}~~~~(c:T) \in E~~\mbox{or}~~(c:=t:T) \in E~\mbox{for some $t$} }{\WTEG{c}{T}}} | |
307 | 309 | \item[Prod] \index{Typing rules!Prod} |
308 | 310 | \inference{\frac{\WTEG{T}{s}~~~~s \in \Sort~~~ |
309 | 311 | \WTE{\Gamma::(x:T)}{U}{\Prop}} |
310 | 312 | { \WTEG{\forall~x:T,U}{\Prop}}} |
311 | \inference{\frac{\WTEG{T}{s}~~~~s\in\{\Prop, \Set\}~~~~~~ | |
313 | \inference{\frac{\WTEG{T}{s}~~~~s \in\{\Prop, \Set\}~~~~~~ | |
312 | 314 | \WTE{\Gamma::(x:T)}{U}{\Set}} |
313 | 315 | { \WTEG{\forall~x:T,U}{\Set}}} |
314 | 316 | \inference{\frac{\WTEG{T}{\Type(i)}~~~~i\leq k~~~ |
372 | 374 | that is to expand (or unfold) it into its value. This |
373 | 375 | reduction is called $\delta$-reduction and shows as follows. |
374 | 376 | |
375 | $$\WTEGRED{x}{\triangleright_{\delta}}{t}~~~~~\mbox{if $(x:=t:T)\in\Gamma$}~~~~~~~~~\WTEGRED{c}{\triangleright_{\delta}}{t}~~~~~\mbox{if $(c:=t:T)\in E$}$$ | |
377 | $$\WTEGRED{x}{\triangleright_{\delta}}{t}~~~~~\mbox{if $(x:=t:T) \in \Gamma$}~~~~~~~~~\WTEGRED{c}{\triangleright_{\delta}}{t}~~~~~\mbox{if $(c:=t:T) \in E$}$$ | |
376 | 378 | |
377 | 379 | |
378 | 380 | \paragraph{$\zeta$-reduction.} |
552 | 554 | \List}\] |
553 | 555 | Assuming |
554 | 556 | $\Gamma_I$ is $[I_1:A_1;\ldots;I_k:A_k]$, and $\Gamma_C$ is |
555 | $[c_1:C_1;\ldots;c_n:C_n]$, the general typing rules are: | |
557 | $[c_1:C_1;\ldots;c_n:C_n]$, the general typing rules are, | |
558 | for $1\leq j\leq k$ and $1\leq i\leq n$: | |
556 | 559 | |
557 | 560 | \bigskip |
558 | \inference{\frac{\NInd{\Gamma}{\Gamma_I}{\Gamma_C} \in E | |
559 | ~~j=1\ldots k}{(I_j:A_j) \in E}} | |
560 | ||
561 | \inference{\frac{\NInd{\Gamma}{\Gamma_I}{\Gamma_C} \in E | |
562 | ~~~~i=1.. n} | |
563 | {(c_i:C_i)\in E}} | |
561 | \inference{\frac{\NInd{\Gamma}{\Gamma_I}{\Gamma_C} \in E}{(I_j:A_j) \in E}} | |
562 | ||
563 | \inference{\frac{\NInd{\Gamma}{\Gamma_I}{\Gamma_C} \in E}{(c_i:C_i) \in E}} | |
564 | 564 | |
565 | 565 | \subsubsection{Inductive definitions with parameters} |
566 | 566 | |
592 | 592 | with $I$ one of the inductive definitions in $\Gamma_I$. |
593 | 593 | We say that $n$ is the number of real arguments of the constructor |
594 | 594 | $c$. |
595 | \paragraph{Context of parameters} | |
595 | \paragraph{Context of parameters.} | |
596 | 596 | If an inductive definition $\NInd{\Gamma}{\Gamma_I}{\Gamma_C}$ admits |
597 | 597 | $r$ inductive parameters, then there exists a context $\Gamma_P$ of |
598 | size $r$, such that $\Gamma_P=p_1:P_1;\ldots;\forall p_r:P_r$ and | |
599 | if $(t:A)\in\Gamma_I,\Gamma_C$ then $A$ can be written as | |
598 | size $r$, such that $\Gamma_P=p_1:P_1;\ldots;p_r:P_r$ and | |
599 | if $(t:A) \in \Gamma_I,\Gamma_C$ then $A$ can be written as | |
600 | 600 | $\forall p_1:P_1,\ldots \forall p_r:P_r,A'$. |
601 | 601 | We call $\Gamma_P$ the context of parameters of the inductive |
602 | 602 | definition and use the notation $\forall \Gamma_P,A'$ for the term $A$. |
740 | 740 | |
741 | 741 | \inference{\frac{\Ind{\Gamma}{p}{\Gamma_I}{\Gamma_C} \in E |
742 | 742 | ~~~~i=1.. n} |
743 | {(c_i:C_i)\in E}} | |
743 | {(c_i:C_i) \in E}} | |
744 | 744 | \end{description} |
745 | 745 | |
746 | 746 | \paragraph{Example.} |
847 | 847 | \begin{description} |
848 | 848 | \item[W-Ind] Let $E$ be an environment and |
849 | 849 | $\Gamma,\Gamma_P,\Gamma_I,\Gamma_C$ are contexts such that |
850 | $\Gamma_I$ is $[I_1:\forall \Gamma_p,A_1;\ldots;I_k:\forall | |
850 | $\Gamma_I$ is $[I_1:\forall \Gamma_P,A_1;\ldots;I_k:\forall | |
851 | 851 | \Gamma_P,A_k]$ and $\Gamma_C$ is |
852 | $[c_1:\forall \Gamma_p,C_1;\ldots;c_n:\forall \Gamma_p,C_n]$. | |
852 | $[c_1:\forall \Gamma_P,C_1;\ldots;c_n:\forall \Gamma_P,C_n]$. | |
853 | 853 | \inference{ |
854 | 854 | \frac{ |
855 | 855 | (\WTE{\Gamma;\Gamma_P}{A_j}{s'_j})_{j=1\ldots k} |
856 | 856 | ~~ (\WTE{\Gamma;\Gamma_I;\Gamma_P}{C_i}{s_{p_i}})_{i=1\ldots n} |
857 | 857 | } |
858 | 858 | {\WF{E;\Ind{\Gamma}{p}{\Gamma_I}{\Gamma_C}}{\Gamma}}} |
859 | providing the following side conditions hold: | |
859 | provided that the following side conditions hold: | |
860 | 860 | \begin{itemize} |
861 | 861 | \item $k>0$, $I_j$, $c_i$ are different names for $j=1\ldots k$ and $i=1\ldots n$, |
862 | 862 | \item $p$ is the number of parameters of \NInd{\Gamma}{\Gamma_I}{\Gamma_C} |
873 | 873 | constructors which will always be satisfied for the impredicative sort |
874 | 874 | (\Prop) but may fail to define inductive definition |
875 | 875 | on sort \Set{} and generate constraints between universes for |
876 | inductive definitions in types. | |
876 | inductive definitions in the {\Type} hierarchy. | |
877 | 877 | |
878 | 878 | \paragraph{Examples.} |
879 | 879 | It is well known that existential quantifier can be encoded as an |
906 | 906 | %is recursive or not. We shall write the type $(x:_R T)C$ if it is |
907 | 907 | %a recursive argument and $(x:_P T)C$ if the argument is not recursive. |
908 | 908 | |
909 | \paragraph{Sort-polymorphism of inductive families.} | |
910 | \index{Sort-polymorphism of inductive families} | |
911 | ||
912 | From {\Coq} version 8.1, inductive families declared in {\Type} are | |
913 | polymorphic over their arguments in {\Type}. | |
914 | ||
915 | If $A$ is an arity and $s$ a sort, we write $A_{/s}$ for the arity | |
916 | obtained from $A$ by replacing its sort with $s$. Especially, if $A$ | |
917 | is well-typed in some environment and context, then $A_{/s}$ is typable | |
918 | by typability of all products in the Calculus of Inductive Constructions. | |
919 | The following typing rule is added to the theory. | |
920 | ||
921 | \begin{description} | |
922 | \item[Ind-Family] Let $\Gamma_P$ be a context of parameters | |
923 | $[p_1:P_1;\ldots;p_{m'}:P_{m'}]$ and $m\leq m'$ be the length of the | |
924 | initial prefix of parameters that occur unchanged in the recursive | |
925 | occurrences of the constructor types. Assume that $\Gamma_I$ is | |
926 | $[I_1:\forall \Gamma_P,A_1;\ldots;I_k:\forall \Gamma_P,A_k]$ and | |
927 | $\Gamma_C$ is $[c_1:\forall \Gamma_P,C_1;\ldots;c_n:\forall | |
928 | \Gamma_P,C_n]$. | |
929 | ||
930 | Let $q_1$, \ldots, $q_r$, with $0\leq r\leq m$, be a possibly partial | |
931 | instantiation of the parameters in $\Gamma_P$. We have: | |
932 | ||
933 | \inference{\frac | |
934 | {\left\{\begin{array}{l} | |
935 | \Ind{\Gamma}{p}{\Gamma_I}{\Gamma_C} \in E\\ | |
936 | (E[\Gamma] \vdash q_s : P'_s)_{s=1\ldots r}\\ | |
937 | (E[\Gamma] \vdash \WTEGLECONV{P'_s}{\subst{P_s}{x_u}{q_u}_{u=1\ldots s-1}})_{s=1\ldots r}\\ | |
938 | 1 \leq j \leq k | |
939 | \end{array} | |
940 | \right.} | |
941 | {(I_j\,q_1\,\ldots\,q_r:\forall \Gamma^{r+1}_p, (A_j)_{/s})} | |
942 | } | |
943 | ||
944 | provided that the following side conditions hold: | |
945 | ||
946 | \begin{itemize} | |
947 | \item $\Gamma_{P'}$ is the context obtained from $\Gamma_P$ by | |
948 | replacing, each $P_s$ that is an arity with the | |
949 | sort of $P'_s$, as soon as $1\leq s \leq r$ (notice that | |
950 | $P_s$ arity implies $P'_s$ arity since $E[\Gamma] | |
951 | \vdash \WTEGLECONV{P'_s}{ \subst{P_s}{x_u}{q_u}_{u=1\ldots s-1}}$); | |
952 | \item there are sorts $s_i$, for $1 \leq i \leq k$ such that, for | |
953 | $\Gamma_{I'}$ obtained from $\Gamma_I$ by changing each $A_i$ by $(A_i)_{/s_i}$, | |
954 | we have $(\WTE{\Gamma;\Gamma_{I'};\Gamma_{P'}}{C_i}{s_{p_i}})_{i=1\ldots n}$; | |
955 | \item the sorts are such that all elimination are allowed (see | |
956 | section~\ref{elimdep}). | |
957 | \end{itemize} | |
958 | \end{description} | |
959 | ||
960 | Notice that if $I_j\,q_1\,\ldots\,q_r$ is typable using the rules {\bf | |
961 | Ind-Const} and {\bf App}, then it is typable using the rule {\bf | |
962 | Ind-Family}. Conversely, the extended theory is not stronger than the | |
963 | theory without {\bf Ind-Family}. We get an equiconsistency result by | |
964 | mapping each $\Ind{\Gamma}{p}{\Gamma_I}{\Gamma_C}$ occurring into a | |
965 | given derivation into as many fresh inductive types and constructors | |
966 | as the number of different (partial) replacements of sorts, needed for | |
967 | this derivation, in the parameters that are arities. That is, the | |
968 | changes in the types of each partial instance $q_1\,\ldots\,q_r$ can | |
969 | be characterized by the ordered sets of arity sorts among the types of | |
970 | parameters, and to each signature is associated a new inductive | |
971 | definition with fresh names. Conversion is preserved as any (partial) | |
972 | instance $I_j\,q_1\,\ldots\,q_r$ or $C_i\,q_1\,\ldots\,q_r$ is mapped | |
973 | to the names chosen in the specific instance of | |
974 | $\Ind{\Gamma}{p}{\Gamma_I}{\Gamma_C}$. | |
975 | ||
976 | \newcommand{\Single}{\mbox{\textsf{Set}}} | |
977 | ||
978 | In practice, the rule is used by {\Coq} only with in case the | |
979 | inductive type is declared with an arity of a sort in the $\Type$ | |
980 | hierarchy, and, then, the polymorphism is over the parameters whose | |
981 | type is an arity in the {\Type} hierarchy. The sort $s_j$ are then | |
982 | chosen canonically so that each $s_j$ is minimal with respect to the | |
983 | hierarchy ${\Prop_u}\subset{\Set_p}\subset\Type$ where $\Set_p$ is | |
984 | predicative {\Set}, and ${\Prop_u}$ is the sort of small singleton | |
985 | inductive types (i.e. of inductive types with one single constructor | |
986 | and that contains either proofs or inhabitants of singleton types | |
987 | only). More precisely, a small singleton inductive family is set in | |
988 | {\Prop}, a small non singleton inductive family is set in {\Set} (even | |
989 | in case {\Set} is impredicative -- see section~\ref{impredicativity}), | |
990 | and otherwise in the {\Type} hierarchy. | |
991 | % TODO: clarify the case of a partial application ?? | |
992 | ||
993 | Note that the side-condition about allowed elimination sorts in the | |
994 | rule~{\bf Ind-Family} is just to avoid to recompute the allowed | |
995 | elimination sorts at each instance of a pattern-matching (see | |
996 | section~\ref{elimdep}). | |
997 | ||
998 | As an example, let us consider the following definition: | |
999 | \begin{coq_example*} | |
1000 | Inductive option (A:Type) : Type := | |
1001 | | None : option A | |
1002 | | Some : A -> option A. | |
1003 | \end{coq_example*} | |
1004 | ||
1005 | As the definition is set in the {\Type} hierarchy, it is used | |
1006 | polymorphically over its parameters whose types are arities of a sort | |
1007 | in the {\Type} hierarchy. Here, the parameter $A$ has this property, | |
1008 | hence, if \texttt{option} is applied to a type in {\Set}, the result is | |
1009 | in {\Set}. Note that if \texttt{option} is applied to a type in {\Prop}, | |
1010 | then, the result is not set in \texttt{Prop} but in \texttt{Set} | |
1011 | still. This is because \texttt{option} is not a singleton type (see | |
1012 | section~\ref{singleton}) and it would loose the elimination to {\Set} and | |
1013 | {\Type} if set in {\Prop}. | |
1014 | ||
1015 | \begin{coq_example} | |
1016 | Check (fun A:Set => option A). | |
1017 | Check (fun A:Prop => option A). | |
1018 | \end{coq_example} | |
1019 | ||
1020 | Here is another example. | |
1021 | ||
1022 | \begin{coq_example*} | |
1023 | Inductive prod (A B:Type) : Type := pair : A -> B -> prod A B. | |
1024 | \end{coq_example*} | |
1025 | ||
1026 | As \texttt{prod} is a singleton type, it will be in {\Prop} if applied | |
1027 | twice to propositions, in {\Set} if applied twice to at least one type | |
1028 | in {\Set} and none in {\Type}, and in {\Type} otherwise. In all cases, | |
1029 | the three kind of eliminations schemes are allowed. | |
1030 | ||
1031 | \begin{coq_example} | |
1032 | Check (fun A:Set => prod A). | |
1033 | Check (fun A:Prop => prod A A). | |
1034 | Check (fun (A:Prop) (B:Set) => prod A B). | |
1035 | Check (fun (A:Type) (B:Prop) => prod A B). | |
1036 | \end{coq_example} | |
1037 | ||
909 | 1038 | \subsection{Destructors} |
910 | 1039 | The specification of inductive definitions with arities and |
911 | 1040 | constructors is quite natural. But we still have to say how to use an |
1048 | 1177 | % \mbox{\tt =>}~ \false} |
1049 | 1178 | |
1050 | 1179 | \paragraph{Allowed elimination sorts.} |
1180 | ||
1051 | 1181 | \index{Elimination sorts} |
1052 | 1182 | |
1053 | 1183 | An important question for building the typing rule for \kw{match} is |
1157 | 1287 | %{\tt Program} tactic or when extracting ML programs. |
1158 | 1288 | |
1159 | 1289 | \paragraph{Empty and singleton elimination} |
1290 | \label{singleton} | |
1160 | 1291 | \index{Elimination!Singleton elimination} |
1161 | 1292 | \index{Elimination!Empty elimination} |
1162 | 1293 | |
1166 | 1297 | \item[\Prop-extended] |
1167 | 1298 | \inference{ |
1168 | 1299 | \frac{I \mbox{~is an empty or singleton |
1169 | definition}~~~s\in\Sort}{\compat{I:\Prop}{I\ra s}} | |
1300 | definition}~~~s \in \Sort}{\compat{I:\Prop}{I\ra s}} | |
1170 | 1301 | } |
1171 | 1302 | \end{description} |
1172 | 1303 | |
1529 | 1660 | in the sort \Set, which is extended to a domain in any sort~: |
1530 | 1661 | \begin{description} |
1531 | 1662 | \item [Prod] \index{Typing rules!Prod (impredicative Set)} |
1532 | \inference{\frac{\WTEG{T}{s}~~~~s\in\Sort~~~~~~ | |
1663 | \inference{\frac{\WTEG{T}{s}~~~~s \in \Sort~~~~~~ | |
1533 | 1664 | \WTE{\Gamma::(x:T)}{U}{\Set}} |
1534 | 1665 | { \WTEG{\forall~x:T,U}{\Set}}} |
1535 | 1666 | \end{description} |
1552 | 1683 | |
1553 | 1684 | |
1554 | 1685 | |
1555 | % $Id: RefMan-cic.tex 8914 2006-06-07 14:57:22Z cpaulin $ | |
1686 | % $Id: RefMan-cic.tex 9001 2006-07-04 13:50:15Z herbelin $ | |
1556 | 1687 | |
1557 | 1688 | %%% Local Variables: |
1558 | 1689 | %%% mode: latex |
85 | 85 | |
86 | 86 | \section{Options} |
87 | 87 | \index{Options of the command line} |
88 | \label{vmoption} | |
88 | 89 | |
89 | 90 | The following command-line options are recognized by the commands {\tt |
90 | 91 | coqc} and {\tt coqtop}, unless stated otherwise: |
237 | 238 | This avoids loading in memory the proofs of opaque theorems |
238 | 239 | resulting in a smaller memory requirement and faster compilation; |
239 | 240 | warning: this invalidates some features such as the extraction tool. |
241 | ||
242 | \item[{\tt -vm}]\ | |
243 | ||
244 | This activates the use of the bytecode-based conversion algorithm | |
245 | for the current session (see section~\ref{SetVirtualMachine}). | |
240 | 246 | |
241 | 247 | \item[{\tt -image} {\em file}]\ |
242 | 248 | |
271 | 277 | % (see section~\ref{coqsearchisos}, page~\pageref{coqsearchisos}). |
272 | 278 | % \end{description} |
273 | 279 | |
274 | % $Id: RefMan-com.tex 8609 2006-02-24 13:32:57Z notin,no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty $ | |
280 | % $Id: RefMan-com.tex 9044 2006-07-12 13:22:17Z herbelin $ | |
275 | 281 | |
276 | 282 | %%% Local Variables: |
277 | 283 | %%% mode: latex |
222 | 222 | \label{Mult-match}} |
223 | 223 | |
224 | 224 | The basic version of \verb+match+ allows pattern-matching on simple |
225 | patterns. As an extension, multiple and nested patterns are | |
226 | allowed, as in ML-like languages. | |
225 | patterns. As an extension, multiple nested patterns or disjunction of | |
226 | patterns are allowed, as in ML-like languages. | |
227 | 227 | |
228 | 228 | The extension just acts as a macro that is expanded during parsing |
229 | 229 | into a sequence of {\tt match} on simple patterns. Especially, a |
230 | construction defined using the extended {\tt match} is printed under | |
231 | its expanded form. | |
230 | construction defined using the extended {\tt match} is generally | |
231 | printed under its expanded form (see~\texttt{Set Printing Matching} in | |
232 | section~\ref{SetPrintingMatching}). | |
232 | 233 | |
233 | 234 | \SeeAlso chapter \ref{Mult-match-full}. |
234 | 235 | |
329 | 330 | $\equiv$~ |
330 | 331 | {\tt match {\term} \zeroone{\ifitem} with C {\ident}$_1$ {\ldots} {\ident}$_n$ \verb!=>! {\term}' end} |
331 | 332 | |
332 | \subsection{Options for pretty-printing of {\tt match} | |
333 | \subsection{Controlling pretty-printing of {\tt match} expressions | |
333 | 334 | \label{printing-options}} |
334 | 335 | |
335 | There are three options controlling the pretty-printing of {\tt match} | |
336 | expressions. | |
336 | The following commands give some control over the pretty-printing of | |
337 | {\tt match} expressions. | |
338 | ||
339 | \subsubsection{Printing nested patterns | |
340 | \label{SetPrintingMatching} | |
341 | \comindex{Set Printing Matching} | |
342 | \comindex{Unset Printing Matching} | |
343 | \comindex{Test Printing Matching}} | |
344 | ||
345 | The Calculus of Inductive Constructions knows pattern-matching only | |
346 | over simple patterns. It is however convenient to re-factorize nested | |
347 | pattern-matching into a single pattern-matching over a nested pattern. | |
348 | {\Coq}'s printer try to do such limited re-factorization. | |
349 | ||
350 | \begin{quote} | |
351 | {\tt Set Printing Matching.} | |
352 | \end{quote} | |
353 | This tells {\Coq} to try to use nested patterns. This is the default | |
354 | behavior. | |
355 | ||
356 | \begin{quote} | |
357 | {\tt Unset Printing Matching.} | |
358 | \end{quote} | |
359 | This tells {\Coq} to print only simple pattern-matching problems in | |
360 | the same way as the {\Coq} kernel handles them. | |
361 | ||
362 | \begin{quote} | |
363 | {\tt Test Printing Matching.} | |
364 | \end{quote} | |
365 | This tells if the printing matching mode is on or off. The default is | |
366 | on. | |
337 | 367 | |
338 | 368 | \subsubsection{Printing of wildcard pattern |
339 | 369 | \comindex{Set Printing Wildcard} |
1087 | 1117 | \SeeAlso more examples in user contribution \texttt{category} |
1088 | 1118 | (\texttt{Rocq/ALGEBRA}). |
1089 | 1119 | |
1120 | \subsubsection{Print Canonical Projections. | |
1121 | \comindex{Print Canonical Projections}} | |
1122 | ||
1123 | This displays the list of global names that are components of some | |
1124 | canonical structure. For each of them, the canonical structure of | |
1125 | which it is a projection is indicated. For instance, the above example | |
1126 | gives the following output: | |
1127 | ||
1128 | \begin{coq_example} | |
1129 | Print Canonical Projections. | |
1130 | \end{coq_example} | |
1131 | ||
1090 | 1132 | \subsection{Implicit types of variables} |
1091 | 1133 | |
1092 | 1134 | It is possible to bind variable names to a given type (e.g. in a |
63 | 63 | \begin{center} |
64 | 64 | \begin{tabular}{rcl} |
65 | 65 | {\firstletter} & ::= & {\tt a..z} $\mid$ {\tt A..Z} $\mid$ {\tt \_} |
66 | % $\mid$ {\tt unicode-letter} | |
66 | $\mid$ {\tt unicode-letter} | |
67 | 67 | \\ |
68 | 68 | {\subsequentletter} & ::= & {\tt a..z} $\mid$ {\tt A..Z} $\mid$ {\tt 0..9} |
69 | 69 | $\mid$ {\tt \_} % $\mid$ {\tt \$} |
70 | $\mid$ {\tt '} \\ | |
70 | $\mid$ {\tt '} | |
71 | $\mid$ {\tt unicode-letter} | |
72 | $\mid$ {\tt unicode-id-part} \\ | |
71 | 73 | {\ident} & ::= & {\firstletter} \sequencewithoutblank{\subsequentletter}{} |
72 | 74 | \end{tabular} |
73 | 75 | \end{center} |
74 | All characters are meaningful. In particular, identifiers are case-sensitive. | |
76 | All characters are meaningful. In particular, identifiers are | |
77 | case-sensitive. The entry {\tt unicode-letter} non-exhaustively | |
78 | includes Latin, Greek, Gothic, Cyrillic, Arabic, Hebrew, Georgian, | |
79 | Hangul, Hiragana and Katakana characters, CJK ideographs, mathematical | |
80 | letter-like symbols, hyphens, non-breaking space, {\ldots} The entry | |
81 | {\tt unicode-id-part} non-exhaustively includes symbols for prime | |
82 | letters and subscripts. | |
83 | ||
75 | 84 | Access identifiers, written {\accessident}, are identifiers prefixed |
76 | 85 | by \verb!.! (dot) without blank. They are used in the syntax of qualified |
77 | 86 | identifiers. |
307 | 316 | &&\\ |
308 | 317 | {\returntype} & ::= & {\tt return} {\term} \\ |
309 | 318 | &&\\ |
310 | {\eqn} & ::= & \nelist{\pattern}{\tt ,} {\tt =>} {\term}\\ | |
319 | {\eqn} & ::= & \nelist{\multpattern}{\tt |} {\tt =>} {\term}\\ | |
320 | &&\\ | |
321 | {\multpattern} & ::= & \nelist{\pattern}{\tt ,}\\ | |
311 | 322 | &&\\ |
312 | 323 | {\pattern} & ::= & {\qualid} \nelist{\pattern}{} \\ |
313 | 324 | & $|$ & {\pattern} {\tt as} {\ident} \\ |
315 | 326 | & $|$ & {\qualid} \\ |
316 | 327 | & $|$ & {\tt \_} \\ |
317 | 328 | & $|$ & {\num} \\ |
318 | & $|$ & {\tt (} \nelist{\pattern}{,} {\tt )} | |
329 | & $|$ & {\tt (} \nelist{\orpattern}{,} {\tt )} \\ | |
330 | \\ | |
331 | {\orpattern} & ::= & \nelist{\pattern}{\tt |}\\ | |
319 | 332 | \end{tabular} |
320 | 333 | \end{centerframe} |
321 | 334 | \caption{Syntax of terms (continued)} |
514 | 527 | {\pattern$_1$} {\tt =>} {\term$_1$} {\tt $|$} {\ldots} {\tt $|$} |
515 | 528 | {\pattern$_n$} {\tt =>} {\term$_n$} {\tt end}, denotes a {\em |
516 | 529 | pattern-matching} over the term {\term$_0$} (expected to be of an |
517 | inductive type $I$). {\term$_1$}\ldots{\term$_n$} are called branches. In | |
530 | inductive type $I$). | |
531 | The terms {\term$_1$}\ldots{\term$_n$} are called branches. In | |
518 | 532 | a simple pattern \qualid~\nelist{\ident}{}, the qualified identifier |
519 | 533 | {\qualid} is intended to |
520 | be a constructor. There should be a branch for every constructor of | |
534 | be a constructor. There should be one branch for every constructor of | |
521 | 535 | $I$. |
522 | 536 | |
523 | 537 | The {\returntype} is used to compute the resulting type of the whole |
529 | 543 | match} depends on the actual {\term$_0$} matched. |
530 | 544 | |
531 | 545 | There are specific notations for case analysis on types with one or |
532 | two constructors: {\tt if / then / else} and | |
533 | {\tt let (}\ldots{\tt ) :=} \ldots {\tt in}\ldots. \SeeAlso | |
534 | section~\ref{Mult-match} for details and examples. | |
546 | two constructors: {\tt if {\ldots} then {\ldots} else {\ldots}} and | |
547 | {\tt let (}\nelist{\ldots}{,}{\tt ) :=} {\ldots} {\tt in} {\ldots}. | |
535 | 548 | |
536 | 549 | \SeeAlso Section~\ref{Mult-match} for details and examples. |
537 | 550 | |
760 | 773 | {\binder$_1$}\ldots{\binder$_n$}{\tt ,}\,\term$_1$\,{\tt :=}}\,% |
761 | 774 | {\tt fun}\,{\binder$_1$}\ldots{\binder$_n$}\,{\tt =>}\,{\term$_2$}\,% |
762 | 775 | {\tt .} |
776 | ||
777 | \item {\tt Example {\ident} := {\term}.}\\ | |
778 | {\tt Example {\ident} {\tt :}{\term$_1$} := {\term$_2$}.}\\ | |
779 | {\tt Example {\ident} {\binder$_1$}\ldots{\binder$_n$} | |
780 | {\tt :}\term$_1$ {\tt :=} {\term$_2$}.}\\ | |
781 | \comindex{Example} | |
782 | These are synonyms of the {\tt Definition} forms. | |
763 | 783 | \end{Variants} |
764 | 784 | |
765 | 785 | \begin{ErrMsgs} |
766 | \item \errindex{In environment {\dots} the term: {\term$_2$} does not have type | |
767 | {\term$_1$}}.\\ | |
768 | \texttt{Actually, it has type {\term$_3$}}. | |
786 | \item \errindex{Error: The term ``{\term}'' has type "{\type}" while it is expected to have type ``{\type}''} | |
769 | 787 | \end{ErrMsgs} |
770 | 788 | |
771 | 789 | \SeeAlso Sections \ref{Opaque}, \ref{Transparent}, \ref{unfold} |
1061 | 1079 | |
1062 | 1080 | \medskip |
1063 | 1081 | {\tt |
1064 | Inductive {{\ident$_1$} {\params} : {\type$_1$} := \\ | |
1065 | \mbox{}\hspace{0.4cm} {\ident$_1^1$} : {\type$_1^1$} \\ | |
1066 | \mbox{}\hspace{0.1cm}| .. \\ | |
1067 | \mbox{}\hspace{0.1cm}| {\ident$_{n_1}^1$} : {\type$_{n_1}^1$} \\ | |
1082 | \begin{tabular}{l} | |
1083 | Inductive {\ident$_1$} {\params} : {\type$_1$} := \\ | |
1084 | \begin{tabular}{clcl} | |
1085 | & {\ident$_1^1$} &:& {\type$_1^1$} \\ | |
1086 | | & {\ldots} && \\ | |
1087 | | & {\ident$_{n_1}^1$} &:& {\type$_{n_1}^1$} | |
1088 | \end{tabular} \\ | |
1068 | 1089 | with\\ |
1069 | \mbox{}\hspace{0.1cm} .. \\ | |
1090 | ~{\ldots} \\ | |
1070 | 1091 | with {\ident$_m$} {\params} : {\type$_m$} := \\ |
1071 | \mbox{}\hspace{0.4cm}{\ident$_1^m$} : {\type$_1^m$} \\ | |
1072 | \mbox{}\hspace{0.1cm}| .. \\ | |
1073 | \mbox{}\hspace{0.1cm}| {\ident$_{n_m}^m$} : {\type$_{n_m}^m$}. | |
1074 | }} | |
1092 | \begin{tabular}{clcl} | |
1093 | & {\ident$_1^m$} &:& {\type$_1^m$} \\ | |
1094 | | & {\ldots} \\ | |
1095 | | & {\ident$_{n_m}^m$} &:& {\type$_{n_m}^m$}. | |
1096 | \end{tabular} | |
1097 | \end{tabular} | |
1098 | } | |
1075 | 1099 | \medskip |
1076 | 1100 | |
1077 | 1101 | \Example |
1183 | 1207 | %% |
1184 | 1208 | \subsection{Definition of recursive functions} |
1185 | 1209 | |
1186 | \subsubsection{\tt Fixpoint {\ident} {\params} {\tt \{struct} | |
1210 | \subsubsection{Recursive functions over a inductive type} | |
1211 | ||
1212 | The command: | |
1213 | \begin{center} | |
1214 | \texttt{Fixpoint {\ident} {\params} {\tt \{struct} | |
1187 | 1215 | \ident$_0$ {\tt \}} : type$_0$ := \term$_0$ |
1188 | \comindex{Fixpoint} | |
1189 | \label{Fixpoint}} | |
1190 | ||
1191 | This command allows to define inductive objects using a fixed point | |
1192 | construction. The meaning of this declaration is to define {\it ident} | |
1193 | a recursive function with arguments specified by the binders in | |
1194 | \params{} % {\binder$_1$}\ldots{\binder$_n$} | |
1195 | such that {\it ident} applied to | |
1196 | arguments corresponding to these binders has type \type$_0$, and is | |
1197 | equivalent to the expression \term$_0$. The type of the {\ident} is | |
1198 | consequently {\tt forall {\params} {\tt,} \type$_0$} | |
1199 | and the value is equivalent to {\tt fun {\params} {\tt =>} \term$_0$}. | |
1216 | \comindex{Fixpoint}\label{Fixpoint}} | |
1217 | \end{center} | |
1218 | allows to define inductive objects using a fixed point construction. | |
1219 | The meaning of this declaration is to define {\it ident} a recursive | |
1220 | function with arguments specified by the binders in {\params} such | |
1221 | that {\it ident} applied to arguments corresponding to these binders | |
1222 | has type \type$_0$, and is equivalent to the expression \term$_0$. The | |
1223 | type of the {\ident} is consequently {\tt forall {\params} {\tt,} | |
1224 | \type$_0$} and the value is equivalent to {\tt fun {\params} {\tt | |
1225 | =>} \term$_0$}. | |
1200 | 1226 | |
1201 | 1227 | To be accepted, a {\tt Fixpoint} definition has to satisfy some |
1202 | 1228 | syntactical constraints on a special argument called the decreasing |
1204 | 1230 | always terminates. The point of the {\tt \{struct \ident {\tt \}}} |
1205 | 1231 | annotation is to let the user tell the system which argument decreases |
1206 | 1232 | along the recursive calls. This annotation may be left implicit for |
1207 | fixpoints with one argument. For instance, one can define the addition | |
1208 | function as : | |
1233 | fixpoints where only one argument has an inductive type. For instance, | |
1234 | one can define the addition function as : | |
1209 | 1235 | |
1210 | 1236 | \begin{coq_example} |
1211 | 1237 | Fixpoint add (n m:nat) {struct n} : nat := |
1322 | 1348 | A generic command {\tt Scheme} is useful to build automatically various |
1323 | 1349 | mutual induction principles. It is described in Section~\ref{Scheme}. |
1324 | 1350 | |
1325 | \subsubsection{\tt Function {\ident} {\binder$_1$}\ldots{\binder$_n$} | |
1326 | {\tt \{}decrease\_annot{\tt\}} : type$_0$ := \term$_0$. | |
1327 | } | |
1328 | \comindex{Function} | |
1329 | \label{Function} | |
1330 | ||
1331 | This \emph{experimental} command can be seen as a generalization of | |
1332 | {\tt Fixpoint}. It is actually a wrapper for several ways of defining | |
1333 | a function \emph{and other useful related objects}, namely: an | |
1334 | induction principle that reflects the recursive structure of the | |
1335 | function (see \ref{FunInduction}), and its fixpoint equality (not | |
1336 | always, see below). The meaning of this declaration is to define a | |
1337 | function {\it ident}, similarly to {\tt Fixpoint}. Like in {\tt | |
1338 | Fixpoint}, the decreasing argument must be given (unless the function | |
1339 | is not recursive), but it must not necessary be \emph{structurally} | |
1340 | decreasing. The point of the {\tt | |
1341 | \{\}} annotation is to name the decreasing argument \emph{and} to | |
1351 | \subsubsection{A more complex definition of recursive functions} | |
1352 | ||
1353 | The \emph{experimental} command | |
1354 | \begin{center} | |
1355 | \texttt{Function {\ident} {\binder$_1$}\ldots{\binder$_n$} | |
1356 | \{decrease\_annot\} : type$_0$ := \term$_0$} | |
1357 | \comindex{Function} | |
1358 | \label{Function} | |
1359 | \end{center} | |
1360 | can be seen as a generalization of {\tt Fixpoint}. It is actually a | |
1361 | wrapper for several ways of defining a function \emph{and other useful | |
1362 | related objects}, namely: an induction principle that reflects the | |
1363 | recursive structure of the function (see \ref{FunInduction}), and its | |
1364 | fixpoint equality (not always, see below). The meaning of this | |
1365 | declaration is to define a function {\it ident}, similarly to {\tt | |
1366 | Fixpoint}. Like in {\tt Fixpoint}, the decreasing argument must be | |
1367 | given (unless the function is not recursive), but it must not | |
1368 | necessary be \emph{structurally} decreasing. The point of the {\tt | |
1369 | \{\}} annotation is to name the decreasing argument \emph{and} to | |
1342 | 1370 | describe which kind of decreasing criteria must be used to ensure |
1343 | 1371 | termination of recursive calls. |
1344 | 1372 | |
1415 | 1443 | |
1416 | 1444 | \SeeAlso{\ref{FunScheme},\ref{FunScheme-examples},\ref{FunInduction}} |
1417 | 1445 | |
1418 | Depending on the {\tt \{\}} annotation, different definition | |
1446 | Depending on the {\tt \{$\ldots$\}} annotation, different definition | |
1419 | 1447 | mechanisms are used by {\tt Function}. More precise description |
1420 | 1448 | given below. |
1421 | 1449 | |
1422 | ||
1423 | ||
1424 | \subsubsection{\tt Function {\ident} {\binder$_1$}\ldots{\binder$_n$} | |
1425 | : type$_0$ := \term$_0$. | |
1426 | \comindex{Function} | |
1427 | } | |
1428 | ||
1429 | Defines the not recursive function \ident\ as if declared with | |
1430 | \texttt{Definition}. Three elimination schemes {\tt\ident\_rect}, | |
1431 | {\tt\ident\_rec} and {\tt\ident\_ind} are generated (see the | |
1432 | documentation of {\tt Inductive} \ref{Inductive}), which reflect the | |
1433 | pattern matching structure of \term$_0$. | |
1434 | ||
1435 | ||
1436 | \subsubsection{\tt Function {\ident} {\binder$_1$}\ldots{\binder$_n$} | |
1437 | {\tt \{}{\tt struct} \ident$_0${\tt\}} : type$_0$ := \term$_0$. | |
1438 | \comindex{Function} | |
1439 | } | |
1440 | ||
1441 | Defines the structural recursive function \ident\ as if declared with | |
1442 | \texttt{Fixpoint} . Three induction schemes {\tt\ident\_rect}, | |
1443 | {\tt\ident\_rec} and {\tt\ident\_ind} are generated (see the | |
1444 | documentation of {\tt Inductive} \ref{Inductive}), which reflect the | |
1445 | recursive structure of \term$_0$. When there is only one parameter, | |
1446 | {\tt \{struct} \ident$_0${\tt\}} can be omitted. | |
1447 | ||
1448 | \subsubsection{\tt Function {\ident} {\binder$_1$}\ldots{\binder$_n$} | |
1449 | {\tt \{}{\tt measure \term$_1$} \ident$_0${\tt\}} : type$_0$ := \term$_0$. | |
1450 | \comindex{Function}} | |
1451 | ||
1452 | \subsubsection{\tt Function {\ident} {\binder$_1$}\ldots{\binder$_n$} | |
1453 | {\tt \{}{\tt wf \term$_1$} \ident$_0${\tt\}} : type$_0$ := \term$_0$. | |
1454 | \comindex{Function}} | |
1450 | \begin{Variants} | |
1451 | \item \texttt{ Function {\ident} {\binder$_1$}\ldots{\binder$_n$} | |
1452 | : type$_0$ := \term$_0$} | |
1453 | ||
1454 | Defines the not recursive function \ident\ as if declared with | |
1455 | \texttt{Definition}. Three elimination schemes {\tt\ident\_rect}, | |
1456 | {\tt\ident\_rec} and {\tt\ident\_ind} are generated (see the | |
1457 | documentation of {\tt Inductive} \ref{Inductive}), which reflect the | |
1458 | pattern matching structure of \term$_0$. | |
1459 | ||
1460 | \item \texttt{Function {\ident} {\binder$_1$}\ldots{\binder$_n$} | |
1461 | {\tt \{}{\tt struct} \ident$_0${\tt\}} : type$_0$ := \term$_0$} | |
1462 | ||
1463 | Defines the structural recursive function \ident\ as if declared | |
1464 | with \texttt{Fixpoint}. Three induction schemes {\tt\ident\_rect}, | |
1465 | {\tt\ident\_rec} and {\tt\ident\_ind} are generated (see the | |
1466 | documentation of {\tt Inductive} \ref{Inductive}), which reflect the | |
1467 | recursive structure of \term$_0$. When there is only one parameter, | |
1468 | {\tt \{struct} \ident$_0${\tt\}} can be omitted. | |
1469 | ||
1470 | \item \texttt{Function {\ident} {\binder$_1$}\ldots{\binder$_n$} {\tt | |
1471 | \{}{\tt measure \term$_1$} \ident$_0${\tt\}} : type$_0$ := | |
1472 | \term$_0$} | |
1473 | \item \texttt{Function {\ident} {\binder$_1$}\ldots{\binder$_n$} | |
1474 | {\tt \{}{\tt wf \term$_1$} \ident$_0${\tt\}} : type$_0$ := \term$_0$} | |
1455 | 1475 | |
1456 | 1476 | Defines a recursive function by well founded recursion. \textbf{The |
1457 | 1477 | module \texttt{Recdef} of the standard library must be loaded for this |
1507 | 1527 | %The decreasing argument cannot be dependent of another?? |
1508 | 1528 | |
1509 | 1529 | %Exemples faux ici |
1510 | ||
1511 | ||
1512 | ||
1513 | ||
1514 | ||
1515 | \subsubsection{\tt CoFixpoint {\ident} : \type$_0$ := \term$_0$. | |
1516 | \comindex{CoFixpoint} | |
1517 | \label{CoFixpoint}} | |
1518 | ||
1519 | The {\tt CoFixpoint} command introduces a method for constructing an | |
1520 | infinite object of a coinduc\-tive type. For example, the stream | |
1521 | containing all natural numbers can be introduced applying the | |
1522 | following method to the number \texttt{O} (see | |
1523 | Section~\ref{CoInductiveTypes} for the definition of {\tt Stream}, | |
1524 | {\tt hd} and {\tt tl}): | |
1530 | \end{Variants} | |
1531 | ||
1532 | ||
1533 | \subsubsection{Recursive functions over co-indcutive types} | |
1534 | ||
1535 | The command: | |
1536 | \begin{center} | |
1537 | \texttt{CoFixpoint {\ident} : \type$_0$ := \term$_0$} | |
1538 | \comindex{CoFixpoint}\label{CoFixpoint} | |
1539 | \end{center} | |
1540 | introduces a method for constructing an infinite object of a | |
1541 | coinduc\-tive type. For example, the stream containing all natural | |
1542 | numbers can be introduced applying the following method to the number | |
1543 | \texttt{O} (see Section~\ref{CoInductiveTypes} for the definition of | |
1544 | {\tt Stream}, {\tt hd} and {\tt tl}): | |
1525 | 1545 | \begin{coq_eval} |
1526 | 1546 | Reset Initial. |
1527 | 1547 | CoInductive Stream : Set := |
1605 | 1625 | |
1606 | 1626 | \begin{Variants} |
1607 | 1627 | \item {\tt Lemma {\ident} : {\type}.}\\ |
1608 | It is a synonymous of \texttt{Theorem} | |
1609 | \item {\tt Remark {\ident} : {\type}.}\\ | |
1610 | It is a synonymous of \texttt{Theorem} | |
1628 | {\tt Remark {\ident} : {\type}.}\\ | |
1629 | {\tt Fact {\ident} : {\type}.}\\ | |
1630 | {\tt Corollary {\ident} : {\type}.}\\ | |
1631 | {\tt Proposition {\ident} : {\type}.}\\ | |
1632 | \comindex{Proposition} | |
1633 | \comindex{Corollary} | |
1634 | All these commands are synonymous of \texttt{Theorem} | |
1611 | 1635 | % Same as {\tt Theorem} except |
1612 | 1636 | % that if this statement is in one or more levels of sections then the |
1613 | 1637 | % name {\ident} will be accessible only prefixed by the sections names |
1615 | 1639 | % closed. |
1616 | 1640 | % %All proofs of persistent objects (such as theorems) referring to {\ident} |
1617 | 1641 | % %within the section will be replaced by the proof of {\ident}. |
1618 | \item {\tt Fact {\ident} : {\type}.}\\ | |
1619 | It is a synonymous of \texttt{Theorem} | |
1620 | 1642 | % Same as {\tt Remark} except |
1621 | 1643 | % that the innermost section name is dropped from the full name. |
1622 | 1644 | \item {\tt Definition {\ident} : {\type}.} \\ |
1683 | 1705 | % TeX-master: "Reference-Manual" |
1684 | 1706 | % End: |
1685 | 1707 | |
1686 | % $Id: RefMan-gal.tex 8915 2006-06-07 15:17:13Z courtieu $ | |
1708 | % $Id: RefMan-gal.tex 9040 2006-07-11 18:06:49Z notin $ |
10 | 10 | \CoqIDE{} is run by typing the command \verb|coqide| on the command |
11 | 11 | line. Without argument, the main screen is displayed with an ``unnamed |
12 | 12 | buffer'', and with a file name as argument, another buffer displaying |
13 | the contents of that file. Additionally, coqide accepts the same | |
14 | options as coqtop, given in Chapter~\ref{Addoc-coqc}, the ones having | |
15 | obviously no meaning for \CoqIDE{} being ignored. | |
13 | the contents of that file. Additionally, \verb|coqide| accepts the same | |
14 | options as \verb|coqtop|, given in Chapter~\ref{Addoc-coqc}, the ones having | |
15 | obviously no meaning for \CoqIDE{} being ignored. Additionally, \verb|coqide| accepts the option \verb|-enable-geoproof| to enable the support for \emph{GeoProof} \footnote{\emph{GeoProof} is dynamic geometry software which can be used in conjunction with \CoqIDE{} to interactively build a Coq statement corresponding to a geometric figure. More information about \emph{GeoProof} can be found here: \url{http://home.gna.org/geoproof/} }. | |
16 | ||
16 | 17 | |
17 | 18 | \begin{figure}[t] |
18 | 19 | \begin{center} |
318 | 319 | |
319 | 320 | |
320 | 321 | |
321 | % $Id: RefMan-ide.tex 8626 2006-03-14 15:01:00Z notin $ | |
322 | % $Id: RefMan-ide.tex 8945 2006-06-10 12:04:14Z jnarboux $ | |
322 | 323 | |
323 | 324 | %%% Local Variables: |
324 | 325 | %%% mode: latex |
102 | 102 | {\tt match reverse goal with} \nelist{\contextrule}{\tt |} {\tt end}\\ |
103 | 103 | & | & |
104 | 104 | {\tt match} {\tacexpr} {\tt with} \nelist{\matchrule}{\tt |} {\tt end}\\ |
105 | & | & | |
106 | {\tt lazymatch goal with} \nelist{\contextrule}{\tt |} {\tt end}\\ | |
107 | & | & | |
108 | {\tt lazymatch reverse goal with} \nelist{\contextrule}{\tt |} {\tt end}\\ | |
109 | & | & | |
110 | {\tt lazymatch} {\tacexpr} {\tt with} \nelist{\matchrule}{\tt |} {\tt end}\\ | |
105 | 111 | & | & {\tt abstract} {\atom}\\ |
106 | 112 | & | & {\tt abstract} {\atom} {\tt using} {\ident} \\ |
107 | 113 | & | & {\tt first [} \nelist{\tacexpr}{\tt |} {\tt ]}\\ |
108 | 114 | & | & {\tt solve [} \nelist{\tacexpr}{\tt |} {\tt ]}\\ |
109 | & | & {\tt idtac} ~|~ {\tt idtac} {\qstring}\\ | |
110 | & | & {\tt fail} ~|~ {\tt fail} {\naturalnumber} {\qstring}\\ | |
115 | & | & {\tt idtac} \sequence{\messagetoken}{}\\ | |
116 | & | & {\tt fail} \zeroone{\naturalnumber} \sequence{\messagetoken}{}\\ | |
111 | 117 | & | & {\tt fresh} ~|~ {\tt fresh} {\qstring}\\ |
112 | 118 | & | & {\tt context} {\ident} {\tt [} {\term} {\tt ]}\\ |
113 | 119 | & | & {\tt eval} {\nterm{redexpr}} {\tt in} {\term}\\ |
114 | 120 | & | & {\tt type of} {\term}\\ |
121 | & | & {\tt external} {\qstring} {\qstring} \nelist{\tacarg}{}\\ | |
115 | 122 | & | & {\tt constr :} {\term}\\ |
116 | 123 | & | & \atomictac\\ |
117 | 124 | & | & {\qualid} \nelist{\tacarg}{}\\ |
121 | 128 | {\qualid} \\ |
122 | 129 | & | & ()\\ |
123 | 130 | & | & {\tt (} {\tacexpr} {\tt )}\\ |
131 | \\ | |
132 | {\messagetoken}\!\!\!\!\!\! & ::= & {\qstring} ~|~ {\term} ~|~ {\integer} \\ | |
124 | 133 | \end{tabular} |
125 | 134 | \end{centerframe} |
126 | 135 | \caption{Syntax of the tactic language} |
265 | 274 | application of $v_0$, for $=1,...,n$. It fails if the application of |
266 | 275 | $v_0$ does not generate exactly $n$ subgoals. |
267 | 276 | |
277 | \variant If no tactic is given for the $i$-th generated subgoal, it | |
278 | behaves as if the tactic {\tt idtac} were given. For instance, {\tt | |
279 | split ; [ | auto ]} is a shortcut for | |
280 | {\tt split ; [ idtac | auto ]}. | |
281 | ||
282 | ||
268 | 283 | \subsubsection{For loop} |
269 | 284 | \tacindex{do} |
270 | 285 | \index{Tacticals!do@{\tt do}} |
368 | 383 | |
369 | 384 | The constant {\tt idtac} is the identity tactic: it leaves any goal |
370 | 385 | unchanged but it appears in the proof script. |
371 | \begin{quote} | |
372 | {\tt idtac} and {\tt idtac "message"} | |
373 | \end{quote} | |
374 | The latter variant prints the string on the standard output. | |
386 | ||
387 | \variant {\tt idtac \nelist{\messagetoken}{}} | |
388 | ||
389 | This prints the given tokens. Strings and integers are printed | |
390 | literally. If a term is given, it is printed, its variables being | |
391 | interpreted in the current environment. In particular, if a variable | |
392 | is given, its value is printed. | |
375 | 393 | |
376 | 394 | |
377 | 395 | \subsubsection{Failing} |
380 | 398 | |
381 | 399 | The tactic {\tt fail} is the always-failing tactic: it does not solve |
382 | 400 | any goal. It is useful for defining other tacticals since it can be |
383 | catched by {\tt try} or {\tt match goal}. There are three variants: | |
384 | \begin{quote} | |
385 | {\tt fail $n$}, {\tt fail "message"} and {\tt fail $n$ "message"} | |
386 | \end{quote} | |
401 | catched by {\tt try} or {\tt match goal}. | |
402 | ||
403 | \begin{Variants} | |
404 | \item {\tt fail $n$}\\ | |
387 | 405 | The number $n$ is the failure level. If no level is specified, it |
388 | 406 | defaults to $0$. The level is used by {\tt try} and {\tt match goal}. |
389 | 407 | If $0$, it makes {\tt match goal} considering the next clause |
390 | 408 | (backtracking). If non zero, the current {\tt match goal} block or |
391 | 409 | {\tt try} command is aborted and the level is decremented. |
392 | 410 | |
393 | \ErrMsg \errindex{Tactic Failure "message" (level $n$)}. | |
411 | \item {\tt fail \nelist{\messagetoken}{}}\\ | |
412 | The given tokens are used for printing the failure message. | |
413 | ||
414 | \item {\tt fail $n$ \nelist{\messagetoken}{}}\\ | |
415 | This is a combination of the previous variants. | |
416 | \end{Variants} | |
417 | ||
418 | \ErrMsg \errindex{Tactic Failure {\it message} (level $n$)}. | |
394 | 419 | |
395 | 420 | \subsubsection{Local definitions} |
396 | 421 | \index{Ltac!let} |
463 | 488 | pattern matching instantiations to the metavariables. If the matching |
464 | 489 | with {\cpattern}$_1$ fails, {\cpattern}$_2$ is used and so on. The |
465 | 490 | pattern {\_} matches any term and shunts all remaining patterns if |
466 | any. If {\tacexpr}$_1$ evaluates to a tactic, this tactic is not | |
467 | immediately applied to the current goal (in contrast with {\tt match | |
468 | goal}). If all clauses fail (in particular, there is no pattern {\_}) | |
469 | then a no-matching error is raised. | |
491 | any. If {\tacexpr}$_1$ evaluates to a tactic and the {\tt match} | |
492 | expression is in position to be applied to a goal (e.g. it is not | |
493 | bound to a variable by a {\tt let in}, then this tactic is applied. If | |
494 | the tactic succeeds, the list of resulting subgoals is the result of | |
495 | the {\tt match} expression. On the opposite, if it fails, the next | |
496 | pattern is tried. If all clauses fail (in particular, there is no | |
497 | pattern {\_}) then a no-matching error is raised. | |
470 | 498 | |
471 | 499 | \begin{ErrMsgs} |
472 | 500 | |
480 | 508 | |
481 | 509 | \end{ErrMsgs} |
482 | 510 | |
483 | \index{context!in pattern} | |
511 | \begin{Variants} | |
512 | \item \index{context!in pattern} | |
484 | 513 | There is a special form of patterns to match a subterm against the |
485 | 514 | pattern: |
486 | 515 | \begin{quote} |
492 | 521 | hole. The definition of {\tt context} in expressions below will show |
493 | 522 | how to use such term contexts. |
494 | 523 | |
495 | This operator never makes backtracking. If there are several subterms | |
496 | matching the pattern, only the first match is considered. Note that | |
497 | the order of matching is left unspecified. | |
498 | %% TODO: clarify this point! It *should* be specified | |
499 | ||
524 | If the evaluation of the right-hand-side of a valid match fails, the | |
525 | next matching subterm is tried. If no further subterm matches, the | |
526 | next clause is tried. Matching subterms are considered top-bottom and | |
527 | from left to right (with respect to the raw printing obtained by | |
528 | setting option {\tt Printing All}, see section~\ref{SetPrintingAll}). | |
529 | ||
530 | \begin{coq_example} | |
531 | Ltac f x := | |
532 | match x with | |
533 | context f [S ?X] => | |
534 | idtac X; (* To display the evaluation order *) | |
535 | assert (p := refl_equal 1 : X=1); (* To filter the case X=1 *) | |
536 | let x:= context f[O] in assert (x=O) (* To observe the context *) | |
537 | end. | |
538 | Goal True. | |
539 | f (3+4). | |
540 | \end{coq_example} | |
541 | ||
542 | \item \index{lazymatch!in Ltac} | |
543 | \index{Ltac!lazymatch} | |
544 | Using {\tt lazymatch} instead of {\tt match} has an effect if the | |
545 | right-hand-side of a clause returns a tactic. With {\tt match}, the | |
546 | tactic is applied to the current goal (and the next clause is tried if | |
547 | it fails). With {\tt lazymatch}, the tactic is directly returned as | |
548 | the result of the whole {\tt lazymatch} block without being first | |
549 | tried to be applied to the goal. Typically, if the {\tt lazymatch} | |
550 | block is bound to some variable $x$ in a {\tt let in}, then tactic | |
551 | expression gets bound to the variable $x$. | |
552 | ||
553 | \end{Variants} | |
500 | 554 | |
501 | 555 | \subsubsection{Pattern matching on goals} |
502 | 556 | \index{Ltac!match goal} |
520 | 574 | \end{tabbing} |
521 | 575 | \end{quote} |
522 | 576 | |
523 | % TODO: specify order of hypothesis and explain reverse... | |
524 | ||
525 | 577 | If each hypothesis pattern $hyp_{1,i}$, with $i=1,...,m_1$ |
526 | 578 | is matched (non-linear first order unification) by an hypothesis of |
527 | 579 | the goal and if {\cpattern}$_1$ is matched by the conclusion of the |
534 | 586 | no other combination of hypotheses then the second proof context |
535 | 587 | pattern is tried and so on. If the next to last proof context pattern |
536 | 588 | fails then {\tacexpr}$_{n+1}$ is evaluated to $v_{n+1}$ and $v_{n+1}$ |
537 | is applied. | |
589 | is applied. Note also that matching against subterms (using the {\tt | |
590 | context} {\ident} {\tt [} {\cpattern} {\tt ]}) is available and may | |
591 | itself induce extra backtrackings. | |
538 | 592 | |
539 | 593 | \ErrMsg \errindex{No matching clauses for match goal} |
540 | 594 | |
551 | 605 | first), but it possible to reverse this order (older first) with |
552 | 606 | the {\tt match reverse goal with} variant. |
553 | 607 | |
608 | \variant | |
609 | \index{lazymatch goal!in Ltac} | |
610 | \index{Ltac!lazymatch goal} | |
611 | \index{lazymatch reverse goal!in Ltac} | |
612 | \index{Ltac!lazymatch reverse goal} | |
613 | Using {\tt lazymatch} instead of {\tt match} has an effect if the | |
614 | right-hand-side of a clause returns a tactic. With {\tt match}, the | |
615 | tactic is applied to the current goal (and the next clause is tried if | |
616 | it fails). With {\tt lazymatch}, the tactic is directly returned as | |
617 | the result of the whole {\tt lazymatch} block without being first | |
618 | tried to be applied to the goal. Typically, if the {\tt lazymatch} | |
619 | block is bound to some variable $x$ in a {\tt let in}, then tactic | |
620 | expression gets bound to the variable $x$. | |
621 | ||
622 | \begin{coq_example} | |
623 | Ltac test_lazy := | |
624 | lazymatch goal with | |
625 | | _ => idtac "here"; fail | |
626 | | _ => idtac "wasn't lazy"; trivial | |
627 | end. | |
628 | Ltac test_eager := | |
629 | match goal with | |
630 | | _ => idtac "here"; fail | |
631 | | _ => idtac "wasn't lazy"; trivial | |
632 | end. | |
633 | Goal True. | |
634 | test_lazy || idtac "was lazy". | |
635 | test_eager || idtac "was lazy". | |
636 | \end{coq_example} | |
637 | ||
554 | 638 | \subsubsection{Filling a term context} |
555 | 639 | \index{context!in expression} |
556 | 640 | |
584 | 668 | by padding {\qstring} with a number if necessary. If no name is given, |
585 | 669 | the prefix is {\tt H}. |
586 | 670 | |
587 | \subsubsection{{\tt type of} {\term}} | |
671 | \subsubsection{Computing in a constr} | |
672 | \index{Ltac!eval} | |
673 | \index{eval!in Ltac} | |
674 | ||
675 | Evaluation of a term can be performed with: | |
676 | \begin{quote} | |
677 | {\tt eval} {\nterm{redexpr}} {\tt in} {\term} | |
678 | \end{quote} | |
679 | where \nterm{redexpr} is a reduction tactic among {\tt red}, {\tt | |
680 | hnf}, {\tt compute}, {\tt simpl}, {\tt cbv}, {\tt lazy}, {\tt unfold}, | |
681 | {\tt fold}, {\tt pattern}. | |
682 | ||
683 | \subsubsection{Type-checking a term} | |
588 | 684 | %\tacindex{type of} |
589 | 685 | \index{Ltac!type of} |
590 | 686 | \index{type of!in Ltac} |
591 | 687 | |
592 | This tactic computes the type of {\term}. | |
593 | ||
594 | \subsubsection{Computing in a constr} | |
595 | \index{Ltac!eval} | |
596 | \index{eval!in Ltac} | |
597 | ||
598 | Evaluation of a term can be performed with: | |
599 | \begin{quote} | |
600 | {\tt eval} {\nterm{redexpr}} {\tt in} {\term} | |
601 | \end{quote} | |
602 | where \nterm{redexpr} is a reduction tactic among {\tt red}, {\tt | |
603 | hnf}, {\tt compute}, {\tt simpl}, {\tt cbv}, {\tt lazy}, {\tt unfold}, | |
604 | {\tt fold}, {\tt pattern}. | |
605 | ||
688 | The following returns the type of {\term}: | |
689 | ||
690 | \begin{quote} | |
691 | {\tt type of} {\term} | |
692 | \end{quote} | |
606 | 693 | |
607 | 694 | \subsubsection{Accessing tactic decomposition} |
608 | 695 | \tacindex{info} |
634 | 721 | |
635 | 722 | \ErrMsg \errindex{Proof is not complete} |
636 | 723 | |
724 | \subsubsection{Calling an external tactic} | |
725 | \index{Ltac!external} | |
726 | ||
727 | The tactic {\tt external} allows to run an executable outside the | |
728 | {\Coq} executable. The communication is done via an XML encoding of | |
729 | constructions. The syntax of the command is | |
730 | ||
731 | \begin{quote} | |
732 | {\tt external} "\textsl{command}" "\textsl{request}" \nelist{\tacarg}{} | |
733 | \end{quote} | |
734 | ||
735 | The string \textsl{command}, to be interpreted in the default | |
736 | execution path of the operating system, is the name of the external | |
737 | command. The string \textsl{request} is the name of a request to be | |
738 | sent to the external command. Finally the list of tactic arguments | |
739 | have to evaluate to terms. An XML tree of the following form is sent | |
740 | to the standard input of the external command. | |
741 | \medskip | |
742 | ||
743 | \begin{tabular}{l} | |
744 | \texttt{<REQUEST req="}\textsl{request}\texttt{">}\\ | |
745 | the XML tree of the first argument\\ | |
746 | {\ldots}\\ | |
747 | the XML tree of the last argument\\ | |
748 | \texttt{</REQUEST>}\\ | |
749 | \end{tabular} | |
750 | \medskip | |
751 | ||
752 | Conversely, the external command must send on its standard output an | |
753 | XML tree of the following forms: | |
754 | ||
755 | \medskip | |
756 | \begin{tabular}{l} | |
757 | \texttt{<TERM>}\\ | |
758 | the XML tree of a term\\ | |
759 | \texttt{</TERM>}\\ | |
760 | \end{tabular} | |
761 | \medskip | |
762 | ||
763 | \noindent or | |
764 | ||
765 | \medskip | |
766 | \begin{tabular}{l} | |
767 | \texttt{<CALL uri="}\textsl{ltac\_qualified\_ident}\texttt{">}\\ | |
768 | the XML tree of a first argument\\ | |
769 | {\ldots}\\ | |
770 | the XML tree of a last argument\\ | |
771 | \texttt{</CALL>}\\ | |
772 | \end{tabular} | |
773 | ||
774 | \medskip | |
775 | \noindent where \textsl{ltac\_qualified\_ident} is the name of a | |
776 | defined {\ltac} function and each subsequent XML tree is recursively a | |
777 | \texttt{CALL} or a \texttt{TERM} node. | |
778 | ||
779 | The Document Type Definition (DTD) for terms of the Calculus of | |
780 | Inductive Constructions is the one developed as part of the MoWGLI | |
781 | European project. It can be found in the file {\tt dev/doc/cic.dtd} of | |
782 | the {\Coq} source archive. | |
783 | ||
784 | An example of parser for this DTD, written in the Objective Caml - | |
785 | Camlp4 language, can be found in the file {\tt parsing/g\_xml.ml4} of | |
786 | the {\Coq} source archive. | |
787 | ||
637 | 788 | \section{Tactic toplevel definitions} |
638 | 789 | \comindex{Ltac} |
639 | 790 | |
640 | Basically, tactics toplevel definitions are made as follows: | |
791 | \subsection{Defining {\ltac} functions} | |
792 | ||
793 | Basically, {\ltac} toplevel definitions are made as follows: | |
641 | 794 | %{\tt Tactic Definition} {\ident} {\tt :=} {\tacexpr}\\ |
642 | 795 | % |
643 | 796 | %{\tacexpr} is evaluated to $v$ and $v$ is associated to {\ident}. Next, every |
648 | 801 | {\tt Ltac} {\ident} {\ident}$_1$ ... {\ident}$_n$ {\tt :=} |
649 | 802 | {\tacexpr} |
650 | 803 | \end{quote} |
651 | This defines a new tactic that can be used in any tactic script or new | |
652 | tactic toplevel definition. | |
804 | This defines a new {\ltac} function that can be used in any tactic | |
805 | script or new {\ltac} toplevel definition. | |
653 | 806 | |
654 | 807 | \Rem The preceding definition can equivalently be written: |
655 | 808 | \begin{quote} |
673 | 826 | %usual except that the substitutions are lazily carried out (when an identifier |
674 | 827 | %to be evaluated is the name of a recursive definition). |
675 | 828 | |
829 | ||
830 | \subsection{Printing {\ltac} tactics} | |
831 | \comindex{Print Ltac} | |
832 | ||
833 | Defined {\ltac} functions can be displayed using the command | |
834 | ||
835 | \begin{quote} | |
836 | {\tt Print Ltac {\qualid}.} | |
837 | \end{quote} | |
838 | ||
839 | \section{Debugging {\ltac} tactics} | |
840 | \comindex{Set Ltac Debug} | |
841 | \comindex{Unset Ltac Debug} | |
842 | \comindex{Test Ltac Debug} | |
843 | ||
844 | The {\ltac} interpreter comes with a step-by-step debugger. The | |
845 | debugger can be activated using the command | |
846 | ||
847 | \begin{quote} | |
848 | {\tt Set Ltac Debug.} | |
849 | \end{quote} | |
850 | ||
851 | \noindent and deactivated using the command | |
852 | ||
853 | \begin{quote} | |
854 | {\tt Unset Ltac Debug.} | |
855 | \end{quote} | |
856 | ||
857 | To know if the debugger is on, use the command \texttt{Test Ltac Debug}. | |
858 | When the debugger is activated, it stops at every step of the | |
859 | evaluation of the current {\ltac} expression and it prints information | |
860 | on what it is doing. The debugger stops, prompting for a command which | |
861 | can be one of the following: | |
862 | ||
863 | \medskip | |
864 | \begin{tabular}{ll} | |
865 | simple newline: & go to the next step\\ | |
866 | h: & get help\\ | |
867 | x: & exit current evaluation\\ | |
868 | s: & continue current evaluation without stopping\\ | |
869 | r$n$: & advance $n$ steps further\\ | |
870 | \end{tabular} | |
676 | 871 | \endinput |
677 | ||
678 | 872 | |
679 | 873 | \subsection{Permutation on closed lists} |
680 | 874 |
54 | 54 | {\modbindings}. The output module type is verified against the |
55 | 55 | module type {\modtype}. |
56 | 56 | |
57 | \item\texttt{Module [Import|Export]} | |
58 | ||
59 | Behaves like \texttt{Module}, but automatically imports or exports | |
60 | the module. | |
61 | ||
57 | 62 | \end{Variants} |
58 | 63 | |
59 | 64 | \subsection{\tt End {\ident} |
138 | 143 | {\modbindings} and returning {\modtype}. |
139 | 144 | \end{Variants} |
140 | 145 | |
141 | \subsection{\tt Declare Module {\ident}} | |
142 | ||
143 | Starts an interactive module declaration. This command is available | |
144 | only in module types. | |
145 | ||
146 | \begin{Variants} | |
147 | ||
148 | \item{\tt Declare Module {\ident} {\modbindings}} | |
149 | ||
150 | Starts an interactive declaration of a functor with parameters given | |
151 | by {\modbindings}. | |
152 | ||
153 | % Particular case of the next item | |
154 | %\item{\tt Declare Module {\ident} \verb.<:. {\modtype}} | |
155 | % | |
156 | % Starts an interactive declaration of a module satisfying {\modtype}. | |
157 | ||
158 | \item{\tt Declare Module {\ident} {\modbindings} \verb.<:. {\modtype}} | |
159 | ||
160 | Starts an interactive declaration of a functor with parameters given | |
161 | by {\modbindings} (possibly none). The declared output module type is | |
162 | verified against the module type {\modtype}. | |
163 | ||
164 | \end{Variants} | |
165 | ||
166 | \subsection{\tt End {\ident}} | |
167 | ||
168 | This command closes the interactive declaration of module {\ident}. | |
169 | ||
170 | 146 | \subsection{\tt Declare Module {\ident} : {\modtype}} |
171 | 147 | |
172 | Declares a module of {\ident} of type {\modtype}. This command is available | |
148 | Declares a module {\ident} of type {\modtype}. This command is available | |
173 | 149 | only in module types. |
174 | 150 | |
175 | 151 | \begin{Variants} |
187 | 163 | |
188 | 164 | Declares a module equal to the module {\qualid}, verifying that the |
189 | 165 | module type of the latter is a subtype of {\modtype}. |
166 | ||
167 | \item\texttt{Declare Module [Import|Export] {\ident} := {\qualid}} | |
168 | ||
169 | Declares a modules {\ident} of type {\modtype}, and imports or | |
170 | exports it directly. | |
190 | 171 | |
191 | 172 | \end{Variants} |
192 | 173 | |
388 | 369 | |
389 | 370 | Prints the module type corresponding to {\ident}. |
390 | 371 | |
372 | \subsection{\texttt{Locate Module {\qualid}} | |
373 | \comindex{Locate Module}} | |
374 | ||
375 | Prints the full name of the module {\qualid}. | |
376 | ||
391 | 377 | |
392 | 378 | %%% Local Variables: |
393 | 379 | %%% mode: latex |
333 | 333 | |
334 | 334 | \SeeAlso Section \ref{LocateSymbol} |
335 | 335 | |
336 | \subsection{The {\sc Whelp} searching tool | |
337 | \label{Whelp}} | |
338 | ||
339 | {\sc Whelp} is an experimental searching and browsing tool for the | |
340 | whole {\Coq} library and the whole set of {\Coq} user contributions. | |
341 | {\sc Whelp} requires a browser to work. {\sc Whelp} has been developed | |
342 | at the University of Bologna as part of the HELM\footnote{Hypertextual | |
343 | Electronic Library of Mathematics} and MoWGLI\footnote{Mathematics on | |
344 | the Web, Get it by Logics and Interfaces} projects. It can be invoked | |
345 | directly from the {\Coq} toplevel or from {\CoqIDE}, assuming a | |
346 | graphical environment is also running. The browser to use can be | |
347 | selected by setting the environment variable {\tt | |
348 | COQREMOTEBROWSER}. If not explicitly set, it defaults to | |
349 | \verb!netscape -remote "OpenURL(%s)"! or | |
350 | \verb!C:\\PROGRA~1\\INTERN~1\\IEXPLORE %s!, depending on the | |
351 | underlying operating system (in the command, the string \verb!%s! | |
352 | serves as metavariable for the url to open). | |
353 | ||
354 | The {\sc Whelp} commands are: | |
355 | ||
356 | \subsubsection{\tt Whelp Locate "{\sl reg\_expr}". | |
357 | \comindex{Whelp Locate}} | |
358 | ||
359 | This command opens a browser window and displays the result of seeking | |
360 | for all names that match the regular expression {\sl reg\_expr} in the | |
361 | {\Coq} library and user contributions. The regular expression can | |
362 | contain the special operators are * and ? that respectively stand for | |
363 | an arbitrary substring and for exactly one character. | |
364 | ||
365 | \variant {\tt Whelp Locate {\ident}.}\\ | |
366 | This is equivalent to {\tt Whelp Locate "{\ident}"}. | |
367 | ||
368 | \subsubsection{\tt Whelp Match {\pattern}. | |
369 | \comindex{Whelp Match}} | |
370 | ||
371 | This command opens a browser window and displays the result of seeking | |
372 | for all statements that match the pattern {\pattern}. Holes in the | |
373 | pattern are represented by the wildcard character ``\_''. | |
374 | ||
375 | \subsubsection{\tt Whelp Instance {\pattern}.} | |
376 | \comindex{Whelp Instance} | |
377 | ||
378 | This command opens a browser window and displays the result of seeking | |
379 | for all statements that are instances of the pattern {\pattern}. The | |
380 | pattern is here assumed to be an universally quantified expression. | |
381 | ||
382 | \subsubsection{\tt Whelp Elim {\qualid}.} | |
383 | \comindex{Whelp Elim} | |
384 | ||
385 | This command opens a browser window and displays the result of seeking | |
386 | for all statements that have the ``form'' of an elimination scheme | |
387 | over the type denoted by {\qualid}. | |
388 | ||
389 | \subsubsection{\tt Whelp Hint {\term}.} | |
390 | \comindex{Whelp Hint} | |
391 | ||
392 | This command opens a browser window and displays the result of seeking | |
393 | for all statements that can be instantiated so that to prove the | |
394 | statement {\term}. | |
395 | ||
396 | \variant {\tt Whelp Hint.}\\ This is equivalent to {\tt Whelp Hint | |
397 | {\sl goal}} where {\sl goal} is the current goal to prove. Notice that | |
398 | {\Coq} does not send the local environment of definitions to the {\sc | |
399 | Whelp} tool so that it only works on requests strictly based on, only, | |
400 | definitions of the standard library and user contributions. | |
401 | ||
336 | 402 | \section{Loading files} |
337 | 403 | |
338 | 404 | \Coq\ offers the possibility of loading different |
764 | 830 | %\subsection{\tt Abstraction ...} |
765 | 831 | %Not yet documented. |
766 | 832 | |
767 | % $Id: RefMan-oth.tex 8606 2006-02-23 13:58:10Z herbelin $ | |
833 | \section{Controlling the conversion algorithm} | |
834 | ||
835 | {\Coq} comes with two algorithms to check the convertibility of types | |
836 | (see section~\ref{convertibility}). The first algorithm lazily | |
837 | compares applicative terms while the other is a brute-force but efficient | |
838 | algorithm that first normalizes the terms before comparing them. The | |
839 | second algorithm is based on a bytecode representation of terms | |
840 | similar to the bytecode representation used in the ZINC virtual | |
841 | machine~\cite{Leroy90}. It is specially useful for intensive | |
842 | computation of algebraic values, such as numbers, and for reflexion-based | |
843 | tactics. | |
844 | ||
845 | \subsection{\tt Set Virtual Machine | |
846 | \label{SetVirtualMachine} | |
847 | \comindex{Set Virtual Machine}} | |
848 | ||
849 | This activates the bytecode-based conversion algorithm. | |
850 | ||
851 | \subsection{\tt Unset Virtual Machine | |
852 | \comindex{Unset Virtual Machine}} | |
853 | ||
854 | This deactivates the bytecode-based conversion algorithm. | |
855 | ||
856 | \subsection{\tt Test Virtual Machine | |
857 | \comindex{Test Virtual Machine}} | |
858 | ||
859 | This tells if the bytecode-based conversion algorithm is | |
860 | activated. The default behavior is to have the bytecode-based | |
861 | conversion algorithm deactivated. | |
862 | ||
863 | \SeeAlso sections~\ref{vmcompute} and~\ref{vmoption}. | |
864 | ||
865 | % $Id: RefMan-oth.tex 9044 2006-07-12 13:22:17Z herbelin $ | |
768 | 866 | |
769 | 867 | %%% Local Variables: |
770 | 868 | %%% mode: latex |
555 | 555 | Laurent Théry's contribution on strings and Pierre Letouzey and |
556 | 556 | Jean-Christophe Filliâtre's contribution on finite maps have been |
557 | 557 | integrated to the {\Coq} standard library. Pierre Letouzey developed a |
558 | library about finite sets ``à la Objective Caml'' and extended the | |
559 | lists library. Pierre Letouzey's contribution on rational numbers | |
560 | has been integrated too. | |
558 | library about finite sets ``à la Objective Caml''. With Jean-Marc | |
559 | Notin, he extended the library on lists. Pierre Letouzey's | |
560 | contribution on rational numbers has been integrated and extended.. | |
561 | 561 | |
562 | 562 | Pierre Corbineau extended his tactic for solving first-order |
563 | statements. He wrote a reflexion-based intuitionistic tautology | |
563 | statements. He wrote a reflection-based intuitionistic tautology | |
564 | 564 | solver. |
565 | 565 | |
566 | Jean-Marc Notin took care of {\textsf{coqdoc}} and of the general | |
567 | maintenance of the system. | |
568 | ||
569 | \begin{flushright} | |
570 | Palaiseau, Apr. 2006\\ | |
566 | Jean-Marc Notin significantly contributed to the general maintenance | |
567 | of the system. He also took care of {\textsf{coqdoc}}. | |
568 | ||
569 | \begin{flushright} | |
570 | Palaiseau, July 2006\\ | |
571 | 571 | Hugo Herbelin |
572 | 572 | \end{flushright} |
573 | 573 | |
576 | 576 | % Integration of ZArith lemmas from Sophia and Nijmegen. |
577 | 577 | |
578 | 578 | |
579 | % $Id: RefMan-pre.tex 8941 2006-06-09 16:43:42Z herbelin $ | |
579 | % $Id: RefMan-pre.tex 9030 2006-07-07 15:37:23Z herbelin $ | |
580 | 580 | |
581 | 581 | %%% Local Variables: |
582 | 582 | %%% mode: latex |
162 | 162 | current section. |
163 | 163 | \end{Variants} |
164 | 164 | |
165 | \subsection{\tt Proof {\term}.}\comindex{Proof} | |
165 | \subsection{\tt Proof {\term}.} | |
166 | \comindex{Proof} | |
167 | \label{BeginProof} | |
166 | 168 | This command applies in proof editing mode. It is equivalent to {\tt |
167 | 169 | exact {\term}; Save.} That is, you have to give the full proof in |
168 | 170 | one gulp, as a proof term (see section \ref{exact}). |
169 | 171 | |
170 | \begin{Variants} | |
171 | ||
172 | \item{\tt Proof.} | |
172 | \variant {\tt Proof.} | |
173 | 173 | |
174 | 174 | Is a noop which is useful to delimit the sequence of tactic commands |
175 | 175 | which start a proof, after a {\tt Theorem} command. It is a good |
176 | 176 | practice to use {\tt Proof.} as an opening parenthesis, closed in |
177 | 177 | the script with a closing {\tt Qed.} |
178 | 178 | |
179 | \item{\tt Proof with {\tac}.} | |
180 | ||
181 | This command may be used to start a proof. It defines a default | |
182 | tactic to be used each time a tactic command is ended by | |
183 | ``\verb#...#''. In this case the tactic command typed by the user is | |
184 | equivalent to \emph{command};{\tac}. | |
185 | ||
186 | \end{Variants} | |
179 | \SeeAlso {\tt Proof with {\tac}.} in section~\ref{ProofWith}. | |
187 | 180 | |
188 | 181 | \subsection{\tt Abort.} |
189 | 182 | \comindex{Abort} |
380 | 373 | This command goes back to the default mode which is to print all |
381 | 374 | available hypotheses. |
382 | 375 | |
383 | % $Id: RefMan-pro.tex 8609 2006-02-24 13:32:57Z notin,no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty $ | |
376 | % $Id: RefMan-pro.tex 9030 2006-07-07 15:37:23Z herbelin $ | |
384 | 377 | |
385 | 378 | %%% Local Variables: |
386 | 379 | %%% mode: latex |
219 | 219 | \begin{quote} |
220 | 220 | \tt Print Grammar constr. |
221 | 221 | \end{quote} |
222 | ||
223 | \variant | |
224 | ||
225 | \comindex{Print Grammar pattern} | |
226 | {\tt Print Grammar pattern.}\\ | |
227 | ||
228 | This displays the state of the subparser of patterns (the parser | |
229 | used in the grammar of the {\tt match} {\tt with} constructions). | |
222 | 230 | |
223 | 231 | \subsection{Displaying symbolic notations} |
224 | 232 | |
435 | 443 | \SeeAlso Section \ref{Locate}. |
436 | 444 | |
437 | 445 | \begin{figure} |
446 | \begin{small} | |
438 | 447 | \begin{centerframe} |
439 | 448 | \begin{tabular}{lcl} |
440 | {\sentence} & ::= & | |
449 | {\sentence} & ::= & | |
441 | 450 | \texttt{Notation} \zeroone{\tt Local} {\str} \texttt{:=} {\term} |
442 | 451 | \zeroone{\modifiers} \zeroone{:{\scope}} .\\ |
443 | 452 | & $|$ & |
473 | 482 | & $|$ & {\tt format} {\str} |
474 | 483 | \end{tabular} |
475 | 484 | \end{centerframe} |
485 | \end{small} | |
476 | 486 | \caption{Syntax of the variants of {\tt Notation}} |
477 | 487 | \label{notation-syntax} |
478 | 488 | \end{figure} |
632 | 642 | definitions of an additive operator. Depending on which interpretation |
633 | 643 | scopes is currently open, the interpretation is different. |
634 | 644 | Interpretation scopes can include an interpretation for |
635 | numerals. However, this is only made possible at the {\ocaml} level. | |
645 | numerals and strings. However, this is only made possible at the | |
646 | {\ocaml} level. | |
636 | 647 | |
637 | 648 | See Figure \ref{notation-syntax} for the syntax of notations including |
638 | 649 | the possibility to declare them in a given scope. Here is a typical |
823 | 834 | delimited by key {\tt positive} and comes with an interpretation for |
824 | 835 | numerals as closed term of type {\tt positive}. |
825 | 836 | |
837 | \subsubsection{\tt Q\_scope} | |
838 | ||
839 | This includes the standard arithmetical operators and relations on | |
840 | type {\tt Q} (rational numbers defined as fractions of an integer and | |
841 | a strictly positive integer modulo the equality of the | |
842 | numerator-denominator cross-product). As for numerals, only $0$ and | |
843 | $1$ have an interpretation in scope {\tt Q\_scope} (their | |
844 | interpretations are $\frac{0}{1}$ and $\frac{1}{1}$ respectively). | |
845 | ||
846 | \subsubsection{\tt Qc\_scope} | |
847 | ||
848 | This includes the standard arithmetical operators and relations on the | |
849 | type {\tt Qc} of rational numbers defined as the type of irreducible | |
850 | fractions of an integer and a strictly positive integer. | |
851 | ||
826 | 852 | \subsubsection{\tt real\_scope} |
827 | 853 | |
828 | 854 | This includes the standard arithmetical operators and relations on |
852 | 878 | |
853 | 879 | This includes the notation for pairs. It is delimited by key {\tt core}. |
854 | 880 | |
881 | \subsubsection{\tt string\_scope} | |
882 | ||
883 | This includes notation for strings as elements of the type {\tt | |
884 | string}. Special characters and escaping follow {\Coq} conventions | |
885 | on strings (see page~\pageref{strings}). Especially, there is no | |
886 | convention to visualize non printable characters of a string. The | |
887 | file {\tt String.v} shows an example that contains quotes, a newline | |
888 | and a beep (i.e. the ascii character of code 7). | |
889 | ||
890 | \subsubsection{\tt char\_scope} | |
891 | ||
892 | This includes interpretation for all strings of the form | |
893 | \verb!"!$c$\verb!"! where $c$ is an ascii character, or of the form | |
894 | \verb!"!$nnn$\verb!"! where $nnn$ is a three-digits number (possibly | |
895 | with leading 0's), or of the form \verb!""""!. Their respective | |
896 | denotations are the ascii code of $c$, the decimal ascii code $nnn$, | |
897 | or the ascii code of the character \verb!"! (i.e. the ascii code | |
898 | 34), all of them being represented in the type {\tt ascii}. | |
899 | ||
855 | 900 | \subsection{Displaying informations about scopes} |
856 | 901 | |
857 | 902 | \subsubsection{\tt Print Visibility} |
947 | 992 | the {\tt Grammar tactic simple\_tactic} command that existed in |
948 | 993 | versions prior to version 8.0.}. Tactic notations obey the following |
949 | 994 | syntax |
950 | ||
995 | \medskip | |
996 | ||
997 | \noindent | |
951 | 998 | \begin{tabular}{lcl} |
952 | {\sentence} & ::= & \texttt{Tactic Notation} {\str} \sequence{\proditem}{} \\ | |
999 | {\sentence} & ::= & \texttt{Tactic Notation} {\taclevel} \sequence{\proditem}{} \\ | |
953 | 1000 | & & \texttt{:= {\tac} .}\\ |
954 | 1001 | {\proditem} & ::= & {\str} $|$ {\tacargtype}{\tt ({\ident})} \\ |
1002 | {\taclevel} & ::= & $|$ {\tt (at level} {\naturalnumber}{\tt )} \\ | |
955 | 1003 | {\tacargtype} & ::= & |
956 | 1004 | %{\tt preident} $|$ |
957 | 1005 | {\tt ident} $|$ |
965 | 1013 | {\tt int\_or\_var} $|$ |
966 | 1014 | {\tt tactic} $|$ |
967 | 1015 | \end{tabular} |
968 | ||
969 | A tactic notation {\tt Tactic Notation {\str} {\sequence{\proditem}{}} | |
970 | := {\tac}} extends the parser and pretty-printer of tactics with a | |
971 | new rule made of the juxtaposition of the head name of the tactic | |
972 | {\str} and the list of its production items (in the syntax of | |
973 | production items, {\str} stands for a terminal symbol and {\tt | |
974 | \tacargtype({\ident}) for non terminal entries}. It then evaluates | |
975 | into the tactic expression {\tac}. | |
1016 | \medskip | |
1017 | ||
1018 | A tactic notation {\tt Tactic Notation {\taclevel} | |
1019 | {\sequence{\proditem}{}} := {\tac}} extends the parser and | |
1020 | pretty-printer of tactics with a new rule made of the list of | |
1021 | production items. It then evaluates into the tactic expression | |
1022 | {\tac}. For simple tactics, it is recommended to use a terminal | |
1023 | symbol, i.e. a {\str}, for the first production item. The tactic | |
1024 | level indicates the parsing precedence of the tactic notation. This | |
1025 | information is particularly relevant for notations of tacticals. | |
1026 | Levels 0 to 5 are available. To know the parsing precedences of the | |
1027 | existing tacticals, use the command {\tt Print Grammar tactic.} | |
976 | 1028 | |
977 | 1029 | Each type of tactic argument has a specific semantic regarding how it |
978 | 1030 | is parsed and how it is interpreted. The semantic is described in the |
1007 | 1059 | syntactically includes identifiers in order to be usable in tactic |
1008 | 1060 | definitions. |
1009 | 1061 | |
1010 | % $Id: RefMan-syn.tex 8609 2006-02-24 13:32:57Z notin,no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty $ | |
1062 | % $Id: RefMan-syn.tex 9012 2006-07-05 16:03:16Z herbelin $ | |
1011 | 1063 | |
1012 | 1064 | %%% Local Variables: |
1013 | 1065 | %%% mode: latex |
68 | 68 | \item \errindex{Not an exact proof} |
69 | 69 | \end{ErrMsgs} |
70 | 70 | |
71 | \begin{Variants} | |
72 | \item \texttt{eexact \term}\tacindex{eexact} | |
73 | ||
74 | This tactic behaves like \texttt{exact} but is able to handle terms with meta-variables. | |
75 | ||
76 | \end{Variants} | |
77 | ||
71 | 78 | |
72 | 79 | \subsection{\tt refine \term |
73 | 80 | \tacindex{refine} |
111 | 118 | \item \errindex{No such assumption} |
112 | 119 | \end{ErrMsgs} |
113 | 120 | |
121 | \begin{Variants} | |
122 | \item \texttt{eassumption} | |
123 | ||
124 | This tactic behaves like \texttt{assumption} but is able to handle | |
125 | goals with meta-variables. | |
126 | ||
127 | \end{Variants} | |
128 | ||
129 | ||
114 | 130 | \subsection{\tt clear {\ident} |
115 | 131 | \tacindex{clear} |
116 | 132 | \label{clear}} |
131 | 147 | This tactic expects {\ident} to be a local definition then clears |
132 | 148 | its body. Otherwise said, this tactic turns a definition into an |
133 | 149 | assumption. |
150 | ||
151 | \item \texttt{clear - {\ident}.} | |
152 | ||
153 | This tactic clears all hypotheses except the ones depending in {\ident}. | |
134 | 154 | |
135 | 155 | \end{Variants} |
136 | 156 | |
504 | 524 | {\tt cut U} transforms the current goal \texttt{T} into the two |
505 | 525 | following subgoals: {\tt U -> T} and \texttt{U}. The subgoal {\tt U |
506 | 526 | -> T} comes first in the list of remaining subgoal to prove. |
527 | ||
528 | \item \texttt{assert {\form} by {\tac}}\tacindex{assert by} | |
529 | ||
530 | This tactic behaves like \texttt{assert} but tries to apply {\tac} | |
531 | to any subgoals generated by \texttt{assert}. | |
532 | ||
533 | \item \texttt{assert {\form} as {\ident}\tacindex{assert as}} | |
534 | ||
535 | This tactic behaves like \texttt{assert ({\ident} : {\form})}. | |
536 | ||
537 | \item \texttt{pose proof {\term} as {\ident}} | |
538 | ||
539 | This tactic behaves like \texttt{assert ({\ident:T} by exact {\term}} where | |
540 | \texttt{T} is the type of {\term}. | |
507 | 541 | |
508 | 542 | \end{Variants} |
509 | 543 | |
720 | 754 | \tacindex{cbv} |
721 | 755 | \tacindex{lazy} |
722 | 756 | \tacindex{compute}} |
757 | \label{vmcompute} | |
723 | 758 | |
724 | 759 | These parameterized reduction tactics apply to any goal and perform |
725 | 760 | the normalization of the goal according to the specified flags. Since |
763 | 798 | \item {\tt compute} \tacindex{compute} |
764 | 799 | |
765 | 800 | This tactic is an alias for {\tt cbv beta delta evar iota zeta}. |
801 | ||
802 | \item {\tt vm\_compute} \tacindex{vm\_compute} | |
803 | ||
804 | This tactic evaluates the goal using the optimized call-by-value | |
805 | evaluation bytecode-based virtual machine. This algorithm is | |
806 | dramatically more efficient than the algorithm used for the {\tt | |
807 | cbv} tactic, but it cannot be fine-tuned. It is specially | |
808 | interesting for full evaluation of algebraic objects. This includes | |
809 | the case of reflexion-based tactics. | |
810 | ||
766 | 811 | \end{Variants} |
767 | 812 | |
768 | 813 | \begin{ErrMsgs} |
1010 | 1055 | As soon as the inductive type has the right number of constructors, |
1011 | 1056 | these expressions are equivalent to the corresponding {\tt |
1012 | 1057 | constructor $i$ with \bindinglist}. |
1058 | ||
1059 | \item \texttt{econstructor} | |
1060 | ||
1061 | This tactic behaves like \texttt{constructor} but is able to | |
1062 | introduce existential variables if an instanciation for a variable | |
1063 | cannot be found (cf \texttt{eapply}). The tactics \texttt{eexists}, | |
1064 | \texttt{esplit}, \texttt{eleft} and \texttt{eright} follows the same | |
1065 | behaviour. | |
1013 | 1066 | |
1014 | 1067 | \end{Variants} |
1015 | 1068 | |
1095 | 1148 | scheme of name {\qualid}. It does not expect that the type of |
1096 | 1149 | {\term} is inductive. |
1097 | 1150 | |
1151 | \item \texttt{induction {\term}$_1$ $\ldots$ {\term}$_n$ using {\qualid}} | |
1152 | ||
1153 | where {\qualid} is an induction principle with complex predicates | |
1154 | (like the ones generated by function induction). | |
1155 | ||
1098 | 1156 | \item {\tt induction {\term} using {\qualid} as {\intropattern}} |
1099 | 1157 | |
1100 | 1158 | This combines {\tt induction {\term} using {\qualid}} |
1232 | 1290 | {\tt ($p_{1}$,\ldots,$p_{n}$)} can be used instead of |
1233 | 1291 | {\tt [} $p_{1} $\ldots $p_{n}$ {\tt ]}. |
1234 | 1292 | |
1293 | \item \texttt{pose proof {\term} as {\intropattern}} | |
1294 | ||
1295 | This tactic behaves like \texttt{destruct {\term} as {\intropattern}}. | |
1296 | ||
1235 | 1297 | \item{\tt destruct {\term} using {\qualid}} |
1236 | 1298 | |
1237 | 1299 | This is a synonym of {\tt induction {\term} using {\qualid}}. |
1278 | 1340 | An introduction pattern is either: |
1279 | 1341 | \begin{itemize} |
1280 | 1342 | \item the wildcard: {\tt \_} |
1343 | \item the pattern \texttt{?} | |
1281 | 1344 | \item a variable |
1282 | 1345 | \item a disjunction of lists of patterns: |
1283 | 1346 | {\tt [$p_{11}$ {\ldots} $p_{1m_1}$ | {\ldots} | $p_{11}$ {\ldots} $p_{nm_n}$]} |
1289 | 1352 | \begin{itemize} |
1290 | 1353 | \item introduction on the wildcard do the introduction and then |
1291 | 1354 | immediately clear (cf~\ref{clear}) the corresponding hypothesis; |
1355 | \item introduction on \texttt{?} do the introduction, and let Coq | |
1356 | choose a fresh name for the variable; | |
1292 | 1357 | \item introduction on a variable behaves like described in~\ref{intro}; |
1293 | 1358 | \item introduction over a |
1294 | 1359 | list of patterns $p_1~\ldots~p_n$ is equivalent to the sequence of |
1322 | 1387 | Lemma intros_test : forall A B C:Prop, A \/ B /\ C -> (A -> C) -> C. |
1323 | 1388 | intros A B C [a| [_ c]] f. |
1324 | 1389 | apply (f a). |
1325 | Proof c. | |
1390 | exact c. | |
1391 | Qed. | |
1326 | 1392 | \end{coq_example} |
1327 | 1393 | |
1328 | 1394 | %\subsection{\tt FixPoint \dots}\tacindex{Fixpoint} |
1478 | 1544 | This tactic applies to any goal. The type of {\term} |
1479 | 1545 | must have the form |
1480 | 1546 | |
1481 | \texttt{(x$_1$:A$_1$) \dots\ (x$_n$:A$_n$)}\term$_1${\tt =}\term$_2$. | |
1547 | \texttt{(x$_1$:A$_1$) \dots\ (x$_n$:A$_n$)}\texttt{eq}\term$_1$ \term$_2$. | |
1548 | ||
1549 | \noindent where \texttt{eq} is the Leibniz equality or a registered | |
1550 | setoid equality. | |
1482 | 1551 | |
1483 | 1552 | \noindent Then {\tt rewrite \term} replaces every occurrence of |
1484 | 1553 | \term$_1$ by \term$_2$ in the goal. Some of the variables x$_1$ are |
1505 | 1574 | \item {\tt rewrite <- {\term}}\tacindex{rewrite <-}\\ |
1506 | 1575 | Uses the equality \term$_1${\tt=}\term$_2$ from right to left |
1507 | 1576 | |
1508 | \item {\tt rewrite {\term} in {\ident}} | |
1577 | \item {\tt rewrite {\term} in \textit{clause}} | |
1509 | 1578 | \tacindex{rewrite \dots\ in}\\ |
1510 | Analogous to {\tt rewrite {\term}} but rewriting is done in the | |
1511 | hypothesis named {\ident}. | |
1579 | Analogous to {\tt rewrite {\term}} but rewriting is done following | |
1580 | \textit{clause} (similarly to \ref{Conversion-tactics}). For instance: | |
1581 | \texttt{rewrite H in H1,H2 |- *} means \texttt{rewrite H in H1; | |
1582 | rewrite H in H2; rewrite H} and \texttt{rewrite H in * |-} will do | |
1583 | \texttt{try rewrite H in H$_i$} for all hypothesis \texttt{H$_i$ <> | |
1584 | H}. | |
1512 | 1585 | |
1513 | 1586 | \item {\tt rewrite -> {\term} in {\ident}} |
1514 | 1587 | \tacindex{rewrite -> \dots\ in}\\ |
1539 | 1612 | \term$_2$=\term$_1$; [intro H{\sl n}; rewrite <- H{\sl n}; clear H{\sl |
1540 | 1613 | n}| assumption || symmetry; try assumption]}. |
1541 | 1614 | |
1615 | \begin{ErrMsgs} | |
1616 | \item \errindex{terms do not have convertible types} | |
1617 | \end{ErrMsgs} | |
1618 | ||
1542 | 1619 | \begin{Variants} |
1543 | 1620 | |
1544 | 1621 | \item {\tt replace {\term$_1$} with {\term$_2$} in \ident}\\ |
1545 | 1622 | This replaces {\term$_1$} with {\term$_2$} in the hypothesis named |
1546 | 1623 | {\ident}, and generates the subgoal {\term$_2$}{\tt =}{\term$_1$}. |
1547 | 1624 | |
1548 | \begin{ErrMsgs} | |
1549 | \item \errindex{No such hypothesis} : {\ident} | |
1550 | \item \errindex{Nothing to rewrite in {\ident}} | |
1551 | \end{ErrMsgs} | |
1552 | ||
1625 | % \begin{ErrMsgs} | |
1626 | % \item \errindex{No such hypothesis} : {\ident} | |
1627 | % \item \errindex{Nothing to rewrite in {\ident}} | |
1628 | % \end{ErrMsgs} | |
1629 | ||
1630 | \item {\tt replace {\term$_1$} with {\term$_2$} by \tac}\\ This acts as | |
1631 | {\tt replace {\term$_1$} with {\term$_2$}} but try to solve the | |
1632 | generated subgoal {\tt \term$_2$=\term$_1$} using {\tt \tac}. | |
1633 | \item {\tt replace {\term$_1$} with {\term$_2$} in \ident by \tac}\\ | |
1634 | This acts as {\tt replace {\term$_1$} with {\term$_2$} in \ident} but try to solve the generated subgoal {\tt \term$_2$=\term$_1$} using {\tt \tac}. | |
1553 | 1635 | \end{Variants} |
1554 | 1636 | |
1555 | 1637 | \subsection{\tt reflexivity |
1616 | 1698 | Lemmas are added to the database using the command |
1617 | 1699 | \comindex{Declare Left Step} |
1618 | 1700 | \begin{quote} |
1619 | {\tt Declare Left Step {\qualid}.} | |
1701 | {\tt Declare Left Step {\term}.} | |
1620 | 1702 | \end{quote} |
1621 | where {\qualid} is the name of the lemma. | |
1622 | 1703 | |
1623 | 1704 | The tactic is especially useful for parametric setoids which are not |
1624 | accepted as regular setoids for {\tt rewrite} and {\tt setoid\_replace} (see chapter \ref{setoid_replace}). | |
1705 | accepted as regular setoids for {\tt rewrite} and {\tt | |
1706 | setoid\_replace} (see chapter \ref{setoid_replace}). | |
1625 | 1707 | |
1626 | 1708 | \tacindex{stepr} |
1627 | 1709 | \comindex{Declare Right Step} |
1637 | 1719 | $z$, $R$ $x$ $y$ {\tt ->} $eq$ $y$ $z$ {\tt ->} $R$ $x$ $z$'' |
1638 | 1720 | and are registered using the command |
1639 | 1721 | \begin{quote} |
1640 | {\tt Declare Right Step {\qualid}.} | |
1722 | {\tt Declare Right Step {\term}.} | |
1641 | 1723 | \end{quote} |
1642 | 1724 | \end{Variants} |
1643 | 1725 | |
2156 | 2238 | Uses all existing hint databases, minus the special database |
2157 | 2239 | {\tt v62}. See Section~\ref{Hints-databases} |
2158 | 2240 | |
2241 | \item \texttt{auto using $lemma_1, \ldots, lemma_n$} | |
2242 | ||
2243 | Uses $lemma_1, \ldots, lemma_n$ in addition to hints (can be conbined | |
2244 | with the \texttt{with \ident} option). | |
2245 | ||
2159 | 2246 | \item {\tt trivial}\tacindex{trivial} |
2160 | 2247 | |
2161 | 2248 | This tactic is a restriction of {\tt auto} that is not recursive and |
2305 | 2392 | % En attente d'un moyen de valoriser les fichiers de demos |
2306 | 2393 | %\SeeAlso file \texttt{contrib/Rocq/DEMOS/Demo\_tauto.v} |
2307 | 2394 | |
2395 | ||
2396 | \subsection{\tt rtauto | |
2397 | \tacindex{rtauto} | |
2398 | \label{rtauto}} | |
2399 | ||
2400 | The {\tt rtauto} tactic solves propositional tautologies similarly to what {\tt tauto} does. The main difference is that the proof term is built using a reflection scheme applied to a sequent calculus proof of the goal. The search procedure is also implemented using a different technique. | |
2401 | ||
2402 | Users should be aware that this difference may result in faster proof-search but slower proof-checking, and {\tt rtauto} might not solve goals that {\tt tauto} would be able to solve (e.g. goals involving universal quantifiers). | |
2403 | ||
2308 | 2404 | \subsection{{\tt firstorder} |
2309 | 2405 | \tacindex{firstorder} |
2310 | 2406 | \label{firstorder}} |
2458 | 2554 | (see \ref{injection} and \ref{discriminate}). |
2459 | 2555 | If the goal is a non-quantified equality, {\tt congruence} tries to |
2460 | 2556 | prove it with non-quantified equalities in the context. Otherwise it |
2461 | tries to infer a discriminable equality from those in the context. | |
2557 | tries to infer a discriminable equality from those in the context. Alternatively, congruence tries to prove that an hypothesis is equal to the goal or to the negation of another hypothesis. | |
2462 | 2558 | |
2463 | 2559 | \begin{coq_eval} |
2464 | 2560 | Reset Initial. |
2488 | 2584 | congruence. |
2489 | 2585 | \end{coq_example} |
2490 | 2586 | |
2587 | \begin{Variants} | |
2588 | \item {\tt congruence with \term$_1$ \dots\ \term$_n$}\\ | |
2589 | Adds {\tt \term$_1$ \dots\ \term$_n$} to the pool of terms used by | |
2590 | {\tt congruence}. This helps in case you have partially applied | |
2591 | constructors in your goal. | |
2592 | \end{Variants} | |
2593 | ||
2491 | 2594 | \begin{ErrMsgs} |
2492 | 2595 | \item \errindex{I don't know how to handle dependent equality} \\ |
2493 | 2596 | The decision procedure managed to find a proof of the goal or of |
2494 | 2597 | a discriminable equality but this proof couldn't be built in Coq |
2495 | 2598 | because of dependently-typed functions. |
2496 | 2599 | \item \errindex{I couldn't solve goal} \\ |
2497 | The decision procedure didn't managed to find a proof of the goal or of | |
2498 | a discriminable equality. | |
2600 | The decision procedure didn't find any way to solve the goal. | |
2601 | \item \errindex{Goal is solvable by congruence but some arguments are missing. Try "congruence with \dots", replacing metavariables by arbitrary terms.} \\ | |
2602 | The decision procedure could solve the goal with the provision | |
2603 | that additional arguments are supplied for some partially applied | |
2604 | constructors. Any term of an appropriate type will allow the | |
2605 | tactic to successfully solve the goal. Those additional arguments | |
2606 | can be given to {\tt congruence} by filling in the holes in the | |
2607 | terms given in the error message, using the {\tt with} variant | |
2608 | described below. | |
2499 | 2609 | \end{ErrMsgs} |
2500 | 2610 | |
2501 | 2611 | \subsection{\tt omega |
2678 | 2788 | to get a very compact and readable version.} carries out rewritings according |
2679 | 2789 | the rewriting rule bases {\tt \ident$_1$ \dots \ident$_n$}. |
2680 | 2790 | |
2681 | Each rewriting rule of a base \ident$_i$ is applied to the main subgoal until | |
2791 | Each rewriting rule of a base \ident$_i$ is applied to the main subgoal until | |
2682 | 2792 | it fails. Once all the rules have been processed, if the main subgoal has |
2683 | 2793 | progressed (e.g., if it is distinct from the initial main goal) then the rules |
2684 | 2794 | of this base are processed again. If the main subgoal has not progressed then |
2694 | 2804 | \item {\tt autorewrite with \ident$_1$ \dots \ident$_n$ using \tac}\\ |
2695 | 2805 | Performs, in the same way, all the rewritings of the bases {\tt $ident_1$ $...$ |
2696 | 2806 | $ident_n$} applying {\tt \tac} to the main subgoal after each rewriting step. |
2697 | %\item{\tt autorewrite [ \ident$_1$ \dots \ident$_n$ ]}\\ | |
2698 | %{\tt autorewrite [ \ident$_1$ \dots \ident$_n$ ] using \tac}\\ | |
2699 | %These are deprecated syntactic variants for | |
2700 | %{\tt autorewrite with \ident$_1$ \dots \ident$_n$} | |
2701 | %and | |
2702 | %{\tt autorewrite with \ident$_1$ \dots \ident$_n$ using \tac}. | |
2807 | ||
2808 | \item \texttt{autorewrite with {\ident} in {\qualid}} | |
2809 | ||
2810 | Performs all the rewritings in hypothesis {\qualid}. | |
2811 | ||
2703 | 2812 | \end{Variant} |
2704 | 2813 | |
2705 | \subsection{\tt Hint Rewrite \term$_1$ \dots \term$_n$ : \ident | |
2706 | \comindex{Hint Rewrite}} | |
2707 | ||
2708 | This vernacular command adds the terms {\tt \term$_1$ \dots \term$_n$} | |
2709 | (their types must be equalities) in the rewriting base {\tt \ident} | |
2710 | with the default orientation (left to right). Notice that the | |
2711 | rewriting bases are distinct from the {\tt auto} hint bases and that | |
2712 | {\tt auto} does not take them into account. | |
2713 | ||
2714 | This command is synchronous with the section mechanism (see \ref{Section}): | |
2715 | when closing a section, all aliases created by \texttt{Hint Rewrite} in that | |
2716 | section are lost. Conversely, when loading a module, all \texttt{Hint Rewrite} | |
2717 | declarations at the global level of that module are loaded. | |
2718 | ||
2719 | \begin{Variants} | |
2720 | \item {\tt Hint Rewrite -> \term$_1$ \dots \term$_n$ : \ident}\\ | |
2721 | This is strictly equivalent to the command above (we only make explicit the | |
2722 | orientation which otherwise defaults to {\tt ->}). | |
2723 | ||
2724 | \item {\tt Hint Rewrite <- \term$_1$ \dots \term$_n$ : \ident}\\ | |
2725 | Adds the rewriting rules {\tt \term$_1$ \dots \term$_n$} with a right-to-left | |
2726 | orientation in the base {\tt \ident}. | |
2727 | ||
2728 | \item {\tt Hint Rewrite \term$_1$ \dots \term$_n$ using {\tac} : {\ident}}\\ | |
2729 | When the rewriting rules {\tt \term$_1$ \dots \term$_n$} in {\tt \ident} will | |
2730 | be used, the tactic {\tt \tac} will be applied to the generated subgoals, the | |
2731 | main subgoal excluded. | |
2732 | ||
2733 | %% \item | |
2734 | %% {\tt Hint Rewrite [ \term$_1$ \dots \term$_n$ ] in \ident}\\ | |
2735 | %% {\tt Hint Rewrite [ \term$_1$ \dots \term$_n$ ] in {\ident} using {\tac}}\\ | |
2736 | %% These are deprecated syntactic variants for | |
2737 | %% {\tt Hint Rewrite \term$_1$ \dots \term$_n$ : \ident} and | |
2738 | %% {\tt Hint Rewrite \term$_1$ \dots \term$_n$ using {\tac} : {\ident}}. | |
2739 | ||
2740 | \end{Variants} | |
2741 | ||
2742 | \SeeAlso \ref{autorewrite-example} for examples showing the use of | |
2814 | \SeeAlso section \ref{HintRewrite} for feeding the database of lemmas used by {\tt autorewrite}. | |
2815 | ||
2816 | \SeeAlso section \ref{autorewrite-example} for examples showing the use of | |
2743 | 2817 | this tactic. |
2744 | 2818 | |
2745 | 2819 | % En attente d'un moyen de valoriser les fichiers de demos |
2746 | 2820 | %\SeeAlso file \texttt{contrib/Rocq/DEMOS/Demo\_AutoRewrite.v} |
2747 | 2821 | |
2748 | \section{The hints databases for {\tt auto} and {\tt eauto} | |
2822 | \section{Controlling automation} | |
2823 | ||
2824 | \subsection{The hints databases for {\tt auto} and {\tt eauto} | |
2749 | 2825 | \index{Hints databases} |
2750 | 2826 | \label{Hints-databases} |
2751 | 2827 | \comindex{Hint}} |
3035 | 3111 | |
3036 | 3112 | \end{Variants} |
3037 | 3113 | |
3114 | \subsection{\tt Hint Rewrite \term$_1$ \dots \term$_n$ : \ident | |
3115 | \label{HintRewrite} | |
3116 | \comindex{Hint Rewrite}} | |
3117 | ||
3118 | This vernacular command adds the terms {\tt \term$_1$ \dots \term$_n$} | |
3119 | (their types must be equalities) in the rewriting base {\tt \ident} | |
3120 | with the default orientation (left to right). Notice that the | |
3121 | rewriting bases are distinct from the {\tt auto} hint bases and that | |
3122 | {\tt auto} does not take them into account. | |
3123 | ||
3124 | This command is synchronous with the section mechanism (see \ref{Section}): | |
3125 | when closing a section, all aliases created by \texttt{Hint Rewrite} in that | |
3126 | section are lost. Conversely, when loading a module, all \texttt{Hint Rewrite} | |
3127 | declarations at the global level of that module are loaded. | |
3128 | ||
3129 | \begin{Variants} | |
3130 | \item {\tt Hint Rewrite -> \term$_1$ \dots \term$_n$ : \ident}\\ | |
3131 | This is strictly equivalent to the command above (we only make explicit the | |
3132 | orientation which otherwise defaults to {\tt ->}). | |
3133 | ||
3134 | \item {\tt Hint Rewrite <- \term$_1$ \dots \term$_n$ : \ident}\\ | |
3135 | Adds the rewriting rules {\tt \term$_1$ \dots \term$_n$} with a right-to-left | |
3136 | orientation in the base {\tt \ident}. | |
3137 | ||
3138 | \item {\tt Hint Rewrite \term$_1$ \dots \term$_n$ using {\tac} : {\ident}}\\ | |
3139 | When the rewriting rules {\tt \term$_1$ \dots \term$_n$} in {\tt \ident} will | |
3140 | be used, the tactic {\tt \tac} will be applied to the generated subgoals, the | |
3141 | main subgoal excluded. | |
3142 | ||
3143 | %% \item | |
3144 | %% {\tt Hint Rewrite [ \term$_1$ \dots \term$_n$ ] in \ident}\\ | |
3145 | %% {\tt Hint Rewrite [ \term$_1$ \dots \term$_n$ ] in {\ident} using {\tac}}\\ | |
3146 | %% These are deprecated syntactic variants for | |
3147 | %% {\tt Hint Rewrite \term$_1$ \dots \term$_n$ : \ident} and | |
3148 | %% {\tt Hint Rewrite \term$_1$ \dots \term$_n$ using {\tac} : {\ident}}. | |
3149 | ||
3150 | \item \texttt{Print Rewrite HintDb {\ident}} | |
3151 | ||
3152 | This command displays all rewrite hints contained in {\ident}. | |
3153 | ||
3154 | \end{Variants} | |
3038 | 3155 | |
3039 | 3156 | \subsection{Hints and sections |
3040 | 3157 | \label{Hint-and-Section}} |
3044 | 3161 | defined inside a section (and not defined with option {\tt Local}) become |
3045 | 3162 | available when the module {\tt A} is imported (using |
3046 | 3163 | e.g. \texttt{Require Import A.}). |
3164 | ||
3165 | \subsection{Setting implicit automation tactics} | |
3166 | ||
3167 | \subsubsection{\tt Proof with {\tac}.} | |
3168 | \label{ProofWith} | |
3169 | \comindex{Proof with} | |
3170 | ||
3171 | This command may be used to start a proof. It defines a default | |
3172 | tactic to be used each time a tactic command {\tac$_1$} is ended by | |
3173 | ``\verb#...#''. In this case the tactic command typed by the user is | |
3174 | equivalent to \tac$_1$;{\tac}. | |
3175 | ||
3176 | \SeeAlso {\tt Proof.} in section~\ref{BeginProof}. | |
3177 | ||
3178 | \subsubsection{\tt Declare Implicit Tactic {\tac}.} | |
3179 | \comindex{Declare Implicit Tactic} | |
3180 | ||
3181 | This command declares a tactic to be used to solve implicit arguments | |
3182 | that {\Coq} does not know how to solve by unification. It is used | |
3183 | every time the term argument of a tactic has one of its holes not | |
3184 | fully resolved. | |
3185 | ||
3186 | Here is an example: | |
3187 | ||
3188 | \begin{coq_example} | |
3189 | Parameter quo : nat -> forall n:nat, n<>0 -> nat. | |
3190 | Notation "x // y" := (quo x y _) (at level 40). | |
3191 | ||
3192 | Declare Implicit Tactic assumption. | |
3193 | Goal forall n m, m<>0 -> { q:nat & { r | q * m + r = n } }. | |
3194 | intros. | |
3195 | exists (n // m). | |
3196 | \end{coq_example} | |
3197 | ||
3198 | The tactic {\tt exists (n // m)} did not fail. The hole was solved by | |
3199 | {\tt assumption} so that it behaved as {\tt exists (quo n m H)}. | |
3047 | 3200 | |
3048 | 3201 | \section{Generation of induction principles with {\tt Scheme} |
3049 | 3202 | \label{Scheme} |
3138 | 3291 | user-defined tactics. |
3139 | 3292 | |
3140 | 3293 | |
3141 | % $Id: RefMan-tac.tex 8938 2006-06-09 16:29:01Z jnarboux $ | |
3294 | % $Id: RefMan-tac.tex 9044 2006-07-12 13:22:17Z herbelin $ | |
3142 | 3295 | |
3143 | 3296 | %%% Local Variables: |
3144 | 3297 | %%% mode: latex |
67 | 67 | \include{RefMan-oth.v}% Vernacular commands |
68 | 68 | \include{RefMan-pro}% Proof handling |
69 | 69 | \include{RefMan-tac.v}% Tactics and tacticals |
70 | \include{RefMan-ltac}% Writing tactics | |
70 | \include{RefMan-ltac.v}% Writing tactics | |
71 | 71 | \include{RefMan-tacex.v}% Detailed Examples of tactics |
72 | 72 | |
73 | 73 | \part{User extensions} |
121 | 121 | \end{document} |
122 | 122 | |
123 | 123 | |
124 | % $Id: Reference-Manual.tex 8688 2006-04-07 15:08:12Z msozeau $ | |
124 | % $Id: Reference-Manual.tex 9038 2006-07-11 13:53:53Z herbelin $ |
12 | 12 | The Coq Proof Assistant<BR> |
13 | 13 | Reference Manual<BR></B></FONT><FONT SIZE=7> |
14 | 14 | </FONT> |
15 | <BR><BR><FONT SIZE=5><B><BR></B></FONT><FONT SIZE=5><B>Version 8.0</B></FONT><FONT SIZE=5><B> | |
15 | <BR><BR><FONT SIZE=5><B><BR></B></FONT><FONT SIZE=5><B>Version 8.1</B></FONT><FONT SIZE=5><B> | |
16 | 16 | </B></FONT><A NAME="text1"></A><A HREF="#note1"><SUP><FONT SIZE=2>1</FONT></SUP></A><FONT SIZE=5><B><BR><BR><BR><BR><BR><BR> |
17 | 17 | </B></FONT><FONT SIZE=5><B>The Coq Development Team</B></FONT><FONT SIZE=5><B><BR></B></FONT><FONT SIZE=5><B>LogiCal Project</B></FONT><FONT SIZE=5><B><BR><BR><BR> |
18 | 18 | </B></FONT></DIV><BR> |
21 | 21 | <DIV ALIGN=left> |
22 | 22 | <FONT SIZE=4>V7.x © INRIA 1999-2004</FONT><BR> |
23 | 23 | <FONT SIZE=4>V8.0 © INRIA 2004-2006</FONT><BR> |
24 | <FONT SIZE=4>V8.1 © INRIA 2006</FONT><BR> | |
24 | 25 | This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at <A HREF="http://www.opencontent.org/openpub">http://www.opencontent.org/openpub</A>). Options A and B are not elected. |
25 | 26 | </DIV> |
26 | 27 | <BR> |
0 | 0 | <HTML> |
1 | 1 | |
2 | <BODY> | |
2 | <HEAD> | |
3 | 3 | |
4 | <CENTER> | |
4 | <TITLE>The Coq Proof Assistant Reference Manual</TITLE> | |
5 | 5 | |
6 | <TABLE BORDER="0" CELLPADDING=10> | |
7 | <TR> | |
8 | <TD><CENTER><A HREF="cover.html" TARGET="UP"><FONT SIZE=2>Cover page</FONT></A></CENTER></TD> | |
9 | <TD><CENTER><A HREF="toc.html" TARGET="UP"><FONT SIZE=2>Table of contents</FONT></A></CENTER></TD> | |
10 | <TD><CENTER><A HREF="biblio.html" TARGET="UP"><FONT SIZE=2> | |
11 | Bibliography</FONT></A></CENTER></TD> | |
12 | <TD><CENTER><A HREF="general-index.html" TARGET="UP"><FONT SIZE=2> | |
13 | Global Index | |
14 | </FONT></A></CENTER></TD> | |
15 | <TD><CENTER><A HREF="tactic-index.html" TARGET="UP"><FONT SIZE=2> | |
16 | Tactics Index | |
17 | </FONT></A></CENTER></TD> | |
18 | <TD><CENTER><A HREF="command-index.html" TARGET="UP"><FONT SIZE=2> | |
19 | Vernacular Commands Index | |
20 | </FONT></A></CENTER></TD> | |
21 | <TD><CENTER><A HREF="error-index.html" TARGET="UP"><FONT SIZE=2> | |
22 | Index of Error Messages | |
23 | </FONT></A></CENTER></TD> | |
24 | </TABLE> | |
6 | </HEAD> | |
25 | 7 | |
26 | </CENTER> | |
8 | <FRAMESET ROWS=90%,*> | |
9 | <FRAME SRC="cover.html" NAME="UP"> | |
10 | <FRAME SRC="menu.html"> | |
11 | </FRAMESET> | |
27 | 12 | |
28 | </BODY></HTML>⏎ | |
13 | </HTML>⏎ |
0 | <HTML> | |
1 | ||
2 | <BODY> | |
3 | ||
4 | <CENTER> | |
5 | ||
6 | <TABLE BORDER="0" CELLPADDING=10> | |
7 | <TR> | |
8 | <TD><CENTER><A HREF="cover.html" TARGET="UP"><FONT SIZE=2>Cover page</FONT></A></CENTER></TD> | |
9 | <TD><CENTER><A HREF="toc.html" TARGET="UP"><FONT SIZE=2>Table of contents</FONT></A></CENTER></TD> | |
10 | <TD><CENTER><A HREF="biblio.html" TARGET="UP"><FONT SIZE=2> | |
11 | Bibliography</FONT></A></CENTER></TD> | |
12 | <TD><CENTER><A HREF="general-index.html" TARGET="UP"><FONT SIZE=2> | |
13 | Global Index | |
14 | </FONT></A></CENTER></TD> | |
15 | <TD><CENTER><A HREF="tactic-index.html" TARGET="UP"><FONT SIZE=2> | |
16 | Tactics Index | |
17 | </FONT></A></CENTER></TD> | |
18 | <TD><CENTER><A HREF="command-index.html" TARGET="UP"><FONT SIZE=2> | |
19 | Vernacular Commands Index | |
20 | </FONT></A></CENTER></TD> | |
21 | <TD><CENTER><A HREF="error-index.html" TARGET="UP"><FONT SIZE=2> | |
22 | Index of Error Messages | |
23 | </FONT></A></CENTER></TD> | |
24 | </TABLE> | |
25 | ||
26 | </CENTER> | |
27 | ||
28 | </BODY></HTML>⏎ |
30 | 30 | the \Coq{} Reference Manual or the \textit{Coq'Art}, a new book by Y. |
31 | 31 | Bertot and P. Castéran on practical uses of the \Coq{} system. |
32 | 32 | |
33 | We assume here that the potential user has installed \Coq~ on his workstation, | |
34 | that he calls \Coq~ from a standard teletype-like shell window, and that | |
35 | he does not use any special interface. | |
33 | Coq can be used from a standard teletype-like shell window but | |
34 | preferably through the graphical user interface | |
35 | CoqIde\footnote{Alternative graphical interfaces exist: Proof General | |
36 | and Pcoq.}. | |
37 | ||
36 | 38 | Instructions on installation procedures, as well as more comprehensive |
37 | 39 | documentation, may be found in the standard distribution of \Coq, |
38 | 40 | which may be obtained from \Coq{} web site \texttt{http://coq.inria.fr}. |
39 | 41 | |
40 | In the following, all examples preceded by the prompting sequence | |
41 | \verb:Coq < : represent user input, terminated by a period. The | |
42 | following lines usually show \Coq's answer as it appears on the users | |
43 | screen. The sequence of such examples is a valid \Coq~ session, unless | |
44 | otherwise specified. This version of the tutorial has been prepared | |
45 | on a PC workstation running Linux. | |
46 | The standard invocation of \Coq\ delivers a message such as: | |
42 | In the following, we assume that \Coq~ is called from a standard | |
43 | teletype-like shell window. All examples preceded by the prompting | |
44 | sequence \verb:Coq < : represent user input, terminated by a | |
45 | period. | |
46 | ||
47 | The following lines usually show \Coq's answer as it appears on the | |
48 | users screen. When used from a graphical user interface such as | |
49 | CoqIde, the prompt is not displayed: user input is given in one window | |
50 | and \Coq's answers are displayed in a different window. | |
51 | ||
52 | The sequence of such examples is a valid \Coq~ | |
53 | session, unless otherwise specified. This version of the tutorial has | |
54 | been prepared on a PC workstation running Linux. The standard | |
55 | invocation of \Coq\ delivers a message such as: | |
47 | 56 | |
48 | 57 | \begin{small} |
49 | 58 | \begin{flushleft} |
1551 | 1560 | |
1552 | 1561 | \end{document} |
1553 | 1562 | |
1554 | % $Id: Tutorial.tex 8715 2006-04-14 12:43:23Z cpaulin $ | |
1563 | % $Id: Tutorial.tex 8978 2006-06-23 10:15:57Z herbelin $ |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (* $Id: coq.ml 8912 2006-06-07 11:20:58Z notin $ *) | |
8 | (* $Id: coq.ml 9024 2006-07-06 10:38:15Z herbelin $ *) | |
9 | 9 | |
10 | 10 | open Vernac |
11 | 11 | open Vernacexpr |
123 | 123 | | VernacDeclareTacticDefinition _ |
124 | 124 | when is_in_proof_mode () -> |
125 | 125 | user_error_loc loc (str "CoqIDE do not support nested goals") |
126 | | VernacDebug _ -> | |
126 | | VernacSetOption (Goptions.SecondaryTable ("Ltac","Debug"), _) -> | |
127 | 127 | user_error_loc loc (str "Debug mode not available within CoqIDE") |
128 | 128 | | VernacResetName _ |
129 | 129 | | VernacResetInitial |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (* $Id: constrextern.ml 8831 2006-05-19 09:29:54Z herbelin $ *) | |
8 | (* $Id: constrextern.ml 8997 2006-07-03 16:40:20Z herbelin $ *) | |
9 | 9 | |
10 | 10 | (*i*) |
11 | 11 | open Pp |
185 | 185 | | CCases(_,_,a1,brl1), CCases(_,_,a2,brl2) -> |
186 | 186 | List.iter2 (fun (tm1,_) (tm2,_) -> check_same_type tm1 tm2) a1 a2; |
187 | 187 | List.iter2 (fun (_,pl1,r1) (_,pl2,r2) -> |
188 | List.iter2 check_same_pattern pl1 pl2; | |
188 | List.iter2 (List.iter2 check_same_pattern) pl1 pl2; | |
189 | 189 | check_same_type r1 r2) brl1 brl2 |
190 | 190 | | CHole _, CHole _ -> () |
191 | 191 | | CPatVar(_,i1), CPatVar(_,i2) when i1=i2 -> () |
796 | 796 | LocalRawAssum([(dummy_loc,na)],ty) :: l)) |
797 | 797 | |
798 | 798 | and extern_eqn inctx scopes vars (loc,ids,pl,c) = |
799 | (loc,List.map (extern_cases_pattern_in_scope scopes vars) pl, | |
799 | (loc,[List.map (extern_cases_pattern_in_scope scopes vars) pl], | |
800 | 800 | extern inctx scopes vars c) |
801 | 801 | |
802 | 802 | and extern_symbol (tmp_scope,scopes as allscopes) vars t = function |
842 | 842 | and extern_recursion_order scopes vars = function |
843 | 843 | RStructRec -> CStructRec |
844 | 844 | | RWfRec c -> CWfRec (extern true scopes vars c) |
845 | | RMeasureRec c -> CMeasureRec (extern true scopes vars c) | |
845 | 846 | |
846 | 847 | |
847 | 848 | let extern_rawconstr vars c = |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (* $Id: constrintern.ml 8924 2006-06-08 17:49:01Z notin $ *) | |
8 | (* $Id: constrintern.ml 8997 2006-07-03 16:40:20Z herbelin $ *) | |
9 | 9 | |
10 | 10 | open Pp |
11 | 11 | open Util |
80 | 80 | str "The variable " ++ pr_id id ++ str " is bound several times in pattern" |
81 | 81 | |
82 | 82 | let explain_bad_patterns_number n1 n2 = |
83 | let s = if n1 > 1 then "s" else "" in | |
84 | str "Expecting " ++ int n1 ++ str " pattern" ++ str s ++ str " but found " | |
85 | ++ int n2 | |
83 | str "Expecting " ++ int n1 ++ str (plural n1 " pattern") ++ | |
84 | str " but found " ++ int n2 | |
86 | 85 | |
87 | 86 | let explain_bad_explicitation_number n po = |
88 | 87 | match n with |
356 | 355 | | x::l -> if List.mem x l then (Some x) else has_duplicate l |
357 | 356 | |
358 | 357 | let loc_of_lhs lhs = |
359 | join_loc (cases_pattern_loc (List.hd lhs)) (cases_pattern_loc (list_last lhs)) | |
358 | join_loc (cases_pattern_loc (List.hd (List.hd lhs))) | |
359 | (cases_pattern_loc (list_last (list_last lhs))) | |
360 | 360 | |
361 | 361 | let check_linearity lhs ids = |
362 | 362 | match has_duplicate ids with |
774 | 774 | in |
775 | 775 | let idl = Array.map |
776 | 776 | (fun (id,(n,order),bl,ty,bd) -> |
777 | let ro, ((ids',_,_),rbl) = | |
778 | (match order with | |
779 | CStructRec -> | |
780 | RStructRec, | |
781 | List.fold_left intern_local_binder (env,[]) bl | |
782 | | CWfRec c -> | |
783 | let before, after = list_chop (succ (out_some n)) bl in | |
784 | let ((ids',_,_),rafter) = | |
785 | List.fold_left intern_local_binder (env,[]) after in | |
786 | let ro = RWfRec (intern (ids', tmp_scope, scopes) c) in | |
787 | ro, List.fold_left intern_local_binder (env,rafter) before) | |
777 | let intern_ro_arg c f = | |
778 | let before, after = list_chop (succ (out_some n)) bl in | |
779 | let ((ids',_,_),rafter) = | |
780 | List.fold_left intern_local_binder (env,[]) after in | |
781 | let ro = (intern (ids', tmp_scope, scopes) c) in | |
782 | f ro, List.fold_left intern_local_binder (env,rafter) before | |
783 | in | |
784 | let ro, ((ids',_,_),rbl) = | |
785 | (match order with | |
786 | CStructRec -> | |
787 | RStructRec, | |
788 | List.fold_left intern_local_binder (env,[]) bl | |
789 | | CWfRec c -> | |
790 | intern_ro_arg c (fun r -> RWfRec r) | |
791 | | CMeasureRec c -> | |
792 | intern_ro_arg c (fun r -> RMeasureRec r)) | |
788 | 793 | in |
789 | 794 | let ids'' = List.fold_right Idset.add lf ids' in |
790 | 795 | ((n, ro), List.rev rbl, |
923 | 928 | ((name_fold Idset.add na ids,ts,sc), |
924 | 929 | (na,Some(intern env def),RHole(loc,Evd.BinderType na))::bl) |
925 | 930 | |
926 | and intern_eqn n (ids,tmp_scope,scopes as _env) (loc,lhs,rhs) = | |
931 | (* Expands a multiple pattern into a disjunction of multiple patterns *) | |
932 | and intern_multiple_pattern scopes pl = | |
927 | 933 | let idsl_pll = |
928 | List.map (intern_cases_pattern globalenv scopes ([],[]) None) lhs in | |
929 | ||
930 | let eqn_ids,pll = product_of_cases_patterns [] idsl_pll in | |
934 | List.map (intern_cases_pattern globalenv scopes ([],[]) None) pl in | |
935 | product_of_cases_patterns [] idsl_pll | |
936 | ||
937 | (* Expands a disjunction of multiple pattern *) | |
938 | and intern_disjunctive_multiple_pattern scopes loc mpl = | |
939 | assert (mpl <> []); | |
940 | let mpl' = List.map (intern_multiple_pattern scopes) mpl in | |
941 | let (idsl,mpl') = List.split mpl' in | |
942 | let ids = List.hd idsl in | |
943 | check_or_pat_variables loc ids (List.tl idsl); | |
944 | (ids,List.flatten mpl') | |
945 | ||
946 | (* Expands a pattern-matching clause [lhs => rhs] *) | |
947 | and intern_eqn n (ids,tmp_scope,scopes) (loc,lhs,rhs) = | |
948 | let eqn_ids,pll = intern_disjunctive_multiple_pattern scopes loc lhs in | |
931 | 949 | (* Linearity implies the order in ids is irrelevant *) |
932 | 950 | check_linearity lhs eqn_ids; |
933 | 951 | check_number_of_pattern loc n (snd (List.hd pll)); |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (*i $Id: genarg.mli 8926 2006-06-08 20:23:17Z herbelin $ i*) | |
8 | (*i $Id: genarg.mli 8983 2006-06-23 13:21:49Z herbelin $ i*) | |
9 | 9 | |
10 | 10 | open Util |
11 | 11 | open Names |
59 | 59 | \begin{verbatim} |
60 | 60 | tag raw open type cooked closed type |
61 | 61 | |
62 | BoolArgType bool bool | |
63 | IntArgType int int | |
64 | IntOrVarArgType int or_var int | |
65 | StringArgType string (parsed w/ "") string | |
66 | PreIdentArgType string (parsed w/o "") (vernac only) | |
67 | IdentArgType identifier identifier | |
68 | IntroPatternArgType intro_pattern_expr intro_pattern_expr | |
69 | VarArgType identifier constr | |
70 | RefArgType reference global_reference | |
71 | ConstrArgType constr_expr constr | |
72 | ConstrMayEvalArgType constr_expr may_eval constr | |
73 | QuantHypArgType quantified_hypothesis quantified_hypothesis | |
74 | OpenConstrArgType constr_expr open_constr | |
75 | ConstrBindingsArgType constr_expr with_bindings constr with_bindings | |
62 | BoolArgType bool bool | |
63 | IntArgType int int | |
64 | IntOrVarArgType int or_var int | |
65 | StringArgType string (parsed w/ "") string | |
66 | PreIdentArgType string (parsed w/o "") (vernac only) | |
67 | IdentArgType identifier identifier | |
68 | IntroPatternArgType intro_pattern_expr intro_pattern_expr | |
69 | VarArgType identifier located identifier | |
70 | RefArgType reference global_reference | |
71 | QuantHypArgType quantified_hypothesis quantified_hypothesis | |
72 | ConstrArgType constr_expr constr | |
73 | ConstrMayEvalArgType constr_expr may_eval constr | |
74 | OpenConstrArgType open_constr_expr open_constr | |
75 | ConstrWithBindingsArgType constr_expr with_bindings constr with_bindings | |
76 | BindingsArgType constr_expr bindings constr bindings | |
76 | 77 | List0ArgType of argument_type |
77 | 78 | List1ArgType of argument_type |
78 | 79 | OptArgType of argument_type |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (* $Id: topconstr.ml 8875 2006-05-29 19:59:11Z msozeau $ *) | |
8 | (* $Id: topconstr.ml 9032 2006-07-07 16:30:34Z herbelin $ *) | |
9 | 9 | |
10 | 10 | (*i*) |
11 | 11 | open Pp |
514 | 514 | (constr_expr * explicitation located option) list |
515 | 515 | | CCases of loc * constr_expr option * |
516 | 516 | (constr_expr * (name option * constr_expr option)) list * |
517 | (loc * cases_pattern_expr list * constr_expr) list | |
517 | (loc * cases_pattern_expr list list * constr_expr) list | |
518 | 518 | | CLetTuple of loc * name list * (name option * constr_expr option) * |
519 | 519 | constr_expr * constr_expr |
520 | 520 | | CIf of loc * constr_expr * (name option * constr_expr option) |
543 | 543 | and recursion_order_expr = |
544 | 544 | | CStructRec |
545 | 545 | | CWfRec of constr_expr |
546 | | CMeasureRec of constr_expr | |
546 | 547 | |
547 | 548 | (***********************) |
548 | 549 | (* For binders parsing *) |
550 | 551 | let rec local_binders_length = function |
551 | 552 | | [] -> 0 |
552 | 553 | | LocalRawDef _::bl -> 1 + local_binders_length bl |
554 | | LocalRawAssum (idl,_)::bl -> List.length idl + local_binders_length bl | |
555 | ||
556 | let rec local_assums_length = function | |
557 | | [] -> 0 | |
558 | | LocalRawDef _::bl -> local_binders_length bl | |
553 | 559 | | LocalRawAssum (idl,_)::bl -> List.length idl + local_binders_length bl |
554 | 560 | |
555 | 561 | let names_of_local_assums bl = |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (*i $Id: topconstr.mli 8875 2006-05-29 19:59:11Z msozeau $ i*) | |
8 | (*i $Id: topconstr.mli 9032 2006-07-07 16:30:34Z herbelin $ i*) | |
9 | 9 | |
10 | 10 | (*i*) |
11 | 11 | open Pp |
97 | 97 | (constr_expr * explicitation located option) list |
98 | 98 | | CCases of loc * constr_expr option * |
99 | 99 | (constr_expr * (name option * constr_expr option)) list * |
100 | (loc * cases_pattern_expr list * constr_expr) list | |
100 | (loc * cases_pattern_expr list list * constr_expr) list | |
101 | 101 | | CLetTuple of loc * name list * (name option * constr_expr option) * |
102 | 102 | constr_expr * constr_expr |
103 | 103 | | CIf of loc * constr_expr * (name option * constr_expr option) |
121 | 121 | and recursion_order_expr = |
122 | 122 | | CStructRec |
123 | 123 | | CWfRec of constr_expr |
124 | | CMeasureRec of constr_expr | |
124 | 125 | |
125 | 126 | and local_binder = |
126 | 127 | | LocalRawDef of name located * constr_expr |
157 | 158 | (* Includes let binders *) |
158 | 159 | val local_binders_length : local_binder list -> int |
159 | 160 | |
161 | (* Excludes let binders *) | |
162 | val local_assums_length : local_binder list -> int | |
163 | ||
160 | 164 | (* Does not take let binders into account *) |
161 | 165 | val names_of_local_assums : local_binder list -> name located list |
162 | 166 |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (* $Id: inductive.ml 8871 2006-05-28 16:46:48Z herbelin $ *) | |
8 | (* $Id: inductive.ml 8972 2006-06-22 22:17:43Z herbelin $ *) | |
9 | 9 | |
10 | 10 | open Util |
11 | 11 | open Names |
134 | 134 | | Prop Null -> neutral_univ |
135 | 135 | | Prop Pos -> base_univ |
136 | 136 | |
137 | let cons_subst u su subst = | |
138 | try (u, sup su (List.assoc u subst)) :: List.remove_assoc u subst | |
139 | with Not_found -> (u, su) :: subst | |
140 | ||
137 | 141 | let rec make_subst env exp act = |
138 | 142 | match exp, act with |
139 | 143 | (* Bind expected levels of parameters to actual levels *) |
140 | 144 | | None :: exp, _ :: act -> |
141 | 145 | make_subst env exp act |
142 | | Some u :: exp, t :: act -> | |
143 | (u, sort_as_univ (snd (dest_arity env t))) :: make_subst env exp act | |
146 | | Some u :: exp, t :: act -> | |
147 | let su = sort_as_univ (snd (dest_arity env t)) in | |
148 | cons_subst u su (make_subst env exp act) | |
144 | 149 | (* Not enough parameters, create a fresh univ *) |
145 | 150 | | Some u :: exp, [] -> |
146 | (u, fresh_local_univ ()) :: make_subst env exp [] | |
151 | let su = fresh_local_univ () in | |
152 | cons_subst u su (make_subst env exp []) | |
147 | 153 | | None :: exp, [] -> |
148 | 154 | make_subst env exp [] |
149 | 155 | (* Uniform parameters are exhausted *) |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (* $Id: argextend.ml4 8926 2006-06-08 20:23:17Z herbelin $ *) | |
8 | (* $Id: argextend.ml4 8976 2006-06-23 10:03:54Z herbelin $ *) | |
9 | 9 | |
10 | 10 | open Genarg |
11 | 11 | open Q_util |
175 | 175 | |
176 | 176 | open Vernacexpr |
177 | 177 | open Pcoq |
178 | ||
179 | let rec interp_entry_name loc s = | |
180 | let l = String.length s in | |
181 | if l > 8 & String.sub s 0 3 = "ne_" & String.sub s (l-5) 5 = "_list" then | |
182 | let t, g = interp_entry_name loc (String.sub s 3 (l-8)) in | |
183 | List1ArgType t, <:expr< Gramext.Slist1 $g$ >> | |
184 | else if l > 5 & String.sub s (l-5) 5 = "_list" then | |
185 | let t, g = interp_entry_name loc (String.sub s 0 (l-5)) in | |
186 | List0ArgType t, <:expr< Gramext.Slist0 $g$ >> | |
187 | else if l > 4 & String.sub s (l-4) 4 = "_opt" then | |
188 | let t, g = interp_entry_name loc (String.sub s 0 (l-4)) in | |
189 | OptArgType t, <:expr< Gramext.Sopt $g$ >> | |
190 | else | |
191 | let t, se = | |
192 | if tactic_genarg_level s <> None then | |
193 | Some (ExtraArgType s), <:expr< Tactic. tactic >> | |
194 | else | |
195 | match Pcoq.entry_type (Pcoq.get_univ "prim") s with | |
196 | | Some _ as x -> x, <:expr< Prim. $lid:s$ >> | |
197 | | None -> | |
198 | match Pcoq.entry_type (Pcoq.get_univ "constr") s with | |
199 | | Some _ as x -> x, <:expr< Constr. $lid:s$ >> | |
200 | | None -> | |
201 | match Pcoq.entry_type (Pcoq.get_univ "tactic") s with | |
202 | | Some _ as x -> x, <:expr< Tactic. $lid:s$ >> | |
203 | | None -> None, <:expr< $lid:s$ >> in | |
204 | let t = | |
205 | match t with | |
206 | | Some t -> t | |
207 | | None -> | |
208 | (* Pp.warning_with Pp_control.err_ft | |
209 | ("Unknown primitive grammar entry: "^s);*) | |
210 | ExtraArgType s | |
211 | in t, <:expr< Gramext.Snterm (Pcoq.Gram.Entry.obj $se$) >> | |
212 | ||
213 | 178 | open Pcaml |
214 | 179 | |
215 | 180 | EXTEND |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (* $Id: g_constr.ml4 8875 2006-05-29 19:59:11Z msozeau $ *) | |
8 | (* $Id: g_constr.ml4 9043 2006-07-12 10:06:40Z herbelin $ *) | |
9 | 9 | |
10 | 10 | open Pcoq |
11 | 11 | open Constr |
243 | 243 | fixannot: |
244 | 244 | [ [ "{"; IDENT "struct"; id=name; "}" -> (Some id, CStructRec) |
245 | 245 | | "{"; IDENT "wf"; id=name; rel=lconstr; "}" -> (Some id, CWfRec rel) |
246 | | "{"; IDENT "measure"; id=name; rel=lconstr; "}" -> (Some id, CMeasureRec rel) | |
246 | 247 | | -> (None, CStructRec) |
247 | 248 | ] ] |
248 | 249 | ; |
272 | 273 | [ [ OPT"|"; br=LIST0 eqn SEP "|" -> br ] ] |
273 | 274 | ; |
274 | 275 | eqn: |
275 | [ [ pl = LIST1 pattern SEP ","; "=>"; rhs = lconstr -> (loc,pl,rhs) ] ] | |
276 | [ [ pll = LIST0 LIST1 pattern LEVEL "99" SEP "," SEP "|"; | |
277 | "=>"; rhs = lconstr -> (loc,pll,rhs) ] ] | |
276 | 278 | ; |
277 | 279 | pattern: |
278 | 280 | [ "200" RIGHTA [ ] |
279 | | "100" LEFTA | |
281 | | "100" RIGHTA | |
280 | 282 | [ p = pattern; "|"; pl = LIST1 pattern SEP "|" -> CPatOr (loc,p::pl) ] |
281 | 283 | | "99" RIGHTA [ ] |
282 | 284 | | "10" LEFTA |
283 | [ p = pattern; lp = LIST1 (pattern LEVEL "0") -> | |
285 | [ p = pattern; lp = LIST1 NEXT -> | |
284 | 286 | (match p with |
285 | 287 | | CPatAtom (_, Some r) -> CPatCstr (loc, r, lp) |
286 | 288 | | _ -> Util.user_err_loc |
287 | 289 | (cases_pattern_loc p, "compound_pattern", |
288 | 290 | Pp.str "Constructor expected")) |
289 | 291 | | p = pattern; "as"; id = ident -> |
290 | CPatAlias (loc, p, id) | |
291 | | c = pattern; "%"; key=IDENT -> | |
292 | CPatDelimiters (loc,key,c) ] | |
292 | CPatAlias (loc, p, id) ] | |
293 | | "1" LEFTA | |
294 | [ c = pattern; "%"; key=IDENT -> CPatDelimiters (loc,key,c) ] | |
293 | 295 | | "0" |
294 | 296 | [ r = Prim.reference -> CPatAtom (loc,Some r) |
295 | 297 | | "_" -> CPatAtom (loc,None) |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (* $Id: g_ltac.ml4 8878 2006-05-30 16:44:25Z herbelin $ *) | |
8 | (* $Id: g_ltac.ml4 9037 2006-07-11 12:43:50Z herbelin $ *) | |
9 | 9 | |
10 | 10 | open Pp |
11 | 11 | open Util |
133 | 133 | | "()" -> TacVoid ] ] |
134 | 134 | ; |
135 | 135 | match_key: |
136 | [ [ "match" -> false ] ] | |
136 | [ [ "match" -> false | "lazymatch" -> true ] ] | |
137 | 137 | ; |
138 | 138 | input_fun: |
139 | 139 | [ [ "_" -> None |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (* $Id: g_vernac.ml4 8929 2006-06-08 22:35:58Z herbelin $ *) | |
8 | (* $Id: g_vernac.ml4 9017 2006-07-05 17:27:34Z herbelin $ *) | |
9 | 9 | (*i camlp4deps: "parsing/grammar.cma" i*) |
10 | 10 | |
11 | 11 | open Pp |
236 | 236 | rec_annotation: |
237 | 237 | [ [ "{"; IDENT "struct"; id=IDENT; "}" -> (Some (id_of_string id), CStructRec) |
238 | 238 | | "{"; IDENT "wf"; id=IDENT; rel=lconstr; "}" -> (Some (id_of_string id), CWfRec rel) |
239 | | "{"; IDENT "measure"; id=IDENT; rel=lconstr; "}" -> (Some (id_of_string id), CMeasureRec rel) | |
239 | 240 | | -> (None, CStructRec) |
240 | 241 | ] ] |
241 | 242 | ; |
650 | 651 | VernacBacktrack (n,m,p) |
651 | 652 | |
652 | 653 | (* Tactic Debugger *) |
653 | | IDENT "Debug"; IDENT "On" -> VernacDebug true | |
654 | | IDENT "Debug"; IDENT "Off" -> VernacDebug false | |
654 | | IDENT "Debug"; IDENT "On" -> | |
655 | VernacSetOption (SecondaryTable ("Ltac","Debug"), BoolValue true) | |
656 | ||
657 | | IDENT "Debug"; IDENT "Off" -> | |
658 | VernacSetOption (SecondaryTable ("Ltac","Debug"), BoolValue false) | |
655 | 659 | |
656 | 660 | ] ]; |
657 | 661 | END |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (* $Id: g_xml.ml4 8875 2006-05-29 19:59:11Z msozeau $ *) | |
8 | (* $Id: g_xml.ml4 9016 2006-07-05 17:19:39Z herbelin $ *) | |
9 | 9 | |
10 | 10 | open Pp |
11 | 11 | open Util |
227 | 227 | (match l with |
228 | 228 | [c] -> RWfRec (interp_xml_type c) |
229 | 229 | | _ -> user_err_loc (loc, "", str "wrong number of arguments (expected one)")) |
230 | | "Measure" -> | |
231 | (match l with | |
232 | [c] -> RMeasureRec (interp_xml_type c) | |
233 | | _ -> user_err_loc (loc, "", str "wrong number of arguments (expected one)")) | |
230 | 234 | | _ -> |
231 | 235 | user_err_loc (locs,"",str "invalid recursion order") |
232 | 236 | |
251 | 255 | |
252 | 256 | (* Interpreting tactic argument *) |
253 | 257 | |
254 | let rec (interp_xml_tactic_expr : xml -> glob_tactic_expr) = function | |
255 | | XmlTag (loc,"TACARG",[],[x]) -> | |
256 | TacArg (interp_xml_tactic_arg x) | |
257 | | _ -> error "Ill-formed xml tree" | |
258 | ||
259 | and interp_xml_tactic_arg = function | |
258 | let rec interp_xml_tactic_arg = function | |
260 | 259 | | XmlTag (loc,"TERM",[],[x]) -> |
261 | 260 | ConstrMayEval (ConstrTerm (interp_xml_constr x,None)) |
262 | 261 | | XmlTag (loc,"CALL",al,xl) -> |
263 | 262 | let ltacref = ltacref_of_cdata (get_xml_attr "uri" al) in |
264 | 263 | TacCall(loc,ArgArg ltacref,List.map interp_xml_tactic_arg xl) |
265 | (* | |
266 | | XmlTag (loc,"TACTIC",[],[x]) -> | |
267 | Tacexp (interp_xml_tactic_expr x) | |
268 | | _ -> error "Ill-formed xml tree" | |
269 | *) | |
270 | 264 | | XmlTag (loc,s,_,_) -> user_err_loc (loc,"", str "Unexpected tag " ++ str s) |
271 | 265 | |
272 | 266 | let parse_tactic_arg ch = |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (*i $Id: lexer.ml4 8924 2006-06-08 17:49:01Z notin $ i*) | |
8 | (*i $Id: lexer.ml4 9015 2006-07-05 17:19:22Z herbelin $ i*) | |
9 | 9 | |
10 | 10 | open Pp |
11 | 11 | open Token |
145 | 145 | (* utf-8 what do to with diacritics U0483-U0489 \ U0487 ? *) |
146 | 146 | (* utf-8 Cyrillic letters U048A-U4F9 (Warning: 04CF) *) |
147 | 147 | | x when 0x048A <= x & x <= 0x04F9 -> Utf8Letter n |
148 | (* utf-8 Cyrillic supplements letters U0500-U050F *) | |
148 | (* utf-8 Cyrillic supplement letters U0500-U050F *) | |
149 | 149 | | x when 0x0500 <= x & x <= 0x050F -> Utf8Letter n |
150 | 150 | (* utf-8 Hebrew letters U05D0-05EA *) |
151 | 151 | | x when 0x05D0 <= x & x <= 0x05EA -> Utf8Letter n |
152 | (* utf-8 Hebrew letters U0621-064A *) | |
152 | (* utf-8 Arabic letters U0621-064A *) | |
153 | 153 | | x when 0x0621 <= x & x <= 0x064A -> Utf8Letter n |
154 | (* utf-8 Arabic supplement letters U0750-076D *) | |
155 | | x when 0x0750 <= x & x <= 0x076D -> Utf8Letter n | |
154 | 156 | | _ -> error_unsupported_unicode_character n cs |
155 | 157 | end |
156 | 158 | | 0x1000 -> |
588 | 590 | | _ -> false |
589 | 591 | |
590 | 592 | let is_number s = |
591 | match s.[0] with | |
592 | | '0'..'9' -> true | |
593 | | _ -> false | |
593 | let rec aux i = | |
594 | String.length s = i or | |
595 | match s.[i] with '0'..'9' -> aux (i+1) | _ -> false | |
596 | in aux 0 | |
594 | 597 | |
595 | 598 | let strip s = |
596 | 599 | let len = |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (*i $Id: pcoq.ml4 8926 2006-06-08 20:23:17Z herbelin $ i*) | |
8 | (*i $Id: pcoq.ml4 9043 2006-07-12 10:06:40Z herbelin $ i*) | |
9 | 9 | |
10 | 10 | open Pp |
11 | 11 | open Util |
483 | 483 | 0,Gramext.RightA] |
484 | 484 | |
485 | 485 | let default_pattern_levels = |
486 | [10,Gramext.LeftA; | |
486 | [200,Gramext.RightA; | |
487 | 100,Gramext.RightA; | |
488 | 99,Gramext.RightA; | |
489 | 10,Gramext.LeftA; | |
490 | 1,Gramext.LeftA; | |
487 | 491 | 0,Gramext.RightA] |
488 | 492 | |
489 | 493 | let level_stack = |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (* $Id: ppconstr.ml 8878 2006-05-30 16:44:25Z herbelin $ *) | |
8 | (* $Id: ppconstr.ml 8997 2006-07-03 16:40:20Z herbelin $ *) | |
9 | 9 | |
10 | 10 | (*i*) |
11 | 11 | open Util |
185 | 185 | |
186 | 186 | let pr_patt = pr_patt mt |
187 | 187 | |
188 | ||
189 | 188 | let pr_eqn pr (loc,pl,rhs) = |
190 | 189 | spc() ++ hov 4 |
191 | 190 | (pr_with_comments loc |
192 | 191 | (str "| " ++ |
193 | hov 0 (prlist_with_sep sep_v (pr_patt ltop) pl ++ str " =>") ++ | |
192 | hov 0 (prlist_with_sep pr_bar (prlist_with_sep sep_v (pr_patt ltop)) pl | |
193 | ++ str " =>") ++ | |
194 | 194 | pr_sep_com spc (pr ltop) rhs)) |
195 | 195 | |
196 | 196 | let begin_of_binder = function |
383 | 383 | else mt() |
384 | 384 | | CWfRec c -> |
385 | 385 | spc () ++ str "{wf " ++ pr lsimple c ++ pr_name (snd (List.nth ids (out_some n))) ++ str"}" |
386 | | CMeasureRec c -> | |
387 | spc () ++ str "{measure " ++ pr lsimple c ++ pr_name (snd (List.nth ids (out_some n))) ++ str"}" | |
386 | 388 | in |
387 | 389 | pr_recursive_decl pr prd dangling_with_for id bl annot t c |
388 | 390 |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (* $Id: ppvernac.ml 8831 2006-05-19 09:29:54Z herbelin $ *) | |
8 | (* $Id: ppvernac.ml 9020 2006-07-05 17:35:23Z herbelin $ *) | |
9 | 9 | |
10 | 10 | open Pp |
11 | 11 | open Names |
413 | 413 | | ExplainTree l -> str"Explain Proof Tree" ++ spc() ++ prlist_with_sep sep int l |
414 | 414 | in pr_showable s |
415 | 415 | | VernacCheckGuard -> str"Guarded" |
416 | | VernacDebug b -> pr_topcmd b | |
417 | 416 | |
418 | 417 | (* Resetting *) |
419 | 418 | | VernacResetName id -> str"Reset" ++ spc() ++ pr_lident id |
570 | 569 | else mt() |
571 | 570 | | CWfRec c -> |
572 | 571 | spc() ++ str "{wf " ++ pr_name name ++ spc() ++ |
572 | pr_lconstr_expr c ++ str"}" | |
573 | | CMeasureRec c -> | |
574 | spc() ++ str "{measure " ++ pr_name name ++ spc() ++ | |
573 | 575 | pr_lconstr_expr c ++ str"}" |
574 | 576 | in |
575 | 577 | pr_id id ++ pr_binders_arg bl ++ annot ++ spc() |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (* $Id: q_util.ml4 7732 2005-12-26 13:51:24Z herbelin $ *) | |
8 | (* $Id: q_util.ml4 8982 2006-06-23 13:17:49Z herbelin $ *) | |
9 | 9 | |
10 | 10 | (* This file defines standard combinators to build ml expressions *) |
11 | 11 | |
83 | 83 | OptArgType t, <:expr< Gramext.Sopt $g$ >> |
84 | 84 | else |
85 | 85 | let s = if s = "hyp" then "var" else s in |
86 | let t, se = | |
86 | let t, se, lev = | |
87 | match tactic_genarg_level s with | |
88 | | Some n -> Some (ExtraArgType s), <:expr< Tactic. tactic_expr >>, Some n | |
89 | | None -> | |
87 | 90 | match Pcoq.entry_type (Pcoq.get_univ "prim") s with |
88 | | Some _ as x -> x, <:expr< Prim. $lid:s$ >> | |
91 | | Some _ as x -> x, <:expr< Prim. $lid:s$ >>, None | |
89 | 92 | | None -> |
90 | 93 | match Pcoq.entry_type (Pcoq.get_univ "constr") s with |
91 | | Some _ as x -> x, <:expr< Constr. $lid:s$ >> | |
94 | | Some _ as x -> x, <:expr< Constr. $lid:s$ >>, None | |
92 | 95 | | None -> |
93 | 96 | match Pcoq.entry_type (Pcoq.get_univ "tactic") s with |
94 | | Some _ as x -> x, <:expr< Tactic. $lid:s$ >> | |
95 | | None -> None, <:expr< $lid:s$ >> in | |
97 | | Some _ as x -> x, <:expr< Tactic. $lid:s$ >>, None | |
98 | | None -> None, <:expr< $lid:s$ >>, None in | |
96 | 99 | let t = |
97 | 100 | match t with |
98 | 101 | | Some t -> t |
99 | | None -> | |
100 | (* Pp.warning_with Pp_control.err_ft | |
101 | ("Unknown primitive grammar entry: "^s);*) | |
102 | ExtraArgType s | |
103 | in t, <:expr< Gramext.Snterm (Pcoq.Gram.Entry.obj $se$) >> | |
102 | | None -> ExtraArgType s in | |
103 | let entry = match lev with | |
104 | | Some n -> | |
105 | let s = string_of_int n in | |
106 | <:expr< Gramext.Snterml (Pcoq.Gram.Entry.obj $se$, $str:s$) >> | |
107 | | None -> | |
108 | <:expr< Gramext.Snterm (Pcoq.Gram.Entry.obj $se$) >> | |
109 | in t, entry |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (* $Id: pattern.ml 8755 2006-04-27 22:22:15Z herbelin $ *) | |
8 | (* $Id: pattern.ml 8963 2006-06-19 18:54:49Z barras $ *) | |
9 | 9 | |
10 | 10 | open Util |
11 | 11 | open Names |
131 | 131 | let map_pattern f = map_pattern_with_binders (fun () -> ()) (fun () -> f) () |
132 | 132 | |
133 | 133 | let rec instantiate_pattern lvar = function |
134 | | PVar id as x -> (try List.assoc id lvar with Not_found -> x) | |
134 | | PVar id as x -> (try Lazy.force(List.assoc id lvar) with Not_found -> x) | |
135 | 135 | | (PFix _ | PCoFix _) -> error ("Not instantiable pattern") |
136 | 136 | | c -> map_pattern (instantiate_pattern lvar) c |
137 | 137 |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (*i $Id: pattern.mli 8755 2006-04-27 22:22:15Z herbelin $ i*) | |
8 | (*i $Id: pattern.mli 8963 2006-06-19 18:54:49Z barras $ i*) | |
9 | 9 | |
10 | 10 | (*i*) |
11 | 11 | open Pp |
75 | 75 | patvar list * constr_pattern |
76 | 76 | |
77 | 77 | val instantiate_pattern : |
78 | (identifier * constr_pattern) list -> constr_pattern -> constr_pattern | |
78 | (identifier * constr_pattern Lazy.t) list -> constr_pattern -> constr_pattern | |
79 | 79 | |
80 | 80 | val lift_pattern : int -> constr_pattern -> constr_pattern |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (* $Id: pretyping.ml 8875 2006-05-29 19:59:11Z msozeau $ *) | |
8 | (* $Id: pretyping.ml 8992 2006-06-27 21:29:18Z herbelin $ *) | |
9 | 9 | |
10 | 10 | open Pp |
11 | 11 | open Util |
481 | 481 | else |
482 | 482 | error_cant_find_case_type_loc loc env (evars_of !isevars) |
483 | 483 | cj.uj_val in |
484 | let ccl = refresh_universes ccl in | |
484 | 485 | let p = it_mkLambda_or_LetIn (lift (nar+1) ccl) psign in |
485 | 486 | let v = |
486 | 487 | let mis,_ = dest_ind_family indf in |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (* $Id: rawterm.ml 8878 2006-05-30 16:44:25Z herbelin $ *) | |
8 | (* $Id: rawterm.ml 8969 2006-06-22 12:51:04Z msozeau $ *) | |
9 | 9 | |
10 | 10 | (*i*) |
11 | 11 | open Util |
72 | 72 | |
73 | 73 | and rawdecl = name * rawconstr option * rawconstr |
74 | 74 | |
75 | and fix_recursion_order = RStructRec | RWfRec of rawconstr | |
75 | and fix_recursion_order = RStructRec | RWfRec of rawconstr | RMeasureRec of rawconstr | |
76 | 76 | |
77 | 77 | and fix_kind = |
78 | 78 | | RFix of ((int option * fix_recursion_order) array * int) |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (*i $Id: rawterm.mli 8878 2006-05-30 16:44:25Z herbelin $ i*) | |
8 | (*i $Id: rawterm.mli 8969 2006-06-22 12:51:04Z msozeau $ i*) | |
9 | 9 | |
10 | 10 | (*i*) |
11 | 11 | open Util |
69 | 69 | |
70 | 70 | and rawdecl = name * rawconstr option * rawconstr |
71 | 71 | |
72 | and fix_recursion_order = RStructRec | RWfRec of rawconstr | |
72 | and fix_recursion_order = RStructRec | RWfRec of rawconstr | RMeasureRec of rawconstr | |
73 | 73 | |
74 | 74 | and fix_kind = |
75 | 75 | | RFix of ((int option * fix_recursion_order) array * int) |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (* $Id: recordops.ml 8752 2006-04-27 19:37:33Z herbelin $ *) | |
8 | (* $Id: recordops.ml 9032 2006-07-07 16:30:34Z herbelin $ *) | |
9 | 9 | |
10 | 10 | open Util |
11 | 11 | open Pp |
31 | 31 | |
32 | 32 | type struc_typ = { |
33 | 33 | s_CONST : identifier; |
34 | s_PARAM : int; | |
34 | s_EXPECTEDPARAM : int; | |
35 | 35 | s_PROJKIND : bool list; |
36 | 36 | s_PROJ : constant option list } |
37 | 37 | |
43 | 43 | let load_structure i (_,(ind,id,kl,projs)) = |
44 | 44 | let n = (fst (Global.lookup_inductive ind)).Declarations.mind_nparams in |
45 | 45 | let struc = |
46 | { s_CONST = id; s_PARAM = n; s_PROJ = projs; s_PROJKIND = kl } in | |
46 | { s_CONST = id; s_EXPECTEDPARAM = n; s_PROJ = projs; s_PROJKIND = kl } in | |
47 | 47 | structure_table := Indmap.add ind struc !structure_table; |
48 | 48 | projection_table := |
49 | 49 | List.fold_right (option_fold_right (fun proj -> Cmap.add proj struc)) |
82 | 82 | |
83 | 83 | let lookup_structure indsp = Indmap.find indsp !structure_table |
84 | 84 | |
85 | let lookup_projections indsp = (lookup_structure indsp).s_PROJ | |
86 | ||
85 | 87 | let find_projection_nparams = function |
86 | | ConstRef cst -> (Cmap.find cst !projection_table).s_PARAM | |
88 | | ConstRef cst -> (Cmap.find cst !projection_table).s_EXPECTEDPARAM | |
87 | 89 | | _ -> raise Not_found |
88 | 90 | |
89 | 91 | |
133 | 135 | let lt,t = Reductionops.splay_lambda (Global.env()) Evd.empty c in |
134 | 136 | let lt = List.rev (List.map snd lt) in |
135 | 137 | let args = snd (decompose_app t) in |
136 | let { s_PARAM = p; s_PROJ = lpj; s_PROJKIND = kl } = lookup_structure ind in | |
138 | let { s_EXPECTEDPARAM = p; s_PROJ = lpj; s_PROJKIND = kl } = lookup_structure ind in | |
137 | 139 | let params, projs = list_chop p args in |
138 | 140 | let lpj = keep_true_projections lpj kl in |
139 | 141 | let lps = List.combine lpj projs in |
201 | 203 | | Construct (indsp,1) -> indsp |
202 | 204 | | _ -> error_not_structure ref in |
203 | 205 | let s = try lookup_structure indsp with Not_found -> error_not_structure ref in |
204 | if s.s_PARAM + List.length s.s_PROJ > Array.length args then | |
206 | let ntrue_projs = List.length (List.filter (fun x -> x) s.s_PROJKIND) in | |
207 | if s.s_EXPECTEDPARAM + ntrue_projs > Array.length args then | |
205 | 208 | error_not_structure ref; |
206 | 209 | (sp,indsp) |
207 | 210 |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (*i $Id: recordops.mli 6748 2005-02-18 22:17:50Z herbelin $ i*) | |
8 | (*i $Id: recordops.mli 9032 2006-07-07 16:30:34Z herbelin $ i*) | |
9 | 9 | |
10 | 10 | (*i*) |
11 | 11 | open Names |
20 | 20 | (*s A structure S is a non recursive inductive type with a single |
21 | 21 | constructor (the name of which defaults to Build_S) *) |
22 | 22 | |
23 | type struc_typ = { | |
24 | s_CONST : identifier; | |
25 | s_PARAM : int; | |
26 | s_PROJKIND : bool list; | |
27 | s_PROJ : constant option list } | |
28 | ||
29 | 23 | val declare_structure : |
30 | 24 | inductive * identifier * int * bool list * constant option list -> unit |
31 | 25 | |
32 | (* [lookup_structure isp] returns the infos associated to inductive path | |
33 | [isp] if it corresponds to a structure, otherwise fails with [Not_found] *) | |
34 | val lookup_structure : inductive -> struc_typ | |
26 | (* [lookup_projections isp] returns the projections associated to the | |
27 | inductive path [isp] if it corresponds to a structure, otherwise | |
28 | it fails with [Not_found] *) | |
29 | val lookup_projections : inductive -> constant option list | |
35 | 30 | |
36 | 31 | (* raise [Not_found] if not a projection *) |
37 | 32 | val find_projection_nparams : global_reference -> int |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (* $Id: equality.ml 8878 2006-05-30 16:44:25Z herbelin $ *) | |
8 | (* $Id: equality.ml 9010 2006-07-05 07:17:41Z jforest $ *) | |
9 | 9 | |
10 | 10 | open Pp |
11 | 11 | open Util |
200 | 200 | ] |
201 | 201 | ] gl |
202 | 202 | else |
203 | error "terms does not have convertible types" | |
203 | error "terms do not have convertible types" | |
204 | 204 | |
205 | 205 | |
206 | 206 | let replace c2 c1 gl = abstract_replace None c2 c1 false tclIDTAC gl |
543 | 543 | |
544 | 544 | (* returns the sigma type (sigS, sigT) with the respective |
545 | 545 | constructor depending on the sort *) |
546 | ||
547 | let find_sigma_data s = | |
548 | match s with | |
549 | | Prop Pos | Type _ -> build_sigma_type () (* Set/Type *) | |
550 | | Prop Null -> error "find_sigma_data" | |
546 | (* J.F.: correction du bug #1167 en accord avec Hugo. *) | |
547 | ||
548 | let find_sigma_data s = build_sigma_type () | |
551 | 549 | |
552 | 550 | (* [make_tuple env sigma (rterm,rty) lind] assumes [lind] is the lesser |
553 | 551 | index bound in [rty] |
7 | 7 | |
8 | 8 | (*i camlp4deps: "parsing/grammar.cma" i*) |
9 | 9 | |
10 | (* $Id: extratactics.ml4 8926 2006-06-08 20:23:17Z herbelin $ *) | |
10 | (* $Id: extratactics.ml4 8979 2006-06-23 10:17:14Z herbelin $ *) | |
11 | 11 | |
12 | 12 | open Pp |
13 | 13 | open Pcoq |
45 | 45 | | None -> mt () |
46 | 46 | | Some t -> spc () ++ hov 2 (str "by" ++ spc () ++ prtac (3,Ppextend.E) t) |
47 | 47 | |
48 | (* Julien Forest: on voudrait pouvoir passer la loc mais je | |
49 | n'ai pas reussi | |
50 | *) | |
48 | let pr_in_hyp = function | |
49 | | None -> mt () | |
50 | | Some id -> spc () ++ hov 2 (str "in" ++ spc () ++ Nameops.pr_id id) | |
51 | 51 | |
52 | 52 | let pr_in_arg_hyp _prc _prlc _prtac opt_c = |
53 | match opt_c with | |
54 | | None -> mt () | |
55 | | Some id -> spc () ++ hov 2 (str "by" ++ spc () ++ Nameops.pr_id id) | |
53 | pr_in_hyp (Util.option_map snd opt_c) | |
54 | ||
55 | let pr_in_arg_hyp_typed _prc _prlc _prtac = | |
56 | pr_in_hyp | |
56 | 57 | |
57 | 58 | ARGUMENT EXTEND by_arg_tac |
58 | 59 | TYPED AS tactic_opt |
62 | 63 | END |
63 | 64 | |
64 | 65 | ARGUMENT EXTEND in_arg_hyp |
65 | TYPED AS ident_opt | |
66 | PRINTED BY pr_in_arg_hyp | |
67 | | [ "in" ident(c) ] -> [ Some (c) ] | |
66 | TYPED AS var_opt | |
67 | PRINTED BY pr_in_arg_hyp_typed | |
68 | RAW_TYPED AS var_opt | |
69 | RAW_PRINTED BY pr_in_arg_hyp | |
70 | GLOB_TYPED AS var_opt | |
71 | GLOB_PRINTED BY pr_in_arg_hyp | |
72 | | [ "in" hyp(c) ] -> [ Some (c) ] | |
68 | 73 | | [ ] -> [ None ] |
69 | 74 | END |
70 | 75 | |
182 | 187 | [ autorewrite Refiner.tclIDTAC l ] |
183 | 188 | | [ "autorewrite" "with" ne_preident_list(l) "using" tactic(t) ] -> |
184 | 189 | [ autorewrite (snd t) l ] |
185 | | [ "autorewrite" "with" ne_preident_list(l) "in" ident(id) ] -> | |
190 | | [ "autorewrite" "with" ne_preident_list(l) "in" hyp(id) ] -> | |
186 | 191 | [ autorewrite_in id Refiner.tclIDTAC l ] |
187 | | [ "autorewrite" "with" ne_preident_list(l) "in" ident(id) "using" tactic(t) ] -> | |
192 | | [ "autorewrite" "with" ne_preident_list(l) "in" hyp(id) "using" tactic(t) ] -> | |
188 | 193 | [ autorewrite_in id (snd t) l ] |
189 | 194 | END |
190 | 195 | |
282 | 287 | |
283 | 288 | TACTIC EXTEND setoid_symmetry |
284 | 289 | [ "setoid_symmetry" ] -> [ setoid_symmetry ] |
285 | | [ "setoid_symmetry" "in" ident(n) ] -> [ setoid_symmetry_in n ] | |
290 | | [ "setoid_symmetry" "in" hyp(n) ] -> [ setoid_symmetry_in n ] | |
286 | 291 | END |
287 | 292 | |
288 | 293 | TACTIC EXTEND setoid_reflexivity |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (*i $Id: extratactics.mli 8780 2006-05-02 21:58:58Z letouzey $ i*) | |
8 | (*i $Id: extratactics.mli 8977 2006-06-23 10:09:59Z herbelin $ i*) | |
9 | 9 | |
10 | open Util | |
10 | 11 | open Names |
11 | 12 | open Term |
12 | 13 | open Proof_type |
13 | 14 | open Rawterm |
15 | open Tacexpr | |
16 | open Topconstr | |
17 | open Genarg | |
14 | 18 | |
15 | 19 | val h_discrHyp : quantified_hypothesis -> tactic |
16 | 20 | val h_injHyp : quantified_hypothesis -> tactic |
25 | 29 | *) |
26 | 30 | |
27 | 31 | |
28 | val rawwit_in_arg_hyp: identifier option Tacexpr.raw_abstract_argument_type | |
29 | val in_arg_hyp: identifier option Pcoq.Gram.Entry.e | |
32 | val rawwit_in_arg_hyp: identifier located option raw_abstract_argument_type | |
33 | ||
34 | val in_arg_hyp: identifier located option Pcoq.Gram.Entry.e | |
30 | 35 | |
31 | 36 | |
32 | 37 | |
33 | 38 | val rawwit_by_arg_tac : |
34 | (Tacexpr.raw_tactic_expr option, Topconstr.constr_expr, | |
35 | Tacexpr.raw_tactic_expr) | |
36 | Genarg.abstract_argument_type | |
39 | (raw_tactic_expr option, constr_expr, raw_tactic_expr) abstract_argument_type | |
37 | 40 | |
38 | 41 | val by_arg_tac : Tacexpr.raw_tactic_expr option Pcoq.Gram.Entry.e |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (* $Id: tacinterp.ml 8926 2006-06-08 20:23:17Z herbelin $ *) | |
8 | (* $Id: tacinterp.ml 8991 2006-06-27 11:59:50Z herbelin $ *) | |
9 | 9 | |
10 | 10 | open Constrintern |
11 | 11 | open Closure |
72 | 72 | | VIntroPattern of intro_pattern_expr (* includes idents which are not *) |
73 | 73 | (* bound as in "Intro H" but which may be bound *) |
74 | 74 | (* later, as in "tac" in "Intro H; tac" *) |
75 | | VConstr of constr (* includes idents known bound and references *) | |
75 | | VConstr of constr (* includes idents known to be bound and references *) | |
76 | 76 | | VConstr_context of constr |
77 | 77 | | VRec of value ref |
78 | 78 | |
115 | 115 | | VVoid -> str "()" |
116 | 116 | | VInteger n -> int n |
117 | 117 | | VIntroPattern ipat -> pr_intro_pattern ipat |
118 | | VConstr c -> pr_lconstr_env env c | |
119 | | VConstr_context c -> pr_lconstr_env env c | |
120 | | (VTactic _ | VRTactic _ | VFun _ | VRec _) -> str "<fun>" | |
118 | | VConstr c | VConstr_context c -> | |
119 | (match env with Some env -> pr_lconstr_env env c | _ -> str "a term") | |
120 | | (VTactic _ | VRTactic _ | VFun _ | VRec _) -> str "a tactic" | |
121 | 121 | |
122 | 122 | (* Transforms a named_context into a (string * constr) list *) |
123 | 123 | let make_hyps = List.map (fun (id,_,typ) -> (id, typ)) |
166 | 166 | | ast -> |
167 | 167 | anomalylabstrm "constrOut" (str "Not a Dynamic ast") |
168 | 168 | |
169 | let loc = dummy_loc | |
169 | let dloc = dummy_loc | |
170 | 170 | |
171 | 171 | (* Globalizes the identifier *) |
172 | ||
173 | 172 | let find_reference env qid = |
174 | 173 | (* We first look for a variable of the current proof *) |
175 | 174 | match repr_qualid qid with |
177 | 176 | -> VarRef id |
178 | 177 | | _ -> Nametab.locate qid |
179 | 178 | |
180 | let coerce_to_reference env = function | |
181 | | VConstr c -> | |
182 | (try global_of_constr c | |
183 | with Not_found -> invalid_arg_loc (loc, "Not a reference")) | |
184 | | v -> errorlabstrm "coerce_to_reference" | |
185 | (str "The value" ++ spc () ++ pr_value env v ++ | |
186 | str "cannot be coerced to a reference") | |
187 | ||
188 | (* turns a value into an evaluable reference *) | |
189 | 179 | let error_not_evaluable s = |
190 | 180 | errorlabstrm "evalref_of_ref" |
191 | 181 | (str "Cannot coerce" ++ spc () ++ s ++ spc () ++ |
192 | 182 | str "to an evaluable reference") |
193 | ||
194 | let coerce_to_evaluable_ref env c = | |
195 | let ev = match c with | |
196 | | VConstr c when isConst c -> EvalConstRef (destConst c) | |
197 | | VConstr c when isVar c -> EvalVarRef (destVar c) | |
198 | | VIntroPattern (IntroIdentifier id) | |
199 | when Environ.evaluable_named id env -> EvalVarRef id | |
200 | | _ -> error_not_evaluable (pr_value env c) | |
201 | in | |
202 | if not (Tacred.is_evaluable env ev) then | |
203 | error_not_evaluable (pr_value env c); | |
204 | ev | |
205 | ||
206 | let coerce_to_inductive = function | |
207 | | VConstr c when isInd c -> destInd c | |
208 | | x -> | |
209 | try | |
210 | let r = match x with | |
211 | | VConstr c -> global_of_constr c | |
212 | | _ -> failwith "" in | |
213 | errorlabstrm "coerce_to_inductive" | |
214 | (pr_global r ++ str " is not an inductive type") | |
215 | with _ -> | |
216 | errorlabstrm "coerce_to_inductive" | |
217 | (str "Found an argument which should be an inductive type") | |
218 | ||
219 | 183 | |
220 | 184 | (* Table of "pervasives" macros tactics (e.g. auto, simpl, etc.) *) |
221 | 185 | let atomic_mactab = ref Idmap.empty |
226 | 190 | let _ = |
227 | 191 | let nocl = {onhyps=Some[];onconcl=true; concl_occs=[]} in |
228 | 192 | List.iter |
229 | (fun (s,t) -> add_primitive_tactic s (TacAtom(dummy_loc,t))) | |
193 | (fun (s,t) -> add_primitive_tactic s (TacAtom(dloc,t))) | |
230 | 194 | [ "red", TacReduce(Red false,nocl); |
231 | 195 | "hnf", TacReduce(Hnf,nocl); |
232 | 196 | "simpl", TacReduce(Simpl None,nocl); |
353 | 317 | |
354 | 318 | let strict_check = ref false |
355 | 319 | |
356 | let adjust_loc loc = if !strict_check then dummy_loc else loc | |
320 | let adjust_loc loc = if !strict_check then dloc else loc | |
357 | 321 | |
358 | 322 | (* Globalize a name which must be bound -- actually just check it is bound *) |
359 | 323 | let intern_hyp ist (loc,id as locid) = |
360 | 324 | if not !strict_check then |
361 | 325 | locid |
362 | 326 | else if find_ident id ist then |
363 | (dummy_loc,id) | |
327 | (dloc,id) | |
364 | 328 | else |
365 | 329 | Pretype_errors.error_var_not_found_loc loc id |
366 | 330 | |
400 | 364 | |
401 | 365 | let intern_constr_reference strict ist = function |
402 | 366 | | Ident (_,id) when (not strict & find_hyp id ist) or find_ctxvar id ist -> |
403 | RVar (loc,id), None | |
367 | RVar (dloc,id), None | |
404 | 368 | | r -> |
405 | 369 | let loc,qid = qualid_of_reference r in |
406 | 370 | RRef (loc,locate_global qid), if strict then None else Some (CRef r) |
473 | 437 | | ElimOnIdent (loc,id) -> |
474 | 438 | if !strict_check then |
475 | 439 | (* If in a defined tactic, no intros-until *) |
476 | ElimOnConstr (intern_constr ist (CRef (Ident (dummy_loc,id)))) | |
440 | ElimOnConstr (intern_constr ist (CRef (Ident (dloc,id)))) | |
477 | 441 | else |
478 | 442 | ElimOnIdent (loc,id) |
479 | 443 | |
508 | 472 | |
509 | 473 | let intern_constr_occurrence ist (l,c) = (l,intern_constr ist c) |
510 | 474 | |
511 | let intern_redexp ist = function | |
475 | let intern_red_expr ist = function | |
512 | 476 | | Unfold l -> Unfold (List.map (intern_unfold ist) l) |
513 | 477 | | Fold l -> Fold (List.map (intern_constr ist) l) |
514 | 478 | | Cbv f -> Cbv (intern_flag ist f) |
538 | 502 | pattern_of_rawconstr c |
539 | 503 | |
540 | 504 | (* Reads a pattern *) |
541 | let intern_pattern evc env lfun = function | |
505 | let intern_pattern sigma env lfun = function | |
542 | 506 | | Subterm (ido,pc) -> |
543 | let (metas,pat) = interp_constrpattern_gen evc env lfun pc in | |
507 | let (metas,pat) = interp_constrpattern_gen sigma env lfun pc in | |
544 | 508 | ido, metas, Subterm (ido,pat) |
545 | 509 | | Term pc -> |
546 | let (metas,pat) = interp_constrpattern_gen evc env lfun pc in | |
510 | let (metas,pat) = interp_constrpattern_gen sigma env lfun pc in | |
547 | 511 | None, metas, Term pat |
548 | 512 | |
549 | 513 | let intern_constr_may_eval ist = function |
550 | | ConstrEval (r,c) -> ConstrEval (intern_redexp ist r,intern_constr ist c) | |
514 | | ConstrEval (r,c) -> ConstrEval (intern_red_expr ist r,intern_constr ist c) | |
551 | 515 | | ConstrContext (locid,c) -> |
552 | 516 | ConstrContext (intern_hyp ist locid,intern_constr ist c) |
553 | 517 | | ConstrTypeOf c -> ConstrTypeOf (intern_constr ist c) |
572 | 536 | output_string ch "</REQUEST>\n" |
573 | 537 | |
574 | 538 | (* Reads the hypotheses of a Match Context rule *) |
575 | let rec intern_match_context_hyps evc env lfun = function | |
539 | let rec intern_match_context_hyps sigma env lfun = function | |
576 | 540 | | (Hyp ((_,na) as locna,mp))::tl -> |
577 | let ido, metas1, pat = intern_pattern evc env lfun mp in | |
578 | let lfun, metas2, hyps = intern_match_context_hyps evc env lfun tl in | |
541 | let ido, metas1, pat = intern_pattern sigma env lfun mp in | |
542 | let lfun, metas2, hyps = intern_match_context_hyps sigma env lfun tl in | |
579 | 543 | let lfun' = name_cons na (option_cons ido lfun) in |
580 | 544 | lfun', metas1@metas2, Hyp (locna,pat)::hyps |
581 | 545 | | [] -> lfun, [], [] |
708 | 672 | |
709 | 673 | (* Conversion *) |
710 | 674 | | TacReduce (r,cl) -> |
711 | TacReduce (intern_redexp ist r, clause_app (intern_hyp_location ist) cl) | |
675 | TacReduce (intern_red_expr ist r, clause_app (intern_hyp_location ist) cl) | |
712 | 676 | | TacChange (occl,c,cl) -> |
713 | 677 | TacChange (option_map (intern_constr_occurrence ist) occl, |
714 | 678 | intern_constr ist c, clause_app (intern_hyp_location ist) cl) |
866 | 830 | in_gen globwit_quant_hyp |
867 | 831 | (intern_quantified_hypothesis ist (out_gen rawwit_quant_hyp x)) |
868 | 832 | | RedExprArgType -> |
869 | in_gen globwit_red_expr (intern_redexp ist (out_gen rawwit_red_expr x)) | |
833 | in_gen globwit_red_expr (intern_red_expr ist (out_gen rawwit_red_expr x)) | |
870 | 834 | | OpenConstrArgType b -> |
871 | 835 | in_gen (globwit_open_constr_gen b) |
872 | 836 | ((),intern_constr ist (snd (out_gen (rawwit_open_constr_gen b) x))) |
913 | 877 | | None -> [] |
914 | 878 | | Some id -> [id,VConstr_context ctxt] |
915 | 879 | |
916 | (* Reads a pattern by substituing vars of lfun *) | |
880 | (* Reads a pattern by substituting vars of lfun *) | |
917 | 881 | let eval_pattern lfun c = |
918 | let lvar = List.map (fun (id,c) -> (id,pattern_of_constr c)) lfun in | |
882 | let lvar = List.map (fun (id,c) -> (id,lazy(pattern_of_constr c))) lfun in | |
919 | 883 | instantiate_pattern lvar c |
920 | 884 | |
921 | let read_pattern evc env lfun = function | |
885 | let read_pattern lfun = function | |
922 | 886 | | Subterm (ido,pc) -> Subterm (ido,eval_pattern lfun pc) |
923 | 887 | | Term pc -> Term (eval_pattern lfun pc) |
924 | 888 | |
925 | 889 | (* Reads the hypotheses of a Match Context rule *) |
926 | 890 | let cons_and_check_name id l = |
927 | 891 | if List.mem id l then |
928 | user_err_loc (loc,"read_match_context_hyps", | |
892 | user_err_loc (dloc,"read_match_context_hyps", | |
929 | 893 | str ("Hypothesis pattern-matching variable "^(string_of_id id)^ |
930 | 894 | " used twice in the same pattern")) |
931 | 895 | else id::l |
932 | 896 | |
933 | let rec read_match_context_hyps evc env lfun lidh = function | |
897 | let rec read_match_context_hyps lfun lidh = function | |
934 | 898 | | (Hyp ((loc,na) as locna,mp))::tl -> |
935 | 899 | let lidh' = name_fold cons_and_check_name na lidh in |
936 | Hyp (locna,read_pattern evc env lfun mp):: | |
937 | (read_match_context_hyps evc env lfun lidh' tl) | |
900 | Hyp (locna,read_pattern lfun mp):: | |
901 | (read_match_context_hyps lfun lidh' tl) | |
938 | 902 | | [] -> [] |
939 | 903 | |
940 | 904 | (* Reads the rules of a Match Context or a Match *) |
941 | let rec read_match_rule evc env lfun = function | |
942 | | (All tc)::tl -> (All tc)::(read_match_rule evc env lfun tl) | |
905 | let rec read_match_rule lfun = function | |
906 | | (All tc)::tl -> (All tc)::(read_match_rule lfun tl) | |
943 | 907 | | (Pat (rl,mp,tc))::tl -> |
944 | Pat (read_match_context_hyps evc env lfun [] rl, | |
945 | read_pattern evc env lfun mp,tc) | |
946 | ::(read_match_rule evc env lfun tl) | |
908 | Pat (read_match_context_hyps lfun [] rl, read_pattern lfun mp,tc) | |
909 | :: read_match_rule lfun tl | |
947 | 910 | | [] -> [] |
948 | 911 | |
949 | 912 | (* For Match Context and Match *) |
1003 | 966 | try shortest_qualid_of_global Idset.empty (global_of_constr c) |
1004 | 967 | with _ -> invalid_arg_loc (loc, "Not a global reference") |
1005 | 968 | |
969 | let is_variable env id = | |
970 | List.mem id (ids_of_named_context (Environ.named_context env)) | |
971 | ||
1006 | 972 | (* Debug reference *) |
1007 | 973 | let debug = ref DebugOff |
1008 | 974 | |
1012 | 978 | (* Gives the state of debug *) |
1013 | 979 | let get_debug () = !debug |
1014 | 980 | |
981 | let error_ltac_variable loc id env v s = | |
982 | user_err_loc (loc, "", str "Ltac variable " ++ pr_id id ++ | |
983 | str " is bound to" ++ spc () ++ pr_value env v ++ spc () ++ | |
984 | str "which cannot be coerced to " ++ str s) | |
985 | ||
986 | exception CannotCoerceTo of string | |
987 | ||
988 | (* Raise Not_found if not in interpretation sign *) | |
989 | let try_interp_ltac_var coerce ist env (loc,id) = | |
990 | let v = List.assoc id ist.lfun in | |
991 | try coerce v with CannotCoerceTo s -> error_ltac_variable loc id env v s | |
992 | ||
993 | let interp_ltac_var coerce ist env locid = | |
994 | try try_interp_ltac_var coerce ist env locid | |
995 | with Not_found -> anomaly "Detected as ltac var at interning time" | |
996 | ||
1015 | 997 | (* Interprets an identifier which must be fresh *) |
1016 | let interp_ident ist id = | |
1017 | try match List.assoc id ist.lfun with | |
998 | let coerce_to_ident env = function | |
1018 | 999 | | VIntroPattern (IntroIdentifier id) -> id |
1019 | | VConstr c when isVar c -> | |
1020 | (* This happends e.g. in definitions like "Tac H = Clear H; Intro H" *) | |
1021 | (* c is then expected not to belong to the proof context *) | |
1022 | (* would be checkable if env were known from interp_ident *) | |
1000 | | VConstr c when isVar c & not (is_variable env (destVar c)) -> | |
1001 | (* This happens e.g. in definitions like "Tac H = clear H; intro H" *) | |
1023 | 1002 | destVar c |
1024 | | _ -> user_err_loc(loc,"interp_ident", str "An ltac name (" ++ pr_id id ++ | |
1025 | str ") should have been bound to an identifier") | |
1003 | | v -> raise (CannotCoerceTo "a fresh identifier") | |
1004 | ||
1005 | let interp_ident ist gl id = | |
1006 | let env = pf_env gl in | |
1007 | try try_interp_ltac_var (coerce_to_ident env) ist (Some env) (dloc,id) | |
1026 | 1008 | with Not_found -> id |
1027 | 1009 | |
1028 | let interp_hint_base ist s = | |
1029 | try match List.assoc (id_of_string s) ist.lfun with | |
1030 | | VIntroPattern (IntroIdentifier id) -> string_of_id id | |
1031 | | _ -> user_err_loc(loc,"", str "An ltac name (" ++ str s ++ | |
1032 | str ") should have been bound to a hint base name") | |
1033 | with Not_found -> s | |
1034 | ||
1035 | let interp_intro_pattern_var ist id = | |
1036 | try match List.assoc id ist.lfun with | |
1010 | (* Interprets an optional identifier which must be fresh *) | |
1011 | let interp_name ist gl = function | |
1012 | | Anonymous -> Anonymous | |
1013 | | Name id -> Name (interp_ident ist gl id) | |
1014 | ||
1015 | let coerce_to_intro_pattern env = function | |
1037 | 1016 | | VIntroPattern ipat -> ipat |
1038 | 1017 | | VConstr c when isVar c -> |
1039 | (* This happends e.g. in definitions like "Tac H = Clear H; Intro H" *) | |
1040 | (* c is then expected not to belong to the proof context *) | |
1041 | (* would be checkable if env were known from interp_ident *) | |
1018 | (* This happens e.g. in definitions like "Tac H = clear H; intro H" *) | |
1019 | (* but also in "destruct H as (H,H')" *) | |
1042 | 1020 | IntroIdentifier (destVar c) |
1043 | | _ -> user_err_loc(loc,"interp_ident", str "An ltac name (" ++ pr_id id ++ | |
1044 | str ") should have been bound to an introduction pattern") | |
1021 | | v -> raise (CannotCoerceTo "an introduction pattern") | |
1022 | ||
1023 | let interp_intro_pattern_var ist env id = | |
1024 | try try_interp_ltac_var (coerce_to_intro_pattern env) ist (Some env)(dloc,id) | |
1045 | 1025 | with Not_found -> IntroIdentifier id |
1046 | 1026 | |
1047 | let interp_int lfun (loc,id) = | |
1048 | try match List.assoc id lfun with | |
1027 | let coerce_to_hint_base = function | |
1028 | | VIntroPattern (IntroIdentifier id) -> string_of_id id | |
1029 | | _ -> raise (CannotCoerceTo "a hint base name") | |
1030 | ||
1031 | let interp_hint_base ist s = | |
1032 | try try_interp_ltac_var coerce_to_hint_base ist None (dloc,id_of_string s) | |
1033 | with Not_found -> s | |
1034 | ||
1035 | let coerce_to_int = function | |
1049 | 1036 | | VInteger n -> n |
1050 | | _ -> user_err_loc(loc,"interp_int",str "should be bound to an integer") | |
1051 | with Not_found -> user_err_loc (loc,"interp_int",str "Unbound variable") | |
1037 | | v -> raise (CannotCoerceTo "an integer") | |
1038 | ||
1039 | let interp_int ist locid = | |
1040 | try try_interp_ltac_var coerce_to_int ist None locid | |
1041 | with Not_found -> user_err_loc(fst locid,"interp_int",str "Unbound variable") | |
1052 | 1042 | |
1053 | 1043 | let interp_int_or_var ist = function |
1054 | | ArgVar locid -> interp_int ist.lfun locid | |
1044 | | ArgVar locid -> interp_int ist locid | |
1055 | 1045 | | ArgArg n -> n |
1056 | 1046 | |
1057 | 1047 | let constr_of_value env = function |
1059 | 1049 | | VIntroPattern (IntroIdentifier id) -> constr_of_id env id |
1060 | 1050 | | _ -> raise Not_found |
1061 | 1051 | |
1062 | let is_variable env id = | |
1063 | List.mem id (ids_of_named_context (Environ.named_context env)) | |
1064 | ||
1065 | let variable_of_value env = function | |
1052 | let coerce_to_hyp env = function | |
1066 | 1053 | | VConstr c when isVar c -> destVar c |
1067 | 1054 | | VIntroPattern (IntroIdentifier id) when is_variable env id -> id |
1068 | | _ -> raise Not_found | |
1069 | ||
1070 | (* Extract a variable from a value, if any *) | |
1071 | let id_of_Identifier = variable_of_value | |
1072 | ||
1073 | (* Extract a constr from a value, if any *) | |
1074 | let constr_of_VConstr = constr_of_value | |
1055 | | _ -> raise (CannotCoerceTo "a variable") | |
1075 | 1056 | |
1076 | 1057 | (* Interprets a bound variable (especially an existing hypothesis) *) |
1077 | let interp_hyp ist gl (loc,id) = | |
1058 | let interp_hyp ist gl (loc,id as locid) = | |
1059 | let env = pf_env gl in | |
1078 | 1060 | (* Look first in lfun for a value coercible to a variable *) |
1079 | try | |
1080 | let v = List.assoc id ist.lfun in | |
1081 | try variable_of_value (pf_env gl) v | |
1082 | with Not_found -> | |
1083 | errorlabstrm "coerce_to_variable" | |
1084 | (str "Cannot coerce" ++ spc () ++ pr_value (pf_env gl) v ++ spc () ++ | |
1085 | str "to a variable") | |
1061 | try try_interp_ltac_var (coerce_to_hyp env) ist (Some env) locid | |
1086 | 1062 | with Not_found -> |
1087 | 1063 | (* Then look if bound in the proof context at calling time *) |
1088 | if is_variable (pf_env gl) id then id | |
1089 | else | |
1090 | user_err_loc (loc,"eval_variable",pr_id id ++ str " not found") | |
1091 | ||
1092 | let interp_name ist = function | |
1093 | | Anonymous -> Anonymous | |
1094 | | Name id -> Name (interp_ident ist id) | |
1064 | if is_variable env id then id | |
1065 | else user_err_loc (loc,"eval_variable",pr_id id ++ str " not found") | |
1095 | 1066 | |
1096 | 1067 | let interp_clause_pattern ist gl (l,occl) = |
1097 | 1068 | let rec check acc = function |
1104 | 1075 | in (l,check [] occl) |
1105 | 1076 | |
1106 | 1077 | (* Interprets a qualified name *) |
1078 | let coerce_to_reference env v = | |
1079 | try match v with | |
1080 | | VConstr c -> global_of_constr c (* may raise Not_found *) | |
1081 | | _ -> raise Not_found | |
1082 | with Not_found -> raise (CannotCoerceTo "a reference") | |
1083 | ||
1107 | 1084 | let interp_reference ist env = function |
1108 | 1085 | | ArgArg (_,r) -> r |
1109 | | ArgVar (loc,id) -> coerce_to_reference env (List.assoc id ist.lfun) | |
1086 | | ArgVar locid -> | |
1087 | interp_ltac_var (coerce_to_reference env) ist (Some env) locid | |
1110 | 1088 | |
1111 | 1089 | let pf_interp_reference ist gl = interp_reference ist (pf_env gl) |
1090 | ||
1091 | let coerce_to_inductive = function | |
1092 | | VConstr c when isInd c -> destInd c | |
1093 | | _ -> raise (CannotCoerceTo "an inductive type") | |
1112 | 1094 | |
1113 | 1095 | let interp_inductive ist = function |
1114 | 1096 | | ArgArg r -> r |
1115 | | ArgVar (_,id) -> coerce_to_inductive (List.assoc id ist.lfun) | |
1097 | | ArgVar locid -> interp_ltac_var coerce_to_inductive ist None locid | |
1098 | ||
1099 | let coerce_to_evaluable_ref env v = | |
1100 | let ev = match v with | |
1101 | | VConstr c when isConst c -> EvalConstRef (destConst c) | |
1102 | | VConstr c when isVar c -> EvalVarRef (destVar c) | |
1103 | | VIntroPattern (IntroIdentifier id) when List.mem id (ids_of_context env) | |
1104 | -> EvalVarRef id | |
1105 | | _ -> raise (CannotCoerceTo "an evaluable reference") | |
1106 | in | |
1107 | if not (Tacred.is_evaluable env ev) then | |
1108 | raise (CannotCoerceTo "an evaluable reference") | |
1109 | else | |
1110 | ev | |
1116 | 1111 | |
1117 | 1112 | let interp_evaluable ist env = function |
1118 | 1113 | | ArgArg (r,Some (loc,id)) -> |
1119 | 1114 | (* Maybe [id] has been introduced by Intro-like tactics *) |
1120 | 1115 | (try match Environ.lookup_named id env with |
1121 | | (_,Some _,_) -> EvalVarRef id | |
1122 | | _ -> error_not_evaluable (pr_id id) | |
1123 | with Not_found -> | |
1124 | match r with | |
1125 | | EvalConstRef _ -> r | |
1126 | | _ -> Pretype_errors.error_var_not_found_loc loc id) | |
1116 | | (_,Some _,_) -> EvalVarRef id | |
1117 | | _ -> error_not_evaluable (pr_id id) | |
1118 | with Not_found -> | |
1119 | match r with | |
1120 | | EvalConstRef _ -> r | |
1121 | | _ -> Pretype_errors.error_var_not_found_loc loc id) | |
1127 | 1122 | | ArgArg (r,None) -> r |
1128 | | ArgVar (_,id) -> coerce_to_evaluable_ref env (List.assoc id ist.lfun) | |
1123 | | ArgVar locid -> | |
1124 | interp_ltac_var (coerce_to_evaluable_ref env) ist (Some env) locid | |
1129 | 1125 | |
1130 | 1126 | (* Interprets an hypothesis name *) |
1131 | 1127 | let interp_hyp_location ist gl ((occs,id),hl) = |
1170 | 1166 | List.fold_right (fun (x,csr) a -> |
1171 | 1167 | try (x,Retyping.get_judgment_of env sigma csr)::a with |
1172 | 1168 | | Anomaly _ -> a) lst [] |
1173 | ||
1174 | (* List.map (fun (x,csr) -> (x,Retyping.get_judgment_of env sigma csr)) lst*) | |
1175 | 1169 | |
1176 | 1170 | let implicit_tactic = ref None |
1177 | 1171 | |
1276 | 1270 | |
1277 | 1271 | let pf_interp_pattern ist gl = interp_pattern ist (project gl) (pf_env gl) |
1278 | 1272 | |
1279 | let redexp_interp ist sigma env = function | |
1273 | let interp_red_expr ist sigma env = function | |
1280 | 1274 | | Unfold l -> Unfold (List.map (interp_unfold ist env) l) |
1281 | 1275 | | Fold l -> Fold (List.map (interp_constr ist sigma env) l) |
1282 | 1276 | | Cbv f -> Cbv (interp_flag ist env f) |
1285 | 1279 | | Simpl o -> Simpl (option_map (interp_pattern ist sigma env) o) |
1286 | 1280 | | (Red _ | Hnf | ExtraRedExpr _ | CbvVm as r) -> r |
1287 | 1281 | |
1288 | let pf_redexp_interp ist gl = redexp_interp ist (project gl) (pf_env gl) | |
1282 | let pf_interp_red_expr ist gl = interp_red_expr ist (project gl) (pf_env gl) | |
1289 | 1283 | |
1290 | 1284 | let interp_may_eval f ist gl = function |
1291 | 1285 | | ConstrEval (r,c) -> |
1292 | let redexp = pf_redexp_interp ist gl r in | |
1286 | let redexp = pf_interp_red_expr ist gl r in | |
1293 | 1287 | pf_reduction_of_red_expr gl redexp (f ist gl c) |
1294 | 1288 | | ConstrContext ((loc,s),c) -> |
1295 | 1289 | (try |
1322 | 1316 | | [] -> mt() |
1323 | 1317 | | MsgString s :: l -> pr_arg str s ++ interp_message ist l |
1324 | 1318 | | MsgInt n :: l -> pr_arg int n ++ interp_message ist l |
1325 | | MsgIdent (_,id) :: l -> | |
1319 | | MsgIdent (loc,id) :: l -> | |
1326 | 1320 | let v = |
1327 | 1321 | try List.assoc id ist.lfun |
1328 | with Not_found -> user_err_loc (loc,"",pr_id id ++ str " not found") in | |
1322 | with Not_found -> user_err_loc (loc,"",pr_id id ++ str" not found") in | |
1329 | 1323 | pr_arg message_of_value v ++ interp_message ist l |
1330 | 1324 | |
1331 | 1325 | let rec interp_message_nl ist = function |
1332 | 1326 | | [] -> mt() |
1333 | 1327 | | l -> interp_message ist l ++ fnl() |
1334 | 1328 | |
1335 | let rec interp_intro_pattern ist = function | |
1336 | | IntroOrAndPattern l -> IntroOrAndPattern (interp_case_intro_pattern ist l) | |
1337 | | IntroIdentifier id -> interp_intro_pattern_var ist id | |
1329 | let rec interp_intro_pattern ist gl = function | |
1330 | | IntroOrAndPattern l -> IntroOrAndPattern (interp_case_intro_pattern ist gl l) | |
1331 | | IntroIdentifier id -> interp_intro_pattern_var ist (pf_env gl) id | |
1338 | 1332 | | IntroWildcard | IntroAnonymous as x -> x |
1339 | 1333 | |
1340 | and interp_case_intro_pattern ist = | |
1341 | List.map (List.map (interp_intro_pattern ist)) | |
1334 | and interp_case_intro_pattern ist gl = | |
1335 | List.map (List.map (interp_intro_pattern ist gl)) | |
1342 | 1336 | |
1343 | 1337 | (* Quantified named or numbered hypothesis or hypothesis in context *) |
1344 | 1338 | (* (as in Inversion) *) |
1339 | let coerce_to_quantified_hypothesis = function | |
1340 | | VInteger n -> AnonHyp n | |
1341 | | VIntroPattern (IntroIdentifier id) -> NamedHyp id | |
1342 | | v -> raise (CannotCoerceTo "a quantified hypothesis") | |
1343 | ||
1345 | 1344 | let interp_quantified_hypothesis ist = function |
1346 | 1345 | | AnonHyp n -> AnonHyp n |
1347 | 1346 | | NamedHyp id -> |
1348 | try match List.assoc id ist.lfun with | |
1349 | | VInteger n -> AnonHyp n | |
1350 | | VIntroPattern (IntroIdentifier id) -> NamedHyp id | |
1351 | | _ -> raise Not_found | |
1352 | with Not_found -> NamedHyp id | |
1347 | try try_interp_ltac_var coerce_to_quantified_hypothesis ist None(dloc,id) | |
1348 | with Not_found | |
1349 | | Stdpp.Exc_located (_, UserError _) | UserError _ (*Compat provisoire*) | |
1350 | -> NamedHyp id | |
1353 | 1351 | |
1354 | 1352 | (* Quantified named or numbered hypothesis or hypothesis in context *) |
1355 | 1353 | (* (as in Inversion) *) |
1354 | let coerce_to_decl_or_quant_hyp env = function | |
1355 | | VInteger n -> AnonHyp n | |
1356 | | v -> | |
1357 | try NamedHyp (coerce_to_hyp env v) | |
1358 | with CannotCoerceTo _ -> | |
1359 | raise (CannotCoerceTo "a declared or quantified hypothesis") | |
1360 | ||
1356 | 1361 | let interp_declared_or_quantified_hypothesis ist gl = function |
1357 | 1362 | | AnonHyp n -> AnonHyp n |
1358 | 1363 | | NamedHyp id -> |
1359 | try match List.assoc id ist.lfun with | |
1360 | | VInteger n -> AnonHyp n | |
1361 | | v -> NamedHyp (variable_of_value (pf_env gl) v) | |
1364 | let env = pf_env gl in | |
1365 | try try_interp_ltac_var | |
1366 | (coerce_to_decl_or_quant_hyp env) ist (Some env) (dloc,id) | |
1362 | 1367 | with Not_found -> NamedHyp id |
1363 | 1368 | |
1364 | 1369 | let interp_induction_arg ist gl = function |
1394 | 1399 | | TacMatch (lz,c,lmr) -> interp_match ist gl lz c lmr |
1395 | 1400 | | TacArg a -> interp_tacarg ist gl a |
1396 | 1401 | (* Delayed evaluation *) |
1397 | | t -> VTactic (dummy_loc,eval_tactic ist t) | |
1402 | | t -> VTactic (dloc,eval_tactic ist t) | |
1398 | 1403 | |
1399 | 1404 | in check_for_interrupt (); |
1400 | 1405 | match ist.debug with |
1436 | 1441 | | TacVoid -> VVoid |
1437 | 1442 | | Reference r -> interp_ltac_reference false false ist gl r |
1438 | 1443 | | Integer n -> VInteger n |
1439 | | IntroPattern ipat -> VIntroPattern ipat | |
1444 | | IntroPattern ipat -> VIntroPattern (interp_intro_pattern ist gl ipat) | |
1440 | 1445 | | ConstrMayEval c -> VConstr (interp_constr_may_eval ist gl c) |
1441 | 1446 | | MetaIdArg (loc,id) -> assert false |
1442 | 1447 | | TacCall (loc,r,[]) -> interp_ltac_reference false true ist gl r |
1466 | 1471 | else if tg = "constr" then |
1467 | 1472 | VConstr (constr_out t) |
1468 | 1473 | else |
1469 | anomaly_loc (loc, "Tacinterp.val_interp", | |
1474 | anomaly_loc (dloc, "Tacinterp.val_interp", | |
1470 | 1475 | (str "Unknown dynamic: <" ++ str (Dyn.tag t) ++ str ">")) |
1471 | 1476 | |
1472 | 1477 | (* Interprets an application node *) |
1540 | 1545 | start_proof id (Local,Proof Lemma) ndc typ (fun _ _ -> ()); |
1541 | 1546 | by t; |
1542 | 1547 | let (_,({const_entry_body = pft},_,_)) = cook_proof () in |
1543 | delete_proof (dummy_loc,id); | |
1548 | delete_proof (dloc,id); | |
1544 | 1549 | pft |
1545 | 1550 | with | NotTactic -> |
1546 | delete_proof (dummy_loc,id); | |
1551 | delete_proof (dloc,id); | |
1547 | 1552 | errorlabstrm "Tacinterp.interp_letin" |
1548 | 1553 | (str "Term or fully applied tactic expected in Let") |
1549 | 1554 | in (id,VConstr (mkCast (csr,DEFAULTcast, typ)))::(interp_letin ist gl tl) |
1598 | 1603 | end in |
1599 | 1604 | let env = pf_env g in |
1600 | 1605 | apply_match_context ist env g 0 lmr |
1601 | (read_match_rule (project g) env (fst (constr_list ist env)) lmr) | |
1606 | (read_match_rule (fst (constr_list ist env)) lmr) | |
1602 | 1607 | |
1603 | 1608 | (* Tries to match the hypotheses in a Match Context *) |
1604 | 1609 | and apply_hyps_context ist env lz goal mt lctxt lgmatch mhyps hyps = |
1628 | 1633 | interp_tacarg ist gl (System.connect f g com) |
1629 | 1634 | |
1630 | 1635 | (* Interprets extended tactic generic arguments *) |
1631 | and interp_genarg ist goal x = | |
1636 | and interp_genarg ist gl x = | |
1632 | 1637 | match genarg_tag x with |
1633 | 1638 | | BoolArgType -> in_gen wit_bool (out_gen globwit_bool x) |
1634 | 1639 | | IntArgType -> in_gen wit_int (out_gen globwit_int x) |
1641 | 1646 | in_gen wit_pre_ident (out_gen globwit_pre_ident x) |
1642 | 1647 | | IntroPatternArgType -> |
1643 | 1648 | in_gen wit_intro_pattern |
1644 | (interp_intro_pattern ist (out_gen globwit_intro_pattern x)) | |
1649 | (interp_intro_pattern ist gl (out_gen globwit_intro_pattern x)) | |
1645 | 1650 | | IdentArgType -> |
1646 | in_gen wit_ident (interp_ident ist (out_gen globwit_ident x)) | |
1651 | in_gen wit_ident (interp_ident ist gl (out_gen globwit_ident x)) | |
1647 | 1652 | | VarArgType -> |
1648 | in_gen wit_var (interp_hyp ist goal (out_gen globwit_var x)) | |
1653 | in_gen wit_var (interp_hyp ist gl (out_gen globwit_var x)) | |
1649 | 1654 | | RefArgType -> |
1650 | in_gen wit_ref (pf_interp_reference ist goal (out_gen globwit_ref x)) | |
1655 | in_gen wit_ref (pf_interp_reference ist gl (out_gen globwit_ref x)) | |
1651 | 1656 | | SortArgType -> |
1652 | 1657 | in_gen wit_sort |
1653 | 1658 | (destSort |
1654 | (pf_interp_constr ist goal | |
1655 | (RSort (dummy_loc,out_gen globwit_sort x), None))) | |
1659 | (pf_interp_constr ist gl | |
1660 | (RSort (dloc,out_gen globwit_sort x), None))) | |
1656 | 1661 | | ConstrArgType -> |
1657 | in_gen wit_constr (pf_interp_constr ist goal (out_gen globwit_constr x)) | |
1662 | in_gen wit_constr (pf_interp_constr ist gl (out_gen globwit_constr x)) | |
1658 | 1663 | | ConstrMayEvalArgType -> |
1659 | in_gen wit_constr_may_eval (interp_constr_may_eval ist goal (out_gen globwit_constr_may_eval x)) | |
1664 | in_gen wit_constr_may_eval (interp_constr_may_eval ist gl (out_gen globwit_constr_may_eval x)) | |
1660 | 1665 | | QuantHypArgType -> |
1661 | 1666 | in_gen wit_quant_hyp |
1662 | (interp_declared_or_quantified_hypothesis ist goal | |
1667 | (interp_declared_or_quantified_hypothesis ist gl | |
1663 | 1668 | (out_gen globwit_quant_hyp x)) |
1664 | 1669 | | RedExprArgType -> |
1665 | in_gen wit_red_expr (pf_redexp_interp ist goal (out_gen globwit_red_expr x)) | |
1670 | in_gen wit_red_expr (pf_interp_red_expr ist gl (out_gen globwit_red_expr x)) | |
1666 | 1671 | | OpenConstrArgType casted -> |
1667 | 1672 | in_gen (wit_open_constr_gen casted) |
1668 | (pf_interp_open_constr casted ist goal | |
1673 | (pf_interp_open_constr casted ist gl | |
1669 | 1674 | (snd (out_gen (globwit_open_constr_gen casted) x))) |
1670 | 1675 | | ConstrWithBindingsArgType -> |
1671 | 1676 | in_gen wit_constr_with_bindings |
1672 | (interp_constr_with_bindings ist goal (out_gen globwit_constr_with_bindings x)) | |
1677 | (interp_constr_with_bindings ist gl (out_gen globwit_constr_with_bindings x)) | |
1673 | 1678 | | BindingsArgType -> |
1674 | 1679 | in_gen wit_bindings |
1675 | (interp_bindings ist goal (out_gen globwit_bindings x)) | |
1676 | | List0ArgType _ -> app_list0 (interp_genarg ist goal) x | |
1677 | | List1ArgType _ -> app_list1 (interp_genarg ist goal) x | |
1678 | | OptArgType _ -> app_opt (interp_genarg ist goal) x | |
1679 | | PairArgType _ -> app_pair (interp_genarg ist goal) (interp_genarg ist goal) x | |
1680 | (interp_bindings ist gl (out_gen globwit_bindings x)) | |
1681 | | List0ArgType _ -> app_list0 (interp_genarg ist gl) x | |
1682 | | List1ArgType _ -> app_list1 (interp_genarg ist gl) x | |
1683 | | OptArgType _ -> app_opt (interp_genarg ist gl) x | |
1684 | | PairArgType _ -> app_pair (interp_genarg ist gl) (interp_genarg ist gl) x | |
1680 | 1685 | | ExtraArgType s -> |
1681 | 1686 | match tactic_genarg_level s with |
1682 | 1687 | | Some n -> |
1683 | 1688 | (* Special treatment of tactic arguments *) |
1684 | 1689 | in_gen (wit_tactic n) (out_gen (globwit_tactic n) x) |
1685 | 1690 | | None -> |
1686 | lookup_interp_genarg s ist goal x | |
1691 | lookup_interp_genarg s ist gl x | |
1687 | 1692 | |
1688 | 1693 | (* Interprets the Match expressions *) |
1689 | 1694 | and interp_match ist g lz constr lmr = |
1711 | 1716 | | _ -> |
1712 | 1717 | errorlabstrm "Tacinterp.apply_match" (str |
1713 | 1718 | "No matching clauses for match") in |
1714 | let env = pf_env g in | |
1715 | let csr = | |
1716 | try constr_of_value env (val_interp ist g constr) | |
1717 | with Not_found -> | |
1718 | errorlabstrm "Tacinterp.apply_match" | |
1719 | (str "Argument of match does not evaluate to a term") in | |
1720 | let ilr = read_match_rule (project g) env (fst (constr_list ist env)) lmr in | |
1719 | let csr = interp_ltac_constr ist g constr in | |
1720 | let ilr = read_match_rule (fst (constr_list ist (pf_env g))) lmr in | |
1721 | 1721 | apply_match ist csr ilr |
1722 | ||
1723 | (* Interprets tactic expressions : returns a "constr" *) | |
1724 | and interp_ltac_constr ist gl e = | |
1725 | try constr_of_value (pf_env gl) (val_interp ist gl e) | |
1726 | with Not_found -> | |
1727 | errorlabstrm "" (str "Must evaluate to a term") | |
1722 | 1728 | |
1723 | 1729 | (* Interprets tactic expressions : returns a "tactic" *) |
1724 | 1730 | and interp_tactic ist tac gl = |
1725 | 1731 | try tactic_of_value (val_interp ist gl tac) gl |
1726 | with | NotTactic -> | |
1727 | errorlabstrm "Tacinterp.interp_tactic" (str | |
1728 | "Must be a command or must give a tactic value") | |
1732 | with NotTactic -> | |
1733 | errorlabstrm "" (str "Must be a command or must give a tactic value") | |
1729 | 1734 | |
1730 | 1735 | (* Interprets a primitive tactic *) |
1731 | 1736 | and interp_atomic ist gl = function |
1732 | 1737 | (* Basic tactics *) |
1733 | 1738 | | TacIntroPattern l -> |
1734 | h_intro_patterns (List.map (interp_intro_pattern ist) l) | |
1739 | h_intro_patterns (List.map (interp_intro_pattern ist gl) l) | |
1735 | 1740 | | TacIntrosUntil hyp -> |
1736 | 1741 | h_intros_until (interp_quantified_hypothesis ist hyp) |
1737 | 1742 | | TacIntroMove (ido,ido') -> |
1738 | h_intro_move (option_map (interp_ident ist) ido) | |
1743 | h_intro_move (option_map (interp_ident ist gl) ido) | |
1739 | 1744 | (option_map (interp_hyp ist gl) ido') |
1740 | 1745 | | TacAssumption -> h_assumption |
1741 | 1746 | | TacExact c -> h_exact (pf_interp_casted_constr ist gl c) |
1747 | 1752 | | TacElimType c -> h_elim_type (pf_interp_type ist gl c) |
1748 | 1753 | | TacCase cb -> h_case (interp_constr_with_bindings ist gl cb) |
1749 | 1754 | | TacCaseType c -> h_case_type (pf_interp_type ist gl c) |
1750 | | TacFix (idopt,n) -> h_fix (option_map (interp_ident ist) idopt) n | |
1755 | | TacFix (idopt,n) -> h_fix (option_map (interp_ident ist gl) idopt) n | |
1751 | 1756 | | TacMutualFix (id,n,l) -> |
1752 | let f (id,n,c) = (interp_ident ist id,n,pf_interp_type ist gl c) in | |
1753 | h_mutual_fix (interp_ident ist id) n (List.map f l) | |
1754 | | TacCofix idopt -> h_cofix (option_map (interp_ident ist) idopt) | |
1757 | let f (id,n,c) = (interp_ident ist gl id,n,pf_interp_type ist gl c) in | |
1758 | h_mutual_fix (interp_ident ist gl id) n (List.map f l) | |
1759 | | TacCofix idopt -> h_cofix (option_map (interp_ident ist gl) idopt) | |
1755 | 1760 | | TacMutualCofix (id,l) -> |
1756 | let f (id,c) = (interp_ident ist id,pf_interp_type ist gl c) in | |
1757 | h_mutual_cofix (interp_ident ist id) (List.map f l) | |
1761 | let f (id,c) = (interp_ident ist gl id,pf_interp_type ist gl c) in | |
1762 | h_mutual_cofix (interp_ident ist gl id) (List.map f l) | |
1758 | 1763 | | TacCut c -> h_cut (pf_interp_type ist gl c) |
1759 | 1764 | | TacAssert (t,ipat,c) -> |
1760 | 1765 | let c = (if t=None then pf_interp_constr else pf_interp_type) ist gl c in |
1761 | 1766 | abstract_tactic (TacAssert (t,ipat,c)) |
1762 | 1767 | (Tactics.forward (option_map (interp_tactic ist) t) |
1763 | (interp_intro_pattern ist ipat) c) | |
1768 | (interp_intro_pattern ist gl ipat) c) | |
1764 | 1769 | | TacGeneralize cl -> h_generalize (List.map (pf_interp_constr ist gl) cl) |
1765 | 1770 | | TacGeneralizeDep c -> h_generalize_dep (pf_interp_constr ist gl c) |
1766 | 1771 | | TacLetTac (na,c,clp) -> |
1767 | 1772 | let clp = interp_clause ist gl clp in |
1768 | h_let_tac (interp_name ist na) (pf_interp_constr ist gl c) clp | |
1773 | h_let_tac (interp_name ist gl na) (pf_interp_constr ist gl c) clp | |
1769 | 1774 | (* | TacInstantiate (n,c,idh) -> h_instantiate n (fst c) |
1770 | 1775 | (* pf_interp_constr ist gl c *) |
1771 | 1776 | (match idh with |
1793 | 1798 | | TacNewInduction (lc,cbo,ids) -> |
1794 | 1799 | h_new_induction (List.map (interp_induction_arg ist gl) lc) |
1795 | 1800 | (option_map (interp_constr_with_bindings ist gl) cbo) |
1796 | (interp_intro_pattern ist ids) | |
1801 | (interp_intro_pattern ist gl ids) | |
1797 | 1802 | | TacSimpleDestruct h -> |
1798 | 1803 | h_simple_destruct (interp_quantified_hypothesis ist h) |
1799 | 1804 | | TacNewDestruct (c,cbo,ids) -> |
1800 | 1805 | h_new_destruct (List.map (interp_induction_arg ist gl) c) |
1801 | 1806 | (option_map (interp_constr_with_bindings ist gl) cbo) |
1802 | (interp_intro_pattern ist ids) | |
1807 | (interp_intro_pattern ist gl ids) | |
1803 | 1808 | | TacDoubleInduction (h1,h2) -> |
1804 | 1809 | let h1 = interp_quantified_hypothesis ist h1 in |
1805 | 1810 | let h2 = interp_quantified_hypothesis ist h2 in |
1819 | 1824 | | TacMove (dep,id1,id2) -> |
1820 | 1825 | h_move dep (interp_hyp ist gl id1) (interp_hyp ist gl id2) |
1821 | 1826 | | TacRename (id1,id2) -> |
1822 | h_rename (interp_hyp ist gl id1) (interp_ident ist (snd id2)) | |
1827 | h_rename (interp_hyp ist gl id1) (interp_ident ist gl (snd id2)) | |
1823 | 1828 | |
1824 | 1829 | (* Constructors *) |
1825 | 1830 | | TacLeft bl -> h_left (interp_bindings ist gl bl) |
1833 | 1838 | |
1834 | 1839 | (* Conversion *) |
1835 | 1840 | | TacReduce (r,cl) -> |
1836 | h_reduce (pf_redexp_interp ist gl r) (interp_clause ist gl cl) | |
1841 | h_reduce (pf_interp_red_expr ist gl r) (interp_clause ist gl cl) | |
1837 | 1842 | | TacChange (occl,c,cl) -> |
1838 | 1843 | h_change (option_map (pf_interp_pattern ist gl) occl) |
1839 | 1844 | (pf_interp_constr ist gl c) (interp_clause ist gl cl) |
1850 | 1855 | (interp_clause ist gl cl) |
1851 | 1856 | | TacInversion (DepInversion (k,c,ids),hyp) -> |
1852 | 1857 | Inv.dinv k (option_map (pf_interp_constr ist gl) c) |
1853 | (interp_intro_pattern ist ids) | |
1858 | (interp_intro_pattern ist gl ids) | |
1854 | 1859 | (interp_declared_or_quantified_hypothesis ist gl hyp) |
1855 | 1860 | | TacInversion (NonDepInversion (k,idl,ids),hyp) -> |
1856 | 1861 | Inv.inv_clause k |
1857 | (interp_intro_pattern ist ids) | |
1862 | (interp_intro_pattern ist gl ids) | |
1858 | 1863 | (List.map (interp_hyp ist gl) idl) |
1859 | 1864 | (interp_declared_or_quantified_hypothesis ist gl hyp) |
1860 | 1865 | | TacInversion (InversionUsing (c,idl),hyp) -> |
1873 | 1878 | | PreIdentArgType -> |
1874 | 1879 | failwith "pre-identifiers cannot be bound" |
1875 | 1880 | | IntroPatternArgType -> |
1876 | VIntroPattern (out_gen globwit_intro_pattern x) | |
1881 | VIntroPattern | |
1882 | (interp_intro_pattern ist gl (out_gen globwit_intro_pattern x)) | |
1877 | 1883 | | IdentArgType -> |
1878 | VIntroPattern (IntroIdentifier (out_gen globwit_ident x)) | |
1884 | VIntroPattern | |
1885 | (IntroIdentifier (interp_ident ist gl (out_gen globwit_ident x))) | |
1879 | 1886 | | VarArgType -> |
1880 | 1887 | VConstr (mkVar (interp_hyp ist gl (out_gen globwit_var x))) |
1881 | 1888 | | RefArgType -> |
1906 | 1913 | try tactic_of_value v gl |
1907 | 1914 | with NotTactic -> user_err_loc (loc,"",str "not a tactic") |
1908 | 1915 | |
1916 | let make_empty_glob_sign () = | |
1917 | { ltacvars = ([],[]); ltacrecvars = []; | |
1918 | gsigma = Evd.empty; genv = Global.env() } | |
1919 | ||
1909 | 1920 | (* Initial call for interpretation *) |
1910 | 1921 | let interp_tac_gen lfun debug t gl = |
1911 | 1922 | interp_tactic { lfun=lfun; debug=debug } |
1916 | 1927 | let eval_tactic t = interp_tactic { lfun=[]; debug=get_debug() } t |
1917 | 1928 | |
1918 | 1929 | let interp t = interp_tac_gen [] (get_debug()) t |
1930 | ||
1931 | let eval_ltac_constr gl t = | |
1932 | interp_ltac_constr { lfun=[]; debug=get_debug() } gl | |
1933 | (intern_tactic (make_empty_glob_sign ()) t ) | |
1919 | 1934 | |
1920 | 1935 | (* Hides interpretation for pretty-print *) |
1921 | 1936 | let hide_interp t ot gl = |
1964 | 1979 | | ArgVar _ as x -> x |
1965 | 1980 | | ArgArg x -> ArgArg (f x) |
1966 | 1981 | |
1967 | let subst_located f (_loc,id) = (loc,f id) | |
1982 | let subst_located f (_loc,id) = (dloc,f id) | |
1968 | 1983 | |
1969 | 1984 | let subst_reference subst = |
1970 | 1985 | subst_or_var (subst_located (subst_kn subst)) |
2106 | 2121 | |
2107 | 2122 | (* For extensions *) |
2108 | 2123 | | TacExtend (_loc,opn,l) -> |
2109 | TacExtend (loc,opn,List.map (subst_genarg subst) l) | |
2124 | TacExtend (dloc,opn,List.map (subst_genarg subst) l) | |
2110 | 2125 | | TacAlias (_,s,l,(dir,body)) -> |
2111 | TacAlias (loc,s,List.map (fun (id,a) -> (id,subst_genarg subst a)) l, | |
2126 | TacAlias (dloc,s,List.map (fun (id,a) -> (id,subst_genarg subst a)) l, | |
2112 | 2127 | (dir,subst_tactic subst body)) |
2113 | 2128 | |
2114 | 2129 | and subst_tactic subst (t:glob_tactic_expr) = match t with |
2115 | | TacAtom (_loc,t) -> TacAtom (loc, subst_atomic subst t) | |
2130 | | TacAtom (_loc,t) -> TacAtom (dloc, subst_atomic subst t) | |
2116 | 2131 | | TacFun tacfun -> TacFun (subst_tactic_fun subst tacfun) |
2117 | 2132 | | TacLetRecIn (lrc,u) -> |
2118 | 2133 | let lrc = List.map (fun (n,b) -> (n,subst_tactic_fun subst b)) lrc in |
2157 | 2172 | | TacDynamic(_,t) as x -> |
2158 | 2173 | (match tag t with |
2159 | 2174 | | "tactic" | "value" | "constr" -> x |
2160 | | s -> anomaly_loc (loc, "Tacinterp.val_interp", | |
2175 | | s -> anomaly_loc (dloc, "Tacinterp.val_interp", | |
2161 | 2176 | str "Unknown dynamic: <" ++ str s ++ str ">")) |
2162 | 2177 | |
2163 | 2178 | (* Reads the rules of a Match Context or a Match *) |
2280 | 2295 | str "There is already an Ltac named " ++ pr_id id); |
2281 | 2296 | kn |
2282 | 2297 | |
2283 | let make_empty_glob_sign () = | |
2284 | { ltacvars = ([],[]); ltacrecvars = []; | |
2285 | gsigma = Evd.empty; genv = Global.env() } | |
2286 | ||
2287 | 2298 | let add_tacdef isrec tacl = |
2288 | 2299 | (* let isrec = if !Options.p1 then isrec else true in*) |
2289 | 2300 | let rfun = List.map (fun ((loc,id as locid),_) -> (id,make_absolute_name locid)) tacl in |
2310 | 2321 | { ltacvars = (l,[]); ltacrecvars = []; gsigma = Evd.empty; genv = env }) |
2311 | 2322 | x |
2312 | 2323 | |
2313 | let interp_redexp env evc r = | |
2324 | let interp_redexp env sigma r = | |
2314 | 2325 | let ist = { lfun=[]; debug=get_debug () } in |
2315 | let gist = {(make_empty_glob_sign ()) with genv = env; gsigma = evc } in | |
2316 | redexp_interp ist evc env (intern_redexp gist r) | |
2326 | let gist = {(make_empty_glob_sign ()) with genv = env; gsigma = sigma } in | |
2327 | interp_red_expr ist sigma env (intern_red_expr gist r) | |
2317 | 2328 | |
2318 | 2329 | (***************************************************************************) |
2319 | 2330 | (* Backwarding recursive needs of tactic glob/interp/eval functions *) |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (*i $Id: tacinterp.mli 7841 2006-01-11 11:24:54Z herbelin $ i*) | |
8 | (*i $Id: tacinterp.mli 8975 2006-06-23 08:52:53Z herbelin $ i*) | |
9 | 9 | |
10 | 10 | (*i*) |
11 | 11 | open Dyn |
12 | 12 | open Pp |
13 | open Util | |
13 | 14 | open Names |
14 | 15 | open Proof_type |
15 | 16 | open Tacmach |
19 | 20 | open Genarg |
20 | 21 | open Topconstr |
21 | 22 | open Mod_subst |
23 | open Redexpr | |
22 | 24 | (*i*) |
23 | 25 | |
24 | 26 | (* Values for interpretation *) |
37 | 39 | and interp_sign = |
38 | 40 | { lfun : (identifier * value) list; |
39 | 41 | debug : debug_info } |
40 | ||
41 | (* Gives the identifier corresponding to an Identifier [tactic_arg] *) | |
42 | val id_of_Identifier : Environ.env -> value -> identifier | |
43 | ||
44 | (* Gives the constr corresponding to a Constr [value] *) | |
45 | val constr_of_VConstr : Environ.env -> value -> constr | |
46 | 42 | |
47 | 43 | (* Transforms an id into a constr if possible *) |
48 | 44 | val constr_of_id : Environ.env -> identifier -> constr |
102 | 98 | (* Interprets any expression *) |
103 | 99 | val val_interp : interp_sign -> goal sigma -> glob_tactic_expr -> value |
104 | 100 | |
101 | (* Interprets an expression that evaluates to a constr *) | |
102 | val interp_ltac_constr : interp_sign -> goal sigma -> glob_tactic_expr -> | |
103 | constr | |
104 | ||
105 | 105 | (* Interprets redexp arguments *) |
106 | val interp_redexp : Environ.env -> Evd.evar_map -> raw_red_expr | |
107 | -> Redexpr.red_expr | |
106 | val interp_redexp : Environ.env -> Evd.evar_map -> raw_red_expr -> red_expr | |
108 | 107 | |
109 | 108 | (* Interprets tactic expressions *) |
110 | 109 | val interp_tac_gen : (identifier * value) list -> |
111 | 110 | debug_info -> raw_tactic_expr -> tactic |
112 | 111 | |
113 | val interp_hyp : interp_sign -> goal sigma -> | |
114 | identifier Util.located -> identifier | |
112 | val interp_hyp : interp_sign -> goal sigma -> identifier located -> identifier | |
115 | 113 | |
116 | 114 | (* Initial call for interpretation *) |
117 | 115 | val glob_tactic : raw_tactic_expr -> glob_tactic_expr |
121 | 119 | val eval_tactic : glob_tactic_expr -> tactic |
122 | 120 | |
123 | 121 | val interp : raw_tactic_expr -> tactic |
122 | ||
123 | val eval_ltac_constr : goal sigma -> raw_tactic_expr -> constr | |
124 | 124 | |
125 | 125 | val subst_tactic : substitution -> glob_tactic_expr -> glob_tactic_expr |
126 | 126 |
0 | (* A check that sort-polymorphic product is not set too low *) | |
1 | ||
2 | Inductive prod (A B:Type) : Type := pair : A -> B -> prod A B. | |
3 | Check (fun (A:Type) (B:Prop) => (prod A B : Prop)). |
0 | (* A check that sort-polymorphic product is not set too low *) | |
1 | ||
2 | Inductive prod (A B:Type) : Type := pair : A -> B -> prod A B. | |
3 | Check (fun (A:Prop) (B:Type) => (prod A B : Prop)). |
0 | (* Check that the nested inductive types positivity check avoids recursively | |
1 | non uniform parameters (at least if these parameters break positivity) *) | |
2 | ||
3 | Inductive t (A:Type) : Type := c : t (A -> A) -> t A. | |
4 | Inductive u : Type := d : u | e : t u -> u. |
0 | (* Bug #1172 *) | |
1 | ||
2 | Structure foo : Type := Foo { | |
3 | A : Set; Aopt := option A; unopt : Aopt -> A | |
4 | }. | |
5 | ||
6 | Canonical Structure unopt_nat := @Foo nat (fun _ => O). |
2 | 2 | Definition g x := |
3 | 3 | match x with ((((1 as x),_) | (_,x)), (_,(2 as y))|(y,_)) => (x,y) end. |
4 | 4 | |
5 | Eval compute in (g ((1,2),(3,4))). | |
6 | (* (1,3) *) | |
5 | Check (refl_equal _ : g ((1,2),(3,4)) = (1,3)). | |
7 | 6 | |
8 | Eval compute in (g ((1,4),(3,2))). | |
9 | (* (1,2) *) | |
7 | Check (refl_equal _ : g ((1,4),(3,2)) = (1,2)). | |
10 | 8 | |
9 | Fixpoint max (n m:nat) {struct m} : nat := | |
10 | match n, m with | |
11 | | S n', S m' => S (max n' m') | |
12 | | 0, p | p, 0 => p | |
13 | end. |
0 | (* This used to fail in Coq version 8.1 beta due to a non variable | |
1 | universe (issued by the inductive sort-polymorphism) being sent by | |
2 | pretyping to the kernel (bug #1182) *) | |
3 | ||
4 | Variable T : Type. | |
5 | Variable x : nat*nat. | |
6 | ||
7 | Check let (_, _) := x in sigT (fun _ : T => nat). |
27 | 27 | intros n m. |
28 | 28 | functional induction ftest n m; auto. |
29 | 29 | Qed. |
30 | ||
31 | Lemma test2 : forall m n, ~ 2 = ftest n m. | |
32 | Proof. | |
33 | intros n m;intro H. | |
34 | functional inversion H ftest. | |
35 | Qed. | |
36 | ||
37 | Lemma test3 : forall n m, ftest n m = 0 -> (n = 0 /\ m = 0) \/ n <> 0. | |
38 | Proof. | |
39 | functional inversion 1 ftest;auto. | |
40 | Qed. | |
41 | ||
30 | 42 | |
31 | 43 | Require Import Arith. |
32 | 44 | Lemma test11 : forall m : nat, ftest 0 m <= 2. |
111 | 123 | | S (S m) => iseven m |
112 | 124 | | _ => false |
113 | 125 | end. |
114 | ||
126 | ||
127 | ||
115 | 128 | Function funex (n : nat) : nat := |
116 | 129 | match iseven n with |
117 | 130 | | true => n |
121 | 134 | end |
122 | 135 | end. |
123 | 136 | |
137 | ||
124 | 138 | Function nat_equal_bool (n m : nat) {struct n} : bool := |
125 | 139 | match n with |
126 | 140 | | O => match m with |
150 | 164 | |
151 | 165 | (* reuse this lemma as a scheme:*) |
152 | 166 | |
153 | ||
154 | 167 | Function nested_lam (n : nat) : nat -> nat := |
155 | 168 | match n with |
156 | 169 | | O => fun m : nat => 0 |
183 | 196 | auto with arith. |
184 | 197 | Qed. |
185 | 198 | |
186 | ||
187 | 199 | Function plus_x_not_five'' (n m : nat) {struct n} : nat := |
188 | 200 | let x := nat_equal_bool m 5 in |
189 | 201 | let y := 0 in |
205 | 217 | Lemma iseq_eq : forall n m : nat, n = m -> nat_equal_bool n m = true. |
206 | 218 | intros n m. |
207 | 219 | functional induction nat_equal_bool n m; simpl in |- *; intros hyp; auto. |
208 | rewrite <- hyp in H1; simpl in H1;tauto. | |
220 | rewrite <- hyp in y; simpl in y;tauto. | |
209 | 221 | inversion hyp. |
210 | 222 | Qed. |
211 | 223 | |
279 | 291 | destruct n. inversion istr. |
280 | 292 | destruct n. inversion istr. |
281 | 293 | destruct n. tauto. |
282 | simpl in *. inversion H1. | |
294 | simpl in *. inversion H0. | |
283 | 295 | Qed. |
284 | 296 | |
285 | 297 | Lemma toto' : forall n m : nat, n = 4 -> istrue (isononeorfour n). |
286 | 298 | intros n. |
287 | 299 | functional induction isononeorfour n; intros m istr; inversion istr. |
288 | 300 | apply istrue0. |
289 | rewrite H in H0; simpl in H0;tauto. | |
301 | rewrite H in y; simpl in y;tauto. | |
290 | 302 | Qed. |
291 | 303 | |
292 | 304 | Function ftest4 (n m : nat) : nat := |
352 | 364 | | S p => ftest2 p m |
353 | 365 | end. |
354 | 366 | |
355 | Lemma test2 : forall n m : nat, ftest2 n m <= 2. | |
367 | Lemma test2' : forall n m : nat, ftest2 n m <= 2. | |
356 | 368 | intros n m. |
357 | 369 | functional induction ftest2 n m; simpl in |- *; intros; auto. |
358 | 370 | Qed. |
366 | 378 | end |
367 | 379 | end. |
368 | 380 | |
369 | Lemma test3 : forall n m : nat, ftest3 n m <= 2. | |
381 | Lemma test3' : forall n m : nat, ftest3 n m <= 2. | |
370 | 382 | intros n m. |
371 | 383 | functional induction ftest3 n m. |
372 | 384 | intros. |
441 | 453 | functional induction ftest6 n m; simpl in |- *; auto. |
442 | 454 | Qed. |
443 | 455 | |
444 | ||
445 | ||
446 | ||
447 | ||
448 | ||
449 | ||
450 | ||
451 | ||
452 | ||
453 | ||
454 | ||
455 | ||
456 | (* Some tests with modules *) | |
457 | Module M. | |
458 | Function test_m (n:nat) : nat := | |
459 | match n with | |
460 | | 0 => 0 | |
461 | | S n => S (S (test_m n)) | |
462 | end. | |
463 | ||
464 | Lemma test_m_is_double : forall n, div2 (test_m n) = n. | |
465 | Proof. | |
466 | intros n. | |
467 | functional induction (test_m n). | |
468 | reflexivity. | |
469 | simpl;rewrite IHn0;reflexivity. | |
470 | Qed. | |
471 | End M. | |
472 | (* We redefine a new Function with the same name *) | |
473 | Function test_m (n:nat) : nat := | |
474 | pred n. | |
475 | ||
476 | Lemma test_m_is_pred : forall n, test_m n = pred n. | |
477 | Proof. | |
478 | intro n. | |
479 | functional induction (test_m n). (* the test_m_ind to use is the last defined saying that test_m = pred*) | |
480 | reflexivity. | |
481 | Qed. | |
482 | ||
483 | (* Checks if the dot notation are correctly treated in infos *) | |
484 | Lemma M_test_m_is_double : forall n, div2 (M.test_m n) = n. | |
485 | intro n. | |
486 | (* here we should apply M.test_m_ind *) | |
487 | functional induction (M.test_m n). | |
488 | reflexivity. | |
489 | simpl;rewrite IHn0;reflexivity. | |
490 | Qed. | |
491 | ||
492 | Import M. | |
493 | (* Now test_m is the one which defines double *) | |
494 | ||
495 | Lemma test_m_is_double : forall n, div2 (M.test_m n) = n. | |
496 | intro n. | |
497 | (* here we should apply M.test_m_ind *) | |
498 | functional induction (test_m n). | |
499 | reflexivity. | |
500 | simpl;rewrite IHn0;reflexivity. | |
501 | Qed. | |
502 | ||
503 | ||
504 | ||
505 | ||
506 | ||
507 | ||
508 | ||
509 |
8 | 8 | |
9 | 9 | (* Finite map library. *) |
10 | 10 | |
11 | (* $Id: FMapAVL.v 8899 2006-06-06 11:09:43Z jforest $ *) | |
11 | (* $Id: FMapAVL.v 8985 2006-06-23 16:12:45Z jforest $ *) | |
12 | 12 | |
13 | 13 | (** This module implements map using AVL trees. |
14 | 14 | It follows the implementation from Ocaml's standard library. *) |
511 | 511 | (* LT *) |
512 | 512 | inv avl. |
513 | 513 | rewrite bal_in; auto. |
514 | rewrite (IHt H1); intuition_in. | |
514 | rewrite (IHt H0); intuition_in. | |
515 | 515 | (* EQ *) |
516 | 516 | inv avl. |
517 | 517 | firstorder_in. |
519 | 519 | (* GT *) |
520 | 520 | inv avl. |
521 | 521 | rewrite bal_in; auto. |
522 | rewrite (IHt H2); intuition_in. | |
522 | rewrite (IHt H1); intuition_in. | |
523 | 523 | Qed. |
524 | 524 | |
525 | 525 | Lemma add_bst : forall elt (m:t elt) x e, bst m -> avl m -> bst (add x e m). |
529 | 529 | (* lt_tree -> lt_tree (add ...) *) |
530 | 530 | red; red in H4. |
531 | 531 | intros. |
532 | rewrite (add_in x y0 e H) in H1. | |
532 | rewrite (add_in x y0 e H) in H0. | |
533 | 533 | intuition. |
534 | 534 | eauto. |
535 | 535 | (* gt_tree -> gt_tree (add ...) *) |
536 | red; red in H5. | |
536 | red; red in H4. | |
537 | 537 | intros. |
538 | rewrite (add_in x y0 e H6) in H1. | |
538 | rewrite (add_in x y0 e H5) in H0. | |
539 | 539 | intuition. |
540 | 540 | apply lt_eq with x; auto. |
541 | 541 | Qed. |
590 | 590 | inversion_clear H. |
591 | 591 | destruct (IHp lh); auto. |
592 | 592 | split; simpl in *. |
593 | rewrite_all H0. simpl in *. | |
593 | rewrite_all e1. simpl in *. | |
594 | 594 | apply bal_avl; subst;auto; omega_max. |
595 | rewrite_all H0;simpl in *;omega_bal. | |
595 | rewrite_all e1;simpl in *;omega_bal. | |
596 | 596 | Qed. |
597 | 597 | |
598 | 598 | Lemma remove_min_avl : forall elt (l:t elt) x e r h, avl (Node l x e r h) -> |
609 | 609 | intuition_in. |
610 | 610 | (* l = Node *) |
611 | 611 | inversion_clear H. |
612 | generalize (remove_min_avl H1). | |
612 | generalize (remove_min_avl H0). | |
613 | 613 | |
614 | rewrite_all H0; simpl; intros. | |
614 | rewrite_all e1; simpl; intros. | |
615 | 615 | rewrite bal_in; auto. |
616 | generalize (IHp lh y H1). | |
616 | generalize (IHp lh y H0). | |
617 | 617 | intuition. |
618 | inversion_clear H8; intuition. | |
618 | inversion_clear H7; intuition. | |
619 | 619 | Qed. |
620 | 620 | |
621 | 621 | Lemma remove_min_mapsto : forall elt (l:t elt) x e r h y e', avl (Node l x e r h) -> |
627 | 627 | intuition_in; subst; auto. |
628 | 628 | (* l = Node *) |
629 | 629 | inversion_clear H. |
630 | generalize (remove_min_avl H1). | |
631 | rewrite_all H0; simpl; intros. | |
630 | generalize (remove_min_avl H0). | |
631 | rewrite_all e1; simpl; intros. | |
632 | 632 | rewrite bal_mapsto; auto; unfold create. |
633 | 633 | simpl in *;destruct (IHp lh y e'). |
634 | 634 | auto. |
635 | 635 | intuition. |
636 | inversion_clear H3; intuition. | |
637 | inversion_clear H10; intuition. | |
636 | inversion_clear H2; intuition. | |
637 | inversion_clear H9; intuition. | |
638 | 638 | Qed. |
639 | 639 | |
640 | 640 | Lemma remove_min_bst : forall elt (l:t elt) x e r h, |
642 | 642 | Proof. |
643 | 643 | intros elt l x e r; functional induction (remove_min l x e r); simpl in *; intros. |
644 | 644 | inv bst; auto. |
645 | inversion_clear H; inversion_clear H1. | |
645 | inversion_clear H; inversion_clear H0. | |
646 | 646 | apply bal_bst; auto. |
647 | rewrite_all H0;simpl in *;firstorder. | |
647 | rewrite_all e1;simpl in *;firstorder. | |
648 | 648 | intro; intros. |
649 | 649 | generalize (remove_min_in y H). |
650 | rewrite_all H0; simpl in *. | |
650 | rewrite_all e1; simpl in *. | |
651 | 651 | destruct 1. |
652 | apply H4; intuition. | |
652 | apply H3; intuition. | |
653 | 653 | Qed. |
654 | 654 | |
655 | 655 | Lemma remove_min_gt_tree : forall elt (l:t elt) x e r h, |
658 | 658 | Proof. |
659 | 659 | intros elt l x e r; functional induction (remove_min l x e r); simpl in *; intros. |
660 | 660 | inv bst; auto. |
661 | inversion_clear H; inversion_clear H1. | |
661 | inversion_clear H; inversion_clear H0. | |
662 | 662 | intro; intro. |
663 | rewrite_all H0;simpl in *. | |
664 | generalize (IHp lh H2 H); clear H7 H8 IHp. | |
663 | rewrite_all e1;simpl in *. | |
664 | generalize (IHp lh H1 H); clear H7 H6 IHp. | |
665 | 665 | generalize (remove_min_avl H). |
666 | 666 | generalize (remove_min_in (fst m) H). |
667 | rewrite H0; simpl; intros. | |
668 | rewrite (bal_in x e y H8 H6) in H1. | |
669 | destruct H7. | |
667 | rewrite e1; simpl; intros. | |
668 | rewrite (bal_in x e y H7 H5) in H0. | |
669 | destruct H6. | |
670 | 670 | firstorder. |
671 | 671 | apply lt_eq with x; auto. |
672 | 672 | apply X.lt_trans with x; auto. |
695 | 695 | Proof. |
696 | 696 | intros elt s1 s2; functional induction (merge s1 s2); simpl in *; intros. |
697 | 697 | split; auto; avl_nns; omega_max. |
698 | destruct s1;try contradiction;clear H1. | |
698 | destruct s1;try contradiction;clear y. | |
699 | 699 | split; auto; avl_nns; simpl in *; omega_max. |
700 | destruct s1;try contradiction;clear H1. | |
700 | destruct s1;try contradiction;clear y. | |
701 | 701 | generalize (remove_min_avl_1 H0). |
702 | rewrite H2; simpl;destruct 1. | |
702 | rewrite e3; simpl;destruct 1. | |
703 | 703 | split. |
704 | 704 | apply bal_avl; auto. |
705 | 705 | simpl; omega_max. |
718 | 718 | intros elt s1 s2; functional induction (merge s1 s2);intros. |
719 | 719 | intuition_in. |
720 | 720 | intuition_in. |
721 | destruct s1;try contradiction;clear H1. | |
721 | destruct s1;try contradiction;clear y. | |
722 | 722 | (* rewrite H_eq_2; rewrite H_eq_2 in H_eq_1; clear H_eq_2. *) |
723 | replace s2' with (fst (remove_min l2 x2 e2 r2)); [|rewrite H2; auto]. | |
723 | replace s2' with (fst (remove_min l2 x2 e2 r2)); [|rewrite e3; auto]. | |
724 | 724 | rewrite bal_in; auto. |
725 | generalize (remove_min_avl H4); rewrite H2; simpl; auto. | |
726 | generalize (remove_min_in y H4); rewrite H2; simpl; intro. | |
727 | rewrite H1; intuition. | |
725 | generalize (remove_min_avl H2); rewrite e3; simpl; auto. | |
726 | generalize (remove_min_in y0 H2); rewrite e3; simpl; intro. | |
727 | rewrite H3; intuition. | |
728 | 728 | Qed. |
729 | 729 | |
730 | 730 | Lemma merge_mapsto : forall elt (s1 s2:t elt) y e, bst s1 -> avl s1 -> bst s2 -> avl s2 -> |
733 | 733 | intros elt s1 s2; functional induction (@merge elt s1 s2); intros. |
734 | 734 | intuition_in. |
735 | 735 | intuition_in. |
736 | destruct s1;try contradiction;clear H1. | |
737 | replace s2' with (fst (remove_min l2 x2 e2 r2)); [|rewrite H2; auto]. | |
736 | destruct s1;try contradiction;clear y. | |
737 | replace s2' with (fst (remove_min l2 x2 e2 r2)); [|rewrite e3; auto]. | |
738 | 738 | rewrite bal_mapsto; auto; unfold create. |
739 | generalize (remove_min_avl H4); rewrite H2; simpl; auto. | |
740 | generalize (remove_min_mapsto y e0 H4); rewrite H2; simpl; intro. | |
741 | rewrite H1; intuition (try subst; auto). | |
742 | inversion_clear H1; intuition. | |
739 | generalize (remove_min_avl H2); rewrite e3; simpl; auto. | |
740 | generalize (remove_min_mapsto y0 e H2); rewrite e3; simpl; intro. | |
741 | rewrite H3; intuition (try subst; auto). | |
742 | inversion_clear H3; intuition. | |
743 | 743 | Qed. |
744 | 744 | |
745 | 745 | Lemma merge_bst : forall elt (s1 s2:t elt), bst s1 -> avl s1 -> bst s2 -> avl s2 -> |
750 | 750 | |
751 | 751 | apply bal_bst; auto. |
752 | 752 | destruct s1;try contradiction. |
753 | generalize (remove_min_bst H3); rewrite H2; simpl in *; auto. | |
753 | generalize (remove_min_bst H1); rewrite e3; simpl in *; auto. | |
754 | 754 | destruct s1;try contradiction. |
755 | 755 | intro; intro. |
756 | apply H5; auto. | |
757 | generalize (remove_min_in x H4); rewrite H2; simpl; intuition. | |
756 | apply H3; auto. | |
757 | generalize (remove_min_in x H2); rewrite e3; simpl; intuition. | |
758 | 758 | destruct s1;try contradiction. |
759 | generalize (remove_min_gt_tree H3); rewrite H2; simpl; auto. | |
759 | generalize (remove_min_gt_tree H1); rewrite e3; simpl; auto. | |
760 | 760 | Qed. |
761 | 761 | |
762 | 762 | (** * Deletion *) |
778 | 778 | split; auto; omega_max. |
779 | 779 | (* LT *) |
780 | 780 | inv avl. |
781 | destruct (IHt H1). | |
781 | destruct (IHt H0). | |
782 | 782 | split. |
783 | 783 | apply bal_avl; auto. |
784 | 784 | omega_max. |
785 | 785 | omega_bal. |
786 | 786 | (* EQ *) |
787 | 787 | inv avl. |
788 | generalize (merge_avl_1 H1 H2 H3). | |
788 | generalize (merge_avl_1 H0 H1 H2). | |
789 | 789 | intuition omega_max. |
790 | 790 | (* GT *) |
791 | 791 | inv avl. |
792 | destruct (IHt H2). | |
792 | destruct (IHt H1). | |
793 | 793 | split. |
794 | 794 | apply bal_avl; auto. |
795 | 795 | omega_max. |
808 | 808 | intros elt s x; functional induction (@remove elt x s); simpl; intros. |
809 | 809 | intuition_in. |
810 | 810 | (* LT *) |
811 | inv avl; inv bst; clear H0. | |
811 | inv avl; inv bst; clear e1. | |
812 | 812 | rewrite bal_in; auto. |
813 | generalize (IHt y0 H1); intuition; [ order | order | intuition_in ]. | |
813 | generalize (IHt y0 H0); intuition; [ order | order | intuition_in ]. | |
814 | 814 | (* EQ *) |
815 | inv avl; inv bst; clear H0. | |
815 | inv avl; inv bst; clear e1. | |
816 | 816 | rewrite merge_in; intuition; [ order | order | intuition_in ]. |
817 | 817 | elim H9; eauto. |
818 | 818 | (* GT *) |
819 | inv avl; inv bst; clear H0. | |
819 | inv avl; inv bst; clear e1. | |
820 | 820 | rewrite bal_in; auto. |
821 | generalize (IHt y0 H6); intuition; [ order | order | intuition_in ]. | |
821 | generalize (IHt y0 H5); intuition; [ order | order | intuition_in ]. | |
822 | 822 | Qed. |
823 | 823 | |
824 | 824 | Lemma remove_bst : forall elt (s:t elt) x, bst s -> avl s -> bst (remove x s). |
829 | 829 | inv avl; inv bst. |
830 | 830 | apply bal_bst; auto. |
831 | 831 | intro; intro. |
832 | rewrite (remove_in x y0 H1) in H; auto. | |
832 | rewrite (remove_in x y0 H0) in H; auto. | |
833 | 833 | destruct H; eauto. |
834 | 834 | (* EQ *) |
835 | 835 | inv avl; inv bst. |
838 | 838 | inv avl; inv bst. |
839 | 839 | apply bal_bst; auto. |
840 | 840 | intro; intro. |
841 | rewrite (remove_in x y0 H6) in H; auto. | |
841 | rewrite (remove_in x y0 H5) in H; auto. | |
842 | 842 | destruct H; eauto. |
843 | 843 | Qed. |
844 | 844 |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (***********************************************************************) |
7 | 7 | |
8 | (* $Id: FMapList.v 8899 2006-06-06 11:09:43Z jforest $ *) | |
8 | (* $Id: FMapList.v 9035 2006-07-09 15:42:09Z herbelin $ *) | |
9 | 9 | |
10 | 10 | (** * Finite map library *) |
11 | 11 | |
18 | 18 | |
19 | 19 | Set Implicit Arguments. |
20 | 20 | Unset Strict Implicit. |
21 | ||
22 | Arguments Scope list [type_scope]. | |
23 | 21 | |
24 | 22 | Module Raw (X:OrderedType). |
25 | 23 | |
160 | 158 | inversion 2. |
161 | 159 | |
162 | 160 | inversion_clear 2. |
163 | clear H0;compute in H1; destruct H1;order. | |
164 | clear H0;generalize (Sort_In_cons_1 Hm (InA_eqke_eqk H1)); compute; order. | |
165 | ||
166 | clear H0;inversion_clear 2. | |
161 | clear e1;compute in H0; destruct H0;order. | |
162 | clear e1;generalize (Sort_In_cons_1 Hm (InA_eqke_eqk H0)); compute; order. | |
163 | ||
164 | clear e1;inversion_clear 2. | |
167 | 165 | compute in H0; destruct H0; intuition congruence. |
168 | 166 | generalize (Sort_In_cons_1 Hm (InA_eqke_eqk H0)); compute; order. |
169 | 167 | |
170 | clear H0; do 2 inversion_clear 1; auto. | |
168 | clear e1; do 2 inversion_clear 1; auto. | |
171 | 169 | compute in H2; destruct H2; order. |
172 | 170 | Qed. |
173 | 171 | |
196 | 194 | Proof. |
197 | 195 | intros m x y e e'. |
198 | 196 | generalize y e; clear y e; unfold PX.MapsTo. |
199 | functional induction (add x e' m) ;simpl;auto; clear H0. | |
197 | functional induction (add x e' m) ;simpl;auto; clear e0. | |
200 | 198 | subst;auto. |
201 | 199 | |
202 | 200 | intros y' e'' eqky'; inversion_clear 1; destruct H0; simpl in *. |
213 | 211 | intros m x y e e'. generalize y e; clear y e; unfold PX.MapsTo. |
214 | 212 | functional induction (add x e' m);simpl; intros. |
215 | 213 | apply (In_inv_3 H0); compute; auto. |
216 | apply (In_inv_3 H1); compute; auto. | |
217 | constructor 2; apply (In_inv_3 H1); compute; auto. | |
218 | inversion_clear H1; auto. | |
214 | apply (In_inv_3 H0); compute; auto. | |
215 | constructor 2; apply (In_inv_3 H0); compute; auto. | |
216 | inversion_clear H0; auto. | |
219 | 217 | Qed. |
220 | 218 | |
221 | 219 | |
264 | 262 | red; inversion 1; inversion H1. |
265 | 263 | |
266 | 264 | apply Sort_Inf_NotIn with x0; auto. |
267 | clear H0;constructor; compute; order. | |
265 | clear e0;constructor; compute; order. | |
268 | 266 | |
269 | clear H0;inversion_clear Hm. | |
267 | clear e0;inversion_clear Hm. | |
270 | 268 | apply Sort_Inf_NotIn with x0; auto. |
271 | 269 | apply Inf_eq with (k',x0);auto; compute; apply X.eq_trans with x; auto. |
272 | 270 | |
273 | clear H0;inversion_clear Hm. | |
271 | clear e0;inversion_clear Hm. | |
274 | 272 | assert (notin:~ In y (remove x l)) by auto. |
275 | 273 | intros (x1,abs). |
276 | 274 | inversion_clear abs. |
392 | 390 | |
393 | 391 | |
394 | 392 | assert (cmp_e_e':cmp e e' = true). |
395 | apply H2 with x; auto. | |
393 | apply H1 with x; auto. | |
396 | 394 | rewrite cmp_e_e'; simpl. |
397 | 395 | apply IHb; auto. |
398 | 396 | inversion_clear Hm; auto. |
401 | 399 | destruct (H0 k). |
402 | 400 | assert (In k ((x,e) ::l)). |
403 | 401 | destruct H as (e'', hyp); exists e''; auto. |
404 | destruct (In_inv (H1 H4)); auto. | |
402 | destruct (In_inv (H2 H4)); auto. | |
405 | 403 | inversion_clear Hm. |
406 | 404 | elim (Sort_Inf_NotIn H6 H7). |
407 | 405 | destruct H as (e'', hyp); exists e''; auto. |
414 | 412 | elim (Sort_Inf_NotIn H6 H7). |
415 | 413 | destruct H as (e'', hyp); exists e''; auto. |
416 | 414 | apply MapsTo_eq with k; auto; order. |
417 | apply H2 with k; destruct (eq_dec x k); auto. | |
418 | ||
419 | ||
420 | destruct (X.compare x x'); try contradiction;clear H2. | |
415 | apply H1 with k; destruct (eq_dec x k); auto. | |
416 | ||
417 | ||
418 | destruct (X.compare x x'); try contradiction; clear y. | |
421 | 419 | destruct (H0 x). |
422 | 420 | assert (In x ((x',e')::l')). |
423 | 421 | apply H; auto. |
491 | 489 | |
492 | 490 | inversion_clear Hm;inversion_clear Hm'. |
493 | 491 | destruct (andb_prop _ _ H); clear H. |
494 | destruct (IHb H1 H4 H7). | |
492 | destruct (IHb H2 H4 H7). | |
495 | 493 | inversion_clear H0. |
496 | 494 | destruct H9; simpl in *; subst. |
497 | inversion_clear H2. | |
495 | inversion_clear H1. | |
498 | 496 | destruct H9; simpl in *; subst; auto. |
499 | 497 | elim (Sort_Inf_NotIn H4 H5). |
500 | 498 | exists e'0; apply MapsTo_eq with k; auto; order. |
501 | inversion_clear H2. | |
499 | inversion_clear H1. | |
502 | 500 | destruct H0; simpl in *; subst; auto. |
503 | elim (Sort_Inf_NotIn H1 H3). | |
501 | elim (Sort_Inf_NotIn H2 H3). | |
504 | 502 | exists e0; apply MapsTo_eq with k; auto; order. |
505 | 503 | apply H8 with k; auto. |
506 | 504 | Qed. |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (***********************************************************************) |
7 | 7 | |
8 | (* $Id: FMapWeakList.v 8899 2006-06-06 11:09:43Z jforest $ *) | |
8 | (* $Id: FMapWeakList.v 8985 2006-06-23 16:12:45Z jforest $ *) | |
9 | 9 | |
10 | 10 | (** * Finite map library *) |
11 | 11 | |
103 | 103 | inversion belong1. inversion H. |
104 | 104 | inversion_clear NoDup. |
105 | 105 | inversion_clear belong1. |
106 | inversion_clear H2. | |
107 | compute in H3; destruct H3. | |
106 | inversion_clear H1. | |
107 | compute in H2; destruct H2. | |
108 | 108 | contradiction. |
109 | 109 | apply IHb; auto. |
110 | 110 | exists x0; auto. |
143 | 143 | inversion 2. |
144 | 144 | |
145 | 145 | do 2 inversion_clear 1. |
146 | compute in H3; destruct H3; subst; trivial. | |
146 | compute in H2; destruct H2; subst; trivial. | |
147 | 147 | elim H; apply InA_eqk with (x,e); auto. |
148 | 148 | |
149 | 149 | do 2 inversion_clear 1; auto. |
150 | compute in H3; destruct H3; elim _x; auto. | |
150 | compute in H2; destruct H2; elim _x; auto. | |
151 | 151 | Qed. |
152 | 152 | |
153 | 153 | (* Not part of the exported specifications, used later for [combine]. *) |
183 | 183 | intros m x y e e'; generalize y e; clear y e; unfold PX.MapsTo. |
184 | 184 | functional induction (add x e' m);simpl;auto. |
185 | 185 | intros y' e'' eqky'; inversion_clear 1. |
186 | destruct H1; simpl in *. | |
186 | destruct H0; simpl in *. | |
187 | 187 | elim eqky'; apply X.eq_trans with k'; auto. |
188 | 188 | auto. |
189 | 189 | intros y' e'' eqky'; inversion_clear 1; intuition. |
195 | 195 | intros m x y e e'. generalize y e; clear y e; unfold PX.MapsTo. |
196 | 196 | functional induction (add x e' m);simpl;auto. |
197 | 197 | intros; apply (In_inv_3 H0); auto. |
198 | constructor 2; apply (In_inv_3 H1); auto. | |
198 | constructor 2; apply (In_inv_3 H0); auto. | |
199 | 199 | inversion_clear 2; auto. |
200 | 200 | Qed. |
201 | 201 | |
207 | 207 | inversion_clear 2. |
208 | 208 | compute in H1; elim H; auto. |
209 | 209 | inversion H1. |
210 | constructor 2; inversion_clear H1; auto. | |
211 | compute in H2; elim H; auto. | |
210 | constructor 2; inversion_clear H0; auto. | |
211 | compute in H1; elim H; auto. | |
212 | 212 | inversion_clear 2; auto. |
213 | 213 | Qed. |
214 | 214 | |
271 | 271 | |
272 | 272 | inversion_clear Hm. |
273 | 273 | subst. |
274 | swap H1. | |
275 | destruct H3 as (e,H3); unfold PX.MapsTo in H3. | |
274 | swap H0. | |
275 | destruct H2 as (e,H2); unfold PX.MapsTo in H2. | |
276 | 276 | apply InA_eqk with (y,e); auto. |
277 | 277 | compute; apply X.eq_trans with x; auto. |
278 | 278 | |
279 | 279 | intro H2. |
280 | 280 | destruct H2 as (e,H2); inversion_clear H2. |
281 | compute in H1; destruct H1. | |
281 | compute in H0; destruct H0. | |
282 | 282 | elim _x; apply X.eq_trans with y; auto. |
283 | 283 | inversion_clear Hm. |
284 | elim (IHt0 H3 H). | |
284 | elim (IHt0 H2 H). | |
285 | 285 | exists e; auto. |
286 | 286 | Qed. |
287 | 287 | |
291 | 291 | intros m Hm x y e; generalize Hm; clear Hm; unfold PX.MapsTo. |
292 | 292 | functional induction (remove x m);auto. |
293 | 293 | inversion_clear 3; auto. |
294 | compute in H2; destruct H2. | |
294 | compute in H1; destruct H1. | |
295 | 295 | elim H; apply X.eq_trans with k'; auto. |
296 | 296 | |
297 | 297 | inversion_clear 1; inversion_clear 2; auto. |
11 | 11 | * Institution: LRI, CNRS UMR 8623 - Université Paris Sud |
12 | 12 | * 91405 Orsay, France *) |
13 | 13 | |
14 | (* $Id: FSetAVL.v 8899 2006-06-06 11:09:43Z jforest $ *) | |
14 | (* $Id: FSetAVL.v 8985 2006-06-23 16:12:45Z jforest $ *) | |
15 | 15 | |
16 | 16 | (** This module implements sets using AVL trees. |
17 | 17 | It follows the implementation from Ocaml's standard library. *) |
514 | 514 | (* LT *) |
515 | 515 | inv avl. |
516 | 516 | rewrite bal_in; auto. |
517 | rewrite (IHt y0 H1); intuition_in. | |
517 | rewrite (IHt y0 H0); intuition_in. | |
518 | 518 | (* EQ *) |
519 | 519 | inv avl. |
520 | 520 | intuition. |
522 | 522 | (* GT *) |
523 | 523 | inv avl. |
524 | 524 | rewrite bal_in; auto. |
525 | rewrite (IHt y0 H2); intuition_in. | |
525 | rewrite (IHt y0 H1); intuition_in. | |
526 | 526 | Qed. |
527 | 527 | |
528 | 528 | Lemma add_bst : forall s x, bst s -> avl s -> bst (add x s). |
530 | 530 | intros s x; functional induction (add x s); auto; intros. |
531 | 531 | inv bst; inv avl; apply bal_bst; auto. |
532 | 532 | (* lt_tree -> lt_tree (add ...) *) |
533 | red; red in H5. | |
533 | red; red in H4. | |
534 | 534 | intros. |
535 | rewrite (add_in l x y0 H) in H1. | |
535 | rewrite (add_in l x y0 H) in H0. | |
536 | 536 | intuition. |
537 | 537 | eauto. |
538 | 538 | inv bst; inv avl; apply bal_bst; auto. |
539 | 539 | (* gt_tree -> gt_tree (add ...) *) |
540 | red; red in H5. | |
540 | red; red in H4. | |
541 | 541 | intros. |
542 | rewrite (add_in r x y0 H6) in H1. | |
542 | rewrite (add_in r x y0 H5) in H0. | |
543 | 543 | intuition. |
544 | 544 | apply MX.lt_eq with x; auto. |
545 | 545 | Qed. |
702 | 702 | avl_nns; omega_max. |
703 | 703 | (* l = Node *) |
704 | 704 | inversion_clear H. |
705 | rewrite H0 in IHp;simpl in IHp;destruct (IHp lh); auto. | |
705 | rewrite e0 in IHp;simpl in IHp;destruct (IHp lh); auto. | |
706 | 706 | split; simpl in *. |
707 | 707 | apply bal_avl; auto; omega_max. |
708 | 708 | omega_bal. |
722 | 722 | intuition_in. |
723 | 723 | (* l = Node *) |
724 | 724 | inversion_clear H. |
725 | generalize (remove_min_avl ll lx lr lh H1). | |
726 | rewrite H0; simpl; intros. | |
725 | generalize (remove_min_avl ll lx lr lh H0). | |
726 | rewrite e0; simpl; intros. | |
727 | 727 | rewrite bal_in; auto. |
728 | rewrite H0 in IHp;generalize (IHp lh y H1). | |
728 | rewrite e0 in IHp;generalize (IHp lh y H0). | |
729 | 729 | intuition. |
730 | inversion_clear H8; intuition. | |
730 | inversion_clear H7; intuition. | |
731 | 731 | Qed. |
732 | 732 | |
733 | 733 | Lemma remove_min_bst : forall l x r h, |
735 | 735 | Proof. |
736 | 736 | intros l x r; functional induction (remove_min l x r); subst;simpl in *; intros. |
737 | 737 | inv bst; auto. |
738 | inversion_clear H; inversion_clear H1. | |
739 | rewrite_all H0;simpl in *. | |
738 | inversion_clear H; inversion_clear H0. | |
739 | rewrite_all e0;simpl in *. | |
740 | 740 | apply bal_bst; auto. |
741 | 741 | firstorder. |
742 | 742 | intro; intros. |
743 | 743 | generalize (remove_min_in ll lx lr lh y H). |
744 | rewrite H0; simpl. | |
744 | rewrite e0; simpl. | |
745 | 745 | destruct 1. |
746 | apply H4; intuition. | |
746 | apply H3; intuition. | |
747 | 747 | Qed. |
748 | 748 | |
749 | 749 | Lemma remove_min_gt_tree : forall l x r h, |
752 | 752 | Proof. |
753 | 753 | intros l x r; functional induction (remove_min l x r); subst;simpl in *; intros. |
754 | 754 | inv bst; auto. |
755 | inversion_clear H; inversion_clear H1. | |
755 | inversion_clear H; inversion_clear H0. | |
756 | 756 | intro; intro. |
757 | generalize (IHp lh H2 H); clear H8 H7 IHp. | |
757 | generalize (IHp lh H1 H); clear H6 H7 IHp. | |
758 | 758 | generalize (remove_min_avl ll lx lr lh H). |
759 | 759 | generalize (remove_min_in ll lx lr lh m H). |
760 | rewrite H0; simpl; intros. | |
761 | rewrite (bal_in l' x r y H8 H6) in H1. | |
762 | destruct H7. | |
760 | rewrite e0; simpl; intros. | |
761 | rewrite (bal_in l' x r y H7 H5) in H0. | |
762 | destruct H6. | |
763 | 763 | firstorder. |
764 | 764 | apply MX.lt_eq with x; auto. |
765 | 765 | apply X.lt_trans with x; auto. |
787 | 787 | intros s1 s2; functional induction (merge s1 s2); subst;simpl in *; intros. |
788 | 788 | split; auto; avl_nns; omega_max. |
789 | 789 | split; auto; avl_nns; simpl in *; omega_max. |
790 | destruct s1;try contradiction;clear H1. | |
790 | destruct s1;try contradiction;clear y. | |
791 | 791 | generalize (remove_min_avl_1 l2 x2 r2 h2 H0). |
792 | rewrite H2; simpl; destruct 1. | |
792 | rewrite e1; simpl; destruct 1. | |
793 | 793 | split. |
794 | 794 | apply bal_avl; auto. |
795 | 795 | simpl; omega_max. |
808 | 808 | intros s1 s2; functional induction (merge s1 s2); subst; simpl in *; intros. |
809 | 809 | intuition_in. |
810 | 810 | intuition_in. |
811 | destruct s1;try contradiction;clear H1. | |
812 | replace s2' with (fst (remove_min l2 x2 r2)); [|rewrite H2; auto]. | |
811 | destruct s1;try contradiction;clear y. | |
812 | replace s2' with (fst (remove_min l2 x2 r2)); [|rewrite e1; auto]. | |
813 | 813 | rewrite bal_in; auto. |
814 | generalize (remove_min_avl l2 x2 r2 h2); rewrite H2; simpl; auto. | |
815 | generalize (remove_min_in l2 x2 r2 h2 y); rewrite H2; simpl; intro. | |
816 | rewrite H1; intuition. | |
814 | generalize (remove_min_avl l2 x2 r2 h2); rewrite e1; simpl; auto. | |
815 | generalize (remove_min_in l2 x2 r2 h2 y0); rewrite e1; simpl; intro. | |
816 | rewrite H3 ; intuition. | |
817 | 817 | Qed. |
818 | 818 | |
819 | 819 | Lemma merge_bst : forall s1 s2, bst s1 -> avl s1 -> bst s2 -> avl s2 -> |
821 | 821 | bst (merge s1 s2). |
822 | 822 | Proof. |
823 | 823 | intros s1 s2; functional induction (merge s1 s2); subst;simpl in *; intros; auto. |
824 | destruct s1;try contradiction;clear H1. | |
824 | destruct s1;try contradiction;clear y. | |
825 | 825 | apply bal_bst; auto. |
826 | generalize (remove_min_bst l2 x2 r2 h2); rewrite H2; simpl in *; auto. | |
826 | generalize (remove_min_bst l2 x2 r2 h2); rewrite e1; simpl in *; auto. | |
827 | 827 | intro; intro. |
828 | apply H5; auto. | |
829 | generalize (remove_min_in l2 x2 r2 h2 m); rewrite H2; simpl; intuition. | |
830 | generalize (remove_min_gt_tree l2 x2 r2 h2); rewrite H2; simpl; auto. | |
828 | apply H3; auto. | |
829 | generalize (remove_min_in l2 x2 r2 h2 m); rewrite e1; simpl; intuition. | |
830 | generalize (remove_min_gt_tree l2 x2 r2 h2); rewrite e1; simpl; auto. | |
831 | 831 | Qed. |
832 | 832 | |
833 | 833 | (** * Deletion *) |
849 | 849 | intuition; omega_max. |
850 | 850 | (* LT *) |
851 | 851 | inv avl. |
852 | destruct (IHt H1). | |
852 | destruct (IHt H0). | |
853 | 853 | split. |
854 | 854 | apply bal_avl; auto. |
855 | 855 | omega_max. |
856 | 856 | omega_bal. |
857 | 857 | (* EQ *) |
858 | 858 | inv avl. |
859 | generalize (merge_avl_1 l r H1 H2 H3). | |
859 | generalize (merge_avl_1 l r H0 H1 H2). | |
860 | 860 | intuition omega_max. |
861 | 861 | (* GT *) |
862 | 862 | inv avl. |
863 | destruct (IHt H2). | |
863 | destruct (IHt H1). | |
864 | 864 | split. |
865 | 865 | apply bal_avl; auto. |
866 | 866 | omega_max. |
879 | 879 | intros s x; functional induction (remove x s); subst;simpl; intros. |
880 | 880 | intuition_in. |
881 | 881 | (* LT *) |
882 | inv avl; inv bst; clear H0. | |
882 | inv avl; inv bst; clear e0. | |
883 | 883 | rewrite bal_in; auto. |
884 | generalize (IHt y0 H1); intuition; [ order | order | intuition_in ]. | |
884 | generalize (IHt y0 H0); intuition; [ order | order | intuition_in ]. | |
885 | 885 | (* EQ *) |
886 | inv avl; inv bst; clear H0. | |
886 | inv avl; inv bst; clear e0. | |
887 | 887 | rewrite merge_in; intuition; [ order | order | intuition_in ]. |
888 | 888 | elim H9; eauto. |
889 | 889 | (* GT *) |
890 | inv avl; inv bst; clear H0. | |
890 | inv avl; inv bst; clear e0. | |
891 | 891 | rewrite bal_in; auto. |
892 | generalize (IHt y0 H6); intuition; [ order | order | intuition_in ]. | |
892 | generalize (IHt y0 H5); intuition; [ order | order | intuition_in ]. | |
893 | 893 | Qed. |
894 | 894 | |
895 | 895 | Lemma remove_bst : forall s x, bst s -> avl s -> bst (remove x s). |
944 | 944 | simpl. |
945 | 945 | destruct l1. |
946 | 946 | inversion 1; subst. |
947 | assert (X.lt x _x) by (apply H3; auto). | |
947 | assert (X.lt x _x) by (apply H2; auto). | |
948 | 948 | inversion_clear 1; auto; order. |
949 | 949 | assert (X.lt t _x) by auto. |
950 | 950 | inversion_clear 2; auto; |
957 | 957 | red; auto. |
958 | 958 | inversion 1. |
959 | 959 | destruct l;try contradiction. |
960 | clear H0;intro H0. | |
960 | clear y;intro H0. | |
961 | 961 | destruct (IHo H0 t); auto. |
962 | 962 | Qed. |
963 | 963 | |
1003 | 1003 | red; auto. |
1004 | 1004 | inversion 1. |
1005 | 1005 | destruct r;try contradiction. |
1006 | clear H0;intros H0; destruct (IHo H0 t); auto. | |
1006 | intros H0; destruct (IHo H0 t); auto. | |
1007 | 1007 | Qed. |
1008 | 1008 | |
1009 | 1009 | (** * Any element *) |
1037 | 1037 | Lemma concat_avl : forall s1 s2, avl s1 -> avl s2 -> avl (concat s1 s2). |
1038 | 1038 | Proof. |
1039 | 1039 | intros s1 s2; functional induction (concat s1 s2); subst;auto. |
1040 | destruct s1;try contradiction;clear H1. | |
1040 | destruct s1;try contradiction;clear y. | |
1041 | 1041 | intros; apply join_avl; auto. |
1042 | generalize (remove_min_avl l2 x2 r2 h2 H0); rewrite H2; simpl; auto. | |
1042 | generalize (remove_min_avl l2 x2 r2 h2 H0); rewrite e1; simpl; auto. | |
1043 | 1043 | Qed. |
1044 | 1044 | |
1045 | 1045 | Lemma concat_bst : forall s1 s2, bst s1 -> avl s1 -> bst s2 -> avl s2 -> |
1047 | 1047 | bst (concat s1 s2). |
1048 | 1048 | Proof. |
1049 | 1049 | intros s1 s2; functional induction (concat s1 s2); subst ;auto. |
1050 | destruct s1;try contradiction;clear H1. | |
1050 | destruct s1;try contradiction;clear y. | |
1051 | 1051 | intros; apply join_bst; auto. |
1052 | generalize (remove_min_bst l2 x2 r2 h2 H1 H3); rewrite H2; simpl; auto. | |
1053 | generalize (remove_min_avl l2 x2 r2 h2 H3); rewrite H2; simpl; auto. | |
1054 | generalize (remove_min_in l2 x2 r2 h2 m H3); rewrite H2; simpl; auto. | |
1052 | generalize (remove_min_bst l2 x2 r2 h2 H1 H2); rewrite e1; simpl; auto. | |
1053 | generalize (remove_min_avl l2 x2 r2 h2 H2); rewrite e1; simpl; auto. | |
1054 | generalize (remove_min_in l2 x2 r2 h2 m H2); rewrite e1; simpl; auto. | |
1055 | 1055 | destruct 1; intuition. |
1056 | generalize (remove_min_gt_tree l2 x2 r2 h2 H1 H3); rewrite H2; simpl; auto. | |
1056 | generalize (remove_min_gt_tree l2 x2 r2 h2 H1 H2); rewrite e1; simpl; auto. | |
1057 | 1057 | Qed. |
1058 | 1058 | |
1059 | 1059 | Lemma concat_in : forall s1 s2 y, bst s1 -> avl s1 -> bst s2 -> avl s2 -> |
1063 | 1063 | intros s1 s2; functional induction (concat s1 s2);subst;simpl. |
1064 | 1064 | intuition. |
1065 | 1065 | inversion_clear H5. |
1066 | destruct s1;try contradiction;clear H1;intuition. | |
1066 | destruct s1;try contradiction;clear y;intuition. | |
1067 | 1067 | inversion_clear H5. |
1068 | destruct s1;try contradiction;clear H1; intros. | |
1068 | destruct s1;try contradiction;clear y; intros. | |
1069 | 1069 | rewrite (join_in (Node s1_1 t s1_2 i) m s2' y H0). |
1070 | generalize (remove_min_avl l2 x2 r2 h2 H3); rewrite H2; simpl; auto. | |
1071 | generalize (remove_min_in l2 x2 r2 h2 y H3); rewrite H2; simpl. | |
1070 | generalize (remove_min_avl l2 x2 r2 h2 H2); rewrite e1; simpl; auto. | |
1071 | generalize (remove_min_in l2 x2 r2 h2 y H2); rewrite e1; simpl. | |
1072 | 1072 | intro EQ; rewrite EQ; intuition. |
1073 | 1073 | Qed. |
1074 | 1074 | |
1099 | 1099 | Proof. |
1100 | 1100 | intros s x; functional induction (split x s);subst;simpl in *. |
1101 | 1101 | auto. |
1102 | rewrite H1 in IHp;simpl in IHp;inversion_clear 1; intuition. | |
1102 | rewrite e1 in IHp;simpl in IHp;inversion_clear 1; intuition. | |
1103 | 1103 | simpl; inversion_clear 1; auto. |
1104 | rewrite H1 in IHp;simpl in IHp;inversion_clear 1; intuition. | |
1104 | rewrite e1 in IHp;simpl in IHp;inversion_clear 1; intuition. | |
1105 | 1105 | Qed. |
1106 | 1106 | |
1107 | 1107 | Lemma split_in_1 : forall s x y, bst s -> avl s -> |
1110 | 1110 | intros s x; functional induction (split x s);subst;simpl in *. |
1111 | 1111 | intuition; try inversion_clear H1. |
1112 | 1112 | (* LT *) |
1113 | rewrite H1 in IHp;simpl in *; inversion_clear 1; inversion_clear 1; clear H8 H9. | |
1114 | rewrite (IHp y0 H2 H6); clear IHp H0. | |
1113 | rewrite e1 in IHp;simpl in *; inversion_clear 1; inversion_clear 1; clear H7 H6. | |
1114 | rewrite (IHp y0 H0 H4); clear IHp e0. | |
1115 | 1115 | intuition. |
1116 | inversion_clear H0; auto; order. | |
1116 | inversion_clear H6; auto; order. | |
1117 | 1117 | (* EQ *) |
1118 | simpl in *; inversion_clear 1; inversion_clear 1; clear H8 H7 H0. | |
1118 | simpl in *; inversion_clear 1; inversion_clear 1; clear H6 H5 e0. | |
1119 | 1119 | intuition. |
1120 | 1120 | order. |
1121 | 1121 | intuition_in; order. |
1122 | 1122 | (* GT *) |
1123 | rewrite H1 in IHp;simpl in *; inversion_clear 1; inversion_clear 1; clear H9 H8. | |
1123 | rewrite e1 in IHp;simpl in *; inversion_clear 1; inversion_clear 1; clear H7 H6. | |
1124 | 1124 | rewrite join_in; auto. |
1125 | generalize (split_avl r x H7); rewrite H1; simpl; intuition. | |
1126 | rewrite (IHp y0 H3 H7); clear H1. | |
1125 | generalize (split_avl r x H5); rewrite e1; simpl; intuition. | |
1126 | rewrite (IHp y0 H1 H5); clear e1. | |
1127 | 1127 | intuition; [ eauto | eauto | intuition_in ]. |
1128 | 1128 | Qed. |
1129 | 1129 | |
1133 | 1133 | intros s x; functional induction (split x s);subst;simpl in *. |
1134 | 1134 | intuition; try inversion_clear H1. |
1135 | 1135 | (* LT *) |
1136 | rewrite H1 in IHp; simpl in *; inversion_clear 1; inversion_clear 1; clear H9 H8. | |
1136 | rewrite e1 in IHp; simpl in *; inversion_clear 1; inversion_clear 1; clear H7 H6. | |
1137 | 1137 | rewrite join_in; auto. |
1138 | generalize (split_avl l x H6); rewrite H1; simpl; intuition. | |
1139 | rewrite (IHp y0 H2 H6); clear IHp H0. | |
1138 | generalize (split_avl l x H4); rewrite e1; simpl; intuition. | |
1139 | rewrite (IHp y0 H0 H4); clear IHp e0. | |
1140 | 1140 | intuition; [ order | order | intuition_in ]. |
1141 | 1141 | (* EQ *) |
1142 | simpl in *; inversion_clear 1; inversion_clear 1; clear H8 H7 H0. | |
1142 | simpl in *; inversion_clear 1; inversion_clear 1; clear H6 H5 e0. | |
1143 | 1143 | intuition; [ order | intuition_in; order ]. |
1144 | 1144 | (* GT *) |
1145 | rewrite H1 in IHp; simpl in *; inversion_clear 1; inversion_clear 1; clear H9 H8. | |
1146 | rewrite (IHp y0 H3 H7); clear IHp H0. | |
1145 | rewrite e1 in IHp; simpl in *; inversion_clear 1; inversion_clear 1; clear H7 H6. | |
1146 | rewrite (IHp y0 H1 H5); clear IHp e0. | |
1147 | 1147 | intuition; intuition_in; order. |
1148 | 1148 | Qed. |
1149 | 1149 | |
1153 | 1153 | intros s x; functional induction (split x s);subst;simpl in *. |
1154 | 1154 | intuition; try inversion_clear H1. |
1155 | 1155 | (* LT *) |
1156 | rewrite H1 in IHp; simpl in *; inversion_clear 1; inversion_clear 1; clear H9 H8. | |
1156 | rewrite e1 in IHp; simpl in *; inversion_clear 1; inversion_clear 1; clear H7 H6. | |
1157 | 1157 | rewrite IHp; auto. |
1158 | 1158 | intuition_in; absurd (X.lt x y); eauto. |
1159 | 1159 | (* EQ *) |
1160 | 1160 | simpl in *; inversion_clear 1; inversion_clear 1; intuition. |
1161 | 1161 | (* GT *) |
1162 | rewrite H1 in IHp; simpl in *; inversion_clear 1; inversion_clear 1; clear H9 H8. | |
1162 | rewrite e1 in IHp; simpl in *; inversion_clear 1; inversion_clear 1; clear H7 H6. | |
1163 | 1163 | rewrite IHp; auto. |
1164 | 1164 | intuition_in; absurd (X.lt y x); eauto. |
1165 | 1165 | Qed. |
1170 | 1170 | intros s x; functional induction (split x s);subst;simpl in *. |
1171 | 1171 | intuition. |
1172 | 1172 | (* LT *) |
1173 | rewrite H1 in IHp; simpl in *; inversion_clear 1; inversion_clear 1. | |
1173 | rewrite e1 in IHp; simpl in *; inversion_clear 1; inversion_clear 1. | |
1174 | 1174 | intuition. |
1175 | 1175 | apply join_bst; auto. |
1176 | generalize (split_avl l x H6); rewrite H1; simpl; intuition. | |
1176 | generalize (split_avl l x H4); rewrite e1; simpl; intuition. | |
1177 | 1177 | intro; intro. |
1178 | generalize (split_in_2 l x y0 H2 H6); rewrite H1; simpl; intuition. | |
1178 | generalize (split_in_2 l x y0 H0 H4); rewrite e1; simpl; intuition. | |
1179 | 1179 | (* EQ *) |
1180 | 1180 | simpl in *; inversion_clear 1; inversion_clear 1; intuition. |
1181 | 1181 | (* GT *) |
1182 | rewrite H1 in IHp; simpl in *; inversion_clear 1; inversion_clear 1. | |
1182 | rewrite e1 in IHp; simpl in *; inversion_clear 1; inversion_clear 1. | |
1183 | 1183 | intuition. |
1184 | 1184 | apply join_bst; auto. |
1185 | generalize (split_avl r x H7); rewrite H1; simpl; intuition. | |
1185 | generalize (split_avl r x H5); rewrite e1; simpl; intuition. | |
1186 | 1186 | intro; intro. |
1187 | generalize (split_in_1 r x y0 H3 H7); rewrite H1; simpl; intuition. | |
1187 | generalize (split_in_1 r x y0 H1 H5); rewrite e1; simpl; intuition. | |
1188 | 1188 | Qed. |
1189 | 1189 | |
1190 | 1190 | (** * Intersection *) |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (*i $Id: Wf.v 8642 2006-03-17 10:09:02Z notin $ i*) | |
8 | (*i $Id: Wf.v 8988 2006-06-25 22:15:32Z letouzey $ i*) | |
9 | 9 | |
10 | 10 | (** This module proves the validity of |
11 | 11 | - well-founded recursion (also called course of values) |
145 | 145 | Variable R : A * B -> A * B -> Prop. |
146 | 146 | |
147 | 147 | Variable P : A -> B -> Type. |
148 | ||
149 | Section Acc_iter_2. | |
148 | 150 | Variable |
149 | 151 | F : |
150 | 152 | forall (x:A) (x':B), |
155 | 157 | F |
156 | 158 | (fun (y:A) (y':B) (h:R (y, y') (x, x')) => |
157 | 159 | Acc_iter_2 (x:=y) (x':=y') (Acc_inv a (y, y') h)). |
160 | End Acc_iter_2. | |
158 | 161 | |
159 | 162 | Hypothesis Rwf : well_founded R. |
160 | 163 |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (*i $Id: List.v 8866 2006-05-28 16:21:04Z herbelin $ i*) | |
8 | (*i $Id: List.v 9035 2006-07-09 15:42:09Z herbelin $ i*) | |
9 | 9 | |
10 | 10 | Require Import Le Gt Minus Min Bool. |
11 | 11 | Require Import Setoid. |
84 | 84 | |
85 | 85 | Bind Scope list_scope with list. |
86 | 86 | |
87 | Arguments Scope list [type_scope]. | |
87 | 88 | |
88 | 89 | (** ** Facts about lists *) |
89 | 90 | |
134 | 135 | Proof. |
135 | 136 | simpl in |- *; auto. |
136 | 137 | Qed. |
137 | Hint Resolve in_eq. | |
138 | 138 | |
139 | 139 | Theorem in_cons : forall (a b:A) (l:list A), In b l -> In b (a :: l). |
140 | 140 | Proof. |
141 | 141 | simpl in |- *; auto. |
142 | 142 | Qed. |
143 | Hint Resolve in_cons. | |
144 | 143 | |
145 | 144 | Theorem in_nil : forall a:A, ~ In a nil. |
146 | 145 | Proof. |
196 | 195 | induction l; simpl in |- *; auto. |
197 | 196 | rewrite <- IHl; auto. |
198 | 197 | Qed. |
199 | Hint Resolve app_nil_end. | |
200 | ||
201 | 198 | |
202 | 199 | (** [app] is associative *) |
203 | 200 | Theorem app_ass : forall l m n:list A, (l ++ m) ++ n = l ++ m ++ n. |
210 | 207 | |
211 | 208 | Theorem ass_app : forall l m n:list A, l ++ m ++ n = (l ++ m) ++ n. |
212 | 209 | Proof. |
213 | auto. | |
214 | Qed. | |
215 | Hint Resolve ass_app. | |
210 | auto using app_ass. | |
211 | Qed. | |
216 | 212 | |
217 | 213 | (** [app] commutes with [cons] *) |
218 | 214 | Theorem app_comm_cons : forall (x y:list A) (a:A), a :: (x ++ y) = (a :: x) ++ y. |
295 | 291 | now_show ((a0 = a \/ In a y) \/ In a m). |
296 | 292 | elim (H H1); auto. |
297 | 293 | Qed. |
298 | Hint Immediate in_app_or. | |
299 | 294 | |
300 | 295 | Lemma in_or_app : forall (l m:list A) (a:A), In a l \/ In a m -> In a (l ++ m). |
301 | 296 | Proof. |
312 | 307 | now_show (H = a \/ In a (y ++ m)). |
313 | 308 | elim H2; auto. |
314 | 309 | Qed. |
315 | Hint Resolve in_or_app. | |
316 | 310 | |
317 | 311 | |
318 | 312 | End Facts. |
889 | 883 | break_list l1 b l1' H0; break_list l3 c l3' H1. |
890 | 884 | auto. |
891 | 885 | apply perm_trans with (l3'++c::l4); auto. |
892 | apply perm_trans with (l1'++a::l2); auto. | |
886 | apply perm_trans with (l1'++a::l2); auto using Permutation_cons_app. | |
893 | 887 | apply perm_skip. |
894 | 888 | apply (IH a l1' l2 l3' l4); auto. |
895 | 889 | (* swap *) |
6 | 6 | (* * GNU Lesser General Public License Version 2.1 *) |
7 | 7 | (************************************************************************) |
8 | 8 | |
9 | (*i $Id: ChoiceFacts.v 8892 2006-06-04 17:59:53Z herbelin $ i*) | |
9 | (*i $Id: ChoiceFacts.v 8999 2006-07-04 12:46:04Z notin $ i*) | |
10 | 10 | |
11 | 11 | (** ** Some facts and definitions concerning choice and description in |
12 | 12 | intuitionistic logic. |
77 | 77 | [Bell93] John L. Bell, Hilbert's Epsilon Operator in Intuitionistic |
78 | 78 | Type Theories, Mathematical Logic Quarterly, volume 39, 1993. |
79 | 79 | |
80 | [Carlstrøm05] Jesper Carlstrøm, Interpreting descriptions in | |
80 | [Carlstrøm05] Jesper Carlstrøm, Interpreting descriptions in | |
81 | 81 | intentional type theory, Journal of Symbolic Logic 70(2):488-514, 2005. |
82 | 82 | *) |
83 | 83 | |
124 | 124 | |
125 | 125 | (** ID_epsilon (constructive version of indefinite description; |
126 | 126 | combined with proof-irrelevance, it may be connected to |
127 | Carlstrøm's type theory with a constructive indefinite description | |
127 | Carlstrøm's type theory with a constructive indefinite description | |
128 | 128 | operator) *) |
129 | 129 | |
130 | 130 | Definition ConstructiveIndefiniteDescription_on := |
132 | 132 | (exists x, P x) -> { x:A | P x }. |
133 | 133 | |
134 | 134 | (** ID_iota (constructive version of definite description; combined |
135 | with proof-irrelevance, it may be connected to Carlstrøm's and | |
135 | with proof-irrelevance, it may be connected to Carlstrøm's and | |
136 | 136 | Stenlund's type theory with a constructive definite description |
137 | 137 | operator) *) |
138 | 138 | |
693 | 693 | We adapt the proof to show that constructive definite description |
694 | 694 | transports excluded-middle from [Prop] to [Set]. |
695 | 695 | |
696 | [ChicliPottierSimpson02] Laurent Chicli, Loïc Pottier, Carlos | |
696 | [ChicliPottierSimpson02] Laurent Chicli, Loïc Pottier, Carlos | |
697 | 697 | Simpson, Mathematical Quotients and Quotient Types in Coq, |
698 | 698 | Proceedings of TYPES 2002, Lecture Notes in Computer Science 2646, |
699 | 699 | Springer Verlag. *) |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (*i $Id: ClassicalUniqueChoice.v 8893 2006-06-04 18:04:53Z herbelin $ i*) | |
8 | (*i $Id: ClassicalUniqueChoice.v 9026 2006-07-06 15:16:20Z herbelin $ i*) | |
9 | 9 | |
10 | 10 | (** This file provides classical logic and unique choice *) |
11 | 11 | |
14 | 14 | excluded-middle in [Set], hence it implies a strongly classical |
15 | 15 | world. Especially it conflicts with the impredicativity of [Set]. |
16 | 16 | |
17 | [ChicliPottierSimpson02] Laurent Chicli, Loïc Pottier, Carlos | |
17 | [ChicliPottierSimpson02] Laurent Chicli, Loïc Pottier, Carlos | |
18 | 18 | Simpson, Mathematical Quotients and Quotient Types in Coq, |
19 | 19 | Proceedings of TYPES 2002, Lecture Notes in Computer Science 2646, |
20 | 20 | Springer Verlag. *) |
38 | 38 | apply (dependent_unique_choice A (fun _ => B)). |
39 | 39 | Qed. |
40 | 40 | |
41 | (** The followig proof comes from [ChicliPottierSimpson02] *) | |
41 | (** The following proof comes from [ChicliPottierSimpson02] *) | |
42 | 42 | |
43 | 43 | Require Import Setoid. |
44 | 44 |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (*i $Id: QArith_base.v 8883 2006-05-31 21:56:37Z letouzey $ i*) | |
8 | (*i $Id: QArith_base.v 8989 2006-06-25 22:17:49Z letouzey $ i*) | |
9 | 9 | |
10 | 10 | Require Export ZArith. |
11 | 11 | Require Export ZArithRing. |
42 | 42 | |
43 | 43 | Infix "==" := Qeq (at level 70, no associativity) : Q_scope. |
44 | 44 | Infix "<" := Qlt : Q_scope. |
45 | Infix ">" := Qgt : Q_scope. | |
45 | 46 | Infix "<=" := Qle : Q_scope. |
46 | Infix ">" := Qgt : Q_scope. | |
47 | Infix ">=" := Qge : Q_scope. | |
47 | Infix ">=" := Qge : Q_scope. | |
48 | 48 | Notation "x <= y <= z" := (x<=y/\y<=z) : Q_scope. |
49 | 49 | |
50 | Hint Unfold Qeq Qle Qlt: qarith. | |
50 | (** Another approach : using Qcompare for defining order relations. *) | |
51 | ||
52 | Definition Qcompare (p q : Q) := (Qnum p * QDen q ?= Qnum q * QDen p)%Z. | |
53 | Notation "p ?= q" := (Qcompare p q) : Q_scope. | |
54 | ||
55 | Lemma Qeq_alt : forall p q, (p == q) <-> (p ?= q) = Eq. | |
56 | Proof. | |
57 | unfold Qeq, Qcompare; intros; split; intros. | |
58 | rewrite H; apply Zcompare_refl. | |
59 | apply Zcompare_Eq_eq; auto. | |
60 | Qed. | |
61 | ||
62 | Lemma Qlt_alt : forall p q, (p<q) <-> (p?=q = Lt). | |
63 | Proof. | |
64 | unfold Qlt, Qcompare, Zlt; split; auto. | |
65 | Qed. | |
66 | ||
67 | Lemma Qgt_alt : forall p q, (p>q) <-> (p?=q = Gt). | |
68 | Proof. | |
69 | unfold Qlt, Qcompare, Zlt. | |
70 | intros; rewrite Zcompare_Gt_Lt_antisym; split; auto. | |
71 | Qed. | |
72 | ||
73 | Lemma Qle_alt : forall p q, (p<=q) <-> (p?=q <> Gt). | |
74 | Proof. | |
75 | unfold Qle, Qcompare, Zle; split; auto. | |
76 | Qed. | |
77 | ||
78 | Lemma Qge_alt : forall p q, (p>=q) <-> (p?=q <> Lt). | |
79 | Proof. | |
80 | unfold Qle, Qcompare, Zle. | |
81 | split; intros; swap H. | |
82 | rewrite Zcompare_Gt_Lt_antisym; auto. | |
83 | rewrite Zcompare_Gt_Lt_antisym in H0; auto. | |
84 | Qed. | |
85 | ||
86 | Hint Unfold Qeq Qlt Qle: qarith. | |
51 | 87 | Hint Extern 5 (?X1 <> ?X2) => intro; discriminate: qarith. |
52 | 88 | |
53 | 89 | (** Properties of equality. *) |
235 | 271 | Open Scope Q_scope. |
236 | 272 | Qed. |
237 | 273 | |
274 | ||
275 | Lemma Qcompare_egal_dec: forall n m p q : Q, | |
276 | (n<m -> p<q) -> (n==m -> p==q) -> (n>m -> p>q) -> ((n?=m) = (p?=q)). | |
277 | Proof. | |
278 | intros. | |
279 | do 2 rewrite Qeq_alt in H0. | |
280 | unfold Qeq, Qlt, Qcompare in *. | |
281 | apply Zcompare_egal_dec; auto. | |
282 | omega. | |
283 | Qed. | |
284 | ||
285 | ||
286 | Add Morphism Qcompare : Qcompare_comp. | |
287 | Proof. | |
288 | intros; apply Qcompare_egal_dec; rewrite H; rewrite H0; auto. | |
289 | Qed. | |
290 | ||
291 | ||
238 | 292 | (** [0] and [1] are apart *) |
239 | 293 | |
240 | 294 | Lemma Q_apart_0_1 : ~ 1 == 0. |
0 | (************************************************************************) | |
1 | (* v * The Coq Proof Assistant / The Coq Development Team *) | |
2 | (* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *) | |
3 | (* \VV/ **************************************************************) | |
4 | (* // * This file is distributed under the terms of the *) | |
5 | (* * GNU Lesser General Public License Version 2.1 *) | |
6 | (************************************************************************) | |
7 | ||
8 | (*i $Id: Qcanon.v 8989 2006-06-25 22:17:49Z letouzey $ i*) | |
9 | ||
10 | Require Import QArith. | |
11 | Require Import Eqdep_dec. | |
12 | ||
13 | (** [Qc] : A canonical representation of rational numbers. | |
14 | based on the setoid representation [Q]. *) | |
15 | ||
16 | Record Qc : Set := Qcmake { this :> Q ; canon : Qred this = this }. | |
17 | ||
18 | Delimit Scope Qc_scope with Qc. | |
19 | Bind Scope Qc_scope with Qc. | |
20 | Arguments Scope Qcmake [Q_scope]. | |
21 | Open Scope Qc_scope. | |
22 | ||
23 | Lemma Qred_identity : | |
24 | forall q:Q, Zgcd (Qnum q) (QDen q) = 1%Z -> Qred q = q. | |
25 | Proof. | |
26 | unfold Qred; intros (a,b); simpl. | |
27 | generalize (Zggcd_gcd a ('b)) (Zggcd_correct_divisors a ('b)). | |
28 | intros. | |
29 | rewrite H1 in H; clear H1. | |
30 | destruct (Zggcd a ('b)) as (g,(aa,bb)); simpl in *; subst. | |
31 | destruct H0. | |
32 | rewrite Zmult_1_l in H, H0. | |
33 | subst; simpl; auto. | |
34 | Qed. | |
35 | ||
36 | Lemma Qred_identity2 : | |
37 | forall q:Q, Qred q = q -> Zgcd (Qnum q) (QDen q) = 1%Z. | |
38 | Proof. | |
39 | unfold Qred; intros (a,b); simpl. | |
40 | generalize (Zggcd_gcd a ('b)) (Zggcd_correct_divisors a ('b)) (Zgcd_is_pos a ('b)). | |
41 | intros. | |
42 | rewrite <- H; rewrite <- H in H1; clear H. | |
43 | destruct (Zggcd a ('b)) as (g,(aa,bb)); simpl in *; subst. | |
44 | injection H2; intros; clear H2. | |
45 | destruct H0. | |
46 | clear H0 H3. | |
47 | destruct g as [|g|g]; destruct bb as [|bb|bb]; simpl in *; try discriminate. | |
48 | f_equal. | |
49 | apply Pmult_reg_r with bb. | |
50 | injection H2; intros. | |
51 | rewrite <- H0. | |
52 | rewrite H; simpl; auto. | |
53 | elim H1; auto. | |
54 | Qed. | |
55 | ||
56 | Lemma Qred_iff : forall q:Q, Qred q = q <-> Zgcd (Qnum q) (QDen q) = 1%Z. | |
57 | Proof. | |
58 | split; intros. | |
59 | apply Qred_identity2; auto. | |
60 | apply Qred_identity; auto. | |
61 | Qed. | |
62 | ||
63 | ||
64 | Lemma Qred_involutive : forall q:Q, Qred (Qred q) = Qred q. | |
65 | Proof. | |
66 | intros; apply Qred_complete. | |
67 | apply Qred_correct. | |
68 | Qed. | |
69 | ||
70 | Definition Q2Qc (q:Q) : Qc := Qcmake (Qred q) (Qred_involutive q). | |
71 | Arguments Scope Q2Qc [Q_scope]. | |
72 | Notation " !! " := Q2Qc : Qc_scope. | |
73 | ||
74 | Lemma Qc_is_canon : forall q q' : Qc, q == q' -> q = q'. | |
75 | Proof. | |
76 | intros (q,proof_q) (q',proof_q'). | |
77 | simpl. | |
78 | intros H. | |
79 | assert (H0:=Qred_complete _ _ H). | |
80 | assert (q = q') by congruence. | |
81 | subst q'. | |
82 | assert (proof_q = proof_q'). | |
83 | apply eq_proofs_unicity; auto; intros. | |
84 | repeat decide equality. | |
85 | congruence. | |
86 | Qed. | |
87 | Hint Resolve Qc_is_canon. | |
88 | ||
89 | Notation " 0 " := (!!0) : Qc_scope. | |
90 | Notation " 1 " := (!!1) : Qc_scope. | |
91 | ||
92 | Definition Qcle (x y : Qc) := (x <= y)%Q. | |
93 | Definition Qclt (x y : Qc) := (x < y)%Q. | |
94 | Notation Qcgt := (fun x y : Qc => Qlt y x). | |
95 | Notation Qcge := (fun x y : Qc => Qle y x). | |
96 | Infix "<" := Qclt : Qc_scope. | |
97 | Infix "<=" := Qcle : Qc_scope. | |
98 | Infix ">" := Qcgt : Qc_scope. | |
99 | Infix ">=" := Qcge : Qc_scope. | |
100 | Notation "x <= y <= z" := (x<=y/\y<=z) : Qc_scope. | |
101 | ||
102 | Definition Qccompare (p q : Qc) := (Qcompare p q). | |
103 | Notation "p ?= q" := (Qccompare p q) : Qc_scope. | |
104 | ||
105 | Lemma Qceq_alt : forall p q, (p = q) <-> (p ?= q) = Eq. | |
106 | Proof. | |
107 | unfold Qccompare. | |
108 | intros; rewrite <- Qeq_alt. | |
109 | split; auto. | |
110 | intro H; rewrite H; auto with qarith. | |
111 | Qed. | |
112 | ||
113 | Lemma Qclt_alt : forall p q, (p<q) <-> (p?=q = Lt). | |
114 | Proof. | |
115 | intros; exact (Qlt_alt p q). | |
116 | Qed. | |
117 | ||
118 | Lemma Qcgt_alt : forall p q, (p>q) <-> (p?=q = Gt). | |
119 | Proof. | |
120 | intros; exact (Qgt_alt p q). | |
121 | Qed. | |
122 | ||
123 | Lemma Qle_alt : forall p q, (p<=q) <-> (p?=q <> Gt). | |
124 | Proof. | |
125 | intros; exact (Qle_alt p q). | |
126 | Qed. | |
127 | ||
128 | Lemma Qge_alt : forall p q, (p>=q) <-> (p?=q <> Lt). | |
129 | Proof. | |
130 | intros; exact (Qge_alt p q). | |
131 | Qed. | |
132 | ||
133 | (** equality on [Qc] is decidable: *) | |
134 | ||
135 | Theorem Qc_eq_dec : forall x y:Qc, {x=y} + {x<>y}. | |
136 | Proof. | |
137 | intros. | |
138 | destruct (Qeq_dec x y) as [H|H]; auto. | |
139 | right; swap H; subst; auto with qarith. | |
140 | Defined. | |
141 | ||
142 | (** The addition, multiplication and opposite are defined | |
143 | in the straightforward way: *) | |
144 | ||
145 | Definition Qcplus (x y : Qc) := !!(x+y). | |
146 | Infix "+" := Qcplus : Qc_scope. | |
147 | Definition Qcmult (x y : Qc) := !!(x*y). | |
148 | Infix "*" := Qcmult : Qc_scope. | |
149 | Definition Qcopp (x : Qc) := !!(-x). | |
150 | Notation "- x" := (Qcopp x) : Qc_scope. | |
151 | Definition Qcminus (x y : Qc) := x+-y. | |
152 | Infix "-" := Qcminus : Qc_scope. | |
153 | Definition Qcinv (x : Qc) := !!(/x). | |
154 | Notation "/ x" := (Qcinv x) : Qc_scope. | |
155 | Definition Qcdiv (x y : Qc) := x*/y. | |
156 | Infix "/" := Qcdiv : Qc_scope. | |
157 | ||
158 | (** [0] and [1] are apart *) | |
159 | ||
160 | Lemma Q_apart_0_1 : 1 <> 0. | |
161 | Proof. | |
162 | unfold Q2Qc. | |
163 | intros H; discriminate H. | |
164 | Qed. | |
165 | ||
166 | Ltac qc := match goal with | |
167 | | q:Qc |- _ => destruct q; qc | |
168 | | _ => apply Qc_is_canon; simpl; repeat rewrite Qred_correct | |
169 | end. | |
170 | ||
171 | Opaque Qred. | |
172 | ||
173 | (** Addition is associative: *) | |
174 | ||
175 | Theorem Qcplus_assoc : forall x y z, x+(y+z)=(x+y)+z. | |
176 | Proof. | |
177 | intros; qc; apply Qplus_assoc. | |
178 | Qed. | |
179 | ||
180 | (** [0] is a neutral element for addition: *) | |
181 | ||
182 | Lemma Qcplus_0_l : forall x, 0+x = x. | |
183 | Proof. | |
184 | intros; qc; apply Qplus_0_l. | |
185 | Qed. | |
186 | ||
187 | Lemma Qcplus_0_r : forall x, x+0 = x. | |
188 | Proof. | |
189 | intros; qc; apply Qplus_0_r. | |
190 | Qed. | |
191 | ||
192 | (** Commutativity of addition: *) | |
193 | ||
194 | Theorem Qcplus_comm : forall x y, x+y = y+x. | |
195 | Proof. | |
196 | intros; qc; apply Qplus_comm. | |
197 | Qed. | |
198 | ||
199 | (** Properties of [Qopp] *) | |
200 | ||
201 | Lemma Qcopp_involutive : forall q, - -q = q. | |
202 | Proof. | |
203 | intros; qc; apply Qopp_involutive. | |
204 | Qed. | |
205 | ||
206 | Theorem Qcplus_opp_r : forall q, q+(-q) = 0. | |
207 | Proof. | |
208 | intros; qc; apply Qplus_opp_r. | |
209 | Qed. | |
210 | ||
211 | (** Multiplication is associative: *) | |
212 | ||
213 | Theorem Qcmult_assoc : forall n m p, n*(m*p)=(n*m)*p. | |
214 | Proof. | |
215 | intros; qc; apply Qmult_assoc. | |
216 | Qed. | |
217 | ||
218 | (** [1] is a neutral element for multiplication: *) | |
219 | ||
220 | Lemma Qcmult_1_l : forall n, 1*n = n. | |
221 | Proof. | |
222 | intros; qc; apply Qmult_1_l. | |
223 | Qed. | |
224 | ||
225 | Theorem Qcmult_1_r : forall n, n*1=n. | |
226 | Proof. | |
227 | intros; qc; apply Qmult_1_r. | |
228 | Qed. | |
229 | ||
230 | (** Commutativity of multiplication *) | |
231 | ||
232 | Theorem Qcmult_comm : forall x y, x*y=y*x. | |
233 | Proof. | |
234 | intros; qc; apply Qmult_comm. | |
235 | Qed. | |
236 | ||
237 | (** Distributivity *) | |
238 | ||
239 | Theorem Qcmult_plus_distr_r : forall x y z, x*(y+z)=(x*y)+(x*z). | |
240 | Proof. | |
241 | intros; qc; apply Qmult_plus_distr_r. | |
242 | Qed. | |
243 | ||
244 | Theorem Qcmult_plus_distr_l : forall x y z, (x+y)*z=(x*z)+(y*z). | |
245 | Proof. | |
246 | intros; qc; apply Qmult_plus_distr_l. | |
247 | Qed. | |
248 | ||
249 | (** Integrality *) | |
250 | ||
251 | Theorem Qcmult_integral : forall x y, x*y=0 -> x=0 \/ y=0. | |
252 | Proof. | |
253 | intros. | |
254 | destruct (Qmult_integral x y); try qc; auto. | |
255 | injection H; clear H; intros. | |
256 | rewrite <- (Qred_correct (x*y)). | |
257 | rewrite <- (Qred_correct 0). | |
258 | rewrite H; auto with qarith. | |
259 | Qed. | |
260 | ||
261 | Theorem Qcmult_integral_l : forall x y, ~ x = 0 -> x*y = 0 -> y = 0. | |
262 | Proof. | |
263 | intros; destruct (Qcmult_integral _ _ H0); tauto. | |
264 | Qed. | |
265 | ||
266 | (** Inverse and division. *) | |
267 | ||
268 | Theorem Qcmult_inv_r : forall x, x<>0 -> x*(/x) = 1. | |
269 | Proof. | |
270 | intros; qc; apply Qmult_inv_r; auto. | |
271 | Qed. | |
272 | ||
273 | Theorem Qcmult_inv_l : forall x, x<>0 -> (/x)*x = 1. | |
274 | Proof. | |
275 | intros. | |
276 | rewrite Qcmult_comm. | |
277 | apply Qcmult_inv_r; auto. | |
278 | Qed. | |
279 | ||
280 | Lemma Qcinv_mult_distr : forall p q, / (p * q) = /p * /q. | |
281 | Proof. | |
282 | intros; qc; apply Qinv_mult_distr. | |
283 | Qed. | |
284 | ||
285 | Theorem Qcdiv_mult_l : forall x y, y<>0 -> (x*y)/y = x. | |
286 | Proof. | |
287 | unfold Qcdiv. | |
288 | intros. | |
289 | rewrite <- Qcmult_assoc. | |
290 | rewrite Qcmult_inv_r; auto. | |
291 | apply Qcmult_1_r. | |
292 | Qed. | |
293 | ||
294 | Theorem Qcmult_div_r : forall x y, ~ y = 0 -> y*(x/y) = x. | |
295 | Proof. | |
296 | unfold Qcdiv. | |
297 | intros. | |
298 | rewrite Qcmult_assoc. | |
299 | rewrite Qcmult_comm. | |
300 | rewrite Qcmult_assoc. | |
301 | rewrite Qcmult_inv_l; auto. | |
302 | apply Qcmult_1_l. | |
303 | Qed. | |
304 | ||
305 | (** Properties of order upon Q. *) | |
306 | ||
307 | Lemma Qcle_refl : forall x, x<=x. | |
308 | Proof. | |
309 | unfold Qcle; intros; simpl; apply Qle_refl. | |
310 | Qed. | |
311 | ||
312 | Lemma Qcle_antisym : forall x y, x<=y -> y<=x -> x=y. | |
313 | Proof. | |
314 | unfold Qcle; intros; simpl in *. | |
315 | apply Qc_is_canon; apply Qle_antisym; auto. | |
316 | Qed. | |
317 | ||
318 | Lemma Qcle_trans : forall x y z, x<=y -> y<=z -> x<=z. | |
319 | Proof. | |
320 | unfold Qcle; intros; eapply Qle_trans; eauto. | |
321 | Qed. | |
322 | ||
323 | Lemma Qclt_not_eq : forall x y, x<y -> x<>y. | |
324 | Proof. | |
325 | unfold Qclt; intros; simpl in *. | |
326 | intro; destruct (Qlt_not_eq _ _ H). | |
327 | subst; auto with qarith. | |
328 | Qed. | |
329 | ||
330 | (** Large = strict or equal *) | |
331 | ||
332 | Lemma Qclt_le_weak : forall x y, x<y -> x<=y. | |
333 | Proof. | |
334 | unfold Qcle, Qclt; intros; apply Qlt_le_weak; auto. | |
335 | Qed. | |
336 | ||
337 | Lemma Qcle_lt_trans : forall x y z, x<=y -> y<z -> x<z. | |
338 | Proof. | |
339 | unfold Qcle, Qclt; intros; eapply Qle_lt_trans; eauto. | |
340 | Qed. | |
341 | ||
342 | Lemma Qclt_le_trans : forall x y z, x<y -> y<=z -> x<z. | |
343 | Proof. | |
344 | unfold Qcle, Qclt; intros; eapply Qlt_le_trans; eauto. | |
345 | Qed. | |
346 | ||
347 | Lemma Qlt_trans : forall x y z, x<y -> y<z -> x<z. | |
348 | Proof. | |
349 | unfold Qclt; intros; eapply Qlt_trans; eauto. | |
350 | Qed. | |
351 | ||
352 | (** [x<y] iff [~(y<=x)] *) | |
353 | ||
354 | Lemma Qcnot_lt_le : forall x y, ~ x<y -> y<=x. | |
355 | Proof. | |
356 | unfold Qcle, Qclt; intros; apply Qnot_lt_le; auto. | |
357 | Qed. | |
358 | ||
359 | Lemma Qcnot_le_lt : forall x y, ~ x<=y -> y<x. | |
360 | Proof. | |
361 | unfold Qcle, Qclt; intros; apply Qnot_le_lt; auto. | |
362 | Qed. | |
363 | ||
364 | Lemma Qclt_not_le : forall x y, x<y -> ~ y<=x. | |
365 | Proof. | |
366 | unfold Qcle, Qclt; intros; apply Qlt_not_le; auto. | |
367 | Qed. | |
368 | ||
369 | Lemma Qcle_not_lt : forall x y, x<=y -> ~ y<x. | |
370 | Proof. | |
371 | unfold Qcle, Qclt; intros; apply Qle_not_lt; auto. | |
372 | Qed. | |
373 | ||
374 | Lemma Qcle_lt_or_eq : forall x y, x<=y -> x<y \/ x==y. | |
375 | Proof. | |
376 | unfold Qcle, Qclt; intros; apply Qle_lt_or_eq; auto. | |
377 | Qed. | |
378 | ||
379 | (** Some decidability results about orders. *) | |
380 | ||
381 | Lemma Qc_dec : forall x y, {x<y} + {y<x} + {x=y}. | |
382 | Proof. | |
383 | unfold Qclt, Qcle; intros. | |
384 | destruct (Q_dec x y) as [H|H]. | |
385 | left; auto. | |
386 | right; apply Qc_is_canon; auto. | |
387 | Defined. | |
388 | ||
389 | Lemma Qclt_le_dec : forall x y, {x<y} + {y<=x}. | |
390 | Proof. | |
391 | unfold Qclt, Qcle; intros; apply Qlt_le_dec; auto. | |
392 | Defined. | |
393 | ||
394 | (** Compatibility of operations with respect to order. *) | |
395 | ||
396 | Lemma Qcopp_le_compat : forall p q, p<=q -> -q <= -p. | |
397 | Proof. | |
398 | unfold Qcle, Qcopp; intros; simpl in *. | |
399 | repeat rewrite Qred_correct. | |
400 | apply Qopp_le_compat; auto. | |
401 | Qed. | |
402 | ||
403 | Lemma Qcle_minus_iff : forall p q, p <= q <-> 0 <= q+-p. | |
404 | Proof. | |
405 | unfold Qcle, Qcminus; intros; simpl in *. | |
406 | repeat rewrite Qred_correct. | |
407 | apply Qle_minus_iff; auto. | |
408 | Qed. | |
409 | ||
410 | Lemma Qclt_minus_iff : forall p q, p < q <-> 0 < q+-p. | |
411 | Proof. | |
412 | unfold Qclt, Qcplus, Qcopp; intros; simpl in *. | |
413 | repeat rewrite Qred_correct. | |
414 | apply Qlt_minus_iff; auto. | |
415 | Qed. | |
416 | ||
417 | Lemma Qcplus_le_compat : | |
418 | forall x y z t, x<=y -> z<=t -> x+z <= y+t. | |
419 | Proof. | |
420 | unfold Qcplus, Qcle; intros; simpl in *. | |
421 | repeat rewrite Qred_correct. | |
422 | apply Qplus_le_compat; auto. | |
423 | Qed. | |
424 | ||
425 | Lemma Qcmult_le_compat_r : forall x y z, x <= y -> 0 <= z -> x*z <= y*z. | |
426 | Proof. | |
427 | unfold Qcmult, Qcle; intros; simpl in *. | |
428 | repeat rewrite Qred_correct. | |
429 | apply Qmult_le_compat_r; auto. | |
430 | Qed. | |
431 | ||
432 | Lemma Qcmult_lt_0_le_reg_r : forall x y z, 0 < z -> x*z <= y*z -> x <= y. | |
433 | Proof. | |
434 | unfold Qcmult, Qcle, Qclt; intros; simpl in *. | |
435 | repeat progress rewrite Qred_correct in * |-. | |
436 | eapply Qmult_lt_0_le_reg_r; eauto. | |
437 | Qed. | |
438 | ||
439 | Lemma Qcmult_lt_compat_r : forall x y z, 0 < z -> x < y -> x*z < y*z. | |
440 | Proof. | |
441 | unfold Qcmult, Qclt; intros; simpl in *. | |
442 | repeat progress rewrite Qred_correct in *. | |
443 | eapply Qmult_lt_compat_r; eauto. | |
444 | Qed. | |
445 | ||
446 | (** Rational to the n-th power *) | |
447 | ||
448 | Fixpoint Qcpower (q:Qc)(n:nat) { struct n } : Qc := | |
449 | match n with | |
450 | | O => 1 | |
451 | | S n => q * (Qcpower q n) | |
452 | end. | |
453 | ||
454 | Notation " q ^ n " := (Qcpower q n) : Qc_scope. | |
455 | ||
456 | Lemma Qcpower_1 : forall n, 1^n = 1. | |
457 | Proof. | |
458 | induction n; simpl; auto with qarith. | |
459 | rewrite IHn; auto with qarith. | |
460 | Qed. | |
461 | ||
462 | Lemma Qcpower_0 : forall n, n<>O -> 0^n = 0. | |
463 | Proof. | |
464 | destruct n; simpl. | |
465 | destruct 1; auto. | |
466 | intros. | |
467 | apply Qc_is_canon. | |
468 | simpl. | |
469 | compute; auto. | |
470 | Qed. | |
471 | ||
472 | Lemma Qpower_pos : forall p n, 0 <= p -> 0 <= p^n. | |
473 | Proof. | |
474 | induction n; simpl; auto with qarith. | |
475 | intros; compute; intro; discriminate. | |
476 | intros. | |
477 | apply Qcle_trans with (0*(p^n)). | |
478 | compute; intro; discriminate. | |
479 | apply Qcmult_le_compat_r; auto. | |
480 | Qed. | |
481 | ||
482 | (** And now everything is easier concerning tactics: *) | |
483 | ||
484 | (** A ring tactic for rational numbers *) | |
485 | ||
486 | Definition Qc_eq_bool (x y : Qc) := | |
487 | if Qc_eq_dec x y then true else false. | |
488 | ||
489 | Lemma Qc_eq_bool_correct : forall x y : Qc, Qc_eq_bool x y = true -> x=y. | |
490 | intros x y; unfold Qc_eq_bool in |- *; case (Qc_eq_dec x y); simpl in |- *; auto. | |
491 | intros _ H; inversion H. | |
492 | Qed. | |
493 | ||
494 | Definition Qcrt : Ring_Theory Qcplus Qcmult 1 0 Qcopp Qc_eq_bool. | |
495 | Proof. | |
496 | constructor. | |
497 | exact Qcplus_comm. | |
498 | exact Qcplus_assoc. | |
499 | exact Qcmult_comm. | |
500 | exact Qcmult_assoc. | |
501 | exact Qcplus_0_l. | |
502 | exact Qcmult_1_l. | |
503 | exact Qcplus_opp_r. | |
504 | exact Qcmult_plus_distr_l. | |
505 | unfold Is_true; intros x y; generalize (Qc_eq_bool_correct x y); | |
506 | case (Qc_eq_bool x y); auto. | |
507 | Qed. | |
508 | ||
509 | Add Ring Qc Qcplus Qcmult 1 0 Qcopp Qc_eq_bool Qcrt [ Qcmake ]. | |
510 | ||
511 | (** A field tactic for rational numbers *) | |
512 | ||
513 | Require Import Field. | |
514 | ||
515 | Add Field Qc Qcplus Qcmult 1 0 Qcopp Qc_eq_bool Qcinv Qcrt Qcmult_inv_l | |
516 | with div:=Qcdiv. | |
517 | ||
518 | Example test_field : forall x y : Qc, y<>0 -> (x/y)*y = x. | |
519 | intros. | |
520 | field. | |
521 | auto. | |
522 | Qed. | |
523 | ||
524 | ||
525 |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (*i $Id: Qreduction.v 8883 2006-05-31 21:56:37Z letouzey $ i*) | |
8 | (*i $Id: Qreduction.v 8989 2006-06-25 22:17:49Z letouzey $ i*) | |
9 | 9 | |
10 | 10 | (** * Normalisation functions for rational numbers. *) |
11 | 11 | |
31 | 31 | simple destruct z; simpl in |- *; auto; intros; elim H; auto. |
32 | 32 | Qed. |
33 | 33 | |
34 | (** A simple cancelation by powers of two *) | |
35 | ||
36 | Fixpoint Pfactor_twos (p p':positive) {struct p} : (positive*positive) := | |
37 | match p, p' with | |
38 | | xO p, xO p' => Pfactor_twos p p' | |
39 | | _, _ => (p,p') | |
40 | end. | |
41 | ||
42 | Definition Qfactor_twos (q:Q) := | |
43 | let (p,q) := q in | |
44 | match p with | |
45 | | Z0 => 0 | |
46 | | Zpos p => let (p,q) := Pfactor_twos p q in (Zpos p)#q | |
47 | | Zneg p => let (p,q) := Pfactor_twos p q in (Zneg p)#q | |
48 | end. | |
49 | ||
50 | Lemma Pfactor_twos_correct : forall p p', | |
51 | (p*(snd (Pfactor_twos p p')))%positive = | |
52 | (p'*(fst (Pfactor_twos p p')))%positive. | |
53 | Proof. | |
54 | induction p; intros. | |
55 | simpl snd; simpl fst; rewrite Pmult_comm; auto. | |
56 | destruct p'. | |
57 | simpl snd; simpl fst; rewrite Pmult_comm; auto. | |
58 | simpl; f_equal; auto. | |
59 | simpl snd; simpl fst; rewrite Pmult_comm; auto. | |
60 | simpl snd; simpl fst; rewrite Pmult_comm; auto. | |
61 | Qed. | |
62 | ||
63 | Lemma Qfactor_twos_correct : forall q, Qfactor_twos q == q. | |
64 | Proof. | |
65 | intros (p,q). | |
66 | destruct p. | |
67 | red; simpl; auto. | |
68 | simpl. | |
69 | generalize (Pfactor_twos_correct p q); destruct (Pfactor_twos p q). | |
70 | red; simpl. | |
71 | intros; f_equal. | |
72 | rewrite H; apply Pmult_comm. | |
73 | simpl. | |
74 | generalize (Pfactor_twos_correct p q); destruct (Pfactor_twos p q). | |
75 | red; simpl. | |
76 | intros; f_equal. | |
77 | rewrite H; apply Pmult_comm. | |
78 | Qed. | |
79 | Hint Resolve Qfactor_twos_correct. | |
80 | ||
81 | 34 | (** Simplification of fractions using [Zgcd]. |
82 | 35 | This version can compute within Coq. *) |
83 | 36 | |
84 | 37 | Definition Qred (q:Q) := |
85 | let (q1,q2) := Qfactor_twos q in | |
86 | let (r1,r2) := snd (Zggcd q1 (Zpos q2)) in r1#(Z2P r2). | |
38 | let (q1,q2) := q in | |
39 | let (r1,r2) := snd (Zggcd q1 ('q2)) | |
40 | in r1#(Z2P r2). | |
87 | 41 | |
88 | 42 | Lemma Qred_correct : forall q, (Qred q) == q. |
89 | 43 | Proof. |
90 | intros; apply Qeq_trans with (Qfactor_twos q); auto. | |
91 | unfold Qred. | |
92 | destruct (Qfactor_twos q) as (n,d); red; simpl. | |
44 | unfold Qred, Qeq; intros (n,d); simpl. | |
93 | 45 | generalize (Zggcd_gcd n ('d)) (Zgcd_is_pos n ('d)) |
94 | 46 | (Zgcd_is_gcd n ('d)) (Zggcd_correct_divisors n ('d)). |
95 | 47 | destruct (Zggcd n (Zpos d)) as (g,(nn,dd)); simpl. |
111 | 63 | |
112 | 64 | Lemma Qred_complete : forall p q, p==q -> Qred p = Qred q. |
113 | 65 | Proof. |
114 | intros. | |
115 | assert (Qfactor_twos p == Qfactor_twos q). | |
116 | apply Qeq_trans with p; auto. | |
117 | apply Qeq_trans with q; auto. | |
118 | symmetry; auto. | |
119 | clear H. | |
120 | unfold Qred. | |
121 | destruct (Qfactor_twos p) as (a,b); | |
122 | destruct (Qfactor_twos q) as (c,d); clear p q. | |
123 | unfold Qeq in *; simpl in *. | |
66 | intros (a,b) (c,d). | |
67 | unfold Qred, Qeq in *; simpl in *. | |
124 | 68 | Open Scope Z_scope. |
125 | 69 | generalize (Zggcd_gcd a ('b)) (Zgcd_is_gcd a ('b)) |
126 | 70 | (Zgcd_is_pos a ('b)) (Zggcd_correct_divisors a ('b)). |
197 | 141 | rewrite (Qred_correct q'); auto. |
198 | 142 | Qed. |
199 | 143 | |
200 | (** Another version, dedicated to extraction *) | |
201 | ||
202 | Definition Qred_extr (q : Q) := | |
203 | let (q1, q2) := Qfactor_twos q in | |
204 | let (p,_) := Zggcd_spec_pos (Zpos q2) (Zle_0_pos q2) q1 in | |
205 | let (r2,r1) := snd p in r1#(Z2P r2). | |
206 | ||
207 | Lemma Qred_extr_Qred : forall q, Qred_extr q = Qred q. | |
208 | Proof. | |
209 | unfold Qred, Qred_extr. | |
210 | intro q; destruct (Qfactor_twos q) as (n,p); clear q. | |
211 | Open Scope Z_scope. | |
212 | destruct (Zggcd_spec_pos (' p) (Zle_0_pos p) n) as ((g,(pp,nn)),H). | |
213 | generalize (H (Zle_0_pos p)); clear H; intros (Hg1,(Hg2,(Hg4,Hg3))). | |
214 | simpl. | |
215 | generalize (Zggcd_gcd n ('p)) (Zgcd_is_gcd n ('p)) | |
216 | (Zgcd_is_pos n ('p)) (Zggcd_correct_divisors n ('p)). | |
217 | destruct (Zggcd n (Zpos p)) as (g',(nn',pp')); simpl. | |
218 | intro H; rewrite <- H; clear H. | |
219 | intros Hg'1 Hg'2 (Hg'3,Hg'4). | |
220 | assert (g<>0). | |
221 | intro; subst g; discriminate. | |
222 | destruct (Zis_gcd_uniqueness_apart_sign n ('p) g g'); auto. | |
223 | apply Zis_gcd_sym; auto. | |
224 | subst g'. | |
225 | f_equal. | |
226 | apply Zmult_reg_l with g; auto; congruence. | |
227 | f_equal. | |
228 | apply Zmult_reg_l with g; auto; congruence. | |
229 | elimtype False; omega. | |
230 | Open Scope Q_scope. | |
231 | Qed. | |
232 | ||
233 | Add Morphism Qred_extr : Qred_extr_comp. | |
234 | Proof. | |
235 | intros q q' H. | |
236 | do 2 rewrite Qred_extr_Qred. | |
237 | rewrite (Qred_correct q); auto. | |
238 | rewrite (Qred_correct q'); auto. | |
239 | Qed. | |
240 | ||
241 | 144 | Definition Qplus' (p q : Q) := Qred (Qplus p q). |
242 | 145 | Definition Qmult' (p q : Q) := Qred (Qmult p q). |
243 | 146 |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (*i $Id: Ranalysis1.v 8670 2006-03-28 22:16:14Z herbelin $ i*) | |
8 | (*i $Id: Ranalysis1.v 9042 2006-07-11 22:06:48Z herbelin $ i*) | |
9 | 9 | |
10 | 10 | Require Import Rbase. |
11 | 11 | Require Import Rfunctions. |
26 | 26 | Definition comp f1 f2 (x:R) : R := f1 (f2 x). |
27 | 27 | Definition inv_fct f (x:R) : R := / f x. |
28 | 28 | |
29 | Delimit Scope Rfun_scope with F. | |
30 | ||
31 | Arguments Scope plus_fct [Rfun_scope Rfun_scope R_scope]. | |
32 | Arguments Scope mult_fct [Rfun_scope Rfun_scope R_scope]. | |
33 | Arguments Scope minus_fct [Rfun_scope Rfun_scope R_scope]. | |
34 | Arguments Scope div_fct [Rfun_scope Rfun_scope R_scope]. | |
35 | Arguments Scope inv_fct [Rfun_scope R_scope]. | |
36 | Arguments Scope opp_fct [Rfun_scope R_scope]. | |
37 | Arguments Scope mult_real_fct [R_scope Rfun_scope R_scope]. | |
38 | Arguments Scope div_real_fct [R_scope Rfun_scope R_scope]. | |
39 | Arguments Scope comp [Rfun_scope Rfun_scope R_scope]. | |
40 | ||
29 | 41 | Infix "+" := plus_fct : Rfun_scope. |
30 | 42 | Notation "- x" := (opp_fct x) : Rfun_scope. |
31 | 43 | Infix "*" := mult_fct : Rfun_scope. |
34 | 46 | Notation Local "f1 'o' f2" := (comp f1 f2) |
35 | 47 | (at level 20, right associativity) : Rfun_scope. |
36 | 48 | Notation "/ x" := (inv_fct x) : Rfun_scope. |
37 | ||
38 | Delimit Scope Rfun_scope with F. | |
39 | 49 | |
40 | 50 | Definition fct_cte (a x:R) : R := a. |
41 | 51 | Definition id (x:R) := x. |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (*i $Id: Znumtheory.v 8853 2006-05-23 18:17:38Z herbelin $ i*) | |
8 | (*i $Id: Znumtheory.v 8990 2006-06-26 13:57:44Z notin $ i*) | |
9 | 9 | |
10 | 10 | Require Import ZArith_base. |
11 | 11 | Require Import ZArithRing. |
12 | 12 | Require Import Zcomplements. |
13 | 13 | Require Import Zdiv. |
14 | Require Import Ndigits. | |
15 | Require Import Wf_nat. | |
14 | 16 | Open Local Scope Z_scope. |
15 | 17 | |
16 | 18 | (** This file contains some notions of number theory upon Z numbers: |
17 | 19 | - a divisibility predicate [Zdivide] |
18 | 20 | - a gcd predicate [gcd] |
19 | 21 | - Euclid algorithm [euclid] |
20 | - an efficient [Zgcd] function | |
21 | 22 | - a relatively prime predicate [rel_prime] |
22 | 23 | - a prime predicate [prime] |
24 | - an efficient [Zgcd] function | |
23 | 25 | *) |
24 | 26 | |
25 | 27 | (** * Divisibility *) |
214 | 216 | constructor; auto with zarith. |
215 | 217 | Qed. |
216 | 218 | |
219 | Lemma Zis_gcd_1 : forall a, Zis_gcd a 1 1. | |
220 | Proof. | |
221 | constructor; auto with zarith. | |
222 | Qed. | |
223 | ||
224 | Lemma Zis_gcd_refl : forall a, Zis_gcd a a a. | |
225 | Proof. | |
226 | constructor; auto with zarith. | |
227 | Qed. | |
228 | ||
217 | 229 | Lemma Zis_gcd_minus : forall a b d:Z, Zis_gcd a (- b) d -> Zis_gcd b a d. |
218 | 230 | Proof. |
219 | 231 | simple induction 1; constructor; intuition. |
222 | 234 | Lemma Zis_gcd_opp : forall a b d:Z, Zis_gcd a b d -> Zis_gcd b a (- d). |
223 | 235 | Proof. |
224 | 236 | simple induction 1; constructor; intuition. |
237 | Qed. | |
238 | ||
239 | Lemma Zis_gcd_0_abs : forall a:Z, Zis_gcd 0 a (Zabs a). | |
240 | Proof. | |
241 | intros a. | |
242 | apply Zabs_ind. | |
243 | intros; apply Zis_gcd_sym; apply Zis_gcd_0; auto. | |
244 | intros; apply Zis_gcd_opp; apply Zis_gcd_0; auto. | |
225 | 245 | Qed. |
226 | 246 | |
227 | 247 | Hint Resolve Zis_gcd_sym Zis_gcd_0 Zis_gcd_minus Zis_gcd_opp: zarith. |
365 | 385 | rewrite H6; rewrite H7; ring. |
366 | 386 | ring. |
367 | 387 | Qed. |
368 | ||
369 | Lemma Zis_gcd_0_abs : forall b, | |
370 | Zis_gcd 0 b (Zabs b) /\ Zabs b >= 0 /\ 0 = Zabs b * 0 /\ b = Zabs b * Zsgn b. | |
371 | Proof. | |
372 | intro b. | |
373 | elim (Z_le_lt_eq_dec _ _ (Zabs_pos b)). | |
374 | intros H0; split. | |
375 | apply Zabs_ind. | |
376 | intros; apply Zis_gcd_sym; apply Zis_gcd_0; auto. | |
377 | intros; apply Zis_gcd_opp; apply Zis_gcd_0; auto. | |
378 | repeat split; auto with zarith. | |
379 | symmetry; apply Zabs_Zsgn. | |
380 | ||
381 | intros H0; rewrite <- H0. | |
382 | rewrite <- (Zabs_Zsgn b); rewrite <- H0; simpl in |- *. | |
383 | split; [ apply Zis_gcd_0 | idtac ]; auto with zarith. | |
384 | Qed. | |
385 | 388 | |
386 | ||
387 | (** We could obtain a [Zgcd] function via [euclid]. But we propose | |
388 | here a more direct version of a [Zgcd], that can compute within Coq. | |
389 | For that, we use an explicit measure in [nat], and we proved later | |
390 | that using [2(d+1)] is enough, where [d] is the number of binary digits | |
391 | of the first argument. *) | |
392 | ||
393 | Fixpoint Zgcdn (n:nat) : Z -> Z -> Z := fun a b => | |
394 | match n with | |
395 | | O => 1 (* arbitrary, since n should be big enough *) | |
396 | | S n => match a with | |
397 | | Z0 => Zabs b | |
398 | | Zpos _ => Zgcdn n (Zmod b a) a | |
399 | | Zneg a => Zgcdn n (Zmod b (Zpos a)) (Zpos a) | |
400 | end | |
401 | end. | |
402 | ||
403 | (* For technical reason, we don't use [Ndigit.Psize] but this | |
404 | ad-hoc version: [Psize p = S (Psiz p)]. *) | |
405 | ||
406 | Fixpoint Psiz (p:positive) : nat := | |
407 | match p with | |
408 | | xH => O | |
409 | | xI p => S (Psiz p) | |
410 | | xO p => S (Psiz p) | |
411 | end. | |
412 | ||
413 | Definition Zgcd_bound (a:Z) := match a with | |
414 | | Z0 => S O | |
415 | | Zpos p => let n := Psiz p in S (S (n+n)) | |
416 | | Zneg p => let n := Psiz p in S (S (n+n)) | |
417 | end. | |
418 | ||
419 | Definition Zgcd a b := Zgcdn (Zgcd_bound a) a b. | |
420 | ||
421 | (** A first obvious fact : [Zgcd a b] is positive. *) | |
422 | ||
423 | Lemma Zgcdn_is_pos : forall n a b, | |
424 | 0 <= Zgcdn n a b. | |
425 | Proof. | |
426 | induction n. | |
427 | simpl; auto with zarith. | |
428 | destruct a; simpl; intros; auto with zarith; auto. | |
429 | Qed. | |
430 | ||
431 | Lemma Zgcd_is_pos : forall a b, 0 <= Zgcd a b. | |
432 | Proof. | |
433 | intros; unfold Zgcd; apply Zgcdn_is_pos; auto. | |
434 | Qed. | |
435 | ||
436 | (** We now prove that Zgcd is indeed a gcd. *) | |
437 | ||
438 | (** 1) We prove a weaker & easier bound. *) | |
439 | ||
440 | Lemma Zgcdn_linear_bound : forall n a b, | |
441 | Zabs a < Z_of_nat n -> Zis_gcd a b (Zgcdn n a b). | |
442 | Proof. | |
443 | induction n. | |
444 | simpl; intros. | |
445 | elimtype False; generalize (Zabs_pos a); omega. | |
446 | destruct a; intros; simpl; | |
447 | [ generalize (Zis_gcd_0_abs b); intuition | | ]; | |
448 | unfold Zmod; | |
449 | generalize (Z_div_mod b (Zpos p) (refl_equal Gt)); | |
450 | destruct (Zdiv_eucl b (Zpos p)) as (q,r); | |
451 | intros (H0,H1); | |
452 | rewrite inj_S in H; simpl Zabs in H; | |
453 | assert (H2: Zabs r < Z_of_nat n) by (rewrite Zabs_eq; auto with zarith); | |
454 | assert (IH:=IHn r (Zpos p) H2); clear IHn; | |
455 | simpl in IH |- *; | |
456 | rewrite H0. | |
457 | apply Zis_gcd_for_euclid2; auto. | |
458 | apply Zis_gcd_minus; apply Zis_gcd_sym. | |
459 | apply Zis_gcd_for_euclid2; auto. | |
460 | Qed. | |
461 | ||
462 | (** 2) For Euclid's algorithm, the worst-case situation corresponds | |
463 | to Fibonacci numbers. Let's define them: *) | |
464 | ||
465 | Fixpoint fibonacci (n:nat) : Z := | |
466 | match n with | |
467 | | O => 1 | |
468 | | S O => 1 | |
469 | | S (S n as p) => fibonacci p + fibonacci n | |
470 | end. | |
471 | ||
472 | Lemma fibonacci_pos : forall n, 0 <= fibonacci n. | |
473 | Proof. | |
474 | cut (forall N n, (n<N)%nat -> 0<=fibonacci n). | |
475 | eauto. | |
476 | induction N. | |
477 | inversion 1. | |
478 | intros. | |
479 | destruct n. | |
480 | simpl; auto with zarith. | |
481 | destruct n. | |
482 | simpl; auto with zarith. | |
483 | change (0 <= fibonacci (S n) + fibonacci n). | |
484 | generalize (IHN n) (IHN (S n)); omega. | |
485 | Qed. | |
486 | ||
487 | Lemma fibonacci_incr : | |
488 | forall n m, (n<=m)%nat -> fibonacci n <= fibonacci m. | |
489 | Proof. | |
490 | induction 1. | |
491 | auto with zarith. | |
492 | apply Zle_trans with (fibonacci m); auto. | |
493 | clear. | |
494 | destruct m. | |
495 | simpl; auto with zarith. | |
496 | change (fibonacci (S m) <= fibonacci (S m)+fibonacci m). | |
497 | generalize (fibonacci_pos m); omega. | |
498 | Qed. | |
499 | ||
500 | (** 3) We prove that fibonacci numbers are indeed worst-case: | |
501 | for a given number [n], if we reach a conclusion about [gcd(a,b)] in | |
502 | exactly [n+1] loops, then [fibonacci (n+1)<=a /\ fibonacci(n+2)<=b] *) | |
503 | ||
504 | Lemma Zgcdn_worst_is_fibonacci : forall n a b, | |
505 | 0 < a < b -> | |
506 | Zis_gcd a b (Zgcdn (S n) a b) -> | |
507 | Zgcdn n a b <> Zgcdn (S n) a b -> | |
508 | fibonacci (S n) <= a /\ | |
509 | fibonacci (S (S n)) <= b. | |
510 | Proof. | |
511 | induction n. | |
512 | simpl; intros. | |
513 | destruct a; omega. | |
514 | intros. | |
515 | destruct a; [simpl in *; omega| | destruct H; discriminate]. | |
516 | revert H1; revert H0. | |
517 | set (m:=S n) in *; (assert (m=S n) by auto); clearbody m. | |
518 | pattern m at 2; rewrite H0. | |
519 | simpl Zgcdn. | |
520 | unfold Zmod; generalize (Z_div_mod b (Zpos p) (refl_equal Gt)). | |
521 | destruct (Zdiv_eucl b (Zpos p)) as (q,r). | |
522 | intros (H1,H2). | |
523 | destruct H2. | |
524 | destruct (Zle_lt_or_eq _ _ H2). | |
525 | generalize (IHn _ _ (conj H4 H3)). | |
526 | intros H5 H6 H7. | |
527 | replace (fibonacci (S (S m))) with (fibonacci (S m) + fibonacci m) by auto. | |
528 | assert (r = Zpos p * (-q) + b) by (rewrite H1; ring). | |
529 | destruct H5; auto. | |
530 | pattern r at 1; rewrite H8. | |
531 | apply Zis_gcd_sym. | |
532 | apply Zis_gcd_for_euclid2; auto. | |
533 | apply Zis_gcd_sym; auto. | |
534 | split; auto. | |
535 | rewrite H1. | |
536 | apply Zplus_le_compat; auto. | |
537 | apply Zle_trans with (Zpos p * 1); auto. | |
538 | ring (Zpos p * 1); auto. | |
539 | apply Zmult_le_compat_l. | |
540 | destruct q. | |
541 | omega. | |
542 | assert (0 < Zpos p0) by (compute; auto). | |
543 | omega. | |
544 | assert (Zpos p * Zneg p0 < 0) by (compute; auto). | |
545 | omega. | |
546 | compute; intros; discriminate. | |
547 | (* r=0 *) | |
548 | subst r. | |
549 | simpl; rewrite H0. | |
550 | intros. | |
551 | simpl in H4. | |
552 | simpl in H5. | |
553 | destruct n. | |
554 | simpl in H5. | |
555 | simpl. | |
556 | omega. | |
557 | simpl in H5. | |
558 | elim H5; auto. | |
559 | Qed. | |
560 | ||
561 | (** 3b) We reformulate the previous result in a more positive way. *) | |
562 | ||
563 | Lemma Zgcdn_ok_before_fibonacci : forall n a b, | |
564 | 0 < a < b -> a < fibonacci (S n) -> | |
565 | Zis_gcd a b (Zgcdn n a b). | |
566 | Proof. | |
567 | destruct a; [ destruct 1; elimtype False; omega | | destruct 1; discriminate]. | |
568 | cut (forall k n b, | |
569 | k = (S (nat_of_P p) - n)%nat -> | |
570 | 0 < Zpos p < b -> Zpos p < fibonacci (S n) -> | |
571 | Zis_gcd (Zpos p) b (Zgcdn n (Zpos p) b)). | |
572 | destruct 2; eauto. | |
573 | clear n; induction k. | |
574 | intros. | |
575 | assert (nat_of_P p < n)%nat by omega. | |
576 | apply Zgcdn_linear_bound. | |
577 | simpl. | |
578 | generalize (inj_le _ _ H2). | |
579 | rewrite inj_S. | |
580 | rewrite <- Zpos_eq_Z_of_nat_o_nat_of_P; auto. | |
581 | omega. | |
582 | intros. | |
583 | generalize (Zgcdn_worst_is_fibonacci n (Zpos p) b H0); intros. | |
584 | assert (Zis_gcd (Zpos p) b (Zgcdn (S n) (Zpos p) b)). | |
585 | apply IHk; auto. | |
586 | omega. | |
587 | replace (fibonacci (S (S n))) with (fibonacci (S n)+fibonacci n) by auto. | |
588 | generalize (fibonacci_pos n); omega. | |
589 | replace (Zgcdn n (Zpos p) b) with (Zgcdn (S n) (Zpos p) b); auto. | |
590 | generalize (H2 H3); clear H2 H3; omega. | |
591 | Qed. | |
592 | ||
593 | (** 4) The proposed bound leads to a fibonacci number that is big enough. *) | |
594 | ||
595 | Lemma Zgcd_bound_fibonacci : | |
596 | forall a, 0 < a -> a < fibonacci (Zgcd_bound a). | |
597 | Proof. | |
598 | destruct a; [omega| | intro H; discriminate]. | |
599 | intros _. | |
600 | induction p. | |
601 | simpl Zgcd_bound in *. | |
602 | rewrite Zpos_xI. | |
603 | rewrite plus_comm; simpl plus. | |
604 | set (n:=S (Psiz p+Psiz p)) in *. | |
605 | change (2*Zpos p+1 < | |
606 | fibonacci (S n) + fibonacci n + fibonacci (S n)). | |
607 | generalize (fibonacci_pos n). | |
608 | omega. | |
609 | simpl Zgcd_bound in *. | |
610 | rewrite Zpos_xO. | |
611 | rewrite plus_comm; simpl plus. | |
612 | set (n:= S (Psiz p +Psiz p)) in *. | |
613 | change (2*Zpos p < | |
614 | fibonacci (S n) + fibonacci n + fibonacci (S n)). | |
615 | generalize (fibonacci_pos n). | |
616 | omega. | |
617 | simpl; auto with zarith. | |
618 | Qed. | |
619 | ||
620 | (* 5) the end: we glue everything together and take care of | |
621 | situations not corresponding to [0<a<b]. *) | |
622 | ||
623 | Lemma Zgcd_is_gcd : | |
624 | forall a b, Zis_gcd a b (Zgcd a b). | |
625 | Proof. | |
626 | unfold Zgcd; destruct a; intros. | |
627 | simpl; generalize (Zis_gcd_0_abs b); intuition. | |
628 | (*Zpos*) | |
629 | generalize (Zgcd_bound_fibonacci (Zpos p)). | |
630 | simpl Zgcd_bound. | |
631 | set (n:=S (Psiz p+Psiz p)); (assert (n=S (Psiz p+Psiz p)) by auto); clearbody n. | |
632 | simpl Zgcdn. | |
633 | unfold Zmod. | |
634 | generalize (Z_div_mod b (Zpos p) (refl_equal Gt)). | |
635 | destruct (Zdiv_eucl b (Zpos p)) as (q,r). | |
636 | intros (H1,H2) H3. | |
637 | rewrite H1. | |
638 | apply Zis_gcd_for_euclid2. | |
639 | destruct H2. | |
640 | destruct (Zle_lt_or_eq _ _ H0). | |
641 | apply Zgcdn_ok_before_fibonacci; auto; omega. | |
642 | subst r n; simpl. | |
643 | apply Zis_gcd_sym; apply Zis_gcd_0. | |
644 | (*Zneg*) | |
645 | generalize (Zgcd_bound_fibonacci (Zpos p)). | |
646 | simpl Zgcd_bound. | |
647 | set (n:=S (Psiz p+Psiz p)); (assert (n=S (Psiz p+Psiz p)) by auto); clearbody n. | |
648 | simpl Zgcdn. | |
649 | unfold Zmod. | |
650 | generalize (Z_div_mod b (Zpos p) (refl_equal Gt)). | |
651 | destruct (Zdiv_eucl b (Zpos p)) as (q,r). | |
652 | intros (H1,H2) H3. | |
653 | rewrite H1. | |
654 | apply Zis_gcd_minus. | |
655 | apply Zis_gcd_sym. | |
656 | apply Zis_gcd_for_euclid2. | |
657 | destruct H2. | |
658 | destruct (Zle_lt_or_eq _ _ H0). | |
659 | apply Zgcdn_ok_before_fibonacci; auto; omega. | |
660 | subst r n; simpl. | |
661 | apply Zis_gcd_sym; apply Zis_gcd_0. | |
662 | Qed. | |
663 | ||
664 | (** A generalized gcd: it additionnally keeps track of the divisors. *) | |
665 | ||
666 | Fixpoint Zggcdn (n:nat) : Z -> Z -> (Z*(Z*Z)) := fun a b => | |
667 | match n with | |
668 | | O => (1,(a,b)) (*(Zabs b,(0,Zsgn b))*) | |
669 | | S n => match a with | |
670 | | Z0 => (Zabs b,(0,Zsgn b)) | |
671 | | Zpos _ => | |
672 | let (q,r) := Zdiv_eucl b a in (* b = q*a+r *) | |
673 | let (g,p) := Zggcdn n r a in | |
674 | let (rr,aa) := p in (* r = g *rr /\ a = g * aa *) | |
675 | (g,(aa,q*aa+rr)) | |
676 | | Zneg a => | |
677 | let (q,r) := Zdiv_eucl b (Zpos a) in (* b = q*(-a)+r *) | |
678 | let (g,p) := Zggcdn n r (Zpos a) in | |
679 | let (rr,aa) := p in (* r = g*rr /\ (-a) = g * aa *) | |
680 | (g,(-aa,q*aa+rr)) | |
681 | end | |
682 | end. | |
683 | ||
684 | Definition Zggcd a b : Z * (Z * Z) := Zggcdn (Zgcd_bound a) a b. | |
685 | ||
686 | (** The first component of [Zggcd] is [Zgcd] *) | |
687 | ||
688 | Lemma Zggcdn_gcdn : forall n a b, | |
689 | fst (Zggcdn n a b) = Zgcdn n a b. | |
690 | Proof. | |
691 | induction n; simpl; auto. | |
692 | destruct a; unfold Zmod; simpl; intros; auto; | |
693 | destruct (Zdiv_eucl b (Zpos p)) as (q,r); | |
694 | rewrite <- IHn; | |
695 | destruct (Zggcdn n r (Zpos p)) as (g,(rr,aa)); simpl; auto. | |
696 | Qed. | |
697 | ||
698 | Lemma Zggcd_gcd : forall a b, fst (Zggcd a b) = Zgcd a b. | |
699 | Proof. | |
700 | intros; unfold Zggcd, Zgcd; apply Zggcdn_gcdn; auto. | |
701 | Qed. | |
702 | ||
703 | (** [Zggcd] always returns divisors that are coherent with its | |
704 | first output. *) | |
705 | ||
706 | Lemma Zggcdn_correct_divisors : forall n a b, | |
707 | let (g,p) := Zggcdn n a b in | |
708 | let (aa,bb):=p in | |
709 | a=g*aa /\ b=g*bb. | |
710 | Proof. | |
711 | induction n. | |
712 | simpl. | |
713 | split; [destruct a|destruct b]; auto. | |
714 | intros. | |
715 | simpl. | |
716 | destruct a. | |
717 | rewrite Zmult_comm; simpl. | |
718 | split; auto. | |
719 | symmetry; apply Zabs_Zsgn. | |
720 | generalize (Z_div_mod b (Zpos p)); | |
721 | destruct (Zdiv_eucl b (Zpos p)) as (q,r). | |
722 | generalize (IHn r (Zpos p)); | |
723 | destruct (Zggcdn n r (Zpos p)) as (g,(rr,aa)). | |
724 | intuition. | |
725 | destruct H0. | |
726 | compute; auto. | |
727 | rewrite H; rewrite H1; rewrite H2; ring. | |
728 | generalize (Z_div_mod b (Zpos p)); | |
729 | destruct (Zdiv_eucl b (Zpos p)) as (q,r). | |
730 | destruct 1. | |
731 | compute; auto. | |
732 | generalize (IHn r (Zpos p)); | |
733 | destruct (Zggcdn n r (Zpos p)) as (g,(rr,aa)). | |
734 | intuition. | |
735 | destruct H0. | |
736 | replace (Zneg p) with (-Zpos p) by compute; auto. | |
737 | rewrite H4; ring. | |
738 | rewrite H; rewrite H4; rewrite H0; ring. | |
739 | Qed. | |
740 | ||
741 | Lemma Zggcd_correct_divisors : forall a b, | |
742 | let (g,p) := Zggcd a b in | |
743 | let (aa,bb):=p in | |
744 | a=g*aa /\ b=g*bb. | |
745 | Proof. | |
746 | unfold Zggcd; intros; apply Zggcdn_correct_divisors; auto. | |
747 | Qed. | |
748 | ||
749 | (** Due to the use of an explicit measure, the extraction of [Zgcd] | |
750 | isn't optimal. We propose here another version [Zgcd_spec] that | |
751 | doesn't suffer from this problem (but doesn't compute in Coq). *) | |
752 | ||
753 | Definition Zgcd_spec_pos : | |
754 | forall a:Z, | |
755 | 0 <= a -> forall b:Z, {g : Z | 0 <= a -> Zis_gcd a b g /\ g >= 0}. | |
756 | Proof. | |
757 | intros a Ha. | |
758 | apply | |
759 | (Zlt_0_rec | |
760 | (fun a:Z => forall b:Z, {g : Z | 0 <= a -> Zis_gcd a b g /\ g >= 0})); | |
761 | try assumption. | |
762 | intro x; case x. | |
763 | intros _ _ b; exists (Zabs b). | |
764 | generalize (Zis_gcd_0_abs b); intuition. | |
765 | ||
766 | intros p Hrec _ b. | |
767 | generalize (Z_div_mod b (Zpos p)). | |
768 | case (Zdiv_eucl b (Zpos p)); intros q r Hqr. | |
769 | elim Hqr; clear Hqr; intros; auto with zarith. | |
770 | elim (Hrec r H0 (Zpos p)); intros g Hgkl. | |
771 | inversion_clear H0. | |
772 | elim (Hgkl H1); clear Hgkl; intros H3 H4. | |
773 | exists g; intros. | |
774 | split; auto. | |
775 | rewrite H. | |
776 | apply Zis_gcd_for_euclid2; auto. | |
777 | ||
778 | intros p _ H b. | |
779 | elim H; auto. | |
780 | Defined. | |
781 | ||
782 | Definition Zgcd_spec : forall a b:Z, {g : Z | Zis_gcd a b g /\ g >= 0}. | |
783 | Proof. | |
784 | intros a; case (Z_gt_le_dec 0 a). | |
785 | intros; assert (0 <= - a). | |
786 | omega. | |
787 | elim (Zgcd_spec_pos (- a) H b); intros g Hgkl. | |
788 | exists g. | |
789 | intuition. | |
790 | intros Ha b; elim (Zgcd_spec_pos a Ha b); intros g; exists g; intuition. | |
791 | Defined. | |
792 | ||
793 | (** A last version aimed at extraction that also returns the divisors. *) | |
794 | ||
795 | Definition Zggcd_spec_pos : | |
796 | forall a:Z, | |
797 | 0 <= a -> forall b:Z, {p : Z*(Z*Z) | let (g,p):=p in let (aa,bb):=p in | |
798 | 0 <= a -> Zis_gcd a b g /\ g >= 0 /\ a=g*aa /\ b=g*bb}. | |
799 | Proof. | |
800 | intros a Ha. | |
801 | pattern a; apply Zlt_0_rec; try assumption. | |
802 | intro x; case x. | |
803 | intros _ _ b; exists (Zabs b,(0,Zsgn b)). | |
804 | intros _; apply Zis_gcd_0_abs. | |
805 | ||
806 | intros p Hrec _ b. | |
807 | generalize (Z_div_mod b (Zpos p)). | |
808 | case (Zdiv_eucl b (Zpos p)); intros q r Hqr. | |
809 | elim Hqr; clear Hqr; intros; auto with zarith. | |
810 | destruct (Hrec r H0 (Zpos p)) as ((g,(rr,pp)),Hgkl). | |
811 | destruct H0. | |
812 | destruct (Hgkl H0) as (H3,(H4,(H5,H6))). | |
813 | exists (g,(pp,pp*q+rr)); intros. | |
814 | split; auto. | |
815 | rewrite H. | |
816 | apply Zis_gcd_for_euclid2; auto. | |
817 | repeat split; auto. | |
818 | rewrite H; rewrite H6; rewrite H5; ring. | |
819 | ||
820 | intros p _ H b. | |
821 | elim H; auto. | |
822 | Defined. | |
823 | ||
824 | Definition Zggcd_spec : | |
825 | forall a b:Z, {p : Z*(Z*Z) | let (g,p):=p in let (aa,bb):=p in | |
826 | Zis_gcd a b g /\ g >= 0 /\ a=g*aa /\ b=g*bb}. | |
827 | Proof. | |
828 | intros a; case (Z_gt_le_dec 0 a). | |
829 | intros; assert (0 <= - a). | |
830 | omega. | |
831 | destruct (Zggcd_spec_pos (- a) H b) as ((g,(aa,bb)),Hgkl). | |
832 | exists (g,(-aa,bb)). | |
833 | intuition. | |
834 | rewrite <- Zopp_mult_distr_r. | |
835 | rewrite <- H2; auto with zarith. | |
836 | intros Ha b; elim (Zggcd_spec_pos a Ha b); intros p; exists p. | |
837 | repeat destruct p; intuition. | |
838 | Defined. | |
839 | 389 | |
840 | 390 | (** * Relative primality *) |
841 | 391 | |
919 | 469 | elim H4; intros. |
920 | 470 | rewrite H2 in H6; subst b; omega. |
921 | 471 | unfold rel_prime in |- *. |
922 | elim (Zgcd_spec (a / g) (b / g)); intros g' [H3 H4]. | |
923 | assert (H5 := Zis_gcd_mult _ _ g _ H3). | |
924 | rewrite <- Z_div_exact_2 in H5; auto with zarith. | |
925 | rewrite <- Z_div_exact_2 in H5; auto with zarith. | |
926 | elim (Zis_gcd_uniqueness_apart_sign _ _ _ _ H1 H5). | |
927 | intros; rewrite (Zmult_reg_l 1 g' g); auto with zarith. | |
928 | intros; rewrite (Zmult_reg_l 1 (- g') g); auto with zarith. | |
929 | pattern g at 1 in |- *; rewrite H6; ring. | |
930 | ||
931 | elim H1; intros. | |
932 | elim H7; intros. | |
933 | rewrite H9. | |
934 | replace (q * g) with (0 + q * g). | |
935 | rewrite Z_mod_plus. | |
936 | compute in |- *; auto. | |
937 | omega. | |
938 | ring. | |
939 | ||
940 | elim H1; intros. | |
941 | elim H6; intros. | |
942 | rewrite H9. | |
943 | replace (q * g) with (0 + q * g). | |
944 | rewrite Z_mod_plus. | |
945 | compute in |- *; auto. | |
946 | omega. | |
947 | ring. | |
472 | destruct H1. | |
473 | destruct H1 as (a',H1). | |
474 | destruct H3 as (b',H3). | |
475 | replace (a/g) with a'; | |
476 | [|rewrite H1; rewrite Z_div_mult; auto with zarith]. | |
477 | replace (b/g) with b'; | |
478 | [|rewrite H3; rewrite Z_div_mult; auto with zarith]. | |
479 | constructor. | |
480 | exists a'; auto with zarith. | |
481 | exists b'; auto with zarith. | |
482 | intros x (xa,H5) (xb,H6). | |
483 | destruct (H4 (x*g)). | |
484 | exists xa; rewrite Zmult_assoc; rewrite <- H5; auto. | |
485 | exists xb; rewrite Zmult_assoc; rewrite <- H6; auto. | |
486 | replace g with (1*g) in H7; auto with zarith. | |
487 | do 2 rewrite Zmult_assoc in H7. | |
488 | generalize (Zmult_reg_r _ _ _ H2 H7); clear H7; intros. | |
489 | rewrite Zmult_1_r in H7. | |
490 | exists q; auto with zarith. | |
948 | 491 | Qed. |
949 | 492 | |
950 | 493 | (** * Primality *) |
1044 | 587 | right; apply Gauss with a; auto with zarith. |
1045 | 588 | Qed. |
1046 | 589 | |
590 | ||
591 | (** We could obtain a [Zgcd] function via Euclid algorithm. But we propose | |
592 | here a binary version of [Zgcd], faster and executable within Coq. | |
593 | ||
594 | Algorithm: | |
595 | ||
596 | gcd 0 b = b | |
597 | gcd a 0 = a | |
598 | gcd (2a) (2b) = 2(gcd a b) | |
599 | gcd (2a+1) (2b) = gcd (2a+1) b | |
600 | gcd (2a) (2b+1) = gcd a (2b+1) | |
601 | gcd (2a+1) (2b+1) = gcd (b-a) (2*a+1) | |
602 | or gcd (a-b) (2*b+1), depending on whether a<b | |
603 | *) | |
604 | ||
605 | Open Scope positive_scope. | |
606 | ||
607 | Fixpoint Pgcdn (n: nat) (a b : positive) { struct n } : positive := | |
608 | match n with | |
609 | | O => 1 | |
610 | | S n => | |
611 | match a,b with | |
612 | | xH, _ => 1 | |
613 | | _, xH => 1 | |
614 | | xO a, xO b => xO (Pgcdn n a b) | |
615 | | a, xO b => Pgcdn n a b | |
616 | | xO a, b => Pgcdn n a b | |
617 | | xI a', xI b' => match Pcompare a' b' Eq with | |
618 | | Eq => a | |
619 | | Lt => Pgcdn n (b'-a') a | |
620 | | Gt => Pgcdn n (a'-b') b | |
621 | end | |
622 | end | |
623 | end. | |
624 | ||
625 | Fixpoint Pggcdn (n: nat) (a b : positive) { struct n } : (positive*(positive*positive)) := | |
626 | match n with | |
627 | | O => (1,(a,b)) | |
628 | | S n => | |
629 | match a,b with | |
630 | | xH, b => (1,(1,b)) | |
631 | | a, xH => (1,(a,1)) | |
632 | | xO a, xO b => | |
633 | let (g,p) := Pggcdn n a b in | |
634 | (xO g,p) | |
635 | | a, xO b => | |
636 | let (g,p) := Pggcdn n a b in | |
637 | let (aa,bb) := p in | |
638 | (g,(aa, xO bb)) | |
639 | | xO a, b => | |
640 | let (g,p) := Pggcdn n a b in | |
641 | let (aa,bb) := p in | |
642 | (g,(xO aa, bb)) | |
643 | | xI a', xI b' => match Pcompare a' b' Eq with | |
644 | | Eq => (a,(1,1)) | |
645 | | Lt => | |
646 | let (g,p) := Pggcdn n (b'-a') a in | |
647 | let (ba,aa) := p in | |
648 | (g,(aa, aa + xO ba)) | |
649 | | Gt => | |
650 | let (g,p) := Pggcdn n (a'-b') b in | |
651 | let (ab,bb) := p in | |
652 | (g,(bb+xO ab, bb)) | |
653 | end | |
654 | end | |
655 | end. | |
656 | ||
657 | Definition Pgcd (a b: positive) := Pgcdn (Psize a + Psize b)%nat a b. | |
658 | Definition Pggcd (a b: positive) := Pggcdn (Psize a + Psize b)%nat a b. | |
659 | ||
660 | Open Scope Z_scope. | |
661 | ||
662 | Definition Zgcd (a b : Z) : Z := match a,b with | |
663 | | Z0, _ => Zabs b | |
664 | | _, Z0 => Zabs a | |
665 | | Zpos a, Zpos b => Zpos (Pgcd a b) | |
666 | | Zpos a, Zneg b => Zpos (Pgcd a b) | |
667 | | Zneg a, Zpos b => Zpos (Pgcd a b) | |
668 | | Zneg a, Zneg b => Zpos (Pgcd a b) | |
669 | end. | |
670 | ||
671 | Definition Zggcd (a b : Z) : Z*(Z*Z) := match a,b with | |
672 | | Z0, _ => (Zabs b,(0, Zsgn b)) | |
673 | | _, Z0 => (Zabs a,(Zsgn a, 0)) | |
674 | | Zpos a, Zpos b => | |
675 | let (g,p) := Pggcd a b in | |
676 | let (aa,bb) := p in | |
677 | (Zpos g, (Zpos aa, Zpos bb)) | |
678 | | Zpos a, Zneg b => | |
679 | let (g,p) := Pggcd a b in | |
680 | let (aa,bb) := p in | |
681 | (Zpos g, (Zpos aa, Zneg bb)) | |
682 | | Zneg a, Zpos b => | |
683 | let (g,p) := Pggcd a b in | |
684 | let (aa,bb) := p in | |
685 | (Zpos g, (Zneg aa, Zpos bb)) | |
686 | | Zneg a, Zneg b => | |
687 | let (g,p) := Pggcd a b in | |
688 | let (aa,bb) := p in | |
689 | (Zpos g, (Zneg aa, Zneg bb)) | |
690 | end. | |
691 | ||
692 | Lemma Zgcd_is_pos : forall a b, 0 <= Zgcd a b. | |
693 | Proof. | |
694 | unfold Zgcd; destruct a; destruct b; auto with zarith. | |
695 | Qed. | |
696 | ||
697 | Lemma Psize_monotone : forall p q, Pcompare p q Eq = Lt -> (Psize p <= Psize q)%nat. | |
698 | Proof. | |
699 | induction p; destruct q; simpl; auto with arith; intros; try discriminate. | |
700 | intros; generalize (Pcompare_Gt_Lt _ _ H); auto with arith. | |
701 | intros; destruct (Pcompare_Lt_Lt _ _ H); auto with arith; subst; auto. | |
702 | Qed. | |
703 | ||
704 | Lemma Pminus_Zminus : forall a b, Pcompare a b Eq = Lt -> | |
705 | Zpos (b-a) = Zpos b - Zpos a. | |
706 | Proof. | |
707 | intros. | |
708 | repeat rewrite Zpos_eq_Z_of_nat_o_nat_of_P. | |
709 | rewrite nat_of_P_minus_morphism. | |
710 | apply inj_minus1. | |
711 | apply lt_le_weak. | |
712 | apply nat_of_P_lt_Lt_compare_morphism; auto. | |
713 | rewrite ZC4; rewrite H; auto. | |
714 | Qed. | |
715 | ||
716 | Lemma Zis_gcd_even_odd : forall a b g, Zis_gcd (Zpos a) (Zpos (xI b)) g -> | |
717 | Zis_gcd (Zpos (xO a)) (Zpos (xI b)) g. | |
718 | Proof. | |
719 | intros. | |
720 | destruct H. | |
721 | constructor; auto. | |
722 | destruct H as (e,H2); exists (2*e); auto with zarith. | |
723 | rewrite Zpos_xO; rewrite H2; ring. | |
724 | intros. | |
725 | apply H1; auto. | |
726 | rewrite Zpos_xO in H2. | |
727 | rewrite Zpos_xI in H3. | |
728 | apply Gauss with 2; auto. | |
729 | apply bezout_rel_prime. | |
730 | destruct H3 as (bb, H3). | |
731 | apply Bezout_intro with bb (-Zpos b). | |
732 | omega. | |
733 | Qed. | |
734 | ||
735 | Lemma Pgcdn_correct : forall n a b, (Psize a + Psize b<=n)%nat -> | |
736 | Zis_gcd (Zpos a) (Zpos b) (Zpos (Pgcdn n a b)). | |
737 | Proof. | |
738 | intro n; pattern n; apply lt_wf_ind; clear n; intros. | |
739 | destruct n. | |
740 | simpl. | |
741 | destruct a; simpl in *; try inversion H0. | |
742 | destruct a. | |
743 | destruct b; simpl. | |
744 | case_eq (Pcompare a b Eq); intros. | |
745 | (* a = xI, b = xI, compare = Eq *) | |
746 | rewrite (Pcompare_Eq_eq _ _ H1); apply Zis_gcd_refl. | |
747 | (* a = xI, b = xI, compare = Lt *) | |
748 | apply Zis_gcd_sym. | |
749 | apply Zis_gcd_for_euclid with 1. | |
750 | apply Zis_gcd_sym. | |
751 | replace (Zpos (xI b) - 1 * Zpos (xI a)) with (Zpos(xO (b - a))). | |
752 | apply Zis_gcd_even_odd. | |
753 | apply H; auto. | |
754 | simpl in *. | |
755 | assert (Psize (b-a) <= Psize b)%nat. | |
756 | apply Psize_monotone. | |
757 | change (Zpos (b-a) < Zpos b). | |
758 | rewrite (Pminus_Zminus _ _ H1). | |
759 | assert (0 < Zpos a) by (compute; auto). | |
760 | omega. | |
761 | omega. | |
762 | rewrite Zpos_xO; do 2 rewrite Zpos_xI. | |
763 | rewrite Pminus_Zminus; auto. | |
764 | omega. | |
765 | (* a = xI, b = xI, compare = Gt *) | |
766 | apply Zis_gcd_for_euclid with 1. | |
767 | replace (Zpos (xI a) - 1 * Zpos (xI b)) with (Zpos(xO (a - b))). | |
768 | apply Zis_gcd_sym. | |
769 | apply Zis_gcd_even_odd. | |
770 | apply H; auto. | |
771 | simpl in *. | |
772 | assert (Psize (a-b) <= Psize a)%nat. | |
773 | apply Psize_monotone. | |
774 | change (Zpos (a-b) < Zpos a). | |
775 | rewrite (Pminus_Zminus b a). | |
776 | assert (0 < Zpos b) by (compute; auto). | |
777 | omega. | |
778 | rewrite ZC4; rewrite H1; auto. | |
779 | omega. | |
780 | rewrite Zpos_xO; do 2 rewrite Zpos_xI. | |
781 | rewrite Pminus_Zminus; auto. | |
782 | omega. | |
783 | rewrite ZC4; rewrite H1; auto. | |
784 | (* a = xI, b = xO *) | |
785 | apply Zis_gcd_sym. | |
786 | apply Zis_gcd_even_odd. | |
787 | apply Zis_gcd_sym. | |
788 | apply H; auto. | |
789 | simpl in *; omega. | |
790 | (* a = xI, b = xH *) | |
791 | apply Zis_gcd_1. | |
792 | destruct b; simpl. | |
793 | (* a = xO, b = xI *) | |
794 | apply Zis_gcd_even_odd. | |
795 | apply H; auto. | |
796 | simpl in *; omega. | |
797 | (* a = xO, b = xO *) | |
798 | rewrite (Zpos_xO a); rewrite (Zpos_xO b); rewrite (Zpos_xO (Pgcdn n a b)). | |
799 | apply Zis_gcd_mult. | |
800 | apply H; auto. | |
801 | simpl in *; omega. | |
802 | (* a = xO, b = xH *) | |
803 | apply Zis_gcd_1. | |
804 | (* a = xH *) | |
805 | simpl; apply Zis_gcd_sym; apply Zis_gcd_1. | |
806 | Qed. | |
807 | ||
808 | Lemma Pgcd_correct : forall a b, Zis_gcd (Zpos a) (Zpos b) (Zpos (Pgcd a b)). | |
809 | Proof. | |
810 | unfold Pgcd; intros. | |
811 | apply Pgcdn_correct; auto. | |
812 | Qed. | |
813 | ||
814 | Lemma Zgcd_is_gcd : forall a b, Zis_gcd a b (Zgcd a b). | |
815 | Proof. | |
816 | destruct a. | |
817 | intros. | |
818 | simpl. | |
819 | apply Zis_gcd_0_abs. | |
820 | destruct b; simpl. | |
821 | apply Zis_gcd_0. | |
822 | apply Pgcd_correct. | |
823 | apply Zis_gcd_sym. | |
824 | apply Zis_gcd_minus; simpl. | |
825 | apply Pgcd_correct. | |
826 | destruct b; simpl. | |
827 | apply Zis_gcd_minus; simpl. | |
828 | apply Zis_gcd_sym. | |
829 | apply Zis_gcd_0. | |
830 | apply Zis_gcd_minus; simpl. | |
831 | apply Zis_gcd_sym. | |
832 | apply Pgcd_correct. | |
833 | apply Zis_gcd_sym. | |
834 | apply Zis_gcd_minus; simpl. | |
835 | apply Zis_gcd_minus; simpl. | |
836 | apply Zis_gcd_sym. | |
837 | apply Pgcd_correct. | |
838 | Qed. | |
839 | ||
840 | ||
841 | Lemma Pggcdn_gcdn : forall n a b, | |
842 | fst (Pggcdn n a b) = Pgcdn n a b. | |
843 | Proof. | |
844 | induction n. | |
845 | simpl; auto. | |
846 | destruct a; destruct b; simpl; auto. | |
847 | destruct (Pcompare a b Eq); simpl; auto. | |
848 | rewrite <- IHn; destruct (Pggcdn n (b-a) (xI a)) as (g,(aa,bb)); simpl; auto. | |
849 | rewrite <- IHn; destruct (Pggcdn n (a-b) (xI b)) as (g,(aa,bb)); simpl; auto. | |
850 | rewrite <- IHn; destruct (Pggcdn n (xI a) b) as (g,(aa,bb)); simpl; auto. | |
851 | rewrite <- IHn; destruct (Pggcdn n a (xI b)) as (g,(aa,bb)); simpl; auto. | |
852 | rewrite <- IHn; destruct (Pggcdn n a b) as (g,(aa,bb)); simpl; auto. | |
853 | Qed. | |
854 | ||
855 | Lemma Pggcd_gcd : forall a b, fst (Pggcd a b) = Pgcd a b. | |
856 | Proof. | |
857 | intros; exact (Pggcdn_gcdn (Psize a+Psize b)%nat a b). | |
858 | Qed. | |
859 | ||
860 | Lemma Zggcd_gcd : forall a b, fst (Zggcd a b) = Zgcd a b. | |
861 | Proof. | |
862 | destruct a; destruct b; simpl; auto; rewrite <- Pggcd_gcd; | |
863 | destruct (Pggcd p p0) as (g,(aa,bb)); simpl; auto. | |
864 | Qed. | |
865 | ||
866 | Open Scope positive_scope. | |
867 | ||
868 | Lemma Pggcdn_correct_divisors : forall n a b, | |
869 | let (g,p) := Pggcdn n a b in | |
870 | let (aa,bb):=p in | |
871 | (a=g*aa) /\ (b=g*bb). | |
872 | Proof. | |
873 | induction n. | |
874 | simpl; auto. | |
875 | destruct a; destruct b; simpl; auto. | |
876 | case_eq (Pcompare a b Eq); intros. | |
877 | (* Eq *) | |
878 | rewrite Pmult_comm; simpl; auto. | |
879 | rewrite (Pcompare_Eq_eq _ _ H); auto. | |
880 | (* Lt *) | |
881 | generalize (IHn (b-a) (xI a)); destruct (Pggcdn n (b-a) (xI a)) as (g,(ba,aa)); simpl. | |
882 | intros (H0,H1); split; auto. | |
883 | rewrite Pmult_plus_distr_l. | |
884 | rewrite Pmult_xO_permute_r. | |
885 | rewrite <- H1; rewrite <- H0. | |
886 | simpl; f_equal; symmetry. | |
887 | apply Pplus_minus; auto. | |
888 | rewrite ZC4; rewrite H; auto. | |
889 | (* Gt *) | |
890 | generalize (IHn (a-b) (xI b)); destruct (Pggcdn n (a-b) (xI b)) as (g,(ab,bb)); simpl. | |
891 | intros (H0,H1); split; auto. | |
892 | rewrite Pmult_plus_distr_l. | |
893 | rewrite Pmult_xO_permute_r. | |
894 | rewrite <- H1; rewrite <- H0. | |
895 | simpl; f_equal; symmetry. | |
896 | apply Pplus_minus; auto. | |
897 | (* Then... *) | |
898 | generalize (IHn (xI a) b); destruct (Pggcdn n (xI a) b) as (g,(ab,bb)); simpl. | |
899 | intros (H0,H1); split; auto. | |
900 | rewrite Pmult_xO_permute_r; rewrite H1; auto. | |
901 | generalize (IHn a (xI b)); destruct (Pggcdn n a (xI b)) as (g,(ab,bb)); simpl. | |
902 | intros (H0,H1); split; auto. | |
903 | rewrite Pmult_xO_permute_r; rewrite H0; auto. | |
904 | generalize (IHn a b); destruct (Pggcdn n a b) as (g,(ab,bb)); simpl. | |
905 | intros (H0,H1); split; subst; auto. | |
906 | Qed. | |
907 | ||
908 | Lemma Pggcd_correct_divisors : forall a b, | |
909 | let (g,p) := Pggcd a b in | |
910 | let (aa,bb):=p in | |
911 | (a=g*aa) /\ (b=g*bb). | |
912 | Proof. | |
913 | intros a b; exact (Pggcdn_correct_divisors (Psize a + Psize b)%nat a b). | |
914 | Qed. | |
915 | ||
916 | Open Scope Z_scope. | |
917 | ||
918 | Lemma Zggcd_correct_divisors : forall a b, | |
919 | let (g,p) := Zggcd a b in | |
920 | let (aa,bb):=p in | |
921 | (a=g*aa) /\ (b=g*bb). | |
922 | Proof. | |
923 | destruct a; destruct b; simpl; auto; try solve [rewrite Pmult_comm; simpl; auto]; | |
924 | generalize (Pggcd_correct_divisors p p0); destruct (Pggcd p p0) as (g,(aa,bb)); | |
925 | destruct 1; subst; auto. | |
926 | Qed. | |
927 | ||
928 | Theorem Zgcd_spec : forall x y : Z, {z : Z | Zis_gcd x y z /\ 0 <= z}. | |
929 | Proof. | |
930 | intros x y; exists (Zgcd x y). | |
931 | split; [apply Zgcd_is_gcd | apply Zgcd_is_pos]. | |
932 | Qed. | |
933 | ||
934 | ||
935 | ||
936 |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (*i $Id: vernacentries.ml 8751 2006-04-27 16:17:51Z courtieu $ i*) | |
8 | (*i $Id: vernacentries.ml 9017 2006-07-05 17:27:34Z herbelin $ i*) | |
9 | 9 | |
10 | 10 | (* Concrete syntax of the mathematical vernacular MV V2.6 *) |
11 | 11 | |
787 | 787 | optname="the printing width"; |
788 | 788 | optread=Pp_control.get_margin; |
789 | 789 | optwrite=Pp_control.set_margin } |
790 | ||
791 | let vernac_debug b = | |
792 | set_debug (if b then Tactic_debug.DebugOn 0 else Tactic_debug.DebugOff) | |
793 | ||
794 | let _ = | |
795 | declare_bool_option | |
796 | { optsync=false; | |
797 | optkey=SecondaryTable("Ltac","Debug"); | |
798 | optname="Ltac debug"; | |
799 | optread=(fun () -> get_debug () <> Tactic_debug.DebugOff); | |
800 | optwrite=vernac_debug } | |
790 | 801 | |
791 | 802 | let vernac_set_opacity opaq locqid = |
792 | 803 | match Nametab.global locqid with |
1068 | 1079 | in |
1069 | 1080 | msgnl message |
1070 | 1081 | |
1071 | let vernac_debug b = | |
1072 | set_debug (if b then Tactic_debug.DebugOn 0 else Tactic_debug.DebugOff) | |
1073 | ||
1074 | 1082 | let interp c = match c with |
1075 | 1083 | (* Control (done in vernac) *) |
1076 | 1084 | | (VernacTime _ | VernacVar _ | VernacList _ | VernacLoad _) -> assert false |
1174 | 1182 | | VernacGo g -> vernac_go g |
1175 | 1183 | | VernacShow s -> vernac_show s |
1176 | 1184 | | VernacCheckGuard -> vernac_check_guard () |
1177 | | VernacDebug b -> vernac_debug b | |
1178 | 1185 | | VernacProof tac -> vernac_set_end_tac tac |
1179 | 1186 | (* Toplevel control *) |
1180 | 1187 | | VernacToplevelControl e -> raise e |
5 | 5 | (* * GNU Lesser General Public License Version 2.1 *) |
6 | 6 | (************************************************************************) |
7 | 7 | |
8 | (*i $Id: vernacexpr.ml 7936 2006-01-28 18:36:54Z herbelin $ i*) | |
8 | (*i $Id: vernacexpr.ml 9017 2006-07-05 17:27:34Z herbelin $ i*) | |
9 | 9 | |
10 | 10 | open Util |
11 | 11 | open Names |
280 | 280 | | VernacGo of goable |
281 | 281 | | VernacShow of showable |
282 | 282 | | VernacCheckGuard |
283 | | VernacDebug of bool | |
284 | 283 | | VernacProof of raw_tactic_expr |
285 | 284 | (* Toplevel control *) |
286 | 285 | | VernacToplevelControl of exn |