aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bintray.json2
-rw-r--r--.github/CODEOWNERS61
-rw-r--r--.gitignore10
-rw-r--r--.gitlab-ci.yml74
-rw-r--r--.ocamlinit1
-rw-r--r--.travis.yml31
-rw-r--r--CHANGES116
-rw-r--r--CODE_OF_CONDUCT.md118
-rw-r--r--CONTRIBUTING.md26
-rw-r--r--CREDITS2
-rw-r--r--META.coq.in110
-rw-r--r--Makefile58
-rw-r--r--Makefile.build12
-rw-r--r--Makefile.ci5
-rw-r--r--Makefile.common19
-rw-r--r--Makefile.dev22
-rw-r--r--Makefile.doc50
-rw-r--r--Makefile.dune51
-rw-r--r--checker/cic.mli3
-rw-r--r--checker/declarations.ml35
-rw-r--r--checker/dune32
-rw-r--r--checker/environ.ml2
-rw-r--r--checker/indtypes.ml6
-rw-r--r--checker/typeops.ml4
-rw-r--r--checker/validate.ml1
-rw-r--r--checker/values.ml24
-rw-r--r--checker/values.mli1
-rw-r--r--checker/votour.ml2
-rw-r--r--clib/cList.ml3
-rw-r--r--clib/cList.mli8
-rw-r--r--clib/dune8
-rw-r--r--config/dune13
-rw-r--r--configure.ml46
-rw-r--r--coq.opam26
-rw-r--r--coqpp/coqpp_ast.mli3
-rw-r--r--coqpp/coqpp_lex.mll16
-rw-r--r--coqpp/coqpp_main.ml27
-rw-r--r--coqpp/coqpp_parse.mly11
-rw-r--r--coqpp/dune8
-rw-r--r--default.nix12
-rwxr-xr-xdev/build/windows/MakeCoq_MinGW.bat29
-rwxr-xr-x[-rw-r--r--]dev/build/windows/makecoq_mingw.sh255
-rw-r--r--dev/ci/README.md44
-rwxr-xr-xdev/ci/ci-basic-overlay.sh113
-rwxr-xr-xdev/ci/ci-bedrock2.sh8
-rwxr-xr-xdev/ci/ci-bignums.sh14
-rwxr-xr-xdev/ci/ci-color.sh6
-rw-r--r--dev/ci/ci-common.sh103
-rwxr-xr-xdev/ci/ci-compcert.sh7
-rwxr-xr-xdev/ci/ci-coq-dpdgraph.sh6
-rwxr-xr-xdev/ci/ci-coquelicot.sh7
-rwxr-xr-xdev/ci/ci-corn.sh6
-rwxr-xr-xdev/ci/ci-cross-crypto.sh8
-rwxr-xr-xdev/ci/ci-elpi.sh6
-rwxr-xr-xdev/ci/ci-equations.sh7
-rwxr-xr-xdev/ci/ci-ext-lib.sh14
-rwxr-xr-xdev/ci/ci-fcsl-pcm.sh6
-rwxr-xr-xdev/ci/ci-fiat-crypto-legacy.sh13
-rwxr-xr-xdev/ci/ci-fiat-crypto.sh14
-rwxr-xr-xdev/ci/ci-fiat-parsers.sh7
-rwxr-xr-xdev/ci/ci-flocq.sh6
-rwxr-xr-xdev/ci/ci-formal-topology.sh6
-rwxr-xr-xdev/ci/ci-geocoq.sh8
-rwxr-xr-xdev/ci/ci-hott.sh6
-rwxr-xr-xdev/ci/ci-iris-lambda-rust.sh22
-rwxr-xr-xdev/ci/ci-ltac2.sh6
-rwxr-xr-xdev/ci/ci-math-classes.sh6
-rwxr-xr-xdev/ci/ci-math-comp.sh11
-rwxr-xr-xdev/ci/ci-mtac2.sh15
-rwxr-xr-xdev/ci/ci-pidetop.sh9
-rwxr-xr-xdev/ci/ci-plugin-tutorial.sh12
-rwxr-xr-xdev/ci/ci-quickchick.sh14
-rwxr-xr-xdev/ci/ci-simple-io.sh8
-rwxr-xr-xdev/ci/ci-template.sh12
-rwxr-xr-xdev/ci/ci-tlc.sh7
-rwxr-xr-xdev/ci/ci-unimath.sh6
-rwxr-xr-xdev/ci/ci-vst.sh6
-rw-r--r--dev/ci/docker/bionic_coq/Dockerfile55
-rwxr-xr-x[-rw-r--r--]dev/ci/gitlab.bat82
-rw-r--r--dev/ci/user-overlays/00669-maximedenes-ssr-merge.sh2
-rw-r--r--dev/ci/user-overlays/07085-ppedrot-pure-sharing-flag.sh8
-rw-r--r--dev/ci/user-overlays/07257-herbelin-master+fix-yet-another-unif-dep-in-alphabet.sh4
-rw-r--r--dev/ci/user-overlays/07288-herbelin-master+new-module-pretyping-id-management.sh6
-rw-r--r--dev/ci/user-overlays/07859-printers.sh6
-rw-r--r--dev/ci/user-overlays/07908-proj-mind.sh6
-rw-r--r--dev/ci/user-overlays/07941-bollu-questionmark-into-record-for-missing-record-field-error.sh6
-rw-r--r--dev/ci/user-overlays/08063-jasongross-string-eqb.sh6
-rw-r--r--dev/ci/user-overlays/08552-gares-elpi-11.sh5
-rw-r--r--dev/ci/user-overlays/README.md8
-rw-r--r--dev/ci/user-overlays/jasongross-numeral-notation-4.sh5
-rw-r--r--dev/doc/build-system.dev.txt40
-rw-r--r--dev/doc/build-system.dune.md120
-rw-r--r--dev/doc/changes.md11
-rw-r--r--dev/doc/critical-bugs10
-rw-r--r--dev/doc/profiling.txt52
-rw-r--r--dev/ocamldebug-coq.run2
-rw-r--r--dev/top_printers.ml24
-rw-r--r--dev/v8-syntax/syntax-v8.tex2
-rw-r--r--dev/vm_printers.ml3
-rw-r--r--doc/README.md56
-rw-r--r--doc/sphinx/README.rst156
-rw-r--r--doc/sphinx/README.template.rst110
-rw-r--r--doc/sphinx/_static/diffs-coqide-compacted.pngbin0 -> 1723 bytes
-rw-r--r--doc/sphinx/_static/diffs-coqide-multigoal.pngbin0 -> 2172 bytes
-rw-r--r--doc/sphinx/_static/diffs-coqide-on.pngbin0 -> 2518 bytes
-rw-r--r--doc/sphinx/_static/diffs-coqide-removed.pngbin0 -> 4187 bytes
-rw-r--r--doc/sphinx/_static/diffs-coqtop-compacted.pngbin0 -> 3458 bytes
-rw-r--r--doc/sphinx/_static/diffs-coqtop-multigoal.pngbin0 -> 4601 bytes
-rw-r--r--doc/sphinx/_static/diffs-coqtop-on.pngbin0 -> 7038 bytes
-rw-r--r--doc/sphinx/_static/diffs-coqtop-on3.pngbin0 -> 2125 bytes
-rw-r--r--doc/sphinx/addendum/canonical-structures.rst3
-rw-r--r--doc/sphinx/addendum/extended-pattern-matching.rst29
-rw-r--r--doc/sphinx/addendum/extraction.rst26
-rw-r--r--doc/sphinx/addendum/generalized-rewriting.rst37
-rw-r--r--doc/sphinx/addendum/implicit-coercions.rst25
-rw-r--r--doc/sphinx/addendum/micromega.rst13
-rw-r--r--doc/sphinx/addendum/miscellaneous-extensions.rst2
-rw-r--r--doc/sphinx/addendum/nsatz.rst2
-rw-r--r--doc/sphinx/addendum/omega.rst33
-rw-r--r--doc/sphinx/addendum/parallel-proof-processing.rst4
-rw-r--r--doc/sphinx/addendum/program.rst36
-rw-r--r--doc/sphinx/addendum/ring.rst24
-rw-r--r--doc/sphinx/addendum/type-classes.rst93
-rw-r--r--doc/sphinx/addendum/universe-polymorphism.rst44
-rw-r--r--doc/sphinx/biblio.bib17
-rwxr-xr-xdoc/sphinx/conf.py96
-rw-r--r--doc/sphinx/coq-cmdindex.rst2
-rw-r--r--doc/sphinx/coq-exnindex.rst8
-rw-r--r--doc/sphinx/coq-optindex.rst8
-rw-r--r--doc/sphinx/coq-tacindex.rst2
-rw-r--r--doc/sphinx/credits-contents.rst (renamed from doc/sphinx/credits.rst)55
-rw-r--r--doc/sphinx/credits.html.rst7
-rw-r--r--doc/sphinx/credits.latex.rst3
-rw-r--r--doc/sphinx/genindex.rst2
-rw-r--r--doc/sphinx/index.html.rst (renamed from doc/sphinx/index.rst)24
-rw-r--r--doc/sphinx/index.latex.rst86
-rw-r--r--doc/sphinx/introduction.rst12
-rw-r--r--doc/sphinx/language/cic.rst78
-rw-r--r--doc/sphinx/language/coq-library.rst4
-rw-r--r--doc/sphinx/language/gallina-extensions.rst381
-rw-r--r--doc/sphinx/language/gallina-specification-language.rst65
-rw-r--r--doc/sphinx/language/module-system.rst3
-rw-r--r--doc/sphinx/license.rst4
-rw-r--r--doc/sphinx/practical-tools/coq-commands.rst69
-rw-r--r--doc/sphinx/practical-tools/coqide.rst8
-rw-r--r--doc/sphinx/practical-tools/utilities.rst23
-rw-r--r--doc/sphinx/preamble.rst92
-rw-r--r--doc/sphinx/proof-engine/detailed-tactic-examples.rst215
-rw-r--r--doc/sphinx/proof-engine/ltac.rst75
-rw-r--r--doc/sphinx/proof-engine/proof-handling.rst249
-rw-r--r--doc/sphinx/proof-engine/ssreflect-proof-language.rst196
-rw-r--r--doc/sphinx/proof-engine/tactics.rst1180
-rw-r--r--doc/sphinx/proof-engine/vernacular-commands.rst232
-rw-r--r--doc/sphinx/refman-preamble.rst (renamed from doc/sphinx/replaces.rst)13
-rw-r--r--doc/sphinx/refman-preamble.sty88
-rw-r--r--doc/sphinx/user-extensions/proof-schemes.rst120
-rw-r--r--doc/sphinx/user-extensions/syntax-extensions.rst196
-rw-r--r--doc/sphinx/zebibliography.html.rst17
-rw-r--r--doc/sphinx/zebibliography.latex.rst (renamed from doc/sphinx/zebibliography.rst)6
-rw-r--r--doc/stdlib/index-list.html.template1
-rw-r--r--doc/tools/coqrst/coqdomain.py200
-rw-r--r--dune11
-rw-r--r--dune-project3
-rw-r--r--dune-workspace6
-rw-r--r--engine/dune6
-rw-r--r--engine/eConstr.ml90
-rw-r--r--engine/eConstr.mli7
-rw-r--r--engine/evarutil.ml4
-rw-r--r--engine/evd.ml4
-rw-r--r--engine/evd.mli2
-rw-r--r--engine/ftactic.ml2
-rw-r--r--engine/ftactic.mli2
-rw-r--r--engine/namegen.ml6
-rw-r--r--engine/proofview.mli4
-rw-r--r--engine/termops.ml55
-rw-r--r--engine/termops.mli38
-rw-r--r--engine/uState.ml20
-rw-r--r--engine/uState.mli2
-rw-r--r--engine/univNames.ml92
-rw-r--r--engine/univNames.mli18
-rw-r--r--engine/universes.ml5
-rw-r--r--engine/universes.mli10
-rw-r--r--grammar/dune41
-rw-r--r--grammar/tacextend.mlp2
-rw-r--r--ide/coq_lex.mll6
-rw-r--r--ide/coqide.ml24
-rw-r--r--ide/coqide.opam19
-rw-r--r--ide/dune28
-rw-r--r--ide/dune-project3
-rw-r--r--ide/idetop.ml40
-rw-r--r--ide/ideutils.ml17
-rw-r--r--ide/preferences.ml3
-rw-r--r--ide/preferences.mli1
-rw-r--r--ide/protocol/dune7
-rw-r--r--interp/constrextern.ml18
-rw-r--r--interp/declare.ml50
-rw-r--r--interp/dune6
-rw-r--r--interp/impargs.ml6
-rw-r--r--interp/notation.ml682
-rw-r--r--interp/notation.mli109
-rw-r--r--interp/reserve.ml2
-rw-r--r--kernel/.merlin.in8
-rw-r--r--kernel/byterun/dune10
-rwxr-xr-xkernel/byterun/make_jumptbl.sh3
-rw-r--r--kernel/cClosure.ml114
-rw-r--r--kernel/cClosure.mli10
-rw-r--r--kernel/cbytecodes.ml92
-rw-r--r--kernel/cbytecodes.mli36
-rw-r--r--kernel/cbytegen.ml35
-rw-r--r--kernel/cemitcodes.ml6
-rw-r--r--kernel/cemitcodes.mli1
-rw-r--r--kernel/cinstr.mli4
-rw-r--r--kernel/clambda.ml58
-rw-r--r--kernel/constr.ml145
-rw-r--r--kernel/constr.mli143
-rw-r--r--kernel/context.ml8
-rw-r--r--kernel/conv_oracle.ml8
-rw-r--r--kernel/cooking.ml39
-rw-r--r--kernel/csymtable.ml6
-rw-r--r--kernel/declarations.ml3
-rw-r--r--kernel/declareops.ml18
-rw-r--r--kernel/declareops.mli5
-rw-r--r--kernel/dune20
-rw-r--r--kernel/entries.ml17
-rw-r--r--kernel/environ.ml40
-rw-r--r--kernel/environ.mli2
-rw-r--r--kernel/indtypes.ml66
-rw-r--r--kernel/inductive.ml48
-rw-r--r--kernel/kernel.mllib2
-rwxr-xr-xkernel/make_opcodes.sh4
-rw-r--r--kernel/mod_subst.ml72
-rw-r--r--kernel/mod_subst.mli5
-rw-r--r--kernel/modops.ml12
-rw-r--r--kernel/names.ml85
-rw-r--r--kernel/names.mli22
-rw-r--r--kernel/nativecode.ml47
-rw-r--r--kernel/nativeconv.ml8
-rw-r--r--kernel/nativeinstr.mli2
-rw-r--r--kernel/nativelambda.ml55
-rw-r--r--kernel/nativelambda.mli1
-rw-r--r--kernel/nativelib.ml6
-rw-r--r--kernel/nativelibrary.ml2
-rw-r--r--kernel/nativevalues.ml34
-rw-r--r--kernel/nativevalues.mli4
-rw-r--r--kernel/opaqueproof.ml14
-rw-r--r--kernel/reduction.ml26
-rw-r--r--kernel/retroknowledge.ml50
-rw-r--r--kernel/retroknowledge.mli35
-rw-r--r--kernel/safe_typing.ml128
-rw-r--r--kernel/safe_typing.mli22
-rw-r--r--kernel/subtyping.ml14
-rw-r--r--kernel/term.ml14
-rw-r--r--kernel/term_typing.ml144
-rw-r--r--kernel/term_typing.mli10
-rw-r--r--kernel/type_errors.ml4
-rw-r--r--kernel/type_errors.mli5
-rw-r--r--kernel/typeops.ml43
-rw-r--r--kernel/uGraph.ml17
-rw-r--r--kernel/uGraph.mli6
-rw-r--r--kernel/univ.ml41
-rw-r--r--kernel/vars.ml4
-rw-r--r--kernel/vconv.ml4
-rw-r--r--kernel/vm.ml3
-rw-r--r--kernel/vmvalues.ml157
-rw-r--r--kernel/vmvalues.mli39
-rw-r--r--lib/dune7
-rw-r--r--lib/genarg.mli4
-rw-r--r--lib/system.ml11
-rw-r--r--lib/system.mli2
-rw-r--r--library/coqlib.ml8
-rw-r--r--library/coqlib.mli8
-rw-r--r--library/dischargedhypsmap.ml21
-rw-r--r--library/dischargedhypsmap.mli19
-rw-r--r--library/dune9
-rw-r--r--library/global.ml12
-rw-r--r--library/global.mli6
-rw-r--r--library/globnames.ml69
-rw-r--r--library/globnames.mli31
-rw-r--r--library/goptions.ml2
-rw-r--r--library/keys.ml6
-rw-r--r--library/lib.ml15
-rw-r--r--library/lib.mli2
-rw-r--r--library/library.mllib1
-rw-r--r--library/nametab.ml48
-rw-r--r--parsing/dune20
-rw-r--r--parsing/g_constr.mlg2
-rw-r--r--parsing/notgram_ops.ml6
-rw-r--r--plugins/btauto/Algebra.v24
-rw-r--r--plugins/btauto/Reflect.v2
-rw-r--r--plugins/btauto/plugin_base.dune5
-rw-r--r--plugins/btauto/refl_btauto.ml4
-rw-r--r--plugins/cc/ccalgo.ml12
-rw-r--r--plugins/cc/plugin_base.dune5
-rw-r--r--plugins/derive/plugin_base.dune5
-rw-r--r--plugins/extraction/extract_env.ml6
-rw-r--r--plugins/extraction/plugin_base.dune5
-rw-r--r--plugins/extraction/table.ml16
-rw-r--r--plugins/firstorder/instances.ml2
-rw-r--r--plugins/firstorder/plugin_base.dune5
-rw-r--r--plugins/firstorder/rules.ml2
-rw-r--r--plugins/firstorder/sequent.ml2
-rw-r--r--plugins/fourier/plugin_base.dune5
-rw-r--r--plugins/funind/glob_term_to_relation.ml8
-rw-r--r--plugins/funind/indfun.ml2
-rw-r--r--plugins/funind/invfun.ml2
-rw-r--r--plugins/funind/plugin_base.dune5
-rw-r--r--plugins/ltac/evar_tactics.ml4
-rw-r--r--plugins/ltac/extraargs.ml4102
-rw-r--r--plugins/ltac/extraargs.mli5
-rw-r--r--plugins/ltac/extratactics.ml421
-rw-r--r--plugins/ltac/g_ltac.ml414
-rw-r--r--plugins/ltac/g_tactic.mlg2
-rw-r--r--plugins/ltac/plugin_base.dune13
-rw-r--r--plugins/ltac/pptactic.ml7
-rw-r--r--plugins/ltac/rewrite.ml5
-rw-r--r--plugins/ltac/tacenv.ml2
-rw-r--r--plugins/ltac/tacenv.mli2
-rw-r--r--plugins/ltac/tacexpr.ml13
-rw-r--r--plugins/ltac/tacexpr.mli11
-rw-r--r--plugins/ltac/tacintern.ml1
-rw-r--r--plugins/ltac/tacinterp.ml29
-rw-r--r--plugins/ltac/tacsubst.ml1
-rw-r--r--plugins/ltac/tactic_debug.ml13
-rw-r--r--plugins/micromega/coq_micromega.ml8
-rw-r--r--plugins/micromega/plugin_base.dune7
-rw-r--r--plugins/nsatz/plugin_base.dune5
-rw-r--r--plugins/omega/PreOmega.v4
-rw-r--r--plugins/omega/coq_omega.ml12
-rw-r--r--plugins/omega/plugin_base.dune5
-rw-r--r--plugins/quote/Quote.v86
-rw-r--r--plugins/quote/g_quote.mlg46
-rw-r--r--plugins/quote/plugin_base.dune5
-rw-r--r--plugins/quote/quote.ml540
-rw-r--r--plugins/quote/quote_plugin.mlpack2
-rw-r--r--plugins/romega/README6
-rw-r--r--plugins/romega/ROmega.v14
-rw-r--r--plugins/romega/ReflOmegaCore.v1872
-rw-r--r--plugins/romega/const_omega.ml332
-rw-r--r--plugins/romega/const_omega.mli124
-rw-r--r--plugins/romega/g_romega.mlg55
-rw-r--r--plugins/romega/refl_omega.ml1071
-rw-r--r--plugins/romega/romega_plugin.mlpack3
-rw-r--r--plugins/rtauto/plugin_base.dune5
-rw-r--r--plugins/setoid_ring/Field_theory.v3
-rw-r--r--plugins/setoid_ring/Ncring_initial.v5
-rw-r--r--plugins/setoid_ring/Ring_base.v1
-rw-r--r--plugins/setoid_ring/Ring_tac.v1
-rw-r--r--plugins/setoid_ring/newring.ml4
-rw-r--r--plugins/setoid_ring/plugin_base.dune5
-rw-r--r--plugins/ssr/plugin_base.dune6
-rw-r--r--plugins/ssr/ssrcommon.ml4
-rw-r--r--plugins/ssr/ssreflect.v3
-rw-r--r--plugins/ssr/ssrelim.ml6
-rw-r--r--plugins/ssr/ssrequality.ml3
-rw-r--r--plugins/ssr/ssrfun.v2
-rw-r--r--plugins/ssr/ssrfwd.ml4
-rw-r--r--plugins/ssr/ssripats.ml5
-rw-r--r--plugins/ssr/ssrparser.ml44
-rw-r--r--plugins/ssr/ssrtacticals.ml4
-rw-r--r--plugins/ssrmatching/plugin_base.dune5
-rw-r--r--plugins/ssrmatching/ssrmatching.ml7
-rw-r--r--plugins/ssrmatching/ssrmatching.v4
-rw-r--r--plugins/syntax/ascii_syntax.ml18
-rw-r--r--plugins/syntax/g_numeral.ml438
-rw-r--r--plugins/syntax/int31_syntax.ml21
-rw-r--r--plugins/syntax/n_syntax.ml81
-rw-r--r--plugins/syntax/n_syntax_plugin.mlpack1
-rw-r--r--plugins/syntax/nat_syntax.ml85
-rw-r--r--plugins/syntax/nat_syntax_plugin.mlpack1
-rw-r--r--plugins/syntax/numeral.ml142
-rw-r--r--plugins/syntax/numeral.mli (renamed from stm/workerLoop.mli)11
-rw-r--r--plugins/syntax/numeral_notation_plugin.mlpack2
-rw-r--r--plugins/syntax/plugin_base.dune35
-rw-r--r--plugins/syntax/positive_syntax.ml101
-rw-r--r--plugins/syntax/positive_syntax_plugin.mlpack1
-rw-r--r--plugins/syntax/r_syntax.ml22
-rw-r--r--plugins/syntax/string_syntax.ml20
-rw-r--r--plugins/syntax/z_syntax.ml78
-rw-r--r--plugins/syntax/z_syntax_plugin.mlpack1
-rw-r--r--plugins/xml/README4
-rw-r--r--pretyping/arguments_renaming.ml6
-rw-r--r--pretyping/cases.ml1055
-rw-r--r--pretyping/cases.mli35
-rw-r--r--pretyping/cbv.ml11
-rw-r--r--pretyping/classops.ml78
-rw-r--r--pretyping/classops.mli4
-rw-r--r--pretyping/coercion.ml9
-rw-r--r--pretyping/dune6
-rw-r--r--pretyping/evarconv.ml14
-rw-r--r--pretyping/evardefine.ml2
-rw-r--r--pretyping/evarsolve.ml71
-rw-r--r--pretyping/globEnv.ml203
-rw-r--r--pretyping/globEnv.mli88
-rw-r--r--pretyping/glob_ops.ml20
-rw-r--r--pretyping/glob_ops.mli1
-rw-r--r--pretyping/indrec.ml16
-rw-r--r--pretyping/indrec.mli2
-rw-r--r--pretyping/inductiveops.ml4
-rw-r--r--pretyping/inferCumulativity.ml2
-rw-r--r--pretyping/ltac_pretype.ml2
-rw-r--r--pretyping/nativenorm.ml18
-rw-r--r--pretyping/pretyping.ml505
-rw-r--r--pretyping/pretyping.mli8
-rw-r--r--pretyping/pretyping.mllib1
-rw-r--r--pretyping/recordops.ml38
-rw-r--r--pretyping/reductionops.ml40
-rw-r--r--pretyping/reductionops.mli7
-rw-r--r--pretyping/tacred.mli2
-rw-r--r--pretyping/typeclasses.ml40
-rw-r--r--pretyping/unification.ml6
-rw-r--r--pretyping/vnorm.ml8
-rw-r--r--printing/dune6
-rw-r--r--printing/prettyp.ml76
-rw-r--r--printing/prettyp.mli7
-rw-r--r--printing/printer.ml132
-rw-r--r--printing/printer.mli58
-rw-r--r--printing/printmod.ml55
-rw-r--r--printing/proof_diffs.ml392
-rw-r--r--printing/proof_diffs.mli29
-rw-r--r--proofs/clenv.ml4
-rw-r--r--proofs/dune6
-rw-r--r--proofs/goal.ml2
-rw-r--r--proofs/goal.mli2
-rw-r--r--proofs/logic.ml1
-rw-r--r--proofs/pfedit.ml25
-rw-r--r--proofs/pfedit.mli2
-rw-r--r--proofs/proof.ml45
-rw-r--r--proofs/proof.mli6
-rw-r--r--proofs/redexpr.ml2
-rw-r--r--proofs/refine.ml23
-rw-r--r--proofs/refine.mli4
-rw-r--r--proofs/tacmach.ml4
-rw-r--r--shell.nix5
-rw-r--r--stm/dune6
-rw-r--r--stm/stm.ml23
-rw-r--r--stm/stm.mli3
-rw-r--r--stm/vernac_classifier.ml3
-rw-r--r--tactics/auto.ml4
-rw-r--r--tactics/autorewrite.ml2
-rw-r--r--tactics/btermdn.ml2
-rw-r--r--tactics/class_tactics.ml21
-rw-r--r--tactics/dune6
-rw-r--r--tactics/eauto.ml6
-rw-r--r--tactics/equality.ml2
-rw-r--r--tactics/hints.ml96
-rw-r--r--tactics/hints.mli12
-rw-r--r--tactics/ind_tables.ml6
-rw-r--r--tactics/inv.ml2
-rw-r--r--tactics/tacticals.ml7
-rw-r--r--tactics/tactics.ml34
-rw-r--r--tactics/tactics.mli2
-rw-r--r--tactics/term_dnet.ml2
-rw-r--r--test-suite/Makefile14
-rw-r--r--test-suite/bugs/closed/2428.v (renamed from test-suite/bugs/2428.v)2
-rw-r--r--test-suite/bugs/closed/2670.v8
-rw-r--r--test-suite/bugs/closed/4527.v8
-rw-r--r--test-suite/bugs/closed/4533.v11
-rw-r--r--test-suite/bugs/closed/4544.v3
-rw-r--r--test-suite/bugs/closed/4612.v7
-rw-r--r--test-suite/bugs/closed/4623.v (renamed from test-suite/bugs/4623.v)0
-rw-r--r--test-suite/bugs/closed/4624.v (renamed from test-suite/bugs/4624.v)0
-rw-r--r--test-suite/bugs/closed/4717.v4
-rw-r--r--test-suite/bugs/closed/4859.v7
-rw-r--r--test-suite/bugs/closed/7333.v (renamed from test-suite/bugs/7333.v)0
-rw-r--r--test-suite/bugs/closed/7754.v21
-rw-r--r--test-suite/bugs/closed/7795.v65
-rw-r--r--test-suite/bugs/closed/7867.v4
-rw-r--r--test-suite/bugs/closed/7900.v53
-rw-r--r--test-suite/bugs/closed/7967.v2
-rw-r--r--test-suite/bugs/closed/8106.v4
-rw-r--r--test-suite/bugs/closed/8121.v46
-rw-r--r--test-suite/bugs/closed/8215.v14
-rw-r--r--test-suite/bugs/closed/8270.v15
-rw-r--r--test-suite/bugs/closed/8288.v7
-rw-r--r--test-suite/bugs/closed/8432.v39
-rw-r--r--test-suite/bugs/closed/8478.v11
-rw-r--r--test-suite/bugs/closed/8532.v8
-rw-r--r--test-suite/coq-makefile/timing/after/time-of-build-both.log.desired6
-rw-r--r--test-suite/coq-makefile/timing/per-file-after/A.v.timing.diff.desired18
-rwxr-xr-xtest-suite/coq-makefile/timing/run.sh4
-rw-r--r--test-suite/interactive/PrimNotation.v64
-rwxr-xr-xtest-suite/misc/poly-capture-global-univs.sh19
-rw-r--r--test-suite/misc/poly-capture-global-univs/.gitignore1
-rw-r--r--test-suite/misc/poly-capture-global-univs/_CoqProject9
-rw-r--r--test-suite/misc/poly-capture-global-univs/src/evil.ml49
-rw-r--r--test-suite/misc/poly-capture-global-univs/src/evilImpl.ml22
-rw-r--r--test-suite/misc/poly-capture-global-univs/src/evilImpl.mli2
-rw-r--r--test-suite/misc/poly-capture-global-univs/src/evil_plugin.mlpack2
-rw-r--r--test-suite/misc/poly-capture-global-univs/theories/evil.v13
-rw-r--r--test-suite/output/Arguments.v2
-rw-r--r--test-suite/output/Cases.out11
-rw-r--r--test-suite/output/Notations.out14
-rw-r--r--test-suite/output/Notations.v1
-rw-r--r--test-suite/output/PrintAssumptions.out2
-rw-r--r--test-suite/output/PrintAssumptions.v10
-rw-r--r--test-suite/output/Quote.v36
-rw-r--r--test-suite/output/UnivBinders.out34
-rw-r--r--test-suite/output/UnivBinders.v9
-rw-r--r--test-suite/output/ltac.out11
-rw-r--r--test-suite/output/ltac.v10
-rw-r--r--test-suite/output/ltac_missing_args.out14
-rw-r--r--test-suite/prerequisite/module_bug7192.v9
-rw-r--r--test-suite/prerequisite/module_bug8416.v2
-rwxr-xr-xtest-suite/report.sh55
-rwxr-xr-xtest-suite/save-logs.sh19
-rw-r--r--test-suite/ssr/delayed_clear_rename.v (renamed from test-suite/success/ssr_delayed_clear_rename.v)0
-rw-r--r--test-suite/ssr/rewrite_illtyped.v (renamed from test-suite/ssr/ssr_rew_illtyped.v)0
-rw-r--r--test-suite/ssr/ssrpattern.v7
-rw-r--r--test-suite/success/BracketsWithGoalSelector.v9
-rw-r--r--test-suite/success/Case13.v38
-rw-r--r--test-suite/success/CombinedScheme.v35
-rw-r--r--test-suite/success/Compat88.v18
-rw-r--r--test-suite/success/CompatCurrentFlag.v3
-rw-r--r--test-suite/success/CompatOldFlag.v5
-rw-r--r--test-suite/success/CompatPreviousFlag.v4
-rw-r--r--test-suite/success/NumeralNotations.v302
-rw-r--r--test-suite/success/ROmega.v29
-rw-r--r--test-suite/success/ROmega0.v76
-rw-r--r--test-suite/success/ROmega2.v8
-rw-r--r--test-suite/success/ROmega3.v8
-rw-r--r--test-suite/success/ROmega4.v6
-rw-r--r--test-suite/success/ROmegaPre.v50
-rw-r--r--test-suite/success/SchemeEquality.v29
-rw-r--r--test-suite/success/Template.v48
-rw-r--r--test-suite/success/apply.v23
-rw-r--r--test-suite/success/attribute-syntax.v12
-rw-r--r--test-suite/success/ltac.v56
-rw-r--r--test-suite/vio/numeral.v21
-rw-r--r--theories/Bool/Bool.v2
-rw-r--r--theories/Bool/Bvector.v12
-rw-r--r--theories/Classes/CEquivalence.v2
-rw-r--r--theories/Classes/CMorphisms.v1
-rw-r--r--theories/Classes/Equivalence.v2
-rw-r--r--theories/Classes/Morphisms.v1
-rw-r--r--theories/Classes/RelationClasses.v2
-rw-r--r--theories/Compat/Coq88.v14
-rw-r--r--theories/FSets/FMapAVL.v1
-rw-r--r--theories/FSets/FMapFullAVL.v6
-rw-r--r--theories/FSets/FSetAVL.v2
-rw-r--r--theories/FSets/FSetEqProperties.v4
-rw-r--r--theories/Init/Datatypes.v41
-rw-r--r--theories/Init/Decimal.v17
-rw-r--r--theories/Init/Logic.v67
-rw-r--r--theories/Init/Nat.v4
-rw-r--r--theories/Init/Notations.v10
-rw-r--r--theories/Init/Peano.v1
-rw-r--r--theories/Init/Prelude.v19
-rw-r--r--theories/Init/Specif.v85
-rw-r--r--theories/Lists/List.v91
-rw-r--r--theories/MSets/MSetAVL.v2
-rw-r--r--theories/MSets/MSetEqProperties.v4
-rw-r--r--theories/MSets/MSetGenTree.v2
-rw-r--r--theories/NArith/BinNat.v2
-rw-r--r--theories/NArith/BinNatDef.v9
-rw-r--r--theories/NArith/Ndigits.v8
-rw-r--r--theories/Numbers/AltBinNotations.v69
-rw-r--r--theories/Numbers/BinNums.v19
-rw-r--r--theories/Numbers/Cyclic/Int31/Cyclic31.v20
-rw-r--r--theories/Numbers/Cyclic/Int31/Int31.v42
-rw-r--r--theories/Numbers/Integer/Abstract/ZBits.v6
-rw-r--r--theories/Numbers/Integer/Abstract/ZDivEucl.v3
-rw-r--r--theories/Numbers/Integer/NatPairs/ZNatPairs.v6
-rw-r--r--theories/Numbers/NatInt/NZDomain.v4
-rw-r--r--theories/Numbers/Natural/Abstract/NBits.v6
-rw-r--r--theories/PArith/BinPos.v2
-rw-r--r--theories/PArith/BinPosDef.v13
-rw-r--r--theories/Program/Basics.v2
-rw-r--r--theories/Program/Tactics.v2
-rw-r--r--theories/Program/Utils.v5
-rw-r--r--theories/QArith/QArith_base.v1
-rw-r--r--theories/QArith/Qcanon.v1
-rw-r--r--theories/Reals/Ranalysis1.v1
-rw-r--r--theories/Reals/Raxioms.v1
-rw-r--r--theories/Reals/Rdefinitions.v7
-rw-r--r--theories/Reals/Rsqrt_def.v2
-rw-r--r--theories/Strings/Ascii.v3
-rw-r--r--theories/Strings/String.v3
-rw-r--r--theories/Structures/GenericMinMax.v2
-rw-r--r--theories/Structures/OrdersFacts.v1
-rw-r--r--theories/Vectors/VectorDef.v1
-rw-r--r--theories/ZArith/BinInt.v2
-rw-r--r--theories/ZArith/BinIntDef.v15
-rw-r--r--theories/ZArith/Int.v1
-rw-r--r--theories/ZArith/Zquot.v26
-rw-r--r--tools/CoqMakefile.in8
-rw-r--r--tools/coq_dune.ml307
-rw-r--r--tools/coq_makefile.ml34
-rw-r--r--tools/coqc.ml8
-rw-r--r--tools/coqdoc/dune6
-rw-r--r--tools/dune43
-rw-r--r--topbin/dune29
-rw-r--r--toplevel/coqargs.ml4
-rw-r--r--toplevel/coqloop.ml27
-rw-r--r--toplevel/coqtop.ml4
-rw-r--r--toplevel/dune13
-rw-r--r--vernac/assumptions.ml38
-rw-r--r--vernac/assumptions.mli5
-rw-r--r--vernac/auto_ind_decl.ml96
-rw-r--r--vernac/auto_ind_decl.mli2
-rw-r--r--vernac/classes.ml341
-rw-r--r--vernac/classes.mli2
-rw-r--r--vernac/comInductive.ml94
-rw-r--r--vernac/comInductive.mli7
-rw-r--r--vernac/dune16
-rw-r--r--vernac/explainErr.ml6
-rw-r--r--vernac/g_proofs.mlg1
-rw-r--r--vernac/g_vernac.mlg23
-rw-r--r--vernac/himsg.ml49
-rw-r--r--vernac/himsg.mli4
-rw-r--r--vernac/indschemes.ml56
-rw-r--r--vernac/lemmas.ml18
-rw-r--r--vernac/metasyntax.ml76
-rw-r--r--vernac/metasyntax.mli9
-rw-r--r--vernac/obligations.ml6
-rw-r--r--vernac/ppvernac.ml15
-rw-r--r--vernac/record.ml57
-rw-r--r--vernac/record.mli4
-rw-r--r--vernac/vernacentries.ml133
-rw-r--r--vernac/vernacexpr.ml54
-rw-r--r--vernac/vernacinterp.ml5
-rw-r--r--vernac/vernacinterp.mli4
621 files changed, 12278 insertions, 11011 deletions
diff --git a/.bintray.json b/.bintray.json
index 8672c2bb9a..1b32a144c8 100644
--- a/.bintray.json
+++ b/.bintray.json
@@ -6,7 +6,7 @@
},
"version": {
- "name": "8.9+alpha"
+ "name": "8.10+alpha"
},
"files":
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 20d49e675f..267da478d7 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -6,11 +6,23 @@
/.github/ @maximedenes
# Secondary maintainer @Zimmi48
+########## Build system ##########
+
+/Makefile* @gares
+
+/configure* @ejgallego
+
+/META.coq.in @ejgallego
+
+/dev/build/windows @MSoegtropIMC
+# Secondary maintainer @maximedenes
+
########## CI infrastructure ##########
/dev/ci/ @coq/ci-maintainers
/.travis.yml @coq/ci-maintainers
/.gitlab-ci.yml @coq/ci-maintainers
+/Makefile.ci @coq/ci-maintainers
/dev/ci/user-overlays/*.sh @ghost
# Trick to avoid getting review requests
@@ -21,8 +33,7 @@
/dev/ci/*.bat @maximedenes
# Secondary maintainer @SkySkimmer
-/default.nix @Zimmi48
-# Secondary maintainer @vbgl
+*.nix @coq/nix-maintainers
########## Documentation ##########
@@ -35,6 +46,9 @@
/CONTRIBUTING.md @Zimmi48
# Secondary maintainer @maximedenes
+/CODE_OF_CONDUCT.md @Zimmi48
+# Secondary maintainer @mattam82
+
/dev/doc/ @Zimmi48
# Secondary maintainer @maximedenes
@@ -42,11 +56,8 @@
# Trick to avoid getting review requests
# each time someone modifies the dev changelog
-/doc/ @maximedenes
-# Secondary maintainer @silene @Zimmi48
-
-/doc/tools/coqrst/ @maximedenes
-# Secondary maintainer @cpitclaudel
+/doc/ @coq/doc-maintainers
+/Makefile.doc @coq/doc-maintainers
/man/ @silene
# Secondary maintainer @maximedenes
@@ -140,9 +151,8 @@
/plugins/ltac/ @ppedrot
# Secondary maintainer @herbelin
-/plugins/micromega/ @fajb
-/test-suite/micromega/ @fajb
-# Secondary maintainer @bgregoir
+/plugins/micromega/ @coq/micromega-maintainers
+/test-suite/micromega/ @coq/micromega-maintainers
/plugins/nsatz/ @thery
# Secondary maintainer @ppedrot
@@ -160,8 +170,6 @@
/plugins/syntax/ @ppedrot
# Secondary maintainer @maximedenes
-/plugins/quote/ @herbelin
-
/plugins/rtauto/ @PierreCorbineau
# Secondary maintainer @herbelin
@@ -260,6 +268,16 @@
/theories/Vectors/ @herbelin
+########## Dune ##########
+
+/.ocamlinit @ejgallego
+/Makefile.dune @ejgallego
+/tools/coq_dune* @ejgallego
+/dune* @ejgallego
+/coq.opam @ejgallego
+/ide/coqide.opam @ejgallego
+# Secondary maintainer @Zimmi48
+
########## Tools ##########
/tools/coqdoc/ @silene
@@ -296,25 +314,6 @@
/vernac/ @mattam82
# Secondary maintainer @maximedenes
-########## Build system ##########
-
-/Makefile* @gares
-
-/configure* @ejgallego
-
-/META.coq.in @ejgallego
-
-/dev/build/windows @MSoegtropIMC
-# Secondary maintainer @maximedenes
-
-# This file belongs to CI
-/Makefile.ci @ejgallego
-# Secondary maintainer @SkySkimmer
-
-# This file belongs to the doc
-/Makefile.doc @maximedenes
-# Secondary maintainer @silene
-
########## Test suite ##########
/test-suite/Makefile @gares
diff --git a/.gitignore b/.gitignore
index 0e41d6a778..0ab6e25852 100644
--- a/.gitignore
+++ b/.gitignore
@@ -99,6 +99,9 @@ doc/faq/axioms.eps
doc/faq/axioms.eps_t
doc/faq/axioms.pdf_t
doc/faq/axioms.png
+doc/sphinx/index.rst
+doc/sphinx/zebibliography.rst
+doc/sphinx/credits.rst
doc/stdlib/Library.out
doc/stdlib/Library.ps
doc/stdlib/Library.coqdoc.tex
@@ -183,3 +186,10 @@ plugins/ssr/ssrvernac.ml
# ocaml dev files
.merlin
META.coq
+
+# Files automatically generated by Dune.
+plugins/*/dune
+theories/*/dune
+theories/*/*/dune
+theories/*/*/*/dune
+*.install
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index c2ca6ebaa4..76d967f078 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -9,7 +9,7 @@ stages:
variables:
# Format: $IMAGE-V$DATE [Cache is not used as of today but kept here
# for reference]
- CACHEKEY: "bionic_coq-V2018-07-11-V2"
+ CACHEKEY: "bionic_coq-V2018-09-24-V01"
IMAGE: "$CI_REGISTRY_IMAGE:$CACHEKEY"
# By default, jobs run in the base switch; override to select another switch
OPAM_SWITCH: "base"
@@ -40,8 +40,8 @@ before_script:
- printenv -0 | sort -z | tr '\0' '\n'
- declare -A switch_table
- switch_table=( ["base"]="$COMPILER" ["edge"]="$COMPILER_EDGE" )
- - opam switch -y "${switch_table[$OPAM_SWITCH]}$OPAM_VARIANT"
- - eval $(opam config env)
+ - opam switch set -y "${switch_table[$OPAM_SWITCH]}$OPAM_VARIANT"
+ - eval $(opam env)
- opam list
- opam config list
@@ -88,18 +88,31 @@ after_script:
- set +e
+.dune-template: &dune-template
+ dependencies: []
+ stage: build
+ artifacts:
+ name: "$CI_JOB_NAME"
+ paths:
+ - _build/
+ expire_in: 1 week
+ script:
+ - set -e
+ - make -f Makefile.dune "$DUNE_TARGET"
+ - set +e
+
# every non build job must set dependencies otherwise all build
# artifacts are used together and we may get some random Coq. To that
# purpose, we add a spurious dependency `not-a-real-job` that must be
# overridden otherwise the CI will fail.
-.doc-templare: &doc-template
+.doc-template: &doc-template
stage: test
dependencies:
- not-a-real-job
script:
- SPHINXENV='COQBIN="'"$PWD"'/_install_ci/bin/" COQBOOT=no'
- - make -j "$NJOBS" SPHINXENV="$SPHINXENV" SPHINX_DEPS= sphinx
+ - make -j "$NJOBS" SPHINXENV="$SPHINXENV" SPHINX_DEPS= refman
- make install-doc-sphinx
artifacts:
name: "$CI_JOB_NAME"
@@ -162,8 +175,8 @@ after_script:
artifacts:
name: "%CI_JOB_NAME%"
paths:
- - dev\nsis\*.exe
- - coq-opensource-archive-windows-*.zip
+ - artifacts
+ when: always
expire_in: 1 week
dependencies: []
tags:
@@ -203,6 +216,12 @@ build:edge+flambda:
COQ_EXTRA_CONF: "-native-compiler yes -coqide opt -flambda-opts "
COQ_EXTRA_CONF_QUOTE: "-O3 -unbox-closures"
+build:egde:dune:dev:
+ <<: *dune-template
+ variables:
+ OPAM_SWITCH: edge
+ DUNE_TARGET: world
+
windows64:
<<: *windows-template
variables:
@@ -212,6 +231,15 @@ windows32:
<<: *windows-template
variables:
ARCH: "32"
+ except:
+ - /^pr-.*$/
+
+pkg:dune-release:
+ <<: *dune-template
+ stage: test
+ variables:
+ OPAM_SWITCH: edge
+ DUNE_TARGET: release
pkg:nix:
image: nixorg/nix:latest # Minimal NixOS image which doesn't even contain git
@@ -242,11 +270,35 @@ pkg:nix:
paths:
- nix-build-coq.drv-0/*/test-suite/logs
-documentation:
+doc:refman:
<<: *doc-template
dependencies:
- build:base
+doc:ml-api:ocamldoc:
+ stage: test
+ dependencies:
+ - build:edge
+ script:
+ - ./configure -warn-error yes -prefix "$(pwd)/_install_ci"
+ - make mli-doc source-doc # ml-doc [broken in 4.07.0]
+ artifacts:
+ name: "$CI_JOB_NAME"
+ paths:
+ - dev/ocamldoc
+
+doc:ml-api:odoc:
+ stage: test
+ dependencies:
+ - build:egde:dune:dev
+ script: make -f Makefile.dune apidoc
+ variables:
+ OPAM_SWITCH: edge
+ artifacts:
+ name: "$CI_JOB_NAME"
+ paths:
+ - _build/default/_doc/
+
test-suite:base:
<<: *test-suite-template
dependencies:
@@ -334,6 +386,9 @@ ci-fcsl-pcm:
ci-fiat-crypto:
<<: *ci-template-flambda
+ci-fiat-crypto-legacy:
+ <<: *ci-template-flambda
+
ci-fiat-parsers:
<<: *ci-template
@@ -364,6 +419,9 @@ ci-mtac2:
ci-pidetop:
<<: *ci-template
+ci-plugin-tutorial:
+ <<: *ci-template
+
ci-quickchick:
<<: *ci-template-flambda
diff --git a/.ocamlinit b/.ocamlinit
new file mode 100644
index 0000000000..3771334e12
--- /dev/null
+++ b/.ocamlinit
@@ -0,0 +1 @@
+#rectypes;;
diff --git a/.travis.yml b/.travis.yml
index f8b047ea18..1a2c909c7d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -40,7 +40,7 @@ env:
# system is == 4.02.3
- COMPILER="system"
- COMPILER_BE="4.07.0"
- - DUNE_VER=".1.0.0"
+ - DUNE_VER=".1.1.1"
- CAMLP5_VER=".6.14"
- CAMLP5_VER_BE=".7.06"
- FINDLIB_VER=".1.4.1"
@@ -105,8 +105,8 @@ matrix:
# Full Coq test-suite with two compilers
- if: NOT (type = pull_request)
env:
- - TEST_TARGET="test-suite"
- - EXTRA_CONF="-coqide opt -with-doc yes"
+ - TEST_TARGET="doc-html test-suite"
+ - EXTRA_CONF="-coqide opt"
- EXTRA_OPAM="${LABLGTK} ounit"
before_install: &sphinx-install
- sudo pip3 install bs4 sphinx sphinx_rtd_theme pexpect antlr4-python3-runtime sphinxcontrib-bibtex
@@ -119,26 +119,17 @@ matrix:
- aspcud
- libgtk2.0-dev
- libgtksourceview2.0-dev
- - texlive-latex-base
- - texlive-latex-recommended
- - texlive-latex-extra
- - texlive-math-extra
- - texlive-fonts-recommended
- - texlive-fonts-extra
- - latex-xcolor
- - ghostscript
- - tipa
- python3
- python3-pip
- python3-setuptools
- if: NOT (type = pull_request)
env:
- - TEST_TARGET="test-suite"
+ - TEST_TARGET="doc-html test-suite"
- COMPILER="${COMPILER_BE}"
- FINDLIB_VER="${FINDLIB_VER_BE}"
- CAMLP5_VER="${CAMLP5_VER_BE}"
- - EXTRA_CONF="-coqide opt -with-doc yes"
+ - EXTRA_CONF="-coqide opt"
- EXTRA_OPAM="${LABLGTK_BE} ounit"
before_install: *sphinx-install
addons:
@@ -150,11 +141,11 @@ matrix:
# Full test-suite with flambda
- if: NOT (type = pull_request)
env:
- - TEST_TARGET="test-suite"
+ - TEST_TARGET="doc-html test-suite"
- COMPILER="${COMPILER_BE}+flambda"
- FINDLIB_VER="${FINDLIB_VER_BE}"
- CAMLP5_VER="${CAMLP5_VER_BE}"
- - EXTRA_CONF="-coqide opt -with-doc yes -flambda-opts -O3"
+ - EXTRA_CONF="-coqide opt -flambda-opts -O3"
- EXTRA_OPAM="${LABLGTK_BE} ounit"
before_install: *sphinx-install
addons:
@@ -175,7 +166,9 @@ matrix:
before_install:
- brew update
- brew unlink python
- - brew install opam gnu-time
+ - brew install gnu-time
+ # only way to continue using OPAM 1.2
+ - brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/d156edeeed7291f4bc1e08620b331bbd05d52b78/Formula/opam.rb
- if: NOT (type = pull_request)
os: osx
@@ -192,7 +185,9 @@ matrix:
before_install:
- brew update
- brew unlink python
- - brew install opam gnu-time gtk+ expat gtksourceview gdk-pixbuf
+ - brew install gnu-time gtk+ expat gtksourceview gdk-pixbuf
+ # only way to continue using OPAM 1.2
+ - brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/d156edeeed7291f4bc1e08620b331bbd05d52b78/Formula/opam.rb
- brew unlink python@2
- brew install python3
- pip3 install macpack
diff --git a/CHANGES b/CHANGES
index df4a1df176..840aeb6c73 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,17 @@
+Changes beyond 8.9
+==================
+
+Plugins
+
+- The quote plugin (https://coq.inria.fr/distrib/V8.8.1/refman/proof-engine/detailed-tactic-examples.html#quote)
+ was removed. If some users are interested in maintaining this plugin
+ externally, the Coq development team can provide assistance for extracting
+ the plugin and setting up a new repository.
+
+Tactics
+
+- Removed the deprecated `romega` tactics.
+
Changes from 8.8.2 to 8.9+beta1
===============================
@@ -10,6 +24,11 @@ Notations
- New support for autonomous grammars of terms, called "custom
entries" (see chapter "Syntax extensions" of the reference manual).
+- New command "Declare Scope" to explicitly declare a scope name
+ before any use of it. Implicit declaration of a scope at the time of
+ "Bind Scope", "Delimit Scope", "Undelimit Scope", or "Notation" is
+ deprecated.
+
Tactics
- Added toplevel goal selector ! which expects a single focused goal.
@@ -34,6 +53,10 @@ Tactics
- Deprecated the Implicit Tactic family of commands.
+- The default program obligation tactic uses a bounded proof search
+ instead of an unbounded and potentially non-terminating one now
+ (source of incompatibility).
+
- The `simple apply` tactic now respects the `Opaque` flag when called from
Ltac (`auto` still does not respect it).
@@ -48,6 +71,34 @@ Tactics
may need to add `Require Import Lra` to your developments. For compatibility,
we now define `fourier` as a deprecated alias of `lra`.
+- The `romega` tactics have been deprecated; please use `lia` instead.
+
+- Names of existential variables occurring in Ltac functions
+ (e.g. "?[n]" or "?n" in terms - not in patterns) are now interpreted
+ the same way as other variable names occurring in Ltac functions.
+
+Focusing
+
+- Focusing bracket `{` now supports named goal selectors,
+ e.g. `[x]: {` will focus on a goal (existential variable) named `x`.
+ As usual, unfocus with `}` once the sub-goal is fully solved.
+
+Specification language, type inference
+
+- A fix to unification (which was sensitive to the ascii name of
+ variables) may occasionally change type inference in incompatible
+ ways, especially regarding the inference of the return clause of "match".
+
+- Fixing a missing check in interpreting instances of existential
+ variables which are bound to local definitions might exceptionally
+ induce an overhead if the cost of checking the conversion of the
+ corresponding definitions is additionally high (PR #8215).
+
+- A few improvements in inference of the return clause of "match" can
+ exceptionally introduce incompatibilities (PR #262). This can be
+ solved by writing an explicit "return" clause, sometimes even simply
+ an explicit "return _" clause.
+
Standard Library
- Added `Ascii.eqb` and `String.eqb` and the `=?` notation for them,
@@ -58,6 +109,37 @@ Standard Library
want).
- Added `Ndigits.N2Bv_sized`, and proved some lemmas about it.
+ Deprecated `Ndigits.N2Bv_gen`.
+
+- The scopes `int_scope` and `uint_scope` have been renamed to
+ `dec_int_scope` and `dec_uint_scope`, to clash less with ssreflect
+ and other packages. They are still delimited by `%int` and `%uint`.
+
+- Syntax notations for `string`, `ascii`, `Z`, `positive`, `N`, `R`,
+ and `int31` are no longer available merely by `Require`ing the files
+ that define the inductives. You must `Import` `Coq.Strings.String`,
+ `Coq.Strings.Ascii`, `Coq.ZArith.BinIntDef`, `Coq.PArith.BinPosDef`,
+ `Coq.NArith.BinNatDef`, `Coq.Reals.Rdefinitions`, and
+ `Coq.Numbers.Cyclic.Int31.Int31`, respectively, to be able to use
+ these notations. Note that passing `-compat 8.8` or issuing
+ `Require Import Coq.Compat.Coq88` will make these notations
+ available. Users wishing to port their developments automatically
+ may download `fix.py` from
+ <https://gist.github.com/JasonGross/5d4558edf8f5c2c548a3d96c17820169>
+ and run a command like `while true; do make -Okj 2>&1 |
+ /path/to/fix.py; done` and get a cup of coffee. (This command must
+ be manually interrupted once the build finishes all the way though.
+ Note also that this method is not fail-proof; you may have to adjust
+ some scopes if you were relying on string notations not being
+ available even when `string_scope` was open.)
+
+- Numeral syntax for `nat` is no longer available without loading the
+ entire prelude (`Require Import Coq.Init.Prelude`). This only
+ impacts users running Coq without the init library (`-nois` or
+ `-noinit`) and also issuing `Require Import Coq.Init.Datatypes`.
+
+- Added `Bvector.BVeq` that decides whether two `Bvector`s are equal.
+- Added notations for `BVxor`, `BVand`, `BVor`, `BVeq` and `BVneg`.
Tools
@@ -76,6 +158,7 @@ Tools
please open an issue. We can help set up external maintenance as part
of Proof-General, or independently as part of coq-community.
+
Vernacular Commands
- Removed deprecated commands Arguments Scope and Implicit Arguments
@@ -91,10 +174,14 @@ Vernacular Commands
overwritting the opacity set of the hint database.
- Added generic syntax for “attributes”, as in:
`#[local] Lemma foo : bar.`
+- Added the `Numeral Notation` command for registering decimal numeral
+ notations for custom types
- The `Set SsrHave NoTCResolution` command no longer has special global
scope. If you want the previous behavior, use `Global Set SsrHave
NoTCResolution`.
- Multiple sections with the same name are allowed.
+- Combined Scheme can now work when inductive schemes are generated in sort
+ Type. It used to be limited to sort Prop.
Coq binaries and process model
@@ -147,7 +234,34 @@ Notations
Note that this might cause incompatibilities if you have, e.g., list_scope
and vector_scope both open with vector_scope on top, and expect `++` to
refer to `app`.
- Solution: wrap `_ ++ _` in `(_ ++ _)%list` (or whichever scope you want).
+ Solution: wrap `_ ++ _` in `(_ ++ _)%list` (or whichever scope you want).
+
+Changes from 8.8.1 to 8.8.2
+===========================
+
+Documentation
+
+- A PDF version of the reference manual is available once again.
+
+Tools
+
+- The coq-makefile targets `print-pretty-timed`, `print-pretty-timed-diff`,
+ and `print-pretty-single-time-diff` now correctly label the "before" and
+ "after" columns, rather than swapping them.
+
+Kernel
+
+- The kernel does not tolerate capture of global universes by
+ polymorphic universe binders, fixing a soundness break (triggered
+ only through custom plugins)
+
+Windows installer
+
+- The Windows installer now includes many more external packages that can be
+individually selected for installation.
+
+Many other bug fixes and lots of documentation improvements (for details,
+see the 8.8.2 milestone at https://github.com/coq/coq/milestone/15?closed=1).
Changes from 8.8.0 to 8.8.1
===========================
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000000..8eee2009c9
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,118 @@
+# Coq Code of Conduct #
+
+The Coq development team and the user community are made up of a mixture of
+professionals and volunteers from all over the world.
+Diversity brings variety of perspectives that can be very valuable, but it can
+also lead to communication issues and unhappiness. Therefore, we have a few
+ground rules that we ask people to adhere to.
+These rules apply equally to core developers (who should lead by example),
+occasional contributors and those seeking help and guidance.
+Their goal is that everyone feels safe and welcome when contributing to Coq or
+interacting with others in Coq related forums.
+
+These rules apply to all spaces managed by the Coq development team.
+This includes the GitHub repository, the mailing lists, the Gitter channel,
+physical events like Coq working groups and workshops, and any other forums
+created or managed by the development team which the community uses for
+communication. In addition, violations of these rules outside these spaces may
+affect a person's ability to participate within them.
+
+- **Be friendly and patient.**
+- **Be welcoming.**
+ We strive to be a community that welcomes and supports people of all
+ backgrounds and identities. This includes, but is not limited to people of
+ any origin, color, status, educational level, gender identity, sexual
+ orientation, age, culture and beliefs, and mental and physical ability.
+- **Be considerate.**
+ Your work will be used by other people, and you in turn will depend on the
+ work of others. Any decision you take will affect users and colleagues, and
+ you should take those consequences into account when making decisions.
+- **Be respectful.**
+ Not all of us will agree all the time, but disagreement is no excuse for poor
+ behavior and poor manners. We might all experience some frustration now and
+ then, but we cannot allow that frustration to turn into a personal attack.
+ It's important to remember that a community where people feel uncomfortable
+ or threatened is not a productive one. Members of the Coq development team
+ and user community should be respectful when dealing with other members as
+ well as with people outside the community.
+- **Be careful in the words that you choose.**
+ Be kind to others. Do not insult or put down other participants. Harassment
+ and other exclusionary behavior aren't acceptable.
+ * Violent language or threats or personal insults have no chance to
+ resolve a dispute or to let a discussion florish. Worse, they can
+ hurt durably, or generate durable fears. They are thus unwelcome.
+ * Not everyone is comfortable with sexually explicit or violent
+ material, even as a joke. In an online open multicultural world, you
+ don't know who might be listening. So be cautious and responsible
+ with your words.
+ * Discussions are online and recorded for posterity; we all have our
+ right for privacy and online gossiping as well as posting or threatening to
+ post other people's personally identifying information is prohibited.
+- **Remember that what you write in a public online forum might be read by
+ many people you don't know.**
+ Consider what image your words will give to outsiders of the development
+ team / the user community as a whole. Try to avoid references to private
+ knowledge to be understandable by anyone.
+- **Coq online forums are only to discuss Coq-related subjects.**
+ Unrelated political discussions or long digressions are unwelcome,
+ even for illustration or comparison purposes.
+- **When we disagree, try to understand why.**
+ Disagreements, both social and technical, happen all the time and Coq is no
+ exception. It is important that we resolve disagreements and differing views
+ constructively. Remember that we are different. Different people
+ have different perspectives on issues. Being unable to understand why someone
+ holds a viewpoint doesn't mean that they're wrong.
+- **It is human to make errors, and please try not to take things personally.**
+ Please do not answer aggressively to problematic behavior and simply
+ signal the issue. If actions have been taken with you (e.g. bans or simple
+ demands of apology, of rephrasing or keeping personal beliefs or troubles
+ private), please understand that they are not intended as aggression or
+ punishment ― even if you they feel harsh to you ― but as ways to enforce a
+ calm communication for the other participants and to give you the opportunity
+ to change your behavior. We understand you may feel hurt, or maybe you had a
+ bad day, so please take this opportunity to question yourself, cool down if
+ necessary and do not persist in the exact same behavior you have been
+ reported for.
+
+## Enforcement ##
+
+If you believe someone is violating the code of conduct, we ask that you report
+it by emailing the Coq Code of Conduct enforcement team at
+<coq-conduct@inria.fr>. Confidentiality with regard to the reporter of an
+incident will be maintained while dealing with it.
+
+In particular, you should seek support from the team instead of dealing by
+yourself with a behavior that you consider hurtful. This applies to members of
+the enforcement team as well, who shouldn't deal by themselves with violations
+in discussions in which they are a participant.
+
+Depending on the violation, the team can choose to address a private or public
+warning to the offender, request an apology, or ban them for a short or a long
+period from interacting on one or all of our forums.
+
+Except in case of serious violations, the team will always try a pedagogical
+approach first (the offender does not necessarily realize immediately why their
+behavior is wrong). We consider short bans to form part of the pedagogical
+approach, especially when they come with explanatory comments, as this can give
+some time to the offender to calm down and think about their actions.
+
+## Questions? ##
+
+If you have questions, feel free to write to <coq-conduct@inria.fr>.
+
+## Attribution ##
+
+This text is adapted from the [Django Code of Conduct][django-code-of-conduct]
+which itself was adapted from the Speak Up! Community Code of Conduct.
+
+## License ##
+
+<a rel="license" href="http://creativecommons.org/licenses/by/4.0/">
+<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by/4.0/88x31.png">
+</a><br>
+This work is licensed under a
+<a rel="license" href="http://creativecommons.org/licenses/by/4.0/">
+Creative Commons Attribution 4.0 International License
+</a>.
+
+[django-code-of-conduct]: https://web.archive.org/web/20180714161115/https://www.djangoproject.com/conduct/
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 9bd3d0b7c7..de7fb9183c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -50,15 +50,28 @@ information on CI tests, including how to run them on your private branches.
If your pull request fixes a bug, please consider adding a regression test as
well. See [`test-suite/README.md`](test-suite/README.md) for how to do so.
+If your pull request fixes a critical bug (a bug allowing a proof of `False`),
+please add an entry to [`dev/doc/critical-bugs`](/dev/doc/critical-bugs).
+
Don't be alarmed if the pull request process takes some time. It can take a few days to get feedback, approval on the final changes, and then a merge. Coq doesn't release new versions very frequently so it can take a few months for your change to land in a released version. That said, you can start using the latest Coq `master` branch to take advantage of all the new features, improvements, and fixes.
Whitespace discipline (do not indent using tabs, no trailing spaces, text files end with newlines) is checked by Travis (using `git diff --check`). We ship a [`dev/tools/pre-commit`](/dev/tools/pre-commit) git hook which fixes these errors at commit time. `configure` automatically sets you up to use it, unless you already have a hook at `.git/hooks/pre-commit`.
Here are a few tags Coq developers may add to your PR and what they mean. In general feedback and requests for you as the pull request author will be in the comments and tags are only used to organize pull requests.
-- [needs: rebase](https://github.com/coq/coq/pulls?utf8=%E2%9C%93&q=is%3Aopen%20is%3Apr%20label%3A%22needs%3A%20rebase%22) indicates the PR should be rebased on top of the latest `master` branch. See the [GitHub documentation](https://help.github.com/articles/about-git-rebase/) for a brief introduction to using `git rebase`.
-- [needs: fixing](https://github.com/coq/coq/pulls?q=is%3Aopen+is%3Apr+label%3A%22needs%3A+fixing%22) indicates the PR needs a fix, as discussed in the comments.
-- [needs: benchmarking](https://github.com/coq/coq/pulls?q=is%3Aopen+is%3Apr+label%3A%22needs%3A+benchmarking%22) and [needs: testing](https://github.com/coq/coq/pulls?q=is%3Aopen+is%3Apr+label%3A%22needs%3A+testing%22) indicate the PR needs testing beyond what the test suite can handle. For example, performance benchmarking is currently performed with a different infrastructure. Unless some followup is specifically requested you aren't expected to do this additional testing.
+- [needs: rebase][rebase-label] indicates the PR should be rebased on top of
+ the latest base branch (usually `master`). See the
+ [GitHub documentation](https://help.github.com/articles/about-git-rebase/)
+ for a brief introduction to using `git rebase`.
+ This label will be automatically added if you open or synchronize your PR and
+ it is not up-to-date with the base branch. So please, do not forget to rebase
+ your branch every time you update it.
+- [needs: fixing][fixing-label] indicates the PR needs a fix, as discussed in the comments.
+- [needs: benchmarking][benchmarking-label] and [needs: testing][testing-label]
+ indicate the PR needs testing beyond what the test suite can handle.
+ For example, performance benchmarking is currently performed with a different
+ infrastructure ([documented in the wiki][jenkins-doc]). Unless some followup
+ is specifically requested you aren't expected to do this additional testing.
To learn more about the merging process, you can read the
[merging documentation for Coq maintainers](dev/doc/MERGING.md).
@@ -98,3 +111,10 @@ External plugins / libraries contribute to create a successful ecosystem around
Ask and answer questions on [Stack Exchange](https://stackexchange.com/filters/299857/questions-tagged-coq-on-stackexchange-sites) which has a helpful community of Coq users.
Hang out on the Coq IRC channel, `irc://irc.freenode.net/#coq`, and help answer questions.
+
+[rebase-label]: https://github.com/coq/coq/pulls?utf8=%E2%9C%93&q=is%3Aopen%20is%3Apr%20label%3A%22needs%3A%20rebase%22
+[fixing-label]: https://github.com/coq/coq/pulls?q=is%3Aopen+is%3Apr+label%3A%22needs%3A+fixing%22
+[benchmarking-label]: https://github.com/coq/coq/pulls?q=is%3Aopen+is%3Apr+label%3A%22needs%3A+benchmarking%22
+[testing-label]: https://github.com/coq/coq/pulls?q=is%3Aopen+is%3Apr+label%3A%22needs%3A+testing%22
+
+[jenkins-doc]: https://github.com/coq/coq/wiki/Jenkins-(automated-benchmarking)
diff --git a/CREDITS b/CREDITS
index 9c3a93da87..3010adc3e1 100644
--- a/CREDITS
+++ b/CREDITS
@@ -50,8 +50,6 @@ plugins/nsatz
developed by Loïc Pottier (INRIA-Marelle, 2009-2011)
plugins/omega
developed by Pierre Crégut (France Telecom R&D, 1996)
-plugins/quote
- developed by Patrick Loiseleur (LRI, 1997-1999)
plugins/romega
developed by Pierre Crégut (France Telecom R&D, 2001-2004)
plugins/rtauto
diff --git a/META.coq.in b/META.coq.in
index b2924e3241..1ccde1338f 100644
--- a/META.coq.in
+++ b/META.coq.in
@@ -1,7 +1,7 @@
# TODO: Generate automatically with Dune
description = "The Coq Proof Assistant Plugin API"
-version = "8.9"
+version = "8.10"
directory = ""
requires = "camlp5"
@@ -9,7 +9,7 @@ requires = "camlp5"
package "grammar" (
description = "Coq Camlp5 Grammar Extensions for Plugins"
- version = "8.9"
+ version = "8.10"
requires = "camlp5.gramlib"
directory = "grammar"
@@ -21,7 +21,7 @@ package "grammar" (
package "config" (
description = "Coq Configuration Variables"
- version = "8.9"
+ version = "8.10"
directory = "config"
@@ -29,7 +29,7 @@ package "config" (
package "clib" (
description = "Base General Coq Library"
- version = "8.9"
+ version = "8.10"
directory = "clib"
requires = "num, str, unix, threads"
@@ -41,7 +41,7 @@ package "clib" (
package "lib" (
description = "Base Coq-Specific Library"
- version = "8.9"
+ version = "8.10"
directory = "lib"
@@ -55,7 +55,7 @@ package "lib" (
package "vm" (
description = "Coq VM"
- version = "8.9"
+ version = "8.10"
directory = "kernel/byterun"
@@ -74,7 +74,7 @@ package "vm" (
package "kernel" (
description = "Coq's Kernel"
- version = "8.9"
+ version = "8.10"
directory = "kernel"
@@ -88,7 +88,7 @@ package "kernel" (
package "library" (
description = "Coq Libraries (vo) support"
- version = "8.9"
+ version = "8.10"
requires = "coq.kernel"
@@ -102,7 +102,7 @@ package "library" (
package "engine" (
description = "Coq Tactic Engine"
- version = "8.9"
+ version = "8.10"
requires = "coq.library"
directory = "engine"
@@ -115,7 +115,7 @@ package "engine" (
package "pretyping" (
description = "Coq Pretyper"
- version = "8.9"
+ version = "8.10"
requires = "coq.engine"
directory = "pretyping"
@@ -128,7 +128,7 @@ package "pretyping" (
package "interp" (
description = "Coq Term Interpretation"
- version = "8.9"
+ version = "8.10"
requires = "coq.pretyping"
directory = "interp"
@@ -141,7 +141,7 @@ package "interp" (
package "proofs" (
description = "Coq Proof Engine"
- version = "8.9"
+ version = "8.10"
requires = "coq.interp"
directory = "proofs"
@@ -154,7 +154,7 @@ package "proofs" (
package "parsing" (
description = "Coq Parsing Engine"
- version = "8.9"
+ version = "8.10"
requires = "camlp5.gramlib, coq.proofs"
directory = "parsing"
@@ -167,7 +167,7 @@ package "parsing" (
package "printing" (
description = "Coq Printing Engine"
- version = "8.9"
+ version = "8.10"
requires = "coq.parsing"
directory = "printing"
@@ -180,7 +180,7 @@ package "printing" (
package "tactics" (
description = "Coq Basic Tactics"
- version = "8.9"
+ version = "8.10"
requires = "coq.printing"
directory = "tactics"
@@ -193,7 +193,7 @@ package "tactics" (
package "vernac" (
description = "Coq Vernacular Interpreter"
- version = "8.9"
+ version = "8.10"
requires = "coq.tactics"
directory = "vernac"
@@ -206,7 +206,7 @@ package "vernac" (
package "stm" (
description = "Coq State Transactional Machine"
- version = "8.9"
+ version = "8.10"
requires = "coq.vernac"
directory = "stm"
@@ -219,7 +219,7 @@ package "stm" (
package "toplevel" (
description = "Coq Toplevel"
- version = "8.9"
+ version = "8.10"
requires = "coq.stm"
directory = "toplevel"
@@ -232,7 +232,7 @@ package "toplevel" (
package "idetop" (
description = "Coq IDE Libraries"
- version = "8.9"
+ version = "8.10"
requires = "coq.toplevel"
directory = "ide"
@@ -246,7 +246,7 @@ package "idetop" (
package "ide" (
description = "Coq IDE Libraries"
- version = "8.9"
+ version = "8.10"
# XXX Add GTK
requires = "coq.toplevel"
@@ -260,14 +260,14 @@ package "ide" (
package "plugins" (
description = "Coq built-in plugins"
- version = "8.9"
+ version = "8.10"
directory = "plugins"
package "ltac" (
description = "Coq LTAC Plugin"
- version = "8.9"
+ version = "8.10"
requires = "coq.stm"
directory = "ltac"
@@ -280,7 +280,7 @@ package "plugins" (
package "tauto" (
description = "Coq tauto plugin"
- version = "8.9"
+ version = "8.10"
requires = "coq.plugins.ltac"
directory = "ltac"
@@ -292,7 +292,7 @@ package "plugins" (
package "omega" (
description = "Coq omega plugin"
- version = "8.9"
+ version = "8.10"
requires = "coq.plugins.ltac"
directory = "omega"
@@ -301,22 +301,10 @@ package "plugins" (
archive(native) = "omega_plugin.cmx"
)
- package "romega" (
-
- description = "Coq romega plugin"
- version = "8.9"
-
- requires = "coq.plugins.omega"
- directory = "romega"
-
- archive(byte) = "romega_plugin.cmo"
- archive(native) = "romega_plugin.cmx"
- )
-
package "micromega" (
description = "Coq micromega plugin"
- version = "8.9"
+ version = "8.10"
requires = "num,coq.plugins.ltac"
directory = "micromega"
@@ -325,24 +313,12 @@ package "plugins" (
archive(native) = "micromega_plugin.cmx"
)
- package "quote" (
-
- description = "Coq quote plugin"
- version = "8.9"
-
- requires = "coq.plugins.ltac"
- directory = "quote"
-
- archive(byte) = "quote_plugin.cmo"
- archive(native) = "quote_plugin.cmx"
- )
-
package "newring" (
description = "Coq newring plugin"
- version = "8.9"
+ version = "8.10"
- requires = "coq.plugins.quote"
+ requires = ""
directory = "setoid_ring"
archive(byte) = "newring_plugin.cmo"
@@ -352,7 +328,7 @@ package "plugins" (
package "extraction" (
description = "Coq extraction plugin"
- version = "8.9"
+ version = "8.10"
requires = "coq.plugins.ltac"
directory = "extraction"
@@ -364,7 +340,7 @@ package "plugins" (
package "cc" (
description = "Coq cc plugin"
- version = "8.9"
+ version = "8.10"
requires = "coq.plugins.ltac"
directory = "cc"
@@ -376,7 +352,7 @@ package "plugins" (
package "ground" (
description = "Coq ground plugin"
- version = "8.9"
+ version = "8.10"
requires = "coq.plugins.ltac"
directory = "firstorder"
@@ -388,7 +364,7 @@ package "plugins" (
package "rtauto" (
description = "Coq rtauto plugin"
- version = "8.9"
+ version = "8.10"
requires = "coq.plugins.ltac"
directory = "rtauto"
@@ -400,7 +376,7 @@ package "plugins" (
package "btauto" (
description = "Coq btauto plugin"
- version = "8.9"
+ version = "8.10"
requires = "coq.plugins.ltac"
directory = "btauto"
@@ -412,7 +388,7 @@ package "plugins" (
package "recdef" (
description = "Coq recdef plugin"
- version = "8.9"
+ version = "8.10"
requires = "coq.plugins.extraction"
directory = "funind"
@@ -424,7 +400,7 @@ package "plugins" (
package "nsatz" (
description = "Coq nsatz plugin"
- version = "8.9"
+ version = "8.10"
requires = "num,coq.plugins.ltac"
directory = "nsatz"
@@ -436,7 +412,7 @@ package "plugins" (
package "natsyntax" (
description = "Coq natsyntax plugin"
- version = "8.9"
+ version = "8.10"
requires = ""
directory = "syntax"
@@ -448,7 +424,7 @@ package "plugins" (
package "zsyntax" (
description = "Coq zsyntax plugin"
- version = "8.9"
+ version = "8.10"
requires = ""
directory = "syntax"
@@ -460,7 +436,7 @@ package "plugins" (
package "rsyntax" (
description = "Coq rsyntax plugin"
- version = "8.9"
+ version = "8.10"
requires = ""
directory = "syntax"
@@ -472,7 +448,7 @@ package "plugins" (
package "int31syntax" (
description = "Coq int31syntax plugin"
- version = "8.9"
+ version = "8.10"
requires = ""
directory = "syntax"
@@ -484,7 +460,7 @@ package "plugins" (
package "asciisyntax" (
description = "Coq asciisyntax plugin"
- version = "8.9"
+ version = "8.10"
requires = ""
directory = "syntax"
@@ -496,7 +472,7 @@ package "plugins" (
package "stringsyntax" (
description = "Coq stringsyntax plugin"
- version = "8.9"
+ version = "8.10"
requires = "coq.plugins.asciisyntax"
directory = "syntax"
@@ -508,7 +484,7 @@ package "plugins" (
package "derive" (
description = "Coq derive plugin"
- version = "8.9"
+ version = "8.10"
requires = ""
directory = "derive"
@@ -520,7 +496,7 @@ package "plugins" (
package "ssrmatching" (
description = "Coq ssrmatching plugin"
- version = "8.9"
+ version = "8.10"
requires = "coq.plugins.ltac"
directory = "ssrmatching"
@@ -532,7 +508,7 @@ package "plugins" (
package "ssreflect" (
description = "Coq ssreflect plugin"
- version = "8.9"
+ version = "8.10"
requires = "coq.plugins.ssrmatching"
directory = "ssr"
diff --git a/Makefile b/Makefile
index 636093d7a5..2e4f46272e 100644
--- a/Makefile
+++ b/Makefile
@@ -81,7 +81,7 @@ export ML4FILES := $(call find, '*.ml4')
export MLGFILES := $(call find, '*.mlg')
export CFILES := $(call findindir, 'kernel/byterun', '*.c')
-export MERLININFILES := $(call find, '.merlin.in')
+MERLININFILES := $(call find, '.merlin.in')
export MERLINFILES := $(MERLININFILES:.in=)
# NB: The lists of currently existing .ml and .mli files will change
@@ -116,7 +116,7 @@ include Makefile.common
NOARG: world
-.PHONY: NOARG help noconfig submake
+.PHONY: NOARG help noconfig submake camldevfiles
help:
@echo "Please use either:"
@@ -143,12 +143,13 @@ Then, you may want to consider whether you want to restore the autosaves)
#run.
endif
-# Apart from clean and tags, everything will be done in a sub-call to make
-# on Makefile.build. This way, we avoid doing here the -include of .d :
-# since they trigger some compilations, we do not want them for a mere clean.
-# Moreover, we regroup this sub-call in a common target named 'submake'.
-# This way, multiple user-given goals (cf the MAKECMDGOALS variable) won't
-# trigger multiple (possibly parallel) make sub-calls
+# Apart from clean and a few misc files, everything will be done in a
+# sub-call to make on Makefile.build. This way, we avoid doing here
+# the -include of .d : since they trigger some compilations, we do not
+# want them for a mere clean. Moreover, we regroup this sub-call in a
+# common target named 'submake'. This way, multiple user-given goals
+# (cf the MAKECMDGOALS variable) won't trigger multiple (possibly
+# parallel) make sub-calls
ifdef COQ_CONFIGURED
%:: submake ;
@@ -161,7 +162,7 @@ MAKE_OPTS := --warn-undefined-variable --no-builtin-rules
bin:
mkdir bin
-submake: alienclean | bin
+submake: alienclean camldevfiles | bin
$(MAKE) $(MAKE_OPTS) -f Makefile.build $(MAKECMDGOALS)
noconfig:
@@ -172,6 +173,23 @@ noconfig:
Makefile $(wildcard Makefile.*) config/Makefile : ;
###########################################################################
+# OCaml dev files
+###########################################################################
+camldevfiles: $(MERLINFILES) META.coq
+
+# prevent submake dependency
+META.coq.in $(MERLININFILES): ;
+
+.merlin: .merlin.in
+ cp -a "$<" "$@"
+
+%/.merlin: %/.merlin.in
+ cp -a "$<" "$@"
+
+META.coq: META.coq.in
+ cp -a "$<" "$@"
+
+###########################################################################
# Cleaning
###########################################################################
@@ -184,7 +202,7 @@ cleankeepvo: indepclean clean-ide optclean cruftclean depclean docclean devdoccl
objclean: archclean indepclean
cruftclean: ml4clean
- find . -name '*~' -o -name '*.annot' | xargs rm -f
+ find . \( -name '*~' -o -name '*.annot' \) -exec rm -f {} +
rm -f gmon.out core
camldevfilesclean:
@@ -193,7 +211,7 @@ camldevfilesclean:
indepclean:
rm -f $(GENFILES)
rm -f $(COQTOPBYTE) $(CHICKENBYTE) $(TOPBYTE)
- find . \( -name '*~' -o -name '*.cm[ioat]' -o -name '*.cmti' \) -delete
+ find . \( -name '*~' -o -name '*.cm[ioat]' -o -name '*.cmti' \) -exec rm -f {} +
rm -f */*.pp[iox] plugins/*/*.pp[iox]
rm -rf $(SOURCEDOCDIR)
rm -f toplevel/mltop.byteml toplevel/mltop.optml
@@ -224,7 +242,7 @@ archclean: clean-ide optclean voclean
optclean:
rm -f $(COQTOPEXE) $(CHICKEN) $(TOPBINOPT)
rm -f $(TOOLS) $(PRIVATEBINARIES) $(CSDPCERT)
- find . -name '*.cmx' -o -name '*.cmx[as]' -o -name '*.[soa]' -o -name '*.so' | xargs rm -f
+ find . \( -name '*.cmx' -o -name '*.cmx[as]' -o -name '*.[soa]' -o -name '*.so' \) -exec rm -f {} +
clean-ide:
rm -f $(COQIDECMO) $(COQIDECMX) $(COQIDECMO:.cmo=.cmi) $(COQIDEBYTE) $(COQIDE)
@@ -237,10 +255,10 @@ ml4clean:
rm -f $(GENML4FILES) $(GENMLGFILES)
depclean:
- find . $(FIND_SKIP_DIRS) '(' -name '*.d' ')' -print | xargs rm -f
+ find . $(FIND_SKIP_DIRS) '(' -name '*.d' ')' -exec rm -f {} +
cacheclean:
- find theories plugins test-suite -name '.*.aux' -delete
+ find theories plugins test-suite -name '.*.aux' -exec rm -f {} +
cleanconfig:
rm -f config/Makefile config/coq_config.ml myocamlbuild_config.ml dev/ocamldebug-coq dev/camlp5.dbg config/Info-*.plist
@@ -248,14 +266,18 @@ cleanconfig:
distclean: clean cleanconfig cacheclean timingclean
voclean:
- find theories plugins test-suite \( -name '*.vo' -o -name '*.glob' -o -name "*.cmxs" -o -name "*.native" -o -name "*.cmx" -o -name "*.cmi" -o -name "*.o" \) -delete
- find theories plugins test-suite -name .coq-native -empty -delete
+ find theories plugins test-suite \( -name '*.vo' -o -name '*.glob' -o -name "*.cmxs" \
+ -o -name "*.native" -o -name "*.cmx" -o -name "*.cmi" -o -name "*.o" \) -exec rm -f {} +
+ find theories plugins test-suite -name .coq-native -empty -exec rm -rf {} +
timingclean:
- find theories plugins test-suite \( -name '*.v.timing' -o -name '*.v.before-timing' -o -name "*.v.after-timing" -o -name "*.v.timing.diff" -o -name "time-of-build.log" -o -name "time-of-build-before.log" -o -name "time-of-build-after.log" -o -name "time-of-build-pretty.log" -o -name "time-of-build-both.log" \) -delete
+ find theories plugins test-suite \( -name '*.v.timing' -o -name '*.v.before-timing' \
+ -o -name "*.v.after-timing" -o -name "*.v.timing.diff" -o -name "time-of-build.log" \
+ -o -name "time-of-build-before.log" -o -name "time-of-build-after.log" \
+ -o -name "time-of-build-pretty.log" -o -name "time-of-build-both.log" \) -exec rm -f {} +
devdocclean:
- find . -name '*.dep.ps' -o -name '*.dot' | xargs rm -f
+ find . \( -name '*.dep.ps' -o -name '*.dot' \) -exec rm -f {} +
rm -f $(OCAMLDOCDIR)/*.log $(OCAMLDOCDIR)/*.aux $(OCAMLDOCDIR)/*.toc
rm -f $(OCAMLDOCDIR)/ocamldoc.sty $(OCAMLDOCDIR)/coq.tex
rm -f $(OCAMLDOCDIR)/html/*.html
diff --git a/Makefile.build b/Makefile.build
index 05633cecc8..0faa18b059 100644
--- a/Makefile.build
+++ b/Makefile.build
@@ -64,7 +64,7 @@ AFTER ?=
# build the different subsystems:
-world: camldevfiles coq coqide documentation revision
+world: coq coqide documentation revision
coq: coqlib coqbinaries tools
@@ -317,13 +317,11 @@ $(LIBCOQRUN): kernel/byterun/coq_jumptbl.h $(BYTERUN)
cd $(dir $(LIBCOQRUN)) && \
$(OCAMLFIND) ocamlmklib -oc $(COQRUN) $(notdir $(BYTERUN))
-kernel/byterun/coq_jumptbl.h : kernel/byterun/coq_instruct.h
- sed -n -e '/^ /s/ \([A-Z]\)/ \&\&coq_lbl_\1/gp' \
- -e '/^}/q' $< $(TOTARGET)
+kernel/byterun/coq_jumptbl.h : kernel/byterun/coq_instruct.h kernel/byterun/make_jumptbl.sh
+ kernel/byterun/make_jumptbl.sh $< $@
-kernel/copcodes.ml: kernel/byterun/coq_instruct.h
- tr -d "\r" < $< | sed -n -e '/^enum/p' -e 's/,//g' -e '/^ /p' | \
- awk -f kernel/make-opcodes $(TOTARGET)
+kernel/copcodes.ml: kernel/byterun/coq_instruct.h kernel/make_opcodes.sh kernel/make-opcodes
+ kernel/make_opcodes.sh $< $@
%.o: %.c
$(SHOW)'OCAMLC $<'
diff --git a/Makefile.ci b/Makefile.ci
index fce16906c4..7fdcb35bc9 100644
--- a/Makefile.ci
+++ b/Makefile.ci
@@ -22,6 +22,7 @@ CI_TARGETS=ci-bedrock2 \
ci-equations \
ci-fcsl-pcm \
ci-fiat-crypto \
+ ci-fiat-crypto-legacy \
ci-fiat-parsers \
ci-flocq \
ci-formal-topology \
@@ -33,8 +34,10 @@ CI_TARGETS=ci-bedrock2 \
ci-math-comp \
ci-mtac2 \
ci-pidetop \
+ ci-plugin-tutorial \
ci-quickchick \
ci-sf \
+ ci-simple-io \
ci-tlc \
ci-unimath \
ci-vst
@@ -53,7 +56,7 @@ ci-math-classes: ci-bignums
ci-corn: ci-math-classes
-ci-quickchick: ci-ext-lib
+ci-quickchick: ci-ext-lib ci-simple-io
ci-formal-topology: ci-corn
diff --git a/Makefile.common b/Makefile.common
index 772561bd70..f90919a4bc 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -95,7 +95,7 @@ CORESRCDIRS:=\
tactics vernac stm toplevel
PLUGINDIRS:=\
- omega romega micromega quote \
+ omega micromega \
setoid_ring extraction \
cc funind firstorder derive \
rtauto nsatz syntax btauto \
@@ -129,9 +129,7 @@ GRAMMARCMA:=grammar/grammar.cma
###########################################################################
OMEGACMO:=plugins/omega/omega_plugin.cmo
-ROMEGACMO:=plugins/romega/romega_plugin.cmo
MICROMEGACMO:=plugins/micromega/micromega_plugin.cmo
-QUOTECMO:=plugins/quote/quote_plugin.cmo
RINGCMO:=plugins/setoid_ring/newring_plugin.cmo
NSATZCMO:=plugins/nsatz/nsatz_plugin.cmo
EXTRACTIONCMO:=plugins/extraction/extraction_plugin.cmo
@@ -140,23 +138,22 @@ FOCMO:=plugins/firstorder/ground_plugin.cmo
CCCMO:=plugins/cc/cc_plugin.cmo
BTAUTOCMO:=plugins/btauto/btauto_plugin.cmo
RTAUTOCMO:=plugins/rtauto/rtauto_plugin.cmo
-NATSYNTAXCMO:=plugins/syntax/nat_syntax_plugin.cmo
-OTHERSYNTAXCMO:=$(addprefix plugins/syntax/, \
- positive_syntax_plugin.cmo n_syntax_plugin.cmo \
- z_syntax_plugin.cmo r_syntax_plugin.cmo \
+SYNTAXCMO:=$(addprefix plugins/syntax/, \
+ r_syntax_plugin.cmo \
int31_syntax_plugin.cmo \
ascii_syntax_plugin.cmo \
- string_syntax_plugin.cmo )
+ string_syntax_plugin.cmo \
+ numeral_notation_plugin.cmo)
DERIVECMO:=plugins/derive/derive_plugin.cmo
LTACCMO:=plugins/ltac/ltac_plugin.cmo plugins/ltac/tauto_plugin.cmo
SSRMATCHINGCMO:=plugins/ssrmatching/ssrmatching_plugin.cmo
SSRCMO:=plugins/ssr/ssreflect_plugin.cmo
-PLUGINSCMO:=$(LTACCMO) $(OMEGACMO) $(ROMEGACMO) $(MICROMEGACMO) \
- $(QUOTECMO) $(RINGCMO) \
+PLUGINSCMO:=$(LTACCMO) $(OMEGACMO) $(MICROMEGACMO) \
+ $(RINGCMO) \
$(EXTRACTIONCMO) \
$(CCCMO) $(FOCMO) $(RTAUTOCMO) $(BTAUTOCMO) \
- $(FUNINDCMO) $(NSATZCMO) $(NATSYNTAXCMO) $(OTHERSYNTAXCMO) \
+ $(FUNINDCMO) $(NSATZCMO) $(SYNTAXCMO) \
$(DERIVECMO) $(SSRMATCHINGCMO) $(SSRCMO)
ifeq ($(HASNATDYNLINK)-$(BEST),false-opt)
diff --git a/Makefile.dev b/Makefile.dev
index ea1a3d40a2..82b81908ac 100644
--- a/Makefile.dev
+++ b/Makefile.dev
@@ -15,7 +15,7 @@
# Debug printers in dev/
#########################
-.PHONY: devel printers camldevfiles
+.PHONY: devel printers
DEBUGPRINTERS:=dev/top_printers.cmo dev/vm_printers.cmo dev/checker_printers.cmo
@@ -85,27 +85,13 @@ endif
# But these partial targets could be quite handy for quick builds
# of specific components of Coq.
-###########################################################################
-# OCaml dev files
-###########################################################################
-camldevfiles: $(MERLINFILES) META.coq
-
-.merlin: .merlin.in
- cp -a "$<" "$@"
-
-%/.merlin: %/.merlin.in
- cp -a "$<" "$@"
-
-META.coq: META.coq.in
- cp -a "$<" "$@"
-
###############################
### 1) general-purpose targets
###############################
coqlight: theories-light tools coqbinaries
-states: camldevfiles theories/Init/Prelude.vo
+states: theories/Init/Prelude.vo
miniopt: $(COQTOPEXE) pluginsopt
minibyte: $(COQTOPBYTE) pluginsbyte
@@ -183,9 +169,7 @@ noreal: unicode logic arith bool zarith qarith lists sets fsets \
################
OMEGAVO:=$(filter plugins/omega/%, $(PLUGINSVO))
-ROMEGAVO:=$(filter plugins/romega/%, $(PLUGINSVO))
MICROMEGAVO:=$(filter plugins/micromega/%, $(PLUGINSVO))
-QUOTEVO:=$(filter plugins/quote/%, $(PLUGINSVO))
RINGVO:=$(filter plugins/setoid_ring/%, $(PLUGINSVO))
NSATZVO:=$(filter plugins/nsatz/%, $(PLUGINSVO))
FUNINDVO:=$(filter plugins/funind/%, $(PLUGINSVO))
@@ -196,7 +180,7 @@ CCVO:=
DERIVEVO:=$(filter plugins/derive/%, $(PLUGINSVO))
LTACVO:=$(filter plugins/ltac/%, $(PLUGINSVO))
-omega: $(OMEGAVO) $(OMEGACMO) $(ROMEGAVO) $(ROMEGACMO)
+omega: $(OMEGAVO) $(OMEGACMO)
micromega: $(MICROMEGAVO) $(MICROMEGACMO) $(CSDPCERT)
setoid_ring: $(RINGVO) $(RINGCMO)
nsatz: $(NSATZVO) $(NSATZCMO)
diff --git a/Makefile.doc b/Makefile.doc
index dde3a37b70..db52607612 100644
--- a/Makefile.doc
+++ b/Makefile.doc
@@ -33,6 +33,10 @@ HTMLSTYLE:=coqremote
# Sphinx-related variables
SPHINXENV:=COQBIN="$(CURDIR)/bin/"
SPHINXOPTS= -j4
+SPHINXWARNERROR ?= 1
+ifeq ($(SPHINXWARNERROR),1)
+SPHINXOPTS += -W
+endif
SPHINXBUILD= sphinx-build
SPHINXBUILDDIR= doc/sphinx/_build
@@ -46,25 +50,35 @@ DOCCOMMON:=doc/common/version.tex doc/common/title.tex doc/common/macros.tex
######################################################################
.PHONY: doc doc-html doc-pdf doc-ps
-.PHONY: stdlib full-stdlib
+.PHONY: stdlib full-stdlib sphinx
-doc: sphinx stdlib
+doc: refman stdlib
ifndef QUICK
SPHINX_DEPS := coq
endif
-sphinx: $(SPHINX_DEPS)
- $(SHOW)'SPHINXBUILD doc/sphinx'
- $(HIDE)$(SPHINXENV) $(SPHINXBUILD) -W -b html $(ALLSPHINXOPTS) doc/sphinx $(SPHINXBUILDDIR)/html
- @echo
- @echo "Build finished. The HTML pages are in $(SPHINXBUILDDIR)/html."
+# refman-html and refman-latex
+refman-%: $(SPHINX_DEPS)
+ $(SHOW)'SPHINXBUILD doc/sphinx ($*)'
+ $(HIDE)$(SPHINXENV) $(SPHINXBUILD) -b $* \
+ $(ALLSPHINXOPTS) doc/sphinx $(SPHINXBUILDDIR)/$*
+
+refman-pdf: refman-latex
+ +$(MAKE) -C $(SPHINXBUILDDIR)/latex
+
+refman: $(SPHINX_DEPS)
+ +$(MAKE) refman-html
+ +$(MAKE) refman-pdf
+
+# compatibility alias
+sphinx: refman-html
doc-html:\
- doc/stdlib/html/index.html sphinx
+ doc/stdlib/html/index.html refman-html
doc-pdf:\
- doc/stdlib/Library.pdf
+ doc/stdlib/Library.pdf refman-pdf
doc-ps:\
doc/stdlib/Library.ps
@@ -214,9 +228,11 @@ ODOCDOTOPTS=-dot -dot-reduce
source-doc: mli-doc $(OCAMLDOCDIR)/coq.pdf
+OCAMLDOC_CAML_FLAGS=-rectypes -I +threads $(MLINCLUDES)
+
$(OCAMLDOCDIR)/coq.tex: $(DOCMLIS:.mli=.cmi)
$(SHOW)'OCAMLDOC -latex -o $@'
- $(HIDE)$(OCAMLFIND) ocamldoc -latex -rectypes -I $(MYCAMLP5LIB) $(MLINCLUDES)\
+ $(HIDE)$(OCAMLFIND) ocamldoc -latex $(OCAMLDOC_CAML_FLAGS) \
$(DOCMLIS) -noheader -t "Coq mlis documentation" \
-intro $(OCAMLDOCDIR)/docintro -o $@.tmp
$(SHOW)'OCAMLDOC utf8 fix'
@@ -226,31 +242,31 @@ $(OCAMLDOCDIR)/coq.tex: $(DOCMLIS:.mli=.cmi)
mli-doc: $(DOCMLIS:.mli=.cmi)
$(SHOW)'OCAMLDOC -html'
- $(HIDE)$(OCAMLFIND) ocamldoc -charset utf-8 -html -rectypes -I +threads -I $(MYCAMLP5LIB) $(MLINCLUDES) \
+ $(HIDE)$(OCAMLFIND) ocamldoc -charset utf-8 -html $(OCAMLDOC_CAML_FLAGS) \
$(DOCMLIS) -d $(OCAMLDOCDIR)/html -colorize-code \
-t "Coq mlis documentation" -intro $(OCAMLDOCDIR)/docintro \
-css-style style.css
ml-dot: $(MLFILES)
- $(OCAMLFIND) ocamldoc -dot -dot-reduce -rectypes -I +threads -I $(CAMLLIB) -I $(MYCAMLP5LIB) $(MLINCLUDES) \
+ $(OCAMLFIND) ocamldoc -dot -dot-reduce $(OCAMLDOC_CAML_FLAGS) \
$(filter $(addsuffix /%.ml,$(CORESRCDIRS)),$(MLFILES)) -o $(OCAMLDOCDIR)/coq.dot
%_dep.png: %.dot
$(DOT) -Tpng $< -o $@
%_types.dot: %.mli
- $(OCAMLFIND) ocamldoc -rectypes $(MLINCLUDES) $(ODOCDOTOPTS) -dot-types -o $@ $<
+ $(OCAMLFIND) ocamldoc $(OCAMLDOC_CAML_FLAGS) $(ODOCDOTOPTS) -dot-types -o $@ $<
-OCAMLDOC_MLLIBD = $(OCAMLFIND) ocamldoc -rectypes $(MLINCLUDES) $(ODOCDOTOPTS) -o $@ \
+OCAMLDOC_MLLIBD = $(OCAMLFIND) ocamldoc $(OCAMLDOC_CAML_FLAGS) $(ODOCDOTOPTS) -o $@ \
$(foreach lib,$(|:.mllib.d=_MLLIB_DEPENDENCIES),$(addsuffix .ml,$($(lib))))
%.dot: | %.mllib.d
$(OCAMLDOC_MLLIBD)
-ml-doc:
+ml-doc: kernel/copcodes.cmi
$(SHOW)'OCAMLDOC -html'
$(HIDE)mkdir -p $(OCAMLDOCDIR)/html/implementation
- $(HIDE)$(OCAMLFIND) ocamldoc -charset utf-8 -html -rectypes -I +threads $(MLINCLUDES) $(COQIDEFLAGS) \
+ $(HIDE)$(OCAMLFIND) ocamldoc -charset utf-8 -html $(OCAMLDOC_CAML_FLAGS) \
$(DOCMLS) -d $(OCAMLDOCDIR)/html/implementation -colorize-code \
-t "Coq mls documentation" \
-css-style ../style.css
@@ -265,7 +281,7 @@ tactics/tactics.dot: | tactics/tactics.mllib.d ltac/ltac.mllib.d
$(OCAMLDOC_MLLIBD)
%.dot: %.mli
- $(OCAMLFIND) ocamldoc -rectypes $(MLINCLUDES) $(ODOCDOTOPTS) -o $@ $<
+ $(OCAMLFIND) ocamldoc $(OCAMLDOC_CAML_FLAGS) $(ODOCDOTOPTS) -o $@ $<
$(OCAMLDOCDIR)/%.pdf: $(OCAMLDOCDIR)/%.tex
$(SHOW)'PDFLATEX $*.tex'
diff --git a/Makefile.dune b/Makefile.dune
new file mode 100644
index 0000000000..1e401a57b9
--- /dev/null
+++ b/Makefile.dune
@@ -0,0 +1,51 @@
+# -*- mode: makefile -*-
+# Dune Makefile for Coq
+
+.PHONY: help voboot states world apidoc
+
+# use DUNEOPT=--display=short for a more verbose build
+# DUNEOPT=--display=short
+
+BUILD_CONTEXT=_build/default
+
+help:
+ @echo "Welcome to Coq's Dune-based build system. Targets are:"
+ @echo " - states: build a minimal functional coqtop"
+ @echo " - world: build all binaries and libraries"
+ @echo " - watch: build all binaries and libraries [continuous build]"
+ @echo " - release: build Coq in release mode"
+ @echo " - apidoc: build ML API documentation"
+ @echo " - clean: remove build directory and autogenerated files"
+ @echo " - help: show this message"
+
+voboot:
+ dune build $(DUNEOPT) @vodeps
+ dune exec coq_dune $(BUILD_CONTEXT)/.vfiles.d
+
+states: voboot
+ dune build $(DUNEOPT) theories/Init/Prelude.vo
+
+world: voboot
+ dune build $(DUNEOPT) @install
+
+watch: voboot
+ dune build $(DUNEOPT) @install -w
+
+release: voboot
+ dune build $(DUNEOPT) -p coq
+
+apidoc: voboot
+ dune build $(DUNEOPT) @doc
+
+clean:
+ dune clean
+
+# Other common dev targets
+#
+# dune build coq.install
+# dune build ide/coqide.install
+
+# Packaging / OPAM targets:
+#
+# dune -p coq @install
+# dune -p coqide @install
diff --git a/checker/cic.mli b/checker/cic.mli
index df747692a4..4162903b04 100644
--- a/checker/cic.mli
+++ b/checker/cic.mli
@@ -132,7 +132,7 @@ type delta_hint =
type delta_resolver = ModPath.t MPmap.t * delta_hint KNmap.t
-type 'a umap_t = 'a MPmap.t * 'a MBImap.t
+type 'a umap_t = 'a MPmap.t
type substitution = (ModPath.t * delta_resolver) umap_t
(** {6 Delayed constr} *)
@@ -220,6 +220,7 @@ type typing_flags = {
points are assumed to be total. *)
check_universes : bool; (** If [false] universe constraints are not checked *)
conv_oracle : oracle; (** Unfolding strategies for conversion *)
+ share_reduction : bool; (** Use by-need reduction algorithm *)
}
type constant_body = {
diff --git a/checker/declarations.ml b/checker/declarations.ml
index 0540227ccb..03fee1ab51 100644
--- a/checker/declarations.ml
+++ b/checker/declarations.ml
@@ -28,18 +28,13 @@ let empty_delta_resolver = Deltamap.empty
module Umap = struct
[@@@ocaml.warning "-32-34"]
type 'a t = 'a umap_t
- let empty = MPmap.empty, MBImap.empty
- let is_empty (m1,m2) = MPmap.is_empty m1 && MBImap.is_empty m2
- let add_mbi mbi x (m1,m2) = (m1,MBImap.add mbi x m2)
- let add_mp mp x (m1,m2) = (MPmap.add mp x m1, m2)
- let find_mp mp map = MPmap.find mp (fst map)
- let find_mbi mbi map = MBImap.find mbi (snd map)
- let mem_mp mp map = MPmap.mem mp (fst map)
- let mem_mbi mbi map = MBImap.mem mbi (snd map)
- let iter_mbi f map = MBImap.iter f (snd map)
- let fold fmp fmbi (m1,m2) i =
- MPmap.fold fmp m1 (MBImap.fold fmbi m2 i)
- let join map1 map2 = fold add_mp add_mbi map1 map2
+ let empty = MPmap.empty
+ let is_empty m = MPmap.is_empty m
+ let add_mbi mbi x m = MPmap.add (MPbound mbi) x m
+ let add_mp mp x m = MPmap.add mp x m
+ let find = MPmap.find
+ let fold = MPmap.fold
+ let join map1 map2 = fold add_mp map1 map2
end
type 'a subst_fun = substitution -> 'a -> 'a
@@ -117,15 +112,10 @@ let constant_of_delta_with_inline resolve con =
let subst_mp0 sub mp = (* 's like subst *)
let rec aux mp =
match mp with
- | MPfile sid -> Umap.find_mp mp sub
- | MPbound bid ->
- begin
- try Umap.find_mbi bid sub
- with Not_found -> Umap.find_mp mp sub
- end
+ | MPfile _ | MPbound _ -> Umap.find mp sub
| MPdot (mp1,l) as mp2 ->
begin
- try Umap.find_mp mp2 sub
+ try Umap.find mp2 sub
with Not_found ->
let mp1',resolve = aux mp1 in
MPdot (mp1',l),resolve
@@ -382,9 +372,7 @@ let substition_prefixed_by k mp subst =
Umap.add_mp new_key (mp_to,reso) sub
else sub
in
- let mbi_prefixmp mbi _ sub = sub
- in
- Umap.fold mp_prefixmp mbi_prefixmp subst empty_subst
+ Umap.fold mp_prefixmp subst empty_subst
let join subst1 subst2 =
let apply_subst mpk add (mp,resolve) res =
@@ -404,8 +392,7 @@ let join subst1 subst2 =
Umap.join prefixed_subst (add (mp',resolve'') res)
in
let mp_apply_subst mp = apply_subst mp (Umap.add_mp mp) in
- let mbi_apply_subst mbi = apply_subst (MPbound mbi) (Umap.add_mbi mbi) in
- let subst = Umap.fold mp_apply_subst mbi_apply_subst subst1 empty_subst in
+ let subst = Umap.fold mp_apply_subst subst1 empty_subst in
Umap.join subst2 subst
let from_val x = { subst_value = x; subst_subst = []; }
diff --git a/checker/dune b/checker/dune
new file mode 100644
index 0000000000..d520171f98
--- /dev/null
+++ b/checker/dune
@@ -0,0 +1,32 @@
+(rule (copy %{project_root}/kernel/names.ml names.ml))
+(rule (copy %{project_root}/kernel/names.mli names.mli))
+(rule (copy %{project_root}/kernel/esubst.ml esubst.ml))
+(rule (copy %{project_root}/kernel/esubst.mli esubst.mli))
+
+; Careful with bug https://github.com/ocaml/odoc/issues/148
+;
+; If we don't pack checker we will have a problem here due to
+; duplicate module names in the whole build.
+(library
+ (name checklib)
+ (public_name coq.checklib)
+ (synopsis "Coq's Standalone Proof Checker")
+ (modules :standard \ main votour)
+ (modules_without_implementation cic)
+ (wrapped true)
+ (libraries coq.lib))
+
+(executable
+ (name main)
+ (public_name coqchk)
+ (modules main)
+ (flags :standard -open Checklib)
+ (libraries coq.checklib))
+
+(executable
+ (name votour)
+ (public_name votour)
+ (modules votour)
+ (flags :standard -open Checklib)
+ (libraries coq.checklib))
+
diff --git a/checker/environ.ml b/checker/environ.ml
index 74cf237763..b172acb126 100644
--- a/checker/environ.ml
+++ b/checker/environ.ml
@@ -183,7 +183,7 @@ let lookup_mind kn env =
let add_mind kn mib env =
if Mindmap_env.mem kn env.env_globals.env_inductives then
- Printf.ksprintf anomaly ("Inductive %s is already defined.")
+ Printf.ksprintf anomaly ("Mutual inductive block %s is already defined.")
(MutInd.to_string kn);
let new_inds = Mindmap_env.add kn mib env.env_globals.env_inductives in
let kn1,kn2 = MutInd.user kn, MutInd.canonical kn in
diff --git a/checker/indtypes.ml b/checker/indtypes.ml
index 8f11e01c33..1fd86bc368 100644
--- a/checker/indtypes.ml
+++ b/checker/indtypes.ml
@@ -595,8 +595,12 @@ let check_subtyping cumi paramsctxt env inds =
(************************************************************************)
(************************************************************************)
+let print_mutind ind =
+ let kn = MutInd.user ind in
+ str (ModPath.to_string (KerName.modpath kn) ^ "." ^ Label.to_string (KerName.label kn))
+
let check_inductive env kn mib =
- Flags.if_verbose Feedback.msg_notice (str " checking ind: " ++ MutInd.print kn);
+ Flags.if_verbose Feedback.msg_notice (str " checking mutind block: " ++ print_mutind kn);
(* check mind_constraints: should be consistent with env *)
let env0 =
match mib.mind_universes with
diff --git a/checker/typeops.ml b/checker/typeops.ml
index 138fe8bc95..e4c3f4ae4b 100644
--- a/checker/typeops.ml
+++ b/checker/typeops.ml
@@ -158,7 +158,7 @@ let judge_of_inductive_knowing_parameters env (ind,u) (paramstyp:constr array) =
let specif =
try lookup_mind_specif env ind
with Not_found ->
- failwith ("Cannot find inductive: "^MutInd.to_string (fst ind))
+ failwith ("Cannot find mutual inductive block: "^MutInd.to_string (fst ind))
in
type_of_inductive_knowing_parameters env (specif,u) paramstyp
@@ -172,7 +172,7 @@ let judge_of_constructor env (c,u) =
let specif =
try lookup_mind_specif env ind
with Not_found ->
- failwith ("Cannot find inductive: "^MutInd.to_string (fst ind))
+ failwith ("Cannot find mutual inductive block: "^MutInd.to_string (fst ind))
in
type_of_constructor (c,u) specif
diff --git a/checker/validate.ml b/checker/validate.ml
index f831875dd4..c214409a2c 100644
--- a/checker/validate.ml
+++ b/checker/validate.ml
@@ -85,6 +85,7 @@ let rec val_gen v ctx o = match v with
| Fail s -> fail ctx o ("unexpected object " ^ s)
| Annot (s,v) -> val_gen v (ctx/CtxAnnot s) o
| Dyn -> val_dyn ctx o
+ | Proxy { contents = v } -> val_gen v ctx o
(* Check that an object is a tuple (or a record). vs is an array of
value representation for each field. Its size corresponds to the
diff --git a/checker/values.ml b/checker/values.ml
index e68cd18b87..35027d5bfb 100644
--- a/checker/values.ml
+++ b/checker/values.ml
@@ -15,7 +15,7 @@
To ensure this file is up-to-date, 'make' now compares the md5 of cic.mli
with a copy we maintain here:
-MD5 064cd8d9651d37aebf77fb638b889cad checker/cic.mli
+MD5 a127e0c2322c7846914bbca9921309c7 checker/cic.mli
*)
@@ -45,6 +45,13 @@ type value =
| String
| Annot of string * value
| Dyn
+ | Proxy of value ref
+
+let fix (f : value -> value) : value =
+ let self = ref Any in
+ let ans = f (Proxy self) in
+ let () = self := ans in
+ ans
(** Some pseudo-constructors *)
@@ -185,10 +192,7 @@ let v_resolver =
let v_mp_resolver = v_tuple "" [|v_mp;v_resolver|]
let v_subst =
- v_tuple "substitution"
- [|v_map v_mp v_mp_resolver;
- v_map v_uid v_mp_resolver|]
-
+ Annot ("substitution", v_map v_mp v_mp_resolver)
(** kernel/lazyconstr *)
@@ -226,7 +230,7 @@ let v_cst_def =
[|[|Opt Int|]; [|v_cstr_subst|]; [|v_lazy_constr|]|]
let v_typing_flags =
- v_tuple "typing_flags" [|v_bool; v_bool; v_oracle|]
+ v_tuple "typing_flags" [|v_bool; v_bool; v_oracle; v_bool|]
let v_const_univs = v_sum "constant_universes" 0 [|[|v_context_set|]; [|v_abs_context|]|]
@@ -350,18 +354,16 @@ let v_states = v_pair Any v_frozen
let v_state = Tuple ("state", [|v_states; Any; v_bool|])
let v_vcs =
- let data = Opt Any in
- let vcs =
+ let vcs self =
Tuple ("vcs",
[|Any; Any;
Tuple ("dag",
[|Any; Any; v_map Any (Tuple ("state_info",
- [|Any; Any; Opt v_state; v_pair data Any|]))
+ [|Any; Any; Opt v_state; v_pair (Opt self) Any|]))
|])
|])
in
- let () = Obj.set_field (Obj.magic data) 0 (Obj.magic vcs) in
- vcs
+ fix vcs
let v_uuid = Any
let v_request id doc =
diff --git a/checker/values.mli b/checker/values.mli
index 20b9d54a68..1b1437a469 100644
--- a/checker/values.mli
+++ b/checker/values.mli
@@ -20,6 +20,7 @@ type value =
| String
| Annot of string * value
| Dyn
+ | Proxy of value ref
val v_univopaques : value
val v_libsum : value
diff --git a/checker/votour.ml b/checker/votour.ml
index bc820e23dd..1ea0de456e 100644
--- a/checker/votour.ml
+++ b/checker/votour.ml
@@ -152,6 +152,7 @@ let rec get_name ?(extra=false) = function
|String -> "string"
|Annot (s,v) -> s^"/"^get_name ~extra v
|Dyn -> "<dynamic>"
+ | Proxy v -> get_name ~extra !v
(** For tuples, its quite handy to display the inner 1st string (if any).
Cf. [structure_body] for instance *)
@@ -255,6 +256,7 @@ let rec get_children v o pos = match v with
| _ -> raise Exit
end
|Fail s -> raise Forbidden
+ | Proxy v -> get_children !v o pos
let get_children v o pos =
try get_children v o pos
diff --git a/clib/cList.ml b/clib/cList.ml
index de42886dcb..dc59ff2970 100644
--- a/clib/cList.ml
+++ b/clib/cList.ml
@@ -60,6 +60,7 @@ sig
val extend : bool list -> 'a -> 'a list -> 'a list
val count : ('a -> bool) -> 'a list -> int
val index : 'a eq -> 'a -> 'a list -> int
+ val safe_index : 'a eq -> 'a -> 'a list -> int option
val index0 : 'a eq -> 'a -> 'a list -> int
val fold_left_until : ('c -> 'a -> 'c CSig.until) -> 'c -> 'a list -> 'c
val fold_right_i : (int -> 'a -> 'b -> 'b) -> int -> 'a list -> 'b -> 'b
@@ -538,6 +539,8 @@ let rec index_f f x l n = match l with
let index f x l = index_f f x l 1
+let safe_index f x l = try Some (index f x l) with Not_found -> None
+
let index0 f x l = index_f f x l 0
(** {6 Folding} *)
diff --git a/clib/cList.mli b/clib/cList.mli
index 42fae5ed39..39d9a5e535 100644
--- a/clib/cList.mli
+++ b/clib/cList.mli
@@ -155,6 +155,10 @@ sig
val index : 'a eq -> 'a -> 'a list -> int
(** [index] returns the 1st index of an element in a list (counting from 1). *)
+ val safe_index : 'a eq -> 'a -> 'a list -> int option
+ (** [safe_index] returns the 1st index of an element in a list (counting from 1)
+ and None otherwise. *)
+
val index0 : 'a eq -> 'a -> 'a list -> int
(** [index0] behaves as [index] except that it starts counting at 0. *)
@@ -285,8 +289,8 @@ sig
val share_tails : 'a list -> 'a list -> 'a list * 'a list * 'a list
(** [share_tails l1 l2] returns [(l1',l2',l)] such that [l1] is
- [l1'@l] and [l2] is [l2'@l] and [l] is maximal amongst all such
- decompositions*)
+ [l1'\@l] and [l2] is [l2'\@l] and [l] is maximal amongst all such
+ decompositions *)
(** {6 Association lists} *)
diff --git a/clib/dune b/clib/dune
new file mode 100644
index 0000000000..689a955ab7
--- /dev/null
+++ b/clib/dune
@@ -0,0 +1,8 @@
+(library
+ (name clib)
+ (synopsis "Coq's Utility Library [general purpose]")
+ (public_name coq.clib)
+ (wrapped false)
+ (modules_without_implementation cSig)
+ (libraries threads str unix dynlink))
+
diff --git a/config/dune b/config/dune
new file mode 100644
index 0000000000..ce87a7816d
--- /dev/null
+++ b/config/dune
@@ -0,0 +1,13 @@
+(library
+ (name config)
+ (synopsis "Coq Configuration Variables")
+ (public_name coq.config)
+ (wrapped false))
+
+; Dune doesn't use configure's output, but it is still necessary for
+; some Coq files to work; will be fixed in the future.
+(rule
+ (targets coq_config.ml)
+ (mode fallback)
+ (deps %{project_root}/configure.ml %{project_root}/dev/ocamldebug-coq.run (env_var COQ_CONFIGURE_PREFIX))
+ (action (chdir %{project_root} (run %{ocaml} configure.ml -no-ask -native-compiler no))))
diff --git a/configure.ml b/configure.ml
index 7fd900d995..277c3d6439 100644
--- a/configure.ml
+++ b/configure.ml
@@ -11,11 +11,11 @@
#load "str.cma"
open Printf
-let coq_version = "8.9+alpha"
-let coq_macos_version = "8.8.90" (** "[...] should be a string comprised of
+let coq_version = "8.10+alpha"
+let coq_macos_version = "8.9.90" (** "[...] should be a string comprised of
three non-negative, period-separated integers [...]" *)
-let vo_magic = 8891
-let state_magic = 58891
+let vo_magic = 8991
+let state_magic = 58991
let distributed_exec =
["coqtop.opt"; "coqidetop.opt"; "coqqueryworker.opt"; "coqproofworker.opt"; "coqtacticworker.opt";
"coqc";"coqchk";"coqdoc";"coqworkmgr";"coq_makefile";"coq-tex";"coqwc";"csdpcert";"coqdep"]
@@ -242,6 +242,7 @@ type ide = Opt | Byte | No
type preferences = {
prefix : string option;
local : bool;
+ interactive : bool;
vmbyteflags : string option;
custom : bool option;
bindir : string option;
@@ -279,6 +280,7 @@ module Profiles = struct
let default = {
prefix = None;
local = false;
+ interactive = true;
vmbyteflags = None;
custom = None;
bindir = None;
@@ -331,6 +333,11 @@ end
let prefs = ref Profiles.default
+(* Support don't ask *)
+let cprintf x =
+ if !prefs.interactive
+ then cprintf x
+ else Printf.ifprintf stdout x
let get_bool = function
| "true" | "yes" | "y" | "all" -> true
@@ -366,6 +373,8 @@ let args_options = Arg.align [
"<dir> Set installation directory to <dir>";
"-local", arg_set (fun p local -> { p with local }),
" Set installation directory to the current source tree";
+ "-no-ask", arg_clear (fun p interactive -> { p with interactive }),
+ " Don't ask questions / print variables during configure [questions will be filled with defaults]";
"-vmbyteflags", arg_string_option (fun p vmbyteflags -> { p with vmbyteflags }),
"<flags> Comma-separated link flags for the VM of coqtop.byte";
"-custom", arg_set_option (fun p custom -> { p with custom }),
@@ -649,9 +658,8 @@ let camltag = match caml_version_list with
50: unexpected documentation comment: too common and annoying to avoid
56: unreachable match case: the [_ -> .] syntax doesn't exist in 4.02.3
58: "no cmx file was found in path": See https://github.com/ocaml/num/issues/9
- 59: "potential assignment to a non-mutable value": See Coq's issue #8043
*)
-let coq_warnings = "-w +a-4-9-27-41-42-44-45-48-50-58-59"
+let coq_warnings = "-w +a-4-9-27-41-42-44-45-48-50-58"
let coq_warn_error =
if !prefs.warn_error
then "-warn-error +a"
@@ -1038,7 +1046,18 @@ let find_suffix prefix path = match prefix with
let do_one_instdir (var,msg,uservalue,selfcontainedlayout,unixlayout,locallayout) =
let dir,suffix =
if !prefs.local then (use_suffix coqtop locallayout,locallayout)
- else match uservalue, !prefs.prefix with
+ else
+ let env_prefix =
+ match !prefs.prefix with
+ | None ->
+ begin
+ try Some (Sys.getenv "COQ_CONFIGURE_PREFIX")
+ with
+ | Not_found when !prefs.interactive -> None
+ | Not_found -> Some "_build/install/default"
+ end
+ | p -> p
+ in match uservalue, env_prefix with
| Some d, p -> d,find_suffix p d
| _, Some p ->
let suffix = if arch_is_win32 then selfcontainedlayout else relativize unixlayout in
@@ -1136,8 +1155,8 @@ let print_summary () =
pr "*Warning* To compile the system for a new architecture\n";
pr " don't forget to do a 'make clean' before './configure'.\n"
-let _ = print_summary ()
-
+let _ =
+ if !prefs.interactive then print_summary ()
(** * Build the dev/ocamldebug-coq file *)
@@ -1214,8 +1233,8 @@ let write_configml f =
pr_s "browser" browser;
pr_s "wwwcoq" !prefs.coqwebsite;
pr_s "wwwbugtracker" (!prefs.coqwebsite ^ "bugs/");
- pr_s "wwwrefman" (!prefs.coqwebsite ^ "distrib/" ^ coq_version ^ "/refman/");
- pr_s "wwwstdlib" (!prefs.coqwebsite ^ "distrib/" ^ coq_version ^ "/stdlib/");
+ pr_s "wwwrefman" (!prefs.coqwebsite ^ "distrib/V" ^ coq_version ^ "/refman/");
+ pr_s "wwwstdlib" (!prefs.coqwebsite ^ "distrib/V" ^ coq_version ^ "/stdlib/");
pr_s "localwwwrefman" ("file:/" ^ docdir ^ "/html/refman");
pr_b "bytecode_compiler" !prefs.bytecodecompiler;
pr_b "native_compiler" !prefs.nativecompiler;
@@ -1231,7 +1250,10 @@ let write_configml f =
pr "\nlet core_src_dirs = [\n%s]\n" core_src_dirs;
pr "\nlet plugins_dirs = [\n";
- let plugins = Sys.readdir "plugins" in
+ let plugins =
+ try Sys.readdir "plugins"
+ with _ -> [||]
+ in
Array.sort compare plugins;
Array.iter
(fun f ->
diff --git a/coq.opam b/coq.opam
new file mode 100644
index 0000000000..cd89057598
--- /dev/null
+++ b/coq.opam
@@ -0,0 +1,26 @@
+opam-version: "1.2"
+maintainer: "The Coq development team <coqdev@inria.fr>"
+authors: "The Coq development team, INRIA, CNRS, and contributors."
+homepage: "https://coq.inria.fr/"
+bug-reports: "https://github.com/coq/coq/issues"
+dev-repo: "https://github.com/coq/coq.git"
+license: "LGPL-2.1"
+
+available: [ ocaml-version >= "4.02.3" ]
+
+depends: [
+ "dune" { build }
+ "ocamlfind" { build }
+ "num"
+ "camlp5"
+]
+
+build-env: [
+ [ COQ_CONFIGURE_PREFIX = "%{prefix}" ]
+]
+
+build: [
+ [ "dune" "build" "@vodeps" ]
+ [ "dune" "exec" "coq_dune" "_build/default/.vfiles.d" ]
+ [ "dune" "build" "-p" name "-j" jobs ]
+]
diff --git a/coqpp/coqpp_ast.mli b/coqpp/coqpp_ast.mli
index 39b4d2ab34..956a916792 100644
--- a/coqpp/coqpp_ast.mli
+++ b/coqpp/coqpp_ast.mli
@@ -11,7 +11,7 @@ type loc = {
loc_end : Lexing.position;
}
-type code = { code : string }
+type code = { code : string; loc : loc; }
type user_symbol =
| Ulist1 of user_symbol
@@ -81,6 +81,7 @@ type grammar_ext = {
type tactic_ext = {
tacext_name : string;
tacext_level : int option;
+ tacext_deprecated : code option;
tacext_rules : tactic_rule list;
}
diff --git a/coqpp/coqpp_lex.mll b/coqpp/coqpp_lex.mll
index 6c6562c204..81a53e887b 100644
--- a/coqpp/coqpp_lex.mll
+++ b/coqpp/coqpp_lex.mll
@@ -29,6 +29,7 @@ let newline lexbuf =
let num_comments = ref 0
let num_braces = ref 0
+let ocaml_start_pos = ref Lexing.dummy_pos
let mode () = if !num_braces = 0 then Extend else OCaml
@@ -57,10 +58,10 @@ let end_comment lexbuf =
else
None
-let start_ocaml _ =
+let start_ocaml lexbuf =
let () = match mode () with
| OCaml -> Buffer.add_string ocaml_buf "{"
- | Extend -> ()
+ | Extend -> ocaml_start_pos := lexeme_start_p lexbuf
in
incr num_braces
@@ -70,7 +71,11 @@ let end_ocaml lexbuf =
else if !num_braces = 0 then
let s = Buffer.contents ocaml_buf in
let () = Buffer.reset ocaml_buf in
- Some (CODE { Coqpp_ast.code = s })
+ let loc = {
+ Coqpp_ast.loc_start = !ocaml_start_pos;
+ Coqpp_ast.loc_end = lexeme_end_p lexbuf
+ } in
+ Some (CODE { Coqpp_ast.code = s; loc })
else
let () = Buffer.add_string ocaml_buf "}" in
None
@@ -87,7 +92,7 @@ let number = [ '0'-'9' ]
rule extend = parse
| "(*" { start_comment (); comment lexbuf }
-| "{" { start_ocaml (); ocaml lexbuf }
+| "{" { start_ocaml lexbuf; ocaml lexbuf }
| "GRAMMAR" { GRAMMAR }
| "VERNAC" { VERNAC }
| "TACTIC" { TACTIC }
@@ -95,6 +100,7 @@ rule extend = parse
| "END" { END }
| "DECLARE" { DECLARE }
| "PLUGIN" { PLUGIN }
+| "DEPRECATED" { DEPRECATED }
(** Camlp5 specific keywords *)
| "GLOBAL" { GLOBAL }
| "FIRST" { FIRST }
@@ -126,7 +132,7 @@ rule extend = parse
| eof { EOF }
and ocaml = parse
-| "{" { start_ocaml (); ocaml lexbuf }
+| "{" { start_ocaml lexbuf; ocaml lexbuf }
| "}" { match end_ocaml lexbuf with Some tk -> tk | None -> ocaml lexbuf }
| '\n' { newline lexbuf; Buffer.add_char ocaml_buf '\n'; ocaml lexbuf }
| '\"' { Buffer.add_char ocaml_buf '\"'; ocaml_string lexbuf }
diff --git a/coqpp/coqpp_main.ml b/coqpp/coqpp_main.ml
index fd425ef4ff..d9fff46d88 100644
--- a/coqpp/coqpp_main.ml
+++ b/coqpp/coqpp_main.ml
@@ -21,6 +21,13 @@ let pr_loc loc =
let epos = loc.loc_end.pos_cnum - loc.loc_start.pos_bol in
Printf.sprintf "File \"%s\", line %d, characters %d-%d:" file line bpos epos
+let print_code fmt c =
+ let loc = c.loc.loc_start in
+ (** Print the line location as a source annotation *)
+ let padding = String.make (loc.pos_cnum - loc.pos_bol + 1) ' ' in
+ let code_insert = asprintf "\n# %i \"%s\"\n%s%s" loc.pos_lnum loc.pos_fname padding c.code in
+ fprintf fmt "@[@<0>%s@]@\n" code_insert
+
let parse_file f =
let chan = open_in f in
let lexbuf = Lexing.from_channel chan in
@@ -181,8 +188,7 @@ let print_fun fmt (vars, body) =
in
let () = fprintf fmt "fun@ " in
let () = List.iter iter vars in
- (** FIXME: use Coq locations in the macros *)
- let () = fprintf fmt "loc ->@ @[%s@]" body.code in
+ let () = fprintf fmt "loc ->@ @[%a@]" print_code body in
()
(** Meta-program instead of calling Tok.of_pattern here because otherwise
@@ -304,8 +310,8 @@ let rec print_binders fmt = function
fprintf fmt "%s@ %a" id print_binders rem
let print_rule fmt r =
- fprintf fmt "@[TyML (%a, @[fun %a -> %s@])@]"
- print_clause r.tac_toks print_binders r.tac_toks r.tac_body.code
+ fprintf fmt "@[TyML (%a, @[fun %a -> %a@])@]"
+ print_clause r.tac_toks print_binders r.tac_toks print_code r.tac_body
let rec print_rules fmt = function
| [] -> ()
@@ -316,10 +322,17 @@ let print_rules fmt rules =
fprintf fmt "Tacentries.([@[<v>%a@]])" print_rules rules
let print_ast fmt ext =
+ let deprecation fmt =
+ function
+ | None -> ()
+ | Some { code } -> fprintf fmt "~deprecation:(%s) " code
+ in
let pr fmt () =
let level = match ext.tacext_level with None -> 0 | Some i -> i in
- fprintf fmt "Tacentries.tactic_extend %s \"%s\" ~level:%i %a"
- plugin_name ext.tacext_name level print_rules ext.tacext_rules
+ fprintf fmt "Tacentries.tactic_extend %s \"%s\" ~level:%i %a%a"
+ plugin_name ext.tacext_name level
+ deprecation ext.tacext_deprecated
+ print_rules ext.tacext_rules
in
let () = fprintf fmt "let () = @[%a@]\n" pr () in
()
@@ -331,7 +344,7 @@ let declare_plugin fmt name =
fprintf fmt "let _ = Mltop.add_known_module %s@\n" plugin_name
let pr_ast fmt = function
-| Code s -> fprintf fmt "%s@\n" s.code
+| Code s -> fprintf fmt "%a@\n" print_code s
| Comment s -> fprintf fmt "%s@\n" s
| DeclarePlugin name -> declare_plugin fmt name
| GramExt gram -> fprintf fmt "%a@\n" GramExt.print_ast gram
diff --git a/coqpp/coqpp_parse.mly b/coqpp/coqpp_parse.mly
index baafd633c4..bf435fd247 100644
--- a/coqpp/coqpp_parse.mly
+++ b/coqpp/coqpp_parse.mly
@@ -62,7 +62,7 @@ let parse_user_entry s sep =
%token <string> IDENT QUALID
%token <string> STRING
%token <int> INT
-%token VERNAC TACTIC GRAMMAR EXTEND END DECLARE PLUGIN
+%token VERNAC TACTIC GRAMMAR EXTEND END DECLARE PLUGIN DEPRECATED
%token LBRACKET RBRACKET PIPE ARROW COMMA EQUAL
%token LPAREN RPAREN COLON SEMICOLON
%token GLOBAL FIRST LAST BEFORE AFTER LEVEL LEFTA RIGHTA NONA
@@ -108,8 +108,13 @@ vernac_extend:
;
tactic_extend:
-| TACTIC EXTEND IDENT tactic_level tactic_rules END
- { TacticExt { tacext_name = $3; tacext_level = $4; tacext_rules = $5 } }
+| TACTIC EXTEND IDENT tactic_deprecated tactic_level tactic_rules END
+ { TacticExt { tacext_name = $3; tacext_deprecated = $4; tacext_level = $5; tacext_rules = $6 } }
+;
+
+tactic_deprecated:
+| { None }
+| DEPRECATED CODE { Some $2 }
;
tactic_level:
diff --git a/coqpp/dune b/coqpp/dune
new file mode 100644
index 0000000000..24b9b9184b
--- /dev/null
+++ b/coqpp/dune
@@ -0,0 +1,8 @@
+(ocamllex coqpp_lex)
+(ocamlyacc coqpp_parse)
+
+(executable
+ (name coqpp_main)
+ (public_name coqpp)
+ (modules coqpp_ast coqpp_lex coqpp_parse coqpp_main)
+ (modules_without_implementation coqpp_ast))
diff --git a/default.nix b/default.nix
index d9317bccaf..1faaafae03 100644
--- a/default.nix
+++ b/default.nix
@@ -23,8 +23,8 @@
{ pkgs ?
(import (fetchTarball {
- url = "https://github.com/NixOS/nixpkgs/archive/060a98e9f4ad879492e48d63e887b0b6db26299e.tar.gz";
- sha256 = "1lzvp3md0hf6kp2bvc6dbzh40navlyd51qlns9wbkz6lqk3lgf6j";
+ url = "https://github.com/NixOS/nixpkgs/archive/4c95508641fe780efe41885366e03339b95d04fb.tar.gz";
+ sha256 = "1wjspwhzdb6d1kz4khd9l0fivxdk2nq3qvj93pql235sb7909ygx";
}) {})
, ocamlPackages ? pkgs.ocaml-ng.ocamlPackages_4_06
, buildIde ? true
@@ -45,6 +45,7 @@ stdenv.mkDerivation rec {
buildInputs = [
hostname
python2 time # coq-makefile timing tools
+ dune
]
++ (with ocamlPackages; [ ocaml findlib camlp5_strict num ])
++ optional buildIde ocamlPackages.lablgtk
@@ -54,6 +55,7 @@ stdenv.mkDerivation rec {
(ps: [ ps.sphinx ps.sphinx_rtd_theme ps.pexpect ps.beautifulsoup4
ps.antlr4-python3-runtime ps.sphinxcontrib-bibtex ]))
antlr4
+ ocamlPackages.odoc
]
++ optionals doInstallCheck (
# Test-suite dependencies
@@ -62,8 +64,8 @@ stdenv.mkDerivation rec {
++ [ ocamlPackages.ounit rsync which ]
)
++ optionals shell (
- [ jq curl git gnupg ] # Dependencies of the merging script
- ++ (with ocamlPackages; [ merlin ocp-indent ocp-index ]) # Dev tools
+ [ jq curl gitFull gnupg ] # Dependencies of the merging script
+ ++ (with ocamlPackages; [ merlin ocp-indent ocp-index utop ]) # Dev tools
);
src =
@@ -71,7 +73,7 @@ stdenv.mkDerivation rec {
else
with builtins; filterSource
(path: _:
- !elem (baseNameOf path) [".git" "result" "bin" "_build_ci"]) ./.;
+ !elem (baseNameOf path) [".git" "result" "bin" "_build" "_build_ci"]) ./.;
prefixKey = "-prefix ";
diff --git a/dev/build/windows/MakeCoq_MinGW.bat b/dev/build/windows/MakeCoq_MinGW.bat
index 5af0fcff3a..61cf6bc4cc 100755
--- a/dev/build/windows/MakeCoq_MinGW.bat
+++ b/dev/build/windows/MakeCoq_MinGW.bat
@@ -247,7 +247,7 @@ IF "%~0" == "-addon" (
IF NOT "%~0" == "" (
ECHO Install cygwin and download, compile and install OCaml and Coq for MinGW
ECHO !!! Illegal parameter %~0
- ECHO Usage:
+ ECHO Usage:
ECHO MakeCoq_MinGW
CALL :PrintPars
GOTO :EOF
@@ -267,7 +267,6 @@ IF "%INSTALLMODE%" == "mingwincygwin" (
IF "%MAKEINSTALLER%" == "Y" (
SET INSTALLMODE=relocatable
- SET INSTALLOCAML=Y
)
REM ========== CONFIRM PARAMETERS ==========
@@ -275,7 +274,7 @@ REM ========== CONFIRM PARAMETERS ==========
CALL :PrintPars
REM Note: DOS batch replaces variables on parsing, so one can't use a variable just set in an () block
IF "%COQREGTESTING%"=="Y" (GOTO DontAsk)
- SET /p ANSWER=Is this correct? y/n
+ SET /p ANSWER="Is this correct? y/n "
IF NOT "%ANSWER%"=="y" (GOTO :EOF)
:DontAsk
@@ -315,12 +314,13 @@ ECHO RESULT INSTALL DIR (MINGW) = %RESULT_INSTALLDIR_MFMT%
ECHO RESULT INSTALL DIR (CYGWIN) = %RESULT_INSTALLDIR_CFMT%
REM WARNING: Add a space after the = in case you want set this to empty, otherwise the variable will be unset
-SET MAKE_OPT=-j %MAKE_THREADS%
+SET MAKE_OPT=-j %MAKE_THREADS%
REM ========== DERIVED CYGWIN SETUP OPTIONS ==========
-REM WARNING: Add a space after the = otherwise the variable will be unset
-SET CYGWIN_OPT=
+REM One can't set a variable to empty in DOS, but you can set it to a space this way.
+REM The quotes are just there to make the space visible and to protect from "remove trailing spaces".
+SET "CYGWIN_OPT= "
IF "%CYGWIN_FROM_CACHE%" == "Y" (
SET CYGWIN_OPT= %CYGWIN_OPT% -L
@@ -334,8 +334,6 @@ IF "%GTK_FROM_SOURCES%"=="N" (
SET CYGWIN_OPT= %CYGWIN_OPT% -P mingw64-%ARCH%-gtk2.0,mingw64-%ARCH%-gtksourceview2.0
)
-ECHO ========== INSTALL CYGWIN ==========
-
REM Cygwin setup sets proper ACLs (permissions) for folders it CREATES.
REM Otherwise chmod won't work and e.g. the ocaml build will fail.
REM Cygwin setup does not touch the ACLs of existing folders.
@@ -349,7 +347,10 @@ IF EXIST "%CYGWIN_INSTALLDIR_WFMT%\etc\setup\installed.db" (
IF NOT "%CYGWIN_QUIET%" == "Y" (
SET RUNSETUP=Y
)
+
IF "%COQREGTESTING%" == "Y" (
+ ECHO "========== REMOVE EXISTING CYGWIN =========="
+ DEL /S /F /Q "%CYGWIN_INSTALLDIR_WFMT%" > NUL
SET RUNSETUP=Y
)
@@ -359,6 +360,8 @@ IF NOT "%APPVEYOR%" == "True" (
SET EXTRAPACKAGES=-P wget,curl,git,gcc-core,gcc-g++,automake1.5
)
+ECHO "========== INSTALL CYGWIN =========="
+
IF "%RUNSETUP%"=="Y" (
%SETUP% ^
--proxy "%PROXY%" ^
@@ -436,10 +439,10 @@ ECHO ========== BATCH FUNCTIONS ==========
ECHO -proxy ^<internet proxy^>
ECHO -cygrepo ^<cygwin download repository^>
ECHO -cygcache ^<local cygwin repository/cache^>
- ECHO -cyglocal ^<Y or N^> install cygwin from cache
+ ECHO -cyglocal ^<Y or N^> install cygwin from cache
ECHO -cygquiet ^<Y or N^> install cygwin without user interaction
ECHO -srccache ^<local source code repository/cache^>
- ECHO -coqver ^<Coq version to install^>
+ ECHO -coqver ^<Coq version to install^>
ECHO -gtksrc ^<Y or N^> build GTK ^(90 min^) or use cygwin version
ECHO -threads ^<1..N^> Number of make threads
ECHO -addon ^<name^> Enable building selected addon (can be repeated)
@@ -452,9 +455,9 @@ ECHO ========== BATCH FUNCTIONS ==========
ECHO -ocaml = %INSTALLOCAML%
ECHO -installer= %MAKEINSTALLER%
ECHO -make = %INSTALLMAKE%
- ECHO -destcyg = %DESTCYG%
- ECHO -destcoq = %DESTCOQ%
- ECHO -setup = %SETUP%
+ ECHO -destcyg = %DESTCYG%
+ ECHO -destcoq = %DESTCOQ%
+ ECHO -setup = %SETUP%
ECHO -proxy = %PROXY%
ECHO -cygrepo = %CYGWIN_REPOSITORY%
ECHO -cygcache = %CYGWIN_LOCAL_CACHE_WFMT%
diff --git a/dev/build/windows/makecoq_mingw.sh b/dev/build/windows/makecoq_mingw.sh
index aee4dd74d8..23eb6fbc63 100644..100755
--- a/dev/build/windows/makecoq_mingw.sh
+++ b/dev/build/windows/makecoq_mingw.sh
@@ -18,6 +18,8 @@
set -o nounset
set -o errexit
set -x
+# Print current wall time as part of the xtrace
+export PS4='+\t '
# Set this to 1 if all module directories shall be removed before build (no incremental make)
RMDIR_BEFORE_BUILD=1
@@ -119,7 +121,11 @@ mkdir -p "$PREFIXCOQ/bin"
mkdir -p "$PREFIXOCAML/bin"
# This is required for building addons and plugins
+# This must be CFMT (/cygdrive/c/...) otherwise coquelicot 3.0.2 configure fails.
+# coquelicot uses which ${COQBIN}/coqc to check if coqc exists. This does not work with COQBIN in MFMT.
export COQBIN=$RESULT_INSTALLDIR_CFMT/bin/
+# This must be MFMT (C:/) otherwise bignums 68a7a3d7e0b21985913a6c3ee12067f4c5ac4e20 fails
+export COQLIB=$RESULT_INSTALLDIR_MFMT/lib/coq/
###################### Copy Cygwin Setup Info #####################
@@ -145,27 +151,64 @@ LOGS=$(pwd)/buildlogs
# The current log target (first part of the log file name)
LOGTARGET=other
-# Log command output - take log target name from command name (like log1 make => log target is "<module>-make")
-log1() {
- "$@" > >(tee "$LOGS/$LOGTARGET-$1.log" | sed -e "s/^/$LOGTARGET-$1.log: /") 2> >(tee "$LOGS/$LOGTARGET-$1.err" | sed -e "s/^/$LOGTARGET-$1.err: /" 1>&2)
-}
-
-# Log command output - take log target name from command name and first argument (like log2 make install => log target is "<module>-make-install")
-log2() {
- "$@" > >(tee "$LOGS/$LOGTARGET-$1-$2.log" | sed -e "s/^/$LOGTARGET-$1-$2.log: /") 2> >(tee "$LOGS/$LOGTARGET-$1-$2.err" | sed -e "s/^/$LOGTARGET-$1-$2.err: /" 1>&2)
-}
-
-# Log command output - take log target name from command name and second argument (like log_1_3 ocaml setup.ml -configure => log target is "<module>-ocaml--configure")
-log_1_3() {
- "$@" > >(tee "$LOGS/$LOGTARGET-$1-$3.log" | sed -e "s/^/$LOGTARGET-$1-$3.log: /") 2> >(tee "$LOGS/$LOGTARGET-$1-$3.err" | sed -e "s/^/$LOGTARGET-$1-$3.err: /" 1>&2)
-}
-
-# Log command output - log target name is first argument (like logn untar tar xvaf ... => log target is "<module>-untar")
-logn() {
- LOGTARGETEX=$1
- shift
- "$@" > >(tee "$LOGS/$LOGTARGET-$LOGTARGETEX.log" | sed -e "s/^/$LOGTARGET-$LOGTARGETEX.log: /") 2> >(tee "$LOGS/$LOGTARGET-$LOGTARGETEX.err" | sed -e "s/^/$LOGTARGET-$LOGTARGETEX.err: /" 1>&2)
-}
+# For an explanation of ${COQREGTESTING:-N} search for ${parameter:-word} in
+# http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
+
+if [ "${COQREGTESTING:-N}" == "Y" ] ; then
+ # If COQREGTESTING, log to log files only
+ # Log command output - take log target name from command name (like log1 make => log target is "<module>-make")
+ log1() {
+ { local -; set +x; } 2> /dev/null
+ "$@" >"$LOGS/$LOGTARGET-$1.log" 2>"$LOGS/$LOGTARGET-$1.err"
+ }
+
+ # Log command output - take log target name from command name and first argument (like log2 make install => log target is "<module>-make-install")
+ log2() {
+ { local -; set +x; } 2> /dev/null
+ "$@" >"$LOGS/$LOGTARGET-$1-$2.log" 2>"$LOGS/$LOGTARGET-$1-$2.err"
+ }
+
+ # Log command output - take log target name from command name and second argument (like log_1_3 ocaml setup.ml -configure => log target is "<module>-ocaml--configure")
+ log_1_3() {
+ { local -; set +x; } 2> /dev/null
+ "$@" >"$LOGS/$LOGTARGET-$1-$3.log" 2>"$LOGS/$LOGTARGET-$1-$3.err"
+ }
+
+ # Log command output - log target name is first argument (like logn untar tar xvaf ... => log target is "<module>-untar")
+ logn() {
+ { local -; set +x; } 2> /dev/null
+ LOGTARGETEX=$1
+ shift
+ "$@" >"$LOGS/$LOGTARGET-$LOGTARGETEX.log" 2>"$LOGS/$LOGTARGET-$LOGTARGETEX.err"
+ }
+else
+ # If COQREGTESTING, log to log files and console
+ # Log command output - take log target name from command name (like log1 make => log target is "<module>-make")
+ log1() {
+ { local -; set +x; } 2> /dev/null
+ "$@" > >(tee "$LOGS/$LOGTARGET-$1.log" | sed -e "s/^/$LOGTARGET-$1.log: /") 2> >(tee "$LOGS/$LOGTARGET-$1.err" | sed -e "s/^/$LOGTARGET-$1.err: /" 1>&2)
+ }
+
+ # Log command output - take log target name from command name and first argument (like log2 make install => log target is "<module>-make-install")
+ log2() {
+ { local -; set +x; } 2> /dev/null
+ "$@" > >(tee "$LOGS/$LOGTARGET-$1-$2.log" | sed -e "s/^/$LOGTARGET-$1-$2.log: /") 2> >(tee "$LOGS/$LOGTARGET-$1-$2.err" | sed -e "s/^/$LOGTARGET-$1-$2.err: /" 1>&2)
+ }
+
+ # Log command output - take log target name from command name and second argument (like log_1_3 ocaml setup.ml -configure => log target is "<module>-ocaml--configure")
+ log_1_3() {
+ { local -; set +x; } 2> /dev/null
+ "$@" > >(tee "$LOGS/$LOGTARGET-$1-$3.log" | sed -e "s/^/$LOGTARGET-$1-$3.log: /") 2> >(tee "$LOGS/$LOGTARGET-$1-$3.err" | sed -e "s/^/$LOGTARGET-$1-$3.err: /" 1>&2)
+ }
+
+ # Log command output - log target name is first argument (like logn untar tar xvaf ... => log target is "<module>-untar")
+ logn() {
+ { local -; set +x; } 2> /dev/null
+ LOGTARGETEX=$1
+ shift
+ "$@" > >(tee "$LOGS/$LOGTARGET-$LOGTARGETEX.log" | sed -e "s/^/$LOGTARGET-$LOGTARGETEX.log: /") 2> >(tee "$LOGS/$LOGTARGET-$LOGTARGETEX.err" | sed -e "s/^/$LOGTARGET-$LOGTARGETEX.err: /" 1>&2)
+ }
+fi
###################### 'UNFIX' SED #####################
@@ -229,7 +272,7 @@ function get_expand_source_tar {
if [ -f "$SOURCE_LOCAL_CACHE_CFMT/$name.$3" ] ; then
cp "$SOURCE_LOCAL_CACHE_CFMT/$name.$3" "$TARBALLS"
else
- wget "$1/$2.$3"
+ wget --progress=dot:giga "$1/$2.$3"
if file -i "$2.$3" | grep text/html; then
echo Download failed: "$1/$2.$3"
echo The file wget downloaded is an html file:
@@ -260,8 +303,8 @@ function get_expand_source_tar {
if [ "$3" == "zip" ] ; then
log1 unzip "$TARBALLS/$name.$3"
if [ "$strip" == "1" ] ; then
- # Ok, this is dirty, but it works and it fails if there are name clashes
- mv -- */* .
+ # move subfolders of root folders one level up
+ find "$(ls)" -mindepth 1 -maxdepth 1 -exec mv -- "{}" . \;
else
echo "Unzip strip count not supported"
return 1
@@ -314,13 +357,13 @@ function build_prep {
fi
# Check if build is already done
- if [ ! -f "flagfiles/$name.finished" ] ; then
+ if [ ! -f "$FLAGFILES/$name.finished" ] ; then
BUILD_PACKAGE_NAME=$name
BUILD_OLDPATH=$PATH
BUILD_OLDPWD=$(pwd)
LOGTARGET=$name
- touch "flagfiles/$name.started"
+ touch "$FLAGFILES/$name.started"
get_expand_source_tar "$1" "$2" "$3" "$strip" "$name"
@@ -344,9 +387,9 @@ function build_prep {
# ------------------------------------------------------------------------------
function build_post {
- if [ ! -f "flagfiles/$BUILD_PACKAGE_NAME.finished" ]; then
+ if [ ! -f "$FLAGFILES/$BUILD_PACKAGE_NAME.finished" ]; then
cd "$BUILD_OLDPWD"
- touch "flagfiles/$BUILD_PACKAGE_NAME.finished"
+ touch "$FLAGFILES/$BUILD_PACKAGE_NAME.finished"
PATH=$BUILD_OLDPATH
LOGTARGET=other
fi
@@ -384,19 +427,17 @@ function build_conf_make_inst {
# Install all files given by a glob pattern to a given folder
#
# parameters
-# $1 glob pattern (in '')
-# $2 target folder
+# $1 source path
+# $2 pattern (in '')
+# $3 target folder
# ------------------------------------------------------------------------------
function install_glob {
- # Check if any files matching the pattern exist
- if [ "$(echo $1)" != "$1" ] ; then
- # shellcheck disable=SC2086
- install -D -t $2 $1
- fi
+ SRCDIR=$(realpath -m $1)
+ DESTDIR=$(realpath -m $3)
+ ( cd "$SRCDIR" && find . -maxdepth 1 -type f -name "$2" -exec install -D -T "$SRCDIR"/{} "$DESTDIR"/{} \; )
}
-
# ------------------------------------------------------------------------------
# Recursively Install all files given by a glob pattern to a given folder
#
@@ -407,12 +448,15 @@ function install_glob {
# ------------------------------------------------------------------------------
function install_rec {
- ( cd "$1" && find . -type f -name "$2" -exec install -D -T "$1"/{} "$3"/{} \; )
+ SRCDIR=$(realpath -m $1)
+ DESTDIR=$(realpath -m $3)
+ ( cd "$SRCDIR" && find . -type f -name "$2" -exec install -D -T "$SRCDIR"/{} "$DESTDIR"/{} \; )
}
# ------------------------------------------------------------------------------
# Write a file list of the target folder
# The file lists are used to create file lists for the windows installer
+# Don't overwrite an existing file list
#
# parameters
# $1 name of file list
@@ -425,6 +469,19 @@ function list_files {
}
# ------------------------------------------------------------------------------
+# Write a file list of the target folder
+# The file lists are used to create file lists for the windows installer
+# Do overwrite an existing file list
+#
+# parameters
+# $1 name of file list
+# ------------------------------------------------------------------------------
+
+function list_files_always {
+ ( cd "$PREFIXCOQ" && find . -type f | sort > /build/filelists/"$1" )
+}
+
+# ------------------------------------------------------------------------------
# Compute the set difference of two file lists
#
# parameters
@@ -777,15 +834,15 @@ function make_flex_dll_link {
# For this purpose hard links are better.
function make_ln {
- if [ ! -f flagfiles/myln.finished ] ; then
- touch flagfiles/myln.started
+ if [ ! -f $FLAGFILES/myln.finished ] ; then
+ touch $FLAGFILES/myln.started
mkdir -p myln
( cd myln
cp $PATCHES/ln.c .
"$TARGET_ARCH-gcc" -DUNICODE -D_UNICODE -DIGNORE_SYMBOLIC -mconsole -o ln.exe ln.c
install -D ln.exe "$PREFIXCOQ/bin/ln.exe"
)
- touch flagfiles/myln.finished
+ touch $FLAGFILES/myln.finished
fi
}
@@ -793,7 +850,7 @@ function make_ln {
function make_ocaml {
get_flex_dll_link_bin
- if build_prep https://github.com/ocaml/ocaml/archive/4.07.0 ocaml-4.07.0 tar.gz 1 ; then
+ if build_prep https://github.com/ocaml/ocaml/archive 4.07.0 tar.gz 1 ocaml-4.07.0 ; then
# See README.win32.adoc
cp config/m-nt.h byterun/caml/m.h
cp config/s-nt.h byterun/caml/s.h
@@ -848,7 +905,6 @@ function make_ocaml {
function make_ocaml_tools {
make_findlib
- # make_menhir
make_camlp5
}
@@ -865,7 +921,7 @@ function make_ocaml_libs {
function make_num {
make_ocaml
# We need this commit due to windows fixed, IMHO this is better than patching v1.1.
- if build_prep https://github.com/ocaml/num/archive/ 7dd5e935aaa2b902585b3b2d0e55ad9b2442fff0 zip 1 num-1.1-7d; then
+ if build_prep https://github.com/ocaml/num/archive 7dd5e935aaa2b902585b3b2d0e55ad9b2442fff0 zip 1 num-1.1-7d; then
log2 make all
# log2 make test
log2 make install
@@ -874,17 +930,34 @@ function make_num {
fi
}
+##### OCAMLBUILD #####
+
+function make_ocamlbuild {
+ make_ocaml
+ if build_prep https://github.com/ocaml/ocamlbuild/archive 0.12.0 tar.gz 1 ocamlbuild-0.12.0; then
+ log2 make configure OCAML_NATIVE=true OCAMLBUILD_PREFIX=$PREFIXOCAML OCAMLBUILD_BINDIR=$PREFIXOCAML/bin OCAMLBUILD_LIBDIR=$PREFIXOCAML/lib
+ log1 make
+ log2 make install
+ build_post
+ fi
+}
+
##### FINDLIB Ocaml library manager #####
function make_findlib {
make_ocaml
- if build_prep https://opam.ocaml.org/archives ocamlfind.1.8.0+opam tar.gz 1 ; then
+ make_ocamlbuild
+ if build_prep https://opam.ocaml.org/1.2.2/archives ocamlfind.1.8.0+opam tar.gz 1 ; then
logn configure ./configure -bindir "$PREFIXOCAML\\bin" -sitelib "$PREFIXOCAML\\libocaml\\site-lib" -config "$PREFIXOCAML\\etc\\findlib.conf"
# Note: findlib doesn't support -j 8, so don't pass MAKE_OPT
log2 make all
log2 make opt
log2 make install
log2 make clean
+ # Add Coq install library path to ocamlfind config file
+ # $(ocamlfind printconf conf | tr -d '\r') is the name of the config file
+ # printf "%q" "$PREFIXCOQ/lib" | sed -e 's/\\/\\\\/g' is the coq lib path double escaped for sed
+ sed -i -e 's|path="\(.*\)"|path="\1;'$(printf "%q" "$PREFIXCOQ/lib" | sed -e 's/\\/\\\\/g')'"|' $(ocamlfind printconf conf | tr -d '\r')
build_post
fi
}
@@ -894,15 +967,11 @@ function make_findlib {
function make_menhir {
make_ocaml
make_findlib
- # if build_prep http://gallium.inria.fr/~fpottier/menhir menhir-20151112 tar.gz 1 ; then
- # For Ocaml 4.02
- # if build_prep http://gallium.inria.fr/~fpottier/menhir menhir-20151012 tar.gz 1 ; then
- # For Ocaml 4.01
- if build_prep http://gallium.inria.fr/~fpottier/menhir menhir-20140422 tar.gz 1 ; then
+ make_ocamlbuild
+ if build_prep http://gallium.inria.fr/~fpottier/menhir menhir-20180530 tar.gz 1 ; then
# Note: menhir doesn't support -j 8, so don't pass MAKE_OPT
log2 make all PREFIX="$PREFIXOCAML"
log2 make install PREFIX="$PREFIXOCAML"
- mv "$PREFIXOCAML/bin/menhir" "$PREFIXOCAML/bin/menhir.exe"
build_post
fi
}
@@ -1085,13 +1154,13 @@ function copy_coq_dlls {
function copy_coq_objects {
# copy objects only from folders which exist in the target lib directory
find . -type d | while read -r FOLDER ; do
- if [ -e "$PREFIXCOQ/lib/$FOLDER" ] ; then
- install_glob "$FOLDER"/'*.cmxa' "$PREFIXCOQ/lib/$FOLDER"
- install_glob "$FOLDER"/'*.cmi' "$PREFIXCOQ/lib/$FOLDER"
- install_glob "$FOLDER"/'*.cma' "$PREFIXCOQ/lib/$FOLDER"
- install_glob "$FOLDER"/'*.cmo' "$PREFIXCOQ/lib/$FOLDER"
- install_glob "$FOLDER"/'*.a' "$PREFIXCOQ/lib/$FOLDER"
- install_glob "$FOLDER"/'*.o' "$PREFIXCOQ/lib/$FOLDER"
+ if [ -e "$PREFIXCOQ/lib/coq/$FOLDER" ] ; then
+ install_glob "$FOLDER" '*.cmxa' "$PREFIXCOQ/lib/coq/$FOLDER"
+ install_glob "$FOLDER" '*.cmi' "$PREFIXCOQ/lib/coq/$FOLDER"
+ install_glob "$FOLDER" '*.cma' "$PREFIXCOQ/lib/coq/$FOLDER"
+ install_glob "$FOLDER" '*.cmo' "$PREFIXCOQ/lib/coq/$FOLDER"
+ install_glob "$FOLDER" '*.a' "$PREFIXCOQ/lib/coq/$FOLDER"
+ install_glob "$FOLDER" '*.o' "$PREFIXCOQ/lib/coq/$FOLDER"
fi
done
}
@@ -1103,10 +1172,10 @@ function copq_coq_gtk {
echo 'gtk-fallback-icon-theme = "Tango"' >> "$PREFIX/etc/gtk-2.0/gtkrc"
if [ "$INSTALLMODE" == "absolute" ] || [ "$INSTALLMODE" == "relocatable" ]; then
- install_glob "$PREFIX/etc/gtk-2.0/"'*' "$PREFIXCOQ/gtk-2.0"
- install_glob "$PREFIX/share/gtksourceview-2.0/language-specs/"'*' "$PREFIXCOQ/share/gtksourceview-2.0/language-specs"
- install_glob "$PREFIX/share/gtksourceview-2.0/styles/"'*' "$PREFIXCOQ/share/gtksourceview-2.0/styles"
- install_rec "$PREFIX/share/themes/" '*' "$PREFIXCOQ/share/themes"
+ install_glob "$PREFIX/etc/gtk-2.0" '*' "$PREFIXCOQ/gtk-2.0"
+ install_glob "$PREFIX/share/gtksourceview-2.0/language-specs" '*' "$PREFIXCOQ/share/gtksourceview-2.0/language-specs"
+ install_glob "$PREFIX/share/gtksourceview-2.0/styles" '*' "$PREFIXCOQ/share/gtksourceview-2.0/styles"
+ install_rec "$PREFIX/share/themes" '*' "$PREFIXCOQ/share/themes"
# This below item look like a bug in make install
if [ -d "$PREFIXCOQ/share/coq/" ] ; then
@@ -1136,7 +1205,7 @@ function copy_coq_license {
install -D README.md "$PREFIXCOQ/license_readme/coq/ReadMe.md"
install -D CHANGES "$PREFIXCOQ/license_readme/coq/Changes.txt"
install -D INSTALL "$PREFIXCOQ/license_readme/coq/Install.txt"
- install -D doc/README.md "$PREFIXCOQ/license_readme/coq/ReadMeDoc.md"
+ install -D doc/README.md "$PREFIXCOQ/license_readme/coq/ReadMeDoc.md" || true
fi
}
@@ -1175,11 +1244,11 @@ function make_coq {
then
if [ "$INSTALLMODE" == "relocatable" ]; then
# HACK: for relocatable builds, first configure with ./, then build but before install reconfigure with the real target path
- ./configure -with-doc no -prefix ./ -libdir ./lib -mandir ./man
+ logn configure ./configure -with-doc no -prefix ./ -libdir ./lib/coq -mandir ./man
elif [ "$INSTALLMODE" == "absolute" ]; then
- ./configure -with-doc no -prefix "$PREFIXCOQ" -libdir "$PREFIXCOQ/lib" -mandir "$PREFIXCOQ/man"
+ logn configure ./configure -with-doc no -prefix "$PREFIXCOQ" -libdir "$PREFIXCOQ/lib/coq" -mandir "$PREFIXCOQ/man"
else
- ./configure -with-doc no -prefix "$PREFIXCOQ"
+ logn configure ./configure -with-doc no -prefix "$PREFIXCOQ"
fi
# The windows resource compiler binary name is hard coded
@@ -1191,21 +1260,21 @@ function make_coq {
log1 make
else
# shellcheck disable=SC2086
- make $MAKE_OPT
+ log1 make $MAKE_OPT
fi
if [ "$INSTALLMODE" == "relocatable" ]; then
- ./configure -with-doc no -prefix "$PREFIXCOQ" -libdir "$PREFIXCOQ/lib" -mandir "$PREFIXCOQ/man"
+ logn reconfigure ./configure -with-doc no -prefix "$PREFIXCOQ" -libdir "$PREFIXCOQ/lib/coq" -mandir "$PREFIXCOQ/man"
fi
- make install
- copy_coq_dlls
+ log2 make install
+ log1 copy_coq_dlls
if [ "$INSTALLOCAML" == "Y" ]; then
copy_coq_objects
fi
- copq_coq_gtk
- copy_coq_license
+ log1 copq_coq_gtk
+ log1 copy_coq_license
# make clean seems to be broken for 8.5pl2
# 1.) find | xargs fails on cygwin, can be fixed by sed -i 's|\| xargs rm -f|-exec rm -fv \{\} \+|' Makefile
@@ -1213,8 +1282,8 @@ function make_coq {
# make clean
# Copy these files somewhere the plugin builds can find them
- cp dev/ci/ci-basic-overlay.sh /build/
- cp -r dev/ci/user-overlays /build/
+ logn copy-basic-overlays cp dev/ci/ci-basic-overlay.sh /build/
+ logn copy-user-overlays cp -r dev/ci/user-overlays /build/
build_post
fi
@@ -1283,8 +1352,8 @@ function make_gcc {
##### Get sources for Cygwin MinGW packages #####
function get_cygwin_mingw_sources {
- if [ ! -f flagfiles/cygwin_mingw_sources.finished ] ; then
- touch flagfiles/cygwin_mingw_sources.started
+ if [ ! -f $FLAGFILES/cygwin_mingw_sources.finished ] ; then
+ touch $FLAGFILES/cygwin_mingw_sources.started
# Find all installed files with mingw in the name and download the corresponding source code file from cygwin
# Steps:
@@ -1311,7 +1380,7 @@ function get_cygwin_mingw_sources {
if [ -f "$SOURCE_LOCAL_CACHE_CFMT/$SOURCEFILE" ] ; then
cp "$SOURCE_LOCAL_CACHE_CFMT/$SOURCEFILE" $TARBALLS
else
- wget "$CYGWIN_REPOSITORY/$SOURCE"
+ wget --progress=dot:giga "$CYGWIN_REPOSITORY/$SOURCE"
mv "$SOURCEFILE" "$TARBALLS"
# Save the source archive in the source cache
if [ -d "$SOURCE_LOCAL_CACHE_CFMT" ] ; then
@@ -1322,7 +1391,7 @@ function get_cygwin_mingw_sources {
done
- touch flagfiles/cygwin_mingw_sources.finished
+ touch $FLAGFILES/cygwin_mingw_sources.finished
fi
}
@@ -1344,7 +1413,7 @@ function make_coq_installer {
filter_files coq_objects coq '\.(cmxa|cmi|cma|cmo|a|o)$'
# Filter out plugin object files
- filter_files coq_objects_plugins coq_objects '/lib/plugins/.*\.(cmxa|cmi|cma|cmo|a|o)$'
+ filter_files coq_objects_plugins coq_objects '/lib/coq/plugins/.*\.(cmxa|cmi|cma|cmo|a|o)$'
# Coq objects objects required for plugin development = coq objects except those for pre installed plugins
diff_files coq_plugindev coq_objects coq_objects_plugins
@@ -1387,12 +1456,12 @@ function make_coq_installer {
# Provides BigN, BigZ, BigQ that used to be part of Coq standard library
function make_addon_bignums {
- bignums_SHA=$(git ls-remote "$bignums_CI_GITURL" "refs/heads/$bignums_CI_BRANCH" | cut -f 1)
+ bignums_SHA=$(git ls-remote "$bignums_CI_GITURL" "refs/heads/$bignums_CI_REF" | cut -f 1)
if [[ "$bignums_SHA" == "" ]]; then
- # $bignums_CI_BRANCH must have been a tag and not a branch
- bignums_SHA="$bignums_CI_BRANCH"
+ # $bignums_CI_REF must have been a tag / commit and not a branch
+ bignums_SHA="$bignums_CI_REF"
fi
- if build_prep "${bignums_CI_GITURL}/archive" "$bignums_SHA" zip 1 "bignums-$bignums_SHA"; then
+ if build_prep "$bignums_CI_ARCHIVEURL" "$bignums_SHA" zip 1 "bignums-$bignums_SHA"; then
# To make command lines shorter :-(
echo 'COQ_SRC_SUBDIRS:=$(filter-out plugins/%,$(COQ_SRC_SUBDIRS)) plugins/syntax' >> Makefile.coq.local
log1 make all
@@ -1405,12 +1474,12 @@ function make_addon_bignums {
# A new (experimental) tactic language
function make_addon_ltac2 {
- ltac2_SHA=$(git ls-remote "$ltac2_CI_GITURL" "refs/heads/$ltac2_CI_BRANCH" | cut -f 1)
+ ltac2_SHA=$(git ls-remote "$ltac2_CI_GITURL" "refs/heads/$ltac2_CI_REF" | cut -f 1)
if [[ "$ltac2_SHA" == "" ]]; then
- # $ltac2_CI_BRANCH must have been a tag and not a branch
- ltac2_SHA="$ltac2_CI_BRANCH"
+ # $ltac2_CI_REF must have been a tag / commit and not a branch
+ ltac2_SHA="$ltac2_CI_REF"
fi
- if build_prep "${ltac2_CI_GITURL}/archive" "$ltac2_SHA" zip 1 "ltac2-$ltac2_SHA"; then
+ if build_prep "$ltac2_CI_ARCHIVEURL" "$ltac2_SHA" zip 1 "ltac2-$ltac2_SHA"; then
log1 make all
log2 make install
build_post
@@ -1421,12 +1490,12 @@ function make_addon_ltac2 {
# A function definition plugin
function make_addon_equations {
- Equations_SHA=$(git ls-remote "$Equations_CI_GITURL" "refs/heads/$Equations_CI_BRANCH" | cut -f 1)
+ Equations_SHA=$(git ls-remote "$Equations_CI_GITURL" "refs/heads/$Equations_CI_REF" | cut -f 1)
if [[ "$Equations_SHA" == "" ]]; then
- # $Equations_CI_BRANCH must have been a tag and not a branch
- Equations_SHA="$Equations_CI_BRANCH"
+ # $Equations_CI_REF must have been a tag / commit and not a branch
+ Equations_SHA="$Equations_CI_REF"
fi
- if build_prep "${Equations_CI_GITURL}/archive" "$Equations_SHA" zip 1 "Equations-$Equations_SHA"; then
+ if build_prep "$Equations_CI_ARCHIVEURL" "$Equations_SHA" zip 1 "Equations-$Equations_SHA"; then
# Note: PATH is autmatically saved/restored by build_prep / build_post
PATH=$COQBIN:$PATH
logn coq_makefile ${COQBIN}coq_makefile -f _CoqProject -o Makefile
@@ -1448,10 +1517,10 @@ function make_addons {
export CI_BRANCH=""
export CI_PULL_REQUEST=""
fi
- . /build/ci-basic-overlay.sh
for overlay in /build/user-overlays/*.sh; do
. "$overlay"
done
+ . /build/ci-basic-overlay.sh
for addon in $COQ_ADDONS; do
"make_addon_$addon"
@@ -1460,6 +1529,8 @@ function make_addons {
###################### TOP LEVEL BUILD #####################
+ocamlfind list || true
+
make_sed
make_ocaml
make_ocaml_tools
@@ -1477,7 +1548,7 @@ list_files ocaml_coq
make_addons
-list_files ocaml_coq_addons
+list_files_always ocaml_coq_addons
if [ "$MAKEINSTALLER" == "Y" ] ; then
make_coq_installer
diff --git a/dev/ci/README.md b/dev/ci/README.md
index 43d680af61..3a179a9431 100644
--- a/dev/ci/README.md
+++ b/dev/ci/README.md
@@ -136,15 +136,41 @@ rebuilding Coq. In one job, Coq is built with `./configure -prefix _install_ci`
and `make install` is run, then the `_install_ci` directory
persists to and is used by the next jobs.
-Artifacts can also be downloaded from the GitLab repository.
-Currently, available artifacts are:
-- the Coq executables and stdlib, in three copies varying in
- architecture and OCaml version used to build Coq.
-- the Coq documentation, built only in the `build:base` job. When submitting
- a documentation PR, this can help reviewers checking the rendered result.
+### Artifacts
-As an exception to the above, jobs testing that compilation triggers
-no OCaml warnings build Coq in parallel with other tests.
+Build artifacts from GitLab can be linked / downloaded in a systematic
+way, see [GitLab's documentation](https://docs.gitlab.com/ce/user/project/pipelines/job_artifacts.html#downloading-the-latest-job-artifacts)
+for more information. For example, to access the documentation of the
+`master` branch, you can do:
+
+https://gitlab.com/coq/coq/-/jobs/artifacts/master/file/_install_ci/share/doc/coq/sphinx/html/index.html?job=doc:refman
+
+Browsing artifacts is also possible:
+https://gitlab.com/coq/coq/-/jobs/artifacts/master/browse/_install_ci/?job=build:base
+
+Above, you can replace `master` and `job` by the desired GitLab branch and job name.
+
+Currently available artifacts are:
+
+- the Coq executables and stdlib, in four copies varying in
+ architecture and OCaml version used to build Coq:
+ https://gitlab.com/coq/coq/-/jobs/artifacts/master/browse/_install_ci/?job=build:base
+
+ Additionally, an experimental Dune build is provided:
+ https://gitlab.com/coq/coq/-/jobs/artifacts/master/browse/_build/?job=build:edge:dune:dev
+
+- the Coq documentation, built in the `doc:*` jobs. When submitting
+ a documentation PR, this can help reviewers checking the rendered result:
+
+ + Coq's Reference Manual [master branch]
+ https://gitlab.com/coq/coq/-/jobs/artifacts/master/file/_install_ci/share/doc/coq/sphinx/html/index.html?job=doc:refman
+ + Coq's Standard Library Documentation [master branch]
+ https://gitlab.com/coq/coq/-/jobs/artifacts/master/file/_install_ci/share/doc/coq/html/stdlib/index.html?job=doc:refman
+ + Coq's ML API Documentation [master branch]
+ https://gitlab.com/coq/coq/-/jobs/artifacts/master/file/dev/ocamldoc/html/index.html?job=doc:ml-api:ocamldoc
+
+ The dune job also provides its own API documentation using the newer `odoc` tool:
+ https://gitlab.com/coq/coq/-/jobs/artifacts/master/file/_build/default/_doc/_html/index.html?job=doc:ml-api:odoc
### GitLab and Windows
@@ -171,6 +197,6 @@ but if you wish to save more time you can skip the job by setting
This means you will need to change its value when the Docker image
needs to be updated. You can do so for a single pipeline by starting
-it through the web interface..
+it through the web interface.
See also [`docker/README.md`](docker/README.md).
diff --git a/dev/ci/ci-basic-overlay.sh b/dev/ci/ci-basic-overlay.sh
index 28321d13e2..8620b01b26 100755
--- a/dev/ci/ci-basic-overlay.sh
+++ b/dev/ci/ci-basic-overlay.sh
@@ -9,124 +9,147 @@
########################################################################
# MathComp
########################################################################
-: "${mathcomp_CI_BRANCH:=master}"
+: "${mathcomp_CI_REF:=master}"
: "${mathcomp_CI_GITURL:=https://github.com/math-comp/math-comp}"
-: "${oddorder_CI_BRANCH:=master}"
+: "${mathcomp_CI_ARCHIVEURL:=${mathcomp_CI_GITURL}/archive}"
+
+: "${oddorder_CI_REF:=master}"
: "${oddorder_CI_GITURL:=https://github.com/math-comp/odd-order}"
+: "${oddorder_CI_ARCHIVEURL:=${oddorder_CI_GITURL}/archive}"
########################################################################
# UniMath
########################################################################
-: "${UniMath_CI_BRANCH:=master}"
+: "${UniMath_CI_REF:=master}"
: "${UniMath_CI_GITURL:=https://github.com/UniMath/UniMath}"
+: "${UniMath_CI_ARCHIVEURL:=${UniMath_CI_GITURL}/archive}"
########################################################################
# Unicoq + Mtac2
########################################################################
-: "${unicoq_CI_BRANCH:=master}"
+: "${unicoq_CI_REF:=master}"
: "${unicoq_CI_GITURL:=https://github.com/unicoq/unicoq}"
+: "${unicoq_CI_ARCHIVEURL:=${unicoq_CI_GITURL}/archive}"
-: "${mtac2_CI_BRANCH:=master-sync}"
+: "${mtac2_CI_REF:=master-sync}"
: "${mtac2_CI_GITURL:=https://github.com/Mtac2/Mtac2}"
+: "${mtac2_CI_ARCHIVEURL:=${mtac2_CI_GITURL}/archive}"
########################################################################
# Mathclasses + Corn
########################################################################
-: "${math_classes_CI_BRANCH:=master}"
-: "${math_classes_CI_GITURL:=https://github.com/math-classes/math-classes}"
+: "${math_classes_CI_REF:=master}"
+: "${math_classes_CI_GITURL:=https://github.com/coq-community/math-classes}"
+: "${math_classes_CI_ARCHIVEURL:=${math_classes_CI_GITURL}/archive}"
-: "${Corn_CI_BRANCH:=master}"
-: "${Corn_CI_GITURL:=https://github.com/c-corn/corn}"
+: "${Corn_CI_REF:=master}"
+: "${Corn_CI_GITURL:=https://github.com/coq-community/corn}"
+: "${Corn_CI_ARCHIVEURL:=${Corn_CI_GITURL}/archive}"
########################################################################
# Iris
########################################################################
-: "${stdpp_CI_BRANCH:=master}"
+: "${stdpp_CI_REF:=master}"
: "${stdpp_CI_GITURL:=https://gitlab.mpi-sws.org/robbertkrebbers/coq-stdpp}"
+: "${stdpp_CI_ARCHIVEURL:=${stdpp_CI_GITURL}/-/archive}"
-: "${Iris_CI_BRANCH:=master}"
+: "${Iris_CI_REF:=master}"
: "${Iris_CI_GITURL:=https://gitlab.mpi-sws.org/FP/iris-coq}"
+: "${Iris_CI_ARCHIVEURL:=${Iris_CI_GITURL}/-/archive}"
-: "${lambdaRust_CI_BRANCH:=master}"
+: "${lambdaRust_CI_REF:=master}"
: "${lambdaRust_CI_GITURL:=https://gitlab.mpi-sws.org/FP/LambdaRust-coq}"
+: "${lambdaRust_CI_ARCHIVEURL:=${lambdaRust_CI_GITURL}/-/archive}"
########################################################################
# HoTT
########################################################################
-: "${HoTT_CI_BRANCH:=master}"
+: "${HoTT_CI_REF:=master}"
: "${HoTT_CI_GITURL:=https://github.com/HoTT/HoTT}"
+: "${HoTT_CI_ARCHIVEURL:=${HoTT_CI_GITURL}/archive}"
########################################################################
# Ltac2
########################################################################
-: "${ltac2_CI_BRANCH:=master}"
+: "${ltac2_CI_REF:=master}"
: "${ltac2_CI_GITURL:=https://github.com/ppedrot/ltac2}"
+: "${ltac2_CI_ARCHIVEURL:=${ltac2_CI_GITURL}/archive}"
########################################################################
# GeoCoq
########################################################################
-: "${GeoCoq_CI_BRANCH:=master}"
+: "${GeoCoq_CI_REF:=master}"
: "${GeoCoq_CI_GITURL:=https://github.com/GeoCoq/GeoCoq}"
+: "${GeoCoq_CI_ARCHIVEURL:=${GeoCoq_CI_GITURL}/archive}"
########################################################################
# Flocq
########################################################################
-: "${Flocq_CI_BRANCH:=master}"
+: "${Flocq_CI_REF:=master}"
: "${Flocq_CI_GITURL:=https://gitlab.inria.fr/flocq/flocq}"
+: "${Flocq_CI_ARCHIVEURL:=${Flocq_CI_GITURL}/-/archive}"
########################################################################
# Coquelicot
########################################################################
-: "${Coquelicot_CI_BRANCH:=master}"
+: "${Coquelicot_CI_REF:=master}"
: "${Coquelicot_CI_GITURL:=https://scm.gforge.inria.fr/anonscm/git/coquelicot/coquelicot}"
########################################################################
# CompCert
########################################################################
-: "${CompCert_CI_BRANCH:=master}"
+: "${CompCert_CI_REF:=master}"
: "${CompCert_CI_GITURL:=https://github.com/AbsInt/CompCert}"
+: "${CompCert_CI_ARCHIVEURL:=${CompCert_CI_GITURL}/archive}"
########################################################################
# VST
########################################################################
-: "${VST_CI_BRANCH:=master}"
+: "${VST_CI_REF:=master}"
: "${VST_CI_GITURL:=https://github.com/PrincetonUniversity/VST}"
+: "${VST_CI_ARCHIVEURL:=${VST_CI_GITURL}/archive}"
########################################################################
# cross-crypto
########################################################################
-: "${cross_crypto_CI_BRANCH:=master}"
+: "${cross_crypto_CI_REF:=master}"
: "${cross_crypto_CI_GITURL:=https://github.com/mit-plv/cross-crypto}"
+: "${cross_crypto_CI_ARCHIVEURL:=${cross_crypto_CI_GITURL}/archive}"
########################################################################
# fiat_parsers
########################################################################
-: "${fiat_parsers_CI_BRANCH:=master}"
+: "${fiat_parsers_CI_REF:=master}"
: "${fiat_parsers_CI_GITURL:=https://github.com/mit-plv/fiat}"
+: "${fiat_parsers_CI_ARCHIVEURL:=${fiat_parsers_CI_GITURL}/archive}"
########################################################################
# fiat_crypto
########################################################################
-: "${fiat_crypto_CI_BRANCH:=master}"
+: "${fiat_crypto_CI_REF:=master}"
: "${fiat_crypto_CI_GITURL:=https://github.com/mit-plv/fiat-crypto}"
+: "${fiat_crypto_CI_ARCHIVEURL:=${fiat_crypto_CI_GITURL}/archive}"
########################################################################
# formal-topology
########################################################################
-: "${formal_topology_CI_BRANCH:=ci}"
+: "${formal_topology_CI_REF:=ci}"
: "${formal_topology_CI_GITURL:=https://github.com/bmsherman/topology}"
+: "${formal_topology_CI_ARCHIVEURL:=${formal_topology_CI_GITURL}/archive}"
########################################################################
# coq-dpdgraph
########################################################################
-: "${coq_dpdgraph_CI_BRANCH:=coq-master}"
+: "${coq_dpdgraph_CI_REF:=coq-master}"
: "${coq_dpdgraph_CI_GITURL:=https://github.com/Karmaki/coq-dpdgraph}"
+: "${coq_dpdgraph_CI_ARCHIVEURL:=${coq_dpdgraph_CI_GITURL}/archive}"
########################################################################
# CoLoR
########################################################################
-: "${CoLoR_CI_BRANCH:=master}"
+: "${CoLoR_CI_REF:=master}"
: "${CoLoR_CI_GITURL:=https://github.com/fblanqui/color}"
+: "${CoLoR_CI_ARCHIVEURL:=${CoLoR_CI_GITURL}/archive}"
########################################################################
# SF
@@ -138,53 +161,75 @@
########################################################################
# TLC
########################################################################
-: "${tlc_CI_BRANCH:=master}"
+: "${tlc_CI_REF:=master}"
: "${tlc_CI_GITURL:=https://gforge.inria.fr/git/tlc/tlc}"
########################################################################
# Bignums
########################################################################
-: "${bignums_CI_BRANCH:=master}"
+: "${bignums_CI_REF:=master}"
: "${bignums_CI_GITURL:=https://github.com/coq/bignums}"
+: "${bignums_CI_ARCHIVEURL:=${bignums_CI_GITURL}/archive}"
########################################################################
# bedrock2
########################################################################
-: "${bedrock2_CI_BRANCH:=master}"
+: "${bedrock2_CI_REF:=master}"
: "${bedrock2_CI_GITURL:=https://github.com/mit-plv/bedrock2}"
+: "${bedrock2_CI_ARCHIVEURL:=${bedrock2_CI_GITURL}/archive}"
########################################################################
# Equations
########################################################################
-: "${Equations_CI_BRANCH:=master}"
+: "${Equations_CI_REF:=master}"
: "${Equations_CI_GITURL:=https://github.com/mattam82/Coq-Equations}"
+: "${Equations_CI_ARCHIVEURL:=${Equations_CI_GITURL}/archive}"
########################################################################
# Elpi
########################################################################
-: "${Elpi_CI_BRANCH:=coq-master}"
+: "${Elpi_CI_REF:=coq-master}"
: "${Elpi_CI_GITURL:=https://github.com/LPCIC/coq-elpi}"
+: "${Elpi_CI_ARCHIVEURL:=${Elpi_CI_GITURL}/archive}"
########################################################################
# fcsl-pcm
########################################################################
-: "${fcsl_pcm_CI_BRANCH:=master}"
+: "${fcsl_pcm_CI_REF:=master}"
: "${fcsl_pcm_CI_GITURL:=https://github.com/imdea-software/fcsl-pcm}"
+: "${fcsl_pcm_CI_ARCHIVEURL:=${fcsl_pcm_CI_GITURL}/archive}"
########################################################################
# pidetop
########################################################################
-: "${pidetop_CI_BRANCH:=v8.9}"
+: "${pidetop_CI_REF:=v8.9}"
: "${pidetop_CI_GITURL:=https://bitbucket.org/coqpide/pidetop}"
+: "${pidetop_CI_ARCHIVEURL:=${pidetop_CI_GITURL}/get}"
########################################################################
# ext-lib
########################################################################
-: "${ext_lib_CI_BRANCH:=master}"
+: "${ext_lib_CI_REF:=master}"
: "${ext_lib_CI_GITURL:=https://github.com/coq-ext-lib/coq-ext-lib}"
+: "${ext_lib_CI_ARCHIVEURL:=${ext_lib_CI_GITURL}/archive}"
+
+########################################################################
+# simple-io
+########################################################################
+: "${simple_io_CI_REF:=master}"
+: "${simple_io_CI_GITURL:=https://github.com/Lysxia/coq-simple-io}"
+: "${simple_io_CI_ARCHIVEURL:=${simple_io_CI_GITURL}/archive}"
########################################################################
# quickchick
########################################################################
-: "${quickchick_CI_BRANCH:=master}"
+: "${quickchick_CI_REF:=master}"
: "${quickchick_CI_GITURL:=https://github.com/QuickChick/QuickChick}"
+: "${quickchick_CI_ARCHIVEURL:=${quickchick_CI_GITURL}/archive}"
+
+########################################################################
+# quickchick
+########################################################################
+: "${plugin_tutorial_CI_REF:=master}"
+: "${plugin_tutorial_CI_GITURL:=https://github.com/ybertot/plugin_tutorials}"
+: "${plugin_tutorial_CI_ARCHIVEURL:=${plugin_tutorial_CI_GITURL}/archive}"
diff --git a/dev/ci/ci-bedrock2.sh b/dev/ci/ci-bedrock2.sh
index 447076e092..5205946261 100755
--- a/dev/ci/ci-bedrock2.sh
+++ b/dev/ci/ci-bedrock2.sh
@@ -3,9 +3,7 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-bedrock2_CI_DIR="${CI_BUILD_DIR}/bedrock2"
+FORCE_GIT=1
+git_download bedrock2
-git_checkout "${bedrock2_CI_BRANCH}" "${bedrock2_CI_GITURL}" "${bedrock2_CI_DIR}"
-( cd "${bedrock2_CI_DIR}" && git submodule update --init --recursive )
-
-( cd "${bedrock2_CI_DIR}" && make )
+( cd "${CI_BUILD_DIR}/bedrock2" && git submodule update --init --recursive && make )
diff --git a/dev/ci/ci-bignums.sh b/dev/ci/ci-bignums.sh
index 0082919679..756f54dfbd 100755
--- a/dev/ci/ci-bignums.sh
+++ b/dev/ci/ci-bignums.sh
@@ -1,16 +1,8 @@
#!/usr/bin/env bash
ci_dir="$(dirname "$0")"
+. "${ci_dir}/ci-common.sh"
-# This script could be included inside other ones
-# Let's avoid to source ci-common twice in this case
-if [ -z "${CI_BUILD_DIR}" ];
-then
- . "${ci_dir}/ci-common.sh"
-fi
+git_download bignums
-bignums_CI_DIR="${CI_BUILD_DIR}/Bignums"
-
-git_checkout "${bignums_CI_BRANCH}" "${bignums_CI_GITURL}" "${bignums_CI_DIR}"
-
-( cd "${bignums_CI_DIR}" && make && make install)
+( cd "${CI_BUILD_DIR}/bignums" && make && make install)
diff --git a/dev/ci/ci-color.sh b/dev/ci/ci-color.sh
index 8ce5f2418f..dc696f69d9 100755
--- a/dev/ci/ci-color.sh
+++ b/dev/ci/ci-color.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-CoLoR_CI_DIR=${CI_BUILD_DIR}/color
+git_download CoLoR
-# Compile CoLoR
-git_checkout "${CoLoR_CI_BRANCH}" "${CoLoR_CI_GITURL}" "${CoLoR_CI_DIR}"
-( cd "${CoLoR_CI_DIR}" && make )
+( cd "${CI_BUILD_DIR}/CoLoR" && make )
diff --git a/dev/ci/ci-common.sh b/dev/ci/ci-common.sh
index 9259a6e0c8..4acc0e86cf 100644
--- a/dev/ci/ci-common.sh
+++ b/dev/ci/ci-common.sh
@@ -8,6 +8,7 @@ export NJOBS
if [ -n "${GITLAB_CI}" ];
then
+ # Gitlab build, Coq installed into `_install_ci`
export OCAMLPATH="$PWD/_install_ci/lib:$OCAMLPATH"
export COQBIN="$PWD/_install_ci/bin"
export CI_BRANCH="$CI_COMMIT_REF_NAME"
@@ -15,18 +16,29 @@ then
then
export CI_PULL_REQUEST="${CI_BRANCH#pr-}"
fi
+elif [ -n "${TRAVIS}" ];
+then
+ # Travis build, `-local` passed to `configure`
+ export OCAMLPATH="$PWD:$OCAMLPATH"
+ export COQBIN="$PWD/bin"
+ export CI_PULL_REQUEST="$TRAVIS_PULL_REQUEST"
+ export CI_BRANCH="$TRAVIS_BRANCH"
+elif [ -d "$PWD/_build/install/default/" ];
+then
+ # Dune build
+ export OCAMLPATH="$PWD/_build/install/default/lib/"
+ export COQBIN="$PWD/_build/install/default/bin"
+ export COQLIB="$PWD/_build/install/default/lib/coq"
+ CI_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
+ export CI_BRANCH
else
- if [ -n "${TRAVIS}" ];
- then
- export CI_PULL_REQUEST="$TRAVIS_PULL_REQUEST"
- export CI_BRANCH="$TRAVIS_BRANCH"
- else # assume local
- CI_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
- export CI_BRANCH
- fi
+ # We assume we are in `-profile devel` build, thus `-local` is set
export OCAMLPATH="$PWD:$OCAMLPATH"
export COQBIN="$PWD/bin"
+ CI_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
+ export CI_BRANCH
fi
+
export PATH="$COQBIN:$PATH"
# Coq's tools need an ending slash :S, we should fix them.
@@ -34,39 +46,48 @@ export COQBIN="$COQBIN/"
ls "$COQBIN"
-# Where we clone and build external developments
+# Where we download and build external developments
CI_BUILD_DIR="$PWD/_build_ci"
-# shellcheck source=ci-basic-overlay.sh
-. "${ci_dir}/ci-basic-overlay.sh"
for overlay in "${ci_dir}"/user-overlays/*.sh; do
# shellcheck source=/dev/null
. "${overlay}"
done
+# shellcheck source=ci-basic-overlay.sh
+. "${ci_dir}/ci-basic-overlay.sh"
-mathcomp_CI_DIR="${CI_BUILD_DIR}/math-comp"
-
-# git_checkout branch url dest will create a git repository
-# in <dest> (if it does not exist already) and checkout the
-# remote branch <branch> from <url>
-git_checkout()
+# [git_download project] will download [project] and unpack it
+# in [$CI_BUILD_DIR/project] if the folder does not exist already;
+# if it does, it will do nothing except print a warning (this can be
+# useful when building locally).
+# Note: when $FORCE_GIT is set to 1 or when $CI is unset or empty
+# (local build), it uses git clone to perform the download.
+git_download()
{
- local _BRANCH=${1}
- local _URL=${2}
- local _DEST=${3}
-
- # Allow an optional 4th argument for the commit
- local _COMMIT=${4:-FETCH_HEAD}
- local _DEPTH=()
- if [ -z "${4}" ]; then _DEPTH=(--depth 1); fi
-
- mkdir -p "${_DEST}"
- ( cd "${_DEST}" && \
- if [ ! -d .git ] ; then git clone "${_DEPTH[@]}" "${_URL}" . ; fi && \
- echo "Checking out ${_DEST}" && \
- git fetch "${_URL}" "${_BRANCH}" && \
- git -c advice.detachedHead=false checkout "${_COMMIT}" && \
- echo "${_DEST}: $(git log -1 --format='%s | %H | %cd | %aN')" )
+ local PROJECT=$1
+ local DEST="$CI_BUILD_DIR/$PROJECT"
+
+ if [ -d "$DEST" ]; then
+ echo "Warning: download and unpacking of $PROJECT skipped because $DEST already exists."
+ elif [ "$FORCE_GIT" = "1" ] || [ "$CI" = "" ]; then
+ local GITURL_VAR="${PROJECT}_CI_GITURL"
+ local GITURL="${!GITURL_VAR}"
+ local REF_VAR="${PROJECT}_CI_REF"
+ local REF="${!REF_VAR}"
+ git clone "$GITURL" "$DEST"
+ cd "$DEST"
+ git checkout "$REF"
+ else # When possible, we download tarballs to reduce bandwidth and latency
+ local ARCHIVEURL_VAR="${PROJECT}_CI_ARCHIVEURL"
+ local ARCHIVEURL="${!ARCHIVEURL_VAR}"
+ local REF_VAR="${PROJECT}_CI_REF"
+ local REF="${!REF_VAR}"
+ mkdir -p "$DEST"
+ cd "$DEST"
+ wget "$ARCHIVEURL/$REF.tar.gz"
+ tar xvfz "$REF.tar.gz" --strip-components=1
+ rm -f "$REF.tar.gz"
+ fi
}
make()
@@ -84,31 +105,27 @@ make()
# this installs just the ssreflect library of math-comp
install_ssreflect()
{
- echo 'Installing ssreflect' && echo -en 'travis_fold:start:ssr.install\\r'
+ echo 'Installing ssreflect'
- git_checkout "${mathcomp_CI_BRANCH}" "${mathcomp_CI_GITURL}" "${mathcomp_CI_DIR}"
+ git_download mathcomp
- ( cd "${mathcomp_CI_DIR}/mathcomp" && \
+ ( cd "${CI_BUILD_DIR}/mathcomp/mathcomp" && \
make Makefile.coq && \
make -f Makefile.coq ssreflect/all_ssreflect.vo && \
make -f Makefile.coq install )
- echo -en 'travis_fold:end:ssr.install\\r'
-
}
# this installs just the ssreflect + algebra library of math-comp
install_ssralg()
{
- echo 'Installing ssralg' && echo -en 'travis_fold:start:ssralg.install\\r'
+ echo 'Installing ssralg'
- git_checkout "${mathcomp_CI_BRANCH}" "${mathcomp_CI_GITURL}" "${mathcomp_CI_DIR}"
+ git_download mathcomp
- ( cd "${mathcomp_CI_DIR}/mathcomp" && \
+ ( cd "${CI_BUILD_DIR}/mathcomp/mathcomp" && \
make Makefile.coq && \
make -f Makefile.coq algebra/all_algebra.vo && \
make -f Makefile.coq install )
- echo -en 'travis_fold:end:ssralg.install\\r'
-
}
diff --git a/dev/ci/ci-compcert.sh b/dev/ci/ci-compcert.sh
index 8d490591b6..01c35ceb4a 100755
--- a/dev/ci/ci-compcert.sh
+++ b/dev/ci/ci-compcert.sh
@@ -3,8 +3,7 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-CompCert_CI_DIR="${CI_BUILD_DIR}/CompCert"
+git_download CompCert
-git_checkout "${CompCert_CI_BRANCH}" "${CompCert_CI_GITURL}" "${CompCert_CI_DIR}"
-
-( cd "${CompCert_CI_DIR}" && ./configure -ignore-coq-version x86_32-linux && make && make check-proof )
+( cd "${CI_BUILD_DIR}/CompCert" && \
+ ./configure -ignore-coq-version x86_32-linux && make && make check-proof )
diff --git a/dev/ci/ci-coq-dpdgraph.sh b/dev/ci/ci-coq-dpdgraph.sh
index 5d57fce1c7..2373ea6c62 100755
--- a/dev/ci/ci-coq-dpdgraph.sh
+++ b/dev/ci/ci-coq-dpdgraph.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-coq_dpdgraph_CI_DIR="${CI_BUILD_DIR}/coq-dpdgraph"
+git_download coq_dpdgraph
-git_checkout "${coq_dpdgraph_CI_BRANCH}" "${coq_dpdgraph_CI_GITURL}" "${coq_dpdgraph_CI_DIR}"
-
-( cd "${coq_dpdgraph_CI_DIR}" && autoconf && ./configure && make && make test-suite )
+( cd "${CI_BUILD_DIR}/coq_dpdgraph" && autoconf && ./configure && make && make test-suite )
diff --git a/dev/ci/ci-coquelicot.sh b/dev/ci/ci-coquelicot.sh
index d86d61ef6a..5d8817491d 100755
--- a/dev/ci/ci-coquelicot.sh
+++ b/dev/ci/ci-coquelicot.sh
@@ -3,10 +3,9 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-Coquelicot_CI_DIR="${CI_BUILD_DIR}/coquelicot"
-
install_ssreflect
-git_checkout "${Coquelicot_CI_BRANCH}" "${Coquelicot_CI_GITURL}" "${Coquelicot_CI_DIR}"
+FORCE_GIT=1
+git_download Coquelicot
-( cd "${Coquelicot_CI_DIR}" && ./autogen.sh && ./configure && ./remake "-j${NJOBS}" )
+( cd "${CI_BUILD_DIR}/Coquelicot" && ./autogen.sh && ./configure && ./remake "-j${NJOBS}" )
diff --git a/dev/ci/ci-corn.sh b/dev/ci/ci-corn.sh
index 9298fc70af..7d5d70cf90 100755
--- a/dev/ci/ci-corn.sh
+++ b/dev/ci/ci-corn.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-Corn_CI_DIR="${CI_BUILD_DIR}/corn"
+git_download Corn
-git_checkout "${Corn_CI_BRANCH}" "${Corn_CI_GITURL}" "${Corn_CI_DIR}"
-
-( cd "${Corn_CI_DIR}" && make && make install )
+( cd "${CI_BUILD_DIR}/Corn" && make && make install )
diff --git a/dev/ci/ci-cross-crypto.sh b/dev/ci/ci-cross-crypto.sh
index a0d3aa6551..900d12c1dd 100755
--- a/dev/ci/ci-cross-crypto.sh
+++ b/dev/ci/ci-cross-crypto.sh
@@ -3,9 +3,7 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-cross_crypto_CI_DIR="${CI_BUILD_DIR}/cross-crypto"
+FORCE_GIT=1
+git_download cross_crypto
-git_checkout "${cross_crypto_CI_BRANCH}" "${cross_crypto_CI_GITURL}" "${cross_crypto_CI_DIR}"
-( cd "${cross_crypto_CI_DIR}" && git submodule update --init --recursive )
-
-( cd "${cross_crypto_CI_DIR}" && make )
+( cd "${CI_BUILD_DIR}/cross_crypto" && git submodule update --init --recursive && make )
diff --git a/dev/ci/ci-elpi.sh b/dev/ci/ci-elpi.sh
index 9c58034be1..9b4a06fd5b 100755
--- a/dev/ci/ci-elpi.sh
+++ b/dev/ci/ci-elpi.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-Elpi_CI_DIR="${CI_BUILD_DIR}/elpi"
+git_download Elpi
-git_checkout "${Elpi_CI_BRANCH}" "${Elpi_CI_GITURL}" "${Elpi_CI_DIR}"
-
-( cd "${Elpi_CI_DIR}" && make && make install )
+( cd "${CI_BUILD_DIR}/Elpi" && make && make install )
diff --git a/dev/ci/ci-equations.sh b/dev/ci/ci-equations.sh
index 98735b4ec4..998d50faa7 100755
--- a/dev/ci/ci-equations.sh
+++ b/dev/ci/ci-equations.sh
@@ -3,8 +3,7 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-Equations_CI_DIR="${CI_BUILD_DIR}/Equations"
+git_download Equations
-git_checkout "${Equations_CI_BRANCH}" "${Equations_CI_GITURL}" "${Equations_CI_DIR}"
-
-( cd "${Equations_CI_DIR}" && coq_makefile -f _CoqProject -o Makefile && make && make test-suite && make examples && make install)
+( cd "${CI_BUILD_DIR}/Equations" && coq_makefile -f _CoqProject -o Makefile && \
+ make && make test-suite && make examples && make install)
diff --git a/dev/ci/ci-ext-lib.sh b/dev/ci/ci-ext-lib.sh
index cf212c2fb5..5eb167d97d 100755
--- a/dev/ci/ci-ext-lib.sh
+++ b/dev/ci/ci-ext-lib.sh
@@ -1,16 +1,8 @@
#!/usr/bin/env bash
ci_dir="$(dirname "$0")"
+. "${ci_dir}/ci-common.sh"
-# This script could be included inside other ones
-# Let's avoid to source ci-common twice in this case
-if [ -z "${CI_BUILD_DIR}" ];
-then
- . "${ci_dir}/ci-common.sh"
-fi
+git_download ext_lib
-ext_lib_CI_DIR="${CI_BUILD_DIR}/ExtLib"
-
-git_checkout "${ext_lib_CI_BRANCH}" "${ext_lib_CI_GITURL}" "${ext_lib_CI_DIR}"
-
-( cd "${ext_lib_CI_DIR}" && make && make install)
+( cd "${CI_BUILD_DIR}/ext_lib" && make && make install)
diff --git a/dev/ci/ci-fcsl-pcm.sh b/dev/ci/ci-fcsl-pcm.sh
index fdc4c729b6..cb951630c8 100755
--- a/dev/ci/ci-fcsl-pcm.sh
+++ b/dev/ci/ci-fcsl-pcm.sh
@@ -3,10 +3,8 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-fcsl_pcm_CI_DIR="${CI_BUILD_DIR}/fcsl-pcm"
-
install_ssreflect
-git_checkout "${fcsl_pcm_CI_BRANCH}" "${fcsl_pcm_CI_GITURL}" "${fcsl_pcm_CI_DIR}"
+git_download fcsl_pcm
-( cd "${fcsl_pcm_CI_DIR}" && make )
+( cd "${CI_BUILD_DIR}/fcsl_pcm" && make )
diff --git a/dev/ci/ci-fiat-crypto-legacy.sh b/dev/ci/ci-fiat-crypto-legacy.sh
new file mode 100755
index 0000000000..e0395754e5
--- /dev/null
+++ b/dev/ci/ci-fiat-crypto-legacy.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+
+ci_dir="$(dirname "$0")"
+. "${ci_dir}/ci-common.sh"
+
+FORCE_GIT=1
+git_download fiat_crypto
+
+fiat_crypto_legacy_CI_TARGETS1="print-old-pipeline-lite old-pipeline-lite lite-display"
+fiat_crypto_legacy_CI_TARGETS2="print-old-pipeline-nobigmem old-pipeline-nobigmem nonautogenerated-specific nonautogenerated-specific-display"
+
+( cd "${CI_BUILD_DIR}/fiat_crypto" && git submodule update --init --recursive && \
+ make ${fiat_crypto_legacy_CI_TARGETS1} && make -j 1 ${fiat_crypto_legacy_CI_TARGETS2} )
diff --git a/dev/ci/ci-fiat-crypto.sh b/dev/ci/ci-fiat-crypto.sh
index 48a1366aba..7e8013be9b 100755
--- a/dev/ci/ci-fiat-crypto.sh
+++ b/dev/ci/ci-fiat-crypto.sh
@@ -3,12 +3,12 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-fiat_crypto_CI_DIR="${CI_BUILD_DIR}/fiat-crypto"
+FORCE_GIT=1
+git_download fiat_crypto
-git_checkout "${fiat_crypto_CI_BRANCH}" "${fiat_crypto_CI_GITURL}" "${fiat_crypto_CI_DIR}"
+# We need a larger stack size to not overflow ocamlopt+flambda when
+# building the executables.
+# c.f. https://github.com/coq/coq/pull/8313#issuecomment-416650241
-( cd "${fiat_crypto_CI_DIR}" && git submodule update --init --recursive )
-
-fiat_crypto_CI_TARGETS1="printlite lite lite-display"
-fiat_crypto_CI_TARGETS2="print-nobigmem nobigmem nonautogenerated-specific nonautogenerated-specific-display"
-( cd "${fiat_crypto_CI_DIR}" && make ${fiat_crypto_CI_TARGETS1} && make -j 1 ${fiat_crypto_CI_TARGETS2} )
+( cd "${CI_BUILD_DIR}/fiat_crypto" && git submodule update --init --recursive && \
+ ulimit -s 32768 && make new-pipeline c-files )
diff --git a/dev/ci/ci-fiat-parsers.sh b/dev/ci/ci-fiat-parsers.sh
index 35c2284050..ac74ebf667 100755
--- a/dev/ci/ci-fiat-parsers.sh
+++ b/dev/ci/ci-fiat-parsers.sh
@@ -3,8 +3,7 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-fiat_parsers_CI_DIR="${CI_BUILD_DIR}/fiat"
+FORCE_GIT=1
+git_download fiat_parsers
-git_checkout "${fiat_parsers_CI_BRANCH}" "${fiat_parsers_CI_GITURL}" "${fiat_parsers_CI_DIR}"
-
-( cd "${fiat_parsers_CI_DIR}" && make parsers parsers-examples && make fiat-core )
+( cd "${CI_BUILD_DIR}/fiat_parsers" && make parsers parsers-examples && make fiat-core )
diff --git a/dev/ci/ci-flocq.sh b/dev/ci/ci-flocq.sh
index 8599e4d50e..e87483df0a 100755
--- a/dev/ci/ci-flocq.sh
+++ b/dev/ci/ci-flocq.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-Flocq_CI_DIR="${CI_BUILD_DIR}/flocq"
+git_download Flocq
-git_checkout "${Flocq_CI_BRANCH}" "${Flocq_CI_GITURL}" "${Flocq_CI_DIR}"
-
-( cd "${Flocq_CI_DIR}" && ./autogen.sh && ./configure && ./remake "-j${NJOBS}" )
+( cd "${CI_BUILD_DIR}/Flocq" && ./autogen.sh && ./configure && ./remake "-j${NJOBS}" )
diff --git a/dev/ci/ci-formal-topology.sh b/dev/ci/ci-formal-topology.sh
index 118d151500..8be5a06ed2 100755
--- a/dev/ci/ci-formal-topology.sh
+++ b/dev/ci/ci-formal-topology.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-formal_topology_CI_DIR="${CI_BUILD_DIR}/formal-topology"
+git_download formal_topology
-git_checkout "${formal_topology_CI_BRANCH}" "${formal_topology_CI_GITURL}" "${formal_topology_CI_DIR}"
-
-( cd "${formal_topology_CI_DIR}" && make )
+( cd "${CI_BUILD_DIR}/formal_topology" && make )
diff --git a/dev/ci/ci-geocoq.sh b/dev/ci/ci-geocoq.sh
index 24cd9c4272..8c57318477 100755
--- a/dev/ci/ci-geocoq.sh
+++ b/dev/ci/ci-geocoq.sh
@@ -3,10 +3,8 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-GeoCoq_CI_DIR="${CI_BUILD_DIR}/GeoCoq"
-
-git_checkout "${GeoCoq_CI_BRANCH}" "${GeoCoq_CI_GITURL}" "${GeoCoq_CI_DIR}"
-
install_ssralg
-( cd "${GeoCoq_CI_DIR}" && ./configure.sh && make )
+git_download GeoCoq
+
+( cd "${CI_BUILD_DIR}/GeoCoq" && ./configure.sh && make )
diff --git a/dev/ci/ci-hott.sh b/dev/ci/ci-hott.sh
index 184b90a50b..7eeeb09372 100755
--- a/dev/ci/ci-hott.sh
+++ b/dev/ci/ci-hott.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-HoTT_CI_DIR="${CI_BUILD_DIR}"/HoTT
+git_download HoTT
-git_checkout "${HoTT_CI_BRANCH}" "${HoTT_CI_GITURL}" "${HoTT_CI_DIR}"
-
-( cd "${HoTT_CI_DIR}" && ./autogen.sh && ./configure && make && make validate )
+( cd "${CI_BUILD_DIR}/HoTT" && ./autogen.sh && ./configure && make && make validate )
diff --git a/dev/ci/ci-iris-lambda-rust.sh b/dev/ci/ci-iris-lambda-rust.sh
index 1af0f634c4..6960a8b98a 100755
--- a/dev/ci/ci-iris-lambda-rust.sh
+++ b/dev/ci/ci-iris-lambda-rust.sh
@@ -3,32 +3,28 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-stdpp_CI_DIR="${CI_BUILD_DIR}/coq-stdpp"
-Iris_CI_DIR="${CI_BUILD_DIR}/iris-coq"
-lambdaRust_CI_DIR="${CI_BUILD_DIR}/lambdaRust"
-
install_ssreflect
# Setup lambdaRust first
-git_checkout "${lambdaRust_CI_BRANCH}" "${lambdaRust_CI_GITURL}" "${lambdaRust_CI_DIR}"
+git_download lambdaRust
# Extract required version of Iris
-Iris_SHA=$(grep -F coq-iris < "${lambdaRust_CI_DIR}/opam" | sed 's/.*"dev\.[0-9.-]\+\.\([0-9a-z]\+\)".*/\1/')
+Iris_REF=$(grep -F coq-iris < "${CI_BUILD_DIR}/lambdaRust/opam" | sed 's/.*"dev\.[0-9.-]\+\.\([0-9a-z]\+\)".*/\1/')
# Setup Iris
-git_checkout "${Iris_CI_BRANCH}" "${Iris_CI_GITURL}" "${Iris_CI_DIR}" "${Iris_SHA}"
+git_download Iris
# Extract required version of std++
-stdpp_SHA=$(grep -F coq-stdpp < "${Iris_CI_DIR}/opam" | sed 's/.*"dev\.[0-9.-]\+\.\([0-9a-z]\+\)".*/\1/')
+stdpp_REF=$(grep -F coq-stdpp < "${CI_BUILD_DIR}/Iris/opam" | sed 's/.*"dev\.[0-9.-]\+\.\([0-9a-z]\+\)".*/\1/')
# Setup std++
-git_checkout "${stdpp_CI_BRANCH}" "${stdpp_CI_GITURL}" "${stdpp_CI_DIR}" "${stdpp_SHA}"
+git_download stdpp
# Build std++
-( cd "${stdpp_CI_DIR}" && make && make install )
+( cd "${CI_BUILD_DIR}/stdpp" && make && make install )
-# Build and validate (except on Travis, i.e., skip if TRAVIS is non-empty) Iris
-( cd "${Iris_CI_DIR}" && make && (test -n "${TRAVIS}" || make validate) && make install )
+# Build and validate Iris
+( cd "${CI_BUILD_DIR}/Iris" && make && make validate && make install )
# Build lambdaRust
-( cd "${lambdaRust_CI_DIR}" && make && make install )
+( cd "${CI_BUILD_DIR}/lambdaRust" && make && make install )
diff --git a/dev/ci/ci-ltac2.sh b/dev/ci/ci-ltac2.sh
index 5981aaaae7..4df22bf249 100755
--- a/dev/ci/ci-ltac2.sh
+++ b/dev/ci/ci-ltac2.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-ltac2_CI_DIR="${CI_BUILD_DIR}/ltac2"
+git_download ltac2
-git_checkout "${ltac2_CI_BRANCH}" "${ltac2_CI_GITURL}" "${ltac2_CI_DIR}"
-
-( cd "${ltac2_CI_DIR}" && make && make tests && make install )
+( cd "${CI_BUILD_DIR}/ltac2" && make && make tests && make install )
diff --git a/dev/ci/ci-math-classes.sh b/dev/ci/ci-math-classes.sh
index 6a064b2971..ae31a8e7f8 100755
--- a/dev/ci/ci-math-classes.sh
+++ b/dev/ci/ci-math-classes.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-math_classes_CI_DIR="${CI_BUILD_DIR}/math-classes"
+git_download math_classes
-git_checkout "${math_classes_CI_BRANCH}" "${math_classes_CI_GITURL}" "${math_classes_CI_DIR}"
-
-( cd "${math_classes_CI_DIR}" && ./configure.sh && make && make install )
+( cd "${CI_BUILD_DIR}/math_classes" && ./configure.sh && make && make install )
diff --git a/dev/ci/ci-math-comp.sh b/dev/ci/ci-math-comp.sh
index 20328baf2a..a74f9fa4d3 100755
--- a/dev/ci/ci-math-comp.sh
+++ b/dev/ci/ci-math-comp.sh
@@ -4,11 +4,10 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-mathcomp_CI_DIR="${CI_BUILD_DIR}/math-comp"
-oddorder_CI_DIR="${CI_BUILD_DIR}/odd-order"
+git_download mathcomp
-git_checkout "${mathcomp_CI_BRANCH}" "${mathcomp_CI_GITURL}" "${mathcomp_CI_DIR}"
-git_checkout "${oddorder_CI_BRANCH}" "${oddorder_CI_GITURL}" "${oddorder_CI_DIR}"
+( cd "${CI_BUILD_DIR}/mathcomp/mathcomp" && make && make install )
-( cd "${mathcomp_CI_DIR}/mathcomp" && make && make install )
-( cd "${oddorder_CI_DIR}/" && make )
+git_download oddorder
+
+( cd "${CI_BUILD_DIR}/oddorder" && make )
diff --git a/dev/ci/ci-mtac2.sh b/dev/ci/ci-mtac2.sh
index 1372acb8e5..7075d4d7f6 100755
--- a/dev/ci/ci-mtac2.sh
+++ b/dev/ci/ci-mtac2.sh
@@ -3,17 +3,10 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-unicoq_CI_DIR=${CI_BUILD_DIR}/unicoq
-mtac2_CI_DIR=${CI_BUILD_DIR}/Mtac2
+git_download unicoq
-# Setup UniCoq
+( cd "${CI_BUILD_DIR}/unicoq" && coq_makefile -f Make -o Makefile && make && make install )
-git_checkout "${unicoq_CI_BRANCH}" "${unicoq_CI_GITURL}" "${unicoq_CI_DIR}"
+git_download mtac2
-( cd "${unicoq_CI_DIR}" && coq_makefile -f Make -o Makefile && make && make install )
-
-# Setup MetaCoq
-
-git_checkout "${mtac2_CI_BRANCH}" "${mtac2_CI_GITURL}" "${mtac2_CI_DIR}"
-
-( cd "${mtac2_CI_DIR}" && coq_makefile -f _CoqProject -o Makefile && make )
+( cd "${CI_BUILD_DIR}/mtac2" && coq_makefile -f _CoqProject -o Makefile && make )
diff --git a/dev/ci/ci-pidetop.sh b/dev/ci/ci-pidetop.sh
index 32cba0808e..1a9a26843c 100755
--- a/dev/ci/ci-pidetop.sh
+++ b/dev/ci/ci-pidetop.sh
@@ -1,12 +1,9 @@
#!/usr/bin/env bash
-# $0 is not the safest way, but...
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-pidetop_CI_DIR="${CI_BUILD_DIR}/pidetop"
-
-git_checkout "${pidetop_CI_BRANCH}" "${pidetop_CI_GITURL}" "${pidetop_CI_DIR}"
+git_download pidetop
# Travis / Gitlab have different filesystem layout due to use of
# `-local`. We need to improve this divergence but if we use Dune this
@@ -17,6 +14,6 @@ else
COQLIB="$COQBIN/../"
fi
-( cd "${pidetop_CI_DIR}" && jbuilder build @install )
+( cd "${CI_BUILD_DIR}/pidetop" && dune build -p pidetop @install )
-echo -en '4\nexit' | "$pidetop_CI_DIR/_build/install/default/bin/pidetop" -coqlib "$COQLIB" -main-channel stdfds
+echo -en '4\nexit' | "${CI_BUILD_DIR}/pidetop/_build/install/default/bin/pidetop" -coqlib "$COQLIB" -main-channel stdfds
diff --git a/dev/ci/ci-plugin-tutorial.sh b/dev/ci/ci-plugin-tutorial.sh
new file mode 100755
index 0000000000..6c26a71a21
--- /dev/null
+++ b/dev/ci/ci-plugin-tutorial.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+ci_dir="$(dirname "$0")"
+. "${ci_dir}/ci-common.sh"
+
+git_download plugin_tutorial
+
+( cd "${CI_BUILD_DIR}/plugin_tutorial" && \
+ pushd tuto0 && make && popd && \
+ pushd tuto1 && make && popd && \
+ pushd tuto2 && make && popd && \
+ pushd tuto3 && make && popd )
diff --git a/dev/ci/ci-quickchick.sh b/dev/ci/ci-quickchick.sh
index fc39e2685d..08686d7ced 100755
--- a/dev/ci/ci-quickchick.sh
+++ b/dev/ci/ci-quickchick.sh
@@ -1,18 +1,10 @@
#!/usr/bin/env bash
ci_dir="$(dirname "$0")"
-
-# This script could be included inside other ones
-# Let's avoid to source ci-common twice in this case
-if [ -z "${CI_BUILD_DIR}" ];
-then
- . "${ci_dir}/ci-common.sh"
-fi
-
-quickchick_CI_DIR="${CI_BUILD_DIR}/Quickchick"
+. "${ci_dir}/ci-common.sh"
install_ssreflect
-git_checkout "${quickchick_CI_BRANCH}" "${quickchick_CI_GITURL}" "${quickchick_CI_DIR}"
+git_download quickchick
-( cd "${quickchick_CI_DIR}" && make && make install)
+( cd "${CI_BUILD_DIR}/quickchick" && make && make install)
diff --git a/dev/ci/ci-simple-io.sh b/dev/ci/ci-simple-io.sh
new file mode 100755
index 0000000000..e7bcd80de7
--- /dev/null
+++ b/dev/ci/ci-simple-io.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+
+ci_dir="$(dirname "$0")"
+. "${ci_dir}/ci-common.sh"
+
+git_download simple_io
+
+( cd "${CI_BUILD_DIR}/simple_io" && make build && make install)
diff --git a/dev/ci/ci-template.sh b/dev/ci/ci-template.sh
deleted file mode 100755
index e77a553047..0000000000
--- a/dev/ci/ci-template.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env bash
-
-ci_dir="$(dirname "$0")"
-. "${ci_dir}/ci-common.sh"
-
-Template_CI_BRANCH=master
-Template_CI_GITURL=https://github.com/Template/Template
-Template_CI_DIR="${CI_BUILD_DIR}/Template"
-
-git_checkout "${Template_CI_BRANCH}" "${Template_CI_GITURL}" "${Template_CI_DIR}"
-
-( cd "${Template_CI_DIR}" && make )
diff --git a/dev/ci/ci-tlc.sh b/dev/ci/ci-tlc.sh
index 31387c8ddc..a2f0bea555 100755
--- a/dev/ci/ci-tlc.sh
+++ b/dev/ci/ci-tlc.sh
@@ -3,8 +3,7 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-tlc_CI_DIR="${CI_BUILD_DIR}/tlc"
+FORCE_GIT=1
+git_download tlc
-git_checkout "${tlc_CI_BRANCH}" "${tlc_CI_GITURL}" "${tlc_CI_DIR}"
-
-( cd "${tlc_CI_DIR}" && make )
+( cd "${CI_BUILD_DIR}/tlc" && make )
diff --git a/dev/ci/ci-unimath.sh b/dev/ci/ci-unimath.sh
index aa20fe1ff0..a7644fee23 100755
--- a/dev/ci/ci-unimath.sh
+++ b/dev/ci/ci-unimath.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-UniMath_CI_DIR="${CI_BUILD_DIR}/UniMath"
+git_download UniMath
-git_checkout "${UniMath_CI_BRANCH}" "${UniMath_CI_GITURL}" "${UniMath_CI_DIR}"
-
-( cd "${UniMath_CI_DIR}" && make BUILD_COQ=no )
+( cd "${CI_BUILD_DIR}/UniMath" && make BUILD_COQ=no )
diff --git a/dev/ci/ci-vst.sh b/dev/ci/ci-vst.sh
index 7a097eaab4..0fec19205a 100755
--- a/dev/ci/ci-vst.sh
+++ b/dev/ci/ci-vst.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-VST_CI_DIR="${CI_BUILD_DIR}/VST"
+git_download VST
-git_checkout "${VST_CI_BRANCH}" "${VST_CI_GITURL}" "${VST_CI_DIR}"
-
-( cd "${VST_CI_DIR}" && make IGNORECOQVERSION=true )
+( cd "${CI_BUILD_DIR}/VST" && make IGNORECOQVERSION=true )
diff --git a/dev/ci/docker/bionic_coq/Dockerfile b/dev/ci/docker/bionic_coq/Dockerfile
index 1361392dc8..8d0f69626e 100644
--- a/dev/ci/docker/bionic_coq/Dockerfile
+++ b/dev/ci/docker/bionic_coq/Dockerfile
@@ -1,4 +1,4 @@
-# CACHEKEY: "bionic_coq-V2018-07-11-V2"
+# CACHEKEY: "bionic_coq-V2018-09-24-V01"
# ^^ Update when modifying this file.
FROM ubuntu:bionic
@@ -7,50 +7,65 @@ LABEL maintainer="e@x80.org"
ENV DEBIAN_FRONTEND="noninteractive"
RUN apt-get update -qq && apt-get install --no-install-recommends -y -qq \
- m4 automake autoconf time wget rsync git gcc-multilib opam \
+ # Dependencies of the image, the test-suite and external projects
+ m4 automake autoconf time wget rsync git gcc-multilib build-essential unzip \
+ # Dependencies of lablgtk (for CoqIDE)
libgtk2.0-dev libgtksourceview2.0-dev \
- texlive-latex-extra texlive-fonts-recommended texlive-science tipa \
- python3-sphinx python3-pexpect python3-sphinx-rtd-theme python3-bs4 python3-sphinxcontrib.bibtex \
- python3-setuptools python3-wheel python3-pip
+ # Dependencies of stdlib and sphinx doc
+ texlive-latex-extra texlive-fonts-recommended texlive-xetex latexmk \
+ xindy python3-pip python3-setuptools python3-pexpect python3-bs4 \
+ # Dependencies of source-doc and coq-makefile
+ texlive-science tipa
-RUN pip3 install antlr4-python3-runtime
+# More dependencies of the sphinx doc
+RUN pip3 install sphinx==1.7.8 sphinx_rtd_theme==0.2.5b2 \
+ antlr4-python3-runtime==4.7.1 sphinxcontrib-bibtex==0.4.0
+
+# We need to install OPAM 2.0 manually for now.
+RUN wget https://github.com/ocaml/opam/releases/download/2.0.0/opam-2.0.0-x86_64-linux -O /usr/bin/opam && chmod 755 /usr/bin/opam
# Basic OPAM setup
ENV NJOBS="2" \
+ OPAMJOBS="2" \
OPAMROOT=/root/.opamcache \
- OPAMROOTISOK="true"
+ OPAMROOTISOK="true" \
+ OPAMYES="true"
# Base opam is the set of base packages required by Coq
ENV COMPILER="4.02.3"
-RUN opam init -a -y -j $NJOBS --compiler="$COMPILER" default https://opam.ocaml.org && eval $(opam config env) && opam update
-
# Common OPAM packages.
# `num` does not have a version number as the right version to install varies
# with the compiler version.
-ENV BASE_OPAM="num ocamlfind.1.8.0 dune.1.0.0 ounit.2.0.8" \
- CI_OPAM="menhir.20180530 elpi.1.0.4 ocamlgraph.1.8.8"
+ENV BASE_OPAM="num ocamlfind.1.8.0 dune.1.2.1 ounit.2.0.8" \
+ CI_OPAM="menhir.20180530 elpi.1.1.0 ocamlgraph.1.8.8"
# BASE switch; CI_OPAM contains Coq's CI dependencies.
ENV CAMLP5_VER="6.14" \
COQIDE_OPAM="lablgtk.2.18.5 conf-gtksourceview.2"
-RUN opam switch -y -j $NJOBS "$COMPILER" && eval $(opam config env) && \
- opam install -j $NJOBS $BASE_OPAM camlp5.$CAMLP5_VER $COQIDE_OPAM $CI_OPAM
+# The separate `opam install ocamlfind` workarounds an OPAM repository bug in 4.02.3
+RUN opam init -a --disable-sandboxing --compiler="$COMPILER" default https://opam.ocaml.org && eval $(opam env) && opam update && \
+ opam install ocamlfind.1.8.0 && \
+ opam install $BASE_OPAM camlp5.$CAMLP5_VER $COQIDE_OPAM $CI_OPAM
# base+32bit switch
-RUN opam switch -y -j $NJOBS "${COMPILER}+32bit" && eval $(opam config env) && \
- opam install -j $NJOBS $BASE_OPAM camlp5.$CAMLP5_VER
+RUN opam switch create "${COMPILER}+32bit" && eval $(opam env) && \
+ opam install ocamlfind.1.8.0 && \
+ opam install $BASE_OPAM camlp5.$CAMLP5_VER
# EDGE switch
ENV COMPILER_EDGE="4.07.0" \
CAMLP5_VER_EDGE="7.06" \
- COQIDE_OPAM_EDGE="lablgtk.2.18.6 conf-gtksourceview.2"
+ COQIDE_OPAM_EDGE="lablgtk.2.18.6 conf-gtksourceview.2" \
+ BASE_OPAM_EDGE="odoc.1.2.0 dune-release.0.3.0"
-RUN opam switch -y -j $NJOBS $COMPILER_EDGE && eval $(opam config env) && \
- opam install -j $NJOBS $BASE_OPAM camlp5.$CAMLP5_VER_EDGE $COQIDE_OPAM_EDGE
+RUN opam switch create $COMPILER_EDGE && eval $(opam env) && \
+ opam install $BASE_OPAM $BASE_OPAM_EDGE camlp5.$CAMLP5_VER_EDGE $COQIDE_OPAM_EDGE
# EDGE+flambda switch, we install CI_OPAM as to be able to use
# `ci-template-flambda` with everything.
-RUN opam switch -y -j $NJOBS "${COMPILER_EDGE}+flambda" && eval $(opam config env) && \
- opam install -j $NJOBS $BASE_OPAM camlp5.$CAMLP5_VER_EDGE $COQIDE_OPAM_EDGE $CI_OPAM
+RUN opam switch create "${COMPILER_EDGE}+flambda" && eval $(opam env) && \
+ opam install $BASE_OPAM $BASE_OPAM_EDGE camlp5.$CAMLP5_VER_EDGE $COQIDE_OPAM_EDGE $CI_OPAM
+
+RUN opam clean -a -c
diff --git a/dev/ci/gitlab.bat b/dev/ci/gitlab.bat
index 973319de68..a848c49d75 100644..100755
--- a/dev/ci/gitlab.bat
+++ b/dev/ci/gitlab.bat
@@ -2,23 +2,38 @@
REM This script builds and signs the Windows packages on Gitlab
+ECHO "Start Time"
+TIME /T
+
+REM List currently used cygwin and target folders for debugging / maintenance purposes
+
+ECHO "Currently used cygwin folders"
+DIR C:\ci\cygwin*
+ECHO "Currently used target folders"
+DIR C:\ci\coq*
+ECHO "Root folders"
+DIR C:\
+
if %ARCH% == 32 (
SET ARCHLONG=i686
- SET CYGROOT=C:\cygwin
SET SETUP=setup-x86.exe
)
if %ARCH% == 64 (
SET ARCHLONG=x86_64
- SET CYGROOT=C:\cygwin64
SET SETUP=setup-x86_64.exe
)
+SET CYGROOT=C:\ci\cygwin%ARCH%
+SET DESTCOQ=C:\ci\coq%ARCH%
+
+CALL :MakeUniqueFolder %CYGROOT% CYGROOT
+CALL :MakeUniqueFolder %DESTCOQ% DESTCOQ
+
powershell -Command "(New-Object Net.WebClient).DownloadFile('http://www.cygwin.com/%SETUP%', '%SETUP%')"
SET CYGCACHE=%CYGROOT%\var\cache\setup
SET CI_PROJECT_DIR_MFMT=%CI_PROJECT_DIR:\=/%
SET CI_PROJECT_DIR_CFMT=%CI_PROJECT_DIR_MFMT:C:/=/cygdrive/c/%
-SET DESTCOQ=C:\coq%ARCH%_inst
SET COQREGTESTING=Y
SET PATH=%PATH%;C:\Program Files\7-Zip\;C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin
@@ -29,10 +44,24 @@ call %CI_PROJECT_DIR%\dev\build\windows\MakeCoq_MinGW.bat -threads=1 ^
-arch=%ARCH% -installer=Y -coqver=%CI_PROJECT_DIR_CFMT% ^
-destcyg=%CYGROOT% -destcoq=%DESTCOQ% -cygcache=%CYGCACHE% ^
-addon="bignums ltac2 equations" -make=N ^
- -setup %CI_PROJECT_DIR%\%SETUP% || GOTO ErrorExit
+ -setup %CI_PROJECT_DIR%\%SETUP% || GOTO ErrorCopyLogFilesAndExit
+
+
+ECHO "Start Artifact Creation"
+TIME /T
+
+mkdir artifacts
+
+CALL :CopyLogFiles
-copy "%CYGROOT%\build\coq-local\dev\nsis\*.exe" dev\nsis || GOTO ErrorExit
-7z a coq-opensource-archive-windows-%ARCHLONG%.zip %CYGROOT%\build\tarballs\* || GOTO ErrorExit
+copy "%CYGROOT%\build\coq-local\dev\nsis\*.exe" artifacts || GOTO ErrorExit
+REM The open source archive is only required for release builds
+IF DEFINED WIN_CERTIFICATE_PATH (
+ 7z a artifacts\coq-opensource-archive-windows-%ARCHLONG%.zip %CYGROOT%\build\tarballs\* || GOTO ErrorExit
+) ELSE (
+ REM In non release builds, create a dummy file
+ ECHO "This is not a release build - open source archive not created / uploaded" > artifacts\coq-opensource-info.txt
+)
REM DO NOT echo the signing command below, as this would leak secrets in the logs
IF DEFINED WIN_CERTIFICATE_PATH (
@@ -43,8 +72,49 @@ IF DEFINED WIN_CERTIFICATE_PATH (
)
)
+ECHO "Finished Artifact Creation"
+TIME /T
+
+CALL :CleanupFolders
+
+ECHO "Finished Cleanup"
+TIME /T
+
GOTO :EOF
+:CopyLogFiles
+ ECHO Copy log files for artifact upload
+ MKDIR artifacts\buildlogs
+ COPY %CYGROOT%\build\buildlogs\* artifacts\buildlogs
+ MKDIR artifacts\filelists
+ COPY %CYGROOT%\build\filelists\* artifacts\filelists
+ MKDIR artifacts\flagfiles
+ COPY %CYGROOT%\build\flagfiles\* artifacts\flagfiles
+ GOTO :EOF
+
+:CleanupFolders
+ ECHO "Cleaning %CYGROOT%"
+ RMDIR /S /Q "%CYGROOT%"
+ ECHO "Cleaning %DESTCOQ%"
+ RMDIR /S /Q "%DESTCOQ%"
+ GOTO :EOF
+
+:MakeUniqueFolder
+ REM Create a uniquely named folder
+ REM This script is safe because folder creation is atomic - either we create it or fail
+ REM %1 = base path or directory (_%RANDOM%_%RANDOM% is appended to this)
+ REM %2 = name of the variable which receives the unique folder name
+ SET "UNIQUENAME=%1_%RANDOM%_%RANDOM%"
+ MKDIR "%UNIQUENAME%"
+ IF ERRORLEVEL 1 GOTO :MakeUniqueFolder
+ SET "%2=%UNIQUENAME%"
+ GOTO :EOF
+
+:ErrorCopyLogFilesAndExit
+ CALL :CopyLogFiles
+ REM fall through
+
:ErrorExit
+ CALL :CleanupFolders
ECHO ERROR %0 failed
EXIT /b 1
diff --git a/dev/ci/user-overlays/00669-maximedenes-ssr-merge.sh b/dev/ci/user-overlays/00669-maximedenes-ssr-merge.sh
index e6a2c4460b..d812df3ec0 100644
--- a/dev/ci/user-overlays/00669-maximedenes-ssr-merge.sh
+++ b/dev/ci/user-overlays/00669-maximedenes-ssr-merge.sh
@@ -1,6 +1,6 @@
#!/bin/sh
if [ "$CI_PULL_REQUEST" = "669" ] || [ "$CI_BRANCH" = "ssr-merge" ]; then
- mathcomp_CI_BRANCH=ssr-merge
+ mathcomp_CI_REF=ssr-merge
mathcomp_CI_GITURL=https://github.com/maximedenes/math-comp
fi
diff --git a/dev/ci/user-overlays/07085-ppedrot-pure-sharing-flag.sh b/dev/ci/user-overlays/07085-ppedrot-pure-sharing-flag.sh
new file mode 100644
index 0000000000..575df07425
--- /dev/null
+++ b/dev/ci/user-overlays/07085-ppedrot-pure-sharing-flag.sh
@@ -0,0 +1,8 @@
+_OVERLAY_BRANCH=pure-sharing-flag
+
+if [ "$CI_PULL_REQUEST" = "7085" ] || [ "$CI_BRANCH" = "$_OVERLAY_BRANCH" ]; then
+
+ mtac2_CI_BRANCH="$_OVERLAY_BRANCH"
+ mtac2_CI_GITURL=https://github.com/ppedrot/Mtac2
+
+fi
diff --git a/dev/ci/user-overlays/07257-herbelin-master+fix-yet-another-unif-dep-in-alphabet.sh b/dev/ci/user-overlays/07257-herbelin-master+fix-yet-another-unif-dep-in-alphabet.sh
new file mode 100644
index 0000000000..019cb8054d
--- /dev/null
+++ b/dev/ci/user-overlays/07257-herbelin-master+fix-yet-another-unif-dep-in-alphabet.sh
@@ -0,0 +1,4 @@
+if [ "$CI_PULL_REQUEST" = "7257" ] || [ "$CI_BRANCH" = "master+fix-yet-another-unif-dep-in-alphabet" ]; then
+ cross_crypto_CI_REF=master+fix-coq7257-ascii-sensitive-unification
+ cross_crypto_CI_GITURL=https://github.com/herbelin/cross-crypto
+fi
diff --git a/dev/ci/user-overlays/07288-herbelin-master+new-module-pretyping-id-management.sh b/dev/ci/user-overlays/07288-herbelin-master+new-module-pretyping-id-management.sh
new file mode 100644
index 0000000000..3a6480a5a1
--- /dev/null
+++ b/dev/ci/user-overlays/07288-herbelin-master+new-module-pretyping-id-management.sh
@@ -0,0 +1,6 @@
+if [ "$CI_PULL_REQUEST" = "7288" ] || [ "$CI_BRANCH" = "master+new-module-pretyping-id-management" ]; then
+
+ ltac2_CI_BRANCH=master+globenv-coq-pr7288
+ ltac2_CI_GITURL=https://github.com/herbelin/ltac2
+
+fi
diff --git a/dev/ci/user-overlays/07859-printers.sh b/dev/ci/user-overlays/07859-printers.sh
deleted file mode 100644
index 27f588e214..0000000000
--- a/dev/ci/user-overlays/07859-printers.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-
-if [ "$CI_PULL_REQUEST" = "7859" ] || [ "$CI_BRANCH" = "rm-univ-broken-printing" ]; then
- Equations_CI_BRANCH=fix-printers
- Equations_CI_GITURL=https://github.com/SkySkimmer/Coq-Equations
-fi
diff --git a/dev/ci/user-overlays/07908-proj-mind.sh b/dev/ci/user-overlays/07908-proj-mind.sh
deleted file mode 100644
index 293eeb5a5a..0000000000
--- a/dev/ci/user-overlays/07908-proj-mind.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-
-if [ "$CI_PULL_REQUEST" = "7908" ] || [ "$CI_BRANCH" = "proj-mind" ]; then
- Equations_CI_BRANCH=fix-proj-mind
- Equations_CI_GITURL=https://github.com/SkySkimmer/Coq-Equations
-fi
diff --git a/dev/ci/user-overlays/07941-bollu-questionmark-into-record-for-missing-record-field-error.sh b/dev/ci/user-overlays/07941-bollu-questionmark-into-record-for-missing-record-field-error.sh
deleted file mode 100644
index 56c0dc3433..0000000000
--- a/dev/ci/user-overlays/07941-bollu-questionmark-into-record-for-missing-record-field-error.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-
-if [ "$CI_PULL_REQUEST" = "7941" ] || [ "$CI_BRANCH" = "jun-27-missing-record-field-error-message-quickfix" ]; then
- Equations_CI_BRANCH=overlay-question-mark-extended-for-missing-record-field
- Equations_CI_GITURL=https://github.com/bollu/Coq-Equations
-fi
diff --git a/dev/ci/user-overlays/08063-jasongross-string-eqb.sh b/dev/ci/user-overlays/08063-jasongross-string-eqb.sh
deleted file mode 100644
index 99a11b9fbf..0000000000
--- a/dev/ci/user-overlays/08063-jasongross-string-eqb.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-
-if [ "$CI_PULL_REQUEST" = "8063" ] || [ "$CI_BRANCH" = "string-eqb" ]; then
- quickchick_CI_BRANCH=fix-for-pr-8063
- quickchick_CI_GITURL=https://github.com/JasonGross/QuickChick
-fi
diff --git a/dev/ci/user-overlays/08552-gares-elpi-11.sh b/dev/ci/user-overlays/08552-gares-elpi-11.sh
new file mode 100644
index 0000000000..c08f44fc50
--- /dev/null
+++ b/dev/ci/user-overlays/08552-gares-elpi-11.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+if [ "$CI_PULL_REQUEST" = "8552" ] || [ "$CI_BRANCH" = "elpi-1.1" ]; then
+ Elpi_CI_REF=coq-master-elpi-1.1
+fi
diff --git a/dev/ci/user-overlays/README.md b/dev/ci/user-overlays/README.md
index d38d1b06d1..68afe7ee4a 100644
--- a/dev/ci/user-overlays/README.md
+++ b/dev/ci/user-overlays/README.md
@@ -7,10 +7,12 @@ request to test it with the adapted version of the external project.
An overlay is a file which defines where to look for the patched version so that
testing is possible. It redefines some variables from
[`ci-basic-overlay.sh`](../ci-basic-overlay.sh):
-give the name of your branch using a `_CI_BRANCH` variable and the location of
-your fork using a `_CI_GITURL` variable.
+give the name of your branch / commit using a `_CI_REF` variable and the
+location of your fork using a `_CI_GITURL` variable.
The `_CI_GITURL` variable should be the URL of the repository without a
trailing `.git`.
+If the fork is not on the same platform (e.g. GitHub instead of GitLab), it is
+necessary to redefine the `_CI_ARCHIVEURL` variable as well.
Moreover, the file contains very simple logic to test the pull request number
or branch name and apply it only in this case.
@@ -25,7 +27,7 @@ Example: `00669-maximedenes-ssr-merge.sh` containing
#!/bin/sh
if [ "$CI_PULL_REQUEST" = "669" ] || [ "$CI_BRANCH" = "ssr-merge" ]; then
- mathcomp_CI_BRANCH=ssr-merge
+ mathcomp_CI_REF=ssr-merge
mathcomp_CI_GITURL=https://github.com/maximedenes/math-comp
fi
```
diff --git a/dev/ci/user-overlays/jasongross-numeral-notation-4.sh b/dev/ci/user-overlays/jasongross-numeral-notation-4.sh
new file mode 100644
index 0000000000..76aa37d380
--- /dev/null
+++ b/dev/ci/user-overlays/jasongross-numeral-notation-4.sh
@@ -0,0 +1,5 @@
+if [ "$CI_PULL_REQUEST" = "8064" ] || [ "$CI_BRANCH" = "numeral-notation-4" ]; then
+ HoTT_CI_REF=fix-for-numeral-notations
+ HoTT_CI_GITURL=https://github.com/JasonGross/HoTT
+ HoTT_CI_ARCHIVEURL=${HoTT_CI_GITURL}/archive
+fi
diff --git a/dev/doc/build-system.dev.txt b/dev/doc/build-system.dev.txt
index abba13428f..b0a2b04121 100644
--- a/dev/doc/build-system.dev.txt
+++ b/dev/doc/build-system.dev.txt
@@ -1,5 +1,3 @@
-
-
HISTORY:
-------
@@ -35,13 +33,41 @@ HISTORY:
grammar.cma (and q_constr.cmo) directly, no need for a separate
subcall to make nor awkward include-failed-and-retry.
-
----------------------------------------------------------------------------
+* February - September 2018 (Emilio Jesús Gallego Arias)
+
+ Dune support added.
+
+ The build setup is mostly vanilla for the OCaml part, however the
+ `.v` to `.vo` compilation relies on `coq_dune` a `coqdep` wrapper
+ that will generate the necessary `dune` files.
+
+ As a developer, you should not have to deal with Dune configuration
+ files on a regular basis unless adding a new library or plugin.
+ The vanilla setup declares all the Coq libraries and binaries [we
+ must respect proper containment/module implementation rules as to
+ allow packing], and we build custom preprocessors (based on `camlp5`
+ and `coqpp`) that will process the `ml4`/`mlg` files.
+
+ This suffices to build `coqtop` and `coqide`, all that remains to
+ handle is `.vo` compilation.
+
+ To teach Dune about the `.vo`, we use a small utility `coq_dune`,
+ that will generate a `dune` file for each directory in `plugins` and
+ `theories`. The code is pretty straightforward and declares build
+ and install rules for each `.v` straight out of `coqdep`. Thus, our
+ build strategy looks like this:
+
+ 1. Use `dune` to build `coqdep` and `coq_dune`.
+ 2. Use `coq_dune` to generate `dune` files for each directory with `.v` files.
+ 3. ?
+ 4. Profit! [Seriously, at this point Dune has all the information to build Coq]
+
+---------------------------------------------------------------------------
-This file documents internals of the implementation of the build
-system. For what a Coq developer needs to know about the build system,
-see build-system.txt .
+This file documents internals of the implementation of the make-based
+build system. For what a Coq developer needs to know about the build
+system, see build-system.txt and build-system.dune.md .
.ml4 files
----------
diff --git a/dev/doc/build-system.dune.md b/dev/doc/build-system.dune.md
new file mode 100644
index 0000000000..36d5e5841b
--- /dev/null
+++ b/dev/doc/build-system.dune.md
@@ -0,0 +1,120 @@
+This file documents what a Coq developer needs to know about the
+Dune-based build system. If you want to enhance the build system
+itself (or are curious about its implementation details), see
+build-system.dev.txt, and in particular its initial HISTORY section.
+
+Quick Start
+===========
+
+You need Dune >= 1.2.1 ; just type `dune build` to build the base Coq
+libraries. No `./configure` step is needed.
+
+Dune will get confused if it finds leftovers of in-tree compilation,
+so please be sure your tree is clean from objects files generated by
+the make-based system.
+
+If you want to build the standard libraries and plugins you should
+call `make -f Makefile.dune voboot`. It is usually enough to do that
+once per-session.
+
+More helper targets are availabe in `Makefile.dune`, `make -f
+Makefile.dune` will display help.
+
+Dune
+====
+
+Coq can now be built using
+[Dune](https://github.com/ocaml/dune). Contrary to other systems,
+Dune, doesn't use a global`makefile` but local build files named
+`dune` that are later composed to form a global build.
+
+As a developer, Dune should take care of all OCaml-related build tasks
+including library management, merlin files, and link order. You are
+are not supposed to modify the `dune` files unless you are adding a
+new binary, library, or plugin.
+
+The current Dune setup also doesn't require a call to `configure`. The
+auto-generated configuration files are properly included in the
+dependency graph so it will be automatically generated by Dune with
+reasonable developer defaults. You can still override the defaults by
+manually calling `./configure`, but note that some configure options
+such as install paths are not used by Dune.
+
+Dune uses a separate directory `_build` to store build artifacts; it
+will generate an `.install` file so artifacts in the build can be
+properly installed by package managers.
+
+## Targets
+
+The default dune target is `dune build` (or `dune build @install`),
+which will scan all sources in the Coq tree and then build the whole
+project, creating an "install" overlay in `_build/install/default`.
+
+You can build some other target by doing `dune build $TARGET`.
+
+In order to build a single package, you can do `dune build
+$PACKAGE.install`. Dune also provides targets for documentation and
+testing, see below.
+
+## Developer shell
+
+You can create a developer shell with `dune utop $library`, where
+`$library` can be any directory in the current workspace. For example,
+`dune utop engine` or `dune utop plugins/ltac` will launch `utop` with
+the right libraries already loaded.
+
+Note that you must invoke the `#rectypes;;` toplevel flag in order to
+use Coq libraries. The provided `.ocamlinit` file does this
+automatically.
+
+## Compositionality, developer and release modes.
+
+By default [in "developer mode"], Dune will compose all the packages
+present in the tree and perform a global build. That means that for
+example you could drop the `ltac2` folder under `plugins` and get a
+build using `ltac2`, that will use the current Coq version.
+
+This is very useful to develop plugins and Coq libraries as your
+plugin will correctly track dependencies and rebuild incrementally as
+needed.
+
+However, it is not always desirable to go this way. For example, the
+current Coq source tree contains two packages [Coq and CoqIDE], and in
+the OPAM CoqIDE package we don't want to build CoqIDE against the
+local copy of Coq. For this purpose, Dune supports the `-p` option, so
+`dune build -p coqide` will build CoqIDE against the system-installed
+version of Coq libs.
+
+## Stanzas
+
+`dune` files contain the so-called "stanzas", that may declare:
+
+- libraries,
+- executables,
+- documentation, arbitrary blobs.
+
+The concrete options for each stanza can be seen in the Dune manual,
+but usually the default setup will work well with the current Coq
+sources. Note that declaring a library or an executable won't make it
+installed by default, for that, you need to provide a "public name".
+
+## Workspaces and Profiles
+
+Dune provides support for tree workspaces so the developer can set
+global options --- such as flags --- on all packages, or build Coq
+with different OPAM switches simultaneously [for example to test
+compatibility]; for more information, please refer to the Dune manual.
+
+## Documentation and test targets
+
+The documentation and test suite targets for Coq are still not
+implemented in Dune.
+
+## Planned and Advanced features
+
+Dune supports or will support extra functionality that may result very
+useful to Coq, some examples are:
+
+- Cross-compilation.
+- Automatic Generation of OPAM files.
+- Multi-directory libraries.
diff --git a/dev/doc/changes.md b/dev/doc/changes.md
index 1eea2443fe..fdeb0abed4 100644
--- a/dev/doc/changes.md
+++ b/dev/doc/changes.md
@@ -1,3 +1,12 @@
+## Changes between Coq 8.9 and Coq 8.10
+
+### ML API
+
+Termops:
+
+- Internal printing functions have been placed under the
+ `Termops.Internal` namespace.
+
## Changes between Coq 8.8 and Coq 8.9
### ML API
@@ -219,7 +228,7 @@ General deprecation
Proof engine
- Due to the introduction of `EConstr` in 8.7, it is not necessary to
+- Due to the introduction of `EConstr` in 8.7, it is not necessary to
track "goal evar normal form status" anymore, thus the type `'a
Proofview.Goal.t` loses its ghost argument. This may introduce some
minor incompatibilities at the typing level. Code-wise, things
diff --git a/dev/doc/critical-bugs b/dev/doc/critical-bugs
index 6166d24b70..8d78559c0d 100644
--- a/dev/doc/critical-bugs
+++ b/dev/doc/critical-bugs
@@ -109,6 +109,16 @@ Universes
GH issue number: none
risk: unlikely to be activated by chance
+ component: universe polymorphism
+ summary: universe polymorphism can capture global universes
+ impacted released versions: V8.5 to V8.8
+ impacted coqchk versions: V8.5 to current (NOT FIXED)
+ fixed in: 2385b5c1ef
+ found by: Gaëtan Gilbert
+ exploit: test-suite/misc/poly-capture-global-univs
+ GH issue number: #8341
+ risk: unlikely to be activated by chance (requires a plugin)
+
Primitive projections
component: primitive projections, guard condition
diff --git a/dev/doc/profiling.txt b/dev/doc/profiling.txt
index b5dd8445db..45766293c7 100644
--- a/dev/doc/profiling.txt
+++ b/dev/doc/profiling.txt
@@ -21,6 +21,58 @@ and plug into the process
perf record -g -p PID
+### Per-component [flame graphs](https://github.com/brendangregg/FlameGraph)
+
+I (Andres Erbsen) have found it useful to look at library-wide flame graphs of
+coq time consumption. As the Ltac interpreter stack is reflected in the OCaml
+stack, calls to the same primitive can appear on top of multiple essentially
+equivalent stacks. To make the profiles more readable, one could either try to
+edit the stack trace to merge "equivalent" frames, or simply look at the
+aggregate profile on a component-by-component basis. Here is how to do the
+second for the standard library ([example output](https://cdn.rawgit.com/andres-erbsen/b29b29cb6480dfc6a662062e4fcd0ae3/raw/304fc3fea9630c8e453929aa7920ca8a2a570d0b/stdlib_categorized_outermost.svg)).
+
+~~~~~
+#!/bin/bash
+make -f Makefile.dune clean
+make -f Makefile.dune states
+perf record -F99 `# ~1GB of data` --call-graph=dwarf -- make -f Makefile.dune world
+perf script --time '0%-100%' |
+ stackcollapse-perf.pl |
+ grep Coqtop__compile |
+ sed -rf <(cat <<'EOF'
+ s/;caml/;/g
+ s/_[0-9]*;/;/g
+ s/Logic_monad__fun;//g
+ s/_apply[0-9];//g
+ s/;System/@&@/
+ s/;Hashcons/@&@/
+ s/;Grammar/@&@/
+ s/;Declaremods/@&@/
+ s/;Tactics/@&@/
+ s/;Pretyping/@&@/
+ s/;Typeops/@&@/
+ s/;Reduction/@&@/
+ s/;Unification/@&@/
+ s/;Evarutil/@&@/
+ s/;Evd/@&@/
+ s/;EConstr/@&@/
+ s/;Constr/@&@/
+ s/;Univ/@&@/
+ s/;Ugraph/@&@/
+ s/;UState/@&@/
+ s/;Micromega/@&@/
+ s/;Omega/@&@/
+ s/;Auto/@&@/
+ s/;Ltac_plugin__Tacinterp/@&@/
+ s/;Ltac_plugin__Rewrite/@&@/
+ s/[^@]*@;([^@]*)@/\1;\1/
+ s/@//g
+ :a; s/;([^;]+);\1;/;\1;/g;ta
+EOF
+ ) |
+ flamegraph.pl
+~~~~~
+
## Memory
You first need a few commits atop trunk for this to work.
diff --git a/dev/ocamldebug-coq.run b/dev/ocamldebug-coq.run
index bccd3fefb4..85bb04efe0 100644
--- a/dev/ocamldebug-coq.run
+++ b/dev/ocamldebug-coq.run
@@ -37,7 +37,7 @@ if [ -z "$GUESS_CHECKER" ]; then
-I $COQTOP/plugins/funind -I $COQTOP/plugins/groebner \
-I $COQTOP/plugins/interface -I $COQTOP/plugins/micromega \
-I $COQTOP/plugins/omega -I $COQTOP/plugins/quote \
- -I $COQTOP/plugins/ring -I $COQTOP/plugins/romega \
+ -I $COQTOP/plugins/ring \
-I $COQTOP/plugins/rtauto -I $COQTOP/plugins/setoid_ring \
-I $COQTOP/plugins/subtac -I $COQTOP/plugins/syntax \
-I $COQTOP/plugins/xml -I $COQTOP/plugins/ltac \
diff --git a/dev/top_printers.ml b/dev/top_printers.ml
index ab679a71ce..e15fd776b2 100644
--- a/dev/top_printers.ml
+++ b/dev/top_printers.ml
@@ -64,8 +64,14 @@ let ppwf_paths x = pp (Rtree.pp_tree prrecarg x)
let envpp pp = let sigma,env = Pfedit.get_current_context () in pp env sigma
let rawdebug = ref false
let ppevar evk = pp (Evar.print evk)
-let ppconstr x = pp (Termops.print_constr (EConstr.of_constr x))
-let ppeconstr x = pp (Termops.print_constr x)
+let pr_constr t =
+ let sigma, env = Pfedit.get_current_context () in
+ Printer.pr_constr_env env sigma t
+let pr_econstr t =
+ let sigma, env = Pfedit.get_current_context () in
+ Printer.pr_econstr_env env sigma t
+let ppconstr x = pp (pr_constr x)
+let ppeconstr x = pp (pr_econstr x)
let ppconstr_expr x = pp (Ppconstr.pr_constr_expr x)
let ppsconstr x = ppconstr (Mod_subst.force_constr x)
let ppconstr_univ x = Constrextern.with_universes ppconstr x
@@ -95,9 +101,9 @@ let ppidmapgen l = pp (pridmapgen l)
let ppevarsubst = ppidmap (fun id0 -> prset (fun (c,copt,id) ->
hov 0
- (Termops.print_constr (EConstr.of_constr c) ++
+ (pr_constr c ++
(match copt with None -> mt () | Some c -> spc () ++ str "<expanded: " ++
- Termops.print_constr (EConstr.of_constr c) ++ str">") ++
+ pr_constr c ++ str">") ++
(if id = id0 then mt ()
else spc () ++ str "<canonical: " ++ Id.print id ++ str ">"))))
@@ -106,7 +112,7 @@ let ppididmap = ppidmap (fun _ -> Id.print)
let prconstrunderbindersidmap = pridmap (fun _ (l,c) ->
hov 1 (str"[" ++ prlist_with_sep spc Id.print l ++ str"]")
- ++ str "," ++ spc () ++ Termops.print_constr c)
+ ++ str "," ++ spc () ++ pr_econstr c)
let ppconstrunderbindersidmap l = pp (prconstrunderbindersidmap l)
@@ -133,7 +139,7 @@ let safe_pr_global = function
| ConstRef kn -> pp (str "CONSTREF(" ++ Constant.debug_print kn ++ str ")")
| IndRef (kn,i) -> pp (str "INDREF(" ++ MutInd.debug_print kn ++ str "," ++
int i ++ str ")")
- | ConstructRef ((kn,i),j) -> pp (str "INDREF(" ++ MutInd.debug_print kn ++ str "," ++
+ | ConstructRef ((kn,i),j) -> pp (str "CONSTRUCTREF(" ++ MutInd.debug_print kn ++ str "," ++
int i ++ str "," ++ int j ++ str ")")
| VarRef id -> pp (str "VARREF(" ++ Id.print id ++ str ")")
@@ -155,9 +161,9 @@ let ppdelta s = pp (Mod_subst.debug_pr_delta s)
let pp_idpred s = pp (pr_idpred s)
let pp_cpred s = pp (pr_cpred s)
let pp_transparent_state s = pp (pr_transparent_state s)
-let pp_stack_t n = pp (Reductionops.Stack.pr (EConstr.of_constr %> Termops.print_constr) n)
-let pp_cst_stack_t n = pp (Reductionops.Cst_stack.pr n)
-let pp_state_t n = pp (Reductionops.pr_state n)
+let pp_stack_t n = pp (Reductionops.Stack.pr (EConstr.of_constr %> pr_econstr) n)
+let pp_cst_stack_t n = pp (Reductionops.Cst_stack.pr Global.(env()) Evd.empty n)
+let pp_state_t n = pp (Reductionops.pr_state Global.(env()) Evd.empty n)
(* proof printers *)
let pr_evar ev = Pp.int (Evar.repr ev)
diff --git a/dev/v8-syntax/syntax-v8.tex b/dev/v8-syntax/syntax-v8.tex
index 6b7960c92f..dd3908c25f 100644
--- a/dev/v8-syntax/syntax-v8.tex
+++ b/dev/v8-syntax/syntax-v8.tex
@@ -765,8 +765,6 @@ Conflicts exists between integers and constrs.
%% plugins/ring
\nlsep \TERM{quote}~\NT{ident}~\OPTGR{\KWD{[}~\PLUS{\NT{ident}}~\KWD{]}}
\nlsep \TERM{ring}~\STAR{\tacconstr}
-%% plugins/romega
-\nlsep \TERM{romega}
\SEPDEF
\DEFNT{orient}
\KWD{$\rightarrow$}~\mid~\KWD{$\leftarrow$}
diff --git a/dev/vm_printers.ml b/dev/vm_printers.ml
index 98190b05b5..ea126e2756 100644
--- a/dev/vm_printers.ml
+++ b/dev/vm_printers.ml
@@ -2,7 +2,6 @@ open Format
open Term
open Constr
open Names
-open Cbytecodes
open Cemitcodes
open Vmvalues
@@ -11,7 +10,7 @@ let ppripos (ri,pos) =
| Reloc_annot a ->
let sp,i = a.ci.ci_ind in
print_string
- ("annot : MutInd("^(MutInd.to_string sp)^","^(string_of_int i)^")\n")
+ ("annot : MutInd("^(MutInd.to_string sp)^","^(string_of_int i)^")\n")
| Reloc_const _ ->
print_string "structured constant\n"
| Reloc_getglobal kn ->
diff --git a/doc/README.md b/doc/README.md
index 6c6e1f01fb..3db1261656 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -9,8 +9,8 @@ The Coq documentation includes
The documentation of the latest released version is available on the Coq
web site at [coq.inria.fr/documentation](http://coq.inria.fr/documentation).
-Additionnally, you can view the documentation for the current master version at
-<https://gitlab.com/coq/coq/-/jobs/artifacts/master/file/_install_ci/share/doc/coq/sphinx/html/index.html?job=documentation>.
+Additionally, you can view the documentation for the current master version at
+<https://gitlab.com/coq/coq/-/jobs/artifacts/master/file/_install_ci/share/doc/coq/sphinx/html/index.html?job=doc:refman>.
The reference manual is written is reStructuredText and compiled
using Sphinx. See [`sphinx/README.rst`](sphinx/README.rst)
@@ -28,18 +28,18 @@ To produce the complete documentation in HTML, you will need Coq dependencies
listed in [`INSTALL`](../INSTALL). Additionally, the Sphinx-based
reference manual requires Python 3, and the following Python packages:
- sphinx sphinx_rtd_theme beautifulsoup4 antlr4-python3-runtime pexpect sphinxcontrib-bibtex
+ - sphinx >= 1.7.8
+ - sphinx_rtd_theme >= 0.2.5b2
+ - beautifulsoup4 >= 4.0.6
+ - antlr4-python3-runtime >= 4.7.1
+ - pexpect >= 4.2.1
+ - sphinxcontrib-bibtex >= 0.4.0
-You can install them using `pip3 install` or using your distribution's package
-manager. E.g. under recent Debian-based operating systems (Debian 10 "Buster",
-Ubuntu 18.04, ...) you can use:
+To install them, you should first install pip and setuptools (for instance,
+with `apt install python3-pip python3-setuptools` on Debian / Ubuntu) then run:
- apt install python3-sphinx python3-pexpect python3-sphinx-rtd-theme \
- python3-bs4 python3-sphinxcontrib.bibtex python3-pip
-
-Then, install the missing Python3 Antlr4 package:
-
- pip3 install antlr4-python3-runtime
+ pip3 install sphinx sphinx_rtd_theme beautifulsoup4 antlr4-python3-runtime \
+ pexpect sphinxcontrib-bibtex
Nix users should get the correct development environment to build the
HTML documentation from Coq's [`default.nix`](../default.nix) (note this
@@ -54,10 +54,19 @@ additional tools are required:
- pdflatex
- dvips
- makeindex
+ - xelatex
+ - latexmk
+ - xindy
+
+All of them are part of the TexLive distribution. E.g. on Debian / Ubuntu,
+install them with:
+
+ apt install texlive-full
-Install them using your package manager. E.g. on Debian / Ubuntu:
+Or if you want to use less disk space:
- apt install texlive-latex-extra texlive-fonts-recommended
+ apt install texlive-latex-extra texlive-fonts-recommended texlive-xetex \
+ latexmk xindy
Compilation
-----------
@@ -79,8 +88,11 @@ Alternatively, you can use some specific targets:
- `make doc-html`
to produce all HTML documents
-- `make sphinx`
- to produce the HTML version of the reference manual
+- `make refman`
+ to produce the HTML and PDF versions of the reference manual
+
+- `make refman-{html,pdf}`
+ to produce only one format of the reference manual
- `make stdlib`
to produce all formats of the Coq standard library
@@ -89,6 +101,18 @@ Alternatively, you can use some specific targets:
Also note the `-with-doc yes` option of `./configure` to enable the
build of the documentation as part of the default make target.
+If you're editing Sphinx documentation, set SPHINXWARNERROR to 0
+to avoid treating Sphinx warnings as errors. Otherwise, Sphinx quits
+upon detecting the first warning. You can set this on the Sphinx `make`
+command line or as an environment variable:
+
+- `make refman SPHINXWARNERROR=0`
+
+- ~~~
+ export SPHINXWARNERROR=0
+ ⋮
+ make refman
+ ~~~
Installation
------------
diff --git a/doc/sphinx/README.rst b/doc/sphinx/README.rst
index 1643baf0e8..01240a062c 100644
--- a/doc/sphinx/README.rst
+++ b/doc/sphinx/README.rst
@@ -32,7 +32,7 @@ Names (link targets) are auto-generated for most simple objects, though they can
- Vernacs (commands) have their name set to the first word of their signature. For example, the auto-generated name of ``Axiom @ident : @term`` is ``Axiom``, and a link to it would take the form ``:cmd:`Axiom```.
- Vernac variants, tactic notations, and tactic variants do not have a default name.
-Most objects should have a body (i.e. a block of indented text following the signature, called “contents” in Sphinx terms). Undocumented objects should have the `:undocumented:` flag instead, as shown above. When multiple objects have a single description, they can be grouped into a single object, like this (semicolons can be used to separate the names of the objects)::
+Most objects should have a body (i.e. a block of indented text following the signature, called “contents” in Sphinx terms). Undocumented objects should have the `:undocumented:` flag instead, as shown above. When multiple objects have a single description, they can be grouped into a single object, like this (semicolons can be used to separate the names of the objects; names starting with ``_`` will be omitted from the indexes)::
.. cmdv:: Lemma @ident {? @binders} : @type
Remark @ident {? @binders} : @type
@@ -114,15 +114,24 @@ Here is the list of all objects of the Coq domain (The symbol :black_nib: indica
Raised if :n:`@tactic` does not fully solve the goal.
-``.. opt::`` :black_nib: A Coq option.
+``.. flag::`` :black_nib: A Coq flag (i.e. a boolean setting).
Example::
- .. opt:: Nonrecursive Elimination Schemes
+ .. flag:: Nonrecursive Elimination Schemes
- This option controls whether types declared with the keywords
- :cmd:`Variant` and :cmd:`Record` get an automatic declaration of the
+ Controls whether types declared with the keywords
+ :cmd:`Variant` and :cmd:`Record` get an automatic declaration of
induction principles.
+``.. opt::`` :black_nib: A Coq option (a setting with non-boolean value, e.g. a string or numeric value).
+ Example::
+
+ .. opt:: Hyps Limit @num
+ :name Hyps Limit
+
+ Controls the maximum number of hypotheses displayed in goals after
+ application of a tactic.
+
``.. prodn::`` A grammar production.
This is useful if you intend to document individual grammar productions.
Otherwise, use Sphinx's `production lists
@@ -141,6 +150,14 @@ Here is the list of all objects of the Coq domain (The symbol :black_nib: indica
.. prodn:: term += let: @pattern := @term in @term
.. prodn:: occ_switch ::= { {? + %| - } {* @num } }
+``.. table::`` :black_nib: A Coq table, i.e. a setting that is a set of values.
+ Example::
+
+ .. table:: Search Blacklist @string
+ :name: Search Blacklist
+
+ Controls ...
+
``.. tacn::`` :black_nib: A tactic, or a tactic notation.
Example::
@@ -202,6 +219,9 @@ In addition to the objects above, the ``coqrst`` Sphinx plugin defines the follo
Print nat.
Definition a := 1.
+ The blank line after the directive is required. If you begin a proof,
+ include an ``Abort`` afterwards to reset coqtop for the next example.
+
Here is a list of permissible options:
- Display options
@@ -260,8 +280,8 @@ In addition to the objects above, the ``coqrst`` Sphinx plugin defines the follo
.. inference:: name
- newline-separated premisses
- ------------------------
+ newline-separated premises
+ --------------------------
conclusion
Example::
@@ -274,14 +294,14 @@ In addition to the objects above, the ``coqrst`` Sphinx plugin defines the follo
-----------------------------
\WTEG{\forall~x:T,U}{\Prop}
-``.. preamble::`` A reST directive for hidden math.
- Mostly useful to let MathJax know about `\def`\ s and `\newcommand`\ s.
-
- Example::
+``.. preamble::`` A reST directive to include a TeX file.
+ Mostly useful to let MathJax know about `\def`s and `\newcommand`s. The
+ contents of the TeX file are wrapped in a math environment, as MathJax
+ doesn't process LaTeX definitions otherwise.
- .. preamble::
+ Usage::
- \newcommand{\paren}[#1]{\left(#1\right)}
+ .. preamble:: preamble.tex
Coq roles
=========
@@ -303,7 +323,7 @@ In addition to the objects and directives above, the ``coqrst`` Sphinx plugin de
it names the introduced hypothesis :token:`ident`.
Note that this example also uses ``:token:``. That's because ``ident`` is
- defined in the the Coq manual as a grammar production, and ``:token:``
+ defined in the Coq manual as a grammar production, and ``:token:``
creates a link to that. When referring to a placeholder that happens to be
a grammar production, ``:token:`…``` is typically preferable to ``:n:`@…```.
@@ -364,6 +384,32 @@ DON'T
This is equivalent to ``Axiom`` :token`ident` : :token:`term`.
+..
+
+DO
+ .. code::
+
+ :n:`power_tac @term [@ltac]`
+ allows :tacn:`ring` and :tacn:`ring_simplify` to recognize …
+
+DON'T
+ .. code::
+
+ power_tac :n:`@term` [:n:`@ltac`]
+ allows :tacn:`ring` and :tacn:`ring_simplify` to recognize …
+
+..
+
+DO
+ .. code::
+
+ :n:`name={*; attr}`
+
+DON'T
+ .. code::
+
+ ``name=``:n:`{*; attr}`
+
Omitting annotations
--------------------
@@ -377,6 +423,86 @@ DON'T
.. tacv:: assert form as intro_pattern
+Using the ``.. coqtop::`` directive for syntax highlighting
+-----------------------------------------------------------
+
+DO
+ .. code::
+
+ A tactic of the form:
+
+ .. coqdoc::
+
+ do [ t1 | … | tn ].
+
+ is equivalent to the standard Ltac expression:
+
+ .. coqdoc::
+
+ first [ t1 | … | tn ].
+
+DON'T
+ .. code::
+
+ A tactic of the form:
+
+ .. coqtop:: in
+
+ do [ t1 | … | tn ].
+
+ is equivalent to the standard Ltac expression:
+
+ .. coqtop:: in
+
+ first [ t1 | … | tn ].
+
+Overusing plain quotes
+----------------------
+
+DO
+ .. code::
+
+ The :tacn:`refine` tactic can raise the :exn:`Invalid argument` exception.
+ The term :g:`let a = 1 in a a` is ill-typed.
+
+DON'T
+ .. code::
+
+ The ``refine`` tactic can raise the ``Invalid argument`` exception.
+ The term ``let a = 1 in a a`` is ill-typed.
+
+Plain quotes produce plain text, without highlighting or cross-references.
+
+Overusing the ``example`` directive
+-----------------------------------
+
+DO
+ .. code::
+
+ Here is a useful axiom:
+
+ .. coqdoc::
+
+ Axiom proof_irrelevance : forall (P : Prop) (x y : P), x=y.
+
+DO
+ .. code::
+
+ .. example:: Using proof-irrelevance
+
+ If you assume the axiom above, …
+
+DON'T
+ .. code::
+
+ Here is a useful axiom:
+
+ .. example::
+
+ .. coqdoc::
+
+ Axiom proof_irrelevance : forall (P : Prop) (x y : P), x=y.
+
Tips and tricks
===============
@@ -398,7 +524,7 @@ Add either ``undo`` to the first block or ``reset`` to the second block to avoid
Abbreviations and macros
------------------------
-Abbreviations and placeholders for specially-formatted names (like ``|Cic|``, ``|Coq|``, ``|CoqIDE|``, ``|Ltac|``, and ``|Gallina|``) are defined in a `separate file </doc/sphinx/replaces.rst>`_ included by most chapters of the manual. Some useful LaTeX macros are defined in `</doc/sphinx/preamble.rst>`_.
+Substitutions for specially-formatted names (like ``|Cic|``, ``|Coq|``, ``|CoqIDE|``, ``|Ltac|``, and ``|Gallina|``), along with some useful LaTeX macros, are defined in a `separate file </doc/sphinx/refman-preamble.rst>`_. This file is automatically included in all manual pages.
Emacs
-----
diff --git a/doc/sphinx/README.template.rst b/doc/sphinx/README.template.rst
index f1d2541eb6..86914a71df 100644
--- a/doc/sphinx/README.template.rst
+++ b/doc/sphinx/README.template.rst
@@ -32,7 +32,7 @@ Names (link targets) are auto-generated for most simple objects, though they can
- Vernacs (commands) have their name set to the first word of their signature. For example, the auto-generated name of ``Axiom @ident : @term`` is ``Axiom``, and a link to it would take the form ``:cmd:`Axiom```.
- Vernac variants, tactic notations, and tactic variants do not have a default name.
-Most objects should have a body (i.e. a block of indented text following the signature, called “contents” in Sphinx terms). Undocumented objects should have the `:undocumented:` flag instead, as shown above. When multiple objects have a single description, they can be grouped into a single object, like this (semicolons can be used to separate the names of the objects)::
+Most objects should have a body (i.e. a block of indented text following the signature, called “contents” in Sphinx terms). Undocumented objects should have the `:undocumented:` flag instead, as shown above. When multiple objects have a single description, they can be grouped into a single object, like this (semicolons can be used to separate the names of the objects; names starting with ``_`` will be omitted from the indexes)::
.. cmdv:: Lemma @ident {? @binders} : @type
Remark @ident {? @binders} : @type
@@ -140,6 +140,32 @@ DON'T
This is equivalent to ``Axiom`` :token`ident` : :token:`term`.
+..
+
+DO
+ .. code::
+
+ :n:`power_tac @term [@ltac]`
+ allows :tacn:`ring` and :tacn:`ring_simplify` to recognize …
+
+DON'T
+ .. code::
+
+ power_tac :n:`@term` [:n:`@ltac`]
+ allows :tacn:`ring` and :tacn:`ring_simplify` to recognize …
+
+..
+
+DO
+ .. code::
+
+ :n:`name={*; attr}`
+
+DON'T
+ .. code::
+
+ ``name=``:n:`{*; attr}`
+
Omitting annotations
--------------------
@@ -153,6 +179,86 @@ DON'T
.. tacv:: assert form as intro_pattern
+Using the ``.. coqtop::`` directive for syntax highlighting
+-----------------------------------------------------------
+
+DO
+ .. code::
+
+ A tactic of the form:
+
+ .. coqdoc::
+
+ do [ t1 | … | tn ].
+
+ is equivalent to the standard Ltac expression:
+
+ .. coqdoc::
+
+ first [ t1 | … | tn ].
+
+DON'T
+ .. code::
+
+ A tactic of the form:
+
+ .. coqtop:: in
+
+ do [ t1 | … | tn ].
+
+ is equivalent to the standard Ltac expression:
+
+ .. coqtop:: in
+
+ first [ t1 | … | tn ].
+
+Overusing plain quotes
+----------------------
+
+DO
+ .. code::
+
+ The :tacn:`refine` tactic can raise the :exn:`Invalid argument` exception.
+ The term :g:`let a = 1 in a a` is ill-typed.
+
+DON'T
+ .. code::
+
+ The ``refine`` tactic can raise the ``Invalid argument`` exception.
+ The term ``let a = 1 in a a`` is ill-typed.
+
+Plain quotes produce plain text, without highlighting or cross-references.
+
+Overusing the ``example`` directive
+-----------------------------------
+
+DO
+ .. code::
+
+ Here is a useful axiom:
+
+ .. coqdoc::
+
+ Axiom proof_irrelevance : forall (P : Prop) (x y : P), x=y.
+
+DO
+ .. code::
+
+ .. example:: Using proof-irrelevance
+
+ If you assume the axiom above, …
+
+DON'T
+ .. code::
+
+ Here is a useful axiom:
+
+ .. example::
+
+ .. coqdoc::
+
+ Axiom proof_irrelevance : forall (P : Prop) (x y : P), x=y.
+
Tips and tricks
===============
@@ -174,7 +280,7 @@ Add either ``undo`` to the first block or ``reset`` to the second block to avoid
Abbreviations and macros
------------------------
-Abbreviations and placeholders for specially-formatted names (like ``|Cic|``, ``|Coq|``, ``|CoqIDE|``, ``|Ltac|``, and ``|Gallina|``) are defined in a `separate file </doc/sphinx/replaces.rst>`_ included by most chapters of the manual. Some useful LaTeX macros are defined in `</doc/sphinx/preamble.rst>`_.
+Substitutions for specially-formatted names (like ``|Cic|``, ``|Coq|``, ``|CoqIDE|``, ``|Ltac|``, and ``|Gallina|``), along with some useful LaTeX macros, are defined in a `separate file </doc/sphinx/refman-preamble.rst>`_. This file is automatically included in all manual pages.
Emacs
-----
diff --git a/doc/sphinx/_static/diffs-coqide-compacted.png b/doc/sphinx/_static/diffs-coqide-compacted.png
new file mode 100644
index 0000000000..b64ffeb269
--- /dev/null
+++ b/doc/sphinx/_static/diffs-coqide-compacted.png
Binary files differ
diff --git a/doc/sphinx/_static/diffs-coqide-multigoal.png b/doc/sphinx/_static/diffs-coqide-multigoal.png
new file mode 100644
index 0000000000..4020279267
--- /dev/null
+++ b/doc/sphinx/_static/diffs-coqide-multigoal.png
Binary files differ
diff --git a/doc/sphinx/_static/diffs-coqide-on.png b/doc/sphinx/_static/diffs-coqide-on.png
new file mode 100644
index 0000000000..f270397ea3
--- /dev/null
+++ b/doc/sphinx/_static/diffs-coqide-on.png
Binary files differ
diff --git a/doc/sphinx/_static/diffs-coqide-removed.png b/doc/sphinx/_static/diffs-coqide-removed.png
new file mode 100644
index 0000000000..8f2e71fdc8
--- /dev/null
+++ b/doc/sphinx/_static/diffs-coqide-removed.png
Binary files differ
diff --git a/doc/sphinx/_static/diffs-coqtop-compacted.png b/doc/sphinx/_static/diffs-coqtop-compacted.png
new file mode 100644
index 0000000000..b37f0a6771
--- /dev/null
+++ b/doc/sphinx/_static/diffs-coqtop-compacted.png
Binary files differ
diff --git a/doc/sphinx/_static/diffs-coqtop-multigoal.png b/doc/sphinx/_static/diffs-coqtop-multigoal.png
new file mode 100644
index 0000000000..cfedde02ac
--- /dev/null
+++ b/doc/sphinx/_static/diffs-coqtop-multigoal.png
Binary files differ
diff --git a/doc/sphinx/_static/diffs-coqtop-on.png b/doc/sphinx/_static/diffs-coqtop-on.png
new file mode 100644
index 0000000000..bdfcf0af1a
--- /dev/null
+++ b/doc/sphinx/_static/diffs-coqtop-on.png
Binary files differ
diff --git a/doc/sphinx/_static/diffs-coqtop-on3.png b/doc/sphinx/_static/diffs-coqtop-on3.png
new file mode 100644
index 0000000000..63ff869432
--- /dev/null
+++ b/doc/sphinx/_static/diffs-coqtop-on3.png
Binary files differ
diff --git a/doc/sphinx/addendum/canonical-structures.rst b/doc/sphinx/addendum/canonical-structures.rst
index 3af3115a59..3e414a714c 100644
--- a/doc/sphinx/addendum/canonical-structures.rst
+++ b/doc/sphinx/addendum/canonical-structures.rst
@@ -1,4 +1,3 @@
-.. include:: ../replaces.rst
.. _canonicalstructures:
Canonical Structures
@@ -75,7 +74,7 @@ We amend that by equipping ``nat`` with a comparison relation.
Check 3 == 3.
Eval compute in 3 == 4.
-This last test shows that |Coq| is now not only able to typecheck ``3 == 3``,
+This last test shows that |Coq| is now not only able to type check ``3 == 3``,
but also that the infix relation was bound to the ``nat_eq`` relation.
This relation is selected whenever ``==`` is used on terms of type nat.
This can be read in the line declaring the canonical structure
diff --git a/doc/sphinx/addendum/extended-pattern-matching.rst b/doc/sphinx/addendum/extended-pattern-matching.rst
index f7fd4b9146..cb267576b2 100644
--- a/doc/sphinx/addendum/extended-pattern-matching.rst
+++ b/doc/sphinx/addendum/extended-pattern-matching.rst
@@ -1,15 +1,13 @@
-.. include:: ../replaces.rst
-
.. _extendedpatternmatching:
-Extended pattern-matching
+Extended pattern matching
=========================
:Authors: Cristina Cornes and Hugo Herbelin
.. TODO links to figures
-This section describes the full form of pattern-matching in |Coq| terms.
+This section describes the full form of pattern matching in |Coq| terms.
.. |rhs| replace:: right hand sides
@@ -38,7 +36,7 @@ same values as ``pattern`` does and ``identifier`` is bound to the matched
value. A pattern of the form :n:`pattern | pattern` is called disjunctive. A
list of patterns separated with commas is also considered as a pattern
and is called *multiple pattern*. However multiple patterns can only
-occur at the root of pattern-matching equations. Disjunctions of
+occur at the root of pattern matching equations. Disjunctions of
*multiple patterns* are allowed though.
Since extended ``match`` expressions are compiled into the primitive ones,
@@ -46,7 +44,7 @@ the expressiveness of the theory remains the same. Once parsing has finished
only simple patterns remain. The original nesting of the ``match`` expressions
is recovered at printing time. An easy way to see the result
of the expansion is to toggle off the nesting performed at printing
-(use here :opt:`Printing Matching`), then by printing the term with :cmd:`Print`
+(use here :flag:`Printing Matching`), then by printing the term with :cmd:`Print`
if the term is a constant, or using the command :cmd:`Check`.
The extended ``match`` still accepts an optional *elimination predicate*
@@ -88,7 +86,7 @@ Using multiple patterns in the definition of ``max`` lets us write:
which will be compiled into the previous form.
-The pattern-matching compilation strategy examines patterns from left
+The pattern matching compilation strategy examines patterns from left
to right. A match expression is generated **only** when there is at least
one constructor in the column of patterns. E.g. the following example
does not build a match expression.
@@ -262,9 +260,9 @@ When we use parameters in patterns there is an error message:
| cons A _ l' => l'
end).
-.. opt:: Asymmetric Patterns
+.. flag:: Asymmetric Patterns
-This option (off by default) removes parameters from constructors in patterns:
+ This flag (off by default) removes parameters from constructors in patterns:
.. coqtop:: all
@@ -407,12 +405,11 @@ length, by writing
.. coqtop:: in
- Fixpoint concat (n:nat) (l:listn n) (m:nat) (l':listn m) {struct l} :
- listn (n + m) :=
- match l in listn n, l' return listn (n + m) with
- | niln, x => x
- | consn n' a y, x => consn (n' + m) a (concat n' y m x)
- end.
+ Check (fun n (a b: listn n) =>
+ match a, b with
+ | niln, b0 => tt
+ | consn n' a y, bS => tt
+ end).
we have a copy of :g:`b` in type :g:`listn 0` resp. :g:`listn (S n')`.
@@ -598,7 +595,7 @@ situation:
incorrect (because constructors are not applied to the correct number of the
arguments, because they are not linear or they are wrongly typed).
-.. exn:: Non exhaustive pattern-matching.
+.. exn:: Non exhaustive pattern matching.
The pattern matching is not exhaustive.
diff --git a/doc/sphinx/addendum/extraction.rst b/doc/sphinx/addendum/extraction.rst
index 8c1eacf085..3d58f522dd 100644
--- a/doc/sphinx/addendum/extraction.rst
+++ b/doc/sphinx/addendum/extraction.rst
@@ -1,5 +1,3 @@
-.. include:: ../replaces.rst
-
.. _extraction:
Extraction of programs in |OCaml| and Haskell
@@ -131,14 +129,14 @@ order to produce more readable code.
The type-preserving optimizations are controlled by the following |Coq| options:
-.. opt:: Extraction Optimize
+.. flag:: Extraction Optimize
Default is on. This controls all type-preserving optimizations made on
the ML terms (mostly reduction of dummy beta/iota redexes, but also
simplifications on Cases, etc). Turn this option off if you want a
ML term as close as possible to the Coq term.
-.. opt:: Extraction Conservative Types
+.. flag:: Extraction Conservative Types
Default is off. This controls the non type-preserving optimizations
made on ML terms (which try to avoid function abstraction of dummy
@@ -146,7 +144,7 @@ The type-preserving optimizations are controlled by the following |Coq| options:
implies that ``e':t'`` where ``e'`` and ``t'`` are the extracted
code of ``e`` and ``t`` respectively.
-.. opt:: Extraction KeepSingleton
+.. flag:: Extraction KeepSingleton
Default is off. Normally, when the extraction of an inductive type
produces a singleton type (i.e. a type with only one constructor, and
@@ -155,7 +153,7 @@ The type-preserving optimizations are controlled by the following |Coq| options:
The typical example is ``sig``. This option allows disabling this
optimization when one wishes to preserve the inductive structure of types.
-.. opt:: Extraction AutoInline
+.. flag:: Extraction AutoInline
Default is on. The extraction mechanism inlines the bodies of
some defined constants, according to some heuristics
@@ -227,7 +225,7 @@ When an actual extraction takes place, an error is normally raised if the
if any of the implicit arguments still occurs in the final code.
This behavior can be relaxed via the following option:
-.. opt:: Extraction SafeImplicits
+.. flag:: Extraction SafeImplicits
Default is on. When this option is off, a warning is emitted
instead of an error if some implicit arguments still occur in the
@@ -319,15 +317,15 @@ native boolean type instead of the |Coq| one. The syntax is the following:
extractions for the type itself (first `string`) and all its
constructors (all the `string` between square brackets). In this form,
the ML extraction must be an ML inductive datatype, and the native
- pattern-matching of the language will be used.
+ pattern matching of the language will be used.
.. cmdv:: Extract Inductive @qualid => @string [ {+ @string } ] @string
Same as before, with a final extra `string` that indicates how to
- perform pattern-matching over this inductive type. In this form,
+ perform pattern matching over this inductive type. In this form,
the ML extraction could be an arbitrary type.
For an inductive type with `k` constructors, the function used to
- emulate the pattern-matching should expect `(k+1)` arguments, first the `k`
+ emulate the pattern matching should expect `(k+1)` arguments, first the `k`
branches in functional form, and then the inductive element to
destruct. For instance, the match branch ``| S n => foo`` gives the
functional form ``(fun n -> foo)``. Note that a constructor with no
@@ -344,7 +342,7 @@ native boolean type instead of the |Coq| one. The syntax is the following:
* Extracting an inductive type to a pre-existing ML inductive type
is quite sound. But extracting to a general type (by providing an
- ad-hoc pattern-matching) will often **not** be fully rigorously
+ ad-hoc pattern matching) will often **not** be fully rigorously
correct. For instance, when extracting ``nat`` to |OCaml| ``int``,
it is theoretically possible to build ``nat`` values that are
larger than |OCaml| ``max_int``. It is the user's responsibility to
@@ -423,7 +421,7 @@ a generic type ``'a`` to any term.
First, if some part of the program is *very* polymorphic, there
may be no ML type for it. In that case the extraction to ML works
alright but the generated code may be refused by the ML
-type-checker. A very well known example is the ``distr-pair``
+type checker. A very well known example is the ``distr-pair``
function:
.. coqtop:: in
@@ -458,7 +456,7 @@ In |OCaml|, we must cast any argument of the constructor dummy
Even with those unsafe castings, you should never get error like
``segmentation fault``. In fact even if your program may seem
-ill-typed to the |OCaml| type-checker, it can't go wrong : it comes
+ill-typed to the |OCaml| type checker, it can't go wrong : it comes
from a Coq well-typed terms, so for example inductive types will always
have the correct number of arguments, etc. Of course, when launching
manually some extracted function, you should apply it to arguments
@@ -469,7 +467,7 @@ found in :cite:`Let02`.
We have to say, though, that in most "realistic" programs, these problems do not
occur. For example all the programs of Coq library are accepted by the |OCaml|
-type-checker without any ``Obj.magic`` (see examples below).
+type checker without any ``Obj.magic`` (see examples below).
Some examples
-------------
diff --git a/doc/sphinx/addendum/generalized-rewriting.rst b/doc/sphinx/addendum/generalized-rewriting.rst
index c7df250672..403b163196 100644
--- a/doc/sphinx/addendum/generalized-rewriting.rst
+++ b/doc/sphinx/addendum/generalized-rewriting.rst
@@ -1,6 +1,3 @@
-.. include:: ../preamble.rst
-.. include:: ../replaces.rst
-
.. _generalizedrewriting:
Generalized rewriting
@@ -22,18 +19,18 @@ The new implementation is a drop-in replacement for the old one
[#tabareau]_, hence most of the documentation still applies.
The work is a complete rewrite of the previous implementation, based
-on the type class infrastructure. It also improves on and generalizes
+on the typeclass infrastructure. It also improves on and generalizes
the previous implementation in several ways:
+ User-extensible algorithm. The algorithm is separated into two parts:
generation of the rewriting constraints (written in ML) and solving
- these constraints using type class resolution. As type class
+ these constraints using typeclass resolution. As typeclass
resolution is extensible using tactics, this allows users to define
general ways to solve morphism constraints.
+ Subrelations. An example extension to the base algorithm is the
ability to define one relation as a subrelation of another so that
morphism declarations on one relation can be used automatically for
- the other. This is done purely using tactics and type class search.
+ the other. This is done purely using tactics and typeclass search.
+ Rewriting under binders. It is possible to rewrite under binders in
the new implementation, if one provides the proper morphisms. Again,
most of the work is handled in the tactics.
@@ -126,10 +123,10 @@ parameters is any term :math:`f \, t_1 \ldots t_n`.
.. coqtop:: in
- forall (A : Type) (S1 S1’ S2 S2’ : list A),
- set_eq A S1 S1’ ->
- set_eq A S2 S2’ ->
- set_eq A (union A S1 S2) (union A S1’ S2’).
+ forall (A: Type) (S1 S1' S2 S2': list A),
+ set_eq A S1 S1' ->
+ set_eq A S2 S2' ->
+ set_eq A (union A S1 S2) (union A S1' S2').
The signature of the function ``union A`` is ``set_eq A ==> set_eq A ==> set_eq A``
for all ``A``.
@@ -226,7 +223,7 @@ following command.
This command declares ``f`` as a parametric morphism of signature ``sig``. The
identifier :token:`ident` gives a unique name to the morphism and it is used as
- the base name of the type class instance definition and as the name of
+ the base name of the typeclass instance definition and as the name of
the lemma that proves the well-definedness of the morphism. The
parameters of the morphism as well as the signature may refer to the
context of variables. The command asks the user to prove interactively
@@ -309,7 +306,7 @@ following command.
Proof. intros. rewrite empty_neutral. reflexivity. Qed.
- The tables of relations and morphisms are managed by the type class
+ The tables of relations and morphisms are managed by the typeclass
instance mechanism. The behavior on section close is to generalize the
instances by the variables of the section (and possibly hypotheses
used in the proofs of instance declarations) but not to export them in
@@ -350,7 +347,7 @@ prove that the argument of the morphism is defined.
.. example::
Let ``eqO`` be ``fun x y => x = y /\ x <> 0`` (the
- smallest PER over non zero elements). Division can be declared as a
+ smallest PER over nonzero elements). Division can be declared as a
morphism of signature ``eq ==> eq0 ==> eq``. Replacing ``x`` with
``y`` in ``div x n = div y n`` opens an additional goal ``eq0 n n``
which is equivalent to ``n = n /\ n <> 0``.
@@ -446,12 +443,12 @@ First class setoids and morphisms
The implementation is based on a first-class representation of
-properties of relations and morphisms as type classes. That is, the
+properties of relations and morphisms as typeclasses. That is, the
various combinations of properties on relations and morphisms are
represented as records and instances of theses classes are put in a
hint database. For example, the declaration:
-.. coqtop:: in
+.. coqdoc::
Add Parametric Relation (x1 : T1) ... (xn : Tn) : (A t1 ... tn) (Aeq t′1 ... t′m)
[reflexivity proved by refl]
@@ -462,7 +459,7 @@ hint database. For example, the declaration:
is equivalent to an instance declaration:
-.. coqtop:: in
+.. coqdoc::
Instance (x1 : T1) ... (xn : Tn) => id : @Equivalence (A t1 ... tn) (Aeq t′1 ... t′m) :=
[Equivalence_Reflexive := refl]
@@ -472,9 +469,9 @@ is equivalent to an instance declaration:
The declaration itself amounts to the definition of an object of the
record type ``Coq.Classes.RelationClasses.Equivalence`` and a hint added
to the ``typeclass_instances`` hint database. Morphism declarations are
-also instances of a type class defined in ``Classes.Morphisms``. See the
-documentation on type classes :ref:`typeclasses`
-and the theories files in Classes for further explanations.
+also instances of a typeclass defined in ``Classes.Morphisms``. See the
+documentation on :ref:`typeclasses` and the theories files in Classes
+for further explanations.
One can inform the rewrite tactic about morphisms and relations just
by using the typeclass mechanism to declare them using Instance and
@@ -703,7 +700,7 @@ example of a mostly user-space extension of the algorithm.
Constant unfolding
~~~~~~~~~~~~~~~~~~
-The resolution tactic is based on type classes and hence regards user-
+The resolution tactic is based on typeclasses and hence regards user-
defined constants as transparent by default. This may slow down the
resolution due to a lot of unifications (all the declared ``Proper``
instances are tried at each node of the search tree). To speed it up,
diff --git a/doc/sphinx/addendum/implicit-coercions.rst b/doc/sphinx/addendum/implicit-coercions.rst
index f134022eb6..fc5a366caf 100644
--- a/doc/sphinx/addendum/implicit-coercions.rst
+++ b/doc/sphinx/addendum/implicit-coercions.rst
@@ -1,5 +1,3 @@
-.. include:: ../replaces.rst
-
.. _implicitcoercions:
Implicit Coercions
@@ -256,19 +254,16 @@ Displaying Available Coercions
Activating the Printing of Coercions
-------------------------------------
-.. opt:: Printing Coercions
+.. flag:: Printing Coercions
When on, this option forces all the coercions to be printed.
By default, coercions are not printed.
-.. cmd:: Add Printing Coercion @qualid
-
- This command forces coercion denoted by :n:`@qualid` to be printed.
- By default, a coercion is never printed.
-
-.. cmd:: Remove Printing Coercion @qualid
+.. table:: Printing Coercion @qualid
+ :name: Printing Coercion
- Use this command, to skip the printing of coercion :n:`@qualid`.
+ Specifies a set of qualids for which coercions are always displayed. Use the
+ :cmd:`Add @table` and :cmd:`Remove @table` commands to update the set of qualids.
.. _coercions-classes-as-records:
@@ -315,7 +310,7 @@ are also forgotten.
Coercions and Modules
---------------------
-.. opt:: Automatic Coercions Import
+.. flag:: Automatic Coercions Import
Since |Coq| version 8.3, the coercions present in a module are activated
only when the module is explicitly imported. Formerly, the coercions
@@ -325,6 +320,12 @@ Coercions and Modules
This option makes it possible to recover the behavior of the versions of
|Coq| prior to 8.3.
+.. warn:: Coercion used but not in scope: @qualid. If you want to use this coercion, please Import the module that contains it.
+
+ This warning is emitted when typechecking relies on a coercion
+ contained in a module that has not been explicitely imported. It helps
+ migrating code and stop relying on the option above.
+
Examples
--------
@@ -352,7 +353,7 @@ We first give an example of coercion between atomic inductive types
.. warning::
- Note that ``Check true=O`` would fail. This is "normal" behaviour of
+ Note that ``Check true=O`` would fail. This is "normal" behavior of
coercions. To validate ``true=O``, the coercion is searched from
``nat`` to ``bool``. There is none.
diff --git a/doc/sphinx/addendum/micromega.rst b/doc/sphinx/addendum/micromega.rst
index d03a31c044..3b9760f586 100644
--- a/doc/sphinx/addendum/micromega.rst
+++ b/doc/sphinx/addendum/micromega.rst
@@ -112,11 +112,11 @@ and checked to be :math:`-1`.
.. tacn:: lia
:name: lia
-This tactic offers an alternative to the :tacn:`omega` and :tacn:`romega`
-tactics. Roughly speaking, the deductive power of lia is the combined deductive
-power of :tacn:`ring_simplify` and :tacn:`omega`. However, it solves linear
-goals that :tacn:`omega` and :tacn:`romega` do not solve, such as the following
-so-called *omega nightmare* :cite:`TheOmegaPaper`.
+ This tactic offers an alternative to the :tacn:`omega` tactic. Roughly
+ speaking, the deductive power of lia is the combined deductive power of
+ :tacn:`ring_simplify` and :tacn:`omega`. However, it solves linear goals
+ that :tacn:`omega` does not solve, such as the following so-called *omega
+ nightmare* :cite:`TheOmegaPaper`.
.. coqtop:: in
@@ -124,8 +124,7 @@ so-called *omega nightmare* :cite:`TheOmegaPaper`.
27 <= 11 * x + 13 * y <= 45 ->
-10 <= 7 * x - 9 * y <= 4 -> False.
-The estimation of the relative efficiency of :tacn:`lia` *vs* :tacn:`omega` and
-:tacn:`romega` is under evaluation.
+The estimation of the relative efficiency of :tacn:`lia` *vs* :tacn:`omega` is under evaluation.
High level view of `lia`
~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/doc/sphinx/addendum/miscellaneous-extensions.rst b/doc/sphinx/addendum/miscellaneous-extensions.rst
index 0f2d35d044..2cde65dcdc 100644
--- a/doc/sphinx/addendum/miscellaneous-extensions.rst
+++ b/doc/sphinx/addendum/miscellaneous-extensions.rst
@@ -1,5 +1,3 @@
-.. include:: ../replaces.rst
-
.. _miscellaneousextensions:
Miscellaneous extensions
diff --git a/doc/sphinx/addendum/nsatz.rst b/doc/sphinx/addendum/nsatz.rst
index 9adeca46fc..e7a8c238ac 100644
--- a/doc/sphinx/addendum/nsatz.rst
+++ b/doc/sphinx/addendum/nsatz.rst
@@ -1,5 +1,3 @@
-.. include:: ../preamble.rst
-
.. _nsatz_chapter:
Nsatz: tactics for proving equalities in integral domains
diff --git a/doc/sphinx/addendum/omega.rst b/doc/sphinx/addendum/omega.rst
index 1ed3bffd2c..03d4f148e3 100644
--- a/doc/sphinx/addendum/omega.rst
+++ b/doc/sphinx/addendum/omega.rst
@@ -11,7 +11,7 @@ Description of ``omega``
.. tacn:: omega
:tacn:`omega` is a tactic for solving goals in Presburger arithmetic,
- i.e. for proving formulas made of equations and inequations over the
+ i.e. for proving formulas made of equations and inequalities over the
type ``nat`` of natural numbers or the type ``Z`` of binary-encoded integers.
Formulas on ``nat`` are automatically injected into ``Z``. The procedure
may use any hypothesis of the current proof session to solve the goal.
@@ -23,11 +23,6 @@ Description of ``omega``
If the tactic cannot solve the goal, it fails with an error message.
In any case, the computation eventually stops.
-.. tacv:: romega
- :name: romega
-
- To be documented.
-
Arithmetical goals recognized by ``omega``
------------------------------------------
@@ -114,23 +109,23 @@ loaded by
Options
-------
-.. opt:: Stable Omega
+.. flag:: Stable Omega
.. deprecated:: 8.5
This deprecated option (on by default) is for compatibility with Coq pre 8.5. It
resets internal name counters to make executions of :tacn:`omega` independent.
-.. opt:: Omega UseLocalDefs
+.. flag:: Omega UseLocalDefs
This option (on by default) allows :tacn:`omega` to use the bodies of local
variables.
-.. opt:: Omega System
+.. flag:: Omega System
This option (off by default) activate the printing of debug information
-.. opt:: Omega Action
+.. flag:: Omega Action
This option (off by default) activate the printing of debug information
@@ -140,12 +135,12 @@ Technical data
Overview of the tactic
~~~~~~~~~~~~~~~~~~~~~~
- * The goal is negated twice and the first negation is introduced as an hypothesis.
- * Hypotheses are decomposed in simple equations or inequations. Multiple
+ * The goal is negated twice and the first negation is introduced as a hypothesis.
+ * Hypotheses are decomposed in simple equations or inequalities. Multiple
goals may result from this phase.
- * Equations and inequations over ``nat`` are translated over
+ * Equations and inequalities over ``nat`` are translated over
``Z``, multiple goals may result from the translation of subtraction.
- * Equations and inequations are normalized.
+ * Equations and inequalities are normalized.
* Goals are solved by the OMEGA decision procedure.
* The script of the solution is replayed.
@@ -156,17 +151,17 @@ The OMEGA decision procedure involved in the :tacn:`omega` tactic uses
a small subset of the decision procedure presented in :cite:`TheOmegaPaper`
Here is an overview, refer to the original paper for more information.
- * Equations and inequations are normalized by division by the GCD of their
+ * Equations and inequalities are normalized by division by the GCD of their
coefficients.
* Equations are eliminated, using the Banerjee test to get a coefficient
equal to one.
- * Note that each inequation cuts the Euclidean space in half.
- * Inequations are solved by projecting on the hyperspace
+ * Note that each inequality cuts the Euclidean space in half.
+ * Inequalities are solved by projecting on the hyperspace
defined by cancelling one of the variables. They are partitioned
according to the sign of the coefficient of the eliminated
- variable. Pairs of inequations from different classes define a
+ variable. Pairs of inequalities from different classes define a
new edge in the projection.
- * Redundant inequations are eliminated or merged in new
+ * Redundant inequalities are eliminated or merged in new
equations that can be eliminated by the Banerjee test.
* The last two steps are iterated until a contradiction is reached
(success) or there is no more variable to eliminate (failure).
diff --git a/doc/sphinx/addendum/parallel-proof-processing.rst b/doc/sphinx/addendum/parallel-proof-processing.rst
index 8ee8f52227..8b7214e2ab 100644
--- a/doc/sphinx/addendum/parallel-proof-processing.rst
+++ b/doc/sphinx/addendum/parallel-proof-processing.rst
@@ -1,5 +1,3 @@
-.. include:: ../replaces.rst
-
.. _asynchronousandparallelproofprocessing:
Asynchronous and Parallel Proof Processing
@@ -60,7 +58,7 @@ variables used.
Automatic suggestion of proof annotations
`````````````````````````````````````````
-The command ``Set Suggest Proof Using`` makes |Coq| suggest, when a ``Qed``
+The flag :flag:`Suggest Proof Using` makes |Coq| suggest, when a ``Qed``
command is processed, a correct proof annotation. It is up to the user
to modify the proof script accordingly.
diff --git a/doc/sphinx/addendum/program.rst b/doc/sphinx/addendum/program.rst
index 28fe68d78d..fad45995d2 100644
--- a/doc/sphinx/addendum/program.rst
+++ b/doc/sphinx/addendum/program.rst
@@ -1,6 +1,3 @@
-.. include:: ../preamble.rst
-.. include:: ../replaces.rst
-
.. this should be just "_program", but refs to it don't work
.. _programs:
@@ -18,7 +15,7 @@ program as in a regular functional programming language whilst using
as rich a specification as desired and proving that the code meets the
specification using the whole |Coq| proof apparatus. This is done using
a technique originating from the “Predicate subtyping” mechanism of
-PVS :cite:`Rushby98`, which generates type-checking conditions while typing a
+PVS :cite:`Rushby98`, which generates type checking conditions while typing a
term constrained to a particular type. Here we insert existential
variables in the term, which must be filled with proofs to get a
complete |Coq| term. |Program| replaces the |Program| tactic by Catherine
@@ -45,7 +42,7 @@ be considered as an object of type :g:`{x : T | P}` for any well-formed
will generate an obligation for every such coercion. In the other direction,
Russell will automatically insert a projection.
-Another distinction is the treatment of pattern-matching. Apart from
+Another distinction is the treatment of pattern matching. Apart from
the following differences, it is equivalent to the standard match
operation (see :ref:`extendedpatternmatching`).
@@ -72,8 +69,8 @@ operation (see :ref:`extendedpatternmatching`).
This permits to get the proper equalities in the context of proof
obligations inside clauses, without which reasoning is very limited.
-+ Generation of inequalities. If a pattern intersects with a previous
- one, an inequality is added in the context of the second branch. See
++ Generation of disequalities. If a pattern intersects with a previous
+ one, a disequality is added in the context of the second branch. See
for example the definition of div2 below, where the second branch is
typed in a context where :g:`∀ p, _ <> S (S p)`.
+ Coercion. If the object being matched is coercible to an inductive
@@ -84,15 +81,15 @@ operation (see :ref:`extendedpatternmatching`).
There are options to control the generation of equalities and
coercions.
-.. opt:: Program Cases
+.. flag:: Program Cases
- This controls the special treatment of pattern-matching generating equalities
- and inequalities when using |Program| (it is on by default). All
+ This controls the special treatment of pattern matching generating equalities
+ and disequalities when using |Program| (it is on by default). All
pattern-matches and let-patterns are handled using the standard algorithm
of |Coq| (see :ref:`extendedpatternmatching`) when this option is
deactivated.
-.. opt:: Program Generalized Coercion
+.. flag:: Program Generalized Coercion
This controls the coercion of general inductive types when using |Program|
(the option is on by default). Coercion of subset types and pairs is still
@@ -104,8 +101,8 @@ Syntactic control over equalities
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To give more control over the generation of equalities, the
-typechecker will fall back directly to |Coq|’s usual typing of dependent
-pattern-matching if a return or in clause is specified. Likewise, the
+type checker will fall back directly to |Coq|’s usual typing of dependent
+pattern matching if a return or in clause is specified. Likewise, the
if construct is not treated specially by |Program| so boolean tests in
the code are not automatically reflected in the obligations. One can
use the :g:`dec` combinator to get the correct hypotheses as in:
@@ -175,7 +172,7 @@ Program Definition
.. TODO refer to production in alias
-See also: Sections :ref:`vernac-controlling-the-reduction-strategies`, :tacn:`unfold`
+.. seealso:: Sections :ref:`vernac-controlling-the-reduction-strategies`, :tacn:`unfold`
.. _program_fixpoint:
@@ -213,7 +210,7 @@ with mutually recursive definitions too.
end.
Here we have one obligation for each branch (branches for :g:`0` and
-``(S 0)`` are automatically generated by the pattern-matching
+``(S 0)`` are automatically generated by the pattern matching
compilation algorithm).
.. coqtop:: all
@@ -320,19 +317,19 @@ optional tactic is replaced by the default one if not specified.
Shows the term that will be fed to the kernel once the obligations
are solved. Useful for debugging.
-.. opt:: Transparent Obligations
+.. flag:: Transparent Obligations
Controls whether all obligations should be declared as transparent
(the default), or if the system should infer which obligations can be
declared opaque.
-.. opt:: Hide Obligations
+.. flag:: Hide Obligations
Controls whether obligations appearing in the
term should be hidden as implicit arguments of the special
constantProgram.Tactics.obligation.
-.. opt:: Shrink Obligations
+.. flag:: Shrink Obligations
*Deprecated since 8.7*
@@ -378,6 +375,3 @@ Frequently Asked Questions
using lazy evaluation;
#. Mutual recursion on the underlying inductive type isn’t possible
anymore, but nested mutual recursion is always possible.
-
-.. bibliography:: ../biblio.bib
- :keyprefix: p-
diff --git a/doc/sphinx/addendum/ring.rst b/doc/sphinx/addendum/ring.rst
index d5c33dc1d4..58617916c0 100644
--- a/doc/sphinx/addendum/ring.rst
+++ b/doc/sphinx/addendum/ring.rst
@@ -1,11 +1,9 @@
-.. include:: ../replaces.rst
.. |ra| replace:: :math:`\rightarrow_{\beta\delta\iota}`
.. |la| replace:: :math:`\leftarrow_{\beta\delta\iota}`
.. |eq| replace:: `=`:sub:`(by the main correctness theorem)`
.. |re| replace:: ``(PEeval`` `v` `ap`\ ``)``
.. |le| replace:: ``(Pphi_dev`` `v` ``(norm`` `ap`\ ``))``
-
.. _theringandfieldtacticfamilies:
The ring and field tactic families
@@ -19,7 +17,7 @@ field equations.
What does this tactic do?
------------------------------
-``ring`` does associative-commutative rewriting in ring and semi-ring
+``ring`` does associative-commutative rewriting in ring and semiring
structures. Assume you have two binary functions :math:`\oplus` and
:math:`\otimes` that are associative and commutative, with :math:`\oplus`
distributive on :math:`\otimes`, and two constants 0 and 1 that are unities for
@@ -37,7 +35,7 @@ order. It is an easy theorem to show that every polynomial is equivalent (modulo
the ring properties) to exactly one canonical sum. This canonical sum is called
the normal form of the polynomial. In fact, the actual representation shares
monomials with same prefixes. So what does the ``ring`` tactic do? It normalizes polynomials over
-any ring or semi-ring structure. The basic use of ``ring`` is to simplify ring
+any ring or semiring structure. The basic use of ``ring`` is to simplify ring
expressions, so that the user does not have to deal manually with the theorems
of associativity and commutativity.
@@ -103,7 +101,7 @@ Concrete usage in Coq
.. tacn:: ring
The ``ring`` tactic solves equations upon polynomial expressions of a ring
-(or semi-ring) structure. It proceeds by normalizing both sides
+(or semiring) structure. It proceeds by normalizing both sides
of the equation (w.r.t. associativity, commutativity and
distributivity, constant propagation, rewriting of monomials) and
comparing syntactically the results.
@@ -264,13 +262,13 @@ are the implementations of the ring operations, ``==`` is the equality of
the coefficients, ``?+!`` is an implementation of this equality, and ``[x]``
is a notation for the image of ``x`` by the ring morphism.
-Since |Z| is an initial ring (and |N| is an initial semi-ring), it can
+Since |Z| is an initial ring (and |N| is an initial semiring), it can
always be considered as a set of coefficients. There are basically
three kinds of (semi-)rings:
abstract rings
to be used when operations are not effective. The set
- of coefficients is |Z| (or |N| for semi-rings).
+ of coefficients is |Z| (or |N| for semirings).
computational rings
to be used when operations are effective. The
@@ -505,10 +503,10 @@ expression `F` to a common denominator :math:`N/D = 0` where `N` and `D`
are two ring expressions. For example, if we take :math:`F = (1 − 1/x) x − x + 1`, this
gives :math:`N = (x − 1) x − x^2 + x` and :math:`D = x`. It then calls ring to solve
:math:`N = 0`.
-Note that ``field`` also generates non-zero conditions for all the
+Note that ``field`` also generates nonzero conditions for all the
denominators it encounters in the reduction. In our example, it
generates the condition :math:`x \neq 0`. These conditions appear as one subgoal
-which is a conjunction if there are several denominators. Non-zero
+which is a conjunction if there are several denominators. Nonzero
conditions are always polynomial expressions. For example when
reducing the expression :math:`1/(1 + 1/x)`, two side conditions are
generated: :math:`x \neq 0` and :math:`x + 1 \neq 0`. Factorized expressions are broken since
@@ -616,7 +614,7 @@ carrier set, an equality, and field operations:
satisfies the field axioms. Semi-fields (fields without + inverse) are
also supported. The equality can be either Leibniz equality, or any
relation declared as a setoid (see :ref:`tactics-enabled-on-user-provided-relations`). The definition of
-fields and semi-fields is:
+fields and semifields is:
.. coqtop:: in
@@ -670,7 +668,7 @@ specific modifier:
completeness :n:`@term`
allows the field tactic to prove automatically
- that the image of non-zero coefficients are mapped to non-zero
+ that the image of nonzero coefficients are mapped to nonzero
elements of the field. :n:`@term` is a proof of
``forall x y, [x] == [y] -> x ?=! y = true``,
@@ -684,7 +682,7 @@ History of ring
First Samuel Boutin designed the tactic ``ACDSimpl``. This tactic did lot
of rewriting. But the proofs terms generated by rewriting were too big
-for |Coq|’s type-checker. Let us see why:
+for |Coq|’s type checker. Let us see why:
.. coqtop:: all
@@ -707,7 +705,7 @@ interleaving of computation and reasoning (see :ref:`discussion_reflection`). He
some |ML| code for the ``Add Ring`` command that allows registering new rings dynamically.
Proofs terms generated by ring are quite small, they are linear in the
-number of :math:`\oplus` and :math:`\otimes` operations in the normalized terms. Type-checking
+number of :math:`\oplus` and :math:`\otimes` operations in the normalized terms. Type checking
those terms requires some time because it makes a large use of the
conversion rule, but memory requirements are much smaller.
diff --git a/doc/sphinx/addendum/type-classes.rst b/doc/sphinx/addendum/type-classes.rst
index b7946c6451..369dae0ead 100644
--- a/doc/sphinx/addendum/type-classes.rst
+++ b/doc/sphinx/addendum/type-classes.rst
@@ -1,12 +1,10 @@
-.. include:: ../replaces.rst
-
.. _typeclasses:
Type Classes
============
This chapter presents a quick reference of the commands related to type
-classes. For an actual introduction to type classes, there is a
+classes. For an actual introduction to typeclasses, there is a
description of the system :cite:`sozeau08` and the literature on type
classes in Haskell which also applies.
@@ -76,7 +74,7 @@ for dealing with obligations.
Binding classes
---------------
-Once a type class is declared, one can use it in class binders:
+Once a typeclass is declared, one can use it in class binders:
.. coqtop:: all
@@ -92,7 +90,7 @@ found, an error is raised:
Fail Definition neqb' (A : Type) (x y : A) := negb (eqb x y).
-The algorithm used to solve constraints is a variant of the eauto
+The algorithm used to solve constraints is a variant of the :tacn:`eauto`
tactic that does proof search with a set of lemmas (the instances). It
will use local hypotheses as well as declared lemmas in
the ``typeclass_instances`` database. Hence the example can also be
@@ -103,13 +101,13 @@ written:
Definition neqb' A (eqa : EqDec A) (x y : A) := negb (eqb x y).
However, the generalizing binders should be used instead as they have
-particular support for type classes:
+particular support for typeclasses:
-+ They automatically set the maximally implicit status for type class
++ They automatically set the maximally implicit status for typeclass
arguments, making derived functions as easy to use as class methods.
In the example above, ``A`` and ``eqa`` should be set maximally implicit.
+ They support implicit quantification on partially applied type
- classes (:ref:`implicit-generalization`). Any argument not given as part of a type class
+ classes (:ref:`implicit-generalization`). Any argument not given as part of a typeclass
binder will be automatically generalized.
+ They also support implicit quantification on :ref:`superclasses`.
@@ -148,7 +146,7 @@ database.
Sections and contexts
---------------------
-To ease the parametrization of developments by type classes, we provide a new
+To ease the parametrization of developments by typeclasses, we provide a new
way to introduce variables into section contexts, compatible with the implicit
argument mechanism. The new command works similarly to the :cmd:`Variables`
vernacular, except it accepts any binding context as argument. For example:
@@ -271,7 +269,7 @@ Summary of the commands
.. cmd:: Class @ident {? @binders} : {? @sort} := {? @ident} { {+; @ident :{? >} @term } }
- The :cmd:`Class` command is used to declare a type class with parameters
+ The :cmd:`Class` command is used to declare a typeclass with parameters
``binders`` and fields the declared record fields.
Variants:
@@ -302,7 +300,7 @@ Variants:
.. cmd:: Instance @ident {? @binders} : Class t1 … tn [| priority] := { field1 := b1 ; …; fieldi := bi }
-The :cmd:`Instance` command is used to declare a type class instance named
+The :cmd:`Instance` command is used to declare a typeclass instance named
``ident`` of the class :cmd:`Class` with parameters ``t1`` to ``tn`` and
fields ``b1`` to ``bi``, where each field must be a declared field of
the class. Missing fields must be filled in interactive proof mode.
@@ -310,7 +308,7 @@ the class. Missing fields must be filled in interactive proof mode.
An arbitrary context of ``binders`` can be put after the name of the
instance and before the colon to declare a parameterized instance. An
optional priority can be declared, 0 being the highest priority as for
-auto hints. If the priority is not specified, it defaults to the number
+:tacn:`auto` hints. If the priority is not specified, it defaults to the number
of non-dependent binders of the instance.
.. cmdv:: Instance @ident {? @binders} : forall {? @binders}, Class t1 … tn [| priority] := @term
@@ -329,7 +327,7 @@ of non-dependent binders of the instance.
.. cmdv:: Program Instance
:name: Program Instance
- Switches the type-checking to Program (chapter :ref:`programs`) and
+ Switches the type checking to Program (chapter :ref:`programs`) and
uses the obligation mechanism to manage missing fields.
.. cmdv:: Declare Instance
@@ -342,12 +340,12 @@ of non-dependent binders of the instance.
Besides the :cmd:`Class` and :cmd:`Instance` vernacular commands, there are a
-few other commands related to type classes.
+few other commands related to typeclasses.
.. cmd:: Existing Instance {+ @ident} [| priority]
This command adds an arbitrary list of constants whose type ends with
- an applied type class to the instance database with an optional
+ an applied typeclass to the instance database with an optional
priority. It can be used for redeclaring instances at the end of
sections, or declaring structure projections as instances. This is
equivalent to ``Hint Resolve ident : typeclass_instances``, except it
@@ -367,11 +365,11 @@ few other commands related to type classes.
+ Contrary to :tacn:`eauto` and :tacn:`auto`, the resolution is done entirely in
the new proof engine (as of Coq 8.6), meaning that backtracking is
available among dependent subgoals, and shelving goals is supported.
- typeclasses eauto is a multi-goal tactic. It analyses the dependencies
+ ``typeclasses eauto`` is a multi-goal tactic. It analyses the dependencies
between subgoals to avoid backtracking on subgoals that are entirely
independent.
- + When called with no arguments, typeclasses eauto uses
+ + When called with no arguments, ``typeclasses eauto`` uses
the ``typeclass_instances`` database by default (instead of core).
Dependent subgoals are automatically shelved, and shelved goals can
remain after resolution ends (following the behavior of Coq 8.5).
@@ -379,13 +377,13 @@ few other commands related to type classes.
.. note::
As of Coq 8.6, ``all:once (typeclasses eauto)`` faithfully
mimicks what happens during typeclass resolution when it is called
- during refinement/type-inference, except that *only* declared class
+ during refinement/type inference, except that *only* declared class
subgoals are considered at the start of resolution during type
inference, while ``all`` can select non-class subgoals as well. It might
move to ``all:typeclasses eauto`` in future versions when the
refinement engine will be able to backtrack.
- + When called with specific databases (e.g. with), typeclasses eauto
+ + When called with specific databases (e.g. with), ``typeclasses eauto``
allows shelved goals to remain at any point during search and treat
typeclass goals like any other.
@@ -403,10 +401,10 @@ few other commands related to type classes.
.. warning::
The semantics for the limit :n:`@num`
- is different than for auto. By default, if no limit is given the
- search is unbounded. Contrary to auto, introduction steps (intro) are
+ is different than for auto. By default, if no limit is given, the
+ search is unbounded. Contrary to :tacn:`auto`, introduction steps are
counted, which might result in larger limits being necessary when
- searching with typeclasses eauto than auto.
+ searching with ``typeclasses eauto`` than with :tacn:`auto`.
.. cmdv:: typeclasses eauto with {+ @ident}
@@ -417,11 +415,11 @@ few other commands related to type classes.
.. tacn:: autoapply @term with @ident
:name: autoapply
- The tactic autoapply applies a term using the transparency information
+ The tactic ``autoapply`` applies a term using the transparency information
of the hint database ident, and does *no* typeclass resolution. This can
be used in :cmd:`Hint Extern`’s for typeclass instances (in the hint
database ``typeclass_instances``) to allow backtracking on the typeclass
- subgoals created by the lemma application, rather than doing type class
+ subgoals created by the lemma application, rather than doing typeclass
resolution locally at the hint application time.
.. _TypeclassesTransparent:
@@ -431,7 +429,7 @@ Typeclasses Transparent, Typclasses Opaque
.. cmd:: Typeclasses Transparent {+ @ident}
- This command defines makes the identifiers transparent during type class
+ This command makes the identifiers transparent during typeclass
resolution.
.. cmd:: Typeclasses Opaque {+ @ident}
@@ -458,7 +456,7 @@ This is equivalent to ``Hint Transparent, Opaque ident : typeclass_instances``.
Options
~~~~~~~
-.. opt:: Typeclasses Dependency Order
+.. flag:: Typeclasses Dependency Order
This option (on by default since 8.6) respects the dependency order
between subgoals, meaning that subgoals on which other subgoals depend
@@ -467,7 +465,7 @@ Options
quite different performance behaviors of proof search.
-.. opt:: Typeclasses Filtered Unification
+.. flag:: Typeclasses Filtered Unification
This option, available since Coq 8.6 and off by default, switches the
hint application procedure to a filter-then-unify strategy. To apply a
@@ -481,27 +479,29 @@ Options
where there is a hole in that place.
-.. opt:: Typeclasses Limit Intros
+.. flag:: Typeclasses Limit Intros
This option (on by default) controls the ability to apply hints while
avoiding (functional) eta-expansions in the generated proof term. It
does so by allowing hints that conclude in a product to apply to a
goal with a matching product directly, avoiding an introduction.
- *Warning:* this can be expensive as it requires rebuilding hint
- clauses dynamically, and does not benefit from the invertibility
- status of the product introduction rule, resulting in potentially more
- expensive proof-search (i.e. more useless backtracking).
+ .. warning::
+
+ This can be expensive as it requires rebuilding hint
+ clauses dynamically, and does not benefit from the invertibility
+ status of the product introduction rule, resulting in potentially more
+ expensive proof-search (i.e. more useless backtracking).
-.. opt:: Typeclass Resolution For Conversion
+.. flag:: Typeclass Resolution For Conversion
This option (on by default) controls the use of typeclass resolution
- when a unification problem cannot be solved during elaboration/type-
+ when a unification problem cannot be solved during elaboration/type
inference. With this option on, when a unification fails, typeclass
resolution is tried before launching unification once again.
-.. opt:: Typeclasses Strict Resolution
+.. flag:: Typeclasses Strict Resolution
Typeclass declarations introduced when this option is set have a
stricter resolution behavior (the option is off by default). When
@@ -511,28 +511,33 @@ Options
instantiated.
-.. opt:: Typeclasses Unique Solutions
+.. flag:: Typeclasses Unique Solutions
When a typeclass resolution is launched we ensure that it has a single
solution or fail. This ensures that the resolution is canonical, but
can make proof search much more expensive.
-.. opt:: Typeclasses Unique Instances
+.. flag:: Typeclasses Unique Instances
Typeclass declarations introduced when this option is set have a more
efficient resolution behavior (the option is off by default). When a
solution to the typeclass goal of this class is found, we never
backtrack on it, assuming that it is canonical.
-.. opt:: Typeclasses Debug {? Verbosity @num}
+.. flag:: Typeclasses Debug
+
+ Controls whether typeclass resolution steps are shown during search. Setting this flag
+ also sets :opt:`Typeclasses Debug Verbosity` to 1.
+
+.. opt:: Typeclasses Debug Verbosity @num
+ :name: Typeclasses Debug Verbosity
- These options allow to see the resolution steps of typeclasses that are
- performed during search. The ``Debug`` option is synonymous to ``Debug
- Verbosity 1``, and ``Debug Verbosity 2`` provides more information
- (tried tactics, shelving of goals, etc…).
+ Determines how much information is shown for typeclass resolution steps during search.
+ 1 is the default level. 2 shows additional information such as tried tactics and shelving
+ of goals. Setting this option also sets :flag:`Typeclasses Debug`.
-.. opt:: Refine Instance Mode
+.. flag:: Refine Instance Mode
This option allows to switch the behavior of instance declarations made through
the Instance command.
@@ -548,7 +553,7 @@ Typeclasses eauto `:=`
.. cmd:: Typeclasses eauto := {? debug} {? {dfs | bfs}} depth
- This command allows more global customization of the type class
+ This command allows more global customization of the typeclass
resolution tactic. The semantics of the options are:
+ ``debug`` In debug mode, the trace of successfully applied tactics is
diff --git a/doc/sphinx/addendum/universe-polymorphism.rst b/doc/sphinx/addendum/universe-polymorphism.rst
index f245fab5ca..41afe3c312 100644
--- a/doc/sphinx/addendum/universe-polymorphism.rst
+++ b/doc/sphinx/addendum/universe-polymorphism.rst
@@ -1,5 +1,3 @@
-.. include:: ../replaces.rst
-
.. _polymorphicuniverses:
Polymorphic Universes
@@ -36,7 +34,7 @@ error:
Fail Definition selfid := identity (@identity).
Indeed, the global level ``Top.1`` would have to be strictly smaller than
-itself for this self-application to typecheck, as the type of
+itself for this self-application to type check, as the type of
:g:`(@identity)` is :g:`forall (A : Type@{Top.1}), A -> A` whose type is itself
:g:`Type@{Top.1+1}`.
@@ -59,7 +57,7 @@ so:
Definition selfpid := pidentity (@pidentity).
Of course, the two instances of :g:`pidentity` in this definition are
-different. This can be seen when the :opt:`Printing Universes` option is on:
+different. This can be seen when the :flag:`Printing Universes` flag is on:
.. coqtop:: none
@@ -79,7 +77,7 @@ levels.
When printing :g:`pidentity`, we can see the universes it binds in
the annotation :g:`@{Top.2}`. Additionally, when
-:opt:`Printing Universes` is on we print the "universe context" of
+:flag:`Printing Universes` is on we print the "universe context" of
:g:`pidentity` consisting of the bound universes and the
constraints they must verify (for :g:`pidentity` there are no constraints).
@@ -129,14 +127,14 @@ Polymorphic, Monomorphic
As shown in the examples, polymorphic definitions and inductives can be
declared using the ``Polymorphic`` prefix.
-.. opt:: Universe Polymorphism
+.. flag:: Universe Polymorphism
Once enabled, this option will implicitly prepend ``Polymorphic`` to any
definition of the user.
.. cmd:: Monomorphic @definition
- When the :opt:`Universe Polymorphism` option is set, to make a definition
+ When the :flag:`Universe Polymorphism` option is set, to make a definition
producing global universe constraints, one can use the ``Monomorphic`` prefix.
Many other commands support the ``Polymorphic`` flag, including:
@@ -169,7 +167,7 @@ declared cumulative using the :g:`Cumulative` prefix.
Declares the inductive as cumulative
-Alternatively, there is an option :opt:`Polymorphic Inductive
+Alternatively, there is a flag :flag:`Polymorphic Inductive
Cumulativity` which when set, makes all subsequent *polymorphic*
inductive definitions cumulative. When set, inductive types and the
like can be enforced to be non-cumulative using the :g:`NonCumulative`
@@ -179,7 +177,7 @@ prefix.
Declares the inductive as non-cumulative
-.. opt:: Polymorphic Inductive Cumulativity
+.. flag:: Polymorphic Inductive Cumulativity
When this option is on, it sets all following polymorphic inductive
types as cumulative (it is off by default).
@@ -229,7 +227,7 @@ Cumulative inductive types, coninductive types, variants and records
only make sense when they are universe polymorphic. Therefore, an
error is issued whenever the user uses the :g:`Cumulative` or
:g:`NonCumulative` prefix in a monomorphic context.
-Notice that this is not the case for the option :opt:`Polymorphic Inductive Cumulativity`.
+Notice that this is not the case for the option :flag:`Polymorphic Inductive Cumulativity`.
That is, this option, when set, makes all subsequent *polymorphic*
inductive declarations cumulative (unless, of course the :g:`NonCumulative` prefix is used)
but has no effect on *monomorphic* inductive declarations.
@@ -277,18 +275,18 @@ An example of a proof using cumulativity
Cumulativity Weak Constraints
-----------------------------
-.. opt:: Cumulativity Weak Constraints
+.. flag:: Cumulativity Weak Constraints
-This option, on by default, causes "weak" constraints to be produced
-when comparing universes in an irrelevant position. Processing weak
-constraints is delayed until minimization time. A weak constraint
-between `u` and `v` when neither is smaller than the other and
-one is flexible causes them to be unified. Otherwise the constraint is
-silently discarded.
+ When set, which is the default, causes "weak" constraints to be produced
+ when comparing universes in an irrelevant position. Processing weak
+ constraints is delayed until minimization time. A weak constraint
+ between `u` and `v` when neither is smaller than the other and
+ one is flexible causes them to be unified. Otherwise the constraint is
+ silently discarded.
-This heuristic is experimental and may change in future versions.
-Disabling weak constraints is more predictable but may produce
-arbitrary numbers of universes.
+ This heuristic is experimental and may change in future versions.
+ Disabling weak constraints is more predictable but may produce
+ arbitrary numbers of universes.
Global and local universes
@@ -354,9 +352,9 @@ This minimization process is applied only to fresh universe variables.
It simply adds an equation between the variable and its lower bound if
it is an atomic universe (i.e. not an algebraic max() universe).
-.. opt:: Universe Minimization ToSet
+.. flag:: Universe Minimization ToSet
- Turning this option off (it is on by default) disallows minimization
+ Turning this flag off (it is on by default) disallows minimization
to the sort :g:`Set` and only collapses floating universes between
themselves.
@@ -436,7 +434,7 @@ underscore or by omitting the annotation to a polymorphic definition.
Check le@{k _}.
Check le.
-.. opt:: Strict Universe Declaration.
+.. flag:: Strict Universe Declaration
Turning this option off allows one to freely use
identifiers for universes without declaring them first, with the
diff --git a/doc/sphinx/biblio.bib b/doc/sphinx/biblio.bib
index 9cfcd7ae64..d9eaa2c6c6 100644
--- a/doc/sphinx/biblio.bib
+++ b/doc/sphinx/biblio.bib
@@ -121,7 +121,7 @@ s},
volume = {7998},
editor = {Sandrine Blazy and Christine Paulin and David Pichardie },
series = {LNCS },
- doi = {10.1007/978-3-642-39634-2\_5 },
+ doi = {10.1007/978-3-642-39634-2_5},
year = {2013},
}
@@ -136,7 +136,7 @@ s},
pages = {85--95},
month = {November},
year = {2000},
- url = {http://www.lirmm.fr/\%7Edelahaye/papers/ltac\%20(LPAR\%2700).pdf}
+ url = {http://www.lirmm.fr/%7Edelahaye/papers/ltac%20(LPAR%2700).pdf}
}
@Article{Dyc92,
@@ -252,7 +252,7 @@ s},
booktitle = {TYPES},
year = 2002,
crossref = {DBLP:conf/types/2002},
- url = {draft at \url{http://www.irif.fr/~letouzey/download/extraction2002.pdf}}
+ url = {http://www.irif.fr/~letouzey/download/extraction2002.pdf}
}
@InProceedings{Luttik97specificationof,
@@ -294,6 +294,17 @@ s},
year = {1994}
}
+@Article{Myers,
+ author = {Eugene Myers},
+ title = {An {O(ND)} difference algorithm and its variations},
+ journal = {Algorithmica},
+ volume = {1},
+ number = {2},
+ year = {1986},
+ bibsource = {https://link.springer.com/article/10.1007\%2FBF01840446},
+ url = {http://www.xmailserver.org/diff2.pdf}
+}
+
@InProceedings{Parent95b,
author = {C. Parent},
booktitle = {{Mathematics of Program Construction'95}},
diff --git a/doc/sphinx/conf.py b/doc/sphinx/conf.py
index 8127d3df3f..71f01cbb17 100755
--- a/doc/sphinx/conf.py
+++ b/doc/sphinx/conf.py
@@ -24,6 +24,8 @@
import sys
import os
+from shutil import copyfile
+import sphinx
# Increase recursion limit for sphinx
sys.setrecursionlimit(1500)
@@ -36,6 +38,12 @@ sys.path.append(os.path.abspath('../../config/'))
import coq_config
+# -- Prolog ---------------------------------------------------------------
+
+# Include substitution definitions in all files
+with open("refman-preamble.rst") as s:
+ rst_prolog = s.read()
+
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
@@ -66,8 +74,36 @@ source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
+# Add extra cases here to support more formats
+
+SUPPORTED_FORMATS = ["html", "latex"]
+
+def readbin(fname):
+ try:
+ with open(fname, mode="rb") as f:
+ return f.read()
+ except FileNotFoundError:
+ return None
+
+def copy_formatspecific_files(app):
+ ext = ".{}.rst".format(app.builder.name)
+ for fname in sorted(os.listdir(app.srcdir)):
+ if fname.endswith(ext):
+ src = os.path.join(app.srcdir, fname)
+ dst = os.path.join(app.srcdir, fname[:-len(ext)] + ".rst")
+ logger = sphinx.util.logging.getLogger(__name__)
+ if readbin(src) == readbin(dst):
+ logger.info("Skipping {}: {} is up to date".format(src, dst))
+ else:
+ logger.info("Copying {} to {}".format(src, dst))
+ copyfile(src, dst)
+
+def setup(app):
+ app.connect('builder-inited', copy_formatspecific_files)
+
# The master toctree document.
-master_doc = 'index'
+# We create this file in `copy_master_doc` above.
+master_doc = "index"
# General information about the project.
project = 'Coq'
@@ -104,9 +140,10 @@ exclude_patterns = [
'Thumbs.db',
'.DS_Store',
'introduction.rst',
+ 'refman-preamble.rst',
'README.rst',
'README.template.rst'
-]
+] + ["*.{}.rst".format(fmt) for fmt in SUPPORTED_FORMATS]
# The reST default role (used for this markup: `text`) to use for all
# documents.
@@ -129,6 +166,7 @@ primary_domain = 'coq'
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
highlight_language = 'text'
+suppress_warnings = ["misc.highlighting_failure"]
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
@@ -257,57 +295,57 @@ smartquotes = False
###########################
# Set things up for XeTeX #
###########################
+
latex_elements = {
'babel': '',
'fontenc': '',
'inputenc': '',
'utf8extra': '',
'cmappkg': '',
- # https://www.topbug.net/blog/2015/12/10/a-collection-of-issues-about-the-latex-output-in-sphinx-and-the-solutions/
'papersize': 'letterpaper',
'classoptions': ',openany', # No blank pages
- 'polyglossia' : '\\usepackage{polyglossia}',
- 'unicode-math' : '\\usepackage{unicode-math}',
- 'microtype' : '\\usepackage{microtype}',
- "preamble": r"\usepackage{coqnotations}"
+ 'polyglossia': '\\usepackage{polyglossia}',
+ 'sphinxsetup': 'verbatimwithframe=false',
+ 'preamble': r"""
+ \usepackage{unicode-math}
+ \usepackage{microtype}
+
+ % Macro definitions
+ \usepackage{refman-preamble}
+
+ % Style definitions for notations
+ \usepackage{coqnotations}
+
+ % Style tweaks
+ \newcssclass{sigannot}{\textrm{#1:}}
+
+ % Silence 'LaTeX Warning: Command \nobreakspace invalid in math mode'
+ \everymath{\def\nobreakspace{\ }}
+ """
}
-from sphinx.builders.latex import LaTeXBuilder
+latex_engine = "xelatex"
########
# done #
########
-latex_additional_files = ["_static/coqnotations.sty"]
+latex_additional_files = [
+ "refman-preamble.sty",
+ "_static/coqnotations.sty"
+]
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title,
-# author, documentclass [howto, manual, or own class]).
-# latex_documents = [
-# (master_doc, 'CoqRefMan.tex', 'Coq Documentation',
-# 'The Coq Development Team', 'manual'),
-#]
+latex_documents = [('index', 'CoqRefMan.tex', 'The Coq Reference Manual', author, 'manual')]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
-#latex_logo = None
-
-# For "manual" documents, if this is true, then toplevel headings are parts,
-# not chapters.
-#latex_use_parts = False
+# latex_logo = "../../ide/coq.png"
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
-#latex_show_urls = False
-
-# Documents to append as an appendix to all manuals.
-#latex_appendices = []
-
-# If false, no module index is generated.
-#latex_domain_indices = True
-
+latex_show_urls = 'footnote'
# -- Options for manual page output ---------------------------------------
diff --git a/doc/sphinx/coq-cmdindex.rst b/doc/sphinx/coq-cmdindex.rst
index 7df6cb36c5..fd0b342ae4 100644
--- a/doc/sphinx/coq-cmdindex.rst
+++ b/doc/sphinx/coq-cmdindex.rst
@@ -1,3 +1,5 @@
+:orphan:
+
.. hack to get index in TOC
-----------------
diff --git a/doc/sphinx/coq-exnindex.rst b/doc/sphinx/coq-exnindex.rst
index 100c57b085..fc55e91eee 100644
--- a/doc/sphinx/coq-exnindex.rst
+++ b/doc/sphinx/coq-exnindex.rst
@@ -1,5 +1,7 @@
+:orphan:
+
.. hack to get index in TOC
-----------------------
-Errors, warnings index
-----------------------
+-------------------------
+Errors and warnings index
+-------------------------
diff --git a/doc/sphinx/coq-optindex.rst b/doc/sphinx/coq-optindex.rst
index f8046a800b..0961bea61f 100644
--- a/doc/sphinx/coq-optindex.rst
+++ b/doc/sphinx/coq-optindex.rst
@@ -1,5 +1,7 @@
+:orphan:
+
.. hack to get index in TOC
------------------
-Option index
------------------
+-------------------------------
+Flags, options and tables index
+-------------------------------
diff --git a/doc/sphinx/coq-tacindex.rst b/doc/sphinx/coq-tacindex.rst
index 588104f465..31b2f7f8cb 100644
--- a/doc/sphinx/coq-tacindex.rst
+++ b/doc/sphinx/coq-tacindex.rst
@@ -1,3 +1,5 @@
+:orphan:
+
.. hack to get index in TOC
-------------
diff --git a/doc/sphinx/credits.rst b/doc/sphinx/credits-contents.rst
index 2988b194e2..212f0a65b0 100644
--- a/doc/sphinx/credits.rst
+++ b/doc/sphinx/credits-contents.rst
@@ -1,12 +1,3 @@
-.. include:: preamble.rst
-.. include:: replaces.rst
-
-.. _credits:
-
--------------------------------------------
-Credits
--------------------------------------------
-
Coq is a proof assistant for higher-order logic, allowing the
development of computer programs consistent with their formal
specification. It is the result of about ten years of research of the
@@ -60,7 +51,7 @@ the language ML.
Automated theorem-proving was pioneered in the 1960’s by Davis and
Putnam in propositional calculus. A complete mechanization (in the sense
-of a semi-decision procedure) of classical first-order logic was
+of a semidecision procedure) of classical first-order logic was
proposed in 1965 by J.A. Robinson, with a single uniform inference rule
called *resolution*. Resolution relies on solving equations in free
algebras (i.e. term structures), using the *unification algorithm*. Many
@@ -205,7 +196,7 @@ between sorts.
The new version provides powerful tools for easier developments.
Cristina Cornes designed an extension of the |Coq| syntax to allow
-definition of terms using a powerful pattern-matching analysis in the
+definition of terms using a powerful pattern matching analysis in the
style of ML programs.
Amokrane Saïbi wrote a mechanism to simulate inheritance between types
@@ -249,7 +240,7 @@ names to Caml functions corresponding to |Coq| tactic names.
Bruno Barras wrote new, more efficient reduction functions.
Hugo Herbelin introduced more uniform notations in the |Coq| specification
-language: the definitions by fixpoints and pattern-matching have a more
+language: the definitions by fixpoints and pattern matching have a more
readable syntax. Patrick Loiseleur introduced user-friendly notations
for arithmetic expressions.
@@ -320,20 +311,20 @@ in March 2001, version 7.1 in September 2001, version 7.2 in January
Jean-Christophe Filliâtre designed the architecture of the new system.
He introduced a new representation for environments and wrote a new
-kernel for type-checking terms. His approach was to use functional
+kernel for type checking terms. His approach was to use functional
data-structures in order to get more sharing, to prepare the addition of
modules and also to get closer to a certified kernel.
Hugo Herbelin introduced a new structure of terms with local
definitions. He introduced “qualified” names, wrote a new
-pattern-matching compilation algorithm and designed a more compact
+pattern matching compilation algorithm and designed a more compact
algorithm for checking the logical consistency of universes. He
contributed to the simplification of |Coq| internal structures and the
optimisation of the system. He added basic tactics for forward reasoning
and coercions in patterns.
David Delahaye introduced a new language for tactics. General tactics
-using pattern-matching on goals and context can directly be written from
+using pattern matching on goals and context can directly be written from
the |Coq| toplevel. He also provided primitives for the design of
user-defined tactics in Caml.
@@ -352,7 +343,7 @@ sensible. Jean-Christophe Filliâtre wrote ``coqdoc``, a documentation
tool for |Coq| libraries usable from version 7.2.
Bruno Barras improved the efficiency of the reduction algorithm and the
-confidence level in the correctness of |Coq| critical type-checking
+confidence level in the correctness of |Coq| critical type checking
algorithm.
Yves Bertot designed the ``SearchPattern`` and ``SearchRewrite`` tools
@@ -506,7 +497,7 @@ Credits: version 8.1
Coq version 8.1 adds various new functionalities.
Benjamin Grégoire implemented an alternative algorithm to check the
-convertibility of terms in the |Coq| type-checker. This alternative
+convertibility of terms in the |Coq| type checker. This alternative
algorithm works by compilation to an efficient bytecode that is
interpreted in an abstract machine similar to Xavier Leroy’s ZINC
machine. Convertibility is performed by comparing the normal forms. This
@@ -526,7 +517,7 @@ Claudio Sacerdoti Coen added new features to the module system.
Benjamin Grégoire, Assia Mahboubi and Bruno Barras developed a new, more
efficient and more general simplification algorithm for rings and
-semi-rings.
+semirings.
Laurent Théry and Bruno Barras developed a new, significantly more
efficient simplification algorithm for fields.
@@ -586,11 +577,11 @@ Coq version 8.2 adds new features, new libraries and improves on many
various aspects.
Regarding the language of |Coq|, the main novelty is the introduction by
-Matthieu Sozeau of a package of commands providing Haskell-style type
-classes. Type classes, that come with a few convenient features such as
+Matthieu Sozeau of a package of commands providing Haskell-style typeclasses.
+Typeclasses, which come with a few convenient features such as
type-based resolution of implicit arguments, play a new landmark role
in the architecture of |Coq| with respect to automation. For
-instance, thanks to type classes support, Matthieu Sozeau could
+instance, thanks to typeclass support, Matthieu Sozeau could
implement a new resolution-based version of the tactics dedicated to
rewriting on arbitrary transitive relations.
@@ -624,8 +615,8 @@ with the library of integers he developed.
Beside the libraries, various improvements were contributed to provide a more
comfortable end-user language and more expressive tactic language. Hugo
-Herbelin and Matthieu Sozeau improved the pattern-matching compilation
-algorithm (detection of impossible clauses in pattern-matching,
+Herbelin and Matthieu Sozeau improved the pattern matching compilation
+algorithm (detection of impossible clauses in pattern matching,
automatic inference of the return type). Hugo Herbelin, Pierre Letouzey
and Matthieu Sozeau contributed various new convenient syntactic
constructs and new tactics or tactic features: more inference of
@@ -648,7 +639,7 @@ maintenance and coqdoc support, Vincent Siles contributed extensions of
the Scheme command and of injection.
Bruno Barras implemented the `coqchk` tool: this is a stand-alone
-type-checker that can be used to certify .vo files. Especially, as this
+type checker that can be used to certify .vo files. Especially, as this
verifier runs in a separate process, it is granted not to be “hijacked”
by virtually malicious extensions added to |Coq|.
@@ -712,7 +703,7 @@ The new tactic nsatz is due to Loïc Pottier. It works by computing
Gröbner bases. Regarding the existing tactics, various improvements have
been done by Matthieu Sozeau, Hugo Herbelin and Pierre Letouzey.
-Matthieu Sozeau extended and refined the type classes and Program
+Matthieu Sozeau extended and refined the typeclasses and Program
features (the Russell language). Pierre Letouzey maintained and improved
the extraction mechanism. Bruno Barras and Élie Soubiran maintained the
Coq checker, Julien Forest maintained the Function mechanism for
@@ -801,7 +792,7 @@ through :math:`\beta`-redexes that are blocked by the “match”
construction (blocked commutative cuts).
Relying on the added permissiveness of the guard condition, Hugo
-Herbelin could extend the pattern-matching compilation algorithm so that
+Herbelin could extend the pattern matching compilation algorithm so that
matching over a sequence of terms involving dependencies of a term or of
the indices of the type of a term in the type of other terms is
systematically supported.
@@ -810,7 +801,7 @@ Regarding the high-level specification language, Pierre Boutillier
introduced the ability to give implicit arguments to anonymous
functions, Hugo Herbelin introduced the ability to define notations with
several binders (e.g. ``exists x y z, P``), Matthieu Sozeau made the
-type classes inference mechanism more robust and predictable, Enrico
+typeclass inference mechanism more robust and predictable, Enrico
Tassi introduced a command Arguments that generalizes Implicit Arguments
and Arguments Scope for assigning various properties to arguments of
constants. Various improvements in the type inference algorithm were
@@ -831,7 +822,7 @@ vm\_compute. Bug fixes and miscellaneous improvements of the tactic
language came from Hugo Herbelin, Pierre Letouzey and Matthieu Sozeau.
Regarding decision tactics, Loïc Pottier maintained nsatz, moving in
-particular to a type-class based reification of goals while Frédéric
+particular to a typeclass based reification of goals while Frédéric
Besson maintained Micromega, adding in particular support for division.
Regarding vernacular commands, Stéphane Glondu provided new commands to
@@ -979,7 +970,7 @@ principle than the previously added :math:`\eta`-conversion for function
types, based on formulations of the Calculus of Inductive Constructions
with typed equality. Primitive projections, which do not carry the
parameters of the record and are rigid names (not defined as a
-pattern-matching construct), make working with nested records more
+pattern matching construct), make working with nested records more
manageable in terms of time and space consumption. This extension and
universe polymorphism were carried out partly while Matthieu Sozeau was
working at the IAS in Princeton.
@@ -1074,7 +1065,7 @@ over 100 contributions integrated. The main user visible changes are:
document.
- More access to the proof engine features from Ltac: goal management
- primitives, range selectors and a typeclasses eauto engine handling
+ primitives, range selectors and a ``typeclasses eauto`` engine handling
multiple goals and multiple successes, by Cyprien Mangin, Matthieu
Sozeau and Arnaud Spiwack.
@@ -1234,7 +1225,7 @@ The efficiency of the whole system has been significantly improved thanks to
contributions from Pierre-Marie Pédrot, Maxime Dénès and Matthieu Sozeau and
performance issue tracking by Jason Gross and Paul Steckler.
-Thomas Sibut-Pinote and Hugo Herbelin added support for side effects hooks in
+Thomas Sibut-Pinote and Hugo Herbelin added support for side effect hooks in
cbv, cbn and simpl. The side effects are provided via a plugin available at
https://github.com/herbelin/reduction-effects/.
@@ -1292,7 +1283,7 @@ integration of new features, with an important focus given to compatibility and
performance issues, resulting in a hopefully more robust release than |Coq| 8.6
while maintaining compatibility.
-|Coq| Enhancement Proposals (CEPs for short) and open pull-requests discussions
+|Coq| Enhancement Proposals (CEPs for short) and open pull request discussions
were used to discuss publicly the new features.
The |Coq| consortium, an organization directed towards users and supporters of the
diff --git a/doc/sphinx/credits.html.rst b/doc/sphinx/credits.html.rst
new file mode 100644
index 0000000000..0b2b1c6ad1
--- /dev/null
+++ b/doc/sphinx/credits.html.rst
@@ -0,0 +1,7 @@
+.. _credits:
+
+-------
+Credits
+-------
+
+.. include:: credits-contents.rst
diff --git a/doc/sphinx/credits.latex.rst b/doc/sphinx/credits.latex.rst
new file mode 100644
index 0000000000..39101f9d52
--- /dev/null
+++ b/doc/sphinx/credits.latex.rst
@@ -0,0 +1,3 @@
+.. _credits:
+
+.. include:: credits-contents.rst
diff --git a/doc/sphinx/genindex.rst b/doc/sphinx/genindex.rst
index a991c7f9f8..29f792b3aa 100644
--- a/doc/sphinx/genindex.rst
+++ b/doc/sphinx/genindex.rst
@@ -1,3 +1,5 @@
+:orphan:
+
.. hack to get index in TOC
-----
diff --git a/doc/sphinx/index.rst b/doc/sphinx/index.html.rst
index baf2e0d981..cf12b57414 100644
--- a/doc/sphinx/index.rst
+++ b/doc/sphinx/index.html.rst
@@ -1,11 +1,13 @@
-.. include:: preamble.rst
-.. include:: replaces.rst
+.. _introduction:
+
+==========================
+Introduction
+==========================
.. include:: introduction.rst
-------------------
Table of contents
-------------------
+-----------------
.. toctree::
:caption: Indexes
@@ -80,12 +82,12 @@ Table of contents
zebibliography
-This material (the Coq Reference Manual) 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
-http://www.opencontent.org/openpub). Options A and B are not elected.
+License
+-------
+
+.. include:: license.rst
.. [#PG] Proof-General is available at https://proofgeneral.github.io/.
- Optionally, you can enhance it with the minor mode
- Company-Coq :cite:`Pit16`
- (see https://github.com/cpitclaudel/company-coq).
+ Optionally, you can enhance it with the minor mode
+ Company-Coq :cite:`Pit16`
+ (see https://github.com/cpitclaudel/company-coq).
diff --git a/doc/sphinx/index.latex.rst b/doc/sphinx/index.latex.rst
new file mode 100644
index 0000000000..af757f8746
--- /dev/null
+++ b/doc/sphinx/index.latex.rst
@@ -0,0 +1,86 @@
+==========================
+ The Coq Reference Manual
+==========================
+
+Introduction
+------------
+
+.. include:: introduction.rst
+
+.. [#PG] Proof-General is available at https://proofgeneral.github.io/.
+ Optionally, you can enhance it with the minor mode
+ Company-Coq :cite:`Pit16`
+ (see https://github.com/cpitclaudel/company-coq).
+
+Credits
+-------
+
+.. include:: credits.rst
+
+License
+-------
+
+.. include:: license.rst
+
+The language
+------------
+
+.. toctree::
+
+ language/gallina-specification-language
+ language/gallina-extensions
+ language/coq-library
+ language/cic
+ language/module-system
+
+The proof engine
+----------------
+
+.. toctree::
+
+ proof-engine/vernacular-commands
+ proof-engine/proof-handling
+ proof-engine/tactics
+ proof-engine/ltac
+ proof-engine/detailed-tactic-examples
+ proof-engine/ssreflect-proof-language
+
+User extensions
+---------------
+
+.. toctree::
+
+ user-extensions/syntax-extensions
+ user-extensions/proof-schemes
+
+Practical tools
+---------------
+
+.. toctree::
+
+ practical-tools/coq-commands
+ practical-tools/utilities
+ practical-tools/coqide
+
+Addendum
+--------
+
+.. toctree::
+
+ addendum/extended-pattern-matching
+ addendum/implicit-coercions
+ addendum/canonical-structures
+ addendum/type-classes
+ addendum/omega
+ addendum/micromega
+ addendum/extraction
+ addendum/program
+ addendum/ring
+ addendum/nsatz
+ addendum/generalized-rewriting
+ addendum/parallel-proof-processing
+ addendum/miscellaneous-extensions
+ addendum/universe-polymorphism
+
+.. toctree::
+ zebibliography
diff --git a/doc/sphinx/introduction.rst b/doc/sphinx/introduction.rst
index 1a610396e5..5bb7bf542c 100644
--- a/doc/sphinx/introduction.rst
+++ b/doc/sphinx/introduction.rst
@@ -1,14 +1,8 @@
-.. _introduction:
-
-------------------------
-Introduction
-------------------------
-
This document is the Reference Manual of the |Coq| proof assistant.
To start using Coq, it is advised to first read a tutorial.
Links to several tutorials can be found at
-https://coq.inria.fr/documentation (see also
-https://github.com/coq/coq/wiki#coq-tutorials).
+https://coq.inria.fr/documentation and
+https://github.com/coq/coq/wiki#coq-tutorials
The |Coq| system is designed to develop mathematical proofs, and
especially to write formal specifications, programs and to verify that
@@ -20,7 +14,7 @@ properties and proofs are formalized in the same language called
*Calculus of Inductive Constructions*, that is a
:math:`\lambda`-calculus with a rich type system. All logical judgments
in |Coq| are typing judgments. The very heart of the |Coq| system is the
-type-checking algorithm that checks the correctness of proofs, in other
+type checking algorithm that checks the correctness of proofs, in other
words that checks that a program complies to its specification. |Coq| also
provides an interactive proof assistant to build proofs using specific
programs called *tactics*.
diff --git a/doc/sphinx/language/cic.rst b/doc/sphinx/language/cic.rst
index 6e0c1e1b61..381f8bb661 100644
--- a/doc/sphinx/language/cic.rst
+++ b/doc/sphinx/language/cic.rst
@@ -1,6 +1,3 @@
-.. include:: ../preamble.rst
-.. include:: ../replaces.rst
-
.. _calculusofinductiveconstructions:
@@ -96,8 +93,9 @@ constraints between the universe variables is maintained globally. To
ensure the existence of a mapping of the universes to the positive
integers, the graph of constraints must remain acyclic. Typing
expressions that violate the acyclicity of the graph of constraints
-results in a Universe inconsistency error (see also Section
-:ref:`printing-universes`).
+results in a Universe inconsistency error.
+
+.. seealso:: Section :ref:`printing-universes`.
.. _Terms:
@@ -604,7 +602,7 @@ Subtyping rules
At the moment, we did not take into account one rule between universes
which says that any term in a universe of index i is also a term in
-the universe of index i+1 (this is the *cumulativity* rule of|Cic|).
+the universe of index i+1 (this is the *cumulativity* rule of |Cic|).
This property extends the equivalence relation of convertibility into
a *subtyping* relation inductively defined by:
@@ -639,7 +637,7 @@ a *subtyping* relation inductively defined by:
respectively then
.. math::
- E[Γ] ⊢ t~w_1 … w_m ≤_{βδιζη} t~w_1' … w_m'
+ E[Γ] ⊢ t~w_1 … w_m ≤_{βδιζη} t'~w_1' … w_m'
(notice that :math:`t` and :math:`t'` are both
fully applied, i.e., they have a sort as a type) if
@@ -747,7 +745,7 @@ the sort of the inductive type t (not to be confused with :math:`\Sort` which is
is:
.. math::
- \ind{~}{\left[\begin{array}{rcl}\tree&:&\Set\\\forest&:&\Set\end{array}\right]}
+ \ind{0}{\left[\begin{array}{rcl}\tree&:&\Set\\\forest&:&\Set\end{array}\right]}
{\left[\begin{array}{rcl}
\node &:& \forest → \tree\\
\emptyf &:& \forest\\
@@ -769,7 +767,7 @@ the sort of the inductive type t (not to be confused with :math:`\Sort` which is
The declaration for a mutual inductive definition of even and odd is:
.. math::
- \ind{1}{\left[\begin{array}{rcl}\even&:&\nat → \Prop \\
+ \ind{0}{\left[\begin{array}{rcl}\even&:&\nat → \Prop \\
\odd&:&\nat → \Prop \end{array}\right]}
{\left[\begin{array}{rcl}
\evenO &:& \even~0\\
@@ -781,7 +779,7 @@ the sort of the inductive type t (not to be confused with :math:`\Sort` which is
.. coqtop:: in
- Inductive even : nat -> prop :=
+ Inductive even : nat -> Prop :=
| even_O : even 0
| even_S : forall n, odd n -> even (S n)
with odd : nat -> prop :=
@@ -966,7 +964,7 @@ such that :math:`Γ_I` is :math:`[I_1 :∀ Γ_P ,A_1 ;…;I_k :∀ Γ_P ,A_k]`,
.. inference:: W-Ind
\WFE{Γ_P}
- (E[Γ_P ] ⊢ A_j : s_j' )_{j=1… k}
+ (E[Γ_P ] ⊢ A_j : s_j )_{j=1… k}
(E[Γ_I ;Γ_P ] ⊢ C_i : s_{q_i} )_{i=1… n}
------------------------------------------
\WF{E;\ind{p}{Γ_I}{Γ_C}}{Γ}
@@ -1009,7 +1007,7 @@ the Type hierarchy.
It is possible to declare the same inductive definition in the
universe :math:`\Type`. The :g:`exType` inductive definition has type
- :math:`(\Type(i)→\Prop)→\Type(j)` with the constraint that the parameter :math:`X` of :math:`\kw{exT_intro}`
+ :math:`(\Type(i)→\Prop)→\Type(j)` with the constraint that the parameter :math:`X` of :math:`\kw{exT}_{\kw{intro}}`
has type :math:`\Type(k)` with :math:`k<j` and :math:`k≤ i`.
.. coqtop:: all
@@ -1024,8 +1022,26 @@ the Type hierarchy.
Template polymorphism
+++++++++++++++++++++
-Inductive types declared in :math:`\Type` are polymorphic over their arguments
-in :math:`\Type`. If :math:`A` is an arity of some sort and math:`s` is a sort, we write :math:`A_{/s}`
+Inductive types can be made polymorphic over their arguments
+in :math:`\Type`.
+
+.. flag:: Auto Template Polymorphism
+
+ This option, enabled by default, makes every inductive type declared
+ at level :math:`Type` (without annotations or hiding it behind a
+ definition) template polymorphic.
+
+ This can be prevented using the ``notemplate`` attribute.
+
+ An inductive type can be forced to be template polymorphic using the
+ ``template`` attribute.
+
+ Template polymorphism and universe polymorphism (see Chapter
+ :ref:`polymorphicuniverses`) are incompatible, so if the later is
+ enabled it will prevail over automatic template polymorphism and
+ cause an error when using the ``template`` attribute.
+
+If :math:`A` is an arity of some sort and :math:`s` is a sort, we write :math:`A_{/s}`
for the arity obtained from :math:`A` by replacing its sort with :math:`s`.
Especially, if :math:`A` is well-typed in some global environment and local
context, then :math:`A_{/s}` is typable by typability of all products in the
@@ -1104,7 +1120,7 @@ and otherwise in the Type hierarchy.
Note that the side-condition about allowed elimination sorts in the
rule **Ind-Family** is just to avoid to recompute the allowed elimination
-sorts at each instance of a pattern-matching (see Section :ref:`Destructors`). As
+sorts at each instance of a pattern matching (see Section :ref:`Destructors`). As
an example, let us consider the following definition:
.. example::
@@ -1228,7 +1244,7 @@ primitive recursion over the structure.
But this operator is rather tedious to implement and use. We choose in
this version of |Coq| to factorize the operator for primitive recursion
into two more primitive operations as was first suggested by Th.
-Coquand in :cite:`Coq92`. One is the definition by pattern-matching. The
+Coquand in :cite:`Coq92`. One is the definition by pattern matching. The
second one is a definition by guarded fixpoints.
@@ -1245,14 +1261,14 @@ The |Coq| term for this proof
will be written:
.. math::
- \Match~m~\with~(c_1~x_{11} ... x_{1p_1} ) ⇒ f_1 | … | (c_n~x_{n1} ... x_{np_n} ) ⇒ f_n \endkw
+ \Match~m~\with~(c_1~x_{11} ... x_{1p_1} ) ⇒ f_1 | … | (c_n~x_{n1} ... x_{np_n} ) ⇒ f_n \kwend
In this expression, if :math:`m` eventually happens to evaluate to
:math:`(c_i~u_1 … u_{p_i})` then the expression will behave as specified in its :math:`i`-th branch
and it will reduce to :math:`f_i` where the :math:`x_{i1} …x_{ip_i}` are replaced by the
:math:`u_1 … u_{p_i}` according to the ι-reduction.
-Actually, for type-checking a :math:`\Match…\with…\endkw` expression we also need
+Actually, for type checking a :math:`\Match…\with…\kwend` expression we also need
to know the predicate P to be proved by case analysis. In the general
case where :math:`I` is an inductively defined :math:`n`-ary relation, :math:`P` is a predicate
over :math:`n+1` arguments: the :math:`n` first ones correspond to the arguments of :math:`I`
@@ -1266,7 +1282,7 @@ using the syntax:
.. math::
\Match~m~\as~x~\In~I~\_~a~\return~P~\with~
(c_1~x_{11} ... x_{1p_1} ) ⇒ f_1 | …
- | (c_n~x_{n1} ... x_{np_n} ) ⇒ f_n~\endkw
+ | (c_n~x_{n1} ... x_{np_n} ) ⇒ f_n~\kwend
The :math:`\as` part can be omitted if either the result type does not depend
on :math:`m` (non-dependent elimination) or :math:`m` is a variable (in this case, :math:`m`
@@ -1398,7 +1414,7 @@ arguments of this constructor have type :math:`\Prop`. In that case, there is a
canonical way to interpret the informative extraction on an object in
that type, such that the elimination on any sort :math:`s` is legal. Typical
examples are the conjunction of non-informative propositions and the
-equality. If there is an hypothesis :math:`h:a=b` in the local context, it can
+equality. If there is a hypothesis :math:`h:a=b` in the local context, it can
be used for rewriting not only in logical propositions but also in any
type.
@@ -1452,6 +1468,8 @@ We write :math:`\{c\}^P` for :math:`\{c:C\}^P` with :math:`C` the type of :math:
where
.. math::
+ :nowrap:
+
\begin{eqnarray*}
P & = & \lambda~l~.~P^\prime\\
f_1 & = & t_1\\
@@ -1692,13 +1710,15 @@ for primitive recursive operators. The following reductions are now
possible:
.. math::
- \def\plus{\mathsf{plus}}
- \def\tri{\triangleright_\iota}
- \begin{eqnarray*}
- \plus~(\nS~(\nS~\nO))~(\nS~\nO) & \tri & \nS~(\plus~(\nS~\nO)~(\nS~\nO))\\
- & \tri & \nS~(\nS~(\plus~\nO~(\nS~\nO)))\\
- & \tri & \nS~(\nS~(\nS~\nO))\\
- \end{eqnarray*}
+ :nowrap:
+
+ {\def\plus{\mathsf{plus}}
+ \def\tri{\triangleright_\iota}
+ \begin{eqnarray*}
+ \plus~(\nS~(\nS~\nO))~(\nS~\nO) & \tri & \nS~(\plus~(\nS~\nO)~(\nS~\nO))\\
+ & \tri & \nS~(\nS~(\plus~\nO~(\nS~\nO)))\\
+ & \tri & \nS~(\nS~(\nS~\nO))\\
+ \end{eqnarray*}}
.. _Mutual-induction:
@@ -1821,7 +1841,7 @@ definitions can be found in :cite:`Gimenez95b,Gim98,GimCas05`.
The Calculus of Inductive Constructions with impredicative Set
-----------------------------------------------------------------
-|Coq| can be used as a type-checker for the Calculus of Inductive
+|Coq| can be used as a type checker for the Calculus of Inductive
Constructions with an impredicative sort :math:`\Set` by using the compiler
option ``-impredicative-set``. For example, using the ordinary `coqtop`
command, the following is rejected,
@@ -1832,7 +1852,7 @@ command, the following is rejected,
Fail Definition id: Set := forall X:Set,X->X.
-while it will type-check, if one uses instead the `coqtop`
+while it will type check, if one uses instead the `coqtop`
``-impredicative-set`` option..
The major change in the theory concerns the rule for product formation
diff --git a/doc/sphinx/language/coq-library.rst b/doc/sphinx/language/coq-library.rst
index 9de30e2190..85474a3e98 100644
--- a/doc/sphinx/language/coq-library.rst
+++ b/doc/sphinx/language/coq-library.rst
@@ -1,5 +1,3 @@
-.. include:: ../replaces.rst
-
.. _thecoqlibrary:
The |Coq| library
@@ -620,7 +618,7 @@ Finally, it gives the definition of the usual orderings ``le``,
Properties of these relations are not initially known, but may be
required by the user from modules ``Le`` and ``Lt``. Finally,
-``Peano`` gives some lemmas allowing pattern-matching, and a double
+``Peano`` gives some lemmas allowing pattern matching, and a double
induction principle.
.. index::
diff --git a/doc/sphinx/language/gallina-extensions.rst b/doc/sphinx/language/gallina-extensions.rst
index 7dd0a6e383..636144e0c8 100644
--- a/doc/sphinx/language/gallina-extensions.rst
+++ b/doc/sphinx/language/gallina-extensions.rst
@@ -1,5 +1,3 @@
-.. include:: ../replaces.rst
-
.. _extensionsofgallina:
Extensions of |Gallina|
@@ -22,7 +20,7 @@ expressions. In this sense, the :cmd:`Record` construction allows defining
.. _record_grammar:
- .. productionlist:: `sentence`
+ .. productionlist:: sentence
record : `record_keyword` `record_body` with … with `record_body`
record_keyword : Record | Inductive | CoInductive
record_body : `ident` [ `binders` ] [: `sort` ] := [ `ident` ] { [ `field` ; … ; `field` ] }.
@@ -82,11 +80,13 @@ To build an object of type :n:`@ident`, one should provide the constructor
Definition half := mkRat true 1 2 (O_S 1) one_two_irred.
Check half.
+.. FIXME: move this to the main grammar in the spec chapter
+
.. _record-named-fields-grammar:
.. productionlist::
- term : {| [`field_def` ; … ; `field_def`] |}
- field_def : name [binders] := `term`
+ record_term : {| [`field_def` ; … ; `field_def`] |}
+ field_def : name [binders] := `record_term`
Alternatively, the following syntax allows creating objects by using named fields, as
shown in this grammar. The fields do not have to be in any particular order, nor do they have
@@ -100,19 +100,25 @@ to be all present if the missing ones can be inferred or prompted for
Rat_bottom_cond := O_S 1;
Rat_irred_cond := one_two_irred |}.
-This syntax can be disabled globally for printing by
+The following settings let you control the display format for types:
+
+.. flag:: Printing Records
-.. cmd:: Unset Printing Records
+ If set, use the record syntax (shown above) as the default display format.
-For a given type, one can override this using either
+You can override the display format for specified types by adding entries to these tables:
-.. cmd:: Add Printing Record @ident
+.. table:: Printing Record @qualid
+ :name: Printing Record
-to get record syntax or
+ Specifies a set of qualids which are displayed as records. Use the
+ :cmd:`Add @table` and :cmd:`Remove @table` commands to update the set of qualids.
-.. cmd:: Add Printing Constructor @ident
+.. table:: Printing Constructor @qualid
+ :name: Printing Constructor
-to get constructor syntax.
+ Specifies a set of qualids which are displayed as constructors. Use the
+ :cmd:`Add @table` and :cmd:`Remove @table` commands to update the set of qualids.
This syntax can also be used for pattern matching.
@@ -145,7 +151,7 @@ available:
It can be activated for printing with
-.. opt:: Printing Projections
+.. flag:: Printing Projections
.. example::
@@ -154,12 +160,14 @@ It can be activated for printing with
Set Printing Projections.
Check top half.
+.. FIXME: move this to the main grammar in the spec chapter
+
.. _record_projections_grammar:
.. productionlist:: terms
- term : term `.` ( qualid )
- : | term `.` ( qualid arg … arg )
- : | term `.` ( @`qualid` `term` … `term` )
+ projection : projection `.` ( `qualid` )
+ : | projection `.` ( `qualid` `arg` … `arg` )
+ : | projection `.` ( @`qualid` `term` … `term` )
Syntax of Record projections
@@ -212,42 +220,42 @@ During the definition of the one-constructor inductive definition, all
the errors of inductive definitions, as described in Section
:ref:`gallina-inductive-definitions`, may also occur.
-**See also** Coercions and records in Section :ref:`coercions-classes-as-records` of the chapter devoted to coercions.
+.. seealso:: Coercions and records in section :ref:`coercions-classes-as-records` of the chapter devoted to coercions.
.. _primitive_projections:
Primitive Projections
~~~~~~~~~~~~~~~~~~~~~
-.. opt:: Primitive Projections
+.. flag:: Primitive Projections
-Turns on the use of primitive
-projections when defining subsequent records (even through the ``Inductive``
-and ``CoInductive`` commands). Primitive projections
-extended the Calculus of Inductive Constructions with a new binary
-term constructor `r.(p)` representing a primitive projection `p` applied
-to a record object `r` (i.e., primitive projections are always applied).
-Even if the record type has parameters, these do not appear at
-applications of the projection, considerably reducing the sizes of
-terms when manipulating parameterized records and typechecking time.
-On the user level, primitive projections can be used as a replacement
-for the usual defined ones, although there are a few notable differences.
+ Turns on the use of primitive
+ projections when defining subsequent records (even through the ``Inductive``
+ and ``CoInductive`` commands). Primitive projections
+ extended the Calculus of Inductive Constructions with a new binary
+ term constructor `r.(p)` representing a primitive projection `p` applied
+ to a record object `r` (i.e., primitive projections are always applied).
+ Even if the record type has parameters, these do not appear at
+ applications of the projection, considerably reducing the sizes of
+ terms when manipulating parameterized records and type checking time.
+ On the user level, primitive projections can be used as a replacement
+ for the usual defined ones, although there are a few notable differences.
-.. opt:: Printing Primitive Projection Parameters
+.. flag:: Printing Primitive Projection Parameters
-This compatibility option reconstructs internally omitted parameters at
-printing time (even though they are absent in the actual AST manipulated
-by the kernel).
+ This compatibility option reconstructs internally omitted parameters at
+ printing time (even though they are absent in the actual AST manipulated
+ by the kernel).
-.. opt:: Printing Primitive Projection Compatibility
+.. flag:: Printing Primitive Projection Compatibility
-This compatibility option (on by default) governs the
-printing of pattern-matching over primitive records.
+ This compatibility option (on by default) governs the
+ printing of pattern matching over primitive records.
Primitive Record Types
++++++++++++++++++++++
-When the :opt:`Primitive Projections` option is on, definitions of
+When the :flag:`Primitive Projections` option is on, definitions of
record types change meaning. When a type is declared with primitive
projections, its :g:`match` construct is disabled (see :ref:`primitive_projections` though).
To eliminate the (co-)inductive type, one must use its defined primitive projections.
@@ -257,9 +265,9 @@ To eliminate the (co-)inductive type, one must use its defined primitive project
For compatibility, the parameters still appear to the user when
printing terms even though they are absent in the actual AST
manipulated by the kernel. This can be changed by unsetting the
-``Printing Primitive Projection Parameters`` flag. Further compatibility
+:flag:`Printing Primitive Projection Parameters` flag. Further compatibility
printing can be deactivated thanks to the ``Printing Primitive Projection
-Compatibility`` option which governs the printing of pattern-matching
+Compatibility`` option which governs the printing of pattern matching
over primitive records.
There are currently two ways to introduce primitive records types:
@@ -289,7 +297,7 @@ the folded version delta-reduces to the unfolded version. This allows to
precisely mimic the usual unfolding rules of constants. Projections
obey the usual ``simpl`` flags of the ``Arguments`` command in particular.
There is currently no way to input unfolded primitive projections at the
-user-level, and one must use the ``Printing Primitive Projection Compatibility``
+user-level, and one must use the :flag:`Printing Primitive Projection Compatibility`
to display unfolded primitive projections as matches and distinguish them from folded ones.
@@ -302,7 +310,7 @@ an object of the record type as arguments, and whose body is an
application of the unfolded primitive projection of the same name. These
constants are used when elaborating partial applications of the
projection. One can distinguish them from applications of the primitive
-projection if the ``Printing Primitive Projection Parameters`` option
+projection if the :flag`Printing Primitive Projection Parameters` option
is off: For a primitive projection application, parameters are printed
as underscores while for the compatibility projections they are printed
as usual.
@@ -316,26 +324,26 @@ Variants and extensions of :g:`match`
.. _mult-match:
-Multiple and nested pattern-matching
+Multiple and nested pattern matching
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The basic version of :g:`match` allows pattern-matching on simple
+The basic version of :g:`match` allows pattern matching on simple
patterns. As an extension, multiple nested patterns or disjunction of
patterns are allowed, as in ML-like languages.
The extension just acts as a macro that is expanded during parsing
into a sequence of match on simple patterns. Especially, a
construction defined using the extended match is generally printed
-under its expanded form (see :opt:`Printing Matching`).
+under its expanded form (see :flag:`Printing Matching`).
-See also: :ref:`extendedpatternmatching`.
+.. seealso:: :ref:`extendedpatternmatching`.
.. _if-then-else:
Pattern-matching on boolean values: the if expression
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-For inductive types with exactly two constructors and for pattern-matching
+For inductive types with exactly two constructors and for pattern matching
expressions that do not depend on the arguments of the constructors, it is possible
to use a ``if … then … else`` notation. For instance, the definition
@@ -474,123 +482,93 @@ of :g:`match` expressions.
Printing nested patterns
+++++++++++++++++++++++++
-.. opt:: Printing Matching
+.. flag:: Printing Matching
-The Calculus of Inductive Constructions knows pattern-matching only
-over simple patterns. It is however convenient to re-factorize nested
-pattern-matching into a single pattern-matching over a nested
-pattern.
+ The Calculus of Inductive Constructions knows pattern matching only
+ over simple patterns. It is however convenient to re-factorize nested
+ pattern matching into a single pattern matching over a nested
+ pattern.
-When this option is on (default), |Coq|’s printer tries to do such
-limited re-factorization.
-Turning it off tells |Coq| to print only simple pattern-matching problems
-in the same way as the |Coq| kernel handles them.
+ When this option is on (default), |Coq|’s printer tries to do such
+ limited re-factorization.
+ Turning it off tells |Coq| to print only simple pattern matching problems
+ in the same way as the |Coq| kernel handles them.
Factorization of clauses with same right-hand side
++++++++++++++++++++++++++++++++++++++++++++++++++
-.. opt:: Printing Factorizable Match Patterns
+.. flag:: Printing Factorizable Match Patterns
-When several patterns share the same right-hand side, it is additionally
-possible to share the clauses using disjunctive patterns. Assuming that the
-printing matching mode is on, this option (on by default) tells |Coq|'s
-printer to try to do this kind of factorization.
+ When several patterns share the same right-hand side, it is additionally
+ possible to share the clauses using disjunctive patterns. Assuming that the
+ printing matching mode is on, this option (on by default) tells |Coq|'s
+ printer to try to do this kind of factorization.
Use of a default clause
+++++++++++++++++++++++
-.. opt:: Printing Allow Default Clause
+.. flag:: Printing Allow Match Default Clause
-When several patterns share the same right-hand side which do not depend on the
-arguments of the patterns, yet an extra factorization is possible: the
-disjunction of patterns can be replaced with a `_` default clause. Assuming that
-the printing matching mode and the factorization mode are on, this option (on by
-default) tells |Coq|'s printer to use a default clause when relevant.
+ When several patterns share the same right-hand side which do not depend on the
+ arguments of the patterns, yet an extra factorization is possible: the
+ disjunction of patterns can be replaced with a `_` default clause. Assuming that
+ the printing matching mode and the factorization mode are on, this option (on by
+ default) tells |Coq|'s printer to use a default clause when relevant.
Printing of wildcard patterns
++++++++++++++++++++++++++++++
-.. opt:: Printing Wildcard
+.. flag:: Printing Wildcard
-Some variables in a pattern may not occur in the right-hand side of
-the pattern-matching clause. When this option is on (default), the
-variables having no occurrences in the right-hand side of the
-pattern-matching clause are just printed using the wildcard symbol
-“_”.
+ Some variables in a pattern may not occur in the right-hand side of
+ the pattern matching clause. When this option is on (default), the
+ variables having no occurrences in the right-hand side of the
+ pattern matching clause are just printed using the wildcard symbol
+ “_”.
Printing of the elimination predicate
+++++++++++++++++++++++++++++++++++++
-.. opt:: Printing Synth
+.. flag:: Printing Synth
-In most of the cases, the type of the result of a matched term is
-mechanically synthesizable. Especially, if the result type does not
-depend of the matched term. When this option is on (default),
-the result type is not printed when |Coq| knows that it can re-
-synthesize it.
+ In most of the cases, the type of the result of a matched term is
+ mechanically synthesizable. Especially, if the result type does not
+ depend of the matched term. When this option is on (default),
+ the result type is not printed when |Coq| knows that it can re-
+ synthesize it.
Printing matching on irrefutable patterns
++++++++++++++++++++++++++++++++++++++++++
-If an inductive type has just one constructor, pattern-matching can be
+If an inductive type has just one constructor, pattern matching can be
written using the first destructuring let syntax.
-.. cmd:: Add Printing Let @ident
-
- This adds `ident` to the list of inductive types for which pattern-matching
- is written using a let expression.
-
-.. cmd:: Remove Printing Let @ident
-
- This removes ident from this list. Note that removing an inductive
- type from this list has an impact only for pattern-matching written
- using :g:`match`. Pattern-matching explicitly written using a destructuring
- :g:`let` are not impacted.
-
-.. cmd:: Test Printing Let for @ident
-
- This tells if `ident` belongs to the list.
-
-.. cmd:: Print Table Printing Let
+.. table:: Printing Let @qualid
+ :name: Printing Let
- This prints the list of inductive types for which pattern-matching is
- written using a let expression.
-
- The list of inductive types for which pattern-matching is written
- using a :g:`let` expression is managed synchronously. This means that it is
- sensitive to the command ``Reset``.
+ Specifies a set of qualids for which pattern matching is displayed using a let expression.
+ Note that this only applies to pattern matching instances entered with :g:`match`.
+ It doesn't affect pattern matching explicitly entered with a destructuring
+ :g:`let`.
+ Use the :cmd:`Add @table` and :cmd:`Remove @table` commands to update this set.
Printing matching on booleans
+++++++++++++++++++++++++++++
-If an inductive type is isomorphic to the boolean type, pattern-matching
-can be written using ``if`` … ``then`` … ``else`` …:
-
-.. cmd:: Add Printing If @ident
-
- This adds ident to the list of inductive types for which pattern-matching is
- written using an if expression.
-
-.. cmd:: Remove Printing If @ident
-
- This removes ident from this list.
+If an inductive type is isomorphic to the boolean type, pattern matching
+can be written using ``if`` … ``then`` … ``else`` …. This table controls
+which types are written this way:
-.. cmd:: Test Printing If for @ident
+.. table:: Printing If @qualid
+ :name: Printing If
- This tells if ident belongs to the list.
-
-.. cmd:: Print Table Printing If
-
- This prints the list of inductive types for which pattern-matching is
- written using an if expression.
-
-The list of inductive types for which pattern-matching is written
-using an ``if`` expression is managed synchronously. This means that it is
-sensitive to the command ``Reset``.
+ Specifies a set of qualids for which pattern matching is displayed using
+ ``if`` … ``then`` … ``else`` …. Use the :cmd:`Add @table` and :cmd:`Remove @table`
+ commands to update this set.
This example emphasizes what the printing options offer.
@@ -672,7 +650,7 @@ than like this:
*Limitations*
-|term_0| must be built as a *pure pattern-matching tree* (:g:`match … with`)
+|term_0| must be built as a *pure pattern matching tree* (:g:`match … with`)
with applications only *at the end* of each branch.
Function does not support partial application of the function being
@@ -700,7 +678,7 @@ terminating functions.
- the definition uses pattern matching on dependent types,
which ``Function`` cannot deal with yet.
- - the definition is not a *pattern-matching tree* as explained above.
+ - the definition is not a *pattern matching tree* as explained above.
.. warn:: Cannot define principle(s) for @ident.
@@ -711,7 +689,7 @@ terminating functions.
`functional inversion` will not be available for the function.
-See also: :ref:`functional-scheme` and :tacn:`function induction`
+.. seealso:: :ref:`functional-scheme` and :tacn:`function induction`
Depending on the ``{…}`` annotation, different definition mechanisms are
used by ``Function``. A more precise description is given below.
@@ -1238,7 +1216,7 @@ component is equal ``nat`` and hence ``M1.T`` as specified.
Prints the module type corresponding to :n:`@ident`.
-.. opt:: Short Module Printing
+.. flag:: Short Module Printing
This option (off by default) disables the printing of the types of fields,
leaving only their names, for the commands :cmd:`Print Module` and
@@ -1260,7 +1238,7 @@ identifiers qualid, i.e. as list of identifiers separated by dots (see
|Coq| library ``Arith`` is named ``Coq.Arith.Mult``. The identifier that starts
the name of a library is called a *library root*. All library files of
the standard library of |Coq| have the reserved root |Coq| but library
-file names based on other roots can be obtained by using |Coq| commands
+filenames based on other roots can be obtained by using |Coq| commands
(coqc, coqtop, coqdep, …) options ``-Q`` or ``-R`` (see :ref:`command-line-options`).
Also, when an interactive |Coq| session starts, a library of root ``Top`` is
started, unless option ``-top`` or ``-notop`` is set (see :ref:`command-line-options`).
@@ -1294,7 +1272,7 @@ short name (or even same partially qualified names as soon as the full
names are different).
Notice that the notion of absolute, partially qualified and short
-names also applies to library file names.
+names also applies to library filenames.
**Visibility**
@@ -1328,7 +1306,7 @@ accessible, absolute names can never be hidden.
Locate nat.
-See also: Commands :cmd:`Locate` and :cmd:`Locate Library`.
+.. seealso:: Commands :cmd:`Locate` and :cmd:`Locate Library`.
.. _libraries-and-filesystem:
@@ -1513,8 +1491,9 @@ says that the implicit argument is maximally inserted.
Each implicit argument can be declared to have to be inserted maximally or non
maximally. This can be governed argument per argument by the command
-:cmd:`Arguments (implicits)` or globally by the :opt:`Maximal Implicit Insertion` option.
-See also :ref:`displaying-implicit-args`.
+:cmd:`Arguments (implicits)` or globally by the :flag:`Maximal Implicit Insertion` option.
+
+.. seealso:: :ref:`displaying-implicit-args`.
Casual use of implicit arguments
@@ -1744,65 +1723,65 @@ appear strictly in the body of the type, they are implicit.
Mode for automatic declaration of implicit arguments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.. opt:: Implicit Arguments
+.. flag:: Implicit Arguments
-This option (off by default) allows to systematically declare implicit
-the arguments detectable as such. Auto-detection of implicit arguments is
-governed by options controlling whether strict and contextual implicit
-arguments have to be considered or not.
+ This option (off by default) allows to systematically declare implicit
+ the arguments detectable as such. Auto-detection of implicit arguments is
+ governed by options controlling whether strict and contextual implicit
+ arguments have to be considered or not.
.. _controlling-strict-implicit-args:
Controlling strict implicit arguments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.. opt:: Strict Implicit
+.. flag:: Strict Implicit
-When the mode for automatic declaration of implicit arguments is on,
-the default is to automatically set implicit only the strict implicit
-arguments plus, for historical reasons, a small subset of the non-strict
-implicit arguments. To relax this constraint and to set
-implicit all non strict implicit arguments by default, you can turn this
-option off.
+ When the mode for automatic declaration of implicit arguments is on,
+ the default is to automatically set implicit only the strict implicit
+ arguments plus, for historical reasons, a small subset of the non-strict
+ implicit arguments. To relax this constraint and to set
+ implicit all non strict implicit arguments by default, you can turn this
+ option off.
-.. opt:: Strongly Strict Implicit
+.. flag:: Strongly Strict Implicit
-Use this option (off by default) to capture exactly the strict implicit
-arguments and no more than the strict implicit arguments.
+ Use this option (off by default) to capture exactly the strict implicit
+ arguments and no more than the strict implicit arguments.
.. _controlling-contextual-implicit-args:
Controlling contextual implicit arguments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.. opt:: Contextual Implicit
+.. flag:: Contextual Implicit
-By default, |Coq| does not automatically set implicit the contextual
-implicit arguments. You can turn this option on to tell |Coq| to also
-infer contextual implicit argument.
+ By default, |Coq| does not automatically set implicit the contextual
+ implicit arguments. You can turn this option on to tell |Coq| to also
+ infer contextual implicit argument.
.. _controlling-rev-pattern-implicit-args:
Controlling reversible-pattern implicit arguments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.. opt:: Reversible Pattern Implicit
+.. flag:: Reversible Pattern Implicit
-By default, |Coq| does not automatically set implicit the reversible-pattern
-implicit arguments. You can turn this option on to tell |Coq| to also infer
-reversible-pattern implicit argument.
+ By default, |Coq| does not automatically set implicit the reversible-pattern
+ implicit arguments. You can turn this option on to tell |Coq| to also infer
+ reversible-pattern implicit argument.
.. _controlling-insertion-implicit-args:
Controlling the insertion of implicit arguments not followed by explicit arguments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.. opt:: Maximal Implicit Insertion
+.. flag:: Maximal Implicit Insertion
-Assuming the implicit argument mode is on, this option (off by default)
-declares implicit arguments to be automatically inserted when a
-function is partially applied and the next argument of the function is
-an implicit one.
+ Assuming the implicit argument mode is on, this option (off by default)
+ declares implicit arguments to be automatically inserted when a
+ function is partially applied and the next argument of the function is
+ an implicit one.
.. _explicit-applications:
@@ -1874,20 +1853,20 @@ if each of them is to be used maximally or not, use the command
Explicit displaying of implicit arguments for pretty-printing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.. opt:: Printing Implicit
+.. flag:: Printing Implicit
-By default, the basic pretty-printing rules hide the inferable implicit
-arguments of an application. Turn this option on to force printing all
-implicit arguments.
+ By default, the basic pretty-printing rules hide the inferable implicit
+ arguments of an application. Turn this option on to force printing all
+ implicit arguments.
-.. opt:: Printing Implicit Defensive
+.. flag:: Printing Implicit Defensive
-By default, the basic pretty-printing rules display the implicit
-arguments that are not detected as strict implicit arguments. This
-“defensive” mode can quickly make the display cumbersome so this can
-be deactivated by turning this option off.
+ By default, the basic pretty-printing rules display the implicit
+ arguments that are not detected as strict implicit arguments. This
+ “defensive” mode can quickly make the display cumbersome so this can
+ be deactivated by turning this option off.
-See also: :opt:`Printing All`.
+.. seealso:: :flag:`Printing All`.
Interaction with subtyping
~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1912,14 +1891,14 @@ but succeeds in
Deactivation of implicit arguments for parsing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.. opt:: Parsing Explicit
+.. flag:: Parsing Explicit
-Turning this option on (it is off by default) deactivates the use of implicit arguments.
+ Turning this option on (it is off by default) deactivates the use of implicit arguments.
-In this case, all arguments of constants, inductive types,
-constructors, etc, including the arguments declared as implicit, have
-to be given as if no arguments were implicit. By symmetry, this also
-affects printing.
+ In this case, all arguments of constants, inductive types,
+ constructors, etc, including the arguments declared as implicit, have
+ to be given as if no arguments were implicit. By symmetry, this also
+ affects printing.
Canonical structures
~~~~~~~~~~~~~~~~~~~~
@@ -1937,7 +1916,7 @@ in :ref:`canonicalstructures`; here only a simple example is given.
Assume that :token:`qualid` denotes an object ``(Build_struct`` |c_1| … |c_n| ``)`` in the
structure :g:`struct` of which the fields are |x_1|, …, |x_n|.
Then, each time an equation of the form ``(``\ |x_i| ``_)`` |eq_beta_delta_iota_zeta| |c_i| has to be
- solved during the type-checking process, :token:`qualid` is used as a solution.
+ solved during the type checking process, :token:`qualid` is used as a solution.
Otherwise said, :token:`qualid` is canonically used to extend the field |c_i|
into a complete structure built on |c_i|.
@@ -2131,32 +2110,32 @@ to coercions are provided in :ref:`implicitcoercions`.
Printing constructions in full
------------------------------
-.. opt:: Printing All
+.. flag:: Printing All
-Coercions, implicit arguments, the type of pattern-matching, but also
-notations (see :ref:`syntaxextensionsandinterpretationscopes`) can obfuscate the behavior of some
-tactics (typically the tactics applying to occurrences of subterms are
-sensitive to the implicit arguments). Turning this option on
-deactivates all high-level printing features such as coercions,
-implicit arguments, returned type of pattern-matching, notations and
-various syntactic sugar for pattern-matching or record projections.
-Otherwise said, :opt:`Printing All` includes the effects of the options
-:opt:`Printing Implicit`, :opt:`Printing Coercions`, :opt:`Printing Synth`,
-:opt:`Printing Projections`, and :opt:`Printing Notations`. To reactivate
-the high-level printing features, use the command ``Unset Printing All``.
+ Coercions, implicit arguments, the type of pattern matching, but also
+ notations (see :ref:`syntaxextensionsandinterpretationscopes`) can obfuscate the behavior of some
+ tactics (typically the tactics applying to occurrences of subterms are
+ sensitive to the implicit arguments). Turning this option on
+ deactivates all high-level printing features such as coercions,
+ implicit arguments, returned type of pattern matching, notations and
+ various syntactic sugar for pattern matching or record projections.
+ Otherwise said, :flag:`Printing All` includes the effects of the options
+ :flag:`Printing Implicit`, :flag:`Printing Coercions`, :flag:`Printing Synth`,
+ :flag:`Printing Projections`, and :flag:`Printing Notations`. To reactivate
+ the high-level printing features, use the command ``Unset Printing All``.
.. _printing-universes:
Printing universes
------------------
-.. opt:: Printing Universes
+.. flag:: Printing Universes
-Turn this option on to activate the display of the actual level of each
-occurrence of :g:`Type`. See :ref:`Sorts` for details. This wizard option, in
-combination with :opt:`Printing All` can help to diagnose failures to unify
-terms apparently identical but internally different in the Calculus of Inductive
-Constructions.
+ Turn this option on to activate the display of the actual level of each
+ occurrence of :g:`Type`. See :ref:`Sorts` for details. This wizard option, in
+ combination with :flag:`Printing All` can help to diagnose failures to unify
+ terms apparently identical but internally different in the Calculus of Inductive
+ Constructions.
The constraints on the internal level of the occurrences of Type
(see :ref:`Sorts`) can be printed using the command
@@ -2218,7 +2197,7 @@ form
is appending to its name, indicating how the variables of its defining context are instantiated.
The variables of the context of the existential variables which are
-instantiated by themselves are not written, unless the flag ``Printing Existential Instances``
+instantiated by themselves are not written, unless the flag :flag:`Printing Existential Instances`
is on (see Section :ref:`explicit-display-existentials`), and this is why an
existential variable used in the same context as its context of definition is written with no instance.
@@ -2240,11 +2219,11 @@ with a named-goal selector, see :ref:`goal-selectors`).
Explicit displaying of existential instances for pretty-printing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.. opt:: Printing Existential Instances
+.. flag:: Printing Existential Instances
-This option (off by default) activates the full display of how the
-context of an existential variable is instantiated at each of the
-occurrences of the existential variable.
+ This option (off by default) activates the full display of how the
+ context of an existential variable is instantiated at each of the
+ occurrences of the existential variable.
.. _tactics-in-terms:
diff --git a/doc/sphinx/language/gallina-specification-language.rst b/doc/sphinx/language/gallina-specification-language.rst
index da5cd00d72..593afa8f20 100644
--- a/doc/sphinx/language/gallina-specification-language.rst
+++ b/doc/sphinx/language/gallina-specification-language.rst
@@ -216,6 +216,11 @@ numbers (see :ref:`datatypes`).
Negative integers are not at the same level as :token:`num`, for this
would make precedence unnatural.
+.. index::
+ single: Set (sort)
+ single: Prop
+ single: Type
+
Sorts
-----
@@ -262,6 +267,8 @@ fun and forall gets identical. Moreover, parentheses can be omitted in
the case of a single sequence of bindings sharing the same type (e.g.:
:g:`fun (x y z : A) => t` can be shortened in :g:`fun x y z : A => t`).
+.. index:: fun ... => ...
+
Abstractions
------------
@@ -282,6 +289,8 @@ a let-binder occurs in
the list of binders, it is expanded to a let-in definition (see
Section :ref:`let-in`).
+.. index:: forall
+
Products
--------
@@ -320,6 +329,11 @@ The notation :n:`(@ident := @term)` for arguments is used for making
explicit the value of implicit arguments (see
Section :ref:`explicit-applications`).
+.. index::
+ single: ... : ... (type cast)
+ single: ... <: ...
+ single: ... <<: ...
+
Type cast
---------
@@ -329,6 +343,11 @@ the type of :token:`term` to be :token:`type`.
:n:`@term <: @type` locally sets up the virtual machine for checking that
:token:`term` has type :token:`type`.
+:n:`@term <<: @type` uses native compilation for checking that :token:`term`
+has type :token:`type`.
+
+.. index:: _
+
Inferable subterms
------------------
@@ -336,6 +355,8 @@ Expressions often contain redundant pieces of information. Subterms that can be
automatically inferred by Coq can be replaced by the symbol ``_`` and Coq will
guess the missing piece of information.
+.. index:: let ... := ... (term)
+
.. _let-in:
Let-in definitions
@@ -347,17 +368,19 @@ denotes the local binding of :token:`term` to the variable
definition of functions: :n:`let @ident {+ @binder} := @term in @term’`
stands for :n:`let @ident := fun {+ @binder} => @term in @term’`.
+.. index:: match ... with ...
+
Definition by case analysis
---------------------------
Objects of inductive types can be destructurated by a case-analysis
-construction called *pattern-matching* expression. A pattern-matching
+construction called *pattern matching* expression. A pattern matching
expression is used to analyze the structure of an inductive object and
to apply specific treatments accordingly.
-This paragraph describes the basic form of pattern-matching. See
+This paragraph describes the basic form of pattern matching. See
Section :ref:`Mult-match` and Chapter :ref:`extendedpatternmatching` for the description
-of the general form. The basic form of pattern-matching is characterized
+of the general form. The basic form of pattern matching is characterized
by a single :token:`match_item` expression, a :token:`mult_pattern` restricted to a
single :token:`pattern` and :token:`pattern` restricted to the form
:n:`@qualid {* @ident}`.
@@ -365,9 +388,9 @@ single :token:`pattern` and :token:`pattern` restricted to the form
The expression match ":token:`term`:math:`_0` :token:`return_type` with
:token:`pattern`:math:`_1` => :token:`term`:math:`_1` :math:`|` … :math:`|`
:token:`pattern`:math:`_n` => :token:`term`:math:`_n` end" denotes a
-*pattern-matching* over the term :token:`term`:math:`_0` (expected to be
+*pattern matching* over the term :token:`term`:math:`_0` (expected to be
of an inductive type :math:`I`). The terms :token:`term`:math:`_1`\ …\
-:token:`term`:math:`_n` are the *branches* of the pattern-matching
+:token:`term`:math:`_n` are the *branches* of the pattern matching
expression. Each of :token:`pattern`:math:`_i` has a form :token:`qualid`
:token:`ident` where :token:`qualid` must denote a constructor. There should be
exactly one branch for every constructor of :math:`I`.
@@ -380,7 +403,7 @@ inferred from the type of the branches [2]_.
In the *dependent* case, there are three subcases. In the first subcase,
the type in each branch may depend on the exact value being matched in
-the branch. In this case, the whole pattern-matching itself depends on
+the branch. In this case, the whole pattern matching itself depends on
the term being matched. This dependency of the term being matched in the
return type is expressed with an “as :token:`ident`” clause where :token:`ident`
is dependent in the return type. For instance, in the following example:
@@ -401,7 +424,7 @@ is dependent in the return type. For instance, in the following example:
the branches have respective types ":g:`or (eq bool true true) (eq bool true false)`"
and ":g:`or (eq bool false true) (eq bool false false)`" while the whole
-pattern-matching expression has type ":g:`or (eq bool b true) (eq bool b false)`",
+pattern matching expression has type ":g:`or (eq bool b true) (eq bool b false)`",
the identifier :g:`b` being used to represent the dependency.
.. note::
@@ -424,7 +447,7 @@ as the equality predicate (see Section :ref:`coq-equality`),
the order predicate on natural numbers or the type of lists of a given
length (see Section :ref:`matching-dependent`). In this configuration, the
type of each branch can depend on the type dependencies specific to the
-branch and the whole pattern-matching expression has a type determined
+branch and the whole pattern matching expression has a type determined
by the specific dependencies in the type of the term being matched. This
dependency of the return type in the annotations of the inductive type
is expressed using a “:g:`in` :math:`I` :g:`_ … _` :token:`pattern`:math:`_1` …
@@ -453,13 +476,13 @@ For instance, in the following example:
the type of the branch is :g:`eq A x x` because the third argument of
:g:`eq` is :g:`x` in the type of the pattern :g:`eq_refl`. On the contrary, the
-type of the whole pattern-matching expression has type :g:`eq A y x` because the
+type of the whole pattern matching expression has type :g:`eq A y x` because the
third argument of eq is y in the type of H. This dependency of the case analysis
in the third argument of :g:`eq` is expressed by the identifier :g:`z` in the
return type.
Finally, the third subcase is a combination of the first and second
-subcase. In particular, it only applies to pattern-matching on terms in
+subcase. In particular, it only applies to pattern matching on terms in
a type with annotations. For this third subcase, both the clauses ``as`` and
``in`` are available.
@@ -467,6 +490,10 @@ There are specific notations for case analysis on types with one or two
constructors: ``if … then … else …`` and ``let (…,…) := … in …`` (see
Sections :ref:`if-then-else` and :ref:`irrefutable-patterns`).
+.. index::
+ single: fix
+ single: cofix
+
Recursive functions
-------------------
@@ -495,7 +522,7 @@ The Vernacular
==============
.. productionlist:: coq
- decorated-sentence : [`decoration`] `sentence`
+ decorated-sentence : [ `decoration` … `decoration` ] `sentence`
sentence : `assumption`
: | `definition`
: | `inductive`
@@ -916,11 +943,11 @@ Parametrized inductive types
sort for the inductive definition and will produce a less convenient
rule for case elimination.
-.. opt:: Uniform Inductive Parameters
+.. flag:: Uniform Inductive Parameters
When this option is set (it is off by default),
inductive definitions are abstracted over their parameters
- before typechecking constructors, allowing to write:
+ before type checking constructors, allowing to write:
.. coqtop:: all undo
@@ -953,7 +980,7 @@ Variants
The :cmd:`Variant` command is identical to the :cmd:`Inductive` command, except
that it disallows recursive definition of types (for instance, lists cannot
be defined using :cmd:`Variant`). No induction scheme is generated for
- this variant, unless option :opt:`Nonrecursive Elimination Schemes` is on.
+ this variant, unless option :flag:`Nonrecursive Elimination Schemes` is on.
.. exn:: The @num th argument of @ident must be @ident in @type.
:undocumented:
@@ -1099,7 +1126,7 @@ constructions.
.. cmd:: Fixpoint @ident @binders {? {struct @ident} } {? : @type } := @term
- This command allows defining functions by pattern-matching over inductive
+ This command allows defining functions by pattern matching over inductive
objects using a fixed point construction. The meaning of this declaration is
to define :token:`ident` a recursive function with arguments specified by
the :token:`binders` such that :token:`ident` applied to arguments
@@ -1124,7 +1151,7 @@ constructions.
arguments, and this choice influences the reduction of the fixpoint.
Hence an explicit annotation must be used if the leftmost decreasing
argument is not the desired one. Writing explicit annotations can also
- speed up type-checking of large mutual fixpoints.
+ speed up type checking of large mutual fixpoints.
+ In order to keep the strong normalization property, the fixed point
reduction will only be performed when the argument in position of the
@@ -1302,7 +1329,7 @@ Chapter :ref:`Tactics`. The basic assertion command is:
You are asserting a new statement while already being in proof editing mode.
This feature, called nested proofs, is disabled by default.
- To activate it, turn option :opt:`Nested Proofs Allowed` on.
+ To activate it, turn option :flag:`Nested Proofs Allowed` on.
.. cmdv:: Lemma @ident {? @binders } : @type
Remark @ident {? @binders } : @type
@@ -1376,7 +1403,7 @@ using the keyword :cmd:`Qed`.
.. note::
#. Several statements can be simultaneously asserted provided option
- :opt:`Nested Proofs Allowed` was turned on.
+ :flag:`Nested Proofs Allowed` was turned on.
#. Not only other assertions but any vernacular command can be given
while in the process of proving a given assertion. In this case, the
@@ -1411,7 +1438,7 @@ Attributes
Any vernacular command can be decorated with a list of attributes, enclosed
between ``#[`` (hash and opening square bracket) and ``]`` (closing square bracket)
-and separated by commas ``,``.
+and separated by commas ``,``. Multiple space-separated blocks may be provided.
Each attribute has a name (an identifier) and may have a value.
A value is either a :token:`string` (in which case it is specified with an equal ``=`` sign),
diff --git a/doc/sphinx/language/module-system.rst b/doc/sphinx/language/module-system.rst
index e6a6736654..15fee91245 100644
--- a/doc/sphinx/language/module-system.rst
+++ b/doc/sphinx/language/module-system.rst
@@ -1,6 +1,3 @@
-.. include:: ../preamble.rst
-.. include:: ../replaces.rst
-
.. _themodulesystem:
The Module System
diff --git a/doc/sphinx/license.rst b/doc/sphinx/license.rst
new file mode 100644
index 0000000000..232b04211c
--- /dev/null
+++ b/doc/sphinx/license.rst
@@ -0,0 +1,4 @@
+This material (the Coq Reference Manual) 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
+http://www.opencontent.org/openpub). Options A and B are not elected.
diff --git a/doc/sphinx/practical-tools/coq-commands.rst b/doc/sphinx/practical-tools/coq-commands.rst
index 0f51b3eba3..de9e327740 100644
--- a/doc/sphinx/practical-tools/coq-commands.rst
+++ b/doc/sphinx/practical-tools/coq-commands.rst
@@ -1,5 +1,3 @@
-.. include:: ../replaces.rst
-
.. _thecoqcommands:
The |Coq| commands
@@ -87,14 +85,25 @@ Some |Coq| commands call other |Coq| commands. In this case, they look for
the commands in directory specified by ``$COQBIN``. If this variable is
not set, they look for the commands in the executable path.
+.. _COQ_COLORS:
+
The ``$COQ_COLORS`` environment variable can be used to specify the set
of colors used by ``coqtop`` to highlight its output. It uses the same
syntax as the ``$LS_COLORS`` variable from GNU’s ls, that is, a colon-separated
-list of assignments of the form ``name=``:n:``{*; attr}`` where
-``name`` is the name of the corresponding highlight tag and each ``attrᵢ`` is an
+list of assignments of the form :n:`name={*; attr}` where
+``name`` is the name of the corresponding highlight tag and each ``attr`` is an
ANSI escape code. The list of highlight tags can be retrieved with the
``-list-tags`` command-line option of ``coqtop``.
+The string uses ANSI escape codes to represent attributes. For example:
+
+ ``export COQ_COLORS=”diff.added=4;48;2;0;0;240:diff.removed=41”``
+
+sets the highlights for added text in diffs to underlined (the 4) with a background RGB
+color (0, 0, 240) and for removed text in diffs to a red background.
+Note that if you specify ``COQ_COLORS``, the predefined attributes are ignored.
+
+
.. _command-line-options:
By command line options
@@ -104,10 +113,14 @@ The following command-line options are recognized by the commands ``coqc``
and ``coqtop``, unless stated otherwise:
:-I *directory*, -include *directory*: Add physical path *directory*
- to the OCaml loadpath. See also: :ref:`names-of-libraries` and the
- command Declare ML Module Section :ref:`compiled-files`.
+ to the OCaml loadpath.
+
+ .. seealso::
+
+ :ref:`names-of-libraries` and the
+ command Declare ML Module Section :ref:`compiled-files`.
:-Q *directory* dirpath: Add physical path *directory* to the list of
- directories where |Coq| looks for a file and bind it to the the logical
+ directories where |Coq| looks for a file and bind it to the logical
directory *dirpath*. The subdirectory structure of *directory* is
recursively available from |Coq| using absolute names (extending the
dirpath prefix) (see Section :ref:`qualified-names`).Note that only those
@@ -115,14 +128,17 @@ and ``coqtop``, unless stated otherwise:
an :n:`@ident` are taken into account. Conversely, the
underlying file systems or operating systems may be more restrictive
than |Coq|. While Linux’s ext4 file system supports any |Coq| recursive
- layout (within the limit of 255 bytes per file name), the default on
+ layout (within the limit of 255 bytes per filename), the default on
NTFS (Windows) or HFS+ (MacOS X) file systems is on the contrary to
disallow two files differing only in the case in the same directory.
- See also: Section :ref:`names-of-libraries`.
+
+ .. seealso:: Section :ref:`names-of-libraries`.
:-R *directory* dirpath: Do as -Q *directory* dirpath but make the
subdirectory structure of *directory* recursively visible so that the
recursive contents of physical *directory* is available from |Coq| using
- short or partially qualified names. See also: Section :ref:`names-of-libraries`.
+ short or partially qualified names.
+
+ .. seealso:: Section :ref:`names-of-libraries`.
:-top dirpath: Set the toplevel module name to dirpath instead of Top.
Not valid for `coqc` as the toplevel module name is inferred from the
name of the output file.
@@ -159,20 +175,29 @@ and ``coqtop``, unless stated otherwise:
:-w (all|none|w₁,…,wₙ): Configure the display of warnings. This
option expects all, none or a comma-separated list of warning names or
categories (see Section :ref:`controlling-display`).
-:-color (on|off|auto): Enable or not the coloring of output of `coqtop`.
- Default is auto, meaning that `coqtop` dynamically decides, depending on
- whether the output channel supports ANSI escape sequences.
+:-color (on|off|auto): *Coqtop only*. Enable or disable color output.
+ Default is auto, meaning color is shown only if
+ the output channel supports ANSI escape sequences.
+:-diffs (on|off|removed): *Coqtop only*. Controls highlighting of differences
+ between proof steps. ``on`` highlights added tokens, ``removed`` highlights both added and
+ removed tokens. Requires that ``–color`` is enabled. (see Section
+ :ref:`showing_diffs`).
:-beautify: Pretty-print each command to *file.beautified* when
compiling *file.v*, in order to get old-fashioned
syntax/definitions/notations.
:-emacs, -ide-slave: Start a special toplevel to communicate with a
specific IDE.
:-impredicative-set: Change the logical theory of |Coq| by declaring the
- sort Set impredicative. Warning: This is known to be inconsistent with some
- standard axioms of classical mathematics such as the functional
- axiom of choice or the principle of description.
-:-type-in-type: Collapse the universe hierarchy of |Coq|. Warning: This makes the logic
- inconsistent.
+ sort Set impredicative.
+
+ .. warning::
+
+ This is known to be inconsistent with some
+ standard axioms of classical mathematics such as the functional
+ axiom of choice or the principle of description.
+:-type-in-type: Collapse the universe hierarchy of |Coq|.
+
+ .. warning:: This makes the logic inconsistent.
:-mangle-names *ident*: Experimental: Do not depend on this option. Replace
Coq's auto-generated name scheme with names of the form *ident0*, *ident1*,
etc. The command ``Set Mangle Names`` turns the behavior on in a document,
@@ -208,7 +233,7 @@ The ``coqchk`` command takes a list of library paths as argument, described eith
by their logical name or by their physical filename, hich must end in ``.vo``. The
corresponding compiled libraries (``.vo`` files) are searched in the path,
recursively processing the libraries they depend on. The content of all these
-libraries is then type-checked. The effect of ``coqchk`` is only to return with
+libraries is then type checked. The effect of ``coqchk`` is only to return with
normal exit code in case of success, and with positive exit code if an error has
been found. Error messages are not deemed to help the user understand what is
wrong. In the current version, it does not modify the compiled libraries to mark
@@ -248,15 +273,15 @@ the following: assuming that ``coqchk`` is called with argument ``M``, option
``-norec N``, and ``-admit A``. Let us write :math:`\overline{S}` for the
set of reflexive transitive dependencies of set :math:`S`. Then:
-+ Modules :math:`C = \overline{M} \backslash \overline{A} \cup M \cup N` are loaded and type-checked before being added
++ Modules :math:`C = \overline{M} \backslash \overline{A} \cup M \cup N` are loaded and type checked before being added
to the context.
+ And :math:`M \cup N \backslash C` is the set of modules that are loaded and added to the
- context without type-checking. Basic integrity checks (checksums) are
+ context without type checking. Basic integrity checks (checksums) are
nonetheless performed.
As a rule of thumb, -admit can be used to tell Coq that some libraries
have already been checked. So ``coqchk A B`` can be split in ``coqchk A`` &&
-``coqchk B -admit A`` without type-checking any definition twice. Of
+``coqchk B -admit A`` without type checking any definition twice. Of
course, the latter is slightly slower since it makes more disk access.
It is also less secure since an attacker might have replaced the
compiled library ``A`` after it has been read by the first command, but
diff --git a/doc/sphinx/practical-tools/coqide.rst b/doc/sphinx/practical-tools/coqide.rst
index f7f442092f..9455228e7d 100644
--- a/doc/sphinx/practical-tools/coqide.rst
+++ b/doc/sphinx/practical-tools/coqide.rst
@@ -1,5 +1,3 @@
-.. include:: ../replaces.rst
-
.. _coqintegrateddevelopmentenvironment:
|Coq| Integrated Development Environment
@@ -12,7 +10,7 @@ file, executing corresponding commands or undoing them respectively.
|CoqIDE| is run by typing the command `coqide` on the command line.
Without argument, the main screen is displayed with an “unnamed
-buffer”, and with a file name as argument, another buffer displaying
+buffer”, and with a filename as argument, another buffer displaying
the contents of that file. Additionally, `coqide` accepts the same
options as `coqtop`, given in :ref:`thecoqcommands`, the ones having obviously
no meaning for |CoqIDE| being ignored.
@@ -92,7 +90,7 @@ buffers (left and right arrows); an "information" button; and a "gears" button.
The "information" button is described in Section :ref:`try-tactics-automatically`.
-The "gears" button submits proof terms to the |Coq| kernel for type-checking.
+The "gears" button submits proof terms to the |Coq| kernel for type checking.
When |Coq| uses asynchronous processing (see Chapter :ref:`asynchronousandparallelproofprocessing`),
proofs may have been completed without kernel-checking of generated proof terms.
The presence of unchecked proof terms is indicated by ``Qed`` statements that
@@ -263,7 +261,7 @@ for the ∀ symbol. A list of symbol codes is available at
An alternative method which does not require to know the hexadecimal
code of the character is to use an Input Method Editor. On POSIX
systems (Linux distributions, BSD variants and MacOS X), you can
-use `uim` version 1.6 or later which provides a :math:`\LaTeX`-style input
+use `uim` version 1.6 or later which provides a LaTeX-style input
method.
To configure uim, execute uim-pref-gtk as your regular user. In the
diff --git a/doc/sphinx/practical-tools/utilities.rst b/doc/sphinx/practical-tools/utilities.rst
index e779515a00..5d300c3d6d 100644
--- a/doc/sphinx/practical-tools/utilities.rst
+++ b/doc/sphinx/practical-tools/utilities.rst
@@ -1,5 +1,3 @@
-.. include:: ../replaces.rst
-
.. _utilities:
---------------------
@@ -43,7 +41,7 @@ Building a |Coq| project with coq_makefile
The majority of |Coq| projects are very similar: a collection of ``.v``
files and eventually some ``.ml`` ones (a |Coq| plugin). The main piece of
metadata needed in order to build the project are the command line
-options to ``coqc`` (e.g. ``-R``, ``-I``, see also: Section
+options to ``coqc`` (e.g. ``-R``, ``-I``, see also: section
:ref:`command-line-options`). Collecting the list of files and options is the job
of the ``_CoqProject`` file.
@@ -107,7 +105,7 @@ decide how to build them. In particular:
The use of ``.mlpack`` files has to be preferred over ``.mllib`` files,
since it results in a “packed” plugin: All auxiliary modules (as
-``Baz`` and ``Bazaux``) are hidden inside the plugin’s “name space”
+``Baz`` and ``Bazaux``) are hidden inside the plugin’s "namespace"
(``Qux_plugin``). This reduces the chances of begin unable to load two
distinct plugins because of a clash in their auxiliary module names.
@@ -268,13 +266,12 @@ file timing data:
+ ``print-pretty-timed-diff``
- this target builds a table of timing
- changes between two compilations; run ``make make-pretty-timed-before`` to
- build the log of the “before” times, and run ``make make-pretty-timed-
- after`` to build the log of the “after” times. The table is printed on
- the command line, and stored in ``time-of-build-both.log``. This target is
- most useful for profiling the difference between two commits to a
- repo.
+ this target builds a table of timing changes between two compilations; run
+ ``make make-pretty-timed-before`` to build the log of the “before” times,
+ and run ``make make-pretty-timed-after`` to build the log of the “after”
+ times. The table is printed on the command line, and stored in
+ ``time-of-build-both.log``. This target is most useful for profiling the
+ difference between two commits in a repository.
.. note::
This target requires ``python`` to build the table.
@@ -331,7 +328,9 @@ line timing data:
Chars 163 - 208 [Definition~foo1~:=~Eval~comp~i...] 0.239 secs (0.236u,0.s)
+ ``print-pretty-single-time-diff``
+
::
+
print-pretty-single-time-diff BEFORE=path/to/file.v.before-timing AFTER=path/to/file.v.after-timing
this target will make a sorted table of the per-line timing differences
@@ -773,7 +772,7 @@ Command line options
preamble, right before ``\begin{document}`` (meaningless with ``-html``).
:--vernac-file file,--tex-file file: Considers the file ‘file’
respectively as a ``.v`` (or ``.g``) file or a ``.tex`` file.
- :--files-from file: Read file names to be processed from the file ‘file’ as if
+ :--files-from file: Read filenames to be processed from the file ‘file’ as if
they were given on the command line. Useful for program sources split
up into several directories.
:-q, --quiet: Be quiet. Do not print anything except errors.
diff --git a/doc/sphinx/preamble.rst b/doc/sphinx/preamble.rst
deleted file mode 100644
index 395f558a85..0000000000
--- a/doc/sphinx/preamble.rst
+++ /dev/null
@@ -1,92 +0,0 @@
-.. preamble::
-
- \[
- \newcommand{\alors}{\textsf{then}}
- \newcommand{\alter}{\textsf{alter}}
- \newcommand{\as}{\kw{as}}
- \newcommand{\Assum}[3]{\kw{Assum}(#1)(#2:#3)}
- \newcommand{\bool}{\textsf{bool}}
- \newcommand{\case}{\kw{case}}
- \newcommand{\conc}{\textsf{conc}}
- \newcommand{\cons}{\textsf{cons}}
- \newcommand{\consf}{\textsf{consf}}
- \newcommand{\conshl}{\textsf{cons\_hl}}
- \newcommand{\Def}[4]{\kw{Def}(#1)(#2:=#3:#4)}
- \newcommand{\emptyf}{\textsf{emptyf}}
- \newcommand{\End}{\kw{End}}
- \newcommand{\endkw}{\kw{end}}
- \newcommand{\EqSt}{\textsf{EqSt}}
- \newcommand{\even}{\textsf{even}}
- \newcommand{\evenO}{\textsf{even_O}}
- \newcommand{\evenS}{\textsf{even_S}}
- \newcommand{\false}{\textsf{false}}
- \newcommand{\filter}{\textsf{filter}}
- \newcommand{\Fix}{\kw{Fix}}
- \newcommand{\fix}{\kw{fix}}
- \newcommand{\for}{\textsf{for}}
- \newcommand{\forest}{\textsf{forest}}
- \newcommand{\from}{\textsf{from}}
- \newcommand{\Functor}{\kw{Functor}}
- \newcommand{\haslength}{\textsf{has\_length}}
- \newcommand{\hd}{\textsf{hd}}
- \newcommand{\ident}{\textsf{ident}}
- \newcommand{\In}{\kw{in}}
- \newcommand{\Ind}[4]{\kw{Ind}[#2](#3:=#4)}
- \newcommand{\ind}[3]{\kw{Ind}~[#1]\left(#2\mathrm{~:=~}#3\right)}
- \newcommand{\Indp}[5]{\kw{Ind}_{#5}(#1)[#2](#3:=#4)}
- \newcommand{\Indpstr}[6]{\kw{Ind}_{#5}(#1)[#2](#3:=#4)/{#6}}
- \newcommand{\injective}{\kw{injective}}
- \newcommand{\kw}[1]{\textsf{#1}}
- \newcommand{\lb}{\lambda}
- \newcommand{\length}{\textsf{length}}
- \newcommand{\letin}[3]{\kw{let}~#1:=#2~\kw{in}~#3}
- \newcommand{\List}{\textsf{list}}
- \newcommand{\lra}{\longrightarrow}
- \newcommand{\Match}{\kw{match}}
- \newcommand{\Mod}[3]{{\kw{Mod}}({#1}:{#2}\,\zeroone{:={#3}})}
- \newcommand{\ModA}[2]{{\kw{ModA}}({#1}=={#2})}
- \newcommand{\ModS}[2]{{\kw{Mod}}({#1}:{#2})}
- \newcommand{\ModType}[2]{{\kw{ModType}}({#1}:={#2})}
- \newcommand{\mto}{.\;}
- \newcommand{\Nat}{\mathbb{N}}
- \newcommand{\nat}{\textsf{nat}}
- \newcommand{\Nil}{\textsf{nil}}
- \newcommand{\nilhl}{\textsf{nil\_hl}}
- \newcommand{\nO}{\textsf{O}}
- \newcommand{\node}{\textsf{node}}
- \newcommand{\nS}{\textsf{S}}
- \newcommand{\odd}{\textsf{odd}}
- \newcommand{\oddS}{\textsf{odd_S}}
- \newcommand{\ovl}[1]{\overline{#1}}
- \newcommand{\Pair}{\textsf{pair}}
- \newcommand{\Prod}{\textsf{prod}}
- \newcommand{\Prop}{\textsf{Prop}}
- \newcommand{\return}{\kw{return}}
- \newcommand{\Set}{\textsf{Set}}
- \newcommand{\si}{\textsf{if}}
- \newcommand{\sinon}{\textsf{else}}
- \newcommand{\Sort}{\cal S}
- \newcommand{\Str}{\textsf{Stream}}
- \newcommand{\Struct}{\kw{Struct}}
- \newcommand{\subst}[3]{#1\{#2/#3\}}
- \newcommand{\tl}{\textsf{tl}}
- \newcommand{\tree}{\textsf{tree}}
- \newcommand{\true}{\textsf{true}}
- \newcommand{\Type}{\textsf{Type}}
- \newcommand{\unfold}{\textsf{unfold}}
- \newcommand{\WEV}[3]{\mbox{$#1[] \vdash #2 \lra #3$}}
- \newcommand{\WEVT}[3]{\mbox{$#1[] \vdash #2 \lra$}\\ \mbox{$ #3$}}
- \newcommand{\WF}[2]{{\cal W\!F}(#1)[#2]}
- \newcommand{\WFE}[1]{\WF{E}{#1}}
- \newcommand{\WFT}[2]{#1[] \vdash {\cal W\!F}(#2)}
- \newcommand{\WFTWOLINES}[2]{{\cal W\!F}\begin{array}{l}(#1)\\\mbox{}[{#2}]\end{array}}
- \newcommand{\with}{\kw{with}}
- \newcommand{\WS}[3]{#1[] \vdash #2 <: #3}
- \newcommand{\WSE}[2]{\WS{E}{#1}{#2}}
- \newcommand{\WT}[4]{#1[#2] \vdash #3 : #4}
- \newcommand{\WTE}[3]{\WT{E}{#1}{#2}{#3}}
- \newcommand{\WTEG}[2]{\WTE{\Gamma}{#1}{#2}}
- \newcommand{\WTM}[3]{\WT{#1}{}{#2}{#3}}
- \newcommand{\zeroone}[1]{[{#1}]}
- \newcommand{\zeros}{\textsf{zeros}}
- \]
diff --git a/doc/sphinx/proof-engine/detailed-tactic-examples.rst b/doc/sphinx/proof-engine/detailed-tactic-examples.rst
index 225df8d54c..bd16b70d02 100644
--- a/doc/sphinx/proof-engine/detailed-tactic-examples.rst
+++ b/doc/sphinx/proof-engine/detailed-tactic-examples.rst
@@ -21,7 +21,7 @@ applied to the abstracted instance and after simplification of the
equalities we get the expected goals.
The abstracting tactic is called generalize_eqs and it takes as
-argument an hypothesis to generalize. It uses the JMeq datatype
+argument a hypothesis to generalize. It uses the JMeq datatype
defined in Coq.Logic.JMeq, hence we need to require it before. For
example, revisiting the first example of the inversion documentation:
@@ -417,219 +417,8 @@ the optional tactic of the ``Hint Rewrite`` command.
Qed.
-.. _quote:
-
-quote
------
-
-The tactic ``quote`` allows using Barendregt’s so-called 2-level approach
-without writing any ML code. Suppose you have a language ``L`` of
-'abstract terms' and a type ``A`` of 'concrete terms' and a function ``f : L -> A``.
-If ``L`` is a simple inductive datatype and ``f`` a simple fixpoint,
-``quote f`` will replace the head of current goal by a convertible term of
-the form ``(f t)``. ``L`` must have a constructor of type: ``A -> L``.
-
-Here is an example:
-
-.. coqtop:: in reset
-
- Require Import Quote.
-
-.. coqtop:: all
-
- Parameters A B C : Prop.
-
-.. coqtop:: all
-
- Inductive formula : Type :=
- | f_and : formula -> formula -> formula (* binary constructor *)
- | f_or : formula -> formula -> formula
- | f_not : formula -> formula (* unary constructor *)
- | f_true : formula (* 0-ary constructor *)
- | f_const : Prop -> formula (* constructor for constants *).
-
-.. coqtop:: all
-
- Fixpoint interp_f (f:formula) : Prop :=
- match f with
- | f_and f1 f2 => interp_f f1 /\ interp_f f2
- | f_or f1 f2 => interp_f f1 \/ interp_f f2
- | f_not f1 => ~ interp_f f1
- | f_true => True
- | f_const c => c
- end.
-
-.. coqtop:: all
-
- Goal A /\ (A \/ True) /\ ~ B /\ (A <-> A).
-
-.. coqtop:: all
-
- quote interp_f.
-
-The algorithm to perform this inversion is: try to match the term with
-right-hand sides expression of ``f``. If there is a match, apply the
-corresponding left-hand side and call yourself recursively on sub-
-terms. If there is no match, we are at a leaf: return the
-corresponding constructor (here ``f_const``) applied to the term.
-
-.. exn:: quote: not a simple fixpoint
-
- Happens when ``quote`` is not able to perform inversion properly.
-
-
-Introducing variables map
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The normal use of quote is to make proofs by reflection: one defines a
-function ``simplify : formula -> formula`` and proves a theorem
-``simplify_ok: (f:formula)(interp_f (simplify f)) -> (interp_f f)``. Then,
-one can simplify formulas by doing:
-
-.. coqtop:: in
-
- quote interp_f.
- apply simplify_ok.
- compute.
-
-But there is a problem with leafs: in the example above one cannot
-write a function that implements, for example, the logical
-simplifications :math:`A \wedge A \rightarrow A` or :math:`A \wedge
-\lnot A \rightarrow \mathrm{False}`. This is because ``Prop`` is
-impredicative.
-
-It is better to use that type of formulas:
-
-.. coqtop:: in reset
-
- Require Import Quote.
-
-.. coqtop:: in
-
- Parameters A B C : Prop.
-
-.. coqtop:: all
-
- Inductive formula : Set :=
- | f_and : formula -> formula -> formula
- | f_or : formula -> formula -> formula
- | f_not : formula -> formula
- | f_true : formula
- | f_atom : index -> formula.
-
-``index`` is defined in module ``Quote``. Equality on that type is
-decidable so we are able to simplify :math:`A \wedge A` into :math:`A`
-at the abstract level.
-
-When there are variables, there are bindings, and ``quote`` also
-provides a type ``(varmap A)`` of bindings from index to any set
-``A``, and a function ``varmap_find`` to search in such maps. The
-interpretation function also has another argument, a variables map:
-
-.. coqtop:: all
-
- Fixpoint interp_f (vm:varmap Prop) (f:formula) {struct f} : Prop :=
- match f with
- | f_and f1 f2 => interp_f vm f1 /\ interp_f vm f2
- | f_or f1 f2 => interp_f vm f1 \/ interp_f vm f2
- | f_not f1 => ~ interp_f vm f1
- | f_true => True
- | f_atom i => varmap_find True i vm
- end.
-
-``quote`` handles this second case properly:
-
-.. coqtop:: all
-
- Goal A /\ (B \/ A) /\ (A \/ ~ B).
-
-.. coqtop:: all
-
- quote interp_f.
-
-It builds ``vm`` and ``t`` such that ``(f vm t)`` is convertible with the
-conclusion of current goal.
-
-
-Combining variables and constants
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-One can have both variables and constants in abstracts terms; for
-example, this is the case for the :tacn:`ring` tactic. Then one must provide to
-``quote`` a list of *constructors of constants*. For example, if the list
-is ``[O S]`` then closed natural numbers will be considered as constants
-and other terms as variables.
-
-.. coqtop:: in reset
-
- Require Import Quote.
-
-.. coqtop:: in
-
- Parameters A B C : Prop.
-
-.. coqtop:: in
-
- Inductive formula : Type :=
- | f_and : formula -> formula -> formula
- | f_or : formula -> formula -> formula
- | f_not : formula -> formula
- | f_true : formula
- | f_const : Prop -> formula (* constructor for constants *)
- | f_atom : index -> formula.
-
-.. coqtop:: in
-
- Fixpoint interp_f (vm:varmap Prop) (f:formula) {struct f} : Prop :=
- match f with
- | f_and f1 f2 => interp_f vm f1 /\ interp_f vm f2
- | f_or f1 f2 => interp_f vm f1 \/ interp_f vm f2
- | f_not f1 => ~ interp_f vm f1
- | f_true => True
- | f_const c => c
- | f_atom i => varmap_find True i vm
- end.
-
-.. coqtop:: in
-
- Goal A /\ (A \/ True) /\ ~ B /\ (C <-> C).
-
-.. coqtop:: all
-
- quote interp_f [ A B ].
-
-
-.. coqtop:: all
-
- Undo.
-
-.. coqtop:: all
-
- quote interp_f [ B C iff ].
-
-.. warning::
- Since functional inversion is undecidable in the general case,
- don’t expect miracles from it!
-
-.. tacv:: quote @ident in @term using @tactic
-
- ``tactic`` must be a functional tactic (starting with ``fun x =>``) and
- will be called with the quoted version of term according to ``ident``.
-
-.. tacv:: quote @ident [{+ @ident}] in @term using @tactic
-
- Same as above, but will use the additional ``ident`` list to chose
- which subterms are constants (see above).
-
-.. seealso::
- Comments from the source file ``plugins/quote/quote.ml``
-
-.. seealso::
- The :tacn:`ring` tactic.
-
-
Using the tactic language
----------------------------
+-------------------------
About the cardinality of the set of natural numbers
diff --git a/doc/sphinx/proof-engine/ltac.rst b/doc/sphinx/proof-engine/ltac.rst
index dc355fa013..edd83b7cee 100644
--- a/doc/sphinx/proof-engine/ltac.rst
+++ b/doc/sphinx/proof-engine/ltac.rst
@@ -1,6 +1,3 @@
-.. include:: ../preamble.rst
-.. include:: ../replaces.rst
-
.. _ltac:
The tactic language
@@ -27,14 +24,14 @@ represent respectively the natural and integer numbers, the authorized
identificators and qualified names, Coq terms and patterns and all the atomic
tactics described in Chapter :ref:`tactics`. The syntax of :token:`cpattern` is
the same as that of terms, but it is extended with pattern matching
-metavariables. In :token:`cpattern`, a pattern-matching metavariable is
+metavariables. In :token:`cpattern`, a pattern matching metavariable is
represented with the syntax :g:`?id` where :g:`id` is an :token:`ident`. The
notation :g:`_` can also be used to denote metavariable whose instance is
irrelevant. In the notation :g:`?id`, the identifier allows us to keep
instantiations and to make constraints whereas :g:`_` shows that we are not
-interested in what will be matched. On the right hand side of pattern-matching
+interested in what will be matched. On the right hand side of pattern matching
clauses, the named metavariables are used without the question mark prefix. There
-is also a special notation for second-order pattern-matching problems: in an
+is also a special notation for second-order pattern matching problems: in an
applicative pattern of the form :g:`@?id id1 … idn`, the variable id matches any
complex expression with (possible) dependencies in the variables :g:`id1 … idn`
and returns a functional term of the form :g:`fun id1 … idn => term`.
@@ -107,7 +104,7 @@ mode but it can also be used in toplevel definitions as shown below.
: | solve [ `expr` | ... | `expr` ]
: | idtac [ `message_token` ... `message_token`]
: | fail [`natural`] [`message_token` ... `message_token`]
- : | fresh | fresh `string` | fresh `qualid`
+ : | fresh [ `component` … `component` ]
: | context `ident` [`term`]
: | eval `redexpr` in `term`
: | type of `term`
@@ -125,6 +122,7 @@ mode but it can also be used in toplevel definitions as shown below.
: | ()
: | `integer`
: | ( `expr` )
+ component : `string` | `qualid`
message_token : `string` | `ident` | `integer`
tacarg : `qualid`
: | ()
@@ -144,10 +142,11 @@ mode but it can also be used in toplevel definitions as shown below.
: | `integer` (< | <= | > | >=) `integer`
selector : [`ident`]
: | `integer`
- : (`integer` | `integer` - `integer`), ..., (`integer` | `integer` - `integer`)
+ : | (`integer` | `integer` - `integer`), ..., (`integer` | `integer` - `integer`)
toplevel_selector : `selector`
- : | `all`
- : | `par`
+ : | all
+ : | par
+ : | !
.. productionlist:: coq
top : [Local] Ltac `ltac_def` with ... with `ltac_def`
@@ -177,7 +176,7 @@ Sequence
A sequence is an expression of the following form:
-.. tacn:: @expr ; @expr
+.. tacn:: @expr__1 ; @expr__2
:name: ltac-seq
The expression :n:`@expr__1` is evaluated to :n:`v__1`, which must be
@@ -207,11 +206,11 @@ following form:
were given. For instance, ``[> | auto]`` is a shortcut for ``[> idtac | auto
]``.
- .. tacv:: [> {*| @expr} | @expr .. | {*| @expr}]
+ .. tacv:: [> {*| @expr__i} | @expr .. | {*| @expr__j}]
- In this variant, token:`expr` is used for each goal coming after those
- covered by the first list of :n:`@expr` but before those coevered by the
- last list of :n:`@expr`.
+ In this variant, :n:`@expr` is used for each goal coming after those
+ covered by the list of :n:`@expr__i` but before those covered by the
+ list of :n:`@expr__j`.
.. tacv:: [> {*| @expr} | .. | {*| @expr}]
@@ -225,11 +224,11 @@ following form:
tactic is not run at all. A tactic which expects multiple goals, such as
``swap``, would act as if a single goal is focused.
- .. tacv:: expr ; [{*| @expr}]
+ .. tacv:: @expr__0 ; [{*| @expr__i}]
This variant of local tactic application is paired with a sequence. In this
- variant, there must be as many :n:`@expr` in the list as goals generated
- by the application of the first :n:`@expr` to each of the individual goals
+ variant, there must be as many :n:`@expr__i` as goals generated
+ by the application of :n:`@expr__0` to each of the individual goals
independently. All the above variants work in this form too.
Formally, :n:`@expr ; [ ... ]` is equivalent to :n:`[> @expr ; [> ... ] .. ]`.
@@ -247,20 +246,20 @@ focused goals with:
We can also use selectors as a tactical, which allows to use them nested
in a tactic expression, by using the keyword ``only``:
- .. tacv:: only selector : expr
+ .. tacv:: only @selector : @expr
:name: only ... : ...
- When selecting several goals, the tactic expr is applied globally to all
+ When selecting several goals, the tactic :token:`expr` is applied globally to all
selected goals.
.. tacv:: [@ident] : @expr
- In this variant, :n:`@expr` is applied locally to a goal previously named
+ In this variant, :token:`expr` is applied locally to a goal previously named
by the user (see :ref:`existential-variables`).
.. tacv:: @num : @expr
- In this variant, :n:`@expr` is applied locally to the :token:`num`-th goal.
+ In this variant, :token:`expr` is applied locally to the :token:`num`-th goal.
.. tacv:: {+, @num-@num} : @expr
@@ -271,13 +270,13 @@ focused goals with:
.. tacv:: all: @expr
:name: all: ...
- In this variant, :n:`@expr` is applied to all focused goals. ``all:`` can only
+ In this variant, :token:`expr` is applied to all focused goals. ``all:`` can only
be used at the toplevel of a tactic expression.
.. tacv:: !: @expr
- In this variant, if exactly one goal is focused :n:`expr` is
- applied to it. Otherwise the tactical fails. ``!:`` can only be
+ In this variant, if exactly one goal is focused, :token:`expr` is
+ applied to it. Otherwise the tactic fails. ``!:`` can only be
used at the toplevel of a tactic expression.
.. tacv:: par: @expr
@@ -390,7 +389,7 @@ tactic to work (i.e. which does not fail) among a panel of tactics:
focused goal independently and stops if it succeeds; otherwise it
tries to apply :n:`v__2` and so on. It fails when there is no
applicable tactic. In other words,
- :n:`first [@expr__1 | ... | @expr__n]` behaves, in each goal, as the the first
+ :n:`first [@expr__1 | ... | @expr__n]` behaves, in each goal, as the first
:n:`v__i` to have *at least* one success.
.. exn:: No applicable tactic.
@@ -555,9 +554,9 @@ Failing
The number is the failure level. If no level is specified, it defaults to 0.
The level is used by :tacn:`try`, :tacn:`repeat`, :tacn:`match goal` and the branching
tacticals. If 0, it makes :tacn:`match goal` consider the next clause
- (backtracking). If non zero, the current :tacn:`match goal` block, :tacn:`try`,
+ (backtracking). If nonzero, the current :tacn:`match goal` block, :tacn:`try`,
:tacn:`repeat`, or branching command is aborted and the level is decremented. In
- the case of :n:`+`, a non-zero level skips the first backtrack point, even if
+ the case of :n:`+`, a nonzero level skips the first backtrack point, even if
the call to :n:`fail @num` is not enclosed in a :n:`+` command,
respecting the algebraic identity.
@@ -715,6 +714,7 @@ Local definitions
Local definitions can be done as follows:
.. tacn:: let @ident__1 := @expr__1 {* with @ident__i := @expr__i} in @expr
+ :name: let ... := ...
each :n:`@expr__i` is evaluated to :n:`v__i`, then, :n:`@expr` is evaluated
by substituting :n:`v__i` to each occurrence of :n:`@ident__i`, for
@@ -833,7 +833,7 @@ We can carry out pattern matching on terms with:
matching subterm is tried. If no further subterm matches, the next clause
is tried. Matching subterms are considered top-bottom and from left to
right (with respect to the raw printing obtained by setting option
- :opt:`Printing All`).
+ :flag:`Printing All`).
.. example::
@@ -862,7 +862,7 @@ We can perform pattern matching on goals using the following expression:
:name: match goal
If each hypothesis pattern :n:`hyp`\ :sub:`1,i`, with i = 1, ..., m\ :sub:`1` is
- matched (non-linear first-order unification) by an hypothesis of the
+ matched (non-linear first-order unification) by a hypothesis of the
goal and if :n:`cpattern_1` is matched by the conclusion of the goal,
then :n:`@expr__1` is evaluated to :n:`v__1` by substituting the
pattern matching to the metavariables and the real hypothesis names
@@ -945,12 +945,10 @@ expression returns an identifier:
.. tacn:: fresh {* component}
It evaluates to an identifier unbound in the goal. This fresh identifier
- is obtained by concatenating the value of the :n:`@component`s (each of them
+ is obtained by concatenating the value of the :n:`@component`\ s (each of them
is, either a :n:`@qualid` which has to refer to a (unqualified) name, or
directly a name denoted by a :n:`@string`).
- .. I don't understand this component thing. Couldn't we give the grammar?
-
If the resulting name is already used, it is padded with a number so that it
becomes fresh. If no component is given, the name is a fresh derivative of
the name ``H``.
@@ -988,7 +986,7 @@ Manipulating untyped terms
An untyped term, in |Ltac|, can contain references to hypotheses or to
|Ltac| variables containing typed or untyped terms. An untyped term can be
- type-checked using the function type_term whose argument is parsed as an
+ type checked using the function type_term whose argument is parsed as an
untyped term and returns a well-typed term which can be used in tactics.
Untyped terms built using :n:`uconstr :` can also be used as arguments to the
@@ -1189,6 +1187,7 @@ Info trace
not printed.
.. opt:: Info Level @num
+ :name: Info Level
This option is an alternative to the :cmd:`Info` command.
@@ -1199,7 +1198,7 @@ Info trace
Interactive debugger
~~~~~~~~~~~~~~~~~~~~
-.. opt:: Ltac Debug
+.. flag:: Ltac Debug
This option governs the step-by-step debugger that comes with the |Ltac| interpreter
@@ -1227,7 +1226,7 @@ following:
A non-interactive mode for the debugger is available via the option:
-.. opt:: Ltac Batch Debug
+.. flag:: Ltac Batch Debug
This option has the effect of presenting a newline at every prompt, when
the debugger is on. The debug log thus created, which does not require
@@ -1248,7 +1247,7 @@ indicates the time spent in a tactic depending on its calling context. Thus
it allows to locate the part of a tactic definition that contains the
performance issue.
-.. opt:: Ltac Profiling
+.. flag:: Ltac Profiling
This option enables and disables the profiler.
@@ -1334,7 +1333,7 @@ performance issue.
benchmarking purposes.
You can also pass the ``-profile-ltac`` command line option to ``coqc``, which
-turns the :opt:`Ltac Profiling` option on at the beginning of each document,
+turns the :flag:`Ltac Profiling` option on at the beginning of each document,
and performs a :cmd:`Show Ltac Profile` at the end.
.. warning::
diff --git a/doc/sphinx/proof-engine/proof-handling.rst b/doc/sphinx/proof-engine/proof-handling.rst
index a9d0c16376..46851050ac 100644
--- a/doc/sphinx/proof-engine/proof-handling.rst
+++ b/doc/sphinx/proof-engine/proof-handling.rst
@@ -1,4 +1,3 @@
-.. include:: ../replaces.rst
.. _proofhandling:
-------------------
@@ -84,7 +83,7 @@ list of assertion commands is given in :ref:`Assertions`. The command
:name: Defined
Same as :cmd:`Qed` but the proof is then declared transparent, which means
- that its content can be explicitly used for type-checking and that it can be
+ that its content can be explicitly used for type checking and that it can be
unfolded in conversion tactics (see :ref:`performingcomputations`,
:cmd:`Opaque`, :cmd:`Transparent`).
@@ -113,7 +112,7 @@ list of assertion commands is given in :ref:`Assertions`. The command
Aborts the editing of the proof named :token:`ident` (in case you have
nested proofs).
- .. seealso:: :opt:`Nested Proofs Allowed`
+ .. seealso:: :flag:`Nested Proofs Allowed`
.. cmdv:: Abort All
@@ -201,13 +200,14 @@ The following options modify the behavior of ``Proof using``.
.. opt:: Default Proof Using "@expression"
+ :name: Default Proof Using
Use :n:`@expression` as the default ``Proof using`` value. E.g. ``Set Default
Proof Using "a b"`` will complete all ``Proof`` commands not followed by a
``using`` part with ``using a b``.
-.. opt:: Suggest Proof Using
+.. flag:: Suggest Proof Using
When :cmd:`Qed` is performed, suggest a ``using`` annotation if the user did not
provide one.
@@ -315,6 +315,9 @@ Navigation in the proof tree
.. _curly-braces:
+.. index:: {
+ }
+
.. cmd:: %{ %| %}
The command ``{`` (without a terminating period) focuses on the first
@@ -329,20 +332,47 @@ Navigation in the proof tree
.. cmdv:: @num: %{
- This focuses on the :token:`num` th subgoal to prove.
+ This focuses on the :token:`num`\-th subgoal to prove.
+
+ .. cmdv:: [@ident]: %{
+
+ This focuses on the named goal :token:`ident`.
+
+ .. note::
+
+ Goals are just existential variables and existential variables do not
+ get a name by default. You can give a name to a goal by using :n:`refine ?[@ident]`.
+
+ .. seealso:: :ref:`existential-variables`
+
+ .. example::
+
+ This can also be a way of focusing on a shelved goal, for instance:
- Error messages:
+ .. coqtop:: all
+
+ Goal exists n : nat, n = n.
+ eexists ?[x].
+ reflexivity.
+ [x]: exact 0.
+ Qed.
.. exn:: This proof is focused, but cannot be unfocused this way.
You are trying to use ``}`` but the current subproof has not been fully solved.
- .. exn:: No such goal.
- :name: No such goal. (Focusing)
+ .. exn:: No such goal (@num).
+ :undocumented:
+
+ .. exn:: No such goal (@ident).
+ :undocumented:
- .. exn:: Brackets only support the single numbered goal selector.
+ .. exn:: Brackets do not support multi-goal selectors.
- See also error messages about bullets below.
+ Brackets are used to focus on a single goal given either by its position
+ or by its name if it has one.
+
+ .. seealso:: The error messages about bullets below.
.. _bullets:
@@ -358,8 +388,10 @@ same bullet ``b``. See the example below.
Different bullets can be used to nest levels. The scope of bullet does
not go beyond enclosing ``{`` and ``}``, so bullets can be reused as further
-nesting levels provided they are delimited by these. Available bullets
-are ``-``, ``+``, ``*``, ``--``, ``++``, ``**``, ``---``, ``+++``, ``***``, ... (without a terminating period).
+nesting levels provided they are delimited by these. Bullets are made of
+repeated ``-``, ``+`` or ``*`` symbols:
+
+.. prodn:: bullet ::= {+ - } %| {+ + } %| {+ * }
Note again that when a focused goal is proved a message is displayed
together with a suggestion about the right bullet or ``}`` to unfocus it
@@ -392,27 +424,37 @@ The following example script illustrates all these features:
- assert True.
{ trivial. }
assumption.
+ Qed.
+.. exn:: Wrong bullet @bullet__1: Current bullet @bullet__2 is not finished.
-.. exn:: Wrong bullet @bullet1: Current bullet @bullet2 is not finished.
+ Before using bullet :n:`@bullet__1` again, you should first finish proving
+ the current focused goal.
+ Note that :n:`@bullet__1` and :n:`@bullet__2` may be the same.
- Before using bullet :n:`@bullet1` again, you should first finish proving the current focused goal. Note that :n:`@bullet1` and :n:`@bullet2` may be the same.
+.. exn:: Wrong bullet @bullet__1: Bullet @bullet__2 is mandatory here.
-.. exn:: Wrong bullet @bullet1: Bullet @bullet2 is mandatory here.
-
- You must put :n:`@bullet2` to focus next goal. No other bullet is allowed here.
+ You must put :n:`@bullet__2` to focus on the next goal. No other bullet is
+ allowed here.
.. exn:: No such goal. Focus next goal with bullet @bullet.
- You tried to apply a tactic but no goals were under focus. Using :n:`@bullet` is mandatory here.
+ You tried to apply a tactic but no goals were under focus.
+ Using :n:`@bullet` is mandatory here.
+
+.. FIXME: the :noindex: below works around a Sphinx issue.
+ (https://github.com/sphinx-doc/sphinx/issues/4979)
+ It should be removed once that issue is fixed.
-.. exn:: No such goal. Try unfocusing with %{.
+.. exn:: No such goal. Try unfocusing with %}.
+ :noindex:
You just finished a goal focused by ``{``, you must unfocus it with ``}``.
Set Bullet Behavior
```````````````````
.. opt:: Bullet Behavior %( "None" %| "Strict Subproofs" %)
+ :name: Bullet Behavior
This option controls the bullet behavior and can take two possible values:
@@ -433,7 +475,7 @@ Requesting information
.. cmdv:: Show @num
- Displays only the :token:`num` th subgoal.
+ Displays only the :token:`num`\-th subgoal.
.. exn:: No such goal.
@@ -453,6 +495,10 @@ Requesting information
eexists ?[n].
Show n.
+ .. coqtop:: none
+
+ Abort.
+
.. cmdv:: Show Script
:name: Show Script
@@ -539,12 +585,171 @@ Requesting information
fixpoint and cofixpoint is violated at some time of the construction
of the proof without having to wait the completion of the proof.
+.. _showing_diffs:
+
+Showing differences between proof steps
+---------------------------------------
+
+
+Coq can automatically highlight the differences between successive proof steps.
+For example, the following screenshots of CoqIDE and coqtop show the application
+of the same :tacn:`intros` tactic. The tactic creates two new hypotheses, highlighted in green.
+The conclusion is entirely in pale green because although it’s changed, no tokens were added
+to it. The second screenshot uses the "removed" option, so it shows the conclusion a
+second time with the old text, with deletions marked in red. Also, since the hypotheses are
+new, no line of old text is shown for them.
+
+.. comment screenshot produced with:
+ Inductive ev : nat -> Prop :=
+ | ev_0 : ev 0
+ | ev_SS : forall n : nat, ev n -> ev (S (S n)).
+
+ Fixpoint double (n:nat) :=
+ match n with
+ | O => O
+ | S n' => S (S (double n'))
+ end.
+
+ Goal forall n, ev n -> exists k, n = double k.
+ intros n E.
+
+..
+
+ .. image:: ../_static/diffs-coqide-on.png
+ :alt: |CoqIDE| with Set Diffs on
+
+..
+
+ .. image:: ../_static/diffs-coqide-removed.png
+ :alt: |CoqIDE| with Set Diffs removed
+
+..
+
+ .. image:: ../_static/diffs-coqtop-on3.png
+ :alt: coqtop with Set Diffs on
+
+How to enable diffs
+```````````````````
+
+.. opt:: Diffs %( "on" %| "off" %| "removed" %)
+
+ .. This ref doesn't work: :opt:`Set Diffs %( "on" %| "off" %| "removed" %)`
+
+ The “on” option highlights added tokens in green, while the “removed” option
+ additionally reprints items with removed tokens in red. Unchanged tokens in
+ modified items are shown with pale green or red. (Colors are user-configurable.)
+
+For coqtop, showing diffs can be enabled when starting coqtop with the
+``-diffs on|off|removed`` command-line option or with the ``Set Diffs``
+command within Coq. You will need to provide the ``-color on|auto`` command-line option when
+you start coqtop in either case.
+
+Colors for coqtop can be configured by setting the ``COQ_COLORS`` environment
+variable. See section :ref:`customization-by-environment-variables`. Diffs
+use the tags ``diff.added``, ``diff.added.bg``, ``diff.removed`` and ``diff.removed.bg``.
+
+In CoqIDE, diffs should be enabled from the ``View`` menu. Don’t use the ``Set Diffs``
+command in CoqIDE. You can change the background colors shown for diffs from the
+``Edit | Preferences | Tags`` panel by changing the settings for the ``diff.added``,
+``diff.added.bg``, ``diff.removed`` and ``diff.removed.bg`` tags. This panel also
+lets you control other attributes of the highlights, such as the foreground
+color, bold, italic, underline and strikeout.
+
+Note: As of this writing (August 2018), Proof General will need minor changes
+to be able to show diffs correctly. We hope it will support this feature soon.
+See https://github.com/ProofGeneral/PG/issues/381 for the current status.
+
+How diffs are calculated
+````````````````````````
+
+Diffs are calculated as follows:
+
+1. Select the old proof state to compare to, which is the proof state before
+ the last tactic that changed the proof. Changes that only affect the view
+ of the proof, such as ``all: swap 1 2``, are ignored.
+
+2. For each goal in the new proof state, determine what old goal to compare
+ it to—the one it is derived from or is the same as. Match the hypotheses by
+ name (order is ignored), handling compacted items specially.
+
+3. For each hypothesis and conclusion (the “items”) in each goal, pass
+ them as strings to the lexer to break them into tokens. Then apply the
+ Myers diff algorithm :cite:`Myers` on the tokens and add appropriate highlighting.
+
+Notes:
+
+* Aside from the highlights, output for the "on" option should be identical
+ to the undiffed output.
+* Goals completed in the last proof step will not be shown even with the
+ "removed" setting.
+
+.. comment The following screenshots show diffs working with multiple goals and with compacted
+ hypotheses. In the first one, notice that the goal ``P 1`` is not highlighted at
+ all after the split because it has not changed.
+
+ .. todo: Use this script and remove the screenshots when COQ_COLORS
+ works for coqtop in sphinx
+ .. coqtop:: none
+
+ Set Diffs "on".
+ Parameter P : nat -> Prop.
+ Goal P 1 /\ P 2 /\ P 3.
+
+ .. coqtop:: out
+
+ split.
+
+ .. coqtop:: all
+
+ 2: split.
+
+ .. coqtop:: none
+
+ Abort.
+
+ ..
+
+ .. coqtop:: none
+
+ Set Diffs "on".
+ Goal forall n m : nat, n + m = m + n.
+ Set Diffs "on".
+
+ .. coqtop:: out
+
+ intros n.
+
+ .. coqtop:: all
+
+ intros m.
+
+ .. coqtop:: none
+
+ Abort.
+
+This screen shot shows the result of applying a :tacn:`split` tactic that replaces one goal
+with 2 goals. Notice that the goal ``P 1`` is not highlighted at all after
+the split because it has not changed.
+
+..
+
+ .. image:: ../_static/diffs-coqide-multigoal.png
+ :alt: coqide with Set Diffs on with multiple goals
+
+This is how diffs may appear after applying a :tacn:`intro` tactic that results
+in compacted hypotheses:
+
+..
+
+ .. image:: ../_static/diffs-coqide-compacted.png
+ :alt: coqide with Set Diffs on with compacted hyptotheses
Controlling the effect of proof editing commands
------------------------------------------------
.. opt:: Hyps Limit @num
+ :name: Hyps Limit
This option controls the maximum number of hypotheses displayed in goals
after the application of a tactic. All the hypotheses remain usable
@@ -553,7 +758,7 @@ Controlling the effect of proof editing commands
available hypotheses.
-.. opt:: Automatic Introduction
+.. flag:: Automatic Introduction
This option controls the way binders are handled
in assertion commands such as :n:`Theorem @ident {? @binders} : @term`. When the
@@ -565,7 +770,7 @@ Controlling the effect of proof editing commands
has to be used to move the assumptions to the local context.
-.. opt:: Nested Proofs Allowed
+.. flag:: Nested Proofs Allowed
When turned on (it is off by default), this option enables support for nested
proofs: a new assertion command can be inserted before the current proof is
diff --git a/doc/sphinx/proof-engine/ssreflect-proof-language.rst b/doc/sphinx/proof-engine/ssreflect-proof-language.rst
index 8a2fc3996a..52609546d5 100644
--- a/doc/sphinx/proof-engine/ssreflect-proof-language.rst
+++ b/doc/sphinx/proof-engine/ssreflect-proof-language.rst
@@ -1,5 +1,3 @@
-.. include:: ../replaces.rst
-
.. _thessreflectprooflanguage:
------------------------------
@@ -37,7 +35,7 @@ bookkeeping is performed on the conclusion of the goal, using for that
purpose a couple of syntactic constructions behaving similar to tacticals
(and often named as such in this chapter). The ``:`` tactical moves hypotheses
from the context to the conclusion, while ``=>`` moves hypotheses from the
-conclusion to the context, and ``in`` moves back and forth an hypothesis from the
+conclusion to the context, and ``in`` moves back and forth a hypothesis from the
context to the conclusion for the time of applying an action to it.
While naming hypotheses is commonly done by means of an ``as`` clause in the
@@ -104,8 +102,8 @@ this corresponds to working in the following context:
Unset Printing Implicit Defensive.
.. seealso::
- :opt:`Implicit Arguments`, :opt:`Strict Implicit`,
- :opt:`Printing Implicit Defensive`
+ :flag:`Implicit Arguments`, :flag:`Strict Implicit`,
+ :flag:`Printing Implicit Defensive`
.. _compatibility_issues_ssr:
@@ -303,7 +301,7 @@ the ``if`` construct to all binary data types; compare
The latter appears to be marginally shorter, but it is quite
ambiguous, and indeed often requires an explicit annotation
-``(term : {_} + {_})`` to type-check, which evens the character count.
+``(term : {_} + {_})`` to type check, which evens the character count.
Therefore, |SSR| restricts by default the condition of a plain if
construct to the standard ``bool`` type; this avoids spurious type
@@ -385,7 +383,7 @@ expressions such as
Unfortunately, such higher-order expressions are quite frequent in
representation functions, especially those which use |Coq|'s
-``Structures`` to emulate Haskell type classes.
+``Structures`` to emulate Haskell typeclasses.
Therefore, |SSR| provides a variant of |Coq|’s implicit argument
declaration, which causes |Coq| to fill in some implicit parameters at
@@ -444,11 +442,16 @@ not its name, one usually uses “arrow” abstractions for prenex
arguments, or the ``(_ : term)`` syntax for inner arguments. In |SSR|,
the latter can be replaced by the open syntax ``of term`` or
(equivalently) ``& term``, which are both syntactically equivalent to a
-``(_ : term)`` expression.
+``(_ : term)`` expression. This feature almost behaves as the
+following extension of the binder syntax:
+
+.. prodn::
+ binder += & @term | of @term
-For instance, the usual two-constructor polymorphic type list, i.e.
-the one of the standard List library, can be defined by the following
-declaration:
+Caveat: ``& T`` and ``of T`` abbreviations have to appear at the end
+of a binder list. For instance, the usual two-constructor polymorphic
+type list, i.e. the one of the standard ``List`` library, can be
+defined by the following declaration:
.. example::
@@ -1285,7 +1288,7 @@ catch the appropriate number of wildcards to be inserted. Note that
this use of the refine tactic implies that the tactic tries to match
the goal up to expansion of constants and evaluation of subterms.
-|SSR|’s apply has a special behaviour on goals containing
+|SSR|’s apply has a special behavior on goals containing
existential metavariables of sort Prop.
.. example::
@@ -2064,26 +2067,27 @@ is equivalent to:
(see section :ref:`discharge_ssr` for the documentation of the apply: combination).
-Warning The list of tactics, possibly chained by semicolons, that
-follows a by keyword is considered as a parenthesized block applied to
-the current goal. Hence for example if the tactic:
+.. warning::
-.. coqtop:: in
+ The list of tactics (possibly chained by semicolons) that
+ follows the ``by`` keyword is considered to be a parenthesized block applied to
+ the current goal. Hence for example if the tactic:
- by rewrite my_lemma1.
+ .. coqtop:: in
-succeeds, then the tactic:
+ by rewrite my_lemma1.
-.. coqtop:: in
+ succeeds, then the tactic:
- by rewrite my_lemma1; apply my_lemma2.
+ .. coqtop:: in
-usually fails since it is equivalent to:
+ by rewrite my_lemma1; apply my_lemma2.
-.. coqtop:: in
+ usually fails since it is equivalent to:
- by (rewrite my_lemma1; apply my_lemma2).
+ .. coqtop:: in
+ by (rewrite my_lemma1; apply my_lemma2).
.. _selectors_ssr:
@@ -2522,7 +2526,8 @@ After the :token:`i_pattern`, a list of binders is allowed.
.. coqtop:: reset
- From Coq Require Import ssreflect Omega.
+ From Coq Require Import ssreflect.
+ From Coq Require Import Omega.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
@@ -2552,12 +2557,9 @@ copying the goal itself.
.. example::
- .. coqtop:: reset
+ .. coqtop:: none
- From Coq Require Import ssreflect.
- Set Implicit Arguments.
- Unset Strict Implicit.
- Unset Printing Implicit Defensive.
+ Abort All.
.. coqtop:: all
@@ -2581,12 +2583,9 @@ context entry name.
.. example::
- .. coqtop:: reset
+ .. coqtop:: none
- From Coq Require Import ssreflect Omega.
- Set Implicit Arguments.
- Unset Strict Implicit.
- Unset Printing Implicit Defensive.
+ Abort All.
Set Printing Depth 15.
.. coqtop:: all
@@ -2601,20 +2600,13 @@ context entry name.
Note that the sub-term produced by ``omega`` is in general huge and
uninteresting, and hence one may want to hide it.
For this purpose the ``[: name ]`` intro pattern and the tactic
-``abstract`` (see page :ref:`abstract_ssr`) are provided.
+``abstract`` (see :ref:`abstract_ssr`) are provided.
.. example::
- .. coqtop:: reset
-
- From Coq Require Import ssreflect Omega.
- Set Implicit Arguments.
- Unset Strict Implicit.
- Unset Printing Implicit Defensive.
+ .. coqtop:: none
- Inductive Ord n := Sub x of x < n.
- Notation "'I_ n" := (Ord n) (at level 8, n at level 2, format "''I_' n").
- Arguments Sub {_} _ _.
+ Abort All.
.. coqtop:: all
@@ -2629,16 +2621,9 @@ with have and an explicit term, they must be used as follows:
.. example::
- .. coqtop:: reset
+ .. coqtop:: none
- From Coq Require Import ssreflect Omega.
- Set Implicit Arguments.
- Unset Strict Implicit.
- Unset Printing Implicit Defensive.
-
- Inductive Ord n := Sub x of x < n.
- Notation "'I_ n" := (Ord n) (at level 8, n at level 2, format "''I_' n").
- Arguments Sub {_} _ _.
+ Abort All.
.. coqtop:: all
@@ -2659,16 +2644,9 @@ makes use of it).
.. example::
- .. coqtop:: reset
-
- From Coq Require Import ssreflect Omega.
- Set Implicit Arguments.
- Unset Strict Implicit.
- Unset Printing Implicit Defensive.
+ .. coqtop:: none
- Inductive Ord n := Sub x of x < n.
- Notation "'I_ n" := (Ord n) (at level 8, n at level 2, format "''I_' n").
- Arguments Sub {_} _ _.
+ Abort All.
.. coqtop:: all
@@ -2679,18 +2657,15 @@ Last, notice that the use of intro patterns for abstract constants is
orthogonal to the transparent flag ``@`` for have.
-The have tactic and type classes resolution
+The have tactic and typeclass resolution
```````````````````````````````````````````
-Since |SSR| 1.5 the have tactic behaves as follows with respect to
-type classes inference.
+Since |SSR| 1.5 the ``have`` tactic behaves as follows with respect to
+typeclass inference.
- .. coqtop:: reset
+ .. coqtop:: none
- From Coq Require Import ssreflect Omega.
- Set Implicit Arguments.
- Unset Strict Implicit.
- Unset Printing Implicit Defensive.
+ Abort All.
Axiom ty : Type.
Axiom t : ty.
@@ -2726,9 +2701,9 @@ type classes inference.
No inference for ``t``. Unresolved instances are
quantified in the (inferred) type of ``t`` and abstracted in ``t``.
-.. opt:: SsrHave NoTCResolution
+.. flag:: SsrHave NoTCResolution
- This option restores the behavior of |SSR| 1.4 and below (never resolve type classes).
+ This option restores the behavior of |SSR| 1.4 and below (never resolve typeclasses).
Variants: the suff and wlog tactics
```````````````````````````````````
@@ -2766,12 +2741,9 @@ The ``have`` modifier can follow the ``suff`` tactic.
.. example::
- .. coqtop:: reset
+ .. coqtop:: none
- From Coq Require Import ssreflect Omega.
- Set Implicit Arguments.
- Unset Strict Implicit.
- Unset Printing Implicit Defensive.
+ Abort All.
Axioms G P : Prop.
.. coqtop:: all
@@ -2839,12 +2811,9 @@ are unique.
.. example::
- .. coqtop:: reset
+ .. coqtop:: none
- From Coq Require Import ssreflect Omega.
- Set Implicit Arguments.
- Unset Strict Implicit.
- Unset Printing Implicit Defensive.
+ Abort All.
.. coqtop:: all
@@ -2935,12 +2904,10 @@ illustrated in the following example.
the pattern ``id (addx x)``, that would produce the following first
subgoal
- .. coqtop:: reset
+ .. coqtop:: none
- From Coq Require Import ssreflect Omega.
- Set Implicit Arguments.
- Unset Strict Implicit.
- Unset Printing Implicit Defensive.
+ Abort All.
+ From Coq Require Import Omega.
Section Test.
Variable x : nat.
Definition addx z := z + x.
@@ -3046,6 +3013,15 @@ An :token:`r_item` can be:
is equivalent to: ``change term1 with term2.`` If ``term2`` is a
single constant and ``term1`` head symbol is not ``term2``, then the head
symbol of ``term1`` is repeatedly unfolded until ``term2`` appears.
++ A :token:`term`, which can be:
+ + A term whose type has the form:
+ ``forall (x1 : A1 )…(xn : An ), eq term1 term2`` where
+ ``eq`` is the Leibniz equality or a registered setoid
+ equality.
+ + A list of terms ``(t1 ,…,tn)``, each ``ti`` having a type above.
+ The tactic: ``rewrite r_prefix (t1 ,…,tn ).``
+ is equivalent to: ``do [rewrite r_prefix t1 | … | rewrite r_prefix tn ].``
+ + An anonymous rewrite lemma ``(_ : term)``, where term has a type as above. tactic: ``rewrite (_ : term)`` is in fact synonym of: ``cutrewrite (term).``.
.. example::
@@ -3063,9 +3039,10 @@ An :token:`r_item` can be:
Lemma test x : ddouble x = 4 * x.
rewrite [ddouble _]/double.
- *Warning* The |SSR|
- terms containing holes are *not* typed as abstractions in this
- context. Hence the following script fails.
+ .. warning::
+
+ The |SSR| terms containing holes are *not* typed as
+ abstractions in this context. Hence the following script fails.
.. coqtop:: none
@@ -3087,17 +3064,6 @@ An :token:`r_item` can be:
rewrite -[f y x]/(y + _).
-+ A :token:`term`, which can be:
-
- + A term whose type has the form:
- ``forall (x1 : A1 )…(xn : An ), eq term1 term2`` where
- ``eq`` is the Leibniz equality or a registered setoid
- equality.
- + A list of terms ``(t1 ,…,tn)``, each ``ti`` having a type above.
- The tactic: ``rewrite r_prefix (t1 ,…,tn ).``
- is equivalent to: ``do [rewrite r_prefix t1 | … | rewrite r_prefix tn ].``
- + An anonymous rewrite lemma ``(_ : term)``, where term has a type as above. tactic: ``rewrite (_ : term)`` is in fact synonym of: ``cutrewrite (term).``.
-
Remarks and examples
~~~~~~~~~~~~~~~~~~~~
@@ -3738,20 +3704,22 @@ Note that ``nosimpl bar`` is simply notation for a term that reduces to
``bar``; hence ``unfold foo`` will replace ``foo`` by ``bar``, and
``fold foo`` will replace ``bar`` by ``foo``.
-*Warning* The ``nosimpl`` trick only works if no reduction is apparent in
-``t``; in particular, the declaration:
+.. warning::
-.. coqtop:: in
+ The ``nosimpl`` trick only works if no reduction is apparent in
+ ``t``; in particular, the declaration:
- Definition foo x := nosimpl (bar x).
+ .. coqtop:: in
-will usually not work. Anyway, the common practice is to tag only the
-function, and to use the following definition, which blocks the
-reduction as expected:
+ Definition foo x := nosimpl (bar x).
-.. coqtop:: in
+ will usually not work. Anyway, the common practice is to tag only the
+ function, and to use the following definition, which blocks the
+ reduction as expected:
+
+ .. coqtop:: in
- Definition foo x := nosimpl bar x.
+ Definition foo x := nosimpl bar x.
A standard example making this technique shine is the case of
arithmetic operations. We define for instance:
@@ -3897,7 +3865,7 @@ duplication of function arguments. These copies usually end up in
types hidden by the implicit arguments machinery or by user-defined
notations. In these situations computing the right occurrence numbers
is very tedious because they must be counted on the goal as printed
-after setting the Printing All flag. Moreover the resulting script is
+after setting the :flag:`Printing All` flag. Moreover the resulting script is
not really informative for the reader, since it refers to occurrence
numbers he cannot easily see.
@@ -4794,7 +4762,7 @@ equivalence property has been defined.
Lemma andE (b1 b2 : bool) : (b1 /\ b2) <-> (b1 && b2).
-Let us compare the respective behaviours of ``andE`` and ``andP``.
+Let us compare the respective behaviors of ``andE`` and ``andP``.
.. example::
@@ -4907,7 +4875,7 @@ The term , called the *view lemma* can be:
Let ``top`` be the top assumption in the goal.
-There are three steps in the behaviour of an assumption view tactic:
+There are three steps in the behavior of an assumption view tactic:
+ It first introduces ``top``.
+ If the type of :token:`term` is neither a double implication nor an
@@ -5422,7 +5390,7 @@ Tacticals
discharge :ref:`discharge_ssr`
-.. prodn:: tactic += @tacitc => {+ @i_item }
+.. prodn:: tactic += @tactic => {+ @i_item }
introduction see :ref:`introduction_ssr`
diff --git a/doc/sphinx/proof-engine/tactics.rst b/doc/sphinx/proof-engine/tactics.rst
index fdb04bf9a0..db9f04ba11 100644
--- a/doc/sphinx/proof-engine/tactics.rst
+++ b/doc/sphinx/proof-engine/tactics.rst
@@ -1,6 +1,3 @@
-.. include:: ../preamble.rst
-.. include:: ../replaces.rst
-
.. _tactics:
Tactics
@@ -51,7 +48,8 @@ specified, the default selector is used.
tactic_invocation : toplevel_selector : tactic.
: |tactic .
-.. opt:: Default Goal Selector @toplevel_selector
+.. opt:: Default Goal Selector "@toplevel_selector"
+ :name: Default Goal Selector
This option controls the default selector, used when no selector is
specified when applying a tactic. The initial value is 1, hence the
@@ -113,26 +111,26 @@ Occurrence sets and occurrence clauses
An occurrence clause is a modifier to some tactics that obeys the
following syntax:
-.. _tactic_occurence_grammar:
-
.. productionlist:: `sentence`
- occurence_clause : in `goal_occurences`
- goal_occurences : [ident [`at_occurences`], ... , ident [`at_occurences`] [|- [* [`at_occurences`]]]]
- :| * |- [* [`at_occurences`]]
+ occurrence_clause : in `goal_occurrences`
+ goal_occurrences : [`ident` [`at_occurrences`], ... , ident [`at_occurrences`] [|- [* [`at_occurrences`]]]]
+ :| * |- [* [`at_occurrences`]]
:| *
at_occurrences : at `occurrences`
- occurences : [-] `num` ... `num`
-
-The role of an occurrence clause is to select a set of occurrences of a term in
-a goal. In the first case, the :n:`@ident {? at {* num}}` parts indicate that
-occurrences have to be selected in the hypotheses named :n:`@ident`. If no
-numbers are given for hypothesis :n:`@ident`, then all the occurrences of `term`
-in the hypothesis are selected. If numbers are given, they refer to occurrences
-of `term` when the term is printed using option :opt:`Printing All`, counting
-from left to right. In particular, occurrences of `term` in implicit arguments
-(see :ref:`ImplicitArguments`) or coercions (see :ref:`Coercions`) are counted.
-
-If a minus sign is given between at and the list of occurrences, it
+ occurrences : [-] `num` ... `num`
+
+The role of an occurrence clause is to select a set of occurrences of a term
+in a goal. In the first case, the :n:`@ident {? at {* num}}` parts indicate
+that occurrences have to be selected in the hypotheses named :token:`ident`.
+If no numbers are given for hypothesis :token:`ident`, then all the
+occurrences of :token:`term` in the hypothesis are selected. If numbers are
+given, they refer to occurrences of :token:`term` when the term is printed
+using option :flag:`Printing All`, counting from left to right. In particular,
+occurrences of :token:`term` in implicit arguments
+(see :ref:`ImplicitArguments`) or coercions (see :ref:`Coercions`) are
+counted.
+
+If a minus sign is given between ``at`` and the list of occurrences, it
negates the condition so that the clause denotes all the occurrences
except the ones explicitly mentioned after the minus sign.
@@ -146,18 +144,20 @@ of term are selected in every hypothesis.
In the first and second case, if ``*`` is mentioned on the right of ``|-``, the
occurrences of the conclusion of the goal have to be selected. If some numbers
are given, then only the occurrences denoted by these numbers are selected. If
-no numbers are given, all occurrences of :n:`@term` in the goal are selected.
+no numbers are given, all occurrences of :token:`term` in the goal are selected.
Finally, the last notation is an abbreviation for ``* |- *``. Note also
that ``|-`` is optional in the first case when no ``*`` is given.
-Here are some tactics that understand occurrence clauses: :tacn:`set`, :tacn:`remember`
-, :tacn:`induction`, :tacn:`destruct`.
+Here are some tactics that understand occurrence clauses: :tacn:`set`,
+:tacn:`remember`, :tacn:`induction`, :tacn:`destruct`.
+
+.. seealso::
+
+ :ref:`Managingthelocalcontext`, :ref:`caseanalysisandinduction`,
+ :ref:`printing_constructions_full`.
-See also: :ref:`Managingthelocalcontext`,
-:ref:`caseanalysisandinduction`,
-:ref:`printing_constructions_full`.
.. _applyingtheorems:
@@ -173,35 +173,39 @@ Applying theorems
:ref:`Conversion-rules`).
.. exn:: Not an exact proof.
+ :undocumented:
.. tacv:: eexact @term.
:name: eexact
- This tactic behaves like exact but is able to handle terms and goals with
- meta-variables.
+ This tactic behaves like :tacn:`exact` but is able to handle terms and
+ goals with existential variables.
.. tacn:: assumption
:name: assumption
- This tactic looks in the local context for an hypothesis which type is equal to
- the goal. If it is the case, the subgoal is proved. Otherwise, it fails.
+ This tactic looks in the local context for a hypothesis whose type is
+ convertible to the goal. If it is the case, the subgoal is proved.
+ Otherwise, it fails.
.. exn:: No such assumption.
+ :undocumented:
.. tacv:: eassumption
:name: eassumption
- This tactic behaves like assumption but is able to handle goals with
- meta-variables.
+ This tactic behaves like :tacn:`assumption` but is able to handle
+ goals with existential variables.
.. tacn:: refine @term
:name: refine
This tactic applies to any goal. It behaves like :tacn:`exact` with a big
- difference: the user can leave some holes (denoted by ``_`` or ``(_:type)``) in
- the term. :tacn:`refine` will generate as many subgoals as there are holes in
- the term. The type of holes must be either synthesized by the system
- or declared by an explicit cast like ``(_:nat->Prop)``. Any subgoal that
+ difference: the user can leave some holes (denoted by ``_``
+ or :n:`(_ : @type)`) in the term. :tacn:`refine` will generate as many
+ subgoals as there are holes in the term. The type of holes must be either
+ synthesized by the system or declared by an explicit cast
+ like ``(_ : nat -> Prop)``. Any subgoal that
occurs in other subgoals is automatically shelved, as if calling
:tacn:`shelve_unifiable`. This low-level tactic can be
useful to advanced users.
@@ -215,16 +219,13 @@ Applying theorems
| Ok : bool -> Option.
Definition get : forall x:Option, x <> Fail -> bool.
-
- refine
- (fun x:Option =>
- match x return x <> Fail -> bool with
- | Fail => _
- | Ok b => fun _ => b
- end).
-
- intros; absurd (Fail = Fail); trivial.
-
+ refine
+ (fun x:Option =>
+ match x return x <> Fail -> bool with
+ | Fail => _
+ | Ok b => fun _ => b
+ end).
+ intros; absurd (Fail = Fail); trivial.
Defined.
.. exn:: Invalid argument.
@@ -252,41 +253,43 @@ Applying theorems
.. tacv:: notypeclasses refine @term
:name: notypeclasses refine
- This tactic behaves like :tacn:`refine` except it performs typechecking without
+ This tactic behaves like :tacn:`refine` except it performs type checking without
resolution of typeclasses.
.. tacv:: simple notypeclasses refine @term
:name: simple notypeclasses refine
- This tactic behaves like :tacn:`simple refine` except it performs typechecking
+ This tactic behaves like :tacn:`simple refine` except it performs type checking
without resolution of typeclasses.
.. tacn:: apply @term
:name: apply
- This tactic applies to any goal. The argument term is a term well-formed in the
- local context. The tactic apply tries to match the current goal against the
- conclusion of the type of term. If it succeeds, then the tactic returns as many
- subgoals as the number of non-dependent premises of the type of term. If the
- conclusion of the type of term does not match the goal *and* the conclusion is
- an inductive type isomorphic to a tuple type, then each component of the tuple
- is recursively matched to the goal in the left-to-right order.
-
- The tactic :tacn:`apply` relies on first-order unification with dependent types
- unless the conclusion of the type of :token:`term` is of the form :g:`P (t`:sub:`1`
- :g:`...` :g:`t`:sub:`n` :g:`)` with `P` to be instantiated. In the latter case, the behavior
- depends on the form of the goal. If the goal is of the form
- :g:`(fun x => Q) u`:sub:`1` :g:`...` :g:`u`:sub:`n` and the :g:`t`:sub:`i` and
- :g:`u`:sub:`i` unifies, then :g:`P` is taken to be :g:`(fun x => Q)`. Otherwise,
- :tacn:`apply` tries to define :g:`P` by abstracting over :g:`t`:sub:`1` :g:`...`
- :g:`t`:sub:`n` in the goal. See :tacn:`pattern` to transform the goal so that it
- gets the form :g:`(fun x => Q) u`:sub:`1` :g:`...` :g:`u`:sub:`n`.
+ This tactic applies to any goal. The argument term is a term well-formed in
+ the local context. The tactic :tacn:`apply` tries to match the current goal
+ against the conclusion of the type of :token:`term`. If it succeeds, then
+ the tactic returns as many subgoals as the number of non-dependent premises
+ of the type of term. If the conclusion of the type of :token:`term` does
+ not match the goal *and* the conclusion is an inductive type isomorphic to
+ a tuple type, then each component of the tuple is recursively matched to
+ the goal in the left-to-right order.
+
+ The tactic :tacn:`apply` relies on first-order unification with dependent
+ types unless the conclusion of the type of :token:`term` is of the form
+ :n:`P (t__1 ... t__n)` with ``P`` to be instantiated. In the latter case,
+ the behavior depends on the form of the goal. If the goal is of the form
+ :n:`(fun x => Q) u__1 ... u__n` and the :n:`t__i` and :n:`u__i` unify,
+ then :g:`P` is taken to be :g:`(fun x => Q)`. Otherwise, :tacn:`apply`
+ tries to define :g:`P` by abstracting over :g:`t_1 ... t__n` in the goal.
+ See :tacn:`pattern` to transform the goal so that it
+ gets the form :n:`(fun x => Q) u__1 ... u__n`.
.. exn:: Unable to unify @term with @term.
- The apply tactic failed to match the conclusion of :token:`term` and the
- current goal. You can help the apply tactic by transforming your goal with
- the :tacn:`change` or :tacn:`pattern` tactics.
+ The :tacn:`apply` tactic failed to match the conclusion of :token:`term`
+ and the current goal. You can help the :tacn:`apply` tactic by
+ transforming your goal with the :tacn:`change` or :tacn:`pattern`
+ tactics.
.. exn:: Unable to find an instance for the variables {+ @ident}.
@@ -302,6 +305,7 @@ Applying theorems
according to the order of these dependent premises of the type of term.
.. exn:: Not the right number of missing arguments.
+ :undocumented:
.. tacv:: apply @term with @bindings_list
@@ -311,11 +315,9 @@ Applying theorems
.. tacv:: apply {+, @term}
- This is a shortcut for :n:`apply @term`:sub:`1`
- :n:`; [.. | ... ; [ .. | apply @term`:sub:`n` :n:`] ... ]`,
- i.e. for the successive applications of :token:`term`:sub:`i+1` on the last subgoal
- generated by :n:`apply @term`:sub:`i` , starting from the application of
- :token:`term`:sub:`1`.
+ This is a shortcut for :n:`apply @term__1; [.. | ... ; [ .. | apply @term__n] ... ]`,
+ i.e. for the successive applications of :n:`@term`:sub:`i+1` on the last subgoal
+ generated by :n:`apply @term__i` , starting from the application of :n:`@term__1`.
.. tacv:: eapply @term
:name: eapply
@@ -327,7 +329,6 @@ Applying theorems
intended to be found later in the proof.
.. tacv:: simple apply @term.
- :name: simple apply
This behaves like :tacn:`apply` but it reasons modulo conversion only on subterms
that contain no variables to instantiate. For instance, the following example
@@ -349,8 +350,8 @@ Applying theorems
does.
.. tacv:: {? simple} apply {+, @term {? with @bindings_list}}
- .. tacv:: {? simple} eapply {+, @term {? with @bindings_list}}
- :name: simple eapply
+ {? simple} eapply {+, @term {? with @bindings_list}}
+ :name: simple apply; simple eapply
This summarizes the different syntaxes for :tacn:`apply` and :tacn:`eapply`.
@@ -365,6 +366,7 @@ Applying theorems
sequence ``cut B. 2:apply H.`` where ``cut`` is described below.
.. warn:: When @term contains more than one non dependent product the tactic lapply only takes into account the first product.
+ :undocumented:
.. example::
@@ -447,7 +449,7 @@ Applying theorems
``forall A, ... -> A``. Excluding this kind of lemma can be avoided by
setting the following option:
-.. opt:: Universal Lemma Under Conjunction
+.. flag:: Universal Lemma Under Conjunction
This option, which preserves compatibility with versions of Coq prior to
8.4 is also available for :n:`apply @term in @ident` (see :tacn:`apply ... in`).
@@ -455,164 +457,151 @@ Applying theorems
.. tacn:: apply @term in @ident
:name: apply ... in
- This tactic applies to any goal. The argument ``term`` is a term well-formed in
- the local context and the argument :n:`@ident` is an hypothesis of the context.
- The tactic ``apply term in ident`` tries to match the conclusion of the type
- of :n:`@ident` against a non-dependent premise of the type of ``term``, trying
- them from right to left. If it succeeds, the statement of hypothesis
- :n:`@ident` is replaced by the conclusion of the type of ``term``. The tactic
- also returns as many subgoals as the number of other non-dependent premises
- in the type of ``term`` and of the non-dependent premises of the type of
- :n:`@ident`. If the conclusion of the type of ``term`` does not match the goal
- *and* the conclusion is an inductive type isomorphic to a tuple type, then
+ This tactic applies to any goal. The argument :token:`term` is a term
+ well-formed in the local context and the argument :token:`ident` is an
+ hypothesis of the context.
+ The tactic :n:`apply @term in @ident` tries to match the conclusion of the
+ type of :token:`ident` against a non-dependent premise of the type
+ of :token:`term`, trying them from right to left. If it succeeds, the
+ statement of hypothesis :token:`ident` is replaced by the conclusion of
+ the type of :token:`term`. The tactic also returns as many subgoals as the
+ number of other non-dependent premises in the type of :token:`term` and of
+ the non-dependent premises of the type of :token:`ident`. If the conclusion
+ of the type of :token:`term` does not match the goal *and* the conclusion
+ is an inductive type isomorphic to a tuple type, then
the tuple is (recursively) decomposed and the first component of the tuple
of which a non-dependent premise matches the conclusion of the type of
- :n:`@ident`. Tuples are decomposed in a width-first left-to-right order (for
- instance if the type of :g:`H1` is :g:`A <-> B` and the type of
- :g:`H2` is :g:`A` then ``apply H1 in H2`` transforms the type of :g:`H2`
- into :g:`B`). The tactic ``apply`` relies on first-order pattern-matching
+ :token:`ident`. Tuples are decomposed in a width-first left-to-right order
+ (for instance if the type of :g:`H1` is :g:`A <-> B` and the type of
+ :g:`H2` is :g:`A` then :g:`apply H1 in H2` transforms the type of :g:`H2`
+ into :g:`B`). The tactic :tacn:`apply` relies on first-order pattern matching
with dependent types.
-.. exn:: Statement without assumptions.
-
- This happens if the type of ``term`` has no non dependent premise.
-
-.. exn:: Unable to apply.
+ .. exn:: Statement without assumptions.
- This happens if the conclusion of :n:`@ident` does not match any of the non
- dependent premises of the type of ``term``.
+ This happens if the type of :token:`term` has no non-dependent premise.
-.. tacv:: apply {+, @term} in @ident
+ .. exn:: Unable to apply.
- This applies each of ``term`` in sequence in :n:`@ident`.
+ This happens if the conclusion of :token:`ident` does not match any of
+ the non-dependent premises of the type of :token:`term`.
-.. tacv:: apply {+, @term with @bindings_list} in @ident
+ .. tacv:: apply {+, @term} in @ident
- This does the same but uses the bindings in each :n:`(@id := @ val)` to
- instantiate the parameters of the corresponding type of ``term`` (see
- :ref:`bindings list <bindingslist>`).
+ This applies each :token:`term` in sequence in :token:`ident`.
-.. tacv:: eapply {+, @term with @bindings_list} in @ident
+ .. tacv:: apply {+, @term with @bindings_list} in @ident
- This works as :tacn:`apply ... in` but turns unresolved bindings into
- existential variables, if any, instead of failing.
+ This does the same but uses the bindings in each :n:`(@ident := @term)` to
+ instantiate the parameters of the corresponding type of :token:`term`
+ (see :ref:`bindings list <bindingslist>`).
-.. tacv:: apply {+, @term with @bindings_list} in @ident as @intro_pattern
- :name: apply ... in ... as
+ .. tacv:: eapply {+, @term {? with @bindings_list } } in @ident
- This works as :tacn:`apply ... in` then applies the
- :n:`@intro_pattern` to the hypothesis :n:`@ident`.
+ This works as :tacn:`apply ... in` but turns unresolved bindings into
+ existential variables, if any, instead of failing.
-.. tacv:: eapply {+, @term with @bindings_list} in @ident as @intro_pattern.
+ .. tacv:: apply {+, @term {? with @bindings_list } } in @ident as @intro_pattern
+ :name: apply ... in ... as
- This works as :tacn:`apply ... in ... as` but using ``eapply``.
+ This works as :tacn:`apply ... in` then applies the :token:`intro_pattern`
+ to the hypothesis :token:`ident`.
-.. tacv:: simple apply @term in @ident
+ .. tacv:: simple apply @term in @ident
- This behaves like :tacn:`apply ... in` but it reasons modulo conversion only
- on subterms that contain no variables to instantiate. For instance, if
- :g:`id := fun x:nat => x` and :g:`H: forall y, id y = y -> True` and
- :g:`H0 : O = O` then ``simple apply H in H0`` does not succeed because it
- would require the conversion of :g:`id ?x` and :g:`O` where :g:`?x` is
- an existential variable to instantiate. Tactic :n:`simple apply @term in @ident` does not
- either traverse tuples as :n:`apply @term in @ident` does.
+ This behaves like :tacn:`apply ... in` but it reasons modulo conversion
+ only on subterms that contain no variables to instantiate. For instance,
+ if :g:`id := fun x:nat => x` and :g:`H: forall y, id y = y -> True` and
+ :g:`H0 : O = O` then :g:`simple apply H in H0` does not succeed because it
+ would require the conversion of :g:`id ?x` and :g:`O` where :g:`?x` is
+ an existential variable to instantiate.
+ Tactic :n:`simple apply @term in @ident` does not
+ either traverse tuples as :n:`apply @term in @ident` does.
-.. tacv:: {? simple} apply {+, @term {? with @bindings_list}} in @ident {? as @intro_pattern}
-.. tacv:: {? simple} eapply {+, @term {? with @bindings_list}} in @ident {? as @intro_pattern}
+ .. tacv:: {? simple} apply {+, @term {? with @bindings_list}} in @ident {? as @intro_pattern}
+ {? simple} eapply {+, @term {? with @bindings_list}} in @ident {? as @intro_pattern}
- This summarizes the different syntactic variants of :n:`apply @term in @ident`
- and :n:`eapply @term in @ident`.
+ This summarizes the different syntactic variants of :n:`apply @term in @ident`
+ and :n:`eapply @term in @ident`.
.. tacn:: constructor @num
:name: constructor
This tactic applies to a goal such that its conclusion is an inductive
- type (say :g:`I`). The argument :n:`@num` must be less or equal to the
- numbers of constructor(s) of :g:`I`. Let :g:`c`:sub:`i` be the i-th
- constructor of :g:`I`, then ``constructor i`` is equivalent to
- ``intros; apply c``:sub:`i`.
+ type (say :g:`I`). The argument :token:`num` must be less or equal to the
+ numbers of constructor(s) of :g:`I`. Let :n:`c__i` be the i-th
+ constructor of :g:`I`, then :g:`constructor i` is equivalent to
+ :n:`intros; apply c__i`.
-.. exn:: Not an inductive product.
-.. exn:: Not enough constructors.
-
-.. tacv:: constructor
-
- This tries :g:`constructor`:sub:`1` then :g:`constructor`:sub:`2`, ..., then
- :g:`constructor`:sub:`n` where `n` is the number of constructors of the head
- of the goal.
-
-.. tacv:: constructor @num with @bindings_list
-
- Let ``c`` be the i-th constructor of :g:`I`, then
- :n:`constructor i with @bindings_list` is equivalent to
- :n:`intros; apply c with @bindings_list`.
+ .. exn:: Not an inductive product.
+ :undocumented:
- .. warn::
- The terms in the @bindings_list are checked in the context where constructor is executed and not in the context where @apply is executed (the introductions are not taken into account).
+ .. exn:: Not enough constructors.
+ :undocumented:
-.. tacv:: split
- :name: split
+ .. tacv:: constructor
- This applies only if :g:`I` has a single constructor. It is then
- equivalent to :n:`constructor 1.`. It is typically used in the case of a
- conjunction :g:`A` :math:`\wedge` :g:`B`.
+ This tries :g:`constructor 1` then :g:`constructor 2`, ..., then
+ :g:`constructor n` where ``n`` is the number of constructors of the head
+ of the goal.
-.. exn:: Not an inductive goal with 1 constructor
+ .. tacv:: constructor @num with @bindings_list
-.. tacv:: exists @val
- :name: exists
+ Let ``c`` be the i-th constructor of :g:`I`, then
+ :n:`constructor i with @bindings_list` is equivalent to
+ :n:`intros; apply c with @bindings_list`.
- This applies only if :g:`I` has a single constructor. It is then equivalent
- to :n:`intros; constructor 1 with @bindings_list.` It is typically used in
- the case of an existential quantification :math:`\exists`:g:`x, P(x).`
-
-.. exn:: Not an inductive goal with 1 constructor.
-
-.. tacv:: exists @bindings_list
+ .. warning::
- This iteratively applies :n:`exists @bindings_list`.
+ The terms in the :token:`bindings_list` are checked in the context
+ where constructor is executed and not in the context where :tacn:`apply`
+ is executed (the introductions are not taken into account).
-.. tacv:: left
- :name: left
+ .. tacv:: split {? with @bindings_list }
+ :name: split
-.. tacv:: right
- :name: right
+ This applies only if :g:`I` has a single constructor. It is then
+ equivalent to :n:`constructor 1 {? with @bindings_list }`. It is
+ typically used in the case of a conjunction :math:`A \wedge B`.
- These tactics apply only if :g:`I` has two constructors, for
- instance in the case of a disjunction :g:`A` :math:`\vee` :g:`B`.
- Then, they are respectively equivalent to ``constructor 1`` and
- ``constructor 2``.
+ .. tacv:: exists @bindings_list
+ :name: exists
-.. exn:: Not an inductive goal with 2 constructors.
+ This applies only if :g:`I` has a single constructor. It is then equivalent
+ to :n:`intros; constructor 1 with @bindings_list.` It is typically used in
+ the case of an existential quantification :math:`\exists x, P(x).`
-.. tacv:: left with @bindings_list
-.. tacv:: right with @bindings_list
-.. tacv:: split with @bindings_list
+ .. tacv:: exists {+, @bindings_list }
- As soon as the inductive type has the right number of constructors, these
- expressions are equivalent to calling :n:`constructor i with @bindings_list`
- for the appropriate ``i``.
+ This iteratively applies :n:`exists @bindings_list`.
-.. tacv:: econstructor
- :name: econstructor
+ .. exn:: Not an inductive goal with 1 constructor.
+ :undocumented:
-.. tacv:: eexists
- :name: eexists
+ .. tacv:: left {? with @bindings_list }
+ right {? with @bindings_list }
+ :name: left; right
-.. tacv:: esplit
- :name: esplit
+ These tactics apply only if :g:`I` has two constructors, for
+ instance in the case of a disjunction :math:`A \vee B`.
+ Then, they are respectively equivalent to
+ :n:`constructor 1 {? with @bindings_list }` and
+ :n:`constructor 2 {? with @bindings_list }`.
-.. tacv:: eleft
- :name: eleft
+ .. exn:: Not an inductive goal with 2 constructors.
-.. tacv:: eright
- :name: eright
+ .. tacv:: econstructor
+ eexists
+ esplit
+ eleft
+ eright
+ :name: econstructor; eexists; esplit; eleft; eright
- These tactics and their variants behave like :tacn:`constructor`,
- :tacn:`exists`, :tacn:`split`, :tacn:`left`, :tacn:`right` and their variants
- but they introduce existential variables instead of failing when the
- instantiation of a variable cannot be found (cf. :tacn:`eapply` and
- :tacn:`apply`).
+ These tactics and their variants behave like :tacn:`constructor`,
+ :tacn:`exists`, :tacn:`split`, :tacn:`left`, :tacn:`right` and their
+ variants but they introduce existential variables instead of failing
+ when the instantiation of a variable cannot be found
+ (cf. :tacn:`eapply` and :tacn:`apply`).
.. _managingthelocalcontext:
@@ -623,101 +612,107 @@ Managing the local context
.. tacn:: intro
:name: intro
-This tactic applies to a goal that is either a product or starts with a let
-binder. If the goal is a product, the tactic implements the "Lam" rule given in
-:ref:`Typing-rules` [1]_. If the goal starts with a let binder, then the
-tactic implements a mix of the "Let" and "Conv".
+ This tactic applies to a goal that is either a product or starts with a
+ let-binder. If the goal is a product, the tactic implements the "Lam" rule
+ given in :ref:`Typing-rules` [1]_. If the goal starts with a let-binder,
+ then the tactic implements a mix of the "Let" and "Conv".
-If the current goal is a dependent product :g:`forall x:T, U` (resp
-:g:`let x:=t in U`) then ``intro`` puts :g:`x:T` (resp :g:`x:=t`) in the local
-context. The new subgoal is :g:`U`.
+ If the current goal is a dependent product :g:`forall x:T, U`
+ (resp :g:`let x:=t in U`) then :tacn:`intro` puts :g:`x:T` (resp :g:`x:=t`)
+ in the local context. The new subgoal is :g:`U`.
-If the goal is a non-dependent product :g:`T`:math:`\rightarrow`:g:`U`, then it
-puts in the local context either :g:`Hn:T` (if :g:`T` is of type :g:`Set` or
-:g:`Prop`) or :g:`Xn:T` (if the type of :g:`T` is :g:`Type`). The optional index
-``n`` is such that ``Hn`` or ``Xn`` is a fresh identifier. In both cases, the
-new subgoal is :g:`U`.
+ If the goal is a non-dependent product :math:`T \rightarrow U`, then it
+ puts in the local context either :g:`Hn:T` (if :g:`T` is of type :g:`Set`
+ or :g:`Prop`) or :g:`Xn:T` (if the type of :g:`T` is :g:`Type`).
+ The optional index ``n`` is such that ``Hn`` or ``Xn`` is a fresh
+ identifier. In both cases, the new subgoal is :g:`U`.
-If the goal is an existential variable, ``intro`` forces the resolution of the
-existential variable into a dependent product :math:`forall`:g:`x:?X, ?Y`, puts
-:g:`x:?X` in the local context and leaves :g:`?Y` as a new subgoal allowed to
-depend on :g:`x`.
+ If the goal is an existential variable, :tacn:`intro` forces the resolution
+ of the existential variable into a dependent product :math:`\forall`\ :g:`x:?X, ?Y`,
+ puts :g:`x:?X` in the local context and leaves :g:`?Y` as a new subgoal
+ allowed to depend on :g:`x`.
-the tactic ``intro`` applies the tactic ``hnf`` until the tactic ``intro`` can
-be applied or the goal is not head-reducible.
+ The tactic :tacn:`intro` applies the tactic :tacn:`hnf`
+ until :tacn:`intro` can be applied or the goal is not head-reducible.
-.. exn:: No product even after head-reduction.
-.. exn:: @ident is already used.
+ .. exn:: No product even after head-reduction.
+ :undocumented:
-.. tacv:: intros
- :name: intros
+ .. tacv:: intro @ident
- This repeats ``intro`` until it meets the head-constant. It never
- reduces head-constants and it never fails.
+ This applies :tacn:`intro` but forces :token:`ident` to be the name of
+ the introduced hypothesis.
-.. tacn:: intro @ident
+ .. exn:: @ident is already used.
+ :undocumented:
- This applies ``intro`` but forces :n:`@ident` to be the name of the
- introduced hypothesis.
+ .. note::
-.. exn:: Name @ident is already used.
+ If a name used by intro hides the base name of a global constant then
+ the latter can still be referred to by a qualified name
+ (see :ref:`Qualified-names`).
-.. note:: If a name used by intro hides the base name of a global
- constant then the latter can still be referred to by a qualified name
- (see :ref:`Qualified-names`).
-.. tacv:: intros {+ @ident}.
+ .. tacv:: intros
+ :name: intros
- This is equivalent to the composed tactic
- :n:`intro @ident; ... ; intro @ident`. More generally, the ``intros`` tactic
- takes a pattern as argument in order to introduce names for components
- of an inductive definition or to clear introduced hypotheses. This is
- explained in :ref:`Managingthelocalcontext`.
+ This repeats :tacn:`intro` until it meets the head-constant. It never
+ reduces head-constants and it never fails.
-.. tacv:: intros until @ident
+ .. tacv:: intros {+ @ident}.
- This repeats intro until it meets a premise of the goal having form
- `(@ident:term)` and discharges the variable named `ident` of the current
- goal.
+ This is equivalent to the composed tactic :n:`intro @ident; ... ; intro @ident`.
-.. exn:: No such hypothesis in current goal.
+ .. tacv:: intros until @ident
-.. tacv:: intros until @num
+ This repeats intro until it meets a premise of the goal having the
+ form :n:`(@ident : @type)` and discharges the variable
+ named :token:`ident` of the current goal.
- This repeats intro until the `num`-th non-dependent product. For instance,
- on the subgoal :g:`forall x y:nat, x=y -> y=x` the tactic
- :n:`intros until 1` is equivalent to :n:`intros x y H`, as :g:`x=y -> y=x`
- is the first non-dependent product. And on the subgoal :g:`forall x y
- z:nat, x=y -> y=x` the tactic :n:`intros until 1` is equivalent to
- :n:`intros x y z` as the product on :g:`z` can be rewritten as a
- non-dependent product: :g:`forall x y:nat, nat -> x=y -> y=x`
+ .. exn:: No such hypothesis in current goal.
+ :undocumented:
-.. exn:: No such hypothesis in current goal.
+ .. tacv:: intros until @num
- This happens when `num` is 0 or is greater than the number of non-dependent
- products of the goal.
+ This repeats :tacn:`intro` until the :token:`num`\-th non-dependent
+ product.
-.. tacv:: intro after @ident
-.. tacv:: intro before @ident
-.. tacv:: intro at top
-.. tacv:: intro at bottom
+ .. example::
- These tactics apply :n:`intro` and move the freshly introduced hypothesis
- respectively after the hypothesis :n:`@ident`, before the hypothesis
- :n:`@ident`, at the top of the local context, or at the bottom of the local
- context. All hypotheses on which the new hypothesis depends are moved
- too so as to respect the order of dependencies between hypotheses.
- Note that :n:`intro at bottom` is a synonym for :n:`intro` with no argument.
+ On the subgoal :g:`forall x y : nat, x = y -> y = x` the
+ tactic :n:`intros until 1` is equivalent to :n:`intros x y H`,
+ as :g:`x = y -> y = x` is the first non-dependent product.
-.. exn:: No such hypothesis: @ident.
+ On the subgoal :g:`forall x y z : nat, x = y -> y = x` the
+ tactic :n:`intros until 1` is equivalent to :n:`intros x y z`
+ as the product on :g:`z` can be rewritten as a non-dependent
+ product: :g:`forall x y : nat, nat -> x = y -> y = x`.
+
+ .. exn:: No such hypothesis in current goal.
+
+ This happens when :token:`num` is 0 or is greater than the number of
+ non-dependent products of the goal.
-.. tacv:: intro @ident after @ident
-.. tacv:: intro @ident before @ident
-.. tacv:: intro @ident at top
-.. tacv:: intro @ident at bottom
+ .. tacv:: intro {? @ident__1 } after @ident__2
+ intro {? @ident__1 } before @ident__2
+ intro {? @ident__1 } at top
+ intro {? @ident__1 } at bottom
- These tactics behave as previously but naming the introduced hypothesis
- :n:`@ident`. It is equivalent to :n:`intro @ident` followed by the
- appropriate call to ``move`` (see :tacn:`move ... after ...`).
+ These tactics apply :n:`intro {? @ident__1}` and move the freshly
+ introduced hypothesis respectively after the hypothesis :n:`@ident__2`,
+ before the hypothesis :n:`@ident__2`, at the top of the local context,
+ or at the bottom of the local context. All hypotheses on which the new
+ hypothesis depends are moved too so as to respect the order of
+ dependencies between hypotheses. It is equivalent to :n:`intro {? @ident__1 }`
+ followed by the appropriate call to :tacn:`move ... after ...`,
+ :tacn:`move ... before ...`, :tacn:`move ... at top`,
+ or :tacn:`move ... at bottom`.
+
+ .. note::
+
+ :n:`intro at bottom` is a synonym for :n:`intro` with no argument.
+
+ .. exn:: No such hypothesis: @ident.
+ :undocumented:
.. tacn:: intros @intro_pattern_list
:name: intros ...
@@ -766,24 +761,22 @@ be applied or the goal is not head-reducible.
:n:`intros p` is defined inductively over the structure of the introduction
pattern :n:`p`:
-Introduction on :n:`?` performs the introduction, and lets Coq choose a fresh
-name for the variable;
-
-Introduction on :n:`?ident` performs the introduction, and lets Coq choose a
-fresh name for the variable based on :n:`@ident`;
+ Introduction on :n:`?` performs the introduction, and lets Coq choose a fresh
+ name for the variable;
-Introduction on :n:`@ident` behaves as described in :tacn:`intro`
+ Introduction on :n:`?@ident` performs the introduction, and lets Coq choose a
+ fresh name for the variable based on :n:`@ident`;
-Introduction over a disjunction of list of patterns
-:n:`[@intro_pattern_list | ... | @intro_pattern_list ]` expects the product
-to be over an inductive type whose number of constructors is `n` (or more
-generally over a type of conclusion an inductive type built from `n`
-constructors, e.g. :g:`C -> A\/B` with `n=2` since :g:`A\/B` has `2`
-constructors): it destructs the introduced hypothesis as :n:`destruct` (see
-:tacn:`destruct`) would and applies on each generated subgoal the
-corresponding tactic;
+ Introduction on :n:`@ident` behaves as described in :tacn:`intro`
-.. tacv:: intros @intro_pattern_list
+ Introduction over a disjunction of list of patterns
+ :n:`[@intro_pattern_list | ... | @intro_pattern_list ]` expects the product
+ to be over an inductive type whose number of constructors is `n` (or more
+ generally over a type of conclusion an inductive type built from `n`
+ constructors, e.g. :g:`C -> A\/B` with `n=2` since :g:`A\/B` has `2`
+ constructors): it destructs the introduced hypothesis as :n:`destruct` (see
+ :tacn:`destruct`) would and applies on each generated subgoal the
+ corresponding tactic;
The introduction patterns in :n:`@intro_pattern_list` are expected to consume
no more than the number of arguments of the `i`-th constructor. If it
@@ -792,60 +785,59 @@ corresponding tactic;
list of patterns :n:`[ | ] H` applied on goal :g:`forall x:nat, x=0 -> 0=x`
behaves the same as the list of patterns :n:`[ | ? ] H`);
-Introduction over a conjunction of patterns :n:`({+, p})` expects
-the goal to be a product over an inductive type :g:`I` with a single
-constructor that itself has at least `n` arguments: It performs a case
-analysis over the hypothesis, as :n:`destruct` would, and applies the
-patterns :n:`{+ p}` to the arguments of the constructor of :g:`I` (observe
-that :n:`({+ p})` is an alternative notation for :n:`[{+ p}]`);
-
-Introduction via :n:`({+& p})` is a shortcut for introduction via
-:n:`(p,( ... ,( ..., p ) ... ))`; it expects the hypothesis to be a sequence of
-right-associative binary inductive constructors such as :g:`conj` or
-:g:`ex_intro`; for instance, an hypothesis with type
-:g:`A /\(exists x, B /\ C /\ D)` can be introduced via pattern
-:n:`(a & x & b & c & d)`;
-
-If the product is over an equality type, then a pattern of the form
-:n:`[= {+ p}]` applies either :tacn:`injection` or :tacn:`discriminate`
-instead of :tacn:`destruct`; if :tacn:`injection` is applicable, the patterns
-:n:`{+, p}` are used on the hypotheses generated by :tacn:`injection`; if the
-number of patterns is smaller than the number of hypotheses generated, the
-pattern :n:`?` is used to complete the list;
-
-.. tacv:: introduction over ->
-.. tacv:: introduction over <-
-
+ Introduction over a conjunction of patterns :n:`({+, p})` expects
+ the goal to be a product over an inductive type :g:`I` with a single
+ constructor that itself has at least `n` arguments: It performs a case
+ analysis over the hypothesis, as :n:`destruct` would, and applies the
+ patterns :n:`{+ p}` to the arguments of the constructor of :g:`I` (observe
+ that :n:`({+ p})` is an alternative notation for :n:`[{+ p}]`);
+
+ Introduction via :n:`({+& p})` is a shortcut for introduction via
+ :n:`(p,( ... ,( ..., p ) ... ))`; it expects the hypothesis to be a sequence of
+ right-associative binary inductive constructors such as :g:`conj` or
+ :g:`ex_intro`; for instance, a hypothesis with type
+ :g:`A /\(exists x, B /\ C /\ D)` can be introduced via pattern
+ :n:`(a & x & b & c & d)`;
+
+ If the product is over an equality type, then a pattern of the form
+ :n:`[= {+ p}]` applies either :tacn:`injection` or :tacn:`discriminate`
+ instead of :tacn:`destruct`; if :tacn:`injection` is applicable, the patterns
+ :n:`{+, p}` are used on the hypotheses generated by :tacn:`injection`; if the
+ number of patterns is smaller than the number of hypotheses generated, the
+ pattern :n:`?` is used to complete the list.
+
+ Introduction over ``->`` (respectively over ``<-``)
expects the hypothesis to be an equality and the right-hand-side
(respectively the left-hand-side) is replaced by the left-hand-side
(respectively the right-hand-side) in the conclusion of the goal;
the hypothesis itself is erased; if the term to substitute is a variable, it
- is substituted also in the context of goal and the variable is removed too;
+ is substituted also in the context of goal and the variable is removed too.
-Introduction over a pattern :n:`p{+ %term}` first applies :n:`{+ term}`
-on the hypothesis to be introduced (as in :n:`apply {+, term}`) prior to the
-application of the introduction pattern :n:`p`;
+ Introduction over a pattern :n:`p{+ %term}` first applies :n:`{+ term}`
+ on the hypothesis to be introduced (as in :n:`apply {+, term}`) prior to the
+ application of the introduction pattern :n:`p`;
-Introduction on the wildcard depends on whether the product is dependent or not:
-in the non-dependent case, it erases the corresponding hypothesis (i.e. it
-behaves as an :tacn:`intro` followed by a :tacn:`clear`) while in the
-dependent case, it succeeds and erases the variable only if the wildcard is part
-of a more complex list of introduction patterns that also erases the hypotheses
-depending on this variable;
+ Introduction on the wildcard depends on whether the product is dependent or not:
+ in the non-dependent case, it erases the corresponding hypothesis (i.e. it
+ behaves as an :tacn:`intro` followed by a :tacn:`clear`) while in the
+ dependent case, it succeeds and erases the variable only if the wildcard is part
+ of a more complex list of introduction patterns that also erases the hypotheses
+ depending on this variable;
-Introduction over :n:`*` introduces all forthcoming quantified variables
-appearing in a row; introduction over :n:`**` introduces all forthcoming
-quantified variables or hypotheses until the goal is not any more a
-quantification or an implication.
+ Introduction over :n:`*` introduces all forthcoming quantified variables
+ appearing in a row; introduction over :n:`**` introduces all forthcoming
+ quantified variables or hypotheses until the goal is not any more a
+ quantification or an implication.
-.. example::
+ .. example::
- .. coqtop:: all
+ .. coqtop:: reset all
- Goal forall A B C:Prop, A \/ B /\ C -> (A -> C) -> C.
- intros * [a | (_,c)] f.
+ Goal forall A B C:Prop, A \/ B /\ C -> (A -> C) -> C.
+ intros * [a | (_,c)] f.
.. note::
+
:n:`intros {+ p}` is not equivalent to :n:`intros p; ... ; intros p`
for the following reason: If one of the :n:`p` is a wildcard pattern, it
might succeed in the first case because the further hypotheses it
@@ -854,13 +846,14 @@ quantification or an implication.
introduced (and a fortiori not yet erased).
.. note::
+
In :n:`intros @intro_pattern_list`, if the last introduction pattern
is a disjunctive or conjunctive pattern
:n:`[{+| @intro_pattern_list}]`, the completion of :n:`@intro_pattern_list`
so that all the arguments of the i-th constructors of the corresponding
inductive type are introduced can be controlled with the following option:
- .. opt:: Bracketing Last Introduction Pattern
+ .. flag:: Bracketing Last Introduction Pattern
Force completion, if needed, when the last introduction pattern is a
disjunctive or conjunctive pattern (on by default).
@@ -872,38 +865,42 @@ quantification or an implication.
the current goal. As a consequence, :n:`@ident` is no more displayed and no
more usable in the proof development.
-.. exn:: No such hypothesis.
+ .. exn:: No such hypothesis.
+ :undocumented:
-.. exn:: @ident is used in the conclusion.
+ .. exn:: @ident is used in the conclusion.
+ :undocumented:
-.. exn:: @ident is used in the hypothesis @ident.
+ .. exn:: @ident is used in the hypothesis @ident.
+ :undocumented:
-.. tacv:: clear {+ @ident}
+ .. tacv:: clear {+ @ident}
- This is equivalent to :n:`clear @ident. ... clear @ident.`
+ This is equivalent to :n:`clear @ident. ... clear @ident.`
-.. tacv:: clear - {+ @ident}
+ .. tacv:: clear - {+ @ident}
- This tactic clears all the hypotheses except the ones depending in the
- hypotheses named :n:`{+ @ident}` and in the goal.
+ This variant clears all the hypotheses except the ones depending in the
+ hypotheses named :n:`{+ @ident}` and in the goal.
-.. tacv:: clear
+ .. tacv:: clear
- This tactic clears all the hypotheses except the ones the goal depends on.
+ This variants clears all the hypotheses except the ones the goal depends on.
-.. tacv:: clear dependent @ident
+ .. tacv:: clear dependent @ident
- This clears the hypothesis :n:`@ident` and all the hypotheses that depend on
- it.
+ This clears the hypothesis :token:`ident` and all the hypotheses that
+ depend on it.
-.. tacv:: clearbody {+ @ident}
- :name: clearbody
+ .. tacv:: clearbody {+ @ident}
+ :name: clearbody
- This tactic expects :n:`{+ @ident}` to be local definitions and clears their
- respective bodies.
- In other words, it turns the given definitions into assumptions.
+ This tactic expects :n:`{+ @ident}` to be local definitions and clears
+ their respective bodies.
+ In other words, it turns the given definitions into assumptions.
-.. exn:: @ident is not a local definition.
+ .. exn:: @ident is not a local definition.
+ :undocumented:
.. tacn:: revert {+ @ident}
:name: revert
@@ -912,172 +909,184 @@ quantification or an implication.
(possibly defined) to the goal, if this respects dependencies. This tactic is
the inverse of :tacn:`intro`.
-.. exn:: No such hypothesis.
+ .. exn:: No such hypothesis.
+ :undocumented:
-.. exn:: @ident is used in the hypothesis @ident.
+ .. exn:: @ident__1 is used in the hypothesis @ident__2.
+ :undocumented:
-.. tacn:: revert dependent @ident
+ .. tacv:: revert dependent @ident
+ :name: revert dependent
- This moves to the goal the hypothesis :n:`@ident` and all the hypotheses that
- depend on it.
+ This moves to the goal the hypothesis :token:`ident` and all the
+ hypotheses that depend on it.
-.. tacn:: move @ident after @ident
+.. tacn:: move @ident__1 after @ident__2
:name: move ... after ...
- This moves the hypothesis named :n:`@ident` in the local context after the
- hypothesis named :n:`@ident`, where “after” is in reference to the
+ This moves the hypothesis named :n:`@ident__1` in the local context after
+ the hypothesis named :n:`@ident__2`, where “after” is in reference to the
direction of the move. The proof term is not changed.
- If :n:`@ident` comes before :n:`@ident` in the order of dependencies, then
- all the hypotheses between :n:`@ident` and :n:`ident@` that (possibly
- indirectly) depend on :n:`@ident` are moved too, and all of them are thus
- moved after :n:`@ident` in the order of dependencies.
+ If :n:`@ident__1` comes before :n:`@ident__2` in the order of dependencies,
+ then all the hypotheses between :n:`@ident__1` and :n:`@ident__2` that
+ (possibly indirectly) depend on :n:`@ident__1` are moved too, and all of
+ them are thus moved after :n:`@ident__2` in the order of dependencies.
- If :n:`@ident` comes after :n:`@ident` in the order of dependencies, then all
- the hypotheses between :n:`@ident` and :n:`@ident` that (possibly indirectly)
- occur in the type of :n:`@ident` are moved too, and all of them are thus
- moved before :n:`@ident` in the order of dependencies.
+ If :n:`@ident__1` comes after :n:`@ident__2` in the order of dependencies,
+ then all the hypotheses between :n:`@ident__1` and :n:`@ident__2` that
+ (possibly indirectly) occur in the type of :n:`@ident__1` are moved too,
+ and all of them are thus moved before :n:`@ident__2` in the order of
+ dependencies.
-.. tacv:: move @ident before @ident
+ .. tacv:: move @ident__1 before @ident__2
+ :name: move ... before ...
- This moves :n:`@ident` towards and just before the hypothesis named
- :n:`@ident`. As for :tacn:`move ... after ...`, dependencies over
- :n:`@ident` (when :n:`@ident` comes before :n:`@ident` in the order of
- dependencies) or in the type of :n:`@ident` (when :n:`@ident` comes after
- :n:`@ident` in the order of dependencies) are moved too.
+ This moves :n:`@ident__1` towards and just before the hypothesis
+ named :n:`@ident__2`. As for :tacn:`move ... after ...`, dependencies
+ over :n:`@ident__1` (when :n:`@ident__1` comes before :n:`@ident__2` in
+ the order of dependencies) or in the type of :n:`@ident__1`
+ (when :n:`@ident__1` comes after :n:`@ident__2` in the order of
+ dependencies) are moved too.
-.. tacv:: move @ident at top
+ .. tacv:: move @ident at top
+ :name: move ... at top
- This moves :n:`@ident` at the top of the local context (at the beginning of
- the context).
+ This moves :token:`ident` at the top of the local context (at the beginning
+ of the context).
-.. tacv:: move @ident at bottom
+ .. tacv:: move @ident at bottom
+ :name: move ... at bottom
- This moves ident at the bottom of the local context (at the end of the
- context).
+ This moves :token:`ident` at the bottom of the local context (at the end of
+ the context).
-.. exn:: No such hypothesis.
-.. exn:: Cannot move @ident after @ident : it occurs in the type of @ident.
-.. exn:: Cannot move @ident after @ident : it depends on @ident.
+ .. exn:: No such hypothesis.
+ :undocumented:
-.. example::
+ .. exn:: Cannot move @ident__1 after @ident__2: it occurs in the type of @ident__2.
+ :undocumented:
- .. coqtop:: all
+ .. exn:: Cannot move @ident__1 after @ident__2: it depends on @ident__2.
+ :undocumented:
- Goal forall x :nat, x = 0 -> forall z y:nat, y=y-> 0=x.
- intros x H z y H0.
- move x after H0.
- Undo.
- move x before H0.
- Undo.
- move H0 after H.
- Undo.
- move H0 before H.
-
-.. tacn:: rename @ident into @ident
+ .. example::
+
+ .. coqtop:: reset all
+
+ Goal forall x :nat, x = 0 -> forall z y:nat, y=y-> 0=x.
+ intros x H z y H0.
+ move x after H0.
+ Undo.
+ move x before H0.
+ Undo.
+ move H0 after H.
+ Undo.
+ move H0 before H.
+
+.. tacn:: rename @ident__1 into @ident__2
:name: rename
-This renames hypothesis :n:`@ident` into :n:`@ident` in the current context.
-The name of the hypothesis in the proof-term, however, is left unchanged.
+ This renames hypothesis :n:`@ident__1` into :n:`@ident__2` in the current
+ context. The name of the hypothesis in the proof-term, however, is left
+ unchanged.
+
+ .. tacv:: rename {+, @ident__i into @ident__j}
-.. tacv:: rename {+, @ident into @ident}
+ This renames the variables :n:`@ident__i` into :n:`@ident__j` in parallel.
+ In particular, the target identifiers may contain identifiers that exist in
+ the source context, as long as the latter are also renamed by the same
+ tactic.
- This renames the variables :n:`@ident` into :n:`@ident` in parallel. In
- particular, the target identifiers may contain identifiers that exist in the
- source context, as long as the latter are also renamed by the same tactic.
+ .. exn:: No such hypothesis.
+ :undocumented:
-.. exn:: No such hypothesis.
-.. exn:: @ident is already used.
+ .. exn:: @ident is already used.
+ :undocumented:
.. tacn:: set (@ident := @term)
:name: set
- This replaces :n:`@term` by :n:`@ident` in the conclusion of the current goal
- and adds the new definition :g:`ident := term` to the local context.
-
- If :n:`@term` has holes (i.e. subexpressions of the form “`_`”), the tactic
- first checks that all subterms matching the pattern are compatible before
- doing the replacement using the leftmost subterm matching the pattern.
+ This replaces :token:`term` by :token:`ident` in the conclusion of the
+ current goal and adds the new definition :n:`@ident := @term` to the
+ local context.
-.. exn:: The variable @ident is already defined.
+ If :token:`term` has holes (i.e. subexpressions of the form “`_`”), the
+ tactic first checks that all subterms matching the pattern are compatible
+ before doing the replacement using the leftmost subterm matching the
+ pattern.
-.. tacv:: set (@ident := @term ) in @goal_occurrences
+ .. exn:: The variable @ident is already defined.
+ :undocumented:
- This notation allows specifying which occurrences of :n:`@term` have to be
- substituted in the context. The :n:`in @goal_occurrences` clause is an
- occurrence clause whose syntax and behavior are described in
- :ref:`goal occurences <occurencessets>`.
+ .. tacv:: set (@ident := @term) in @goal_occurrences
-.. tacv:: set (@ident {+ @binder} := @term )
+ This notation allows specifying which occurrences of :token:`term` have
+ to be substituted in the context. The :n:`in @goal_occurrences` clause
+ is an occurrence clause whose syntax and behavior are described in
+ :ref:`goal occurences <occurencessets>`.
- This is equivalent to :n:`set (@ident := funbinder {+ binder} => @term )`.
+ .. tacv:: set (@ident @binders := @term) {? in @goal_occurrences }
-.. tacv:: set term
- This behaves as :n:`set(@ident := @term)` but :n:`@ident` is generated by
- Coq. This variant also supports an occurrence clause.
+ This is equivalent to :n:`set (@ident := fun @binders => @term) {? in @goal_occurrences }`.
-.. tacv:: set (@ident {+ @binder} := @term) in @goal_occurrences
-.. tacv:: set @term in @goal_occurrences
+ .. tacv:: set @term {? in @goal_occurrences }
- These are the general forms that combine the previous possibilities.
+ This behaves as :n:`set (@ident := @term) {? in @goal_occurrences }`
+ but :token:`ident` is generated by Coq.
-.. tacv:: eset (@ident {+ @binder} := @term ) in @goal_occurrences
-.. tacv:: eset @term in @goal_occurrences
- :name: eset
+ .. tacv:: eset (@ident {? @binders } := @term) {? in @goal_occurrences }
+ eset @term {? in @goal_occurrences }
+ :name: eset; _
- While the different variants of :tacn:`set` expect that no existential
- variables are generated by the tactic, :n:`eset` removes this constraint. In
- practice, this is relevant only when :n:`eset` is used as a synonym of
- :tacn:`epose`, i.e. when the :`@term` does not occur in the goal.
+ While the different variants of :tacn:`set` expect that no existential
+ variables are generated by the tactic, :tacn:`eset` removes this
+ constraint. In practice, this is relevant only when :tacn:`eset` is
+ used as a synonym of :tacn:`epose`, i.e. when the :token:`term` does
+ not occur in the goal.
-.. tacv:: remember @term as @ident
+.. tacn:: remember @term as @ident__1 {? eqn:@ident__2 }
:name: remember
- This behaves as :n:`set (@ident:= @term ) in *` and using a logical
+ This behaves as :n:`set (@ident__1 := @term) in *`, using a logical
(Leibniz’s) equality instead of a local definition.
+ If :n:`@ident__2` is provided, it will be the name of the new equation.
-.. tacv:: remember @term as @ident eqn:@ident
-
- This behaves as :n:`remember @term as @ident`, except that the name of the
- generated equality is also given.
-
-.. tacv:: remember @term as @ident in @goal_occurrences
+ .. tacv:: remember @term as @ident__1 {? eqn:@ident__2 } in @goal_occurrences
- This is a more general form of :n:`remember` that remembers the occurrences
- of term specified by an occurrence set.
+ This is a more general form of :tacn:`remember` that remembers the
+ occurrences of :token:`term` specified by an occurrence set.
-.. tacv:: eremember @term as @ident
-.. tacv:: eremember @term as @ident in @goal_occurrences
-.. tacv:: eremember @term as @ident eqn:@ident
- :name: eremember
+ .. tacv:: eremember @term as @ident__1 {? eqn:@ident__2 } {? in @goal_occurrences }
+ :name: eremember
- While the different variants of :n:`remember` expect that no existential
- variables are generated by the tactic, :n:`eremember` removes this constraint.
+ While the different variants of :tacn:`remember` expect that no
+ existential variables are generated by the tactic, :tacn:`eremember`
+ removes this constraint.
-.. tacv:: pose ( @ident := @term )
+.. tacn:: pose (@ident := @term)
:name: pose
This adds the local definition :n:`@ident := @term` to the current context
without performing any replacement in the goal or in the hypotheses. It is
- equivalent to :n:`set ( @ident := @term ) in |-`.
+ equivalent to :n:`set (@ident := @term) in |-`.
-.. tacv:: pose ( @ident {+ @binder} := @term )
+ .. tacv:: pose (@ident @binders := @term)
- This is equivalent to :n:`pose (@ident := funbinder {+ binder} => @term)`.
+ This is equivalent to :n:`pose (@ident := fun @binders => @term)`.
-.. tacv:: pose @term
+ .. tacv:: pose @term
- This behaves as :n:`pose (@ident := @term )` but :n:`@ident` is generated by
- Coq.
+ This behaves as :n:`pose (@ident := @term)` but :token:`ident` is
+ generated by Coq.
-.. tacv:: epose (@ident := @term )
-.. tacv:: epose (@ident {+ @binder} := @term )
-.. tacv:: epose term
- :name: epose
+ .. tacv:: epose (@ident {? @binders} := @term)
+ .. tacv:: epose term
+ :name: epose
- While the different variants of :tacn:`pose` expect that no
- existential variables are generated by the tactic, epose removes this
- constraint.
+ While the different variants of :tacn:`pose` expect that no
+ existential variables are generated by the tactic, :tacn:`epose`
+ removes this constraint.
.. tacn:: decompose [{+ @qualid}] @term
:name: decompose
@@ -1085,25 +1094,30 @@ The name of the hypothesis in the proof-term, however, is left unchanged.
This tactic recursively decomposes a complex proposition in order to
obtain atomic ones.
-.. example::
+ .. example::
- .. coqtop:: all
+ .. coqtop:: reset all
- Goal forall A B C:Prop, A /\ B /\ C \/ B /\ C \/ C /\ A -> C.
- intros A B C H; decompose [and or] H; assumption.
- Qed.
+ Goal forall A B C:Prop, A /\ B /\ C \/ B /\ C \/ C /\ A -> C.
+ intros A B C H; decompose [and or] H.
+ all: assumption.
+ Qed.
+
+ .. note::
+
+ :tacn:`decompose` does not work on right-hand sides of implications or
+ products.
-:n:`decompose` does not work on right-hand sides of implications or products.
+ .. tacv:: decompose sum @term
-.. tacv:: decompose sum @term
+ This decomposes sum types (like :g:`or`).
- This decomposes sum types (like or).
+ .. tacv:: decompose record @term
-.. tacv:: decompose record @term
+ This decomposes record types (inductive types with one constructor,
+ like :g:`and` and :g:`exists` and those defined with the :cmd:`Record`
+ command.
- This decomposes record types (inductive types with one constructor, like
- "and" and "exists" and those defined with the Record macro, see
- :ref:`record-types`).
.. _controllingtheproofflow:
@@ -1282,7 +1296,7 @@ name of the variable (here :g:`n`) is chosen based on :g:`T`.
This is equivalent to :n:`generalize @term` but it generalizes only over the
specified occurrences of :n:`@term` (counting from left to right on the
- expression printed using option :opt:`Printing All`).
+ expression printed using option :flag:`Printing All`).
.. tacv:: generalize @term as @ident
@@ -1329,8 +1343,8 @@ name of the variable (here :g:`n`) is chosen based on :g:`T`.
changes in the goal, its use is strongly discouraged.
.. tacv:: instantiate ( @num := @term ) in @ident
-.. tacv:: instantiate ( @num := @term ) in ( Value of @ident )
-.. tacv:: instantiate ( @num := @term ) in ( Type of @ident )
+.. tacv:: instantiate ( @num := @term ) in ( value of @ident )
+.. tacv:: instantiate ( @num := @term ) in ( type of @ident )
These allow to refer respectively to existential variables occurring in a
hypothesis or in the body or the type of a local definition.
@@ -1368,7 +1382,7 @@ goals cannot be closed with :g:`Qed` but only with :g:`Admitted`.
:name: contradiction
This tactic applies to any goal. The contradiction tactic attempts to
- find in the current context (after all intros) an hypothesis that is
+ find in the current context (after all intros) a hypothesis that is
equivalent to an empty inductive type (e.g. :g:`False`), to the negation of
a singleton inductive type (e.g. :g:`True` or :g:`x=x`), or two contradictory
hypotheses.
@@ -1410,94 +1424,101 @@ analysis on inductive or co-inductive objects (see :ref:`inductive-definitions`)
.. tacn:: destruct @term
:name: destruct
- This tactic applies to any goal. The argument :n:`@term` must be of
+ This tactic applies to any goal. The argument :token:`term` must be of
inductive or co-inductive type and the tactic generates subgoals, one
- for each possible form of :n:`@term`, i.e. one for each constructor of the
- inductive or co-inductive type. Unlike :n:`induction`, no induction
- hypothesis is generated by :n:`destruct`.
+ for each possible form of :token:`term`, i.e. one for each constructor of the
+ inductive or co-inductive type. Unlike :tacn:`induction`, no induction
+ hypothesis is generated by :tacn:`destruct`.
+
+ .. tacv:: destruct @ident
+
+ If :token:`ident` denotes a quantified variable of the conclusion
+ of the goal, then :n:`destruct @ident` behaves
+ as :n:`intros until @ident; destruct @ident`. If :token:`ident` is not
+ anymore dependent in the goal after application of :tacn:`destruct`, it
+ is erased (to avoid erasure, use parentheses, as in :n:`destruct (@ident)`).
- There are special cases:
+ If :token:`ident` is a hypothesis of the context, and :token:`ident`
+ is not anymore dependent in the goal after application
+ of :tacn:`destruct`, it is erased (to avoid erasure, use parentheses, as
+ in :n:`destruct (@ident)`).
- + If :n:`@term` is an identifier :n:`@ident` denoting a quantified variable
- of the conclusion of the goal, then :n:`destruct @ident` behaves as
- :n:`intros until @ident; destruct @ident`. If :n:`@ident` is not anymore
- dependent in the goal after application of :n:`destruct`, it is erased
- (to avoid erasure, use parentheses, as in :n:`destruct (@ident)`).
+ .. tacv:: destruct @num
- + If term is a num, then destruct num behaves as intros until num
- followed by destruct applied to the last introduced hypothesis.
+ :n:`destruct @num` behaves as :n:`intros until @num`
+ followed by destruct applied to the last introduced hypothesis.
.. note::
- For destruction of a numeral, use syntax destruct (num) (not
+ For destruction of a numeral, use syntax :n:`destruct (@num)` (not
very interesting anyway).
- + In case term is an hypothesis :n:`@ident` of the context, and :n:`@ident`
- is not anymore dependent in the goal after application of :n:`destruct`, it
- is erased (to avoid erasure, use parentheses, as in :n:`destruct (@ident)`).
+ .. tacv:: destruct @pattern
- + The argument :n:`@term` can also be a pattern of which holes are denoted
- by “_”. In this case, the tactic checks that all subterms matching the
- pattern in the conclusion and the hypotheses are compatible and
- performs case analysis using this subterm.
+ The argument of :tacn:`destruct` can also be a pattern of which holes are
+ denoted by “_”. In this case, the tactic checks that all subterms
+ matching the pattern in the conclusion and the hypotheses are compatible
+ and performs case analysis using this subterm.
-.. tacv:: destruct {+, @term}
+ .. tacv:: destruct {+, @term}
- This is a shortcut for :n:`destruct term; ...; destruct term`.
+ This is a shortcut for :n:`destruct @term; ...; destruct @term`.
-.. tacv:: destruct @term as @disj_conj_intro_pattern
+ .. tacv:: destruct @term as @disj_conj_intro_pattern
- This behaves as :n:`destruct @term` but uses the names in :n:`@intro_pattern`
- to name the variables introduced in the context. The :n:`@intro_pattern` must
- have the form :n:`[p11 ... p1n | ... | pm1 ... pmn ]` with `m` being the
- number of constructors of the type of :n:`@term`. Each variable introduced
- by :n:`destruct` in the context of the `i`-th goal gets its name from the
- list :n:`pi1 ... pin` in order. If there are not enough names,
- :n:`@destruct` invents names for the remaining variables to introduce. More
- generally, the :n:`pij` can be any introduction pattern (see
- :tacn:`intros`). This provides a concise notation for chaining destruction of
- an hypothesis.
+ This behaves as :n:`destruct @term` but uses the names
+ in :token:`disj_conj_intro_pattern` to name the variables introduced in the
+ context. The :token:`disj_conj_intro_pattern` must have the
+ form :n:`[p11 ... p1n | ... | pm1 ... pmn ]` with ``m`` being the
+ number of constructors of the type of :token:`term`. Each variable
+ introduced by :tacn:`destruct` in the context of the ``i``-th goal
+ gets its name from the list :n:`pi1 ... pin` in order. If there are not
+ enough names, :tacn:`destruct` invents names for the remaining variables
+ to introduce. More generally, the :n:`pij` can be any introduction
+ pattern (see :tacn:`intros`). This provides a concise notation for
+ chaining destruction of a hypothesis.
-.. tacv:: destruct @term eqn:@naming_intro_pattern
+ .. tacv:: destruct @term eqn:@naming_intro_pattern
+ :name: destruct ... eqn:
- This behaves as :n:`destruct @term` but adds an equation between :n:`@term`
- and the value that :n:`@term` takes in each of the possible cases. The name
- of the equation is specified by :n:`@naming_intro_pattern` (see
- :tacn:`intros`), in particular `?` can be used to let Coq generate a fresh
- name.
+ This behaves as :n:`destruct @term` but adds an equation
+ between :token:`term` and the value that it takes in each of the
+ possible cases. The name of the equation is specified
+ by :token:`naming_intro_pattern` (see :tacn:`intros`),
+ in particular ``?`` can be used to let Coq generate a fresh name.
-.. tacv:: destruct @term with @bindings_list
+ .. tacv:: destruct @term with @bindings_list
- This behaves like :n:`destruct @term` providing explicit instances for the
- dependent premises of the type of :n:`@term` (see :ref:`syntax of bindings <bindingslist>`).
+ This behaves like :n:`destruct @term` providing explicit instances for
+ the dependent premises of the type of :token:`term`.
-.. tacv:: edestruct @term
- :name: edestruct
+ .. tacv:: edestruct @term
+ :name: edestruct
- This tactic behaves like :n:`destruct @term` except that it does not fail if
- the instance of a dependent premises of the type of :n:`@term` is not
- inferable. Instead, the unresolved instances are left as existential
- variables to be inferred later, in the same way as :tacn:`eapply` does.
+ This tactic behaves like :n:`destruct @term` except that it does not
+ fail if the instance of a dependent premises of the type
+ of :token:`term` is not inferable. Instead, the unresolved instances
+ are left as existential variables to be inferred later, in the same way
+ as :tacn:`eapply` does.
-.. tacv:: destruct @term using @term
-.. tacv:: destruct @term using @term with @bindings_list
+ .. tacv:: destruct @term using @term {? with @bindings_list }
- These are synonyms of :n:`induction @term using @term` and
- :n:`induction @term using @term with @bindings_list`.
+ This is synonym of :n:`induction @term using @term {? with @bindings_list }`.
-.. tacv:: destruct @term in @goal_occurrences
+ .. tacv:: destruct @term in @goal_occurrences
- This syntax is used for selecting which occurrences of :n:`@term` the case
- analysis has to be done on. The :n:`in @goal_occurrences` clause is an
- occurrence clause whose syntax and behavior is described in
- :ref:`occurences sets <occurencessets>`.
+ This syntax is used for selecting which occurrences of :token:`term`
+ the case analysis has to be done on. The :n:`in @goal_occurrences`
+ clause is an occurrence clause whose syntax and behavior is described
+ in :ref:`occurences sets <occurencessets>`.
-.. tacv:: destruct @term with @bindings_list as @disj_conj_intro_pattern eqn:@naming_intro_pattern using @term with @bindings_list in @goal_occurrences
-.. tacv:: edestruct @term with @bindings_list as @disj_conj_intro_pattern eqn:@naming_intro_pattern using @term with @bindings_list in @goal_occurrences
+ .. tacv:: destruct @term {? with @bindings_list } {? as @disj_conj_intro_pattern } {? eqn:@naming_intro_pattern } {? using @term {? with @bindings_list } } {? in @goal_occurrences }
+ edestruct @term {? with @bindings_list } {? as @disj_conj_intro_pattern } {? eqn:@naming_intro_pattern } {? using @term {? with @bindings_list } } {? in @goal_occurrences }
- These are the general forms of :n:`destruct` and :n:`edestruct`. They combine
- the effects of the `with`, `as`, `eqn:`, `using`, and `in` clauses.
+ These are the general forms of :tacn:`destruct` and :tacn:`edestruct`.
+ They combine the effects of the ``with``, ``as``, ``eqn:``, ``using``,
+ and ``in`` clauses.
-.. tacv:: case term
+.. tacn:: case term
:name: case
The tactic :n:`case` is a more basic tactic to perform case analysis without
@@ -1563,7 +1584,7 @@ analysis on inductive or co-inductive objects (see :ref:`inductive-definitions`)
For simple induction on a numeral, use syntax induction (num)
(not very interesting anyway).
- + In case term is an hypothesis :n:`@ident` of the context, and :n:`@ident`
+ + In case term is a hypothesis :n:`@ident` of the context, and :n:`@ident`
is not anymore dependent in the goal after application of :n:`induction`,
it is erased (to avoid erasure, use parentheses, as in
:n:`induction (@ident)`).
@@ -1855,9 +1876,7 @@ and an explanation of the underlying technique.
:g:`Fixpoint` or :g:`Definition`. See :ref:`advanced-recursive-functions`
for details.
-See also: :ref:`advanced-recursive-functions`
- :ref:`functional-scheme`
- :tacn:`inversion`
+.. seealso:: :ref:`advanced-recursive-functions`, :ref:`functional-scheme` and :tacn:`inversion`
.. exn:: Cannot find induction information on @qualid.
.. exn:: Not the right number of induction arguments.
@@ -2018,16 +2037,16 @@ See also: :ref:`advanced-recursive-functions`
the number of equalities newly generated. If it is smaller, fresh
names are automatically generated to adjust the list of :n:`@intro_pattern`
to the number of new equalities. The original equality is erased if it
- corresponds to an hypothesis.
+ corresponds to a hypothesis.
- .. opt:: Structural Injection
+ .. flag:: Structural Injection
This option ensure that :n:`injection @term` erases the original hypothesis
and leaves the generated equalities in the context rather than putting them
as antecedents of the current goal, as if giving :n:`injection @term as`
(with an empty list of names). This option is off by default.
- .. opt:: Keep Proof Equalities
+ .. flag:: Keep Proof Equalities
By default, :tacn:`injection` only creates new equalities between :n:`@terms`
whose type is in sort :g:`Type` or :g:`Set`, thus implementing a special
@@ -2059,7 +2078,7 @@ See also: :ref:`advanced-recursive-functions`
being processed. By default, no equalities are generated if they
relate two proofs (i.e. equalities between :n:`@terms` whose type is in sort
:g:`Prop`). This behavior can be turned off by using the option
- :opt`Keep Proof Equalities`.
+ :flag`Keep Proof Equalities`.
.. tacv:: inversion @num
@@ -2195,6 +2214,7 @@ See also: :ref:`advanced-recursive-functions`
``simple inversion``.
.. tacv:: inversion @ident using @ident
+ :name: inversion ... using ...
Let :n:`@ident` have type :g:`(I t)` (:g:`I` an inductive predicate) in the
local context, and :n:`@ident` be a (dependent) inversion lemma. Then, this
@@ -2289,8 +2309,8 @@ See also: :ref:`advanced-recursive-functions`
As H occurs in the goal, we may want to reason by cases on its
structure and so, we would like inversion tactics to substitute H by
- the corresponding @term in constructor form. Neither Inversion nor
- Inversion_clear make such a substitution. To have such a behavior we
+ the corresponding @term in constructor form. Neither :tacn:`inversion` nor
+ :n:`inversion_clear` do such a substitution. To have such a behavior we
use the dependent inversion tactics:
.. coqtop:: all
@@ -2569,7 +2589,7 @@ simply :g:`t=u` dropping the implicit type of :g:`t` and :g:`u`.
context for which an equality of the form :n:`@ident = t` or :n:`t = @ident`
or :n:`@ident := t` exists, with :n:`@ident` not occurring in ``t``.
- .. opt:: Regular Subst Tactic
+ .. flag:: Regular Subst Tactic
This option controls the behavior of :tacn:`subst`. When it is
activated (it is by default), :tacn:`subst` also deals with the following corner cases:
@@ -2704,7 +2724,7 @@ the conversion in hypotheses :n:`{+ @ident}`.
:math:`\beta` (reduction of functional application), :math:`\delta`
(unfolding of transparent constants, see :ref:`vernac-controlling-the-reduction-strategies`),
:math:`\iota` (reduction of
- pattern-matching over a constructed term, and unfolding of :g:`fix` and
+ pattern matching over a constructed term, and unfolding of :g:`fix` and
:g:`cofix` expressions) and :math:`\zeta` (contraction of local definitions), the
flags are either ``beta``, ``delta``, ``match``, ``fix``, ``cofix``,
``iota`` or ``zeta``. The ``iota`` flag is a shorthand for ``match``, ``fix``
@@ -2787,12 +2807,13 @@ the conversion in hypotheses :n:`{+ @ident}`.
compilation cost is higher, so it is worth using only for intensive
computations.
- .. opt:: NativeCompute Profiling
+ .. flag:: NativeCompute Profiling
On Linux, if you have the ``perf`` profiler installed, this option makes
it possible to profile ``native_compute`` evaluations.
- .. opt:: NativeCompute Profile Filename
+ .. opt:: NativeCompute Profile Filename @string
+ :name: NativeCompute Profile Filename
This option specifies the profile output; the default is
``native_compute_profile.data``. The actual filename used
@@ -2803,7 +2824,7 @@ the conversion in hypotheses :n:`{+ @ident}`.
on the profile file to see the results. Consult the ``perf`` documentation
for more details.
-.. opt:: Debug Cbv
+.. flag:: Debug Cbv
This option makes :tacn:`cbv` (and its derivative :tacn:`compute`) print
information about the constants it encounters and the unfolding decisions it
@@ -2970,7 +2991,7 @@ the conversion in hypotheses :n:`{+ @ident}`.
This applies ``simpl`` only to the :n:`{+ @num}` applicative subterms whose
head occurrence is :n:`@qualid` (or :n:`@string`).
-.. opt:: Debug RAKAM
+.. flag:: Debug RAKAM
This option makes :tacn:`cbn` print various debugging information.
``RAKAM`` is the Refolding Algebraic Krivine Abstract Machine.
@@ -3177,12 +3198,13 @@ hints of the database named core.
The following options enable printing of informative or debug information for
the :tacn:`auto` and :tacn:`trivial` tactics:
-.. opt:: Info Auto
-.. opt:: Debug Auto
-.. opt:: Info Trivial
-.. opt:: Debug Trivial
+.. flag:: Info Auto
+ Debug Auto
+ Info Trivial
+ Debug Trivial
+ :undocumented:
-See also: :ref:`The Hints Databases for auto and eauto <thehintsdatabasesforautoandeauto>`
+.. seealso:: :ref:`The Hints Databases for auto and eauto <thehintsdatabasesforautoandeauto>`
.. tacn:: eauto
:name: eauto
@@ -3210,10 +3232,11 @@ Note that ``ex_intro`` should be declared as a hint.
:tacn:`eauto` also obeys the following options:
-.. opt:: Info Eauto
-.. opt:: Debug Eauto
+.. flag:: Info Eauto
+ Debug Eauto
+ :undocumented:
-See also: :ref:`The Hints Databases for auto and eauto <thehintsdatabasesforautoandeauto>`
+.. seealso:: :ref:`The Hints Databases for auto and eauto <thehintsdatabasesforautoandeauto>`
.. tacn:: autounfold with {+ @ident}
@@ -3270,10 +3293,10 @@ command.
Performs all the rewriting in the clause :n:`@clause`. The clause argument
must not contain any ``type of`` nor ``value of``.
-See also: :ref:`Hint-Rewrite <hintrewrite>` for feeding the database of lemmas used by
-:tacn:`autorewrite`.
+.. seealso::
-See also: :tacn:`autorewrite` for examples showing the use of this tactic.
+ :ref:`Hint-Rewrite <hintrewrite>` for feeding the database of lemmas used by
+ :tacn:`autorewrite` and :tacn:`autorewrite` for examples showing the use of this tactic.
.. tacn:: easy
:name: easy
@@ -3545,7 +3568,7 @@ The general command to add a hint to some databases :n:`{+ @ident}` is
.. note::
- One can use an ``Extern`` hint with no pattern to do pattern-matching on
+ One can use an ``Extern`` hint with no pattern to do pattern matching on
hypotheses using ``match goal`` with inside the tactic.
@@ -3569,7 +3592,7 @@ At Coq startup, only the core database is nonempty and can be used.
:zarith: contains lemmas about binary signed integers from the directories
theories/ZArith. When required, the module Omega also extends the
database zarith with a high-cost hint that calls ``omega`` on equations
- and inequalities in nat or Z.
+ and inequalities in ``nat`` or ``Z``.
:bool: contains lemmas about booleans, mostly from directory theories/Bool.
@@ -3579,7 +3602,7 @@ At Coq startup, only the core database is nonempty and can be used.
:sets: contains lemmas about sets and relations from the directories Sets and
Relations.
-:typeclass_instances: contains all the type class instances declared in the
+:typeclass_instances: contains all the typeclass instances declared in the
environment, including those used for ``setoid_rewrite``,
from the Classes directory.
@@ -3708,7 +3731,7 @@ Setting implicit automation tactics
In this case the tactic command typed by the user is equivalent to
``tactic``:sub:`1` ``;tactic``.
- See also: ``Proof.`` in :ref:`proof-editing-mode`.
+ .. seealso:: :cmd:`Proof` in :ref:`proof-editing-mode`.
.. cmdv:: Proof with tactic using {+ @ident}
@@ -3841,7 +3864,7 @@ some incompatibilities.
``Empty_set``, ``unit``, ``True``, :tacn:`dintuition` also recognizes all inductive
types with one constructor and no indices, i.e. record-style connectives.
-.. opt:: Intuition Negation Unfolding
+.. flag:: Intuition Negation Unfolding
Controls whether :tacn:`intuition` unfolds inner negations which do not need
to be unfolded. This option is on by default.
@@ -3870,6 +3893,7 @@ usual logical connectives but instead may reason about any first-order class
inductive definition.
.. opt:: Firstorder Solver @tactic
+ :name: Firstorder Solver
The default tactic used by :tacn:`firstorder` when no rule applies is
:g:`auto with *`, it can be reset locally or globally using this option.
@@ -3898,6 +3922,7 @@ inductive definition.
This combines the effects of the different variants of :tacn:`firstorder`.
.. opt:: Firstorder Depth @num
+ :name: Firstorder Depth
This option controls the proof-search depth bound.
@@ -3960,7 +3985,7 @@ match against it.
additional arguments can be given to congruence by filling in the holes in the
terms given in the error message, using the :tacn:`congruence with` variant described above.
-.. opt:: Congruence Verbose
+.. flag:: Congruence Verbose
This option makes :tacn:`congruence` print debug information.
@@ -4182,8 +4207,9 @@ available after a ``Require Import FunInd``.
.. tacv:: functional inversion @num
- This does the same thing as intros until num thenfunctional inversion ident
- where ident is the identifier for the last introduced hypothesis.
+ This does the same thing as :n:`intros until @num` folowed by
+ :n:`functional inversion @ident` where :token:`ident` is the
+ identifier for the last introduced hypothesis.
.. tacv:: functional inversion ident qualid
.. tacv:: functional inversion num qualid
@@ -4195,26 +4221,6 @@ available after a ``Require Import FunInd``.
functional inversion, this variant allows choosing which :n:`@qualid` is
inverted.
-.. tacn:: quote @ident
- :name: quote
-
-This kind of inversion has nothing to do with the tactic :tacn:`inversion`
-above. This tactic does :g:`change (@ident t)`, where `t` is a term built in
-order to ensure the convertibility. In other words, it does inversion of the
-function :n:`@ident`. This function must be a fixpoint on a simple recursive
-datatype: see :ref:`quote` for the full details.
-
-
-.. exn:: quote: not a simple fixpoint.
-
- Happens when quote is not able to perform inversion properly.
-
-
-.. tacv:: quote @ident {* @ident}
-
- All terms that are built only with :n:`{* @ident}` will be considered by quote
- as constants rather than variables.
-
Classical tactics
-----------------
@@ -4290,7 +4296,7 @@ and :g:`Z` of binary integers. This tactic must be loaded by the command
:name: ring_simplify
The :n:`ring` tactic solves equations upon polynomial expressions of a ring
-(or semi-ring) structure. It proceeds by normalizing both hand sides
+(or semiring) structure. It proceeds by normalizing both hand sides
of the equation (w.r.t. associativity, commutativity and
distributivity, constant propagation) and comparing syntactically the
results.
@@ -4343,8 +4349,10 @@ printed with the Print Fields command.
intros; field.
-See also: file plugins/setoid_ring/RealField.v for an example of instantiation,
-theory theories/Reals for many examples of use of field.
+.. seealso::
+
+ File plugins/setoid_ring/RealField.v for an example of instantiation,
+ theory theories/Reals for many examples of use of field.
Non-logical tactics
------------------------
@@ -4465,7 +4473,7 @@ user-defined tactics.
other one can be automatically checked.
.. [2] This corresponds to the cut rule of sequent calculus.
.. [3] Reminder: opaque constants will not be expanded by δ reductions.
-.. [4] The behavior of this tactic has much changed compared to the
+.. [4] The behavior of this tactic has changed a lot compared to the
versions available in the previous distributions (V6). This may cause
significant changes in your theories to obtain the same result. As a
drawback of the re-engineering of the code, this tactic has also been
diff --git a/doc/sphinx/proof-engine/vernacular-commands.rst b/doc/sphinx/proof-engine/vernacular-commands.rst
index 0a517973c2..be65ff7570 100644
--- a/doc/sphinx/proof-engine/vernacular-commands.rst
+++ b/doc/sphinx/proof-engine/vernacular-commands.rst
@@ -1,6 +1,3 @@
-.. include:: ../preamble.rst
-.. include:: ../replaces.rst
-
.. _vernacularcommands:
Vernacular commands
@@ -38,7 +35,7 @@ Displaying
.. cmdv:: Print {? Term } @qualid\@@name
This locally renames the polymorphic universes of :n:`@qualid`.
- An underscore means the raw universe is printed.
+ An underscore means the usual name is printed.
.. cmd:: About @qualid
@@ -52,7 +49,7 @@ Displaying
.. cmdv:: About @qualid\@@name
This locally renames the polymorphic universes of :n:`@qualid`.
- An underscore means the raw universe is printed.
+ An underscore means the usual name is printed.
.. cmd:: Print All
@@ -78,145 +75,106 @@ Displaying
Flags, Options and Tables
-----------------------------
-|Coq| configurability is based on flags (e.g. :opt:`Printing All`), options
-(e.g. :opt:`Printing Width`), or tables (e.g. :cmd:`Add Printing Record`). The
-names of flags, options and tables are made of non-empty sequences of
-identifiers (conventionally with capital initial letter). The general commands
-handling flags, options and tables are given below.
-
-.. TODO : flag is not a syntax entry
-
-.. cmd:: Set @flag
-
- This command switches :n:`@flag` on. The original state of :n:`@flag`
- is restored when the current module ends.
-
- .. cmdv:: Local Set @flag
-
- This command switches :n:`@flag` on. The original state
- of :n:`@flag` is restored when the current *section* ends.
-
- .. cmdv:: Global Set @flag
-
- This command switches :n:`@flag` on. The original state
- of :n:`@flag` is *not* restored at the end of the module. Additionally, if
- set in a file, :n:`@flag` is switched on when the file is `Require`-d.
-
- .. cmdv:: Export Set @flag
+Coq has many settings to control its behavior. Setting types include flags, options
+and tables:
- This command switches :n:`@flag` on. The original state
- of :n:`@flag` is restored at the end of the current module, but :n:`@flag`
- is switched on when this module is imported.
+* A :production:`flag` has a boolean value, such as :flag:`Asymmetric Patterns`.
+* An :production:`option` generally has a numeric or string value, such as :opt:`Firstorder Depth`.
+* A :production:`table` contains a set of strings or qualids.
+* In addition, some commands provide settings, such as :cmd:`Extraction Language OCaml`.
+.. FIXME Convert `Extraction Language OCaml` to an option.
-.. cmd:: Unset @flag
+Flags, options and tables are identified by a series of identifiers, each with an initial
+capital letter.
- This command switches :n:`@flag` off. The original state of
- :n:`@flag` is restored when the current module ends.
+.. cmd:: {? Local | Global | Export } Set @flag
+ :name: Set
- .. cmdv:: Local Unset @flag
+ Sets :token:`flag` on. Scoping qualifiers are
+ described :ref:`here <set_unset_scope_qualifiers>`.
- This command switches :n:`@flag` off. The original
- state of :n:`@flag` is restored when the current *section* ends.
-
- .. cmdv:: Global Unset @flag
-
- This command switches :n:`@flag` off. The original
- state of :n:`@flag` is *not* restored at the end of the module. Additionally,
- if set in a file, :n:`@flag` is switched off when the file is `Require`-d.
-
- .. cmdv:: Export Unset @flag
-
- This command switches :n:`@flag` off. The original state
- of :n:`@flag` is restored at the end of the current module, but :n:`@flag`
- is switched off when this module is imported.
+.. cmd:: {? Local | Global | Export } Unset @flag
+ :name: Unset
+ Sets :token:`flag` off. Scoping qualifiers are
+ described :ref:`here <set_unset_scope_qualifiers>`.
.. cmd:: Test @flag
- This command prints whether :n:`@flag` is on or off.
-
-
-.. cmd:: Set @option @value
-
- This command sets :n:`@option` to :n:`@value`. The original value of ` option` is
- restored when the current module ends.
-
- .. TODO : option and value are not syntax entries
-
- .. cmdv:: Local Set @option @value
+ Prints the current value of :token:`flag`.
- This command sets :n:`@option` to :n:`@value`. The
- original value of :n:`@option` is restored at the end of the module.
- .. cmdv:: Global Set @option @value
+.. cmd:: {? Local | Global | Export } Set @option ( @num | @string )
+ :name: Set @option
- This command sets :n:`@option` to :n:`@value`. The
- original value of :n:`@option` is *not* restored at the end of the module.
- Additionally, if set in a file, :n:`@option` is set to value when the file
- is `Require`-d.
+ Sets :token:`option` to the specified value. Scoping qualifiers are
+ described :ref:`here <set_unset_scope_qualifiers>`.
- .. cmdv:: Export Set @option
+.. cmd:: {? Local | Global | Export } Unset @option
+ :name: Unset @option
- This command set :n:`@option` to :n:`@value`. The original state
- of :n:`@option` is restored at the end of the current module, but :n:`@option`
- is set to :n:`@value` when this module is imported.
+ Sets :token:`option` to its default value. Scoping qualifiers are
+ described :ref:`here <set_unset_scope_qualifiers>`.
+.. cmd:: Test @option
-.. cmd:: Unset @option
-
- This command turns off :n:`@option`.
-
- .. cmdv:: Local Unset @option
+ Prints the current value of :token:`option`.
- This command turns off :n:`@option`. The original state of :n:`@option`
- is restored when the current *section* ends.
+.. cmd:: Print Options
- .. cmdv:: Global Unset @option
+ Prints the current value of all flags and options, and the names of all tables.
- This command turns off :n:`@option`. The original state of :n:`@option`
- is *not* restored at the end of the module. Additionally, if unset in a file,
- :n:`@option` is reset to its default value when the file is `Require`-d.
- .. cmdv:: Export Unset @option
+.. cmd:: Add @table ( @string | @qualid )
+ :name: Add @table
- This command turns off :n:`@option`. The original state of :n:`@option`
- is restored at the end of the current module, but :n:`@option` is set to
- its default value when this module is imported.
+ Adds the specified value to :token:`table`.
+.. cmd:: Remove @table ( @string | @qualid )
+ :name: Remove @table
-.. cmd:: Test @option
+ Removes the specified value from :token:`table`.
- This command prints the current value of :n:`@option`.
+.. cmd:: Test @table for ( @string | @qualid )
+ :name: Test @table for
+ Reports whether :token:`table` contains the specified value.
-.. TODO : table is not a syntax entry
-
-.. cmd:: Add @table @value
- :name: Add `table` `value`
+.. cmd:: Print Table @table
+ :name: Print Table @table
-.. cmd:: Remove @table @value
- :name: Remove `table` `value`
+ Prints the values in :token:`table`.
-.. cmd:: Test @table @value
- :name: Test `table` `value`
+.. cmd:: Test @table
-.. cmd:: Test @table for @value
- :name: Test `table` for `value`
+ A synonym for :cmd:`Print Table @table`.
-.. cmd:: Print Table @table
+.. cmd:: Print Tables
-These are general commands for tables.
+ A synonym for :cmd:`Print Options`.
+.. _set_unset_scope_qualifiers:
-.. cmd:: Print Options
+Scope qualifiers for :cmd:`Set` and :cmd:`Unset`
+`````````````````````````````````````````````````
- This command lists all available flags, options and tables.
+:n:`{? Local | Global | Export }`
- .. cmdv:: Print Tables
+Flag and option settings can be global in scope or local to nested scopes created by
+:cmd:`Module` and :cmd:`Section` commands. There are four alternatives:
- This is a synonymous of :cmd:`Print Options`.
+* no qualifier: the original setting is *not* restored at the end of the current module or section.
+* **Local**: the setting is applied within the current scope. The original value of the option
+ or flag is restored at the end of the current module or section.
+* **Global**: similar to no qualifier, the original setting is *not* restored at the end of the current
+ module or section. In addition, if the value is set in a file, then :cmd:`Require`-ing
+ the file sets the option.
+* **Export**: similar to **Local**, the original value of the option or flag is restored at the
+ end of the current module or section. In addition, if the value is set in a file, then :cmd:`Import`-ing
+ the file sets the option.
+Newly opened scopes inherit the current settings.
.. _requests-to-the-environment:
@@ -246,7 +204,7 @@ Requests to the environment
hypothesis introduced in the first subgoal (if a proof is in
progress).
- See also: Section :ref:`performingcomputations`.
+ .. seealso:: Section :ref:`performingcomputations`.
.. cmd:: Compute @term
@@ -255,7 +213,7 @@ Requests to the environment
bytecode-based virtual machine. It is a shortcut for ``Eval vm_compute in``
:n:`@term`.
- See also: Section :ref:`performingcomputations`.
+ .. seealso:: Section :ref:`performingcomputations`.
.. cmd:: Print Assumptions @qualid
@@ -502,26 +460,23 @@ Requests to the environment
.. note::
- .. cmd:: Add Search Blacklist @string
+ .. table:: Search Blacklist @string
- For the ``Search``, ``SearchHead``, ``SearchPattern`` and ``SearchRewrite``
- queries, it is possible to globally filter the search results using this
- command. A lemma whose fully-qualified name
- contains any of the declared strings will be removed from the
- search results. The default blacklisted substrings are ``_subproof`` and
+ Specifies a set of strings used to exclude lemmas from the results of :cmd:`Search`,
+ :cmd:`SearchHead`, :cmd:`SearchPattern` and :cmd:`SearchRewrite` queries. A lemma whose
+ fully-qualified name contains any of the strings will be excluded from the
+ search results. The default blacklisted substrings are ``_subterm``, ``_subproof`` and
``Private_``.
- .. cmd:: Remove Search Blacklist @string
-
- This command allows expunging this blacklist.
-
+ Use the :cmd:`Add @table` and :cmd:`Remove @table` commands to update the set of
+ blacklisted strings.
.. cmd:: Locate @qualid
This command displays the full name of objects whose name is a prefix
of the qualified identifier :n:`@qualid`, and consequently the |Coq| module in
which they are defined. It searches for objects from the different
- qualified name spaces of |Coq|: terms, modules, Ltac, etc.
+ qualified namespaces of |Coq|: terms, modules, Ltac, etc.
.. example::
@@ -549,7 +504,7 @@ Requests to the environment
As Locate but restricted to tactics.
-See also: Section :ref:`locating-notations`
+.. seealso:: Section :ref:`locating-notations`
.. _loading-files:
@@ -587,7 +542,9 @@ toplevel. This kind of file is called a *script* for |Coq|. The standard
Display, while loading,
the answers of |Coq| to each command (including tactics) contained in
- the loaded file See also: Section :ref:`controlling-display`.
+ the loaded file.
+
+ .. seealso:: Section :ref:`controlling-display`.
.. exn:: Can’t find file @ident on loadpath.
@@ -699,10 +656,7 @@ file is a particular case of module called *library file*.
that the commands ``Import`` and ``Export`` alone can be used inside modules
(see Section :ref:`Import <import_qualid>`).
-
-
-See also: Chapter :ref:`thecoqcommands`
-
+ .. seealso:: Chapter :ref:`thecoqcommands`
.. cmd:: Print Libraries
@@ -930,7 +884,7 @@ Quitting and debugging
.. cmd:: Drop
- This is used mostly as a debug facility by |Coq|’s implementors and does
+ This is used mostly as a debug facility by |Coq|’s implementers and does
not concern the casual user. This command permits to leave |Coq|
temporarily and enter the OCaml toplevel. The OCaml
command:
@@ -980,6 +934,7 @@ Quitting and debugging
displayed.
.. opt:: Default Timeout @num
+ :name: Default Timeout
This option controls a default timeout for subsequent commands, as if they
were passed to a :cmd:`Timeout` command. Commands already starting by a
@@ -1004,11 +959,12 @@ Quitting and debugging
Controlling display
-----------------------
-.. opt:: Silent
+.. flag:: Silent
This option controls the normal displaying.
.. opt:: Warnings "{+, {? %( - %| + %) } @ident }"
+ :name: Warnings
This option configures the display of warnings. It is experimental, and
expects, between quotes, a comma-separated list of warning names or
@@ -1018,7 +974,7 @@ Controlling display
interpreted from left to right, so in case of an overlap, the flags on the
right have higher priority, meaning that `A,-A` is equivalent to `-A`.
-.. opt:: Search Output Name Only
+.. flag:: Search Output Name Only
This option restricts the output of search commands to identifier names;
turning it on causes invocations of :cmd:`Search`, :cmd:`SearchHead`,
@@ -1039,7 +995,7 @@ Controlling display
printing. Beyond this depth, display of subterms is replaced by dots. At the
time of writing this documentation, the default value is 50.
-.. opt:: Printing Compact Contexts
+.. flag:: Printing Compact Contexts
This option controls the compact display mode for goals contexts. When on,
the printer tries to reduce the vertical size of goals contexts by putting
@@ -1047,13 +1003,13 @@ Controlling display
does not exceed the printing width (see :opt:`Printing Width`). At the time
of writing this documentation, it is off by default.
-.. opt:: Printing Unfocused
+.. flag:: Printing Unfocused
This option controls whether unfocused goals are displayed. Such goals are
created by focusing other goals with bullets (see :ref:`bullets` or
:ref:`curly braces <curly-braces>`). It is off by default.
-.. opt:: Printing Dependent Evars Line
+.. flag:: Printing Dependent Evars Line
This option controls the printing of the “(dependent evars: …)” line when
``-emacs`` is passed.
@@ -1097,8 +1053,10 @@ described first.
The scope of :cmd:`Opaque` is limited to the current section, or current
file, unless the variant :cmd:`Global Opaque` is used.
- See also: sections :ref:`performingcomputations`, :ref:`tactics-automating`,
- :ref:`proof-editing-mode`
+ .. seealso::
+
+ Sections :ref:`performingcomputations`, :ref:`tactics-automating`,
+ :ref:`proof-editing-mode`
.. exn:: The reference @qualid was not found in the current environment.
@@ -1130,8 +1088,10 @@ described first.
There is no constant referred by :n:`@qualid` in the environment.
- See also: sections :ref:`performingcomputations`,
- :ref:`tactics-automating`, :ref:`proof-editing-mode`
+ .. seealso::
+
+ Sections :ref:`performingcomputations`,
+ :ref:`tactics-automating`, :ref:`proof-editing-mode`
.. _vernac-strategy:
@@ -1195,7 +1155,7 @@ described first.
nothing prevents the user to also perform a
``Ltac`` `ident` ``:=`` `convtactic`.
- See also: sections :ref:`performingcomputations`
+ .. seealso:: :ref:`performingcomputations`
.. _controlling-locality-of-commands:
diff --git a/doc/sphinx/replaces.rst b/doc/sphinx/refman-preamble.rst
index 28a04f90ce..c662028773 100644
--- a/doc/sphinx/replaces.rst
+++ b/doc/sphinx/refman-preamble.rst
@@ -1,4 +1,13 @@
-.. some handy replacements for common items
+.. This file is automatically prepended to all other files using the ``rst_prolog`` option.
+
+.. only:: html
+
+ .. This is included once per page in the HTML build, and a single time (in the
+ document's preamble) in the LaTeX one.
+
+ .. preamble:: /refman-preamble.sty
+
+.. Some handy replacements for common items
.. role:: smallcaps
@@ -21,7 +30,7 @@
.. |class_2| replace:: `class`\ :math:`_{2}`
.. |Coq| replace:: :smallcaps:`Coq`
.. |CoqIDE| replace:: :smallcaps:`CoqIDE`
-.. |eq_beta_delta_iota_zeta| replace:: `=`\ :math:`_{\small{\beta\delta\iota\zeta}}`
+.. |eq_beta_delta_iota_zeta| replace:: `=`\ :math:`_{\beta\delta\iota\zeta}`
.. |Gallina| replace:: :smallcaps:`Gallina`
.. |ident_0| replace:: `ident`\ :math:`_{0}`
.. |ident_1,1| replace:: `ident`\ :math:`_{1,1}`
diff --git a/doc/sphinx/refman-preamble.sty b/doc/sphinx/refman-preamble.sty
new file mode 100644
index 0000000000..b4fc608e47
--- /dev/null
+++ b/doc/sphinx/refman-preamble.sty
@@ -0,0 +1,88 @@
+\newcommand{\alors}{\textsf{then}}
+\newcommand{\alter}{\textsf{alter}}
+\newcommand{\as}{\kw{as}}
+\newcommand{\Assum}[3]{\kw{Assum}(#1)(#2:#3)}
+\newcommand{\bool}{\textsf{bool}}
+\newcommand{\case}{\kw{case}}
+\newcommand{\conc}{\textsf{conc}}
+\newcommand{\cons}{\textsf{cons}}
+\newcommand{\consf}{\textsf{consf}}
+\newcommand{\conshl}{\textsf{cons\_hl}}
+\newcommand{\Def}[4]{\kw{Def}(#1)(#2:=#3:#4)}
+\newcommand{\emptyf}{\textsf{emptyf}}
+\newcommand{\End}{\kw{End}}
+\newcommand{\kwend}{\kw{end}}
+\newcommand{\EqSt}{\textsf{EqSt}}
+\newcommand{\even}{\textsf{even}}
+\newcommand{\evenO}{\textsf{even}_\textsf{O}}
+\newcommand{\evenS}{\textsf{even}_\textsf{S}}
+\newcommand{\false}{\textsf{false}}
+\newcommand{\filter}{\textsf{filter}}
+\newcommand{\Fix}{\kw{Fix}}
+\newcommand{\fix}{\kw{fix}}
+\newcommand{\for}{\textsf{for}}
+\newcommand{\forest}{\textsf{forest}}
+\newcommand{\from}{\textsf{from}}
+\newcommand{\Functor}{\kw{Functor}}
+\newcommand{\haslength}{\textsf{has\_length}}
+\newcommand{\hd}{\textsf{hd}}
+\newcommand{\ident}{\textsf{ident}}
+\newcommand{\In}{\kw{in}}
+\newcommand{\Ind}[4]{\kw{Ind}[#2](#3:=#4)}
+\newcommand{\ind}[3]{\kw{Ind}~[#1]\left(#2\mathrm{~:=~}#3\right)}
+\newcommand{\Indp}[5]{\kw{Ind}_{#5}(#1)[#2](#3:=#4)}
+\newcommand{\Indpstr}[6]{\kw{Ind}_{#5}(#1)[#2](#3:=#4)/{#6}}
+\newcommand{\injective}{\kw{injective}}
+\newcommand{\kw}[1]{\textsf{#1}}
+\newcommand{\lb}{\lambda}
+\newcommand{\length}{\textsf{length}}
+\newcommand{\letin}[3]{\kw{let}~#1:=#2~\kw{in}~#3}
+\newcommand{\List}{\textsf{list}}
+\newcommand{\lra}{\longrightarrow}
+\newcommand{\Match}{\kw{match}}
+\newcommand{\Mod}[3]{{\kw{Mod}}({#1}:{#2}\,\zeroone{:={#3}})}
+\newcommand{\ModA}[2]{{\kw{ModA}}({#1}=={#2})}
+\newcommand{\ModS}[2]{{\kw{Mod}}({#1}:{#2})}
+\newcommand{\ModType}[2]{{\kw{ModType}}({#1}:={#2})}
+\newcommand{\mto}{.\;}
+\newcommand{\Nat}{\mathbb{N}}
+\newcommand{\nat}{\textsf{nat}}
+\newcommand{\Nil}{\textsf{nil}}
+\newcommand{\nilhl}{\textsf{nil\_hl}}
+\newcommand{\nO}{\textsf{O}}
+\newcommand{\node}{\textsf{node}}
+\newcommand{\nS}{\textsf{S}}
+\newcommand{\odd}{\textsf{odd}}
+\newcommand{\oddS}{\textsf{odd}_\textsf{S}}
+\newcommand{\ovl}[1]{\overline{#1}}
+\newcommand{\Pair}{\textsf{pair}}
+\newcommand{\Prod}{\textsf{prod}}
+\newcommand{\Prop}{\textsf{Prop}}
+\newcommand{\return}{\kw{return}}
+\newcommand{\Set}{\textsf{Set}}
+\newcommand{\si}{\textsf{if}}
+\newcommand{\sinon}{\textsf{else}}
+\newcommand{\Sort}{\cal S}
+\newcommand{\Str}{\textsf{Stream}}
+\newcommand{\Struct}{\kw{Struct}}
+\newcommand{\subst}[3]{#1\{#2/#3\}}
+\newcommand{\tl}{\textsf{tl}}
+\newcommand{\tree}{\textsf{tree}}
+\newcommand{\true}{\textsf{true}}
+\newcommand{\Type}{\textsf{Type}}
+\newcommand{\unfold}{\textsf{unfold}}
+\newcommand{\WEV}[3]{\mbox{$#1[] \vdash #2 \lra #3$}}
+\newcommand{\WEVT}[3]{\mbox{$#1[] \vdash #2 \lra$}\\ \mbox{$ #3$}}
+\newcommand{\WF}[2]{{\cal W\!F}(#1)[#2]}
+\newcommand{\WFE}[1]{\WF{E}{#1}}
+\newcommand{\WFT}[2]{#1[] \vdash {\cal W\!F}(#2)}
+\newcommand{\WFTWOLINES}[2]{{\cal W\!F}\begin{array}{l}(#1)\\\mbox{}[{#2}]\end{array}}
+\newcommand{\with}{\kw{with}}
+\newcommand{\WS}[3]{#1[] \vdash #2 <: #3}
+\newcommand{\WSE}[2]{\WS{E}{#1}{#2}}
+\newcommand{\WT}[4]{#1[#2] \vdash #3 : #4}
+\newcommand{\WTE}[3]{\WT{E}{#1}{#2}{#3}}
+\newcommand{\WTEG}[2]{\WTE{\Gamma}{#1}{#2}}
+\newcommand{\WTM}[3]{\WT{#1}{}{#2}{#3}}
+\newcommand{\zeroone}[1]{[{#1}]}
+\newcommand{\zeros}{\textsf{zeros}}
diff --git a/doc/sphinx/user-extensions/proof-schemes.rst b/doc/sphinx/user-extensions/proof-schemes.rst
index ab1edc0b27..eacd7b4676 100644
--- a/doc/sphinx/user-extensions/proof-schemes.rst
+++ b/doc/sphinx/user-extensions/proof-schemes.rst
@@ -12,13 +12,15 @@ The ``Scheme`` command is a high-level tool for generating automatically
(possibly mutual) induction principles for given types and sorts. Its
syntax follows the schema:
-.. cmd:: Scheme @ident := Induction for @ident Sort sort {* with @ident := Induction for @ident Sort sort}
+.. cmd:: Scheme @ident__1 := Induction for @ident__2 Sort sort {* with @ident__i := Induction for @ident__j Sort sort}
-where each `ident'ᵢ` is a different inductive type identifier
-belonging to the same package of mutual inductive definitions. This
-command generates the `identᵢ`s to be mutually recursive
-definitions. Each term `identᵢ` proves a general principle of mutual
-induction for objects in type `identᵢ`.
+ This command is a high-level tool for generating automatically
+ (possibly mutual) induction principles for given types and sorts.
+ Each :n:`@ident__j` is a different inductive type identifier belonging to
+ the same package of mutual inductive definitions.
+ The command generates the :n:`@ident__i`\s to be mutually recursive
+ definitions. Each term :n:`@ident__i` proves a general principle of mutual
+ induction for objects in type :n:`@ident__j`.
.. cmdv:: Scheme @ident := Minimality for @ident Sort sort {* with @ident := Minimality for @ident' Sort sort}
@@ -44,9 +46,9 @@ induction for objects in type `identᵢ`.
.. coqtop:: none
- Axiom A : Set.
- Axiom B : Set.
-
+ Axiom A : Set.
+ Axiom B : Set.
+
.. coqtop:: all
Inductive tree : Set := node : A -> forest -> tree
@@ -79,7 +81,7 @@ induction for objects in type `identᵢ`.
.. coqtop:: all
Inductive odd : nat -> Prop := oddS : forall n:nat, even n -> odd (S n)
- with even : nat -> Prop :=
+ with even : nat -> Prop :=
| evenO : even 0
| evenS : forall n:nat, odd n -> even (S n).
@@ -103,26 +105,23 @@ induction for objects in type `identᵢ`.
Automatic declaration of schemes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.. opt:: Elimination Schemes
+.. flag:: Elimination Schemes
- It is possible to deactivate the automatic declaration of the
- induction principles when defining a new inductive type with the
- ``Unset Elimination Schemes`` command. It may be reactivated at any time with
- ``Set Elimination Schemes``.
+ Enables automatic declaration of induction principles when defining a new
+ inductive type. Defaults to on.
-.. opt:: Nonrecursive Elimination Schemes
+.. flag:: Nonrecursive Elimination Schemes
- This option controls whether types declared with the keywords :cmd:`Variant` and
- :cmd:`Record` get an automatic declaration of the induction principles.
+ Enables automatic declaration of induction principles for types declared with the :cmd:`Variant` and
+ :cmd:`Record` commands. Defaults to off.
-.. opt:: Case Analysis Schemes
+.. flag:: Case Analysis Schemes
This flag governs the generation of case analysis lemmas for inductive types,
- i.e. corresponding to the pattern-matching term alone and without fixpoint.
-
-.. opt:: Boolean Equality Schemes
+ i.e. corresponding to the pattern matching term alone and without fixpoint.
-.. opt:: Decidable Equality Schemes
+.. flag:: Boolean Equality Schemes
+ Decidable Equality Schemes
These flags control the automatic declaration of those Boolean equalities (see
the second variant of ``Scheme``).
@@ -132,26 +131,27 @@ Automatic declaration of schemes
You have to be careful with this option since Coq may now reject well-defined
inductive types because it cannot compute a Boolean equality for them.
-.. opt:: Rewriting Schemes
+.. flag:: Rewriting Schemes
This flag governs generation of equality-related schemes such as congruence.
Combined Scheme
~~~~~~~~~~~~~~~~~~~~~~
-The ``Combined Scheme`` command is a tool for combining induction
-principles generated by the ``Scheme command``. Its syntax follows the
-schema :
-
-.. cmd:: Combined Scheme @ident from {+, ident}
+.. cmd:: Combined Scheme @ident from {+, @ident__i}
-where each identᵢ after the ``from`` is a different inductive principle that must
-belong to the same package of mutual inductive principle definitions.
-This command generates the leftmost `ident` to be the conjunction of the
-principles: it is built from the common premises of the principles and
-concluded by the conjunction of their conclusions.
+ This command is a tool for combining induction principles generated
+ by the :cmd:`Scheme` command.
+ Each :n:`@ident__i` is a different inductive principle that must belong
+ to the same package of mutual inductive principle definitions.
+ This command generates :n:`@ident` to be the conjunction of the
+ principles: it is built from the common premises of the principles
+ and concluded by the conjunction of their conclusions.
+ In the case where all the inductive principles used are in sort
+ ``Prop``, the propositional conjunction ``and`` is used, otherwise
+ the simple product ``prod`` is used instead.
-.. example::
+.. example::
We can define the induction principles for trees and forests using:
@@ -173,6 +173,23 @@ concluded by the conjunction of their conclusions.
Check tree_forest_mutind.
+.. example::
+
+ We can also combine schemes at sort ``Type``:
+
+ .. coqtop:: all
+
+ Scheme tree_forest_rect := Induction for tree Sort Type
+ with forest_tree_rect := Induction for forest Sort Type.
+
+ .. coqtop:: all
+
+ Combined Scheme tree_forest_mutrect from tree_forest_rect, forest_tree_rect.
+
+ .. coqtop:: all
+
+ Check tree_forest_mutrect.
+
.. _functional-scheme:
Generation of induction principles with ``Functional`` ``Scheme``
@@ -189,7 +206,7 @@ schema:
where each `ident'ᵢ` is a different mutually defined function
name (the names must be in the same order as when they were defined). This
command generates the induction principle for each `identᵢ`, following
-the recursive structure and case analyses of the corresponding function
+the recursive structure and case analyses of the corresponding function
identᵢ’.
.. warning::
@@ -199,7 +216,7 @@ identᵢ’.
:cmd:`Function` generally produces smaller principles that are closer to how
a user would implement them. See :ref:`advanced-recursive-functions` for details.
-.. example::
+.. example::
Induction scheme for div2.
@@ -265,11 +282,11 @@ identᵢ’.
We define trees by the following mutual inductive type:
.. original LaTeX had "Variable" instead of "Axiom", which generates an ugly warning
-
+
.. coqtop:: reset all
Axiom A : Set.
-
+
Inductive tree : Set :=
node : A -> forest -> tree
with forest : Set :=
@@ -316,20 +333,21 @@ identᵢ’.
Check tree_size_ind2.
.. _derive-inversion:
-
+
Generation of inversion principles with ``Derive`` ``Inversion``
-----------------------------------------------------------------
-The syntax of ``Derive`` ``Inversion`` follows the schema:
-
.. cmd:: Derive Inversion @ident with forall (x : T), I t Sort sort
-This command generates an inversion principle for the `inversion … using`
-tactic. Let `I` be an inductive predicate and `x` the variables occurring
-in t. This command generates and stocks the inversion lemma for the
-sort `sort` corresponding to the instance `∀ (x:T), I t` with the name
-`ident` in the global environment. When applied, it is equivalent to
-having inverted the instance with the tactic `inversion`.
+ This command generates an inversion principle for the
+ :tacn:`inversion ... using ...` tactic. Let :g:`I` be an inductive
+ predicate and :g:`x` the variables occurring in t. This command
+ generates and stocks the inversion lemma for the sort :g:`sort`
+ corresponding to the instance :g:`∀ (x:T), I t` with the name
+ :n:`@ident` in the global environment. When applied, it is
+ equivalent to having inverted the instance with the tactic
+ :g:`inversion`.
+
.. cmdv:: Derive Inversion_clear @ident with forall (x:T), I t Sort sort
@@ -350,7 +368,7 @@ having inverted the instance with the tactic `inversion`.
Consider the relation `Le` over natural numbers and the following
parameter ``P``:
-
+
.. coqtop:: all
Inductive Le : nat -> nat -> Set :=
@@ -373,9 +391,9 @@ having inverted the instance with the tactic `inversion`.
.. coqtop:: none
- Goal forall (n m : nat) (H : Le (S n) m), P n m.
+ Goal forall (n m : nat) (H : Le (S n) m), P n m.
intros.
-
+
.. coqtop:: all
Show.
diff --git a/doc/sphinx/user-extensions/syntax-extensions.rst b/doc/sphinx/user-extensions/syntax-extensions.rst
index d92b9a6794..705d67e6c6 100644
--- a/doc/sphinx/user-extensions/syntax-extensions.rst
+++ b/doc/sphinx/user-extensions/syntax-extensions.rst
@@ -1,5 +1,3 @@
-.. include:: ../replaces.rst
-
.. _syntaxextensionsandinterpretationscopes:
Syntax extensions and interpretation scopes
@@ -119,7 +117,7 @@ command understands. Here is how the previous examples refine.
Notation "A /\ B" := (and A B) (at level 80, right associativity).
Notation "A \/ B" := (or A B) (at level 85, right associativity).
-By default, a notation is considered non-associative, but the
+By default, a notation is considered nonassociative, but the
precedence level is mandatory (except for special cases whose level is
canonical). The level is either a number or the phrase ``next level``
whose meaning is obvious.
@@ -139,7 +137,7 @@ instance define prefix notations.
Notation "~ x" := (not x) (at level 75, right associativity).
One can also define notations for incomplete terms, with the hole
-expected to be inferred during typechecking.
+expected to be inferred during type checking.
.. coqtop:: in
@@ -296,7 +294,7 @@ the possible following elements delimited by single quotes:
after the “``[``” is applied at the beginning of each newline
Notations disappear when a section is closed. No typing of the denoted
-expression is performed at definition time. Type-checking is done only
+expression is performed at definition time. Type checking is done only
at the time of use of the notation.
.. note:: Sometimes, a notation is expected only for the parser. To do
@@ -378,17 +376,14 @@ for records. Here are examples:
Displaying information about notations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.. opt:: Printing Notations
-
- To deactivate the printing of all notations, use the command
- ``Unset Printing Notations``. To reactivate it, use the command
- ``Set Printing Notations``.
+.. flag:: Printing Notations
- The default is to use notations for printing terms wherever possible.
+ Controls whether to use notations for printing terms wherever possible.
+ Default is on.
.. seealso::
- :opt:`Printing All`
+ :flag:`Printing All`
To disable other elements in addition to notations.
.. _locating-notations:
@@ -899,7 +894,7 @@ notations are given below. The optional :production:`scope` is described in
: | as strict pattern
.. note:: No typing of the denoted expression is performed at definition
- time. Type-checking is done only at the time of use of the notation.
+ time. Type checking is done only at the time of use of the notation.
.. note:: Some examples of Notation may be found in the files composing
the initial state of Coq (see directory :file:`$COQLIB/theories/Init`).
@@ -949,16 +944,25 @@ Interpretation scopes can include an interpretation for numerals and
strings. However, this is only made possible at the Objective Caml
level.
-See :ref:`above <NotationSyntax>` for the syntax of notations including the
-possibility to declare them in a given scope. Here is a typical example which
-declares the notation for conjunction in the scope ``type_scope``.
+.. cmd:: Declare Scope @scope
+
+ This adds a new scope named :n:`@scope`. Note that the initial
+ state of Coq declares by default the following interpretation scopes:
+ ``core_scope``, ``type_scope``, ``function_scope``, ``nat_scope``,
+ ``bool_scope``, ``list_scope``, ``int_scope``, ``uint_scope``.
+
+The syntax to associate a notation to a scope is given
+:ref:`above <NotationSyntax>`. Here is a typical example which declares the
+notation for conjunction in the scope ``type_scope``.
.. coqtop:: in
Notation "A /\ B" := (and A B) : type_scope.
.. note:: A notation not defined in a scope is called a *lonely*
- notation.
+ notation. No example of lonely notations can be found in the
+ initial state of Coq though.
+
Global interpretation rules for notations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -977,10 +981,6 @@ interpretation: otherwise said, only the order of lonely
interpretations and opening of scopes matters, and not the declaration
of interpretations within a scope).
-The initial state of Coq declares three interpretation scopes and no
-lonely notations. These scopes, in opening order, are ``core_scope``,
-``type_scope`` and ``nat_scope``.
-
.. cmd:: Open Scope @scope
The command to add a scope to the interpretation scope stack is
@@ -1369,9 +1369,157 @@ Abbreviations
Check (id 0).
Abbreviations disappear when a section is closed. No typing of the
- denoted expression is performed at definition time. Type-checking is
+ denoted expression is performed at definition time. Type checking is
done only at the time of use of the abbreviation.
+
+Numeral notations
+-----------------
+
+.. cmd:: Numeral Notation @ident__1 @ident__2 @ident__3 : @scope.
+
+ This command allows the user to customize the way numeral literals
+ are parsed and printed.
+
+ The token :n:`@ident__1` should be the name of an inductive type,
+ while :n:`@ident__2` and :n:`@ident__3` should be the names of the
+ parsing and printing functions, respectively. The parsing function
+ :n:`@ident__2` should have one of the following types:
+
+ * :n:`Decimal.int -> @ident__1`
+ * :n:`Decimal.int -> option @ident__1`
+ * :n:`Decimal.uint -> @ident__1`
+ * :n:`Decimal.uint -> option @ident__1`
+ * :n:`Z -> @ident__1`
+ * :n:`Z -> option @ident__1`
+
+ And the printing function :n:`@ident__3` should have one of the
+ following types:
+
+ * :n:`@ident__1 -> Decimal.int`
+ * :n:`@ident__1 -> option Decimal.int`
+ * :n:`@ident__1 -> Decimal.uint`
+ * :n:`@ident__1 -> option Decimal.uint`
+ * :n:`@ident__1 -> Z`
+ * :n:`@ident__1 -> option Z`
+
+ When parsing, the application of the parsing function
+ :n:`@ident__2` to the number will be fully reduced, and universes
+ of the resulting term will be refreshed.
+
+ .. cmdv:: Numeral Notation @ident__1 @ident__2 @ident__3 : @scope (warning after @num).
+
+ When a literal larger than :token:`num` is parsed, a warning
+ message about possible stack overflow, resulting from evaluating
+ :n:`@ident__2`, will be displayed.
+
+ .. cmdv:: Numeral Notation @ident__1 @ident__2 @ident__3 : @scope (abstract after @num).
+
+ When a literal :g:`m` larger than :token:`num` is parsed, the
+ result will be :n:`(@ident__2 m)`, without reduction of this
+ application to a normal form. Here :g:`m` will be a
+ :g:`Decimal.int` or :g:`Decimal.uint` or :g:`Z`, depending on the
+ type of the parsing function :n:`@ident__2`. This allows for a
+ more compact representation of literals in types such as :g:`nat`,
+ and limits parse failures due to stack overflow. Note that a
+ warning will be emitted when an integer larger than :token:`num`
+ is parsed. Note that :n:`(abstract after @num)` has no effect
+ when :n:`@ident__2` lands in an :g:`option` type.
+
+ .. exn:: Cannot interpret this number as a value of type @type
+
+ The numeral notation registered for :token:`type` does not support
+ the given numeral. This error is given when the interpretation
+ function returns :g:`None`, or if the interpretation is registered
+ for only non-negative integers, and the given numeral is negative.
+
+ .. exn:: @ident should go from Decimal.int to @type or (option @type). Instead of Decimal.int, the types Decimal.uint or Z could be used{? (require BinNums first)}.
+
+ The parsing function given to the :cmd:`Numeral Notation`
+ vernacular is not of the right type.
+
+ .. exn:: @ident should go from @type to Decimal.int or (option Decimal.int). Instead of Decimal.int, the types Decimal.uint or Z could be used{? (require BinNums first)}.
+
+ The printing function given to the :cmd:`Numeral Notation`
+ vernacular is not of the right type.
+
+ .. exn:: @type is not an inductive type.
+
+ Numeral notations can only be declared for inductive types with no
+ arguments.
+
+ .. exn:: Unexpected term @term while parsing a numeral notation.
+
+ Parsing functions must always return ground terms, made up of
+ applications of constructors and inductive types. Parsing
+ functions may not return terms containing axioms, bare
+ (co)fixpoints, lambdas, etc.
+
+ .. exn:: Unexpected non-option term @term while parsing a numeral notation.
+
+ Parsing functions expected to return an :g:`option` must always
+ return a concrete :g:`Some` or :g:`None` when applied to a
+ concrete numeral expressed as a decimal. They may not return
+ opaque constants.
+
+ .. exn:: Cannot interpret in @scope because @ident could not be found in the current environment.
+
+ The inductive type used to register the numeral notation is no
+ longer available in the environment. Most likely, this is because
+ the numeral notation was declared inside a functor for an
+ inductive type inside the functor. This use case is not currently
+ supported.
+
+ Alternatively, you might be trying to use a primitive token
+ notation from a plugin which forgot to specify which module you
+ must :g:`Require` for access to that notation.
+
+ .. exn:: Syntax error: [prim:reference] expected after 'Notation' (in [vernac:command]).
+
+ The type passed to :cmd:`Numeral Notation` must be a single
+ identifier.
+
+ .. exn:: Syntax error: [prim:reference] expected after [prim:reference] (in [vernac:command]).
+
+ Both functions passed to :cmd:`Numeral Notation` must be single
+ identifiers.
+
+ .. exn:: The reference @ident was not found in the current environment.
+
+ Identifiers passed to :cmd:`Numeral Notation` must exist in the
+ global environment.
+
+ .. exn:: @ident is bound to a notation that does not denote a reference.
+
+ Identifiers passed to :cmd:`Numeral Notation` must be global
+ references, or notations which denote to single identifiers.
+
+ .. warn:: Stack overflow or segmentation fault happens when working with large numbers in @type (threshold may vary depending on your system limits and on the command executed).
+
+ When a :cmd:`Numeral Notation` is registered in the current scope
+ with :n:`(warning after @num)`, this warning is emitted when
+ parsing a numeral greater than or equal to :token:`num`.
+
+ .. warn:: To avoid stack overflow, large numbers in @type are interpreted as applications of @ident__2.
+
+ When a :cmd:`Numeral Notation` is registered in the current scope
+ with :n:`(abstract after @num)`, this warning is emitted when
+ parsing a numeral greater than or equal to :token:`num`.
+ Typically, this indicates that the fully computed representation
+ of numerals can be so large that non-tail-recursive OCaml
+ functions run out of stack space when trying to walk them.
+
+ For example
+
+ .. coqtop:: all
+
+ Check 90000.
+
+ .. warn:: The 'abstract after' directive has no effect when the parsing function (@ident__2) targets an option type.
+
+ As noted above, the :n:`(abstract after @num)` directive has no
+ effect when :n:`@ident__2` lands in an :g:`option` type.
+
.. _TacticNotation:
Tactic Notations
@@ -1431,7 +1579,7 @@ Tactic notations allow to customize the syntax of tactics. They have the followi
* - ``hyp``
- identifier
- - an hypothesis defined in context
+ - a hypothesis defined in context
- clear
* - ``reference``
@@ -1503,7 +1651,7 @@ Tactic notations allow to customize the syntax of tactics. They have the followi
.. [#and_or_levels] which are the levels effectively chosen in the current
implementation of Coq
-.. [#no_associativity] Coq accepts notations declared as non-associative but the parser on
+.. [#no_associativity] Coq accepts notations declared as nonassociative but the parser on
which Coq is built, namely Camlp5, currently does not implement ``no associativity`` and
replaces it with ``left associativity``; hence it is the same for Coq: ``no associativity``
is in fact ``left associativity`` for the purposes of parsing
diff --git a/doc/sphinx/zebibliography.html.rst b/doc/sphinx/zebibliography.html.rst
new file mode 100644
index 0000000000..756edd5482
--- /dev/null
+++ b/doc/sphinx/zebibliography.html.rst
@@ -0,0 +1,17 @@
+.. There are multiple issues with sphinxcontrib-bibtex that we have to work around:
+ - The list of cited entries is computed right after encountering
+ `.. bibliography`, so the file containing that command has to come last
+ alphabetically:
+ https://sphinxcontrib-bibtex.readthedocs.io/en/latest/usage.html#unresolved-citations-across-documents
+ - `.. bibliography::` puts the bibliography on its own page with its own
+ title in LaTeX, but includes it inline without a title in HTML:
+ https://sphinxcontrib-bibtex.readthedocs.io/en/latest/usage.html#mismatch-between-output-of-html-and-latex-backends
+
+.. _bibliography:
+
+==============
+ Bibliography
+==============
+
+.. bibliography:: biblio.bib
+ :cited:
diff --git a/doc/sphinx/zebibliography.rst b/doc/sphinx/zebibliography.latex.rst
index 0000caa301..2c0396f1c9 100644
--- a/doc/sphinx/zebibliography.rst
+++ b/doc/sphinx/zebibliography.latex.rst
@@ -1,8 +1,6 @@
-.. _bibliography:
+.. See zebibliography.html.rst for details
-============
-Bibliography
-============
+.. _bibliography:
.. bibliography:: biblio.bib
:cited:
diff --git a/doc/stdlib/index-list.html.template b/doc/stdlib/index-list.html.template
index f448248468..0fa42cadad 100644
--- a/doc/stdlib/index-list.html.template
+++ b/doc/stdlib/index-list.html.template
@@ -226,6 +226,7 @@ through the <tt>Require Import</tt> command.</p>
theories/Numbers/BinNums.v
theories/Numbers/NumPrelude.v
theories/Numbers/NaryFunctions.v
+ theories/Numbers/AltBinNotations.v
theories/Numbers/DecimalFacts.v
theories/Numbers/DecimalNat.v
theories/Numbers/DecimalPos.v
diff --git a/doc/tools/coqrst/coqdomain.py b/doc/tools/coqrst/coqdomain.py
index e6b71a8293..2c69dcfe08 100644
--- a/doc/tools/coqrst/coqdomain.py
+++ b/doc/tools/coqrst/coqdomain.py
@@ -34,7 +34,7 @@ from sphinx.util.logging import getLogger
from sphinx.directives import ObjectDescription
from sphinx.domains import Domain, ObjType, Index
from sphinx.domains.std import token_xrefs
-from sphinx.ext.mathbase import MathDirective, displaymath
+from sphinx.ext import mathbase
from . import coqdoc
from .repl import ansicolors
@@ -58,6 +58,15 @@ def make_target(objtype, targetid):
"""Create a target to an object of type objtype and id targetid"""
return "coq:{}.{}".format(objtype, targetid)
+def make_math_node(latex, docname, nowrap):
+ node = mathbase.displaymath()
+ node['latex'] = latex
+ node['label'] = None # Otherwise equations are numbered
+ node['nowrap'] = nowrap
+ node['docname'] = docname
+ node['number'] = None
+ return node
+
class CoqObject(ObjectDescription):
"""A generic Coq object for Sphinx; all Coq objects are subclasses of this.
@@ -101,7 +110,9 @@ class CoqObject(ObjectDescription):
# Explicit object naming
'name': directives.unchanged,
# Silence warnings produced by report_undocumented_coq_objects
- 'undocumented': directives.flag
+ 'undocumented': directives.flag,
+ # noindex omits this object from its index
+ 'noindex': directives.flag
}
def subdomain_data(self):
@@ -123,7 +134,20 @@ class CoqObject(ObjectDescription):
"""
self._render_annotation(signode)
self._render_signature(signature, signode)
- return self._names.get(signature) or self._name_from_signature(signature)
+ name = self._names.get(signature)
+ if name is None:
+ name = self._name_from_signature(signature)
+ # remove trailing ‘.’ found in commands, but not ‘...’ (ellipsis)
+ if name is not None and name.endswith(".") and not name.endswith("..."):
+ name = name[:-1]
+ return name
+
+ def _warn_if_duplicate_name(self, objects, name):
+ """Check that two objects in the same domain don't have the same name."""
+ if name in objects:
+ MSG = 'Duplicate object: {}; other is at {}'
+ msg = MSG.format(name, self.env.doc2path(objects[name][0]))
+ self.state_machine.reporter.warning(msg, line=self.lineno)
def _warn_if_duplicate_name(self, objects, name):
"""Check that two objects in the same domain don't have the same name."""
@@ -157,18 +181,20 @@ class CoqObject(ObjectDescription):
def _add_index_entry(self, name, target):
"""Add `name` (pointing to `target`) to the main index."""
- index_text = name
- if self.index_suffix:
- index_text += " " + self.index_suffix
- self.indexnode['entries'].append(('single', index_text, target, '', None))
+ assert isinstance(name, str)
+ if not name.startswith("_"):
+ # remove trailing . , found in commands, but not ... (ellipsis)
+ trim = name.endswith(".") and not name.endswith("...")
+ index_text = name[:-1] if trim else name
+ if self.index_suffix:
+ index_text += " " + self.index_suffix
+ self.indexnode['entries'].append(('single', index_text, target, '', None))
def add_target_and_index(self, name, _, signode):
- """Attach a link target to `signode` and an index entry for `name`."""
+ """Attach a link target to `signode` and an index entry for `name`.
+ This is only called (from ``ObjectDescription.run``) if ``:noindex:`` isn't specified."""
if name:
target = self._add_target(signode, name)
- # remove trailing . , found in commands, but not ... (ellipsis)
- if name[-1] == "." and not name[-3:] == "..." :
- name = name[0:-1]
self._add_index_entry(name, target)
return target
@@ -307,15 +333,15 @@ class TacticNotationVariantObject(TacticNotationObject):
annotation = "Variant"
class OptionObject(NotationObject):
- """A Coq option.
+ """A Coq option (a setting with non-boolean value, e.g. a string or numeric value).
Example::
- .. opt:: Nonrecursive Elimination Schemes
+ .. opt:: Hyps Limit @num
+ :name Hyps Limit
- This option controls whether types declared with the keywords
- :cmd:`Variant` and :cmd:`Record` get an automatic declaration of the
- induction principles.
+ Controls the maximum number of hypotheses displayed in goals after
+ application of a tactic.
"""
subdomain = "opt"
index_suffix = "(opt)"
@@ -324,6 +350,43 @@ class OptionObject(NotationObject):
def _name_from_signature(self, signature):
return stringify_with_ellipses(signature)
+
+class FlagObject(NotationObject):
+ """A Coq flag (i.e. a boolean setting).
+
+ Example::
+
+ .. flag:: Nonrecursive Elimination Schemes
+
+ Controls whether types declared with the keywords
+ :cmd:`Variant` and :cmd:`Record` get an automatic declaration of
+ induction principles.
+ """
+ subdomain = "flag"
+ index_suffix = "(flag)"
+ annotation = "Flag"
+
+ def _name_from_signature(self, signature):
+ return stringify_with_ellipses(signature)
+
+
+class TableObject(NotationObject):
+ """A Coq table, i.e. a setting that is a set of values.
+
+ Example::
+
+ .. table:: Search Blacklist @string
+ :name: Search Blacklist
+
+ Controls ...
+ """
+ subdomain = "table"
+ index_suffix = "(table)"
+ annotation = "Table"
+
+ def _name_from_signature(self, signature):
+ return stringify_with_ellipses(signature)
+
class ProductionObject(CoqObject):
r"""A grammar production.
@@ -449,7 +512,7 @@ def NotationRole(role, rawtext, text, lineno, inliner, options={}, content=[]):
it names the introduced hypothesis :token:`ident`.
Note that this example also uses ``:token:``. That's because ``ident`` is
- defined in the the Coq manual as a grammar production, and ``:token:``
+ defined in the Coq manual as a grammar production, and ``:token:``
creates a link to that. When referring to a placeholder that happens to be
a grammar production, ``:token:`…``` is typically preferable to ``:n:`@…```.
"""
@@ -482,7 +545,7 @@ def coq_code_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
CoqCodeRole = coq_code_role
class CoqtopDirective(Directive):
- """A reST directive to describe interactions with Coqtop.
+ r"""A reST directive to describe interactions with Coqtop.
Usage::
@@ -497,6 +560,9 @@ class CoqtopDirective(Directive):
Print nat.
Definition a := 1.
+ The blank line after the directive is required. If you begin a proof,
+ include an ``Abort`` afterwards to reset coqtop for the next example.
+
Here is a list of permissible options:
- Display options
@@ -520,16 +586,17 @@ class CoqtopDirective(Directive):
required_arguments = 0
optional_arguments = 1
final_argument_whitespace = True
+ option_spec = { 'name': directives.unchanged }
directive_name = "coqtop"
def run(self):
# Uses a ‘container’ instead of a ‘literal_block’ to disable
# Pygments-based post-processing (we could also set rawsource to '')
content = '\n'.join(self.content)
- options = self.arguments[0].split() if self.arguments else ['in']
- if 'all' in options:
- options.extend(['in', 'out'])
- node = nodes.container(content, coqtop_options = list(set(options)),
+ args = self.arguments[0].split() if self.arguments else ['in']
+ if 'all' in args:
+ args.extend(['in', 'out'])
+ node = nodes.container(content, coqtop_options = list(set(args)),
classes=['coqtop', 'literal-block'])
self.add_name(node)
return [node]
@@ -554,6 +621,7 @@ class CoqdocDirective(Directive):
required_arguments = 0
optional_arguments = 0
final_argument_whitespace = True
+ option_spec = { 'name': directives.unchanged }
directive_name = "coqdoc"
def run(self):
@@ -562,6 +630,7 @@ class CoqdocDirective(Directive):
content = '\n'.join(self.content)
node = nodes.inline(content, '', *highlight_using_coqdoc(content))
wrapper = nodes.container(content, node, classes=['coqdoc', 'literal-block'])
+ self.add_name(wrapper)
return [wrapper]
class ExampleDirective(BaseAdmonition):
@@ -597,24 +666,41 @@ class ExampleDirective(BaseAdmonition):
self.options['classes'] = ['admonition', 'note']
return super().run()
-class PreambleDirective(MathDirective):
- r"""A reST directive for hidden math.
+class PreambleDirective(Directive):
+ r"""A reST directive to include a TeX file.
- Mostly useful to let MathJax know about `\def`\ s and `\newcommand`\ s.
+ Mostly useful to let MathJax know about `\def`s and `\newcommand`s. The
+ contents of the TeX file are wrapped in a math environment, as MathJax
+ doesn't process LaTeX definitions otherwise.
- Example::
-
- .. preamble::
+ Usage::
- \newcommand{\paren}[#1]{\left(#1\right)}
+ .. preamble:: preamble.tex
"""
-
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {}
directive_name = "preamble"
def run(self):
- self.options['nowrap'] = True
- [node] = super().run()
+ document = self.state.document
+ env = document.settings.env
+
+ if not document.settings.file_insertion_enabled:
+ msg = 'File insertion disabled'
+ return [document.reporter.warning(msg, line=self.lineno)]
+
+ rel_fname, abs_fname = env.relfn2path(self.arguments[0])
+ env.note_dependency(rel_fname)
+
+ with open(abs_fname, encoding="utf-8") as ltx:
+ latex = ltx.read()
+
+ node = make_math_node(latex, env.docname, nowrap=False)
node['classes'] = ["math-preamble"]
+ set_source_info(self, node)
return [node]
class InferenceDirective(Directive):
@@ -627,8 +713,8 @@ class InferenceDirective(Directive):
.. inference:: name
- newline-separated premisses
- ------------------------
+ newline-separated premises
+ --------------------------
conclusion
Example::
@@ -647,15 +733,6 @@ class InferenceDirective(Directive):
final_argument_whitespace = True
directive_name = "inference"
- def make_math_node(self, latex):
- node = displaymath()
- node['latex'] = latex
- node['label'] = None # Otherwise equations are numbered
- node['nowrap'] = False
- node['docname'] = self.state.document.settings.env.docname
- node['number'] = None
- return node
-
@staticmethod
def prepare_latex_operand(op):
# TODO: Could use a fancier inference class in LaTeX
@@ -675,7 +752,8 @@ class InferenceDirective(Directive):
title = self.arguments[0]
content = '\n'.join(self.content)
latex = self.prepare_latex(content)
- math_node = self.make_math_node(latex)
+ docname = self.state.document.settings.env.docname
+ math_node = make_math_node(latex, docname, nowrap=False)
tid = nodes.make_id(title)
target = nodes.target('', '', ids=['inference-' + tid])
@@ -822,23 +900,28 @@ class CoqtopBlocksTransform(Transform):
kept_node['classes'] = [c for c in kept_node['classes']
if c != 'coqtop-hidden']
- def merge_consecutive_coqtop_blocks(self):
+ @staticmethod
+ def merge_consecutive_coqtop_blocks(app, doctree, _):
"""Merge consecutive divs wrapping lists of Coq sentences; keep ‘dl’s separate."""
- for node in self.document.traverse(CoqtopBlocksTransform.is_coqtop_block):
+ for node in doctree.traverse(CoqtopBlocksTransform.is_coqtop_block):
if node.parent:
+ rawsources, names = [node.rawsource], set(node['names'])
for sibling in node.traverse(include_self=False, descend=False,
siblings=True, ascend=False):
if CoqtopBlocksTransform.is_coqtop_block(sibling):
- self.merge_coqtop_classes(node, sibling)
+ CoqtopBlocksTransform.merge_coqtop_classes(node, sibling)
+ rawsources.append(sibling.rawsource)
+ names.update(sibling['names'])
node.extend(sibling.children)
node.parent.remove(sibling)
sibling.parent = None
else:
break
+ node.rawsource = "\n\n".join(rawsources)
+ node['names'] = list(names)
def apply(self):
self.add_coqtop_output()
- self.merge_consecutive_coqtop_blocks()
class CoqSubdomainsIndex(Index):
"""Index subclass to provide subdomain-specific indices.
@@ -871,7 +954,7 @@ class CoqTacticIndex(CoqSubdomainsIndex):
name, localname, shortname, subdomains = "tacindex", "Tactic Index", "tactics", ["tacn"]
class CoqOptionIndex(CoqSubdomainsIndex):
- name, localname, shortname, subdomains = "optindex", "Option Index", "options", ["opt"]
+ name, localname, shortname, subdomains = "optindex", "Flags, options and Tables Index", "options", ["flag", "opt", "table"]
class CoqGallinaIndex(CoqSubdomainsIndex):
name, localname, shortname, subdomains = "thmindex", "Gallina Index", "theorems", ["thm"]
@@ -944,6 +1027,8 @@ class CoqDomain(Domain):
'tacn': ObjType('tacn', 'tacn'),
'tacv': ObjType('tacv', 'tacn'),
'opt': ObjType('opt', 'opt'),
+ 'flag': ObjType('flag', 'flag'),
+ 'table': ObjType('table', 'table'),
'thm': ObjType('thm', 'thm'),
'prodn': ObjType('prodn', 'prodn'),
'exn': ObjType('exn', 'exn'),
@@ -960,6 +1045,8 @@ class CoqDomain(Domain):
'tacn': TacticNotationObject,
'tacv': TacticNotationVariantObject,
'opt': OptionObject,
+ 'flag': FlagObject,
+ 'table': TableObject,
'thm': GallinaObject,
'prodn' : ProductionObject,
'exn': ExceptionObject,
@@ -971,6 +1058,8 @@ class CoqDomain(Domain):
'cmd': XRefRole(warn_dangling=True),
'tacn': XRefRole(warn_dangling=True),
'opt': XRefRole(warn_dangling=True),
+ 'flag': XRefRole(warn_dangling=True),
+ 'table': XRefRole(warn_dangling=True),
'thm': XRefRole(warn_dangling=True),
'prodn' : XRefRole(warn_dangling=True),
'exn': XRefRole(warn_dangling=True),
@@ -992,6 +1081,8 @@ class CoqDomain(Domain):
'cmd': {},
'tacn': {},
'opt': {},
+ 'flag': {},
+ 'table': {},
'thm': {},
'prodn' : {},
'exn': {},
@@ -1054,7 +1145,6 @@ def simplify_source_code_blocks_for_latex(app, doctree, fromdocname): # pylint:
pygments if available. This prevents the LaTeX builder from getting
confused.
"""
-
is_html = app.builder.tags.has("html")
for node in doctree.traverse(is_coqtop_or_coqdoc_block):
if is_html:
@@ -1091,6 +1181,7 @@ def setup(app):
app.add_transform(CoqtopBlocksTransform)
app.connect('doctree-resolved', simplify_source_code_blocks_for_latex)
+ app.connect('doctree-resolved', CoqtopBlocksTransform.merge_consecutive_coqtop_blocks)
# Add extra styles
app.add_stylesheet("fonts.css")
@@ -1103,4 +1194,11 @@ def setup(app):
# Tell Sphinx about extra settings
app.add_config_value("report_undocumented_coq_objects", None, 'env')
- return {'version': '0.1', "parallel_read_safe": True}
+ # ``env_version`` is used by Sphinx to know when to invalidate
+ # coqdomain-specific bits in its caches. It should be incremented when the
+ # contents of ``env.domaindata['coq']`` change. See
+ # `https://github.com/sphinx-doc/sphinx/issues/4460`.
+ meta = { "version": "0.1",
+ "env_version": 2,
+ "parallel_read_safe": True }
+ return meta
diff --git a/dune b/dune
new file mode 100644
index 0000000000..b758fc7b56
--- /dev/null
+++ b/dune
@@ -0,0 +1,11 @@
+(rule
+ (targets .vfiles.d)
+ (deps
+ (source_tree theories)
+ (source_tree plugins))
+ (action (with-stdout-to .vfiles.d (system "%{bin:coqdep} -dyndep opt -noglob -boot `find theories plugins -type f -name *.v`"))))
+
+(alias
+ (name vodeps)
+ (deps tools/coq_dune.exe .vfiles.d))
+ ; (action (run coq_dune .vfiles.d))))
diff --git a/dune-project b/dune-project
new file mode 100644
index 0000000000..607e5a68a5
--- /dev/null
+++ b/dune-project
@@ -0,0 +1,3 @@
+(lang dune 1.2)
+
+(name coq)
diff --git a/dune-workspace b/dune-workspace
new file mode 100644
index 0000000000..38875eac2c
--- /dev/null
+++ b/dune-workspace
@@ -0,0 +1,6 @@
+(lang dune 1.2)
+
+; Add custom flags here. Default developer profile is `dev`
+(env
+ (dev (flags :standard -rectypes -w -9-27-50+60))
+ (release (flags :standard -rectypes)))
diff --git a/engine/dune b/engine/dune
new file mode 100644
index 0000000000..e2b7ab9c87
--- /dev/null
+++ b/engine/dune
@@ -0,0 +1,6 @@
+(library
+ (name engine)
+ (synopsis "Coq's Tactic Engine")
+ (public_name coq.engine)
+ (wrapped false)
+ (libraries library))
diff --git a/engine/eConstr.ml b/engine/eConstr.ml
index 3dc1933a14..8ab3ce821e 100644
--- a/engine/eConstr.ml
+++ b/engine/eConstr.ml
@@ -14,7 +14,23 @@ open Names
open Constr
open Context
-include Evd.MiniEConstr
+module ESorts = struct
+ include Evd.MiniEConstr.ESorts
+
+ let equal sigma s1 s2 =
+ Sorts.equal (kind sigma s1) (kind sigma s2)
+end
+
+module EInstance = struct
+ include Evd.MiniEConstr.EInstance
+
+ let equal sigma i1 i2 =
+ Univ.Instance.equal (kind sigma i1) (kind sigma i2)
+end
+
+include (Evd.MiniEConstr : module type of Evd.MiniEConstr
+ with module ESorts := ESorts
+ and module EInstance := EInstance)
type types = t
type constr = t
@@ -259,7 +275,17 @@ let decompose_prod_n_assum sigma n c =
let existential_type = Evd.existential_type
-let map sigma f c = match kind sigma c with
+let map_under_context f n c =
+ let f c = unsafe_to_constr (f (of_constr c)) in
+ of_constr (Constr.map_under_context f n (unsafe_to_constr c))
+let map_branches f ci br =
+ let f c = unsafe_to_constr (f (of_constr c)) in
+ of_constr_array (Constr.map_branches f ci (unsafe_to_constr_array br))
+let map_return_predicate f ci p =
+ let f c = unsafe_to_constr (f (of_constr c)) in
+ of_constr (Constr.map_return_predicate f ci (unsafe_to_constr p))
+
+let map_gen userview sigma f c = match kind sigma c with
| (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
| Construct _) -> c
| Cast (b,k,t) ->
@@ -296,6 +322,12 @@ let map sigma f c = match kind sigma c with
let l' = Array.Smart.map f l in
if l'==l then c
else mkEvar (e, l')
+ | Case (ci,p,b,bl) when userview ->
+ let b' = f b in
+ let p' = map_return_predicate f ci p in
+ let bl' = map_branches f ci bl in
+ if b'==b && p'==p && bl'==bl then c
+ else mkCase (ci, p', b', bl')
| Case (ci,p,b,bl) ->
let b' = f b in
let p' = f p in
@@ -313,6 +345,9 @@ let map sigma f c = match kind sigma c with
if tl'==tl && bl'==bl then c
else mkCoFix (ln,(lna,tl',bl'))
+let map_user_view = map_gen true
+let map = map_gen false
+
let map_with_binders sigma g f l c0 = match kind sigma c0 with
| (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
| Construct _) -> c0
@@ -427,23 +462,27 @@ let compare_gen k eq_inst eq_sort eq_constr nargs c1 c2 =
(c1 == c2) || Constr.compare_head_gen_with k k eq_inst eq_sort eq_constr nargs c1 c2
let eq_constr sigma c1 c2 =
- let kind c = kind_upto sigma c in
+ let kind c = kind sigma c in
+ let eq_inst _ _ i1 i2 = EInstance.equal sigma i1 i2 in
+ let eq_sorts s1 s2 = ESorts.equal sigma s1 s2 in
let rec eq_constr nargs c1 c2 =
- compare_gen kind (fun _ _ -> Univ.Instance.equal) Sorts.equal eq_constr nargs c1 c2
+ compare_gen kind eq_inst eq_sorts eq_constr nargs c1 c2
in
- eq_constr 0 (unsafe_to_constr c1) (unsafe_to_constr c2)
+ eq_constr 0 c1 c2
let eq_constr_nounivs sigma c1 c2 =
- let kind c = kind_upto sigma c in
+ let kind c = kind sigma c in
let rec eq_constr nargs c1 c2 =
compare_gen kind (fun _ _ _ _ -> true) (fun _ _ -> true) eq_constr nargs c1 c2
in
- eq_constr 0 (unsafe_to_constr c1) (unsafe_to_constr c2)
+ eq_constr 0 c1 c2
let compare_constr sigma cmp c1 c2 =
- let kind c = kind_upto sigma c in
- let cmp nargs c1 c2 = cmp (of_constr c1) (of_constr c2) in
- compare_gen kind (fun _ _ -> Univ.Instance.equal) Sorts.equal cmp 0 (unsafe_to_constr c1) (unsafe_to_constr c2)
+ let kind c = kind sigma c in
+ let eq_inst _ _ i1 i2 = EInstance.equal sigma i1 i2 in
+ let eq_sorts s1 s2 = ESorts.equal sigma s1 s2 in
+ let cmp nargs c1 c2 = cmp c1 c2 in
+ compare_gen kind eq_inst eq_sorts cmp 0 c1 c2
let compare_cumulative_instances cv_pb nargs_ok variances u u' cstrs =
let open UnivProblem in
@@ -495,10 +534,10 @@ let cmp_constructors (mind, ind, cns as spec) nargs u1 u2 cstrs =
cstrs (Univ.Instance.to_array u1) (Univ.Instance.to_array u2)
let eq_universes env sigma cstrs cv_pb ref nargs l l' =
- if Univ.Instance.is_empty l then (assert (Univ.Instance.is_empty l'); true)
+ if EInstance.is_empty l then (assert (EInstance.is_empty l'); true)
else
- let l = Evd.normalize_universe_instance sigma l
- and l' = Evd.normalize_universe_instance sigma l' in
+ let l = EInstance.kind sigma l
+ and l' = EInstance.kind sigma l' in
let open GlobRef in
let open UnivProblem in
match ref with
@@ -516,7 +555,7 @@ let eq_universes env sigma cstrs cv_pb ref nargs l l' =
let test_constr_universes env sigma leq m n =
let open UnivProblem in
- let kind c = kind_upto sigma c in
+ let kind c = kind sigma c in
if m == n then Some Set.empty
else
let cstrs = ref Set.empty in
@@ -524,16 +563,16 @@ let test_constr_universes env sigma leq m n =
let eq_universes ref nargs l l' = eq_universes env sigma cstrs Reduction.CONV ref nargs l l'
and leq_universes ref nargs l l' = eq_universes env sigma cstrs cv_pb ref nargs l l' in
let eq_sorts s1 s2 =
- let s1 = ESorts.kind sigma (ESorts.make s1) in
- let s2 = ESorts.kind sigma (ESorts.make s2) in
+ let s1 = ESorts.kind sigma s1 in
+ let s2 = ESorts.kind sigma s2 in
if Sorts.equal s1 s2 then true
else (cstrs := Set.add
(UEq (Sorts.univ_of_sort s1,Sorts.univ_of_sort s2)) !cstrs;
true)
in
let leq_sorts s1 s2 =
- let s1 = ESorts.kind sigma (ESorts.make s1) in
- let s2 = ESorts.kind sigma (ESorts.make s2) in
+ let s1 = ESorts.kind sigma s1 in
+ let s2 = ESorts.kind sigma s2 in
if Sorts.equal s1 s2 then true
else
(cstrs := Set.add
@@ -554,16 +593,16 @@ let test_constr_universes env sigma leq m n =
if res then Some !cstrs else None
let eq_constr_universes env sigma m n =
- test_constr_universes env sigma false (unsafe_to_constr m) (unsafe_to_constr n)
+ test_constr_universes env sigma false m n
let leq_constr_universes env sigma m n =
- test_constr_universes env sigma true (unsafe_to_constr m) (unsafe_to_constr n)
+ test_constr_universes env sigma true m n
let compare_head_gen_proj env sigma equ eqs eqc' nargs m n =
- let kind c = kind_upto sigma c in
- match kind_upto sigma m, kind_upto sigma n with
+ let kind c = kind sigma c in
+ match kind m, kind n with
| Proj (p, c), App (f, args)
| App (f, args), Proj (p, c) ->
- (match kind_upto sigma f with
+ (match kind f with
| Const (p', u) when Constant.equal (Projection.constant p) p' ->
let npars = Projection.npars p in
if Array.length args == npars + 1 then
@@ -579,6 +618,8 @@ let eq_constr_universes_proj env sigma m n =
let cstrs = ref Set.empty in
let eq_universes ref l l' = eq_universes env sigma cstrs Reduction.CONV ref l l' in
let eq_sorts s1 s2 =
+ let s1 = ESorts.kind sigma s1 in
+ let s2 = ESorts.kind sigma s2 in
if Sorts.equal s1 s2 then true
else
(cstrs := Set.add
@@ -588,7 +629,7 @@ let eq_constr_universes_proj env sigma m n =
let rec eq_constr' nargs m n =
m == n || compare_head_gen_proj env sigma eq_universes eq_sorts eq_constr' nargs m n
in
- let res = eq_constr' 0 (unsafe_to_constr m) (unsafe_to_constr n) in
+ let res = eq_constr' 0 m n in
if res then Some !cstrs else None
let universes_of_constr sigma c =
@@ -794,6 +835,7 @@ struct
let to_sorts = ESorts.unsafe_to_sorts
let to_instance = EInstance.unsafe_to_instance
let to_constr = unsafe_to_constr
+let to_constr_array = unsafe_to_constr_array
let to_rel_decl = unsafe_to_rel_decl
let to_named_decl = unsafe_to_named_decl
let to_named_context =
diff --git a/engine/eConstr.mli b/engine/eConstr.mli
index ecb36615f3..f897448557 100644
--- a/engine/eConstr.mli
+++ b/engine/eConstr.mli
@@ -224,7 +224,11 @@ val compare_constr : Evd.evar_map -> (t -> t -> bool) -> t -> t -> bool
(** {6 Iterators} *)
val map : Evd.evar_map -> (t -> t) -> t -> t
+val map_user_view : Evd.evar_map -> (t -> t) -> t -> t
val map_with_binders : Evd.evar_map -> ('a -> 'a) -> ('a -> t -> t) -> 'a -> t -> t
+val map_under_context : (t -> t) -> int -> t -> t
+val map_branches : (t -> t) -> case_info -> t array -> t array
+val map_return_predicate : (t -> t) -> case_info -> t -> t
val iter : Evd.evar_map -> (t -> unit) -> t -> unit
val iter_with_binders : Evd.evar_map -> ('a -> 'a) -> ('a -> t -> unit) -> 'a -> t -> unit
val iter_with_full_binders : Evd.evar_map -> (rel_declaration -> 'a -> 'a) -> ('a -> t -> unit) -> 'a -> t -> unit
@@ -315,6 +319,9 @@ sig
val to_constr : t -> Constr.t
(** Physical identity. Does not care for defined evars. *)
+ val to_constr_array : t array -> Constr.t array
+ (** Physical identity. Does not care for defined evars. *)
+
val to_rel_decl : (t, types) Context.Rel.Declaration.pt -> (Constr.t, Constr.types) Context.Rel.Declaration.pt
(** Physical identity. Does not care for defined evars. *)
diff --git a/engine/evarutil.ml b/engine/evarutil.ml
index b77bf55d8d..b1d880b0ad 100644
--- a/engine/evarutil.ml
+++ b/engine/evarutil.ml
@@ -284,8 +284,8 @@ type csubst = {
csubst_rev : subst_val Id.Map.t;
(** Reverse mapping of the substitution *)
}
-(** This type represent a name substitution for the named and De Bruijn parts of
- a environment. For efficiency we also store the reverse substitution.
+(** This type represents a name substitution for the named and De Bruijn parts of
+ an environment. For efficiency we also store the reverse substitution.
Invariant: all identifiers in the codomain of [csubst_var] and [csubst_rel]
must be pairwise distinct. *)
diff --git a/engine/evd.ml b/engine/evd.ml
index d1c7fef738..d7b03a84f1 100644
--- a/engine/evd.ml
+++ b/engine/evd.ml
@@ -774,7 +774,7 @@ let universe_subst evd =
UState.subst evd.universes
let merge_context_set ?loc ?(sideff=false) rigid evd ctx' =
- {evd with universes = UState.merge ?loc sideff rigid evd.universes ctx'}
+ {evd with universes = UState.merge ?loc ~sideff ~extend:true rigid evd.universes ctx'}
let merge_universe_subst evd subst =
{evd with universes = UState.merge_subst evd.universes subst }
@@ -1267,7 +1267,9 @@ module MiniEConstr = struct
let kind_of_type sigma c = Term.kind_of_type (whd_evar sigma c)
let of_kind = Constr.of_kind
let of_constr c = c
+ let of_constr_array v = v
let unsafe_to_constr c = c
+ let unsafe_to_constr_array v = v
let unsafe_eq = Refl
let to_constr ?(abort_on_undefined_evars=true) sigma c =
diff --git a/engine/evd.mli b/engine/evd.mli
index db2bd4eedf..1a5614988d 100644
--- a/engine/evd.mli
+++ b/engine/evd.mli
@@ -657,10 +657,12 @@ module MiniEConstr : sig
val of_kind : (t, t, ESorts.t, EInstance.t) Constr.kind_of_term -> t
val of_constr : Constr.t -> t
+ val of_constr_array : Constr.t array -> t array
val to_constr : ?abort_on_undefined_evars:bool -> evar_map -> t -> Constr.t
val unsafe_to_constr : t -> Constr.t
+ val unsafe_to_constr_array : t array -> Constr.t array
val unsafe_eq : (t, Constr.t) eq
diff --git a/engine/ftactic.ml b/engine/ftactic.ml
index e23a03c0c7..b371884ba4 100644
--- a/engine/ftactic.ml
+++ b/engine/ftactic.ml
@@ -61,7 +61,7 @@ let nf_enter f =
(fun gl ->
gl >>= fun gl ->
Proofview.Goal.normalize gl >>= fun nfgl ->
- Proofview.V82.wrap_exceptions (fun () -> f nfgl))
+ Proofview.V82.wrap_exceptions (fun () -> f nfgl)) [@warning "-3"]
let enter f =
bind goals
diff --git a/engine/ftactic.mli b/engine/ftactic.mli
index 6c389b2d67..3c4fa6f4e8 100644
--- a/engine/ftactic.mli
+++ b/engine/ftactic.mli
@@ -42,6 +42,8 @@ val run : 'a t -> ('a -> unit Proofview.tactic) -> unit Proofview.tactic
(** {5 Focussing} *)
val nf_enter : (Proofview.Goal.t -> 'a t) -> 'a t
+[@@ocaml.deprecated "Normalization is enforced by EConstr, please use [enter]"]
+
(** Enter a goal. The resulting tactic is focussed. *)
val enter : (Proofview.Goal.t -> 'a t) -> 'a t
diff --git a/engine/namegen.ml b/engine/namegen.ml
index 978f33b683..2a59b914db 100644
--- a/engine/namegen.ml
+++ b/engine/namegen.ml
@@ -258,15 +258,15 @@ let restart_subscript id =
forget_subscript id
let visible_ids sigma (nenv, c) =
- let accu = ref (Refset_env.empty, Int.Set.empty, Id.Set.empty) in
+ let accu = ref (GlobRef.Set_env.empty, Int.Set.empty, Id.Set.empty) in
let rec visible_ids n c = match EConstr.kind sigma c with
| Const _ | Ind _ | Construct _ | Var _ as c ->
let (gseen, vseen, ids) = !accu in
let g = global_of_constr c in
- if not (Refset_env.mem g gseen) then
+ if not (GlobRef.Set_env.mem g gseen) then
begin
try
- let gseen = Refset_env.add g gseen in
+ let gseen = GlobRef.Set_env.add g gseen in
let short = shortest_qualid_of_global Id.Set.empty g in
let dir, id = repr_qualid short in
let ids = if DirPath.is_empty dir then Id.Set.add id ids else ids in
diff --git a/engine/proofview.mli b/engine/proofview.mli
index 970bf67732..0bb3229a9b 100644
--- a/engine/proofview.mli
+++ b/engine/proofview.mli
@@ -497,6 +497,7 @@ module Goal : sig
(** Normalises the argument goal. *)
val normalize : t -> t tactic
+ [@@ocaml.deprecated "Normalization is enforced by EConstr, [normalize] is not needed anymore"]
(** [concl], [hyps], [env] and [sigma] given a goal [gl] return
respectively the conclusion of [gl], the hypotheses of [gl], the
@@ -514,6 +515,7 @@ module Goal : sig
the current goal is also given as an argument to [t]. The goal
is normalised with respect to evars. *)
val nf_enter : (t -> unit tactic) -> unit tactic
+ [@@ocaml.deprecated "Normalization is enforced by EConstr, please use [enter]"]
(** Like {!nf_enter}, but does not normalize the goal beforehand. *)
val enter : (t -> unit tactic) -> unit tactic
@@ -532,7 +534,7 @@ module Goal : sig
(** Compatibility: avoid if possible *)
val goal : t -> Evar.t
- val print : t -> Goal.goal Evd.sigma
+ val print : t -> Evar.t Evd.sigma
end
diff --git a/engine/termops.ml b/engine/termops.ml
index e4c8ae66bc..efe1525c9a 100644
--- a/engine/termops.ml
+++ b/engine/termops.ml
@@ -22,6 +22,8 @@ module RelDecl = Context.Rel.Declaration
module NamedDecl = Context.Named.Declaration
module CompactedDecl = Context.Compacted.Declaration
+module Internal = struct
+
(* Sorts and sort family *)
let print_sort = function
@@ -49,6 +51,8 @@ let pr_puniverses p u =
if Univ.Instance.is_empty u then p
else p ++ str"(*" ++ Univ.Instance.pr UnivNames.pr_with_global_universes u ++ str"*)"
+(* Minimalistic constr printer, typically for debugging *)
+
let rec pr_constr c = match kind c with
| Rel n -> str "#"++int n
| Meta n -> str "Meta(" ++ int n ++ str ")"
@@ -96,12 +100,16 @@ let rec pr_constr c = match kind c with
cut() ++ str":=" ++ pr_constr bd) (Array.to_list fixl)) ++
str"}")
-let term_printer = ref (fun _env _sigma c -> pr_constr (EConstr.Unsafe.to_constr c))
+let debug_print_constr c = pr_constr EConstr.Unsafe.(to_constr c)
+let debug_print_constr_env env sigma c = pr_constr EConstr.(to_constr sigma c)
+let term_printer = ref debug_print_constr_env
+
let print_constr_env env sigma t = !term_printer env sigma t
let print_constr t =
let env = Global.env () in
let evd = Evd.from_env env in
!term_printer env evd t
+
let set_print_constr f = term_printer := f
module EvMap = Evar.Map
@@ -715,10 +723,26 @@ let map_constr_with_binders_left_to_right sigma g f l c =
then c
else mkCoFix (ln,(lna,tl',bl'))
+let map_under_context_with_full_binders sigma g f l n d =
+ let open EConstr in
+ let f l c = Unsafe.to_constr (f l (of_constr c)) in
+ let g d l = g (of_rel_decl d) l in
+ let d = EConstr.Unsafe.to_constr (EConstr.whd_evar sigma d) in
+ EConstr.of_constr (Constr.map_under_context_with_full_binders g f l n d)
+
+let map_branches_with_full_binders sigma g f l ci bl =
+ let tags = Array.map List.length ci.ci_pp_info.cstr_tags in
+ let bl' = Array.map2 (map_under_context_with_full_binders sigma g f l) tags bl in
+ if Array.for_all2 (==) bl' bl then bl else bl'
+
+let map_return_predicate_with_full_binders sigma g f l ci p =
+ let n = List.length ci.ci_pp_info.ind_tags in
+ let p' = map_under_context_with_full_binders sigma g f l n p in
+ if p' == p then p else p'
+
(* strong *)
-let map_constr_with_full_binders sigma g f l cstr =
+let map_constr_with_full_binders_gen userview sigma g f l cstr =
let open EConstr in
- let open RelDecl in
match EConstr.kind sigma cstr with
| (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
| Construct _) -> cstr
@@ -728,16 +752,16 @@ let map_constr_with_full_binders sigma g f l cstr =
if c==c' && t==t' then cstr else mkCast (c', k, t')
| Prod (na,t,c) ->
let t' = f l t in
- let c' = f (g (LocalAssum (na, t)) l) c in
+ let c' = f (g (RelDecl.LocalAssum (na, t)) l) c in
if t==t' && c==c' then cstr else mkProd (na, t', c')
| Lambda (na,t,c) ->
let t' = f l t in
- let c' = f (g (LocalAssum (na, t)) l) c in
+ let c' = f (g (RelDecl.LocalAssum (na, t)) l) c in
if t==t' && c==c' then cstr else mkLambda (na, t', c')
| LetIn (na,b,t,c) ->
let b' = f l b in
let t' = f l t in
- let c' = f (g (LocalDef (na, b, t)) l) c in
+ let c' = f (g (RelDecl.LocalDef (na, b, t)) l) c in
if b==b' && t==t' && c==c' then cstr else mkLetIn (na, b', t', c')
| App (c,al) ->
let c' = f l c in
@@ -749,6 +773,12 @@ let map_constr_with_full_binders sigma g f l cstr =
| Evar (e,al) ->
let al' = Array.map (f l) al in
if Array.for_all2 (==) al al' then cstr else mkEvar (e, al')
+ | Case (ci,p,c,bl) when userview ->
+ let p' = map_return_predicate_with_full_binders sigma g f l ci p in
+ let c' = f l c in
+ let bl' = map_branches_with_full_binders sigma g f l ci bl in
+ if p==p' && c==c' && bl'==bl then cstr else
+ mkCase (ci, p', c', bl')
| Case (ci,p,c,bl) ->
let p' = f l p in
let c' = f l c in
@@ -758,7 +788,7 @@ let map_constr_with_full_binders sigma g f l cstr =
| Fix (ln,(lna,tl,bl)) ->
let tl' = Array.map (f l) tl in
let l' =
- Array.fold_left2 (fun l na t -> g (LocalAssum (na, t)) l) l lna tl in
+ Array.fold_left2 (fun l na t -> g (RelDecl.LocalAssum (na, t)) l) l lna tl in
let bl' = Array.map (f l') bl in
if Array.for_all2 (==) tl tl' && Array.for_all2 (==) bl bl'
then cstr
@@ -766,12 +796,18 @@ let map_constr_with_full_binders sigma g f l cstr =
| CoFix(ln,(lna,tl,bl)) ->
let tl' = Array.map (f l) tl in
let l' =
- Array.fold_left2 (fun l na t -> g (LocalAssum (na, t)) l) l lna tl in
+ Array.fold_left2 (fun l na t -> g (RelDecl.LocalAssum (na, t)) l) l lna tl in
let bl' = Array.map (f l') bl in
if Array.for_all2 (==) tl tl' && Array.for_all2 (==) bl bl'
then cstr
else mkCoFix (ln,(lna,tl',bl'))
+let map_constr_with_full_binders sigma g f =
+ map_constr_with_full_binders_gen false sigma g f
+
+let map_constr_with_full_binders_user_view sigma g f =
+ map_constr_with_full_binders_gen true sigma g f
+
(* [fold_constr_with_binders g f n acc c] folds [f n] on the immediate
subterms of [c] starting from [acc] and proceeding from left to
right according to the usual representation of the constructions as
@@ -1507,3 +1543,6 @@ let env_rel_context_chop k env =
let ctx1,ctx2 = List.chop k rels in
push_rel_context ctx2 (reset_with_named_context (named_context_val env) env),
ctx1
+end
+
+include Internal
diff --git a/engine/termops.mli b/engine/termops.mli
index 80988989f1..aa0f837938 100644
--- a/engine/termops.mli
+++ b/engine/termops.mli
@@ -63,6 +63,10 @@ val map_constr_with_full_binders :
Evd.evar_map ->
(rel_declaration -> 'a -> 'a) ->
('a -> constr -> constr) -> 'a -> constr -> constr
+val map_constr_with_full_binders_user_view :
+ Evd.evar_map ->
+ (rel_declaration -> 'a -> 'a) ->
+ ('a -> constr -> constr) -> 'a -> constr -> constr
(** [fold_constr_with_binders g f n acc c] folds [f n] on the immediate
subterms of [c] starting from [acc] and proceeding from left to
@@ -307,12 +311,40 @@ val pr_metaset : Metaset.t -> Pp.t
val pr_evar_universe_context : UState.t -> Pp.t
val pr_evd_level : evar_map -> Univ.Level.t -> Pp.t
-(** debug printer: do not use to display terms to the casual user... *)
+module Internal : sig
-val set_print_constr : (env -> Evd.evar_map -> constr -> Pp.t) -> unit
-val print_constr : constr -> Pp.t
+(** NOTE: to print terms you always want to use functions in
+ Printer, not these ones which are for very special cases. *)
+
+(** debug printers: print raw form for terms, both with
+ evar-substitution and without. *)
+val debug_print_constr : constr -> Pp.t
+val debug_print_constr_env : env -> evar_map -> constr -> Pp.t
+
+(** Pretty-printer hook: [print_constr_env env sigma c] will pretty
+ print c if the pretty printing layer has been linked into the Coq
+ binary. *)
val print_constr_env : env -> Evd.evar_map -> constr -> Pp.t
+
+(** [set_print_constr f] sets f to be the pretty printer *)
+val set_print_constr : (env -> Evd.evar_map -> constr -> Pp.t) -> unit
+
+(** Printers for contexts *)
val print_named_context : env -> Pp.t
val pr_rel_decl : env -> Constr.rel_declaration -> Pp.t
val print_rel_context : env -> Pp.t
val print_env : env -> Pp.t
+
+val print_constr : constr -> Pp.t
+[@@deprecated "use print_constr_env"]
+
+end
+
+val print_constr : constr -> Pp.t
+[@@deprecated "use Internal.print_constr_env"]
+
+val print_constr_env : env -> Evd.evar_map -> constr -> Pp.t
+[@@deprecated "use Internal.print_constr_env"]
+
+val print_rel_context : env -> Pp.t
+[@@deprecated "use Internal.print_rel_context"]
diff --git a/engine/uState.ml b/engine/uState.ml
index 0791e4c277..29cb3c9bcc 100644
--- a/engine/uState.ml
+++ b/engine/uState.ml
@@ -430,10 +430,17 @@ let univ_rigid = UnivRigid
let univ_flexible = UnivFlexible false
let univ_flexible_alg = UnivFlexible true
-let merge ?loc sideff rigid uctx ctx' =
+(** ~sideff indicates that it is ok to redeclare a universe.
+ ~extend also merges the universe context in the local constraint structures
+ and not only in the graph. This depends if the
+ context we merge comes from a side effect that is already inlined
+ or defined separately. In the later case, there is no extension,
+ see [emit_side_effects] for example. *)
+let merge ?loc ~sideff ~extend rigid uctx ctx' =
let open Univ in
let levels = ContextSet.levels ctx' in
- let uctx = if sideff then uctx else
+ let uctx =
+ if not extend then uctx else
match rigid with
| UnivRigid -> uctx
| UnivFlexible b ->
@@ -448,9 +455,8 @@ let merge ?loc sideff rigid uctx ctx' =
else { uctx with uctx_univ_variables = uvars' }
in
let uctx_local =
- if sideff then uctx.uctx_local
- else ContextSet.append ctx' uctx.uctx_local
- in
+ if not extend then uctx.uctx_local
+ else ContextSet.append ctx' uctx.uctx_local in
let declare g =
LSet.fold (fun u g ->
try UGraph.add_universe u false g
@@ -479,7 +485,7 @@ let merge_subst uctx s =
let emit_side_effects eff u =
let uctxs = Safe_typing.universes_of_private eff in
- List.fold_left (merge true univ_rigid) u uctxs
+ List.fold_left (merge ~sideff:true ~extend:false univ_rigid) u uctxs
let new_univ_variable ?loc rigid name
({ uctx_local = ctx; uctx_univ_variables = uvars; uctx_univ_algebraic = avars} as uctx) =
@@ -668,7 +674,7 @@ let update_sigma_env uctx env =
{ uctx with uctx_initial_universes = univs;
uctx_universes = univs }
in
- merge true univ_rigid eunivs eunivs.uctx_local
+ merge ~sideff:true ~extend:false univ_rigid eunivs eunivs.uctx_local
let pr_weak prl {uctx_weak_constraints=weak} =
let open Pp in
diff --git a/engine/uState.mli b/engine/uState.mli
index a59e61b894..f833508ebf 100644
--- a/engine/uState.mli
+++ b/engine/uState.mli
@@ -103,7 +103,7 @@ val univ_rigid : rigid
val univ_flexible : rigid
val univ_flexible_alg : rigid
-val merge : ?loc:Loc.t -> bool -> rigid -> t -> Univ.ContextSet.t -> t
+val merge : ?loc:Loc.t -> sideff:bool -> extend:bool -> rigid -> t -> Univ.ContextSet.t -> t
val merge_subst : t -> UnivSubst.universe_opt_subst -> t
val emit_side_effects : Safe_typing.private_constants -> t -> t
diff --git a/engine/univNames.ml b/engine/univNames.ml
index a688401741..70cdd3a2db 100644
--- a/engine/univNames.ml
+++ b/engine/univNames.ml
@@ -8,10 +8,9 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
+open Util
open Names
open Univ
-open Globnames
-open Nametab
let qualid_of_level l =
@@ -31,44 +30,48 @@ let pr_with_global_universes l = Libnames.pr_qualid (qualid_of_level l)
(** Global universe information outside the kernel, to handle
polymorphic universe names in sections that have to be discharged. *)
-let universe_map = (Summary.ref UnivIdMap.empty ~name:"global universe info" : bool Nametab.UnivIdMap.t ref)
-
-let add_global_universe u p =
- match Level.name u with
- | Some n -> universe_map := Nametab.UnivIdMap.add n p !universe_map
- | None -> ()
-
-let is_polymorphic l =
- match Level.name l with
- | Some n ->
- (try Nametab.UnivIdMap.find n !universe_map
- with Not_found -> false)
- | None -> false
-
(** Local universe names of polymorphic references *)
type universe_binders = Univ.Level.t Names.Id.Map.t
let empty_binders = Id.Map.empty
-let universe_binders_table = Summary.ref Refmap.empty ~name:"universe binders"
+let universe_binders_table = Summary.ref GlobRef.Map.empty ~name:"universe binders"
-let universe_binders_of_global ref : universe_binders =
+let universe_binders_of_global ref : Id.t list =
try
- let l = Refmap.find ref !universe_binders_table in l
- with Not_found -> Names.Id.Map.empty
+ let l = GlobRef.Map.find ref !universe_binders_table in l
+ with Not_found -> []
let cache_ubinder (_,(ref,l)) =
- universe_binders_table := Refmap.add ref l !universe_binders_table
+ universe_binders_table := GlobRef.Map.add ref l !universe_binders_table
let subst_ubinder (subst,(ref,l as orig)) =
let ref' = fst (Globnames.subst_global subst ref) in
if ref == ref' then orig else ref', l
+let name_universe lvl =
+ (** Best-effort naming from the string representation of the level. This is
+ completely hackish and should be solved in upper layers instead. *)
+ Id.of_string_soft (Level.to_string lvl)
+
let discharge_ubinder (_,(ref,l)) =
+ (** Expand polymorphic binders with the section context *)
+ let info = Lib.section_segment_of_reference ref in
+ let sec_inst = Array.to_list (Instance.to_array (info.Lib.abstr_subst)) in
+ let map lvl = match Level.name lvl with
+ | None -> (* Having Prop/Set/Var as section universes makes no sense *)
+ assert false
+ | Some na ->
+ try
+ let qid = Nametab.shortest_qualid_of_universe na in
+ snd (Libnames.repr_qualid qid)
+ with Not_found -> name_universe lvl
+ in
+ let l = List.map map sec_inst @ l in
Some (Lib.discharge_global ref, l)
-let ubinder_obj : GlobRef.t * universe_binders -> Libobject.obj =
+let ubinder_obj : GlobRef.t * Id.t list -> Libobject.obj =
let open Libobject in
declare_object { (default_object "universe binder") with
cache_function = cache_ubinder;
@@ -79,28 +82,35 @@ let ubinder_obj : GlobRef.t * universe_binders -> Libobject.obj =
rebuild_function = (fun x -> x); }
let register_universe_binders ref ubinders =
- (* Add the polymorphic (section) universes *)
- let ubinders = UnivIdMap.fold (fun lvl poly ubinders ->
- let qid = Nametab.shortest_qualid_of_universe lvl in
- let level = Level.make (fst lvl) (snd lvl) in
- if poly then Id.Map.add (snd (Libnames.repr_qualid qid)) level ubinders
- else ubinders)
- !universe_map ubinders
+ (** TODO: change the API to register a [Name.t list] instead. This is the last
+ part of the code that depends on the internal representation of names in
+ abstract contexts, but removing it requires quite a rework of the
+ callers. *)
+ let univs = AUContext.instance (Global.universes_of_global ref) in
+ let revmap = Id.Map.fold (fun id lvl accu -> LMap.add lvl id accu) ubinders LMap.empty in
+ let map lvl =
+ try LMap.find lvl revmap
+ with Not_found -> name_universe lvl
in
- if not (Id.Map.is_empty ubinders)
- then Lib.add_anonymous_leaf (ubinder_obj (ref,ubinders))
+ let ubinders = Array.map_to_list map (Instance.to_array univs) in
+ if not (List.is_empty ubinders) then Lib.add_anonymous_leaf (ubinder_obj (ref, ubinders))
type univ_name_list = Names.lname list
-let universe_binders_with_opt_names ref levels = function
- | None -> universe_binders_of_global ref
+let universe_binders_with_opt_names ref names =
+ let orig = universe_binders_of_global ref in
+ let udecl = match names with
+ | None -> orig
| Some udecl ->
- if Int.equal(List.length levels) (List.length udecl)
- then
- List.fold_left2 (fun acc { CAst.v = na} lvl -> match na with
- | Anonymous -> acc
- | Name na -> Names.Id.Map.add na lvl acc)
- empty_binders udecl levels
- else
+ try
+ List.map2 (fun orig {CAst.v = na} ->
+ match na with
+ | Anonymous -> orig
+ | Name id -> id) orig udecl
+ with Invalid_argument _ ->
+ let len = List.length orig in
CErrors.user_err ~hdr:"universe_binders_with_opt_names"
- Pp.(str "Universe instance should have length " ++ int (List.length levels))
+ Pp.(str "Universe instance should have length " ++ int len)
+ in
+ let fold i acc na = Names.Id.Map.add na (Level.var i) acc in
+ List.fold_left_i fold 0 empty_binders udecl
diff --git a/engine/univNames.mli b/engine/univNames.mli
index 837beac267..bd4062ade4 100644
--- a/engine/univNames.mli
+++ b/engine/univNames.mli
@@ -13,13 +13,6 @@ open Univ
val pr_with_global_universes : Level.t -> Pp.t
val qualid_of_level : Level.t -> Libnames.qualid
-(** Global universe information outside the kernel, to handle
- polymorphic universes in sections that have to be discharged. *)
-val add_global_universe : Level.t -> Decl_kinds.polymorphic -> unit
-
-(** Is [lvl] a global polymorphic universe? (ie section polymorphic universe) *)
-val is_polymorphic : Level.t -> bool
-
(** Local universe name <-> level mapping *)
type universe_binders = Univ.Level.t Names.Id.Map.t
@@ -27,15 +20,14 @@ type universe_binders = Univ.Level.t Names.Id.Map.t
val empty_binders : universe_binders
val register_universe_binders : Names.GlobRef.t -> universe_binders -> unit
-val universe_binders_of_global : Names.GlobRef.t -> universe_binders
type univ_name_list = Names.lname list
-(** [universe_binders_with_opt_names ref u l]
+(** [universe_binders_with_opt_names ref l]
- If [l] is [Some univs] return the universe binders naming the levels of [u] by [univs] (skipping Anonymous).
- May error if the lengths mismatch.
+ If [l] is [Some univs] return the universe binders naming the bound levels
+ of [ref] by [univs] (skipping Anonymous). May error if the lengths mismatch.
- Otherwise return [universe_binders_of_global ref]. *)
+ Otherwise return the bound universe names registered for [ref]. *)
val universe_binders_with_opt_names : Names.GlobRef.t ->
- Univ.Level.t list -> univ_name_list option -> universe_binders
+ univ_name_list option -> universe_binders
diff --git a/engine/universes.ml b/engine/universes.ml
index ee9668433c..5d0157b2db 100644
--- a/engine/universes.ml
+++ b/engine/universes.ml
@@ -19,14 +19,9 @@ type univ_name_list = UnivNames.univ_name_list
let pr_with_global_universes = UnivNames.pr_with_global_universes
let reference_of_level = UnivNames.qualid_of_level
-let add_global_universe = UnivNames.add_global_universe
-
-let is_polymorphic = UnivNames.is_polymorphic
-
let empty_binders = UnivNames.empty_binders
let register_universe_binders = UnivNames.register_universe_binders
-let universe_binders_of_global = UnivNames.universe_binders_of_global
let universe_binders_with_opt_names = UnivNames.universe_binders_with_opt_names
diff --git a/engine/universes.mli b/engine/universes.mli
index ad937471e9..0d3bae4c95 100644
--- a/engine/universes.mli
+++ b/engine/universes.mli
@@ -25,12 +25,6 @@ val pr_with_global_universes : Level.t -> Pp.t
val reference_of_level : Level.t -> Libnames.qualid
[@@ocaml.deprecated "Use [UnivNames.qualid_of_level]"]
-val add_global_universe : Level.t -> Decl_kinds.polymorphic -> unit
-[@@ocaml.deprecated "Use [UnivNames.add_global_universe]"]
-
-val is_polymorphic : Level.t -> bool
-[@@ocaml.deprecated "Use [UnivNames.is_polymorphic]"]
-
type universe_binders = UnivNames.universe_binders
[@@ocaml.deprecated "Use [UnivNames.universe_binders]"]
@@ -39,14 +33,12 @@ val empty_binders : universe_binders
val register_universe_binders : Globnames.global_reference -> universe_binders -> unit
[@@ocaml.deprecated "Use [UnivNames.register_universe_binders]"]
-val universe_binders_of_global : Globnames.global_reference -> universe_binders
-[@@ocaml.deprecated "Use [UnivNames.universe_binders_of_global]"]
type univ_name_list = UnivNames.univ_name_list
[@@ocaml.deprecated "Use [UnivNames.univ_name_list]"]
val universe_binders_with_opt_names : Globnames.global_reference ->
- Univ.Level.t list -> univ_name_list option -> universe_binders
+ univ_name_list option -> universe_binders
[@@ocaml.deprecated "Use [UnivNames.universe_binders_with_opt_names]"]
(** ****** Deprecated: moved to [UnivGen] *)
diff --git a/grammar/dune b/grammar/dune
new file mode 100644
index 0000000000..90847e7fb6
--- /dev/null
+++ b/grammar/dune
@@ -0,0 +1,41 @@
+(library
+ (name grammar)
+ (synopsis "Coq Camlp5 Grammar Extensions for Plugins")
+ (public_name coq.grammar)
+ (wrapped false)
+ (flags (:standard -w -58))
+ (libraries camlp5))
+
+; Custom camlp5! This is a net speedup, and a preparation for using
+; Dune's preprocessor abilities.
+(rule
+ (targets coqmlp5)
+ (action (run mkcamlp5.opt pa_o.cmx pa_op.cmx pr_dump.cmx pa_extend.cmx q_MLast.cmx pa_macro.cmx pr_o.cmx -o coqmlp5)))
+
+(rule
+ (targets coqp5)
+ (action (run mkcamlp5.opt pa_o.cmx pa_op.cmx pr_dump.cmx pa_extend.cmx q_MLast.cmx pa_macro.cmx pr_o.cmx %{dep:grammar.cmxa} -o coqp5)))
+
+(install
+ (section bin)
+ (files coqp5 coqmlp5))
+
+(rule
+ (targets q_util.ml)
+ (deps (:mlp-file q_util.mlp))
+ (action (run coqmlp5 -loc loc -impl %{mlp-file} -o %{targets})))
+
+(rule
+ (targets argextend.ml)
+ (deps (:mlp-file argextend.mlp))
+ (action (run coqmlp5 -loc loc -impl %{mlp-file} -o %{targets})))
+
+(rule
+ (targets tacextend.ml)
+ (deps (:mlp-file tacextend.mlp))
+ (action (run coqmlp5 -loc loc -impl %{mlp-file} -o %{targets})))
+
+(rule
+ (targets vernacextend.ml)
+ (deps (:mlp-file vernacextend.mlp))
+ (action (run coqmlp5 -loc loc -impl %{mlp-file} -o %{targets})))
diff --git a/grammar/tacextend.mlp b/grammar/tacextend.mlp
index 07239e7af0..5943600b7c 100644
--- a/grammar/tacextend.mlp
+++ b/grammar/tacextend.mlp
@@ -8,6 +8,8 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
+(** WARNING: this file is deprecated; consider modifying coqpp instead. *)
+
(** Implementation of the TACTIC EXTEND macro. *)
open Q_util
diff --git a/ide/coq_lex.mll b/ide/coq_lex.mll
index 1fdd7317b5..b6654f6d7a 100644
--- a/ide/coq_lex.mll
+++ b/ide/coq_lex.mll
@@ -23,7 +23,11 @@ let number = [ '0'-'9' ]+
let string = "\"" _+ "\""
-let undotted_sep = (number space* ':' space*)? '{' | '}' | '-'+ | '+'+ | '*'+
+let alpha = ['a'-'z' 'A'-'Z']
+
+let ident = alpha (alpha | number | '_' | "'")*
+
+let undotted_sep = ((number | '[' ident ']') space* ':' space*)? '{' | '}' | '-'+ | '+'+ | '*'+
let vernac_control = "Fail" | "Time" | "Redirect" space+ string | "Timeout" space+ number
diff --git a/ide/coqide.ml b/ide/coqide.ml
index 09a82ba91e..00d43e6e64 100644
--- a/ide/coqide.ml
+++ b/ide/coqide.ml
@@ -1046,16 +1046,24 @@ let build_ui () =
~accel:"F1"
~callback:(cb_on_current_term MiscMenu.show_hide_query_pane);
GAction.group_radio_actions
- ~callback:begin function
- | 0 -> List.iter (fun o -> Opt.set o "off") Opt.diff_item.Opt.opts
- | 1 -> List.iter (fun o -> Opt.set o "on") Opt.diff_item.Opt.opts
- | 2 -> List.iter (fun o -> Opt.set o "removed") Opt.diff_item.Opt.opts
- | _ -> assert false
+ ~init_value:(
+ let v = diffs#get in
+ List.iter (fun o -> Opt.set o v) Opt.diff_item.Opt.opts;
+ if v = "on" then 1
+ else if v = "removed" then 2
+ else 0)
+ ~callback:begin fun n ->
+ (match n with
+ | 0 -> List.iter (fun o -> Opt.set o "off"; diffs#set "off") Opt.diff_item.Opt.opts
+ | 1 -> List.iter (fun o -> Opt.set o "on"; diffs#set "on") Opt.diff_item.Opt.opts
+ | 2 -> List.iter (fun o -> Opt.set o "removed"; diffs#set "removed") Opt.diff_item.Opt.opts
+ | _ -> assert false);
+ send_to_coq (fun sn -> sn.coqops#show_goals)
end
[
- radio "Unset diff" 0 ~label:"Unset _Diff";
- radio "Set diff" 1 ~label:"Set Di_ff";
- radio "Set removed diff" 2 ~label:"Set _Removed Diff";
+ radio "Unset diff" 0 ~label:"_Don't show diffs";
+ radio "Set diff" 1 ~label:"Show diffs: only _added";
+ radio "Set removed diff" 2 ~label:"Show diffs: added and _removed";
];
];
toggle_items view_menu Coq.PrintOpt.bool_items;
diff --git a/ide/coqide.opam b/ide/coqide.opam
new file mode 100644
index 0000000000..ba05b9edcf
--- /dev/null
+++ b/ide/coqide.opam
@@ -0,0 +1,19 @@
+opam-version: "1.2"
+maintainer: "The Coq development team <coqdev@inria.fr>"
+authors: "The Coq development team, INRIA, CNRS, and contributors."
+homepage: "https://coq.inria.fr/"
+bug-reports: "https://github.com/coq/coq/issues"
+dev-repo: "https://github.com/coq/coq.git"
+license: "LGPL-2.1"
+
+available: [ocaml-version >= "4.02.3"]
+
+depends: [
+ "dune" { build }
+ "ocamlfind" { build }
+ "num"
+ "camlp5"
+ "coq"
+]
+
+build: [ [ "dune" "build" "-p" name "-j" jobs ] ]
diff --git a/ide/dune b/ide/dune
new file mode 100644
index 0000000000..6931a747ac
--- /dev/null
+++ b/ide/dune
@@ -0,0 +1,28 @@
+(ocamllex utf8_convert config_lexer coq_lex)
+
+(library
+ (name core)
+ (public_name coqide.core)
+ (wrapped false)
+ (modules (:standard \ idetop coqide_main))
+ (libraries threads str lablgtk2.sourceview2 coq.lib coqide.protocol))
+
+(rule
+ (targets coqide_main.ml)
+ (deps (:ml4-file coqide_main.ml4))
+ (action (run coqmlp5 -loc loc -impl %{ml4-file} -o %{targets})))
+
+(executable
+ (name coqide_main)
+ (public_name coqide)
+ (package coqide)
+ (modules coqide_main)
+ (libraries coqide.core))
+
+(executable
+ (name idetop)
+ (public_name coqidetop.opt)
+ (package coqide)
+ (modules idetop)
+ (libraries coq.toplevel coqide.protocol)
+ (link_flags -linkall))
diff --git a/ide/dune-project b/ide/dune-project
new file mode 100644
index 0000000000..948dc59000
--- /dev/null
+++ b/ide/dune-project
@@ -0,0 +1,3 @@
+(lang dune 1.0)
+
+(name coqide-devel)
diff --git a/ide/idetop.ml b/ide/idetop.ml
index 417ade51fd..8a221a93e9 100644
--- a/ide/idetop.ml
+++ b/ide/idetop.ml
@@ -53,10 +53,12 @@ let coqide_known_option table = List.mem table [
["Printing";"Records"];
["Printing";"Existential";"Instances"];
["Printing";"Universes"];
- ["Printing";"Unfocused"]]
+ ["Printing";"Unfocused"];
+ ["Diffs"]]
let is_known_option cmd = match Vernacprop.under_control cmd with
| VernacSetOption (_, o, BoolValue true)
+ | VernacSetOption (_, o, StringValue _)
| VernacUnsetOption (_, o) -> coqide_known_option o
| _ -> false
@@ -202,27 +204,35 @@ let export_pre_goals pgs =
Interface.given_up_goals = pgs.Proof.given_up_goals
}
-let add_diffs oldp newp intf =
- let open Interface in
- let (hyps_pp_list, concl_pp) = Proof_diffs.diff_first_goal oldp newp in
- match intf.fg_goals with
- | [] -> intf
- | first_goal :: tl ->
- { intf with fg_goals = { first_goal with goal_hyp = hyps_pp_list; goal_ccl = concl_pp } :: tl }
-
let goals () =
let doc = get_doc () in
set_doc @@ Stm.finish ~doc;
try
let newp = Proof_global.give_me_the_proof () in
- let intf = export_pre_goals (Proof.map_structured_proof newp process_goal) in
- if Proof_diffs.show_diffs () then
+ if Proof_diffs.show_diffs () then begin
let oldp = Stm.get_prev_proof ~doc (Stm.get_current_state ~doc) in
+ let diff_goal_map = Proof_diffs.make_goal_map oldp newp in
+ let map_goal_for_diff ng = (* todo: move to proof_diffs.ml *)
+ try Evar.Map.find ng diff_goal_map with Not_found -> ng
+ in
+
+ let process_goal_diffs nsigma ng =
+ let open Evd in
+ let og = map_goal_for_diff ng in
+ let og_s = match oldp with
+ | Some oldp ->
+ let (_,_,_,_,osigma) = Proof.proof oldp in
+ Some { it = og; sigma = osigma }
+ | None -> None
+ in
+ let (hyps_pp_list, concl_pp) = Proof_diffs.diff_goal_ide og_s ng nsigma in
+ { Interface.goal_hyp = hyps_pp_list; Interface.goal_ccl = concl_pp; Interface.goal_id = Goal.uid ng }
+ in
try
- Some (add_diffs oldp (Some newp) intf)
- with Pp_diff.Diff_Failure _ -> Some intf
- else
- Some intf
+ Some (export_pre_goals (Proof.map_structured_proof newp process_goal_diffs))
+ with Pp_diff.Diff_Failure _ -> Some (export_pre_goals (Proof.map_structured_proof newp process_goal))
+ end else
+ Some (export_pre_goals (Proof.map_structured_proof newp process_goal))
with Proof_global.NoCurrentProof -> None;;
let evars () =
diff --git a/ide/ideutils.ml b/ide/ideutils.ml
index 960beb8455..7044263b94 100644
--- a/ide/ideutils.ml
+++ b/ide/ideutils.ml
@@ -71,15 +71,15 @@ let insert_xml ?(mark = `INSERT) ?(tags = []) (buf : #GText.buffer_skel) msg =
let rmark = `MARK (buf#create_mark buf#start_iter) in
(* insert the string, but don't apply diff highlights to white space at the begin/end of line *)
let rec insert_str tags s =
+ let etags = try List.hd !dtags :: tags with hd -> tags in
try
- let _ = Str.search_forward nl_white_regex s 0 in
+ let start = Str.search_forward nl_white_regex s 0 in
+ insert_with_tags buf mark rmark etags (String.sub s 0 start);
insert_with_tags buf mark rmark tags (Str.matched_group 1 s);
let mend = Str.match_end () in
insert_str tags (String.sub s mend (String.length s - mend))
- with Not_found -> begin
- let etags = try List.hd !dtags :: tags with hd -> tags in
+ with Not_found ->
insert_with_tags buf mark rmark etags s
- end
in
let rec insert tags = function
| PCData s -> insert_str tags s
@@ -328,15 +328,18 @@ let coqtop_path () =
| None ->
try
let new_prog = System.get_toplevel_path "coqidetop" in
- if Sys.file_exists new_prog then new_prog
+ (* The file exists or it is to be found by path *)
+ if Sys.file_exists new_prog ||
+ CString.equal Filename.(basename new_prog) new_prog
+ then new_prog
else
let in_macos_bundle =
Filename.concat
(Filename.dirname new_prog)
(Filename.concat "../Resources/bin" (Filename.basename new_prog))
in if Sys.file_exists in_macos_bundle then in_macos_bundle
- else "coqidetop"
- with Not_found -> "coqidetop"
+ else "coqidetop.opt"
+ with Not_found -> "coqidetop.opt"
in file
(* In win32, when a command-line is to be executed via cmd.exe
diff --git a/ide/preferences.ml b/ide/preferences.ml
index 526d94a939..955ee87840 100644
--- a/ide/preferences.ml
+++ b/ide/preferences.ml
@@ -565,6 +565,9 @@ let nanoPG =
let user_queries =
new preference ~name:["user_queries"] ~init:[] ~repr:Repr.(string_pair_list '$')
+let diffs =
+ new preference ~name:["diffs"] ~init:"off" ~repr:Repr.(string)
+
class tag_button (box : Gtk.box Gtk.obj) =
object (self)
diff --git a/ide/preferences.mli b/ide/preferences.mli
index f3882d486d..dd2976efc2 100644
--- a/ide/preferences.mli
+++ b/ide/preferences.mli
@@ -102,6 +102,7 @@ val tab_length : int preference
val highlight_current_line : bool preference
val nanoPG : bool preference
val user_queries : (string * string) list preference
+val diffs : string preference
val save_pref : unit -> unit
val load_pref : unit -> unit
diff --git a/ide/protocol/dune b/ide/protocol/dune
new file mode 100644
index 0000000000..9ce4559940
--- /dev/null
+++ b/ide/protocol/dune
@@ -0,0 +1,7 @@
+(library
+ (name protocol)
+ (public_name coqide.protocol)
+ (wrapped false)
+ (libraries coq.lib))
+
+(ocamllex xml_lexer)
diff --git a/interp/constrextern.ml b/interp/constrextern.ml
index 009894fddb..3996a1756c 100644
--- a/interp/constrextern.ml
+++ b/interp/constrextern.ml
@@ -102,7 +102,7 @@ let _show_inactive_notations () =
(function
| NotationRule (scopt, ntn) ->
Feedback.msg_notice (pr_notation ntn ++ show_scope scopt)
- | SynDefRule kn -> Feedback.msg_notice (str (Names.KerName.to_string kn)))
+ | SynDefRule kn -> Feedback.msg_notice (str (string_of_qualid (Nametab.shortest_qualid_of_syndef Id.Set.empty kn))))
!inactive_notations_table
let deactivate_notation nr =
@@ -135,8 +135,9 @@ let reactivate_notation nr =
++ str "is already active" ++ show_scope scopt ++
str ".")
| SynDefRule kn ->
+ let s = string_of_qualid (Nametab.shortest_qualid_of_syndef Id.Set.empty kn) in
Feedback.msg_warning
- (str "Notation" ++ spc () ++ str (Names.KerName.to_string kn)
+ (str "Notation" ++ spc () ++ str s
++ spc () ++ str "is already active.")
@@ -531,18 +532,7 @@ let extern_ind_pattern_in_scope (custom,scopes as allscopes) vars ind args =
else
try
if !Flags.raw_print || !print_no_symbol then raise No_match;
- let (sc,p) = uninterp_prim_token_ind_pattern ind args in
- match availability_of_entry_coercion custom InConstrEntrySomeLevel with
- | None -> raise No_match
- | Some coercion ->
- match availability_of_prim_token p sc scopes with
- | None -> raise No_match
- | Some key ->
- insert_pat_coercion coercion (insert_pat_delimiters (CAst.make @@ CPatPrim p) key)
- with No_match ->
- try
- if !Flags.raw_print || !print_no_symbol then raise No_match;
- extern_notation_ind_pattern allscopes vars ind args
+ extern_notation_ind_pattern allscopes vars ind args
(uninterp_ind_pattern_notations ind)
with No_match ->
let c = extern_reference vars (IndRef ind) in
diff --git a/interp/declare.ml b/interp/declare.ml
index 2b2ca36edc..23c68b5e18 100644
--- a/interp/declare.ml
+++ b/interp/declare.ml
@@ -39,7 +39,6 @@ type constant_obj = {
cst_decl : global_declaration option;
(** [None] when the declaration is a side-effect and has already been defined
in the global environment. *)
- cst_hyps : Dischargedhypsmap.discharged_hyps;
cst_kind : logical_kind;
cst_locl : bool;
}
@@ -94,28 +93,20 @@ let cache_constant ((sp,kn), obj) =
Nametab.push (Nametab.Until 1) sp (ConstRef (Constant.make1 kn));
let cst = Global.lookup_constant kn' in
add_section_constant (Declareops.constant_is_polymorphic cst) kn' cst.const_hyps;
- Dischargedhypsmap.set_discharged_hyps sp obj.cst_hyps;
add_constant_kind (Constant.make1 kn) obj.cst_kind
-let discharged_hyps kn sechyps =
- let (_,dir,_) = KerName.repr kn in
- let args = Array.to_list (instance_from_variable_context sechyps) in
- List.rev_map (Libnames.make_path dir) args
-
let discharge_constant ((sp, kn), obj) =
let con = Constant.make1 kn in
let from = Global.lookup_constant con in
let modlist = replacement_context () in
let { abstr_ctx = hyps; abstr_subst = subst; abstr_uctx = uctx } = section_segment_of_constant con in
- let new_hyps = (discharged_hyps kn hyps) @ obj.cst_hyps in
let abstract = (named_of_variable_context hyps, subst, uctx) in
let new_decl = GlobalRecipe{ from; info = { Opaqueproof.modlist; abstract}} in
- Some { obj with cst_hyps = new_hyps; cst_decl = Some new_decl; }
+ Some { obj with cst_decl = Some new_decl; }
(* Hack to reduce the size of .vo: we keep only what load/open needs *)
let dummy_constant cst = {
cst_decl = None;
- cst_hyps = [];
cst_kind = cst.cst_kind;
cst_locl = cst.cst_locl;
}
@@ -142,7 +133,6 @@ let update_tables c =
let register_side_effect (c, role) =
let o = inConstant {
cst_decl = None;
- cst_hyps = [] ;
cst_kind = IsProof Theorem;
cst_locl = false;
} in
@@ -150,8 +140,8 @@ let register_side_effect (c, role) =
ignore(add_leaf id o);
update_tables c;
match role with
- | Safe_typing.Subproof -> ()
- | Safe_typing.Schema (ind, kind) -> !declare_scheme kind [|ind,c|]
+ | Subproof -> ()
+ | Schema (ind, kind) -> !declare_scheme kind [|ind,c|]
let declare_constant_common id cst =
let o = inConstant cst in
@@ -194,7 +184,6 @@ let declare_constant ?(internal = UserIndividualRequest) ?(local = false) id ?(e
let () = List.iter register_side_effect export in
let cst = {
cst_decl = Some decl;
- cst_hyps = [] ;
cst_kind = kind;
cst_locl = local;
} in
@@ -255,7 +244,6 @@ let cache_variable ((sp,_),o) =
poly, univs in
Nametab.push (Nametab.Until 1) (restrict_path 0 sp) (VarRef id);
add_section_variable id impl poly ctx;
- Dischargedhypsmap.set_discharged_hyps sp [];
add_variable_data id (p,opaq,ctx,poly,mk)
let discharge_variable (_,o) = match o with
@@ -311,15 +299,15 @@ let inductive_names sp kn mie =
([], 0) mie.mind_entry_inds
in names
-let load_inductive i ((sp,kn),(_,mie)) =
+let load_inductive i ((sp,kn),mie) =
let names = inductive_names sp kn mie in
List.iter (fun (sp, ref) -> Nametab.push (Nametab.Until i) sp ref ) names
-let open_inductive i ((sp,kn),(_,mie)) =
+let open_inductive i ((sp,kn),mie) =
let names = inductive_names sp kn mie in
List.iter (fun (sp, ref) -> Nametab.push (Nametab.Exactly i) sp ref) names
-let cache_inductive ((sp,kn),(dhyps,mie)) =
+let cache_inductive ((sp,kn),mie) =
let names = inductive_names sp kn mie in
List.iter check_exists (List.map fst names);
let id = basename sp in
@@ -328,17 +316,14 @@ let cache_inductive ((sp,kn),(dhyps,mie)) =
assert (MutInd.equal kn' (MutInd.make1 kn));
let mind = Global.lookup_mind kn' in
add_section_kn (Declareops.inductive_is_polymorphic mind) kn' mind.mind_hyps;
- Dischargedhypsmap.set_discharged_hyps sp dhyps;
List.iter (fun (sp, ref) -> Nametab.push (Nametab.Until 1) sp ref) names
-let discharge_inductive ((sp,kn),(dhyps,mie)) =
+let discharge_inductive ((sp,kn),mie) =
let mind = Global.mind_of_delta_kn kn in
let mie = Global.lookup_mind mind in
let repl = replacement_context () in
let info = section_segment_of_mutual_inductive mind in
- let sechyps = info.Lib.abstr_ctx in
- Some (discharged_hyps kn sechyps,
- Discharge.process_inductive info repl mie)
+ Some (Discharge.process_inductive info repl mie)
let dummy_one_inductive_entry mie = {
mind_entry_typename = mie.mind_entry_typename;
@@ -349,30 +334,28 @@ let dummy_one_inductive_entry mie = {
}
(* Hack to reduce the size of .vo: we keep only what load/open needs *)
-let dummy_inductive_entry (_,m) = ([],{
+let dummy_inductive_entry m = {
mind_entry_params = [];
mind_entry_record = None;
mind_entry_finite = Declarations.BiFinite;
mind_entry_inds = List.map dummy_one_inductive_entry m.mind_entry_inds;
mind_entry_universes = Monomorphic_ind_entry Univ.ContextSet.empty;
mind_entry_private = None;
-})
+}
(* reinfer subtyping constraints for inductive after section is dischared. *)
-let infer_inductive_subtyping (pth, mind_ent) =
+let infer_inductive_subtyping mind_ent =
match mind_ent.mind_entry_universes with
| Monomorphic_ind_entry _ | Polymorphic_ind_entry _ ->
- (pth, mind_ent)
+ mind_ent
| Cumulative_ind_entry cumi ->
begin
let env = Global.env () in
(* let (env'', typed_params) = Typeops.infer_local_decls env' (mind_ent.mind_entry_params) in *)
- (pth, InferCumulativity.infer_inductive env mind_ent)
+ InferCumulativity.infer_inductive env mind_ent
end
-type inductive_obj = Dischargedhypsmap.discharged_hyps * mutual_inductive_entry
-
-let inInductive : inductive_obj -> obj =
+let inInductive : mutual_inductive_entry -> obj =
declare_object {(default_object "INDUCTIVE") with
cache_function = cache_inductive;
load_function = load_inductive;
@@ -426,7 +409,7 @@ let declare_mind mie =
let id = match mie.mind_entry_inds with
| ind::_ -> ind.mind_entry_typename
| [] -> anomaly (Pp.str "cannot declare an empty list of inductives.") in
- let (sp,kn as oname) = add_leaf id (inInductive ([],mie)) in
+ let (sp,kn as oname) = add_leaf id (inInductive mie) in
let mind = Global.mind_of_delta_kn kn in
let isprim = declare_projections mie.mind_entry_universes mind in
declare_mib_implicits mind;
@@ -508,7 +491,6 @@ let add_universe src (dp, i) =
Option.iter (fun poly ->
let ctx = Univ.ContextSet.add_universe level Univ.ContextSet.empty in
Global.push_context_set poly ctx;
- UnivNames.add_global_universe level poly;
if poly then Lib.add_section_context ctx)
optpoly
@@ -597,7 +579,7 @@ let do_constraint poly l =
let open Univ in
let u_of_id x =
let level = Pretyping.interp_known_glob_level (Evd.from_env (Global.env ())) x in
- UnivNames.is_polymorphic level, level
+ Lib.is_polymorphic_univ level, level
in
let in_section = Lib.sections_are_opened () in
let () =
diff --git a/interp/dune b/interp/dune
new file mode 100644
index 0000000000..e9ef7ba99a
--- /dev/null
+++ b/interp/dune
@@ -0,0 +1,6 @@
+(library
+ (name interp)
+ (synopsis "Coq's Syntactic Interpretation for AST [notations, implicits]")
+ (public_name coq.interp)
+ (wrapped false)
+ (libraries pretyping))
diff --git a/interp/impargs.ml b/interp/impargs.ml
index e542b818f6..3603367cf1 100644
--- a/interp/impargs.ml
+++ b/interp/impargs.ml
@@ -508,11 +508,11 @@ type implicit_discharge_request =
| ImplInteractive of GlobRef.t * implicits_flags *
implicit_interactive_request
-let implicits_table = Summary.ref Refmap.empty ~name:"implicits"
+let implicits_table = Summary.ref GlobRef.Map.empty ~name:"implicits"
let implicits_of_global ref =
try
- let l = Refmap.find ref !implicits_table in
+ let l = GlobRef.Map.find ref !implicits_table in
try
let rename_l = Arguments_renaming.arguments_names ref in
let rec rename implicits names = match implicits, names with
@@ -527,7 +527,7 @@ let implicits_of_global ref =
with Not_found -> [DefaultImpArgs,[]]
let cache_implicits_decl (ref,imps) =
- implicits_table := Refmap.add ref imps !implicits_table
+ implicits_table := GlobRef.Map.add ref imps !implicits_table
let load_implicits _ (_,(_,l)) = List.iter cache_implicits_decl l
diff --git a/interp/notation.ml b/interp/notation.ml
index 625d072b9f..02c7812e21 100644
--- a/interp/notation.ml
+++ b/interp/notation.ml
@@ -98,21 +98,40 @@ let init_scope_map () =
(**********************************************************************)
(* Operations on scopes *)
+let warn_undeclared_scope =
+ CWarnings.create ~name:"undeclared-scope" ~category:"deprecated"
+ (fun (scope) ->
+ strbrk "Declaring a scope implicitly is deprecated; use in advance an explicit "
+ ++ str "\"Declare Scope " ++ str scope ++ str ".\".")
+
let declare_scope scope =
try let _ = String.Map.find scope !scope_map in ()
with Not_found ->
-(* Flags.if_warn message ("Creating scope "^scope);*)
scope_map := String.Map.add scope empty_scope !scope_map
let error_unknown_scope sc =
user_err ~hdr:"Notation"
(str "Scope " ++ str sc ++ str " is not declared.")
-let find_scope scope =
+let find_scope ?(tolerant=false) scope =
try String.Map.find scope !scope_map
- with Not_found -> error_unknown_scope scope
+ with Not_found ->
+ if tolerant then
+ (* tolerant mode to be turn off after deprecation phase *)
+ begin
+ warn_undeclared_scope scope;
+ scope_map := String.Map.add scope empty_scope !scope_map;
+ empty_scope
+ end
+ else
+ error_unknown_scope scope
-let check_scope sc = let _ = find_scope sc in ()
+let check_scope ?(tolerant=false) scope =
+ let _ = find_scope ~tolerant scope in ()
+
+let ensure_scope scope = check_scope ~tolerant:true scope
+
+let find_scope scope = find_scope scope
(* [sc] might be here a [scope_name] or a [delimiter]
(now allowed after Open Scope) *)
@@ -245,7 +264,7 @@ type key =
| Oth
let key_compare k1 k2 = match k1, k2 with
-| RefKey gr1, RefKey gr2 -> RefOrdered.compare gr1 gr2
+| RefKey gr1, RefKey gr2 -> GlobRef.Ordered.compare gr1 gr2
| RefKey _, Oth -> -1
| Oth, RefKey _ -> 1
| Oth, Oth -> 0
@@ -266,16 +285,14 @@ let keymap_find key map =
(* Scopes table : interpretation -> scope_name *)
let notations_key_table = ref (KeyMap.empty : notation_rule list KeyMap.t)
-let prim_token_key_table = ref (KeyMap.empty : (string * (any_glob_constr -> prim_token option) * bool) KeyMap.t)
-
let glob_prim_constr_key c = match DAst.get c with
- | GRef (ref, _) -> RefKey (canonical_gr ref)
+ | GRef (ref, _) -> Some (canonical_gr ref)
| GApp (c, _) ->
begin match DAst.get c with
- | GRef (ref, _) -> RefKey (canonical_gr ref)
- | _ -> Oth
+ | GRef (ref, _) -> Some (canonical_gr ref)
+ | _ -> None
end
- | _ -> Oth
+ | _ -> None
let glob_constr_keys c = match DAst.get c with
| GApp (c, _) ->
@@ -303,77 +320,521 @@ let notation_constr_key = function (* Rem: NApp(NRef ref,[]) stands for @ref *)
(* Interpreting numbers (not in summary because functional objects) *)
type required_module = full_path * string list
+type rawnum = Constrexpr.raw_natural_number * Constrexpr.sign
-type 'a prim_token_interpreter =
- ?loc:Loc.t -> 'a -> glob_constr
+type prim_token_uid = string
-type cases_pattern_status = bool (* true = use prim token in patterns *)
+type 'a prim_token_interpreter = ?loc:Loc.t -> 'a -> glob_constr
+type 'a prim_token_uninterpreter = any_glob_constr -> 'a option
-type 'a prim_token_uninterpreter =
- glob_constr list * (any_glob_constr -> 'a option) * cases_pattern_status
+type 'a prim_token_interpretation =
+ 'a prim_token_interpreter * 'a prim_token_uninterpreter
-type internal_prim_token_interpreter =
- ?loc:Loc.t -> prim_token -> required_module * (unit -> glob_constr)
+module InnerPrimToken = struct
-let prim_token_interpreter_tab =
- (Hashtbl.create 7 : (scope_name, internal_prim_token_interpreter) Hashtbl.t)
+ type interpreter =
+ | RawNumInterp of (?loc:Loc.t -> rawnum -> glob_constr)
+ | BigNumInterp of (?loc:Loc.t -> Bigint.bigint -> glob_constr)
+ | StringInterp of (?loc:Loc.t -> string -> glob_constr)
-let add_prim_token_interpreter sc interp =
- try
- let cont = Hashtbl.find prim_token_interpreter_tab sc in
- Hashtbl.replace prim_token_interpreter_tab sc (interp cont)
- with Not_found ->
- let cont = (fun ?loc _p -> raise Not_found) in
- Hashtbl.add prim_token_interpreter_tab sc (interp cont)
-
-let declare_prim_token_interpreter sc interp (patl,uninterp,b) =
- declare_scope sc;
- add_prim_token_interpreter sc interp;
- List.iter (fun pat ->
- prim_token_key_table := KeyMap.add
- (glob_prim_constr_key pat) (sc,uninterp,b) !prim_token_key_table)
- patl
-
-let mkNumeral n =
- if Bigint.is_pos_or_zero n then Numeral (Bigint.to_string n, true)
- else Numeral (Bigint.to_string (Bigint.neg n), false)
-
-let ofNumeral n s =
+ let interp_eq f f' = match f,f' with
+ | RawNumInterp f, RawNumInterp f' -> f == f'
+ | BigNumInterp f, BigNumInterp f' -> f == f'
+ | StringInterp f, StringInterp f' -> f == f'
+ | _ -> false
+
+ let ofNumeral n s =
+ if s then Bigint.of_string n else Bigint.neg (Bigint.of_string n)
+
+ let do_interp ?loc interp primtok =
+ match primtok, interp with
+ | Numeral (n,s), RawNumInterp interp -> interp ?loc (n,s)
+ | Numeral (n,s), BigNumInterp interp -> interp ?loc (ofNumeral n s)
+ | String s, StringInterp interp -> interp ?loc s
+ | _ -> raise Not_found
+
+ type uninterpreter =
+ | RawNumUninterp of (any_glob_constr -> rawnum option)
+ | BigNumUninterp of (any_glob_constr -> Bigint.bigint option)
+ | StringUninterp of (any_glob_constr -> string option)
+
+ let uninterp_eq f f' = match f,f' with
+ | RawNumUninterp f, RawNumUninterp f' -> f == f'
+ | BigNumUninterp f, BigNumUninterp f' -> f == f'
+ | StringUninterp f, StringUninterp f' -> f == f'
+ | _ -> false
+
+ let mkNumeral n =
+ if Bigint.is_pos_or_zero n then Numeral (Bigint.to_string n, true)
+ else Numeral (Bigint.to_string (Bigint.neg n), false)
+
+ let mkString = function
+ | None -> None
+ | Some s -> if Unicode.is_utf8 s then Some (String s) else None
+
+ let do_uninterp uninterp g = match uninterp with
+ | RawNumUninterp u -> Option.map (fun (n,s) -> Numeral (n,s)) (u g)
+ | BigNumUninterp u -> Option.map mkNumeral (u g)
+ | StringUninterp u -> mkString (u g)
+
+end
+
+(* The following two tables of (un)interpreters will *not* be
+ synchronized. But their indexes will be checked to be unique.
+ These tables contain primitive token interpreters which are
+ registered in plugins, such as string and ascii syntax. It is
+ essential that only plugins add to these tables, and that
+ vernacular commands do not. See
+ https://github.com/coq/coq/issues/8401 for details of what goes
+ wrong when vernacular commands add to these tables. *)
+let prim_token_interpreters =
+ (Hashtbl.create 7 : (prim_token_uid, InnerPrimToken.interpreter) Hashtbl.t)
+
+let prim_token_uninterpreters =
+ (Hashtbl.create 7 : (prim_token_uid, InnerPrimToken.uninterpreter) Hashtbl.t)
+
+(*******************************************************)
+(* Numeral notation interpretation *)
+type numeral_notation_error =
+ | UnexpectedTerm of Constr.t
+ | UnexpectedNonOptionTerm of Constr.t
+
+exception NumeralNotationError of Environ.env * Evd.evar_map * numeral_notation_error
+
+type numnot_option =
+ | Nop
+ | Warning of raw_natural_number
+ | Abstract of raw_natural_number
+
+type int_ty =
+ { uint : Names.inductive;
+ int : Names.inductive }
+
+type z_pos_ty =
+ { z_ty : Names.inductive;
+ pos_ty : Names.inductive }
+
+type target_kind =
+ | Int of int_ty (* Coq.Init.Decimal.int + uint *)
+ | UInt of Names.inductive (* Coq.Init.Decimal.uint *)
+ | Z of z_pos_ty (* Coq.Numbers.BinNums.Z and positive *)
+
+type option_kind = Option | Direct
+type conversion_kind = target_kind * option_kind
+
+type numeral_notation_obj =
+ { to_kind : conversion_kind;
+ to_ty : GlobRef.t;
+ of_kind : conversion_kind;
+ of_ty : GlobRef.t;
+ num_ty : Libnames.qualid; (* for warnings / error messages *)
+ warning : numnot_option }
+
+module Numeral = struct
+(** * Numeral notation *)
+
+(** Reduction
+
+ The constr [c] below isn't necessarily well-typed, since we
+ built it via an [mkApp] of a conversion function on a term
+ that starts with the right constructor but might be partially
+ applied.
+
+ At least [c] is known to be evar-free, since it comes from
+ our own ad-hoc [constr_of_glob] or from conversions such
+ as [coqint_of_rawnum].
+*)
+
+let eval_constr env sigma (c : Constr.t) =
+ let c = EConstr.of_constr c in
+ let sigma,t = Typing.type_of env sigma c in
+ let c' = Vnorm.cbv_vm env sigma c t in
+ EConstr.Unsafe.to_constr c'
+
+(* For testing with "compute" instead of "vm_compute" :
+let eval_constr env sigma (c : Constr.t) =
+ let c = EConstr.of_constr c in
+ let c' = Tacred.compute env sigma c in
+ EConstr.Unsafe.to_constr c'
+*)
+
+let eval_constr_app env sigma c1 c2 =
+ eval_constr env sigma (mkApp (c1,[| c2 |]))
+
+exception NotANumber
+
+let warn_large_num =
+ CWarnings.create ~name:"large-number" ~category:"numbers"
+ (fun ty ->
+ strbrk "Stack overflow or segmentation fault happens when " ++
+ strbrk "working with large numbers in " ++ pr_qualid ty ++
+ strbrk " (threshold may vary depending" ++
+ strbrk " on your system limits and on the command executed).")
+
+let warn_abstract_large_num =
+ CWarnings.create ~name:"abstract-large-number" ~category:"numbers"
+ (fun (ty,f) ->
+ strbrk "To avoid stack overflow, large numbers in " ++
+ pr_qualid ty ++ strbrk " are interpreted as applications of " ++
+ Nametab.pr_global_env (Termops.vars_of_env (Global.env ())) f ++ strbrk ".")
+
+(** Comparing two raw numbers (base 10, big-endian, non-negative).
+ A bit nasty, but not critical: only used to decide when a
+ number is considered as large (see warnings above). *)
+
+exception Comp of int
+
+let rec rawnum_compare s s' =
+ let l = String.length s and l' = String.length s' in
+ if l < l' then - rawnum_compare s' s
+ else
+ let d = l-l' in
+ try
+ for i = 0 to d-1 do if s.[i] != '0' then raise (Comp 1) done;
+ for i = d to l-1 do
+ let c = Pervasives.compare s.[i] s'.[i-d] in
+ if c != 0 then raise (Comp c)
+ done;
+ 0
+ with Comp c -> c
+
+(***********************************************************************)
+
+(** ** Conversion between Coq [Decimal.int] and internal raw string *)
+
+(** Decimal.Nil has index 1, then Decimal.D0 has index 2 .. Decimal.D9 is 11 *)
+
+let digit_of_char c =
+ assert ('0' <= c && c <= '9');
+ Char.code c - Char.code '0' + 2
+
+let char_of_digit n =
+ assert (2<=n && n<=11);
+ Char.chr (n-2 + Char.code '0')
+
+let coquint_of_rawnum uint str =
+ let nil = mkConstruct (uint,1) in
+ let rec do_chars s i acc =
+ if i < 0 then acc
+ else
+ let dg = mkConstruct (uint, digit_of_char s.[i]) in
+ do_chars s (i-1) (mkApp(dg,[|acc|]))
+ in
+ do_chars str (String.length str - 1) nil
+
+let coqint_of_rawnum inds (str,sign) =
+ let uint = coquint_of_rawnum inds.uint str in
+ mkApp (mkConstruct (inds.int, if sign then 1 else 2), [|uint|])
+
+let rawnum_of_coquint c =
+ let rec of_uint_loop c buf =
+ match Constr.kind c with
+ | Construct ((_,1), _) (* Nil *) -> ()
+ | App (c, [|a|]) ->
+ (match Constr.kind c with
+ | Construct ((_,n), _) (* D0 to D9 *) ->
+ let () = Buffer.add_char buf (char_of_digit n) in
+ of_uint_loop a buf
+ | _ -> raise NotANumber)
+ | _ -> raise NotANumber
+ in
+ let buf = Buffer.create 64 in
+ let () = of_uint_loop c buf in
+ if Int.equal (Buffer.length buf) 0 then
+ (* To avoid ambiguities between Nil and (D0 Nil), we choose
+ to not display Nil alone as "0" *)
+ raise NotANumber
+ else Buffer.contents buf
+
+let rawnum_of_coqint c =
+ match Constr.kind c with
+ | App (c,[|c'|]) ->
+ (match Constr.kind c with
+ | Construct ((_,1), _) (* Pos *) -> (rawnum_of_coquint c', true)
+ | Construct ((_,2), _) (* Neg *) -> (rawnum_of_coquint c', false)
+ | _ -> raise NotANumber)
+ | _ -> raise NotANumber
+
+
+(***********************************************************************)
+
+(** ** Conversion between Coq [Z] and internal bigint *)
+
+(** First, [positive] from/to bigint *)
+
+let rec pos_of_bigint posty n =
+ match Bigint.div2_with_rest n with
+ | (q, false) ->
+ let c = mkConstruct (posty, 2) in (* xO *)
+ mkApp (c, [| pos_of_bigint posty q |])
+ | (q, true) when not (Bigint.equal q Bigint.zero) ->
+ let c = mkConstruct (posty, 1) in (* xI *)
+ mkApp (c, [| pos_of_bigint posty q |])
+ | (q, true) ->
+ mkConstruct (posty, 3) (* xH *)
+
+let rec bigint_of_pos c = match Constr.kind c with
+ | Construct ((_, 3), _) -> (* xH *) Bigint.one
+ | App (c, [| d |]) ->
+ begin match Constr.kind c with
+ | Construct ((_, n), _) ->
+ begin match n with
+ | 1 -> (* xI *) Bigint.add_1 (Bigint.mult_2 (bigint_of_pos d))
+ | 2 -> (* xO *) Bigint.mult_2 (bigint_of_pos d)
+ | n -> assert false (* no other constructor of type positive *)
+ end
+ | x -> raise NotANumber
+ end
+ | x -> raise NotANumber
+
+(** Now, [Z] from/to bigint *)
+
+let z_of_bigint { z_ty; pos_ty } n =
+ if Bigint.equal n Bigint.zero then
+ mkConstruct (z_ty, 1) (* Z0 *)
+ else
+ let (s, n) =
+ if Bigint.is_pos_or_zero n then (2, n) (* Zpos *)
+ else (3, Bigint.neg n) (* Zneg *)
+ in
+ let c = mkConstruct (z_ty, s) in
+ mkApp (c, [| pos_of_bigint pos_ty n |])
+
+let bigint_of_z z = match Constr.kind z with
+ | Construct ((_, 1), _) -> (* Z0 *) Bigint.zero
+ | App (c, [| d |]) ->
+ begin match Constr.kind c with
+ | Construct ((_, n), _) ->
+ begin match n with
+ | 2 -> (* Zpos *) bigint_of_pos d
+ | 3 -> (* Zneg *) Bigint.neg (bigint_of_pos d)
+ | n -> assert false (* no other constructor of type Z *)
+ end
+ | _ -> raise NotANumber
+ end
+ | _ -> raise NotANumber
+
+(** The uninterp function below work at the level of [glob_constr]
+ which is too low for us here. So here's a crude conversion back
+ to [constr] for the subset that concerns us. *)
+
+let rec constr_of_glob env sigma g = match DAst.get g with
+ | Glob_term.GRef (ConstructRef c, _) ->
+ let sigma,c = Evd.fresh_constructor_instance env sigma c in
+ sigma,mkConstructU c
+ | Glob_term.GApp (gc, gcl) ->
+ let sigma,c = constr_of_glob env sigma gc in
+ let sigma,cl = List.fold_left_map (constr_of_glob env) sigma gcl in
+ sigma,mkApp (c, Array.of_list cl)
+ | _ ->
+ raise NotANumber
+
+let rec glob_of_constr ?loc env sigma c = match Constr.kind c with
+ | App (c, ca) ->
+ let c = glob_of_constr ?loc env sigma c in
+ let cel = List.map (glob_of_constr ?loc env sigma) (Array.to_list ca) in
+ DAst.make ?loc (Glob_term.GApp (c, cel))
+ | Construct (c, _) -> DAst.make ?loc (Glob_term.GRef (ConstructRef c, None))
+ | Const (c, _) -> DAst.make ?loc (Glob_term.GRef (ConstRef c, None))
+ | Ind (ind, _) -> DAst.make ?loc (Glob_term.GRef (IndRef ind, None))
+ | Var id -> DAst.make ?loc (Glob_term.GRef (VarRef id, None))
+ | _ -> Loc.raise ?loc (NumeralNotationError(env,sigma,UnexpectedTerm c))
+
+let no_such_number ?loc ty =
+ CErrors.user_err ?loc
+ (str "Cannot interpret this number as a value of type " ++
+ pr_qualid ty)
+
+let interp_option ty ?loc env sigma c =
+ match Constr.kind c with
+ | App (_Some, [| _; c |]) -> glob_of_constr ?loc env sigma c
+ | App (_None, [| _ |]) -> no_such_number ?loc ty
+ | x -> Loc.raise ?loc (NumeralNotationError(env,sigma,UnexpectedNonOptionTerm c))
+
+let uninterp_option c =
+ match Constr.kind c with
+ | App (_Some, [| _; x |]) -> x
+ | _ -> raise NotANumber
+
+let big2raw n =
+ if Bigint.is_pos_or_zero n then (Bigint.to_string n, true)
+ else (Bigint.to_string (Bigint.neg n), false)
+
+let raw2big (n,s) =
if s then Bigint.of_string n else Bigint.neg (Bigint.of_string n)
-let mkString = function
-| None -> None
-| Some s -> if Unicode.is_utf8 s then Some (String s) else None
+let interp o ?loc n =
+ begin match o.warning with
+ | Warning threshold when snd n && rawnum_compare (fst n) threshold >= 0 ->
+ warn_large_num o.num_ty
+ | _ -> ()
+ end;
+ let c = match fst o.to_kind with
+ | Int int_ty -> coqint_of_rawnum int_ty n
+ | UInt uint_ty when snd n -> coquint_of_rawnum uint_ty (fst n)
+ | UInt _ (* n <= 0 *) -> no_such_number ?loc o.num_ty
+ | Z z_pos_ty -> z_of_bigint z_pos_ty (raw2big n)
+ in
+ let env = Global.env () in
+ let sigma = Evd.from_env env in
+ let sigma,to_ty = Evd.fresh_global env sigma o.to_ty in
+ let to_ty = EConstr.Unsafe.to_constr to_ty in
+ match o.warning, snd o.to_kind with
+ | Abstract threshold, Direct when rawnum_compare (fst n) threshold >= 0 ->
+ warn_abstract_large_num (o.num_ty,o.to_ty);
+ glob_of_constr ?loc env sigma (mkApp (to_ty,[|c|]))
+ | _ ->
+ let res = eval_constr_app env sigma to_ty c in
+ match snd o.to_kind with
+ | Direct -> glob_of_constr ?loc env sigma res
+ | Option -> interp_option o.num_ty ?loc env sigma res
+
+let uninterp o (Glob_term.AnyGlobConstr n) =
+ let env = Global.env () in
+ let sigma = Evd.from_env env in
+ let sigma,of_ty = Evd.fresh_global env sigma o.of_ty in
+ let of_ty = EConstr.Unsafe.to_constr of_ty in
+ try
+ let sigma,n = constr_of_glob env sigma n in
+ let c = eval_constr_app env sigma of_ty n in
+ let c = if snd o.of_kind == Direct then c else uninterp_option c in
+ match fst o.of_kind with
+ | Int _ -> Some (rawnum_of_coqint c)
+ | UInt _ -> Some (rawnum_of_coquint c, true)
+ | Z _ -> Some (big2raw (bigint_of_z c))
+ with
+ | Type_errors.TypeError _ | Pretype_errors.PretypeError _ -> None (* cf. eval_constr_app *)
+ | NotANumber -> None (* all other functions except big2raw *)
+end
+
+(* A [prim_token_infos], which is synchronized with the document
+ state, either contains a unique id pointing to an unsynchronized
+ prim token function, or a numeral notation object describing how to
+ interpret and uninterpret. We provide [prim_token_infos] because
+ we expect plugins to provide their own interpretation functions,
+ rather than going through numeral notations, which are available as
+ a vernacular. *)
+
+type prim_token_interp_info =
+ Uid of prim_token_uid
+ | NumeralNotation of numeral_notation_obj
+
+type prim_token_infos = {
+ pt_local : bool; (** Is this interpretation local? *)
+ pt_scope : scope_name; (** Concerned scope *)
+ pt_interp_info : prim_token_interp_info; (** Unique id "pointing" to (un)interp functions, OR a numeral notation object describing (un)interp functions *)
+ pt_required : required_module; (** Module that should be loaded first *)
+ pt_refs : GlobRef.t list; (** Entry points during uninterpretation *)
+ pt_in_match : bool (** Is this prim token legal in match patterns ? *)
+}
-let delay dir int ?loc x = (dir, (fun () -> int ?loc x))
+(* Table from scope_name to backtrack-able informations about interpreters
+ (in particular interpreter unique id). *)
+let prim_token_interp_infos =
+ ref (String.Map.empty : (required_module * prim_token_interp_info) String.Map.t)
+
+(* Table from global_reference to backtrack-able informations about
+ prim_token uninterpretation (in particular uninterpreter unique id). *)
+let prim_token_uninterp_infos =
+ ref (GlobRef.Map.empty : (scope_name * prim_token_interp_info * bool) GlobRef.Map.t)
+
+let hashtbl_check_and_set allow_overwrite uid f h eq =
+ match Hashtbl.find h uid with
+ | exception Not_found -> Hashtbl.add h uid f
+ | _ when allow_overwrite -> Hashtbl.add h uid f
+ | g when eq f g -> ()
+ | _ ->
+ user_err ~hdr:"prim_token_interpreter"
+ (str "Unique identifier " ++ str uid ++
+ str " already used to register a numeral or string (un)interpreter.")
+
+let register_gen_interpretation allow_overwrite uid (interp, uninterp) =
+ hashtbl_check_and_set
+ allow_overwrite uid interp prim_token_interpreters InnerPrimToken.interp_eq;
+ hashtbl_check_and_set
+ allow_overwrite uid uninterp prim_token_uninterpreters InnerPrimToken.uninterp_eq
+
+let register_rawnumeral_interpretation ?(allow_overwrite=false) uid (interp, uninterp) =
+ register_gen_interpretation allow_overwrite uid
+ (InnerPrimToken.RawNumInterp interp, InnerPrimToken.RawNumUninterp uninterp)
+
+let register_bignumeral_interpretation ?(allow_overwrite=false) uid (interp, uninterp) =
+ register_gen_interpretation allow_overwrite uid
+ (InnerPrimToken.BigNumInterp interp, InnerPrimToken.BigNumUninterp uninterp)
+
+let register_string_interpretation ?(allow_overwrite=false) uid (interp, uninterp) =
+ register_gen_interpretation allow_overwrite uid
+ (InnerPrimToken.StringInterp interp, InnerPrimToken.StringUninterp uninterp)
+
+let cache_prim_token_interpretation (_,infos) =
+ let ptii = infos.pt_interp_info in
+ let sc = infos.pt_scope in
+ check_scope ~tolerant:true sc;
+ prim_token_interp_infos :=
+ String.Map.add sc (infos.pt_required,ptii) !prim_token_interp_infos;
+ List.iter (fun r -> prim_token_uninterp_infos :=
+ GlobRef.Map.add r (sc,ptii,infos.pt_in_match)
+ !prim_token_uninterp_infos)
+ infos.pt_refs
+
+let subst_prim_token_interpretation (subs,infos) =
+ { infos with
+ pt_refs = List.map (subst_global_reference subs) infos.pt_refs }
+
+let classify_prim_token_interpretation infos =
+ if infos.pt_local then Dispose else Substitute infos
+
+let inPrimTokenInterp : prim_token_infos -> obj =
+ declare_object {(default_object "PRIM-TOKEN-INTERP") with
+ open_function = (fun i o -> if Int.equal i 1 then cache_prim_token_interpretation o);
+ cache_function = cache_prim_token_interpretation;
+ subst_function = subst_prim_token_interpretation;
+ classify_function = classify_prim_token_interpretation}
+
+let enable_prim_token_interpretation infos =
+ Lib.add_anonymous_leaf (inPrimTokenInterp infos)
+
+(** Compatibility.
+ Avoid the next two functions, they will now store unnecessary
+ objects in the library segment. Instead, combine
+ [register_*_interpretation] and [enable_prim_token_interpretation]
+ (the latter inside a [Mltop.declare_cache_obj]).
+*)
-type rawnum = Constrexpr.raw_natural_number * Constrexpr.sign
+let fresh_string_of =
+ let count = ref 0 in
+ fun root -> count := !count+1; (string_of_int !count)^"_"^root
+
+let declare_numeral_interpreter ?(local=false) sc dir interp (patl,uninterp,b) =
+ let uid = fresh_string_of sc in
+ register_bignumeral_interpretation uid (interp,uninterp);
+ enable_prim_token_interpretation
+ { pt_local = local;
+ pt_scope = sc;
+ pt_interp_info = Uid uid;
+ pt_required = dir;
+ pt_refs = List.map_filter glob_prim_constr_key patl;
+ pt_in_match = b }
+let declare_string_interpreter ?(local=false) sc dir interp (patl,uninterp,b) =
+ let uid = fresh_string_of sc in
+ register_string_interpretation uid (interp,uninterp);
+ enable_prim_token_interpretation
+ { pt_local = local;
+ pt_scope = sc;
+ pt_interp_info = Uid uid;
+ pt_required = dir;
+ pt_refs = List.map_filter glob_prim_constr_key patl;
+ pt_in_match = b }
-let declare_rawnumeral_interpreter sc dir interp (patl,uninterp,inpat) =
- declare_prim_token_interpreter sc
- (fun cont ?loc -> function Numeral (n,s) -> delay dir interp ?loc (n,s)
- | p -> cont ?loc p)
- (patl, (fun r -> match uninterp r with
- | None -> None
- | Some (n,s) -> Some (Numeral (n,s))), inpat)
-
-let declare_numeral_interpreter sc dir interp (patl,uninterp,inpat) =
- let interp' ?loc (n,s) = interp ?loc (ofNumeral n s) in
- declare_prim_token_interpreter sc
- (fun cont ?loc -> function Numeral (n,s) -> delay dir interp' ?loc (n,s)
- | p -> cont ?loc p)
- (patl, (fun r -> Option.map mkNumeral (uninterp r)), inpat)
-
-let declare_string_interpreter sc dir interp (patl,uninterp,inpat) =
- declare_prim_token_interpreter sc
- (fun cont ?loc -> function String s -> delay dir interp ?loc s | p -> cont ?loc p)
- (patl, (fun r -> mkString (uninterp r)), inpat)
let check_required_module ?loc sc (sp,d) =
try let _ = Nametab.global_of_path sp in ()
with Not_found ->
- user_err ?loc ~hdr:"prim_token_interpreter"
- (str "Cannot interpret in " ++ str sc ++ str " without requiring first module " ++ str (List.last d) ++ str ".")
+ match d with
+ | [] -> user_err ?loc ~hdr:"prim_token_interpreter"
+ (str "Cannot interpret in " ++ str sc ++ str " because " ++ pr_path sp ++ str " could not be found in the current environment.")
+ | _ -> user_err ?loc ~hdr:"prim_token_interpreter"
+ (str "Cannot interpret in " ++ str sc ++ str " without requiring first module " ++ str (List.last d) ++ str ".")
(* Look if some notation or numeral printer in [scope] can be used in
the scope stack [scopes], and if yes, using delimiters or not *)
@@ -476,9 +937,13 @@ let find_prim_token check_allowed ?loc p sc =
pat, df
with Not_found ->
(* Try for a primitive numerical notation *)
- let (spdir,interp) = Hashtbl.find prim_token_interpreter_tab sc ?loc p in
+ let (spdir,info) = String.Map.find sc !prim_token_interp_infos in
check_required_module ?loc sc spdir;
- let pat = interp () in
+ let interp = match info with
+ | Uid uid -> Hashtbl.find prim_token_interpreters uid
+ | NumeralNotation o -> InnerPrimToken.RawNumInterp (Numeral.interp o)
+ in
+ let pat = InnerPrimToken.do_interp ?loc interp p in
check_allowed pat;
pat, ((dirpath (fst spdir),DirPath.empty),"")
@@ -649,43 +1114,41 @@ let entry_has_ident = function
try String.Map.find s !entry_has_ident_map <= n with Not_found -> false
let uninterp_prim_token c =
- try
- let (sc,numpr,_) =
- KeyMap.find (glob_prim_constr_key c) !prim_token_key_table in
- match numpr (AnyGlobConstr c) with
- | None -> raise Notation_ops.No_match
- | Some n -> (sc,n)
- with Not_found -> raise Notation_ops.No_match
-
-let uninterp_prim_token_ind_pattern ind args =
- let ref = IndRef ind in
- try
- let k = RefKey (canonical_gr ref) in
- let (sc,numpr,b) = KeyMap.find k !prim_token_key_table in
- if not b then raise Notation_ops.No_match;
- let args' = List.map
- (fun x -> snd (glob_constr_of_closed_cases_pattern x)) args in
- let ref = DAst.make @@ GRef (ref,None) in
- match numpr (AnyGlobConstr (DAst.make @@ GApp (ref,args'))) with
- | None -> raise Notation_ops.No_match
- | Some n -> (sc,n)
- with Not_found -> raise Notation_ops.No_match
+ match glob_prim_constr_key c with
+ | None -> raise Notation_ops.No_match
+ | Some r ->
+ try
+ let (sc,info,_) = GlobRef.Map.find r !prim_token_uninterp_infos in
+ let uninterp = match info with
+ | Uid uid -> Hashtbl.find prim_token_uninterpreters uid
+ | NumeralNotation o -> InnerPrimToken.RawNumUninterp (Numeral.uninterp o)
+ in
+ match InnerPrimToken.do_uninterp uninterp (AnyGlobConstr c) with
+ | None -> raise Notation_ops.No_match
+ | Some n -> (sc,n)
+ with Not_found -> raise Notation_ops.No_match
let uninterp_prim_token_cases_pattern c =
- try
- let k = cases_pattern_key c in
- let (sc,numpr,b) = KeyMap.find k !prim_token_key_table in
- if not b then raise Notation_ops.No_match;
- let na,c = glob_constr_of_closed_cases_pattern c in
- match numpr (AnyGlobConstr c) with
- | None -> raise Notation_ops.No_match
- | Some n -> (na,sc,n)
- with Not_found -> raise Notation_ops.No_match
+ match glob_constr_of_closed_cases_pattern c with
+ | exception Not_found -> raise Notation_ops.No_match
+ | na,c -> let (sc,n) = uninterp_prim_token c in (na,sc,n)
let availability_of_prim_token n printer_scope local_scopes =
let f scope =
- try ignore ((Hashtbl.find prim_token_interpreter_tab scope) n); true
- with Not_found -> false in
+ try
+ let uid = snd (String.Map.find scope !prim_token_interp_infos) in
+ let open InnerPrimToken in
+ match n, uid with
+ | Numeral _, NumeralNotation _ -> true
+ | _, NumeralNotation _ -> false
+ | _, Uid uid ->
+ let interp = Hashtbl.find prim_token_interpreters uid in
+ match n, interp with
+ | Numeral _, (RawNumInterp _ | BigNumInterp _) -> true
+ | String _, StringInterp _ -> true
+ | _ -> false
+ with Not_found -> false
+ in
let scopes = make_current_scopes local_scopes in
Option.map snd (find_without_delimiters f (Some printer_scope,None) scopes)
@@ -803,7 +1266,7 @@ let rec update_scopes cls scl = match cls, scl with
| _, [] -> List.map find_scope_class_opt cls
| cl :: cls, sco :: scl -> update_scope cl sco :: update_scopes cls scl
-let arguments_scope = ref Refmap.empty
+let arguments_scope = ref GlobRef.Map.empty
type arguments_scope_discharge_request =
| ArgsScopeAuto
@@ -813,7 +1276,7 @@ type arguments_scope_discharge_request =
let load_arguments_scope _ (_,(_,r,n,scl,cls)) =
List.iter (Option.iter check_scope) scl;
let initial_stamp = ScopeClassMap.empty in
- arguments_scope := Refmap.add r (scl,cls,initial_stamp) !arguments_scope
+ arguments_scope := GlobRef.Map.add r (scl,cls,initial_stamp) !arguments_scope
let cache_arguments_scope o =
load_arguments_scope 1 o
@@ -894,13 +1357,13 @@ let declare_arguments_scope local r scl =
let find_arguments_scope r =
try
- let (scl,cls,stamp) = Refmap.find r !arguments_scope in
+ let (scl,cls,stamp) = GlobRef.Map.find r !arguments_scope in
let cur_stamp = !scope_class_map in
if stamp == cur_stamp then scl
else
(* Recent changes in the Bind Scope base, we re-compute the scopes *)
let scl' = update_scopes cls scl in
- arguments_scope := Refmap.add r (scl',cls,cur_stamp) !arguments_scope;
+ arguments_scope := GlobRef.Map.add r (scl',cls,cur_stamp) !arguments_scope;
scl'
with Not_found -> []
@@ -1206,16 +1669,19 @@ let pr_visibility prglob = function
let freeze _ =
(!scope_map, !scope_stack, !arguments_scope,
!delimiters_map, !notations_key_table, !scope_class_map,
+ !prim_token_interp_infos, !prim_token_uninterp_infos,
!entry_coercion_map, !entry_has_global_map,
!entry_has_ident_map)
-let unfreeze (scm,scs,asc,dlm,fkm,clsc,coe,globs,ids) =
+let unfreeze (scm,scs,asc,dlm,fkm,clsc,ptii,ptui,coe,globs,ids) =
scope_map := scm;
scope_stack := scs;
delimiters_map := dlm;
arguments_scope := asc;
notations_key_table := fkm;
scope_class_map := clsc;
+ prim_token_interp_infos := ptii;
+ prim_token_uninterp_infos := ptui;
entry_coercion_map := coe;
entry_has_global_map := globs;
entry_has_ident_map := ids
@@ -1224,7 +1690,9 @@ let init () =
init_scope_map ();
delimiters_map := String.Map.empty;
notations_key_table := KeyMap.empty;
- scope_class_map := initial_scope_class_map
+ scope_class_map := initial_scope_class_map;
+ prim_token_interp_infos := String.Map.empty;
+ prim_token_uninterp_infos := GlobRef.Map.empty
let _ =
Summary.declare_summary "symbols"
diff --git a/interp/notation.mli b/interp/notation.mli
index c921606484..734198bbf6 100644
--- a/interp/notation.mli
+++ b/interp/notation.mli
@@ -8,7 +8,6 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
-open Bigint
open Names
open Libnames
open Constrexpr
@@ -42,6 +41,9 @@ type scopes (** = [scope_name list] *)
val declare_scope : scope_name -> unit
+(* To be removed after deprecation phase *)
+val ensure_scope : scope_name -> unit
+
val current_scopes : unit -> scopes
(** Check where a scope is opened or not in a scope list, or in
@@ -75,24 +77,103 @@ val find_delimiters_scope : ?loc:Loc.t -> delimiters -> scope_name
type notation_location = (DirPath.t * DirPath.t) * string
type required_module = full_path * string list
-type cases_pattern_status = bool (** true = use prim token in patterns *)
+type rawnum = Constrexpr.raw_natural_number * Constrexpr.sign
-type 'a prim_token_interpreter =
- ?loc:Loc.t -> 'a -> glob_constr
+(** The unique id string below will be used to refer to a particular
+ registered interpreter/uninterpreter of numeral or string notation.
+ Using the same uid for different (un)interpreters will fail.
+ If at most one interpretation of prim token is used per scope,
+ then the scope name could be used as unique id. *)
-type 'a prim_token_uninterpreter =
- glob_constr list * (any_glob_constr -> 'a option) * cases_pattern_status
+type prim_token_uid = string
-type rawnum = Constrexpr.raw_natural_number * Constrexpr.sign
+type 'a prim_token_interpreter = ?loc:Loc.t -> 'a -> glob_constr
+type 'a prim_token_uninterpreter = any_glob_constr -> 'a option
+
+type 'a prim_token_interpretation =
+ 'a prim_token_interpreter * 'a prim_token_uninterpreter
+
+val register_rawnumeral_interpretation :
+ ?allow_overwrite:bool -> prim_token_uid -> rawnum prim_token_interpretation -> unit
+
+val register_bignumeral_interpretation :
+ ?allow_overwrite:bool -> prim_token_uid -> Bigint.bigint prim_token_interpretation -> unit
+
+val register_string_interpretation :
+ ?allow_overwrite:bool -> prim_token_uid -> string prim_token_interpretation -> unit
+
+(** * Numeral notation *)
+
+type numeral_notation_error =
+ | UnexpectedTerm of Constr.t
+ | UnexpectedNonOptionTerm of Constr.t
+
+exception NumeralNotationError of Environ.env * Evd.evar_map * numeral_notation_error
+
+type numnot_option =
+ | Nop
+ | Warning of raw_natural_number
+ | Abstract of raw_natural_number
+
+type int_ty =
+ { uint : Names.inductive;
+ int : Names.inductive }
+
+type z_pos_ty =
+ { z_ty : Names.inductive;
+ pos_ty : Names.inductive }
+
+type target_kind =
+ | Int of int_ty (* Coq.Init.Decimal.int + uint *)
+ | UInt of Names.inductive (* Coq.Init.Decimal.uint *)
+ | Z of z_pos_ty (* Coq.Numbers.BinNums.Z and positive *)
+
+type option_kind = Option | Direct
+type conversion_kind = target_kind * option_kind
+
+type numeral_notation_obj =
+ { to_kind : conversion_kind;
+ to_ty : GlobRef.t;
+ of_kind : conversion_kind;
+ of_ty : GlobRef.t;
+ num_ty : Libnames.qualid; (* for warnings / error messages *)
+ warning : numnot_option }
+
+type prim_token_interp_info =
+ Uid of prim_token_uid
+ | NumeralNotation of numeral_notation_obj
+
+type prim_token_infos = {
+ pt_local : bool; (** Is this interpretation local? *)
+ pt_scope : scope_name; (** Concerned scope *)
+ pt_interp_info : prim_token_interp_info; (** Unique id "pointing" to (un)interp functions, OR a numeral notation object describing (un)interp functions *)
+ pt_required : required_module; (** Module that should be loaded first *)
+ pt_refs : GlobRef.t list; (** Entry points during uninterpretation *)
+ pt_in_match : bool (** Is this prim token legal in match patterns ? *)
+}
+
+(** Note: most of the time, the [pt_refs] field above will contain
+ inductive constructors (e.g. O and S for nat). But it could also be
+ injection functions such as IZR for reals. *)
+
+(** Activate a prim token interpretation whose unique id and functions
+ have already been registered. *)
-val declare_rawnumeral_interpreter : scope_name -> required_module ->
- rawnum prim_token_interpreter -> rawnum prim_token_uninterpreter -> unit
+val enable_prim_token_interpretation : prim_token_infos -> unit
-val declare_numeral_interpreter : scope_name -> required_module ->
- bigint prim_token_interpreter -> bigint prim_token_uninterpreter -> unit
+(** Compatibility.
+ Avoid the next two functions, they will now store unnecessary
+ objects in the library segment. Instead, combine
+ [register_*_interpretation] and [enable_prim_token_interpretation]
+ (the latter inside a [Mltop.declare_cache_obj]).
+*)
-val declare_string_interpreter : scope_name -> required_module ->
- string prim_token_interpreter -> string prim_token_uninterpreter -> unit
+val declare_numeral_interpreter : ?local:bool -> scope_name -> required_module ->
+ Bigint.bigint prim_token_interpreter ->
+ glob_constr list * Bigint.bigint prim_token_uninterpreter * bool -> unit
+val declare_string_interpreter : ?local:bool -> scope_name -> required_module ->
+ string prim_token_interpreter ->
+ glob_constr list * string prim_token_uninterpreter * bool -> unit
(** Return the [term]/[cases_pattern] bound to a primitive token in a
given scope context*)
@@ -110,8 +191,6 @@ val uninterp_prim_token :
'a glob_constr_g -> scope_name * prim_token
val uninterp_prim_token_cases_pattern :
'a cases_pattern_g -> Name.t * scope_name * prim_token
-val uninterp_prim_token_ind_pattern :
- inductive -> cases_pattern list -> scope_name * prim_token
val availability_of_prim_token :
prim_token -> scope_name -> subscopes -> delimiters option option
diff --git a/interp/reserve.ml b/interp/reserve.ml
index 071248f01f..edbdf1dbba 100644
--- a/interp/reserve.ml
+++ b/interp/reserve.ml
@@ -28,7 +28,7 @@ type key =
(** TODO: share code from Notation *)
let key_compare k1 k2 = match k1, k2 with
-| RefKey gr1, RefKey gr2 -> RefOrdered.compare gr1 gr2
+| RefKey gr1, RefKey gr2 -> GlobRef.Ordered.compare gr1 gr2
| RefKey _, Oth -> -1
| Oth, RefKey _ -> 1
| Oth, Oth -> 0
diff --git a/kernel/.merlin.in b/kernel/.merlin.in
new file mode 100644
index 0000000000..912ff61496
--- /dev/null
+++ b/kernel/.merlin.in
@@ -0,0 +1,8 @@
+FLG -rectypes -thread -safe-string -w +a-4-44-50
+
+S ../clib
+B ../clib
+S ../config
+B ../config
+S ../lib
+B ../lib
diff --git a/kernel/byterun/dune b/kernel/byterun/dune
new file mode 100644
index 0000000000..3a714a8a59
--- /dev/null
+++ b/kernel/byterun/dune
@@ -0,0 +1,10 @@
+(library
+ (name byterun)
+ (synopsis "Coq's Kernel Abstract Reduction Machine [C implementation]")
+ (public_name coq.vm)
+ (c_names coq_fix_code coq_memory coq_values coq_interp))
+
+(rule
+ (targets coq_jumptbl.h)
+ (deps (:h-file coq_instruct.h))
+ (action (run ./make_jumptbl.sh %{h-file} %{targets})))
diff --git a/kernel/byterun/make_jumptbl.sh b/kernel/byterun/make_jumptbl.sh
new file mode 100755
index 0000000000..eacd4daac8
--- /dev/null
+++ b/kernel/byterun/make_jumptbl.sh
@@ -0,0 +1,3 @@
+#!/usr/bin/env bash
+
+sed -n -e '/^ /s/ \([A-Z]\)/ \&\&coq_lbl_\1/gp' -e '/^}/q' ${1} > ${2}
diff --git a/kernel/cClosure.ml b/kernel/cClosure.ml
index ac4c6c52c6..003b49535f 100644
--- a/kernel/cClosure.ml
+++ b/kernel/cClosure.ml
@@ -31,7 +31,6 @@ open Environ
open Esubst
let stats = ref false
-let share = ref true
(* Profiling *)
let beta = ref 0
@@ -266,6 +265,7 @@ type 'a infos_cache = {
i_env : env;
i_sigma : existential -> constr option;
i_rels : (Constr.rel_declaration * lazy_val) Range.t;
+ i_share : bool;
}
and 'a infos = {
@@ -281,7 +281,7 @@ let assoc_defined id env = match Environ.lookup_named id env with
| LocalDef (_, c, _) -> c
| _ -> raise Not_found
-let ref_value_cache ({i_cache = cache} as infos) tab ref =
+let ref_value_cache ({i_cache = cache;_} as infos) tab ref =
try
Some (KeyTable.find tab ref)
with Not_found ->
@@ -289,7 +289,7 @@ let ref_value_cache ({i_cache = cache} as infos) tab ref =
let body =
match ref with
| RelKey n ->
- let open Context.Rel.Declaration in
+ let open! Context.Rel.Declaration in
let i = n - 1 in
let (d, _) =
try Range.get cache.i_rels i
@@ -313,12 +313,13 @@ let ref_value_cache ({i_cache = cache} as infos) tab ref =
let evar_value cache ev =
cache.i_sigma ev
-let create mk_cl flgs env evars =
+let create ~repr ~share flgs env evars =
let cache =
- { i_repr = mk_cl;
+ { i_repr = repr;
i_env = env;
i_sigma = evars;
i_rels = env.env_rel_context.env_rel_map;
+ i_share = share;
}
in { i_flags = flgs; i_cache = cache }
@@ -384,8 +385,8 @@ let mk_red f = {norm=Red;term=f}
(* Could issue a warning if no is still Red, pointing out that we loose
sharing. *)
-let update v1 no t =
- if !share then
+let update ~share v1 no t =
+ if share then
(v1.norm <- no;
v1.term <- t;
v1)
@@ -498,14 +499,16 @@ let compact_stack head stk =
(* Be sure to create a new cell otherwise sharing would be
lost by the update operation *)
let h' = lft_fconstr depth head in
- let _ = update m h'.norm h'.term in
+ (** The stack contains [Zupdate] marks only if in sharing mode *)
+ let _ = update ~share:true m h'.norm h'.term in
strip_rec depth s
| stk -> zshift depth stk in
strip_rec 0 stk
(* Put an update mark in the stack, only if needed *)
-let zupdate m s =
- if !share && begin match m.norm with Red -> true | _ -> false end
+let zupdate info m s =
+ let share = info.i_cache.i_share in
+ if share && begin match m.norm with Red -> true | _ -> false end
then
let s' = compact_stack m s in
let _ = m.term <- FLOCKED in
@@ -548,45 +551,7 @@ let mk_clos_vect env v = match v with
[|mk_clos env v0; mk_clos env v1; mk_clos env v2; mk_clos env v3|]
| v -> Array.Fun1.map mk_clos env v
-(* Translate the head constructor of t from constr to fconstr. This
- function is parameterized by the function to apply on the direct
- subterms.
- Could be used insted of mk_clos. *)
-let mk_clos_deep clos_fun env t =
- match kind t with
- | (Rel _|Ind _|Const _|Construct _|Var _|Meta _ | Sort _) ->
- mk_clos env t
- | Cast (a,k,b) ->
- { norm = Red;
- term = FCast (clos_fun env a, k, clos_fun env b)}
- | App (f,v) ->
- { norm = Red;
- term = FApp (clos_fun env f, Array.Fun1.map clos_fun env v) }
- | Proj (p,c) ->
- { norm = Red;
- term = FProj (p, clos_fun env c) }
- | Case (ci,p,c,v) ->
- { norm = Red;
- term = FCaseT (ci, p, clos_fun env c, v, env) }
- | Fix fx ->
- { norm = Cstr; term = FFix (fx, env) }
- | CoFix cfx ->
- { norm = Cstr; term = FCoFix(cfx,env) }
- | Lambda _ ->
- { norm = Cstr; term = mk_lambda env t }
- | Prod (n,t,c) ->
- { norm = Whnf;
- term = FProd (n, clos_fun env t, clos_fun (subs_lift env) c) }
- | LetIn (n,b,t,c) ->
- { norm = Red;
- term = FLetIn (n, clos_fun env b, clos_fun env t, c, env) }
- | Evar ev ->
- { norm = Red; term = FEvar(ev,env) }
-
-(* A better mk_clos? *)
-let mk_clos2 = mk_clos_deep mk_clos
-
-(* The inverse of mk_clos_deep: move back to constr *)
+(* The inverse of mk_clos: move back to constr *)
let rec to_constr lfts v =
match v.term with
| FRel i -> mkRel (reloc_rel i lfts)
@@ -698,7 +663,8 @@ let rec zip m stk =
| Zshift(n)::s ->
zip (lift_fconstr n m) s
| Zupdate(rf)::s ->
- zip (update rf m.norm m.term) s
+ (** The stack contains [Zupdate] marks only if in sharing mode *)
+ zip (update ~share:true rf m.norm m.term) s
let fapp_stack (m,stk) = zip m stk
@@ -718,7 +684,8 @@ let strip_update_shift_app_red head stk =
strip_rec (Zapp args :: rstk)
{norm=h.norm;term=FApp(h,args)} depth s
| Zupdate(m)::s ->
- strip_rec rstk (update m h.norm h.term) depth s
+ (** The stack contains [Zupdate] marks only if in sharing mode *)
+ strip_rec rstk (update ~share:true m h.norm h.term) depth s
| stk -> (depth,List.rev rstk, stk) in
strip_rec [] head 0 stk
@@ -743,7 +710,8 @@ let get_nth_arg head n stk =
List.rev (if Int.equal n 0 then rstk else (Zapp bef :: rstk)) in
(Some (stk', args.(n)), append_stack aft s')
| Zupdate(m)::s ->
- strip_rec rstk (update m h.norm h.term) n s
+ (** The stack contains [Zupdate] mark only if in sharing mode *)
+ strip_rec rstk (update ~share:true m h.norm h.term) n s
| s -> (None, List.rev rstk @ s) in
strip_rec [] head n stk
@@ -752,7 +720,8 @@ let get_nth_arg head n stk =
let rec get_args n tys f e stk =
match stk with
Zupdate r :: s ->
- let _hd = update r Cstr (FLambda(n,tys,f,e)) in
+ (** The stack contains [Zupdate] mark only if in sharing mode *)
+ let _hd = update ~share:true r Cstr (FLambda(n,tys,f,e)) in
get_args n tys f e s
| Zshift k :: s ->
get_args n tys f (subs_shft (k,e)) s
@@ -830,7 +799,7 @@ let eta_expand_ind_stack env ind m s (f, s') =
arg1..argn ~= (proj1 t...projn t) where t = zip (f,s') *)
let pars = mib.Declarations.mind_nparams in
let right = fapp_stack (f, s') in
- let (depth, args, s) = strip_update_shift_app m s in
+ let (depth, args, _s) = strip_update_shift_app m s in
(** Try to drop the params, might fail on partially applied constructors. *)
let argss = try_drop_parameters depth pars args in
let hstack = Array.map (fun p ->
@@ -889,10 +858,10 @@ let unfold_projection info p =
let rec knh info m stk =
match m.term with
| FLIFT(k,a) -> knh info a (zshift k stk)
- | FCLOS(t,e) -> knht info e t (zupdate m stk)
+ | FCLOS(t,e) -> knht info e t (zupdate info m stk)
| FLOCKED -> assert false
- | FApp(a,b) -> knh info a (append_stack b (zupdate m stk))
- | FCaseT(ci,p,t,br,e) -> knh info t (ZcaseT(ci,p,br,e)::zupdate m stk)
+ | FApp(a,b) -> knh info a (append_stack b (zupdate info m stk))
+ | FCaseT(ci,p,t,br,e) -> knh info t (ZcaseT(ci,p,br,e)::zupdate info m stk)
| FFix(((ri,n),(_,_,_)),_) ->
(match get_nth_arg m ri.(n) stk with
(Some(pars,arg),stk') -> knh info arg (Zfix(m,pars)::stk')
@@ -901,7 +870,7 @@ let rec knh info m stk =
| FProj (p,c) ->
(match unfold_projection info p with
| None -> (m, stk)
- | Some s -> knh info c (s :: zupdate m stk))
+ | Some s -> knh info c (s :: zupdate info m stk))
(* cases where knh stops *)
| (FFlex _|FLetIn _|FConstruct _|FEvar _|
@@ -915,13 +884,18 @@ and knht info e t stk =
knht info e a (append_stack (mk_clos_vect e b) stk)
| Case(ci,p,t,br) ->
knht info e t (ZcaseT(ci, p, br, e)::stk)
- | Fix _ -> knh info (mk_clos2 e t) stk
+ | Fix fx -> knh info { norm = Cstr; term = FFix (fx, e) } stk
| Cast(a,_,_) -> knht info e a stk
| Rel n -> knh info (clos_rel e n) stk
- | Proj (p,c) -> knh info (mk_clos2 e t) stk
- | (Lambda _|Prod _|Construct _|CoFix _|Ind _|
- LetIn _|Const _|Var _|Evar _|Meta _|Sort _) ->
- (mk_clos2 e t, stk)
+ | Proj (p, c) -> knh info { norm = Red; term = FProj (p, mk_clos e c) } stk
+ | (Ind _|Const _|Construct _|Var _|Meta _ | Sort _) -> (mk_clos e t, stk)
+ | CoFix cfx -> { norm = Cstr; term = FCoFix (cfx,e) }, stk
+ | Lambda _ -> { norm = Cstr; term = mk_lambda e t }, stk
+ | Prod (n, t, c) ->
+ { norm = Whnf; term = FProd (n, mk_clos e t, mk_clos (subs_lift e) c) }, stk
+ | LetIn (n,b,t,c) ->
+ { norm = Red; term = FLetIn (n, mk_clos e b, mk_clos e t, c, e) }, stk
+ | Evar ev -> { norm = Red; term = FEvar (ev, e) }, stk
(************************************************************************)
@@ -945,7 +919,7 @@ let rec knr info tab m stk =
(match ref_value_cache info tab (RelKey k) with
Some v -> kni info tab v stk
| None -> (set_norm m; (m,stk)))
- | FConstruct((ind,c),u) ->
+ | FConstruct((_ind,c),_u) ->
let use_match = red_set info.i_flags fMATCH in
let use_fix = red_set info.i_flags fFIX in
if use_match || use_fix then
@@ -1011,7 +985,7 @@ let rec zip_term zfun m stk =
zip_term zfun h s
| Zshift(n)::s ->
zip_term zfun (lift n m) s
- | Zupdate(rf)::s ->
+ | Zupdate(_rf)::s ->
zip_term zfun m s
(* Computes the strong normal form of a term.
@@ -1019,10 +993,11 @@ let rec zip_term zfun m stk =
2- tries to rebuild the term. If a closure still has to be computed,
calls itself recursively. *)
let rec kl info tab m =
+ let share = info.i_cache.i_share in
if is_val m then (incr prune; term_of_fconstr m)
else
let (nm,s) = kni info tab m [] in
- let () = if !share then ignore (fapp_stack (nm, s)) in (* to unlock Zupdates! *)
+ let () = if share then ignore (fapp_stack (nm, s)) in (* to unlock Zupdates! *)
zip_term (kl info tab) (norm_head info tab nm) s
(* no redex: go up for atoms and already normalized terms, go down
@@ -1030,7 +1005,7 @@ let rec kl info tab m =
and norm_head info tab m =
if is_val m then (incr prune; term_of_fconstr m) else
match m.term with
- | FLambda(n,tys,f,e) ->
+ | FLambda(_n,tys,f,e) ->
let (e',rvtys) =
List.fold_left (fun (e,ctxt) (na,ty) ->
(subs_lift e, (na,kl info tab (mk_clos e ty))::ctxt))
@@ -1078,14 +1053,15 @@ let whd_stack infos tab m stk = match m.norm with
knh infos m stk
| Red | Cstr ->
let k = kni infos tab m stk in
- let () = if !share then ignore (fapp_stack k) in (* to unlock Zupdates! *)
+ let () = if infos.i_cache.i_share then ignore (fapp_stack k) in (* to unlock Zupdates! *)
k
(* cache of constants: the body is computed only when needed. *)
type clos_infos = fconstr infos
let create_clos_infos ?(evars=fun _ -> None) flgs env =
- create (fun _ _ c -> inject c) flgs env evars
+ let share = (Environ.typing_flags env).Declarations.share_reduction in
+ create ~share ~repr:(fun _ _ c -> inject c) flgs env evars
let create_tab () = KeyTable.create 17
diff --git a/kernel/cClosure.mli b/kernel/cClosure.mli
index 1e3e7b48ac..6121b3a1ec 100644
--- a/kernel/cClosure.mli
+++ b/kernel/cClosure.mli
@@ -15,7 +15,6 @@ open Esubst
(** Flags for profiling reductions. *)
val stats : bool ref
-val share : bool ref
val with_stats: 'a Lazy.t -> 'a
@@ -106,8 +105,13 @@ type 'a infos = {
i_cache : 'a infos_cache }
val ref_value_cache: 'a infos -> 'a infos_tab -> table_key -> 'a option
-val create: ('a infos -> 'a infos_tab -> constr -> 'a) -> reds -> env ->
- (existential -> constr option) -> 'a infos
+val create:
+ repr:('a infos -> 'a infos_tab -> constr -> 'a) ->
+ share:bool ->
+ reds ->
+ env ->
+ (existential -> constr option) ->
+ 'a infos
val create_tab : unit -> 'a infos_tab
val evar_value : 'a infos_cache -> existential -> constr option
diff --git a/kernel/cbytecodes.ml b/kernel/cbytecodes.ml
index 9a1224aab2..c63795b295 100644
--- a/kernel/cbytecodes.ml
+++ b/kernel/cbytecodes.ml
@@ -15,78 +15,7 @@
(* This file defines the type of bytecode instructions *)
open Names
-open Constr
-
-type tag = int
-
-let accu_tag = 0
-
-let type_atom_tag = 2
-let max_atom_tag = 2
-let proj_tag = 3
-let fix_app_tag = 4
-let switch_tag = 5
-let cofix_tag = 6
-let cofix_evaluated_tag = 7
-
-(* It would be great if OCaml exported this value,
- So fixme if this happens in a new version of OCaml *)
-let last_variant_tag = 245
-
-type structured_constant =
- | Const_sort of Sorts.t
- | Const_ind of inductive
- | Const_b0 of tag
- | Const_bn of tag * structured_constant array
- | Const_univ_level of Univ.Level.t
-
-type reloc_table = (tag * int) array
-
-type annot_switch =
- {ci : case_info; rtbl : reloc_table; tailcall : bool; max_stack_size : int}
-
-let rec eq_structured_constant c1 c2 = match c1, c2 with
-| Const_sort s1, Const_sort s2 -> Sorts.equal s1 s2
-| Const_sort _, _ -> false
-| Const_ind i1, Const_ind i2 -> eq_ind i1 i2
-| Const_ind _, _ -> false
-| Const_b0 t1, Const_b0 t2 -> Int.equal t1 t2
-| Const_b0 _, _ -> false
-| Const_bn (t1, a1), Const_bn (t2, a2) ->
- Int.equal t1 t2 && CArray.equal eq_structured_constant a1 a2
-| Const_bn _, _ -> false
-| Const_univ_level l1 , Const_univ_level l2 -> Univ.Level.equal l1 l2
-| Const_univ_level _ , _ -> false
-
-let rec hash_structured_constant c =
- let open Hashset.Combine in
- match c with
- | Const_sort s -> combinesmall 1 (Sorts.hash s)
- | Const_ind i -> combinesmall 2 (ind_hash i)
- | Const_b0 t -> combinesmall 3 (Int.hash t)
- | Const_bn (t, a) ->
- let fold h c = combine h (hash_structured_constant c) in
- let h = Array.fold_left fold 0 a in
- combinesmall 4 (combine (Int.hash t) h)
- | Const_univ_level l -> combinesmall 5 (Univ.Level.hash l)
-
-let eq_annot_switch asw1 asw2 =
- let eq_ci ci1 ci2 =
- eq_ind ci1.ci_ind ci2.ci_ind &&
- Int.equal ci1.ci_npar ci2.ci_npar &&
- CArray.equal Int.equal ci1.ci_cstr_ndecls ci2.ci_cstr_ndecls
- in
- let eq_rlc (i1, j1) (i2, j2) = Int.equal i1 i2 && Int.equal j1 j2 in
- eq_ci asw1.ci asw2.ci &&
- CArray.equal eq_rlc asw1.rtbl asw2.rtbl &&
- (asw1.tailcall : bool) == asw2.tailcall
-
-let hash_annot_switch asw =
- let open Hashset.Combine in
- let h1 = Constr.case_info_hash asw.ci in
- let h2 = Array.fold_left (fun h (t, i) -> combine3 h t i) 0 asw.rtbl in
- let h3 = if asw.tailcall then 1 else 0 in
- combine3 h1 h2 h3
+open Vmvalues
module Label =
struct
@@ -197,8 +126,8 @@ let compare e1 e2 = match e1, e2 with
| FVrel r1, FVrel r2 -> Int.compare r1 r2
| FVrel _, (FVuniv_var _ | FVevar _) -> -1
| FVuniv_var i1, FVuniv_var i2 -> Int.compare i1 i2
-| FVuniv_var i1, (FVnamed _ | FVrel _) -> 1
-| FVuniv_var i1, FVevar _ -> -1
+| FVuniv_var _i1, (FVnamed _ | FVrel _) -> 1
+| FVuniv_var _i1, FVevar _ -> -1
| FVevar _, (FVnamed _ | FVrel _ | FVuniv_var _) -> 1
| FVevar e1, FVevar e2 -> Evar.compare e1 e2
@@ -232,21 +161,6 @@ type comp_env = {
open Pp
open Util
-let pp_sort s =
- let open Sorts in
- match s with
- | Prop -> str "Prop"
- | Set -> str "Set"
- | Type u -> str "Type@{" ++ Univ.pr_uni u ++ str "}"
-
-let rec pp_struct_const = function
- | Const_sort s -> pp_sort s
- | Const_ind (mind, i) -> MutInd.print mind ++ str"#" ++ int i
- | Const_b0 i -> int i
- | Const_bn (i,t) ->
- int i ++ surround (prvect_with_sep pr_comma pp_struct_const t)
- | Const_univ_level l -> Univ.Level.pr l
-
let pp_lbl lbl = str "L" ++ int lbl
let pp_fv_elem = function
diff --git a/kernel/cbytecodes.mli b/kernel/cbytecodes.mli
index f17a1e657e..9c04c166a2 100644
--- a/kernel/cbytecodes.mli
+++ b/kernel/cbytecodes.mli
@@ -11,41 +11,7 @@
(* $Id$ *)
open Names
-open Constr
-
-type tag = int
-
-val accu_tag : tag
-
-val type_atom_tag : tag
-val max_atom_tag : tag
-val proj_tag : tag
-val fix_app_tag : tag
-val switch_tag : tag
-val cofix_tag : tag
-val cofix_evaluated_tag : tag
-
-val last_variant_tag : tag
-
-type structured_constant =
- | Const_sort of Sorts.t
- | Const_ind of inductive
- | Const_b0 of tag
- | Const_bn of tag * structured_constant array
- | Const_univ_level of Univ.Level.t
-
-val pp_struct_const : structured_constant -> Pp.t
-
-type reloc_table = (tag * int) array
-
-type annot_switch =
- {ci : case_info; rtbl : reloc_table; tailcall : bool; max_stack_size : int}
-
-val eq_structured_constant : structured_constant -> structured_constant -> bool
-val hash_structured_constant : structured_constant -> int
-
-val eq_annot_switch : annot_switch -> annot_switch -> bool
-val hash_annot_switch : annot_switch -> int
+open Vmvalues
module Label :
sig
diff --git a/kernel/cbytegen.ml b/kernel/cbytegen.ml
index e336ea922d..73620ae578 100644
--- a/kernel/cbytegen.ml
+++ b/kernel/cbytegen.ml
@@ -14,6 +14,7 @@
open Util
open Names
+open Vmvalues
open Cbytecodes
open Cemitcodes
open Cinstr
@@ -395,24 +396,24 @@ let init_fun_code () = fun_code := []
(*
If [tag] hits the OCaml limitation for non constant constructors, we switch to
another representation for the remaining constructors:
-[last_variant_tag|tag - last_variant_tag|args]
+[last_variant_tag|tag - Obj.last_non_constant_constructor_tag|args]
-We subtract last_variant_tag for efficiency of match interpretation.
+We subtract Obj.last_non_constant_constructor_tag for efficiency of match interpretation.
*)
let nest_block tag arity cont =
- Kconst (Const_b0 (tag - last_variant_tag)) ::
- Kmakeblock(arity+1, last_variant_tag) :: cont
+ Kconst (Const_b0 (tag - Obj.last_non_constant_constructor_tag)) ::
+ Kmakeblock(arity+1, Obj.last_non_constant_constructor_tag) :: cont
let code_makeblock ~stack_size ~arity ~tag cont =
- if tag < last_variant_tag then
+ if tag < Obj.last_non_constant_constructor_tag then
Kmakeblock(arity, tag) :: cont
else begin
set_max_stack_size (stack_size + 1);
Kpush :: nest_block tag arity cont
end
-let compile_structured_constant cenv sc sz cont =
+let compile_structured_constant _cenv sc sz cont =
set_max_stack_size sz;
Kconst sc :: cont
@@ -490,7 +491,9 @@ let rec compile_lam env cenv lam sz cont =
match lam with
| Lrel(_, i) -> pos_rel i cenv sz :: cont
- | Lval v -> compile_structured_constant cenv v sz cont
+ | Lint i -> compile_structured_constant cenv (Const_b0 i) sz cont
+
+ | Lval v -> compile_structured_constant cenv (Const_val v) sz cont
| Lproj (p,arg) ->
compile_lam env cenv arg sz (Kproj p :: cont)
@@ -531,7 +534,7 @@ let rec compile_lam env cenv lam sz cont =
comp_app compile_structured_constant compile_get_univ cenv
(Const_sort (Sorts.Type u)) (Array.of_list s) sz cont
- | Llet (id,def,body) ->
+ | Llet (_id,def,body) ->
compile_lam env cenv def sz
(Kpush ::
compile_lam env (push_local sz cenv) body (sz+1) (add_pop 1 cont))
@@ -558,7 +561,7 @@ let rec compile_lam env cenv lam sz cont =
| _ -> comp_app (compile_lam env) (compile_lam env) cenv f args sz cont
end
- | Lfix ((rec_args, init), (decl, types, bodies)) ->
+ | Lfix ((rec_args, init), (_decl, types, bodies)) ->
let ndef = Array.length types in
let rfv = ref empty_fv in
let lbl_types = Array.make ndef Label.no in
@@ -591,7 +594,7 @@ let rec compile_lam env cenv lam sz cont =
(Kclosurerec(fv.size,init,lbl_types,lbl_bodies) :: cont)
- | Lcofix(init, (decl,types,bodies)) ->
+ | Lcofix(init, (_decl,types,bodies)) ->
let ndef = Array.length types in
let lbl_types = Array.make ndef Label.no in
let lbl_bodies = Array.make ndef Label.no in
@@ -634,9 +637,9 @@ let rec compile_lam env cenv lam sz cont =
let lbl_consts = Array.make oib.mind_nb_constant Label.no in
let nallblock = oib.mind_nb_args + 1 in (* +1 : accumulate *)
let nconst = Array.length branches.constant_branches in
- let nblock = min nallblock (last_variant_tag + 1) in
+ let nblock = min nallblock (Obj.last_non_constant_constructor_tag + 1) in
let lbl_blocks = Array.make nblock Label.no in
- let neblock = max 0 (nallblock - last_variant_tag) in
+ let neblock = max 0 (nallblock - Obj.last_non_constant_constructor_tag) in
let lbl_eblocks = Array.make neblock Label.no in
let branch1, cont = make_branch cont in
(* Compilation of the return type *)
@@ -662,7 +665,7 @@ let rec compile_lam env cenv lam sz cont =
let lbl_b, code_b =
label_code (
Kpush :: Kfield 0 :: Kswitch(lbl_eblocks, [||]) :: !c) in
- lbl_blocks.(last_variant_tag) <- lbl_b;
+ lbl_blocks.(Obj.last_non_constant_constructor_tag) <- lbl_b;
c := code_b
end;
@@ -684,7 +687,7 @@ let rec compile_lam env cenv lam sz cont =
compile_lam env (push_param arity sz_b cenv)
body (sz_b+arity) (add_pop arity (branch::!c)) in
let code_b =
- if tag < last_variant_tag then begin
+ if tag < Obj.last_non_constant_constructor_tag then begin
set_max_stack_size (sz_b + arity);
Kpushfields arity :: code_b
end
@@ -694,8 +697,8 @@ let rec compile_lam env cenv lam sz cont =
end
in
let lbl_b, code_b = label_code code_b in
- if tag < last_variant_tag then lbl_blocks.(tag) <- lbl_b
- else lbl_eblocks.(tag - last_variant_tag) <- lbl_b;
+ if tag < Obj.last_non_constant_constructor_tag then lbl_blocks.(tag) <- lbl_b
+ else lbl_eblocks.(tag - Obj.last_non_constant_constructor_tag) <- lbl_b;
c := code_b
done;
diff --git a/kernel/cemitcodes.ml b/kernel/cemitcodes.ml
index ca24f9b689..50f5607e31 100644
--- a/kernel/cemitcodes.ml
+++ b/kernel/cemitcodes.ml
@@ -14,6 +14,7 @@
open Names
open Constr
+open Vmvalues
open Cbytecodes
open Copcodes
open Mod_subst
@@ -357,10 +358,9 @@ let rec emit env insns remaining = match insns with
type to_patch = emitcodes * patches * fv
(* Substitution *)
-let rec subst_strcst s sc =
+let subst_strcst s sc =
match sc with
- | Const_sort _ | Const_b0 _ | Const_univ_level _ -> sc
- | Const_bn(tag,args) -> Const_bn(tag,Array.map (subst_strcst s) args)
+ | Const_sort _ | Const_b0 _ | Const_univ_level _ | Const_val _ -> sc
| Const_ind ind -> let kn,i = ind in Const_ind (subst_mind s kn, i)
let subst_reloc s ri =
diff --git a/kernel/cemitcodes.mli b/kernel/cemitcodes.mli
index 9009926bdb..39ddf4a047 100644
--- a/kernel/cemitcodes.mli
+++ b/kernel/cemitcodes.mli
@@ -1,4 +1,5 @@
open Names
+open Vmvalues
open Cbytecodes
type reloc_info =
diff --git a/kernel/cinstr.mli b/kernel/cinstr.mli
index 171ca38830..dca1757b7d 100644
--- a/kernel/cinstr.mli
+++ b/kernel/cinstr.mli
@@ -9,6 +9,7 @@
(************************************************************************)
open Names
open Constr
+open Vmvalues
open Cbytecodes
(** This file defines the lambda code for the bytecode compiler. It has been
@@ -33,10 +34,11 @@ and lambda =
| Lfix of (int array * int) * fix_decl
| Lcofix of int * fix_decl (* must be in eta-expanded form *)
| Lmakeblock of int * lambda array
- | Lval of structured_constant
+ | Lval of structured_values
| Lsort of Sorts.t
| Lind of pinductive
| Lproj of Projection.Repr.t * lambda
+ | Lint of int
| Luint of uint
(* Cofixpoints have to be in eta-expanded form for their call-by-need evaluation
diff --git a/kernel/clambda.ml b/kernel/clambda.ml
index 7c00e40fb0..c21ce22421 100644
--- a/kernel/clambda.ml
+++ b/kernel/clambda.ml
@@ -4,6 +4,7 @@ open Esubst
open Term
open Constr
open Declarations
+open Vmvalues
open Cbytecodes
open Cinstr
open Environ
@@ -106,7 +107,7 @@ let rec pp_lam lam =
| Lval _ -> str "values"
| Lsort s -> pp_sort s
| Lind ((mind,i), _) -> MutInd.print mind ++ str"#" ++ int i
- | Lprim((kn,_u),ar,op,args) ->
+ | Lprim((kn,_u),_ar,_op,args) ->
hov 1
(str "(PRIM " ++ pr_con kn ++ spc() ++
prlist_with_sep spc pp_lam (Array.to_list args) ++
@@ -115,6 +116,8 @@ let rec pp_lam lam =
hov 1
(str "(proj " ++ Projection.Repr.print p ++ str "(" ++ pp_lam arg
++ str ")")
+ | Lint i ->
+ Pp.(str "(int:" ++ int i ++ str ")")
| Luint _ ->
str "(uint)"
@@ -150,7 +153,7 @@ let shift subst = subs_shft (1, subst)
let rec map_lam_with_binders g f n lam =
match lam with
- | Lrel _ | Lvar _ | Lconst _ | Lval _ | Lsort _ | Lind _ -> lam
+ | Lrel _ | Lvar _ | Lconst _ | Lval _ | Lsort _ | Lind _ | Lint _ -> lam
| Levar (evk, args) ->
let args' = Array.Smart.map (f n) args in
if args == args' then lam else Levar (evk, args')
@@ -212,7 +215,7 @@ let rec map_lam_with_binders g f n lam =
let u' = map_uint g f n u in
if u == u' then lam else Luint u'
-and map_uint g f n u =
+and map_uint _g f n u =
match u with
| UintVal _ -> u
| UintDigits(args) ->
@@ -269,7 +272,7 @@ let lam_subst_args subst args =
let can_subst lam =
match lam with
| Lrel _ | Lvar _ | Lconst _
- | Lval _ | Lsort _ | Lind _ | Llam _ -> true
+ | Lval _ | Lsort _ | Lind _ -> true
| _ -> false
let rec simplify subst lam =
@@ -349,7 +352,7 @@ let rec occurrence k kind lam =
if n = k then
if kind then false else raise Not_found
else kind
- | Lvar _ | Lconst _ | Lval _ | Lsort _ | Lind _ -> kind
+ | Lvar _ | Lconst _ | Lval _ | Lsort _ | Lind _ | Lint _ -> kind
| Levar (_, args) ->
occurrence_args k kind args
| Lprod(dom, codom) ->
@@ -419,7 +422,7 @@ let rec remove_let subst lam =
exception TooLargeInductive of Pp.t
let max_nb_const = 0x1000000
-let max_nb_block = 0x1000000 + last_variant_tag - 1
+let max_nb_block = 0x1000000 + Obj.last_non_constant_constructor_tag - 1
let str_max_constructors =
Format.sprintf
@@ -436,23 +439,22 @@ let check_compilable ib =
let is_value lc =
match lc with
- | Lval _ -> true
+ | Lval _ | Lint _ -> true
| _ -> false
let get_value lc =
match lc with
| Lval v -> v
+ | Lint i -> val_of_int i
| _ -> raise Not_found
-let mkConst_b0 n = Lval (Cbytecodes.Const_b0 n)
-
let make_args start _end =
Array.init (start - _end + 1) (fun i -> Lrel (Anonymous, start - i))
(* Translation of constructors *)
let expand_constructor tag nparams arity =
let ids = Array.make (nparams + arity) Anonymous in
- if arity = 0 then mkLlam ids (mkConst_b0 tag)
+ if arity = 0 then mkLlam ids (Lint tag)
else
let args = make_args arity 1 in
Llam(ids, Lmakeblock (tag, args))
@@ -463,15 +465,15 @@ let makeblock tag nparams arity args =
mkLapp (expand_constructor tag nparams arity) args
else
(* The constructor is fully applied *)
- if arity = 0 then mkConst_b0 tag
+ if arity = 0 then Lint tag
else
if Array.for_all is_value args then
- if tag < last_variant_tag then
- Lval(Cbytecodes.Const_bn(tag, Array.map get_value args))
+ if tag < Obj.last_non_constant_constructor_tag then
+ Lval(val_of_block tag (Array.map get_value args))
else
let args = Array.map get_value args in
- let args = Array.append [|Cbytecodes.Const_b0 (tag - last_variant_tag) |] args in
- Lval(Cbytecodes.Const_bn(last_variant_tag, args))
+ let args = Array.append [| val_of_int (tag - Obj.last_non_constant_constructor_tag) |] args in
+ Lval(val_of_block Obj.last_non_constant_constructor_tag args)
else Lmakeblock(tag, args)
@@ -530,7 +532,7 @@ struct
size = 0;
}
- let extend v =
+ let extend (v : 'a t) =
if v.size = Array.length v.elems then
let new_size = min (2*v.size) Sys.max_array_length in
if new_size <= v.size then raise (Invalid_argument "Vect.extend");
@@ -543,12 +545,12 @@ struct
v.elems.(v.size) <- a;
v.size <- v.size + 1
- let popn v n =
+ let popn (v : 'a t) n =
v.size <- max 0 (v.size - n)
let pop v = popn v 1
- let get_last v n =
+ let get_last (v : 'a t) n =
if v.size <= n then raise
(Invalid_argument "Vect.get:index out of bounds");
v.elems.(v.size - n - 1)
@@ -659,11 +661,11 @@ let rec lambda_of_constr env c =
(* translation of the argument *)
let la = lambda_of_constr env a in
- let entry = mkInd ind in
+ let gr = GlobRef.IndRef ind in
let la =
try
Retroknowledge.get_vm_before_match_info env.global_env.retroknowledge
- entry la
+ gr la
with Not_found -> la
in
(* translation of the type *)
@@ -713,7 +715,7 @@ let rec lambda_of_constr env c =
and lambda_of_app env f args =
match Constr.kind f with
- | Const (kn,u as c) ->
+ | Const (kn,_u as c) ->
let kn = get_alias env.global_env kn in
(* spiwack: checks if there is a specific way to compile the constant
if there is not, Not_found is raised, and the function
@@ -721,7 +723,7 @@ and lambda_of_app env f args =
(try
(* We delay the compilation of arguments to avoid an exponential behavior *)
let f = Retroknowledge.get_vm_compiling_info env.global_env.retroknowledge
- (mkConstU (kn,u)) in
+ (GlobRef.ConstRef kn) in
let args = lambda_of_args env 0 args in
f args
with Not_found ->
@@ -734,6 +736,7 @@ and lambda_of_app env f args =
| Construct (c,_) ->
let tag, nparams, arity = Renv.get_construct_info env c in
let nargs = Array.length args in
+ let gr = GlobRef.ConstructRef c in
if Int.equal (nparams + arity) nargs then (* fully applied *)
(* spiwack: *)
(* 1/ tries to compile the constructor in an optimal way,
@@ -748,7 +751,7 @@ and lambda_of_app env f args =
try
Retroknowledge.get_vm_constant_static_info
env.global_env.retroknowledge
- f args
+ gr args
with NotClosed ->
(* 2/ if the arguments are not all closed (this is
expectingly (and it is currently the case) the only
@@ -769,7 +772,7 @@ and lambda_of_app env f args =
let args = lambda_of_args env nparams rargs in
Retroknowledge.get_vm_constant_dynamic_info
env.global_env.retroknowledge
- f args
+ gr args
with Not_found ->
(* 3/ if no special behavior is available, then the compiler
falls back to the normal behavior *)
@@ -782,7 +785,7 @@ and lambda_of_app env f args =
(try
(Retroknowledge.get_vm_constant_dynamic_info
env.global_env.retroknowledge
- f) args
+ gr) args
with Not_found ->
if nparams <= nargs then (* got all parameters *)
makeblock tag 0 arity args
@@ -834,10 +837,11 @@ let dynamic_int31_compilation fc args =
if not fc then raise Not_found else
Luint (UintDigits args)
+let d0 = Lint 0
+let d1 = Lint 1
+
(* We are relying here on the tags of digits constructors *)
let digits_from_uint i =
- let d0 = mkConst_b0 0 in
- let d1 = mkConst_b0 1 in
let digits = Array.make 31 d0 in
for k = 0 to 30 do
if Int.equal ((Uint31.to_int i lsr k) land 1) 1 then
diff --git a/kernel/constr.ml b/kernel/constr.ml
index 9bf743152f..c97969c0e0 100644
--- a/kernel/constr.ml
+++ b/kernel/constr.ml
@@ -237,6 +237,17 @@ let mkVar id = Var id
let kind c = c
+let rec kind_nocast_gen kind c =
+ match kind c with
+ | Cast (c, _, _) -> kind_nocast_gen kind c
+ | App (h, outer) as k ->
+ (match kind_nocast_gen kind h with
+ | App (h, inner) -> App (h, Array.append inner outer)
+ | _ -> k)
+ | k -> k
+
+let kind_nocast c = kind_nocast_gen kind c
+
(* The other way around. We treat specifically smart constructors *)
let of_kind = function
| App (f, a) -> mkApp (f, a)
@@ -360,17 +371,17 @@ let destConst c = match kind c with
(* Destructs an existential variable *)
let destEvar c = match kind c with
- | Evar (kn, a as r) -> r
+ | Evar (_kn, _a as r) -> r
| _ -> raise DestKO
(* Destructs a (co)inductive type named kn *)
let destInd c = match kind c with
- | Ind (kn, a as r) -> r
+ | Ind (_kn, _a as r) -> r
| _ -> raise DestKO
(* Destructs a constructor *)
let destConstruct c = match kind c with
- | Construct (kn, a as r) -> r
+ | Construct (_kn, _a as r) -> r
| _ -> raise DestKO
(* Destructs a term <p>Case c of lc1 | lc2 .. | lcn end *)
@@ -421,12 +432,12 @@ let fold f acc c = match kind c with
| Lambda (_,t,c) -> f (f acc t) c
| LetIn (_,b,t,c) -> f (f (f acc b) t) c
| App (c,l) -> Array.fold_left f (f acc c) l
- | Proj (p,c) -> f acc c
+ | Proj (_p,c) -> f acc c
| Evar (_,l) -> Array.fold_left f acc l
| Case (_,p,c,bl) -> Array.fold_left f (f (f acc p) c) bl
- | Fix (_,(lna,tl,bl)) ->
+ | Fix (_,(_lna,tl,bl)) ->
Array.fold_left2 (fun acc t b -> f (f acc t) b) acc tl bl
- | CoFix (_,(lna,tl,bl)) ->
+ | CoFix (_,(_lna,tl,bl)) ->
Array.fold_left2 (fun acc t b -> f (f acc t) b) acc tl bl
(* [iter f c] iters [f] on the immediate subterms of [c]; it is
@@ -441,7 +452,7 @@ let iter f c = match kind c with
| Lambda (_,t,c) -> f t; f c
| LetIn (_,b,t,c) -> f b; f t; f c
| App (c,l) -> f c; Array.iter f l
- | Proj (p,c) -> f c
+ | Proj (_p,c) -> f c
| Evar (_,l) -> Array.iter f l
| Case (_,p,c,bl) -> f p; f c; Array.iter f bl
| Fix (_,(_,tl,bl)) -> Array.iter f tl; Array.iter f bl
@@ -463,7 +474,7 @@ let iter_with_binders g f n c = match kind c with
| App (c,l) -> f n c; Array.Fun1.iter f n l
| Evar (_,l) -> Array.Fun1.iter f n l
| Case (_,p,c,bl) -> f n p; f n c; Array.Fun1.iter f n bl
- | Proj (p,c) -> f n c
+ | Proj (_p,c) -> f n c
| Fix (_,(_,tl,bl)) ->
Array.Fun1.iter f n tl;
Array.Fun1.iter f (iterate g (Array.length tl) n) bl
@@ -483,19 +494,19 @@ let fold_constr_with_binders g f n acc c =
| (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
| Construct _) -> acc
| Cast (c,_, t) -> f n (f n acc c) t
- | Prod (na,t,c) -> f (g n) (f n acc t) c
- | Lambda (na,t,c) -> f (g n) (f n acc t) c
- | LetIn (na,b,t,c) -> f (g n) (f n (f n acc b) t) c
+ | Prod (_na,t,c) -> f (g n) (f n acc t) c
+ | Lambda (_na,t,c) -> f (g n) (f n acc t) c
+ | LetIn (_na,b,t,c) -> f (g n) (f n (f n acc b) t) c
| App (c,l) -> Array.fold_left (f n) (f n acc c) l
- | Proj (p,c) -> f n acc c
+ | Proj (_p,c) -> f n acc c
| Evar (_,l) -> Array.fold_left (f n) acc l
| Case (_,p,c,bl) -> Array.fold_left (f n) (f n (f n acc p) c) bl
| Fix (_,(lna,tl,bl)) ->
- let n' = CArray.fold_left2 (fun c n t -> g c) n lna tl in
+ let n' = CArray.fold_left2 (fun c _n _t -> g c) n lna tl in
let fd = Array.map2 (fun t b -> (t,b)) tl bl in
Array.fold_left (fun acc (t,b) -> f n' (f n acc t) b) acc fd
| CoFix (_,(lna,tl,bl)) ->
- let n' = CArray.fold_left2 (fun c n t -> g c) n lna tl in
+ let n' = CArray.fold_left2 (fun c _n _t -> g c) n lna tl in
let fd = Array.map2 (fun t b -> (t,b)) tl bl in
Array.fold_left (fun acc (t,b) -> f n' (f n acc t) b) acc fd
@@ -503,7 +514,79 @@ let fold_constr_with_binders g f n acc c =
not recursive and the order with which subterms are processed is
not specified *)
-let map f c = match kind c with
+let rec map_under_context f n d =
+ if n = 0 then f d else
+ match kind d with
+ | LetIn (na,b,t,c) ->
+ let b' = f b in
+ let t' = f t in
+ let c' = map_under_context f (n-1) c in
+ if b' == b && t' == t && c' == c then d
+ else mkLetIn (na,b',t',c')
+ | Lambda (na,t,b) ->
+ let t' = f t in
+ let b' = map_under_context f (n-1) b in
+ if t' == t && b' == b then d
+ else mkLambda (na,t',b')
+ | _ -> CErrors.anomaly (Pp.str "Ill-formed context")
+
+let map_branches f ci bl =
+ let nl = Array.map List.length ci.ci_pp_info.cstr_tags in
+ let bl' = Array.map2 (map_under_context f) nl bl in
+ if Array.for_all2 (==) bl' bl then bl else bl'
+
+let map_return_predicate f ci p =
+ map_under_context f (List.length ci.ci_pp_info.ind_tags) p
+
+let rec map_under_context_with_binders g f l n d =
+ if n = 0 then f l d else
+ match kind d with
+ | LetIn (na,b,t,c) ->
+ let b' = f l b in
+ let t' = f l t in
+ let c' = map_under_context_with_binders g f (g l) (n-1) c in
+ if b' == b && t' == t && c' == c then d
+ else mkLetIn (na,b',t',c')
+ | Lambda (na,t,b) ->
+ let t' = f l t in
+ let b' = map_under_context_with_binders g f (g l) (n-1) b in
+ if t' == t && b' == b then d
+ else mkLambda (na,t',b')
+ | _ -> CErrors.anomaly (Pp.str "Ill-formed context")
+
+let map_branches_with_binders g f l ci bl =
+ let tags = Array.map List.length ci.ci_pp_info.cstr_tags in
+ let bl' = Array.map2 (map_under_context_with_binders g f l) tags bl in
+ if Array.for_all2 (==) bl' bl then bl else bl'
+
+let map_return_predicate_with_binders g f l ci p =
+ map_under_context_with_binders g f l (List.length ci.ci_pp_info.ind_tags) p
+
+let rec map_under_context_with_full_binders g f l n d =
+ if n = 0 then f l d else
+ match kind d with
+ | LetIn (na,b,t,c) ->
+ let b' = f l b in
+ let t' = f l t in
+ let c' = map_under_context_with_full_binders g f (g (Context.Rel.Declaration.LocalDef (na,b,t)) l) (n-1) c in
+ if b' == b && t' == t && c' == c then d
+ else mkLetIn (na,b',t',c')
+ | Lambda (na,t,b) ->
+ let t' = f l t in
+ let b' = map_under_context_with_full_binders g f (g (Context.Rel.Declaration.LocalAssum (na,t)) l) (n-1) b in
+ if t' == t && b' == b then d
+ else mkLambda (na,t',b')
+ | _ -> CErrors.anomaly (Pp.str "Ill-formed context")
+
+let map_branches_with_full_binders g f l ci bl =
+ let tags = Array.map List.length ci.ci_pp_info.cstr_tags in
+ let bl' = Array.map2 (map_under_context_with_full_binders g f l) tags bl in
+ if Array.for_all2 (==) bl' bl then bl else bl'
+
+let map_return_predicate_with_full_binders g f l ci p =
+ map_under_context_with_full_binders g f l (List.length ci.ci_pp_info.ind_tags) p
+
+let map_gen userview f c = match kind c with
| (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
| Construct _) -> c
| Cast (b,k,t) ->
@@ -540,6 +623,12 @@ let map f c = match kind c with
let l' = Array.Smart.map f l in
if l'==l then c
else mkEvar (e, l')
+ | Case (ci,p,b,bl) when userview ->
+ let b' = f b in
+ let p' = map_return_predicate f ci p in
+ let bl' = map_branches f ci bl in
+ if b'==b && p'==p && bl'==bl then c
+ else mkCase (ci, p', b', bl')
| Case (ci,p,b,bl) ->
let b' = f b in
let p' = f p in
@@ -557,6 +646,9 @@ let map f c = match kind c with
if tl'==tl && bl'==bl then c
else mkCoFix (ln,(lna,tl',bl'))
+let map_user_view = map_gen true
+let map = map_gen false
+
(* Like {!map} but with an accumulator. *)
let fold_map f accu c = match kind c with
@@ -674,10 +766,10 @@ let map_with_binders g f l c0 = match kind c0 with
let bl' = Array.Fun1.Smart.map f l' bl in
mkCoFix (ln,(lna,tl',bl'))
-type instance_compare_fn = GlobRef.t -> int ->
- Univ.Instance.t -> Univ.Instance.t -> bool
+type 'univs instance_compare_fn = GlobRef.t -> int ->
+ 'univs -> 'univs -> bool
-type constr_compare_fn = int -> constr -> constr -> bool
+type 'constr constr_compare_fn = int -> 'constr -> 'constr -> bool
(* [compare_head_gen_evar k1 k2 u s e eq leq c1 c2] compare [c1] and
[c2] (using [k1] to expose the structure of [c1] and [k2] to expose
@@ -691,19 +783,16 @@ type constr_compare_fn = int -> constr -> constr -> bool
calls to {!Array.equal_norefl}). *)
let compare_head_gen_leq_with kind1 kind2 leq_universes leq_sorts eq leq nargs t1 t2 =
- match kind1 t1, kind2 t2 with
+ match kind_nocast_gen kind1 t1, kind_nocast_gen kind2 t2 with
+ | Cast _, _ | _, Cast _ -> assert false (* kind_nocast *)
| Rel n1, Rel n2 -> Int.equal n1 n2
| Meta m1, Meta m2 -> Int.equal m1 m2
| Var id1, Var id2 -> Id.equal id1 id2
| Sort s1, Sort s2 -> leq_sorts s1 s2
- | Cast (c1, _, _), _ -> leq nargs c1 t2
- | _, Cast (c2, _, _) -> leq nargs t1 c2
| Prod (_,t1,c1), Prod (_,t2,c2) -> eq 0 t1 t2 && leq 0 c1 c2
| Lambda (_,t1,c1), Lambda (_,t2,c2) -> eq 0 t1 t2 && eq 0 c1 c2
| LetIn (_,b1,t1,c1), LetIn (_,b2,t2,c2) -> eq 0 b1 b2 && eq 0 t1 t2 && leq nargs c1 c2
(* Why do we suddenly make a special case for Cast here? *)
- | App (Cast (c1, _, _), l1), _ -> leq nargs (mkApp (c1, l1)) t2
- | _, App (Cast (c2, _, _), l2) -> leq nargs t1 (mkApp (c2, l2))
| App (c1, l1), App (c2, l2) ->
let len = Array.length l1 in
Int.equal len (Array.length l2) &&
@@ -882,11 +971,11 @@ let constr_ord_int f t1 t2 =
| LetIn _, _ -> -1 | _, LetIn _ -> 1
| App (c1,l1), App (c2,l2) -> (f =? (Array.compare f)) c1 c2 l1 l2
| App _, _ -> -1 | _, App _ -> 1
- | Const (c1,u1), Const (c2,u2) -> Constant.CanOrd.compare c1 c2
+ | Const (c1,_u1), Const (c2,_u2) -> Constant.CanOrd.compare c1 c2
| Const _, _ -> -1 | _, Const _ -> 1
- | Ind (ind1, u1), Ind (ind2, u2) -> ind_ord ind1 ind2
+ | Ind (ind1, _u1), Ind (ind2, _u2) -> ind_ord ind1 ind2
| Ind _, _ -> -1 | _, Ind _ -> 1
- | Construct (ct1,u1), Construct (ct2,u2) -> constructor_ord ct1 ct2
+ | Construct (ct1,_u1), Construct (ct2,_u2) -> constructor_ord ct1 ct2
| Construct _, _ -> -1 | _, Construct _ -> 1
| Case (_,p1,c1,bl1), Case (_,p2,c2,bl2) ->
((f =? f) ==? (Array.compare f)) p1 p2 c1 c2 bl1 bl2
@@ -1145,9 +1234,9 @@ let rec hash t =
combinesmall 11 (combine (constructor_hash c) (Instance.hash u))
| Case (_ , p, c, bl) ->
combinesmall 12 (combine3 (hash c) (hash p) (hash_term_array bl))
- | Fix (ln ,(_, tl, bl)) ->
+ | Fix (_ln ,(_, tl, bl)) ->
combinesmall 13 (combine (hash_term_array bl) (hash_term_array tl))
- | CoFix(ln, (_, tl, bl)) ->
+ | CoFix(_ln, (_, tl, bl)) ->
combinesmall 14 (combine (hash_term_array bl) (hash_term_array tl))
| Meta n -> combinesmall 15 n
| Rel n -> combinesmall 16 n
diff --git a/kernel/constr.mli b/kernel/constr.mli
index 70acf19328..2efdae007c 100644
--- a/kernel/constr.mli
+++ b/kernel/constr.mli
@@ -241,6 +241,11 @@ type ('constr, 'types, 'sort, 'univs) kind_of_term =
val kind : constr -> (constr, types, Sorts.t, Univ.Instance.t) kind_of_term
val of_kind : (constr, types, Sorts.t, Univ.Instance.t) kind_of_term -> constr
+val kind_nocast_gen : ('v -> ('v, 'v, 'sort, 'univs) kind_of_term) ->
+ ('v -> ('v, 'v, 'sort, 'univs) kind_of_term)
+
+val kind_nocast : constr -> (constr, types, Sorts.t, Univ.Instance.t) kind_of_term
+
(** {6 Simple case analysis} *)
val isRel : constr -> bool
val isRelN : int -> constr -> bool
@@ -285,8 +290,8 @@ val destMeta : constr -> metavariable
(** Destructs a variable *)
val destVar : constr -> Id.t
-(** Destructs a sort. [is_Prop] recognizes the sort {% \textsf{%}Prop{% }%}, whether
- [isprop] recognizes both {% \textsf{%}Prop{% }%} and {% \textsf{%}Set{% }%}. *)
+(** Destructs a sort. [is_Prop] recognizes the sort [Prop], whether
+ [isprop] recognizes both [Prop] and [Set]. *)
val destSort : constr -> Sorts.t
(** Destructs a casted term *)
@@ -381,6 +386,85 @@ type rel_context = rel_declaration list
type named_context = named_declaration list
type compacted_context = compacted_declaration list
+(** {6 Functionals working on expressions canonically abstracted over
+ a local context (possibly with let-ins)} *)
+
+(** [map_under_context f l c] maps [f] on the immediate subterms of a
+ term abstracted over a context of length [n] (local definitions
+ are counted) *)
+
+val map_under_context : (constr -> constr) -> int -> constr -> constr
+
+(** [map_branches f br] maps [f] on the immediate subterms of an array
+ of "match" branches [br] in canonical eta-let-expanded form; it is
+ not recursive and the order with which subterms are processed is
+ not specified; it preserves sharing; the immediate subterms are the
+ types and possibly terms occurring in the context of each branch as
+ well as the body of each branch *)
+
+val map_branches : (constr -> constr) -> case_info -> constr array -> constr array
+
+(** [map_return_predicate f p] maps [f] on the immediate subterms of a
+ return predicate of a "match" in canonical eta-let-expanded form;
+ it is not recursive and the order with which subterms are processed
+ is not specified; it preserves sharing; the immediate subterms are
+ the types and possibly terms occurring in the context of each
+ branch as well as the body of the predicate *)
+
+val map_return_predicate : (constr -> constr) -> case_info -> constr -> constr
+
+(** [map_under_context_with_binders g f n l c] maps [f] on the
+ immediate subterms of a term abstracted over a context of length
+ [n] (local definitions are counted); it preserves sharing; it
+ carries an extra data [n] (typically a lift index) which is
+ processed by [g] (which typically add 1 to [n]) at each binder
+ traversal *)
+
+val map_under_context_with_binders : ('a -> 'a) -> ('a -> constr -> constr) -> 'a -> int -> constr -> constr
+
+(** [map_branches_with_binders f br] maps [f] on the immediate
+ subterms of an array of "match" branches [br] in canonical
+ eta-let-expanded form; it carries an extra data [n] (typically a
+ lift index) which is processed by [g] (which typically adds 1 to
+ [n]) at each binder traversal; it is not recursive and the order
+ with which subterms are processed is not specified; it preserves
+ sharing; the immediate subterms are the types and possibly terms
+ occurring in the context of the branch as well as the body of the
+ branch *)
+
+val map_branches_with_binders : ('a -> 'a) -> ('a -> constr -> constr) -> 'a -> case_info -> constr array -> constr array
+
+(** [map_return_predicate_with_binders f p] maps [f] on the immediate
+ subterms of a return predicate of a "match" in canonical
+ eta-let-expanded form; it carries an extra data [n] (typically a
+ lift index) which is processed by [g] (which typically adds 1 to
+ [n]) at each binder traversal; it is not recursive and the order
+ with which subterms are processed is not specified; it preserves
+ sharing; the immediate subterms are the types and possibly terms
+ occurring in the context of each branch as well as the body of the
+ predicate *)
+
+val map_return_predicate_with_binders : ('a -> 'a) -> ('a -> constr -> constr) -> 'a -> case_info -> constr -> constr
+
+(** [map_under_context_with_full_binders g f n l c] is similar to
+ [map_under_context_with_binders] except that [g] takes also a full
+ binder as argument and that only the number of binders (and not
+ their signature) is required *)
+
+val map_under_context_with_full_binders : ((constr, constr) Context.Rel.Declaration.pt -> 'a -> 'a) -> ('a -> constr -> constr) -> 'a -> int -> constr -> constr
+
+(** [map_branches_with_full_binders g f l br] is equivalent to
+ [map_branches_with_binders] but using
+ [map_under_context_with_full_binders] *)
+
+val map_branches_with_full_binders : ((constr, constr) Context.Rel.Declaration.pt -> 'a -> 'a) -> ('a -> constr -> constr) -> 'a -> case_info -> constr array -> constr array
+
+(** [map_return_predicate_with_full_binders g f l p] is equivalent to
+ [map_return_predicate_with_binders] but using
+ [map_under_context_with_full_binders] *)
+
+val map_return_predicate_with_full_binders : ((constr, constr) Context.Rel.Declaration.pt -> 'a -> 'a) -> ('a -> constr -> constr) -> 'a -> case_info -> constr -> constr
+
(** {6 Functionals working on the immediate subterm of a construction } *)
(** [fold f acc c] folds [f] on the immediate subterms of [c]
@@ -395,6 +479,13 @@ val fold : ('a -> constr -> 'a) -> 'a -> constr -> 'a
val map : (constr -> constr) -> constr -> constr
+(** [map_user_view f c] maps [f] on the immediate subterms of [c]; it
+ differs from [map f c] in that the typing context and body of the
+ return predicate and of the branches of a [match] are considered as
+ immediate subterm of a [match] *)
+
+val map_user_view : (constr -> constr) -> constr -> constr
+
(** Like {!map}, but also has an additional accumulator. *)
val fold_map : ('a -> constr -> 'a * constr) -> 'a -> constr -> 'a * constr
@@ -432,50 +523,50 @@ val iter_with_binders :
val fold_constr_with_binders :
('a -> 'a) -> ('a -> 'b -> constr -> 'b) -> 'a -> 'b -> constr -> 'b
-type constr_compare_fn = int -> constr -> constr -> bool
+type 'constr constr_compare_fn = int -> 'constr -> 'constr -> bool
(** [compare_head f c1 c2] compare [c1] and [c2] using [f] to compare
the immediate subterms of [c1] of [c2] if needed; Cast's, binders
name and Cases annotations are not taken into account *)
-val compare_head : constr_compare_fn -> constr_compare_fn
+val compare_head : constr constr_compare_fn -> constr constr_compare_fn
(** Convert a global reference applied to 2 instances. The int says
how many arguments are given (as we can only use cumulativity for
fully applied inductives/constructors) .*)
-type instance_compare_fn = GlobRef.t -> int ->
- Univ.Instance.t -> Univ.Instance.t -> bool
+type 'univs instance_compare_fn = GlobRef.t -> int ->
+ 'univs -> 'univs -> bool
(** [compare_head_gen u s f c1 c2] compare [c1] and [c2] using [f] to
compare the immediate subterms of [c1] of [c2] if needed, [u] to
compare universe instances, [s] to compare sorts; Cast's, binders
name and Cases annotations are not taken into account *)
-val compare_head_gen : instance_compare_fn ->
+val compare_head_gen : Univ.Instance.t instance_compare_fn ->
(Sorts.t -> Sorts.t -> bool) ->
- constr_compare_fn ->
- constr_compare_fn
+ constr constr_compare_fn ->
+ constr constr_compare_fn
val compare_head_gen_leq_with :
- (constr -> (constr, types, Sorts.t, Univ.Instance.t) kind_of_term) ->
- (constr -> (constr, types, Sorts.t, Univ.Instance.t) kind_of_term) ->
- instance_compare_fn ->
- (Sorts.t -> Sorts.t -> bool) ->
- constr_compare_fn ->
- constr_compare_fn ->
- constr_compare_fn
+ ('v -> ('v, 'v, 'sort, 'univs) kind_of_term) ->
+ ('v -> ('v, 'v, 'sort, 'univs) kind_of_term) ->
+ 'univs instance_compare_fn ->
+ ('sort -> 'sort -> bool) ->
+ 'v constr_compare_fn ->
+ 'v constr_compare_fn ->
+ 'v constr_compare_fn
(** [compare_head_gen_with k1 k2 u s f c1 c2] compares [c1] and [c2]
like [compare_head_gen u s f c1 c2], except that [k1] (resp. [k2])
is used,rather than {!kind}, to expose the immediate subterms of
[c1] (resp. [c2]). *)
val compare_head_gen_with :
- (constr -> (constr, types, Sorts.t, Univ.Instance.t) kind_of_term) ->
- (constr -> (constr, types, Sorts.t, Univ.Instance.t) kind_of_term) ->
- instance_compare_fn ->
- (Sorts.t -> Sorts.t -> bool) ->
- constr_compare_fn ->
- constr_compare_fn
+ ('v -> ('v, 'v, 'sort, 'univs) kind_of_term) ->
+ ('v -> ('v, 'v, 'sort, 'univs) kind_of_term) ->
+ 'univs instance_compare_fn ->
+ ('sort -> 'sort -> bool) ->
+ 'v constr_compare_fn ->
+ 'v constr_compare_fn
(** [compare_head_gen_leq u s f fle c1 c2] compare [c1] and [c2] using
[f] to compare the immediate subterms of [c1] of [c2] for
@@ -484,11 +575,11 @@ val compare_head_gen_with :
[s] to compare sorts for for subtyping; Cast's, binders name and
Cases annotations are not taken into account *)
-val compare_head_gen_leq : instance_compare_fn ->
+val compare_head_gen_leq : Univ.Instance.t instance_compare_fn ->
(Sorts.t -> Sorts.t -> bool) ->
- constr_compare_fn ->
- constr_compare_fn ->
- constr_compare_fn
+ constr constr_compare_fn ->
+ constr constr_compare_fn ->
+ constr constr_compare_fn
(** {6 Hashconsing} *)
diff --git a/kernel/context.ml b/kernel/context.ml
index 4a7204b75c..3d98381fbb 100644
--- a/kernel/context.ml
+++ b/kernel/context.ml
@@ -142,8 +142,8 @@ struct
(** Reduce all terms in a given declaration to a single value. *)
let fold_constr f decl acc =
match decl with
- | LocalAssum (n,ty) -> f ty acc
- | LocalDef (n,v,ty) -> f ty (f v acc)
+ | LocalAssum (_n,ty) -> f ty acc
+ | LocalDef (_n,v,ty) -> f ty (f v acc)
let to_tuple = function
| LocalAssum (na, ty) -> na, None, ty
@@ -151,7 +151,7 @@ struct
let drop_body = function
| LocalAssum _ as d -> d
- | LocalDef (na, v, ty) -> LocalAssum (na, ty)
+ | LocalDef (na, _v, ty) -> LocalAssum (na, ty)
end
@@ -356,7 +356,7 @@ struct
let drop_body = function
| LocalAssum _ as d -> d
- | LocalDef (id, v, ty) -> LocalAssum (id, ty)
+ | LocalDef (id, _v, ty) -> LocalAssum (id, ty)
let of_rel_decl f = function
| Rel.Declaration.LocalAssum (na,t) ->
diff --git a/kernel/conv_oracle.ml b/kernel/conv_oracle.ml
index 7ef63c1860..c74f2ab318 100644
--- a/kernel/conv_oracle.ml
+++ b/kernel/conv_oracle.ml
@@ -42,7 +42,7 @@ let empty = {
cst_trstate = Cpred.full;
}
-let get_strategy { var_opacity; cst_opacity } f = function
+let get_strategy { var_opacity; cst_opacity; _ } f = function
| VarKey id ->
(try Id.Map.find id var_opacity
with Not_found -> default)
@@ -51,7 +51,7 @@ let get_strategy { var_opacity; cst_opacity } f = function
with Not_found -> default)
| RelKey _ -> Expand
-let set_strategy ({ var_opacity; cst_opacity } as oracle) k l =
+let set_strategy ({ var_opacity; cst_opacity; _ } as oracle) k l =
match k with
| VarKey id ->
let var_opacity =
@@ -75,13 +75,13 @@ let set_strategy ({ var_opacity; cst_opacity } as oracle) k l =
{ oracle with cst_opacity; cst_trstate; }
| RelKey _ -> CErrors.user_err Pp.(str "set_strategy: RelKey")
-let fold_strategy f { var_opacity; cst_opacity; } accu =
+let fold_strategy f { var_opacity; cst_opacity; _ } accu =
let fvar id lvl accu = f (VarKey id) lvl accu in
let fcst cst lvl accu = f (ConstKey cst) lvl accu in
let accu = Id.Map.fold fvar var_opacity accu in
Cmap.fold fcst cst_opacity accu
-let get_transp_state { var_trstate; cst_trstate } = (var_trstate, cst_trstate)
+let get_transp_state { var_trstate; cst_trstate; _ } = (var_trstate, cst_trstate)
(* Unfold the first constant only if it is "more transparent" than the
second one. In case of tie, use the recommended default. *)
diff --git a/kernel/cooking.ml b/kernel/cooking.ml
index c06358054e..b361e36bbf 100644
--- a/kernel/cooking.ml
+++ b/kernel/cooking.ml
@@ -24,6 +24,7 @@ open Declarations
open Univ
module NamedDecl = Context.Named.Declaration
+module RelDecl = Context.Rel.Declaration
(*s Cooking the constants. *)
@@ -90,7 +91,7 @@ let update_case_info cache ci modlist =
try
let ind, n =
match share cache (IndRef ci.ci_ind) modlist with
- | (IndRef f,(u,l)) -> (f, Array.length l)
+ | (IndRef f,(_u,l)) -> (f, Array.length l)
| _ -> assert false in
{ ci with ci_ind = ind; ci_npar = ci.ci_npar + n }
with Not_found ->
@@ -140,11 +141,31 @@ let expmod_constr cache modlist c =
if is_empty_modlist modlist then c
else substrec c
-let abstract_constant_type =
- List.fold_left (fun c d -> mkNamedProd_wo_LetIn d c)
+(** Transforms a named context into a rel context. Also returns the list of
+ variables [id1 ... idn] that need to be replaced by [Rel 1 ... Rel n] to
+ abstract a term that lived in that context. *)
+let abstract_context hyps =
+ let fold decl (ctx, subst) =
+ let id, decl = match decl with
+ | NamedDecl.LocalDef (id, b, t) ->
+ let b = Vars.subst_vars subst b in
+ let t = Vars.subst_vars subst t in
+ id, RelDecl.LocalDef (Name id, b, t)
+ | NamedDecl.LocalAssum (id, t) ->
+ let t = Vars.subst_vars subst t in
+ id, RelDecl.LocalAssum (Name id, t)
+ in
+ (decl :: ctx, id :: subst)
+ in
+ Context.Named.fold_outside fold hyps ~init:([], [])
+
+let abstract_constant_type t (hyps, subst) =
+ let t = Vars.subst_vars subst t in
+ List.fold_left (fun c d -> mkProd_wo_LetIn d c) t hyps
-let abstract_constant_body =
- List.fold_left (fun c d -> mkNamedLambda_or_LetIn d c)
+let abstract_constant_body c (hyps, subst) =
+ let c = Vars.subst_vars subst c in
+ it_mkLambda_or_LetIn c hyps
type recipe = { from : constant_body; info : Opaqueproof.cooking_info }
type inline = bool
@@ -173,6 +194,7 @@ let cook_constr { Opaqueproof.modlist ; abstract = (vars, subst, _) } c =
let cache = RefTable.create 13 in
let expmod = expmod_constr_subst cache modlist subst in
let hyps = Context.Named.map expmod vars in
+ let hyps = abstract_context hyps in
abstract_constant_body (expmod c) hyps
let lift_univs cb subst auctx0 =
@@ -207,12 +229,13 @@ let cook_constant ~hcons { from = cb; info } =
let abstract, usubst, abs_ctx = abstract in
let usubst, univs = lift_univs cb usubst abs_ctx in
let expmod = expmod_constr_subst cache modlist usubst in
- let hyps = Context.Named.map expmod abstract in
+ let hyps0 = Context.Named.map expmod abstract in
+ let hyps = abstract_context hyps0 in
let map c =
let c = abstract_constant_body (expmod c) hyps in
if hcons then Constr.hcons c else c
in
- let body = on_body modlist (hyps, usubst, abs_ctx)
+ let body = on_body modlist (hyps0, usubst, abs_ctx)
map
cb.const_body
in
@@ -220,7 +243,7 @@ let cook_constant ~hcons { from = cb; info } =
Context.Named.fold_outside (fun decl hyps ->
List.filter (fun decl' -> not (Id.equal (NamedDecl.get_id decl) (NamedDecl.get_id decl')))
hyps)
- hyps ~init:cb.const_hyps in
+ hyps0 ~init:cb.const_hyps in
let typ = abstract_constant_type (expmod cb.const_type) hyps in
{
cook_body = body;
diff --git a/kernel/csymtable.ml b/kernel/csymtable.ml
index bb9231d000..8bef6aec42 100644
--- a/kernel/csymtable.ml
+++ b/kernel/csymtable.ml
@@ -173,7 +173,7 @@ and slot_for_fv env fv =
| Some (v, _) -> v
end
| FVevar evk -> val_of_evar evk
- | FVuniv_var idu ->
+ | FVuniv_var _idu ->
assert false
and eval_to_patch env (buff,pl,fv) =
@@ -192,5 +192,5 @@ and val_of_constr env c =
| Some v -> eval_to_patch env (to_memory v)
| None -> assert false
-let set_transparent_const kn = () (* !?! *)
-let set_opaque_const kn = () (* !?! *)
+let set_transparent_const _kn = () (* !?! *)
+let set_opaque_const _kn = () (* !?! *)
diff --git a/kernel/declarations.ml b/kernel/declarations.ml
index 0811eb72fd..61fcb4832a 100644
--- a/kernel/declarations.ml
+++ b/kernel/declarations.ml
@@ -65,6 +65,7 @@ type typing_flags = {
points are assumed to be total. *)
check_universes : bool; (** If [false] universe constraints are not checked *)
conv_oracle : Conv_oracle.oracle; (** Unfolding strategies for conversion *)
+ share_reduction : bool; (** Use by-need reduction algorithm *)
}
(* some contraints are in constant_constraints, some other may be in
@@ -163,7 +164,7 @@ type one_inductive_body = {
mind_nb_args : int; (** number of no constant constructor *)
- mind_reloc_tbl : Cbytecodes.reloc_table;
+ mind_reloc_tbl : Vmvalues.reloc_table;
}
type abstract_inductive_universes =
diff --git a/kernel/declareops.ml b/kernel/declareops.ml
index bbe4bc0dcb..d995786d97 100644
--- a/kernel/declareops.ml
+++ b/kernel/declareops.ml
@@ -21,6 +21,7 @@ let safe_flags oracle = {
check_guarded = true;
check_universes = true;
conv_oracle = oracle;
+ share_reduction = true;
}
(** {6 Arities } *)
@@ -180,7 +181,7 @@ let subst_regular_ind_arity sub s =
if uar' == s.mind_user_arity then s
else { mind_user_arity = uar'; mind_sort = s.mind_sort }
-let subst_template_ind_arity sub s = s
+let subst_template_ind_arity _sub s = s
(* FIXME records *)
let subst_ind_arity =
@@ -239,14 +240,14 @@ let inductive_polymorphic_context mib =
let inductive_is_polymorphic mib =
match mib.mind_universes with
| Monomorphic_ind _ -> false
- | Polymorphic_ind ctx -> true
- | Cumulative_ind cumi -> true
+ | Polymorphic_ind _ctx -> true
+ | Cumulative_ind _cumi -> true
let inductive_is_cumulative mib =
match mib.mind_universes with
| Monomorphic_ind _ -> false
- | Polymorphic_ind ctx -> false
- | Cumulative_ind cumi -> true
+ | Polymorphic_ind _ctx -> false
+ | Cumulative_ind _cumi -> true
let inductive_make_projection ind mib ~proj_arg =
match mib.mind_record with
@@ -305,13 +306,6 @@ let hcons_mind mib =
mind_params_ctxt = hcons_rel_context mib.mind_params_ctxt;
mind_universes = hcons_mind_universes mib.mind_universes }
-(** {6 Stm machinery } *)
-
-let string_of_side_effect { Entries.eff } = match eff with
- | Entries.SEsubproof (c,_,_) -> "P(" ^ Names.Constant.to_string c ^ ")"
- | Entries.SEscheme (cl,_) ->
- "S(" ^ String.concat ", " (List.map (fun (_,c,_,_) -> Names.Constant.to_string c) cl) ^ ")"
-
(** Hashconsing of modules *)
let hcons_functorize hty he hself f = match f with
diff --git a/kernel/declareops.mli b/kernel/declareops.mli
index f91e69807f..35490ceef9 100644
--- a/kernel/declareops.mli
+++ b/kernel/declareops.mli
@@ -11,7 +11,6 @@
open Declarations
open Mod_subst
open Univ
-open Entries
(** Operations concerning types in [Declarations] :
[constant_body], [mutual_inductive_body], [module_body] ... *)
@@ -39,10 +38,6 @@ val constant_is_polymorphic : constant_body -> bool
val is_opaque : constant_body -> bool
-(** Side effects *)
-
-val string_of_side_effect : side_effect -> string
-
(** {6 Inductive types} *)
val eq_recarg : recarg -> recarg -> bool
diff --git a/kernel/dune b/kernel/dune
new file mode 100644
index 0000000000..a503238907
--- /dev/null
+++ b/kernel/dune
@@ -0,0 +1,20 @@
+(library
+ (name kernel)
+ (synopsis "The Coq Kernel")
+ (public_name coq.kernel)
+ (wrapped false)
+ (modules_without_implementation cinstr nativeinstr)
+ (libraries clib config lib byterun))
+
+(rule
+ (targets copcodes.ml)
+ (deps (:h-file byterun/coq_instruct.h) make-opcodes)
+ (action (run ./make_opcodes.sh %{h-file} %{targets})))
+
+(documentation
+ (package coq))
+
+; In dev profile, we check the kernel against a more strict set of
+; warnings.
+(env
+ (dev (flags :standard -w +a-4-44-50)))
diff --git a/kernel/entries.ml b/kernel/entries.ml
index 40873bea76..94248ad26b 100644
--- a/kernel/entries.ml
+++ b/kernel/entries.ml
@@ -120,11 +120,14 @@ type seff_env =
Same as the constant_body's but not in an ephemeron *)
| `Opaque of Constr.t * Univ.ContextSet.t ]
-type side_eff =
- | SEsubproof of Constant.t * Declarations.constant_body * seff_env
- | SEscheme of (inductive * Constant.t * Declarations.constant_body * seff_env) list * string
-
-type side_effect = {
- from_env : Declarations.structure_body CEphemeron.key;
- eff : side_eff;
+(** Not used by the kernel. *)
+type side_effect_role =
+ | Subproof
+ | Schema of inductive * string
+
+type side_eff = {
+ seff_constant : Constant.t;
+ seff_body : Declarations.constant_body;
+ seff_env : seff_env;
+ seff_role : side_effect_role;
}
diff --git a/kernel/environ.ml b/kernel/environ.ml
index e7efa5e2c9..dffcd70282 100644
--- a/kernel/environ.ml
+++ b/kernel/environ.ml
@@ -296,12 +296,12 @@ let eq_named_context_val c1 c2 =
(* A local const is evaluable if it is defined *)
-open Context.Named.Declaration
-
let named_type id env =
+ let open Context.Named.Declaration in
get_type (lookup_named id env)
let named_body id env =
+ let open Context.Named.Declaration in
get_value (lookup_named id env)
let evaluable_named id env =
@@ -333,7 +333,7 @@ let fold_named_context f env ~init =
let rec fold_right env =
match match_named_context_val env.env_named_context with
| None -> init
- | Some (d, v, rem) ->
+ | Some (d, _v, rem) ->
let env =
reset_with_named_context rem env in
f env d (fold_right env)
@@ -365,8 +365,7 @@ let push_constraints_to_env (_,univs) env =
let add_universes strict ctx g =
let g = Array.fold_left
- (* Be lenient, module typing reintroduces universes and constraints due to includes *)
- (fun g v -> try UGraph.add_universe v strict g with UGraph.AlreadyDeclared -> g)
+ (fun g v -> UGraph.add_universe v strict g)
g (Univ.Instance.to_array (Univ.UContext.instance ctx))
in
UGraph.merge_constraints (Univ.UContext.constraints ctx) g
@@ -376,6 +375,7 @@ let push_context ?(strict=false) ctx env =
let add_universes_set strict ctx g =
let g = Univ.LSet.fold
+ (* Be lenient, module typing reintroduces universes and constraints due to includes *)
(fun v g -> try UGraph.add_universe v strict g with UGraph.AlreadyDeclared -> g)
(Univ.ContextSet.levels ctx) g
in UGraph.merge_constraints (Univ.ContextSet.constraints ctx) g
@@ -415,7 +415,7 @@ let constant_type env (kn,u) =
let cb = lookup_constant kn env in
match cb.const_universes with
| Monomorphic_const _ -> cb.const_type, Univ.Constraint.empty
- | Polymorphic_const ctx ->
+ | Polymorphic_const _ctx ->
let csts = constraints_of cb u in
(subst_instance_constr u cb.const_type, csts)
@@ -508,14 +508,14 @@ let get_projections env ind =
Declareops.inductive_make_projections ind mib
(* Mutual Inductives *)
-let polymorphic_ind (mind,i) env =
+let polymorphic_ind (mind,_i) env =
Declareops.inductive_is_polymorphic (lookup_mind mind env)
let polymorphic_pind (ind,u) env =
if Univ.Instance.is_empty u then false
else polymorphic_ind ind env
-let type_in_type_ind (mind,i) env =
+let type_in_type_ind (mind,_i) env =
not (lookup_mind mind env).mind_typing_flags.check_universes
let template_polymorphic_ind (mind,i) env =
@@ -527,7 +527,7 @@ let template_polymorphic_pind (ind,u) env =
if not (Univ.Instance.is_empty u) then false
else template_polymorphic_ind ind env
-let add_mind_key kn (mind, _ as mind_key) env =
+let add_mind_key kn (_mind, _ as mind_key) env =
let new_inds = Mindmap_env.add kn mind_key env.env_globals.env_inductives in
let new_globals =
{ env.env_globals with
@@ -543,7 +543,7 @@ let lookup_constant_variables c env =
let cmap = lookup_constant c env in
Context.Named.to_vars cmap.const_hyps
-let lookup_inductive_variables (kn,i) env =
+let lookup_inductive_variables (kn,_i) env =
let mis = lookup_mind kn env in
Context.Named.to_vars mis.mind_hyps
@@ -579,6 +579,7 @@ let global_vars_set env constr =
contained in the types of the needed variables. *)
let really_needed env needed =
+ let open! Context.Named.Declaration in
Context.Named.fold_inside
(fun need decl ->
if Id.Set.mem (get_id decl) need then
@@ -594,6 +595,7 @@ let really_needed env needed =
(named_context env)
let keep_hyps env needed =
+ let open Context.Named.Declaration in
let really_needed = really_needed env needed in
Context.Named.fold_outside
(fun d nsign ->
@@ -647,6 +649,7 @@ type unsafe_type_judgment = types punsafe_type_judgment
exception Hyp_not_found
let apply_to_hyp ctxt id f =
+ let open Context.Named.Declaration in
let rec aux rtail ctxt =
match match_named_context_val ctxt with
| Some (d, v, ctxt) ->
@@ -663,6 +666,7 @@ let remove_hyps ids check_context check_value ctxt =
let rec remove_hyps ctxt = match match_named_context_val ctxt with
| None -> empty_named_context_val, false
| Some (d, v, rctxt) ->
+ let open Context.Named.Declaration in
let (ans, seen) = remove_hyps rctxt in
if Id.Set.mem (get_id d) ids then (ans, true)
else if not seen then ctxt, false
@@ -693,12 +697,12 @@ let register_one env field entry =
{ env with retroknowledge = Retroknowledge.add_field env.retroknowledge field entry }
(* [register env field entry] may register several fields when needed *)
-let register env field entry =
+let register env field gr =
match field with
- | KInt31 (grp, Int31Type) ->
- let i31c = match kind entry with
- | Ind i31t -> mkConstructUi (i31t, 1)
- | _ -> anomaly ~label:"Environ.register" (Pp.str "should be an inductive type.")
- in
- register_one (register_one env (KInt31 (grp,Int31Constructor)) i31c) field entry
- | field -> register_one env field entry
+ | KInt31 Int31Type ->
+ let i31c = match gr with
+ | GlobRef.IndRef i31t -> GlobRef.ConstructRef (i31t, 1)
+ | _ -> anomaly ~label:"Environ.register" (Pp.str "should be an inductive type.")
+ in
+ register_one (register_one env (KInt31 Int31Constructor) i31c) field gr
+ | field -> register_one env field gr
diff --git a/kernel/environ.mli b/kernel/environ.mli
index f45b7be821..1343b9029b 100644
--- a/kernel/environ.mli
+++ b/kernel/environ.mli
@@ -325,7 +325,7 @@ val retroknowledge : (retroknowledge->'a) -> env -> 'a
val registered : env -> field -> bool
-val register : env -> field -> Retroknowledge.entry -> env
+val register : env -> field -> GlobRef.t -> env
(** Native compiler *)
val no_link_info : link_info
diff --git a/kernel/indtypes.ml b/kernel/indtypes.ml
index d7eb865e0a..b976469ff7 100644
--- a/kernel/indtypes.ml
+++ b/kernel/indtypes.ml
@@ -234,8 +234,7 @@ let check_subtyping cumi paramsctxt env_ar inds =
let instance_other = Instance.of_array new_levels in
let constraints_other = Univ.subst_univs_level_constraints lmap (Univ.UContext.constraints uctx) in
let uctx_other = Univ.UContext.make (instance_other, constraints_other) in
- let env = Environ.push_context uctx env_ar in
- let env = Environ.push_context uctx_other env in
+ let env = Environ.push_context uctx_other env_ar in
let subtyp_constraints =
CumulativityInfo.leq_constraints cumi
(UContext.instance uctx) instance_other
@@ -243,7 +242,7 @@ let check_subtyping cumi paramsctxt env_ar inds =
in
let env = Environ.add_constraints subtyp_constraints env in
(* process individual inductive types: *)
- Array.iter (fun (id,cn,lc,(sign,arity)) ->
+ Array.iter (fun (_id,_cn,lc,(_sign,arity)) ->
match arity with
| RegularArity (_, full_arity, _) ->
check_subtyping_arity_constructor env dosubst full_arity numparams true;
@@ -280,7 +279,7 @@ let typecheck_inductive env mie =
List.fold_left
(fun (env_ar,l) ind ->
(* Arities (without params) are typed-checked here *)
- let expltype = ind.mind_entry_template in
+ let template = ind.mind_entry_template in
let arity =
if isArity ind.mind_entry_arity then
let (ctx,s) = dest_arity env_params ind.mind_entry_arity in
@@ -316,7 +315,7 @@ let typecheck_inductive env mie =
let env_ar' =
push_rel (LocalAssum (Name id, full_arity)) env_ar in
(* (add_constraints cst2 env_ar) in *)
- (env_ar', (id,full_arity,sign @ paramsctxt,expltype,deflev,inflev)::l))
+ (env_ar', (id,full_arity,sign @ paramsctxt,template,deflev,inflev)::l))
(env',[])
mie.mind_entry_inds in
@@ -343,7 +342,7 @@ let typecheck_inductive env mie =
(* Compute/check the sorts of the inductive types *)
let inds =
- Array.map (fun ((id,full_arity,sign,expltype,def_level,inf_level),cn,lc,clev) ->
+ Array.map (fun ((id,full_arity,sign,template,def_level,inf_level),cn,lc,clev) ->
let infu =
(** Inferred level, with parameters and constructors. *)
match inf_level with
@@ -369,31 +368,34 @@ let typecheck_inductive env mie =
RegularArity (not is_natural,full_arity,defu)
in
let template_polymorphic () =
- let sign, s =
+ let _sign, s =
try dest_arity env full_arity
with NotArity -> raise (InductiveError (NotAnArity (env, full_arity)))
- in
- match s with
- | Type u when expltype (* Explicitly polymorphic *) ->
- (* The polymorphic level is a function of the level of the *)
- (* conclusions of the parameters *)
- (* We enforce [u >= lev] in case [lev] has a strict upper *)
- (* constraints over [u] *)
- let b = type_in_type env || UGraph.check_leq (universes env') infu u in
- if not b then
- anomaly ~label:"check_inductive"
- (Pp.str"Incorrect universe " ++
- Universe.pr u ++ Pp.str " declared for inductive type, inferred level is "
- ++ Universe.pr clev ++ Pp.str ".")
- else
- TemplateArity (param_ccls paramsctxt, infu)
- | _ (* Not an explicit occurrence of Type *) ->
- full_polymorphic ()
+ in
+ let u = Sorts.univ_of_sort s in
+ (* The polymorphic level is a function of the level of the *)
+ (* conclusions of the parameters *)
+ (* We enforce [u >= lev] in case [lev] has a strict upper *)
+ (* constraints over [u] *)
+ let b = type_in_type env || UGraph.check_leq (universes env') infu u in
+ if not b then
+ anomaly ~label:"check_inductive"
+ (Pp.str"Incorrect universe " ++
+ Universe.pr u ++ Pp.str " declared for inductive type, inferred level is "
+ ++ Universe.pr clev ++ Pp.str ".")
+ else
+ TemplateArity (param_ccls paramsctxt, infu)
in
let arity =
match mie.mind_entry_universes with
- | Monomorphic_ind_entry _ -> template_polymorphic ()
- | Polymorphic_ind_entry _ | Cumulative_ind_entry _ -> full_polymorphic ()
+ | Monomorphic_ind_entry _ ->
+ if template then template_polymorphic ()
+ else full_polymorphic ()
+ | Polymorphic_ind_entry _ | Cumulative_ind_entry _ ->
+ if template
+ then anomaly ~label:"polymorphic_template_ind"
+ Pp.(strbrk "Template polymorphism and full polymorphism are incompatible.")
+ else full_polymorphic ()
in
(id,cn,lc,(sign,arity)))
inds
@@ -426,7 +428,7 @@ exception IllFormedInd of ill_formed_ind
let mind_extract_params = decompose_prod_n_assum
let explain_ind_err id ntyp env nparamsctxt c err =
- let (lparams,c') = mind_extract_params nparamsctxt c in
+ let (_lparams,c') = mind_extract_params nparamsctxt c in
match err with
| LocalNonPos kt ->
raise (InductiveError (NonPos (env,c',mkRel (kt+nparamsctxt))))
@@ -594,7 +596,7 @@ let check_positivity_one ~chkpos recursive (env,_,ntypes,_ as ienv) paramsctxt (
discharged to the [check_positive_nested] function. *)
if List.for_all (noccur_between n ntypes) largs then (nmr,mk_norec)
else check_positive_nested ienv nmr (ind_kn, largs)
- | err ->
+ | _err ->
(** If an inductive of the mutually inductive block
appears in any other way, then the positivy check gives
up. *)
@@ -611,7 +613,7 @@ let check_positivity_one ~chkpos recursive (env,_,ntypes,_ as ienv) paramsctxt (
defined types, not one of the types of the mutually inductive
block being defined). *)
(* accesses to the environment are not factorised, but is it worth? *)
- and check_positive_nested (env,n,ntypes,ra_env as ienv) nmr ((mi,u), largs) =
+ and check_positive_nested (env,n,ntypes,_ra_env as ienv) nmr ((mi,u), largs) =
let (mib,mip) = lookup_mind_specif env mi in
let auxnrecpar = mib.mind_nparams_rec in
let auxnnonrecpar = mib.mind_nparams - auxnrecpar in
@@ -662,7 +664,7 @@ let check_positivity_one ~chkpos recursive (env,_,ntypes,_ as ienv) paramsctxt (
the type [c]) is checked to be the right (properly applied)
inductive type. *)
and check_constructors ienv check_head nmr c =
- let rec check_constr_rec (env,n,ntypes,ra_env as ienv) nmr lrec c =
+ let rec check_constr_rec (env,n,ntypes,_ra_env as ienv) nmr lrec c =
let x,largs = decompose_app (whd_all env c) in
match kind x with
@@ -811,7 +813,7 @@ let compute_projections (kn, i as ind) mib =
in
let projections decl (i, j, labs, pbs, letsubst) =
match decl with
- | LocalDef (na,c,t) ->
+ | LocalDef (_na,c,_t) ->
(* From [params, field1,..,fieldj |- c(params,field1,..,fieldj)]
to [params, x:I, field1,..,fieldj |- c(params,field1,..,fieldj)] *)
let c = liftn 1 j c in
@@ -839,7 +841,7 @@ let compute_projections (kn, i as ind) mib =
(i + 1, j + 1, lab :: labs, projty :: pbs, fterm :: letsubst)
| Anonymous -> raise UndefinableExpansion
in
- let (_, _, labs, pbs, letsubst) =
+ let (_, _, labs, pbs, _letsubst) =
List.fold_right projections ctx (0, 1, [], [], paramsletsubst)
in
Array.of_list (List.rev labs),
diff --git a/kernel/inductive.ml b/kernel/inductive.ml
index 4d13a5fcb8..9bbcf07f7e 100644
--- a/kernel/inductive.ml
+++ b/kernel/inductive.ml
@@ -154,10 +154,10 @@ let make_subst env =
let rec make subst = function
| LocalDef _ :: sign, exp, args ->
make subst (sign, exp, args)
- | d::sign, None::exp, args ->
+ | _d::sign, None::exp, args ->
let args = match args with _::args -> args | [] -> [] in
make subst (sign, exp, args)
- | d::sign, Some u::exp, a::args ->
+ | _d::sign, Some u::exp, a::args ->
(* We recover the level of the argument, but we don't change the *)
(* level in the corresponding type in the arity; this level in the *)
(* arity is a global level which, at typing time, will be enforce *)
@@ -165,7 +165,7 @@ let make_subst env =
(* a useless extra constraint *)
let s = Sorts.univ_of_sort (snd (dest_arity env (Lazy.force a))) in
make (cons_subst u s subst) (sign, exp, args)
- | LocalAssum (na,t) :: sign, Some u::exp, [] ->
+ | LocalAssum (_na,_t) :: sign, Some u::exp, [] ->
(* No more argument here: we add the remaining universes to the *)
(* substitution (when [u] is distinct from all other universes in the *)
(* template, it is identity substitution otherwise (ie. when u is *)
@@ -173,7 +173,7 @@ let make_subst env =
(* update its image [x] by [sup x u] in order not to forget the *)
(* dependency in [u] that remains to be fullfilled. *)
make (remember_subst u subst) (sign, exp, [])
- | sign, [], _ ->
+ | _sign, [], _ ->
(* Uniform parameters are exhausted *)
subst
| [], _, _ ->
@@ -199,7 +199,7 @@ let instantiate_universes env ctx ar argsorts =
(* Type of an inductive type *)
-let type_of_inductive_gen ?(polyprop=true) env ((mib,mip),u) paramtyps =
+let type_of_inductive_gen ?(polyprop=true) env ((_mib,mip),u) paramtyps =
match mip.mind_arity with
| RegularArity a -> subst_instance_constr u a.mind_user_arity
| TemplateArity ar ->
@@ -215,12 +215,12 @@ let type_of_inductive_gen ?(polyprop=true) env ((mib,mip),u) paramtyps =
let type_of_inductive env pind =
type_of_inductive_gen env pind [||]
-let constrained_type_of_inductive env ((mib,mip),u as pind) =
+let constrained_type_of_inductive env ((mib,_mip),u as pind) =
let ty = type_of_inductive env pind in
let cst = instantiate_inductive_constraints mib u in
(ty, cst)
-let constrained_type_of_inductive_knowing_parameters env ((mib,mip),u as pind) args =
+let constrained_type_of_inductive_knowing_parameters env ((mib,_mip),u as pind) args =
let ty = type_of_inductive_gen env pind args in
let cst = instantiate_inductive_constraints mib u in
(ty, cst)
@@ -249,7 +249,7 @@ let type_of_constructor (cstr, u) (mib,mip) =
if i > nconstr then user_err Pp.(str "Not enough constructors in the type.");
constructor_instantiate (fst ind) u mib specif.(i-1)
-let constrained_type_of_constructor (cstr,u as cstru) (mib,mip as ind) =
+let constrained_type_of_constructor (_cstr,u as cstru) (mib,_mip as ind) =
let ty = type_of_constructor cstru ind in
let cst = instantiate_inductive_constraints mib u in
(ty, cst)
@@ -279,7 +279,7 @@ let inductive_sort_family mip =
let mind_arity mip =
mip.mind_arity_ctxt, inductive_sort_family mip
-let get_instantiated_arity (ind,u) (mib,mip) params =
+let get_instantiated_arity (_ind,u) (mib,mip) params =
let sign, s = mind_arity mip in
full_inductive_instantiate mib u params sign, s
@@ -563,7 +563,7 @@ let check_inductive_codomain env p =
let env = push_rel_context absctx env in
let arctx, s = dest_prod_assum env ar in
let env = push_rel_context arctx env in
- let i,l' = decompose_app (whd_all env s) in
+ let i,_l' = decompose_app (whd_all env s) in
isInd i
(* The following functions are almost duplicated from indtypes.ml, except
@@ -635,10 +635,10 @@ let get_recargs_approx env tree ind args =
build_recargs_nested ienv tree (ind_kn, largs)
| _ -> mk_norec
end
- | err ->
+ | _err ->
mk_norec
- and build_recargs_nested (env,ra_env as ienv) tree (((mind,i),u), largs) =
+ and build_recargs_nested (env,_ra_env as ienv) tree (((mind,i),u), largs) =
(* If the inferred tree already disallows recursion, no need to go further *)
if eq_wf_paths tree mk_norec then tree
else
@@ -676,7 +676,7 @@ let get_recargs_approx env tree ind args =
(Rtree.mk_rec irecargs).(i)
and build_recargs_constructors ienv trees c =
- let rec recargs_constr_rec (env,ra_env as ienv) trees lrec c =
+ let rec recargs_constr_rec (env,_ra_env as ienv) trees lrec c =
let x,largs = decompose_app (whd_all env c) in
match kind x with
@@ -685,7 +685,7 @@ let get_recargs_approx env tree ind args =
let recarg = build_recargs ienv (List.hd trees) b in
let ienv' = ienv_push_var ienv (na,b,mk_norec) in
recargs_constr_rec ienv' (List.tl trees) (recarg::lrec) d
- | hd ->
+ | _hd ->
List.rev lrec
in
recargs_constr_rec ienv trees [] c
@@ -794,7 +794,7 @@ let rec subterm_specif renv stack t =
| Proj (p, c) ->
let subt = subterm_specif renv stack c in
(match subt with
- | Subterm (s, wf) ->
+ | Subterm (_s, wf) ->
(* We take the subterm specs of the constructor of the record *)
let wf_args = (dest_subterms wf).(0) in
(* We extract the tree of the projected argument *)
@@ -932,7 +932,7 @@ let check_one_fix renv recpos trees def =
let case_spec = branches_specif renv
(lazy_subterm_specif renv [] c_0) ci in
let stack' = push_stack_closures renv l stack in
- let stack' = filter_stack_domain renv.env p stack' in
+ let stack' = filter_stack_domain renv.env p stack' in
Array.iteri (fun k br' ->
let stack_br = push_stack_args case_spec.(k) stack' in
check_rec_call renv stack_br br') lrest
@@ -964,7 +964,7 @@ let check_one_fix renv recpos trees def =
else check_rec_call renv' [] body)
bodies
- | Const (kn,u as cu) ->
+ | Const (kn,_u as cu) ->
if evaluable_constant kn renv.env then
try List.iter (check_rec_call renv []) l
with (FixGuardError _ ) ->
@@ -983,7 +983,7 @@ let check_one_fix renv recpos trees def =
check_rec_call renv [] a;
check_rec_call (push_var_renv renv (x,a)) [] b
- | CoFix (i,(_,typarray,bodies as recdef)) ->
+ | CoFix (_i,(_,typarray,bodies as recdef)) ->
List.iter (check_rec_call renv []) l;
Array.iter (check_rec_call renv []) typarray;
let renv' = push_fix_renv renv recdef in
@@ -992,13 +992,13 @@ let check_one_fix renv recpos trees def =
| (Ind _ | Construct _) ->
List.iter (check_rec_call renv []) l
- | Proj (p, c) ->
+ | Proj (_p, c) ->
List.iter (check_rec_call renv []) l;
check_rec_call renv [] c
| Var id ->
begin
- let open Context.Named.Declaration in
+ let open! Context.Named.Declaration in
match lookup_named id renv.env with
| LocalAssum _ ->
List.iter (check_rec_call renv []) l
@@ -1129,10 +1129,10 @@ let check_one_cofix env nbfix def deftype =
raise (CoFixGuardError (env,UnguardedRecursiveCall t))
else if not(List.for_all (noccur_with_meta n nbfix) args) then
raise (CoFixGuardError (env,NestedRecursiveOccurrences))
- | Construct ((_,i as cstr_kn),u) ->
+ | Construct ((_,i as cstr_kn),_u) ->
let lra = vlra.(i-1) in
let mI = inductive_of_constructor cstr_kn in
- let (mib,mip) = lookup_mind_specif env mI in
+ let (mib,_mip) = lookup_mind_specif env mI in
let realargs = List.skipn mib.mind_nparams args in
let rec process_args_of_constr = function
| (t::lr), (rar::lrar) ->
@@ -1157,7 +1157,7 @@ let check_one_cofix env nbfix def deftype =
else
raise (CoFixGuardError (env,RecCallInTypeOfAbstraction a))
- | CoFix (j,(_,varit,vdefs as recdef)) ->
+ | CoFix (_j,(_,varit,vdefs as recdef)) ->
if List.for_all (noccur_with_meta n nbfix) args
then
if Array.for_all (noccur_with_meta n nbfix) varit then
@@ -1203,7 +1203,7 @@ let check_one_cofix env nbfix def deftype =
(* The function which checks that the whole block of definitions
satisfies the guarded condition *)
-let check_cofix env (bodynum,(names,types,bodies as recdef)) =
+let check_cofix env (_bodynum,(names,types,bodies as recdef)) =
let flags = Environ.typing_flags env in
if flags.check_guarded then
let nbfix = Array.length bodies in
diff --git a/kernel/kernel.mllib b/kernel/kernel.mllib
index 07a02f6ef5..a18c5d1e20 100644
--- a/kernel/kernel.mllib
+++ b/kernel/kernel.mllib
@@ -10,13 +10,13 @@ Constr
Vars
Term
Mod_subst
+Vmvalues
Cbytecodes
Copcodes
Cemitcodes
Opaqueproof
Declarations
Entries
-Vmvalues
Nativevalues
CPrimitives
Declareops
diff --git a/kernel/make_opcodes.sh b/kernel/make_opcodes.sh
new file mode 100755
index 0000000000..bb8aba2f07
--- /dev/null
+++ b/kernel/make_opcodes.sh
@@ -0,0 +1,4 @@
+#!/usr/bin/env bash
+
+script_dir="$(dirname "$0")"
+tr -d "\r" < "${1}" | sed -n -e '/^enum/p' -e 's/,//g' -e '/^ /p' | awk -f "$script_dir"/make-opcodes > "${2}"
diff --git a/kernel/mod_subst.ml b/kernel/mod_subst.ml
index b35b9dda31..bff3092655 100644
--- a/kernel/mod_subst.ml
+++ b/kernel/mod_subst.ml
@@ -53,18 +53,25 @@ type delta_resolver = Deltamap.t
let empty_delta_resolver = Deltamap.empty
-module Umap = struct
- type 'a t = 'a MPmap.t * 'a MBImap.t
- let empty = MPmap.empty, MBImap.empty
- let is_empty (m1,m2) = MPmap.is_empty m1 && MBImap.is_empty m2
- let add_mbi mbi x (m1,m2) = (m1,MBImap.add mbi x m2)
- let add_mp mp x (m1,m2) = (MPmap.add mp x m1, m2)
- let find_mp mp map = MPmap.find mp (fst map)
- let find_mbi mbi map = MBImap.find mbi (snd map)
- let iter_mbi f map = MBImap.iter f (snd map)
- let fold fmp fmbi (m1,m2) i =
- MPmap.fold fmp m1 (MBImap.fold fmbi m2 i)
- let join map1 map2 = fold add_mp add_mbi map1 map2
+module Umap :
+ sig
+ type 'a t
+ val empty : 'a t
+ val is_empty : 'a t -> bool
+ val add_mbi : MBId.t -> 'a -> 'a t -> 'a t
+ val add_mp : ModPath.t -> 'a -> 'a t -> 'a t
+ val find : ModPath.t -> 'a t -> 'a
+ val join : 'a t -> 'a t -> 'a t
+ val fold : (ModPath.t -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b
+ end = struct
+ type 'a t = 'a MPmap.t
+ let empty = MPmap.empty
+ let is_empty m = MPmap.is_empty m
+ let add_mbi mbi x m = MPmap.add (MPbound mbi) x m
+ let add_mp mp x m = MPmap.add mp x m
+ let find = MPmap.find
+ let fold = MPmap.fold
+ let join map1 map2 = fold add_mp map1 map2
end
type substitution = (ModPath.t * delta_resolver) Umap.t
@@ -93,8 +100,7 @@ let debug_string_of_delta resolve =
let list_contents sub =
let one_pair (mp,reso) = (ModPath.to_string mp,debug_string_of_delta reso) in
let mp_one_pair mp0 p l = (ModPath.to_string mp0, one_pair p)::l in
- let mbi_one_pair mbi p l = (MBId.debug_to_string mbi, one_pair p)::l in
- Umap.fold mp_one_pair mbi_one_pair sub []
+ Umap.fold mp_one_pair sub []
let debug_string_of_subst sub =
let l = List.map (fun (s1,(s2,s3)) -> s1^"|->"^s2^"["^s3^"]")
@@ -222,15 +228,10 @@ let search_delta_inline resolve kn1 kn2 =
let subst_mp0 sub mp = (* 's like subst *)
let rec aux mp =
match mp with
- | MPfile sid -> Umap.find_mp mp sub
- | MPbound bid ->
- begin
- try Umap.find_mbi bid sub
- with Not_found -> Umap.find_mp mp sub
- end
+ | MPfile _ | MPbound _ -> Umap.find mp sub
| MPdot (mp1,l) as mp2 ->
begin
- try Umap.find_mp mp2 sub
+ try Umap.find mp2 sub
with Not_found ->
let mp1',resolve = aux mp1 in
MPdot (mp1',l),resolve
@@ -318,12 +319,12 @@ let subst_con sub cst =
let subst_con_kn sub con =
subst_con sub (con,Univ.Instance.empty)
-let subst_pcon sub (con,u as pcon) =
- try let con', can = subst_con0 sub pcon in
+let subst_pcon sub (_con,u as pcon) =
+ try let con', _can = subst_con0 sub pcon in
con',u
with No_subst -> pcon
-let subst_pcon_term sub (con,u as pcon) =
+let subst_pcon_term sub (_con,u as pcon) =
try let con', can = subst_con0 sub pcon in
(con',u), can
with No_subst -> pcon, mkConstU pcon
@@ -440,7 +441,7 @@ let replace_mp_in_kn mpfrom mpto kn =
let rec mp_in_mp mp mp1 =
match mp1 with
| _ when ModPath.equal mp1 mp -> true
- | MPdot (mp2,l) -> mp_in_mp mp mp2
+ | MPdot (mp2,_l) -> mp_in_mp mp mp2
| _ -> false
let subset_prefixed_by mp resolver =
@@ -525,9 +526,7 @@ let substition_prefixed_by k mp subst =
Umap.add_mp new_key (mp_to,reso) sub
else sub
in
- let mbi_prefixmp mbi _ sub = sub
- in
- Umap.fold mp_prefixmp mbi_prefixmp subst empty_subst
+ Umap.fold mp_prefixmp subst empty_subst
let join subst1 subst2 =
let apply_subst mpk add (mp,resolve) res =
@@ -547,24 +546,9 @@ let join subst1 subst2 =
Umap.join prefixed_subst (add (mp',resolve'') res)
in
let mp_apply_subst mp = apply_subst mp (Umap.add_mp mp) in
- let mbi_apply_subst mbi = apply_subst (MPbound mbi) (Umap.add_mbi mbi) in
- let subst = Umap.fold mp_apply_subst mbi_apply_subst subst1 empty_subst in
+ let subst = Umap.fold mp_apply_subst subst1 empty_subst in
Umap.join subst2 subst
-let rec occur_in_path mbi = function
- | MPbound bid' -> MBId.equal mbi bid'
- | MPdot (mp1,_) -> occur_in_path mbi mp1
- | _ -> false
-
-let occur_mbid mbi sub =
- let check_one mbi' (mp,_) =
- if MBId.equal mbi mbi' || occur_in_path mbi mp then raise Exit
- in
- try
- Umap.iter_mbi check_one sub;
- false
- with Exit -> true
-
type 'a substituted = {
mutable subst_value : 'a;
mutable subst_subst : substitution list;
diff --git a/kernel/mod_subst.mli b/kernel/mod_subst.mli
index 2e5211c770..8416094063 100644
--- a/kernel/mod_subst.mli
+++ b/kernel/mod_subst.mli
@@ -165,11 +165,6 @@ val replace_mp_in_kn : ModPath.t -> ModPath.t -> KerName.t -> KerName.t
names appearing in [c] *)
val subst_mps : substitution -> constr -> constr
-(** [occur_*id id sub] returns true iff [id] occurs in [sub]
- on either side *)
-
-val occur_mbid : MBId.t -> substitution -> bool
-
(** [repr_substituted r] dumps the representation of a substituted:
- [None, a] when r is a value
- [Some s, a] when r is a delayed substitution [s] applied to [a] *)
diff --git a/kernel/modops.ml b/kernel/modops.ml
index 98a9973117..424d329e09 100644
--- a/kernel/modops.ml
+++ b/kernel/modops.ml
@@ -138,7 +138,7 @@ let rec functor_smart_map fty f0 funct = match funct with
let a' = f0 a in if a==a' then funct else NoFunctor a'
let rec functor_iter fty f0 = function
- |MoreFunctor (mbid,ty,e) -> fty ty; functor_iter fty f0 e
+ |MoreFunctor (_mbid,ty,e) -> fty ty; functor_iter fty f0 e
|NoFunctor a -> f0 a
(** {6 Misc operations } *)
@@ -171,7 +171,7 @@ let implem_iter fs fa impl = match impl with
(** {6 Substitutions of modular structures } *)
-let id_delta x y = x
+let id_delta x _y = x
let subst_with_body sub = function
|WithMod(id,mp) as orig ->
@@ -200,7 +200,7 @@ let rec subst_structure sub do_delta sign =
and subst_body : 'a. _ -> _ -> (_ -> 'a -> 'a) -> _ -> 'a generic_module_body -> 'a generic_module_body =
fun is_mod sub subst_impl do_delta mb ->
- let { mod_mp=mp; mod_expr=me; mod_type=ty; mod_type_alg=aty } = mb in
+ let { mod_mp=mp; mod_expr=me; mod_type=ty; mod_type_alg=aty; _ } = mb in
let mp' = subst_mp sub mp in
let sub =
if ModPath.equal mp mp' then sub
@@ -267,7 +267,7 @@ let subst_structure subst = subst_structure subst do_delta_codom
(* lclrk : retroknowledge_action list, rkaction : retroknowledge action *)
let add_retroknowledge =
let perform rkaction env = match rkaction with
- | Retroknowledge.RKRegister (f, e) when (isConst e || isInd e) ->
+ | Retroknowledge.RKRegister (f, ((GlobRef.ConstRef _ | GlobRef.IndRef _) as e)) ->
Environ.register env f e
| _ ->
CErrors.anomaly ~label:"Modops.add_retroknowledge"
@@ -371,7 +371,7 @@ and strengthen_sig mp_from struc mp_to reso = match struc with
let item' = l,SFBmodule mb' in
let reso',rest' = strengthen_sig mp_from rest mp_to reso in
add_delta_resolver reso' mb.mod_delta, item':: rest'
- |(l,SFBmodtype mty as item) :: rest ->
+ |(_l,SFBmodtype _mty as item) :: rest ->
let reso',rest' = strengthen_sig mp_from rest mp_to reso in
reso',item::rest'
@@ -628,7 +628,7 @@ let join_structure except otab s =
let rec join_module : 'a. 'a generic_module_body -> unit = fun mb ->
Option.iter join_expression mb.mod_type_alg;
join_signature mb.mod_type
- and join_field (l,body) = match body with
+ and join_field (_l,body) = match body with
|SFBconst sb -> join_constant_body except otab sb
|SFBmind _ -> ()
|SFBmodule m ->
diff --git a/kernel/names.ml b/kernel/names.ml
index e1d70e8111..6d33f233e9 100644
--- a/kernel/names.ml
+++ b/kernel/names.ml
@@ -207,7 +207,7 @@ struct
let repr mbid = mbid
- let to_string (i, s, p) =
+ let to_string (_i, s, p) =
DirPath.to_string p ^ "." ^ s
let debug_to_string (i, s, p) =
@@ -328,7 +328,7 @@ module ModPath = struct
let rec dp = function
| MPfile sl -> sl
| MPbound (_,_,dp) -> dp
- | MPdot (mp,l) -> dp mp
+ | MPdot (mp,_l) -> dp mp
module Self_Hashcons = struct
type t = module_path
@@ -420,7 +420,7 @@ module KerName = struct
let hash kn =
let h = kn.refhash in
if h < 0 then
- let { modpath = mp; dirpath = dp; knlabel = lbl; } = kn in
+ let { modpath = mp; dirpath = dp; knlabel = lbl; _ } = kn in
let h = combine3 (ModPath.hash mp) (DirPath.hash dp) (Label.hash lbl) in
(* Ensure positivity on all platforms. *)
let h = h land 0x3FFFFFFF in
@@ -623,8 +623,8 @@ let constr_modpath (ind,_) = ind_modpath ind
let ith_mutual_inductive (mind, _) i = (mind, i)
let ith_constructor_of_inductive ind i = (ind, i)
-let inductive_of_constructor (ind, i) = ind
-let index_of_constructor (ind, i) = i
+let inductive_of_constructor (ind, _i) = ind
+let index_of_constructor (_ind, i) = i
let eq_ind (m1, i1) (m2, i2) = Int.equal i1 i2 && MutInd.equal m1 m2
let eq_user_ind (m1, i1) (m2, i2) =
@@ -935,7 +935,7 @@ end
type projection = Projection.t
-module GlobRef = struct
+module GlobRefInternal = struct
type t =
| VarRef of variable (** A reference to the section-context. *)
@@ -951,11 +951,84 @@ module GlobRef = struct
| VarRef v1, VarRef v2 -> Id.equal v1 v2
| (ConstRef _ | IndRef _ | ConstructRef _ | VarRef _), _ -> false
+ let global_eq_gen eq_cst eq_ind eq_cons x y =
+ x == y ||
+ match x, y with
+ | ConstRef cx, ConstRef cy -> eq_cst cx cy
+ | IndRef indx, IndRef indy -> eq_ind indx indy
+ | ConstructRef consx, ConstructRef consy -> eq_cons consx consy
+ | VarRef v1, VarRef v2 -> Id.equal v1 v2
+ | (VarRef _ | ConstRef _ | IndRef _ | ConstructRef _), _ -> false
+
+ let global_ord_gen ord_cst ord_ind ord_cons x y =
+ if x == y then 0
+ else match x, y with
+ | VarRef v1, VarRef v2 -> Id.compare v1 v2
+ | VarRef _, _ -> -1
+ | _, VarRef _ -> 1
+ | ConstRef cx, ConstRef cy -> ord_cst cx cy
+ | ConstRef _, _ -> -1
+ | _, ConstRef _ -> 1
+ | IndRef indx, IndRef indy -> ord_ind indx indy
+ | IndRef _, _ -> -1
+ | _ , IndRef _ -> 1
+ | ConstructRef consx, ConstructRef consy -> ord_cons consx consy
+
+ let global_hash_gen hash_cst hash_ind hash_cons gr =
+ let open Hashset.Combine in
+ match gr with
+ | ConstRef c -> combinesmall 1 (hash_cst c)
+ | IndRef i -> combinesmall 2 (hash_ind i)
+ | ConstructRef c -> combinesmall 3 (hash_cons c)
+ | VarRef id -> combinesmall 4 (Id.hash id)
+
+end
+
+module GlobRef = struct
+
+ type t = GlobRefInternal.t =
+ | VarRef of variable (** A reference to the section-context. *)
+ | ConstRef of Constant.t (** A reference to the environment. *)
+ | IndRef of inductive (** A reference to an inductive type. *)
+ | ConstructRef of constructor (** A reference to a constructor of an inductive type. *)
+
+ let equal = GlobRefInternal.equal
+
+ (* By default, [global_reference] are ordered on their canonical part *)
+
+ module Ordered = struct
+ open Constant.CanOrd
+ type t = GlobRefInternal.t
+ let compare gr1 gr2 =
+ GlobRefInternal.global_ord_gen compare ind_ord constructor_ord gr1 gr2
+ let equal gr1 gr2 = GlobRefInternal.global_eq_gen equal eq_ind eq_constructor gr1 gr2
+ let hash gr = GlobRefInternal.global_hash_gen hash ind_hash constructor_hash gr
+ end
+
+ module Ordered_env = struct
+ open Constant.UserOrd
+ type t = GlobRefInternal.t
+ let compare gr1 gr2 =
+ GlobRefInternal.global_ord_gen compare ind_user_ord constructor_user_ord gr1 gr2
+ let equal gr1 gr2 =
+ GlobRefInternal.global_eq_gen equal eq_user_ind eq_user_constructor gr1 gr2
+ let hash gr = GlobRefInternal.global_hash_gen hash ind_user_hash constructor_user_hash gr
+ end
+
+ module Map = HMap.Make(Ordered)
+ module Set = Map.Set
+
+ (* Alternative sets and maps indexed by the user part of the kernel names *)
+
+ module Map_env = HMap.Make(Ordered_env)
+ module Set_env = Map_env.Set
+
end
type global_reference = GlobRef.t
[@@ocaml.deprecated "Alias for [GlobRef.t]"]
+
type evaluable_global_reference =
| EvalVarRef of Id.t
| EvalConstRef of Constant.t
diff --git a/kernel/names.mli b/kernel/names.mli
index 1cdf5c2402..2ea8108734 100644
--- a/kernel/names.mli
+++ b/kernel/names.mli
@@ -645,6 +645,28 @@ module GlobRef : sig
val equal : t -> t -> bool
+ module Ordered : sig
+ type nonrec t = t
+ val compare : t -> t -> int
+ val equal : t -> t -> bool
+ val hash : t -> int
+ end
+
+ module Ordered_env : sig
+ type nonrec t = t
+ val compare : t -> t -> int
+ val equal : t -> t -> bool
+ val hash : t -> int
+ end
+
+ module Set_env : CSig.SetS with type elt = t
+ module Map_env : Map.ExtS
+ with type key = t and module Set := Set_env
+
+ module Set : CSig.SetS with type elt = t
+ module Map : Map.ExtS
+ with type key = t and module Set := Set
+
end
type global_reference = GlobRef.t
diff --git a/kernel/nativecode.ml b/kernel/nativecode.ml
index cc35a70cbf..74b075f4a5 100644
--- a/kernel/nativecode.ml
+++ b/kernel/nativecode.ml
@@ -632,6 +632,14 @@ let mkMLapp f args =
| MLapp(f,args') -> MLapp(f,Array.append args' args)
| _ -> MLapp(f,args)
+let mkForceCofix prefix ind arg =
+ let name = fresh_lname Anonymous in
+ MLlet (name, arg,
+ MLif (
+ MLisaccu (prefix, ind, MLlocal name),
+ MLapp (MLprimitive Force_cofix, [|MLlocal name|]),
+ MLlocal name))
+
let empty_params = [||]
let decompose_MLlam c =
@@ -999,7 +1007,7 @@ let compile_prim decl cond paux =
*)
let rec opt_prim_aux paux =
match paux with
- | PAprim(prefix, kn, op, args) ->
+ | PAprim(_prefix, _kn, op, args) ->
let args = Array.map opt_prim_aux args in
app_prim (Coq_primitive(op,None)) args
(*
@@ -1063,16 +1071,15 @@ let ml_of_instance instance u =
match t with
| Lrel(id ,i) -> get_rel env id i
| Lvar id -> get_var env id
- | Lmeta(mv,ty) ->
+ | Lmeta(mv,_ty) ->
let tyn = fresh_lname Anonymous in
let i = push_symbol (SymbMeta mv) in
MLapp(MLprimitive Mk_meta, [|get_meta_code i; MLlocal tyn|])
- | Levar(evk,ty,args) ->
- let tyn = fresh_lname Anonymous in
+ | Levar(evk, args) ->
let i = push_symbol (SymbEvar evk) in
+ (** Arguments are *not* reversed in evar instances in native compilation *)
let args = MLarray(Array.map (ml_of_lam env l) args) in
- MLlet(tyn, ml_of_lam env l ty,
- MLapp(MLprimitive Mk_evar, [|get_evar_code i;MLlocal tyn; args|]))
+ MLapp(MLprimitive Mk_evar, [|get_evar_code i; args|])
| Lprod(dom,codom) ->
let dom = ml_of_lam env l dom in
let codom = ml_of_lam env l codom in
@@ -1144,7 +1151,7 @@ let ml_of_instance instance u =
let arg = ml_of_lam env l a in
let force =
if annot.asw_finite then arg
- else MLapp(MLprimitive Force_cofix, [|arg|]) in
+ else mkForceCofix annot.asw_prefix annot.asw_ind arg in
mkMLapp (MLapp (MLglobal cn, fv_args env fvn fvr)) [|force|]
| Lif(t,bt,bf) ->
MLif(ml_of_lam env l t, ml_of_lam env l bt, ml_of_lam env l bf)
@@ -1177,7 +1184,7 @@ let ml_of_instance instance u =
let lf,env_n = push_rels (empty_env env.env_univ ()) ids in
let t_params = Array.make ndef [||] in
let t_norm_f = Array.make ndef (Gnorm (l,-1)) in
- let mk_let envi (id,def) t = MLlet (id,def,t) in
+ let mk_let _envi (id,def) t = MLlet (id,def,t) in
let mk_lam_or_let (params,lets,env) (id,def) =
let ln,env' = push_rel env id in
match def with
@@ -1210,7 +1217,7 @@ let ml_of_instance instance u =
(Array.map (fun g -> mkMLapp (MLglobal g) fv_args') t_norm_f) in
(* Compilation of fix *)
let fv_args = fv_args env fvn fvr in
- let lf, env = push_rels env ids in
+ let lf, _env = push_rels env ids in
let lf_args = Array.map (fun id -> MLlocal id) lf in
let mk_norm = MLapp(MLglobal norm, fv_args) in
let mkrec i lname =
@@ -1265,9 +1272,9 @@ let ml_of_instance instance u =
let mk_norm = MLapp(MLglobal norm, fv_args) in
let lnorm = fresh_lname Anonymous in
let ltype = fresh_lname Anonymous in
- let lf, env = push_rels env ids in
+ let lf, _env = push_rels env ids in
let lf_args = Array.map (fun id -> MLlocal id) lf in
- let upd i lname cont =
+ let upd i _lname cont =
let paramsi = t_params.(i) in
let pargsi = Array.map (fun id -> MLlocal id) paramsi in
let uniti = fresh_lname Anonymous in
@@ -1298,7 +1305,7 @@ let ml_of_instance instance u =
(lname, paramsi, body) in
MLletrec(Array.mapi mkrec lf, lf_args.(start)) *)
- | Lmakeblock (prefix,(cn,u),_,args) ->
+ | Lmakeblock (prefix,(cn,_u),_,args) ->
let args = Array.map (ml_of_lam env l) args in
MLconstruct(prefix,cn,args)
| Lconstruct (prefix, (cn,u)) ->
@@ -1554,7 +1561,7 @@ let rec list_of_mp acc = function
let list_of_mp mp = list_of_mp [] mp
let string_of_kn kn =
- let (mp,dp,l) = KerName.repr kn in
+ let (mp,_dp,l) = KerName.repr kn in
let mp = list_of_mp mp in
String.concat "_" mp ^ "_" ^ string_of_label l
@@ -1749,7 +1756,7 @@ let pp_mllam fmt l =
| Mk_cofix(start) -> Format.fprintf fmt "mk_cofix_accu %i" start
| Mk_rel i -> Format.fprintf fmt "mk_rel_accu %i" i
| Mk_var id ->
- Format.fprintf fmt "mk_var_accu (Names.id_of_string \"%s\")" (string_of_id id)
+ Format.fprintf fmt "mk_var_accu (Names.Id.of_string \"%s\")" (string_of_id id)
| Mk_proj -> Format.fprintf fmt "mk_proj_accu"
| Is_int -> Format.fprintf fmt "is_int"
| Cast_accu -> Format.fprintf fmt "cast_accu"
@@ -1980,7 +1987,7 @@ let compile_mind mb mind stack =
(MLconstruct("", c, Array.map (fun id -> MLlocal id) args)))::acc
in
let constructors = Array.fold_left_i add_construct [] ob.mind_reloc_tbl in
- let add_proj proj_arg acc pb =
+ let add_proj proj_arg acc _pb =
let tbl = ob.mind_reloc_tbl in
(* Building info *)
let ci = { ci_ind = ind; ci_npar = nparams;
@@ -2000,7 +2007,7 @@ let compile_mind mb mind stack =
let accu = MLapp (MLprimitive Cast_accu, [|MLlocal cf_uid|]) in
let accu_br = MLapp (MLprimitive Mk_proj, [|get_proj_code i;accu|]) in
let code = MLmatch(asw,MLlocal cf_uid,accu_br,[|[((ind,1),cargs)],MLlocal ci_uid|]) in
- let code = MLlet(cf_uid, MLapp (MLprimitive Force_cofix, [|MLlocal c_uid|]), code) in
+ let code = MLlet(cf_uid, mkForceCofix "" ind (MLlocal c_uid), code) in
let gn = Gproj ("", ind, proj_arg) in
Glet (gn, mkMLlam [|c_uid|] code) :: acc
in
@@ -2046,9 +2053,9 @@ let compile_mind_deps env prefix ~interactive
let compile_deps env sigma prefix ~interactive init t =
let rec aux env lvl init t =
match kind t with
- | Ind ((mind,_),u) -> compile_mind_deps env prefix ~interactive init mind
+ | Ind ((mind,_),_u) -> compile_mind_deps env prefix ~interactive init mind
| Const c ->
- let c,u = get_alias env c in
+ let c,_u = get_alias env c in
let cb,(nameref,_) = lookup_constant_key c env in
let (_, (_, const_updates)) = init in
if is_code_loaded ~interactive nameref
@@ -2067,11 +2074,11 @@ let compile_deps env sigma prefix ~interactive init t =
let comp_stack = code@comp_stack in
let const_updates = Cmap_env.add c (nameref, name) const_updates in
comp_stack, (mind_updates, const_updates)
- | Construct (((mind,_),_),u) -> compile_mind_deps env prefix ~interactive init mind
+ | Construct (((mind,_),_),_u) -> compile_mind_deps env prefix ~interactive init mind
| Proj (p,c) ->
let init = compile_mind_deps env prefix ~interactive init (Projection.mind p) in
aux env lvl init c
- | Case (ci, p, c, ac) ->
+ | Case (ci, _p, _c, _ac) ->
let mind = fst ci.ci_ind in
let init = compile_mind_deps env prefix ~interactive init mind in
fold_constr_with_binders succ (aux env) lvl init t
diff --git a/kernel/nativeconv.ml b/kernel/nativeconv.ml
index 931b8bbc86..054b6a2d17 100644
--- a/kernel/nativeconv.ml
+++ b/kernel/nativeconv.ml
@@ -25,9 +25,9 @@ let rec conv_val env pb lvl v1 v2 cu =
| Vfun f1, Vfun f2 ->
let v = mk_rel_accu lvl in
conv_val env CONV (lvl+1) (f1 v) (f2 v) cu
- | Vfun f1, _ ->
+ | Vfun _f1, _ ->
conv_val env CONV lvl v1 (fun x -> v2 x) cu
- | _, Vfun f2 ->
+ | _, Vfun _f2 ->
conv_val env CONV lvl (fun x -> v1 x) v2 cu
| Vaccu k1, Vaccu k2 ->
conv_accu env pb lvl k1 k2 cu
@@ -64,7 +64,7 @@ and conv_atom env pb lvl a1 a2 cu =
match a1, a2 with
| Ameta (m1,_), Ameta (m2,_) ->
if Int.equal m1 m2 then cu else raise NotConvertible
- | Aevar (ev1,_,args1), Aevar (ev2,_,args2) ->
+ | Aevar (ev1, args1), Aevar (ev2, args2) ->
if Evar.equal ev1 ev2 then
Array.fold_right2 (conv_val env CONV lvl) args1 args2 cu
else raise NotConvertible
@@ -110,7 +110,7 @@ and conv_atom env pb lvl a1 a2 cu =
else
if not (Int.equal (Array.length f1) (Array.length f2)) then raise NotConvertible
else conv_fix env lvl t1 f1 t2 f2 cu
- | Aprod(_,d1,c1), Aprod(_,d2,c2) ->
+ | Aprod(_,d1,_c1), Aprod(_,d2,_c2) ->
let cu = conv_val env CONV lvl d1 d2 cu in
let v = mk_rel_accu lvl in
conv_val env pb (lvl + 1) (d1 v) (d2 v) cu
diff --git a/kernel/nativeinstr.mli b/kernel/nativeinstr.mli
index 5075bd3d14..2d8e2ba2f0 100644
--- a/kernel/nativeinstr.mli
+++ b/kernel/nativeinstr.mli
@@ -25,7 +25,7 @@ and lambda =
| Lrel of Name.t * int
| Lvar of Id.t
| Lmeta of metavariable * lambda (* type *)
- | Levar of Evar.t * lambda (* type *) * lambda array (* arguments *)
+ | Levar of Evar.t * lambda array (* arguments *)
| Lprod of lambda * lambda
| Llam of Name.t array * lambda
| Llet of Name.t * lambda * lambda
diff --git a/kernel/nativelambda.ml b/kernel/nativelambda.ml
index cec0ee57d5..70cb8691c6 100644
--- a/kernel/nativelambda.ml
+++ b/kernel/nativelambda.ml
@@ -23,7 +23,6 @@ exception NotClosed
type evars =
{ evars_val : existential -> constr option;
- evars_typ : existential -> types;
evars_metas : metavariable -> types }
(*s Constructors *)
@@ -88,7 +87,7 @@ let get_const_prefix env c =
let rec map_lam_with_binders g f n lam =
match lam with
| Lrel _ | Lvar _ | Lconst _ | Lproj _ | Lval _ | Lsort _ | Lind _
- | Lconstruct _ | Llazy | Lforce | Lmeta _ | Levar _ -> lam
+ | Lconstruct _ | Llazy | Lforce | Lmeta _ -> lam
| Lprod(dom,codom) ->
let dom' = f n dom in
let codom' = f n codom in
@@ -139,8 +138,11 @@ let rec map_lam_with_binders g f n lam =
| Luint u ->
let u' = map_uint g f n u in
if u == u' then lam else Luint u'
+ | Levar (evk, args) ->
+ let args' = Array.Smart.map (f n) args in
+ if args == args' then lam else Levar (evk, args')
-and map_uint g f n u =
+and map_uint _g f n u =
match u with
| UintVal _ -> u
| UintDigits(prefix,c,args) ->
@@ -201,7 +203,7 @@ let can_subst lam =
let can_merge_if bt bf =
match bt, bf with
- | Llam(idst,_), Llam(idsf,_) -> true
+ | Llam(_idst,_), Llam(_idsf,_) -> true
| _ -> false
let merge_if t bt bf =
@@ -368,17 +370,17 @@ module Cache =
let is_lazy env prefix t =
match kind t with
- | App (f,args) ->
+ | App (f,_args) ->
begin match kind f with
| Construct (c,_) ->
- let entry = mkInd (fst c) in
- (try
- let _ =
- Retroknowledge.get_native_before_match_info env.retroknowledge
- entry prefix c Llazy;
- in
+ let gr = GlobRef.IndRef (fst c) in
+ (try
+ let _ =
+ Retroknowledge.get_native_before_match_info env.retroknowledge
+ gr prefix c Llazy;
+ in
false
- with Not_found -> true)
+ with Not_found -> true)
| _ -> true
end
| LetIn _ | Case _ | Proj _ -> true
@@ -386,13 +388,10 @@ let is_lazy env prefix t =
let evar_value sigma ev = sigma.evars_val ev
-let evar_type sigma ev = sigma.evars_typ ev
-
let meta_type sigma mv = sigma.evars_metas mv
let empty_evars =
{ evars_val = (fun _ -> None);
- evars_typ = (fun _ -> assert false);
evars_metas = (fun _ -> assert false) }
let empty_ids = [||]
@@ -420,9 +419,8 @@ let rec lambda_of_constr cache env sigma c =
| Evar (evk,args as ev) ->
(match evar_value sigma ev with
| None ->
- let ty = evar_type sigma ev in
let args = Array.map (lambda_of_constr cache env sigma) args in
- Levar(evk, lambda_of_constr cache env sigma ty, args)
+ Levar(evk, args)
| Some t -> lambda_of_constr cache env sigma t)
| Cast (c, _, _) -> lambda_of_constr cache env sigma c
@@ -433,7 +431,7 @@ let rec lambda_of_constr cache env sigma c =
| Sort s -> Lsort s
- | Ind (ind,u as pind) ->
+ | Ind (ind,_u as pind) ->
let prefix = get_mind_prefix env (fst ind) in
Lind (prefix, pind)
@@ -484,12 +482,12 @@ let rec lambda_of_constr cache env sigma c =
in
(* translation of the argument *)
let la = lambda_of_constr cache env sigma a in
- let entry = mkInd ind in
+ let gr = GlobRef.IndRef ind in
let la =
- try
- Retroknowledge.get_native_before_match_info (env).retroknowledge
- entry prefix (ind,1) la
- with Not_found -> la
+ try
+ Retroknowledge.get_native_before_match_info (env).retroknowledge
+ gr prefix (ind,1) la
+ with Not_found -> la
in
(* translation of the type *)
let lt = lambda_of_constr cache env sigma t in
@@ -531,14 +529,14 @@ let rec lambda_of_constr cache env sigma c =
and lambda_of_app cache env sigma f args =
match kind f with
- | Const (kn,u as c) ->
+ | Const (_kn,_u as c) ->
let kn,u = get_alias env c in
let cb = lookup_constant kn env in
(try
let prefix = get_const_prefix env kn in
(* We delay the compilation of arguments to avoid an exponential behavior *)
let f = Retroknowledge.get_native_compiling_info
- (env).retroknowledge (mkConst kn) prefix in
+ (env).retroknowledge (GlobRef.ConstRef kn) prefix in
let args = lambda_of_args cache env sigma 0 args in
f args
with Not_found ->
@@ -563,17 +561,18 @@ and lambda_of_app cache env sigma f args =
let expected = nparams + arity in
let nargs = Array.length args in
let prefix = get_mind_prefix env (fst (fst c)) in
+ let gr = GlobRef.ConstructRef c in
if Int.equal nargs expected then
try
try
Retroknowledge.get_native_constant_static_info
(env).retroknowledge
- f args
+ gr args
with NotClosed ->
assert (Int.equal nparams 0); (* should be fine for int31 *)
let args = lambda_of_args cache env sigma nparams args in
Retroknowledge.get_native_constant_dynamic_info
- (env).retroknowledge f prefix c args
+ (env).retroknowledge gr prefix c args
with Not_found ->
let args = lambda_of_args cache env sigma nparams args in
makeblock env c u tag args
@@ -581,7 +580,7 @@ and lambda_of_app cache env sigma f args =
let args = lambda_of_args cache env sigma 0 args in
(try
Retroknowledge.get_native_constant_dynamic_info
- (env).retroknowledge f prefix c args
+ (env).retroknowledge gr prefix c args
with Not_found ->
mkLapp (Lconstruct (prefix, (c,u))) args)
| _ ->
diff --git a/kernel/nativelambda.mli b/kernel/nativelambda.mli
index efe1700cd7..7b20258929 100644
--- a/kernel/nativelambda.mli
+++ b/kernel/nativelambda.mli
@@ -15,7 +15,6 @@ open Nativeinstr
(** This file defines the lambda code generation phase of the native compiler *)
type evars =
{ evars_val : existential -> constr option;
- evars_typ : existential -> types;
evars_metas : metavariable -> types }
val empty_evars : evars
diff --git a/kernel/nativelib.ml b/kernel/nativelib.ml
index f784509b6f..b4126dd68c 100644
--- a/kernel/nativelib.ml
+++ b/kernel/nativelib.ml
@@ -40,7 +40,7 @@ let include_dirs () =
[Filename.get_temp_dir_name (); coqlib () / "kernel"; coqlib () / "library"]
(* Pointer to the function linking an ML object into coq's toplevel *)
-let load_obj = ref (fun x -> () : string -> unit)
+let load_obj = ref (fun _x -> () : string -> unit)
let rt1 = ref (dummy_value ())
let rt2 = ref (dummy_value ())
@@ -113,7 +113,7 @@ let call_compiler ?profile:(profile=false) ml_filename =
let res = CUnix.sys_command (ocamlfind ()) args in
let res = match res with
| Unix.WEXITED 0 -> true
- | Unix.WEXITED n | Unix.WSIGNALED n | Unix.WSTOPPED n ->
+ | Unix.WEXITED _n | Unix.WSIGNALED _n | Unix.WSTOPPED _n ->
warn_native_compiler_failed (Inl res); false
in
res, link_filename
@@ -158,7 +158,7 @@ let call_linker ?(fatal=true) prefix f upds =
(try
if Dynlink.is_native then Dynlink.loadfile f else !load_obj f;
register_native_file prefix
- with Dynlink.Error e as exn ->
+ with Dynlink.Error _ as exn ->
let exn = CErrors.push exn in
if fatal then iraise exn
else if !Flags.debug then Feedback.msg_debug CErrors.(iprint exn));
diff --git a/kernel/nativelibrary.ml b/kernel/nativelibrary.ml
index edce9367fc..8ac3538fc5 100644
--- a/kernel/nativelibrary.ml
+++ b/kernel/nativelibrary.ml
@@ -29,7 +29,7 @@ and translate_field prefix mp env acc (l,x) =
| SFBconst cb ->
let con = Constant.make3 mp DirPath.empty l in
(if !Flags.debug then
- let msg = Printf.sprintf "Compiling constant %s..." (Constant.to_string con) in
+ let msg = Printf.sprintf "Compiling constant %s..." (Constant.to_string con) in
Feedback.msg_debug (Pp.str msg));
compile_constant_field env prefix con acc cb
| SFBmind mb ->
diff --git a/kernel/nativevalues.ml b/kernel/nativevalues.ml
index 91f6add1c3..93e74af845 100644
--- a/kernel/nativevalues.ml
+++ b/kernel/nativevalues.ml
@@ -63,7 +63,7 @@ type atom =
| Acofixe of t array * t array * int * t
| Aprod of Name.t * t * (t -> t)
| Ameta of metavariable * t
- | Aevar of Evar.t * t * t array
+ | Aevar of Evar.t * t array
| Aproj of (inductive * int) * accumulator
let accumulate_tag = 0
@@ -135,8 +135,8 @@ let mk_prod_accu s dom codom =
let mk_meta_accu mv ty =
mk_accu (Ameta (mv,ty))
-let mk_evar_accu ev ty args =
- mk_accu (Aevar (ev,ty,args))
+let mk_evar_accu ev args =
+ mk_accu (Aevar (ev, args))
let mk_proj_accu kn c =
mk_accu (Aproj (kn,c))
@@ -154,10 +154,6 @@ let args_of_accu (k:accumulator) =
let acc = (get_accu k).acc_arg in
(Obj.magic (Array.of_list acc) : t array)
-let is_accu x =
- let o = Obj.repr x in
- Obj.is_block o && Int.equal (Obj.tag o) accumulate_tag
-
let mk_fix_accu rec_pos pos types bodies =
mk_accu (Afix(types,bodies,rec_pos, pos))
@@ -172,19 +168,17 @@ let upd_cofix (cofix :t) (cofix_fun : t) =
| _ -> assert false
let force_cofix (cofix : t) =
- if is_accu cofix then
- let accu = (Obj.magic cofix : accumulator) in
- let atom = atom_of_accu accu in
- match atom with
- | Acofix(typ,norm,pos,f) ->
- let args = args_of_accu accu in
- let f = Array.fold_right (fun arg f -> f arg) args f in
- let v = f (Obj.magic ()) in
- set_atom_of_accu accu (Acofixe(typ,norm,pos,v));
- v
- | Acofixe(_,_,_,v) -> v
- | _ -> cofix
- else cofix
+ let accu = (Obj.magic cofix : accumulator) in
+ let atom = atom_of_accu accu in
+ match atom with
+ | Acofix(typ,norm,pos,f) ->
+ let args = args_of_accu accu in
+ let f = Array.fold_right (fun arg f -> f arg) args f in
+ let v = f (Obj.magic ()) in
+ set_atom_of_accu accu (Acofixe(typ,norm,pos,v));
+ v
+ | Acofixe(_,_,_,v) -> v
+ | _ -> cofix
let mk_const tag = Obj.magic tag
diff --git a/kernel/nativevalues.mli b/kernel/nativevalues.mli
index 6bbf15160c..10689941e8 100644
--- a/kernel/nativevalues.mli
+++ b/kernel/nativevalues.mli
@@ -53,7 +53,7 @@ type atom =
| Acofixe of t array * t array * int * t
| Aprod of Name.t * t * (t -> t)
| Ameta of metavariable * t
- | Aevar of Evar.t * t (* type *) * t array (* arguments *)
+ | Aevar of Evar.t * t array (* arguments *)
| Aproj of (inductive * int) * accumulator
(* Constructors *)
@@ -70,7 +70,7 @@ val mk_prod_accu : Name.t -> t -> t -> t
val mk_fix_accu : rec_pos -> int -> t array -> t array -> t
val mk_cofix_accu : int -> t array -> t array -> t
val mk_meta_accu : metavariable -> t
-val mk_evar_accu : Evar.t -> t -> t array -> t
+val mk_evar_accu : Evar.t -> t array -> t
val mk_proj_accu : (inductive * int) -> accumulator -> t
val upd_cofix : t -> t -> unit
val force_cofix : t -> t
diff --git a/kernel/opaqueproof.ml b/kernel/opaqueproof.ml
index f8b71e4564..303cb06c55 100644
--- a/kernel/opaqueproof.ml
+++ b/kernel/opaqueproof.ml
@@ -87,21 +87,21 @@ let discharge_direct_opaque ~cook_constr ci = function
| Direct (d,cu) ->
Direct (ci::d,Future.chain cu (fun (c, u) -> cook_constr c, u))
-let join_opaque { opaque_val = prfs; opaque_dir = odp } = function
+let join_opaque { opaque_val = prfs; opaque_dir = odp; _ } = function
| Direct (_,cu) -> ignore(Future.join cu)
| Indirect (_,dp,i) ->
if DirPath.equal dp odp then
let fp = snd (Int.Map.find i prfs) in
ignore(Future.join fp)
-let uuid_opaque { opaque_val = prfs; opaque_dir = odp } = function
+let uuid_opaque { opaque_val = prfs; opaque_dir = odp; _ } = function
| Direct (_,cu) -> Some (Future.uuid cu)
| Indirect (_,dp,i) ->
if DirPath.equal dp odp
then Some (Future.uuid (snd (Int.Map.find i prfs)))
else None
-let force_proof { opaque_val = prfs; opaque_dir = odp } = function
+let force_proof { opaque_val = prfs; opaque_dir = odp; _ } = function
| Direct (_,cu) ->
fst(Future.force cu)
| Indirect (l,dp,i) ->
@@ -112,7 +112,7 @@ let force_proof { opaque_val = prfs; opaque_dir = odp } = function
let c = Future.force pt in
force_constr (List.fold_right subst_substituted l (from_val c))
-let force_constraints { opaque_val = prfs; opaque_dir = odp } = function
+let force_constraints { opaque_val = prfs; opaque_dir = odp; _ } = function
| Direct (_,cu) -> snd(Future.force cu)
| Indirect (_,dp,i) ->
if DirPath.equal dp odp
@@ -121,14 +121,14 @@ let force_constraints { opaque_val = prfs; opaque_dir = odp } = function
| None -> Univ.ContextSet.empty
| Some u -> Future.force u
-let get_constraints { opaque_val = prfs; opaque_dir = odp } = function
+let get_constraints { opaque_val = prfs; opaque_dir = odp; _ } = function
| Direct (_,cu) -> Some(Future.chain cu snd)
| Indirect (_,dp,i) ->
if DirPath.equal dp odp
then Some(Future.chain (snd (Int.Map.find i prfs)) snd)
else !get_univ dp i
-let get_proof { opaque_val = prfs; opaque_dir = odp } = function
+let get_proof { opaque_val = prfs; opaque_dir = odp; _ } = function
| Direct (_,cu) -> Future.chain cu fst
| Indirect (l,dp,i) ->
let pt =
@@ -144,7 +144,7 @@ let a_constr = Future.from_val (mkRel 1)
let a_univ = Future.from_val Univ.ContextSet.empty
let a_discharge : cooking_info list = []
-let dump { opaque_val = otab; opaque_len = n } =
+let dump { opaque_val = otab; opaque_len = n; _ } =
let opaque_table = Array.make n a_constr in
let univ_table = Array.make n a_univ in
let disch_table = Array.make n a_discharge in
diff --git a/kernel/reduction.ml b/kernel/reduction.ml
index c701b53fe4..2abb4b485c 100644
--- a/kernel/reduction.ml
+++ b/kernel/reduction.ml
@@ -53,9 +53,9 @@ let compare_stack_shape stk1 stk2 =
| (_, (Zupdate _|Zshift _)::s2) -> compare_rec bal stk1 s2
| (Zapp l1::s1, _) -> compare_rec (bal+Array.length l1) s1 stk2
| (_, Zapp l2::s2) -> compare_rec (bal-Array.length l2) stk1 s2
- | (Zproj p1::s1, Zproj p2::s2) ->
+ | (Zproj _p1::s1, Zproj _p2::s2) ->
Int.equal bal 0 && compare_rec 0 s1 s2
- | (ZcaseT(c1,_,_,_)::s1, ZcaseT(c2,_,_,_)::s2) ->
+ | (ZcaseT(_c1,_,_,_)::s1, ZcaseT(_c2,_,_,_)::s2) ->
Int.equal bal 0 (* && c1.ci_ind = c2.ci_ind *) && compare_rec 0 s1 s2
| (Zfix(_,a1)::s1, Zfix(_,a2)::s2) ->
Int.equal bal 0 && compare_rec 0 a1 a2 && compare_rec 0 s1 s2
@@ -261,7 +261,7 @@ let convert_constructors_gen cmp_instances cmp_cumul (mind, ind, cns) nargs u1 u
s
| Declarations.Polymorphic_ind _ ->
cmp_instances u1 u2 s
- | Declarations.Cumulative_ind cumi ->
+ | Declarations.Cumulative_ind _cumi ->
let num_cnstr_args = constructor_cumulativity_arguments (mind,ind,cns) in
if not (Int.equal num_cnstr_args nargs) then
cmp_instances u1 u2 s
@@ -296,7 +296,7 @@ let compare_stacks f fmind lft1 stk1 lft2 stk2 cuniv =
(match (z1,z2) with
| (Zlapp a1,Zlapp a2) ->
Array.fold_right2 f a1 a2 cu1
- | (Zlproj (c1,l1),Zlproj (c2,l2)) ->
+ | (Zlproj (c1,_l1),Zlproj (c2,_l2)) ->
if not (Projection.Repr.equal c1 c2) then
raise NotConvertible
else cu1
@@ -498,7 +498,7 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
eqappr cv_pb l2r infos (lft1, r1) appr2 cuniv
| None ->
match c2 with
- | FConstruct ((ind2,j2),u2) ->
+ | FConstruct ((ind2,_j2),_u2) ->
(try
let v2, v1 =
eta_expand_ind_stack (info_env infos.cnv_inf) ind2 hd2 v2 (snd appr1)
@@ -515,7 +515,7 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
eqappr cv_pb l2r infos appr1 (lft2, r2) cuniv
| None ->
match c1 with
- | FConstruct ((ind1,j1),u1) ->
+ | FConstruct ((ind1,_j1),_u1) ->
(try let v1, v2 =
eta_expand_ind_stack (info_env infos.cnv_inf) ind1 hd1 v1 (snd appr2)
in convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
@@ -554,14 +554,14 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
else raise NotConvertible
(* Eta expansion of records *)
- | (FConstruct ((ind1,j1),u1), _) ->
+ | (FConstruct ((ind1,_j1),_u1), _) ->
(try
let v1, v2 =
eta_expand_ind_stack (info_env infos.cnv_inf) ind1 hd1 v1 (snd appr2)
in convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
with Not_found -> raise NotConvertible)
- | (_, FConstruct ((ind2,j2),u2)) ->
+ | (_, FConstruct ((ind2,_j2),_u2)) ->
(try
let v2, v1 =
eta_expand_ind_stack (info_env infos.cnv_inf) ind2 hd2 v2 (snd appr1)
@@ -659,14 +659,14 @@ let check_sort_cmp_universes env pb s0 s1 univs =
| Prop, (Set | Type _) -> if not (is_cumul pb) then raise NotConvertible
| Set, Prop -> raise NotConvertible
| Set, Type u -> check_pb Univ.type0_univ u
- | Type u, Prop -> raise NotConvertible
+ | Type _u, Prop -> raise NotConvertible
| Type u, Set -> check_pb u Univ.type0_univ
| Type u0, Type u1 -> check_pb u0 u1
let checked_sort_cmp_universes env pb s0 s1 univs =
check_sort_cmp_universes env pb s0 s1 univs; univs
-let check_convert_instances ~flex u u' univs =
+let check_convert_instances ~flex:_ u u' univs =
if UGraph.check_eq_instances univs u u' then univs
else raise NotConvertible
@@ -707,7 +707,7 @@ let infer_cmp_universes env pb s0 s1 univs =
| Prop, (Set | Type _) -> if not (is_cumul pb) then raise NotConvertible else univs
| Set, Prop -> raise NotConvertible
| Set, Type u -> infer_pb Univ.type0_univ u
- | Type u, Prop -> raise NotConvertible
+ | Type _u, Prop -> raise NotConvertible
| Type u, Set -> infer_pb u Univ.type0_univ
| Type u0, Type u1 -> infer_pb u0 u1
@@ -781,7 +781,7 @@ let infer_conv_leq ?(l2r=false) ?(evars=fun _ -> None) ?(ts=full_transparent_sta
env univs t1 t2 =
infer_conv_universes CUMUL l2r evars ts env univs t1 t2
-let default_conv cv_pb ?(l2r=false) env t1 t2 =
+let default_conv cv_pb ?l2r:_ env t1 t2 =
gen_conv cv_pb env t1 t2
let default_conv_leq = default_conv CUMUL
@@ -912,7 +912,7 @@ let is_arity env c =
with NotArity -> false
let eta_expand env t ty =
- let ctxt, codom = dest_prod env ty in
+ let ctxt, _codom = dest_prod env ty in
let ctxt',t = dest_lam env t in
let d = Context.Rel.nhyps ctxt - Context.Rel.nhyps ctxt' in
let eta_args = List.rev_map mkRel (List.interval 1 d) in
diff --git a/kernel/retroknowledge.ml b/kernel/retroknowledge.ml
index 34f62defb8..e51c25c06b 100644
--- a/kernel/retroknowledge.ml
+++ b/kernel/retroknowledge.ml
@@ -19,12 +19,9 @@ open Names
open Constr
(* The retroknowledge defines a bijective correspondance between some
- [entry]-s (which are, in fact, merely terms) and [field]-s which
+ [entry]-s (which are, in fact, merely names) and [field]-s which
are roles assigned to these entries. *)
-(* aliased type for clarity purpose*)
-type entry = Constr.t
-
type int31_field =
| Int31Bits
| Int31Type
@@ -53,8 +50,37 @@ type int31_field =
| Int31Lxor
type field =
- | KInt31 of string*int31_field
-
+ | KInt31 of int31_field
+
+let int31_field_of_string =
+ function
+ | "bits" -> Int31Bits
+ | "type" -> Int31Type
+ | "twice" -> Int31Twice
+ | "twice_plus_one" -> Int31TwicePlusOne
+ | "phi" -> Int31Phi
+ | "phi_inv" -> Int31PhiInv
+ | "plus" -> Int31Plus
+ | "plusc" -> Int31PlusC
+ | "pluscarryc" -> Int31PlusCarryC
+ | "minus" -> Int31Minus
+ | "minusc" -> Int31MinusC
+ | "minuscarryc" -> Int31MinusCarryC
+ | "times" -> Int31Times
+ | "timesc" -> Int31TimesC
+ | "div21" -> Int31Div21
+ | "div" -> Int31Div
+ | "diveucl" -> Int31Diveucl
+ | "addmuldiv" -> Int31AddMulDiv
+ | "compare" -> Int31Compare
+ | "head0" -> Int31Head0
+ | "tail0" -> Int31Tail0
+ | "lor" -> Int31Lor
+ | "land" -> Int31Land
+ | "lxor" -> Int31Lxor
+ | s -> CErrors.user_err Pp.(str "Registering unknown int31 operator " ++ str s)
+
+let int31_path = DirPath.make [ Id.of_string "int31" ]
(* record representing all the flags of the internal state of the kernel *)
type flags = {fastcomputation : bool}
@@ -68,19 +94,13 @@ type flags = {fastcomputation : bool}
module Proactive =
Map.Make (struct type t = field let compare = Pervasives.compare end)
-type proactive = entry Proactive.t
+type proactive = GlobRef.t Proactive.t
(* The [reactive] knowledge contains the mapping
[entry->field]. Fields are later to be interpreted as a
[reactive_info]. *)
-module EntryOrd =
-struct
- type t = entry
- let compare = Constr.compare
-end
-
-module Reactive = Map.Make (EntryOrd)
+module Reactive = GlobRef.Map
type reactive_info = {(*information required by the compiler of the VM *)
vm_compiling :
@@ -127,7 +147,7 @@ and retroknowledge = {flags : flags; proactive : proactive; reactive : reactive}
(* As per now, there is only the possibility of registering things
the possibility of unregistering or changing the flag is under study *)
type action =
- | RKRegister of field*entry
+ | RKRegister of field * GlobRef.t
(*initialisation*)
diff --git a/kernel/retroknowledge.mli b/kernel/retroknowledge.mli
index 02d961d893..0a2ef5300e 100644
--- a/kernel/retroknowledge.mli
+++ b/kernel/retroknowledge.mli
@@ -13,9 +13,6 @@ open Constr
type retroknowledge
-(** aliased type for clarity purpose*)
-type entry = Constr.t
-
(** the following types correspond to the different "things"
the kernel can learn about.*)
type int31_field =
@@ -46,14 +43,18 @@ type int31_field =
| Int31Lxor
type field =
- | KInt31 of string*int31_field
+ | KInt31 of int31_field
+
+val int31_field_of_string : string -> int31_field
+
+val int31_path : DirPath.t
(** This type represent an atomic action of the retroknowledge. It
is stored in the compiled libraries
As per now, there is only the possibility of registering things
the possibility of unregistering or changing the flag is under study *)
type action =
- | RKRegister of field*entry
+ | RKRegister of field * GlobRef.t
(** initial value for retroknowledge *)
@@ -64,7 +65,7 @@ val initial_retroknowledge : retroknowledge
and the continuation cont of the bytecode compilation
returns the compilation of id in cont if it has a specific treatment
or raises Not_found if id should be compiled as usual *)
-val get_vm_compiling_info : retroknowledge -> entry ->
+val get_vm_compiling_info : retroknowledge -> GlobRef.t ->
Cinstr.lambda array -> Cinstr.lambda
(*Given an identifier id (usually Construct _)
and its argument array, returns a function that tries an ad-hoc optimisated
@@ -73,7 +74,7 @@ val get_vm_compiling_info : retroknowledge -> entry ->
raises Not_found if id should be compiled as usual, and expectingly
CBytecodes.NotClosed if the term is not a closed constructor pattern
(a constant for the compiler) *)
-val get_vm_constant_static_info : retroknowledge -> entry ->
+val get_vm_constant_static_info : retroknowledge -> GlobRef.t ->
constr array -> Cinstr.lambda
(*Given an identifier id (usually Construct _ )
@@ -81,45 +82,45 @@ val get_vm_constant_static_info : retroknowledge -> entry ->
of id+args+cont when id has a specific treatment (in the case of
31-bit integers, that would be the dynamic compilation into integers)
or raises Not_found if id should be compiled as usual *)
-val get_vm_constant_dynamic_info : retroknowledge -> entry ->
+val get_vm_constant_dynamic_info : retroknowledge -> GlobRef.t ->
Cinstr.lambda array -> Cinstr.lambda
(** Given a type identifier, this function is used before compiling a match
over this type. In the case of 31-bit integers for instance, it is used
to add the instruction sequence which would perform a dynamic decompilation
in case the argument of the match is not in coq representation *)
-val get_vm_before_match_info : retroknowledge -> entry -> Cinstr.lambda
+val get_vm_before_match_info : retroknowledge -> GlobRef.t -> Cinstr.lambda
-> Cinstr.lambda
(** Given a type identifier, this function is used by pretyping/vnorm.ml to
recover the elements of that type from their compiled form if it's non
standard (it is used (and can be used) only when the compiled form
is not a block *)
-val get_vm_decompile_constant_info : retroknowledge -> entry -> int -> constr
+val get_vm_decompile_constant_info : retroknowledge -> GlobRef.t -> int -> constr
-val get_native_compiling_info : retroknowledge -> entry -> Nativeinstr.prefix ->
+val get_native_compiling_info : retroknowledge -> GlobRef.t -> Nativeinstr.prefix ->
Nativeinstr.lambda array -> Nativeinstr.lambda
-val get_native_constant_static_info : retroknowledge -> entry ->
+val get_native_constant_static_info : retroknowledge -> GlobRef.t ->
constr array -> Nativeinstr.lambda
-val get_native_constant_dynamic_info : retroknowledge -> entry ->
+val get_native_constant_dynamic_info : retroknowledge -> GlobRef.t ->
Nativeinstr.prefix -> constructor ->
Nativeinstr.lambda array ->
Nativeinstr.lambda
-val get_native_before_match_info : retroknowledge -> entry ->
+val get_native_before_match_info : retroknowledge -> GlobRef.t ->
Nativeinstr.prefix -> constructor ->
Nativeinstr.lambda -> Nativeinstr.lambda
(** the following functions are solely used in Environ and Safe_typing to implement
the functions register and unregister (and mem) of Environ *)
-val add_field : retroknowledge -> field -> entry -> retroknowledge
+val add_field : retroknowledge -> field -> GlobRef.t -> retroknowledge
val mem : retroknowledge -> field -> bool
(* val remove : retroknowledge -> field -> retroknowledge *)
-val find : retroknowledge -> field -> entry
+val find : retroknowledge -> field -> GlobRef.t
(** Dispatching type for the above [get_*] functions. *)
@@ -161,4 +162,4 @@ val empty_reactive_info : reactive_info
(** Hook to be set after the compiler are installed to dispatch fields
into the above [get_*] functions. *)
-val dispatch_hook : (retroknowledge -> entry -> field -> reactive_info) Hook.t
+val dispatch_hook : (retroknowledge -> GlobRef.t -> field -> reactive_info) Hook.t
diff --git a/kernel/safe_typing.ml b/kernel/safe_typing.ml
index f87ec9e023..b036aa6a67 100644
--- a/kernel/safe_typing.ml
+++ b/kernel/safe_typing.ml
@@ -210,13 +210,8 @@ let get_opaque_body env cbo =
(Opaqueproof.force_proof (Environ.opaque_tables env) opaque,
Opaqueproof.force_constraints (Environ.opaque_tables env) opaque)
-type private_constant = Entries.side_effect
type private_constants = Term_typing.side_effects
-type private_constant_role = Term_typing.side_effect_role =
- | Subproof
- | Schema of inductive * string
-
let empty_private_constants = Term_typing.empty_seff
let add_private = Term_typing.add_seff
let concat_private = Term_typing.concat_seff
@@ -225,44 +220,38 @@ let inline_private_constants_in_constr = Term_typing.inline_side_effects
let inline_private_constants_in_definition_entry = Term_typing.inline_entry_side_effects
let side_effects_of_private_constants = Term_typing.uniq_seff
+let make_eff env cst r =
+ let open Entries in
+ let cbo = Environ.lookup_constant cst env.env in
+ {
+ seff_constant = cst;
+ seff_body = cbo;
+ seff_env = get_opaque_body env.env cbo;
+ seff_role = r;
+ }
+
let private_con_of_con env c =
- let cbo = Environ.lookup_constant c env.env in
- { Entries.from_env = CEphemeron.create env.revstruct;
- Entries.eff = Entries.SEsubproof (c,cbo,get_opaque_body env.env cbo) }
+ let open Entries in
+ let eff = [make_eff env c Subproof] in
+ add_private env.revstruct eff empty_private_constants
let private_con_of_scheme ~kind env cl =
- { Entries.from_env = CEphemeron.create env.revstruct;
- Entries.eff = Entries.SEscheme(
- List.map (fun (i,c) ->
- let cbo = Environ.lookup_constant c env.env in
- i, c, cbo, get_opaque_body env.env cbo) cl,
- kind) }
+ let open Entries in
+ let eff = List.map (fun (i, c) -> make_eff env c (Schema (i, kind))) cl in
+ add_private env.revstruct eff empty_private_constants
let universes_of_private eff =
- let open Declarations in
- List.fold_left
- (fun acc { Entries.eff } ->
- match eff with
- | Entries.SEscheme (l,s) ->
- List.fold_left
- (fun acc (_,_,cb,c) ->
- let acc = match c with
- | `Nothing -> acc
- | `Opaque (_, ctx) -> ctx :: acc
- in
- match cb.const_universes with
- | Monomorphic_const ctx ->
- ctx :: acc
- | Polymorphic_const _ -> acc
- )
- acc l
- | Entries.SEsubproof (c, cb, e) ->
- match cb.const_universes with
- | Monomorphic_const ctx ->
- ctx :: acc
- | Polymorphic_const _ -> acc
- )
- [] (Term_typing.uniq_seff eff)
+ let open Entries in
+ let fold acc eff =
+ let acc = match eff.seff_env with
+ | `Nothing -> acc
+ | `Opaque (_, ctx) -> ctx :: acc
+ in
+ match eff.seff_body.const_universes with
+ | Monomorphic_const ctx -> ctx :: acc
+ | Polymorphic_const _ -> acc
+ in
+ List.fold_left fold [] (Term_typing.uniq_seff eff)
let env_of_safe_env senv = senv.env
let env_of_senv = env_of_safe_env
@@ -284,7 +273,6 @@ let add_constraints_list cst senv =
List.fold_left (fun acc c -> add_constraints c acc) senv cst
let push_context_set poly ctx = add_constraints (Now (poly,ctx))
-let push_context poly ctx = add_constraints (Now (poly,Univ.ContextSet.of_context ctx))
let is_curmod_library senv =
match senv.modvariant with LIBRARY -> true | _ -> false
@@ -489,7 +477,7 @@ type global_declaration =
| GlobalRecipe of Cooking.recipe
type exported_private_constant =
- Constant.t * private_constant_role
+ Constant.t * Entries.side_effect_role
let add_constant_aux no_section senv (kn, cb) =
let l = pi3 (Constant.repr3 kn) in
@@ -903,8 +891,8 @@ let retroknowledge f senv =
Environ.retroknowledge f (env_of_senv senv)
[@@@ocaml.warning "+3"]
-let register field value by_clause senv =
- (* todo : value closed, by_clause safe, by_clause of the proper type*)
+let register field value senv =
+ (* todo : value closed *)
(* spiwack : updates the safe_env with the information that the register
action has to be performed (again) when the environment is imported *)
{ senv with
@@ -988,39 +976,39 @@ let dispatch =
it to the name of the coq definition in the reactive retroknowledge) *)
let int31_op n op prim kn =
{ empty_reactive_info with
- vm_compiling = Some (Clambda.compile_prim n op kn);
- native_compiling = Some (Nativelambda.compile_prim prim (Univ.out_punivs kn));
+ vm_compiling = Some (Clambda.compile_prim n op (kn, Univ.Instance.empty)); (*XXX: FIXME universes? *)
+ native_compiling = Some (Nativelambda.compile_prim prim kn);
}
in
fun rk value field ->
(* subfunction which shortens the (very common) dispatch of operations *)
let int31_op_from_const n op prim =
- match Constr.kind value with
- | Constr.Const kn -> int31_op n op prim kn
+ match value with
+ | GlobRef.ConstRef kn -> int31_op n op prim kn
| _ -> anomaly ~label:"Environ.register" (Pp.str "should be a constant.")
in
let int31_binop_from_const op prim = int31_op_from_const 2 op prim in
let int31_unop_from_const op prim = int31_op_from_const 1 op prim in
match field with
- | KInt31 (grp, Int31Type) ->
+ | KInt31 Int31Type ->
let int31bit =
(* invariant : the type of bits is registered, otherwise the function
would raise Not_found. The invariant is enforced in safe_typing.ml *)
match field with
- | KInt31 (grp, Int31Type) -> Retroknowledge.find rk (KInt31 (grp,Int31Bits))
+ | KInt31 Int31Type -> Retroknowledge.find rk (KInt31 Int31Bits)
| _ -> anomaly ~label:"Environ.register"
(Pp.str "add_int31_decompilation_from_type called with an abnormal field.")
in
let i31bit_type =
- match Constr.kind int31bit with
- | Constr.Ind (i31bit_type,_) -> i31bit_type
+ match int31bit with
+ | GlobRef.IndRef i31bit_type -> i31bit_type
| _ -> anomaly ~label:"Environ.register"
(Pp.str "Int31Bits should be an inductive type.")
in
let int31_decompilation =
- match Constr.kind value with
- | Constr.Ind (i31t,_) ->
+ match value with
+ | GlobRef.IndRef i31t ->
constr_of_int31 i31t i31bit_type
| _ -> anomaly ~label:"Environ.register"
(Pp.str "should be an inductive type.")
@@ -1030,46 +1018,46 @@ fun rk value field ->
vm_before_match = Some Clambda.int31_escape_before_match;
native_before_match = Some (Nativelambda.before_match_int31 i31bit_type);
}
- | KInt31 (_, Int31Constructor) ->
+ | KInt31 Int31Constructor ->
{ empty_reactive_info with
vm_constant_static = Some Clambda.compile_structured_int31;
vm_constant_dynamic = Some Clambda.dynamic_int31_compilation;
native_constant_static = Some Nativelambda.compile_static_int31;
native_constant_dynamic = Some Nativelambda.compile_dynamic_int31;
}
- | KInt31 (_, Int31Plus) -> int31_binop_from_const Cbytecodes.Kaddint31
+ | KInt31 Int31Plus -> int31_binop_from_const Cbytecodes.Kaddint31
CPrimitives.Int31add
- | KInt31 (_, Int31PlusC) -> int31_binop_from_const Cbytecodes.Kaddcint31
+ | KInt31 Int31PlusC -> int31_binop_from_const Cbytecodes.Kaddcint31
CPrimitives.Int31addc
- | KInt31 (_, Int31PlusCarryC) -> int31_binop_from_const Cbytecodes.Kaddcarrycint31
+ | KInt31 Int31PlusCarryC -> int31_binop_from_const Cbytecodes.Kaddcarrycint31
CPrimitives.Int31addcarryc
- | KInt31 (_, Int31Minus) -> int31_binop_from_const Cbytecodes.Ksubint31
+ | KInt31 Int31Minus -> int31_binop_from_const Cbytecodes.Ksubint31
CPrimitives.Int31sub
- | KInt31 (_, Int31MinusC) -> int31_binop_from_const Cbytecodes.Ksubcint31
+ | KInt31 Int31MinusC -> int31_binop_from_const Cbytecodes.Ksubcint31
CPrimitives.Int31subc
- | KInt31 (_, Int31MinusCarryC) -> int31_binop_from_const
+ | KInt31 Int31MinusCarryC -> int31_binop_from_const
Cbytecodes.Ksubcarrycint31 CPrimitives.Int31subcarryc
- | KInt31 (_, Int31Times) -> int31_binop_from_const Cbytecodes.Kmulint31
+ | KInt31 Int31Times -> int31_binop_from_const Cbytecodes.Kmulint31
CPrimitives.Int31mul
- | KInt31 (_, Int31TimesC) -> int31_binop_from_const Cbytecodes.Kmulcint31
+ | KInt31 Int31TimesC -> int31_binop_from_const Cbytecodes.Kmulcint31
CPrimitives.Int31mulc
- | KInt31 (_, Int31Div21) -> int31_op_from_const 3 Cbytecodes.Kdiv21int31
+ | KInt31 Int31Div21 -> int31_op_from_const 3 Cbytecodes.Kdiv21int31
CPrimitives.Int31div21
- | KInt31 (_, Int31Diveucl) -> int31_binop_from_const Cbytecodes.Kdivint31
+ | KInt31 Int31Diveucl -> int31_binop_from_const Cbytecodes.Kdivint31
CPrimitives.Int31diveucl
- | KInt31 (_, Int31AddMulDiv) -> int31_op_from_const 3 Cbytecodes.Kaddmuldivint31
+ | KInt31 Int31AddMulDiv -> int31_op_from_const 3 Cbytecodes.Kaddmuldivint31
CPrimitives.Int31addmuldiv
- | KInt31 (_, Int31Compare) -> int31_binop_from_const Cbytecodes.Kcompareint31
+ | KInt31 Int31Compare -> int31_binop_from_const Cbytecodes.Kcompareint31
CPrimitives.Int31compare
- | KInt31 (_, Int31Head0) -> int31_unop_from_const Cbytecodes.Khead0int31
+ | KInt31 Int31Head0 -> int31_unop_from_const Cbytecodes.Khead0int31
CPrimitives.Int31head0
- | KInt31 (_, Int31Tail0) -> int31_unop_from_const Cbytecodes.Ktail0int31
+ | KInt31 Int31Tail0 -> int31_unop_from_const Cbytecodes.Ktail0int31
CPrimitives.Int31tail0
- | KInt31 (_, Int31Lor) -> int31_binop_from_const Cbytecodes.Klorint31
+ | KInt31 Int31Lor -> int31_binop_from_const Cbytecodes.Klorint31
CPrimitives.Int31lor
- | KInt31 (_, Int31Land) -> int31_binop_from_const Cbytecodes.Klandint31
+ | KInt31 Int31Land -> int31_binop_from_const Cbytecodes.Klandint31
CPrimitives.Int31land
- | KInt31 (_, Int31Lxor) -> int31_binop_from_const Cbytecodes.Klxorint31
+ | KInt31 Int31Lxor -> int31_binop_from_const Cbytecodes.Klxorint31
CPrimitives.Int31lxor
| _ -> empty_reactive_info
diff --git a/kernel/safe_typing.mli b/kernel/safe_typing.mli
index aca77ccd13..6e0febaa3f 100644
--- a/kernel/safe_typing.mli
+++ b/kernel/safe_typing.mli
@@ -41,29 +41,20 @@ type 'a safe_transformer = safe_environment -> 'a * safe_environment
(** {6 Stm machinery } *)
-type private_constant
type private_constants
-type private_constant_role =
- | Subproof
- | Schema of inductive * string
-
val side_effects_of_private_constants :
- private_constants -> Entries.side_effect list
+ private_constants -> Entries.side_eff list
(** Return the list of individual side-effects in the order of their
creation. *)
val empty_private_constants : private_constants
-val add_private : private_constant -> private_constants -> private_constants
-(** Add a constant to a list of private constants. The former must be more
- recent than all constants appearing in the latter, i.e. one should not
- create a dependency cycle. *)
val concat_private : private_constants -> private_constants -> private_constants
(** [concat_private e1 e2] adds the constants of [e1] to [e2], i.e. constants in
[e1] must be more recent than those of [e2]. *)
-val private_con_of_con : safe_environment -> Constant.t -> private_constant
-val private_con_of_scheme : kind:string -> safe_environment -> (inductive * Constant.t) list -> private_constant
+val private_con_of_con : safe_environment -> Constant.t -> private_constants
+val private_con_of_scheme : kind:string -> safe_environment -> (inductive * Constant.t) list -> private_constants
val mk_pure_proof : Constr.constr -> private_constants Entries.proof_output
val inline_private_constants_in_constr :
@@ -105,7 +96,7 @@ type global_declaration =
| GlobalRecipe of Cooking.recipe
type exported_private_constant =
- Constant.t * private_constant_role
+ Constant.t * Entries.side_effect_role
val export_private_constants : in_section:bool ->
private_constants Entries.definition_entry ->
@@ -137,9 +128,6 @@ val add_modtype :
val push_context_set :
bool -> Univ.ContextSet.t -> safe_transformer0
-val push_context :
- bool -> Univ.UContext.t -> safe_transformer0
-
val add_constraints :
Univ.Constraint.t -> safe_transformer0
@@ -224,7 +212,7 @@ val retroknowledge : (retroknowledge-> 'a) -> safe_environment -> 'a
[@@ocaml.deprecated "Use the projection of Environ.env"]
val register :
- field -> Retroknowledge.entry -> Constr.constr -> safe_transformer0
+ field -> GlobRef.t -> safe_transformer0
val register_inline : Constant.t -> safe_transformer0
diff --git a/kernel/subtyping.ml b/kernel/subtyping.ml
index 74042f9e04..bfe68671a2 100644
--- a/kernel/subtyping.ml
+++ b/kernel/subtyping.ml
@@ -138,7 +138,7 @@ let check_inductive cst env mp1 l info1 mp2 mib2 spec2 subst1 subst2 reso1 reso2
let mib2 = Declareops.subst_mind_body subst2 mib2 in
let check_inductive_type cst name t1 t2 =
check_conv (NotConvertibleInductiveField name)
- cst (inductive_is_polymorphic mib1) infer_conv_leq env t1 t2
+ cst (inductive_is_polymorphic mib1) (infer_conv_leq ?l2r:None ?evars:None ?ts:None) env t1 t2
in
let check_packet cst p1 p2 =
@@ -162,10 +162,10 @@ let check_inductive cst env mp1 l info1 mp2 mib2 spec2 subst1 subst2 reso1 reso2
cst
in
let mind = MutInd.make1 kn1 in
- let check_cons_types i cst p1 p2 =
+ let check_cons_types _i cst p1 p2 =
Array.fold_left3
(fun cst id t1 t2 -> check_conv (NotConvertibleConstructorField id) cst
- (inductive_is_polymorphic mib1) infer_conv env t1 t2)
+ (inductive_is_polymorphic mib1) (infer_conv ?l2r:None ?evars:None ?ts:None) env t1 t2)
cst
p2.mind_consnames
(arities_of_specif (mind, inst) (mib1, p1))
@@ -229,7 +229,7 @@ let check_constant cst env l info1 cb2 spec2 subst1 subst2 =
let check_conv cst poly f = check_conv_error error cst poly f in
let check_type poly cst env t1 t2 =
let err = NotConvertibleTypeField (env, t1, t2) in
- check_conv err cst poly infer_conv_leq env t1 t2
+ check_conv err cst poly (infer_conv_leq ?l2r:None ?evars:None ?ts:None) env t1 t2
in
match info1 with
| Constant cb1 ->
@@ -268,14 +268,14 @@ let check_constant cst env l info1 cb2 spec2 subst1 subst2 =
Anyway [check_conv] will handle that afterwards. *)
let c1 = Mod_subst.force_constr lc1 in
let c2 = Mod_subst.force_constr lc2 in
- check_conv NotConvertibleBodyField cst poly infer_conv env c1 c2))
- | IndType ((kn,i),mind1) ->
+ check_conv NotConvertibleBodyField cst poly (infer_conv ?l2r:None ?evars:None ?ts:None) env c1 c2))
+ | IndType ((_kn,_i),_mind1) ->
CErrors.user_err Pp.(str @@
"The kernel does not recognize yet that a parameter can be " ^
"instantiated by an inductive type. Hint: you can rename the " ^
"inductive type and give a definition to map the old name to the new " ^
"name.")
- | IndConstr (((kn,i),j),mind1) ->
+ | IndConstr (((_kn,_i),_j),_mind1) ->
CErrors.user_err Pp.(str @@
"The kernel does not recognize yet that a parameter can be " ^
"instantiated by a constructor. Hint: you can rename the " ^
diff --git a/kernel/term.ml b/kernel/term.ml
index 4851a9c0d0..795cdeb040 100644
--- a/kernel/term.ml
+++ b/kernel/term.ml
@@ -54,13 +54,13 @@ let mkProd_wo_LetIn decl c =
let open Context.Rel.Declaration in
match decl with
| LocalAssum (na,t) -> mkProd (na, t, c)
- | LocalDef (na,b,t) -> subst1 b c
+ | LocalDef (_na,b,_t) -> subst1 b c
let mkNamedProd_wo_LetIn decl c =
let open Context.Named.Declaration in
match decl with
| LocalAssum (id,t) -> mkNamedProd id t c
- | LocalDef (id,b,t) -> subst1 b (subst_var id c)
+ | LocalDef (id,b,_t) -> subst1 b (subst_var id c)
(* non-dependent product t1 -> t2 *)
let mkArrow t1 t2 = mkProd (Anonymous, t1, t2)
@@ -81,7 +81,7 @@ let mkNamedLambda_or_LetIn decl c =
(* prodn n [xn:Tn;..;x1:T1;Gamma] b = (x1:T1)..(xn:Tn)b *)
let prodn n env b =
let rec prodrec = function
- | (0, env, b) -> b
+ | (0, _env, b) -> b
| (n, ((v,t)::l), b) -> prodrec (n-1, l, mkProd (v,t,b))
| _ -> assert false
in
@@ -93,7 +93,7 @@ let compose_prod l b = prodn (List.length l) l b
(* lamn n [xn:Tn;..;x1:T1;Gamma] b = [x1:T1]..[xn:Tn]b *)
let lamn n env b =
let rec lamrec = function
- | (0, env, b) -> b
+ | (0, _env, b) -> b
| (n, ((v,t)::l), b) -> lamrec (n-1, l, mkLambda (v,t,b))
| _ -> assert false
in
@@ -276,7 +276,7 @@ let decompose_prod_n_assum n =
| Prod (x,t,c) -> prodec_rec (Context.Rel.add (LocalAssum (x,t)) l) (n-1) c
| LetIn (x,b,t,c) -> prodec_rec (Context.Rel.add (LocalDef (x,b,t)) l) (n-1) c
| Cast (c,_,_) -> prodec_rec l n c
- | c -> user_err (str "decompose_prod_n_assum: not enough assumptions")
+ | _ -> user_err (str "decompose_prod_n_assum: not enough assumptions")
in
prodec_rec Context.Rel.empty n
@@ -297,7 +297,7 @@ let decompose_lam_n_assum n =
| Lambda (x,t,c) -> lamdec_rec (Context.Rel.add (LocalAssum (x,t)) l) (n-1) c
| LetIn (x,b,t,c) -> lamdec_rec (Context.Rel.add (LocalDef (x,b,t)) l) n c
| Cast (c,_,_) -> lamdec_rec l n c
- | c -> user_err (str "decompose_lam_n_assum: not enough abstractions")
+ | _c -> user_err (str "decompose_lam_n_assum: not enough abstractions")
in
lamdec_rec Context.Rel.empty n
@@ -313,7 +313,7 @@ let decompose_lam_n_decls n =
| Lambda (x,t,c) -> lamdec_rec (Context.Rel.add (LocalAssum (x,t)) l) (n-1) c
| LetIn (x,b,t,c) -> lamdec_rec (Context.Rel.add (LocalDef (x,b,t)) l) (n-1) c
| Cast (c,_,_) -> lamdec_rec l n c
- | c -> user_err (str "decompose_lam_n_decls: not enough abstractions")
+ | _ -> user_err (str "decompose_lam_n_decls: not enough abstractions")
in
lamdec_rec Context.Rel.empty n
diff --git a/kernel/term_typing.ml b/kernel/term_typing.ml
index 1f7ee145a2..47247ff25e 100644
--- a/kernel/term_typing.ml
+++ b/kernel/term_typing.ml
@@ -27,16 +27,10 @@ module NamedDecl = Context.Named.Declaration
(* Insertion of constants and parameters in environment. *)
-let equal_eff e1 e2 =
- let open Entries in
- match e1, e2 with
- | { eff = SEsubproof (c1,_,_) }, { eff = SEsubproof (c2,_,_) } ->
- Names.Constant.equal c1 c2
- | { eff = SEscheme (cl1,_) }, { eff = SEscheme (cl2,_) } ->
- CList.for_all2eq
- (fun (_,c1,_,_) (_,c2,_,_) -> Names.Constant.equal c1 c2)
- cl1 cl2
- | _ -> false
+type side_effect = {
+ from_env : Declarations.structure_body CEphemeron.key;
+ eff : side_eff list;
+}
module SideEffects :
sig
@@ -48,17 +42,11 @@ sig
end =
struct
-let compare_seff e1 e2 = match e1, e2 with
-| SEsubproof (c1, _, _), SEsubproof (c2, _, _) -> Constant.CanOrd.compare c1 c2
-| SEscheme (cl1, _), SEscheme (cl2, _) ->
- let cmp (_, c1, _, _) (_, c2, _, _) = Constant.CanOrd.compare c1 c2 in
- CList.compare cmp cl1 cl2
-| SEsubproof _, SEscheme _ -> -1
-| SEscheme _, SEsubproof _ -> 1
-
module SeffOrd = struct
type t = side_effect
-let compare e1 e2 = compare_seff e1.eff e2.eff
+let compare e1 e2 =
+ let cmp e1 e2 = Constant.CanOrd.compare e1.seff_constant e2.seff_constant in
+ List.compare cmp e1.eff e2.eff
end
module SeffSet = Set.Make(SeffOrd)
@@ -83,10 +71,14 @@ type _ trust =
| SideEffects : structure_body -> side_effects trust
let uniq_seff_rev = SideEffects.repr
-let uniq_seff l = List.rev (SideEffects.repr l)
+let uniq_seff l =
+ let ans = List.rev (SideEffects.repr l) in
+ List.map_append (fun { eff ; _ } -> eff) ans
let empty_seff = SideEffects.empty
-let add_seff = SideEffects.add
+let add_seff mb eff effs =
+ let from_env = CEphemeron.create mb in
+ SideEffects.add { eff; from_env } effs
let concat_seff = SideEffects.concat
let mk_pure_proof c = (c, Univ.ContextSet.empty), empty_seff
@@ -94,11 +86,8 @@ let mk_pure_proof c = (c, Univ.ContextSet.empty), empty_seff
let inline_side_effects env body ctx side_eff =
(** First step: remove the constants that are still in the environment *)
let filter { eff = se; from_env = mb } =
- let cbl = match se with
- | SEsubproof (c, cb, b) -> [c, cb, b]
- | SEscheme (cl,_) ->
- List.map (fun (_, c, cb, b) -> c, cb, b) cl
- in
+ let map e = (e.seff_constant, e.seff_body, e.seff_env) in
+ let cbl = List.map map se in
let not_exists (c,_,_) =
try ignore(Environ.lookup_constant c env); false
with Not_found -> true in
@@ -114,12 +103,7 @@ let inline_side_effects env body ctx side_eff =
if List.is_empty side_eff then (body, ctx, sigs)
else
(** Second step: compute the lifts and substitutions to apply *)
- let cname c =
- let name = Constant.to_string c in
- let map c = if c == '.' || c == '#' then '_' else c in
- let name = String.map map name in
- Name (Id.of_string name)
- in
+ let cname c = Name (Label.to_id (Constant.label c)) in
let fold (subst, var, ctx, args) (c, cb, b) =
let (b, opaque) = match cb.const_body, b with
| Def b, _ -> (Mod_subst.force_constr b, false)
@@ -133,7 +117,7 @@ let inline_side_effects env body ctx side_eff =
let subst = Cmap_env.add c (Inr var) subst in
let ctx = Univ.ContextSet.union ctx univs in
(subst, var + 1, ctx, (cname c, b, ty, opaque) :: args)
- | Polymorphic_const auctx ->
+ | Polymorphic_const _auctx ->
(** Inline the term to emulate universe polymorphism *)
let subst = Cmap_env.add c (Inl b) subst in
(subst, var, ctx, args)
@@ -261,12 +245,14 @@ let infer_declaration (type a) ~(trust : a trust) env (dcl : a constant_entry) =
delay even in the polymorphic case. *)
| DefinitionEntry ({ const_entry_type = Some typ;
const_entry_opaque = true;
- const_entry_universes = Monomorphic_const_entry univs } as c) ->
+ const_entry_universes = Monomorphic_const_entry univs; _ } as c) ->
let env = push_context_set ~strict:true univs env in
- let { const_entry_body = body; const_entry_feedback = feedback_id } = c in
+ let { const_entry_body = body; const_entry_feedback = feedback_id ; _ } = c in
let tyj = infer_type env typ in
let proofterm =
Future.chain body (fun ((body,uctx),side_eff) ->
+ (* don't redeclare universes which are declared for the type *)
+ let uctx = Univ.ContextSet.diff uctx univs in
let j, uctx = match trust with
| Pure ->
let env = push_context_set uctx env in
@@ -297,8 +283,8 @@ let infer_declaration (type a) ~(trust : a trust) env (dcl : a constant_entry) =
(** Other definitions have to be processed immediately. *)
| DefinitionEntry c ->
- let { const_entry_type = typ; const_entry_opaque = opaque } = c in
- let { const_entry_body = body; const_entry_feedback = feedback_id } = c in
+ let { const_entry_type = typ; const_entry_opaque = opaque ; _ } = c in
+ let { const_entry_body = body; const_entry_feedback = feedback_id; _ } = c in
let (body, ctx), side_eff = Future.join body in
let body, ctx, _ = match trust with
| Pure -> body, ctx, []
@@ -357,7 +343,7 @@ let record_aux env s_ty s_bo =
(keep_hyps env s_bo)) in
Aux_file.record_in_aux "context_used" v
-let build_constant_declaration kn env result =
+let build_constant_declaration _kn env result =
let open Cooking in
let typ = result.cook_type in
let check declared inferred =
@@ -468,58 +454,50 @@ let constant_entry_of_side_effect cb u =
const_entry_inline_code = cb.const_inline_code }
;;
-let turn_direct (kn,cb,u,r as orig) =
- match cb.const_body, u with
- | OpaqueDef _, `Opaque (b,c) ->
- let pt = Future.from_val (b,c) in
- kn, { cb with const_body = OpaqueDef (Opaqueproof.create pt) }, u, r
- | _ -> orig
-;;
-
-type side_effect_role =
- | Subproof
- | Schema of inductive * string
+let turn_direct orig =
+ let cb = orig.seff_body in
+ if Declareops.is_opaque cb then
+ let p = match orig.seff_env with
+ | `Opaque (b, c) -> (b, c)
+ | _ -> assert false
+ in
+ let const_body = OpaqueDef (Opaqueproof.create (Future.from_val p)) in
+ let cb = { cb with const_body } in
+ { orig with seff_body = cb }
+ else orig
type exported_side_effect =
Constant.t * constant_body * side_effect_role
+let export_eff eff =
+ (eff.seff_constant, eff.seff_body, eff.seff_role)
+
let export_side_effects mb env c =
- let { const_entry_body = body } = c in
+ let { const_entry_body = body; _ } = c in
let _, eff = Future.force body in
let ce = { c with
const_entry_body = Future.chain body
(fun (b_ctx, _) -> b_ctx, ()) } in
- let not_exists (c,_,_,_) =
- try ignore(Environ.lookup_constant c env); false
+ let not_exists e =
+ try ignore(Environ.lookup_constant e.seff_constant env); false
with Not_found -> true in
let aux (acc,sl) { eff = se; from_env = mb } =
- let cbl = match se with
- | SEsubproof (c,cb,b) -> [c,cb,b,Subproof]
- | SEscheme (cl,k) ->
- List.map (fun (i,c,cb,b) -> c,cb,b,Schema(i,k)) cl in
- let cbl = List.filter not_exists cbl in
- if cbl = [] then acc, sl
+ let cbl = List.filter not_exists se in
+ if List.is_empty cbl then acc, sl
else cbl :: acc, (mb,List.length cbl) :: sl in
let seff, signatures = List.fold_left aux ([],[]) (uniq_seff_rev eff) in
let trusted = check_signatures mb signatures in
- let push_seff env = function
- | kn, cb, `Nothing, _ ->
- begin
- let env = Environ.add_constant kn cb env in
- match cb.const_universes with
- | Monomorphic_const ctx ->
- Environ.push_context_set ~strict:true ctx env
- | Polymorphic_const _ -> env
- end
- | kn, cb, `Opaque(_, ctx), _ ->
- begin
- let env = Environ.add_constant kn cb env in
- match cb.const_universes with
- | Monomorphic_const cstctx ->
- let env = Environ.push_context_set ~strict:true cstctx env in
- Environ.push_context_set ~strict:true ctx env
- | Polymorphic_const _ -> env
- end
+ let push_seff env eff =
+ let { seff_constant = kn; seff_body = cb ; _ } = eff in
+ let env = Environ.add_constant kn cb env in
+ match cb.const_universes with
+ | Polymorphic_const _ -> env
+ | Monomorphic_const ctx ->
+ let ctx = match eff.seff_env with
+ | `Nothing -> ctx
+ | `Opaque(_, ctx') -> Univ.ContextSet.union ctx' ctx
+ in
+ Environ.push_context_set ~strict:true ctx env
in
let rec translate_seff sl seff acc env =
match seff with
@@ -527,18 +505,22 @@ let export_side_effects mb env c =
| cbs :: rest ->
if Int.equal sl 0 then
let env, cbs =
- List.fold_left (fun (env,cbs) (kn, ocb, u, r) ->
+ List.fold_left (fun (env,cbs) eff ->
+ let { seff_constant = kn; seff_body = ocb; seff_env = u ; _ } = eff in
let ce = constant_entry_of_side_effect ocb u in
let cb = translate_constant Pure env kn ce in
- (push_seff env (kn, cb,`Nothing, Subproof),(kn,cb,r) :: cbs))
+ let eff = { eff with
+ seff_body = cb;
+ seff_env = `Nothing;
+ } in
+ (push_seff env eff, export_eff eff :: cbs))
(env,[]) cbs in
translate_seff 0 rest (cbs @ acc) env
else
let cbs_len = List.length cbs in
let cbs = List.map turn_direct cbs in
let env = List.fold_left push_seff env cbs in
- let ecbs = List.map (fun (kn,cb,u,r) ->
- kn, cb, r) cbs in
+ let ecbs = List.map export_eff cbs in
translate_seff (sl - cbs_len) rest (ecbs @ acc) env
in
translate_seff trusted seff [] env
@@ -556,7 +538,7 @@ let translate_recipe env kn r =
let hcons = DirPath.is_empty dir in
build_constant_declaration kn env (Cooking.cook_constant ~hcons r)
-let translate_local_def env id centry =
+let translate_local_def env _id centry =
let open Cooking in
let body = Future.from_val ((centry.secdef_body, Univ.ContextSet.empty), ()) in
let centry = {
diff --git a/kernel/term_typing.mli b/kernel/term_typing.mli
index 6a0ff072f5..b05e05e4dc 100644
--- a/kernel/term_typing.mli
+++ b/kernel/term_typing.mli
@@ -38,24 +38,18 @@ val inline_entry_side_effects :
yet type checked proof. *)
val empty_seff : side_effects
-val add_seff : side_effect -> side_effects -> side_effects
+val add_seff : Declarations.structure_body -> Entries.side_eff list -> side_effects -> side_effects
val concat_seff : side_effects -> side_effects -> side_effects
(** [concat_seff e1 e2] adds the side-effects of [e1] to [e2], i.e. effects in
[e1] must be more recent than those of [e2]. *)
-val uniq_seff : side_effects -> side_effect list
+val uniq_seff : side_effects -> side_eff list
(** Return the list of individual side-effects in the order of their
creation. *)
-val equal_eff : side_effect -> side_effect -> bool
-
val translate_constant :
'a trust -> env -> Constant.t -> 'a constant_entry ->
constant_body
-type side_effect_role =
- | Subproof
- | Schema of inductive * string
-
type exported_side_effect =
Constant.t * constant_body * side_effect_role
diff --git a/kernel/type_errors.ml b/kernel/type_errors.ml
index 1c323e3ea2..60293fe864 100644
--- a/kernel/type_errors.ml
+++ b/kernel/type_errors.ml
@@ -62,6 +62,7 @@ type ('constr, 'types) ptype_error =
| IllTypedRecBody of
int * Name.t array * ('constr, 'types) punsafe_judgment array * 'types array
| UnsatisfiedConstraints of Univ.Constraint.t
+ | UndeclaredUniverse of Univ.Level.t
type type_error = (constr, types) ptype_error
@@ -125,3 +126,6 @@ let error_elim_explain kp ki =
let error_unsatisfied_constraints env c =
raise (TypeError (env, UnsatisfiedConstraints c))
+
+let error_undeclared_universe env l =
+ raise (TypeError (env, UndeclaredUniverse l))
diff --git a/kernel/type_errors.mli b/kernel/type_errors.mli
index 20bf300ac3..3fd40a7f42 100644
--- a/kernel/type_errors.mli
+++ b/kernel/type_errors.mli
@@ -12,7 +12,7 @@ open Names
open Constr
open Environ
-(** Type errors. {% \label{%}typeerrors{% }%} *)
+(** Type errors. {% \label{typeerrors} %} *)
(*i Rem: NotEnoughAbstractionInFixBody should only occur with "/i" Fix
notation i*)
@@ -63,6 +63,7 @@ type ('constr, 'types) ptype_error =
| IllTypedRecBody of
int * Name.t array * ('constr, 'types) punsafe_judgment array * 'types array
| UnsatisfiedConstraints of Univ.Constraint.t
+ | UndeclaredUniverse of Univ.Level.t
type type_error = (constr, types) ptype_error
@@ -108,3 +109,5 @@ val error_ill_typed_rec_body :
val error_elim_explain : Sorts.family -> Sorts.family -> arity_error
val error_unsatisfied_constraints : env -> Univ.Constraint.t -> 'a
+
+val error_undeclared_universe : env -> Univ.Level.t -> 'a
diff --git a/kernel/typeops.ml b/kernel/typeops.ml
index 7f36f3813f..7456ecea56 100644
--- a/kernel/typeops.ml
+++ b/kernel/typeops.ml
@@ -118,14 +118,14 @@ let check_hyps_inclusion env f c sign =
(* Type of constants *)
-let type_of_constant env (kn,u as cst) =
+let type_of_constant env (kn,_u as cst) =
let cb = lookup_constant kn env in
let () = check_hyps_inclusion env mkConstU cst cb.const_hyps in
let ty, cu = constant_type env cst in
let () = check_constraints cu env in
ty
-let type_of_constant_in env (kn,u as cst) =
+let type_of_constant_in env (kn,_u as cst) =
let cb = lookup_constant kn env in
let () = check_hyps_inclusion env mkConstU cst cb.const_hyps in
constant_type_in env cst
@@ -142,7 +142,7 @@ let type_of_constant_in env (kn,u as cst) =
and no upper constraint exists on the sort $s$, we don't need to compute $s$
*)
-let type_of_abstraction env name var ty =
+let type_of_abstraction _env name var ty =
mkProd (name, var, ty)
(* Type of an application. *)
@@ -204,7 +204,7 @@ let sort_of_product env domsort rangsort =
where j.uj_type is convertible to a sort s2
*)
-let type_of_product env name s1 s2 =
+let type_of_product env _name s1 s2 =
let s = sort_of_product env s1 s2 in
mkSort s
@@ -247,7 +247,7 @@ let check_cast env c ct k expected_type =
dynamic constraints of the form u<=v are enforced *)
let type_of_inductive_knowing_parameters env (ind,u as indu) args =
- let (mib,mip) as spec = lookup_mind_specif env ind in
+ let (mib,_mip) as spec = lookup_mind_specif env ind in
check_hyps_inclusion env mkIndU indu mib.mind_hyps;
let t,cst = Inductive.constrained_type_of_inductive_knowing_parameters
env (spec,u) args
@@ -264,7 +264,7 @@ let type_of_inductive env (ind,u as indu) =
(* Constructors. *)
-let type_of_constructor env (c,u as cu) =
+let type_of_constructor env (c,_u as cu) =
let () =
let ((kn,_),_) = c in
let mib = lookup_mind kn env in
@@ -285,7 +285,7 @@ let check_branch_types env (ind,u) c ct lft explft =
| Invalid_argument _ ->
error_number_branches env (make_judge c ct) (Array.length explft)
-let type_of_case env ci p pt c ct lf lft =
+let type_of_case env ci p pt c ct _lf lft =
let (pind, _ as indspec) =
try find_rectype env ct
with Not_found -> error_case_not_inductive env (make_judge c ct) in
@@ -399,7 +399,7 @@ let rec execute env cstr =
let lft = execute_array env lf in
type_of_case env ci p pt c ct lf lft
- | Fix ((vn,i as vni),recdef) ->
+ | Fix ((_vn,i as vni),recdef) ->
let (fix_ty,recdef') = execute_recdef env recdef i in
let fix = (vni,recdef') in
check_fix env fix; fix_ty
@@ -431,7 +431,28 @@ and execute_recdef env (names,lar,vdef) i =
and execute_array env = Array.map (execute env)
(* Derived functions *)
+
+let universe_levels_of_constr _env c =
+ let rec aux s c =
+ match kind c with
+ | Const (_c, u) ->
+ LSet.fold LSet.add (Instance.levels u) s
+ | Ind ((_mind,_), u) | Construct (((_mind,_),_), u) ->
+ LSet.fold LSet.add (Instance.levels u) s
+ | Sort u when not (Sorts.is_small u) ->
+ let u = Sorts.univ_of_sort u in
+ LSet.fold LSet.add (Universe.levels u) s
+ | _ -> Constr.fold aux s c
+ in aux LSet.empty c
+
+let check_wellformed_universes env c =
+ let univs = universe_levels_of_constr env c in
+ try UGraph.check_declared_universes (universes env) univs
+ with UGraph.UndeclaredLevel u ->
+ error_undeclared_universe env u
+
let infer env constr =
+ let () = check_wellformed_universes env constr in
let t = execute env constr in
make_judge constr t
@@ -449,11 +470,13 @@ let type_judgment env {uj_val=c; uj_type=t} =
{utj_val = c; utj_type = s }
let infer_type env constr =
+ let () = check_wellformed_universes env constr in
let t = execute env constr in
let s = check_type env constr t in
{utj_val = constr; utj_type = s}
let infer_v env cv =
+ let () = Array.iter (check_wellformed_universes env) cv in
let jv = execute_array env cv in
make_judgev cv jv
@@ -461,9 +484,11 @@ let infer_v env cv =
let infer_local_decl env id = function
| Entries.LocalDefEntry c ->
+ let () = check_wellformed_universes env c in
let t = execute env c in
RelDecl.LocalDef (Name id, c, t)
| Entries.LocalAssumEntry c ->
+ let () = check_wellformed_universes env c in
let t = execute env c in
RelDecl.LocalAssum (Name id, check_assumption env c t)
@@ -505,7 +530,7 @@ let judge_of_product env x varj outj =
make_judge (mkProd (x, varj.utj_val, outj.utj_val))
(mkSort (sort_of_product env varj.utj_type outj.utj_type))
-let judge_of_letin env name defj typj j =
+let judge_of_letin _env name defj typj j =
make_judge (mkLetIn (name, defj.uj_val, typj.utj_val, j.uj_val))
(subst1 defj.uj_val j.uj_type)
diff --git a/kernel/uGraph.ml b/kernel/uGraph.ml
index bc624ba56d..9ff51fca55 100644
--- a/kernel/uGraph.ml
+++ b/kernel/uGraph.ml
@@ -194,7 +194,7 @@ let check_universes_invariants g =
UMap.iter (fun l u ->
match u with
| Canonical u ->
- UMap.iter (fun v strict ->
+ UMap.iter (fun v _strict ->
incr n_edges;
let v = repr g v in
assert (topo_compare u v = -1);
@@ -435,7 +435,7 @@ let reorder g u v =
| n0::q0 ->
(* Computing new root. *)
let root, rank_rest =
- List.fold_left (fun ((best, rank_rest) as acc) n ->
+ List.fold_left (fun ((best, _rank_rest) as acc) n ->
if n.rank >= best.rank then n, best.rank else acc)
(n0, min_int) q0
in
@@ -529,6 +529,11 @@ let add_universe vlev strict g =
let add_universe_unconstrained vlev g =
fst (add_universe_gen vlev g)
+exception UndeclaredLevel of Univ.Level.t
+let check_declared_universes g us =
+ let check l = if not (UMap.mem l g.entries) then raise (UndeclaredLevel l) in
+ Univ.LSet.iter check us
+
exception Found_explanation of explanation
let get_explanation strict u v g =
@@ -804,7 +809,7 @@ let normalize_universes g =
in
UMap.fold (fun _ u g ->
match u with
- | Equiv u -> g
+ | Equiv _u -> g
| Canonical u ->
let _, u, g = get_ltle g u in
let _, _, g = get_gtge g u in
@@ -816,7 +821,7 @@ let constraints_of_universes g =
let uf = UF.create () in
let constraints_of u v acc =
match v with
- | Canonical {univ=u; ltle} ->
+ | Canonical {univ=u; ltle; _} ->
UMap.fold (fun v strict acc->
let typ = if strict then Lt else Le in
Constraint.add (u,typ,v) acc) ltle acc
@@ -938,7 +943,7 @@ let check_eq_instances g t1 t2 =
(** Pretty-printing *)
let pr_arc prl = function
- | _, Canonical {univ=u; ltle} ->
+ | _, Canonical {univ=u; ltle; _} ->
if UMap.is_empty ltle then mt ()
else
prl u ++ str " " ++
@@ -958,7 +963,7 @@ let pr_universes prl g =
let dump_universes output g =
let dump_arc u = function
- | Canonical {univ=u; ltle} ->
+ | Canonical {univ=u; ltle; _} ->
let u_str = Level.to_string u in
UMap.iter (fun v strict ->
let typ = if strict then Lt else Le in
diff --git a/kernel/uGraph.mli b/kernel/uGraph.mli
index 8c2d877b0b..752bf76270 100644
--- a/kernel/uGraph.mli
+++ b/kernel/uGraph.mli
@@ -55,6 +55,12 @@ val add_universe : Level.t -> bool -> t -> t
(** Add a universe without (Prop,Set) <= u *)
val add_universe_unconstrained : Level.t -> t -> t
+(** Check that the universe levels are declared. Otherwise
+ @raise UndeclaredLevel l for the first undeclared level found. *)
+exception UndeclaredLevel of Univ.Level.t
+
+val check_declared_universes : t -> Univ.LSet.t -> unit
+
(** {6 Pretty-printing of universes. } *)
val pr_universes : (Level.t -> Pp.t) -> t -> Pp.t
diff --git a/kernel/univ.ml b/kernel/univ.ml
index 311477daca..61ad1d0a82 100644
--- a/kernel/univ.ml
+++ b/kernel/univ.ml
@@ -86,7 +86,7 @@ struct
| Level (n,d) as x ->
let d' = Names.DirPath.hcons d in
if d' == d then x else Level (n,d')
- | Var n as x -> x
+ | Var _n as x -> x
open Hashset.Combine
@@ -160,13 +160,6 @@ module Level = struct
let compare u v =
if u == v then 0
- else
- let c = Int.compare (hash u) (hash v) in
- if c == 0 then RawLevel.compare (data u) (data v)
- else c
-
- let natural_compare u v =
- if u == v then 0
else RawLevel.compare (data u) (data v)
let to_string x =
@@ -206,13 +199,13 @@ module LMap = struct
include M
let union l r =
- merge (fun k l r ->
+ merge (fun _k l r ->
match l, r with
| Some _, _ -> l
| _, _ -> r) l r
let subst_union l r =
- merge (fun k l r ->
+ merge (fun _k l r ->
match l, r with
| Some (Some _), _ -> l
| Some None, None -> l
@@ -365,14 +358,14 @@ struct
else f v ++ str"+" ++ int n
let is_level = function
- | (v, 0) -> true
+ | (_v, 0) -> true
| _ -> false
let level = function
| (v,0) -> Some v
| _ -> None
- let get_level (v,n) = v
+ let get_level (v,_n) = v
let map f (v, n as x) =
let v' = f v in
@@ -582,7 +575,7 @@ struct
prl u2 ++ fnl () ) c (str "")
let universes_of c =
- fold (fun (u1, op, u2) unvs -> LSet.add u2 (LSet.add u1 unvs)) c LSet.empty
+ fold (fun (u1, _op, u2) unvs -> LSet.add u2 (LSet.add u1 unvs)) c LSet.empty
end
let universes_of_constraints = Constraint.universes_of
@@ -907,7 +900,7 @@ let subst_instance_constraints s csts =
type universe_instance = Instance.t
type 'a puniverses = 'a * Instance.t
-let out_punivs (x, y) = x
+let out_punivs (x, _y) = x
let in_punivs x = (x, Instance.empty)
let eq_puniverses f (x, u) (y, u') =
f x y && Instance.equal u u'
@@ -932,8 +925,8 @@ struct
let hcons (univs, cst) =
(Instance.hcons univs, hcons_constraints cst)
- let instance (univs, cst) = univs
- let constraints (univs, cst) = cst
+ let instance (univs, _cst) = univs
+ let constraints (_univs, cst) = cst
let union (univs, cst) (univs', cst') =
Instance.append univs univs', Constraint.union cst cst'
@@ -952,7 +945,9 @@ struct
include UContext
let repr (inst, cst) =
- (Array.mapi (fun i l -> Level.var i) inst, cst)
+ (Array.mapi (fun i _l -> Level.var i) inst, cst)
+
+ let pr f ?variance ctx = pr f ?variance (repr ctx)
let instantiate inst (u, cst) =
assert (Array.length u = Array.length inst);
@@ -988,8 +983,8 @@ struct
let hcons (univs, variance) = (* should variance be hconsed? *)
(UContext.hcons univs, variance)
- let univ_context (univs, subtypcst) = univs
- let variance (univs, variance) = variance
+ let univ_context (univs, _subtypcst) = univs
+ let variance (_univs, variance) = variance
(** This function takes a universe context representing constraints
of an inductive and produces a CumulativityInfo.t with the
@@ -1054,7 +1049,7 @@ struct
(univs, cst)
let sort_levels a =
- Array.sort Level.natural_compare a; a
+ Array.sort Level.compare a; a
let to_context (ctx, cst) =
(Instance.of_array (sort_levels (Array.of_list (LSet.elements ctx))), cst)
@@ -1066,8 +1061,8 @@ struct
if is_empty ctx then mt() else
h 0 (LSet.pr prl univs ++ str " |= ") ++ h 0 (v 0 (Constraint.pr prl cst))
- let constraints (univs, cst) = cst
- let levels (univs, cst) = univs
+ let constraints (_univs, cst) = cst
+ let levels (univs, _cst) = univs
let size (univs,_) = LSet.cardinal univs
end
@@ -1155,7 +1150,7 @@ let make_inverse_instance_subst i =
LMap.empty arr
let make_abstract_instance (ctx, _) =
- Array.mapi (fun i l -> Level.var i) ctx
+ Array.mapi (fun i _l -> Level.var i) ctx
let abstract_universes ctx =
let instance = UContext.instance ctx in
diff --git a/kernel/vars.ml b/kernel/vars.ml
index 0f588a6302..9d5d79124b 100644
--- a/kernel/vars.ml
+++ b/kernel/vars.ml
@@ -66,7 +66,7 @@ let isMeta c = match Constr.kind c with
let noccur_with_meta n m term =
let rec occur_rec n c = match Constr.kind c with
| Constr.Rel p -> if n<=p && p<n+m then raise LocalOccur
- | Constr.App(f,cl) ->
+ | Constr.App(f,_cl) ->
(match Constr.kind f with
| Constr.Cast (c,_,_) when isMeta c -> ()
| Constr.Meta _ -> ()
@@ -188,7 +188,7 @@ let adjust_rel_to_rel_context sign n =
let open RelDecl in
match sign with
| LocalAssum _ :: sign' -> let (n',p) = aux sign' in (n'+1,p)
- | LocalDef (_,c,_)::sign' -> let (n',p) = aux sign' in (n'+1,if n'<n then p+1 else p)
+ | LocalDef (_,_c,_)::sign' -> let (n',p) = aux sign' in (n'+1,if n'<n then p+1 else p)
| [] -> (0,n)
in snd (aux sign)
diff --git a/kernel/vconv.ml b/kernel/vconv.ml
index d19bea5199..5965853e1e 100644
--- a/kernel/vconv.ml
+++ b/kernel/vconv.ml
@@ -11,7 +11,7 @@ open Csymtable
let compare_zipper z1 z2 =
match z1, z2 with
| Zapp args1, Zapp args2 -> Int.equal (nargs args1) (nargs args2)
- | Zfix(f1,args1), Zfix(f2,args2) -> Int.equal (nargs args1) (nargs args2)
+ | Zfix(_f1,args1), Zfix(_f2,args2) -> Int.equal (nargs args1) (nargs args2)
| Zswitch _, Zswitch _ | Zproj _, Zproj _ -> true
| Zapp _ , _ | Zfix _, _ | Zswitch _, _ | Zproj _, _ -> false
@@ -84,7 +84,7 @@ and conv_whd env pb k whd1 whd2 cu =
and conv_atom env pb k a1 stk1 a2 stk2 cu =
(* Pp.(msg_debug (str "conv_atom(" ++ pr_atom a1 ++ str ", " ++ pr_atom a2 ++ str ")")) ; *)
match a1, a2 with
- | Aind ((mi,i) as ind1) , Aind ind2 ->
+ | Aind ((mi,_i) as ind1) , Aind ind2 ->
if eq_ind ind1 ind2 && compare_stack stk1 stk2 then
if Environ.polymorphic_ind ind1 env then
let mib = Environ.lookup_mind mi env in
diff --git a/kernel/vm.ml b/kernel/vm.ml
index d7eedc226c..eaf64ba4af 100644
--- a/kernel/vm.ml
+++ b/kernel/vm.ml
@@ -8,7 +8,6 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
-open Cbytecodes
open Vmvalues
external set_drawinstr : unit -> unit = "coq_set_drawinstr"
@@ -188,5 +187,5 @@ let apply_whd k whd =
interprete (cofix_upd_code to_up) (cofix_upd_val to_up) (cofix_upd_env to_up) 0
| Vatom_stk(a,stk) ->
apply_stack (val_of_atom a) stk v
- | Vuniv_level lvl -> assert false
+ | Vuniv_level _lvl -> assert false
diff --git a/kernel/vmvalues.ml b/kernel/vmvalues.ml
index d6d9312938..217ef4b8e5 100644
--- a/kernel/vmvalues.ml
+++ b/kernel/vmvalues.ml
@@ -9,8 +9,8 @@
(************************************************************************)
open Names
open Sorts
-open Cbytecodes
open Univ
+open Constr
(*******************************************)
(* Initalization of the abstract machine ***)
@@ -25,11 +25,124 @@ let _ = init_vm ()
(* Abstract data types and utility functions **********)
(******************************************************)
+(* The representation of values relies on this assertion *)
+let _ = assert (Int.equal Obj.first_non_constant_constructor_tag 0)
+
(* Values of the abstract machine *)
type values
+type structured_values = values
let val_of_obj v = ((Obj.obj v):values)
let crazy_val = (val_of_obj (Obj.repr 0))
+type tag = int
+
+let accu_tag = 0
+
+let type_atom_tag = 2
+let max_atom_tag = 2
+let proj_tag = 3
+let fix_app_tag = 4
+let switch_tag = 5
+let cofix_tag = 6
+let cofix_evaluated_tag = 7
+
+(** Structured constants are constants whose construction is done once. Their
+occurrences share the same value modulo kernel name substitutions (for functor
+application). Structured values have the additional property that no
+substitution will need to be performed, so their runtime value can directly be
+shared without reallocating a more structured representation. *)
+type structured_constant =
+ | Const_sort of Sorts.t
+ | Const_ind of inductive
+ | Const_b0 of tag
+ | Const_univ_level of Univ.Level.t
+ | Const_val of structured_values
+
+type reloc_table = (tag * int) array
+
+type annot_switch =
+ {ci : case_info; rtbl : reloc_table; tailcall : bool; max_stack_size : int}
+
+let rec eq_structured_values v1 v2 =
+ v1 == v2 ||
+ let o1 = Obj.repr v1 in
+ let o2 = Obj.repr v2 in
+ if Obj.is_int o1 && Obj.is_int o2 then o1 == o2
+ else
+ let t1 = Obj.tag o1 in
+ let t2 = Obj.tag o2 in
+ if Int.equal t1 t2 &&
+ Int.equal (Obj.size o1) (Obj.size o2)
+ then begin
+ assert (t1 <= Obj.last_non_constant_constructor_tag &&
+ t2 <= Obj.last_non_constant_constructor_tag);
+ let i = ref 0 in
+ while (!i < Obj.size o1 && eq_structured_values
+ (Obj.magic (Obj.field o1 !i) : structured_values)
+ (Obj.magic (Obj.field o2 !i) : structured_values)) do
+ incr i
+ done;
+ !i >= Obj.size o1
+ end
+ else false
+
+let hash_structured_values (v : structured_values) =
+ (* We may want a better hash function here *)
+ Hashtbl.hash v
+
+let eq_structured_constant c1 c2 = match c1, c2 with
+| Const_sort s1, Const_sort s2 -> Sorts.equal s1 s2
+| Const_sort _, _ -> false
+| Const_ind i1, Const_ind i2 -> eq_ind i1 i2
+| Const_ind _, _ -> false
+| Const_b0 t1, Const_b0 t2 -> Int.equal t1 t2
+| Const_b0 _, _ -> false
+| Const_univ_level l1 , Const_univ_level l2 -> Univ.Level.equal l1 l2
+| Const_univ_level _ , _ -> false
+| Const_val v1, Const_val v2 -> eq_structured_values v1 v2
+| Const_val _v1, _ -> false
+
+let hash_structured_constant c =
+ let open Hashset.Combine in
+ match c with
+ | Const_sort s -> combinesmall 1 (Sorts.hash s)
+ | Const_ind i -> combinesmall 2 (ind_hash i)
+ | Const_b0 t -> combinesmall 3 (Int.hash t)
+ | Const_univ_level l -> combinesmall 4 (Univ.Level.hash l)
+ | Const_val v -> combinesmall 5 (hash_structured_values v)
+
+let eq_annot_switch asw1 asw2 =
+ let eq_ci ci1 ci2 =
+ eq_ind ci1.ci_ind ci2.ci_ind &&
+ Int.equal ci1.ci_npar ci2.ci_npar &&
+ CArray.equal Int.equal ci1.ci_cstr_ndecls ci2.ci_cstr_ndecls
+ in
+ let eq_rlc (i1, j1) (i2, j2) = Int.equal i1 i2 && Int.equal j1 j2 in
+ eq_ci asw1.ci asw2.ci &&
+ CArray.equal eq_rlc asw1.rtbl asw2.rtbl &&
+ (asw1.tailcall : bool) == asw2.tailcall
+
+let hash_annot_switch asw =
+ let open Hashset.Combine in
+ let h1 = Constr.case_info_hash asw.ci in
+ let h2 = Array.fold_left (fun h (t, i) -> combine3 h t i) 0 asw.rtbl in
+ let h3 = if asw.tailcall then 1 else 0 in
+ combine3 h1 h2 h3
+
+let pp_sort s =
+ let open Sorts in
+ match s with
+ | Prop -> Pp.str "Prop"
+ | Set -> Pp.str "Set"
+ | Type u -> Pp.(str "Type@{" ++ Univ.pr_uni u ++ str "}")
+
+let pp_struct_const = function
+ | Const_sort s -> pp_sort s
+ | Const_ind (mind, i) -> Pp.(MutInd.print mind ++ str"#" ++ int i)
+ | Const_b0 i -> Pp.int i
+ | Const_univ_level l -> Univ.Level.pr l
+ | Const_val _ -> Pp.str "(value)"
+
(* Abstract data *)
type vprod
type vfun
@@ -132,7 +245,7 @@ type id_key =
| RelKey of Int.t
| EvarKey of Evar.t
-let eq_id_key k1 k2 = match k1, k2 with
+let eq_id_key (k1 : id_key) (k2 : id_key) = match k1, k2 with
| ConstKey c1, ConstKey c2 -> Constant.equal c1 c2
| VarKey id1, VarKey id2 -> Id.equal id1 id2
| RelKey n1, RelKey n2 -> Int.equal n1 n2
@@ -191,9 +304,9 @@ let uni_lvl_val (v : values) : Univ.Level.t =
| Vfun _ -> str "Vfun"
| Vfix _ -> str "Vfix"
| Vcofix _ -> str "Vcofix"
- | Vconstr_const i -> str "Vconstr_const"
- | Vconstr_block b -> str "Vconstr_block"
- | Vatom_stk (a,stk) -> str "Vatom_stk"
+ | Vconstr_const _i -> str "Vconstr_const"
+ | Vconstr_block _b -> str "Vconstr_block"
+ | Vatom_stk (_a,_stk) -> str "Vatom_stk"
| _ -> assert false
in
CErrors.anomaly
@@ -293,19 +406,21 @@ let obj_of_atom : atom -> Obj.t =
res
(* obj_of_str_const : structured_constant -> Obj.t *)
-let rec obj_of_str_const str =
+let obj_of_str_const str =
match str with
| Const_sort s -> obj_of_atom (Asort s)
| Const_ind ind -> obj_of_atom (Aind ind)
| Const_b0 tag -> Obj.repr tag
- | Const_bn(tag, args) ->
- let len = Array.length args in
- let res = Obj.new_block tag len in
- for i = 0 to len - 1 do
- Obj.set_field res i (obj_of_str_const args.(i))
- done;
- res
| Const_univ_level l -> Obj.repr (Vuniv_level l)
+ | Const_val v -> Obj.repr v
+
+let val_of_block tag (args : structured_values array) =
+ let nargs = Array.length args in
+ let r = Obj.new_block tag nargs in
+ for i = 0 to nargs - 1 do
+ Obj.set_field r i (Obj.repr args.(i))
+ done;
+ (Obj.magic r : structured_values)
let val_of_obj o = ((Obj.obj o) : values)
@@ -313,6 +428,8 @@ let val_of_str_const str = val_of_obj (obj_of_str_const str)
let val_of_atom a = val_of_obj (obj_of_atom a)
+let val_of_int i = (Obj.magic i : values)
+
let atom_of_proj kn v =
let r = Obj.new_block proj_tag 2 in
Obj.set_field r 0 (Obj.repr kn);
@@ -327,7 +444,7 @@ struct
type t = id_key
let equal = eq_id_key
open Hashset.Combine
- let hash = function
+ let hash : t -> tag = function
| ConstKey c -> combinesmall 1 (Constant.hash c)
| VarKey id -> combinesmall 2 (Id.hash id)
| RelKey i -> combinesmall 3 (Int.hash i)
@@ -514,10 +631,10 @@ let branch_arg k (tag,arity) =
if Int.equal arity 0 then ((Obj.magic tag):values)
else
let b, ofs =
- if tag < last_variant_tag then Obj.new_block tag arity, 0
+ if tag < Obj.last_non_constant_constructor_tag then Obj.new_block tag arity, 0
else
- let b = Obj.new_block last_variant_tag (arity+1) in
- Obj.set_field b 0 (Obj.repr (tag-last_variant_tag));
+ let b = Obj.new_block Obj.last_non_constant_constructor_tag (arity+1) in
+ Obj.set_field b 0 (Obj.repr (tag-Obj.last_non_constant_constructor_tag));
b,1 in
for i = ofs to ofs + arity - 1 do
Obj.set_field b i (Obj.repr (val_of_rel (k+i)))
@@ -541,7 +658,7 @@ and pr_whd w =
| Vfix _ -> str "Vfix"
| Vcofix _ -> str "Vcofix"
| Vconstr_const i -> str "Vconstr_const(" ++ int i ++ str ")"
- | Vconstr_block b -> str "Vconstr_block"
+ | Vconstr_block _b -> str "Vconstr_block"
| Vatom_stk (a,stk) -> str "Vatom_stk(" ++ pr_atom a ++ str ", " ++ pr_stack stk ++ str ")"
| Vuniv_level _ -> assert false)
and pr_stack stk =
@@ -551,6 +668,6 @@ and pr_stack stk =
and pr_zipper z =
Pp.(match z with
| Zapp args -> str "Zapp(len = " ++ int (nargs args) ++ str ")"
- | Zfix (f,args) -> str "Zfix(..., len=" ++ int (nargs args) ++ str ")"
- | Zswitch s -> str "Zswitch(...)"
+ | Zfix (_f,args) -> str "Zfix(..., len=" ++ int (nargs args) ++ str ")"
+ | Zswitch _s -> str "Zswitch(...)"
| Zproj c -> str "Zproj(" ++ Projection.Repr.print c ++ str ")")
diff --git a/kernel/vmvalues.mli b/kernel/vmvalues.mli
index 6eedcf1d37..ae1d416ed5 100644
--- a/kernel/vmvalues.mli
+++ b/kernel/vmvalues.mli
@@ -9,11 +9,12 @@
(************************************************************************)
open Names
-open Cbytecodes
+open Constr
(** Values *)
type values
+type structured_values
type vm_env
type vm_global
type vprod
@@ -25,6 +26,38 @@ type arguments
type vstack = values array
type to_update
+type tag = int
+
+val accu_tag : tag
+
+val type_atom_tag : tag
+val max_atom_tag : tag
+val proj_tag : tag
+val fix_app_tag : tag
+val switch_tag : tag
+val cofix_tag : tag
+val cofix_evaluated_tag : tag
+
+type structured_constant =
+ | Const_sort of Sorts.t
+ | Const_ind of inductive
+ | Const_b0 of tag
+ | Const_univ_level of Univ.Level.t
+ | Const_val of structured_values
+
+val pp_struct_const : structured_constant -> Pp.t
+
+type reloc_table = (tag * int) array
+
+type annot_switch =
+ {ci : case_info; rtbl : reloc_table; tailcall : bool; max_stack_size : int}
+
+val eq_structured_constant : structured_constant -> structured_constant -> bool
+val hash_structured_constant : structured_constant -> int
+
+val eq_annot_switch : annot_switch -> annot_switch -> bool
+val hash_annot_switch : annot_switch -> int
+
val fun_val : vfun -> values
val fix_val : vfix -> values
val cofix_upd_val : to_update -> values
@@ -110,6 +143,8 @@ val val_of_constant : Constant.t -> values
val val_of_evar : Evar.t -> values
val val_of_proj : Projection.Repr.t -> values -> values
val val_of_atom : atom -> values
+val val_of_int : int -> structured_values
+val val_of_block : tag -> structured_values array -> structured_values
external val_of_annot_switch : annot_switch -> values = "%identity"
external val_of_proj_name : Projection.Repr.t -> values = "%identity"
@@ -158,4 +193,4 @@ val bfield : vblock -> int -> values
(** Switch *)
val check_switch : vswitch -> vswitch -> bool
-val branch_arg : int -> Cbytecodes.tag * int -> values
+val branch_arg : int -> tag * int -> values
diff --git a/lib/dune b/lib/dune
new file mode 100644
index 0000000000..232c208aa6
--- /dev/null
+++ b/lib/dune
@@ -0,0 +1,7 @@
+(library
+ (name lib)
+ (synopsis "Coq's Utility Library [coq-specific]")
+ (public_name coq.lib)
+ (wrapped false)
+ (modules_without_implementation xml_datatype)
+ (libraries threads coq.clib coq.config))
diff --git a/lib/genarg.mli b/lib/genarg.mli
index bb85f99e3c..52db3df088 100644
--- a/lib/genarg.mli
+++ b/lib/genarg.mli
@@ -13,7 +13,7 @@
(** The route of a generic argument, from parsing to evaluation.
In the following diagram, "object" can be tactic_expr, constr, tactic_arg, etc.
-{% \begin{%}verbatim{% }%}
+{% \begin{verbatim} %}
parsing in_raw out_raw
char stream ---> raw_object ---> raw_object generic_argument -------+
encapsulation decaps|
@@ -36,7 +36,7 @@ In the following diagram, "object" can be tactic_expr, constr, tactic_arg, etc.
|
V
effective use
-{% \end{%}verbatim{% }%}
+{% \end{verbatim} %}
To distinguish between the uninterpreted, globalized and
interpreted worlds, we annotate the type [generic_argument] by a
diff --git a/lib/system.ml b/lib/system.ml
index eef65a4e3d..eec007dcab 100644
--- a/lib/system.ml
+++ b/lib/system.ml
@@ -301,8 +301,11 @@ let with_time ~batch f x =
Feedback.msg_info (str msg ++ fmt_time_difference tstart tend ++ str msg2);
raise e
-let get_toplevel_path top =
- let dir = Filename.dirname Sys.executable_name in
+(* We use argv.[0] as we don't want to resolve symlinks *)
+let get_toplevel_path ?(byte=not Dynlink.is_native) top =
+ let open Filename in
+ let dir = if String.equal (basename Sys.argv.(0)) Sys.argv.(0)
+ then "" else dirname Sys.argv.(0) ^ dir_sep in
let exe = if Sys.(os_type = "Win32" || os_type = "Cygwin") then ".exe" else "" in
- let eff = if Dynlink.is_native then ".opt" else ".byte" in
- dir ^ Filename.dir_sep ^ top ^ eff ^ exe
+ let eff = if byte then ".byte" else ".opt" in
+ dir ^ top ^ eff ^ exe
diff --git a/lib/system.mli b/lib/system.mli
index a34280037c..f13fd30923 100644
--- a/lib/system.mli
+++ b/lib/system.mli
@@ -122,4 +122,4 @@ val with_time : batch:bool -> ('a -> 'b) -> 'a -> 'b
the right name you want you execution to fail rather than fall into
choosing some random binary from the system-wide installation of
Coq. *)
-val get_toplevel_path : string -> string
+val get_toplevel_path : ?byte:bool -> string -> string
diff --git a/library/coqlib.ml b/library/coqlib.ml
index 408e259196..026b7aa316 100644
--- a/library/coqlib.ml
+++ b/library/coqlib.ml
@@ -47,7 +47,7 @@ let gen_reference_in_modules locstr dirs s =
let dirs = List.map make_dir dirs in
let qualid = qualid_of_string s in
let all = Nametab.locate_all qualid in
- let all = List.sort_uniquize RefOrdered_env.compare all in
+ let all = List.sort_uniquize GlobRef.Ordered_env.compare all in
let these = List.filter (has_suffix_in_dirs dirs) all in
match these with
| [x] -> x
@@ -349,6 +349,9 @@ let coq_iff = lazy_init_reference ["Logic"] "iff"
let coq_iff_left_proj = lazy_init_reference ["Logic"] "proj1"
let coq_iff_right_proj = lazy_init_reference ["Logic"] "proj2"
+let coq_prod = lazy_init_reference ["Datatypes"] "prod"
+let coq_pair = lazy_init_reference ["Datatypes"] "pair"
+
(* Runtime part *)
let build_coq_True () = Lazy.force coq_True
let build_coq_I () = Lazy.force coq_I
@@ -364,6 +367,9 @@ let build_coq_iff () = Lazy.force coq_iff
let build_coq_iff_left_proj () = Lazy.force coq_iff_left_proj
let build_coq_iff_right_proj () = Lazy.force coq_iff_right_proj
+let build_coq_prod () = Lazy.force coq_prod
+let build_coq_pair () = Lazy.force coq_pair
+
(* The following is less readable but does not depend on parsing *)
let coq_eq_ref = lazy (init_reference ["Logic"] "eq")
diff --git a/library/coqlib.mli b/library/coqlib.mli
index b4bd1b0e06..8844684957 100644
--- a/library/coqlib.mli
+++ b/library/coqlib.mli
@@ -101,7 +101,7 @@ val glob_jmeq : GlobRef.t
at compile time. Therefore, we can only provide methods to build
them at runtime. This is the purpose of the [constr delayed] and
[constr_pattern delayed] types. Objects of this time needs to be
- forced with [delayed_force] to get the actual constr or pattern
+ forced with [delayed_force] to get the actual constr or pattern
at runtime. *)
type coq_bool_data = {
@@ -167,7 +167,7 @@ val build_coq_inversion_eq_true_data : coq_inversion_data delayed
val build_coq_sumbool : GlobRef.t delayed
(** {6 ... } *)
-(** Connectives
+(** Connectives
The False proposition *)
val build_coq_False : GlobRef.t delayed
@@ -186,6 +186,10 @@ val build_coq_iff : GlobRef.t delayed
val build_coq_iff_left_proj : GlobRef.t delayed
val build_coq_iff_right_proj : GlobRef.t delayed
+(** Pairs *)
+val build_coq_prod : GlobRef.t delayed
+val build_coq_pair : GlobRef.t delayed
+
(** Disjunction *)
val build_coq_or : GlobRef.t delayed
diff --git a/library/dischargedhypsmap.ml b/library/dischargedhypsmap.ml
deleted file mode 100644
index abcdb93a27..0000000000
--- a/library/dischargedhypsmap.ml
+++ /dev/null
@@ -1,21 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-open Libnames
-
-type discharged_hyps = full_path list
-
-let discharged_hyps_map = Summary.ref Spmap.empty ~name:"discharged_hypothesis"
-
-let set_discharged_hyps sp hyps =
- discharged_hyps_map := Spmap.add sp hyps !discharged_hyps_map
-
-let get_discharged_hyps sp =
- try Spmap.find sp !discharged_hyps_map with Not_found -> []
diff --git a/library/dischargedhypsmap.mli b/library/dischargedhypsmap.mli
deleted file mode 100644
index c70677225b..0000000000
--- a/library/dischargedhypsmap.mli
+++ /dev/null
@@ -1,19 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-open Libnames
-
-type discharged_hyps = full_path list
-
-(** Discharged hypothesis. Here we store the discharged hypothesis of each
- constant or inductive type declaration. *)
-
-val set_discharged_hyps : full_path -> discharged_hyps -> unit
-val get_discharged_hyps : full_path -> discharged_hyps
diff --git a/library/dune b/library/dune
new file mode 100644
index 0000000000..344fad5a75
--- /dev/null
+++ b/library/dune
@@ -0,0 +1,9 @@
+(library
+ (name library)
+ (synopsis "Coq's Loadable Libraries (vo) Support")
+ (public_name coq.library)
+ (wrapped false)
+ (libraries kernel))
+
+(documentation
+ (package coq))
diff --git a/library/global.ml b/library/global.ml
index dcb20a280e..e872d081d6 100644
--- a/library/global.ml
+++ b/library/global.ml
@@ -86,10 +86,10 @@ let push_named_assum a = globalize0 (Safe_typing.push_named_assum a)
let push_named_def d = globalize0 (Safe_typing.push_named_def d)
let add_constraints c = globalize0 (Safe_typing.add_constraints c)
let push_context_set b c = globalize0 (Safe_typing.push_context_set b c)
-let push_context b c = globalize0 (Safe_typing.push_context b c)
let set_engagement c = globalize0 (Safe_typing.set_engagement c)
let set_typing_flags c = globalize0 (Safe_typing.set_typing_flags c)
+let typing_flags () = Environ.typing_flags (env ())
let export_private_constants ~in_section cd = globalize (Safe_typing.export_private_constants ~in_section cd)
let add_constant dir id d = globalize (Safe_typing.add_constant dir (i2l id) d)
let add_mind dir id mie = globalize (Safe_typing.add_mind dir (i2l id) mie)
@@ -270,11 +270,17 @@ let with_global f =
push_context_set false ctx; a
(* spiwack: register/unregister functions for retroknowledge *)
-let register field value by_clause =
- globalize0 (Safe_typing.register field value by_clause)
+let register field value =
+ globalize0 (Safe_typing.register field value)
let register_inline c = globalize0 (Safe_typing.register_inline c)
let set_strategy k l =
GlobalSafeEnv.set_safe_env (Safe_typing.set_strategy (safe_env ()) k l)
+let set_reduction_sharing b =
+ let env = safe_env () in
+ let flags = Environ.typing_flags (Safe_typing.env_of_safe_env env) in
+ let flags = { flags with Declarations.share_reduction = b } in
+ let env = Safe_typing.set_typing_flags flags env in
+ GlobalSafeEnv.set_safe_env env
diff --git a/library/global.mli b/library/global.mli
index b2a191ceeb..5205968c7b 100644
--- a/library/global.mli
+++ b/library/global.mli
@@ -30,6 +30,7 @@ val named_context : unit -> Constr.named_context
(** Changing the (im)predicativity of the system *)
val set_engagement : Declarations.engagement -> unit
val set_typing_flags : Declarations.typing_flags -> unit
+val typing_flags : unit -> Declarations.typing_flags
(** Variables, Local definitions, constants, inductive types *)
@@ -48,7 +49,6 @@ val add_mind :
(** Extra universe constraints *)
val add_constraints : Univ.Constraint.t -> unit
-val push_context : bool -> Univ.UContext.t -> unit
val push_context_set : bool -> Univ.ContextSet.t -> unit
(** Non-interactive modules and module types *)
@@ -147,7 +147,7 @@ val universes_of_global : GlobRef.t -> Univ.AUContext.t
(** {6 Retroknowledge } *)
val register :
- Retroknowledge.field -> Constr.constr -> Constr.constr -> unit
+ Retroknowledge.field -> GlobRef.t -> unit
val register_inline : Constant.t -> unit
@@ -155,6 +155,8 @@ val register_inline : Constant.t -> unit
val set_strategy : Constant.t Names.tableKey -> Conv_oracle.level -> unit
+val set_reduction_sharing : bool -> unit
+
(* Modifies the global state, registering new universes *)
val current_modpath : unit -> ModPath.t
diff --git a/library/globnames.ml b/library/globnames.ml
index 6383a1f8f6..6bbdd36489 100644
--- a/library/globnames.ml
+++ b/library/globnames.ml
@@ -87,65 +87,14 @@ let printable_constr_of_global = function
| ConstructRef sp -> mkConstruct sp
| IndRef sp -> mkInd sp
-let global_eq_gen eq_cst eq_ind eq_cons x y =
- x == y ||
- match x, y with
- | ConstRef cx, ConstRef cy -> eq_cst cx cy
- | IndRef indx, IndRef indy -> eq_ind indx indy
- | ConstructRef consx, ConstructRef consy -> eq_cons consx consy
- | VarRef v1, VarRef v2 -> Id.equal v1 v2
- | (VarRef _ | ConstRef _ | IndRef _ | ConstructRef _), _ -> false
-
-let global_ord_gen ord_cst ord_ind ord_cons x y =
- if x == y then 0
- else match x, y with
- | VarRef v1, VarRef v2 -> Id.compare v1 v2
- | VarRef _, _ -> -1
- | _, VarRef _ -> 1
- | ConstRef cx, ConstRef cy -> ord_cst cx cy
- | ConstRef _, _ -> -1
- | _, ConstRef _ -> 1
- | IndRef indx, IndRef indy -> ord_ind indx indy
- | IndRef _, _ -> -1
- | _ , IndRef _ -> 1
- | ConstructRef consx, ConstructRef consy -> ord_cons consx consy
-
-let global_hash_gen hash_cst hash_ind hash_cons gr =
- let open Hashset.Combine in
- match gr with
- | ConstRef c -> combinesmall 1 (hash_cst c)
- | IndRef i -> combinesmall 2 (hash_ind i)
- | ConstructRef c -> combinesmall 3 (hash_cons c)
- | VarRef id -> combinesmall 4 (Id.hash id)
-
-(* By default, [global_reference] are ordered on their canonical part *)
-
-module RefOrdered = struct
- open Constant.CanOrd
- type t = global_reference
- let compare gr1 gr2 =
- global_ord_gen compare ind_ord constructor_ord gr1 gr2
- let equal gr1 gr2 = global_eq_gen equal eq_ind eq_constructor gr1 gr2
- let hash gr = global_hash_gen hash ind_hash constructor_hash gr
-end
-
-module RefOrdered_env = struct
- open Constant.UserOrd
- type t = global_reference
- let compare gr1 gr2 =
- global_ord_gen compare ind_user_ord constructor_user_ord gr1 gr2
- let equal gr1 gr2 =
- global_eq_gen equal eq_user_ind eq_user_constructor gr1 gr2
- let hash gr = global_hash_gen hash ind_user_hash constructor_user_hash gr
-end
-
-module Refmap = HMap.Make(RefOrdered)
-module Refset = Refmap.Set
+module RefOrdered = Names.GlobRef.Ordered
+module RefOrdered_env = Names.GlobRef.Ordered_env
-(* Alternative sets and maps indexed by the user part of the kernel names *)
+module Refmap = Names.GlobRef.Map
+module Refset = Names.GlobRef.Set
-module Refmap_env = HMap.Make(RefOrdered_env)
-module Refset_env = Refmap_env.Set
+module Refmap_env = Names.GlobRef.Map_env
+module Refset_env = Names.GlobRef.Set_env
(* Extended global references *)
@@ -164,14 +113,14 @@ module ExtRefOrdered = struct
let equal x y =
x == y ||
match x, y with
- | TrueGlobal rx, TrueGlobal ry -> RefOrdered_env.equal rx ry
+ | TrueGlobal rx, TrueGlobal ry -> GlobRef.Ordered_env.equal rx ry
| SynDef knx, SynDef kny -> KerName.equal knx kny
| (TrueGlobal _ | SynDef _), _ -> false
let compare x y =
if x == y then 0
else match x, y with
- | TrueGlobal rx, TrueGlobal ry -> RefOrdered_env.compare rx ry
+ | TrueGlobal rx, TrueGlobal ry -> GlobRef.Ordered_env.compare rx ry
| SynDef knx, SynDef kny -> KerName.compare knx kny
| TrueGlobal _, SynDef _ -> -1
| SynDef _, TrueGlobal _ -> 1
@@ -179,7 +128,7 @@ module ExtRefOrdered = struct
open Hashset.Combine
let hash = function
- | TrueGlobal gr -> combinesmall 1 (RefOrdered_env.hash gr)
+ | TrueGlobal gr -> combinesmall 1 (GlobRef.Ordered_env.hash gr)
| SynDef kn -> combinesmall 2 (KerName.hash kn)
end
diff --git a/library/globnames.mli b/library/globnames.mli
index 15fcd5bdd9..45ee069b06 100644
--- a/library/globnames.mli
+++ b/library/globnames.mli
@@ -8,7 +8,6 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
-open Util
open Names
open Constr
open Mod_subst
@@ -49,27 +48,21 @@ val printable_constr_of_global : GlobRef.t -> constr
raise [Not_found] if not a global reference *)
val global_of_constr : constr -> GlobRef.t
-module RefOrdered : sig
- type t = GlobRef.t
- val compare : t -> t -> int
- val equal : t -> t -> bool
- val hash : t -> int
-end
+module RefOrdered = Names.GlobRef.Ordered
+[@@ocaml.deprecated "Use Names.GlobRef.Ordered"]
-module RefOrdered_env : sig
- type t = GlobRef.t
- val compare : t -> t -> int
- val equal : t -> t -> bool
- val hash : t -> int
-end
+module RefOrdered_env = Names.GlobRef.Ordered_env
+[@@ocaml.deprecated "Use Names.GlobRef.Ordered_env"]
-module Refset : CSig.SetS with type elt = GlobRef.t
-module Refmap : Map.ExtS
- with type key = GlobRef.t and module Set := Refset
+module Refset = Names.GlobRef.Set
+[@@ocaml.deprecated "Use Names.GlobRef.Set"]
+module Refmap = Names.GlobRef.Map
+[@@ocaml.deprecated "Use Names.GlobRef.Map"]
-module Refset_env : CSig.SetS with type elt = GlobRef.t
-module Refmap_env : Map.ExtS
- with type key = GlobRef.t and module Set := Refset_env
+module Refset_env = GlobRef.Set_env
+[@@ocaml.deprecated "Use Names.GlobRef.Set_env"]
+module Refmap_env = GlobRef.Map_env
+[@@ocaml.deprecated "Use Names.GlobRef.Map_env"]
(** {6 Extended global references } *)
diff --git a/library/goptions.ml b/library/goptions.ml
index eafcb8fea6..dcbc46ab72 100644
--- a/library/goptions.ml
+++ b/library/goptions.ml
@@ -412,7 +412,7 @@ let print_tables () =
if depr then msg ++ str " [DEPRECATED]" ++ fnl ()
else msg ++ fnl ()
in
- str "Synchronous options:" ++ fnl () ++
+ str "Options:" ++ fnl () ++
OptionMap.fold
(fun key (name, depr, (read,_,_)) p ->
p ++ print_option key name (read ()) depr)
diff --git a/library/keys.ml b/library/keys.ml
index 3cadcb6472..a74d13c600 100644
--- a/library/keys.ml
+++ b/library/keys.ml
@@ -31,7 +31,7 @@ module KeyOrdered = struct
let hash gr =
match gr with
- | KGlob gr -> 8 + RefOrdered.hash gr
+ | KGlob gr -> 8 + GlobRef.Ordered.hash gr
| KLam -> 0
| KLet -> 1
| KProd -> 2
@@ -43,14 +43,14 @@ module KeyOrdered = struct
let compare gr1 gr2 =
match gr1, gr2 with
- | KGlob gr1, KGlob gr2 -> RefOrdered.compare gr1 gr2
+ | KGlob gr1, KGlob gr2 -> GlobRef.Ordered.compare gr1 gr2
| _, KGlob _ -> -1
| KGlob _, _ -> 1
| k, k' -> Int.compare (hash k) (hash k')
let equal k1 k2 =
match k1, k2 with
- | KGlob gr1, KGlob gr2 -> RefOrdered.equal gr1 gr2
+ | KGlob gr1, KGlob gr2 -> GlobRef.Ordered.equal gr1 gr2
| _, KGlob _ -> false
| KGlob _, _ -> false
| k, k' -> k == k'
diff --git a/library/lib.ml b/library/lib.ml
index 8ebe44890c..07026a9c2a 100644
--- a/library/lib.ml
+++ b/library/lib.ml
@@ -440,6 +440,21 @@ let add_section_context ctx =
check_same_poly true vars;
sectab := (Context ctx :: vars,repl,abs)::sl
+exception PolyFound of bool (* make this a let exception once possible *)
+let is_polymorphic_univ u =
+ try
+ let open Univ in
+ List.iter (fun (vars,_,_) ->
+ List.iter (function
+ | Variable (_,_,poly,(univs,_)) ->
+ if LSet.mem u univs then raise (PolyFound poly)
+ | Context (univs,_) ->
+ if LSet.mem u univs then raise (PolyFound true)
+ ) vars
+ ) !sectab;
+ false
+ with PolyFound b -> b
+
let extract_hyps (secs,ohyps) =
let rec aux = function
| (Variable (id,impl,poly,ctx)::idl, decl::hyps) when Names.Id.equal id (NamedDecl.get_id decl) ->
diff --git a/library/lib.mli b/library/lib.mli
index 9933b762ba..a7d21060e9 100644
--- a/library/lib.mli
+++ b/library/lib.mli
@@ -183,6 +183,8 @@ val add_section_kn : Decl_kinds.polymorphic ->
MutInd.t -> Constr.named_context -> unit
val replacement_context : unit -> Opaqueproof.work_list
+val is_polymorphic_univ : Univ.Level.t -> bool
+
(** {6 Discharge: decrease the section level if in the current section } *)
val discharge_kn : MutInd.t -> MutInd.t
diff --git a/library/library.mllib b/library/library.mllib
index 9cacaba4a7..8f694f4a31 100644
--- a/library/library.mllib
+++ b/library/library.mllib
@@ -11,7 +11,6 @@ Loadpath
Library
States
Kindops
-Dischargedhypsmap
Goptions
Decls
Keys
diff --git a/library/nametab.ml b/library/nametab.ml
index a3b3ca6e74..840cf8e380 100644
--- a/library/nametab.ml
+++ b/library/nametab.ml
@@ -279,10 +279,10 @@ module ExtRefTab = Make(FullPath)(ExtRefEqual)
module MPTab = Make(FullPath)(MPEqual)
type ccitab = ExtRefTab.t
-let the_ccitab = ref (ExtRefTab.empty : ccitab)
+let the_ccitab = Summary.ref ~name:"ccitab" (ExtRefTab.empty : ccitab)
type mptab = MPTab.t
-let the_modtypetab = ref (MPTab.empty : mptab)
+let the_modtypetab = Summary.ref ~name:"modtypetab" (MPTab.empty : mptab)
module DirPath' =
struct
@@ -303,7 +303,7 @@ module DirTab = Make(DirPath')(GlobDir)
(* If we have a (closed) module M having a submodule N, than N does not
have the entry in [the_dirtab]. *)
type dirtab = DirTab.t
-let the_dirtab = ref (DirTab.empty : dirtab)
+let the_dirtab = Summary.ref ~name:"dirtab" (DirTab.empty : dirtab)
type universe_id = DirPath.t * int
@@ -314,7 +314,7 @@ struct
end
module UnivTab = Make(FullPath)(UnivIdEqual)
type univtab = UnivTab.t
-let the_univtab = ref (UnivTab.empty : univtab)
+let the_univtab = Summary.ref ~name:"univtab" (UnivTab.empty : univtab)
(* Reversed name tables ***************************************************)
@@ -322,14 +322,14 @@ let the_univtab = ref (UnivTab.empty : univtab)
module Globrevtab = HMap.Make(ExtRefOrdered)
type globrevtab = full_path Globrevtab.t
-let the_globrevtab = ref (Globrevtab.empty : globrevtab)
+let the_globrevtab = Summary.ref ~name:"globrevtab" (Globrevtab.empty : globrevtab)
type mprevtab = DirPath.t MPmap.t
-let the_modrevtab = ref (MPmap.empty : mprevtab)
+let the_modrevtab = Summary.ref ~name:"modrevtab" (MPmap.empty : mprevtab)
type mptrevtab = full_path MPmap.t
-let the_modtyperevtab = ref (MPmap.empty : mptrevtab)
+let the_modtyperevtab = Summary.ref ~name:"modtyperevtab" (MPmap.empty : mptrevtab)
module UnivIdOrdered =
struct
@@ -344,7 +344,7 @@ end
module UnivIdMap = HMap.Make(UnivIdOrdered)
type univrevtab = full_path UnivIdMap.t
-let the_univrevtab = ref (UnivIdMap.empty : univrevtab)
+let the_univrevtab = Summary.ref ~name:"univrevtab" (UnivIdMap.empty : univrevtab)
(* Push functions *********************************************************)
@@ -546,38 +546,6 @@ let global_inductive qid =
(********************************************************************)
-(********************************************************************)
-(* Registration of tables as a global table and rollback *)
-
-type frozen = ccitab * dirtab * mptab * univtab
- * globrevtab * mprevtab * mptrevtab * univrevtab
-
-let freeze _ : frozen =
- !the_ccitab,
- !the_dirtab,
- !the_modtypetab,
- !the_univtab,
- !the_globrevtab,
- !the_modrevtab,
- !the_modtyperevtab,
- !the_univrevtab
-
-let unfreeze (ccit,dirt,mtyt,univt,globr,modr,mtyr,univr) =
- the_ccitab := ccit;
- the_dirtab := dirt;
- the_modtypetab := mtyt;
- the_univtab := univt;
- the_globrevtab := globr;
- the_modrevtab := modr;
- the_modtyperevtab := mtyr;
- the_univrevtab := univr
-
-let _ =
- Summary.declare_summary "names"
- { Summary.freeze_function = freeze;
- Summary.unfreeze_function = unfreeze;
- Summary.init_function = Summary.nop }
-
(* Deprecated synonyms *)
let extended_locate = locate_extended
diff --git a/parsing/dune b/parsing/dune
new file mode 100644
index 0000000000..b70612a52b
--- /dev/null
+++ b/parsing/dune
@@ -0,0 +1,20 @@
+(library
+ (name parsing)
+ (public_name coq.parsing)
+ (wrapped false)
+ (libraries proofs))
+
+(rule
+ (targets cLexer.ml)
+ (deps (:ml4-file cLexer.ml4))
+ (action (run camlp5o -loc loc -impl %{ml4-file} -o %{targets})))
+
+(rule
+ (targets g_prim.ml)
+ (deps (:mlg-file g_prim.mlg))
+ (action (run coqpp %{mlg-file})))
+
+(rule
+ (targets g_constr.ml)
+ (deps (:mlg-file g_constr.mlg))
+ (action (run coqpp %{mlg-file})))
diff --git a/parsing/g_constr.mlg b/parsing/g_constr.mlg
index 49e1cd7ec9..7cb5af787b 100644
--- a/parsing/g_constr.mlg
+++ b/parsing/g_constr.mlg
@@ -249,7 +249,7 @@ GRAMMAR EXTEND Gram
record_field_declaration:
[ [ id = global; bl = binders; ":="; c = lconstr ->
- { (id, mkCLambdaN ~loc bl c) } ] ]
+ { (id, if bl = [] then c else mkCLambdaN ~loc bl c) } ] ]
;
binder_constr:
[ [ "forall"; bl = open_binders; ","; c = operconstr LEVEL "200" ->
diff --git a/parsing/notgram_ops.ml b/parsing/notgram_ops.ml
index c36b3b17bf..5cc1292c92 100644
--- a/parsing/notgram_ops.ml
+++ b/parsing/notgram_ops.ml
@@ -19,8 +19,10 @@ open Notation_gram
let notation_level_map = Summary.ref ~name:"notation_level_map" NotationMap.empty
let declare_notation_level ?(onlyprint=false) ntn level =
- if NotationMap.mem ntn !notation_level_map then
- anomaly (str "Notation " ++ pr_notation ntn ++ str " is already assigned a level.");
+ try
+ let (level,onlyprint) = NotationMap.find ntn !notation_level_map in
+ if not onlyprint then anomaly (str "Notation " ++ pr_notation ntn ++ str " is already assigned a level.")
+ with Not_found ->
notation_level_map := NotationMap.add ntn (level,onlyprint) !notation_level_map
let level_of_notation ?(onlyprint=false) ntn =
diff --git a/plugins/btauto/Algebra.v b/plugins/btauto/Algebra.v
index ee7341a4a2..f1095fc9f1 100644
--- a/plugins/btauto/Algebra.v
+++ b/plugins/btauto/Algebra.v
@@ -1,4 +1,4 @@
-Require Import Bool PArith DecidableClass Omega ROmega.
+Require Import Bool PArith DecidableClass Omega Lia.
Ltac bool :=
repeat match goal with
@@ -84,9 +84,9 @@ Ltac case_decide := match goal with
let H := fresh "H" in
define (@decide P D) b H; destruct b; try_decide
| [ |- context [Pos.compare ?x ?y] ] =>
- destruct (Pos.compare_spec x y); try (exfalso; zify; romega)
+ destruct (Pos.compare_spec x y); try lia
| [ X : context [Pos.compare ?x ?y] |- _ ] =>
- destruct (Pos.compare_spec x y); try (exfalso; zify; romega)
+ destruct (Pos.compare_spec x y); try lia
end.
Section Definitions.
@@ -325,13 +325,13 @@ Qed.
Lemma linear_le_compat : forall k l p, linear k p -> (k <= l)%positive -> linear l p.
Proof.
-intros k l p H; revert l; induction H; constructor; eauto; zify; romega.
+intros k l p H; revert l; induction H; constructor; eauto; lia.
Qed.
Lemma linear_valid_incl : forall k p, linear k p -> valid k p.
Proof.
intros k p H; induction H; constructor; auto.
-eapply valid_le_compat; eauto; zify; romega.
+eapply valid_le_compat; eauto; lia.
Qed.
End Validity.
@@ -417,13 +417,13 @@ Qed.
Hint Extern 5 =>
match goal with
| [ |- (Pos.max ?x ?y <= ?z)%positive ] =>
- apply Pos.max_case_strong; intros; zify; romega
+ apply Pos.max_case_strong; intros; lia
| [ |- (?z <= Pos.max ?x ?y)%positive ] =>
- apply Pos.max_case_strong; intros; zify; romega
+ apply Pos.max_case_strong; intros; lia
| [ |- (Pos.max ?x ?y < ?z)%positive ] =>
- apply Pos.max_case_strong; intros; zify; romega
+ apply Pos.max_case_strong; intros; lia
| [ |- (?z < Pos.max ?x ?y)%positive ] =>
- apply Pos.max_case_strong; intros; zify; romega
+ apply Pos.max_case_strong; intros; lia
| _ => zify; omega
end.
Hint Resolve Pos.le_max_r Pos.le_max_l.
@@ -445,8 +445,8 @@ intros kl kr pl pr Hl Hr; revert kr pr Hr; induction Hl; intros kr pr Hr; simpl.
now rewrite <- (Pos.max_id i); intuition.
destruct (Pos.compare_spec i i0); subst; try case_decide; repeat (constructor; intuition).
+ apply (valid_le_compat (Pos.max i0 i0)); [now auto|]; rewrite Pos.max_id; auto.
- + apply (valid_le_compat (Pos.max i0 i0)); [now auto|]; rewrite Pos.max_id; zify; romega.
- + apply (valid_le_compat (Pos.max (Pos.succ i0) (Pos.succ i0))); [now auto|]; rewrite Pos.max_id; zify; romega.
+ + apply (valid_le_compat (Pos.max i0 i0)); [now auto|]; rewrite Pos.max_id; lia.
+ + apply (valid_le_compat (Pos.max (Pos.succ i0) (Pos.succ i0))); [now auto|]; rewrite Pos.max_id; lia.
+ apply (valid_le_compat (Pos.max (Pos.succ i) i0)); intuition.
+ apply (valid_le_compat (Pos.max i (Pos.succ i0))); intuition.
}
@@ -456,7 +456,7 @@ Lemma poly_mul_cst_valid_compat : forall k v p, valid k p -> valid k (poly_mul_c
Proof.
intros k v p H; induction H; simpl; [now auto|].
case_decide; [|now auto].
-eapply (valid_le_compat i); [now auto|zify; romega].
+eapply (valid_le_compat i); [now auto|lia].
Qed.
Lemma poly_mul_mon_null_compat : forall i p, null (poly_mul_mon i p) -> null p.
diff --git a/plugins/btauto/Reflect.v b/plugins/btauto/Reflect.v
index 3bd7cd622c..d82e8ae8ad 100644
--- a/plugins/btauto/Reflect.v
+++ b/plugins/btauto/Reflect.v
@@ -1,4 +1,4 @@
-Require Import Bool DecidableClass Algebra Ring PArith ROmega Omega.
+Require Import Bool DecidableClass Algebra Ring PArith Omega.
Section Bool.
diff --git a/plugins/btauto/plugin_base.dune b/plugins/btauto/plugin_base.dune
new file mode 100644
index 0000000000..6a024358c3
--- /dev/null
+++ b/plugins/btauto/plugin_base.dune
@@ -0,0 +1,5 @@
+(library
+ (name btauto_plugin)
+ (public_name coq.plugins.btauto)
+ (synopsis "Coq's btauto plugin")
+ (libraries coq.plugins.ltac))
diff --git a/plugins/btauto/refl_btauto.ml b/plugins/btauto/refl_btauto.ml
index c2bc8c079c..b0f97c59b8 100644
--- a/plugins/btauto/refl_btauto.ml
+++ b/plugins/btauto/refl_btauto.ml
@@ -224,7 +224,7 @@ module Btauto = struct
Tacticals.tclFAIL 0 msg gl
let try_unification env =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.enter begin fun gl ->
let concl = Proofview.Goal.concl gl in
let eq = Lazy.force eq in
let concl = EConstr.Unsafe.to_constr concl in
@@ -240,7 +240,7 @@ module Btauto = struct
end
let tac =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.enter begin fun gl ->
let concl = Proofview.Goal.concl gl in
let concl = EConstr.Unsafe.to_constr concl in
let sigma = Tacmach.New.project gl in
diff --git a/plugins/cc/ccalgo.ml b/plugins/cc/ccalgo.ml
index ce620d5312..f26ec0f401 100644
--- a/plugins/cc/ccalgo.ml
+++ b/plugins/cc/ccalgo.ml
@@ -26,6 +26,10 @@ let init_size=5
let cc_verbose=ref false
+let print_constr t =
+ let sigma, env = Pfedit.get_current_context () in
+ Printer.pr_econstr_env env sigma t
+
let debug x =
if !cc_verbose then Feedback.msg_debug (x ())
@@ -483,10 +487,10 @@ let rec inst_pattern subst = function
args t
let pr_idx_term uf i = str "[" ++ int i ++ str ":=" ++
- Termops.print_constr (EConstr.of_constr (constr_of_term (term uf i))) ++ str "]"
+ print_constr (EConstr.of_constr (constr_of_term (term uf i))) ++ str "]"
let pr_term t = str "[" ++
- Termops.print_constr (EConstr.of_constr (constr_of_term t)) ++ str "]"
+ print_constr (EConstr.of_constr (constr_of_term t)) ++ str "]"
let rec add_term state t=
let uf=state.uf in
@@ -601,7 +605,7 @@ let add_inst state (inst,int_subst) =
begin
debug (fun () ->
(str "Adding new equality, depth="++ int state.rew_depth) ++ fnl () ++
- (str " [" ++ Termops.print_constr (EConstr.of_constr prf) ++ str " : " ++
+ (str " [" ++ print_constr (EConstr.of_constr prf) ++ str " : " ++
pr_term s ++ str " == " ++ pr_term t ++ str "]"));
add_equality state prf s t
end
@@ -609,7 +613,7 @@ let add_inst state (inst,int_subst) =
begin
debug (fun () ->
(str "Adding new disequality, depth="++ int state.rew_depth) ++ fnl () ++
- (str " [" ++ Termops.print_constr (EConstr.of_constr prf) ++ str " : " ++
+ (str " [" ++ print_constr (EConstr.of_constr prf) ++ str " : " ++
pr_term s ++ str " <> " ++ pr_term t ++ str "]"));
add_disequality state (Hyp prf) s t
end
diff --git a/plugins/cc/plugin_base.dune b/plugins/cc/plugin_base.dune
new file mode 100644
index 0000000000..2a92996d2a
--- /dev/null
+++ b/plugins/cc/plugin_base.dune
@@ -0,0 +1,5 @@
+(library
+ (name cc_plugin)
+ (public_name coq.plugins.cc)
+ (synopsis "Coq's congruence closure plugin")
+ (libraries coq.plugins.ltac))
diff --git a/plugins/derive/plugin_base.dune b/plugins/derive/plugin_base.dune
new file mode 100644
index 0000000000..ba9cd595ce
--- /dev/null
+++ b/plugins/derive/plugin_base.dune
@@ -0,0 +1,5 @@
+(library
+ (name derive_plugin)
+ (public_name coq.plugins.derive)
+ (synopsis "Coq's derive plugin")
+ (libraries coq.plugins.ltac))
diff --git a/plugins/extraction/extract_env.ml b/plugins/extraction/extract_env.ml
index 4ede11b5c9..5d3115d8d7 100644
--- a/plugins/extraction/extract_env.ml
+++ b/plugins/extraction/extract_env.ml
@@ -710,10 +710,10 @@ let structure_for_compute env sg c =
init false false ~compute:true;
let ast, mlt = Extraction.extract_constr env sg c in
let ast = Mlutil.normalize ast in
- let refs = ref Refset.empty in
- let add_ref r = refs := Refset.add r !refs in
+ let refs = ref GlobRef.Set.empty in
+ let add_ref r = refs := GlobRef.Set.add r !refs in
let () = ast_iter_references add_ref add_ref add_ref ast in
- let refs = Refset.elements !refs in
+ let refs = GlobRef.Set.elements !refs in
let struc = optimize_struct (refs,[]) (mono_environment refs []) in
(flatten_structure struc), ast, mlt
diff --git a/plugins/extraction/plugin_base.dune b/plugins/extraction/plugin_base.dune
new file mode 100644
index 0000000000..037b0d5053
--- /dev/null
+++ b/plugins/extraction/plugin_base.dune
@@ -0,0 +1,5 @@
+(library
+ (name extraction_plugin)
+ (public_name coq.plugins.extraction)
+ (synopsis "Coq's extraction plugin")
+ (libraries num coq.plugins.ltac))
diff --git a/plugins/extraction/table.ml b/plugins/extraction/table.ml
index c3f4cfe654..e05e82af6f 100644
--- a/plugins/extraction/table.ml
+++ b/plugins/extraction/table.ml
@@ -30,8 +30,8 @@ let capitalize = String.capitalize
(** Sets and maps for [global_reference] that use the "user" [kernel_name]
instead of the canonical one *)
-module Refmap' = Refmap_env
-module Refset' = Refset_env
+module Refmap' = GlobRef.Map_env
+module Refset' = GlobRef.Set_env
(*S Utilities about [module_path] and [kernel_names] and [global_reference] *)
@@ -213,12 +213,12 @@ let is_recursor = function
(* NB: here, working modulo name equivalence is ok *)
-let projs = ref (Refmap.empty : (inductive*int) Refmap.t)
-let init_projs () = projs := Refmap.empty
-let add_projection n kn ip = projs := Refmap.add (ConstRef kn) (ip,n) !projs
-let is_projection r = Refmap.mem r !projs
-let projection_arity r = snd (Refmap.find r !projs)
-let projection_info r = Refmap.find r !projs
+let projs = ref (GlobRef.Map.empty : (inductive*int) GlobRef.Map.t)
+let init_projs () = projs := GlobRef.Map.empty
+let add_projection n kn ip = projs := GlobRef.Map.add (ConstRef kn) (ip,n) !projs
+let is_projection r = GlobRef.Map.mem r !projs
+let projection_arity r = snd (GlobRef.Map.find r !projs)
+let projection_info r = GlobRef.Map.find r !projs
(*s Table of used axioms *)
diff --git a/plugins/firstorder/instances.ml b/plugins/firstorder/instances.ml
index 85f4939560..286021d68e 100644
--- a/plugins/firstorder/instances.ml
+++ b/plugins/firstorder/instances.ml
@@ -38,7 +38,7 @@ let compare_gr id1 id2 =
if id1==id2 then 0 else
if id1==dummy_id then 1
else if id2==dummy_id then -1
- else Globnames.RefOrdered.compare id1 id2
+ else GlobRef.Ordered.compare id1 id2
module OrderedInstance=
struct
diff --git a/plugins/firstorder/plugin_base.dune b/plugins/firstorder/plugin_base.dune
new file mode 100644
index 0000000000..bcbb99d9fc
--- /dev/null
+++ b/plugins/firstorder/plugin_base.dune
@@ -0,0 +1,5 @@
+(library
+ (name ground_plugin)
+ (public_name coq.plugins.ground)
+ (synopsis "Coq's first order logic solver plugin")
+ (libraries coq.plugins.ltac))
diff --git a/plugins/firstorder/rules.ml b/plugins/firstorder/rules.ml
index b13580bc03..3ae777cc9a 100644
--- a/plugins/firstorder/rules.ml
+++ b/plugins/firstorder/rules.ml
@@ -34,7 +34,7 @@ type lseqtac= GlobRef.t -> seqtac
type 'a with_backtracking = tactic -> 'a
let wrap n b continue seq =
- Proofview.Goal.nf_enter begin fun gls ->
+ Proofview.Goal.enter begin fun gls ->
Control.check_for_interrupt ();
let nc = Proofview.Goal.hyps gls in
let env=pf_env gls in
diff --git a/plugins/firstorder/sequent.ml b/plugins/firstorder/sequent.ml
index 2a527da9be..5958fe8203 100644
--- a/plugins/firstorder/sequent.ml
+++ b/plugins/firstorder/sequent.ml
@@ -62,7 +62,7 @@ module Hitem=
struct
type t = h_item
let compare (id1,co1) (id2,co2)=
- let c = Globnames.RefOrdered.compare id1 id2 in
+ let c = GlobRef.Ordered.compare id1 id2 in
if c = 0 then
let cmp (i1, c1) (i2, c2) =
let c = Int.compare i1 i2 in
diff --git a/plugins/fourier/plugin_base.dune b/plugins/fourier/plugin_base.dune
new file mode 100644
index 0000000000..8cc76f6f9e
--- /dev/null
+++ b/plugins/fourier/plugin_base.dune
@@ -0,0 +1,5 @@
+(library
+ (name fourier_plugin)
+ (public_name coq.plugins.fourier)
+ (synopsis "Coq's fourier plugin")
+ (libraries coq.plugins.ltac))
diff --git a/plugins/funind/glob_term_to_relation.ml b/plugins/funind/glob_term_to_relation.ml
index 5fc4293cbb..fd2d90e9cf 100644
--- a/plugins/funind/glob_term_to_relation.ml
+++ b/plugins/funind/glob_term_to_relation.ml
@@ -1469,7 +1469,7 @@ let do_build_inductive
(rel_constructors)
in
let rel_ind i ext_rel_constructors =
- (((CAst.make @@ relnames.(i)), None),
+ ((CAst.make @@ relnames.(i)),
rel_params,
Some rel_arities.(i),
ext_rel_constructors),[]
@@ -1499,14 +1499,14 @@ let do_build_inductive
let _time2 = System.get_time () in
try
with_full_print
- (Flags.silently (ComInductive.do_mutual_inductive rel_inds (Flags.is_universe_polymorphism ()) false false ~uniform:ComInductive.NonUniformParameters))
+ (Flags.silently (ComInductive.do_mutual_inductive ~template:None None rel_inds (Flags.is_universe_polymorphism ()) false false ~uniform:ComInductive.NonUniformParameters))
Declarations.Finite
with
| UserError(s,msg) as e ->
let _time3 = System.get_time () in
(* Pp.msgnl (str "error : "++ str (string_of_float (System.time_difference time2 time3))); *)
let repacked_rel_inds =
- List.map (fun ((a , b , c , l),ntn) -> ((false,a) , b, c , Vernacexpr.Inductive_kw, Vernacexpr.Constructors l),ntn )
+ List.map (fun ((a , b , c , l),ntn) -> ((false,(a,None)) , b, c , Vernacexpr.Inductive_kw, Vernacexpr.Constructors l),ntn )
rel_inds
in
let msg =
@@ -1521,7 +1521,7 @@ let do_build_inductive
let _time3 = System.get_time () in
(* Pp.msgnl (str "error : "++ str (string_of_float (System.time_difference time2 time3))); *)
let repacked_rel_inds =
- List.map (fun ((a , b , c , l),ntn) -> ((false,a) , b, c , Vernacexpr.Inductive_kw, Vernacexpr.Constructors l),ntn )
+ List.map (fun ((a , b , c , l),ntn) -> ((false,(a,None)) , b, c , Vernacexpr.Inductive_kw, Vernacexpr.Constructors l),ntn )
rel_inds
in
let msg =
diff --git a/plugins/funind/indfun.ml b/plugins/funind/indfun.ml
index 489a40ed09..e114a0119e 100644
--- a/plugins/funind/indfun.ml
+++ b/plugins/funind/indfun.ml
@@ -98,7 +98,7 @@ let functional_induction with_clean c princl pat =
List.map2
(fun c pat ->
((None,
- Ltac_plugin.Tacexpr.ElimOnConstr (fun env sigma -> (sigma,(c,NoBindings)))),
+ Tactics.ElimOnConstr (fun env sigma -> (sigma,(c,NoBindings)))),
(None,pat),
None))
(args@c_list)
diff --git a/plugins/funind/invfun.ml b/plugins/funind/invfun.ml
index 439274240f..ad11f853ca 100644
--- a/plugins/funind/invfun.ml
+++ b/plugins/funind/invfun.ml
@@ -351,7 +351,7 @@ let prove_fun_correct evd funs_constr graphs_constr schemes lemmas_types_infos i
Locusops.onConcl);
observe_tac ("toto ") tclIDTAC;
- (* introducing the the result of the graph and the equality hypothesis *)
+ (* introducing the result of the graph and the equality hypothesis *)
observe_tac "introducing" (tclMAP (fun x -> Proofview.V82.of_tactic (Simple.intro x)) [res;hres]);
(* replacing [res] with its value *)
observe_tac "rewriting res value" (Proofview.V82.of_tactic (Equality.rewriteLR (mkVar hres)));
diff --git a/plugins/funind/plugin_base.dune b/plugins/funind/plugin_base.dune
new file mode 100644
index 0000000000..002eb28eea
--- /dev/null
+++ b/plugins/funind/plugin_base.dune
@@ -0,0 +1,5 @@
+(library
+ (name recdef_plugin)
+ (public_name coq.plugins.recdef)
+ (synopsis "Coq's functional induction plugin")
+ (libraries coq.plugins.extraction))
diff --git a/plugins/ltac/evar_tactics.ml b/plugins/ltac/evar_tactics.ml
index 84f13d2131..b0277e9cc2 100644
--- a/plugins/ltac/evar_tactics.ml
+++ b/plugins/ltac/evar_tactics.ml
@@ -94,12 +94,12 @@ let let_evar name typ =
in
let (sigma, evar) = Evarutil.new_evar env sigma ~src ~naming:(Namegen.IntroFresh id) typ in
Tacticals.New.tclTHEN (Proofview.Unsafe.tclEVARS sigma)
- (Tactics.letin_tac None (Name.Name id) evar None Locusops.nowhere)
+ (Tactics.pose_tac (Name.Name id) evar)
end
let hget_evar n =
let open EConstr in
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.enter begin fun gl ->
let sigma = Tacmach.New.project gl in
let concl = Proofview.Goal.concl gl in
let evl = evar_list sigma concl in
diff --git a/plugins/ltac/extraargs.ml4 b/plugins/ltac/extraargs.ml4
index dbbdbfa396..f4555509cc 100644
--- a/plugins/ltac/extraargs.ml4
+++ b/plugins/ltac/extraargs.ml4
@@ -52,8 +52,11 @@ let () =
(* Rewriting orientation *)
-let _ = Metasyntax.add_token_obj "<-"
-let _ = Metasyntax.add_token_obj "->"
+let _ =
+ Mltop.declare_cache_obj
+ (fun () -> Metasyntax.add_token_obj "<-";
+ Metasyntax.add_token_obj "->")
+ "ltac_plugin"
let pr_orient _prc _prlc _prt = function
| true -> Pp.mt ()
@@ -196,9 +199,9 @@ let pr_gen_place pr_id = function
ConclLocation () -> Pp.mt ()
| HypLocation (id,InHyp) -> str "in " ++ pr_id id
| HypLocation (id,InHypTypeOnly) ->
- str "in (Type of " ++ pr_id id ++ str ")"
+ str "in (type of " ++ pr_id id ++ str ")"
| HypLocation (id,InHypValueOnly) ->
- str "in (Value of " ++ pr_id id ++ str ")"
+ str "in (value of " ++ pr_id id ++ str ")"
let pr_loc_place _ _ _ = pr_gen_place (fun { CAst.v = id } -> Id.print id)
let pr_place _ _ _ = pr_gen_place Id.print
@@ -217,6 +220,14 @@ let interp_place ist gl p =
let subst_place subst pl = pl
+let warn_deprecated_instantiate_syntax =
+ CWarnings.create ~name:"deprecated-instantiate-syntax" ~category:"deprecated"
+ (fun (v,v',id) ->
+ let s = Id.to_string id in
+ Pp.strbrk
+ ("Syntax \"in (" ^ v ^ " of " ^ s ^ ")\" is deprecated; use \"in (" ^ v' ^ " of " ^ s ^ ")\".")
+ )
+
ARGUMENT EXTEND hloc
PRINTED BY pr_place
INTERPRETED BY interp_place
@@ -231,8 +242,14 @@ ARGUMENT EXTEND hloc
| [ "in" ident(id) ] ->
[ HypLocation ((CAst.make id),InHyp) ]
| [ "in" "(" "Type" "of" ident(id) ")" ] ->
- [ HypLocation ((CAst.make id),InHypTypeOnly) ]
+ [ warn_deprecated_instantiate_syntax ("Type","type",id);
+ HypLocation ((CAst.make id),InHypTypeOnly) ]
| [ "in" "(" "Value" "of" ident(id) ")" ] ->
+ [ warn_deprecated_instantiate_syntax ("Value","value",id);
+ HypLocation ((CAst.make id),InHypValueOnly) ]
+| [ "in" "(" "type" "of" ident(id) ")" ] ->
+ [ HypLocation ((CAst.make id),InHypTypeOnly) ]
+| [ "in" "(" "value" "of" ident(id) ")" ] ->
[ HypLocation ((CAst.make id),InHypValueOnly) ]
END
@@ -294,78 +311,3 @@ let pr_lpar_id_colon _ _ _ _ = mt ()
ARGUMENT EXTEND test_lpar_id_colon TYPED AS unit PRINTED BY pr_lpar_id_colon
| [ local_test_lpar_id_colon(x) ] -> [ () ]
END
-
-(* spiwack: the print functions are incomplete, but I don't know what they are
- used for *)
-let pr_r_int31_field i31f =
- str "int31 " ++
- match i31f with
- | Retroknowledge.Int31Bits -> str "bits"
- | Retroknowledge.Int31Type -> str "type"
- | Retroknowledge.Int31Twice -> str "twice"
- | Retroknowledge.Int31TwicePlusOne -> str "twice plus one"
- | Retroknowledge.Int31Phi -> str "phi"
- | Retroknowledge.Int31PhiInv -> str "phi inv"
- | Retroknowledge.Int31Plus -> str "plus"
- | Retroknowledge.Int31Times -> str "times"
- | Retroknowledge.Int31Constructor -> assert false
- | Retroknowledge.Int31PlusC -> str "plusc"
- | Retroknowledge.Int31PlusCarryC -> str "pluscarryc"
- | Retroknowledge.Int31Minus -> str "minus"
- | Retroknowledge.Int31MinusC -> str "minusc"
- | Retroknowledge.Int31MinusCarryC -> str "minuscarryc"
- | Retroknowledge.Int31TimesC -> str "timesc"
- | Retroknowledge.Int31Div21 -> str "div21"
- | Retroknowledge.Int31Div -> str "div"
- | Retroknowledge.Int31Diveucl -> str "diveucl"
- | Retroknowledge.Int31AddMulDiv -> str "addmuldiv"
- | Retroknowledge.Int31Compare -> str "compare"
- | Retroknowledge.Int31Head0 -> str "head0"
- | Retroknowledge.Int31Tail0 -> str "tail0"
- | Retroknowledge.Int31Lor -> str "lor"
- | Retroknowledge.Int31Land -> str "land"
- | Retroknowledge.Int31Lxor -> str "lxor"
-
-let pr_retroknowledge_field f =
- match f with
- (* | Retroknowledge.KEq -> str "equality"
- | Retroknowledge.KNat natf -> pr_r_nat_field () () () natf
- | Retroknowledge.KN nf -> pr_r_n_field () () () nf *)
- | Retroknowledge.KInt31 (group, i31f) -> (pr_r_int31_field i31f) ++
- spc () ++ str "in " ++ qs group
-
-VERNAC ARGUMENT EXTEND retroknowledge_int31
-PRINTED BY pr_r_int31_field
-| [ "int31" "bits" ] -> [ Retroknowledge.Int31Bits ]
-| [ "int31" "type" ] -> [ Retroknowledge.Int31Type ]
-| [ "int31" "twice" ] -> [ Retroknowledge.Int31Twice ]
-| [ "int31" "twice" "plus" "one" ] -> [ Retroknowledge.Int31TwicePlusOne ]
-| [ "int31" "phi" ] -> [ Retroknowledge.Int31Phi ]
-| [ "int31" "phi" "inv" ] -> [ Retroknowledge.Int31PhiInv ]
-| [ "int31" "plus" ] -> [ Retroknowledge.Int31Plus ]
-| [ "int31" "plusc" ] -> [ Retroknowledge.Int31PlusC ]
-| [ "int31" "pluscarryc" ] -> [ Retroknowledge.Int31PlusCarryC ]
-| [ "int31" "minus" ] -> [ Retroknowledge.Int31Minus ]
-| [ "int31" "minusc" ] -> [ Retroknowledge.Int31MinusC ]
-| [ "int31" "minuscarryc" ] -> [ Retroknowledge.Int31MinusCarryC ]
-| [ "int31" "times" ] -> [ Retroknowledge.Int31Times ]
-| [ "int31" "timesc" ] -> [ Retroknowledge.Int31TimesC ]
-| [ "int31" "div21" ] -> [ Retroknowledge.Int31Div21 ]
-| [ "int31" "div" ] -> [ Retroknowledge.Int31Div ]
-| [ "int31" "diveucl" ] -> [ Retroknowledge.Int31Diveucl ]
-| [ "int31" "addmuldiv" ] -> [ Retroknowledge.Int31AddMulDiv ]
-| [ "int31" "compare" ] -> [ Retroknowledge.Int31Compare ]
-| [ "int31" "head0" ] -> [ Retroknowledge.Int31Head0 ]
-| [ "int31" "tail0" ] -> [ Retroknowledge.Int31Tail0 ]
-| [ "int31" "lor" ] -> [ Retroknowledge.Int31Lor ]
-| [ "int31" "land" ] -> [ Retroknowledge.Int31Land ]
-| [ "int31" "lxor" ] -> [ Retroknowledge.Int31Lxor ]
-END
-
-VERNAC ARGUMENT EXTEND retroknowledge_field
-PRINTED BY pr_retroknowledge_field
-(*| [ "equality" ] -> [ Retroknowledge.KEq ]
-| [ retroknowledge_nat(n)] -> [ Retroknowledge.KNat n ]
-| [ retroknowledge_binary_n (n)] -> [ Retroknowledge.KN n ]*)
-| [ retroknowledge_int31 (i) "in" string(g)] -> [ Retroknowledge.KInt31(g,i) ]
-END
diff --git a/plugins/ltac/extraargs.mli b/plugins/ltac/extraargs.mli
index e477b12cd3..fa70235975 100644
--- a/plugins/ltac/extraargs.mli
+++ b/plugins/ltac/extraargs.mli
@@ -72,11 +72,6 @@ val test_lpar_id_colon : unit Pcoq.Entry.t
val wit_test_lpar_id_colon : (unit, unit, unit) Genarg.genarg_type
-(** Spiwack: Primitive for retroknowledge registration *)
-
-val retroknowledge_field : Retroknowledge.field Pcoq.Entry.t
-val wit_retroknowledge_field : (Retroknowledge.field, unit, unit) Genarg.genarg_type
-
val wit_in_clause :
(lident Locus.clause_expr,
lident Locus.clause_expr,
diff --git a/plugins/ltac/extratactics.ml4 b/plugins/ltac/extratactics.ml4
index dc027c4041..ba3fa6fa0d 100644
--- a/plugins/ltac/extratactics.ml4
+++ b/plugins/ltac/extratactics.ml4
@@ -26,6 +26,7 @@ open Termops
open Equality
open Namegen
open Tactypes
+open Tactics
open Proofview.Notations
open Vernacinterp
@@ -545,22 +546,6 @@ END
(**********************************************************************)
-(*spiwack : Vernac commands for retroknowledge *)
-
-VERNAC COMMAND EXTEND RetroknowledgeRegister CLASSIFIED AS SIDEFF
- | [ "Register" constr(c) "as" retroknowledge_field(f) "by" constr(b)] ->
- [ let env = Global.env () in
- let evd = Evd.from_env env in
- let tc,_ctx = Constrintern.interp_constr env evd c in
- let tb,_ctx(*FIXME*) = Constrintern.interp_constr env evd b in
- let tc = EConstr.to_constr evd tc in
- let tb = EConstr.to_constr evd tb in
- Global.register f tc tb ]
-END
-
-
-
-(**********************************************************************)
(* sozeau: abs/gen for induction on instantiated dependent inductives, using "Ford" induction as
defined by Conor McBride *)
TACTIC EXTEND generalize_eqs
@@ -796,9 +781,9 @@ END
(**********************************************************************)
TACTIC EXTEND transparent_abstract
-| [ "transparent_abstract" tactic3(t) ] -> [ Proofview.Goal.nf_enter begin fun gl ->
+| [ "transparent_abstract" tactic3(t) ] -> [ Proofview.Goal.enter begin fun gl ->
Tactics.tclABSTRACT ~opaque:false None (Tacinterp.tactic_of_value ist t) end ]
-| [ "transparent_abstract" tactic3(t) "using" ident(id) ] -> [ Proofview.Goal.nf_enter begin fun gl ->
+| [ "transparent_abstract" tactic3(t) "using" ident(id) ] -> [ Proofview.Goal.enter begin fun gl ->
Tactics.tclABSTRACT ~opaque:false (Some id) (Tacinterp.tactic_of_value ist t) end ]
END
diff --git a/plugins/ltac/g_ltac.ml4 b/plugins/ltac/g_ltac.ml4
index c13bd69daf..929390b1c4 100644
--- a/plugins/ltac/g_ltac.ml4
+++ b/plugins/ltac/g_ltac.ml4
@@ -314,22 +314,23 @@ GEXTEND Gram
range_selector_or_nth:
[ [ n = natural ; "-" ; m = natural;
l = OPT [","; l = LIST1 range_selector SEP "," -> l] ->
- SelectList ((n, m) :: Option.default [] l)
+ Goal_select.SelectList ((n, m) :: Option.default [] l)
| n = natural;
l = OPT [","; l = LIST1 range_selector SEP "," -> l] ->
+ let open Goal_select in
Option.cata (fun l -> SelectList ((n, n) :: l)) (SelectNth n) l ] ]
;
selector_body:
[ [ l = range_selector_or_nth -> l
- | test_bracket_ident; "["; id = ident; "]" -> SelectId id ] ]
+ | test_bracket_ident; "["; id = ident; "]" -> Goal_select.SelectId id ] ]
;
selector:
[ [ IDENT "only"; sel = selector_body; ":" -> sel ] ]
;
toplevel_selector:
[ [ sel = selector_body; ":" -> sel
- | "!"; ":" -> SelectAlreadyFocused
- | IDENT "all"; ":" -> SelectAll ] ]
+ | "!"; ":" -> Goal_select.SelectAlreadyFocused
+ | IDENT "all"; ":" -> Goal_select.SelectAll ] ]
;
tactic_mode:
[ [ g = OPT toplevel_selector; tac = G_vernac.query_command -> tac g
@@ -346,7 +347,7 @@ GEXTEND Gram
hint:
[ [ IDENT "Extern"; n = natural; c = OPT Constr.constr_pattern ; "=>";
tac = Pltac.tactic ->
- Vernacexpr.HintsExtern (n,c, in_tac tac) ] ]
+ Hints.HintsExtern (n,c, in_tac tac) ] ]
;
operconstr: LEVEL "0"
[ [ IDENT "ltac"; ":"; "("; tac = Pltac.tactic_expr; ")" ->
@@ -373,6 +374,7 @@ let _ = declare_int_option {
}
let vernac_solve n info tcom b =
+ let open Goal_select in
let status = Proof_global.with_current_proof (fun etac p ->
let with_end_tac = if b then Some etac else None in
let global = match n with SelectAll | SelectList _ -> true | _ -> false in
@@ -432,7 +434,7 @@ VERNAC tactic_mode EXTEND VernacSolve
VtLater
] -> [
let t = rm_abstract t in
- vernac_solve SelectAll n t def
+ vernac_solve Goal_select.SelectAll n t def
]
END
diff --git a/plugins/ltac/g_tactic.mlg b/plugins/ltac/g_tactic.mlg
index 2e1ce814aa..571595be70 100644
--- a/plugins/ltac/g_tactic.mlg
+++ b/plugins/ltac/g_tactic.mlg
@@ -21,6 +21,8 @@ open Constrexpr
open Libnames
open Tok
open Tactypes
+open Tactics
+open Inv
open Locus
open Decl_kinds
diff --git a/plugins/ltac/plugin_base.dune b/plugins/ltac/plugin_base.dune
new file mode 100644
index 0000000000..5611f5ba16
--- /dev/null
+++ b/plugins/ltac/plugin_base.dune
@@ -0,0 +1,13 @@
+(library
+ (name ltac_plugin)
+ (public_name coq.plugins.ltac)
+ (synopsis "Coq's LTAC tactic language")
+ (modules :standard \ tauto)
+ (libraries coq.stm))
+
+(library
+ (name tauto_plugin)
+ (public_name coq.plugins.tauto)
+ (synopsis "Coq's tauto tactic")
+ (modules tauto)
+ (libraries coq.plugins.ltac))
diff --git a/plugins/ltac/pptactic.ml b/plugins/ltac/pptactic.ml
index 4357689ee2..b219ee25ca 100644
--- a/plugins/ltac/pptactic.ml
+++ b/plugins/ltac/pptactic.ml
@@ -28,6 +28,7 @@ open Printer
open Tacexpr
open Tacarg
+open Tactics
module Tag =
struct
@@ -271,6 +272,8 @@ let string_of_genarg_arg (ArgumentType arg) =
in
pr_sequence pr prods
with Not_found ->
+ (* FIXME: This key, moreover printed with a low-level printer,
+ has no meaning user-side *)
KerName.print key
let pr_alias_gen pr_gen lev key l =
@@ -507,7 +510,7 @@ let string_of_genarg_arg (ArgumentType arg) =
let pr_destruction_arg prc prlc (clear_flag,h) =
pr_clear_flag clear_flag (pr_core_destruction_arg prc prlc) h
- let pr_inversion_kind = function
+ let pr_inversion_kind = let open Inv in function
| SimpleInversion -> primitive "simple inversion"
| FullInversion -> primitive "inversion"
| FullInversionClear -> primitive "inversion_clear"
@@ -516,7 +519,7 @@ let string_of_genarg_arg (ArgumentType arg) =
if Int.equal i j then int i
else int i ++ str "-" ++ int j
-let pr_goal_selector toplevel = function
+let pr_goal_selector toplevel = let open Goal_select in function
| SelectAlreadyFocused -> str "!:"
| SelectNth i -> int i ++ str ":"
| SelectList l -> prlist_with_sep (fun () -> str ", ") pr_range_selector l ++ str ":"
diff --git a/plugins/ltac/rewrite.ml b/plugins/ltac/rewrite.ml
index 9f8cd2fc4e..5b8bd6d01a 100644
--- a/plugins/ltac/rewrite.ml
+++ b/plugins/ltac/rewrite.ml
@@ -520,11 +520,6 @@ let rewrite_db = "rewrite"
let conv_transparent_state = (Id.Pred.empty, Cpred.full)
-let _ =
- Hints.add_hints_init
- (fun () ->
- Hints.create_hint_db false rewrite_db conv_transparent_state true)
-
let rewrite_transparent_state () =
Hints.Hint_db.transparent_state (Hints.searchtable_map rewrite_db)
diff --git a/plugins/ltac/tacenv.ml b/plugins/ltac/tacenv.ml
index 0bb9ccb1d8..1f2c722b34 100644
--- a/plugins/ltac/tacenv.ml
+++ b/plugins/ltac/tacenv.ml
@@ -144,7 +144,7 @@ let add ~deprecation kn b t =
mactab := KNmap.add kn entry !mactab
let replace kn path t =
- let (path, _, _) = KerName.repr path in
+ let path = KerName.modpath path in
let entry _ e = { e with tac_body = t; tac_redef = path :: e.tac_redef } in
mactab := KNmap.modify kn entry !mactab
diff --git a/plugins/ltac/tacenv.mli b/plugins/ltac/tacenv.mli
index 7143f51853..d5d36c97fa 100644
--- a/plugins/ltac/tacenv.mli
+++ b/plugins/ltac/tacenv.mli
@@ -41,7 +41,7 @@ val register_alias : alias -> alias_tactic -> unit
(** Register a tactic alias. *)
val interp_alias : alias -> alias_tactic
-(** Recover the the body of an alias. Raises an anomaly if it does not exist. *)
+(** Recover the body of an alias. Raises an anomaly if it does not exist. *)
val check_alias : alias -> bool
(** Returns [true] if an alias is defined, false otherwise. *)
diff --git a/plugins/ltac/tacexpr.ml b/plugins/ltac/tacexpr.ml
index 59b748e25e..11d13d3a2f 100644
--- a/plugins/ltac/tacexpr.ml
+++ b/plugins/ltac/tacexpr.ml
@@ -37,16 +37,24 @@ type clear_flag = bool option (* true = clear hyp, false = keep hyp, None = use
type goal_selector = Goal_select.t =
| SelectAlreadyFocused
+ [@ocaml.deprecated "Use constructors in [Goal_select]"]
| SelectNth of int
+ [@ocaml.deprecated "Use constructors in [Goal_select]"]
| SelectList of (int * int) list
+ [@ocaml.deprecated "Use constructors in [Goal_select]"]
| SelectId of Id.t
+ [@ocaml.deprecated "Use constructors in [Goal_select]"]
| SelectAll
-[@@ocaml.deprecated "Use Vernacexpr.goal_selector"]
+ [@ocaml.deprecated "Use constructors in [Goal_select]"]
+[@@ocaml.deprecated "Use [Goal_select.t]"]
type 'a core_destruction_arg = 'a Tactics.core_destruction_arg =
| ElimOnConstr of 'a
+ [@ocaml.deprecated "Use constructors in [Tactics]"]
| ElimOnIdent of lident
+ [@ocaml.deprecated "Use constructors in [Tactics]"]
| ElimOnAnonHyp of int
+ [@ocaml.deprecated "Use constructors in [Tactics]"]
[@@ocaml.deprecated "Use Tactics.core_destruction_arg"]
type 'a destruction_arg =
@@ -55,8 +63,11 @@ type 'a destruction_arg =
type inversion_kind = Inv.inversion_kind =
| SimpleInversion
+ [@ocaml.deprecated "Use constructors in [Inv]"]
| FullInversion
+ [@ocaml.deprecated "Use constructors in [Inv]"]
| FullInversionClear
+ [@ocaml.deprecated "Use constructors in [Inv]"]
[@@ocaml.deprecated "Use Tactics.inversion_kind"]
type ('c,'d,'id) inversion_strength =
diff --git a/plugins/ltac/tacexpr.mli b/plugins/ltac/tacexpr.mli
index 3a0badb28f..6b131edaac 100644
--- a/plugins/ltac/tacexpr.mli
+++ b/plugins/ltac/tacexpr.mli
@@ -37,16 +37,24 @@ type clear_flag = bool option (* true = clear hyp, false = keep hyp, None = use
type goal_selector = Goal_select.t =
| SelectAlreadyFocused
+ [@ocaml.deprecated "Use constructors in [Goal_select]"]
| SelectNth of int
+ [@ocaml.deprecated "Use constructors in [Goal_select]"]
| SelectList of (int * int) list
+ [@ocaml.deprecated "Use constructors in [Goal_select]"]
| SelectId of Id.t
+ [@ocaml.deprecated "Use constructors in [Goal_select]"]
| SelectAll
+ [@ocaml.deprecated "Use constructors in [Goal_select]"]
[@@ocaml.deprecated "Use Vernacexpr.goal_selector"]
type 'a core_destruction_arg = 'a Tactics.core_destruction_arg =
| ElimOnConstr of 'a
+ [@ocaml.deprecated "Use constructors in [Tactics]"]
| ElimOnIdent of lident
+ [@ocaml.deprecated "Use constructors in [Tactics]"]
| ElimOnAnonHyp of int
+ [@ocaml.deprecated "Use constructors in [Tactics]"]
[@@ocaml.deprecated "Use Tactics.core_destruction_arg"]
type 'a destruction_arg =
@@ -55,8 +63,11 @@ type 'a destruction_arg =
type inversion_kind = Inv.inversion_kind =
| SimpleInversion
+ [@ocaml.deprecated "Use constructors in [Inv]"]
| FullInversion
+ [@ocaml.deprecated "Use constructors in [Inv]"]
| FullInversionClear
+ [@ocaml.deprecated "Use constructors in [Inv]"]
[@@ocaml.deprecated "Use Tactics.inversion_kind"]
type ('c,'d,'id) inversion_strength =
diff --git a/plugins/ltac/tacintern.ml b/plugins/ltac/tacintern.ml
index 1444800624..5501cf92a5 100644
--- a/plugins/ltac/tacintern.ml
+++ b/plugins/ltac/tacintern.ml
@@ -29,6 +29,7 @@ open Stdarg
open Tacarg
open Namegen
open Tactypes
+open Tactics
open Locus
(** Globalization of tactic expressions :
diff --git a/plugins/ltac/tacinterp.ml b/plugins/ltac/tacinterp.ml
index a0446bd6a0..9f34df4608 100644
--- a/plugins/ltac/tacinterp.ml
+++ b/plugins/ltac/tacinterp.ml
@@ -37,6 +37,7 @@ open Tacarg
open Printer
open Pretyping
open Tactypes
+open Tactics
open Locus
open Tacintern
open Taccoerce
@@ -1297,7 +1298,7 @@ and tactic_of_value ist vle =
match appl with
UnnamedAppl -> "An unnamed user-defined tactic"
| GlbAppl apps ->
- let nms = List.map (fun (kn,_) -> Names.KerName.to_string kn) apps in
+ let nms = List.map (fun (kn,_) -> string_of_qualid (Tacenv.shortest_qualid_of_tactic kn)) apps in
match nms with
[] -> assert false
| kn::_ -> "The user-defined tactic \"" ^ kn ^ "\"" (* TODO: when do we not have a singleton? *)
@@ -1468,7 +1469,7 @@ and interp_genarg ist x : Val.t Ftactic.t =
independently of goals. *)
and interp_genarg_constr_list ist x =
- Ftactic.nf_enter begin fun gl ->
+ Ftactic.enter begin fun gl ->
let env = Proofview.Goal.env gl in
let sigma = Proofview.Goal.sigma gl in
let lc = Genarg.out_gen (glbwit (wit_list wit_constr)) x in
@@ -1600,7 +1601,7 @@ and interp_atomic ist tac : unit Proofview.tactic =
| TacMutualFix (id,n,l) ->
(* spiwack: until the tactic is in the monad *)
Proofview.Trace.name_tactic (fun () -> Pp.str"<mutual fix>") begin
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.enter begin fun gl ->
let env = pf_env gl in
let f sigma (id,n,c) =
let (sigma,c_interp) = interp_type ist env sigma c in
@@ -1615,7 +1616,7 @@ and interp_atomic ist tac : unit Proofview.tactic =
| TacMutualCofix (id,l) ->
(* spiwack: until the tactic is in the monad *)
Proofview.Trace.name_tactic (fun () -> Pp.str"<mutual cofix>") begin
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.enter begin fun gl ->
let env = pf_env gl in
let f sigma (id,c) =
let (sigma,c_interp) = interp_type ist env sigma c in
@@ -1664,16 +1665,18 @@ and interp_atomic ist tac : unit Proofview.tactic =
(* We try to fully-typecheck the term *)
let flags = open_constr_use_classes_flags () in
let (sigma,c_interp) = interp_open_constr ~flags ist env sigma c in
- let let_tac b na c cl eqpat =
- let id = Option.default (make IntroAnonymous) eqpat in
- let with_eq = if b then None else Some (true,id) in
- Tactics.letin_tac with_eq na c None cl
- in
let na = interp_name ist env sigma na in
+ let let_tac =
+ if b then Tactics.pose_tac na c_interp
+ else
+ let id = Option.default (make IntroAnonymous) eqpat in
+ let with_eq = Some (true, id) in
+ Tactics.letin_tac with_eq na c_interp None Locusops.nowhere
+ in
Tacticals.New.tclWITHHOLES ev
(name_atomic ~env
(TacLetTac(ev,na,c_interp,clp,b,eqpat))
- (let_tac b na c_interp clp eqpat)) sigma
+ let_tac) sigma
else
(* We try to keep the pattern structure as much as possible *)
let let_pat_tac b na c cl eqpat =
@@ -1693,7 +1696,7 @@ and interp_atomic ist tac : unit Proofview.tactic =
| TacInductionDestruct (isrec,ev,(l,el)) ->
(* spiwack: some unknown part of destruct needs the goal to be
prenormalised. *)
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.enter begin fun gl ->
let env = Proofview.Goal.env gl in
let sigma = project gl in
let sigma,l =
@@ -1720,7 +1723,7 @@ and interp_atomic ist tac : unit Proofview.tactic =
(* Conversion *)
| TacReduce (r,cl) ->
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.enter begin fun gl ->
let (sigma,r_interp) = interp_red_expr ist (pf_env gl) (project gl) r in
Tacticals.New.tclTHEN (Proofview.Unsafe.tclEVARS sigma)
(Tactics.reduce r_interp (interp_clause ist (pf_env gl) (project gl) cl))
@@ -2029,7 +2032,7 @@ let _ =
let (c, sigma) = Pfedit.refine_by_tactic env sigma ty tac in
(EConstr.of_constr c, sigma)
in
- Pretyping.register_constr_interp0 wit_tactic eval
+ GlobEnv.register_constr_interp0 wit_tactic eval
let vernac_debug b =
set_debug (if b then Tactic_debug.DebugOn 0 else Tactic_debug.DebugOff)
diff --git a/plugins/ltac/tacsubst.ml b/plugins/ltac/tacsubst.ml
index dd799dc131..4626378db6 100644
--- a/plugins/ltac/tacsubst.ml
+++ b/plugins/ltac/tacsubst.ml
@@ -15,6 +15,7 @@ open Genarg
open Stdarg
open Tacarg
open Tactypes
+open Tactics
open Globnames
open Genredexpr
open Patternops
diff --git a/plugins/ltac/tactic_debug.ml b/plugins/ltac/tactic_debug.ml
index 105b5c59ae..6bab8d0353 100644
--- a/plugins/ltac/tactic_debug.ml
+++ b/plugins/ltac/tactic_debug.ml
@@ -12,7 +12,6 @@ open Util
open Names
open Pp
open Tacexpr
-open Termops
let (ltac_trace_info : ltac_trace Exninfo.t) = Exninfo.make ()
@@ -51,14 +50,14 @@ let msg_tac_notice s = Proofview.NonLogical.print_notice (s++fnl())
let db_pr_goal gl =
let env = Proofview.Goal.env gl in
let concl = Proofview.Goal.concl gl in
- let penv = print_named_context env in
- let pc = print_constr_env env (Tacmach.New.project gl) concl in
+ let penv = Termops.Internal.print_named_context env in
+ let pc = Printer.pr_econstr_env env (Tacmach.New.project gl) concl in
str" " ++ hv 0 (penv ++ fnl () ++
str "============================" ++ fnl () ++
str" " ++ pc) ++ fnl ()
let db_pr_goal =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.enter begin fun gl ->
let pg = db_pr_goal gl in
Proofview.tclLIFT (msg_tac_notice (str "Goal:" ++ fnl () ++ pg))
end
@@ -243,7 +242,7 @@ let db_constr debug env sigma c =
let open Proofview.NonLogical in
is_debug debug >>= fun db ->
if db then
- msg_tac_debug (str "Evaluated term: " ++ print_constr_env env sigma c)
+ msg_tac_debug (str "Evaluated term: " ++ Printer.pr_econstr_env env sigma c)
else return ()
(* Prints the pattern rule *)
@@ -268,7 +267,7 @@ let db_matched_hyp debug env sigma (id,_,c) ido =
is_debug debug >>= fun db ->
if db then
msg_tac_debug (str "Hypothesis " ++ Id.print id ++ hyp_bound ido ++
- str " has been matched: " ++ print_constr_env env sigma c)
+ str " has been matched: " ++ Printer.pr_econstr_env env sigma c)
else return ()
(* Prints the matched conclusion *)
@@ -276,7 +275,7 @@ let db_matched_concl debug env sigma c =
let open Proofview.NonLogical in
is_debug debug >>= fun db ->
if db then
- msg_tac_debug (str "Conclusion has been matched: " ++ print_constr_env env sigma c)
+ msg_tac_debug (str "Conclusion has been matched: " ++ Printer.pr_econstr_env env sigma c)
else return ()
(* Prints a success message when the goal has been matched *)
diff --git a/plugins/micromega/coq_micromega.ml b/plugins/micromega/coq_micromega.ml
index f22147f8b0..e0a369ca5f 100644
--- a/plugins/micromega/coq_micromega.ml
+++ b/plugins/micromega/coq_micromega.ml
@@ -1456,7 +1456,7 @@ let micromega_order_change spec cert cert_typ env ff (*: unit Proofview.tactic*
let ff = dump_formula formula_typ (dump_cstr spec.coeff spec.dump_coeff) ff in
let vm = dump_varmap (spec.typ) (vm_of_list env) in
(* todo : directly generate the proof term - or generalize before conversion? *)
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.enter begin fun gl ->
Tacticals.New.tclTHENLIST
[
Tactics.change_concl
@@ -1709,7 +1709,7 @@ let micromega_gen
(normalise:'cst atom -> 'cst mc_cnf)
unsat deduce
spec dumpexpr prover tac =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.enter begin fun gl ->
let sigma = Tacmach.New.project gl in
let concl = Tacmach.New.pf_concl gl in
let hyps = Tacmach.New.pf_hyps_types gl in
@@ -1787,7 +1787,7 @@ let micromega_order_changer cert env ff =
let formula_typ = (EConstr.mkApp (Lazy.force coq_Cstr,[| coeff|])) in
let ff = dump_formula formula_typ (dump_cstr coeff dump_coeff) ff in
let vm = dump_varmap (typ) (vm_of_list env) in
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.enter begin fun gl ->
Tacticals.New.tclTHENLIST
[
(Tactics.change_concl
@@ -1817,7 +1817,7 @@ let micromega_genr prover tac =
proof_typ = Lazy.force coq_QWitness ;
dump_proof = dump_psatz coq_Q dump_q
} in
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.enter begin fun gl ->
let sigma = Tacmach.New.project gl in
let concl = Tacmach.New.pf_concl gl in
let hyps = Tacmach.New.pf_hyps_types gl in
diff --git a/plugins/micromega/plugin_base.dune b/plugins/micromega/plugin_base.dune
new file mode 100644
index 0000000000..0ae0e6855d
--- /dev/null
+++ b/plugins/micromega/plugin_base.dune
@@ -0,0 +1,7 @@
+(library
+ (name micromega_plugin)
+ (public_name coq.plugins.micromega)
+ ; be careful not to link the executable to the plugin!
+ (modules (:standard \ csdpcert))
+ (synopsis "Coq's micromega plugin")
+ (libraries num coq.plugins.ltac))
diff --git a/plugins/nsatz/plugin_base.dune b/plugins/nsatz/plugin_base.dune
new file mode 100644
index 0000000000..9da5b39972
--- /dev/null
+++ b/plugins/nsatz/plugin_base.dune
@@ -0,0 +1,5 @@
+(library
+ (name nsatz_plugin)
+ (public_name coq.plugins.nsatz)
+ (synopsis "Coq's nsatz solver plugin")
+ (libraries num coq.plugins.ltac))
diff --git a/plugins/omega/PreOmega.v b/plugins/omega/PreOmega.v
index 59fd9b8017..094adfda7a 100644
--- a/plugins/omega/PreOmega.v
+++ b/plugins/omega/PreOmega.v
@@ -85,6 +85,7 @@ Ltac zify_binop t thm a b:=
Ltac zify_op_1 :=
match goal with
+ | x := ?t : Z |- _ => let h := fresh "heq_" x in pose proof (eq_refl : x = t) as h; clearbody x
| |- context [ Z.max ?a ?b ] => zify_binop Z.max Z.max_spec a b
| H : context [ Z.max ?a ?b ] |- _ => zify_binop Z.max Z.max_spec a b
| |- context [ Z.min ?a ?b ] => zify_binop Z.min Z.min_spec a b
@@ -114,6 +115,7 @@ Ltac hide_Z_of_nat t :=
Ltac zify_nat_rel :=
match goal with
(* I: equalities *)
+ | x := ?t : nat |- _ => let h := fresh "heq_" x in pose proof (eq_refl : x = t) as h; clearbody x
| |- (@eq nat ?a ?b) => apply (Nat2Z.inj a b) (* shortcut *)
| H : context [ @eq nat ?a ?b ] |- _ => rewrite <- (Nat2Z.inj_iff a b) in H
| |- context [ @eq nat ?a ?b ] => rewrite <- (Nat2Z.inj_iff a b)
@@ -223,6 +225,7 @@ Ltac hide_Zpos t :=
Ltac zify_positive_rel :=
match goal with
(* I: equalities *)
+ | x := ?t : positive |- _ => let h := fresh "heq_" x in pose proof (eq_refl : x = t) as h; clearbody x
| |- (@eq positive ?a ?b) => apply Pos2Z.inj
| H : context [ @eq positive ?a ?b ] |- _ => rewrite <- (Pos2Z.inj_iff a b) in H
| |- context [ @eq positive ?a ?b ] => rewrite <- (Pos2Z.inj_iff a b)
@@ -348,6 +351,7 @@ Ltac hide_Z_of_N t :=
Ltac zify_N_rel :=
match goal with
(* I: equalities *)
+ | x := ?t : N |- _ => let h := fresh "heq_" x in pose proof (eq_refl : x = t) as h; clearbody x
| |- (@eq N ?a ?b) => apply (N2Z.inj a b) (* shortcut *)
| H : context [ @eq N ?a ?b ] |- _ => rewrite <- (N2Z.inj_iff a b) in H
| |- context [ @eq N ?a ?b ] => rewrite <- (N2Z.inj_iff a b)
diff --git a/plugins/omega/coq_omega.ml b/plugins/omega/coq_omega.ml
index e14c4e2ec1..abae6940fa 100644
--- a/plugins/omega/coq_omega.ml
+++ b/plugins/omega/coq_omega.ml
@@ -588,7 +588,7 @@ let abstract_path sigma typ path t =
let focused_simpl path =
let open Tacmach.New in
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.enter begin fun gl ->
let newc = context (project gl) (fun i t -> pf_nf gl t) (List.rev path) (pf_concl gl) in
convert_concl_no_check newc DEFAULTcast
end
@@ -656,7 +656,7 @@ let new_hole env sigma c =
let clever_rewrite_base_poly typ p result theorem =
let open Tacmach.New in
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.enter begin fun gl ->
let full = pf_concl gl in
let env = pf_env gl in
let (abstracted,occ) = abstract_path (project gl) typ (List.rev p) full in
@@ -708,7 +708,7 @@ let refine_app gl t =
let clever_rewrite p vpath t =
let open Tacmach.New in
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.enter begin fun gl ->
let full = pf_concl gl in
let (abstracted,occ) = abstract_path (project gl) (Lazy.force coq_Z) (List.rev p) full in
let vargs = List.map (fun p -> occurrence (project gl) p occ) vpath in
@@ -1763,7 +1763,7 @@ let onClearedName id tac =
(* so renaming may be necessary *)
tclTHEN
(tclTRY (clear [id]))
- (Proofview.Goal.nf_enter begin fun gl ->
+ (Proofview.Goal.enter begin fun gl ->
let id = fresh_id Id.Set.empty id gl in
tclTHEN (introduction id) (tac id)
end)
@@ -1771,7 +1771,7 @@ let onClearedName id tac =
let onClearedName2 id tac =
tclTHEN
(tclTRY (clear [id]))
- (Proofview.Goal.nf_enter begin fun gl ->
+ (Proofview.Goal.enter begin fun gl ->
let id1 = fresh_id Id.Set.empty (add_suffix id "_left") gl in
let id2 = fresh_id Id.Set.empty (add_suffix id "_right") gl in
tclTHENLIST [ introduction id1; introduction id2; tac id1 id2 ]
@@ -1956,7 +1956,7 @@ let destructure_goal =
try
let dec = decidability t in
tclTHEN
- (Proofview.Goal.nf_enter begin fun gl ->
+ (Proofview.Goal.enter begin fun gl ->
refine_app gl (mkApp (Lazy.force coq_dec_not_not, [| t; dec |]))
end)
intro
diff --git a/plugins/omega/plugin_base.dune b/plugins/omega/plugin_base.dune
new file mode 100644
index 0000000000..f512501c78
--- /dev/null
+++ b/plugins/omega/plugin_base.dune
@@ -0,0 +1,5 @@
+(library
+ (name omega_plugin)
+ (public_name coq.plugins.omega)
+ (synopsis "Coq's omega plugin")
+ (libraries coq.plugins.ltac))
diff --git a/plugins/quote/Quote.v b/plugins/quote/Quote.v
deleted file mode 100644
index 2d3d9170c1..0000000000
--- a/plugins/quote/Quote.v
+++ /dev/null
@@ -1,86 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-Declare ML Module "quote_plugin".
-
-(***********************************************************************
- The "abstract" type index is defined to represent variables.
-
- index : Set
- index_eq : index -> bool
- index_eq_prop: (n,m:index)(index_eq n m)=true -> n=m
- index_lt : index -> bool
- varmap : Type -> Type.
- varmap_find : (A:Type)A -> index -> (varmap A) -> A.
-
- The first arg. of varmap_find is the default value to take
- if the object is not found in the varmap.
-
- index_lt defines a total well-founded order, but we don't prove that.
-
-***********************************************************************)
-
-Set Implicit Arguments.
-
-Section variables_map.
-
-Variable A : Type.
-
-Inductive varmap : Type :=
- | Empty_vm : varmap
- | Node_vm : A -> varmap -> varmap -> varmap.
-
-Inductive index : Set :=
- | Left_idx : index -> index
- | Right_idx : index -> index
- | End_idx : index.
-
-Fixpoint varmap_find (default_value:A) (i:index) (v:varmap) {struct v} : A :=
- match i, v with
- | End_idx, Node_vm x _ _ => x
- | Right_idx i1, Node_vm x v1 v2 => varmap_find default_value i1 v2
- | Left_idx i1, Node_vm x v1 v2 => varmap_find default_value i1 v1
- | _, _ => default_value
- end.
-
-Fixpoint index_eq (n m:index) {struct m} : bool :=
- match n, m with
- | End_idx, End_idx => true
- | Left_idx n', Left_idx m' => index_eq n' m'
- | Right_idx n', Right_idx m' => index_eq n' m'
- | _, _ => false
- end.
-
-Fixpoint index_lt (n m:index) {struct m} : bool :=
- match n, m with
- | End_idx, Left_idx _ => true
- | End_idx, Right_idx _ => true
- | Left_idx n', Right_idx m' => true
- | Right_idx n', Right_idx m' => index_lt n' m'
- | Left_idx n', Left_idx m' => index_lt n' m'
- | _, _ => false
- end.
-
-Lemma index_eq_prop : forall n m:index, index_eq n m = true -> n = m.
- simple induction n; simple induction m; simpl; intros.
- rewrite (H i0 H1); reflexivity.
- discriminate.
- discriminate.
- discriminate.
- rewrite (H i0 H1); reflexivity.
- discriminate.
- discriminate.
- discriminate.
- reflexivity.
-Qed.
-
-End variables_map.
-
-Unset Implicit Arguments.
diff --git a/plugins/quote/g_quote.mlg b/plugins/quote/g_quote.mlg
deleted file mode 100644
index 749903c3ad..0000000000
--- a/plugins/quote/g_quote.mlg
+++ /dev/null
@@ -1,46 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-{
-
-open Ltac_plugin
-open Names
-open Tacexpr
-open Geninterp
-open Quote
-open Stdarg
-open Tacarg
-
-}
-
-DECLARE PLUGIN "quote_plugin"
-
-{
-
-let cont = Id.of_string "cont"
-let x = Id.of_string "x"
-
-let make_cont (k : Val.t) (c : EConstr.t) =
- let c = Tacinterp.Value.of_constr c in
- let tac = TacCall (Loc.tag (Locus.ArgVar CAst.(make cont), [Reference (Locus.ArgVar CAst.(make x))])) in
- let ist = { lfun = Id.Map.add cont k (Id.Map.singleton x c); extra = TacStore.empty; } in
- Tacinterp.eval_tactic_ist ist (TacArg (Loc.tag tac))
-
-}
-
-TACTIC EXTEND quote
-| [ "quote" ident(f) ] -> { quote f [] }
-| [ "quote" ident(f) "[" ne_ident_list(lc) "]"] -> { quote f lc }
-| [ "quote" ident(f) "in" constr(c) "using" tactic(k) ] ->
- { gen_quote (make_cont k) c f [] }
-| [ "quote" ident(f) "[" ne_ident_list(lc) "]"
- "in" constr(c) "using" tactic(k) ] ->
- { gen_quote (make_cont k) c f lc }
-END
diff --git a/plugins/quote/plugin_base.dune b/plugins/quote/plugin_base.dune
new file mode 100644
index 0000000000..323906acb2
--- /dev/null
+++ b/plugins/quote/plugin_base.dune
@@ -0,0 +1,5 @@
+(library
+ (name quote_plugin)
+ (public_name coq.plugins.quote)
+ (synopsis "Coq's quote plugin")
+ (libraries coq.plugins.ltac))
diff --git a/plugins/quote/quote.ml b/plugins/quote/quote.ml
deleted file mode 100644
index 7464b42dc5..0000000000
--- a/plugins/quote/quote.ml
+++ /dev/null
@@ -1,540 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-(* The `Quote' tactic *)
-
-(* The basic idea is to automatize the inversion of interpretation functions
- in 2-level approach
-
- Examples are given in \texttt{theories/DEMOS/DemoQuote.v}
-
- Suppose you have a langage \texttt{L} of 'abstract terms'
- and a type \texttt{A} of 'concrete terms'
- and a function \texttt{f : L -> (varmap A L) -> A}.
-
- Then, the tactic \texttt{quote f} will replace an
- expression \texttt{e} of type \texttt{A} by \texttt{(f vm t)}
- such that \texttt{e} and \texttt{(f vm t)} are convertible.
-
- The problem is then inverting the function \texttt{f}.
-
- The tactic works when:
-
- \begin{itemize}
- \item L is a simple inductive datatype. The constructors of L may
- have one of the three following forms:
-
- \begin{enumerate}
- \item ordinary recursive constructors like: \verb|Cplus : L -> L -> L|
- \item variable leaf like: \verb|Cvar : index -> L|
- \item constant leaf like \verb|Cconst : A -> L|
- \end{enumerate}
-
- The definition of \texttt{L} must contain at most one variable
- leaf and at most one constant leaf.
-
- When there are both a variable leaf and a constant leaf, there is
- an ambiguity on inversion. The term t can be either the
- interpretation of \texttt{(Cconst t)} or the interpretation of
- (\texttt{Cvar}~$i$) in a variable map containing the binding $i
- \rightarrow$~\texttt{t}. How to discriminate between these
- choices?
-
- To solve the dilemma, one gives to \texttt{quote} a list of
- \emph{constant constructors}: a term will be considered as a
- constant if it is either a constant constructor or the
- application of a constant constructor to constants. For example
- the list \verb+[S, O]+ defines the closed natural
- numbers. \texttt{(S (S O))} is a constant when \texttt{(S x)} is
- not.
-
- The definition of constants vary for each application of the
- tactic, so it can even be different for two applications of
- \texttt{quote} with the same function.
-
- \item \texttt{f} is a quite simple fixpoint on
- \texttt{L}. In particular, \texttt{f} must verify:
-
-\begin{verbatim}
- (f (Cvar i)) = (varmap_find vm default_value i)
-\end{verbatim}
-\begin{verbatim}
- (f (Cconst c)) = c
-\end{verbatim}
-
- where \texttt{index} and \texttt{varmap\_find} are those defined
- the \texttt{Quote} module. \emph{The tactic won't work with
- user's own variables map!!} It is mandatory to use the
- variable map defined in module \texttt{Quote}.
-
- \end{itemize}
-
- The method to proceed is then clear:
-
- \begin{itemize}
- \item Start with an empty hashtable of "registed leafs"
- that maps constr to integers and a "variable counter" equal to 0.
- \item Try to match the term with every right hand side of the
- definition of \texttt{f}.
-
- If there is one match, returns the correponding left hand
- side and call yourself recursively to get the arguments of this
- left hand side.
-
- If there is no match, we are at a leaf. That is the
- interpretation of either a variable or a constant.
-
- If it is a constant, return \texttt{Cconst} applied to that
- constant.
-
- If not, it is a variable. Look in the hashtable
- if this leaf has been already encountered. If not, increment
- the variable counter and add an entry to the hashtable; then
- return \texttt{(Cvar !variables\_counter)}
- \end{itemize}
-*)
-
-
-(*i*)
-open CErrors
-open Util
-open Names
-open Constr
-open EConstr
-open Pattern
-open Patternops
-open Constr_matching
-open Tacmach
-open Proofview.Notations
-(*i*)
-
-(*s First, we need to access some Coq constants
- We do that lazily, because this code can be linked before
- the constants are loaded in the environment *)
-
-let constant dir s =
- EConstr.of_constr @@ UnivGen.constr_of_global @@
- Coqlib.coq_reference "Quote" ("quote"::dir) s
-
-let coq_Empty_vm = lazy (constant ["Quote"] "Empty_vm")
-let coq_Node_vm = lazy (constant ["Quote"] "Node_vm")
-let coq_varmap_find = lazy (constant ["Quote"] "varmap_find")
-let coq_Right_idx = lazy (constant ["Quote"] "Right_idx")
-let coq_Left_idx = lazy (constant ["Quote"] "Left_idx")
-let coq_End_idx = lazy (constant ["Quote"] "End_idx")
-
-(*s Then comes the stuff to decompose the body of interpetation function
- and pre-compute the inversion data.
-
-For a function like:
-
-\begin{verbatim}
- Fixpoint interp (vm:varmap Prop) (f:form) :=
- match f with
- | f_and f1 f1 f2 => (interp f1) /\ (interp f2)
- | f_or f1 f1 f2 => (interp f1) \/ (interp f2)
- | f_var i => varmap_find Prop default_v i vm
- | f_const c => c
- end.
-\end{verbatim}
-
-With the constant constructors \texttt{C1}, \dots, \texttt{Cn}, the
-corresponding scheme will be:
-
-\begin{verbatim}
- {normal_lhs_rhs =
- [ "(f_and ?1 ?2)", "?1 /\ ?2";
- "(f_or ?1 ?2)", " ?1 \/ ?2";];
- return_type = "Prop";
- constants = Some [C1,...Cn];
- variable_lhs = Some "(f_var ?1)";
- constant_lhs = Some "(f_const ?1)"
- }
-\end{verbatim}
-
-If there is no constructor for variables in the type \texttt{form},
-then [variable_lhs] is [None]. Idem for constants and
-[constant_lhs]. Both cannot be equal to [None].
-
-The metas in the RHS must correspond to those in the LHS (one cannot
-exchange ?1 and ?2 in the example above)
-
-*)
-
-module ConstrSet = Set.Make(Constr)
-
-type inversion_scheme = {
- normal_lhs_rhs : (constr * constr_pattern) list;
- variable_lhs : constr option;
- return_type : constr;
- constants : ConstrSet.t;
- constant_lhs : constr option }
-
-(*s [compute_ivs gl f cs] computes the inversion scheme associated to
- [f:constr] with constants list [cs:constr list] in the context of
- goal [gl]. This function uses the auxiliary functions
- [i_can't_do_that], [decomp_term], [compute_lhs] and [compute_rhs]. *)
-
-let i_can't_do_that () = user_err Pp.(str "Quote: not a simple fixpoint")
-
-let decomp_term sigma c = EConstr.kind sigma (Termops.strip_outer_cast sigma c)
-
-(*s [compute_lhs typ i nargsi] builds the term \texttt{(C ?nargsi ...
- ?2 ?1)}, where \texttt{C} is the [i]-th constructor of inductive
- type [typ] *)
-
-let coerce_meta_out id =
- let s = Id.to_string id in
- int_of_string (String.sub s 1 (String.length s - 1))
-let coerce_meta_in n =
- Id.of_string ("M" ^ string_of_int n)
-
-let compute_lhs sigma typ i nargsi =
- match EConstr.kind sigma typ with
- | Ind((sp,0),u) ->
- let argsi = Array.init nargsi (fun j -> mkMeta (nargsi - j)) in
- mkApp (mkConstructU (((sp,0),i+1),u), argsi)
- | _ -> i_can't_do_that ()
-
-(*s This function builds the pattern from the RHS. Recursive calls are
- replaced by meta-variables ?i corresponding to those in the LHS *)
-
-let compute_rhs env sigma bodyi index_of_f =
- let rec aux c =
- match EConstr.kind sigma c with
- | App (j, args) when isRel sigma j && Int.equal (destRel sigma j) index_of_f (* recursive call *) ->
- let i = destRel sigma (Array.last args) in
- PMeta (Some (coerce_meta_in i))
- | App (f,args) ->
- PApp (pattern_of_constr env sigma (EConstr.to_constr sigma f), Array.map aux args)
- | Cast (c,_,_) -> aux c
- | _ -> pattern_of_constr env sigma (EConstr.to_constr sigma c)
- in
- aux bodyi
-
-(*s Now the function [compute_ivs] itself *)
-
-let compute_ivs f cs gl =
- let env = Proofview.Goal.env gl in
- let sigma = Tacmach.New.project gl in
- let (cst, u) = try destConst sigma f with DestKO -> i_can't_do_that () in
- let u = EInstance.kind sigma u in
- let body = Environ.constant_value_in (Global.env()) (cst, u) in
- let body = EConstr.of_constr body in
- match decomp_term sigma body with
- | Fix(([| len |], 0), ([| name |], [| typ |], [| body2 |])) ->
- let (args3, body3) = decompose_lam sigma body2 in
- let nargs3 = List.length args3 in
- let is_conv = Reductionops.is_conv env sigma in
- begin match decomp_term sigma body3 with
- | Case(_,p,c,lci) -> (* <p> Case c of c1 ... cn end *)
- let n_lhs_rhs = ref []
- and v_lhs = ref (None : constr option)
- and c_lhs = ref (None : constr option) in
- Array.iteri
- (fun i ci ->
- let argsi, bodyi = decompose_lam sigma ci in
- let nargsi = List.length argsi in
- (* REL (narg3 + nargsi + 1) is f *)
- (* REL nargsi+1 to REL nargsi + nargs3 are arguments of f *)
- (* REL 1 to REL nargsi are argsi (reverse order) *)
- (* First we test if the RHS is the RHS for constants *)
- if isRel sigma bodyi && Int.equal (destRel sigma bodyi) 1 then
- c_lhs := Some (compute_lhs sigma (snd (List.hd args3))
- i nargsi)
- (* Then we test if the RHS is the RHS for variables *)
- else begin match decompose_app sigma bodyi with
- | vmf, [_; _; a3; a4 ]
- when isRel sigma a3 && isRel sigma a4 && is_conv vmf
- (Lazy.force coq_varmap_find) ->
- v_lhs := Some (compute_lhs sigma
- (snd (List.hd args3))
- i nargsi)
- (* Third case: this is a normal LHS-RHS *)
- | _ ->
- n_lhs_rhs :=
- (compute_lhs sigma (snd (List.hd args3)) i nargsi,
- compute_rhs env sigma bodyi (nargs3 + nargsi + 1))
- :: !n_lhs_rhs
- end)
- lci;
-
- if Option.is_empty !c_lhs && Option.is_empty !v_lhs then i_can't_do_that ();
-
- (* The Cases predicate is a lambda; we assume no dependency *)
- let p = match EConstr.kind sigma p with
- | Lambda (_,_,p) -> Termops.pop p
- | _ -> p
- in
-
- { normal_lhs_rhs = List.rev !n_lhs_rhs;
- variable_lhs = !v_lhs;
- return_type = p;
- constants = List.fold_right ConstrSet.add cs ConstrSet.empty;
- constant_lhs = !c_lhs }
-
- | _ -> i_can't_do_that ()
- end
- |_ -> i_can't_do_that ()
-
-(* TODO for that function:
-\begin{itemize}
-\item handle the case where the return type is an argument of the
- function
-\item handle the case of simple mutual inductive (for example terms
- and lists of terms) formulas with the corresponding mutual
- recursvive interpretation functions.
-\end{itemize}
-*)
-
-(*s Stuff to build variables map, currently implemented as complete
-binary search trees (see file \texttt{Quote.v}) *)
-
-(* First the function to distinghish between constants (closed terms)
- and variables (open terms) *)
-
-let rec closed_under sigma cset t =
- (ConstrSet.mem (EConstr.Unsafe.to_constr t) cset) ||
- (match EConstr.kind sigma t with
- | Cast(c,_,_) -> closed_under sigma cset c
- | App(f,l) -> closed_under sigma cset f && Array.for_all (closed_under sigma cset) l
- | _ -> false)
-
-(*s [btree_of_array [| c1; c2; c3; c4; c5 |]] builds the complete
- binary search tree containing the [ci], that is:
-
-\begin{verbatim}
- c1
- / \
- c2 c3
- / \
- c4 c5
-\end{verbatim}
-
-The second argument is a constr (the common type of the [ci])
-*)
-
-let btree_of_array a ty =
- let size_of_a = Array.length a in
- let semi_size_of_a = size_of_a lsr 1 in
- let node = Lazy.force coq_Node_vm
- and empty = mkApp (Lazy.force coq_Empty_vm, [| ty |]) in
- let rec aux n =
- if n > size_of_a
- then empty
- else if n > semi_size_of_a
- then mkApp (node, [| ty; a.(n-1); empty; empty |])
- else mkApp (node, [| ty; a.(n-1); aux (2*n); aux (2*n+1) |])
- in
- aux 1
-
-(*s [btree_of_array] and [path_of_int] verify the following invariant:\\
- {\tt (varmap\_find A dv }[(path_of_int n)] [(btree_of_array a ty)]
- = [a.(n)]\\
- [n] must be [> 0] *)
-
-let path_of_int n =
- (* returns the list of digits of n in reverse order with
- initial 1 removed *)
- let rec digits_of_int n =
- if Int.equal n 1 then []
- else (Int.equal (n mod 2) 1)::(digits_of_int (n lsr 1))
- in
- List.fold_right
- (fun b c -> mkApp ((if b then Lazy.force coq_Right_idx
- else Lazy.force coq_Left_idx),
- [| c |]))
- (List.rev (digits_of_int n))
- (Lazy.force coq_End_idx)
-
-(*s The tactic works with a list of subterms sharing the same
- variables map. We need to sort terms in order to avoid than
- strange things happen during replacement of terms by their
- 'abstract' counterparties. *)
-
-(* [subterm t t'] tests if constr [t'] occurs in [t] *)
-(* This function does not descend under binders (lambda and Cases) *)
-
-let rec subterm gl (t : constr) (t' : constr) =
- (pf_conv_x gl t t') ||
- (match EConstr.kind (project gl) t with
- | App (f,args) -> Array.exists (fun t -> subterm gl t t') args
- | Cast(t,_,_) -> (subterm gl t t')
- | _ -> false)
-
-(*s We want to sort the list according to reverse subterm order. *)
-(* Since it's a partial order the algoritm of Sort.list won't work !! *)
-
-let rec sort_subterm gl l =
- let sigma = project gl in
- let rec insert c = function
- | [] -> [c]
- | (h::t as l) when EConstr.eq_constr sigma c h -> l (* Avoid doing the same work twice *)
- | h::t -> if subterm gl c h then c::h::t else h::(insert c t)
- in
- match l with
- | [] -> []
- | h::t -> insert h (sort_subterm gl t)
-
-module Constrhash = Hashtbl.Make(Constr)
-
-let subst_meta subst c =
- let subst = List.map (fun (i, c) -> i, EConstr.Unsafe.to_constr c) subst in
- EConstr.of_constr (Termops.subst_meta subst (EConstr.Unsafe.to_constr c))
-
-(*s Now we are able to do the inversion itself.
- We destructurate the term and use an imperative hashtable
- to store leafs that are already encountered.
- The type of arguments is:\\
- [ivs : inversion_scheme]\\
- [lc: constr list]\\
- [gl: goal sigma]\\ *)
-let quote_terms env sigma ivs lc =
- Coqlib.check_required_library ["Coq";"quote";"Quote"];
- let varhash = (Constrhash.create 17 : constr Constrhash.t) in
- let varlist = ref ([] : constr list) in (* list of variables *)
- let counter = ref 1 in (* number of variables created + 1 *)
- let rec aux c =
- let rec auxl l =
- match l with
- | (lhs, rhs)::tail ->
- begin try
- let s1 = Id.Map.bindings (matches env sigma rhs c) in
- let s2 = List.map (fun (i,c_i) -> (coerce_meta_out i,aux c_i)) s1
- in
- subst_meta s2 lhs
- with PatternMatchingFailure -> auxl tail
- end
- | [] ->
- begin match ivs.variable_lhs with
- | None ->
- begin match ivs.constant_lhs with
- | Some c_lhs -> subst_meta [1, c] c_lhs
- | None -> anomaly (Pp.str "invalid inversion scheme for quote.")
- end
- | Some var_lhs ->
- begin match ivs.constant_lhs with
- | Some c_lhs when closed_under sigma ivs.constants c ->
- subst_meta [1, c] c_lhs
- | _ ->
- begin
- try Constrhash.find varhash (EConstr.Unsafe.to_constr c)
- with Not_found ->
- let newvar =
- subst_meta [1, (path_of_int !counter)]
- var_lhs in
- begin
- incr counter;
- varlist := c :: !varlist;
- Constrhash.add varhash (EConstr.Unsafe.to_constr c) newvar;
- newvar
- end
- end
- end
- end
- in
- auxl ivs.normal_lhs_rhs
- in
- let lp = List.map aux lc in
- (lp, (btree_of_array (Array.of_list (List.rev !varlist))
- ivs.return_type ))
-
-(*s actually we could "quote" a list of terms instead of a single
- term. Ring for example needs that, but Ring doesn't use Quote
- yet. *)
-
-let pf_constrs_of_globals l =
- let rec aux l acc =
- match l with
- [] -> Proofview.tclUNIT (List.rev acc)
- | hd :: tl ->
- Tacticals.New.pf_constr_of_global hd >>= fun g -> aux tl (g :: acc)
- in aux l []
-
-let quote f lid =
- Proofview.Goal.enter begin fun gl ->
- let fg = Tacmach.New.pf_global f gl in
- let clg = List.map (fun id -> Tacmach.New.pf_global id gl) lid in
- Tacticals.New.pf_constr_of_global fg >>= fun f ->
- pf_constrs_of_globals clg >>= fun cl ->
- Proofview.Goal.nf_enter begin fun gl ->
- let env = Proofview.Goal.env gl in
- let sigma = Tacmach.New.project gl in
- let ivs = compute_ivs f (List.map (EConstr.to_constr sigma) cl) gl in
- let concl = Proofview.Goal.concl gl in
- let quoted_terms = quote_terms env sigma ivs [concl] in
- let (p, vm) = match quoted_terms with
- | [p], vm -> (p,vm)
- | _ -> assert false
- in
- match ivs.variable_lhs with
- | None -> Tactics.convert_concl (mkApp (f, [| p |])) DEFAULTcast
- | Some _ -> Tactics.convert_concl (mkApp (f, [| vm; p |])) DEFAULTcast
- end
- end
-
-let gen_quote cont c f lid =
- Proofview.Goal.enter begin fun gl ->
- let fg = Tacmach.New.pf_global f gl in
- let clg = List.map (fun id -> Tacmach.New.pf_global id gl) lid in
- Tacticals.New.pf_constr_of_global fg >>= fun f ->
- pf_constrs_of_globals clg >>= fun cl ->
- Proofview.Goal.nf_enter begin fun gl ->
- let env = Proofview.Goal.env gl in
- let sigma = Tacmach.New.project gl in
- let cl = List.map (EConstr.to_constr sigma) cl in
- let ivs = compute_ivs f cl gl in
- let quoted_terms = quote_terms env sigma ivs [c] in
- let (p, vm) = match quoted_terms with
- | [p], vm -> (p,vm)
- | _ -> assert false
- in
- match ivs.variable_lhs with
- | None -> cont (mkApp (f, [| p |]))
- | Some _ -> cont (mkApp (f, [| vm; p |]))
- end
- end
-
-(*i
-
-Just testing ...
-
-#use "include.ml";;
-open Quote;;
-
-let r = glob_constr_of_string;;
-
-let ivs = {
- normal_lhs_rhs =
- [ r "(f_and ?1 ?2)", r "?1/\?2";
- r "(f_not ?1)", r "~?1"];
- variable_lhs = Some (r "(f_atom ?1)");
- return_type = r "Prop";
- constants = ConstrSet.empty;
- constant_lhs = (r "nat")
-};;
-
-let t1 = r "True/\(True /\ ~False)";;
-let t2 = r "True/\~~False";;
-
-quote_term ivs () t1;;
-quote_term ivs () t2;;
-
-let ivs2 =
- normal_lhs_rhs =
- [ r "(f_and ?1 ?2)", r "?1/\?2";
- r "(f_not ?1)", r "~?1"
- r "True", r "f_true"];
- variable_lhs = Some (r "(f_atom ?1)");
- return_type = r "Prop";
- constants = ConstrSet.empty;
- constant_lhs = (r "nat")
-
-i*)
diff --git a/plugins/quote/quote_plugin.mlpack b/plugins/quote/quote_plugin.mlpack
deleted file mode 100644
index 2e9be09d8d..0000000000
--- a/plugins/quote/quote_plugin.mlpack
+++ /dev/null
@@ -1,2 +0,0 @@
-Quote
-G_quote
diff --git a/plugins/romega/README b/plugins/romega/README
deleted file mode 100644
index 86c9e58afd..0000000000
--- a/plugins/romega/README
+++ /dev/null
@@ -1,6 +0,0 @@
-This work was done for the RNRT Project Calife.
-As such it is distributed under the LGPL licence.
-
-Report bugs to :
- pierre.cregut@francetelecom.com
-
diff --git a/plugins/romega/ROmega.v b/plugins/romega/ROmega.v
deleted file mode 100644
index 657aae90e8..0000000000
--- a/plugins/romega/ROmega.v
+++ /dev/null
@@ -1,14 +0,0 @@
-(*************************************************************************
-
- PROJET RNRT Calife - 2001
- Author: Pierre Crégut - France Télécom R&D
- Licence : LGPL version 2.1
-
- *************************************************************************)
-
-Require Import ReflOmegaCore.
-Require Export Setoid.
-Require Export PreOmega.
-Require Export ZArith_base.
-Require Import OmegaPlugin.
-Declare ML Module "romega_plugin".
diff --git a/plugins/romega/ReflOmegaCore.v b/plugins/romega/ReflOmegaCore.v
deleted file mode 100644
index 51b99b9935..0000000000
--- a/plugins/romega/ReflOmegaCore.v
+++ /dev/null
@@ -1,1872 +0,0 @@
-(* -*- coding: utf-8 -*- *)
-(*************************************************************************
-
- PROJET RNRT Calife - 2001
- Author: Pierre Crégut - France Télécom R&D
- Licence du projet : LGPL version 2.1
-
- *************************************************************************)
-
-Require Import List Bool Sumbool EqNat Setoid Ring_theory Decidable ZArith_base.
-Delimit Scope Int_scope with I.
-
-(** * Abstract Integers. *)
-
-Module Type Int.
-
- Parameter t : Set.
-
- Bind Scope Int_scope with t.
-
- Parameter Inline zero : t.
- Parameter Inline one : t.
- Parameter Inline plus : t -> t -> t.
- Parameter Inline opp : t -> t.
- Parameter Inline minus : t -> t -> t.
- Parameter Inline mult : t -> t -> t.
-
- Notation "0" := zero : Int_scope.
- Notation "1" := one : Int_scope.
- Infix "+" := plus : Int_scope.
- Infix "-" := minus : Int_scope.
- Infix "*" := mult : Int_scope.
- Notation "- x" := (opp x) : Int_scope.
-
- Open Scope Int_scope.
-
- (** First, Int is a ring: *)
- Axiom ring : @ring_theory t 0 1 plus mult minus opp (@eq t).
-
- (** Int should also be ordered: *)
-
- Parameter Inline le : t -> t -> Prop.
- Parameter Inline lt : t -> t -> Prop.
- Parameter Inline ge : t -> t -> Prop.
- Parameter Inline gt : t -> t -> Prop.
- Notation "x <= y" := (le x y): Int_scope.
- Notation "x < y" := (lt x y) : Int_scope.
- Notation "x >= y" := (ge x y) : Int_scope.
- Notation "x > y" := (gt x y): Int_scope.
- Axiom le_lt_iff : forall i j, (i<=j) <-> ~(j<i).
- Axiom ge_le_iff : forall i j, (i>=j) <-> (j<=i).
- Axiom gt_lt_iff : forall i j, (i>j) <-> (j<i).
-
- (** Basic properties of this order *)
- Axiom lt_trans : forall i j k, i<j -> j<k -> i<k.
- Axiom lt_not_eq : forall i j, i<j -> i<>j.
-
- (** Compatibilities *)
- Axiom lt_0_1 : 0<1.
- Axiom plus_le_compat : forall i j k l, i<=j -> k<=l -> i+k<=j+l.
- Axiom opp_le_compat : forall i j, i<=j -> (-j)<=(-i).
- Axiom mult_lt_compat_l :
- forall i j k, 0 < k -> i < j -> k*i<k*j.
-
- (** We should have a way to decide the equality and the order*)
- Parameter compare : t -> t -> comparison.
- Infix "?=" := compare (at level 70, no associativity) : Int_scope.
- Axiom compare_Eq : forall i j, compare i j = Eq <-> i=j.
- Axiom compare_Lt : forall i j, compare i j = Lt <-> i<j.
- Axiom compare_Gt : forall i j, compare i j = Gt <-> i>j.
-
- (** Up to here, these requirements could be fulfilled
- by any totally ordered ring. Let's now be int-specific: *)
- Axiom le_lt_int : forall x y, x<y <-> x<=y+-(1).
-
- (** Btw, lt_0_1 could be deduced from this last axiom *)
-
- (** Now we also require a division function.
- It is deliberately underspecified, since that's enough
- for the proofs below. But the most appropriate variant
- (and the one needed to stay in sync with the omega engine)
- is "Floor" (the historical version of Coq's [Z.div]). *)
-
- Parameter diveucl : t -> t -> t * t.
- Notation "i / j" := (fst (diveucl i j)).
- Notation "i 'mod' j" := (snd (diveucl i j)).
- Axiom diveucl_spec :
- forall i j, j<>0 -> i = j * (i/j) + (i mod j).
-
-End Int.
-
-
-
-(** Of course, Z is a model for our abstract int *)
-
-Module Z_as_Int <: Int.
-
- Open Scope Z_scope.
-
- Definition t := Z.
- Definition zero := 0.
- Definition one := 1.
- Definition plus := Z.add.
- Definition opp := Z.opp.
- Definition minus := Z.sub.
- Definition mult := Z.mul.
-
- Lemma ring : @ring_theory t zero one plus mult minus opp (@eq t).
- Proof.
- constructor.
- exact Z.add_0_l.
- exact Z.add_comm.
- exact Z.add_assoc.
- exact Z.mul_1_l.
- exact Z.mul_comm.
- exact Z.mul_assoc.
- exact Z.mul_add_distr_r.
- unfold minus, Z.sub; auto.
- exact Z.add_opp_diag_r.
- Qed.
-
- Definition le := Z.le.
- Definition lt := Z.lt.
- Definition ge := Z.ge.
- Definition gt := Z.gt.
- Definition le_lt_iff := Z.le_ngt.
- Definition ge_le_iff := Z.ge_le_iff.
- Definition gt_lt_iff := Z.gt_lt_iff.
-
- Definition lt_trans := Z.lt_trans.
- Definition lt_not_eq := Z.lt_neq.
-
- Definition lt_0_1 := Z.lt_0_1.
- Definition plus_le_compat := Z.add_le_mono.
- Definition mult_lt_compat_l := Zmult_lt_compat_l.
- Lemma opp_le_compat i j : i<=j -> (-j)<=(-i).
- Proof. apply -> Z.opp_le_mono. Qed.
-
- Definition compare := Z.compare.
- Definition compare_Eq := Z.compare_eq_iff.
- Lemma compare_Lt i j : compare i j = Lt <-> i<j.
- Proof. reflexivity. Qed.
- Lemma compare_Gt i j : compare i j = Gt <-> i>j.
- Proof. reflexivity. Qed.
-
- Definition le_lt_int := Z.lt_le_pred.
-
- Definition diveucl := Z.div_eucl.
- Definition diveucl_spec := Z.div_mod.
-
-End Z_as_Int.
-
-
-(** * Properties of abstract integers *)
-
-Module IntProperties (I:Int).
- Import I.
- Local Notation int := I.t.
-
- (** Primo, some consequences of being a ring theory... *)
-
- Definition two := 1+1.
- Notation "2" := two : Int_scope.
-
- (** Aliases for properties packed in the ring record. *)
-
- Definition plus_assoc := ring.(Radd_assoc).
- Definition plus_comm := ring.(Radd_comm).
- Definition plus_0_l := ring.(Radd_0_l).
- Definition mult_assoc := ring.(Rmul_assoc).
- Definition mult_comm := ring.(Rmul_comm).
- Definition mult_1_l := ring.(Rmul_1_l).
- Definition mult_plus_distr_r := ring.(Rdistr_l).
- Definition opp_def := ring.(Ropp_def).
- Definition minus_def := ring.(Rsub_def).
-
- Opaque plus_assoc plus_comm plus_0_l mult_assoc mult_comm mult_1_l
- mult_plus_distr_r opp_def minus_def.
-
- (** More facts about [plus] *)
-
- Lemma plus_0_r : forall x, x+0 = x.
- Proof. intros; rewrite plus_comm; apply plus_0_l. Qed.
-
- Lemma plus_permute : forall x y z, x+(y+z) = y+(x+z).
- Proof. intros; do 2 rewrite plus_assoc; f_equal; apply plus_comm. Qed.
-
- Lemma plus_reg_l : forall x y z, x+y = x+z -> y = z.
- Proof.
- intros.
- rewrite <- (plus_0_r y), <- (plus_0_r z), <-(opp_def x).
- now rewrite plus_permute, plus_assoc, H, <- plus_assoc, plus_permute.
- Qed.
-
- (** More facts about [mult] *)
-
- Lemma mult_plus_distr_l : forall x y z, x*(y+z)=x*y+x*z.
- Proof.
- intros.
- rewrite (mult_comm x (y+z)), (mult_comm x y), (mult_comm x z).
- apply mult_plus_distr_r.
- Qed.
-
- Lemma mult_0_l x : 0*x = 0.
- Proof.
- assert (H := mult_plus_distr_r 0 1 x).
- rewrite plus_0_l, mult_1_l, plus_comm in H.
- apply plus_reg_l with x.
- now rewrite <- H, plus_0_r.
- Qed.
-
- Lemma mult_0_r x : x*0 = 0.
- Proof.
- rewrite mult_comm. apply mult_0_l.
- Qed.
-
- Lemma mult_1_r x : x*1 = x.
- Proof.
- rewrite mult_comm. apply mult_1_l.
- Qed.
-
- (** More facts about [opp] *)
-
- Definition plus_opp_r := opp_def.
-
- Lemma plus_opp_l : forall x, -x + x = 0.
- Proof. intros; now rewrite plus_comm, opp_def. Qed.
-
- Lemma mult_opp_comm : forall x y, - x * y = x * - y.
- Proof.
- intros.
- apply plus_reg_l with (x*y).
- rewrite <- mult_plus_distr_l, <- mult_plus_distr_r.
- now rewrite opp_def, opp_def, mult_0_l, mult_comm, mult_0_l.
- Qed.
-
- Lemma opp_eq_mult_neg_1 : forall x, -x = x * -(1).
- Proof.
- intros; now rewrite mult_comm, mult_opp_comm, mult_1_l.
- Qed.
-
- Lemma opp_involutive : forall x, -(-x) = x.
- Proof.
- intros.
- apply plus_reg_l with (-x).
- now rewrite opp_def, plus_comm, opp_def.
- Qed.
-
- Lemma opp_plus_distr : forall x y, -(x+y) = -x + -y.
- Proof.
- intros.
- apply plus_reg_l with (x+y).
- rewrite opp_def.
- rewrite plus_permute.
- do 2 rewrite plus_assoc.
- now rewrite (plus_comm (-x)), opp_def, plus_0_l, opp_def.
- Qed.
-
- Lemma opp_mult_distr_r : forall x y, -(x*y) = x * -y.
- Proof.
- intros.
- rewrite <- mult_opp_comm.
- apply plus_reg_l with (x*y).
- now rewrite opp_def, <-mult_plus_distr_r, opp_def, mult_0_l.
- Qed.
-
- Lemma egal_left n m : 0 = n+-m <-> n = m.
- Proof.
- split; intros.
- - apply plus_reg_l with (-m).
- rewrite plus_comm, <- H. symmetry. apply plus_opp_l.
- - symmetry. subst; apply opp_def.
- Qed.
-
- (** Specialized distributivities *)
-
- Hint Rewrite mult_plus_distr_l mult_plus_distr_r mult_assoc : int.
- Hint Rewrite <- plus_assoc : int.
-
- Hint Rewrite plus_0_l plus_0_r mult_0_l mult_0_r mult_1_l mult_1_r : int.
-
- Lemma OMEGA10 v c1 c2 l1 l2 k1 k2 :
- v * (c1 * k1 + c2 * k2) + (l1 * k1 + l2 * k2) =
- (v * c1 + l1) * k1 + (v * c2 + l2) * k2.
- Proof.
- autorewrite with int; f_equal; now rewrite plus_permute.
- Qed.
-
- Lemma OMEGA11 v1 c1 l1 l2 k1 :
- v1 * (c1 * k1) + (l1 * k1 + l2) = (v1 * c1 + l1) * k1 + l2.
- Proof.
- now autorewrite with int.
- Qed.
-
- Lemma OMEGA12 v2 c2 l1 l2 k2 :
- v2 * (c2 * k2) + (l1 + l2 * k2) = l1 + (v2 * c2 + l2) * k2.
- Proof.
- autorewrite with int; now rewrite plus_permute.
- Qed.
-
- Lemma sum1 a b c d : 0 = a -> 0 = b -> 0 = a * c + b * d.
- Proof.
- intros; subst. now autorewrite with int.
- Qed.
-
-
- (** Secondo, some results about order (and equality) *)
-
- Lemma lt_irrefl : forall n, ~ n<n.
- Proof.
- intros n H.
- elim (lt_not_eq _ _ H); auto.
- Qed.
-
- Lemma lt_antisym : forall n m, n<m -> m<n -> False.
- Proof.
- intros; elim (lt_irrefl _ (lt_trans _ _ _ H H0)); auto.
- Qed.
-
- Lemma lt_le_weak : forall n m, n<m -> n<=m.
- Proof.
- intros; rewrite le_lt_iff; intro H'; eapply lt_antisym; eauto.
- Qed.
-
- Lemma le_refl : forall n, n<=n.
- Proof.
- intros; rewrite le_lt_iff; apply lt_irrefl; auto.
- Qed.
-
- Lemma le_antisym : forall n m, n<=m -> m<=n -> n=m.
- Proof.
- intros n m; do 2 rewrite le_lt_iff; intros.
- rewrite <- compare_Lt in H0.
- rewrite <- gt_lt_iff, <- compare_Gt in H.
- rewrite <- compare_Eq.
- destruct compare; intuition.
- Qed.
-
- Lemma lt_eq_lt_dec : forall n m, { n<m }+{ n=m }+{ m<n }.
- Proof.
- intros.
- generalize (compare_Lt n m)(compare_Eq n m)(compare_Gt n m).
- destruct compare; [ left; right | left; left | right ]; intuition.
- rewrite gt_lt_iff in H1; intuition.
- Qed.
-
- Lemma lt_dec : forall n m: int, { n<m } + { ~n<m }.
- Proof.
- intros.
- generalize (compare_Lt n m)(compare_Eq n m)(compare_Gt n m).
- destruct compare; [ right | left | right ]; intuition discriminate.
- Qed.
-
- Lemma lt_le_iff : forall n m, (n<m) <-> ~(m<=n).
- Proof.
- intros.
- rewrite le_lt_iff.
- destruct (lt_dec n m); intuition.
- Qed.
-
- Lemma le_dec : forall n m: int, { n<=m } + { ~n<=m }.
- Proof.
- intros; destruct (lt_dec m n); [right|left]; rewrite le_lt_iff; intuition.
- Qed.
-
- Lemma le_lt_dec : forall n m, { n<=m } + { m<n }.
- Proof.
- intros; destruct (le_dec n m); [left|right]; auto; now rewrite lt_le_iff.
- Qed.
-
-
- Definition beq i j := match compare i j with Eq => true | _ => false end.
-
- Infix "=?" := beq : Int_scope.
-
- Lemma beq_iff i j : (i =? j) = true <-> i=j.
- Proof.
- unfold beq. rewrite <- (compare_Eq i j). now destruct compare.
- Qed.
-
- Lemma beq_reflect i j : reflect (i=j) (i =? j).
- Proof.
- apply iff_reflect. symmetry. apply beq_iff.
- Qed.
-
- Lemma eq_dec : forall n m:int, { n=m } + { n<>m }.
- Proof.
- intros n m; generalize (beq_iff n m); destruct beq; [left|right]; intuition.
- Qed.
-
- Definition blt i j := match compare i j with Lt => true | _ => false end.
-
- Infix "<?" := blt : Int_scope.
-
- Lemma blt_iff i j : (i <? j) = true <-> i<j.
- Proof.
- unfold blt. rewrite <- (compare_Lt i j). now destruct compare.
- Qed.
-
- Lemma blt_reflect i j : reflect (i<j) (i <? j).
- Proof.
- apply iff_reflect. symmetry. apply blt_iff.
- Qed.
-
- Lemma le_is_lt_or_eq : forall n m, n<=m -> { n<m } + { n=m }.
- Proof.
- intros n m Hnm.
- destruct (eq_dec n m) as [H'|H'].
- - right; intuition.
- - left; rewrite lt_le_iff.
- contradict H'.
- now apply le_antisym.
- Qed.
-
- Lemma le_neq_lt : forall n m, n<=m -> n<>m -> n<m.
- Proof.
- intros n m H. now destruct (le_is_lt_or_eq _ _ H).
- Qed.
-
- Lemma le_trans : forall n m p, n<=m -> m<=p -> n<=p.
- Proof.
- intros n m p; rewrite 3 le_lt_iff; intros A B C.
- destruct (lt_eq_lt_dec p m) as [[H|H]|H]; subst; auto.
- generalize (lt_trans _ _ _ H C); intuition.
- Qed.
-
- Lemma not_eq (a b:int) : ~ a <> b <-> a = b.
- Proof.
- destruct (eq_dec a b); intuition.
- Qed.
-
- (** Order and operations *)
-
- Lemma le_0_neg n : n <= 0 <-> 0 <= -n.
- Proof.
- rewrite <- (mult_0_l (-(1))) at 2.
- rewrite <- opp_eq_mult_neg_1.
- split; intros.
- - now apply opp_le_compat.
- - rewrite <-(opp_involutive 0), <-(opp_involutive n).
- now apply opp_le_compat.
- Qed.
-
- Lemma plus_le_reg_r : forall n m p, n + p <= m + p -> n <= m.
- Proof.
- intros.
- replace n with ((n+p)+-p).
- replace m with ((m+p)+-p).
- apply plus_le_compat; auto.
- apply le_refl.
- now rewrite <- plus_assoc, opp_def, plus_0_r.
- now rewrite <- plus_assoc, opp_def, plus_0_r.
- Qed.
-
- Lemma plus_le_lt_compat : forall n m p q, n<=m -> p<q -> n+p<m+q.
- Proof.
- intros.
- apply le_neq_lt.
- apply plus_le_compat; auto.
- apply lt_le_weak; auto.
- rewrite lt_le_iff in H0.
- contradict H0.
- apply plus_le_reg_r with m.
- rewrite (plus_comm q m), <-H0, (plus_comm p m).
- apply plus_le_compat; auto.
- apply le_refl; auto.
- Qed.
-
- Lemma plus_lt_compat : forall n m p q, n<m -> p<q -> n+p<m+q.
- Proof.
- intros.
- apply plus_le_lt_compat; auto.
- apply lt_le_weak; auto.
- Qed.
-
- Lemma opp_lt_compat : forall n m, n<m -> -m < -n.
- Proof.
- intros n m; do 2 rewrite lt_le_iff; intros H; contradict H.
- rewrite <-(opp_involutive m), <-(opp_involutive n).
- apply opp_le_compat; auto.
- Qed.
-
- Lemma lt_0_neg n : n < 0 <-> 0 < -n.
- Proof.
- rewrite <- (mult_0_l (-(1))) at 2.
- rewrite <- opp_eq_mult_neg_1.
- split; intros.
- - now apply opp_lt_compat.
- - rewrite <-(opp_involutive 0), <-(opp_involutive n).
- now apply opp_lt_compat.
- Qed.
-
- Lemma mult_lt_0_compat : forall n m, 0 < n -> 0 < m -> 0 < n*m.
- Proof.
- intros.
- rewrite <- (mult_0_l n), mult_comm.
- apply mult_lt_compat_l; auto.
- Qed.
-
- Lemma mult_integral_r n m : 0 < n -> n * m = 0 -> m = 0.
- Proof.
- intros Hn H.
- destruct (lt_eq_lt_dec 0 m) as [[Hm| <- ]|Hm]; auto; exfalso.
- - generalize (mult_lt_0_compat _ _ Hn Hm).
- rewrite H.
- exact (lt_irrefl 0).
- - rewrite lt_0_neg in Hm.
- generalize (mult_lt_0_compat _ _ Hn Hm).
- rewrite <- opp_mult_distr_r, opp_eq_mult_neg_1, H, mult_0_l.
- exact (lt_irrefl 0).
- Qed.
-
- Lemma mult_integral n m : n * m = 0 -> n = 0 \/ m = 0.
- Proof.
- intros H.
- destruct (lt_eq_lt_dec 0 n) as [[Hn|Hn]|Hn].
- - right; apply (mult_integral_r n m); trivial.
- - now left.
- - right; apply (mult_integral_r (-n) m).
- + now apply lt_0_neg.
- + rewrite mult_comm, <- opp_mult_distr_r, mult_comm, H.
- now rewrite opp_eq_mult_neg_1, mult_0_l.
- Qed.
-
- Lemma mult_le_compat_l i j k :
- 0<=k -> i<=j -> k*i <= k*j.
- Proof.
- intros Hk Hij.
- apply le_is_lt_or_eq in Hk. apply le_is_lt_or_eq in Hij.
- destruct Hk as [Hk | <-], Hij as [Hij | <-];
- rewrite ? mult_0_l; try apply le_refl.
- now apply lt_le_weak, mult_lt_compat_l.
- Qed.
-
- Lemma mult_le_compat i j k l :
- i<=j -> k<=l -> 0<=i -> 0<=k -> i*k<=j*l.
- Proof.
- intros Hij Hkl Hi Hk.
- apply le_trans with (i*l).
- - now apply mult_le_compat_l.
- - rewrite (mult_comm i), (mult_comm j).
- apply mult_le_compat_l; trivial.
- now apply le_trans with k.
- Qed.
-
- Lemma sum5 a b c d : 0 <> c -> 0 <> a -> 0 = b -> 0 <> a * c + b * d.
- Proof.
- intros Hc Ha <-. autorewrite with int. contradict Hc.
- symmetry in Hc. destruct (mult_integral _ _ Hc); congruence.
- Qed.
-
- Lemma le_left n m : n <= m <-> 0 <= m + - n.
- Proof.
- split; intros.
- - rewrite <- (opp_def m).
- apply plus_le_compat.
- apply le_refl.
- apply opp_le_compat; auto.
- - apply plus_le_reg_r with (-n).
- now rewrite plus_opp_r.
- Qed.
-
- Lemma OMEGA8 x y : 0 <= x -> 0 <= y -> x = - y -> x = 0.
- Proof.
- intros.
- assert (y=-x).
- subst x; symmetry; apply opp_involutive.
- clear H1; subst y.
- destruct (eq_dec 0 x) as [H'|H']; auto.
- assert (H'':=le_neq_lt _ _ H H').
- generalize (plus_le_lt_compat _ _ _ _ H0 H'').
- rewrite plus_opp_l, plus_0_l.
- intros.
- elim (lt_not_eq _ _ H1); auto.
- Qed.
-
- Lemma sum2 a b c d :
- 0 <= d -> 0 = a -> 0 <= b -> 0 <= a * c + b * d.
- Proof.
- intros Hd <- Hb. autorewrite with int.
- rewrite <- (mult_0_l 0).
- apply mult_le_compat; auto; apply le_refl.
- Qed.
-
- Lemma sum3 a b c d :
- 0 <= c -> 0 <= d -> 0 <= a -> 0 <= b -> 0 <= a * c + b * d.
- Proof.
- intros.
- rewrite <- (plus_0_l 0).
- apply plus_le_compat; auto.
- rewrite <- (mult_0_l 0).
- apply mult_le_compat; auto; apply le_refl.
- rewrite <- (mult_0_l 0).
- apply mult_le_compat; auto; apply le_refl.
- Qed.
-
- (** Lemmas specific to integers (they use [le_lt_int]) *)
-
- Lemma lt_left n m : n < m <-> 0 <= m + -n + -(1).
- Proof.
- rewrite <- plus_assoc, (plus_comm (-n)), plus_assoc.
- rewrite <- le_left.
- apply le_lt_int.
- Qed.
-
- Lemma OMEGA4 x y z : 0 < x -> x < y -> z * y + x <> 0.
- Proof.
- intros H H0 H'.
- assert (0 < y) by now apply lt_trans with x.
- destruct (lt_eq_lt_dec z 0) as [[G|G]|G].
-
- - generalize (plus_le_lt_compat _ _ _ _ (le_refl (z*y)) H0).
- rewrite H'.
- rewrite <-(mult_1_l y) at 2. rewrite <-mult_plus_distr_r.
- apply le_lt_iff.
- rewrite mult_comm. rewrite <- (mult_0_r y).
- apply mult_le_compat_l; auto using lt_le_weak.
- apply le_0_neg. rewrite opp_plus_distr.
- apply le_lt_int. now apply lt_0_neg.
-
- - apply (lt_not_eq 0 (z*y+x)); auto.
- subst. now autorewrite with int.
-
- - apply (lt_not_eq 0 (z*y+x)); auto.
- rewrite <- (plus_0_l 0).
- auto using plus_lt_compat, mult_lt_0_compat.
- Qed.
-
- Lemma OMEGA19 x : x<>0 -> 0 <= x + -(1) \/ 0 <= x * -(1) + -(1).
- Proof.
- intros.
- do 2 rewrite <- le_lt_int.
- rewrite <- opp_eq_mult_neg_1.
- destruct (lt_eq_lt_dec 0 x) as [[H'|H']|H'].
- auto.
- congruence.
- right.
- rewrite <-(mult_0_l (-(1))), <-(opp_eq_mult_neg_1 0).
- apply opp_lt_compat; auto.
- Qed.
-
- Lemma mult_le_approx n m p :
- 0 < n -> p < n -> 0 <= m * n + p -> 0 <= m.
- Proof.
- do 2 rewrite le_lt_iff; intros Hn Hpn H Hm. destruct H.
- apply lt_0_neg, le_lt_int, le_left in Hm.
- rewrite lt_0_neg.
- rewrite opp_plus_distr, mult_comm, opp_mult_distr_r.
- rewrite le_lt_int. apply lt_left.
- rewrite le_lt_int.
- apply le_trans with (n+-(1)); [ now apply le_lt_int | ].
- apply plus_le_compat; [ | apply le_refl ].
- rewrite <- (mult_1_r n) at 1.
- apply mult_le_compat_l; auto using lt_le_weak.
- Qed.
-
- (** Some decidabilities *)
-
- Lemma dec_eq : forall i j:int, decidable (i=j).
- Proof.
- red; intros; destruct (eq_dec i j); auto.
- Qed.
-
- Lemma dec_ne : forall i j:int, decidable (i<>j).
- Proof.
- red; intros; destruct (eq_dec i j); auto.
- Qed.
-
- Lemma dec_le : forall i j:int, decidable (i<=j).
- Proof.
- red; intros; destruct (le_dec i j); auto.
- Qed.
-
- Lemma dec_lt : forall i j:int, decidable (i<j).
- Proof.
- red; intros; destruct (lt_dec i j); auto.
- Qed.
-
- Lemma dec_ge : forall i j:int, decidable (i>=j).
- Proof.
- red; intros; rewrite ge_le_iff; destruct (le_dec j i); auto.
- Qed.
-
- Lemma dec_gt : forall i j:int, decidable (i>j).
- Proof.
- red; intros; rewrite gt_lt_iff; destruct (lt_dec j i); auto.
- Qed.
-
-End IntProperties.
-
-
-(** * The Coq side of the romega tactic *)
-
-Module IntOmega (I:Int).
-Import I.
-Module IP:=IntProperties(I).
-Import IP.
-Local Notation int := I.t.
-
-(* ** Definition of reified integer expressions
-
- Terms are either:
- - integers [Tint]
- - variables [Tvar]
- - operation over integers (addition, product, opposite, subtraction)
-
- Opposite and subtraction are translated in additions and products.
- Note that we'll only deal with products for which at least one side
- is [Tint]. *)
-
-Inductive term : Set :=
- | Tint : int -> term
- | Tplus : term -> term -> term
- | Tmult : term -> term -> term
- | Tminus : term -> term -> term
- | Topp : term -> term
- | Tvar : N -> term.
-
-Bind Scope romega_scope with term.
-Delimit Scope romega_scope with term.
-Arguments Tint _%I.
-Arguments Tplus (_ _)%term.
-Arguments Tmult (_ _)%term.
-Arguments Tminus (_ _)%term.
-Arguments Topp _%term.
-
-Infix "+" := Tplus : romega_scope.
-Infix "*" := Tmult : romega_scope.
-Infix "-" := Tminus : romega_scope.
-Notation "- x" := (Topp x) : romega_scope.
-Notation "[ x ]" := (Tvar x) (at level 0) : romega_scope.
-
-(* ** Definition of reified goals
-
- Very restricted definition of handled predicates that should be extended
- to cover a wider set of operations.
- Taking care of negations and disequations require solving more than a
- goal in parallel. This is a major improvement over previous versions. *)
-
-Inductive proposition : Set :=
- (** First, basic equations, disequations, inequations *)
- | EqTerm : term -> term -> proposition
- | NeqTerm : term -> term -> proposition
- | LeqTerm : term -> term -> proposition
- | GeqTerm : term -> term -> proposition
- | GtTerm : term -> term -> proposition
- | LtTerm : term -> term -> proposition
- (** Then, the supported logical connectors *)
- | TrueTerm : proposition
- | FalseTerm : proposition
- | Tnot : proposition -> proposition
- | Tor : proposition -> proposition -> proposition
- | Tand : proposition -> proposition -> proposition
- | Timp : proposition -> proposition -> proposition
- (** Everything else is left as a propositional atom (and ignored). *)
- | Tprop : nat -> proposition.
-
-(** Definition of goals as a list of hypothesis *)
-Notation hyps := (list proposition).
-
-(** Definition of lists of subgoals (set of open goals) *)
-Notation lhyps := (list hyps).
-
-(** A single goal packed in a subgoal list *)
-Notation singleton := (fun a : hyps => a :: nil).
-
-(** An absurd goal *)
-Definition absurd := FalseTerm :: nil.
-
-(** ** Decidable equality on terms *)
-
-Fixpoint eq_term (t1 t2 : term) {struct t2} : bool :=
- match t1, t2 with
- | Tint i1, Tint i2 => i1 =? i2
- | (t11 + t12), (t21 + t22) => eq_term t11 t21 && eq_term t12 t22
- | (t11 * t12), (t21 * t22) => eq_term t11 t21 && eq_term t12 t22
- | (t11 - t12), (t21 - t22) => eq_term t11 t21 && eq_term t12 t22
- | (- t1), (- t2) => eq_term t1 t2
- | [v1], [v2] => N.eqb v1 v2
- | _, _ => false
- end%term.
-
-Infix "=?" := eq_term : romega_scope.
-
-Theorem eq_term_iff (t t' : term) :
- (t =? t')%term = true <-> t = t'.
-Proof.
- revert t'. induction t; destruct t'; simpl in *;
- rewrite ?andb_true_iff, ?beq_iff, ?N.eqb_eq, ?IHt, ?IHt1, ?IHt2;
- intuition congruence.
-Qed.
-
-Theorem eq_term_reflect (t t' : term) : reflect (t=t') (t =? t')%term.
-Proof.
- apply iff_reflect. symmetry. apply eq_term_iff.
-Qed.
-
-(** ** Interpretations of terms (as integers). *)
-
-Fixpoint Nnth {A} (n:N)(l:list A)(default:A) :=
- match n, l with
- | _, nil => default
- | 0%N, x::_ => x
- | _, _::l => Nnth (N.pred n) l default
- end.
-
-Fixpoint interp_term (env : list int) (t : term) : int :=
- match t with
- | Tint x => x
- | (t1 + t2)%term => interp_term env t1 + interp_term env t2
- | (t1 * t2)%term => interp_term env t1 * interp_term env t2
- | (t1 - t2)%term => interp_term env t1 - interp_term env t2
- | (- t)%term => - interp_term env t
- | [n]%term => Nnth n env 0
- end.
-
-(** ** Interpretation of predicats (as Coq propositions) *)
-
-Fixpoint interp_prop (envp : list Prop) (env : list int)
- (p : proposition) : Prop :=
- match p with
- | EqTerm t1 t2 => interp_term env t1 = interp_term env t2
- | NeqTerm t1 t2 => (interp_term env t1) <> (interp_term env t2)
- | LeqTerm t1 t2 => interp_term env t1 <= interp_term env t2
- | GeqTerm t1 t2 => interp_term env t1 >= interp_term env t2
- | GtTerm t1 t2 => interp_term env t1 > interp_term env t2
- | LtTerm t1 t2 => interp_term env t1 < interp_term env t2
- | TrueTerm => True
- | FalseTerm => False
- | Tnot p' => ~ interp_prop envp env p'
- | Tor p1 p2 => interp_prop envp env p1 \/ interp_prop envp env p2
- | Tand p1 p2 => interp_prop envp env p1 /\ interp_prop envp env p2
- | Timp p1 p2 => interp_prop envp env p1 -> interp_prop envp env p2
- | Tprop n => nth n envp True
- end.
-
-(** ** Intepretation of hypothesis lists (as Coq conjunctions) *)
-
-Fixpoint interp_hyps (envp : list Prop) (env : list int) (l : hyps)
- : Prop :=
- match l with
- | nil => True
- | p' :: l' => interp_prop envp env p' /\ interp_hyps envp env l'
- end.
-
-(** ** Interpretation of conclusion + hypotheses
-
- Here we use Coq implications : it's less easy to manipulate,
- but handy to relate to the Coq original goal (cf. the use of
- [generalize], and lighter (no repetition of types in intermediate
- conjunctions). *)
-
-Fixpoint interp_goal_concl (c : proposition) (envp : list Prop)
- (env : list int) (l : hyps) : Prop :=
- match l with
- | nil => interp_prop envp env c
- | p' :: l' =>
- interp_prop envp env p' -> interp_goal_concl c envp env l'
- end.
-
-Notation interp_goal := (interp_goal_concl FalseTerm).
-
-(** Equivalence between these two interpretations. *)
-
-Theorem goal_to_hyps :
- forall (envp : list Prop) (env : list int) (l : hyps),
- (interp_hyps envp env l -> False) -> interp_goal envp env l.
-Proof.
- induction l; simpl; auto.
-Qed.
-
-Theorem hyps_to_goal :
- forall (envp : list Prop) (env : list int) (l : hyps),
- interp_goal envp env l -> interp_hyps envp env l -> False.
-Proof.
- induction l; simpl; auto.
- intros H (H1,H2). auto.
-Qed.
-
-(** ** Interpretations of list of goals
-
- Here again, two flavours... *)
-
-Fixpoint interp_list_hyps (envp : list Prop) (env : list int)
- (l : lhyps) : Prop :=
- match l with
- | nil => False
- | h :: l' => interp_hyps envp env h \/ interp_list_hyps envp env l'
- end.
-
-Fixpoint interp_list_goal (envp : list Prop) (env : list int)
- (l : lhyps) : Prop :=
- match l with
- | nil => True
- | h :: l' => interp_goal envp env h /\ interp_list_goal envp env l'
- end.
-
-(** Equivalence between the two flavours. *)
-
-Theorem list_goal_to_hyps :
- forall (envp : list Prop) (env : list int) (l : lhyps),
- (interp_list_hyps envp env l -> False) -> interp_list_goal envp env l.
-Proof.
- induction l; simpl; intuition. now apply goal_to_hyps.
-Qed.
-
-Theorem list_hyps_to_goal :
- forall (envp : list Prop) (env : list int) (l : lhyps),
- interp_list_goal envp env l -> interp_list_hyps envp env l -> False.
-Proof.
- induction l; simpl; intuition. eapply hyps_to_goal; eauto.
-Qed.
-
-(** ** Stabiliy and validity of operations *)
-
-(** An operation on terms is stable if the interpretation is unchanged. *)
-
-Definition term_stable (f : term -> term) :=
- forall (e : list int) (t : term), interp_term e t = interp_term e (f t).
-
-(** An operation on one hypothesis is valid if this hypothesis implies
- the result of this operation. *)
-
-Definition valid1 (f : proposition -> proposition) :=
- forall (ep : list Prop) (e : list int) (p1 : proposition),
- interp_prop ep e p1 -> interp_prop ep e (f p1).
-
-Definition valid2 (f : proposition -> proposition -> proposition) :=
- forall (ep : list Prop) (e : list int) (p1 p2 : proposition),
- interp_prop ep e p1 ->
- interp_prop ep e p2 -> interp_prop ep e (f p1 p2).
-
-(** Same for lists of hypotheses, and for list of goals *)
-
-Definition valid_hyps (f : hyps -> hyps) :=
- forall (ep : list Prop) (e : list int) (lp : hyps),
- interp_hyps ep e lp -> interp_hyps ep e (f lp).
-
-Definition valid_list_hyps (f : hyps -> lhyps) :=
- forall (ep : list Prop) (e : list int) (lp : hyps),
- interp_hyps ep e lp -> interp_list_hyps ep e (f lp).
-
-Definition valid_list_goal (f : hyps -> lhyps) :=
- forall (ep : list Prop) (e : list int) (lp : hyps),
- interp_list_goal ep e (f lp) -> interp_goal ep e lp.
-
-(** Some results about these validities. *)
-
-Theorem valid_goal :
- forall (ep : list Prop) (env : list int) (l : hyps) (a : hyps -> hyps),
- valid_hyps a -> interp_goal ep env (a l) -> interp_goal ep env l.
-Proof.
- intros; simpl; apply goal_to_hyps; intro H1;
- apply (hyps_to_goal ep env (a l) H0); apply H; assumption.
-Qed.
-
-Theorem goal_valid :
- forall f : hyps -> lhyps, valid_list_hyps f -> valid_list_goal f.
-Proof.
- unfold valid_list_goal; intros f H ep e lp H1; apply goal_to_hyps;
- intro H2; apply list_hyps_to_goal with (1 := H1);
- apply (H ep e lp); assumption.
-Qed.
-
-Theorem append_valid :
- forall (ep : list Prop) (e : list int) (l1 l2 : lhyps),
- interp_list_hyps ep e l1 \/ interp_list_hyps ep e l2 ->
- interp_list_hyps ep e (l1 ++ l2).
-Proof.
- induction l1; simpl in *.
- - now intros l2 [H| H].
- - intros l2 [[H| H]| H].
- + auto.
- + right; apply IHl1; now left.
- + right; apply IHl1; now right.
-Qed.
-
-(** ** Valid operations on hypotheses *)
-
-(** Extract an hypothesis from the list *)
-
-Definition nth_hyps (n : nat) (l : hyps) := nth n l TrueTerm.
-
-Theorem nth_valid :
- forall (ep : list Prop) (e : list int) (i : nat) (l : hyps),
- interp_hyps ep e l -> interp_prop ep e (nth_hyps i l).
-Proof.
- unfold nth_hyps. induction i; destruct l; simpl in *; try easy.
- intros (H1,H2). now apply IHi.
-Qed.
-
-(** Apply a valid operation on two hypotheses from the list, and
- store the result in the list. *)
-
-Definition apply_oper_2 (i j : nat)
- (f : proposition -> proposition -> proposition) (l : hyps) :=
- f (nth_hyps i l) (nth_hyps j l) :: l.
-
-Theorem apply_oper_2_valid :
- forall (i j : nat) (f : proposition -> proposition -> proposition),
- valid2 f -> valid_hyps (apply_oper_2 i j f).
-Proof.
- intros i j f Hf; unfold apply_oper_2, valid_hyps; simpl;
- intros lp Hlp; split.
- - apply Hf; apply nth_valid; assumption.
- - assumption.
-Qed.
-
-(** In-place modification of an hypothesis by application of
- a valid operation. *)
-
-Fixpoint apply_oper_1 (i : nat) (f : proposition -> proposition)
- (l : hyps) {struct i} : hyps :=
- match l with
- | nil => nil
- | p :: l' =>
- match i with
- | O => f p :: l'
- | S j => p :: apply_oper_1 j f l'
- end
- end.
-
-Theorem apply_oper_1_valid :
- forall (i : nat) (f : proposition -> proposition),
- valid1 f -> valid_hyps (apply_oper_1 i f).
-Proof.
- unfold valid_hyps.
- induction i; intros f Hf ep e [ | p lp]; simpl; intuition.
-Qed.
-
-(** ** A tactic for proving stability *)
-
-Ltac loop t :=
- match t with
- (* Global *)
- | (?X1 = ?X2) => loop X1 || loop X2
- | (_ -> ?X1) => loop X1
- (* Interpretations *)
- | (interp_hyps _ _ ?X1) => loop X1
- | (interp_list_hyps _ _ ?X1) => loop X1
- | (interp_prop _ _ ?X1) => loop X1
- | (interp_term _ ?X1) => loop X1
- (* Propositions *)
- | (EqTerm ?X1 ?X2) => loop X1 || loop X2
- | (LeqTerm ?X1 ?X2) => loop X1 || loop X2
- (* Terms *)
- | (?X1 + ?X2)%term => loop X1 || loop X2
- | (?X1 - ?X2)%term => loop X1 || loop X2
- | (?X1 * ?X2)%term => loop X1 || loop X2
- | (- ?X1)%term => loop X1
- | (Tint ?X1) => loop X1
- (* Eliminations *)
- | (if ?X1 =? ?X2 then _ else _) =>
- let H := fresh "H" in
- case (beq_reflect X1 X2); intro H;
- try (rewrite H in *; clear H); simpl; auto; Simplify
- | (if ?X1 <? ?X2 then _ else _) =>
- case (blt_reflect X1 X2); intro; simpl; auto; Simplify
- | (if (?X1 =? ?X2)%term then _ else _) =>
- let H := fresh "H" in
- case (eq_term_reflect X1 X2); intro H;
- try (rewrite H in *; clear H); simpl; auto; Simplify
- | (if _ && _ then _ else _) => rewrite andb_if; Simplify
- | (if negb _ then _ else _) => rewrite negb_if; Simplify
- | match N.compare ?X1 ?X2 with _ => _ end =>
- destruct (N.compare_spec X1 X2); Simplify
- | match ?X1 with _ => _ end => destruct X1; auto; Simplify
- | _ => fail
- end
-
-with Simplify := match goal with
- | |- ?X1 => try loop X1
- | _ => idtac
- end.
-
-(** ** Operations on equation bodies *)
-
-(** The operations below handle in priority _normalized_ terms, i.e.
- terms of the form:
- [([v1]*Tint k1 + ([v2]*Tint k2 + (... + Tint cst)))]
- with [v1>v2>...] and all [ki<>0].
- See [normalize] below for a way to put terms in this form.
-
- These operations also produce a correct (but suboptimal)
- result in case of non-normalized input terms, but this situation
- should normally not happen when running [romega].
-
- /!\ Do not modify this section (especially [fusion] and [normalize])
- without tweaking the corresponding functions in [refl_omega.ml].
-*)
-
-(** Multiplication and sum by two constants. Invariant: [k1<>0]. *)
-
-Fixpoint scalar_mult_add (t : term) (k1 k2 : int) : term :=
- match t with
- | v1 * Tint x1 + l1 =>
- v1 * Tint (x1 * k1) + scalar_mult_add l1 k1 k2
- | Tint x => Tint (k1 * x + k2)
- | _ => t * Tint k1 + Tint k2 (* shouldn't happen *)
- end%term.
-
-Theorem scalar_mult_add_stable e t k1 k2 :
- interp_term e (scalar_mult_add t k1 k2) =
- interp_term e (t * Tint k1 + Tint k2).
-Proof.
- induction t; simpl; Simplify; simpl; auto. f_equal. apply mult_comm.
- rewrite IHt2. simpl. apply OMEGA11.
-Qed.
-
-(** Multiplication by a (non-nul) constant. *)
-
-Definition scalar_mult (t : term) (k : int) := scalar_mult_add t k 0.
-
-Theorem scalar_mult_stable e t k :
- interp_term e (scalar_mult t k) =
- interp_term e (t * Tint k).
-Proof.
- unfold scalar_mult. rewrite scalar_mult_add_stable. simpl.
- apply plus_0_r.
-Qed.
-
-(** Adding a constant
-
- Instead of using [scalar_norm_add t 1 k], the following
- definition spares some computations.
- *)
-
-Fixpoint scalar_add (t : term) (k : int) : term :=
- match t with
- | m + l => m + scalar_add l k
- | Tint x => Tint (x + k)
- | _ => t + Tint k
- end%term.
-
-Theorem scalar_add_stable e t k :
- interp_term e (scalar_add t k) = interp_term e (t + Tint k).
-Proof.
- induction t; simpl; Simplify; simpl; auto.
- rewrite IHt2. simpl. apply plus_assoc.
-Qed.
-
-(** Division by a constant
-
- All the non-constant coefficients should be exactly dividable *)
-
-Fixpoint scalar_div (t : term) (k : int) : option (term * int) :=
- match t with
- | v * Tint x + l =>
- let (q,r) := diveucl x k in
- if (r =? 0)%I then
- match scalar_div l k with
- | None => None
- | Some (u,c) => Some (v * Tint q + u, c)
- end
- else None
- | Tint x =>
- let (q,r) := diveucl x k in
- Some (Tint q, r)
- | _ => None
- end%term.
-
-Lemma scalar_div_stable e t k u c : k<>0 ->
- scalar_div t k = Some (u,c) ->
- interp_term e (u * Tint k + Tint c) = interp_term e t.
-Proof.
- revert u c.
- induction t; simpl; Simplify; try easy.
- - intros u c Hk. assert (H := diveucl_spec t0 k Hk).
- simpl in H.
- destruct diveucl as (q,r). simpl in H. rewrite H.
- injection 1 as <- <-. simpl. f_equal. apply mult_comm.
- - intros u c Hk.
- destruct t1; simpl; Simplify; try easy.
- destruct t1_2; simpl; Simplify; try easy.
- assert (H := diveucl_spec t0 k Hk).
- simpl in H.
- destruct diveucl as (q,r). simpl in H. rewrite H.
- case beq_reflect; [intros -> | easy].
- destruct (scalar_div t2 k) as [(u',c')|] eqn:E; [|easy].
- injection 1 as <- ->. simpl.
- rewrite <- (IHt2 u' c Hk); simpl; auto.
- rewrite plus_0_r , (mult_comm k q). symmetry. apply OMEGA11.
-Qed.
-
-
-(** Fusion of two equations.
-
- From two normalized equations, this fusion will produce
- a normalized output corresponding to the coefficiented sum.
- Invariant: [k1<>0] and [k2<>0].
-*)
-
-Fixpoint fusion (t1 t2 : term) (k1 k2 : int) : term :=
- match t1 with
- | [v1] * Tint x1 + l1 =>
- (fix fusion_t1 t2 : term :=
- match t2 with
- | [v2] * Tint x2 + l2 =>
- match N.compare v1 v2 with
- | Eq =>
- let k := (k1 * x1 + k2 * x2)%I in
- if (k =? 0)%I then fusion l1 l2 k1 k2
- else [v1] * Tint k + fusion l1 l2 k1 k2
- | Lt => [v2] * Tint (k2 * x2) + fusion_t1 l2
- | Gt => [v1] * Tint (k1 * x1) + fusion l1 t2 k1 k2
- end
- | Tint x2 => [v1] * Tint (k1 * x1) + fusion l1 t2 k1 k2
- | _ => t1 * Tint k1 + t2 * Tint k2 (* shouldn't happen *)
- end) t2
- | Tint x1 => scalar_mult_add t2 k2 (k1 * x1)
- | _ => t1 * Tint k1 + t2 * Tint k2 (* shouldn't happen *)
- end%term.
-
-Theorem fusion_stable e t1 t2 k1 k2 :
- interp_term e (fusion t1 t2 k1 k2) =
- interp_term e (t1 * Tint k1 + t2 * Tint k2).
-Proof.
- revert t2; induction t1; simpl; Simplify; simpl; auto.
- - intros; rewrite scalar_mult_add_stable. simpl.
- rewrite plus_comm. f_equal. apply mult_comm.
- - intros. Simplify. induction t2; simpl; Simplify; simpl; auto.
- + rewrite IHt1_2. simpl. rewrite (mult_comm k1); apply OMEGA11.
- + rewrite IHt1_2. simpl. subst n0.
- rewrite (mult_comm k1), (mult_comm k2) in H0.
- rewrite <- OMEGA10, H0. now autorewrite with int.
- + rewrite IHt1_2. simpl. subst n0.
- rewrite (mult_comm k1), (mult_comm k2); apply OMEGA10.
- + rewrite IHt2_2. simpl. rewrite (mult_comm k2); apply OMEGA12.
- + rewrite IHt1_2. simpl. rewrite (mult_comm k1); apply OMEGA11.
-Qed.
-
-(** Term normalization.
-
- Precondition: all [Tmult] should be on at least one [Tint].
- Postcondition: a normalized equivalent term (see below).
-*)
-
-Fixpoint normalize t :=
- match t with
- | Tint n => Tint n
- | [n]%term => ([n] * Tint 1 + Tint 0)%term
- | (t + t')%term => fusion (normalize t) (normalize t') 1 1
- | (- t)%term => scalar_mult (normalize t) (-(1))
- | (t - t')%term => fusion (normalize t) (normalize t') 1 (-(1))
- | (Tint k * t)%term | (t * Tint k)%term =>
- if k =? 0 then Tint 0 else scalar_mult (normalize t) k
- | (t1 * t2)%term => (t1 * t2)%term (* shouldn't happen *)
- end.
-
-Theorem normalize_stable : term_stable normalize.
-Proof.
- intros e t.
- induction t; simpl; Simplify; simpl;
- rewrite ?scalar_mult_stable; simpl in *; rewrite <- ?IHt1;
- rewrite ?fusion_stable; simpl; autorewrite with int; auto.
- - now f_equal.
- - rewrite mult_comm. now f_equal.
- - rewrite <- opp_eq_mult_neg_1, <-minus_def. now f_equal.
- - rewrite <- opp_eq_mult_neg_1. now f_equal.
-Qed.
-
-(** ** Normalization of a proposition.
-
- The only basic facts left after normalization are
- [0 = ...] or [0 <> ...] or [0 <= ...].
- When a fact is in negative position, we factorize a [Tnot]
- out of it, and normalize the reversed fact inside.
-
- /!\ Here again, do not change this code without corresponding
- modifications in [refl_omega.ml].
-*)
-
-Fixpoint normalize_prop (negated:bool)(p:proposition) :=
- match p with
- | EqTerm t1 t2 =>
- if negated then Tnot (NeqTerm (Tint 0) (normalize (t1-t2)))
- else EqTerm (Tint 0) (normalize (t1-t2))
- | NeqTerm t1 t2 =>
- if negated then Tnot (EqTerm (Tint 0) (normalize (t1-t2)))
- else NeqTerm (Tint 0) (normalize (t1-t2))
- | LeqTerm t1 t2 =>
- if negated then Tnot (LeqTerm (Tint 0) (normalize (t1-t2+Tint (-(1)))))
- else LeqTerm (Tint 0) (normalize (t2-t1))
- | GeqTerm t1 t2 =>
- if negated then Tnot (LeqTerm (Tint 0) (normalize (t2-t1+Tint (-(1)))))
- else LeqTerm (Tint 0) (normalize (t1-t2))
- | LtTerm t1 t2 =>
- if negated then Tnot (LeqTerm (Tint 0) (normalize (t1-t2)))
- else LeqTerm (Tint 0) (normalize (t2-t1+Tint (-(1))))
- | GtTerm t1 t2 =>
- if negated then Tnot (LeqTerm (Tint 0) (normalize (t2-t1)))
- else LeqTerm (Tint 0) (normalize (t1-t2+Tint (-(1))))
- | Tnot p => Tnot (normalize_prop (negb negated) p)
- | Tor p p' => Tor (normalize_prop negated p) (normalize_prop negated p')
- | Tand p p' => Tand (normalize_prop negated p) (normalize_prop negated p')
- | Timp p p' => Timp (normalize_prop (negb negated) p)
- (normalize_prop negated p')
- | Tprop _ | TrueTerm | FalseTerm => p
- end.
-
-Definition normalize_hyps := List.map (normalize_prop false).
-
-Local Ltac simp := cbn -[normalize].
-
-Theorem normalize_prop_valid b e ep p :
- interp_prop e ep (normalize_prop b p) <-> interp_prop e ep p.
-Proof.
- revert b.
- induction p; intros; simp; try tauto.
- - destruct b; simp;
- rewrite <- ?normalize_stable; simpl; rewrite ?minus_def.
- + rewrite not_eq. apply egal_left.
- + apply egal_left.
- - destruct b; simp;
- rewrite <- ?normalize_stable; simpl; rewrite ?minus_def;
- apply not_iff_compat, egal_left.
- - destruct b; simp;
- rewrite <- ? normalize_stable; simpl; rewrite ?minus_def.
- + symmetry. rewrite le_lt_iff. apply not_iff_compat, lt_left.
- + now rewrite <- le_left.
- - destruct b; simp;
- rewrite <- ? normalize_stable; simpl; rewrite ?minus_def.
- + symmetry. rewrite ge_le_iff, le_lt_iff.
- apply not_iff_compat, lt_left.
- + rewrite ge_le_iff. now rewrite <- le_left.
- - destruct b; simp;
- rewrite <- ? normalize_stable; simpl; rewrite ?minus_def.
- + rewrite gt_lt_iff, lt_le_iff. apply not_iff_compat.
- now rewrite <- le_left.
- + symmetry. rewrite gt_lt_iff. apply lt_left.
- - destruct b; simp;
- rewrite <- ? normalize_stable; simpl; rewrite ?minus_def.
- + rewrite lt_le_iff. apply not_iff_compat.
- now rewrite <- le_left.
- + symmetry. apply lt_left.
- - now rewrite IHp.
- - now rewrite IHp1, IHp2.
- - now rewrite IHp1, IHp2.
- - now rewrite IHp1, IHp2.
-Qed.
-
-Theorem normalize_hyps_valid : valid_hyps normalize_hyps.
-Proof.
- intros e ep l. induction l; simpl; intuition.
- now rewrite normalize_prop_valid.
-Qed.
-
-Theorem normalize_hyps_goal (ep : list Prop) (env : list int) (l : hyps) :
- interp_goal ep env (normalize_hyps l) -> interp_goal ep env l.
-Proof.
- intros; apply valid_goal with (2 := H); apply normalize_hyps_valid.
-Qed.
-
-(** ** A simple decidability checker
-
- For us, everything is considered decidable except
- propositional atoms [Tprop _]. *)
-
-Fixpoint decidability (p : proposition) : bool :=
- match p with
- | Tnot t => decidability t
- | Tand t1 t2 => decidability t1 && decidability t2
- | Timp t1 t2 => decidability t1 && decidability t2
- | Tor t1 t2 => decidability t1 && decidability t2
- | Tprop _ => false
- | _ => true
- end.
-
-Theorem decidable_correct :
- forall (ep : list Prop) (e : list int) (p : proposition),
- decidability p = true -> decidable (interp_prop ep e p).
-Proof.
- induction p; simpl; intros Hp; try destruct (andb_prop _ _ Hp).
- - apply dec_eq.
- - apply dec_ne.
- - apply dec_le.
- - apply dec_ge.
- - apply dec_gt.
- - apply dec_lt.
- - left; auto.
- - right; unfold not; auto.
- - apply dec_not; auto.
- - apply dec_or; auto.
- - apply dec_and; auto.
- - apply dec_imp; auto.
- - discriminate.
-Qed.
-
-(** ** Omega steps
-
- The following inductive type describes steps as they can be
- found in the trace coming from the decision procedure Omega.
- We consider here only normalized equations [0=...], disequations
- [0<>...] or inequations [0<=...].
-
- First, the final steps leading to a contradiction:
- - [O_BAD_CONSTANT i] : hypothesis i has a constant body
- and this constant is not compatible with the kind of i.
- - [O_NOT_EXACT_DIVIDE i k] :
- equation i can be factorized as some [k*t+c] with [0<c<k].
-
- Now, the intermediate steps leading to a new hypothesis:
- - [O_DIVIDE i k cont] :
- the body of hypothesis i could be factorized as [k*t+c]
- with either [k<>0] and [c=0] for a (dis)equation, or
- [0<k] and [c<k] for an inequation. We change in-place the
- body of i for [t].
- - [O_SUM k1 i1 k2 i2 cont] : creates a new hypothesis whose
- kind depends on the kind of hypotheses [i1] and [i2], and
- whose body is [k1*body(i1) + k2*body(i2)]. Depending of the
- situation, [k1] or [k2] might have to be positive or non-nul.
- - [O_MERGE_EQ i j cont] :
- inequations i and j have opposite bodies, we add an equation
- with one these bodies.
- - [O_SPLIT_INEQ i cont1 cont2] :
- disequation i is split into a disjonction of inequations.
-*)
-
-Definition idx := nat. (** Index of an hypothesis in the list *)
-
-Inductive t_omega : Set :=
- | O_BAD_CONSTANT : idx -> t_omega
- | O_NOT_EXACT_DIVIDE : idx -> int -> t_omega
-
- | O_DIVIDE : idx -> int -> t_omega -> t_omega
- | O_SUM : int -> idx -> int -> idx -> t_omega -> t_omega
- | O_MERGE_EQ : idx -> idx -> t_omega -> t_omega
- | O_SPLIT_INEQ : idx -> t_omega -> t_omega -> t_omega.
-
-(** ** Actual resolution steps of an omega normalized goal *)
-
-(** First, the final steps, leading to a contradiction *)
-
-(** [O_BAD_CONSTANT] *)
-
-Definition bad_constant (i : nat) (h : hyps) :=
- match nth_hyps i h with
- | EqTerm (Tint Nul) (Tint n) => if n =? Nul then h else absurd
- | NeqTerm (Tint Nul) (Tint n) => if n =? Nul then absurd else h
- | LeqTerm (Tint Nul) (Tint n) => if n <? Nul then absurd else h
- | _ => h
- end.
-
-Theorem bad_constant_valid i : valid_hyps (bad_constant i).
-Proof.
- unfold valid_hyps, bad_constant; intros ep e lp H.
- generalize (nth_valid ep e i lp H); Simplify.
- rewrite le_lt_iff. intuition.
-Qed.
-
-(** [O_NOT_EXACT_DIVIDE] *)
-
-Definition not_exact_divide (i : nat) (k : int) (l : hyps) :=
- match nth_hyps i l with
- | EqTerm (Tint Nul) b =>
- match scalar_div b k with
- | Some (body,c) =>
- if (Nul =? 0) && (0 <? c) && (c <? k) then absurd
- else l
- | None => l
- end
- | _ => l
- end.
-
-Theorem not_exact_divide_valid i k :
- valid_hyps (not_exact_divide i k).
-Proof.
- unfold valid_hyps, not_exact_divide; intros.
- generalize (nth_valid ep e i lp).
- destruct (nth_hyps i lp); simpl; auto.
- destruct t0; auto.
- destruct (scalar_div t1 k) as [(body,c)|] eqn:E; auto.
- Simplify.
- assert (k <> 0).
- { intro. apply (lt_not_eq 0 k); eauto using lt_trans. }
- apply (scalar_div_stable e) in E; auto. simpl in E.
- intros H'; rewrite <- H' in E; auto.
- exfalso. revert E. now apply OMEGA4.
-Qed.
-
-(** Now, the steps generating a new equation. *)
-
-(** [O_DIVIDE] *)
-
-Definition divide (k : int) (prop : proposition) :=
- match prop with
- | EqTerm (Tint o) b =>
- match scalar_div b k with
- | Some (body,c) =>
- if (o =? 0) && (c =? 0) && negb (k =? 0)
- then EqTerm (Tint 0) body
- else TrueTerm
- | None => TrueTerm
- end
- | NeqTerm (Tint o) b =>
- match scalar_div b k with
- | Some (body,c) =>
- if (o =? 0) && (c =? 0) && negb (k =? 0)
- then NeqTerm (Tint 0) body
- else TrueTerm
- | None => TrueTerm
- end
- | LeqTerm (Tint o) b =>
- match scalar_div b k with
- | Some (body,c) =>
- if (o =? 0) && (0 <? k) && (c <? k)
- then LeqTerm (Tint 0) body
- else prop
- | None => prop
- end
- | _ => TrueTerm
- end.
-
-Theorem divide_valid k : valid1 (divide k).
-Proof.
- unfold valid1, divide; intros ep e p;
- destruct p; simpl; auto;
- destruct t0; simpl; auto;
- destruct scalar_div as [(body,c)|] eqn:E; simpl; Simplify; auto.
- - apply (scalar_div_stable e) in E; auto. simpl in E.
- intros H'; rewrite <- H' in E. rewrite plus_0_r in E.
- apply mult_integral in E. intuition.
- - apply (scalar_div_stable e) in E; auto. simpl in E.
- intros H' H''. now rewrite <- H'', mult_0_l, plus_0_l in E.
- - assert (k <> 0).
- { intro. apply (lt_not_eq 0 k); eauto using lt_trans. }
- apply (scalar_div_stable e) in E; auto. simpl in E. rewrite <- E.
- intro H'. now apply mult_le_approx with (3 := H').
-Qed.
-
-(** [O_SUM]. Invariant: [k1] and [k2] non-nul. *)
-
-Definition sum (k1 k2 : int) (prop1 prop2 : proposition) :=
- match prop1 with
- | EqTerm (Tint o) b1 =>
- match prop2 with
- | EqTerm (Tint o') b2 =>
- if (o =? 0) && (o' =? 0)
- then EqTerm (Tint 0) (fusion b1 b2 k1 k2)
- else TrueTerm
- | LeqTerm (Tint o') b2 =>
- if (o =? 0) && (o' =? 0) && (0 <? k2)
- then LeqTerm (Tint 0) (fusion b1 b2 k1 k2)
- else TrueTerm
- | NeqTerm (Tint o') b2 =>
- if (o =? 0) && (o' =? 0) && negb (k2 =? 0)
- then NeqTerm (Tint 0) (fusion b1 b2 k1 k2)
- else TrueTerm
- | _ => TrueTerm
- end
- | LeqTerm (Tint o) b1 =>
- if (o =? 0) && (0 <? k1)
- then match prop2 with
- | EqTerm (Tint o') b2 =>
- if o' =? 0 then
- LeqTerm (Tint 0) (fusion b1 b2 k1 k2)
- else TrueTerm
- | LeqTerm (Tint o') b2 =>
- if (o' =? 0) && (0 <? k2)
- then LeqTerm (Tint 0) (fusion b1 b2 k1 k2)
- else TrueTerm
- | _ => TrueTerm
- end
- else TrueTerm
- | NeqTerm (Tint o) b1 =>
- match prop2 with
- | EqTerm (Tint o') b2 =>
- if (o =? 0) && (o' =? 0) && negb (k1 =? 0)
- then NeqTerm (Tint 0) (fusion b1 b2 k1 k2)
- else TrueTerm
- | _ => TrueTerm
- end
- | _ => TrueTerm
- end.
-
-Theorem sum_valid :
- forall (k1 k2 : int), valid2 (sum k1 k2).
-Proof.
- unfold valid2; intros k1 k2 t ep e p1 p2; unfold sum;
- Simplify; simpl; rewrite ?fusion_stable;
- simpl; intros; auto.
- - apply sum1; auto.
- - rewrite plus_comm. apply sum5; auto.
- - apply sum2; auto using lt_le_weak.
- - apply sum5; auto.
- - rewrite plus_comm. apply sum2; auto using lt_le_weak.
- - apply sum3; auto using lt_le_weak.
-Qed.
-
-(** [MERGE_EQ] *)
-
-Definition merge_eq (prop1 prop2 : proposition) :=
- match prop1 with
- | LeqTerm (Tint o) b1 =>
- match prop2 with
- | LeqTerm (Tint o') b2 =>
- if (o =? 0) && (o' =? 0) &&
- (b1 =? scalar_mult b2 (-(1)))%term
- then EqTerm (Tint 0) b1
- else TrueTerm
- | _ => TrueTerm
- end
- | _ => TrueTerm
- end.
-
-Theorem merge_eq_valid : valid2 merge_eq.
-Proof.
- unfold valid2, merge_eq; intros ep e p1 p2; Simplify; simpl; auto.
- rewrite scalar_mult_stable. simpl.
- intros; symmetry ; apply OMEGA8 with (2 := H0).
- - assumption.
- - elim opp_eq_mult_neg_1; trivial.
-Qed.
-
-(** [O_SPLIT_INEQ] (only step to produce two subgoals). *)
-
-Definition split_ineq (i : nat) (f1 f2 : hyps -> lhyps) (l : hyps) :=
- match nth_hyps i l with
- | NeqTerm (Tint o) b1 =>
- if o =? 0 then
- f1 (LeqTerm (Tint 0) (scalar_add b1 (-(1))) :: l) ++
- f2 (LeqTerm (Tint 0) (scalar_mult_add b1 (-(1)) (-(1))) :: l)
- else l :: nil
- | _ => l :: nil
- end.
-
-Theorem split_ineq_valid :
- forall (i : nat) (f1 f2 : hyps -> lhyps),
- valid_list_hyps f1 ->
- valid_list_hyps f2 -> valid_list_hyps (split_ineq i f1 f2).
-Proof.
- unfold valid_list_hyps, split_ineq; intros i f1 f2 H1 H2 ep e lp H;
- generalize (nth_valid _ _ i _ H); case (nth_hyps i lp);
- simpl; auto; intros t1 t2; case t1; simpl;
- auto; intros z; simpl; auto; intro H3.
- Simplify.
- apply append_valid; elim (OMEGA19 (interp_term e t2)).
- - intro H4; left; apply H1; simpl; rewrite scalar_add_stable;
- simpl; auto.
- - intro H4; right; apply H2; simpl; rewrite scalar_mult_add_stable;
- simpl; auto.
- - generalize H3; unfold not; intros E1 E2; apply E1;
- symmetry ; trivial.
-Qed.
-
-(** ** Replaying the resolution trace *)
-
-Fixpoint execute_omega (t : t_omega) (l : hyps) : lhyps :=
- match t with
- | O_BAD_CONSTANT i => singleton (bad_constant i l)
- | O_NOT_EXACT_DIVIDE i k => singleton (not_exact_divide i k l)
- | O_DIVIDE i k cont =>
- execute_omega cont (apply_oper_1 i (divide k) l)
- | O_SUM k1 i1 k2 i2 cont =>
- execute_omega cont (apply_oper_2 i1 i2 (sum k1 k2) l)
- | O_MERGE_EQ i1 i2 cont =>
- execute_omega cont (apply_oper_2 i1 i2 merge_eq l)
- | O_SPLIT_INEQ i cont1 cont2 =>
- split_ineq i (execute_omega cont1) (execute_omega cont2) l
- end.
-
-Theorem omega_valid : forall tr : t_omega, valid_list_hyps (execute_omega tr).
-Proof.
- simple induction tr; unfold valid_list_hyps, valid_hyps; simpl.
- - intros; left; now apply bad_constant_valid.
- - intros; left; now apply not_exact_divide_valid.
- - intros m k t' Ht' ep e lp H; apply Ht';
- apply
- (apply_oper_1_valid m (divide k)
- (divide_valid k) ep e lp H).
- - intros k1 i1 k2 i2 t' Ht' ep e lp H; apply Ht';
- apply
- (apply_oper_2_valid i1 i2 (sum k1 k2) (sum_valid k1 k2) ep e
- lp H).
- - intros i1 i2 t' Ht' ep e lp H; apply Ht';
- apply
- (apply_oper_2_valid i1 i2 merge_eq merge_eq_valid ep e
- lp H).
- - intros i k1 H1 k2 H2 ep e lp H;
- apply
- (split_ineq_valid i (execute_omega k1) (execute_omega k2) H1 H2 ep e
- lp H).
-Qed.
-
-
-(** ** Rules for decomposing the hypothesis
-
- This type allows navigation in the logical constructors that
- form the predicats of the hypothesis in order to decompose them.
- This allows in particular to extract one hypothesis from a conjunction.
- NB: negations are now silently traversed. *)
-
-Inductive direction : Set :=
- | D_left : direction
- | D_right : direction.
-
-(** This type allows extracting useful components from hypothesis, either
- hypothesis generated by splitting a disjonction, or equations.
- The last constructor indicates how to solve the obtained system
- via the use of the trace type of Omega [t_omega] *)
-
-Inductive e_step : Set :=
- | E_SPLIT : nat -> list direction -> e_step -> e_step -> e_step
- | E_EXTRACT : nat -> list direction -> e_step -> e_step
- | E_SOLVE : t_omega -> e_step.
-
-(** Selection of a basic fact inside an hypothesis. *)
-
-Fixpoint extract_hyp_pos (s : list direction) (p : proposition) :
- proposition :=
- match p, s with
- | Tand x y, D_left :: l => extract_hyp_pos l x
- | Tand x y, D_right :: l => extract_hyp_pos l y
- | Tnot x, _ => extract_hyp_neg s x
- | _, _ => p
- end
-
- with extract_hyp_neg (s : list direction) (p : proposition) :
- proposition :=
- match p, s with
- | Tor x y, D_left :: l => extract_hyp_neg l x
- | Tor x y, D_right :: l => extract_hyp_neg l y
- | Timp x y, D_left :: l =>
- if decidability x then extract_hyp_pos l x else Tnot p
- | Timp x y, D_right :: l => extract_hyp_neg l y
- | Tnot x, _ => if decidability x then extract_hyp_pos s x else Tnot p
- | _, _ => Tnot p
- end.
-
-Theorem extract_valid :
- forall s : list direction, valid1 (extract_hyp_pos s).
-Proof.
- assert (forall p s ep e,
- (interp_prop ep e p ->
- interp_prop ep e (extract_hyp_pos s p)) /\
- (interp_prop ep e (Tnot p) ->
- interp_prop ep e (extract_hyp_neg s p))).
- { induction p; destruct s; simpl; auto; split; try destruct d; try easy;
- intros; (apply IHp || apply IHp1 || apply IHp2 || idtac); simpl; try tauto;
- destruct decidability eqn:D; auto;
- apply (decidable_correct ep e) in D; unfold decidable in D;
- (apply IHp || apply IHp1); tauto. }
- red. intros. now apply H.
-Qed.
-
-(** Attempt to shorten error messages if romega goes rogue...
- NB: [interp_list_goal _ _ BUG = False /\ True]. *)
-Definition BUG : lhyps := nil :: nil.
-
-(** Split and extract in hypotheses *)
-
-Fixpoint decompose_solve (s : e_step) (h : hyps) : lhyps :=
- match s with
- | E_SPLIT i dl s1 s2 =>
- match extract_hyp_pos dl (nth_hyps i h) with
- | Tor x y => decompose_solve s1 (x :: h) ++ decompose_solve s2 (y :: h)
- | Tnot (Tand x y) =>
- if decidability x
- then
- decompose_solve s1 (Tnot x :: h) ++
- decompose_solve s2 (Tnot y :: h)
- else BUG
- | Timp x y =>
- if decidability x then
- decompose_solve s1 (Tnot x :: h) ++ decompose_solve s2 (y :: h)
- else BUG
- | _ => BUG
- end
- | E_EXTRACT i dl s1 =>
- decompose_solve s1 (extract_hyp_pos dl (nth_hyps i h) :: h)
- | E_SOLVE t => execute_omega t h
- end.
-
-Theorem decompose_solve_valid (s : e_step) :
- valid_list_goal (decompose_solve s).
-Proof.
- apply goal_valid. red. induction s; simpl; intros ep e lp H.
- - assert (H' : interp_prop ep e (extract_hyp_pos l (nth_hyps n lp))).
- { now apply extract_valid, nth_valid. }
- destruct extract_hyp_pos; simpl in *; auto.
- + destruct p; simpl; auto.
- destruct decidability eqn:D; [ | simpl; auto].
- apply (decidable_correct ep e) in D.
- apply append_valid. simpl in *. destruct D.
- * right. apply IHs2. simpl; auto.
- * left. apply IHs1. simpl; auto.
- + apply append_valid. destruct H'.
- * left. apply IHs1. simpl; auto.
- * right. apply IHs2. simpl; auto.
- + destruct decidability eqn:D; [ | simpl; auto].
- apply (decidable_correct ep e) in D.
- apply append_valid. destruct D.
- * right. apply IHs2. simpl; auto.
- * left. apply IHs1. simpl; auto.
- - apply IHs; simpl; split; auto.
- now apply extract_valid, nth_valid.
- - now apply omega_valid.
-Qed.
-
-(** Reduction of subgoal list by discarding the contradictory subgoals. *)
-
-Definition valid_lhyps (f : lhyps -> lhyps) :=
- forall (ep : list Prop) (e : list int) (lp : lhyps),
- interp_list_hyps ep e lp -> interp_list_hyps ep e (f lp).
-
-Fixpoint reduce_lhyps (lp : lhyps) : lhyps :=
- match lp with
- | nil => nil
- | (FalseTerm :: nil) :: lp' => reduce_lhyps lp'
- | x :: lp' => BUG
- end.
-
-Theorem reduce_lhyps_valid : valid_lhyps reduce_lhyps.
-Proof.
- unfold valid_lhyps; intros ep e lp; elim lp.
- - simpl; auto.
- - intros a l HR; elim a.
- + simpl; tauto.
- + intros a1 l1; case l1; case a1; simpl; tauto.
-Qed.
-
-Theorem do_reduce_lhyps :
- forall (envp : list Prop) (env : list int) (l : lhyps),
- interp_list_goal envp env (reduce_lhyps l) -> interp_list_goal envp env l.
-Proof.
- intros envp env l H; apply list_goal_to_hyps; intro H1;
- apply list_hyps_to_goal with (1 := H); apply reduce_lhyps_valid;
- assumption.
-Qed.
-
-(** Pushing the conclusion into the hypotheses. *)
-
-Definition concl_to_hyp (p : proposition) :=
- if decidability p then Tnot p else TrueTerm.
-
-Definition do_concl_to_hyp :
- forall (envp : list Prop) (env : list int) (c : proposition) (l : hyps),
- interp_goal envp env (concl_to_hyp c :: l) ->
- interp_goal_concl c envp env l.
-Proof.
- induction l; simpl.
- - unfold concl_to_hyp; simpl.
- destruct decidability eqn:D; [ | simpl; tauto ].
- apply (decidable_correct envp env) in D. unfold decidable in D.
- simpl. tauto.
- - simpl in *; tauto.
-Qed.
-
-(** The omega tactic : all steps together *)
-
-Definition omega_tactic (t1 : e_step) (c : proposition) (l : hyps) :=
- reduce_lhyps (decompose_solve t1 (normalize_hyps (concl_to_hyp c :: l))).
-
-Theorem do_omega :
- forall (t : e_step) (envp : list Prop)
- (env : list int) (c : proposition) (l : hyps),
- interp_list_goal envp env (omega_tactic t c l) ->
- interp_goal_concl c envp env l.
-Proof.
- unfold omega_tactic; intros t ep e c l H.
- apply do_concl_to_hyp.
- apply normalize_hyps_goal.
- apply (decompose_solve_valid t).
- now apply do_reduce_lhyps.
-Qed.
-
-End IntOmega.
-
-(** For now, the above modular construction is instanciated on Z,
- in order to retrieve the initial ROmega. *)
-
-Module ZOmega := IntOmega(Z_as_Int).
diff --git a/plugins/romega/const_omega.ml b/plugins/romega/const_omega.ml
deleted file mode 100644
index 949cba2dbe..0000000000
--- a/plugins/romega/const_omega.ml
+++ /dev/null
@@ -1,332 +0,0 @@
-(*************************************************************************
-
- PROJET RNRT Calife - 2001
- Author: Pierre Crégut - France Télécom R&D
- Licence : LGPL version 2.1
-
- *************************************************************************)
-
-open Names
-
-let module_refl_name = "ReflOmegaCore"
-let module_refl_path = ["Coq"; "romega"; module_refl_name]
-
-type result =
- | Kvar of string
- | Kapp of string * EConstr.t list
- | Kimp of EConstr.t * EConstr.t
- | Kufo
-
-let meaningful_submodule = [ "Z"; "N"; "Pos" ]
-
-let string_of_global r =
- let dp = Nametab.dirpath_of_global r in
- let prefix = match Names.DirPath.repr dp with
- | [] -> ""
- | m::_ ->
- let s = Names.Id.to_string m in
- if Util.String.List.mem s meaningful_submodule then s^"." else ""
- in
- prefix^(Names.Id.to_string (Nametab.basename_of_global r))
-
-let destructurate sigma t =
- let c, args = EConstr.decompose_app sigma t in
- let open Constr in
- match EConstr.kind sigma c, args with
- | Const (sp,_), args ->
- Kapp (string_of_global (Globnames.ConstRef sp), args)
- | Construct (csp,_) , args ->
- Kapp (string_of_global (Globnames.ConstructRef csp), args)
- | Ind (isp,_), args ->
- Kapp (string_of_global (Globnames.IndRef isp), args)
- | Var id, [] -> Kvar(Names.Id.to_string id)
- | Prod (Anonymous,typ,body), [] -> Kimp(typ,body)
- | _ -> Kufo
-
-exception DestConstApp
-
-let dest_const_apply sigma t =
- let open Constr in
- let f,args = EConstr.decompose_app sigma t in
- let ref =
- match EConstr.kind sigma f with
- | Const (sp,_) -> Globnames.ConstRef sp
- | Construct (csp,_) -> Globnames.ConstructRef csp
- | Ind (isp,_) -> Globnames.IndRef isp
- | _ -> raise DestConstApp
- in Nametab.basename_of_global ref, args
-
-let logic_dir = ["Coq";"Logic";"Decidable"]
-
-let coq_modules =
- Coqlib.init_modules @ [logic_dir] @ Coqlib.arith_modules @ Coqlib.zarith_base_modules
- @ [["Coq"; "Lists"; "List"]]
- @ [module_refl_path]
- @ [module_refl_path@["ZOmega"]]
-
-let bin_module = [["Coq";"Numbers";"BinNums"]]
-let z_module = [["Coq";"ZArith";"BinInt"]]
-
-let init_constant x =
- EConstr.of_constr @@
- UnivGen.constr_of_global @@
- Coqlib.gen_reference_in_modules "Omega" Coqlib.init_modules x
-let constant x =
- EConstr.of_constr @@
- UnivGen.constr_of_global @@
- Coqlib.gen_reference_in_modules "Omega" coq_modules x
-let z_constant x =
- EConstr.of_constr @@
- UnivGen.constr_of_global @@
- Coqlib.gen_reference_in_modules "Omega" z_module x
-let bin_constant x =
- EConstr.of_constr @@
- UnivGen.constr_of_global @@
- Coqlib.gen_reference_in_modules "Omega" bin_module x
-
-(* Logic *)
-let coq_refl_equal = lazy(init_constant "eq_refl")
-let coq_and = lazy(init_constant "and")
-let coq_not = lazy(init_constant "not")
-let coq_or = lazy(init_constant "or")
-let coq_True = lazy(init_constant "True")
-let coq_False = lazy(init_constant "False")
-let coq_I = lazy(init_constant "I")
-
-(* ReflOmegaCore/ZOmega *)
-
-let coq_t_int = lazy (constant "Tint")
-let coq_t_plus = lazy (constant "Tplus")
-let coq_t_mult = lazy (constant "Tmult")
-let coq_t_opp = lazy (constant "Topp")
-let coq_t_minus = lazy (constant "Tminus")
-let coq_t_var = lazy (constant "Tvar")
-
-let coq_proposition = lazy (constant "proposition")
-let coq_p_eq = lazy (constant "EqTerm")
-let coq_p_leq = lazy (constant "LeqTerm")
-let coq_p_geq = lazy (constant "GeqTerm")
-let coq_p_lt = lazy (constant "LtTerm")
-let coq_p_gt = lazy (constant "GtTerm")
-let coq_p_neq = lazy (constant "NeqTerm")
-let coq_p_true = lazy (constant "TrueTerm")
-let coq_p_false = lazy (constant "FalseTerm")
-let coq_p_not = lazy (constant "Tnot")
-let coq_p_or = lazy (constant "Tor")
-let coq_p_and = lazy (constant "Tand")
-let coq_p_imp = lazy (constant "Timp")
-let coq_p_prop = lazy (constant "Tprop")
-
-let coq_s_bad_constant = lazy (constant "O_BAD_CONSTANT")
-let coq_s_divide = lazy (constant "O_DIVIDE")
-let coq_s_not_exact_divide = lazy (constant "O_NOT_EXACT_DIVIDE")
-let coq_s_sum = lazy (constant "O_SUM")
-let coq_s_merge_eq = lazy (constant "O_MERGE_EQ")
-let coq_s_split_ineq =lazy (constant "O_SPLIT_INEQ")
-
-(* construction for the [extract_hyp] tactic *)
-let coq_direction = lazy (constant "direction")
-let coq_d_left = lazy (constant "D_left")
-let coq_d_right = lazy (constant "D_right")
-
-let coq_e_split = lazy (constant "E_SPLIT")
-let coq_e_extract = lazy (constant "E_EXTRACT")
-let coq_e_solve = lazy (constant "E_SOLVE")
-
-let coq_interp_sequent = lazy (constant "interp_goal_concl")
-let coq_do_omega = lazy (constant "do_omega")
-
-(* Nat *)
-
-let coq_S = lazy(init_constant "S")
-let coq_O = lazy(init_constant "O")
-
-let rec mk_nat = function
- | 0 -> Lazy.force coq_O
- | n -> EConstr.mkApp (Lazy.force coq_S, [| mk_nat (n-1) |])
-
-(* Lists *)
-
-let mkListConst c =
- let r =
- Coqlib.coq_reference "" ["Init";"Datatypes"] c
- in
- let inst =
- if Global.is_polymorphic r then
- fun u -> EConstr.EInstance.make (Univ.Instance.of_array [|u|])
- else
- fun _ -> EConstr.EInstance.empty
- in
- fun u -> EConstr.mkConstructU (Globnames.destConstructRef r, inst u)
-
-let coq_cons univ typ = EConstr.mkApp (mkListConst "cons" univ, [|typ|])
-let coq_nil univ typ = EConstr.mkApp (mkListConst "nil" univ, [|typ|])
-
-let mk_list univ typ l =
- let rec loop = function
- | [] -> coq_nil univ typ
- | (step :: l) ->
- EConstr.mkApp (coq_cons univ typ, [| step; loop l |]) in
- loop l
-
-let mk_plist =
- let type1lev = UnivGen.new_univ_level () in
- fun l -> mk_list type1lev EConstr.mkProp l
-
-let mk_list = mk_list Univ.Level.set
-
-type parse_term =
- | Tplus of EConstr.t * EConstr.t
- | Tmult of EConstr.t * EConstr.t
- | Tminus of EConstr.t * EConstr.t
- | Topp of EConstr.t
- | Tsucc of EConstr.t
- | Tnum of Bigint.bigint
- | Tother
-
-type parse_rel =
- | Req of EConstr.t * EConstr.t
- | Rne of EConstr.t * EConstr.t
- | Rlt of EConstr.t * EConstr.t
- | Rle of EConstr.t * EConstr.t
- | Rgt of EConstr.t * EConstr.t
- | Rge of EConstr.t * EConstr.t
- | Rtrue
- | Rfalse
- | Rnot of EConstr.t
- | Ror of EConstr.t * EConstr.t
- | Rand of EConstr.t * EConstr.t
- | Rimp of EConstr.t * EConstr.t
- | Riff of EConstr.t * EConstr.t
- | Rother
-
-let parse_logic_rel sigma c = match destructurate sigma c with
- | Kapp("True",[]) -> Rtrue
- | Kapp("False",[]) -> Rfalse
- | Kapp("not",[t]) -> Rnot t
- | Kapp("or",[t1;t2]) -> Ror (t1,t2)
- | Kapp("and",[t1;t2]) -> Rand (t1,t2)
- | Kimp(t1,t2) -> Rimp (t1,t2)
- | Kapp("iff",[t1;t2]) -> Riff (t1,t2)
- | _ -> Rother
-
-(* Binary numbers *)
-
-let coq_Z = lazy (bin_constant "Z")
-let coq_xH = lazy (bin_constant "xH")
-let coq_xO = lazy (bin_constant "xO")
-let coq_xI = lazy (bin_constant "xI")
-let coq_Z0 = lazy (bin_constant "Z0")
-let coq_Zpos = lazy (bin_constant "Zpos")
-let coq_Zneg = lazy (bin_constant "Zneg")
-let coq_N0 = lazy (bin_constant "N0")
-let coq_Npos = lazy (bin_constant "Npos")
-
-let rec mk_positive n =
- if Bigint.equal n Bigint.one then Lazy.force coq_xH
- else
- let (q,r) = Bigint.euclid n Bigint.two in
- EConstr.mkApp
- ((if Bigint.equal r Bigint.zero
- then Lazy.force coq_xO else Lazy.force coq_xI),
- [| mk_positive q |])
-
-let mk_N = function
- | 0 -> Lazy.force coq_N0
- | n -> EConstr.mkApp (Lazy.force coq_Npos,
- [| mk_positive (Bigint.of_int n) |])
-
-module type Int = sig
- val typ : EConstr.t Lazy.t
- val is_int_typ : Proofview.Goal.t -> EConstr.t -> bool
- val plus : EConstr.t Lazy.t
- val mult : EConstr.t Lazy.t
- val opp : EConstr.t Lazy.t
- val minus : EConstr.t Lazy.t
-
- val mk : Bigint.bigint -> EConstr.t
- val parse_term : Evd.evar_map -> EConstr.t -> parse_term
- val parse_rel : Proofview.Goal.t -> EConstr.t -> parse_rel
- (* check whether t is built only with numbers and + * - *)
- val get_scalar : Evd.evar_map -> EConstr.t -> Bigint.bigint option
-end
-
-module Z : Int = struct
-
-let typ = coq_Z
-let plus = lazy (z_constant "Z.add")
-let mult = lazy (z_constant "Z.mul")
-let opp = lazy (z_constant "Z.opp")
-let minus = lazy (z_constant "Z.sub")
-
-let recognize_pos sigma t =
- let rec loop t =
- let f,l = dest_const_apply sigma t in
- match Id.to_string f,l with
- | "xI",[t] -> Bigint.add Bigint.one (Bigint.mult Bigint.two (loop t))
- | "xO",[t] -> Bigint.mult Bigint.two (loop t)
- | "xH",[] -> Bigint.one
- | _ -> raise DestConstApp
- in
- try Some (loop t) with DestConstApp -> None
-
-let recognize_Z sigma t =
- try
- let f,l = dest_const_apply sigma t in
- match Id.to_string f,l with
- | "Zpos",[t] -> recognize_pos sigma t
- | "Zneg",[t] -> Option.map Bigint.neg (recognize_pos sigma t)
- | "Z0",[] -> Some Bigint.zero
- | _ -> None
- with DestConstApp -> None
-
-let mk_Z n =
- if Bigint.equal n Bigint.zero then Lazy.force coq_Z0
- else if Bigint.is_strictly_pos n then
- EConstr.mkApp (Lazy.force coq_Zpos, [| mk_positive n |])
- else
- EConstr.mkApp (Lazy.force coq_Zneg, [| mk_positive (Bigint.neg n) |])
-
-let mk = mk_Z
-
-let parse_term sigma t =
- match destructurate sigma t with
- | Kapp("Z.add",[t1;t2]) -> Tplus (t1,t2)
- | Kapp("Z.sub",[t1;t2]) -> Tminus (t1,t2)
- | Kapp("Z.mul",[t1;t2]) -> Tmult (t1,t2)
- | Kapp("Z.opp",[t]) -> Topp t
- | Kapp("Z.succ",[t]) -> Tsucc t
- | Kapp("Z.pred",[t]) -> Tplus(t, mk_Z (Bigint.neg Bigint.one))
- | Kapp(("Zpos"|"Zneg"|"Z0"),_) ->
- (match recognize_Z sigma t with Some t -> Tnum t | None -> Tother)
- | _ -> Tother
-
-let is_int_typ gl t =
- Tacmach.New.pf_apply Reductionops.is_conv gl t (Lazy.force coq_Z)
-
-let parse_rel gl t =
- let sigma = Proofview.Goal.sigma gl in
- match destructurate sigma t with
- | Kapp("eq",[typ;t1;t2]) when is_int_typ gl typ -> Req (t1,t2)
- | Kapp("Zne",[t1;t2]) -> Rne (t1,t2)
- | Kapp("Z.le",[t1;t2]) -> Rle (t1,t2)
- | Kapp("Z.lt",[t1;t2]) -> Rlt (t1,t2)
- | Kapp("Z.ge",[t1;t2]) -> Rge (t1,t2)
- | Kapp("Z.gt",[t1;t2]) -> Rgt (t1,t2)
- | _ -> parse_logic_rel sigma t
-
-let rec get_scalar sigma t =
- match destructurate sigma t with
- | Kapp("Z.add", [t1;t2]) ->
- Option.lift2 Bigint.add (get_scalar sigma t1) (get_scalar sigma t2)
- | Kapp ("Z.sub",[t1;t2]) ->
- Option.lift2 Bigint.sub (get_scalar sigma t1) (get_scalar sigma t2)
- | Kapp ("Z.mul",[t1;t2]) ->
- Option.lift2 Bigint.mult (get_scalar sigma t1) (get_scalar sigma t2)
- | Kapp("Z.opp", [t]) -> Option.map Bigint.neg (get_scalar sigma t)
- | Kapp("Z.succ", [t]) -> Option.map Bigint.add_1 (get_scalar sigma t)
- | Kapp("Z.pred", [t]) -> Option.map Bigint.sub_1 (get_scalar sigma t)
- | Kapp(("Zpos"|"Zneg"|"Z0"),_) -> recognize_Z sigma t
- | _ -> None
-
-end
diff --git a/plugins/romega/const_omega.mli b/plugins/romega/const_omega.mli
deleted file mode 100644
index 64668df007..0000000000
--- a/plugins/romega/const_omega.mli
+++ /dev/null
@@ -1,124 +0,0 @@
-(*************************************************************************
-
- PROJET RNRT Calife - 2001
- Author: Pierre Crégut - France Télécom R&D
- Licence : LGPL version 2.1
-
- *************************************************************************)
-
-
-(** Coq objects used in romega *)
-
-(* from Logic *)
-val coq_refl_equal : EConstr.t lazy_t
-val coq_and : EConstr.t lazy_t
-val coq_not : EConstr.t lazy_t
-val coq_or : EConstr.t lazy_t
-val coq_True : EConstr.t lazy_t
-val coq_False : EConstr.t lazy_t
-val coq_I : EConstr.t lazy_t
-
-(* from ReflOmegaCore/ZOmega *)
-
-val coq_t_int : EConstr.t lazy_t
-val coq_t_plus : EConstr.t lazy_t
-val coq_t_mult : EConstr.t lazy_t
-val coq_t_opp : EConstr.t lazy_t
-val coq_t_minus : EConstr.t lazy_t
-val coq_t_var : EConstr.t lazy_t
-
-val coq_proposition : EConstr.t lazy_t
-val coq_p_eq : EConstr.t lazy_t
-val coq_p_leq : EConstr.t lazy_t
-val coq_p_geq : EConstr.t lazy_t
-val coq_p_lt : EConstr.t lazy_t
-val coq_p_gt : EConstr.t lazy_t
-val coq_p_neq : EConstr.t lazy_t
-val coq_p_true : EConstr.t lazy_t
-val coq_p_false : EConstr.t lazy_t
-val coq_p_not : EConstr.t lazy_t
-val coq_p_or : EConstr.t lazy_t
-val coq_p_and : EConstr.t lazy_t
-val coq_p_imp : EConstr.t lazy_t
-val coq_p_prop : EConstr.t lazy_t
-
-val coq_s_bad_constant : EConstr.t lazy_t
-val coq_s_divide : EConstr.t lazy_t
-val coq_s_not_exact_divide : EConstr.t lazy_t
-val coq_s_sum : EConstr.t lazy_t
-val coq_s_merge_eq : EConstr.t lazy_t
-val coq_s_split_ineq : EConstr.t lazy_t
-
-val coq_direction : EConstr.t lazy_t
-val coq_d_left : EConstr.t lazy_t
-val coq_d_right : EConstr.t lazy_t
-
-val coq_e_split : EConstr.t lazy_t
-val coq_e_extract : EConstr.t lazy_t
-val coq_e_solve : EConstr.t lazy_t
-
-val coq_interp_sequent : EConstr.t lazy_t
-val coq_do_omega : EConstr.t lazy_t
-
-val mk_nat : int -> EConstr.t
-val mk_N : int -> EConstr.t
-
-(** Precondition: the type of the list is in Set *)
-val mk_list : EConstr.t -> EConstr.t list -> EConstr.t
-val mk_plist : EConstr.types list -> EConstr.types
-
-(** Analyzing a coq term *)
-
-(* The generic result shape of the analysis of a term.
- One-level depth, except when a number is found *)
-type parse_term =
- Tplus of EConstr.t * EConstr.t
- | Tmult of EConstr.t * EConstr.t
- | Tminus of EConstr.t * EConstr.t
- | Topp of EConstr.t
- | Tsucc of EConstr.t
- | Tnum of Bigint.bigint
- | Tother
-
-(* The generic result shape of the analysis of a relation.
- One-level depth. *)
-type parse_rel =
- Req of EConstr.t * EConstr.t
- | Rne of EConstr.t * EConstr.t
- | Rlt of EConstr.t * EConstr.t
- | Rle of EConstr.t * EConstr.t
- | Rgt of EConstr.t * EConstr.t
- | Rge of EConstr.t * EConstr.t
- | Rtrue
- | Rfalse
- | Rnot of EConstr.t
- | Ror of EConstr.t * EConstr.t
- | Rand of EConstr.t * EConstr.t
- | Rimp of EConstr.t * EConstr.t
- | Riff of EConstr.t * EConstr.t
- | Rother
-
-(* A module factorizing what we should now about the number representation *)
-module type Int =
- sig
- (* the coq type of the numbers *)
- val typ : EConstr.t Lazy.t
- (* Is a constr expands to the type of these numbers *)
- val is_int_typ : Proofview.Goal.t -> EConstr.t -> bool
- (* the operations on the numbers *)
- val plus : EConstr.t Lazy.t
- val mult : EConstr.t Lazy.t
- val opp : EConstr.t Lazy.t
- val minus : EConstr.t Lazy.t
- (* building a coq number *)
- val mk : Bigint.bigint -> EConstr.t
- (* parsing a term (one level, except if a number is found) *)
- val parse_term : Evd.evar_map -> EConstr.t -> parse_term
- (* parsing a relation expression, including = < <= >= > *)
- val parse_rel : Proofview.Goal.t -> EConstr.t -> parse_rel
- (* Is a particular term only made of numbers and + * - ? *)
- val get_scalar : Evd.evar_map -> EConstr.t -> Bigint.bigint option
- end
-
-(* Currently, we only use Z numbers *)
-module Z : Int
diff --git a/plugins/romega/g_romega.mlg b/plugins/romega/g_romega.mlg
deleted file mode 100644
index c1ce30027e..0000000000
--- a/plugins/romega/g_romega.mlg
+++ /dev/null
@@ -1,55 +0,0 @@
-(*************************************************************************
-
- PROJET RNRT Calife - 2001
- Author: Pierre Crégut - France Télécom R&D
- Licence : LGPL version 2.1
-
- *************************************************************************)
-
-
-DECLARE PLUGIN "romega_plugin"
-
-{
-
-open Ltac_plugin
-open Names
-open Refl_omega
-open Stdarg
-
-let eval_tactic name =
- let dp = DirPath.make (List.map Id.of_string ["PreOmega"; "omega"; "Coq"]) in
- let kn = KerName.make2 (ModPath.MPfile dp) (Label.make name) in
- let tac = Tacenv.interp_ltac kn in
- Tacinterp.eval_tactic tac
-
-let romega_tactic unsafe l =
- let tacs = List.map
- (function
- | "nat" -> eval_tactic "zify_nat"
- | "positive" -> eval_tactic "zify_positive"
- | "N" -> eval_tactic "zify_N"
- | "Z" -> eval_tactic "zify_op"
- | s -> CErrors.user_err Pp.(str ("No ROmega knowledge base for type "^s)))
- (Util.List.sort_uniquize String.compare l)
- in
- Tacticals.New.tclTHEN
- (Tacticals.New.tclREPEAT (Proofview.tclPROGRESS (Tacticals.New.tclTHENLIST tacs)))
- (Tacticals.New.tclTHEN
- (* because of the contradiction process in (r)omega,
- we'd better leave as little as possible in the conclusion,
- for an easier decidability argument. *)
- (Tactics.intros)
- (total_reflexive_omega_tactic unsafe))
-
-}
-
-TACTIC EXTEND romega
-| [ "romega" ] -> { romega_tactic false [] }
-| [ "unsafe_romega" ] -> { romega_tactic true [] }
-END
-
-TACTIC EXTEND romega'
-| [ "romega" "with" ne_ident_list(l) ] ->
- { romega_tactic false (List.map Names.Id.to_string l) }
-| [ "romega" "with" "*" ] -> { romega_tactic false ["nat";"positive";"N";"Z"] }
-END
diff --git a/plugins/romega/refl_omega.ml b/plugins/romega/refl_omega.ml
deleted file mode 100644
index e603480656..0000000000
--- a/plugins/romega/refl_omega.ml
+++ /dev/null
@@ -1,1071 +0,0 @@
-(*************************************************************************
-
- PROJET RNRT Calife - 2001
- Author: Pierre Crégut - France Télécom R&D
- Licence : LGPL version 2.1
-
- *************************************************************************)
-
-open Pp
-open Util
-open Constr
-open Const_omega
-module OmegaSolver = Omega_plugin.Omega.MakeOmegaSolver (Bigint)
-open OmegaSolver
-
-module Id = Names.Id
-module IntSet = Int.Set
-module IntHtbl = Hashtbl.Make(Int)
-
-(* \section{Useful functions and flags} *)
-(* Especially useful debugging functions *)
-let debug = ref false
-
-let show_goal = Tacticals.New.tclIDTAC
-
-let pp i = print_int i; print_newline (); flush stdout
-
-(* More readable than the prefix notation *)
-let (>>) = Tacticals.New.tclTHEN
-
-(* \section{Types}
- \subsection{How to walk in a term}
- To represent how to get to a proposition. Only choice points are
- kept (branch to choose in a disjunction and identifier of the disjunctive
- connector) *)
-type direction = Left of int | Right of int
-
-(* Step to find a proposition (operators are at most binary). A list is
- a path *)
-type occ_step = O_left | O_right | O_mono
-type occ_path = occ_step list
-
-(* chemin identifiant une proposition sous forme du nom de l'hypothèse et
- d'une liste de pas à partir de la racine de l'hypothèse *)
-type occurrence = {o_hyp : Id.t; o_path : occ_path}
-
-type atom_index = int
-
-(* \subsection{reifiable formulas} *)
-type oformula =
- (* integer *)
- | Oint of Bigint.bigint
- (* recognized binary and unary operations *)
- | Oplus of oformula * oformula
- | Omult of oformula * oformula (* Invariant : one side is [Oint] *)
- | Ominus of oformula * oformula
- | Oopp of oformula
- (* an atom in the environment *)
- | Oatom of atom_index
-
-(* Operators for comparison recognized by Omega *)
-type comparaison = Eq | Leq | Geq | Gt | Lt | Neq
-
-(* Representation of reified predicats (fragment of propositional calculus,
- no quantifier here). *)
-(* Note : in [Pprop p], the non-reified constr [p] should be closed
- (it could contains some [Term.Var] but no [Term.Rel]). So no need to
- lift when breaking or creating arrows. *)
-type oproposition =
- Pequa of EConstr.t * oequation (* constr = copy of the Coq formula *)
- | Ptrue
- | Pfalse
- | Pnot of oproposition
- | Por of int * oproposition * oproposition
- | Pand of int * oproposition * oproposition
- | Pimp of int * oproposition * oproposition
- | Pprop of EConstr.t
-
-(* The equations *)
-and oequation = {
- e_comp: comparaison; (* comparaison *)
- e_left: oformula; (* formule brute gauche *)
- e_right: oformula; (* formule brute droite *)
- e_origin: occurrence; (* l'hypothèse dont vient le terme *)
- e_negated: bool; (* vrai si apparait en position nié
- après normalisation *)
- e_depends: direction list; (* liste des points de disjonction dont
- dépend l'accès à l'équation avec la
- direction (branche) pour y accéder *)
- e_omega: OmegaSolver.afine (* normalized formula *)
- }
-
-(* \subsection{Proof context}
- This environment codes
- \begin{itemize}
- \item the terms and propositions that are given as
- parameters of the reified proof (and are represented as variables in the
- reified goals)
- \item translation functions linking the decision procedure and the Coq proof
- \end{itemize} *)
-
-type environment = {
- (* La liste des termes non reifies constituant l'environnement global *)
- mutable terms : EConstr.t list;
- (* La meme chose pour les propositions *)
- mutable props : EConstr.t list;
- (* Traduction des indices utilisés ici en les indices finaux utilisés par
- * la tactique Omega après dénombrement des variables utiles *)
- real_indices : int IntHtbl.t;
- mutable cnt_connectors : int;
- equations : oequation IntHtbl.t;
- constructors : occurrence IntHtbl.t
-}
-
-(* \subsection{Solution tree}
- Définition d'une solution trouvée par Omega sous la forme d'un identifiant,
- d'un ensemble d'équation dont dépend la solution et d'une trace *)
-
-type solution = {
- s_index : int;
- s_equa_deps : IntSet.t;
- s_trace : OmegaSolver.action list }
-
-(* Arbre de solution résolvant complètement un ensemble de systèmes *)
-type solution_tree =
- Leaf of solution
- (* un noeud interne représente un point de branchement correspondant à
- l'élimination d'un connecteur générant plusieurs buts
- (typ. disjonction). Le premier argument
- est l'identifiant du connecteur *)
- | Tree of int * solution_tree * solution_tree
-
-(* Représentation de l'environnement extrait du but initial sous forme de
- chemins pour extraire des equations ou d'hypothèses *)
-
-type context_content =
- CCHyp of occurrence
- | CCEqua of int
-
-(** Some dedicated equality tests *)
-
-let occ_step_eq s1 s2 = match s1, s2 with
-| O_left, O_left | O_right, O_right | O_mono, O_mono -> true
-| _ -> false
-
-let rec oform_eq f f' = match f,f' with
- | Oint i, Oint i' -> Bigint.equal i i'
- | Oplus (f1,f2), Oplus (f1',f2')
- | Omult (f1,f2), Omult (f1',f2')
- | Ominus (f1,f2), Ominus (f1',f2') -> oform_eq f1 f1' && oform_eq f2 f2'
- | Oopp f, Oopp f' -> oform_eq f f'
- | Oatom a, Oatom a' -> Int.equal a a'
- | _ -> false
-
-let dir_eq d d' = match d, d' with
- | Left i, Left i' | Right i, Right i' -> Int.equal i i'
- | _ -> false
-
-(* \section{Specific utility functions to handle base types} *)
-(* Nom arbitraire de l'hypothèse codant la négation du but final *)
-let id_concl = Id.of_string "__goal__"
-
-(* Initialisation de l'environnement de réification de la tactique *)
-let new_environment () = {
- terms = []; props = []; cnt_connectors = 0;
- real_indices = IntHtbl.create 7;
- equations = IntHtbl.create 7;
- constructors = IntHtbl.create 7;
-}
-
-(* Génération d'un nom d'équation *)
-let new_connector_id env =
- env.cnt_connectors <- succ env.cnt_connectors; env.cnt_connectors
-
-(* Calcul de la branche complémentaire *)
-let barre = function Left x -> Right x | Right x -> Left x
-
-(* Identifiant associé à une branche *)
-let indice = function Left x | Right x -> x
-
-(* Affichage de l'environnement de réification (termes et propositions) *)
-let print_env_reification env =
- let rec loop c i = function
- [] -> str " ===============================\n\n"
- | t :: l ->
- let sigma, env = Pfedit.get_current_context () in
- let s = Printf.sprintf "(%c%02d)" c i in
- spc () ++ str s ++ str " := " ++ Printer.pr_econstr_env env sigma t ++ fnl () ++
- loop c (succ i) l
- in
- let prop_info = str "ENVIRONMENT OF PROPOSITIONS :" ++ fnl () ++ loop 'P' 0 env.props in
- let term_info = str "ENVIRONMENT OF TERMS :" ++ fnl () ++ loop 'V' 0 env.terms in
- Feedback.msg_debug (prop_info ++ fnl () ++ term_info)
-
-(* \subsection{Gestion des environnements de variable pour Omega} *)
-(* generation d'identifiant d'equation pour Omega *)
-
-let new_omega_eq, rst_omega_eq =
- let cpt = ref (-1) in
- (function () -> incr cpt; !cpt),
- (function () -> cpt:=(-1))
-
-(* generation d'identifiant de variable pour Omega *)
-
-let new_omega_var, rst_omega_var, set_omega_maxvar =
- let cpt = ref (-1) in
- (function () -> incr cpt; !cpt),
- (function () -> cpt:=(-1)),
- (function n -> cpt:=n)
-
-(* Affichage des variables d'un système *)
-
-let display_omega_var i = Printf.sprintf "OV%d" i
-
-(* \subsection{Gestion des environnements de variable pour la réflexion}
- Gestion des environnements de traduction entre termes des constructions
- non réifiés et variables des termes reifies. Attention il s'agit de
- l'environnement initial contenant tout. Il faudra le réduire après
- calcul des variables utiles. *)
-
-let add_reified_atom sigma t env =
- try List.index0 (EConstr.eq_constr sigma) t env.terms
- with Not_found ->
- let i = List.length env.terms in
- env.terms <- env.terms @ [t]; i
-
-let get_reified_atom env =
- try List.nth env.terms with Invalid_argument _ -> failwith "get_reified_atom"
-
-(** When the omega resolution has created a variable [v], we re-sync
- the environment with this new variable. To be done in the right order. *)
-
-let set_reified_atom v t env =
- assert (Int.equal v (List.length env.terms));
- env.terms <- env.terms @ [t]
-
-(* \subsection{Gestion de l'environnement de proposition pour Omega} *)
-(* ajout d'une proposition *)
-let add_prop sigma env t =
- try List.index0 (EConstr.eq_constr sigma) t env.props
- with Not_found ->
- let i = List.length env.props in env.props <- env.props @ [t]; i
-
-(* accès a une proposition *)
-let get_prop v env =
- try List.nth v env with Invalid_argument _ -> failwith "get_prop"
-
-(* \subsection{Gestion du nommage des équations} *)
-(* Ajout d'une equation dans l'environnement de reification *)
-let add_equation env e =
- let id = e.e_omega.id in
- if IntHtbl.mem env.equations id then () else IntHtbl.add env.equations id e
-
-(* accès a une equation *)
-let get_equation env id =
- try IntHtbl.find env.equations id
- with Not_found as e ->
- Printf.printf "Omega Equation %d non trouvée\n" id; raise e
-
-(* Affichage des termes réifiés *)
-let rec oprint ch = function
- | Oint n -> Printf.fprintf ch "%s" (Bigint.to_string n)
- | Oplus (t1,t2) -> Printf.fprintf ch "(%a + %a)" oprint t1 oprint t2
- | Omult (t1,t2) -> Printf.fprintf ch "(%a * %a)" oprint t1 oprint t2
- | Ominus(t1,t2) -> Printf.fprintf ch "(%a - %a)" oprint t1 oprint t2
- | Oopp t1 ->Printf.fprintf ch "~ %a" oprint t1
- | Oatom n -> Printf.fprintf ch "V%02d" n
-
-let print_comp = function
- | Eq -> "=" | Leq -> "<=" | Geq -> ">="
- | Gt -> ">" | Lt -> "<" | Neq -> "!="
-
-let rec pprint ch = function
- Pequa (_,{ e_comp=comp; e_left=t1; e_right=t2 }) ->
- Printf.fprintf ch "%a %s %a" oprint t1 (print_comp comp) oprint t2
- | Ptrue -> Printf.fprintf ch "TT"
- | Pfalse -> Printf.fprintf ch "FF"
- | Pnot t -> Printf.fprintf ch "not(%a)" pprint t
- | Por (_,t1,t2) -> Printf.fprintf ch "(%a or %a)" pprint t1 pprint t2
- | Pand(_,t1,t2) -> Printf.fprintf ch "(%a and %a)" pprint t1 pprint t2
- | Pimp(_,t1,t2) -> Printf.fprintf ch "(%a => %a)" pprint t1 pprint t2
- | Pprop c -> Printf.fprintf ch "Prop"
-
-(* \subsection{Omega vers Oformula} *)
-
-let oformula_of_omega af =
- let rec loop = function
- | ({v=v; c=n}::r) -> Oplus(Omult(Oatom v,Oint n),loop r)
- | [] -> Oint af.constant
- in
- loop af.body
-
-let app f v = EConstr.mkApp(Lazy.force f,v)
-
-(* \subsection{Oformula vers COQ reel} *)
-
-let coq_of_formula env t =
- let rec loop = function
- | Oplus (t1,t2) -> app Z.plus [| loop t1; loop t2 |]
- | Oopp t -> app Z.opp [| loop t |]
- | Omult(t1,t2) -> app Z.mult [| loop t1; loop t2 |]
- | Oint v -> Z.mk v
- | Oatom var ->
- (* attention ne traite pas les nouvelles variables si on ne les
- * met pas dans env.term *)
- get_reified_atom env var
- | Ominus(t1,t2) -> app Z.minus [| loop t1; loop t2 |] in
- loop t
-
-(* \subsection{Oformula vers COQ reifié} *)
-
-let reified_of_atom env i =
- try IntHtbl.find env.real_indices i
- with Not_found ->
- Printf.printf "Atome %d non trouvé\n" i;
- IntHtbl.iter (fun k v -> Printf.printf "%d -> %d\n" k v) env.real_indices;
- raise Not_found
-
-let reified_binop = function
- | Oplus _ -> app coq_t_plus
- | Ominus _ -> app coq_t_minus
- | Omult _ -> app coq_t_mult
- | _ -> assert false
-
-let rec reified_of_formula env t = match t with
- | Oplus (t1,t2) | Omult (t1,t2) | Ominus (t1,t2) ->
- reified_binop t [| reified_of_formula env t1; reified_of_formula env t2 |]
- | Oopp t -> app coq_t_opp [| reified_of_formula env t |]
- | Oint v -> app coq_t_int [| Z.mk v |]
- | Oatom i -> app coq_t_var [| mk_N (reified_of_atom env i) |]
-
-let reified_of_formula env f =
- try reified_of_formula env f
- with reraise -> oprint stderr f; raise reraise
-
-let reified_cmp = function
- | Eq -> app coq_p_eq
- | Leq -> app coq_p_leq
- | Geq -> app coq_p_geq
- | Gt -> app coq_p_gt
- | Lt -> app coq_p_lt
- | Neq -> app coq_p_neq
-
-let reified_conn = function
- | Por _ -> app coq_p_or
- | Pand _ -> app coq_p_and
- | Pimp _ -> app coq_p_imp
- | _ -> assert false
-
-let rec reified_of_oprop sigma env t = match t with
- | Pequa (_,{ e_comp=cmp; e_left=t1; e_right=t2 }) ->
- reified_cmp cmp [| reified_of_formula env t1; reified_of_formula env t2 |]
- | Ptrue -> Lazy.force coq_p_true
- | Pfalse -> Lazy.force coq_p_false
- | Pnot t -> app coq_p_not [| reified_of_oprop sigma env t |]
- | Por (_,t1,t2) | Pand (_,t1,t2) | Pimp (_,t1,t2) ->
- reified_conn t
- [| reified_of_oprop sigma env t1; reified_of_oprop sigma env t2 |]
- | Pprop t -> app coq_p_prop [| mk_nat (add_prop sigma env t) |]
-
-let reified_of_proposition sigma env f =
- try reified_of_oprop sigma env f
- with reraise -> pprint stderr f; raise reraise
-
-let reified_of_eq env (l,r) =
- app coq_p_eq [| reified_of_formula env l; reified_of_formula env r |]
-
-(* \section{Opérations sur les équations}
-Ces fonctions préparent les traces utilisées par la tactique réfléchie
-pour faire des opérations de normalisation sur les équations. *)
-
-(* \subsection{Extractions des variables d'une équation} *)
-(* Extraction des variables d'une équation. *)
-(* Chaque fonction retourne une liste triée sans redondance *)
-
-let (@@) = IntSet.union
-
-let rec vars_of_formula = function
- | Oint _ -> IntSet.empty
- | Oplus (e1,e2) -> (vars_of_formula e1) @@ (vars_of_formula e2)
- | Omult (e1,e2) -> (vars_of_formula e1) @@ (vars_of_formula e2)
- | Ominus (e1,e2) -> (vars_of_formula e1) @@ (vars_of_formula e2)
- | Oopp e -> vars_of_formula e
- | Oatom i -> IntSet.singleton i
-
-let rec vars_of_equations = function
- | [] -> IntSet.empty
- | e::l ->
- (vars_of_formula e.e_left) @@
- (vars_of_formula e.e_right) @@
- (vars_of_equations l)
-
-let rec vars_of_prop = function
- | Pequa(_,e) -> vars_of_equations [e]
- | Pnot p -> vars_of_prop p
- | Por(_,p1,p2) -> (vars_of_prop p1) @@ (vars_of_prop p2)
- | Pand(_,p1,p2) -> (vars_of_prop p1) @@ (vars_of_prop p2)
- | Pimp(_,p1,p2) -> (vars_of_prop p1) @@ (vars_of_prop p2)
- | Pprop _ | Ptrue | Pfalse -> IntSet.empty
-
-(* Normalized formulas :
-
- - sorted list of monomials, largest index first,
- with non-null coefficients
- - a constant coefficient
-
- /!\ Keep in sync with the corresponding functions in ReflOmegaCore !
-*)
-
-type nformula =
- { coefs : (atom_index * Bigint.bigint) list;
- cst : Bigint.bigint }
-
-let scale n { coefs; cst } =
- { coefs = List.map (fun (v,k) -> (v,k*n)) coefs;
- cst = cst*n }
-
-let shuffle nf1 nf2 =
- let rec merge l1 l2 = match l1,l2 with
- | [],_ -> l2
- | _,[] -> l1
- | (v1,k1)::r1,(v2,k2)::r2 ->
- if Int.equal v1 v2 then
- let k = k1+k2 in
- if Bigint.equal k Bigint.zero then merge r1 r2
- else (v1,k) :: merge r1 r2
- else if v1 > v2 then (v1,k1) :: merge r1 l2
- else (v2,k2) :: merge l1 r2
- in
- { coefs = merge nf1.coefs nf2.coefs;
- cst = nf1.cst + nf2.cst }
-
-let rec normalize = function
- | Oplus(t1,t2) -> shuffle (normalize t1) (normalize t2)
- | Ominus(t1,t2) -> normalize (Oplus (t1, Oopp(t2)))
- | Oopp(t) -> scale negone (normalize t)
- | Omult(t,Oint n) | Omult (Oint n, t) ->
- if Bigint.equal n Bigint.zero then { coefs = []; cst = zero }
- else scale n (normalize t)
- | Omult _ -> assert false (* invariant on Omult *)
- | Oint n -> { coefs = []; cst = n }
- | Oatom v -> { coefs = [v,Bigint.one]; cst=Bigint.zero}
-
-(* From normalized formulas to omega representations *)
-
-let omega_of_nformula env kind nf =
- { id = new_omega_eq ();
- kind;
- constant=nf.cst;
- body = List.map (fun (v,c) -> { v; c }) nf.coefs }
-
-
-let negate_oper = function
- Eq -> Neq | Neq -> Eq | Leq -> Gt | Geq -> Lt | Lt -> Geq | Gt -> Leq
-
-let normalize_equation env (negated,depends,origin,path) oper t1 t2 =
- let mk_step t kind =
- let equa = omega_of_nformula env kind (normalize t) in
- { e_comp = oper; e_left = t1; e_right = t2;
- e_negated = negated; e_depends = depends;
- e_origin = { o_hyp = origin; o_path = List.rev path };
- e_omega = equa }
- in
- try match (if negated then (negate_oper oper) else oper) with
- | Eq -> mk_step (Oplus (t1,Oopp t2)) EQUA
- | Neq -> mk_step (Oplus (t1,Oopp t2)) DISE
- | Leq -> mk_step (Oplus (t2,Oopp t1)) INEQ
- | Geq -> mk_step (Oplus (t1,Oopp t2)) INEQ
- | Lt -> mk_step (Oplus (Oplus(t2,Oint negone),Oopp t1)) INEQ
- | Gt -> mk_step (Oplus (Oplus(t1,Oint negone),Oopp t2)) INEQ
- with e when Logic.catchable_exception e -> raise e
-
-(* \section{Compilation des hypothèses} *)
-
-let mkPor i x y = Por (i,x,y)
-let mkPand i x y = Pand (i,x,y)
-let mkPimp i x y = Pimp (i,x,y)
-
-let rec oformula_of_constr sigma env t =
- match Z.parse_term sigma t with
- | Tplus (t1,t2) -> binop sigma env (fun x y -> Oplus(x,y)) t1 t2
- | Tminus (t1,t2) -> binop sigma env (fun x y -> Ominus(x,y)) t1 t2
- | Tmult (t1,t2) ->
- (match Z.get_scalar sigma t1 with
- | Some n -> Omult (Oint n,oformula_of_constr sigma env t2)
- | None ->
- match Z.get_scalar sigma t2 with
- | Some n -> Omult (oformula_of_constr sigma env t1, Oint n)
- | None -> Oatom (add_reified_atom sigma t env))
- | Topp t -> Oopp(oformula_of_constr sigma env t)
- | Tsucc t -> Oplus(oformula_of_constr sigma env t, Oint one)
- | Tnum n -> Oint n
- | Tother -> Oatom (add_reified_atom sigma t env)
-
-and binop sigma env c t1 t2 =
- let t1' = oformula_of_constr sigma env t1 in
- let t2' = oformula_of_constr sigma env t2 in
- c t1' t2'
-
-and binprop sigma env (neg2,depends,origin,path)
- add_to_depends neg1 gl c t1 t2 =
- let i = new_connector_id env in
- let depends1 = if add_to_depends then Left i::depends else depends in
- let depends2 = if add_to_depends then Right i::depends else depends in
- if add_to_depends then
- IntHtbl.add env.constructors i {o_hyp = origin; o_path = List.rev path};
- let t1' =
- oproposition_of_constr sigma env (neg1,depends1,origin,O_left::path) gl t1 in
- let t2' =
- oproposition_of_constr sigma env (neg2,depends2,origin,O_right::path) gl t2 in
- (* On numérote le connecteur dans l'environnement. *)
- c i t1' t2'
-
-and mk_equation sigma env ctxt c connector t1 t2 =
- let t1' = oformula_of_constr sigma env t1 in
- let t2' = oformula_of_constr sigma env t2 in
- (* On ajoute l'equation dans l'environnement. *)
- let omega = normalize_equation env ctxt connector t1' t2' in
- add_equation env omega;
- Pequa (c,omega)
-
-and oproposition_of_constr sigma env ((negated,depends,origin,path) as ctxt) gl c =
- match Z.parse_rel gl c with
- | Req (t1,t2) -> mk_equation sigma env ctxt c Eq t1 t2
- | Rne (t1,t2) -> mk_equation sigma env ctxt c Neq t1 t2
- | Rle (t1,t2) -> mk_equation sigma env ctxt c Leq t1 t2
- | Rlt (t1,t2) -> mk_equation sigma env ctxt c Lt t1 t2
- | Rge (t1,t2) -> mk_equation sigma env ctxt c Geq t1 t2
- | Rgt (t1,t2) -> mk_equation sigma env ctxt c Gt t1 t2
- | Rtrue -> Ptrue
- | Rfalse -> Pfalse
- | Rnot t ->
- let ctxt' = (not negated, depends, origin,(O_mono::path)) in
- Pnot (oproposition_of_constr sigma env ctxt' gl t)
- | Ror (t1,t2) -> binprop sigma env ctxt (not negated) negated gl mkPor t1 t2
- | Rand (t1,t2) -> binprop sigma env ctxt negated negated gl mkPand t1 t2
- | Rimp (t1,t2) ->
- binprop sigma env ctxt (not negated) (not negated) gl mkPimp t1 t2
- | Riff (t1,t2) ->
- (* No lifting here, since Omega only works on closed propositions. *)
- binprop sigma env ctxt negated negated gl mkPand
- (EConstr.mkArrow t1 t2) (EConstr.mkArrow t2 t1)
- | _ -> Pprop c
-
-(* Destructuration des hypothèses et de la conclusion *)
-
-let display_gl env t_concl t_lhyps =
- Printf.printf "REIFED PROBLEM\n\n";
- Printf.printf " CONCL: %a\n" pprint t_concl;
- List.iter
- (fun (i,_,t) -> Printf.printf " %s: %a\n" (Id.to_string i) pprint t)
- t_lhyps;
- print_env_reification env
-
-type defined = Defined | Assumed
-
-let reify_hyp sigma env gl i =
- let open Context.Named.Declaration in
- let ctxt = (false,[],i,[]) in
- match Tacmach.New.pf_get_hyp i gl with
- | LocalDef (_,d,t) when Z.is_int_typ gl t ->
- let dummy = Lazy.force coq_True in
- let p = mk_equation sigma env ctxt dummy Eq (EConstr.mkVar i) d in
- i,Defined,p
- | LocalDef (_,_,t) | LocalAssum (_,t) ->
- let p = oproposition_of_constr sigma env ctxt gl t in
- i,Assumed,p
-
-let reify_gl env gl =
- let sigma = Proofview.Goal.sigma gl in
- let concl = Tacmach.New.pf_concl gl in
- let hyps = Tacmach.New.pf_ids_of_hyps gl in
- let ctxt_concl = (true,[],id_concl,[O_mono]) in
- let t_concl = oproposition_of_constr sigma env ctxt_concl gl concl in
- let t_lhyps = List.map (reify_hyp sigma env gl) hyps in
- let () = if !debug then display_gl env t_concl t_lhyps in
- t_concl, t_lhyps
-
-let rec destruct_pos_hyp eqns = function
- | Pequa (_,e) -> [e :: eqns]
- | Ptrue | Pfalse | Pprop _ -> [eqns]
- | Pnot t -> destruct_neg_hyp eqns t
- | Por (_,t1,t2) ->
- let s1 = destruct_pos_hyp eqns t1 in
- let s2 = destruct_pos_hyp eqns t2 in
- s1 @ s2
- | Pand(_,t1,t2) ->
- List.map_append
- (fun le1 -> destruct_pos_hyp le1 t2)
- (destruct_pos_hyp eqns t1)
- | Pimp(_,t1,t2) ->
- let s1 = destruct_neg_hyp eqns t1 in
- let s2 = destruct_pos_hyp eqns t2 in
- s1 @ s2
-
-and destruct_neg_hyp eqns = function
- | Pequa (_,e) -> [e :: eqns]
- | Ptrue | Pfalse | Pprop _ -> [eqns]
- | Pnot t -> destruct_pos_hyp eqns t
- | Pand (_,t1,t2) ->
- let s1 = destruct_neg_hyp eqns t1 in
- let s2 = destruct_neg_hyp eqns t2 in
- s1 @ s2
- | Por(_,t1,t2) ->
- List.map_append
- (fun le1 -> destruct_neg_hyp le1 t2)
- (destruct_neg_hyp eqns t1)
- | Pimp(_,t1,t2) ->
- List.map_append
- (fun le1 -> destruct_neg_hyp le1 t2)
- (destruct_pos_hyp eqns t1)
-
-let rec destructurate_hyps = function
- | [] -> [[]]
- | (i,_,t) :: l ->
- let l_syst1 = destruct_pos_hyp [] t in
- let l_syst2 = destructurate_hyps l in
- List.cartesian (@) l_syst1 l_syst2
-
-(* \subsection{Affichage d'un système d'équation} *)
-
-(* Affichage des dépendances de système *)
-let display_depend = function
- Left i -> Printf.printf " L%d" i
- | Right i -> Printf.printf " R%d" i
-
-let display_systems syst_list =
- let display_omega om_e =
- Printf.printf " E%d : %a %s 0\n"
- om_e.id
- (fun _ -> display_eq display_omega_var)
- (om_e.body, om_e.constant)
- (operator_of_eq om_e.kind) in
-
- let display_equation oformula_eq =
- pprint stdout (Pequa (Lazy.force coq_I,oformula_eq)); print_newline ();
- display_omega oformula_eq.e_omega;
- Printf.printf " Depends on:";
- List.iter display_depend oformula_eq.e_depends;
- Printf.printf "\n Path: %s"
- (String.concat ""
- (List.map (function O_left -> "L" | O_right -> "R" | O_mono -> "M")
- oformula_eq.e_origin.o_path));
- Printf.printf "\n Origin: %s (negated : %s)\n\n"
- (Id.to_string oformula_eq.e_origin.o_hyp)
- (if oformula_eq.e_negated then "yes" else "no") in
-
- let display_system syst =
- Printf.printf "=SYSTEM===================================\n";
- List.iter display_equation syst in
- List.iter display_system syst_list
-
-(* Extraction des prédicats utilisées dans une trace. Permet ensuite le
- calcul des hypothèses *)
-
-let rec hyps_used_in_trace = function
- | [] -> IntSet.empty
- | act :: l ->
- match act with
- | HYP e -> IntSet.add e.id (hyps_used_in_trace l)
- | SPLIT_INEQ (_,(_,act1),(_,act2)) ->
- hyps_used_in_trace act1 @@ hyps_used_in_trace act2
- | _ -> hyps_used_in_trace l
-
-(** Retreive variables declared as extra equations during resolution
- and declare them into the environment.
- We should consider these variables in their introduction order,
- otherwise really bad things will happen. *)
-
-let state_cmp x y = Int.compare x.st_var y.st_var
-
-module StateSet =
- Set.Make (struct type t = state_action let compare = state_cmp end)
-
-let rec stated_in_trace = function
- | [] -> StateSet.empty
- | [SPLIT_INEQ (_,(_,t1),(_,t2))] ->
- StateSet.union (stated_in_trace t1) (stated_in_trace t2)
- | STATE action :: l -> StateSet.add action (stated_in_trace l)
- | _ :: l -> stated_in_trace l
-
-let rec stated_in_tree = function
- | Tree(_,t1,t2) -> StateSet.union (stated_in_tree t1) (stated_in_tree t2)
- | Leaf s -> stated_in_trace s.s_trace
-
-let mk_refl t = app coq_refl_equal [|Lazy.force Z.typ; t|]
-
-let digest_stated_equations env tree =
- let do_equation st (vars,gens,eqns,ids) =
- (** We turn the definition of [v]
- - into a reified formula : *)
- let v_def = oformula_of_omega st.st_def in
- (** - into a concrete Coq formula
- (this uses only older vars already in env) : *)
- let coq_v = coq_of_formula env v_def in
- (** We then update the environment *)
- set_reified_atom st.st_var coq_v env;
- (** The term we'll introduce *)
- let term_to_generalize = mk_refl coq_v in
- (** Its representation as equation (but not reified yet,
- we lack the proper env to do that). *)
- let term_to_reify = (v_def,Oatom st.st_var) in
- (st.st_var::vars,
- term_to_generalize::gens,
- term_to_reify::eqns,
- CCEqua st.st_def.id :: ids)
- in
- let (vars,gens,eqns,ids) =
- StateSet.fold do_equation (stated_in_tree tree) ([],[],[],[])
- in
- (List.rev vars, List.rev gens, List.rev eqns, List.rev ids)
-
-(* Calcule la liste des éclatements à réaliser sur les hypothèses
- nécessaires pour extraire une liste d'équations donnée *)
-
-(* PL: experimentally, the result order of the following function seems
- _very_ crucial for efficiency. No idea why. Do not remove the List.rev
- or modify the current semantics of Util.List.union (some elements of first
- arg, then second arg), unless you know what you're doing. *)
-
-let rec get_eclatement env = function
- | [] -> []
- | i :: r ->
- let l = try (get_equation env i).e_depends with Not_found -> [] in
- List.union dir_eq (List.rev l) (get_eclatement env r)
-
-let select_smaller l =
- let comp (_,x) (_,y) = Int.compare (List.length x) (List.length y) in
- try List.hd (List.sort comp l) with Failure _ -> failwith "select_smaller"
-
-let filter_compatible_systems required systems =
- let rec select = function
- | [] -> []
- | (x::l) ->
- if List.mem_f dir_eq x required then select l
- else if List.mem_f dir_eq (barre x) required then raise Exit
- else x :: select l
- in
- List.map_filter
- (function (sol, splits) ->
- try Some (sol, select splits) with Exit -> None)
- systems
-
-let rec equas_of_solution_tree = function
- | Tree(_,t1,t2) ->
- (equas_of_solution_tree t1)@@(equas_of_solution_tree t2)
- | Leaf s -> s.s_equa_deps
-
-(** [maximize_prop] pushes useless props in a new Pprop atom.
- The reified formulas get shorter, but be careful with decidabilities.
- For instance, anything that contains a Pprop is considered to be
- undecidable in [ReflOmegaCore], whereas a Pfalse for instance at
- the same spot will lead to a decidable formula.
- In particular, do not use this function on the conclusion.
- Even in hypotheses, we could probably build pathological examples
- that romega won't handle correctly, but they should be pretty rare.
-*)
-
-let maximize_prop equas c =
- let rec loop c = match c with
- | Pequa(t,e) -> if IntSet.mem e.e_omega.id equas then c else Pprop t
- | Pnot t ->
- (match loop t with
- | Pprop p -> Pprop (app coq_not [|p|])
- | t' -> Pnot t')
- | Por(i,t1,t2) ->
- (match loop t1, loop t2 with
- | Pprop p1, Pprop p2 -> Pprop (app coq_or [|p1;p2|])
- | t1', t2' -> Por(i,t1',t2'))
- | Pand(i,t1,t2) ->
- (match loop t1, loop t2 with
- | Pprop p1, Pprop p2 -> Pprop (app coq_and [|p1;p2|])
- | t1', t2' -> Pand(i,t1',t2'))
- | Pimp(i,t1,t2) ->
- (match loop t1, loop t2 with
- | Pprop p1, Pprop p2 -> Pprop (EConstr.mkArrow p1 p2) (* no lift (closed) *)
- | t1', t2' -> Pimp(i,t1',t2'))
- | Ptrue -> Pprop (app coq_True [||])
- | Pfalse -> Pprop (app coq_False [||])
- | Pprop _ -> c
- in loop c
-
-let rec display_solution_tree ch = function
- Leaf t ->
- output_string ch
- (Printf.sprintf "%d[%s]"
- t.s_index
- (String.concat " " (List.map string_of_int
- (IntSet.elements t.s_equa_deps))))
- | Tree(i,t1,t2) ->
- Printf.fprintf ch "S%d(%a,%a)" i
- display_solution_tree t1 display_solution_tree t2
-
-let rec solve_with_constraints all_solutions path =
- let rec build_tree sol buf = function
- [] -> Leaf sol
- | (Left i :: remainder) ->
- Tree(i,
- build_tree sol (Left i :: buf) remainder,
- solve_with_constraints all_solutions (List.rev(Right i :: buf)))
- | (Right i :: remainder) ->
- Tree(i,
- solve_with_constraints all_solutions (List.rev (Left i :: buf)),
- build_tree sol (Right i :: buf) remainder) in
- let weighted = filter_compatible_systems path all_solutions in
- let (winner_sol,winner_deps) =
- try select_smaller weighted
- with reraise ->
- Printf.printf "%d - %d\n"
- (List.length weighted) (List.length all_solutions);
- List.iter display_depend path; raise reraise
- in
- build_tree winner_sol (List.rev path) winner_deps
-
-let find_path {o_hyp=id;o_path=p} env =
- let rec loop_path = function
- ([],l) -> Some l
- | (x1::l1,x2::l2) when occ_step_eq x1 x2 -> loop_path (l1,l2)
- | _ -> None in
- let rec loop_id i = function
- CCHyp{o_hyp=id';o_path=p'} :: l when Id.equal id id' ->
- begin match loop_path (p',p) with
- Some r -> i,r
- | None -> loop_id (succ i) l
- end
- | _ :: l -> loop_id (succ i) l
- | [] -> failwith "find_path" in
- loop_id 0 env
-
-let mk_direction_list l =
- let trans = function
- | O_left -> Some (Lazy.force coq_d_left)
- | O_right -> Some (Lazy.force coq_d_right)
- | O_mono -> None (* No more [D_mono] constructor now *)
- in
- mk_list (Lazy.force coq_direction) (List.map_filter trans l)
-
-
-(* \section{Rejouer l'historique} *)
-
-let hyp_idx env_hyp i =
- let rec loop count = function
- | [] -> failwith (Printf.sprintf "get_hyp %d" i)
- | CCEqua i' :: _ when Int.equal i i' -> mk_nat count
- | _ :: l -> loop (succ count) l
- in loop 0 env_hyp
-
-
-(* We now expand NEGATE_CONTRADICT and CONTRADICTION into
- a O_SUM followed by a O_BAD_CONSTANT *)
-
-let sum_bad inv i1 i2 =
- let open EConstr in
- mkApp (Lazy.force coq_s_sum,
- [| Z.mk Bigint.one; i1;
- Z.mk (if inv then negone else Bigint.one); i2;
- mkApp (Lazy.force coq_s_bad_constant, [| mk_nat 0 |])|])
-
-let rec reify_trace env env_hyp =
- let open EConstr in
- function
- | CONSTANT_NOT_NUL(e,_) :: []
- | CONSTANT_NEG(e,_) :: []
- | CONSTANT_NUL e :: [] ->
- mkApp (Lazy.force coq_s_bad_constant,[| hyp_idx env_hyp e |])
- | NEGATE_CONTRADICT(e1,e2,direct) :: [] ->
- sum_bad direct (hyp_idx env_hyp e1.id) (hyp_idx env_hyp e2.id)
- | CONTRADICTION (e1,e2) :: [] ->
- sum_bad false (hyp_idx env_hyp e1.id) (hyp_idx env_hyp e2.id)
- | NOT_EXACT_DIVIDE (e1,k) :: [] ->
- mkApp (Lazy.force coq_s_not_exact_divide,
- [| hyp_idx env_hyp e1.id; Z.mk k |])
- | DIVIDE_AND_APPROX (e1,_,k,_) :: l
- | EXACT_DIVIDE (e1,k) :: l ->
- mkApp (Lazy.force coq_s_divide,
- [| hyp_idx env_hyp e1.id; Z.mk k;
- reify_trace env env_hyp l |])
- | MERGE_EQ(e3,e1,e2) :: l ->
- mkApp (Lazy.force coq_s_merge_eq,
- [| hyp_idx env_hyp e1.id; hyp_idx env_hyp e2;
- reify_trace env (CCEqua e3:: env_hyp) l |])
- | SUM(e3,(k1,e1),(k2,e2)) :: l ->
- mkApp (Lazy.force coq_s_sum,
- [| Z.mk k1; hyp_idx env_hyp e1.id;
- Z.mk k2; hyp_idx env_hyp e2.id;
- reify_trace env (CCEqua e3 :: env_hyp) l |])
- | STATE {st_new_eq; st_def; st_orig; st_coef } :: l ->
- (* we now produce a [O_SUM] here *)
- mkApp (Lazy.force coq_s_sum,
- [| Z.mk Bigint.one; hyp_idx env_hyp st_orig.id;
- Z.mk st_coef; hyp_idx env_hyp st_def.id;
- reify_trace env (CCEqua st_new_eq.id :: env_hyp) l |])
- | HYP _ :: l -> reify_trace env env_hyp l
- | SPLIT_INEQ(e,(e1,l1),(e2,l2)) :: _ ->
- let r1 = reify_trace env (CCEqua e1 :: env_hyp) l1 in
- let r2 = reify_trace env (CCEqua e2 :: env_hyp) l2 in
- mkApp (Lazy.force coq_s_split_ineq,
- [| hyp_idx env_hyp e.id; r1 ; r2 |])
- | (FORGET_C _ | FORGET _ | FORGET_I _) :: l -> reify_trace env env_hyp l
- | WEAKEN _ :: l -> failwith "not_treated"
- | _ -> failwith "bad history"
-
-let rec decompose_tree env ctxt = function
- Tree(i,left,right) ->
- let org =
- try IntHtbl.find env.constructors i
- with Not_found ->
- failwith (Printf.sprintf "Cannot find constructor %d" i) in
- let (index,path) = find_path org ctxt in
- let left_hyp = CCHyp{o_hyp=org.o_hyp;o_path=org.o_path @ [O_left]} in
- let right_hyp = CCHyp{o_hyp=org.o_hyp;o_path=org.o_path @ [O_right]} in
- app coq_e_split
- [| mk_nat index;
- mk_direction_list path;
- decompose_tree env (left_hyp::ctxt) left;
- decompose_tree env (right_hyp::ctxt) right |]
- | Leaf s ->
- decompose_tree_hyps s.s_trace env ctxt (IntSet.elements s.s_equa_deps)
-and decompose_tree_hyps trace env ctxt = function
- [] -> app coq_e_solve [| reify_trace env ctxt trace |]
- | (i::l) ->
- let equation =
- try IntHtbl.find env.equations i
- with Not_found ->
- failwith (Printf.sprintf "Cannot find equation %d" i) in
- let (index,path) = find_path equation.e_origin ctxt in
- let cont =
- decompose_tree_hyps trace env
- (CCEqua equation.e_omega.id :: ctxt) l in
- app coq_e_extract [|mk_nat index; mk_direction_list path; cont |]
-
-let solve_system env index list_eq =
- let system = List.map (fun eq -> eq.e_omega) list_eq in
- let trace =
- OmegaSolver.simplify_strong
- (new_omega_eq,new_omega_var,display_omega_var)
- system
- in
- (* Hypotheses used for this solution *)
- let vars = hyps_used_in_trace trace in
- let splits = get_eclatement env (IntSet.elements vars) in
- if !debug then
- begin
- Printf.printf "SYSTEME %d\n" index;
- display_action display_omega_var trace;
- print_string "\n Depend :";
- IntSet.iter (fun i -> Printf.printf " %d" i) vars;
- print_string "\n Split points :";
- List.iter display_depend splits;
- Printf.printf "\n------------------------------------\n"
- end;
- {s_index = index; s_trace = trace; s_equa_deps = vars}, splits
-
-(* \section{La fonction principale} *)
- (* Cette fonction construit la
-trace pour la procédure de décision réflexive. A partir des résultats
-de l'extraction des systèmes, elle lance la résolution par Omega, puis
-l'extraction d'un ensemble minimal de solutions permettant la
-résolution globale du système et enfin construit la trace qui permet
-de faire rejouer cette solution par la tactique réflexive. *)
-
-let resolution unsafe sigma env (reified_concl,reified_hyps) systems_list =
- if !debug then Printf.printf "\n====================================\n";
- let all_solutions = List.mapi (solve_system env) systems_list in
- let solution_tree = solve_with_constraints all_solutions [] in
- if !debug then begin
- display_solution_tree stdout solution_tree;
- print_newline()
- end;
- (** Collect all hypotheses and variables used in the solution tree *)
- let useful_equa_ids = equas_of_solution_tree solution_tree in
- let useful_hypnames, useful_vars =
- IntSet.fold
- (fun i (hyps,vars) ->
- let e = get_equation env i in
- Id.Set.add e.e_origin.o_hyp hyps,
- vars_of_equations [e] @@ vars)
- useful_equa_ids
- (Id.Set.empty, vars_of_prop reified_concl)
- in
- let useful_hypnames =
- Id.Set.elements (Id.Set.remove id_concl useful_hypnames)
- in
-
- (** Parts coming from equations introduced by omega: *)
- let stated_vars, l_generalize_arg, to_reify_stated, hyp_stated_vars =
- digest_stated_equations env solution_tree
- in
- (** The final variables are either coming from:
- - useful hypotheses (and conclusion)
- - equations introduced during resolution *)
- let all_vars_env = (IntSet.elements useful_vars) @ stated_vars
- in
- (** We prepare the renumbering from all variables to useful ones.
- Since [all_var_env] is sorted, this renumbering will preserve
- order: this way, the equations in ReflOmegaCore will have
- the same normal forms as here. *)
- let reduced_term_env =
- let rec loop i = function
- | [] -> []
- | var :: l ->
- let t = get_reified_atom env var in
- IntHtbl.add env.real_indices var i; t :: loop (succ i) l
- in
- mk_list (Lazy.force Z.typ) (loop 0 all_vars_env)
- in
- (** The environment [env] (and especially [env.real_indices]) is now
- ready for the coming reifications: *)
- let l_reified_stated = List.map (reified_of_eq env) to_reify_stated in
- let reified_concl = reified_of_proposition sigma env reified_concl in
- let l_reified_terms =
- List.map
- (fun id ->
- match Id.Map.find id reified_hyps with
- | Defined,p ->
- reified_of_proposition sigma env p, mk_refl (EConstr.mkVar id)
- | Assumed,p ->
- reified_of_proposition sigma env (maximize_prop useful_equa_ids p),
- EConstr.mkVar id
- | exception Not_found -> assert false)
- useful_hypnames
- in
- let l_reified_terms, l_reified_hypnames = List.split l_reified_terms in
- let env_props_reified = mk_plist env.props in
- let reified_goal =
- mk_list (Lazy.force coq_proposition)
- (l_reified_stated @ l_reified_terms) in
- let reified =
- app coq_interp_sequent
- [| reified_concl;env_props_reified;reduced_term_env;reified_goal|]
- in
- let mk_occ id = {o_hyp=id;o_path=[]} in
- let initial_context =
- List.map (fun id -> CCHyp (mk_occ id)) useful_hypnames in
- let context =
- CCHyp (mk_occ id_concl) :: hyp_stated_vars @ initial_context in
- let decompose_tactic = decompose_tree env context solution_tree in
-
- Tactics.generalize (l_generalize_arg @ l_reified_hypnames) >>
- Tactics.convert_concl_no_check reified DEFAULTcast >>
- Tactics.apply (app coq_do_omega [|decompose_tactic|]) >>
- show_goal >>
- (if unsafe then
- (* Trust the produced term. Faster, but might fail later at Qed.
- Also handy when debugging, e.g. via a Show Proof after romega. *)
- Tactics.convert_concl_no_check (Lazy.force coq_True) VMcast
- else
- Tactics.normalise_vm_in_concl) >>
- Tactics.apply (Lazy.force coq_I)
-
-let total_reflexive_omega_tactic unsafe =
- Proofview.Goal.nf_enter begin fun gl ->
- Coqlib.check_required_library ["Coq";"romega";"ROmega"];
- rst_omega_eq ();
- rst_omega_var ();
- try
- let env = new_environment () in
- let (concl,hyps) = reify_gl env gl in
- (* Register all atom indexes created during reification as omega vars *)
- set_omega_maxvar (pred (List.length env.terms));
- let full_reified_goal = (id_concl,Assumed,Pnot concl) :: hyps in
- let systems_list = destructurate_hyps full_reified_goal in
- let hyps =
- List.fold_left (fun s (id,d,p) -> Id.Map.add id (d,p) s) Id.Map.empty hyps
- in
- if !debug then display_systems systems_list;
- let sigma = Proofview.Goal.sigma gl in
- resolution unsafe sigma env (concl,hyps) systems_list
- with NO_CONTRADICTION -> CErrors.user_err Pp.(str "ROmega can't solve this system")
- end
-
diff --git a/plugins/romega/romega_plugin.mlpack b/plugins/romega/romega_plugin.mlpack
deleted file mode 100644
index 38d0e94111..0000000000
--- a/plugins/romega/romega_plugin.mlpack
+++ /dev/null
@@ -1,3 +0,0 @@
-Const_omega
-Refl_omega
-G_romega
diff --git a/plugins/rtauto/plugin_base.dune b/plugins/rtauto/plugin_base.dune
new file mode 100644
index 0000000000..233845ae0f
--- /dev/null
+++ b/plugins/rtauto/plugin_base.dune
@@ -0,0 +1,5 @@
+(library
+ (name rtauto_plugin)
+ (public_name coq.plugins.rtauto)
+ (synopsis "Coq's rtauto plugin")
+ (libraries coq.plugins.ltac))
diff --git a/plugins/setoid_ring/Field_theory.v b/plugins/setoid_ring/Field_theory.v
index d9e32dbbf8..ce115f564f 100644
--- a/plugins/setoid_ring/Field_theory.v
+++ b/plugins/setoid_ring/Field_theory.v
@@ -19,6 +19,7 @@ Section MakeFieldPol.
(* Field elements : R *)
Variable R:Type.
+Declare Scope R_scope.
Bind Scope R_scope with R.
Delimit Scope R_scope with ring.
Local Open Scope R_scope.
@@ -94,6 +95,7 @@ Let rdistr_r := ARdistr_r Rsth Reqe ARth.
(* Coefficients : C *)
Variable C: Type.
+Declare Scope C_scope.
Bind Scope C_scope with C.
Delimit Scope C_scope with coef.
@@ -139,6 +141,7 @@ Let rpow_pow := pow_th.(rpow_pow_N).
(* Polynomial expressions : (PExpr C) *)
+Declare Scope PE_scope.
Bind Scope PE_scope with PExpr.
Delimit Scope PE_scope with poly.
diff --git a/plugins/setoid_ring/Ncring_initial.v b/plugins/setoid_ring/Ncring_initial.v
index 523c7b02eb..1ca6227f25 100644
--- a/plugins/setoid_ring/Ncring_initial.v
+++ b/plugins/setoid_ring/Ncring_initial.v
@@ -79,8 +79,9 @@ Context {R:Type}`{Ring R}.
| Z0 => 0
| Zneg p => -(gen_phiPOS p)
end.
- Local Notation "[ x ]" := (gen_phiZ x) : ZMORPHISM.
- Local Open Scope ZMORPHISM.
+ Declare Scope ZMORPHISM.
+ Notation "[ x ]" := (gen_phiZ x) : ZMORPHISM.
+ Open Scope ZMORPHISM.
Definition get_signZ z :=
match z with
diff --git a/plugins/setoid_ring/Ring_base.v b/plugins/setoid_ring/Ring_base.v
index a9b4d9d6f4..920b13ef49 100644
--- a/plugins/setoid_ring/Ring_base.v
+++ b/plugins/setoid_ring/Ring_base.v
@@ -12,7 +12,6 @@
ring tactic. Abstract rings need more theory, depending on
ZArith_base. *)
-Require Import Quote.
Declare ML Module "newring_plugin".
Require Export Ring_theory.
Require Export Ring_tac.
diff --git a/plugins/setoid_ring/Ring_tac.v b/plugins/setoid_ring/Ring_tac.v
index e8efb362e2..26fef99bb2 100644
--- a/plugins/setoid_ring/Ring_tac.v
+++ b/plugins/setoid_ring/Ring_tac.v
@@ -15,7 +15,6 @@ Require Import Ring_polynom.
Require Import BinList.
Require Export ListTactics.
Require Import InitialRing.
-Require Import Quote.
Declare ML Module "newring_plugin".
diff --git a/plugins/setoid_ring/newring.ml b/plugins/setoid_ring/newring.ml
index a736eec5e7..b05e1e85b7 100644
--- a/plugins/setoid_ring/newring.ml
+++ b/plugins/setoid_ring/newring.ml
@@ -99,7 +99,7 @@ let protect_tac_in map id =
let rec closed_under sigma cset t =
try
let (gr, _) = Termops.global_of_constr sigma t in
- Refset_env.mem gr cset
+ GlobRef.Set_env.mem gr cset
with Not_found ->
match EConstr.kind sigma t with
| Cast(c,_,_) -> closed_under sigma cset c
@@ -111,7 +111,7 @@ let closed_term args _ = match args with
let t = Option.get (Value.to_constr t) in
let l = List.map (fun c -> Value.cast (Genarg.topwit Stdarg.wit_ref) c) (Option.get (Value.to_list l)) in
Proofview.tclEVARMAP >>= fun sigma ->
- let cs = List.fold_right Refset_env.add l Refset_env.empty in
+ let cs = List.fold_right GlobRef.Set_env.add l GlobRef.Set_env.empty in
if closed_under sigma cs t then Proofview.tclUNIT () else Tacticals.New.tclFAIL 0 (mt())
| _ -> assert false
diff --git a/plugins/setoid_ring/plugin_base.dune b/plugins/setoid_ring/plugin_base.dune
new file mode 100644
index 0000000000..101246e28f
--- /dev/null
+++ b/plugins/setoid_ring/plugin_base.dune
@@ -0,0 +1,5 @@
+(library
+ (name newring_plugin)
+ (public_name coq.plugins.setoid_ring)
+ (synopsis "Coq's setoid ring plugin")
+ (libraries coq.plugins.quote))
diff --git a/plugins/ssr/plugin_base.dune b/plugins/ssr/plugin_base.dune
new file mode 100644
index 0000000000..de9053f1a0
--- /dev/null
+++ b/plugins/ssr/plugin_base.dune
@@ -0,0 +1,6 @@
+(library
+ (name ssreflect_plugin)
+ (public_name coq.plugins.ssreflect)
+ (synopsis "Coq's ssreflect plugin")
+ (modules_without_implementation ssrast)
+ (libraries coq.plugins.ssrmatching))
diff --git a/plugins/ssr/ssrcommon.ml b/plugins/ssr/ssrcommon.ml
index 54f3f9c718..f2f236f448 100644
--- a/plugins/ssr/ssrcommon.ml
+++ b/plugins/ssr/ssrcommon.ml
@@ -469,7 +469,7 @@ let ssrevaltac ist gtac = Tacinterp.tactic_of_value ist gtac
(* term mkApp (t', args) is convertible to t. *)
(* This makes a useful shorthand for local definitions in proofs, *)
(* i.e., pose succ := _ + 1 means pose succ := fun n : nat => n + 1, *)
-(* and, in context of the the 4CT library, pose mid := maps id means *)
+(* and, in context of the 4CT library, pose mid := maps id means *)
(* pose mid := fun d : detaSet => @maps d d (@id (datum d)) *)
(* Note that this facility does not extend to set, which tries *)
(* instead to fill holes by matching a goal subterm. *)
@@ -1088,7 +1088,7 @@ let () = CLexer.set_keyword_state frozen_lexer ;;
(** Basic tactics *)
-let rec fst_prod red tac = Proofview.Goal.nf_enter begin fun gl ->
+let rec fst_prod red tac = Proofview.Goal.enter begin fun gl ->
let concl = Proofview.Goal.concl gl in
match EConstr.kind (Proofview.Goal.sigma gl) concl with
| Prod (id,_,tgt) | LetIn(id,_,_,tgt) -> tac id
diff --git a/plugins/ssr/ssreflect.v b/plugins/ssr/ssreflect.v
index b4144aa45e..460bdc6d23 100644
--- a/plugins/ssr/ssreflect.v
+++ b/plugins/ssr/ssreflect.v
@@ -86,6 +86,7 @@ Export SsrSyntax.
(* recognize the expansion of the boolean if; using the default printer *)
(* avoids a spurrious trailing %GEN_IF. *)
+Declare Scope general_if_scope.
Delimit Scope general_if_scope with GEN_IF.
Notation "'if' c 'then' v1 'else' v2" :=
@@ -103,6 +104,7 @@ Notation "'if' c 'as' x 'return' t 'then' v1 'else' v2" :=
(* Force boolean interpretation of simple if expressions. *)
+Declare Scope boolean_if_scope.
Delimit Scope boolean_if_scope with BOOL_IF.
Notation "'if' c 'return' t 'then' v1 'else' v2" :=
@@ -125,6 +127,7 @@ Open Scope boolean_if_scope.
(* Non-ssreflect libraries that do not respect the form syntax (e.g., the Coq *)
(* Lists library) should be loaded before ssreflect so that their notations *)
(* do not mask all ssreflect forms. *)
+Declare Scope form_scope.
Delimit Scope form_scope with FORM.
Open Scope form_scope.
diff --git a/plugins/ssr/ssrelim.ml b/plugins/ssr/ssrelim.ml
index fbe3b000fb..602fcfcab5 100644
--- a/plugins/ssr/ssrelim.ml
+++ b/plugins/ssr/ssrelim.ml
@@ -293,7 +293,8 @@ let ssrelim ?(ind=ref None) ?(is_case=false) deps what ?elim eqid elim_intro_tac
let c, cl, ucst = match_pat env p occ h cl in
let gl = pf_merge_uc ucst gl in
let c = EConstr.of_constr c in
- let gl = try pf_unify_HO gl inf_t c with _ -> error gl c inf_t in
+ let gl = try pf_unify_HO gl inf_t c
+ with exn when CErrors.noncritical exn -> error gl c inf_t in
cl, gl, post
with
| NoMatch | NoProgress ->
@@ -302,7 +303,8 @@ let ssrelim ?(ind=ref None) ?(is_case=false) deps what ?elim eqid elim_intro_tac
let e = EConstr.of_constr e in
let n, e, _, _ucst = pf_abs_evars gl (fst p, e) in
let e, _, _, gl = pf_saturate ~beta:true gl e n in
- let gl = try pf_unify_HO gl inf_t e with _ -> error gl e inf_t in
+ let gl = try pf_unify_HO gl inf_t e
+ with exn when CErrors.noncritical exn -> error gl e inf_t in
cl, gl, post
in
let rec match_all concl gl patterns =
diff --git a/plugins/ssr/ssrequality.ml b/plugins/ssr/ssrequality.ml
index 23cbf49c05..f23433f2f4 100644
--- a/plugins/ssr/ssrequality.ml
+++ b/plugins/ssr/ssrequality.ml
@@ -115,7 +115,8 @@ let newssrcongrtac arg ist gl =
(* utils *)
let fs gl t = Reductionops.nf_evar (project gl) t in
let tclMATCH_GOAL (c, gl_c) proj t_ok t_fail gl =
- match try Some (pf_unify_HO gl_c (pf_concl gl) c) with _ -> None with
+ match try Some (pf_unify_HO gl_c (pf_concl gl) c)
+ with exn when CErrors.noncritical exn -> None with
| Some gl_c ->
tclTHEN (Proofview.V82.of_tactic (convert_concl (fs gl_c c)))
(t_ok (proj gl_c)) gl
diff --git a/plugins/ssr/ssrfun.v b/plugins/ssr/ssrfun.v
index b2d5143e36..99ff943e61 100644
--- a/plugins/ssr/ssrfun.v
+++ b/plugins/ssr/ssrfun.v
@@ -216,6 +216,7 @@ Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
+Declare Scope fun_scope.
Delimit Scope fun_scope with FUN.
Open Scope fun_scope.
@@ -225,6 +226,7 @@ Notation "f ^~ y" := (fun x => f x y)
Notation "@^~ x" := (fun f => f x)
(at level 10, x at level 8, no associativity, format "@^~ x") : fun_scope.
+Declare Scope pair_scope.
Delimit Scope pair_scope with PAIR.
Open Scope pair_scope.
diff --git a/plugins/ssr/ssrfwd.ml b/plugins/ssr/ssrfwd.ml
index e367cd32d6..f67cf20e49 100644
--- a/plugins/ssr/ssrfwd.ml
+++ b/plugins/ssr/ssrfwd.ml
@@ -25,9 +25,7 @@ module RelDecl = Context.Rel.Declaration
(** 8. Forward chaining tactics (pose, set, have, suffice, wlog) *)
(** Defined identifier *)
-
-let settac id c = Tactics.letin_tac None (Name id) c None
-let posetac id cl = Proofview.V82.of_tactic (settac id cl Locusops.nowhere)
+let posetac id cl = Proofview.V82.of_tactic (Tactics.pose_tac (Name id) cl)
let ssrposetac (id, (_, t)) gl =
let ist, t =
diff --git a/plugins/ssr/ssripats.ml b/plugins/ssr/ssripats.ml
index 46fde41150..1dbacf0ff7 100644
--- a/plugins/ssr/ssripats.ml
+++ b/plugins/ssr/ssripats.ml
@@ -379,8 +379,9 @@ let elim_intro_tac ipats ?ist what eqid ssrelim is_rec clr =
let ctx, last = EConstr.decompose_prod_assum sigma concl in
let args = match EConstr.kind_of_type sigma last with
| Term.AtomicType (hd, args) ->
- assert(Ssrcommon.is_protect hd env sigma);
- args
+ if Ssrcommon.is_protect hd env sigma then args
+ else Ssrcommon.errorstrm
+ (Pp.str "Too many names in intro pattern")
| _ -> assert false in
let case = args.(Array.length args-1) in
if not(EConstr.Vars.closed0 sigma case)
diff --git a/plugins/ssr/ssrparser.ml4 b/plugins/ssr/ssrparser.ml4
index 8b9c94f2db..e4a0910673 100644
--- a/plugins/ssr/ssrparser.ml4
+++ b/plugins/ssr/ssrparser.ml4
@@ -342,7 +342,7 @@ let interp_index ist gl idx =
open Pltac
-ARGUMENT EXTEND ssrindex TYPED AS ssrindex PRINTED BY pr_ssrindex
+ARGUMENT EXTEND ssrindex PRINTED BY pr_ssrindex
INTERPRETED BY interp_index
| [ int_or_var(i) ] -> [ mk_index ~loc i ]
END
@@ -1949,7 +1949,7 @@ ARGUMENT EXTEND ssrexactarg TYPED AS ssrapplyarg PRINTED BY pr_ssraarg
END
let vmexacttac pf =
- Goal.nf_enter begin fun gl ->
+ Goal.enter begin fun gl ->
exact_no_check (EConstr.mkCast (pf, _vmcast, Tacmach.New.pf_concl gl))
end
diff --git a/plugins/ssr/ssrtacticals.ml b/plugins/ssr/ssrtacticals.ml
index 83581f3416..f12f9fac0f 100644
--- a/plugins/ssr/ssrtacticals.ml
+++ b/plugins/ssr/ssrtacticals.ml
@@ -14,7 +14,6 @@ open Names
open Constr
open Termops
open Tacmach
-open Locusops
open Ssrast
open Ssrcommon
@@ -82,8 +81,7 @@ let pf_clauseids gl gens clseq =
let hidden_clseq = function InHyps | InHypsSeq | InAllHyps -> true | _ -> false
-let settac id c = Tactics.letin_tac None (Name id) c None
-let posetac id cl = Proofview.V82.of_tactic (settac id cl nowhere)
+let posetac id cl = Proofview.V82.of_tactic (Tactics.pose_tac (Name id) cl)
let hidetacs clseq idhide cl0 =
if not (hidden_clseq clseq) then [] else
diff --git a/plugins/ssrmatching/plugin_base.dune b/plugins/ssrmatching/plugin_base.dune
new file mode 100644
index 0000000000..06f67c3774
--- /dev/null
+++ b/plugins/ssrmatching/plugin_base.dune
@@ -0,0 +1,5 @@
+(library
+ (name ssrmatching_plugin)
+ (public_name coq.plugins.ssrmatching)
+ (synopsis "Coq ssrmatching plugin")
+ (libraries coq.plugins.ltac))
diff --git a/plugins/ssrmatching/ssrmatching.ml b/plugins/ssrmatching/ssrmatching.ml
index 30a998c6ce..aadb4fe5f6 100644
--- a/plugins/ssrmatching/ssrmatching.ml
+++ b/plugins/ssrmatching/ssrmatching.ml
@@ -291,7 +291,10 @@ let unif_EQ_args env sigma pa a =
prof_unif_eq_args.profile (unif_EQ_args env sigma pa) a
;;
-let unif_HO env ise p c = Evarconv.the_conv_x env p c ise
+let unif_HO env ise p c =
+ try Evarconv.the_conv_x env p c ise
+ with Evarconv.UnableToUnify(ise, err) ->
+ raise Pretype_errors.(PretypeError(env,ise,CannotUnify(p,c,Some err)))
let unif_HO_args env ise0 pa i ca =
let n = Array.length pa in
@@ -1363,7 +1366,7 @@ let ssrpatterntac _ist arg gl =
let concl0 = pf_concl gl in
let concl0 = EConstr.Unsafe.to_constr concl0 in
let (t, uc), concl_x =
- fill_occ_pattern (Global.env()) sigma0 concl0 pat noindex 1 in
+ fill_occ_pattern (pf_env gl) sigma0 concl0 pat noindex 1 in
let t = EConstr.of_constr t in
let concl_x = EConstr.of_constr concl_x in
let gl, tty = pf_type_of gl t in
diff --git a/plugins/ssrmatching/ssrmatching.v b/plugins/ssrmatching/ssrmatching.v
index 829ee05e11..9a53e1dd1a 100644
--- a/plugins/ssrmatching/ssrmatching.v
+++ b/plugins/ssrmatching/ssrmatching.v
@@ -11,9 +11,11 @@ Reserved Notation "( a 'as' b )" (at level 0).
Reserved Notation "( a 'in' b 'in' c )" (at level 0).
Reserved Notation "( a 'as' b 'in' c )" (at level 0).
+Declare Scope ssrpatternscope.
+Delimit Scope ssrpatternscope with pattern.
+
(* Notation to define shortcuts for the "X in t" part of a pattern. *)
Notation "( X 'in' t )" := (_ : fun X => t) : ssrpatternscope.
-Delimit Scope ssrpatternscope with pattern.
(* Some shortcuts for recurrent "X in t" parts. *)
Notation RHS := (X in _ = X)%pattern.
diff --git a/plugins/syntax/ascii_syntax.ml b/plugins/syntax/ascii_syntax.ml
index 47a59ba631..53153198f9 100644
--- a/plugins/syntax/ascii_syntax.ml
+++ b/plugins/syntax/ascii_syntax.ml
@@ -83,8 +83,18 @@ let make_ascii_string n =
let uninterp_ascii_string (AnyGlobConstr r) = Option.map make_ascii_string (uninterp_ascii r)
+open Notation
+
+let at_declare_ml_module f x =
+ Mltop.declare_cache_obj (fun () -> f x) __coq_plugin_name
+
let _ =
- Notation.declare_string_interpreter "char_scope"
- (ascii_path,ascii_module)
- interp_ascii_string
- ([DAst.make @@ GRef (static_glob_Ascii,None)], uninterp_ascii_string, true)
+ let sc = "char_scope" in
+ register_string_interpretation sc (interp_ascii_string,uninterp_ascii_string);
+ at_declare_ml_module enable_prim_token_interpretation
+ { pt_local = false;
+ pt_scope = sc;
+ pt_interp_info = Uid sc;
+ pt_required = (ascii_path,ascii_module);
+ pt_refs = [static_glob_Ascii];
+ pt_in_match = true }
diff --git a/plugins/syntax/g_numeral.ml4 b/plugins/syntax/g_numeral.ml4
new file mode 100644
index 0000000000..55f61a58f9
--- /dev/null
+++ b/plugins/syntax/g_numeral.ml4
@@ -0,0 +1,38 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+DECLARE PLUGIN "numeral_notation_plugin"
+
+open Notation
+open Numeral
+open Pp
+open Names
+open Vernacinterp
+open Ltac_plugin
+open Stdarg
+open Pcoq.Prim
+
+let pr_numnot_option _ _ _ = function
+ | Nop -> mt ()
+ | Warning n -> str "(warning after " ++ str n ++ str ")"
+ | Abstract n -> str "(abstract after " ++ str n ++ str ")"
+
+ARGUMENT EXTEND numnotoption
+ PRINTED BY pr_numnot_option
+| [ ] -> [ Nop ]
+| [ "(" "warning" "after" bigint(waft) ")" ] -> [ Warning waft ]
+| [ "(" "abstract" "after" bigint(n) ")" ] -> [ Abstract n ]
+END
+
+VERNAC COMMAND EXTEND NumeralNotation CLASSIFIED AS SIDEFF
+ | [ "Numeral" "Notation" reference(ty) reference(f) reference(g) ":"
+ ident(sc) numnotoption(o) ] ->
+ [ vernac_numeral_notation (Locality.make_module_locality atts.locality) ty f g (Id.to_string sc) o ]
+END
diff --git a/plugins/syntax/int31_syntax.ml b/plugins/syntax/int31_syntax.ml
index f10f98e23b..e34a401c2c 100644
--- a/plugins/syntax/int31_syntax.ml
+++ b/plugins/syntax/int31_syntax.ml
@@ -96,10 +96,19 @@ let uninterp_int31 (AnyGlobConstr i) =
with Non_closed ->
None
+open Notation
+
+let at_declare_ml_module f x =
+ Mltop.declare_cache_obj (fun () -> f x) __coq_plugin_name
+
(* Actually declares the interpreter for int31 *)
-let _ = Notation.declare_numeral_interpreter int31_scope
- (int31_path, int31_module)
- interp_int31
- ([DAst.make (GRef (int31_construct, None))],
- uninterp_int31,
- true)
+
+let _ =
+ register_bignumeral_interpretation int31_scope (interp_int31,uninterp_int31);
+ at_declare_ml_module enable_prim_token_interpretation
+ { pt_local = false;
+ pt_scope = int31_scope;
+ pt_interp_info = Uid int31_scope;
+ pt_required = (int31_path,int31_module);
+ pt_refs = [int31_construct];
+ pt_in_match = true }
diff --git a/plugins/syntax/n_syntax.ml b/plugins/syntax/n_syntax.ml
deleted file mode 100644
index 0e202be47f..0000000000
--- a/plugins/syntax/n_syntax.ml
+++ /dev/null
@@ -1,81 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-open Pp
-open CErrors
-open Names
-open Bigint
-open Positive_syntax_plugin.Positive_syntax
-
-(* Poor's man DECLARE PLUGIN *)
-let __coq_plugin_name = "n_syntax_plugin"
-let () = Mltop.add_known_module __coq_plugin_name
-
-(**********************************************************************)
-(* Parsing N via scopes *)
-(**********************************************************************)
-
-open Globnames
-open Glob_term
-
-let binnums = ["Coq";"Numbers";"BinNums"]
-
-let make_dir l = DirPath.make (List.rev_map Id.of_string l)
-let make_path dir id = Libnames.make_path (make_dir dir) (Id.of_string id)
-
-(* TODO: temporary hack *)
-let make_kn dir id = Globnames.encode_mind dir id
-
-let n_kn = make_kn (make_dir binnums) (Id.of_string "N")
-let glob_n = IndRef (n_kn,0)
-let path_of_N0 = ((n_kn,0),1)
-let path_of_Npos = ((n_kn,0),2)
-let glob_N0 = ConstructRef path_of_N0
-let glob_Npos = ConstructRef path_of_Npos
-
-let n_path = make_path binnums "N"
-
-let n_of_binnat ?loc pos_or_neg n = DAst.make ?loc @@
- if not (Bigint.equal n zero) then
- GApp(DAst.make @@ GRef (glob_Npos,None), [pos_of_bignat ?loc n])
- else
- GRef(glob_N0, None)
-
-let error_negative ?loc =
- user_err ?loc ~hdr:"interp_N" (str "No negative numbers in type \"N\".")
-
-let n_of_int ?loc n =
- if is_pos_or_zero n then n_of_binnat ?loc true n
- else error_negative ?loc
-
-(**********************************************************************)
-(* Printing N via scopes *)
-(**********************************************************************)
-
-let bignat_of_n n = DAst.with_val (function
- | GApp (r, [a]) when is_gr r glob_Npos -> bignat_of_pos a
- | GRef (a,_) when GlobRef.equal a glob_N0 -> Bigint.zero
- | _ -> raise Non_closed_number
- ) n
-
-let uninterp_n (AnyGlobConstr p) =
- try Some (bignat_of_n p)
- with Non_closed_number -> None
-
-(************************************************************************)
-(* Declaring interpreters and uninterpreters for N *)
-
-let _ = Notation.declare_numeral_interpreter "N_scope"
- (n_path,binnums)
- n_of_int
- ([DAst.make @@ GRef (glob_N0, None);
- DAst.make @@ GRef (glob_Npos, None)],
- uninterp_n,
- true)
diff --git a/plugins/syntax/n_syntax_plugin.mlpack b/plugins/syntax/n_syntax_plugin.mlpack
deleted file mode 100644
index 4c56645f07..0000000000
--- a/plugins/syntax/n_syntax_plugin.mlpack
+++ /dev/null
@@ -1 +0,0 @@
-N_syntax
diff --git a/plugins/syntax/nat_syntax.ml b/plugins/syntax/nat_syntax.ml
deleted file mode 100644
index e158e0b516..0000000000
--- a/plugins/syntax/nat_syntax.ml
+++ /dev/null
@@ -1,85 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-
-(* Poor's man DECLARE PLUGIN *)
-let __coq_plugin_name = "nat_syntax_plugin"
-let () = Mltop.add_known_module __coq_plugin_name
-
-(* This file defines the printer for natural numbers in [nat] *)
-
-(*i*)
-open Pp
-open CErrors
-open Names
-open Glob_term
-open Bigint
-open Coqlib
-(*i*)
-
-(**********************************************************************)
-(* Parsing via scopes *)
-(* For example, (nat_of_string "3") is <<(S (S (S O)))>> *)
-
-let threshold = of_int 5000
-
-let warn_large_nat =
- CWarnings.create ~name:"large-nat" ~category:"numbers"
- (fun () -> strbrk "Stack overflow or segmentation fault happens when " ++
- strbrk "working with large numbers in nat (observed threshold " ++
- strbrk "may vary from 5000 to 70000 depending on your system " ++
- strbrk "limits and on the command executed).")
-
-let nat_of_int ?loc n =
- if is_pos_or_zero n then begin
- if less_than threshold n then warn_large_nat ();
- let ref_O = DAst.make ?loc @@ GRef (glob_O, None) in
- let ref_S = DAst.make ?loc @@ GRef (glob_S, None) in
- let rec mk_nat acc n =
- if n <> zero then
- mk_nat (DAst.make ?loc @@ GApp (ref_S, [acc])) (sub_1 n)
- else
- acc
- in
- mk_nat ref_O n
- end
- else
- user_err ?loc ~hdr:"nat_of_int"
- (str "Cannot interpret a negative number as a number of type nat")
-
-(************************************************************************)
-(* Printing via scopes *)
-
-exception Non_closed_number
-
-let rec int_of_nat x = DAst.with_val (function
- | GApp (r, [a]) ->
- begin match DAst.get r with
- | GRef (s,_) when GlobRef.equal s glob_S -> add_1 (int_of_nat a)
- | _ -> raise Non_closed_number
- end
- | GRef (z,_) when GlobRef.equal z glob_O -> zero
- | _ -> raise Non_closed_number
- ) x
-
-let uninterp_nat (AnyGlobConstr p) =
- try
- Some (int_of_nat p)
- with
- Non_closed_number -> None
-
-(************************************************************************)
-(* Declare the primitive parsers and printers *)
-
-let _ =
- Notation.declare_numeral_interpreter "nat_scope"
- (nat_path,datatypes_module_name)
- nat_of_int
- ([DAst.make @@ GRef (glob_S,None); DAst.make @@ GRef (glob_O,None)], uninterp_nat, true)
diff --git a/plugins/syntax/nat_syntax_plugin.mlpack b/plugins/syntax/nat_syntax_plugin.mlpack
deleted file mode 100644
index 39bdd62f47..0000000000
--- a/plugins/syntax/nat_syntax_plugin.mlpack
+++ /dev/null
@@ -1 +0,0 @@
-Nat_syntax
diff --git a/plugins/syntax/numeral.ml b/plugins/syntax/numeral.ml
new file mode 100644
index 0000000000..10a0af0b8f
--- /dev/null
+++ b/plugins/syntax/numeral.ml
@@ -0,0 +1,142 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+open Pp
+open Util
+open Names
+open Libnames
+open Globnames
+open Constrexpr
+open Constrexpr_ops
+open Notation
+
+(** * Numeral notation *)
+
+let warn_abstract_large_num_no_op =
+ CWarnings.create ~name:"abstract-large-number-no-op" ~category:"numbers"
+ (fun f ->
+ strbrk "The 'abstract after' directive has no effect when " ++
+ strbrk "the parsing function (" ++
+ Nametab.pr_global_env (Termops.vars_of_env (Global.env ())) f ++ strbrk ") targets an " ++
+ strbrk "option type.")
+
+let get_constructors ind =
+ let mib,oib = Global.lookup_inductive ind in
+ let mc = oib.Declarations.mind_consnames in
+ Array.to_list
+ (Array.mapi (fun j c -> ConstructRef (ind, j + 1)) mc)
+
+let q_z = qualid_of_string "Coq.Numbers.BinNums.Z"
+let q_positive = qualid_of_string "Coq.Numbers.BinNums.positive"
+let q_int = qualid_of_string "Coq.Init.Decimal.int"
+let q_uint = qualid_of_string "Coq.Init.Decimal.uint"
+let q_option = qualid_of_string "Coq.Init.Datatypes.option"
+
+let unsafe_locate_ind q =
+ match Nametab.locate q with
+ | IndRef i -> i
+ | _ -> raise Not_found
+
+let locate_ind q =
+ try unsafe_locate_ind q
+ with Not_found -> Nametab.error_global_not_found q
+
+let locate_z () =
+ try
+ Some { z_ty = unsafe_locate_ind q_z;
+ pos_ty = unsafe_locate_ind q_positive }
+ with Not_found -> None
+
+let locate_int () =
+ { uint = locate_ind q_uint;
+ int = locate_ind q_int }
+
+let has_type f ty =
+ let (sigma, env) = Pfedit.get_current_context () in
+ let c = mkCastC (mkRefC f, Glob_term.CastConv ty) in
+ try let _ = Constrintern.interp_constr env sigma c in true
+ with Pretype_errors.PretypeError _ -> false
+
+let type_error_to f ty loadZ =
+ CErrors.user_err
+ (pr_qualid f ++ str " should go from Decimal.int to " ++
+ pr_qualid ty ++ str " or (option " ++ pr_qualid ty ++ str ")." ++
+ fnl () ++ str "Instead of Decimal.int, the types Decimal.uint or Z could be used" ++
+ (if loadZ then str " (require BinNums first)." else str "."))
+
+let type_error_of g ty loadZ =
+ CErrors.user_err
+ (pr_qualid g ++ str " should go from " ++ pr_qualid ty ++
+ str " to Decimal.int or (option Decimal.int)." ++ fnl () ++
+ str "Instead of Decimal.int, the types Decimal.uint or Z could be used" ++
+ (if loadZ then str " (require BinNums first)." else str "."))
+
+let vernac_numeral_notation local ty f g scope opts =
+ let int_ty = locate_int () in
+ let z_pos_ty = locate_z () in
+ let tyc = Smartlocate.global_inductive_with_alias ty in
+ let to_ty = Smartlocate.global_with_alias f in
+ let of_ty = Smartlocate.global_with_alias g in
+ let cty = mkRefC ty in
+ let app x y = mkAppC (x,[y]) in
+ let cref q = mkRefC q in
+ let arrow x y =
+ mkProdC ([CAst.make Anonymous],Default Decl_kinds.Explicit, x, y)
+ in
+ let cZ = cref q_z in
+ let cint = cref q_int in
+ let cuint = cref q_uint in
+ let coption = cref q_option in
+ let opt r = app coption r in
+ let constructors = get_constructors tyc in
+ (* Check the type of f *)
+ let to_kind =
+ if has_type f (arrow cint cty) then Int int_ty, Direct
+ else if has_type f (arrow cint (opt cty)) then Int int_ty, Option
+ else if has_type f (arrow cuint cty) then UInt int_ty.uint, Direct
+ else if has_type f (arrow cuint (opt cty)) then UInt int_ty.uint, Option
+ else
+ match z_pos_ty with
+ | Some z_pos_ty ->
+ if has_type f (arrow cZ cty) then Z z_pos_ty, Direct
+ else if has_type f (arrow cZ (opt cty)) then Z z_pos_ty, Option
+ else type_error_to f ty false
+ | None -> type_error_to f ty true
+ in
+ (* Check the type of g *)
+ let of_kind =
+ if has_type g (arrow cty cint) then Int int_ty, Direct
+ else if has_type g (arrow cty (opt cint)) then Int int_ty, Option
+ else if has_type g (arrow cty cuint) then UInt int_ty.uint, Direct
+ else if has_type g (arrow cty (opt cuint)) then UInt int_ty.uint, Option
+ else
+ match z_pos_ty with
+ | Some z_pos_ty ->
+ if has_type g (arrow cty cZ) then Z z_pos_ty, Direct
+ else if has_type g (arrow cty (opt cZ)) then Z z_pos_ty, Option
+ else type_error_of g ty false
+ | None -> type_error_of g ty true
+ in
+ let o = { to_kind; to_ty; of_kind; of_ty;
+ num_ty = ty;
+ warning = opts }
+ in
+ (match opts, to_kind with
+ | Abstract _, (_, Option) -> warn_abstract_large_num_no_op o.to_ty
+ | _ -> ());
+ let i =
+ { pt_local = local;
+ pt_scope = scope;
+ pt_interp_info = NumeralNotation o;
+ pt_required = Nametab.path_of_global (IndRef tyc),[];
+ pt_refs = constructors;
+ pt_in_match = true }
+ in
+ enable_prim_token_interpretation i
diff --git a/stm/workerLoop.mli b/plugins/syntax/numeral.mli
index 37ec6dacca..f96b8321f8 100644
--- a/stm/workerLoop.mli
+++ b/plugins/syntax/numeral.mli
@@ -8,9 +8,10 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
-(* Default priority *)
-val async_proofs_worker_priority : CoqworkmgrApi.priority ref
+open Libnames
+open Vernacexpr
+open Notation
-val loop :
- (unit -> unit) -> Coqargs.coq_cmdopts -> string list ->
- Coqargs.coq_cmdopts * string list
+(** * Numeral notation *)
+
+val vernac_numeral_notation : locality_flag -> qualid -> qualid -> qualid -> Notation_term.scope_name -> numnot_option -> unit
diff --git a/plugins/syntax/numeral_notation_plugin.mlpack b/plugins/syntax/numeral_notation_plugin.mlpack
new file mode 100644
index 0000000000..f4d9cae3ff
--- /dev/null
+++ b/plugins/syntax/numeral_notation_plugin.mlpack
@@ -0,0 +1,2 @@
+Numeral
+G_numeral
diff --git a/plugins/syntax/plugin_base.dune b/plugins/syntax/plugin_base.dune
new file mode 100644
index 0000000000..bfdd480fe9
--- /dev/null
+++ b/plugins/syntax/plugin_base.dune
@@ -0,0 +1,35 @@
+(library
+ (name numeral_notation_plugin)
+ (public_name coq.plugins.numeral_notation)
+ (synopsis "Coq numeral notation plugin")
+ (modules g_numeral numeral)
+ (libraries coq.plugins.ltac))
+
+(library
+ (name r_syntax_plugin)
+ (public_name coq.plugins.r_syntax)
+ (synopsis "Coq syntax plugin: reals")
+ (modules r_syntax)
+ (libraries coq.vernac))
+
+(library
+ (name ascii_syntax_plugin)
+ (public_name coq.plugins.ascii_syntax)
+ (synopsis "Coq syntax plugin: ASCII")
+ (modules ascii_syntax)
+ (libraries coq.vernac))
+
+(library
+ (name string_syntax_plugin)
+ (public_name coq.plugins.string_syntax)
+ (synopsis "Coq syntax plugin: strings")
+ (modules string_syntax)
+ (libraries coq.plugins.ascii_syntax))
+
+(library
+ (name int31_syntax_plugin)
+ (public_name coq.plugins.int31_syntax)
+ (synopsis "Coq syntax plugin: int31")
+ (modules int31_syntax)
+ (libraries coq.vernac))
+
diff --git a/plugins/syntax/positive_syntax.ml b/plugins/syntax/positive_syntax.ml
deleted file mode 100644
index 0c82e47445..0000000000
--- a/plugins/syntax/positive_syntax.ml
+++ /dev/null
@@ -1,101 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-open Pp
-open CErrors
-open Util
-open Names
-open Bigint
-
-(* Poor's man DECLARE PLUGIN *)
-let __coq_plugin_name = "positive_syntax_plugin"
-let () = Mltop.add_known_module __coq_plugin_name
-
-exception Non_closed_number
-
-(**********************************************************************)
-(* Parsing positive via scopes *)
-(**********************************************************************)
-
-open Globnames
-open Glob_term
-
-let binnums = ["Coq";"Numbers";"BinNums"]
-
-let make_dir l = DirPath.make (List.rev_map Id.of_string l)
-let make_path dir id = Libnames.make_path (make_dir dir) (Id.of_string id)
-
-let positive_path = make_path binnums "positive"
-
-(* TODO: temporary hack *)
-let make_kn dir id = Globnames.encode_mind dir id
-
-let positive_kn = make_kn (make_dir binnums) (Id.of_string "positive")
-let glob_positive = IndRef (positive_kn,0)
-let path_of_xI = ((positive_kn,0),1)
-let path_of_xO = ((positive_kn,0),2)
-let path_of_xH = ((positive_kn,0),3)
-let glob_xI = ConstructRef path_of_xI
-let glob_xO = ConstructRef path_of_xO
-let glob_xH = ConstructRef path_of_xH
-
-let pos_of_bignat ?loc x =
- let ref_xI = DAst.make ?loc @@ GRef (glob_xI, None) in
- let ref_xH = DAst.make ?loc @@ GRef (glob_xH, None) in
- let ref_xO = DAst.make ?loc @@ GRef (glob_xO, None) in
- let rec pos_of x =
- match div2_with_rest x with
- | (q,false) -> DAst.make ?loc @@ GApp (ref_xO,[pos_of q])
- | (q,true) when not (Bigint.equal q zero) -> DAst.make ?loc @@ GApp (ref_xI,[pos_of q])
- | (q,true) -> ref_xH
- in
- pos_of x
-
-let error_non_positive ?loc =
- user_err ?loc ~hdr:"interp_positive"
- (str "Only strictly positive numbers in type \"positive\".")
-
-let interp_positive ?loc n =
- if is_strictly_pos n then pos_of_bignat ?loc n
- else error_non_positive ?loc
-
-(**********************************************************************)
-(* Printing positive via scopes *)
-(**********************************************************************)
-
-let is_gr c gr = match DAst.get c with
-| GRef (r, _) -> GlobRef.equal r gr
-| _ -> false
-
-let rec bignat_of_pos x = DAst.with_val (function
- | GApp (r ,[a]) when is_gr r glob_xO -> mult_2(bignat_of_pos a)
- | GApp (r ,[a]) when is_gr r glob_xI -> add_1(mult_2(bignat_of_pos a))
- | GRef (a, _) when GlobRef.equal a glob_xH -> Bigint.one
- | _ -> raise Non_closed_number
- ) x
-
-let uninterp_positive (AnyGlobConstr p) =
- try
- Some (bignat_of_pos p)
- with Non_closed_number ->
- None
-
-(************************************************************************)
-(* Declaring interpreters and uninterpreters for positive *)
-(************************************************************************)
-
-let _ = Notation.declare_numeral_interpreter "positive_scope"
- (positive_path,binnums)
- interp_positive
- ([DAst.make @@ GRef (glob_xI, None);
- DAst.make @@ GRef (glob_xO, None);
- DAst.make @@ GRef (glob_xH, None)],
- uninterp_positive,
- true)
diff --git a/plugins/syntax/positive_syntax_plugin.mlpack b/plugins/syntax/positive_syntax_plugin.mlpack
deleted file mode 100644
index ac8f3c425c..0000000000
--- a/plugins/syntax/positive_syntax_plugin.mlpack
+++ /dev/null
@@ -1 +0,0 @@
-Positive_syntax
diff --git a/plugins/syntax/r_syntax.ml b/plugins/syntax/r_syntax.ml
index 94aa143350..49497aef54 100644
--- a/plugins/syntax/r_syntax.ml
+++ b/plugins/syntax/r_syntax.ml
@@ -131,9 +131,19 @@ let uninterp_r (AnyGlobConstr p) =
with Non_closed_number ->
None
-let _ = Notation.declare_numeral_interpreter "R_scope"
- (r_path,["Coq";"Reals";"Rdefinitions"])
- r_of_int
- ([DAst.make @@ GRef (glob_IZR, None)],
- uninterp_r,
- false)
+open Notation
+
+let at_declare_ml_module f x =
+ Mltop.declare_cache_obj (fun () -> f x) __coq_plugin_name
+
+let r_scope = "R_scope"
+
+let _ =
+ register_bignumeral_interpretation r_scope (r_of_int,uninterp_r);
+ at_declare_ml_module enable_prim_token_interpretation
+ { pt_local = false;
+ pt_scope = r_scope;
+ pt_interp_info = Uid r_scope;
+ pt_required = (r_path,["Coq";"Reals";"Rdefinitions"]);
+ pt_refs = [glob_IZR];
+ pt_in_match = false }
diff --git a/plugins/syntax/string_syntax.ml b/plugins/syntax/string_syntax.ml
index c22869f4d6..7478c1e978 100644
--- a/plugins/syntax/string_syntax.ml
+++ b/plugins/syntax/string_syntax.ml
@@ -64,10 +64,18 @@ let uninterp_string (AnyGlobConstr r) =
with
Non_closed_string -> None
+open Notation
+
+let at_declare_ml_module f x =
+ Mltop.declare_cache_obj (fun () -> f x) __coq_plugin_name
+
let _ =
- Notation.declare_string_interpreter "string_scope"
- (string_path,["Coq";"Strings";"String"])
- interp_string
- ([DAst.make @@ GRef (static_glob_String,None);
- DAst.make @@ GRef (static_glob_EmptyString,None)],
- uninterp_string, true)
+ let sc = "string_scope" in
+ register_string_interpretation sc (interp_string,uninterp_string);
+ at_declare_ml_module enable_prim_token_interpretation
+ { pt_local = false;
+ pt_scope = sc;
+ pt_interp_info = Uid sc;
+ pt_required = (string_path,["Coq";"Strings";"String"]);
+ pt_refs = [static_glob_String; static_glob_EmptyString];
+ pt_in_match = true }
diff --git a/plugins/syntax/z_syntax.ml b/plugins/syntax/z_syntax.ml
deleted file mode 100644
index 2534162e36..0000000000
--- a/plugins/syntax/z_syntax.ml
+++ /dev/null
@@ -1,78 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-open Names
-open Bigint
-open Positive_syntax_plugin.Positive_syntax
-
-(* Poor's man DECLARE PLUGIN *)
-let __coq_plugin_name = "z_syntax_plugin"
-let () = Mltop.add_known_module __coq_plugin_name
-
-(**********************************************************************)
-(* Parsing Z via scopes *)
-(**********************************************************************)
-
-open Globnames
-open Glob_term
-
-let binnums = ["Coq";"Numbers";"BinNums"]
-
-let make_dir l = DirPath.make (List.rev_map Id.of_string l)
-let make_path dir id = Libnames.make_path (make_dir dir) (Id.of_string id)
-
-(* TODO: temporary hack *)
-let make_kn dir id = Globnames.encode_mind dir id
-
-let z_path = make_path binnums "Z"
-let z_kn = make_kn (make_dir binnums) (Id.of_string "Z")
-let glob_z = IndRef (z_kn,0)
-let path_of_ZERO = ((z_kn,0),1)
-let path_of_POS = ((z_kn,0),2)
-let path_of_NEG = ((z_kn,0),3)
-let glob_ZERO = ConstructRef path_of_ZERO
-let glob_POS = ConstructRef path_of_POS
-let glob_NEG = ConstructRef path_of_NEG
-
-let z_of_int ?loc n =
- if not (Bigint.equal n zero) then
- let sgn, n =
- if is_pos_or_zero n then glob_POS, n else glob_NEG, Bigint.neg n in
- DAst.make ?loc @@ GApp(DAst.make ?loc @@ GRef(sgn,None), [pos_of_bignat ?loc n])
- else
- DAst.make ?loc @@ GRef(glob_ZERO, None)
-
-(**********************************************************************)
-(* Printing Z via scopes *)
-(**********************************************************************)
-
-let bigint_of_z z = DAst.with_val (function
- | GApp (r, [a]) when is_gr r glob_POS -> bignat_of_pos a
- | GApp (r, [a]) when is_gr r glob_NEG -> Bigint.neg (bignat_of_pos a)
- | GRef (a, _) when GlobRef.equal a glob_ZERO -> Bigint.zero
- | _ -> raise Non_closed_number
- ) z
-
-let uninterp_z (AnyGlobConstr p) =
- try
- Some (bigint_of_z p)
- with Non_closed_number -> None
-
-(************************************************************************)
-(* Declaring interpreters and uninterpreters for Z *)
-
-let _ = Notation.declare_numeral_interpreter "Z_scope"
- (z_path,binnums)
- z_of_int
- ([DAst.make @@ GRef (glob_ZERO, None);
- DAst.make @@ GRef (glob_POS, None);
- DAst.make @@ GRef (glob_NEG, None)],
- uninterp_z,
- true)
diff --git a/plugins/syntax/z_syntax_plugin.mlpack b/plugins/syntax/z_syntax_plugin.mlpack
deleted file mode 100644
index 411260c04c..0000000000
--- a/plugins/syntax/z_syntax_plugin.mlpack
+++ /dev/null
@@ -1 +0,0 @@
-Z_syntax
diff --git a/plugins/xml/README b/plugins/xml/README
deleted file mode 100644
index 3128189929..0000000000
--- a/plugins/xml/README
+++ /dev/null
@@ -1,4 +0,0 @@
-The xml export plugin for Coq has been removed from the sources.
-A backward compatible plug-in will be provided as a third-party plugin.
-For more informations, contact
-Claudio Sacerdoti Coen <claudio.sacerdoticoen@unibo.it>.
diff --git a/pretyping/arguments_renaming.ml b/pretyping/arguments_renaming.ml
index 9d4badc60a..b8958ca944 100644
--- a/pretyping/arguments_renaming.ml
+++ b/pretyping/arguments_renaming.ml
@@ -21,7 +21,7 @@ module NamedDecl = Context.Named.Declaration
(*i*)
let name_table =
- Summary.ref (Refmap.empty : Name.t list Refmap.t)
+ Summary.ref (GlobRef.Map.empty : Name.t list GlobRef.Map.t)
~name:"rename-arguments"
type req =
@@ -29,7 +29,7 @@ type req =
| ReqGlobal of GlobRef.t * Name.t list
let load_rename_args _ (_, (_, (r, names))) =
- name_table := Refmap.add r names !name_table
+ name_table := GlobRef.Map.add r names !name_table
let cache_rename_args o = load_rename_args 1 o
@@ -68,7 +68,7 @@ let rename_arguments local r names =
let req = if local then ReqLocal else ReqGlobal (r, names) in
Lib.add_anonymous_leaf (inRenameArgs (req, (r, names)))
-let arguments_names r = Refmap.find r !name_table
+let arguments_names r = GlobRef.Map.find r !name_table
let rec rename_prod c = function
| [] -> c
diff --git a/pretyping/cases.ml b/pretyping/cases.ml
index ad33297f0a..37dd3708b3 100644
--- a/pretyping/cases.ml
+++ b/pretyping/cases.ml
@@ -35,7 +35,7 @@ open Evarsolve
open Evarconv
open Evd
open Context.Rel.Declaration
-open Ltac_pretype
+open GlobEnv
module RelDecl = Context.Rel.Declaration
module NamedDecl = Context.Named.Declaration
@@ -114,8 +114,10 @@ let rec relocate_index sigma n1 n2 k t =
(**********************************************************************)
(* Structures used in compiling pattern-matching *)
+let (!!) env = GlobEnv.env env
+
type 'a rhs =
- { rhs_env : env;
+ { rhs_env : GlobEnv.t;
rhs_vars : Id.Set.t;
avoid_ids : Id.Set.t;
it : 'a option}
@@ -247,16 +249,14 @@ let push_history_pattern n pci cont =
*)
type 'a pattern_matching_problem =
- { env : env;
- lvar : Ltac_pretype.ltac_var_map;
- evdref : evar_map ref;
+ { env : GlobEnv.t;
pred : constr;
tomatch : tomatch_stack;
history : pattern_continuation;
mat : 'a matrix;
caseloc : Loc.t option;
casestyle : case_style;
- typing_function: type_constraint -> env -> evar_map ref -> 'a option -> unsafe_judgment }
+ typing_function: type_constraint -> GlobEnv.t -> evar_map -> 'a option -> evar_map * unsafe_judgment }
(*--------------------------------------------------------------------------*
* A few functions to infer the inductive type from the patterns instead of *
@@ -281,30 +281,30 @@ let rec find_row_ind = function
| PatVar _ -> find_row_ind l
| PatCstr(c,_,_) -> Some (p.CAst.loc,c)
-let inductive_template evdref env tmloc ind =
- let indu = evd_comb1 (Evd.fresh_inductive_instance env) evdref ind in
+let inductive_template env sigma tmloc ind =
+ let sigma, indu = Evd.fresh_inductive_instance env sigma ind in
let arsign = inductive_alldecls_env env indu in
let indu = on_snd EInstance.make indu in
let hole_source i = match tmloc with
| Some loc -> Loc.tag ~loc @@ Evar_kinds.TomatchTypeParameter (ind,i)
| None -> Loc.tag @@ Evar_kinds.TomatchTypeParameter (ind,i) in
- let (_,evarl,_) =
+ let (sigma, _, evarl, _) =
List.fold_right
- (fun decl (subst,evarl,n) ->
+ (fun decl (sigma, subst, evarl, n) ->
match decl with
| LocalAssum (na,ty) ->
let ty = EConstr.of_constr ty in
let ty' = substl subst ty in
- let e = evd_comb1
- (Evarutil.new_evar env ~src:(hole_source n))
- evdref ty'
+ let sigma, e =
+ Evarutil.new_evar env ~src:(hole_source n)
+ sigma ty'
in
- (e::subst,e::evarl,n+1)
+ (sigma, e::subst,e::evarl,n+1)
| LocalDef (na,b,ty) ->
let b = EConstr.of_constr b in
- (substl subst b::subst,evarl,n+1))
- arsign ([],[],1) in
- applist (mkIndU indu,List.rev evarl)
+ (sigma, substl subst b::subst,evarl,n+1))
+ arsign (sigma, [], [], 1) in
+ sigma, applist (mkIndU indu,List.rev evarl)
let try_find_ind env sigma typ realnames =
let (IndType(indf,realargs) as ind) = find_rectype env sigma typ in
@@ -316,21 +316,24 @@ let try_find_ind env sigma typ realnames =
List.make (inductive_nrealdecls ind) Anonymous in
IsInd (typ,ind,names)
-let inh_coerce_to_ind evdref env loc ty tyi =
- let orig = !evdref in
- let expected_typ = inductive_template evdref env loc tyi in
+let inh_coerce_to_ind env sigma0 loc ty tyi =
+ let sigma, expected_typ = inductive_template env sigma0 loc tyi in
(* Try to refine the type with inductive information coming from the
constructor and renounce if not able to give more information *)
(* devrait être indifférent d'exiger leq ou pas puisque pour
un inductif cela doit être égal *)
- match cumul env !evdref expected_typ ty with
- | Some sigma -> evdref := sigma
- | None -> evdref := orig
+ match cumul env sigma expected_typ ty with
+ | Some sigma -> sigma
+ | None -> sigma0
let binding_vars_of_inductive sigma = function
| NotInd _ -> []
| IsInd (_,IndType(_,realargs),_) -> List.filter (isRel sigma) realargs
+let set_tomatch_realnames names = function
+ | NotInd _ as t -> t
+ | IsInd (typ,ind,_) -> IsInd (typ,ind,names)
+
let extract_inductive_data env sigma decl =
match decl with
| LocalAssum (_,t) ->
@@ -342,74 +345,73 @@ let extract_inductive_data env sigma decl =
| LocalDef (_,_,t) ->
(NotInd (None, t), [])
-let unify_tomatch_with_patterns evdref env loc typ pats realnames =
+let unify_tomatch_with_patterns env sigma loc typ pats realnames =
match find_row_ind pats with
- | None -> NotInd (None,typ)
+ | None -> sigma, NotInd (None,typ)
| Some (_,(ind,_)) ->
- inh_coerce_to_ind evdref env loc typ ind;
- try try_find_ind env !evdref typ realnames
- with Not_found -> NotInd (None,typ)
+ let sigma = inh_coerce_to_ind env sigma loc typ ind in
+ try sigma, try_find_ind env sigma typ realnames
+ with Not_found -> sigma, NotInd (None,typ)
-let find_tomatch_tycon evdref env loc = function
+let find_tomatch_tycon env sigma loc = function
(* Try if some 'in I ...' is present and can be used as a constraint *)
| Some {CAst.v=(ind,realnal)} ->
- mk_tycon (inductive_template evdref env loc ind),Some (List.rev realnal)
+ let sigma, tycon = inductive_template env sigma loc ind in
+ sigma, mk_tycon tycon, Some (List.rev realnal)
| None ->
- empty_tycon,None
+ sigma, empty_tycon, None
-let make_return_predicate_ltac_lvar sigma na tm c lvar =
+let make_return_predicate_ltac_lvar env sigma na tm c =
+ (* If we have an [x as x return ...] clause and [x] expands to [c],
+ we have to update the status of [x] in the substitution:
+ - if [c] is a variable [id'], then [x] should now become [id']
+ - otherwise, [x] should be hidden *)
match na, DAst.get tm with
| Name id, (GVar id' | GRef (Globnames.VarRef id', _)) when Id.equal id id' ->
- if Id.Map.mem id lvar.ltac_genargs then
- let ltac_genargs = Id.Map.remove id lvar.ltac_genargs in
- let ltac_idents = match kind sigma c with
- | Var id' -> Id.Map.add id id' lvar.ltac_idents
- | _ -> lvar.ltac_idents in
- { lvar with ltac_genargs; ltac_idents }
- else lvar
- | _ -> lvar
-
-let ltac_interp_realnames lvar = function
- | t, IsInd (ty,ind,realnal) -> t, IsInd (ty,ind,List.map (ltac_interp_name lvar) realnal)
- | _ as x -> x
+ let expansion = match kind sigma c with
+ | Var id' -> Name id'
+ | _ -> Anonymous in
+ GlobEnv.hide_variable env expansion id
+ | _ -> env
let is_patvar pat =
match DAst.get pat with
| PatVar _ -> true
| _ -> false
-let coerce_row typing_fun evdref env lvar pats (tomatch,(na,indopt)) =
+let coerce_row typing_fun env sigma pats (tomatch,(na,indopt)) =
let loc = loc_of_glob_constr tomatch in
- let tycon,realnames = find_tomatch_tycon evdref env loc indopt in
- let j = typing_fun tycon env evdref !lvar tomatch in
- let j = evd_comb1 (Coercion.inh_coerce_to_base ?loc:(loc_of_glob_constr tomatch) env) evdref j in
- let typ = nf_evar !evdref j.uj_type in
- lvar := make_return_predicate_ltac_lvar !evdref na tomatch j.uj_val !lvar;
- let t =
- if realnames = None && pats <> [] && List.for_all is_patvar pats then NotInd (None,typ) else
- try try_find_ind env !evdref typ realnames
+ let sigma, tycon, realnames = find_tomatch_tycon !!env sigma loc indopt in
+ let sigma, j = typing_fun tycon env sigma tomatch in
+ let sigma, j = Coercion.inh_coerce_to_base ?loc:(loc_of_glob_constr tomatch) !!env sigma j in
+ let typ = nf_evar sigma j.uj_type in
+ let env = make_return_predicate_ltac_lvar env sigma na tomatch j.uj_val in
+ let sigma, t =
+ if realnames = None && pats <> [] && List.for_all is_patvar pats then
+ sigma, NotInd (None,typ)
+ else
+ try sigma, try_find_ind !!env sigma typ realnames
with Not_found ->
- unify_tomatch_with_patterns evdref env loc typ pats realnames in
- (j.uj_val,t)
+ unify_tomatch_with_patterns !!env sigma loc typ pats realnames
+ in
+ ((env, sigma), (j.uj_val,t))
-let coerce_to_indtype typing_fun evdref env lvar matx tomatchl =
+let coerce_to_indtype typing_fun env sigma matx tomatchl =
let pats = List.map (fun r -> r.patterns) matx in
let matx' = match matrix_transpose pats with
| [] -> List.map (fun _ -> []) tomatchl (* no patterns at all *)
| m -> m in
- let lvar = ref lvar in
- let tms = List.map2 (coerce_row typing_fun evdref env lvar) matx' tomatchl in
- let tms = List.map (ltac_interp_realnames !lvar) tms in
- !lvar,tms
+ let (env, sigma), tms = List.fold_left2_map (fun (env, sigma) -> coerce_row typing_fun env sigma) (env, sigma) matx' tomatchl in
+ env, sigma, tms
(************************************************************************)
(* Utils *)
-let mkExistential env ?(src=(Loc.tag Evar_kinds.InternalHole)) evdref =
- let (e, u) = evd_comb1 (new_type_evar env ~src:src) evdref univ_flexible_alg in
- e
+let mkExistential ?(src=(Loc.tag Evar_kinds.InternalHole)) env sigma =
+ let sigma, (e, u) = new_type_evar env sigma ~src:src univ_flexible_alg in
+ sigma, e
-let adjust_tomatch_to_pattern pb ((current,typ),deps,dep) =
+let adjust_tomatch_to_pattern sigma pb ((current,typ),deps,dep) =
(* Ideally, we could find a common inductive type to which both the
term to match and the patterns coerce *)
(* In practice, we coerce the term to match if it is not already an
@@ -418,26 +420,27 @@ let adjust_tomatch_to_pattern pb ((current,typ),deps,dep) =
let typ,names =
match typ with IsInd(t,_,names) -> t,Some names | NotInd(_,t) -> t,None in
let tmtyp =
- try try_find_ind pb.env !(pb.evdref) typ names
+ try try_find_ind !!(pb.env) sigma typ names
with Not_found -> NotInd (None,typ) in
match tmtyp with
| NotInd (None,typ) ->
let tm1 = List.map (fun eqn -> List.hd eqn.patterns) pb.mat in
(match find_row_ind tm1 with
- | None -> (current,tmtyp)
+ | None -> sigma, (current, tmtyp)
| Some (_,(ind,_)) ->
- let indt = inductive_template pb.evdref pb.env None ind in
- let current =
- if List.is_empty deps && isEvar !(pb.evdref) typ then
+ let sigma, indt = inductive_template !!(pb.env) sigma None ind in
+ let sigma, current =
+ if List.is_empty deps && isEvar sigma typ then
(* Don't insert coercions if dependent; only solve evars *)
- let () = Option.iter ((:=) pb.evdref) (cumul pb.env !(pb.evdref) indt typ) in
- current
+ match cumul !!(pb.env) sigma indt typ with
+ | None -> sigma, current
+ | Some sigma -> sigma, current
else
- (evd_comb2 (Coercion.inh_conv_coerce_to true pb.env)
- pb.evdref (make_judge current typ) indt).uj_val in
- let sigma = !(pb.evdref) in
- (current,try_find_ind pb.env sigma indt names))
- | _ -> (current,tmtyp)
+ let sigma, j = Coercion.inh_conv_coerce_to true !!(pb.env) sigma (make_judge current typ) indt in
+ sigma, j.uj_val
+ in
+ sigma, (current, try_find_ind !!(pb.env) sigma indt names))
+ | _ -> sigma, (current, tmtyp)
let type_of_tomatch = function
| IsInd (t,_,_) -> t
@@ -466,10 +469,10 @@ let remove_current_pattern eqn =
alias_stack = alias_of_pat pat :: eqn.alias_stack }
| [] -> anomaly (Pp.str "Empty list of patterns.")
-let push_current_pattern (cur,ty) eqn =
+let push_current_pattern sigma (cur,ty) eqn =
match eqn.patterns with
| pat::pats ->
- let rhs_env = push_rel (LocalDef (alias_of_pat pat,cur,ty)) eqn.rhs.rhs_env in
+ let _,rhs_env = push_rel sigma (LocalDef (alias_of_pat pat,cur,ty)) eqn.rhs.rhs_env in
{ eqn with
rhs = { eqn.rhs with rhs_env = rhs_env };
patterns = pats }
@@ -739,7 +742,7 @@ let merge_name get_name obj = function
let merge_names get_name = List.map2 (merge_name get_name)
-let get_names env sigma sign eqns =
+let get_names avoid env sigma sign eqns =
let names1 = List.make (Context.Rel.length sign) Anonymous in
(* If any, we prefer names used in pats, from top to bottom *)
let names2,aliasname =
@@ -752,7 +755,7 @@ let get_names env sigma sign eqns =
avoiding conflicts with user ids *)
let allvars =
List.fold_left (fun l (_,_,eqn) -> Id.Set.union l eqn.rhs.avoid_ids)
- Id.Set.empty eqns in
+ avoid eqns in
let names3,_ =
List.fold_left2
(fun (l,avoid) d na ->
@@ -774,7 +777,7 @@ let get_names env sigma sign eqns =
let recover_initial_subpattern_names = List.map2 RelDecl.set_name
-let recover_and_adjust_alias_names names sign =
+let recover_and_adjust_alias_names (_,avoid) names sign =
let rec aux = function
| [],[] ->
[]
@@ -786,31 +789,31 @@ let recover_and_adjust_alias_names names sign =
in
List.split (aux (names,sign))
-let push_rels_eqn sign eqn =
+let push_rels_eqn sigma sign eqn =
{eqn with
- rhs = {eqn.rhs with rhs_env = push_rel_context sign eqn.rhs.rhs_env} }
+ rhs = {eqn.rhs with rhs_env = snd (push_rel_context sigma sign eqn.rhs.rhs_env) } }
-let push_rels_eqn_with_names sign eqn =
+let push_rels_eqn_with_names sigma sign eqn =
let subpats = List.rev (List.firstn (List.length sign) eqn.patterns) in
let subpatnames = List.map alias_of_pat subpats in
let sign = recover_initial_subpattern_names subpatnames sign in
- push_rels_eqn sign eqn
+ push_rels_eqn sigma sign eqn
-let push_generalized_decl_eqn env n decl eqn =
+let push_generalized_decl_eqn env sigma n decl eqn =
match RelDecl.get_name decl with
| Anonymous ->
- push_rels_eqn [decl] eqn
+ push_rels_eqn sigma [decl] eqn
| Name _ ->
- push_rels_eqn [RelDecl.set_name (RelDecl.get_name (Environ.lookup_rel n eqn.rhs.rhs_env)) decl] eqn
+ push_rels_eqn sigma [RelDecl.set_name (RelDecl.get_name (Environ.lookup_rel n !!(eqn.rhs.rhs_env))) decl] eqn
let drop_alias_eqn eqn =
{ eqn with alias_stack = List.tl eqn.alias_stack }
-let push_alias_eqn alias eqn =
+let push_alias_eqn sigma alias eqn =
let aliasname = List.hd eqn.alias_stack in
let eqn = drop_alias_eqn eqn in
let alias = RelDecl.set_name aliasname alias in
- push_rels_eqn [alias] eqn
+ push_rels_eqn sigma [alias] eqn
(**********************************************************************)
(* Functions to deal with elimination predicate *)
@@ -958,7 +961,7 @@ let rec extract_predicate ccl = function
ccl
let abstract_predicate env sigma indf cur realargs (names,na) tms ccl =
- let sign = make_arity_signature env sigma true indf in
+ let sign = make_arity_signature !!env sigma true indf in
(* n is the number of real args + 1 (+ possible let-ins in sign) *)
let n = List.length sign in
(* Before abstracting we generalize over cur and on those realargs *)
@@ -979,7 +982,7 @@ let abstract_predicate env sigma indf cur realargs (names,na) tms ccl =
let pred = extract_predicate ccl tms in
(* Build the predicate properly speaking *)
let sign = List.map2 set_name (na::names) sign in
- it_mkLambda_or_LetIn_name env sigma pred sign
+ it_mkLambda_or_LetIn_name !!env sigma pred sign
(* [expand_arg] is used by [specialize_predicate]
if Yk denotes [Xk;xk] or [Xk],
@@ -1010,7 +1013,7 @@ let add_assert_false_case pb tomatch =
eqn_loc = None;
used = ref false } ]
-let adjust_impossible_cases pb pred tomatch submat =
+let adjust_impossible_cases sigma pb pred tomatch submat =
match submat with
| [] ->
(** FIXME: This breaks if using evar-insensitive primitives. In particular,
@@ -1018,17 +1021,20 @@ let adjust_impossible_cases pb pred tomatch submat =
evar. See e.g. first definition of test for bug #3388. *)
let pred = EConstr.Unsafe.to_constr pred in
begin match Constr.kind pred with
- | Evar (evk,_) when snd (evar_source evk !(pb.evdref)) == Evar_kinds.ImpossibleCase ->
- if not (Evd.is_defined !(pb.evdref) evk) then begin
- let default = evd_comb0 use_unit_judge pb.evdref in
- pb.evdref := Evd.define evk default.uj_type !(pb.evdref)
- end;
- add_assert_false_case pb tomatch
+ | Evar (evk,_) when snd (evar_source evk sigma) == Evar_kinds.ImpossibleCase ->
+ let sigma =
+ if not (Evd.is_defined sigma evk) then
+ let sigma, default = use_unit_judge sigma in
+ let sigma = Evd.define evk default.uj_type sigma in
+ sigma
+ else sigma
+ in
+ sigma, add_assert_false_case pb tomatch
| _ ->
- submat
+ sigma, submat
end
| _ ->
- submat
+ sigma, submat
(*****************************************************************************)
(* Let pred = PI [X;x:I(X)]. PI tms. P be a typing predicate for the *)
@@ -1085,9 +1091,9 @@ let specialize_predicate newtomatchs (names,depna) arsign cs tms ccl =
(* We finally get gamma,x'1..x'n,x |- [X1;x1:I(X1)]..[Xn;xn:I(Xn)]pred'''*)
snd (List.fold_left (expand_arg tms) (1,ccl''') newtomatchs)
-let find_predicate loc env evdref p current (IndType (indf,realargs)) dep tms =
- let pred = abstract_predicate env !evdref indf current realargs dep tms p in
- (pred, whd_betaiota !evdref
+let find_predicate loc env sigma p current (IndType (indf,realargs)) dep tms =
+ let pred = abstract_predicate env sigma indf current realargs dep tms p in
+ (pred, whd_betaiota sigma
(applist (pred, realargs@[current])))
(* Take into account that a type has been discovered to be inductive, leading
@@ -1208,7 +1214,7 @@ let first_clause_irrefutable env = function
let group_equations pb ind current cstrs mat =
let mat =
- if first_clause_irrefutable pb.env mat then [List.hd mat] else mat in
+ if first_clause_irrefutable !!(pb.env) mat then [List.hd mat] else mat in
let brs = Array.make (Array.length cstrs) [] in
let only_default = ref None in
let _ =
@@ -1216,7 +1222,7 @@ let group_equations pb ind current cstrs mat =
(fun eqn () ->
let rest = remove_current_pattern eqn in
let pat = current_pattern eqn in
- match DAst.get (check_and_adjust_constructor pb.env ind cstrs pat) with
+ match DAst.get (check_and_adjust_constructor !!(pb.env) ind cstrs pat) with
| PatVar name ->
(* This is a default clause that we expand *)
for i=1 to Array.length cstrs do
@@ -1234,34 +1240,34 @@ let group_equations pb ind current cstrs mat =
(* Here starts the pattern-matching compilation algorithm *)
(* Abstracting over dependent subterms to match *)
-let rec generalize_problem names pb = function
+let rec generalize_problem names sigma pb = function
| [] -> pb, []
| i::l ->
- let pb',deps = generalize_problem names pb l in
- let d = map_constr (lift i) (lookup_rel i pb.env) in
+ let pb',deps = generalize_problem names sigma pb l in
+ let d = map_constr (lift i) (lookup_rel i !!(pb.env)) in
begin match d with
| LocalDef (Anonymous,_,_) -> pb', deps
| _ ->
(* for better rendering *)
- let d = RelDecl.map_type (fun c -> whd_betaiota !(pb.evdref) c) d in
+ let d = RelDecl.map_type (fun c -> whd_betaiota sigma c) d in
let tomatch = lift_tomatch_stack 1 pb'.tomatch in
- let tomatch = relocate_index_tomatch !(pb.evdref) (i+1) 1 tomatch in
+ let tomatch = relocate_index_tomatch sigma (i+1) 1 tomatch in
{ pb' with
tomatch = Abstract (i,d) :: tomatch;
- pred = generalize_predicate !(pb'.evdref) names i d pb'.tomatch pb'.pred },
+ pred = generalize_predicate sigma names i d pb'.tomatch pb'.pred },
i::deps
end
(* No more patterns: typing the right-hand side of equations *)
-let build_leaf pb =
+let build_leaf sigma pb =
let rhs = extract_rhs pb in
- let j = pb.typing_function (mk_tycon pb.pred) rhs.rhs_env pb.evdref rhs.it in
- j_nf_evar !(pb.evdref) j
+ let sigma, j = pb.typing_function (mk_tycon pb.pred) rhs.rhs_env sigma rhs.it in
+ sigma, j_nf_evar sigma j
(* Build the sub-pattern-matching problem for a given branch "C x1..xn as x" *)
(* spiwack: the [initial] argument keeps track whether the branch is a
toplevel branch ([true]) or a deep one ([false]). *)
-let build_branch initial current realargs deps (realnames,curname) pb arsign eqns const_info =
+let build_branch initial current realargs deps (realnames,curname) sigma pb arsign eqns const_info =
(* We remember that we descend through constructor C *)
let history =
push_history_pattern const_info.cs_nargs (fst const_info.cs_cstr) pb.history in
@@ -1271,7 +1277,7 @@ let build_branch initial current realargs deps (realnames,curname) pb arsign eqn
(* that had matched constructor C *)
let cs_args = const_info.cs_args in
let cs_args = List.map (fun d -> map_rel_decl EConstr.of_constr d) cs_args in
- let names,aliasname = get_names pb.env !(pb.evdref) cs_args eqns in
+ let names,aliasname = get_names (GlobEnv.vars_of_env pb.env) !!(pb.env) sigma cs_args eqns in
let typs = List.map2 RelDecl.set_name names cs_args
in
@@ -1279,7 +1285,7 @@ let build_branch initial current realargs deps (realnames,curname) pb arsign eqn
(* This is a bit too strong I think, in the sense that what we would *)
(* really like is to have beta-iota reduction only at the positions where *)
(* parameters are substituted *)
- let typs = List.map (map_type (nf_betaiota pb.env !(pb.evdref))) typs in
+ let typs = List.map (map_type (nf_betaiota !!(pb.env) sigma)) typs in
(* We build the matrix obtained by expanding the matching on *)
(* "C x1..xn as x" followed by a residual matching on eqn into *)
@@ -1291,17 +1297,17 @@ let build_branch initial current realargs deps (realnames,curname) pb arsign eqn
let typs' =
List.map_i (fun i d -> (mkRel i, map_constr (lift i) d)) 1 typs in
- let extenv = push_rel_context typs pb.env in
+ let typs,extenv = push_rel_context sigma typs pb.env in
let typs' =
List.map (fun (c,d) ->
- (c,extract_inductive_data extenv !(pb.evdref) d,d)) typs' in
+ (c,extract_inductive_data !!extenv sigma d,d)) typs' in
(* We compute over which of x(i+1)..xn and x matching on xi will need a *)
(* generalization *)
let dep_sign =
- find_dependencies_signature !(pb.evdref)
- (dependencies_in_rhs !(pb.evdref) const_info.cs_nargs current pb.tomatch eqns)
+ find_dependencies_signature sigma
+ (dependencies_in_rhs sigma const_info.cs_nargs current pb.tomatch eqns)
(List.rev typs') in
(* The dependent term to subst in the types of the remaining UnPushed
@@ -1317,13 +1323,13 @@ let build_branch initial current realargs deps (realnames,curname) pb arsign eqn
(* Do the specialization for terms to match *)
let tomatch = List.fold_right2 (fun par arg tomatch ->
- match EConstr.kind !(pb.evdref) par with
- | Rel i -> replace_tomatch !(pb.evdref) (i+const_info.cs_nargs) arg tomatch
+ match EConstr.kind sigma par with
+ | Rel i -> replace_tomatch sigma (i+const_info.cs_nargs) arg tomatch
| _ -> tomatch) (current::realargs) (ci::cirealargs)
(lift_tomatch_stack const_info.cs_nargs pb.tomatch) in
let pred_is_not_dep =
- noccur_predicate_between !(pb.evdref) 1 (List.length realnames + 1) pb.pred tomatch in
+ noccur_predicate_between sigma 1 (List.length realnames + 1) pb.pred tomatch in
let typs' =
List.map2
@@ -1357,20 +1363,20 @@ let build_branch initial current realargs deps (realnames,curname) pb arsign eqn
let tomatch = List.rev_append (alias :: currents) tomatch in
- let submat = adjust_impossible_cases pb pred tomatch submat in
+ let sigma, submat = adjust_impossible_cases sigma pb pred tomatch submat in
let () = match submat with
| [] ->
- raise_pattern_matching_error (pb.env, Evd.empty, NonExhaustive (complete_history history))
+ raise_pattern_matching_error (!!(pb.env), Evd.empty, NonExhaustive (complete_history history))
| _ -> ()
in
- typs,
+ sigma, typs,
{ pb with
env = extenv;
tomatch = tomatch;
pred = pred;
history = history;
- mat = List.map (push_rels_eqn_with_names typs) submat }
+ mat = List.map (push_rels_eqn_with_names sigma typs) submat }
(**********************************************************************
INVARIANT:
@@ -1385,127 +1391,130 @@ let build_branch initial current realargs deps (realnames,curname) pb arsign eqn
(**********************************************************************)
(* Main compiling descent *)
-let rec compile pb =
+let rec compile sigma pb =
match pb.tomatch with
- | Pushed cur :: rest -> match_current { pb with tomatch = rest } cur
- | Alias (initial,x) :: rest -> compile_alias initial pb x rest
- | NonDepAlias :: rest -> compile_non_dep_alias pb rest
- | Abstract (i,d) :: rest -> compile_generalization pb i d rest
- | [] -> build_leaf pb
+ | Pushed cur :: rest -> match_current sigma { pb with tomatch = rest } cur
+ | Alias (initial,x) :: rest -> compile_alias initial sigma pb x rest
+ | NonDepAlias :: rest -> compile_non_dep_alias sigma pb rest
+ | Abstract (i,d) :: rest -> compile_generalization sigma pb i d rest
+ | [] -> build_leaf sigma pb
(* Case splitting *)
-and match_current pb (initial,tomatch) =
- let tm = adjust_tomatch_to_pattern pb tomatch in
+and match_current sigma pb (initial,tomatch) =
+ let sigma, tm = adjust_tomatch_to_pattern sigma pb tomatch in
let pb,tomatch = adjust_predicate_from_tomatch tomatch tm pb in
let ((current,typ),deps,dep) = tomatch in
match typ with
| NotInd (_,typ) ->
- check_all_variables pb.env !(pb.evdref) typ pb.mat;
- compile_all_variables initial tomatch pb
+ check_all_variables !!(pb.env) sigma typ pb.mat;
+ compile_all_variables initial tomatch sigma pb
| IsInd (_,(IndType(indf,realargs) as indt),names) ->
let mind,_ = dest_ind_family indf in
- let mind = Tacred.check_privacy pb.env mind in
- let cstrs = get_constructors pb.env indf in
- let arsign, _ = get_arity pb.env indf in
+ let mind = Tacred.check_privacy !!(pb.env) mind in
+ let cstrs = get_constructors !!(pb.env) indf in
+ let arsign, _ = get_arity !!(pb.env) indf in
let eqns,onlydflt = group_equations pb (fst mind) current cstrs pb.mat in
let no_cstr = Int.equal (Array.length cstrs) 0 in
if (not no_cstr || not (List.is_empty pb.mat)) && onlydflt then
- compile_all_variables initial tomatch pb
+ compile_all_variables initial tomatch sigma pb
else
(* We generalize over terms depending on current term to match *)
- let pb,deps = generalize_problem (names,dep) pb deps in
+ let pb,deps = generalize_problem (names,dep) sigma pb deps in
(* We compile branches *)
- let brvals = Array.map2 (compile_branch initial current realargs (names,dep) deps pb arsign) eqns cstrs in
+ let fold_br sigma eqn cstr =
+ compile_branch initial current realargs (names,dep) deps sigma pb arsign eqn cstr
+ in
+ let sigma, brvals = Array.fold_left2_map fold_br sigma eqns cstrs in
(* We build the (elementary) case analysis *)
- let depstocheck = current::binding_vars_of_inductive !(pb.evdref) typ in
+ let depstocheck = current::binding_vars_of_inductive sigma typ in
let brvals,tomatch,pred,inst =
- postprocess_dependencies !(pb.evdref) depstocheck
+ postprocess_dependencies sigma depstocheck
brvals pb.tomatch pb.pred deps cstrs in
let brvals = Array.map (fun (sign,body) ->
- let sign = List.map (map_name (ltac_interp_name pb.lvar)) sign in
it_mkLambda_or_LetIn body sign) brvals in
let (pred,typ) =
- find_predicate pb.caseloc pb.env pb.evdref
+ find_predicate pb.caseloc pb.env sigma
pred current indt (names,dep) tomatch in
- let ci = make_case_info pb.env (fst mind) pb.casestyle in
- let pred = nf_betaiota pb.env !(pb.evdref) pred in
+ let ci = make_case_info !!(pb.env) (fst mind) pb.casestyle in
+ let pred = nf_betaiota !!(pb.env) sigma pred in
let case =
- make_case_or_project pb.env !(pb.evdref) indf ci pred current brvals
+ make_case_or_project !!(pb.env) sigma indf ci pred current brvals
in
- let _ = Evarutil.evd_comb1 (Typing.type_of pb.env) pb.evdref pred in
- Typing.check_allowed_sort pb.env !(pb.evdref) mind current pred;
- { uj_val = applist (case, inst);
- uj_type = prod_applist !(pb.evdref) typ inst }
+ let sigma, _ = Typing.type_of !!(pb.env) sigma pred in
+ Typing.check_allowed_sort !!(pb.env) sigma mind current pred;
+ sigma, { uj_val = applist (case, inst);
+ uj_type = prod_applist sigma typ inst }
(* Building the sub-problem when all patterns are variables. Case
where [current] is an intially pushed term. *)
-and shift_problem ((current,t),_,na) pb =
+and shift_problem ((current,t),_,na) sigma pb =
let ty = type_of_tomatch t in
let tomatch = lift_tomatch_stack 1 pb.tomatch in
- let pred = specialize_predicate_var (current,t,na) pb.env pb.tomatch pb.pred in
+ let pred = specialize_predicate_var (current,t,na) !!(pb.env) pb.tomatch pb.pred in
+ let env = Name.fold_left (fun env id -> hide_variable env Anonymous id) pb.env na in
let pb =
{ pb with
- env = push_rel (LocalDef (na,current,ty)) pb.env;
+ env = snd (push_rel sigma (LocalDef (na,current,ty)) env);
tomatch = tomatch;
pred = lift_predicate 1 pred tomatch;
history = pop_history pb.history;
- mat = List.map (push_current_pattern (current,ty)) pb.mat } in
- let j = compile pb in
- { uj_val = subst1 current j.uj_val;
+ mat = List.map (push_current_pattern sigma (current,ty)) pb.mat } in
+ let sigma, j = compile sigma pb in
+ sigma, { uj_val = subst1 current j.uj_val;
uj_type = subst1 current j.uj_type }
(* Building the sub-problem when all patterns are variables,
non-initial case. Variables which appear as subterms of constructor
are already introduced in the context, we avoid creating aliases to
themselves by treating this case specially. *)
-and pop_problem ((current,t),_,na) pb =
- let pred = specialize_predicate_var (current,t,na) pb.env pb.tomatch pb.pred in
+and pop_problem ((current,t),_,na) sigma pb =
+ let pred = specialize_predicate_var (current,t,na) !!(pb.env) pb.tomatch pb.pred in
let pb =
{ pb with
pred = pred;
history = pop_history pb.history;
mat = List.map push_noalias_current_pattern pb.mat } in
- compile pb
+ compile sigma pb
(* Building the sub-problem when all patterns are variables. *)
-and compile_all_variables initial cur pb =
- if initial then shift_problem cur pb
- else pop_problem cur pb
+and compile_all_variables initial cur sigma pb =
+ if initial then shift_problem cur sigma pb
+ else pop_problem cur sigma pb
(* Building the sub-problem when all patterns are variables *)
-and compile_branch initial current realargs names deps pb arsign eqns cstr =
- let sign, pb = build_branch initial current realargs deps names pb arsign eqns cstr in
- sign, (compile pb).uj_val
+and compile_branch initial current realargs names deps sigma pb arsign eqns cstr =
+ let sigma, sign, pb = build_branch initial current realargs deps names sigma pb arsign eqns cstr in
+ let sigma, j = compile sigma pb in
+ sigma, (sign, j.uj_val)
(* Abstract over a declaration before continuing splitting *)
-and compile_generalization pb i d rest =
+and compile_generalization sigma pb i d rest =
let pb =
{ pb with
- env = push_rel d pb.env;
+ env = snd (push_rel sigma d pb.env);
tomatch = rest;
- mat = List.map (push_generalized_decl_eqn pb.env i d) pb.mat } in
- let j = compile pb in
- { uj_val = mkLambda_or_LetIn d j.uj_val;
+ mat = List.map (push_generalized_decl_eqn pb.env sigma i d) pb.mat } in
+ let sigma, j = compile sigma pb in
+ sigma, { uj_val = mkLambda_or_LetIn d j.uj_val;
uj_type = mkProd_wo_LetIn d j.uj_type }
(* spiwack: the [initial] argument keeps track whether the alias has
been introduced by a toplevel branch ([true]) or a deep one
([false]). *)
-and compile_alias initial pb (na,orig,(expanded,expanded_typ)) rest =
+and compile_alias initial sigma pb (na,orig,(expanded,expanded_typ)) rest =
let f c t =
let alias = LocalDef (na,c,t) in
let pb =
{ pb with
- env = push_rel alias pb.env;
+ env = snd (push_rel sigma alias pb.env);
tomatch = lift_tomatch_stack 1 rest;
pred = lift_predicate 1 pb.pred pb.tomatch;
history = pop_history_pattern pb.history;
- mat = List.map (push_alias_eqn alias) pb.mat } in
- let j = compile pb in
- let sigma = !(pb.evdref) in
- { uj_val =
+ mat = List.map (push_alias_eqn sigma alias) pb.mat } in
+ let sigma, j = compile sigma pb in
+ sigma, { uj_val =
if isRel sigma c || isVar sigma c || count_occurrences sigma (mkRel 1) j.uj_val <= 1 then
subst1 c j.uj_val
else
@@ -1514,15 +1523,14 @@ and compile_alias initial pb (na,orig,(expanded,expanded_typ)) rest =
(* spiwack: when an alias appears on a deep branch, its non-expanded
form is automatically a variable of the same name. We avoid
introducing such superfluous aliases so that refines are elegant. *)
- let just_pop () =
+ let just_pop sigma =
let pb =
{ pb with
tomatch = rest;
history = pop_history_pattern pb.history;
mat = List.map drop_alias_eqn pb.mat } in
- compile pb
+ compile sigma pb
in
- let sigma = !(pb.evdref) in
(* If the "match" was orginally over a variable, as in "match x with
O => true | n => n end", we give preference to non-expansion in
the default clause (i.e. "match x with O => true | n => n end"
@@ -1534,12 +1542,11 @@ and compile_alias initial pb (na,orig,(expanded,expanded_typ)) rest =
if not (Flags.is_program_mode ()) && (isRel sigma orig || isVar sigma orig) then
(* Try to compile first using non expanded alias *)
try
- if initial then f orig (Retyping.get_type_of pb.env sigma orig)
- else just_pop ()
+ if initial then f orig (Retyping.get_type_of !!(pb.env) sigma orig)
+ else just_pop sigma
with e when precatchable_exception e ->
(* Try then to compile using expanded alias *)
(* Could be needed in case of dependent return clause *)
- pb.evdref := sigma;
f expanded expanded_typ
else
(* Try to compile first using expanded alias *)
@@ -1548,19 +1555,18 @@ and compile_alias initial pb (na,orig,(expanded,expanded_typ)) rest =
(* Try then to compile using non expanded alias *)
(* Could be needed in case of a recursive call which requires to
be on a variable for size reasons *)
- pb.evdref := sigma;
- if initial then f orig (Retyping.get_type_of pb.env !(pb.evdref) orig)
- else just_pop ()
+ if initial then f orig (Retyping.get_type_of !!(pb.env) sigma orig)
+ else just_pop sigma
(* Remember that a non-trivial pattern has been consumed *)
-and compile_non_dep_alias pb rest =
+and compile_non_dep_alias sigma pb rest =
let pb =
{ pb with
tomatch = rest;
history = pop_history_pattern pb.history;
mat = List.map drop_alias_eqn pb.mat } in
- compile pb
+ compile sigma pb
(* pour les alias des initiaux, enrichir les env de ce qu'il faut et
substituer après par les initiaux *)
@@ -1573,7 +1579,7 @@ substituer après par les initiaux *)
* Syntactic correctness has already been done in constrintern *)
let matx_of_eqns env eqns =
let build_eqn {CAst.loc;v=(ids,initial_lpat,initial_rhs)} =
- let avoid = ids_of_named_context_val (named_context_val env) in
+ let avoid = ids_of_named_context_val (named_context_val !!env) in
let avoid = List.fold_left (fun accu id -> Id.Set.add id accu) avoid ids in
let rhs =
{ rhs_env = env;
@@ -1616,8 +1622,8 @@ let matx_of_eqns env eqns =
*)
let adjust_to_extended_env_and_remove_deps env extenv sigma subst t =
- let n = Context.Rel.length (rel_context env) in
- let n' = Context.Rel.length (rel_context extenv) in
+ let n = Context.Rel.length (rel_context !!env) in
+ let n' = Context.Rel.length (rel_context !!extenv) in
(* We first remove the bindings that are dependently typed (they are
difficult to manage and it is not sure these are so useful in practice);
Notes:
@@ -1630,22 +1636,22 @@ let adjust_to_extended_env_and_remove_deps env extenv sigma subst t =
(* d1 ... dn dn+1 ... dn'-p+1 ... dn' *)
(* \--env-/ (= x:ty) *)
(* \--------------extenv------------/ *)
- let (p, _, _) = lookup_rel_id x (rel_context extenv) in
+ let (p, _, _) = lookup_rel_id x (rel_context !!extenv) in
let rec traverse_local_defs p =
- match lookup_rel p extenv with
+ match lookup_rel p !!extenv with
| LocalDef (_,c,_) -> assert (isRel sigma c); traverse_local_defs (p + destRel sigma c)
| LocalAssum _ -> p in
let p = traverse_local_defs p in
let u = lift (n' - n) u in
- try Some (p, u, expand_vars_in_term extenv sigma u)
+ try Some (p, u, expand_vars_in_term !!extenv sigma u)
(* pedrot: does this really happen to raise [Failure _]? *)
with Failure _ -> None in
let subst0 = List.map_filter map subst in
let t0 = lift (n' - n) t in
(subst0, t0)
-let push_binder d (k,env,subst) =
- (k+1,push_rel d env,List.map (fun (na,u,d) -> (na,lift 1 u,d)) subst)
+let push_binder sigma d (k,env,subst) =
+ (k+1,snd (push_rel sigma d env),List.map (fun (na,u,d) -> (na,lift 1 u,d)) subst)
let rec list_assoc_in_triple x = function
[] -> raise Not_found
@@ -1666,88 +1672,94 @@ let rec list_assoc_in_triple x = function
* similarly for each ti.
*)
-let abstract_tycon ?loc env evdref subst tycon extenv t =
- let t = nf_betaiota env !evdref t in (* it helps in some cases to remove K-redex*)
- let src = match EConstr.kind !evdref t with
+let abstract_tycon ?loc env sigma subst tycon extenv t =
+ let t = nf_betaiota !!env sigma t in (* it helps in some cases to remove K-redex*)
+ let src = match EConstr.kind sigma t with
| Evar (evk,_) -> (Loc.tag ?loc @@ Evar_kinds.SubEvar (None,evk))
| _ -> (Loc.tag ?loc @@ Evar_kinds.CasesType true) in
- let subst0,t0 = adjust_to_extended_env_and_remove_deps env extenv !evdref subst t in
+ let subst0,t0 = adjust_to_extended_env_and_remove_deps env extenv sigma subst t in
(* We traverse the type T of the original problem Xi looking for subterms
that match the non-constructor part of the constraints (this part
is in subst); these subterms are the "good" subterms and we replace them
by an evar that may depend (and only depend) on the corresponding
convertible subterms of the substitution *)
+ let evdref = ref sigma in
let rec aux (k,env,subst as x) t =
- match EConstr.kind !evdref t with
- | Rel n when is_local_def (lookup_rel n env) -> t
+ (** Use a reference because the [map_constr_with_full_binders] does not
+ allow threading a state. *)
+ let sigma = !evdref in
+ match EConstr.kind sigma t with
+ | Rel n when is_local_def (lookup_rel n !!env) -> t
| Evar ev ->
- let ty = get_type_of env !evdref t in
- let ty = Evarutil.evd_comb1 (refresh_universes (Some false) env) evdref ty in
+ let ty = get_type_of !!env sigma t in
+ let sigma, ty = refresh_universes (Some false) !!env sigma ty in
let inst =
List.map_i
(fun i _ ->
try list_assoc_in_triple i subst0 with Not_found -> mkRel i)
- 1 (rel_context env) in
- let ev' = evd_comb1 (Evarutil.new_evar env ~src) evdref ty in
- begin match solve_simple_eqn (evar_conv_x full_transparent_state) env !evdref (None,ev,substl inst ev') with
+ 1 (rel_context !!env) in
+ let sigma, ev' = Evarutil.new_evar ~src !!env sigma ty in
+ begin match solve_simple_eqn (evar_conv_x full_transparent_state) !!env sigma (None,ev,substl inst ev') with
| Success evd -> evdref := evd
| UnifFailure _ -> assert false
end;
ev'
| _ ->
- let good = List.filter (fun (_,u,_) -> is_conv_leq env !evdref t u) subst in
+ let good = List.filter (fun (_,u,_) -> is_conv_leq !!env sigma t u) subst in
match good with
| [] ->
- map_constr_with_full_binders !evdref push_binder aux x t
+ map_constr_with_full_binders sigma (push_binder sigma) aux x t
| (_, _, u) :: _ -> (* u is in extenv *)
let vl = List.map pi1 good in
let ty =
- let ty = get_type_of env !evdref t in
- Evarutil.evd_comb1 (refresh_universes (Some false) env) evdref ty
+ let ty = get_type_of !!env sigma t in
+ Evarutil.evd_comb1 (refresh_universes (Some false) !!env) evdref ty
in
let dummy_subst = List.init k (fun _ -> mkProp) in
let ty = substl dummy_subst (aux x ty) in
- let depvl = free_rels !evdref ty in
+ let sigma = !evdref in
+ let depvl = free_rels sigma ty in
let inst =
List.map_i
(fun i _ -> if Int.List.mem i vl then u else mkRel i) 1
- (rel_context extenv) in
- let map a = match EConstr.kind !evdref a with
- | Rel n -> not (noccurn !evdref n u) || Int.Set.mem n depvl
+ (rel_context !!extenv) in
+ let map a = match EConstr.kind sigma a with
+ | Rel n -> not (noccurn sigma n u) || Int.Set.mem n depvl
| _ -> true
in
let rel_filter = List.map map inst in
let named_filter =
- List.map (fun d -> local_occur_var !evdref (NamedDecl.get_id d) u)
- (named_context extenv) in
+ List.map (fun d -> local_occur_var sigma (NamedDecl.get_id d) u)
+ (named_context !!extenv) in
let filter = Filter.make (rel_filter @ named_filter) in
- let candidates = u :: List.map mkRel vl in
- let ev = evd_comb1 (Evarutil.new_evar extenv ~src ~filter ~candidates) evdref ty in
+ let candidates = List.rev (u :: List.map mkRel vl) in
+ let sigma, ev = Evarutil.new_evar !!extenv ~src ~filter ~candidates sigma ty in
+ let () = evdref := sigma in
lift k ev
in
- aux (0,extenv,subst0) t0
+ let ans = aux (0,extenv,subst0) t0 in
+ !evdref, ans
-let build_tycon ?loc env tycon_env s subst tycon extenv evdref t =
- let t,tt = match t with
+let build_tycon ?loc env tycon_env s subst tycon extenv sigma t =
+ let sigma, t, tt = match t with
| None ->
(* This is the situation we are building a return predicate and
we are in an impossible branch *)
- let n = Context.Rel.length (rel_context env) in
- let n' = Context.Rel.length (rel_context tycon_env) in
- let impossible_case_type, u =
- evd_comb1
- (new_type_evar (reset_context env) ~src:(Loc.tag ?loc Evar_kinds.ImpossibleCase))
- evdref univ_flexible_alg
+ let n = Context.Rel.length (rel_context !!env) in
+ let n' = Context.Rel.length (rel_context !!tycon_env) in
+ let sigma, (impossible_case_type, u) =
+ new_type_evar (reset_context !!env) ~src:(Loc.tag ?loc Evar_kinds.ImpossibleCase)
+ sigma univ_flexible_alg
in
- (lift (n'-n) impossible_case_type, mkSort u)
+ (sigma, lift (n'-n) impossible_case_type, mkSort u)
| Some t ->
- let t = abstract_tycon ?loc tycon_env evdref subst tycon extenv t in
- let tt = evd_comb1 (Typing.type_of extenv) evdref t in
- (t,tt) in
- match cumul env !evdref tt (mkSort s) with
+ let sigma, t = abstract_tycon ?loc tycon_env sigma subst tycon extenv t in
+ let sigma, tt = Typing.type_of !!extenv sigma t in
+ (sigma, t, tt) in
+ match cumul !!env sigma tt (mkSort s) with
| None -> anomaly (Pp.str "Build_tycon: should be a type.");
- | Some sigma -> evdref := sigma;
- { uj_val = t; uj_type = tt }
+ | Some sigma ->
+ sigma, { uj_val = t; uj_type = tt }
(* For a multiple pattern-matching problem Xi on t1..tn with return
* type T, [build_inversion_problem Gamma Sigma (t1..tn) T] builds a return
@@ -1761,14 +1773,14 @@ let build_tycon ?loc env tycon_env s subst tycon extenv evdref t =
let build_inversion_problem loc env sigma tms t =
let make_patvar t (subst,avoid) =
- let id = next_name_away (named_hd env sigma t Anonymous) avoid in
+ let id = next_name_away (named_hd !!env sigma t Anonymous) avoid in
DAst.make @@ PatVar (Name id), ((id,t)::subst, Id.Set.add id avoid) in
let rec reveal_pattern t (subst,avoid as acc) =
- match EConstr.kind sigma (whd_all env sigma t) with
+ match EConstr.kind sigma (whd_all !!env sigma t) with
| Construct (cstr,u) -> DAst.make (PatCstr (cstr,[],Anonymous)), acc
| App (f,v) when isConstruct sigma f ->
let cstr,u = destConstruct sigma f in
- let n = constructor_nrealargs_env env cstr in
+ let n = constructor_nrealargs_env !!env cstr in
let l = List.lastn n (Array.to_list v) in
let l,acc = List.fold_right_map reveal_pattern l acc in
DAst.make (PatCstr (cstr,l,Anonymous)), acc
@@ -1780,19 +1792,19 @@ let build_inversion_problem loc env sigma tms t =
let patl,acc = List.fold_right_map reveal_pattern realargs acc in
let pat,acc = make_patvar t acc in
let indf' = lift_inductive_family n indf in
- let sign = make_arity_signature env sigma true indf' in
+ let sign = make_arity_signature !!env sigma true indf' in
let patl = pat :: List.rev patl in
- let patl,sign = recover_and_adjust_alias_names patl sign in
+ let patl,sign = recover_and_adjust_alias_names acc patl sign in
let p = List.length patl in
- let env' = push_rel_context sign env in
+ let _,env' = push_rel_context sigma sign env in
let patl',acc_sign,acc = aux (n+p) env' (sign@acc_sign) tms acc in
List.rev_append patl patl',acc_sign,acc
| (t, NotInd (bo,typ)) :: tms ->
let pat,acc = make_patvar t acc in
let d = LocalAssum (alias_of_pat pat,typ) in
- let patl,acc_sign,acc = aux (n+1) (push_rel d env) (d::acc_sign) tms acc in
+ let patl,acc_sign,acc = aux (n+1) (snd (push_rel sigma d env)) (d::acc_sign) tms acc in
pat::patl,acc_sign,acc in
- let avoid0 = vars_of_env env in
+ let avoid0 = GlobEnv.vars_of_env env in
(* [patl] is a list of patterns revealing the substructure of
constructors present in the constraints on the type of the
multiple terms t1..tn that are matched in the original problem;
@@ -1808,9 +1820,9 @@ let build_inversion_problem loc env sigma tms t =
let decls =
List.map_i (fun i d -> (mkRel i, map_constr (lift i) d)) 1 sign in
- let pb_env = push_rel_context sign env in
+ let _,pb_env = push_rel_context sigma sign env in
let decls =
- List.map (fun (c,d) -> (c,extract_inductive_data pb_env sigma d,d)) decls in
+ List.map (fun (c,d) -> (c,extract_inductive_data !!(pb_env) sigma d,d)) decls in
let decls = List.rev decls in
let dep_sign = find_dependencies_signature sigma (List.make n true) decls in
@@ -1843,7 +1855,7 @@ let build_inversion_problem loc env sigma tms t =
constraints are incompatible with the constraints on the
inductive types of the multiple terms matched in Xi *)
let catch_all_eqn =
- if List.for_all (irrefutable env) patl then
+ if List.for_all (irrefutable !!env) patl then
(* No need for a catch all clause *)
[]
else
@@ -1857,14 +1869,11 @@ let build_inversion_problem loc env sigma tms t =
it = None } } ] in
(* [pb] is the auxiliary pattern-matching serving as skeleton for the
return type of the original problem Xi *)
- let s' = Retyping.get_sort_of env sigma t in
+ let s' = Retyping.get_sort_of !!env sigma t in
let sigma, s = Evd.new_sort_variable univ_flexible sigma in
- let sigma = Evd.set_leq_sort env sigma s' s in
- let evdref = ref sigma in
+ let sigma = Evd.set_leq_sort !!env sigma s' s in
let pb =
{ env = pb_env;
- lvar = empty_lvar;
- evdref = evdref;
pred = (*ty *) mkSort s;
tomatch = sub_tms;
history = start_history n;
@@ -1872,22 +1881,22 @@ let build_inversion_problem loc env sigma tms t =
caseloc = loc;
casestyle = RegularStyle;
typing_function = build_tycon ?loc env pb_env s subst} in
- let pred = (compile pb).uj_val in
- (!evdref,pred)
+ let sigma, j = compile sigma pb in
+ (sigma, j.uj_val)
(* Here, [pred] is assumed to be in the context built from all *)
(* realargs and terms to match *)
let build_initial_predicate arsign pred =
- let rec buildrec n pred tmnames = function
+ let rec buildrec pred tmnames = function
| [] -> List.rev tmnames,pred
| (decl::realdecls)::lnames ->
let na = RelDecl.get_name decl in
- let n' = n + List.length realdecls in
- buildrec (n'+1) pred (force_name na::tmnames) lnames
+ let realnames = List.map RelDecl.get_name realdecls in
+ buildrec pred ((force_name na,realnames)::tmnames) lnames
| _ -> assert false
- in buildrec 0 pred [] (List.rev arsign)
+ in buildrec pred [] (List.rev arsign)
-let extract_arity_signature ?(dolift=true) env0 lvar tomatchl tmsign =
+let extract_arity_signature ?(dolift=true) env0 tomatchl tmsign =
let lift = if dolift then lift else fun n t -> t in
let get_one_sign n tm (na,t) =
match tm with
@@ -1895,7 +1904,7 @@ let extract_arity_signature ?(dolift=true) env0 lvar tomatchl tmsign =
(match t with
| None -> let sign = match bo with
| None -> [LocalAssum (na, lift n typ)]
- | Some b -> [LocalDef (na, lift n b, lift n typ)] in sign,sign
+ | Some b -> [LocalDef (na, lift n b, lift n typ)] in sign
| Some {CAst.loc} ->
user_err ?loc
(str"Unexpected type annotation for a term of non inductive type."))
@@ -1905,52 +1914,55 @@ let extract_arity_signature ?(dolift=true) env0 lvar tomatchl tmsign =
let nrealargs_ctxt = inductive_nrealdecls_env env0 ind in
let arsign = fst (get_arity env0 indf') in
let arsign = List.map (fun d -> map_rel_decl EConstr.of_constr d) arsign in
- let realnal, realnal' =
+ let realnal =
match t with
| Some {CAst.loc;v=(ind',realnal)} ->
if not (eq_ind ind ind') then
user_err ?loc (str "Wrong inductive type.");
if not (Int.equal nrealargs_ctxt (List.length realnal)) then
anomaly (Pp.str "Ill-formed 'in' clause in cases.");
- let realnal = List.rev realnal in
- let realnal' = List.map (ltac_interp_name lvar) realnal in
- realnal,realnal'
+ List.rev realnal
| None ->
- let realnal = List.make nrealargs_ctxt Anonymous in
- realnal, realnal in
- let na' = ltac_interp_name lvar na in
+ List.make nrealargs_ctxt Anonymous in
let t = EConstr.of_constr (build_dependent_inductive env0 indf') in
- (* Context with names for typing *)
- let arsign1 = LocalAssum (na, t) :: List.map2 RelDecl.set_name realnal arsign in
- (* Context with names for building the term *)
- let arsign2 = LocalAssum (na', t) :: List.map2 RelDecl.set_name realnal' arsign in
- arsign1,arsign2 in
+ LocalAssum (na, t) :: List.map2 RelDecl.set_name realnal arsign in
let rec buildrec n = function
| [],[] -> []
| (_,tm)::ltm, (_,x)::tmsign ->
let l = get_one_sign n tm x in
- l :: buildrec (n + List.length (fst l)) (ltm,tmsign)
+ l :: buildrec (n + List.length l) (ltm,tmsign)
| _ -> assert false
in List.rev (buildrec 0 (tomatchl,tmsign))
-let inh_conv_coerce_to_tycon ?loc env evdref j tycon =
+let inh_conv_coerce_to_tycon ?loc env sigma j tycon =
match tycon with
- | Some p ->
- evd_comb2 (Coercion.inh_conv_coerce_to ?loc true env) evdref j p
- | None -> j
+ | Some p -> Coercion.inh_conv_coerce_to ?loc true env sigma j p
+ | None -> sigma, j
(* We put the tycon inside the arity signature, possibly discovering dependencies. *)
+let add_subst sigma c len (rel_subst,var_subst) =
+ match EConstr.kind sigma c with
+ | Rel n -> (n,len) :: rel_subst, var_subst
+ | Var id -> rel_subst, (id,len) :: var_subst
+ | _ -> assert false
+
+let dependent_rel_or_var sigma tm c =
+ match EConstr.kind sigma tm with
+ | Rel n -> not (noccurn sigma n c)
+ | Var id -> Termops.local_occur_var sigma id c
+ | _ -> assert false
+
let prepare_predicate_from_arsign_tycon env sigma loc tomatchs arsign c =
let nar = List.fold_left (fun n sign -> Context.Rel.nhyps sign + n) 0 arsign in
- let subst, len =
+ let (rel_subst,var_subst), len =
List.fold_right2 (fun (tm, tmtype) sign (subst, len) ->
let signlen = List.length sign in
match EConstr.kind sigma tm with
- | Rel n when Int.equal signlen 1 && not (noccurn sigma n c)
+ | Rel _ | Var _ when Int.equal signlen 1 && dependent_rel_or_var sigma tm c
(* The term to match is not of a dependent type itself *) ->
- ((n, len) :: subst, len - signlen)
- | Rel n when signlen > 1 (* The term is of a dependent type,
+ (add_subst sigma tm len subst, len - signlen)
+ | Rel _ | Var _ when signlen > 1 (* The term is of a dependent type,
maybe some variable in its type appears in the tycon. *) ->
(match tmtype with
NotInd _ -> (subst, len - signlen)
@@ -1959,36 +1971,44 @@ let prepare_predicate_from_arsign_tycon env sigma loc tomatchs arsign c =
List.fold_left
(fun (subst, len) arg ->
match EConstr.kind sigma arg with
- | Rel n when not (noccurn sigma n c) ->
- ((n, len) :: subst, pred len)
+ | Rel _ | Var _ when dependent_rel_or_var sigma arg c ->
+ (add_subst sigma arg len subst, pred len)
| _ -> (subst, pred len))
(subst, len) realargs
in
let subst =
- if not (noccurn sigma n c) && List.for_all (isRel sigma) realargs
- then (n, len) :: subst else subst
+ if dependent_rel_or_var sigma tm c && List.for_all (fun c -> isRel sigma c || isVar sigma c) realargs
+ then add_subst sigma tm len subst else subst
in (subst, pred len))
| _ -> (subst, len - signlen))
- (List.rev tomatchs) arsign ([], nar)
+ (List.rev tomatchs) arsign (([],[]), nar)
in
let rec predicate lift c =
match EConstr.kind sigma c with
| Rel n when n > lift ->
(try
(* Make the predicate dependent on the matched variable *)
- let idx = Int.List.assoc (n - lift) subst in
+ let idx = Int.List.assoc (n - lift) rel_subst in
mkRel (idx + lift)
with Not_found ->
- (* A variable that is not matched, lift over the arsign. *)
+ (* A variable that is not matched, lift over the arsign *)
mkRel (n + nar))
+ | Var id ->
+ (try
+ (* Make the predicate dependent on the matched variable *)
+ let idx = Id.List.assoc id var_subst in
+ mkRel (idx + lift)
+ with Not_found ->
+ (* A variable that is not matched *)
+ c)
| _ ->
EConstr.map_with_binders sigma succ predicate lift c
in
assert (len == 0);
let p = predicate 0 c in
- let env' = List.fold_right push_rel_context arsign env in
- try let sigma' = fst (Typing.type_of env' sigma p) in
- Some (sigma', p)
+ let arsign,env' = List.fold_right_map (push_rel_context sigma) arsign env in
+ try let sigma' = fst (Typing.type_of !!env' sigma p) in
+ Some (sigma', p, arsign)
with e when precatchable_exception e -> None
(* Builds the predicate. If the predicate is dependent, its context is
@@ -1996,80 +2016,59 @@ let prepare_predicate_from_arsign_tycon env sigma loc tomatchs arsign c =
* type and 1 assumption for each term not _syntactically_ in an
* inductive type.
- * Each matched terms are independently considered dependent or not.
-
- * A type constraint but no annotation case: we try to specialize the
- * tycon to make the predicate if it is not closed.
+ * Each matched term is independently considered dependent or not.
*)
-exception LocalOccur
-
-let noccur_with_meta sigma n m term =
- let rec occur_rec n c = match EConstr.kind sigma c with
- | Rel p -> if n<=p && p<n+m then raise LocalOccur
- | App(f,cl) ->
- (match EConstr.kind sigma f with
- | Cast (c,_,_) when isMeta sigma c -> ()
- | Meta _ -> ()
- | _ -> EConstr.iter_with_binders sigma succ occur_rec n c)
- | Evar (_, _) -> ()
- | _ -> EConstr.iter_with_binders sigma succ occur_rec n c
- in
- try (occur_rec n term; true) with LocalOccur -> false
-
-let prepare_predicate ?loc typing_fun env sigma lvar tomatchs arsign tycon pred =
+let prepare_predicate ?loc typing_fun env sigma tomatchs arsign tycon pred =
let refresh_tycon sigma t =
(** If we put the typing constraint in the term, it has to be
refreshed to preserve the invariant that no algebraic universe
can appear in the term. *)
refresh_universes ~status:Evd.univ_flexible ~onlyalg:true (Some true)
- env sigma t
+ !!env sigma t
in
- let typing_arsign,building_arsign = List.split arsign in
let preds =
- match pred, tycon with
+ match pred with
(* No return clause *)
- | None, Some t when not (noccur_with_meta sigma 0 max_int t) ->
- (* If the tycon is not closed w.r.t real variables, we try *)
- (* two different strategies *)
- (* First strategy: we abstract the tycon wrt to the dependencies *)
- let sigma, t = refresh_tycon sigma t in
- let p1 =
- prepare_predicate_from_arsign_tycon env sigma loc tomatchs typing_arsign t in
- (* Second strategy: we build an "inversion" predicate *)
- let sigma2,pred2 = build_inversion_problem loc env sigma tomatchs t in
- (match p1 with
- | Some (sigma1,pred1) -> [sigma1, pred1; sigma2, pred2]
- | None -> [sigma2, pred2])
- | None, _ ->
- (* No dependent type constraint, or no constraints at all: *)
- (* we use two strategies *)
- let sigma,t = match tycon with
- | Some t -> refresh_tycon sigma t
- | None ->
- let (sigma, (t, _)) =
- new_type_evar env sigma univ_flexible_alg ~src:(Loc.tag ?loc @@ Evar_kinds.CasesType false) in
- sigma, t
- in
- (* First strategy: we build an "inversion" predicate *)
- let sigma1,pred1 = build_inversion_problem loc env sigma tomatchs t in
- (* Second strategy: we directly use the evar as a non dependent pred *)
- let pred2 = lift (List.length (List.flatten typing_arsign)) t in
- [sigma1, pred1; sigma, pred2]
+ | None ->
+ let sigma,t =
+ match tycon with
+ | Some t -> refresh_tycon sigma t
+ | None ->
+ (* No type constraint: we first create a generic evar type constraint *)
+ let src = (loc, Evar_kinds.CasesType false) in
+ let sigma, (t, _) = new_type_evar !!env sigma univ_flexible_alg ~src in
+ sigma, t in
+ (* First strategy: we build an "inversion" predicate, also replacing the *)
+ (* dependencies with existential variables *)
+ let sigma1,pred1 = build_inversion_problem loc env sigma tomatchs t in
+ (* Optional second strategy: we abstract the tycon wrt to the dependencies *)
+ let p2 =
+ prepare_predicate_from_arsign_tycon env sigma loc tomatchs arsign t in
+ (* Third strategy: we take the type constraint as it is; of course we could *)
+ (* need something inbetween, abstracting some but not all of the dependencies *)
+ (* the "inversion" strategy deals with that but unification may not be *)
+ (* powerful enough so strategy 2 and 3 helps; moreover, inverting does not *)
+ (* work (yet) when a constructor has a type not precise enough for the inversion *)
+ (* see log message for details *)
+ let pred3 = lift (List.length (List.flatten arsign)) t in
+ (match p2 with
+ | Some (sigma2,pred2,arsign) when not (EConstr.eq_constr sigma pred2 pred3) ->
+ [sigma1, pred1, arsign; sigma2, pred2, arsign; sigma, pred3, arsign]
+ | _ ->
+ [sigma1, pred1, arsign; sigma, pred3, arsign])
(* Some type annotation *)
- | Some rtntyp, _ ->
+ | Some rtntyp ->
(* We extract the signature of the arity *)
- let envar = List.fold_right push_rel_context typing_arsign env in
+ let building_arsign,envar = List.fold_right_map (push_rel_context sigma) arsign env in
let sigma, newt = new_sort_variable univ_flexible_alg sigma in
- let evdref = ref sigma in
- let predcclj = typing_fun (mk_tycon (mkSort newt)) envar evdref lvar rtntyp in
- let sigma = !evdref in
+ let sigma, predcclj = typing_fun (mk_tycon (mkSort newt)) envar sigma rtntyp in
let predccl = nf_evar sigma predcclj.uj_val in
- [sigma, predccl]
+ [sigma, predccl, building_arsign]
in
List.map
- (fun (sigma,pred) ->
- let (nal,pred) = build_initial_predicate building_arsign pred in
+ (fun (sigma,pred,arsign) ->
+ let (nal,pred) = build_initial_predicate arsign pred in
sigma,nal,pred)
preds
@@ -2102,12 +2101,17 @@ let eq_id avoid id =
let hid' = next_ident_away hid avoid in
hid'
-let mk_eq evdref typ x y = papp evdref coq_eq_ind [| typ; x ; y |]
-let mk_eq_refl evdref typ x = papp evdref coq_eq_refl [| typ; x |]
-let mk_JMeq evdref typ x typ' y =
- papp evdref coq_JMeq_ind [| typ; x ; typ'; y |]
-let mk_JMeq_refl evdref typ x =
- papp evdref coq_JMeq_refl [| typ; x |]
+let papp sigma gr args =
+ let evdref = ref sigma in
+ let ans = papp evdref gr args in
+ !evdref, ans
+
+let mk_eq sigma typ x y = papp sigma coq_eq_ind [| typ; x ; y |]
+let mk_eq_refl sigma typ x = papp sigma coq_eq_refl [| typ; x |]
+let mk_JMeq sigma typ x typ' y =
+ papp sigma coq_JMeq_ind [| typ; x ; typ'; y |]
+let mk_JMeq_refl sigma typ x =
+ papp sigma coq_JMeq_refl [| typ; x |]
let hole na = DAst.make @@
GHole (Evar_kinds.QuestionMark {
@@ -2116,8 +2120,8 @@ let hole na = DAst.make @@
Evar_kinds.qm_record_field=None},
IntroAnonymous, None)
-let constr_of_pat env evdref arsign pat avoid =
- let rec typ env (ty, realargs) pat avoid =
+let constr_of_pat env sigma arsign pat avoid =
+ let rec typ env sigma (ty, realargs) pat avoid =
let loc = pat.CAst.loc in
match DAst.get pat with
| PatVar name ->
@@ -2127,14 +2131,14 @@ let constr_of_pat env evdref arsign pat avoid =
let previd, id = prime avoid (Name (Id.of_string "wildcard")) in
Name id, Id.Set.add id avoid
in
- ((DAst.make ?loc @@ PatVar name), [LocalAssum (name, ty)] @ realargs, mkRel 1, ty,
+ (sigma, (DAst.make ?loc @@ PatVar name), [LocalAssum (name, ty)] @ realargs, mkRel 1, ty,
(List.map (fun x -> mkRel 1) realargs), 1, avoid)
| PatCstr (((_, i) as cstr),args,alias) ->
let cind = inductive_of_constructor cstr in
let IndType (indf, _) =
- try find_rectype env ( !evdref) (lift (-(List.length realargs)) ty)
- with Not_found -> error_case_not_inductive env !evdref
- {uj_val = ty; uj_type = Typing.unsafe_type_of env !evdref ty}
+ try find_rectype env sigma (lift (-(List.length realargs)) ty)
+ with Not_found -> error_case_not_inductive env sigma
+ {uj_val = ty; uj_type = Typing.unsafe_type_of env sigma ty}
in
let (ind,u), params = dest_ind_family indf in
let params = List.map EConstr.of_constr params in
@@ -2143,18 +2147,18 @@ let constr_of_pat env evdref arsign pat avoid =
let ci = cstrs.(i-1) in
let nb_args_constr = ci.cs_nargs in
assert (Int.equal nb_args_constr (List.length args));
- let patargs, args, sign, env, n, m, avoid =
+ let sigma, patargs, args, sign, env, n, m, avoid =
List.fold_right2
- (fun decl ua (patargs, args, sign, env, n, m, avoid) ->
+ (fun decl ua (sigma, patargs, args, sign, env, n, m, avoid) ->
let t = EConstr.of_constr (RelDecl.get_type decl) in
- let pat', sign', arg', typ', argtypargs, n', avoid =
+ let sigma, pat', sign', arg', typ', argtypargs, n', avoid =
let liftt = liftn (List.length sign) (succ (List.length args)) t in
- typ env (substl args liftt, []) ua avoid
+ typ env sigma (substl args liftt, []) ua avoid
in
let args' = arg' :: List.map (lift n') args in
- let env' = push_rel_context sign' env in
- (pat' :: patargs, args', sign' @ sign, env', n' + n, succ m, avoid))
- ci.cs_args (List.rev args) ([], [], [], env, 0, 0, avoid)
+ let env' = EConstr.push_rel_context sign' env in
+ (sigma, pat' :: patargs, args', sign' @ sign, env', n' + n, succ m, avoid))
+ ci.cs_args (List.rev args) (sigma, [], [], [], env, 0, 0, avoid)
in
let args = List.rev args in
let patargs = List.rev patargs in
@@ -2162,32 +2166,32 @@ let constr_of_pat env evdref arsign pat avoid =
let cstr = mkConstructU (on_snd EInstance.make ci.cs_cstr) in
let app = applist (cstr, List.map (lift (List.length sign)) params) in
let app = applist (app, args) in
- let apptype = Retyping.get_type_of env ( !evdref) app in
- let IndType (indf, realargs) = find_rectype env (!evdref) apptype in
+ let apptype = Retyping.get_type_of env sigma app in
+ let IndType (indf, realargs) = find_rectype env sigma apptype in
match alias with
Anonymous ->
- pat', sign, app, apptype, realargs, n, avoid
+ sigma, pat', sign, app, apptype, realargs, n, avoid
| Name id ->
let sign = LocalAssum (alias, lift m ty) :: sign in
let avoid = Id.Set.add id avoid in
- let sign, i, avoid =
+ let sigma, sign, i, avoid =
try
- let env = push_rel_context sign env in
- evdref := the_conv_x_leq (push_rel_context sign env)
- (lift (succ m) ty) (lift 1 apptype) !evdref;
- let eq_t = mk_eq evdref (lift (succ m) ty)
+ let env = EConstr.push_rel_context sign env in
+ let sigma = the_conv_x_leq (EConstr.push_rel_context sign env)
+ (lift (succ m) ty) (lift 1 apptype) sigma in
+ let sigma, eq_t = mk_eq sigma (lift (succ m) ty)
(mkRel 1) (* alias *)
(lift 1 app) (* aliased term *)
in
let neq = eq_id avoid id in
- LocalDef (Name neq, mkRel 0, eq_t) :: sign, 2, Id.Set.add neq avoid
- with Reduction.NotConvertible -> sign, 1, avoid
+ sigma, LocalDef (Name neq, mkRel 0, eq_t) :: sign, 2, Id.Set.add neq avoid
+ with Reduction.NotConvertible -> sigma, sign, 1, avoid
in
(* Mark the equality as a hole *)
- pat', sign, lift i app, lift i apptype, realargs, n + i, avoid
+ sigma, pat', sign, lift i app, lift i apptype, realargs, n + i, avoid
in
- let pat', sign, patc, patty, args, z, avoid = typ env (RelDecl.get_type (List.hd arsign), List.tl arsign) pat avoid in
- pat', (sign, patc, (RelDecl.get_type (List.hd arsign), args), pat'), avoid
+ let sigma, pat', sign, patc, patty, args, z, avoid = typ env sigma (RelDecl.get_type (List.hd arsign), List.tl arsign) pat avoid in
+ sigma, pat', (sign, patc, (RelDecl.get_type (List.hd arsign), args), pat'), avoid
(* shadows functional version *)
@@ -2239,58 +2243,59 @@ let lift_rel_context n l =
Hence pats is already typed in its
full signature. However prevpatterns are in the original one signature per pattern form.
*)
-let build_ineqs evdref prevpatterns pats liftsign =
- let _tomatchs = List.length pats in
- let diffs =
+let build_ineqs sigma prevpatterns pats liftsign =
+ let sigma, diffs =
List.fold_left
- (fun c eqnpats ->
- let acc = List.fold_left2
+ (fun (sigma, c) eqnpats ->
+ let sigma, acc = List.fold_left2
(* ppat is the pattern we are discriminating against, curpat is the current one. *)
- (fun acc (ppat_sign, ppat_c, (ppat_ty, ppat_tyargs), ppat)
+ (fun (sigma, acc) (ppat_sign, ppat_c, (ppat_ty, ppat_tyargs), ppat)
(curpat_sign, curpat_c, (curpat_ty, curpat_tyargs), curpat) ->
match acc with
- None -> None
+ None -> sigma, None
| Some (sign, len, n, c) -> (* FixMe: do not work with ppat_args *)
if is_included curpat ppat then
(* Length of previous pattern's signature *)
let lens = List.length ppat_sign in
(* Accumulated length of previous pattern's signatures *)
let len' = lens + len in
+ let sigma, c' =
+ papp sigma coq_eq_ind
+ [| lift (len' + liftsign) curpat_ty;
+ liftn (len + liftsign) (succ lens) ppat_c ;
+ lift len' curpat_c |]
+ in
let acc =
((* Jump over previous prevpat signs *)
lift_rel_context len ppat_sign @ sign,
len',
succ n, (* nth pattern *)
- (papp evdref coq_eq_ind
- [| lift (len' + liftsign) curpat_ty;
- liftn (len + liftsign) (succ lens) ppat_c ;
- lift len' curpat_c |]) ::
- List.map (lift lens (* Jump over this prevpat signature *)) c)
- in Some acc
- else None)
- (Some ([], 0, 0, [])) eqnpats pats
+ c' :: List.map (lift lens (* Jump over this prevpat signature *)) c)
+ in sigma, Some acc
+ else sigma, None)
+ (sigma, Some ([], 0, 0, [])) eqnpats pats
in match acc with
- None -> c
+ None -> sigma, c
| Some (sign, len, _, c') ->
- let sigma, conj = mk_coq_and !evdref c' in
+ let sigma, conj = mk_coq_and sigma c' in
let sigma, neg = mk_coq_not sigma conj in
let conj = it_mkProd_or_LetIn neg (lift_rel_context liftsign sign) in
- evdref := sigma; conj :: c)
- [] prevpatterns
- in match diffs with [] -> None
- | _ -> Some (let sigma, conj = mk_coq_and !evdref diffs in evdref := sigma; conj)
+ sigma, conj :: c)
+ (sigma, []) prevpatterns
+ in match diffs with [] -> sigma, None
+ | _ -> let sigma, conj = mk_coq_and sigma diffs in sigma, Some conj
-let constrs_of_pats typing_fun env evdref eqns tomatchs sign neqs arity =
+let constrs_of_pats typing_fun env sigma eqns tomatchs sign neqs arity =
let i = ref 0 in
- let (x, y, z) =
+ let (sigma, x, y, z) =
List.fold_left
- (fun (branches, eqns, prevpatterns) eqn ->
- let _, newpatterns, pats =
+ (fun (sigma, branches, eqns, prevpatterns) eqn ->
+ let sigma, _, newpatterns, pats =
List.fold_left2
- (fun (idents, newpatterns, pats) pat arsign ->
- let pat', cpat, idents = constr_of_pat env evdref arsign pat idents in
- (idents, pat' :: newpatterns, cpat :: pats))
- (Id.Set.empty, [], []) eqn.patterns sign
+ (fun (sigma, idents, newpatterns, pats) pat arsign ->
+ let sigma, pat', cpat, idents = constr_of_pat !!env sigma arsign pat idents in
+ (sigma, idents, pat' :: newpatterns, cpat :: pats))
+ (sigma, Id.Set.empty, [], []) eqn.patterns sign
in
let newpatterns = List.rev newpatterns and opats = List.rev pats in
let rhs_rels, pats, signlen =
@@ -2309,13 +2314,13 @@ let constrs_of_pats typing_fun env evdref eqns tomatchs sign neqs arity =
(* lift to get outside of past patterns to get terms in the combined environment. *)
(fun (pats, n) (sign, c, (s, args), p) ->
let len = List.length sign in
- ((rels_of_patsign !evdref sign, lift n c,
+ ((rels_of_patsign sigma sign, lift n c,
(s, List.map (lift n) args), p) :: pats, len + n))
([], 0) pats
in
- let ineqs = build_ineqs evdref prevpatterns pats signlen in
- let rhs_rels' = rels_of_patsign !evdref rhs_rels in
- let _signenv = push_rel_context rhs_rels' env in
+ let sigma, ineqs = build_ineqs sigma prevpatterns pats signlen in
+ let rhs_rels' = rels_of_patsign sigma rhs_rels in
+ let _signenv,_ = push_rel_context sigma rhs_rels' env in
let arity =
let args, nargs =
List.fold_right (fun (sign, c, (_, args), _) (allargs,n) ->
@@ -2332,19 +2337,19 @@ let constrs_of_pats typing_fun env evdref eqns tomatchs sign neqs arity =
| Some ineqs ->
[LocalAssum (Anonymous, ineqs)], lift 1 arity
in
- let eqs_rels, arity = decompose_prod_n_assum !evdref neqs arity in
+ let eqs_rels, arity = decompose_prod_n_assum sigma neqs arity in
eqs_rels @ neqs_rels @ rhs_rels', arity
in
- let rhs_env = push_rel_context rhs_rels' env in
- let j = typing_fun (mk_tycon tycon) rhs_env eqn.rhs.it in
+ let _,rhs_env = push_rel_context sigma rhs_rels' env in
+ let sigma, j = typing_fun (mk_tycon tycon) rhs_env sigma eqn.rhs.it in
let bbody = it_mkLambda_or_LetIn j.uj_val rhs_rels'
and btype = it_mkProd_or_LetIn j.uj_type rhs_rels' in
- let _btype = evd_comb1 (Typing.type_of env) evdref bbody in
+ let sigma, _btype = Typing.type_of !!env sigma bbody in
let branch_name = Id.of_string ("program_branch_" ^ (string_of_int !i)) in
let branch_decl = LocalDef (Name branch_name, lift !i bbody, lift !i btype) in
let branch =
let bref = DAst.make @@ GVar branch_name in
- match vars_of_ctx !evdref rhs_rels with
+ match vars_of_ctx sigma rhs_rels with
[] -> bref
| l -> DAst.make @@ GApp (bref, l)
in
@@ -2354,11 +2359,12 @@ let constrs_of_pats typing_fun env evdref eqns tomatchs sign neqs arity =
in
incr i;
let rhs = { eqn.rhs with it = Some branch } in
- (branch_decl :: branches,
+ (sigma, branch_decl :: branches,
{ eqn with patterns = newpatterns; rhs = rhs } :: eqns,
opats :: prevpatterns))
- ([], [], []) eqns
- in x, y
+ (sigma, [], [], []) eqns
+ in
+ sigma, x, y
(* Builds the predicate. If the predicate is dependent, its context is
* made of 1+nrealargs assumptions for each matched term in an inductive
@@ -2395,14 +2401,14 @@ let abstract_tomatch env sigma tomatchs tycon =
([], [], Id.Set.empty, tycon) tomatchs
in List.rev prev, ctx, tycon
-let build_dependent_signature env evdref avoid tomatchs arsign =
+let build_dependent_signature env sigma avoid tomatchs arsign =
let avoid = ref avoid in
let arsign = List.rev arsign in
let allnames = List.rev_map (List.map RelDecl.get_name) arsign in
let nar = List.fold_left (fun n names -> List.length names + n) 0 allnames in
- let eqs, neqs, refls, slift, arsign' =
+ let sigma, eqs, neqs, refls, slift, arsign' =
List.fold_left2
- (fun (eqs, neqs, refl_args, slift, arsigns) (tm, ty) arsign ->
+ (fun (sigma, eqs, neqs, refl_args, slift, arsigns) (tm, ty) arsign ->
(* The accumulator:
previous eqs,
number of previous eqs,
@@ -2418,49 +2424,56 @@ let build_dependent_signature env evdref avoid tomatchs arsign =
let appn = RelDecl.get_name app_decl in
let appt = RelDecl.get_type app_decl in
let argsign = List.rev argsign in (* arguments in application order *)
- let env', nargeqs, argeqs, refl_args, slift, argsign' =
+ let sigma, env', nargeqs, argeqs, refl_args, slift, argsign' =
List.fold_left2
- (fun (env, nargeqs, argeqs, refl_args, slift, argsign') arg decl ->
+ (fun (sigma, env, nargeqs, argeqs, refl_args, slift, argsign') arg decl ->
let name = RelDecl.get_name decl in
let t = RelDecl.get_type decl in
- let argt = Retyping.get_type_of env !evdref arg in
- let eq, refl_arg =
- if Reductionops.is_conv env !evdref argt t then
- (mk_eq evdref (lift (nargeqs + slift) argt)
- (mkRel (nargeqs + slift))
- (lift (nargeqs + nar) arg),
- mk_eq_refl evdref argt arg)
+ let argt = Retyping.get_type_of env sigma arg in
+ let sigma, eq, refl_arg =
+ if Reductionops.is_conv env sigma argt t then
+ let sigma, eq =
+ mk_eq sigma (lift (nargeqs + slift) argt)
+ (mkRel (nargeqs + slift))
+ (lift (nargeqs + nar) arg)
+ in
+ let sigma, refl = mk_eq_refl sigma argt arg in
+ sigma, eq, refl
else
- (mk_JMeq evdref (lift (nargeqs + slift) t)
- (mkRel (nargeqs + slift))
- (lift (nargeqs + nar) argt)
- (lift (nargeqs + nar) arg),
- mk_JMeq_refl evdref argt arg)
+ let sigma, eq =
+ mk_JMeq sigma (lift (nargeqs + slift) t)
+ (mkRel (nargeqs + slift))
+ (lift (nargeqs + nar) argt)
+ (lift (nargeqs + nar) arg)
+ in
+ let sigma, refl = mk_JMeq_refl sigma argt arg in
+ (sigma, eq, refl)
in
let previd, id =
let name =
- match EConstr.kind !evdref arg with
+ match EConstr.kind sigma arg with
Rel n -> RelDecl.get_name (lookup_rel n env)
| _ -> name
in
make_prime avoid name
in
- (env, succ nargeqs,
+ (sigma, env, succ nargeqs,
(LocalAssum (Name (eq_id avoid previd), eq)) :: argeqs,
refl_arg :: refl_args,
pred slift,
RelDecl.set_name (Name id) decl :: argsign'))
- (env, neqs, [], [], slift, []) args argsign
+ (sigma, env, neqs, [], [], slift, []) args argsign
in
- let eq = mk_JMeq evdref
- (lift (nargeqs + slift) appt)
- (mkRel (nargeqs + slift))
- (lift (nargeqs + nar) ty)
- (lift (nargeqs + nar) tm)
+ let sigma, eq =
+ mk_JMeq sigma
+ (lift (nargeqs + slift) appt)
+ (mkRel (nargeqs + slift))
+ (lift (nargeqs + nar) ty)
+ (lift (nargeqs + nar) tm)
in
- let refl_eq = mk_JMeq_refl evdref ty tm in
+ let sigma, refl_eq = mk_JMeq_refl sigma ty tm in
let previd, id = make_prime avoid appn in
- ((LocalAssum (Name (eq_id avoid previd), eq) :: argeqs) :: eqs,
+ (sigma, (LocalAssum (Name (eq_id avoid previd), eq) :: argeqs) :: eqs,
succ nargeqs,
refl_eq :: refl_args,
pred slift,
@@ -2472,18 +2485,20 @@ let build_dependent_signature env evdref avoid tomatchs arsign =
let previd, id = make_prime avoid name in
let arsign' = RelDecl.set_name (Name id) decl in
let tomatch_ty = type_of_tomatch ty in
- let eq =
- mk_eq evdref (lift nar tomatch_ty)
- (mkRel slift) (lift nar tm)
- in
- ([LocalAssum (Name (eq_id avoid previd), eq)] :: eqs, succ neqs,
- (mk_eq_refl evdref tomatch_ty tm) :: refl_args,
- pred slift, (arsign' :: []) :: arsigns))
- ([], 0, [], nar, []) tomatchs arsign
+ let sigma, eq =
+ mk_eq sigma (lift nar tomatch_ty)
+ (mkRel slift) (lift nar tm)
+ in
+ let sigma, refl = mk_eq_refl sigma tomatch_ty tm in
+ (sigma,
+ [LocalAssum (Name (eq_id avoid previd), eq)] :: eqs, succ neqs,
+ refl :: refl_args,
+ pred slift, (arsign' :: []) :: arsigns))
+ (sigma, [], 0, [], nar, []) tomatchs arsign
in
let arsign'' = List.rev arsign' in
assert(Int.equal slift 0); (* we must have folded over all elements of the arity signature *)
- arsign'', allnames, nar, eqs, neqs, refls
+ sigma, arsign'', allnames, nar, eqs, neqs, refls
let context_of_arsign l =
let (x, _) = List.fold_right
@@ -2492,56 +2507,57 @@ let context_of_arsign l =
l ([], 0)
in x
-let compile_program_cases ?loc style (typing_function, evdref) tycon env lvar
+let compile_program_cases ?loc style (typing_function, sigma) tycon env
(predopt, tomatchl, eqns) =
- let typing_fun tycon env = function
- | Some t -> typing_function tycon env evdref lvar t
- | None -> Evarutil.evd_comb0 use_unit_judge evdref in
+ let typing_fun tycon env sigma = function
+ | Some t -> typing_function tycon env sigma t
+ | None -> use_unit_judge sigma in
(* We build the matrix of patterns and right-hand side *)
let matx = matx_of_eqns env eqns in
(* We build the vector of terms to match consistently with the *)
(* constructors found in patterns *)
- let predlvar,tomatchs = coerce_to_indtype typing_function evdref env lvar matx tomatchl in
+ let env, sigma, tomatchs = coerce_to_indtype typing_function env sigma matx tomatchl in
let tycon = valcon_of_tycon tycon in
- let tomatchs, tomatchs_lets, tycon' = abstract_tomatch env !evdref tomatchs tycon in
- let env = push_rel_context tomatchs_lets env in
+ let tomatchs, tomatchs_lets, tycon' = abstract_tomatch env sigma tomatchs tycon in
+ let _,env = push_rel_context sigma tomatchs_lets env in
let len = List.length eqns in
- let sign, allnames, signlen, eqs, neqs, args =
+ let sigma, sign, allnames, signlen, eqs, neqs, args =
(* The arity signature *)
- let arsign = extract_arity_signature ~dolift:false env predlvar tomatchs tomatchl in
- let arsign = List.map fst arsign in (* Because no difference between the arity for typing and the arity for building *)
+ let arsign = extract_arity_signature ~dolift:false !!env tomatchs tomatchl in
(* Build the dependent arity signature, the equalities which makes
the first part of the predicate and their instantiations. *)
let avoid = Id.Set.empty in
- build_dependent_signature env evdref avoid tomatchs arsign
+ build_dependent_signature !!env sigma avoid tomatchs arsign
in
- let tycon, arity =
+ let sigma, tycon, arity =
let nar = List.fold_left (fun n sign -> List.length sign + n) 0 sign in
match tycon' with
- | None -> let ev = mkExistential env evdref in ev, lift nar ev
+ | None ->
+ let sigma, ev = mkExistential !!env sigma in
+ sigma, ev, lift nar ev
| Some t ->
- let pred =
- match prepare_predicate_from_arsign_tycon env !evdref loc tomatchs sign t with
- | Some (evd, pred) -> evdref := evd; pred
- | None ->
- lift nar t
- in Option.get tycon, pred
+ let sigma, pred =
+ match prepare_predicate_from_arsign_tycon env sigma loc tomatchs sign t with
+ | Some (evd, pred, arsign) -> evd, pred
+ | None -> sigma, lift nar t
+ in
+ sigma, Option.get tycon, pred
in
let neqs, arity =
let ctx = context_of_arsign eqs in
let neqs = List.length ctx in
neqs, it_mkProd_or_LetIn (lift neqs arity) ctx
in
- let lets, matx =
+ let sigma, lets, matx =
(* Type the rhs under the assumption of equations *)
- constrs_of_pats typing_fun env evdref matx tomatchs sign neqs arity
+ constrs_of_pats typing_fun env sigma matx tomatchs sign neqs arity
in
let matx = List.rev matx in
let _ = assert (Int.equal len (List.length lets)) in
- let env = push_rel_context lets env in
+ let _,env = push_rel_context sigma lets env in
let matx = List.map (fun eqn -> { eqn with rhs = { eqn.rhs with rhs_env = env } }) matx in
let tomatchs = List.map (fun (x, y) -> lift len x, lift_tomatch_type len y) tomatchs in
let args = List.rev_map (lift len) args in
@@ -2554,33 +2570,32 @@ let compile_program_cases ?loc style (typing_function, evdref) tycon env lvar
let out_tmt na = function NotInd (None,t) -> LocalAssum (na,t)
| NotInd (Some b, t) -> LocalDef (na,b,t)
| IsInd (typ,_,_) -> LocalAssum (na,typ) in
- let typs = List.map2 (fun na (tm,tmt) -> (tm,out_tmt na tmt)) nal tomatchs in
+ let typs = List.map2 (fun (na,_) (tm,tmt) -> (tm,out_tmt na tmt)) nal tomatchs in
let typs =
- List.map (fun (c,d) -> (c,extract_inductive_data env !evdref d,d)) typs in
+ List.map (fun (c,d) -> (c,extract_inductive_data !!env sigma d,d)) typs in
let dep_sign =
- find_dependencies_signature !evdref
+ find_dependencies_signature sigma
(List.make (List.length typs) true)
typs in
let typs' =
List.map3
- (fun (tm,tmt) deps na ->
- let deps = if not (isRel !evdref tm) then [] else deps in
+ (fun (tm,tmt) deps (na,realnames) ->
+ let deps = if not (isRel sigma tm) then [] else deps in
+ let tmt = set_tomatch_realnames realnames tmt in
((tm,tmt),deps,na))
tomatchs dep_sign nal in
let initial_pushed = List.map (fun x -> Pushed (true,x)) typs' in
- let typing_function tycon env evdref = function
- | Some t -> typing_function tycon env evdref lvar t
- | None -> evd_comb0 use_unit_judge evdref in
+ let typing_function tycon env sigma = function
+ | Some t -> typing_function tycon env sigma t
+ | None -> use_unit_judge sigma in
let pb =
{ env = env;
- lvar = lvar;
- evdref = evdref;
pred = pred;
tomatch = initial_pushed;
history = start_history (List.length initial_pushed);
@@ -2589,23 +2604,23 @@ let compile_program_cases ?loc style (typing_function, evdref) tycon env lvar
casestyle= style;
typing_function = typing_function } in
- let j = compile pb in
+ let sigma, j = compile sigma pb in
(* We check for unused patterns *)
- List.iter (check_unused_pattern env) matx;
+ List.iter (check_unused_pattern !!env) matx;
let body = it_mkLambda_or_LetIn (applist (j.uj_val, args)) lets in
let j =
{ uj_val = it_mkLambda_or_LetIn body tomatchs_lets;
(* XXX: is this normalization needed? *)
- uj_type = Evarutil.nf_evar !evdref tycon; }
- in j
+ uj_type = Evarutil.nf_evar sigma tycon; }
+ in sigma, j
(**************************************************************************)
(* Main entry of the matching compilation *)
-let compile_cases ?loc style (typing_fun, evdref) tycon env lvar (predopt, tomatchl, eqns) =
+let compile_cases ?loc style (typing_fun, sigma) tycon env (predopt, tomatchl, eqns) =
if predopt == None && Flags.is_program_mode () && Program.is_program_cases () then
- compile_program_cases ?loc style (typing_fun, evdref)
- tycon env lvar (predopt, tomatchl, eqns)
+ compile_program_cases ?loc style (typing_fun, sigma)
+ tycon env (predopt, tomatchl, eqns)
else
(* We build the matrix of patterns and right-hand side *)
@@ -2613,15 +2628,13 @@ let compile_cases ?loc style (typing_fun, evdref) tycon env lvar (predopt, tomat
(* We build the vector of terms to match consistently with the *)
(* constructors found in patterns *)
- let predlvar,tomatchs = coerce_to_indtype typing_fun evdref env lvar matx tomatchl in
-
-
+ let predenv, sigma, tomatchs = coerce_to_indtype typing_fun env sigma matx tomatchl in
(* If an elimination predicate is provided, we check it is compatible
with the type of arguments to match; if none is provided, we
build alternative possible predicates *)
- let arsign = extract_arity_signature env predlvar tomatchs tomatchl in
- let preds = prepare_predicate ?loc typing_fun env !evdref predlvar tomatchs arsign tycon predopt in
+ let arsign = extract_arity_signature !!env tomatchs tomatchl in
+ let preds = prepare_predicate ?loc typing_fun predenv sigma tomatchs arsign tycon predopt in
let compile_for_one_predicate (sigma,nal,pred) =
(* We push the initial terms to match and push their alias to rhs' envs *)
@@ -2631,36 +2644,33 @@ let compile_cases ?loc style (typing_fun, evdref) tycon env lvar (predopt, tomat
let out_tmt na = function NotInd (None,t) -> LocalAssum (na,t)
| NotInd (Some b,t) -> LocalDef (na,b,t)
| IsInd (typ,_,_) -> LocalAssum (na,typ) in
- let typs = List.map2 (fun na (tm,tmt) -> (tm,out_tmt na tmt)) nal tomatchs in
+ let typs = List.map2 (fun (na,_) (tm,tmt) -> (tm,out_tmt na tmt)) nal tomatchs in
let typs =
- List.map (fun (c,d) -> (c,extract_inductive_data env sigma d,d)) typs in
+ List.map (fun (c,d) -> (c,extract_inductive_data !!env sigma d,d)) typs in
let dep_sign =
- find_dependencies_signature !evdref
+ find_dependencies_signature sigma
(List.make (List.length typs) true)
typs in
let typs' =
List.map3
- (fun (tm,tmt) deps na ->
- let deps = if not (isRel !evdref tm) then [] else deps in
+ (fun (tm,tmt) deps (na,realnames) ->
+ let deps = if not (isRel sigma tm) then [] else deps in
+ let tmt = set_tomatch_realnames realnames tmt in
((tm,tmt),deps,na))
tomatchs dep_sign nal in
let initial_pushed = List.map (fun x -> Pushed (true,x)) typs' in
(* A typing function that provides with a canonical term for absurd cases*)
- let typing_fun tycon env evdref = function
- | Some t -> typing_fun tycon env evdref lvar t
- | None -> evd_comb0 use_unit_judge evdref in
-
- let myevdref = ref sigma in
+ let typing_fun tycon env sigma = function
+ | Some t -> typing_fun tycon env sigma t
+ | None -> use_unit_judge sigma in
let pb =
{ env = env;
- lvar = lvar;
- evdref = myevdref;
pred = pred;
tomatch = initial_pushed;
history = start_history (List.length initial_pushed);
@@ -2669,18 +2679,17 @@ let compile_cases ?loc style (typing_fun, evdref) tycon env lvar (predopt, tomat
casestyle = style;
typing_function = typing_fun } in
- let j = compile pb in
+ let sigma, j = compile sigma pb in
(* We coerce to the tycon (if an elim predicate was provided) *)
- let j = inh_conv_coerce_to_tycon ?loc env myevdref j tycon in
- evdref := !myevdref;
- j in
+ inh_conv_coerce_to_tycon ?loc !!env sigma j tycon
+ in
(* Return the term compiled with the first possible elimination *)
(* predicate for which the compilation succeeds *)
let j = list_try_compile compile_for_one_predicate preds in
(* We check for unused patterns *)
- List.iter (check_unused_pattern env) matx;
+ List.iter (check_unused_pattern !!env) matx;
j
diff --git a/pretyping/cases.mli b/pretyping/cases.mli
index 04a3464679..36cfa0a70d 100644
--- a/pretyping/cases.mli
+++ b/pretyping/cases.mli
@@ -15,7 +15,6 @@ open Environ
open EConstr
open Inductiveops
open Glob_term
-open Ltac_pretype
open Evardefine
(** {5 Compilation of pattern-matching } *)
@@ -42,24 +41,24 @@ val irrefutable : env -> cases_pattern -> bool
val compile_cases :
?loc:Loc.t -> case_style ->
- (type_constraint -> env -> evar_map ref -> ltac_var_map -> glob_constr -> unsafe_judgment) * evar_map ref ->
+ (type_constraint -> GlobEnv.t -> evar_map -> glob_constr -> evar_map * unsafe_judgment) * evar_map ->
type_constraint ->
- env -> ltac_var_map -> glob_constr option * tomatch_tuples * cases_clauses ->
- unsafe_judgment
+ GlobEnv.t -> glob_constr option * tomatch_tuples * cases_clauses ->
+ evar_map * unsafe_judgment
val constr_of_pat :
Environ.env ->
- Evd.evar_map ref ->
+ Evd.evar_map ->
rel_context ->
Glob_term.cases_pattern ->
Names.Id.Set.t ->
- Glob_term.cases_pattern *
+ Evd.evar_map * Glob_term.cases_pattern *
(rel_context * constr *
(types * constr list) * Glob_term.cases_pattern) *
Names.Id.Set.t
type 'a rhs =
- { rhs_env : env;
+ { rhs_env : GlobEnv.t;
rhs_vars : Id.Set.t;
avoid_ids : Id.Set.t;
it : 'a option}
@@ -103,30 +102,26 @@ and pattern_continuation =
| Result of cases_pattern list
type 'a pattern_matching_problem =
- { env : env;
- lvar : Ltac_pretype.ltac_var_map;
- evdref : evar_map ref;
+ { env : GlobEnv.t;
pred : constr;
tomatch : tomatch_stack;
history : pattern_continuation;
mat : 'a matrix;
caseloc : Loc.t option;
casestyle : case_style;
- typing_function: type_constraint -> env -> evar_map ref -> 'a option -> unsafe_judgment }
-
+ typing_function: type_constraint -> GlobEnv.t -> evar_map -> 'a option -> evar_map * unsafe_judgment }
-val compile : 'a pattern_matching_problem -> unsafe_judgment
+val compile : evar_map -> 'a pattern_matching_problem -> evar_map * unsafe_judgment
val prepare_predicate : ?loc:Loc.t ->
(type_constraint ->
- Environ.env -> Evd.evar_map ref -> ltac_var_map -> glob_constr -> unsafe_judgment) ->
- Environ.env ->
+ GlobEnv.t -> Evd.evar_map -> glob_constr -> Evd.evar_map * unsafe_judgment) ->
+ GlobEnv.t ->
Evd.evar_map ->
- Ltac_pretype.ltac_var_map ->
(types * tomatch_type) list ->
- (rel_context * rel_context) list ->
+ rel_context list ->
constr option ->
- glob_constr option -> (Evd.evar_map * Name.t list * constr) list
+ glob_constr option -> (Evd.evar_map * (Name.t * Name.t list) list * constr) list
-val make_return_predicate_ltac_lvar : Evd.evar_map -> Name.t ->
- Glob_term.glob_constr -> constr -> Ltac_pretype.ltac_var_map -> ltac_var_map
+val make_return_predicate_ltac_lvar : GlobEnv.t -> Evd.evar_map -> Name.t ->
+ Glob_term.glob_constr -> constr -> GlobEnv.t
diff --git a/pretyping/cbv.ml b/pretyping/cbv.ml
index da6e26cc4b..265909980b 100644
--- a/pretyping/cbv.ml
+++ b/pretyping/cbv.ml
@@ -187,7 +187,7 @@ let _ = Goptions.declare_bool_option {
Goptions.optwrite = (fun a -> debug_cbv:=a);
}
-let pr_key = function
+let debug_pr_key = function
| ConstKey (sp,_) -> Names.Constant.print sp
| VarKey id -> Names.Id.print id
| RelKey n -> Pp.(str "REL_" ++ int n)
@@ -320,14 +320,14 @@ and norm_head_ref k info env stack normt =
if red_set_ref (info_flags info.infos) normt then
match ref_value_cache info.infos info.tab normt with
| Some body ->
- if !debug_cbv then Feedback.msg_debug Pp.(str "Unfolding " ++ pr_key normt);
+ if !debug_cbv then Feedback.msg_debug Pp.(str "Unfolding " ++ debug_pr_key normt);
strip_appl (shift_value k body) stack
| None ->
- if !debug_cbv then Feedback.msg_debug Pp.(str "Not unfolding " ++ pr_key normt);
+ if !debug_cbv then Feedback.msg_debug Pp.(str "Not unfolding " ++ debug_pr_key normt);
(VAL(0,make_constr_ref k normt),stack)
else
begin
- if !debug_cbv then Feedback.msg_debug Pp.(str "Not unfolding " ++ pr_key normt);
+ if !debug_cbv then Feedback.msg_debug Pp.(str "Not unfolding " ++ debug_pr_key normt);
(VAL(0,make_constr_ref k normt),stack)
end
@@ -455,7 +455,8 @@ let cbv_norm infos constr =
(* constant bodies are normalized at the first expansion *)
let create_cbv_infos flgs env sigma =
let infos = create
- (fun old_info tab c -> cbv_stack_term { tab; infos = old_info; sigma } TOP (subs_id 0) c)
+ ~share:true (** Not used by cbv *)
+ ~repr:(fun old_info tab c -> cbv_stack_term { tab; infos = old_info; sigma } TOP (subs_id 0) c)
flgs
env
(Reductionops.safe_evar_value sigma) in
diff --git a/pretyping/classops.ml b/pretyping/classops.ml
index 542fb5456c..b264e31474 100644
--- a/pretyping/classops.ml
+++ b/pretyping/classops.ml
@@ -16,7 +16,6 @@ open Constr
open Libnames
open Globnames
open Nametab
-open Environ
open Libobject
open Mod_subst
@@ -39,7 +38,7 @@ type cl_info_typ = {
type coe_typ = GlobRef.t
-module CoeTypMap = Refmap_env
+module CoeTypMap = GlobRef.Map_env
type coe_info_typ = {
coe_value : GlobRef.t;
@@ -112,11 +111,18 @@ end
type cl_index = Bijint.Index.t
+let init_class_tab =
+ let open Bijint in
+ add CL_FUN { cl_param = 0 } (add CL_SORT { cl_param = 0 } empty)
+
let class_tab =
- ref (Bijint.empty : cl_info_typ Bijint.t)
+ Summary.ref ~name:"class_tab" (init_class_tab : cl_info_typ Bijint.t)
let coercion_tab =
- ref (CoeTypMap.empty : coe_info_typ CoeTypMap.t)
+ Summary.ref ~name:"coercion_tab" (CoeTypMap.empty : coe_info_typ CoeTypMap.t)
+
+let coercions_in_scope =
+ Summary.ref ~name:"coercions_in_scope" GlobRef.Set_env.empty
module ClPairOrd =
struct
@@ -129,14 +135,7 @@ end
module ClPairMap = Map.Make(ClPairOrd)
let inheritance_graph =
- ref (ClPairMap.empty : inheritance_path ClPairMap.t)
-
-let freeze _ = (!class_tab, !coercion_tab, !inheritance_graph)
-
-let unfreeze (fcl,fco,fig) =
- class_tab:=fcl;
- coercion_tab:=fco;
- inheritance_graph:=fig
+ Summary.ref ~name:"inheritance_graph" (ClPairMap.empty : inheritance_path ClPairMap.t)
(* ajout de nouveaux "objets" *)
@@ -150,21 +149,6 @@ let add_new_coercion coe s =
let add_new_path x y =
inheritance_graph := ClPairMap.add x y !inheritance_graph
-let init () =
- class_tab:= Bijint.empty;
- add_new_class CL_FUN { cl_param = 0 };
- add_new_class CL_SORT { cl_param = 0 };
- coercion_tab:= CoeTypMap.empty;
- inheritance_graph:= ClPairMap.empty
-
-let _ =
- Summary.declare_summary "inh_graph"
- { Summary.freeze_function = freeze;
- Summary.unfreeze_function = unfreeze;
- Summary.init_function = init }
-
-let _ = init()
-
(* class_info : cl_typ -> int * cl_info_typ *)
let class_info cl = Bijint.revmap cl !class_tab
@@ -316,16 +300,16 @@ let lookup_pattern_path_between env (s,t) =
(* rajouter une coercion dans le graphe *)
-let path_printer : (env -> Evd.evar_map -> (Bijint.Index.t * Bijint.Index.t) * inheritance_path -> Pp.t) ref =
- ref (fun _ _ _ -> str "<a class path>")
+let path_printer : ((Bijint.Index.t * Bijint.Index.t) * inheritance_path -> Pp.t) ref =
+ ref (fun _ -> str "<a class path>")
let install_path_printer f = path_printer := f
-let print_path env sigma x = !path_printer env sigma x
+let print_path x = !path_printer x
-let message_ambig env sigma l =
+let message_ambig l =
str"Ambiguous paths:" ++ spc () ++
- prlist_with_sep fnl (fun ijp -> print_path env sigma ijp) l
+ prlist_with_sep fnl print_path l
(* add_coercion_in_graph : coe_index * cl_index * cl_index -> unit
coercion,source,target *)
@@ -339,7 +323,7 @@ let different_class_params i =
| CL_CONST c -> Global.is_polymorphic (ConstRef c)
| _ -> false
-let add_coercion_in_graph env sigma (ic,source,target) =
+let add_coercion_in_graph (ic,source,target) =
let old_inheritance_graph = !inheritance_graph in
let ambig_paths =
(ref [] : ((cl_index * cl_index) * inheritance_path) list ref) in
@@ -381,7 +365,7 @@ let add_coercion_in_graph env sigma (ic,source,target) =
end;
let is_ambig = match !ambig_paths with [] -> false | _ -> true in
if is_ambig && not !Flags.quiet then
- Feedback.msg_info (message_ambig env sigma !ambig_paths)
+ Feedback.msg_info (message_ambig !ambig_paths)
type coercion = {
coercion_type : coe_typ;
@@ -426,7 +410,7 @@ let _ =
optread = (fun () -> !automatically_import_coercions);
optwrite = (:=) automatically_import_coercions }
-let cache_coercion env sigma (_, c) =
+let cache_coercion (_, c) =
let () = add_class c.coercion_source in
let () = add_class c.coercion_target in
let is, _ = class_info c.coercion_source in
@@ -439,15 +423,22 @@ let cache_coercion env sigma (_, c) =
coe_param = c.coercion_params;
} in
let () = add_new_coercion c.coercion_type xf in
- add_coercion_in_graph env sigma (xf,is,it)
+ add_coercion_in_graph (xf,is,it)
let load_coercion _ o =
if !automatically_import_coercions then
- cache_coercion (Global.env ()) Evd.empty o
+ cache_coercion o
+
+let set_coercion_in_scope (_, c) =
+ let r = c.coercion_type in
+ coercions_in_scope := GlobRef.Set_env.add r !coercions_in_scope
let open_coercion i o =
- if Int.equal i 1 && not !automatically_import_coercions then
- cache_coercion (Global.env ()) Evd.empty o
+ if Int.equal i 1 then begin
+ set_coercion_in_scope o;
+ if not !automatically_import_coercions then
+ cache_coercion o
+ end
let subst_coercion (subst, c) =
let coe = subst_coe_typ subst c.coercion_type in
@@ -492,8 +483,8 @@ let inCoercion : coercion -> obj =
open_function = open_coercion;
load_function = load_coercion;
cache_function = (fun objn ->
- let env = Global.env () in cache_coercion env Evd.empty objn
- );
+ set_coercion_in_scope objn;
+ cache_coercion objn);
subst_function = subst_coercion;
classify_function = classify_coercion;
discharge_function = discharge_coercion }
@@ -535,7 +526,7 @@ let coercion_of_reference r =
module CoercionPrinting =
struct
type t = coe_typ
- let compare = RefOrdered.compare
+ let compare = GlobRef.Ordered.compare
let encode = coercion_of_reference
let subst = subst_coe_typ
let printer x = pr_global_env Id.Set.empty x
@@ -553,3 +544,6 @@ let hide_coercion coe =
let coe_info = coercion_info coe in
Some coe_info.coe_param
else None
+
+let is_coercion_in_scope r =
+ GlobRef.Set_env.mem r !coercions_in_scope
diff --git a/pretyping/classops.mli b/pretyping/classops.mli
index af00c0a8dc..7c4842c8ae 100644
--- a/pretyping/classops.mli
+++ b/pretyping/classops.mli
@@ -99,7 +99,7 @@ val lookup_pattern_path_between :
(**/**)
(* Crade *)
val install_path_printer :
- (env -> evar_map -> (cl_index * cl_index) * inheritance_path -> Pp.t) -> unit
+ ((cl_index * cl_index) * inheritance_path -> Pp.t) -> unit
(**/**)
(** {6 This is for printing purpose } *)
@@ -113,3 +113,5 @@ val coercions : unit -> coe_info_typ list
(** [hide_coercion] returns the number of params to skip if the coercion must
be hidden, [None] otherwise; it raises [Not_found] if not a coercion *)
val hide_coercion : coe_typ -> int option
+
+val is_coercion_in_scope : GlobRef.t -> bool
diff --git a/pretyping/coercion.ml b/pretyping/coercion.ml
index 5e3821edf1..e15c00f7dc 100644
--- a/pretyping/coercion.ml
+++ b/pretyping/coercion.ml
@@ -363,12 +363,20 @@ let saturate_evd env evd =
Typeclasses.resolve_typeclasses
~filter:Typeclasses.no_goals ~split:true ~fail:false env evd
+let warn_coercion_not_in_scope =
+ CWarnings.create ~name:"coercion-not-in-scope" ~category:"deprecated"
+ Pp.(fun r -> str "Coercion used but not in scope: " ++
+ Nametab.pr_global_env Id.Set.empty r ++ str ". If you want to use "
+ ++ str "this coercion, please Import the module that contains it.")
+
(* Apply coercion path from p to hj; raise NoCoercion if not applicable *)
let apply_coercion env sigma p hj typ_cl =
try
let j,t,evd =
List.fold_left
(fun (ja,typ_cl,sigma) i ->
+ if not (is_coercion_in_scope i.coe_value) then
+ warn_coercion_not_in_scope i.coe_value;
let isid = i.coe_is_identity in
let isproj = i.coe_is_projection in
let sigma, c = new_global sigma i.coe_value in
@@ -386,7 +394,6 @@ let apply_coercion env sigma p hj typ_cl =
(hj,typ_cl,sigma) p
in evd, j
with NoCoercion as e -> raise e
- | e when CErrors.noncritical e -> anomaly (Pp.str "apply_coercion.")
(* Try to coerce to a funclass; raise NoCoercion if not possible *)
let inh_app_fun_core env evd j =
diff --git a/pretyping/dune b/pretyping/dune
new file mode 100644
index 0000000000..6609b4e328
--- /dev/null
+++ b/pretyping/dune
@@ -0,0 +1,6 @@
+(library
+ (name pretyping)
+ (synopsis "Coq's Type Inference Component (Pretyper)")
+ (public_name coq.pretyping)
+ (wrapped false)
+ (libraries camlp5.gramlib engine))
diff --git a/pretyping/evarconv.ml b/pretyping/evarconv.ml
index 984fa92c0e..7d480b8d48 100644
--- a/pretyping/evarconv.ml
+++ b/pretyping/evarconv.ml
@@ -588,7 +588,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) ts env evd pbty
(* Evar must be undefined since we have flushed evars *)
let () = if !debug_unification then
let open Pp in
- Feedback.msg_notice (v 0 (pr_state appr1 ++ cut () ++ pr_state appr2 ++ cut ())) in
+ Feedback.msg_notice (v 0 (pr_state env evd appr1 ++ cut () ++ pr_state env evd appr2 ++ cut ())) in
match (flex_kind_of_term (fst ts) env evd term1 sk1,
flex_kind_of_term (fst ts) env evd term2 sk2) with
| Flexible (sp1,al1 as ev1), Flexible (sp2,al2 as ev2) ->
@@ -1225,8 +1225,9 @@ let apply_conversion_problem_heuristic ts env evd pbty t1 t2 =
let (term2,l2 as appr2) = try destApp evd t2 with DestKO -> (t2, [||]) in
let () = if !debug_unification then
let open Pp in
- Feedback.msg_notice (v 0 (str "Heuristic:" ++ spc () ++ print_constr t1
- ++ cut () ++ print_constr t2 ++ cut ())) in
+ Feedback.msg_notice (v 0 (str "Heuristic:" ++ spc () ++
+ Termops.Internal.print_constr_env env evd t1 ++ cut () ++
+ Termops.Internal.print_constr_env env evd t2 ++ cut ())) in
let app_empty = Array.is_empty l1 && Array.is_empty l2 in
match EConstr.kind evd term1, EConstr.kind evd term2 with
| Evar (evk1,args1), (Rel _|Var _) when app_empty
@@ -1317,6 +1318,7 @@ let rec solve_unconstrained_evars_with_candidates ts evd =
let rec aux = function
| [] -> user_err Pp.(str "Unsolvable existential variables.")
| a::l ->
+ (* In case of variables, most recent ones come first *)
try
let conv_algo = evar_conv_x ts in
let evd = check_evar_instance evd evk a conv_algo in
@@ -1327,9 +1329,9 @@ let rec solve_unconstrained_evars_with_candidates ts evd =
with
| IllTypedInstance _ -> aux l
| e when Pretype_errors.precatchable_exception e -> aux l in
- (* List.rev is there to favor most dependent solutions *)
- (* and favor progress when used with the refine tactics *)
- let evd = aux (List.rev l) in
+ (* Expected invariant: most dependent solutions come first *)
+ (* so as to favor progress when used with the refine tactics *)
+ let evd = aux l in
solve_unconstrained_evars_with_candidates ts evd
let solve_unconstrained_impossible_cases env evd =
diff --git a/pretyping/evardefine.ml b/pretyping/evardefine.ml
index b452755b10..571be7466c 100644
--- a/pretyping/evardefine.ml
+++ b/pretyping/evardefine.ml
@@ -201,4 +201,4 @@ let lift_tycon n = Option.map (lift n)
let pr_tycon env sigma = function
None -> str "None"
- | Some t -> Termops.print_constr_env env sigma t
+ | Some t -> Termops.Internal.print_constr_env env sigma t
diff --git a/pretyping/evarsolve.ml b/pretyping/evarsolve.ml
index 3f5d186d4e..2dd3721980 100644
--- a/pretyping/evarsolve.ml
+++ b/pretyping/evarsolve.ml
@@ -599,11 +599,12 @@ let solve_pattern_eqn env sigma l c =
let make_projectable_subst aliases sigma evi args =
let sign = evar_filtered_context evi in
let evar_aliases = compute_var_aliases sign sigma in
- let (_,full_subst,cstr_subst) =
- List.fold_right
- (fun decl (args,all,cstrs) ->
+ let (_,full_subst,cstr_subst,_) =
+ List.fold_right_i
+ (fun i decl (args,all,cstrs,revmap) ->
match decl,args with
| LocalAssum (id,c), a::rest ->
+ let revmap = Id.Map.add id i revmap in
let cstrs =
let a',args = decompose_app_vect sigma a in
match EConstr.kind sigma a' with
@@ -611,22 +612,26 @@ let make_projectable_subst aliases sigma evi args =
let l = try Constrmap.find (fst cstr) cstrs with Not_found -> [] in
Constrmap.add (fst cstr) ((args,id)::l) cstrs
| _ -> cstrs in
- (rest,Id.Map.add id [a,normalize_alias_opt sigma aliases a,id] all,cstrs)
+ let all = Int.Map.add i [a,normalize_alias_opt sigma aliases a,id] all in
+ (rest,all,cstrs,revmap)
| LocalDef (id,c,_), a::rest ->
+ let revmap = Id.Map.add id i revmap in
(match EConstr.kind sigma c with
| Var id' ->
let idc = normalize_alias_var sigma evar_aliases id' in
- let sub = try Id.Map.find idc all with Not_found -> [] in
+ let ic, sub =
+ try let ic = Id.Map.find idc revmap in ic, Int.Map.find ic all
+ with Not_found -> i, [] (* e.g. [idc] is a filtered variable: treat [id] as an assumption *) in
if List.exists (fun (c,_,_) -> EConstr.eq_constr sigma a c) sub then
- (rest,all,cstrs)
+ (rest,all,cstrs,revmap)
else
- (rest,
- Id.Map.add idc ((a,normalize_alias_opt sigma aliases a,id)::sub) all,
- cstrs)
+ let all = Int.Map.add ic ((a,normalize_alias_opt sigma aliases a,id)::sub) all in
+ (rest,all,cstrs,revmap)
| _ ->
- (rest,Id.Map.add id [a,normalize_alias_opt sigma aliases a,id] all,cstrs))
- | _ -> anomaly (Pp.str "Instance does not match its signature."))
- sign (Array.rev_to_list args,Id.Map.empty,Constrmap.empty) in
+ let all = Int.Map.add i [a,normalize_alias_opt sigma aliases a,id] all in
+ (rest,all,cstrs,revmap))
+ | _ -> anomaly (Pp.str "Instance does not match its signature.")) 0
+ sign (Array.rev_to_list args,Int.Map.empty,Constrmap.empty,Id.Map.empty) in
(full_subst,cstr_subst)
(*------------------------------------*
@@ -793,11 +798,11 @@ let rec assoc_up_to_alias sigma aliases y yc = function
let rec find_projectable_vars with_evars aliases sigma y subst =
let yc = normalize_alias sigma aliases y in
- let is_projectable idc idcl subst' =
+ let is_projectable idc idcl (subst1,subst2 as subst') =
(* First test if some [id] aliased to [idc] is bound to [y] in [subst] *)
try
let id = assoc_up_to_alias sigma aliases y yc idcl in
- (id,ProjectVar)::subst'
+ (id,ProjectVar)::subst1,subst2
with Not_found ->
(* Then test if [idc] is (indirectly) bound in [subst] to some evar *)
(* projectable on [y] *)
@@ -812,14 +817,18 @@ let rec find_projectable_vars with_evars aliases sigma y subst =
let subst,_ = make_projectable_subst aliases sigma evi argsv in
let l = find_projectable_vars with_evars aliases sigma y subst in
match l with
- | [id',p] -> (id,ProjectEvar (t,evi,id',p))::subst'
+ | [id',p] -> (subst1,(id,ProjectEvar (t,evi,id',p))::subst2)
| _ -> subst'
end
| [] -> subst'
| _ -> anomaly (Pp.str "More than one non var in aliases class of evar instance.")
else
subst' in
- Id.Map.fold is_projectable subst []
+ let subst1,subst2 = Int.Map.fold is_projectable subst ([],[]) in
+ (* We return the substitution with ProjectVar first (from most
+ recent to oldest var), followed by ProjectEvar (from most recent
+ to oldest var too) *)
+ subst1 @ subst2
(* [filter_solution] checks if one and only one possible projection exists
* among a set of solutions to a projection problem *)
@@ -842,25 +851,6 @@ let rec find_solution_type evarenv = function
| (id,ProjectEvar _)::l -> find_solution_type evarenv l
| [] -> assert false
-let is_preferred_projection_over sign (id,p) (id',p') =
- (* We give priority to projection of variables over instantiation of
- an evar considering that the latter is a stronger decision which
- may even procude an incorrect (ill-typed) solution *)
- match p, p' with
- | ProjectEvar _, ProjectVar -> false
- | ProjectVar, ProjectEvar _ -> true
- | _, _ ->
- List.index Id.equal id sign < List.index Id.equal id' sign
-
-let choose_projection evi sols =
- let sign = List.map get_id (evar_filtered_context evi) in
- match sols with
- | y::l ->
- List.fold_right (fun (id,p as x) (id',_ as y) ->
- if is_preferred_projection_over sign x y then x else y)
- l y
- | _ -> assert false
-
(* In case the solution to a projection problem requires the instantiation of
* subsidiary evars, [do_projection_effects] performs them; it
* also try to instantiate the type of those subsidiary evars if their
@@ -1447,12 +1437,8 @@ let rec invert_definition conv_algo choose env evd pbty (evk,argsv as ev) rhs =
let c, p = match sols with
| [] -> raise Not_found
| [id,p] -> (mkVar id, p)
- | _ ->
- if choose then
- let (id,p) = choose_projection evi sols in
- (mkVar id, p)
- else
- raise (NotUniqueInType sols)
+ | (id,p)::_ ->
+ if choose then (mkVar id, p) else raise (NotUniqueInType sols)
in
let ty = lazy (Retyping.get_type_of env !evdref (of_alias t)) in
let evd = do_projection_effects (evar_define conv_algo ~choose) env ty !evdref p in
@@ -1556,7 +1542,8 @@ let rec invert_definition conv_algo choose env evd pbty (evk,argsv as ev) rhs =
let t =
map_constr_with_full_binders !evdref (fun d (env,k) -> push_rel d env, k+1)
imitate envk t in
- t::l
+ (* Less dependent solutions come last *)
+ l@[t]
with e when CErrors.noncritical e -> l in
(match candidates with
| [x] -> x
diff --git a/pretyping/globEnv.ml b/pretyping/globEnv.ml
new file mode 100644
index 0000000000..63a66b471b
--- /dev/null
+++ b/pretyping/globEnv.ml
@@ -0,0 +1,203 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+open Util
+open Pp
+open CErrors
+open Names
+open Environ
+open EConstr
+open Evarutil
+open Termops
+open Vars
+open Ltac_pretype
+
+(** This files provides a level of abstraction for the kind of
+ environment used for type inference (so-called pretyping); in
+ particular:
+ - it supports that term variables can be interpreted as Ltac
+ variables pointing to the effective expected name
+ - it incrementally and lazily computes the renaming of rel
+ variables used to build purely-named evar contexts
+*)
+
+type t = {
+ static_env : env;
+ (** For locating indices *)
+ renamed_env : env;
+ (** For name management *)
+ extra : ext_named_context Lazy.t;
+ (** Delay the computation of the evar extended environment *)
+ lvar : ltac_var_map;
+}
+
+let make env sigma lvar =
+ let get_extra env sigma =
+ let avoid = Environ.ids_of_named_context_val (Environ.named_context_val env) in
+ Context.Rel.fold_outside (fun d acc -> push_rel_decl_to_named_context sigma d acc)
+ (rel_context env) ~init:(empty_csubst, avoid, named_context env) in
+ {
+ static_env = env;
+ renamed_env = env;
+ extra = lazy (get_extra env sigma);
+ lvar = lvar;
+ }
+
+let env env = env.static_env
+
+let vars_of_env env =
+ Id.Set.union (Id.Map.domain env.lvar.ltac_genargs) (vars_of_env env.static_env)
+
+let ltac_interp_id { ltac_idents ; ltac_genargs } id =
+ try Id.Map.find id ltac_idents
+ with Not_found ->
+ if Id.Map.mem id ltac_genargs then
+ user_err (str "Ltac variable" ++ spc () ++ Id.print id ++
+ spc () ++ str "is not bound to an identifier." ++
+ spc () ++str "It cannot be used in a binder.")
+ else id
+
+let ltac_interp_name lvar = Nameops.Name.map (ltac_interp_id lvar)
+
+let push_rel sigma d env =
+ let d' = Context.Rel.Declaration.map_name (ltac_interp_name env.lvar) d in
+ let env = {
+ static_env = push_rel d env.static_env;
+ renamed_env = push_rel d' env.renamed_env;
+ extra = lazy (push_rel_decl_to_named_context sigma d' (Lazy.force env.extra));
+ lvar = env.lvar;
+ } in
+ d', env
+
+let push_rel_context ?(force_names=false) sigma ctx env =
+ let open Context.Rel.Declaration in
+ let ctx' = List.Smart.map (map_name (ltac_interp_name env.lvar)) ctx in
+ let ctx' = if force_names then Namegen.name_context env.renamed_env sigma ctx' else ctx' in
+ let env = {
+ static_env = push_rel_context ctx env.static_env;
+ renamed_env = push_rel_context ctx' env.renamed_env;
+ extra = lazy (List.fold_right (fun d acc -> push_rel_decl_to_named_context sigma d acc) ctx' (Lazy.force env.extra));
+ lvar = env.lvar;
+ } in
+ ctx', env
+
+let push_rec_types sigma (lna,typarray) env =
+ let open Context.Rel.Declaration in
+ let ctxt = Array.map2_i (fun i na t -> Context.Rel.Declaration.LocalAssum (na, lift i t)) lna typarray in
+ let env,ctx = Array.fold_left_map (fun e assum -> let (d,e) = push_rel sigma assum e in (e,d)) env ctxt in
+ Array.map get_name ctx, env
+
+let e_new_evar env evdref ?src ?naming typ =
+ let open Context.Named.Declaration in
+ let inst_vars = List.map (get_id %> mkVar) (named_context env.renamed_env) in
+ let inst_rels = List.rev (rel_list 0 (nb_rel env.renamed_env)) in
+ let (subst, _, nc) = Lazy.force env.extra in
+ let typ' = csubst_subst subst typ in
+ let instance = inst_rels @ inst_vars in
+ let sign = val_of_named_context nc in
+ let sigma = !evdref in
+ let (sigma, e) = new_evar_instance sign sigma typ' ?src ?naming instance in
+ evdref := sigma;
+ e
+
+let e_new_type_evar env evdref ~src =
+ let (evd', s) = Evd.new_sort_variable Evd.univ_flexible_alg !evdref in
+ evdref := evd';
+ e_new_evar env evdref ~src (EConstr.mkSort s)
+
+let hide_variable env expansion id =
+ let lvar = env.lvar in
+ if Id.Map.mem id lvar.ltac_genargs then
+ let lvar = match expansion with
+ | Name id' ->
+ (* We are typically in a situation [match id return P with ... end]
+ which we interpret as [match id' as id' return P with ... end],
+ with [P] interpreted in an environment where [id] is bound to [id'].
+ The variable is already bound to [id'], so nothing to do *)
+ lvar
+ | _ ->
+ (* We are typically in a situation [match id return P with ... end]
+ with [id] bound to a non-variable term [c]. We interpret as
+ [match c as id return P with ... end], and hides [id] while
+ interpreting [P], since it has become a binder and cannot be anymore be
+ substituted by a variable coming from the Ltac substitution. *)
+ { lvar with
+ ltac_uconstrs = Id.Map.remove id lvar.ltac_uconstrs;
+ ltac_constrs = Id.Map.remove id lvar.ltac_constrs;
+ ltac_genargs = Id.Map.remove id lvar.ltac_genargs } in
+ { env with lvar }
+ else
+ env
+
+let protected_get_type_of env sigma c =
+ try Retyping.get_type_of ~lax:true env sigma c
+ with Retyping.RetypeError _ ->
+ user_err
+ (str "Cannot reinterpret " ++ quote (Termops.Internal.print_constr_env env sigma c) ++
+ str " in the current environment.")
+
+let invert_ltac_bound_name env id0 id =
+ try mkRel (pi1 (lookup_rel_id id (rel_context env.static_env)))
+ with Not_found ->
+ user_err (str "Ltac variable " ++ Id.print id0 ++
+ str " depends on pattern variable name " ++ Id.print id ++
+ str " which is not bound in current context.")
+
+let interp_ltac_variable ?loc typing_fun env sigma id =
+ (* Check if [id] is an ltac variable *)
+ try
+ let (ids,c) = Id.Map.find id env.lvar.ltac_constrs in
+ let subst = List.map (invert_ltac_bound_name env id) ids in
+ let c = substl subst c in
+ { uj_val = c; uj_type = protected_get_type_of env.renamed_env sigma c }
+ with Not_found ->
+ try
+ let {closure;term} = Id.Map.find id env.lvar.ltac_uconstrs in
+ let lvar = {
+ ltac_constrs = closure.typed;
+ ltac_uconstrs = closure.untyped;
+ ltac_idents = closure.idents;
+ ltac_genargs = Id.Map.empty; }
+ in
+ (* spiwack: I'm catching [Not_found] potentially too eagerly
+ here, as the call to the main pretyping function is caught
+ inside the try but I want to avoid refactoring this function
+ too much for now. *)
+ typing_fun {env with lvar} term
+ with Not_found ->
+ (* Check if [id] is a ltac variable not bound to a term *)
+ (* and build a nice error message *)
+ if Id.Map.mem id env.lvar.ltac_genargs then begin
+ let Geninterp.Val.Dyn (typ, _) = Id.Map.find id env.lvar.ltac_genargs in
+ user_err ?loc
+ (str "Variable " ++ Id.print id ++ str " should be bound to a term but is \
+ bound to a " ++ Geninterp.Val.pr typ ++ str ".")
+ end;
+ raise Not_found
+
+let interp_ltac_id env id = ltac_interp_id env.lvar id
+
+module ConstrInterpObj =
+struct
+ type ('r, 'g, 't) obj =
+ unbound_ltac_var_map -> env -> Evd.evar_map -> types -> 'g -> constr * Evd.evar_map
+ let name = "constr_interp"
+ let default _ = None
+end
+
+module ConstrInterp = Genarg.Register(ConstrInterpObj)
+
+let register_constr_interp0 = ConstrInterp.register0
+
+let interp_glob_genarg env sigma ty arg =
+ let open Genarg in
+ let GenArg (Glbwit tag, arg) = arg in
+ let interp = ConstrInterp.obj tag in
+ interp env.lvar.ltac_genargs env.renamed_env sigma ty arg
diff --git a/pretyping/globEnv.mli b/pretyping/globEnv.mli
new file mode 100644
index 0000000000..70a7ee6e2f
--- /dev/null
+++ b/pretyping/globEnv.mli
@@ -0,0 +1,88 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+open Names
+open Environ
+open Evd
+open EConstr
+open Ltac_pretype
+
+(** To embed constr in glob_constr *)
+
+val register_constr_interp0 :
+ ('r, 'g, 't) Genarg.genarg_type ->
+ (unbound_ltac_var_map -> env -> evar_map -> types -> 'g -> constr * evar_map) -> unit
+
+(** {6 Pretyping name management} *)
+
+(** The following provides a level of abstraction for the kind of
+ environment used for type inference (so-called pretyping); in
+ particular:
+ - it supports that term variables can be interpreted as Ltac
+ variables pointing to the effective expected name
+ - it incrementally and lazily computes the renaming of rel
+ variables used to build purely-named evar contexts
+*)
+
+(** Type of environment extended with naming and ltac interpretation data *)
+
+type t
+
+(** Build a pretyping environment from an ltac environment *)
+
+val make : env -> evar_map -> ltac_var_map -> t
+
+(** Export the underlying environement *)
+
+val env : t -> env
+
+val vars_of_env : t -> Id.Set.t
+
+(** Push to the environment, returning the declaration(s) with interpreted names *)
+
+val push_rel : evar_map -> rel_declaration -> t -> rel_declaration * t
+val push_rel_context : ?force_names:bool -> evar_map -> rel_context -> t -> rel_context * t
+val push_rec_types : evar_map -> Name.t array * constr array -> t -> Name.t array * t
+
+(** Declare an evar using renaming information *)
+
+val e_new_evar : t -> evar_map ref -> ?src:Evar_kinds.t Loc.located ->
+ ?naming:Namegen.intro_pattern_naming_expr -> constr -> constr
+
+val e_new_type_evar : t -> evar_map ref -> src:Evar_kinds.t Loc.located -> constr
+
+(** [hide_variable env na id] tells to hide the binding of [id] in
+ the ltac environment part of [env] and to additionally rebind
+ it to [id'] in case [na] is some [Name id']. It is useful e.g.
+ for the dual status of [y] as term and binder. This is the case
+ of [match y return p with ... end] which implicitly denotes
+ [match z as z return p with ... end] when [y] is bound to a
+ variable [z] and [match t as y return p with ... end] when [y]
+ is bound to a non-variable term [t]. In the latter case, the
+ binding of [y] to [t] should be hidden in [p]. *)
+
+val hide_variable : t -> Name.t -> Id.t -> t
+
+(** In case a variable is not bound by a term binder, look if it has
+ an interpretation as a term in the ltac_var_map *)
+
+val interp_ltac_variable : ?loc:Loc.t -> (t -> Glob_term.glob_constr -> unsafe_judgment) ->
+ t -> evar_map -> Id.t -> unsafe_judgment
+
+(** Interp an identifier as an ltac variable bound to an identifier,
+ or as the identifier itself if not bound to an ltac variable *)
+
+val interp_ltac_id : t -> Id.t -> Id.t
+
+(** Interpreting a generic argument, typically a "ltac:(...)", taking
+ into account the possible renaming *)
+
+val interp_glob_genarg : t -> evar_map -> constr ->
+ Genarg.glob_generic_argument -> constr * evar_map
diff --git a/pretyping/glob_ops.ml b/pretyping/glob_ops.ml
index 24eb666828..bd13f1d00a 100644
--- a/pretyping/glob_ops.ml
+++ b/pretyping/glob_ops.ml
@@ -15,7 +15,6 @@ open Nameops
open Globnames
open Glob_term
open Evar_kinds
-open Ltac_pretype
(* Untyped intermediate terms, after ASTs and before constr. *)
@@ -577,22 +576,9 @@ let glob_constr_of_closed_cases_pattern p = match DAst.get p with
let glob_constr_of_cases_pattern p = glob_constr_of_cases_pattern_aux false p
-(**********************************************************************)
-(* Interpreting ltac variables *)
-
-open Pp
-open CErrors
-
-let ltac_interp_name { ltac_idents ; ltac_genargs } = function
- | Anonymous -> Anonymous
- | Name id as n ->
- try Name (Id.Map.find id ltac_idents)
- with Not_found ->
- if Id.Map.mem id ltac_genargs then
- user_err (str"Ltac variable"++spc()++ Id.print id ++
- spc()++str"is not bound to an identifier."++spc()++
- str"It cannot be used in a binder.")
- else n
+(* This has to be in some file... *)
+
+open Ltac_pretype
let empty_lvar : ltac_var_map = {
ltac_constrs = Id.Map.empty;
diff --git a/pretyping/glob_ops.mli b/pretyping/glob_ops.mli
index c967f4e884..91a2ef9c1e 100644
--- a/pretyping/glob_ops.mli
+++ b/pretyping/glob_ops.mli
@@ -101,5 +101,4 @@ val glob_constr_of_cases_pattern : 'a cases_pattern_g -> 'a glob_constr_g
val add_patterns_for_params_remove_local_defs : constructor -> 'a cases_pattern_g list -> 'a cases_pattern_g list
-val ltac_interp_name : Ltac_pretype.ltac_var_map -> Name.t -> Name.t
val empty_lvar : Ltac_pretype.ltac_var_map
diff --git a/pretyping/indrec.ml b/pretyping/indrec.ml
index dc900ab814..418fdf2a26 100644
--- a/pretyping/indrec.ml
+++ b/pretyping/indrec.ml
@@ -40,7 +40,7 @@ type recursion_scheme_error =
| NotMutualInScheme of inductive * inductive
| NotAllowedDependentAnalysis of (*isrec:*) bool * inductive
-exception RecursionSchemeError of recursion_scheme_error
+exception RecursionSchemeError of env * recursion_scheme_error
let named_hd env t na = named_hd env (Evd.from_env env) (EConstr.of_constr t) na
let name_assumption env = function
@@ -86,7 +86,7 @@ let mis_make_case_com dep env sigma (ind, u as pind) (mib,mip as specif) kind =
if not (Sorts.List.mem kind (elim_sorts specif)) then
raise
(RecursionSchemeError
- (NotAllowedCaseAnalysis (false, fst (UnivGen.fresh_sort_in_family kind), pind)))
+ (env, NotAllowedCaseAnalysis (false, fst (UnivGen.fresh_sort_in_family kind), pind)))
in
let ndepar = mip.mind_nrealdecls + 1 in
@@ -490,7 +490,7 @@ let mis_make_indrec env sigma ?(force_mutual=false) listdepkind mib u =
let build_case_analysis_scheme env sigma pity dep kind =
let (mib,mip) = lookup_mind_specif env (fst pity) in
if dep && not (Inductiveops.has_dependent_elim mib) then
- raise (RecursionSchemeError (NotAllowedDependentAnalysis (false, fst pity)));
+ raise (RecursionSchemeError (env, NotAllowedDependentAnalysis (false, fst pity)));
mis_make_case_com dep env sigma pity (mib,mip) kind
let is_in_prop mip =
@@ -550,9 +550,9 @@ let check_arities env listdepkind =
let kelim = elim_sorts (mibi,mipi) in
if not (Sorts.List.mem kind kelim) then raise
(RecursionSchemeError
- (NotAllowedCaseAnalysis (true, fst (UnivGen.fresh_sort_in_family kind),(mind,u))))
+ (env, NotAllowedCaseAnalysis (true, fst (UnivGen.fresh_sort_in_family kind),(mind,u))))
else if Int.List.mem ni ln then raise
- (RecursionSchemeError (NotMutualInScheme (mind,mind)))
+ (RecursionSchemeError (env, NotMutualInScheme (mind,mind)))
else ni::ln)
[] listdepkind
in true
@@ -561,7 +561,7 @@ let build_mutual_induction_scheme env sigma ?(force_mutual=false) = function
| ((mind,u),dep,s)::lrecspec ->
let (mib,mip) = lookup_mind_specif env mind in
if dep && not (Inductiveops.has_dependent_elim mib) then
- raise (RecursionSchemeError (NotAllowedDependentAnalysis (true, mind)));
+ raise (RecursionSchemeError (env, NotAllowedDependentAnalysis (true, mind)));
let (sp,tyi) = mind in
let listdepkind =
((mind,u),mib,mip,dep,s)::
@@ -572,7 +572,7 @@ let build_mutual_induction_scheme env sigma ?(force_mutual=false) = function
let (mibi',mipi') = lookup_mind_specif env mind' in
((mind',u'),mibi',mipi',dep',s')
else
- raise (RecursionSchemeError (NotMutualInScheme (mind,mind'))))
+ raise (RecursionSchemeError (env, NotMutualInScheme (mind,mind'))))
lrecspec)
in
let _ = check_arities env listdepkind in
@@ -582,7 +582,7 @@ let build_mutual_induction_scheme env sigma ?(force_mutual=false) = function
let build_induction_scheme env sigma pind dep kind =
let (mib,mip) = lookup_mind_specif env (fst pind) in
if dep && not (Inductiveops.has_dependent_elim mib) then
- raise (RecursionSchemeError (NotAllowedDependentAnalysis (true, fst pind)));
+ raise (RecursionSchemeError (env, NotAllowedDependentAnalysis (true, fst pind)));
let sigma, l = mis_make_indrec env sigma [(pind,mib,mip,dep,kind)] mib (snd pind) in
sigma, List.hd l
diff --git a/pretyping/indrec.mli b/pretyping/indrec.mli
index de9d3a0abf..91a5651f7f 100644
--- a/pretyping/indrec.mli
+++ b/pretyping/indrec.mli
@@ -20,7 +20,7 @@ type recursion_scheme_error =
| NotMutualInScheme of inductive * inductive
| NotAllowedDependentAnalysis of (*isrec:*) bool * inductive
-exception RecursionSchemeError of recursion_scheme_error
+exception RecursionSchemeError of env * recursion_scheme_error
(** Eliminations *)
diff --git a/pretyping/inductiveops.ml b/pretyping/inductiveops.ml
index b379cdf410..0fa573b9a6 100644
--- a/pretyping/inductiveops.ml
+++ b/pretyping/inductiveops.ml
@@ -358,7 +358,7 @@ let make_case_or_project env sigma indf ci pred c branches =
not (has_dependent_elim mib) then
user_err ~hdr:"make_case_or_project"
Pp.(str"Dependent case analysis not allowed" ++
- str" on inductive type " ++ Names.MutInd.print (fst ind))
+ str" on inductive type " ++ Termops.Internal.print_constr_env env sigma (mkInd ind))
in
let branch = branches.(0) in
let ctx, br = decompose_lam_n_assum sigma (Array.length ps) branch in
@@ -633,7 +633,7 @@ let is_predicate_explicitly_dep env sigma pred arsign =
dependency status (of course, Anonymous implies non
dependent, but not conversely).
- From Coq > 8.2, using or not the the effective dependency of
+ From Coq > 8.2, using or not the effective dependency of
the predicate is parametrable! *)
begin match na with
diff --git a/pretyping/inferCumulativity.ml b/pretyping/inferCumulativity.ml
index eb283a0220..be79b8b07d 100644
--- a/pretyping/inferCumulativity.ml
+++ b/pretyping/inferCumulativity.ml
@@ -99,7 +99,7 @@ let rec infer_fterm cv_pb infos variances hd stk =
| FEvar ((_,args),e) ->
let variances = infer_stack infos variances stk in
infer_vect infos variances (Array.map (mk_clos e) args)
- | FRel _ -> variances
+ | FRel _ -> infer_stack infos variances stk
| FFlex fl ->
let variances = infer_table_key infos variances fl in
infer_stack infos variances stk
diff --git a/pretyping/ltac_pretype.ml b/pretyping/ltac_pretype.ml
index be8579c2e5..ac59b96eef 100644
--- a/pretyping/ltac_pretype.ml
+++ b/pretyping/ltac_pretype.ml
@@ -64,5 +64,5 @@ type ltac_var_map = {
ltac_idents: Id.t Id.Map.t;
(** Ltac variables bound to identifiers *)
ltac_genargs : unbound_ltac_var_map;
- (** Ltac variables bound to other kinds of arguments *)
+ (** All Ltac variables (to pass on ltac subterms, and for error reporting) *)
}
diff --git a/pretyping/nativenorm.ml b/pretyping/nativenorm.ml
index 5df41ef76a..20185363e6 100644
--- a/pretyping/nativenorm.ml
+++ b/pretyping/nativenorm.ml
@@ -123,7 +123,7 @@ let construct_of_constr_notnative const env tag (mind, _ as ind) u allargs =
try
if const then
let ctyp = type_constructor mind mib u (mip.mind_nf_lc.(0)) params in
- Retroknowledge.get_vm_decompile_constant_info env.retroknowledge (mkInd ind) tag, ctyp
+ Retroknowledge.get_vm_decompile_constant_info env.retroknowledge (GlobRef.IndRef ind) tag, ctyp
else
raise Not_found
with Not_found ->
@@ -354,9 +354,8 @@ and nf_atom_type env sigma atom =
let env = push_rel (LocalAssum (n,dom)) env in
let codom,s2 = nf_type_sort env sigma (codom vn) in
mkProd(n,dom,codom), Typeops.type_of_product env n s1 s2
- | Aevar(evk,ty,args) ->
- let ty = nf_type env sigma ty in
- nf_evar env sigma evk ty args
+ | Aevar(evk,args) ->
+ nf_evar env sigma evk args
| Ameta(mv,ty) ->
let ty = nf_type env sigma ty in
mkMeta mv, ty
@@ -398,22 +397,27 @@ and nf_predicate env sigma ind mip params v pT =
mkLambda(name,dom,body)
| _ -> nf_type env sigma v
-and nf_evar env sigma evk ty args =
+and nf_evar env sigma evk args =
let evi = try Evd.find sigma evk with Not_found -> assert false in
let hyps = Environ.named_context_of_val (Evd.evar_filtered_hyps evi) in
+ let ty = EConstr.Unsafe.to_constr @@ Evd.evar_concl evi in
if List.is_empty hyps then begin
assert (Int.equal (Array.length args) 0);
mkEvar (evk, [||]), ty
end
else
+ (** Let-bound arguments are present in the evar arguments but not in the
+ type, so we turn the let into a product. *)
+ let hyps = Context.Named.drop_bodies hyps in
let fold accu d = Term.mkNamedProd_or_LetIn d accu in
let t = List.fold_left fold ty hyps in
let ty, args = nf_args env sigma args t in
- mkEvar (evk, Array.of_list args), ty
+ (** nf_args takes arguments in the reverse order but produces them in the
+ correct one, so we have to reverse them again for the evar node *)
+ mkEvar (evk, Array.rev_of_list args), ty
let evars_of_evar_map sigma =
{ Nativelambda.evars_val = Evd.existential_opt_value0 sigma;
- Nativelambda.evars_typ = Evd.existential_type0 sigma;
Nativelambda.evars_metas = Evd.meta_type0 sigma }
(* fork perf process, return profiler's process id *)
diff --git a/pretyping/pretyping.ml b/pretyping/pretyping.ml
index 3b9a8e6a1d..162adf0626 100644
--- a/pretyping/pretyping.ml
+++ b/pretyping/pretyping.ml
@@ -38,19 +38,20 @@ open Reductionops
open Type_errors
open Typing
open Globnames
-open Nameops
open Evarutil
open Evardefine
open Pretype_errors
open Glob_term
open Glob_ops
+open GlobEnv
open Evarconv
-open Ltac_pretype
module NamedDecl = Context.Named.Declaration
type typing_constraint = OfType of types | IsType | WithoutTypeConstraint
+let (!!) env = GlobEnv.env env
+
(************************************************************************)
(* This concerns Cases *)
open Inductive
@@ -58,60 +59,6 @@ open Inductiveops
(************************************************************************)
-module ExtraEnv =
-struct
-
-type t = {
- env : Environ.env;
- extra : Evarutil.ext_named_context Lazy.t;
- (** Delay the computation of the evar extended environment *)
-}
-
-let get_extra env sigma =
- let open Context.Named.Declaration in
- let ids = List.map get_id (named_context env) in
- let avoid = List.fold_right Id.Set.add ids Id.Set.empty in
- Context.Rel.fold_outside (fun d acc -> push_rel_decl_to_named_context sigma d acc)
- (rel_context env) ~init:(empty_csubst, avoid, named_context env)
-
-let make_env env sigma = { env = env; extra = lazy (get_extra env sigma) }
-let rel_context env = rel_context env.env
-
-let push_rel sigma d env = {
- env = push_rel d env.env;
- extra = lazy (push_rel_decl_to_named_context sigma d (Lazy.force env.extra));
-}
-
-let pop_rel_context n env sigma = make_env (pop_rel_context n env.env) sigma
-
-let push_rel_context sigma ctx env = {
- env = push_rel_context ctx env.env;
- extra = lazy (List.fold_right (fun d acc -> push_rel_decl_to_named_context sigma d acc) ctx (Lazy.force env.extra));
-}
-
-let lookup_named id env = lookup_named id env.env
-
-let e_new_evar env evdref ?src ?naming typ =
- let open Context.Named.Declaration in
- let inst_vars = List.map (get_id %> mkVar) (named_context env.env) in
- let inst_rels = List.rev (rel_list 0 (nb_rel env.env)) in
- let (subst, _, nc) = Lazy.force env.extra in
- let typ' = csubst_subst subst typ in
- let instance = inst_rels @ inst_vars in
- let sign = val_of_named_context nc in
- let sigma = !evdref in
- let (sigma, e) = new_evar_instance sign sigma typ' ?src ?naming instance in
- evdref := sigma;
- e
-
-let push_rec_types sigma (lna,typarray,_) env =
- let ctxt = Array.map2_i (fun i na t -> Context.Rel.Declaration.LocalAssum (na, lift i t)) lna typarray in
- Array.fold_left (fun e assum -> push_rel sigma assum e) env ctxt
-
-end
-
-open ExtraEnv
-
(* An auxiliary function for searching for fixpoint guard indexes *)
exception Found of int array
@@ -402,7 +349,7 @@ let adjust_evar_source evdref na c =
let inh_conv_coerce_to_tycon ?loc resolve_tc env evdref j = function
| None -> j
| Some t ->
- evd_comb2 (Coercion.inh_conv_coerce_to ?loc resolve_tc env.ExtraEnv.env) evdref j t
+ evd_comb2 (Coercion.inh_conv_coerce_to ?loc resolve_tc !!env) evdref j t
let check_instance loc subst = function
| [] -> ()
@@ -419,76 +366,21 @@ let orelse_name name name' = match name with
| Anonymous -> name'
| _ -> name
-let ltac_interp_name_env k0 lvar env sigma =
- (* envhd is the initial part of the env when pretype was called first *)
- (* (in practice is is probably 0, but we have to grant the
- specification of pretype which accepts to start with a non empty
- rel_context) *)
- (* tail is the part of the env enriched by pretyping *)
- let n = Context.Rel.length (rel_context env) - k0 in
- let ctxt,_ = List.chop n (rel_context env) in
- let open Context.Rel.Declaration in
- let ctxt' = List.Smart.map (map_name (ltac_interp_name lvar)) ctxt in
- if List.equal (fun d1 d2 -> Name.equal (get_name d1) (get_name d2)) ctxt ctxt' then env
- else push_rel_context sigma ctxt' (pop_rel_context n env sigma)
-
-let invert_ltac_bound_name lvar env id0 id =
- let id' = Id.Map.find id lvar.ltac_idents in
- try mkRel (pi1 (lookup_rel_id id' (rel_context env)))
- with Not_found ->
- user_err (str "Ltac variable " ++ Id.print id0 ++
- str " depends on pattern variable name " ++ Id.print id ++
- str " which is not bound in current context.")
-
-let protected_get_type_of env sigma c =
- try Retyping.get_type_of ~lax:true env.ExtraEnv.env sigma c
- with Retyping.RetypeError _ ->
- user_err
- (str "Cannot reinterpret " ++ quote (print_constr c) ++
- str " in the current environment.")
-
-let pretype_id pretype k0 loc env evdref lvar id =
- let sigma = !evdref in
+let pretype_id pretype k0 loc env evdref id =
(* Look for the binder of [id] *)
try
- let (n,_,typ) = lookup_rel_id id (rel_context env) in
+ let (n,_,typ) = lookup_rel_id id (rel_context !!env) in
{ uj_val = mkRel n; uj_type = lift n typ }
with Not_found ->
- let env = ltac_interp_name_env k0 lvar env !evdref in
- (* Check if [id] is an ltac variable *)
- try
- let (ids,c) = Id.Map.find id lvar.ltac_constrs in
- let subst = List.map (invert_ltac_bound_name lvar env id) ids in
- let c = substl subst c in
- { uj_val = c; uj_type = protected_get_type_of env sigma c }
- with Not_found -> try
- let {closure;term} = Id.Map.find id lvar.ltac_uconstrs in
- let lvar = {
- ltac_constrs = closure.typed;
- ltac_uconstrs = closure.untyped;
- ltac_idents = closure.idents;
- ltac_genargs = Id.Map.empty; }
- in
- (* spiwack: I'm catching [Not_found] potentially too eagerly
- here, as the call to the main pretyping function is caught
- inside the try but I want to avoid refactoring this function
- too much for now. *)
- pretype env evdref lvar term
- with Not_found ->
- (* Check if [id] is a ltac variable not bound to a term *)
- (* and build a nice error message *)
- if Id.Map.mem id lvar.ltac_genargs then begin
- let Geninterp.Val.Dyn (typ, _) = Id.Map.find id lvar.ltac_genargs in
- user_err ?loc
- (str "Variable " ++ Id.print id ++ str " should be bound to a term but is \
- bound to a " ++ Geninterp.Val.pr typ ++ str ".")
- end;
- (* Check if [id] is a section or goal variable *)
- try
- { uj_val = mkVar id; uj_type = NamedDecl.get_type (lookup_named id env) }
- with Not_found ->
- (* [id] not found, standard error message *)
- error_var_not_found ?loc id
+ try
+ GlobEnv.interp_ltac_variable ?loc (fun env -> pretype env evdref) env !evdref id
+ with Not_found ->
+ (* Check if [id] is a section or goal variable *)
+ try
+ { uj_val = mkVar id; uj_type = NamedDecl.get_type (lookup_named id !!env) }
+ with Not_found ->
+ (* [id] not found, standard error message *)
+ error_var_not_found ?loc id
(*************************************************************************)
(* Main pretyping function *)
@@ -526,18 +418,18 @@ let pretype_global ?loc rigid env evd gr us =
match us with
| None -> evd, None
| Some l ->
- let _, ctx = Global.constr_of_global_in_context env.ExtraEnv.env gr in
+ let _, ctx = Global.constr_of_global_in_context !!env gr in
let len = Univ.AUContext.size ctx in
interp_instance ?loc evd ~len l
in
- let (sigma, c) = Evd.fresh_global ?loc ~rigid ?names:instance env.ExtraEnv.env evd gr in
+ let (sigma, c) = Evd.fresh_global ?loc ~rigid ?names:instance !!env evd gr in
(sigma, c)
let pretype_ref ?loc evdref env ref us =
match ref with
| VarRef id ->
(* Section variable *)
- (try make_judge (mkVar id) (NamedDecl.get_type (lookup_named id env))
+ (try make_judge (mkVar id) (NamedDecl.get_type (lookup_named id !!env))
with Not_found ->
(* This may happen if env is a goal env and section variables have
been cleared - section variables should be different from goal
@@ -546,7 +438,7 @@ let pretype_ref ?loc evdref env ref us =
| ref ->
let evd, c = pretype_global ?loc univ_flexible env !evdref ref us in
let () = evdref := evd in
- let ty = unsafe_type_of env.ExtraEnv.env evd c in
+ let ty = unsafe_type_of !!env evd c in
make_judge c ty
let judge_of_Type ?loc evd s =
@@ -562,31 +454,13 @@ let pretype_sort ?loc evdref = function
| GType s -> evd_comb1 (judge_of_Type ?loc) evdref s
let new_type_evar env evdref loc =
- let sigma = !evdref in
- let (sigma, (e, _)) =
- Evarutil.new_type_evar env.ExtraEnv.env sigma
- univ_flexible_alg ~src:(loc,Evar_kinds.InternalHole)
- in
- evdref := sigma;
- e
-
-module ConstrInterpObj =
-struct
- type ('r, 'g, 't) obj =
- unbound_ltac_var_map -> env -> evar_map -> types -> 'g -> constr * evar_map
- let name = "constr_interp"
- let default _ = None
-end
-
-module ConstrInterp = Genarg.Register(ConstrInterpObj)
-
-let register_constr_interp0 = ConstrInterp.register0
+ e_new_type_evar env evdref ~src:(Loc.tag ?loc Evar_kinds.InternalHole)
(* [pretype tycon env evdref lvar lmeta cstr] attempts to type [cstr] *)
(* in environment [env], with existential variables [evdref] and *)
(* the type constraint tycon *)
-let rec pretype k0 resolve_tc (tycon : type_constraint) (env : ExtraEnv.t) evdref (lvar : ltac_var_map) t =
+let rec pretype k0 resolve_tc (tycon : type_constraint) (env : GlobEnv.t) evdref t =
let inh_conv_coerce_to_tycon ?loc = inh_conv_coerce_to_tycon ?loc resolve_tc in
let pretype_type = pretype_type k0 resolve_tc in
let pretype = pretype k0 resolve_tc in
@@ -600,24 +474,24 @@ let rec pretype k0 resolve_tc (tycon : type_constraint) (env : ExtraEnv.t) evdre
| GVar id ->
inh_conv_coerce_to_tycon ?loc env evdref
- (pretype_id (fun e r l t -> pretype tycon e r l t) k0 loc env evdref lvar id)
+ (pretype_id (fun e r t -> pretype tycon e r t) k0 loc env evdref id)
tycon
| GEvar (id, inst) ->
(* Ne faudrait-il pas s'assurer que hyps est bien un
sous-contexte du contexte courant, et qu'il n'y a pas de Rel "caché" *)
+ let id = interp_ltac_id env id in
let evk =
try Evd.evar_key id !evdref
with Not_found ->
user_err ?loc (str "Unknown existential variable.") in
let hyps = evar_filtered_context (Evd.find !evdref evk) in
- let args = pretype_instance k0 resolve_tc env evdref lvar loc hyps evk inst in
+ let args = pretype_instance k0 resolve_tc env evdref loc hyps evk inst in
let c = mkEvar (evk, args) in
- let j = (Retyping.get_judgment_of env.ExtraEnv.env !evdref c) in
+ let j = (Retyping.get_judgment_of !!env !evdref c) in
inh_conv_coerce_to_tycon ?loc env evdref j tycon
| GPatVar kind ->
- let env = ltac_interp_name_env k0 lvar env !evdref in
let ty =
match tycon with
| Some ty -> ty
@@ -626,48 +500,45 @@ let rec pretype k0 resolve_tc (tycon : type_constraint) (env : ExtraEnv.t) evdre
{ uj_val = e_new_evar env evdref ~src:(loc,k) ty; uj_type = ty }
| GHole (k, naming, None) ->
- let env = ltac_interp_name_env k0 lvar env !evdref in
+ let open Namegen in
+ let naming = match naming with
+ | IntroIdentifier id -> IntroIdentifier (interp_ltac_id env id)
+ | IntroAnonymous -> IntroAnonymous
+ | IntroFresh id -> IntroFresh (interp_ltac_id env id) in
let ty =
match tycon with
| Some ty -> ty
- | None ->
- new_type_evar env evdref loc in
+ | None -> new_type_evar env evdref loc in
{ uj_val = e_new_evar env evdref ~src:(loc,k) ~naming ty; uj_type = ty }
| GHole (k, _naming, Some arg) ->
- let env = ltac_interp_name_env k0 lvar env !evdref in
let ty =
match tycon with
| Some ty -> ty
- | None ->
- new_type_evar env evdref loc in
- let open Genarg in
- let ist = lvar.ltac_genargs in
- let GenArg (Glbwit tag, arg) = arg in
- let interp = ConstrInterp.obj tag in
- let (c, sigma) = interp ist env.ExtraEnv.env !evdref ty arg in
+ | None -> new_type_evar env evdref loc in
+ let (c, sigma) = GlobEnv.interp_glob_genarg env !evdref ty arg in
let () = evdref := sigma in
{ uj_val = c; uj_type = ty }
| GRec (fixkind,names,bl,lar,vdef) ->
let rec type_bl env ctxt = function
- [] -> ctxt
+ | [] -> ctxt
| (na,bk,None,ty)::bl ->
- let ty' = pretype_type empty_valcon env evdref lvar ty in
+ let ty' = pretype_type empty_valcon env evdref ty in
let dcl = LocalAssum (na, ty'.utj_val) in
- let dcl' = LocalAssum (ltac_interp_name lvar na,ty'.utj_val) in
- type_bl (push_rel !evdref dcl env) (Context.Rel.add dcl' ctxt) bl
+ let dcl', env = push_rel !evdref dcl env in
+ type_bl env (Context.Rel.add dcl' ctxt) bl
| (na,bk,Some bd,ty)::bl ->
- let ty' = pretype_type empty_valcon env evdref lvar ty in
- let bd' = pretype (mk_tycon ty'.utj_val) env evdref lvar bd in
+ let ty' = pretype_type empty_valcon env evdref ty in
+ let bd' = pretype (mk_tycon ty'.utj_val) env evdref bd in
let dcl = LocalDef (na, bd'.uj_val, ty'.utj_val) in
- let dcl' = LocalDef (ltac_interp_name lvar na, bd'.uj_val, ty'.utj_val) in
- type_bl (push_rel !evdref dcl env) (Context.Rel.add dcl' ctxt) bl in
+ let dcl', env = push_rel !evdref dcl env in
+ type_bl env (Context.Rel.add dcl' ctxt) bl in
let ctxtv = Array.map (type_bl env Context.Rel.empty) bl in
let larj =
Array.map2
(fun e ar ->
- pretype_type empty_valcon (push_rel_context !evdref e env) evdref lvar ar)
+ pretype_type empty_valcon (snd (push_rel_context !evdref e env)) evdref ar)
ctxtv lar in
let lara = Array.map (fun a -> a.utj_val) larj in
let ftys = Array.map2 (fun e a -> it_mkProd_or_LetIn a e) ctxtv lara in
@@ -680,14 +551,14 @@ let rec pretype k0 resolve_tc (tycon : type_constraint) (env : ExtraEnv.t) evdre
| GFix (vn,i) -> i
| GCoFix i -> i
in
- begin match conv env.ExtraEnv.env !evdref ftys.(fixi) t with
+ begin match conv !!env !evdref ftys.(fixi) t with
| None -> ()
| Some sigma -> evdref := sigma
end
| None -> ()
in
(* Note: bodies are not used by push_rec_types, so [||] is safe *)
- let newenv = push_rec_types !evdref (names,ftys,[||]) env in
+ let names,newenv = push_rec_types !evdref (names,ftys) env in
let vdefj =
Array.map2_i
(fun i ctxt def ->
@@ -696,12 +567,12 @@ let rec pretype k0 resolve_tc (tycon : type_constraint) (env : ExtraEnv.t) evdre
let (ctxt,ty) =
decompose_prod_n_assum !evdref (Context.Rel.length ctxt)
(lift nbfix ftys.(i)) in
- let nenv = push_rel_context !evdref ctxt newenv in
- let j = pretype (mk_tycon ty) nenv evdref lvar def in
+ let ctxt,nenv = push_rel_context !evdref ctxt newenv in
+ let j = pretype (mk_tycon ty) nenv evdref def in
{ uj_val = it_mkLambda_or_LetIn j.uj_val ctxt;
uj_type = it_mkProd_or_LetIn j.uj_type ctxt })
ctxtv vdef in
- evdref := Typing.check_type_fixpoint ?loc env.ExtraEnv.env !evdref names ftys vdefj;
+ evdref := Typing.check_type_fixpoint ?loc !!env !evdref names ftys vdefj;
let nf c = nf_evar !evdref c in
let ftys = Array.map nf ftys in (** FIXME *)
let fdefs = Array.map (fun x -> nf (j_val x)) vdefj in
@@ -723,13 +594,13 @@ let rec pretype k0 resolve_tc (tycon : type_constraint) (env : ExtraEnv.t) evdre
let fixdecls = (names,ftys,fdefs) in
let indexes =
search_guard
- ?loc env.ExtraEnv.env possible_indexes (nf_fix !evdref fixdecls)
+ ?loc !!env possible_indexes (nf_fix !evdref fixdecls)
in
make_judge (mkFix ((indexes,i),fixdecls)) ftys.(i)
| GCoFix i ->
let fixdecls = (names,ftys,fdefs) in
let cofix = (i, fixdecls) in
- (try check_cofix env.ExtraEnv.env (i, nf_fix !evdref fixdecls)
+ (try check_cofix !!env (i, nf_fix !evdref fixdecls)
with reraise ->
let (e, info) = CErrors.push reraise in
let info = Option.cata (Loc.add_loc info) info loc in
@@ -744,11 +615,11 @@ let rec pretype k0 resolve_tc (tycon : type_constraint) (env : ExtraEnv.t) evdre
| GProj (p, c) ->
(* TODO: once GProj is used as an input syntax, use bidirectional typing here *)
- let cj = pretype empty_tycon env evdref lvar c in
- judge_of_projection env.ExtraEnv.env !evdref p cj
+ let cj = pretype empty_tycon env evdref c in
+ judge_of_projection !!env !evdref p cj
| GApp (f,args) ->
- let fj = pretype empty_tycon env evdref lvar f in
+ let fj = pretype empty_tycon env evdref f in
let floc = loc_of_glob_constr f in
let length = List.length args in
let candargs =
@@ -764,7 +635,7 @@ let rec pretype k0 resolve_tc (tycon : type_constraint) (env : ExtraEnv.t) evdre
if Int.equal npars 0 then []
else
try
- let IndType (indf, args) = find_rectype env.ExtraEnv.env !evdref ty in
+ let IndType (indf, args) = find_rectype !!env !evdref ty in
let ((ind',u'),pars) = dest_ind_family indf in
if eq_ind ind ind' then List.map EConstr.of_constr pars
else (* Let the usual code throw an error *) []
@@ -786,17 +657,17 @@ let rec pretype k0 resolve_tc (tycon : type_constraint) (env : ExtraEnv.t) evdre
| [] -> resj
| c::rest ->
let argloc = loc_of_glob_constr c in
- let resj = evd_comb1 (Coercion.inh_app_fun resolve_tc env.ExtraEnv.env) evdref resj in
- let resty = whd_all env.ExtraEnv.env !evdref resj.uj_type in
+ let resj = evd_comb1 (Coercion.inh_app_fun resolve_tc !!env) evdref resj in
+ let resty = whd_all !!env !evdref resj.uj_type in
match EConstr.kind !evdref resty with
| Prod (na,c1,c2) ->
let tycon = Some c1 in
- let hj = pretype tycon env evdref lvar c in
+ let hj = pretype tycon env evdref c in
let candargs, ujval =
match candargs with
| [] -> [], j_val hj
| arg :: args ->
- begin match conv env.ExtraEnv.env !evdref (j_val hj) arg with
+ begin match conv !!env !evdref (j_val hj) arg with
| Some sigma -> evdref := sigma;
args, nf_evar !evdref (j_val hj)
| None ->
@@ -809,104 +680,96 @@ let rec pretype k0 resolve_tc (tycon : type_constraint) (env : ExtraEnv.t) evdre
apply_rec env (n+1) j candargs rest
| _ ->
- let hj = pretype empty_tycon env evdref lvar c in
+ let hj = pretype empty_tycon env evdref c in
error_cant_apply_not_functional
- ?loc:(Loc.merge_opt floc argloc) env.ExtraEnv.env !evdref
+ ?loc:(Loc.merge_opt floc argloc) !!env !evdref
resj [|hj|]
in
let resj = apply_rec env 1 fj candargs args in
let resj =
match EConstr.kind !evdref resj.uj_val with
| App (f,args) ->
- if is_template_polymorphic env.ExtraEnv.env !evdref f then
+ if is_template_polymorphic !!env !evdref f then
(* Special case for inductive type applications that must be
refreshed right away. *)
let c = mkApp (f, args) in
- let c = evd_comb1 (Evarsolve.refresh_universes (Some true) env.ExtraEnv.env) evdref c in
- let t = Retyping.get_type_of env.ExtraEnv.env !evdref c in
+ let c = evd_comb1 (Evarsolve.refresh_universes (Some true) !!env) evdref c in
+ let t = Retyping.get_type_of !!env !evdref c in
make_judge c (* use this for keeping evars: resj.uj_val *) t
else resj
| _ -> resj
in
inh_conv_coerce_to_tycon ?loc env evdref resj tycon
- | GLambda(name,bk,c1,c2) ->
+ | GLambda(name,bk,c1,c2) ->
let tycon' = evd_comb1
(fun evd tycon ->
match tycon with
| None -> evd, tycon
| Some ty ->
- let evd, ty' = Coercion.inh_coerce_to_prod ?loc env.ExtraEnv.env evd ty in
+ let evd, ty' = Coercion.inh_coerce_to_prod ?loc !!env evd ty in
evd, Some ty')
evdref tycon
in
- let (name',dom,rng) = evd_comb1 (split_tycon ?loc env.ExtraEnv.env) evdref tycon' in
+ let (name',dom,rng) = evd_comb1 (split_tycon ?loc !!env) evdref tycon' in
let dom_valcon = valcon_of_tycon dom in
- let j = pretype_type dom_valcon env evdref lvar c1 in
- (* The name specified by ltac is used also to create bindings. So
- the substitution must also be applied on variables before they are
- looked up in the rel context. *)
+ let j = pretype_type dom_valcon env evdref c1 in
let var = LocalAssum (name, j.utj_val) in
- let j' = pretype rng (push_rel !evdref var env) evdref lvar c2 in
- let name = ltac_interp_name lvar name in
- let resj = judge_of_abstraction env.ExtraEnv.env (orelse_name name name') j j' in
+ let var',env' = push_rel !evdref var env in
+ let j' = pretype rng env' evdref c2 in
+ let name = get_name var' in
+ let resj = judge_of_abstraction !!env (orelse_name name name') j j' in
inh_conv_coerce_to_tycon ?loc env evdref resj tycon
- | GProd(name,bk,c1,c2) ->
- let j = pretype_type empty_valcon env evdref lvar c1 in
- (* The name specified by ltac is used also to create bindings. So
- the substitution must also be applied on variables before they are
- looked up in the rel context. *)
- let j' = match name with
+ | GProd(name,bk,c1,c2) ->
+ let j = pretype_type empty_valcon env evdref c1 in
+ let name, j' = match name with
| Anonymous ->
- let j = pretype_type empty_valcon env evdref lvar c2 in
- { j with utj_val = lift 1 j.utj_val }
+ let j = pretype_type empty_valcon env evdref c2 in
+ name, { j with utj_val = lift 1 j.utj_val }
| Name _ ->
let var = LocalAssum (name, j.utj_val) in
- let env' = push_rel !evdref var env in
- pretype_type empty_valcon env' evdref lvar c2
+ let var, env' = push_rel !evdref var env in
+ get_name var, pretype_type empty_valcon env' evdref c2
in
- let name = ltac_interp_name lvar name in
let resj =
try
- judge_of_product env.ExtraEnv.env name j j'
+ judge_of_product !!env name j j'
with TypeError _ as e ->
let (e, info) = CErrors.push e in
let info = Option.cata (Loc.add_loc info) info loc in
iraise (e, info) in
inh_conv_coerce_to_tycon ?loc env evdref resj tycon
- | GLetIn(name,c1,t,c2) ->
+ | GLetIn(name,c1,t,c2) ->
let tycon1 =
match t with
| Some t ->
- mk_tycon (pretype_type empty_valcon env evdref lvar t).utj_val
+ mk_tycon (pretype_type empty_valcon env evdref t).utj_val
| None ->
empty_tycon in
- let j = pretype tycon1 env evdref lvar c1 in
+ let j = pretype tycon1 env evdref c1 in
let t = evd_comb1 (Evarsolve.refresh_universes
- ~onlyalg:true ~status:Evd.univ_flexible (Some false) env.ExtraEnv.env)
+ ~onlyalg:true ~status:Evd.univ_flexible (Some false) !!env)
evdref j.uj_type in
- (* The name specified by ltac is used also to create bindings. So
- the substitution must also be applied on variables before they are
- looked up in the rel context. *)
let var = LocalDef (name, j.uj_val, t) in
let tycon = lift_tycon 1 tycon in
- let j' = pretype tycon (push_rel !evdref var env) evdref lvar c2 in
- let name = ltac_interp_name lvar name in
+ let var, env = push_rel !evdref var env in
+ let j' = pretype tycon env evdref c2 in
+ let name = get_name var in
{ uj_val = mkLetIn (name, j.uj_val, t, j'.uj_val) ;
uj_type = subst1 j.uj_val j'.uj_type }
| GLetTuple (nal,(na,po),c,d) ->
- let cj = pretype empty_tycon env evdref lvar c in
+ let cj = pretype empty_tycon env evdref c in
let (IndType (indf,realargs)) =
- try find_rectype env.ExtraEnv.env !evdref cj.uj_type
+ try find_rectype !!env !evdref cj.uj_type
with Not_found ->
let cloc = loc_of_glob_constr c in
- error_case_not_inductive ?loc:cloc env.ExtraEnv.env !evdref cj
+ error_case_not_inductive ?loc:cloc !!env !evdref cj
in
let ind = fst (fst (dest_ind_family indf)) in
- let cstrs = get_constructors env.ExtraEnv.env indf in
+ let cstrs = get_constructors !!env indf in
if not (Int.equal (Array.length cstrs) 1) then
user_err ?loc (str "Destructing let is only for inductive types" ++
str " with one constructor.");
@@ -916,7 +779,7 @@ let rec pretype k0 resolve_tc (tycon : type_constraint) (env : ExtraEnv.t) evdre
int cs.cs_nargs ++ str " variables.");
let fsign, record =
let set_name na d = set_name na (map_rel_decl EConstr.of_constr d) in
- match Environ.get_projections env.ExtraEnv.env ind with
+ match Environ.get_projections !!env ind with
| None ->
List.map2 set_name (List.rev nal) cs.cs_args, false
| Some ps ->
@@ -935,108 +798,97 @@ let rec pretype k0 resolve_tc (tycon : type_constraint) (env : ExtraEnv.t) evdre
let fsign = if Flags.version_strictly_greater Flags.V8_6
then Context.Rel.map (whd_betaiota !evdref) fsign
else fsign (* beta-iota-normalization regression in 8.5 and 8.6 *) in
+ let fsign,env_f = push_rel_context !evdref fsign env in
let obj ind p v f =
- if not record then
- let nal = List.map (fun na -> ltac_interp_name lvar na) nal in
- let nal = List.rev nal in
- let fsign = List.map2 set_name nal fsign in
+ if not record then
let f = it_mkLambda_or_LetIn f fsign in
- let ci = make_case_info env.ExtraEnv.env (fst ind) LetStyle in
+ let ci = make_case_info !!env (fst ind) LetStyle in
mkCase (ci, p, cj.uj_val,[|f|])
else it_mkLambda_or_LetIn f fsign
in
- let env_f = push_rel_context !evdref fsign env in
- (* Make dependencies from arity signature impossible *)
+ (* Make dependencies from arity signature impossible *)
let arsgn =
- let arsgn,_ = get_arity env.ExtraEnv.env indf in
+ let arsgn,_ = get_arity !!env indf in
List.map (set_name Anonymous) arsgn
in
- let indt = build_dependent_inductive env.ExtraEnv.env indf in
+ let indt = build_dependent_inductive !!env indf in
let psign = LocalAssum (na, indt) :: arsgn in (* For locating names in [po] *)
- let predlvar = Cases.make_return_predicate_ltac_lvar !evdref na c cj.uj_val lvar in
- let psign' = LocalAssum (ltac_interp_name predlvar na, indt) :: arsgn in
- let psign' = List.map (fun d -> map_rel_decl EConstr.of_constr d) psign' in
- let psign' = Namegen.name_context env.ExtraEnv.env !evdref psign' in (* For naming abstractions in [po] *)
let psign = List.map (fun d -> map_rel_decl EConstr.of_constr d) psign in
+ let predenv = Cases.make_return_predicate_ltac_lvar env !evdref na c cj.uj_val in
let nar = List.length arsgn in
+ let psign',env_p = push_rel_context ~force_names:true !evdref psign predenv in
(match po with
| Some p ->
- let env_p = push_rel_context !evdref psign env in
- let pj = pretype_type empty_valcon env_p evdref predlvar p in
+ let pj = pretype_type empty_valcon env_p evdref p in
let ccl = nf_evar !evdref pj.utj_val in
let p = it_mkLambda_or_LetIn ccl psign' in
let inst =
(Array.map_to_list EConstr.of_constr cs.cs_concl_realargs)
@[EConstr.of_constr (build_dependent_constructor cs)] in
let lp = lift cs.cs_nargs p in
- let fty = hnf_lam_applist env.ExtraEnv.env !evdref lp inst in
- let fj = pretype (mk_tycon fty) env_f evdref lvar d in
+ let fty = hnf_lam_applist !!env !evdref lp inst in
+ let fj = pretype (mk_tycon fty) env_f evdref d in
let v =
let ind,_ = dest_ind_family indf in
- Typing.check_allowed_sort env.ExtraEnv.env !evdref ind cj.uj_val p;
+ Typing.check_allowed_sort !!env !evdref ind cj.uj_val p;
obj ind p cj.uj_val fj.uj_val
in
{ uj_val = v; uj_type = (substl (realargs@[cj.uj_val]) ccl) }
| None ->
let tycon = lift_tycon cs.cs_nargs tycon in
- let fj = pretype tycon env_f evdref predlvar d in
+ let fj = pretype tycon env_f evdref d in
let ccl = nf_evar !evdref fj.uj_type in
let ccl =
if noccur_between !evdref 1 cs.cs_nargs ccl then
lift (- cs.cs_nargs) ccl
else
- error_cant_find_case_type ?loc env.ExtraEnv.env !evdref
+ error_cant_find_case_type ?loc !!env !evdref
cj.uj_val in
(* let ccl = refresh_universes ccl in *)
let p = it_mkLambda_or_LetIn (lift (nar+1) ccl) psign' in
let v =
let ind,_ = dest_ind_family indf in
- Typing.check_allowed_sort env.ExtraEnv.env !evdref ind cj.uj_val p;
+ Typing.check_allowed_sort !!env !evdref ind cj.uj_val p;
obj ind p cj.uj_val fj.uj_val
in { uj_val = v; uj_type = ccl })
| GIf (c,(na,po),b1,b2) ->
- let cj = pretype empty_tycon env evdref lvar c in
+ let cj = pretype empty_tycon env evdref c in
let (IndType (indf,realargs)) =
- try find_rectype env.ExtraEnv.env !evdref cj.uj_type
+ try find_rectype !!env !evdref cj.uj_type
with Not_found ->
let cloc = loc_of_glob_constr c in
- error_case_not_inductive ?loc:cloc env.ExtraEnv.env !evdref cj in
- let cstrs = get_constructors env.ExtraEnv.env indf in
+ error_case_not_inductive ?loc:cloc !!env !evdref cj in
+ let cstrs = get_constructors !!env indf in
if not (Int.equal (Array.length cstrs) 2) then
user_err ?loc
(str "If is only for inductive types with two constructors.");
let arsgn =
- let arsgn,_ = get_arity env.ExtraEnv.env indf in
+ let arsgn,_ = get_arity !!env indf in
(* Make dependencies from arity signature impossible *)
List.map (set_name Anonymous) arsgn
in
let nar = List.length arsgn in
- let indt = build_dependent_inductive env.ExtraEnv.env indf in
+ let indt = build_dependent_inductive !!env indf in
let psign = LocalAssum (na, indt) :: arsgn in (* For locating names in [po] *)
- let predlvar = Cases.make_return_predicate_ltac_lvar !evdref na c cj.uj_val lvar in
- let psign' = LocalAssum (ltac_interp_name predlvar na, indt) :: arsgn in
- let psign' = List.map (fun d -> map_rel_decl EConstr.of_constr d) psign' in
- let psign' = Namegen.name_context env.ExtraEnv.env !evdref psign' in (* For naming abstractions in [po] *)
let psign = List.map (fun d -> map_rel_decl EConstr.of_constr d) psign in
+ let predenv = Cases.make_return_predicate_ltac_lvar env !evdref na c cj.uj_val in
+ let psign,env_p = push_rel_context !evdref psign predenv in
let pred,p = match po with
| Some p ->
- let env_p = push_rel_context !evdref psign env in
- let pj = pretype_type empty_valcon env_p evdref predlvar p in
+ let pj = pretype_type empty_valcon env_p evdref p in
let ccl = nf_evar !evdref pj.utj_val in
- let pred = it_mkLambda_or_LetIn ccl psign' in
+ let pred = it_mkLambda_or_LetIn ccl psign in
let typ = lift (- nar) (beta_applist !evdref (pred,[cj.uj_val])) in
pred, typ
| None ->
let p = match tycon with
| Some ty -> ty
- | None ->
- let env = ltac_interp_name_env k0 lvar env !evdref in
- new_type_evar env evdref loc
+ | None -> new_type_evar env evdref loc
in
- it_mkLambda_or_LetIn (lift (nar+1) p) psign', p in
+ it_mkLambda_or_LetIn (lift (nar+1) p) psign, p in
let pred = nf_evar !evdref pred in
let p = nf_evar !evdref p in
let f cs b =
@@ -1051,85 +903,121 @@ let rec pretype k0 resolve_tc (tycon : type_constraint) (env : ExtraEnv.t) evdre
let csgn =
List.map (set_name Anonymous) cs_args
in
- let env_c = push_rel_context !evdref csgn env in
- let bj = pretype (mk_tycon pi) env_c evdref lvar b in
+ let _,env_c = push_rel_context !evdref csgn env in
+ let bj = pretype (mk_tycon pi) env_c evdref b in
it_mkLambda_or_LetIn bj.uj_val cs_args in
let b1 = f cstrs.(0) b1 in
let b2 = f cstrs.(1) b2 in
let v =
let ind,_ = dest_ind_family indf in
- let ci = make_case_info env.ExtraEnv.env (fst ind) IfStyle in
+ let ci = make_case_info !!env (fst ind) IfStyle in
let pred = nf_evar !evdref pred in
- Typing.check_allowed_sort env.ExtraEnv.env !evdref ind cj.uj_val pred;
+ Typing.check_allowed_sort !!env !evdref ind cj.uj_val pred;
mkCase (ci, pred, cj.uj_val, [|b1;b2|])
in
let cj = { uj_val = v; uj_type = p } in
inh_conv_coerce_to_tycon ?loc env evdref cj tycon
| GCases (sty,po,tml,eqns) ->
- Cases.compile_cases ?loc sty
- ((fun vtyc env evdref -> pretype vtyc (make_env env !evdref) evdref),evdref)
- tycon env.ExtraEnv.env (* loc *) lvar (po,tml,eqns)
+ let pretype tycon env sigma c =
+ let evdref = ref sigma in
+ let t = pretype tycon env evdref c in
+ !evdref, t
+ in
+ let sigma = !evdref in
+ let sigma, j = Cases.compile_cases ?loc sty (pretype, sigma) tycon env (po,tml,eqns) in
+ let () = evdref := sigma in
+ j
| GCast (c,k) ->
let cj =
match k with
| CastCoerce ->
- let cj = pretype empty_tycon env evdref lvar c in
- evd_comb1 (Coercion.inh_coerce_to_base ?loc env.ExtraEnv.env) evdref cj
+ let cj = pretype empty_tycon env evdref c in
+ evd_comb1 (Coercion.inh_coerce_to_base ?loc !!env) evdref cj
| CastConv t | CastVM t | CastNative t ->
let k = (match k with CastVM _ -> VMcast | CastNative _ -> NATIVEcast | _ -> DEFAULTcast) in
- let tj = pretype_type empty_valcon env evdref lvar t in
+ let tj = pretype_type empty_valcon env evdref t in
let tval = evd_comb1 (Evarsolve.refresh_universes
- ~onlyalg:true ~status:Evd.univ_flexible (Some false) env.ExtraEnv.env)
+ ~onlyalg:true ~status:Evd.univ_flexible (Some false) !!env)
evdref tj.utj_val in
let tval = nf_evar !evdref tval in
let cj, tval = match k with
| VMcast ->
- let cj = pretype empty_tycon env evdref lvar c in
+ let cj = pretype empty_tycon env evdref c in
let cty = nf_evar !evdref cj.uj_type and tval = nf_evar !evdref tval in
if not (occur_existential !evdref cty || occur_existential !evdref tval) then
- match Reductionops.vm_infer_conv env.ExtraEnv.env !evdref cty tval with
+ match Reductionops.vm_infer_conv !!env !evdref cty tval with
| Some evd -> (evdref := evd; cj, tval)
| None ->
- error_actual_type ?loc env.ExtraEnv.env !evdref cj tval
- (ConversionFailed (env.ExtraEnv.env,cty,tval))
+ error_actual_type ?loc !!env !evdref cj tval
+ (ConversionFailed (!!env,cty,tval))
else user_err ?loc (str "Cannot check cast with vm: " ++
str "unresolved arguments remain.")
| NATIVEcast ->
- let cj = pretype empty_tycon env evdref lvar c in
+ let cj = pretype empty_tycon env evdref c in
let cty = nf_evar !evdref cj.uj_type and tval = nf_evar !evdref tval in
begin
- match Nativenorm.native_infer_conv env.ExtraEnv.env !evdref cty tval with
+ match Nativenorm.native_infer_conv !!env !evdref cty tval with
| Some evd -> (evdref := evd; cj, tval)
| None ->
- error_actual_type ?loc env.ExtraEnv.env !evdref cj tval
- (ConversionFailed (env.ExtraEnv.env,cty,tval))
+ error_actual_type ?loc !!env !evdref cj tval
+ (ConversionFailed (!!env,cty,tval))
end
| _ ->
- pretype (mk_tycon tval) env evdref lvar c, tval
+ pretype (mk_tycon tval) env evdref c, tval
in
let v = mkCast (cj.uj_val, k, tval) in
{ uj_val = v; uj_type = tval }
in inh_conv_coerce_to_tycon ?loc env evdref cj tycon
-and pretype_instance k0 resolve_tc env evdref lvar loc hyps evk update =
+and pretype_instance k0 resolve_tc env evdref loc hyps evk update =
let f decl (subst,update) =
let id = NamedDecl.get_id decl in
+ let b = Option.map (replace_vars subst) (NamedDecl.get_value decl) in
let t = replace_vars subst (NamedDecl.get_type decl) in
+ let check_body id c =
+ match b, c with
+ | Some b, Some c ->
+ if not (is_conv !!env !evdref b c) then
+ user_err ?loc (str "Cannot interpret " ++
+ pr_existential_key !evdref evk ++
+ strbrk " in current context: binding for " ++ Id.print id ++
+ strbrk " is not convertible to its expected definition (cannot unify " ++
+ quote (Termops.Internal.print_constr_env !!env !evdref b) ++
+ strbrk " and " ++
+ quote (Termops.Internal.print_constr_env !!env !evdref c) ++
+ str ").")
+ | Some b, None ->
+ user_err ?loc (str "Cannot interpret " ++
+ pr_existential_key !evdref evk ++
+ strbrk " in current context: " ++ Id.print id ++
+ strbrk " should be bound to a local definition.")
+ | None, _ -> () in
+ let check_type id t' =
+ if not (is_conv !!env !evdref t t') then
+ user_err ?loc (str "Cannot interpret " ++
+ pr_existential_key !evdref evk ++
+ strbrk " in current context: binding for " ++ Id.print id ++
+ strbrk " is not well-typed.") in
let c, update =
try
let c = List.assoc id update in
- let c = pretype k0 resolve_tc (mk_tycon t) env evdref lvar c in
+ let c = pretype k0 resolve_tc (mk_tycon t) env evdref c in
+ check_body id (Some c.uj_val);
c.uj_val, List.remove_assoc id update
with Not_found ->
try
- let (n,_,t') = lookup_rel_id id (rel_context env) in
- if is_conv env.ExtraEnv.env !evdref t (lift n t') then mkRel n, update else raise Not_found
+ let (n,b',t') = lookup_rel_id id (rel_context !!env) in
+ check_type id (lift n t');
+ check_body id (Option.map (lift n) b');
+ mkRel n, update
with Not_found ->
try
- let t' = env |> lookup_named id |> NamedDecl.get_type in
- if is_conv env.ExtraEnv.env !evdref t t' then mkVar id, update else raise Not_found
+ let decl = lookup_named id !!env in
+ check_type id (NamedDecl.get_type decl);
+ check_body id (NamedDecl.get_value decl);
+ mkVar id, update
with Not_found ->
user_err ?loc (str "Cannot interpret " ++
pr_existential_key !evdref evk ++
@@ -1139,19 +1027,19 @@ and pretype_instance k0 resolve_tc env evdref lvar loc hyps evk update =
check_instance loc subst inst;
Array.map_of_list snd subst
-(* [pretype_type valcon env evdref lvar c] coerces [c] into a type *)
-and pretype_type k0 resolve_tc valcon (env : ExtraEnv.t) evdref lvar c = match DAst.get c with
+(* [pretype_type valcon env evdref c] coerces [c] into a type *)
+and pretype_type k0 resolve_tc valcon (env : GlobEnv.t) evdref c = match DAst.get c with
| GHole (knd, naming, None) ->
let loc = loc_of_glob_constr c in
(match valcon with
| Some v ->
let s =
let sigma = !evdref in
- let t = Retyping.get_type_of env.ExtraEnv.env sigma v in
- match EConstr.kind sigma (whd_all env.ExtraEnv.env sigma t) with
+ let t = Retyping.get_type_of !!env sigma v in
+ match EConstr.kind sigma (whd_all !!env sigma t) with
| Sort s -> ESorts.kind sigma s
| Evar ev when is_Type sigma (existential_type sigma ev) ->
- evd_comb1 (define_evar_as_sort env.ExtraEnv.env) evdref ev
+ evd_comb1 (define_evar_as_sort !!env) evdref ev
| _ -> anomaly (Pp.str "Found a type constraint which is not a type.")
in
(* Correction of bug #5315 : we need to define an evar for *all* holes *)
@@ -1162,40 +1050,39 @@ and pretype_type k0 resolve_tc valcon (env : ExtraEnv.t) evdref lvar c = match D
{ utj_val = v;
utj_type = s }
| None ->
- let env = ltac_interp_name_env k0 lvar env !evdref in
let s = evd_comb0 (new_sort_variable univ_flexible_alg) evdref in
{ utj_val = e_new_evar env evdref ~src:(loc, knd) ~naming (mkSort s);
utj_type = s})
| _ ->
- let j = pretype k0 resolve_tc empty_tycon env evdref lvar c in
+ let j = pretype k0 resolve_tc empty_tycon env evdref c in
let loc = loc_of_glob_constr c in
- let tj = evd_comb1 (Coercion.inh_coerce_to_sort ?loc env.ExtraEnv.env) evdref j in
+ let tj = evd_comb1 (Coercion.inh_coerce_to_sort ?loc !!env) evdref j in
match valcon with
| None -> tj
| Some v ->
- begin match cumul env.ExtraEnv.env !evdref v tj.utj_val with
+ begin match cumul !!env !evdref v tj.utj_val with
| Some sigma -> evdref := sigma; tj
| None ->
error_unexpected_type
- ?loc:(loc_of_glob_constr c) env.ExtraEnv.env !evdref tj.utj_val v
+ ?loc:(loc_of_glob_constr c) !!env !evdref tj.utj_val v
end
let ise_pretype_gen flags env sigma lvar kind c =
- let env = make_env env sigma in
+ let env = GlobEnv.make env sigma lvar in
let evdref = ref sigma in
- let k0 = Context.Rel.length (rel_context env) in
+ let k0 = Context.Rel.length (rel_context !!env) in
let c', c'_ty = match kind with
| WithoutTypeConstraint ->
- let j = pretype k0 flags.use_typeclasses empty_tycon env evdref lvar c in
+ let j = pretype k0 flags.use_typeclasses empty_tycon env evdref c in
j.uj_val, j.uj_type
| OfType exptyp ->
- let j = pretype k0 flags.use_typeclasses (mk_tycon exptyp) env evdref lvar c in
+ let j = pretype k0 flags.use_typeclasses (mk_tycon exptyp) env evdref c in
j.uj_val, j.uj_type
| IsType ->
- let tj = pretype_type k0 flags.use_typeclasses empty_valcon env evdref lvar c in
+ let tj = pretype_type k0 flags.use_typeclasses empty_valcon env evdref c in
tj.utj_val, mkSort tj.utj_type
in
- process_inference_flags flags env.ExtraEnv.env sigma (!evdref,c',c'_ty)
+ process_inference_flags flags !!env sigma (!evdref,c',c'_ty)
let default_inference_flags fail = {
use_typeclasses = true;
@@ -1238,7 +1125,7 @@ let understand_ltac flags env sigma lvar kind c =
(sigma, c)
let pretype k0 resolve_tc typcon env evdref lvar t =
- pretype k0 resolve_tc typcon (make_env env !evdref) evdref lvar t
+ pretype k0 resolve_tc typcon (GlobEnv.make env !evdref lvar) evdref t
let pretype_type k0 resolve_tc valcon env evdref lvar t =
- pretype_type k0 resolve_tc valcon (make_env env !evdref) evdref lvar t
+ pretype_type k0 resolve_tc valcon (GlobEnv.make env !evdref lvar) evdref t
diff --git a/pretyping/pretyping.mli b/pretyping/pretyping.mli
index 73f5b77e0e..fcc361b16b 100644
--- a/pretyping/pretyping.mli
+++ b/pretyping/pretyping.mli
@@ -122,11 +122,3 @@ val pretype_type :
val ise_pretype_gen :
inference_flags -> env -> evar_map ->
ltac_var_map -> typing_constraint -> glob_constr -> evar_map * constr * types
-
-(**/**)
-
-(** To embed constr in glob_constr *)
-
-val register_constr_interp0 :
- ('r, 'g, 't) Genarg.genarg_type ->
- (unbound_ltac_var_map -> env -> evar_map -> types -> 'g -> constr * evar_map) -> unit
diff --git a/pretyping/pretyping.mllib b/pretyping/pretyping.mllib
index 5da5aff449..d0359b43f4 100644
--- a/pretyping/pretyping.mllib
+++ b/pretyping/pretyping.mllib
@@ -32,6 +32,7 @@ Program
Coercion
Detyping
Indrec
+GlobEnv
Cases
Pretyping
Unification
diff --git a/pretyping/recordops.ml b/pretyping/recordops.ml
index 2f861c117b..c25416405e 100644
--- a/pretyping/recordops.ml
+++ b/pretyping/recordops.ml
@@ -192,11 +192,11 @@ let rec assoc_pat a = function
let object_table =
- Summary.ref (Refmap.empty : ((cs_pattern * constr) * obj_typ) list Refmap.t)
+ Summary.ref (GlobRef.Map.empty : ((cs_pattern * constr) * obj_typ) list GlobRef.Map.t)
~name:"record-canonical-structs"
let canonical_projections () =
- Refmap.fold (fun x -> List.fold_right (fun ((y,_),c) acc -> ((x,y),c)::acc))
+ GlobRef.Map.fold (fun x -> List.fold_right (fun ((y,_),c) acc -> ((x,y),c)::acc))
!object_table []
let keep_true_projections projs kinds =
@@ -229,7 +229,7 @@ let warn_projection_no_head_constant =
let env = Termops.push_rels_assum sign env in
let con_pp = Nametab.pr_global_env Id.Set.empty (ConstRef con) in
let proji_sp_pp = Nametab.pr_global_env Id.Set.empty (ConstRef proji_sp) in
- let term_pp = Termops.print_constr_env env (Evd.from_env env) (EConstr.of_constr t) in
+ let term_pp = Termops.Internal.print_constr_env env (Evd.from_env env) (EConstr.of_constr t) in
strbrk "Projection value has no head constant: "
++ term_pp ++ strbrk " in canonical instance "
++ con_pp ++ str " of " ++ proji_sp_pp ++ strbrk ", ignoring it.")
@@ -289,14 +289,18 @@ let warn_redundant_canonical_projection =
let add_canonical_structure warn o =
let lo = compute_canonical_projections warn o in
List.iter (fun ((proj,(cs_pat,_ as pat)),s) ->
- let l = try Refmap.find proj !object_table with Not_found -> [] in
+ let l = try GlobRef.Map.find proj !object_table with Not_found -> [] in
let ocs = try Some (assoc_pat cs_pat l)
with Not_found -> None
in match ocs with
- | None -> object_table := Refmap.add proj ((pat,s)::l) !object_table;
+ | None -> object_table := GlobRef.Map.add proj ((pat,s)::l) !object_table;
| Some (c, cs) ->
- let old_can_s = (Termops.print_constr (EConstr.of_constr cs.o_DEF))
- and new_can_s = (Termops.print_constr (EConstr.of_constr s.o_DEF)) in
+ (* XXX: Undesired global access to env *)
+ let env = Global.env () in
+ let sigma = Evd.from_env env in
+ let old_can_s = (Termops.Internal.print_constr_env env sigma (EConstr.of_constr cs.o_DEF))
+ and new_can_s = (Termops.Internal.print_constr_env env sigma (EConstr.of_constr s.o_DEF))
+ in
let prj = (Nametab.pr_global_env Id.Set.empty proj)
and hd_val = (pr_cs_pattern cs_pat) in
if warn then warn_redundant_canonical_projection (hd_val,prj,new_can_s,old_can_s))
@@ -334,19 +338,19 @@ let error_not_structure ref description =
user_err ~hdr:"object_declare"
(str"Could not declare a canonical structure " ++
(Id.print (basename_of_global ref) ++ str"." ++ spc() ++
- str(description)))
+ description))
let check_and_decompose_canonical_structure ref =
let sp =
match ref with
ConstRef sp -> sp
- | _ -> error_not_structure ref "Expected an instance of a record or structure."
+ | _ -> error_not_structure ref (str "Expected an instance of a record or structure.")
in
let env = Global.env () in
let u = Univ.make_abstract_instance (Environ.constant_context env sp) in
let vc = match Environ.constant_opt_value_in env (sp, u) with
| Some vc -> vc
- | None -> error_not_structure ref "Could not find its value in the global environment." in
+ | None -> error_not_structure ref (str "Could not find its value in the global environment.") in
let env = Global.env () in
let evd = Evd.from_env env in
let body = snd (splay_lam (Global.env()) evd (EConstr.of_constr vc)) in
@@ -354,36 +358,36 @@ let check_and_decompose_canonical_structure ref =
let f,args = match kind body with
| App (f,args) -> f,args
| _ ->
- error_not_structure ref "Expected a record or structure constructor applied to arguments." in
+ error_not_structure ref (str "Expected a record or structure constructor applied to arguments.") in
let indsp = match kind f with
| Construct ((indsp,1),u) -> indsp
- | _ -> error_not_structure ref "Expected an instance of a record or structure." in
+ | _ -> error_not_structure ref (str "Expected an instance of a record or structure.") in
let s =
try lookup_structure indsp
with Not_found ->
error_not_structure ref
- ("Could not find the record or structure " ^ (MutInd.to_string (fst indsp))) in
+ (str "Could not find the record or structure " ++ Termops.Internal.print_constr_env env evd (EConstr.mkInd indsp)) in
let ntrue_projs = List.count snd s.s_PROJKIND in
if s.s_EXPECTEDPARAM + ntrue_projs > Array.length args then
- error_not_structure ref "Got too few arguments to the record or structure constructor.";
+ error_not_structure ref (str "Got too few arguments to the record or structure constructor.");
(sp,indsp)
let declare_canonical_structure ref =
add_canonical_structure (check_and_decompose_canonical_structure ref)
let lookup_canonical_conversion (proj,pat) =
- assoc_pat pat (Refmap.find proj !object_table)
+ assoc_pat pat (GlobRef.Map.find proj !object_table)
let decompose_projection sigma c args =
match EConstr.kind sigma c with
| Const (c, u) ->
let n = find_projection_nparams (ConstRef c) in
(** Check if there is some canonical projection attached to this structure *)
- let _ = Refmap.find (ConstRef c) !object_table in
+ let _ = GlobRef.Map.find (ConstRef c) !object_table in
let arg = Stack.nth args n in
arg
| Proj (p, c) ->
- let _ = Refmap.find (ConstRef (Projection.constant p)) !object_table in
+ let _ = GlobRef.Map.find (ConstRef (Projection.constant p)) !object_table in
c
| _ -> raise Not_found
diff --git a/pretyping/reductionops.ml b/pretyping/reductionops.ml
index ba40262815..e8c3b3e2b3 100644
--- a/pretyping/reductionops.ml
+++ b/pretyping/reductionops.ml
@@ -88,6 +88,7 @@ let set_reduction_effect x funkey =
(** Machinery to custom the behavior of the reduction *)
module ReductionBehaviour = struct
open Globnames
+ open Names
open Libobject
type t = {
@@ -97,7 +98,7 @@ module ReductionBehaviour = struct
}
let table =
- Summary.ref (Refmap.empty : t Refmap.t) ~name:"reductionbehaviour"
+ Summary.ref (GlobRef.Map.empty : t GlobRef.Map.t) ~name:"reductionbehaviour"
type flag = [ `ReductionDontExposeCase | `ReductionNeverUnfold ]
type req =
@@ -105,7 +106,7 @@ module ReductionBehaviour = struct
| ReqGlobal of GlobRef.t * (int list * int * flag list)
let load _ (_,(_,(r, b))) =
- table := Refmap.add r b !table
+ table := GlobRef.Map.add r b !table
let cache o = load 1 o
@@ -160,7 +161,7 @@ module ReductionBehaviour = struct
let get r =
try
- let b = Refmap.find r !table in
+ let b = GlobRef.Map.find r !table in
let flags =
if Int.equal b.b_nargs max_int then [`ReductionNeverUnfold]
else if b.b_dont_expose_case then [`ReductionDontExposeCase] else [] in
@@ -253,9 +254,9 @@ module Cst_stack = struct
(applist (cst, List.rev params))
t) cst_l c
- let pr l =
+ let pr env sigma l =
let open Pp in
- let p_c c = Termops.print_constr c in
+ let p_c c = Termops.Internal.print_constr_env env sigma c in
prlist_with_sep pr_semicolon
(fun (c,params,args) ->
hov 1 (str"(" ++ p_c c ++ str ")" ++ spc () ++ pr_sequence p_c params ++ spc () ++ str "(args:" ++
@@ -340,6 +341,7 @@ struct
| Cst of cst_member * int * int list * 'a t * Cst_stack.t
and 'a t = 'a member list
+ (* Debugging printer *)
let rec pr_member pr_c member =
let open Pp in
let pr_c x = hov 1 (pr_c x) in
@@ -350,7 +352,7 @@ struct
prvect_with_sep (pr_bar) pr_c br
++ str ")"
| Proj (p,cst) ->
- str "ZProj(" ++ Constant.print (Projection.constant p) ++ str ")"
+ str "ZProj(" ++ Constant.debug_print (Projection.constant p) ++ str ")"
| Fix (f,args,cst) ->
str "ZFix(" ++ Termops.pr_fix pr_c f
++ pr_comma () ++ pr pr_c args ++ str ")"
@@ -367,11 +369,11 @@ struct
let open Pp in
match c with
| Cst_const (c, u) ->
- if Univ.Instance.is_empty u then Constant.print c
- else str"(" ++ Constant.print c ++ str ", " ++
+ if Univ.Instance.is_empty u then Constant.debug_print c
+ else str"(" ++ Constant.debug_print c ++ str ", " ++
Univ.Instance.pr Univ.Level.pr u ++ str")"
| Cst_proj p ->
- str".(" ++ Constant.print (Projection.constant p) ++ str")"
+ str".(" ++ Constant.debug_print (Projection.constant p) ++ str")"
let empty = []
let is_empty = CList.is_empty
@@ -613,9 +615,9 @@ type contextual_state_reduction_function =
type state_reduction_function = contextual_state_reduction_function
type local_state_reduction_function = evar_map -> state -> state
-let pr_state (tm,sk) =
+let pr_state env sigma (tm,sk) =
let open Pp in
- let pr c = Termops.print_constr c in
+ let pr c = Termops.Internal.print_constr_env env sigma c in
h 0 (pr tm ++ str "|" ++ cut () ++ Stack.pr pr sk)
(*************************************)
@@ -628,6 +630,18 @@ let safe_meta_value sigma ev =
try Some (Evd.meta_value sigma ev)
with Not_found -> None
+let strong_with_flags whdfun flags env sigma t =
+ let push_rel_check_zeta d env =
+ let open CClosure.RedFlags in
+ let d = match d with
+ | LocalDef (na,c,t) when not (red_set flags fZETA) -> LocalAssum (na,t)
+ | d -> d in
+ push_rel d env in
+ let rec strongrec env t =
+ map_constr_with_full_binders sigma
+ push_rel_check_zeta strongrec env (whdfun flags env sigma t) in
+ strongrec env t
+
let strong whdfun env sigma t =
let rec strongrec env t =
map_constr_with_full_binders sigma push_rel strongrec env (whdfun env sigma t) in
@@ -841,10 +855,10 @@ let rec whd_state_gen ?csts ~refold ~tactic_mode flags env sigma =
let rec whrec cst_l (x, stack) =
let () = if !debug_RAKAM then
let open Pp in
- let pr c = Termops.print_constr c in
+ let pr c = Termops.Internal.print_constr_env env sigma c in
Feedback.msg_notice
(h 0 (str "<<" ++ pr x ++
- str "|" ++ cut () ++ Cst_stack.pr cst_l ++
+ str "|" ++ cut () ++ Cst_stack.pr env sigma cst_l ++
str "|" ++ cut () ++ Stack.pr pr stack ++
str ">>"))
in
diff --git a/pretyping/reductionops.mli b/pretyping/reductionops.mli
index 07eeec9276..c0ff6723f6 100644
--- a/pretyping/reductionops.mli
+++ b/pretyping/reductionops.mli
@@ -60,7 +60,7 @@ module Cst_stack : sig
val best_cst : t -> (constr * constr list) option
val best_replace : Evd.evar_map -> constr -> t -> constr -> constr
val reference : Evd.evar_map -> t -> Constant.t option
- val pr : t -> Pp.t
+ val pr : env -> Evd.evar_map -> t -> Pp.t
end
module Stack : sig
@@ -140,10 +140,13 @@ type contextual_state_reduction_function =
type state_reduction_function = contextual_state_reduction_function
type local_state_reduction_function = evar_map -> state -> state
-val pr_state : state -> Pp.t
+val pr_state : env -> evar_map -> state -> Pp.t
(** {6 Reduction Function Operators } *)
+val strong_with_flags :
+ (CClosure.RedFlags.reds -> reduction_function) ->
+ (CClosure.RedFlags.reds -> reduction_function)
val strong : reduction_function -> reduction_function
val local_strong : local_reduction_function -> local_reduction_function
val strong_prodspine : local_reduction_function -> local_reduction_function
diff --git a/pretyping/tacred.mli b/pretyping/tacred.mli
index e6065dda87..bf38c30a1f 100644
--- a/pretyping/tacred.mli
+++ b/pretyping/tacred.mli
@@ -23,7 +23,7 @@ type reduction_tactic_error =
exception ReductionTacticError of reduction_tactic_error
-(** {6 Reduction functions associated to tactics. {% \label{%}tacred{% }%} } *)
+(** {6 Reduction functions associated to tactics. } *)
(** Evaluable global reference *)
diff --git a/pretyping/typeclasses.ml b/pretyping/typeclasses.ml
index efb3c339ac..55d9838bbb 100644
--- a/pretyping/typeclasses.ml
+++ b/pretyping/typeclasses.ml
@@ -88,7 +88,7 @@ type typeclass = {
cl_unique : bool;
}
-type typeclasses = typeclass Refmap.t
+type typeclasses = typeclass GlobRef.Map.t
type instance = {
is_class: GlobRef.t;
@@ -99,7 +99,7 @@ type instance = {
is_impl: GlobRef.t;
}
-type instances = (instance Refmap.t) Refmap.t
+type instances = (instance GlobRef.Map.t) GlobRef.Map.t
let instance_impl is = is.is_impl
@@ -121,8 +121,8 @@ let new_instance cl info glob impl =
* states management
*)
-let classes : typeclasses ref = Summary.ref Refmap.empty ~name:"classes"
-let instances : instances ref = Summary.ref Refmap.empty ~name:"instances"
+let classes : typeclasses ref = Summary.ref GlobRef.Map.empty ~name:"classes"
+let instances : instances ref = Summary.ref GlobRef.Map.empty ~name:"instances"
let typeclass_univ_instance (cl, u) =
assert (Univ.AUContext.size cl.cl_univs == Univ.Instance.length u);
@@ -131,7 +131,7 @@ let typeclass_univ_instance (cl, u) =
cl_props = subst_ctx cl.cl_props}
let class_info c =
- try Refmap.find c !classes
+ try GlobRef.Map.find c !classes
with Not_found -> not_a_class (Global.env()) (EConstr.of_constr (printable_constr_of_global c))
let global_class_of_constr env sigma c =
@@ -154,7 +154,7 @@ let class_of_constr sigma c =
let is_class_constr sigma c =
try let gr, u = Termops.global_of_constr sigma c in
- Refmap.mem gr !classes
+ GlobRef.Map.mem gr !classes
with Not_found -> false
let rec is_class_type evd c =
@@ -172,7 +172,7 @@ let is_class_evar evd evi =
*)
let load_class (_, cl) =
- classes := Refmap.add cl.cl_impl cl !classes
+ classes := GlobRef.Map.add cl.cl_impl cl !classes
let cache_class = load_class
@@ -336,17 +336,17 @@ type instance_action =
let load_instance inst =
let insts =
- try Refmap.find inst.is_class !instances
- with Not_found -> Refmap.empty in
- let insts = Refmap.add inst.is_impl inst insts in
- instances := Refmap.add inst.is_class insts !instances
+ try GlobRef.Map.find inst.is_class !instances
+ with Not_found -> GlobRef.Map.empty in
+ let insts = GlobRef.Map.add inst.is_impl inst insts in
+ instances := GlobRef.Map.add inst.is_class insts !instances
let remove_instance inst =
let insts =
- try Refmap.find inst.is_class !instances
+ try GlobRef.Map.find inst.is_class !instances
with Not_found -> assert false in
- let insts = Refmap.remove inst.is_impl insts in
- instances := Refmap.add inst.is_class insts !instances
+ let insts = GlobRef.Map.remove inst.is_impl insts in
+ instances := GlobRef.Map.add inst.is_class insts !instances
let cache_instance (_, (action, i)) =
match action with
@@ -464,23 +464,23 @@ let instance_constructor (cl,u) args =
(term, applist (mkConstU cst, pars))
| _ -> assert false
-let typeclasses () = Refmap.fold (fun _ l c -> l :: c) !classes []
+let typeclasses () = GlobRef.Map.fold (fun _ l c -> l :: c) !classes []
-let cmap_elements c = Refmap.fold (fun k v acc -> v :: acc) c []
+let cmap_elements c = GlobRef.Map.fold (fun k v acc -> v :: acc) c []
let instances_of c =
- try cmap_elements (Refmap.find c.cl_impl !instances) with Not_found -> []
+ try cmap_elements (GlobRef.Map.find c.cl_impl !instances) with Not_found -> []
let all_instances () =
- Refmap.fold (fun k v acc ->
- Refmap.fold (fun k v acc -> v :: acc) v acc)
+ GlobRef.Map.fold (fun k v acc ->
+ GlobRef.Map.fold (fun k v acc -> v :: acc) v acc)
!instances []
let instances r =
let cl = class_info r in instances_of cl
let is_class gr =
- Refmap.exists (fun _ v -> GlobRef.equal v.cl_impl gr) !classes
+ GlobRef.Map.exists (fun _ v -> GlobRef.equal v.cl_impl gr) !classes
let is_instance = function
| ConstRef c ->
diff --git a/pretyping/unification.ml b/pretyping/unification.ml
index fc1f6fc81e..e223674579 100644
--- a/pretyping/unification.ml
+++ b/pretyping/unification.ml
@@ -684,8 +684,10 @@ let rec unify_0_with_initial_metas (sigma,ms,es as subst : subst0) conv_at_top e
and cN = Evarutil.whd_head_evar sigma curn in
let () =
if !debug_unification then
- Feedback.msg_debug (print_constr_env curenv sigma cM ++ str" ~= " ++ print_constr_env curenv sigma cN)
- in
+ Feedback.msg_debug (
+ Termops.Internal.print_constr_env curenv sigma cM ++ str" ~= " ++
+ Termops.Internal.print_constr_env curenv sigma cN)
+ in
match (EConstr.kind sigma cM, EConstr.kind sigma cN) with
| Meta k1, Meta k2 ->
if Int.equal k1 k2 then substn else
diff --git a/pretyping/vnorm.ml b/pretyping/vnorm.ml
index 255707dc7b..c30c4f0932 100644
--- a/pretyping/vnorm.ml
+++ b/pretyping/vnorm.ml
@@ -79,7 +79,7 @@ let construct_of_constr const env tag typ =
(* spiwack : here be a branch for specific decompilation handled by retroknowledge *)
try
if const then
- ((Retroknowledge.get_vm_decompile_constant_info env.retroknowledge (mkIndU indu) tag),
+ ((Retroknowledge.get_vm_decompile_constant_info env.retroknowledge (GlobRef.IndRef ind) tag),
typ) (*spiwack: this may need to be changed in case there are parameters in the
type which may cause a constant value to have an arity.
(type_constructor seems to be all about parameters actually)
@@ -161,9 +161,9 @@ and nf_whd env sigma whd typ =
| Vconstr_block b ->
let tag = btag b in
let (tag,ofs) =
- if tag = Cbytecodes.last_variant_tag then
+ if tag = Obj.last_non_constant_constructor_tag then
match whd_val (bfield b 0) with
- | Vconstr_const tag -> (tag+Cbytecodes.last_variant_tag, 1)
+ | Vconstr_const tag -> (tag+Obj.last_non_constant_constructor_tag, 1)
| _ -> assert false
else (tag, 0) in
let capp,ctyp = construct_of_constr_block env tag typ in
@@ -278,7 +278,7 @@ and nf_stk ?from:(from=0) env sigma c t stk =
in
let branchs = Array.mapi mkbranch bsw in
let tcase = build_case_type p realargs c in
- let ci = sw.sw_annot.Cbytecodes.ci in
+ let ci = sw.sw_annot.Vmvalues.ci in
nf_stk env sigma (mkCase(ci, p, c, branchs)) tcase stk
| Zproj p :: stk ->
assert (from = 0) ;
diff --git a/printing/dune b/printing/dune
new file mode 100644
index 0000000000..3392342165
--- /dev/null
+++ b/printing/dune
@@ -0,0 +1,6 @@
+(library
+ (name printing)
+ (synopsis "Coq's Term Pretty Printing Library")
+ (public_name coq.printing)
+ (wrapped false)
+ (libraries parsing proofs))
diff --git a/printing/prettyp.ml b/printing/prettyp.ml
index 1810cc6588..66f748454d 100644
--- a/printing/prettyp.ml
+++ b/printing/prettyp.ml
@@ -71,17 +71,17 @@ let int_or_no n = if Int.equal n 0 then str "no" else int n
let print_basename sp = pr_global (ConstRef sp)
let print_ref reduce ref udecl =
- let typ, ctx = Global.type_of_global_in_context (Global.env ()) ref in
- let typ = Vars.subst_instance_constr (Univ.AUContext.instance ctx) typ in
+ let typ, univs = Global.type_of_global_in_context (Global.env ()) ref in
+ let inst = Univ.make_abstract_instance univs in
+ let bl = UnivNames.universe_binders_with_opt_names ref udecl in
+ let sigma = Evd.from_ctx (UState.of_binders bl) in
let typ = EConstr.of_constr typ in
let typ =
if reduce then
let env = Global.env () in
- let sigma = Evd.from_env env in
let ctx,ccl = Reductionops.splay_prod_assum env sigma typ
in EConstr.it_mkProd_or_LetIn ccl ctx
else typ in
- let univs = Global.universes_of_global ref in
let variance = match ref with
| VarRef _ | ConstRef _ -> None
| IndRef (ind,_) | ConstructRef ((ind,_),_) ->
@@ -91,19 +91,14 @@ let print_ref reduce ref udecl =
| Declarations.Cumulative_ind cumi -> Some (Univ.ACumulativityInfo.variance cumi)
end
in
- let inst = Univ.AUContext.instance univs in
- let univs = Univ.UContext.make (inst, Univ.AUContext.instantiate inst univs) in
let env = Global.env () in
- let bl = UnivNames.universe_binders_with_opt_names ref
- (Array.to_list (Univ.Instance.to_array inst)) udecl in
- let sigma = Evd.from_ctx (UState.of_binders bl) in
let inst =
if Global.is_polymorphic ref
- then Printer.pr_universe_instance sigma (Univ.UContext.instance univs)
+ then Printer.pr_universe_instance sigma inst
else mt ()
in
hov 0 (pr_global ref ++ inst ++ str " :" ++ spc () ++ pr_letype_env env sigma typ ++
- Printer.pr_universe_ctx sigma ?variance univs)
+ Printer.pr_abstract_universe_ctx sigma ?variance univs)
(********************************)
(** Printing implicit arguments *)
@@ -552,48 +547,31 @@ let print_typed_body env evd (val_0,typ) =
let print_instance sigma cb =
if Declareops.constant_is_polymorphic cb then
let univs = Declareops.constant_polymorphic_context cb in
- let inst = Univ.AUContext.instance univs in
+ let inst = Univ.make_abstract_instance univs in
pr_universe_instance sigma inst
else mt()
let print_constant with_values sep sp udecl =
let cb = Global.lookup_constant sp in
let val_0 = Global.body_of_constant_body cb in
- let typ =
- match cb.const_universes with
- | Monomorphic_const _ -> cb.const_type
- | Polymorphic_const univs ->
- let inst = Univ.AUContext.instance univs in
- Vars.subst_instance_constr inst cb.const_type
- in
- let univs, ulist =
- let open Entries in
+ let typ = cb.const_type in
+ let univs =
let open Univ in
let otab = Global.opaque_tables () in
match cb.const_body with
- | Undef _ | Def _ ->
- begin
- match cb.const_universes with
- | Monomorphic_const ctx -> Monomorphic_const_entry ctx, []
- | Polymorphic_const ctx ->
- let inst = AUContext.instance ctx in
- Polymorphic_const_entry (UContext.make (inst, AUContext.instantiate inst ctx)),
- Array.to_list (Instance.to_array inst)
- end
+ | Undef _ | Def _ -> cb.const_universes
| OpaqueDef o ->
let body_uctxs = Opaqueproof.force_constraints otab o in
match cb.const_universes with
| Monomorphic_const ctx ->
- Monomorphic_const_entry (ContextSet.union body_uctxs ctx), []
+ Monomorphic_const (ContextSet.union body_uctxs ctx)
| Polymorphic_const ctx ->
assert(ContextSet.is_empty body_uctxs);
- let inst = AUContext.instance ctx in
- Polymorphic_const_entry (UContext.make (inst, AUContext.instantiate inst ctx)),
- Array.to_list (Instance.to_array inst)
+ Polymorphic_const ctx
in
let ctx =
UState.of_binders
- (UnivNames.universe_binders_with_opt_names (ConstRef sp) ulist udecl)
+ (UnivNames.universe_binders_with_opt_names (ConstRef sp) udecl)
in
let env = Global.env () and sigma = Evd.from_ctx ctx in
let pr_ltype = pr_ltype_env env sigma in
@@ -605,7 +583,6 @@ let print_constant with_values sep sp udecl =
str" ]" ++
Printer.pr_constant_universes sigma univs
| Some (c, ctx) ->
- let c = Vars.subst_instance_constr (Univ.AUContext.instance ctx) c in
print_basename sp ++ print_instance sigma cb ++ str sep ++ cut () ++
(if with_values then print_typed_body env sigma (Some c,typ) else pr_ltype typ)++
Printer.pr_constant_universes sigma univs)
@@ -712,11 +689,6 @@ let print_eval x = !object_pr.print_eval x
(**** Printing declarations and judgments *)
(**** Abstract layer *****)
-let print_typed_value x =
- let env = Global.env () in
- let sigma = Evd.from_env env in
- print_typed_value_in_env env sigma x
-
let print_judgment env sigma {uj_val=trm;uj_type=typ} =
print_typed_value_in_env env sigma (trm, typ)
@@ -852,11 +824,9 @@ let print_opaque_name env sigma qid =
print_inductive sp None
| ConstructRef cstr as gr ->
let ty, ctx = Global.type_of_global_in_context env gr in
- let inst = Univ.AUContext.instance ctx in
- let ty = Vars.subst_instance_constr inst ty in
let ty = EConstr.of_constr ty in
let open EConstr in
- print_typed_value (mkConstruct cstr, ty)
+ print_typed_value_in_env env sigma (mkConstruct cstr, ty)
| VarRef id ->
env |> lookup_named id |> print_named_decl env sigma
@@ -902,28 +872,28 @@ let inspect env sigma depth =
open Classops
-let print_coercion_value env sigma v = Printer.pr_global v.coe_value
+let print_coercion_value v = Printer.pr_global v.coe_value
let print_class i =
let cl,_ = class_info_from_index i in
pr_class cl
-let print_path env sigma ((i,j),p) =
+let print_path ((i,j),p) =
hov 2 (
- str"[" ++ hov 0 (prlist_with_sep pr_semicolon (print_coercion_value env sigma) p) ++
+ str"[" ++ hov 0 (prlist_with_sep pr_semicolon print_coercion_value p) ++
str"] : ") ++
print_class i ++ str" >-> " ++ print_class j
let _ = Classops.install_path_printer print_path
-let print_graph env sigma =
- prlist_with_sep fnl (print_path env sigma) (inheritance_graph())
+let print_graph () =
+ prlist_with_sep fnl print_path (inheritance_graph())
let print_classes () =
pr_sequence pr_class (classes())
-let print_coercions env sigma =
- pr_sequence (print_coercion_value env sigma) (coercions())
+let print_coercions () =
+ pr_sequence print_coercion_value (coercions())
let index_of_class cl =
try
@@ -932,7 +902,7 @@ let index_of_class cl =
user_err ~hdr:"index_of_class"
(pr_class cl ++ spc() ++ str "not a defined class.")
-let print_path_between env sigma cls clt =
+let print_path_between cls clt =
let i = index_of_class cls in
let j = index_of_class clt in
let p =
@@ -943,7 +913,7 @@ let print_path_between env sigma cls clt =
(str"No path between " ++ pr_class cls ++ str" and " ++ pr_class clt
++ str ".")
in
- print_path env sigma ((i,j),p)
+ print_path ((i,j),p)
let print_canonical_projections env sigma =
prlist_with_sep fnl
diff --git a/printing/prettyp.mli b/printing/prettyp.mli
index 1668bce297..58606db019 100644
--- a/printing/prettyp.mli
+++ b/printing/prettyp.mli
@@ -12,7 +12,6 @@ open Names
open Environ
open Reductionops
open Libnames
-open Evd
(** A Pretty-Printer for the Calculus of Inductive Constructions. *)
@@ -40,10 +39,10 @@ val print_about : env -> Evd.evar_map -> qualid Constrexpr.or_by_notation ->
val print_impargs : qualid Constrexpr.or_by_notation -> Pp.t
(** Pretty-printing functions for classes and coercions *)
-val print_graph : env -> evar_map -> Pp.t
+val print_graph : unit -> Pp.t
val print_classes : unit -> Pp.t
-val print_coercions : env -> Evd.evar_map -> Pp.t
-val print_path_between : env -> evar_map -> Classops.cl_typ -> Classops.cl_typ -> Pp.t
+val print_coercions : unit -> Pp.t
+val print_path_between : Classops.cl_typ -> Classops.cl_typ -> Pp.t
val print_canonical_projections : env -> Evd.evar_map -> Pp.t
(** Pretty-printing functions for type classes and instances *)
diff --git a/printing/printer.ml b/printing/printer.ml
index 5b3ead181f..cfa3e8b6e9 100644
--- a/printing/printer.ml
+++ b/printing/printer.ml
@@ -87,7 +87,6 @@ let pr_leconstr_core = Proof_diffs.pr_leconstr_core
let pr_constr_n_env env sigma n c = pr_econstr_n_core false env sigma n (EConstr.of_constr c)
let pr_lconstr_env = Proof_diffs.pr_lconstr_env
let pr_constr_env env sigma c = pr_econstr_core false env sigma (EConstr.of_constr c)
-let _ = Hook.set Refine.pr_constr pr_constr_env
let pr_lconstr_goal_style_env env sigma c = pr_leconstr_core true env sigma (EConstr.of_constr c)
let pr_constr_goal_style_env env sigma c = pr_econstr_core true env sigma (EConstr.of_constr c)
@@ -192,7 +191,7 @@ let pr_constr_pattern t =
let pr_sort sigma s = pr_glob_sort (extern_sort sigma s)
-let _ = Termops.set_print_constr
+let _ = Termops.Internal.set_print_constr
(fun env sigma t -> pr_lconstr_expr (extern_constr ~lax:true false env sigma t))
let pr_in_comment pr x = str "(* " ++ pr x ++ str " *)"
@@ -270,9 +269,16 @@ let pr_universe_ctx sigma ?variance c =
else
mt()
+let pr_abstract_universe_ctx sigma ?variance c =
+ if !Detyping.print_universes && not (Univ.AUContext.is_empty c) then
+ fnl()++pr_in_comment (fun c -> v 0
+ (Univ.pr_abstract_universe_context (Termops.pr_evd_level sigma) ?variance c)) c
+ else
+ mt()
+
let pr_constant_universes sigma = function
- | Entries.Monomorphic_const_entry ctx -> pr_universe_ctx_set sigma ctx
- | Entries.Polymorphic_const_entry ctx -> pr_universe_ctx sigma ctx
+ | Declarations.Monomorphic_const ctx -> pr_universe_ctx_set sigma ctx
+ | Declarations.Polymorphic_const ctx -> pr_abstract_universe_ctx sigma ctx
let pr_cumulativity_info sigma cumi =
if !Detyping.print_universes
@@ -282,6 +288,14 @@ let pr_cumulativity_info sigma cumi =
else
mt()
+let pr_abstract_cumulativity_info sigma cumi =
+ if !Detyping.print_universes
+ && not (Univ.AUContext.is_empty (Univ.ACumulativityInfo.univ_context cumi)) then
+ fnl()++pr_in_comment (fun uii -> v 0
+ (Univ.pr_abstract_cumulativity_info (Termops.pr_evd_level sigma) uii)) cumi
+ else
+ mt()
+
(**********************************************************************)
(* Global references *)
@@ -494,17 +508,17 @@ let pr_transparent_state (ids, csts) =
str"CONSTANTS: " ++ pr_cpred csts ++ fnl ())
(* display complete goal
- prev_gs has info on the previous proof step for diffs
- gs has info on the current proof step
+ og_s has goal+sigma on the previous proof step for diffs
+ g_s has goal+sigma on the current proof step
*)
-let pr_goal ?(diffs=false) ?prev_gs gs =
- let g = sig_it gs in
- let sigma = project gs in
+let pr_goal ?(diffs=false) ?og_s g_s =
+ let g = sig_it g_s in
+ let sigma = project g_s in
let env = Goal.V82.env sigma g in
let concl = Goal.V82.concl sigma g in
let goal =
if diffs then
- Proof_diffs.diff_goals ?prev_gs (Some gs)
+ Proof_diffs.diff_goal ?og_s g sigma
else
pr_context_of env sigma ++ cut () ++
str "============================" ++ cut () ++
@@ -525,13 +539,18 @@ let pr_goal_name sigma g =
let pr_goal_header nme sigma g =
let (g,sigma) = Goal.V82.nf_evar sigma g in
str "subgoal " ++ nme ++ (if should_tag() then pr_goal_tag g else str"")
- ++ (if should_gname() then str " " ++ Pp.surround (pr_existential_key sigma g) else mt ())
+ ++ (if should_gname() then str " " ++ Pp.surround (pr_existential_key sigma g) else mt ())
(* display the conclusion of a goal *)
-let pr_concl n sigma g =
+let pr_concl n ?(diffs=false) ?og_s sigma g =
let (g,sigma) = Goal.V82.nf_evar sigma g in
let env = Goal.V82.env sigma g in
- let pc = pr_goal_concl_style_env env sigma (Goal.V82.concl sigma g) in
+ let pc =
+ if diffs then
+ Proof_diffs.diff_concl ?og_s sigma g
+ else
+ pr_goal_concl_style_env env sigma (Goal.V82.concl sigma g)
+ in
let header = pr_goal_header (int n) sigma g in
header ++ str " is:" ++ cut () ++ str" " ++ pc
@@ -698,13 +717,25 @@ let print_dependent_evars gl sigma seeds =
in
constraints ++ evars ()
+module GoalMap = Evar.Map
+
(* Print open subgoals. Checks for uninstantiated existential variables *)
(* spiwack: [seeds] is for printing dependent evars in emacs mode. *)
(* spiwack: [pr_first] is true when the first goal must be singled out
and printed in its entirety. *)
-(* [prev] is the previous proof step, used for diffs *)
-let pr_subgoals ?(pr_first=true) ?(diffs=false) ?prev
+(* [os_map] is derived from the previous proof step, used for diffs *)
+let pr_subgoals ?(pr_first=true) ?(diffs=false) ?os_map
close_cmd sigma ~seeds ~shelf ~stack ~unfocused ~goals =
+ let diff_goal_map =
+ match os_map with
+ | Some (_, diff_goal_map) -> diff_goal_map
+ | None -> GoalMap.empty
+ in
+
+ let map_goal_for_diff ng = (* todo: move to proof_diffs.ml *)
+ try GoalMap.find ng diff_goal_map with Not_found -> ng
+ in
+
(** Printing functions for the extra informations. *)
let rec print_stack a = function
| [] -> Pp.int a
@@ -738,23 +769,23 @@ let pr_subgoals ?(pr_first=true) ?(diffs=false) ?prev
else str" " (* non-breakable space *)
in
+ let get_ogs g =
+ match os_map with
+ | Some (osigma, _) -> Some { it = map_goal_for_diff g; sigma = osigma }
+ | None -> None
+ in
let rec pr_rec n = function
| [] -> (mt ())
| g::rest ->
- let pc = pr_concl n sigma g in
+ let og_s = get_ogs g in
+ let pc = pr_concl n ~diffs ?og_s sigma g in
let prest = pr_rec (n+1) rest in
(cut () ++ pc ++ prest)
in
let print_multiple_goals g l =
if pr_first then
- let prev_gs =
- match prev with
- | Some (prev_goals, prev_sigma) ->
- if prev_goals = [] then None
- else Some { it = List.hd prev_goals; sigma = prev_sigma}
- | None -> None
- in
- pr_goal ~diffs ?prev_gs { it = g ; sigma = sigma }
+ let og_s = get_ogs g in
+ pr_goal ~diffs ?og_s { it = g ; sigma = sigma }
++ (if l=[] then mt () else cut ())
++ pr_rec 2 l
else
@@ -797,7 +828,7 @@ let pr_subgoals ?(pr_first=true) ?(diffs=false) ?prev
++ print_dependent_evars (Some g1) sigma seeds
)
-let pr_open_subgoals_diff ?(quiet=false) ?(diffs=false) ?prev_proof proof =
+let pr_open_subgoals_diff ?(quiet=false) ?(diffs=false) ?oproof proof =
(* spiwack: it shouldn't be the job of the printer to look up stuff
in the [evar_map], I did stuff that way because it was more
straightforward, but seriously, [Proof.proof] should return
@@ -833,15 +864,15 @@ let pr_open_subgoals_diff ?(quiet=false) ?(diffs=false) ?prev_proof proof =
let { Evd.it = bgoals ; sigma = bsigma } = Proof.V82.background_subgoals p in
let bgoals_focused, bgoals_unfocused = List.partition (fun x -> List.mem x goals) bgoals in
let unfocused_if_needed = if should_unfoc() then bgoals_unfocused else [] in
- let prev = match prev_proof with
- | Some op ->
- let (ogoals , _, _, _, _) = Proof.proof op in
- let { Evd.it = obgoals; sigma = osigma } = Proof.V82.background_subgoals op in
- let obgoals_focused = List.filter (fun x -> List.mem x ogoals) obgoals in
- Some (obgoals_focused, osigma)
- | None -> None
+ let os_map = match oproof with
+ | Some op when diffs ->
+ let (_,_,_,_, osigma) = Proof.proof op in
+ let diff_goal_map = Proof_diffs.make_goal_map oproof proof in
+ Some (osigma, diff_goal_map)
+ | _ -> None
in
- pr_subgoals ~pr_first:true ~diffs ?prev None bsigma ~seeds ~shelf ~stack:[] ~unfocused:unfocused_if_needed ~goals:bgoals_focused
+ pr_subgoals ~pr_first:true ~diffs ?os_map None bsigma ~seeds ~shelf ~stack:[]
+ ~unfocused:unfocused_if_needed ~goals:bgoals_focused
end
let pr_open_subgoals ~proof =
@@ -927,11 +958,18 @@ let pr_assumptionset env sigma s =
let safe_pr_constant env kn =
try pr_constant env kn
with Not_found ->
+ (* FIXME? *)
let mp,_,lab = Constant.repr3 kn in
str (ModPath.to_string mp) ++ str "." ++ Label.print lab
in
- let safe_pr_ltype typ =
- try str " : " ++ pr_ltype typ
+ let safe_pr_inductive env kn =
+ try pr_inductive env (kn,0)
+ with Not_found ->
+ (* FIXME? *)
+ MutInd.print kn
+ in
+ let safe_pr_ltype env sigma typ =
+ try str " : " ++ pr_ltype_env env sigma typ
with e when CErrors.noncritical e -> mt ()
in
let safe_pr_ltype_relctx (rctx, typ) =
@@ -942,9 +980,9 @@ let pr_assumptionset env sigma s =
let pr_axiom env ax typ =
match ax with
| Constant kn ->
- safe_pr_constant env kn ++ safe_pr_ltype typ
+ safe_pr_constant env kn ++ safe_pr_ltype env sigma typ
| Positive m ->
- hov 2 (MutInd.print m ++ spc () ++ strbrk"is positive.")
+ hov 2 (safe_pr_inductive env m ++ spc () ++ strbrk"is positive.")
| Guarded kn ->
hov 2 (safe_pr_constant env kn ++ spc () ++ strbrk"is positive.")
in
@@ -952,7 +990,7 @@ let pr_assumptionset env sigma s =
let (v, a, o, tr) = accu in
match t with
| Variable id ->
- let var = pr_id id ++ str " : " ++ pr_ltype typ in
+ let var = pr_id id ++ str " : " ++ pr_ltype_env env sigma typ in
(var :: v, a, o, tr)
| Axiom (axiom, []) ->
let ax = pr_axiom env axiom typ in
@@ -966,10 +1004,10 @@ let pr_assumptionset env sigma s =
l in
(v, ax :: a, o, tr)
| Opaque kn ->
- let opq = safe_pr_constant env kn ++ safe_pr_ltype typ in
+ let opq = safe_pr_constant env kn ++ safe_pr_ltype env sigma typ in
(v, a, opq :: o, tr)
| Transparent kn ->
- let tran = safe_pr_constant env kn ++ safe_pr_ltype typ in
+ let tran = safe_pr_constant env kn ++ safe_pr_ltype env sigma typ in
(v, a, o, tran :: tr)
in
let (vars, axioms, opaque, trans) =
@@ -1023,22 +1061,14 @@ let print_and_diff oldp newp =
| Some proof ->
let output =
if Proof_diffs.show_diffs () then
- try pr_open_subgoals_diff ~diffs:true ?prev_proof:oldp proof
+ try pr_open_subgoals_diff ~diffs:true ?oproof:oldp proof
with Pp_diff.Diff_Failure msg -> begin
(* todo: print the unparsable string (if we know it) *)
- Feedback.msg_warning Pp.(str ("Diff failure:" ^ msg ^ "; showing results without diff highlighting" ));
+ Feedback.msg_warning Pp.(str ("Diff failure: " ^ msg) ++ cut()
+ ++ str "Showing results without diff highlighting" );
pr_open_subgoals ~proof
end
else
pr_open_subgoals ~proof
in
Feedback.msg_notice output;;
-
-(* Do diffs on the first goal returning a Pp. *)
-let diff_pr_open_subgoals ?(quiet=false) o_proof n_proof =
- match n_proof with
- | None -> Pp.mt ()
- | Some proof ->
- try pr_open_subgoals_diff ~quiet ~diffs:true ?prev_proof:o_proof proof
- with Pp_diff.Diff_Failure _ -> pr_open_subgoals ~proof
- (* todo: print the unparsable string (if we know it) *)
diff --git a/printing/printer.mli b/printing/printer.mli
index 971241d5f9..96db7091a6 100644
--- a/printing/printer.mli
+++ b/printing/printer.mli
@@ -123,9 +123,12 @@ val pr_cumulative : bool -> bool -> Pp.t
val pr_universe_instance : evar_map -> Univ.Instance.t -> Pp.t
val pr_universe_ctx : evar_map -> ?variance:Univ.Variance.t array ->
Univ.UContext.t -> Pp.t
+val pr_abstract_universe_ctx : evar_map -> ?variance:Univ.Variance.t array ->
+ Univ.AUContext.t -> Pp.t
val pr_universe_ctx_set : evar_map -> Univ.ContextSet.t -> Pp.t
-val pr_constant_universes : evar_map -> Entries.constant_universes_entry -> Pp.t
+val pr_constant_universes : evar_map -> Declarations.constant_universes -> Pp.t
val pr_cumulativity_info : evar_map -> Univ.CumulativityInfo.t -> Pp.t
+val pr_abstract_cumulativity_info : evar_map -> Univ.ACumulativityInfo.t -> Pp.t
(** Printing global references using names as short as possible *)
@@ -171,26 +174,46 @@ val pr_transparent_state : transparent_state -> Pp.t
(** Proofs, these functions obey [Hyps Limit] and [Compact contexts]. *)
-val pr_goal : ?diffs:bool -> ?prev_gs:(goal sigma) -> goal sigma -> Pp.t
-
-(** [pr_subgoals ~pr_first ~prev_proof pp sigma seeds shelf focus_stack unfocused goals]
- prints the goals of the list [goals] followed by the goals in
- [unfocused], in a short way (typically only the conclusion) except
- for the first goal if [pr_first] is true. Also, if [diffs] is true
- and [pr_first] is true, then highlight diffs relative to [prev] in the
- output for first goal. This function prints only the
- focused goals unless the conrresponding option
- [enable_unfocused_goal_printing] is set. [seeds] is for printing
- dependent evars (mainly for emacs proof tree mode). *)
-val pr_subgoals : ?pr_first:bool -> ?diffs:bool -> ?prev:(goal list * evar_map) -> Pp.t option -> evar_map
+(** [pr_goal ~diffs ~og_s g_s] prints the goal specified by [g_s]. If [diffs] is true,
+ highlight the differences between the old goal, [og_s], and [g_s]. [g_s] and [og_s] are
+ records containing the goal and sigma for, respectively, the new and old proof steps,
+ e.g. [{ it = g ; sigma = sigma }].
+*)
+val pr_goal : ?diffs:bool -> ?og_s:(goal sigma) -> goal sigma -> Pp.t
+
+(** [pr_subgoals ~pr_first ~diffs ~os_map close_cmd sigma ~seeds ~shelf ~stack ~unfocused ~goals]
+ prints the goals in [goals] followed by the goals in [unfocused] in a compact form
+ (typically only the conclusion). If [pr_first] is true, print the first goal in full.
+ [close_cmd] is printed afterwards verbatim.
+
+ If [diffs] is true, then highlight diffs relative to [os_map] in the output for first goal.
+ [os_map] contains sigma for the old proof step and the goal map created by
+ [Proof_diffs.make_goal_map].
+
+ This function prints only the focused goals unless the corresponding option [enable_unfocused_goal_printing] is set.
+ [seeds] is for printing dependent evars (mainly for emacs proof tree mode). [shelf] is from
+ Proof.proof and is used to identify shelved goals in a message if there are no more subgoals but
+ there are non-instantiated existential variables. [stack] is used to print summary info on unfocused
+ goals.
+*)
+val pr_subgoals : ?pr_first:bool -> ?diffs:bool -> ?os_map:(evar_map * Evar.t Evar.Map.t) -> Pp.t option -> evar_map
-> seeds:goal list -> shelf:goal list -> stack:int list
-> unfocused: goal list -> goals:goal list -> Pp.t
val pr_subgoal : int -> evar_map -> goal list -> Pp.t
-val pr_concl : int -> evar_map -> goal -> Pp.t
-val pr_open_subgoals_diff : ?quiet:bool -> ?diffs:bool -> ?prev_proof:Proof.t -> Proof.t -> Pp.t
-val diff_pr_open_subgoals : ?quiet:bool -> Proof.t option -> Proof.t option -> Pp.t
+(** [pr_concl n ~diffs ~og_s sigma g] prints the conclusion of the goal [g] using [sigma]. The output
+ is labelled "subgoal [n]". If [diffs] is true, highlight the differences between the old conclusion,
+ [og_s], and [g]+[sigma]. [og_s] is a record containing the old goal and sigma, e.g. [{ it = g ; sigma = sigma }].
+*)
+val pr_concl : int -> ?diffs:bool -> ?og_s:(goal sigma) -> evar_map -> goal -> Pp.t
+
+(** [pr_open_subgoals_diff ~quiet ~diffs ~oproof proof] shows the context for [proof] as used by, for example, coqtop.
+ The first active goal is printed with all its antecedents and the conclusion. The other active goals only show their
+ conclusions. If [diffs] is true, highlight the differences between the old proof, [oproof], and [proof]. [quiet]
+ disables printing messages as Feedback.
+*)
+val pr_open_subgoals_diff : ?quiet:bool -> ?diffs:bool -> ?oproof:Proof.t -> Proof.t -> Pp.t
val pr_open_subgoals : proof:Proof.t -> Pp.t
val pr_nth_open_subgoal : proof:Proof.t -> int -> Pp.t
val pr_evar : evar_map -> (Evar.t * evar_info) -> Pp.t
@@ -200,13 +223,14 @@ val pr_ne_evar_set : Pp.t -> Pp.t -> evar_map ->
Evar.Set.t -> Pp.t
val pr_prim_rule : prim_rule -> Pp.t
+[@@ocaml.deprecated "[pr_prim_rule] is scheduled to be removed along with the legacy proof engine"]
val print_and_diff : Proof.t option -> Proof.t option -> unit
(** Backwards compatibility *)
val prterm : constr -> Pp.t (** = pr_lconstr *)
-
+[@@ocaml.deprecated "The global printing API is deprecated, please use the _env functions"]
(** Declarations for the "Print Assumption" command *)
type axiom =
diff --git a/printing/printmod.ml b/printing/printmod.ml
index e2d9850bf8..1fc308ac99 100644
--- a/printing/printmod.ml
+++ b/printing/printmod.ml
@@ -90,9 +90,7 @@ let build_ind_type env mip =
Inductive.type_of_inductive env mip
let print_one_inductive env sigma mib ((_,i) as ind) =
- let u = if Declareops.inductive_is_polymorphic mib then
- Univ.AUContext.instance (Declareops.inductive_polymorphic_context mib)
- else Univ.Instance.empty in
+ let u = Univ.make_abstract_instance (Declareops.inductive_polymorphic_context mib) in
let mip = mib.mind_packets.(i) in
let params = Inductive.inductive_paramdecls (mib,u) in
let nparamdecls = Context.Rel.length params in
@@ -111,16 +109,6 @@ let print_one_inductive env sigma mib ((_,i) as ind) =
str ": " ++ Printer.pr_lconstr_env envpar sigma arity ++ str " :=") ++
brk(0,2) ++ print_constructors envpar sigma mip.mind_consnames cstrtypes
-let instantiate_cumulativity_info cumi =
- let open Univ in
- let univs = ACumulativityInfo.univ_context cumi in
- let expose ctx =
- let inst = AUContext.instance ctx in
- let cst = AUContext.instantiate inst ctx in
- UContext.make (inst, cst)
- in
- CumulativityInfo.make (expose univs, ACumulativityInfo.variance cumi)
-
let print_mutual_inductive env mind mib udecl =
let inds = List.init (Array.length mib.mind_packets) (fun x -> (mind, x))
in
@@ -131,14 +119,7 @@ let print_mutual_inductive env mind mib udecl =
| BiFinite -> "Variant"
| CoFinite -> "CoInductive"
in
- let univs =
- let open Univ in
- if Declareops.inductive_is_polymorphic mib then
- Array.to_list (Instance.to_array
- (AUContext.instance (Declareops.inductive_polymorphic_context mib)))
- else []
- in
- let bl = UnivNames.universe_binders_with_opt_names (IndRef (mind, 0)) univs udecl in
+ let bl = UnivNames.universe_binders_with_opt_names (IndRef (mind, 0)) udecl in
let sigma = Evd.from_ctx (UState.of_binders bl) in
hov 0 (Printer.pr_polymorphic (Declareops.inductive_is_polymorphic mib) ++
Printer.pr_cumulative
@@ -150,8 +131,7 @@ let print_mutual_inductive env mind mib udecl =
match mib.mind_universes with
| Monomorphic_ind _ | Polymorphic_ind _ -> str ""
| Cumulative_ind cumi ->
- Printer.pr_cumulativity_info
- sigma (instantiate_cumulativity_info cumi))
+ Printer.pr_abstract_cumulativity_info sigma cumi)
let get_fields =
let rec prodec_rec l subst c =
@@ -167,11 +147,7 @@ let get_fields =
prodec_rec [] []
let print_record env mind mib udecl =
- let u =
- if Declareops.inductive_is_polymorphic mib then
- Univ.AUContext.instance (Declareops.inductive_polymorphic_context mib)
- else Univ.Instance.empty
- in
+ let u = Univ.make_abstract_instance (Declareops.inductive_polymorphic_context mib) in
let mip = mib.mind_packets.(0) in
let params = Inductive.inductive_paramdecls (mib,u) in
let nparamdecls = Context.Rel.length params in
@@ -181,8 +157,7 @@ let print_record env mind mib udecl =
let cstrtype = hnf_prod_applist_assum env nparamdecls cstrtypes.(0) args in
let fields = get_fields cstrtype in
let envpar = push_rel_context params env in
- let bl = UnivNames.universe_binders_with_opt_names (IndRef (mind,0))
- (Array.to_list (Univ.Instance.to_array u)) udecl in
+ let bl = UnivNames.universe_binders_with_opt_names (IndRef (mind,0)) udecl in
let sigma = Evd.from_ctx (UState.of_binders bl) in
let keyword =
let open Declarations in
@@ -210,8 +185,7 @@ let print_record env mind mib udecl =
match mib.mind_universes with
| Monomorphic_ind _ | Polymorphic_ind _ -> str ""
| Cumulative_ind cumi ->
- Printer.pr_cumulativity_info
- sigma (instantiate_cumulativity_info cumi)
+ Printer.pr_abstract_cumulativity_info sigma cumi
)
let pr_mutual_inductive_body env mind mib udecl =
@@ -315,12 +289,6 @@ let print_body is_impl env mp (l,body) =
| SFBmodtype _ -> keyword "Module Type" ++ spc () ++ name
| SFBconst cb ->
let ctx = Declareops.constant_polymorphic_context cb in
- let u =
- if Declareops.constant_is_polymorphic cb then
- Univ.AUContext.instance ctx
- else Univ.Instance.empty
- in
- let ctx = Univ.UContext.make (u, Univ.AUContext.instantiate u ctx) in
(match cb.const_body with
| Def _ -> def "Definition" ++ spc ()
| OpaqueDef _ when is_impl -> def "Theorem" ++ spc ()
@@ -328,18 +296,17 @@ let print_body is_impl env mp (l,body) =
(match env with
| None -> mt ()
| Some env ->
+ let bl = UnivNames.universe_binders_with_opt_names (ConstRef (Constant.make2 mp l)) None in
+ let sigma = Evd.from_ctx (UState.of_binders bl) in
str " :" ++ spc () ++
- hov 0 (Printer.pr_ltype_env env (Evd.from_env env)
- (Vars.subst_instance_constr u
- cb.const_type)) ++
+ hov 0 (Printer.pr_ltype_env env sigma cb.const_type) ++
(match cb.const_body with
| Def l when is_impl ->
spc () ++
hov 2 (str ":= " ++
- Printer.pr_lconstr_env env (Evd.from_env env)
- (Vars.subst_instance_constr u (Mod_subst.force_constr l)))
+ Printer.pr_lconstr_env env sigma (Mod_subst.force_constr l))
| _ -> mt ()) ++ str "." ++
- Printer.pr_universe_ctx (Evd.from_env env) ctx)
+ Printer.pr_abstract_universe_ctx sigma ctx)
| SFBmind mib ->
try
let env = Option.get env in
diff --git a/printing/proof_diffs.ml b/printing/proof_diffs.ml
index 3a81e908a7..5bb1053645 100644
--- a/printing/proof_diffs.ml
+++ b/printing/proof_diffs.ml
@@ -14,39 +14,26 @@ Proof General requires minor changes to make the diffs visible, but this code
shouldn't break the existing version of PG. See pp_diff.ml for details on how
the diff works.
-Diffs are computed for the hypotheses and conclusion of the first goal between
-the old and new proofs.
+Diffs are computed for the hypotheses and conclusion of each goal in the new
+proof with its matching goal in the old proof.
-Diffs can be enabled with the Coq commmand "Set Diffs on|off|removed." or
-'-diffs "on"|"off"|"removed"' on the OS command line. The "on" option shows only the
-new item with added text, while "removed" shows each modified item twice--once
-with the old value showing removed text and once with the new value showing
-added text.
+Diffs can be enabled in coqtop with 'Set Diffs "on"|"off"|"removed"' or
+'-diffs on|off|removed' on the OS command line. In CoqIDE, they can be enabled
+from the View menu. The "on" option shows only the new item with added text,
+while "removed" shows each modified item twice--once with the old value showing
+removed text and once with the new value showing added text.
In CoqIDE, colors and highlights can be set in the Edit/Preferences/Tags panel.
For coqtop, these can be set through the COQ_COLORS environment variable.
Limitations/Possible enhancements:
-- If you go back to a prior proof step, diffs are not shown on the new current
-step. Diffs will be shown again once you do another proof step.
-
-- Diffs are done between the first active goal in the old and new proofs.
-If, for example, the proof step completed a goal, then the new goal is a
-different goal, not a transformation of the old goal, so a diff is probably
-not appropriate. (There's currently no way to tell when this happens or to
-accurately match goals across old and new proofs.
-See https://github.com/coq/coq/issues/7653) This is also why only the
-first goal is diffed.
-
-- "Set Diffs "xx"." should reprint the current goal using the new option.
-
- coqtop colors were chosen for white text on a black background. They're
not the greatest. I didn't want to change the existing green highlight.
Suggestions welcome.
- coqtop underlines removed text because (per Wikipedia) the ANSI escape code
-for strikeout is not commonly supported (it didn't work on mine). CoqIDE
+for strikeout is not commonly supported (it didn't work on my system). CoqIDE
uses strikeout on removed text.
*)
@@ -54,8 +41,6 @@ open Pp_diff
let diff_option = ref `OFF
-(* todo: Is there a way to persist the setting between sessions?
- Eg if the user wants this as a permanent config setting? *)
let read_diffs_option () = match !diff_option with
| `OFF -> "off"
| `ON -> "on"
@@ -136,7 +121,8 @@ let diff_hyps o_line_idents o_map n_line_idents n_map =
(* use the order from the old line in case it's changed in the new *)
let old_ids = if old_ids_uo = [] then [] else
let orig = (StringMap.find (List.hd old_ids_uo) o_map).idents in
- List.concat (List.map (contains orig) old_ids_uo) in
+ List.concat (List.map (contains orig) old_ids_uo)
+ in
let setup ids map = if ids = [] then ("", Pp.mt ()) else
let open Pp in
@@ -233,6 +219,12 @@ let to_tuple : Constr.compacted_declaration -> (Names.Id.t list * 'pc option * '
(* XXX: Very unfortunately we cannot use the Proofview interface as
Proof is still using the "legacy" one. *)
+let process_goal_concl sigma g : Constr.t * Environ.env =
+ let env = Goal.V82.env sigma g in
+ let ty = Goal.V82.concl sigma g in
+ let ty = EConstr.to_constr sigma ty in
+ (ty, env)
+
let process_goal sigma g : Constr.t reified_goal =
let env = Goal.V82.env sigma g in
let hyps = Goal.V82.hyps sigma g in
@@ -256,14 +248,29 @@ let pr_leconstr_core goal_concl_style env sigma t =
let pr_lconstr_env env sigma c = pr_leconstr_core false env sigma (EConstr.of_constr c)
+let diff_concl ?og_s nsigma ng =
+ let open Evd in
+ let o_concl_pp = match og_s with
+ | Some { it=og; sigma=osigma } ->
+ let (oty, oenv) = process_goal_concl osigma og in
+ pp_of_type oenv osigma oty
+ | None -> Pp.mt()
+ in
+ let (nty, nenv) = process_goal_concl nsigma ng in
+ let n_concl_pp = pp_of_type nenv nsigma nty in
+
+ let show_removed = Some (show_removed ()) in
+
+ diff_pp_combined ~tokenize_string ?show_removed o_concl_pp n_concl_pp
+
(* fetch info from a goal, returning (idents, map, concl_pp) where
-idents is a list with one entry for each hypothesis, each entry is the list of
-idents on the lhs of the hypothesis. map is a map from ident to hyp_info
-reoords. For example: for the hypotheses:
+idents is a list with one entry for each hypothesis, in which each entry
+is the list of idents on the lhs of the hypothesis. map is a map from
+ident to hyp_info reoords. For example: for the hypotheses:
b : bool
n, m : nat
-list will be [ ["b"]; ["n"; "m"] ]
+idents will be [ ["b"]; ["n"; "m"] ]
map will contain:
"b" -> { ["b"], Pp.t for ": bool"; false }
@@ -317,31 +324,314 @@ let hyp_list_to_pp hyps =
| h :: tl -> List.fold_left (fun x y -> x ++ cut () ++ y) h tl
| [] -> mt ();;
-(* Special purpuse, use only for the IDE interface, *)
-let diff_first_goal o_proof n_proof =
- let first_goal_info proof =
- match proof with
- | None -> ([], StringMap.empty, Pp.mt ())
- | Some proof2 ->
- let (goals,_,_,_,sigma) = Proof.proof proof2 in
- match goals with
- | hd :: tl -> goal_info hd sigma;
- | _ -> ([], StringMap.empty, Pp.mt ())
- in
- diff_goal_info (first_goal_info o_proof) (first_goal_info n_proof);;
-
-let diff_goals ?prev_gs n_gs =
- let unwrap gs =
- match gs with
- | Some gs ->
- let goal = Evd.sig_it gs in
- let sigma = Refiner.project gs in
- goal_info goal sigma
- | None -> ([], StringMap.empty, Pp.mt ())
- in
- let (hyps_pp_list, concl_pp) = diff_goal_info (unwrap prev_gs) (unwrap n_gs) in
+let unwrap g_s =
+ match g_s with
+ | Some g_s ->
+ let goal = Evd.sig_it g_s in
+ let sigma = Refiner.project g_s in
+ goal_info goal sigma
+ | None -> ([], StringMap.empty, Pp.mt ())
+
+let diff_goal_ide og_s ng nsigma =
+ diff_goal_info (unwrap og_s) (goal_info ng nsigma)
+
+let diff_goal ?og_s ng ns =
+ let (hyps_pp_list, concl_pp) = diff_goal_info (unwrap og_s) (goal_info ng ns) in
let open Pp in
v 0 (
(hyp_list_to_pp hyps_pp_list) ++ cut () ++
str "============================" ++ cut () ++
concl_pp);;
+
+
+(*** Code to determine which calls to compare between the old and new proofs ***)
+
+open Constrexpr
+open Glob_term
+open Names
+open CAst
+
+(* Compare the old and new proof trees to identify the correspondence between
+new and old goals. Returns a map from the new evar name to the old,
+e.g. "Goal2" -> "Goal1". Assumes that proof steps only rewrite CEvar nodes
+and that CEvar nodes cannot contain other CEvar nodes.
+
+The comparison works this way:
+1. Traverse the old and new trees together (ogname = "", ot != nt):
+- if the old and new trees both have CEvar nodes, add an entry to the map from
+ the new evar name to the old evar name. (Position of goals is preserved but
+ evar names may not be--see below.)
+- if the old tree has a CEvar node and the new tree has a different type of node,
+ we've found a changed goal. Set ogname to the evar name of the old goal and
+ go to step 2.
+- any other mismatch violates the assumptions, raise an exception
+2. Traverse the new tree from the point of the difference (ogname <> "", ot = nt).
+- if the node is a CEvar, generate a map entry from the new evar name to ogname.
+
+Goal ids for unchanged goals appear to be preserved across proof steps.
+However, the evar name associated with a goal id may change in a proof step
+even if that goal is not changed by the tactic. You can see this by enabling
+the call to db_goal_map and entering the following:
+
+ Parameter P : nat -> Prop.
+ Goal (P 1 /\ P 2 /\ P 3) /\ P 4.
+ split.
+ Show Proof.
+ split.
+ Show Proof.
+
+ Which gives you this summarized output:
+
+ > split.
+ New Goals: 3 -> Goal 4 -> Goal0 <--- goal 4 is "Goal0"
+ Old Goals: 1 -> Goal
+ Goal map: 3 -> 1 4 -> 1
+ > Show Proof.
+ (conj ?Goal ?Goal0) <--- goal 4 is the rightmost goal in the proof
+ > split.
+ New Goals: 6 -> Goal0 7 -> Goal1 4 -> Goal <--- goal 4 is now "Goal"
+ Old Goals: 3 -> Goal 4 -> Goal0
+ Goal map: 6 -> 3 7 -> 3
+ > Show Proof.
+ (conj (conj ?Goal0 ?Goal1) ?Goal) <--- goal 4 is still the rightmost goal in the proof
+ *)
+let match_goals ot nt =
+ let nevar_to_oevar = ref StringMap.empty in
+ (* ogname is "" when there is no difference on the current path.
+ It's set to the old goal's evar name once a rewitten goal is found,
+ at which point the code only searches for the replacing goals
+ (and ot is set to nt). *)
+ let rec match_goals_r ogname ot nt =
+ let constr_expr ogname exp exp2 =
+ match_goals_r ogname exp.v exp2.v
+ in
+ let constr_expr_opt ogname exp exp2 =
+ match exp, exp2 with
+ | Some expa, Some expb -> constr_expr ogname expa expb
+ | None, None -> ()
+ | _, _ -> raise (Diff_Failure "Unable to match goals betwen old and new proof states (1)")
+ in
+ let local_binder_expr ogname exp exp2 =
+ match exp, exp2 with
+ | CLocalAssum (nal,bk,ty), CLocalAssum(nal2,bk2,ty2) ->
+ constr_expr ogname ty ty2
+ | CLocalDef (n,c,t), CLocalDef (n2,c2,t2) ->
+ constr_expr ogname c c2;
+ constr_expr_opt ogname t t2
+ | CLocalPattern p, CLocalPattern p2 ->
+ let (p,ty), (p2,ty2) = p.v,p2.v in
+ constr_expr_opt ogname ty ty2
+ | _, _ -> raise (Diff_Failure "Unable to match goals betwen old and new proof states (2)")
+ in
+ let recursion_order_expr ogname exp exp2 =
+ match exp, exp2 with
+ | CStructRec, CStructRec -> ()
+ | CWfRec c, CWfRec c2 ->
+ constr_expr ogname c c2
+ | CMeasureRec (m,r), CMeasureRec (m2,r2) ->
+ constr_expr ogname m m2;
+ constr_expr_opt ogname r r2
+ | _, _ -> raise (Diff_Failure "Unable to match goals betwen old and new proof states (3)")
+ in
+ let fix_expr ogname exp exp2 =
+ let (l,(lo,ro),lb,ce1,ce2), (l2,(lo2,ro2),lb2,ce12,ce22) = exp,exp2 in
+ recursion_order_expr ogname ro ro2;
+ List.iter2 (local_binder_expr ogname) lb lb2;
+ constr_expr ogname ce1 ce12;
+ constr_expr ogname ce2 ce22
+ in
+ let cofix_expr ogname exp exp2 =
+ let (l,lb,ce1,ce2), (l2,lb2,ce12,ce22) = exp,exp2 in
+ List.iter2 (local_binder_expr ogname) lb lb2;
+ constr_expr ogname ce1 ce12;
+ constr_expr ogname ce2 ce22
+ in
+ let case_expr ogname exp exp2 =
+ let (ce,l,cp), (ce2,l2,cp2) = exp,exp2 in
+ constr_expr ogname ce ce2
+ in
+ let branch_expr ogname exp exp2 =
+ let (cpe,ce), (cpe2,ce2) = exp.v,exp2.v in
+ constr_expr ogname ce ce2
+ in
+ let constr_notation_substitution ogname exp exp2 =
+ let (ce, cel, cp, lb), (ce2, cel2, cp2, lb2) = exp, exp2 in
+ List.iter2 (constr_expr ogname) ce ce2;
+ List.iter2 (fun a a2 -> List.iter2 (constr_expr ogname) a a2) cel cel2;
+ List.iter2 (fun a a2 -> List.iter2 (local_binder_expr ogname) a a2) lb lb2
+ in
+ begin
+ match ot, nt with
+ | CRef (ref,us), CRef (ref2,us2) -> ()
+ | CFix (id,fl), CFix (id2,fl2) ->
+ List.iter2 (fix_expr ogname) fl fl2
+ | CCoFix (id,cfl), CCoFix (id2,cfl2) ->
+ List.iter2 (cofix_expr ogname) cfl cfl2
+ | CProdN (bl,c2), CProdN (bl2,c22)
+ | CLambdaN (bl,c2), CLambdaN (bl2,c22) ->
+ List.iter2 (local_binder_expr ogname) bl bl2;
+ constr_expr ogname c2 c22
+ | CLetIn (na,c1,t,c2), CLetIn (na2,c12,t2,c22) ->
+ constr_expr ogname c1 c12;
+ constr_expr_opt ogname t t2;
+ constr_expr ogname c2 c22
+ | CAppExpl ((isproj,ref,us),args), CAppExpl ((isproj2,ref2,us2),args2) ->
+ List.iter2 (constr_expr ogname) args args2
+ | CApp ((isproj,f),args), CApp ((isproj2,f2),args2) ->
+ constr_expr ogname f f2;
+ List.iter2 (fun a a2 -> let (c, _) = a and (c2, _) = a2 in
+ constr_expr ogname c c2) args args2
+ | CRecord fs, CRecord fs2 ->
+ List.iter2 (fun a a2 -> let (_, c) = a and (_, c2) = a2 in
+ constr_expr ogname c c2) fs fs2
+ | CCases (sty,rtnpo,tms,eqns), CCases (sty2,rtnpo2,tms2,eqns2) ->
+ constr_expr_opt ogname rtnpo rtnpo2;
+ List.iter2 (case_expr ogname) tms tms2;
+ List.iter2 (branch_expr ogname) eqns eqns2
+ | CLetTuple (nal,(na,po),b,c), CLetTuple (nal2,(na2,po2),b2,c2) ->
+ constr_expr_opt ogname po po2;
+ constr_expr ogname b b2;
+ constr_expr ogname c c2
+ | CIf (c,(na,po),b1,b2), CIf (c2,(na2,po2),b12,b22) ->
+ constr_expr ogname c c2;
+ constr_expr_opt ogname po po2;
+ constr_expr ogname b1 b12;
+ constr_expr ogname b2 b22
+ | CHole (k,naming,solve), CHole (k2,naming2,solve2) -> ()
+ | CPatVar _, CPatVar _ -> ()
+ | CEvar (n,l), CEvar (n2,l2) ->
+ let oevar = if ogname = "" then Id.to_string n else ogname in
+ nevar_to_oevar := StringMap.add (Id.to_string n2) oevar !nevar_to_oevar;
+ List.iter2 (fun x x2 -> let (_, g) = x and (_, g2) = x2 in constr_expr ogname g g2) l l2
+ | CEvar (n,l), nt' ->
+ (* pass down the old goal evar name *)
+ match_goals_r (Id.to_string n) nt' nt'
+ | CSort s, CSort s2 -> ()
+ | CCast (c,c'), CCast (c2,c'2) ->
+ constr_expr ogname c c2;
+ (match c', c'2 with
+ | CastConv a, CastConv a2
+ | CastVM a, CastVM a2
+ | CastNative a, CastNative a2 ->
+ constr_expr ogname a a2
+ | CastCoerce, CastCoerce -> ()
+ | _, _ -> raise (Diff_Failure "Unable to match goals betwen old and new proof states (4)"))
+ | CNotation (ntn,args), CNotation (ntn2,args2) ->
+ constr_notation_substitution ogname args args2
+ | CGeneralization (b,a,c), CGeneralization (b2,a2,c2) ->
+ constr_expr ogname c c2
+ | CPrim p, CPrim p2 -> ()
+ | CDelimiters (key,e), CDelimiters (key2,e2) ->
+ constr_expr ogname e e2
+ | CProj (pr,c), CProj (pr2,c2) ->
+ constr_expr ogname c c2
+ | _, _ -> raise (Diff_Failure "Unable to match goals betwen old and new proof states (5)")
+ end
+ in
+
+ (match ot with
+ | Some ot -> match_goals_r "" ot nt
+ | None -> ());
+ !nevar_to_oevar
+
+
+let to_constr p =
+ let open CAst in
+ let pprf = Proof.partial_proof p in
+ (* pprf generally has only one element, but it may have more in the derive plugin *)
+ let t = List.hd pprf in
+ let sigma, env = Pfedit.get_current_context ~p () in
+ let x = Constrextern.extern_constr false env sigma t in (* todo: right options?? *)
+ x.v
+
+
+module GoalMap = Evar.Map
+
+let goal_to_evar g sigma = Id.to_string (Termops.pr_evar_suggested_name g sigma)
+
+[@@@ocaml.warning "-32"]
+let db_goal_map op np ng_to_og =
+ Printf.printf "New Goals: ";
+ let (ngoals,_,_,_,nsigma) = Proof.proof np in
+ List.iter (fun ng -> Printf.printf "%d -> %s " (Evar.repr ng) (goal_to_evar ng nsigma)) ngoals;
+ (match op with
+ | Some op ->
+ let (ogoals,_,_,_,osigma) = Proof.proof op in
+ Printf.printf "\nOld Goals: ";
+ List.iter (fun og -> Printf.printf "%d -> %s " (Evar.repr og) (goal_to_evar og osigma)) ogoals
+ | None -> ());
+ Printf.printf "\nGoal map: ";
+ GoalMap.iter (fun og ng -> Printf.printf "%d -> %d " (Evar.repr og) (Evar.repr ng)) ng_to_og;
+ Printf.printf "\n"
+[@@@ocaml.warning "+32"]
+
+(* Create a map from new goals to old goals for proof diff. The map only
+ has entries for new goals that are not the same as the corresponding old
+ goal; there are no entries for unchanged goals.
+
+ It proceeds as follows:
+ 1. Find the goal ids that were removed from the old proof and that were
+ added in the new proof. If the same goal id is present in both proofs
+ then conclude the goal is unchanged (assumption).
+
+ 2. The code assumes that proof changes only take the form of replacing
+ one or more goal symbols (CEvars) with new terms. Therefore:
+ - if there are no removals, the proofs are the same.
+ - if there are removals but no additions, then there are no new goals
+ that aren't the same as their associated old goals. For the both of
+ these cases, the map is empty because there are no new goals that differ
+ from their old goals
+ - if there is only one removal, then any added goals should be mapped to
+ the removed goal.
+ - if there are more than 2 removals and more than one addition, call
+ match_goals to get a map between old and new evar names, then use this
+ to create the map from new goal ids to old goal ids for the differing goals.
+*)
+let make_goal_map_i op np =
+ let ng_to_og = ref GoalMap.empty in
+ match op with
+ | None -> !ng_to_og
+ | Some op ->
+ let open Goal.Set in
+ let ogs = Proof.all_goals op in
+ let ngs = Proof.all_goals np in
+ let rem_gs = diff ogs ngs in
+ let num_rems = cardinal rem_gs in
+ let add_gs = diff ngs ogs in
+ let num_adds = cardinal add_gs in
+
+ if num_rems = 0 then
+ !ng_to_og (* proofs are the same *)
+ else if num_adds = 0 then
+ !ng_to_og (* only removals *)
+ else if num_rems = 1 then begin
+ (* only 1 removal, some additions *)
+ let removed_g = List.hd (elements rem_gs) in
+ Goal.Set.iter (fun x -> ng_to_og := GoalMap.add x removed_g !ng_to_og) add_gs;
+ !ng_to_og
+ end else begin
+ (* >= 2 removals, >= 1 addition, need to match *)
+ let nevar_to_oevar = match_goals (Some (to_constr op)) (to_constr np) in
+
+ let oevar_to_og = ref StringMap.empty in
+ let (_,_,_,_,osigma) = Proof.proof op in
+ List.iter (fun og -> oevar_to_og := StringMap.add (goal_to_evar og osigma) og !oevar_to_og)
+ (Goal.Set.elements rem_gs);
+
+ try
+ let (_,_,_,_,nsigma) = Proof.proof np in
+ let get_og ng =
+ let nevar = goal_to_evar ng nsigma in
+ let oevar = StringMap.find nevar nevar_to_oevar in
+ let og = StringMap.find oevar !oevar_to_og in
+ og
+ in
+ Goal.Set.iter (fun ng -> ng_to_og := GoalMap.add ng (get_og ng) !ng_to_og) add_gs;
+ !ng_to_og
+ with Not_found -> raise (Diff_Failure "Unable to match goals betwen old and new proof states (6)")
+ end
+
+let make_goal_map op np =
+ let ng_to_og = make_goal_map_i op np in
+ (*db_goal_map op np ng_to_og;*)
+ ng_to_og
diff --git a/printing/proof_diffs.mli b/printing/proof_diffs.mli
index 482f03b686..832393e15f 100644
--- a/printing/proof_diffs.mli
+++ b/printing/proof_diffs.mli
@@ -15,8 +15,13 @@ val write_diffs_option : string -> unit
(** Returns true if the diffs option is "on" or "removed" *)
val show_diffs : unit -> bool
-(** Computes the diff between the first goal of two Proofs and returns
-the highlighted hypotheses and conclusion.
+open Evd
+open Proof_type
+open Environ
+open Constr
+
+(** Computes the diff between the goals of two Proofs and returns
+the highlighted lists of hypotheses and conclusions.
If the strings used to display the goal are not lexable (this is believed
unlikely), this routine will generate a Diff_Failure. This routine may also
@@ -26,12 +31,7 @@ If you want to make your call especially bulletproof, catch these
exceptions, print a user-visible message, then recall this routine with
the first argument set to None, which will skip the diff.
*)
-val diff_first_goal : Proof.t option -> Proof.t option -> Pp.t list * Pp.t
-
-open Evd
-open Proof_type
-open Environ
-open Constr
+val diff_goal_ide : goal sigma option -> goal -> Evd.evar_map -> Pp.t list * Pp.t
(** Computes the diff between two goals
@@ -43,7 +43,7 @@ If you want to make your call especially bulletproof, catch these
exceptions, print a user-visible message, then recall this routine with
the first argument set to None, which will skip the diff.
*)
-val diff_goals : ?prev_gs:(goal sigma) -> goal sigma option -> Pp.t
+val diff_goal : ?og_s:(goal sigma) -> goal -> Evd.evar_map -> Pp.t
(** Convert a string to a list of token strings using the lexer *)
val tokenize_string : string -> string list
@@ -52,6 +52,17 @@ val pr_letype_core : bool -> Environ.env -> Evd.evar_map -> EConstr.type
val pr_leconstr_core : bool -> Environ.env -> Evd.evar_map -> EConstr.constr -> Pp.t
val pr_lconstr_env : env -> evar_map -> constr -> Pp.t
+(** Computes diffs for a single conclusion *)
+val diff_concl : ?og_s:goal sigma -> Evd.evar_map -> Goal.goal -> Pp.t
+
+(** Generates a map from [np] to [op] that maps changed goals to their prior
+forms. The map doesn't include entries for unchanged goals; unchanged goals
+will have the same goal id in both versions.
+
+[op] and [np] must be from the same proof document and [op] must be for a state
+before [np]. *)
+val make_goal_map : Proof.t option -> Proof.t -> Evar.t Evar.Map.t
+
(* Exposed for unit test, don't use these otherwise *)
(* output channel for the test log file *)
val log_out_ch : out_channel ref
diff --git a/proofs/clenv.ml b/proofs/clenv.ml
index 79b7e1599b..95e908c4dd 100644
--- a/proofs/clenv.ml
+++ b/proofs/clenv.ml
@@ -575,8 +575,8 @@ let make_clenv_binding env sigma = make_clenv_binding_gen false None env sigma
let pr_clenv clenv =
h 0
- (str"TEMPL: " ++ print_constr clenv.templval.rebus ++
- str" : " ++ print_constr clenv.templtyp.rebus ++ fnl () ++
+ (str"TEMPL: " ++ Termops.Internal.print_constr_env clenv.env clenv.evd clenv.templval.rebus ++
+ str" : " ++ Termops.Internal.print_constr_env clenv.env clenv.evd clenv.templtyp.rebus ++ fnl () ++
pr_evar_map (Some 2) clenv.evd)
(****************************************************************)
diff --git a/proofs/dune b/proofs/dune
new file mode 100644
index 0000000000..679c45f6bf
--- /dev/null
+++ b/proofs/dune
@@ -0,0 +1,6 @@
+(library
+ (name proofs)
+ (synopsis "Coq's Higher-level Refinement Proof Engine and Top-level Proof Structure")
+ (public_name coq.proofs)
+ (wrapped false)
+ (libraries interp))
diff --git a/proofs/goal.ml b/proofs/goal.ml
index 1440d1636b..c14c0a8a77 100644
--- a/proofs/goal.ml
+++ b/proofs/goal.ml
@@ -143,3 +143,5 @@ module V82 = struct
) ~init:(concl sigma gl) env
end
+
+module Set = Set.Make(struct type t = goal let compare = Evar.compare end)
diff --git a/proofs/goal.mli b/proofs/goal.mli
index b8c979ad7a..a033d6daab 100644
--- a/proofs/goal.mli
+++ b/proofs/goal.mli
@@ -71,3 +71,5 @@ module V82 : sig
val abstract_type : Evd.evar_map -> goal -> EConstr.types
end
+
+module Set : sig include Set.S with type elt = goal end
diff --git a/proofs/logic.ml b/proofs/logic.ml
index e8ca719932..613581ade7 100644
--- a/proofs/logic.ml
+++ b/proofs/logic.ml
@@ -62,6 +62,7 @@ let is_unification_error = function
let catchable_exception = function
| CErrors.UserError _ | TypeError _
+ | Notation.NumeralNotationError _
| RefinerError _ | Indrec.RecursionSchemeError _
| Nametab.GlobalizationError _
(* reduction errors *)
diff --git a/proofs/pfedit.ml b/proofs/pfedit.ml
index 678c3ea3f7..e6507332b1 100644
--- a/proofs/pfedit.ml
+++ b/proofs/pfedit.ml
@@ -51,23 +51,22 @@ let _ = CErrors.register_handler begin function
| _ -> raise CErrors.Unhandled
end
-let get_nth_V82_goal i =
- let p = Proof_global.give_me_the_proof () in
+let get_nth_V82_goal p i =
let goals,_,_,_,sigma = Proof.proof p in
try { it = List.nth goals (i-1) ; sigma }
with Failure _ -> raise NoSuchGoal
-let get_goal_context_gen i =
- let { it=goal ; sigma=sigma; } = get_nth_V82_goal i in
+let get_goal_context_gen p i =
+ let { it=goal ; sigma=sigma; } = get_nth_V82_goal p i in
(sigma, Refiner.pf_env { it=goal ; sigma=sigma; })
let get_goal_context i =
- try get_goal_context_gen i
+ try get_goal_context_gen (Proof_global.give_me_the_proof ()) i
with Proof_global.NoCurrentProof -> CErrors.user_err Pp.(str "No focused proof.")
| NoSuchGoal -> CErrors.user_err Pp.(str "No such goal.")
let get_current_goal_context () =
- try get_goal_context_gen 1
+ try get_goal_context_gen (Proof_global.give_me_the_proof ()) 1
with Proof_global.NoCurrentProof -> CErrors.user_err Pp.(str "No focused proof.")
| NoSuchGoal ->
(* spiwack: returning empty evar_map, since if there is no goal, under focus,
@@ -75,14 +74,18 @@ let get_current_goal_context () =
let env = Global.env () in
(Evd.from_env env, env)
-let get_current_context () =
- try get_goal_context_gen 1
+let get_current_context ?p () =
+ let current_proof_by_default = function
+ | Some p -> p
+ | None -> Proof_global.give_me_the_proof ()
+ in
+ try get_goal_context_gen (current_proof_by_default p) 1
with Proof_global.NoCurrentProof ->
let env = Global.env () in
(Evd.from_env env, env)
| NoSuchGoal ->
(* No more focused goals ? *)
- let p = Proof_global.give_me_the_proof () in
+ let p = (current_proof_by_default p) in
let evd = Proof.in_proof p (fun x -> x) in
(evd, Global.env ())
@@ -173,8 +176,8 @@ let build_by_tactic ?(side_eff=true) env sigma ?(poly=false) typ tac =
const_entry_body = Future.chain ce.const_entry_body
(fun (pt, _) -> pt, ()) } in
let (cb, ctx), () = Future.force ce.const_entry_body in
- let univs' = Evd.merge_context_set Evd.univ_rigid (Evd.from_ctx univs) ctx in
- cb, status, Evd.evar_universe_context univs'
+ let univs = UState.merge ~sideff:side_eff ~extend:true Evd.univ_rigid univs ctx in
+ cb, status, univs
let refine_by_tactic env sigma ty tac =
(** Save the initial side-effects to restore them afterwards. We set the
diff --git a/proofs/pfedit.mli b/proofs/pfedit.mli
index e02b5ab956..5feb5bd645 100644
--- a/proofs/pfedit.mli
+++ b/proofs/pfedit.mli
@@ -60,7 +60,7 @@ val get_current_goal_context : unit -> Evd.evar_map * env
If there is no pending proof then it returns the current global
environment and empty evar_map. *)
-val get_current_context : unit -> Evd.evar_map * env
+val get_current_context : ?p:Proof.t -> unit -> Evd.evar_map * env
(** [current_proof_statement] *)
diff --git a/proofs/proof.ml b/proofs/proof.ml
index 51e0a1d614..8bbd82bb0a 100644
--- a/proofs/proof.ml
+++ b/proofs/proof.ml
@@ -63,6 +63,7 @@ exception CannotUnfocusThisWay
(* Cannot focus on non-existing subgoals *)
exception NoSuchGoals of int * int
+exception NoSuchGoal of Names.Id.t
exception FullyUnfocused
@@ -75,6 +76,10 @@ let _ = CErrors.register_handler begin function
CErrors.user_err ~hdr:"Focus" Pp.(
str"Not every goal in range ["++ int i ++ str","++int j++str"] exist."
)
+ | NoSuchGoal id ->
+ CErrors.user_err
+ ~hdr:"Focus"
+ Pp.(str "No such goal: " ++ str (Names.Id.to_string id) ++ str ".")
| FullyUnfocused -> CErrors.user_err Pp.(str "The proof is not focused")
| _ -> raise CErrors.Unhandled
end
@@ -230,6 +235,37 @@ let focus cond inf i pr =
try _focus cond (Obj.repr inf) i i pr
with CList.IndexOutOfRange -> raise (NoSuchGoals (i,i))
+(* Focus on the goal named id *)
+let focus_id cond inf id pr =
+ let (focused_goals, evar_map) = Proofview.proofview pr.proofview in
+ begin match try Some (Evd.evar_key id evar_map) with Not_found -> None with
+ | Some ev ->
+ begin match CList.safe_index Evar.equal ev focused_goals with
+ | Some i ->
+ (* goal is already under focus *)
+ _focus cond (Obj.repr inf) i i pr
+ | None ->
+ if CList.mem_f Evar.equal ev pr.shelf then
+ (* goal is on the shelf, put it in focus *)
+ let proofview = Proofview.unshelve [ev] pr.proofview in
+ let shelf =
+ CList.filter (fun ev' -> Evar.equal ev ev' |> not) pr.shelf
+ in
+ let pr = { pr with proofview; shelf } in
+ let (focused_goals, _) = Proofview.proofview pr.proofview in
+ let i =
+ (* Now we know that this will succeed *)
+ try CList.index Evar.equal ev focused_goals
+ with Not_found -> assert false
+ in
+ _focus cond (Obj.repr inf) i i pr
+ else
+ raise CannotUnfocusThisWay
+ end
+ | None ->
+ raise (NoSuchGoal id)
+ end
+
let rec unfocus kind pr () =
let cond = cond_of_focus pr in
match test_cond cond kind pr.proofview with
@@ -452,3 +488,12 @@ module V82 = struct
{ pr with proofview ; shelf }
end
+
+let all_goals p =
+ let add gs set =
+ List.fold_left (fun s g -> Goal.Set.add g s) set gs in
+ let (goals,stack,shelf,given_up,_) = proof p in
+ let set = add goals Goal.Set.empty in
+ let set = List.fold_left (fun s gs -> let (g1, g2) = gs in add g1 (add g2 set)) set stack in
+ let set = add shelf set in
+ add given_up set
diff --git a/proofs/proof.mli b/proofs/proof.mli
index c0e832fb8c..511dcc2e00 100644
--- a/proofs/proof.mli
+++ b/proofs/proof.mli
@@ -137,6 +137,9 @@ val done_cond : ?loose_end:bool -> 'a focus_kind -> 'a focus_condition
a need for it? *)
val focus : 'a focus_condition -> 'a -> int -> t -> t
+(* focus on goal named id *)
+val focus_id : 'aa focus_condition -> 'a -> Names.Id.t -> t -> t
+
exception FullyUnfocused
exception CannotUnfocusThisWay
@@ -207,3 +210,6 @@ module V82 : sig
(* Implements the Existential command *)
val instantiate_evar : int -> Constrexpr.constr_expr -> t -> t
end
+
+(* returns the set of all goals in the proof *)
+val all_goals : t -> Goal.Set.t
diff --git a/proofs/redexpr.ml b/proofs/redexpr.ml
index 629b77be2a..44685d2bbd 100644
--- a/proofs/redexpr.ml
+++ b/proofs/redexpr.ml
@@ -52,7 +52,7 @@ let whd_cbn flags env sigma t =
Reductionops.Stack.zip ~refold:true sigma state
let strong_cbn flags =
- strong (whd_cbn flags)
+ strong_with_flags whd_cbn flags
let simplIsCbn = ref (false)
let _ = Goptions.declare_bool_option {
diff --git a/proofs/refine.ml b/proofs/refine.ml
index b64e7a2e5e..05474d5f84 100644
--- a/proofs/refine.ml
+++ b/proofs/refine.ml
@@ -44,25 +44,16 @@ let typecheck_evar ev env sigma =
let sigma, _ = Typing.sort_of env sigma (Evd.evar_concl info) in
sigma
-let (pr_constrv,pr_constr) =
- Hook.make ~default:(fun _env _sigma _c -> Pp.str"<constr>") ()
-
(* Get the side-effect's constant declarations to update the monad's
* environmnent *)
-let add_if_undefined kn cb env =
- try ignore(Environ.lookup_constant kn env); env
- with Not_found -> Environ.add_constant kn cb env
+let add_if_undefined env eff =
+ let open Entries in
+ try ignore(Environ.lookup_constant eff.seff_constant env); env
+ with Not_found -> Environ.add_constant eff.seff_constant eff.seff_body env
(* Add the side effects to the monad's environment, if not already done. *)
-let add_side_effect env = function
- | { Entries.eff = Entries.SEsubproof (kn, cb, eff_env) } ->
- add_if_undefined kn cb env
- | { Entries.eff = Entries.SEscheme (l,_) } ->
- List.fold_left (fun env (_,kn,cb,eff_env) ->
- add_if_undefined kn cb env) env l
-
-let add_side_effects env effects =
- List.fold_left (fun env eff -> add_side_effect env eff) env effects
+let add_side_effects env eff =
+ List.fold_left add_if_undefined env eff
let generic_refine ~typecheck f gl =
let sigma = Proofview.Goal.sigma gl in
@@ -117,7 +108,7 @@ let generic_refine ~typecheck f gl =
let sigma = CList.fold_left Proofview.Unsafe.mark_as_goal sigma comb in
let comb = CList.map (fun x -> Proofview.goal_with_state x state) comb in
let trace () = Pp.(hov 2 (str"simple refine"++spc()++
- Hook.get pr_constrv env sigma (EConstr.Unsafe.to_constr c))) in
+ Termops.Internal.print_constr_env env sigma c)) in
Proofview.Trace.name_tactic trace (Proofview.tclUNIT v) >>= fun v ->
Proofview.Unsafe.tclSETENV (Environ.reset_context env) <*>
Proofview.Unsafe.tclEVARS sigma <*>
diff --git a/proofs/refine.mli b/proofs/refine.mli
index 70a23a9fba..1af6463a02 100644
--- a/proofs/refine.mli
+++ b/proofs/refine.mli
@@ -17,10 +17,6 @@ open Proofview
(** {6 The refine tactic} *)
-(** Printer used to print the constr which refine refines. *)
-val pr_constr :
- (Environ.env -> Evd.evar_map -> Constr.constr -> Pp.t) Hook.t
-
(** {7 Refinement primitives} *)
val refine : typecheck:bool -> (Evd.evar_map -> Evd.evar_map * EConstr.t) -> unit tactic
diff --git a/proofs/tacmach.ml b/proofs/tacmach.ml
index 6036c8cbca..9e42a71ea8 100644
--- a/proofs/tacmach.ml
+++ b/proofs/tacmach.ml
@@ -127,8 +127,8 @@ open Pp
let db_pr_goal sigma g =
let env = Goal.V82.env sigma g in
- let penv = print_named_context env in
- let pc = print_constr_env env sigma (Goal.V82.concl sigma g) in
+ let penv = Termops.Internal.print_named_context env in
+ let pc = Termops.Internal.print_constr_env env sigma (Goal.V82.concl sigma g) in
str" " ++ hv 0 (penv ++ fnl () ++
str "============================" ++ fnl () ++
str" " ++ pc) ++ fnl ()
diff --git a/shell.nix b/shell.nix
index 3201c50501..75ac952bd6 100644
--- a/shell.nix
+++ b/shell.nix
@@ -1,4 +1,3 @@
-# Some developers don't want a pinned nix-shell by default.
-# If you want to use the pin nix-shell or a more sophisticated set of arguments:
+# If you want to use a more sophisticated set of arguments:
# $ nix-shell default.nix --arg shell true
-import ./default.nix { pkgs = import <nixpkgs> {}; shell = true; }
+import ./default.nix { shell = true; }
diff --git a/stm/dune b/stm/dune
new file mode 100644
index 0000000000..c369bd00fb
--- /dev/null
+++ b/stm/dune
@@ -0,0 +1,6 @@
+(library
+ (name stm)
+ (synopsis "Coq's Document Manager and Proof Checking Scheduler")
+ (public_name coq.stm)
+ (wrapped false)
+ (libraries vernac))
diff --git a/stm/stm.ml b/stm/stm.ml
index 2e9bf71e49..b7ba163309 100644
--- a/stm/stm.ml
+++ b/stm/stm.ml
@@ -1231,9 +1231,22 @@ end = struct (* {{{ *)
let get_prev_proof ~doc id =
try
- let did = fold_until back_tactic 1 id in
- get_proof ~doc did
- with Not_found -> None
+ let np = get_proof ~doc id in
+ match np with
+ | None -> None
+ | Some cp ->
+ let did = ref id in
+ let rv = ref np in
+ let done_ = ref false in
+ while not !done_ do
+ did := fold_until back_tactic 1 !did;
+ rv := get_proof ~doc !did;
+ done_ := match !rv with
+ | Some rv -> not (Goal.Set.equal (Proof.all_goals rv) (Proof.all_goals cp))
+ | None -> true
+ done;
+ !rv
+ with Not_found | Proof_global.NoCurrentProof -> None
end (* }}} *)
@@ -1996,7 +2009,7 @@ end = struct (* {{{ *)
1 goals in
TaskQueue.join queue;
let assign_tac : unit Proofview.tactic =
- Proofview.(Goal.nf_enter begin fun g ->
+ Proofview.(Goal.enter begin fun g ->
let gid = Goal.goal g in
let f =
try List.assoc gid res
@@ -2288,7 +2301,7 @@ let known_state ~doc ?(redefine_qed=false) ~cache id =
| `Leaks -> Exninfo.iraise exn
| `ValidBlock { base_state; goals_to_admit; recovery_command } -> begin
let tac =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.enter begin fun gl ->
if CList.mem_f Evar.equal
(Proofview.Goal.goal gl) goals_to_admit then
Proofview.give_up else Proofview.tclUNIT ()
diff --git a/stm/stm.mli b/stm/stm.mli
index 7f70ea18da..1e5ceb7e23 100644
--- a/stm/stm.mli
+++ b/stm/stm.mli
@@ -111,7 +111,8 @@ val add : doc:doc -> ontop:Stateid.t -> ?newtip:Stateid.t ->
doc * Stateid.t * [ `NewTip | `Unfocus of Stateid.t ]
(* Returns the proof state before the last tactic that was applied at or before
-the specified state. Used to compute proof diffs. *)
+the specified state AND that has differences in the underlying proof (i.e.,
+ignoring proofview-only changes). Used to compute proof diffs. *)
val get_prev_proof : doc:doc -> Stateid.t -> Proof.t option
(* [query at ?report_with cmd] Executes [cmd] at a given state [at],
diff --git a/stm/vernac_classifier.ml b/stm/vernac_classifier.ml
index 2170477938..85babd922b 100644
--- a/stm/vernac_classifier.ml
+++ b/stm/vernac_classifier.ml
@@ -168,7 +168,8 @@ let classify_vernac e =
| VernacDeclareModuleType ({v=id},bl,_,_) ->
VtSideff [id], if bl = [] then VtLater else VtNow
(* These commands alter the parser *)
- | VernacOpenCloseScope _ | VernacDelimiters _ | VernacBindScope _
+ | VernacOpenCloseScope _ | VernacDeclareScope _
+ | VernacDelimiters _ | VernacBindScope _
| VernacInfix _ | VernacNotation _ | VernacNotationAddFormat _
| VernacSyntaxExtension _
| VernacSyntacticDefinition _
diff --git a/tactics/auto.ml b/tactics/auto.ml
index d7de6c4fb5..65b2615b6b 100644
--- a/tactics/auto.ml
+++ b/tactics/auto.ml
@@ -416,6 +416,7 @@ and trivial_resolve sigma dbg mod_delta db_list local_db secvars cl =
"nocore" amongst the databases. *)
let trivial ?(debug=Off) lems dbnames =
+ Hints.wrap_hint_warning @@
Proofview.Goal.enter begin fun gl ->
let env = Proofview.Goal.env gl in
let sigma = Tacmach.New.project gl in
@@ -427,6 +428,7 @@ let trivial ?(debug=Off) lems dbnames =
end
let full_trivial ?(debug=Off) lems =
+ Hints.wrap_hint_warning @@
Proofview.Goal.enter begin fun gl ->
let env = Proofview.Goal.env gl in
let sigma = Tacmach.New.project gl in
@@ -501,6 +503,7 @@ let search d n mod_delta db_list local_db =
let default_search_depth = ref 5
let delta_auto debug mod_delta n lems dbnames =
+ Hints.wrap_hint_warning @@
Proofview.Goal.enter begin fun gl ->
let env = Proofview.Goal.env gl in
let sigma = Tacmach.New.project gl in
@@ -524,6 +527,7 @@ let new_auto ?(debug=Off) n = delta_auto debug true n
let default_auto = auto !default_search_depth [] []
let delta_full_auto ?(debug=Off) mod_delta n lems =
+ Hints.wrap_hint_warning @@
Proofview.Goal.enter begin fun gl ->
let env = Proofview.Goal.env gl in
let sigma = Tacmach.New.project gl in
diff --git a/tactics/autorewrite.ml b/tactics/autorewrite.ml
index c8fd0b7a75..8e296de617 100644
--- a/tactics/autorewrite.ml
+++ b/tactics/autorewrite.ml
@@ -162,7 +162,7 @@ let gen_auto_multi_rewrite conds tac_main lbas cl =
| None ->
(* try to rewrite in all hypothesis
(except maybe the rewritten one) *)
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.enter begin fun gl ->
let ids = Tacmach.New.pf_ids_of_hyps gl in
try_do_hyps (fun id -> id) ids
end)
diff --git a/tactics/btermdn.ml b/tactics/btermdn.ml
index aca7f6c65e..bfee0422e7 100644
--- a/tactics/btermdn.ml
+++ b/tactics/btermdn.ml
@@ -28,7 +28,7 @@ type term_label =
| SortLabel
let compare_term_label t1 t2 = match t1, t2 with
-| GRLabel gr1, GRLabel gr2 -> RefOrdered.compare gr1 gr2
+| GRLabel gr1, GRLabel gr2 -> GlobRef.Ordered.compare gr1 gr2
| _ -> Pervasives.compare t1 t2 (** OK *)
type 'res lookup_res = 'res Dn.lookup_res = Label of 'res | Nothing | Everything
diff --git a/tactics/class_tactics.ml b/tactics/class_tactics.ml
index 9c5fdcd1ce..9bd406e14d 100644
--- a/tactics/class_tactics.ml
+++ b/tactics/class_tactics.ml
@@ -416,7 +416,7 @@ and e_my_find_search db_list local_db secvars hdc complete only_classes env sigm
if get_typeclasses_filtered_unification () then
let tac =
matches_pattern concl p <*>
- Proofview.Goal.nf_enter
+ Proofview.Goal.enter
(fun gl -> unify_resolve_refine poly flags gl (c,None,clenv)) in
Tacticals.New.tclTHEN tac Proofview.shelve_unifiable
else
@@ -693,8 +693,9 @@ module Search = struct
let msg =
match fst ie with
| Pretype_errors.PretypeError (env, evd, Pretype_errors.CannotUnify (x,y,_)) ->
- str"Cannot unify " ++ print_constr_env env evd x ++ str" and " ++
- print_constr_env env evd y
+ str"Cannot unify " ++
+ Printer.pr_econstr_env env evd x ++ str" and " ++
+ Printer.pr_econstr_env env evd y
| ReachedLimitEx -> str "Proof-search reached its limit."
| NoApplicableEx -> str "Proof-search failed."
| e -> CErrors.iprint ie
@@ -934,6 +935,9 @@ module Search = struct
| Some i -> str ", with depth limit " ++ int i));
tac
+ let eauto_tac ?st ?unique ~only_classes ?strategy ~depth ~dep hints =
+ Hints.wrap_hint_warning @@ eauto_tac ?st ?unique ~only_classes ?strategy ~depth ~dep hints
+
let run_on_evars env evm p tac =
match evars_to_goals p evm with
| None -> None (* This happens only because there's no evar having p *)
@@ -1143,15 +1147,19 @@ let resolve_typeclass_evars debug depth unique env evd filter split fail =
(initial_select_evars filter) evd split fail
let solve_inst env evd filter unique split fail =
- resolve_typeclass_evars
+ let ((), sigma) = Hints.wrap_hint_warning_fun env evd begin fun evd ->
+ (), resolve_typeclass_evars
(get_typeclasses_debug ())
(get_typeclasses_depth ())
unique env evd filter split fail
+ end in
+ sigma
let _ =
Hook.set Typeclasses.solve_all_instances_hook solve_inst
let resolve_one_typeclass env ?(sigma=Evd.from_env env) gl unique =
+ let (term, sigma) = Hints.wrap_hint_warning_fun env sigma begin fun sigma ->
let nc, gl, subst, _ = Evarutil.push_rel_context_to_named_context env sigma gl in
let (gl,t,sigma) =
Goal.V82.mk_goal sigma nc gl Store.empty in
@@ -1169,7 +1177,9 @@ let resolve_one_typeclass env ?(sigma=Evd.from_env env) gl unique =
let evd = sig_sig gls' in
let t' = mkEvar (ev, Array.of_list subst) in
let term = Evarutil.nf_evar evd t' in
- evd, term
+ term, evd
+ end in
+ (sigma, term)
let _ =
Hook.set Typeclasses.solve_one_instance_hook
@@ -1205,6 +1215,7 @@ let is_ground c =
let autoapply c i =
let open Proofview.Notations in
+ Hints.wrap_hint_warning @@
Proofview.Goal.enter begin fun gl ->
let hintdb = try Hints.searchtable_map i with Not_found ->
CErrors.user_err (Pp.str ("Unknown hint database " ^ i ^ "."))
diff --git a/tactics/dune b/tactics/dune
new file mode 100644
index 0000000000..908dde5253
--- /dev/null
+++ b/tactics/dune
@@ -0,0 +1,6 @@
+(library
+ (name tactics)
+ (synopsis "Coq's Core Tactics [ML implementation]")
+ (public_name coq.tactics)
+ (wrapped false)
+ (libraries printing))
diff --git a/tactics/eauto.ml b/tactics/eauto.ml
index 80d07c5c03..5067315d08 100644
--- a/tactics/eauto.ml
+++ b/tactics/eauto.ml
@@ -409,7 +409,7 @@ let e_search_auto debug (in_depth,p) lems db_list gl =
(* let e_search_auto = CProfile.profile5 e_search_auto_key e_search_auto *)
let eauto_with_bases ?(debug=Off) np lems db_list =
- tclTRY (e_search_auto debug np lems db_list)
+ Proofview.V82.of_tactic (Hints.wrap_hint_warning (Proofview.V82.tactic (tclTRY (e_search_auto debug np lems db_list))))
let eauto ?(debug=Off) np lems dbnames =
let db_list = make_db_list dbnames in
@@ -420,8 +420,8 @@ let full_eauto ?(debug=Off) n lems gl =
tclTRY (e_search_auto debug n lems db_list) gl
let gen_eauto ?(debug=Off) np lems = function
- | None -> Proofview.V82.tactic (full_eauto ~debug np lems)
- | Some l -> Proofview.V82.tactic (eauto ~debug np lems l)
+ | None -> Hints.wrap_hint_warning (Proofview.V82.tactic (full_eauto ~debug np lems))
+ | Some l -> Hints.wrap_hint_warning (Proofview.V82.tactic (eauto ~debug np lems l))
let make_depth = function
| None -> !default_search_depth
diff --git a/tactics/equality.ml b/tactics/equality.ml
index 0e39215701..d0f4b2c680 100644
--- a/tactics/equality.ml
+++ b/tactics/equality.ml
@@ -249,7 +249,7 @@ let rewrite_elim with_evars frzevars cls c e =
let tclNOTSAMEGOAL tac =
let goal gl = Proofview.Goal.goal gl in
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.enter begin fun gl ->
let sigma = project gl in
let ev = goal gl in
tac >>= fun () ->
diff --git a/tactics/hints.ml b/tactics/hints.ml
index 43a450ea71..c0ba363360 100644
--- a/tactics/hints.ml
+++ b/tactics/hints.ml
@@ -288,7 +288,7 @@ let lookup_tacs sigma concl st se =
let sl' = List.stable_sort pri_order_int l' in
List.merge pri_order_int se.sentry_nopat sl'
-module Constr_map = Map.Make(RefOrdered)
+module Constr_map = Map.Make(GlobRef.Ordered)
let is_transparent_gr (ids, csts) = function
| VarRef id -> Id.Pred.mem id ids
@@ -734,8 +734,6 @@ module Hintdbmap = String.Map
type hint_db = Hint_db.t
-type hint_db_table = hint_db Hintdbmap.t ref
-
(** Initially created hint databases, for typeclasses and rewrite *)
let typeclasses_db = "typeclass_instances"
@@ -746,8 +744,8 @@ let auto_init_db =
(Hintdbmap.add rewrite_db (Hint_db.empty cst_full_transparent_state true)
Hintdbmap.empty)
-let searchtable : hint_db_table = ref auto_init_db
-let statustable = ref KNmap.empty
+let searchtable = Summary.ref ~name:"searchtable" auto_init_db
+let statustable = Summary.ref ~name:"statustable" KNmap.empty
let searchtable_map name =
Hintdbmap.find name !searchtable
@@ -762,25 +760,6 @@ let error_no_such_hint_database x =
user_err ~hdr:"Hints" (str "No such Hint database: " ++ str x ++ str ".")
(**************************************************************************)
-(* Definition of the summary *)
-(**************************************************************************)
-
-let hints_init : (unit -> unit) ref = ref (fun () -> ())
-let add_hints_init f =
- let init = !hints_init in
- hints_init := (fun () -> init (); f ())
-
-let init () =
- searchtable := auto_init_db; statustable := KNmap.empty; !hints_init ()
-let freeze _ = (!searchtable, !statustable)
-let unfreeze (fs, st) = searchtable := fs; statustable := st
-
-let _ = Summary.declare_summary "search"
- { Summary.freeze_function = freeze;
- Summary.unfreeze_function = unfreeze;
- Summary.init_function = init }
-
-(**************************************************************************)
(* Auxiliary functions to prepare AUTOHINT objects *)
(**************************************************************************)
@@ -1600,25 +1579,76 @@ let print_mp mp =
let is_imported h = try KNmap.find h.uid !statustable with Not_found -> true
+let hint_trace = Evd.Store.field ()
+
+let log_hint h =
+ let open Proofview.Notations in
+ Proofview.tclEVARMAP >>= fun sigma ->
+ let store = get_extra_data sigma in
+ match Store.get store hint_trace with
+ | None ->
+ (** All calls to hint logging should be well-scoped *)
+ assert false
+ | Some trace ->
+ let trace = KNmap.add h.uid h trace in
+ let store = Store.set store hint_trace trace in
+ Proofview.Unsafe.tclEVARS (set_extra_data store sigma)
+
let warn_non_imported_hint =
CWarnings.create ~name:"non-imported-hint" ~category:"automation"
(fun (hint,mp) ->
strbrk "Hint used but not imported: " ++ hint ++ print_mp mp)
-let warn h x =
- let open Proofview in
- tclBIND tclENV (fun env ->
- tclBIND tclEVARMAP (fun sigma ->
- let hint = pr_hint env sigma h in
- let (mp, _, _) = KerName.repr h.uid in
- warn_non_imported_hint (hint,mp);
- Proofview.tclUNIT x))
+let warn env sigma h =
+ let hint = pr_hint env sigma h in
+ let (mp, _, _) = KerName.repr h.uid in
+ warn_non_imported_hint (hint,mp)
+
+let wrap_hint_warning t =
+ let open Proofview.Notations in
+ Proofview.tclEVARMAP >>= fun sigma ->
+ let store = get_extra_data sigma in
+ let old = Store.get store hint_trace in
+ let store = Store.set store hint_trace KNmap.empty in
+ Proofview.Unsafe.tclEVARS (set_extra_data store sigma) >>= fun () ->
+ t >>= fun ans ->
+ Proofview.tclENV >>= fun env ->
+ Proofview.tclEVARMAP >>= fun sigma ->
+ let store = get_extra_data sigma in
+ let hints = match Store.get store hint_trace with
+ | None -> assert false
+ | Some hints -> hints
+ in
+ let () = KNmap.iter (fun _ h -> warn env sigma h) hints in
+ let store = match old with
+ | None -> Store.remove store hint_trace
+ | Some v -> Store.set store hint_trace v
+ in
+ Proofview.Unsafe.tclEVARS (set_extra_data store sigma) >>= fun () ->
+ Proofview.tclUNIT ans
+
+let wrap_hint_warning_fun env sigma t =
+ let store = get_extra_data sigma in
+ let old = Store.get store hint_trace in
+ let store = Store.set store hint_trace KNmap.empty in
+ let (ans, sigma) = t (set_extra_data store sigma) in
+ let store = get_extra_data sigma in
+ let hints = match Store.get store hint_trace with
+ | None -> assert false
+ | Some hints -> hints
+ in
+ let () = KNmap.iter (fun _ h -> warn env sigma h) hints in
+ let store = match old with
+ | None -> Store.remove store hint_trace
+ | Some v -> Store.set store hint_trace v
+ in
+ (ans, set_extra_data store sigma)
let run_hint tac k = match !warn_hint with
| `LAX -> k tac.obj
| `WARN ->
if is_imported tac then k tac.obj
- else Proofview.tclBIND (k tac.obj) (fun x -> warn tac x)
+ else Proofview.tclTHEN (log_hint tac) (k tac.obj)
| `STRICT ->
if is_imported tac then k tac.obj
else Proofview.tclZERO (UserError (None, (str "Tactic failure.")))
diff --git a/tactics/hints.mli b/tactics/hints.mli
index 9bf6c175a5..d63efea27d 100644
--- a/tactics/hints.mli
+++ b/tactics/hints.mli
@@ -282,6 +282,15 @@ val make_db_list : hint_db_name list -> hint_db list
val typeclasses_db : hint_db_name
val rewrite_db : hint_db_name
+val wrap_hint_warning : 'a Proofview.tactic -> 'a Proofview.tactic
+(** Use around toplevel calls to hint-using tactics, to enable the tracking of
+ non-imported hints. Any tactic calling [run_hint] must be wrapped this
+ way. *)
+
+val wrap_hint_warning_fun : env -> evar_map ->
+ (evar_map -> 'a * evar_map) -> 'a * evar_map
+(** Variant of the above for non-tactics *)
+
(** Printing hints *)
val pr_searchtable : env -> evar_map -> Pp.t
@@ -293,8 +302,5 @@ val pr_hint_db : Hint_db.t -> Pp.t
[@@ocaml.deprecated "please used pr_hint_db_env"]
val pr_hint : env -> evar_map -> hint -> Pp.t
-(** Hook for changing the initialization of auto *)
-val add_hints_init : (unit -> unit) -> unit
-
type nonrec hint_info = hint_info
[@@ocaml.deprecated "Use [Typeclasses.hint_info]"]
diff --git a/tactics/ind_tables.ml b/tactics/ind_tables.ml
index 21520f5d2b..e4013152e6 100644
--- a/tactics/ind_tables.ml
+++ b/tactics/ind_tables.ml
@@ -154,7 +154,7 @@ let define_individual_scheme_base kind suff f mode idopt (mind,i as ind) =
| None -> add_suffix mib.mind_packets.(i).mind_typename suff in
let const = define mode id c (Declareops.inductive_is_polymorphic mib) ctx in
declare_scheme kind [|ind,const|];
- const, Safe_typing.add_private
+ const, Safe_typing.concat_private
(Safe_typing.private_con_of_scheme ~kind (Global.safe_env()) [ind,const]) eff
let define_individual_scheme kind mode names (mind,i as ind) =
@@ -174,7 +174,7 @@ let define_mutual_scheme_base kind suff f mode names mind =
let schemes = Array.mapi (fun i cst -> ((mind,i),cst)) consts in
declare_scheme kind schemes;
consts,
- Safe_typing.add_private
+ Safe_typing.concat_private
(Safe_typing.private_con_of_scheme
~kind (Global.safe_env()) (Array.to_list schemes))
eff
@@ -187,7 +187,7 @@ let define_mutual_scheme kind mode names mind =
let find_scheme_on_env_too kind ind =
let s = String.Map.find kind (Indmap.find ind !scheme_map) in
- s, Safe_typing.add_private
+ s, Safe_typing.concat_private
(Safe_typing.private_con_of_scheme
~kind (Global.safe_env()) [ind, s])
Safe_typing.empty_private_constants
diff --git a/tactics/inv.ml b/tactics/inv.ml
index 43786c8e19..f718b13a63 100644
--- a/tactics/inv.ml
+++ b/tactics/inv.ml
@@ -495,7 +495,7 @@ let raw_inversion inv_kind id status names =
(* Error messages of the inversion tactics *)
let wrap_inv_error id = function (e, info) -> match e with
| Indrec.RecursionSchemeError
- (Indrec.NotAllowedCaseAnalysis (_,(Type _ | Set as k),i)) ->
+ (_, Indrec.NotAllowedCaseAnalysis (_,(Type _ | Set as k),i)) ->
Proofview.tclENV >>= fun env ->
Proofview.tclEVARMAP >>= fun sigma ->
tclZEROMSG (
diff --git a/tactics/tacticals.ml b/tactics/tacticals.ml
index 837865e644..596feeec8b 100644
--- a/tactics/tacticals.ml
+++ b/tactics/tacticals.ml
@@ -655,12 +655,11 @@ module New = struct
| _ ->
let name_elim =
match EConstr.kind sigma elim with
- | Const (kn, _) -> Constant.to_string kn
- | Var id -> Id.to_string id
- | _ -> "\b"
+ | Const _ | Var _ -> str " " ++ Printer.pr_econstr_env (pf_env gl) sigma elim
+ | _ -> mt ()
in
user_err ~hdr:"Tacticals.general_elim_then_using"
- (str "The elimination combinator " ++ str name_elim ++ str " is unknown.")
+ (str "The elimination combinator " ++ name_elim ++ str " is unknown.")
in
let elimclause' = clenv_fchain ~with_univs:false indmv elimclause indclause in
let branchsigns = compute_constructor_signatures ~rec_flag ind in
diff --git a/tactics/tactics.ml b/tactics/tactics.ml
index 2a8ebe08ca..6999b17d8e 100644
--- a/tactics/tactics.ml
+++ b/tactics/tactics.ml
@@ -125,7 +125,7 @@ let unsafe_intro env store decl b =
let ninst = mkRel 1 :: inst in
let nb = subst1 (mkVar (NamedDecl.get_id decl)) b in
let (sigma, ev) = new_evar_instance nctx sigma nb ~principal:true ~store ninst in
- (sigma, mkNamedLambda_or_LetIn decl ev)
+ (sigma, mkLambda_or_LetIn (NamedDecl.to_rel_decl decl) ev)
end
let introduction id =
@@ -2690,6 +2690,34 @@ let mkletin_goal env sigma store with_eq dep (id,lastlhyp,ccl,c) ty =
let (sigma, x) = new_evar newenv sigma ~principal:true ~store ccl in
(sigma, mkNamedLetIn id c t x)
+let pose_tac na c =
+ Proofview.Goal.enter begin fun gl ->
+ let sigma = Proofview.Goal.sigma gl in
+ let env = Proofview.Goal.env gl in
+ let hyps = named_context_val env in
+ let concl = Proofview.Goal.concl gl in
+ let t = typ_of env sigma c in
+ let (sigma, t) = Evarsolve.refresh_universes ~onlyalg:true (Some false) env sigma t in
+ let id = match na with
+ | Name id ->
+ let () = if mem_named_context_val id hyps then
+ user_err (str "Variable " ++ Id.print id ++ str " is already declared.")
+ in
+ id
+ | Anonymous ->
+ let id = id_of_name_using_hdchar env sigma t Anonymous in
+ next_ident_away_in_goal id (ids_of_named_context_val hyps)
+ in
+ Proofview.Unsafe.tclEVARS sigma <*>
+ Refine.refine ~typecheck:false begin fun sigma ->
+ let nhyps = EConstr.push_named_context_val (NamedDecl.LocalDef (id, c, t)) hyps in
+ let (sigma, ev) = Evarutil.new_pure_evar nhyps sigma concl in
+ let inst = Array.map_of_list (fun d -> mkVar (get_id d)) (named_context env) in
+ let body = mkEvar (ev, Array.append [|mkRel 1|] inst) in
+ (sigma, mkLetIn (Name id, c, t, body))
+ end
+ end
+
let letin_tac with_eq id c ty occs =
Proofview.Goal.enter begin fun gl ->
let sigma = Proofview.Goal.sigma gl in
@@ -2796,7 +2824,7 @@ let generalize_goal gl i ((occs,c,b),na as o) (cl,sigma) =
let generalize_dep ?(with_let=false) c =
let open Tacmach.New in
let open Tacticals.New in
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.enter begin fun gl ->
let env = pf_env gl in
let sign = Proofview.Goal.hyps gl in
let sigma = project gl in
@@ -5007,7 +5035,7 @@ let cache_term_by_tactic_then ~opaque ?(goal_type=None) id gk tac tacK =
let evd = Evd.set_universe_context evd ectx in
let open Safe_typing in
let eff = private_con_of_con (Global.safe_env ()) cst in
- let effs = add_private eff
+ let effs = concat_private eff
Entries.(snd (Future.force const.const_entry_body)) in
let solve =
Proofview.tclEFFECTS effs <*>
diff --git a/tactics/tactics.mli b/tactics/tactics.mli
index 57f20d2ff2..c088e404b0 100644
--- a/tactics/tactics.mli
+++ b/tactics/tactics.mli
@@ -390,6 +390,8 @@ val cut : types -> unit Proofview.tactic
(** {6 Tactics for adding local definitions. } *)
+val pose_tac : Name.t -> constr -> unit Proofview.tactic
+
val letin_tac : (bool * intro_pattern_naming) option ->
Name.t -> constr -> types option -> clause -> unit Proofview.tactic
diff --git a/tactics/term_dnet.ml b/tactics/term_dnet.ml
index 8bdcc63215..03d2a17eee 100644
--- a/tactics/term_dnet.ml
+++ b/tactics/term_dnet.ml
@@ -100,7 +100,7 @@ struct
| DRel, _ -> -1 | _, DRel -> 1
| DSort, DSort -> 0
| DSort, _ -> -1 | _, DSort -> 1
- | DRef gr1, DRef gr2 -> RefOrdered.compare gr1 gr2
+ | DRef gr1, DRef gr2 -> GlobRef.Ordered.compare gr1 gr2
| DRef _, _ -> -1 | _, DRef _ -> 1
| DCtx (tl1, tr1), DCtx (tl2, tr2)
diff --git a/test-suite/Makefile b/test-suite/Makefile
index b8aac8b6f8..93ce519350 100644
--- a/test-suite/Makefile
+++ b/test-suite/Makefile
@@ -106,7 +106,8 @@ SUBSYSTEMS := $(VSUBSYSTEMS) misc bugs ide vio coqchk coqwc coq-makefile unit-te
PREREQUISITELOG = prerequisite/admit.v.log \
prerequisite/make_local.v.log prerequisite/make_notation.v.log \
- prerequisite/bind_univs.v.log
+ prerequisite/bind_univs.v.log prerequisite/module_bug8416.v.log \
+ prerequisite/module_bug7192.v.log
#######################################################################
# Phony targets
@@ -126,14 +127,14 @@ clean:
$(SHOW) 'RM <**/*.stamp> <**/*.vo> <**/*.vio> <**/*.log> <**/*.glob>'
$(HIDE)find . \( \
-name '*.stamp' -o -name '*.vo' -o -name '*.vio' -o -name '*.log' -o -name '*.glob' \
- \) -print0 | xargs -0 rm -f
+ \) -exec rm -f {} +
$(SHOW) 'RM <**/*.cmx> <**/*.cmi> <**/*.o> <**/*.test>'
$(HIDE)find unit-tests \( \
-name '*.cmx' -o -name '*.cmi' -o -name '*.o' -o -name '*.test' \
- \) -print0 | xargs -0 rm -f
+ \) -exec rm -f {} +
distclean: clean
$(SHOW) 'RM <**/*.aux>'
- $(HIDE)find . -name '*.aux' -print0 | xargs -0 rm -f
+ $(HIDE)find . -name '*.aux' -exec rm -f {} +
#######################################################################
# Per-subsystem targets
@@ -195,10 +196,7 @@ PRINT_LOGS:=APPVEYOR
endif #APPVEYOR
report: summary.log
- $(HIDE)bash save-logs.sh
- $(HIDE)if [ -n "${TRAVIS}" ]; then find logs/ -name '*.log' -not -name 'summary.log' -exec 'bash' '-c' 'echo "travis_fold:start:coq.logs.$$(echo '{}' | sed s,/,.,g)"' ';' -exec cat '{}' ';' -exec 'bash' '-c' 'echo "travis_fold:end:coq.logs.$$(echo '{}' | sed s,/,.,g)"' ';'; fi
- $(HIDE)if [ -n "${PRINT_LOGS}" ]; then find logs/ -name '*.log' -not -name 'summary.log' -exec 'bash' '-c' 'echo {}' ';' -exec cat '{}' ';' -exec 'bash' '-c' 'echo' ';'; fi
- $(HIDE)if grep -q -F 'Error!' summary.log ; then echo FAILURES; grep -F 'Error!' summary.log; false; else echo NO FAILURES; fi
+ $(HIDE)bash report.sh
#######################################################################
# Regression (and progression) tests
diff --git a/test-suite/bugs/2428.v b/test-suite/bugs/closed/2428.v
index a4f587a58d..b398a76d91 100644
--- a/test-suite/bugs/2428.v
+++ b/test-suite/bugs/closed/2428.v
@@ -5,6 +5,6 @@ Definition myFact := forall x, P x.
Hint Extern 1 (P _) => progress (unfold myFact in *).
Lemma test : (True -> myFact) -> P 3.
-Proof.
+Proof.
intros. debug eauto.
Qed.
diff --git a/test-suite/bugs/closed/2670.v b/test-suite/bugs/closed/2670.v
index c401420e94..791889b24b 100644
--- a/test-suite/bugs/closed/2670.v
+++ b/test-suite/bugs/closed/2670.v
@@ -15,6 +15,14 @@ Proof.
refine (match e return _ with refl_equal => _ end).
reflexivity.
Undo 2.
+ (** Check insensitivity to alphabetic order *)
+ refine (match e as a in _ = b return _ with refl_equal => _ end).
+ reflexivity.
+ Undo 2.
+ (** Check insensitivity to alphabetic order *)
+ refine (match e as z in _ = y return _ with refl_equal => _ end).
+ reflexivity.
+ Undo 2.
(* Next line similarly has a dependent and a non dependent solution *)
refine (match e with refl_equal => _ end).
reflexivity.
diff --git a/test-suite/bugs/closed/4527.v b/test-suite/bugs/closed/4527.v
index 117d6523a8..f8cedfff6e 100644
--- a/test-suite/bugs/closed/4527.v
+++ b/test-suite/bugs/closed/4527.v
@@ -23,7 +23,9 @@ Module Export Datatypes.
Set Implicit Arguments.
Notation nat := Coq.Init.Datatypes.nat.
+Notation O := Coq.Init.Datatypes.O.
Notation S := Coq.Init.Datatypes.S.
+Notation two := (S (S O)).
Record prod (A B : Type) := pair { fst : A ; snd : B }.
@@ -159,7 +161,7 @@ End Adjointify.
(n : nat) {A : Type@{i}} {B : Type@{j}}
(f : A -> B) (C : B -> Type@{k}) : Type@{l}
:= match n with
- | 0 => Unit@{l}
+ | O => Unit@{l}
| S n => (forall (g : forall a, C (f a)),
ExtensionAlong@{i j k l l} f C g) *
forall (h k : forall b, C b),
@@ -220,12 +222,12 @@ Section ORecursion.
Definition O_indpaths {P Q : Type} {Q_inO : In O Q}
(g h : O P -> Q) (p : g o to O P == h o to O P)
: g == h
- := (fst (snd (extendable_to_O O 2) g h) p).1.
+ := (fst (snd (extendable_to_O O two) g h) p).1.
Definition O_indpaths_beta {P Q : Type} {Q_inO : In O Q}
(g h : O P -> Q) (p : g o (to O P) == h o (to O P)) (x : P)
: O_indpaths g h p (to O P x) = p x
- := (fst (snd (extendable_to_O O 2) g h) p).2 x.
+ := (fst (snd (extendable_to_O O two) g h) p).2 x.
End ORecursion.
diff --git a/test-suite/bugs/closed/4533.v b/test-suite/bugs/closed/4533.v
index c3e0da1117..fd2380a070 100644
--- a/test-suite/bugs/closed/4533.v
+++ b/test-suite/bugs/closed/4533.v
@@ -17,7 +17,10 @@ Notation "A -> B" := (forall (_ : A), B) : type_scope.
Module Export Datatypes.
Set Implicit Arguments.
Notation nat := Coq.Init.Datatypes.nat.
+ Notation O := Coq.Init.Datatypes.O.
Notation S := Coq.Init.Datatypes.S.
+ Notation one := (S O).
+ Notation two := (S one).
Record prod (A B : Type) := pair { fst : A ; snd : B }.
Notation "x * y" := (prod x y) : type_scope.
Delimit Scope nat_scope with nat.
@@ -109,7 +112,7 @@ Fixpoint ExtendableAlong@{i j k l}
(n : nat) {A : Type@{i}} {B : Type@{j}}
(f : A -> B) (C : B -> Type@{k}) : Type@{l}
:= match n with
- | 0 => Unit@{l}
+ | O => Unit@{l}
| S n => (forall (g : forall a, C (f a)),
ExtensionAlong@{i j k l l} f C g) *
forall (h k : forall b, C b),
@@ -160,17 +163,17 @@ Module ReflectiveSubuniverses_Theory (Os : ReflectiveSubuniverses).
Definition O_rec {P Q : Type} {Q_inO : In O Q}
(f : P -> Q)
: O P -> Q
- := (fst (extendable_to_O O 1%nat) f).1.
+ := (fst (extendable_to_O O one) f).1.
Definition O_rec_beta {P Q : Type} {Q_inO : In O Q}
(f : P -> Q) (x : P)
: O_rec f (to O P x) = f x
- := (fst (extendable_to_O O 1%nat) f).2 x.
+ := (fst (extendable_to_O O one) f).2 x.
Definition O_indpaths {P Q : Type} {Q_inO : In O Q}
(g h : O P -> Q) (p : g o to O P == h o to O P)
: g == h
- := (fst (snd (extendable_to_O O 2) g h) p).1.
+ := (fst (snd (extendable_to_O O two) g h) p).1.
End ORecursion.
diff --git a/test-suite/bugs/closed/4544.v b/test-suite/bugs/closed/4544.v
index 4ad53bc629..13c47edc8f 100644
--- a/test-suite/bugs/closed/4544.v
+++ b/test-suite/bugs/closed/4544.v
@@ -19,6 +19,7 @@ Inductive sum (A B : Type) : Type :=
| inl : A -> sum A B
| inr : B -> sum A B.
Notation nat := Coq.Init.Datatypes.nat.
+Notation O := Coq.Init.Datatypes.O.
Notation S := Coq.Init.Datatypes.S.
Notation "x + y" := (sum x y) : type_scope.
@@ -449,7 +450,7 @@ Section Extensions.
(n : nat) {A : Type@{i}} {B : Type@{j}}
(f : A -> B) (C : B -> Type@{k}) : Type@{l}
:= match n with
- | 0 => Unit@{l}
+ | O => Unit@{l}
| S n => (forall (g : forall a, C (f a)),
ExtensionAlong@{i j k l l} f C g) *
forall (h k : forall b, C b),
diff --git a/test-suite/bugs/closed/4612.v b/test-suite/bugs/closed/4612.v
new file mode 100644
index 0000000000..ce95f26acc
--- /dev/null
+++ b/test-suite/bugs/closed/4612.v
@@ -0,0 +1,7 @@
+(* While waiting for support, check at least that it does not raise an anomaly *)
+
+Inductive ctype :=
+| Struct: list ctype -> ctype
+| Bot : ctype.
+
+Fail Scheme Equality for ctype.
diff --git a/test-suite/bugs/4623.v b/test-suite/bugs/closed/4623.v
index 7ecfd98b67..7ecfd98b67 100644
--- a/test-suite/bugs/4623.v
+++ b/test-suite/bugs/closed/4623.v
diff --git a/test-suite/bugs/4624.v b/test-suite/bugs/closed/4624.v
index f5ce981cd0..f5ce981cd0 100644
--- a/test-suite/bugs/4624.v
+++ b/test-suite/bugs/closed/4624.v
diff --git a/test-suite/bugs/closed/4717.v b/test-suite/bugs/closed/4717.v
index 1507fa4bf0..bd9bac37ef 100644
--- a/test-suite/bugs/closed/4717.v
+++ b/test-suite/bugs/closed/4717.v
@@ -19,8 +19,6 @@ Proof.
omega.
Qed.
-Require Import ZArith ROmega.
-
Open Scope Z_scope.
Definition Z' := Z.
@@ -32,6 +30,4 @@ Theorem Zle_not_eq_lt : forall n m,
Proof.
intros.
omega.
- Undo.
- romega.
Qed.
diff --git a/test-suite/bugs/closed/4859.v b/test-suite/bugs/closed/4859.v
new file mode 100644
index 0000000000..7be0bedcfc
--- /dev/null
+++ b/test-suite/bugs/closed/4859.v
@@ -0,0 +1,7 @@
+(* Not supported but check at least that it does not raise an anomaly *)
+
+Inductive Fin{n : nat} : Set :=
+| F1{i : nat}{e : n = S i}
+| FS{i : nat}(f : @ Fin i){e : n = S i}.
+
+Fail Scheme Equality for Fin.
diff --git a/test-suite/bugs/7333.v b/test-suite/bugs/closed/7333.v
index fba5b9029d..fba5b9029d 100644
--- a/test-suite/bugs/7333.v
+++ b/test-suite/bugs/closed/7333.v
diff --git a/test-suite/bugs/closed/7754.v b/test-suite/bugs/closed/7754.v
new file mode 100644
index 0000000000..229df93773
--- /dev/null
+++ b/test-suite/bugs/closed/7754.v
@@ -0,0 +1,21 @@
+
+Set Universe Polymorphism.
+
+Module OK.
+
+ Inductive one@{i j} : Type@{i} :=
+ with two : Type@{j} := .
+ Check one@{Set Type} : Set.
+ Fail Check two@{Set Type} : Set.
+
+End OK.
+
+Module Bad.
+
+ Fail Inductive one :=
+ with two@{i +} : Type@{i} := .
+
+ Fail Inductive one@{i +} :=
+ with two@{i +} := .
+
+End Bad.
diff --git a/test-suite/bugs/closed/7795.v b/test-suite/bugs/closed/7795.v
new file mode 100644
index 0000000000..5db0f81cc5
--- /dev/null
+++ b/test-suite/bugs/closed/7795.v
@@ -0,0 +1,65 @@
+
+
+Definition fwd (b: bool) A (e2: A): A. Admitted.
+
+Ltac destruct_refinement_aux T :=
+ let m := fresh "mres" in
+ let r := fresh "r" in
+ let P := fresh "P" in
+ pose T as m;
+ destruct m as [ r P ].
+
+Ltac destruct_refinement :=
+ match goal with
+ | |- context[proj1_sig ?T] => destruct_refinement_aux T
+ end.
+
+Ltac t_base := discriminate || destruct_refinement.
+
+
+Inductive List (T: Type) :=
+| Cons_construct: T -> List T -> List T
+| Nil_construct: List T.
+
+Definition t (T: Type): List T. Admitted.
+Definition size (T: Type) (src: List T): nat. Admitted.
+Definition filter1_rt1_type (T: Type): Type := { res: List T | false = true }.
+Definition filter1 (T: Type): filter1_rt1_type T. Admitted.
+
+Definition hh_1:
+ forall T : Type,
+ (forall (T0 : Type),
+ False -> filter1_rt1_type T0) ->
+ False.
+Admitted.
+
+Definition hh_2:
+ forall (T : Type),
+ filter1_rt1_type T ->
+ filter1_rt1_type T.
+Admitted.
+
+Definition hh:
+ forall (T : Type) (f1 : forall (T0 : Type), False -> filter1_rt1_type T0),
+ fwd
+ (Nat.leb
+ (size T
+ (fwd false (List T)
+ (fwd false (List T)
+ (proj1_sig
+ (hh_2 T
+ (f1 T (hh_1 T f1))))))) 0) bool
+ false = true.
+Admitted.
+
+Set Program Mode. (* removing this line prevents the bug *)
+Obligation Tactic := repeat t_base.
+
+Goal
+ forall T (h17: T),
+ filter1 T =
+ exist
+ _
+ (Nil_construct T)
+ (hh T (fun (T : Type) (_ : False) => filter1 T)).
+Abort.
diff --git a/test-suite/bugs/closed/7867.v b/test-suite/bugs/closed/7867.v
new file mode 100644
index 0000000000..d0c7902756
--- /dev/null
+++ b/test-suite/bugs/closed/7867.v
@@ -0,0 +1,4 @@
+(* Was a printer anomaly due to an internal lambda with no binders *)
+
+Class class := { foo : nat }.
+Fail Instance : class := { foo := 0 ; bar := 0 }.
diff --git a/test-suite/bugs/closed/7900.v b/test-suite/bugs/closed/7900.v
new file mode 100644
index 0000000000..583ef0ef3b
--- /dev/null
+++ b/test-suite/bugs/closed/7900.v
@@ -0,0 +1,53 @@
+Require Import Coq.Program.Program.
+(* Set Universe Polymorphism. *)
+Set Printing Universes.
+
+Axiom ALL : forall {T:Prop}, T.
+
+Inductive Expr : Set := E (a : Expr).
+
+Parameter Value : Set.
+
+Fixpoint eval (e: Expr): Value :=
+ match e with
+ | E a => eval a
+ end.
+
+Class Quote (n: Value) : Set :=
+ { quote: Expr
+ ; eval_quote: eval quote = n }.
+
+Program Definition quote_mult n
+ `{!Quote n} : Quote n :=
+ {| quote := E (quote (n:=n)) |}.
+
+Set Printing Universes.
+Next Obligation.
+Proof.
+ Show Universes.
+ destruct Quote0 as [q eq].
+ Show Universes.
+ rewrite <- eq.
+ clear n eq.
+ Show Universes.
+ apply ALL.
+ Show Universes.
+Qed.
+Print quote_mult_obligation_1.
+(* quote_mult_obligation_1@{} =
+let Top_internal_eq_rew_dep :=
+ fun (A : Type@{Coq.Init.Logic.8}) (x : A) (P : forall a : A, x = a -> Type@{Top.5} (* <- XXX *))
+ (f : P x eq_refl) (y : A) (e : x = y) =>
+ match e as e0 in (_ = y0) return (P y0 e0) with
+ | eq_refl => f
+ end in
+fun (n : Value) (Quote0 : Quote n) =>
+match Quote0 as q return (eval quote = n) with
+| {| quote := q; eval_quote := eq0 |} =>
+ Top_internal_eq_rew_dep Value (eval q) (fun (n0 : Value) (eq1 : eval q = n0) => eval quote = n0)
+ ALL n eq0
+end
+ : forall (n : Value) (Quote0 : Quote n), eval (E quote) = n
+
+quote_mult_obligation_1 is universe polymorphic
+*)
diff --git a/test-suite/bugs/closed/7967.v b/test-suite/bugs/closed/7967.v
new file mode 100644
index 0000000000..2c8855fd54
--- /dev/null
+++ b/test-suite/bugs/closed/7967.v
@@ -0,0 +1,2 @@
+Set Universe Polymorphism.
+Inductive A@{} : Set := B : ltac:(let y := constr:(Type) in exact nat) -> A.
diff --git a/test-suite/bugs/closed/8106.v b/test-suite/bugs/closed/8106.v
new file mode 100644
index 0000000000..a711c5adef
--- /dev/null
+++ b/test-suite/bugs/closed/8106.v
@@ -0,0 +1,4 @@
+(* Was raising an anomaly "already assigned a level" on the second line *)
+
+Notation "c1 ; c2" := (c1 + c2) (only printing, at level 76, right associativity, c1 at level 76, c2 at level 76).
+Notation "c1 ; c2" := (c1 + c2) (only parsing, at level 76, right associativity, c2 at level 76).
diff --git a/test-suite/bugs/closed/8121.v b/test-suite/bugs/closed/8121.v
new file mode 100644
index 0000000000..99267612ca
--- /dev/null
+++ b/test-suite/bugs/closed/8121.v
@@ -0,0 +1,46 @@
+Require Import Coq.Strings.String.
+
+Section T.
+ Eval native_compute in let x := tt in _.
+(* Error: Anomaly "Uncaught exception Constr.DestKO." Please report at http://coq.inria.fr/bugs/. *)
+ Eval native_compute in let _ := Set in _.
+(* Error: Anomaly "Uncaught exception Constr.DestKO." Please report at http://coq.inria.fr/bugs/. *)
+ Eval native_compute in let _ := Prop in _.
+(* Error: Anomaly "Uncaught exception Constr.DestKO." Please report at http://coq.inria.fr/bugs/. *)
+End T.
+
+Section U0.
+ Let n : unit := tt.
+ Eval native_compute in _.
+(* Error: Anomaly "Uncaught exception Constr.DestKO." Please report at http://coq.inria.fr/bugs/. *)
+ Goal exists tt : unit, tt = tt. eexists. native_compute. Abort.
+(* Error: Anomaly "Uncaught exception Constr.DestKO." Please report at http://coq.inria.fr/bugs/. *)
+End U0.
+
+Section S0.
+ Let LF : string := String (Coq.Strings.Ascii.Ascii false true false true false false false false) "".
+ Eval native_compute in _.
+(* Error: Anomaly "Uncaught exception Constr.DestKO." Please report at http://coq.inria.fr/bugs/. *)
+ Goal exists tt : unit, tt = tt. eexists. native_compute. Abort.
+(* Error: Anomaly "Uncaught exception Constr.DestKO." Please report at http://coq.inria.fr/bugs/. *)
+End S0.
+
+Class T := { }.
+Section S1.
+ Context {p : T}.
+ Let LF : string := String (Coq.Strings.Ascii.Ascii false true false true false false false false) "".
+ Eval native_compute in _.
+(* Error: Anomaly "Uncaught exception Not_found." Please report at http://coq.inria.fr/bugs/. *)
+ Goal exists tt : unit, tt = tt. eexists. native_compute. Abort.
+(* Error: Anomaly "Uncaught exception Not_found." Please report at http://coq.inria.fr/bugs/. *)
+End S1.
+
+Class M := { m : Type }.
+Section S2.
+ Context {p : M}.
+ Let LF : string := String (Coq.Strings.Ascii.Ascii false true false true false false false false) "".
+ Eval native_compute in _.
+(* Error: Anomaly "File "pretyping/vnorm.ml", line 60, characters 9-15: Assertion failed." *)
+ Goal exists tt : unit, tt = tt. eexists. native_compute. Abort.
+(* Error: Anomaly "File "pretyping/vnorm.ml", line 60, characters 9-15: Assertion failed." *)
+End S2.
diff --git a/test-suite/bugs/closed/8215.v b/test-suite/bugs/closed/8215.v
new file mode 100644
index 0000000000..c4b29a6354
--- /dev/null
+++ b/test-suite/bugs/closed/8215.v
@@ -0,0 +1,14 @@
+(* Check that instances for local definitions in evars have compatible body *)
+Goal False.
+Proof.
+ pose (n := 1).
+ evar (m:nat).
+ subst n.
+ pose (n := 0).
+ Fail Check ?m. (* n cannot be reinterpreted with a value convertible to 1 *)
+ clearbody n.
+ Fail Check ?m. (* n cannot be reinterpreted with a value convertible to 1 *)
+ clear n.
+ pose (n := 0+1).
+ Check ?m. (* Should be ok *)
+Abort.
diff --git a/test-suite/bugs/closed/8270.v b/test-suite/bugs/closed/8270.v
new file mode 100644
index 0000000000..f36f757f10
--- /dev/null
+++ b/test-suite/bugs/closed/8270.v
@@ -0,0 +1,15 @@
+(* Don't do zeta in cbn when not asked for *)
+
+Goal let x := 0 in
+ let y := x in
+ y = 0.
+ (* We use "cofix" as an example because there are obviously no
+ cofixpoints in sight. This problem arises with any set of
+ reduction flags (not including zeta where the lets are of course reduced away) *)
+ cbn cofix.
+ intro x.
+ unfold x at 1. (* Should succeed *)
+ Undo 2.
+ cbn zeta.
+ Fail unfold x at 1.
+Abort.
diff --git a/test-suite/bugs/closed/8288.v b/test-suite/bugs/closed/8288.v
new file mode 100644
index 0000000000..0350be9c06
--- /dev/null
+++ b/test-suite/bugs/closed/8288.v
@@ -0,0 +1,7 @@
+Set Universe Polymorphism.
+Set Printing Universes.
+
+Set Polymorphic Inductive Cumulativity.
+
+Inductive foo := C : (forall A : Type -> Type, A Type) -> foo.
+(* anomaly invalid subtyping relation *)
diff --git a/test-suite/bugs/closed/8432.v b/test-suite/bugs/closed/8432.v
new file mode 100644
index 0000000000..844ee12668
--- /dev/null
+++ b/test-suite/bugs/closed/8432.v
@@ -0,0 +1,39 @@
+Require Import Program.Tactics.
+
+Obligation Tactic := idtac.
+Set Universe Polymorphism.
+
+Inductive paths {A : Type} (a : A) : A -> Type :=
+ idpath : paths a a.
+
+Inductive Empty : Type :=.
+Inductive Unit : Type := tt.
+Definition not (A : Type) := A -> Empty.
+
+ Lemma nat_path_O_S (n : nat) (H : paths O (S n)) : Empty.
+ Proof. refine (
+ match H in paths _ i return
+ match i with
+ | O => Unit
+ | S _ => Empty
+ end
+ with
+ | idpath _ => tt
+ end
+ ). Defined.
+ Lemma symmetry {A} (x y : A) (p : paths x y) : paths y x.
+ Proof.
+ destruct p. apply idpath.
+ Defined.
+ Lemma nat_path_S_O (n : nat) (H : paths (S n) O) : Empty.
+ Proof. eapply nat_path_O_S. exact (symmetry _ _ H). Defined.
+Set Printing Universes.
+Program Fixpoint succ_not_zero (n:nat) : not (paths (S n) 0) :=
+match n as n return not (paths (S n) 0) with
+| 0 => nat_path_S_O _
+| S n' => let dummy := succ_not_zero n' in _
+end.
+Next Obligation.
+ intros f _ n dummy H. exact (nat_path_S_O _ H).
+ Show Universes.
+Defined.
diff --git a/test-suite/bugs/closed/8478.v b/test-suite/bugs/closed/8478.v
new file mode 100644
index 0000000000..8baaf8686a
--- /dev/null
+++ b/test-suite/bugs/closed/8478.v
@@ -0,0 +1,11 @@
+Set Universe Polymorphism.
+Set Printing Universes.
+Unset Strict Universe Declaration.
+
+Monomorphic Universe v.
+
+Section Foo.
+ Let bar := Type@{u}.
+ Fail Monomorphic Constraint bar.u < v.
+
+End Foo. (* was anomaly undeclared universe due to the constraint *)
diff --git a/test-suite/bugs/closed/8532.v b/test-suite/bugs/closed/8532.v
new file mode 100644
index 0000000000..00aa66e701
--- /dev/null
+++ b/test-suite/bugs/closed/8532.v
@@ -0,0 +1,8 @@
+(* Checking Print Assumptions relatively to a bound module *)
+
+Module Type Typ.
+ Parameter Inline(10) t : Type.
+End Typ.
+Module Terms_mod (SetVars : Typ).
+Print Assumptions SetVars.t.
+End Terms_mod.
diff --git a/test-suite/coq-makefile/timing/after/time-of-build-both.log.desired b/test-suite/coq-makefile/timing/after/time-of-build-both.log.desired
index 56815d241e..72c520218c 100644
--- a/test-suite/coq-makefile/timing/after/time-of-build-both.log.desired
+++ b/test-suite/coq-makefile/timing/after/time-of-build-both.log.desired
@@ -1,6 +1,6 @@
After | File Name | Before || Change | % Change
--------------------------------------------------------
-0m00.38s | Total | 0m00.39s || -0m00.01s | -2.56%
+0m00.34s | Total | 0m00.49s || -0m00.14s | -30.61%
--------------------------------------------------------
-0m00.35s | Slow | 0m00.02s || +0m00.32s | +1649.99%
-0m00.03s | Fast | 0m00.37s || -0m00.34s | -91.89% \ No newline at end of file
+0m00.32s | Fast | 0m00.02s || +0m00.30s | +1500.00%
+0m00.02s | Slow | 0m00.47s || -0m00.44s | -95.74% \ No newline at end of file
diff --git a/test-suite/coq-makefile/timing/per-file-after/A.v.timing.diff.desired b/test-suite/coq-makefile/timing/per-file-after/A.v.timing.diff.desired
index 18f0f34b28..74dad73332 100644
--- a/test-suite/coq-makefile/timing/per-file-after/A.v.timing.diff.desired
+++ b/test-suite/coq-makefile/timing/per-file-after/A.v.timing.diff.desired
@@ -1,9 +1,9 @@
-After | Code | Before || Change | % Change
----------------------------------------------------------------------------------------------------
-0m00.50s | Total | 0m04.17s || -0m03.66s | -87.96%
----------------------------------------------------------------------------------------------------
-0m00.145s | Chars 069 - 162 [Definition~foo0~:=~Eval~comp~i...] | 0m00.192s || -0m00.04s | -24.47%
-0m00.126s | Chars 000 - 026 [Require~Coq.ZArith.BinInt.] | 0m00.143s || -0m00.01s | -11.88%
- N/A | Chars 027 - 068 [Declare~Reduction~comp~:=~nati...] | 0m00.s || +0m00.00s | N/A
-0m00.s | Chars 027 - 068 [Declare~Reduction~comp~:=~vm_c...] | N/A || +0m00.00s | N/A
-0m00.231s | Chars 163 - 208 [Definition~foo1~:=~Eval~comp~i...] | 0m03.836s || -0m03.60s | -93.97% \ No newline at end of file
+After | Code | Before || Change | % Change
+----------------------------------------------------------------------------------------------------
+0m04.35s | Total | 0m00.58s || +0m03.77s | +649.05%
+----------------------------------------------------------------------------------------------------
+0m03.87s | Chars 163 - 208 [Definition~foo1~:=~Eval~comp~i...] | 0m00.246s || +0m03.62s | +1473.17%
+0m00.322s | Chars 069 - 162 [Definition~foo0~:=~Eval~comp~i...] | 0m00.189s || +0m00.13s | +70.37%
+0m00.16s | Chars 000 - 026 [Require~Coq.ZArith.BinInt.] | 0m00.146s || +0m00.01s | +9.58%
+0m00.s | Chars 027 - 068 [Declare~Reduction~comp~:=~nati...] | N/A || +0m00.00s | N/A
+ N/A | Chars 027 - 068 [Declare~Reduction~comp~:=~vm_c...] | 0m00.s || +0m00.00s | N/A \ No newline at end of file
diff --git a/test-suite/coq-makefile/timing/run.sh b/test-suite/coq-makefile/timing/run.sh
index 6737197ee4..78a3f7c63a 100755
--- a/test-suite/coq-makefile/timing/run.sh
+++ b/test-suite/coq-makefile/timing/run.sh
@@ -5,6 +5,10 @@ set -e
. ../template/path-init.sh
+# reset MAKEFLAGS so that, e.g., `make -C test-suite -B coq-makefile` doesn't give us issues
+
+MAKEFLAGS=
+
cd precomputed-time-tests
./run.sh || exit $?
diff --git a/test-suite/interactive/PrimNotation.v b/test-suite/interactive/PrimNotation.v
new file mode 100644
index 0000000000..07986b0df3
--- /dev/null
+++ b/test-suite/interactive/PrimNotation.v
@@ -0,0 +1,64 @@
+(* Until recently, the Notation.declare_numeral_notation wasn't synchronized
+ w.r.t. backtracking. This should be ok now.
+ This test is pretty artificial (we must declare Z_scope for this to work).
+*)
+
+Delimit Scope Z_scope with Z.
+Open Scope Z_scope.
+Check let v := 0 in v : nat.
+(* let v := 0 in v : nat : nat *)
+Require BinInt.
+Check let v := 0 in v : BinNums.Z.
+(* let v := 0 in v : BinNums.Z : BinNums.Z *)
+Back 2.
+Check let v := 0 in v : nat.
+(* Expected answer: let v := 0 in v : nat : nat *)
+(* Used to fail with:
+Error: Cannot interpret in Z_scope without requiring first module BinNums.
+*)
+
+Local Set Universe Polymorphism.
+Delimit Scope punit_scope with punit.
+Delimit Scope pcunit_scope with pcunit.
+Delimit Scope int_scope with int.
+Numeral Notation Decimal.int Decimal.int_of_int Decimal.int_of_int : int_scope.
+Module A.
+ NonCumulative Inductive punit@{u} : Type@{u} := ptt.
+ Cumulative Inductive pcunit@{u} : Type@{u} := pctt.
+ Definition to_punit : Decimal.int -> option punit
+ := fun v => match v with 0%int => Some ptt | _ => None end.
+ Definition to_pcunit : Decimal.int -> option pcunit
+ := fun v => match v with 0%int => Some pctt | _ => None end.
+ Definition of_punit : punit -> Decimal.uint := fun _ => Nat.to_uint 0.
+ Definition of_pcunit : pcunit -> Decimal.uint := fun _ => Nat.to_uint 0.
+ Numeral Notation punit to_punit of_punit : punit_scope.
+ Check let v := 0%punit in v : punit.
+ Back 2.
+ Numeral Notation pcunit to_pcunit of_pcunit : punit_scope.
+ Check let v := 0%punit in v : pcunit.
+End A.
+Reset A.
+Local Unset Universe Polymorphism.
+Module A.
+ Inductive punit : Set := ptt.
+ Definition to_punit : Decimal.int -> option punit
+ := fun v => match v with 0%int => Some ptt | _ => None end.
+ Definition of_punit : punit -> Decimal.uint := fun _ => Nat.to_uint 0.
+ Numeral Notation punit to_punit of_punit : punit_scope.
+ Check let v := 0%punit in v : punit.
+End A.
+Local Set Universe Polymorphism.
+Inductive punit@{u} : Type@{u} := ptt.
+Definition to_punit : Decimal.int -> option punit
+ := fun v => match v with 0%int => Some ptt | _ => None end.
+Definition of_punit : punit -> Decimal.uint := fun _ => Nat.to_uint 0.
+Numeral Notation punit to_punit of_punit : punit_scope.
+Check let v := 0%punit in v : punit.
+Back 6. (* check backtracking of registering universe polymorphic constants *)
+Local Unset Universe Polymorphism.
+Inductive punit : Set := ptt.
+Definition to_punit : Decimal.int -> option punit
+ := fun v => match v with 0%int => Some ptt | _ => None end.
+Definition of_punit : punit -> Decimal.uint := fun _ => Nat.to_uint 0.
+Numeral Notation punit to_punit of_punit : punit_scope.
+Check let v := 0%punit in v : punit.
diff --git a/test-suite/misc/poly-capture-global-univs.sh b/test-suite/misc/poly-capture-global-univs.sh
new file mode 100755
index 0000000000..e066ac039b
--- /dev/null
+++ b/test-suite/misc/poly-capture-global-univs.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+
+set -e
+
+export COQBIN=$BIN
+export PATH=$COQBIN:$PATH
+
+cd misc/poly-capture-global-univs/
+
+coq_makefile -f _CoqProject -o Makefile
+
+make clean
+
+make src/evil_plugin.cmxs
+
+if make; then
+ >&2 echo 'Should have failed!'
+ exit 1
+fi
diff --git a/test-suite/misc/poly-capture-global-univs/.gitignore b/test-suite/misc/poly-capture-global-univs/.gitignore
new file mode 100644
index 0000000000..f5a6d22b8e
--- /dev/null
+++ b/test-suite/misc/poly-capture-global-univs/.gitignore
@@ -0,0 +1 @@
+/Makefile*
diff --git a/test-suite/misc/poly-capture-global-univs/_CoqProject b/test-suite/misc/poly-capture-global-univs/_CoqProject
new file mode 100644
index 0000000000..70ec246062
--- /dev/null
+++ b/test-suite/misc/poly-capture-global-univs/_CoqProject
@@ -0,0 +1,9 @@
+-Q theories Evil
+-I src
+
+src/evil.ml4
+src/evilImpl.ml
+src/evilImpl.mli
+src/evil_plugin.mlpack
+theories/evil.v
+
diff --git a/test-suite/misc/poly-capture-global-univs/src/evil.ml4 b/test-suite/misc/poly-capture-global-univs/src/evil.ml4
new file mode 100644
index 0000000000..565e979aaa
--- /dev/null
+++ b/test-suite/misc/poly-capture-global-univs/src/evil.ml4
@@ -0,0 +1,9 @@
+
+open Stdarg
+open EvilImpl
+
+DECLARE PLUGIN "evil_plugin"
+
+VERNAC COMMAND FUNCTIONAL EXTEND VernacEvil CLASSIFIED AS SIDEFF
+| [ "Evil" ident(x) ident(y) ] -> [ fun ~atts ~st -> evil x y; st ]
+END
diff --git a/test-suite/misc/poly-capture-global-univs/src/evilImpl.ml b/test-suite/misc/poly-capture-global-univs/src/evilImpl.ml
new file mode 100644
index 0000000000..6d8ce7c5d7
--- /dev/null
+++ b/test-suite/misc/poly-capture-global-univs/src/evilImpl.ml
@@ -0,0 +1,22 @@
+open Names
+
+let evil t f =
+ let open Univ in
+ let open Entries in
+ let open Decl_kinds in
+ let open Constr in
+ let k = IsDefinition Definition in
+ let u = Level.var 0 in
+ let tu = mkType (Universe.make u) in
+ let te = Declare.definition_entry
+ ~univs:(Monomorphic_const_entry (ContextSet.singleton u)) tu
+ in
+ let tc = Declare.declare_constant t (DefinitionEntry te, k) in
+ let tc = mkConst tc in
+
+ let fe = Declare.definition_entry
+ ~univs:(Polymorphic_const_entry (UContext.make (Instance.of_array [|u|],Constraint.empty)))
+ ~types:(Term.mkArrow tc tu)
+ (mkLambda (Name.Name (Id.of_string "x"), tc, mkRel 1))
+ in
+ ignore (Declare.declare_constant f (DefinitionEntry fe, k))
diff --git a/test-suite/misc/poly-capture-global-univs/src/evilImpl.mli b/test-suite/misc/poly-capture-global-univs/src/evilImpl.mli
new file mode 100644
index 0000000000..97c7e3dadd
--- /dev/null
+++ b/test-suite/misc/poly-capture-global-univs/src/evilImpl.mli
@@ -0,0 +1,2 @@
+
+val evil : Names.Id.t -> Names.Id.t -> unit
diff --git a/test-suite/misc/poly-capture-global-univs/src/evil_plugin.mlpack b/test-suite/misc/poly-capture-global-univs/src/evil_plugin.mlpack
new file mode 100644
index 0000000000..0093328a40
--- /dev/null
+++ b/test-suite/misc/poly-capture-global-univs/src/evil_plugin.mlpack
@@ -0,0 +1,2 @@
+EvilImpl
+Evil
diff --git a/test-suite/misc/poly-capture-global-univs/theories/evil.v b/test-suite/misc/poly-capture-global-univs/theories/evil.v
new file mode 100644
index 0000000000..7fd98c2773
--- /dev/null
+++ b/test-suite/misc/poly-capture-global-univs/theories/evil.v
@@ -0,0 +1,13 @@
+
+Declare ML Module "evil_plugin".
+
+Evil T f. (* <- if this doesn't fail then the rest goes through *)
+
+Definition g : Type -> Set := f.
+
+Require Import Hurkens.
+
+Lemma absurd : False.
+Proof.
+ exact (TypeNeqSmallType.paradox (g Type) eq_refl).
+Qed.
diff --git a/test-suite/output/Arguments.v b/test-suite/output/Arguments.v
index bd9240476f..b67ac4f0df 100644
--- a/test-suite/output/Arguments.v
+++ b/test-suite/output/Arguments.v
@@ -10,6 +10,8 @@ Arguments Nat.sub !n !m.
About Nat.sub.
Definition pf (D1 C1 : Type) (f : D1 -> C1) (D2 C2 : Type) (g : D2 -> C2) :=
fun x => (f (fst x), g (snd x)).
+Declare Scope foo_scope.
+Declare Scope bar_scope.
Delimit Scope foo_scope with F.
Arguments pf {D1%F C1%type} f [D2 C2] g x : simpl never.
About pf.
diff --git a/test-suite/output/Cases.out b/test-suite/output/Cases.out
index dfab400baa..cb835ab48d 100644
--- a/test-suite/output/Cases.out
+++ b/test-suite/output/Cases.out
@@ -64,14 +64,9 @@ In environment
texpDenote : forall t : type, texp t -> typeDenote t
t : type
e : texp t
-t1 : type
-t2 : type
-t0 : type
-b : tbinop t1 t2 t0
-e1 : texp t1
-e2 : texp t2
-The term "0" has type "nat" while it is expected to have type
- "typeDenote t0".
+n : nat
+The term "n" has type "nat" while it is expected to have type
+ "typeDenote ?t@{t1:=Nat}".
fun '{{n, m, _}} => n + m
: J -> nat
fun '{{n, m, p}} => n + m + p
diff --git a/test-suite/output/Notations.out b/test-suite/output/Notations.out
index b60b1ee863..94b86fc222 100644
--- a/test-suite/output/Notations.out
+++ b/test-suite/output/Notations.out
@@ -125,13 +125,15 @@ s
: nat
fun _ : nat => 9
: nat -> nat
-fun (x : nat) (p : x = x) => match p with
- | ONE => ONE
- end = p
+fun (x : nat) (p : x = x) =>
+match p in (_ = n) return (n = n) with
+| ONE => ONE
+end = p
: forall x : nat, x = x -> Prop
-fun (x : nat) (p : x = x) => match p with
- | 1 => 1
- end = p
+fun (x : nat) (p : x = x) =>
+match p in (_ = n) return (n = n) with
+| 1 => 1
+end = p
: forall x : nat, x = x -> Prop
bar 0
: nat
diff --git a/test-suite/output/Notations.v b/test-suite/output/Notations.v
index fe6c05c39e..adab324cf0 100644
--- a/test-suite/output/Notations.v
+++ b/test-suite/output/Notations.v
@@ -76,6 +76,7 @@ Open Scope nat_scope.
Inductive znat : Set := Zpos (n : nat) | Zneg (m : nat).
Coercion Zpos: nat >-> znat.
+Declare Scope znat_scope.
Delimit Scope znat_scope with znat.
Open Scope znat_scope.
diff --git a/test-suite/output/PrintAssumptions.out b/test-suite/output/PrintAssumptions.out
index 34f44cd246..3f4d5ef58c 100644
--- a/test-suite/output/PrintAssumptions.out
+++ b/test-suite/output/PrintAssumptions.out
@@ -20,3 +20,5 @@ Axioms:
M.foo : False
Closed under the global context
Closed under the global context
+Closed under the global context
+Closed under the global context
diff --git a/test-suite/output/PrintAssumptions.v b/test-suite/output/PrintAssumptions.v
index ea1ab63786..3d4dfe603d 100644
--- a/test-suite/output/PrintAssumptions.v
+++ b/test-suite/output/PrintAssumptions.v
@@ -137,3 +137,13 @@ Module F (X : T).
End F.
End SUBMODULES.
+
+(* Testing a variant of #7192 across files *)
+(* This was missing in the original fix to #7192 *)
+Require Import module_bug7192.
+Print Assumptions M7192.D.f.
+
+(* Testing reporting assumptions from modules in files *)
+(* A regression introduced in the original fix to #7192 was missing implementations *)
+Require Import module_bug8416.
+Print Assumptions M8416.f.
diff --git a/test-suite/output/Quote.v b/test-suite/output/Quote.v
deleted file mode 100644
index 2c373d5052..0000000000
--- a/test-suite/output/Quote.v
+++ /dev/null
@@ -1,36 +0,0 @@
-Require Import Quote.
-
-Parameter A B : Prop.
-
-Inductive formula : Type :=
- | f_and : formula -> formula -> formula
- | f_or : formula -> formula -> formula
- | f_not : formula -> formula
- | f_true : formula
- | f_atom : index -> formula
- | f_const : Prop -> formula.
-
-Fixpoint interp_f (vm:
- varmap Prop) (f:formula) {struct f} : Prop :=
- match f with
- | f_and f1 f2 => interp_f vm f1 /\ interp_f vm f2
- | f_or f1 f2 => interp_f vm f1 \/ interp_f vm f2
- | f_not f1 => ~ interp_f vm f1
- | f_true => True
- | f_atom i => varmap_find True i vm
- | f_const c => c
- end.
-
-Goal A \/ B -> A /\ (B \/ A) /\ (A \/ ~ B).
-intro H.
-match goal with
- | H : ?a \/ ?b |- _ => quote interp_f in a using (fun x => idtac x; change (x \/ b) in H)
-end.
-match goal with
- |- ?g => quote interp_f [ A ] in g using (fun x => idtac x)
-end.
-quote interp_f.
-Show.
-simpl; quote interp_f [ A ].
-Show.
-Admitted.
diff --git a/test-suite/output/UnivBinders.out b/test-suite/output/UnivBinders.out
index 6f41b2fcf9..f8f11d7cf6 100644
--- a/test-suite/output/UnivBinders.out
+++ b/test-suite/output/UnivBinders.out
@@ -48,6 +48,12 @@ Type@{Top.17} -> Type@{v} -> Type@{u}
(* u Top.17 v |= *)
foo is universe polymorphic
+Type@{i} -> Type@{j}
+ : Type@{max(i+1,j+1)}
+(* {j i} |= *)
+ = Type@{i} -> Type@{j}
+ : Type@{max(i+1,j+1)}
+(* {j i} |= *)
Monomorphic mono = Type@{mono.u}
: Type@{mono.u+1}
(* {mono.u} |= *)
@@ -80,10 +86,10 @@ Type@{M} -> Type@{N} -> Type@{E}
(* E M N |= *)
foo is universe polymorphic
-foo@{Top.16 Top.17 Top.18} =
-Type@{Top.17} -> Type@{Top.18} -> Type@{Top.16}
- : Type@{max(Top.16+1,Top.17+1,Top.18+1)}
-(* Top.16 Top.17 Top.18 |= *)
+foo@{u Top.17 v} =
+Type@{Top.17} -> Type@{v} -> Type@{u}
+ : Type@{max(u+1,Top.17+1,v+1)}
+(* u Top.17 v |= *)
foo is universe polymorphic
NonCumulative Inductive Empty@{E} : Type@{E} :=
@@ -123,11 +129,19 @@ insec@{v} = Type@{u} -> Type@{v}
(* v |= *)
insec is universe polymorphic
+NonCumulative Inductive insecind@{k} : Type@{k+1} :=
+ inseccstr : Type@{k} -> insecind@{k}
+
+For inseccstr: Argument scope is [type_scope]
insec@{u v} = Type@{u} -> Type@{v}
: Type@{max(u+1,v+1)}
(* u v |= *)
insec is universe polymorphic
+NonCumulative Inductive insecind@{u k} : Type@{k+1} :=
+ inseccstr : Type@{k} -> insecind@{u k}
+
+For inseccstr: Argument scope is [type_scope]
inmod@{u} = Type@{u}
: Type@{u+1}
(* u |= *)
@@ -149,24 +163,24 @@ inmod@{u} -> Type@{v}
(* u v |= *)
Applied.infunct is universe polymorphic
-axfoo@{i Top.44 Top.45} : Type@{Top.44} -> Type@{i}
-(* i Top.44 Top.45 |= *)
+axfoo@{i Top.55 Top.56} : Type@{Top.55} -> Type@{i}
+(* i Top.55 Top.56 |= *)
axfoo is universe polymorphic
Argument scope is [type_scope]
Expands to: Constant Top.axfoo
-axbar@{i Top.44 Top.45} : Type@{Top.45} -> Type@{i}
-(* i Top.44 Top.45 |= *)
+axbar@{i Top.55 Top.56} : Type@{Top.56} -> Type@{i}
+(* i Top.55 Top.56 |= *)
axbar is universe polymorphic
Argument scope is [type_scope]
Expands to: Constant Top.axbar
-axfoo' : Type@{Top.47} -> Type@{axbar'.i}
+axfoo' : Type@{Top.58} -> Type@{axbar'.i}
axfoo' is not universe polymorphic
Argument scope is [type_scope]
Expands to: Constant Top.axfoo'
-axbar' : Type@{Top.47} -> Type@{axbar'.i}
+axbar' : Type@{Top.58} -> Type@{axbar'.i}
axbar' is not universe polymorphic
Argument scope is [type_scope]
diff --git a/test-suite/output/UnivBinders.v b/test-suite/output/UnivBinders.v
index c6efc240a6..9aebce1b9a 100644
--- a/test-suite/output/UnivBinders.v
+++ b/test-suite/output/UnivBinders.v
@@ -30,6 +30,11 @@ Unset Strict Universe Declaration.
order of appearance. *)
Definition foo@{u +} := Type -> Type@{v} -> Type@{u}.
Print foo.
+
+Check Type@{i} -> Type@{j}.
+
+Eval cbv in Type@{i} -> Type@{j}.
+
Set Strict Universe Declaration.
(* Binders even work with monomorphic definitions! *)
@@ -117,8 +122,12 @@ Section SomeSec.
Universe u.
Definition insec@{v} := Type@{u} -> Type@{v}.
Print insec.
+
+ Inductive insecind@{k} := inseccstr : Type@{k} -> insecind.
+ Print insecind.
End SomeSec.
Print insec.
+Print insecind.
Module SomeMod.
Definition inmod@{u} := Type@{u}.
diff --git a/test-suite/output/ltac.out b/test-suite/output/ltac.out
index eb9f571022..efdc94fb1e 100644
--- a/test-suite/output/ltac.out
+++ b/test-suite/output/ltac.out
@@ -38,3 +38,14 @@ Ltac foo :=
let w := () in
let z := 1 in
pose v
+2 subgoals
+
+ n : nat
+ ============================
+ (fix a (n0 : nat) : nat := match n0 with
+ | 0 => 0
+ | S n1 => a n1
+ end) n = n
+
+subgoal 2 is:
+ forall a : nat, a = 0
diff --git a/test-suite/output/ltac.v b/test-suite/output/ltac.v
index 901b1e3aa6..40e743c3f0 100644
--- a/test-suite/output/ltac.v
+++ b/test-suite/output/ltac.v
@@ -71,3 +71,13 @@ Ltac foo :=
let z := 1 in
pose v.
Print Ltac foo.
+
+(* Ltac renaming was not applied to "fix" and "cofix" *)
+
+Goal forall a, a = 0.
+match goal with
+|- (forall x, x = _) => assert (forall n, (fix x n := match n with O => O | S n => x n end) n = n)
+end.
+intro.
+Show.
+Abort.
diff --git a/test-suite/output/ltac_missing_args.out b/test-suite/output/ltac_missing_args.out
index 7326f137c2..8a00cd3fe5 100644
--- a/test-suite/output/ltac_missing_args.out
+++ b/test-suite/output/ltac_missing_args.out
@@ -1,25 +1,25 @@
The command has indeed failed with message:
-The user-defined tactic "Top.foo" was not fully applied:
+The user-defined tactic "foo" was not fully applied:
There is a missing argument for variable x,
no arguments at all were provided.
The command has indeed failed with message:
-The user-defined tactic "Top.bar" was not fully applied:
+The user-defined tactic "bar" was not fully applied:
There is a missing argument for variable x,
no arguments at all were provided.
The command has indeed failed with message:
-The user-defined tactic "Top.bar" was not fully applied:
+The user-defined tactic "bar" was not fully applied:
There are missing arguments for variables y and _,
an argument was provided for variable x.
The command has indeed failed with message:
-The user-defined tactic "Top.baz" was not fully applied:
+The user-defined tactic "baz" was not fully applied:
There is a missing argument for variable x,
no arguments at all were provided.
The command has indeed failed with message:
-The user-defined tactic "Top.qux" was not fully applied:
+The user-defined tactic "qux" was not fully applied:
There is a missing argument for variable x,
no arguments at all were provided.
The command has indeed failed with message:
-The user-defined tactic "Top.mydo" was not fully applied:
+The user-defined tactic "mydo" was not fully applied:
There is a missing argument for variable _,
no arguments at all were provided.
The command has indeed failed with message:
@@ -31,7 +31,7 @@ An unnamed user-defined tactic was not fully applied:
There is a missing argument for variable _,
no arguments at all were provided.
The command has indeed failed with message:
-The user-defined tactic "Top.rec" was not fully applied:
+The user-defined tactic "rec" was not fully applied:
There is a missing argument for variable x,
no arguments at all were provided.
The command has indeed failed with message:
diff --git a/test-suite/prerequisite/module_bug7192.v b/test-suite/prerequisite/module_bug7192.v
new file mode 100644
index 0000000000..82cfe560af
--- /dev/null
+++ b/test-suite/prerequisite/module_bug7192.v
@@ -0,0 +1,9 @@
+(* Variant of #7192 to be tested in a file requiring this file *)
+(* #7192 is about Print Assumptions not entering implementation of submodules *)
+
+Definition a := True.
+Module Type B. Axiom f : Prop. End B.
+Module Type C. Declare Module D : B. End C.
+Module M7192: C.
+ Module D <: B. Definition f := a. End D.
+End M7192.
diff --git a/test-suite/prerequisite/module_bug8416.v b/test-suite/prerequisite/module_bug8416.v
new file mode 100644
index 0000000000..70f43d132a
--- /dev/null
+++ b/test-suite/prerequisite/module_bug8416.v
@@ -0,0 +1,2 @@
+Module Type A. Axiom f : True. End A.
+Module M8416 : A. Definition f := I. End M8416.
diff --git a/test-suite/report.sh b/test-suite/report.sh
new file mode 100755
index 0000000000..05f39b4b02
--- /dev/null
+++ b/test-suite/report.sh
@@ -0,0 +1,55 @@
+#!/usr/bin/env bash
+
+# save failed logs to logs/, then print failure information
+# returns failure code if any failed logs exist
+
+# save step
+
+SAVEDIR="logs"
+
+# reset for local builds
+rm -rf "$SAVEDIR"
+mkdir "$SAVEDIR"
+
+# keep this synced with test-suite/Makefile
+FAILMARK="==========> FAILURE <=========="
+
+FAILED=$(mktemp /tmp/coq-check-XXXXXX)
+find . '(' -path ./bugs/opened -prune ')' -o '(' -name '*.log' -exec grep "$FAILMARK" -q '{}' ';' -print0 ')' > "$FAILED"
+
+rsync -a --from0 --files-from="$FAILED" . "$SAVEDIR"
+cp summary.log "$SAVEDIR"/
+
+# cleanup
+rm "$FAILED"
+
+# print info
+if [ -n "$TRAVIS" ] || [ -n "$PRINT_LOGS" ]; then
+ find logs/ -name '*.log' -not -name 'summary.log' -print0 | while IFS= read -r -d '' file; do
+ if [ -n "$TRAVIS" ]; then
+ # ${foo////.} replaces every / by . in $foo
+ printf 'travis_fold:start:coq.logs.%s\n' "${file////.}";
+ else printf '%s\n' "$file"
+ fi
+
+ cat "$file"
+
+ if [ -n "$TRAVIS" ]; then
+ # ${foo////.} replaces every / by . in $foo
+ printf 'travis_fold:end:coq.logs.%s\n' "${file////.}";
+ else printf '\n'
+ fi
+ done
+fi
+
+if grep -q -F 'Error!' summary.log ; then
+ echo FAILURES;
+ grep -F 'Error!' summary.log;
+ if [ -z "$TRAVIS" ] && [ -z "$PRINT_LOGS" ]; then
+ echo 'To print details of failed tests, rerun with environment variable PRINT_LOGS=1'
+ echo 'eg "make report PRINT_LOGS=1" from the test suite directory"'
+ echo 'See README.md in the test suite directory for more information.'
+ fi
+ false
+else echo NO FAILURES;
+fi
diff --git a/test-suite/save-logs.sh b/test-suite/save-logs.sh
deleted file mode 100755
index 9b8fff09f8..0000000000
--- a/test-suite/save-logs.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env bash
-
-SAVEDIR="logs"
-
-# reset for local builds
-rm -rf "$SAVEDIR"
-mkdir "$SAVEDIR"
-
-# keep this synced with test-suite/Makefile
-FAILMARK="==========> FAILURE <=========="
-
-FAILED=$(mktemp /tmp/coq-check-XXXXXX)
-find . '(' -path ./bugs/opened -prune ')' -o '(' -name '*.log' -exec grep "$FAILMARK" -q '{}' ';' -print0 ')' > "$FAILED"
-
-rsync -a --from0 --files-from="$FAILED" . "$SAVEDIR"
-cp summary.log "$SAVEDIR"/
-
-# cleanup
-rm "$FAILED"
diff --git a/test-suite/success/ssr_delayed_clear_rename.v b/test-suite/ssr/delayed_clear_rename.v
index 951e5aff79..951e5aff79 100644
--- a/test-suite/success/ssr_delayed_clear_rename.v
+++ b/test-suite/ssr/delayed_clear_rename.v
diff --git a/test-suite/ssr/ssr_rew_illtyped.v b/test-suite/ssr/rewrite_illtyped.v
index 7358068c8d..7358068c8d 100644
--- a/test-suite/ssr/ssr_rew_illtyped.v
+++ b/test-suite/ssr/rewrite_illtyped.v
diff --git a/test-suite/ssr/ssrpattern.v b/test-suite/ssr/ssrpattern.v
new file mode 100644
index 0000000000..422bb95fdf
--- /dev/null
+++ b/test-suite/ssr/ssrpattern.v
@@ -0,0 +1,7 @@
+Require Import ssrmatching.
+
+Goal forall n, match n with 0 => 0 | _ => 0 end = 0.
+Proof.
+ intro n.
+ ssrpattern (match _ with 0 => _ | S n' => _ end).
+Abort.
diff --git a/test-suite/success/BracketsWithGoalSelector.v b/test-suite/success/BracketsWithGoalSelector.v
index ed035f5213..2f7425bce6 100644
--- a/test-suite/success/BracketsWithGoalSelector.v
+++ b/test-suite/success/BracketsWithGoalSelector.v
@@ -14,3 +14,12 @@ Proof.
Fail Qed.
}
Qed.
+
+Lemma foo (n: nat) (P : nat -> Prop):
+ P n.
+Proof.
+ intros.
+ refine (nat_ind _ ?[Base] ?[Step] _).
+ [Base]: { admit. }
+ [Step]: { admit. }
+Abort.
diff --git a/test-suite/success/Case13.v b/test-suite/success/Case13.v
index 8f95484cfd..356a67efec 100644
--- a/test-suite/success/Case13.v
+++ b/test-suite/success/Case13.v
@@ -87,3 +87,41 @@ Check fun (x : E) => match x with c => e c end.
Inductive C' : bool -> Set := c' : C' true.
Inductive E' (b : bool) : Set := e' :> C' b -> E' b.
Check fun (x : E' true) => match x with c' => e' true c' end.
+
+(* Check use of the no-dependency strategy when a type constraint is
+ given (and when the "inversion-and-dependencies-as-evars" strategy
+ is not strong enough because of a constructor with a type whose
+ pattern structure is not refined enough for it to be captured by
+ the inversion predicate) *)
+
+Inductive K : bool -> bool -> Type := F : K true true | G x : K x x.
+
+Check fun z P Q (y:K true z) (H1 H2:P y) (f:forall y, P y -> Q y z) =>
+ match y with
+ | F => f y H1
+ | G _ => f y H2
+ end : Q y z.
+
+(* Check use of the maximal-dependency-in-variable strategy even when
+ no explicit type constraint is given (and when the
+ "inversion-and-dependencies-as-evars" strategy is not strong enough
+ because of a constructor with a type whose pattern structure is not
+ refined enough for it to be captured by the inversion predicate) *)
+
+Check fun z P Q (y:K true z) (H1 H2:P y) (f:forall y z, P y -> Q y z) =>
+ match y with
+ | F => f y true H1
+ | G b => f y b H2
+ end.
+
+(* Check use of the maximal-dependency-in-variable strategy for "Var"
+ variables *)
+
+Goal forall z P Q (y:K true z) (H1 H2:P y) (f:forall y z, P y -> Q y z), Q y z.
+intros z P Q y H1 H2 f.
+Show.
+refine (match y with
+ | F => f y true H1
+ | G b => f y b H2
+ end).
+Qed.
diff --git a/test-suite/success/CombinedScheme.v b/test-suite/success/CombinedScheme.v
new file mode 100644
index 0000000000..d6ca7a299f
--- /dev/null
+++ b/test-suite/success/CombinedScheme.v
@@ -0,0 +1,35 @@
+Inductive even (x : bool) : nat -> Type :=
+| evenO : even x 0
+| evenS : forall n, odd x n -> even x (S n)
+with odd (x : bool) : nat -> Type :=
+| oddS : forall n, even x n -> odd x (S n).
+
+Scheme even_ind_prop := Induction for even Sort Prop
+with odd_ind_prop := Induction for odd Sort Prop.
+
+Combined Scheme even_cprop from even_ind_prop, odd_ind_prop.
+
+Check even_cprop :
+ forall (x : bool) (P : forall n : nat, even x n -> Prop)
+ (P0 : forall n : nat, odd x n -> Prop),
+ P 0 (evenO x) ->
+ (forall (n : nat) (o : odd x n), P0 n o -> P (S n) (evenS x n o)) ->
+ (forall (n : nat) (e : even x n), P n e -> P0 (S n) (oddS x n e)) ->
+ (forall (n : nat) (e : even x n), P n e) /\
+ (forall (n : nat) (o : odd x n), P0 n o).
+
+Scheme even_ind_type := Induction for even Sort Type
+with odd_ind_type := Induction for odd Sort Type.
+
+(* This didn't work in v8.7 *)
+
+Combined Scheme even_ctype from even_ind_type, odd_ind_type.
+
+Check even_ctype :
+ forall (x : bool) (P : forall n : nat, even x n -> Prop)
+ (P0 : forall n : nat, odd x n -> Prop),
+ P 0 (evenO x) ->
+ (forall (n : nat) (o : odd x n), P0 n o -> P (S n) (evenS x n o)) ->
+ (forall (n : nat) (e : even x n), P n e -> P0 (S n) (oddS x n e)) ->
+ (forall (n : nat) (e : even x n), P n e) *
+ (forall (n : nat) (o : odd x n), P0 n o).
diff --git a/test-suite/success/Compat88.v b/test-suite/success/Compat88.v
new file mode 100644
index 0000000000..e2045900d5
--- /dev/null
+++ b/test-suite/success/Compat88.v
@@ -0,0 +1,18 @@
+(* -*- coq-prog-args: ("-compat" "8.8") -*- *)
+(** Check that various syntax usage is available without importing
+ relevant files. *)
+Require Coq.Strings.Ascii Coq.Strings.String.
+Require Coq.ZArith.BinIntDef Coq.PArith.BinPosDef Coq.NArith.BinNatDef.
+Require Coq.Reals.Rdefinitions.
+Require Coq.Numbers.Cyclic.Int31.Cyclic31.
+
+Require Import Coq.Compat.Coq88. (* XXX FIXME Should not need [Require], see https://github.com/coq/coq/issues/8311 *)
+
+Check String.String "a" String.EmptyString.
+Check String.eqb "a" "a".
+Check Nat.eqb 1 1.
+Check BinNat.N.eqb 1 1.
+Check BinInt.Z.eqb 1 1.
+Check BinPos.Pos.eqb 1 1.
+Check Rdefinitions.Rplus 1 1.
+Check Int31.iszero 1.
diff --git a/test-suite/success/CompatCurrentFlag.v b/test-suite/success/CompatCurrentFlag.v
new file mode 100644
index 0000000000..288c9d1da0
--- /dev/null
+++ b/test-suite/success/CompatCurrentFlag.v
@@ -0,0 +1,3 @@
+(* -*- coq-prog-args: ("-compat" "8.8") -*- *)
+(** Check that the current compatibility flag actually requires the relevant modules. *)
+Import Coq.Compat.Coq88.
diff --git a/test-suite/success/CompatOldFlag.v b/test-suite/success/CompatOldFlag.v
new file mode 100644
index 0000000000..b7bbc505b4
--- /dev/null
+++ b/test-suite/success/CompatOldFlag.v
@@ -0,0 +1,5 @@
+(* -*- coq-prog-args: ("-compat" "8.6") -*- *)
+(** Check that the current-minus-two compatibility flag actually requires the relevant modules. *)
+Import Coq.Compat.Coq88.
+Import Coq.Compat.Coq87.
+Import Coq.Compat.Coq86.
diff --git a/test-suite/success/CompatPreviousFlag.v b/test-suite/success/CompatPreviousFlag.v
new file mode 100644
index 0000000000..9cfe60390f
--- /dev/null
+++ b/test-suite/success/CompatPreviousFlag.v
@@ -0,0 +1,4 @@
+(* -*- coq-prog-args: ("-compat" "8.7") -*- *)
+(** Check that the current-minus-one compatibility flag actually requires the relevant modules. *)
+Import Coq.Compat.Coq88.
+Import Coq.Compat.Coq87.
diff --git a/test-suite/success/NumeralNotations.v b/test-suite/success/NumeralNotations.v
new file mode 100644
index 0000000000..47ef381270
--- /dev/null
+++ b/test-suite/success/NumeralNotations.v
@@ -0,0 +1,302 @@
+(* Test that we fail, rather than raising anomalies, on opaque terms during interpretation *)
+
+(* https://github.com/coq/coq/pull/8064#discussion_r202497516 *)
+Module Test1.
+ Axiom hold : forall {A B C}, A -> B -> C.
+ Definition opaque3 (x : Decimal.int) : Decimal.int := hold x (fix f (x : nat) : nat := match x with O => O | S n => S (f n) end).
+ Numeral Notation Decimal.int opaque3 opaque3 : opaque_scope.
+ Delimit Scope opaque_scope with opaque.
+ Fail Check 1%opaque.
+End Test1.
+
+(* https://github.com/coq/coq/pull/8064#discussion_r202497990 *)
+Module Test2.
+ Axiom opaque4 : option Decimal.int.
+ Definition opaque6 (x : Decimal.int) : option Decimal.int := opaque4.
+ Numeral Notation Decimal.int opaque6 opaque6 : opaque_scope.
+ Delimit Scope opaque_scope with opaque.
+ Open Scope opaque_scope.
+ Fail Check 1%opaque.
+End Test2.
+
+Module Test3.
+ Inductive silly := SILLY (v : Decimal.uint) (f : forall A, A -> A).
+ Definition to_silly (v : Decimal.uint) := SILLY v (fun _ x => x).
+ Definition of_silly (v : silly) := match v with SILLY v _ => v end.
+ Numeral Notation silly to_silly of_silly : silly_scope.
+ Delimit Scope silly_scope with silly.
+ Fail Check 1%silly.
+End Test3.
+
+
+Module Test4.
+ Polymorphic NonCumulative Inductive punit := ptt.
+ Polymorphic Definition pto_punit (v : Decimal.uint) : option punit := match Nat.of_uint v with O => Some ptt | _ => None end.
+ Polymorphic Definition pto_punit_all (v : Decimal.uint) : punit := ptt.
+ Polymorphic Definition pof_punit (v : punit) : Decimal.uint := Nat.to_uint 0.
+ Definition to_punit (v : Decimal.uint) : option punit := match Nat.of_uint v with O => Some ptt | _ => None end.
+ Definition of_punit (v : punit) : Decimal.uint := Nat.to_uint 0.
+ Polymorphic Definition pto_unit (v : Decimal.uint) : option unit := match Nat.of_uint v with O => Some tt | _ => None end.
+ Polymorphic Definition pof_unit (v : unit) : Decimal.uint := Nat.to_uint 0.
+ Definition to_unit (v : Decimal.uint) : option unit := match Nat.of_uint v with O => Some tt | _ => None end.
+ Definition of_unit (v : unit) : Decimal.uint := Nat.to_uint 0.
+ Numeral Notation punit to_punit of_punit : pto.
+ Numeral Notation punit pto_punit of_punit : ppo.
+ Numeral Notation punit to_punit pof_punit : ptp.
+ Numeral Notation punit pto_punit pof_punit : ppp.
+ Numeral Notation unit to_unit of_unit : uto.
+ Delimit Scope pto with pto.
+ Delimit Scope ppo with ppo.
+ Delimit Scope ptp with ptp.
+ Delimit Scope ppp with ppp.
+ Delimit Scope uto with uto.
+ Check let v := 0%pto in v : punit.
+ Check let v := 0%ppo in v : punit.
+ Check let v := 0%ptp in v : punit.
+ Check let v := 0%ppp in v : punit.
+ Check let v := 0%uto in v : unit.
+ Fail Check 1%uto.
+ Fail Check (-1)%uto.
+ Numeral Notation unit pto_unit of_unit : upo.
+ Numeral Notation unit to_unit pof_unit : utp.
+ Numeral Notation unit pto_unit pof_unit : upp.
+ Delimit Scope upo with upo.
+ Delimit Scope utp with utp.
+ Delimit Scope upp with upp.
+ Check let v := 0%upo in v : unit.
+ Check let v := 0%utp in v : unit.
+ Check let v := 0%upp in v : unit.
+
+ Polymorphic Definition pto_punits := pto_punit_all@{Set}.
+ Polymorphic Definition pof_punits := pof_punit@{Set}.
+ Numeral Notation punit pto_punits pof_punits : ppps (abstract after 1).
+ Delimit Scope ppps with ppps.
+ Universe u.
+ Constraint Set < u.
+ Check let v := 0%ppps in v : punit@{u}. (* Check that universes are refreshed *)
+ Fail Check let v := 1%ppps in v : punit@{u}. (* Note that universes are not refreshed here *)
+End Test4.
+
+Module Test5.
+ Check S. (* At one point gave Error: Anomaly "Uncaught exception Pretype_errors.PretypeError(_, _, _)." Please report at http://coq.inria.fr/bugs/. *)
+End Test5.
+
+Module Test6.
+ (* Check that numeral notations on enormous terms don't take forever to print/parse *)
+ (* Ackerman definition from https://stackoverflow.com/a/10303475/377022 *)
+ Fixpoint ack (n m : nat) : nat :=
+ match n with
+ | O => S m
+ | S p => let fix ackn (m : nat) :=
+ match m with
+ | O => ack p 1
+ | S q => ack p (ackn q)
+ end
+ in ackn m
+ end.
+
+ Timeout 1 Check (S (ack 4 4)). (* should be instantaneous *)
+
+ Local Set Primitive Projections.
+ Record > wnat := wrap { unwrap :> nat }.
+ Definition to_uint (x : wnat) : Decimal.uint := Nat.to_uint x.
+ Definition of_uint (x : Decimal.uint) : wnat := Nat.of_uint x.
+ Module Export Scopes.
+ Delimit Scope wnat_scope with wnat.
+ End Scopes.
+ Module Export Notations.
+ Export Scopes.
+ Numeral Notation wnat of_uint to_uint : wnat_scope (abstract after 5000).
+ End Notations.
+ Check let v := 0%wnat in v : wnat.
+ Check wrap O.
+ Timeout 1 Check wrap (ack 4 4). (* should be instantaneous *)
+End Test6.
+
+Module Test6_2.
+ Import Test6.Scopes.
+ Check Test6.wrap 0.
+ Import Test6.Notations.
+ Check let v := 0%wnat in v : Test6.wnat.
+End Test6_2.
+
+Module Test7.
+ Local Set Primitive Projections.
+ Record wuint := wrap { unwrap : Decimal.uint }.
+ Delimit Scope wuint_scope with wuint.
+ Numeral Notation wuint wrap unwrap : wuint_scope.
+ Check let v := 0%wuint in v : wuint.
+ Check let v := 1%wuint in v : wuint.
+End Test7.
+
+Module Test8.
+ Local Set Primitive Projections.
+ Record wuint := wrap { unwrap : Decimal.uint }.
+ Delimit Scope wuint8_scope with wuint8.
+ Delimit Scope wuint8'_scope with wuint8'.
+ Section with_var.
+ Context (dummy : unit).
+ Definition wrap' := let __ := dummy in wrap.
+ Definition unwrap' := let __ := dummy in unwrap.
+ Numeral Notation wuint wrap' unwrap' : wuint8_scope.
+ Check let v := 0%wuint8 in v : wuint.
+ End with_var.
+ Check let v := 0%wuint8 in v : nat.
+ Fail Check let v := 0%wuint8 in v : wuint.
+ Compute wrap (Nat.to_uint 0).
+
+ Notation wrap'' := wrap.
+ Notation unwrap'' := unwrap.
+ Numeral Notation wuint wrap'' unwrap'' : wuint8'_scope.
+ Check let v := 0%wuint8' in v : wuint.
+End Test8.
+
+Module Test9.
+ Delimit Scope wuint9_scope with wuint9.
+ Delimit Scope wuint9'_scope with wuint9'.
+ Section with_let.
+ Local Set Primitive Projections.
+ Record wuint := wrap { unwrap : Decimal.uint }.
+ Let wrap' := wrap.
+ Let unwrap' := unwrap.
+ Local Notation wrap'' := wrap.
+ Local Notation unwrap'' := unwrap.
+ Numeral Notation wuint wrap' unwrap' : wuint9_scope.
+ Check let v := 0%wuint9 in v : wuint.
+ Numeral Notation wuint wrap'' unwrap'' : wuint9'_scope.
+ Check let v := 0%wuint9' in v : wuint.
+ End with_let.
+ Check let v := 0%wuint9 in v : nat.
+ Fail Check let v := 0%wuint9 in v : wuint.
+End Test9.
+
+Module Test10.
+ (* Test that it is only a warning to add abstract after to an optional parsing function *)
+ Definition to_uint (v : unit) := Nat.to_uint 0.
+ Definition of_uint (v : Decimal.uint) := match Nat.of_uint v with O => Some tt | _ => None end.
+ Definition of_any_uint (v : Decimal.uint) := tt.
+ Delimit Scope unit_scope with unit.
+ Delimit Scope unit2_scope with unit2.
+ Numeral Notation unit of_uint to_uint : unit_scope (abstract after 1).
+ Local Set Warnings Append "+abstract-large-number-no-op".
+ (* Check that there is actually a warning here *)
+ Fail Numeral Notation unit of_uint to_uint : unit2_scope (abstract after 1).
+ (* Check that there is no warning here *)
+ Numeral Notation unit of_any_uint to_uint : unit2_scope (abstract after 1).
+End Test10.
+
+Module Test11.
+ (* Test that numeral notations don't work on proof-local variables, especially not ones containing evars *)
+ Inductive unit11 := tt11.
+ Delimit Scope unit11_scope with unit11.
+ Goal True.
+ evar (to_uint : unit11 -> Decimal.uint).
+ evar (of_uint : Decimal.uint -> unit11).
+ Fail Numeral Notation unit11 of_uint to_uint : uint11_scope.
+ exact I.
+ Unshelve.
+ all: solve [ constructor ].
+ Qed.
+End Test11.
+
+Module Test12.
+ (* Test for numeral notations on context variables *)
+ Delimit Scope test12_scope with test12.
+ Section test12.
+ Context (to_uint : unit -> Decimal.uint) (of_uint : Decimal.uint -> unit).
+
+ Numeral Notation unit of_uint to_uint : test12_scope.
+ Check let v := 1%test12 in v : unit.
+ End test12.
+End Test12.
+
+Module Test13.
+ (* Test for numeral notations on notations which do not denote references *)
+ Delimit Scope test13_scope with test13.
+ Delimit Scope test13'_scope with test13'.
+ Delimit Scope test13''_scope with test13''.
+ Definition to_uint (x y : unit) : Decimal.uint := Nat.to_uint O.
+ Definition of_uint (x : Decimal.uint) : unit := tt.
+ Definition to_uint_good := to_uint tt.
+ Notation to_uint' := (to_uint tt).
+ Notation to_uint'' := (to_uint _).
+ Numeral Notation unit of_uint to_uint_good : test13_scope.
+ Check let v := 0%test13 in v : unit.
+ Fail Numeral Notation unit of_uint to_uint' : test13'_scope.
+ Fail Check let v := 0%test13' in v : unit.
+ Fail Numeral Notation unit of_uint to_uint'' : test13''_scope.
+ Fail Check let v := 0%test13'' in v : unit.
+End Test13.
+
+Module Test14.
+ (* Test that numeral notations follow [Import], not [Require], and
+ also test that [Local Numeral Notation]s do not escape modules
+ nor sections. *)
+ Delimit Scope test14_scope with test14.
+ Delimit Scope test14'_scope with test14'.
+ Delimit Scope test14''_scope with test14''.
+ Delimit Scope test14'''_scope with test14'''.
+ Module Inner.
+ Definition to_uint (x : unit) : Decimal.uint := Nat.to_uint O.
+ Definition of_uint (x : Decimal.uint) : unit := tt.
+ Local Numeral Notation unit of_uint to_uint : test14_scope.
+ Global Numeral Notation unit of_uint to_uint : test14'_scope.
+ Check let v := 0%test14 in v : unit.
+ Check let v := 0%test14' in v : unit.
+ End Inner.
+ Fail Check let v := 0%test14 in v : unit.
+ Fail Check let v := 0%test14' in v : unit.
+ Import Inner.
+ Fail Check let v := 0%test14 in v : unit.
+ Check let v := 0%test14' in v : unit.
+ Section InnerSection.
+ Definition to_uint (x : unit) : Decimal.uint := Nat.to_uint O.
+ Definition of_uint (x : Decimal.uint) : unit := tt.
+ Local Numeral Notation unit of_uint to_uint : test14''_scope.
+ Fail Global Numeral Notation unit of_uint to_uint : test14'''_scope.
+ Check let v := 0%test14'' in v : unit.
+ Fail Check let v := 0%test14''' in v : unit.
+ End InnerSection.
+ Fail Check let v := 0%test14'' in v : unit.
+ Fail Check let v := 0%test14''' in v : unit.
+End Test14.
+
+Module Test15.
+ (** Test module include *)
+ Delimit Scope test15_scope with test15.
+ Module Inner.
+ Definition to_uint (x : unit) : Decimal.uint := Nat.to_uint O.
+ Definition of_uint (x : Decimal.uint) : unit := tt.
+ Numeral Notation unit of_uint to_uint : test15_scope.
+ Check let v := 0%test15 in v : unit.
+ End Inner.
+ Module Inner2.
+ Include Inner.
+ Check let v := 0%test15 in v : unit.
+ End Inner2.
+ Import Inner Inner2.
+ Check let v := 0%test15 in v : unit.
+End Test15.
+
+Module Test16.
+ (** Test functors *)
+ Delimit Scope test16_scope with test16.
+ Module Type A.
+ Axiom T : Set.
+ Axiom t : T.
+ End A.
+ Module F (a : A).
+ Inductive Foo := foo (_ : a.T).
+ Definition to_uint (x : Foo) : Decimal.uint := Nat.to_uint O.
+ Definition of_uint (x : Decimal.uint) : Foo := foo a.t.
+ Global Numeral Notation Foo of_uint to_uint : test16_scope.
+ Check let v := 0%test16 in v : Foo.
+ End F.
+ Module a <: A.
+ Definition T : Set := unit.
+ Definition t : T := tt.
+ End a.
+ Module Import f := F a.
+ (** Ideally this should work, but it should definitely not anomaly *)
+ Fail Check let v := 0%test16 in v : Foo.
+End Test16.
diff --git a/test-suite/success/ROmega.v b/test-suite/success/ROmega.v
index 0df3d5685d..a97afa7ff0 100644
--- a/test-suite/success/ROmega.v
+++ b/test-suite/success/ROmega.v
@@ -1,5 +1,7 @@
-
-Require Import ZArith ROmega.
+(* This file used to test the `romega` tactics.
+ In Coq 8.9 (end of 2018), these tactics are deprecated.
+ The tests in this file remain but now call the `lia` tactic. *)
+Require Import ZArith Lia.
(* Submitted by Xavier Urbain 18 Jan 2002 *)
@@ -7,14 +9,14 @@ Lemma lem1 :
forall x y : Z, (-5 < x < 5)%Z -> (-5 < y)%Z -> (-5 < x + y + 5)%Z.
Proof.
intros x y.
-romega.
+lia.
Qed.
(* Proposed by Pierre Crégut *)
Lemma lem2 : forall x : Z, (x < 4)%Z -> (x > 2)%Z -> x = 3%Z.
intro.
- romega.
+ lia.
Qed.
(* Proposed by Jean-Christophe Filliâtre *)
@@ -22,7 +24,7 @@ Qed.
Lemma lem3 : forall x y : Z, x = y -> (x + x)%Z = (y + y)%Z.
Proof.
intros.
-romega.
+lia.
Qed.
(* Proposed by Jean-Christophe Filliâtre: confusion between an Omega *)
@@ -32,7 +34,7 @@ Section A.
Variable x y : Z.
Hypothesis H : (x > y)%Z.
Lemma lem4 : (x > y)%Z.
- romega.
+ lia.
Qed.
End A.
@@ -48,7 +50,7 @@ Hypothesis L : (R1 >= 0)%Z -> S2 = S1.
Hypothesis M : (H <= 2 * S)%Z.
Hypothesis N : (S < H)%Z.
Lemma lem5 : (H > 0)%Z.
- romega.
+ lia.
Qed.
End B.
@@ -56,11 +58,10 @@ End B.
Lemma lem6 :
forall (A : Set) (i : Z), (i <= 0)%Z -> ((i <= 0)%Z -> A) -> (i <= 0)%Z.
intros.
- romega.
+ lia.
Qed.
(* Adapted from an example in Nijmegen/FTA/ftc/RefSeparating (Oct 2002) *)
-Require Import Omega.
Section C.
Parameter g : forall m : nat, m <> 0 -> Prop.
Parameter f : forall (m : nat) (H : m <> 0), g m H.
@@ -68,23 +69,21 @@ Variable n : nat.
Variable ap_n : n <> 0.
Let delta := f n ap_n.
Lemma lem7 : n = n.
- romega with nat.
+ lia.
Qed.
End C.
(* Problem of dependencies *)
-Require Import Omega.
Lemma lem8 : forall H : 0 = 0 -> 0 = 0, H = H -> 0 = 0.
intros.
-romega with nat.
+lia.
Qed.
(* Bug that what caused by the use of intro_using in Omega *)
-Require Import Omega.
Lemma lem9 :
forall p q : nat, ~ (p <= q /\ p < q \/ q <= p /\ p < q) -> p < p \/ p <= p.
intros.
-romega with nat.
+lia.
Qed.
(* Check that the interpretation of mult on nat enforces its positivity *)
@@ -92,5 +91,5 @@ Qed.
(* Postponed... problem with goals of the form "(n*m=0)%nat -> (n*m=0)%Z" *)
Lemma lem10 : forall n m : nat, le n (plus n (mult n m)).
Proof.
-intros; romega with nat.
+intros; lia.
Qed.
diff --git a/test-suite/success/ROmega0.v b/test-suite/success/ROmega0.v
index 3ddf6a40fb..7f69422ab3 100644
--- a/test-suite/success/ROmega0.v
+++ b/test-suite/success/ROmega0.v
@@ -1,25 +1,27 @@
-Require Import ZArith ROmega.
+Require Import ZArith Lia.
Open Scope Z_scope.
(* Pierre L: examples gathered while debugging romega. *)
+(* Starting from Coq 8.9 (late 2018), `romega` tactics are deprecated.
+ The tests in this file remain but now call the `lia` tactic. *)
-Lemma test_romega_0 :
+Lemma test_lia_0 :
forall m m',
0<= m <= 1 -> 0<= m' <= 1 -> (0 < m <-> 0 < m') -> m = m'.
Proof.
intros.
-romega.
+lia.
Qed.
-Lemma test_romega_0b :
+Lemma test_lia_0b :
forall m m',
0<= m <= 1 -> 0<= m' <= 1 -> (0 < m <-> 0 < m') -> m = m'.
Proof.
intros m m'.
-romega.
+lia.
Qed.
-Lemma test_romega_1 :
+Lemma test_lia_1 :
forall (z z1 z2 : Z),
z2 <= z1 ->
z1 <= z2 ->
@@ -29,10 +31,10 @@ Lemma test_romega_1 :
z >= 0.
Proof.
intros.
-romega.
+lia.
Qed.
-Lemma test_romega_1b :
+Lemma test_lia_1b :
forall (z z1 z2 : Z),
z2 <= z1 ->
z1 <= z2 ->
@@ -42,24 +44,24 @@ Lemma test_romega_1b :
z >= 0.
Proof.
intros z z1 z2.
-romega.
+lia.
Qed.
-Lemma test_romega_2 : forall a b c:Z,
+Lemma test_lia_2 : forall a b c:Z,
0<=a-b<=1 -> b-c<=2 -> a-c<=3.
Proof.
intros.
-romega.
+lia.
Qed.
-Lemma test_romega_2b : forall a b c:Z,
+Lemma test_lia_2b : forall a b c:Z,
0<=a-b<=1 -> b-c<=2 -> a-c<=3.
Proof.
intros a b c.
-romega.
+lia.
Qed.
-Lemma test_romega_3 : forall a b h hl hr ha hb,
+Lemma test_lia_3 : forall a b h hl hr ha hb,
0 <= ha - hl <= 1 ->
-2 <= hl - hr <= 2 ->
h =b+1 ->
@@ -70,10 +72,10 @@ Lemma test_romega_3 : forall a b h hl hr ha hb,
0 <= hb - h <= 1.
Proof.
intros.
-romega.
+lia.
Qed.
-Lemma test_romega_3b : forall a b h hl hr ha hb,
+Lemma test_lia_3b : forall a b h hl hr ha hb,
0 <= ha - hl <= 1 ->
-2 <= hl - hr <= 2 ->
h =b+1 ->
@@ -84,79 +86,79 @@ Lemma test_romega_3b : forall a b h hl hr ha hb,
0 <= hb - h <= 1.
Proof.
intros a b h hl hr ha hb.
-romega.
+lia.
Qed.
-Lemma test_romega_4 : forall hr ha,
+Lemma test_lia_4 : forall hr ha,
ha = 0 ->
(ha = 0 -> hr =0) ->
hr = 0.
Proof.
intros hr ha.
-romega.
+lia.
Qed.
-Lemma test_romega_5 : forall hr ha,
+Lemma test_lia_5 : forall hr ha,
ha = 0 ->
(~ha = 0 \/ hr =0) ->
hr = 0.
Proof.
intros hr ha.
-romega.
+lia.
Qed.
-Lemma test_romega_6 : forall z, z>=0 -> 0>z+2 -> False.
+Lemma test_lia_6 : forall z, z>=0 -> 0>z+2 -> False.
Proof.
intros.
-romega.
+lia.
Qed.
-Lemma test_romega_6b : forall z, z>=0 -> 0>z+2 -> False.
+Lemma test_lia_6b : forall z, z>=0 -> 0>z+2 -> False.
Proof.
intros z.
-romega.
+lia.
Qed.
-Lemma test_romega_7 : forall z,
+Lemma test_lia_7 : forall z,
0>=0 /\ z=0 \/ 0<=0 /\ z =0 -> 1 = z+1.
Proof.
intros.
-romega.
+lia.
Qed.
-Lemma test_romega_7b : forall z,
+Lemma test_lia_7b : forall z,
0>=0 /\ z=0 \/ 0<=0 /\ z =0 -> 1 = z+1.
Proof.
intros.
-romega.
+lia.
Qed.
(* Magaud BZ#240 *)
-Lemma test_romega_8 : forall x y:Z, x*x<y*y-> ~ y*y <= x*x.
+Lemma test_lia_8 : forall x y:Z, x*x<y*y-> ~ y*y <= x*x.
Proof.
intros.
-romega.
+lia.
Qed.
-Lemma test_romega_8b : forall x y:Z, x*x<y*y-> ~ y*y <= x*x.
+Lemma test_lia_8b : forall x y:Z, x*x<y*y-> ~ y*y <= x*x.
Proof.
intros x y.
-romega.
+lia.
Qed.
(* Besson BZ#1298 *)
-Lemma test_romega9 : forall z z':Z, z<>z' -> z'=z -> False.
+Lemma test_lia9 : forall z z':Z, z<>z' -> z'=z -> False.
Proof.
intros.
-romega.
+lia.
Qed.
(* Letouzey, May 2017 *)
-Lemma test_romega10 : forall x a a' b b',
+Lemma test_lia10 : forall x a a' b b',
a' <= b ->
a <= b' ->
b < b' ->
@@ -164,5 +166,5 @@ Lemma test_romega10 : forall x a a' b b',
a <= x < b' <-> a <= x < b \/ a' <= x < b'.
Proof.
intros.
- romega.
+ lia.
Qed.
diff --git a/test-suite/success/ROmega2.v b/test-suite/success/ROmega2.v
index 43eda67ea3..e3b090699d 100644
--- a/test-suite/success/ROmega2.v
+++ b/test-suite/success/ROmega2.v
@@ -1,4 +1,6 @@
-Require Import ZArith ROmega.
+(* Starting from Coq 8.9 (late 2018), `romega` tactics are deprecated.
+ The tests in this file remain but now call the `lia` tactic. *)
+Require Import ZArith Lia.
(* Submitted by Yegor Bryukhov (BZ#922) *)
@@ -13,7 +15,7 @@ forall v1 v2 v5 : Z,
0 < v2 ->
4*v2 <> 5*v1.
intros.
-romega.
+lia.
Qed.
@@ -37,5 +39,5 @@ forall v1 v2 v3 v4 v5 : Z,
((7 * v1) + (1 * v3)) + ((2 * v3) + (1 * v3)) >= ((6 * v5) + (4)) + ((1) + (9))
-> False.
intros.
-romega.
+lia.
Qed.
diff --git a/test-suite/success/ROmega3.v b/test-suite/success/ROmega3.v
index fd4ff260b5..ef9cb17b4b 100644
--- a/test-suite/success/ROmega3.v
+++ b/test-suite/success/ROmega3.v
@@ -1,10 +1,14 @@
-Require Import ZArith ROmega.
+Require Import ZArith Lia.
Local Open Scope Z_scope.
(** Benchmark provided by Chantal Keller, that romega used to
solve far too slowly (compared to omega or lia). *)
+(* In Coq 8.9 (end of 2018), the `romega` tactics are deprecated.
+ The tests in this file remain but now call the `lia` tactic. *)
+
+
Parameter v4 : Z.
Parameter v3 : Z.
Parameter o4 : Z.
@@ -27,5 +31,5 @@ Lemma lemma_5833 :
(-4096 * o5 + (-2048 * s6 + (2 * v1 + (-2048 * o6 +
(-1024 * s7 + (v0 + -1024 * o7)))))))))) >= 1024.
Proof.
-Timeout 1 romega. (* should take a few milliseconds, not seconds *)
+Timeout 1 lia. (* should take a few milliseconds, not seconds *)
Timeout 1 Qed. (* ditto *)
diff --git a/test-suite/success/ROmega4.v b/test-suite/success/ROmega4.v
index 58ae5b8fb8..a724592749 100644
--- a/test-suite/success/ROmega4.v
+++ b/test-suite/success/ROmega4.v
@@ -3,12 +3,12 @@
See also #148 for the corresponding improvement in Omega.
*)
-Require Import ZArith ROmega.
+Require Import ZArith Lia.
Open Scope Z.
Goal let x := 3 in x = 3.
intros.
-romega.
+lia.
Qed.
(** Example seen in #4132
@@ -22,5 +22,5 @@ Lemma foo
(H : - zxy' <= zxy)
(H' : zxy' <= x') : - b <= zxy.
Proof.
-romega.
+lia.
Qed.
diff --git a/test-suite/success/ROmegaPre.v b/test-suite/success/ROmegaPre.v
index fa659273e1..6ca32f450f 100644
--- a/test-suite/success/ROmegaPre.v
+++ b/test-suite/success/ROmegaPre.v
@@ -1,127 +1,123 @@
-Require Import ZArith Nnat ROmega.
+Require Import ZArith Nnat Lia.
Open Scope Z_scope.
(** Test of the zify preprocessor for (R)Omega *)
+(* Starting from Coq 8.9 (late 2018), `romega` tactics are deprecated.
+ The tests in this file remain but now call the `lia` tactic. *)
(* More details in file PreOmega.v
-
- (r)omega with Z : starts with zify_op
- (r)omega with nat : starts with zify_nat
- (r)omega with positive : starts with zify_positive
- (r)omega with N : starts with uses zify_N
- (r)omega with * : starts zify (a saturation of the others)
*)
(* zify_op *)
Goal forall a:Z, Z.max a a = a.
intros.
-romega with *.
+lia.
Qed.
Goal forall a b:Z, Z.max a b = Z.max b a.
intros.
-romega with *.
+lia.
Qed.
Goal forall a b c:Z, Z.max a (Z.max b c) = Z.max (Z.max a b) c.
intros.
-romega with *.
+lia.
Qed.
Goal forall a b:Z, Z.max a b + Z.min a b = a + b.
intros.
-romega with *.
+lia.
Qed.
Goal forall a:Z, (Z.abs a)*(Z.sgn a) = a.
intros.
zify.
-intuition; subst; romega. (* pure multiplication: omega alone can't do it *)
+intuition; subst; lia. (* pure multiplication: omega alone can't do it *)
Qed.
Goal forall a:Z, Z.abs a = a -> a >= 0.
intros.
-romega with *.
+lia.
Qed.
Goal forall a:Z, Z.sgn a = a -> a = 1 \/ a = 0 \/ a = -1.
intros.
-romega with *.
+lia.
Qed.
(* zify_nat *)
Goal forall m: nat, (m<2)%nat -> (0<= m+m <=2)%nat.
intros.
-romega with *.
+lia.
Qed.
Goal forall m:nat, (m<1)%nat -> (m=0)%nat.
intros.
-romega with *.
+lia.
Qed.
Goal forall m: nat, (m<=100)%nat -> (0<= m+m <=200)%nat.
intros.
-romega with *.
+lia.
Qed.
(* 2000 instead of 200: works, but quite slow *)
Goal forall m: nat, (m*m>=0)%nat.
intros.
-romega with *.
+lia.
Qed.
(* zify_positive *)
Goal forall m: positive, (m<2)%positive -> (2 <= m+m /\ m+m <= 2)%positive.
intros.
-romega with *.
+lia.
Qed.
Goal forall m:positive, (m<2)%positive -> (m=1)%positive.
intros.
-romega with *.
+lia.
Qed.
Goal forall m: positive, (m<=1000)%positive -> (2<=m+m/\m+m <=2000)%positive.
intros.
-romega with *.
+lia.
Qed.
Goal forall m: positive, (m*m>=1)%positive.
intros.
-romega with *.
+lia.
Qed.
(* zify_N *)
Goal forall m:N, (m<2)%N -> (0 <= m+m /\ m+m <= 2)%N.
intros.
-romega with *.
+lia.
Qed.
Goal forall m:N, (m<1)%N -> (m=0)%N.
intros.
-romega with *.
+lia.
Qed.
Goal forall m:N, (m<=1000)%N -> (0<=m+m/\m+m <=2000)%N.
intros.
-romega with *.
+lia.
Qed.
Goal forall m:N, (m*m>=0)%N.
intros.
-romega with *.
+lia.
Qed.
(* mix of datatypes *)
Goal forall p, Z.of_N (N.of_nat (N.to_nat (Npos p))) = Zpos p.
intros.
-romega with *.
+lia.
Qed.
diff --git a/test-suite/success/SchemeEquality.v b/test-suite/success/SchemeEquality.v
new file mode 100644
index 0000000000..85d5c3e123
--- /dev/null
+++ b/test-suite/success/SchemeEquality.v
@@ -0,0 +1,29 @@
+(* Examples of use of Scheme Equality *)
+
+Module A.
+Definition N := nat.
+Inductive list := nil | cons : N -> list -> list.
+Scheme Equality for list.
+End A.
+
+Module B.
+ Section A.
+ Context A (eq_A:A->A->bool)
+ (A_bl : forall x y, eq_A x y = true -> x = y)
+ (A_lb : forall x y, x = y -> eq_A x y = true).
+ Inductive I := C : A -> I.
+ Scheme Equality for I.
+ End A.
+End B.
+
+Module C.
+ Parameter A : Type.
+ Parameter eq_A : A->A->bool.
+ Parameter A_bl : forall x y, eq_A x y = true -> x = y.
+ Parameter A_lb : forall x y, x = y -> eq_A x y = true.
+ Hint Resolve A_bl A_lb : core.
+ Inductive I := C : A -> I.
+ Scheme Equality for I.
+ Inductive J := D : list A -> J.
+ Scheme Equality for J.
+End C.
diff --git a/test-suite/success/Template.v b/test-suite/success/Template.v
new file mode 100644
index 0000000000..1c6e2d81d8
--- /dev/null
+++ b/test-suite/success/Template.v
@@ -0,0 +1,48 @@
+Set Printing Universes.
+
+Module AutoYes.
+ Inductive Box (A:Type) : Type := box : A -> Box A.
+
+ About Box.
+
+ (* This checks that Box is template poly, see module No for how it fails *)
+ Universe i j. Constraint i < j.
+ Definition j_lebox (A:Type@{j}) := Box A.
+ Definition box_lti A := Box A : Type@{i}.
+
+End AutoYes.
+
+Module AutoNo.
+ Unset Auto Template Polymorphism.
+ Inductive Box (A:Type) : Type := box : A -> Box A.
+
+ About Box.
+
+ Universe i j. Constraint i < j.
+ Definition j_lebox (A:Type@{j}) := Box A.
+ Fail Definition box_lti A := Box A : Type@{i}.
+
+End AutoNo.
+
+Module Yes.
+ #[template]
+ Inductive Box@{i} (A:Type@{i}) : Type@{i} := box : A -> Box A.
+
+ About Box.
+
+ Universe i j. Constraint i < j.
+ Definition j_lebox (A:Type@{j}) := Box A.
+ Definition box_lti A := Box A : Type@{i}.
+
+End Yes.
+
+Module No.
+ #[notemplate]
+ Inductive Box (A:Type) : Type := box : A -> Box A.
+
+ About Box.
+
+ Universe i j. Constraint i < j.
+ Definition j_lebox (A:Type@{j}) := Box A.
+ Fail Definition box_lti A := Box A : Type@{i}.
+End No.
diff --git a/test-suite/success/apply.v b/test-suite/success/apply.v
index b287b5facf..e1df9ba84a 100644
--- a/test-suite/success/apply.v
+++ b/test-suite/success/apply.v
@@ -559,3 +559,26 @@ split.
- (* clear b:True *) match goal with H:_ |- _ => clear H end.
(* use a:0=0 *) match goal with H:_ |- _ => exact H end.
Qed.
+
+(* Test choice of most dependent solution *)
+Goal forall n, n = 0 -> exists p, p = n /\ p = 0.
+intros. eexists ?[p]. split. rewrite H.
+reflexivity. (* Compatibility tells [?p:=n] rather than [?p:=0] *)
+exact H. (* this checks that the goal is [n=0], not [0=0] *)
+Qed.
+
+(* Check insensitivity to alphabetic order of names*)
+(* In both cases, the last name is conventionally chosen *)
+(* Before 8.9, the name coming first in alphabetic order *)
+(* was chosen. *)
+Goal forall m n, m = n -> n = 0 -> exists p, p = n /\ p = 0.
+intros. eexists ?[p]. split. rewrite H.
+reflexivity.
+exact H0.
+Qed.
+
+Goal forall n m, n = m -> m = 0 -> exists p, p = m /\ p = 0.
+intros. eexists ?[p]. split. rewrite H.
+reflexivity.
+exact H0.
+Qed.
diff --git a/test-suite/success/attribute-syntax.v b/test-suite/success/attribute-syntax.v
index 83fb3d0c8e..241d4eb200 100644
--- a/test-suite/success/attribute-syntax.v
+++ b/test-suite/success/attribute-syntax.v
@@ -1,4 +1,4 @@
-From Coq Require Program.
+From Coq Require Program.Wf.
Section Scope.
@@ -21,3 +21,13 @@ Fixpoint f (n: nat) {wf lt n} : nat := _.
#[deprecated(since="8.9.0")]
Ltac foo := foo.
+
+Module M.
+ #[local] #[polymorphic] Definition zed := Type.
+
+ #[local, polymorphic] Definition kats := Type.
+End M.
+Check M.zed@{_}.
+Fail Check zed.
+Check M.kats@{_}.
+Fail Check kats.
diff --git a/test-suite/success/ltac.v b/test-suite/success/ltac.v
index 0f22a1f0a0..448febed25 100644
--- a/test-suite/success/ltac.v
+++ b/test-suite/success/ltac.v
@@ -348,3 +348,59 @@ symmetry in H.
match goal with h:_ |- _ => assert (h=h) end. (* h should be H0 *)
exact (eq_refl H0).
Abort.
+
+(* Check that internal names used in "match" compilation to push "term
+ to match" on the environment are not interpreted as ltac variables *)
+
+Module ToMatchNames.
+Ltac g c := let r := constr:(match c return _ with a => 1 end) in idtac.
+Goal True.
+g 1.
+Abort.
+End ToMatchNames.
+
+(* An example where internal names used to build the return predicate
+ (here "n" because "a" is bound to "nil" and "n" is the first letter
+ of "nil") by small inversion should be taken distinct from Ltac names. *)
+
+Module LtacNames.
+Inductive t (A : Type) : nat -> Type :=
+ nil : t A 0 | cons : A -> forall n : nat, t A n -> t A (S n).
+
+Ltac f a n :=
+ let x := constr:(match a with nil _ => true | cons _ _ _ _ => I end) in
+ assert (x=x/\n=n).
+
+Goal forall (y:t nat 0), True.
+intros.
+f y true.
+Abort.
+
+End LtacNames.
+
+(* Test binding of the name of existential variables in Ltac *)
+
+Module EvarNames.
+
+Ltac pick x := eexists ?[x].
+Goal exists y, y = 0.
+pick foo.
+[foo]:exact 0.
+auto.
+Qed.
+
+Ltac goal x := refine ?[x].
+
+Goal forall n, n + 0 = n.
+Proof.
+ induction n; [ goal Base | goal Rec ].
+ [Base]: {
+ easy.
+ }
+ [Rec]: {
+ simpl.
+ now f_equal.
+ }
+Qed.
+
+End EvarNames.
diff --git a/test-suite/vio/numeral.v b/test-suite/vio/numeral.v
new file mode 100644
index 0000000000..f28355bb29
--- /dev/null
+++ b/test-suite/vio/numeral.v
@@ -0,0 +1,21 @@
+Lemma foo : True.
+Proof.
+Check 0 : nat.
+Check 0 : nat.
+exact I.
+Qed.
+
+Lemma bar : True.
+Proof.
+pose (0 : nat).
+exact I.
+Qed.
+
+Require Import Coq.Strings.Ascii.
+Open Scope char_scope.
+
+Lemma baz : True.
+Proof.
+pose "s".
+exact I.
+Qed.
diff --git a/theories/Bool/Bool.v b/theories/Bool/Bool.v
index 66a82008d8..42af3583d4 100644
--- a/theories/Bool/Bool.v
+++ b/theories/Bool/Bool.v
@@ -757,6 +757,8 @@ Qed.
with lazy behavior (for vm_compute) *)
(*****************************************)
+Declare Scope lazy_bool_scope.
+
Notation "a &&& b" := (if a then b else false)
(at level 40, left associativity) : lazy_bool_scope.
Notation "a ||| b" := (if a then true else b)
diff --git a/theories/Bool/Bvector.v b/theories/Bool/Bvector.v
index aecdb59dbe..3d615485b9 100644
--- a/theories/Bool/Bvector.v
+++ b/theories/Bool/Bvector.v
@@ -70,6 +70,8 @@ Definition BVor := @Vector.map2 _ _ _ orb.
Definition BVxor := @Vector.map2 _ _ _ xorb.
+Definition BVeq m n := @Vector.eqb bool eqb m n.
+
Definition BshiftL (n:nat) (bv:Bvector (S n)) (carry:bool) :=
Bcons carry n (Vector.shiftout bv).
@@ -99,3 +101,13 @@ Fixpoint BshiftRa_iter (n:nat) (bv:Bvector (S n)) (p:nat) : Bvector (S n) :=
End BOOLEAN_VECTORS.
+Module BvectorNotations.
+Declare Scope Bvector_scope.
+Delimit Scope Bvector_scope with Bvector.
+Notation "^~ x" := (Bneg _ x) (at level 35, right associativity) : Bvector_scope.
+Infix "^&" := (BVand _) (at level 40, left associativity) : Bvector_scope.
+Infix "^⊕" := (BVxor _) (at level 45, left associativity) : Bvector_scope.
+Infix "^|" := (BVor _) (at level 50, left associativity) : Bvector_scope.
+Infix "=?" := (BVeq _ _) (at level 70, no associativity) : Bvector_scope.
+Open Scope Bvector_scope.
+End BvectorNotations.
diff --git a/theories/Classes/CEquivalence.v b/theories/Classes/CEquivalence.v
index 03e611f549..c376efef2e 100644
--- a/theories/Classes/CEquivalence.v
+++ b/theories/Classes/CEquivalence.v
@@ -35,6 +35,8 @@ Definition equiv `{Equivalence A R} : crelation A := R.
(** Overloaded notations for setoid equivalence and inequivalence.
Not to be confused with [eq] and [=]. *)
+Declare Scope equiv_scope.
+
Notation " x === y " := (equiv x y) (at level 70, no associativity) : equiv_scope.
Notation " x =/= y " := (complement equiv x y) (at level 70, no associativity) : equiv_scope.
diff --git a/theories/Classes/CMorphisms.v b/theories/Classes/CMorphisms.v
index 09b35ca75d..97510578ae 100644
--- a/theories/Classes/CMorphisms.v
+++ b/theories/Classes/CMorphisms.v
@@ -87,6 +87,7 @@ Hint Extern 2 (ProperProxy ?R _) =>
not_evar R; class_apply @proper_proper_proxy : typeclass_instances.
(** Notations reminiscent of the old syntax for declaring morphisms. *)
+Declare Scope signature_scope.
Delimit Scope signature_scope with signature.
Module ProperNotations.
diff --git a/theories/Classes/Equivalence.v b/theories/Classes/Equivalence.v
index 5217aedb88..516ea12099 100644
--- a/theories/Classes/Equivalence.v
+++ b/theories/Classes/Equivalence.v
@@ -35,6 +35,8 @@ Definition equiv `{Equivalence A R} : relation A := R.
(** Overloaded notations for setoid equivalence and inequivalence.
Not to be confused with [eq] and [=]. *)
+Declare Scope equiv_scope.
+
Notation " x === y " := (equiv x y) (at level 70, no associativity) : equiv_scope.
Notation " x =/= y " := (complement equiv x y) (at level 70, no associativity) : equiv_scope.
diff --git a/theories/Classes/Morphisms.v b/theories/Classes/Morphisms.v
index 1858ba76ae..001b7dfdfd 100644
--- a/theories/Classes/Morphisms.v
+++ b/theories/Classes/Morphisms.v
@@ -88,6 +88,7 @@ Hint Extern 2 (ProperProxy ?R _) =>
not_evar R; class_apply @proper_proper_proxy : typeclass_instances.
(** Notations reminiscent of the old syntax for declaring morphisms. *)
+Declare Scope signature_scope.
Delimit Scope signature_scope with signature.
Module ProperNotations.
diff --git a/theories/Classes/RelationClasses.v b/theories/Classes/RelationClasses.v
index 2ab3af2029..86a3a88be9 100644
--- a/theories/Classes/RelationClasses.v
+++ b/theories/Classes/RelationClasses.v
@@ -357,6 +357,8 @@ Definition predicate_implication {l : Tlist} :=
(** Notations for pointwise equivalence and implication of predicates. *)
+Declare Scope predicate_scope.
+
Infix "<∙>" := predicate_equivalence (at level 95, no associativity) : predicate_scope.
Infix "-∙>" := predicate_implication (at level 70, right associativity) : predicate_scope.
diff --git a/theories/Compat/Coq88.v b/theories/Compat/Coq88.v
index 4142af05d2..578425bfb5 100644
--- a/theories/Compat/Coq88.v
+++ b/theories/Compat/Coq88.v
@@ -9,3 +9,17 @@
(************************************************************************)
(** Compatibility file for making Coq act similar to Coq v8.8 *)
+(** In Coq 8.9, prim token notations follow [Import] rather than
+ [Require]. So we make all of the relevant notations accessible in
+ compatibility mode. *)
+Require Coq.Strings.Ascii Coq.Strings.String.
+Require Coq.ZArith.BinIntDef Coq.PArith.BinPosDef Coq.NArith.BinNatDef.
+Require Coq.Reals.Rdefinitions.
+Require Coq.Numbers.Cyclic.Int31.Int31.
+Declare ML Module "string_syntax_plugin".
+Declare ML Module "ascii_syntax_plugin".
+Declare ML Module "r_syntax_plugin".
+Declare ML Module "int31_syntax_plugin".
+Numeral Notation BinNums.Z BinIntDef.Z.of_int BinIntDef.Z.to_int : Z_scope.
+Numeral Notation BinNums.positive BinPosDef.Pos.of_int BinPosDef.Pos.to_int : positive_scope.
+Numeral Notation BinNums.N BinNatDef.N.of_int BinNatDef.N.to_int : N_scope.
diff --git a/theories/FSets/FMapAVL.v b/theories/FSets/FMapAVL.v
index 3485b9c68d..b0d1824827 100644
--- a/theories/FSets/FMapAVL.v
+++ b/theories/FSets/FMapAVL.v
@@ -25,6 +25,7 @@ Unset Strict Implicit.
(** Notations and helper lemma about pairs *)
+Declare Scope pair_scope.
Notation "s #1" := (fst s) (at level 9, format "s '#1'") : pair_scope.
Notation "s #2" := (snd s) (at level 9, format "s '#2'") : pair_scope.
diff --git a/theories/FSets/FMapFullAVL.v b/theories/FSets/FMapFullAVL.v
index 3452967821..c0db8646c7 100644
--- a/theories/FSets/FMapFullAVL.v
+++ b/theories/FSets/FMapFullAVL.v
@@ -27,7 +27,7 @@
*)
-Require Import FunInd Recdef FMapInterface FMapList ZArith Int FMapAVL ROmega.
+Require Import FunInd Recdef FMapInterface FMapList ZArith Int FMapAVL Lia.
Set Implicit Arguments.
Unset Strict Implicit.
@@ -39,7 +39,7 @@ Import Raw.Proofs.
Local Open Scope pair_scope.
Local Open Scope Int_scope.
-Ltac omega_max := i2z_refl; romega with Z.
+Ltac omega_max := i2z_refl; lia.
Section Elt.
Variable elt : Type.
@@ -697,7 +697,7 @@ Module IntMake_ord (I:Int)(X: OrderedType)(D : OrderedType) <:
end.
Proof.
intros; unfold cardinal_e_2; simpl;
- abstract (do 2 rewrite cons_cardinal_e; romega with * ).
+ abstract (do 2 rewrite cons_cardinal_e; lia ).
Defined.
Definition Cmp c :=
diff --git a/theories/FSets/FSetAVL.v b/theories/FSets/FSetAVL.v
index 3c9b6b428b..dcaea894eb 100644
--- a/theories/FSets/FSetAVL.v
+++ b/theories/FSets/FSetAVL.v
@@ -15,7 +15,7 @@
It follows the implementation from Ocaml's standard library,
All operations given here expect and produce well-balanced trees
- (in the ocaml sense: heigths of subtrees shouldn't differ by more
+ (in the ocaml sense: heights of subtrees shouldn't differ by more
than 2), and hence has low complexities (e.g. add is logarithmic
in the size of the set). But proving these balancing preservations
is in fact not necessary for ensuring correct operational behavior
diff --git a/theories/FSets/FSetEqProperties.v b/theories/FSets/FSetEqProperties.v
index 56844f4773..59b2f789ab 100644
--- a/theories/FSets/FSetEqProperties.v
+++ b/theories/FSets/FSetEqProperties.v
@@ -333,7 +333,7 @@ Proof.
auto with set.
Qed.
-(* caracterisation of [union] via [subset] *)
+(* characterisation of [union] via [subset] *)
Lemma union_subset_1: subset s (union s s')=true.
Proof.
@@ -408,7 +408,7 @@ intros; apply equal_1; apply inter_add_2.
rewrite not_mem_iff; auto.
Qed.
-(* caracterisation of [union] via [subset] *)
+(* characterisation of [union] via [subset] *)
Lemma inter_subset_1: subset (inter s s') s=true.
Proof.
diff --git a/theories/Init/Datatypes.v b/theories/Init/Datatypes.v
index 05b741f0ac..8a0265438a 100644
--- a/theories/Init/Datatypes.v
+++ b/theories/Init/Datatypes.v
@@ -12,7 +12,6 @@ Set Implicit Arguments.
Require Import Notations.
Require Import Logic.
-Declare ML Module "nat_syntax_plugin".
(********************************************************************)
(** * Datatypes with zero and one element *)
@@ -38,8 +37,8 @@ Inductive bool : Set :=
Add Printing If bool.
+Declare Scope bool_scope.
Delimit Scope bool_scope with bool.
-
Bind Scope bool_scope with bool.
(** Basic boolean operators *)
@@ -137,6 +136,7 @@ Inductive nat : Set :=
| O : nat
| S : nat -> nat.
+Declare Scope nat_scope.
Delimit Scope nat_scope with nat.
Bind Scope nat_scope with nat.
Arguments S _%nat.
@@ -177,11 +177,12 @@ Arguments inr {A B} _ , A [B] _.
the pair [pair A B a b] of [a] and [b] is abbreviated [(a,b)] *)
Inductive prod (A B:Type) : Type :=
- pair : A -> B -> prod A B.
+ pair : A -> B -> A * B
+
+where "x * y" := (prod x y) : type_scope.
Add Printing Let prod.
-Notation "x * y" := (prod x y) : type_scope.
Notation "( x , y , .. , z )" := (pair .. (pair x y) .. z) : core_scope.
Arguments pair {A B} _ _.
@@ -189,18 +190,14 @@ Arguments pair {A B} _ _.
Section projections.
Context {A : Type} {B : Type}.
- Definition fst (p:A * B) := match p with
- | (x, y) => x
- end.
- Definition snd (p:A * B) := match p with
- | (x, y) => y
- end.
+ Definition fst (p:A * B) := match p with (x, y) => x end.
+ Definition snd (p:A * B) := match p with (x, y) => y end.
End projections.
Hint Resolve pair inl inr: core.
Lemma surjective_pairing :
- forall (A B:Type) (p:A * B), p = pair (fst p) (snd p).
+ forall (A B:Type) (p:A * B), p = (fst p, snd p).
Proof.
destruct p; reflexivity.
Qed.
@@ -213,13 +210,19 @@ Proof.
rewrite Hfst; rewrite Hsnd; reflexivity.
Qed.
-Definition prod_uncurry (A B C:Type) (f:prod A B -> C)
- (x:A) (y:B) : C := f (pair x y).
+Definition prod_uncurry (A B C:Type) (f:A * B -> C)
+ (x:A) (y:B) : C := f (x,y).
Definition prod_curry (A B C:Type) (f:A -> B -> C)
- (p:prod A B) : C := match p with
- | pair x y => f x y
- end.
+ (p:A * B) : C := match p with (x, y) => f x y end.
+
+Import EqNotations.
+
+Lemma rew_pair : forall A (P Q : A->Type) x1 x2 (y1:P x1) (y2:Q x1) (H:x1=x2),
+ (rew H in y1, rew H in y2) = rew [fun x => (P x * Q x)%type] H in (y1,y2).
+Proof.
+ destruct H. reflexivity.
+Defined.
(** Polymorphic lists and some operations *)
@@ -229,10 +232,13 @@ Inductive list (A : Type) : Type :=
Arguments nil {A}.
Arguments cons {A} a l.
-Infix "::" := cons (at level 60, right associativity) : list_scope.
+
+Declare Scope list_scope.
Delimit Scope list_scope with list.
Bind Scope list_scope with list.
+Infix "::" := cons (at level 60, right associativity) : list_scope.
+
Local Open Scope list_scope.
Definition length (A : Type) : list A -> nat :=
@@ -251,7 +257,6 @@ Definition app (A : Type) : list A -> list A -> list A :=
| a :: l1 => a :: app l1 m
end.
-
Infix "++" := app (right associativity, at level 60) : list_scope.
(* Unset Universe Polymorphism. *)
diff --git a/theories/Init/Decimal.v b/theories/Init/Decimal.v
index 57163b1b07..537400fb05 100644
--- a/theories/Init/Decimal.v
+++ b/theories/Init/Decimal.v
@@ -42,10 +42,13 @@ Notation zero := (D0 Nil).
Inductive int := Pos (d:uint) | Neg (d:uint).
-Delimit Scope uint_scope with uint.
-Bind Scope uint_scope with uint.
-Delimit Scope int_scope with int.
-Bind Scope int_scope with int.
+Declare Scope dec_uint_scope.
+Delimit Scope dec_uint_scope with uint.
+Bind Scope dec_uint_scope with uint.
+
+Declare Scope dec_int_scope.
+Delimit Scope dec_int_scope with int.
+Bind Scope dec_int_scope with int.
(** This representation favors simplicity over canonicity.
For normalizing numbers, we need to remove head zero digits,
@@ -161,3 +164,9 @@ with succ_double d :=
end.
End Little.
+
+(** Pseudo-conversion functions used when declaring
+ Numeral Notations on [uint] and [int]. *)
+
+Definition uint_of_uint (i:uint) := i.
+Definition int_of_int (i:int) := i.
diff --git a/theories/Init/Logic.v b/theories/Init/Logic.v
index 9d60cf54c3..4ec0049a9c 100644
--- a/theories/Init/Logic.v
+++ b/theories/Init/Logic.v
@@ -406,6 +406,37 @@ End EqNotations.
Import EqNotations.
+Section equality_dep.
+ Variable A : Type.
+ Variable B : A -> Type.
+ Variable f : forall x, B x.
+ Variables x y : A.
+
+ Theorem f_equal_dep : forall (H: x = y), rew H in f x = f y.
+ Proof.
+ destruct H; reflexivity.
+ Defined.
+
+End equality_dep.
+
+Section equality_dep2.
+
+ Variable A A' : Type.
+ Variable B : A -> Type.
+ Variable B' : A' -> Type.
+ Variable f : A -> A'.
+ Variable g : forall a:A, B a -> B' (f a).
+ Variables x y : A.
+
+ Lemma f_equal_dep2 : forall {A A' B B'} (f : A -> A') (g : forall a:A, B a -> B' (f a))
+ {x1 x2 : A} {y1 : B x1} {y2 : B x2} (H : x1 = x2),
+ rew H in y1 = y2 -> rew f_equal f H in g x1 y1 = g x2 y2.
+ Proof.
+ destruct H, 1. reflexivity.
+ Defined.
+
+End equality_dep2.
+
Lemma rew_opp_r : forall A (P:A->Type) (x y:A) (H:x=y) (a:P y), rew H in rew <- H in a = a.
Proof.
intros.
@@ -492,6 +523,42 @@ Proof.
destruct e''; reflexivity.
Defined.
+Theorem rew_map : forall A B (P:B->Type) (f:A->B) x1 x2 (H:x1=x2) (y:P (f x1)),
+ rew [fun x => P (f x)] H in y = rew f_equal f H in y.
+Proof.
+ destruct H; reflexivity.
+Defined.
+
+Theorem eq_trans_map : forall {A B} {x1 x2 x3:A} {y1:B x1} {y2:B x2} {y3:B x3},
+ forall (H1:x1=x2) (H2:x2=x3) (H1': rew H1 in y1 = y2) (H2': rew H2 in y2 = y3),
+ rew eq_trans H1 H2 in y1 = y3.
+Proof.
+ intros. destruct H2. exact (eq_trans H1' H2').
+Defined.
+
+Lemma map_subst : forall {A} {P Q:A->Type} (f : forall x, P x -> Q x) {x y} (H:x=y) (z:P x),
+ rew H in f x z = f y (rew H in z).
+Proof.
+ destruct H. reflexivity.
+Defined.
+
+Lemma map_subst_map : forall {A B} {P:A->Type} {Q:B->Type} (f:A->B) (g : forall x, P x -> Q (f x)),
+ forall {x y} (H:x=y) (z:P x), rew f_equal f H in g x z = g y (rew H in z).
+Proof.
+ destruct H. reflexivity.
+Defined.
+
+Lemma rew_swap : forall A (P:A->Type) x1 x2 (H:x1=x2) (y1:P x1) (y2:P x2), rew H in y1 = y2 -> y1 = rew <- H in y2.
+Proof.
+ destruct H. trivial.
+Defined.
+
+Lemma rew_compose : forall A (P:A->Type) x1 x2 x3 (H1:x1=x2) (H2:x2=x3) (y:P x1),
+ rew H2 in rew H1 in y = rew (eq_trans H1 H2) in y.
+Proof.
+ destruct H2. reflexivity.
+Defined.
+
(** Extra properties of equality *)
Theorem eq_id_comm_l : forall A (f:A->A) (Hf:forall a, a = f a), forall a, f_equal f (Hf a) = Hf (f a).
diff --git a/theories/Init/Nat.v b/theories/Init/Nat.v
index ad1bc717c4..eb4ba0e5e6 100644
--- a/theories/Init/Nat.v
+++ b/theories/Init/Nat.v
@@ -24,6 +24,10 @@ Definition t := nat.
(** ** Constants *)
+Local Notation "0" := O.
+Local Notation "1" := (S O).
+Local Notation "2" := (S (S O)).
+
Definition zero := 0.
Definition one := 1.
Definition two := 2.
diff --git a/theories/Init/Notations.v b/theories/Init/Notations.v
index 72073bb4f6..8f8e639187 100644
--- a/theories/Init/Notations.v
+++ b/theories/Init/Notations.v
@@ -108,13 +108,17 @@ End IfNotations.
(** Scopes *)
-Delimit Scope type_scope with type.
-Delimit Scope function_scope with function.
+Declare Scope core_scope.
Delimit Scope core_scope with core.
-Bind Scope type_scope with Sortclass.
+Declare Scope function_scope.
+Delimit Scope function_scope with function.
Bind Scope function_scope with Funclass.
+Declare Scope type_scope.
+Delimit Scope type_scope with type.
+Bind Scope type_scope with Sortclass.
+
Open Scope core_scope.
Open Scope function_scope.
Open Scope type_scope.
diff --git a/theories/Init/Peano.v b/theories/Init/Peano.v
index d5322d0945..65e5e76a22 100644
--- a/theories/Init/Peano.v
+++ b/theories/Init/Peano.v
@@ -31,6 +31,7 @@ Require Import Logic.
Require Coq.Init.Nat.
Open Scope nat_scope.
+Local Notation "0" := O.
Definition eq_S := f_equal S.
Definition f_equal_nat := f_equal (A:=nat).
diff --git a/theories/Init/Prelude.v b/theories/Init/Prelude.v
index 802f18c0f2..6d98bcb34a 100644
--- a/theories/Init/Prelude.v
+++ b/theories/Init/Prelude.v
@@ -19,9 +19,24 @@ Require Export Peano.
Require Export Coq.Init.Wf.
Require Export Coq.Init.Tactics.
Require Export Coq.Init.Tauto.
-(* Initially available plugins
- (+ nat_syntax_plugin loaded in Datatypes) *)
+(* Some initially available plugins. See also:
+ - ltac_plugin (in Notations)
+ - tauto_plugin (in Tauto).
+*)
Declare ML Module "cc_plugin".
Declare ML Module "ground_plugin".
+Declare ML Module "numeral_notation_plugin".
+
+(* Parsing / printing of decimal numbers *)
+Arguments Nat.of_uint d%dec_uint_scope.
+Arguments Nat.of_int d%dec_int_scope.
+Numeral Notation Decimal.uint Decimal.uint_of_uint Decimal.uint_of_uint
+ : dec_uint_scope.
+Numeral Notation Decimal.int Decimal.int_of_int Decimal.int_of_int
+ : dec_int_scope.
+
+(* Parsing / printing of [nat] numbers *)
+Numeral Notation nat Nat.of_uint Nat.to_uint : nat_scope (abstract after 5000).
+
(* Default substrings not considered by queries like SearchAbout *)
Add Search Blacklist "_subproof" "_subterm" "Private_".
diff --git a/theories/Init/Specif.v b/theories/Init/Specif.v
index b6afba29a0..d6a0fb214f 100644
--- a/theories/Init/Specif.v
+++ b/theories/Init/Specif.v
@@ -154,6 +154,10 @@ Section Projections.
End Projections.
+Local Notation "( x ; y )" := (existT _ x y) (at level 0, format "( x ; '/ ' y )").
+Local Notation "x .1" := (projT1 x) (at level 1, left associativity, format "x .1").
+Local Notation "x .2" := (projT2 x) (at level 1, left associativity, format "x .2").
+
(** [sigT2] of a predicate can be projected to a [sigT].
This allows [projT1] and [projT2] to be usable with [sigT2].
@@ -231,6 +235,7 @@ Proof.
Qed.
(** Equality of sigma types *)
+
Import EqNotations.
Local Notation "'rew' 'dependent' H 'in' H'"
:= (match H with
@@ -244,18 +249,18 @@ Section sigT.
Local Unset Implicit Arguments.
(** Projecting an equality of a pair to equality of the first components *)
Definition projT1_eq {A} {P : A -> Type} {u v : { a : A & P a }} (p : u = v)
- : projT1 u = projT1 v
- := f_equal (@projT1 _ _) p.
+ : u.1 = v.1
+ := f_equal (fun x => x.1) p.
(** Projecting an equality of a pair to equality of the second components *)
Definition projT2_eq {A} {P : A -> Type} {u v : { a : A & P a }} (p : u = v)
- : rew projT1_eq p in projT2 u = projT2 v
+ : rew projT1_eq p in u.2 = v.2
:= rew dependent p in eq_refl.
(** Equality of [sigT] is itself a [sigT] (forwards-reasoning version) *)
Definition eq_existT_uncurried {A : Type} {P : A -> Type} {u1 v1 : A} {u2 : P u1} {v2 : P v1}
(pq : { p : u1 = v1 & rew p in u2 = v2 })
- : existT _ u1 u2 = existT _ v1 v2.
+ : (u1; u2) = (v1; v2).
Proof.
destruct pq as [p q].
destruct q; simpl in *.
@@ -264,23 +269,55 @@ Section sigT.
(** Equality of [sigT] is itself a [sigT] (backwards-reasoning version) *)
Definition eq_sigT_uncurried {A : Type} {P : A -> Type} (u v : { a : A & P a })
- (pq : { p : projT1 u = projT1 v & rew p in projT2 u = projT2 v })
+ (pq : { p : u.1 = v.1 & rew p in u.2 = v.2 })
: u = v.
Proof.
destruct u as [u1 u2], v as [v1 v2]; simpl in *.
apply eq_existT_uncurried; exact pq.
Defined.
+ Lemma eq_existT_curried {A : Type} {P : A -> Type} {u1 v1 : A} {u2 : P u1} {v2 : P v1}
+ (p : u1 = v1) (q : rew p in u2 = v2) : (u1; u2) = (v1; v2).
+ Proof.
+ destruct p, q. reflexivity.
+ Defined.
+
+ Local Notation "(= u ; v )" := (eq_existT_curried u v) (at level 0, format "(= u ; '/ ' v )").
+
+ Lemma eq_existT_curried_map {A A' P P'} (f:A -> A') (g:forall u:A, P u -> P' (f u))
+ {u1 v1 : A} {u2 : P u1} {v2 : P v1} (p : u1 = v1) (q : rew p in u2 = v2) :
+ f_equal (fun x => (f x.1; g x.1 x.2)) (= p; q) =
+ (= f_equal f p; f_equal_dep2 f g p q).
+ Proof.
+ destruct p, q. reflexivity.
+ Defined.
+
+ Lemma eq_existT_curried_trans {A P} {u1 v1 w1 : A} {u2 : P u1} {v2 : P v1} {w2 : P w1}
+ (p : u1 = v1) (q : rew p in u2 = v2)
+ (p' : v1 = w1) (q': rew p' in v2 = w2) :
+ eq_trans (= p; q) (= p'; q') =
+ (= eq_trans p p'; eq_trans_map p p' q q').
+ Proof.
+ destruct p', q'. reflexivity.
+ Defined.
+
+ Theorem eq_existT_curried_congr {A P} {u1 v1 : A} {u2 : P u1} {v2 : P v1}
+ {p p' : u1 = v1} {q : rew p in u2 = v2} {q': rew p' in u2 = v2}
+ (r : p = p') : rew [fun H => rew H in u2 = v2] r in q = q' -> (= p; q) = (= p'; q').
+ Proof.
+ destruct r, 1. reflexivity.
+ Qed.
+
(** Curried version of proving equality of sigma types *)
Definition eq_sigT {A : Type} {P : A -> Type} (u v : { a : A & P a })
- (p : projT1 u = projT1 v) (q : rew p in projT2 u = projT2 v)
+ (p : u.1 = v.1) (q : rew p in u.2 = v.2)
: u = v
:= eq_sigT_uncurried u v (existT _ p q).
(** Equality of [sigT] when the property is an hProp *)
Definition eq_sigT_hprop {A P} (P_hprop : forall (x : A) (p q : P x), p = q)
(u v : { a : A & P a })
- (p : projT1 u = projT1 v)
+ (p : u.1 = v.1)
: u = v
:= eq_sigT u v p (P_hprop _ _ _).
@@ -289,7 +326,7 @@ Section sigT.
but for simplicity, we don't. *)
Definition eq_sigT_uncurried_iff {A P}
(u v : { a : A & P a })
- : u = v <-> { p : projT1 u = projT1 v & rew p in projT2 u = projT2 v }.
+ : u = v <-> { p : u.1 = v.1 & rew p in u.2 = v.2 }.
Proof.
split; [ intro; subst; exists eq_refl; reflexivity | apply eq_sigT_uncurried ].
Defined.
@@ -305,12 +342,12 @@ Section sigT.
(** Equivalence of equality of [sigT] involving hProps with equality of the first components *)
Definition eq_sigT_hprop_iff {A P} (P_hprop : forall (x : A) (p q : P x), p = q)
(u v : { a : A & P a })
- : u = v <-> (projT1 u = projT1 v)
+ : u = v <-> (u.1 = v.1)
:= conj (fun p => f_equal (@projT1 _ _) p) (eq_sigT_hprop P_hprop u v).
(** Non-dependent classification of equality of [sigT] *)
Definition eq_sigT_nondep {A B : Type} (u v : { a : A & B })
- (p : projT1 u = projT1 v) (q : projT2 u = projT2 v)
+ (p : u.1 = v.1) (q : u.2 = v.2)
: u = v
:= @eq_sigT _ _ u v p (eq_trans (rew_const _ _) q).
@@ -319,8 +356,8 @@ Section sigT.
: rew [fun a => { p : P a & Q a p }] H in u
= existT
(Q y)
- (rew H in projT1 u)
- (rew dependent H in (projT2 u)).
+ (rew H in u.1)
+ (rew dependent H in (u.2)).
Proof.
destruct H, u; reflexivity.
Defined.
@@ -416,12 +453,12 @@ Section sigT2.
: u = v :> { a : A & P a }
:= f_equal _ p.
Definition projT1_of_sigT2_eq {A} {P Q : A -> Type} {u v : { a : A & P a & Q a }} (p : u = v)
- : projT1 u = projT1 v
+ : u.1 = v.1
:= projT1_eq (sigT_of_sigT2_eq p).
(** Projecting an equality of a pair to equality of the second components *)
Definition projT2_of_sigT2_eq {A} {P Q : A -> Type} {u v : { a : A & P a & Q a }} (p : u = v)
- : rew projT1_of_sigT2_eq p in projT2 u = projT2 v
+ : rew projT1_of_sigT2_eq p in u.2 = v.2
:= rew dependent p in eq_refl.
(** Projecting an equality of a pair to equality of the third components *)
@@ -443,8 +480,8 @@ Section sigT2.
(** Equality of [sigT2] is itself a [sigT2] (backwards-reasoning version) *)
Definition eq_sigT2_uncurried {A : Type} {P Q : A -> Type} (u v : { a : A & P a & Q a })
- (pqr : { p : projT1 u = projT1 v
- & rew p in projT2 u = projT2 v & rew p in projT3 u = projT3 v })
+ (pqr : { p : u.1 = v.1
+ & rew p in u.2 = v.2 & rew p in projT3 u = projT3 v })
: u = v.
Proof.
destruct u as [u1 u2 u3], v as [v1 v2 v3]; simpl in *.
@@ -453,8 +490,8 @@ Section sigT2.
(** Curried version of proving equality of sigma types *)
Definition eq_sigT2 {A : Type} {P Q : A -> Type} (u v : { a : A & P a & Q a })
- (p : projT1 u = projT1 v)
- (q : rew p in projT2 u = projT2 v)
+ (p : u.1 = v.1)
+ (q : rew p in u.2 = v.2)
(r : rew p in projT3 u = projT3 v)
: u = v
:= eq_sigT2_uncurried u v (existT2 _ _ p q r).
@@ -472,8 +509,8 @@ Section sigT2.
Definition eq_sigT2_uncurried_iff {A P Q}
(u v : { a : A & P a & Q a })
: u = v
- <-> { p : projT1 u = projT1 v
- & rew p in projT2 u = projT2 v & rew p in projT3 u = projT3 v }.
+ <-> { p : u.1 = v.1
+ & rew p in u.2 = v.2 & rew p in projT3 u = projT3 v }.
Proof.
split; [ intro; subst; exists eq_refl; reflexivity | apply eq_sigT2_uncurried ].
Defined.
@@ -498,7 +535,7 @@ Section sigT2.
(** Non-dependent classification of equality of [sigT] *)
Definition eq_sigT2_nondep {A B C : Type} (u v : { a : A & B & C })
- (p : projT1 u = projT1 v) (q : projT2 u = projT2 v) (r : projT3 u = projT3 v)
+ (p : u.1 = v.1) (q : u.2 = v.2) (r : projT3 u = projT3 v)
: u = v
:= @eq_sigT2 _ _ _ u v p (eq_trans (rew_const _ _) q) (eq_trans (rew_const _ _) r).
@@ -510,8 +547,8 @@ Section sigT2.
= existT2
(Q y)
(R y)
- (rew H in projT1 u)
- (rew dependent H in projT2 u)
+ (rew H in u.1)
+ (rew dependent H in u.2)
(rew dependent H in projT3 u).
Proof.
destruct H, u; reflexivity.
@@ -697,7 +734,7 @@ End Choice_lemmas.
Section Dependent_choice_lemmas.
- Variables X : Set.
+ Variable X : Set.
Variable R : X -> X -> Prop.
Lemma dependent_choice :
diff --git a/theories/Lists/List.v b/theories/Lists/List.v
index ca5f154e95..4614d215eb 100644
--- a/theories/Lists/List.v
+++ b/theories/Lists/List.v
@@ -1023,6 +1023,18 @@ Proof.
intros; rewrite H by intuition; rewrite IHl; auto.
Qed.
+Lemma ext_in_map :
+ forall (A B : Type)(f g:A->B) l, map f l = map g l -> forall a, In a l -> f a = g a.
+Proof. induction l; intros [=] ? []; subst; auto. Qed.
+
+Arguments ext_in_map [A B f g l].
+
+Lemma map_ext_in_iff :
+ forall (A B : Type)(f g:A->B) l, map f l = map g l <-> forall a, In a l -> f a = g a.
+Proof. split; [apply ext_in_map | apply map_ext_in]. Qed.
+
+Arguments map_ext_in_iff [A B f g l].
+
Lemma map_ext :
forall (A B : Type)(f g:A->B), (forall a, f a = g a) -> forall l, map f l = map g l.
Proof.
@@ -1717,6 +1729,32 @@ Section Cutting.
end
end.
+ Lemma firstn_skipn_comm : forall m n l,
+ firstn m (skipn n l) = skipn n (firstn (n + m) l).
+ Proof. now intros m; induction n; intros []; simpl; destruct m. Qed.
+
+ Lemma skipn_firstn_comm : forall m n l,
+ skipn m (firstn n l) = firstn (n - m) (skipn m l).
+ Proof. now induction m; intros [] []; simpl; rewrite ?firstn_nil. Qed.
+
+ Lemma skipn_O : forall l, skipn 0 l = l.
+ Proof. reflexivity. Qed.
+
+ Lemma skipn_nil : forall n, skipn n ([] : list A) = [].
+ Proof. now intros []. Qed.
+
+ Lemma skipn_cons n a l: skipn (S n) (a::l) = skipn n l.
+ Proof. reflexivity. Qed.
+
+ Lemma skipn_none : forall l, skipn (length l) l = [].
+ Proof. now induction l. Qed.
+
+ Lemma skipn_all2 n: forall l, length l <= n -> skipn n l = [].
+ Proof.
+ intros l L%Nat.sub_0_le; rewrite <-(firstn_all l) at 1.
+ now rewrite skipn_firstn_comm, L.
+ Qed.
+
Lemma firstn_skipn : forall n l, firstn n l ++ skipn n l = l.
Proof.
induction n.
@@ -1730,6 +1768,51 @@ Section Cutting.
induction n; destruct l; simpl; auto.
Qed.
+ Lemma skipn_length n :
+ forall l, length (skipn n l) = length l - n.
+ Proof.
+ induction n.
+ - intros l; simpl; rewrite Nat.sub_0_r; reflexivity.
+ - destruct l; simpl; auto.
+ Qed.
+
+ Lemma skipn_all l: skipn (length l) l = nil.
+ Proof. now induction l. Qed.
+
+ Lemma skipn_app n : forall l1 l2,
+ skipn n (l1 ++ l2) = (skipn n l1) ++ (skipn (n - length l1) l2).
+ Proof. induction n; auto; intros [|]; simpl; auto. Qed.
+
+ Lemma firstn_skipn_rev: forall x l,
+ firstn x l = rev (skipn (length l - x) (rev l)).
+ Proof.
+ intros x l; rewrite <-(firstn_skipn x l) at 3.
+ rewrite rev_app_distr, skipn_app, rev_app_distr, rev_length,
+ skipn_length, Nat.sub_diag; simpl; rewrite rev_involutive.
+ rewrite <-app_nil_r at 1; f_equal; symmetry; apply length_zero_iff_nil.
+ repeat rewrite rev_length, skipn_length; apply Nat.sub_diag.
+ Qed.
+
+ Lemma firstn_rev: forall x l,
+ firstn x (rev l) = rev (skipn (length l - x) l).
+ Proof.
+ now intros x l; rewrite firstn_skipn_rev, rev_involutive, rev_length.
+ Qed.
+
+ Lemma skipn_rev: forall x l,
+ skipn x (rev l) = rev (firstn (length l - x) l).
+ Proof.
+ intros x l; rewrite firstn_skipn_rev, rev_involutive, <-rev_length.
+ destruct (Nat.le_ge_cases (length (rev l)) x) as [L | L].
+ - rewrite skipn_all2; [apply Nat.sub_0_le in L | trivial].
+ now rewrite L, Nat.sub_0_r, skipn_none.
+ - replace (length (rev l) - (length (rev l) - x))
+ with (length (rev l) + x - length (rev l)).
+ rewrite minus_plus. reflexivity.
+ rewrite <- (Nat.sub_add _ _ L) at 2.
+ now rewrite <-!(Nat.add_comm x), <-minus_plus_simpl_l_reverse.
+ Qed.
+
Lemma removelast_firstn : forall n l, n < length l ->
removelast (firstn (S n) l) = firstn n l.
Proof.
@@ -2073,6 +2156,14 @@ Section NatSeq.
rewrite in_seq. intros (H,_). apply (Lt.lt_irrefl _ H).
Qed.
+ Lemma seq_app : forall len1 len2 start,
+ seq start (len1 + len2) = seq start len1 ++ seq (start + len1) len2.
+ Proof.
+ induction len1 as [|len1' IHlen]; intros; simpl in *.
+ - now rewrite Nat.add_0_r.
+ - now rewrite Nat.add_succ_r, IHlen.
+ Qed.
+
End NatSeq.
Section Exists_Forall.
diff --git a/theories/MSets/MSetAVL.v b/theories/MSets/MSetAVL.v
index b966f217aa..aec88f93bf 100644
--- a/theories/MSets/MSetAVL.v
+++ b/theories/MSets/MSetAVL.v
@@ -340,6 +340,8 @@ Functional Scheme union_ind := Induction for union Sort Prop.
(** Notations and helper lemma about pairs and triples *)
+Declare Scope pair_scope.
+
Notation "s #1" := (fst s) (at level 9, format "s '#1'") : pair_scope.
Notation "s #2" := (snd s) (at level 9, format "s '#2'") : pair_scope.
Notation "t #l" := (t_left t) (at level 9, format "t '#l'") : pair_scope.
diff --git a/theories/MSets/MSetEqProperties.v b/theories/MSets/MSetEqProperties.v
index 1ee098cb07..4f2fdcf94c 100644
--- a/theories/MSets/MSetEqProperties.v
+++ b/theories/MSets/MSetEqProperties.v
@@ -333,7 +333,7 @@ Proof.
auto with set.
Qed.
-(* caracterisation of [union] via [subset] *)
+(* characterisation of [union] via [subset] *)
Lemma union_subset_1: subset s (union s s')=true.
Proof.
@@ -408,7 +408,7 @@ intros; apply equal_1; apply inter_add_2.
rewrite not_mem_iff; auto.
Qed.
-(* caracterisation of [union] via [subset] *)
+(* characterisation of [union] via [subset] *)
Lemma inter_subset_1: subset (inter s s') s=true.
Proof.
diff --git a/theories/MSets/MSetGenTree.v b/theories/MSets/MSetGenTree.v
index 9d2a73ed0f..95868861fa 100644
--- a/theories/MSets/MSetGenTree.v
+++ b/theories/MSets/MSetGenTree.v
@@ -13,7 +13,7 @@
This module factorizes common parts in implementations
of finite sets as AVL trees and as Red-Black trees. The nodes
of the trees defined here include an generic information
- parameter, that will be the heigth in AVL trees and the color
+ parameter, that will be the height in AVL trees and the color
in Red-Black trees. Without more details here about these
information parameters, trees here are not known to be
well-balanced, but simply binary-search-trees.
diff --git a/theories/NArith/BinNat.v b/theories/NArith/BinNat.v
index 5d3ec5abc7..bd27f94abd 100644
--- a/theories/NArith/BinNat.v
+++ b/theories/NArith/BinNat.v
@@ -930,6 +930,8 @@ Bind Scope N_scope with N.t N.
(** Exportation of notations *)
+Numeral Notation N N.of_uint N.to_uint : N_scope.
+
Infix "+" := N.add : N_scope.
Infix "-" := N.sub : N_scope.
Infix "*" := N.mul : N_scope.
diff --git a/theories/NArith/BinNatDef.v b/theories/NArith/BinNatDef.v
index 5de75537cb..be12fffaaf 100644
--- a/theories/NArith/BinNatDef.v
+++ b/theories/NArith/BinNatDef.v
@@ -13,6 +13,10 @@ Require Import BinPos.
Local Open Scope N_scope.
+Local Notation "0" := N0.
+Local Notation "1" := (Npos 1).
+Local Notation "2" := (Npos 2).
+
(**********************************************************************)
(** * Binary natural numbers, definitions of operations *)
(**********************************************************************)
@@ -398,4 +402,9 @@ Definition to_uint n :=
Definition to_int n := Decimal.Pos (to_uint n).
+Numeral Notation N of_uint to_uint : N_scope.
+
End N.
+
+(** Re-export the notation for those who just [Import NatIntDef] *)
+Numeral Notation N N.of_uint N.to_uint : N_scope.
diff --git a/theories/NArith/Ndigits.v b/theories/NArith/Ndigits.v
index 68a98e4292..a2a2430e91 100644
--- a/theories/NArith/Ndigits.v
+++ b/theories/NArith/Ndigits.v
@@ -578,6 +578,7 @@ Qed.
(** To state nonetheless a second result about composition of
conversions, we define a conversion on a given number of bits : *)
+#[deprecated(since = "8.9.0", note = "Use N2Bv_sized instead.")]
Fixpoint N2Bv_gen (n:nat)(a:N) : Bvector n :=
match n return Bvector n with
| 0 => Bnil
@@ -705,3 +706,10 @@ Proof with simpl; auto.
destruct (Bv2N n v) as [|[]];
rewrite <- IHv...
Qed.
+
+Lemma N2Bv_N2Bv_sized_above (a : N) (k : nat) :
+ N2Bv_sized (N.size_nat a + k) a = N2Bv a ++ Bvect_false k.
+Proof with auto.
+ destruct a...
+ induction p; simpl; f_equal...
+Qed.
diff --git a/theories/Numbers/AltBinNotations.v b/theories/Numbers/AltBinNotations.v
new file mode 100644
index 0000000000..c7e3999691
--- /dev/null
+++ b/theories/Numbers/AltBinNotations.v
@@ -0,0 +1,69 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+(** * Alternative Binary Numeral Notations *)
+
+(** Faster but less safe parsers and printers of [positive], [N], [Z]. *)
+
+(** By default, literals in types [positive], [N], [Z] are parsed and
+ printed via the [Numeral Notation] command, by conversion from/to
+ the [Decimal.int] representation. When working with numbers with
+ thousands of digits and more, conversion from/to [Decimal.int] can
+ become significantly slow. If that becomes a problem for your
+ development, this file provides some alternative [Numeral
+ Notation] commmands that use [Z] as bridge type. To enable these
+ commands, just be sure to [Require] this file after other files
+ defining numeral notations.
+
+ Note: up to Coq 8.8, literals in types [positive], [N], [Z] were
+ parsed and printed using a native ML library of arbitrary
+ precision integers named bigint.ml. From 8.9, the default is to
+ parse and print using a Coq library converting sequences of
+ digits, hence reducing the amount of ML code to trust. But this
+ method is slower. This file then gives access to the legacy
+ method, trading efficiency against a larger ML trust base relying
+ on bigint.ml. *)
+
+Require Import BinNums.
+
+(** [positive] *)
+
+Definition pos_of_z z :=
+ match z with
+ | Zpos p => Some p
+ | _ => None
+ end.
+
+Definition pos_to_z p := Zpos p.
+
+Numeral Notation positive pos_of_z pos_to_z : positive_scope.
+
+(** [N] *)
+
+Definition n_of_z z :=
+ match z with
+ | Z0 => Some N0
+ | Zpos p => Some (Npos p)
+ | Zneg _ => None
+ end.
+
+Definition n_to_z n :=
+ match n with
+ | N0 => Z0
+ | Npos p => Zpos p
+ end.
+
+Numeral Notation N n_of_z n_to_z : N_scope.
+
+(** [Z] *)
+
+Definition z_of_z (z:Z) := z.
+
+Numeral Notation Z z_of_z z_of_z : Z_scope.
diff --git a/theories/Numbers/BinNums.v b/theories/Numbers/BinNums.v
index d5eb4f2681..7b6740e94b 100644
--- a/theories/Numbers/BinNums.v
+++ b/theories/Numbers/BinNums.v
@@ -12,21 +12,18 @@
Set Implicit Arguments.
-Declare ML Module "positive_syntax_plugin".
-Declare ML Module "n_syntax_plugin".
-Declare ML Module "z_syntax_plugin".
-
(** [positive] is a datatype representing the strictly positive integers
in a binary way. Starting from 1 (represented by [xH]), one can
add a new least significant digit via [xO] (digit 0) or [xI] (digit 1).
- Numbers in [positive] can also be denoted using a decimal notation;
- e.g. [6%positive] abbreviates [xO (xI xH)] *)
+ Numbers in [positive] will also be denoted using a decimal notation;
+ e.g. [6%positive] will abbreviate [xO (xI xH)] *)
Inductive positive : Set :=
| xI : positive -> positive
| xO : positive -> positive
| xH : positive.
+Declare Scope positive_scope.
Delimit Scope positive_scope with positive.
Bind Scope positive_scope with positive.
Arguments xO _%positive.
@@ -34,13 +31,14 @@ Arguments xI _%positive.
(** [N] is a datatype representing natural numbers in a binary way,
by extending the [positive] datatype with a zero.
- Numbers in [N] can also be denoted using a decimal notation;
- e.g. [6%N] abbreviates [Npos (xO (xI xH))] *)
+ Numbers in [N] will also be denoted using a decimal notation;
+ e.g. [6%N] will abbreviate [Npos (xO (xI xH))] *)
Inductive N : Set :=
| N0 : N
| Npos : positive -> N.
+Declare Scope N_scope.
Delimit Scope N_scope with N.
Bind Scope N_scope with N.
Arguments Npos _%positive.
@@ -49,14 +47,15 @@ Arguments Npos _%positive.
An integer is either zero or a strictly positive number
(coded as a [positive]) or a strictly negative number
(whose opposite is stored as a [positive] value).
- Numbers in [Z] can also be denoted using a decimal notation;
- e.g. [(-6)%Z] abbreviates [Zneg (xO (xI xH))] *)
+ Numbers in [Z] will also be denoted using a decimal notation;
+ e.g. [(-6)%Z] will abbreviate [Zneg (xO (xI xH))] *)
Inductive Z : Set :=
| Z0 : Z
| Zpos : positive -> Z
| Zneg : positive -> Z.
+Declare Scope Z_scope.
Delimit Scope Z_scope with Z.
Bind Scope Z_scope with Z.
Arguments Zpos _%positive.
diff --git a/theories/Numbers/Cyclic/Int31/Cyclic31.v b/theories/Numbers/Cyclic/Int31/Cyclic31.v
index bd4f0279d4..4a1f24b95e 100644
--- a/theories/Numbers/Cyclic/Int31/Cyclic31.v
+++ b/theories/Numbers/Cyclic/Int31/Cyclic31.v
@@ -21,9 +21,7 @@ Require Import Znumtheory.
Require Import Zgcd_alt.
Require Import Zpow_facts.
Require Import CyclicAxioms.
-Require Import ROmega.
-
-Declare ML Module "int31_syntax_plugin".
+Require Import Lia.
Local Open Scope nat_scope.
Local Open Scope int31_scope.
@@ -128,7 +126,7 @@ Section Basics.
Lemma nshiftl_S_tail :
forall n x, nshiftl x (S n) = nshiftl (shiftl x) n.
- Proof.
+ Proof.
intros n; elim n; simpl; intros; now f_equal.
Qed.
@@ -1239,7 +1237,7 @@ Section Int31_Specs.
destruct (Z_lt_le_dec (X+Y) wB).
contradict H1; auto using Zmod_small with zarith.
rewrite <- (Z_mod_plus_full (X+Y) (-1) wB).
- rewrite Zmod_small; romega.
+ rewrite Zmod_small; lia.
generalize (Z.compare_eq ((X+Y) mod wB) (X+Y)); intros Heq.
destruct Z.compare; intros;
@@ -1263,7 +1261,7 @@ Section Int31_Specs.
destruct (Z_lt_le_dec (X+Y+1) wB).
contradict H1; auto using Zmod_small with zarith.
rewrite <- (Z_mod_plus_full (X+Y+1) (-1) wB).
- rewrite Zmod_small; romega.
+ rewrite Zmod_small; lia.
generalize (Z.compare_eq ((X+Y+1) mod wB) (X+Y+1)); intros Heq.
destruct Z.compare; intros;
@@ -1301,8 +1299,8 @@ Section Int31_Specs.
unfold interp_carry; rewrite phi_phi_inv, Z.compare_eq_iff; intros.
destruct (Z_lt_le_dec (X-Y) 0).
rewrite <- (Z_mod_plus_full (X-Y) 1 wB).
- rewrite Zmod_small; romega.
- contradict H1; apply Zmod_small; romega.
+ rewrite Zmod_small; lia.
+ contradict H1; apply Zmod_small; lia.
generalize (Z.compare_eq ((X-Y) mod wB) (X-Y)); intros Heq.
destruct Z.compare; intros;
@@ -1320,8 +1318,8 @@ Section Int31_Specs.
unfold interp_carry; rewrite phi_phi_inv, Z.compare_eq_iff; intros.
destruct (Z_lt_le_dec (X-Y-1) 0).
rewrite <- (Z_mod_plus_full (X-Y-1) 1 wB).
- rewrite Zmod_small; romega.
- contradict H1; apply Zmod_small; romega.
+ rewrite Zmod_small; lia.
+ contradict H1; apply Zmod_small; lia.
generalize (Z.compare_eq ((X-Y-1) mod wB) (X-Y-1)); intros Heq.
destruct Z.compare; intros;
@@ -1358,7 +1356,7 @@ Section Int31_Specs.
change [|1|] with 1; change [|0|] with 0.
rewrite <- (Z_mod_plus_full (0-[|x|]) 1 wB).
rewrite Zminus_mod_idemp_l.
- rewrite Zmod_small; generalize (phi_bounded x); romega.
+ rewrite Zmod_small; generalize (phi_bounded x); lia.
Qed.
Lemma spec_pred_c : forall x, [-|sub31c x 1|] = [|x|] - 1.
diff --git a/theories/Numbers/Cyclic/Int31/Int31.v b/theories/Numbers/Cyclic/Int31/Int31.v
index 9f8da831d8..3a2503d6b7 100644
--- a/theories/Numbers/Cyclic/Int31/Int31.v
+++ b/theories/Numbers/Cyclic/Int31/Int31.v
@@ -19,7 +19,7 @@ Require Export DoubleType.
(** This file contains basic definitions of a 31-bit integer
arithmetic. In fact it is more general than that. The only reason
- for this use of 31 is the underlying mecanism for hardware-efficient
+ for this use of 31 is the underlying mechanism for hardware-efficient
computations by A. Spiwack. Apart from this, a switch to, say,
63-bit integers is now just a matter of replacing every occurrences
of 31 by 63. This is actually made possible by the use of
@@ -45,9 +45,11 @@ Inductive int31 : Type := I31 : digits31 int31.
(* spiwack: Registration of the type of integers, so that the matchs in
the functions below perform dynamic decompilation (otherwise some segfault
occur when they are applied to one non-closed term and one closed term). *)
-Register digits as int31 bits in "coq_int31" by True.
-Register int31 as int31 type in "coq_int31" by True.
+Register digits as int31.bits.
+Register int31 as int31.type.
+Declare Scope int31_scope.
+Declare ML Module "int31_syntax_plugin".
Delimit Scope int31_scope with int31.
Bind Scope int31_scope with int31.
Local Open Scope int31_scope.
@@ -343,21 +345,21 @@ Definition lor31 n m := phi_inv (Z.lor (phi n) (phi m)).
Definition land31 n m := phi_inv (Z.land (phi n) (phi m)).
Definition lxor31 n m := phi_inv (Z.lxor (phi n) (phi m)).
-Register add31 as int31 plus in "coq_int31" by True.
-Register add31c as int31 plusc in "coq_int31" by True.
-Register add31carryc as int31 pluscarryc in "coq_int31" by True.
-Register sub31 as int31 minus in "coq_int31" by True.
-Register sub31c as int31 minusc in "coq_int31" by True.
-Register sub31carryc as int31 minuscarryc in "coq_int31" by True.
-Register mul31 as int31 times in "coq_int31" by True.
-Register mul31c as int31 timesc in "coq_int31" by True.
-Register div3121 as int31 div21 in "coq_int31" by True.
-Register div31 as int31 diveucl in "coq_int31" by True.
-Register compare31 as int31 compare in "coq_int31" by True.
-Register addmuldiv31 as int31 addmuldiv in "coq_int31" by True.
-Register lor31 as int31 lor in "coq_int31" by True.
-Register land31 as int31 land in "coq_int31" by True.
-Register lxor31 as int31 lxor in "coq_int31" by True.
+Register add31 as int31.plus.
+Register add31c as int31.plusc.
+Register add31carryc as int31.pluscarryc.
+Register sub31 as int31.minus.
+Register sub31c as int31.minusc.
+Register sub31carryc as int31.minuscarryc.
+Register mul31 as int31.times.
+Register mul31c as int31.timesc.
+Register div3121 as int31.div21.
+Register div31 as int31.diveucl.
+Register compare31 as int31.compare.
+Register addmuldiv31 as int31.addmuldiv.
+Register lor31 as int31.lor.
+Register land31 as int31.land.
+Register lxor31 as int31.lxor.
Definition lnot31 n := lxor31 Tn n.
Definition ldiff31 n m := land31 n (lnot31 m).
@@ -483,5 +485,5 @@ Definition tail031 (i:int31) :=
end)
i On.
-Register head031 as int31 head0 in "coq_int31" by True.
-Register tail031 as int31 tail0 in "coq_int31" by True.
+Register head031 as int31.head0.
+Register tail031 as int31.tail0.
diff --git a/theories/Numbers/Integer/Abstract/ZBits.v b/theories/Numbers/Integer/Abstract/ZBits.v
index 2da4452819..4aabda77ee 100644
--- a/theories/Numbers/Integer/Abstract/ZBits.v
+++ b/theories/Numbers/Integer/Abstract/ZBits.v
@@ -80,7 +80,7 @@ Proof.
now apply testbit_even_succ.
Qed.
-(** Alternative caracterisations of [testbit] *)
+(** Alternative characterisations of [testbit] *)
(** This concise equation could have been taken as specification
for testbit in the interface, but it would have been hard to
@@ -102,10 +102,10 @@ Proof.
left. destruct b; split; simpl; order'.
Qed.
-(** This caracterisation that uses only basic operations and
+(** This characterisation that uses only basic operations and
power was initially taken as specification for testbit.
We describe [a] as having a low part and a high part, with
- the corresponding bit in the middle. This caracterisation
+ the corresponding bit in the middle. This characterisation
is moderatly complex to implement, but also moderately
usable... *)
diff --git a/theories/Numbers/Integer/Abstract/ZDivEucl.v b/theories/Numbers/Integer/Abstract/ZDivEucl.v
index d7f25a6613..a70ecd19d8 100644
--- a/theories/Numbers/Integer/Abstract/ZDivEucl.v
+++ b/theories/Numbers/Integer/Abstract/ZDivEucl.v
@@ -13,7 +13,7 @@ Require Import ZAxioms ZMulOrder ZSgnAbs NZDiv.
(** * Euclidean Division for integers, Euclid convention
We use here the "usual" formulation of the Euclid Theorem
- [forall a b, b<>0 -> exists b q, a = b*q+r /\ 0 < r < |b| ]
+ [forall a b, b<>0 -> exists r q, a = b*q+r /\ 0 <= r < |b| ]
The outcome of the modulo function is hence always positive.
This corresponds to convention "E" in the following paper:
@@ -46,6 +46,7 @@ Module ZEuclidProp
(** We put notations in a scope, to avoid warnings about
redefinitions of notations *)
+ Declare Scope euclid.
Infix "/" := D.div : euclid.
Infix "mod" := D.modulo : euclid.
Local Open Scope euclid.
diff --git a/theories/Numbers/Integer/NatPairs/ZNatPairs.v b/theories/Numbers/Integer/NatPairs/ZNatPairs.v
index 4b2d5c13b5..995d96b314 100644
--- a/theories/Numbers/Integer/NatPairs/ZNatPairs.v
+++ b/theories/Numbers/Integer/NatPairs/ZNatPairs.v
@@ -13,15 +13,18 @@
Require Import NSub ZAxioms.
Require Export Ring.
+Declare Scope pair_scope.
+Local Open Scope pair_scope.
+
Notation "s #1" := (fst s) (at level 9, format "s '#1'") : pair_scope.
Notation "s #2" := (snd s) (at level 9, format "s '#2'") : pair_scope.
-Local Open Scope pair_scope.
Module ZPairsAxiomsMod (Import N : NAxiomsMiniSig) <: ZAxiomsMiniSig.
Module Import NProp.
Include NSubProp N.
End NProp.
+Declare Scope NScope.
Delimit Scope NScope with N.
Bind Scope NScope with N.t.
Infix "==" := N.eq (at level 70) : NScope.
@@ -73,6 +76,7 @@ Definition max (n m : t) : t := (max (n#1 + m#2) (m#1 + n#2), n#2 + m#2).
End Z.
+Declare Scope ZScope.
Delimit Scope ZScope with Z.
Bind Scope ZScope with Z.t.
Infix "==" := Z.eq (at level 70) : ZScope.
diff --git a/theories/Numbers/NatInt/NZDomain.v b/theories/Numbers/NatInt/NZDomain.v
index 3d0c005fd1..acebfcf1d2 100644
--- a/theories/Numbers/NatInt/NZDomain.v
+++ b/theories/Numbers/NatInt/NZDomain.v
@@ -220,8 +220,10 @@ End NZDomainProp.
Module NZOfNat (Import NZ:NZDomainSig').
Definition ofnat (n : nat) : t := (S^n) 0.
-Notation "[ n ]" := (ofnat n) (at level 7) : ofnat.
+
+Declare Scope ofnat.
Local Open Scope ofnat.
+Notation "[ n ]" := (ofnat n) (at level 7) : ofnat.
Lemma ofnat_zero : [O] == 0.
Proof.
diff --git a/theories/Numbers/Natural/Abstract/NBits.v b/theories/Numbers/Natural/Abstract/NBits.v
index e1391f5990..90663de3f2 100644
--- a/theories/Numbers/Natural/Abstract/NBits.v
+++ b/theories/Numbers/Natural/Abstract/NBits.v
@@ -78,7 +78,7 @@ Proof.
apply testbit_even_succ, le_0_l.
Qed.
-(** Alternative caracterisations of [testbit] *)
+(** Alternative characterisations of [testbit] *)
(** This concise equation could have been taken as specification
for testbit in the interface, but it would have been hard to
@@ -99,10 +99,10 @@ Proof.
destruct b; order'.
Qed.
-(** This caracterisation that uses only basic operations and
+(** This characterisation that uses only basic operations and
power was initially taken as specification for testbit.
We describe [a] as having a low part and a high part, with
- the corresponding bit in the middle. This caracterisation
+ the corresponding bit in the middle. This characterisation
is moderatly complex to implement, but also moderately
usable... *)
diff --git a/theories/PArith/BinPos.v b/theories/PArith/BinPos.v
index 000d895e10..dcaae1606d 100644
--- a/theories/PArith/BinPos.v
+++ b/theories/PArith/BinPos.v
@@ -1871,6 +1871,8 @@ Bind Scope positive_scope with Pos.t positive.
(** Exportation of notations *)
+Numeral Notation positive Pos.of_int Pos.to_uint : positive_scope.
+
Infix "+" := Pos.add : positive_scope.
Infix "-" := Pos.sub : positive_scope.
Infix "*" := Pos.mul : positive_scope.
diff --git a/theories/PArith/BinPosDef.v b/theories/PArith/BinPosDef.v
index 070314746a..7f30733559 100644
--- a/theories/PArith/BinPosDef.v
+++ b/theories/PArith/BinPosDef.v
@@ -26,6 +26,8 @@ Require Export BinNums.
for the number 6 (which is 110 in binary notation).
*)
+Local Notation "1" := xH.
+
Notation "p ~ 1" := (xI p)
(at level 7, left associativity, format "p '~' '1'") : positive_scope.
Notation "p ~ 0" := (xO p)
@@ -325,14 +327,14 @@ Definition sqrtrem_step (f g:positive->positive) p :=
let r' := g (f r) in
if s' <=? r' then (s~1, sub_mask r' s')
else (s~0, IsPos r')
- | (s,_) => (s~0, sub_mask (g (f 1)) 4)
+ | (s,_) => (s~0, sub_mask (g (f 1)) 1~0~0)
end.
Fixpoint sqrtrem p : positive * mask :=
match p with
| 1 => (1,IsNul)
- | 2 => (1,IsPos 1)
- | 3 => (1,IsPos 2)
+ | 1~0 => (1,IsPos 1)
+ | 1~1 => (1,IsPos 1~0)
| p~0~0 => sqrtrem_step xO xO (sqrtrem p)
| p~0~1 => sqrtrem_step xO xI (sqrtrem p)
| p~1~0 => sqrtrem_step xI xO (sqrtrem p)
@@ -614,4 +616,9 @@ Definition to_uint p := Decimal.rev (to_little_uint p).
Definition to_int n := Decimal.Pos (to_uint n).
+Numeral Notation positive of_int to_uint : positive_scope.
+
End Pos.
+
+(** Re-export the notation for those who just [Import BinPosDef] *)
+Numeral Notation positive Pos.of_int Pos.to_uint : positive_scope.
diff --git a/theories/Program/Basics.v b/theories/Program/Basics.v
index f55093ed48..c2316689fc 100644
--- a/theories/Program/Basics.v
+++ b/theories/Program/Basics.v
@@ -28,6 +28,8 @@ Definition compose {A B C} (g : B -> C) (f : A -> B) :=
Hint Unfold compose.
+Declare Scope program_scope.
+
Notation " g ∘ f " := (compose g f)
(at level 40, left associativity) : program_scope.
diff --git a/theories/Program/Tactics.v b/theories/Program/Tactics.v
index bc83881849..edbae6534a 100644
--- a/theories/Program/Tactics.v
+++ b/theories/Program/Tactics.v
@@ -326,7 +326,7 @@ Ltac program_solve_wf :=
Create HintDb program discriminated.
-Ltac program_simpl := program_simplify ; try typeclasses eauto with program ; try program_solve_wf.
+Ltac program_simpl := program_simplify ; try typeclasses eauto 10 with program ; try program_solve_wf.
Obligation Tactic := program_simpl.
diff --git a/theories/Program/Utils.v b/theories/Program/Utils.v
index 78c36dc7d1..c51cacac68 100644
--- a/theories/Program/Utils.v
+++ b/theories/Program/Utils.v
@@ -20,12 +20,13 @@ Notation "{ ( x , y ) : A | P }" :=
(sig (fun anonymous : A => let (x,y) := anonymous in P))
(x ident, y ident, at level 10) : type_scope.
+Declare Scope program_scope.
+Delimit Scope program_scope with prg.
+
(** Generates an obligation to prove False. *)
Notation " ! " := (False_rect _ _) : program_scope.
-Delimit Scope program_scope with prg.
-
(** Abbreviation for first projection and hiding of proofs of subset objects. *)
Notation " ` t " := (proj1_sig t) (at level 10, t at next level) : program_scope.
diff --git a/theories/QArith/QArith_base.v b/theories/QArith/QArith_base.v
index 35706e7fa2..139c4bf432 100644
--- a/theories/QArith/QArith_base.v
+++ b/theories/QArith/QArith_base.v
@@ -18,6 +18,7 @@ Require Export Morphisms Setoid Bool.
Record Q : Set := Qmake {Qnum : Z; Qden : positive}.
+Declare Scope Q_scope.
Delimit Scope Q_scope with Q.
Bind Scope Q_scope with Q.
Arguments Qmake _%Z _%positive.
diff --git a/theories/QArith/Qcanon.v b/theories/QArith/Qcanon.v
index 1510a7b825..81c318138e 100644
--- a/theories/QArith/Qcanon.v
+++ b/theories/QArith/Qcanon.v
@@ -18,6 +18,7 @@ Require Import Eqdep_dec.
Record Qc : Set := Qcmake { this :> Q ; canon : Qred this = this }.
+Declare Scope Qc_scope.
Delimit Scope Qc_scope with Qc.
Bind Scope Qc_scope with Qc.
Arguments Qcmake this%Q _.
diff --git a/theories/Reals/Ranalysis1.v b/theories/Reals/Ranalysis1.v
index 36ac738ca6..9f8039ec9d 100644
--- a/theories/Reals/Ranalysis1.v
+++ b/theories/Reals/Ranalysis1.v
@@ -28,6 +28,7 @@ Definition div_real_fct (a:R) f (x:R) : R := a / f x.
Definition comp f1 f2 (x:R) : R := f1 (f2 x).
Definition inv_fct f (x:R) : R := / f x.
+Declare Scope Rfun_scope.
Delimit Scope Rfun_scope with F.
Arguments plus_fct (f1 f2)%F x%R.
diff --git a/theories/Reals/Raxioms.v b/theories/Reals/Raxioms.v
index 6019d4faf1..a2818371e9 100644
--- a/theories/Reals/Raxioms.v
+++ b/theories/Reals/Raxioms.v
@@ -14,6 +14,7 @@
Require Export ZArith_base.
Require Export Rdefinitions.
+Declare Scope R_scope.
Local Open Scope R_scope.
(*********************************************************)
diff --git a/theories/Reals/Rdefinitions.v b/theories/Reals/Rdefinitions.v
index 857b4ec33b..932fcddaf5 100644
--- a/theories/Reals/Rdefinitions.v
+++ b/theories/Reals/Rdefinitions.v
@@ -12,12 +12,15 @@
(** Definitions for the axiomatization *)
(*********************************************************)
-Declare ML Module "r_syntax_plugin".
Require Export ZArith_base.
Parameter R : Set.
-(* Declare Scope positive_scope with Key R *)
+(* Declare primitive numeral notations for Scope R_scope *)
+Declare Scope R_scope.
+Declare ML Module "r_syntax_plugin".
+
+(* Declare Scope R_scope with Key R *)
Delimit Scope R_scope with R.
(* Automatically open scope R_scope for arguments of type R *)
diff --git a/theories/Reals/Rsqrt_def.v b/theories/Reals/Rsqrt_def.v
index 6a3dd97656..9b8dd1db0b 100644
--- a/theories/Reals/Rsqrt_def.v
+++ b/theories/Reals/Rsqrt_def.v
@@ -392,7 +392,7 @@ Definition cond_positivity (x:R) : bool :=
| right _ => false
end.
-(** Sequential caracterisation of continuity *)
+(** Sequential characterisation of continuity *)
Lemma continuity_seq :
forall (f:R -> R) (Un:nat -> R) (l:R),
continuity_pt f l -> Un_cv Un l -> Un_cv (fun i:nat => f (Un i)) (f l).
diff --git a/theories/Strings/Ascii.v b/theories/Strings/Ascii.v
index 31a7fb8ad6..3f676c1888 100644
--- a/theories/Strings/Ascii.v
+++ b/theories/Strings/Ascii.v
@@ -13,7 +13,6 @@
Adapted to Coq V8 by the Coq Development Team *)
Require Import Bool BinPos BinNat PeanoNat Nnat.
-Declare ML Module "ascii_syntax_plugin".
(** * Definition of ascii characters *)
@@ -21,6 +20,8 @@ Declare ML Module "ascii_syntax_plugin".
Inductive ascii : Set := Ascii (_ _ _ _ _ _ _ _ : bool).
+Declare Scope char_scope.
+Declare ML Module "ascii_syntax_plugin".
Delimit Scope char_scope with char.
Bind Scope char_scope with ascii.
diff --git a/theories/Strings/String.v b/theories/Strings/String.v
index be9a10c6dc..b27474ef25 100644
--- a/theories/Strings/String.v
+++ b/theories/Strings/String.v
@@ -15,7 +15,6 @@
Require Import Arith.
Require Import Ascii.
Require Import Bool.
-Declare ML Module "string_syntax_plugin".
(** *** Definition of strings *)
@@ -25,6 +24,8 @@ Inductive string : Set :=
| EmptyString : string
| String : ascii -> string -> string.
+Declare Scope string_scope.
+Declare ML Module "string_syntax_plugin".
Delimit Scope string_scope with string.
Bind Scope string_scope with string.
Local Open Scope string_scope.
diff --git a/theories/Structures/GenericMinMax.v b/theories/Structures/GenericMinMax.v
index 05edc6ccde..4d04667c01 100644
--- a/theories/Structures/GenericMinMax.v
+++ b/theories/Structures/GenericMinMax.v
@@ -83,7 +83,7 @@ End GenericMinMax.
Module MinMaxLogicalProperties (Import O:TotalOrder')(Import M:HasMinMax O).
Module Import Private_Tac := !MakeOrderTac O O.
-(** An alternative caracterisation of [max], equivalent to
+(** An alternative characterisation of [max], equivalent to
[max_l /\ max_r] *)
Lemma max_spec n m :
diff --git a/theories/Structures/OrdersFacts.v b/theories/Structures/OrdersFacts.v
index 87df6b479d..60c64d306b 100644
--- a/theories/Structures/OrdersFacts.v
+++ b/theories/Structures/OrdersFacts.v
@@ -132,6 +132,7 @@ Module OrderedTypeFacts (Import O: OrderedType').
Module OrderTac := OT_to_OrderTac O.
Ltac order := OrderTac.order.
+ Declare Scope order.
Notation "x <= y" := (~lt y x) : order.
Infix "?=" := compare (at level 70, no associativity) : order.
diff --git a/theories/Vectors/VectorDef.v b/theories/Vectors/VectorDef.v
index ba3e411091..390ca78c0e 100644
--- a/theories/Vectors/VectorDef.v
+++ b/theories/Vectors/VectorDef.v
@@ -305,6 +305,7 @@ Eval cbv delta beta in fold_right (fun h H => Datatypes.cons h H) v Datatypes.ni
End VECTORLIST.
Module VectorNotations.
+Declare Scope vector_scope.
Delimit Scope vector_scope with vector.
Notation "[ ]" := [] (format "[ ]") : vector_scope.
Notation "h :: t" := (h :: t) (at level 60, right associativity)
diff --git a/theories/ZArith/BinInt.v b/theories/ZArith/BinInt.v
index cf7397b57e..a11d491a8b 100644
--- a/theories/ZArith/BinInt.v
+++ b/theories/ZArith/BinInt.v
@@ -1248,6 +1248,8 @@ Bind Scope Z_scope with Z.t Z.
(** Re-export Notations *)
+Numeral Notation Z Z.of_int Z.to_int : Z_scope.
+
Infix "+" := Z.add : Z_scope.
Notation "- x" := (Z.opp x) : Z_scope.
Infix "-" := Z.sub : Z_scope.
diff --git a/theories/ZArith/BinIntDef.v b/theories/ZArith/BinIntDef.v
index db4de0b90c..8cb62622db 100644
--- a/theories/ZArith/BinIntDef.v
+++ b/theories/ZArith/BinIntDef.v
@@ -14,6 +14,10 @@ Require Import BinPos BinNat.
Local Open Scope Z_scope.
+Local Notation "0" := Z0.
+Local Notation "1" := (Zpos 1).
+Local Notation "2" := (Zpos 2).
+
(***********************************************************)
(** * Binary Integers, Definitions of Operations *)
(***********************************************************)
@@ -53,7 +57,7 @@ Definition succ_double x :=
Definition pred_double x :=
match x with
- | 0 => -1
+ | 0 => neg 1
| neg p => neg p~1
| pos p => pos (Pos.pred_double p)
end.
@@ -104,7 +108,7 @@ Definition succ x := x + 1.
(** ** Predecessor *)
-Definition pred x := x + -1.
+Definition pred x := x + neg 1.
(** ** Subtraction *)
@@ -171,7 +175,7 @@ Definition sgn z :=
match z with
| 0 => 0
| pos p => 1
- | neg p => -1
+ | neg p => neg 1
end.
(** Boolean equality and comparisons *)
@@ -635,4 +639,9 @@ Definition lxor a b :=
| neg a, neg b => of_N (N.lxor (Pos.pred_N a) (Pos.pred_N b))
end.
+Numeral Notation Z of_int to_int : Z_scope.
+
End Z.
+
+(** Re-export the notation for those who just [Import BinIntDef] *)
+Numeral Notation Z Z.of_int Z.to_int : Z_scope.
diff --git a/theories/ZArith/Int.v b/theories/ZArith/Int.v
index 2f3bf9a32a..1e35370d29 100644
--- a/theories/ZArith/Int.v
+++ b/theories/ZArith/Int.v
@@ -17,6 +17,7 @@
*)
Require Import BinInt.
+Declare Scope Int_scope.
Delimit Scope Int_scope with I.
Local Open Scope Int_scope.
diff --git a/theories/ZArith/Zquot.v b/theories/ZArith/Zquot.v
index e93ebb1ad5..0c9aca2657 100644
--- a/theories/ZArith/Zquot.v
+++ b/theories/ZArith/Zquot.v
@@ -8,7 +8,7 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
-Require Import Nnat ZArith_base ROmega ZArithRing Zdiv Morphisms.
+Require Import Nnat ZArith_base Lia ZArithRing Zdiv Morphisms.
Local Open Scope Z_scope.
@@ -129,33 +129,33 @@ Qed.
Theorem Zrem_lt_pos a b : 0<=a -> b<>0 -> 0 <= Z.rem a b < Z.abs b.
Proof.
intros; generalize (Z.rem_nonneg a b) (Z.rem_bound_abs a b);
- romega with *.
+ lia.
Qed.
Theorem Zrem_lt_neg a b : a<=0 -> b<>0 -> -Z.abs b < Z.rem a b <= 0.
Proof.
intros; generalize (Z.rem_nonpos a b) (Z.rem_bound_abs a b);
- romega with *.
+ lia.
Qed.
Theorem Zrem_lt_pos_pos a b : 0<=a -> 0<b -> 0 <= Z.rem a b < b.
Proof.
- intros; generalize (Zrem_lt_pos a b); romega with *.
+ intros; generalize (Zrem_lt_pos a b); lia.
Qed.
Theorem Zrem_lt_pos_neg a b : 0<=a -> b<0 -> 0 <= Z.rem a b < -b.
Proof.
- intros; generalize (Zrem_lt_pos a b); romega with *.
+ intros; generalize (Zrem_lt_pos a b); lia.
Qed.
Theorem Zrem_lt_neg_pos a b : a<=0 -> 0<b -> -b < Z.rem a b <= 0.
Proof.
- intros; generalize (Zrem_lt_neg a b); romega with *.
+ intros; generalize (Zrem_lt_neg a b); lia.
Qed.
Theorem Zrem_lt_neg_neg a b : a<=0 -> b<0 -> b < Z.rem a b <= 0.
Proof.
- intros; generalize (Zrem_lt_neg a b); romega with *.
+ intros; generalize (Zrem_lt_neg a b); lia.
Qed.
@@ -171,12 +171,12 @@ Lemma Remainder_equiv : forall a b r,
Remainder a b r <-> Remainder_alt a b r.
Proof.
unfold Remainder, Remainder_alt; intuition.
- - romega with *.
- - romega with *.
- - rewrite <-(Z.mul_opp_opp). apply Z.mul_nonneg_nonneg; romega.
+ - lia.
+ - lia.
+ - rewrite <-(Z.mul_opp_opp). apply Z.mul_nonneg_nonneg; lia.
- assert (0 <= Z.sgn r * Z.sgn a).
{ rewrite <-Z.sgn_mul, Z.sgn_nonneg; auto. }
- destruct r; simpl Z.sgn in *; romega with *.
+ destruct r; simpl Z.sgn in *; lia.
Qed.
Theorem Zquot_mod_unique_full a b q r :
@@ -185,7 +185,7 @@ Proof.
destruct 1 as [(H,H0)|(H,H0)]; intros.
apply Zdiv_mod_unique with b; auto.
apply Zrem_lt_pos; auto.
- romega with *.
+ lia.
rewrite <- H1; apply Z.quot_rem'.
rewrite <- (Z.opp_involutive a).
@@ -193,7 +193,7 @@ Proof.
generalize (Zdiv_mod_unique b (-q) (-a÷b) (-r) (Z.rem (-a) b)).
generalize (Zrem_lt_pos (-a) b).
rewrite <-Z.quot_rem', Z.mul_opp_r, <-Z.opp_add_distr, <-H1.
- romega with *.
+ lia.
Qed.
Theorem Zquot_unique_full a b q r :
diff --git a/tools/CoqMakefile.in b/tools/CoqMakefile.in
index 8b6822a4ed..403ad61798 100644
--- a/tools/CoqMakefile.in
+++ b/tools/CoqMakefile.in
@@ -343,19 +343,19 @@ make-pretty-timed make-pretty-timed-before make-pretty-timed-after::
print-pretty-timed::
$(HIDE)$(COQMAKE_ONE_TIME_FILE) $(TIME_OF_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES)
print-pretty-timed-diff::
- $(HIDE)$(COQMAKE_BOTH_TIME_FILES) --sort-by=$(TIMING_SORT_BY) $(TIME_OF_BUILD_BEFORE_FILE) $(TIME_OF_BUILD_AFTER_FILE) $(TIME_OF_PRETTY_BOTH_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES)
+ $(HIDE)$(COQMAKE_BOTH_TIME_FILES) --sort-by=$(TIMING_SORT_BY) $(TIME_OF_BUILD_AFTER_FILE) $(TIME_OF_BUILD_BEFORE_FILE) $(TIME_OF_PRETTY_BOTH_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES)
ifeq (,$(BEFORE))
print-pretty-single-time-diff::
- @echo 'Error: Usage: $(MAKE) print-pretty-single-time-diff BEFORE=path/to/file.v.before-timing AFTER=path/to/file.v.after-timing'
+ @echo 'Error: Usage: $(MAKE) print-pretty-single-time-diff AFTER=path/to/file.v.after-timing BEFORE=path/to/file.v.before-timing'
$(HIDE)false
else
ifeq (,$(AFTER))
print-pretty-single-time-diff::
- @echo 'Error: Usage: $(MAKE) print-pretty-single-time-diff BEFORE=path/to/file.v.before-timing AFTER=path/to/file.v.after-timing'
+ @echo 'Error: Usage: $(MAKE) print-pretty-single-time-diff AFTER=path/to/file.v.after-timing BEFORE=path/to/file.v.before-timing'
$(HIDE)false
else
print-pretty-single-time-diff::
- $(HIDE)$(COQMAKE_BOTH_SINGLE_TIMING_FILES) --sort-by=$(TIMING_SORT_BY) $(BEFORE) $(AFTER) $(TIME_OF_PRETTY_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES)
+ $(HIDE)$(COQMAKE_BOTH_SINGLE_TIMING_FILES) --sort-by=$(TIMING_SORT_BY) $(AFTER) $(BEFORE) $(TIME_OF_PRETTY_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES)
endif
endif
pretty-timed:
diff --git a/tools/coq_dune.ml b/tools/coq_dune.ml
new file mode 100644
index 0000000000..ab60920fbc
--- /dev/null
+++ b/tools/coq_dune.ml
@@ -0,0 +1,307 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+(* LICENSE NOTE: This file is dually MIT/LGPL 2.1+ licensed. MIT license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *)
+
+(* coq_dune: generate dune build rules for .vo files *)
+(* *)
+(* At some point this file will become a Dune plugin, so it is very *)
+(* important that this file can be bootstrapped with: *)
+(* *)
+(* ocamlfind ocamlopt -linkpkg -package str coq_dune.ml -o coq_dune *)
+
+open Format
+
+(* Keeping this file self-contained as it is a "bootstrap" utility *)
+(* Is OCaml missing these basic functions in the stdlib? *)
+module Aux = struct
+
+ let option_iter f o = match o with
+ | Some x -> f x
+ | None -> ()
+
+ let option_cata d f o = match o with
+ | Some x -> f x
+ | None -> d
+
+ let list_compare f = let rec lc x y = match x, y with
+ | [], [] -> 0
+ | [], _ -> -1
+ | _, [] -> 1
+ | x::xs, y::ys -> let r = f x y in if r = 0 then lc xs ys else r
+ in lc
+
+ let rec pp_list pp sep fmt l = match l with
+ | [] -> ()
+ | [l] -> fprintf fmt "%a" pp l
+ | x::xs -> fprintf fmt "%a%a%a" pp x sep () (pp_list pp sep) xs
+
+ let rec pmap f l = match l with
+ | [] -> []
+ | x :: xs ->
+ begin match f x with
+ | None -> pmap f xs
+ | Some r -> r :: pmap f xs
+ end
+
+ let sep fmt () = fprintf fmt "@;"
+
+ module DirOrd = struct
+ type t = string list
+ let compare = list_compare String.compare
+ end
+
+ module DirMap = Map.Make(DirOrd)
+
+ (* Functions available in newer OCaml versions *)
+ (* Taken from the OCaml std library (c) INRIA / LGPL-2.1 *)
+ module Legacy = struct
+
+ (* Slower version of DirMap.update, waiting for OCaml 4.06.0 *)
+ let dirmap_update key f map =
+ match begin
+ try f (Some (DirMap.find key map))
+ with Not_found -> f None
+ end with
+ | None -> DirMap.remove key map
+ | Some x -> DirMap.add key x map
+
+ (* Available in OCaml >= 4.04 *)
+ let split_on_char sep s =
+ let open String in
+ let r = ref [] in
+ let j = ref (length s) in
+ for i = length s - 1 downto 0 do
+ if unsafe_get s i = sep then begin
+ r := sub s (i + 1) (!j - i - 1) :: !r;
+ j := i
+ end
+ done;
+ sub s 0 !j :: !r
+
+ (* Available in OCaml >= 4.04 *)
+ let is_dir_sep = match Sys.os_type with
+ | "Win32" -> fun s i -> s.[i] = '\\'
+ | _ -> fun s i -> s.[i] = '/'
+
+ let extension_len name =
+ let rec check i0 i =
+ if i < 0 || is_dir_sep name i then 0
+ else if name.[i] = '.' then check i0 (i - 1)
+ else String.length name - i0
+ in
+ let rec search_dot i =
+ if i < 0 || is_dir_sep name i then 0
+ else if name.[i] = '.' then check i (i - 1)
+ else search_dot (i - 1)
+ in
+ search_dot (String.length name - 1)
+
+ let remove_extension name =
+ let l = extension_len name in
+ if l = 0 then name else String.sub name 0 (String.length name - l)
+
+ end
+
+ let add_map_list key elem map =
+ (* Move to Dirmap.update once we require OCaml >= 4.06.0 *)
+ Legacy.dirmap_update key (fun l -> Some (option_cata [elem] (fun ll -> elem :: ll) l)) map
+
+end
+
+open Aux
+
+(* Once this is a Dune plugin the flags will be taken from the env *)
+module Options = struct
+
+ type flag = {
+ enabled : bool;
+ cmd : string;
+ }
+
+ let all_opts =
+ [ { enabled = false; cmd = "-debug"; }
+ ; { enabled = false; cmd = "-native_compiler"; }
+ ]
+
+ let build_coq_flags () =
+ let popt o = if o.enabled then Some o.cmd else None in
+ String.concat " " @@ pmap popt all_opts
+end
+
+type vodep = {
+ target: string;
+ deps : string list;
+}
+
+type ldep = | VO of vodep | ML4 of string | MLG of string
+type ddir = ldep list DirMap.t
+
+(* Filter `.vio` etc... *)
+let filter_no_vo =
+ List.filter (fun f -> Filename.check_suffix f ".vo")
+
+(* We could have coqdep to output dune files directly *)
+
+(* Fix once we move to OCaml >= 4.06.0 *)
+let list_init len f =
+ let rec init_aux i n f =
+ if i >= n then []
+ else let r = f i in r :: init_aux (i+1) n f
+ in init_aux 0 len f
+
+let gen_sub n =
+ (* Move to List.init once we can depend on OCaml >= 4.06.0 *)
+ String.concat "/" (list_init n (fun _ -> "..")) ^ "/"
+
+let pp_rule fmt targets deps action =
+ (* Special printing of the first rule *)
+ let ppl = pp_list pp_print_string sep in
+ let pp_deps fmt l = match l with
+ | [] ->
+ ()
+ | x :: xs ->
+ fprintf fmt "(:pp-file %s)%a" x sep ();
+ pp_list pp_print_string sep fmt xs
+ in
+ fprintf fmt
+ "@[(rule@\n @[(targets @[%a@])@\n(deps @[%a@])@\n(action @[%a@])@])@]@\n"
+ ppl targets pp_deps deps pp_print_string action
+
+(* Generate the dune rule: *)
+let pp_vo_dep dir fmt vo =
+ let depth = List.length dir in
+ let sdir = gen_sub depth in
+ (* All files except those in Init implicitly depend on the Prelude, we account for it here. *)
+ let eflag, edep = if List.tl dir = ["Init"] then "-noinit -R theories Coq", [] else "", ["theories/Init/Prelude.vo"] in
+ (* Coq flags *)
+ let cflag = Options.build_coq_flags () in
+ (* Correct path from global to local "theories/Init/Decimal.vo" -> "../../theories/Init/Decimal.vo" *)
+ let deps = List.map (fun s -> sdir ^ s) (edep @ vo.deps) in
+ (* The source file is also corrected as we will call coqtop from the top dir *)
+ let source = String.concat "/" dir ^ "/" ^ Legacy.(remove_extension vo.target) ^ ".v" in
+ (* The final build rule *)
+ let action = sprintf "(chdir %%{project_root} (run coqtop -boot %s %s -compile %s))" eflag cflag source in
+ pp_rule fmt [vo.target] deps action
+
+let pp_ml4_dep _dir fmt ml =
+ let target = Legacy.(remove_extension ml) ^ ".ml" in
+ let ml4_rule = "(run coqp5 -loc loc -impl %{pp-file} -o %{targets})" in
+ pp_rule fmt [target] [ml] ml4_rule
+
+let pp_mlg_dep _dir fmt ml =
+ let target = Legacy.(remove_extension ml) ^ ".ml" in
+ let ml4_rule = "(run coqpp %{pp-file})" in
+ pp_rule fmt [target] [ml] ml4_rule
+
+let pp_dep dir fmt oo = match oo with
+ | VO vo -> pp_vo_dep dir fmt vo
+ | ML4 f -> pp_ml4_dep dir fmt f
+ | MLG f -> pp_mlg_dep dir fmt f
+
+let out_install fmt dir ff =
+ let itarget = String.concat "/" dir in
+ let ff = pmap (function | VO vo -> Some vo.target | _ -> None) ff in
+ let pp_ispec fmt tg = fprintf fmt "(%s as %s)" tg (itarget^"/"^tg) in
+ fprintf fmt "(install@\n @[(section lib)@\n(files @[%a@])@])@\n"
+ (pp_list pp_ispec sep) ff
+
+(* For each directory, we must record two things, the build rules and
+ the install specification. *)
+let record_dune d ff =
+ let sd = String.concat "/" d in
+ if Sys.file_exists sd && Sys.is_directory sd then
+ let out = open_out (sd^"/dune") in
+ let fmt = formatter_of_out_channel out in
+ if List.nth d 0 = "plugins" then
+ fprintf fmt "(include plugin_base.dune)@\n";
+ out_install fmt d ff;
+ List.iter (pp_dep d fmt) ff;
+ fprintf fmt "%!";
+ close_out out
+ else
+ eprintf "error in coq_dune, a directory disappeared: %s@\n%!" sd
+
+(* File Scanning *)
+let choose_ml4g_form f =
+ if Filename.check_suffix f ".ml4" then ML4 f
+ else MLG f
+
+let scan_mlg4 m d =
+ let dir = ["plugins"; d] in
+ let m = DirMap.add dir [] m in
+ let ml4 = Sys.(List.filter (fun f -> Filename.(check_suffix f ".ml4" || check_suffix f ".mlg"))
+ Array.(to_list @@ readdir String.(concat "/" dir))) in
+ List.fold_left (fun m f -> add_map_list ["plugins"; d] (choose_ml4g_form f) m) m ml4
+
+let scan_plugins m =
+ let dirs = Sys.(List.filter (fun f -> is_directory @@ "plugins/"^f) Array.(to_list @@ readdir "plugins/")) in
+ List.fold_left scan_mlg4 m dirs
+
+(* Process .vfiles.d and generate a skeleton for the dune file *)
+let parse_coqdep_line l =
+ match Str.(split (regexp ":") l) with
+ | [targets;deps] ->
+ let targets = Str.(split (regexp "[ \t]+") targets) in
+ let deps = Str.(split (regexp "[ \t]+") deps) in
+ let targets = filter_no_vo targets in
+ begin match targets with
+ | [target] ->
+ let dir, target = Filename.(dirname target, basename target) in
+ Some (Legacy.split_on_char '/' dir, VO { target; deps; })
+ (* Otherwise a vio file, we ignore *)
+ | _ -> None
+ end
+ (* Strange rule, we ignore *)
+ | _ -> None
+
+let rec read_vfiles ic map =
+ try
+ let rule = parse_coqdep_line (input_line ic) in
+ (* Add vo_entry to its corresponding map entry *)
+ let map = option_cata map (fun (dir, vo) -> add_map_list dir vo map) rule in
+ read_vfiles ic map
+ with End_of_file -> map
+
+let out_map map =
+ DirMap.iter record_dune map
+
+let exec_ifile f =
+ match Array.length Sys.argv with
+ | 1 -> f stdin
+ | 2 ->
+ let ic = open_in Sys.argv.(1) in
+ (try f ic with _ -> close_in ic)
+ | _ -> eprintf "Error: wrong number of arguments@\n%!"; exit 1
+
+let _ =
+ exec_ifile (fun ic ->
+ let map = scan_plugins DirMap.empty in
+ let map = read_vfiles ic map in
+ out_map map)
diff --git a/tools/coq_makefile.ml b/tools/coq_makefile.ml
index ad489da822..c3bdf656d1 100644
--- a/tools/coq_makefile.ml
+++ b/tools/coq_makefile.ml
@@ -31,8 +31,19 @@ let rec print_prefix_list sep = function
| x :: l -> print sep; print x; print_prefix_list sep l
| [] -> ()
-let usage_common () =
+let usage_coq_makefile () =
+ output_string stderr "Usage summary:\
+\n\
+\ncoq_makefile .... [file.v] ... [file.ml[i4]?] ... [file.ml{lib,pack}]\
+\n ... [any] ... [-extra[-phony] result dependencies command]\
+\n ... [-I dir] ... [-R physicalpath logicalpath]\
+\n ... [-Q physicalpath logicalpath] ... [VARIABLE = value]\
+\n ... [-arg opt] ... [-opt|-byte] [-no-install] [-f file] [-o file]\
+\n [-h] [--help]\
+\n";
output_string stderr "\
+\nFull list of options:\
+\n\
\n[file.v]: Coq file to be compiled\
\n[file.ml[i4]?]: Objective Caml file to be compiled\
\n[file.ml{lib,pack}]: ocamlbuild file that describes a Objective Caml\
@@ -61,25 +72,6 @@ let usage_common () =
\n[-install opt]: where opt is \"user\" to force install into user directory,\
\n \"none\" to build a makefile with no install target or\
\n \"global\" to force install in $COQLIB directory\
-\n"
-
-let usage_coq_project () =
- output_string stderr "Available arguments:";
- usage_common ();
- exit 1
-
-let usage_coq_makefile () =
- output_string stderr "Usage summary:\
-\n\
-\ncoq_makefile .... [file.v] ... [file.ml[i4]?] ... [file.ml{lib,pack}]\
-\n ... [any] ... [-extra[-phony] result dependencies command]\
-\n ... [-I dir] ... [-R physicalpath logicalpath]\
-\n ... [-Q physicalpath logicalpath] ... [VARIABLE = value]\
-\n ... [-arg opt] ... [-opt|-byte] [-no-install] [-f file] [-o file]\
-\n [-h] [--help]\
-\n";
- usage_common ();
- output_string stderr "\
\n[-f file]: take the contents of file as arguments\
\n[-o file]: output should go in file file (recommended)\
\n Output file outside the current directory is forbidden.\
@@ -405,7 +397,7 @@ let _ =
let project =
try cmdline_args_to_project ~curdir:Filename.current_dir_name args
- with Parsing_error s -> prerr_endline s; usage_coq_project () in
+ with Parsing_error s -> prerr_endline s; usage_coq_makefile () in
if only_destination <> None then begin
destination_of project (Option.get only_destination);
diff --git a/tools/coqc.ml b/tools/coqc.ml
index 90d8e67c1e..2cbf05bd8b 100644
--- a/tools/coqc.ml
+++ b/tools/coqc.ml
@@ -24,7 +24,7 @@
let environment = Unix.environment ()
-let binary = ref "coqtop"
+let use_bytecode = ref false
let image = ref ""
let verbose = ref false
@@ -69,8 +69,8 @@ let parse_args () =
verbose := true ; parse (cfiles,args) rem
| "-image" :: f :: rem -> image := f; parse (cfiles,args) rem
| "-image" :: [] -> usage ()
- | "-byte" :: rem -> binary := "coqtop.byte"; parse (cfiles,args) rem
- | "-opt" :: rem -> binary := "coqtop"; parse (cfiles,args) rem
+ | "-byte" :: rem -> use_bytecode := true; parse (cfiles,args) rem
+ | "-opt" :: rem -> use_bytecode := false; parse (cfiles,args) rem
(* Informative options *)
@@ -155,7 +155,7 @@ let main () =
end;
let coqtopname =
if !image <> "" then !image
- else Filename.concat Envars.coqbin (!binary ^ Coq_config.exec_extension)
+ else System.get_toplevel_path ~byte:!use_bytecode "coqtop"
in
(* List.iter (compile coqtopname args) cfiles*)
Unix.handle_unix_error (compile coqtopname args) cfiles
diff --git a/tools/coqdoc/dune b/tools/coqdoc/dune
new file mode 100644
index 0000000000..8e05c7d97e
--- /dev/null
+++ b/tools/coqdoc/dune
@@ -0,0 +1,6 @@
+(executable
+ (name main)
+ (public_name coqdoc)
+ (libraries str coq.config))
+
+(ocamllex cpretty)
diff --git a/tools/dune b/tools/dune
new file mode 100644
index 0000000000..05a620fb07
--- /dev/null
+++ b/tools/dune
@@ -0,0 +1,43 @@
+(executable
+ (name coqc)
+ (public_name coqc)
+ (modules coqc)
+ (libraries coq.toplevel))
+
+(executable
+ (name coq_makefile)
+ (public_name coq_makefile)
+ (modules coq_makefile)
+ (libraries coq.lib))
+
+(install
+ (section lib)
+ (files (CoqMakefile.in as tools/CoqMakefile.in)))
+
+(executable
+ (name coqdep)
+ (public_name coqdep)
+ (modules coqdep_lexer coqdep_common coqdep)
+ (libraries coq.lib))
+
+(ocamllex coqdep_lexer)
+
+(executable
+ (name coqwc)
+ (public_name coqwc)
+ (modules coqwc)
+ (libraries))
+
+(ocamllex coqwc)
+
+(executable
+ (name coq_tex)
+ (public_name coq_tex)
+ (modules coq_tex)
+ (libraries str))
+
+(executable
+ (name coq_dune)
+ (public_name coq_dune)
+ (modules coq_dune)
+ (libraries str))
diff --git a/topbin/dune b/topbin/dune
new file mode 100644
index 0000000000..5f07492a10
--- /dev/null
+++ b/topbin/dune
@@ -0,0 +1,29 @@
+(install
+ (section bin)
+ (files (coqtop_bin.exe as coqtop)))
+
+(executable
+ (name coqtop_bin)
+ (public_name coqtop.opt)
+ (package coq)
+ (modules coqtop_bin)
+ (libraries coq.toplevel)
+ (link_flags -linkall))
+
+(executable
+ (name coqtop_byte_bin)
+ (public_name coqtop.byte)
+ (package coq)
+ (modules coqtop_byte_bin)
+ (libraries compiler-libs.toplevel coq.toplevel)
+ (modes byte)
+ (link_flags -linkall))
+
+; Workers
+(executables
+ (names coqqueryworker_bin coqtacticworker_bin coqproofworker_bin)
+ (public_names coqqueryworker.opt coqtacticworker.opt coqproofworker.opt)
+ (package coq)
+ (modules :standard \ coqtop_byte_bin coqtop_bin)
+ (libraries coq.toplevel)
+ (link_flags -linkall))
diff --git a/toplevel/coqargs.ml b/toplevel/coqargs.ml
index 900964609d..98a28bb2b6 100644
--- a/toplevel/coqargs.ml
+++ b/toplevel/coqargs.ml
@@ -154,7 +154,7 @@ let add_compat_require opts v =
match v with
| Flags.V8_6 -> add_vo_require opts "Coq.Compat.Coq86" None (Some false)
| Flags.V8_7 -> add_vo_require opts "Coq.Compat.Coq87" None (Some false)
- | Flags.Current -> opts
+ | Flags.Current -> add_vo_require opts "Coq.Compat.Coq88" None (Some false)
let set_batch_mode opts =
Flags.quiet := true;
@@ -425,7 +425,7 @@ let parse_args arglist : coq_cmdopts * string list =
|"-worker-id" -> set_worker_id opt (next ()); oval
|"-compat" ->
- let v = G_vernac.parse_compat_version ~allow_old:false (next ()) in
+ let v = G_vernac.parse_compat_version (next ()) in
Flags.compat_version := v;
add_compat_require oval v
diff --git a/toplevel/coqloop.ml b/toplevel/coqloop.ml
index 9e16b97608..59a464a22e 100644
--- a/toplevel/coqloop.ml
+++ b/toplevel/coqloop.ml
@@ -330,17 +330,33 @@ let cproof p1 p2 =
let drop_last_doc = ref None
+(* todo: could add other Set/Unset commands, such as "Printing Universes" *)
+let print_anyway_opts = [
+ [ "Diffs" ];
+ ]
+
+let print_anyway c =
+ let open Vernacexpr in
+ match c with
+ | VernacExpr (_, VernacSetOption (_, opt, _))
+ | VernacExpr (_, VernacUnsetOption (_, opt)) ->
+ List.mem opt print_anyway_opts
+ | _ -> false
+
(* We try to behave better when goal printing raises an exception
[usually Ctrl-C]
This is mostly a hack as we should protect printing in a more
generic way, but that'll do for now *)
-let top_goal_print oldp newp =
+let top_goal_print ~doc c oldp newp =
try
let proof_changed = not (Option.equal cproof oldp newp) in
- let print_goals = not !Flags.quiet &&
- proof_changed && Proof_global.there_are_pending_proofs () in
- if print_goals then Printer.print_and_diff oldp newp;
+ let print_goals = proof_changed && Proof_global.there_are_pending_proofs () ||
+ print_anyway c in
+ if not !Flags.quiet && print_goals then begin
+ let dproof = Stm.get_prev_proof ~doc (Stm.get_current_state ~doc) in
+ Printer.print_and_diff dproof newp
+ end
with
| exn ->
let (e, info) = CErrors.push exn in
@@ -376,8 +392,7 @@ let rec vernac_loop ~state =
else (Feedback.msg_warning (str "There is no ML toplevel."); vernac_loop ~state)
| {v=VernacControl c; loc} ->
let nstate = Vernac.process_expr ~state (make ?loc c) in
- let dproof = Stm.get_prev_proof ~doc:state.doc (Stm.get_current_state ~doc:state.doc) in
- top_goal_print dproof nstate.proof;
+ top_goal_print ~doc:state.doc c state.proof nstate.proof;
vernac_loop ~state:nstate
with
| Stm.End_of_input ->
diff --git a/toplevel/coqtop.ml b/toplevel/coqtop.ml
index 9b68f303a6..8cd262c6d6 100644
--- a/toplevel/coqtop.ml
+++ b/toplevel/coqtop.ml
@@ -362,7 +362,7 @@ let init_color opts =
false
in
if Proof_diffs.show_diffs () && not term_color && not opts.batch_mode then
- CErrors.user_err Pp.(str "Error: -diffs requires enabling -color");
+ (prerr_endline "Error: -diffs requires enabling -color"; exit 1);
Topfmt.init_terminal_output ~color:term_color
let print_style_tags opts =
@@ -384,7 +384,7 @@ let print_style_tags opts =
(** GC tweaking *)
(** Coq is a heavy user of persistent data structures and symbolic ASTs, so the
- minor heap is heavily sollicited. Unfortunately, the default size is far too
+ minor heap is heavily solicited. Unfortunately, the default size is far too
small, so we enlarge it a lot (128 times larger).
To better handle huge memory consumers, we also augment the default major
diff --git a/toplevel/dune b/toplevel/dune
new file mode 100644
index 0000000000..f51e50aaa3
--- /dev/null
+++ b/toplevel/dune
@@ -0,0 +1,13 @@
+(library
+ (name toplevel)
+ (public_name coq.toplevel)
+ (synopsis "Coq's Interactive Shell [terminal-based]")
+ (wrapped false)
+ (libraries num coq.stm))
+; Coqlevel provides the `Num` library to plugins, we could also use
+; -linkall in the plugins file, to be discussed.
+
+(rule
+ (targets g_toplevel.ml)
+ (deps (:mlg-file g_toplevel.mlg))
+ (action (run coqpp %{mlg-file})))
diff --git a/vernac/assumptions.ml b/vernac/assumptions.ml
index 765f962e99..b000745961 100644
--- a/vernac/assumptions.ml
+++ b/vernac/assumptions.ml
@@ -70,8 +70,8 @@ let rec fields_of_functor f subs mp0 args = function
let rec lookup_module_in_impl mp =
match mp with
- | MPfile _ -> raise Not_found
- | MPbound _ -> assert false
+ | MPfile _ -> Global.lookup_module mp
+ | MPbound _ -> Global.lookup_module mp
| MPdot (mp',lab') ->
if ModPath.equal mp' (Global.current_modpath ()) then
Global.lookup_module mp
@@ -213,25 +213,25 @@ let rec traverse current ctx accu t = match Constr.kind t with
and traverse_object ?inhabits (curr, data, ax2ty) body obj =
let data, ax2ty =
- let already_in = Refmap_env.mem obj data in
+ let already_in = GlobRef.Map_env.mem obj data in
match body () with
| None ->
let data =
- if not already_in then Refmap_env.add obj Refset_env.empty data else data in
+ if not already_in then GlobRef.Map_env.add obj GlobRef.Set_env.empty data else data in
let ax2ty =
if Option.is_empty inhabits then ax2ty else
let ty = Option.get inhabits in
- try let l = Refmap_env.find obj ax2ty in Refmap_env.add obj (ty::l) ax2ty
- with Not_found -> Refmap_env.add obj [ty] ax2ty in
+ try let l = GlobRef.Map_env.find obj ax2ty in GlobRef.Map_env.add obj (ty::l) ax2ty
+ with Not_found -> GlobRef.Map_env.add obj [ty] ax2ty in
data, ax2ty
| Some body ->
if already_in then data, ax2ty else
let contents,data,ax2ty =
traverse (label_of obj) Context.Rel.empty
- (Refset_env.empty,data,ax2ty) body in
- Refmap_env.add obj contents data, ax2ty
+ (GlobRef.Set_env.empty,data,ax2ty) body in
+ GlobRef.Map_env.add obj contents data, ax2ty
in
- (Refset_env.add obj curr, data, ax2ty)
+ (GlobRef.Set_env.add obj curr, data, ax2ty)
(** Collects the references occurring in the declaration of mutual inductive
definitions. All the constructors and names of a mutual inductive
@@ -244,14 +244,14 @@ and traverse_inductive (curr, data, ax2ty) mind obj =
(* Invariant : I_0 \in data iff I_i \in data iff c_ij \in data
where I_0, I_1, ... are in the same mutual definition and c_ij
are all their constructors. *)
- if Refmap_env.mem firstind_ref data then data, ax2ty else
+ if GlobRef.Map_env.mem firstind_ref data then data, ax2ty else
let mib = lookup_mind mind in
(* Collects references of parameters *)
let param_ctx = mib.mind_params_ctxt in
let nparam = List.length param_ctx in
let accu =
traverse_context label Context.Rel.empty
- (Refset_env.empty, data, ax2ty) param_ctx
+ (GlobRef.Set_env.empty, data, ax2ty) param_ctx
in
(* Build the context of all arities *)
let arities_ctx =
@@ -283,14 +283,14 @@ and traverse_inductive (curr, data, ax2ty) mind obj =
(* Maps all these dependencies to inductives and constructors*)
let data = Array.fold_left_i (fun n data oib ->
let ind = (mind, n) in
- let data = Refmap_env.add (IndRef ind) contents data in
+ let data = GlobRef.Map_env.add (IndRef ind) contents data in
Array.fold_left_i (fun k data _ ->
- Refmap_env.add (ConstructRef (ind, k+1)) contents data
+ GlobRef.Map_env.add (ConstructRef (ind, k+1)) contents data
) data oib.mind_consnames) data mib.mind_packets
in
data, ax2ty
in
- (Refset_env.add obj curr, data, ax2ty)
+ (GlobRef.Set_env.add obj curr, data, ax2ty)
(** Collects references in a rel_context. *)
and traverse_context current ctx accu ctxt =
@@ -307,7 +307,7 @@ and traverse_context current ctx accu ctxt =
let traverse current t =
let () = modcache := MPmap.empty in
- traverse current Context.Rel.empty (Refset_env.empty, Refmap_env.empty, Refmap_env.empty) t
+ traverse current Context.Rel.empty (GlobRef.Set_env.empty, GlobRef.Map_env.empty, GlobRef.Map_env.empty) t
(** Hopefully bullet-proof function to recover the type of a constant. It just
ignores all the universe stuff. There are many issues that can arise when
@@ -330,12 +330,12 @@ let assumptions ?(add_opaque=false) ?(add_transparent=false) st gr t =
let accu =
if cb.const_typing_flags.check_guarded then accu
else
- let l = try Refmap_env.find obj ax2ty with Not_found -> [] in
+ let l = try GlobRef.Map_env.find obj ax2ty with Not_found -> [] in
ContextObjectMap.add (Axiom (Guarded kn, l)) Constr.mkProp accu
in
if not (Declareops.constant_has_body cb) || not cb.const_typing_flags.check_universes then
let t = type_of_constant cb in
- let l = try Refmap_env.find obj ax2ty with Not_found -> [] in
+ let l = try GlobRef.Map_env.find obj ax2ty with Not_found -> [] in
ContextObjectMap.add (Axiom (Constant kn,l)) t accu
else if add_opaque && (Declareops.is_opaque cb || not (Cpred.mem kn knst)) then
let t = type_of_constant cb in
@@ -350,7 +350,7 @@ let assumptions ?(add_opaque=false) ?(add_transparent=false) st gr t =
if mind.mind_typing_flags.check_guarded then
accu
else
- let l = try Refmap_env.find obj ax2ty with Not_found -> [] in
+ let l = try GlobRef.Map_env.find obj ax2ty with Not_found -> [] in
ContextObjectMap.add (Axiom (Positive m, l)) Constr.mkProp accu
in
- Refmap_env.fold fold graph ContextObjectMap.empty
+ GlobRef.Map_env.fold fold graph ContextObjectMap.empty
diff --git a/vernac/assumptions.mli b/vernac/assumptions.mli
index 751e79d89c..aead345d8c 100644
--- a/vernac/assumptions.mli
+++ b/vernac/assumptions.mli
@@ -10,7 +10,6 @@
open Names
open Constr
-open Globnames
open Printer
(** Collects all the objects on which a term directly relies, bypassing kernel
@@ -22,8 +21,8 @@ open Printer
*)
val traverse :
Label.t -> constr ->
- (Refset_env.t * Refset_env.t Refmap_env.t *
- (Label.t * Constr.rel_context * types) list Refmap_env.t)
+ (GlobRef.Set_env.t * GlobRef.Set_env.t GlobRef.Map_env.t *
+ (Label.t * Constr.rel_context * types) list GlobRef.Map_env.t)
(** Collects all the assumptions (optionally including opaque definitions)
on which a term relies (together with their type). The above warning of
diff --git a/vernac/auto_ind_decl.ml b/vernac/auto_ind_decl.ml
index ee578669c2..dee7541d37 100644
--- a/vernac/auto_ind_decl.ml
+++ b/vernac/auto_ind_decl.ml
@@ -59,6 +59,8 @@ exception ParameterWithoutEquality of GlobRef.t
exception NonSingletonProp of inductive
exception DecidabilityMutualNotSupported
exception NoDecidabilityCoInductive
+exception ConstructorWithNonParametricInductiveType of inductive
+exception DecidabilityIndicesNotSupported
let constr_of_global g = lazy (UnivGen.constr_of_global g)
@@ -120,6 +122,10 @@ let check_bool_is_defined () =
try let _ = Global.type_of_global_in_context (Global.env ()) Coqlib.glob_bool in ()
with e when CErrors.noncritical e -> raise (UndefinedCst "bool")
+let check_no_indices mib =
+ if Array.exists (fun mip -> mip.mind_nrealargs <> 0) mib.mind_packets then
+ raise DecidabilityIndicesNotSupported
+
let beq_scheme_kind_aux = ref (fun _ -> failwith "Undefined")
let build_beq_scheme mode kn =
@@ -133,6 +139,7 @@ let build_beq_scheme mode kn =
(* number of params in the type *)
let nparams = mib.mind_nparams in
let nparrec = mib.mind_nparams_rec in
+ check_no_indices mib;
(* params context divided *)
let lnonparrec,lnamesparrec =
context_chop (nparams-nparrec) mib.mind_params_ctxt in
@@ -193,6 +200,7 @@ let build_beq_scheme mode kn =
match Constr.kind c with
| Rel x -> mkRel (x-nlist+ndx), Safe_typing.empty_private_constants
| Var x ->
+ (* Support for working in a context with "eq_x : x -> x -> bool" *)
let eid = Id.of_string ("eq_"^(Id.to_string x)) in
let () =
try ignore (Environ.lookup_named eid env)
@@ -225,9 +233,17 @@ let build_beq_scheme mode kn =
| Lambda _-> raise (EqUnknown "abstraction")
| LetIn _ -> raise (EqUnknown "let-in")
| Const (kn, u) ->
- (match Environ.constant_opt_value_in env (kn, u) with
- | None -> raise (ParameterWithoutEquality (ConstRef kn))
- | Some c -> aux (Term.applist (c,a)))
+ (match Environ.constant_opt_value_in env (kn, u) with
+ | Some c -> aux (Term.applist (c,a))
+ | None ->
+ (* Support for working in a context with "eq_x : x -> x -> bool" *)
+ (* Needs Hints, see test suite *)
+ let eq_lbl = Label.make ("eq_" ^ Label.to_string (Constant.label kn)) in
+ let kneq = Constant.change_label kn eq_lbl in
+ try let _ = Environ.constant_opt_value_in env (kneq, u) in
+ Term.applist (mkConst kneq,a),
+ Safe_typing.empty_private_constants
+ with Not_found -> raise (ParameterWithoutEquality (ConstRef kn)))
| Proj _ -> raise (EqUnknown "projection")
| Construct _ -> raise (EqUnknown "constructor")
| Case _ -> raise (EqUnknown "match")
@@ -341,13 +357,10 @@ let _ = beq_scheme_kind_aux := fun () -> beq_scheme_kind
(* This function tryies to get the [inductive] between a constr
the constr should be Ind i or App(Ind i,[|args|])
*)
-let destruct_ind sigma c =
+let destruct_ind env sigma c =
let open EConstr in
- try let u,v = destApp sigma c in
- let indc = destInd sigma u in
- indc,v
- with DestKO -> let indc = destInd sigma c in
- indc,[||]
+ let (c,v) = Reductionops.whd_all_stack env sigma c in
+ destInd sigma c, Array.of_list v
(*
In the following, avoid is the list of names to avoid.
@@ -355,16 +368,16 @@ let destruct_ind sigma c =
then avoid should be
[| lb_An ... lb _A1 (resp. bl_An ... bl_A1)
eq_An .... eq_A1 An ... A1 |]
-so from Ai we can find the the correct eq_Ai bl_ai or lb_ai
+so from Ai we can find the correct eq_Ai bl_ai or lb_ai
*)
(* used in the leib -> bool side*)
let do_replace_lb mode lb_scheme_key aavoid narg p q =
let open EConstr in
let avoid = Array.of_list aavoid in
- let do_arg sigma v offset =
- try
+ let do_arg sigma hd v offset =
+ match kind sigma v with
+ | Var s ->
let x = narg*offset in
- let s = destVar sigma v in
let n = Array.length avoid in
let rec find i =
if Id.equal avoid.(n-i) s then avoid.(n-i-x)
@@ -373,22 +386,20 @@ let do_replace_lb mode lb_scheme_key aavoid narg p q =
(str "Var " ++ Id.print s ++ str " seems unknown.")
)
in mkVar (find 1)
- with e when CErrors.noncritical e ->
- (* if this happen then the args have to be already declared as a
- Parameter*)
- (
- let mp,dir,lbl = Constant.repr3 (fst (destConst sigma v)) in
- mkConst (Constant.make3 mp dir (Label.make (
- if Int.equal offset 1 then ("eq_"^(Label.to_string lbl))
- else ((Label.to_string lbl)^"_lb")
- )))
- )
+ | Const (cst,_) ->
+ (* Works in specific situations where the args have to be already declared as a
+ Parameter (see example "J" in test file SchemeEquality.v) *)
+ let lbl = Label.to_string (Constant.label cst) in
+ let newlbl = if Int.equal offset 1 then ("eq_" ^ lbl) else (lbl ^ "_lb") in
+ mkConst (Constant.change_label cst (Label.make newlbl))
+ | _ -> raise (ConstructorWithNonParametricInductiveType (fst hd))
+
in
Proofview.Goal.enter begin fun gl ->
let type_of_pq = Tacmach.New.pf_unsafe_type_of gl p in
let sigma = Tacmach.New.project gl in
let env = Tacmach.New.pf_env gl in
- let u,v = destruct_ind sigma type_of_pq
+ let u,v = destruct_ind env sigma type_of_pq
in let lb_type_of_p =
try
let c, eff = find_scheme ~mode lb_scheme_key (fst u) (*FIXME*) in
@@ -409,8 +420,8 @@ let do_replace_lb mode lb_scheme_key aavoid narg p q =
Proofview.tclEVARMAP >>= fun sigma ->
let lb_args = Array.append (Array.append
v
- (Array.Smart.map (fun x -> do_arg sigma x 1) v))
- (Array.Smart.map (fun x -> do_arg sigma x 2) v)
+ (Array.Smart.map (fun x -> do_arg sigma u x 1) v))
+ (Array.Smart.map (fun x -> do_arg sigma u x 2) v)
in let app = if Array.is_empty lb_args
then lb_type_of_p else mkApp (lb_type_of_p,lb_args)
in
@@ -419,14 +430,14 @@ let do_replace_lb mode lb_scheme_key aavoid narg p q =
Equality.replace p q ; apply app ; Auto.default_auto]
end
-(* used in the bool -> leib side *)
+(* used in the bool -> leb side *)
let do_replace_bl mode bl_scheme_key (ind,u as indu) aavoid narg lft rgt =
let open EConstr in
let avoid = Array.of_list aavoid in
- let do_arg sigma v offset =
- try
+ let do_arg sigma hd v offset =
+ match kind sigma v with
+ | Var s ->
let x = narg*offset in
- let s = destVar sigma v in
let n = Array.length avoid in
let rec find i =
if Id.equal avoid.(n-i) s then avoid.(n-i-x)
@@ -435,16 +446,13 @@ let do_replace_bl mode bl_scheme_key (ind,u as indu) aavoid narg lft rgt =
(str "Var " ++ Id.print s ++ str " seems unknown.")
)
in mkVar (find 1)
- with e when CErrors.noncritical e ->
- (* if this happen then the args have to be already declared as a
- Parameter*)
- (
- let mp,dir,lbl = Constant.repr3 (fst (destConst sigma v)) in
- mkConst (Constant.make3 mp dir (Label.make (
- if Int.equal offset 1 then ("eq_"^(Label.to_string lbl))
- else ((Label.to_string lbl)^"_bl")
- )))
- )
+ | Const (cst,_) ->
+ (* Works in specific situations where the args have to be already declared as a
+ Parameter (see example "J" in test file SchemeEquality.v) *)
+ let lbl = Label.to_string (Constant.label cst) in
+ let newlbl = if Int.equal offset 1 then ("eq_" ^ lbl) else (lbl ^ "_bl") in
+ mkConst (Constant.change_label cst (Label.make newlbl))
+ | _ -> raise (ConstructorWithNonParametricInductiveType (fst hd))
in
let rec aux l1 l2 =
@@ -456,7 +464,7 @@ let do_replace_bl mode bl_scheme_key (ind,u as indu) aavoid narg lft rgt =
let env = Tacmach.New.pf_env gl in
if EConstr.eq_constr sigma t1 t2 then aux q1 q2
else (
- let u,v = try destruct_ind sigma tt1
+ let u,v = try destruct_ind env sigma tt1
(* trick so that the good sequence is returned*)
with e when CErrors.noncritical e -> indu,[||]
in if eq_ind (fst u) ind
@@ -480,8 +488,8 @@ let do_replace_bl mode bl_scheme_key (ind,u as indu) aavoid narg lft rgt =
in let bl_args =
Array.append (Array.append
v
- (Array.Smart.map (fun x -> do_arg sigma x 1) v))
- (Array.Smart.map (fun x -> do_arg sigma x 2) v )
+ (Array.Smart.map (fun x -> do_arg sigma u x 1) v))
+ (Array.Smart.map (fun x -> do_arg sigma u x 2) v )
in
let app = if Array.is_empty bl_args
then bl_t1 else mkApp (bl_t1,bl_args)
@@ -543,7 +551,7 @@ let eqI ind l =
and e, eff =
try let c, eff = find_scheme beq_scheme_kind ind in mkConst c, eff
with Not_found -> user_err ~hdr:"AutoIndDecl.eqI"
- (str "The boolean equality on " ++ MutInd.print (fst ind) ++ str " is needed.");
+ (str "The boolean equality on " ++ Printer.pr_inductive (Global.env ()) ind ++ str " is needed.");
in (if Array.equal Constr.equal eA [||] then e else mkApp(e,eA)), eff
(**********************************************************************)
diff --git a/vernac/auto_ind_decl.mli b/vernac/auto_ind_decl.mli
index 11f26c7c36..647ff3d8d6 100644
--- a/vernac/auto_ind_decl.mli
+++ b/vernac/auto_ind_decl.mli
@@ -27,6 +27,8 @@ exception ParameterWithoutEquality of GlobRef.t
exception NonSingletonProp of inductive
exception DecidabilityMutualNotSupported
exception NoDecidabilityCoInductive
+exception ConstructorWithNonParametricInductiveType of inductive
+exception DecidabilityIndicesNotSupported
val beq_scheme_kind : mutual scheme_kind
val build_beq_scheme : mutual_scheme_object_function
diff --git a/vernac/classes.ml b/vernac/classes.ml
index bf734ab36d..c738d14af9 100644
--- a/vernac/classes.ml
+++ b/vernac/classes.ml
@@ -42,7 +42,7 @@ let typeclasses_db = "typeclass_instances"
let set_typeclass_transparency c local b =
Hints.add_hints ~local [typeclasses_db]
- (Hints.HintsTransparencyEntry (Vernacexpr.HintsReferences [c], b))
+ (Hints.HintsTransparencyEntry (Hints.HintsReferences [c], b))
let _ =
Hook.set Typeclasses.add_instance_hint_hook
@@ -121,19 +121,167 @@ let declare_instance_constant k info global imps ?hook id decl poly sigma term t
Evd.restrict_universe_context sigma levels
in
let uctx = Evd.check_univ_decl ~poly sigma decl in
- let entry =
- Declare.definition_entry ~types:termtype ~univs:uctx term
- in
+ let entry = Declare.definition_entry ~types:termtype ~univs:uctx term in
let cdecl = (DefinitionEntry entry, kind) in
let kn = Declare.declare_constant id cdecl in
- Declare.definition_message id;
- Declare.declare_univ_binders (ConstRef kn) (Evd.universe_binders sigma);
- instance_hook k info global imps ?hook (ConstRef kn);
- id
+ Declare.definition_message id;
+ Declare.declare_univ_binders (ConstRef kn) (Evd.universe_binders sigma);
+ instance_hook k info global imps ?hook (ConstRef kn)
+
+let do_abstract_instance env sigma ?hook ~global ~poly k u ctx ctx' pri decl imps subst id =
+ let subst = List.fold_left2
+ (fun subst' s decl -> if is_local_assum decl then s :: subst' else subst')
+ [] subst (snd k.cl_context)
+ in
+ let (_, ty_constr) = instance_constructor (k,u) subst in
+ let termtype = it_mkProd_or_LetIn ty_constr (ctx' @ ctx) in
+ let sigma = Evd.minimize_universes sigma in
+ Pretyping.check_evars env (Evd.from_env env) sigma termtype;
+ let univs = Evd.check_univ_decl ~poly sigma decl in
+ let termtype = to_constr sigma termtype in
+ let cst = Declare.declare_constant ~internal:Declare.InternalTacticRequest id
+ (ParameterEntry
+ (None,(termtype,univs),None), Decl_kinds.IsAssumption Decl_kinds.Logical)
+ in
+ Declare.declare_univ_binders (ConstRef cst) (Evd.universe_binders sigma);
+ instance_hook k pri global imps ?hook (ConstRef cst); id
-let new_instance ?(abstract=false) ?(global=false) ?(refine= !refine_instance)
- ~program_mode poly ctx (instid, bk, cl) props ?(generalize=true)
- ?(tac:unit Proofview.tactic option) ?hook pri =
+let declare_instance_open env sigma ?hook ~tac ~program_mode ~global ~poly k id pri imps decl len term termtype =
+ let kind = Decl_kinds.Global, poly, Decl_kinds.DefinitionBody Decl_kinds.Instance in
+ if program_mode then
+ let hook vis gr _ =
+ let cst = match gr with ConstRef kn -> kn | _ -> assert false in
+ Impargs.declare_manual_implicits false gr ~enriching:false [imps];
+ let pri = intern_info pri in
+ Typeclasses.declare_instance (Some pri) (not global) (ConstRef cst)
+ in
+ let obls, constr, typ =
+ match term with
+ | Some t ->
+ let obls, _, constr, typ =
+ Obligations.eterm_obligations env id sigma 0 t termtype
+ in obls, Some constr, typ
+ | None -> [||], None, termtype
+ in
+ let hook = Lemmas.mk_hook hook in
+ let ctx = Evd.evar_universe_context sigma in
+ ignore (Obligations.add_definition id ?term:constr
+ ~univdecl:decl typ ctx ~kind:(Global,poly,Instance) ~hook obls)
+ else
+ Flags.silently (fun () ->
+ (* spiwack: it is hard to reorder the actions to do
+ the pretyping after the proof has opened. As a
+ consequence, we use the low-level primitives to code
+ the refinement manually.*)
+ let gls = List.rev (Evd.future_goals sigma) in
+ let sigma = Evd.reset_future_goals sigma in
+ Lemmas.start_proof id ~pl:decl kind sigma (EConstr.of_constr termtype)
+ (Lemmas.mk_hook
+ (fun _ -> instance_hook k pri global imps ?hook));
+ (* spiwack: I don't know what to do with the status here. *)
+ if not (Option.is_empty term) then
+ let init_refine =
+ Tacticals.New.tclTHENLIST [
+ Refine.refine ~typecheck:false (fun sigma -> (sigma,EConstr.of_constr (Option.get term)));
+ Proofview.Unsafe.tclNEWGOALS (CList.map Proofview.with_empty_state gls);
+ Tactics.New.reduce_after_refine;
+ ]
+ in
+ ignore (Pfedit.by init_refine)
+ else if Flags.is_auto_intros () then
+ ignore (Pfedit.by (Tacticals.New.tclDO len Tactics.intro));
+ (match tac with Some tac -> ignore (Pfedit.by tac) | None -> ())) ()
+
+let do_transparent_instance env env' sigma ?hook ~refine ~tac ~global ~poly ~program_mode cty k u ctx ctx' pri decl imps subst id props len =
+ let props =
+ match props with
+ | Some (true, { CAst.v = CRecord fs }) ->
+ if List.length fs > List.length k.cl_props then
+ mismatched_props env' (List.map snd fs) k.cl_props;
+ Some (Inl fs)
+ | Some (_, t) -> Some (Inr t)
+ | None ->
+ if program_mode then Some (Inl [])
+ else None
+ in
+ let subst, sigma =
+ match props with
+ | None ->
+ (if List.is_empty k.cl_props then Some (Inl subst) else None), sigma
+ | Some (Inr term) ->
+ let sigma, c = interp_casted_constr_evars env' sigma term cty in
+ Some (Inr (c, subst)), sigma
+ | Some (Inl props) ->
+ let get_id qid = CAst.make ?loc:qid.CAst.loc @@ qualid_basename qid in
+ let props, rest =
+ List.fold_left
+ (fun (props, rest) decl ->
+ if is_local_assum decl then
+ try
+ let is_id (id', _) = match RelDecl.get_name decl, get_id id' with
+ | Name id, {CAst.v=id'} -> Id.equal id id'
+ | Anonymous, _ -> false
+ in
+ let (loc_mid, c) = List.find is_id rest in
+ let rest' = List.filter (fun v -> not (is_id v)) rest
+ in
+ let {CAst.loc;v=mid} = get_id loc_mid in
+ List.iter (fun (n, _, x) ->
+ if Name.equal n (Name mid) then
+ Option.iter (fun x -> Dumpglob.add_glob ?loc (ConstRef x)) x) k.cl_projs;
+ c :: props, rest'
+ with Not_found ->
+ ((CAst.make @@ CHole (None(* Some Evar_kinds.GoalEvar *), Namegen.IntroAnonymous, None)) :: props), rest
+ else props, rest)
+ ([], props) k.cl_props
+ in
+ match rest with
+ | (n, _) :: _ ->
+ unbound_method env' k.cl_impl (get_id n)
+ | _ ->
+ let kcl_props = List.map (Termops.map_rel_decl of_constr) k.cl_props in
+ let sigma, res = type_ctx_instance (push_rel_context ctx' env') sigma kcl_props props subst in
+ Some (Inl res), sigma
+ in
+ let term, termtype =
+ match subst with
+ | None -> let termtype = it_mkProd_or_LetIn cty ctx in
+ None, termtype
+ | Some (Inl subst) ->
+ let subst = List.fold_left2
+ (fun subst' s decl -> if is_local_assum decl then s :: subst' else subst')
+ [] subst (k.cl_props @ snd k.cl_context)
+ in
+ let (app, ty_constr) = instance_constructor (k,u) subst in
+ let termtype = it_mkProd_or_LetIn ty_constr (ctx' @ ctx) in
+ let term = it_mkLambda_or_LetIn (Option.get app) (ctx' @ ctx) in
+ Some term, termtype
+ | Some (Inr (def, subst)) ->
+ let termtype = it_mkProd_or_LetIn cty ctx in
+ let term = it_mkLambda_or_LetIn def ctx in
+ Some term, termtype
+ in
+ let sigma = Evarutil.nf_evar_map sigma in
+ let sigma = Typeclasses.resolve_typeclasses ~filter:Typeclasses.no_goals_or_obligations ~fail:true env sigma in
+ (* Try resolving fields that are typeclasses automatically. *)
+ let sigma = Typeclasses.resolve_typeclasses ~filter:Typeclasses.all_evars ~fail:false env sigma in
+ let sigma = Evarutil.nf_evar_map_undefined sigma in
+ (* Beware of this step, it is required as to minimize universes. *)
+ let sigma = Evd.minimize_universes sigma in
+ (* Check that the type is free of evars now. *)
+ Pretyping.check_evars env (Evd.from_env env) sigma termtype;
+ let termtype = to_constr sigma termtype in
+ let term = Option.map (to_constr ~abort_on_undefined_evars:false sigma) term in
+ if not (Evd.has_undefined sigma) && not (Option.is_empty term) then
+ declare_instance_constant k pri global imps ?hook id decl poly sigma (Option.get term) termtype
+ else if program_mode || refine || Option.is_empty term then
+ declare_instance_open env sigma ?hook ~tac ~program_mode ~global ~poly k id pri imps decl len term termtype
+ else CErrors.user_err Pp.(str "Unsolved obligations remaining.");
+ id
+
+let new_instance ?(abstract=false) ?(global=false) ?(refine= !refine_instance) ~program_mode
+ poly ctx (instid, bk, cl) props
+ ?(generalize=true) ?(tac:unit Proofview.tactic option) ?hook pri =
let env = Global.env() in
let ({CAst.loc;v=instid}, pl) = instid in
let sigma, decl = Constrexpr_ops.interp_univ_decl_opt env pl in
@@ -150,9 +298,9 @@ let new_instance ?(abstract=false) ?(global=false) ?(refine= !refine_instance)
cl
| Explicit -> cl, Id.Set.empty
in
- let tclass =
- if generalize then CAst.make @@ CGeneralization (Implicit, Some AbsPi, tclass)
- else tclass
+ let tclass =
+ if generalize then CAst.make @@ CGeneralization (Implicit, Some AbsPi, tclass)
+ else tclass
in
let sigma, k, u, cty, ctx', ctx, len, imps, subst =
let sigma, (impls, ((env', ctx), imps)) = interp_context_evars env sigma ctx in
@@ -189,163 +337,12 @@ let new_instance ?(abstract=false) ?(global=false) ?(refine= !refine_instance)
let env' = push_rel_context ctx env in
let sigma = Evarutil.nf_evar_map sigma in
let sigma = resolve_typeclasses ~filter:Typeclasses.all_evars ~fail:true env sigma in
- if abstract then
- begin
- let subst = List.fold_left2
- (fun subst' s decl -> if is_local_assum decl then s :: subst' else subst')
- [] subst (snd k.cl_context)
- in
- let (_, ty_constr) = instance_constructor (k,u) subst in
- let termtype = it_mkProd_or_LetIn ty_constr (ctx' @ ctx) in
- let sigma = Evd.minimize_universes sigma in
- Pretyping.check_evars env (Evd.from_env env) sigma termtype;
- let univs = Evd.check_univ_decl ~poly sigma decl in
- let termtype = to_constr sigma termtype in
- let cst = Declare.declare_constant ~internal:Declare.InternalTacticRequest id
- (ParameterEntry
- (None,(termtype,univs),None), Decl_kinds.IsAssumption Decl_kinds.Logical)
- in
- Declare.declare_univ_binders (ConstRef cst) (Evd.universe_binders sigma);
- instance_hook k pri global imps ?hook (ConstRef cst); id
- end
- else (
- let props =
- match props with
- | Some (true, { CAst.v = CRecord fs }) ->
- if List.length fs > List.length k.cl_props then
- mismatched_props env' (List.map snd fs) k.cl_props;
- Some (Inl fs)
- | Some (_, t) -> Some (Inr t)
- | None ->
- if program_mode then Some (Inl [])
- else None
- in
- let subst, sigma =
- match props with
- | None ->
- (if List.is_empty k.cl_props then Some (Inl subst) else None), sigma
- | Some (Inr term) ->
- let sigma, c = interp_casted_constr_evars env' sigma term cty in
- Some (Inr (c, subst)), sigma
- | Some (Inl props) ->
- let get_id qid = CAst.make ?loc:qid.CAst.loc @@ qualid_basename qid in
- let props, rest =
- List.fold_left
- (fun (props, rest) decl ->
- if is_local_assum decl then
- try
- let is_id (id', _) = match RelDecl.get_name decl, get_id id' with
- | Name id, {CAst.v=id'} -> Id.equal id id'
- | Anonymous, _ -> false
- in
- let (loc_mid, c) =
- List.find is_id rest
- in
- let rest' =
- List.filter (fun v -> not (is_id v)) rest
- in
- let {CAst.loc;v=mid} = get_id loc_mid in
- List.iter (fun (n, _, x) ->
- if Name.equal n (Name mid) then
- Option.iter (fun x -> Dumpglob.add_glob ?loc (ConstRef x)) x)
- k.cl_projs;
- c :: props, rest'
- with Not_found ->
- ((CAst.make @@ CHole (None(* Some Evar_kinds.GoalEvar *), Namegen.IntroAnonymous, None)) :: props), rest
- else props, rest)
- ([], props) k.cl_props
- in
- match rest with
- | (n, _) :: _ ->
- unbound_method env' k.cl_impl (get_id n)
- | _ ->
- let kcl_props = List.map (Termops.map_rel_decl of_constr) k.cl_props in
- let sigma, res = type_ctx_instance (push_rel_context ctx' env') sigma kcl_props props subst in
- Some (Inl res), sigma
- in
- let term, termtype =
- match subst with
- | None -> let termtype = it_mkProd_or_LetIn cty ctx in
- None, termtype
- | Some (Inl subst) ->
- let subst = List.fold_left2
- (fun subst' s decl -> if is_local_assum decl then s :: subst' else subst')
- [] subst (k.cl_props @ snd k.cl_context)
- in
- let (app, ty_constr) = instance_constructor (k,u) subst in
- let termtype = it_mkProd_or_LetIn ty_constr (ctx' @ ctx) in
- let term = it_mkLambda_or_LetIn (Option.get app) (ctx' @ ctx) in
- Some term, termtype
- | Some (Inr (def, subst)) ->
- let termtype = it_mkProd_or_LetIn cty ctx in
- let term = it_mkLambda_or_LetIn def ctx in
- Some term, termtype
- in
- let sigma = Evarutil.nf_evar_map sigma in
- let sigma = Typeclasses.resolve_typeclasses ~filter:Typeclasses.no_goals_or_obligations ~fail:true env sigma in
- (* Try resolving fields that are typeclasses automatically. *)
- let sigma = Typeclasses.resolve_typeclasses ~filter:Typeclasses.all_evars ~fail:false env sigma in
- let sigma = Evarutil.nf_evar_map_undefined sigma in
- (* Beware of this step, it is required as to minimize universes. *)
- let sigma = Evd.minimize_universes sigma in
- (* Check that the type is free of evars now. *)
- Pretyping.check_evars env (Evd.from_env env) sigma termtype;
- let termtype = to_constr sigma termtype in
- let term = Option.map (to_constr ~abort_on_undefined_evars:false sigma) term in
- if not (Evd.has_undefined sigma) && not (Option.is_empty term) then
- declare_instance_constant k pri global imps ?hook id decl
- poly sigma (Option.get term) termtype
- else if program_mode || refine || Option.is_empty term then begin
- let kind = Decl_kinds.Global, poly, Decl_kinds.DefinitionBody Decl_kinds.Instance in
- if program_mode then
- let hook vis gr _ =
- let cst = match gr with ConstRef kn -> kn | _ -> assert false in
- Impargs.declare_manual_implicits false gr ~enriching:false [imps];
- let pri = intern_info pri in
- Typeclasses.declare_instance (Some pri) (not global) (ConstRef cst)
- in
- let obls, constr, typ =
- match term with
- | Some t ->
- let obls, _, constr, typ =
- Obligations.eterm_obligations env id sigma 0 t termtype
- in obls, Some constr, typ
- | None -> [||], None, termtype
- in
- let hook = Lemmas.mk_hook hook in
- let ctx = Evd.evar_universe_context sigma in
- ignore (Obligations.add_definition id ?term:constr
- ~univdecl:decl typ ctx ~kind:(Global,poly,Instance) ~hook obls);
- id
- else
- (Flags.silently
- (fun () ->
- (* spiwack: it is hard to reorder the actions to do
- the pretyping after the proof has opened. As a
- consequence, we use the low-level primitives to code
- the refinement manually.*)
- let gls = List.rev (Evd.future_goals sigma) in
- let sigma = Evd.reset_future_goals sigma in
- Lemmas.start_proof id ~pl:decl kind sigma (EConstr.of_constr termtype)
- (Lemmas.mk_hook
- (fun _ -> instance_hook k pri global imps ?hook));
- (* spiwack: I don't know what to do with the status here. *)
- if not (Option.is_empty term) then
- let init_refine =
- Tacticals.New.tclTHENLIST [
- Refine.refine ~typecheck:false (fun sigma -> (sigma,EConstr.of_constr (Option.get term)));
- Proofview.Unsafe.tclNEWGOALS (CList.map Proofview.with_empty_state gls);
- Tactics.New.reduce_after_refine;
- ]
- in
- ignore (Pfedit.by init_refine)
- else if Flags.is_auto_intros () then
- ignore (Pfedit.by (Tacticals.New.tclDO len Tactics.intro));
- (match tac with Some tac -> ignore (Pfedit.by tac) | None -> ())) ();
- id)
- end
- else CErrors.user_err Pp.(str "Unsolved obligations remaining."))
-
+ if abstract then
+ do_abstract_instance env sigma ?hook ~global ~poly k u ctx ctx' pri decl imps subst id
+ else
+ do_transparent_instance env env' sigma ?hook ~refine ~tac ~global ~poly ~program_mode
+ cty k u ctx ctx' pri decl imps subst id props len
+
let named_of_rel_context l =
let open Vars in
let acc, ctx =
@@ -433,5 +430,5 @@ let context poly l =
Lib.sections_are_opened () || Lib.is_modtype_strict ()
in
status && nstatus
- in
+ in
List.fold_left fn true (List.rev ctx)
diff --git a/vernac/classes.mli b/vernac/classes.mli
index 9c37364cb0..bb70334342 100644
--- a/vernac/classes.mli
+++ b/vernac/classes.mli
@@ -37,7 +37,7 @@ val declare_instance_constant :
Evd.evar_map -> (* Universes *)
Constr.t -> (** body *)
Constr.types -> (** type *)
- Names.Id.t
+ unit
val new_instance :
?abstract:bool -> (** Not abstract by default. *)
diff --git a/vernac/comInductive.ml b/vernac/comInductive.ml
index ad1ffa35a1..7b28895814 100644
--- a/vernac/comInductive.ml
+++ b/vernac/comInductive.ml
@@ -35,6 +35,18 @@ module RelDecl = Context.Rel.Declaration
(* 3b| Mutual inductive definitions *)
+let should_auto_template =
+ let open Goptions in
+ let auto = ref true in
+ let _ = declare_bool_option
+ { optdepr = false;
+ optname = "Automatically make some inductive types template polymorphic";
+ optkey = ["Auto";"Template";"Polymorphism"];
+ optread = (fun () -> !auto);
+ optwrite = (fun b -> auto := b); }
+ in
+ fun () -> !auto
+
let rec complete_conclusion a cs = CAst.map_with_loc (fun ?loc -> function
| CProdN (bl,c) -> CProdN (bl,complete_conclusion a cs c)
| CLetIn (na,b,t,c) -> CLetIn (na,b,t,complete_conclusion a cs c)
@@ -55,7 +67,6 @@ let push_types env idl tl =
type structured_one_inductive_expr = {
ind_name : Id.t;
- ind_univs : universe_decl_expr option;
ind_arity : constr_expr;
ind_lc : (Id.t * constr_expr) list
}
@@ -113,17 +124,16 @@ let rec check_anonymous_type ind =
| GCast (e, _) -> check_anonymous_type e
| _ -> false
-let make_conclusion_flexible sigma ty poly =
- if poly && Term.isArity ty then
- let _, concl = Term.destArity ty in
- match concl with
- | Type u ->
- (match Univ.universe_level u with
+let make_conclusion_flexible sigma = function
+ | None -> sigma
+ | Some s ->
+ (match EConstr.ESorts.kind sigma s with
+ | Type u ->
+ (match Univ.universe_level u with
| Some u ->
Evd.make_flexible_variable sigma ~algebraic:true u
| None -> sigma)
- | _ -> sigma
- else sigma
+ | _ -> sigma)
let is_impredicative env u =
u = Prop || (is_impredicative_set env && u = Set)
@@ -133,10 +143,12 @@ let interp_ind_arity env sigma ind =
let impls = Implicit_quantifiers.implicits_of_glob_constr ~with_products:true c in
let sigma,t = understand_tcc env sigma ~expected_type:IsType c in
let pseudo_poly = check_anonymous_type c in
- let () = if not (Reductionops.is_arity env sigma t) then
+ match Reductionops.sort_of_arity env sigma t with
+ | exception Invalid_argument _ ->
user_err ?loc:(constr_loc ind.ind_arity) (str "Not an arity")
- in
- sigma, (t, pseudo_poly, impls)
+ | s ->
+ let concl = if pseudo_poly then Some s else None in
+ sigma, (t, concl, impls)
let interp_cstrs env sigma impls mldata arity ind =
let cnames,ctyps = List.split ind.ind_lc in
@@ -326,13 +338,21 @@ let check_param = function
| CLocalPattern {CAst.loc} ->
Loc.raise ?loc (Stream.Error "pattern with quote not allowed here")
-let interp_mutual_inductive_gen env0 (uparamsl,paramsl,indl) notations cum poly prv finite =
+let restrict_inductive_universes sigma ctx_params arities constructors =
+ let merge_universes_of_constr c =
+ Univ.LSet.union (EConstr.universes_of_constr sigma (EConstr.of_constr c)) in
+ let uvars = Univ.LSet.empty in
+ let uvars = Context.Rel.(fold_outside (Declaration.fold_constr merge_universes_of_constr) ctx_params ~init:uvars) in
+ let uvars = List.fold_right merge_universes_of_constr arities uvars in
+ let uvars = List.fold_right (fun (_,ctypes,_) -> List.fold_right merge_universes_of_constr ctypes) constructors uvars in
+ Evd.restrict_universe_context sigma uvars
+
+let interp_mutual_inductive_gen env0 ~template udecl (uparamsl,paramsl,indl) notations cum poly prv finite =
check_all_names_different indl;
List.iter check_param paramsl;
if not (List.is_empty uparamsl) && not (List.is_empty notations)
then user_err (str "Inductives with uniform parameters may not have attached notations.");
- let pl = (List.hd indl).ind_univs in
- let sigma, decl = interp_univ_decl_opt env0 pl in
+ let sigma, udecl = interp_univ_decl_opt env0 udecl in
let sigma, (uimpls, ((env_uparams, ctx_uparams), useruimpls)) =
interp_context_evars env0 sigma uparamsl in
let sigma, (impls, ((env_params, ctx_params), userimpls)) =
@@ -354,7 +374,7 @@ let interp_mutual_inductive_gen env0 (uparamsl,paramsl,indl) notations cum poly
(* Compute interpretation metadatas *)
let indimpls = List.map (fun (_, _, impls) -> userimpls @
lift_implicits (Context.Rel.nhyps ctx_params) impls) arities in
- let arities = List.map pi1 arities and aritypoly = List.map pi2 arities in
+ let arities = List.map pi1 arities and arityconcl = List.map pi2 arities in
let impls = compute_internalization_env env_uparams sigma ~impls (Inductive (params,true)) indnames fullarities indimpls in
let ntn_impls = compute_internalization_env env_uparams sigma (Inductive (params,true)) indnames fullarities indimpls in
let mldatas = List.map2 (mk_mltype_data sigma env_params params) arities indnames in
@@ -393,14 +413,16 @@ let interp_mutual_inductive_gen env0 (uparamsl,paramsl,indl) notations cum poly
let nf = Evarutil.nf_evars_universes sigma in
let constructors = List.map (fun (idl,cl,impsl) -> (idl,List.map nf cl,impsl)) constructors in
let arities = List.map EConstr.(to_constr sigma) arities in
- let sigma = List.fold_left2 (fun sigma ty poly -> make_conclusion_flexible sigma ty poly) sigma arities aritypoly in
+ let sigma = List.fold_left make_conclusion_flexible sigma arityconcl in
let sigma, arities = inductive_levels env_ar_params sigma poly arities constructors in
let sigma = Evd.minimize_universes sigma in
let nf = Evarutil.nf_evars_universes sigma in
let arities = List.map nf arities in
let constructors = List.map (fun (idl,cl,impsl) -> (idl,List.map nf cl,impsl)) constructors in
let ctx_params = List.map Termops.(map_rel_decl (EConstr.to_constr sigma)) ctx_params in
- let uctx = Evd.check_univ_decl ~poly sigma decl in
+ let arityconcl = List.map (Option.map (EConstr.ESorts.kind sigma)) arityconcl in
+ let sigma = restrict_inductive_universes sigma ctx_params arities constructors in
+ let uctx = Evd.check_univ_decl ~poly sigma udecl in
List.iter (fun c -> check_evars env_params (Evd.from_env env_params) sigma (EConstr.of_constr c)) arities;
Context.Rel.iter (fun c -> check_evars env0 (Evd.from_env env0) sigma (EConstr.of_constr c)) ctx_params;
List.iter (fun (_,ctyps,_) ->
@@ -408,13 +430,23 @@ let interp_mutual_inductive_gen env0 (uparamsl,paramsl,indl) notations cum poly
constructors;
(* Build the inductive entries *)
- let entries = List.map4 (fun ind arity template (cnames,ctypes,cimpls) -> {
- mind_entry_typename = ind.ind_name;
- mind_entry_arity = arity;
- mind_entry_template = template;
- mind_entry_consnames = cnames;
- mind_entry_lc = ctypes
- }) indl arities aritypoly constructors in
+ let entries = List.map4 (fun ind arity concl (cnames,ctypes,cimpls) ->
+ let template = match template with
+ | Some template ->
+ if poly && template then user_err Pp.(strbrk "template and polymorphism not compatible");
+ template
+ | None ->
+ should_auto_template () && not poly &&
+ Option.cata (fun s -> not (Sorts.is_small s)) false concl
+ in
+ { mind_entry_typename = ind.ind_name;
+ mind_entry_arity = arity;
+ mind_entry_template = template;
+ mind_entry_consnames = cnames;
+ mind_entry_lc = ctypes
+ })
+ indl arities arityconcl constructors
+ in
let impls =
let len = Context.Rel.nhyps ctx_params in
List.map2 (fun indimpls (_,_,cimpls) ->
@@ -444,8 +476,8 @@ let interp_mutual_inductive_gen env0 (uparamsl,paramsl,indl) notations cum poly
InferCumulativity.infer_inductive env_ar mind_ent
else mind_ent), Evd.universe_binders sigma, impls
-let interp_mutual_inductive (paramsl,indl) notations cum poly prv finite =
- interp_mutual_inductive_gen (Global.env()) ([],paramsl,indl) notations cum poly prv finite
+let interp_mutual_inductive ~template udecl (paramsl,indl) notations cum poly prv finite =
+ interp_mutual_inductive_gen (Global.env()) ~template udecl ([],paramsl,indl) notations cum poly prv finite
(* Very syntactical equality *)
let eq_local_binders bl1 bl2 =
@@ -466,8 +498,8 @@ let extract_params indl =
params
let extract_inductive indl =
- List.map (fun (({CAst.v=indname},pl),_,ar,lc) -> {
- ind_name = indname; ind_univs = pl;
+ List.map (fun ({CAst.v=indname},_,ar,lc) -> {
+ ind_name = indname;
ind_arity = Option.cata (fun x -> x) (CAst.make @@ CSort (Glob_term.GType [])) ar;
ind_lc = List.map (fun (_,({CAst.v=id},t)) -> (id,t)) lc
}) indl
@@ -533,11 +565,11 @@ type uniform_inductive_flag =
| UniformParameters
| NonUniformParameters
-let do_mutual_inductive indl cum poly prv ~uniform finite =
+let do_mutual_inductive ~template udecl indl cum poly prv ~uniform finite =
let (params,indl),coes,ntns = extract_mutual_inductive_declaration_components indl in
(* Interpret the types *)
let indl = match uniform with UniformParameters -> (params, [], indl) | NonUniformParameters -> ([], params, indl) in
- let mie,pl,impls = interp_mutual_inductive_gen (Global.env()) indl ntns cum poly prv finite in
+ let mie,pl,impls = interp_mutual_inductive_gen (Global.env()) ~template udecl indl ntns cum poly prv finite in
(* Declare the mutual inductive block with its associated schemes *)
ignore (declare_mutual_inductive_with_eliminations mie pl impls);
(* Declare the possible notations of inductive types *)
diff --git a/vernac/comInductive.mli b/vernac/comInductive.mli
index 4e30ed7de5..f23085a538 100644
--- a/vernac/comInductive.mli
+++ b/vernac/comInductive.mli
@@ -24,6 +24,7 @@ type uniform_inductive_flag =
| NonUniformParameters
val do_mutual_inductive :
+ template:bool option -> universe_decl_expr option ->
(one_inductive_expr * decl_notation list) list -> cumulative_inductive_flag ->
polymorphic -> private_flag -> uniform:uniform_inductive_flag ->
Declarations.recursivity_kind -> unit
@@ -45,6 +46,8 @@ val declare_mutual_inductive_with_eliminations :
mutual_inductive_entry -> UnivNames.universe_binders -> one_inductive_impls list ->
MutInd.t
+val should_auto_template : unit -> bool
+
(** Exported for Funind *)
(** Extracting the semantical components out of the raw syntax of mutual
@@ -52,7 +55,6 @@ val declare_mutual_inductive_with_eliminations :
type structured_one_inductive_expr = {
ind_name : Id.t;
- ind_univs : universe_decl_expr option;
ind_arity : constr_expr;
ind_lc : (Id.t * constr_expr) list
}
@@ -67,6 +69,7 @@ val extract_mutual_inductive_declaration_components :
(** Typing mutual inductive definitions *)
val interp_mutual_inductive :
- structured_inductive_expr -> decl_notation list -> cumulative_inductive_flag ->
+ template:bool option -> universe_decl_expr option -> structured_inductive_expr ->
+ decl_notation list -> cumulative_inductive_flag ->
polymorphic -> private_flag -> Declarations.recursivity_kind ->
mutual_inductive_entry * UnivNames.universe_binders * one_inductive_impls list
diff --git a/vernac/dune b/vernac/dune
new file mode 100644
index 0000000000..45b567d631
--- /dev/null
+++ b/vernac/dune
@@ -0,0 +1,16 @@
+(library
+ (name vernac)
+ (synopsis "Coq's Vernacular Language")
+ (public_name coq.vernac)
+ (wrapped false)
+ (libraries tactics parsing))
+
+(rule
+ (targets g_proofs.ml)
+ (deps (:mlg-file g_proofs.mlg))
+ (action (run coqpp %{mlg-file})))
+
+(rule
+ (targets g_vernac.ml)
+ (deps (:mlg-file g_vernac.mlg))
+ (action (run coqpp %{mlg-file})))
diff --git a/vernac/explainErr.ml b/vernac/explainErr.ml
index 504e7095b0..b37fce645a 100644
--- a/vernac/explainErr.ml
+++ b/vernac/explainErr.ml
@@ -64,6 +64,8 @@ let process_vernac_interp_error exn = match fst exn with
wrap_vernac_error exn (Himsg.explain_type_error ctx Evd.empty te)
| PretypeError(ctx,sigma,te) ->
wrap_vernac_error exn (Himsg.explain_pretype_error ctx sigma te)
+ | Notation.NumeralNotationError(ctx,sigma,te) ->
+ wrap_vernac_error exn (Himsg.explain_numeral_notation_error ctx sigma te)
| Typeclasses_errors.TypeClassError(env, te) ->
wrap_vernac_error exn (Himsg.explain_typeclass_error env te)
| Implicit_quantifiers.MismatchedContextInstance(e,c,l,x) ->
@@ -74,8 +76,8 @@ let process_vernac_interp_error exn = match fst exn with
wrap_vernac_error exn (Himsg.explain_module_error e)
| Modintern.ModuleInternalizationError e ->
wrap_vernac_error exn (Himsg.explain_module_internalization_error e)
- | RecursionSchemeError e ->
- wrap_vernac_error exn (Himsg.explain_recursion_scheme_error e)
+ | RecursionSchemeError (env,e) ->
+ wrap_vernac_error exn (Himsg.explain_recursion_scheme_error env e)
| Cases.PatternMatchingError (env,sigma,e) ->
wrap_vernac_error exn (Himsg.explain_pattern_matching_error env sigma e)
| Tacred.ReductionTacticError e ->
diff --git a/vernac/g_proofs.mlg b/vernac/g_proofs.mlg
index dacef6e211..ecc7d3ff88 100644
--- a/vernac/g_proofs.mlg
+++ b/vernac/g_proofs.mlg
@@ -13,6 +13,7 @@
open Glob_term
open Constrexpr
open Vernacexpr
+open Hints
open Proof_global
open Pcoq
diff --git a/vernac/g_vernac.mlg b/vernac/g_vernac.mlg
index b959f2afa9..7dd5471f3f 100644
--- a/vernac/g_vernac.mlg
+++ b/vernac/g_vernac.mlg
@@ -59,7 +59,7 @@ let make_bullet s =
| '*' -> Star n
| _ -> assert false
-let parse_compat_version ?(allow_old = true) = let open Flags in function
+let parse_compat_version = let open Flags in function
| "8.8" -> Current
| "8.7" -> V8_7
| "8.6" -> V8_6
@@ -83,11 +83,10 @@ GRAMMAR EXTEND Gram
]
;
decorated_vernac:
- [ [ a = attributes ; fv = vernac -> { let (f, v) = fv in (List.append a f, v) }
- | fv = vernac -> { fv } ]
- ]
+ [ [ a = LIST0 quoted_attributes ; fv = vernac ->
+ { let (f, v) = fv in (List.append (List.flatten a) f, v) } ] ]
;
- attributes:
+ quoted_attributes:
[ [ "#[" ; a = attribute_list ; "]" -> { a } ]
]
;
@@ -212,8 +211,10 @@ GRAMMAR EXTEND Gram
| IDENT "Scheme"; l = LIST1 scheme SEP "with" -> { VernacScheme l }
| IDENT "Combined"; IDENT "Scheme"; id = identref; IDENT "from";
l = LIST1 identref SEP "," -> { VernacCombinedScheme (id, l) }
- | IDENT "Register"; IDENT "Inline"; id = identref ->
- { VernacRegister(id, RegisterInline) }
+ | IDENT "Register"; g = global; "as"; quid = qualid ->
+ { VernacRegister(g, RegisterRetroknowledge quid) }
+ | IDENT "Register"; IDENT "Inline"; g = global ->
+ { VernacRegister(g, RegisterInline) }
| IDENT "Universe"; l = LIST1 identref -> { VernacUniverse l }
| IDENT "Universes"; l = LIST1 identref -> { VernacUniverse l }
| IDENT "Constraint"; l = LIST1 univ_constraint SEP "," -> { VernacConstraint l }
@@ -846,6 +847,10 @@ GRAMMAR EXTEND Gram
info = hint_info ->
{ VernacInstance (true, snd namesup, (fst namesup, expl, t), None, info) }
+ (* Should be in syntax, but camlp5 would not factorize *)
+ | IDENT "Declare"; IDENT "Scope"; sc = IDENT ->
+ { VernacDeclareScope sc }
+
(* System directory *)
| IDENT "Pwd" -> { VernacChdir None }
| IDENT "Cd" -> { VernacChdir None }
@@ -1141,8 +1146,8 @@ GRAMMAR EXTEND Gram
l = [ "("; l = LIST1 syntax_modifier SEP ","; ")" -> { l } | -> { [] } ]
-> { VernacSyntaxExtension (false, (s,l)) }
- (* "Print" "Grammar" should be here but is in "command" entry in order
- to factorize with other "Print"-based vernac entries *)
+ (* "Print" "Grammar" and "Declare" "Scope" should be here but are in "command" entry in order
+ to factorize with other "Print"-based or "Declare"-based vernac entries *)
] ]
;
only_parsing:
diff --git a/vernac/himsg.ml b/vernac/himsg.ml
index b9c47ff475..a4b3a75c9f 100644
--- a/vernac/himsg.ml
+++ b/vernac/himsg.ml
@@ -601,12 +601,12 @@ let explain_var_not_found env id =
spc () ++ str "in the current" ++ spc () ++ str "environment" ++ str "."
let explain_wrong_case_info env (ind,u) ci =
- let pi = pr_inductive (Global.env()) ind in
+ let pi = pr_inductive env ind in
if eq_ind ci.ci_ind ind then
str "Pattern-matching expression on an object of inductive type" ++
spc () ++ pi ++ spc () ++ str "has invalid information."
else
- let pc = pr_inductive (Global.env()) ci.ci_ind in
+ let pc = pr_inductive env ci.ci_ind in
str "A term of inductive type" ++ spc () ++ pi ++ spc () ++
str "was given to a pattern-matching expression on the inductive type" ++
spc () ++ pc ++ str "."
@@ -679,6 +679,11 @@ let explain_unsatisfied_constraints env sigma cst =
Univ.pr_constraints (Termops.pr_evd_level sigma) cst ++
spc () ++ str "(maybe a bugged tactic)."
+let explain_undeclared_universe env sigma l =
+ strbrk "Undeclared universe: " ++
+ Termops.pr_evd_level sigma l ++
+ spc () ++ str "(maybe a bugged tactic)."
+
let explain_type_error env sigma err =
let env = make_all_name_different env sigma in
match err with
@@ -716,6 +721,8 @@ let explain_type_error env sigma err =
explain_wrong_case_info env ind ci
| UnsatisfiedConstraints cst ->
explain_unsatisfied_constraints env sigma cst
+ | UndeclaredUniverse l ->
+ explain_undeclared_universe env sigma l
let pr_position (cl,pos) =
let clpos = match cl with
@@ -889,7 +896,8 @@ let explain_not_match_error = function
quote (Printer.safe_pr_lconstr_env env (Evd.from_env env) t2)
| IncompatibleConstraints cst ->
str " the expected (polymorphic) constraints do not imply " ++
- let cst = Univ.AUContext.instantiate (Univ.AUContext.instance cst) cst in
+ let cst = Univ.UContext.constraints (Univ.AUContext.repr cst) in
+ (** FIXME: provide a proper naming for the bound variables *)
quote (Univ.pr_constraints (Termops.pr_evd_level Evd.empty) cst)
let explain_signature_mismatch l spec why =
@@ -1148,24 +1156,24 @@ let error_large_non_prop_inductive_not_in_type () =
(* Recursion schemes errors *)
-let error_not_allowed_case_analysis isrec kind i =
+let error_not_allowed_case_analysis env isrec kind i =
str (if isrec then "Induction" else "Case analysis") ++
strbrk " on sort " ++ pr_sort Evd.empty kind ++
strbrk " is not allowed for inductive definition " ++
- pr_inductive (Global.env()) (fst i) ++ str "."
+ pr_inductive env (fst i) ++ str "."
-let error_not_allowed_dependent_analysis isrec i =
+let error_not_allowed_dependent_analysis env isrec i =
str "Dependent " ++ str (if isrec then "induction" else "case analysis") ++
strbrk " is not allowed for inductive definition " ++
- pr_inductive (Global.env()) i ++ str "."
+ pr_inductive env i ++ str "."
-let error_not_mutual_in_scheme ind ind' =
+let error_not_mutual_in_scheme env ind ind' =
if eq_ind ind ind' then
- str "The inductive type " ++ pr_inductive (Global.env()) ind ++
+ str "The inductive type " ++ pr_inductive env ind ++
str " occurs twice."
else
- str "The inductive types " ++ pr_inductive (Global.env()) ind ++ spc () ++
- str "and" ++ spc () ++ pr_inductive (Global.env()) ind' ++ spc () ++
+ str "The inductive types " ++ pr_inductive env ind ++ spc () ++
+ str "and" ++ spc () ++ pr_inductive env ind' ++ spc () ++
str "are not mutually defined."
(* Inductive constructions errors *)
@@ -1186,12 +1194,12 @@ let explain_inductive_error = function
(* Recursion schemes errors *)
-let explain_recursion_scheme_error = function
+let explain_recursion_scheme_error env = function
| NotAllowedCaseAnalysis (isrec,k,i) ->
- error_not_allowed_case_analysis isrec k i
- | NotMutualInScheme (ind,ind')-> error_not_mutual_in_scheme ind ind'
+ error_not_allowed_case_analysis env isrec k i
+ | NotMutualInScheme (ind,ind')-> error_not_mutual_in_scheme env ind ind'
| NotAllowedDependentAnalysis (isrec, i) ->
- error_not_allowed_dependent_analysis isrec i
+ error_not_allowed_dependent_analysis env isrec i
(* Pattern-matching errors *)
@@ -1299,6 +1307,7 @@ let map_ptype_error f = function
| IllTypedRecBody (n, na, jv, t) ->
IllTypedRecBody (n, na, Array.map (on_judgment f) jv, Array.map f t)
| UnsatisfiedConstraints g -> UnsatisfiedConstraints g
+| UndeclaredUniverse l -> UndeclaredUniverse l
let explain_reduction_tactic_error = function
| Tacred.InvalidAbstraction (env,sigma,c,(env',e)) ->
@@ -1307,3 +1316,13 @@ let explain_reduction_tactic_error = function
quote (pr_goal_concl_style_env env sigma c) ++
spc () ++ str "is not well typed." ++ fnl () ++
explain_type_error env' (Evd.from_env env') e
+
+let explain_numeral_notation_error env sigma = function
+ | Notation.UnexpectedTerm c ->
+ (strbrk "Unexpected term " ++
+ pr_constr_env env sigma c ++
+ strbrk " while parsing a numeral notation.")
+ | Notation.UnexpectedNonOptionTerm c ->
+ (strbrk "Unexpected non-option term " ++
+ pr_constr_env env sigma c ++
+ strbrk " while parsing a numeral notation.")
diff --git a/vernac/himsg.mli b/vernac/himsg.mli
index 91caddcf13..db05aaa125 100644
--- a/vernac/himsg.mli
+++ b/vernac/himsg.mli
@@ -29,7 +29,7 @@ val explain_mismatched_contexts : env -> contexts -> Constrexpr.constr_expr list
val explain_typeclass_error : env -> typeclass_error -> Pp.t
-val explain_recursion_scheme_error : recursion_scheme_error -> Pp.t
+val explain_recursion_scheme_error : env -> recursion_scheme_error -> Pp.t
val explain_refiner_error : env -> Evd.evar_map -> refiner_error -> Pp.t
@@ -46,3 +46,5 @@ val explain_module_internalization_error :
val map_pguard_error : ('c -> 'd) -> 'c pguard_error -> 'd pguard_error
val map_ptype_error : ('c -> 'd) -> ('c, 'c) ptype_error -> ('d, 'd) ptype_error
+
+val explain_numeral_notation_error : env -> Evd.evar_map -> Notation.numeral_notation_error -> Pp.t
diff --git a/vernac/indschemes.ml b/vernac/indschemes.ml
index e86e108772..b354ad0521 100644
--- a/vernac/indschemes.ml
+++ b/vernac/indschemes.ml
@@ -82,7 +82,7 @@ let _ =
let is_eq_flag () = !eq_flag
-let eq_dec_flag = ref false
+let eq_dec_flag = ref false
let _ =
declare_bool_option
{ optdepr = false;
@@ -142,7 +142,8 @@ let try_declare_scheme what f internal names kn =
try f internal names kn
with e ->
let e = CErrors.push e in
- let msg = match fst e with
+ let rec extract_exn = function Logic_monad.TacticFailure e -> extract_exn e | e -> e in
+ let msg = match extract_exn (fst e) with
| ParameterWithoutEquality cst ->
alarm what internal
(str "Boolean equality not found for parameter " ++ Printer.pr_global cst ++
@@ -176,6 +177,14 @@ let try_declare_scheme what f internal names kn =
| NoDecidabilityCoInductive ->
alarm what internal
(str "Scheme Equality is only for inductive types.")
+ | DecidabilityIndicesNotSupported ->
+ alarm what internal
+ (str "Inductive types with annotations not supported.")
+ | ConstructorWithNonParametricInductiveType ind ->
+ alarm what internal
+ (strbrk "Unsupported constructor with an argument whose type is a non-parametric inductive type." ++
+ strbrk " Type " ++ quote (Printer.pr_inductive (Global.env()) ind) ++
+ str " is applied to an argument which is not a variable.")
| e when CErrors.noncritical e ->
alarm what internal
(str "Unexpected error during scheme creation: " ++ CErrors.print e)
@@ -321,11 +330,10 @@ let declare_sym_scheme ind =
(* Scheme command *)
let smart_global_inductive y = smart_global_inductive y
-let rec split_scheme l =
- let env = Global.env() in
+let rec split_scheme env l =
match l with
| [] -> [],[]
- | (Some id,t)::q -> let l1,l2 = split_scheme q in
+ | (Some id,t)::q -> let l1,l2 = split_scheme env q in
( match t with
| InductionScheme (x,y,z) -> ((id,x,smart_global_inductive y,z)::l1),l2
| CaseScheme (x,y,z) -> ((id,x,smart_global_inductive y,z)::l1),l2
@@ -336,7 +344,7 @@ let rec split_scheme l =
requested
*)
| (None,t)::q ->
- let l1,l2 = split_scheme q in
+ let l1,l2 = split_scheme env q in
let names inds recs isdep y z =
let ind = smart_global_inductive y in
let sort_of_ind = inductive_sort_family (snd (lookup_mind_specif env ind)) in
@@ -375,7 +383,7 @@ let do_mutual_induction_scheme ?(force_mutual=false) lnamedepindsort =
and env0 = Global.env() in
let sigma, lrecspec, _ =
List.fold_right
- (fun (_,dep,ind,sort) (evd, l, inst) ->
+ (fun (_,dep,ind,sort) (evd, l, inst) ->
let evd, indu, inst =
match inst with
| None ->
@@ -399,12 +407,12 @@ let do_mutual_induction_scheme ?(force_mutual=false) lnamedepindsort =
let _ = List.fold_right2 declare listdecl lrecnames [] in
fixpoint_message None lrecnames
-let get_common_underlying_mutual_inductive = function
+let get_common_underlying_mutual_inductive env = function
| [] -> assert false
| (id,(mind,i as ind))::l as all ->
match List.filter (fun (_,(mind',_)) -> not (MutInd.equal mind mind')) l with
| (_,ind')::_ ->
- raise (RecursionSchemeError (NotMutualInScheme (ind,ind')))
+ raise (RecursionSchemeError (env, NotMutualInScheme (ind,ind')))
| [] ->
if not (List.distinct_f Int.compare (List.map snd (List.map snd all)))
then user_err Pp.(str "A type occurs twice");
@@ -413,7 +421,8 @@ let get_common_underlying_mutual_inductive = function
(function (Some id,(_,i)) -> Some (i,id.CAst.v) | (None,_) -> None) all
let do_scheme l =
- let ischeme,escheme = split_scheme l in
+ let env = Global.env() in
+ let ischeme,escheme = split_scheme env l in
(* we want 1 kind of scheme at a time so we check if the user
tried to declare different schemes at once *)
if not (List.is_empty ischeme) && not (List.is_empty escheme)
@@ -422,7 +431,7 @@ tried to declare different schemes at once *)
else (
if not (List.is_empty ischeme) then do_mutual_induction_scheme ischeme
else
- let mind,l = get_common_underlying_mutual_inductive escheme in
+ let mind,l = get_common_underlying_mutual_inductive env escheme in
declare_beq_scheme_with l mind;
declare_eq_decidability_scheme_with l mind
)
@@ -445,6 +454,9 @@ let fold_left' f = function
let mk_coq_and sigma = Evarutil.new_global sigma (Coqlib.build_coq_and ())
let mk_coq_conj sigma = Evarutil.new_global sigma (Coqlib.build_coq_conj ())
+let mk_coq_prod sigma = Evarutil.new_global sigma (Coqlib.build_coq_prod ())
+let mk_coq_pair sigma = Evarutil.new_global sigma (Coqlib.build_coq_pair ())
+
let build_combined_scheme env schemes =
let evdref = ref (Evd.from_env env) in
let defs = List.map (fun cst ->
@@ -462,10 +474,25 @@ let build_combined_scheme env schemes =
in
let (c, t) = List.hd defs in
let ctx, ind, nargs = find_inductive t in
+ (* We check if ALL the predicates are in Prop, if so we use propositional
+ conjunction '/\', otherwise we use the simple product '*'.
+ *)
+ let inprop =
+ let inprop (_,t) =
+ Retyping.get_sort_family_of env !evdref (EConstr.of_constr t)
+ == Sorts.InProp
+ in
+ List.for_all inprop defs
+ in
+ let mk_and, mk_conj =
+ if inprop
+ then (mk_coq_and, mk_coq_conj)
+ else (mk_coq_prod, mk_coq_pair)
+ in
(* Number of clauses, including the predicates quantification *)
let prods = nb_prod !evdref (EConstr.of_constr t) - (nargs + 1) in
- let sigma, coqand = mk_coq_and !evdref in
- let sigma, coqconj = mk_coq_conj sigma in
+ let sigma, coqand = mk_and !evdref in
+ let sigma, coqconj = mk_conj sigma in
let () = evdref := sigma in
let relargs = rel_vect 0 prods in
let concls = List.rev_map
@@ -483,7 +510,8 @@ let build_combined_scheme env schemes =
(List.rev_map (fun (x, y) -> LocalAssum (x, y)) ctx) in
let typ = List.fold_left (fun d c -> Term.mkProd_wo_LetIn c d) concl_typ ctx in
let body = it_mkLambda_or_LetIn concl_bod ctx in
- (!evdref, body, typ)
+ let sigma = Typing.check env !evdref (EConstr.of_constr body) (EConstr.of_constr typ) in
+ (sigma, body, typ)
let do_combined_scheme name schemes =
let open CAst in
diff --git a/vernac/lemmas.ml b/vernac/lemmas.ml
index ce74f2344a..880a11becd 100644
--- a/vernac/lemmas.ml
+++ b/vernac/lemmas.ml
@@ -71,17 +71,13 @@ let adjust_guardness_conditions const = function
List.interval 0 (List.length ((lam_assum c))))
lemma_guard (Array.to_list fixdefs) in
*)
- let add c cb e =
- let exists c e =
- try ignore(Environ.lookup_constant c e); true
- with Not_found -> false in
- if exists c e then e else Environ.add_constant c cb e in
- let env = List.fold_left (fun env { eff } ->
- match eff with
- | SEsubproof (c, cb,_) -> add c cb env
- | SEscheme (l,_) ->
- List.fold_left (fun e (_,c,cb,_) -> add c cb e) env l)
- env (Safe_typing.side_effects_of_private_constants eff) in
+ let fold env eff =
+ try
+ let _ = Environ.lookup_constant eff.seff_constant env in
+ env
+ with Not_found -> Environ.add_constant eff.seff_constant eff.seff_body env
+ in
+ let env = List.fold_left fold env (Safe_typing.side_effects_of_private_constants eff) in
let indexes =
search_guard env
possible_indexes fixdecls in
diff --git a/vernac/metasyntax.ml b/vernac/metasyntax.ml
index d66a121437..2e5e11bb09 100644
--- a/vernac/metasyntax.ml
+++ b/vernac/metasyntax.ml
@@ -1306,8 +1306,18 @@ type notation_obj = {
notobj_notation : notation * notation_location;
}
-let load_notation _ (_, nobj) =
- Option.iter Notation.declare_scope nobj.notobj_scope
+let load_notation_common silently_define_scope_if_undefined _ (_, nobj) =
+ (* When the default shall be to require that a scope already exists *)
+ (* the call to ensure_scope will have to be removed *)
+ if silently_define_scope_if_undefined then
+ (* Don't warn if the scope is not defined: *)
+ (* there was already a warning at "cache" time *)
+ Option.iter Notation.declare_scope nobj.notobj_scope
+ else
+ Option.iter Notation.ensure_scope nobj.notobj_scope
+
+let load_notation =
+ load_notation_common true
let open_notation i (_, nobj) =
let scope = nobj.notobj_scope in
@@ -1331,7 +1341,7 @@ let open_notation i (_, nobj) =
end
let cache_notation o =
- load_notation 1 o;
+ load_notation_common false 1 o;
open_notation 1 o
let subst_notation (subst, nobj) =
@@ -1566,52 +1576,72 @@ let add_infix local env ({CAst.loc;v=inf},modifiers) pr sc =
add_notation local env c (df,modifiers) sc
(**********************************************************************)
-(* Delimiters and classes bound to scopes *)
+(* Scopes, delimiters and classes bound to scopes *)
type scope_command =
- | ScopeDelim of string
+ | ScopeDeclare
+ | ScopeDelimAdd of string
+ | ScopeDelimRemove
| ScopeClasses of scope_class list
- | ScopeRemove
-
-let load_scope_command _ (_,(scope,dlm)) =
- Notation.declare_scope scope
-let open_scope_command i (_,(scope,o)) =
+let load_scope_command_common silently_define_scope_if_undefined _ (_,(local,scope,o)) =
+ let declare_scope_if_needed =
+ if silently_define_scope_if_undefined then Notation.declare_scope
+ else Notation.ensure_scope in
+ match o with
+ | ScopeDeclare -> Notation.declare_scope scope
+ (* When the default shall be to require that a scope already exists *)
+ (* the call to declare_scope_if_needed will have to be removed below *)
+ | ScopeDelimAdd dlm -> declare_scope_if_needed scope
+ | ScopeDelimRemove -> declare_scope_if_needed scope
+ | ScopeClasses cl -> declare_scope_if_needed scope
+
+let load_scope_command =
+ load_scope_command_common true
+
+let open_scope_command i (_,(local,scope,o)) =
if Int.equal i 1 then
match o with
- | ScopeDelim dlm -> Notation.declare_delimiters scope dlm
+ | ScopeDeclare -> ()
+ | ScopeDelimAdd dlm -> Notation.declare_delimiters scope dlm
+ | ScopeDelimRemove -> Notation.remove_delimiters scope
| ScopeClasses cl -> List.iter (Notation.declare_scope_class scope) cl
- | ScopeRemove -> Notation.remove_delimiters scope
let cache_scope_command o =
- load_scope_command 1 o;
+ load_scope_command_common false 1 o;
open_scope_command 1 o
-let subst_scope_command (subst,(scope,o as x)) = match o with
+let subst_scope_command (subst,(local,scope,o as x)) = match o with
| ScopeClasses cl ->
let cl' = List.map_filter (subst_scope_class subst) cl in
let cl' =
if List.for_all2eq (==) cl cl' then cl
else cl' in
- scope, ScopeClasses cl'
+ local, scope, ScopeClasses cl'
| _ -> x
-let inScopeCommand : scope_name * scope_command -> obj =
+let classify_scope_command (local, _, _ as o) =
+ if local then Dispose else Substitute o
+
+let inScopeCommand : locality_flag * scope_name * scope_command -> obj =
declare_object {(default_object "DELIMITERS") with
cache_function = cache_scope_command;
open_function = open_scope_command;
load_function = load_scope_command;
subst_function = subst_scope_command;
- classify_function = (fun obj -> Substitute obj)}
+ classify_function = classify_scope_command}
+
+let declare_scope local scope =
+ Lib.add_anonymous_leaf (inScopeCommand(local,scope,ScopeDeclare))
-let add_delimiters scope key =
- Lib.add_anonymous_leaf (inScopeCommand(scope,ScopeDelim key))
+let add_delimiters local scope key =
+ Lib.add_anonymous_leaf (inScopeCommand(local,scope,ScopeDelimAdd key))
-let remove_delimiters scope =
- Lib.add_anonymous_leaf (inScopeCommand(scope,ScopeRemove))
+let remove_delimiters local scope =
+ Lib.add_anonymous_leaf (inScopeCommand(local,scope,ScopeDelimRemove))
-let add_class_scope scope cl =
- Lib.add_anonymous_leaf (inScopeCommand(scope,ScopeClasses cl))
+let add_class_scope local scope cl =
+ Lib.add_anonymous_leaf (inScopeCommand(local,scope,ScopeClasses cl))
(* Check if abbreviation to a name and avoid early insertion of
maximal implicit arguments *)
diff --git a/vernac/metasyntax.mli b/vernac/metasyntax.mli
index 73bee7121b..38dbdf7e41 100644
--- a/vernac/metasyntax.mli
+++ b/vernac/metasyntax.mli
@@ -27,11 +27,12 @@ val add_notation : locality_flag -> env -> constr_expr ->
val add_notation_extra_printing_rule : string -> string -> string -> unit
-(** Declaring delimiter keys and default scopes *)
+(** Declaring scopes, delimiter keys and default scopes *)
-val add_delimiters : scope_name -> string -> unit
-val remove_delimiters : scope_name -> unit
-val add_class_scope : scope_name -> scope_class list -> unit
+val declare_scope : locality_flag -> scope_name -> unit
+val add_delimiters : locality_flag -> scope_name -> string -> unit
+val remove_delimiters : locality_flag -> scope_name -> unit
+val add_class_scope : locality_flag -> scope_name -> scope_class list -> unit
(** Add only the interpretation of a notation that already has pa/pp rules *)
diff --git a/vernac/obligations.ml b/vernac/obligations.ml
index 14d7642328..3987e53bc7 100644
--- a/vernac/obligations.ml
+++ b/vernac/obligations.ml
@@ -523,11 +523,11 @@ let declare_mutual_definition l =
(List.map (fun x ->
let subs, typ = (subst_body true x) in
let env = Global.env () in
- let sigma = Evd.from_env env in
+ let sigma = Evd.from_ctx x.prg_ctx in
let term = snd (Reductionops.splay_lam_n env sigma len (EConstr.of_constr subs)) in
let typ = snd (Reductionops.splay_prod_n env sigma len (EConstr.of_constr typ)) in
- let term = EConstr.Unsafe.to_constr term in
- let typ = EConstr.Unsafe.to_constr typ in
+ let term = EConstr.to_constr sigma term in
+ let typ = EConstr.to_constr sigma typ in
x.prg_reduce term, x.prg_reduce typ, x.prg_implicits) l)
in
(* let fixdefs = List.map reduce_fix fixdefs in *)
diff --git a/vernac/ppvernac.ml b/vernac/ppvernac.ml
index 93e4e89a12..b4b3aead91 100644
--- a/vernac/ppvernac.ml
+++ b/vernac/ppvernac.ml
@@ -178,11 +178,11 @@ open Pputils
| [] -> mt()
| _ as z -> str":" ++ spc() ++ prlist_with_sep sep str z
- let pr_reference_or_constr pr_c = function
+ let pr_reference_or_constr pr_c = let open Hints in function
| HintsReference r -> pr_qualid r
| HintsConstr c -> pr_c c
- let pr_hint_mode = function
+ let pr_hint_mode = let open Hints in function
| ModeInput -> str"+"
| ModeNoHeadEvar -> str"!"
| ModeOutput -> str"-"
@@ -194,6 +194,7 @@ open Pputils
let pr_hints db h pr_c pr_pat =
let opth = pr_opt_hintbases db in
let pph =
+ let open Hints in
match h with
| HintsResolve l ->
keyword "Resolve " ++ prlist_with_sep sep
@@ -635,6 +636,10 @@ open Pputils
keyword (if opening then "Open " else "Close ") ++
keyword "Scope" ++ spc() ++ str sc
)
+ | VernacDeclareScope sc ->
+ return (
+ keyword "Declare Scope" ++ spc () ++ str sc
+ )
| VernacDelimiters (sc,Some key) ->
return (
keyword "Delimit Scope" ++ spc () ++ str sc ++
@@ -1157,7 +1162,11 @@ open Pputils
| VernacRegister (id, RegisterInline) ->
return (
hov 2
- (keyword "Register Inline" ++ spc() ++ pr_lident id)
+ (keyword "Register Inline" ++ spc() ++ pr_qualid id)
+ )
+ | VernacRegister (id, RegisterRetroknowledge n) ->
+ return (
+ hov 2 (keyword "Register" ++ spc () ++ pr_qualid id ++ spc () ++ keyword "as" ++ pr_qualid n)
)
| VernacComments l ->
return (
diff --git a/vernac/record.ml b/vernac/record.ml
index 6b5c538df2..724b6e62fe 100644
--- a/vernac/record.ml
+++ b/vernac/record.ml
@@ -393,14 +393,14 @@ open Typeclasses
let declare_structure finite ubinders univs paramimpls params template ?(kind=StructureComponent) ?name record_data =
let nparams = List.length params in
- let template, ctx =
+ let poly, ctx =
match univs with
| Monomorphic_ind_entry ctx ->
- template, Monomorphic_const_entry Univ.ContextSet.empty
+ false, Monomorphic_const_entry Univ.ContextSet.empty
| Polymorphic_ind_entry ctx ->
- false, Polymorphic_const_entry ctx
+ true, Polymorphic_const_entry ctx
| Cumulative_ind_entry cumi ->
- false, Polymorphic_const_entry (Univ.CumulativityInfo.univ_context cumi)
+ true, Polymorphic_const_entry (Univ.CumulativityInfo.univ_context cumi)
in
let binder_name =
match name with
@@ -417,6 +417,18 @@ let declare_structure finite ubinders univs paramimpls params template ?(kind=St
let args = Context.Rel.to_extended_list mkRel nfields params in
let ind = applist (mkRel (ntypes - i + nparams + nfields), args) in
let type_constructor = it_mkProd_or_LetIn ind fields in
+ let template =
+ match template with
+ | Some template, _ ->
+ (* templateness explicitly requested *)
+ if poly && template then user_err Pp.(strbrk "template and polymorphism not compatible");
+ template
+ | None, template ->
+ (* auto detect template *)
+ ComInductive.should_auto_template () && template && not poly &&
+ let _, s = Reduction.dest_arity (Global.env()) arity in
+ not (Sorts.is_small s)
+ in
{ mind_entry_typename = id;
mind_entry_arity = arity;
mind_entry_template = template;
@@ -441,7 +453,6 @@ let declare_structure finite ubinders univs paramimpls params template ?(kind=St
let cstr = (rsp, 1) in
let kinds,sp_projs = declare_projections rsp ctx ~kind binder_name.(i) coers ubinders fieldimpls fields in
let build = ConstructRef cstr in
- let poly = match ctx with | Polymorphic_const_entry _ -> true | Monomorphic_const_entry _ -> false in
let () = if is_coe then Class.try_add_new_coercion build ~local:false poly in
let () = Recordops.declare_structure(rsp,cstr,List.rev kinds,List.rev sp_projs) in
rsp
@@ -476,10 +487,11 @@ let declare_class finite def cum ubinders univs id idbuild paramimpls params ari
let cst = Declare.declare_constant id
(DefinitionEntry class_entry, IsDefinition Definition)
in
- let cstu = (cst, match univs with
- | Polymorphic_const_entry univs -> Univ.UContext.instance univs
- | Monomorphic_const_entry _ -> Univ.Instance.empty)
+ let inst, univs = match univs with
+ | Polymorphic_const_entry uctx -> Univ.UContext.instance uctx, univs
+ | Monomorphic_const_entry _ -> Univ.Instance.empty, Monomorphic_const_entry Univ.ContextSet.empty
in
+ let cstu = (cst, inst) in
let inst_type = appvectc (mkConstU cstu)
(Termops.rel_vect 0 (List.length params)) in
let proj_type =
@@ -616,7 +628,7 @@ let check_unique_names records =
| Vernacexpr.DefExpr ({CAst.v=Name id},_,_) -> id::acc
| _ -> acc in
let allnames =
- List.fold_left (fun acc (_, id, _, _, cfs, _, _) ->
+ List.fold_left (fun acc (_, id, _, cfs, _, _) ->
id.CAst.v :: (List.fold_left extract_name acc cfs)) [] records
in
match List.duplicates Id.equal allnames with
@@ -625,19 +637,19 @@ let check_unique_names records =
let check_priorities kind records =
let isnot_class = match kind with Class false -> false | _ -> true in
- let has_priority (_, _, _, _, cfs, _, _) =
+ let has_priority (_, _, _, cfs, _, _) =
List.exists (fun ((_, pri), _) -> not (Option.is_empty pri)) cfs
in
if isnot_class && List.exists has_priority records then
user_err Pp.(str "Priorities only allowed for type class substructures")
let extract_record_data records =
- let map (is_coe, id, _, _, cfs, idbuild, s) =
+ let map (is_coe, id, _, cfs, idbuild, s) =
let fs = List.map (fun (((_, f), _), _) -> f) cfs in
id.CAst.v, s, List.map snd cfs, fs
in
let data = List.map map records in
- let pss = List.map (fun (_, _, _, ps, _, _, _) -> ps) records in
+ let pss = List.map (fun (_, _, ps, _, _, _) -> ps) records in
let ps = match pss with
| [] -> CErrors.anomaly (str "Empty record block")
| ps :: rem ->
@@ -649,29 +661,28 @@ let extract_record_data records =
in
ps
in
- (** FIXME: Same issue as #7754 *)
- let _, _, pl, _, _, _, _ = List.hd records in
- pl, ps, data
+ ps, data
(* [fs] corresponds to fields and [ps] to parameters; [coers] is a
list telling if the corresponding fields must me declared as coercions
or subinstances. *)
-let definition_structure kind cum poly finite records =
+let definition_structure udecl kind ~template cum poly finite records =
let () = check_unique_names records in
let () = check_priorities kind records in
- let pl, ps, data = extract_record_data records in
- let pl, univs, template, params, implpars, data =
+ let ps, data = extract_record_data records in
+ let ubinders, univs, auto_template, params, implpars, data =
States.with_state_protection (fun () ->
- typecheck_params_and_fields finite (kind = Class true) poly pl ps data) () in
+ typecheck_params_and_fields finite (kind = Class true) poly udecl ps data) () in
+ let template = template, auto_template in
match kind with
| Class def ->
- let (_, id, _, _, cfs, idbuild, _), (arity, implfs, fields) = match records, data with
+ let (_, id, _, cfs, idbuild, _), (arity, implfs, fields) = match records, data with
| [r], [d] -> r, d
| _, _ -> CErrors.user_err (str "Mutual definitional classes are not handled")
in
let priorities = List.map (fun ((_, id), _) -> {hint_priority = id; hint_pattern = None}) cfs in
let coers = List.map (fun (((coe, _), _), _) -> coe) cfs in
- declare_class finite def cum pl univs id.CAst.v idbuild
+ declare_class finite def cum ubinders univs id.CAst.v idbuild
implpars params arity template implfs fields coers priorities
| _ ->
let map impls = implpars @ Impargs.lift_implicits (succ (List.length params)) impls in
@@ -686,11 +697,11 @@ let definition_structure kind cum poly finite records =
| Monomorphic_const_entry univs ->
Monomorphic_ind_entry univs
in
- let map (arity, implfs, fields) (is_coe, id, _, _, cfs, idbuild, _) =
+ let map (arity, implfs, fields) (is_coe, id, _, cfs, idbuild, _) =
let coers = List.map (fun (((coe, _), _), _) -> coe) cfs in
let coe = List.map (fun coe -> not (Option.is_empty coe)) coers in
id.CAst.v, idbuild, arity, implfs, fields, is_coe, coe
in
let data = List.map2 map data records in
- let inds = declare_structure finite pl univs implpars params template data in
+ let inds = declare_structure finite ubinders univs implpars params template data in
List.map (fun ind -> IndRef ind) inds
diff --git a/vernac/record.mli b/vernac/record.mli
index 567f2b3138..953d5ec3b6 100644
--- a/vernac/record.mli
+++ b/vernac/record.mli
@@ -26,11 +26,11 @@ val declare_projections :
(Name.t * bool) list * Constant.t option list
val definition_structure :
- inductive_kind -> Decl_kinds.cumulative_inductive_flag -> Decl_kinds.polymorphic ->
+ universe_decl_expr option -> inductive_kind -> template:bool option ->
+ Decl_kinds.cumulative_inductive_flag -> Decl_kinds.polymorphic ->
Declarations.recursivity_kind ->
(coercion_flag *
Names.lident *
- universe_decl_expr option *
local_binder_expr list *
(local_decl_expr with_instance with_priority with_notation) list *
Id.t * constr_expr option) list ->
diff --git a/vernac/vernacentries.ml b/vernac/vernacentries.ml
index 9824172315..015d5fabef 100644
--- a/vernac/vernacentries.ml
+++ b/vernac/vernacentries.ml
@@ -403,17 +403,24 @@ let dump_global r =
(**********)
(* Syntax *)
-let vernac_syntax_extension atts infix l =
+let vernac_syntax_extension ~atts infix l =
let local = enforce_module_locality atts.locality in
if infix then Metasyntax.check_infix_modifiers (snd l);
Metasyntax.add_syntax_extension local l
-let vernac_delimiters sc = function
- | Some lr -> Metasyntax.add_delimiters sc lr
- | None -> Metasyntax.remove_delimiters sc
+let vernac_declare_scope ~atts sc =
+ let local = enforce_module_locality atts.locality in
+ Metasyntax.declare_scope local sc
+
+let vernac_delimiters ~atts sc action =
+ let local = enforce_module_locality atts.locality in
+ match action with
+ | Some lr -> Metasyntax.add_delimiters local sc lr
+ | None -> Metasyntax.remove_delimiters local sc
-let vernac_bind_scope sc cll =
- Metasyntax.add_class_scope sc (List.map scope_class_of_qualid cll)
+let vernac_bind_scope ~atts sc cll =
+ let local = enforce_module_locality atts.locality in
+ Metasyntax.add_class_scope local sc (List.map scope_class_of_qualid cll)
let vernac_open_close_scope ~atts (b,s) =
let local = enforce_section_locality atts.locality in
@@ -548,9 +555,9 @@ let should_treat_as_uniform () =
then ComInductive.UniformParameters
else ComInductive.NonUniformParameters
-let vernac_record cum k poly finite records =
+let vernac_record ~template udecl cum k poly finite records =
let is_cumulative = should_treat_as_cumulative cum poly in
- let map ((coe, (id, pl)), binders, sort, nameopt, cfs) =
+ let map ((coe, id), binders, sort, nameopt, cfs) =
let const = match nameopt with
| None -> add_prefix "Build_" id.v
| Some lid ->
@@ -567,10 +574,22 @@ let vernac_record cum k poly finite records =
in
List.iter iter cfs
in
- coe, id, pl, binders, cfs, const, sort
+ coe, id, binders, cfs, const, sort
in
let records = List.map map records in
- ignore(Record.definition_structure k is_cumulative poly finite records)
+ ignore(Record.definition_structure ~template udecl k is_cumulative poly finite records)
+
+let extract_inductive_udecl (indl:(inductive_expr * decl_notation list) list) =
+ match indl with
+ | [] -> assert false
+ | (((coe,(id,udecl)),b,c,k,d),e) :: rest ->
+ let rest = List.map (fun (((coe,(id,udecl)),b,c,k,d),e) ->
+ if Option.has_some udecl
+ then user_err ~hdr:"inductive udecl" Pp.(strbrk "Universe binders must be on the first inductive of the block.")
+ else (((coe,id),b,c,k,d),e))
+ rest
+ in
+ udecl, (((coe,id),b,c,k,d),e) :: rest
(** When [poly] is true the type is declared polymorphic. When [lo] is true,
then the type is declared private (as per the [Private] keyword). [finite]
@@ -578,8 +597,9 @@ let vernac_record cum k poly finite records =
neither. *)
let vernac_inductive ~atts cum lo finite indl =
let open Pp in
+ let udecl, indl = extract_inductive_udecl indl in
if Dumpglob.dump () then
- List.iter (fun (((coe,(lid,_)), _, _, _, cstrs), _) ->
+ List.iter (fun (((coe,lid), _, _, _, cstrs), _) ->
match cstrs with
| Constructors cstrs ->
Dumpglob.dump_definition lid false "ind";
@@ -587,6 +607,7 @@ let vernac_inductive ~atts cum lo finite indl =
Dumpglob.dump_definition lid false "constr") cstrs
| _ -> () (* dumping is done by vernac_record (called below) *) )
indl;
+
let is_record = function
| ((_ , _ , _ , _, RecordDecl _), _) -> true
| _ -> false
@@ -599,13 +620,14 @@ let vernac_inductive ~atts cum lo finite indl =
| [ ( id , bl , c , Class _, Constructors [l]), [] ] -> Some (id, bl, c, l)
| _ -> None
in
+ let template = atts.template in
if Option.has_some is_defclass then
(** Definitional class case *)
let (id, bl, c, l) = Option.get is_defclass in
let (coe, (lid, ce)) = l in
let coe' = if coe then Some true else None in
let f = (((coe', AssumExpr ((make ?loc:lid.loc @@ Name lid.v), ce)), None), []) in
- vernac_record cum (Class true) atts.polymorphic finite [id, bl, c, None, [f]]
+ vernac_record ~template udecl cum (Class true) atts.polymorphic finite [id, bl, c, None, [f]]
else if List.for_all is_record indl then
(** Mutual record case *)
let check_kind ((_, _, _, kind, _), _) = match kind with
@@ -628,7 +650,7 @@ let vernac_inductive ~atts cum lo finite indl =
let ((_, _, _, kind, _), _) = List.hd indl in
let kind = match kind with Class _ -> Class false | _ -> kind in
let recordl = List.map unpack indl in
- vernac_record cum kind atts.polymorphic finite recordl
+ vernac_record ~template udecl cum kind atts.polymorphic finite recordl
else if List.for_all is_constructor indl then
(** Mutual inductive case *)
let check_kind ((_, _, _, kind, _), _) = match kind with
@@ -654,7 +676,7 @@ let vernac_inductive ~atts cum lo finite indl =
let indl = List.map unpack indl in
let is_cumulative = should_treat_as_cumulative cum atts.polymorphic in
let uniform = should_treat_as_uniform () in
- ComInductive.do_mutual_inductive indl is_cumulative atts.polymorphic lo ~uniform finite
+ ComInductive.do_mutual_inductive ~template udecl indl is_cumulative atts.polymorphic lo ~uniform finite
else
user_err (str "Mixed record-inductive definitions are not allowed")
(*
@@ -1505,8 +1527,8 @@ let _ =
{ optdepr = false;
optname = "kernel term sharing";
optkey = ["Kernel"; "Term"; "Sharing"];
- optread = (fun () -> !CClosure.share);
- optwrite = (fun b -> CClosure.share := b) }
+ optread = (fun () -> (Global.typing_flags ()).Declarations.share_reduction);
+ optwrite = (fun b -> Global.set_reduction_sharing b) }
let _ =
declare_bool_option
@@ -1692,36 +1714,37 @@ let query_command_selector ?loc = function
let vernac_check_may_eval ~atts redexp glopt rc =
let glopt = query_command_selector ?loc:atts.loc glopt in
let (sigma, env) = get_current_context_of_args glopt in
- let sigma', c = interp_open_constr env sigma rc in
- let sigma' = Evarconv.solve_unif_constraints_with_heuristics env sigma' in
- Evarconv.check_problems_are_solved env sigma';
- let sigma' = Evd.minimize_universes sigma' in
- let uctx = Evd.universe_context_set sigma' in
- let env = Environ.push_context_set uctx (Evarutil.nf_env_evar sigma' env) in
+ let sigma, c = interp_open_constr env sigma rc in
+ let sigma = Evarconv.solve_unif_constraints_with_heuristics env sigma in
+ Evarconv.check_problems_are_solved env sigma;
+ let sigma = Evd.minimize_universes sigma in
+ let uctx = Evd.universe_context_set sigma in
+ let env = Environ.push_context_set uctx (Evarutil.nf_env_evar sigma env) in
let j =
- if Evarutil.has_undefined_evars sigma' c then
- Evarutil.j_nf_evar sigma' (Retyping.get_judgment_of env sigma' c)
+ if Evarutil.has_undefined_evars sigma c then
+ Evarutil.j_nf_evar sigma (Retyping.get_judgment_of env sigma c)
else
- let c = EConstr.to_constr sigma' c in
+ let c = EConstr.to_constr sigma c in
(* OK to call kernel which does not support evars *)
Termops.on_judgment EConstr.of_constr (Arguments_renaming.rename_typing env c)
in
- match redexp with
+ let pp = match redexp with
| None ->
- let evars_of_term c = Evarutil.undefined_evars_of_term sigma' c in
+ let evars_of_term c = Evarutil.undefined_evars_of_term sigma c in
let l = Evar.Set.union (evars_of_term j.Environ.uj_val) (evars_of_term j.Environ.uj_type) in
- let j = { j with Environ.uj_type = Reductionops.nf_betaiota env sigma' j.Environ.uj_type } in
- print_judgment env sigma' j ++
- pr_ne_evar_set (fnl () ++ str "where" ++ fnl ()) (mt ()) sigma' l ++
- Printer.pr_universe_ctx_set sigma uctx
+ let j = { j with Environ.uj_type = Reductionops.nf_betaiota env sigma j.Environ.uj_type } in
+ print_judgment env sigma j ++
+ pr_ne_evar_set (fnl () ++ str "where" ++ fnl ()) (mt ()) sigma l
| Some r ->
- let (sigma',r_interp) = Hook.get f_interp_redexp env sigma' r in
+ let (sigma,r_interp) = Hook.get f_interp_redexp env sigma r in
let redfun env evm c =
let (redfun, _) = reduction_of_red_expr env r_interp in
let (_, c) = redfun env evm c in
c
in
- print_eval redfun env sigma' rc j
+ print_eval redfun env sigma rc j
+ in
+ pp ++ Printer.pr_universe_ctx_set sigma uctx
let vernac_declare_reduction ~atts s r =
let local = make_locality atts.locality in
@@ -1801,13 +1824,13 @@ let vernac_print ~atts env sigma =
| PrintName (qid,udecl) ->
dump_global qid;
print_name env sigma qid udecl
- | PrintGraph -> Prettyp.print_graph env sigma
+ | PrintGraph -> Prettyp.print_graph ()
| PrintClasses -> Prettyp.print_classes()
| PrintTypeClasses -> Prettyp.print_typeclasses()
| PrintInstances c -> Prettyp.print_instances (smart_global c)
- | PrintCoercions -> Prettyp.print_coercions env sigma
+ | PrintCoercions -> Prettyp.print_coercions ()
| PrintCoercionPaths (cls,clt) ->
- Prettyp.print_path_between env sigma (cl_of_qualid cls) (cl_of_qualid clt)
+ Prettyp.print_path_between (cl_of_qualid cls) (cl_of_qualid clt)
| PrintCanonicalConversions -> Prettyp.print_canonical_projections env sigma
| PrintUniverses (b, dst) ->
let univ = Global.universes () in
@@ -1941,14 +1964,23 @@ let vernac_locate = function
| LocateOther (s, qid) -> print_located_other s qid
| LocateFile f -> locate_file f
-let vernac_register id r =
+let vernac_register qid r =
+ let gr = Smartlocate.global_with_alias qid in
if Proof_global.there_are_pending_proofs () then
user_err Pp.(str "Cannot register a primitive while in proof editing mode.");
- let kn = Constrintern.global_reference id.v in
- if not (isConstRef kn) then
- user_err Pp.(str "Register inline: a constant is expected");
match r with
- | RegisterInline -> Global.register_inline (destConstRef kn)
+ | RegisterInline ->
+ if not (isConstRef gr) then
+ user_err Pp.(str "Register inline: a constant is expected");
+ Global.register_inline (destConstRef gr)
+ | RegisterRetroknowledge n ->
+ let path, id = Libnames.repr_qualid n in
+ if DirPath.equal path Retroknowledge.int31_path
+ then
+ let f = Retroknowledge.(KInt31 (int31_field_of_string (Id.to_string id))) in
+ Global.register f gr
+ else
+ user_err Pp.(str "Register in unknown namespace: " ++ str (DirPath.to_string path))
(********************)
(* Proof management *)
@@ -1987,8 +2019,9 @@ let vernac_subproof gln =
match gln with
| None -> Proof.focus subproof_cond () 1 p
| Some (Goal_select.SelectNth n) -> Proof.focus subproof_cond () n p
+ | Some (Goal_select.SelectId id) -> Proof.focus_id subproof_cond () id p
| _ -> user_err ~hdr:"bracket_selector"
- (str "Brackets only support the single numbered goal selector."))
+ (str "Brackets do not support multi-goal selectors."))
let vernac_end_subproof () =
Proof_global.simple_with_current_proof (fun _ p ->
@@ -2091,9 +2124,10 @@ let interp ?proof ~atts ~st c =
(* Syntax *)
| VernacSyntaxExtension (infix, sl) ->
- vernac_syntax_extension atts infix sl
- | VernacDelimiters (sc,lr) -> vernac_delimiters sc lr
- | VernacBindScope (sc,rl) -> vernac_bind_scope sc rl
+ vernac_syntax_extension ~atts infix sl
+ | VernacDeclareScope sc -> vernac_declare_scope ~atts sc
+ | VernacDelimiters (sc,lr) -> vernac_delimiters ~atts sc lr
+ | VernacBindScope (sc,rl) -> vernac_bind_scope ~atts sc rl
| VernacOpenCloseScope (b, s) -> vernac_open_close_scope ~atts (b,s)
| VernacInfix (mv,qid,sc) -> vernac_infix ~atts mv qid sc
| VernacNotation (c,infpl,sc) ->
@@ -2230,6 +2264,7 @@ let check_vernac_supports_locality c l =
| Some _, (
VernacOpenCloseScope _
| VernacSyntaxExtension _ | VernacInfix _ | VernacNotation _
+ | VernacDeclareScope _ | VernacDelimiters _ | VernacBindScope _
| VernacDeclareCustomEntry _
| VernacDefinition _ | VernacFixpoint _ | VernacCoFixpoint _
| VernacAssumption _ | VernacStartTheoremProof _
@@ -2347,6 +2382,14 @@ let attributes_of_flags f atts =
(Some false, atts)
| ("polymorphic" | "monomorphic") ->
user_err Pp.(str "Polymorphism specified twice")
+ | "template" when atts.template = None ->
+ assert_empty k v;
+ polymorphism, { atts with template = Some true }
+ | "notemplate" when atts.template = None ->
+ assert_empty k v;
+ polymorphism, { atts with template = Some false }
+ | "template" | "notemplate" ->
+ user_err Pp.(str "Templateness specified twice")
| "local" when Option.is_empty atts.locality ->
assert_empty k v;
(polymorphism, { atts with locality = Some true })
diff --git a/vernac/vernacexpr.ml b/vernac/vernacexpr.ml
index 8fb74e6d78..a5601d8c85 100644
--- a/vernac/vernacexpr.ml
+++ b/vernac/vernacexpr.ml
@@ -16,11 +16,11 @@ open Libnames
type class_rawexpr = FunClass | SortClass | RefClass of qualid or_by_notation
type goal_selector = Goal_select.t =
- | SelectAlreadyFocused
- | SelectNth of int
- | SelectList of (int * int) list
- | SelectId of Id.t
- | SelectAll
+ | SelectAlreadyFocused [@ocaml.deprecated "Use Goal_select.SelectAlreadyFocused"]
+ | SelectNth of int [@ocaml.deprecated "Use Goal_select.SelectNth"]
+ | SelectList of (int * int) list [@ocaml.deprecated "Use Goal_select.SelectList"]
+ | SelectId of Id.t [@ocaml.deprecated "Use Goal_select.SelectId"]
+ | SelectAll [@ocaml.deprecated "Use Goal_select.SelectAll"]
[@@ocaml.deprecated "Use Goal_select.t"]
type goal_identifier = string
@@ -103,38 +103,41 @@ type comment =
| CommentInt of int
type reference_or_constr = Hints.reference_or_constr =
- | HintsReference of qualid
- | HintsConstr of constr_expr
+ | HintsReference of qualid [@ocaml.deprecated "Use Hints.HintsReference"]
+ | HintsConstr of constr_expr [@ocaml.deprecated "Use Hints.HintsConstr"]
[@@ocaml.deprecated "Please use [Hints.reference_or_constr]"]
type hint_mode = Hints.hint_mode =
- | ModeInput (* No evars *)
- | ModeNoHeadEvar (* No evar at the head *)
- | ModeOutput (* Anything *)
+ | ModeInput [@ocaml.deprecated "Use Hints.ModeInput"]
+ | ModeNoHeadEvar [@ocaml.deprecated "Use Hints.ModeNoHeadEvar"]
+ | ModeOutput [@ocaml.deprecated "Use Hints.ModeOutput"]
[@@ocaml.deprecated "Please use [Hints.hint_mode]"]
type 'a hint_info_gen = 'a Typeclasses.hint_info_gen =
- { hint_priority : int option;
- hint_pattern : 'a option }
+ { hint_priority : int option; [@ocaml.deprecated "Use Typeclasses.hint_priority"]
+ hint_pattern : 'a option [@ocaml.deprecated "Use Typeclasses.hint_pattern"] }
[@@ocaml.deprecated "Please use [Typeclasses.hint_info_gen]"]
type hint_info_expr = Hints.hint_info_expr
[@@ocaml.deprecated "Please use [Hints.hint_info_expr]"]
-type 'a hints_transparency_target = 'a Hints.hints_transparency_target =
- | HintsVariables
- | HintsConstants
- | HintsReferences of 'a list
-
type hints_expr = Hints.hints_expr =
| HintsResolve of (Hints.hint_info_expr * bool * Hints.reference_or_constr) list
+ [@ocaml.deprecated "Use the constructor in module [Hints]"]
| HintsResolveIFF of bool * qualid list * int option
+ [@ocaml.deprecated "Use the constructor in module [Hints]"]
| HintsImmediate of Hints.reference_or_constr list
+ [@ocaml.deprecated "Use the constructor in module [Hints]"]
| HintsUnfold of qualid list
- | HintsTransparency of qualid hints_transparency_target * bool
+ [@ocaml.deprecated "Use the constructor in module [Hints]"]
+ | HintsTransparency of qualid Hints.hints_transparency_target * bool
+ [@ocaml.deprecated "Use the constructor in module [Hints]"]
| HintsMode of qualid * Hints.hint_mode list
+ [@ocaml.deprecated "Use the constructor in module [Hints]"]
| HintsConstructors of qualid list
+ [@ocaml.deprecated "Use the constructor in module [Hints]"]
| HintsExtern of int * constr_expr option * Genarg.raw_generic_argument
+ [@ocaml.deprecated "Use the constructor in module [Hints]"]
[@@ocaml.deprecated "Please use [Hints.hints_expr]"]
type search_restriction =
@@ -143,7 +146,9 @@ type search_restriction =
type rec_flag = bool (* true = Rec; false = NoRec *)
type verbose_flag = bool (* true = Verbose; false = Silent *)
-type opacity_flag = Proof_global.opacity_flag = Opaque | Transparent
+type opacity_flag = Proof_global.opacity_flag =
+ Opaque [@ocaml.deprecated "Use Proof_global.Opaque"]
+ | Transparent [@ocaml.deprecated "Use Proof_global.Transparent"]
[@ocaml.deprecated "Please use [Proof_global.opacity_flag]"]
type coercion_flag = bool (* true = AddCoercion false = NoCoercion *)
type instance_flag = bool option
@@ -202,7 +207,7 @@ type inductive_expr =
constructor_list_or_record_decl_expr
type one_inductive_expr =
- ident_decl * local_binder_expr list * constr_expr option * constructor_expr list
+ lident * local_binder_expr list * constr_expr option * constructor_expr list
type typeclass_constraint = name_decl * Decl_kinds.binding_kind * constr_expr
and typeclass_context = typeclass_constraint list
@@ -278,6 +283,7 @@ type extend_name =
It will be extended with primitive inductive types and operators *)
type register_kind =
| RegisterInline
+ | RegisterRetroknowledge of qualid
type bullet = Proof_bullet.t
[@@ocaml.deprecated "Alias type, please use [Proof_bullet.t]"]
@@ -288,7 +294,9 @@ type bullet = Proof_bullet.t
type 'a module_signature = 'a Declaremods.module_signature =
| Enforce of 'a (** ... : T *)
+ [@ocaml.deprecated "Use the constructor in module [Declaremods]"]
| Check of 'a list (** ... <: T1 <: T2, possibly empty *)
+ [@ocaml.deprecated "Use the constructor in module [Declaremods]"]
[@@ocaml.deprecated "please use [Declaremods.module_signature]."]
(** Which module inline annotations should we honor,
@@ -297,8 +305,11 @@ type 'a module_signature = 'a Declaremods.module_signature =
type inline = Declaremods.inline =
| NoInline
+ [@ocaml.deprecated "Use the constructor in module [Declaremods]"]
| DefaultInline
+ [@ocaml.deprecated "Use the constructor in module [Declaremods]"]
| InlineAt of int
+ [@ocaml.deprecated "Use the constructor in module [Declaremods]"]
[@@ocaml.deprecated "please use [Declaremods.inline]."]
type module_ast_inl = module_ast * Declaremods.inline
@@ -325,6 +336,7 @@ type nonrec vernac_expr =
(* Syntax *)
| VernacSyntaxExtension of bool * (lstring * syntax_modifier list)
| VernacOpenCloseScope of bool * scope_name
+ | VernacDeclareScope of scope_name
| VernacDelimiters of scope_name * string option
| VernacBindScope of scope_name * class_rawexpr list
| VernacInfix of (lstring * syntax_modifier list) *
@@ -437,7 +449,7 @@ type nonrec vernac_expr =
| VernacPrint of printable
| VernacSearch of searchable * Goal_select.t option * search_restriction
| VernacLocate of locatable
- | VernacRegister of lident * register_kind
+ | VernacRegister of qualid * register_kind
| VernacComments of comment list
(* Proof management *)
diff --git a/vernac/vernacinterp.ml b/vernac/vernacinterp.ml
index 1bb1414f3d..2746cbd144 100644
--- a/vernac/vernacinterp.ml
+++ b/vernac/vernacinterp.ml
@@ -21,12 +21,13 @@ type atts = {
loc : Loc.t option;
locality : bool option;
polymorphic : bool;
+ template : bool option;
program : bool;
deprecated : deprecation option;
}
-let mk_atts ?(loc=None) ?(locality=None) ?(polymorphic=false) ?(program=false) ?(deprecated=None) () : atts =
- { loc ; locality ; polymorphic ; program ; deprecated }
+let mk_atts ?(loc=None) ?(locality=None) ?(polymorphic=false) ?(template=None) ?(program=false) ?(deprecated=None) () : atts =
+ { loc ; locality ; polymorphic ; program ; deprecated; template }
type 'a vernac_command = 'a -> atts:atts -> st:Vernacstate.t -> Vernacstate.t
diff --git a/vernac/vernacinterp.mli b/vernac/vernacinterp.mli
index 46468b3098..62a178b555 100644
--- a/vernac/vernacinterp.mli
+++ b/vernac/vernacinterp.mli
@@ -18,12 +18,14 @@ type atts = {
loc : Loc.t option;
locality : bool option;
polymorphic : bool;
+ template : bool option;
program : bool;
deprecated : deprecation option;
}
val mk_atts : ?loc: Loc.t option -> ?locality: bool option ->
- ?polymorphic: bool -> ?program: bool -> ?deprecated: deprecation option -> unit -> atts
+ ?polymorphic: bool -> ?template:bool option ->
+ ?program: bool -> ?deprecated: deprecation option -> unit -> atts
type 'a vernac_command = 'a -> atts:atts -> st:Vernacstate.t -> Vernacstate.t