aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.circleci/config.yml40
-rw-r--r--.github/CODEOWNERS13
-rw-r--r--.gitignore2
-rw-r--r--.gitlab-ci.yml54
-rw-r--r--.travis.yml65
-rw-r--r--CHANGES8
-rw-r--r--CONTRIBUTING.md8
-rw-r--r--INSTALL.doc30
-rw-r--r--Makefile2
-rw-r--r--Makefile.build1
-rw-r--r--Makefile.checker24
-rw-r--r--Makefile.common38
-rw-r--r--Makefile.doc109
-rw-r--r--Makefile.vofiles40
-rw-r--r--README.md1
-rw-r--r--appveyor.yml12
-rw-r--r--configure.ml11
-rw-r--r--default.nix4
-rw-r--r--dev/build/windows/makecoq_mingw.sh4
-rw-r--r--dev/ci/README.md102
-rw-r--r--dev/ci/appveyor.sh2
-rwxr-xr-xdev/ci/ci-basic-overlay.sh2
-rw-r--r--dev/ci/ci-common.sh12
-rwxr-xr-xdev/ci/ci-fiat-crypto.sh4
-rwxr-xr-xdev/ci/ci-geocoq.sh4
-rwxr-xr-xdev/ci/ci-math-comp.sh11
-rwxr-xr-xdev/ci/ci-unimath.sh5
-rwxr-xr-xdev/ci/ci-vst.sh5
-rw-r--r--dev/ci/gitlab.bat50
-rw-r--r--dev/ci/user-overlays/07213-ppedrot-fast-constr-match-no-context.sh6
-rw-r--r--dev/doc/MERGING.md5
-rw-r--r--dev/doc/changes.md5
-rwxr-xr-xdev/tools/check-owners-pr.sh32
-rwxr-xr-xdev/tools/check-owners.sh138
-rw-r--r--dev/tools/coqdev.el45
-rwxr-xr-xdev/tools/pre-commit6
-rw-r--r--doc/RecTutorial/RecTutorial.tex3690
-rw-r--r--doc/RecTutorial/RecTutorial.v1231
-rw-r--r--doc/RecTutorial/coqartmacros.tex180
-rw-r--r--doc/RecTutorial/manbiblio.bib870
-rw-r--r--doc/RecTutorial/morebib.bib55
-rw-r--r--doc/RecTutorial/recmacros.tex75
-rw-r--r--doc/sphinx/MIGRATING238
-rw-r--r--doc/sphinx/README.rst325
-rw-r--r--doc/sphinx/README.template.rst117
-rw-r--r--doc/sphinx/addendum/generalized-rewriting.rst3
-rw-r--r--doc/sphinx/addendum/implicit-coercions.rst31
-rw-r--r--doc/sphinx/addendum/micromega.rst5
-rw-r--r--doc/sphinx/addendum/miscellaneous-extensions.rst2
-rw-r--r--doc/sphinx/addendum/omega.rst5
-rw-r--r--doc/sphinx/addendum/universe-polymorphism.rst2
-rw-r--r--doc/sphinx/biblio.bib9
-rwxr-xr-xdoc/sphinx/conf.py12
-rw-r--r--doc/sphinx/introduction.rst11
-rw-r--r--doc/sphinx/language/gallina-extensions.rst65
-rw-r--r--doc/sphinx/language/gallina-specification-language.rst98
-rw-r--r--doc/sphinx/practical-tools/coq-commands.rst15
-rw-r--r--doc/sphinx/proof-engine/ltac.rst3
-rw-r--r--doc/sphinx/proof-engine/proof-handling.rst480
-rw-r--r--doc/sphinx/proof-engine/tactics.rst118
-rw-r--r--doc/sphinx/proof-engine/vernacular-commands.rst31
-rw-r--r--doc/sphinx/user-extensions/proof-schemes.rst17
-rw-r--r--doc/sphinx/user-extensions/syntax-extensions.rst5
-rw-r--r--doc/tools/coqrst/coqdoc/main.py3
-rw-r--r--doc/tools/coqrst/coqdomain.py344
-rwxr-xr-xdoc/tools/coqrst/regen_readme.py58
-rw-r--r--doc/tools/coqrst/repl/coqtop.py4
-rw-r--r--doc/tutorial/Tutorial.tex1575
-rw-r--r--engine/evd.ml4
-rw-r--r--engine/uState.ml2
-rw-r--r--engine/universes.ml34
-rw-r--r--engine/universes.mli9
-rw-r--r--ide/ide_slave.ml2
-rw-r--r--interp/notation.ml47
-rw-r--r--interp/notation.mli4
-rw-r--r--interp/notation_ops.ml8
-rw-r--r--kernel/byterun/coq_fix_code.c51
-rw-r--r--kernel/byterun/coq_fix_code.h2
-rw-r--r--kernel/byterun/coq_interp.c34
-rw-r--r--kernel/byterun/coq_memory.c20
-rw-r--r--kernel/byterun/coq_values.c31
-rw-r--r--kernel/cemitcodes.ml4
-rw-r--r--kernel/vmvalues.ml32
-rw-r--r--library/lib.ml23
-rw-r--r--library/libnames.ml3
-rw-r--r--library/libnames.mli2
-rw-r--r--library/nametab.ml1
-rw-r--r--man/coqtop.12
-rw-r--r--plugins/ltac/tactic_matching.ml2
-rw-r--r--pretyping/constr_matching.ml4
-rw-r--r--pretyping/constr_matching.mli2
-rw-r--r--printing/prettyp.ml1
-rw-r--r--test-suite/Makefile75
-rw-r--r--test-suite/README.md3
-rw-r--r--test-suite/bugs/closed/4722.v1
l---------test-suite/bugs/closed/4722/tata1
-rw-r--r--test-suite/bugs/closed/7462.v13
-rw-r--r--test-suite/misc/.gitignore2
-rwxr-xr-xtest-suite/misc/4722.sh15
-rwxr-xr-xtest-suite/misc/coqc_dash_o.sh2
-rw-r--r--test-suite/output/Notations3.out10
-rw-r--r--test-suite/output/Notations3.v5
-rw-r--r--test-suite/output/ssr_explain_match.out55
-rw-r--r--test-suite/output/ssr_explain_match.v23
-rw-r--r--test-suite/prerequisite/ssr_mini_mathcomp.v1472
-rw-r--r--test-suite/prerequisite/ssr_ssrsyntax1.v36
-rwxr-xr-xtest-suite/save-logs.sh2
-rw-r--r--test-suite/ssr/absevarprop.v96
-rw-r--r--test-suite/ssr/abstract_var2.v25
-rw-r--r--test-suite/ssr/binders.v55
-rw-r--r--test-suite/ssr/binders_of.v23
-rw-r--r--test-suite/ssr/caseview.v17
-rw-r--r--test-suite/ssr/congr.v34
-rw-r--r--test-suite/ssr/deferclear.v37
-rw-r--r--test-suite/ssr/dependent_type_err.v20
-rw-r--r--test-suite/ssr/derive_inversion.v29
-rw-r--r--test-suite/ssr/elim.v279
-rw-r--r--test-suite/ssr/elim2.v74
-rw-r--r--test-suite/ssr/elim_pattern.v27
-rw-r--r--test-suite/ssr/first_n.v21
-rw-r--r--test-suite/ssr/gen_have.v174
-rw-r--r--test-suite/ssr/gen_pattern.v33
-rw-r--r--test-suite/ssr/have_TC.v50
-rw-r--r--test-suite/ssr/have_transp.v48
-rw-r--r--test-suite/ssr/have_view_idiom.v18
-rw-r--r--test-suite/ssr/havesuff.v85
-rw-r--r--test-suite/ssr/if_isnt.v22
-rw-r--r--test-suite/ssr/intro_beta.v25
-rw-r--r--test-suite/ssr/intro_noop.v37
-rw-r--r--test-suite/ssr/ipatalternation.v18
-rw-r--r--test-suite/ssr/ltac_have.v39
-rw-r--r--test-suite/ssr/ltac_in.v26
-rw-r--r--test-suite/ssr/move_after.v19
-rw-r--r--test-suite/ssr/multiview.v58
-rw-r--r--test-suite/ssr/occarrow.v23
-rw-r--r--test-suite/ssr/patnoX.v18
-rw-r--r--test-suite/ssr/pattern.v32
-rw-r--r--test-suite/ssr/primproj.v164
-rw-r--r--test-suite/ssr/rewpatterns.v146
-rw-r--r--test-suite/ssr/set_lamda.v27
-rw-r--r--test-suite/ssr/set_pattern.v64
-rw-r--r--test-suite/ssr/ssrsyntax2.v20
-rw-r--r--test-suite/ssr/tc.v39
-rw-r--r--test-suite/ssr/typeof.v22
-rw-r--r--test-suite/ssr/unfold_Opaque.v18
-rw-r--r--test-suite/ssr/unkeyed.v31
-rw-r--r--test-suite/ssr/view_case.v31
-rw-r--r--test-suite/ssr/wlog_suff.v28
-rw-r--r--test-suite/ssr/wlogletin.v50
-rw-r--r--test-suite/ssr/wlong_intro.v20
-rw-r--r--test-suite/unit-tests/.merlin6
-rw-r--r--test-suite/unit-tests/clib/inteq.ml13
-rw-r--r--test-suite/unit-tests/clib/unicode_tests.ml15
-rw-r--r--test-suite/unit-tests/src/utest.ml74
-rw-r--r--test-suite/unit-tests/src/utest.mli12
-rw-r--r--vernac/comDefinition.ml4
-rw-r--r--vernac/metasyntax.ml6
157 files changed, 5932 insertions, 8936 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 14c102ced..79f83d472 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -160,22 +160,22 @@ workflows:
requires:
- build
- bignums
- - compcert: *req-main
- - coq-dpdgraph: *req-main
- - coquelicot: *req-main
- - cross-crypto: *req-main
- - elpi: *req-main
- - equations: *req-main
- - geocoq: *req-main
- - fcsl-pcm: *req-main
- - fiat-crypto: *req-main
- - fiat-parsers: *req-main
- - flocq: *req-main
+ # - compcert: *req-main
+ # - coq-dpdgraph: *req-main
+ # - coquelicot: *req-main
+ # - cross-crypto: *req-main
+ # - elpi: *req-main
+ # - equations: *req-main
+ # - geocoq: *req-main
+ # - fcsl-pcm: *req-main
+ # - fiat-crypto: *req-main
+ # - fiat-parsers: *req-main
+ # - flocq: *req-main
- math-classes:
requires:
- build
- bignums
- - mtac2: *req-main
+ # - mtac2: *req-main
- corn:
requires:
- build
@@ -184,11 +184,11 @@ workflows:
requires:
- build
- corn
- - hott: *req-main
- - iris-lambda-rust: *req-main
- - ltac2: *req-main
- - math-comp: *req-main
- - pidetop: *req-main
- - sf: *req-main
- - unimath: *req-main
- - vst: *req-main
+ # - hott: *req-main
+ # - iris-lambda-rust: *req-main
+ # - ltac2: *req-main
+ # - math-comp: *req-main
+ # - pidetop: *req-main
+ # - sf: *req-main
+ # - unimath: *req-main
+ # - vst: *req-main
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index ab9725c96..2ca827492 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -8,9 +8,13 @@
########## CI infrastructure ##########
-/dev/ci/*.sh @ejgallego
+/dev/ci/ @ejgallego
# Secondary maintainer @SkySkimmer
+/dev/ci/user-overlays/*.sh @ghost
+# Trick to avoid getting review requests
+# each time someone adds an overlay
+
/.circleci/ @SkySkimmer
# Secondary maintainer @ejgallego
@@ -20,7 +24,9 @@
/.gitlab-ci.yml @SkySkimmer
# Secondary maintainer @ejgallego
-/appveyor.yml @maximedenes
+/appveyor.yml @maximedenes
+/dev/ci/appveyor.* @maximedenes
+/dev/ci/*.bat @maximedenes
# Secondary maintainer @SkySkimmer
/default.nix @Zimmi48
@@ -338,3 +344,6 @@
/dev/tools/pre-commit @SkySkimmer
/dev/tools/sudo-apt-get-update @JasonGross
+
+/dev/tools/check-owners*.sh @SkySkimmer
+# Secondary maintainer @maximedenes
diff --git a/.gitignore b/.gitignore
index e2a97b3a1..f1960ba68 100644
--- a/.gitignore
+++ b/.gitignore
@@ -88,6 +88,8 @@ test-suite/coqdoc/Coqdoc.*
test-suite/coqdoc/index.html
test-suite/coqdoc/coqdoc.css
test-suite/output/MExtraction.out
+test-suite/oUnit-anon.cache
+test-suite/unit-tests/**/*.test
# documentation
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ac4304da1..c010da4cf 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,6 +1,7 @@
-image: coqci/base:V2018-05-07-V2
+image: "$IMAGE"
stages:
+ - docker
- build
- test
@@ -9,11 +10,28 @@ variables:
# Format: $IMAGE-V$DATE [Cache is not used as of today but kept here
# for reference]
CACHEKEY: bionic_coq-V2018-05-07-V2
+ IMAGE: "$CI_REGISTRY_IMAGE:$CACHEKEY"
# By default, jobs run in the base switch; override to select another switch
OPAM_SWITCH: "base"
# Used to select special compiler switches such as flambda, 32bits, etc...
OPAM_VARIANT: ""
+docker-boot:
+ stage: docker
+ image: docker:stable
+ services:
+ - docker:dind
+ before_script: []
+ script:
+ - docker login -u gitlab-ci-token -p "$CI_JOB_TOKEN" "$CI_REGISTRY"
+ - cd dev/ci/docker/bionic_coq/
+ - if docker pull "$IMAGE"; then echo "Image prebuilt!"; exit 0; fi
+ - docker build -t "$IMAGE" .
+ - docker push "$IMAGE"
+ except:
+ variables:
+ - $SKIP_DOCKER == "true"
+
before_script:
- cat /proc/{cpu,mem}info || true
- ls -a # figure out if artifacts are around
@@ -76,7 +94,7 @@ before_script:
- set +e
variables: &warnings-variables
- COQ_EXTRA_CONF: "-native-compiler yes -coqide byte -byte-only"
+ COQ_EXTRA_CONF: "-native-compiler yes -coqide byte -byte-only -warn-error yes"
# every non build job must set dependencies otherwise all build
# artifacts are used together and we may get some random Coq. To that
@@ -134,6 +152,24 @@ before_script:
OPAM_SWITCH: "edge"
OPAM_VARIANT: "+flambda"
+.windows-template: &windows-template
+ stage: test
+ artifacts:
+ name: "%CI_JOB_NAME%"
+ paths:
+ - dev\nsis\*.exe
+ - coq-opensource-archive-windows-*.zip
+ expire_in: 1 week
+ dependencies: []
+ tags:
+ - windows
+ before_script: []
+ script:
+ - call dev/ci/gitlab.bat
+ only:
+ variables:
+ - $WINDOWS == "enabled"
+
build:base:
<<: *build-template
variables:
@@ -160,6 +196,16 @@ build:edge+flambda:
COQ_EXTRA_CONF: "-native-compiler no -coqide opt -flambda-opts "
COQ_EXTRA_CONF_QUOTE: "-O3 -unbox-closures"
+windows64:
+ <<: *windows-template
+ variables:
+ ARCH: "64"
+
+windows32:
+ <<: *windows-template
+ variables:
+ ARCH: "32"
+
warnings:base:
<<: *warnings-template
@@ -171,6 +217,7 @@ warnings:base:
warnings:edge:
<<: *warnings-template
variables:
+ <<: *warnings-variables
OPAM_SWITCH: edge
test-suite:base:
@@ -278,9 +325,6 @@ ci-iris-lambda-rust:
ci-ltac2:
<<: *ci-template
-ci-math-classes:
- <<: *ci-template
-
ci-math-comp:
<<: *ci-template-flambda
diff --git a/.travis.yml b/.travis.yml
index d7caf1daf..890ee6d7c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -49,18 +49,24 @@ env:
- NATIVE_COMP="yes"
- COQ_DEST="-local"
- MAIN_TARGET="world"
- # Main test suites
- matrix:
- - TEST_TARGET="test-suite" COMPILER="4.02.3+32bit"
- - TEST_TARGET="validate" TW="travis_wait"
- - TEST_TARGET="validate" COMPILER="4.02.3+32bit" TW="travis_wait"
- - TEST_TARGET="validate" COMPILER="${COMPILER_BE}+flambda" CAMLP5_VER="${CAMLP5_VER_BE}" NATIVE_COMP="no" EXTRA_CONF="-flambda-opts -O3" FINDLIB_VER="${FINDLIB_VER_BE}"
matrix:
include:
- if: NOT (type = pull_request)
env:
+ - TEST_TARGET="test-suite" COMPILER="4.02.3+32bit" EXTRA_OPAM="ounit"
+ - if: NOT (type = pull_request)
+ env:
+ - TEST_TARGET="validate" TW="travis_wait"
+ - if: NOT (type = pull_request)
+ env:
+ - TEST_TARGET="validate" COMPILER="4.02.3+32bit" TW="travis_wait"
+ - if: NOT (type = pull_request)
+ env:
+ - TEST_TARGET="validate" COMPILER="${COMPILER_BE}+flambda" CAMLP5_VER="${CAMLP5_VER_BE}" NATIVE_COMP="no" EXTRA_CONF="-flambda-opts -O3" FINDLIB_VER="${FINDLIB_VER_BE}"
+ - if: NOT (type = pull_request)
+ env:
- TEST_TARGET="ci-bignums"
- if: NOT (type = pull_request)
env:
@@ -87,39 +93,24 @@ matrix:
- TEST_TARGET="ci-equations"
- if: NOT (type = pull_request)
env:
- - TEST_TARGET="ci-geocoq"
- - if: NOT (type = pull_request)
- env:
- TEST_TARGET="ci-fcsl-pcm"
- if: NOT (type = pull_request)
env:
- - TEST_TARGET="ci-fiat-crypto"
- - if: NOT (type = pull_request)
- env:
- TEST_TARGET="ci-fiat-parsers"
- if: NOT (type = pull_request)
env:
- TEST_TARGET="ci-flocq"
- if: NOT (type = pull_request)
env:
- - TEST_TARGET="ci-formal-topology"
- - if: NOT (type = pull_request)
- env:
- TEST_TARGET="ci-hott"
- if: NOT (type = pull_request)
env:
- - TEST_TARGET="ci-iris-lambda-rust"
- - if: NOT (type = pull_request)
- env:
- TEST_TARGET="ci-ltac2"
- if: NOT (type = pull_request)
env:
- TEST_TARGET="ci-math-classes"
- if: NOT (type = pull_request)
env:
- - TEST_TARGET="ci-math-comp"
- - if: NOT (type = pull_request)
- env:
- TEST_TARGET="ci-mtac2"
- if: NOT (type = pull_request)
env:
@@ -127,12 +118,6 @@ matrix:
- if: NOT (type = pull_request)
env:
- TEST_TARGET="ci-sf"
- - if: NOT (type = pull_request)
- env:
- - TEST_TARGET="ci-unimath"
- - if: NOT (type = pull_request)
- env:
- - TEST_TARGET="ci-vst"
- env:
- TEST_TARGET="lint"
@@ -146,10 +131,11 @@ matrix:
- dev/lint-repository.sh
# Full Coq test-suite with two compilers
- - env:
+ - if: NOT (type = pull_request)
+ env:
- TEST_TARGET="test-suite"
- EXTRA_CONF="-coqide opt -with-doc yes"
- - EXTRA_OPAM="hevea ${LABLGTK}"
+ - EXTRA_OPAM="${LABLGTK} ounit"
before_install: &sphinx-install
- sudo pip3 install bs4 sphinx sphinx_rtd_theme pexpect antlr4-python3-runtime sphinxcontrib-bibtex
addons:
@@ -174,13 +160,14 @@ matrix:
- python3-pip
- python3-setuptools
- - env:
+ - if: NOT (type = pull_request)
+ env:
- TEST_TARGET="test-suite"
- COMPILER="${COMPILER_BE}"
- FINDLIB_VER="${FINDLIB_VER_BE}"
- CAMLP5_VER="${CAMLP5_VER_BE}"
- EXTRA_CONF="-coqide opt -with-doc yes"
- - EXTRA_OPAM="hevea ${LABLGTK_BE}"
+ - EXTRA_OPAM="${LABLGTK_BE} ounit"
before_install: *sphinx-install
addons:
apt:
@@ -189,14 +176,15 @@ matrix:
packages: *extra-packages
# Full test-suite with flambda
- - env:
+ - if: NOT (type = pull_request)
+ env:
- TEST_TARGET="test-suite"
- COMPILER="${COMPILER_BE}+flambda"
- FINDLIB_VER="${FINDLIB_VER_BE}"
- CAMLP5_VER="${CAMLP5_VER_BE}"
- NATIVE_COMP="no"
- EXTRA_CONF="-coqide opt -with-doc yes -flambda-opts -O3"
- - EXTRA_OPAM="hevea ${LABLGTK_BE}"
+ - EXTRA_OPAM="${LABLGTK_BE} ounit"
before_install: *sphinx-install
addons:
apt:
@@ -205,10 +193,11 @@ matrix:
packages: *extra-packages
# Ocaml warnings with two compilers
- - env:
+ - if: NOT (type = pull_request)
+ env:
- MAIN_TARGET="coqocaml"
- EXTRA_CONF="-byte-only -coqide byte -warn-error yes"
- - EXTRA_OPAM="hevea ${LABLGTK}"
+ - EXTRA_OPAM="${LABLGTK}"
addons:
apt:
sources:
@@ -219,13 +208,14 @@ matrix:
- libgtk2.0-dev
- libgtksourceview2.0-dev
- - env:
+ - if: NOT (type = pull_request)
+ env:
- MAIN_TARGET="coqocaml"
- COMPILER="${COMPILER_BE}"
- FINDLIB_VER="${FINDLIB_VER_BE}"
- CAMLP5_VER="${CAMLP5_VER_BE}"
- EXTRA_CONF="-byte-only -coqide byte -warn-error yes"
- - EXTRA_OPAM="hevea ${LABLGTK_BE}"
+ - EXTRA_OPAM="${LABLGTK_BE}"
addons:
apt:
sources:
@@ -239,6 +229,7 @@ matrix:
- CAMLP5_VER=".6.17"
- NATIVE_COMP="no"
- COQ_DEST="-local"
+ - EXTRA_OPAM="ounit"
before_install:
- brew update
- brew unlink python
diff --git a/CHANGES b/CHANGES
index 68cc495f5..cdc1ff6a6 100644
--- a/CHANGES
+++ b/CHANGES
@@ -33,6 +33,14 @@ Tactic language
called by OCaml-defined tactics.
- Option "Ltac Debug" now applies also to terms built using Ltac functions.
+Changes from 8.8.0 to 8.8.1
+===========================
+
+Notations
+
+- Fixed unexpected collision between only-parsing and only-printing
+ notations (issue #7462).
+
Changes from 8.8+beta1 to 8.8.0
===============================
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1a3c99369..7fb976ee0 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -28,7 +28,13 @@ Please make pull requests against the `master` branch.
If it's your first significant contribution to Coq (significant means: more than fixing a typo), your pull request should include a commit adding your name to the [`CREDITS`](/CREDITS) file (possibly with the name of your institution / employer if relevant to your contribution, an ORCID if you have one —you may log into https://orcid.org/ using your institutional account to get one—, and the year of your contribution).
-It's helpful to run the Coq test suite with `make test-suite` before submitting your change. Travis CI runs this test suite and a much larger one including external Coq developments on every pull request, but these results take significantly longer to come back (on the order of a few hours). Running the test suite locally will take somewhere around 10-15 minutes. Refer to [`dev/ci/README.md`](/dev/ci/README.md#information-for-developers) for more information on Travis CI tests.
+It's helpful to run the Coq test suite with `make test-suite` before submitting
+your change. Our CI runs this test suite and lots of other tests, including
+building external Coq developments, on every pull request, but these results
+take significantly longer to come back (on the order of a few hours). Running
+the test suite locally will take somewhere around 10-15 minutes. Refer to
+[`dev/ci/README.md`](/dev/ci/README.md#information-for-developers) for more
+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.
diff --git a/INSTALL.doc b/INSTALL.doc
index f8a085280..13e6440d0 100644
--- a/INSTALL.doc
+++ b/INSTALL.doc
@@ -4,13 +4,13 @@
The Coq documentation includes
- A Reference Manual
-- A Tutorial
- A document presenting the Coq standard library
-- A list of questions/answers in the FAQ style
-The sources of the documents are mainly made of LaTeX code from which
-user-readable PostScript or PDF files, or a user-browsable bunch of
-html files are generated.
+The reference manual is written is reStructuredText and compiled
+using Sphinx (see `doc/sphinx/README.rst`) to learn more.
+
+The documentation for the standard library is generated from
+the `.v` source files using coqdoc.
Prerequisite
------------
@@ -20,9 +20,7 @@ To produce all the documents, the following tools are needed:
- latex (latex2e)
- pdflatex
- dvips
- - bibtex
- makeindex
- - hevea
- Python 3
- Sphinx 1.6.5 (http://www.sphinx-doc.org/en/stable/)
- sphinx_rtd_theme
@@ -35,7 +33,7 @@ Under recent Debian based operating systems (Debian 10 "Buster",
Ubuntu 18.04, ...) a working set of packages for compiling the
documentation for Coq is:
- texlive-latex-extra texlive-fonts-recommended hevea python3-sphinx
+ texlive-latex-extra texlive-fonts-recommended python3-sphinx
python3-pexpect python3-sphinx-rtd-theme python3-bs4
python3-sphinxcontrib.bibtex python3-pip
@@ -44,7 +42,7 @@ Then, install the Python3 Antlr4 package:
pip3 install antlr4-python3-runtime
Nix users should get the correct development environment to build the
-Sphinx documentation from Coq's `default.nix`. [Note Nix setup doesn't
+HTML documentation from Coq's `default.nix`. [Note Nix setup doesn't
include the LaTeX packages needed to build the full documentation.]
If you are in an older/different distribution you can install the
@@ -75,15 +73,6 @@ Alternatively, you can use some specific targets:
make sphinx
to produce the HTML version of the reference manual
- make tutorial
- to produce all formats of the tutorial
-
- make rectutorial
- to produce all formats of the tutorial on recursive types
-
- make faq
- to produce all formats of the FAQ
-
make stdlib
to produce all formats of the Coq standard library
@@ -99,7 +88,4 @@ To install all produced documents, do:
make DOCDIR=/some/directory/for/documentation install-doc
-DOCDIR defauts to /usr/share/doc/coq
-
-
-
+DOCDIR defaults to /usr/share/doc/coq
diff --git a/Makefile b/Makefile
index 793afb661..f914de5a6 100644
--- a/Makefile
+++ b/Makefile
@@ -58,7 +58,7 @@ FIND_SKIP_DIRS:='(' \
-name '_build_ci' -o \
-name '_install_ci' -o \
-name 'user-contrib' -o \
- -name 'coq-makefile' -o \
+ -name 'test-suite' -o \
-name '.opamcache' -o \
-name '.coq-native' \
')' -prune -o
diff --git a/Makefile.build b/Makefile.build
index ffe605757..179ca28b6 100644
--- a/Makefile.build
+++ b/Makefile.build
@@ -89,6 +89,7 @@ byte: coqbyte coqide-byte pluginsbyte printers
MLFILES := $(MLSTATICFILES) $(GENMLFILES) $(ML4FILES:.ml4=.ml)
include Makefile.common
+include Makefile.vofiles
include Makefile.doc ## provides the 'documentation' rule
include Makefile.checker
include Makefile.ide ## provides the 'coqide' rule
diff --git a/Makefile.checker b/Makefile.checker
index 172c64af3..dd1f6d514 100644
--- a/Makefile.checker
+++ b/Makefile.checker
@@ -34,6 +34,20 @@ CHECKMLLIBFILE := checker/.mllibfiles
CHECKERDEPS := $(addsuffix .d, $(CHECKMLDFILE) $(CHECKMLLIBFILE))
-include $(CHECKERDEPS)
+# Copied files
+checker/esubst.mli: kernel/esubst.mli
+ cp -a $< $@
+ sed -i.bak '1i(* AUTOGENERATED FILE: DO NOT EDIT *)\n\n\n\n\n\n\n\n' $@ && rm $@.bak
+checker/esubst.ml: kernel/esubst.ml
+ cp -a $< $@
+ sed -i.bak '1i(* AUTOGENERATED FILE: DO NOT EDIT *)\n\n\n\n\n\n\n\n' $@ && rm $@.bak
+checker/names.mli: kernel/names.mli
+ cp -a $< $@
+ sed -i.bak '1i(* AUTOGENERATED FILE: DO NOT EDIT *)\n\n\n\n\n\n\n\n' $@ && rm $@.bak
+checker/names.ml: kernel/names.ml
+ cp -a $< $@
+ sed -i.bak '1i(* AUTOGENERATED FILE: DO NOT EDIT *)\n\n\n\n\n\n\n\n' $@ && rm $@.bak
+
ifeq ($(BEST),opt)
$(CHICKEN): checker/check.cmxa checker/main.mli checker/main.ml
$(SHOW)'OCAMLOPT -o $@'
@@ -57,13 +71,15 @@ checker/check.cmxa: checker/check.mllib | md5chk
$(SHOW)'OCAMLOPT -a -o $@'
$(HIDE)$(OCAMLOPT) $(CHKLIBS) $(OPTFLAGS) -a -o $@ $(filter-out %.mllib, $^)
-$(CHECKMLDFILE).d: $(filter checker/%, $(MLFILES) $(MLIFILES))
+CHECKGENFILES:=$(addprefix checker/, names.mli names.ml esubst.mli esubst.ml)
+
+$(CHECKMLDFILE).d: $(filter checker/%, $(MLFILES) $(MLIFILES) $(CHECKGENFILES))
$(SHOW)'OCAMLDEP checker/MLFILES checker/MLIFILES'
- $(HIDE)$(OCAMLFIND) ocamldep -slash $(CHKLIBS) $(filter checker/%, $(MLFILES) $(MLIFILES)) $(TOTARGET)
+ $(HIDE)$(OCAMLFIND) ocamldep -slash $(CHKLIBS) $(filter checker/%, $(MLFILES) $(MLIFILES) $(CHECKGENFILES)) $(TOTARGET)
-$(CHECKMLLIBFILE).d: $(filter checker/%, $(MLLIBFILES) $(MLPACKFILES)) | $(OCAMLLIBDEP)
+$(CHECKMLLIBFILE).d: $(filter checker/%, $(MLLIBFILES) $(MLPACKFILES) $(CHECKGENFILES)) | $(OCAMLLIBDEP)
$(SHOW)'OCAMLLIBDEP checker/MLLIBFILES checker/MLPACKFILES'
- $(HIDE)$(OCAMLLIBDEP) $(CHKLIBS) $(filter checker/%, $(MLLIBFILES) $(MLPACKFILES)) $(TOTARGET)
+ $(HIDE)$(OCAMLLIBDEP) $(CHKLIBS) $(filter checker/%, $(MLLIBFILES) $(MLPACKFILES) $(CHECKGENFILES)) $(TOTARGET)
checker/%.cmi: checker/%.mli
$(SHOW)'OCAMLC $<'
diff --git a/Makefile.common b/Makefile.common
index eed41fbe7..9493acd1f 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -105,16 +105,12 @@ BYTERUN:=$(addprefix kernel/byterun/, \
CORECMA:=clib/clib.cma lib/lib.cma kernel/kernel.cma library/library.cma \
engine/engine.cma pretyping/pretyping.cma interp/interp.cma proofs/proofs.cma \
parsing/parsing.cma printing/printing.cma tactics/tactics.cma vernac/vernac.cma \
- stm/stm.cma toplevel/toplevel.cma
+ stm/stm.cma toplevel/toplevel.cma
TOPLOOPCMA:=stm/proofworkertop.cma stm/tacworkertop.cma stm/queryworkertop.cma
GRAMMARCMA:=grammar/grammar.cma
-# modules known by the toplevel of Coq
-
-OBJSMOD:=$(shell cat $(CORECMA:.cma=.mllib))
-
###########################################################################
# plugins object files
###########################################################################
@@ -163,40 +159,8 @@ PLUGINSOPT:=$(PLUGINSCMO:.cmo=.cmxs)
LINKCMO:=$(CORECMA) $(STATICPLUGINS)
LINKCMX:=$(CORECMA:.cma=.cmxa) $(STATICPLUGINS:.cmo=.cmx)
-###########################################################################
-# vo files
-###########################################################################
-
-THEORIESVO := $(patsubst %.v,%.vo,$(shell find theories -type f -name "*.v"))
-PLUGINSVO := $(patsubst %.v,%.vo,$(shell find plugins -type f -name "*.v"))
-ALLVO := $(THEORIESVO) $(PLUGINSVO)
-VFILES := $(ALLVO:.vo=.v)
-
-## More specific targets
-
-THEORIESLIGHTVO:= \
- $(filter theories/Init/% theories/Logic/% theories/Unicode/% theories/Arith/%, $(THEORIESVO))
-
ALLSTDLIB := test-suite/misc/universes/all_stdlib
-# convert a (stdlib) filename into a module name:
-# remove .vo, replace theories and plugins by Coq, and replace slashes by dots
-vo_to_mod = $(subst /,.,$(patsubst theories/%,Coq.%,$(patsubst plugins/%,Coq.%,$(1:.vo=))))
-
-ALLMODS:=$(call vo_to_mod,$(ALLVO))
-
-
-# Converting a stdlib filename into native compiler filenames
-# Used for install targets
-vo_to_cm = $(foreach vo,$(1),$(dir $(vo)).coq-native/$(subst /,_,$(patsubst theories/%,NCoq_%,$(patsubst plugins/%,NCoq_%,$(vo:.vo=.cm*)))))
-
-vo_to_obj = $(foreach vo,$(1),$(dir $(vo)).coq-native/$(subst /,_,$(patsubst theories/%,NCoq_%,$(patsubst plugins/%,NCoq_%,$(vo:.vo=.o)))))
-
-GLOBFILES:=$(ALLVO:.vo=.glob)
-LIBFILES:=$(ALLVO) $(call vo_to_cm,$(ALLVO)) \
- $(call vo_to_obj,$(ALLVO)) \
- $(VFILES) $(GLOBFILES)
-
# For emacs:
# Local Variables:
# mode: makefile
diff --git a/Makefile.doc b/Makefile.doc
index 9b6013d8d..41ae11b86 100644
--- a/Makefile.doc
+++ b/Makefile.doc
@@ -10,10 +10,7 @@
# Makefile for the Coq documentation
-# To compile documentation, you need the following tools:
-# Dvi: latex (latex2e), bibtex, makeindex
-# Pdf: pdflatex
-# Html: hevea (http://hevea.inria.fr) >= 1.05
+# Read INSTALL.doc to learn about the dependencies
# The main entry point :
@@ -28,20 +25,10 @@ doc-no:
######################################################################
LATEX:=latex
-BIBTEX:=BIBINPUTS=.: bibtex -min-crossrefs=10
MAKEINDEX:=makeindex
PDFLATEX:=pdflatex
DVIPS:=dvips
-HEVEA:=hevea
-HEVEAOPTS:=-fix -exec xxdate.exe
-HEVEALIB:=/usr/local/lib/hevea:/usr/lib/hevea
HTMLSTYLE:=coqremote
-export TEXINPUTS:=$(HEVEALIB):
-ifdef COQDOC_NOBOOT
-COQTEXOPTS:=-n 72 -sl -small
-else
-COQTEXOPTS:=-boot -n 72 -sl -small
-endif
# Sphinx-related variables
SPHINXOPTS= -j4
@@ -57,31 +44,29 @@ DOCCOMMON:=doc/common/version.tex doc/common/title.tex doc/common/macros.tex
### General rules
######################################################################
-.PHONY: doc sphinxdoc-html doc-pdf doc-ps tutorial
-.PHONY: stdlib full-stdlib rectutorial
+.PHONY: doc doc-html doc-pdf doc-ps
+.PHONY: stdlib full-stdlib
-doc: sphinx tutorial rectutorial stdlib
+doc: sphinx stdlib
+
+ifndef QUICK
+SPHINX_DEPS := coq
+endif
-sphinx: coq
+sphinx: $(SPHINX_DEPS)
$(SHOW)'SPHINXBUILD doc/sphinx'
$(HIDE)COQBIN="$(PWD)/bin" $(SPHINXBUILD) -W -b html $(ALLSPHINXOPTS) doc/sphinx $(SPHINXBUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(SPHINXBUILDDIR)/html."
doc-html:\
- doc/tutorial/Tutorial.v.html \
- doc/stdlib/html/index.html doc/RecTutorial/RecTutorial.html
+ doc/stdlib/html/index.html sphinx
doc-pdf:\
- doc/tutorial/Tutorial.v.pdf \
- doc/stdlib/Library.pdf doc/RecTutorial/RecTutorial.pdf
+ doc/stdlib/Library.pdf
doc-ps:\
- doc/tutorial/Tutorial.v.ps \
- doc/stdlib/Library.ps doc/RecTutorial/RecTutorial.ps
-
-tutorial: \
- doc/tutorial/Tutorial.v.html doc/tutorial/Tutorial.v.ps doc/tutorial/Tutorial.v.pdf
+ doc/stdlib/Library.ps
stdlib: \
doc/stdlib/html/index.html doc/stdlib/Library.ps doc/stdlib/Library.pdf
@@ -89,32 +74,14 @@ stdlib: \
full-stdlib: \
doc/stdlib/html/index.html doc/stdlib/FullLibrary.ps doc/stdlib/FullLibrary.pdf
-rectutorial: doc/RecTutorial/RecTutorial.html \
- doc/RecTutorial/RecTutorial.ps doc/RecTutorial/RecTutorial.pdf
-
######################################################################
### Implicit rules
######################################################################
-ifdef QUICK
-%.v.tex: %.tex
- $(COQTEX) $(COQTEXOPTS) $<
-else
-%.v.tex: %.tex $(COQTEX) $(COQTOPEXE) $(ALLVO)
- $(COQTEX) $(COQTEXOPTS) $<
-endif
-
%.ps: %.dvi
(cd `dirname $<`; $(DVIPS) -q -o `basename $@` `basename $<`)
######################################################################
-# Macros for filtering outputs
-######################################################################
-
-HIDEBIBTEXINFO=| grep -v "^A level-1 auxiliary file"
-SHOWMAKEINDEXERROR=egrep '^!! Input index error|^\*\* Input style error|^ --'
-
-######################################################################
# Common
######################################################################
@@ -124,23 +91,6 @@ doc/common/version.tex: config/Makefile
printf '\\newcommand{\\coqversion}{$(VERSION)}' > doc/common/version.tex
######################################################################
-# Tutorial
-######################################################################
-
-doc/tutorial/Tutorial.v.dvi: $(DOCCOMMON) doc/tutorial/Tutorial.v.tex
- (cd doc/tutorial;\
- $(LATEX) -interaction=batchmode Tutorial.v;\
- ../tools/show_latex_messages Tutorial.v.log)
-
-doc/tutorial/Tutorial.v.pdf: $(DOCCOMMON) doc/tutorial/Tutorial.v.tex
- (cd doc/tutorial;\
- $(PDFLATEX) -interaction=batchmode Tutorial.v.tex;\
- ../tools/show_latex_messages Tutorial.v.log)
-
-doc/tutorial/Tutorial.v.html: $(DOCCOMMON) doc/tutorial/Tutorial.v.tex
- (cd doc/tutorial; $(HEVEA) $(HEVEAOPTS) Tutorial.v)
-
-######################################################################
# Standard library
######################################################################
@@ -214,53 +164,28 @@ doc/stdlib/FullLibrary.pdf: $(DOCCOMMON) doc/stdlib/FullLibrary.coqdoc.tex doc/s
../tools/show_latex_messages -no-overfull FullLibrary.log)
######################################################################
-# Tutorial on inductive types
-######################################################################
-
-doc/RecTutorial/RecTutorial.dvi: doc/common/version.tex doc/common/title.tex doc/RecTutorial/RecTutorial.tex
- (cd doc/RecTutorial;\
- $(LATEX) -interaction=batchmode RecTutorial;\
- $(BIBTEX) -terse RecTutorial;\
- $(LATEX) -interaction=batchmode RecTutorial > /dev/null;\
- $(LATEX) -interaction=batchmode RecTutorial > /dev/null;\
- ../tools/show_latex_messages RecTutorial.log)
-
-doc/RecTutorial/RecTutorial.pdf: doc/common/version.tex doc/common/title.tex doc/RecTutorial/RecTutorial.dvi
- (cd doc/RecTutorial;\
- $(PDFLATEX) -interaction=batchmode RecTutorial.tex;\
- ../tools/show_latex_messages RecTutorial.log)
-
-doc/RecTutorial/RecTutorial.html: doc/RecTutorial/RecTutorial.tex
- (cd doc/RecTutorial; $(HEVEA) $(HEVEAOPTS) RecTutorial)
-
-######################################################################
# Install all documentation files
######################################################################
.PHONY: install-doc install-doc-meta install-doc-html install-doc-printable \
- install-doc-index-urls install-doc-sphinx
+ install-doc-sphinx install-doc-stdlib-html
-install-doc: install-doc-meta install-doc-html install-doc-printable \
- install-doc-index-urls install-doc-sphinx
+install-doc: install-doc-meta install-doc-html install-doc-printable
install-doc-meta:
$(MKDIR) $(FULLDOCDIR)
$(INSTALLLIB) doc/LICENSE $(FULLDOCDIR)/LICENSE.doc
-install-doc-html:
+install-doc-html: install-doc-stdlib-html install-doc-sphinx
+
+install-doc-stdlib-html:
$(MKDIR) $(FULLDOCDIR)/html/stdlib
$(INSTALLLIB) doc/stdlib/html/* $(FULLDOCDIR)/html/stdlib
- $(INSTALLLIB) doc/RecTutorial/RecTutorial.html $(FULLDOCDIR)/html/RecTutorial.html
- $(INSTALLLIB) doc/tutorial/Tutorial.v.html $(FULLDOCDIR)/html/Tutorial.html
install-doc-printable:
$(MKDIR) $(FULLDOCDIR)/ps $(FULLDOCDIR)/pdf
$(INSTALLLIB) doc/stdlib/Library.pdf $(FULLDOCDIR)/pdf
$(INSTALLLIB) doc/stdlib/Library.ps $(FULLDOCDIR)/ps
- $(INSTALLLIB) doc/tutorial/Tutorial.v.pdf $(FULLDOCDIR)/pdf/Tutorial.pdf
- $(INSTALLLIB) doc/RecTutorial/RecTutorial.pdf $(FULLDOCDIR)/pdf/RecTutorial.pdf
- $(INSTALLLIB) doc/tutorial/Tutorial.v.ps $(FULLDOCDIR)/ps/Tutorial.ps
- $(INSTALLLIB) doc/RecTutorial/RecTutorial.ps $(FULLDOCDIR)/ps/RecTutorial.ps
install-doc-sphinx:
$(MKDIR) $(FULLDOCDIR)/sphinx
diff --git a/Makefile.vofiles b/Makefile.vofiles
new file mode 100644
index 000000000..fc902c4a8
--- /dev/null
+++ b/Makefile.vofiles
@@ -0,0 +1,40 @@
+
+# This file calls [find] and as such is not suitable for inclusion in
+# the test suite Makefile, unlike Makefile.common.
+
+###########################################################################
+# vo files
+###########################################################################
+
+THEORIESVO := $(patsubst %.v,%.vo,$(shell find theories -type f -name "*.v"))
+PLUGINSVO := $(patsubst %.v,%.vo,$(shell find plugins -type f -name "*.v"))
+ALLVO := $(THEORIESVO) $(PLUGINSVO)
+VFILES := $(ALLVO:.vo=.v)
+
+## More specific targets
+
+THEORIESLIGHTVO:= \
+ $(filter theories/Init/% theories/Logic/% theories/Unicode/% theories/Arith/%, $(THEORIESVO))
+
+# convert a (stdlib) filename into a module name:
+# remove .vo, replace theories and plugins by Coq, and replace slashes by dots
+vo_to_mod = $(subst /,.,$(patsubst theories/%,Coq.%,$(patsubst plugins/%,Coq.%,$(1:.vo=))))
+
+ALLMODS:=$(call vo_to_mod,$(ALLVO))
+
+
+# Converting a stdlib filename into native compiler filenames
+# Used for install targets
+vo_to_cm = $(foreach vo,$(1),$(dir $(vo)).coq-native/$(subst /,_,$(patsubst theories/%,NCoq_%,$(patsubst plugins/%,NCoq_%,$(vo:.vo=.cm*)))))
+
+vo_to_obj = $(foreach vo,$(1),$(dir $(vo)).coq-native/$(subst /,_,$(patsubst theories/%,NCoq_%,$(patsubst plugins/%,NCoq_%,$(vo:.vo=.o)))))
+
+GLOBFILES:=$(ALLVO:.vo=.glob)
+LIBFILES:=$(ALLVO) $(call vo_to_cm,$(ALLVO)) \
+ $(call vo_to_obj,$(ALLVO)) \
+ $(VFILES) $(GLOBFILES)
+
+# For emacs:
+# Local Variables:
+# mode: makefile
+# End:
diff --git a/README.md b/README.md
index 883630acf..4956da36d 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,6 @@
# Coq
+[![pipeline status](https://gitlab.com/coq/coq/badges/master/pipeline.svg)](https://gitlab.com/coq/coq/commits/master)
[![Travis](https://travis-ci.org/coq/coq.svg?branch=master)](https://travis-ci.org/coq/coq/builds)
[![Appveyor](https://ci.appveyor.com/api/projects/status/eln43k05pa2vm908/branch/master?svg=true)](https://ci.appveyor.com/project/coq/coq/branch/master)
[![Circle CI](https://circleci.com/gh/coq/coq/tree/master.svg?style=shield)](https://circleci.com/gh/coq/workflows/coq/tree/master)
diff --git a/appveyor.yml b/appveyor.yml
index 44a93d15d..cd3b88d00 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -10,10 +10,6 @@ image:
environment:
CYGMIRROR: http://ftp.inf.tu-dresden.de/software/windows/cygwin32
matrix:
- - USEOPAM: false
- ARCH: 32
- - USEOPAM: false
- ARCH: 64
- USEOPAM: true
ARCH: 64
@@ -21,11 +17,3 @@ build_script:
- cmd: 'call %APPVEYOR_BUILD_FOLDER%\dev\ci\appveyor.bat'
test: off
-
-artifacts:
- - path: 'dev\nsis\*.exe'
- name: installer
-
- - path: 'coq-opensource-archive-*.zip'
- name: opensource-archive
-
diff --git a/configure.ml b/configure.ml
index e77310eb7..d4750700b 100644
--- a/configure.ml
+++ b/configure.ml
@@ -1247,17 +1247,6 @@ let write_configml f =
let _ = write_configml "config/coq_config.ml"
-(** * Symlinks or copies for the checker *)
-
-let _ =
- let prog, args, prf =
- if arch = "win32" then "cp", [], ""
- else "ln", ["-s"], "../" in
- List.iter (fun file ->
- ignore(run "rm" ["-f"; "checker/"^file]);
- ignore(run ~fatal:true prog (args @ [prf^"kernel/"^file;"checker/"^file])))
- [ "esubst.ml"; "esubst.mli"; "names.ml"; "names.mli" ]
-
(** * Build the config/Makefile file *)
let write_makefile f =
diff --git a/default.nix b/default.nix
index 0b4794274..effee720d 100644
--- a/default.nix
+++ b/default.nix
@@ -90,9 +90,9 @@ stdenv.mkDerivation rec {
prefixKey = "-prefix ";
- buildFlags = optionals buildDoc [ "world" "sphinx" ];
+ buildFlags = [ "world" ] ++ optional buildDoc "doc-html";
- installTargets = [ "install" ] ++ optional buildDoc "install-doc-sphinx";
+ installTargets = [ "install" ] ++ optional buildDoc "install-doc-html";
inherit doCheck;
diff --git a/dev/build/windows/makecoq_mingw.sh b/dev/build/windows/makecoq_mingw.sh
index f4ec218b6..3608f7305 100644
--- a/dev/build/windows/makecoq_mingw.sh
+++ b/dev/build/windows/makecoq_mingw.sh
@@ -970,6 +970,10 @@ function make_lablgtk {
# These changes are included in dev/build/windows/patches_coq/lablgtk-2.18.3.patch
log2 make world
+
+ # lablgtk does not escape FINDLIBDIR path, which can contain backslashes
+ sed -i "s|^FINDLIBDIR=.*|FINDLIBDIR=$PREFIXOCAML/libocaml/site-lib|" config.make
+
log2 make install
log2 make clean
build_post
diff --git a/dev/ci/README.md b/dev/ci/README.md
index bb13587e9..dee3d2aff 100644
--- a/dev/ci/README.md
+++ b/dev/ci/README.md
@@ -36,9 +36,8 @@ On the condition that:
- You do not push, to the branches that we test, commits that haven't been
first tested to compile with the corresponding branch(es) of Coq.
-- Your development compiles in less than 35 minutes with just two threads.
- If this is not the case, consider adding a "lite" target that compiles just
- part of it.
+- You maintain a reasonable build time for your development, or you provide
+ a "lite" target that we can use.
In case you forget to comply with these last three conditions, we would reach
out to you and give you a 30-day grace period during which your development
@@ -54,9 +53,10 @@ Add a new `ci-mydev.sh` script to [`dev/ci`](/dev/ci) (have a look at
set the corresponding variables in
[`ci-basic-overlay.sh`](/dev/ci/ci-basic-overlay.sh); add the corresponding
target to [`Makefile.ci`](/Makefile.ci); add new jobs to
-[`.travis.yml`](/.travis.yml) and [`.gitlab-ci.yml`](/.gitlab-ci.yml) so that
-this new target is run. **Do not hesitate to submit an incomplete pull request
-if you need help to finish it.**
+[`.gitlab-ci.yml`](/.gitlab-ci.yml),
+[`.circleci/config.yml`](/.circleci/config.yml) and
+[`.travis.yml`](/.travis.yml) so that this new target is run. **Do not
+hesitate to submit an incomplete pull request if you need help to finish it.**
You may also be interested in having your development tested in our
performance benchmark. Currently this is done by providing an OPAM package
@@ -71,24 +71,39 @@ When you submit a pull request (PR) on Coq GitHub repository, this will
automatically launch a battery of CI tests. The PR will not be integrated
unless these tests pass.
-Currently, we have two CI platforms:
+We are currently running tests on the following platforms:
-- Travis is the main CI platform. It tests the compilation of Coq, of the
+- GitLab CI is the main CI platform. It tests the compilation of Coq, of the
documentation, and of CoqIDE on Linux with several versions of OCaml /
camlp5, and with warnings as errors; it runs the test-suite and tests the
- compilation of several external developments. It also tests the compilation
- of Coq on OS X.
+ compilation of several external developments.
+
+- Circle CI runs tests that are redundant with GitLab CI and may be removed
+ eventually.
+
+- Travis CI is used to test the compilation of Coq and run the test-suite on
+ macOS. It also runs a linter that checks whitespace discipline. A
+ [pre-commit hook](/dev/tools/pre-commit) is automatically installed by
+ `./configure`. It should allow complying with this discipline without pain.
- AppVeyor is used to test the compilation of Coq and run the test-suite on
Windows.
-You can anticipate the results of these tests prior to submitting your PR
-by having them run of your fork of Coq, on GitHub or GitLab. This can be
-especially helpful given that our Travis platform is often overloaded and
-therefore there can be a significant delay before these tests are actually
-run on your PR. To take advantage of this, simply create a Travis account
-and link it to your GitHub account, or activate the pipelines on your GitLab
-fork.
+You can anticipate the results of most of these tests prior to submitting your
+PR by running GitLab CI on your private branches. To do so follow these steps:
+
+1. Log into GitLab CI (the easiest way is to sign in with your GitHub account).
+2. Click on "New Project".
+3. Choose "CI / CD for external repository" then click on "GitHub".
+4. Find your fork of the Coq repository and click on "Connect".
+5. If GitLab did not do so automatically, [enable the Container Registry](https://docs.gitlab.com/ee/user/project/container_registry.html#enable-the-container-registry-for-your-project).
+6. You are encouraged to go to the CI / CD general settings and increase the
+ timeout from 1h to 2h for better reliability.
+
+Now everytime you push (including force-push unless you changed the default
+GitLab setting) to your fork on GitHub, it will be synchronized on GitLab and
+CI will be run. You will receive an e-mail with a report of the failures if
+there are some.
You can also run one CI target locally (using `make ci-somedev`).
@@ -97,36 +112,53 @@ so that it doesn't, or provide a branch fixing these developments (or at
least work with the author of the development / other Coq developers to
prepare these fixes). Then, add an overlay in
[`dev/ci/user-overlays`](/dev/ci/user-overlays) (see the README there)
-in a separate commit in your PR.
+as part of your PR.
The process to merge your PR is then to submit PRs to the external
development repositories, merge the latter first (if the fixes are
-backward-compatible), drop the overlay commit and merge the PR on Coq then.
+backward-compatible), and merge the PR on Coq then.
See also [`test-suite/README.md`](/test-suite/README.md) for information about adding new tests to the test-suite.
-Travis specific information
----------------------------
+Advanced GitLab CI information
+------------------------------
-Travis rebuilds all of Coq's executables and stdlib for each job. Coq
-is built with `./configure -local`, then used for the job's test.
-
-
-GitLab specific information
----------------------------
-
-GitLab is set up to use the "build artifact" feature to avoid
-rebuilding Coq. In one job, Coq is built with `./configure -prefix
-install` and `make install` is run, then the `install` directory
+GitLab CI is set up to use the "build artifact" feature to avoid
+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, in two different copies varying in the OCaml
- version used to build Coq
+ 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.
As an exception to the above, jobs testing that compilation triggers
-no Ocaml warnings build Coq in parallel with other tests.
+no OCaml warnings build Coq in parallel with other tests.
+
+### GitLab and Windows
+
+
+If your repository has access to runners tagged `windows`, setting the
+secret variable `WINDOWS` to `enabled` will add jobs building Windows
+versions of Coq (32bit and 64bit).
+
+The Windows jobs are enabled on Coq's repository, where pipelines for
+pull requests run.
+
+### GitLab and Docker
+
+System and opam packages are installed in a Docker image. The image is
+automatically built and uploaded to your GitLab registry, and is
+loaded by subsequent jobs.
+
+The Docker building job reuses the uploaded image if it is available,
+but if you wish to save more time you can skip the job by setting
+`SKIP_DOCKER` to `true`.
+
+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.
diff --git a/dev/ci/appveyor.sh b/dev/ci/appveyor.sh
index 93e7bd99a..c72705c7f 100644
--- a/dev/ci/appveyor.sh
+++ b/dev/ci/appveyor.sh
@@ -5,5 +5,5 @@ tar -xf opam64.tar.xz
bash opam64/install.sh
opam init -a mingw https://github.com/fdopen/opam-repository-mingw.git --comp 4.02.3+mingw64c --switch 4.02.3+mingw64c
eval "$(opam config env)"
-opam install -y ocamlfind camlp5
+opam install -y ocamlfind camlp5 ounit
cd "$APPVEYOR_BUILD_FOLDER" && ./configure -local && make && make byte && make -C test-suite all INTERACTIVE= && make validate
diff --git a/dev/ci/ci-basic-overlay.sh b/dev/ci/ci-basic-overlay.sh
index b7faea13e..5c882ee85 100755
--- a/dev/ci/ci-basic-overlay.sh
+++ b/dev/ci/ci-basic-overlay.sh
@@ -11,6 +11,8 @@
########################################################################
: "${mathcomp_CI_BRANCH:=master}"
: "${mathcomp_CI_GITURL:=https://github.com/math-comp/math-comp.git}"
+: "${oddorder_CI_BRANCH:=master}"
+: "${oddorder_CI_GITURL:=https://github.com/math-comp/odd-order.git}"
########################################################################
# UniMath
diff --git a/dev/ci/ci-common.sh b/dev/ci/ci-common.sh
index 189734a0b..f867fd189 100644
--- a/dev/ci/ci-common.sh
+++ b/dev/ci/ci-common.sh
@@ -10,6 +10,10 @@ if [ -n "${GITLAB_CI}" ];
then
export COQBIN="$PWD/_install_ci/bin"
export CI_BRANCH="$CI_COMMIT_REF_NAME"
+ if [[ ${CI_BRANCH#pr-} =~ ^[0-9]*$ ]]
+ then
+ export CI_PULL_REQUEST="${CI_BRANCH#pr-}"
+ fi
else
if [ -n "${TRAVIS}" ];
then
@@ -67,11 +71,6 @@ git_checkout()
echo "${_DEST}: $(git log -1 --format='%s | %H | %cd | %aN')" )
}
-checkout_mathcomp()
-{
- git_checkout "${mathcomp_CI_BRANCH}" "${mathcomp_CI_GITURL}" "${1}"
-}
-
make()
{
# +x: add x only if defined
@@ -89,7 +88,8 @@ install_ssreflect()
{
echo 'Installing ssreflect' && echo -en 'travis_fold:start:ssr.install\\r'
- checkout_mathcomp "${mathcomp_CI_DIR}"
+ git_checkout "${mathcomp_CI_BRANCH}" "${mathcomp_CI_GITURL}" "${mathcomp_CI_DIR}"
+
( cd "${mathcomp_CI_DIR}/mathcomp" && \
sed -i.bak '/ssrtest/d' Make && \
sed -i.bak '/odd_order/d' Make && \
diff --git a/dev/ci/ci-fiat-crypto.sh b/dev/ci/ci-fiat-crypto.sh
index 845addb4c..5d96c2499 100755
--- a/dev/ci/ci-fiat-crypto.sh
+++ b/dev/ci/ci-fiat-crypto.sh
@@ -6,6 +6,8 @@ ci_dir="$(dirname "$0")"
fiat_crypto_CI_DIR="${CI_BUILD_DIR}/fiat-crypto"
git_checkout "${fiat_crypto_CI_BRANCH}" "${fiat_crypto_CI_GITURL}" "${fiat_crypto_CI_DIR}"
+
( cd "${fiat_crypto_CI_DIR}" && git submodule update --init --recursive )
-( cd "${fiat_crypto_CI_DIR}" && make lite lite-display )
+fiat_crypto_CI_TARGETS="print-nobigmem nobigmem nonautogenerated-specific nonautogenerated-specific-display"
+( cd "${fiat_crypto_CI_DIR}" && make ${fiat_crypto_CI_TARGETS} )
diff --git a/dev/ci/ci-geocoq.sh b/dev/ci/ci-geocoq.sh
index bd1d88993..920272bcf 100755
--- a/dev/ci/ci-geocoq.sh
+++ b/dev/ci/ci-geocoq.sh
@@ -7,6 +7,4 @@ GeoCoq_CI_DIR="${CI_BUILD_DIR}/GeoCoq"
git_checkout "${GeoCoq_CI_BRANCH}" "${GeoCoq_CI_GITURL}" "${GeoCoq_CI_DIR}"
-( cd "${GeoCoq_CI_DIR}" && \
- ./configure-ci.sh && \
- make )
+( cd "${GeoCoq_CI_DIR}" && ./configure.sh && make )
diff --git a/dev/ci/ci-math-comp.sh b/dev/ci/ci-math-comp.sh
index 8c6b910bb..20328baf2 100755
--- a/dev/ci/ci-math-comp.sh
+++ b/dev/ci/ci-math-comp.sh
@@ -5,11 +5,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"
-checkout_mathcomp "${mathcomp_CI_DIR}"
+git_checkout "${mathcomp_CI_BRANCH}" "${mathcomp_CI_GITURL}" "${mathcomp_CI_DIR}"
+git_checkout "${oddorder_CI_BRANCH}" "${oddorder_CI_GITURL}" "${oddorder_CI_DIR}"
-# odd_order takes too much time for travis.
-( cd "${mathcomp_CI_DIR}/mathcomp" && \
- sed -i.bak '/PFsection/d' Make && \
- sed -i.bak '/stripped_odd_order_theorem/d' Make && \
- make Makefile.coq && make -f Makefile.coq all )
+( cd "${mathcomp_CI_DIR}/mathcomp" && make && make install )
+( cd "${oddorder_CI_DIR}/" && make )
diff --git a/dev/ci/ci-unimath.sh b/dev/ci/ci-unimath.sh
index 62a949f59..aa20fe1ff 100755
--- a/dev/ci/ci-unimath.sh
+++ b/dev/ci/ci-unimath.sh
@@ -7,7 +7,4 @@ UniMath_CI_DIR="${CI_BUILD_DIR}/UniMath"
git_checkout "${UniMath_CI_BRANCH}" "${UniMath_CI_GITURL}" "${UniMath_CI_DIR}"
-( cd "${UniMath_CI_DIR}" && \
- sed -i.bak '/Folds/d' Makefile && \
- sed -i.bak '/HomologicalAlgebra/d' Makefile && \
- make BUILD_COQ=no )
+( cd "${UniMath_CI_DIR}" && make BUILD_COQ=no )
diff --git a/dev/ci/ci-vst.sh b/dev/ci/ci-vst.sh
index 79001c547..7a097eaab 100755
--- a/dev/ci/ci-vst.sh
+++ b/dev/ci/ci-vst.sh
@@ -5,9 +5,6 @@ ci_dir="$(dirname "$0")"
VST_CI_DIR="${CI_BUILD_DIR}/VST"
-# opam install -j ${NJOBS} -y menhir
git_checkout "${VST_CI_BRANCH}" "${VST_CI_GITURL}" "${VST_CI_DIR}"
-# We have to omit progs as otherwise we timeout on Travis; on Gitlab
-# we will be able to just use `make`
-( cd "${VST_CI_DIR}" && make IGNORECOQVERSION=true -o progs )
+( cd "${VST_CI_DIR}" && make IGNORECOQVERSION=true )
diff --git a/dev/ci/gitlab.bat b/dev/ci/gitlab.bat
new file mode 100644
index 000000000..70278e6d0
--- /dev/null
+++ b/dev/ci/gitlab.bat
@@ -0,0 +1,50 @@
+@ECHO OFF
+
+REM This script builds and signs the Windows packages on Gitlab
+
+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
+)
+
+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
+
+if exist %CYGROOT%\build\ rd /s /q %CYGROOT%\build
+if exist %DESTCOQ%\ rd /s /q %DESTCOQ%
+
+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 -make=N ^
+ -setup %CI_PROJECT_DIR%\%SETUP% || GOTO ErrorExit
+
+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
+
+REM DO NOT echo the signing command below, as this would leak secrets in the logs
+IF DEFINED WIN_CERTIFICATE_PATH (
+ IF DEFINED WIN_CERTIFICATE_PASSWORD (
+ ECHO Signing package
+ @signtool sign /f %WIN_CERTIFICATE_PATH% /p %WIN_CERTIFICATE_PASSWORD% dev\nsis\*.exe
+ signtool verify /pa dev\nsis\*.exe
+ )
+)
+
+GOTO :EOF
+
+:ErrorExit
+ ECHO ERROR %0 failed
+ EXIT /b 1
diff --git a/dev/ci/user-overlays/07213-ppedrot-fast-constr-match-no-context.sh b/dev/ci/user-overlays/07213-ppedrot-fast-constr-match-no-context.sh
new file mode 100644
index 000000000..517088a24
--- /dev/null
+++ b/dev/ci/user-overlays/07213-ppedrot-fast-constr-match-no-context.sh
@@ -0,0 +1,6 @@
+if [ "$CI_PULL_REQUEST" = "7213" ] || [ "$CI_BRANCH" = "fast-constr-match-no-context" ]; then
+
+ ltac2_CI_BRANCH=fast-constr-match-no-context
+ ltac2_CI_GITURL=https://github.com/ppedrot/ltac2
+
+fi
diff --git a/dev/doc/MERGING.md b/dev/doc/MERGING.md
index 84ff94c66..a466124c1 100644
--- a/dev/doc/MERGING.md
+++ b/dev/doc/MERGING.md
@@ -109,9 +109,8 @@ There are two cases to consider:
The merge script passes option `-S` to `git merge` to ensure merge commits
are signed. Consequently, it depends on the GnuPG command utility being
-installed and a GPG key being available. Here is a short tutorial to
-creating your own GPG key:
-<https://ekaia.org/blog/2009/05/10/creating-new-gpgkey/>
+installed and a GPG key being available. Here is a short documentation on
+how to use GPG, git & GitHub: https://help.github.com/articles/signing-commits-with-gpg/.
The script depends on a few other utilities. If you are a Nix user, the
simplest way of getting them is to run `nix-shell` first.
diff --git a/dev/doc/changes.md b/dev/doc/changes.md
index 6d7c0d368..fb3f751db 100644
--- a/dev/doc/changes.md
+++ b/dev/doc/changes.md
@@ -22,6 +22,11 @@ Proof engine
should indicate what the canonical form is. An important change is
the move of `Globnames.global_reference` to `Names.GlobRef.t`.
+### Unit testing
+
+ The test suite now allows writing unit tests against OCaml code in the Coq
+ code base. Those unit tests create a dependency on the OUnit test framework.
+
## Changes between Coq 8.7 and Coq 8.8
### Bug tracker
diff --git a/dev/tools/check-owners-pr.sh b/dev/tools/check-owners-pr.sh
new file mode 100755
index 000000000..d2910279b
--- /dev/null
+++ b/dev/tools/check-owners-pr.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env sh
+
+usage() {
+ { echo "usage: $0 PR [ARGS]..."
+ echo "A wrapper around check-owners.sh to check owners for a PR."
+ echo "Assumes upstream is the canonical Coq repository."
+ echo "Assumes the PR is against master."
+ echo
+ echo " PR: PR number"
+ echo " ARGS: passed through to check-owners.sh"
+ } >&2
+}
+
+case "$1" in
+ "--help"|"-h")
+ usage
+ if [ $# = 1 ]; then exit 0; else exit 1; fi;;
+ "")
+ usage
+ exit 1;;
+esac
+
+PR="$1"
+shift
+
+# this puts both refs in the FETCH_HEAD file but git rev-parse will use the first
+git fetch upstream "+refs/pull/$PR/head" master
+
+head=$(git rev-parse FETCH_HEAD)
+base=$(git merge-base upstream/master "$head")
+
+git diff --name-only -z "$base" "$head" | xargs -0 dev/tools/check-owners.sh "$@"
diff --git a/dev/tools/check-owners.sh b/dev/tools/check-owners.sh
new file mode 100755
index 000000000..1a97508ab
--- /dev/null
+++ b/dev/tools/check-owners.sh
@@ -0,0 +1,138 @@
+#!/usr/bin/env bash
+
+# Determine CODEOWNERS of the files given in argument
+# For a given commit range:
+# git diff --name-only -z COMMIT1 COMMIT2 | xargs -0 dev/tools/check-owners.sh [opts]
+
+# NB: gitignore files will be messed up if you interrupt the script.
+# You should be able to just move the .gitignore.bak files back manually.
+
+usage() {
+ { echo "usage: $0 [--show-patterns] [--owner OWNER] [FILE]..."
+ echo " --show-patterns: instead of printing file names print the matching patterns (more compact)"
+ echo " --owner: show only files/patterns owned by OWNER (use Nobody to see only non-owned files)"
+ } >&2
+}
+
+case "$1" in
+ "--help"|"-h")
+ usage
+ if [ $# = 1 ]; then exit 0; else exit 1; fi
+esac
+
+if ! [ -e .github/CODEOWNERS ]; then
+ >&2 echo "No CODEOWNERS set up or calling from wrong directory."
+ exit 1
+fi
+
+files=()
+show_patterns=false
+
+target_owner=""
+
+while [[ "$#" -gt 0 ]]; do
+ case "$1" in
+ "--show-patterns")
+ show_patterns=true
+ shift;;
+ "--owner")
+ if [[ "$#" = 1 ]]; then
+ >&2 echo "Missing argument to --owner"
+ usage
+ exit 1
+ elif [[ "$target_owner" != "" ]]; then
+ >&2 echo "Only one --owner allowed"
+ usage
+ exit 1
+ fi
+ target_owner="$2"
+ shift 2;;
+ *)
+ files+=("$@")
+ break;;
+ esac
+done
+
+# CODEOWNERS uses .gitignore patterns so we want to use git to parse it
+# The only available tool for that is git check-ignore
+# However it provides no way to use alternate .gitignore files
+# so we rename them temporarily
+
+find . -name .gitignore -print0 | while IFS= read -r -d '' f; do
+ if [ -e "$f.bak" ]; then
+ >&2 echo "$f.bak exists!"
+ exit 1
+ else
+ mv "$f" "$f.bak"
+ fi
+done
+
+# CODEOWNERS is not quite .gitignore patterns:
+# after the pattern is the owner (space separated)
+# git would interpret that as a big pattern containing spaces
+# so we create a valid .gitignore by removing all but the first field
+
+while read -r pat _; do
+ printf '%s\n' "$pat" >> .gitignore
+done < .github/CODEOWNERS
+
+# associative array [file => owner]
+declare -A owners
+
+for f in "${files[@]}"; do
+ data=$(git check-ignore --verbose --no-index "./$f")
+ code=$?
+
+ if [[ "$code" = 1 ]] || ! [[ "$data" =~ .gitignore:.* ]] ; then
+ # no match, or match from non tracked gitignore (eg global gitignore)
+ if [ "$target_owner" != "" ] && [ "$target_owner" != Nobody ] ; then
+ owner=""
+ else
+ owner="Nobody"
+ pat="$f" # no patterns for unowned files
+ fi
+ else
+ # data looks like [.gitignore:$line:$pattern $file]
+ # extract the line to look it up in CODEOWNERS
+ data=${data#'.gitignore:'}
+ line=${data%%:*}
+
+ # NB: supports multiple owners
+ # Does not support secondary owners declared in comment
+ read -r pat fowners < <(sed "${line}q;d" .github/CODEOWNERS)
+
+ owner=""
+ if [ "$target_owner" != "" ]; then
+ for o in $fowners; do # do not quote: multiple owners possible
+ if [ "$o" = "$target_owner" ]; then
+ owner="$o"
+ fi
+ done
+ else
+ owner="$fowners"
+ fi
+ fi
+
+ if [ "$owner" != "" ]; then
+ if $show_patterns; then
+ owners[$pat]="$owner"
+ else
+ owners[$f]="$owner"
+ fi
+ fi
+done
+
+for f in "${!owners[@]}"; do
+ printf '%s: %s\n' "$f" "${owners[$f]}"
+done | sort -k 2 -k 1 # group by owner
+
+# restore gitignore files
+rm .gitignore
+find . -name .gitignore.bak -print0 | while IFS= read -r -d '' f; do
+ base=${f%.bak}
+ if [ -e "$base" ]; then
+ >&2 echo "$base exists!"
+ else
+ mv "$f" "$base"
+ fi
+done
diff --git a/dev/tools/coqdev.el b/dev/tools/coqdev.el
index 62fdaec80..70a9756e5 100644
--- a/dev/tools/coqdev.el
+++ b/dev/tools/coqdev.el
@@ -23,7 +23,7 @@
;; If you load this file from a git repository, checking out an old
;; commit will make it disappear and cause errors for your Emacs
-;; startup. To ignore those errors use (require 'coqdev nil t). If you
+;; startup. To ignore those errors use (require 'coqdev nil t). If you
;; check out a malicious commit Emacs startup would allow it to run
;; arbitrary code, to avoid this you can copy coqdev.el to any
;; location and adjust the load path accordingly (of course if you run
@@ -103,5 +103,48 @@ Note that this function is executed before _Coqproject is read if it exists."
2 (3 . 4) (5 . 6)))
(add-to-list 'compilation-error-regexp-alist 'coq-backtrace))
+(defvar bug-reference-bug-regexp)
+(defvar bug-reference-url-format)
+(defun coqdev-setup-bug-reference-mode ()
+ "Setup `bug-reference-bug-regexp' and `bug-reference-url-format' for Coq.
+
+This does not enable `bug-reference-mode'."
+ (let ((dir (coqdev-default-directory)))
+ (when dir
+ (setq-local bug-reference-bug-regexp "#\\(?2:[0-9]+\\)")
+ (setq-local bug-reference-url-format "https://github.com/coq/coq/issues/%s"))))
+(add-hook 'hack-local-variables-hook #'coqdev-setup-bug-reference-mode)
+
+(defun coqdev-sphinx-quote-coq-refman-region (left right &optional offset beg end)
+ "Add LEFT and RIGHT around the BEG..END.
+Leave the point after RIGHT. BEG and END default to the bounds
+of the current region. Leave point OFFSET characters after the
+left quote (if OFFSET is nil, leave the point after the right
+quote)."
+ (unless beg
+ (if (region-active-p)
+ (setq beg (region-beginning) end (region-end))
+ (setq beg (point) end nil)))
+ (save-excursion
+ (goto-char (or end beg))
+ (insert right))
+ (save-excursion
+ (goto-char beg)
+ (insert left))
+ (if (and end (not offset)) ;; Second test handles the ::`` case
+ (goto-char (+ end (length left) (length right)))
+ (goto-char (+ beg (or offset (length left))))))
+
+(defun coqdev-sphinx-rst-coq-action ()
+ "Insert a Sphinx role template or quote the current region."
+ (interactive)
+ (pcase (read-char "Command [gntm:`]?")
+ (?g (coqdev-sphinx-quote-coq-refman-region ":g:`" "`"))
+ (?n (coqdev-sphinx-quote-coq-refman-region ":n:`" "`"))
+ (?t (coqdev-sphinx-quote-coq-refman-region ":token:`" "`"))
+ (?m (coqdev-sphinx-quote-coq-refman-region ":math:`" "`"))
+ (?: (coqdev-sphinx-quote-coq-refman-region "::`" "`" 1))
+ (?` (coqdev-sphinx-quote-coq-refman-region "``" "``"))))
+
(provide 'coqdev)
;;; coqdev ends here
diff --git a/dev/tools/pre-commit b/dev/tools/pre-commit
index b56925c37..ad2f2f93e 100755
--- a/dev/tools/pre-commit
+++ b/dev/tools/pre-commit
@@ -14,9 +14,9 @@ then
# We fix whitespace in the index and in the working tree
# separately to preserve non-added changes.
- index=$(mktemp "git-fix-ws-index.XXXXX")
- fixed_index=$(mktemp "git-fix-ws-index-fixed.XXXXX")
- tree=$(mktemp "git-fix-ws-tree.XXXXX")
+ index=$(mktemp "git-fix-ws-index.XXXXXX")
+ fixed_index=$(mktemp "git-fix-ws-index-fixed.XXXXXX")
+ tree=$(mktemp "git-fix-ws-tree.XXXXXX")
1>&2 echo "Patches are saved in '$index', '$fixed_index' and '$tree'."
1>&2 echo "If an error destroys your changes you can recover using them."
1>&2 echo "(The files are cleaned up on success.)"
diff --git a/doc/RecTutorial/RecTutorial.tex b/doc/RecTutorial/RecTutorial.tex
deleted file mode 100644
index 01369b900..000000000
--- a/doc/RecTutorial/RecTutorial.tex
+++ /dev/null
@@ -1,3690 +0,0 @@
-\documentclass[11pt]{article}
-\title{A Tutorial on [Co-]Inductive Types in Coq}
-\author{Eduardo Gim\'enez\thanks{Eduardo.Gimenez@inria.fr},
-Pierre Cast\'eran\thanks{Pierre.Casteran@labri.fr}}
-\date{May 1998 --- \today}
-
-\usepackage{multirow}
-% \usepackage{aeguill}
-% \externaldocument{RefMan-gal.v}
-% \externaldocument{RefMan-ext.v}
-% \externaldocument{RefMan-tac.v}
-% \externaldocument{RefMan-oth}
-% \externaldocument{RefMan-tus.v}
-% \externaldocument{RefMan-syn.v}
-% \externaldocument{Extraction.v}
-\input{recmacros}
-\input{coqartmacros}
-\newcommand{\refmancite}[1]{{}}
-% \newcommand{\refmancite}[1]{\cite{coqrefman}}
-% \newcommand{\refmancite}[1]{\cite[#1] {]{coqrefman}}
-
-\usepackage[utf8]{inputenc}
-\usepackage[T1]{fontenc}
-\usepackage{makeidx}
-% \usepackage{multind}
-\usepackage{alltt}
-\usepackage{verbatim}
-\usepackage{amssymb}
-\usepackage{amsmath}
-\usepackage{theorem}
-\usepackage[dvips]{epsfig}
-\usepackage{epic}
-\usepackage{eepic}
-% \usepackage{ecltree}
-\usepackage{moreverb}
-\usepackage{color}
-\usepackage{pifont}
-\usepackage{xr}
-\usepackage{url}
-
-\usepackage{alltt}
-\renewcommand{\familydefault}{ptm}
-\renewcommand{\seriesdefault}{m}
-\renewcommand{\shapedefault}{n}
-\newtheorem{exercise}{Exercise}[section]
-\makeindex
-\begin{document}
-\maketitle
-
-\begin{abstract}
-This document\footnote{The first versions of this document were entirely written by Eduardo Gimenez.
-Pierre Cast\'eran wrote the 2004 and 2006 revisions.} is an introduction to the definition and
-use of inductive and co-inductive types in the {\coq} proof environment. It explains how types like natural numbers and infinite streams are defined
-in {\coq}, and the kind of proof techniques that can be used to reason
-about them (case analysis, induction, inversion of predicates,
-co-induction, etc). Each technique is illustrated through an
-executable and self-contained {\coq} script.
-\end{abstract}
-%\RRkeyword{Proof environments, recursive types.}
-%\makeRT
-
-\addtocontents{toc}{\protect \thispagestyle{empty}}
-\pagenumbering{arabic}
-
-\cleardoublepage
-\tableofcontents
-\clearpage
-
-\section{About this document}
-
-This document is an introduction to the definition and use of
-inductive and co-inductive types in the {\coq} proof environment. It was born from the
-notes written for the course about the version V5.10 of {\coq}, given
-by Eduardo Gimenez at
-the Ecole Normale Sup\'erieure de Lyon in March 1996. This article is
-a revised and improved version of these notes for the version V8.0 of
-the system.
-
-
-We assume that the reader has some familiarity with the
-proofs-as-programs paradigm of Logic \cite{Coquand:metamathematical} and the generalities
-of the {\coq} system \cite{coqrefman}. You would take a greater advantage of
-this document if you first read the general tutorial about {\coq} and
-{\coq}'s FAQ, both available on \cite{coqsite}.
-A text book \cite{coqart}, accompanied with a lot of
-examples and exercises \cite{Booksite}, presents a detailed description
-of the {\coq} system and its underlying
-formalism: the Calculus of Inductive Construction.
-Finally, the complete description of {\coq} is given in the reference manual
-\cite{coqrefman}. Most of the tactics and commands we describe have
-several options, which we do not present exhaustively.
-If some script herein uses a non described feature, please refer to
-the Reference Manual.
-
-
-If you are familiar with other proof environments
-based on type theory and the LCF style ---like PVS, LEGO, Isabelle,
-etc--- then you will find not difficulty to guess the unexplained
-details.
-
-The better way to read this document is to start up the {\coq} system,
-type by yourself the examples and exercises, and observe the
-behavior of the system. All the examples proposed in this tutorial
-can be downloaded from the same site as the present document.
-
-
-The tutorial is organised as follows. The next section describes how
-inductive types are defined in {\coq}, and introduces some useful ones,
-like natural numbers, the empty type, the propositional equality type,
-and the logical connectives. Section \ref{CaseAnalysis} explains
-definitions by pattern-matching and their connection with the
-principle of case analysis. This principle is the most basic
-elimination rule associated with inductive or co-inductive types
- and follows a
-general scheme that we illustrate for some of the types introduced in
-Section \ref{Introduction}. Section \ref{CaseTechniques} illustrates
-the pragmatics of this principle, showing different proof techniques
-based on it. Section \ref{StructuralInduction} introduces definitions
-by structural recursion and proofs by induction.
-Section~\ref{CaseStudy} presents some elaborate techniques
-about dependent case analysis. Finally, Section
-\ref{CoInduction} is a brief introduction to co-inductive types
---i.e., types containing infinite objects-- and the principle of
-co-induction.
-
-
-Thanks to Bruno Barras, Yves Bertot, Hugo Herbelin, Jean-Fran\c{c}ois Monin
-and Michel L\'evy for their help.
-
-\subsection*{Lexical conventions}
-The \texttt{typewriter} font is used to represent text
-input by the user, while the \textit{italic} font is used to represent
-the text output by the system as answers.
-
-
-Moreover, the mathematical symbols \coqle{}, \coqdiff, \(\exists\),
-\(\forall\), \arrow{}, $\rightarrow{}$ \coqor{}, \coqand{}, and \funarrow{}
-stand for the character strings \citecoq{<=}, \citecoq{<>},
-\citecoq{exists}, \citecoq{forall}, \citecoq{->}, \citecoq{<-},
-\texttt{\char'134/}, \texttt{/\char'134}, and \citecoq{=>},
-respectively. For instance, the \coq{} statement
-%V8 A prendre
-% inclusion numero 1
-% traduction numero 1
-\begin{alltt}
-\hide{Open Scope nat_scope. Check (}forall A:Type,(exists x : A, forall (y:A), x <> y) -> 2 = 3\hide{).}
-\end{alltt}
-is written as follows in this tutorial:
-%V8 A prendre
-% inclusion numero 2
-% traduction numero 2
-\begin{alltt}
-\hide{Check (}{\prodsym}A:Type,(\exsym{}x:A, {\prodsym}y:A, x {\coqdiff} y) \arrow{} 2 = 3\hide{).}
-\end{alltt}
-
-When a fragment of \coq{} input text appears in the middle of
-regular text, we often place this fragment between double quotes
-``\dots.'' These double quotes do not belong to the \coq{} syntax.
-
-Finally, any
-string enclosed between \texttt{(*} and \texttt{*)} is a comment and
-is ignored by the \coq{} system.
-
-\section{Introducing Inductive Types}
-\label{Introduction}
-
-Inductive types are types closed with respect to their introduction
-rules. These rules explain the most basic or \textsl{canonical} ways
-of constructing an element of the type. In this sense, they
-characterize the recursive type. Different rules must be considered as
-introducing different objects. In order to fix ideas, let us introduce
-in {\coq} the most well-known example of a recursive type: the type of
-natural numbers.
-
-%V8 A prendre
-\begin{alltt}
-Inductive nat : Set :=
- | O : nat
- | S : nat\arrow{}nat.
-\end{alltt}
-
-The definition of a recursive type has two main parts. First, we
-establish what kind of recursive type we will characterize (a set, in
-this case). Second, we present the introduction rules that define the
-type ({\Z} and {\SUCC}), also called its {\sl constructors}. The constructors
-{\Z} and {\SUCC} determine all the elements of this type. In other
-words, if $n\mbox{:}\nat$, then $n$ must have been introduced either
-by the rule {\Z} or by an application of the rule {\SUCC} to a
-previously constructed natural number. In this sense, we can say
-that {\nat} is \emph{closed}. On the contrary, the type
-$\Set$ is an {\it open} type, since we do not know {\it a priori} all
-the possible ways of introducing an object of type \texttt{Set}.
-
-After entering this command, the constants {\nat}, {\Z} and {\SUCC} are
-available in the current context. We can see their types using the
-\texttt{Check} command \refmancite{Section \ref{Check}}:
-
-%V8 A prendre
-\begin{alltt}
-Check nat.
-\it{}nat : Set
-\tt{}Check O.
-\it{}O : nat
-\tt{}Check S.
-\it{}S : nat {\arrow} nat
-\end{alltt}
-
-Moreover, {\coq} adds to the context three constants named
- $\natind$, $\natrec$ and $\natrect$, which
- correspond to different principles of structural induction on
-natural numbers that {\coq} infers automatically from the definition. We
-will come back to them in Section \ref{StructuralInduction}.
-
-
-In fact, the type of natural numbers as well as several useful
-theorems about them are already defined in the basic library of {\coq},
-so there is no need to introduce them. Therefore, let us throw away
-our (re)definition of {\nat}, using the command \texttt{Reset}.
-
-%V8 A prendre
-\begin{alltt}
-Reset nat.
-Print nat.
-\it{}Inductive nat : Set := O : nat | S : nat \arrow{} nat
-For S: Argument scope is [nat_scope]
-\end{alltt}
-
-Notice that \coq{}'s \emph{interpretation scope} for natural numbers
-(called \texttt{nat\_scope})
-allows us to read and write natural numbers in decimal form (see \cite{coqrefman}). For instance, the constructor \texttt{O} can be read or written
-as the digit $0$, and the term ``~\texttt{S (S (S O))}~'' as $3$.
-
-%V8 A prendre
-\begin{alltt}
-Check O.
-\it 0 : nat.
-\tt
-Check (S (S (S O))).
-\it 3 : nat
-\end{alltt}
-
-Let us now take a look to some other
-recursive types contained in the standard library of {\coq}.
-
-\subsection{Lists}
-Lists are defined in library \citecoq{List}\footnote{Notice that in versions of
-{\coq}
-prior to 8.1, the parameter $A$ had sort \citecoq{Set} instead of \citecoq{Type};
-the constant \citecoq{list} was thus of type \citecoq{Set\arrow{} Set}.}
-
-
-\begin{alltt}
-Require Import List.
-Print list.
-\it
-Inductive list (A : Type) : Type:=
- nil : list A | cons : A {\arrow} list A {\arrow} list A
-For nil: Argument A is implicit
-For cons: Argument A is implicit
-For list: Argument scope is [type_scope]
-For nil: Argument scope is [type_scope]
-For cons: Argument scopes are [type_scope _ _]
-\end{alltt}
-
-In this definition, \citecoq{A} is a \emph{general parameter}, global
-to both constructors.
-This kind of definition allows us to build a whole family of
-inductive types, indexed over the sort \citecoq{Type}.
-This can be observed if we consider the type of identifiers
-\citecoq{list}, \citecoq{cons} and \citecoq{nil}.
-Notice the notation \citecoq{(A := \dots)} which must be used
-when {\coq}'s type inference algorithm cannot infer the implicit
-parameter \citecoq{A}.
-\begin{alltt}
-Check list.
-\it list
- : Type {\arrow} Type
-
-\tt Check (nil (A:=nat)).
-\it nil
- : list nat
-
-\tt Check (nil (A:= nat {\arrow} nat)).
-\it nil
- : list (nat {\arrow} nat)
-
-\tt Check (fun A: Type {\funarrow} (cons (A:=A))).
-\it fun A : Type {\funarrow} cons (A:=A)
- : {\prodsym} A : Type, A {\arrow} list A {\arrow} list A
-
-\tt Check (cons 3 (cons 2 nil)).
-\it 3 :: 2 :: nil
- : list nat
-
-\tt Check (nat :: bool ::nil).
-\it nat :: bool :: nil
- : list Set
-
-\tt Check ((3<=4) :: True ::nil).
-\it (3<=4) :: True :: nil
- : list Prop
-
-\tt Check (Prop::Set::nil).
-\it Prop::Set::nil
- : list Type
-\end{alltt}
-
-\subsection{Vectors.}
-\label{vectors}
-
-Like \texttt{list}, \citecoq{vector} is a polymorphic type:
-if $A$ is a type, and $n$ a natural number, ``~\citecoq{vector $A$ $n$}~''
-is the type of vectors of elements of $A$ and size $n$.
-
-
-\begin{alltt}
-Require Import Bvector.
-
-Print vector.
-\it
-Inductive vector (A : Type) : nat {\arrow} Type :=
- Vnil : vector A 0
- | Vcons : A {\arrow} {\prodsym} n : nat, vector A n {\arrow} vector A (S n)
-For vector: Argument scopes are [type_scope nat_scope]
-For Vnil: Argument scope is [type_scope]
-For Vcons: Argument scopes are [type_scope _ nat_scope _]
-\end{alltt}
-
-
-Remark the difference between the two parameters $A$ and $n$:
-The first one is a \textsl{general parameter}, global to all the
-introduction rules,while the second one is an \textsl{index}, which is
-instantiated differently in the introduction rules.
-Such types parameterized by regular
-values are called \emph{dependent types}.
-
-\begin{alltt}
-Check (Vnil nat).
-\it Vnil nat
- : vector nat 0
-
-\tt Check (fun (A:Type)(a:A){\funarrow} Vcons _ a _ (Vnil _)).
-\it fun (A : Type) (a : A) {\funarrow} Vcons A a 0 (Vnil A)
- : {\prodsym} A : Type, A {\arrow} vector A 1
-
-
-\tt Check (Vcons _ 5 _ (Vcons _ 3 _ (Vnil _))).
-\it Vcons nat 5 1 (Vcons nat 3 0 (Vnil nat))
- : vector nat 2
-\end{alltt}
-
-\subsection{The contradictory proposition.}
-Another example of an inductive type is the contradictory proposition.
-This type inhabits the universe of propositions, and has no element
-at all.
-%V8 A prendre
-\begin{alltt}
-Print False.
-\it{} Inductive False : Prop :=
-\end{alltt}
-
-\noindent Notice that no constructor is given in this definition.
-
-\subsection{The tautological proposition.}
-Similarly, the
-tautological proposition {\True} is defined as an inductive type
-with only one element {\I}:
-
-%V8 A prendre
-\begin{alltt}
-Print True.
-\it{}Inductive True : Prop := I : True
-\end{alltt}
-
-\subsection{Relations as inductive types.}
-Some relations can also be introduced in a smart way as an inductive family
-of propositions. Let us take as example the order $n \leq m$ on natural
-numbers, called \citecoq{le} in {\coq}.
- This relation is introduced through
-the following definition, quoted from the standard library\footnote{In the interpretation scope
-for Peano arithmetic:
-\citecoq{nat\_scope}, ``~\citecoq{n <= m}~'' is equivalent to
-``~\citecoq{le n m}~'' .}:
-
-
-
-
-%V8 A prendre
-\begin{alltt}
-Print le. \it
-Inductive le (n:nat) : nat\arrow{}Prop :=
-| le_n: n {\coqle} n
-| le_S: {\prodsym} m, n {\coqle} m \arrow{} n {\coqle} S m.
-\end{alltt}
-
-Notice that in this definition $n$ is a general parameter,
-while the second argument of \citecoq{le} is an index (see section
-~\ref{vectors}).
- This definition
-introduces the binary relation $n {\leq} m$ as the family of unary predicates
-``\textsl{to be greater or equal than a given $n$}'', parameterized by $n$.
-
-The introduction rules of this type can be seen as a sort of Prolog
-rules for proving that a given integer $n$ is less or equal than another one.
-In fact, an object of type $n{\leq} m$ is nothing but a proof
-built up using the constructors \textsl{le\_n} and
-\textsl{le\_S} of this type. As an example, let us construct
-a proof that zero is less or equal than three using {\coq}'s interactive
-proof mode.
-Such an object can be obtained applying three times the second
-introduction rule of \citecoq{le}, to a proof that zero is less or equal
-than itself,
-which is provided by the first constructor of \citecoq{le}:
-
-%V8 A prendre
-\begin{alltt}
-Theorem zero_leq_three: 0 {\coqle} 3.
-Proof.
-\it{} 1 subgoal
-
-============================
- 0 {\coqle} 3
-
-\tt{}Proof.
- constructor 2.
-
-\it{} 1 subgoal
-============================
- 0 {\coqle} 2
-
-\tt{} constructor 2.
-\it{} 1 subgoal
-============================
- 0 {\coqle} 1
-
-\tt{} constructor 2
-\it{} 1 subgoal
-============================
- 0 {\coqle} 0
-
-\tt{} constructor 1.
-
-\it{}Proof completed
-\tt{}Qed.
-\end{alltt}
-
-\noindent When
-the current goal is an inductive type, the tactic
-``~\citecoq{constructor $i$}~'' \refmancite{Section \ref{constructor}} applies the $i$-th constructor in the
-definition of the type. We can take a look at the proof constructed
-using the command \texttt{Print}:
-
-%V8 A prendre
-\begin{alltt}
-Print Print zero_leq_three.
-\it{}zero_leq_three =
-zero_leq_three = le_S 0 2 (le_S 0 1 (le_S 0 0 (le_n 0)))
- : 0 {\coqle} 3
-\end{alltt}
-
-When the parameter $i$ is not supplied, the tactic \texttt{constructor}
-tries to apply ``~\texttt{constructor $1$}~'', ``~\texttt{constructor $2$}~'',\dots,
-``~\texttt{constructor $n$}~'' where $n$ is the number of constructors
-of the inductive type (2 in our example) of the conclusion of the goal.
-Our little proof can thus be obtained iterating the tactic
-\texttt{constructor} until it fails:
-
-%V8 A prendre
-\begin{alltt}
-Lemma zero_leq_three': 0 {\coqle} 3.
- repeat constructor.
-Qed.
-\end{alltt}
-
-Notice that the strict order on \texttt{nat}, called \citecoq{lt}
-is not inductively defined: the proposition $n<p$ (notation for \citecoq{lt $n$ $p$})
-is reducible to \citecoq{(S $n$) $\leq$ p}.
-
-\begin{alltt}
-Print lt.
-\it
-lt = fun n m : nat {\funarrow} S n {\coqle} m
- : nat {\arrow} nat {\arrow} Prop
-\tt
-Lemma zero_lt_three : 0 < 3.
-Proof.
- repeat constructor.
-Qed.
-
-Print zero_lt_three.
-\it zero_lt_three = le_S 1 2 (le_S 1 1 (le_n 1))
- : 0 < 3
-\end{alltt}
-
-
-
-\subsection{About general parameters (\coq{} version $\geq$ 8.1)}
-\label{parameterstuff}
-
-Since version $8.1$, it is possible to write more compact inductive definitions
-than in earlier versions.
-
-Consider the following alternative definition of the relation $\leq$ on
-type \citecoq{nat}:
-
-\begin{alltt}
-Inductive le'(n:nat):nat -> Prop :=
- | le'_n : le' n n
- | le'_S : forall p, le' (S n) p -> le' n p.
-
-Hint Constructors le'.
-\end{alltt}
-
-We notice that the type of the second constructor of \citecoq{le'}
-has an argument whose type is \citecoq{le' (S n) p}.
-This constrasts with earlier versions
-of {\coq}, in which a general parameter $a$ of an inductive
-type $I$ had to appear only in applications of the form $I\,\dots\,a$.
-
-Since version $8.1$, if $a$ is a general parameter of an inductive
-type $I$, the type of an argument of a constructor of $I$ may be
-of the form $I\,\dots\,t_a$ , where $t_a$ is any term.
-Notice that the final type of the constructors must be of the form
-$I\,\dots\,a$, since these constructors describe how to form
-inhabitants of type $I\,\dots\,a$ (this is the role of parameter $a$).
-
-Another example of this new feature is {\coq}'s definition of accessibility
-(see Section~\ref{WellFoundedRecursion}), which has a general parameter
-$x$; the constructor for the predicate
-``$x$ is accessible'' takes an argument of type ``$y$ is accessible''.
-
-
-
-In earlier versions of {\coq}, a relation like \citecoq{le'} would have to be
-defined without $n$ being a general parameter.
-
-\begin{alltt}
-Reset le'.
-
-Inductive le': nat-> nat -> Prop :=
- | le'_n : forall n, le' n n
- | le'_S : forall n p, le' (S n) p -> le' n p.
-\end{alltt}
-
-
-
-
-\subsection{The propositional equality type.} \label{equality}
-In {\coq}, the propositional equality between two inhabitants $a$ and
-$b$ of
-the same type $A$ ,
-noted $a=b$, is introduced as a family of recursive predicates
-``~\textsl{to be equal to $a$}~'', parameterised by both $a$ and its type
-$A$. This family of types has only one introduction rule, which
-corresponds to reflexivity.
-Notice that the syntax ``\citecoq{$a$ = $b$}~'' is an abbreviation
-for ``\citecoq{eq $a$ $b$}~'', and that the parameter $A$ is \emph{implicit},
-as it can be infered from $a$.
-%V8 A prendre
-\begin{alltt}
-Print eq.
-\it{} Inductive eq (A : Type) (x : A) : A \arrow{} Prop :=
- eq_refl : x = x
-For eq: Argument A is implicit
-For eq_refl: Argument A is implicit
-For eq: Argument scopes are [type_scope _ _]
-For eq_refl: Argument scopes are [type_scope _]
-\end{alltt}
-
-Notice also that the first parameter $A$ of \texttt{eq} has type
-\texttt{Type}. The type system of {\coq} allows us to consider equality between
-various kinds of terms: elements of a set, proofs, propositions,
-types, and so on.
-Look at \cite{coqrefman, coqart} to get more details on {\coq}'s type
-system, as well as implicit arguments and argument scopes.
-
-
-\begin{alltt}
-Lemma eq_3_3 : 2 + 1 = 3.
-Proof.
- reflexivity.
-Qed.
-
-Lemma eq_proof_proof : eq_refl (2*6) = eq_refl (3*4).
-Proof.
- reflexivity.
-Qed.
-
-Print eq_proof_proof.
-\it eq_proof_proof =
-eq_refl (eq_refl (3 * 4))
- : eq_refl (2 * 6) = eq_refl (3 * 4)
-\tt
-
-Lemma eq_lt_le : ( 2 < 4) = (3 {\coqle} 4).
-Proof.
- reflexivity.
-Qed.
-
-Lemma eq_nat_nat : nat = nat.
-Proof.
- reflexivity.
-Qed.
-
-Lemma eq_Set_Set : Set = Set.
-Proof.
- reflexivity.
-Qed.
-\end{alltt}
-
-\subsection{Logical connectives.} \label{LogicalConnectives}
-The conjunction and disjunction of two propositions are also examples
-of recursive types:
-
-\begin{alltt}
-Inductive or (A B : Prop) : Prop :=
- or_introl : A \arrow{} A {\coqor} B | or_intror : B \arrow{} A {\coqor} B
-
-Inductive and (A B : Prop) : Prop :=
- conj : A \arrow{} B \arrow{} A {\coqand} B
-
-\end{alltt}
-
-The propositions $A$ and $B$ are general parameters of these
-connectives. Choosing different universes for
-$A$ and $B$ and for the inductive type itself gives rise to different
-type constructors. For example, the type \textsl{sumbool} is a
-disjunction but with computational contents.
-
-\begin{alltt}
-Inductive sumbool (A B : Prop) : Set :=
- left : A \arrow{} \{A\} + \{B\} | right : B \arrow{} \{A\} + \{B\}
-\end{alltt}
-
-
-
-This type --noted \texttt{\{$A$\}+\{$B$\}} in {\coq}-- can be used in {\coq}
-programs as a sort of boolean type, to check whether it is $A$ or $B$
-that is true. The values ``~\citecoq{left $p$}~'' and
-``~\citecoq{right $q$}~'' replace the boolean values \textsl{true} and
-\textsl{false}, respectively. The advantage of this type over
-\textsl{bool} is that it makes available the proofs $p$ of $A$ or $q$
-of $B$, which could be necessary to construct a verification proof
-about the program.
-For instance, let us consider the certified program \citecoq{le\_lt\_dec}
-of the Standard Library.
-
-\begin{alltt}
-Require Import Compare_dec.
-Check le_lt_dec.
-\it
-le_lt_dec
- : {\prodsym} n m : nat, \{n {\coqle} m\} + \{m < n\}
-
-\end{alltt}
-
-We use \citecoq{le\_lt\_dec} to build a function for computing
-the max of two natural numbers:
-
-\begin{alltt}
-Definition max (n p :nat) := match le_lt_dec n p with
- | left _ {\funarrow} p
- | right _ {\funarrow} n
- end.
-\end{alltt}
-
-In the following proof, the case analysis on the term
-``~\citecoq{le\_lt\_dec n p}~'' gives us an access to proofs
-of $n\leq p$ in the first case, $p<n$ in the other.
-
-\begin{alltt}
-Theorem le_max : {\prodsym} n p, n {\coqle} p {\arrow} max n p = p.
-Proof.
- intros n p ; unfold max ; case (le_lt_dec n p); simpl.
-\it
-2 subgoals
-
- n : nat
- p : nat
- ============================
- n {\coqle} p {\arrow} n {\coqle} p {\arrow} p = p
-
-subgoal 2 is:
- p < n {\arrow} n {\coqle} p {\arrow} n = p
-\tt
- trivial.
- intros; absurd (p < p); eauto with arith.
-Qed.
-\end{alltt}
-
-
- Once the program verified, the proofs are
-erased by the extraction procedure:
-
-\begin{alltt}
-Extraction max.
-\it
-(** val max : nat {\arrow} nat {\arrow} nat **)
-
-let max n p =
- match le_lt_dec n p with
- | Left {\arrow} p
- | Right {\arrow} n
-\end{alltt}
-
-Another example of use of \citecoq{sumbool} is given in Section
-\ref{WellFoundedRecursion}: the theorem \citecoq{eq\_nat\_dec} of
-library \citecoq{Coq.Arith.Peano\_dec} is used in an euclidean division
-algorithm.
-
-\subsection{The existential quantifier.}\label{ex-def}
-The existential quantifier is yet another example of a logical
-connective introduced as an inductive type.
-
-\begin{alltt}
-Inductive ex (A : Type) (P : A \arrow{} Prop) : Prop :=
- ex_intro : {\prodsym} x : A, P x \arrow{} ex P
-\end{alltt}
-
-Notice that {\coq} uses the abreviation ``~\citecoq{\exsym\,$x$:$A$, $B$}~''
-for \linebreak ``~\citecoq{ex (fun $x$:$A$ \funarrow{} $B$)}~''.
-
-
-\noindent The former quantifier inhabits the universe of propositions.
-As for the conjunction and disjunction connectives, there is also another
-version of existential quantification inhabiting the universes $\Type_i$,
-which is written \texttt{sig $P$}. The syntax
-``~\citecoq{\{$x$:$A$ | $B$\}}~'' is an abreviation for ``~\citecoq{sig (fun $x$:$A$ {\funarrow} $B$)}~''.
-
-
-
-%\paragraph{The logical connectives.} Conjuction and disjuction are
-%also introduced as recursive types:
-%\begin{alltt}
-%Print or.
-%\end{alltt}
-%begin{alltt}
-%Print and.
-%\end{alltt}
-
-
-\subsection{Mutually Dependent Definitions}
-\label{MutuallyDependent}
-
-Mutually dependent definitions of recursive types are also allowed in
-{\coq}. A typical example of these kind of declaration is the
-introduction of the trees of unbounded (but finite) width:
-\label{Forest}
-\begin{alltt}
-Inductive tree(A:Type) : Type :=
- node : A {\arrow} forest A \arrow{} tree A
-with forest (A: Set) : Type :=
- nochild : forest A |
- addchild : tree A \arrow{} forest A \arrow{} forest A.
-\end{alltt}
-\noindent Yet another example of mutually dependent types are the
-predicates \texttt{even} and \texttt{odd} on natural numbers:
-\label{Even}
-\begin{alltt}
-Inductive
- even : nat\arrow{}Prop :=
- evenO : even O |
- evenS : {\prodsym} n, odd n \arrow{} even (S n)
-with
- odd : nat\arrow{}Prop :=
- oddS : {\prodsym} n, even n \arrow{} odd (S n).
-\end{alltt}
-
-\begin{alltt}
-Lemma odd_49 : odd (7 * 7).
- simpl; repeat constructor.
-Qed.
-\end{alltt}
-
-
-
-\section{Case Analysis and Pattern-matching}
-\label{CaseAnalysis}
-\subsection{Non-dependent Case Analysis}
-An \textsl{elimination rule} for the type $A$ is some way to use an
-object $a:A$ in order to define an object in some type $B$.
-A natural elimination rule for an inductive type is \emph{case analysis}.
-
-
-For instance, any value of type {\nat} is built using either \texttt{O} or \texttt{S}.
-Thus, a systematic way of building a value of type $B$ from any
-value of type {\nat} is to associate to \texttt{O} a constant $t_O:B$ and
-to every term of the form ``~\texttt{S $p$}~'' a term $t_S:B$. The following
-construction has type $B$:
-\begin{alltt}
-match \(n\) return \(B\) with O \funarrow \(t\sb{O}\) | S p \funarrow \(t\sb{S}\) end
-\end{alltt}
-
-
-In most of the cases, {\coq} is able to infer the type $B$ of the object
-defined, so the ``\texttt{return $B$}'' part can be omitted.
-
-The computing rules associated with this construct are the expected ones
-(the notation $t_S\{q/\texttt{p}\}$ stands for the substitution of $p$ by
-$q$ in $t_S$ :)
-
-\begin{eqnarray*}
-\texttt{match $O$ return $b$ with O {\funarrow} $t_O$ | S p {\funarrow} $t_S$ end} &\Longrightarrow& t_O\\
-\texttt{match $S\;q$ return $b$ with O {\funarrow} $t_O$ | S p {\funarrow} $t_S$ end} &\Longrightarrow& t_S\{q/\texttt{p}\}
-\end{eqnarray*}
-
-
-\subsubsection{Example: the predecessor function.}\label{firstpred}
-An example of a definition by case analysis is the function which
-computes the predecessor of any given natural number:
-\begin{alltt}
-Definition pred (n:nat) := match n with
- | O {\funarrow} O
- | S m {\funarrow} m
- end.
-
-Eval simpl in pred 56.
-\it{} = 55
- : nat
-\tt
-Eval simpl in pred 0.
-\it{} = 0
- : nat
-
-\tt{}Eval simpl in fun p {\funarrow} pred (S p).
-\it{} = fun p : nat {\funarrow} p
- : nat {\arrow} nat
-\end{alltt}
-
-As in functional programming, tuples and wild-cards can be used in
-patterns \refmancite{Section \ref{ExtensionsOfCases}}. Such
-definitions are automatically compiled by {\coq} into an expression which
-may contain several nested case expressions. For example, the
-exclusive \emph{or} on booleans can be defined as follows:
-\begin{alltt}
-Definition xorb (b1 b2:bool) :=
- match b1, b2 with
- | false, true {\funarrow} true
- | true, false {\funarrow} true
- | _ , _ {\funarrow} false
- end.
-\end{alltt}
-
-This kind of definition is compiled in {\coq} as follows\footnote{{\coq} uses
-the conditional ``~\citecoq{if $b$ then $a$ else $b$}~'' as an abreviation to
-``~\citecoq{match $b$ with true \funarrow{} $a$ | false \funarrow{} $b$ end}~''.}:
-
-\begin{alltt}
-Print xorb.
-xorb =
-fun b1 b2 : bool {\funarrow}
-if b1 then if b2 then false else true
- else if b2 then true else false
- : bool {\arrow} bool {\arrow} bool
-\end{alltt}
-
-\subsection{Dependent Case Analysis}
-\label{DependentCase}
-
-For a pattern matching construct of the form
-``~\citecoq{match n with \dots end}~'' a more general typing rule
-is obtained considering that the type of the whole expression
-may also depend on \texttt{n}.
- For instance, let us consider some function
-$Q:\texttt{nat}\arrow{}\texttt{Type}$, and $n:\citecoq{nat}$.
-In order to build a term of type $Q\;n$, we can associate
-to the constructor \texttt{O} some term $t_O: Q\;\texttt{O}$ and to
-the pattern ``~\texttt{S p}~'' some term $t_S : Q\;(S\;p)$.
-Notice that the terms $t_O$ and $t_S$ do not have the same type.
-
-The syntax of the \emph{dependent case analysis} and its
-associated typing rule make precise how the resulting
-type depends on the argument of the pattern matching, and
-which constraint holds on the branches of the pattern matching:
-
-\label{Prod-sup-rule}
-\[
-\begin{array}[t]{l}
-Q: \texttt{nat}{\arrow}\texttt{Type}\quad{t_O}:{{Q\;\texttt{O}}} \quad
-\smalljuge{p:\texttt{nat}}{t_p}{{Q\;(\texttt{S}\;p)}} \quad n:\texttt{nat} \\
-\hline
-{\texttt{match \(n\) as \(n\sb{0}\) return \(Q\;n\sb{0}\) with | O \funarrow \(t\sb{O}\) | S p \funarrow \(t\sb{S}\) end}}:{{Q\;n}}
-\end{array}
-\]
-
-
-The interest of this rule of \textsl{dependent} pattern-matching is
-that it can also be read as the following logical principle (when $Q$ has type \citecoq{nat\arrow{}Prop}
-by \texttt{Prop} in the type of $Q$): in order to prove
-that a property $Q$ holds for all $n$, it is sufficient to prove that
-$Q$ holds for {\Z} and that for all $p:\nat$, $Q$ holds for
-$(\SUCC\;p)$. The former, non-dependent version of case analysis can
-be obtained from this latter rule just taking $Q$ as a constant
-function on $n$.
-
-Notice that destructuring $n$ into \citecoq{O} or ``~\citecoq{S p}~''
- doesn't
-make appear in the goal the equalities ``~$n=\citecoq{O}$~''
- and ``~$n=\citecoq{S p}$~''.
-They are ``internalized'' in the rules above (see section~\ref{inversion}.)
-
-\subsubsection{Example: strong specification of the predecessor function.}
-
-In Section~\ref{firstpred}, the predecessor function was defined directly
-as a function from \texttt{nat} to \texttt{nat}. It remains to prove
-that this function has some desired properties. Another way to proceed
-is to, first introduce a specification of what is the predecessor of a
-natural number, under the form of a {\coq} type, then build an inhabitant
-of this type: in other words, a realization of this specification. This way, the correctness
-of this realization is ensured by {\coq}'s type system.
-
-A reasonable specification for $\pred$ is to say that for all $n$
-there exists another $m$ such that either $m=n=0$, or $(\SUCC\;m)$
-is equal to $n$. The function $\pred$ should be just the way to
-compute such an $m$.
-
-\begin{alltt}
-Definition pred_spec (n:nat) :=
- \{m:nat | n=0{\coqand} m=0 {\coqor} n = S m\}.
-
-Definition predecessor : {\prodsym} n:nat, pred_spec n.
- intro n; case n.
-\it{}
- n : nat
- ============================
- pred_spec 0
-
-\tt{} unfold pred_spec;exists 0;auto.
-\it{}
- =========================================
- {\prodsym} n0 : nat, pred_spec (S n0)
-\tt{}
- unfold pred_spec; intro n0; exists n0; auto.
-Defined.
-\end{alltt}
-
-If we print the term built by {\coq}, its dependent pattern-matching structure can be observed:
-
-\begin{alltt}
-predecessor = fun n : nat {\funarrow}
-\textbf{match n as n0 return (pred_spec n0) with}
-\textbf{| O {\funarrow}}
- exist (fun m : nat {\funarrow} 0 = 0 {\coqand} m = 0 {\coqor} 0 = S m) 0
- (or_introl (0 = 1)
- (conj (eq_refl 0) (eq_refl 0)))
-\textbf{| S n0 {\funarrow}}
- exist (fun m : nat {\funarrow} S n0 = 0 {\coqand} m = 0 {\coqor} S n0 = S m) n0
- (or_intror (S n0 = 0 {\coqand} n0 = 0) (eq_refl (S n0)))
-\textbf{end} : {\prodsym} n : nat, \textbf{pred_spec n}
-\end{alltt}
-
-
-Notice that there are many variants to the pattern ``~\texttt{intros \dots; case \dots}~''. Look at for tactics
-``~\texttt{destruct}~'', ``~\texttt{intro \emph{pattern}}~'', etc. in
-the reference manual and/or the book.
-
-\noindent The command \texttt{Extraction} \refmancite{Section
-\ref{ExtractionIdent}} can be used to see the computational
-contents associated to the \emph{certified} function \texttt{predecessor}:
-\begin{alltt}
-Extraction predecessor.
-\it
-(** val predecessor : nat {\arrow} pred_spec **)
-
-let predecessor = function
- | O {\arrow} O
- | S n0 {\arrow} n0
-\end{alltt}
-
-
-\begin{exercise} \label{expand}
-Prove the following theorem:
-\begin{alltt}
-Theorem nat_expand : {\prodsym} n:nat,
- n = match n with
- | 0 {\funarrow} 0
- | S p {\funarrow} S p
- end.
-\end{alltt}
-\end{exercise}
-
-\subsection{Some Examples of Case Analysis}
-\label{CaseScheme}
-The reader will find in the Reference manual all details about
-typing case analysis (chapter 4: Calculus of Inductive Constructions,
-and chapter 15: Extended Pattern-Matching).
-
-The following commented examples will show the different situations to consider.
-
-
-%\subsubsection{General Scheme}
-
-%Case analysis is then the most basic elimination rule that {\coq}
-%provides for inductive types. This rule follows a general schema,
-%valid for any inductive type $I$. First, if $I$ has type
-%``~$\forall\,(z_1:A_1)\ldots(z_r:A_r),S$~'', with $S$ either $\Set$, $\Prop$ or
-%$\Type$, then a case expression on $p$ of type ``~$R\;a_1\ldots a_r$~''
-% inhabits ``~$Q\;a_1\ldots a_r\;p$~''. The types of the branches of the case expression
-%are obtained from the definition of the type in this way: if the type
-%of the $i$-th constructor $c_i$ of $R$ is
-%``~$\forall\, (x_1:T_1)\ldots
-%(x_n:T_n),(R\;q_1\ldots q_r)$~'', then the $i-th$ branch must have the
-%form ``~$c_i\; x_1\; \ldots \;x_n\; \funarrow{}\; t_i$~'' where
-%$$(x_1:T_1),\ldots, (x_n:T_n) \vdash t_i : Q\;q_1\ldots q_r)$$
-% for non-dependent case
-%analysis, and $$(x_1:T_1)\ldots (x_n:T_n)\vdash t_i :Q\;q_1\ldots
-%q_r\;({c}_i\;x_1\;\ldots x_n)$$ for dependent one. In the
-%following section, we illustrate this general scheme for different
-%recursive types.
-%%\textbf{A vérifier}
-
-\subsubsection{The Empty Type}
-
-In a definition by case analysis, there is one branch for each
-introduction rule of the type. Hence, in a definition by case analysis
-on $p:\False$ there are no cases to be considered. In other words, the
-rule of (non-dependent) case analysis for the type $\False$ is
-(for $s$ in \texttt{Prop}, \texttt{Set} or \texttt{Type}):
-
-\begin{center}
-\snregla {\JM{Q}{s}\;\;\;\;\;
- \JM{p}{\False}}
- {\JM{\texttt{match $p$ return $Q$ with end}}{Q}}
-\end{center}
-
-As a corollary, if we could construct an object in $\False$, then it
-could be possible to define an object in any type. The tactic
-\texttt{contradiction} \refmancite{Section \ref{Contradiction}}
-corresponds to the application of the elimination rule above. It
-searches in the context for an absurd hypothesis (this is, a
-hypothesis whose type is $\False$) and then proves the goal by a case
-analysis of it.
-
-\begin{alltt}
-Theorem fromFalse : False \arrow{} 0=1.
-Proof.
- intro H.
- contradiction.
-Qed.
-\end{alltt}
-
-
-In {\coq} the negation is defined as follows :
-
-\begin{alltt}
-Definition not (P:Prop) := P {\arrow} False
-\end{alltt}
-
-The proposition ``~\citecoq{not $A$}~'' is also written ``~$\neg A$~''.
-
-If $A$ and $B$ are propositions, $a$ is a proof of $A$ and
-$H$ is a proof of $\neg A$,
-the term ``~\citecoq{match $H\;a$ return $B$ with end}~'' is a proof term of
-$B$.
-Thus, if your goal is $B$ and you have some hypothesis $H:\neg A$,
-the tactic ``~\citecoq{case $H$}~'' generates a new subgoal with
-statement $A$, as shown by the following example\footnote{Notice that
-$a\coqdiff b$ is just an abreviation for ``~\coqnot a= b~''}.
-
-\begin{alltt}
-Fact Nosense : 0 {\coqdiff} 0 {\arrow} 2 = 3.
-Proof.
- intro H; case H.
-\it
-===========================
- 0 = 0
-\tt
- reflexivity.
-Qed.
-\end{alltt}
-
-The tactic ``~\texttt{absurd $A$}~'' (where $A$ is any proposition),
-is based on the same principle, but
-generates two subgoals: $A$ and $\neg A$, for solving $B$.
-
-\subsubsection{The Equality Type}
-
-Let $A:\Type$, $a$, $b$ of type $A$, and $\pi$ a proof of
-$a=b$. Non dependent case analysis of $\pi$ allows us to
-associate to any proof of ``~$Q\;a$~'' a proof of ``~$Q\;b$~'',
-where $Q:A\arrow{} s$ (where $s\in\{\Prop, \Set, \Type\}$).
-The following term is a proof of ``~$Q\;a\, \arrow{}\, Q\;b$~''.
-
-\begin{alltt}
-fun H : Q a {\funarrow}
- match \(\pi\) in (_ = y) return Q y with
- eq_refl {\funarrow} H
- end
-\end{alltt}
-Notice the header of the \texttt{match} construct.
-It expresses how the resulting type ``~\citecoq{Q y}~'' depends on
-the \emph{type} of \texttt{p}.
-Notice also that in the pattern introduced by the keyword \texttt{in},
-the parameter \texttt{a} in the type ``~\texttt{a = y}~'' must be
-implicit, and replaced by a wildcard '\texttt{\_}'.
-
-
-Therefore, case analysis on a proof of the equality $a=b$
-amounts to replacing all the occurrences of the term $b$ with the term
-$a$ in the goal to be proven. Let us illustrate this through an
-example: the transitivity property of this equality.
-\begin{alltt}
-Theorem trans : {\prodsym} n m p:nat, n=m \arrow{} m=p \arrow{} n=p.
-Proof.
- intros n m p eqnm.
-\it{}
- n : nat
- m : nat
- p : nat
- eqnm : n = m
- ============================
- m = p {\arrow} n = p
-\tt{} case eqnm.
-\it{}
- n : nat
- m : nat
- p : nat
- eqnm : n = m
- ============================
- n = p {\arrow} n = p
-\tt{} trivial.
-Qed.
-\end{alltt}
-
-%\noindent The case analysis on the hypothesis $H:n=m$ yields the
-%tautological subgoal $n=p\rightarrow n=p$, that is directly proven by
-%the tactic \texttt{Trivial}.
-
-\begin{exercise}
-Prove the symmetry property of equality.
-\end{exercise}
-
-Instead of using \texttt{case}, we can use the tactic
-\texttt{rewrite} \refmancite{Section \ref{Rewrite}}. If $H$ is a proof
-of $a=b$, then
-``~\citecoq{rewrite $H$}~''
- performs a case analysis on a proof of $b=a$, obtained by applying a
-symmetry theorem to $H$. This application of symmetry allows us to rewrite
-the equality from left to right, which looks more natural. An optional
-parameter (either \texttt{\arrow{}} or \texttt{$\leftarrow$}) can be used to precise
-in which sense the equality must be rewritten. By default,
-``~\texttt{rewrite} $H$~'' corresponds to ``~\texttt{rewrite \arrow{}} $H$~''
-\begin{alltt}
-Lemma Rw : {\prodsym} x y: nat, y = y * x {\arrow} y * x * x = y.
- intros x y e; do 2 rewrite <- e.
-\it
-1 subgoal
-
- x : nat
- y : nat
- e : y = y * x
- ============================
- y = y
-\tt
- reflexivity.
-Qed.
-\end{alltt}
-
-Notice that, if $H:a=b$, then the tactic ``~\texttt{rewrite $H$}~''
- replaces \textsl{all} the
-occurrences of $a$ by $b$. However, in certain situations we could be
-interested in rewriting some of the occurrences, but not all of them.
-This can be done using the tactic \texttt{pattern} \refmancite{Section
-\ref{Pattern}}. Let us consider yet another example to
-illustrate this.
-
-Let us start with some simple theorems of arithmetic; two of them
-are already proven in the Standard Library, the last is left as an exercise.
-
-\begin{alltt}
-\it
-mult_1_l
- : {\prodsym} n : nat, 1 * n = n
-
-mult_plus_distr_r
- : {\prodsym} n m p : nat, (n + m) * p = n * p + m * p
-
-mult_distr_S : {\prodsym} n p : nat, n * p + p = (S n)* p.
-\end{alltt}
-
-Let us now prove a simple result:
-
-\begin{alltt}
-Lemma four_n : {\prodsym} n:nat, n+n+n+n = 4*n.
-Proof.
- intro n;rewrite <- (mult_1_l n).
-\it
- n : nat
- ============================
- 1 * n + 1 * n + 1 * n + 1 * n = 4 * (1 * n)
-\end{alltt}
-
-We can see that the \texttt{rewrite} tactic call replaced \emph{all}
-the occurrences of \texttt{n} by the term ``~\citecoq{1 * n}~''.
-If we want to do the rewriting ony on the leftmost occurrence of
-\texttt{n}, we can mark this occurrence using the \texttt{pattern}
-tactic:
-
-
-\begin{alltt}
- Undo.
- intro n; pattern n at 1.
- \it
- n : nat
- ============================
- (fun n0 : nat {\funarrow} n0 + n + n + n = 4 * n) n
-\end{alltt}
-Applying the tactic ``~\citecoq{pattern n at 1}~'' allowed us
-to explicitly abstract the first occurrence of \texttt{n} from the
-goal, putting this goal under the form ``~\citecoq{$Q$ n}~'',
-thus pointing to \texttt{rewrite} the particular predicate on $n$
-that we search to prove.
-
-
-\begin{alltt}
- rewrite <- mult_1_l.
-\it
-1 subgoal
-
- n : nat
- ============================
- 1 * n + n + n + n = 4 * n
-\tt
- repeat rewrite mult_distr_S.
-\it
- n : nat
- ============================
- 4 * n = 4 * n
-\tt
- trivial.
-Qed.
-\end{alltt}
-
-\subsubsection{The Predicate $n {\leq} m$}
-
-
-The last but one instance of the elimination schema that we will illustrate is
-case analysis for the predicate $n {\leq} m$:
-
-Let $n$ and $p$ be terms of type \citecoq{nat}, and $Q$ a predicate
-of type $\citecoq{nat}\arrow{}\Prop$.
-If $H$ is a proof of ``~\texttt{n {\coqle} p}~'',
-$H_0$ a proof of ``~\texttt{$Q$ n}~'' and
-$H_S$ a proof of the statement ``~\citecoq{{\prodsym}m:nat, n {\coqle} m {\arrow} Q (S m)}~'',
-then the term
-\begin{alltt}
-match H in (_ {\coqle} q) return (Q q) with
- | le_n {\funarrow} H0
- | le_S m Hm {\funarrow} HS m Hm
-end
-\end{alltt}
- is a proof term of ``~\citecoq{$Q$ $p$}~''.
-
-
-The two patterns of this \texttt{match} construct describe
-all possible forms of proofs of ``~\citecoq{n {\coqle} m}~'' (notice
-again that the general parameter \texttt{n} is implicit in
- the ``~\texttt{in \dots}~''
-clause and is absent from the match patterns.
-
-
-Notice that the choice of introducing some of the arguments of the
-predicate as being general parameters in its definition has
-consequences on the rule of case analysis that is derived. In
-particular, the type $Q$ of the object defined by the case expression
-only depends on the indexes of the predicate, and not on the general
-parameters. In the definition of the predicate $\leq$, the first
-argument of this relation is a general parameter of the
-definition. Hence, the predicate $Q$ to be proven only depends on the
-second argument of the relation. In other words, the integer $n$ is
-also a general parameter of the rule of case analysis.
-
-An example of an application of this rule is the following theorem,
-showing that any integer greater or equal than $1$ is the successor of another
-natural number:
-
-\begin{alltt}
-Lemma predecessor_of_positive :
- {\prodsym} n, 1 {\coqle} n {\arrow} {\exsym} p:nat, n = S p.
-Proof.
- intros n H;case H.
-\it
- n : nat
- H : 1 {\coqle} n
- ============================
- {\exsym} p : nat, 1 = S p
-\tt
- exists 0; trivial.
-\it
-
- n : nat
- H : 1 {\coqle} n
- ============================
- {\prodsym} m : nat, 0 {\coqle} m {\arrow} {\exsym} p : nat, S m = S p
-\tt
- intros m _ .
- exists m.
- trivial.
-Qed.
-\end{alltt}
-
-
-\subsubsection{Vectors}
-
-The \texttt{vector} polymorphic and dependent family of types will
-give an idea of the most general scheme of pattern-matching.
-
-For instance, let us define a function for computing the tail of
-any vector. Notice that we shall build a \emph{total} function,
-by considering that the tail of an empty vector is this vector itself.
-In that sense, it will be slightly different from the \texttt{Vtail}
-function of the Standard Library, which is defined only for vectors
-of type ``~\citecoq{vector $A$ (S $n$)}~''.
-
-The header of the function we want to build is the following:
-
-\begin{verbatim}
-Definition Vtail_total
- (A : Type) (n : nat) (v : vector A n) : vector A (pred n):=
-\end{verbatim}
-
-Since the branches will not have the same type
-(depending on the parameter \texttt{n}),
-the body of this function is a dependent pattern matching on
-\citecoq{v}.
-So we will have :
-\begin{verbatim}
-match v in (vector _ n0) return (vector A (pred n0)) with
-\end{verbatim}
-
-The first branch deals with the constructor \texttt{Vnil} and must
-return a value in ``~\citecoq{vector A (pred 0)}~'', convertible
-to ``~\citecoq{vector A 0}~''. So, we propose:
-\begin{alltt}
-| Vnil {\funarrow} Vnil A
-\end{alltt}
-
-The second branch considers a vector in ``~\citecoq{vector A (S n0)}~''
-of the form
-``~\citecoq{Vcons A n0 v0}~'', with ``~\citecoq{v0:vector A n0}~'',
-and must return a value of type ``~\citecoq{vector A (pred (S n0))}~'',
-which is convertible to ``~\citecoq{vector A n0}~''.
-This second branch is thus :
-\begin{alltt}
-| Vcons _ n0 v0 {\funarrow} v0
-\end{alltt}
-
-Here is the full definition:
-
-\begin{alltt}
-Definition Vtail_total
- (A : Type) (n : nat) (v : vector A n) : vector A (pred n):=
-match v in (vector _ n0) return (vector A (pred n0)) with
-| Vnil {\funarrow} Vnil A
-| Vcons _ n0 v0 {\funarrow} v0
-end.
-\end{alltt}
-
-
-\subsection{Case Analysis and Logical Paradoxes}
-
-In the previous section we have illustrated the general scheme for
-generating the rule of case analysis associated to some recursive type
-from the definition of the type. However, if the logical soundness is
-to be preserved, certain restrictions to this schema are
-necessary. This section provides a brief explanation of these
-restrictions.
-
-
-\subsubsection{The Positivity Condition}
-\label{postypes}
-
-In order to make sense of recursive types as types closed under their
-introduction rules, a constraint has to be imposed on the possible
-forms of such rules. This constraint, known as the
-\textsl{positivity condition}, is necessary to prevent the user from
-naively introducing some recursive types which would open the door to
-logical paradoxes. An example of such a dangerous type is the
-``inductive type'' \citecoq{Lambda}, whose only constructor is
-\citecoq{lambda} of type \citecoq{(Lambda\arrow False)\arrow Lambda}.
- Following the pattern
-given in Section \ref{CaseScheme}, the rule of (non dependent) case
-analysis for \citecoq{Lambda} would be the following:
-
-\begin{center}
-\snregla {\JM{Q}{\Prop}\;\;\;\;\;
- \JM{p}{\texttt{Lambda}}\;\;\;\;\;
- {h : {\texttt{Lambda}}\arrow\False\; \vdash\; t\,:\,Q}}
- {\JM{\citecoq{match $p$ return $Q$ with lambda h {\funarrow} $t$ end}}{Q}}
-\end{center}
-
-In order to avoid paradoxes, it is impossible to construct
-the type \citecoq{Lambda} in {\coq}:
-
-\begin{alltt}
-Inductive Lambda : Set :=
- lambda : (Lambda {\arrow} False) {\arrow} Lambda.
-\it
-Error: Non strictly positive occurrence of "Lambda" in
- "(Lambda {\arrow} False) {\arrow} Lambda"
-\end{alltt}
-
-In order to explain this danger, we
-will declare some constants for simulating the construction of
-\texttt{Lambda} as an inductive type.
-
-Let us open some section, and declare two variables, the first one for
-\texttt{Lambda}, the other for the constructor \texttt{lambda}.
-
-\begin{alltt}
-Section Paradox.
-Variable Lambda : Set.
-Variable lambda : (Lambda {\arrow} False) {\arrow}Lambda.
-\end{alltt}
-
-Since \texttt{Lambda} is not a truely inductive type, we can't use
-the \texttt{match} construct. Nevertheless, we can simulate it by a
-variable \texttt{matchL} such that the term
-``~\citecoq{matchL $l$ $Q$ (fun $h$ : Lambda {\arrow} False {\funarrow} $t$)}~''
-should be understood as
-``~\citecoq{match $l$ return $Q$ with | lambda h {\funarrow} $t$)}~''
-
-
-\begin{alltt}
-Variable matchL : Lambda {\arrow}
- {\prodsym} Q:Prop, ((Lambda {\arrow}False) {\arrow} Q) {\arrow}
- Q.
-\end{alltt}
-
->From these constants, it is possible to define application by case
-analysis. Then, through auto-application, the well-known looping term
-$(\lambda x.(x\;x)\;\lambda x.(x\;x))$ provides a proof of falsehood.
-
-\begin{alltt}
-Definition application (f x: Lambda) :False :=
- matchL f False (fun h {\funarrow} h x).
-
-Definition Delta : Lambda :=
- lambda (fun x : Lambda {\funarrow} application x x).
-
-Definition loop : False := application Delta Delta.
-
-Theorem two_is_three : 2 = 3.
-Proof.
- elim loop.
-Qed.
-
-End Paradox.
-\end{alltt}
-
-\noindent This example can be seen as a formulation of Russell's
-paradox in type theory associating $(\textsl{application}\;x\;x)$ to the
-formula $x\not\in x$, and \textsl{Delta} to the set $\{ x \mid
-x\not\in x\}$. If \texttt{matchL} would satisfy the reduction rule
-associated to case analysis, that is,
-$$ \citecoq{matchL (lambda $f$) $Q$ $h$} \Longrightarrow h\;f$$
-then the term \texttt{loop}
-would compute into itself. This is not actually surprising, since the
-proof of the logical soundness of {\coq} strongly lays on the property
-that any well-typed term must terminate. Hence, non-termination is
-usually a synonymous of inconsistency.
-
-%\paragraph{} In this case, the construction of a non-terminating
-%program comes from the so-called \textsl{negative occurrence} of
-%$\Lambda$ in the type of the constructor $\lambda$. In order to be
-%admissible for {\coq}, all the occurrences of the recursive type in its
-%own introduction rules must be positive, in the sense on the following
-%definition:
-%
-%\begin{enumerate}
-%\item $R$ is positive in $(R\;\vec{t})$;
-%\item $R$ is positive in $(x: A)C$ if it does not
-%occur in $A$ and $R$ is positive in $C$;
-%\item if $P\equiv (\vec{x}:\vec{T})Q$, then $R$ is positive in $(P
-%\rightarrow C)$ if $R$ does not occur in $\vec{T}$, $R$ is positive
-%in $C$, and either
-%\begin{enumerate}
-%\item $Q\equiv (R\;\vec{q})$ or
-%\item $Q\equiv (J\;\vec{t})$, \label{relax}
-% where $J$ is a recursive type, and for any term $t_i$ either :
-% \begin{enumerate}
-% \item $R$ does not occur in $t_i$, or
-% \item $t_i\equiv (z:\vec{Z})(R\;\vec{q})$, $R$ does not occur
-% in $\vec{Z}$, $t_i$ instantiates a general
-% parameter of $J$, and this parameter is positive in the
-% arguments of the constructors of $J$.
-% \end{enumerate}
-%\end{enumerate}
-%\end{enumerate}
-%\noindent Those types obtained by erasing option (\ref{relax}) in the
-%definition above are called \textsl{strictly positive} types.
-
-
-\subsubsection*{Remark} In this case, the construction of a non-terminating
-program comes from the so-called \textsl{negative occurrence} of
-\texttt{Lambda} in the argument of the constructor \texttt{lambda}.
-
-The reader will find in the Reference Manual a complete formal
-definition of the notions of \emph{positivity condition} and
-\emph{strict positivity} that an inductive definition must satisfy.
-
-
-%In order to be
-%admissible for {\coq}, the type $R$ must be positive in the types of the
-%arguments of its own introduction rules, in the sense on the following
-%definition:
-
-%\textbf{La définition du manuel de référence est plus complexe:
-%la recopier ou donner seulement des exemples?
-%}
-%\begin{enumerate}
-%\item $R$ is positive in $T$ if $R$ does not occur in $T$;
-%\item $R$ is positive in $(R\;\vec{t})$ if $R$ does not occur in $\vec{t}$;
-%\item $R$ is positive in $(x:A)C$ if it does not
-% occur in $A$ and $R$ is positive in $C$;
-%\item $R$ is positive in $(J\;\vec{t})$, \label{relax}
-% if $J$ is a recursive type, and for any term $t_i$ either :
-% \begin{enumerate}
-% \item $R$ does not occur in $t_i$, or
-% \item $R$ is positive in $t_i$, $t_i$ instantiates a general
-% parameter of $J$, and this parameter is positive in the
-% arguments of the constructors of $J$.
-% \end{enumerate}
-%\end{enumerate}
-
-%\noindent When we can show that $R$ is positive without using the item
-%(\ref{relax}) of the definition above, then we say that $R$ is
-%\textsl{strictly positive}.
-
-%\textbf{Changer le discours sur les ordinaux}
-
-Notice that the positivity condition does not forbid us to
-put functional recursive
-arguments in the constructors.
-
-For instance, let us consider the type of infinitely branching trees,
-with labels in \texttt{Z}.
-\begin{alltt}
-Require Import ZArith.
-
-Inductive itree : Set :=
-| ileaf : itree
-| inode : Z {\arrow} (nat {\arrow} itree) {\arrow} itree.
-\end{alltt}
-
-In this representation, the $i$-th child of a tree
-represented by ``~\texttt{inode $z$ $s$}~'' is obtained by applying
-the function $s$ to $i$.
-The following definitions show how to construct a tree with a single
-node, a tree of height 1 and a tree of height 2:
-
-\begin{alltt}
-Definition isingle l := inode l (fun i {\funarrow} ileaf).
-
-Definition t1 := inode 0 (fun n {\funarrow} isingle (Z.of_nat n)).
-
-Definition t2 :=
- inode 0
- (fun n : nat {\funarrow}
- inode (Z.of_nat n)
- (fun p {\funarrow} isingle (Z.of_nat (n*p)))).
-\end{alltt}
-
-
-Let us define a preorder on infinitely branching trees.
- In order to compare two non-leaf trees,
-it is necessary to compare each of their children
- without taking care of the order in which they
-appear:
-
-\begin{alltt}
-Inductive itree_le : itree{\arrow} itree {\arrow} Prop :=
- | le_leaf : {\prodsym} t, itree_le ileaf t
- | le_node : {\prodsym} l l' s s',
- Z.le l l' {\arrow}
- ({\prodsym} i, {\exsym} j:nat, itree_le (s i) (s' j)){\arrow}
- itree_le (inode l s) (inode l' s').
-
-\end{alltt}
-
-Notice that a call to the predicate \texttt{itree\_le} appears as
-a general parameter of the inductive type \texttt{ex} (see Sect.\ref{ex-def}).
-This kind of definition is accepted by {\coq}, but may lead to some
-difficulties, since the induction principle automatically
-generated by the system
-is not the most appropriate (see chapter 14 of~\cite{coqart} for a detailed
-explanation).
-
-
-The following definition, obtained by
-skolemising the
-proposition \linebreak $\forall\, i,\exists\, j,(\texttt{itree\_le}\;(s\;i)\;(s'\;j))$ in
-the type of \texttt{itree\_le}, does not present this problem:
-
-
-\begin{alltt}
-Inductive itree_le' : itree{\arrow} itree {\arrow} Prop :=
- | le_leaf' : {\prodsym} t, itree_le' ileaf t
- | le_node' : {\prodsym} l l' s s' g,
- Z.le l l' {\arrow}
- ({\prodsym} i, itree_le' (s i) (s' (g i))) {\arrow}
- itree_le' (inode l s) (inode l' s').
-
-\end{alltt}
-\iffalse
-\begin{alltt}
-Lemma t1_le'_t2 : itree_le' t1 t2.
-Proof.
- unfold t1, t2.
- constructor 2 with (fun i : nat {\funarrow} 2 * i).
- auto with zarith.
- unfold isingle;
- intro i ; constructor 2 with (fun i :nat {\funarrow} i).
- auto with zarith.
- constructor .
-Qed.
-\end{alltt}
-\fi
-
-%In general, strictly positive definitions are preferable to only
-%positive ones. The reason is that it is sometimes difficult to derive
-%structural induction combinators for the latter ones. Such combinators
-%are automatically generated for strictly positive types, but not for
-%the only positive ones. Nevertheless, sometimes non-strictly positive
-%definitions provide a smarter or shorter way of declaring a recursive
-%type.
-
-Another example is the type of trees
- of unbounded width, in which a recursive subterm
-\texttt{(ltree A)} instantiates the type of polymorphic lists:
-
-\begin{alltt}
-Require Import List.
-
-Inductive ltree (A:Set) : Set :=
- lnode : A {\arrow} list (ltree A) {\arrow} ltree A.
-\end{alltt}
-
-This declaration can be transformed
-adding an extra type to the definition, as was done in Section
-\ref{MutuallyDependent}.
-
-
-\subsubsection{Impredicative Inductive Types}
-
-An inductive type $I$ inhabiting a universe $U$ is \textsl{predicative}
-if the introduction rules of $I$ do not make a universal
-quantification on a universe containing $U$. All the recursive types
-previously introduced are examples of predicative types. An example of
-an impredicative one is the following type:
-%\textsl{exT}, the dependent product
-%of a certain set (or proposition) $x$, and a proof of a property $P$
-%about $x$.
-
-%\begin{alltt}
-%Print exT.
-%\end{alltt}
-%\textbf{ttention, EXT c'est ex!}
-%\begin{alltt}
-%Check (exists P:Prop, P {\arrow} not P).
-%\end{alltt}
-
-%This type is useful for expressing existential quantification over
-%types, like ``there exists a proposition $x$ such that $(P\;x)$''
-%---written $(\textsl{EXT}\; x:Prop \mid (P\;x))$ in {\coq}. However,
-
-\begin{alltt}
-Inductive prop : Prop :=
- prop_intro : Prop {\arrow} prop.
-\end{alltt}
-
-Notice
-that the constructor of this type can be used to inject any
-proposition --even itself!-- into the type.
-
-\begin{alltt}
-Check (prop_intro prop).\it
-prop_intro prop
- : prop
-\end{alltt}
-
-A careless use of such a
-self-contained objects may lead to a variant of Burali-Forti's
-paradox. The construction of Burali-Forti's paradox is more
-complicated than Russel's one, so we will not describe it here, and
-point the interested reader to \cite{Bar98,Coq86}.
-
-
-Another example is the second order existential quantifier for propositions:
-
-\begin{alltt}
-Inductive ex_Prop (P : Prop {\arrow} Prop) : Prop :=
- exP_intro : {\prodsym} X : Prop, P X {\arrow} ex_Prop P.
-\end{alltt}
-
-%\begin{alltt}
-%(*
-%Check (match prop_inject with (prop_intro p _) {\funarrow} p end).
-
-%Error: Incorrect elimination of "prop_inject" in the inductive type
-% ex
-%The elimination predicate ""fun _ : prop {\funarrow} Prop" has type
-% "prop {\arrow} Type"
-%It should be one of :
-% "Prop"
-
-%Elimination of an inductive object of sort : "Prop"
-%is not allowed on a predicate in sort : "Type"
-%because non-informative objects may not construct informative ones.
-
-%*)
-%Print prop_inject.
-
-%(*
-%prop_inject =
-%prop_inject = prop_intro prop (fun H : prop {\funarrow} H)
-% : prop
-%*)
-%\end{alltt}
-
-% \textbf{Et par ça?
-%}
-
-Notice that predicativity on sort \citecoq{Set} forbids us to build
-the following definitions.
-
-
-\begin{alltt}
-Inductive aSet : Set :=
- aSet_intro: Set {\arrow} aSet.
-
-\it{}User error: Large non-propositional inductive types must be in Type
-\tt
-Inductive ex_Set (P : Set {\arrow} Prop) : Set :=
- exS_intro : {\prodsym} X : Set, P X {\arrow} ex_Set P.
-
-\it{}User error: Large non-propositional inductive types must be in Type
-\end{alltt}
-
-Nevertheless, one can define types like \citecoq{aSet} and \citecoq{ex\_Set}, as inhabitants of \citecoq{Type}.
-
-\begin{alltt}
-Inductive ex_Set (P : Set {\arrow} Prop) : Type :=
- exS_intro : {\prodsym} X : Set, P X {\arrow} ex_Set P.
-\end{alltt}
-
-In the following example, the inductive type \texttt{typ} can be defined,
-but the term associated with the interactive Definition of
-\citecoq{typ\_inject} is incompatible with {\coq}'s hierarchy of universes:
-
-
-\begin{alltt}
-Inductive typ : Type :=
- typ_intro : Type {\arrow} typ.
-
-Definition typ_inject: typ.
- split; exact typ.
-\it Proof completed
-
-\tt{}Defined.
-\it Error: Universe Inconsistency.
-\tt
-Abort.
-\end{alltt}
-
-One possible way of avoiding this new source of paradoxes is to
-restrict the kind of eliminations by case analysis that can be done on
-impredicative types. In particular, projections on those universes
-equal or bigger than the one inhabited by the impredicative type must
-be forbidden \cite{Coq86}. A consequence of this restriction is that it
-is not possible to define the first projection of the type
-``~\citecoq{ex\_Prop $P$}~'':
-\begin{alltt}
-Check (fun (P:Prop{\arrow}Prop)(p: ex_Prop P) {\funarrow}
- match p with exP_intro X HX {\funarrow} X end).
-\it
-Error:
-Incorrect elimination of "p" in the inductive type
-"ex_Prop", the return type has sort "Type" while it should be
-"Prop"
-
-Elimination of an inductive object of sort "Prop"
-is not allowed on a predicate in sort "Type"
-because proofs can be eliminated only to build proofs.
-\end{alltt}
-
-%In order to explain why, let us consider for example the following
-%impredicative type \texttt{ALambda}.
-%\begin{alltt}
-%Inductive ALambda : Set :=
-% alambda : (A:Set)(A\arrow{}False)\arrow{}ALambda.
-%
-%Definition Lambda : Set := ALambda.
-%Definition lambda : (ALambda\arrow{}False)\arrow{}ALambda := (alambda ALambda).
-%Lemma CaseAL : (Q:Prop)ALambda\arrow{}((ALambda\arrow{}False)\arrow{}Q)\arrow{}Q.
-%\end{alltt}
-%
-%This type contains all the elements of the dangerous type $\Lambda$
-%described at the beginning of this section. Try to construct the
-%non-ending term $(\Delta\;\Delta)$ as an object of
-%\texttt{ALambda}. Why is it not possible?
-
-\subsubsection{Extraction Constraints}
-
-There is a final constraint on case analysis that is not motivated by
-the potential introduction of paradoxes, but for compatibility reasons
-with {\coq}'s extraction mechanism \refmancite{Appendix
-\ref{CamlHaskellExtraction}}. This mechanism is based on the
-classification of basic types into the universe $\Set$ of sets and the
-universe $\Prop$ of propositions. The objects of a type in the
-universe $\Set$ are considered as relevant for computation
-purposes. The objects of a type in $\Prop$ are considered just as
-formalised comments, not necessary for execution. The extraction
-mechanism consists in erasing such formal comments in order to obtain
-an executable program. Hence, in general, it is not possible to define
-an object in a set (that should be kept by the extraction mechanism)
-by case analysis of a proof (which will be thrown away).
-
-Nevertheless, this general rule has an exception which is important in
-practice: if the definition proceeds by case analysis on a proof of a
-\textsl{singleton proposition} or an empty type (\emph{e.g.} \texttt{False}),
- then it is allowed. A singleton
-proposition is a non-recursive proposition with a single constructor
-$c$, all whose arguments are proofs. For example, the propositional
-equality and the conjunction of two propositions are examples of
-singleton propositions.
-
-%From the point of view of the extraction
-%mechanism, such types are isomorphic to a type containing a single
-%object $c$, so a definition $\Case{x}{c \Rightarrow b}$ is
-%directly replaced by $b$ as an extra optimisation.
-
-\subsubsection{Strong Case Analysis on Proofs}
-
-One could consider allowing
- to define a proposition $Q$ by case
-analysis on the proofs of another recursive proposition $R$. As we
-will see in Section \ref{Discrimination}, this would enable one to prove that
-different introduction rules of $R$ construct different
-objects. However, this property would be in contradiction with the principle
-of excluded middle of classical logic, because this principle entails
-that the proofs of a proposition cannot be distinguished. This
-principle is not provable in {\coq}, but it is frequently introduced by
-the users as an axiom, for reasoning in classical logic. For this
-reason, the definition of propositions by case analysis on proofs is
- not allowed in {\coq}.
-
-\begin{alltt}
-
-Definition comes_from_the_left (P Q:Prop)(H:P{\coqor}Q): Prop :=
- match H with
- | or_introl p {\funarrow} True
- | or_intror q {\funarrow} False
- end.
-\it
-Error:
-Incorrect elimination of "H" in the inductive type
-"or", the return type has sort "Type" while it should be
-"Prop"
-
-Elimination of an inductive object of sort "Prop"
-is not allowed on a predicate in sort "Type"
-because proofs can be eliminated only to build proofs.
-
-\end{alltt}
-
-On the other hand, if we replace the proposition $P {\coqor} Q$ with
-the informative type $\{P\}+\{Q\}$, the elimination is accepted:
-
-\begin{alltt}
-Definition comes_from_the_left_sumbool
- (P Q:Prop)(x:\{P\} + \{Q\}): Prop :=
- match x with
- | left p {\funarrow} True
- | right q {\funarrow} False
- end.
-\end{alltt}
-
-
-\subsubsection{Summary of Constraints}
-
-To end with this section, the following table summarizes which
-universe $U_1$ may inhabit an object of type $Q$ defined by case
-analysis on $x:R$, depending on the universe $U_2$ inhabited by the
-inductive types $R$.\footnote{In the box indexed by $U_1=\citecoq{Type}$
-and $U_2=\citecoq{Set}$, the answer ``yes'' takes into account the
-predicativity of sort \citecoq{Set}. If you are working with the
-option ``impredicative-set'', you must put in this box the
-condition ``if $R$ is predicative''.}
-
-
-\begin{center}
-%%% displease hevea less by using * in multirow rather than \LL
-\renewcommand{\multirowsetup}{\centering}
-%\newlength{\LL}
-%\settowidth{\LL}{$x : R : U_2$}
-\begin{tabular}{|c|c|c|c|c|}
-\hline
-\multirow{5}*{$x : R : U_2$} &
-\multicolumn{4}{|c|}{$Q : U_1$}\\
-\hline
-& &\textsl{Set} & \textsl{Prop} & \textsl{Type}\\
-\cline{2-5}
-&\textsl{Set} & yes & yes & yes\\
-\cline{2-5}
-&\textsl{Prop} & if $R$ singleton & yes & no\\
-\cline{2-5}
-&\textsl{Type} & yes & yes & yes\\
-\hline
-\end{tabular}
-\end{center}
-
-\section{Some Proof Techniques Based on Case Analysis}
-\label{CaseTechniques}
-
-In this section we illustrate the use of case analysis as a proof
-principle, explaining the proof techniques behind three very useful
-{\coq} tactics, called \texttt{discriminate}, \texttt{injection} and
-\texttt{inversion}.
-
-\subsection{Discrimination of introduction rules}
-\label{Discrimination}
-
-In the informal semantics of recursive types described in Section
-\ref{Introduction} it was said that each of the introduction rules of a
-recursive type is considered as being different from all the others.
-It is possible to capture this fact inside the logical system using
-the propositional equality. We take as example the following theorem,
-stating that \textsl{O} constructs a natural number different
-from any of those constructed with \texttt{S}.
-
-\begin{alltt}
-Theorem S_is_not_O : {\prodsym} n, S n {\coqdiff} 0.
-\end{alltt}
-
-In order to prove this theorem, we first define a proposition by case
-analysis on natural numbers, so that the proposition is true for {\Z}
-and false for any natural number constructed with {\SUCC}. This uses
-the empty and singleton type introduced in Sections \ref{Introduction}.
-
-\begin{alltt}
-Definition Is_zero (x:nat):= match x with
- | 0 {\funarrow} True
- | _ {\funarrow} False
- end.
-\end{alltt}
-
-\noindent Then, we prove the following lemma:
-
-\begin{alltt}
-Lemma O_is_zero : {\prodsym} m, m = 0 {\arrow} Is_zero m.
-Proof.
- intros m H; subst m.
-\it{}
-================
- Is_zero 0
-\tt{}
-simpl;trivial.
-Qed.
-\end{alltt}
-
-\noindent Finally, the proof of \texttt{S\_is\_not\_O} follows by the
-application of the previous lemma to $S\;n$.
-
-
-\begin{alltt}
-
- red; intros n Hn.
- \it{}
- n : nat
- Hn : S n = 0
- ============================
- False \tt
-
- apply O_is_zero with (m := S n).
- assumption.
-Qed.
-\end{alltt}
-
-
-The tactic \texttt{discriminate} \refmancite{Section \ref{Discriminate}} is
-a special-purpose tactic for proving disequalities between two
-elements of a recursive type introduced by different constructors. It
-generalizes the proof method described here for natural numbers to any
-[co]-inductive type. This tactic is also capable of proving disequalities
-where the difference is not in the constructors at the head of the
-terms, but deeper inside them. For example, it can be used to prove
-the following theorem:
-
-\begin{alltt}
-Theorem disc2 : {\prodsym} n, S (S n) {\coqdiff} 1.
-Proof.
- intros n Hn; discriminate.
-Qed.
-\end{alltt}
-
-When there is an assumption $H$ in the context stating a false
-equality $t_1=t_2$, \texttt{discriminate} solves the goal by first
-proving $(t_1\not =t_2)$ and then reasoning by absurdity with respect
-to $H$:
-
-\begin{alltt}
-Theorem disc3 : {\prodsym} n, S (S n) = 0 {\arrow} {\prodsym} Q:Prop, Q.
-Proof.
- intros n Hn Q.
- discriminate.
-Qed.
-\end{alltt}
-
-\noindent In this case, the proof proceeds by absurdity with respect
-to the false equality assumed, whose negation is proved by
-discrimination.
-
-\subsection{Injectiveness of introduction rules}
-
-Another useful property about recursive types is the
-\textsl{injectiveness} of introduction rules, i.e., that whenever two
-objects were built using the same introduction rule, then this rule
-should have been applied to the same element. This can be stated
-formally using the propositional equality:
-
-\begin{alltt}
-Theorem inj : {\prodsym} n m, S n = S m {\arrow} n = m.
-Proof.
-\end{alltt}
-
-\noindent This theorem is just a corollary of a lemma about the
-predecessor function:
-
-\begin{alltt}
- Lemma inj_pred : {\prodsym} n m, n = m {\arrow} pred n = pred m.
- Proof.
- intros n m eq_n_m.
- rewrite eq_n_m.
- trivial.
- Qed.
-\end{alltt}
-\noindent Once this lemma is proven, the theorem follows directly
-from it:
-\begin{alltt}
- intros n m eq_Sn_Sm.
- apply inj_pred with (n:= S n) (m := S m); assumption.
-Qed.
-\end{alltt}
-
-This proof method is implemented by the tactic \texttt{injection}
-\refmancite{Section \ref{injection}}. This tactic is applied to
-a term $t$ of type ``~$c\;{t_1}\;\dots\;t_n = c\;t'_1\;\dots\;t'_n$~'', where $c$ is some constructor of
-an inductive type. The tactic \texttt{injection} is applied as deep as
-possible to derive the equality of all pairs of subterms of $t_i$ and $t'_i$
-placed in the same position. All these equalities are put as antecedents
-of the current goal.
-
-
-
-Like \texttt{discriminate}, the tactic \citecoq{injection}
-can be also applied if $x$ does not
-occur in a direct sub-term, but somewhere deeper inside it. Its
-application may leave some trivial goals that can be easily solved
-using the tactic \texttt{trivial}.
-
-\begin{alltt}
-
- Lemma list_inject : {\prodsym} (A:Type)(a b :A)(l l':list A),
- a :: b :: l = b :: a :: l' {\arrow} a = b {\coqand} l = l'.
-Proof.
- intros A a b l l' e.
-
-
-\it
- e : a :: b :: l = b :: a :: l'
- ============================
- a = b {\coqand} l = l'
-\tt
- injection e.
-\it
- ============================
- l = l' {\arrow} b = a {\arrow} a = b {\arrow} a = b {\coqand} l = l'
-
-\tt{} auto.
-Qed.
-\end{alltt}
-
-\subsection{Inversion Techniques}\label{inversion}
-
-In section \ref{DependentCase}, we motivated the rule of dependent case
-analysis as a way of internalizing the informal equalities $n=O$ and
-$n=\SUCC\;p$ associated to each case. This internalisation
-consisted in instantiating $n$ with the corresponding term in the type
-of each branch. However, sometimes it could be better to internalise
-these equalities as extra hypotheses --for example, in order to use
-the tactics \texttt{rewrite}, \texttt{discriminate} or
-\texttt{injection} presented in the previous sections. This is
-frequently the case when the element analysed is denoted by a term
-which is not a variable, or when it is an object of a particular
-instance of a recursive family of types. Consider for example the
-following theorem:
-
-\begin{alltt}
-Theorem not_le_Sn_0 : {\prodsym} n:nat, ~ (S n {\coqle} 0).
-\end{alltt}
-
-\noindent Intuitively, this theorem should follow by case analysis on
-the hypothesis $H:(S\;n\;\leq\;\Z)$, because no introduction rule allows
-to instantiate the arguments of \citecoq{le} with respectively a successor
-and zero. However, there
-is no way of capturing this with the typing rule for case analysis
-presented in section \ref{Introduction}, because it does not take into
-account what particular instance of the family the type of $H$ is.
-Let us try it:
-\begin{alltt}
-Proof.
- red; intros n H; case H.
-\it 2 subgoals
-
- n : nat
- H : S n {\coqle} 0
- ============================
- False
-
-subgoal 2 is:
- {\prodsym} m : nat, S n {\coqle} m {\arrow} False
-\tt
-Undo.
-\end{alltt}
-
-\noindent What is necessary here is to make available the equalities
-``~$\SUCC\;n = \Z$~'' and ``~$\SUCC\;m = \Z$~''
- as extra hypotheses of the
-branches, so that the goal can be solved using the
-\texttt{Discriminate} tactic. In order to obtain the desired
-equalities as hypotheses, let us prove an auxiliary lemma, that our
-theorem is a corollary of:
-
-\begin{alltt}
- Lemma not_le_Sn_0_with_constraints :
- {\prodsym} n p , S n {\coqle} p {\arrow} p = 0 {\arrow} False.
- Proof.
- intros n p H; case H .
-\it
-2 subgoals
-
- n : nat
- p : nat
- H : S n {\coqle} p
- ============================
- S n = 0 {\arrow} False
-
-subgoal 2 is:
- {\prodsym} m : nat, S n {\coqle} m {\arrow} S m = 0 {\arrow} False
-\tt
- intros;discriminate.
- intros;discriminate.
-Qed.
-\end{alltt}
-\noindent Our main theorem can now be solved by an application of this lemma:
-\begin{alltt}
-Show.
-\it
-2 subgoals
-
- n : nat
- p : nat
- H : S n {\coqle} p
- ============================
- S n = 0 {\arrow} False
-
-subgoal 2 is:
- {\prodsym} m : nat, S n {\coqle} m {\arrow} S m = 0 {\arrow} False
-\tt
- eapply not_le_Sn_0_with_constraints; eauto.
-Qed.
-\end{alltt}
-
-
-The general method to address such situations consists in changing the
-goal to be proven into an implication, introducing as preconditions
-the equalities needed to eliminate the cases that make no
-sense. This proof technique is implemented by the tactic
-\texttt{inversion} \refmancite{Section \ref{Inversion}}. In order
-to prove a goal $G\;\vec{q}$ from an object of type $R\;\vec{t}$,
-this tactic automatically generates a lemma $\forall, \vec{x}.
-(R\;\vec{x}) \rightarrow \vec{x}=\vec{t}\rightarrow \vec{B}\rightarrow
-(G\;\vec{q})$, where the list of propositions $\vec{B}$ correspond to
-the subgoals that cannot be directly proven using
-\texttt{discriminate}. This lemma can either be saved for later
-use, or generated interactively. In this latter case, the subgoals
-yielded by the tactic are the hypotheses $\vec{B}$ of the lemma. If the
-lemma has been stored, then the tactic \linebreak
- ``~\citecoq{inversion \dots using \dots}~'' can be
-used to apply it.
-
-Let us show both techniques on our previous example:
-
-\subsubsection{Interactive mode}
-
-\begin{alltt}
-Theorem not_le_Sn_0' : {\prodsym} n:nat, ~ (S n {\coqle} 0).
-Proof.
- red; intros n H ; inversion H.
-Qed.
-\end{alltt}
-
-
-\subsubsection{Static mode}
-
-\begin{alltt}
-
-Derive Inversion le_Sn_0_inv with ({\prodsym} n :nat, S n {\coqle} 0).
-Theorem le_Sn_0'' : {\prodsym} n p : nat, ~ S n {\coqle} 0 .
-Proof.
- intros n p H;
- inversion H using le_Sn_0_inv.
-Qed.
-\end{alltt}
-
-
-In the example above, all the cases are solved using discriminate, so
-there remains no subgoal to be proven (i.e. the list $\vec{B}$ is
-empty). Let us present a second example, where this list is not empty:
-
-
-\begin{alltt}
-TTheorem le_reverse_rules :
- {\prodsym} n m:nat, n {\coqle} m {\arrow}
- n = m {\coqor}
- {\exsym} p, n {\coqle} p {\coqand} m = S p.
-Proof.
- intros n m H; inversion H.
-\it
-2 subgoals
-
-
-
-
- n : nat
- m : nat
- H : n {\coqle} m
- H0 : n = m
- ============================
- m = m {\coqor} ({\exsym} p : nat, m {\coqle} p {\coqand} m = S p)
-
-subgoal 2 is:
- n = S m0 {\coqor} ({\exsym} p : nat, n {\coqle} p {\coqand} S m0 = S p)
-\tt
- left;trivial.
- right; exists m0; split; trivial.
-\it
-Proof completed
-\end{alltt}
-
-This example shows how this tactic can be used to ``reverse'' the
-introduction rules of a recursive type, deriving the possible premises
-that could lead to prove a given instance of the predicate. This is
-why these tactics are called \texttt{inversion} tactics: they go back
-from conclusions to premises.
-
-The hypotheses corresponding to the propositional equalities are not
-needed in this example, since the tactic does the necessary rewriting
-to solve the subgoals. When the equalities are no longer needed after
-the inversion, it is better to use the tactic
-\texttt{Inversion\_clear}. This variant of the tactic clears from the
-context all the equalities introduced.
-
-\begin{alltt}
-Restart.
- intros n m H; inversion_clear H.
-\it
-\it
-
- n : nat
- m : nat
- ============================
- m = m {\coqor} ({\exsym} p : nat, m {\coqle} p {\coqand} m = S p)
-\tt
- left;trivial.
-\it
- n : nat
- m : nat
- m0 : nat
- H0 : n {\coqle} m0
- ============================
- n = S m0 {\coqor} ({\exsym} p : nat, n {\coqle} p {\coqand} S m0 = S p)
-\tt
- right; exists m0; split; trivial.
-Qed.
-\end{alltt}
-
-
-%This proof technique works in most of the cases, but not always. In
-%particular, it could not if the list $\vec{t}$ contains a term $t_j$
-%whose type $T$ depends on a previous term $t_i$, with $i<j$. Remark
-%that if this is the case, the propositional equality $x_j=t_j$ is not
-%well-typed, since $x_j:T(x_i)$ but $t_j:T(t_i)$, and both types are
-%not convertible (otherwise, the problem could be solved using the
-%tactic \texttt{Case}).
-
-
-
-\begin{exercise}
-Consider the following language of arithmetic expression, and
-its operational semantics, described by a set of rewriting rules.
-%\textbf{J'ai enlevé une règle de commutativité de l'addition qui
-%me paraissait bizarre du point de vue de la sémantique opérationnelle}
-
-\begin{alltt}
-Inductive ArithExp : Set :=
- | Zero : ArithExp
- | Succ : ArithExp {\arrow} ArithExp
- | Plus : ArithExp {\arrow} ArithExp {\arrow} ArithExp.
-
-Inductive RewriteRel : ArithExp {\arrow} ArithExp {\arrow} Prop :=
- | RewSucc : {\prodsym} e1 e2 :ArithExp,
- RewriteRel e1 e2 {\arrow}
- RewriteRel (Succ e1) (Succ e2)
- | RewPlus0 : {\prodsym} e:ArithExp,
- RewriteRel (Plus Zero e) e
- | RewPlusS : {\prodsym} e1 e2:ArithExp,
- RewriteRel e1 e2 {\arrow}
- RewriteRel (Plus (Succ e1) e2)
- (Succ (Plus e1 e2)).
-
-\end{alltt}
-\begin{enumerate}
-\item Prove that \texttt{Zero} cannot be rewritten any further.
-\item Prove that an expression of the form ``~$\texttt{Succ}\;e$~'' is always
-rewritten
-into an expression of the same form.
-\end{enumerate}
-\end{exercise}
-
-%Theorem zeroNotCompute : (e:ArithExp)~(RewriteRel Zero e).
-%Intro e.
-%Red.
-%Intro H.
-%Inversion_clear H.
-%Defined.
-%Theorem evalPlus :
-% (e1,e2:ArithExp)
-% (RewriteRel (Succ e1) e2)\arrow{}(EX e3 : ArithExp | e2=(Succ e3)).
-%Intros e1 e2 H.
-%Inversion_clear H.
-%Exists e3;Reflexivity.
-%Qed.
-
-
-\section{Inductive Types and Structural Induction}
-\label{StructuralInduction}
-
-Elements of inductive types are well-founded with
-respect to the structural order induced by the constructors of the
-type. In addition to case analysis, this extra hypothesis about
-well-foundedness justifies a stronger elimination rule for them, called
-\textsl{structural induction}. This form of elimination consists in
-defining a value ``~$f\;x$~'' from some element $x$ of the inductive type
-$I$, assuming that values have been already associated in the same way
-to the sub-parts of $x$ of type $I$.
-
-
-Definitions by structural induction are expressed through the
-\texttt{Fixpoint} command \refmancite{Section
-\ref{Fixpoint}}. This command is quite close to the
-\texttt{let-rec} construction of functional programming languages.
-For example, the following definition introduces the addition of two
-natural numbers (already defined in the Standard Library:)
-
-\begin{alltt}
-Fixpoint plus (n p:nat) \{struct n\} : nat :=
- match n with
- | 0 {\funarrow} p
- | S m {\funarrow} S (plus m p)
- end.
-\end{alltt}
-
-The definition is by structural induction on the first argument of the
-function. This is indicated by the ``~\citecoq{\{struct n\}}~''
-directive in the function's header\footnote{This directive is optional
-in the case of a function of a single argument}.
- In
-order to be accepted, the definition must satisfy a syntactical
-condition, called the \textsl{guardedness condition}. Roughly
-speaking, this condition constrains the arguments of a recursive call
-to be pattern variables, issued from a case analysis of the formal
-argument of the function pointed by the \texttt{struct} directive.
- In the case of the
-function \texttt{plus}, the argument \texttt{m} in the recursive call is a
-pattern variable issued from a case analysis of \texttt{n}. Therefore, the
-definition is accepted.
-
-Notice that we could have defined the addition with structural induction
-on its second argument:
-\begin{alltt}
-Fixpoint plus' (n p:nat) \{struct p\} : nat :=
- match p with
- | 0 {\funarrow} n
- | S q {\funarrow} S (plus' n q)
- end.
-\end{alltt}
-
-%This notation is useful when defining a function whose decreasing
-%argument has a dependent type. As an example, consider the following
-%recursivly defined proof of the theorem
-%$(n,m:\texttt{nat})n<m \rightarrow (S\;n)<(S\;m)$:
-%\begin{alltt}
-%Fixpoint lt_n_S [n,m:nat;p:(lt n m)] : (lt (S n) (S m)) :=
-% <[n0:nat](lt (S n) (S n0))>
-% Cases p of
-% lt_intro1 {\funarrow} (lt_intro1 (S n))
-% | (lt_intro2 m1 p2) {\funarrow} (lt_intro2 (S n) (S m1) (lt_n_S n m1 p2))
-% end.
-%\end{alltt}
-
-%The guardedness condition must be satisfied only by the last argument
-%of the enclosed list. For example, the following declaration is an
-%alternative way of defining addition:
-
-%\begin{alltt}
-%Reset add.
-%Fixpoint add [n:nat] : nat\arrow{}nat :=
-% Cases n of
-% O {\funarrow} [x:nat]x
-% | (S m) {\funarrow} [x:nat](add m (S x))
-% end.
-%\end{alltt}
-
-In the following definition of addition,
-the second argument of {\tt plus{'}{'}} grows at each
-recursive call. However, as the first one always decreases, the
-definition is sound.
-\begin{alltt}
-Fixpoint plus'' (n p:nat) \{struct n\} : nat :=
- match n with
- | 0 {\funarrow} p
- | S m {\funarrow} plus'' m (S p)
- end.
-\end{alltt}
-
- Moreover, the argument in the recursive call
-could be a deeper component of $n$. This is the case in the following
-definition of a boolean function determining whether a number is even
-or odd:
-
-\begin{alltt}
-Fixpoint even_test (n:nat) : bool :=
- match n
- with 0 {\funarrow} true
- | 1 {\funarrow} false
- | S (S p) {\funarrow} even_test p
- end.
-\end{alltt}
-
-Mutually dependent definitions by structural induction are also
-allowed. For example, the previous function \textsl{even} could alternatively
-be defined using an auxiliary function \textsl{odd}:
-
-\begin{alltt}
-Reset even_test.
-
-
-
-Fixpoint even_test (n:nat) : bool :=
- match n
- with
- | 0 {\funarrow} true
- | S p {\funarrow} odd_test p
- end
-with odd_test (n:nat) : bool :=
- match n
- with
- | 0 {\funarrow} false
- | S p {\funarrow} even_test p
- end.
-\end{alltt}
-
-%\begin{exercise}
-%Define a function by structural induction that computes the number of
-%nodes of a tree structure defined in page \pageref{Forest}.
-%\end{exercise}
-
-Definitions by structural induction are computed
- only when they are applied, and the decreasing argument
-is a term having a constructor at the head. We can check this using
-the \texttt{Eval} command, which computes the normal form of a well
-typed term.
-
-\begin{alltt}
-Eval simpl in even_test.
-\it
- = even_test
- : nat {\arrow} bool
-\tt
-Eval simpl in (fun x : nat {\funarrow} even x).
-\it
- = fun x : nat {\funarrow} even x
- : nat {\arrow} Prop
-\tt
-Eval simpl in (fun x : nat => plus 5 x).
-\it
- = fun x : nat {\funarrow} S (S (S (S (S x))))
-
-\tt
-Eval simpl in (fun x : nat {\funarrow} even_test (plus 5 x)).
-\it
- = fun x : nat {\funarrow} odd_test x
- : nat {\arrow} bool
-\tt
-Eval simpl in (fun x : nat {\funarrow} even_test (plus x 5)).
-\it
- = fun x : nat {\funarrow} even_test (x + 5)
- : nat {\arrow} bool
-\end{alltt}
-
-
-%\begin{exercise}
-%Prove that the second definition of even satisfies the following
-%theorem:
-%\begin{verbatim}
-%Theorem unfold_even :
-% (x:nat)
-% (even x)= (Cases x of
-% O {\funarrow} true
-% | (S O) {\funarrow} false
-% | (S (S m)) {\funarrow} (even m)
-% end).
-%\end{verbatim}
-%\end{exercise}
-
-\subsection{Proofs by Structural Induction}
-
-The principle of structural induction can be also used in order to
-define proofs, that is, to prove theorems. Let us call an
-\textsl{elimination combinator} any function that, given a predicate
-$P$, defines a proof of ``~$P\;x$~'' by structural induction on $x$. In
-{\coq}, the principle of proof by induction on natural numbers is a
-particular case of an elimination combinator. The definition of this
-combinator depends on three general parameters: the predicate to be
-proven, the base case, and the inductive step:
-
-\begin{alltt}
-Section Principle_of_Induction.
-Variable P : nat {\arrow} Prop.
-Hypothesis base_case : P 0.
-Hypothesis inductive_step : {\prodsym} n:nat, P n {\arrow} P (S n).
-Fixpoint nat_ind (n:nat) : (P n) :=
- match n return P n with
- | 0 {\funarrow} base_case
- | S m {\funarrow} inductive_step m (nat_ind m)
- end.
-
-End Principle_of_Induction.
-\end{alltt}
-
-As this proof principle is used very often, {\coq} automatically generates it
-when an inductive type is introduced. Similar principles
-\texttt{nat\_rec} and \texttt{nat\_rect} for defining objects in the
-universes $\Set$ and $\Type$ are also automatically generated
-\footnote{In fact, whenever possible, {\coq} generates the
-principle \texttt{$I$\_rect}, then derives from it the
-weaker principles \texttt{$I$\_ind} and \texttt{$I$\_rec}.
-If some principle has to be defined by hand, the user may try
-to build \texttt{$I$\_rect} (if possible). Thanks to {\coq}'s conversion
-rule, this principle can be used directly to build proofs and/or
-programs.}. The
-command \texttt{Scheme} \refmancite{Section \ref{Scheme}} can be
-used to generate an elimination combinator from certain parameters,
-like the universe that the defined objects must inhabit, whether the
-case analysis in the definitions must be dependent or not, etc. For
-example, it can be used to generate an elimination combinator for
-reasoning on even natural numbers from the mutually dependent
-predicates introduced in page \pageref{Even}. We do not display the
-combinators here by lack of space, but you can see them using the
-\texttt{Print} command.
-
-\begin{alltt}
-Scheme Even_induction := Minimality for even Sort Prop
-with Odd_induction := Minimality for odd Sort Prop.
-\end{alltt}
-
-\begin{alltt}
-Theorem even_plus_four : {\prodsym} n:nat, even n {\arrow} even (4+n).
-Proof.
- intros n H.
- elim H using Even_induction with (P0 := fun n {\funarrow} odd (4+n));
- simpl;repeat constructor;assumption.
-Qed.
-\end{alltt}
-
-Another example of an elimination combinator is the principle
-of double induction on natural numbers, introduced by the following
-definition:
-
-\begin{alltt}
-Section Principle_of_Double_Induction.
-Variable P : nat {\arrow} nat {\arrow}Prop.
-Hypothesis base_case1 : {\prodsym} m:nat, P 0 m.
-Hypothesis base_case2 : {\prodsym} n:nat, P (S n) 0.
-Hypothesis inductive_step : {\prodsym} n m:nat, P n m {\arrow}
- \,\, P (S n) (S m).
-
-Fixpoint nat_double_ind (n m:nat)\{struct n\} : P n m :=
- match n, m return P n m with
- | 0 , x {\funarrow} base_case1 x
- | (S x), 0 {\funarrow} base_case2 x
- | (S x), (S y) {\funarrow} inductive_step x y (nat_double_ind x y)
- end.
-End Principle_of_Double_Induction.
-\end{alltt}
-
-Changing the type of $P$ into $\nat\rightarrow\nat\rightarrow\Type$,
-another combinator for constructing
-(certified) programs, \texttt{nat\_double\_rect}, can be defined in exactly the same way.
-This definition is left as an exercise.\label{natdoublerect}
-
-\iffalse
-\begin{alltt}
-Section Principle_of_Double_Recursion.
-Variable P : nat {\arrow} nat {\arrow} Type.
-Hypothesis base_case1 : {\prodsym} x:nat, P 0 x.
-Hypothesis base_case2 : {\prodsym} x:nat, P (S x) 0.
-Hypothesis inductive_step : {\prodsym} n m:nat, P n m {\arrow} P (S n) (S m).
-Fixpoint nat_double_rect (n m:nat)\{struct n\} : P n m :=
- match n, m return P n m with
- 0 , x {\funarrow} base_case1 x
- | (S x), 0 {\funarrow} base_case2 x
- | (S x), (S y) {\funarrow} inductive_step x y (nat_double_rect x y)
- end.
-End Principle_of_Double_Recursion.
-\end{alltt}
-\fi
-For instance the function computing the minimum of two natural
-numbers can be defined in the following way:
-
-\begin{alltt}
-Definition min : nat {\arrow} nat {\arrow} nat :=
- nat_double_rect (fun (x y:nat) {\funarrow} nat)
- (fun (x:nat) {\funarrow} 0)
- (fun (y:nat) {\funarrow} 0)
- (fun (x y r:nat) {\funarrow} S r).
-Eval compute in (min 5 8).
-\it
-= 5 : nat
-\end{alltt}
-
-
-%\begin{exercise}
-%
-%Define the combinator \texttt{nat\_double\_rec}, and apply it
-%to give another definition of \citecoq{le\_lt\_dec} (using the theorems
-%of the \texttt{Arith} library).
-%\end{exercise}
-
-\subsection{Using Elimination Combinators.}
-The tactic \texttt{apply} can be used to apply one of these proof
-principles during the development of a proof.
-
-\begin{alltt}
-Lemma not_circular : {\prodsym} n:nat, n {\coqdiff} S n.
-Proof.
- intro n.
- apply nat_ind with (P:= fun n {\funarrow} n {\coqdiff} S n).
-\it
-
-
-
-2 subgoals
-
- n : nat
- ============================
- 0 {\coqdiff} 1
-
-
-subgoal 2 is:
- {\prodsym} n0 : nat, n0 {\coqdiff} S n0 {\arrow} S n0 {\coqdiff} S (S n0)
-
-\tt
- discriminate.
- red; intros n0 Hn0 eqn0Sn0;injection eqn0Sn0;trivial.
-Qed.
-\end{alltt}
-
-The tactic \texttt{elim} \refmancite{Section \ref{Elim}} is a
-refinement of \texttt{apply}, specially designed for the application
-of elimination combinators. If $t$ is an object of an inductive type
-$I$, then ``~\citecoq{elim $t$}~'' tries to find an abstraction $P$ of the
-current goal $G$ such that $(P\;t)\equiv G$. Then it solves the goal
-applying ``~$I\texttt{\_ind}\;P$~'', where $I$\texttt{\_ind} is the
-combinator associated to $I$. The different cases of the induction
-then appear as subgoals that remain to be solved.
-In the previous proof, the tactic call ``~\citecoq{apply nat\_ind with (P:= fun n {\funarrow} n {\coqdiff} S n)}~'' can simply be replaced with ``~\citecoq{elim n}~''.
-
-The option ``~\citecoq{\texttt{elim} $t$ \texttt{using} $C$}~''
- allows the use of a
-derived combinator $C$ instead of the default one. Consider the
-following theorem, stating that equality is decidable on natural
-numbers:
-
-\label{iseqpage}
-\begin{alltt}
-Lemma eq_nat_dec : {\prodsym} n p:nat, \{n=p\}+\{n {\coqdiff} p\}.
-Proof.
- intros n p.
-\end{alltt}
-
-Let us prove this theorem using the combinator \texttt{nat\_double\_rect}
-of section~\ref{natdoublerect}. The example also illustrates how
-\texttt{elim} may sometimes fail in finding a suitable abstraction $P$
-of the goal. Note that if ``~\texttt{elim n}~''
- is used directly on the
-goal, the result is not the expected one.
-
-\vspace{12pt}
-
-%\pagebreak
-\begin{alltt}
- elim n using nat_double_rect.
-\it
-4 subgoals
-
- n : nat
- p : nat
- ============================
- {\prodsym} x : nat, \{x = p\} + \{x {\coqdiff} p\}
-
-subgoal 2 is:
- nat {\arrow} \{0 = p\} + \{0 {\coqdiff} p\}
-
-subgoal 3 is:
- nat {\arrow} {\prodsym} m : nat, \{m = p\} + \{m {\coqdiff} p\} {\arrow} \{S m = p\} + \{S m {\coqdiff} p\}
-
-subgoal 4 is:
- nat
-\end{alltt}
-
-The four sub-goals obtained do not correspond to the premises that
-would be expected for the principle \texttt{nat\_double\_rec}. The
-problem comes from the fact that
-this principle for eliminating $n$
-has a universally quantified formula as conclusion, which confuses
-\texttt{elim} about the right way of abstracting the goal.
-
-%In effect, let us consider the type of the goal before the call to
-%\citecoq{elim}: ``~\citecoq{\{n = p\} + \{n {\coqdiff} p\}}~''.
-
-%Among all the abstractions that can be built by ``~\citecoq{elim n}~''
-%let us consider this one
-%$P=$\citecoq{fun n :nat {\funarrow} fun q : nat {\funarrow} {\{q= p\} + \{q {\coqdiff} p\}}}.
-%It is easy to verify that
-%$P$ has type \citecoq{nat {\arrow} nat {\arrow} Set}, and that, if some
-%$q:\citecoq{nat}$ is given, then $P\;q\;$ matches the current goal.
-%Then applying \citecoq{nat\_double\_rec} with $P$ generates
-%four goals, corresponding to
-
-
-
-
-Therefore,
-in this case the abstraction must be explicited using the
-\texttt{pattern} tactic. Once the right abstraction is provided, the rest of
-the proof is immediate:
-
-\begin{alltt}
-Undo.
- pattern p,n.
-\it
- n : nat
- p : nat
- ============================
- (fun n0 n1 : nat {\funarrow} \{n1 = n0\} + \{n1 {\coqdiff} n0\}) p n
-\tt
- elim n using nat_double_rec.
-\it
-3 subgoals
-
- n : nat
- p : nat
- ============================
- {\prodsym} x : nat, \{x = 0\} + \{x {\coqdiff} 0\}
-
-subgoal 2 is:
- {\prodsym} x : nat, \{0 = S x\} + \{0 {\coqdiff} S x\}
-subgoal 3 is:
- {\prodsym} n0 m : nat, \{m = n0\} + \{m {\coqdiff} n0\} {\arrow} \{S m = S n0\} + \{S m {\coqdiff} S n0\}
-
-\tt
- destruct x; auto.
- destruct x; auto.
- intros n0 m H; case H.
- intro eq; rewrite eq ; auto.
- intro neg; right; red ; injection 1; auto.
-Defined.
-\end{alltt}
-
-
-Notice that the tactic ``~\texttt{decide equality}~''
-\refmancite{Section\ref{DecideEquality}} generalises the proof
-above to a large class of inductive types. It can be used for proving
-a proposition of the form
-$\forall\,(x,y:R),\{x=y\}+\{x{\coqdiff}y\}$, where $R$ is an inductive datatype
-all whose constructors take informative arguments ---like for example
-the type {\nat}:
-
-\begin{alltt}
-Definition eq_nat_dec' : {\prodsym} n p:nat, \{n=p\} + \{n{\coqdiff}p\}.
- decide equality.
-Defined.
-\end{alltt}
-
-\begin{exercise}
-\begin{enumerate}
-\item Define a recursive function of name \emph{nat2itree}
-that maps any natural number $n$ into an infinitely branching
-tree of height $n$.
-\item Provide an elimination combinator for these trees.
-\item Prove that the relation \citecoq{itree\_le} is a preorder
-(i.e. reflexive and transitive).
-\end{enumerate}
-\end{exercise}
-
-\begin{exercise} \label{zeroton}
-Define the type of lists, and a predicate ``being an ordered list''
-using an inductive family. Then, define the function
-$(from\;n)=0::1\;\ldots\; n::\texttt{nil}$ and prove that it always generates an
-ordered list.
-\end{exercise}
-
-\begin{exercise}
-Prove that \citecoq{le' n p} and \citecoq{n $\leq$ p} are logically equivalent
-for all n and p. (\citecoq{le'} is defined in section \ref{parameterstuff}).
-\end{exercise}
-
-
-\subsection{Well-founded Recursion}
-\label{WellFoundedRecursion}
-
-Structural induction is a strong elimination rule for inductive types.
-This method can be used to define any function whose termination is
-a consequence of the well-foundedness of a certain order relation $R$ decreasing
-at each recursive call. What makes this principle so strong is the
-possibility of reasoning by structural induction on the proof that
-certain $R$ is well-founded. In order to illustrate this we have
-first to introduce the predicate of accessibility.
-
-\begin{alltt}
-Print Acc.
-\it
-Inductive Acc (A : Type) (R : A {\arrow} A {\arrow} Prop) (x:A) : Prop :=
- Acc_intro : ({\prodsym} y : A, R y x {\arrow} Acc R y) {\arrow} Acc R x
-For Acc: Argument A is implicit
-For Acc_intro: Arguments A, R are implicit
-
-\dots
-\end{alltt}
-
-\noindent This inductive predicate characterizes those elements $x$ of
-$A$ such that any descending $R$-chain $\ldots x_2\;R\;x_1\;R\;x$
-starting from $x$ is finite. A well-founded relation is a relation
-such that all the elements of $A$ are accessible.
-\emph{Notice the use of parameter $x$ (see Section~\ref{parameterstuff}, page
-\pageref{parameterstuff}).}
-
-Consider now the problem of representing in {\coq} the following ML
-function $\textsl{div}(x,y)$ on natural numbers, which computes
-$\lceil\frac{x}{y}\rceil$ if $y>0$ and yields $x$ otherwise.
-
-\begin{verbatim}
-let rec div x y =
- if x = 0 then 0
- else if y = 0 then x
- else (div (x-y) y)+1;;
-\end{verbatim}
-
-
-The equality test on natural numbers can be implemented using the
-function \textsl{eq\_nat\_dec} that is defined page \pageref{iseqpage}. Giving $x$ and
-$y$, this function yields either the value $(\textsl{left}\;p)$ if
-there exists a proof $p:x=y$, or the value $(\textsl{right}\;q)$ if
-there exists $q:a\not = b$. The subtraction function is already
-defined in the library \citecoq{Minus}.
-
-Hence, direct translation of the ML function \textsl{div} would be:
-
-\begin{alltt}
-Require Import Minus.
-
-Fixpoint div (x y:nat)\{struct x\}: nat :=
- if eq_nat_dec x 0
- then 0
- else if eq_nat_dec y 0
- then x
- else S (div (x-y) y).
-
-\it Error:
-Recursive definition of div is ill-formed.
-In environment
-div : nat {\arrow} nat {\arrow} nat
-x : nat
-y : nat
-_ : x {\coqdiff} 0
-_ : y {\coqdiff} 0
-
-Recursive call to div has principal argument equal to
-"x - y"
-instead of a subterm of x
-\end{alltt}
-
-
-The program \texttt{div} is rejected by {\coq} because it does not verify
-the syntactical condition to ensure termination. In particular, the
-argument of the recursive call is not a pattern variable issued from a
-case analysis on $x$.
-We would have the same problem if we had the directive
-``~\citecoq{\{struct y\}}~'' instead of ``~\citecoq{\{struct x\}}~''.
-However, we know that this program always
-stops. One way to justify its termination is to define it by
-structural induction on a proof that $x$ is accessible trough the
-relation $<$. Notice that any natural number $x$ is accessible
-for this relation. In order to do this, it is first necessary to prove
-some auxiliary lemmas, justifying that the first argument of
-\texttt{div} decreases at each recursive call.
-
-\begin{alltt}
-Lemma minus_smaller_S : {\prodsym} x y:nat, x - y < S x.
-Proof.
- intros x y; pattern y, x;
- elim x using nat_double_ind.
- destruct x0; auto with arith.
- simpl; auto with arith.
- simpl; auto with arith.
-Qed.
-
-
-Lemma minus_smaller_positive :
- {\prodsym} x y:nat, x {\coqdiff}0 {\arrow} y {\coqdiff} 0 {\arrow} x - y < x.
-Proof.
- destruct x; destruct y;
- ( simpl;intros; apply minus_smaller ||
- intros; absurd (0=0); auto).
-Qed.
-\end{alltt}
-
-\noindent The last two lemmas are necessary to prove that for any pair
-of positive natural numbers $x$ and $y$, if $x$ is accessible with
-respect to \citecoq{lt}, then so is $x-y$.
-
-\begin{alltt}
-Definition minus_decrease : {\prodsym} x y:nat, Acc lt x {\arrow}
- x {\coqdiff} 0 {\arrow}
- y {\coqdiff} 0 {\arrow}
- Acc lt (x-y).
-Proof.
- intros x y H; case H.
- intros Hz posz posy.
- apply Hz; apply minus_smaller_positive; assumption.
-Defined.
-\end{alltt}
-
-Let us take a look at the proof of the lemma \textsl{minus\_decrease}, since
-the way in which it has been proven is crucial for what follows.
-\begin{alltt}
-Print minus_decrease.
-\it
-minus_decrease =
-fun (x y : nat) (H : Acc lt x) {\funarrow}
-match H in (Acc _ y0) return (y0 {\coqdiff} 0 {\arrow} y {\coqdiff} 0 {\arrow} Acc lt (y0 - y)) with
-| Acc_intro z Hz {\funarrow}
- fun (posz : z {\coqdiff} 0) (posy : y {\coqdiff} 0) {\funarrow}
- Hz (z - y) (minus_smaller_positive z y posz posy)
-end
- : {\prodsym} x y : nat, Acc lt x {\arrow} x {\coqdiff} 0 {\arrow} y {\coqdiff} 0 {\arrow} Acc lt (x - y)
-
-\end{alltt}
-\noindent Notice that the function call
-$(\texttt{minus\_decrease}\;n\;m\;H)$
-indeed yields an accessibility proof that is \textsl{structurally
-smaller} than its argument $H$, because it is (an application of) its
-recursive component $Hz$. This enables to justify the following
-definition of \textsl{div\_aux}:
-
-\begin{alltt}
-Definition div_aux (x y:nat)(H: Acc lt x):nat.
- fix div_aux 3.
- intros.
- refine (if eq_nat_dec x 0
- then 0
- else if eq_nat_dec y 0
- then y
- else div_aux (x-y) y _).
-\it
- div_aux : {\prodsym} x : nat, nat {\arrow} Acc lt x {\arrow} nat
- x : nat
- y : nat
- H : Acc lt x
- _ : x {\coqdiff} 0
- _0 : y {\coqdiff} 0
- ============================
- Acc lt (x - y)
-
-\tt
- apply (minus_decrease x y H);auto.
-Defined.
-\end{alltt}
-
-The main division function is easily defined, using the theorem
-\citecoq{lt\_wf} of the library \citecoq{Wf\_nat}. This theorem asserts that
-\citecoq{nat} is well founded w.r.t. \citecoq{lt}, thus any natural number
-is accessible.
-\begin{alltt}
-Definition div x y := div_aux x y (lt_wf x).
-\end{alltt}
-
-Let us explain the proof above. In the definition of \citecoq{div\_aux},
-what decreases is not $x$ but the \textsl{proof} of the accessibility
-of $x$. The tactic ``~\texttt{fix div\_aux 3}~'' is used to indicate that the proof
-proceeds by structural induction on the third argument of the theorem
---that is, on the accessibility proof. It also introduces a new
-hypothesis in the context, named ``~\texttt{div\_aux}~'', and with the
-same type as the goal. Then, the proof is refined with an incomplete
-proof term, containing a hole \texttt{\_}. This hole corresponds to the proof
-of accessibility for $x-y$, and is filled up with the (smaller!)
-accessibility proof provided by the function \texttt{minus\_decrease}.
-
-
-\noindent Let us take a look to the term \textsl{div\_aux} defined:
-
-\pagebreak
-\begin{alltt}
-Print div_aux.
-\it
-div_aux =
-(fix div_aux (x y : nat) (H : Acc lt x) \{struct H\} : nat :=
- match eq_nat_dec x 0 with
- | left _ {\funarrow} 0
- | right _ {\funarrow}
- match eq_nat_dec y 0 with
- | left _ {\funarrow} y
- | right _0 {\funarrow} div_aux (x - y) y (minus_decrease x y H _ _0)
- end
- end)
- : {\prodsym} x : nat, nat {\arrow} Acc lt x {\arrow} nat
-
-\end{alltt}
-
-If the non-informative parts from this proof --that is, the
-accessibility proof-- are erased, then we obtain exactly the program
-that we were looking for.
-\begin{alltt}
-
-Extraction div.
-
-\it
-let div x y =
- div_aux x y
-\tt
-
-Extraction div_aux.
-
-\it
-let rec div_aux x y =
- match eq_nat_dec x O with
- | Left {\arrow} O
- | Right {\arrow}
- (match eq_nat_dec y O with
- | Left {\arrow} y
- | Right {\arrow} div_aux (minus x y) y)
-\end{alltt}
-
-This methodology enables the representation
-of any program whose termination can be proved in {\coq}. Once the
-expected properties from this program have been verified, the
-justification of its termination can be thrown away, keeping just the
-desired computational behavior for it.
-
-\section{A case study in dependent elimination}\label{CaseStudy}
-
-Dependent types are very expressive, but ignoring some useful
-techniques can cause some problems to the beginner.
-Let us consider again the type of vectors (see section~\ref{vectors}).
-We want to prove a quite trivial property: the only value of type
-``~\citecoq{vector A 0}~'' is ``~\citecoq{Vnil $A$}~''.
-
-Our first naive attempt leads to a \emph{cul-de-sac}.
-\begin{alltt}
-Lemma vector0_is_vnil :
- {\prodsym} (A:Type)(v:vector A 0), v = Vnil A.
-Proof.
- intros A v;inversion v.
-\it
-1 subgoal
-
- A : Set
- v : vector A 0
- ============================
- v = Vnil A
-\tt
-Abort.
-\end{alltt}
-
-Another attempt is to do a case analysis on a vector of any length
-$n$, under an explicit hypothesis $n=0$. The tactic
-\texttt{discriminate} will help us to get rid of the case
-$n=\texttt{S $p$}$.
-Unfortunately, even the statement of our lemma is refused!
-
-\begin{alltt}
- Lemma vector0_is_vnil_aux :
- {\prodsym} (A:Type)(n:nat)(v:vector A n), n = 0 {\arrow} v = Vnil A.
-
-\it
-Error: In environment
-A : Type
-n : nat
-v : vector A n
-e : n = 0
-The term "Vnil A" has type "vector A 0" while it is expected to have type
- "vector A n"
-\end{alltt}
-
-In effect, the equality ``~\citecoq{v = Vnil A}~'' is ill-typed and this is
-because the type ``~\citecoq{vector A n}~'' is not \emph{convertible}
-with ``~\citecoq{vector A 0}~''.
-
-This problem can be solved if we consider the heterogeneous
-equality \citecoq{JMeq} \cite{conor:motive}
-which allows us to consider terms of different types, even if this
-equality can only be proven for terms in the same type.
-The axiom \citecoq{JMeq\_eq}, from the library \citecoq{JMeq} allows us to convert a
-heterogeneous equality to a standard one.
-
-\begin{alltt}
-Lemma vector0_is_vnil_aux :
- {\prodsym} (A:Type)(n:nat)(v:vector A n),
- n= 0 {\arrow} JMeq v (Vnil A).
-Proof.
- destruct v.
- auto.
- intro; discriminate.
-Qed.
-\end{alltt}
-
-Our property of vectors of null length can be easily proven:
-
-\begin{alltt}
-Lemma vector0_is_vnil : {\prodsym} (A:Type)(v:vector A 0), v = Vnil A.
- intros a v;apply JMeq_eq.
- apply vector0_is_vnil_aux.
- trivial.
-Qed.
-\end{alltt}
-
-It is interesting to look at another proof of
-\citecoq{vector0\_is\_vnil}, which illustrates a technique developed
-and used by various people (consult in the \emph{Coq-club} mailing
-list archive the contributions by Yves Bertot, Pierre Letouzey, Laurent Théry,
-Jean Duprat, and Nicolas Magaud, Venanzio Capretta and Conor McBride).
-This technique is also used for unfolding infinite list definitions
-(see chapter13 of~\cite{coqart}).
-Notice that this definition does not rely on any axiom (\emph{e.g.} \texttt{JMeq\_eq}).
-
-We first give a new definition of the identity on vectors. Before that,
-we make the use of constructors and selectors lighter thanks to
-the implicit arguments feature:
-
-\begin{alltt}
-Implicit Arguments Vcons [A n].
-Implicit Arguments Vnil [A].
-Implicit Arguments Vhead [A n].
-Implicit Arguments Vtail [A n].
-
-Definition Vid : {\prodsym} (A : Type)(n:nat), vector A n {\arrow} vector A n.
-Proof.
- destruct n; intro v.
- exact Vnil.
- exact (Vcons (Vhead v) (Vtail v)).
-Defined.
-\end{alltt}
-
-
-Then we prove that \citecoq{Vid} is the identity on vectors:
-
-\begin{alltt}
-Lemma Vid_eq : {\prodsym} (n:nat) (A:Type)(v:vector A n), v=(Vid _ n v).
-Proof.
- destruct v.
-
-\it
- A : Type
- ============================
- Vnil = Vid A 0 Vnil
-
-subgoal 2 is:
- Vcons a v = Vid A (S n) (Vcons a v)
-\tt
- reflexivity.
- reflexivity.
-Defined.
-\end{alltt}
-
-Why defining a new identity function on vectors? The following
-dialogue shows that \citecoq{Vid} has some interesting computational
-properties:
-
-\begin{alltt}
-Eval simpl in (fun (A:Type)(v:vector A 0) {\funarrow} (Vid _ _ v)).
-\it = fun (A : Type) (_ : vector A 0) {\funarrow} Vnil
- : {\prodsym} A : Type, vector A 0 {\arrow} vector A 0
-
-\end{alltt}
-
-Notice that the plain identity on vectors doesn't convert \citecoq{v}
-into \citecoq{Vnil}.
-\begin{alltt}
-Eval simpl in (fun (A:Type)(v:vector A 0) {\funarrow} v).
-\it = fun (A : Type) (v : vector A 0) {\funarrow} v
- : {\prodsym} A : Type, vector A 0 {\arrow} vector A 0
-\end{alltt}
-
-Then we prove easily that any vector of length 0 is \citecoq{Vnil}:
-
-\begin{alltt}
-Theorem zero_nil : {\prodsym} A (v:vector A 0), v = Vnil.
-Proof.
- intros.
- change (Vnil (A:=A)) with (Vid _ 0 v).
-\it
-1 subgoal
-
- A : Type
- v : vector A 0
- ============================
- v = Vid A 0 v
-\tt
- apply Vid_eq.
-Defined.
-\end{alltt}
-
-A similar result can be proven about vectors of strictly positive
-length\footnote{As for \citecoq{Vid} and \citecoq{Vid\_eq}, this definition
-is from Jean Duprat.}.
-
-\begin{alltt}
-
-
-Theorem decomp :
- {\prodsym} (A : Type) (n : nat) (v : vector A (S n)),
- v = Vcons (Vhead v) (Vtail v).
-Proof.
- intros.
- change (Vcons (Vhead v) (Vtail v)) with (Vid _ (S n) v).
-\it
- 1 subgoal
-
- A : Type
- n : nat
- v : vector A (S n)
- ============================
- v = Vid A (S n) v
-
-\tt{} apply Vid_eq.
-Defined.
-\end{alltt}
-
-
-Both lemmas: \citecoq{zero\_nil} and \citecoq{decomp},
-can be used to easily derive a double recursion principle
-on vectors of same length:
-
-
-\begin{alltt}
-Definition vector_double_rect :
- {\prodsym} (A:Type) (P: {\prodsym} (n:nat),(vector A n){\arrow}(vector A n) {\arrow} Type),
- P 0 Vnil Vnil {\arrow}
- ({\prodsym} n (v1 v2 : vector A n) a b, P n v1 v2 {\arrow}
- P (S n) (Vcons a v1) (Vcons b v2)) {\arrow}
- {\prodsym} n (v1 v2 : vector A n), P n v1 v2.
- induction n.
- intros; rewrite (zero_nil _ v1); rewrite (zero_nil _ v2).
- auto.
- intros v1 v2; rewrite (decomp _ _ v1);rewrite (decomp _ _ v2).
- apply X0; auto.
-Defined.
-\end{alltt}
-
-Notice that, due to the conversion rule of {\coq}'s type system,
-this function can be used directly with \citecoq{Prop} or \citecoq{Type}
-instead of type (thus it is useless to build
-\citecoq{vector\_double\_ind} and \citecoq{vector\_double\_rec}) from scratch.
-
-We finish this example with showing how to define the bitwise
-\emph{or} on boolean vectors of the same length,
-and proving a little property about this
-operation.
-
-\begin{alltt}
-Definition bitwise_or n v1 v2 : vector bool n :=
- vector_double_rect
- bool
- (fun n v1 v2 {\funarrow} vector bool n)
- Vnil
- (fun n v1 v2 a b r {\funarrow} Vcons (orb a b) r) n v1 v2.
-\end{alltt}
-
-Let us define recursively the $n$-th element of a vector. Notice
-that it must be a partial function, in case $n$ is greater or equal
-than the length of the vector. Since {\coq} only considers total
-functions, the function returns a value in an \emph{option} type.
-
-\begin{alltt}
-Fixpoint vector_nth (A:Type)(n:nat)(p:nat)(v:vector A p)
- \{struct v\}
- : option A :=
- match n,v with
- _ , Vnil {\funarrow} None
- | 0 , Vcons b _ _ {\funarrow} Some b
- | S n', Vcons _ p' v' {\funarrow} vector_nth A n' p' v'
- end.
-Implicit Arguments vector_nth [A p].
-\end{alltt}
-
-We can now prove --- using the double induction combinator ---
-a simple property relying \citecoq{vector\_nth} and \citecoq{bitwise\_or}:
-
-\begin{alltt}
-Lemma nth_bitwise :
- {\prodsym} (n:nat) (v1 v2: vector bool n) i a b,
- vector_nth i v1 = Some a {\arrow}
- vector_nth i v2 = Some b {\arrow}
- vector_nth i (bitwise_or _ v1 v2) = Some (orb a b).
-Proof.
- intros n v1 v2; pattern n,v1,v2.
- apply vector_double_rect.
- simpl.
- destruct i; discriminate 1.
- destruct i; simpl;auto.
- injection 1; injection 2;intros; subst a; subst b; auto.
-Qed.
-\end{alltt}
-
-
-\section{Co-inductive Types and Non-ending Constructions}
-\label{CoInduction}
-
-The objects of an inductive type are well-founded with respect to
-the constructors of the type. In other words, these objects are built
-by applying \emph{a finite number of times} the constructors of the type.
-Co-inductive types are obtained by relaxing this condition,
-and may contain non-well-founded objects \cite{EG96,EG95a}. An
-example of a co-inductive type is the type of infinite
-sequences formed with elements of type $A$, also called streams. This
-type can be introduced through the following definition:
-
-\begin{alltt}
- CoInductive Stream (A: Type) :Type :=
- | Cons : A\arrow{}Stream A\arrow{}Stream A.
-\end{alltt}
-
-If we are interested in finite or infinite sequences, we consider the type
-of \emph{lazy lists}:
-
-\begin{alltt}
-CoInductive LList (A: Type) : Type :=
- | LNil : LList A
- | LCons : A {\arrow} LList A {\arrow} LList A.
-\end{alltt}
-
-
-It is also possible to define co-inductive types for the
-trees with infinitely-many branches (see Chapter 13 of~\cite{coqart}).
-
-Structural induction is the way of expressing that inductive types
-only contain well-founded objects. Hence, this elimination principle
-is not valid for co-inductive types, and the only elimination rule for
-streams is case analysis. This principle can be used, for example, to
-define the destructors \textsl{head} and \textsl{tail}.
-
-\begin{alltt}
- Definition head (A:Type)(s : Stream A) :=
- match s with Cons a s' {\funarrow} a end.
-
- Definition tail (A : Type)(s : Stream A) :=
- match s with Cons a s' {\funarrow} s' end.
-\end{alltt}
-
-Infinite objects are defined by means of (non-ending) methods of
-construction, like in lazy functional programming languages. Such
-methods can be defined using the \texttt{CoFixpoint} command
-\refmancite{Section \ref{CoFixpoint}}. For example, the following
-definition introduces the infinite list $[a,a,a,\ldots]$:
-
-\begin{alltt}
- CoFixpoint repeat (A:Type)(a:A) : Stream A :=
- Cons a (repeat a).
-\end{alltt}
-
-
-However, not every co-recursive definition is an admissible method of
-construction. Similarly to the case of structural induction, the
-definition must verify a \textsl{guardedness} condition to be
-accepted. This condition states that any recursive call in the
-definition must be protected --i.e, be an argument of-- some
-constructor, and only an argument of constructors \cite{EG94a}. The
-following definitions are examples of valid methods of construction:
-
-\begin{alltt}
-CoFixpoint iterate (A: Type)(f: A {\arrow} A)(a : A) : Stream A:=
- Cons a (iterate f (f a)).
-
-CoFixpoint map
- (A B:Type)(f: A {\arrow} B)(s : Stream A) : Stream B:=
- match s with Cons a tl {\funarrow} Cons (f a) (map f tl) end.
-\end{alltt}
-
-\begin{exercise}
-Define two different methods for constructing the stream which
-infinitely alternates the values \citecoq{true} and \citecoq{false}.
-\end{exercise}
-\begin{exercise}
-Using the destructors \texttt{head} and \texttt{tail}, define a function
-which takes the n-th element of an infinite stream.
-\end{exercise}
-
-A non-ending method of construction is computed lazily. This means
-that its definition is unfolded only when the object that it
-introduces is eliminated, that is, when it appears as the argument of
-a case expression. We can check this using the command
-\texttt{Eval}.
-
-\begin{alltt}
-Eval simpl in (fun (A:Type)(a:A) {\funarrow} repeat a).
-\it = fun (A : Type) (a : A) {\funarrow} repeat a
- : {\prodsym} A : Type, A {\arrow} Stream A
-\tt
-Eval simpl in (fun (A:Type)(a:A) {\funarrow} head (repeat a)).
-\it = fun (A : Type) (a : A) {\funarrow} a
- : {\prodsym} A : Type, A {\arrow} A
-\end{alltt}
-
-%\begin{exercise}
-%Prove the following theorem:
-%\begin{verbatim}
-%Theorem expand_repeat : (a:A)(repeat a)=(Cons a (repeat a)).
-%\end{verbatim}
-%Hint: Prove first the streams version of the lemma in exercise
-%\ref{expand}.
-%\end{exercise}
-
-\subsection{Extensional Properties}
-
-Case analysis is also a valid proof principle for infinite
-objects. However, this principle is not sufficient to prove
-\textsl{extensional} properties, that is, properties concerning the
-whole infinite object \cite{EG95a}. A typical example of an
-extensional property is the predicate expressing that two streams have
-the same elements. In many cases, the minimal reflexive relation $a=b$
-that is used as equality for inductive types is too small to capture
-equality between streams. Consider for example the streams
-$\texttt{iterate}\;f\;(f\;x)$ and
-$(\texttt{map}\;f\;(\texttt{iterate}\;f\;x))$. Even though these two streams have
-the same elements, no finite expansion of their definitions lead to
-equal terms. In other words, in order to deal with extensional
-properties, it is necessary to construct infinite proofs. The type of
-infinite proofs of equality can be introduced as a co-inductive
-predicate, as follows:
-\begin{alltt}
-CoInductive EqSt (A: Type) : Stream A {\arrow} Stream A {\arrow} Prop :=
- eqst : {\prodsym} s1 s2: Stream A,
- head s1 = head s2 {\arrow}
- EqSt (tail s1) (tail s2) {\arrow}
- EqSt s1 s2.
-\end{alltt}
-
-It is possible to introduce proof principles for reasoning about
-infinite objects as combinators defined through
-\texttt{CoFixpoint}. However, oppositely to the case of inductive
-types, proof principles associated to co-inductive types are not
-elimination but \textsl{introduction} combinators. An example of such
-a combinator is Park's principle for proving the equality of two
-streams, usually called the \textsl{principle of co-induction}. It
-states that two streams are equal if they satisfy a
-\textit{bisimulation}. A bisimulation is a binary relation $R$ such
-that any pair of streams $s_1$ ad $s_2$ satisfying $R$ have equal
-heads, and tails also satisfying $R$. This principle is in fact a
-method for constructing an infinite proof:
-
-\begin{alltt}
-Section Parks_Principle.
-Variable A : Type.
-Variable R : Stream A {\arrow} Stream A {\arrow} Prop.
-Hypothesis bisim1 : {\prodsym} s1 s2:Stream A,
- R s1 s2 {\arrow} head s1 = head s2.
-
-Hypothesis bisim2 : {\prodsym} s1 s2:Stream A,
- R s1 s2 {\arrow} R (tail s1) (tail s2).
-
-CoFixpoint park_ppl :
- {\prodsym} s1 s2:Stream A, R s1 s2 {\arrow} EqSt s1 s2 :=
- fun s1 s2 (p : R s1 s2) {\funarrow}
- eqst s1 s2 (bisim1 s1 s2 p)
- (park_ppl (tail s1)
- (tail s2)
- (bisim2 s1 s2 p)).
-End Parks_Principle.
-\end{alltt}
-
-Let us use the principle of co-induction to prove the extensional
-equality mentioned above.
-\begin{alltt}
-Theorem map_iterate : {\prodsym} (A:Type)(f:A{\arrow}A)(x:A),
- EqSt (iterate f (f x))
- (map f (iterate f x)).
-Proof.
- intros A f x.
- apply park_ppl with
- (R:= fun s1 s2 {\funarrow}
- {\exsym} x: A, s1 = iterate f (f x) {\coqand}
- s2 = map f (iterate f x)).
-
- intros s1 s2 (x0,(eqs1,eqs2));
- rewrite eqs1; rewrite eqs2; reflexivity.
- intros s1 s2 (x0,(eqs1,eqs2)).
- exists (f x0);split;
- [rewrite eqs1|rewrite eqs2]; reflexivity.
- exists x;split; reflexivity.
-Qed.
-\end{alltt}
-
-The use of Park's principle is sometimes annoying, because it requires
-to find an invariant relation and prove that it is indeed a
-bisimulation. In many cases, a shorter proof can be obtained trying
-to construct an ad-hoc infinite proof, defined by a guarded
-declaration. The tactic ``~``\texttt{Cofix $f$}~'' can be used to do
-that. Similarly to the tactic \texttt{fix} indicated in Section
-\ref{WellFoundedRecursion}, this tactic introduces an extra hypothesis
-$f$ into the context, whose type is the same as the current goal. Note
-that the applications of $f$ in the proof \textsl{must be guarded}. In
-order to prevent us from doing unguarded calls, we can define a tactic
-that always apply a constructor before using $f$ \refmancite{Chapter
-\ref{WritingTactics}} :
-
-\begin{alltt}
-Ltac infiniteproof f :=
- cofix f;
- constructor;
- [clear f| simpl; try (apply f; clear f)].
-\end{alltt}
-
-
-In the example above, this tactic produces a much simpler proof
-that the former one:
-
-\begin{alltt}
-Theorem map_iterate' : {\prodsym} ((A:Type)f:A{\arrow}A)(x:A),
- EqSt (iterate f (f x))
- (map f (iterate f x)).
-Proof.
- infiniteproof map_iterate'.
- reflexivity.
-Qed.
-\end{alltt}
-
-\begin{exercise}
-Define a co-inductive type of name $Nat$ that contains non-standard
-natural numbers --this is, verifying
-
-$$\exists m \in \mbox{\texttt{Nat}}, \forall\, n \in \mbox{\texttt{Nat}}, n<m$$.
-\end{exercise}
-
-\begin{exercise}
-Prove that the extensional equality of streams is an equivalence relation
-using Park's co-induction principle.
-\end{exercise}
-
-
-\begin{exercise}
-Provide a suitable definition of ``being an ordered list'' for infinite lists
-and define a principle for proving that an infinite list is ordered. Apply
-this method to the list $[0,1,\ldots ]$. Compare the result with
-exercise \ref{zeroton}.
-\end{exercise}
-
-\subsection{About injection, discriminate, and inversion}
-Since co-inductive types are closed w.r.t. their constructors,
-the techniques shown in Section~\ref{CaseTechniques} work also
-with these types.
-
-Let us consider the type of lazy lists, introduced on page~\pageref{CoInduction}.
-The following lemmas are straightforward applications
- of \texttt{discriminate} and \citecoq{injection}:
-
-\begin{alltt}
-Lemma Lnil_not_Lcons : {\prodsym} (A:Type)(a:A)(l:LList A),
- LNil {\coqdiff} (LCons a l).
-Proof.
- intros;discriminate.
-Qed.
-
-Lemma injection_demo : {\prodsym} (A:Type)(a b : A)(l l': LList A),
- LCons a (LCons b l) = LCons b (LCons a l') {\arrow}
- a = b {\coqand} l = l'.
-Proof.
- intros A a b l l' e; injection e; auto.
-Qed.
-
-\end{alltt}
-
-In order to show \citecoq{inversion} at work, let us define
-two predicates on lazy lists:
-
-\begin{alltt}
-Inductive Finite (A:Type) : LList A {\arrow} Prop :=
-| Lnil_fin : Finite (LNil (A:=A))
-| Lcons_fin : {\prodsym} a l, Finite l {\arrow} Finite (LCons a l).
-
-CoInductive Infinite (A:Type) : LList A {\arrow} Prop :=
-| LCons_inf : {\prodsym} a l, Infinite l {\arrow} Infinite (LCons a l).
-\end{alltt}
-
-\noindent
-First, two easy theorems:
-\begin{alltt}
-Lemma LNil_not_Infinite : {\prodsym} (A:Type), ~ Infinite (LNil (A:=A)).
-Proof.
- intros A H;inversion H.
-Qed.
-
-Lemma Finite_not_Infinite : {\prodsym} (A:Type)(l:LList A),
- Finite l {\arrow} ~ Infinite l.
-Proof.
- intros A l H; elim H.
- apply LNil_not_Infinite.
- intros a l0 F0 I0' I1.
- case I0'; inversion_clear I1.
- trivial.
-Qed.
-\end{alltt}
-
-
-On the other hand, the next proof uses the \citecoq{cofix} tactic.
-Notice the destructuration of \citecoq{l}, which allows us to
-apply the constructor \texttt{LCons\_inf}, thus satisfying
- the guard condition:
-\begin{alltt}
-Lemma Not_Finite_Infinite : {\prodsym} (A:Type)(l:LList A),
- ~ Finite l {\arrow} Infinite l.
-Proof.
- cofix H.
- destruct l.
- intro;
- absurd (Finite (LNil (A:=A)));
- [auto|constructor].
-\it
-
-
-
-
-1 subgoal
-
- H : forall (A : Type) (l : LList A), ~ Finite l -> Infinite l
- A : Type
- a : A
- l : LList A
- H0 : ~ Finite (LCons a l)
- ============================
- Infinite l
-\end{alltt}
-At this point, one must not apply \citecoq{H}! . It would be possible
-to solve the current goal by an inversion of ``~\citecoq{Finite (LCons a l)}~'', but, since the guard condition would be violated, the user
-would get an error message after typing \citecoq{Qed}.
-In order to satisfy the guard condition, we apply the constructor of
-\citecoq{Infinite}, \emph{then} apply \citecoq{H}.
-
-\begin{alltt}
- constructor.
- apply H.
- red; intro H1;case H0.
- constructor.
- trivial.
-Qed.
-\end{alltt}
-
-
-
-
-The reader is invited to replay this proof and understand each of its steps.
-
-
-\bibliographystyle{abbrv}
-\bibliography{manbiblio,morebib}
-
-\end{document}
-
diff --git a/doc/RecTutorial/RecTutorial.v b/doc/RecTutorial/RecTutorial.v
deleted file mode 100644
index 4a17e0818..000000000
--- a/doc/RecTutorial/RecTutorial.v
+++ /dev/null
@@ -1,1231 +0,0 @@
-Unset Automatic Introduction.
-
-Check (forall A:Type, (exists x:A, forall (y:A), x <> y) -> 2 = 3).
-
-
-
-Inductive nat : Set :=
- | O : nat
- | S : nat->nat.
-Check nat.
-Check O.
-Check S.
-
-Reset nat.
-Print nat.
-
-
-Print le.
-
-Theorem zero_leq_three: 0 <= 3.
-
-Proof.
- constructor 2.
- constructor 2.
- constructor 2.
- constructor 1.
-
-Qed.
-
-Print zero_leq_three.
-
-
-Lemma zero_leq_three': 0 <= 3.
- repeat constructor.
-Qed.
-
-
-Lemma zero_lt_three : 0 < 3.
-Proof.
- repeat constructor.
-Qed.
-
-Print zero_lt_three.
-
-Inductive le'(n:nat):nat -> Prop :=
- | le'_n : le' n n
- | le'_S : forall p, le' (S n) p -> le' n p.
-
-Hint Constructors le'.
-
-
-Require Import List.
-
-Print list.
-
-Check list.
-
-Check (nil (A:=nat)).
-
-Check (nil (A:= nat -> nat)).
-
-Check (fun A: Type => (cons (A:=A))).
-
-Check (cons 3 (cons 2 nil)).
-
-Check (nat :: bool ::nil).
-
-Check ((3<=4) :: True ::nil).
-
-Check (Prop::Set::nil).
-
-Require Import Bvector.
-
-Print Vector.t.
-
-Check (Vector.nil nat).
-
-Check (fun (A:Type)(a:A)=> Vector.cons _ a _ (Vector.nil _)).
-
-Check (Vector.cons _ 5 _ (Vector.cons _ 3 _ (Vector.nil _))).
-
-Lemma eq_3_3 : 2 + 1 = 3.
-Proof.
- reflexivity.
-Qed.
-Print eq_3_3.
-
-Lemma eq_proof_proof : eq_refl (2*6) = eq_refl (3*4).
-Proof.
- reflexivity.
-Qed.
-Print eq_proof_proof.
-
-Lemma eq_lt_le : ( 2 < 4) = (3 <= 4).
-Proof.
- reflexivity.
-Qed.
-
-Lemma eq_nat_nat : nat = nat.
-Proof.
- reflexivity.
-Qed.
-
-Lemma eq_Set_Set : Set = Set.
-Proof.
- reflexivity.
-Qed.
-
-Lemma eq_Type_Type : Type = Type.
-Proof.
- reflexivity.
-Qed.
-
-
-Check (2 + 1 = 3).
-
-
-Check (Type = Type).
-
-Goal Type = Type.
-reflexivity.
-Qed.
-
-
-Print or.
-
-Print and.
-
-
-Print sumbool.
-
-Print ex.
-
-Require Import ZArith.
-Require Import Compare_dec.
-
-Check le_lt_dec.
-
-Definition max (n p :nat) := match le_lt_dec n p with
- | left _ => p
- | right _ => n
- end.
-
-Theorem le_max : forall n p, n <= p -> max n p = p.
-Proof.
- intros n p ; unfold max ; case (le_lt_dec n p); simpl.
- trivial.
- intros; absurd (p < p); eauto with arith.
-Qed.
-
-Require Extraction.
-Extraction max.
-
-
-
-
-
-
-Inductive tree(A:Type) : Type :=
- node : A -> forest A -> tree A
-with
- forest (A: Type) : Type :=
- nochild : forest A |
- addchild : tree A -> forest A -> forest A.
-
-
-
-
-
-Inductive
- even : nat->Prop :=
- evenO : even O |
- evenS : forall n, odd n -> even (S n)
-with
- odd : nat->Prop :=
- oddS : forall n, even n -> odd (S n).
-
-Lemma odd_49 : odd (7 * 7).
- simpl; repeat constructor.
-Qed.
-
-
-
-Definition nat_case :=
- fun (Q : Type)(g0 : Q)(g1 : nat -> Q)(n:nat) =>
- match n return Q with
- | 0 => g0
- | S p => g1 p
- end.
-
-Eval simpl in (nat_case nat 0 (fun p => p) 34).
-
-Eval simpl in (fun g0 g1 => nat_case nat g0 g1 34).
-
-Eval simpl in (fun g0 g1 => nat_case nat g0 g1 0).
-
-
-Definition pred (n:nat) := match n with O => O | S m => m end.
-
-Eval simpl in pred 56.
-
-Eval simpl in pred 0.
-
-Eval simpl in fun p => pred (S p).
-
-
-Definition xorb (b1 b2:bool) :=
-match b1, b2 with
- | false, true => true
- | true, false => true
- | _ , _ => false
-end.
-
-
- Definition pred_spec (n:nat) := {m:nat | n=0 /\ m=0 \/ n = S m}.
-
-
- Definition predecessor : forall n:nat, pred_spec n.
- intro n;case n.
- unfold pred_spec;exists 0;auto.
- unfold pred_spec; intro n0;exists n0; auto.
- Defined.
-
-Print predecessor.
-
-Extraction predecessor.
-
-Theorem nat_expand :
- forall n:nat, n = match n with 0 => 0 | S p => S p end.
- intro n;case n;simpl;auto.
-Qed.
-
-Check (fun p:False => match p return 2=3 with end).
-
-Theorem fromFalse : False -> 0=1.
- intro absurd.
- contradiction.
-Qed.
-
-Section equality_elimination.
- Variables (A: Type)
- (a b : A)
- (p : a = b)
- (Q : A -> Type).
- Check (fun H : Q a =>
- match p in (eq _ y) return Q y with
- eq_refl => H
- end).
-
-End equality_elimination.
-
-
-Theorem trans : forall n m p:nat, n=m -> m=p -> n=p.
-Proof.
- intros n m p eqnm.
- case eqnm.
- trivial.
-Qed.
-
-Lemma Rw : forall x y: nat, y = y * x -> y * x * x = y.
- intros x y e; do 2 rewrite <- e.
- reflexivity.
-Qed.
-
-
-Require Import Arith.
-
-Check mult_1_l.
-(*
-mult_1_l
- : forall n : nat, 1 * n = n
-*)
-
-Check mult_plus_distr_r.
-(*
-mult_plus_distr_r
- : forall n m p : nat, (n + m) * p = n * p + m * p
-
-*)
-
-Lemma mult_distr_S : forall n p : nat, n * p + p = (S n)* p.
- simpl;auto with arith.
-Qed.
-
-Lemma four_n : forall n:nat, n+n+n+n = 4*n.
- intro n;rewrite <- (mult_1_l n).
-
- Undo.
- intro n; pattern n at 1.
-
-
- rewrite <- mult_1_l.
- repeat rewrite mult_distr_S.
- trivial.
-Qed.
-
-
-Section Le_case_analysis.
- Variables (n p : nat)
- (H : n <= p)
- (Q : nat -> Prop)
- (H0 : Q n)
- (HS : forall m, n <= m -> Q (S m)).
- Check (
- match H in (_ <= q) return (Q q) with
- | le_n _ => H0
- | le_S _ m Hm => HS m Hm
- end
- ).
-
-
-End Le_case_analysis.
-
-
-Lemma predecessor_of_positive : forall n, 1 <= n -> exists p:nat, n = S p.
-Proof.
- intros n H; case H.
- exists 0; trivial.
- intros m Hm; exists m;trivial.
-Qed.
-
-Definition Vtail_total
- (A : Type) (n : nat) (v : Vector.t A n) : Vector.t A (pred n):=
-match v in (Vector.t _ n0) return (Vector.t A (pred n0)) with
-| Vector.nil _ => Vector.nil A
-| Vector.cons _ _ n0 v0 => v0
-end.
-
-Definition Vtail' (A:Type)(n:nat)(v:Vector.t A n) : Vector.t A (pred n).
- intros A n v; case v.
- simpl.
- exact (Vector.nil A).
- simpl.
- auto.
-Defined.
-
-(*
-Inductive Lambda : Set :=
- lambda : (Lambda -> False) -> Lambda.
-
-
-Error: Non strictly positive occurrence of "Lambda" in
- "(Lambda -> False) -> Lambda"
-
-*)
-
-Section Paradox.
- Variable Lambda : Set.
- Variable lambda : (Lambda -> False) ->Lambda.
-
- Variable matchL : Lambda -> forall Q:Prop, ((Lambda ->False) -> Q) -> Q.
- (*
- understand matchL Q l (fun h : Lambda -> False => t)
-
- as match l return Q with lambda h => t end
- *)
-
- Definition application (f x: Lambda) :False :=
- matchL f False (fun h => h x).
-
- Definition Delta : Lambda := lambda (fun x : Lambda => application x x).
-
- Definition loop : False := application Delta Delta.
-
- Theorem two_is_three : 2 = 3.
- Proof.
- elim loop.
- Qed.
-
-End Paradox.
-
-
-Require Import ZArith.
-
-
-
-Inductive itree : Set :=
-| ileaf : itree
-| inode : Z-> (nat -> itree) -> itree.
-
-Definition isingle l := inode l (fun i => ileaf).
-
-Definition t1 := inode 0 (fun n => isingle (Z.of_nat (2*n))).
-
-Definition t2 := inode 0
- (fun n : nat =>
- inode (Z.of_nat n)
- (fun p => isingle (Z.of_nat (n*p)))).
-
-
-Inductive itree_le : itree-> itree -> Prop :=
- | le_leaf : forall t, itree_le ileaf t
- | le_node : forall l l' s s',
- Z.le l l' ->
- (forall i, exists j:nat, itree_le (s i) (s' j)) ->
- itree_le (inode l s) (inode l' s').
-
-
-Theorem itree_le_trans :
- forall t t', itree_le t t' ->
- forall t'', itree_le t' t'' -> itree_le t t''.
- induction t.
- constructor 1.
-
- intros t'; case t'.
- inversion 1.
- intros z0 i0 H0.
- intro t'';case t''.
- inversion 1.
- intros.
- inversion_clear H1.
- constructor 2.
- inversion_clear H0;eauto with zarith.
- inversion_clear H0.
- intro i2; case (H4 i2).
- intros.
- generalize (H i2 _ H0).
- intros.
- case (H3 x);intros.
- generalize (H5 _ H6).
- exists x0;auto.
-Qed.
-
-
-
-Inductive itree_le' : itree-> itree -> Prop :=
- | le_leaf' : forall t, itree_le' ileaf t
- | le_node' : forall l l' s s' g,
- Z.le l l' ->
- (forall i, itree_le' (s i) (s' (g i))) ->
- itree_le' (inode l s) (inode l' s').
-
-
-
-
-
-Lemma t1_le_t2 : itree_le t1 t2.
- unfold t1, t2.
- constructor.
- auto with zarith.
- intro i; exists (2 * i).
- unfold isingle.
- constructor.
- auto with zarith.
- exists i;constructor.
-Qed.
-
-
-
-Lemma t1_le'_t2 : itree_le' t1 t2.
- unfold t1, t2.
- constructor 2 with (fun i : nat => 2 * i).
- auto with zarith.
- unfold isingle;
- intro i ; constructor 2 with (fun i :nat => i).
- auto with zarith.
- constructor .
-Qed.
-
-
-Require Import List.
-
-Inductive ltree (A:Set) : Set :=
- lnode : A -> list (ltree A) -> ltree A.
-
-Inductive prop : Prop :=
- prop_intro : Prop -> prop.
-
-Check (prop_intro prop).
-
-Inductive ex_Prop (P : Prop -> Prop) : Prop :=
- exP_intro : forall X : Prop, P X -> ex_Prop P.
-
-Lemma ex_Prop_inhabitant : ex_Prop (fun P => P -> P).
-Proof.
- exists (ex_Prop (fun P => P -> P)).
- trivial.
-Qed.
-
-
-
-
-(*
-
-Check (fun (P:Prop->Prop)(p: ex_Prop P) =>
- match p with exP_intro X HX => X end).
-Error:
-Incorrect elimination of "p" in the inductive type
-"ex_Prop", the return type has sort "Type" while it should be
-"Prop"
-
-Elimination of an inductive object of sort "Prop"
-is not allowed on a predicate in sort "Type"
-because proofs can be eliminated only to build proofs
-
-*)
-
-
-Inductive typ : Type :=
- typ_intro : Type -> typ.
-
-Definition typ_inject: typ.
-split.
-Fail exact typ.
-(*
-Error: Universe Inconsistency.
-*)
-Abort.
-(*
-
-Inductive aSet : Set :=
- aSet_intro: Set -> aSet.
-
-
-User error: Large non-propositional inductive types must be in Type
-
-*)
-
-Inductive ex_Set (P : Set -> Prop) : Type :=
- exS_intro : forall X : Set, P X -> ex_Set P.
-
-
-Inductive comes_from_the_left (P Q:Prop): P \/ Q -> Prop :=
- c1 : forall p, comes_from_the_left P Q (or_introl (A:=P) Q p).
-
-Goal (comes_from_the_left _ _ (or_introl True I)).
-split.
-Qed.
-
-Goal ~(comes_from_the_left _ _ (or_intror True I)).
- red;inversion 1.
- (* discriminate H0.
- *)
-Abort.
-
-Reset comes_from_the_left.
-
-(*
-
-
-
-
-
-
- Definition comes_from_the_left (P Q:Prop)(H:P \/ Q): Prop :=
- match H with
- | or_introl p => True
- | or_intror q => False
- end.
-
-Error:
-Incorrect elimination of "H" in the inductive type
-"or", the return type has sort "Type" while it should be
-"Prop"
-
-Elimination of an inductive object of sort "Prop"
-is not allowed on a predicate in sort "Type"
-because proofs can be eliminated only to build proofs
-
-*)
-
-Definition comes_from_the_left_sumbool
- (P Q:Prop)(x:{P}+{Q}): Prop :=
- match x with
- | left p => True
- | right q => False
- end.
-
-
-
-
-Close Scope Z_scope.
-
-
-
-
-
-Theorem S_is_not_O : forall n, S n <> 0.
-
-Definition Is_zero (x:nat):= match x with
- | 0 => True
- | _ => False
- end.
- Lemma O_is_zero : forall m, m = 0 -> Is_zero m.
- Proof.
- intros m H; subst m.
- (*
- ============================
- Is_zero 0
- *)
- simpl;trivial.
- Qed.
-
- red; intros n Hn.
- apply O_is_zero with (m := S n).
- assumption.
-Qed.
-
-Theorem disc2 : forall n, S (S n) <> 1.
-Proof.
- intros n Hn; discriminate.
-Qed.
-
-
-Theorem disc3 : forall n, S (S n) = 0 -> forall Q:Prop, Q.
-Proof.
- intros n Hn Q.
- discriminate.
-Qed.
-
-
-
-Theorem inj_succ : forall n m, S n = S m -> n = m.
-Proof.
-
-
-Lemma inj_pred : forall n m, n = m -> pred n = pred m.
-Proof.
- intros n m eq_n_m.
- rewrite eq_n_m.
- trivial.
-Qed.
-
- intros n m eq_Sn_Sm.
- apply inj_pred with (n:= S n) (m := S m); assumption.
-Qed.
-
-Lemma list_inject : forall (A:Type)(a b :A)(l l':list A),
- a :: b :: l = b :: a :: l' -> a = b /\ l = l'.
-Proof.
- intros A a b l l' e.
- injection e.
- auto.
-Qed.
-
-
-Theorem not_le_Sn_0 : forall n:nat, ~ (S n <= 0).
-Proof.
- red; intros n H.
- case H.
-Undo.
-
-Lemma not_le_Sn_0_with_constraints :
- forall n p , S n <= p -> p = 0 -> False.
-Proof.
- intros n p H; case H ;
- intros; discriminate.
-Qed.
-
-eapply not_le_Sn_0_with_constraints; eauto.
-Qed.
-
-
-Theorem not_le_Sn_0' : forall n:nat, ~ (S n <= 0).
-Proof.
- red; intros n H ; inversion H.
-Qed.
-
-Derive Inversion le_Sn_0_inv with (forall n :nat, S n <= 0).
-Check le_Sn_0_inv.
-
-Theorem le_Sn_0'' : forall n p : nat, ~ S n <= 0 .
-Proof.
- intros n p H;
- inversion H using le_Sn_0_inv.
-Qed.
-
-Derive Inversion_clear le_Sn_0_inv' with (forall n :nat, S n <= 0).
-Check le_Sn_0_inv'.
-
-
-Theorem le_reverse_rules :
- forall n m:nat, n <= m ->
- n = m \/
- exists p, n <= p /\ m = S p.
-Proof.
- intros n m H; inversion H.
- left;trivial.
- right; exists m0; split; trivial.
-Restart.
- intros n m H; inversion_clear H.
- left;trivial.
- right; exists m0; split; trivial.
-Qed.
-
-Inductive ArithExp : Set :=
- Zero : ArithExp
- | Succ : ArithExp -> ArithExp
- | Plus : ArithExp -> ArithExp -> ArithExp.
-
-Inductive RewriteRel : ArithExp -> ArithExp -> Prop :=
- RewSucc : forall e1 e2 :ArithExp,
- RewriteRel e1 e2 -> RewriteRel (Succ e1) (Succ e2)
- | RewPlus0 : forall e:ArithExp,
- RewriteRel (Plus Zero e) e
- | RewPlusS : forall e1 e2:ArithExp,
- RewriteRel e1 e2 ->
- RewriteRel (Plus (Succ e1) e2) (Succ (Plus e1 e2)).
-
-
-
-Fixpoint plus (n p:nat) {struct n} : nat :=
- match n with
- | 0 => p
- | S m => S (plus m p)
- end.
-
-Fixpoint plus' (n p:nat) {struct p} : nat :=
- match p with
- | 0 => n
- | S q => S (plus' n q)
- end.
-
-Fixpoint plus'' (n p:nat) {struct n} : nat :=
- match n with
- | 0 => p
- | S m => plus'' m (S p)
- end.
-
-
-Fixpoint even_test (n:nat) : bool :=
- match n
- with 0 => true
- | 1 => false
- | S (S p) => even_test p
- end.
-
-
-Reset even_test.
-
-Fixpoint even_test (n:nat) : bool :=
- match n
- with
- | 0 => true
- | S p => odd_test p
- end
-with odd_test (n:nat) : bool :=
- match n
- with
- | 0 => false
- | S p => even_test p
- end.
-
-
-
-Eval simpl in even_test.
-
-
-
-Eval simpl in (fun x : nat => even_test x).
-
-Eval simpl in (fun x : nat => plus 5 x).
-Eval simpl in (fun x : nat => even_test (plus 5 x)).
-
-Eval simpl in (fun x : nat => even_test (plus x 5)).
-
-
-Section Principle_of_Induction.
-Variable P : nat -> Prop.
-Hypothesis base_case : P 0.
-Hypothesis inductive_step : forall n:nat, P n -> P (S n).
-Fixpoint nat_ind (n:nat) : (P n) :=
- match n return P n with
- | 0 => base_case
- | S m => inductive_step m (nat_ind m)
- end.
-
-End Principle_of_Induction.
-
-Scheme Even_induction := Minimality for even Sort Prop
-with Odd_induction := Minimality for odd Sort Prop.
-
-Theorem even_plus_four : forall n:nat, even n -> even (4+n).
-Proof.
- intros n H.
- elim H using Even_induction with (P0 := fun n => odd (4+n));
- simpl;repeat constructor;assumption.
-Qed.
-
-
-Section Principle_of_Double_Induction.
-Variable P : nat -> nat ->Prop.
-Hypothesis base_case1 : forall x:nat, P 0 x.
-Hypothesis base_case2 : forall x:nat, P (S x) 0.
-Hypothesis inductive_step : forall n m:nat, P n m -> P (S n) (S m).
-Fixpoint nat_double_ind (n m:nat){struct n} : P n m :=
- match n, m return P n m with
- | 0 , x => base_case1 x
- | (S x), 0 => base_case2 x
- | (S x), (S y) => inductive_step x y (nat_double_ind x y)
- end.
-End Principle_of_Double_Induction.
-
-Section Principle_of_Double_Recursion.
-Variable P : nat -> nat -> Type.
-Hypothesis base_case1 : forall x:nat, P 0 x.
-Hypothesis base_case2 : forall x:nat, P (S x) 0.
-Hypothesis inductive_step : forall n m:nat, P n m -> P (S n) (S m).
-Fixpoint nat_double_rect (n m:nat){struct n} : P n m :=
- match n, m return P n m with
- | 0 , x => base_case1 x
- | (S x), 0 => base_case2 x
- | (S x), (S y) => inductive_step x y (nat_double_rect x y)
- end.
-End Principle_of_Double_Recursion.
-
-Definition min : nat -> nat -> nat :=
- nat_double_rect (fun (x y:nat) => nat)
- (fun (x:nat) => 0)
- (fun (y:nat) => 0)
- (fun (x y r:nat) => S r).
-
-Eval compute in (min 5 8).
-Eval compute in (min 8 5).
-
-
-
-Lemma not_circular : forall n:nat, n <> S n.
-Proof.
- intro n.
- apply nat_ind with (P:= fun n => n <> S n).
- discriminate.
- red; intros n0 Hn0 eqn0Sn0;injection eqn0Sn0;trivial.
-Qed.
-
-Definition eq_nat_dec : forall n p:nat , {n=p}+{n <> p}.
-Proof.
- intros n p.
- apply nat_double_rect with (P:= fun (n q:nat) => {q=p}+{q <> p}).
-Undo.
- pattern p,n.
- elim n using nat_double_rect.
- destruct x; auto.
- destruct x; auto.
- intros n0 m H; case H.
- intro eq; rewrite eq ; auto.
- intro neg; right; red ; injection 1; auto.
-Defined.
-
-Definition eq_nat_dec' : forall n p:nat, {n=p}+{n <> p}.
- decide equality.
-Defined.
-
-
-
-Require Import Le.
-Lemma le'_le : forall n p, le' n p -> n <= p.
-Proof.
- induction 1;auto with arith.
-Qed.
-
-Lemma le'_n_Sp : forall n p, le' n p -> le' n (S p).
-Proof.
- induction 1;auto.
-Qed.
-
-Hint Resolve le'_n_Sp.
-
-
-Lemma le_le' : forall n p, n<=p -> le' n p.
-Proof.
- induction 1;auto with arith.
-Qed.
-
-
-Print Acc.
-
-
-Require Import Minus.
-
-(*
-Fixpoint div (x y:nat){struct x}: nat :=
- if eq_nat_dec x 0
- then 0
- else if eq_nat_dec y 0
- then x
- else S (div (x-y) y).
-
-Error:
-Recursive definition of div is ill-formed.
-In environment
-div : nat -> nat -> nat
-x : nat
-y : nat
-_ : x <> 0
-_ : y <> 0
-
-Recursive call to div has principal argument equal to
-"x - y"
-instead of a subterm of x
-
-*)
-
-Lemma minus_smaller_S: forall x y:nat, x - y < S x.
-Proof.
- intros x y; pattern y, x;
- elim x using nat_double_ind.
- destruct x0; auto with arith.
- simpl; auto with arith.
- simpl; auto with arith.
-Qed.
-
-Lemma minus_smaller_positive : forall x y:nat, x <>0 -> y <> 0 ->
- x - y < x.
-Proof.
- destruct x; destruct y;
- ( simpl;intros; apply minus_smaller_S ||
- intros; absurd (0=0); auto).
-Qed.
-
-Definition minus_decrease : forall x y:nat, Acc lt x ->
- x <> 0 ->
- y <> 0 ->
- Acc lt (x-y).
-Proof.
- intros x y H; case H.
- intros Hz posz posy.
- apply Hz; apply minus_smaller_positive; assumption.
-Defined.
-
-Print minus_decrease.
-
-
-Definition div_aux (x y:nat)(H: Acc lt x):nat.
- fix div_aux 3.
- intros.
- refine (if eq_nat_dec x 0
- then 0
- else if eq_nat_dec y 0
- then y
- else div_aux (x-y) y _).
- apply (minus_decrease x y H);assumption.
-Defined.
-
-
-Print div_aux.
-(*
-div_aux =
-(fix div_aux (x y : nat) (H : Acc lt x) {struct H} : nat :=
- match eq_nat_dec x 0 with
- | left _ => 0
- | right _ =>
- match eq_nat_dec y 0 with
- | left _ => y
- | right _0 => div_aux (x - y) y (minus_decrease x y H _ _0)
- end
- end)
- : forall x : nat, nat -> Acc lt x -> nat
-*)
-
-Require Import Wf_nat.
-Definition div x y := div_aux x y (lt_wf x).
-
-Extraction div.
-(*
-let div x y =
- div_aux x y
-*)
-
-Extraction div_aux.
-
-(*
-let rec div_aux x y =
- match eq_nat_dec x O with
- | Left -> O
- | Right ->
- (match eq_nat_dec y O with
- | Left -> y
- | Right -> div_aux (minus x y) y)
-*)
-
-Lemma vector0_is_vnil : forall (A:Type)(v:Vector.t A 0), v = Vector.nil A.
-Proof.
- intros A v;inversion v.
-Abort.
-
-(*
- Lemma vector0_is_vnil_aux : forall (A:Type)(n:nat)(v:Vector.t A n),
- n= 0 -> v = Vector.nil A.
-
-Toplevel input, characters 40281-40287
-> Lemma vector0_is_vnil_aux : forall (A:Set)(n:nat)(v:Vector.t A n), n= 0 -> v = Vector.nil A.
-> ^^^^^^
-Error: In environment
-A : Set
-n : nat
-v : Vector.t A n
-e : n = 0
-The term "Vector.nil A" has type "Vector.t A 0" while it is expected to have type
- "Vector.t A n"
-*)
- Require Import JMeq.
-
-
-(* On devrait changer Set en Type ? *)
-
-Lemma vector0_is_vnil_aux : forall (A:Type)(n:nat)(v:Vector.t A n),
- n= 0 -> JMeq v (Vector.nil A).
-Proof.
- destruct v.
- auto.
- intro; discriminate.
-Qed.
-
-Lemma vector0_is_vnil : forall (A:Type)(v:Vector.t A 0), v = Vector.nil A.
-Proof.
- intros a v;apply JMeq_eq.
- apply vector0_is_vnil_aux.
- trivial.
-Qed.
-
-
-Implicit Arguments Vector.cons [A n].
-Implicit Arguments Vector.nil [A].
-Implicit Arguments Vector.hd [A n].
-Implicit Arguments Vector.tl [A n].
-
-Definition Vid : forall (A : Type)(n:nat), Vector.t A n -> Vector.t A n.
-Proof.
- destruct n; intro v.
- exact Vector.nil.
- exact (Vector.cons (Vector.hd v) (Vector.tl v)).
-Defined.
-
-Eval simpl in (fun (A:Type)(v:Vector.t A 0) => (Vid _ _ v)).
-
-Eval simpl in (fun (A:Type)(v:Vector.t A 0) => v).
-
-
-
-Lemma Vid_eq : forall (n:nat) (A:Type)(v:Vector.t A n), v=(Vid _ n v).
-Proof.
- destruct v.
- reflexivity.
- reflexivity.
-Defined.
-
-Theorem zero_nil : forall A (v:Vector.t A 0), v = Vector.nil.
-Proof.
- intros.
- change (Vector.nil (A:=A)) with (Vid _ 0 v).
- apply Vid_eq.
-Defined.
-
-
-Theorem decomp :
- forall (A : Type) (n : nat) (v : Vector.t A (S n)),
- v = Vector.cons (Vector.hd v) (Vector.tl v).
-Proof.
- intros.
- change (Vector.cons (Vector.hd v) (Vector.tl v)) with (Vid _ (S n) v).
- apply Vid_eq.
-Defined.
-
-
-
-Definition vector_double_rect :
- forall (A:Type) (P: forall (n:nat),(Vector.t A n)->(Vector.t A n) -> Type),
- P 0 Vector.nil Vector.nil ->
- (forall n (v1 v2 : Vector.t A n) a b, P n v1 v2 ->
- P (S n) (Vector.cons a v1) (Vector.cons b v2)) ->
- forall n (v1 v2 : Vector.t A n), P n v1 v2.
- induction n.
- intros; rewrite (zero_nil _ v1); rewrite (zero_nil _ v2).
- auto.
- intros v1 v2; rewrite (decomp _ _ v1);rewrite (decomp _ _ v2).
- apply X0; auto.
-Defined.
-
-Require Import Bool.
-
-Definition bitwise_or n v1 v2 : Vector.t bool n :=
- vector_double_rect bool (fun n v1 v2 => Vector.t bool n)
- Vector.nil
- (fun n v1 v2 a b r => Vector.cons (orb a b) r) n v1 v2.
-
-Fixpoint vector_nth (A:Type)(n:nat)(p:nat)(v:Vector.t A p){struct v}
- : option A :=
- match n,v with
- _ , Vector.nil => None
- | 0 , Vector.cons b _ => Some b
- | S n', @Vector.cons _ _ p' v' => vector_nth A n' p' v'
- end.
-
-Implicit Arguments vector_nth [A p].
-
-
-Lemma nth_bitwise : forall (n:nat) (v1 v2: Vector.t bool n) i a b,
- vector_nth i v1 = Some a ->
- vector_nth i v2 = Some b ->
- vector_nth i (bitwise_or _ v1 v2) = Some (orb a b).
-Proof.
- intros n v1 v2; pattern n,v1,v2.
- apply vector_double_rect.
- simpl.
- destruct i; discriminate 1.
- destruct i; simpl;auto.
- injection 1; injection 2;intros; subst a; subst b; auto.
-Qed.
-
- Set Implicit Arguments.
-
- CoInductive Stream (A:Type) : Type :=
- | Cons : A -> Stream A -> Stream A.
-
- CoInductive LList (A: Type) : Type :=
- | LNil : LList A
- | LCons : A -> LList A -> LList A.
-
-
-
-
-
- Definition head (A:Type)(s : Stream A) := match s with Cons a s' => a end.
-
- Definition tail (A : Type)(s : Stream A) :=
- match s with Cons a s' => s' end.
-
- CoFixpoint repeat (A:Type)(a:A) : Stream A := Cons a (repeat a).
-
- CoFixpoint iterate (A: Type)(f: A -> A)(a : A) : Stream A:=
- Cons a (iterate f (f a)).
-
- CoFixpoint map (A B:Type)(f: A -> B)(s : Stream A) : Stream B:=
- match s with Cons a tl => Cons (f a) (map f tl) end.
-
-Eval simpl in (fun (A:Type)(a:A) => repeat a).
-
-Eval simpl in (fun (A:Type)(a:A) => head (repeat a)).
-
-
-CoInductive EqSt (A: Type) : Stream A -> Stream A -> Prop :=
- eqst : forall s1 s2: Stream A,
- head s1 = head s2 ->
- EqSt (tail s1) (tail s2) ->
- EqSt s1 s2.
-
-
-Section Parks_Principle.
-Variable A : Type.
-Variable R : Stream A -> Stream A -> Prop.
-Hypothesis bisim1 : forall s1 s2:Stream A, R s1 s2 ->
- head s1 = head s2.
-Hypothesis bisim2 : forall s1 s2:Stream A, R s1 s2 ->
- R (tail s1) (tail s2).
-
-CoFixpoint park_ppl : forall s1 s2:Stream A, R s1 s2 ->
- EqSt s1 s2 :=
- fun s1 s2 (p : R s1 s2) =>
- eqst s1 s2 (bisim1 p)
- (park_ppl (bisim2 p)).
-End Parks_Principle.
-
-
-Theorem map_iterate : forall (A:Type)(f:A->A)(x:A),
- EqSt (iterate f (f x)) (map f (iterate f x)).
-Proof.
- intros A f x.
- apply park_ppl with
- (R:= fun s1 s2 => exists x: A,
- s1 = iterate f (f x) /\ s2 = map f (iterate f x)).
-
- intros s1 s2 (x0,(eqs1,eqs2));rewrite eqs1;rewrite eqs2;reflexivity.
- intros s1 s2 (x0,(eqs1,eqs2)).
- exists (f x0);split;[rewrite eqs1|rewrite eqs2]; reflexivity.
- exists x;split; reflexivity.
-Qed.
-
-Ltac infiniteproof f :=
- cofix f; constructor; [clear f| simpl; try (apply f; clear f)].
-
-
-Theorem map_iterate' : forall (A:Type)(f:A->A)(x:A),
- EqSt (iterate f (f x)) (map f (iterate f x)).
-infiniteproof map_iterate'.
- reflexivity.
-Qed.
-
-
-Implicit Arguments LNil [A].
-
-Lemma Lnil_not_Lcons : forall (A:Type)(a:A)(l:LList A),
- LNil <> (LCons a l).
- intros;discriminate.
-Qed.
-
-Lemma injection_demo : forall (A:Type)(a b : A)(l l': LList A),
- LCons a (LCons b l) = LCons b (LCons a l') ->
- a = b /\ l = l'.
-Proof.
- intros A a b l l' e; injection e; auto.
-Qed.
-
-
-Inductive Finite (A:Type) : LList A -> Prop :=
-| Lnil_fin : Finite (LNil (A:=A))
-| Lcons_fin : forall a l, Finite l -> Finite (LCons a l).
-
-CoInductive Infinite (A:Type) : LList A -> Prop :=
-| LCons_inf : forall a l, Infinite l -> Infinite (LCons a l).
-
-Lemma LNil_not_Infinite : forall (A:Type), ~ Infinite (LNil (A:=A)).
-Proof.
- intros A H;inversion H.
-Qed.
-
-Lemma Finite_not_Infinite : forall (A:Type)(l:LList A),
- Finite l -> ~ Infinite l.
-Proof.
- intros A l H; elim H.
- apply LNil_not_Infinite.
- intros a l0 F0 I0' I1.
- case I0'; inversion_clear I1.
- trivial.
-Qed.
-
-Lemma Not_Finite_Infinite : forall (A:Type)(l:LList A),
- ~ Finite l -> Infinite l.
-Proof.
- cofix H.
- destruct l.
- intro; absurd (Finite (LNil (A:=A)));[auto|constructor].
- constructor.
- apply H.
- red; intro H1;case H0.
- constructor.
- trivial.
-Qed.
-
-
-
diff --git a/doc/RecTutorial/coqartmacros.tex b/doc/RecTutorial/coqartmacros.tex
deleted file mode 100644
index 72d749269..000000000
--- a/doc/RecTutorial/coqartmacros.tex
+++ /dev/null
@@ -1,180 +0,0 @@
-\usepackage{url}
-
-\newcommand{\variantspringer}[1]{#1}
-\newcommand{\marginok}[1]{\marginpar{\raggedright OK:#1}}
-\newcommand{\tab}{{\null\hskip1cm}}
-\newcommand{\Ltac}{\mbox{\emph{$\cal L$}tac}}
-\newcommand{\coq}{\mbox{\emph{Coq}}}
-\newcommand{\lcf}{\mbox{\emph{LCF}}}
-\newcommand{\hol}{\mbox{\emph{HOL}}}
-\newcommand{\pvs}{\mbox{\emph{PVS}}}
-\newcommand{\isabelle}{\mbox{\emph{Isabelle}}}
-\newcommand{\prolog}{\mbox{\emph{Prolog}}}
-\newcommand{\goalbar}{\tt{}============================\it}
-\newcommand{\gallina}{\mbox{\emph{Gallina}}}
-\newcommand{\joker}{\texttt{\_}}
-\newcommand{\eprime}{\(\e^{\prime}\)}
-\newcommand{\Ztype}{\citecoq{Z}}
-\newcommand{\propsort}{\citecoq{Prop}}
-\newcommand{\setsort}{\citecoq{Set}}
-\newcommand{\typesort}{\citecoq{Type}}
-\newcommand{\ocaml}{\mbox{\emph{OCAML}}}
-\newcommand{\haskell}{\mbox{\emph{Haskell}}}
-\newcommand{\why}{\mbox{\emph{Why}}}
-\newcommand{\Pascal}{\mbox{\emph{Pascal}}}
-
-\newcommand{\ml}{\mbox{\emph{ML}}}
-
-\newcommand{\scheme}{\mbox{\emph{Scheme}}}
-\newcommand{\lisp}{\mbox{\emph{Lisp}}}
-
-\newcommand{\implarrow}{\mbox{$\Rightarrow$}}
-\newcommand{\metavar}[1]{?#1}
-\newcommand{\notincoq}[1]{#1}
-\newcommand{\coqscope}[1]{\%#1}
-\newcommand{\arrow}{\mbox{$\rightarrow$}}
-\newcommand{\fleche}{\arrow}
-\newcommand{\funarrow}{\mbox{$\Rightarrow$}}
-\newcommand{\ltacarrow}{\funarrow}
-\newcommand{\coqand}{\mbox{\(\wedge\)}}
-\newcommand{\coqor}{\mbox{\(\vee\)}}
-\newcommand{\coqnot}{\mbox{\(\neg\)}}
-\newcommand{\hide}[1]{}
-\newcommand{\hidedots}[1]{...}
-\newcommand{\sig}[3]{\texttt{\{}#1\texttt{:}#2 \texttt{|} #3\texttt{\}}}
-\renewcommand{\neg}{\sim}
-\renewcommand{\marginpar}[1]{}
-
-\addtocounter{secnumdepth}{1}
-\providecommand{\og}{«}
-\providecommand{\fg}{»}
-
-
-\newcommand{\hard}{\mbox{\small *}}
-\newcommand{\xhard}{\mbox{\small **}}
-\newcommand{\xxhard}{\mbox{\small ***}}
-
-%%% Operateurs, etc.
-\newcommand{\impl}{\mbox{$\rightarrow$}}
-\newcommand{\appli}[2]{\mbox{\tt{#1 #2}}}
-\newcommand{\applis}[1]{\mbox{\texttt{#1}}}
-\newcommand{\abst}[3]{\mbox{\tt{fun #1:#2 \funarrow #3}}}
-\newcommand{\coqle}{\mbox{$\leq$}}
-\newcommand{\coqge}{\mbox{$\geq$}}
-\newcommand{\coqdiff}{\mbox{$\neq$}}
-\newcommand{\coqiff}{\mbox{$\leftrightarrow$}}
-\newcommand{\prodsym}{\mbox{\(\forall\,\)}}
-\newcommand{\exsym}{\mbox{\(\exists\,\)}}
-
-\newcommand{\substsign}{/}
-\newcommand{\subst}[3]{\mbox{#1\{#2\substsign{}#3\}}}
-\newcommand{\anoabst}[2]{\mbox{\tt[#1]#2}}
-\newcommand{\letin}[3]{\mbox{\tt let #1:=#2 in #3}}
-\newcommand{\prodep}[3]{\mbox{\tt \(\forall\,\)#1:#2,$\,$#3}}
-\newcommand{\prodplus}[2]{\mbox{\tt\(\forall\,\)$\,$#1,$\,$#2}}
-\newcommand{\dom}[1]{\textrm{dom}(#1)} % domaine d'un contexte (log function)
-\newcommand{\norm}[1]{\textrm{n}(#1)} % forme normale (log function)
-\newcommand{\coqZ}[1]{\mbox{\tt{`#1`}}}
-\newcommand{\coqnat}[1]{\mbox{\tt{#1}}}
-\newcommand{\coqcart}[2]{\mbox{\tt{#1*#2}}}
-\newcommand{\alphacong}{\mbox{$\,\cong_{\alpha}\,$}} % alpha-congruence
-\newcommand{\betareduc}{\mbox{$\,\rightsquigarrow_{\!\beta}$}\,} % beta reduction
-%\newcommand{\betastar}{\mbox{$\,\Rightarrow_{\!\beta}^{*}\,$}} % beta reduction
-\newcommand{\deltareduc}{\mbox{$\,\rightsquigarrow_{\!\delta}$}\,} % delta reduction
-\newcommand{\dbreduc}{\mbox{$\,\rightsquigarrow_{\!\delta\beta}$}\,} % delta,beta reduction
-\newcommand{\ireduc}{\mbox{$\,\rightsquigarrow_{\!\iota}$}\,} % delta,beta reduction
-
-
-% jugement de typage
-\newcommand{\these}{\boldsymbol{\large \vdash}}
-\newcommand{\disj}{\mbox{$\backslash/$}}
-\newcommand{\conj}{\mbox{$/\backslash$}}
-%\newcommand{\juge}[3]{\mbox{$#1 \boldsymbol{\vdash} #2 : #3 $}}
-\newcommand{\juge}[4]{\mbox{$#1,#2 \these #3 \boldsymbol{:} #4 $}}
-\newcommand{\smalljuge}[3]{\mbox{$#1 \these #2 \boldsymbol{:} #3 $}}
-\newcommand{\goal}[3]{\mbox{$#1,#2 \these^{\!\!\!?} #3 $}}
-\newcommand{\sgoal}[2]{\mbox{$#1\these^{\!\!\!\!?} #2 $}}
-\newcommand{\reduc}[5]{\mbox{$#1,#2 \these #3 \rhd_{#4}#5 $}}
-\newcommand{\convert}[5]{\mbox{$#1,#2 \these #3 =_{#4}#5 $}}
-\newcommand{\convorder}[5]{\mbox{$#1,#2 \these #3\leq _{#4}#5 $}}
-\newcommand{\wouff}[2]{\mbox{$\emph{WF}(#1)[#2]$}}
-
-
-%\newcommand{\mthese}{\underset{M}{\vdash}}
-\newcommand{\mthese}{\boldsymbol{\vdash}_{\!\!M}}
-\newcommand{\type}{\boldsymbol{:}}
-
-% jugement absolu
-
-%\newcommand{\ajuge}[2]{\mbox{$ \boldsymbol{\vdash} #1 : #2 $}}
-\newcommand{\ajuge}[2]{\mbox{$\these #1 \boldsymbol{:} #2 $}}
-
-%%% logique minimale
-\newcommand{\propzero}{\mbox{$P_0$}} % types de Fzero
-
-%%% logique propositionnelle classique
-\newcommand {\ff}{\boldsymbol{f}} % faux
-\newcommand {\vv}{\boldsymbol{t}} % vrai
-
-\newcommand{\verite}{\mbox{$\cal{B}$}} % {\ff,\vv}
-\newcommand{\sequ}[2]{\mbox{$#1 \vdash #2 $}} % sequent
-\newcommand{\strip}[1]{#1^o} % enlever les variables d'un contexte
-
-
-
-%%% tactiques
-\newcommand{\decomp}{\delta} % decomposition
-\newcommand{\recomp}{\rho} % recomposition
-
-%%% divers
-\newcommand{\cqfd}{\mbox{\textbf{cqfd}}}
-\newcommand{\fail}{\mbox{\textbf{F}}}
-\newcommand{\succes}{\mbox{$\blacksquare$}}
-%%% Environnements
-
-
-%% Fzero
-\newcommand{\con}{\mbox{$\cal C$}}
-\newcommand{\var}{\mbox{$\cal V$}}
-
-\newcommand{\atomzero}{\mbox{${\cal A}_0$}} % types de base de Fzero
-\newcommand{\typezero}{\mbox{${\cal T}_0$}} % types de Fzero
-\newcommand{\termzero}{\mbox{$\Lambda_0$}} % termes de Fzero
-\newcommand{\conzero}{\mbox{$\cal C_0$}} % contextes de Fzero
-
-\newcommand{\buts}{\mbox{$\cal B$}} % buts
-
-%%% for drawing terms
-% abstraction [x:t]e
-\newcommand{\PicAbst}[3]{\begin{bundle}{\bf abst}\chunk{#1}\chunk{#2}\chunk{#3}%
- \end{bundle}}
-
-% the same in de Bruijn form
-\newcommand{\PicDbj}[2]{\begin{bundle}{\bf abst}\chunk{#1}\chunk{#2}
- \end{bundle}}
-
-
-% applications
-\newcommand{\PicAppl}[2]{\begin{bundle}{\bf appl}\chunk{#1}\chunk{#2}%
- \end{bundle}}
-
-% variables
-\newcommand{\PicVar}[1]{\begin{bundle}{\bf var}\chunk{#1}
- \end{bundle}}
-
-% constantes
-\newcommand{\PicCon}[1]{\begin{bundle}{\bf const}\chunk{#1}\end{bundle}}
-
-% arrows
-\newcommand{\PicImpl}[2]{\begin{bundle}{\impl}\chunk{#1}\chunk{#2}%
- \end{bundle}}
-
-
-
-%%%% scripts coq
-\newcommand{\prompt}{\mbox{\sl Coq $<\;$}}
-\newcommand{\natquicksort}{\texttt{nat\_quicksort}}
-\newcommand{\citecoq}[1]{\mbox{\texttt{#1}}}
-\newcommand{\safeit}{\it}
-\newtheorem{remarque}{Remark}[section]
-%\newtheorem{definition}{Definition}[chapter]
diff --git a/doc/RecTutorial/manbiblio.bib b/doc/RecTutorial/manbiblio.bib
deleted file mode 100644
index caee81782..000000000
--- a/doc/RecTutorial/manbiblio.bib
+++ /dev/null
@@ -1,870 +0,0 @@
-
-@STRING{toappear="To appear"}
-@STRING{lncs="Lecture Notes in Computer Science"}
-
-@TECHREPORT{RefManCoq,
- AUTHOR = {Bruno~Barras, Samuel~Boutin,
- Cristina~Cornes, Judicaël~Courant, Yann~Coscoy, David~Delahaye,
- Daniel~de~Rauglaudre, Jean-Christophe~Filliâtre, Eduardo~Giménez,
- Hugo~Herbelin, Gérard~Huet, Henri~Laulhère, César~Muñoz,
- Chetan~Murthy, Catherine~Parent-Vigouroux, Patrick~Loiseleur,
- Christine~Paulin-Mohring, Amokrane~Saïbi, Benjamin~Werner},
- INSTITUTION = {INRIA},
- TITLE = {{The Coq Proof Assistant Reference Manual -- Version V6.2}},
- YEAR = {1998}
-}
-
-@INPROCEEDINGS{Aud91,
- AUTHOR = {Ph. Audebaud},
- BOOKTITLE = {Proceedings of the sixth Conf. on Logic in Computer Science.},
- PUBLISHER = {IEEE},
- TITLE = {Partial {Objects} in the {Calculus of Constructions}},
- YEAR = {1991}
-}
-
-@PHDTHESIS{Aud92,
- AUTHOR = {Ph. Audebaud},
- SCHOOL = {{Universit\'e} Bordeaux I},
- TITLE = {Extension du Calcul des Constructions par Points fixes},
- YEAR = {1992}
-}
-
-@INPROCEEDINGS{Audebaud92b,
- AUTHOR = {Ph. Audebaud},
- BOOKTITLE = {{Proceedings of the 1992 Workshop on Types for Proofs and Programs}},
- EDITOR = {{B. Nordstr\"om and K. Petersson and G. Plotkin}},
- NOTE = {Also Research Report LIP-ENS-Lyon},
- PAGES = {pp 21--34},
- TITLE = {{CC+ : an extension of the Calculus of Constructions with fixpoints}},
- YEAR = {1992}
-}
-
-@INPROCEEDINGS{Augustsson85,
- AUTHOR = {L. Augustsson},
- TITLE = {{Compiling Pattern Matching}},
- BOOKTITLE = {Conference Functional Programming and
-Computer Architecture},
- YEAR = {1985}
-}
-
-@INPROCEEDINGS{EG94a,
- AUTHOR = {E. Gim\'enez},
- EDITORS = {P. Dybjer and B. Nordstr\"om and J. Smith},
- BOOKTITLE = {Workshop on Types for Proofs and Programs},
- PAGES = {39-59},
- SERIES = {LNCS},
- NUMBER = {996},
- TITLE = {{Codifying guarded definitions with recursive schemes}},
- YEAR = {1994},
- PUBLISHER = {Springer-Verlag},
-}
-
-@INPROCEEDINGS{EG95a,
- AUTHOR = {E. Gim\'enez},
- BOOKTITLE = {Workshop on Types for Proofs and Programs},
- SERIES = {LNCS},
- NUMBER = {1158},
- PAGES = {135-152},
- TITLE = {An application of co-Inductive types in Coq:
- verification of the Alternating Bit Protocol},
- EDITORS = {S. Berardi and M. Coppo},
- PUBLISHER = {Springer-Verlag},
- YEAR = {1995}
-}
-
-@PhdThesis{EG96,
- author = {E. Gim\'enez},
- title = {A Calculus of Infinite Constructions and its
- application to the verification of communicating systems},
- school = {Ecole Normale Sup\'erieure de Lyon},
- year = {1996}
-}
-
-@ARTICLE{BaCo85,
- AUTHOR = {J.L. Bates and R.L. Constable},
- JOURNAL = {ACM transactions on Programming Languages and Systems},
- TITLE = {Proofs as {Programs}},
- VOLUME = {7},
- YEAR = {1985}
-}
-
-@BOOK{Bar81,
- AUTHOR = {H.P. Barendregt},
- PUBLISHER = {North-Holland},
- TITLE = {The Lambda Calculus its Syntax and Semantics},
- YEAR = {1981}
-}
-
-@TECHREPORT{Bar91,
- AUTHOR = {H. Barendregt},
- INSTITUTION = {Catholic University Nijmegen},
- NOTE = {In Handbook of Logic in Computer Science, Vol II},
- NUMBER = {91-19},
- TITLE = {Lambda {Calculi with Types}},
- YEAR = {1991}
-}
-
-@BOOK{Bastad92,
- EDITOR = {B. Nordstr\"om and K. Petersson and G. Plotkin},
- PUBLISHER = {Available by ftp at site ftp.inria.fr},
- TITLE = {Proceedings of the 1992 Workshop on Types for Proofs and Programs},
- YEAR = {1992}
-}
-
-@BOOK{Bee85,
- AUTHOR = {M.J. Beeson},
- PUBLISHER = {Springer-Verlag},
- TITLE = {Foundations of Constructive Mathematics, Metamathematical Studies},
- YEAR = {1985}
-}
-
-@ARTICLE{BeKe92,
- AUTHOR = {G. Bellin and J. Ketonen},
- JOURNAL = {Theoretical Computer Science},
- PAGES = {115--142},
- TITLE = {A decision procedure revisited : Notes on direct logic, linear logic and its implementation},
- VOLUME = {95},
- YEAR = {1992}
-}
-
-@BOOK{Bis67,
- AUTHOR = {E. Bishop},
- PUBLISHER = {McGraw-Hill},
- TITLE = {Foundations of Constructive Analysis},
- YEAR = {1967}
-}
-
-@BOOK{BoMo79,
- AUTHOR = {R.S. Boyer and J.S. Moore},
- KEY = {BoMo79},
- PUBLISHER = {Academic Press},
- SERIES = {ACM Monograph},
- TITLE = {A computational logic},
- YEAR = {1979}
-}
-
-@MASTERSTHESIS{Bou92,
- AUTHOR = {S. Boutin},
- MONTH = sep,
- SCHOOL = {{Universit\'e Paris 7}},
- TITLE = {Certification d'un compilateur {ML en Coq}},
- YEAR = {1992}
-}
-
-@ARTICLE{Bru72,
- AUTHOR = {N.J. de Bruijn},
- JOURNAL = {Indag. Math.},
- TITLE = {{Lambda-Calculus Notation with Nameless Dummies, a Tool for Automatic Formula Manipulation, with Application to the Church-Rosser Theorem}},
- VOLUME = {34},
- YEAR = {1972}
-}
-
-@INCOLLECTION{Bru80,
- AUTHOR = {N.J. de Bruijn},
- BOOKTITLE = {to H.B. Curry : Essays on Combinatory Logic, Lambda Calculus and Formalism.},
- EDITOR = {J.P. Seldin and J.R. Hindley},
- PUBLISHER = {Academic Press},
- TITLE = {A survey of the project {Automath}},
- YEAR = {1980}
-}
-
-@TECHREPORT{Leroy90,
- AUTHOR = {X. Leroy},
- TITLE = {The {ZINC} experiment: an economical implementation
-of the {ML} language},
- INSTITUTION = {INRIA},
- NUMBER = {117},
- YEAR = {1990}
-}
-
-@BOOK{Caml,
- AUTHOR = {P. Weis and X. Leroy},
- PUBLISHER = {InterEditions},
- TITLE = {Le langage Caml},
- YEAR = {1993}
-}
-
-@TECHREPORT{CoC89,
- AUTHOR = {Projet Formel},
- INSTITUTION = {INRIA},
- NUMBER = {110},
- TITLE = {{The Calculus of Constructions. Documentation and user's guide, Version 4.10}},
- YEAR = {1989}
-}
-
-@INPROCEEDINGS{CoHu85a,
- AUTHOR = {Th. Coquand and G. Huet},
- ADDRESS = {Linz},
- BOOKTITLE = {EUROCAL'85},
- PUBLISHER = {Springer-Verlag},
- SERIES = {LNCS},
- TITLE = {{Constructions : A Higher Order Proof System for Mechanizing Mathematics}},
- VOLUME = {203},
- YEAR = {1985}
-}
-
-@Misc{Bar98,
- author = {B. Barras},
- title = {A formalisation of
- \uppercase{B}urali-\uppercase{F}orti's paradox in Coq},
- howpublished = {Distributed within the bunch of contribution to the
- Coq system},
- year = {1998},
- month = {March},
- note = {\texttt{http://pauillac.inria.fr/coq}}
-}
-
-
-@INPROCEEDINGS{CoHu85b,
- AUTHOR = {Th. Coquand and G. Huet},
- BOOKTITLE = {Logic Colloquium'85},
- EDITOR = {The Paris Logic Group},
- PUBLISHER = {North-Holland},
- TITLE = {{Concepts Math\'ematiques et Informatiques formalis\'es dans le Calcul des Constructions}},
- YEAR = {1987}
-}
-
-@ARTICLE{CoHu86,
- AUTHOR = {Th. Coquand and G. Huet},
- JOURNAL = {Information and Computation},
- NUMBER = {2/3},
- TITLE = {The {Calculus of Constructions}},
- VOLUME = {76},
- YEAR = {1988}
-}
-
-@BOOK{Con86,
- AUTHOR = {R.L. {Constable et al.}},
- PUBLISHER = {Prentice-Hall},
- TITLE = {{Implementing Mathematics with the Nuprl Proof Development System}},
- YEAR = {1986}
-}
-
-@INPROCEEDINGS{CoPa89,
- AUTHOR = {Th. Coquand and C. Paulin-Mohring},
- BOOKTITLE = {Proceedings of Colog'88},
- EDITOR = {P. Martin-L{\"o}f and G. Mints},
- PUBLISHER = {Springer-Verlag},
- SERIES = {LNCS},
- TITLE = {Inductively defined types},
- VOLUME = {417},
- YEAR = {1990}
-}
-
-@PHDTHESIS{Coq85,
- AUTHOR = {Th. Coquand},
- MONTH = jan,
- SCHOOL = {Universit\'e Paris~7},
- TITLE = {Une Th\'eorie des Constructions},
- YEAR = {1985}
-}
-
-@INPROCEEDINGS{Coq86,
- AUTHOR = {Th. Coquand},
- ADDRESS = {Cambridge, MA},
- BOOKTITLE = {Symposium on Logic in Computer Science},
- PUBLISHER = {IEEE Computer Society Press},
- TITLE = {{An Analysis of Girard's Paradox}},
- YEAR = {1986}
-}
-
-@INPROCEEDINGS{Coq90,
- AUTHOR = {Th. Coquand},
- BOOKTITLE = {Logic and Computer Science},
- EDITOR = {P. Oddifredi},
- NOTE = {INRIA Research Report 1088, also in~\cite{CoC89}},
- PUBLISHER = {Academic Press},
- TITLE = {{Metamathematical Investigations of a Calculus of Constructions}},
- YEAR = {1990}
-}
-
-@INPROCEEDINGS{Coq92,
- AUTHOR = {Th. Coquand},
- BOOKTITLE = {in \cite{Bastad92}},
- TITLE = {{Pattern Matching with Dependent Types}},
- YEAR = {1992},
- crossref = {Bastad92}
-}
-
-@TECHREPORT{COQ93,
- AUTHOR = {G. Dowek and A. Felty and H. Herbelin and G. Huet and C. Murthy and C. Parent and C. Paulin-Mohring and B. Werner},
- INSTITUTION = {INRIA},
- MONTH = may,
- NUMBER = {154},
- TITLE = {{The Coq Proof Assistant User's Guide Version 5.8}},
- YEAR = {1993}
-}
-
-@INPROCEEDINGS{Coquand93,
- AUTHOR = {Th. Coquand},
- BOOKTITLE = {in \cite{Nijmegen93}},
- TITLE = {{Infinite Objects in Type Theory}},
- YEAR = {1993},
- crossref = {Nijmegen93}
-}
-
-@MASTERSTHESIS{Cou94a,
- AUTHOR = {J. Courant},
- MONTH = sep,
- SCHOOL = {DEA d'Informatique, ENS Lyon},
- TITLE = {Explicitation de preuves par r\'ecurrence implicite},
- YEAR = {1994}
-}
-
-@TECHREPORT{CPar93,
- AUTHOR = {C. Parent},
- INSTITUTION = {Ecole {Normale} {Sup\'erieure} de {Lyon}},
- MONTH = oct,
- NOTE = {Also in~\cite{Nijmegen93}},
- NUMBER = {93-29},
- TITLE = {Developing certified programs in the system {Coq}- {The} {Program} tactic},
- YEAR = {1993}
-}
-
-@PHDTHESIS{CPar95,
- AUTHOR = {C. Parent},
- SCHOOL = {Ecole {Normale} {Sup\'erieure} de {Lyon}},
- TITLE = {{Synth\`ese de preuves de programmes dans le Calcul des Constructions Inductives}},
- YEAR = {1995}
-}
-
-@TECHREPORT{Dow90,
- AUTHOR = {G. Dowek},
- INSTITUTION = {INRIA},
- NUMBER = {1283},
- TITLE = {{Naming and Scoping in a Mathematical Vernacular}},
- TYPE = {Research Report},
- YEAR = {1990}
-}
-
-@ARTICLE{Dow91a,
- AUTHOR = {G. Dowek},
- JOURNAL = {{Compte Rendu de l'Acad\'emie des Sciences}},
- NOTE = {(The undecidability of Third Order Pattern Matching in Calculi with Dependent Types or Type Constructors)},
- NUMBER = {12},
- PAGES = {951--956},
- TITLE = {{L'Ind\'ecidabilit\'e du Filtrage du Troisi\`eme Ordre dans les Calculs avec Types D\'ependants ou Constructeurs de Types}},
- VOLUME = {I, 312},
- YEAR = {1991}
-}
-
-@INPROCEEDINGS{Dow91b,
- AUTHOR = {G. Dowek},
- BOOKTITLE = {Proceedings of Mathematical Foundation of Computer Science},
- NOTE = {Also INRIA Research Report},
- PAGES = {151--160},
- PUBLISHER = {Springer-Verlag},
- SERIES = {LNCS},
- TITLE = {{A Second Order Pattern Matching Algorithm in the Cube of Typed {$\lambda$}-calculi}},
- VOLUME = {520},
- YEAR = {1991}
-}
-
-@PHDTHESIS{Dow91c,
- AUTHOR = {G. Dowek},
- MONTH = dec,
- SCHOOL = {{Universit\'e Paris 7}},
- TITLE = {{D\'emonstration automatique dans le Calcul des Constructions}},
- YEAR = {1991}
-}
-
-@ARTICLE{dowek93,
- AUTHOR = {G. Dowek},
- TITLE = {{A Complete Proof Synthesis Method for the Cube of Type Systems}},
- JOURNAL = {Journal Logic Computation},
- VOLUME = {3},
- NUMBER = {3},
- PAGES = {287--315},
- MONTH = {June},
- YEAR = {1993}
-}
-
-@UNPUBLISHED{Dow92a,
- AUTHOR = {G. Dowek},
- NOTE = {To appear in Theoretical Computer Science},
- TITLE = {{The Undecidability of Pattern Matching in Calculi where Primitive Recursive Functions are Representable}},
- YEAR = {1992}
-}
-
-@ARTICLE{Dow94a,
- AUTHOR = {G. Dowek},
- JOURNAL = {Annals of Pure and Applied Logic},
- VOLUME = {69},
- PAGES = {135--155},
- TITLE = {Third order matching is decidable},
- YEAR = {1994}
-}
-
-@INPROCEEDINGS{Dow94b,
- AUTHOR = {G. Dowek},
- BOOKTITLE = {Proceedings of the second international conference on typed lambda calculus and applications},
- TITLE = {{Lambda-calculus, Combinators and the Comprehension Schema}},
- YEAR = {1995}
-}
-
-@INPROCEEDINGS{Dyb91,
- AUTHOR = {P. Dybjer},
- BOOKTITLE = {Logical Frameworks},
- EDITOR = {G. Huet and G. Plotkin},
- PAGES = {59--79},
- PUBLISHER = {Cambridge University Press},
- TITLE = {{Inductive sets and families in {Martin-L{\"o}f's Type Theory} and their set-theoretic semantics : An inversion principle for {Martin-L\"of's} type theory}},
- VOLUME = {14},
- YEAR = {1991}
-}
-
-@ARTICLE{Dyc92,
- AUTHOR = {Roy Dyckhoff},
- JOURNAL = {The Journal of Symbolic Logic},
- MONTH = sep,
- NUMBER = {3},
- TITLE = {Contraction-free sequent calculi for intuitionistic logic},
- VOLUME = {57},
- YEAR = {1992}
-}
-
-@MASTERSTHESIS{Fil94,
- AUTHOR = {J.-C. Filli\^atre},
- MONTH = sep,
- SCHOOL = {DEA d'Informatique, ENS Lyon},
- TITLE = {Une proc\'edure de d\'ecision pour le {C}alcul des {P}r\'edicats {D}irect. {E}tude et impl\'ementation dans le syst\`eme {C}oq},
- YEAR = {1994}
-}
-
-@TECHREPORT{Filliatre95,
- AUTHOR = {J.-C. Filli\^atre},
- INSTITUTION = {LIP-ENS-Lyon},
- TITLE = {{A decision procedure for Direct Predicate Calculus}},
- TYPE = {Research report},
- NUMBER = {96--25},
- YEAR = {1995}
-}
-
-@UNPUBLISHED{Fle90,
- AUTHOR = {E. Fleury},
- MONTH = jul,
- NOTE = {Rapport de Stage},
- TITLE = {Implantation des algorithmes de {Floyd et de Dijkstra} dans le {Calcul des Constructions}},
- YEAR = {1990}
-}
-
-
-@TechReport{Gim98,
- author = {E. Gim\'nez},
- title = {A Tutorial on Recursive Types in Coq},
- institution = {INRIA},
- year = {1998}
-}
-
-@TECHREPORT{HKP97,
- author = {G. Huet and G. Kahn and Ch. Paulin-Mohring},
- title = {The {Coq} Proof Assistant - A tutorial, Version 6.1},
- institution = {INRIA},
- type = {rapport technique},
- month = {Août},
- year = {1997},
- note = {Version révisée distribuée avec {Coq}},
- number = {204},
-}
-
-@INPROCEEDINGS{Gir70,
- AUTHOR = {J.-Y. Girard},
- BOOKTITLE = {Proceedings of the 2nd Scandinavian Logic Symposium},
- PUBLISHER = {North-Holland},
- TITLE = {Une extension de l'interpr\'etation de {G\"odel} \`a l'analyse, et son application \`a l'\'elimination des coupures dans l'analyse et la th\'eorie des types},
- YEAR = {1970}
-}
-
-@PHDTHESIS{Gir72,
- AUTHOR = {J.-Y. Girard},
- SCHOOL = {Universit\'e Paris~7},
- TITLE = {Interpr\'etation fonctionnelle et \'elimination des coupures de l'arithm\'etique d'ordre sup\'erieur},
- YEAR = {1972}
-}
-
-@BOOK{Gir89,
- AUTHOR = {J.-Y. Girard and Y. Lafont and P. Taylor},
- PUBLISHER = {Cambridge University Press},
- SERIES = {Cambridge Tracts in Theoretical Computer Science 7},
- TITLE = {Proofs and Types},
- YEAR = {1989}
-}
-
-@MASTERSTHESIS{Hir94,
- AUTHOR = {D. Hirschkoff},
- MONTH = sep,
- SCHOOL = {DEA IARFA, Ecole des Ponts et Chauss\'ees, Paris},
- TITLE = {{Ecriture d'une tactique arithm\'etique pour le syst\`eme Coq}},
- YEAR = {1994}
-}
-
-@INCOLLECTION{How80,
- AUTHOR = {W.A. Howard},
- BOOKTITLE = {to H.B. Curry : Essays on Combinatory Logic, Lambda Calculus and Formalism.},
- EDITOR = {J.P. Seldin and J.R. Hindley},
- NOTE = {Unpublished 1969 Manuscript},
- PUBLISHER = {Academic Press},
- TITLE = {The Formulae-as-Types Notion of Constructions},
- YEAR = {1980}
-}
-
-@INCOLLECTION{HuetLevy79,
- AUTHOR = {G. Huet and J.-J. L\'{e}vy},
- TITLE = {Call by Need Computations in Non-Ambigous
-Linear Term Rewriting Systems},
- NOTE = {Also research report 359, INRIA, 1979},
- BOOKTITLE = {Computational Logic, Essays in Honor of
-Alan Robinson},
- EDITOR = {J.-L. Lassez and G. Plotkin},
- PUBLISHER = {The MIT press},
- YEAR = {1991}
-}
-
-@INPROCEEDINGS{Hue87,
- AUTHOR = {G. Huet},
- BOOKTITLE = {Programming of Future Generation Computers},
- EDITOR = {K. Fuchi and M. Nivat},
- NOTE = {Also in Proceedings of TAPSOFT87, LNCS 249, Springer-Verlag, 1987, pp 276--286},
- PUBLISHER = {Elsevier Science},
- TITLE = {Induction Principles Formalized in the {Calculus of Constructions}},
- YEAR = {1988}
-}
-
-@INPROCEEDINGS{Hue88,
- AUTHOR = {G. Huet},
- BOOKTITLE = {A perspective in Theoretical Computer Science. Commemorative Volume for Gift Siromoney},
- EDITOR = {R. Narasimhan},
- NOTE = {Also in~\cite{CoC89}},
- PUBLISHER = {World Scientific Publishing},
- TITLE = {{The Constructive Engine}},
- YEAR = {1989}
-}
-
-@BOOK{Hue89,
- EDITOR = {G. Huet},
- PUBLISHER = {Addison-Wesley},
- SERIES = {The UT Year of Programming Series},
- TITLE = {Logical Foundations of Functional Programming},
- YEAR = {1989}
-}
-
-@INPROCEEDINGS{Hue92,
- AUTHOR = {G. Huet},
- BOOKTITLE = {Proceedings of 12th FST/TCS Conference, New Delhi},
- PAGES = {229--240},
- PUBLISHER = {Springer Verlag},
- SERIES = {LNCS},
- TITLE = {{The Gallina Specification Language : A case study}},
- VOLUME = {652},
- YEAR = {1992}
-}
-
-@ARTICLE{Hue94,
- AUTHOR = {G. Huet},
- JOURNAL = {J. Functional Programming},
- PAGES = {371--394},
- PUBLISHER = {Cambridge University Press},
- TITLE = {Residual theory in $\lambda$-calculus: a formal development},
- VOLUME = {4,3},
- YEAR = {1994}
-}
-
-@ARTICLE{KeWe84,
- AUTHOR = {J. Ketonen and R. Weyhrauch},
- JOURNAL = {Theoretical Computer Science},
- PAGES = {297--307},
- TITLE = {A decidable fragment of {P}redicate {C}alculus},
- VOLUME = {32},
- YEAR = {1984}
-}
-
-@BOOK{Kle52,
- AUTHOR = {S.C. Kleene},
- PUBLISHER = {North-Holland},
- SERIES = {Bibliotheca Mathematica},
- TITLE = {Introduction to Metamathematics},
- YEAR = {1952}
-}
-
-@BOOK{Kri90,
- AUTHOR = {J.-L. Krivine},
- PUBLISHER = {Masson},
- SERIES = {Etudes et recherche en informatique},
- TITLE = {Lambda-calcul {types et mod\`eles}},
- YEAR = {1990}
-}
-
-@ARTICLE{Laville91,
- AUTHOR = {A. Laville},
- TITLE = {Comparison of Priority Rules in Pattern
-Matching and Term Rewriting},
- JOURNAL = {Journal of Symbolic Computation},
- VOLUME = {11},
- PAGES = {321--347},
- YEAR = {1991}
-}
-
-@BOOK{LE92,
- EDITOR = {G. Huet and G. Plotkin},
- PUBLISHER = {Cambridge University Press},
- TITLE = {Logical Environments},
- YEAR = {1992}
-}
-
-@INPROCEEDINGS{LePa94,
- AUTHOR = {F. Leclerc and C. Paulin-Mohring},
- BOOKTITLE = {{Types for Proofs and Programs, Types' 93}},
- EDITOR = {H. Barendregt and T. Nipkow},
- PUBLISHER = {Springer-Verlag},
- SERIES = {LNCS},
- TITLE = {{Programming with Streams in Coq. A case study : The Sieve of Eratosthenes}},
- VOLUME = {806},
- YEAR = {1994}
-}
-
-@BOOK{LF91,
- EDITOR = {G. Huet and G. Plotkin},
- PUBLISHER = {Cambridge University Press},
- TITLE = {Logical Frameworks},
- YEAR = {1991}
-}
-
-@BOOK{MaL84,
- AUTHOR = {{P. Martin-L\"of}},
- PUBLISHER = {Bibliopolis},
- SERIES = {Studies in Proof Theory},
- TITLE = {Intuitionistic Type Theory},
- YEAR = {1984}
-}
-
-@INPROCEEDINGS{manoury94,
- AUTHOR = {P. Manoury},
- TITLE = {{A User's Friendly Syntax to Define
-Recursive Functions as Typed $\lambda-$Terms}},
- BOOKTITLE = {{Types for Proofs and Programs, TYPES'94}},
- SERIES = {LNCS},
- VOLUME = {996},
- MONTH = jun,
- YEAR = {1994}
-}
-
-@ARTICLE{MaSi94,
- AUTHOR = {P. Manoury and M. Simonot},
- JOURNAL = {TCS},
- TITLE = {Automatizing termination proof of recursively defined function},
- YEAR = {To appear}
-}
-
-@TECHREPORT{maranget94,
- AUTHOR = {L. Maranget},
- INSTITUTION = {INRIA},
- NUMBER = {2385},
- TITLE = {{Two Techniques for Compiling Lazy Pattern Matching}},
- YEAR = {1994}
-}
-
-@INPROCEEDINGS{Moh89a,
- AUTHOR = {C. Paulin-Mohring},
- ADDRESS = {Austin},
- BOOKTITLE = {Sixteenth Annual ACM Symposium on Principles of Programming Languages},
- MONTH = jan,
- PUBLISHER = {ACM},
- TITLE = {Extracting ${F}_{\omega}$'s programs from proofs in the {Calculus of Constructions}},
- YEAR = {1989}
-}
-
-@PHDTHESIS{Moh89b,
- AUTHOR = {C. Paulin-Mohring},
- MONTH = jan,
- SCHOOL = {{Universit\'e Paris 7}},
- TITLE = {Extraction de programmes dans le {Calcul des Constructions}},
- YEAR = {1989}
-}
-
-@INPROCEEDINGS{Moh93,
- AUTHOR = {C. Paulin-Mohring},
- BOOKTITLE = {Proceedings of the conference Typed Lambda Calculi and Applications},
- EDITOR = {M. Bezem and J.-F. Groote},
- NOTE = {Also LIP research report 92-49, ENS Lyon},
- NUMBER = {664},
- PUBLISHER = {Springer-Verlag},
- SERIES = {LNCS},
- TITLE = {{Inductive Definitions in the System Coq - Rules and Properties}},
- YEAR = {1993}
-}
-
-@MASTERSTHESIS{Mun94,
- AUTHOR = {C. Mu\~noz},
- MONTH = sep,
- SCHOOL = {DEA d'Informatique Fondamentale, Universit\'e Paris 7},
- TITLE = {D\'emonstration automatique dans la logique propositionnelle intuitionniste},
- YEAR = {1994}
-}
-
-@BOOK{Nijmegen93,
- EDITOR = {H. Barendregt and T. Nipkow},
- PUBLISHER = {Springer-Verlag},
- SERIES = {LNCS},
- TITLE = {Types for Proofs and Programs},
- VOLUME = {806},
- YEAR = {1994}
-}
-
-@BOOK{NoPS90,
- AUTHOR = {B. {Nordstr\"om} and K. Peterson and J. Smith},
- BOOKTITLE = {Information Processing 83},
- PUBLISHER = {Oxford Science Publications},
- SERIES = {International Series of Monographs on Computer Science},
- TITLE = {Programming in {Martin-L\"of's} Type Theory},
- YEAR = {1990}
-}
-
-@ARTICLE{Nor88,
- AUTHOR = {B. {Nordstr\"om}},
- JOURNAL = {BIT},
- TITLE = {Terminating General Recursion},
- VOLUME = {28},
- YEAR = {1988}
-}
-
-@BOOK{Odi90,
- EDITOR = {P. Odifreddi},
- PUBLISHER = {Academic Press},
- TITLE = {Logic and Computer Science},
- YEAR = {1990}
-}
-
-@INPROCEEDINGS{PaMS92,
- AUTHOR = {M. Parigot and P. Manoury and M. Simonot},
- ADDRESS = {St. Petersburg, Russia},
- BOOKTITLE = {Logic Programming and automated reasoning},
- EDITOR = {A. Voronkov},
- MONTH = jul,
- NUMBER = {624},
- PUBLISHER = {Springer-Verlag},
- SERIES = {LNCS},
- TITLE = {{ProPre : A Programming language with proofs}},
- YEAR = {1992}
-}
-
-@ARTICLE{Par92,
- AUTHOR = {M. Parigot},
- JOURNAL = {Theoretical Computer Science},
- NUMBER = {2},
- PAGES = {335--356},
- TITLE = {{Recursive Programming with Proofs}},
- VOLUME = {94},
- YEAR = {1992}
-}
-
-@INPROCEEDINGS{Parent95b,
- AUTHOR = {C. Parent},
- BOOKTITLE = {{Mathematics of Program Construction'95}},
- PUBLISHER = {Springer-Verlag},
- SERIES = {LNCS},
- TITLE = {{Synthesizing proofs from programs in
-the Calculus of Inductive Constructions}},
- VOLUME = {947},
- YEAR = {1995}
-}
-
-@ARTICLE{PaWe92,
- AUTHOR = {C. Paulin-Mohring and B. Werner},
- JOURNAL = {Journal of Symbolic Computation},
- PAGES = {607--640},
- TITLE = {{Synthesis of ML programs in the system Coq}},
- VOLUME = {15},
- YEAR = {1993}
-}
-
-@INPROCEEDINGS{Prasad93,
- AUTHOR = {K.V. Prasad},
- BOOKTITLE = {{Proceedings of CONCUR'93}},
- PUBLISHER = {Springer-Verlag},
- SERIES = {LNCS},
- TITLE = {{Programming with broadcasts}},
- VOLUME = {715},
- YEAR = {1993}
-}
-
-@INPROCEEDINGS{puel-suarez90,
- AUTHOR = {L.Puel and A. Su\'arez},
- BOOKTITLE = {{Conference Lisp and Functional Programming}},
- SERIES = {ACM},
- PUBLISHER = {Springer-Verlag},
- TITLE = {{Compiling Pattern Matching by Term
-Decomposition}},
- YEAR = {1990}
-}
-
-@UNPUBLISHED{Rou92,
- AUTHOR = {J. Rouyer},
- MONTH = aug,
- NOTE = {To appear as a technical report},
- TITLE = {{D\'eveloppement de l'Algorithme d'Unification dans le Calcul des Constructions}},
- YEAR = {1992}
-}
-
-@TECHREPORT{Saibi94,
- AUTHOR = {A. Sa\"{\i}bi},
- INSTITUTION = {INRIA},
- MONTH = dec,
- NUMBER = {2345},
- TITLE = {{Axiomatization of a lambda-calculus with explicit-substitutions in the Coq System}},
- YEAR = {1994}
-}
-
-@MASTERSTHESIS{saidi94,
- AUTHOR = {H. Saidi},
- MONTH = sep,
- SCHOOL = {DEA d'Informatique Fondamentale, Universit\'e Paris 7},
- TITLE = {R\'esolution d'\'equations dans le syst\`eme T
- de G\"odel},
- YEAR = {1994}
-}
-
-@MASTERSTHESIS{Ter92,
- AUTHOR = {D. Terrasse},
- MONTH = sep,
- SCHOOL = {IARFA},
- TITLE = {{Traduction de TYPOL en COQ. Application \`a Mini ML}},
- YEAR = {1992}
-}
-
-@TECHREPORT{ThBeKa92,
- AUTHOR = {L. Th\'ery and Y. Bertot and G. Kahn},
- INSTITUTION = {INRIA Sophia},
- MONTH = may,
- NUMBER = {1684},
- TITLE = {Real theorem provers deserve real user-interfaces},
- TYPE = {Research Report},
- YEAR = {1992}
-}
-
-@BOOK{TrDa89,
- AUTHOR = {A.S. Troelstra and D. van Dalen},
- PUBLISHER = {North-Holland},
- SERIES = {Studies in Logic and the foundations of Mathematics, volumes 121 and 123},
- TITLE = {Constructivism in Mathematics, an introduction},
- YEAR = {1988}
-}
-
-@INCOLLECTION{wadler87,
- AUTHOR = {P. Wadler},
- TITLE = {Efficient Compilation of Pattern Matching},
- BOOKTITLE = {The Implementation of Functional Programming
-Languages},
- EDITOR = {S.L. Peyton Jones},
- PUBLISHER = {Prentice-Hall},
- YEAR = {1987}
-}
-
-@PHDTHESIS{Wer94,
- AUTHOR = {B. Werner},
- SCHOOL = {Universit\'e Paris 7},
- TITLE = {Une th\'eorie des constructions inductives},
- TYPE = {Th\`ese de Doctorat},
- YEAR = {1994}
-}
-
-
diff --git a/doc/RecTutorial/morebib.bib b/doc/RecTutorial/morebib.bib
deleted file mode 100644
index 438f2133d..000000000
--- a/doc/RecTutorial/morebib.bib
+++ /dev/null
@@ -1,55 +0,0 @@
-@book{coqart,
- title = "Interactive Theorem Proving and Program Development.
- Coq'Art: The Calculus of Inductive Constructions",
- author = {Yves Bertot and Pierre Castéran},
- publisher = "Springer Verlag",
- series = "Texts in Theoretical Computer Science. An EATCS series",
- year = 2004
-}
-
-@Article{Coquand:Huet,
- author = {Thierry Coquand and Gérard Huet},
- title = {The Calculus of Constructions},
- journal = {Information and Computation},
- year = {1988},
- volume = {76},
-}
-
-@INcollection{Coquand:metamathematical,
- author = "Thierry Coquand",
- title = "Metamathematical Investigations on a Calculus of Constructions",
- booktitle="Logic and Computer Science",
- year = {1990},
- editor="P. Odifreddi",
- publisher = "Academic Press",
-}
-
-@Misc{coqrefman,
- title = {The {C}oq reference manual},
- author={{C}oq {D}evelopment Team},
- note= {LogiCal Project, \texttt{http://coq.inria.fr/}}
- }
-
-@Misc{coqsite,
- author= {{C}oq {D}evelopment Team},
- title = {The \emph{Coq} proof assistant},
- note = {Documentation, system download. {C}ontact: \texttt{http://coq.inria.fr/}}
-}
-
-
-
-@Misc{Booksite,
- author = {Yves Bertot and Pierre Cast\'eran},
- title = {Coq'{A}rt: examples and exercises},
- note = {\url{http://www.labri.fr/Perso/~casteran/CoqArt}}
-}
-
-
-@InProceedings{conor:motive,
- author ="Conor McBride",
- title = "Elimination with a motive",
- booktitle = "Types for Proofs and Programs'2000",
- volume = 2277,
- pages = "197-217",
- year = "2002",
-}
diff --git a/doc/RecTutorial/recmacros.tex b/doc/RecTutorial/recmacros.tex
deleted file mode 100644
index 0334553f2..000000000
--- a/doc/RecTutorial/recmacros.tex
+++ /dev/null
@@ -1,75 +0,0 @@
-%===================================
-% Style of the document
-%===================================
-%\newtheorem{example}{Example}[section]
-%\newtheorem{exercise}{Exercise}[section]
-
-
-\newcommand{\comentario}[1]{\texttt{#1}}
-
-%===================================
-% Keywords
-%===================================
-
-\newcommand{\Prop}{\texttt{Prop}}
-\newcommand{\Set}{\texttt{Set}}
-\newcommand{\Type}{\texttt{Type}}
-\newcommand{\true}{\texttt{true}}
-\newcommand{\false}{\texttt{false}}
-\newcommand{\Lth}{\texttt{Lth}}
-
-\newcommand{\Nat}{\texttt{nat}}
-\newcommand{\nat}{\texttt{nat}}
-\newcommand{\Z} {\texttt{O}}
-\newcommand{\SUCC}{\texttt{S}}
-\newcommand{\pred}{\texttt{pred}}
-
-\newcommand{\False}{\texttt{False}}
-\newcommand{\True}{\texttt{True}}
-\newcommand{\I}{\texttt{I}}
-
-\newcommand{\natind}{\texttt{nat\_ind}}
-\newcommand{\natrec}{\texttt{nat\_rec}}
-\newcommand{\natrect}{\texttt{nat\_rect}}
-
-\newcommand{\eqT}{\texttt{eqT}}
-\newcommand{\identityT}{\texttt{identityT}}
-
-\newcommand{\map}{\texttt{map}}
-\newcommand{\iterates}{\texttt{iterates}}
-
-
-%===================================
-% Numbering
-%===================================
-
-
-\newtheorem{definition}{Definition}[section]
-\newtheorem{example}{Example}[section]
-
-
-%===================================
-% Judgements
-%===================================
-
-
-\newcommand{\JM}[2]{\ensuremath{#1 : #2}}
-
-%===================================
-% Expressions
-%===================================
-
-\newcommand{\Case}[3][]{\ensuremath{#1\textsf{Case}~#2~\textsf of}~#3~\textsf{end}}
-
-%=======================================
-
-\newcommand{\snreglados} [3] {\begin{tabular}{c} \ensuremath{#1} \\[2pt]
- \ensuremath{#2}\\ \hline \ensuremath{#3} \end{tabular}}
-
-
-\newcommand{\snregla} [2] {\begin{tabular}{c}
- \ensuremath{#1}\\ \hline \ensuremath{#2} \end{tabular}}
-
-
-%=======================================
-
diff --git a/doc/sphinx/MIGRATING b/doc/sphinx/MIGRATING
deleted file mode 100644
index fa6fe1537..000000000
--- a/doc/sphinx/MIGRATING
+++ /dev/null
@@ -1,238 +0,0 @@
-How to migrate the Coq Reference Manual to Sphinx
-=================================================
-
-# Install Python3 packages (requires Python 3, python3-pip, python3-setuptools)
-
- * pip3 install bs4 sphinx sphinx_rtd_theme pexpect antlr4-python3-runtime sphinxcontrib-bibtex
-
-# You may want to do this under a virtualenv, particularly if you end up with issues finding sphinxcontrib.bibtex. http://docs.python-guide.org/en/latest/dev/virtualenvs/
-
- * pip3 install virtualenv
- * virtualenv coqsphinxing # you may want to use -p to specify the python version
- * source coqsphinxing/bin/activate # activate the virtual environment
-
-# After activating the virtual environment you can run the above pip3 command to install sphinx. You will have to activate the virtual environment before building the docs in your session.
-
-# Add this Elisp code to .emacs, if you're using emacs (recommended):
-
- (defun sphinx/quote-coq-refman-region (left right &optional beg end count)
- (unless beg
- (if (region-active-p)
- (setq beg (region-beginning) end (region-end))
- (setq beg (point) end nil)))
- (unless count
- (setq count 1))
- (save-excursion
- (goto-char (or end beg))
- (dotimes (_ count) (insert right)))
- (save-excursion
- (goto-char beg)
- (dotimes (_ count) (insert left)))
- (if (and end (characterp left)) ;; Second test handles the ::`` case
- (goto-char (+ (* 2 count) end))
- (goto-char (+ count beg))))
-
- (defun sphinx/coqtop (beg end)
- (interactive (list (region-beginning) (region-end)))
- (replace-regexp "^Coq < " " " nil beg end)
- (indent-rigidly beg end -3)
- (goto-char beg)
- (insert ".. coqtop:: all\n\n"))
-
- (defun sphinx/rst-coq-action ()
- (interactive)
- (pcase (read-char "Command?")
- (?g (sphinx/quote-coq-refman-region ":g:`" "`"))
- (?n (sphinx/quote-coq-refman-region ":n:`" "`"))
- (?t (sphinx/quote-coq-refman-region ":token:`" "`"))
- (?m (sphinx/quote-coq-refman-region ":math:`" "`"))
- (?: (sphinx/quote-coq-refman-region "::`" "`"))
- (?` (sphinx/quote-coq-refman-region "``" "``"))
- (?c (sphinx/coqtop (region-beginning) (region-end)))))
-
- (global-set-key (kbd "<f12>") #'sphinx/rst-coq-action)
-
- With this code installed, you can hit "F12" followed by an appropriate key to do quick markup of text
- (this will make more sense once you've started editing the text).
-
-# Fork the Coq repo, if needed:
-
- https://github.com/coq/coq
-
-# Clone the repo to your work machine
-
-# Add Maxime Dénès's repo as a remote:
-
- git remote add sphinx https://github.com/maximedenes/coq.git
-
- (or choose a name other than "sphinx")
-
- Verify with:
-
- git remote -v
-
-# Fetch from the remote
-
- git fetch sphinx
-
-# Checkout the sphinx-doc branch
-
- git checkout sphinx-doc
-
- You should pull from the repo from time to time to keep your local copy up-to-date:
-
- git pull sphinx sphinx-doc
-
- You may want to create a new branch to do your work in.
-
-# Choose a Reference Manual chapter to work on at
-
- https://docs.google.com/document/d/1Yo7dV4OI0AY9Di-lsEQ3UTmn5ygGLlhxjym7cTCMCWU
-
-# For each chapter, raw ReStructuredText (the Sphinx format), created by the "html2rest" utility,
- is available in the directory porting/raw-rst/
-
- Elsewhere, depending on the chapter, there should be an almost-empty template file already created,
- which is in the location where the final version should go
-
-# Manually edit the .rst file, place it in the correct location
-
- There are small examples in sphinx/porting/, a larger example in language/gallina-extensions.rst
-
- (N.B.: the migration is a work-in-progress, your suggestions are welcome)
-
- Find the chapter you're working on from the online manual at https://coq.inria.fr/distrib/current/refman/.
- At the top of the file, after the chapter heading, add:
-
- :Source: https://coq.inria.fr/distrib/current/refman/the-chapter-file.html
- :Converted by: Your Name
-
- N.B.: These source and converted-by annotations should help for the migration phase. Later on,
- those annotations will be removed, and contributors will be mentioned in the Coq credits.
-
- Remove chapter numbers
-
- Replace section, subsection numbers with reference labels:
-
- .. _some-reference-label:
-
- Place the label before the section or subsection, followed by a blank line.
-
- Note the leading underscore. Use :ref:`some_reference-label` to refer to such a label; note the leading underscore is omitted.
- Many cross-references may be to other chapters. If the required label exists, use it. Otherwise, use a dummy reference of the form
- `TODO-n.n.n-mnemonic` we can fixup later. Example:
-
- :ref:`TODO-1.3.2-definitions`
-
- We can grep for those TODOs, and the existing subsection number makes it easy to find in the exisyting manual.
-
- For the particular case of references to chapters, we can use a
-convention for the cross-reference name, so no TODO is needed.
-
- :ref:`thegallinaspecificationlanguage`
-
-That is, the chapter label is the chapter title, all in lower-case,
-with no spaces or punctuation. For chapters with subtitles marked with
-a ":", like those for Omega and Nsatz, use just the chapter part
-preceding the ":". These labels should already be in the
-placeholder .rst files for each chapter.
-
-
- You can also label other items, like grammars, with the same syntax. To refer to such labels, not involving a
- section or subsection, use the syntax
-
- :ref:`Some link text <label-name>`
-
- Yes, the angle-brackets are needed here!
-
- For bibliographic references (those in biblio.bib), use :cite:`thecitation`.
-
- Grammars will get mangled by the translation. Look for "productionlist" in the examples, also see
- http://www.sphinx-doc.org/en/stable/markup/para.html.
-
- For Coq examples that appear, look at the "coqtop" syntax in porting/tricky-bits.rst. The Sphinx
- script will run coqtop on those examples, and can show the output (or not).
-
- The file replaces.rst contains replacement definitions for some items that are clumsy to write out otherwise.
- Use
-
- .. include:: replaces.rst
-
- to gain access to those definitions in your file (you might need a path prefix). Some especially-important
- replacements are |Cic|, |Coq|, |CoqIDE|, and |Gallina|, which display those names in small-caps. Please use them,
- so that they're rendered consistently.
-
- Similarly, there are some LaTeX macros in preamble.rst that can be useful.
-
- Conventions:
-
- - Keywords and other literal text is double-backquoted (e.g. ``Module``, ``Section``, ``(``, ``,``).
-
- - Metavariables are single-backquotes (e.g. `term`, `ident`)
-
- - Use the cmd directive for Vernacular commands, like:
-
- .. cmd:: Set Printing All.
-
- Within this directive, prefix metavariables (ident, term) with @:
-
- .. cmd:: Add Printing Let @ident.
-
- There's also the "cmdv" directive for variants of a command.
-
- - Use the "exn" and "warn" directives for errors and warnings:
-
- .. exn:: Something's not right.
- .. warn:: You shouldn't do that.
-
- - Use the "example" directive for examples
-
- - Use the "g" role for inline Gallina, like :g:`fun x => x`
-
- - Use code blocks for blocks of Gallina. You can use a double-colon at the end of a line::
-
- your code here
-
- which prints a single colon, or put the double-colon on a newline.
-
-::
-
- your other code here
-
-# Making changes to the text
-
- The goal of the migration is simply to change the storage format from LaTeX to ReStructuredText. The goal is not
- to make any organizational or other substantive changes to the text. If you do notice nits (misspellings, wrong
- verb tense, and so on), please do change them. For example, the programming language that Coq is written in is these days
- called "OCaml", and there are mentions of the older name "Objective Caml" in the reference manual that should be changed.
-
-# Build, view the manual
-
- In the root directory of your local repo, run "make sphinx". You can view the result in a browser by loading the HTML file
- associated with your chapter, which will be contained in the directory doc/sphinx/_build/html/ beneath the repo root directory.
- Make any changes you need until there are no build warnings and the output is perfect. :-)
-
-# Creating pull requests
-
- When your changes are done, commit them, push to your fork:
-
- git commit -m "useful commit message" file
- git push origin sphinx-doc
-
- (or push to another branch, if you've created one). Then go to your GitHub
- fork and create a pull request against Maxime's sphinx-doc
- branch. If your commit is recent, you should see a link on your
- fork's code page to do that. Otherwise, you may need to go to your
- branch on GitHub to do that.
-
-# Issues/Questions/Suggestions
-
- As the migration proceeds, if you have technical issues, have a more general question, or want to suggest something, please contact:
-
- Paul Steckler <steck@stecksoft.com>
- Maxime Dénès <maxime.denes@inria.fr>
-
-# Issues
-
- Should the stuff in replaces.rst go in preamble.rst?
- In LaTeX, some of the grammars add productions to existing nonterminals, like term ++= ... . How to indicate that?
diff --git a/doc/sphinx/README.rst b/doc/sphinx/README.rst
new file mode 100644
index 000000000..5f2f21f2b
--- /dev/null
+++ b/doc/sphinx/README.rst
@@ -0,0 +1,325 @@
+=============================
+ Documenting Coq with Sphinx
+=============================
+
+..
+ README.rst is auto-generated from README.template.rst and the coqrst docs;
+ use ``doc/tools/coqrst/regen_readme.py`` to rebuild it.
+
+Coq's reference manual is written in `reStructuredText <http://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html>`_ (“reST”), and compiled with `Sphinx <http://www.sphinx-doc.org/en/master/>`_.
+
+In addition to standard reST directives (a directive is similar to a LaTeX environment) and roles (a role is similar to a LaTeX command), the ``coqrst`` plugin loaded by the documentation uses a custom *Coq domain* — a set of Coq-specific directives that define *objects* like tactics, commands (vernacs), warnings, etc. —, some custom *directives*, and a few custom *roles*. Finally, this manual uses a small DSL to describe tactic invocations and commands.
+
+Coq objects
+===========
+
+Our Coq domain define multiple `objects`_. Each object has a *signature* (think *type signature*), followed by an optional body (a description of that object). The following example defines two objects: a variant of the ``simpl`` tactic, and an error that it may raise::
+
+ .. tacv:: simpl @pattern at {+ @num}
+ :name: simpl_at
+
+ This applies ``simpl`` only to the :n:`{+ @num}` occurrences of the subterms
+ matching :n:`@pattern` in the current goal.
+
+ .. exn:: Too few occurrences
+
+Objects are automatically collected into indices, and can be linked to using the role version of the object's directive. For example, you could link to the tactic variant above using ``:tacv:`simpl_at```, and to its exception using ``:exn:`Too few occurrences```.
+
+Names (link targets) are auto-generated for most simple objects, though they can always be overwritten using a ``:name:`` option, as shown above.
+
+- Options, errors, warnings have their name set to their signature, with ``...`` replacing all notation bits. For example, the auto-generated name of ``.. exn:: @qualid is not a module`` is ``... is not a module``, and a link to it would take the form ``:exn:`... is not a module```.
+- 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.
+
+Notations
+---------
+
+The signatures of most objects can be written using a succinct DSL for Coq notations (think regular expressions written with a Lispy syntax). A typical signature might look like ``Hint Extern @num {? @pattern} => @tactic``, which means that the ``Hint Extern`` command takes a number (``num``), followed by an optional pattern, and a mandatory tactic. The language has the following constructs (the full grammar is in `TacticNotations.g </doc/tools/coqrst/notations/TacticNotations.g>`_):
+
+``@…``
+ A placeholder (``@ident``, ``@num``, ``@tactic``\ …)
+
+``{? …}``
+ an optional block
+
+``{* …}``, ``{+ …}``
+ an optional (``*``) or mandatory (``+``) block that can be repeated, with repetitions separated by spaces
+
+``{*, …}``, ``{+, …}``
+ an optional or mandatory repeatable block, with repetitions separated by commas
+
+``%|``, ``%{``, …
+ an escaped character (rendered without the leading ``%``)
+
+..
+ FIXME document the new subscript support
+
+As an exercise, what do the following patterns mean?
+
+.. code::
+
+ pattern {+, @term {? at {+ @num}}}
+ generalize {+, @term at {+ @num} as @ident}
+ fix @ident @num with {+ (@ident {+ @binder} {? {struct @ident'}} : @type)}
+
+Objects
+-------
+
+Here is the list of all objects of the Coq domain (The symbol :black_nib: indicates an object whose signature can be written using the notations DSL):
+
+``.. cmd::`` :black_nib: A Coq command.
+ Example::
+
+ .. cmd:: Infix "@symbol" := @term ({+, @modifier}).
+
+ This command is equivalent to :n:`…`.
+
+``.. cmdv::`` :black_nib: A variant of a Coq command.
+ Example::
+
+ .. cmd:: Axiom @ident : @term.
+
+ This command links :token:`term` to the name :token:`term` as its specification in
+ the global context. The fact asserted by :token:`term` is thus assumed as a
+ postulate.
+
+ .. cmdv:: Parameter @ident : @term.
+
+ This is equivalent to :n:`Axiom @ident : @term`.
+
+``.. exn::`` :black_nib: An error raised by a Coq command or tactic.
+ This commonly appears nested in the ``.. tacn::`` that raises the
+ exception.
+
+ Example::
+
+ .. tacv:: assert @form by @tactic
+
+ This tactic applies :n:`@tactic` to solve the subgoals generated by
+ ``assert``.
+
+ .. exn:: Proof is not complete
+
+ Raised if :n:`@tactic` does not fully solve the goal.
+
+``.. opt::`` :black_nib: A Coq option.
+ Example::
+
+ .. opt:: 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.
+
+``.. prodn::`` :black_nib: Grammar productions.
+ This is useful if you intend to document individual grammar productions.
+ Otherwise, use Sphinx's `production lists
+ <http://www.sphinx-doc.org/en/stable/markup/para.html#directive-productionlist>`_.
+
+``.. tacn::`` :black_nib: A tactic, or a tactic notation.
+ Example::
+
+ .. tacn:: do @num @expr
+
+ :token:`expr` is evaluated to ``v`` which must be a tactic value. …
+
+``.. tacv::`` :black_nib: A variant of a tactic.
+ Example::
+
+ .. tacn:: fail
+
+ This is the always-failing tactic: it does not solve any goal. It is
+ useful for defining other tacticals since it can be caught by
+ :tacn:`try`, :tacn:`repeat`, :tacn:`match goal`, or the branching
+ tacticals. …
+
+ .. tacv:: fail @natural
+
+ The number is the failure level. If no level is specified, it
+ defaults to 0. …
+
+``.. thm::`` A theorem.
+ Example::
+
+ .. thm:: Bound on the ceiling function
+
+ Let :math:`p` be an integer and :math:`c` a rational constant. Then
+ :math:`p \ge c \rightarrow p \ge \lceil{c}\rceil`.
+
+``.. warn::`` :black_nib: An warning raised by a Coq command or tactic..
+ Do not mistake this for ``.. warning::``; this directive is for warning
+ messages produced by Coq.
+
+
+ Example::
+
+ .. warn:: Ambiguous path
+
+ When the coercion :token:`qualid` is added to the inheritance graph, non
+ valid coercion paths are ignored.
+
+Coq directives
+==============
+
+In addition to the objects above, the ``coqrst`` Sphinx plugin defines the following directives:
+
+``.. coqtop::`` A reST directive to describe interactions with Coqtop.
+ Usage::
+
+ .. coqtop:: options…
+
+ Coq code to send to coqtop
+
+ Example::
+
+ .. coqtop:: in reset undo
+
+ Print nat.
+ Definition a := 1.
+
+ Here is a list of permissible options:
+
+ - Display options
+
+ - ``all``: Display input and output
+ - ``in``: Display only input
+ - ``out``: Display only output
+ - ``none``: Display neither (useful for setup commands)
+
+ - Behavior options
+
+ - ``reset``: Send a ``Reset Initial`` command before running this block
+ - ``undo``: Send an ``Undo n`` (``n`` = number of sentences) command after
+ running all the commands in this block
+
+ ``coqtop``\ 's state is preserved across consecutive ``.. coqtop::`` blocks
+ of the same document (``coqrst`` creates a single ``coqtop`` process per
+ reST source file). Use the ``reset`` option to reset Coq's state.
+
+``.. coqdoc::`` A reST directive to display Coqtop-formatted source code.
+ Usage::
+
+ .. coqdoc::
+
+ Coq code to highlight
+
+ Example::
+
+ .. coqdoc::
+
+ Definition test := 1.
+
+``.. example::`` A reST directive for examples.
+ This behaves like a generic admonition; see
+ http://docutils.sourceforge.net/docs/ref/rst/directives.html#generic-admonition
+ for more details.
+
+ Example::
+
+ .. example:: Adding a hint to a database
+
+ The following adds ``plus_comm`` to the ``plu`` database:
+
+ .. coqdoc::
+
+ Hint Resolve plus_comm : plu.
+
+``.. inference::`` A reST directive to format inference rules.
+ This also serves as a small illustration of the way to create new Sphinx
+ directives.
+
+ Usage::
+
+ .. inference:: name
+
+ newline-separated premisses
+ ------------------------
+ conclusion
+
+ Example::
+
+ .. inference:: Prod-Pro
+
+ \WTEG{T}{s}
+ s \in \Sort
+ \WTE{\Gamma::(x:T)}{U}{\Prop}
+ -----------------------------
+ \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::
+
+ \newcommand{\paren}[#1]{\left(#1\right)}
+
+Coq roles
+=========
+
+In addition to the objects and directives above, the ``coqrst`` Sphinx plugin defines the following roles:
+
+``:g:`` Coq code.
+ Use this for Gallina and Ltac snippets::
+
+ :g:`apply plus_comm; reflexivity`
+ :g:`Set Printing All.`
+ :g:`forall (x: t), P(x)`
+
+``:n:`` Any text using the notation syntax (``@id``, ``{+, …}``, etc.).
+ Use this to explain tactic equivalences. For example, you might write
+ this::
+
+ :n:`generalize @term as @ident` is just like :n:`generalize @term`, but
+ 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:``
+ creates a link to that. When referring to a placeholder that happens to be
+ a grammar production, ``:token:`…``` is typically preferable to ``:n:`@…```.
+
+``:production:`` A grammar production not included in a ``productionlist`` directive.
+ Useful to informally introduce a production, as part of running text.
+
+ Example::
+
+ :production:`string` indicates a quoted string.
+
+ You're not likely to use this role very commonly; instead, use a
+ `production list
+ <http://www.sphinx-doc.org/en/stable/markup/para.html#directive-productionlist>`_
+ and reference its tokens using ``:token:`…```.
+
+Tips and tricks
+===============
+
+Nested lemmas
+-------------
+
+The ``.. coqtop::`` directive does *not* reset Coq after running its contents. That is, the following will create two nested lemmas::
+
+ .. coqtop:: all
+
+ Lemma l1: 1 + 1 = 2.
+
+ .. coqtop:: all
+
+ Lemma l2: 2 + 2 <> 1.
+
+Add either ``undo`` to the first block or ``reset`` to the second block to avoid nesting lemmas.
+
+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>`_.
+
+Emacs
+-----
+
+The ``dev/tools/coqdev.el`` folder contains a convenient Emacs function to quickly insert Sphinx roles and quotes. It takes a single character (one of ``gntm:```), and inserts one of ``:g:``, ``:n:``, ``:t:``, or an arbitrary role, or double quotes. You can also select a region of text, and wrap it in single or double backticks using that function.
+
+Use the following snippet to bind it to :kbd:`F12` in ``rst-mode``::
+
+ (with-eval-after-load 'rst
+ (define-key rst-mode-map (kbd "<f12>") #'coqdev-sphinx-rst-coq-action))
diff --git a/doc/sphinx/README.template.rst b/doc/sphinx/README.template.rst
new file mode 100644
index 000000000..203251abf
--- /dev/null
+++ b/doc/sphinx/README.template.rst
@@ -0,0 +1,117 @@
+=============================
+ Documenting Coq with Sphinx
+=============================
+
+..
+ README.rst is auto-generated from README.template.rst and the coqrst docs;
+ use ``doc/tools/coqrst/regen_readme.py`` to rebuild it.
+
+Coq's reference manual is written in `reStructuredText <http://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html>`_ (“reST”), and compiled with `Sphinx <http://www.sphinx-doc.org/en/master/>`_.
+
+In addition to standard reST directives (a directive is similar to a LaTeX environment) and roles (a role is similar to a LaTeX command), the ``coqrst`` plugin loaded by the documentation uses a custom *Coq domain* — a set of Coq-specific directives that define *objects* like tactics, commands (vernacs), warnings, etc. —, some custom *directives*, and a few custom *roles*. Finally, this manual uses a small DSL to describe tactic invocations and commands.
+
+Coq objects
+===========
+
+Our Coq domain define multiple `objects`_. Each object has a *signature* (think *type signature*), followed by an optional body (a description of that object). The following example defines two objects: a variant of the ``simpl`` tactic, and an error that it may raise::
+
+ .. tacv:: simpl @pattern at {+ @num}
+ :name: simpl_at
+
+ This applies ``simpl`` only to the :n:`{+ @num}` occurrences of the subterms
+ matching :n:`@pattern` in the current goal.
+
+ .. exn:: Too few occurrences
+
+Objects are automatically collected into indices, and can be linked to using the role version of the object's directive. For example, you could link to the tactic variant above using ``:tacv:`simpl_at```, and to its exception using ``:exn:`Too few occurrences```.
+
+Names (link targets) are auto-generated for most simple objects, though they can always be overwritten using a ``:name:`` option, as shown above.
+
+- Options, errors, warnings have their name set to their signature, with ``...`` replacing all notation bits. For example, the auto-generated name of ``.. exn:: @qualid is not a module`` is ``... is not a module``, and a link to it would take the form ``:exn:`... is not a module```.
+- 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.
+
+Notations
+---------
+
+The signatures of most objects can be written using a succinct DSL for Coq notations (think regular expressions written with a Lispy syntax). A typical signature might look like ``Hint Extern @num {? @pattern} => @tactic``, which means that the ``Hint Extern`` command takes a number (``num``), followed by an optional pattern, and a mandatory tactic. The language has the following constructs (the full grammar is in `TacticNotations.g </doc/tools/coqrst/notations/TacticNotations.g>`_):
+
+``@…``
+ A placeholder (``@ident``, ``@num``, ``@tactic``\ …)
+
+``{? …}``
+ an optional block
+
+``{* …}``, ``{+ …}``
+ an optional (``*``) or mandatory (``+``) block that can be repeated, with repetitions separated by spaces
+
+``{*, …}``, ``{+, …}``
+ an optional or mandatory repeatable block, with repetitions separated by commas
+
+``%|``, ``%{``, …
+ an escaped character (rendered without the leading ``%``)
+
+..
+ FIXME document the new subscript support
+
+As an exercise, what do the following patterns mean?
+
+.. code::
+
+ pattern {+, @term {? at {+ @num}}}
+ generalize {+, @term at {+ @num} as @ident}
+ fix @ident @num with {+ (@ident {+ @binder} {? {struct @ident'}} : @type)}
+
+Objects
+-------
+
+Here is the list of all objects of the Coq domain (The symbol :black_nib: indicates an object whose signature can be written using the notations DSL):
+
+[OBJECTS]
+
+Coq directives
+==============
+
+In addition to the objects above, the ``coqrst`` Sphinx plugin defines the following directives:
+
+[DIRECTIVES]
+
+Coq roles
+=========
+
+In addition to the objects and directives above, the ``coqrst`` Sphinx plugin defines the following roles:
+
+[ROLES]
+
+Tips and tricks
+===============
+
+Nested lemmas
+-------------
+
+The ``.. coqtop::`` directive does *not* reset Coq after running its contents. That is, the following will create two nested lemmas::
+
+ .. coqtop:: all
+
+ Lemma l1: 1 + 1 = 2.
+
+ .. coqtop:: all
+
+ Lemma l2: 2 + 2 <> 1.
+
+Add either ``undo`` to the first block or ``reset`` to the second block to avoid nesting lemmas.
+
+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>`_.
+
+Emacs
+-----
+
+The ``dev/tools/coqdev.el`` folder contains a convenient Emacs function to quickly insert Sphinx roles and quotes. It takes a single character (one of ``gntm:```), and inserts one of ``:g:``, ``:n:``, ``:t:``, or an arbitrary role, or double quotes. You can also select a region of text, and wrap it in single or double backticks using that function.
+
+Use the following snippet to bind it to :kbd:`F12` in ``rst-mode``::
+
+ (with-eval-after-load 'rst
+ (define-key rst-mode-map (kbd "<f12>") #'coqdev-sphinx-rst-coq-action))
diff --git a/doc/sphinx/addendum/generalized-rewriting.rst b/doc/sphinx/addendum/generalized-rewriting.rst
index f5237e4fb..e10e16c10 100644
--- a/doc/sphinx/addendum/generalized-rewriting.rst
+++ b/doc/sphinx/addendum/generalized-rewriting.rst
@@ -599,6 +599,7 @@ Notice that the syntax is not completely backward compatible since the
identifier was not required.
.. cmd:: Add Morphism f : @ident
+ :name: Add Morphism
The latter command also is restricted to the declaration of morphisms
without parameters. It is not fully backward compatible since the
@@ -616,7 +617,7 @@ the same signature. Finally, the :tacn:`replace` and :tacn:`rewrite` tactics can
used to replace terms in contexts that were refused by the old
implementation. As discussed in the next section, the semantics of the
new :tacn:`setoid_rewrite` tactic differs slightly from the old one and
-tacn:`rewrite`.
+:tacn:`rewrite`.
Extensions
diff --git a/doc/sphinx/addendum/implicit-coercions.rst b/doc/sphinx/addendum/implicit-coercions.rst
index 5f8c06484..09faa0676 100644
--- a/doc/sphinx/addendum/implicit-coercions.rst
+++ b/doc/sphinx/addendum/implicit-coercions.rst
@@ -140,29 +140,29 @@ Declaration of Coercions
.. warn:: Ambiguous path.
- When the coercion `qualid` is added to the inheritance graph, non
- valid coercion paths are ignored; they are signaled by a warning
- displaying these paths of the form :g:`[f₁;..;fₙ] : C >-> D`.
+ When the coercion :token:`qualid` is added to the inheritance graph, non
+ valid coercion paths are ignored; they are signaled by a warning
+ displaying these paths of the form :g:`[f₁;..;fₙ] : C >-> D`.
.. cmdv:: Local Coercion @qualid : @class >-> @class
- Declares the construction denoted by `qualid` as a coercion local to
- the current section.
+ Declares the construction denoted by `qualid` as a coercion local to
+ the current section.
.. cmdv:: Coercion @ident := @term
- This defines `ident` just like ``Definition`` `ident` ``:=`` `term`,
- and then declares `ident` as a coercion between it source and its target.
+ This defines `ident` just like ``Definition`` `ident` ``:=`` `term`,
+ and then declares `ident` as a coercion between it source and its target.
.. cmdv:: Coercion @ident := @term : @type
- This defines `ident` just like ``Definition`` `ident` : `type` ``:=`` `term`,
- and then declares `ident` as a coercion between it source and its target.
+ This defines `ident` just like ``Definition`` `ident` : `type` ``:=`` `term`,
+ and then declares `ident` as a coercion between it source and its target.
.. cmdv:: Local Coercion @ident := @term
- This defines `ident` just like ``Let`` `ident` ``:=`` `term`,
- and then declares `ident` as a coercion between it source and its target.
+ This defines `ident` just like ``Let`` `ident` ``:=`` `term`,
+ and then declares `ident` as a coercion between it source and its target.
Assumptions can be declared as coercions at declaration time.
This extends the grammar of assumptions from
@@ -263,9 +263,12 @@ Activating the Printing of Coercions
.. cmd:: Add Printing Coercion @qualid
- This command forces coercion denoted by :n:`@qualid` to be printed. To skip
- the printing of coercion :n:`@qualid`, use :cmd:`Remove Printing Coercion`. By
- default, a coercion is never printed.
+ This command forces coercion denoted by :n:`@qualid` to be printed.
+ By default, a coercion is never printed.
+
+.. cmd:: Remove Printing Coercion @qualid
+
+ Use this command, to skip the printing of coercion :n:`@qualid`.
.. _coercions-classes-as-records:
diff --git a/doc/sphinx/addendum/micromega.rst b/doc/sphinx/addendum/micromega.rst
index f887a5fee..0e9c23b9b 100644
--- a/doc/sphinx/addendum/micromega.rst
+++ b/doc/sphinx/addendum/micromega.rst
@@ -150,9 +150,10 @@ are a way to take into account the discreteness of :math:`\mathbb{Z}` by roundin
.. _ceil_thm:
-**Theorem**. Let :math:`p` be an integer and :math:`c` a rational constant. Then
+.. thm:: Bound on the ceiling function
- :math:`p \ge c \rightarrow p \ge \lceil{c}\rceil`
+ Let :math:`p` be an integer and :math:`c` a rational constant. Then
+ :math:`p \ge c \rightarrow p \ge \lceil{c}\rceil`.
For instance, from 2 x = 1 we can deduce
diff --git a/doc/sphinx/addendum/miscellaneous-extensions.rst b/doc/sphinx/addendum/miscellaneous-extensions.rst
index 80ea8a116..b6c35d8fa 100644
--- a/doc/sphinx/addendum/miscellaneous-extensions.rst
+++ b/doc/sphinx/addendum/miscellaneous-extensions.rst
@@ -11,7 +11,7 @@ Program derivation
|Coq| comes with an extension called ``Derive``, which supports program
derivation. Typically in the style of Bird and Meertens or derivations
of program refinements. To use the Derive extension it must first be
-required with ``Require Coq.Derive.Derive``. When the extension is loaded,
+required with ``Require Coq.derive.Derive``. When the extension is loaded,
it provides the following command:
.. cmd:: Derive @ident SuchThat @term As @ident
diff --git a/doc/sphinx/addendum/omega.rst b/doc/sphinx/addendum/omega.rst
index 009efd0d2..80ce01620 100644
--- a/doc/sphinx/addendum/omega.rst
+++ b/doc/sphinx/addendum/omega.rst
@@ -26,6 +26,11 @@ solvable. This is the restriction meant by "Presburger arithmetic".
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``
------------------------------------------
diff --git a/doc/sphinx/addendum/universe-polymorphism.rst b/doc/sphinx/addendum/universe-polymorphism.rst
index e80cfb6bb..6e7ccba63 100644
--- a/doc/sphinx/addendum/universe-polymorphism.rst
+++ b/doc/sphinx/addendum/universe-polymorphism.rst
@@ -412,7 +412,7 @@ end of a definition or proof, we check that the only remaining
universes are the ones declared. In the term and in general in proof
mode, introduced universe names can be referred to in terms. Note that
local universe names shadow global universe names. During a proof, one
-can use :ref:`Show Universes <ShowUniverses>` to display the current context of universes.
+can use :cmd:`Show Universes` to display the current context of universes.
Definitions can also be instantiated explicitly, giving their full
instance:
diff --git a/doc/sphinx/biblio.bib b/doc/sphinx/biblio.bib
index 97231c9ec..aeb45611e 100644
--- a/doc/sphinx/biblio.bib
+++ b/doc/sphinx/biblio.bib
@@ -1201,15 +1201,6 @@ Decomposition}},
note = {\url{https://proofgeneral.github.io/}}
}
-@Book{CoqArt,
- title = {Interactive Theorem Proving and Program Development.
- Coq'Art: The Calculus of Inductive Constructions},
- author = {Yves Bertot and Pierre Castéran},
- publisher = {Springer Verlag},
- series = {Texts in Theoretical Computer Science. An EATCS series},
- year = 2004
-}
-
@InCollection{wadler87,
author = {P. Wadler},
title = {Efficient Compilation of Pattern Matching},
diff --git a/doc/sphinx/conf.py b/doc/sphinx/conf.py
index 23bc9a2e4..1f7dd9d68 100755
--- a/doc/sphinx/conf.py
+++ b/doc/sphinx/conf.py
@@ -96,11 +96,13 @@ language = None
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = [
- '_build',
- 'Thumbs.db',
- '.DS_Store',
- 'introduction.rst',
- 'credits.rst'
+ '_build',
+ 'Thumbs.db',
+ '.DS_Store',
+ 'introduction.rst',
+ 'credits.rst',
+ 'README.rst',
+ 'README.template.rst'
]
# The reST default role (used for this markup: `text`) to use for all
diff --git a/doc/sphinx/introduction.rst b/doc/sphinx/introduction.rst
index 4a313df0c..75ff72c4d 100644
--- a/doc/sphinx/introduction.rst
+++ b/doc/sphinx/introduction.rst
@@ -2,12 +2,11 @@
Introduction
------------------------
-This document is the Reference Manual of the |Coq|  proof
-assistant. A companion volume, the |Coq| Tutorial, is provided for the
-beginners. It is advised to read the Tutorial first. A
-book :cite:`CoqArt` on practical uses of the |Coq| system was
-published in 2004 and is a good support for both the beginner and the
-advanced user.
+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).
The |Coq| system is designed to develop mathematical proofs, and
especially to write formal specifications, programs and to verify that
diff --git a/doc/sphinx/language/gallina-extensions.rst b/doc/sphinx/language/gallina-extensions.rst
index 8746897e7..53b993edd 100644
--- a/doc/sphinx/language/gallina-extensions.rst
+++ b/doc/sphinx/language/gallina-extensions.rst
@@ -1175,52 +1175,53 @@ component is equal ``nat`` and hence ``M1.T`` as specified.
If `qualid` denotes a valid basic module (i.e. its module type is a
signature), makes its components available by their short names.
-.. example::
+ .. example::
- .. coqtop:: reset all
+ .. coqtop:: reset all
- Module Mod.
+ Module Mod.
- Definition T:=nat.
+ Definition T:=nat.
- Check T.
+ Check T.
- End Mod.
+ End Mod.
- Check Mod.T.
+ Check Mod.T.
- Fail Check T.
+ Fail Check T.
- Import Mod.
+ Import Mod.
- Check T.
+ Check T.
-Some features defined in modules are activated only when a module is
-imported. This is for instance the case of notations (see :ref:`Notations`).
+ Some features defined in modules are activated only when a module is
+ imported. This is for instance the case of notations (see :ref:`Notations`).
-Declarations made with the Local flag are never imported by theImport
-command. Such declarations are only accessible through their fully
-qualified name.
+ Declarations made with the ``Local`` flag are never imported by the :cmd:`Import`
+ command. Such declarations are only accessible through their fully
+ qualified name.
-.. example::
+ .. example::
- .. coqtop:: all
+ .. coqtop:: all
- Module A.
+ Module A.
- Module B.
+ Module B.
- Local Definition T := nat.
+ Local Definition T := nat.
- End B.
+ End B.
- End A.
+ End A.
- Import A.
+ Import A.
- Fail Check B.T.
+ Fail Check B.T.
.. cmdv:: Export @qualid
+ :name: Export
When the module containing the command Export qualid
is imported, qualid is imported as well.
@@ -1231,16 +1232,17 @@ qualified name.
.. cmd:: Print Module @ident
- Prints the module type and (optionally) the body of the module `ident`.
+ Prints the module type and (optionally) the body of the module :n:`@ident`.
.. cmd:: Print Module Type @ident
- Prints the module type corresponding to `ident`.
+ Prints the module type corresponding to :n:`@ident`.
.. opt:: Short Module Printing
- This option (off by default) disables the printing of the types of fields,
- leaving only their names, for the commands ``Print Module`` and ``Print Module Type``.
+ This option (off by default) disables the printing of the types of fields,
+ leaving only their names, for the commands :cmd:`Print Module` and
+ :cmd:`Print Module Type`.
Libraries and qualified names
---------------------------------
@@ -1510,9 +1512,8 @@ implicitly applied to the implicit arguments it is waiting for: one
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 ``Implicit
-Arguments`` (see Section :ref:`declare-implicit-args`) or globally by the
-:opt:`Maximal Implicit Insertion` option.
+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`.
@@ -1565,7 +1566,7 @@ absent in every situation but still be able to specify it if needed:
The syntax is supported in all top-level definitions:
-``Definition``, ``Fixpoint``, ``Lemma`` and so on. For (co-)inductive datatype
+:cmd:`Definition`, :cmd:`Fixpoint`, :cmd:`Lemma` and so on. For (co-)inductive datatype
declarations, the semantics are the following: an inductive parameter
declared as an implicit argument need not be repeated in the inductive
definition but will become implicit for the constructors of the
diff --git a/doc/sphinx/language/gallina-specification-language.rst b/doc/sphinx/language/gallina-specification-language.rst
index 46e684b12..4dcd7deb1 100644
--- a/doc/sphinx/language/gallina-specification-language.rst
+++ b/doc/sphinx/language/gallina-specification-language.rst
@@ -553,8 +553,8 @@ has type :token:`type`.
.. cmd:: Axiom @ident : @term
- This command links *term* to the name *ident* as its specification in
- the global context. The fact asserted by *term* is thus assumed as a
+ This command links :token:`term` to the name :token:`ident` as its specification in
+ the global context. The fact asserted by :token:`term` is thus assumed as a
postulate.
.. exn:: @ident already exists.
@@ -609,6 +609,7 @@ of any section is equivalent to using ``Local Parameter``.
Adds blocks of variables with different specifications.
.. cmdv:: Variables {+ ( {+ @ident } : @term) }
+ :name: Variables
.. cmdv:: Hypothesis {+ ( {+ @ident } : @term) }
:name: Hypothesis
@@ -672,6 +673,7 @@ Section :ref:`typing-rules`.
You have to explicitly give their fully qualified name to refer to them.
.. cmdv:: Example @ident := @term
+ :name: Example
.. cmdv:: Example @ident : @term := @term
@@ -1243,37 +1245,37 @@ inhabitant of the type) is interactively built using tactics. The interactive
proof mode is described in Chapter :ref:`proofhandling` and the tactics in
Chapter :ref:`Tactics`. The basic assertion command is:
-.. cmd:: Theorem @ident : @type
+.. cmd:: Theorem @ident {? @binders } : @type
-After the statement is asserted, Coq needs a proof. Once a proof of
-:token:`type` under the assumptions represented by :token:`binders` is given and
-validated, the proof is generalized into a proof of forall , :token:`type` and
-the theorem is bound to the name :token:`ident` in the environment.
+ After the statement is asserted, Coq needs a proof. Once a proof of
+ :token:`type` under the assumptions represented by :token:`binders` is given and
+ validated, the proof is generalized into a proof of :n:`forall @binders, @type` and
+ the theorem is bound to the name :token:`ident` in the environment.
-.. exn:: The term @term has type @type which should be Set, Prop or Type.
+ .. exn:: The term @term has type @type which should be Set, Prop or Type.
-.. exn:: @ident already exists.
- :name: @ident already exists. (Theorem)
+ .. exn:: @ident already exists.
+ :name: @ident already exists. (Theorem)
- The name you provided is already defined. You have then to choose
- another name.
+ The name you provided is already defined. You have then to choose
+ another name.
-.. cmdv:: Lemma @ident : @type
- :name: Lemma
+ The following commands are synonyms of :n:`Theorem @ident {? @binders } : type`:
-.. cmdv:: Remark @ident : @type
- :name: Remark
+ .. cmdv:: Lemma @ident {? @binders } : @type
+ :name: Lemma
-.. cmdv:: Fact @ident : @type
- :name: Fact
+ .. cmdv:: Remark @ident {? @binders } : @type
+ :name: Remark
-.. cmdv:: Corollary @ident : @type
- :name: Corollary
+ .. cmdv:: Fact @ident {? @binders } : @type
+ :name: Fact
-.. cmdv:: Proposition @ident : @type
- :name: Proposition
+ .. cmdv:: Corollary @ident {? @binders } : @type
+ :name: Corollary
- These commands are synonyms of ``Theorem`` :token:`ident` : :token:`type`.
+ .. cmdv:: Proposition @ident {? @binders } : @type
+ :name: Proposition
.. cmdv:: Theorem @ident : @type {* with @ident : @type}
@@ -1300,13 +1302,13 @@ the theorem is bound to the name :token:`ident` in the environment.
.. cmdv:: Definition @ident : @type
This allows defining a term of type :token:`type` using the proof editing
- mode. It behaves as Theorem but is intended to be used in conjunction with
+ mode. It behaves as :cmd:`Theorem` but is intended to be used in conjunction with
:cmd:`Defined` in order to define a constant of which the computational
behavior is relevant.
The command can be used also with :cmd:`Example` instead of :cmd:`Definition`.
- See also :cmd:`Opaque`, :cmd:`Transparent`, :tacn:`unfold`.
+ .. seealso:: :cmd:`Opaque`, :cmd:`Transparent`, :tacn:`unfold`.
.. cmdv:: Let @ident : @type
@@ -1326,21 +1328,14 @@ the theorem is bound to the name :token:`ident` in the environment.
This generalizes the syntax of CoFixpoint so that one or more bodies
can be defined interactively using the proof editing mode.
-.. cmd:: Proof
-
- A proof starts by the keyword Proof. Then Coq enters the proof editing mode
- until the proof is completed. The proof editing mode essentially contains
- tactics that are described in chapter :ref:`Tactics`. Besides tactics, there
- are commands to manage the proof editing mode. They are described in Chapter
- :ref:`proofhandling`.
-
-.. cmd:: Qed
-
- When the proof is completed it should be validated and put in the environment
- using the keyword Qed.
+A proof starts by the keyword :cmd:`Proof`. Then Coq enters the proof editing mode
+until the proof is completed. The proof editing mode essentially contains
+tactics that are described in chapter :ref:`Tactics`. Besides tactics, there
+are commands to manage the proof editing mode. They are described in Chapter
+:ref:`proofhandling`.
-.. exn:: @ident already exists.
- :name: @ident already exists. (Qed)
+When the proof is completed it should be validated and put in the environment
+using the keyword :cmd:`Qed`.
.. note::
@@ -1349,28 +1344,19 @@ the theorem is bound to the name :token:`ident` in the environment.
#. Not only other assertions but any vernacular command can be given
while in the process of proving a given assertion. In this case, the
command is understood as if it would have been given before the
- statements still to be proved.
-
- #. Proof is recommended but can currently be omitted. On the opposite
- side, Qed (or Defined, see below) is mandatory to validate a proof.
+ statements still to be proved. Nonetheless, this practice is discouraged
+ and may stop working in future versions.
- #. Proofs ended by Qed are declared opaque. Their content cannot be
+ #. Proofs ended by :cmd:`Qed` are declared opaque. Their content cannot be
unfolded (see :ref:`performingcomputations`), thus
realizing some form of *proof-irrelevance*. To be able to unfold a
- proof, the proof should be ended by Defined (see below).
-
-.. cmdv:: Defined
- :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
- unfolded in conversion tactics (see :ref:`performingcomputations`,
- :cmd:`Opaque`, :cmd:`Transparent`).
+ proof, the proof should be ended by :cmd:`Defined`.
-.. cmdv:: Admitted
- :name: Admitted
+ #. :cmd:`Proof` is recommended but can currently be omitted. On the opposite
+ side, :cmd:`Qed` (or :cmd:`Defined`) is mandatory to validate a proof.
- Turns the current asserted statement into an axiom and exits the proof mode.
+ #. One can also use :cmd:`Admitted` in place of :cmd:`Qed` to turn the
+ current asserted statement into an axiom and exit the proof editing mode.
.. [1]
This is similar to the expression “*entry* :math:`\{` sep *entry*
diff --git a/doc/sphinx/practical-tools/coq-commands.rst b/doc/sphinx/practical-tools/coq-commands.rst
index 83dddab4f..ad1f0caa6 100644
--- a/doc/sphinx/practical-tools/coq-commands.rst
+++ b/doc/sphinx/practical-tools/coq-commands.rst
@@ -55,15 +55,20 @@ Customization at launch time
By resource file
~~~~~~~~~~~~~~~~~~~~~~~
-When |Coq| is launched, with either ``coqtop`` or ``coqc``, the resource file
-``$XDG_CONFIG_HOME/coq/coqrc.xxx`` is loaded, where ``$XDG_CONFIG_HOME``
+When |Coq| is launched, with either ``coqtop`` or ``coqc``, the
+resource file ``$XDG_CONFIG_HOME/coq/coqrc.xxx``, if it exists, will
+be implicitly prepended to any document read by Coq, whether it is an
+interactive session or a file to compile. Here, ``$XDG_CONFIG_HOME``
is the configuration directory of the user (by default its home
-directory ``/.config`` and ``xxx`` is the version number (e.g. 8.8). If
+directory ``~/.config``) and ``xxx`` is the version number (e.g. 8.8). If
this file is not found, then the file ``$XDG_CONFIG_HOME/coqrc`` is
-searched. You can also specify an arbitrary name for the resource file
+searched. If not found, it is the file ``~/.coqrc.xxx`` which is searched,
+and, if still not found, the file ``~/.coqrc``. If the latter is also
+absent, no resource file is loaded.
+You can also specify an arbitrary name for the resource file
(see option ``-init-file`` below).
-This file may contain, for instance, ``Add LoadPath`` commands to add
+The resource file may contain, for instance, ``Add LoadPath`` commands to add
directories to the load path of |Coq|. It is possible to skip the
loading of the resource file with the option ``-q``.
diff --git a/doc/sphinx/proof-engine/ltac.rst b/doc/sphinx/proof-engine/ltac.rst
index c5ee724ca..2b128b98f 100644
--- a/doc/sphinx/proof-engine/ltac.rst
+++ b/doc/sphinx/proof-engine/ltac.rst
@@ -245,7 +245,7 @@ focused goals with:
:name: ... : ... (goal selector)
We can also use selectors as a tactical, which allows to use them nested
- in a tactic expression, by using the keyword :tacn:`only`:
+ in a tactic expression, by using the keyword ``only``:
.. tacv:: only selector : expr
:name: only ... : ...
@@ -826,6 +826,7 @@ We can make pattern matching on goals using the following expression:
.. we should provide the full grammar here
.. tacn:: match goal with {+| {+ hyp} |- @cpattern => @expr } | _ => @expr end
+ :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
diff --git a/doc/sphinx/proof-engine/proof-handling.rst b/doc/sphinx/proof-engine/proof-handling.rst
index df8ef74f7..6d0b27728 100644
--- a/doc/sphinx/proof-engine/proof-handling.rst
+++ b/doc/sphinx/proof-engine/proof-handling.rst
@@ -8,12 +8,13 @@
In |Coq|’s proof editing mode all top-level commands documented in
Chapter :ref:`vernacularcommands` remain available and the user has access to specialized
commands dealing with proof development pragmas documented in this
-section. He can also use some other specialized commands called
+section. They can also use some other specialized commands called
*tactics*. They are the very tools allowing the user to deal with
logical reasoning. They are documented in Chapter :ref:`tactics`.
-When switching in editing proof mode, the prompt ``Coq <`` is changed into
-``ident <`` where ``ident`` is the declared name of the theorem currently
-edited.
+
+Coq user interfaces usually have a way of marking whether the user has
+switched to proof editing mode. For instance, in coqtop the prompt ``Coq <``   is changed into
+:n:`@ident <`   where :token:`ident` is the declared name of the theorem currently edited.
At each stage of a proof development, one has a list of goals to
prove. Initially, the list consists only in the theorem itself. After
@@ -36,8 +37,8 @@ terms are called *proof terms*.
.. exn:: No focused proof.
-Coq raises this error message when one attempts to use a proof editing command
-out of the proof editing mode.
+ Coq raises this error message when one attempts to use a proof editing command
+ out of the proof editing mode.
.. _proof-editing-mode:
@@ -46,139 +47,149 @@ Switching on/off the proof editing mode
The proof editing mode is entered by asserting a statement, which typically is
the assertion of a theorem using an assertion command like :cmd:`Theorem`. The
-list of assertion commands is given in Section :ref:`Assertions`. The command
+list of assertion commands is given in :ref:`Assertions`. The command
:cmd:`Goal` can also be used.
.. cmd:: Goal @form
-This is intended for quick assertion of statements, without knowing in
-advance which name to give to the assertion, typically for quick
-testing of the provability of a statement. If the proof of the
-statement is eventually completed and validated, the statement is then
-bound to the name ``Unnamed_thm`` (or a variant of this name not already
-used for another statement).
+ This is intended for quick assertion of statements, without knowing in
+ advance which name to give to the assertion, typically for quick
+ testing of the provability of a statement. If the proof of the
+ statement is eventually completed and validated, the statement is then
+ bound to the name ``Unnamed_thm`` (or a variant of this name not already
+ used for another statement).
.. cmd:: Qed
- :name: Qed (interactive proof)
-
-This command is available in interactive editing proof mode when the
-proof is completed. Then ``Qed`` extracts a proof term from the proof
-script, switches back to Coq top-level and attaches the extracted
-proof term to the declared name of the original goal. This name is
-added to the environment as an opaque constant.
+ This command is available in interactive editing proof mode when the
+ proof is completed. Then :cmd:`Qed` extracts a proof term from the proof
+ script, switches back to Coq top-level and attaches the extracted
+ proof term to the declared name of the original goal. This name is
+ added to the environment as an opaque constant.
-.. exn:: Attempt to save an incomplete proof.
+ .. exn:: Attempt to save an incomplete proof.
-.. note::
+ .. note::
- Sometimes an error occurs when building the proof term, because
- tactics do not enforce completely the term construction
- constraints.
+ Sometimes an error occurs when building the proof term, because
+ tactics do not enforce completely the term construction
+ constraints.
-The user should also be aware of the fact that since the
-proof term is completely rechecked at this point, one may have to wait
-a while when the proof is large. In some exceptional cases one may
-even incur a memory overflow.
+ The user should also be aware of the fact that since the
+ proof term is completely rechecked at this point, one may have to wait
+ a while when the proof is large. In some exceptional cases one may
+ even incur a memory overflow.
-.. cmdv:: Defined
- :name: Defined (interactive proof)
+ .. cmdv:: Defined
+ :name: Defined
-Defines the proved term as a transparent constant.
+ 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
+ unfolded in conversion tactics (see :ref:`performingcomputations`,
+ :cmd:`Opaque`, :cmd:`Transparent`).
-.. cmdv:: Save @ident
+ .. cmdv:: Save @ident
+ :name: Save
-Forces the name of the original goal to be :n:`@ident`. This
-command (and the following ones) can only be used if the original goal
-has been opened using the ``Goal`` command.
+ Forces the name of the original goal to be :token:`ident`. This
+ command (and the following ones) can only be used if the original goal
+ has been opened using the :cmd:`Goal` command.
.. cmd:: Admitted
- :name: Admitted (interactive proof)
-
-This command is available in interactive editing mode to give up
-the current proof and declare the initial goal as an axiom.
-
-.. cmd:: Proof @term
- :name: Proof `term`
-
-This command applies in proof editing mode. It is equivalent to
-.. coqtop:: in
+ This command is available in interactive editing mode to give up
+ the current proof and declare the initial goal as an axiom.
- exact @term. Qed.
+.. cmd:: Abort
-That is, you have to give the full proof in one gulp, as a
-proof term (see Section :ref:`applyingtheorems`).
+ This command cancels the current proof development, switching back to
+ the previous proof development, or to the |Coq| toplevel if no other
+ proof was edited.
-.. cmdv:: Proof
- :name: Proof (interactive proof)
+ .. exn:: No focused proof (No proof-editing in progress).
-Is a noop which is useful to delimit the sequence of tactic commands
-which start a proof, after a ``Theorem`` command. It is a good practice to
-use ``Proof``. as an opening parenthesis, closed in the script with a
-closing ``Qed``.
+ .. cmdv:: Abort @ident
+ Aborts the editing of the proof named :token:`ident` (in case you have
+ nested proofs).
-See also: ``Proof with tactic.`` in Section
-:ref:`tactics-implicit-automation`.
+ .. cmdv:: Abort All
+ Aborts all current goals.
-.. cmd:: Proof using @ident1 ... @identn
+.. cmd:: Proof @term
+ :name: Proof `term`
-This command applies in proof editing mode. It declares the set of
-section variables (see :ref:`gallina-assumptions`) used by the proof. At ``Qed`` time, the
-system will assert that the set of section variables actually used in
-the proof is a subset of the declared one.
+ This command applies in proof editing mode. It is equivalent to
+ :n:`exact @term. Qed.`
+ That is, you have to give the full proof in one gulp, as a
+ proof term (see Section :ref:`applyingtheorems`).
-The set of declared variables is closed under type dependency. For
-example if ``T`` is variable and a is a variable of type ``T``, the commands
-``Proof using a`` and ``Proof using T a``` are actually equivalent.
+.. cmd:: Proof
+ Is a no-op which is useful to delimit the sequence of tactic commands
+ which start a proof, after a :cmd:`Theorem` command. It is a good practice to
+ use :cmd:`Proof` as an opening parenthesis, closed in the script with a
+ closing :cmd:`Qed`.
-.. cmdv:: Proof using @ident1 ... @identn with @tactic
+ .. seealso:: :cmd:`Proof with`
-in Section :ref:`tactics-implicit-automation`.
+.. cmd:: Proof using {+ @ident }
-.. cmdv:: Proof using All
+ This command applies in proof editing mode. It declares the set of
+ section variables (see :ref:`gallina-assumptions`) used by the proof.
+ At :cmd:`Qed` time, the
+ system will assert that the set of section variables actually used in
+ the proof is a subset of the declared one.
-Use all section variables.
+ The set of declared variables is closed under type dependency. For
+ example if ``T`` is variable and a is a variable of type ``T``, the commands
+ ``Proof using a`` and ``Proof using T a`` are actually equivalent.
+ .. cmdv:: Proof using {+ @ident } with @tactic
-.. cmdv:: Proof using Type
+ Combines in a single line :cmd:`Proof with` and :cmd:`Proof using`.
-.. cmdv:: Proof using
+ .. seealso:: :ref:`tactics-implicit-automation`
-Use only section variables occurring in the statement.
+ .. cmdv:: Proof using All
+ Use all section variables.
-.. cmdv:: Proof using Type*
+ .. cmdv:: Proof using {? Type }
-The ``*`` operator computes the forward transitive closure. E.g. if the
-variable ``H`` has type ``p < 5`` then ``H`` is in ``p*`` since ``p`` occurs in the type
-of ``H``. ``Type*`` is the forward transitive closure of the entire set of
-section variables occurring in the statement.
+ Use only section variables occurring in the statement.
+ .. cmdv:: Proof using Type*
-.. cmdv:: Proof using -(@ident1 ... @identn)
+ The ``*`` operator computes the forward transitive closure. E.g. if the
+ variable ``H`` has type ``p < 5`` then ``H`` is in ``p*`` since ``p`` occurs in the type
+ of ``H``. ``Type*`` is the forward transitive closure of the entire set of
+ section variables occurring in the statement.
-Use all section variables except :n:`@ident1` ... :n:`@identn`.
+ .. cmdv:: Proof using -({+ @ident })
+ Use all section variables except the list of :token:`ident`.
-.. cmdv:: Proof using @collection1 + @collection2
+ .. cmdv:: Proof using @collection1 + @collection2
+ Use section variables from the union of both collections.
+ See :ref:`nameaset` to know how to form a named collection.
-.. cmdv:: Proof using @collection1 - @collection2
+ .. cmdv:: Proof using @collection1 - @collection2
+ Use section variables which are in the first collection but not in the
+ second one.
-.. cmdv:: Proof using @collection - ( @ident1 ... @identn )
+ .. cmdv:: Proof using @collection - ({+ @ident })
+ Use section variables which are in the first collection but not in the
+ list of :token:`ident`.
-.. cmdv:: Proof using @collection *
+ .. cmdv:: Proof using @collection *
-Use section variables being, respectively, in the set union, set
-difference, set complement, set forward transitive closure. See
-Section :ref:`nameaset` to know how to form a named collection. The ``*`` operator
-binds stronger than ``+`` and ``-``.
+ Use section variables in the forward transitive closure of the collection.
+ The ``*`` operator binds stronger than ``+`` and ``-``.
Proof using options
@@ -189,14 +200,14 @@ The following options modify the behavior of ``Proof using``.
.. opt:: Default Proof Using "@expression"
- 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``.
+ 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
- When ``Qed`` is performed, suggest a using annotation if the user did not
+ When :cmd:`Qed` is performed, suggest a ``using`` annotation if the user did not
provide one.
.. _`nameaset`:
@@ -204,80 +215,50 @@ The following options modify the behavior of ``Proof using``.
Name a set of section hypotheses for ``Proof using``
````````````````````````````````````````````````````
-.. cmd:: Collection @ident := @section_subset_expr
-
-The command ``Collection`` can be used to name a set of section
-hypotheses, with the purpose of making ``Proof using`` annotations more
-compact.
-
-
-.. cmdv:: Collection Some := x y z
-
-Define the collection named "Some" containing ``x``, ``y`` and ``z``.
+.. cmd:: Collection @ident := @expression
+ This can be used to name a set of section
+ hypotheses, with the purpose of making ``Proof using`` annotations more
+ compact.
-.. cmdv:: Collection Fewer := Some - z
+ .. example::
-Define the collection named "Fewer" containing only ``x`` and ``y``.
+ Define the collection named ``Some`` containing ``x``, ``y`` and ``z``::
+ Collection Some := x y z.
-.. cmdv:: Collection Many := Fewer + Some
-.. cmdv:: Collection Many := Fewer - Some
+ Define the collection named ``Fewer`` containing only ``x`` and ``y``::
-Define the collection named "Many" containing the set union or set
-difference of "Fewer" and "Some".
+ Collection Fewer := Some - z
+ Define the collection named ``Many`` containing the set union or set
+ difference of ``Fewer`` and ``Some``::
-.. cmdv:: Collection Many := Fewer - (x y)
-
-Define the collection named "Many" containing the set difference of
-"Fewer" and the unnamed collection ``x`` ``y``
-
-
-.. cmd:: Abort
+ Collection Many := Fewer + Some
+ Collection Many := Fewer - Some
-This command cancels the current proof development, switching back to
-the previous proof development, or to the |Coq| toplevel if no other
-proof was edited.
+ Define the collection named ``Many`` containing the set difference of
+ ``Fewer`` and the unnamed collection ``x y``::
-
-.. exn:: No focused proof (No proof-editing in progress).
-
-
-
-.. cmdv:: Abort @ident
-
-Aborts the editing of the proof named :n:`@ident`.
-
-.. cmdv:: Abort All
-
-Aborts all current goals, switching back to the |Coq|
-toplevel.
+ Collection Many := Fewer - (x y)
.. cmd:: Existential @num := @term
-This command instantiates an existential variable. :n:`@num` is an index in
-the list of uninstantiated existential variables displayed by ``Show
-Existentials`` (described in Section :ref:`requestinginformation`).
-
-This command is intended to be used to instantiate existential
-variables when the proof is completed but some uninstantiated
-existential variables remain. To instantiate existential variables
-during proof edition, you should use the tactic :tacn:`instantiate`.
-
-
-See also: ``instantiate (num:= term).`` in Section
-:ref:`controllingtheproofflow`.
-See also: ``Grab Existential Variables.`` below.
+ This command instantiates an existential variable. :token:`num` is an index in
+ the list of uninstantiated existential variables displayed by :cmd:`Show Existentials`.
+ This command is intended to be used to instantiate existential
+ variables when the proof is completed but some uninstantiated
+ existential variables remain. To instantiate existential variables
+ during proof edition, you should use the tactic :tacn:`instantiate`.
.. cmd:: Grab Existential Variables
-This command can be run when a proof has no more goal to be solved but
-has remaining uninstantiated existential variables. It takes every
-uninstantiated existential variable and turns it into a goal.
+ This command can be run when a proof has no more goal to be solved but
+ has remaining uninstantiated existential variables. It takes every
+ uninstantiated existential variable and turns it into a goal.
Navigation in the proof tree
@@ -290,7 +271,7 @@ Navigation in the proof tree
.. cmdv:: Undo @num
- Repeats Undo :n:`@num` times.
+ Repeats Undo :token:`num` times.
.. cmdv:: Restart
:name: Restart
@@ -306,19 +287,22 @@ Navigation in the proof tree
is solved or unfocused. This is useful when there are many current
subgoals which clutter your screen.
+ .. deprecated:: 8.8
+
+ Prefer the use of bullets or focusing brackets (see below).
+
.. cmdv:: Focus @num
- This focuses the attention on the :n:`@num` th subgoal to prove.
+ This focuses the attention on the :token:`num` th subgoal to prove.
.. deprecated:: 8.8
- Prefer the use of bullets or
- focusing brackets instead, including :n:`@num : %{`
+ Prefer the use of focusing brackets with a goal selector (see below).
.. cmd:: Unfocus
This command restores to focus the goal that were suspended by the
- last ``Focus`` command.
+ last :cmd:`Focus` command.
.. deprecated:: 8.8
@@ -332,7 +316,7 @@ Navigation in the proof tree
.. cmd:: %{ %| %}
The command ``{`` (without a terminating period) focuses on the first
- goal, much like ``Focus.`` does, however, the subproof can only be
+ goal, much like :cmd:`Focus` does, however, the subproof can only be
unfocused when it has been fully solved ( *i.e.* when there is no
focused goal left). Unfocusing is then handled by ``}`` (again, without a
terminating period). See also example in next section.
@@ -341,9 +325,9 @@ Navigation in the proof tree
together with a suggestion about the right bullet or ``}`` to unfocus it
or focus the next one.
-.. cmdv:: @num: %{
+ .. cmdv:: @num: %{
- This focuses on the :n:`@num` th subgoal to prove.
+ This focuses on the :token:`num` th subgoal to prove.
Error messages:
@@ -409,19 +393,19 @@ The following example script illustrates all these features:
.. exn:: Wrong bullet @bullet1: Current bullet @bullet2 is not finished.
-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.
+ 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 @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:`@bullet2` to focus next goal. No other bullet is allowed here.
.. exn:: No such goal. Focus next goal with bullet @bullet.
-You tried to applied a tactic but no goal where under focus. Using :n:`@bullet` is mandatory here.
+ You tried to apply a tactic but no goal where under focus. Using :n:`@bullet` is mandatory here.
.. exn:: No such goal. Try unfocusing with %{.
-You just finished a goal focused by ``{``, you must unfocus it with ``}``.
+ You just finished a goal focused by ``{``, you must unfocus it with ``}``.
Set Bullet Behavior
```````````````````
@@ -440,110 +424,116 @@ Requesting information
.. cmd:: Show
-This command displays the current goals.
+ This command displays the current goals.
+ .. exn:: No focused proof.
-.. cmdv:: Show @num
+ .. cmdv:: Show @num
-Displays only the :n:`@num`-th subgoal.
+ Displays only the :token:`num` th subgoal.
-.. exn:: No such goal.
-.. exn:: No focused proof.
+ .. exn:: No such goal.
-.. cmdv:: Show @ident
-Displays the named goal :n:`@ident`. This is useful in
-particular to display a shelved goal but only works if the
-corresponding existential variable has been named by the user
-(see :ref:`existential-variables`) as in the following example.
+ .. cmdv:: Show @ident
-.. example::
+ Displays the named goal :token:`ident`. This is useful in
+ particular to display a shelved goal but only works if the
+ corresponding existential variable has been named by the user
+ (see :ref:`existential-variables`) as in the following example.
- .. coqtop:: all
+ .. example::
- Goal exists n, n = 0.
- eexists ?[n].
- Show n.
+ .. coqtop:: all
-.. cmdv:: Show Script
+ Goal exists n, n = 0.
+ eexists ?[n].
+ Show n.
-Displays the whole list of tactics applied from the
-beginning of the current proof. This tactics script may contain some
-holes (subgoals not yet proved). They are printed under the form
+ .. cmdv:: Show Script
+ :name: Show Script
-``<Your Tactic Text here>``.
+ Displays the whole list of tactics applied from the
+ beginning of the current proof. This tactics script may contain some
+ holes (subgoals not yet proved). They are printed under the form
-.. cmdv:: Show Proof
+ ``<Your Tactic Text here>``.
-It displays the proof term generated by the tactics
-that have been applied. If the proof is not completed, this term
-contain holes, which correspond to the sub-terms which are still to be
-constructed. These holes appear as a question mark indexed by an
-integer, and applied to the list of variables in the context, since it
-may depend on them. The types obtained by abstracting away the context
-from the type of each hole-placer are also printed.
+ .. cmdv:: Show Proof
+ :name: Show Proof
-.. cmdv:: Show Conjectures
+ It displays the proof term generated by the tactics
+ that have been applied. If the proof is not completed, this term
+ contain holes, which correspond to the sub-terms which are still to be
+ constructed. These holes appear as a question mark indexed by an
+ integer, and applied to the list of variables in the context, since it
+ may depend on them. The types obtained by abstracting away the context
+ from the type of each hole-placer are also printed.
-It prints the list of the names of all the
-theorems that are currently being proved. As it is possible to start
-proving a previous lemma during the proof of a theorem, this list may
-contain several names.
+ .. cmdv:: Show Conjectures
+ :name: Show Conjectures
-.. cmdv:: Show Intro
+ It prints the list of the names of all the
+ theorems that are currently being proved. As it is possible to start
+ proving a previous lemma during the proof of a theorem, this list may
+ contain several names.
-If the current goal begins by at least one product,
-this command prints the name of the first product, as it would be
-generated by an anonymous ``intro``. The aim of this command is to ease
-the writing of more robust scripts. For example, with an appropriate
-Proof General macro, it is possible to transform any anonymous ``intro``
-into a qualified one such as ``intro y13``. In the case of a non-product
-goal, it prints nothing.
+ .. cmdv:: Show Intro
+ :name: Show Intro
-.. cmdv:: Show Intros
+ If the current goal begins by at least one product,
+ this command prints the name of the first product, as it would be
+ generated by an anonymous :tacn:`intro`. The aim of this command is to ease
+ the writing of more robust scripts. For example, with an appropriate
+ Proof General macro, it is possible to transform any anonymous :tacn:`intro`
+ into a qualified one such as ``intro y13``. In the case of a non-product
+ goal, it prints nothing.
-This command is similar to the previous one, it
-simulates the naming process of an intros.
+ .. cmdv:: Show Intros
+ :name: Show Intros
-.. cmdv:: Show Existentials
+ This command is similar to the previous one, it
+ simulates the naming process of an :tacn:`intros`.
-It displays the set of all uninstantiated
-existential variables in the current proof tree, along with the type
-and the context of each variable.
+ .. cmdv:: Show Existentials
+ :name: Show Existentials
-.. cmdv:: Show Match @ident
+ It displays the set of all uninstantiated
+ existential variables in the current proof tree, along with the type
+ and the context of each variable.
-This variant displays a template of the Gallina
-``match`` construct with a branch for each constructor of the type
-:n:`@ident`
+ .. cmdv:: Show Match @ident
-.. example::
- .. coqtop:: all
+ This variant displays a template of the Gallina
+ ``match`` construct with a branch for each constructor of the type
+ :token:`ident`
- Show Match nat.
+ .. example::
+ .. coqtop:: all
-.. exn:: Unknown inductive type.
+ Show Match nat.
-.. _ShowUniverses:
+ .. exn:: Unknown inductive type.
-.. cmdv:: Show Universes
+ .. cmdv:: Show Universes
+ :name: Show Universes
-It displays the set of all universe constraints and
-its normalized form at the current stage of the proof, useful for
-debugging universe inconsistencies.
+ It displays the set of all universe constraints and
+ its normalized form at the current stage of the proof, useful for
+ debugging universe inconsistencies.
.. cmd:: Guarded
-Some tactics (e.g. :tacn:`refine`) allow to build proofs using
-fixpoint or co-fixpoint constructions. Due to the incremental nature
-of interactive proof construction, the check of the termination (or
-guardedness) of the recursive calls in the fixpoint or cofixpoint
-constructions is postponed to the time of the completion of the proof.
+ Some tactics (e.g. :tacn:`refine`) allow to build proofs using
+ fixpoint or co-fixpoint constructions. Due to the incremental nature
+ of interactive proof construction, the check of the termination (or
+ guardedness) of the recursive calls in the fixpoint or cofixpoint
+ constructions is postponed to the time of the completion of the proof.
-The command :cmd:`Guarded` allows checking if the guard condition for
-fixpoint and cofixpoint is violated at some time of the construction
-of the proof without having to wait the completion of the proof.
+ The command :cmd:`Guarded` allows checking if the guard condition for
+ fixpoint and cofixpoint is violated at some time of the construction
+ of the proof without having to wait the completion of the proof.
Controlling the effect of proof editing commands
@@ -552,23 +542,23 @@ Controlling the effect of proof editing commands
.. opt:: Hyps Limit @num
-This option controls the maximum number of hypotheses displayed in goals
-after the application of a tactic. All the hypotheses remain usable
-in the proof development.
-When unset, it goes back to the default mode which is to print all
-available hypotheses.
+ This option controls the maximum number of hypotheses displayed in goals
+ after the application of a tactic. All the hypotheses remain usable
+ in the proof development.
+ When unset, it goes back to the default mode which is to print all
+ available hypotheses.
.. opt:: Automatic Introduction
-This option controls the way binders are handled
-in assertion commands such as ``Theorem ident [binders] : form``. When the
-option is on, which is the default, binders are automatically put in
-the local context of the goal to prove.
+ This option controls the way binders are handled
+ in assertion commands such as :n:`Theorem @ident {? @binders} : @term`. When the
+ option is on, which is the default, binders are automatically put in
+ the local context of the goal to prove.
-When the option is off, binders are discharged on the statement to be
-proved and a tactic such as :tacn:`intro` (see Section :ref:`managingthelocalcontext`)
-has to be used to move the assumptions to the local context.
+ When the option is off, binders are discharged on the statement to be
+ proved and a tactic such as :tacn:`intro` (see Section :ref:`managingthelocalcontext`)
+ has to be used to move the assumptions to the local context.
Controlling memory usage
@@ -580,13 +570,13 @@ to force |Coq| to optimize some of its internal data structures.
.. cmd:: Optimize Proof
-This command forces |Coq| to shrink the data structure used to represent
-the ongoing proof.
+ This command forces |Coq| to shrink the data structure used to represent
+ the ongoing proof.
.. cmd:: Optimize Heap
-This command forces the |OCaml| runtime to perform a heap compaction.
-This is in general an expensive operation.
-See: `OCaml Gc <http://caml.inria.fr/pub/docs/manual-ocaml/libref/Gc.html#VALcompact>`_
-There is also an analogous tactic :tacn:`optimize_heap`.
+ This command forces the |OCaml| runtime to perform a heap compaction.
+ This is in general an expensive operation.
+ See: `OCaml Gc <http://caml.inria.fr/pub/docs/manual-ocaml/libref/Gc.html#VALcompact>`_
+ There is also an analogous tactic :tacn:`optimize_heap`.
diff --git a/doc/sphinx/proof-engine/tactics.rst b/doc/sphinx/proof-engine/tactics.rst
index b3537bad8..3835524f0 100644
--- a/doc/sphinx/proof-engine/tactics.rst
+++ b/doc/sphinx/proof-engine/tactics.rst
@@ -96,10 +96,10 @@ bindings_list`` where ``bindings_list`` may be of two different forms:
+ A bindings list can also be a simple list of terms :n:`{* term}`.
In that case the references to which these terms correspond are
- determined by the tactic. In case of ``induction``, ``destruct``, ``elim``
- and ``case`` (see :ref:`ltac`) the terms have to
+ determined by the tactic. In case of :tacn:`induction`, :tacn:`destruct`, :tacn:`elim`
+ and :tacn:`case`, the terms have to
provide instances for all the dependent products in the type of term while in
- the case of ``apply``, or of ``constructor`` and its variants, only instances
+ the case of :tacn:`apply`, or of :tacn:`constructor` and its variants, only instances
for the dependent products that are not bound in the conclusion of the type
are required.
@@ -503,7 +503,7 @@ Applying theorems
.. tacv:: eapply {+, @term with @bindings_list} in @ident as @intro_pattern.
- This works as :tacn:`apply ... in as` but using ``eapply``.
+ This works as :tacn:`apply ... in ... as` but using ``eapply``.
.. tacv:: simple apply @term in @ident
@@ -511,15 +511,15 @@ Applying theorems
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 ?1234` and :g:`O` where :g:`?1234` is
- a variable to instantiate. Tactic :n:`simple apply @term in @ident` does not
+ 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}
- 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
@@ -626,22 +626,21 @@ 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 :math:`\forall` :g:`x:T, U` (resp
+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 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 Xn:T (if the type of :g:`T` is :g:`Type`). The optional index
+: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
+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 neither a product, nor starting with a let definition, nor an existential variable,
the tactic ``intro`` applies the tactic ``hnf`` until the tactic ``intro`` can
be applied or the goal is not head-reducible.
@@ -649,11 +648,12 @@ be applied or the goal is not head-reducible.
.. exn:: @ident is already used.
.. tacv:: intros
+ :name: intros
This repeats ``intro`` until it meets the head-constant. It never
reduces head-constants and it never fails.
-.. tac:: intro @ident
+.. tacn:: intro @ident
This applies ``intro`` but forces :n:`@ident` to be the name of the
introduced hypothesis.
@@ -715,7 +715,7 @@ be applied or the goal is not head-reducible.
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`).
+ appropriate call to ``move`` (see :tacn:`move ... after ...`).
.. tacn:: intros @intro_pattern_list
:name: intros ...
@@ -760,7 +760,7 @@ be applied or the goal is not head-reducible.
Assuming a goal of type :g:`Q → P` (non-dependent product), or of type
- :math:`\forall`:g:`x:T, P` (dependent product), the behavior of
+ :g:`forall x:T, P` (dependent product), the behavior of
:n:`intros p` is defined inductively over the structure of the introduction
pattern :n:`p`:
@@ -904,21 +904,21 @@ quantification or an implication.
.. tacn:: revert {+ @ident}
:name: revert
-This applies to any goal with variables :n:`{+ @ident}`. It moves the hypotheses
-(possibly defined) to the goal, if this respects dependencies. This tactic is
-the inverse of :tacn:`intro`.
+ This applies to any goal with variables :n:`{+ @ident}`. It moves the hypotheses
+ (possibly defined) to the goal, if this respects dependencies. This tactic is
+ the inverse of :tacn:`intro`.
.. exn:: No such hypothesis.
.. exn:: @ident is used in the hypothesis @ident.
-.. tac:: revert dependent @ident
+.. tacn:: revert dependent @ident
This moves to the goal the hypothesis :n:`@ident` and all the hypotheses that
depend on it.
.. tacn:: move @ident after @ident
- :name: move .. after ...
+ :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
@@ -1122,7 +1122,7 @@ Controlling the proof flow
This behaves as :n:`assert (@ident : form)` but :n:`@ident` is generated by
Coq.
-.. tacv:: assert form by tactic
+.. tacv:: assert @form by @tactic
This tactic behaves like :n:`assert` but applies tactic to solve the subgoals
generated by assert.
@@ -1130,7 +1130,7 @@ Controlling the proof flow
.. exn:: Proof is not complete.
:name: Proof is not complete. (assert)
-.. tacv:: assert form as intro_pattern
+.. tacv:: assert @form as @intro_pattern
If :n:`intro_pattern` is a naming introduction pattern (see :tacn:`intro`),
the hypothesis is named after this introduction pattern (in particular, if
@@ -1139,7 +1139,7 @@ Controlling the proof flow
introduction pattern, the tactic behaves like :n:`assert form` followed by
the action done by this introduction pattern.
-.. tacv:: assert form as intro_pattern by tactic
+.. tacv:: assert @form as @intro_pattern by @tactic
This combines the two previous variants of :n:`assert`.
@@ -1192,9 +1192,9 @@ Controlling the proof flow
This behaves like :n:`enough form` using :n:`intro_pattern` to name or
destruct the new hypothesis.
-.. tacv:: enough (@ident : form) by tactic
-.. tacv:: enough form by tactic
-.. tacv:: enough form as intro_pattern by tactic
+.. tacv:: enough (@ident : @form) by @tactic
+.. tacv:: enough @form by @tactic
+.. tacv:: enough @form as @intro_pattern by @tactic
This behaves as above but with :n:`tactic` expected to solve the initial goal
after the extra assumption :n:`form` is added and possibly destructed. If the
@@ -2149,13 +2149,13 @@ See also: :ref:`advanced-recursive-functions`
:n:`dependent inversion_clear @ident`.
.. tacv:: dependent inversion @ident with @term
- :name: dependent inversion ...
+ :name: dependent inversion ... with ...
This variant allows you to specify the generalization of the goal. It is
useful when the system fails to generalize the goal automatically. If
- :n:`@ident` has type :g:`(I t)` and :g:`I` has type :math:`\forall`
- :g:`(x:T), s`, then :n:`@term` must be of type :g:`I:`:math:`\forall`
- :g:`(x:T), I x -> s'` where :g:`s'` is the type of the goal.
+ :n:`@ident` has type :g:`(I t)` and :g:`I` has type :g:`forall (x:T), s`,
+ then :n:`@term` must be of type :g:`I:forall (x:T), I x -> s'` where
+ :g:`s'` is the type of the goal.
.. tacv:: dependent inversion @ident as @intro_pattern with @term
@@ -2164,7 +2164,7 @@ See also: :ref:`advanced-recursive-functions`
.. tacv:: dependent inversion_clear @ident with @term
- Like :tacn:`dependent inversion ...` with but clears :n:`@ident` from the
+ Like :tacn:`dependent inversion ... with ...` with but clears :n:`@ident` from the
local context.
.. tacv:: dependent inversion_clear @ident as @intro_pattern with @term
@@ -3194,7 +3194,7 @@ can solve such a goal:
Goal forall P:nat -> Prop, P 0 -> exists n, P n.
eauto.
-Note that :tacn:`ex_intro` should be declared as a hint.
+Note that ``ex_intro`` should be declared as a hint.
.. tacv:: {? info_}eauto {? @num} {? using {+ @lemma}} {? with {+ @ident}}
@@ -3240,7 +3240,9 @@ the processing of the rewriting rules.
The rewriting rule bases are built with the ``Hint Rewrite vernacular``
command.
-.. warn:: This tactic may loop if you build non terminating rewriting systems.
+.. warning::
+
+ This tactic may loop if you build non terminating rewriting systems.
.. tacv:: autorewrite with {+ @ident} using @tactic
@@ -3444,7 +3446,8 @@ The general command to add a hint to some databases :n:`{+ @ident}` is
Declares each :n:`@ident` as a transparent or opaque constant.
- .. cmdv:: Hint Extern @num {? @pattern} => tactic
+ .. cmdv:: Hint Extern @num {? @pattern} => @tactic
+ :name: Hint Extern
This hint type is to extend :tacn:`auto` with tactics other than :tacn:`apply` and
:tacn:`unfold`. For that, we must specify a cost, an optional :n:`@pattern` and a
@@ -3665,6 +3668,7 @@ option which accepts three flags allowing for a fine-grained handling of
non-imported hints.
.. opt:: Loose Hint Behavior %( "Lax" %| "Warn" %| "Strict" %)
+ :name: Loose Hint Behavior
This option accepts three values, which control the behavior of hints w.r.t.
:cmd:`Import`:
@@ -3809,14 +3813,15 @@ some incompatibilities.
.. tacv:: intuition
- Is equivalent to :g:`intuition auto with *`.
+ Is equivalent to :g:`intuition auto with *`.
.. tacv:: dintuition
+ :name: dintuition
- While :tacn:`intuition` recognizes inductively defined connectives
- isomorphic to the standard connective ``and, prod, or, sum, False,
- Empty_set, unit, True``, :tacn:`dintuition` recognizes also all inductive
- types with one constructors and no indices, i.e. record-style connectives.
+ While :tacn:`intuition` recognizes inductively defined connectives
+ isomorphic to the standard connective ``and``, ``prod``, ``or``, ``sum``, ``False``,
+ ``Empty_set``, ``unit``, ``True``, :tacn:`dintuition` recognizes also all inductive
+ types with one constructors and no indices, i.e. record-style connectives.
.. opt:: Intuition Negation Unfolding
@@ -3845,11 +3850,14 @@ first- order reasoning, written by Pierre Corbineau. It is not restricted to
usual logical connectives but instead may reason about any first-order class
inductive definition.
-.. opt:: Firstorder Solver
+.. opt:: Firstorder Solver @tactic
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 and
- printed using :cmd:`Print Firstorder Solver`.
+ :g:`auto with *`, it can be reset locally or globally using this option.
+
+ .. cmd:: Print Firstorder Solver
+
+ Prints the default tactic used by :tacn:`firstorder` when no rule applies.
.. tacv:: firstorder @tactic
@@ -4012,8 +4020,8 @@ solved by :tacn:`f_equal`.
:name: reflexivity
This tactic applies to a goal that has the form :g:`t=u`. It checks that `t`
-and `u` are convertible and then solves the goal. It is equivalent to apply
-:tacn:`refl_equal`.
+and `u` are convertible and then solves the goal. It is equivalent to
+``apply refl_equal``.
.. exn:: The conclusion is not a substitutive equation.
@@ -4105,7 +4113,7 @@ symbol :g:`=`.
:n:`intro @ident; simplify_eq @ident`.
.. tacn:: dependent rewrite -> @ident
- :name: dependent rewrite
+ :name: dependent rewrite ->
This tactic applies to any goal. If :n:`@ident` has type
:g:`(existT B a b)=(existT B a' b')` in the local context (i.e. each
@@ -4116,6 +4124,7 @@ symbol :g:`=`.
:tacn:`injection` and :tacn:`inversion` tactics.
.. tacv:: dependent rewrite <- @ident
+ :name: dependent rewrite <-
Analogous to :tacn:`dependent rewrite ->` but uses the equality from right to
left.
@@ -4375,19 +4384,20 @@ This tactics reverses the list of the focused goals.
unification, or they can be called back into focus with the command
:cmd:`Unshelve`.
-.. tacv:: shelve_unifiable
+ .. tacv:: shelve_unifiable
+ :name: shelve_unifiable
- Shelves only the goals under focus that are mentioned in other goals.
- Goals that appear in the type of other goals can be solved by unification.
+ Shelves only the goals under focus that are mentioned in other goals.
+ Goals that appear in the type of other goals can be solved by unification.
-.. example::
+ .. example::
- .. coqtop:: all reset
+ .. coqtop:: all reset
- Goal exists n, n=0.
- refine (ex_intro _ _ _).
- all:shelve_unifiable.
- reflexivity.
+ Goal exists n, n=0.
+ refine (ex_intro _ _ _).
+ all: shelve_unifiable.
+ reflexivity.
.. cmd:: Unshelve
diff --git a/doc/sphinx/proof-engine/vernacular-commands.rst b/doc/sphinx/proof-engine/vernacular-commands.rst
index 7ba103b22..c37233734 100644
--- a/doc/sphinx/proof-engine/vernacular-commands.rst
+++ b/doc/sphinx/proof-engine/vernacular-commands.rst
@@ -360,6 +360,7 @@ Requests to the environment
Search (?x * _ + ?x * _)%Z outside OmegaLemmas.
.. cmdv:: SearchAbout
+ :name: SearchAbout
.. deprecated:: 8.5
@@ -416,7 +417,7 @@ Requests to the environment
current goal (if any) and theorems of the current context whose
statement’s conclusion or last hypothesis and conclusion matches the
expressionterm where holes in the latter are denoted by `_`.
- It is a variant of Search @term_pattern that does not look for subterms
+ It is a variant of :n:`Search @term_pattern` that does not look for subterms
but searches for statements whose conclusion has exactly the expected
form, or whose statement finishes by the given series of
hypothesis/conclusion.
@@ -625,6 +626,7 @@ file is a particular case of module called *library file*.
.. cmdv:: Require Import @qualid
+ :name: Require Import
This loads and declares the module :n:`@qualid`
and its dependencies then imports the contents of :n:`@qualid` as described
@@ -637,10 +639,11 @@ file is a particular case of module called *library file*.
:cmd:`Import` :n:`@qualid` would.
.. cmdv:: Require Export @qualid
+ :name: Require Export
- This command acts as ``Require Import`` :n:`@qualid`,
- but if a further module, say `A`, contains a command ``Require Export`` `B`,
- then the command ``Require Import`` `A` also imports the module `B.`
+ This command acts as :cmd:`Require Import` :n:`@qualid`,
+ but if a further module, say `A`, contains a command :cmd:`Require Export` `B`,
+ then the command :cmd:`Require Import` `A` also imports the module `B.`
.. cmdv:: Require [Import | Export] {+ @qualid }
@@ -653,7 +656,7 @@ file is a particular case of module called *library file*.
.. cmdv:: From @dirpath Require @qualid
- This command acts as ``Require``, but picks
+ This command acts as :cmd:`Require`, but picks
any library whose absolute name is of the form dirpath.dirpath’.qualid
for some `dirpath’`. This is useful to ensure that the :n:`@qualid` library
comes from a given package by making explicit its absolute root.
@@ -895,6 +898,7 @@ interactively, they cannot be part of a vernacular file loaded via
necessary.
.. cmdv:: Backtrack @num @num @num
+ :name: Backtrack
.. deprecated:: 8.4
@@ -1022,12 +1026,14 @@ Controlling display
output, printing only identifiers.
.. opt:: Printing Width @num
+ :name: Printing Width
This command sets which left-aligned part of the width of the screen is used
for display. At the time of writing this documentation, the default value
is 78.
.. opt:: Printing Depth @num
+ :name: Printing Depth
This option controls the nesting depth of the formatter used for pretty-
printing. Beyond this depth, display of subterms is replaced by dots. At the
@@ -1208,28 +1214,29 @@ scope of their effect. There are four kinds of commands:
+ Commands whose default is to extend their effect both outside the
section and the module or library file they occur in. For these
commands, the Local modifier limits the effect of the command to the
- current section or module it occurs in. As an example, the ``Coercion``
- (see Section :ref:`coercions`) and ``Strategy`` (see :ref:`here <vernac-strategy>`)
- commands belong to this category.
+ current section or module it occurs in. As an example, the :cmd:`Coercion`
+ and :cmd:`Strategy` commands belong to this category.
+ Commands whose default behavior is to stop their effect at the end
of the section they occur in but to extent their effect outside the module or
library file they occur in. For these commands, the Local modifier limits the
effect of the command to the current module if the command does not occur in a
section and the Global modifier extends the effect outside the current
sections and current module if the command occurs in a section. As an example,
- the :cmd:`Implicit Arguments`, :cmd:`Ltac` or :cmd:`Notation` commands belong
+ the :cmd:`Arguments`, :cmd:`Ltac` or :cmd:`Notation` commands belong
to this category. Notice that a subclass of these commands do not support
extension of their scope outside sections at all and the Global is not
applicable to them.
+ Commands whose default behavior is to stop their effect at the end
- of the section or module they occur in. For these commands, the Global
+ of the section or module they occur in. For these commands, the ``Global``
modifier extends their effect outside the sections and modules they
- occurs in. The ``Transparent`` and ``Opaque`` (see Section :ref:`vernac-controlling-the-reduction-strategies`) commands belong to this category.
+ occurs in. The :cmd:`Transparent` and :cmd:`Opaque`
+ (see Section :ref:`vernac-controlling-the-reduction-strategies`) commands
+ belong to this category.
+ Commands whose default behavior is to extend their effect outside
sections but not outside modules when they occur in a section and to
extend their effect outside the module or library file they occur in
when no section contains them.For these commands, the Local modifier
limits the effect to the current section or module while the Global
modifier extends the effect outside the module even when the command
- occurs in a section. The ``Set`` and ``Unset`` commands belong to this
+ occurs in a section. The :cmd:`Set` and :cmd:`Unset` commands belong to this
category.
diff --git a/doc/sphinx/user-extensions/proof-schemes.rst b/doc/sphinx/user-extensions/proof-schemes.rst
index e12e4d897..838926d65 100644
--- a/doc/sphinx/user-extensions/proof-schemes.rst
+++ b/doc/sphinx/user-extensions/proof-schemes.rst
@@ -26,6 +26,7 @@ induction for objects in type `identᵢ`.
natural in case of inductively defined relations.
.. cmdv:: Scheme Equality for @ident
+ :name: Scheme Equality
Tries to generate a Boolean equality and a proof of the decidability of the usual equality. If `ident`
involves some other inductive types, their equality has to be defined first.
@@ -105,15 +106,15 @@ Automatic declaration of schemes
.. opt:: 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``.
+ 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``.
.. opt:: 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.
+ This option controls whether types declared with the keywords :cmd:`Variant` and
+ :cmd:`Record` get an automatic declaration of the induction principles.
.. opt:: Case Analysis Schemes
@@ -124,8 +125,8 @@ This option controls whether types declared with the keywords :cmd:`Variant` and
.. opt:: Decidable Equality Schemes
-These flags control the automatic declaration of those Boolean equalities (see
-the second variant of ``Scheme``).
+ These flags control the automatic declaration of those Boolean equalities (see
+ the second variant of ``Scheme``).
.. warning::
diff --git a/doc/sphinx/user-extensions/syntax-extensions.rst b/doc/sphinx/user-extensions/syntax-extensions.rst
index 6958b5f26..3b95a37ed 100644
--- a/doc/sphinx/user-extensions/syntax-extensions.rst
+++ b/doc/sphinx/user-extensions/syntax-extensions.rst
@@ -916,9 +916,8 @@ Binding arguments of a constant to an interpretation scope
.. seealso::
- :cmd:`About @qualid`
- The command to show the scopes bound to the arguments of a
- function is described in Section 2.
+ The command :cmd:`About` can be used to show the scopes bound to the
+ arguments of a function.
.. note::
diff --git a/doc/tools/coqrst/coqdoc/main.py b/doc/tools/coqrst/coqdoc/main.py
index d464f75bb..a004959eb 100644
--- a/doc/tools/coqrst/coqdoc/main.py
+++ b/doc/tools/coqrst/coqdoc/main.py
@@ -32,8 +32,9 @@ COQDOC_OPTIONS = ['--body-only', '--no-glob', '--no-index', '--no-externals',
COQDOC_SYMBOLS = ["->", "<-", "<->", "=>", "<=", ">=", "<>", "~", "/\\", "\\/", "|-", "*", "forall", "exists"]
COQDOC_HEADER = "".join("(** remove printing {} *)".format(s) for s in COQDOC_SYMBOLS)
-def coqdoc(coq_code, coqdoc_bin = os.path.join(os.getenv("COQBIN"),"coqdoc")):
+def coqdoc(coq_code, coqdoc_bin=None):
"""Get the output of coqdoc on coq_code."""
+ coqdoc_bin = coqdoc_bin or os.path.join(os.getenv("COQBIN"), "coqdoc")
fd, filename = mkstemp(prefix="coqdoc-", suffix=".v")
try:
os.write(fd, COQDOC_HEADER.encode("utf-8"))
diff --git a/doc/tools/coqrst/coqdomain.py b/doc/tools/coqrst/coqdomain.py
index f09ed4b55..606d725bf 100644
--- a/doc/tools/coqrst/coqdomain.py
+++ b/doc/tools/coqrst/coqdomain.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
##########################################################################
## # The Coq Proof Assistant / The Coq Development Team ##
## v # INRIA, CNRS and contributors - Copyright 1999-2018 ##
@@ -57,30 +58,37 @@ def make_target(objtype, targetid):
return "coq:{}.{}".format(objtype, targetid)
class CoqObject(ObjectDescription):
- """A generic Coq object; all Coq objects are subclasses of this.
+ """A generic Coq object for Sphinx; all Coq objects are subclasses of this.
The fields and methods to override are listed at the top of this class'
implementation. Each object supports the :name: option, which gives an
explicit name to link to.
- See the documentation of CoqDomain for high-level information.
+ See the comments and docstrings in CoqObject for more information.
"""
- # The semantic domain in which this object lives.
+ # The semantic domain in which this object lives (eg. “tac”, “cmd”, “chm”…).
# It matches exactly one of the roles used for cross-referencing.
- subdomain = None
+ subdomain = None # type: str
- # The suffix to use in indices for objects of this type
- index_suffix = None
+ # The suffix to use in indices for objects of this type (eg. “(tac)”)
+ index_suffix = None # type: str
# The annotation to add to headers of objects of this type
- annotation = None
+ # (eg. “Command”, “Theorem”)
+ annotation = None # type: str
def _name_from_signature(self, signature): # pylint: disable=no-self-use, unused-argument
"""Convert a signature into a name to link to.
+ ‘Signature’ is Sphinx parlance for an object's header (think “type
+ signature”); for example, the signature of the simplest form of the
+ ``exact`` tactic is ``exact @id``.
+
Returns None by default, in which case no name will be automatically
- generated.
+ generated. This is a convenient way to automatically generate names
+ (link targets) without having to write explicit names everywhere.
+
"""
return None
@@ -100,7 +108,7 @@ class CoqObject(ObjectDescription):
def handle_signature(self, signature, signode):
"""Prefix signature with the proper annotation, then render it using
- _render_signature.
+ ``_render_signature`` (for example, add “Command” in front of commands).
:returns: the name given to the resulting node, if any
"""
@@ -110,11 +118,6 @@ class CoqObject(ObjectDescription):
self._render_signature(signature, signode)
return self.options.get("name") or self._name_from_signature(signature)
- @property
- def _index_suffix(self):
- if self.index_suffix:
- return " " + self.index_suffix
-
def _record_name(self, name, target_id):
"""Record a name, mapping it to target_id
@@ -141,12 +144,14 @@ class CoqObject(ObjectDescription):
return targetid
def _add_index_entry(self, name, target):
- """Add name (with target) to the main index."""
- index_text = name + self._index_suffix
+ """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))
def add_target_and_index(self, name, _, signode):
- """Create a target and an index entry for name"""
+ """Attach a link target to `signode` and an index entry for `name`."""
if name:
target = self._add_target(signode, name)
# remove trailing . , found in commands, but not ... (ellipsis)
@@ -156,31 +161,44 @@ class CoqObject(ObjectDescription):
return target
class PlainObject(CoqObject):
- """A base class for objects whose signatures should be rendered literaly."""
+ """A base class for objects whose signatures should be rendered literally."""
def _render_signature(self, signature, signode):
signode += addnodes.desc_name(signature, signature)
class NotationObject(CoqObject):
- """A base class for objects whose signatures should be rendered as nested boxes."""
+ """A base class for objects whose signatures should be rendered as nested boxes.
+
+ Objects that inherit from this class can use the notation grammar (“{+ …}”,
+ “@…”, etc.) in their signature.
+ """
def _render_signature(self, signature, signode):
position = self.state_machine.get_source_and_line(self.lineno)
tacn_node = parse_notation(signature, *position)
signode += addnodes.desc_name(signature, '', tacn_node)
-class TacticObject(PlainObject):
- """An object to represent Coq tactics"""
- subdomain = "tac"
- index_suffix = "(tac)"
- annotation = None
-
class GallinaObject(PlainObject):
- """An object to represent Coq theorems"""
+ r"""A theorem.
+
+ Example::
+
+ .. thm:: Bound on the ceiling function
+
+ Let :math:`p` be an integer and :math:`c` a rational constant. Then
+ :math:`p \ge c \rightarrow p \ge \lceil{c}\rceil`.
+ """
subdomain = "thm"
index_suffix = "(thm)"
annotation = "Theorem"
class VernacObject(NotationObject):
- """An object to represent Coq commands"""
+ """A Coq command.
+
+ Example::
+
+ .. cmd:: Infix "@symbol" := @term ({+, @modifier}).
+
+ This command is equivalent to :n:`…`.
+ """
subdomain = "cmd"
index_suffix = "(cmd)"
annotation = "Command"
@@ -191,7 +209,20 @@ class VernacObject(NotationObject):
return m.group(0).strip()
class VernacVariantObject(VernacObject):
- """An object to represent variants of Coq commands"""
+ """A variant of a Coq command.
+
+ Example::
+
+ .. cmd:: Axiom @ident : @term.
+
+ This command links :token:`term` to the name :token:`term` as its specification in
+ the global context. The fact asserted by :token:`term` is thus assumed as a
+ postulate.
+
+ .. cmdv:: Parameter @ident : @term.
+
+ This is equivalent to :n:`Axiom @ident : @term`.
+ """
index_suffix = "(cmdv)"
annotation = "Variant"
@@ -199,18 +230,49 @@ class VernacVariantObject(VernacObject):
return None
class TacticNotationObject(NotationObject):
- """An object to represent Coq tactic notations"""
+ """A tactic, or a tactic notation.
+
+ Example::
+
+ .. tacn:: do @num @expr
+
+ :token:`expr` is evaluated to ``v`` which must be a tactic value. …
+ """
subdomain = "tacn"
index_suffix = "(tacn)"
annotation = None
class TacticNotationVariantObject(TacticNotationObject):
- """An object to represent variants of Coq tactic notations"""
+ """A variant of a tactic.
+
+ Example::
+
+ .. tacn:: fail
+
+ This is the always-failing tactic: it does not solve any goal. It is
+ useful for defining other tacticals since it can be caught by
+ :tacn:`try`, :tacn:`repeat`, :tacn:`match goal`, or the branching
+ tacticals. …
+
+ .. tacv:: fail @natural
+
+ The number is the failure level. If no level is specified, it
+ defaults to 0. …
+ """
index_suffix = "(tacnv)"
annotation = "Variant"
class OptionObject(NotationObject):
- """An object to represent Coq options"""
+ """A Coq option.
+
+ Example::
+
+ .. opt:: 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.
+ """
subdomain = "opt"
index_suffix = "(opt)"
annotation = "Option"
@@ -219,7 +281,13 @@ class OptionObject(NotationObject):
return stringify_with_ellipses(signature)
class ProductionObject(NotationObject):
- """An object to represent grammar productions"""
+ """Grammar productions.
+
+ This is useful if you intend to document individual grammar productions.
+ Otherwise, use Sphinx's `production lists
+ <http://www.sphinx-doc.org/en/stable/markup/para.html#directive-productionlist>`_.
+ """
+ # FIXME (CPC): I have no idea what this does :/ Someone should add an example.
subdomain = "prodn"
index_suffix = None
annotation = None
@@ -258,7 +326,22 @@ class ProductionObject(NotationObject):
return [idx, node]
class ExceptionObject(NotationObject):
- """An object to represent Coq errors."""
+ """An error raised by a Coq command or tactic.
+
+ This commonly appears nested in the ``.. tacn::`` that raises the
+ exception.
+
+ Example::
+
+ .. tacv:: assert @form by @tactic
+
+ This tactic applies :n:`@tactic` to solve the subgoals generated by
+ ``assert``.
+
+ .. exn:: Proof is not complete
+
+ Raised if :n:`@tactic` does not fully solve the goal.
+ """
subdomain = "exn"
index_suffix = "(err)"
annotation = "Error"
@@ -269,7 +352,19 @@ class ExceptionObject(NotationObject):
return stringify_with_ellipses(signature)
class WarningObject(NotationObject):
- """An object to represent Coq warnings."""
+ """An warning raised by a Coq command or tactic..
+
+ Do not mistake this for ``.. warning::``; this directive is for warning
+ messages produced by Coq.
+
+
+ Example::
+
+ .. warn:: Ambiguous path
+
+ When the coercion :token:`qualid` is added to the inheritance graph, non
+ valid coercion paths are ignored.
+ """
subdomain = "warn"
index_suffix = "(warn)"
annotation = "Warning"
@@ -280,14 +375,33 @@ class WarningObject(NotationObject):
def NotationRole(role, rawtext, text, lineno, inliner, options={}, content=[]):
#pylint: disable=unused-argument, dangerous-default-value
- """And inline role for notations"""
+ """Any text using the notation syntax (``@id``, ``{+, …}``, etc.).
+
+ Use this to explain tactic equivalences. For example, you might write
+ this::
+
+ :n:`generalize @term as @ident` is just like :n:`generalize @term`, but
+ 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:``
+ creates a link to that. When referring to a placeholder that happens to be
+ a grammar production, ``:token:`…``` is typically preferable to ``:n:`@…```.
+ """
notation = utils.unescape(text, 1)
position = inliner.reporter.get_source_and_line(lineno)
return [nodes.literal(rawtext, '', parse_notation(notation, *position, rawtext=rawtext))], []
def coq_code_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
#pylint: disable=dangerous-default-value
- """And inline role for Coq source code"""
+ """Coq code.
+
+ Use this for Gallina and Ltac snippets::
+
+ :g:`apply plus_comm; reflexivity`
+ :g:`Set Printing All.`
+ :g:`forall (x: t), P(x)`
+ """
options['language'] = 'Coq'
return code_role(role, rawtext, text, lineno, inliner, options, content)
## Too heavy:
@@ -300,15 +414,14 @@ def coq_code_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
# node = nodes.literal(rawtext, '', *highlight_using_coqdoc(code), classes=classes)
# return [node], []
-# TODO pass different languages?
-LtacRole = GallinaRole = VernacRole = coq_code_role
+CoqCodeRole = coq_code_role
class CoqtopDirective(Directive):
"""A reST directive to describe interactions with Coqtop.
Usage::
- .. coqtop:: (options)+
+ .. coqtop:: options…
Coq code to send to coqtop
@@ -321,20 +434,28 @@ class CoqtopDirective(Directive):
Here is a list of permissible options:
- Display
- - ‘all’: Display input and output
- - ‘in’: Display only input
- - ‘out’: Display only output
- - ‘none’: Display neither (useful for setup commands)
- Behaviour
- - ‘reset’: Send a `Reset Initial` command before running this block
- - ‘undo’: Send an `Undo n` (n=number of sentences) command after running
- all the commands in this block
+ - Display options
+
+ - ``all``: Display input and output
+ - ``in``: Display only input
+ - ``out``: Display only output
+ - ``none``: Display neither (useful for setup commands)
+
+ - Behavior options
+
+ - ``reset``: Send a ``Reset Initial`` command before running this block
+ - ``undo``: Send an ``Undo n`` (``n`` = number of sentences) command after
+ running all the commands in this block
+
+ ``coqtop``\ 's state is preserved across consecutive ``.. coqtop::`` blocks
+ of the same document (``coqrst`` creates a single ``coqtop`` process per
+ reST source file). Use the ``reset`` option to reset Coq's state.
"""
has_content = True
required_arguments = 0
optional_arguments = 1
final_argument_whitespace = True
+ directive_name = "coqtop"
def run(self):
# Uses a ‘container’ instead of a ‘literal_block’ to disable
@@ -349,12 +470,26 @@ class CoqtopDirective(Directive):
return [node]
class CoqdocDirective(Directive):
- """A reST directive to display Coqtop-formatted source code"""
+ """A reST directive to display Coqtop-formatted source code.
+
+ Usage::
+
+ .. coqdoc::
+
+ Coq code to highlight
+
+ Example::
+
+ .. coqdoc::
+
+ Definition test := 1.
+ """
# TODO implement this as a Pygments highlighter?
has_content = True
required_arguments = 0
optional_arguments = 0
final_argument_whitespace = True
+ directive_name = "coqdoc"
def run(self):
# Uses a ‘container’ instead of a ‘literal_block’ to disable
@@ -365,8 +500,24 @@ class CoqdocDirective(Directive):
return [wrapper]
class ExampleDirective(BaseAdmonition):
- """A reST directive for examples"""
+ """A reST directive for examples.
+
+ This behaves like a generic admonition; see
+ http://docutils.sourceforge.net/docs/ref/rst/directives.html#generic-admonition
+ for more details.
+
+ Example::
+
+ .. example:: Adding a hint to a database
+
+ The following adds ``plus_comm`` to the ``plu`` database:
+
+ .. coqdoc::
+
+ Hint Resolve plus_comm : plu.
+ """
node_class = nodes.admonition
+ directive_name = "example"
def run(self):
# ‘BaseAdmonition’ checks whether ‘node_class’ is ‘nodes.admonition’,
@@ -380,8 +531,17 @@ class ExampleDirective(BaseAdmonition):
class PreambleDirective(MathDirective):
r"""A reST directive for hidden math.
- Mostly useful to let MathJax know about `\def`s and `\newcommand`s
+ Mostly useful to let MathJax know about `\def`\ s and `\newcommand`\ s.
+
+ Example::
+
+ .. preamble::
+
+ \newcommand{\paren}[#1]{\left(#1\right)}
"""
+
+ directive_name = "preamble"
+
def run(self):
self.options['nowrap'] = True
[node] = super().run()
@@ -389,14 +549,17 @@ class PreambleDirective(MathDirective):
return [node]
class InferenceDirective(Directive):
- r"""A small example of what directives let you do in Sphinx.
+ r"""A reST directive to format inference rules.
+
+ This also serves as a small illustration of the way to create new Sphinx
+ directives.
Usage::
.. inference:: name
- \n-separated premisses
- ----------------------
+ newline-separated premisses
+ ------------------------
conclusion
Example::
@@ -413,6 +576,7 @@ class InferenceDirective(Directive):
optional_arguments = 0
has_content = True
final_argument_whitespace = True
+ directive_name = "inference"
def make_math_node(self, latex):
node = displaymath()
@@ -613,7 +777,7 @@ class CoqSubdomainsIndex(Index):
Just as in the original manual, we want to have separate indices for each
Coq subdomain (tactics, commands, options, etc)"""
- name, localname, shortname, subdomains = None, None, None, None # Must be overwritten
+ name, localname, shortname, subdomains = None, None, None, [] # Must be overwritten
def generate(self, docnames=None):
content = defaultdict(list)
@@ -635,7 +799,7 @@ class CoqVernacIndex(CoqSubdomainsIndex):
name, localname, shortname, subdomains = "cmdindex", "Command Index", "commands", ["cmd"]
class CoqTacticIndex(CoqSubdomainsIndex):
- name, localname, shortname, subdomains = "tacindex", "Tactic Index", "tactics", ["tac", "tacn"]
+ name, localname, shortname, subdomains = "tacindex", "Tactic Index", "tactics", ["tacn"]
class CoqOptionIndex(CoqSubdomainsIndex):
name, localname, shortname, subdomains = "optindex", "Option Index", "options", ["opt"]
@@ -665,10 +829,18 @@ class IndexXRefRole(XRefRole):
return title, target
def GrammarProductionRole(typ, rawtext, text, lineno, inliner, options={}, content=[]):
- """An inline role to declare grammar productions that are not in fact included
- in a `productionlist` directive.
+ """A grammar production not included in a ``productionlist`` directive.
- Useful to informally introduce a production, as part of running text
+ Useful to informally introduce a production, as part of running text.
+
+ Example::
+
+ :production:`string` indicates a quoted string.
+
+ You're not likely to use this role very commonly; instead, use a
+ `production list
+ <http://www.sphinx-doc.org/en/stable/markup/para.html#directive-productionlist>`_
+ and reference its tokens using ``:token:`…```.
"""
#pylint: disable=dangerous-default-value, unused-argument
env = inliner.document.settings.env
@@ -681,6 +853,8 @@ def GrammarProductionRole(typ, rawtext, text, lineno, inliner, options={}, conte
env.domaindata['std']['objects']['token', text] = env.docname, targetid
return [node], []
+GrammarProductionRole.role_name = "production"
+
class CoqDomain(Domain):
"""A domain to document Coq code.
@@ -703,7 +877,6 @@ class CoqDomain(Domain):
# ObjType (= directive type) → (Local name, *xref-roles)
'cmd': ObjType('cmd', 'cmd'),
'cmdv': ObjType('cmdv', 'cmd'),
- 'tac': ObjType('tac', 'tac'),
'tacn': ObjType('tacn', 'tacn'),
'tacv': ObjType('tacv', 'tacn'),
'opt': ObjType('opt', 'opt'),
@@ -720,7 +893,6 @@ class CoqDomain(Domain):
# the same role.
'cmd': VernacObject,
'cmdv': VernacVariantObject,
- 'tac': TacticObject,
'tacn': TacticNotationObject,
'tacv': TacticNotationVariantObject,
'opt': OptionObject,
@@ -732,23 +904,18 @@ class CoqDomain(Domain):
roles = {
# Each of these roles lives in a different semantic “subdomain”
- 'cmd': XRefRole(),
- 'tac': XRefRole(),
- 'tacn': XRefRole(),
- 'opt': XRefRole(),
- 'thm': XRefRole(),
- 'prodn' : XRefRole(),
- 'exn': XRefRole(),
- 'warn': XRefRole(),
+ 'cmd': XRefRole(warn_dangling=True),
+ 'tacn': XRefRole(warn_dangling=True),
+ 'opt': XRefRole(warn_dangling=True),
+ 'thm': XRefRole(warn_dangling=True),
+ 'prodn' : XRefRole(warn_dangling=True),
+ 'exn': XRefRole(warn_dangling=True),
+ 'warn': XRefRole(warn_dangling=True),
# This one is special
'index': IndexXRefRole(),
# These are used for highlighting
- 'notation': NotationRole,
- 'gallina': GallinaRole,
- 'ltac': LtacRole,
'n': NotationRole,
- 'g': GallinaRole,
- 'l': LtacRole, #FIXME unused?
+ 'g': CoqCodeRole
}
indices = [CoqVernacIndex, CoqTacticIndex, CoqOptionIndex, CoqGallinaIndex, CoqProductionIndex, CoqExceptionIndex]
@@ -759,7 +926,6 @@ class CoqDomain(Domain):
# others, such as “version”
'objects' : { # subdomain → name → docname, objtype, targetid
'cmd': {},
- 'tac': {},
'tacn': {},
'opt': {},
'thm': {},
@@ -829,11 +995,18 @@ def simplify_source_code_blocks_for_latex(app, doctree, fromdocname): # pylint:
for node in doctree.traverse(is_coqtop_or_coqdoc_block):
if is_html:
node.rawsource = '' # Prevent pygments from kicking in
+ elif 'coqtop-hidden' in node['classes']:
+ node.parent.remove(node)
else:
- if 'coqtop-hidden' in node['classes']:
- node.parent.remove(node)
- else:
- node.replace_self(nodes.literal_block(node.rawsource, node.rawsource, language="Coq"))
+ node.replace_self(nodes.literal_block(node.rawsource, node.rawsource, language="Coq"))
+
+COQ_ADDITIONAL_DIRECTIVES = [CoqtopDirective,
+ CoqdocDirective,
+ ExampleDirective,
+ InferenceDirective,
+ PreambleDirective]
+
+COQ_ADDITIONAL_ROLES = [GrammarProductionRole]
def setup(app):
"""Register the Coq domain"""
@@ -845,12 +1018,13 @@ def setup(app):
# Add domain, directives, and roles
app.add_domain(CoqDomain)
- app.add_role("production", GrammarProductionRole)
- app.add_directive("coqtop", CoqtopDirective)
- app.add_directive("coqdoc", CoqdocDirective)
- app.add_directive("example", ExampleDirective)
- app.add_directive("inference", InferenceDirective)
- app.add_directive("preamble", PreambleDirective)
+
+ for role in COQ_ADDITIONAL_ROLES:
+ app.add_role(role.role_name, role)
+
+ for directive in COQ_ADDITIONAL_DIRECTIVES:
+ app.add_directive(directive.directive_name, directive)
+
app.add_transform(CoqtopBlocksTransform)
app.connect('doctree-resolved', simplify_source_code_blocks_for_latex)
diff --git a/doc/tools/coqrst/regen_readme.py b/doc/tools/coqrst/regen_readme.py
new file mode 100755
index 000000000..e56882a52
--- /dev/null
+++ b/doc/tools/coqrst/regen_readme.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+"""Rebuild sphinx/README.rst from sphinx/README.template.rst."""
+
+import re
+from os import sys, path
+
+SCRIPT_DIR = path.dirname(path.abspath(__file__))
+if __name__ == "__main__" and __package__ is None:
+ sys.path.append(path.dirname(SCRIPT_DIR))
+
+import sphinx
+from coqrst import coqdomain
+
+README_ROLES_MARKER = "[ROLES]"
+README_OBJECTS_MARKER = "[OBJECTS]"
+README_DIRECTIVES_MARKER = "[DIRECTIVES]"
+
+FIRST_LINE_BLANKS = re.compile("^(.*)\n *\n")
+def format_docstring(template, obj, *strs):
+ docstring = obj.__doc__.strip()
+ strs = strs + (FIRST_LINE_BLANKS.sub(r"\1\n", docstring),)
+ return template.format(*strs)
+
+SPHINX_DIR = path.join(SCRIPT_DIR, "../../sphinx/")
+README_PATH = path.join(SPHINX_DIR, "README.rst")
+README_TEMPLATE_PATH = path.join(SPHINX_DIR, "README.template.rst")
+
+def notation_symbol(d):
+ return " :black_nib:" if issubclass(d, coqdomain.NotationObject) else ""
+
+def regen_readme():
+ objects_docs = [format_docstring("``.. {}::``{} {}", obj, objname, notation_symbol(obj))
+ for objname, obj in sorted(coqdomain.CoqDomain.directives.items())]
+
+ roles = ([(name, cls)
+ for name, cls in sorted(coqdomain.CoqDomain.roles.items())
+ if not isinstance(cls, (sphinx.roles.XRefRole, coqdomain.IndexXRefRole))] +
+ [(fn.role_name, fn)
+ for fn in coqdomain.COQ_ADDITIONAL_ROLES])
+ roles_docs = [format_docstring("``:{}:`` {}", role, name)
+ for (name, role) in roles]
+
+ directives_docs = [format_docstring("``.. {}::`` {}", d, d.directive_name)
+ for d in coqdomain.COQ_ADDITIONAL_DIRECTIVES]
+
+ with open(README_TEMPLATE_PATH, encoding="utf-8") as readme:
+ contents = readme.read()
+
+ with open(README_PATH, mode="w", encoding="utf-8") as readme:
+ readme.write(contents
+ .replace(README_ROLES_MARKER, "\n\n".join(roles_docs))
+ .replace(README_OBJECTS_MARKER, "\n\n".join(objects_docs))
+ .replace(README_DIRECTIVES_MARKER, "\n\n".join(directives_docs)))
+
+if __name__ == '__main__':
+ regen_readme()
diff --git a/doc/tools/coqrst/repl/coqtop.py b/doc/tools/coqrst/repl/coqtop.py
index efb5cb550..aeadce4c4 100644
--- a/doc/tools/coqrst/repl/coqtop.py
+++ b/doc/tools/coqrst/repl/coqtop.py
@@ -41,7 +41,9 @@ class CoqTop:
the ansicolors module)
:param args: Additional arugments to coqtop.
"""
- self.coqtop_bin = coqtop_bin or os.path.join(os.getenv('COQBIN'),"coqtop")
+ self.coqtop_bin = coqtop_bin or os.path.join(os.getenv('COQBIN', ""), "coqtop")
+ if not pexpect.utils.which(self.coqtop_bin):
+ raise ValueError("coqtop binary not found: '{}'".format(self.coqtop_bin))
self.args = (args or []) + ["-boot", "-color", "on"] * color
self.coqtop = None
diff --git a/doc/tutorial/Tutorial.tex b/doc/tutorial/Tutorial.tex
deleted file mode 100644
index 77ce8574f..000000000
--- a/doc/tutorial/Tutorial.tex
+++ /dev/null
@@ -1,1575 +0,0 @@
-\documentclass[11pt,a4paper]{book}
-\usepackage[T1]{fontenc}
-\usepackage[utf8]{inputenc}
-\usepackage{textcomp}
-\usepackage{pslatex}
-\usepackage{hyperref}
-
-\input{../common/version.tex}
-\input{../common/macros.tex}
-\input{../common/title.tex}
-
-%\makeindex
-
-\begin{document}
-\coverpage{A Tutorial}{Gérard Huet, Gilles Kahn and Christine Paulin-Mohring}{}
-
-%\tableofcontents
-
-\chapter*{Getting started}
-
-\Coq{} is a Proof Assistant for a Logical Framework known as the Calculus
-of Inductive Constructions. It allows the interactive construction of
-formal proofs, and also the manipulation of functional programs
-consistently with their specifications. It runs as a computer program
-on many architectures.
-
-It is available with a variety of user interfaces. The present
-document does not attempt to present a comprehensive view of all the
-possibilities of \Coq, but rather to present in the most elementary
-manner a tutorial on the basic specification language, called Gallina,
-in which formal axiomatisations may be developed, and on the main
-proof tools. For more advanced information, the reader could refer to
-the \Coq{} Reference Manual or the \textit{Coq'Art}, a book by Y.
-Bertot and P. Castéran on practical uses of the \Coq{} system.
-
-Instructions on installation procedures, as well as more comprehensive
-documentation, may be found in the standard distribution of \Coq,
-which may be obtained from \Coq{} web site
-\url{https://coq.inria.fr/}\footnote{You can report any bug you find
-while using \Coq{} at \url{https://coq.inria.fr/bugs}. Make sure to
-always provide a way to reproduce it and to specify the exact version
-you used. You can get this information by running \texttt{coqc -v}}.
-\Coq{} is distributed together with a graphical user interface called
-CoqIDE. Alternative interfaces exist such as
-Proof General\footnote{See \url{https://proofgeneral.github.io/}.}.
-
-In the following examples, lines preceded by the prompt \verb:Coq < :
-represent user input, terminated by a period.
-The following lines usually show \Coq's answer.
-When used from a graphical user interface such as
-CoqIDE, the prompt is not displayed: user input is given in one window
-and \Coq's answers are displayed in a different window.
-
-\chapter{Basic Predicate Calculus}
-
-\section{An overview of the specification language Gallina}
-
-A formal development in Gallina consists in a sequence of {\sl declarations}
-and {\sl definitions}.
-
-\subsection{Declarations}
-
-A declaration associates a {\sl name} with a {\sl specification}.
-A name corresponds roughly to an identifier in a programming
-language, i.e. to a string of letters, digits, and a few ASCII symbols like
-underscore (\verb"_") and prime (\verb"'"), starting with a letter.
-We use case distinction, so that the names \verb"A" and \verb"a" are distinct.
-Certain strings are reserved as key-words of \Coq, and thus are forbidden
-as user identifiers.
-
-A specification is a formal expression which classifies the notion which is
-being declared. There are basically three kinds of specifications:
-{\sl logical propositions}, {\sl mathematical collections}, and
-{\sl abstract types}. They are classified by the three basic sorts
-of the system, called respectively \verb:Prop:, \verb:Set:, and
-\verb:Type:, which are themselves atomic abstract types.
-
-Every valid expression $e$ in Gallina is associated with a specification,
-itself a valid expression, called its {\sl type} $\tau(E)$. We write
-$e:\tau(E)$ for the judgment that $e$ is of type $E$.
-You may request \Coq{} to return to you the type of a valid expression by using
-the command \verb:Check::
-
-\begin{coq_eval}
-Set Printing Width 60.
-\end{coq_eval}
-
-\begin{coq_example}
-Check O.
-\end{coq_example}
-
-Thus we know that the identifier \verb:O: (the name `O', not to be
-confused with the numeral `0' which is not a proper identifier!) is
-known in the current context, and that its type is the specification
-\verb:nat:. This specification is itself classified as a mathematical
-collection, as we may readily check:
-
-\begin{coq_example}
-Check nat.
-\end{coq_example}
-
-The specification \verb:Set: is an abstract type, one of the basic
-sorts of the Gallina language, whereas the notions $nat$ and $O$ are
-notions which are defined in the arithmetic prelude,
-automatically loaded when running the \Coq{} system.
-
-We start by introducing a so-called section name. The role of sections
-is to structure the modelisation by limiting the scope of parameters,
-hypotheses and definitions. It will also give a convenient way to
-reset part of the development.
-
-\begin{coq_example}
-Section Declaration.
-\end{coq_example}
-With what we already know, we may now enter in the system a declaration,
-corresponding to the informal mathematics {\sl let n be a natural
- number}.
-
-\begin{coq_example}
-Variable n : nat.
-\end{coq_example}
-
-If we want to translate a more precise statement, such as
-{\sl let n be a positive natural number},
-we have to add another declaration, which will declare explicitly the
-hypothesis \verb:Pos_n:, with specification the proper logical
-proposition:
-\begin{coq_example}
-Hypothesis Pos_n : (gt n 0).
-\end{coq_example}
-
-Indeed we may check that the relation \verb:gt: is known with the right type
-in the current context:
-
-\begin{coq_example}
-Check gt.
-\end{coq_example}
-
-which tells us that \texttt{gt} is a function expecting two arguments of
-type \texttt{nat} in order to build a logical proposition.
-What happens here is similar to what we are used to in a functional
-programming language: we may compose the (specification) type \texttt{nat}
-with the (abstract) type \texttt{Prop} of logical propositions through the
-arrow function constructor, in order to get a functional type
-\texttt{nat -> Prop}:
-\begin{coq_example}
-Check (nat -> Prop).
-\end{coq_example}
-which may be composed once more with \verb:nat: in order to obtain the
-type \texttt{nat -> nat -> Prop} of binary relations over natural numbers.
-Actually the type \texttt{nat -> nat -> Prop} is an abbreviation for
-\texttt{nat -> (nat -> Prop)}.
-
-Functional notions may be composed in the usual way. An expression $f$
-of type $A\ra B$ may be applied to an expression $e$ of type $A$ in order
-to form the expression $(f~e)$ of type $B$. Here we get that
-the expression \verb:(gt n): is well-formed of type \texttt{nat -> Prop},
-and thus that the expression \verb:(gt n O):, which abbreviates
-\verb:((gt n) O):, is a well-formed proposition.
-\begin{coq_example}
-Check gt n O.
-\end{coq_example}
-
-\subsection{Definitions}
-
-The initial prelude contains a few arithmetic definitions:
-\texttt{nat} is defined as a mathematical collection (type \texttt{Set}),
-constants \texttt{O}, \texttt{S}, \texttt{plus}, are defined as objects of
-types respectively \texttt{nat}, \texttt{nat -> nat}, and \texttt{nat ->
-nat -> nat}.
-You may introduce new definitions, which link a name to a well-typed value.
-For instance, we may introduce the constant \texttt{one} as being defined
-to be equal to the successor of zero:
-\begin{coq_example}
-Definition one := (S O).
-\end{coq_example}
-We may optionally indicate the required type:
-\begin{coq_example}
-Definition two : nat := S one.
-\end{coq_example}
-
-Actually \Coq{} allows several possible syntaxes:
-\begin{coq_example}
-Definition three := S two : nat.
-\end{coq_example}
-
-Here is a way to define the doubling function, which expects an
-argument \verb:m: of type \verb:nat: in order to build its result as
-\verb:(plus m m)::
-
-\begin{coq_example}
-Definition double (m : nat) := plus m m.
-\end{coq_example}
-This introduces the constant \texttt{double} defined as the
-expression \texttt{fun m : nat => plus m m}.
-The abstraction introduced by \texttt{fun} is explained as follows.
-The expression \texttt{fun x : A => e} is well formed of type
-\texttt{A -> B} in a context whenever the expression \texttt{e} is
-well-formed of type \texttt{B} in the given context to which we add the
-declaration that \texttt{x} is of type \texttt{A}. Here \texttt{x} is a
-bound, or dummy variable in the expression \texttt{fun x : A => e}.
-For instance we could as well have defined \texttt{double} as
-\texttt{fun n : nat => (plus n n)}.
-
-Bound (local) variables and free (global) variables may be mixed.
-For instance, we may define the function which adds the constant \verb:n:
-to its argument as
-\begin{coq_example}
-Definition add_n (m:nat) := plus m n.
-\end{coq_example}
-However, note that here we may not rename the formal argument $m$ into $n$
-without capturing the free occurrence of $n$, and thus changing the meaning
-of the defined notion.
-
-Binding operations are well known for instance in logic, where they
-are called quantifiers. Thus we may universally quantify a
-proposition such as $m>0$ in order to get a universal proposition
-$\forall m\cdot m>0$. Indeed this operator is available in \Coq, with
-the following syntax: \texttt{forall m : nat, gt m O}. Similarly to the
-case of the functional abstraction binding, we are obliged to declare
-explicitly the type of the quantified variable. We check:
-\begin{coq_example}
-Check (forall m : nat, gt m 0).
-\end{coq_example}
-
-\begin{coq_eval}
-Reset Initial.
-Set Printing Width 60.
-Set Printing Compact Contexts.
-\end{coq_eval}
-
-\section{Introduction to the proof engine: Minimal Logic}
-
-In the following, we are going to consider various propositions, built
-from atomic propositions $A, B, C$. This may be done easily, by
-introducing these atoms as global variables declared of type \verb:Prop:.
-It is easy to declare several names with the same specification:
-\begin{coq_example}
-Section Minimal_Logic.
-Variables A B C : Prop.
-\end{coq_example}
-
-We shall consider simple implications, such as $A\ra B$, read as
-``$A$ implies $B$''. Note that we overload the arrow symbol, which
-has been used above as the functionality type constructor, and which
-may be used as well as propositional connective:
-\begin{coq_example}
-Check (A -> B).
-\end{coq_example}
-
-Let us now embark on a simple proof. We want to prove the easy tautology
-$((A\ra (B\ra C))\ra (A\ra B)\ra (A\ra C)$.
-We enter the proof engine by the command
-\verb:Goal:, followed by the conjecture we want to verify:
-\begin{coq_example}
-Goal (A -> B -> C) -> (A -> B) -> A -> C.
-\end{coq_example}
-
-The system displays the current goal below a double line, local hypotheses
-(there are none initially) being displayed above the line. We call
-the combination of local hypotheses with a goal a {\sl judgment}.
-We are now in an inner
-loop of the system, in proof mode.
-New commands are available in this
-mode, such as {\sl tactics}, which are proof combining primitives.
-A tactic operates on the current goal by attempting to construct a proof
-of the corresponding judgment, possibly from proofs of some
-hypothetical judgments, which are then added to the current
-list of conjectured judgments.
-For instance, the \verb:intro: tactic is applicable to any judgment
-whose goal is an implication, by moving the proposition to the left
-of the application to the list of local hypotheses:
-\begin{coq_example}
-intro H.
-\end{coq_example}
-
-Several introductions may be done in one step:
-\begin{coq_example}
-intros H' HA.
-\end{coq_example}
-
-We notice that $C$, the current goal, may be obtained from hypothesis
-\verb:H:, provided the truth of $A$ and $B$ are established.
-The tactic \verb:apply: implements this piece of reasoning:
-\begin{coq_example}
-apply H.
-\end{coq_example}
-
-We are now in the situation where we have two judgments as conjectures
-that remain to be proved. Only the first is listed in full, for the
-others the system displays only the corresponding subgoal, without its
-local hypotheses list. Note that \verb:apply: has kept the local
-hypotheses of its father judgment, which are still available for
-the judgments it generated.
-
-In order to solve the current goal, we just have to notice that it is
-exactly available as hypothesis $HA$:
-\begin{coq_example}
-exact HA.
-\end{coq_example}
-
-Now $H'$ applies:
-\begin{coq_example}
-apply H'.
-\end{coq_example}
-
-And we may now conclude the proof as before, with \verb:exact HA.:
-Actually, we may not bother with the name \verb:HA:, and just state that
-the current goal is solvable from the current local assumptions:
-\begin{coq_example}
-assumption.
-\end{coq_example}
-
-The proof is now finished. We are now going to ask \Coq{}'s kernel
-to check and save the proof.
-\begin{coq_example}
-Qed.
-\end{coq_example}
-
-Let us redo the same proof with a few variations. First of all we may name
-the initial goal as a conjectured lemma:
-\begin{coq_example}
-Lemma distr_impl : (A -> B -> C) -> (A -> B) -> A -> C.
-\end{coq_example}
-
-Next, we may omit the names of local assumptions created by the introduction
-tactics, they can be automatically created by the proof engine as new
-non-clashing names.
-\begin{coq_example}
-intros.
-\end{coq_example}
-
-The \verb:intros: tactic, with no arguments, effects as many individual
-applications of \verb:intro: as is legal.
-
-Then, we may compose several tactics together in sequence, or in parallel,
-through {\sl tacticals}, that is tactic combinators. The main constructions
-are the following:
-\begin{itemize}
-\item $T_1 ; T_2$ (read $T_1$ then $T_2$) applies tactic $T_1$ to the current
-goal, and then tactic $T_2$ to all the subgoals generated by $T_1$.
-\item $T; [T_1 | T_2 | ... | T_n]$ applies tactic $T$ to the current
-goal, and then tactic $T_1$ to the first newly generated subgoal,
-..., $T_n$ to the nth.
-\end{itemize}
-
-We may thus complete the proof of \verb:distr_impl: with one composite tactic:
-\begin{coq_example}
-apply H; [ assumption | apply H0; assumption ].
-\end{coq_example}
-
-You should be aware however that relying on automatically generated names is
-not robust to slight updates to this proof script. Consequently, it is
-discouraged in finished proof scripts. As for the composition of tactics with
-\texttt{:} it may hinder the readability of the proof script and it is also
-harder to see what's going on when replaying the proof because composed
-tactics are evaluated in one go.
-
-Actually, such an easy combination of tactics \verb:intro:, \verb:apply:
-and \verb:assumption: may be found completely automatically by an automatic
-tactic, called \verb:auto:, without user guidance:
-
-\begin{coq_eval}
-Abort.
-\end{coq_eval}
-\begin{coq_example}
-Lemma distr_impl : (A -> B -> C) -> (A -> B) -> A -> C.
-auto.
-\end{coq_example}
-
-Let us now save lemma \verb:distr_impl::
-\begin{coq_example}
-Qed.
-\end{coq_example}
-
-\section{Propositional Calculus}
-
-\subsection{Conjunction}
-
-We have seen how \verb:intro: and \verb:apply: tactics could be combined
-in order to prove implicational statements. More generally, \Coq{} favors a style
-of reasoning, called {\sl Natural Deduction}, which decomposes reasoning into
-so called {\sl introduction rules}, which tell how to prove a goal whose main
-operator is a given propositional connective, and {\sl elimination rules},
-which tell how to use an hypothesis whose main operator is the propositional
-connective. Let us show how to use these ideas for the propositional connectives
-\verb:/\: and \verb:\/:.
-
-\begin{coq_example}
-Lemma and_commutative : A /\ B -> B /\ A.
-intro H.
-\end{coq_example}
-
-We make use of the conjunctive hypothesis \verb:H: with the \verb:elim: tactic,
-which breaks it into its components:
-\begin{coq_example}
-elim H.
-\end{coq_example}
-
-We now use the conjunction introduction tactic \verb:split:, which splits the
-conjunctive goal into the two subgoals:
-\begin{coq_example}
-split.
-\end{coq_example}
-and the proof is now trivial. Indeed, the whole proof is obtainable as follows:
-\begin{coq_eval}
-Abort.
-\end{coq_eval}
-\begin{coq_example}
-Lemma and_commutative : A /\ B -> B /\ A.
-intro H; elim H; auto.
-Qed.
-\end{coq_example}
-
-The tactic \verb:auto: succeeded here because it knows as a hint the
-conjunction introduction operator \verb+conj+
-\begin{coq_example}
-Check conj.
-\end{coq_example}
-
-Actually, the tactic \verb+split+ is just an abbreviation for \verb+apply conj.+
-
-What we have just seen is that the \verb:auto: tactic is more powerful than
-just a simple application of local hypotheses; it tries to apply as well
-lemmas which have been specified as hints. A
-\verb:Hint Resolve: command registers a
-lemma as a hint to be used from now on by the \verb:auto: tactic, whose power
-may thus be incrementally augmented.
-
-\subsection{Disjunction}
-
-In a similar fashion, let us consider disjunction:
-
-\begin{coq_example}
-Lemma or_commutative : A \/ B -> B \/ A.
-intro H; elim H.
-\end{coq_example}
-
-Let us prove the first subgoal in detail. We use \verb:intro: in order to
-be left to prove \verb:B\/A: from \verb:A::
-
-\begin{coq_example}
-intro HA.
-\end{coq_example}
-
-Here the hypothesis \verb:H: is not needed anymore. We could choose to
-actually erase it with the tactic \verb:clear:; in this simple proof it
-does not really matter, but in bigger proof developments it is useful to
-clear away unnecessary hypotheses which may clutter your screen.
-\begin{coq_example}
-clear H.
-\end{coq_example}
-
-The tactic \verb:destruct: combines the effects of \verb:elim:, \verb:intros:,
-and \verb:clear::
-
-\begin{coq_eval}
-Abort.
-\end{coq_eval}
-\begin{coq_example}
-Lemma or_commutative : A \/ B -> B \/ A.
-intros H; destruct H.
-\end{coq_example}
-
-The disjunction connective has two introduction rules, since \verb:P\/Q:
-may be obtained from \verb:P: or from \verb:Q:; the two corresponding
-proof constructors are called respectively \verb:or_introl: and
-\verb:or_intror:; they are applied to the current goal by tactics
-\verb:left: and \verb:right: respectively. For instance:
-\begin{coq_example}
-right.
-trivial.
-\end{coq_example}
-The tactic \verb:trivial: works like \verb:auto: with the hints
-database, but it only tries those tactics that can solve the goal in one
-step.
-
-As before, all these tedious elementary steps may be performed automatically,
-as shown for the second symmetric case:
-
-\begin{coq_example}
-auto.
-\end{coq_example}
-
-However, \verb:auto: alone does not succeed in proving the full lemma, because
-it does not try any elimination step.
-It is a bit disappointing that \verb:auto: is not able to prove automatically
-such a simple tautology. The reason is that we want to keep
-\verb:auto: efficient, so that it is always effective to use.
-
-\subsection{Tauto}
-
-A complete tactic for propositional
-tautologies is indeed available in \Coq{} as the \verb:tauto: tactic.
-\begin{coq_eval}
-Abort.
-\end{coq_eval}
-\begin{coq_example}
-Lemma or_commutative : A \/ B -> B \/ A.
-tauto.
-Qed.
-\end{coq_example}
-
-It is possible to inspect the actual proof tree constructed by \verb:tauto:,
-using a standard command of the system, which prints the value of any notion
-currently defined in the context:
-\begin{coq_example}
-Print or_commutative.
-\end{coq_example}
-
-It is not easy to understand the notation for proof terms without some
-explanations. The \texttt{fun} prefix, such as \verb+fun H : A\/B =>+,
-corresponds
-to \verb:intro H:, whereas a subterm such as
-\verb:(or_intror: \verb:B H0):
-corresponds to the sequence of tactics \verb:apply or_intror; exact H0:.
-The generic combinator \verb:or_intror: needs to be instantiated by
-the two properties \verb:B: and \verb:A:. Because \verb:A: can be
-deduced from the type of \verb:H0:, only \verb:B: is printed.
-The two instantiations are effected automatically by the tactic
-\verb:apply: when pattern-matching a goal. The specialist will of course
-recognize our proof term as a $\lambda$-term, used as notation for the
-natural deduction proof term through the Curry-Howard isomorphism. The
-naive user of \Coq{} may safely ignore these formal details.
-
-Let us exercise the \verb:tauto: tactic on a more complex example:
-\begin{coq_example}
-Lemma distr_and : A -> B /\ C -> (A -> B) /\ (A -> C).
-tauto.
-Qed.
-\end{coq_example}
-
-\subsection{Classical reasoning}
-
-The tactic \verb:tauto: always comes back with an answer. Here is an example where it
-fails:
-\begin{coq_example}
-Lemma Peirce : ((A -> B) -> A) -> A.
-try tauto.
-\end{coq_example}
-
-Note the use of the \verb:try: tactical, which does nothing if its tactic
-argument fails.
-
-This may come as a surprise to someone familiar with classical reasoning.
-Peirce's lemma is true in Boolean logic, i.e. it evaluates to \verb:true: for
-every truth-assignment to \verb:A: and \verb:B:. Indeed the double negation
-of Peirce's law may be proved in \Coq{} using \verb:tauto::
-\begin{coq_eval}
-Abort.
-\end{coq_eval}
-\begin{coq_example}
-Lemma NNPeirce : ~ ~ (((A -> B) -> A) -> A).
-tauto.
-Qed.
-\end{coq_example}
-
-In classical logic, the double negation of a proposition is equivalent to this
-proposition, but in the constructive logic of \Coq{} this is not so. If you
-want to use classical logic in \Coq, you have to import explicitly the
-\verb:Classical: module, which will declare the axiom \verb:classic:
-of excluded middle, and classical tautologies such as de Morgan's laws.
-The \verb:Require: command is used to import a module from \Coq's library:
-\begin{coq_example}
-Require Import Classical.
-Check NNPP.
-\end{coq_example}
-
-and it is now easy (although admittedly not the most direct way) to prove
-a classical law such as Peirce's:
-\begin{coq_example}
-Lemma Peirce : ((A -> B) -> A) -> A.
-apply NNPP; tauto.
-Qed.
-\end{coq_example}
-
-Here is one more example of propositional reasoning, in the shape of
-a Scottish puzzle. A private club has the following rules:
-\begin{enumerate}
-\item Every non-scottish member wears red socks
-\item Every member wears a kilt or doesn't wear red socks
-\item The married members don't go out on Sunday
-\item A member goes out on Sunday if and only if he is Scottish
-\item Every member who wears a kilt is Scottish and married
-\item Every scottish member wears a kilt
-\end{enumerate}
-Now, we show that these rules are so strict that no one can be accepted.
-\begin{coq_example}
-Section club.
-Variables Scottish RedSocks WearKilt Married GoOutSunday : Prop.
-Hypothesis rule1 : ~ Scottish -> RedSocks.
-Hypothesis rule2 : WearKilt \/ ~ RedSocks.
-Hypothesis rule3 : Married -> ~ GoOutSunday.
-Hypothesis rule4 : GoOutSunday <-> Scottish.
-Hypothesis rule5 : WearKilt -> Scottish /\ Married.
-Hypothesis rule6 : Scottish -> WearKilt.
-Lemma NoMember : False.
-tauto.
-Qed.
-\end{coq_example}
-At that point \verb:NoMember: is a proof of the absurdity depending on
-hypotheses.
-We may end the section, in that case, the variables and hypotheses
-will be discharged, and the type of \verb:NoMember: will be
-generalised.
-
-\begin{coq_example}
-End club.
-Check NoMember.
-\end{coq_example}
-
-\section{Predicate Calculus}
-
-Let us now move into predicate logic, and first of all into first-order
-predicate calculus. The essence of predicate calculus is that to try to prove
-theorems in the most abstract possible way, without using the definitions of
-the mathematical notions, but by formal manipulations of uninterpreted
-function and predicate symbols.
-
-\subsection{Sections and signatures}
-
-Usually one works in some domain of discourse, over which range the individual
-variables and function symbols. In \Coq{}, we speak in a language with a rich
-variety of types, so we may mix several domains of discourse, in our
-multi-sorted language. For the moment, we just do a few exercises, over a
-domain of discourse \verb:D: axiomatised as a \verb:Set:, and we consider two
-predicate symbols \verb:P: and \verb:R: over \verb:D:, of arities
-1 and 2, respectively.
-
-\begin{coq_eval}
-Reset Initial.
-Set Printing Width 60.
-Set Printing Compact Contexts.
-\end{coq_eval}
-
-We start by assuming a domain of
-discourse \verb:D:, and a binary relation \verb:R: over \verb:D::
-\begin{coq_example}
-Section Predicate_calculus.
-Variable D : Set.
-Variable R : D -> D -> Prop.
-\end{coq_example}
-
-As a simple example of predicate calculus reasoning, let us assume
-that relation \verb:R: is symmetric and transitive, and let us show that
-\verb:R: is reflexive in any point \verb:x: which has an \verb:R: successor.
-Since we do not want to make the assumptions about \verb:R: global axioms of
-a theory, but rather local hypotheses to a theorem, we open a specific
-section to this effect.
-\begin{coq_example}
-Section R_sym_trans.
-Hypothesis R_symmetric : forall x y : D, R x y -> R y x.
-Hypothesis R_transitive :
- forall x y z : D, R x y -> R y z -> R x z.
-\end{coq_example}
-
-Note the syntax \verb+forall x : D,+ which stands for universal quantification
-$\forall x : D$.
-
-\subsection{Existential quantification}
-
-We now state our lemma, and enter proof mode.
-\begin{coq_example}
-Lemma refl_if : forall x : D, (exists y, R x y) -> R x x.
-\end{coq_example}
-
-The hypotheses that are local to the currently opened sections
-are listed as local hypotheses to the current goals.
-That is because these hypotheses are going to be discharged, as
-we shall see, when we shall close the corresponding sections.
-
-Note the functional syntax for existential quantification. The existential
-quantifier is built from the operator \verb:ex:, which expects a
-predicate as argument:
-\begin{coq_example}
-Check ex.
-\end{coq_example}
-and the notation \verb+(exists x : D, P x)+ is just concrete syntax for
-the expression \verb+(ex D (fun x : D => P x))+.
-Existential quantification is handled in \Coq{} in a similar
-fashion to the connectives \verb:/\: and \verb:\/:: it is introduced by
-the proof combinator \verb:ex_intro:, which is invoked by the specific
-tactic \verb:exists:, and its elimination provides a witness \verb+a : D+ to
-\verb:P:, together with an assumption \verb+h : (P a)+ that indeed \verb+a+
-verifies \verb:P:. Let us see how this works on this simple example.
-\begin{coq_example}
-intros x x_Rlinked.
-\end{coq_example}
-
-Note that \verb:intros: treats universal quantification in the same way
-as the premises of implications. Renaming of bound variables occurs
-when it is needed; for instance, had we started with \verb:intro y:,
-we would have obtained the goal:
-\begin{coq_eval}
-Undo.
-\end{coq_eval}
-\begin{coq_example}
-intro y.
-\end{coq_example}
-\begin{coq_eval}
-Undo.
-intros x x_Rlinked.
-\end{coq_eval}
-
-Let us now use the existential hypothesis \verb:x_Rlinked: to
-exhibit an R-successor y of x. This is done in two steps, first with
-\verb:elim:, then with \verb:intros:
-
-\begin{coq_example}
-elim x_Rlinked.
-intros y Rxy.
-\end{coq_example}
-
-Now we want to use \verb:R_transitive:. The \verb:apply: tactic will know
-how to match \verb:x: with \verb:x:, and \verb:z: with \verb:x:, but needs
-help on how to instantiate \verb:y:, which appear in the hypotheses of
-\verb:R_transitive:, but not in its conclusion. We give the proper hint
-to \verb:apply: in a \verb:with: clause, as follows:
-\begin{coq_example}
-apply R_transitive with y.
-\end{coq_example}
-
-The rest of the proof is routine:
-\begin{coq_example}
-assumption.
-apply R_symmetric; assumption.
-\end{coq_example}
-\begin{coq_example*}
-Qed.
-\end{coq_example*}
-
-Let us now close the current section.
-\begin{coq_example}
-End R_sym_trans.
-\end{coq_example}
-
-All the local hypotheses have been
-discharged in the statement of \verb:refl_if:, which now becomes a general
-theorem in the first-order language declared in section
-\verb:Predicate_calculus:. In this particular example, section
-\verb:R_sym_trans: has not been really useful, since we could have
-instead stated theorem \verb:refl_if: in its general form, and done
-basically the same proof, obtaining \verb:R_symmetric: and
-\verb:R_transitive: as local hypotheses by initial \verb:intros: rather
-than as global hypotheses in the context. But if we had pursued the
-theory by proving more theorems about relation \verb:R:,
-we would have obtained all general statements at the closing of the section,
-with minimal dependencies on the hypotheses of symmetry and transitivity.
-
-\subsection{Paradoxes of classical predicate calculus}
-
-Let us illustrate this feature by pursuing our \verb:Predicate_calculus:
-section with an enrichment of our language: we declare a unary predicate
-\verb:P: and a constant \verb:d::
-\begin{coq_example}
-Variable P : D -> Prop.
-Variable d : D.
-\end{coq_example}
-
-We shall now prove a well-known fact from first-order logic: a universal
-predicate is non-empty, or in other terms existential quantification
-follows from universal quantification.
-\begin{coq_example}
-Lemma weird : (forall x:D, P x) -> exists a, P a.
- intro UnivP.
-\end{coq_example}
-
-First of all, notice the pair of parentheses around
-\verb+forall x : D, P x+ in
-the statement of lemma \verb:weird:.
-If we had omitted them, \Coq's parser would have interpreted the
-statement as a truly trivial fact, since we would
-postulate an \verb:x: verifying \verb:(P x):. Here the situation is indeed
-more problematic. If we have some element in \verb:Set: \verb:D:, we may
-apply \verb:UnivP: to it and conclude, otherwise we are stuck. Indeed
-such an element \verb:d: exists, but this is just by virtue of our
-new signature. This points out a subtle difference between standard
-predicate calculus and \Coq. In standard first-order logic,
-the equivalent of lemma \verb:weird: always holds,
-because such a rule is wired in the inference rules for quantifiers, the
-semantic justification being that the interpretation domain is assumed to
-be non-empty. Whereas in \Coq, where types are not assumed to be
-systematically inhabited, lemma \verb:weird: only holds in signatures
-which allow the explicit construction of an element in the domain of
-the predicate.
-
-Let us conclude the proof, in order to show the use of the \verb:exists:
-tactic:
-\begin{coq_example}
-exists d; trivial.
-Qed.
-\end{coq_example}
-
-Another fact which illustrates the sometimes disconcerting rules of
-classical
-predicate calculus is Smullyan's drinkers' paradox: ``In any non-empty
-bar, there is a person such that if she drinks, then everyone drinks''.
-We modelize the bar by Set \verb:D:, drinking by predicate \verb:P:.
-We shall need classical reasoning. Instead of loading the \verb:Classical:
-module as we did above, we just state the law of excluded middle as a
-local hypothesis schema at this point:
-\begin{coq_example}
-Hypothesis EM : forall A : Prop, A \/ ~ A.
-Lemma drinker : exists x : D, P x -> forall x : D, P x.
-\end{coq_example}
-The proof goes by cases on whether or not
-there is someone who does not drink. Such reasoning by cases proceeds
-by invoking the excluded middle principle, via \verb:elim: of the
-proper instance of \verb:EM::
-\begin{coq_example}
-elim (EM (exists x, ~ P x)).
-\end{coq_example}
-
-We first look at the first case. Let Tom be the non-drinker.
-The following combines at once the effect of \verb:intros: and
-\verb:destruct::
-\begin{coq_example}
-intros (Tom, Tom_does_not_drink).
-\end{coq_example}
-
-We conclude in that case by considering Tom, since his drinking leads to
-a contradiction:
-\begin{coq_example}
-exists Tom; intro Tom_drinks.
-\end{coq_example}
-
-There are several ways in which we may eliminate a contradictory case;
-in this case, we use \verb:contradiction: to let \Coq{} find out the
-two contradictory hypotheses:
-\begin{coq_example}
-contradiction.
-\end{coq_example}
-
-We now proceed with the second case, in which actually any person will do;
-such a John Doe is given by the non-emptiness witness \verb:d::
-\begin{coq_example}
-intro No_nondrinker; exists d; intro d_drinks.
-\end{coq_example}
-
-Now we consider any Dick in the bar, and reason by cases according to its
-drinking or not:
-\begin{coq_example}
-intro Dick; elim (EM (P Dick)); trivial.
-\end{coq_example}
-
-The only non-trivial case is again treated by contradiction:
-\begin{coq_example}
-intro Dick_does_not_drink; absurd (exists x, ~ P x); trivial.
-exists Dick; trivial.
-Qed.
-\end{coq_example}
-
-Now, let us close the main section and look at the complete statements
-we proved:
-\begin{coq_example}
-End Predicate_calculus.
-Check refl_if.
-Check weird.
-Check drinker.
-\end{coq_example}
-
-Note how the three theorems are completely generic in the most general
-fashion;
-the domain \verb:D: is discharged in all of them, \verb:R: is discharged in
-\verb:refl_if: only, \verb:P: is discharged only in \verb:weird: and
-\verb:drinker:, along with the hypothesis that \verb:D: is inhabited.
-Finally, the excluded middle hypothesis is discharged only in
-\verb:drinker:.
-
-Note, too, that the name \verb:d: has vanished from
-the statements of \verb:weird: and \verb:drinker:,
-since \Coq's pretty-printer replaces
-systematically a quantification such as \texttt{forall d : D, E},
-where \texttt{d} does not occur in \texttt{E},
-by the functional notation \texttt{D -> E}.
-Similarly the name \texttt{EM} does not appear in \texttt{drinker}.
-
-Actually, universal quantification, implication,
-as well as function formation, are
-all special cases of one general construct of type theory called
-{\sl dependent product}. This is the mathematical construction
-corresponding to an indexed family of functions. A function
-$f\in \Pi x:D\cdot Cx$ maps an element $x$ of its domain $D$ to its
-(indexed) codomain $Cx$. Thus a proof of $\forall x:D\cdot Px$ is
-a function mapping an element $x$ of $D$ to a proof of proposition $Px$.
-
-
-\subsection{Flexible use of local assumptions}
-
-Very often during the course of a proof we want to retrieve a local
-assumption and reintroduce it explicitly in the goal, for instance
-in order to get a more general induction hypothesis. The tactic
-\verb:generalize: is what is needed here:
-
-\begin{coq_example}
-Section Predicate_Calculus.
-Variables P Q : nat -> Prop.
-Variable R : nat -> nat -> Prop.
-Lemma PQR :
- forall x y:nat, (R x x -> P x -> Q x) -> P x -> R x y -> Q x.
-intros.
-generalize H0.
-\end{coq_example}
-
-Sometimes it may be convenient to state an intermediate fact.
-The tactic \verb:assert: does this and introduces a new subgoal
-for this fact to be proved first. The tactic \verb:enough: does
-the same while keeping this goal for later.
-\begin{coq_example}
-enough (R x x) by auto.
-\end{coq_example}
-We clean the goal by doing an \verb:Abort: command.
-\begin{coq_example*}
-Abort.
-\end{coq_example*}
-
-
-\subsection{Equality}
-
-The basic equality provided in \Coq{} is Leibniz equality, noted infix like
-\texttt{x = y}, when \texttt{x} and \texttt{y} are two expressions of
-type the same Set. The replacement of \texttt{x} by \texttt{y} in any
-term is effected by a variety of tactics, such as \texttt{rewrite}
-and \texttt{replace}.
-
-Let us give a few examples of equality replacement. Let us assume that
-some arithmetic function \verb:f: is null in zero:
-\begin{coq_example}
-Variable f : nat -> nat.
-Hypothesis foo : f 0 = 0.
-\end{coq_example}
-
-We want to prove the following conditional equality:
-\begin{coq_example*}
-Lemma L1 : forall k:nat, k = 0 -> f k = k.
-\end{coq_example*}
-
-As usual, we first get rid of local assumptions with \verb:intro::
-\begin{coq_example}
-intros k E.
-\end{coq_example}
-
-Let us now use equation \verb:E: as a left-to-right rewriting:
-\begin{coq_example}
-rewrite E.
-\end{coq_example}
-This replaced both occurrences of \verb:k: by \verb:O:.
-
-Now \verb:apply foo: will finish the proof:
-
-\begin{coq_example}
-apply foo.
-Qed.
-\end{coq_example}
-
-When one wants to rewrite an equality in a right to left fashion, we should
-use \verb:rewrite <- E: rather than \verb:rewrite E: or the equivalent
-\verb:rewrite -> E:.
-Let us now illustrate the tactic \verb:replace:.
-\begin{coq_example}
-Hypothesis f10 : f 1 = f 0.
-Lemma L2 : f (f 1) = 0.
-replace (f 1) with 0.
-\end{coq_example}
-What happened here is that the replacement left the first subgoal to be
-proved, but another proof obligation was generated by the \verb:replace:
-tactic, as the second subgoal. The first subgoal is solved immediately
-by applying lemma \verb:foo:; the second one transitivity and then
-symmetry of equality, for instance with tactics \verb:transitivity: and
-\verb:symmetry::
-\begin{coq_example}
-apply foo.
-transitivity (f 0); symmetry; trivial.
-\end{coq_example}
-In case the equality $t=u$ generated by \verb:replace: $u$ \verb:with:
-$t$ is an assumption
-(possibly modulo symmetry), it will be automatically proved and the
-corresponding goal will not appear. For instance:
-
-\begin{coq_eval}
-Restart.
-\end{coq_eval}
-\begin{coq_example}
-Lemma L2 : f (f 1) = 0.
-replace (f 1) with (f 0).
-replace (f 0) with 0; trivial.
-Qed.
-\end{coq_example}
-
-\section{Using definitions}
-
-The development of mathematics does not simply proceed by logical
-argumentation from first principles: definitions are used in an essential way.
-A formal development proceeds by a dual process of abstraction, where one
-proves abstract statements in predicate calculus, and use of definitions,
-which in the contrary one instantiates general statements with particular
-notions in order to use the structure of mathematical values for the proof of
-more specialised properties.
-
-\subsection{Unfolding definitions}
-
-Assume that we want to develop the theory of sets represented as characteristic
-predicates over some universe \verb:U:. For instance:
-\begin{coq_example}
-Variable U : Type.
-Definition set := U -> Prop.
-Definition element (x : U) (S : set) := S x.
-Definition subset (A B : set) :=
- forall x : U, element x A -> element x B.
-\end{coq_example}
-
-Now, assume that we have loaded a module of general properties about
-relations over some abstract type \verb:T:, such as transitivity:
-
-\begin{coq_example}
-Definition transitive (T : Type) (R : T -> T -> Prop) :=
- forall x y z : T, R x y -> R y z -> R x z.
-\end{coq_example}
-
-We want to prove that \verb:subset: is a \verb:transitive:
-relation.
-\begin{coq_example}
-Lemma subset_transitive : transitive set subset.
-\end{coq_example}
-
-In order to make any progress, one needs to use the definition of
-\verb:transitive:. The \verb:unfold: tactic, which replaces all
-occurrences of a defined notion by its definition in the current goal,
-may be used here.
-\begin{coq_example}
-unfold transitive.
-\end{coq_example}
-
-Now, we must unfold \verb:subset::
-\begin{coq_example}
-unfold subset.
-\end{coq_example}
-Now, unfolding \verb:element: would be a mistake, because indeed a simple proof
-can be found by \verb:auto:, keeping \verb:element: an abstract predicate:
-\begin{coq_example}
-auto.
-\end{coq_example}
-
-Many variations on \verb:unfold: are provided in \Coq. For instance,
-instead of unfolding all occurrences of \verb:subset:, we may want to
-unfold only one designated occurrence:
-\begin{coq_eval}
-Undo 2.
-\end{coq_eval}
-\begin{coq_example}
-unfold subset at 2.
-\end{coq_example}
-
-One may also unfold a definition in a given local hypothesis, using the
-\verb:in: notation:
-\begin{coq_example}
-intros.
-unfold subset in H.
-\end{coq_example}
-
-Finally, the tactic \verb:red: does only unfolding of the head occurrence
-of the current goal:
-\begin{coq_example}
-red.
-auto.
-Qed.
-\end{coq_example}
-
-
-\subsection{Principle of proof irrelevance}
-
-Even though in principle the proof term associated with a verified lemma
-corresponds to a defined value of the corresponding specification, such
-definitions cannot be unfolded in \Coq: a lemma is considered an {\sl opaque}
-definition. This conforms to the mathematical tradition of {\sl proof
-irrelevance}: the proof of a logical proposition does not matter, and the
-mathematical justification of a logical development relies only on
-{\sl provability} of the lemmas used in the formal proof.
-
-Conversely, ordinary mathematical definitions can be unfolded at will, they
-are {\sl transparent}.
-
-\chapter{Induction}
-
-\begin{coq_eval}
-Reset Initial.
-Set Printing Width 60.
-Set Printing Compact Contexts.
-\end{coq_eval}
-
-\section{Data Types as Inductively Defined Mathematical Collections}
-
-All the notions which were studied until now pertain to traditional
-mathematical logic. Specifications of objects were abstract properties
-used in reasoning more or less constructively; we are now entering
-the realm of inductive types, which specify the existence of concrete
-mathematical constructions.
-
-\subsection{Booleans}
-
-Let us start with the collection of booleans, as they are specified
-in the \Coq's \verb:Prelude: module:
-\begin{coq_example}
-Inductive bool : Set := true | false.
-\end{coq_example}
-
-Such a declaration defines several objects at once. First, a new
-\verb:Set: is declared, with name \verb:bool:. Then the {\sl constructors}
-of this \verb:Set: are declared, called \verb:true: and \verb:false:.
-Those are analogous to introduction rules of the new Set \verb:bool:.
-Finally, a specific elimination rule for \verb:bool: is now available, which
-permits to reason by cases on \verb:bool: values. Three instances are
-indeed defined as new combinators in the global context: \verb:bool_ind:,
-a proof combinator corresponding to reasoning by cases,
-\verb:bool_rec:, an if-then-else programming construct,
-and \verb:bool_rect:, a similar combinator at the level of types.
-Indeed:
-\begin{coq_example}
-Check bool_ind.
-Check bool_rec.
-Check bool_rect.
-\end{coq_example}
-
-Let us for instance prove that every Boolean is true or false.
-\begin{coq_example}
-Lemma duality : forall b:bool, b = true \/ b = false.
-intro b.
-\end{coq_example}
-
-We use the knowledge that \verb:b: is a \verb:bool: by calling tactic
-\verb:elim:, which is this case will appeal to combinator \verb:bool_ind:
-in order to split the proof according to the two cases:
-\begin{coq_example}
-elim b.
-\end{coq_example}
-
-It is easy to conclude in each case:
-\begin{coq_example}
-left; trivial.
-right; trivial.
-\end{coq_example}
-
-Indeed, the whole proof can be done with the combination of the
- \verb:destruct:, which combines \verb:intro: and \verb:elim:,
-with good old \verb:auto::
-\begin{coq_eval}
-Abort.
-\end{coq_eval}
-\begin{coq_example}
-Lemma duality : forall b:bool, b = true \/ b = false.
-destruct b; auto.
-Qed.
-\end{coq_example}
-
-\subsection{Natural numbers}
-
-Similarly to Booleans, natural numbers are defined in the \verb:Prelude:
-module with constructors \verb:S: and \verb:O::
-\begin{coq_example}
-Inductive nat : Set :=
- | O : nat
- | S : nat -> nat.
-\end{coq_example}
-
-The elimination principles which are automatically generated are Peano's
-induction principle, and a recursion operator:
-\begin{coq_example}
-Check nat_ind.
-Check nat_rec.
-\end{coq_example}
-
-Let us start by showing how to program the standard primitive recursion
-operator \verb:prim_rec: from the more general \verb:nat_rec::
-\begin{coq_example}
-Definition prim_rec := nat_rec (fun i : nat => nat).
-\end{coq_example}
-
-That is, instead of computing for natural \verb:i: an element of the indexed
-\verb:Set: \verb:(P i):, \verb:prim_rec: computes uniformly an element of
-\verb:nat:. Let us check the type of \verb:prim_rec::
-\begin{coq_example}
-About prim_rec.
-\end{coq_example}
-
-Oops! Instead of the expected type \verb+nat->(nat->nat->nat)->nat->nat+ we
-get an apparently more complicated expression.
-In fact, the two types are convertible and one way of having the proper
-type would be to do some computation before actually defining \verb:prim_rec:
-as such:
-
-\begin{coq_eval}
-Reset Initial.
-Set Printing Width 60.
-Set Printing Compact Contexts.
-\end{coq_eval}
-
-\begin{coq_example}
-Definition prim_rec :=
- Eval compute in nat_rec (fun i : nat => nat).
-About prim_rec.
-\end{coq_example}
-
-Let us now show how to program addition with primitive recursion:
-\begin{coq_example}
-Definition addition (n m:nat) :=
- prim_rec m (fun p rec : nat => S rec) n.
-\end{coq_example}
-
-That is, we specify that \verb+(addition n m)+ computes by cases on \verb:n:
-according to its main constructor; when \verb:n = O:, we get \verb:m:;
- when \verb:n = S p:, we get \verb:(S rec):, where \verb:rec: is the result
-of the recursive computation \verb+(addition p m)+. Let us verify it by
-asking \Coq{} to compute for us say $2+3$:
-\begin{coq_example}
-Eval compute in (addition (S (S O)) (S (S (S O)))).
-\end{coq_example}
-
-Actually, we do not have to do all explicitly. {\Coq} provides a
-special syntax {\tt Fixpoint/match} for generic primitive recursion,
-and we could thus have defined directly addition as:
-
-\begin{coq_example}
-Fixpoint plus (n m:nat) {struct n} : nat :=
- match n with
- | O => m
- | S p => S (plus p m)
- end.
-\end{coq_example}
-
-\begin{coq_eval}
-\begin{coq_example}
-Reset Initial.
-Set Printing Width 60.
-Set Printing Compact Contexts.
-\end{coq_eval}
-
-\subsection{Simple proofs by induction}
-
-Let us now show how to do proofs by structural induction. We start with easy
-properties of the \verb:plus: function we just defined. Let us first
-show that $n=n+0$.
-\begin{coq_example}
-Lemma plus_n_O : forall n : nat, n = n + 0.
-intro n; elim n.
-\end{coq_example}
-
-What happened was that \texttt{elim n}, in order to construct a \texttt{Prop}
-(the initial goal) from a \texttt{nat} (i.e. \texttt{n}), appealed to the
-corresponding induction principle \texttt{nat\_ind} which we saw was indeed
-exactly Peano's induction scheme. Pattern-matching instantiated the
-corresponding predicate \texttt{P} to \texttt{fun n : nat => n = n + 0},
-and we get as subgoals the corresponding instantiations of the base case
-\texttt{(P O)}, and of the inductive step
-\texttt{forall y : nat, P y -> P (S y)}.
-In each case we get an instance of function \texttt{plus} in which its second
-argument starts with a constructor, and is thus amenable to simplification
-by primitive recursion. The \Coq{} tactic \texttt{simpl} can be used for
-this purpose:
-\begin{coq_example}
-simpl.
-auto.
-\end{coq_example}
-
-We proceed in the same way for the base step:
-\begin{coq_example}
-simpl; auto.
-Qed.
-\end{coq_example}
-
-Here \verb:auto: succeeded, because it used as a hint lemma \verb:eq_S:,
-which say that successor preserves equality:
-\begin{coq_example}
-Check eq_S.
-\end{coq_example}
-
-Actually, let us see how to declare our lemma \verb:plus_n_O: as a hint
-to be used by \verb:auto::
-\begin{coq_example}
-Hint Resolve plus_n_O .
-\end{coq_example}
-
-We now proceed to the similar property concerning the other constructor
-\verb:S::
-\begin{coq_example}
-Lemma plus_n_S : forall n m:nat, S (n + m) = n + S m.
-\end{coq_example}
-
-We now go faster, using the tactic \verb:induction:, which does the
-necessary \verb:intros: before applying \verb:elim:. Factoring simplification
-and automation in both cases thanks to tactic composition, we prove this
-lemma in one line:
-\begin{coq_example}
-induction n; simpl; auto.
-Qed.
-Hint Resolve plus_n_S .
-\end{coq_example}
-
-Let us end this exercise with the commutativity of \verb:plus::
-
-\begin{coq_example}
-Lemma plus_com : forall n m:nat, n + m = m + n.
-\end{coq_example}
-
-Here we have a choice on doing an induction on \verb:n: or on \verb:m:, the
-situation being symmetric. For instance:
-\begin{coq_example}
-induction m as [ | m IHm ]; simpl; auto.
-\end{coq_example}
-
-Here \verb:auto: succeeded on the base case, thanks to our hint
-\verb:plus_n_O:, but the induction step requires rewriting, which
-\verb:auto: does not handle:
-
-\begin{coq_example}
-rewrite <- IHm; auto.
-Qed.
-\end{coq_example}
-
-\subsection{Discriminate}
-
-It is also possible to define new propositions by primitive recursion.
-Let us for instance define the predicate which discriminates between
-the constructors \verb:O: and \verb:S:: it computes to \verb:False:
-when its argument is \verb:O:, and to \verb:True: when its argument is
-of the form \verb:(S n)::
-\begin{coq_example}
-Definition Is_S (n : nat) := match n with
- | O => False
- | S p => True
- end.
-\end{coq_example}
-
-Now we may use the computational power of \verb:Is_S: to prove
-trivially that \verb:(Is_S (S n))::
-\begin{coq_example}
-Lemma S_Is_S : forall n:nat, Is_S (S n).
-simpl; trivial.
-Qed.
-\end{coq_example}
-
-But we may also use it to transform a \verb:False: goal into
-\verb:(Is_S O):. Let us show a particularly important use of this feature;
-we want to prove that \verb:O: and \verb:S: construct different values, one
-of Peano's axioms:
-\begin{coq_example}
-Lemma no_confusion : forall n:nat, 0 <> S n.
-\end{coq_example}
-
-First of all, we replace negation by its definition, by reducing the
-goal with tactic \verb:red:; then we get contradiction by successive
-\verb:intros::
-\begin{coq_example}
-red; intros n H.
-\end{coq_example}
-
-Now we use our trick:
-\begin{coq_example}
-change (Is_S 0).
-\end{coq_example}
-
-Now we use equality in order to get a subgoal which computes out to
-\verb:True:, which finishes the proof:
-\begin{coq_example}
-rewrite H; trivial.
-simpl; trivial.
-\end{coq_example}
-
-Actually, a specific tactic \verb:discriminate: is provided
-to produce mechanically such proofs, without the need for the user to define
-explicitly the relevant discrimination predicates:
-
-\begin{coq_eval}
-Abort.
-\end{coq_eval}
-\begin{coq_example}
-Lemma no_confusion : forall n:nat, 0 <> S n.
-intro n; discriminate.
-Qed.
-\end{coq_example}
-
-
-\section{Logic programming}
-
-In the same way as we defined standard data-types above, we
-may define inductive families, and for instance inductive predicates.
-Here is the definition of predicate $\le$ over type \verb:nat:, as
-given in \Coq's \verb:Prelude: module:
-\begin{coq_example*}
-Inductive le (n : nat) : nat -> Prop :=
- | le_n : le n n
- | le_S : forall m : nat, le n m -> le n (S m).
-\end{coq_example*}
-
-This definition introduces a new predicate
-\verb+le : nat -> nat -> Prop+,
-and the two constructors \verb:le_n: and \verb:le_S:, which are the
-defining clauses of \verb:le:. That is, we get not only the ``axioms''
-\verb:le_n: and \verb:le_S:, but also the converse property, that
-\verb:(le n m): if and only if this statement can be obtained as a
-consequence of these defining clauses; that is, \verb:le: is the
-minimal predicate verifying clauses \verb:le_n: and \verb:le_S:. This is
-insured, as in the case of inductive data types, by an elimination principle,
-which here amounts to an induction principle \verb:le_ind:, stating this
-minimality property:
-\begin{coq_example}
-Check le.
-Check le_ind.
-\end{coq_example}
-
-Let us show how proofs may be conducted with this principle.
-First we show that $n\le m \Rightarrow n+1\le m+1$:
-\begin{coq_example}
-Lemma le_n_S : forall n m : nat, le n m -> le (S n) (S m).
-intros n m n_le_m.
-elim n_le_m.
-\end{coq_example}
-
-What happens here is similar to the behaviour of \verb:elim: on natural
-numbers: it appeals to the relevant induction principle, here \verb:le_ind:,
-which generates the two subgoals, which may then be solved easily
-with the help of the defining clauses of \verb:le:.
-\begin{coq_example}
-apply le_n; trivial.
-intros; apply le_S; trivial.
-\end{coq_example}
-
-Now we know that it is a good idea to give the defining clauses as hints,
-so that the proof may proceed with a simple combination of
-\verb:induction: and \verb:auto:. \verb:Hint Constructors le:
-is just an abbreviation for \verb:Hint Resolve le_n le_S:.
-\begin{coq_eval}
-Abort.
-\end{coq_eval}
-\begin{coq_example}
-Hint Constructors le.
-Lemma le_n_S : forall n m : nat, le n m -> le (S n) (S m).
-\end{coq_example}
-
-We have a slight problem however. We want to say ``Do an induction on
-hypothesis \verb:(le n m):'', but we have no explicit name for it. What we
-do in this case is to say ``Do an induction on the first unnamed hypothesis'',
-as follows.
-\begin{coq_example}
-induction 1; auto.
-Qed.
-\end{coq_example}
-
-Here is a more tricky problem. Assume we want to show that
-$n\le 0 \Rightarrow n=0$. This reasoning ought to follow simply from the
-fact that only the first defining clause of \verb:le: applies.
-\begin{coq_example}
-Lemma tricky : forall n:nat, le n 0 -> n = 0.
-\end{coq_example}
-
-However, here trying something like \verb:induction 1: would lead
-nowhere (try it and see what happens).
-An induction on \verb:n: would not be convenient either.
-What we must do here is analyse the definition of \verb"le" in order
-to match hypothesis \verb:(le n O): with the defining clauses, to find
-that only \verb:le_n: applies, whence the result.
-This analysis may be performed by the ``inversion'' tactic
-\verb:inversion_clear: as follows:
-\begin{coq_example}
-intros n H; inversion_clear H.
-trivial.
-Qed.
-\end{coq_example}
-
-\chapter{Modules}
-
-\begin{coq_eval}
-Reset Initial.
-Set Printing Width 60.
-Set Printing Compact Contexts.
-\end{coq_eval}
-
-\section{Opening library modules}
-
-When you start \Coq{} without further requirements in the command line,
-you get a bare system with few libraries loaded. As we saw, a standard
-prelude module provides the standard logic connectives, and a few
-arithmetic notions. If you want to load and open other modules from
-the library, you have to use the \verb"Require" command, as we saw for
-classical logic above. For instance, if you want more arithmetic
-constructions, you should request:
-\begin{coq_example*}
-Require Import Arith.
-\end{coq_example*}
-
-Such a command looks for a (compiled) module file \verb:Arith.vo: in
-the libraries registered by \Coq. Libraries inherit the structure of
-the file system of the operating system and are registered with the
-command \verb:Add LoadPath:. Physical directories are mapped to
-logical directories. Especially the standard library of \Coq{} is
-pre-registered as a library of name \verb=Coq=. Modules have absolute
-unique names denoting their place in \Coq{} libraries. An absolute
-name is a sequence of single identifiers separated by dots. E.g. the
-module \verb=Arith= has full name \verb=Coq.Arith.Arith= and because
-it resides in eponym subdirectory \verb=Arith= of the standard
-library, it can be as well required by the command
-
-\begin{coq_example*}
-Require Import Coq.Arith.Arith.
-\end{coq_example*}
-
-This may be useful to avoid ambiguities if somewhere, in another branch
-of the libraries known by Coq, another module is also called
-\verb=Arith=. Notice that by default, when a library is registered,
-all its contents, and all the contents of its subdirectories recursively are
-visible and accessible by a short (relative) name as \verb=Arith=.
-Notice also that modules or definitions not explicitly registered in
-a library are put in a default library called \verb=Top=.
-
-The loading of a compiled file is quick, because the corresponding
-development is not type-checked again.
-
-\section{Creating your own modules}
-
-You may create your own module files, by writing {\Coq} commands in a file,
-say \verb:my_module.v:. Such a module may be simply loaded in the current
-context, with command \verb:Load my_module:. It may also be compiled,
-in ``batch'' mode, using the UNIX command
-\verb:coqc:. Compiling the module \verb:my_module.v: creates a
-file \verb:my_module.vo:{} that can be reloaded with command
-\verb:Require: \verb:Import: \verb:my_module:.
-
-If a required module depends on other modules then the latters are
-automatically required beforehand. However their contents is not
-automatically visible. If you want a module \verb=M= required in a
-module \verb=N= to be automatically visible when \verb=N= is required,
-you should use \verb:Require Export M: in your module \verb:N:.
-
-\section{Managing the context}
-
-It is often difficult to remember the names of all lemmas and
-definitions available in the current context, especially if large
-libraries have been loaded. A convenient \verb:Search: command
-is available to lookup all known facts
-concerning a given predicate. For instance, if you want to know all the
-known lemmas about both the successor and the less or equal relation, just ask:
-\begin{coq_eval}
-Reset Initial.
-Set Printing Width 60.
-Set Printing Compact Contexts.
-\end{coq_eval}
-\begin{coq_example}
-Search S le.
-\end{coq_example}
-Another command \verb:SearchHead: displays only lemmas where the searched
-predicate appears at the head position in the conclusion.
-\begin{coq_example}
-SearchHead le.
-\end{coq_example}
-
-The \verb:Search: commands also allows finding the theorems
-containing a given pattern, where \verb:_: can be used in
-place of an arbitrary term. As shown in this example, \Coq{}
-provides usual infix notations for arithmetic operators.
-
-\begin{coq_example}
-Search (_ + _ = _).
-\end{coq_example}
-
-\section{Now you are on your own}
-
-This tutorial is necessarily incomplete. If you wish to pursue serious
-proving in \Coq, you should now get your hands on \Coq's Reference Manual,
-which contains a complete description of all the tactics we saw,
-plus many more.
-You also should look in the library of developed theories which is distributed
-with \Coq, in order to acquaint yourself with various proof techniques.
-
-
-\end{document}
-
diff --git a/engine/evd.ml b/engine/evd.ml
index af22de5cd..20a7c80ea 100644
--- a/engine/evd.ml
+++ b/engine/evd.ml
@@ -842,12 +842,12 @@ let universe_rigidity evd l =
else UnivRigid
let normalize_universe evd =
- let vars = ref (UState.subst evd.universes) in
+ let vars = UState.subst evd.universes in
let normalize = Universes.normalize_universe_opt_subst vars in
normalize
let normalize_universe_instance evd l =
- let vars = ref (UState.subst evd.universes) in
+ let vars = UState.subst evd.universes in
let normalize = Universes.level_subst_of (Universes.normalize_univ_variable_opt_subst vars) in
Univ.Instance.subst_fn normalize l
diff --git a/engine/uState.ml b/engine/uState.ml
index 6c8dbe3f4..df50bae86 100644
--- a/engine/uState.ml
+++ b/engine/uState.ml
@@ -156,7 +156,7 @@ let process_universe_constraints ctx cstrs =
let univs = ctx.uctx_universes in
let vars = ref ctx.uctx_univ_variables in
let weak = ref ctx.uctx_weak_constraints in
- let normalize = normalize_univ_variable_opt_subst vars in
+ let normalize u = normalize_univ_variable_opt_subst !vars u in
let nf_constraint = function
| ULub (u, v) -> ULub (level_subst_of normalize u, level_subst_of normalize v)
| UWeak (u, v) -> UWeak (level_subst_of normalize u, level_subst_of normalize v)
diff --git a/engine/universes.ml b/engine/universes.ml
index 938f5ad9c..a13663cba 100644
--- a/engine/universes.ml
+++ b/engine/universes.ml
@@ -605,31 +605,25 @@ let fresh_universe_context_set_instance ctx =
let cst' = subst_univs_level_constraints subst cst in
subst, (univs', cst')
-let normalize_univ_variable ~find ~update =
+let normalize_univ_variable ~find =
let rec aux cur =
let b = find cur in
let b' = subst_univs_universe aux b in
if Universe.equal b' b then b
- else update cur b'
+ else b'
in aux
let normalize_univ_variable_opt_subst ectx =
let find l =
- match Univ.LMap.find l !ectx with
+ match Univ.LMap.find l ectx with
| Some b -> b
| None -> raise Not_found
in
- let update l b =
- assert (match Universe.level b with Some l' -> not (Level.equal l l') | None -> true);
- try ectx := Univ.LMap.add l (Some b) !ectx; b with Not_found -> assert false
- in normalize_univ_variable ~find ~update
+ normalize_univ_variable ~find
let normalize_univ_variable_subst subst =
- let find l = Univ.LMap.find l !subst in
- let update l b =
- assert (match Universe.level b with Some l' -> not (Level.equal l l') | None -> true);
- try subst := Univ.LMap.set l b !subst; b with Not_found -> assert false in
- normalize_univ_variable ~find ~update
+ let find l = Univ.LMap.find l subst in
+ normalize_univ_variable ~find
let normalize_universe_opt_subst subst =
let normlevel = normalize_univ_variable_opt_subst subst in
@@ -640,13 +634,10 @@ let normalize_universe_subst subst =
subst_univs_universe normlevel
let normalize_opt_subst ctx =
- let ectx = ref ctx in
- let normalize = normalize_univ_variable_opt_subst ectx in
- let () =
- Univ.LMap.iter (fun u v ->
- if Option.is_empty v then ()
- else try ignore(normalize u) with Not_found -> assert(false)) ctx
- in !ectx
+ let normalize = normalize_universe_opt_subst ctx in
+ Univ.LMap.mapi (fun u -> function
+ | None -> None
+ | Some v -> Some (normalize v)) ctx
type universe_opt_subst = Universe.t option universe_map
@@ -655,7 +646,7 @@ let subst_univs_fn_puniverses f (c, u as cu) =
if u' == u then cu else (c, u')
let nf_evars_and_universes_opt_subst f subst =
- let subst = normalize_univ_variable_opt_subst (ref subst) in
+ let subst = normalize_univ_variable_opt_subst subst in
let lsubst = level_subst_of subst in
let rec aux c =
match kind c with
@@ -975,7 +966,7 @@ let normalize_context_set g ctx us algs weak =
(* Process weak constraints: when one side is flexible and the 2
universes are unrelated unify them. *)
let ctx, us, g = UPairSet.fold (fun (u,v) (ctx, us, g as acc) ->
- let norm = let us = ref us in level_subst_of (normalize_univ_variable_opt_subst us) in
+ let norm = level_subst_of (normalize_univ_variable_opt_subst us) in
let u = norm u and v = norm v in
let set_to a b =
(LSet.remove a ctx,
@@ -994,7 +985,6 @@ let normalize_context_set g ctx us algs weak =
(* Noneqs is now in canonical form w.r.t. equality constraints,
and contains only inequality constraints. *)
let noneqs =
- let us = ref us in
let norm = level_subst_of (normalize_univ_variable_opt_subst us) in
Constraint.fold (fun (u,d,v) noneqs ->
let u = norm u and v = norm v in
diff --git a/engine/universes.mli b/engine/universes.mli
index e6bee42bb..df2e961d6 100644
--- a/engine/universes.mli
+++ b/engine/universes.mli
@@ -184,19 +184,18 @@ val normalize_univ_variables : universe_opt_subst ->
val normalize_univ_variable :
find:(Level.t -> Universe.t) ->
- update:(Level.t -> Universe.t -> Universe.t) ->
Level.t -> Universe.t
-val normalize_univ_variable_opt_subst : universe_opt_subst ref ->
+val normalize_univ_variable_opt_subst : universe_opt_subst ->
(Level.t -> Universe.t)
-val normalize_univ_variable_subst : universe_subst ref ->
+val normalize_univ_variable_subst : universe_subst ->
(Level.t -> Universe.t)
-val normalize_universe_opt_subst : universe_opt_subst ref ->
+val normalize_universe_opt_subst : universe_opt_subst ->
(Universe.t -> Universe.t)
-val normalize_universe_subst : universe_subst ref ->
+val normalize_universe_subst : universe_subst ->
(Universe.t -> Universe.t)
(** Create a fresh global in the global environment, without side effects.
diff --git a/ide/ide_slave.ml b/ide/ide_slave.ml
index c66d69c03..6c7ca4f8e 100644
--- a/ide/ide_slave.ml
+++ b/ide/ide_slave.ml
@@ -352,7 +352,6 @@ let about () = {
}
let handle_exn (e, info) =
- let (e, info) = ExplainErr.process_vernac_interp_error (e, info) in
let dummy = Stateid.dummy in
let loc_of e = match Loc.get_loc e with
| Some loc -> Some (Loc.unloc loc)
@@ -509,7 +508,6 @@ let rec parse = function
let () = Coqtop.toploop_init := (fun coq_args extra_args ->
let args = parse extra_args in
- Flags.quiet := true;
CoqworkmgrApi.(init High);
coq_args, args)
diff --git a/interp/notation.ml b/interp/notation.ml
index 4a6d2a154..e6df7b96c 100644
--- a/interp/notation.ml
+++ b/interp/notation.ml
@@ -49,7 +49,6 @@ type notation_location = (DirPath.t * DirPath.t) * string
type notation_data = {
not_interp : interpretation;
not_location : notation_location;
- not_onlyprinting : bool;
}
type scope = {
@@ -430,13 +429,15 @@ let rec find_without_delimiters find (ntn_scope,ntn) = function
(* Uninterpreted notation levels *)
-let declare_notation_level ntn level =
+let declare_notation_level ?(onlyprint=false) ntn level =
if String.Map.mem ntn !notation_level_map then
anomaly (str "Notation " ++ str ntn ++ str " is already assigned a level.");
- notation_level_map := String.Map.add ntn level !notation_level_map
+ notation_level_map := String.Map.add ntn (level,onlyprint) !notation_level_map
-let level_of_notation ntn =
- String.Map.find ntn !notation_level_map
+let level_of_notation ?(onlyprint=false) ntn =
+ let (level,onlyprint') = String.Map.find ntn !notation_level_map in
+ if onlyprint' && not onlyprint then raise Not_found;
+ level
(* The mapping between notations and their interpretation *)
@@ -449,20 +450,21 @@ let warn_notation_overridden =
let declare_notation_interpretation ntn scopt pat df ~onlyprint =
let scope = match scopt with Some s -> s | None -> default_scope in
let sc = find_scope scope in
- let () =
- if String.Map.mem ntn sc.notations then
- let which_scope = match scopt with
- | None -> mt ()
- | Some _ -> spc () ++ strbrk "in scope" ++ spc () ++ str scope in
- warn_notation_overridden (ntn,which_scope)
- in
- let notdata = {
- not_interp = pat;
- not_location = df;
- not_onlyprinting = onlyprint;
- } in
- let sc = { sc with notations = String.Map.add ntn notdata sc.notations } in
- let () = scope_map := String.Map.add scope sc !scope_map in
+ if not onlyprint then begin
+ let () =
+ if String.Map.mem ntn sc.notations then
+ let which_scope = match scopt with
+ | None -> mt ()
+ | Some _ -> spc () ++ strbrk "in scope" ++ spc () ++ str scope in
+ warn_notation_overridden (ntn,which_scope)
+ in
+ let notdata = {
+ not_interp = pat;
+ not_location = df;
+ } in
+ let sc = { sc with notations = String.Map.add ntn notdata sc.notations } in
+ scope_map := String.Map.add scope sc !scope_map
+ end;
begin match scopt with
| None -> scope_stack := SingleNotation ntn :: !scope_stack
| Some _ -> ()
@@ -487,7 +489,6 @@ let rec find_interpretation ntn find = function
let find_notation ntn sc =
let n = String.Map.find ntn (find_scope sc).notations in
- let () = if n.not_onlyprinting then raise Not_found in
(n.not_interp, n.not_location)
let notation_of_prim_token = function
@@ -631,7 +632,6 @@ let exists_notation_in_scope scopt ntn onlyprint r =
try
let sc = String.Map.find scope !scope_map in
let n = String.Map.find ntn sc.notations in
- onlyprint = n.not_onlyprinting &&
interpretation_eq n.not_interp r
with Not_found -> false
@@ -1051,7 +1051,7 @@ let locate_notation prglob ntn scope =
| [] -> str "Unknown notation"
| _ ->
str "Notation" ++ fnl () ++
- prlist (fun (ntn,l) ->
+ prlist_with_sep fnl (fun (ntn,l) ->
let scope = find_default ntn scopes in
prlist
(fun (sc,r,(_,df)) ->
@@ -1060,8 +1060,7 @@ let locate_notation prglob ntn scope =
(if String.equal sc default_scope then mt ()
else (spc () ++ str ": " ++ str sc)) ++
(if Option.equal String.equal (Some sc) scope
- then spc () ++ str "(default interpretation)" else mt ())
- ++ fnl ()))
+ then spc () ++ str "(default interpretation)" else mt ())))
l) ntns
let collect_notation_in_scope scope sc known =
diff --git a/interp/notation.mli b/interp/notation.mli
index eac87414f..ccc67fe49 100644
--- a/interp/notation.mli
+++ b/interp/notation.mli
@@ -137,8 +137,8 @@ val availability_of_notation : scope_name option * notation -> local_scopes ->
(** {6 Declare and test the level of a (possibly uninterpreted) notation } *)
-val declare_notation_level : notation -> level -> unit
-val level_of_notation : notation -> level (** raise [Not_found] if no level *)
+val declare_notation_level : ?onlyprint:bool -> notation -> level -> unit
+val level_of_notation : ?onlyprint:bool -> notation -> level (** raise [Not_found] if no level or not respecting onlyprint *)
(** {6 Miscellaneous} *)
diff --git a/interp/notation_ops.ml b/interp/notation_ops.ml
index 6a282624e..b806dce0b 100644
--- a/interp/notation_ops.ml
+++ b/interp/notation_ops.ml
@@ -165,15 +165,15 @@ let glob_constr_of_notation_constr_with_binders ?loc g f e nc =
| NApp (a,args) -> GApp (f e a, List.map (f e) args)
| NList (x,y,iter,tail,swap) ->
let t = f e tail in let it = f e iter in
- let innerl = (ldots_var,t)::(if swap then [] else [x, lt @@ GVar y]) in
+ let innerl = (ldots_var,t)::(if swap then [y, lt @@ GVar x] else []) in
let inner = lt @@ GApp (lt @@ GVar (ldots_var),[subst_glob_vars innerl it]) in
- let outerl = (ldots_var,inner)::(if swap then [x, lt @@ GVar y] else []) in
+ let outerl = (ldots_var,inner)::(if swap then [] else [y, lt @@ GVar x]) in
DAst.get (subst_glob_vars outerl it)
| NBinderList (x,y,iter,tail,swap) ->
let t = f e tail in let it = f e iter in
- let innerl = (ldots_var,t)::(if swap then [] else [x, lt @@ GVar y]) in
+ let innerl = (ldots_var,t)::(if swap then [y, lt @@ GVar x] else []) in
let inner = lt @@ GApp (lt @@ GVar ldots_var,[subst_glob_vars innerl it]) in
- let outerl = (ldots_var,inner)::(if swap then [x, lt @@ GVar y] else []) in
+ let outerl = (ldots_var,inner)::(if swap then [] else [y, lt @@ GVar x]) in
DAst.get (subst_glob_vars outerl it)
| NLambda (na,ty,c) ->
let e',disjpat,na = g e na in GLambda (na,Explicit,f e ty,Option.fold_right (apply_cases_pattern ?loc) disjpat (f e' c))
diff --git a/kernel/byterun/coq_fix_code.c b/kernel/byterun/coq_fix_code.c
index d5feafbf9..be2b05da8 100644
--- a/kernel/byterun/coq_fix_code.c
+++ b/kernel/byterun/coq_fix_code.c
@@ -18,6 +18,7 @@
#include <caml/misc.h>
#include <caml/mlvalues.h>
#include <caml/fail.h>
+#include <caml/alloc.h>
#include <caml/memory.h>
#include "coq_instruct.h"
#include "coq_fix_code.h"
@@ -78,38 +79,41 @@ void * coq_stat_alloc (asize_t sz)
}
value coq_makeaccu (value i) {
- code_t q;
- code_t res = coq_stat_alloc(2 * sizeof(opcode_t));
- q = res;
+ CAMLparam1(i);
+ CAMLlocal1(res);
+ code_t q = coq_stat_alloc(2 * sizeof(opcode_t));
+ res = caml_alloc_small(1, Abstract_tag);
+ Code_val(res) = q;
*q++ = VALINSTR(MAKEACCU);
*q = (opcode_t)Int_val(i);
- return (value)res;
+ CAMLreturn(res);
}
value coq_pushpop (value i) {
- code_t res;
- int n;
- n = Int_val(i);
+ CAMLparam1(i);
+ CAMLlocal1(res);
+ code_t q;
+ res = caml_alloc_small(1, Abstract_tag);
+ int n = Int_val(i);
if (n == 0) {
- res = coq_stat_alloc(sizeof(opcode_t));
- *res = VALINSTR(STOP);
- return (value)res;
+ q = coq_stat_alloc(sizeof(opcode_t));
+ Code_val(res) = q;
+ *q = VALINSTR(STOP);
+ CAMLreturn(res);
}
else {
- code_t q;
- res = coq_stat_alloc(3 * sizeof(opcode_t));
- q = res;
+ q = coq_stat_alloc(3 * sizeof(opcode_t));
+ Code_val(res) = q;
*q++ = VALINSTR(POP);
*q++ = (opcode_t)n;
*q = VALINSTR(STOP);
- return (value)res;
+ CAMLreturn(res);
}
}
value coq_is_accumulate_code(value code){
- code_t q;
+ code_t q = Code_val(code);
int res;
- q = (code_t)code;
res = Is_instruction(q,ACCUMULATE);
return Val_bool(res);
}
@@ -132,11 +136,14 @@ value coq_is_accumulate_code(value code){
#define COPY32(dst,src) (*dst=*src)
#endif /* ARCH_BIG_ENDIAN */
-value coq_tcode_of_code (value code, value size) {
- code_t p, q, res;
- asize_t len = (asize_t) Long_val(size);
- res = coq_stat_alloc(len);
- q = res;
+value coq_tcode_of_code (value code) {
+ CAMLparam1 (code);
+ CAMLlocal1 (res);
+ code_t p, q;
+ asize_t len = (asize_t) caml_string_length(code);
+ res = caml_alloc_small(1, Abstract_tag);
+ q = coq_stat_alloc(len);
+ Code_val(res) = q;
len /= sizeof(opcode_t);
for (p = (code_t)code; p < (code_t)code + len; /*nothing*/) {
opcode_t instr;
@@ -166,5 +173,5 @@ value coq_tcode_of_code (value code, value size) {
for(i=0; i<ar; i++) { COPY32(q,p); p++; q++; };
}
}
- return (value)res;
+ CAMLreturn(res);
}
diff --git a/kernel/byterun/coq_fix_code.h b/kernel/byterun/coq_fix_code.h
index 5c85389dd..638d6b5ab 100644
--- a/kernel/byterun/coq_fix_code.h
+++ b/kernel/byterun/coq_fix_code.h
@@ -26,7 +26,7 @@ void init_arity();
#define Is_instruction(pc,instr) (*pc == VALINSTR(instr))
-value coq_tcode_of_code(value code, value len);
+value coq_tcode_of_code(value code);
value coq_makeaccu (value i);
value coq_pushpop (value i);
value coq_is_accumulate_code(value code);
diff --git a/kernel/byterun/coq_interp.c b/kernel/byterun/coq_interp.c
index cfeb0a9ee..8ac1ecc79 100644
--- a/kernel/byterun/coq_interp.c
+++ b/kernel/byterun/coq_interp.c
@@ -16,6 +16,7 @@
#include <stdio.h>
#include <signal.h>
#include <stdint.h>
+#include <caml/memory.h>
#include "coq_gc.h"
#include "coq_instruct.h"
#include "coq_fix_code.h"
@@ -629,7 +630,7 @@ value coq_interprete
print_instr("CLOSUREREC");
if (nvars > 0) *--sp = accu;
/* construction du vecteur de type */
- Alloc_small(accu, nfuncs, 0);
+ Alloc_small(accu, nfuncs, Abstract_tag);
for(i = 0; i < nfuncs; i++) {
Field(accu,i) = (value)(pc+pc[i]);
}
@@ -665,7 +666,7 @@ value coq_interprete
print_instr("CLOSURECOFIX");
if (nvars > 0) *--sp = accu;
/* construction du vecteur de type */
- Alloc_small(accu, nfunc, 0);
+ Alloc_small(accu, nfunc, Abstract_tag);
for(i = 0; i < nfunc; i++) {
Field(accu,i) = (value)(pc+pc[i]);
}
@@ -1071,12 +1072,22 @@ value coq_interprete
}
}
*--sp = accu;
- /* We create the switch zipper */
- Alloc_small(accu, 5, Default_tag);
- Field(accu, 0) = (value)typlbl; Field(accu, 1) = (value)swlbl;
- Field(accu, 2) = sp[1]; Field(accu, 3) = sp[0];
- Field(accu, 4) = coq_env;
- sp++;sp[0] = accu;
+ /* Create bytecode wrappers */
+ Alloc_small(accu, 1, Abstract_tag);
+ Code_val(accu) = typlbl;
+ *--sp = accu;
+ Alloc_small(accu, 1, Abstract_tag);
+ Code_val(accu) = swlbl;
+ *--sp = accu;
+ /* We create the switch zipper */
+ Alloc_small(accu, 5, Default_tag);
+ Field(accu, 0) = sp[1];
+ Field(accu, 1) = sp[0];
+ Field(accu, 2) = sp[3];
+ Field(accu, 3) = sp[2];
+ Field(accu, 4) = coq_env;
+ sp += 3;
+ sp[0] = accu;
/* We create the atom */
Alloc_small(accu, 2, ATOM_SWITCH_TAG);
Field(accu, 0) = sp[1]; Field(accu, 1) = sp[0];
@@ -1476,7 +1487,8 @@ value coq_interprete
#endif
}
-value coq_push_ra(value tcode) {
+value coq_push_ra(value code) {
+ code_t tcode = Code_val(code);
print_instr("push_ra");
coq_sp -= 3;
coq_sp[0] = (value) tcode;
@@ -1516,8 +1528,10 @@ value coq_push_vstack(value stk, value max_stack_size) {
}
value coq_interprete_ml(value tcode, value a, value t, value g, value e, value ea) {
+ // Registering the other arguments w.r.t. the OCaml GC is done by coq_interprete
+ CAMLparam1(tcode);
print_instr("coq_interprete");
- return coq_interprete((code_t)tcode, a, t, g, e, Long_val(ea));
+ CAMLreturn (coq_interprete(Code_val(tcode), a, t, g, e, Long_val(ea)));
print_instr("end coq_interprete");
}
diff --git a/kernel/byterun/coq_memory.c b/kernel/byterun/coq_memory.c
index b2917a55e..542a05fd2 100644
--- a/kernel/byterun/coq_memory.c
+++ b/kernel/byterun/coq_memory.c
@@ -10,6 +10,8 @@
#include <stdio.h>
#include <string.h>
+#include <caml/alloc.h>
+#include <caml/address_class.h>
#include "coq_gc.h"
#include "coq_instruct.h"
#include "coq_fix_code.h"
@@ -46,7 +48,11 @@ value coq_static_alloc(value size) /* ML */
value accumulate_code(value unit) /* ML */
{
- return (value) accumulate;
+ CAMLparam1(unit);
+ CAMLlocal1(res);
+ res = caml_alloc_small(1, Abstract_tag);
+ Code_val(res) = accumulate;
+ CAMLreturn(res);
}
static void (*coq_prev_scan_roots_hook) (scanning_action);
@@ -56,6 +62,10 @@ static void coq_scan_roots(scanning_action action)
register value * i;
/* Scan the stack */
for (i = coq_sp; i < coq_stack_high; i++) {
+#ifdef NO_NAKED_POINTERS
+ /* The VM stack may contain C-allocated bytecode */
+ if (Is_block(*i) && !Is_in_heap_or_young(*i)) continue;
+#endif
(*action) (*i, i);
};
/* Hook */
@@ -94,8 +104,12 @@ value init_coq_vm(value unit) /* ML */
/* Initialing the interpreter */
init_coq_interpreter();
- /* Some predefined pointer code */
- accumulate = (code_t) coq_stat_alloc(sizeof(opcode_t));
+ /* Some predefined pointer code.
+ * It is typically contained in accumlator blocks whose tag is 0 and thus
+ * scanned by the GC, so make it look like an OCaml block. */
+ value accu_block = (value) coq_stat_alloc(2 * sizeof(value));
+ Hd_hp (accu_block) = Make_header (1, Abstract_tag, Caml_black); \
+ accumulate = (code_t) Val_hp(accu_block);
*accumulate = VALINSTR(ACCUMULATE);
/* Initialize GC */
diff --git a/kernel/byterun/coq_values.c b/kernel/byterun/coq_values.c
index 528babebf..e05f3fb82 100644
--- a/kernel/byterun/coq_values.c
+++ b/kernel/byterun/coq_values.c
@@ -9,6 +9,7 @@
/***********************************************************************/
#include <stdio.h>
+#include <caml/memory.h>
#include "coq_fix_code.h"
#include "coq_instruct.h"
#include "coq_memory.h"
@@ -58,10 +59,36 @@ value coq_offset_closure(value v, value offset){
return (value)&Field(v, Int_val(offset));
}
+value coq_set_bytecode_field(value v, value i, value code) {
+ // No write barrier because the bytecode does not live on the OCaml heap
+ Field(v, Long_val(i)) = (value) Code_val(code);
+ return Val_unit;
+}
+
value coq_offset_tcode(value code,value offset){
- return((value)((code_t)code + Int_val(offset)));
+ CAMLparam1(code);
+ CAMLlocal1(res);
+ res = caml_alloc_small(1, Abstract_tag);
+ Code_val(res) = Code_val(code) + Int_val(offset);
+ CAMLreturn(res);
}
-value coq_int_tcode(value code, value offset) {
+value coq_int_tcode(value pc, value offset) {
+ code_t code = Code_val(pc);
return Val_int(*((code_t) code + Int_val(offset)));
}
+
+value coq_tcode_array(value tcodes) {
+ CAMLparam1(tcodes);
+ CAMLlocal2(res, tmp);
+ int i;
+ /* Assumes that the vector of types is small. This was implicit in the
+ previous code which was building the type array using Alloc_small. */
+ res = caml_alloc_small(Wosize_val(tcodes), Default_tag);
+ for (i = 0; i < Wosize_val(tcodes); i++) {
+ tmp = caml_alloc_small(1, Abstract_tag);
+ Code_val(tmp) = (code_t) Field(tcodes, i);
+ Store_field(res, i, tmp);
+ }
+ CAMLreturn(res);
+}
diff --git a/kernel/cemitcodes.ml b/kernel/cemitcodes.ml
index 14f4f27c0..cea09c510 100644
--- a/kernel/cemitcodes.ml
+++ b/kernel/cemitcodes.ml
@@ -20,7 +20,7 @@ open Mod_subst
type emitcodes = String.t
-external tcode_of_code : Bytes.t -> int -> Vmvalues.tcode = "coq_tcode_of_code"
+external tcode_of_code : Bytes.t -> Vmvalues.tcode = "coq_tcode_of_code"
(* Relocation information *)
type reloc_info =
@@ -82,7 +82,7 @@ let patch buff pl f =
(** Order seems important here? *)
let reloc = CArray.map (fun (r, pos) -> (f r, pos)) pl.reloc_infos in
let buff = patch_int buff reloc in
- tcode_of_code buff (Bytes.length buff)
+ tcode_of_code buff
(* Buffering of bytecode *)
diff --git a/kernel/vmvalues.ml b/kernel/vmvalues.ml
index 6a41efac2..7a703e653 100644
--- a/kernel/vmvalues.ml
+++ b/kernel/vmvalues.ml
@@ -59,14 +59,17 @@ let vm_global (v : values array) = (Obj.magic v : vm_global)
(*******************************************)
type tcode
+(** A block whose first field is a C-allocated VM bytecode, encoded as char*.
+ This is compatible with the representation of the Coq VM closures. *)
+
+type tcode_array
external mkAccuCode : int -> tcode = "coq_makeaccu"
external offset_tcode : tcode -> int -> tcode = "coq_offset_tcode"
-let tcode_of_obj v = ((Obj.obj v):tcode)
-let fun_code v = tcode_of_obj (Obj.field (Obj.repr v) 0)
-let fix_code v = fun_code v
-let cofix_upd_code v = fun_code v
+let fun_code v = (Obj.magic v : tcode)
+let fix_code = fun_code
+let cofix_upd_code = fun_code
type vswitch = {
@@ -255,6 +258,7 @@ external kind_of_closure : Obj.t -> int = "coq_kind_of_closure"
external is_accumulate : tcode -> bool = "coq_is_accumulate_code"
external int_tcode : tcode -> int -> int = "coq_int_tcode"
external accumulate : unit -> tcode = "accumulate_code"
+external set_bytecode_field : Obj.t -> int -> tcode -> unit = "coq_set_bytecode_field"
let accumulate = accumulate ()
let whd_val : values -> whd =
@@ -284,7 +288,7 @@ let whd_val : values -> whd =
let obj_of_atom : atom -> Obj.t =
fun a ->
let res = Obj.new_block accu_tag 2 in
- Obj.set_field res 0 (Obj.repr accumulate);
+ set_bytecode_field res 0 accumulate;
Obj.set_field res 1 (Obj.repr a);
res
@@ -370,17 +374,20 @@ external closure_arity : vfun -> int = "coq_closure_arity"
external offset : Obj.t -> int = "coq_offset"
external offset_closure : Obj.t -> int -> Obj.t = "coq_offset_closure"
external offset_closure_fix : vfix -> int -> vm_env = "coq_offset_closure"
+external tcode_array : tcode_array -> tcode array = "coq_tcode_array"
let first o = (offset_closure o (offset o))
let first_fix (v:vfix) = (Obj.magic (first (Obj.repr v)) : vfix)
let last o = (Obj.field o (Obj.size o - 1))
-let fix_types (v:vfix) = (Obj.magic (last (Obj.repr v)) : tcode array)
-let cofix_types (v:vcofix) = (Obj.magic (last (Obj.repr v)) : tcode array)
+let fix_types (v:vfix) = tcode_array (Obj.magic (last (Obj.repr v)) : tcode_array)
+let cofix_types (v:vcofix) = tcode_array (Obj.magic (last (Obj.repr v)) : tcode_array)
let current_fix vf = - (offset (Obj.repr vf) / 2)
-let unsafe_fb_code fb i = tcode_of_obj (Obj.field (Obj.repr fb) (2 * i))
+let unsafe_fb_code fb i =
+ let off = (2 * i) * (Sys.word_size / 8) in
+ Obj.obj (Obj.add_offset (Obj.repr fb) (Int32.of_int off))
let unsafe_rec_arg fb i = int_tcode (unsafe_fb_code fb i) 1
@@ -442,13 +449,12 @@ let relaccu_code i =
let mk_fix_body k ndef fb =
let e = Obj.dup (Obj.repr fb) in
for i = 0 to ndef - 1 do
- Obj.set_field e (2 * i) (Obj.repr (relaccu_code (k + i)))
+ set_bytecode_field e (2 * i) (relaccu_code (k + i))
done;
let fix_body i =
- let jump_grabrec c = offset_tcode c 2 in
- let c = jump_grabrec (unsafe_fb_code fb i) in
+ let c = offset_tcode (unsafe_fb_code fb i) 2 in
let res = Obj.new_block Obj.closure_tag 2 in
- Obj.set_field res 0 (Obj.repr c);
+ set_bytecode_field res 0 c;
Obj.set_field res 1 (offset_closure e (2*i));
((Obj.obj res) : vfun) in
Array.init ndef fix_body
@@ -486,7 +492,7 @@ let mk_cofix_body apply_varray k ndef vcf =
Obj.set_field e 0 c;
let atom = Obj.new_block cofix_tag 1 in
let self = Obj.new_block accu_tag 2 in
- Obj.set_field self 0 (Obj.repr accumulate);
+ set_bytecode_field self 0 accumulate;
Obj.set_field self 1 (Obj.repr atom);
apply_varray (Obj.obj e) [|Obj.obj self|] in
Array.init ndef cofix_body
diff --git a/library/lib.ml b/library/lib.ml
index 543cb45bc..8a54995b9 100644
--- a/library/lib.ml
+++ b/library/lib.ml
@@ -183,22 +183,11 @@ let split_lib_gen test =
| before -> after,equal,before
in
let rec findeq after = function
- | hd :: before ->
- if test hd
- then Some (collect after [hd] before)
- else (match hd with
- | (sp,ClosedModule seg)
- | (sp,ClosedSection seg) ->
- (match findeq after seg with
- | None -> findeq (hd::after) before
- | Some (sub_after,sub_equal,sub_before) ->
- Some (sub_after, sub_equal, (List.append sub_before before)))
- | _ -> findeq (hd::after) before)
- | [] -> None
+ | hd :: before when test hd -> collect after [hd] before
+ | hd :: before -> findeq (hd::after) before
+ | [] -> user_err Pp.(str "no such entry")
in
- match findeq [] !lib_state.lib_stk with
- | None -> user_err Pp.(str "no such entry")
- | Some r -> r
+ findeq [] !lib_state.lib_stk
let eq_object_name (fp1, kn1) (fp2, kn2) =
eq_full_path fp1 fp2 && Names.KerName.equal kn1 kn2
@@ -580,13 +569,11 @@ let close_section () =
in
let (secdecls,mark,before) = split_lib_at_opening oname in
lib_state := { !lib_state with lib_stk = before };
- let full_olddir = !lib_state.path_prefix.obj_dir in
pop_path_prefix ();
add_entry oname (ClosedSection (List.rev (mark::secdecls)));
let newdecls = List.map discharge_item secdecls in
Summary.unfreeze_summaries fs;
- List.iter (Option.iter (fun (id,o) -> add_discharged_leaf id o)) newdecls;
- Nametab.push_dir (Nametab.Until 1) full_olddir (DirClosedSection full_olddir)
+ List.iter (Option.iter (fun (id,o) -> add_discharged_leaf id o)) newdecls
(* State and initialization. *)
diff --git a/library/libnames.ml b/library/libnames.ml
index d84731322..4ceea480d 100644
--- a/library/libnames.ml
+++ b/library/libnames.ml
@@ -174,8 +174,6 @@ type global_dir_reference =
| DirOpenModtype of object_prefix
| DirOpenSection of object_prefix
| DirModule of object_prefix
- | DirClosedSection of DirPath.t
- (* this won't last long I hope! *)
let eq_op op1 op2 =
DirPath.equal op1.obj_dir op2.obj_dir &&
@@ -187,7 +185,6 @@ let eq_global_dir_reference r1 r2 = match r1, r2 with
| DirOpenModtype op1, DirOpenModtype op2 -> eq_op op1 op2
| DirOpenSection op1, DirOpenSection op2 -> eq_op op1 op2
| DirModule op1, DirModule op2 -> eq_op op1 op2
-| DirClosedSection dp1, DirClosedSection dp2 -> DirPath.equal dp1 dp2
| _ -> false
type reference_r =
diff --git a/library/libnames.mli b/library/libnames.mli
index 9dad26129..81e5bc5b1 100644
--- a/library/libnames.mli
+++ b/library/libnames.mli
@@ -125,8 +125,6 @@ type global_dir_reference =
| DirOpenModtype of object_prefix
| DirOpenSection of object_prefix
| DirModule of object_prefix
- | DirClosedSection of DirPath.t
- (** this won't last long I hope! *)
val eq_global_dir_reference :
global_dir_reference -> global_dir_reference -> bool
diff --git a/library/nametab.ml b/library/nametab.ml
index 2046bf758..995f44706 100644
--- a/library/nametab.ml
+++ b/library/nametab.ml
@@ -432,7 +432,6 @@ let full_name_module qid =
let locate_section qid =
match locate_dir qid with
| DirOpenSection { obj_dir; _ } -> obj_dir
- | DirClosedSection dir -> dir
| _ -> raise Not_found
let locate_all qid =
diff --git a/man/coqtop.1 b/man/coqtop.1
index b1fbb3262..084adfe45 100644
--- a/man/coqtop.1
+++ b/man/coqtop.1
@@ -110,7 +110,7 @@ print Coq version and exit
.TP
.B \-q
-skip loading of rcfile
+skip loading of rcfile (resource file) if any
.TP
.BI \-init\-file \ filename
diff --git a/plugins/ltac/tactic_matching.ml b/plugins/ltac/tactic_matching.ml
index b6462c810..c949589e2 100644
--- a/plugins/ltac/tactic_matching.ml
+++ b/plugins/ltac/tactic_matching.ml
@@ -46,7 +46,7 @@ let adjust : Constr_matching.bound_ident_map * Ltac_pretype.patvar_map ->
(** Adds a binding to a {!Id.Map.t} if the identifier is [Some id] *)
let id_map_try_add id x m =
match id with
- | Some id -> Id.Map.add id x m
+ | Some id -> Id.Map.add id (Lazy.force x) m
| None -> m
(** Adds a binding to a {!Id.Map.t} if the name is [Name id] *)
diff --git a/pretyping/constr_matching.ml b/pretyping/constr_matching.ml
index 89d490a41..b4e1a1b10 100644
--- a/pretyping/constr_matching.ml
+++ b/pretyping/constr_matching.ml
@@ -427,7 +427,7 @@ let special_meta = (-1)
type matching_result =
{ m_sub : bound_ident_map * patvar_map;
- m_ctx : constr; }
+ m_ctx : constr Lazy.t; }
let mkresult s c n = IStream.Cons ( { m_sub=s; m_ctx=c; } , (IStream.thunk n) )
@@ -451,7 +451,7 @@ let authorized_occ env sigma closed pat c mk_ctx =
let subst = matches_core_closed env sigma pat c in
if closed && Id.Map.exists (fun _ c -> not (closed0 sigma c)) (snd subst)
then (fun next -> next ())
- else (fun next -> mkresult subst (mk_ctx (mkMeta special_meta)) next)
+ else (fun next -> mkresult subst (lazy (mk_ctx (mkMeta special_meta))) next)
with PatternMatchingFailure -> (fun next -> next ())
let subargs env v = Array.map_to_list (fun c -> (env, c)) v
diff --git a/pretyping/constr_matching.mli b/pretyping/constr_matching.mli
index 3c2c73915..d19789ef4 100644
--- a/pretyping/constr_matching.mli
+++ b/pretyping/constr_matching.mli
@@ -61,7 +61,7 @@ val is_matching_head : env -> Evd.evar_map -> constr_pattern -> constr -> bool
(whose hole is denoted here with [special_meta]) *)
type matching_result =
{ m_sub : bound_ident_map * patvar_map;
- m_ctx : EConstr.t }
+ m_ctx : EConstr.t Lazy.t }
(** [match_subterm pat c] returns the substitution and the context
corresponding to each **closed** subterm of [c] matching [pat],
diff --git a/printing/prettyp.ml b/printing/prettyp.ml
index b95691031..185b1648c 100644
--- a/printing/prettyp.ml
+++ b/printing/prettyp.ml
@@ -376,7 +376,6 @@ let pr_located_qualid = function
| DirOpenModtype { obj_dir ; _ } -> "Open Module Type", obj_dir
| DirOpenSection { obj_dir ; _ } -> "Open Section", obj_dir
| DirModule { obj_dir ; _ } -> "Module", obj_dir
- | DirClosedSection dir -> "Closed Section", dir
in
str s ++ spc () ++ DirPath.print dir
| ModuleType mp ->
diff --git a/test-suite/Makefile b/test-suite/Makefile
index 9d84cd5c7..ce21ff41c 100644
--- a/test-suite/Makefile
+++ b/test-suite/Makefile
@@ -8,9 +8,6 @@
## # (see LICENSE file for the text of the license) ##
##########################################################################
-# This is a standalone Makefile to run the test-suite. It can be used
-# outside of the Coq source tree (if BIN is overridden).
-
# There is one %.v.log target per %.v test file. The target will be
# filled with the output, timings and status of the test. There is
# also one target per directory containing %.v files, that runs all
@@ -23,6 +20,14 @@
# The "run" target runs all tests that have not been run yet. To force
# all tests to be run, use the "clean" target.
+
+###########################################################################
+# Includes
+###########################################################################
+
+include ../config/Makefile
+include ../Makefile.common
+
#######################################################################
# Variables
#######################################################################
@@ -94,10 +99,10 @@ INTERACTIVE := interactive
VSUBSYSTEMS := prerequisite success failure $(BUGS) output \
output-modulo-time $(INTERACTIVE) micromega $(COMPLEXITY) modules stm \
- coqdoc
+ coqdoc ssr
# All subsystems
-SUBSYSTEMS := $(VSUBSYSTEMS) misc bugs ide vio coqchk coqwc coq-makefile
+SUBSYSTEMS := $(VSUBSYSTEMS) misc bugs ide vio coqchk coqwc coq-makefile unit-tests
PREREQUISITELOG = prerequisite/admit.v.log \
prerequisite/make_local.v.log prerequisite/make_notation.v.log \
@@ -118,13 +123,16 @@ bugs: $(BUGS)
clean:
rm -f trace .lia.cache output/MExtraction.out
- $(SHOW) "RM <**/*.vo> <**/*.vio> <**/*.log> <**/*.glob>"
+ $(SHOW) 'RM <**/*.stamp> <**/*.vo> <**/*.vio> <**/*.log> <**/*.glob>'
$(HIDE)find . \( \
- -name '*.vo' -o -name '*.vio' -o -name '*.log' -o -name '*.glob' \
- \) -print0 | xargs -0 rm -f
-
+ -name '*.stamp' -o -name '*.vo' -o -name '*.vio' -o -name '*.log' -o -name '*.glob' \
+ \) -print0 | xargs -0 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
distclean: clean
- $(SHOW) "RM <**/*.aux>"
+ $(SHOW) 'RM <**/*.aux>'
$(HIDE)find . -name '*.aux' -print0 | xargs -0 rm -f
#######################################################################
@@ -158,18 +166,20 @@ summary:
$(call summary_dir, "Complexity tests", complexity); \
$(call summary_dir, "Module tests", modules); \
$(call summary_dir, "STM tests", stm); \
+ $(call summary_dir, "SSR tests", ssr); \
$(call summary_dir, "IDE tests", ide); \
$(call summary_dir, "VI tests", vio); \
$(call summary_dir, "Coqchk tests", coqchk); \
$(call summary_dir, "Coqwc tests", coqwc); \
$(call summary_dir, "Coq makefile", coq-makefile); \
$(call summary_dir, "Coqdoc tests", coqdoc); \
+ $(call summary_dir, "Unit tests", unit-tests); \
nb_success=`find . -name '*.log' -exec tail -n2 '{}' \; | grep -e $(log_success) | wc -l`; \
nb_failure=`find . -name '*.log' -exec tail -n2 '{}' \; | grep -e $(log_failure) | wc -l`; \
nb_tests=`expr $$nb_success + $$nb_failure`; \
- pourcentage=`expr 100 \* $$nb_success / $$nb_tests`; \
+ percentage=`expr 100 \* $$nb_success / $$nb_tests`; \
echo; \
- echo "$$nb_success tests passed over $$nb_tests, i.e. $$pourcentage %"; \
+ echo "$$nb_success tests passed over $$nb_tests, i.e. $$percentage %"; \
}
summary.log:
@@ -243,6 +253,44 @@ $(addsuffix .log,$(wildcard bugs/closed/*.v)): %.v.log: %.v
} > "$@"
#######################################################################
+# Unit tests
+#######################################################################
+
+OCAMLOPT := $(OCAMLFIND) opt $(CAMLFLAGS)
+SYSMOD:=-package num,str,unix,dynlink,threads
+
+COQSRCDIRS:=$(addprefix -I $(LIB)/,$(CORESRCDIRS))
+COQCMXS:=$(addprefix $(LIB)/,$(LINKCMX))
+
+# ML files from unit-test framework, not containing tests
+UNIT_SRCFILES:=$(shell find ./unit-tests/src -name *.ml)
+UNIT_ALLMLFILES:=$(shell find ./unit-tests -name *.ml)
+UNIT_MLFILES:=$(filter-out $(UNIT_SRCFILES),$(UNIT_ALLMLFILES))
+UNIT_LOGFILES:=$(patsubst %.ml,%.ml.log,$(UNIT_MLFILES))
+
+UNIT_CMXS=utest.cmx
+
+unit-tests/src/utest.cmx: unit-tests/src/utest.ml unit-tests/src/utest.cmi
+ $(SHOW) 'OCAMLOPT $<'
+ $(HIDE)$(OCAMLOPT) -c -I unit-tests/src -package oUnit $<
+unit-tests/src/utest.cmi: unit-tests/src/utest.mli
+ $(SHOW) 'OCAMLOPT $<'
+ $(HIDE)$(OCAMLOPT) -package oUnit $<
+
+$(UNIT_LOGFILES): unit-tests/src/utest.cmx
+
+unit-tests: $(UNIT_LOGFILES)
+
+# Build executable, run it to generate log file
+unit-tests/%.ml.log: unit-tests/%.ml
+ $(SHOW) 'TEST $<'
+ $(HIDE)$(OCAMLOPT) -linkall -linkpkg -cclib -lcoqrun \
+ $(SYSMOD) -package camlp5.gramlib,oUnit \
+ -I unit-tests/src $(COQSRCDIRS) $(COQCMXS) \
+ $(UNIT_CMXS) $< -o $<.test;
+ $(HIDE)./$<.test
+
+#######################################################################
# Other generic tests
#######################################################################
@@ -261,7 +309,8 @@ $(addsuffix .log,$(wildcard prerequisite/*.v)): %.v.log: %.v
fi; \
} > "$@"
-$(addsuffix .log,$(wildcard success/*.v micromega/*.v modules/*.v)): %.v.log: %.v $(PREREQUISITELOG)
+ssr: $(wildcard ssr/*.v:%.v=%.v.log)
+$(addsuffix .log,$(wildcard ssr/*.v success/*.v micromega/*.v modules/*.v)): %.v.log: %.v $(PREREQUISITELOG)
@echo "TEST $< $(call get_coq_prog_args_in_parens,"$<")"
$(HIDE){ \
opts="$(if $(findstring modules/,$<),-R modules Mods -impredicative-set)"; \
diff --git a/test-suite/README.md b/test-suite/README.md
index 1d1195646..4572c98cf 100644
--- a/test-suite/README.md
+++ b/test-suite/README.md
@@ -73,3 +73,6 @@ When you fix a bug, you should usually add a regression test here as well.
The error "(bug seems to be opened, please check)" when running `make test-suite` means that a test in `bugs/closed` failed to compile.
There are also output tests in `test-suite/output` which consist of a `.v` file and a `.out` file with the expected output.
+
+There are unit tests of OCaml code in `test-suite/unit-tests`. These tests are contained in `.ml` files, and rely on the `OUnit`
+unit-test framework, as described at http://ounit.forge.ocamlcore.org/. Use `make unit-tests' in the unit-tests directory to run them.
diff --git a/test-suite/bugs/closed/4722.v b/test-suite/bugs/closed/4722.v
deleted file mode 100644
index 2d41828f1..000000000
--- a/test-suite/bugs/closed/4722.v
+++ /dev/null
@@ -1 +0,0 @@
-(* -*- coq-prog-args: ("-R" "4722" "Foo") -*- *)
diff --git a/test-suite/bugs/closed/4722/tata b/test-suite/bugs/closed/4722/tata
deleted file mode 120000
index b38e66e75..000000000
--- a/test-suite/bugs/closed/4722/tata
+++ /dev/null
@@ -1 +0,0 @@
-toto \ No newline at end of file
diff --git a/test-suite/bugs/closed/7462.v b/test-suite/bugs/closed/7462.v
new file mode 100644
index 000000000..40ca39e38
--- /dev/null
+++ b/test-suite/bugs/closed/7462.v
@@ -0,0 +1,13 @@
+(* Adding an only-printing notation should not override existing
+ interpretations for the same notation. *)
+
+Notation "$ x" := (@id nat x) (only parsing, at level 0).
+Notation "$ x" := (@id bool x) (only printing, at level 0).
+Check $1. (* Was: Error: Unknown interpretation for notation "$ _". *)
+
+(* Adding an only-printing notation should not let believe
+ that a parsing rule has been given *)
+
+Notation "$ x" := (@id bool x) (only printing, at level 0).
+Notation "$ x" := (@id nat x) (only parsing, at level 0).
+Check $1. (* Was: Error: Syntax Error: Lexer: Undefined token *)
diff --git a/test-suite/misc/.gitignore b/test-suite/misc/.gitignore
new file mode 100644
index 000000000..a4083e931
--- /dev/null
+++ b/test-suite/misc/.gitignore
@@ -0,0 +1,2 @@
+4722/
+4722.v
diff --git a/test-suite/misc/4722.sh b/test-suite/misc/4722.sh
new file mode 100755
index 000000000..86bc50b5c
--- /dev/null
+++ b/test-suite/misc/4722.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+set -e
+
+# create test files
+mkdir -p misc/4722
+ln -sf toto misc/4722/tata
+touch misc/4722.v
+
+# run test
+$coqtop "-R" "misc/4722" "Foo" -top Top -load-vernac-source misc/4722.v
+
+# clean up test files
+rm misc/4722/tata
+rmdir misc/4722
+rm misc/4722.v
diff --git a/test-suite/misc/coqc_dash_o.sh b/test-suite/misc/coqc_dash_o.sh
index f303214b9..0ae7873fd 100755
--- a/test-suite/misc/coqc_dash_o.sh
+++ b/test-suite/misc/coqc_dash_o.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
DOUT=misc/tmp_coqc_dash_o/
OUT=${DOUT}coqc_dash_o.vo
diff --git a/test-suite/output/Notations3.out b/test-suite/output/Notations3.out
index 304353f55..996af5927 100644
--- a/test-suite/output/Notations3.out
+++ b/test-suite/output/Notations3.out
@@ -231,3 +231,13 @@ fun l : list nat => match l with
: list nat -> list nat
Argument scope is [list_scope]
+Notation
+"'exists' x .. y , p" := ex (fun x => .. (ex (fun y => p)) ..) : type_scope
+(default interpretation)
+"'exists' ! x .. y , p" := ex
+ (unique
+ (fun x => .. (ex (unique (fun y => p))) ..))
+: type_scope (default interpretation)
+Notation
+"( x , y , .. , z )" := pair .. (pair x y) .. z : core_scope
+(default interpretation)
diff --git a/test-suite/output/Notations3.v b/test-suite/output/Notations3.v
index d2d136946..3cf0c913f 100644
--- a/test-suite/output/Notations3.v
+++ b/test-suite/output/Notations3.v
@@ -380,3 +380,8 @@ Definition foo (l : list nat) :=
end.
Print foo.
End Issue7110.
+
+Module LocateNotations.
+Locate "exists".
+Locate "( _ , _ , .. , _ )".
+End LocateNotations.
diff --git a/test-suite/output/ssr_explain_match.out b/test-suite/output/ssr_explain_match.out
new file mode 100644
index 000000000..fa2393b91
--- /dev/null
+++ b/test-suite/output/ssr_explain_match.out
@@ -0,0 +1,55 @@
+File "stdin", line 12, characters 0-61:
+Warning: Notation _ - _ was already used in scope nat_scope.
+[notation-overridden,parsing]
+File "stdin", line 12, characters 0-61:
+Warning: Notation _ <= _ was already used in scope nat_scope.
+[notation-overridden,parsing]
+File "stdin", line 12, characters 0-61:
+Warning: Notation _ < _ was already used in scope nat_scope.
+[notation-overridden,parsing]
+File "stdin", line 12, characters 0-61:
+Warning: Notation _ >= _ was already used in scope nat_scope.
+[notation-overridden,parsing]
+File "stdin", line 12, characters 0-61:
+Warning: Notation _ > _ was already used in scope nat_scope.
+[notation-overridden,parsing]
+File "stdin", line 12, characters 0-61:
+Warning: Notation _ <= _ <= _ was already used in scope nat_scope.
+[notation-overridden,parsing]
+File "stdin", line 12, characters 0-61:
+Warning: Notation _ < _ <= _ was already used in scope nat_scope.
+[notation-overridden,parsing]
+File "stdin", line 12, characters 0-61:
+Warning: Notation _ <= _ < _ was already used in scope nat_scope.
+[notation-overridden,parsing]
+File "stdin", line 12, characters 0-61:
+Warning: Notation _ < _ < _ was already used in scope nat_scope.
+[notation-overridden,parsing]
+File "stdin", line 12, characters 0-61:
+Warning: Notation _ + _ was already used in scope nat_scope.
+[notation-overridden,parsing]
+File "stdin", line 12, characters 0-61:
+Warning: Notation _ * _ was already used in scope nat_scope.
+[notation-overridden,parsing]
+BEGIN INSTANCES
+instance: (x + y + z) matches: (x + y + z)
+instance: (x + y) matches: (x + y)
+instance: (x + y) matches: (x + y)
+END INSTANCES
+BEGIN INSTANCES
+instance: (addnC (x + y) z) matches: (x + y + z)
+instance: (addnC x y) matches: (x + y)
+instance: (addnC x y) matches: (x + y)
+END INSTANCES
+BEGIN INSTANCES
+instance: (addnA x y z) matches: (x + y + z)
+END INSTANCES
+BEGIN INSTANCES
+instance: (addnA x y z) matches: (x + y + z)
+instance: (addnC z (x + y)) matches: (x + y + z)
+instance: (addnC y x) matches: (x + y)
+instance: (addnC y x) matches: (x + y)
+END INSTANCES
+The command has indeed failed with message:
+Ltac call to "ssrinstancesoftpat (cpattern)" failed.
+Not supported
diff --git a/test-suite/output/ssr_explain_match.v b/test-suite/output/ssr_explain_match.v
new file mode 100644
index 000000000..56ca24b6e
--- /dev/null
+++ b/test-suite/output/ssr_explain_match.v
@@ -0,0 +1,23 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+Require Import ssrmatching.
+Require Import ssreflect ssrbool TestSuite.ssr_mini_mathcomp.
+
+Definition addnAC := (addnA, addnC).
+
+Lemma test x y z : x + y + z = x + y.
+
+ssrinstancesoftpat (_ + _).
+ssrinstancesofruleL2R addnC.
+ssrinstancesofruleR2L addnA.
+ssrinstancesofruleR2L addnAC.
+Fail ssrinstancesoftpat (_ + _ in RHS). (* Not implemented *)
+Admitted.
diff --git a/test-suite/prerequisite/ssr_mini_mathcomp.v b/test-suite/prerequisite/ssr_mini_mathcomp.v
new file mode 100644
index 000000000..cb2c56736
--- /dev/null
+++ b/test-suite/prerequisite/ssr_mini_mathcomp.v
@@ -0,0 +1,1472 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* Some code from mathcomp needed in order to run ssr_* tests *)
+
+Require Import ssreflect ssrfun ssrbool.
+
+Global Set SsrOldRewriteGoalsOrder.
+Global Set Asymmetric Patterns.
+Global Set Bullet Behavior "None".
+
+Set Implicit Arguments.
+Unset Strict Implicit.
+Unset Printing Implicit Defensive.
+
+(* eqtype ---------------------------------------------------------- *)
+
+Module Equality.
+
+Definition axiom T (e : rel T) := forall x y, reflect (x = y) (e x y).
+
+Structure mixin_of T := Mixin {op : rel T; _ : axiom op}.
+Notation class_of := mixin_of (only parsing).
+
+Section ClassDef.
+
+Structure type := Pack {sort; _ : class_of sort; _ : Type}.
+Local Coercion sort : type >-> Sortclass.
+Variables (T : Type) (cT : type).
+
+Definition class := let: Pack _ c _ := cT return class_of cT in c.
+
+Definition pack c := @Pack T c T.
+Definition clone := fun c & cT -> T & phant_id (pack c) cT => pack c.
+
+End ClassDef.
+
+Module Exports.
+Coercion sort : type >-> Sortclass.
+Notation eqType := type.
+Notation EqMixin := Mixin.
+Notation EqType T m := (@pack T m).
+Notation "[ 'eqMixin' 'of' T ]" := (class _ : mixin_of T)
+ (at level 0, format "[ 'eqMixin' 'of' T ]") : form_scope.
+Notation "[ 'eqType' 'of' T 'for' C ]" := (@clone T C _ idfun id)
+ (at level 0, format "[ 'eqType' 'of' T 'for' C ]") : form_scope.
+Notation "[ 'eqType' 'of' T ]" := (@clone T _ _ id id)
+ (at level 0, format "[ 'eqType' 'of' T ]") : form_scope.
+End Exports.
+
+End Equality.
+Export Equality.Exports.
+
+Definition eq_op T := Equality.op (Equality.class T).
+
+Lemma eqE T x : eq_op x = Equality.op (Equality.class T) x.
+Proof. by []. Qed.
+
+Lemma eqP T : Equality.axiom (@eq_op T).
+Proof. by case: T => ? []. Qed.
+Arguments eqP [T x y].
+
+Delimit Scope eq_scope with EQ.
+Open Scope eq_scope.
+
+Notation "x == y" := (eq_op x y)
+ (at level 70, no associativity) : bool_scope.
+Notation "x == y :> T" := ((x : T) == (y : T))
+ (at level 70, y at next level) : bool_scope.
+Notation "x != y" := (~~ (x == y))
+ (at level 70, no associativity) : bool_scope.
+Notation "x != y :> T" := (~~ (x == y :> T))
+ (at level 70, y at next level) : bool_scope.
+Notation "x =P y" := (eqP : reflect (x = y) (x == y))
+ (at level 70, no associativity) : eq_scope.
+Notation "x =P y :> T" := (eqP : reflect (x = y :> T) (x == y :> T))
+ (at level 70, y at next level, no associativity) : eq_scope.
+
+Prenex Implicits eq_op eqP.
+
+Lemma eq_refl (T : eqType) (x : T) : x == x. Proof. exact/eqP. Qed.
+Notation eqxx := eq_refl.
+
+Lemma eq_sym (T : eqType) (x y : T) : (x == y) = (y == x).
+Proof. exact/eqP/eqP. Qed.
+
+Hint Resolve eq_refl eq_sym.
+
+
+Definition eqb b := addb (~~ b).
+
+Lemma eqbP : Equality.axiom eqb.
+Proof. by do 2!case; constructor. Qed.
+
+Canonical bool_eqMixin := EqMixin eqbP.
+Canonical bool_eqType := Eval hnf in EqType bool bool_eqMixin.
+
+Section ProdEqType.
+
+Variable T1 T2 : eqType.
+
+Definition pair_eq := [rel u v : T1 * T2 | (u.1 == v.1) && (u.2 == v.2)].
+
+Lemma pair_eqP : Equality.axiom pair_eq.
+Proof.
+move=> [x1 x2] [y1 y2] /=; apply: (iffP andP) => [[]|[<- <-]] //=.
+by do 2!move/eqP->.
+Qed.
+
+Definition prod_eqMixin := EqMixin pair_eqP.
+Canonical prod_eqType := Eval hnf in EqType (T1 * T2) prod_eqMixin.
+
+End ProdEqType.
+
+Section OptionEqType.
+
+Variable T : eqType.
+
+Definition opt_eq (u v : option T) : bool :=
+ oapp (fun x => oapp (eq_op x) false v) (~~ v) u.
+
+Lemma opt_eqP : Equality.axiom opt_eq.
+Proof.
+case=> [x|] [y|] /=; by [constructor | apply: (iffP eqP) => [|[]] ->].
+Qed.
+
+Canonical option_eqMixin := EqMixin opt_eqP.
+Canonical option_eqType := Eval hnf in EqType (option T) option_eqMixin.
+
+End OptionEqType.
+
+Notation xpred1 := (fun a1 x => x == a1).
+Notation xpredU1 := (fun a1 (p : pred _) x => (x == a1) || p x).
+
+Section EqPred.
+
+Variable T : eqType.
+
+Definition pred1 (a1 : T) := SimplPred (xpred1 a1).
+Definition predU1 (a1 : T) p := SimplPred (xpredU1 a1 p).
+
+End EqPred.
+
+Section TransferEqType.
+
+Variables (T : Type) (eT : eqType) (f : T -> eT).
+
+Lemma inj_eqAxiom : injective f -> Equality.axiom (fun x y => f x == f y).
+Proof. by move=> f_inj x y; apply: (iffP eqP) => [|-> //]; apply: f_inj. Qed.
+
+Definition InjEqMixin f_inj := EqMixin (inj_eqAxiom f_inj).
+
+Definition PcanEqMixin g (fK : pcancel f g) := InjEqMixin (pcan_inj fK).
+
+Definition CanEqMixin g (fK : cancel f g) := InjEqMixin (can_inj fK).
+
+End TransferEqType.
+
+(* We use the module system to circumvent a silly limitation that *)
+(* forbids using the same constant to coerce to different targets. *)
+Module Type EqTypePredSig.
+Parameter sort : eqType -> predArgType.
+End EqTypePredSig.
+Module MakeEqTypePred (eqmod : EqTypePredSig).
+Coercion eqmod.sort : eqType >-> predArgType.
+End MakeEqTypePred.
+Module Export EqTypePred := MakeEqTypePred Equality.
+
+
+Section SubType.
+
+Variables (T : Type) (P : pred T).
+
+Structure subType : Type := SubType {
+ sub_sort :> Type;
+ val : sub_sort -> T;
+ Sub : forall x, P x -> sub_sort;
+ _ : forall K (_ : forall x Px, K (@Sub x Px)) u, K u;
+ _ : forall x Px, val (@Sub x Px) = x
+}.
+
+Arguments Sub [s].
+Lemma vrefl : forall x, P x -> x = x. Proof. by []. Qed.
+Definition vrefl_rect := vrefl.
+
+Definition clone_subType U v :=
+ fun sT & sub_sort sT -> U =>
+ fun c Urec cK (sT' := @SubType U v c Urec cK) & phant_id sT' sT => sT'.
+
+Variable sT : subType.
+
+CoInductive Sub_spec : sT -> Type := SubSpec x Px : Sub_spec (Sub x Px).
+
+Lemma SubP u : Sub_spec u.
+Proof. by case: sT Sub_spec SubSpec u => T' _ C rec /= _. Qed.
+
+Lemma SubK x Px : @val sT (Sub x Px) = x.
+Proof. by case: sT. Qed.
+
+Definition insub x :=
+ if @idP (P x) is ReflectT Px then @Some sT (Sub x Px) else None.
+
+Definition insubd u0 x := odflt u0 (insub x).
+
+CoInductive insub_spec x : option sT -> Type :=
+ | InsubSome u of P x & val u = x : insub_spec x (Some u)
+ | InsubNone of ~~ P x : insub_spec x None.
+
+Lemma insubP x : insub_spec x (insub x).
+Proof.
+by rewrite /insub; case: {-}_ / idP; [left; rewrite ?SubK | right; apply/negP].
+Qed.
+
+Lemma insubT x Px : insub x = Some (Sub x Px).
+Admitted.
+
+Lemma insubF x : P x = false -> insub x = None.
+Proof. by move/idP; case: insubP. Qed.
+
+Lemma insubN x : ~~ P x -> insub x = None.
+Proof. by move/negPf/insubF. Qed.
+
+Lemma isSome_insub : ([eta insub] : pred T) =1 P.
+Proof. by apply: fsym => x; case: insubP => // /negPf. Qed.
+
+Lemma insubK : ocancel insub (@val _).
+Proof. by move=> x; case: insubP. Qed.
+
+Lemma valP (u : sT) : P (val u).
+Proof. by case/SubP: u => x Px; rewrite SubK. Qed.
+
+Lemma valK : pcancel (@val _) insub.
+Proof. by case/SubP=> x Px; rewrite SubK; apply: insubT. Qed.
+
+Lemma val_inj : injective (@val sT).
+Proof. exact: pcan_inj valK. Qed.
+
+Lemma valKd u0 : cancel (@val _) (insubd u0).
+Proof. by move=> u; rewrite /insubd valK. Qed.
+
+Lemma val_insubd u0 x : val (insubd u0 x) = if P x then x else val u0.
+Proof. by rewrite /insubd; case: insubP => [u -> | /negPf->]. Qed.
+
+Lemma insubdK u0 : {in P, cancel (insubd u0) (@val _)}.
+Proof. by move=> x Px; rewrite /= val_insubd [P x]Px. Qed.
+
+Definition insub_eq x :=
+ let Some_sub Px := Some (Sub x Px : sT) in
+ let None_sub _ := None in
+ (if P x as Px return P x = Px -> _ then Some_sub else None_sub) (erefl _).
+
+Lemma insub_eqE : insub_eq =1 insub.
+Proof.
+rewrite /insub_eq /insub => x; case: {2 3}_ / idP (erefl _) => // Px Px'.
+by congr (Some _); apply: val_inj; rewrite !SubK.
+Qed.
+
+End SubType.
+
+Arguments SubType [T P].
+Arguments Sub [T P s].
+Arguments vrefl [T P].
+Arguments vrefl_rect [T P].
+Arguments clone_subType [T P] U v [sT] _ [c Urec cK].
+Arguments insub [T P sT].
+Arguments insubT [T] P [sT x].
+Arguments val_inj [T P sT].
+Prenex Implicits val Sub vrefl vrefl_rect insub insubd val_inj.
+
+Local Notation inlined_sub_rect :=
+ (fun K K_S u => let (x, Px) as u return K u := u in K_S x Px).
+
+Local Notation inlined_new_rect :=
+ (fun K K_S u => let (x) as u return K u := u in K_S x).
+
+Notation "[ 'subType' 'for' v ]" := (SubType _ v _ inlined_sub_rect vrefl_rect)
+ (at level 0, only parsing) : form_scope.
+
+Notation "[ 'sub' 'Type' 'for' v ]" := (SubType _ v _ _ vrefl_rect)
+ (at level 0, format "[ 'sub' 'Type' 'for' v ]") : form_scope.
+
+Notation "[ 'subType' 'for' v 'by' rec ]" := (SubType _ v _ rec vrefl)
+ (at level 0, format "[ 'subType' 'for' v 'by' rec ]") : form_scope.
+
+Notation "[ 'subType' 'of' U 'for' v ]" := (clone_subType U v id idfun)
+ (at level 0, format "[ 'subType' 'of' U 'for' v ]") : form_scope.
+
+(*
+Notation "[ 'subType' 'for' v ]" := (clone_subType _ v id idfun)
+ (at level 0, format "[ 'subType' 'for' v ]") : form_scope.
+*)
+Notation "[ 'subType' 'of' U ]" := (clone_subType U _ id id)
+ (at level 0, format "[ 'subType' 'of' U ]") : form_scope.
+
+Definition NewType T U v c Urec :=
+ let Urec' P IH := Urec P (fun x : T => IH x isT : P _) in
+ SubType U v (fun x _ => c x) Urec'.
+Arguments NewType [T U].
+
+Notation "[ 'newType' 'for' v ]" := (NewType v _ inlined_new_rect vrefl_rect)
+ (at level 0, only parsing) : form_scope.
+
+Notation "[ 'new' 'Type' 'for' v ]" := (NewType v _ _ vrefl_rect)
+ (at level 0, format "[ 'new' 'Type' 'for' v ]") : form_scope.
+
+Notation "[ 'newType' 'for' v 'by' rec ]" := (NewType v _ rec vrefl)
+ (at level 0, format "[ 'newType' 'for' v 'by' rec ]") : form_scope.
+
+Definition innew T nT x := @Sub T predT nT x (erefl true).
+Arguments innew [T nT].
+Prenex Implicits innew.
+
+Lemma innew_val T nT : cancel val (@innew T nT).
+Proof. by move=> u; apply: val_inj; apply: SubK. Qed.
+
+(* Prenex Implicits and renaming. *)
+Notation sval := (@proj1_sig _ _).
+Notation "@ 'sval'" := (@proj1_sig) (at level 10, format "@ 'sval'").
+
+Section SubEqType.
+
+Variables (T : eqType) (P : pred T) (sT : subType P).
+
+Local Notation ev_ax := (fun T v => @Equality.axiom T (fun x y => v x == v y)).
+Lemma val_eqP : ev_ax sT val. Proof. exact: inj_eqAxiom val_inj. Qed.
+
+Definition sub_eqMixin := EqMixin val_eqP.
+Canonical sub_eqType := Eval hnf in EqType sT sub_eqMixin.
+
+Definition SubEqMixin :=
+ (let: SubType _ v _ _ _ as sT' := sT
+ return ev_ax sT' val -> Equality.class_of sT' in
+ fun vP : ev_ax _ v => EqMixin vP
+ ) val_eqP.
+
+Lemma val_eqE (u v : sT) : (val u == val v) = (u == v).
+Proof. by []. Qed.
+
+End SubEqType.
+
+Arguments val_eqP [T P sT x y].
+Prenex Implicits val_eqP.
+
+Notation "[ 'eqMixin' 'of' T 'by' <: ]" := (SubEqMixin _ : Equality.class_of T)
+ (at level 0, format "[ 'eqMixin' 'of' T 'by' <: ]") : form_scope.
+
+(* ssrnat ---------------------------------------------------------- *)
+
+Notation succn := Datatypes.S.
+Notation predn := Peano.pred.
+
+Notation "n .+1" := (succn n) (at level 2, left associativity,
+ format "n .+1") : nat_scope.
+Notation "n .+2" := n.+1.+1 (at level 2, left associativity,
+ format "n .+2") : nat_scope.
+Notation "n .+3" := n.+2.+1 (at level 2, left associativity,
+ format "n .+3") : nat_scope.
+Notation "n .+4" := n.+2.+2 (at level 2, left associativity,
+ format "n .+4") : nat_scope.
+
+Notation "n .-1" := (predn n) (at level 2, left associativity,
+ format "n .-1") : nat_scope.
+Notation "n .-2" := n.-1.-1 (at level 2, left associativity,
+ format "n .-2") : nat_scope.
+
+Fixpoint eqn m n {struct m} :=
+ match m, n with
+ | 0, 0 => true
+ | m'.+1, n'.+1 => eqn m' n'
+ | _, _ => false
+ end.
+
+Lemma eqnP : Equality.axiom eqn.
+Proof.
+move=> n m; apply: (iffP idP) => [|<-]; last by elim n.
+by elim: n m => [|n IHn] [|m] //= /IHn->.
+Qed.
+
+Canonical nat_eqMixin := EqMixin eqnP.
+Canonical nat_eqType := Eval hnf in EqType nat nat_eqMixin.
+
+Arguments eqnP [x y].
+Prenex Implicits eqnP.
+
+Coercion nat_of_bool (b : bool) := if b then 1 else 0.
+
+Fixpoint odd n := if n is n'.+1 then ~~ odd n' else false.
+
+Lemma oddb (b : bool) : odd b = b. Proof. by case: b. Qed.
+
+Definition subn_rec := minus.
+Notation "m - n" := (subn_rec m n) : nat_rec_scope.
+
+Definition subn := nosimpl subn_rec.
+Notation "m - n" := (subn m n) : nat_scope.
+
+Definition leq m n := m - n == 0.
+
+Notation "m <= n" := (leq m n) : nat_scope.
+Notation "m < n" := (m.+1 <= n) : nat_scope.
+Notation "m >= n" := (n <= m) (only parsing) : nat_scope.
+Notation "m > n" := (n < m) (only parsing) : nat_scope.
+
+
+Notation "m <= n <= p" := ((m <= n) && (n <= p)) : nat_scope.
+Notation "m < n <= p" := ((m < n) && (n <= p)) : nat_scope.
+Notation "m <= n < p" := ((m <= n) && (n < p)) : nat_scope.
+Notation "m < n < p" := ((m < n) && (n < p)) : nat_scope.
+
+Open Scope nat_scope.
+
+
+Lemma ltnS m n : (m < n.+1) = (m <= n). Proof. by []. Qed.
+Lemma leq0n n : 0 <= n. Proof. by []. Qed.
+Lemma ltn0Sn n : 0 < n.+1. Proof. by []. Qed.
+Lemma ltn0 n : n < 0 = false. Proof. by []. Qed.
+Lemma leqnn n : n <= n. Proof. by elim: n. Qed.
+Hint Resolve leqnn.
+Lemma leqnSn n : n <= n.+1. Proof. by elim: n. Qed.
+
+Lemma leq_trans n m p : m <= n -> n <= p -> m <= p.
+Admitted.
+Lemma leqW m n : m <= n -> m <= n.+1.
+Admitted.
+Hint Resolve leqnSn.
+Lemma ltnW m n : m < n -> m <= n.
+Proof. exact: leq_trans. Qed.
+Hint Resolve ltnW.
+
+Definition addn_rec := plus.
+Notation "m + n" := (addn_rec m n) : nat_rec_scope.
+
+Definition addn := nosimpl addn_rec.
+Notation "m + n" := (addn m n) : nat_scope.
+
+Lemma addn0 : right_id 0 addn. Proof. by move=> n; apply/eqP; elim: n. Qed.
+Lemma add0n : left_id 0 addn. Proof. by []. Qed.
+Lemma addSn m n : m.+1 + n = (m + n).+1. Proof. by []. Qed.
+Lemma addnS m n : m + n.+1 = (m + n).+1. Proof. by elim: m. Qed.
+
+Lemma addnCA : left_commutative addn.
+Proof. by move=> m n p; elim: m => //= m; rewrite addnS => <-. Qed.
+
+Lemma addnC : commutative addn.
+Proof. by move=> m n; rewrite -{1}[n]addn0 addnCA addn0. Qed.
+
+Lemma addnA : associative addn.
+Proof. by move=> m n p; rewrite (addnC n) addnCA addnC. Qed.
+
+Lemma subnK m n : m <= n -> (n - m) + m = n.
+Admitted.
+
+
+Definition muln_rec := mult.
+Notation "m * n" := (muln_rec m n) : nat_rec_scope.
+
+Definition muln := nosimpl muln_rec.
+Notation "m * n" := (muln m n) : nat_scope.
+
+Lemma mul0n : left_zero 0 muln. Proof. by []. Qed.
+Lemma muln0 : right_zero 0 muln. Proof. by elim. Qed.
+Lemma mul1n : left_id 1 muln. Proof. exact: addn0. Qed.
+
+Lemma mulSn m n : m.+1 * n = n + m * n. Proof. by []. Qed.
+Lemma mulSnr m n : m.+1 * n = m * n + n. Proof. exact: addnC. Qed.
+
+Lemma mulnS m n : m * n.+1 = m + m * n.
+Proof. by elim: m => // m; rewrite !mulSn !addSn addnCA => ->. Qed.
+
+Lemma mulnSr m n : m * n.+1 = m * n + m.
+Proof. by rewrite addnC mulnS. Qed.
+
+Lemma muln1 : right_id 1 muln.
+Proof. by move=> n; rewrite mulnSr muln0. Qed.
+
+Lemma mulnC : commutative muln.
+Proof.
+by move=> m n; elim: m => [|m]; rewrite (muln0, mulnS) // mulSn => ->.
+Qed.
+
+Lemma mulnDl : left_distributive muln addn.
+Proof. by move=> m1 m2 n; elim: m1 => //= m1 IHm; rewrite -addnA -IHm. Qed.
+
+Lemma mulnDr : right_distributive muln addn.
+Proof. by move=> m n1 n2; rewrite !(mulnC m) mulnDl. Qed.
+
+Lemma mulnA : associative muln.
+Proof. by move=> m n p; elim: m => //= m; rewrite mulSn mulnDl => ->. Qed.
+
+Lemma mulnCA : left_commutative muln.
+Proof. by move=> m n1 n2; rewrite !mulnA (mulnC m). Qed.
+
+Lemma mulnAC : right_commutative muln.
+Proof. by move=> m n p; rewrite -!mulnA (mulnC n). Qed.
+
+Lemma mulnACA : interchange muln muln.
+Proof. by move=> m n p q; rewrite -!mulnA (mulnCA n). Qed.
+
+(* seq ------------------------------------------------------------- *)
+
+Delimit Scope seq_scope with SEQ.
+Open Scope seq_scope.
+
+(* Inductive seq (T : Type) : Type := Nil | Cons of T & seq T. *)
+Notation seq := list.
+Prenex Implicits cons.
+Notation Cons T := (@cons T) (only parsing).
+Notation Nil T := (@nil T) (only parsing).
+
+Bind Scope seq_scope with list.
+Arguments cons _%type _ _%SEQ.
+
+(* As :: and ++ are (improperly) declared in Init.datatypes, we only rebind *)
+(* them here. *)
+Infix "::" := cons : seq_scope.
+
+(* GG - this triggers a camlp4 warning, as if this Notation had been Reserved *)
+Notation "[ :: ]" := nil (at level 0, format "[ :: ]") : seq_scope.
+
+Notation "[ :: x1 ]" := (x1 :: [::])
+ (at level 0, format "[ :: x1 ]") : seq_scope.
+
+Notation "[ :: x & s ]" := (x :: s) (at level 0, only parsing) : seq_scope.
+
+Notation "[ :: x1 , x2 , .. , xn & s ]" := (x1 :: x2 :: .. (xn :: s) ..)
+ (at level 0, format
+ "'[hv' [ :: '[' x1 , '/' x2 , '/' .. , '/' xn ']' '/ ' & s ] ']'"
+ ) : seq_scope.
+
+Notation "[ :: x1 ; x2 ; .. ; xn ]" := (x1 :: x2 :: .. [:: xn] ..)
+ (at level 0, format "[ :: '[' x1 ; '/' x2 ; '/' .. ; '/' xn ']' ]"
+ ) : seq_scope.
+
+Section Sequences.
+
+Variable n0 : nat. (* numerical parameter for take, drop et al *)
+Variable T : Type. (* must come before the implicit Type *)
+Variable x0 : T. (* default for head/nth *)
+
+Implicit Types x y z : T.
+Implicit Types m n : nat.
+Implicit Type s : seq T.
+
+Fixpoint size s := if s is _ :: s' then (size s').+1 else 0.
+
+Fixpoint cat s1 s2 := if s1 is x :: s1' then x :: s1' ++ s2 else s2
+where "s1 ++ s2" := (cat s1 s2) : seq_scope.
+
+Lemma cat0s s : [::] ++ s = s. Proof. by []. Qed.
+
+Lemma cats0 s : s ++ [::] = s.
+Proof. by elim: s => //= x s ->. Qed.
+
+Lemma catA s1 s2 s3 : s1 ++ s2 ++ s3 = (s1 ++ s2) ++ s3.
+Proof. by elim: s1 => //= x s1 ->. Qed.
+
+Fixpoint nth s n {struct n} :=
+ if s is x :: s' then if n is n'.+1 then @nth s' n' else x else x0.
+
+Fixpoint rcons s z := if s is x :: s' then x :: rcons s' z else [:: z].
+
+CoInductive last_spec : seq T -> Type :=
+ | LastNil : last_spec [::]
+ | LastRcons s x : last_spec (rcons s x).
+
+Lemma lastP s : last_spec s.
+Proof using. Admitted.
+
+Lemma last_ind P :
+ P [::] -> (forall s x, P s -> P (rcons s x)) -> forall s, P s.
+Proof using. Admitted.
+
+
+Section Map.
+
+Variables (T2 : Type) (f : T -> T2).
+
+Fixpoint map s := if s is x :: s' then f x :: map s' else [::].
+
+End Map.
+
+Section SeqFind.
+
+Variable a : pred T.
+
+Fixpoint count s := if s is x :: s' then a x + count s' else 0.
+
+Fixpoint filter s :=
+ if s is x :: s' then if a x then x :: filter s' else filter s' else [::].
+
+End SeqFind.
+
+End Sequences.
+
+Infix "++" := cat : seq_scope.
+
+Notation count_mem x := (count (pred_of_simpl (pred1 x))).
+
+Section EqSeq.
+
+Variables (n0 : nat) (T : eqType) (x0 : T).
+Local Notation nth := (nth x0).
+Implicit Type s : seq T.
+Implicit Types x y z : T.
+
+Fixpoint eqseq s1 s2 {struct s2} :=
+ match s1, s2 with
+ | [::], [::] => true
+ | x1 :: s1', x2 :: s2' => (x1 == x2) && eqseq s1' s2'
+ | _, _ => false
+ end.
+
+Lemma eqseqP : Equality.axiom eqseq.
+Proof.
+move; elim=> [|x1 s1 IHs] [|x2 s2]; do [by constructor | simpl].
+case: (x1 =P x2) => [<-|neqx]; last by right; case.
+by apply: (iffP (IHs s2)) => [<-|[]].
+Qed.
+
+Canonical seq_eqMixin := EqMixin eqseqP.
+Canonical seq_eqType := Eval hnf in EqType (seq T) seq_eqMixin.
+
+Fixpoint mem_seq (s : seq T) :=
+ if s is y :: s' then xpredU1 y (mem_seq s') else xpred0.
+
+Definition eqseq_class := seq T.
+Identity Coercion seq_of_eqseq : eqseq_class >-> seq.
+Coercion pred_of_eq_seq (s : eqseq_class) : pred_class := [eta mem_seq s].
+
+Canonical seq_predType := @mkPredType T (seq T) pred_of_eq_seq.
+
+Fixpoint uniq s := if s is x :: s' then (x \notin s') && uniq s' else true.
+
+End EqSeq.
+
+Definition bitseq := seq bool.
+Canonical bitseq_eqType := Eval hnf in [eqType of bitseq].
+Canonical bitseq_predType := Eval hnf in [predType of bitseq].
+
+Section Pmap.
+
+Variables (aT rT : Type) (f : aT -> option rT) (g : rT -> aT).
+
+Fixpoint pmap s :=
+ if s is x :: s' then let r := pmap s' in oapp (cons^~ r) r (f x) else [::].
+
+End Pmap.
+
+Fixpoint iota m n := if n is n'.+1 then m :: iota m.+1 n' else [::].
+
+Section FoldRight.
+
+Variables (T : Type) (R : Type) (f : T -> R -> R) (z0 : R).
+
+Fixpoint foldr s := if s is x :: s' then f x (foldr s') else z0.
+
+End FoldRight.
+
+Lemma mem_iota m n i : (i \in iota m n) = (m <= i) && (i < m + n).
+Admitted.
+
+
+(* choice ------------------------------------------------------------- *)
+
+Module Choice.
+
+Section ClassDef.
+
+Record mixin_of T := Mixin {
+ find : pred T -> nat -> option T;
+ _ : forall P n x, find P n = Some x -> P x;
+ _ : forall P : pred T, (exists x, P x) -> exists n, find P n;
+ _ : forall P Q : pred T, P =1 Q -> find P =1 find Q
+}.
+
+Record class_of T := Class {base : Equality.class_of T; mixin : mixin_of T}.
+Local Coercion base : class_of >-> Equality.class_of.
+
+Structure type := Pack {sort; _ : class_of sort; _ : Type}.
+Local Coercion sort : type >-> Sortclass.
+Variables (T : Type) (cT : type).
+Definition class := let: Pack _ c _ as cT' := cT return class_of cT' in c.
+Definition clone c of phant_id class c := @Pack T c T.
+Let xT := let: Pack T _ _ := cT in T.
+Notation xclass := (class : class_of xT).
+
+Definition pack m :=
+ fun b bT & phant_id (Equality.class bT) b => Pack (@Class T b m) T.
+
+(* Inheritance *)
+Definition eqType := @Equality.Pack cT xclass xT.
+
+End ClassDef.
+
+Module Import Exports.
+Coercion base : class_of >-> Equality.class_of.
+Coercion sort : type >-> Sortclass.
+Coercion eqType : type >-> Equality.type.
+Canonical eqType.
+Notation choiceType := type.
+Notation choiceMixin := mixin_of.
+Notation ChoiceType T m := (@pack T m _ _ id).
+Notation "[ 'choiceType' 'of' T 'for' cT ]" := (@clone T cT _ idfun)
+ (at level 0, format "[ 'choiceType' 'of' T 'for' cT ]") : form_scope.
+Notation "[ 'choiceType' 'of' T ]" := (@clone T _ _ id)
+ (at level 0, format "[ 'choiceType' 'of' T ]") : form_scope.
+
+End Exports.
+
+End Choice.
+Export Choice.Exports.
+
+Section ChoiceTheory.
+
+Variable T : choiceType.
+
+Section CanChoice.
+
+Variables (sT : Type) (f : sT -> T).
+
+Lemma PcanChoiceMixin f' : pcancel f f' -> choiceMixin sT.
+Admitted.
+
+Definition CanChoiceMixin f' (fK : cancel f f') :=
+ PcanChoiceMixin (can_pcan fK).
+
+End CanChoice.
+
+Section SubChoice.
+
+Variables (P : pred T) (sT : subType P).
+
+Definition sub_choiceMixin := PcanChoiceMixin (@valK T P sT).
+Definition sub_choiceClass := @Choice.Class sT (sub_eqMixin sT) sub_choiceMixin.
+Canonical sub_choiceType := Choice.Pack sub_choiceClass sT.
+
+End SubChoice.
+
+
+Fact seq_choiceMixin : choiceMixin (seq T).
+Admitted.
+Canonical seq_choiceType := Eval hnf in ChoiceType (seq T) seq_choiceMixin.
+End ChoiceTheory.
+
+Fact nat_choiceMixin : choiceMixin nat.
+Proof.
+pose f := [fun (P : pred nat) n => if P n then Some n else None].
+exists f => [P n m | P [n Pn] | P Q eqPQ n] /=; last by rewrite eqPQ.
+ by case: ifP => // Pn [<-].
+by exists n; rewrite Pn.
+Qed.
+Canonical nat_choiceType := Eval hnf in ChoiceType nat nat_choiceMixin.
+
+Definition bool_choiceMixin := CanChoiceMixin oddb.
+Canonical bool_choiceType := Eval hnf in ChoiceType bool bool_choiceMixin.
+Canonical bitseq_choiceType := Eval hnf in [choiceType of bitseq].
+
+
+Notation "[ 'choiceMixin' 'of' T 'by' <: ]" :=
+ (sub_choiceMixin _ : choiceMixin T)
+ (at level 0, format "[ 'choiceMixin' 'of' T 'by' <: ]") : form_scope.
+
+
+
+
+Module Countable.
+
+Record mixin_of (T : Type) : Type := Mixin {
+ pickle : T -> nat;
+ unpickle : nat -> option T;
+ pickleK : pcancel pickle unpickle
+}.
+
+Definition EqMixin T m := PcanEqMixin (@pickleK T m).
+Definition ChoiceMixin T m := PcanChoiceMixin (@pickleK T m).
+
+Section ClassDef.
+
+Record class_of T := Class { base : Choice.class_of T; mixin : mixin_of T }.
+Local Coercion base : class_of >-> Choice.class_of.
+
+Structure type : Type := Pack {sort : Type; _ : class_of sort; _ : Type}.
+Local Coercion sort : type >-> Sortclass.
+Variables (T : Type) (cT : type).
+Definition class := let: Pack _ c _ as cT' := cT return class_of cT' in c.
+Definition clone c of phant_id class c := @Pack T c T.
+Let xT := let: Pack T _ _ := cT in T.
+Notation xclass := (class : class_of xT).
+
+Definition pack m :=
+ fun bT b & phant_id (Choice.class bT) b => Pack (@Class T b m) T.
+
+Definition eqType := @Equality.Pack cT xclass xT.
+Definition choiceType := @Choice.Pack cT xclass xT.
+
+End ClassDef.
+
+Module Exports.
+Coercion base : class_of >-> Choice.class_of.
+Coercion mixin : class_of >-> mixin_of.
+Coercion sort : type >-> Sortclass.
+Coercion eqType : type >-> Equality.type.
+Canonical eqType.
+Coercion choiceType : type >-> Choice.type.
+Canonical choiceType.
+Notation countType := type.
+Notation CountType T m := (@pack T m _ _ id).
+Notation CountMixin := Mixin.
+Notation CountChoiceMixin := ChoiceMixin.
+Notation "[ 'countType' 'of' T 'for' cT ]" := (@clone T cT _ idfun)
+ (at level 0, format "[ 'countType' 'of' T 'for' cT ]") : form_scope.
+Notation "[ 'countType' 'of' T ]" := (@clone T _ _ id)
+ (at level 0, format "[ 'countType' 'of' T ]") : form_scope.
+
+End Exports.
+
+End Countable.
+Export Countable.Exports.
+
+Definition unpickle T := Countable.unpickle (Countable.class T).
+Definition pickle T := Countable.pickle (Countable.class T).
+Arguments unpickle [T].
+Prenex Implicits pickle unpickle.
+
+Section CountableTheory.
+
+Variable T : countType.
+
+Lemma pickleK : @pcancel nat T pickle unpickle.
+Proof. exact: Countable.pickleK. Qed.
+
+Definition pickle_inv n :=
+ obind (fun x : T => if pickle x == n then Some x else None) (unpickle n).
+
+Lemma pickle_invK : ocancel pickle_inv pickle.
+Proof.
+by rewrite /pickle_inv => n; case def_x: (unpickle n) => //= [x]; case: eqP.
+Qed.
+
+Lemma pickleK_inv : pcancel pickle pickle_inv.
+Proof. by rewrite /pickle_inv => x; rewrite pickleK /= eqxx. Qed.
+
+Lemma pcan_pickleK sT f f' :
+ @pcancel T sT f f' -> pcancel (pickle \o f) (pcomp f' unpickle).
+Proof. by move=> fK x; rewrite /pcomp pickleK /= fK. Qed.
+
+Definition PcanCountMixin sT f f' (fK : pcancel f f') :=
+ @CountMixin sT _ _ (pcan_pickleK fK).
+
+Definition CanCountMixin sT f f' (fK : cancel f f') :=
+ @PcanCountMixin sT _ _ (can_pcan fK).
+
+Definition sub_countMixin P sT := PcanCountMixin (@valK T P sT).
+
+End CountableTheory.
+Notation "[ 'countMixin' 'of' T 'by' <: ]" :=
+ (sub_countMixin _ : Countable.mixin_of T)
+ (at level 0, format "[ 'countMixin' 'of' T 'by' <: ]") : form_scope.
+
+Section SubCountType.
+
+Variables (T : choiceType) (P : pred T).
+Import Countable.
+
+Structure subCountType : Type :=
+ SubCountType {subCount_sort :> subType P; _ : mixin_of subCount_sort}.
+
+Coercion sub_countType (sT : subCountType) :=
+ Eval hnf in pack (let: SubCountType _ m := sT return mixin_of sT in m) id.
+Canonical sub_countType.
+
+Definition pack_subCountType U :=
+ fun sT cT & sub_sort sT * sort cT -> U * U =>
+ fun b m & phant_id (Class b m) (class cT) => @SubCountType sT m.
+
+End SubCountType.
+
+(* This assumes that T has both countType and subType structures. *)
+Notation "[ 'subCountType' 'of' T ]" :=
+ (@pack_subCountType _ _ T _ _ id _ _ id)
+ (at level 0, format "[ 'subCountType' 'of' T ]") : form_scope.
+
+Lemma nat_pickleK : pcancel id (@Some nat). Proof. by []. Qed.
+Definition nat_countMixin := CountMixin nat_pickleK.
+Canonical nat_countType := Eval hnf in CountType nat nat_countMixin.
+
+(* fintype --------------------------------------------------------- *)
+
+Module Finite.
+
+Section RawMixin.
+
+Variable T : eqType.
+
+Definition axiom e := forall x : T, count_mem x e = 1.
+
+Lemma uniq_enumP e : uniq e -> e =i T -> axiom e.
+Admitted.
+
+Record mixin_of := Mixin {
+ mixin_base : Countable.mixin_of T;
+ mixin_enum : seq T;
+ _ : axiom mixin_enum
+}.
+
+End RawMixin.
+
+Section Mixins.
+
+Variable T : countType.
+
+Definition EnumMixin :=
+ let: Countable.Pack _ (Countable.Class _ m) _ as cT := T
+ return forall e : seq cT, axiom e -> mixin_of cT in
+ @Mixin (EqType _ _) m.
+
+Definition UniqMixin e Ue eT := @EnumMixin e (uniq_enumP Ue eT).
+
+Variable n : nat.
+
+End Mixins.
+
+Section ClassDef.
+
+Record class_of T := Class {
+ base : Choice.class_of T;
+ mixin : mixin_of (Equality.Pack base T)
+}.
+Definition base2 T c := Countable.Class (@base T c) (mixin_base (mixin c)).
+Local Coercion base : class_of >-> Choice.class_of.
+
+Structure type : Type := Pack {sort; _ : class_of sort; _ : Type}.
+Local Coercion sort : type >-> Sortclass.
+Variables (T : Type) (cT : type).
+Definition class := let: Pack _ c _ as cT' := cT return class_of cT' in c.
+Definition clone c of phant_id class c := @Pack T c T.
+Let xT := let: Pack T _ _ := cT in T.
+Notation xclass := (class : class_of xT).
+
+Definition pack b0 (m0 : mixin_of (EqType T b0)) :=
+ fun bT b & phant_id (Choice.class bT) b =>
+ fun m & phant_id m0 m => Pack (@Class T b m) T.
+
+Definition eqType := @Equality.Pack cT xclass xT.
+Definition choiceType := @Choice.Pack cT xclass xT.
+Definition countType := @Countable.Pack cT (base2 xclass) xT.
+
+End ClassDef.
+
+Module Import Exports.
+Coercion mixin_base : mixin_of >-> Countable.mixin_of.
+Coercion base : class_of >-> Choice.class_of.
+Coercion mixin : class_of >-> mixin_of.
+Coercion base2 : class_of >-> Countable.class_of.
+Coercion sort : type >-> Sortclass.
+Coercion eqType : type >-> Equality.type.
+Canonical eqType.
+Coercion choiceType : type >-> Choice.type.
+Canonical choiceType.
+Coercion countType : type >-> Countable.type.
+Canonical countType.
+Notation finType := type.
+Notation FinType T m := (@pack T _ m _ _ id _ id).
+Notation FinMixin := EnumMixin.
+Notation UniqFinMixin := UniqMixin.
+Notation "[ 'finType' 'of' T 'for' cT ]" := (@clone T cT _ idfun)
+ (at level 0, format "[ 'finType' 'of' T 'for' cT ]") : form_scope.
+Notation "[ 'finType' 'of' T ]" := (@clone T _ _ id)
+ (at level 0, format "[ 'finType' 'of' T ]") : form_scope.
+End Exports.
+
+Module Type EnumSig.
+Parameter enum : forall cT : type, seq cT.
+Axiom enumDef : enum = fun cT => mixin_enum (class cT).
+End EnumSig.
+
+Module EnumDef : EnumSig.
+Definition enum cT := mixin_enum (class cT).
+Definition enumDef := erefl enum.
+End EnumDef.
+
+Notation enum := EnumDef.enum.
+
+End Finite.
+Export Finite.Exports.
+
+Section SubFinType.
+
+Variables (T : choiceType) (P : pred T).
+Import Finite.
+
+Structure subFinType := SubFinType {
+ subFin_sort :> subType P;
+ _ : mixin_of (sub_eqType subFin_sort)
+}.
+
+Definition pack_subFinType U :=
+ fun cT b m & phant_id (class cT) (@Class U b m) =>
+ fun sT m' & phant_id m' m => @SubFinType sT m'.
+
+Implicit Type sT : subFinType.
+
+Definition subFin_mixin sT :=
+ let: SubFinType _ m := sT return mixin_of (sub_eqType sT) in m.
+
+Coercion subFinType_subCountType sT := @SubCountType _ _ sT (subFin_mixin sT).
+Canonical subFinType_subCountType.
+
+Coercion subFinType_finType sT :=
+ Pack (@Class sT (sub_choiceClass sT) (subFin_mixin sT)) sT.
+Canonical subFinType_finType.
+
+Definition enum_mem T (mA : mem_pred _) := filter mA (Finite.enum T).
+Definition image_mem T T' f mA : seq T' := map f (@enum_mem T mA).
+Definition codom T T' f := @image_mem T T' f (mem T).
+
+Lemma codom_val sT x : (x \in codom (val : sT -> T)) = P x.
+Admitted.
+
+End SubFinType.
+
+
+(* This assumes that T has both finType and subCountType structures. *)
+Notation "[ 'subFinType' 'of' T ]" := (@pack_subFinType _ _ T _ _ _ id _ _ id)
+ (at level 0, format "[ 'subFinType' 'of' T ]") : form_scope.
+
+
+
+Section OrdinalSub.
+
+Variable n : nat.
+
+Inductive ordinal : predArgType := Ordinal m of m < n.
+
+Coercion nat_of_ord i := let: Ordinal m _ := i in m.
+
+Canonical ordinal_subType := [subType for nat_of_ord].
+Definition ordinal_eqMixin := Eval hnf in [eqMixin of ordinal by <:].
+Canonical ordinal_eqType := Eval hnf in EqType ordinal ordinal_eqMixin.
+Definition ordinal_choiceMixin := [choiceMixin of ordinal by <:].
+Canonical ordinal_choiceType :=
+ Eval hnf in ChoiceType ordinal ordinal_choiceMixin.
+Definition ordinal_countMixin := [countMixin of ordinal by <:].
+Canonical ordinal_countType := Eval hnf in CountType ordinal ordinal_countMixin.
+Canonical ordinal_subCountType := [subCountType of ordinal].
+
+Lemma ltn_ord (i : ordinal) : i < n. Proof. exact: valP i. Qed.
+
+Lemma ord_inj : injective nat_of_ord. Proof. exact: val_inj. Qed.
+
+Definition ord_enum : seq ordinal := pmap insub (iota 0 n).
+
+Lemma val_ord_enum : map val ord_enum = iota 0 n.
+Admitted.
+
+Lemma ord_enum_uniq : uniq ord_enum.
+Admitted.
+
+Lemma mem_ord_enum i : i \in ord_enum.
+Admitted.
+
+Definition ordinal_finMixin :=
+ Eval hnf in UniqFinMixin ord_enum_uniq mem_ord_enum.
+Canonical ordinal_finType := Eval hnf in FinType ordinal ordinal_finMixin.
+Canonical ordinal_subFinType := Eval hnf in [subFinType of ordinal].
+
+End OrdinalSub.
+
+Notation "''I_' n" := (ordinal n)
+ (at level 8, n at level 2, format "''I_' n").
+
+(* bigop ----------------------------------------------------------------- *)
+
+Reserved Notation "\big [ op / idx ]_ i F"
+ (at level 36, F at level 36, op, idx at level 10, i at level 0,
+ right associativity,
+ format "'[' \big [ op / idx ]_ i '/ ' F ']'").
+Reserved Notation "\big [ op / idx ]_ ( i <- r | P ) F"
+ (at level 36, F at level 36, op, idx at level 10, i, r at level 50,
+ format "'[' \big [ op / idx ]_ ( i <- r | P ) '/ ' F ']'").
+Reserved Notation "\big [ op / idx ]_ ( i <- r ) F"
+ (at level 36, F at level 36, op, idx at level 10, i, r at level 50,
+ format "'[' \big [ op / idx ]_ ( i <- r ) '/ ' F ']'").
+Reserved Notation "\big [ op / idx ]_ ( m <= i < n | P ) F"
+ (at level 36, F at level 36, op, idx at level 10, m, i, n at level 50,
+ format "'[' \big [ op / idx ]_ ( m <= i < n | P ) F ']'").
+Reserved Notation "\big [ op / idx ]_ ( m <= i < n ) F"
+ (at level 36, F at level 36, op, idx at level 10, i, m, n at level 50,
+ format "'[' \big [ op / idx ]_ ( m <= i < n ) '/ ' F ']'").
+Reserved Notation "\big [ op / idx ]_ ( i | P ) F"
+ (at level 36, F at level 36, op, idx at level 10, i at level 50,
+ format "'[' \big [ op / idx ]_ ( i | P ) '/ ' F ']'").
+Reserved Notation "\big [ op / idx ]_ ( i : t | P ) F"
+ (at level 36, F at level 36, op, idx at level 10, i at level 50,
+ format "'[' \big [ op / idx ]_ ( i : t | P ) '/ ' F ']'").
+Reserved Notation "\big [ op / idx ]_ ( i : t ) F"
+ (at level 36, F at level 36, op, idx at level 10, i at level 50,
+ format "'[' \big [ op / idx ]_ ( i : t ) '/ ' F ']'").
+Reserved Notation "\big [ op / idx ]_ ( i < n | P ) F"
+ (at level 36, F at level 36, op, idx at level 10, i, n at level 50,
+ format "'[' \big [ op / idx ]_ ( i < n | P ) '/ ' F ']'").
+Reserved Notation "\big [ op / idx ]_ ( i < n ) F"
+ (at level 36, F at level 36, op, idx at level 10, i, n at level 50,
+ format "'[' \big [ op / idx ]_ ( i < n ) F ']'").
+Reserved Notation "\big [ op / idx ]_ ( i 'in' A | P ) F"
+ (at level 36, F at level 36, op, idx at level 10, i, A at level 50,
+ format "'[' \big [ op / idx ]_ ( i 'in' A | P ) '/ ' F ']'").
+Reserved Notation "\big [ op / idx ]_ ( i 'in' A ) F"
+ (at level 36, F at level 36, op, idx at level 10, i, A at level 50,
+ format "'[' \big [ op / idx ]_ ( i 'in' A ) '/ ' F ']'").
+
+Module Monoid.
+
+Section Definitions.
+Variables (T : Type) (idm : T).
+
+Structure law := Law {
+ operator : T -> T -> T;
+ _ : associative operator;
+ _ : left_id idm operator;
+ _ : right_id idm operator
+}.
+Local Coercion operator : law >-> Funclass.
+
+Structure com_law := ComLaw {
+ com_operator : law;
+ _ : commutative com_operator
+}.
+Local Coercion com_operator : com_law >-> law.
+
+Structure mul_law := MulLaw {
+ mul_operator : T -> T -> T;
+ _ : left_zero idm mul_operator;
+ _ : right_zero idm mul_operator
+}.
+Local Coercion mul_operator : mul_law >-> Funclass.
+
+Structure add_law (mul : T -> T -> T) := AddLaw {
+ add_operator : com_law;
+ _ : left_distributive mul add_operator;
+ _ : right_distributive mul add_operator
+}.
+Local Coercion add_operator : add_law >-> com_law.
+
+Let op_id (op1 op2 : T -> T -> T) := phant_id op1 op2.
+
+Definition clone_law op :=
+ fun (opL : law) & op_id opL op =>
+ fun opmA op1m opm1 (opL' := @Law op opmA op1m opm1)
+ & phant_id opL' opL => opL'.
+
+Definition clone_com_law op :=
+ fun (opL : law) (opC : com_law) & op_id opL op & op_id opC op =>
+ fun opmC (opC' := @ComLaw opL opmC) & phant_id opC' opC => opC'.
+
+Definition clone_mul_law op :=
+ fun (opM : mul_law) & op_id opM op =>
+ fun op0m opm0 (opM' := @MulLaw op op0m opm0) & phant_id opM' opM => opM'.
+
+Definition clone_add_law mop aop :=
+ fun (opC : com_law) (opA : add_law mop) & op_id opC aop & op_id opA aop =>
+ fun mopDm mopmD (opA' := @AddLaw mop opC mopDm mopmD)
+ & phant_id opA' opA => opA'.
+
+End Definitions.
+
+Module Import Exports.
+Coercion operator : law >-> Funclass.
+Coercion com_operator : com_law >-> law.
+Coercion mul_operator : mul_law >-> Funclass.
+Coercion add_operator : add_law >-> com_law.
+Notation "[ 'law' 'of' f ]" := (@clone_law _ _ f _ id _ _ _ id)
+ (at level 0, format"[ 'law' 'of' f ]") : form_scope.
+Notation "[ 'com_law' 'of' f ]" := (@clone_com_law _ _ f _ _ id id _ id)
+ (at level 0, format "[ 'com_law' 'of' f ]") : form_scope.
+Notation "[ 'mul_law' 'of' f ]" := (@clone_mul_law _ _ f _ id _ _ id)
+ (at level 0, format"[ 'mul_law' 'of' f ]") : form_scope.
+Notation "[ 'add_law' m 'of' a ]" := (@clone_add_law _ _ m a _ _ id id _ _ id)
+ (at level 0, format "[ 'add_law' m 'of' a ]") : form_scope.
+End Exports.
+
+Section CommutativeAxioms.
+
+Variable (T : Type) (zero one : T) (mul add : T -> T -> T) (inv : T -> T).
+Hypothesis mulC : commutative mul.
+
+Lemma mulC_id : left_id one mul -> right_id one mul.
+Proof. by move=> mul1x x; rewrite mulC. Qed.
+
+Lemma mulC_zero : left_zero zero mul -> right_zero zero mul.
+Proof. by move=> mul0x x; rewrite mulC. Qed.
+
+Lemma mulC_dist : left_distributive mul add -> right_distributive mul add.
+Proof. by move=> mul_addl x y z; rewrite !(mulC x). Qed.
+
+End CommutativeAxioms.
+Module Theory.
+
+Section Theory.
+Variables (T : Type) (idm : T).
+
+Section Plain.
+Variable mul : law idm.
+Lemma mul1m : left_id idm mul. Proof. by case mul. Qed.
+Lemma mulm1 : right_id idm mul. Proof. by case mul. Qed.
+Lemma mulmA : associative mul. Proof. by case mul. Qed.
+(*Lemma iteropE n x : iterop n mul x idm = iter n (mul x) idm.*)
+
+End Plain.
+
+Section Commutative.
+Variable mul : com_law idm.
+Lemma mulmC : commutative mul. Proof. by case mul. Qed.
+Lemma mulmCA : left_commutative mul.
+Proof. by move=> x y z; rewrite !mulmA (mulmC x). Qed.
+Lemma mulmAC : right_commutative mul.
+Proof. by move=> x y z; rewrite -!mulmA (mulmC y). Qed.
+Lemma mulmACA : interchange mul mul.
+Proof. by move=> x y z t; rewrite -!mulmA (mulmCA y). Qed.
+End Commutative.
+
+Section Mul.
+Variable mul : mul_law idm.
+Lemma mul0m : left_zero idm mul. Proof. by case mul. Qed.
+Lemma mulm0 : right_zero idm mul. Proof. by case mul. Qed.
+End Mul.
+
+Section Add.
+Variables (mul : T -> T -> T) (add : add_law idm mul).
+Lemma addmA : associative add. Proof. exact: mulmA. Qed.
+Lemma addmC : commutative add. Proof. exact: mulmC. Qed.
+Lemma addmCA : left_commutative add. Proof. exact: mulmCA. Qed.
+Lemma addmAC : right_commutative add. Proof. exact: mulmAC. Qed.
+Lemma add0m : left_id idm add. Proof. exact: mul1m. Qed.
+Lemma addm0 : right_id idm add. Proof. exact: mulm1. Qed.
+Lemma mulm_addl : left_distributive mul add. Proof. by case add. Qed.
+Lemma mulm_addr : right_distributive mul add. Proof. by case add. Qed.
+End Add.
+
+Definition simpm := (mulm1, mulm0, mul1m, mul0m, mulmA).
+
+End Theory.
+
+End Theory.
+Include Theory.
+
+End Monoid.
+Export Monoid.Exports.
+
+Section PervasiveMonoids.
+
+Import Monoid.
+
+Canonical andb_monoid := Law andbA andTb andbT.
+Canonical andb_comoid := ComLaw andbC.
+
+Canonical andb_muloid := MulLaw andFb andbF.
+Canonical orb_monoid := Law orbA orFb orbF.
+Canonical orb_comoid := ComLaw orbC.
+Canonical orb_muloid := MulLaw orTb orbT.
+Canonical addb_monoid := Law addbA addFb addbF.
+Canonical addb_comoid := ComLaw addbC.
+Canonical orb_addoid := AddLaw andb_orl andb_orr.
+Canonical andb_addoid := AddLaw orb_andl orb_andr.
+Canonical addb_addoid := AddLaw andb_addl andb_addr.
+
+Canonical addn_monoid := Law addnA add0n addn0.
+Canonical addn_comoid := ComLaw addnC.
+Canonical muln_monoid := Law mulnA mul1n muln1.
+Canonical muln_comoid := ComLaw mulnC.
+Canonical muln_muloid := MulLaw mul0n muln0.
+Canonical addn_addoid := AddLaw mulnDl mulnDr.
+
+Canonical cat_monoid T := Law (@catA T) (@cat0s T) (@cats0 T).
+
+End PervasiveMonoids.
+Delimit Scope big_scope with BIG.
+Open Scope big_scope.
+
+(* The bigbody wrapper is a workaround for a quirk of the Coq pretty-printer, *)
+(* which would fail to redisplay the \big notation when the <general_term> or *)
+(* <condition> do not depend on the bound index. The BigBody constructor *)
+(* packages both in in a term in which i occurs; it also depends on the *)
+(* iterated <op>, as this can give more information on the expected type of *)
+(* the <general_term>, thus allowing for the insertion of coercions. *)
+CoInductive bigbody R I := BigBody of I & (R -> R -> R) & bool & R.
+
+Definition applybig {R I} (body : bigbody R I) x :=
+ let: BigBody _ op b v := body in if b then op v x else x.
+
+Definition reducebig R I idx r (body : I -> bigbody R I) :=
+ foldr (applybig \o body) idx r.
+
+Module Type BigOpSig.
+Parameter bigop : forall R I, R -> seq I -> (I -> bigbody R I) -> R.
+Axiom bigopE : bigop = reducebig.
+End BigOpSig.
+
+Module BigOp : BigOpSig.
+Definition bigop := reducebig.
+Lemma bigopE : bigop = reducebig. Proof. by []. Qed.
+End BigOp.
+
+Notation bigop := BigOp.bigop (only parsing).
+Canonical bigop_unlock := Unlockable BigOp.bigopE.
+
+Definition index_iota m n := iota m (n - m).
+
+Definition index_enum (T : finType) := Finite.enum T.
+
+Lemma mem_index_iota m n i : i \in index_iota m n = (m <= i < n).
+Admitted.
+
+Lemma mem_index_enum T i : i \in index_enum T.
+Admitted.
+
+Hint Resolve mem_index_enum.
+
+(*
+Lemma filter_index_enum T P : filter P (index_enum T) = enum P.
+Proof. by []. Qed.
+*)
+
+Notation "\big [ op / idx ]_ ( i <- r | P ) F" :=
+ (bigop idx r (fun i => BigBody i op P%B F)) : big_scope.
+Notation "\big [ op / idx ]_ ( i <- r ) F" :=
+ (bigop idx r (fun i => BigBody i op true F)) : big_scope.
+Notation "\big [ op / idx ]_ ( m <= i < n | P ) F" :=
+ (bigop idx (index_iota m n) (fun i : nat => BigBody i op P%B F))
+ : big_scope.
+Notation "\big [ op / idx ]_ ( m <= i < n ) F" :=
+ (bigop idx (index_iota m n) (fun i : nat => BigBody i op true F))
+ : big_scope.
+Notation "\big [ op / idx ]_ ( i | P ) F" :=
+ (bigop idx (index_enum _) (fun i => BigBody i op P%B F)) : big_scope.
+Notation "\big [ op / idx ]_ i F" :=
+ (bigop idx (index_enum _) (fun i => BigBody i op true F)) : big_scope.
+Notation "\big [ op / idx ]_ ( i : t | P ) F" :=
+ (bigop idx (index_enum _) (fun i : t => BigBody i op P%B F))
+ (only parsing) : big_scope.
+Notation "\big [ op / idx ]_ ( i : t ) F" :=
+ (bigop idx (index_enum _) (fun i : t => BigBody i op true F))
+ (only parsing) : big_scope.
+Notation "\big [ op / idx ]_ ( i < n | P ) F" :=
+ (\big[op/idx]_(i : ordinal n | P%B) F) : big_scope.
+Notation "\big [ op / idx ]_ ( i < n ) F" :=
+ (\big[op/idx]_(i : ordinal n) F) : big_scope.
+Notation "\big [ op / idx ]_ ( i 'in' A | P ) F" :=
+ (\big[op/idx]_(i | (i \in A) && P) F) : big_scope.
+Notation "\big [ op / idx ]_ ( i 'in' A ) F" :=
+ (\big[op/idx]_(i | i \in A) F) : big_scope.
+
+Notation BIG_F := (F in \big[_/_]_(i <- _ | _) F i)%pattern.
+Notation BIG_P := (P in \big[_/_]_(i <- _ | P i) _)%pattern.
+
+(* Induction loading *)
+Lemma big_load R (K K' : R -> Type) idx op I r (P : pred I) F :
+ K (\big[op/idx]_(i <- r | P i) F i) * K' (\big[op/idx]_(i <- r | P i) F i)
+ -> K' (\big[op/idx]_(i <- r | P i) F i).
+Proof. by case. Qed.
+
+Arguments big_load [R] K [K'] idx op [I].
+
+Section Elim3.
+
+Variables (R1 R2 R3 : Type) (K : R1 -> R2 -> R3 -> Type).
+Variables (id1 : R1) (op1 : R1 -> R1 -> R1).
+Variables (id2 : R2) (op2 : R2 -> R2 -> R2).
+Variables (id3 : R3) (op3 : R3 -> R3 -> R3).
+
+Hypothesis Kid : K id1 id2 id3.
+
+Lemma big_rec3 I r (P : pred I) F1 F2 F3
+ (K_F : forall i y1 y2 y3, P i -> K y1 y2 y3 ->
+ K (op1 (F1 i) y1) (op2 (F2 i) y2) (op3 (F3 i) y3)) :
+ K (\big[op1/id1]_(i <- r | P i) F1 i)
+ (\big[op2/id2]_(i <- r | P i) F2 i)
+ (\big[op3/id3]_(i <- r | P i) F3 i).
+Proof. by rewrite unlock; elim: r => //= i r; case: ifP => //; apply: K_F. Qed.
+
+Hypothesis Kop : forall x1 x2 x3 y1 y2 y3,
+ K x1 x2 x3 -> K y1 y2 y3-> K (op1 x1 y1) (op2 x2 y2) (op3 x3 y3).
+Lemma big_ind3 I r (P : pred I) F1 F2 F3
+ (K_F : forall i, P i -> K (F1 i) (F2 i) (F3 i)) :
+ K (\big[op1/id1]_(i <- r | P i) F1 i)
+ (\big[op2/id2]_(i <- r | P i) F2 i)
+ (\big[op3/id3]_(i <- r | P i) F3 i).
+Proof. by apply: big_rec3 => i x1 x2 x3 /K_F; apply: Kop. Qed.
+
+End Elim3.
+
+Arguments big_rec3 [R1 R2 R3] K [id1 op1 id2 op2 id3 op3] _ [I r P F1 F2 F3].
+Arguments big_ind3 [R1 R2 R3] K [id1 op1 id2 op2 id3 op3] _ _ [I r P F1 F2 F3].
+
+Section Elim2.
+
+Variables (R1 R2 : Type) (K : R1 -> R2 -> Type) (f : R2 -> R1).
+Variables (id1 : R1) (op1 : R1 -> R1 -> R1).
+Variables (id2 : R2) (op2 : R2 -> R2 -> R2).
+
+Hypothesis Kid : K id1 id2.
+
+Lemma big_rec2 I r (P : pred I) F1 F2
+ (K_F : forall i y1 y2, P i -> K y1 y2 ->
+ K (op1 (F1 i) y1) (op2 (F2 i) y2)) :
+ K (\big[op1/id1]_(i <- r | P i) F1 i) (\big[op2/id2]_(i <- r | P i) F2 i).
+Proof. by rewrite unlock; elim: r => //= i r; case: ifP => //; apply: K_F. Qed.
+
+Hypothesis Kop : forall x1 x2 y1 y2,
+ K x1 x2 -> K y1 y2 -> K (op1 x1 y1) (op2 x2 y2).
+Lemma big_ind2 I r (P : pred I) F1 F2 (K_F : forall i, P i -> K (F1 i) (F2 i)) :
+ K (\big[op1/id1]_(i <- r | P i) F1 i) (\big[op2/id2]_(i <- r | P i) F2 i).
+Proof. by apply: big_rec2 => i x1 x2 /K_F; apply: Kop. Qed.
+
+Hypotheses (f_op : {morph f : x y / op2 x y >-> op1 x y}) (f_id : f id2 = id1).
+Lemma big_morph I r (P : pred I) F :
+ f (\big[op2/id2]_(i <- r | P i) F i) = \big[op1/id1]_(i <- r | P i) f (F i).
+Proof. by rewrite unlock; elim: r => //= i r <-; rewrite -f_op -fun_if. Qed.
+
+End Elim2.
+
+Arguments big_rec2 [R1 R2] K [id1 op1 id2 op2] _ [I r P F1 F2].
+Arguments big_ind2 [R1 R2] K [id1 op1 id2 op2] _ _ [I r P F1 F2].
+Arguments big_morph [R1 R2] f [id1 op1 id2 op2] _ _ [I].
+
+Section Elim1.
+
+Variables (R : Type) (K : R -> Type) (f : R -> R).
+Variables (idx : R) (op op' : R -> R -> R).
+
+Hypothesis Kid : K idx.
+
+Lemma big_rec I r (P : pred I) F
+ (Kop : forall i x, P i -> K x -> K (op (F i) x)) :
+ K (\big[op/idx]_(i <- r | P i) F i).
+Proof. by rewrite unlock; elim: r => //= i r; case: ifP => //; apply: Kop. Qed.
+
+Hypothesis Kop : forall x y, K x -> K y -> K (op x y).
+Lemma big_ind I r (P : pred I) F (K_F : forall i, P i -> K (F i)) :
+ K (\big[op/idx]_(i <- r | P i) F i).
+Proof. by apply: big_rec => // i x /K_F /Kop; apply. Qed.
+
+Hypothesis Kop' : forall x y, K x -> K y -> op x y = op' x y.
+Lemma eq_big_op I r (P : pred I) F (K_F : forall i, P i -> K (F i)) :
+ \big[op/idx]_(i <- r | P i) F i = \big[op'/idx]_(i <- r | P i) F i.
+Proof.
+by elim/(big_load K): _; elim/big_rec2: _ => // i _ y Pi [Ky <-]; auto.
+Qed.
+
+Hypotheses (fM : {morph f : x y / op x y}) (f_id : f idx = idx).
+Lemma big_endo I r (P : pred I) F :
+ f (\big[op/idx]_(i <- r | P i) F i) = \big[op/idx]_(i <- r | P i) f (F i).
+Proof. exact: big_morph. Qed.
+
+End Elim1.
+
+Arguments big_rec [R] K [idx op] _ [I r P F].
+Arguments big_ind [R] K [idx op] _ _ [I r P F].
+Arguments eq_big_op [R] K [idx op] op' _ _ _ [I].
+Arguments big_endo [R] f [idx op] _ _ [I].
+
+(* zmodp -------------------------------------------------------------------- *)
+
+Lemma ord1 : all_equal_to (@Ordinal 1 0 is_true_true : 'I_1).
+Admitted.
diff --git a/test-suite/prerequisite/ssr_ssrsyntax1.v b/test-suite/prerequisite/ssr_ssrsyntax1.v
new file mode 100644
index 000000000..2b404e2de
--- /dev/null
+++ b/test-suite/prerequisite/ssr_ssrsyntax1.v
@@ -0,0 +1,36 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require ssreflect.
+Require Import Arith.
+
+Goal (forall a b, a + b = b + a).
+intros.
+rewrite plus_comm, plus_comm.
+split.
+Abort.
+
+Module Foo.
+Import ssreflect.
+
+Goal (forall a b, a + b = b + a).
+intros.
+rewrite 2![_ + _]plus_comm.
+split.
+Abort.
+End Foo.
+
+Goal (forall a b, a + b = b + a).
+intros.
+rewrite plus_comm, plus_comm.
+split.
+Abort.
diff --git a/test-suite/save-logs.sh b/test-suite/save-logs.sh
index b61362108..9b8fff09f 100755
--- a/test-suite/save-logs.sh
+++ b/test-suite/save-logs.sh
@@ -9,7 +9,7 @@ mkdir "$SAVEDIR"
# keep this synced with test-suite/Makefile
FAILMARK="==========> FAILURE <=========="
-FAILED=$(mktemp /tmp/coq-check-XXXXX)
+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"
diff --git a/test-suite/ssr/absevarprop.v b/test-suite/ssr/absevarprop.v
new file mode 100644
index 000000000..fa1de0095
--- /dev/null
+++ b/test-suite/ssr/absevarprop.v
@@ -0,0 +1,96 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect ssrbool ssrfun.
+Require Import TestSuite.ssr_mini_mathcomp.
+
+Lemma test15: forall (y : nat) (x : 'I_2), y < 1 -> val x = y -> Some x = insub y.
+move=> y x le_1 defx; rewrite insubT ?(leq_trans le_1) // => ?.
+by congr (Some _); apply: val_inj=> /=; exact: defx.
+Qed.
+
+Axiom P : nat -> Prop.
+Axiom Q : forall n, P n -> Prop.
+Definition R := fun (x : nat) (p : P x) m (q : P (x+1)) => m > 0.
+
+Inductive myEx : Type := ExI : forall n (pn : P n) pn', Q n pn -> R n pn n pn' -> myEx.
+
+Variable P1 : P 1.
+Variable P11 : P (1 + 1).
+Variable Q1 : forall P1, Q 1 P1.
+
+Lemma testmE1 : myEx.
+Proof.
+apply: ExI 1 _ _ _ _.
+ match goal with |- P 1 => exact: P1 | _ => fail end.
+ match goal with |- P (1+1) => exact: P11 | _ => fail end.
+ match goal with |- forall p : P 1, Q 1 p => move=> *; exact: Q1 | _ => fail end.
+match goal with |- forall (p : P 1) (q : P (1+1)), is_true (R 1 p 1 q) => done | _ => fail end.
+Qed.
+
+Lemma testE2 : exists y : { x | P x }, sval y = 1.
+Proof.
+apply: ex_intro (exist _ 1 _) _.
+ match goal with |- P 1 => exact: P1 | _ => fail end.
+match goal with |- forall p : P 1, @sval _ _ (@exist _ _ 1 p) = 1 => done | _ => fail end.
+Qed.
+
+Lemma testE3 : exists y : { x | P x }, sval y = 1.
+Proof.
+have := (ex_intro _ (exist _ 1 _) _); apply.
+ match goal with |- P 1 => exact: P1 | _ => fail end.
+match goal with |- forall p : P 1, @sval _ _ (@exist _ _ 1 p) = 1 => done | _ => fail end.
+Qed.
+
+Lemma testE4 : P 2 -> exists y : { x | P x }, sval y = 2.
+Proof.
+move=> P2; apply: ex_intro (exist _ 2 _) _.
+match goal with |- @sval _ _ (@exist _ _ 2 P2) = 2 => done | _ => fail end.
+Qed.
+
+Hint Resolve P1.
+
+Lemma testmE12 : myEx.
+Proof.
+apply: ExI 1 _ _ _ _.
+ match goal with |- P (1+1) => exact: P11 | _ => fail end.
+ match goal with |- Q 1 P1 => exact: Q1 | _ => fail end.
+match goal with |- forall (q : P (1+1)), is_true (R 1 P1 1 q) => done | _ => fail end.
+Qed.
+
+Create HintDb SSR.
+
+Hint Resolve P11 : SSR.
+
+Ltac ssrautoprop := trivial with SSR.
+
+Lemma testmE13 : myEx.
+Proof.
+apply: ExI 1 _ _ _ _.
+ match goal with |- Q 1 P1 => exact: Q1 | _ => fail end.
+match goal with |- is_true (R 1 P1 1 P11) => done | _ => fail end.
+Qed.
+
+Definition R1 := fun (x : nat) (p : P x) m (q : P (x+1)) (r : Q x p) => m > 0.
+
+Inductive myEx1 : Type :=
+ ExI1 : forall n (pn : P n) pn' (q : Q n pn), R1 n pn n pn' q -> myEx1.
+
+Hint Resolve (Q1 P1) : SSR.
+
+(* tests that goals in prop are solved in the right order, propagating instantiations,
+ thus the goal Q 1 ?p1 is faced by trivial after ?p1, and is thus evar free *)
+Lemma testmE14 : myEx1.
+Proof.
+apply: ExI1 1 _ _ _ _.
+match goal with |- is_true (R1 1 P1 1 P11 (Q1 P1)) => done | _ => fail end.
+Qed.
diff --git a/test-suite/ssr/abstract_var2.v b/test-suite/ssr/abstract_var2.v
new file mode 100644
index 000000000..7c57d2024
--- /dev/null
+++ b/test-suite/ssr/abstract_var2.v
@@ -0,0 +1,25 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+Require Import ssreflect.
+
+Set Implicit Arguments.
+
+Axiom P : nat -> nat -> Prop.
+
+Axiom tr :
+ forall x y z, P x y -> P y z -> P x z.
+
+Lemma test a b c : P a c -> P a b.
+Proof.
+intro H.
+Fail have [: s1 s2] H1 : P a b := @tr _ _ _ s1 s2.
+have [: w s1 s2] H1 : P a b := @tr _ w _ s1 s2.
+Abort.
diff --git a/test-suite/ssr/binders.v b/test-suite/ssr/binders.v
new file mode 100644
index 000000000..97b7d830f
--- /dev/null
+++ b/test-suite/ssr/binders.v
@@ -0,0 +1,55 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrbool TestSuite.ssr_mini_mathcomp.
+
+Lemma test (x : bool) : True.
+have H1 x := x.
+have (x) := x => H2.
+have H3 T (x : T) := x.
+have ? : bool := H1 _ x.
+have ? : bool := H2 _ x.
+have ? : bool := H3 _ x.
+have ? (z : bool) : forall y : bool, z = z := fun y => refl_equal _.
+have ? w : w = w := @refl_equal nat w.
+have ? y : true by [].
+have ? (z : bool) : z = z.
+ exact: (@refl_equal _ z).
+have ? (z w : bool) : z = z by exact: (@refl_equal _ z).
+have H w (a := 3) (_ := 4) : w && true = w.
+ by rewrite andbT.
+exact I.
+Qed.
+
+Lemma test1 : True.
+suff (x : bool): x = x /\ True.
+ by move/(_ true); case=> _.
+split; first by exact: (@refl_equal _ x).
+suff H y : y && true = y /\ True.
+ by case: (H true).
+suff H1 /= : true && true /\ True.
+ by rewrite andbT; split; [exact: (@refl_equal _ y) | exact: I].
+match goal with |- is_true true /\ True => idtac end.
+by split.
+Qed.
+
+Lemma foo n : n >= 0.
+have f i (j := i + n) : j < n.
+ match goal with j := i + n |- _ => idtac end.
+Undo 2.
+suff f i (j := i + n) : j < n.
+ done.
+match goal with j := i + n |- _ => idtac end.
+Undo 3.
+done.
+Qed.
diff --git a/test-suite/ssr/binders_of.v b/test-suite/ssr/binders_of.v
new file mode 100644
index 000000000..69b52eace
--- /dev/null
+++ b/test-suite/ssr/binders_of.v
@@ -0,0 +1,23 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+
+Require Import ssreflect.
+Require Import TestSuite.ssr_mini_mathcomp.
+
+Lemma test1 : True.
+have f of seq nat & nat : nat.
+ exact 3.
+have g of nat := 3.
+have h of nat : nat := 3.
+have _ : f [::] 3 = g 3 + h 4.
+Admitted.
diff --git a/test-suite/ssr/caseview.v b/test-suite/ssr/caseview.v
new file mode 100644
index 000000000..94b064b02
--- /dev/null
+++ b/test-suite/ssr/caseview.v
@@ -0,0 +1,17 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+
+
+Lemma test (A B : Prop) : A /\ B -> True.
+Proof. by case=> _ /id _. Qed.
diff --git a/test-suite/ssr/congr.v b/test-suite/ssr/congr.v
new file mode 100644
index 000000000..7e60b04a6
--- /dev/null
+++ b/test-suite/ssr/congr.v
@@ -0,0 +1,34 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrbool TestSuite.ssr_mini_mathcomp.
+
+Lemma test1 : forall a b : nat, a == b -> a == 0 -> b == 0.
+Proof. move=> a b Eab Eac; congr (_ == 0) : Eac; exact: eqP Eab. Qed.
+
+Definition arrow A B := A -> B.
+
+Lemma test2 : forall a b : nat, a == b -> arrow (a == 0) (b == 0).
+Proof. move=> a b Eab; congr (_ == 0); exact: eqP Eab. Qed.
+
+Definition equals T (A B : T) := A = B.
+
+Lemma test3 : forall a b : nat, a = b -> equals nat (a + b) (b + b).
+Proof. move=> a b E; congr (_ + _); exact E. Qed.
+
+Variable S : eqType.
+Variable f : nat -> S.
+Coercion f : nat >-> Equality.sort.
+
+Lemma test4 : forall a b : nat, b = a -> @eq S (b + b) (a + a).
+Proof. move=> a b Eba; congr (_ + _); exact: Eba. Qed.
diff --git a/test-suite/ssr/deferclear.v b/test-suite/ssr/deferclear.v
new file mode 100644
index 000000000..85353dadf
--- /dev/null
+++ b/test-suite/ssr/deferclear.v
@@ -0,0 +1,37 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+
+Require Import ssrbool TestSuite.ssr_mini_mathcomp.
+
+Variable T : Type.
+
+Lemma test0 : forall a b c d : T, True.
+Proof. by move=> a b {a} a c; exact I. Qed.
+
+Variable P : T -> Prop.
+
+Lemma test1 : forall a b c : T, P a -> forall d : T, True.
+Proof. move=> a b {a} a _ d; exact I. Qed.
+
+Definition Q := forall x y : nat, x = y.
+Axiom L : 0 = 0 -> Q.
+Axiom L' : 0 = 0 -> forall x y : nat, x = y.
+Lemma test3 : Q.
+by apply/L.
+Undo.
+rewrite /Q.
+by apply/L.
+Undo 2.
+by apply/L'.
+Qed.
diff --git a/test-suite/ssr/dependent_type_err.v b/test-suite/ssr/dependent_type_err.v
new file mode 100644
index 000000000..a5789d8dd
--- /dev/null
+++ b/test-suite/ssr/dependent_type_err.v
@@ -0,0 +1,20 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrfun ssrbool TestSuite.ssr_mini_mathcomp.
+
+Lemma ltn_leq_trans : forall n m p : nat, m < n -> n <= p -> m < p.
+move=> n m p Hmn Hnp; rewrite -ltnS.
+Fail rewrite (_ : forall n0 m0 p0 : nat, m0 <= n0 -> n0 < p0 -> m0 < p0).
+Fail rewrite leq_ltn_trans.
+Admitted.
diff --git a/test-suite/ssr/derive_inversion.v b/test-suite/ssr/derive_inversion.v
new file mode 100644
index 000000000..abf63a20c
--- /dev/null
+++ b/test-suite/ssr/derive_inversion.v
@@ -0,0 +1,29 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+Require Import ssreflect ssrbool.
+
+Set Implicit Arguments.
+
+ Inductive wf T : bool -> option T -> Type :=
+ | wf_f : wf false None
+ | wf_t : forall x, wf true (Some x).
+
+ Derive Inversion wf_inv with (forall T b (o : option T), wf b o) Sort Prop.
+
+ Lemma Problem T b (o : option T) :
+ wf b o ->
+ match b with
+ | true => exists x, o = Some x
+ | false => o = None
+ end.
+ Proof.
+ by case: b; elim/wf_inv=> //; case: o=> // a *; exists a.
+ Qed.
diff --git a/test-suite/ssr/elim.v b/test-suite/ssr/elim.v
new file mode 100644
index 000000000..908249a36
--- /dev/null
+++ b/test-suite/ssr/elim.v
@@ -0,0 +1,279 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrbool ssrfun TestSuite.ssr_mini_mathcomp.
+Axiom daemon : False. Ltac myadmit := case: daemon.
+
+(* Ltac debugging feature: recursive elim + eq generation *)
+Lemma testL1 : forall A (s : seq A), s = s.
+Proof.
+move=> A s; elim branch: s => [|x xs _].
+match goal with _ : _ = [::] |- [::] = [::] => move: branch => // | _ => fail end.
+match goal with _ : _ = _ :: _ |- _ :: _ = _ :: _ => move: branch => // | _ => fail end.
+Qed.
+
+(* The same but with explicit eliminator and a conflict in the intro pattern *)
+Lemma testL2 : forall A (s : seq A), s = s.
+Proof.
+move=> A s; elim/last_ind branch: s => [|x s _].
+match goal with _ : _ = [::] |- [::] = [::] => move: branch => // | _ => fail end.
+match goal with _ : _ = rcons _ _ |- rcons _ _ = rcons _ _ => move: branch => // | _ => fail end.
+Qed.
+
+(* The same but without names for variables involved in the generated eq *)
+Lemma testL3 : forall A (s : seq A), s = s.
+Proof.
+move=> A s; elim branch: s; move: (s) => _.
+match goal with _ : _ = [::] |- [::] = [::] => move: branch => // | _ => fail end.
+move=> _; match goal with _ : _ = _ :: _ |- _ :: _ = _ :: _ => move: branch => // | _ => fail end.
+Qed.
+
+Inductive foo : Type := K1 : foo | K2 : foo -> foo -> foo | K3 : (nat -> foo) -> foo.
+
+(* The same but with more intros to be done *)
+Lemma testL4 : forall (o : foo), o = o.
+Proof.
+move=> o; elim branch: o.
+match goal with _ : _ = K1 |- K1 = K1 => move: branch => // | _ => fail end.
+move=> _; match goal with _ : _ = K2 _ _ |- K2 _ _ = K2 _ _ => move: branch => // | _ => fail end.
+move=> _; match goal with _ : _ = K3 _ |- K3 _ = K3 _ => move: branch => // | _ => fail end.
+Qed.
+
+(* Occurrence counting *)
+Lemma testO1: forall (b : bool), b = b.
+Proof.
+move=> b; case: (b) / idP.
+match goal with |- is_true b -> true = true => done | _ => fail end.
+match goal with |- ~ is_true b -> false = false => done | _ => fail end.
+Qed.
+
+(* The same but only the second occ *)
+Lemma testO2: forall (b : bool), b = b.
+Proof.
+move=> b; case: {2}(b) / idP.
+match goal with |- is_true b -> b = true => done | _ => fail end.
+match goal with |- ~ is_true b -> b = false => move/(introF idP) => // | _ => fail end.
+Qed.
+
+(* The same but with eq generation *)
+Lemma testO3: forall (b : bool), b = b.
+Proof.
+move=> b; case E: {2}(b) / idP.
+match goal with _ : is_true b, _ : b = true |- b = true => move: E => _; done | _ => fail end.
+match goal with H : ~ is_true b, _ : b = false |- b = false => move: E => _; move/(introF idP): H => // | _ => fail end.
+Qed.
+
+(* Views *)
+Lemma testV1 : forall A (s : seq A), s = s.
+Proof.
+move=> A s; case/lastP E: {1}s => [| x xs].
+match goal with _ : s = [::] |- [::] = s => symmetry; exact E | _ => fail end.
+match goal with _ : s = rcons x xs |- rcons _ _ = s => symmetry; exact E | _ => fail end.
+Qed.
+
+Lemma testV2 : forall A (s : seq A), s = s.
+Proof.
+move=> A s; case/lastP E: s => [| x xs].
+match goal with _ : s = [::] |- [::] = [::] => done | _ => fail end.
+match goal with _ : s = rcons x xs |- rcons _ _ = rcons _ _ => done | _ => fail end.
+Qed.
+
+Lemma testV3 : forall A (s : seq A), s = s.
+Proof.
+move=> A s; case/lastP: s => [| x xs].
+match goal with |- [::] = [::] => done | _ => fail end.
+match goal with |- rcons _ _ = rcons _ _ => done | _ => fail end.
+Qed.
+
+(* Patterns *)
+Lemma testP1: forall (x y : nat), (y == x) && (y == x) -> y == x.
+move=> x y; elim: {2}(_ == _) / eqP.
+match goal with |- (y = x -> is_true ((y == x) && true) -> is_true (y == x)) => move=> -> // | _ => fail end.
+match goal with |- (y <> x -> is_true ((y == x) && false) -> is_true (y == x)) => move=> _; rewrite andbC // | _ => fail end.
+Qed.
+
+(* The same but with an implicit pattern *)
+Lemma testP2 : forall (x y : nat), (y == x) && (y == x) -> y == x.
+move=> x y; elim: {2}_ / eqP.
+match goal with |- (y = x -> is_true ((y == x) && true) -> is_true (y == x)) => move=> -> // | _ => fail end.
+match goal with |- (y <> x -> is_true ((y == x) && false) -> is_true (y == x)) => move=> _; rewrite andbC // | _ => fail end.
+Qed.
+
+(* The same but with an eq generation switch *)
+Lemma testP3 : forall (x y : nat), (y == x) && (y == x) -> y == x.
+move=> x y; elim E: {2}_ / eqP.
+match goal with _ : y = x |- (is_true ((y == x) && true) -> is_true (y == x)) => rewrite E; reflexivity | _ => fail end.
+match goal with _ : y <> x |- (is_true ((y == x) && false) -> is_true (y == x)) => rewrite E => /= H; exact H | _ => fail end.
+Qed.
+
+Inductive spec : nat -> nat -> nat -> Prop :=
+| specK : forall a b c, a = 0 -> b = 2 -> c = 4 -> spec a b c.
+Lemma specP : spec 0 2 4. Proof. by constructor. Qed.
+
+Lemma testP4 : (1+1) * 4 = 2 + (1+1) + (2 + 2).
+Proof.
+case: specP => a b c defa defb defc.
+match goal with |- (a.+1 + a.+1) * c = b + (a.+1 + a.+1) + (b + b) => subst; done | _ => fail end.
+Qed.
+
+Lemma testP5 : (1+1) * 4 = 2 + (1+1) + (2 + 2).
+Proof.
+case: (1 + 1) _ / specP => a b c defa defb defc.
+match goal with |- b * c = a.+2 + b + (a.+2 + a.+2) => subst; done | _ => fail end.
+Qed.
+
+Lemma testP6 : (1+1) * 4 = 2 + (1+1) + (2 + 2).
+Proof.
+case: {2}(1 + 1) _ / specP => a b c defa defb defc.
+match goal with |- (a.+1 + a.+1) * c = a.+2 + b + (a.+2 + a.+2) => subst; done | _ => fail end.
+Qed.
+
+Lemma testP7 : (1+1) * 4 = 2 + (1+1) + (2 + 2).
+Proof.
+case: _ (1 + 1) (2 + _) / specP => a b c defa defb defc.
+match goal with |- b * a.+4 = c + c => subst; done | _ => fail end.
+Qed.
+
+Lemma testP8 : (1+1) * 4 = 2 + (1+1) + (2 + 2).
+Proof.
+case E: (1 + 1) (2 + _) / specP=> [a b c defa defb defc].
+match goal with |- b * a.+4 = c + c => subst; done | _ => fail end.
+Qed.
+
+Variables (T : Type) (tr : T -> T).
+
+Inductive exec (cf0 cf1 : T) : seq T -> Prop :=
+| exec_step : tr cf0 = cf1 -> exec cf0 cf1 [::]
+| exec_star : forall cf2 t, tr cf0 = cf2 ->
+ exec cf2 cf1 t -> exec cf0 cf1 (cf2 :: t).
+
+Inductive execr (cf0 cf1 : T) : seq T -> Prop :=
+| execr_step : tr cf0 = cf1 -> execr cf0 cf1 [::]
+| execr_star : forall cf2 t, execr cf0 cf2 t ->
+ tr cf2 = cf1 -> execr cf0 cf1 (t ++ [:: cf2]).
+
+Lemma execP : forall cf0 cf1 t, exec cf0 cf1 t <-> execr cf0 cf1 t.
+Proof.
+move=> cf0 cf1 t; split => [] Ecf.
+ elim: Ecf.
+ match goal with |- forall cf2 cf3 : T, tr cf2 = cf3 ->
+ execr cf2 cf3 [::] => myadmit | _ => fail end.
+ match goal with |- forall (cf2 cf3 cf4 : T) (t0 : seq T),
+ tr cf2 = cf4 -> exec cf4 cf3 t0 -> execr cf4 cf3 t0 ->
+ execr cf2 cf3 (cf4 :: t0) => myadmit | _ => fail end.
+elim: Ecf.
+ match goal with |- forall cf2 : T,
+ tr cf0 = cf2 -> exec cf0 cf2 [::] => myadmit | _ => fail end.
+match goal with |- forall (cf2 cf3 : T) (t0 : seq T),
+ execr cf0 cf3 t0 -> exec cf0 cf3 t0 -> tr cf3 = cf2 ->
+ exec cf0 cf2 (t0 ++ [:: cf3]) => myadmit | _ => fail end.
+Qed.
+
+Fixpoint plus (m n : nat) {struct n} : nat :=
+ match n with
+ | 0 => m
+ | S p => S (plus m p)
+ end.
+
+Definition plus_equation :
+forall m n : nat,
+ plus m n =
+ match n with
+ | 0 => m
+ | p.+1 => (plus m p).+1
+ end
+:=
+fun m n : nat =>
+match
+ n as n0
+ return
+ (forall m0 : nat,
+ plus m0 n0 =
+ match n0 with
+ | 0 => m0
+ | p.+1 => (plus m0 p).+1
+ end)
+with
+| 0 => @erefl nat
+| n0.+1 => fun m0 : nat => erefl (plus m0 n0).+1
+end m.
+
+Definition plus_rect :
+forall (m : nat) (P : nat -> nat -> Type),
+ (forall n : nat, n = 0 -> P 0 m) ->
+ (forall n p : nat,
+ n = p.+1 -> P p (plus m p) -> P p.+1 (plus m p).+1) ->
+ forall n : nat, P n (plus m n)
+:=
+fun (m : nat) (P : nat -> nat -> Type)
+ (f0 : forall n : nat, n = 0 -> P 0 m)
+ (f : forall n p : nat,
+ n = p.+1 -> P p (plus m p) -> P p.+1 (plus m p).+1) =>
+fix plus0 (n : nat) : P n (plus m n) :=
+ eq_rect_r [eta P n]
+ (let f1 := f0 n in
+ let f2 := f n in
+ match
+ n as n0
+ return
+ (n = n0 ->
+ (forall p : nat,
+ n0 = p.+1 -> P p (plus m p) -> P p.+1 (plus m p).+1) ->
+ (n0 = 0 -> P 0 m) ->
+ P n0 match n0 with
+ | 0 => m
+ | p.+1 => (plus m p).+1
+ end)
+ with
+ | 0 =>
+ fun (_ : n = 0)
+ (_ : forall p : nat,
+ 0 = p.+1 ->
+ P p (plus m p) -> P p.+1 (plus m p).+1)
+ (f4 : 0 = 0 -> P 0 m) => unkeyed (f4 (erefl 0))
+ | n0.+1 =>
+ fun (_ : n = n0.+1)
+ (f3 : forall p : nat,
+ n0.+1 = p.+1 ->
+ P p (plus m p) -> P p.+1 (plus m p).+1)
+ (_ : n0.+1 = 0 -> P 0 m) =>
+ let f5 :=
+ let p := n0 in
+ let H := erefl n0.+1 : n0.+1 = p.+1 in f3 p H in
+ unkeyed (let Hrec := plus0 n0 in f5 Hrec)
+ end (erefl n) f2 f1) (plus_equation m n).
+
+Definition plus_ind := plus_rect.
+
+Lemma exF x y z: plus (plus x y) z = plus x (plus y z).
+elim/plus_ind: z / (plus _ z).
+match goal with |- forall n : nat, n = 0 -> plus x y = plus x (plus y 0) => idtac end.
+Undo 2.
+elim/plus_ind: (plus _ z).
+match goal with |- forall n : nat, n = 0 -> plus x y = plus x (plus y 0) => idtac end.
+Undo 2.
+elim/plus_ind: {z}(plus _ z).
+match goal with |- forall n : nat, n = 0 -> plus x y = plus x (plus y 0) => idtac end.
+Undo 2.
+elim/plus_ind: {z}_.
+match goal with |- forall n : nat, n = 0 -> plus x y = plus x (plus y 0) => idtac end.
+Undo 2.
+elim/plus_ind: z / _.
+match goal with |- forall n : nat, n = 0 -> plus x y = plus x (plus y 0) => idtac end.
+ done.
+by move=> _ p _ ->.
+Qed.
+
+(* BUG elim-False *)
+Lemma testeF : False -> 1 = 0.
+Proof. by elim. Qed.
diff --git a/test-suite/ssr/elim2.v b/test-suite/ssr/elim2.v
new file mode 100644
index 000000000..c7c20d8f8
--- /dev/null
+++ b/test-suite/ssr/elim2.v
@@ -0,0 +1,74 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrbool TestSuite.ssr_mini_mathcomp.
+(* div fintype finfun path bigop. *)
+
+Axiom daemon : False. Ltac myadmit := case: daemon.
+
+Lemma big_load R (K K' : R -> Type) idx op I r (P : pred I) F :
+ let s := \big[op/idx]_(i <- r | P i) F i in
+ K s * K' s -> K' s.
+Proof. by move=> /= [_]. Qed.
+Arguments big_load [R] K [K' idx op I r P F].
+
+Section Elim1.
+
+Variables (R : Type) (K : R -> Type) (f : R -> R).
+Variables (idx : R) (op op' : R -> R -> R).
+
+Hypothesis Kid : K idx.
+
+Ltac ASSERT1 := match goal with |- (K idx) => myadmit end.
+Ltac ASSERT2 K := match goal with |- (forall x1 : R, R ->
+ forall y1 : R, R -> K x1 -> K y1 -> K (op x1 y1)) => myadmit end.
+
+
+Lemma big_rec I r (P : pred I) F
+ (Kop : forall i x, P i -> K x -> K (op (F i) x)) :
+ K (\big[op/idx]_(i <- r | P i) F i).
+Proof.
+elim/big_ind2: {-}_.
+ ASSERT1. ASSERT2 K. match goal with |- (forall i : I, is_true (P i) -> K (F i)) => myadmit end. Undo 4.
+elim/big_ind2: _ / {-}_.
+ ASSERT1. ASSERT2 K. match goal with |- (forall i : I, is_true (P i) -> K (F i)) => myadmit end. Undo 4.
+
+elim/big_rec2: (\big[op/idx]_(i <- r | P i) op idx (F i))
+ / (\big[op/idx]_(i <- r | P i) F i).
+ ASSERT1. match goal with |- (forall i : I, R -> forall y2 : R, is_true (P i) -> K y2 -> K (op (F i) y2)) => myadmit end. Undo 3.
+
+elim/(big_load (phantom R)): _.
+ Undo.
+
+Fail elim/big_rec2: {2}_.
+
+elim/big_rec2: (\big[op/idx]_(i <- r | P i) F i)
+ / {1}(\big[op/idx]_(i <- r | P i) F i).
+ Undo.
+
+elim/(big_load (phantom R)): _.
+Undo.
+
+Fail elim/big_rec2: _ / {2}(\big[op/idx]_(i <- r | P i) F i).
+Admitted.
+
+Definition morecomplexthannecessary A (P : A -> A -> Prop) x y := P x y.
+
+Lemma grab A (P : A -> A -> Prop) n m : (n = m) -> (P n n) -> morecomplexthannecessary A P n m.
+by move->.
+Qed.
+
+Goal forall n m, m + (n + m) = m + (n * 1 + m).
+Proof. move=> n m; elim/grab : (_ * _) / {1}n => //; exact: muln1. Qed.
+
+End Elim1.
diff --git a/test-suite/ssr/elim_pattern.v b/test-suite/ssr/elim_pattern.v
new file mode 100644
index 000000000..ef4658287
--- /dev/null
+++ b/test-suite/ssr/elim_pattern.v
@@ -0,0 +1,27 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrbool TestSuite.ssr_mini_mathcomp.
+Axiom daemon : False. Ltac myadmit := case: daemon.
+
+Lemma test x : (x == x) = (x + x.+1 == 2 * x + 1).
+case: (X in _ = X) / eqP => _.
+match goal with |- (x == x) = true => myadmit end.
+match goal with |- (x == x) = false => myadmit end.
+Qed.
+
+Lemma test1 x : (x == x) = (x + x.+1 == 2 * x + 1).
+elim: (x in RHS).
+match goal with |- (x == x) = _ => myadmit end.
+match goal with |- forall n, (x == x) = _ -> (x == x) = _ => myadmit end.
+Qed.
diff --git a/test-suite/ssr/first_n.v b/test-suite/ssr/first_n.v
new file mode 100644
index 000000000..4971add91
--- /dev/null
+++ b/test-suite/ssr/first_n.v
@@ -0,0 +1,21 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrbool.
+
+Lemma test : False -> (bool -> False -> True -> True) -> True.
+move=> F; let w := constr:(2) in apply; last w first.
+- by apply: F.
+- by apply: I.
+- by apply: true.
+Qed.
diff --git a/test-suite/ssr/gen_have.v b/test-suite/ssr/gen_have.v
new file mode 100644
index 000000000..249e006f9
--- /dev/null
+++ b/test-suite/ssr/gen_have.v
@@ -0,0 +1,174 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrfun ssrbool TestSuite.ssr_mini_mathcomp.
+Axiom daemon : False. Ltac myadmit := case: daemon.
+
+Axiom P : nat -> Prop.
+Lemma clear_test (b1 b2 : bool) : b2 = b2.
+Proof.
+(* wlog gH : (b3 := b2) / b2 = b3. myadmit. *)
+gen have {b1} H, gH : (b3 := b2) (w := erefl 3) / b2 = b3.
+ myadmit.
+Fail exact (H b1).
+exact (H b2 (erefl _)).
+Qed.
+
+
+Lemma test1 n (ngt0 : 0 < n) : P n.
+gen have lt2le, /andP[H1 H2] : n ngt0 / (0 <= n) && (n != 0).
+ match goal with |- is_true((0 <= n) && (n != 0)) => myadmit end.
+Check (lt2le : forall n : nat, 0 < n -> (0 <= n) && (n != 0)).
+Check (H1 : 0 <= n).
+Check (H2 : n != 0).
+myadmit.
+Qed.
+
+Lemma test2 n (ngt0 : 0 < n) : P n.
+gen have _, /andP[H1 H2] : n ngt0 / (0 <= n) && (n != 0).
+ match goal with |- is_true((0 <= n) && (n != 0)) => myadmit end.
+lazymatch goal with
+ | lt2le : forall n : nat, is_true(0 < n) -> is_true((0 <= n) && (n != 0))
+ |- _ => fail "not cleared"
+ | _ => idtac end.
+Check (H1 : 0 <= n).
+Check (H2 : n != 0).
+myadmit.
+Qed.
+
+Lemma test3 n (ngt0 : 0 < n) : P n.
+gen have H : n ngt0 / (0 <= n) && (n != 0).
+ match goal with |- is_true((0 <= n) && (n != 0)) => myadmit end.
+Check (H : forall n : nat, 0 < n -> (0 <= n) && (n != 0)).
+myadmit.
+Qed.
+
+Lemma test4 n (ngt0 : 0 < n) : P n.
+gen have : n ngt0 / (0 <= n) && (n != 0).
+ match goal with |- is_true((0 <= n) && (n != 0)) => myadmit end.
+move=> H.
+Check(H : forall n : nat, 0 < n -> (0 <= n) && (n != 0)).
+myadmit.
+Qed.
+
+Lemma test4bis n (ngt0 : 0 < n) : P n.
+wlog suff : n ngt0 / (0 <= n) && (n != 0); last first.
+ match goal with |- is_true((0 <= n) && (n != 0)) => myadmit end.
+move=> H.
+Check(H : forall n : nat, 0 < n -> (0 <= n) && (n != 0)).
+myadmit.
+Qed.
+
+Lemma test5 n (ngt0 : 0 < n) : P n.
+Fail gen have : / (0 <= n) && (n != 0).
+Abort.
+
+Lemma test6 n (ngt0 : 0 < n) : P n.
+gen have : n ngt0 / (0 <= n) && (n != 0) by myadmit.
+Abort.
+
+Lemma test7 n (ngt0 : 0 < n) : P n.
+Fail gen have : n / (0 <= n) && (n != 0).
+Abort.
+
+Lemma test3wlog2 n (ngt0 : 0 < n) : P n.
+gen have H : (m := n) ngt0 / (0 <= m) && (m != 0).
+ match goal with
+ ngt0 : is_true(0 < m) |- is_true((0 <= m) && (m != 0)) => myadmit end.
+Check (H : forall n : nat, 0 < n -> (0 <= n) && (n != 0)).
+myadmit.
+Qed.
+
+Lemma test3wlog3 n (ngt0 : 0 < n) : P n.
+gen have H : {n} (m := n) (n := 0) ngt0 / (0 <= m) && (m != n).
+ match goal with
+ ngt0 : is_true(n < m) |- is_true((0 <= m) && (m != n)) => myadmit end.
+Check (H : forall m n : nat, n < m -> (0 <= m) && (m != n)).
+myadmit.
+Qed.
+
+Lemma testw1 n (ngt0 : 0 < n) : n <= 0.
+wlog H : (z := 0) (m := n) ngt0 / m != 0.
+ match goal with
+ |- (forall z m,
+ is_true(z < m) -> is_true(m != 0) -> is_true(m <= z)) ->
+ is_true(n <= 0) => myadmit end.
+Check(n : nat).
+Check(m : nat).
+Check(z : nat).
+Check(ngt0 : z < m).
+Check(H : m != 0).
+myadmit.
+Qed.
+
+Lemma testw2 n (ngt0 : 0 < n) : n <= 0.
+wlog H : (m := n) (z := (X in n <= X)) ngt0 / m != z.
+ match goal with
+ |- (forall m z : nat,
+ is_true(0 < m) -> is_true(m != z) -> is_true(m <= z)) ->
+ is_true(n <= 0) => idtac end.
+Restart.
+wlog H : (m := n) (one := (X in X <= _)) ngt0 / m != one.
+ match goal with
+ |- (forall m one : nat,
+ is_true(one <= m) -> is_true(m != one) -> is_true(m <= 0)) ->
+ is_true(n <= 0) => idtac end.
+Restart.
+wlog H : {n} (m := n) (z := (X in _ <= X)) ngt0 / m != z.
+ match goal with
+ |- (forall m z : nat,
+ is_true(0 < z) -> is_true(m != z) -> is_true(m <= 0)) ->
+ is_true(n <= 0) => idtac end.
+ myadmit.
+Fail Check n.
+myadmit.
+Qed.
+
+Section Test.
+Variable x : nat.
+Definition addx y := y + x.
+
+Lemma testw3 (m n : nat) (ngt0 : 0 < n) : n <= addx x.
+wlog H : (n0 := n) (y := x) (@twoy := (id _ as X in _ <= X)) / twoy = 2 * y.
+ myadmit.
+myadmit.
+Qed.
+
+
+Definition twox := x + x.
+Definition bis := twox.
+
+Lemma testw3x n (ngt0 : 0 < n) : n + x <= twox.
+wlog H : (y := x) (@twoy := (X in _ <= X)) / twoy = 2 * y.
+ match goal with
+ |- (forall y : nat,
+ let twoy := y + y in
+ twoy = 2 * y -> is_true(n + y <= twoy)) ->
+ is_true(n + x <= twox) => myadmit end.
+Restart.
+wlog H : (y := x) (@twoy := (id _ as X in _ <= X)) / twoy = 2 * y.
+ match goal with
+ |- (forall y : nat,
+ let twoy := twox in
+ twoy = 2 * y -> is_true(n + y <= twoy)) ->
+ is_true(n + x <= twox) => myadmit end.
+myadmit.
+Qed.
+
+End Test.
+
+Lemma test_in n k (def_k : k = 0) (ngtk : k < n) : P n.
+rewrite -(add0n n) in {def_k k ngtk} (m := k) (def_m := def_k) (ngtm := ngtk).
+rewrite def_m add0n in {ngtm} (e := erefl 0 ) (ngt0 := ngtm) => {def_m}.
+myadmit.
+Qed.
diff --git a/test-suite/ssr/gen_pattern.v b/test-suite/ssr/gen_pattern.v
new file mode 100644
index 000000000..c0592e884
--- /dev/null
+++ b/test-suite/ssr/gen_pattern.v
@@ -0,0 +1,33 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrbool TestSuite.ssr_mini_mathcomp.
+
+Notation "( a 'in' c )" := (a + c) (only parsing) : myscope.
+Delimit Scope myscope with myscope.
+
+Notation "( a 'in' c )" := (a + c) (only parsing).
+
+Lemma foo x y : x + x.+1 = x.+1 + y.
+move: {x} (x.+1) {1}x y (x.+1 in RHS).
+ match goal with |- forall a b c d, b + a = d + c => idtac end.
+Admitted.
+
+Lemma bar x y : x + x.+1 = x.+1 + y.
+move E: ((x.+1 in y)) => w.
+ match goal with |- x + x.+1 = w => rewrite -{w}E end.
+move E: (x.+1 in y)%myscope => w.
+ match goal with |- x + x.+1 = w => rewrite -{w}E end.
+move E: ((x + y).+1 as RHS) => w.
+ match goal with |- x + x.+1 = w => rewrite -{}E -addSn end.
+Admitted.
diff --git a/test-suite/ssr/have_TC.v b/test-suite/ssr/have_TC.v
new file mode 100644
index 000000000..b3a26ed2c
--- /dev/null
+++ b/test-suite/ssr/have_TC.v
@@ -0,0 +1,50 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+
+Axiom daemon : False. Ltac myadmit := case: daemon.
+
+Class foo (T : Type) := { n : nat }.
+Instance five : foo nat := {| n := 5 |}.
+
+Definition bar T {f : foo T} m : Prop :=
+ @n _ f = m.
+
+Eval compute in (bar nat 7).
+
+Lemma a : True.
+set toto := bar _ 8.
+have titi : bar _ 5.
+ reflexivity.
+have titi2 : bar _ 5 := .
+ Fail reflexivity.
+ by myadmit.
+have totoc (H : bar _ 5) : 3 = 3 := eq_refl.
+move/totoc: nat => _.
+exact I.
+Qed.
+
+Set SsrHave NoTCResolution.
+
+Lemma a' : True.
+set toto := bar _ 8.
+have titi : bar _ 5.
+ Fail reflexivity.
+ by myadmit.
+have titi2 : bar _ 5 := .
+ Fail reflexivity.
+ by myadmit.
+have totoc (H : bar _ 5) : 3 = 3 := eq_refl.
+move/totoc: nat => _.
+exact I.
+Qed.
diff --git a/test-suite/ssr/have_transp.v b/test-suite/ssr/have_transp.v
new file mode 100644
index 000000000..1c998da71
--- /dev/null
+++ b/test-suite/ssr/have_transp.v
@@ -0,0 +1,48 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrfun ssrbool TestSuite.ssr_mini_mathcomp.
+
+
+Lemma test1 n : n >= 0.
+Proof.
+have [:s1] @h m : 'I_(n+m).+1.
+ apply: Sub 0 _.
+ abstract: s1 m.
+ by auto.
+cut (forall m, 0 < (n+m).+1); last assumption.
+rewrite [_ 1 _]/= in s1 h *.
+by [].
+Qed.
+
+Lemma test2 n : n >= 0.
+Proof.
+have [:s1] @h m : 'I_(n+m).+1 := Sub 0 (s1 m).
+ move=> m; reflexivity.
+cut (forall m, 0 < (n+m).+1); last assumption.
+by [].
+Qed.
+
+Lemma test3 n : n >= 0.
+Proof.
+Fail have [:s1] @h m : 'I_(n+m).+1 by apply: (Sub 0 (s1 m)); auto.
+have [:s1] @h m : 'I_(n+m).+1 by apply: (Sub 0); abstract: s1 m; auto.
+cut (forall m, 0 < (n+m).+1); last assumption.
+by [].
+Qed.
+
+Lemma test4 n : n >= 0.
+Proof.
+have @h m : 'I_(n+m).+1 by apply: (Sub 0); abstract auto.
+by [].
+Qed.
diff --git a/test-suite/ssr/have_view_idiom.v b/test-suite/ssr/have_view_idiom.v
new file mode 100644
index 000000000..3d6c9d980
--- /dev/null
+++ b/test-suite/ssr/have_view_idiom.v
@@ -0,0 +1,18 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrbool.
+
+Lemma test (a b : bool) (pab : a && b) : b.
+have {pab} /= /andP [pa -> //] /= : true && (a && b) := pab.
+Qed.
diff --git a/test-suite/ssr/havesuff.v b/test-suite/ssr/havesuff.v
new file mode 100644
index 000000000..aa1f71879
--- /dev/null
+++ b/test-suite/ssr/havesuff.v
@@ -0,0 +1,85 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+
+
+Variables P G : Prop.
+
+Lemma test1 : (P -> G) -> P -> G.
+Proof.
+move=> pg p.
+have suff {pg} H : P.
+ match goal with |- P -> G => move=> _; exact: pg p | _ => fail end.
+match goal with H : P -> G |- G => exact: H p | _ => fail end.
+Qed.
+
+Lemma test2 : (P -> G) -> P -> G.
+Proof.
+move=> pg p.
+have suffices {pg} H : P.
+ match goal with |- P -> G => move=> _; exact: pg p | _ => fail end.
+match goal with H : P -> G |- G => exact: H p | _ => fail end.
+Qed.
+
+Lemma test3 : (P -> G) -> P -> G.
+Proof.
+move=> pg p.
+suff have {pg} H : P.
+ match goal with H : P |- G => exact: pg H | _ => fail end.
+match goal with |- (P -> G) -> G => move=> H; exact: H p | _ => fail end.
+Qed.
+
+Lemma test4 : (P -> G) -> P -> G.
+Proof.
+move=> pg p.
+suffices have {pg} H: P.
+ match goal with H : P |- G => exact: pg H | _ => fail end.
+match goal with |- (P -> G) -> G => move=> H; exact: H p | _ => fail end.
+Qed.
+
+(*
+Lemma test5 : (P -> G) -> P -> G.
+Proof.
+move=> pg p.
+suff have {pg} H : P := pg H.
+match goal with |- (P -> G) -> G => move=> H; exact: H p | _ => fail end.
+Qed.
+*)
+
+(*
+Lemma test6 : (P -> G) -> P -> G.
+Proof.
+move=> pg p.
+suff have {pg} H := pg H.
+match goal with |- (P -> G) -> G => move=> H; exact: H p | _ => fail end.
+Qed.
+*)
+
+Lemma test7 : (P -> G) -> P -> G.
+Proof.
+move=> pg p.
+have suff {pg} H : P := pg.
+match goal with H : P -> G |- G => exact: H p | _ => fail end.
+Qed.
+
+Lemma test8 : (P -> G) -> P -> G.
+Proof.
+move=> pg p.
+have suff {pg} H := pg.
+match goal with H : P -> G |- G => exact: H p | _ => fail end.
+Qed.
+
+Goal forall x y : bool, x = y -> x = y.
+move=> x y E.
+by have {x E} -> : x = y by [].
+Qed.
diff --git a/test-suite/ssr/if_isnt.v b/test-suite/ssr/if_isnt.v
new file mode 100644
index 000000000..b8f6b7739
--- /dev/null
+++ b/test-suite/ssr/if_isnt.v
@@ -0,0 +1,22 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+
+
+Definition unopt (x : option bool) :=
+ if x isn't Some x then false else x.
+
+Lemma test1 : unopt None = false /\
+ unopt (Some false) = false /\
+ unopt (Some true) = true.
+Proof. by auto. Qed.
diff --git a/test-suite/ssr/intro_beta.v b/test-suite/ssr/intro_beta.v
new file mode 100644
index 000000000..8a164bd80
--- /dev/null
+++ b/test-suite/ssr/intro_beta.v
@@ -0,0 +1,25 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+
+
+Axiom T : Type.
+
+Definition C (P : T -> Prop) := forall x, P x.
+
+Axiom P : T -> T -> Prop.
+
+Lemma foo : C (fun x => forall y, let z := x in P y x).
+move=> a b.
+match goal with |- (let y := _ in _) => idtac end.
+Admitted.
diff --git a/test-suite/ssr/intro_noop.v b/test-suite/ssr/intro_noop.v
new file mode 100644
index 000000000..fdc85173a
--- /dev/null
+++ b/test-suite/ssr/intro_noop.v
@@ -0,0 +1,37 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrbool.
+Axiom daemon : False. Ltac myadmit := case: daemon.
+
+Lemma v : True -> bool -> bool. Proof. by []. Qed.
+
+Reserved Notation " a -/ b " (at level 0).
+Reserved Notation " a -// b " (at level 0).
+Reserved Notation " a -/= b " (at level 0).
+Reserved Notation " a -//= b " (at level 0).
+
+Lemma test : forall a b c, a || b || c.
+Proof.
+move=> ---a--- - -/=- -//- -/=- -//=- b [|-].
+move: {-}a => /v/v-H; have _ := H I I.
+Fail move: {-}a {H} => /v-/v-H.
+have - -> : a = (id a) by [].
+have --> : a = (id a) by [].
+have - - _ : a = (id a) by [].
+have -{1}-> : a = (id a) by [].
+ by myadmit.
+move: a.
+case: b => -[] //.
+by myadmit.
+Qed.
diff --git a/test-suite/ssr/ipatalternation.v b/test-suite/ssr/ipatalternation.v
new file mode 100644
index 000000000..6aa9a954c
--- /dev/null
+++ b/test-suite/ssr/ipatalternation.v
@@ -0,0 +1,18 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+
+
+Lemma test1 : Prop -> Prop -> Prop -> Prop -> Prop -> True = False -> Prop -> True \/ True.
+by move=> A /= /= /= B C {A} {B} ? _ {C} {1}-> *; right.
+Qed.
diff --git a/test-suite/ssr/ltac_have.v b/test-suite/ssr/ltac_have.v
new file mode 100644
index 000000000..380e52af4
--- /dev/null
+++ b/test-suite/ssr/ltac_have.v
@@ -0,0 +1,39 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrbool TestSuite.ssr_mini_mathcomp.
+
+Ltac SUFF1 h t := suff h x (p := x < 0) : t.
+Ltac SUFF2 h t := suff h x (p := x < 0) : t by apply h.
+Ltac HAVE1 h t u := have h x (p := x < 0) : t := u.
+Ltac HAVE2 h t := have h x (p := x < 0) : t by [].
+Ltac HAVE3 h t := have h x (p := x < 0) : t.
+Ltac HAVES h t := have suff h : t.
+Ltac SUFFH h t := suff have h : t.
+
+Lemma foo z : z < 0.
+SUFF1 h1 (z+1 < 0).
+Undo.
+SUFF2 h2 (z < 0).
+Undo.
+HAVE1 h3 (z = z) (refl_equal z).
+Undo.
+HAVE2 h4 (z = z).
+Undo.
+HAVE3 h5 (z < 0).
+Undo.
+HAVES h6 (z < 1).
+Undo.
+SUFFH h7 (z < 1).
+Undo.
+Admitted.
diff --git a/test-suite/ssr/ltac_in.v b/test-suite/ssr/ltac_in.v
new file mode 100644
index 000000000..bcdf96dde
--- /dev/null
+++ b/test-suite/ssr/ltac_in.v
@@ -0,0 +1,26 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrbool TestSuite.ssr_mini_mathcomp.
+
+Set Implicit Arguments.
+Unset Strict Implicit.
+Import Prenex Implicits.
+
+(* error 1 *)
+
+Ltac subst1 H := move: H; rewrite {1} addnC; move => H.
+Ltac subst2 H := rewrite addnC in H.
+
+Goal ( forall a b: nat, b+a = 0 -> b+a=0).
+Proof. move=> a b hyp. subst1 hyp. subst2 hyp. done. Qed.
diff --git a/test-suite/ssr/move_after.v b/test-suite/ssr/move_after.v
new file mode 100644
index 000000000..a7a9afea0
--- /dev/null
+++ b/test-suite/ssr/move_after.v
@@ -0,0 +1,19 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+
+
+Goal True -> True -> True.
+move=> H1 H2.
+move H1 after H2.
+Admitted.
diff --git a/test-suite/ssr/multiview.v b/test-suite/ssr/multiview.v
new file mode 100644
index 000000000..f4e717b38
--- /dev/null
+++ b/test-suite/ssr/multiview.v
@@ -0,0 +1,58 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrbool TestSuite.ssr_mini_mathcomp.
+
+Goal forall m n p, n <= p -> m <= n -> m <= p.
+by move=> m n p le_n_p /leq_trans; apply.
+Undo 1.
+by move=> m n p le_n_p /leq_trans /(_ le_n_p) le_m_p; exact: le_m_p.
+Undo 1.
+by move=> m n p le_n_p /leq_trans ->.
+Qed.
+
+Goal forall P Q X : Prop, Q -> (True -> X -> Q = P) -> X -> P.
+by move=> P Q X q V /V <-.
+Qed.
+
+Lemma test0: forall a b, a && a && b -> b.
+by move=> a b; repeat move=> /andP []; move=> *.
+Qed.
+
+Lemma test1 : forall a b, a && b -> b.
+by move=> a b /andP /andP /andP [] //.
+Qed.
+
+Lemma test2 : forall a b, a && b -> b.
+by move=> a b /andP /andP /(@andP a) [] //.
+Qed.
+
+Lemma test3 : forall a b, a && (b && b) -> b.
+by move=> a b /andP [_ /andP [_ //]].
+Qed.
+
+Lemma test4: forall a b, a && b = b && a.
+by move=> a b; apply/andP/andP=> ?; apply/andP/andP/andP; rewrite andbC; apply/andP.
+Qed.
+
+Lemma test5: forall C I A O, (True -> O) -> (O -> A) -> (True -> A -> I) -> (I -> C) -> C.
+by move=> c i a o O A I C; apply/C/I/A/O.
+Qed.
+
+Lemma test6: forall A B, (A -> B) -> A -> B.
+move=> A B A_to_B a; move/A_to_B in a; exact: a.
+Qed.
+
+Lemma test7: forall A B, (A -> B) -> A -> B.
+move=> A B A_to_B a; apply A_to_B in a; exact: a.
+Qed.
diff --git a/test-suite/ssr/occarrow.v b/test-suite/ssr/occarrow.v
new file mode 100644
index 000000000..49af7ae08
--- /dev/null
+++ b/test-suite/ssr/occarrow.v
@@ -0,0 +1,23 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import TestSuite.ssr_mini_mathcomp.
+
+Lemma test1 : forall n m : nat, n = m -> m * m + n * n = n * n + n * n.
+move=> n m E; have [{2}-> _] : n * n = m * n /\ True by move: E => {1}<-.
+by move: E => {3}->.
+Qed.
+
+Lemma test2 : forall n m : nat, True /\ (n = m -> n * n = n * m).
+by move=> n m; constructor=> [|{2}->].
+Qed.
diff --git a/test-suite/ssr/patnoX.v b/test-suite/ssr/patnoX.v
new file mode 100644
index 000000000..d69f03ac3
--- /dev/null
+++ b/test-suite/ssr/patnoX.v
@@ -0,0 +1,18 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrbool.
+Goal forall x, x && true = x.
+move=> x.
+Fail (rewrite [X in _ && _]andbT).
+Abort.
diff --git a/test-suite/ssr/pattern.v b/test-suite/ssr/pattern.v
new file mode 100644
index 000000000..396f4f032
--- /dev/null
+++ b/test-suite/ssr/pattern.v
@@ -0,0 +1,32 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+Require Import ssrmatching.
+
+(*Set Debug SsrMatching.*)
+
+Tactic Notation "at" "[" ssrpatternarg(pat) "]" tactic(t) :=
+ let name := fresh in
+ let def_name := fresh in
+ ssrpattern pat;
+ intro name;
+ pose proof (refl_equal name) as def_name;
+ unfold name at 1 in def_name;
+ t def_name;
+ [ rewrite <- def_name | idtac.. ];
+ clear name def_name.
+
+Lemma test (H : True -> True -> 3 = 7) : 28 = 3 * 4.
+Proof.
+at [ X in X * 4 ] ltac:(fun place => rewrite -> H in place).
+- reflexivity.
+- trivial.
+- trivial.
+Qed.
diff --git a/test-suite/ssr/primproj.v b/test-suite/ssr/primproj.v
new file mode 100644
index 000000000..cf61eb436
--- /dev/null
+++ b/test-suite/ssr/primproj.v
@@ -0,0 +1,164 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+
+
+Require Import Setoid.
+Set Primitive Projections.
+
+
+Module CoqBug.
+Record foo A := Foo { foo_car : A }.
+
+Definition bar : foo _ := Foo nat 10.
+
+Variable alias : forall A, foo A -> A.
+
+Parameter e : @foo_car = alias.
+
+Goal foo_car _ bar = alias _ bar.
+Proof.
+(* Coq equally fails *)
+Fail rewrite -> e.
+Fail rewrite e at 1.
+Fail setoid_rewrite e.
+Fail setoid_rewrite e at 1.
+Set Keyed Unification.
+Fail rewrite -> e.
+Fail rewrite e at 1.
+Fail setoid_rewrite e.
+Fail setoid_rewrite e at 1.
+Admitted.
+
+End CoqBug.
+
+(* ----------------------------------------------- *)
+Require Import ssreflect.
+
+Set Primitive Projections.
+
+Module T1.
+
+Record foo A := Foo { foo_car : A }.
+
+Definition bar : foo _ := Foo nat 10.
+
+Goal foo_car _ bar = 10.
+Proof.
+match goal with
+| |- foo_car _ bar = 10 => idtac
+end.
+rewrite /foo_car.
+(*
+Fail match goal with
+| |- foo_car _ bar = 10 => idtac
+end.
+*)
+Admitted.
+
+End T1.
+
+
+Module T2.
+
+Record foo {A} := Foo { foo_car : A }.
+
+Definition bar : foo := Foo nat 10.
+
+Goal foo_car bar = 10.
+match goal with
+| |- foo_car bar = 10 => idtac
+end.
+rewrite /foo_car.
+(*
+Fail match goal with
+| |- foo_car bar = 10 => idtac
+end.
+*)
+Admitted.
+
+End T2.
+
+
+Module T3.
+
+Record foo {A} := Foo { foo_car : A }.
+
+Definition bar : foo := Foo nat 10.
+
+Goal foo_car bar = 10.
+Proof.
+rewrite -[foo_car _]/(id _).
+match goal with |- id _ = 10 => idtac end.
+Admitted.
+
+Goal foo_car bar = 10.
+Proof.
+set x := foo_car _.
+match goal with |- x = 10 => idtac end.
+Admitted.
+
+End T3.
+
+Module T4.
+
+Inductive seal {A} (f : A) := { unseal : A; seal_eq : unseal = f }.
+Arguments unseal {_ _} _.
+Arguments seal_eq {_ _} _.
+
+Record uPred : Type := IProp { uPred_holds :> Prop }.
+
+Definition uPred_or_def (P Q : uPred) : uPred :=
+ {| uPred_holds := P \/ Q |}.
+Definition uPred_or_aux : seal (@uPred_or_def). by eexists. Qed.
+Definition uPred_or := unseal uPred_or_aux.
+Definition uPred_or_eq: @uPred_or = @uPred_or_def := seal_eq uPred_or_aux.
+
+Lemma foobar (P1 P2 Q : uPred) :
+ (P1 <-> P2) -> (uPred_or P1 Q) <-> (uPred_or P2 Q).
+Proof.
+ rewrite uPred_or_eq. (* This fails. *)
+Admitted.
+
+End T4.
+
+
+Module DesignFlaw.
+
+Record foo A := Foo { foo_car : A }.
+Definition bar : foo _ := Foo nat 10.
+
+Definition app (f : foo nat -> nat) x := f x.
+
+Goal app (foo_car _) bar = 10.
+Proof.
+unfold app. (* mkApp should produce a Proj *)
+Fail set x := (foo_car _ _).
+Admitted.
+
+End DesignFlaw.
+
+
+Module Bug.
+
+Record foo A := Foo { foo_car : A }.
+
+Definition bar : foo _ := Foo nat 10.
+
+Variable alias : forall A, foo A -> A.
+
+Parameter e : @foo_car = alias.
+
+Goal foo_car _ bar = alias _ bar.
+Proof.
+Fail rewrite e. (* Issue: #86 *)
+Admitted.
+
+End Bug.
diff --git a/test-suite/ssr/rewpatterns.v b/test-suite/ssr/rewpatterns.v
new file mode 100644
index 000000000..f7993f402
--- /dev/null
+++ b/test-suite/ssr/rewpatterns.v
@@ -0,0 +1,146 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+
+Require Import ssreflect.
+Require Import ssrbool ssrfun TestSuite.ssr_mini_mathcomp.
+
+Lemma test1 : forall x y (f : nat -> nat), f (x + y).+1 = f (y + x.+1).
+by move=> x y f; rewrite [_.+1](addnC x.+1).
+Qed.
+
+Lemma test2 : forall x y f, x + y + f (y + x) + f (y + x) = x + y + f (y + x) + f (x + y).
+by move=> x y f; rewrite {2}[in f _]addnC.
+Qed.
+
+Lemma test2' : forall x y f, true && f (x * (y + x)) = true && f(x * (x + y)).
+by move=> x y f; rewrite [in f _](addnC y).
+Qed.
+
+Lemma test2'' : forall x y f, f (y + x) + f(y + x) + f(y + x) = f(x + y) + f(y + x) + f(x + y).
+by move=> x y f; rewrite {1 3}[in f _](addnC y).
+Qed.
+
+(* patterns catching bound vars not supported *)
+Lemma test2_1 : forall x y f, true && (let z := x in f (z * (y + x))) = true && f(x * (x + y)).
+by move=> x y f; rewrite [in f _](addnC x). (* put y when bound var will be OK *)
+Qed.
+
+Lemma test3 : forall x y f, x + f (x + y) (f (y + x) x) = x + f (x + y) (f (x + y) x).
+by move=> x y f; rewrite [in X in (f _ X)](addnC y).
+Qed.
+
+Lemma test3' : forall x y f, x = y -> x + f (x + x) x + f (x + x) x =
+ x + f (x + y) x + f (y + x) x.
+by move=> x y f E; rewrite {2 3}[in X in (f X _)]E.
+Qed.
+
+Lemma test3'' : forall x y f, x = y -> x + f (x + y) x + f (x + y) x =
+ x + f (x + y) x + f (y + y) x.
+by move=> x y f E; rewrite {2}[in X in (f X _)]E.
+Qed.
+
+Lemma test4 : forall x y f, x = y -> x + f (fun _ : nat => x + x) x + f (fun _ => x + x) x =
+ x + f (fun _ => x + y) x + f (fun _ => y + x) x.
+by move=> x y f E; rewrite {2 3}[in X in (f X _)]E.
+Qed.
+
+Lemma test4' : forall x y f, x = y -> x + f (fun _ _ _ : nat => x + x) x =
+ x + f (fun _ _ _ => x + y) x.
+by move=> x y f E; rewrite {2}[in X in (f X _)]E.
+Qed.
+
+Lemma test5 : forall x y f, x = y -> x + f (y + x) x + f (y + x) x =
+ x + f (x + y) x + f (y + x) x.
+by move=> x y f E; rewrite {1}[X in (f X _)]addnC.
+Qed.
+
+Lemma test3''' : forall x y f, x = y -> x + f (x + y) x + f (x + y) (x + y) =
+ x + f (x + y) x + f (y + y) (x + y).
+by move=> x y f E; rewrite {1}[in X in (f X X)]E.
+Qed.
+
+Lemma test3'''' : forall x y f, x = y -> x + f (x + y) x + f (x + y) (x + y) =
+ x + f (x + y) x + f (y + y) (y + y).
+by move=> x y f E; rewrite [in X in (f X X)]E.
+Qed.
+
+Lemma test3x : forall x y f, y+y = x+y -> x + f (x + y) x + f (x + y) (x + y) =
+ x + f (x + y) x + f (y + y) (y + y).
+by move=> x y f E; rewrite -[X in (f X X)]E.
+Qed.
+
+Lemma test6 : forall x y (f : nat -> nat), f (x + y).+1 = f (y.+1 + x).
+by move=> x y f; rewrite [(x + y) in X in (f X)]addnC.
+Qed.
+
+Lemma test7 : forall x y (f : nat -> nat), f (x + y).+1 = f (y + x.+1).
+by move=> x y f; rewrite [(x.+1 + y) as X in (f X)]addnC.
+Qed.
+
+Lemma manual x y z (f : nat -> nat -> nat) : (x + y).+1 + f (x.+1 + y) (z + (x + y).+1) = 0.
+Proof.
+rewrite [in f _]addSn.
+match goal with |- (x + y).+1 + f (x + y).+1 (z + (x + y).+1) = 0 => idtac end.
+rewrite -[X in _ = X]addn0.
+match goal with |- (x + y).+1 + f (x + y).+1 (z + (x + y).+1) = 0 + 0 => idtac end.
+rewrite -{2}[in X in _ = X](addn0 0).
+match goal with |- (x + y).+1 + f (x + y).+1 (z + (x + y).+1) = 0 + (0 + 0) => idtac end.
+rewrite [_.+1 in X in f _ X](addnC x.+1).
+match goal with |- (x + y).+1 + f (x + y).+1 (z + (y + x.+1)) = 0 + (0 + 0) => idtac end.
+rewrite [x.+1 + y as X in f X _]addnC.
+match goal with |- (x + y).+1 + f (y + x.+1) (z + (y + x.+1)) = 0 + (0 + 0) => idtac end.
+Admitted.
+
+Goal (exists x : 'I_3, x > 0).
+apply: (ex_intro _ (@Ordinal _ 2 _)).
+Admitted.
+
+Goal (forall y, 1 < y < 2 -> exists x : 'I_3, x > 0).
+move=> y; case/andP=> y_gt1 y_lt2; apply: (ex_intro _ (@Ordinal _ y _)).
+ by apply: leq_trans y_lt2 _.
+by move=> y_lt3; apply: leq_trans _ y_gt1.
+Qed.
+
+Goal (forall x y : nat, forall P : nat -> Prop, x = y -> True).
+move=> x y P E.
+have: P x -> P y by suff: x = y by move=> ?; congr (P _).
+Admitted.
+
+Goal forall a : bool, a -> true && a || false && a.
+by move=> a ?; rewrite [true && _]/= [_ && a]/= orbC [_ || _]//=.
+Qed.
+
+Goal forall a : bool, a -> true && a || false && a.
+by move=> a ?; rewrite [X in X || _]/= [X in _ || X]/= orbC [false && a as X in X || _]//=.
+Qed.
+
+Variable a : bool.
+Definition f x := x || a.
+Definition g x := f x.
+
+Goal a -> g false.
+by move=> Ha; rewrite [g _]/f orbC Ha.
+Qed.
+
+Goal a -> g false || g false.
+move=> Ha; rewrite {2}[g _]/f orbC Ha.
+match goal with |- (is_true (false || true || g false)) => done end.
+Qed.
+
+Goal a -> (a && a || true && a) && true.
+by move=> Ha; rewrite -[_ || _]/(g _) andbC /= Ha [g _]/f.
+Qed.
+
+Goal a -> (a || a) && true.
+by move=> Ha; rewrite -[in _ || _]/(f _) Ha andbC /f.
+Qed.
diff --git a/test-suite/ssr/set_lamda.v b/test-suite/ssr/set_lamda.v
new file mode 100644
index 000000000..a012ec680
--- /dev/null
+++ b/test-suite/ssr/set_lamda.v
@@ -0,0 +1,27 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrbool ssrfun.
+Require Import TestSuite.ssr_mini_mathcomp.
+
+Set Implicit Arguments.
+Unset Strict Implicit.
+Import Prenex Implicits.
+
+(* error 2 *)
+
+Goal (exists f: Set -> nat, f nat = 0).
+Proof. set (f:= fun _:Set =>0). by exists f. Qed.
+
+Goal (exists f: Set -> nat, f nat = 0).
+Proof. set f := (fun _:Set =>0). by exists f. Qed.
diff --git a/test-suite/ssr/set_pattern.v b/test-suite/ssr/set_pattern.v
new file mode 100644
index 000000000..3ce75e879
--- /dev/null
+++ b/test-suite/ssr/set_pattern.v
@@ -0,0 +1,64 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+
+Axiom daemon : False. Ltac myadmit := case: daemon.
+
+Ltac T1 x := match goal with |- _ => set t := (x in X in _ = X) end.
+Ltac T2 x := first [set t := (x in RHS)].
+Ltac T3 x := first [set t := (x in Y in _ = Y)|idtac].
+Ltac T4 x := set t := (x in RHS); idtac.
+Ltac T5 x := match goal with |- _ => set t := (x in RHS) | |- _ => idtac end.
+
+Require Import ssrbool TestSuite.ssr_mini_mathcomp.
+
+Open Scope nat_scope.
+
+Lemma foo x y : x.+1 = y + x.+1.
+set t := (_.+1 in RHS). match goal with |- x.+1 = y + t => rewrite /t {t} end.
+set t := (x in RHS). match goal with |- x.+1 = y + t.+1 => rewrite /t {t} end.
+set t := (x in _ = x). match goal with |- x.+1 = t => rewrite /t {t} end.
+set t := (x in X in _ = X).
+ match goal with |- x.+1 = y + t.+1 => rewrite /t {t} end.
+set t := (x in RHS). match goal with |- x.+1 = y + t.+1 => rewrite /t {t} end.
+set t := (y + (1 + x) as X in _ = X).
+ match goal with |- x.+1 = t => rewrite /t addSn add0n {t} end.
+set t := x.+1. match goal with |- t = y + t => rewrite /t {t} end.
+set t := (x).+1. match goal with |- t = y + t => rewrite /t {t} end.
+set t := ((x).+1 in X in _ = X).
+ match goal with |- x.+1 = y + t => rewrite /t {t} end.
+set t := (x.+1 in RHS). match goal with |- x.+1 = y + t => rewrite /t {t} end.
+T1 (x.+1). match goal with |- x.+1 = y + t => rewrite /t {t} end.
+T2 (x.+1). match goal with |- x.+1 = y + t => rewrite /t {t} end.
+T3 (x.+1). match goal with |- x.+1 = y + t => rewrite /t {t} end.
+T4 (x.+1). match goal with |- x.+1 = y + t => rewrite /t {t} end.
+T5 (x.+1). match goal with |- x.+1 = y + t => rewrite /t {t} end.
+rewrite [RHS]addnC.
+ match goal with |- x.+1 = x.+1 + y => rewrite -[RHS]addnC end.
+rewrite -[in RHS](@subnK 1 x.+1) //.
+ match goal with |- x.+1 = y + (x.+1 - 1 + 1) => rewrite subnK // end.
+have H : x.+1 = y by myadmit.
+set t := _.+1 in H |- *.
+ match goal with H : t = y |- t = y + t => rewrite /t {t} in H * end.
+set t := (_.+1 in X in _ + X) in H |- *.
+ match goal with H : x.+1 = y |- x.+1 = y + t => rewrite /t {t} in H * end.
+set t := 0. match goal with t := 0 |- x.+1 = y + x.+1 => clear t end.
+set t := y + _. match goal with |- x.+1 = t => rewrite /t {t} end.
+set t : nat := 0. clear t.
+set t : nat := (x in RHS).
+ match goal with |- x.+1 = y + t.+1 => rewrite /t {t} end.
+set t : nat := RHS. match goal with |- x.+1 = t => rewrite /t {t} end.
+(* set t := 0 + _. *)
+(* set t := (x).+1 in X in _ + X in H |-. *)
+(* set t := (x).+1 in X in _ = X.*)
+Admitted.
diff --git a/test-suite/ssr/ssrsyntax2.v b/test-suite/ssr/ssrsyntax2.v
new file mode 100644
index 000000000..af839fabd
--- /dev/null
+++ b/test-suite/ssr/ssrsyntax2.v
@@ -0,0 +1,20 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import TestSuite.ssr_ssrsyntax1.
+Require Import Arith.
+
+Goal (forall a b, a + b = b + a).
+intros.
+rewrite plus_comm, plus_comm.
+split.
+Qed.
diff --git a/test-suite/ssr/tc.v b/test-suite/ssr/tc.v
new file mode 100644
index 000000000..ae4589ef3
--- /dev/null
+++ b/test-suite/ssr/tc.v
@@ -0,0 +1,39 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+
+
+Class foo (A : Type) : Type := mkFoo { val : A }.
+Instance foo_pair {A B} {f1 : foo A} {f2 : foo B} : foo (A * B) | 2 :=
+ {| val := (@val _ f1, @val _ f2) |}.
+Instance foo_nat : foo nat | 3 := {| val := 0 |}.
+
+Definition id {A} (x : A) := x.
+Axiom E : forall A {f : foo A} (a : A), id a = (@val _ f).
+
+Lemma test (x : nat) : id true = true -> id x = 0.
+Proof.
+Fail move=> _; reflexivity.
+Timeout 2 rewrite E => _; reflexivity.
+Qed.
+
+Definition P {A} (x : A) : Prop := x = x.
+Axiom V : forall A {f : foo A} (x:A), P x -> P (id x).
+
+Lemma test1 (x : nat) : P x -> P (id x).
+Proof.
+move=> px.
+Timeout 2 Fail move/V: px.
+Timeout 2 move/V : (px) => _.
+move/(V nat) : px => H; exact H.
+Qed.
diff --git a/test-suite/ssr/typeof.v b/test-suite/ssr/typeof.v
new file mode 100644
index 000000000..ca121fdb3
--- /dev/null
+++ b/test-suite/ssr/typeof.v
@@ -0,0 +1,22 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+
+Ltac mycut x :=
+ let tx := type of x in
+ cut tx.
+
+Lemma test : True.
+Proof.
+by mycut I=> [ x | ]; [ exact x | exact I ].
+Qed.
diff --git a/test-suite/ssr/unfold_Opaque.v b/test-suite/ssr/unfold_Opaque.v
new file mode 100644
index 000000000..7c2b51de4
--- /dev/null
+++ b/test-suite/ssr/unfold_Opaque.v
@@ -0,0 +1,18 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+Require Import ssreflect.
+
+Definition x := 3.
+Opaque x.
+
+Goal x = 3.
+Fail rewrite /x.
+Admitted.
diff --git a/test-suite/ssr/unkeyed.v b/test-suite/ssr/unkeyed.v
new file mode 100644
index 000000000..710941c30
--- /dev/null
+++ b/test-suite/ssr/unkeyed.v
@@ -0,0 +1,31 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrfun ssrbool TestSuite.ssr_mini_mathcomp.
+
+Set Implicit Arguments.
+Unset Strict Implicit.
+Import Prenex Implicits.
+
+Lemma test0 (a b : unit) f : a = f b.
+Proof. by rewrite !unitE. Qed.
+
+Lemma phE T : all_equal_to (Phant T). Proof. by case. Qed.
+
+Lemma test1 (a b : phant nat) f : a = f b.
+Proof. by rewrite !phE. Qed.
+
+Lemma eq_phE (T : eqType) : all_equal_to (Phant T). Proof. by case. Qed.
+
+Lemma test2 (a b : phant bool) f : a = locked (f b).
+Proof. by rewrite !eq_phE. Qed.
diff --git a/test-suite/ssr/view_case.v b/test-suite/ssr/view_case.v
new file mode 100644
index 000000000..2721470c4
--- /dev/null
+++ b/test-suite/ssr/view_case.v
@@ -0,0 +1,31 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrbool TestSuite.ssr_mini_mathcomp.
+
+Axiom P : forall T, seq T -> Prop.
+
+Goal (forall T (s : seq T), P _ s).
+move=> T s.
+elim: s => [| x /lastP [| s] IH].
+Admitted.
+
+Goal forall x : 'I_1, x = 0 :> nat.
+move=> /ord1 -> /=; exact: refl_equal.
+Qed.
+
+Goal forall x : 'I_1, x = 0 :> nat.
+move=> x.
+move=> /ord1 -> in x |- *.
+exact: refl_equal.
+Qed.
diff --git a/test-suite/ssr/wlog_suff.v b/test-suite/ssr/wlog_suff.v
new file mode 100644
index 000000000..43a8f3b8b
--- /dev/null
+++ b/test-suite/ssr/wlog_suff.v
@@ -0,0 +1,28 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrbool.
+
+Lemma test b : b || ~~b.
+wlog _ : b / b = true.
+ case: b; [ by apply | by rewrite orbC ].
+wlog suff: b / b || ~~b.
+ by case: b.
+by case: b.
+Qed.
+
+Lemma test2 b c (H : c = b) : b || ~~b.
+wlog _ : b {c H} / b = true.
+ by case: b H.
+by case: b.
+Qed.
diff --git a/test-suite/ssr/wlogletin.v b/test-suite/ssr/wlogletin.v
new file mode 100644
index 000000000..64e1ea84f
--- /dev/null
+++ b/test-suite/ssr/wlogletin.v
@@ -0,0 +1,50 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrbool.
+Require Import TestSuite.ssr_mini_mathcomp.
+
+Variable T : Type.
+Variables P : T -> Prop.
+
+Definition f := fun x y : T => x.
+
+Lemma test1 : forall x y : T, P (f x y) -> P x.
+Proof.
+move=> x y; set fxy := f x y; move=> Pfxy.
+wlog H : @fxy Pfxy / P x.
+ match goal with |- (let fxy0 := f x y in P fxy0 -> P x -> P x) -> P x => by auto | _ => fail end.
+exact: H.
+Qed.
+
+Lemma test2 : forall x y : T, P (f x y) -> P x.
+Proof.
+move=> x y; set fxy := f x y; move=> Pfxy.
+wlog H : fxy Pfxy / P x.
+ match goal with |- (forall fxy, P fxy -> P x -> P x) -> P x => by auto | _ => fail end.
+exact: H.
+Qed.
+
+Lemma test3 : forall x y : T, P (f x y) -> P x.
+Proof.
+move=> x y; set fxy := f x y; move=> Pfxy.
+move: {1}@fxy (Pfxy) (Pfxy).
+match goal with |- (let fxy0 := f x y in P fxy0 -> P fxy -> P x) => by auto | _ => fail end.
+Qed.
+
+Lemma test4 : forall n m z: bool, n = z -> let x := n in x = m && n -> x = m && n.
+move=> n m z E x H.
+case: true.
+ by rewrite {1 2}E in (x) H |- *.
+by rewrite {1}E in x H |- *.
+Qed.
diff --git a/test-suite/ssr/wlong_intro.v b/test-suite/ssr/wlong_intro.v
new file mode 100644
index 000000000..dd80f0435
--- /dev/null
+++ b/test-suite/ssr/wlong_intro.v
@@ -0,0 +1,20 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(* (c) Copyright 2006-2016 Microsoft Corporation and Inria. *)
+
+Require Import ssreflect.
+Require Import ssrbool.
+Require Import TestSuite.ssr_mini_mathcomp.
+
+Goal (forall x y : nat, True).
+move=> x y.
+wlog suff: x y / x <= y.
+Admitted.
diff --git a/test-suite/unit-tests/.merlin b/test-suite/unit-tests/.merlin
new file mode 100644
index 000000000..b2279de74
--- /dev/null
+++ b/test-suite/unit-tests/.merlin
@@ -0,0 +1,6 @@
+REC
+
+S **
+B **
+
+PKG oUnit
diff --git a/test-suite/unit-tests/clib/inteq.ml b/test-suite/unit-tests/clib/inteq.ml
new file mode 100644
index 000000000..c07ec293f
--- /dev/null
+++ b/test-suite/unit-tests/clib/inteq.ml
@@ -0,0 +1,13 @@
+open Utest
+
+let eq0 = mk_bool_test "clib-inteq0"
+ "Int.equal on 0"
+ (Int.equal 0 0)
+
+let eq42 = mk_bool_test "clib-inteq42"
+ "Int.equal on 42"
+ (Int.equal 42 42)
+
+let tests = [ eq0; eq42 ]
+
+let _ = run_tests __FILE__ tests
diff --git a/test-suite/unit-tests/clib/unicode_tests.ml b/test-suite/unit-tests/clib/unicode_tests.ml
new file mode 100644
index 000000000..9ae405977
--- /dev/null
+++ b/test-suite/unit-tests/clib/unicode_tests.ml
@@ -0,0 +1,15 @@
+open Utest
+
+let unicode0 = mk_eq_test "clib-unicode0"
+ "split_at_first_letter, first letter is character"
+ None
+ (Unicode.split_at_first_letter "ident")
+
+let unicode1 = mk_eq_test "clib-unicode1"
+ "split_at_first_letter, first letter not character"
+ (Some ("__","ident"))
+ (Unicode.split_at_first_letter "__ident")
+
+let tests = [ unicode0; unicode1 ]
+
+let _ = run_tests __FILE__ tests
diff --git a/test-suite/unit-tests/src/utest.ml b/test-suite/unit-tests/src/utest.ml
new file mode 100644
index 000000000..069e6a4bf
--- /dev/null
+++ b/test-suite/unit-tests/src/utest.ml
@@ -0,0 +1,74 @@
+open OUnit
+
+(* general case to build a test *)
+let mk_test nm test = nm >: test
+
+(* common cases for building tests *)
+let mk_eq_test nm descr expected actual =
+ mk_test nm (TestCase (fun _ -> assert_equal ~msg:descr expected actual))
+
+let mk_bool_test nm descr actual =
+ mk_test nm (TestCase (fun _ -> assert_bool descr actual))
+
+let cfprintf oc = Printf.(kfprintf (fun oc -> fprintf oc "\n%!") oc)
+
+(* given test result, print message, return success boolean *)
+let logger out_ch result =
+ let cprintf s = cfprintf out_ch s in
+ match result with
+ | RSuccess path ->
+ cprintf "TEST SUCCEEDED: %s" (string_of_path path);
+ true
+ | RError (path,msg)
+ | RFailure (path,msg) ->
+ cprintf "TEST FAILED: %s (%s)" (string_of_path path) msg;
+ false
+ | RSkip (path,msg)
+ | RTodo (path,msg) ->
+ cprintf "TEST DID NOT SUCCEED: %s (%s)" (string_of_path path) msg;
+ false
+
+(* run one OUnit test case, return successes, no. of tests *)
+(* notionally one test, which might be a TestList *)
+let run_one logit test =
+ let rec process_results rs =
+ match rs with
+ [] -> (0,0)
+ | (r::rest) ->
+ let succ = if logit r then 1 else 0 in
+ let succ_results,tot_results = process_results rest in
+ (succ + succ_results,tot_results + 1)
+ in
+ let results = perform_test (fun _ -> ()) test in
+ process_results results
+
+(* run list of OUnit test cases, log results *)
+let run_tests ml_fn tests =
+ let log_fn = ml_fn ^ ".log" in
+ let out_ch = open_out log_fn in
+ let cprintf s = cfprintf out_ch s in
+ let ceprintf s = cfprintf stderr s in
+ let logit = logger out_ch in
+ let rec run_some tests succ tot =
+ match tests with
+ [] -> (succ,tot)
+ | (t::ts) ->
+ let succ_one,tot_one = run_one logit t in
+ run_some ts (succ + succ_one) (tot + tot_one)
+ in
+ (* format for test-suite summary to find status
+ success if all tests succeeded, else failure
+ *)
+ let succ,tot = run_some tests 0 0 in
+ cprintf
+ "*** Ran %d tests, with %d successes and %d failures ***"
+ tot succ (tot - succ);
+ if succ = tot then
+ cprintf
+ "==========> SUCCESS <==========\n %s...Ok" ml_fn
+ else begin
+ cprintf
+ "==========> FAILURE <==========\n %s...Error!" ml_fn;
+ ceprintf "FAILED %s.log" ml_fn
+ end;
+ close_out out_ch
diff --git a/test-suite/unit-tests/src/utest.mli b/test-suite/unit-tests/src/utest.mli
new file mode 100644
index 000000000..70928228b
--- /dev/null
+++ b/test-suite/unit-tests/src/utest.mli
@@ -0,0 +1,12 @@
+(** give a name to a unit test *)
+val mk_test : string -> OUnit.test -> OUnit.test
+
+(** simple ways to build a test *)
+val mk_eq_test : string -> string -> 'a -> 'a -> OUnit.test
+val mk_bool_test : string -> string -> bool -> OUnit.test
+
+(** run unit tests *)
+(* the string argument should be the name of the .ml file
+ containing the tests; use __FILE__ for that purpose.
+ *)
+val run_tests : string -> OUnit.test list -> unit
diff --git a/vernac/comDefinition.ml b/vernac/comDefinition.ml
index 9aa61ab46..863adb0d1 100644
--- a/vernac/comDefinition.ml
+++ b/vernac/comDefinition.ml
@@ -90,7 +90,7 @@ let interp_definition pl bl poly red_option c ctypopt =
Note: in program mode some evars may remain. *)
let ctx = List.map Termops.(map_rel_decl (to_constr ~abort_on_undefined_evars:false evd)) ctx in
let c = Term.it_mkLambda_or_LetIn (EConstr.to_constr ~abort_on_undefined_evars:false evd c) ctx in
- let tyopt = Option.map (fun ty -> Term.it_mkProd_or_LetIn (EConstr.to_constr evd ty) ctx) tyopt in
+ let tyopt = Option.map (fun ty -> Term.it_mkProd_or_LetIn (EConstr.to_constr ~abort_on_undefined_evars:false evd ty) ctx) tyopt in
(* Keep only useful universes. *)
let uvars_fold uvars c =
Univ.LSet.union uvars (universes_of_constr env evd (of_constr c))
@@ -118,7 +118,7 @@ let do_definition ~program_mode ident k univdecl bl red_option c ctypopt hook =
assert(Univ.ContextSet.is_empty ctx);
let typ = match ce.const_entry_type with
| Some t -> t
- | None -> EConstr.to_constr evd (Retyping.get_type_of env evd (EConstr.of_constr c))
+ | None -> EConstr.to_constr ~abort_on_undefined_evars:false evd (Retyping.get_type_of env evd (EConstr.of_constr c))
in
Obligations.check_evars env evd;
let obls, _, c, cty =
diff --git a/vernac/metasyntax.ml b/vernac/metasyntax.ml
index feeca6075..76958b05f 100644
--- a/vernac/metasyntax.ml
+++ b/vernac/metasyntax.ml
@@ -738,12 +738,12 @@ let cache_one_syntax_extension se =
let prec = se.synext_level in
let onlyprint = se.synext_notgram.notgram_onlyprinting in
try
- let oldprec = Notation.level_of_notation ntn in
+ let oldprec = Notation.level_of_notation ~onlyprint ntn in
if not (Notation.level_eq prec oldprec) then error_incompatible_level ntn oldprec prec;
with Not_found ->
if is_active_compat se.synext_compat then begin
(* Reserve the notation level *)
- Notation.declare_notation_level ntn prec;
+ Notation.declare_notation_level ntn prec ~onlyprint;
(* Declare the parsing rule *)
if not onlyprint then List.iter (check_and_extend_constr_grammar ntn) se.synext_notgram.notgram_rules;
(* Declare the notation rule *)
@@ -1274,7 +1274,7 @@ exception NoSyntaxRule
let recover_notation_syntax ntn =
try
- let prec = Notation.level_of_notation ntn in
+ let prec = Notation.level_of_notation ~onlyprint:true ntn (* Be as little restrictive as possible *) in
let pp_rule,_ = Notation.find_notation_printing_rule ntn in
let pp_extra_rules = Notation.find_notation_extra_printing_rules ntn in
let pa_rule = Notation.find_notation_parsing_rules ntn in