aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.circleci/config.yml13
-rw-r--r--.github/PULL_REQUEST_TEMPLATE.md2
-rw-r--r--.gitignore1
-rw-r--r--.travis.yml102
-rw-r--r--CHANGES38
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--INSTALL.ide4
-rw-r--r--META.coq314
-rw-r--r--Makefile.build38
-rw-r--r--Makefile.checker9
-rw-r--r--Makefile.ci7
-rw-r--r--Makefile.ide4
-rw-r--r--README.md1
-rw-r--r--checker/checker.ml5
-rw-r--r--checker/checker.mli9
-rw-r--r--checker/cic.mli12
-rw-r--r--checker/closure.ml46
-rw-r--r--checker/closure.mli14
-rw-r--r--checker/declarations.ml4
-rw-r--r--checker/environ.ml39
-rw-r--r--checker/environ.mli7
-rw-r--r--checker/indtypes.ml34
-rw-r--r--checker/inductive.ml16
-rw-r--r--checker/main.mli10
-rw-r--r--checker/mod_checking.ml11
-rw-r--r--checker/print.mli11
-rw-r--r--checker/reduction.ml60
-rw-r--r--checker/univ.ml42
-rw-r--r--checker/univ.mli17
-rw-r--r--checker/validate.ml2
-rw-r--r--checker/validate.mli9
-rw-r--r--checker/values.ml40
-rw-r--r--checker/values.mli26
-rw-r--r--checker/votour.ml6
-rw-r--r--checker/votour.mli10
-rw-r--r--clib/clib.mllib1
-rw-r--r--clib/range.ml91
-rw-r--r--clib/range.mli37
-rw-r--r--configure.ml58
-rw-r--r--default.nix1
-rw-r--r--dev/README30
-rw-r--r--dev/base_include2
-rwxr-xr-xdev/build/osx/make-macos-dmg.sh2
-rw-r--r--dev/build/windows/patches_coq/coq_new.nsi2
-rw-r--r--dev/ci/README.md2
-rw-r--r--dev/ci/appveyor.bat2
-rw-r--r--dev/ci/ci-basic-overlay.sh104
-rw-r--r--dev/ci/ci-common.sh45
-rwxr-xr-xdev/ci/ci-compcert.sh2
-rwxr-xr-xdev/ci/ci-iris-lambda-rust.sh4
-rw-r--r--dev/ci/user-overlays/06482-ppedrot-check-poly-effects.sh4
-rw-r--r--dev/ci/user-overlays/06535-fix-push-rel-to-named.sh4
-rw-r--r--dev/ci/user-overlays/06686-ccnv-no-proj.sh4
-rw-r--r--dev/db95
-rw-r--r--dev/doc/COMPATIBILITY (renamed from COMPATIBILITY)7
-rw-r--r--dev/doc/changes.md11
-rw-r--r--dev/doc/debugging.md27
-rw-r--r--dev/doc/setup.txt24
-rw-r--r--dev/include1
-rwxr-xr-xdev/lint-repository.sh13
-rwxr-xr-xdev/nsis/coq.nsi2
-rw-r--r--dev/ocamldebug-coq.run2
-rw-r--r--dev/set_raw_db1
-rwxr-xr-xdev/tools/backport-pr.sh16
-rwxr-xr-xdev/tools/check-eof-newline.sh19
-rwxr-xr-xdev/tools/github-check-prs.py47
-rwxr-xr-xdev/tools/merge-pr.sh20
-rwxr-xr-xdev/tools/should-check-whitespace.sh6
-rwxr-xr-xdev/tools/sudo-apt-get-update.sh4
-rw-r--r--dev/top_printers.ml15
-rw-r--r--dev/top_printers.mli173
-rw-r--r--dev/vm_printers.ml2
-rw-r--r--doc/refman/AsyncProofs.tex2
-rw-r--r--doc/refman/RefMan-ide.tex86
-rw-r--r--doc/refman/RefMan-ltac.tex10
-rw-r--r--doc/refman/RefMan-oth.tex9
-rw-r--r--doc/refman/RefMan-pre.tex10
-rw-r--r--doc/refman/RefMan-pro.tex17
-rw-r--r--doc/refman/Universes.tex39
-rw-r--r--doc/refman/coqide-queries.pngbin27316 -> 66656 bytes
-rw-r--r--doc/refman/coqide.pngbin20953 -> 59662 bytes
-rw-r--r--engine/eConstr.ml5
-rw-r--r--engine/eConstr.mli1
-rw-r--r--engine/evarutil.ml119
-rw-r--r--engine/evarutil.mli5
-rw-r--r--engine/evd.ml2
-rw-r--r--engine/logic_monad.ml1
-rw-r--r--engine/logic_monad.mli1
-rw-r--r--engine/proofview.ml5
-rw-r--r--engine/proofview.mli2
-rw-r--r--engine/termops.ml12
-rw-r--r--engine/termops.mli10
-rw-r--r--engine/uState.ml22
-rw-r--r--engine/universes.ml89
-rw-r--r--engine/universes.mli11
-rw-r--r--ide/config_lexer.mli10
-rw-r--r--ide/coq_commands.mli11
-rw-r--r--ide/coq_lex.mli11
-rw-r--r--ide/coq_lex.mll10
-rw-r--r--ide/coqide.ml11
-rw-r--r--ide/coqide_main.ml43
-rw-r--r--ide/coqide_main.mli10
-rw-r--r--ide/coqide_ui.mli10
-rw-r--r--ide/gtk_parsing.ml109
-rw-r--r--ide/gtk_parsing.mli26
-rw-r--r--ide/ide_slave.ml10
-rw-r--r--ide/ide_slave.mli10
-rw-r--r--ide/ideutils.ml7
-rw-r--r--ide/ideutils.mli2
-rw-r--r--ide/macos_prehook.mli10
-rw-r--r--ide/nanoPG.mli11
-rw-r--r--ide/session.ml5
-rw-r--r--ide/utf8_convert.mli9
-rw-r--r--ide/wg_Find.ml61
-rwxr-xr-xinstall.sh8
-rw-r--r--interp/constrexpr_ops.ml8
-rw-r--r--interp/constrexpr_ops.mli2
-rw-r--r--interp/constrextern.ml3
-rw-r--r--interp/constrintern.ml24
-rw-r--r--interp/declare.ml12
-rw-r--r--interp/discharge.ml6
-rw-r--r--interp/impargs.ml2
-rw-r--r--interp/notation_ops.ml19
-rw-r--r--intf/constrexpr.ml1
-rw-r--r--intf/glob_term.ml1
-rw-r--r--intf/notation_term.ml1
-rw-r--r--intf/pattern.ml2
-rw-r--r--intf/vernacexpr.ml40
-rw-r--r--kernel/cClosure.ml59
-rw-r--r--kernel/cClosure.mli4
-rw-r--r--kernel/cbytegen.ml18
-rw-r--r--kernel/constr.ml5
-rw-r--r--kernel/constr.mli4
-rw-r--r--kernel/cooking.ml54
-rw-r--r--kernel/csymtable.ml6
-rw-r--r--kernel/csymtable.mli2
-rw-r--r--kernel/declarations.ml1
-rw-r--r--kernel/declareops.ml3
-rw-r--r--kernel/declareops.mli2
-rw-r--r--kernel/environ.ml54
-rw-r--r--kernel/environ.mli4
-rw-r--r--kernel/indtypes.ml30
-rw-r--r--kernel/inductive.ml24
-rw-r--r--kernel/kernel.mllib1
-rw-r--r--kernel/mod_typing.ml4
-rw-r--r--kernel/names.mli9
-rw-r--r--kernel/nativecode.ml29
-rw-r--r--kernel/nativecode.mli2
-rw-r--r--kernel/nativeconv.ml11
-rw-r--r--kernel/nativeinstr.mli2
-rw-r--r--kernel/nativelambda.ml7
-rw-r--r--kernel/nativelib.ml5
-rw-r--r--kernel/nativevalues.ml18
-rw-r--r--kernel/nativevalues.mli6
-rw-r--r--kernel/opaqueproof.ml2
-rw-r--r--kernel/opaqueproof.mli2
-rw-r--r--kernel/pre_env.ml55
-rw-r--r--kernel/pre_env.mli20
-rw-r--r--kernel/reduction.ml308
-rw-r--r--kernel/reduction.mli22
-rw-r--r--kernel/term.ml8
-rw-r--r--kernel/term.mli16
-rw-r--r--kernel/term_typing.ml32
-rw-r--r--kernel/univ.ml207
-rw-r--r--kernel/univ.mli76
-rw-r--r--kernel/vars.ml43
-rw-r--r--kernel/vars.mli6
-rw-r--r--kernel/vconv.ml1
-rw-r--r--kernel/vconv.mli2
-rw-r--r--kernel/vm.ml546
-rw-r--r--kernel/vm.mli106
-rw-r--r--kernel/vmvalues.ml526
-rw-r--r--kernel/vmvalues.mli144
-rw-r--r--lib/coqProject_file.ml42
-rw-r--r--lib/feedback.mli5
-rw-r--r--lib/flags.ml18
-rw-r--r--library/globnames.ml2
-rw-r--r--library/lib.ml49
-rw-r--r--library/lib.mli11
-rw-r--r--parsing/g_proofs.ml43
-rw-r--r--parsing/g_vernac.ml448
-rw-r--r--plugins/firstorder/formula.ml3
-rw-r--r--plugins/funind/functional_principles_proofs.ml15
-rw-r--r--plugins/funind/functional_principles_types.mli4
-rw-r--r--plugins/funind/g_indfun.ml42
-rw-r--r--plugins/funind/glob_term_to_relation.ml8
-rw-r--r--plugins/funind/glob_termops.ml166
-rw-r--r--plugins/funind/glob_termops.mli30
-rw-r--r--plugins/funind/indfun.ml3
-rw-r--r--plugins/funind/indfun_common.ml1
-rw-r--r--plugins/funind/invfun.ml22
-rw-r--r--plugins/funind/invfun.mli17
-rw-r--r--plugins/funind/merge.ml1013
-rw-r--r--plugins/funind/recdef.mli1
-rw-r--r--plugins/funind/recdef_plugin.mlpack1
-rw-r--r--plugins/ltac/extratactics.ml49
-rw-r--r--plugins/ltac/g_ltac.ml43
-rw-r--r--plugins/ltac/rewrite.ml13
-rw-r--r--plugins/omega/coq_omega.ml2
-rw-r--r--plugins/ssr/ssrcommon.ml4
-rw-r--r--plugins/ssr/ssrvernac.ml44
-rw-r--r--pretyping/arguments_renaming.ml8
-rw-r--r--pretyping/cases.ml6
-rw-r--r--pretyping/cbv.ml2
-rw-r--r--pretyping/constr_matching.ml10
-rw-r--r--pretyping/detyping.ml14
-rw-r--r--pretyping/evarconv.ml19
-rw-r--r--pretyping/evardefine.ml4
-rw-r--r--pretyping/glob_ops.ml10
-rw-r--r--pretyping/inductiveops.ml146
-rw-r--r--pretyping/inductiveops.mli9
-rw-r--r--pretyping/inferCumulativity.ml224
-rw-r--r--pretyping/inferCumulativity.mli10
-rw-r--r--pretyping/nativenorm.ml28
-rw-r--r--pretyping/patternops.ml6
-rw-r--r--pretyping/pretyping.ml12
-rw-r--r--pretyping/pretyping.mllib1
-rw-r--r--pretyping/recordops.ml27
-rw-r--r--pretyping/reductionops.ml92
-rw-r--r--pretyping/reductionops.mli6
-rw-r--r--pretyping/tacred.ml16
-rw-r--r--pretyping/typeclasses.ml3
-rw-r--r--pretyping/typing.ml5
-rw-r--r--pretyping/typing.mli1
-rw-r--r--pretyping/unification.ml10
-rw-r--r--pretyping/vnorm.ml18
-rw-r--r--printing/ppconstr.ml3
-rw-r--r--printing/ppvernac.ml82
-rw-r--r--printing/prettyp.ml11
-rw-r--r--printing/printer.ml4
-rw-r--r--printing/printer.mli3
-rw-r--r--printing/printmod.ml13
-rw-r--r--proofs/clenv.ml2
-rw-r--r--proofs/logic.ml4
-rw-r--r--proofs/proof_global.ml18
-rw-r--r--proofs/tacmach.ml2
-rw-r--r--stm/asyncTaskQueue.mli6
-rw-r--r--stm/proofBlockDelimiter.ml4
-rw-r--r--stm/proofworkertop.ml2
-rw-r--r--stm/queryworkertop.ml2
-rw-r--r--stm/stm.ml188
-rw-r--r--stm/stm.mli73
-rw-r--r--stm/tacworkertop.ml2
-rw-r--r--stm/vernac_classifier.ml31
-rw-r--r--stm/workerLoop.ml4
-rw-r--r--stm/workerLoop.mli2
-rw-r--r--tactics/class_tactics.ml2
-rw-r--r--tactics/equality.ml2
-rw-r--r--tactics/hipattern.ml61
-rw-r--r--tactics/ind_tables.ml3
-rw-r--r--tactics/tactics.ml8
-rw-r--r--test-suite/Makefile13
-rw-r--r--test-suite/README.md75
-rw-r--r--test-suite/bugs/closed/5286.v9
-rw-r--r--test-suite/bugs/closed/5726.v34
-rw-r--r--test-suite/bugs/closed/6297.v8
-rw-r--r--test-suite/bugs/closed/6490.v4
-rw-r--r--test-suite/bugs/closed/6534.v7
-rw-r--r--test-suite/bugs/closed/6617.v34
-rw-r--r--test-suite/bugs/closed/6677.v5
-rw-r--r--test-suite/bugs/opened/6393.v11
-rw-r--r--test-suite/coq-makefile/emptyprefix/_CoqProject11
-rw-r--r--test-suite/coq-makefile/emptyprefix/_CoqProject.sub3
-rwxr-xr-xtest-suite/coq-makefile/emptyprefix/run.sh17
-rw-r--r--test-suite/coq-makefile/quick2vo/_CoqProject10
-rwxr-xr-xtest-suite/coq-makefile/quick2vo/run.sh12
-rwxr-xr-xtest-suite/coq-makefile/timing/run.sh8
-rw-r--r--test-suite/coq-makefile/vio2vo/_CoqProject10
-rwxr-xr-xtest-suite/coq-makefile/vio2vo/run.sh13
-rw-r--r--test-suite/coqchk/include.v11
-rw-r--r--test-suite/coqchk/primproj2.v10
-rw-r--r--test-suite/output/ErrorInCanonicalStructures.out5
-rw-r--r--test-suite/output/ErrorInCanonicalStructures.v3
-rw-r--r--test-suite/output/ErrorInCanonicalStructures2.out5
-rw-r--r--test-suite/output/ErrorInCanonicalStructures2.v3
-rw-r--r--test-suite/output/Inductive.out4
-rw-r--r--test-suite/output/Inductive.v4
-rw-r--r--test-suite/output/UnivBinders.out2
-rw-r--r--test-suite/output/optimize_heap.out8
-rw-r--r--test-suite/output/optimize_heap.v7
-rw-r--r--test-suite/success/BracketsWithGoalSelector.v16
-rw-r--r--test-suite/success/abstract_poly.v2
-rw-r--r--test-suite/success/cumulativity.v26
-rw-r--r--test-suite/success/dtauto-let-deps.v24
-rw-r--r--theories/Arith/Between.v4
-rw-r--r--theories/Lists/List.v27
-rw-r--r--tools/CoqMakefile.in23
-rw-r--r--tools/TimeFileMaker.py28
-rw-r--r--tools/coq_makefile.ml2
-rw-r--r--tools/coqdep.ml4
-rwxr-xr-xtools/make-both-single-timing-files.py18
-rwxr-xr-xtools/make-both-time-files.py18
-rw-r--r--tools/md5sum.ml24
-rw-r--r--toplevel/coqargs.ml575
-rw-r--r--toplevel/coqargs.mli63
-rw-r--r--toplevel/coqinit.ml138
-rw-r--r--toplevel/coqinit.mli16
-rw-r--r--toplevel/coqloop.ml4
-rw-r--r--toplevel/coqtop.ml746
-rw-r--r--toplevel/coqtop.mli6
-rw-r--r--toplevel/toplevel.mllib1
-rw-r--r--vernac/comInductive.ml4
-rw-r--r--vernac/explainErr.ml1
-rw-r--r--vernac/himsg.ml22
-rw-r--r--vernac/lemmas.ml32
-rw-r--r--vernac/lemmas.mli2
-rw-r--r--vernac/mltop.ml34
-rw-r--r--vernac/mltop.mli24
-rw-r--r--vernac/record.ml16
-rw-r--r--vernac/topfmt.ml3
-rw-r--r--vernac/vernacentries.ml287
-rw-r--r--vernac/vernacinterp.ml1
-rw-r--r--vernac/vernacinterp.mli1
-rw-r--r--vernac/vernacprop.ml8
314 files changed, 5795 insertions, 4683 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
index c49bc3b08..9b0cc2119 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -54,10 +54,17 @@ opam-switch: &opam-switch
steps:
- checkout
- run: *before_script
+ - run:
+ name: Cache selection
+ command: |
+ source ~/.profile
+ # We can't use environment variables in cache names
+ # So put it in a file and use the checksum
+ echo "$COMPILER" > COMPILER
- restore_cache:
keys:
- - coq-opam-cache-v1-{{ arch }}-{{ .Environment.COMPILER }}-{{ checksum ".circleci/config.yml" }}-
- - coq-opam-cache-v1-{{ arch }}-{{ .Environment.COMPILER }}- # this grabs old cache if checksum doesn't match
+ - coq-opam-cache-v1-{{ arch }}-{{ checksum "COMPILER" }}-{{ checksum ".circleci/config.yml" }}-
+ - coq-opam-cache-v1-{{ arch }}-{{ checksum "COMPILER" }}- # this grabs old cache if checksum doesn't match
- run:
name: Update opam lists
command: |
@@ -76,7 +83,7 @@ opam-switch: &opam-switch
source ~/.profile
rm -rf ~/.opam/log/
- save_cache:
- key: coq-opam-cache-v1-{{ arch }}-{{ .Environment.COMPILER }}-{{ checksum ".circleci/config.yml" }}-
+ key: coq-opam-cache-v1-{{ arch }}-{{ checksum "COMPILER" }}-{{ checksum ".circleci/config.yml" }}-
paths:
- ~/.opam
- persist_to_workspace:
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index c7437c4a4..a9230042a 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -13,4 +13,4 @@ Fixes / closes #????
<!-- If this is a feature pull request / breaks compatibility: -->
<!-- (Otherwise, remove these lines.) -->
- [ ] Corresponding documentation was added / updated.
-- [ ] Entry added in [CHANGES](/CHANGES).
+- [ ] Entry added in CHANGES.
diff --git a/.gitignore b/.gitignore
index 27ac0631a..1e7f982a5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -85,6 +85,7 @@ test-suite/coq-makefile/merlin1/.merlin
test-suite/coqdoc/Coqdoc.*
test-suite/coqdoc/index.html
test-suite/coqdoc/coqdoc.css
+test-suite/output/MExtraction.out
# documentation
diff --git a/.travis.yml b/.travis.yml
index 0bc43c110..19e7075f2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -20,10 +20,19 @@ addons:
apt:
sources:
- avsm
- packages:
- - opam
- - aspcud
- - gcc-multilib
+## Due to issues like
+## https://github.com/travis-ci/travis-ci/issues/8507 ,
+## https://github.com/travis-ci/travis-ci/issues/9000 ,
+## https://github.com/travis-ci/travis-ci/issues/9081 , and
+## https://github.com/travis-ci/travis-ci/issues/9126 , we get frequent
+## failures with using `packages`. Therefore, for most targets, we
+## instead invoke `apt-get update` manually with `travis_retry` before
+## invoking `apt-get install`, manually, below in the `install:`
+## target.
+# packages:
+# - opam
+# - aspcud
+# - gcc-multilib
env:
global:
@@ -35,7 +44,7 @@ env:
- CAMLP5_VER_BE="7.03"
- FINDLIB_VER="1.4.1"
- FINDLIB_VER_BE="1.7.3"
- - LABLGTK="lablgtk.2.16.0 lablgtk-extras.1.5"
+ - LABLGTK="lablgtk.2.18.3 lablgtk-extras.1.6"
- LABLGTK_BE="lablgtk.2.18.6 lablgtk-extras.1.6"
- NATIVE_COMP="yes"
- COQ_DEST="-local"
@@ -46,33 +55,68 @@ env:
- 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" EXTRA_OPAM="num" FINDLIB_VER="${FINDLIB_VER_BE}"
- - TEST_TARGET="ci-bignums"
- - TEST_TARGET="ci-color"
- - TEST_TARGET="ci-compcert"
- - TEST_TARGET="ci-coq-dpdgraph" EXTRA_OPAM="ocamlgraph"
- - TEST_TARGET="ci-coquelicot"
- - TEST_TARGET="ci-equations"
- - TEST_TARGET="ci-geocoq"
- - TEST_TARGET="ci-fiat-crypto"
- - TEST_TARGET="ci-fiat-parsers"
- - TEST_TARGET="ci-flocq"
- - TEST_TARGET="ci-formal-topology"
- - TEST_TARGET="ci-hott"
- - TEST_TARGET="ci-iris-lambda-rust"
- - TEST_TARGET="ci-ltac2"
- - TEST_TARGET="ci-math-classes"
- - TEST_TARGET="ci-math-comp"
- - TEST_TARGET="ci-sf"
- - TEST_TARGET="ci-unimath"
- - TEST_TARGET="ci-vst"
- # Not ready yet for 8.7
- # - TEST_TARGET="ci-cpdt"
- # - TEST_TARGET="ci-metacoq"
- # - TEST_TARGET="ci-tlc"
matrix:
include:
+ - if: NOT (type = pull_request)
+ env:
+ - TEST_TARGET="ci-bignums"
+ - if: NOT (type = pull_request)
+ env:
+ - TEST_TARGET="ci-color"
+ - if: NOT (type = pull_request)
+ env:
+ - TEST_TARGET="ci-compcert"
+ - if: NOT (type = pull_request)
+ env:
+ - TEST_TARGET="ci-coq-dpdgraph" EXTRA_OPAM="ocamlgraph"
+ - if: NOT (type = pull_request)
+ env:
+ - TEST_TARGET="ci-coquelicot"
+ - if: NOT (type = pull_request)
+ env:
+ - TEST_TARGET="ci-equations"
+ - if: NOT (type = pull_request)
+ env:
+ - TEST_TARGET="ci-geocoq"
+ - 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-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"
install: []
@@ -212,6 +256,8 @@ before_install:
- if [ "${TRAVIS_PULL_REQUEST}" != "false" ]; then echo "Tested commit (followed by parent commits):"; git log -1; for commit in `git log -1 --format="%P"`; do echo; git log -1 $commit; done; fi
install:
+- if [ "${TRAVIS_OS_NAME}" == "linux" ]; then travis_retry ./dev/tools/sudo-apt-get-update.sh -q; fi
+- if [ "${TRAVIS_OS_NAME}" == "linux" ]; then sudo apt-get install -y opam aspcud gcc-multilib; fi
- opam init -j ${NJOBS} --compiler=${COMPILER} -n -y
- eval $(opam config env)
- opam config list
diff --git a/CHANGES b/CHANGES
index cbaa2c5e2..8d344d4f0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -37,9 +37,25 @@ Tactics
- Added tactics reset ltac profile, show ltac profile (and variants)
- Added tactics restart_timer, finish_timing, and time_constr as an
experimental way of timing Ltac's evaluation phase
+- Added tactic optimize_heap, analogous to the Vernacular Optimize
+ Heap, which performs a major garbage collection and heap compaction
+ in the OCaml run-time system.
+- The tactics "dtauto", "dintuition", "firstorder" now handle inductive types
+ with let bindings in the parameters.
+- The tactic "dtauto" now handles some inductives such as
+ "@sigT A (fun _ => B)" as non-dependent conjunctions.
+
+Focusing
+
+- Focusing bracket `{` now supports single-numbered goal selector,
+ e.g. `2: {` will focus on the second sub-goal. As usual, unfocus
+ with `}` once the sub-goal is fully solved.
Vernacular Commands
+- Proofs ending in "Qed exporting ident, .., ident" are not supported
+ anymore. Constants generated during `abstract` are kept private to the
+ local environment.
- The deprecated Coercion Local, Open Local Scope, Notation Local syntax
was removed. Use Local as a prefix instead.
- For the Extraction Language command, "OCaml" is spelled correctly.
@@ -52,17 +68,39 @@ Universes
module and library boundaries. Global universe names introduced in an
inductive / constant / Let declaration get qualified with the name of
the declaration.
+- Universe cumulativity for inductive types is now specified as a
+ variance for each polymorphic universe. See the reference manual for
+ more information.
+- Fix #5726: Notations that start with `Type` now support universe instances
+ with `@{u}`.
Checker
- The checker now accepts filenames in addition to logical paths.
+CoqIDE
+
+- Find and Replace All report the number of occurrences found; Find indicates
+ when it wraps.
+
Documentation
- The Coq FAQ, formerly located at https://coq.inria.fr/faq, has been
moved to the GitHub wiki section of this repository; the main entry
page is https://github.com/coq/coq/wiki/The-Coq-FAQ.
+Changes from 8.7.1 to 8.7.2
+===========================
+
+Fixed a critical bug in the VM handling of universes (#6677). This bug
+affected all releases since 8.5.
+
+Improved support for building with OCaml 4.06.0 and external num package.
+
+Many other bug fixes, documentation improvements, and user
+message improvements (for details, see the 8.7.2 milestone at
+https://github.com/coq/coq/milestone/11?closed=1).
+
Changes from 8.7.0 to 8.7.1
===========================
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 37b556c55..1a769333c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -28,6 +28,8 @@ Please make pull requests against the `master` branch.
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.
+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.
+
Don't be alarmed if the pull request process takes some time. It can take a few days to get feedback, approval on the final changes, and then a merge. Coq doesn't release new versions very frequently so it can take a few months for your change to land in a released version. That said, you can start using the latest Coq `master` branch to take advantage of all the new features, improvements, and fixes.
Here are a few tags Coq developers may add to your PR and what they mean. In general feedback and requests for you as the pull request author will be in the comments and tags are only used to organize pull requests.
diff --git a/INSTALL.ide b/INSTALL.ide
index 513e37c91..26c192baa 100644
--- a/INSTALL.ide
+++ b/INSTALL.ide
@@ -39,7 +39,7 @@ COMPILATION REQUIREMENTS
install GTK+ 2.x, should you need to force it for one reason
or another.)
- The OCaml bindings for GTK+ 2.x, lablgtk2 with support for gtksourceview2.
- You need at least version 2.16.
+ You need at least version 2.18.3.
Your distribution may contain precompiled packages. For example, for
Debian, run
@@ -57,7 +57,7 @@ COMPILATION REQUIREMENTS
./configure && make world && make install
You must have write access to the OCaml standard library path.
- If this fails, read lablgtk-2.14.2/README.
+ If this fails, read the README.
INSTALLATION
diff --git a/META.coq b/META.coq
index 76d5b4147..d180820e8 100644
--- a/META.coq
+++ b/META.coq
@@ -43,8 +43,8 @@ package "lib" (
requires = "coq.clib, coq.config"
- archive(byte) += "lib.cma"
- archive(native) += "lib.cmxa"
+ archive(byte) = "lib.cma"
+ archive(native) = "lib.cmxa"
)
@@ -240,19 +240,6 @@ package "stm" (
)
-package "ltac" (
-
- description = "Coq LTAC Plugin"
- version = "8.7"
-
- requires = "coq.stm"
- directory = "plugins/ltac"
-
- archive(byte) = "ltac_plugin.cmo"
- archive(native) = "ltac_plugin.cmx"
-
-)
-
package "toplevel" (
description = "Coq Toplevel"
@@ -293,3 +280,300 @@ package "ide" (
archive(native) = "ide.cmxa"
)
+
+package "plugins" (
+
+ description = "Coq built-in plugins"
+ version = "8.7"
+
+ directory = "plugins"
+
+ package "ltac" (
+
+ description = "Coq LTAC Plugin"
+ version = "8.7"
+
+ requires = "coq.stm"
+ directory = "ltac"
+
+ archive(byte) = "ltac_plugin.cmo"
+ archive(native) = "ltac_plugin.cmx"
+
+ )
+
+ package "tauto" (
+
+ description = "Coq tauto plugin"
+ version = "8.7"
+
+ requires = "coq.plugins.ltac"
+ directory = "ltac"
+
+ archive(byte) = "tauto_plugin.cmo"
+ archive(native) = "tauto_plugin.cmx"
+ )
+
+ package "omega" (
+
+ description = "Coq omega plugin"
+ version = "8.7"
+
+ requires = "coq.plugins.ltac"
+ directory = "omega"
+
+ archive(byte) = "omega_plugin.cmo"
+ archive(native) = "omega_plugin.cmx"
+ )
+
+ package "romega" (
+
+ description = "Coq romega plugin"
+ version = "8.7"
+
+ requires = "coq.plugins.omega"
+ directory = "romega"
+
+ archive(byte) = "romega_plugin.cmo"
+ archive(native) = "romega_plugin.cmx"
+ )
+
+ package "micromega" (
+
+ description = "Coq micromega plugin"
+ version = "8.7"
+
+ requires = "num,coq.plugins.ltac"
+ directory = "micromega"
+
+ archive(byte) = "micromega_plugin.cmo"
+ archive(native) = "micromega_plugin.cmx"
+ )
+
+ package "quote" (
+
+ description = "Coq quote plugin"
+ version = "8.7"
+
+ requires = "coq.plugins.ltac"
+ directory = "quote"
+
+ archive(byte) = "quote_plugin.cmo"
+ archive(native) = "quote_plugin.cmx"
+ )
+
+ package "newring" (
+
+ description = "Coq newring plugin"
+ version = "8.7"
+
+ requires = "coq.plugins.quote"
+ directory = "setoid_ring"
+
+ archive(byte) = "newring_plugin.cmo"
+ archive(native) = "newring_plugin.cmx"
+ )
+
+ package "fourier" (
+
+ description = "Coq fourier plugin"
+ version = "8.7"
+
+ requires = "coq.plugins.ltac"
+ directory = "fourier"
+
+ archive(byte) = "fourier_plugin.cmo"
+ archive(native) = "fourier_plugin.cmx"
+ )
+
+ package "extraction" (
+
+ description = "Coq extraction plugin"
+ version = "8.7"
+
+ requires = "coq.plugins.ltac"
+ directory = "extraction"
+
+ archive(byte) = "extraction_plugin.cmo"
+ archive(native) = "extraction_plugin.cmx"
+ )
+
+ package "cc" (
+
+ description = "Coq cc plugin"
+ version = "8.7"
+
+ requires = "coq.plugins.ltac"
+ directory = "cc"
+
+ archive(byte) = "cc_plugin.cmo"
+ archive(native) = "cc_plugin.cmx"
+ )
+
+ package "ground" (
+
+ description = "Coq ground plugin"
+ version = "8.7"
+
+ requires = "coq.plugins.ltac"
+ directory = "firstorder"
+
+ archive(byte) = "ground_plugin.cmo"
+ archive(native) = "ground_plugin.cmx"
+ )
+
+ package "rtauto" (
+
+ description = "Coq rtauto plugin"
+ version = "8.7"
+
+ requires = "coq.plugins.ltac"
+ directory = "rtauto"
+
+ archive(byte) = "rtauto_plugin.cmo"
+ archive(native) = "rtauto_plugin.cmx"
+ )
+
+ package "btauto" (
+
+ description = "Coq btauto plugin"
+ version = "8.7"
+
+ requires = "coq.plugins.ltac"
+ directory = "btauto"
+
+ archive(byte) = "btauto_plugin.cmo"
+ archive(native) = "btauto_plugin.cmx"
+ )
+
+ package "recdef" (
+
+ description = "Coq recdef plugin"
+ version = "8.7"
+
+ requires = "coq.plugins.extraction"
+ directory = "funind"
+
+ archive(byte) = "recdef_plugin.cmo"
+ archive(native) = "recdef_plugin.cmx"
+ )
+
+ package "nsatz" (
+
+ description = "Coq nsatz plugin"
+ version = "8.7"
+
+ requires = "num,coq.plugins.ltac"
+ directory = "nsatz"
+
+ archive(byte) = "nsatz_plugin.cmo"
+ archive(native) = "nsatz_plugin.cmx"
+ )
+
+ package "natsyntax" (
+
+ description = "Coq natsyntax plugin"
+ version = "8.7"
+
+ requires = ""
+ directory = "syntax"
+
+ archive(byte) = "nat_syntax_plugin.cmo"
+ archive(native) = "nat_syntax_plugin.cmx"
+ )
+
+ package "zsyntax" (
+
+ description = "Coq zsyntax plugin"
+ version = "8.7"
+
+ requires = ""
+ directory = "syntax"
+
+ archive(byte) = "z_syntax_plugin.cmo"
+ archive(native) = "z_syntax_plugin.cmx"
+ )
+
+ package "rsyntax" (
+
+ description = "Coq rsyntax plugin"
+ version = "8.7"
+
+ requires = ""
+ directory = "syntax"
+
+ archive(byte) = "r_syntax_plugin.cmo"
+ archive(native) = "r_syntax_plugin.cmx"
+ )
+
+ package "int31syntax" (
+
+ description = "Coq int31syntax plugin"
+ version = "8.7"
+
+ requires = ""
+ directory = "syntax"
+
+ archive(byte) = "int31_syntax_plugin.cmo"
+ archive(native) = "int31_syntax_plugin.cmx"
+ )
+
+ package "asciisyntax" (
+
+ description = "Coq asciisyntax plugin"
+ version = "8.7"
+
+ requires = ""
+ directory = "syntax"
+
+ archive(byte) = "ascii_syntax_plugin.cmo"
+ archive(native) = "ascii_syntax_plugin.cmx"
+ )
+
+ package "stringsyntax" (
+
+ description = "Coq stringsyntax plugin"
+ version = "8.7"
+
+ requires = "coq.plugins.asciisyntax"
+ directory = "syntax"
+
+ archive(byte) = "string_syntax_plugin.cmo"
+ archive(native) = "string_syntax_plugin.cmx"
+ )
+
+ package "derive" (
+
+ description = "Coq derive plugin"
+ version = "8.7"
+
+ requires = ""
+ directory = "derive"
+
+ archive(byte) = "derive_plugin.cmo"
+ archive(native) = "derive_plugin.cmx"
+ )
+
+ package "ssrmatching" (
+
+ description = "Coq ssrmatching plugin"
+ version = "8.7"
+
+ requires = "coq.plugins.ltac"
+ directory = "ssrmatching"
+
+ archive(byte) = "ssrmatching_plugin.cmo"
+ archive(native) = "ssrmatching_plugin.cmx"
+ )
+
+ package "ssreflect" (
+
+ description = "Coq ssreflect plugin"
+ version = "8.7"
+
+ requires = "coq.plugins.ssrmatching"
+ directory = "ssr"
+
+ archive(byte) = "ssreflect_plugin.cmo"
+ archive(native) = "ssreflect_plugin.cmx"
+ )
+)
diff --git a/Makefile.build b/Makefile.build
index 9a838b85c..dc988e885 100644
--- a/Makefile.build
+++ b/Makefile.build
@@ -406,17 +406,16 @@ $(COQTOPEXE): $(COQTOPBYTE)
cp $< $@
endif
-# Are "-cclib lcoqrun -dllib -lcoqrun" necessary?
+# VMBYTEFLAGS will either contain -custom of the right -dllpath for the VM
$(COQTOPBYTE): $(LINKCMO) $(LIBCOQRUN) $(TOPLOOPCMA) $(COQTOP_BYTE_MLTOP)
$(SHOW)'COQMKTOP -o $@'
$(HIDE)$(OCAMLC) -linkall -linkpkg -I toplevel \
- -I kernel/byterun -dllpath $(abspath kernel/byterun) -cclib -lcoqrun -dllib -lcoqrun \
+ -I kernel/byterun/ -cclib -lcoqrun $(VMBYTEFLAGS) \
$(SYSMOD) -package camlp5.gramlib,compiler-libs.toplevel \
$(LINKCMO) $(BYTEFLAGS) \
$(COQTOP_BYTE_MLTOP) toplevel/coqtop_bin.ml -o $@
-# coqc
-
+# For coqc
COQCCMO:=clib/clib.cma lib/lib.cma toplevel/usage.cmo tools/coqc.cmo
$(COQC): $(call bestobj, $(COQCCMO))
@@ -594,16 +593,35 @@ kernel/kernel.cma: kernel/kernel.mllib
$(SHOW)'OCAMLOPT -pack -o $@'
$(HIDE)$(OCAMLOPT) $(MLINCLUDES) $(OPTFLAGS) -pack -o $@ $(filter-out %.mlpack, $^)
+COND_IDEFLAGS=$(if $(filter tools/fake_ide% tools/coq_makefile%,$<), -I ide,)
+COND_PRINTERFLAGS=$(if $(filter dev/%,$<), -I dev,)
+
COND_BYTEFLAGS= \
- $(if $(filter tools/fake_ide% tools/coq_makefile%,$<), -I ide,) $(MLINCLUDES) $(BYTEFLAGS)
+ $(COND_IDEFLAGS) $(COND_PRINTERFLAGS) $(MLINCLUDES) $(BYTEFLAGS)
COND_OPTFLAGS= \
- $(if $(filter tools/fake_ide% tools/coq_makefile%,$<), -I ide,) $(MLINCLUDES) $(OPTFLAGS)
+ $(COND_IDEFLAGS) $(MLINCLUDES) $(OPTFLAGS)
+
+plugins/micromega/%.cmi: plugins/micromega/%.mli
+ $(SHOW)'OCAMLC $<'
+ $(HIDE)$(OCAMLC) $(COND_BYTEFLAGS) -package unix,num -c $<
+
+plugins/nsatz/%.cmi: plugins/nsatz/%.mli
+ $(SHOW)'OCAMLC $<'
+ $(HIDE)$(OCAMLC) $(COND_BYTEFLAGS) -package unix,num -c $<
%.cmi: %.mli
$(SHOW)'OCAMLC $<'
$(HIDE)$(OCAMLC) $(COND_BYTEFLAGS) -c $<
+plugins/micromega/%.cmo: plugins/micromega/%.ml
+ $(SHOW)'OCAMLC $<'
+ $(HIDE)$(OCAMLC) $(COND_BYTEFLAGS) -package unix,num -c $<
+
+plugins/nsatz/%.cmo: plugins/nsatz/%.ml
+ $(SHOW)'OCAMLC $<'
+ $(HIDE)$(OCAMLC) $(COND_BYTEFLAGS) -package unix,num -c $<
+
%.cmo: %.ml
$(SHOW)'OCAMLC $<'
$(HIDE)$(OCAMLC) $(COND_BYTEFLAGS) -c $<
@@ -637,6 +655,14 @@ plugins/micromega/sos_FORPACK:=
plugins/micromega/sos_print_FORPACK:=
plugins/micromega/csdpcert_FORPACK:=
+plugins/micromega/%.cmx: plugins/micromega/%.ml
+ $(SHOW)'OCAMLOPT $<'
+ $(HIDE)$(OCAMLOPT) $(COND_OPTFLAGS) $(HACKMLI) $($(@:.cmx=_FORPACK)) -package unix,num -c $<
+
+plugins/nsatz/%.cmx: plugins/nsatz/%.ml
+ $(SHOW)'OCAMLOPT $<'
+ $(HIDE)$(OCAMLOPT) $(COND_OPTFLAGS) $(HACKMLI) $($(@:.cmx=_FORPACK)) -package unix,num -c $<
+
plugins/%.cmx: plugins/%.ml
$(SHOW)'OCAMLOPT $<'
$(HIDE)$(OCAMLOPT) $(COND_OPTFLAGS) $(HACKMLI) $($(@:.cmx=_FORPACK)) -c $<
diff --git a/Makefile.checker b/Makefile.checker
index 5b5855782..0e429fe86 100644
--- a/Makefile.checker
+++ b/Makefile.checker
@@ -33,7 +33,7 @@ CHECKERDEPS := $(addsuffix .d, $(CHECKMLDFILE) $(CHECKMLLIBFILE))
-include $(CHECKERDEPS)
ifeq ($(BEST),opt)
-$(CHICKEN): checker/check.cmxa checker/main.ml
+$(CHICKEN): checker/check.cmxa checker/main.mli checker/main.ml
$(SHOW)'OCAMLOPT -o $@'
$(HIDE)$(OCAMLOPT) -linkpkg $(SYSMOD) $(CHKLIBS) $(OPTFLAGS) $(LINKMETADATA) -o $@ $^
$(STRIP) $@
@@ -43,7 +43,7 @@ $(CHICKEN): $(CHICKENBYTE)
cp $< $@
endif
-$(CHICKENBYTE): checker/check.cma checker/main.ml
+$(CHICKENBYTE): checker/check.cma checker/main.mli checker/main.ml
$(SHOW)'OCAMLC -o $@'
$(HIDE)$(OCAMLC) -linkpkg $(SYSMOD) $(CHKLIBS) $(BYTEFLAGS) $(CUSTOM) -o $@ $^
@@ -77,9 +77,8 @@ checker/%.cmx: checker/%.ml
md5chk:
$(SHOW)'MD5SUM cic.mli'
- $(HIDE)v=`tr -d "\r" < checker/cic.mli | $(MD5SUM) | sed -n -e 's/ .*//' -e '/^/p'`; \
- if grep -q "$$v" checker/values.ml; \
- then true; else echo "Error: outdated checker/values.ml: $$v" >&2; false; fi
+ $(HIDE)if grep -q "^MD5 $$($(OCAML) tools/md5sum.ml checker/cic.mli)$$" checker/values.ml; \
+ then true; else echo "Error: outdated checker/values.ml" >&2; false; fi
.PHONY: md5chk
diff --git a/Makefile.ci b/Makefile.ci
index 334827a93..80fbd7bbe 100644
--- a/Makefile.ci
+++ b/Makefile.ci
@@ -1,5 +1,4 @@
-CI_TARGETS=ci-all \
- ci-bignums \
+CI_TARGETS=ci-bignums \
ci-color \
ci-compcert \
ci-coq-dpdgraph \
@@ -23,7 +22,7 @@ CI_TARGETS=ci-all \
ci-unimath \
ci-vst
-.PHONY: $(CI_TARGETS)
+.PHONY: ci-all $(CI_TARGETS)
ci-color: ci-bignums
@@ -37,6 +36,8 @@ ci-formal-topology: ci-corn
$(CI_TARGETS): ci-%:
+./dev/ci/ci-wrapper.sh $*
+ci-all: $(CI_TARGETS)
+
# For emacs:
# Local Variables:
# mode: makefile
diff --git a/Makefile.ide b/Makefile.ide
index 08829b554..09eef1f6b 100644
--- a/Makefile.ide
+++ b/Makefile.ide
@@ -45,8 +45,8 @@ IDEDEPS:=clib/clib.cma lib/lib.cma
IDECMA:=ide/ide.cma
IDETOPLOOPCMA=ide/coqidetop.cma
-LINKIDE:=$(IDEDEPS) $(IDECDEPS) $(IDECMA) ide/coqide_main.ml
-LINKIDEOPT:=$(IDEOPTCDEPS) $(patsubst %.cma,%.cmxa,$(IDEDEPS:.cmo=.cmx)) $(IDECMA:.cma=.cmxa) ide/coqide_main.ml
+LINKIDE:=$(IDEDEPS) $(IDECDEPS) $(IDECMA) ide/coqide_main.mli ide/coqide_main.ml
+LINKIDEOPT:=$(IDEOPTCDEPS) $(patsubst %.cma,%.cmxa,$(IDEDEPS:.cmo=.cmx)) $(IDECMA:.cma=.cmxa) ide/coqide_main.mli ide/coqide_main.ml
IDEFILES=$(wildcard ide/*.lang) ide/coq_style.xml ide/coq.png ide/MacOS/default_accel_map
diff --git a/README.md b/README.md
index fae83e02c..883630acf 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,7 @@
[![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)
[![Gitter](https://badges.gitter.im/coq/coq.svg)](https://gitter.im/coq/coq)
+[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.1003420.svg)](https://doi.org/10.5281/zenodo.1003420)
Coq is a formal proof management system. It provides a formal language to write
mathematical definitions, executable algorithms and theorems together with an
diff --git a/checker/checker.ml b/checker/checker.ml
index fee31b667..e8eff889c 100644
--- a/checker/checker.ml
+++ b/checker/checker.ml
@@ -18,7 +18,7 @@ let () = at_exit flush_all
let chk_pp = Pp.pp_with Format.std_formatter
let fatal_error info anomaly =
- flush_all (); Feedback.msg_error info; flush_all ();
+ flush_all (); Format.eprintf "@[Fatal Error: @[%a@]@]%!@\n" Pp.pp_with info; flush_all ();
exit (if anomaly then 129 else 1)
let coq_root = Id.of_string "Coq"
@@ -208,8 +208,7 @@ let usage () =
open Type_errors
let anomaly_string () = str "Anomaly: "
-let report () = (str "." ++ spc () ++ str "Please report" ++
- strbrk "at " ++ str Coq_config.wwwbugtracker ++ str ".")
+let report () = strbrk (". Please report at " ^ Coq_config.wwwbugtracker ^ ".")
let guill s = str "\"" ++ str s ++ str "\""
diff --git a/checker/checker.mli b/checker/checker.mli
new file mode 100644
index 000000000..ceab13774
--- /dev/null
+++ b/checker/checker.mli
@@ -0,0 +1,9 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+val start : unit -> unit
diff --git a/checker/cic.mli b/checker/cic.mli
index 4a0e706aa..95dd18f5f 100644
--- a/checker/cic.mli
+++ b/checker/cic.mli
@@ -170,6 +170,17 @@ type set_predicativity = ImpredicativeSet | PredicativeSet
type engagement = set_predicativity
+(** {6 Conversion oracle} *)
+
+type level = Expand | Level of int | Opaque
+
+type oracle = {
+ var_opacity : level Id.Map.t;
+ cst_opacity : level Cmap.t;
+ var_trstate : Id.Pred.t;
+ cst_trstate : Cpred.t;
+}
+
(** {6 Representation of constants (Definition/Axiom) } *)
@@ -219,6 +230,7 @@ type typing_flags = {
check_guarded : bool; (** If [false] then fixed points and co-fixed
points are assumed to be total. *)
check_universes : bool; (** If [false] universe constraints are not checked *)
+ conv_oracle : oracle; (** Unfolding strategies for conversion *)
}
type constant_body = {
diff --git a/checker/closure.ml b/checker/closure.ml
index 3a56bba01..14b31e09d 100644
--- a/checker/closure.ml
+++ b/checker/closure.ml
@@ -49,13 +49,6 @@ let with_stats c =
end else
Lazy.force c
-type transparent_state = Id.Pred.t * Cpred.t
-let all_opaque = (Id.Pred.empty, Cpred.empty)
-let all_transparent = (Id.Pred.full, Cpred.full)
-
-let is_transparent_variable (ids, _) id = Id.Pred.mem id ids
-let is_transparent_constant (_, csts) cst = Cpred.mem cst csts
-
module type RedFlagsSig = sig
type reds
type red_kind
@@ -63,8 +56,6 @@ module type RedFlagsSig = sig
val fDELTA : red_kind
val fIOTA : red_kind
val fZETA : red_kind
- val fCONST : Constant.t -> red_kind
- val fVAR : Id.t -> red_kind
val no_red : reds
val red_add : reds -> red_kind -> reds
val mkflags : red_kind list -> reds
@@ -80,51 +71,33 @@ module RedFlags = (struct
type reds = {
r_beta : bool;
r_delta : bool;
- r_const : transparent_state;
r_zeta : bool;
r_evar : bool;
r_iota : bool }
type red_kind = BETA | DELTA | IOTA | ZETA
- | CONST of Constant.t | VAR of Id.t
+
let fBETA = BETA
let fDELTA = DELTA
let fIOTA = IOTA
let fZETA = ZETA
- let fCONST kn = CONST kn
- let fVAR id = VAR id
let no_red = {
r_beta = false;
r_delta = false;
- r_const = all_opaque;
r_zeta = false;
r_evar = false;
r_iota = false }
let red_add red = function
| BETA -> { red with r_beta = true }
- | DELTA -> { red with r_delta = true; r_const = all_transparent }
- | CONST kn ->
- let (l1,l2) = red.r_const in
- { red with r_const = l1, Cpred.add kn l2 }
+ | DELTA -> { red with r_delta = true}
| IOTA -> { red with r_iota = true }
| ZETA -> { red with r_zeta = true }
- | VAR id ->
- let (l1,l2) = red.r_const in
- { red with r_const = Id.Pred.add id l1, l2 }
let mkflags = List.fold_left red_add no_red
let red_set red = function
| BETA -> incr_cnt red.r_beta beta
- | CONST kn ->
- let (_,l) = red.r_const in
- let c = Cpred.mem kn l in
- incr_cnt c delta
- | VAR id -> (* En attendant d'avoir des kn pour les Var *)
- let (l,_) = red.r_const in
- let c = Id.Pred.mem id l in
- incr_cnt c delta
| ZETA -> incr_cnt red.r_zeta zeta
| IOTA -> incr_cnt red.r_iota iota
| DELTA -> (* Used for Rel/Var defined in context *)
@@ -700,6 +673,9 @@ let contract_fix_vect fix =
in
(subs_cons(Array.init nfix make_body, env), thisbody)
+let unfold_projection env p =
+ let pb = lookup_projection p env in
+ Zproj (pb.proj_npars, pb.proj_arg, p)
(*********************************************************************)
(* A machine that inspects the head of a term until it finds an
@@ -720,10 +696,9 @@ let rec knh info m stk =
| FCast(t,_,_) -> knh info t stk
| FProj (p,c) ->
- if red_set info.i_flags (fCONST (Projection.constant p)) then
- (let pb = lookup_projection p (info.i_env) in
- knh info c (Zproj (pb.proj_npars, pb.proj_arg, p)
- :: zupdate m stk))
+ if red_set info.i_flags fDELTA then
+ let s = unfold_projection info.i_env p in
+ knh info c (s :: zupdate m stk)
else (m,stk)
(* cases where knh stops *)
@@ -755,11 +730,11 @@ let rec knr info m stk =
(match get_args n tys f e stk with
Inl e', s -> knit info e' f s
| Inr lam, s -> (lam,s))
- | FFlex(ConstKey kn) when red_set info.i_flags (fCONST (fst kn)) ->
+ | FFlex(ConstKey kn) when red_set info.i_flags fDELTA ->
(match ref_value_cache info (ConstKey kn) with
Some v -> kni info v stk
| None -> (set_norm m; (m,stk)))
- | FFlex(VarKey id) when red_set info.i_flags (fVAR id) ->
+ | FFlex(VarKey id) when red_set info.i_flags fDELTA ->
(match ref_value_cache info (VarKey id) with
Some v -> kni info v stk
| None -> (set_norm m; (m,stk)))
@@ -822,6 +797,7 @@ type clos_infos = fconstr infos
let infos_env x = x.i_env
let infos_flags x = x.i_flags
+let oracle_of_infos x = x.i_env.env_conv_oracle
let create_clos_infos flgs env =
create (fun _ -> inject) flgs env
diff --git a/checker/closure.mli b/checker/closure.mli
index 02d8b22fa..7bdc21b60 100644
--- a/checker/closure.mli
+++ b/checker/closure.mli
@@ -24,14 +24,6 @@ val with_stats: 'a Lazy.t -> 'a
Rem: reduction of a Rel/Var bound to a term is Delta, but reduction of
a LetIn expression is Letin reduction *)
-type transparent_state = Id.Pred.t * Cpred.t
-
-val all_opaque : transparent_state
-val all_transparent : transparent_state
-
-val is_transparent_variable : transparent_state -> variable -> bool
-val is_transparent_constant : transparent_state -> Constant.t -> bool
-
(* Sets of reduction kinds. *)
module type RedFlagsSig = sig
type reds
@@ -42,8 +34,6 @@ module type RedFlagsSig = sig
val fDELTA : red_kind
val fIOTA : red_kind
val fZETA : red_kind
- val fCONST : Constant.t -> red_kind
- val fVAR : Id.t -> red_kind
(* No reduction at all *)
val no_red : reds
@@ -131,6 +121,8 @@ val eta_expand_stack : stack -> stack
val eta_expand_ind_stack : env -> inductive -> fconstr -> stack ->
(fconstr * stack) -> stack * stack
+val unfold_projection : env -> Projection.t -> stack_member
+
(* To lazy reduce a constr, create a [clos_infos] with
[create_clos_infos], inject the term to reduce with [inject]; then use
a reduction function *)
@@ -147,6 +139,8 @@ type clos_infos
val create_clos_infos : reds -> env -> clos_infos
val infos_env : clos_infos -> env
val infos_flags : clos_infos -> reds
+val oracle_of_infos : clos_infos -> oracle
+
(* Reduction function *)
diff --git a/checker/declarations.ml b/checker/declarations.ml
index 884a1ef18..15b1f0a0c 100644
--- a/checker/declarations.ml
+++ b/checker/declarations.ml
@@ -484,8 +484,8 @@ let subst_wf_paths sub p = Rtree.smartmap (subst_recarg sub) p
let eq_recarg r1 r2 = match r1, r2 with
| Norec, Norec -> true
- | Mrec i1, Mrec i2 -> Names.eq_ind i1 i2
- | Imbr i1, Imbr i2 -> Names.eq_ind i1 i2
+ | Mrec i1, Mrec i2 -> Names.eq_ind_chk i1 i2
+ | Imbr i1, Imbr i2 -> Names.eq_ind_chk i1 i2
| _ -> false
let eq_wf_paths = Rtree.equal eq_recarg
diff --git a/checker/environ.ml b/checker/environ.ml
index 9db0d60e8..bbd043c8e 100644
--- a/checker/environ.ml
+++ b/checker/environ.ml
@@ -21,7 +21,15 @@ type env = {
env_globals : globals;
env_rel_context : rel_context;
env_stratification : stratification;
- env_imports : Cic.vodigest MPmap.t }
+ env_imports : Cic.vodigest MPmap.t;
+ env_conv_oracle : oracle; }
+
+let empty_oracle = {
+ var_opacity = Id.Map.empty;
+ cst_opacity = Cmap.empty;
+ var_trstate = Id.Pred.empty;
+ cst_trstate = Cpred.empty;
+}
let empty_env = {
env_globals =
@@ -34,7 +42,8 @@ let empty_env = {
env_stratification =
{ env_universes = Univ.initial_universes;
env_engagement = PredicativeSet };
- env_imports = MPmap.empty }
+ env_imports = MPmap.empty;
+ env_conv_oracle = empty_oracle }
let engagement env = env.env_stratification.env_engagement
let universes env = env.env_stratification.env_universes
@@ -51,6 +60,8 @@ let set_engagement (impr_set as c) env =
{ env with env_stratification =
{ env.env_stratification with env_engagement = c } }
+let set_oracle env oracle = { env with env_conv_oracle = oracle }
+
(* Digests *)
let add_digest env dp digest =
@@ -115,7 +126,7 @@ let add_constant kn cs env =
env_constants = new_constants } in
{ env with env_globals = new_globals }
-type const_evaluation_result = NoBody | Opaque | IsProj
+type const_evaluation_result = NoBody | Opaque
(* Constant types *)
@@ -137,18 +148,16 @@ exception NotEvaluableConst of const_evaluation_result
let constant_value env (kn,u) =
let cb = lookup_constant kn env in
- if cb.const_proj = None then
- match cb.const_body with
- | Def l_body ->
- let b = force_constr l_body in
- begin
- match cb.const_universes with
- | Monomorphic_const _ -> b
- | Polymorphic_const _ -> subst_instance_constr u (force_constr l_body)
- end
- | OpaqueDef _ -> raise (NotEvaluableConst Opaque)
- | Undef _ -> raise (NotEvaluableConst NoBody)
- else raise (NotEvaluableConst IsProj)
+ match cb.const_body with
+ | Def l_body ->
+ let b = force_constr l_body in
+ begin
+ match cb.const_universes with
+ | Monomorphic_const _ -> b
+ | Polymorphic_const _ -> subst_instance_constr u (force_constr l_body)
+ end
+ | OpaqueDef _ -> raise (NotEvaluableConst Opaque)
+ | Undef _ -> raise (NotEvaluableConst NoBody)
(* A global const is evaluable if it is defined and not opaque *)
let evaluable_constant cst env =
diff --git a/checker/environ.mli b/checker/environ.mli
index 6bda838f8..36e0ea027 100644
--- a/checker/environ.mli
+++ b/checker/environ.mli
@@ -18,6 +18,7 @@ type env = {
env_rel_context : rel_context;
env_stratification : stratification;
env_imports : Cic.vodigest MPmap.t;
+ env_conv_oracle : Cic.oracle;
}
val empty_env : env
@@ -25,6 +26,10 @@ val empty_env : env
val engagement : env -> Cic.engagement
val set_engagement : Cic.engagement -> env -> env
+(** Oracle *)
+
+val set_oracle : env -> Cic.oracle -> env
+
(* Digests *)
val add_digest : env -> DirPath.t -> Cic.vodigest -> env
val lookup_digest : env -> DirPath.t -> Cic.vodigest
@@ -47,7 +52,7 @@ val check_constraints : Univ.constraints -> env -> bool
val lookup_constant : Constant.t -> env -> Cic.constant_body
val add_constant : Constant.t -> Cic.constant_body -> env -> env
val constant_type : env -> Constant.t puniverses -> constr Univ.constrained
-type const_evaluation_result = NoBody | Opaque | IsProj
+type const_evaluation_result = NoBody | Opaque
exception NotEvaluableConst of const_evaluation_result
val constant_value : env -> Constant.t puniverses -> constr
val evaluable_constant : Constant.t -> env -> bool
diff --git a/checker/indtypes.ml b/checker/indtypes.ml
index 22c843812..1807ae0ec 100644
--- a/checker/indtypes.ml
+++ b/checker/indtypes.ml
@@ -502,10 +502,19 @@ let check_positivity_one (env, _,ntypes,_ as ienv) hyps nrecp (_,i as ind) indlc
indlc
in mk_paths (Mrec ind) irecargs
+let prrecarg = function
+ | Norec -> str "Norec"
+ | Mrec (mind,i) ->
+ str "Mrec[" ++ MutInd.debug_print mind ++ pr_comma () ++ int i ++ str "]"
+ | Imbr (mind,i) ->
+ str "Imbr[" ++ MutInd.debug_print mind ++ pr_comma () ++ int i ++ str "]"
+
let check_subtree t1 t2 =
let cmp_labels l1 l2 = l1 == Norec || eq_recarg l1 l2 in
if not (Rtree.equiv eq_recarg cmp_labels t1 t2)
- then failwith "bad recursive trees"
+ then user_err Pp.(str "Bad recursive tree: found " ++ fnl ()
+ ++ Rtree.pp_tree prrecarg t1 ++ fnl () ++ str " when expected " ++ fnl ()
+ ++ Rtree.pp_tree prrecarg t2)
(* if t1=t2 then () else msg_warning (str"TODO: check recursive positions")*)
let check_positivity env_ar mind params nrecp inds =
@@ -555,14 +564,23 @@ let check_subtyping cumi paramsctxt env inds =
We must produce the substitution σ : [ Var(i) -> Var (i + n) | 0 <= i < n]
and push the constraints [ Var(n) ... Var(2n - 1) |- cst{σ} ], together
with the cumulativity constraints [ cumul_cst ]. *)
- let len = AUContext.size (ACumulativityInfo.univ_context cumi) in
- let inst = Instance.of_array (Array.init len (fun i -> Level.var (i + len))) in
+ let uctx = ACumulativityInfo.univ_context cumi in
+ let len = AUContext.size uctx in
+ let inst = Instance.of_array @@ Array.init len (fun i -> Level.var (i + len)) in
+
let other_context = ACumulativityInfo.univ_context cumi in
let uctx_other = UContext.make (inst, AUContext.instantiate inst other_context) in
- let cumul_context = AUContext.repr (ACumulativityInfo.subtyp_context cumi) in
- let cumul_cst = UContext.constraints cumul_context in
+ let cumul_cst =
+ Array.fold_left_i (fun i csts var ->
+ match var with
+ | Variance.Irrelevant -> csts
+ | Variance.Covariant -> Constraint.add (Level.var i,Le,Level.var (i+len)) csts
+ | Variance.Invariant -> Constraint.add (Level.var i,Eq,Level.var (i+len)) csts)
+ Constraint.empty (ACumulativityInfo.variance cumi)
+ in
let env = Environ.push_context uctx_other env in
let env = Environ.add_constraints cumul_cst env in
+
(* process individual inductive types: *)
Array.iter (fun { mind_user_lc = lc; mind_arity = arity } ->
match arity with
@@ -586,6 +604,8 @@ let check_inductive env kn mib =
Univ.AUContext.repr (Univ.ACumulativityInfo.univ_context cumi)
in
let env = Environ.push_context ind_ctx env in
+ (** Locally set the oracle for further typechecking *)
+ let env0 = Environ.set_oracle env mib.mind_typing_flags.conv_oracle in
(* check mind_record : TODO ? check #constructor = 1 ? *)
(* check mind_finite : always OK *)
(* check mind_ntypes *)
@@ -593,13 +613,13 @@ let check_inductive env kn mib =
user_err Pp.(str "not the right number of packets");
(* check mind_params_ctxt *)
let params = mib.mind_params_ctxt in
- let _ = check_ctxt env params in
+ let _ = check_ctxt env0 params in
(* check mind_nparams *)
if rel_context_nhyps params <> mib.mind_nparams then
user_err Pp.(str "number the right number of parameters");
(* mind_packets *)
(* - check arities *)
- let env_ar = typecheck_arity env params mib.mind_packets in
+ let env_ar = typecheck_arity env0 params mib.mind_packets in
(* - check constructor types *)
Array.iter (typecheck_one_inductive env_ar params mib) mib.mind_packets;
(* check the inferred subtyping relation *)
diff --git a/checker/inductive.ml b/checker/inductive.ml
index 22353ec16..8d426a3c0 100644
--- a/checker/inductive.ml
+++ b/checker/inductive.ml
@@ -381,7 +381,7 @@ let type_case_branches env (pind,largs) (p,pj) c =
let check_case_info env indsp ci =
let (mib,mip) = lookup_mind_specif env indsp in
if
- not (eq_ind indsp ci.ci_ind) ||
+ not (eq_ind_chk indsp ci.ci_ind) ||
(mib.mind_nparams <> ci.ci_npar) ||
(mip.mind_consnrealdecls <> ci.ci_cstr_ndecls) ||
(mip.mind_consnrealargs <> ci.ci_cstr_nargs)
@@ -435,20 +435,14 @@ type subterm_spec =
| Dead_code
| Not_subterm
-let eq_recarg r1 r2 = match r1, r2 with
-| Norec, Norec -> true
-| Mrec i1, Mrec i2 -> Names.eq_ind i1 i2
-| Imbr i1, Imbr i2 -> Names.eq_ind i1 i2
-| _ -> false
-
let eq_wf_paths = Rtree.equal eq_recarg
let inter_recarg r1 r2 = match r1, r2 with
| Norec, Norec -> Some r1
| Mrec i1, Mrec i2
| Imbr i1, Imbr i2
-| Mrec i1, Imbr i2 -> if Names.eq_ind i1 i2 then Some r1 else None
-| Imbr i1, Mrec i2 -> if Names.eq_ind i1 i2 then Some r2 else None
+| Mrec i1, Imbr i2 -> if Names.eq_ind_chk i1 i2 then Some r1 else None
+| Imbr i1, Mrec i2 -> if Names.eq_ind_chk i1 i2 then Some r2 else None
| _ -> None
let inter_wf_paths = Rtree.inter eq_recarg inter_recarg Norec
@@ -544,7 +538,7 @@ let lookup_subterms env ind =
let match_inductive ind ra =
match ra with
- | (Mrec i | Imbr i) -> eq_ind ind i
+ | (Mrec i | Imbr i) -> eq_ind_chk ind i
| Norec -> false
(* In {match c as z in ci y_s return P with |C_i x_s => t end}
@@ -645,7 +639,7 @@ let get_recargs_approx env tree ind args =
(* When the inferred tree allows it, we consider that we have a potential
nested inductive type *)
begin match dest_recarg tree with
- | Imbr kn' | Mrec kn' when eq_ind (fst ind_kn) kn' ->
+ | Imbr kn' | Mrec kn' when eq_ind_chk (fst ind_kn) kn' ->
build_recargs_nested ienv tree (ind_kn, largs)
| _ -> mk_norec
end
diff --git a/checker/main.mli b/checker/main.mli
new file mode 100644
index 000000000..e1555ba2e
--- /dev/null
+++ b/checker/main.mli
@@ -0,0 +1,10 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* This empty file avoids a race condition that occurs when compiling a .ml file
+ that does not have a corresponding .mli file *)
diff --git a/checker/mod_checking.ml b/checker/mod_checking.ml
index 4357a690e..7685863ea 100644
--- a/checker/mod_checking.ml
+++ b/checker/mod_checking.ml
@@ -26,6 +26,9 @@ let refresh_arity ar =
let check_constant_declaration env kn cb =
Flags.if_verbose Feedback.msg_notice (str " checking cst:" ++ prcon kn);
+ (** Locally set the oracle for further typechecking *)
+ let oracle = env.env_conv_oracle in
+ let env = Environ.set_oracle env cb.const_typing_flags.conv_oracle in
(** [env'] contains De Bruijn universe variables *)
let env' =
match cb.const_universes with
@@ -53,8 +56,12 @@ let check_constant_declaration env kn cb =
conv_leq envty j ty)
| None -> ()
in
- if constant_is_polymorphic cb then add_constant kn cb env
- else add_constant kn cb env'
+ let env =
+ if constant_is_polymorphic cb then add_constant kn cb env
+ else add_constant kn cb env'
+ in
+ (** Reset the value of the oracle *)
+ Environ.set_oracle env oracle
(** {6 Checking modules } *)
diff --git a/checker/print.mli b/checker/print.mli
new file mode 100644
index 000000000..3b2715de9
--- /dev/null
+++ b/checker/print.mli
@@ -0,0 +1,11 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+open Cic
+
+val print_pure_constr : constr -> unit
diff --git a/checker/reduction.ml b/checker/reduction.ml
index 9b8eac04c..2297c90b3 100644
--- a/checker/reduction.ml
+++ b/checker/reduction.ml
@@ -158,24 +158,17 @@ let compare_stacks f fmind lft1 stk1 lft2 stk2 =
let convert_inductive_instances cv_pb cumi u u' univs =
let len_instance =
Univ.AUContext.size (Univ.ACumulativityInfo.univ_context cumi) in
- let ind_subtypctx = Univ.ACumulativityInfo.subtyp_context cumi in
if not ((len_instance = Univ.Instance.length u) &&
(len_instance = Univ.Instance.length u')) then
anomaly (Pp.str "Invalid inductive subtyping encountered!")
else
- let comp_cst =
- let comp_subst = (Univ.Instance.append u u') in
- Univ.AUContext.instantiate comp_subst ind_subtypctx
- in
+ let variance = Univ.ACumulativityInfo.variance cumi in
let comp_cst =
match cv_pb with
- CONV ->
- let comp_cst' =
- let comp_subst = (Univ.Instance.append u' u) in
- Univ.AUContext.instantiate comp_subst ind_subtypctx
- in
- Univ.Constraint.union comp_cst comp_cst'
- | CUMUL -> comp_cst
+ | CONV ->
+ Univ.Variance.eq_constraints variance u u' Univ.Constraint.empty
+ | CUMUL ->
+ Univ.Variance.leq_constraints variance u u' Univ.Constraint.empty
in
if (Univ.check_constraints comp_cst univs) then () else raise NotConvertible
@@ -276,16 +269,29 @@ let in_whnf (t,stk) =
| (FFlex _ | FProd _ | FEvar _ | FInd _ | FAtom _ | FRel _ | FProj _) -> true
| FLOCKED -> assert false
-let oracle_order fl1 fl2 =
- match fl1,fl2 with
- ConstKey c1, ConstKey c2 -> (*height c1 > height c2*)false
- | _, ConstKey _ -> true
- | _ -> false
-
-let unfold_projection infos p c =
- let pb = lookup_projection p (infos_env infos) in
- let s = Zproj (pb.proj_npars, pb.proj_arg, p) in
- (c, s)
+let default_level = Level 0
+
+let get_strategy { var_opacity; cst_opacity } = function
+ | VarKey id ->
+ (try Names.Id.Map.find id var_opacity
+ with Not_found -> default_level)
+ | ConstKey (c, _) ->
+ (try Names.Cmap.find c cst_opacity
+ with Not_found -> default_level)
+ | RelKey _ -> Expand
+
+let oracle_order infos l2r k1 k2 =
+ let o = Closure.oracle_of_infos infos in
+ match get_strategy o k1, get_strategy o k2 with
+ | Expand, Expand -> l2r
+ | Expand, (Opaque | Level _) -> true
+ | (Opaque | Level _), Expand -> false
+ | Opaque, Opaque -> l2r
+ | Level _, Opaque -> true
+ | Opaque, Level _ -> false
+ | Level n1, Level n2 ->
+ if Int.equal n1 n2 then l2r
+ else n1 < n2
(* Conversion between [lft1]term1 and [lft2]term2 *)
let rec ccnv univ cv_pb infos lft1 lft2 term1 term2 =
@@ -339,7 +345,7 @@ and eqappr univ cv_pb infos (lft1,st1) (lft2,st2) =
with NotConvertible ->
(* else the oracle tells which constant is to be expanded *)
let (app1,app2) =
- if oracle_order fl1 fl2 then
+ if oracle_order infos false fl1 fl2 then
match unfold_reference infos fl1 with
| Some def1 -> ((lft1, whd_stack infos def1 v1), appr2)
| None ->
@@ -356,12 +362,12 @@ and eqappr univ cv_pb infos (lft1,st1) (lft2,st2) =
eqappr univ cv_pb infos app1 app2)
| (FProj (p1,c1), _) ->
- let (def1, s1) = unfold_projection infos p1 c1 in
- eqappr univ cv_pb infos (lft1, whd_stack infos def1 (s1 :: v1)) appr2
+ let s1 = unfold_projection (infos_env infos) p1 in
+ eqappr univ cv_pb infos (lft1, whd_stack infos c1 (s1 :: v1)) appr2
| (_, FProj (p2,c2)) ->
- let (def2, s2) = unfold_projection infos p2 c2 in
- eqappr univ cv_pb infos appr1 (lft2, whd_stack infos def2 (s2 :: v2))
+ let s2 = unfold_projection (infos_env infos) p2 in
+ eqappr univ cv_pb infos appr1 (lft2, whd_stack infos c2 (s2 :: v2))
(* other constructors *)
| (FLambda _, FLambda _) ->
diff --git a/checker/univ.ml b/checker/univ.ml
index 4f3131813..46b3ce680 100644
--- a/checker/univ.ml
+++ b/checker/univ.ml
@@ -881,14 +881,6 @@ type universe_level_subst = universe_level universe_map
(** A full substitution might involve algebraic universes *)
type universe_subst = universe universe_map
-let level_subst_of f =
- fun l ->
- try let u = f l in
- match Universe.level u with
- | None -> l
- | Some l -> l
- with Not_found -> l
-
module Instance : sig
type t = Level.t array
@@ -1011,12 +1003,42 @@ end
type abstract_universe_context = AUContext.t
+module Variance =
+struct
+ (** A universe position in the instance given to a cumulative
+ inductive can be the following. Note there is no Contravariant
+ case because [forall x : A, B <= forall x : A', B'] requires [A =
+ A'] as opposed to [A' <= A]. *)
+ type t = Irrelevant | Covariant | Invariant
+
+ let leq_constraint csts variance u u' =
+ match variance with
+ | Irrelevant -> csts
+ | Covariant -> Constraint.add (u, Le, u') csts
+ | Invariant -> Constraint.add (u, Eq, u') csts
+
+ let eq_constraint csts variance u u' =
+ match variance with
+ | Irrelevant -> csts
+ | Covariant | Invariant -> Constraint.add (u, Eq, u') csts
+
+ let leq_constraints variance u u' csts =
+ let len = Array.length u in
+ assert (len = Array.length u' && len = Array.length variance);
+ Array.fold_left3 leq_constraint csts variance u u'
+
+ let eq_constraints variance u u' csts =
+ let len = Array.length u in
+ assert (len = Array.length u' && len = Array.length variance);
+ Array.fold_left3 eq_constraint csts variance u u'
+end
+
module CumulativityInfo =
struct
- type t = universe_context * universe_context
+ type t = universe_context * Variance.t array
let univ_context (univcst, subtypcst) = univcst
- let subtyp_context (univcst, subtypcst) = subtypcst
+ let variance (univs, variance) = variance
end
diff --git a/checker/univ.mli b/checker/univ.mli
index 0eadc6801..8c0685e0b 100644
--- a/checker/univ.mli
+++ b/checker/univ.mli
@@ -150,8 +150,6 @@ type universe_level_subst_fn = universe_level -> universe_level
type universe_subst = universe universe_map
type universe_level_subst = universe_level universe_map
-val level_subst_of : universe_subst_fn -> universe_level_subst_fn
-
(** {6 Universe instances} *)
module Instance :
@@ -220,12 +218,25 @@ end
type abstract_universe_context = AUContext.t
+module Variance :
+sig
+ (** A universe position in the instance given to a cumulative
+ inductive can be the following. Note there is no Contravariant
+ case because [forall x : A, B <= forall x : A', B'] requires [A =
+ A'] as opposed to [A' <= A]. *)
+ type t = Irrelevant | Covariant | Invariant
+
+ val leq_constraints : t array -> Instance.t constraint_function
+ val eq_constraints : t array -> Instance.t constraint_function
+end
+
+
module ACumulativityInfo :
sig
type t
val univ_context : t -> abstract_universe_context
- val subtyp_context : t -> abstract_universe_context
+ val variance : t -> Variance.t array
end
diff --git a/checker/validate.ml b/checker/validate.ml
index 820040587..2624e6d49 100644
--- a/checker/validate.ml
+++ b/checker/validate.ml
@@ -49,8 +49,6 @@ let (/) (ctx:error_context) s : error_context = s::ctx
exception ValidObjError of string * error_context * Obj.t
let fail ctx o s = raise (ValidObjError(s,ctx,o))
-type func = error_context -> Obj.t -> unit
-
(* Check that object o is a block with tag t *)
let val_tag t ctx o =
if Obj.is_block o && Obj.tag o = t then ()
diff --git a/checker/validate.mli b/checker/validate.mli
new file mode 100644
index 000000000..7eed692a0
--- /dev/null
+++ b/checker/validate.mli
@@ -0,0 +1,9 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+val validate : bool -> Values.value -> 'a -> unit
diff --git a/checker/values.ml b/checker/values.ml
index 5a371164c..55e1cdb6f 100644
--- a/checker/values.ml
+++ b/checker/values.ml
@@ -13,7 +13,7 @@
To ensure this file is up-to-date, 'make' now compares the md5 of cic.mli
with a copy we maintain here:
-MD5 56ac4cade33eff3d26ed5cdadb580c7e checker/cic.mli
+MD5 483493b20fe91cc1bea4350a2db2f82d checker/cic.mli
*)
@@ -70,6 +70,8 @@ let v_map vk vd =
let v_hset v = v_map Int (v_set v)
let v_hmap vk vd = v_map Int (v_map vk vd)
+let v_pred v = v_pair v_bool (v_set v)
+
(* lib/future *)
let v_computation f =
Annot ("Future.computation",
@@ -108,10 +110,12 @@ let v_cstrs =
(v_tuple "univ_constraint"
[|v_level;v_enum "order_request" 3;v_level|]))
+let v_variance = v_enum "variance" 3
+
let v_instance = Annot ("instance", Array v_level)
let v_context = v_tuple "universe_context" [|v_instance;v_cstrs|]
let v_abs_context = v_context (* only for clarity *)
-let v_abs_cum_info = v_tuple "cumulativity_info" [|v_abs_context; v_context|]
+let v_abs_cum_info = v_tuple "cumulativity_info" [|v_abs_context; Array v_variance|]
let v_context_set = v_tuple "universe_context_set" [|v_hset v_level;v_cstrs|]
(** kernel/term *)
@@ -199,6 +203,17 @@ let v_lazy_constr =
let v_impredicative_set = v_enum "impr-set" 2
let v_engagement = v_impredicative_set
+let v_conv_level =
+ v_sum "conv_level" 2 [|[|Int|]|]
+
+let v_oracle =
+ v_tuple "oracle" [|
+ v_map v_id v_conv_level;
+ v_hmap v_cst v_conv_level;
+ v_pred v_id;
+ v_pred v_cst;
+ |]
+
let v_pol_arity =
v_tuple "polymorphic_arity" [|List(Opt v_level);v_univ|]
@@ -213,7 +228,7 @@ let v_projbody =
v_constr|]
let v_typing_flags =
- v_tuple "typing_flags" [|v_bool; v_bool|]
+ v_tuple "typing_flags" [|v_bool; v_bool; v_oracle|]
let v_const_univs = v_sum "constant_universes" 0 [|[|v_context_set|]; [|v_abs_context|]|]
@@ -372,22 +387,3 @@ let v_lib =
let v_opaques = Array (v_computation v_constr)
let v_univopaques =
Opt (Tuple ("univopaques",[|Array (v_computation v_context_set);v_context_set;v_bool|]))
-
-(** Registering dynamic values *)
-
-module IntOrd =
-struct
- type t = int
- let compare (x : t) (y : t) = compare x y
-end
-
-module IntMap = Map.Make(IntOrd)
-
-let dyn_table : value IntMap.t ref = ref IntMap.empty
-
-let register_dyn name t =
- dyn_table := IntMap.add name t !dyn_table
-
-let find_dyn name =
- try IntMap.find name !dyn_table
- with Not_found -> Any
diff --git a/checker/values.mli b/checker/values.mli
new file mode 100644
index 000000000..aad8fd5f4
--- /dev/null
+++ b/checker/values.mli
@@ -0,0 +1,26 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+type value =
+ | Any
+ | Fail of string
+ | Tuple of string * value array
+ | Sum of string * int * value array array
+ | Array of value
+ | List of value
+ | Opt of value
+ | Int
+ | String
+ | Annot of string * value
+ | Dyn
+
+val v_univopaques : value
+val v_libsum : value
+val v_lib : value
+val v_opaques : value
+val v_stm_seg : value
diff --git a/checker/votour.ml b/checker/votour.ml
index 77c9999c4..8cb97a2b1 100644
--- a/checker/votour.ml
+++ b/checker/votour.ml
@@ -210,7 +210,6 @@ let access_list v o pos =
let access_block o = match Repr.repr o with
| BLOCK (tag, os) -> (tag, os)
| _ -> raise Exit
-let access_int o = match Repr.repr o with INT i -> i | _ -> raise Exit
(** raises Exit if the object has not the expected structure *)
exception Forbidden
@@ -249,8 +248,7 @@ let rec get_children v o pos = match v with
|Dyn ->
begin match Repr.repr o with
| BLOCK (0, [|id; o|]) ->
- let n = access_int id in
- let tpe = find_dyn n in
+ let tpe = Any in
[|(Int, id, 0 :: pos); (tpe, o, 1 :: pos)|]
| _ -> raise Exit
end
@@ -395,7 +393,7 @@ let visit_vo f =
| None -> ()
done
-let main =
+let () =
if not !Sys.interactive then
Arg.parse [] visit_vo
("votour: guided tour of a Coq .vo or .vi file\n"^
diff --git a/checker/votour.mli b/checker/votour.mli
new file mode 100644
index 000000000..e1555ba2e
--- /dev/null
+++ b/checker/votour.mli
@@ -0,0 +1,10 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* This empty file avoids a race condition that occurs when compiling a .ml file
+ that does not have a corresponding .mli file *)
diff --git a/clib/clib.mllib b/clib/clib.mllib
index bd5ddb152..0b5d9826f 100644
--- a/clib/clib.mllib
+++ b/clib/clib.mllib
@@ -12,6 +12,7 @@ CString
CStack
Int
+Range
HMap
Bigint
diff --git a/clib/range.ml b/clib/range.ml
new file mode 100644
index 000000000..86a078633
--- /dev/null
+++ b/clib/range.ml
@@ -0,0 +1,91 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2016 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+type 'a tree =
+| Leaf of 'a
+| Node of 'a * 'a tree * 'a tree
+
+type 'a t = Nil | Cons of int * 'a tree * 'a t
+
+let oob () = invalid_arg "index out of bounds"
+
+let empty = Nil
+
+let cons x l = match l with
+| Cons (h1, t1, Cons (h2, t2, rem)) ->
+ if Int.equal h1 h2 then Cons (1 + h1 + h2, Node (x, t1, t2), rem)
+ else Cons (1, Leaf x, l)
+| _ -> Cons (1, Leaf x, l)
+
+let is_empty = function
+| Nil -> true
+| _ -> false
+
+let rec tree_get h t i = match t with
+| Leaf x ->
+ if i = 0 then x else oob ()
+| Node (x, t1, t2) ->
+ if i = 0 then x
+ else
+ let h = h / 2 in
+ if i <= h then tree_get h t1 (i - 1) else tree_get h t2 (i - h - 1)
+
+let rec get l i = match l with
+| Nil -> oob ()
+| Cons (h, t, rem) ->
+ if i < h then tree_get h t i else get rem (i - h)
+
+let length l =
+ let rec length accu = function
+ | Nil -> accu
+ | Cons (h, _, l) -> length (h + accu) l
+ in
+ length 0 l
+
+let rec tree_map f = function
+| Leaf x -> Leaf (f x)
+| Node (x, t1, t2) -> Node (f x, tree_map f t1, tree_map f t2)
+
+let rec map f = function
+| Nil -> Nil
+| Cons (h, t, l) -> Cons (h, tree_map f t, map f l)
+
+let rec tree_fold_left f accu = function
+| Leaf x -> f accu x
+| Node (x, t1, t2) ->
+ tree_fold_left f (tree_fold_left f (f accu x) t1) t2
+
+let rec fold_left f accu = function
+| Nil -> accu
+| Cons (_, t, l) -> fold_left f (tree_fold_left f accu t) l
+
+let rec tree_fold_right f t accu = match t with
+| Leaf x -> f x accu
+| Node (x, t1, t2) ->
+ f x (tree_fold_right f t1 (tree_fold_right f t2 accu))
+
+let rec fold_right f l accu = match l with
+| Nil -> accu
+| Cons (_, t, l) -> tree_fold_right f t (fold_right f l accu)
+
+let hd = function
+| Nil -> failwith "hd"
+| Cons (_, Leaf x, _) -> x
+| Cons (_, Node (x, _, _), _) -> x
+
+let tl = function
+| Nil -> failwith "tl"
+| Cons (_, Leaf _, l) -> l
+| Cons (h, Node (_, t1, t2), l) ->
+ let h = h / 2 in
+ Cons (h, t1, Cons (h, t2, l))
+
+let rec skipn n l =
+ if n = 0 then l
+ else if is_empty l then failwith "List.skipn"
+ else skipn (pred n) (tl l)
diff --git a/clib/range.mli b/clib/range.mli
new file mode 100644
index 000000000..ae7684ffa
--- /dev/null
+++ b/clib/range.mli
@@ -0,0 +1,37 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2016 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(** Skewed lists
+
+ This is a purely functional datastructure isomorphic to usual lists, except
+ that it features a O(log n) lookup while preserving the O(1) cons operation.
+
+*)
+
+(** {5 Constructors} *)
+
+type +'a t
+
+val empty : 'a t
+val cons : 'a -> 'a t -> 'a t
+
+(** {5 List operations} *)
+
+val is_empty : 'a t -> bool
+val length : 'a t -> int
+val map : ('a -> 'b) -> 'a t -> 'b t
+val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a
+val fold_right : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b
+val hd : 'a t -> 'a
+val tl : 'a t -> 'a t
+
+val skipn : int -> 'a t -> 'a t
+
+(** {5 Indexing operations} *)
+
+val get : 'a t -> int -> 'a
diff --git a/configure.ml b/configure.ml
index a86b78ba5..06a7dd822 100644
--- a/configure.ml
+++ b/configure.ml
@@ -276,7 +276,8 @@ module Prefs = struct
let flambda_flags = ref []
let debug = ref true
let profile = ref false
- let annotate = ref false
+ let bin_annot = ref false
+ let annot = ref false
let bytecodecompiler = ref true
let nativecompiler = ref (not (os_type_win32 || os_type_cygwin))
let coqwebsite = ref "http://coq.inria.fr/"
@@ -342,8 +343,12 @@ let args_options = Arg.align [
" Do not add debugging information in the Coq executables";
"-profile", Arg.Set Prefs.profile,
" Add profiling information in the Coq executables";
- "-annotate", Arg.Set Prefs.annotate,
- " Dumps ml annotation files while compiling Coq";
+ "-annotate", Arg.Unit (fun () -> printf "*Warning* -annotate is deprecated. Please use -annot or -bin-annot instead.\n"),
+ " Deprecated. Please use -annot or -bin-annot instead";
+ "-annot", Arg.Set Prefs.annot,
+ " Dumps ml text annotation files while compiling Coq (e.g. for Tuareg)";
+ "-bin-annot", Arg.Set Prefs.bin_annot,
+ " Dumps ml binary annotation files while compiling Coq (e.g. for Merlin)";
"-bytecode-compiler", arg_bool Prefs.bytecodecompiler,
"(yes|no) Enable Coq's bytecode reduction machine (VM)";
"-native-compiler", arg_bool Prefs.nativecompiler,
@@ -388,10 +393,8 @@ let reset_caml_find c o = c.find <- o
let coq_debug_flag = if !Prefs.debug then "-g" else ""
let coq_profile_flag = if !Prefs.profile then "-p" else ""
-let coq_annotate_flag =
- if !Prefs.annotate
- then if program_in_path "ocamlmerlin" then "-bin-annot" else "-annot"
- else ""
+let coq_annot_flag = if !Prefs.annot then "-annot" else ""
+let coq_bin_annot_flag = if !Prefs.bin_annot then "-bin-annot" else ""
(* This variable can be overriden only for debug purposes, use with
care. *)
@@ -561,7 +564,7 @@ let coq_warn_error =
(* Flags used to compile Coq and plugins (via coq_makefile) *)
let caml_flags =
- Printf.sprintf "-thread -rectypes %s %s %s" coq_warnings coq_annotate_flag coq_safe_string
+ Printf.sprintf "-thread -rectypes %s %s %s %s" coq_warnings coq_annot_flag coq_bin_annot_flag coq_safe_string
(* Flags used to compile Coq but _not_ plugins (via coq_makefile) *)
let coq_caml_flags =
@@ -758,24 +761,22 @@ let get_lablgtkdir () =
let check_lablgtk_version src dir = match src with
| Manual | Stdlib ->
- let test accu f =
- if accu then
- let test = sprintf "grep -q -w %s %S/glib.mli" f dir in
- Sys.command test = 0
- else false
- in
- let heuristics = [
- "convert_with_fallback";
- "wrap_poll_func"; (** Introduced in lablgtk 2.16 *)
- ] in
- let ans = List.fold_left test true heuristics in
- if ans then printf "Warning: could not check the version of lablgtk2.\n";
- (ans, "an unknown version")
+ printf "Warning: could not check the version of lablgtk2.\nMake sure your version is at least 2.18.3.\n";
+ (true, "an unknown version")
| OCamlFind ->
let v, _ = tryrun camlexec.find ["query"; "-format"; "%v"; "lablgtk2"] in
try
let vi = List.map s2i (numeric_prefix_list v) in
- ([2; 16] <= vi, v)
+ if vi < [2; 16; 0] then
+ (false, v)
+ else if vi < [2; 18; 3] then
+ begin
+ (* Version 2.18.3 is known to report incorrectly as 2.18.0, and Launchpad packages report as version 2.16.0 due to a misconfigured META file; see https://bugs.launchpad.net/ubuntu/+source/lablgtk2/+bug/1577236 *)
+ printf "Warning: Your installed lablgtk reports as %s.\n It is possible that the installed version is actually more recent\n but reports an incorrect version. If the installed version is\n actually more recent than 2.18.3, that's fine; if it is not,\n CoqIDE will compile but may be very unstable.\n" v;
+ (true, "an unknown version")
+ end
+ else
+ (true, v)
with _ -> (false, v)
let pr_ide = function No -> "no" | Byte -> "only bytecode" | Opt -> "native"
@@ -802,7 +803,7 @@ let check_coqide () =
if dir = "" then set_ide No "LablGtk2 not found";
let (ok, version) = check_lablgtk_version via dir in
let found = sprintf "LablGtk2 found (%s, %s)" (get_source via) version in
- if not ok then set_ide No (found^", but too old (required >= 2.16, found " ^ version ^ ")");
+ if not ok then set_ide No (found^", but too old (required >= 2.18.3, found " ^ version ^ ")");
(* We're now sure to produce at least one kind of coqide *)
lablgtkdir := shorten_camllib dir;
if !Prefs.coqide = Some Byte then set_ide Byte (found^", bytecode requested");
@@ -865,13 +866,6 @@ let strip =
if strip = "" then "strip" else strip
end
-(** * md5sum command *)
-
-let md5sum =
- select_command "Don’t know how to compute MD5 checksums…" [
- "md5sum", [], [ "--version" ];
- "md5", ["-q"], [ "-s" ; "''" ];
- ]
(** * Documentation : do we have latex, hevea, ... *)
@@ -1056,7 +1050,7 @@ let _ = print_summary ()
let write_dbg_wrapper f =
safe_remove f;
- let o = open_out f in
+ let o = open_out_bin f in (* _bin to avoid adding \r on Cygwin/Windows *)
let pr s = fprintf o s in
pr "#!/bin/sh\n\n";
pr "###### ocamldebug-coq : a wrapper around ocamldebug for Coq ######\n\n";
@@ -1250,8 +1244,6 @@ let write_makefile f =
pr "# Unix systems and profiling: true\n";
pr "# Unix systems and no profiling: strip\n";
pr "STRIP=%s\n\n" strip;
- pr "#the command md5sum\n";
- pr "MD5SUM=%s\n\n" md5sum;
pr "# LablGTK\n";
pr "COQIDEINCLUDES=%s\n\n" !lablgtkincludes;
pr "# CoqIde (no/byte/opt)\n";
diff --git a/default.nix b/default.nix
index 3dd24bac4..af2a13a84 100644
--- a/default.nix
+++ b/default.nix
@@ -36,6 +36,7 @@ stdenv.mkDerivation rec {
ocaml
findlib
camlp5_strict
+ num
]) ++ (if buildIde then [
diff --git a/dev/README b/dev/README
index f97e2a769..453f85f0d 100644
--- a/dev/README
+++ b/dev/README
@@ -1,4 +1,4 @@
-This directory contains informations and tools to help developing the
+This directory contains information and tools to help develop the
Coq system
======================
@@ -6,30 +6,30 @@ This directory contains informations and tools to help developing the
Debugging and profiling (in current directory - see doc/debugging.txt)
-----------------------
-ocamldebug-coq: to launch ocaml debugger
+ocamldebug-coq: to launch ocaml debugger (generated by the configure script)
-db: to install pretty-printers from ocaml debugger
-base_db: to install raw pretty-printers from ocaml debugger
+db: to install pretty-printers from ocaml debugger
+base_db: to install raw pretty-printers from ocaml debugger
-include: to install pretty-printers from ocaml toplevel
+include: to install pretty-printers from ocaml toplevel (use with the coq Drop command)
base_include: to install raw pretty-printers from ocaml toplevel
-vm_printers.ml, dev_printers.ml: ML pretty-printers for debugging
+vm_printers.ml, top_printers.ml: ML pretty-printers for debugging
-Miscellaneous informations about the code (directory doc)
+Miscellaneous information about the code (directory doc)
-----------------------------------------
-changes.txt: (partial) per-version summary of the evolutions of Coq ML source
-style.txt: a few style recommendations for writing Coq ML files
-debugging.txt: help for debugging or profiling
-universes.txt: help to debug universes
-translate.txt: help to use coq translator
+changes.md: (partial) per-version summary of the evolution of Coq ML source
+style.txt: a few style recommendations for writing Coq ML files
+debugging.md: help for debugging or profiling
+universes.txt: help for debugging universes
+translate.txt: help for using coq translator
extensions.txt: some help about TACTIC EXTEND
-header: standard header for Coq ML files
-perf-analysis: analysis of perfs measured on the compilation of user contribs
-cic.dtd: official dtd of the calc. of ind. constr. for im/ex-portation
+header: standard header for Coq ML files
+perf-analysis: analysis of perfs measured on the compilation of user contribs
+cic.dtd: official dtd of the calc. of ind. constr. for im/ex-portation
Documentation of ML interfaces using ocamldoc (directory ocamldoc/html)
diff --git a/dev/base_include b/dev/base_include
index 2a4ad4a15..472c0c605 100644
--- a/dev/base_include
+++ b/dev/base_include
@@ -52,7 +52,7 @@
#install_printer ppvblock;;
#install_printer (* bigint *) ppbigint;;
#install_printer (* loc *) pploc;;
-#install_printer (* substitution *) prsubst;;
+#install_printer (* substitution *) ppsubst;;
(* Open main files *)
diff --git a/dev/build/osx/make-macos-dmg.sh b/dev/build/osx/make-macos-dmg.sh
index cfcc09b32..dc33838f1 100755
--- a/dev/build/osx/make-macos-dmg.sh
+++ b/dev/build/osx/make-macos-dmg.sh
@@ -25,4 +25,4 @@ mkdir -p _build
# Temporary countermeasure to hdiutil error 5341
# head -c9703424 /dev/urandom > $DMGDIR/.padding
-hdiutil create -imagekey zlib-level=9 -volname CoqIDE_$VERSION -srcfolder $DMGDIR -ov -format UDZO _build/CoqIDE_$VERSION.dmg
+hdiutil create -imagekey zlib-level=9 -volname coq-$VERSION-installer-macos -srcfolder $DMGDIR -ov -format UDZO _build/coq-$VERSION-installer-macos.dmg
diff --git a/dev/build/windows/patches_coq/coq_new.nsi b/dev/build/windows/patches_coq/coq_new.nsi
index 48f1d3759..2c2f0fa47 100644
--- a/dev/build/windows/patches_coq/coq_new.nsi
+++ b/dev/build/windows/patches_coq/coq_new.nsi
@@ -15,7 +15,7 @@
SetCompressor lzma
!define MY_PRODUCT "Coq" ;Define your own software name here
-!define OUTFILE "coq-installer-${VERSION}-${ARCH}.exe"
+!define OUTFILE "coq-${VERSION}-installer-windows-${ARCH}.exe"
!include "MUI2.nsh"
!include "FileAssociation.nsh"
diff --git a/dev/ci/README.md b/dev/ci/README.md
index f4423558c..bb13587e9 100644
--- a/dev/ci/README.md
+++ b/dev/ci/README.md
@@ -103,6 +103,8 @@ 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.
+See also [`test-suite/README.md`](/test-suite/README.md) for information about adding new tests to the test-suite.
+
Travis specific information
---------------------------
diff --git a/dev/ci/appveyor.bat b/dev/ci/appveyor.bat
index 72ee89962..dec6f0d18 100644
--- a/dev/ci/appveyor.bat
+++ b/dev/ci/appveyor.bat
@@ -25,7 +25,7 @@ if %USEOPAM% == false (
-destcyg=%CYGROOT% -destcoq=%DESTCOQ% -cygcache=%CYGCACHE% ^
-setup %CYGROOT%\%SETUP% || GOTO ErrorExit
copy "%CYGROOT%\build\coq-local\dev\nsis\*.exe" dev\nsis || GOTO ErrorExit
- 7z a coq-opensource-archive-%ARCHLONG%.zip %CYGROOT%\build\tarballs\* || GOTO ErrorExit
+ 7z a coq-opensource-archive-windows-%ARCHLONG%.zip %CYGROOT%\build\tarballs\* || GOTO ErrorExit
)
if %USEOPAM% == true (
diff --git a/dev/ci/ci-basic-overlay.sh b/dev/ci/ci-basic-overlay.sh
index 232b8a56e..784da6f97 100644
--- a/dev/ci/ci-basic-overlay.sh
+++ b/dev/ci/ci-basic-overlay.sh
@@ -4,141 +4,143 @@
# Maybe we should just use Ruby to have real objects...
+# : "${foo:=bar}" sets foo to "bar" if it is unset or null
+
########################################################################
# MathComp
########################################################################
-: ${mathcomp_CI_BRANCH:=master}
-: ${mathcomp_CI_GITURL:=https://github.com/math-comp/math-comp.git}
+: "${mathcomp_CI_BRANCH:=master}"
+: "${mathcomp_CI_GITURL:=https://github.com/math-comp/math-comp.git}"
########################################################################
# UniMath
########################################################################
-: ${UniMath_CI_BRANCH:=master}
-: ${UniMath_CI_GITURL:=https://github.com/UniMath/UniMath.git}
+: "${UniMath_CI_BRANCH:=master}"
+: "${UniMath_CI_GITURL:=https://github.com/UniMath/UniMath.git}"
########################################################################
# Unicoq + Metacoq
########################################################################
-: ${unicoq_CI_BRANCH:=master}
-: ${unicoq_CI_GITURL:=https://github.com/unicoq/unicoq.git}
+: "${unicoq_CI_BRANCH:=master}"
+: "${unicoq_CI_GITURL:=https://github.com/unicoq/unicoq.git}"
-: ${metacoq_CI_BRANCH:=master}
-: ${metacoq_CI_GITURL:=https://github.com/MetaCoq/MetaCoq.git}
+: "${metacoq_CI_BRANCH:=master}"
+: "${metacoq_CI_GITURL:=https://github.com/MetaCoq/MetaCoq.git}"
########################################################################
# Mathclasses + Corn
########################################################################
-: ${math_classes_CI_BRANCH:=master}
-: ${math_classes_CI_GITURL:=https://github.com/math-classes/math-classes.git}
+: "${math_classes_CI_BRANCH:=master}"
+: "${math_classes_CI_GITURL:=https://github.com/math-classes/math-classes.git}"
-: ${Corn_CI_BRANCH:=master}
-: ${Corn_CI_GITURL:=https://github.com/c-corn/corn.git}
+: "${Corn_CI_BRANCH:=master}"
+: "${Corn_CI_GITURL:=https://github.com/c-corn/corn.git}"
########################################################################
# Iris
########################################################################
-: ${stdpp_CI_BRANCH:=master}
-: ${stdpp_CI_GITURL:=https://gitlab.mpi-sws.org/robbertkrebbers/coq-stdpp.git}
+: "${stdpp_CI_BRANCH:=master}"
+: "${stdpp_CI_GITURL:=https://gitlab.mpi-sws.org/robbertkrebbers/coq-stdpp.git}"
-: ${Iris_CI_BRANCH:=master}
-: ${Iris_CI_GITURL:=https://gitlab.mpi-sws.org/FP/iris-coq.git}
+: "${Iris_CI_BRANCH:=master}"
+: "${Iris_CI_GITURL:=https://gitlab.mpi-sws.org/FP/iris-coq.git}"
-: ${lambdaRust_CI_BRANCH:=master}
-: ${lambdaRust_CI_GITURL:=https://gitlab.mpi-sws.org/FP/LambdaRust-coq.git}
+: "${lambdaRust_CI_BRANCH:=master}"
+: "${lambdaRust_CI_GITURL:=https://gitlab.mpi-sws.org/FP/LambdaRust-coq.git}"
########################################################################
# HoTT
########################################################################
-: ${HoTT_CI_BRANCH:=master}
-: ${HoTT_CI_GITURL:=https://github.com/HoTT/HoTT.git}
+: "${HoTT_CI_BRANCH:=master}"
+: "${HoTT_CI_GITURL:=https://github.com/HoTT/HoTT.git}"
########################################################################
# Ltac2
########################################################################
-: ${ltac2_CI_BRANCH:=master}
-: ${ltac2_CI_GITURL:=https://github.com/ppedrot/ltac2.git}
+: "${ltac2_CI_BRANCH:=master}"
+: "${ltac2_CI_GITURL:=https://github.com/ppedrot/ltac2.git}"
########################################################################
# GeoCoq
########################################################################
-: ${GeoCoq_CI_BRANCH:=master}
-: ${GeoCoq_CI_GITURL:=https://github.com/GeoCoq/GeoCoq.git}
+: "${GeoCoq_CI_BRANCH:=master}"
+: "${GeoCoq_CI_GITURL:=https://github.com/GeoCoq/GeoCoq.git}"
########################################################################
# Flocq
########################################################################
-: ${Flocq_CI_BRANCH:=master}
-: ${Flocq_CI_GITURL:=https://scm.gforge.inria.fr/anonscm/git/flocq/flocq.git}
+: "${Flocq_CI_BRANCH:=master}"
+: "${Flocq_CI_GITURL:=https://gitlab.inria.fr/flocq/flocq.git}"
########################################################################
# Coquelicot
########################################################################
-: ${Coquelicot_CI_BRANCH:=master}
-: ${Coquelicot_CI_GITURL:=https://scm.gforge.inria.fr/anonscm/git/coquelicot/coquelicot.git}
+: "${Coquelicot_CI_BRANCH:=master}"
+: "${Coquelicot_CI_GITURL:=https://scm.gforge.inria.fr/anonscm/git/coquelicot/coquelicot.git}"
########################################################################
# CompCert
########################################################################
-: ${CompCert_CI_BRANCH:=master}
-: ${CompCert_CI_GITURL:=https://github.com/AbsInt/CompCert.git}
+: "${CompCert_CI_BRANCH:=master}"
+: "${CompCert_CI_GITURL:=https://github.com/AbsInt/CompCert.git}"
########################################################################
# VST
########################################################################
-: ${VST_CI_BRANCH:=master}
-: ${VST_CI_GITURL:=https://github.com/PrincetonUniversity/VST.git}
+: "${VST_CI_BRANCH:=master}"
+: "${VST_CI_GITURL:=https://github.com/PrincetonUniversity/VST.git}"
########################################################################
# fiat_parsers
########################################################################
-: ${fiat_parsers_CI_BRANCH:=master}
-: ${fiat_parsers_CI_GITURL:=https://github.com/mit-plv/fiat.git}
+: "${fiat_parsers_CI_BRANCH:=master}"
+: "${fiat_parsers_CI_GITURL:=https://github.com/mit-plv/fiat.git}"
########################################################################
# fiat_crypto
########################################################################
-: ${fiat_crypto_CI_BRANCH:=master}
-: ${fiat_crypto_CI_GITURL:=https://github.com/mit-plv/fiat-crypto.git}
+: "${fiat_crypto_CI_BRANCH:=master}"
+: "${fiat_crypto_CI_GITURL:=https://github.com/mit-plv/fiat-crypto.git}"
########################################################################
# formal-topology
########################################################################
-: ${formal_topology_CI_BRANCH:=ci}
-: ${formal_topology_CI_GITURL:=https://github.com/bmsherman/topology.git}
+: "${formal_topology_CI_BRANCH:=ci}"
+: "${formal_topology_CI_GITURL:=https://github.com/bmsherman/topology.git}"
########################################################################
# coq-dpdgraph
########################################################################
-: ${coq_dpdgraph_CI_BRANCH:=coq-trunk}
-: ${coq_dpdgraph_CI_GITURL:=https://github.com/Karmaki/coq-dpdgraph.git}
+: "${coq_dpdgraph_CI_BRANCH:=coq-trunk}"
+: "${coq_dpdgraph_CI_GITURL:=https://github.com/Karmaki/coq-dpdgraph.git}"
########################################################################
# CoLoR
########################################################################
-: ${CoLoR_CI_BRANCH:=master}
-: ${CoLoR_CI_GITURL:=https://github.com/fblanqui/color.git}
+: "${CoLoR_CI_BRANCH:=master}"
+: "${CoLoR_CI_GITURL:=https://github.com/fblanqui/color.git}"
########################################################################
# SF
########################################################################
-: ${sf_lf_CI_TARURL:=https://www.cis.upenn.edu/~bcpierce/sf/lf-current/lf.tgz}
-: ${sf_plf_CI_TARURL:=https://www.cis.upenn.edu/~bcpierce/sf/plf-current/plf.tgz}
-: ${sf_vfa_CI_TARURL:=https://www.cis.upenn.edu/~bcpierce/sf/vfa-current/vfa.tgz}
+: "${sf_lf_CI_TARURL:=https://www.cis.upenn.edu/~bcpierce/sf/lf-current/lf.tgz}"
+: "${sf_plf_CI_TARURL:=https://www.cis.upenn.edu/~bcpierce/sf/plf-current/plf.tgz}"
+: "${sf_vfa_CI_TARURL:=https://www.cis.upenn.edu/~bcpierce/sf/vfa-current/vfa.tgz}"
########################################################################
# TLC
########################################################################
-: ${tlc_CI_BRANCH:=master}
-: ${tlc_CI_GITURL:=https://gforge.inria.fr/git/tlc/tlc.git}
+: "${tlc_CI_BRANCH:=master}"
+: "${tlc_CI_GITURL:=https://gforge.inria.fr/git/tlc/tlc.git}"
########################################################################
# Bignums
########################################################################
-: ${bignums_CI_BRANCH:=master}
-: ${bignums_CI_GITURL:=https://github.com/coq/bignums.git}
+: "${bignums_CI_BRANCH:=master}"
+: "${bignums_CI_GITURL:=https://github.com/coq/bignums.git}"
########################################################################
# Equations
########################################################################
-: ${Equations_CI_BRANCH:=8.8+alpha}
-: ${Equations_CI_GITURL:=https://github.com/mattam82/Coq-Equations.git}
+: "${Equations_CI_BRANCH:=8.8+alpha}"
+: "${Equations_CI_GITURL:=https://github.com/mattam82/Coq-Equations.git}"
diff --git a/dev/ci/ci-common.sh b/dev/ci/ci-common.sh
index 58c90ff11..d7a356930 100644
--- a/dev/ci/ci-common.sh
+++ b/dev/ci/ci-common.sh
@@ -2,9 +2,13 @@
set -xe
+# default value for NJOBS
+: "${NJOBS:=1}"
+export NJOBS
+
if [ -n "${GITLAB_CI}" ];
then
- export COQBIN=`pwd`/_install_ci/bin
+ export COQBIN="$PWD/_install_ci/bin"
export CI_BRANCH="$CI_COMMIT_REF_NAME"
else
if [ -n "${TRAVIS}" ];
@@ -15,8 +19,10 @@ else
then
export CI_PULL_REQUEST="$CIRCLE_PR_NUMBER"
export CI_BRANCH="$CIRCLE_BRANCH"
+ else # assume local
+ export CI_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
fi
- export COQBIN=`pwd`/bin
+ export COQBIN="$PWD/bin"
fi
export PATH="$COQBIN:$PATH"
@@ -26,14 +32,16 @@ export COQBIN="$COQBIN/"
ls "$COQBIN"
# Where we clone and build external developments
-CI_BUILD_DIR=`pwd`/_build_ci
+CI_BUILD_DIR="$PWD/_build_ci"
-for overlay in ${ci_dir}/user-overlays/*.sh; do
- source ${overlay}
+# shellcheck source=ci-basic-overlay.sh
+source "${ci_dir}/ci-basic-overlay.sh"
+for overlay in "${ci_dir}"/user-overlays/*.sh; do
+ # shellcheck source=/dev/null
+ source "${overlay}"
done
-source ${ci_dir}/ci-basic-overlay.sh
-mathcomp_CI_DIR=${CI_BUILD_DIR}/math-comp
+mathcomp_CI_DIR="${CI_BUILD_DIR}/math-comp"
# git_checkout branch url dest will create a git repository
# in <dest> (if it does not exist already) and checkout the
@@ -46,15 +54,16 @@ git_checkout()
# Allow an optional 4th argument for the commit
local _COMMIT=${4:-FETCH_HEAD}
- local _DEPTH=$(if [ -z "${4}" ]; then echo "--depth 1"; fi)
-
- mkdir -p ${_DEST}
- ( cd ${_DEST} && \
- if [ ! -d .git ] ; then git clone ${_DEPTH} ${_URL} . ; fi && \
- echo "Checking out ${_DEST}" && \
- git fetch ${_URL} ${_BRANCH} && \
- git checkout ${_COMMIT} && \
- echo "${_DEST}: `git log -1 --format='%s | %H | %cd | %aN'`" )
+ local _DEPTH=()
+ if [ -z "${4}" ]; then _DEPTH=(--depth 1); fi
+
+ mkdir -p "${_DEST}"
+ ( cd "${_DEST}" && \
+ if [ ! -d .git ] ; then git clone "${_DEPTH[@]}" "${_URL}" . ; fi && \
+ echo "Checking out ${_DEST}" && \
+ git fetch "${_URL}" "${_BRANCH}" && \
+ git checkout "${_COMMIT}" && \
+ echo "${_DEST}: $(git log -1 --format='%s | %H | %cd | %aN')" )
}
checkout_mathcomp()
@@ -79,8 +88,8 @@ install_ssreflect()
{
echo 'Installing ssreflect' && echo -en 'travis_fold:start:ssr.install\\r'
- checkout_mathcomp ${mathcomp_CI_DIR}
- ( cd ${mathcomp_CI_DIR}/mathcomp && \
+ checkout_mathcomp "${mathcomp_CI_DIR}"
+ ( cd "${mathcomp_CI_DIR}/mathcomp" && \
sed -i.bak '/ssrtest/d' Make && \
sed -i.bak '/odd_order/d' Make && \
sed -i.bak '/all\/all.v/d' Make && \
diff --git a/dev/ci/ci-compcert.sh b/dev/ci/ci-compcert.sh
index fc3cef342..6a0ce2aef 100755
--- a/dev/ci/ci-compcert.sh
+++ b/dev/ci/ci-compcert.sh
@@ -5,7 +5,7 @@ source ${ci_dir}/ci-common.sh
CompCert_CI_DIR=${CI_BUILD_DIR}/CompCert
-opam install -j ${NJOBS} -y menhir
+opam install -j "$NJOBS" -y menhir
git_checkout ${CompCert_CI_BRANCH} ${CompCert_CI_GITURL} ${CompCert_CI_DIR}
( cd ${CompCert_CI_DIR} && ./configure -ignore-coq-version x86_32-linux && make && make check-proof )
diff --git a/dev/ci/ci-iris-lambda-rust.sh b/dev/ci/ci-iris-lambda-rust.sh
index cf24d202d..267e13359 100755
--- a/dev/ci/ci-iris-lambda-rust.sh
+++ b/dev/ci/ci-iris-lambda-rust.sh
@@ -34,8 +34,8 @@ git_checkout ${stdpp_CI_BRANCH} ${stdpp_URL_PARTS[0]} ${stdpp_CI_DIR} ${stdpp_UR
# Build std++
( cd ${stdpp_CI_DIR} && make && make install )
-# Build iris
-( cd ${Iris_CI_DIR} && make && make install )
+# Build and validate (except on Travis, i.e., skip if TRAVIS is non-empty) Iris
+( cd ${Iris_CI_DIR} && make && (test -n "${TRAVIS}" || make validate) && make install )
# Build lambdaRust
( cd ${lambdaRust_CI_DIR} && make && make install )
diff --git a/dev/ci/user-overlays/06482-ppedrot-check-poly-effects.sh b/dev/ci/user-overlays/06482-ppedrot-check-poly-effects.sh
new file mode 100644
index 000000000..78789a6fc
--- /dev/null
+++ b/dev/ci/user-overlays/06482-ppedrot-check-poly-effects.sh
@@ -0,0 +1,4 @@
+if [ "$TRAVIS_PULL_REQUEST" = "6483" ] || [ "$TRAVIS_BRANCH" = "check-poly-effects" ]; then
+ HoTT_CI_BRANCH=check-poly-effects
+ HoTT_CI_GITURL=https://github.com/ppedrot/HoTT.git
+fi
diff --git a/dev/ci/user-overlays/06535-fix-push-rel-to-named.sh b/dev/ci/user-overlays/06535-fix-push-rel-to-named.sh
new file mode 100644
index 000000000..8a50fb111
--- /dev/null
+++ b/dev/ci/user-overlays/06535-fix-push-rel-to-named.sh
@@ -0,0 +1,4 @@
+if [ "$CI_PULL_REQUEST" = "6535" ] || [ "$CI_BRANCH" = "fix-push-rel-to-named" ]; then
+ Equations_CI_BRANCH=fix-6535
+ Equations_CI_GITURL=https://github.com/ppedrot/Coq-Equations
+fi
diff --git a/dev/ci/user-overlays/06686-ccnv-no-proj.sh b/dev/ci/user-overlays/06686-ccnv-no-proj.sh
new file mode 100644
index 000000000..3a3ab44e0
--- /dev/null
+++ b/dev/ci/user-overlays/06686-ccnv-no-proj.sh
@@ -0,0 +1,4 @@
+if [ "$CI_PULL_REQUEST" = "6686" ] || [ "$CI_BRANCH" = "ccnv-no-proj" ]; then
+ Equations_CI_BRANCH=ccnv-fixes
+ Equations_CI_GITURL=https://github.com/SkySkimmer/Coq-Equations
+fi
diff --git a/dev/db b/dev/db
index 24ae3957e..2f8c13485 100644
--- a/dev/db
+++ b/dev/db
@@ -1,37 +1,67 @@
source core.dbg
load_printer top_printers.cmo
+install_printer Top_printers.pP
install_printer Top_printers.ppfuture
-
install_printer Top_printers.ppid
-install_printer Top_printers.ppidset
-install_printer Top_printers.ppevar
-install_printer Top_printers.ppevarsubst
-install_printer Top_printers.ppexistentialfilter
-install_printer Top_printers.ppexistentialset
-install_printer Top_printers.ppintset
install_printer Top_printers.pplab
-install_printer Top_printers.ppdir
install_printer Top_printers.ppmbid
+install_printer Top_printers.ppdir
install_printer Top_printers.ppmp
-install_printer Top_printers.ppkn
install_printer Top_printers.ppcon
-install_printer Top_printers.ppwf_paths
+install_printer Top_printers.ppproj
+install_printer Top_printers.ppkn
install_printer Top_printers.ppmind
+install_printer Top_printers.ppind
install_printer Top_printers.ppsp
install_printer Top_printers.ppqualid
install_printer Top_printers.ppclindex
-install_printer Top_printers.ppbigint
-install_printer Top_printers.pp_transparent_state
-
-install_printer Top_printers.pppattern
-install_printer Top_printers.ppglob_constr
-
+install_printer Top_printers.ppscheme
+install_printer Top_printers.ppwf_paths
+install_printer Top_printers.ppevar
install_printer Top_printers.ppconstr
+install_printer Top_printers.ppsconstr
install_printer Top_printers.ppeconstr
+install_printer Top_printers.ppconstr_expr
+install_printer Top_printers.ppglob_constr
+install_printer Top_printers.pppattern
+install_printer Top_printers.ppfconstr
+install_printer Top_printers.ppbigint
+install_printer Top_printers.ppintset
+install_printer Top_printers.ppidset
+install_printer Top_printers.ppidmapgen
+install_printer Top_printers.ppididmap
+install_printer Top_printers.ppconstrunderbindersidmap
+install_printer Top_printers.ppevarsubst
+install_printer Top_printers.ppunbound_ltac_var_map
+install_printer Top_printers.ppclosure
+install_printer Top_printers.ppclosedglobconstr
+install_printer Top_printers.ppclosedglobconstridmap
+install_printer Top_printers.ppglobal
+install_printer Top_printers.ppconst
+install_printer Top_printers.ppvar
+install_printer Top_printers.ppj
+install_printer Top_printers.ppsubst
+install_printer Top_printers.ppdelta
+install_printer Top_printers.pp_idpred
+install_printer Top_printers.pp_cpred
+install_printer Top_printers.pp_transparent_state
+install_printer Top_printers.pp_stack_t
+install_printer Top_printers.pp_cst_stack_t
+install_printer Top_printers.pp_state_t
+install_printer Top_printers.ppmetas
+install_printer Top_printers.ppevm
+install_printer Top_printers.ppexistentialset
+install_printer Top_printers.ppexistentialfilter
+install_printer Top_printers.ppclenv
+install_printer Top_printers.ppgoalgoal
+install_printer Top_printers.ppgoal
+install_printer Top_printers.pphintdb
+install_printer Top_printers.ppproofview
+install_printer Top_printers.ppopenconstr
+install_printer Top_printers.pproof
install_printer Top_printers.ppuni
-install_printer Top_printers.ppuniverses
-install_printer Top_printers.ppconstraints
+install_printer Top_printers.ppuni_level
install_printer Top_printers.ppuniverse_set
install_printer Top_printers.ppuniverse_instance
install_printer Top_printers.ppuniverse_context
@@ -40,34 +70,19 @@ install_printer Top_printers.ppuniverse_subst
install_printer Top_printers.ppuniverse_opt_subst
install_printer Top_printers.ppuniverse_level_subst
install_printer Top_printers.ppevar_universe_context
+install_printer Top_printers.ppconstraints
+install_printer Top_printers.ppuniverseconstraints
+install_printer Top_printers.ppuniverse_context_future
install_printer Top_printers.ppcumulativity_info
install_printer Top_printers.ppabstract_cumulativity_info
-install_printer Top_printers.pptype
-install_printer Top_printers.ppj
-install_printer Top_printers.ppenv
+install_printer Top_printers.ppuniverses
install_printer Top_printers.ppnamedcontextval
-install_printer Top_printers.pp_stack_t
-install_printer Top_printers.pp_cst_stack_t
-
-install_printer Top_printers.ppmetas
-install_printer Top_printers.ppevm
-install_printer Top_printers.ppgoalgoal
-install_printer Top_printers.ppgoal
-install_printer Top_printers.ppproofview
-install_printer Top_printers.pphintdb
-
+install_printer Top_printers.ppenv
install_printer Top_printers.pptac
install_printer Top_printers.ppobj
install_printer Top_printers.pploc
-install_printer Top_printers.prsubst
-install_printer Top_printers.prdelta
-install_printer Top_printers.ppfconstr
+install_printer Top_printers.pp_argument_type
+install_printer Top_printers.pp_generic_argument
install_printer Top_printers.ppgenarginfo
install_printer Top_printers.ppgenargargt
install_printer Top_printers.ppist
-install_printer Top_printers.ppconstrunderbindersidmap
-install_printer Top_printers.ppunbound_ltac_var_map
-install_printer Top_printers.ppididmap
-install_printer Top_printers.ppidmapgen
-install_printer Top_printers.ppclosure
-install_printer Top_printers.ppclosedglobconstr
diff --git a/COMPATIBILITY b/dev/doc/COMPATIBILITY
index b5fed7f01..a81afca32 100644
--- a/COMPATIBILITY
+++ b/dev/doc/COMPATIBILITY
@@ -1,3 +1,6 @@
+Note: this file isn't used anymore. Incompatibilities are documented
+as part of CHANGES.
+
Potential sources of incompatibilities between Coq V8.6 and V8.7
----------------------------------------------------------------
@@ -5,10 +8,6 @@ Potential sources of incompatibilities between Coq V8.6 and V8.7
error rather than a warning when the superfluous name is already in
use. The easy fix is to remove the superfluous name.
-- Proofs ending in "Qed exporting ident, .., ident" are not supported
- anymore. Constants generated during `abstract` are kept private to the
- local environment.
-
Potential sources of incompatibilities between Coq V8.5 and V8.6
----------------------------------------------------------------
diff --git a/dev/doc/changes.md b/dev/doc/changes.md
index e616bd566..aef62b009 100644
--- a/dev/doc/changes.md
+++ b/dev/doc/changes.md
@@ -58,6 +58,17 @@ Declaration of printers for arguments used only in vernac command
happen. An alternative is to register the corresponding argument as
a value, using "Geninterp.register_val0 wit None".
+### STM API
+
+The STM API has seen a general overhaul. The main change is the
+introduction of a "Coq document" type, which all operations now take
+as a parameter. This effectively functionalize the STM API and will
+allow in the future to handle several documents simultaneously.
+
+The main remarkable point is that key implicit global parameters such
+as load-paths and required modules are now arguments to the document
+creation function. This helps enforcing some key invariants.
+
### XML IDE Protocol
- Before 8.8, `Query` only executed the first command present in the
diff --git a/dev/doc/debugging.md b/dev/doc/debugging.md
index fa145d498..fd3cbd1bc 100644
--- a/dev/doc/debugging.md
+++ b/dev/doc/debugging.md
@@ -22,8 +22,8 @@ Debugging from Coq toplevel using Caml trace mechanism
printers too.
-Debugging from Caml debugger
-============================
+Debugging with ocamldebug from Emacs
+====================================
Requires [Tuareg mode](https://github.com/ocaml/tuareg) in Emacs.\
Coq must be configured with `-local` (`./configure -local`) and the
@@ -59,6 +59,29 @@ Debugging from Caml debugger
from the debugger. If this happens, unset the variable, re-start Emacs, and
run the debugger again.
+Debugging with ocamldebug from the command line
+===============================================
+
+In the `coq` directory:
+1. (on Cygwin/Windows) Pass the `-no-custom` option to the `configure` script before building Coq.
+2. Run `make` (to compile the .v files)
+3. Run `make byte`
+4. (on Cygwin/Windows) Add the full pathname of the directory `.../kernel/byterun` to your bash PATH.
+ Alternatively, copy the file `kernel/byterun/dllcoqrun.dll` to a directory that is in the PATH. (The
+ CAML_LD_LIBRARY_PATH mechanism described at the end of INSTALL isn't working.)
+5. Run `dev/ocamldebug-coq bin/coqtop.byte` (on Cygwin/Windows, use `... bin/coqtop.byte.exe`)
+6. Enter `source db` to load printers
+7. Enter `set arguments -coqlib .` so Coq can find plugins, theories, etc.
+8. See the ocamldebug manual for more information. A few points:
+ - use `break @ Printer 501` to set a breakpoint on line 501 in the Printer module (printer.ml).
+ `break` can be abbreviated as `b`.
+ - `backtrace` or `bt` to see the call stack
+ - `step` or `s` goes into called functions; `next` or `n` skips over them
+ - `list` or `li` shows the code just before and after the current stack frame
+ - `print <var>` or `p <var>` to see the value of a variable
+Note that `make byte` doesn't recompile .v files. `make` recompiles all of them if there
+are changes in any .ml file--safer but much slower.
+
Global gprof-based profiling
============================
diff --git a/dev/doc/setup.txt b/dev/doc/setup.txt
index 26f3d0ddc..0003a2c21 100644
--- a/dev/doc/setup.txt
+++ b/dev/doc/setup.txt
@@ -58,30 +58,12 @@ behave as expected.
A note about rlwrap
-------------------
-Running "coqtop" under "rlwrap" is possible, but (on Debian) there is a catch. If you try:
-
- cd ~/git/coq
- rlwrap bin/coqtop
-
-you will get an error:
+When using "rlwrap coqtop" make sure the version of rlwrap is at least
+0.42, otherwise you will get
rlwrap: error: Couldn't read completions from /usr/share/rlwrap/completions/coqtop: No such file or directory
-This is a known issue:
-
- https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=779692
-
-It was fixed upstream in version 0.42, and in a Debian package that, at the time of writing, is not part of Debian stable/testing/sid archives but only of Debian experimental.
-
- https://packages.debian.org/experimental/rlwrap
-
-The quick solution is to grab it from there, since it installs fine on Debian stable (jessie).
-
- cd /tmp
- wget http://ftp.us.debian.org/debian/pool/main/r/rlwrap/rlwrap_0.42-1_amd64.deb
- sudo dpkg -i rlwrap_0.42-1_amd64.deb
-
-After that, "rlwrap" works fine with "coqtop".
+If this happens either update or use an alternate readline wrapper like "ledit".
How to install and configure Merlin (for Emacs)
diff --git a/dev/include b/dev/include
index 0d34595f4..b982f4c9f 100644
--- a/dev/include
+++ b/dev/include
@@ -36,7 +36,6 @@
#install_printer (* constraints *) ppconstraints;;
#install_printer (* univ constraints *) ppuniverseconstraints;;
#install_printer (* universe *) ppuni;;
-#install_printer (* universes *) ppuniverse;;
#install_printer (* universes *) ppuniverses;;
#install_printer (* univ level *) ppuni_level;;
#install_printer (* univ context *) ppuniverse_context;;
diff --git a/dev/lint-repository.sh b/dev/lint-repository.sh
index 87a829746..ee9c8777a 100755
--- a/dev/lint-repository.sh
+++ b/dev/lint-repository.sh
@@ -9,12 +9,12 @@
CODE=0
-if [ "(" "-n" "${TRAVIS_PULL_REQUEST}" ")" "-a" "(" "${TRAVIS_PULL_REQUEST}" "!=" "false" ")" ];
+if [ -n "${TRAVIS_PULL_REQUEST}" ] && [ "${TRAVIS_PULL_REQUEST}" != false ];
then
# skip PRs from before the linter existed
if [ -z "$(git ls-tree --name-only "${TRAVIS_PULL_REQUEST_SHA}" dev/lint-commits.sh)" ];
then
- 2>&1 echo "Linting skipped: pull request older than the linter."
+ 1>&2 echo "Linting skipped: pull request older than the linter."
exit 0
fi
@@ -22,14 +22,13 @@ then
# can still check that they don't worsen.
CUR_HEAD=${TRAVIS_COMMIT_RANGE%%...*}
PR_HEAD=${TRAVIS_COMMIT_RANGE##*...}
- MERGE_BASE=$(git merge-base $CUR_HEAD $PR_HEAD)
- dev/lint-commits.sh $MERGE_BASE $PR_HEAD || CODE=1
+ MERGE_BASE=$(git merge-base "$CUR_HEAD" "$PR_HEAD")
+ dev/lint-commits.sh "$MERGE_BASE" "$PR_HEAD" || CODE=1
fi
# Check that the files with 'whitespace' gitattribute end in a newline.
# xargs exit status is 123 if any file failed the test
-find . "(" -path ./.git -prune ")" -type f \
--o "(" -exec dev/tools/should-check-whitespace.sh '{}' ';' ")" \
--print0 | xargs -0 -L 1 dev/tools/check-eof-newline.sh || CODE=1
+find . "(" -path ./.git -prune ")" -o -type f -print0 |
+ xargs -0 dev/tools/check-eof-newline.sh || CODE=1
exit $CODE
diff --git a/dev/nsis/coq.nsi b/dev/nsis/coq.nsi
index 80da84517..f48013cf2 100755
--- a/dev/nsis/coq.nsi
+++ b/dev/nsis/coq.nsi
@@ -13,7 +13,7 @@ SetCompressor lzma
!define MY_PRODUCT "Coq" ;Define your own software name here
!define COQ_SRC_PATH "..\.."
-!define OUTFILE "coq-installer-${VERSION}-${ARCH}.exe"
+!define OUTFILE "coq-${VERSION}-installer-windows-${ARCH}.exe"
!include "MUI2.nsh"
!include "FileAssociation.nsh"
diff --git a/dev/ocamldebug-coq.run b/dev/ocamldebug-coq.run
index 3850c05fd..3cbccab44 100644
--- a/dev/ocamldebug-coq.run
+++ b/dev/ocamldebug-coq.run
@@ -17,7 +17,7 @@ export CAML_LD_LIBRARY_PATH=$COQTOP/kernel/byterun:$CAML_LD_LIBRARY_PATH
exec $OCAMLDEBUG \
-I $CAMLP4LIB -I +threads \
-I $COQTOP \
- -I $COQTOP/config -I $COQTOP/printing -I $COQTOP/grammar \
+ -I $COQTOP/config -I $COQTOP/printing -I $COQTOP/grammar -I $COQTOP/clib \
-I $COQTOP/lib -I $COQTOP/intf -I $COQTOP/kernel -I $COQTOP/kernel/byterun \
-I $COQTOP/library -I $COQTOP/engine \
-I $COQTOP/pretyping -I $COQTOP/parsing -I $COQTOP/vernac \
diff --git a/dev/set_raw_db b/dev/set_raw_db
deleted file mode 100644
index 5caff7e5d..000000000
--- a/dev/set_raw_db
+++ /dev/null
@@ -1 +0,0 @@
-install_printer Top_printers.ppconstrdb
diff --git a/dev/tools/backport-pr.sh b/dev/tools/backport-pr.sh
index 4c4dbe1e9..e4359f703 100755
--- a/dev/tools/backport-pr.sh
+++ b/dev/tools/backport-pr.sh
@@ -1,10 +1,11 @@
#!/usr/bin/env bash
-# Usage: dev/tools/backport-pr.sh <PR number>
+# Usage: dev/tools/backport-pr.sh <PR number> [--stop-before-merging]
set -e
PRNUM=$1
+OPTION=$2
if ! git log master --grep "Merge PR #${PRNUM}" | grep "." > /dev/null; then
echo "PR #${PRNUM} does not exist."
@@ -49,6 +50,19 @@ else
fi
+if ! git diff --exit-code HEAD ${BRANCH} -- "*.mli"; then
+ echo
+ read -p "Some mli files are modified. Bypass? [y/N] " -n 1 -r
+ echo
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
+ exit 1
+ fi
+fi
+
+if [[ "${OPTION}" == "--stop-before-merging" ]]; then
+ exit 0
+fi
+
git merge -S --no-ff ${BRANCH} -m "${MESSAGE}"
git branch -d ${BRANCH}
diff --git a/dev/tools/check-eof-newline.sh b/dev/tools/check-eof-newline.sh
index 1c578c05c..9e4c8661d 100755
--- a/dev/tools/check-eof-newline.sh
+++ b/dev/tools/check-eof-newline.sh
@@ -1,9 +1,14 @@
#!/usr/bin/env bash
-if [ -z "$(tail -c 1 "$1")" ]
-then
- exit 0
-else
- echo "No newline at end of file $1!"
- exit 1
-fi
+CODE=0
+for f in "$@"; do
+ if git ls-files --error-unmatch "$f" >/dev/null 2>&1 && \
+ git check-attr whitespace -- "$f" | grep -q -v -e 'unset$' -e 'unspecified$' && \
+ [ -n "$(tail -c 1 "$f")" ]
+ then
+ echo "No newline at end of file $f!"
+ CODE=1
+ fi
+done
+
+exit "$CODE"
diff --git a/dev/tools/github-check-prs.py b/dev/tools/github-check-prs.py
new file mode 100755
index 000000000..beb26d910
--- /dev/null
+++ b/dev/tools/github-check-prs.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python3
+
+# Requires PyGithub https://pypi.python.org/pypi/PyGithub, for instance
+# debian package: python3-github
+# nix: nix-shell -p python3 python3Packages.PyGithub --run ./github-check-rebase.py
+from github import Github
+import argparse
+
+REPO = "coq/coq"
+REBASE_LABEL="needs: rebase"
+
+parser = argparse.ArgumentParser()
+parser.add_argument("--token-file", type=argparse.FileType('r'))
+args = parser.parse_args()
+
+if args.token_file is None:
+ token = input("Github access token: ").strip()
+else:
+ token = args.token_file.read().rstrip("\n")
+ args.token_file.close()
+
+if token == "":
+ print ("Warning: using the GitHub API without a token")
+ print ("We may run into rate limit issues")
+ g = Github()
+else:
+ g = Github(token)
+
+repo = g.get_repo(REPO)
+
+for pull in repo.get_pulls():
+ # if conflicts then dirty
+ # otherwise blocked (because I have no rights)
+ dirty = pull.mergeable_state == "dirty"
+ labelled = False
+ for label in repo.get_issue(pull.number).get_labels():
+ if label.name == REBASE_LABEL:
+ labelled = True
+ if labelled and not dirty:
+ print ("PR #" + str(pull.number) + " is not dirty but is labelled")
+ print ("("+ pull.html_url +")")
+ elif dirty and not labelled:
+ print ("PR #" + str(pull.number) + " is dirty and not labelled")
+ print ("("+ pull.html_url +")")
+ else:
+ # give some feedback so the user can see we didn't crash
+ print ("PR #" + str(pull.number) + " OK")
diff --git a/dev/tools/merge-pr.sh b/dev/tools/merge-pr.sh
index 0c4a79bfd..9f24960ff 100755
--- a/dev/tools/merge-pr.sh
+++ b/dev/tools/merge-pr.sh
@@ -9,18 +9,18 @@ set -e
PR=$1
-CURRENT_LOCAL_BRANCH=`git rev-parse --abbrev-ref HEAD`
-REMOTE=`git config --get branch.$CURRENT_LOCAL_BRANCH.remote`
-git fetch $REMOTE refs/pull/$PR/head
+CURRENT_LOCAL_BRANCH=$(git rev-parse --abbrev-ref HEAD)
+REMOTE=$(git config --get "branch.$CURRENT_LOCAL_BRANCH.remote")
+git fetch "$REMOTE" "refs/pull/$PR/head"
API=https://api.github.com/repos/coq/coq
-BASE_BRANCH=`curl -s $API/pulls/$PR | jq -r '.base.label'`
+BASE_BRANCH=$(curl -s "$API/pulls/$PR" | jq -r '.base.label')
-COMMIT=`git rev-parse FETCH_HEAD`
-STATUS=`curl -s $API/commits/$COMMIT/status | jq -r '.state'`
+COMMIT=$(git rev-parse FETCH_HEAD)
+STATUS=$(curl -s "$API/commits/$COMMIT/status" | jq -r '.state')
-if [ $BASE_BRANCH != "coq:$CURRENT_LOCAL_BRANCH" ]; then
+if [ "$BASE_BRANCH" != "coq:$CURRENT_LOCAL_BRANCH" ]; then
echo "Wrong base branch"
read -p "Bypass? [y/N] " -n 1 -r
echo
@@ -30,7 +30,7 @@ if [ $BASE_BRANCH != "coq:$CURRENT_LOCAL_BRANCH" ]; then
fi
fi;
-if [ $STATUS != "success" ]; then
+if [ "$STATUS" != "success" ]; then
echo "CI status is \"$STATUS\""
read -p "Bypass? [y/N] " -n 1 -r
echo
@@ -40,10 +40,10 @@ if [ $STATUS != "success" ]; then
fi
fi;
-git merge -S --no-ff FETCH_HEAD -m "Merge PR #$PR: `curl -s $API/pulls/$PR | jq -r '.title'`" -e
+git merge -S --no-ff FETCH_HEAD -m "Merge PR #$PR: $(curl -s "$API/pulls/$PR" | jq -r '.title')" -e
# TODO: improve this check
-if [[ `git diff $REMOTE/$CURRENT_LOCAL_BRANCH dev/ci` ]]; then
+if ! git diff --quiet "$REMOTE/$CURRENT_LOCAL_BRANCH" -- dev/ci; then
echo "******************************************"
echo "** WARNING: does this PR have overlays? **"
echo "******************************************"
diff --git a/dev/tools/should-check-whitespace.sh b/dev/tools/should-check-whitespace.sh
deleted file mode 100755
index d85d65107..000000000
--- a/dev/tools/should-check-whitespace.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/env bash
-
-# determine if a file has whitespace checking enabled in .gitattributes
-
-git ls-files --error-unmatch "$1" >/dev/null 2>&1 &&
-git check-attr whitespace -- "$1" | grep -q -v -e 'unset$' -e 'unspecified$'
diff --git a/dev/tools/sudo-apt-get-update.sh b/dev/tools/sudo-apt-get-update.sh
new file mode 100755
index 000000000..f8bf6bed4
--- /dev/null
+++ b/dev/tools/sudo-apt-get-update.sh
@@ -0,0 +1,4 @@
+#!/usr/bin/env bash
+
+(sudo apt-get update "$@" 2>&1 || echo 'E: update failed') | tee /tmp/apt.err
+! grep -q '^\(E:\|W: Failed to fetch\)' /tmp/apt.err || exit $?
diff --git a/dev/top_printers.ml b/dev/top_printers.ml
index ff3825787..af38ce4b8 100644
--- a/dev/top_printers.ml
+++ b/dev/top_printers.ml
@@ -50,13 +50,13 @@ let ppqualid qid = pp(pr_qualid qid)
let ppclindex cl = pp(Classops.pr_cl_index cl)
let ppscheme k = pp (Ind_tables.pr_scheme_kind k)
-let pprecarg = function
+let prrecarg = function
| Declarations.Norec -> str "Norec"
| Declarations.Mrec (mind,i) ->
str "Mrec[" ++ MutInd.print mind ++ pr_comma () ++ int i ++ str "]"
| Declarations.Imbr (mind,i) ->
str "Imbr[" ++ MutInd.print mind ++ pr_comma () ++ int i ++ str "]"
-let ppwf_paths x = pp (Rtree.pp_tree pprecarg x)
+let ppwf_paths x = pp (Rtree.pp_tree prrecarg x)
(* term printers *)
let envpp pp = let sigma,env = Pfedit.get_current_context () in pp env sigma
@@ -65,8 +65,6 @@ let ppevar evk = pp (Evar.print evk)
let ppconstr x = pp (Termops.print_constr (EConstr.of_constr x))
let ppeconstr x = pp (Termops.print_constr x)
let ppconstr_expr x = pp (Ppconstr.pr_constr_expr x)
-let ppconstrdb x = pp(Flags.with_option rawdebug Termops.print_constr (EConstr.of_constr x))
-let ppterm = ppconstr
let ppsconstr x = ppconstr (Mod_subst.force_constr x)
let ppconstr_univ x = Constrextern.with_universes ppconstr x
let ppglob_constr = (fun x -> pp(pr_lglob_constr_env (Global.env()) x))
@@ -111,7 +109,7 @@ let prconstrunderbindersidmap = pridmap (fun _ (l,c) ->
let ppconstrunderbindersidmap l = pp (prconstrunderbindersidmap l)
let ppunbound_ltac_var_map l = ppidmap (fun _ arg ->
- str"<genarg:" ++ pr_argument_type(genarg_tag arg) ++ str">")
+ str"<genarg:" ++ pr_argument_type(genarg_tag arg) ++ str">") l
open Ltac_pretype
let rec pr_closure {idents=idents;typed=typed;untyped=untyped} =
@@ -149,8 +147,8 @@ let genppj f j = let (c,t) = f j in (c ++ str " : " ++ t)
let ppj j = pp (genppj (envpp pr_ljudge_env) j)
-let prsubst s = pp (Mod_subst.debug_pr_subst s)
-let prdelta s = pp (Mod_subst.debug_pr_delta s)
+let ppsubst s = pp (Mod_subst.debug_pr_subst s)
+let ppdelta s = pp (Mod_subst.debug_pr_delta s)
let pp_idpred s = pp (pr_idpred s)
let pp_cpred s = pp (pr_cpred s)
@@ -200,9 +198,8 @@ let pppftreestate p = pp(print_pftreestate p)
let pproof p = pp(Proof.pr_proof p)
-let ppuni u = pp(pr_uni u)
+let ppuni u = pp(Universe.pr u)
let ppuni_level u = pp (Level.pr u)
-let ppuniverse u = pp (str"[" ++ Universe.pr u ++ str"]")
let prlev = Universes.pr_with_global_universes
let ppuniverse_set l = pp (LSet.pr prlev l)
diff --git a/dev/top_printers.mli b/dev/top_printers.mli
new file mode 100644
index 000000000..7b5e4a0b6
--- /dev/null
+++ b/dev/top_printers.mli
@@ -0,0 +1,173 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(** Printers for the ocaml toplevel. *)
+
+val pp : Pp.t -> unit
+val pP : Pp.t -> unit (* with surrounding box *)
+
+val ppfuture : 'a Future.computation -> unit
+
+val ppid : Names.Id.t -> unit
+val pplab : Names.Label.t -> unit
+val ppmbid : Names.MBId.t -> unit
+val ppdir : Names.DirPath.t -> unit
+val ppmp : Names.ModPath.t -> unit
+val ppcon : Names.Constant.t -> unit
+val ppproj : Names.Projection.t -> unit
+val ppkn : Names.KerName.t -> unit
+val ppmind : Names.MutInd.t -> unit
+val ppind : Names.inductive -> unit
+
+val ppsp : Libnames.full_path -> unit
+val ppqualid : Libnames.qualid -> unit
+
+val ppclindex : Classops.cl_index -> unit
+
+val ppscheme : 'a Ind_tables.scheme_kind -> unit
+
+val prrecarg : Declarations.recarg -> Pp.t
+val ppwf_paths : Declarations.recarg Rtree.t -> unit
+
+val pr_evar : Evar.t -> Pp.t
+val ppevar : Evar.t -> unit
+
+(* Multiple printers for Constr.t *)
+val ppconstr : Constr.t -> unit (* by Termops printer *)
+val ppconstr_univ : Constr.t -> unit
+
+(* Extern as type *)
+val pptype : Constr.types -> unit
+
+val ppsconstr : Constr.constr Mod_subst.substituted -> unit
+val ppeconstr : EConstr.constr -> unit (* Termops printer *)
+val ppconstr_expr : Constrexpr.constr_expr -> unit
+val ppglob_constr : 'a Glob_term.glob_constr_g -> unit
+val pppattern : Pattern.constr_pattern -> unit
+val ppfconstr : CClosure.fconstr -> unit
+
+val ppbigint : Bigint.bigint -> unit
+
+val ppintset : Int.Set.t -> unit
+val ppidset : Names.Id.Set.t -> unit
+
+val pridmap : (Names.Id.Map.key -> 'a -> Pp.t) -> 'a Names.Id.Map.t -> Pp.t
+val ppidmap : (Names.Id.Map.key -> 'a -> Pp.t) -> 'a Names.Id.Map.t -> unit
+
+val pridmapgen : 'a Names.Id.Map.t -> Pp.t
+val ppidmapgen : 'a Names.Id.Map.t -> unit
+
+val prididmap : Names.Id.t Names.Id.Map.t -> Pp.t
+val ppididmap : Names.Id.t Names.Id.Map.t -> unit
+
+val prconstrunderbindersidmap :
+ (Names.Id.t list * EConstr.constr) Names.Id.Map.t -> Pp.t
+val ppconstrunderbindersidmap :
+ (Names.Id.t list * EConstr.constr) Names.Id.Map.t -> unit
+
+val ppevarsubst :
+ (Constr.t * Constr.t option * Names.Id.Map.key) list Names.Id.Map.t -> unit
+
+val ppunbound_ltac_var_map :
+ 'a Genarg.generic_argument Names.Id.Map.t -> unit
+
+val pr_closure : Ltac_pretype.closure -> Pp.t
+val pr_closed_glob_constr_idmap :
+ Ltac_pretype.closed_glob_constr Names.Id.Map.t -> Pp.t
+val pr_closed_glob_constr : Ltac_pretype.closed_glob_constr -> Pp.t
+val ppclosure : Ltac_pretype.closure -> unit
+val ppclosedglobconstr : Ltac_pretype.closed_glob_constr -> unit
+val ppclosedglobconstridmap :
+ Ltac_pretype.closed_glob_constr Names.Id.Map.t -> unit
+
+val ppglobal : Globnames.global_reference -> unit
+
+val ppconst :
+ Names.KerName.t * (Constr.constr, 'a) Environ.punsafe_judgment -> unit
+val ppvar : Names.Id.t * Constr.constr -> unit
+
+val genppj : ('a -> Pp.t * Pp.t) -> 'a -> Pp.t
+val ppj : EConstr.unsafe_judgment -> unit
+
+val ppsubst : Mod_subst.substitution -> unit
+val ppdelta : Mod_subst.delta_resolver -> unit
+
+val pp_idpred : Names.Id.Pred.t -> unit
+val pp_cpred : Names.Cpred.t -> unit
+val pp_transparent_state : Names.transparent_state -> unit
+
+val pp_stack_t : Constr.t Reductionops.Stack.t -> unit
+val pp_cst_stack_t : Reductionops.Cst_stack.t -> unit
+val pp_state_t : Reductionops.state -> unit
+
+val ppmetas : Evd.Metaset.t -> unit
+val ppevm : Evd.evar_map -> unit
+val ppevmall : Evd.evar_map -> unit
+
+val pr_existentialset : Evar.Set.t -> Pp.t
+val ppexistentialset : Evar.Set.t -> unit
+
+val ppexistentialfilter : Evd.Filter.t -> unit
+
+val ppclenv : Clenv.clausenv -> unit
+
+val ppgoalgoal : Goal.goal -> unit
+
+val ppgoal : Proof_type.goal Evd.sigma -> unit
+(* also print evar map *)
+val ppgoalsigma : Proof_type.goal Evd.sigma -> unit
+
+val pphintdb : Hints.Hint_db.t -> unit
+val ppproofview : Proofview.proofview -> unit
+val ppopenconstr : Evd.open_constr -> unit
+
+val pproof : Proof.t -> unit
+
+(* Universes *)
+val ppuni : Univ.Universe.t -> unit
+val ppuni_level : Univ.Level.t -> unit (* raw *)
+val prlev : Univ.Level.t -> Pp.t (* with global names (does this work?) *)
+val ppuniverse_set : Univ.LSet.t -> unit
+val ppuniverse_instance : Univ.Instance.t -> unit
+val ppuniverse_context : Univ.UContext.t -> unit
+val ppuniverse_context_set : Univ.ContextSet.t -> unit
+val ppuniverse_subst : Univ.universe_subst -> unit
+val ppuniverse_opt_subst : Universes.universe_opt_subst -> unit
+val ppuniverse_level_subst : Univ.universe_level_subst -> unit
+val ppevar_universe_context : UState.t -> unit
+val ppconstraints : Univ.Constraint.t -> unit
+val ppuniverseconstraints : Universes.Constraints.t -> unit
+val ppuniverse_context_future : Univ.UContext.t Future.computation -> unit
+val ppcumulativity_info : Univ.CumulativityInfo.t -> unit
+val ppabstract_cumulativity_info : Univ.ACumulativityInfo.t -> unit
+val ppuniverses : UGraph.t -> unit
+
+val ppnamedcontextval : Environ.named_context_val -> unit
+val ppenv : Environ.env -> unit
+val ppenvwithcst : Environ.env -> unit
+
+val pptac : Tacexpr.glob_tactic_expr -> unit
+
+val ppobj : Libobject.obj -> unit
+
+(* Some super raw printers *)
+val cast_kind_display : Constr.cast_kind -> string
+val constr_display : Constr.constr -> unit
+val print_pure_constr : Constr.types -> unit
+
+val pploc : Loc.t -> unit
+
+val pp_argument_type : Genarg.argument_type -> unit
+val pp_generic_argument : 'a Genarg.generic_argument -> unit
+
+val prgenarginfo : Geninterp.Val.t -> Pp.t
+val ppgenarginfo : Geninterp.Val.t -> unit
+
+val ppgenargargt : ('a, 'b, 'c) Genarg.ArgT.tag -> unit
+
+val ppist : Geninterp.interp_sign -> unit
diff --git a/dev/vm_printers.ml b/dev/vm_printers.ml
index 8e43bf6ed..f819d2e6a 100644
--- a/dev/vm_printers.ml
+++ b/dev/vm_printers.ml
@@ -3,7 +3,7 @@ open Term
open Names
open Cbytecodes
open Cemitcodes
-open Vm
+open Vmvalues
let ppripos (ri,pos) =
(match ri with
diff --git a/doc/refman/AsyncProofs.tex b/doc/refman/AsyncProofs.tex
index 30039d489..8f9d876cb 100644
--- a/doc/refman/AsyncProofs.tex
+++ b/doc/refman/AsyncProofs.tex
@@ -1,4 +1,4 @@
-\achapter{Asynchronous and Parallel Proof Processing}
+\achapter{Asynchronous and Parallel Proof Processing\label{Asyncprocessing}}
%HEVEA\cutname{async-proofs.html}
\aauthor{Enrico Tassi}
diff --git a/doc/refman/RefMan-ide.tex b/doc/refman/RefMan-ide.tex
index 436099e74..2d9853430 100644
--- a/doc/refman/RefMan-ide.tex
+++ b/doc/refman/RefMan-ide.tex
@@ -44,9 +44,10 @@ bottom is the status bar.
In the script window, you may open arbitrarily many buffers to
edit. The \emph{File} menu allows you to open files or create some,
save them, print or export them into various formats. Among all these
-buffers, there is always one which is the current \emph{running
- buffer}, whose name is displayed on a green background, which is the
-one where Coq commands are currently executed.
+buffers, there is always one which is the current
+\emph{running buffer}, whose name is displayed on a background in the
+\emph{processed} color (green by default), which is the one where Coq commands
+are currently executed.
Buffers may be edited as in any text editor, and classical basic
editing commands (Copy/Paste, \ldots) are available in the \emph{Edit}
@@ -58,12 +59,13 @@ menu.
\section{Interactive navigation into \Coq{} scripts}
The running buffer is the one where navigation takes place. The
-toolbar proposes five basic commands for this. The first one,
+toolbar offers five basic navigation commands. The first one,
represented by a down arrow icon, is for going forward executing one
command. If that command is successful, the part of the script that
-has been executed is displayed on a green background. If that command
-fails, the error message is displayed in the message window, and the
-location of the error is emphasized by a red underline.
+has been executed is displayed on a background with the
+processed color. If that command fails, the error message is
+displayed in the message window, and the location of the error is
+emphasized by an underline in the error foreground color (red by default).
On Figure~\ref{fig:coqide}, the running buffer is \verb|Fermat.v|, all
commands until the \verb|Theorem| have been already executed, and the
@@ -71,23 +73,41 @@ user tried to go forward executing \verb|Induction n|. That command
failed because no such tactic exist (tactics are now in
lowercase\ldots), and the wrong word is underlined.
-Notice that the green part of the running buffer is not editable. If
+Notice that the processed part of the running buffer is not editable. If
you ever want to modify something you have to go backward using the up
arrow tool, or even better, put the cursor where you want to go back
and use the \textsf{goto} button. Unlike with \verb|coqtop|, you
should never use \verb|Undo| to go backward.
-Two additional tool buttons exist, one to go directly to the end and
-one to go back to the beginning. If you try to go to the end, or in
-general to run several commands using the \textsf{goto} button, the
- execution will stop whenever an error is found.
+There are two additional buttons for navigation within the running buffer.
+The ``down'' button with a line goes directly to the end; the ``up'' button
+with a line goes back to the beginning. The handling of errors when using the
+go-to-the-end button depends on whether \Coq{} is running in asynchronous mode or not
+(see Chapter~\ref{Asyncprocessing}). If it is not running in that mode, execution stops
+as soon as an error is found. Otherwise, execution continues, and the
+error is marked with an underline in the error foreground color, with a background in
+the error background color (pink by default). The same characterization of
+error-handling applies when running several commands using the \textsf{goto} button.
If you ever try to execute a command which happens to run during a
long time, and would like to abort it before its
termination, you may use the interrupt button (the white cross on a red circle).
-Finally, notice that these navigation buttons are also available in
-the menu, where their keyboard shortcuts are given.
+There are other buttons on the \CoqIDE{} toolbar: a button to save the running
+buffer; a button to close the current buffer (an ``X''); buttons to switch among
+buffers (left and right arrows); an ``information'' button; and a ``gears'' button.
+
+The ``information'' button is described in Section~\ref{sec:trytactics}.
+
+The ``gears'' button submits proof terms to the \Coq{} kernel for type-checking.
+When \Coq{} uses asynchronous processing (see Chapter~\ref{Asyncprocessing}), proofs may
+have been completed without kernel-checking of generated proof terms. The presence of
+unchecked proof terms is indicated by \texttt{Qed} statements
+that have a subdued \emph{being-processed} color (light blue by default),
+rather than the processed color, though their preceding proofs have the processed color.
+
+Notice that for all these buttons, except for the ``gears'' button, their operations
+are also available in the menu, where their keyboard shortcuts are given.
\section[Try tactics automatically]{Try tactics automatically\label{sec:trytactics}}
@@ -96,8 +116,8 @@ trying to solve the current goal using simple tactics. If such a
tactic succeeds in solving the goal, then its text is automatically
inserted into the script. There is finally a combination of these
tactics, called the \emph{proof wizard} which will try each of them in
-turn. This wizard is also available as a tool button (the light
-bulb). The set of tactics tried by the wizard is customizable in
+turn. This wizard is also available as a tool button (the ``information''
+button). The set of tactics tried by the wizard is customizable in
the preferences.
These tactics are general ones, in particular they do not refer to
@@ -132,7 +152,7 @@ arguments.
\begin{figure}[t]
\begin{center}
-%HEVEA\imgsrc[alt="coqide query window"]{coqide-queries.png}
+%HEVEA\imgsrc[alt="coqide query"]{coqide-queries.png}
%BEGIN LATEX
\ifpdf % si on est en pdflatex
\includegraphics[width=1.0\textwidth]{coqide-queries.png}
@@ -141,27 +161,21 @@ arguments.
\fi
%END LATEX
\end{center}
-\caption{\CoqIDE{}: the query window}
-\label{fig:querywindow}
+\caption{\CoqIDE{}: a Print query on a selected phrase}
+\label{fig:queryselected}
\end{figure}
-
-We call \emph{query} any vernacular command that do not change the
-current state, such as \verb|Check|, \verb|Search|, etc. Those
-commands are of course useless during compilation of a file, hence
-should not be included in scripts. To run such commands without
-writing them in the script, \CoqIDE{} offers another input window
-called the \emph{query window}. This window can be displayed on
-demand, either by using the \texttt{Window} menu, or directly using
-shortcuts given in the \texttt{Queries} menu. Indeed, with \CoqIDE{}
-the simplest way to perform a \texttt{Search} on some identifier
-is to select it using the mouse, and pressing \verb|F2|. This will
-both make appear the query window and run the \texttt{Search} in
-it, displaying the result. Shortcuts \verb|F3| and \verb|F4| are for
-\verb|Check| and \verb|Print| respectively.
-Figure~\ref{fig:querywindow} displays the query window after selection
-of the word ``mult'' in the script windows, and pressing \verb|F4| to
-print its definition.
+We call \emph{query} any vernacular command that does not change the
+current state, such as \verb|Check|, \verb|Search|, etc.
+To run such commands interactively, without writing them in scripts,
+\CoqIDE{} offers a \emph{query pane}.
+The query pane can be displayed on demand by using the \texttt{View} menu,
+or using the shortcut \verb|F1|. Queries can also be performed by
+selecting a particular phrase, then choosing an item from the
+\texttt{Queries} menu. The response then appears in the message window.
+Figure~\ref{fig:queryselected} shows the result after selecting
+of the phrase \verb|Nat.mul| in the script window, and choosing \verb|Print|
+from the \texttt{Queries} menu.
\section{Compilation}
diff --git a/doc/refman/RefMan-ltac.tex b/doc/refman/RefMan-ltac.tex
index ef0f4af8f..c4c0435c5 100644
--- a/doc/refman/RefMan-ltac.tex
+++ b/doc/refman/RefMan-ltac.tex
@@ -1426,6 +1426,16 @@ You can also pass the {\tt -profile-ltac} command line option to {\tt coqc}, whi
Note that the profiler currently does not handle backtracking into multi-success tactics, and issues a warning to this effect in many cases when such backtracking occurs.
+\subsection[Run-time optimization tactic]{Run-time optimization tactic\label{tactic-optimizeheap}}.
+
+The following tactic behaves like {\tt idtac}, and running it compacts the heap in the
+OCaml run-time system. It is analogous to the Vernacular command {\tt Optimize Heap} (see~\ref{vernac-optimizeheap}).
+
+\tacindex{optimize\_heap}
+\begin{quote}
+{\tt optimize\_heap}.
+\end{quote}
+
\endinput
\subsection{Permutation on closed lists}
diff --git a/doc/refman/RefMan-oth.tex b/doc/refman/RefMan-oth.tex
index 3ebeba178..1cd23c929 100644
--- a/doc/refman/RefMan-oth.tex
+++ b/doc/refman/RefMan-oth.tex
@@ -912,6 +912,15 @@ This command turns off the use of a default timeout.
This command displays whether some default timeout has be set or not.
+\subsection[\tt Fail \textrm{\textsl{command-or-tactic}}.]{\tt Fail \textrm{\textsl{command-or-tactic}}.\comindex{Fail}\label{Fail}}
+
+For debugging {\Coq} scripts, sometimes it is desirable to know
+whether a command or a tactic fails. If the given command or tactic
+fails, the {\tt Fail} statement succeeds, without changing the proof
+state, and in interactive mode, {\Coq} prints a message confirming the failure.
+If the command or tactic succeeds, the statement is an error, and
+{\Coq} prints a message indicating that the failure did not occur.
+
\section{Controlling display}
\subsection[\tt Set Silent.]{\tt Set Silent.\optindex{Silent}
diff --git a/doc/refman/RefMan-pre.tex b/doc/refman/RefMan-pre.tex
index 991c9745e..05775bfbe 100644
--- a/doc/refman/RefMan-pre.tex
+++ b/doc/refman/RefMan-pre.tex
@@ -499,7 +499,7 @@ Claude Marché coordinated the edition of the Reference Manual for
Pierre Letouzey and Jacek Chrz\k{a}szcz respectively maintained the
extraction tool and module system of {\Coq}.
-Jean-Christophe Filliâtre, Pierre Letouzey, Hugo Herbelin ando
+Jean-Christophe Filliâtre, Pierre Letouzey, Hugo Herbelin and other
contributors from Sophia-Antipolis and Nijmegen participated to the
extension of the library.
@@ -659,7 +659,7 @@ Matthieu Sozeau extended the \textsc{Russell} language, ending in an
convenient way to write programs of given specifications, Pierre
Corbineau extended the Mathematical Proof Language and the
automatization tools that accompany it, Pierre Letouzey supervised and
-extended various parts the standard library, Stéphane Glondu
+extended various parts of the standard library, Stéphane Glondu
contributed a few tactics and improvements, Jean-Marc Notin provided
help in debugging, general maintenance and {\tt coqdoc} support,
Vincent Siles contributed extensions of the {\tt Scheme} command and
@@ -680,7 +680,7 @@ Nicolas Tabareau made the adaptation of the interface of the old
the interaction between Coq and its external interfaces. With Samuel
Mimram, he also helped making Coq compatible with recent software
tools. Russell O'Connor, Cezary Kaliscyk, Milad Niqui contributed to
-improved the libraries of integers, rational, and real numbers. We
+improve the libraries of integers, rational, and real numbers. We
also thank many users and partners for suggestions and feedback, in
particular Pierre Castéran and Arthur Charguéraud, the INRIA Marelle
team, Georges Gonthier and the INRIA-Microsoft Mathematical Components team,
@@ -714,7 +714,7 @@ implementation of $\mathbb{N}$, $\mathbb{Z}$ or
$\mathbb{Z}/n\mathbb{Z}$.
The main other evolutions of the library are due to Hugo Herbelin who
-made a revision of the sorting library (includingh a certified
+made a revision of the sorting library (including a certified
merge-sort) and to Guillaume Melquiond who slightly revised and
cleaned up the library of reals.
@@ -723,7 +723,7 @@ some efficiency issues and a more flexible construction of module
types, Élie Soubiran brought a new model of name equivalence, the
$\Delta$-equivalence, which respects as much as possible the names
given by the users. He also designed with Pierre Letouzey a new
-convenient operator \verb!<+! for nesting functor application, what
+convenient operator \verb!<+! for nesting functor application, that
provides a light notation for inheriting the properties of cascading
modules.
diff --git a/doc/refman/RefMan-pro.tex b/doc/refman/RefMan-pro.tex
index 1d3311edc..6b24fdde7 100644
--- a/doc/refman/RefMan-pro.tex
+++ b/doc/refman/RefMan-pro.tex
@@ -320,10 +320,19 @@ Note that when a focused goal is proved a message is displayed
together with a suggestion about the right bullet or {\tt \}} to
unfocus it or focus the next one.
+\begin{Variants}
+
+\item {\tt {\num}: \{}\\
+This focuses on the $\num^{th}$ subgoal to prove.
+
+\end{Variants}
+
\begin{ErrMsgs}
\item \errindex{This proof is focused, but cannot be unfocused
this way} You are trying to use {\tt \}} but the current subproof
has not been fully solved.
+\item \errindex{No such goal}
+\item \errindex{Brackets only support the single numbered goal selector}
\item see also error message about bullets below.
\end{ErrMsgs}
@@ -555,12 +564,12 @@ used to force Coq to optimize some of its internal data structures.
This command forces Coq to shrink the data structure used to represent
the ongoing proof.
-\subsection[\tt Optimize Heap.]{\tt Optimize Heap.}
+\subsection[\tt Optimize Heap.]{\tt Optimize Heap.\label{vernac-optimizeheap}}
This command forces the OCaml runtime to perform a heap compaction.
-This is in general an expensive operation. See:
- \url{http://caml.inria.fr/pub/docs/manual-ocaml/libref/Gc.html#VALcompact}
-
+This is in general an expensive operation. See: \\
+\ \url{http://caml.inria.fr/pub/docs/manual-ocaml/libref/Gc.html#VALcompact} \\
+There is also an analogous tactic {\tt optimize\_heap} (see~\ref{tactic-optimizeheap}).
%%% Local Variables:
%%% mode: latex
diff --git a/doc/refman/Universes.tex b/doc/refman/Universes.tex
index a1a6a4391..6c84a1818 100644
--- a/doc/refman/Universes.tex
+++ b/doc/refman/Universes.tex
@@ -68,6 +68,13 @@ is only valid as long as \texttt{Top.4} is strictly smaller than
monomorphic (not universe polymorphic), so the two universes
(in this case \texttt{Top.3} and \texttt{Top.4}) are actually global levels.
+When printing \texttt{pidentity}, we can see the universes it binds in
+the annotation \texttt{@\{Top.2\}}. Additionally, when \texttt{Set
+ Printing Universes} is on we print the ``universe context'' of
+\texttt{pidentity} consisting of the bound universes and the
+constraints they must verify (for \texttt{pidentity} there are no
+constraints).
+
Inductive types can also be declared universes polymorphic on universes
appearing in their parameters or fields. A typical example is given by
monoids:
@@ -138,7 +145,7 @@ producing global universe constraints, one can use the
\optindex{Polymorphic Inductive Cumulativity}
Polymorphic inductive types, coinductive types, variants and records can be
-declared cumulative using the \texttt{Cumulative}. Alternatively,
+declared cumulative using the \texttt{Cumulative} prefix. Alternatively,
there is an option \texttt{Set Polymorphic Inductive Cumulativity} which when set,
makes all subsequent \emph{polymorphic} inductive definitions cumulative. When set,
inductive types and the like can be enforced to be
@@ -151,15 +158,22 @@ Polymorphic Cumulative Inductive list {A : Type} :=
\begin{coq_example}
Print list.
\end{coq_example}
-When printing \texttt{list}, the part of the output of the form
-\texttt{$\mathtt{\sim}$@\{i\} <= $\mathtt{\sim}$@\{j\} iff }
-indicates the universe constraints in order to have the subtyping
-$\WTEGLECONV{\mathtt{list@\{i\}} A}{\mathtt{list@\{j\}} B}$
-(for fully applied instances of \texttt{list}) whenever $\WTEGCONV{A}{B}$.
-In the case of \texttt{list} there is no constraint!
-This also means that any two instances of \texttt{list} are convertible:
-$\WTEGCONV{\mathtt{list@\{i\}} A}{\mathtt{list@\{j\}} B}$ whenever $\WTEGCONV{A}{B}$ and
-furthermore their corresponding (when fully applied to convertible arguments) constructors.
+When printing \texttt{list}, the universe context indicates the
+subtyping constraints by prefixing the level names with symbols.
+
+Because inductive subtypings are only produced by comparing inductives
+to themselves with universes changed, they amount to variance
+information: each universe is either invariant, covariant or
+irrelevant (there are no contravariant subtypings in Coq),
+respectively represented by the symbols \texttt{=}, \texttt{+} and
+\texttt{*}.
+
+Here we see that \texttt{list} binds an irrelevant universe, so any
+two instances of \texttt{list} are convertible:
+$\WTEGCONV{\mathtt{list@\{i\}} A}{\mathtt{list@\{j\}} B}$ whenever
+$\WTEGCONV{A}{B}$ and furthermore their corresponding (when fully
+applied to convertible arguments) constructors.
+
See Chapter~\ref{Cic} for more details on convertibility and subtyping.
The following is an example of a record with non-trivial subtyping relation:
\begin{coq_example*}
@@ -168,8 +182,9 @@ Polymorphic Cumulative Record packType := {pk : Type}.
\begin{coq_example}
Print packType.
\end{coq_example}
-Notice that as expected, \texttt{packType@\{i\}} and \texttt{packType@\{j\}} are
-convertible if and only if \texttt{i $=$ j}.
+\texttt{packType} binds a covariant universe, i.e.
+$\WTEGCONV{\mathtt{packType@\{i\}}}{\mathtt{packType@\{j\}}}$ whenever
+\texttt{i $\leq$ j}.
Cumulative inductive types, coninductive types, variants and records
only make sense when they are universe polymorphic. Therefore, an
diff --git a/doc/refman/coqide-queries.png b/doc/refman/coqide-queries.png
index dea5626f8..7a46ac4e6 100644
--- a/doc/refman/coqide-queries.png
+++ b/doc/refman/coqide-queries.png
Binary files differ
diff --git a/doc/refman/coqide.png b/doc/refman/coqide.png
index a6a0f5850..e300401c9 100644
--- a/doc/refman/coqide.png
+++ b/doc/refman/coqide.png
Binary files differ
diff --git a/engine/eConstr.ml b/engine/eConstr.ml
index a65b3941e..9ac16b5b4 100644
--- a/engine/eConstr.ml
+++ b/engine/eConstr.ml
@@ -695,6 +695,10 @@ let cast_rel_context :
type a b. (a,b) eq -> (a, a) Rel.pt -> (b, b) Rel.pt =
fun Refl x -> x
+let cast_rec_decl :
+ type a b. (a,b) eq -> (a, a) Constr.prec_declaration -> (b, b) Constr.prec_declaration =
+ fun Refl x -> x
+
let cast_named_decl :
type a b. (a,b) eq -> (a, a) Named.Declaration.pt -> (b, b) Named.Declaration.pt =
fun Refl x -> x
@@ -817,6 +821,7 @@ let it_mkLambda_or_LetIn t ctx = List.fold_left (fun c d -> mkLambda_or_LetIn d
let push_rel d e = push_rel (cast_rel_decl unsafe_eq d) e
let push_rel_context d e = push_rel_context (cast_rel_context unsafe_eq d) e
+let push_rec_types d e = push_rec_types (cast_rec_decl unsafe_eq d) e
let push_named d e = push_named (cast_named_decl unsafe_eq d) e
let push_named_context d e = push_named_context (cast_named_context unsafe_eq d) e
let push_named_context_val d e = push_named_context_val (cast_named_decl unsafe_eq d) e
diff --git a/engine/eConstr.mli b/engine/eConstr.mli
index 30de748a1..6fa338c73 100644
--- a/engine/eConstr.mli
+++ b/engine/eConstr.mli
@@ -251,6 +251,7 @@ end
val push_rel : rel_declaration -> env -> env
val push_rel_context : rel_context -> env -> env
+val push_rec_types : (t, t) Constr.prec_declaration -> env -> env
val push_named : named_declaration -> env -> env
val push_named_context : named_context -> env -> env
diff --git a/engine/evarutil.ml b/engine/evarutil.ml
index 374fdce72..f82ffccdc 100644
--- a/engine/evarutil.ml
+++ b/engine/evarutil.ml
@@ -257,22 +257,6 @@ let make_pure_subst evi args =
* we have the property that u and phi(t) are convertible in env.
*)
-let csubst_subst (k, s) c =
- (** Safe because this is a substitution *)
- let c = EConstr.Unsafe.to_constr c in
- let rec subst n c = match Constr.kind c with
- | Rel m ->
- if m <= n then c
- else if m - n <= k then EConstr.Unsafe.to_constr (Int.Map.find (k - m + n) s)
- else mkRel (m - k)
- | _ -> Constr.map_with_binders succ subst n c
- in
- let c = if k = 0 then c else subst 0 c in
- EConstr.of_constr c
-
-let subst2 subst vsubst c =
- csubst_subst subst (EConstr.Vars.replace_vars vsubst c)
-
let next_ident_away id avoid =
let avoid id = Id.Set.mem id avoid in
next_ident_away_from id avoid
@@ -282,19 +266,79 @@ let next_name_away na avoid =
let id = match na with Name id -> id | Anonymous -> default_non_dependent_ident in
next_ident_away_from id avoid
-type csubst = int * EConstr.t Int.Map.t
+type subst_val =
+| SRel of int
+| SVar of Id.t
+
+type csubst = {
+ csubst_len : int;
+ (** Cardinal of [csubst_rel] *)
+ csubst_var : Constr.t Id.Map.t;
+ (** A mapping of variables to variables. We use the more general
+ [Constr.t] to share allocations, but all values are of shape [Var _]. *)
+ csubst_rel : Constr.t Int.Map.t;
+ (** A contiguous mapping of integers to variables. Same remark for values. *)
+ csubst_rev : subst_val Id.Map.t;
+ (** Reverse mapping of the substitution *)
+}
+(** This type represent a name substitution for the named and De Bruijn parts of
+ a environment. For efficiency we also store the reverse substitution.
+ Invariant: all identifiers in the codomain of [csubst_var] and [csubst_rel]
+ must be pairwise distinct. *)
+
+let empty_csubst = {
+ csubst_len = 0;
+ csubst_rel = Int.Map.empty;
+ csubst_var = Id.Map.empty;
+ csubst_rev = Id.Map.empty;
+}
-let empty_csubst = (0, Int.Map.empty)
+let csubst_subst { csubst_len = k; csubst_var = v; csubst_rel = s } c =
+ (** Safe because this is a substitution *)
+ let c = EConstr.Unsafe.to_constr c in
+ let rec subst n c = match Constr.kind c with
+ | Rel m ->
+ if m <= n then c
+ else if m - n <= k then Int.Map.find (k - m + n) s
+ else mkRel (m - k)
+ | Var id ->
+ begin try Id.Map.find id v with Not_found -> c end
+ | _ -> Constr.map_with_binders succ subst n c
+ in
+ let c = if k = 0 && Id.Map.is_empty v then c else subst 0 c in
+ EConstr.of_constr c
type ext_named_context =
- csubst * (Id.t * EConstr.constr) list *
- Id.Set.t * EConstr.named_context
-
-let push_var id (n, s) =
- let s = Int.Map.add n (EConstr.mkVar id) s in
- (succ n, s)
-
-let push_rel_decl_to_named_context sigma decl (subst, vsubst, avoid, nc) =
+ csubst * Id.Set.t * EConstr.named_context
+
+let push_var id { csubst_len = n; csubst_var = v; csubst_rel = s; csubst_rev = r } =
+ let s = Int.Map.add n (Constr.mkVar id) s in
+ let r = Id.Map.add id (SRel n) r in
+ { csubst_len = succ n; csubst_var = v; csubst_rel = s; csubst_rev = r }
+
+(** Post-compose the substitution with the generator [src ↦ tgt] *)
+let update_var src tgt subst =
+ let cur =
+ try Some (Id.Map.find src subst.csubst_rev)
+ with Not_found -> None
+ in
+ match cur with
+ | None ->
+ (** Missing keys stand for identity substitution [src ↦ src] *)
+ let csubst_var = Id.Map.add src (Constr.mkVar tgt) subst.csubst_var in
+ let csubst_rev = Id.Map.add tgt (SVar src) subst.csubst_rev in
+ { subst with csubst_var; csubst_rev }
+ | Some bnd ->
+ let csubst_rev = Id.Map.add tgt bnd (Id.Map.remove src subst.csubst_rev) in
+ match bnd with
+ | SRel m ->
+ let csubst_rel = Int.Map.add m (Constr.mkVar tgt) subst.csubst_rel in
+ { subst with csubst_rel; csubst_rev }
+ | SVar id ->
+ let csubst_var = Id.Map.add id (Constr.mkVar tgt) subst.csubst_var in
+ { subst with csubst_var; csubst_rev }
+
+let push_rel_decl_to_named_context sigma decl (subst, avoid, nc) =
let open EConstr in
let open Vars in
let map_decl f d =
@@ -330,18 +374,17 @@ let push_rel_decl_to_named_context sigma decl (subst, vsubst, avoid, nc) =
binding named [id], we will keep [id0] (the name given
by the user) and rename [id0] into [id] in the named
context. Unless [id] is a section variable. *)
- let subst = (fst subst, Int.Map.map (replace_vars [id0,mkVar id]) (snd subst)) in
- let vsubst = (id0,mkVar id)::vsubst in
- let d = decl |> NamedDecl.of_rel_decl (fun _ -> id0) |> map_decl (subst2 subst vsubst) in
+ let subst = update_var id0 id subst in
+ let d = decl |> NamedDecl.of_rel_decl (fun _ -> id0) |> map_decl (csubst_subst subst) in
let nc = List.map (replace_var_named_declaration id0 id) nc in
- (push_var id0 subst, vsubst, Id.Set.add id avoid, d :: nc)
+ (push_var id0 subst, Id.Set.add id avoid, d :: nc)
| _ ->
(* spiwack: if [id0] is a section variable renaming it is
incorrect. We revert to a less robust behaviour where
the new binder has name [id]. Which amounts to the same
behaviour than when [id=id0]. *)
- let d = decl |> NamedDecl.of_rel_decl (fun _ -> id) |> map_decl (subst2 subst vsubst) in
- (push_var id subst, vsubst, Id.Set.add id avoid, d :: nc)
+ let d = decl |> NamedDecl.of_rel_decl (fun _ -> id) |> map_decl (csubst_subst subst) in
+ (push_var id subst, Id.Set.add id avoid, d :: nc)
let push_rel_context_to_named_context env sigma typ =
(* compute the instances relative to the named context and rel_context *)
@@ -350,17 +393,17 @@ let push_rel_context_to_named_context env sigma typ =
let ids = List.map get_id (named_context env) in
let inst_vars = List.map mkVar ids in
if List.is_empty (Environ.rel_context env) then
- (named_context_val env, typ, inst_vars, empty_csubst, [])
+ (named_context_val env, typ, inst_vars, empty_csubst)
else
let avoid = List.fold_right Id.Set.add ids Id.Set.empty in
let inst_rels = List.rev (rel_list 0 (nb_rel env)) in
(* move the rel context to a named context and extend the named instance *)
(* with vars of the rel context *)
(* We do keep the instances corresponding to local definition (see above) *)
- let (subst, vsubst, _, env) =
+ let (subst, _, env) =
Context.Rel.fold_outside (fun d acc -> push_rel_decl_to_named_context sigma d acc)
- (rel_context env) ~init:(empty_csubst, [], avoid, named_context env) in
- (val_of_named_context env, subst2 subst vsubst typ, inst_rels@inst_vars, subst, vsubst)
+ (rel_context env) ~init:(empty_csubst, avoid, named_context env) in
+ (val_of_named_context env, csubst_subst subst typ, inst_rels@inst_vars, subst)
(*------------------------------------*
* Entry points to define new evars *
@@ -425,8 +468,8 @@ let new_evar_from_context sign evd ?src ?filter ?candidates ?store ?naming ?prin
(* [new_evar] declares a new existential in an env env with type typ *)
(* Converting the env into the sign of the evar to define *)
let new_evar env evd ?src ?filter ?candidates ?store ?naming ?principal typ =
- let sign,typ',instance,subst,vsubst = push_rel_context_to_named_context env evd typ in
- let map c = subst2 subst vsubst c in
+ let sign,typ',instance,subst = push_rel_context_to_named_context env evd typ in
+ let map c = csubst_subst subst c in
let candidates = Option.map (fun l -> List.map map l) candidates in
let instance =
match filter with
diff --git a/engine/evarutil.mli b/engine/evarutil.mli
index 37f5968ad..923bf49a9 100644
--- a/engine/evarutil.mli
+++ b/engine/evarutil.mli
@@ -222,14 +222,13 @@ val empty_csubst : csubst
val csubst_subst : csubst -> constr -> constr
type ext_named_context =
- csubst * (Id.t * constr) list *
- Id.Set.t * named_context
+ csubst * Id.Set.t * named_context
val push_rel_decl_to_named_context :
evar_map -> rel_declaration -> ext_named_context -> ext_named_context
val push_rel_context_to_named_context : Environ.env -> evar_map -> types ->
- named_context_val * types * constr list * csubst * (Id.t*constr) list
+ named_context_val * types * constr list * csubst
val generalize_evar_over_rels : evar_map -> existential -> types * constr list
diff --git a/engine/evd.ml b/engine/evd.ml
index e33c851f6..0e9472158 100644
--- a/engine/evd.ml
+++ b/engine/evd.ml
@@ -855,7 +855,7 @@ let normalize_universe evd =
let normalize_universe_instance evd l =
let vars = ref (UState.subst evd.universes) in
- let normalize = Univ.level_subst_of (Universes.normalize_univ_variable_opt_subst vars) in
+ let normalize = Universes.level_subst_of (Universes.normalize_univ_variable_opt_subst vars) in
Univ.Instance.subst_fn normalize l
let normalize_sort evars s =
diff --git a/engine/logic_monad.ml b/engine/logic_monad.ml
index 9dc5d473b..3674bb943 100644
--- a/engine/logic_monad.ml
+++ b/engine/logic_monad.ml
@@ -107,7 +107,6 @@ struct
let print_debug s = make (fun _ -> Feedback.msg_info s)
let print_info s = make (fun _ -> Feedback.msg_info s)
let print_warning s = make (fun _ -> Feedback.msg_warning s)
- let print_error s = make (fun _ -> Feedback.msg_error s)
let print_notice s = make (fun _ -> Feedback.msg_notice s)
let run = fun x ->
diff --git a/engine/logic_monad.mli b/engine/logic_monad.mli
index 8c8f9fe93..50b4abd8b 100644
--- a/engine/logic_monad.mli
+++ b/engine/logic_monad.mli
@@ -61,7 +61,6 @@ module NonLogical : sig
val print_warning : Pp.t -> unit t
val print_notice : Pp.t -> unit t
val print_info : Pp.t -> unit t
- val print_error : Pp.t -> unit t
(** [Pervasives.raise]. Except that exceptions are wrapped with
{!Exception}. *)
diff --git a/engine/proofview.ml b/engine/proofview.ml
index 0a6435195..47b9b406d 100644
--- a/engine/proofview.ml
+++ b/engine/proofview.ml
@@ -1086,7 +1086,7 @@ module Goal = struct
end
end
- let enter_one f =
+ let enter_one ?(__LOC__=__LOC__) f =
let open Proof in
Comb.get >>= function
| [goal] -> begin
@@ -1097,7 +1097,8 @@ module Goal = struct
let (e, info) = CErrors.push e in
tclZERO ~info e
end
- | _ -> assert false (* unsatisfied not-exactly-one-goal precondition *)
+ | _ ->
+ CErrors.anomaly Pp.(str __LOC__ ++ str " enter_one")
let goals =
Pv.get >>= fun step ->
diff --git a/engine/proofview.mli b/engine/proofview.mli
index 59728a2fd..b02fde3a8 100644
--- a/engine/proofview.mli
+++ b/engine/proofview.mli
@@ -499,7 +499,7 @@ module Goal : sig
(** Like {!enter}, but assumes exactly one goal under focus, raising *)
(** a fatal error otherwise. *)
- val enter_one : ([ `LZ ] t -> 'a tactic) -> 'a tactic
+ val enter_one : ?__LOC__:string -> ([ `LZ ] t -> 'a tactic) -> 'a tactic
(** Recover the list of current goals under focus, without evar-normalization.
FIXME: encapsulate the level in an existential type. *)
diff --git a/engine/termops.ml b/engine/termops.ml
index a71bdff31..40b3d0d8b 100644
--- a/engine/termops.ml
+++ b/engine/termops.ml
@@ -1463,6 +1463,18 @@ let prod_applist sigma c l =
| _ -> anomaly (Pp.str "Not enough prod's.") in
app [] c l
+let prod_applist_assum sigma n c l =
+ let open EConstr in
+ let rec app n subst c l =
+ if Int.equal n 0 then
+ if l == [] then Vars.substl subst c
+ else anomaly (Pp.str "Not enough arguments.")
+ else match EConstr.kind sigma c, l with
+ | Prod(_,_,c), arg::l -> app (n-1) (arg::subst) c l
+ | LetIn(_,b,_,c), _ -> app (n-1) (Vars.substl subst b::subst) c l
+ | _ -> anomaly (Pp.str "Not enough prod/let's.") in
+ app n [] c l
+
(* Combinators on judgments *)
let on_judgment f j = { uj_val = f j.uj_val; uj_type = f j.uj_type }
diff --git a/engine/termops.mli b/engine/termops.mli
index c1600abe8..a3559a693 100644
--- a/engine/termops.mli
+++ b/engine/termops.mli
@@ -159,8 +159,18 @@ val eta_reduce_head : Evd.evar_map -> constr -> constr
(** Flattens application lists *)
val collapse_appl : Evd.evar_map -> constr -> constr
+(** [prod_applist] [forall (x1:B1;...;xn:Bn), B] [a1...an] @return [B[a1...an]] *)
val prod_applist : Evd.evar_map -> constr -> constr list -> constr
+(** In [prod_applist_assum n c args], [c] is supposed to have the
+ form [∀Γ.c] with [Γ] of length [m] and possibly with let-ins; it
+ returns [c] with the assumptions of [Γ] instantiated by [args] and
+ the local definitions of [Γ] expanded.
+ Note that [n] counts both let-ins and prods, while the length of [args]
+ only counts prods. In other words, varying [n] changes how many
+ trailing let-ins are expanded. *)
+val prod_applist_assum : Evd.evar_map -> int -> constr -> constr list -> constr
+
(** Remove recursively the casts around a term i.e.
[strip_outer_cast (Cast (Cast ... (Cast c, t) ... ))] is [c]. *)
val strip_outer_cast : Evd.evar_map -> constr -> constr
diff --git a/engine/uState.ml b/engine/uState.ml
index 6131f4c03..4b650c9c9 100644
--- a/engine/uState.ml
+++ b/engine/uState.ml
@@ -201,14 +201,18 @@ let process_universe_constraints ctx cstrs =
| None -> user_err Pp.(str "Algebraic universe on the right")
| Some r' ->
if Univ.Level.is_small r' then
- let levels = Univ.Universe.levels l in
- let fold l' local =
- let l = Univ.Universe.make l' in
- if Univ.Level.is_small l' || is_local l' then
- equalize_variables false l l' r r' local
- else raise (Univ.UniverseInconsistency (Univ.Le, l, r, None))
- in
- Univ.LSet.fold fold levels local
+ if not (Univ.Universe.is_levels l)
+ then
+ raise (Univ.UniverseInconsistency (Univ.Le, l, r, None))
+ else
+ let levels = Univ.Universe.levels l in
+ let fold l' local =
+ let l = Univ.Universe.make l' in
+ if Univ.Level.is_small l' || is_local l' then
+ equalize_variables false l l' r r' local
+ else raise (Univ.UniverseInconsistency (Univ.Le, l, r, None))
+ in
+ Univ.LSet.fold fold levels local
else
Univ.enforce_leq l r local
end
@@ -516,7 +520,7 @@ let is_sort_variable uctx s =
| _ -> None
let subst_univs_context_with_def def usubst (ctx, cst) =
- (Univ.LSet.diff ctx def, Univ.subst_univs_constraints usubst cst)
+ (Univ.LSet.diff ctx def, Universes.subst_univs_constraints usubst cst)
let normalize_variables uctx =
let normalized_variables, undef, def, subst =
diff --git a/engine/universes.ml b/engine/universes.ml
index 30490ec56..3a00f0fd1 100644
--- a/engine/universes.ml
+++ b/engine/universes.ml
@@ -181,6 +181,30 @@ let enforce_eq_instances_univs strict x y c =
(fun x y -> Constraints.add (Universe.make x, d, Universe.make y))
ax ay c
+let enforce_univ_constraint (u,d,v) =
+ match d with
+ | Eq -> enforce_eq u v
+ | Le -> enforce_leq u v
+ | Lt -> enforce_leq (super u) v
+
+let subst_univs_level fn l =
+ try Some (fn l)
+ with Not_found -> None
+
+let subst_univs_constraint fn (u,d,v as c) cstrs =
+ let u' = subst_univs_level fn u in
+ let v' = subst_univs_level fn v in
+ match u', v' with
+ | None, None -> Constraint.add c cstrs
+ | Some u, None -> enforce_univ_constraint (u,d,Universe.make v) cstrs
+ | None, Some v -> enforce_univ_constraint (Universe.make u,d,v) cstrs
+ | Some u, Some v -> enforce_univ_constraint (u,d,v) cstrs
+
+let subst_univs_constraints subst csts =
+ Constraint.fold
+ (fun c cstrs -> subst_univs_constraint subst c cstrs)
+ csts Constraint.empty
+
let subst_univs_universe_constraint fn (u,d,v) =
let u' = subst_univs_universe fn u and v' = subst_univs_universe fn v in
if Universe.equal u' v' then None
@@ -519,13 +543,60 @@ let choose_canonical ctx flexible algs s =
let canon = LSet.choose algs in
canon, (global, rigid, LSet.remove canon flexible)
+let level_subst_of f =
+ fun l ->
+ try let u = f l in
+ match Universe.level u with
+ | None -> l
+ | Some l -> l
+ with Not_found -> l
+
+let subst_univs_fn_constr f c =
+ let changed = ref false in
+ let fu = Univ.subst_univs_universe f in
+ let fi = Univ.Instance.subst_fn (level_subst_of f) in
+ let rec aux t =
+ match kind t with
+ | Sort (Sorts.Type u) ->
+ let u' = fu u in
+ if u' == u then t else
+ (changed := true; mkSort (Sorts.sort_of_univ u'))
+ | Const (c, u) ->
+ let u' = fi u in
+ if u' == u then t
+ else (changed := true; mkConstU (c, u'))
+ | Ind (i, u) ->
+ let u' = fi u in
+ if u' == u then t
+ else (changed := true; mkIndU (i, u'))
+ | Construct (c, u) ->
+ let u' = fi u in
+ if u' == u then t
+ else (changed := true; mkConstructU (c, u'))
+ | _ -> map aux t
+ in
+ let c' = aux c in
+ if !changed then c' else c
+
+let subst_univs_constr subst c =
+ if Univ.is_empty_subst subst then c
+ else
+ let f = Univ.make_subst subst in
+ subst_univs_fn_constr f c
+
+let subst_univs_constr =
+ if Flags.profile then
+ let subst_univs_constr_key = CProfile.declare_profile "subst_univs_constr" in
+ CProfile.profile2 subst_univs_constr_key subst_univs_constr
+ else subst_univs_constr
+
let subst_univs_fn_puniverses lsubst (c, u as cu) =
let u' = Instance.subst_fn lsubst u in
if u' == u then cu else (c, u')
let nf_evars_and_universes_opt_subst f subst =
let subst = fun l -> match LMap.find l subst with None -> raise Not_found | Some l' -> l' in
- let lsubst = Univ.level_subst_of subst in
+ let lsubst = level_subst_of subst in
let rec aux c =
match kind c with
| Evar (evk, args) ->
@@ -605,7 +676,7 @@ let normalize_opt_subst ctx =
in !ectx
type universe_opt_subst = Universe.t option universe_map
-
+
let make_opt_subst s =
fun x ->
(match Univ.LMap.find x s with
@@ -614,8 +685,7 @@ let make_opt_subst s =
let subst_opt_univs_constr s =
let f = make_opt_subst s in
- Vars.subst_univs_fn_constr f
-
+ subst_univs_fn_constr f
let normalize_univ_variables ctx =
let ctx = normalize_opt_subst ctx in
@@ -1033,14 +1103,3 @@ let solve_constraints_system levels level_bounds level_min =
done;
done;
v
-
-
-(** Operations for universe_info_ind *)
-
-(** Given a universe context representing constraints of an inductive
- this function produces a UInfoInd.t that with the trivial subtyping relation. *)
-let univ_inf_ind_from_universe_context univcst =
- let freshunivs = Instance.of_array
- (Array.map (fun _ -> new_univ_level ())
- (Instance.to_array (UContext.instance univcst)))
- in CumulativityInfo.from_universe_context univcst freshunivs
diff --git a/engine/universes.mli b/engine/universes.mli
index 1a98d969b..cb6e2ba1b 100644
--- a/engine/universes.mli
+++ b/engine/universes.mli
@@ -154,6 +154,11 @@ val extend_context : 'a in_universe_context_set -> ContextSet.t ->
module UF : Unionfind.PartitionSig with type elt = Level.t
+val level_subst_of : universe_subst_fn -> universe_level_subst_fn
+val subst_univs_constraints : universe_subst_fn -> Constraint.t -> Constraint.t
+
+val subst_univs_constr : universe_subst -> constr -> constr
+
type universe_opt_subst = Universe.t option universe_map
val make_opt_subst : universe_opt_subst -> universe_subst_fn
@@ -216,9 +221,3 @@ val pr_universe_opt_subst : universe_opt_subst -> Pp.t
val solve_constraints_system : Universe.t option array -> Universe.t array -> Universe.t array ->
Universe.t array
-
-(** Operations for universe_info_ind *)
-
-(** Given a universe context representing constraints of an inductive
- this function produces a UInfoInd.t that with the trivial subtyping relation. *)
-val univ_inf_ind_from_universe_context : UContext.t -> CumulativityInfo.t
diff --git a/ide/config_lexer.mli b/ide/config_lexer.mli
new file mode 100644
index 000000000..0c0c5d1e7
--- /dev/null
+++ b/ide/config_lexer.mli
@@ -0,0 +1,10 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+val print_file : string -> string list Util.String.Map.t -> unit
+val load_file : string -> string list Util.String.Map.t
diff --git a/ide/coq_commands.mli b/ide/coq_commands.mli
new file mode 100644
index 000000000..53026be38
--- /dev/null
+++ b/ide/coq_commands.mli
@@ -0,0 +1,11 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+val tactics : string list list
+val commands : string list list
+val state_preserving : string list
diff --git a/ide/coq_lex.mli b/ide/coq_lex.mli
new file mode 100644
index 000000000..417e0a76f
--- /dev/null
+++ b/ide/coq_lex.mli
@@ -0,0 +1,11 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+val delimit_sentences : (int -> GText.tag -> unit) -> string -> unit
+
+exception Unterminated
diff --git a/ide/coq_lex.mll b/ide/coq_lex.mll
index 8bfd937e3..fcc242e07 100644
--- a/ide/coq_lex.mll
+++ b/ide/coq_lex.mll
@@ -17,7 +17,13 @@
let space = [' ' '\n' '\r' '\t' '\012'] (* '\012' is form-feed *)
-let undotted_sep = '{' | '}' | '-'+ | '+'+ | '*'+
+let number = [ '0'-'9' ]+
+
+let string = "\"" _+ "\""
+
+let undotted_sep = (number space* ':' space*)? '{' | '}' | '-'+ | '+'+ | '*'+
+
+let vernac_control = "Fail" | "Time" | "Redirect" space+ string | "Timeout" space+ number
let dot_sep = '.' (space | eof)
@@ -65,7 +71,7 @@ and sentence initial stamp = parse
stamp (utf8_lexeme_start lexbuf) Tags.Script.sentence;
sentence true stamp lexbuf
}
- | undotted_sep {
+ | (vernac_control space+)* undotted_sep {
(* Separators like { or } and bullets * - + are only active
at the start of a sentence *)
if initial then stamp (utf8_lexeme_start lexbuf + String.length (Lexing.lexeme lexbuf) - 1) Tags.Script.sentence;
diff --git a/ide/coqide.ml b/ide/coqide.ml
index 842d06859..3cc46b6aa 100644
--- a/ide/coqide.ml
+++ b/ide/coqide.ml
@@ -1221,9 +1221,14 @@ let build_ui () =
(* Emacs/PG mode *)
NanoPG.init w notebook all_menus;
- (* Reset on tab switch *)
- let _ = notebook#connect#switch_page ~callback:(fun _ ->
- if reset_on_tab_switch#get then Nav.restart ())
+ (* On tab switch, reset, update location *)
+ let _ = notebook#connect#switch_page ~callback:(fun n ->
+ let _ = if reset_on_tab_switch#get then Nav.restart () in
+ try
+ let session = notebook#get_nth_term n in
+ let ins = session.buffer#get_iter_at_mark `INSERT in
+ Ideutils.display_location ins
+ with _ -> ())
in
(* Vertical Separator between Scripts and Goals *)
diff --git a/ide/coqide_main.ml4 b/ide/coqide_main.ml4
index 8d99cc3e6..6e330c62b 100644
--- a/ide/coqide_main.ml4
+++ b/ide/coqide_main.ml4
@@ -55,6 +55,8 @@ let os_specific_init () = ()
(** Win32 *)
+IFDEF WIN32 THEN
+
(* On win32, we add the directory of coqide to the PATH at launch-time
(this used to be done in a .bat script). *)
@@ -86,7 +88,6 @@ let reroute_stdout_stderr () =
(* We also provide specific kill and interrupt functions. *)
-IFDEF WIN32 THEN
external win32_kill : int -> unit = "win32_kill"
external win32_interrupt : int -> unit = "win32_interrupt"
let () =
diff --git a/ide/coqide_main.mli b/ide/coqide_main.mli
new file mode 100644
index 000000000..e1555ba2e
--- /dev/null
+++ b/ide/coqide_main.mli
@@ -0,0 +1,10 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* This empty file avoids a race condition that occurs when compiling a .ml file
+ that does not have a corresponding .mli file *)
diff --git a/ide/coqide_ui.mli b/ide/coqide_ui.mli
new file mode 100644
index 000000000..9f6fa5635
--- /dev/null
+++ b/ide/coqide_ui.mli
@@ -0,0 +1,10 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+val init : unit -> unit
+val ui_m : GAction.ui_manager
diff --git a/ide/gtk_parsing.ml b/ide/gtk_parsing.ml
index f0575e325..7c0a7495a 100644
--- a/ide/gtk_parsing.ml
+++ b/ide/gtk_parsing.ml
@@ -7,11 +7,7 @@
(************************************************************************)
let underscore = Glib.Utf8.to_unichar "_" ~pos:(ref 0)
-let arobase = Glib.Utf8.to_unichar "@" ~pos:(ref 0)
let prime = Glib.Utf8.to_unichar "'" ~pos:(ref 0)
-let bn = Glib.Utf8.to_unichar "\n" ~pos:(ref 0)
-let space = Glib.Utf8.to_unichar " " ~pos:(ref 0)
-let tab = Glib.Utf8.to_unichar "\t" ~pos:(ref 0)
(* TODO: avoid num and prime at the head of a word *)
@@ -30,17 +26,6 @@ let ends_word (it:GText.iter) =
not (is_word_char c)
)
-
-let inside_word (it:GText.iter) =
- let c = it#char in
- not (starts_word it) &&
- not (ends_word it) &&
- is_word_char c
-
-
-let is_on_word_limit (it:GText.iter) = inside_word it || ends_word it
-
-
let find_word_start (it:GText.iter) =
let rec step_to_start it =
Minilib.log "Find word start";
@@ -72,100 +57,6 @@ let get_word_around (it:GText.iter) =
let stop = find_word_end it in
start,stop
-
-let rec complete_backward w (it:GText.iter) =
- Minilib.log "Complete backward...";
- match it#backward_search w with
- | None -> (Minilib.log "backward_search failed";None)
- | Some (start,stop) ->
- Minilib.log ("complete_backward got a match:"^(string_of_int start#offset)^(string_of_int stop#offset));
- if starts_word start then
- let ne = find_word_end stop in
- if ne#compare stop = 0
- then complete_backward w start
- else Some (start,stop,ne)
- else complete_backward w start
-
-
-let rec complete_forward w (it:GText.iter) =
- Minilib.log "Complete forward...";
- match it#forward_search w with
- | None -> None
- | Some (start,stop) ->
- if starts_word start then
- let ne = find_word_end stop in
- if ne#compare stop = 0 then
- complete_forward w stop
- else Some (stop,stop,ne)
- else complete_forward w stop
-
-
-let find_comment_end (start:GText.iter) =
- let rec find_nested_comment (search_start:GText.iter) (search_end:GText.iter) (comment_end:GText.iter) =
- match (search_start#forward_search ~limit:search_end "(*"),(comment_end#forward_search "*)") with
- | None,_ -> comment_end
- | Some _, None -> raise Not_found
- | Some (_,next_search_start),Some (next_search_end,next_comment_end) ->
- find_nested_comment next_search_start next_search_end next_comment_end
- in
- match start#forward_search "*)" with
- | None -> raise Not_found
- | Some (search_end,comment_end) -> find_nested_comment start search_end comment_end
-
-
-let rec find_string_end (start:GText.iter) =
- let dblquote = int_of_char '"' in
- let rec escaped_dblquote c =
- (c#char = dblquote) && not (escaped_dblquote c#backward_char)
- in
- match start#forward_search "\"" with
- | None -> raise Not_found
- | Some (stop,next_start) ->
- if escaped_dblquote stop#backward_char
- then find_string_end next_start
- else next_start
-
-
-let rec find_next_sentence (from:GText.iter) =
- match (from#forward_search ".") with
- | None -> raise Not_found
- | Some (non_vernac_search_end,next_sentence) ->
- match from#forward_search ~limit:non_vernac_search_end "(*",from#forward_search ~limit:non_vernac_search_end "\"" with
- | None,None ->
- if Glib.Unichar.isspace next_sentence#char || next_sentence#compare next_sentence#forward_char == 0
- then next_sentence else find_next_sentence next_sentence
- | None,Some (_,string_search_start) -> find_next_sentence (find_string_end string_search_start)
- | Some (_,comment_search_start),None -> find_next_sentence (find_comment_end comment_search_start)
- | Some (_,comment_search_start),Some (_,string_search_start) ->
- find_next_sentence (
- if comment_search_start#compare string_search_start < 0
- then find_comment_end comment_search_start
- else find_string_end string_search_start)
-
-
-let find_nearest_forward (cursor:GText.iter) targets =
- let fold_targets acc target =
- match cursor#forward_search target,acc with
- | Some (t_start,_),Some nearest when (t_start#compare nearest < 0) -> Some t_start
- | Some (t_start,_),None -> Some t_start
- | _ -> acc
- in
- match List.fold_left fold_targets None targets with
- | None -> raise Not_found
- | Some nearest -> nearest
-
-
-let find_nearest_backward (cursor:GText.iter) targets =
- let fold_targets acc target =
- match cursor#backward_search target,acc with
- | Some (t_start,_),Some nearest when (t_start#compare nearest > 0) -> Some t_start
- | Some (t_start,_),None -> Some t_start
- | _ -> acc
- in
- match List.fold_left fold_targets None targets with
- | None -> raise Not_found
- | Some nearest -> nearest
-
(** On double-click on a view, select the whole word. This is a workaround for
a deficient word handling in TextView. *)
let fix_double_click self =
diff --git a/ide/gtk_parsing.mli b/ide/gtk_parsing.mli
new file mode 100644
index 000000000..b54f731b3
--- /dev/null
+++ b/ide/gtk_parsing.mli
@@ -0,0 +1,26 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+val fix_double_click :
+ < buffer : < get_iter : [> `INSERT ] -> GText.iter;
+ move_mark : [> `INSERT | `SEL_BOUND ] ->
+ where:GText.iter -> unit;
+ .. >;
+ event : < connect :
+ < button_press :
+ callback:([> `TWO_BUTTON_PRESS ] Gdk.event ->
+ bool) ->
+ 'a;
+ .. >;
+ .. >;
+ .. > ->
+ unit
+val starts_word : GText.iter -> bool
+val ends_word : GText.iter -> bool
+val find_word_start : GText.iter -> GText.iter
+val find_word_end : GText.iter -> GText.iter
diff --git a/ide/ide_slave.ml b/ide/ide_slave.ml
index 5f40a2242..6d1064d25 100644
--- a/ide/ide_slave.ml
+++ b/ide/ide_slave.ml
@@ -454,9 +454,11 @@ let slave_feeder fmt xml_oc msg =
let msg_format = ref (fun () ->
let margin = Option.default 72 (Topfmt.get_margin ()) in
Xmlprotocol.Richpp margin
-)
+ )
-let loop doc =
+(* The loop ignores the command line arguments as the current model delegates
+ its handing to the toplevel container. *)
+let loop _args doc =
set_doc doc;
init_signal_handler ();
catch_break := false;
@@ -504,8 +506,8 @@ let rec parse = function
| x :: rest -> x :: parse rest
| [] -> []
-let () = Coqtop.toploop_init := (fun args ->
- let args = parse args in
+let () = Coqtop.toploop_init := (fun coq_args extra_args ->
+ let args = parse extra_args in
Flags.quiet := true;
CoqworkmgrApi.(init High);
args)
diff --git a/ide/ide_slave.mli b/ide/ide_slave.mli
new file mode 100644
index 000000000..e1555ba2e
--- /dev/null
+++ b/ide/ide_slave.mli
@@ -0,0 +1,10 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* This empty file avoids a race condition that occurs when compiling a .ml file
+ that does not have a corresponding .mli file *)
diff --git a/ide/ideutils.ml b/ide/ideutils.ml
index 0977a1890..9c5b06a0d 100644
--- a/ide/ideutils.ml
+++ b/ide/ideutils.ml
@@ -69,6 +69,12 @@ let insert_xml ?(mark = `INSERT) ?(tags = []) (buf : #GText.buffer_skel) msg =
let set_location = ref (function s -> failwith "not ready")
+let display_location ins =
+ let line = ins#line + 1 in
+ let off = ins#line_offset + 1 in
+ let msg = Printf.sprintf "Line: %5d Char: %3d" line off in
+ !set_location msg
+
(** A utf8 char is either a single byte (ascii char, 0xxxxxxx)
or multi-byte (with a leading byte 11xxxxxx and extra bytes 10xxxxxx) *)
@@ -465,4 +471,3 @@ let browse_keyword prerr text =
let u = Lazy.force url_for_keyword text in
browse prerr (doc_url() ^ u)
with Not_found -> prerr ("No documentation found for \""^text^"\".\n")
-
diff --git a/ide/ideutils.mli b/ide/ideutils.mli
index f06a48aeb..99ff763e2 100644
--- a/ide/ideutils.mli
+++ b/ide/ideutils.mli
@@ -56,6 +56,7 @@ val insert_xml : ?mark:GText.mark -> ?tags:GText.tag list ->
#GText.buffer_skel -> Richpp.richpp -> unit
val set_location : (string -> unit) ref
+val display_location : GText.iter -> unit
(* In win32, when a command-line is to be executed via cmd.exe
(i.e. Sys.command, Unix.open_process, ...), it cannot contain several
@@ -95,4 +96,3 @@ val io_read_all : Glib.Io.channel -> string
val run_command :
(string -> unit) -> (Unix.process_status -> unit) -> string -> unit
-
diff --git a/ide/macos_prehook.mli b/ide/macos_prehook.mli
new file mode 100644
index 000000000..e1555ba2e
--- /dev/null
+++ b/ide/macos_prehook.mli
@@ -0,0 +1,10 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* This empty file avoids a race condition that occurs when compiling a .ml file
+ that does not have a corresponding .mli file *)
diff --git a/ide/nanoPG.mli b/ide/nanoPG.mli
new file mode 100644
index 000000000..3ad8435b5
--- /dev/null
+++ b/ide/nanoPG.mli
@@ -0,0 +1,11 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+val get_documentation : unit -> string
+val init : GWindow.window -> Session.session Wg_Notebook.typed_notebook ->
+ GAction.action_group list -> unit
diff --git a/ide/session.ml b/ide/session.ml
index 0a09cc9f5..8dada8ff2 100644
--- a/ide/session.ml
+++ b/ide/session.ml
@@ -209,10 +209,7 @@ let set_buffer_handlers
let mark_set_cb it m =
debug_edit_zone ();
let ins = get_insert () in
- let line = ins#line + 1 in
- let off = ins#line_offset + 1 in
- let msg = Printf.sprintf "Line: %5d Char: %3d" line off in
- let () = !Ideutils.set_location msg in
+ let () = Ideutils.display_location ins in
match GtkText.Mark.get_name m with
| Some "insert" -> ()
| Some s -> Minilib.log (s^" moved")
diff --git a/ide/utf8_convert.mli b/ide/utf8_convert.mli
new file mode 100644
index 000000000..06a131a68
--- /dev/null
+++ b/ide/utf8_convert.mli
@@ -0,0 +1,9 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+val f : string -> string
diff --git a/ide/wg_Find.ml b/ide/wg_Find.ml
index a62ff2de5..cb182465a 100644
--- a/ide/wg_Find.ml
+++ b/ide/wg_Find.ml
@@ -84,8 +84,10 @@ class finder name (view : GText.view) =
method private backward_search starti =
let text = view#buffer#start_iter#get_text ~stop:starti in
let regexp = self#regex in
- try
- let i = Str.search_backward regexp text (String.length text - 1) in
+ let offs = (String.length text - 1) in
+ if offs < 0 then None
+ else try
+ let i = Str.search_backward regexp text offs in
let j = Str.match_end () in
Some(view#buffer#start_iter#forward_chars (b2c text i),
view#buffer#start_iter#forward_chars (b2c text j))
@@ -101,24 +103,33 @@ class finder name (view : GText.view) =
with Not_found -> None
method replace_all () =
- let rec replace_at (iter : GText.iter) =
+ let rec replace_at (iter : GText.iter) ct tot =
let found = self#forward_search iter in
match found with
- | None -> ()
+ | None ->
+ let tot_str = if Int.equal ct tot then "" else " of " ^ string_of_int tot in
+ let occ_str = CString.plural tot "occurrence" in
+ let _ = Ideutils.flash_info ("Replaced " ^ string_of_int ct ^ tot_str ^ " " ^ occ_str) in
+ ()
| Some (start, stop) ->
let text = iter#get_text ~stop:view#buffer#end_iter in
let start_mark = view#buffer#create_mark start in
let stop_mark = view#buffer#create_mark ~left_gravity:false stop in
+ let mod_save = view#buffer#modified in
+ let _ = view#buffer#set_modified false in
let _ = view#buffer#delete_interactive ~start ~stop () in
let iter = view#buffer#get_iter_at_mark (`MARK start_mark) in
- let _ = view#buffer#insert_interactive ~iter (self#replacement text)in
+ let _ = view#buffer#insert_interactive ~iter (self#replacement text) in
+ let edited = view#buffer#modified in
+ let _ = view#buffer#set_modified (edited || mod_save) in
let next = view#buffer#get_iter_at_mark (`MARK stop_mark) in
let () = view#buffer#delete_mark (`MARK start_mark) in
let () = view#buffer#delete_mark (`MARK stop_mark) in
- replace_at next
+ let next_ct = if edited then ct + 1 else ct in
+ replace_at next next_ct (tot + 1)
in
let () = view#buffer#begin_user_action () in
- let () = replace_at view#buffer#start_iter in
+ let () = replace_at view#buffer#start_iter 0 0 in
view#buffer#end_user_action ()
method private set_not_found () =
@@ -130,22 +141,52 @@ class finder name (view : GText.view) =
method private set_normal () =
find_entry#misc#modify_base [`NORMAL, `NAME "white"]
- method private find_from backward (starti : GText.iter) =
+ method private find_from backward ?(wrapped=false) (starti : GText.iter) =
let found =
if backward then self#backward_search starti
else self#forward_search starti in
match found with
| None ->
if not backward && not (starti#equal view#buffer#start_iter) then
- self#find_from backward view#buffer#start_iter
+ self#find_from backward ~wrapped:true view#buffer#start_iter
else if backward && not (starti#equal view#buffer#end_iter) then
- self#find_from backward view#buffer#end_iter
+ self#find_from backward ~wrapped:true view#buffer#end_iter
else
+ let _ = Ideutils.flash_info "String not found" in
self#set_not_found ()
| Some (start, stop) ->
+ let text = view#buffer#start_iter#get_text ~stop:view#buffer#end_iter in
+ let rec find_all offs accum =
+ if offs > String.length text then
+ List.rev accum
+ else try
+ let i = Str.search_forward self#regex text offs in
+ let j = Str.match_end () in
+ find_all (j + 1) (i :: accum)
+ with Not_found -> List.rev accum
+ in
+ let occurs = find_all 0 [] in
+ let num_occurs = List.length occurs in
+ (* assoc table of offset, occurrence index pairs *)
+ let occur_tbl = List.mapi (fun ndx occ -> (occ,ndx+1)) occurs in
let _ = view#buffer#select_range start stop in
let scroll = `MARK (view#buffer#create_mark stop) in
let _ = view#scroll_to_mark ~use_align:false scroll in
+ let _ =
+ try
+ let occ_ndx = List.assoc start#offset occur_tbl in
+ let occ_str = CString.plural num_occurs "occurrence" in
+ let wrap_str = if wrapped then
+ if backward then " (wrapped backwards)"
+ else " (wrapped)"
+ else ""
+ in
+ Ideutils.flash_info
+ (string_of_int occ_ndx ^ " of " ^ string_of_int num_occurs ^
+ " " ^ occ_str ^ wrap_str)
+ with Not_found ->
+ CErrors.anomaly (Pp.str "Occurrence of Find string not in table")
+ in
self#set_found ()
method find_forward () =
diff --git a/install.sh b/install.sh
index f8589a3c7..4f60080a1 100755
--- a/install.sh
+++ b/install.sh
@@ -4,13 +4,13 @@ dest="$1"
shift
for f; do
- bn=`basename $f`
- dn=`dirname $f`
+ bn=$(basename "$f")
+ dn=$(dirname "$f")
install -d "$dest/$dn"
case $bn in
- *.cmxs|*.py) install -m 755 $f "$dest/$dn/$bn"
+ *.cmxs|*.py) install -m 755 "$f" "$dest/$dn/$bn"
;;
- *) install -m 644 $f "$dest/$dn/$bn"
+ *) install -m 644 "$f" "$dest/$dn/$bn"
;;
esac
done
diff --git a/interp/constrexpr_ops.ml b/interp/constrexpr_ops.ml
index 7cc8de85d..da04d8786 100644
--- a/interp/constrexpr_ops.ml
+++ b/interp/constrexpr_ops.ml
@@ -173,10 +173,12 @@ let rec constr_expr_eq e1 e2 =
| CDelimiters(s1,e1), CDelimiters(s2,e2) ->
String.equal s1 s2 &&
constr_expr_eq e1 e2
+ | CProj(p1,c1), CProj(p2,c2) ->
+ eq_reference p1 p2 && constr_expr_eq c1 c2
| (CRef _ | CFix _ | CCoFix _ | CProdN _ | CLambdaN _ | CLetIn _ | CAppExpl _
| CApp _ | CRecord _ | CCases _ | CLetTuple _ | CIf _ | CHole _
| CPatVar _ | CEvar _ | CSort _ | CCast _ | CNotation _ | CPrim _
- | CGeneralization _ | CDelimiters _), _ -> false
+ | CGeneralization _ | CDelimiters _ | CProj _), _ -> false
and args_eq (a1,e1) (a2,e2) =
Option.equal (eq_located explicitation_eq) e1 e2 &&
@@ -365,6 +367,8 @@ let fold_constr_expr_with_binders g f n acc = CAst.with_val (function
(fold_local_binders g f n acc t lb) c lb) l acc
| CCoFix (_,_) ->
Feedback.msg_warning (strbrk "Capture check in multiple binders not done"); acc
+ | CProj (_,c) ->
+ f n acc c
)
let free_vars_of_constr_expr c =
@@ -446,6 +450,8 @@ let map_constr_expr_with_binders g f e = CAst.map (function
let e'' = List.fold_left (fun e ((_,id),_,_,_) -> g id e) e' dl in
let d' = f e'' d in
(id,bl',t',d')) dl)
+ | CProj (p,c) ->
+ CProj (p, f e c)
)
(* Used in constrintern *)
diff --git a/interp/constrexpr_ops.mli b/interp/constrexpr_ops.mli
index 3ecb3d321..6e5c0f851 100644
--- a/interp/constrexpr_ops.mli
+++ b/interp/constrexpr_ops.mli
@@ -84,7 +84,7 @@ val names_of_local_assums : local_binder_expr list -> Name.t located list
(** Same as [names_of_local_binder_exprs], but does not take the [let] bindings into
account. *)
-(** { 6 Folds and maps } *)
+(** {6 Folds and maps} *)
(** Used in typeclasses *)
val fold_constr_expr_with_binders : (Id.t -> 'a -> 'a) ->
diff --git a/interp/constrextern.ml b/interp/constrextern.ml
index 1330b3741..4f7d537d3 100644
--- a/interp/constrextern.ml
+++ b/interp/constrextern.ml
@@ -908,6 +908,9 @@ let rec extern inctx scopes vars r =
| GCast (c, c') ->
CCast (sub_extern true scopes vars c,
Miscops.map_cast_type (extern_typ scopes vars) c')
+ | GProj (p, c) ->
+ let pr = extern_reference ?loc Id.Set.empty (ConstRef (Projection.constant p)) in
+ CProj (pr, sub_extern inctx scopes vars c)
) r'
and extern_typ (_,scopes) =
diff --git a/interp/constrintern.ml b/interp/constrintern.ml
index 61b33aa41..4afe301dd 100644
--- a/interp/constrintern.ml
+++ b/interp/constrintern.ml
@@ -836,6 +836,18 @@ let intern_reference ref =
in
Smartlocate.global_of_extended_global r
+let sort_info_of_level_info (info: Misctypes.level_info) : (Libnames.reference * int) option =
+ match info with
+ | Misctypes.UAnonymous -> None
+ | Misctypes.UUnknown -> None
+ | Misctypes.UNamed id -> Some (id, 0)
+
+let glob_sort_of_level (level: Misctypes.glob_level) : Misctypes.glob_sort =
+ match level with
+ | Misctypes.GProp -> Misctypes.GProp
+ | Misctypes.GSet -> Misctypes.GSet
+ | Misctypes.GType info -> Misctypes.GType [sort_info_of_level_info info]
+
(* Is it a global reference or a syntactic definition? *)
let intern_qualid loc qid intern env lvar us args =
match intern_extended_global_of_qualid (loc,qid) with
@@ -867,6 +879,10 @@ let intern_qualid loc qid intern env lvar us args =
DAst.make ?loc @@ GApp (DAst.make ?loc:loc' @@ GRef (ref, us), arg)
| _ -> err ()
end
+ | Some [s], GSort (Misctypes.GType []) -> DAst.make ?loc @@ GSort (glob_sort_of_level s)
+ | Some [_old_level], GSort _new_sort ->
+ (* TODO: add old_level and new_sort to the error message *)
+ user_err ?loc (str "Cannot change universe level of notation " ++ pr_qualid qid)
| Some _, _ -> err ()
in
c, projapp, args2
@@ -1869,7 +1885,13 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
| CCast (c1, c2) ->
DAst.make ?loc @@
GCast (intern env c1, Miscops.map_cast_type (intern_type env) c2)
- )
+ | CProj (pr, c) ->
+ match intern_reference pr with
+ | ConstRef p ->
+ DAst.make ?loc @@ GProj (Projection.make p false, intern env c)
+ | _ ->
+ raise (InternalizationError (loc,IllegalMetavariable)) (* FIXME *)
+ )
and intern_type env = intern (set_type_scope env)
and intern_local_binder env bind : intern_env * Glob_term.extended_glob_local_binder list =
diff --git a/interp/declare.ml b/interp/declare.ml
index d1b79ffcd..72cdabfd2 100644
--- a/interp/declare.ml
+++ b/interp/declare.ml
@@ -104,7 +104,7 @@ let discharge_constant ((sp, kn), obj) =
let con = Constant.make1 kn in
let from = Global.lookup_constant con in
let modlist = replacement_context () in
- let hyps,subst,uctx = section_segment_of_constant con in
+ let { abstr_ctx = hyps; abstr_subst = subst; abstr_uctx = uctx } = section_segment_of_constant con in
let new_hyps = (discharged_hyps kn hyps) @ obj.cst_hyps in
let abstract = (named_of_variable_context hyps, subst, uctx) in
let new_decl = GlobalRecipe{ from; info = { Opaqueproof.modlist; abstract}} in
@@ -333,7 +333,8 @@ let discharge_inductive ((sp,kn),(dhyps,mie)) =
let mind = Global.mind_of_delta_kn kn in
let mie = Global.lookup_mind mind in
let repl = replacement_context () in
- let sechyps, _, _ as info = section_segment_of_mutual_inductive mind in
+ let info = section_segment_of_mutual_inductive mind in
+ let sechyps = info.Lib.abstr_ctx in
Some (discharged_hyps kn sechyps,
Discharge.process_inductive info repl mie)
@@ -363,13 +364,8 @@ let infer_inductive_subtyping (pth, mind_ent) =
| Cumulative_ind_entry cumi ->
begin
let env = Global.env () in
- let env' =
- Environ.push_context
- (Univ.CumulativityInfo.univ_context cumi) env
- in
(* let (env'', typed_params) = Typeops.infer_local_decls env' (mind_ent.mind_entry_params) in *)
- let evd = Evd.from_env env' in
- (pth, Inductiveops.infer_inductive_subtyping env' evd mind_ent)
+ (pth, InferCumulativity.infer_inductive env mind_ent)
end
type inductive_obj = Dischargedhypsmap.discharged_hyps * mutual_inductive_entry
diff --git a/interp/discharge.ml b/interp/discharge.ml
index 5b4b5f67b..710f88c3f 100644
--- a/interp/discharge.ml
+++ b/interp/discharge.ml
@@ -78,8 +78,8 @@ let refresh_polymorphic_type_of_inductive (_,mip) =
let ctx = List.rev mip.mind_arity_ctxt in
mkArity (List.rev ctx, Type ar.template_level), true
-let process_inductive (section_decls,_,_ as info) modlist mib =
- let section_decls = Lib.named_of_variable_context section_decls in
+let process_inductive info modlist mib =
+ let section_decls = Lib.named_of_variable_context info.Lib.abstr_ctx in
let nparamdecls = Context.Rel.length mib.mind_params_ctxt in
let subst, ind_univs =
match mib.mind_universes with
@@ -92,7 +92,7 @@ let process_inductive (section_decls,_,_ as info) modlist mib =
let auctx = Univ.ACumulativityInfo.univ_context cumi in
let subst, auctx = Lib.discharge_abstract_universe_context info auctx in
let auctx = Univ.AUContext.repr auctx in
- subst, Cumulative_ind_entry (Universes.univ_inf_ind_from_universe_context auctx)
+ subst, Cumulative_ind_entry (Univ.CumulativityInfo.from_universe_context auctx)
in
let discharge c = Vars.subst_univs_level_constr subst (expmod_constr modlist c) in
let inds =
diff --git a/interp/impargs.ml b/interp/impargs.ml
index 3105214d5..ed1cd5276 100644
--- a/interp/impargs.ml
+++ b/interp/impargs.ml
@@ -548,7 +548,7 @@ let discharge_implicits (_,(req,l)) =
| ImplConstant (con,flags) ->
(try
let con' = pop_con con in
- let vars,_,_ = section_segment_of_constant con in
+ let vars = variable_section_segment_of_reference (ConstRef con) in
let extra_impls = impls_of_context vars in
let newimpls = List.map (add_section_impls vars extra_impls) (snd (List.hd l)) in
let l' = [ConstRef con',newimpls] in
diff --git a/interp/notation_ops.ml b/interp/notation_ops.ml
index 20492e38c..326d05cba 100644
--- a/interp/notation_ops.ml
+++ b/interp/notation_ops.ml
@@ -86,9 +86,11 @@ let rec eq_notation_constr (vars1,vars2 as vars) t1 t2 = match t1, t2 with
Miscops.glob_sort_eq s1 s2
| NCast (t1, c1), NCast (t2, c2) ->
(eq_notation_constr vars) t1 t2 && cast_type_eq (eq_notation_constr vars) c1 c2
+| NProj (p1, c1), NProj (p2, c2) ->
+ Projection.equal p1 p2 && eq_notation_constr vars c1 c2
| (NRef _ | NVar _ | NApp _ | NHole _ | NList _ | NLambda _ | NProd _
| NBinderList _ | NLetIn _ | NCases _ | NLetTuple _ | NIf _
- | NRec _ | NSort _ | NCast _), _ -> false
+ | NRec _ | NSort _ | NCast _ | NProj _), _ -> false
(**********************************************************************)
(* Re-interpret a notation as a glob_constr, taking care of binders *)
@@ -189,6 +191,7 @@ let glob_constr_of_notation_constr_with_binders ?loc g f e nc =
| NSort x -> GSort x
| NHole (x, naming, arg) -> GHole (x, naming, arg)
| NRef x -> GRef (x,None)
+ | NProj (p,c) -> GProj (p, f e c)
let glob_constr_of_notation_constr ?loc x =
let rec aux () x =
@@ -383,6 +386,7 @@ let notation_constr_and_vars_of_glob_constr a =
if arg != None then has_ltac := true;
NHole (w, naming, arg)
| GRef (r,_) -> NRef r
+ | GProj (p, c) -> NProj (p, aux c)
| GEvar _ | GPatVar _ ->
user_err Pp.(str "Existential variables not allowed in notations.")
) x
@@ -576,6 +580,14 @@ let rec subst_notation_constr subst bound raw =
let k' = Miscops.smartmap_cast_type (subst_notation_constr subst bound) k in
if r1' == r1 && k' == k then raw else NCast(r1',k')
+ | NProj (p, c) ->
+ let kn = Projection.constant p in
+ let b = Projection.unfolded p in
+ let kn' = subst_constant subst kn in
+ let c' = subst_notation_constr subst bound c in
+ if kn' == kn && c' == c then raw else NProj(Projection.make kn' b, c')
+
+
let subst_interpretation subst (metas,pat) =
let bound = List.fold_left (fun accu (id, _) -> Id.Set.add id accu) Id.Set.empty metas in
(metas,subst_notation_constr subst bound pat)
@@ -1167,9 +1179,12 @@ let rec match_ inner u alp metas sigma a1 a2 =
match_names metas (alp,sigma) (Name id') na in
match_in u alp metas sigma (mkGApp a1 (DAst.make @@ GVar id')) b2
+ | GProj(p1, t1), NProj(p2, t2) when Projection.equal p1 p2 ->
+ match_in u alp metas sigma t1 t2
+
| (GRef _ | GVar _ | GEvar _ | GPatVar _ | GApp _ | GLambda _ | GProd _
| GLetIn _ | GCases _ | GLetTuple _ | GIf _ | GRec _ | GSort _ | GHole _
- | GCast _), _ -> raise No_match
+ | GCast _ | GProj _ ), _ -> raise No_match
and match_in u = match_ true u
diff --git a/intf/constrexpr.ml b/intf/constrexpr.ml
index 8bcdbcc0e..fbf9e248a 100644
--- a/intf/constrexpr.ml
+++ b/intf/constrexpr.ml
@@ -97,6 +97,7 @@ and constr_expr_r =
| CGeneralization of binding_kind * abstraction_kind option * constr_expr
| CPrim of prim_token
| CDelimiters of string * constr_expr
+ | CProj of reference * constr_expr
and constr_expr = constr_expr_r CAst.t
and case_expr = constr_expr (* expression that is being matched *)
diff --git a/intf/glob_term.ml b/intf/glob_term.ml
index f311d33b8..61bbe2c26 100644
--- a/intf/glob_term.ml
+++ b/intf/glob_term.ml
@@ -55,6 +55,7 @@ type 'a glob_constr_r =
| GSort of glob_sort
| GHole of Evar_kinds.t * intro_pattern_naming_expr * Genarg.glob_generic_argument option
| GCast of 'a glob_constr_g * 'a glob_constr_g cast_type
+ | GProj of Projection.t * 'a glob_constr_g
and 'a glob_constr_g = ('a glob_constr_r, 'a) DAst.t
and 'a glob_decl_g = Name.t * binding_kind * 'a glob_constr_g option * 'a glob_constr_g
diff --git a/intf/notation_term.ml b/intf/notation_term.ml
index 7823d3feb..cad6f4b82 100644
--- a/intf/notation_term.ml
+++ b/intf/notation_term.ml
@@ -43,6 +43,7 @@ type notation_constr =
notation_constr array * notation_constr array
| NSort of glob_sort
| NCast of notation_constr * notation_constr cast_type
+ | NProj of Projection.t * notation_constr
(** Note concerning NList: first constr is iterator, second is terminator;
first id is where each argument of the list has to be substituted
diff --git a/intf/pattern.ml b/intf/pattern.ml
index 20636accf..64873a039 100644
--- a/intf/pattern.ml
+++ b/intf/pattern.ml
@@ -26,7 +26,7 @@ type constr_pattern =
| PRel of int
| PApp of constr_pattern * constr_pattern array
| PSoApp of patvar * constr_pattern list
- | PProj of projection * constr_pattern
+ | PProj of Projection.t * constr_pattern
| PLambda of Name.t * constr_pattern * constr_pattern
| PProd of Name.t * constr_pattern * constr_pattern
| PLetIn of Name.t * constr_pattern * constr_pattern option * constr_pattern
diff --git a/intf/vernacexpr.ml b/intf/vernacexpr.ml
index 5106e513b..8e0fe54c5 100644
--- a/intf/vernacexpr.ml
+++ b/intf/vernacexpr.ml
@@ -167,6 +167,7 @@ type option_ref_value =
type universe_decl_expr = (Id.t Loc.located list, glob_constraint list) gen_universe_decl
type ident_decl = lident * universe_decl_expr option
+type name_decl = lname * universe_decl_expr option
type sort_expr = Sorts.family
@@ -204,12 +205,12 @@ type inductive_expr =
type one_inductive_expr =
ident_decl * local_binder_expr list * constr_expr option * constructor_expr list
-type typeclass_constraint = (Name.t Loc.located * universe_decl_expr option) * binding_kind * constr_expr
+type typeclass_constraint = name_decl * binding_kind * constr_expr
and typeclass_context = typeclass_constraint list
type proof_expr =
- ident_decl option * (local_binder_expr list * constr_expr)
+ ident_decl * (local_binder_expr list * constr_expr)
type syntax_modifier =
| SetItemLevel of string list * Extend.production_level
@@ -314,7 +315,16 @@ type cumulative_inductive_parsing_flag =
(** {6 The type of vernacular expressions} *)
-type vernac_expr =
+type vernac_implicit_status = Implicit | MaximallyImplicit | NotImplicit
+
+type vernac_argument_status = {
+ name : Name.t;
+ recarg_like : bool;
+ notation_scope : string Loc.located option;
+ implicit_status : vernac_implicit_status;
+}
+
+type nonrec vernac_expr =
| VernacLoad of verbose_flag * string
(* Syntax *)
@@ -330,7 +340,7 @@ type vernac_expr =
| VernacNotationAddFormat of string * string * string
(* Gallina *)
- | VernacDefinition of (discharge * definition_object_kind) * ident_decl * definition_expr
+ | VernacDefinition of (discharge * definition_object_kind) * name_decl * definition_expr
| VernacStartTheoremProof of theorem_kind * proof_expr list
| VernacEndProof of proof_end
| VernacExactProof of constr_expr
@@ -440,7 +450,6 @@ type vernac_expr =
| VernacComments of comment list
(* Proof management *)
- | VernacGoal of constr_expr
| VernacAbort of lident option
| VernacAbortAll
| VernacRestart
@@ -451,7 +460,7 @@ type vernac_expr =
| VernacUnfocus
| VernacUnfocused
| VernacBullet of bullet
- | VernacSubproof of int option
+ | VernacSubproof of goal_selector option
| VernacEndSubproof
| VernacShow of showable
| VernacCheckGuard
@@ -463,22 +472,13 @@ type vernac_expr =
(* For extension *)
| VernacExtend of extend_name * Genarg.raw_generic_argument list
- (* Flags *)
- | VernacProgram of vernac_expr
- | VernacPolymorphic of bool * vernac_expr
- | VernacLocal of bool * vernac_expr
-
-and vernac_implicit_status = Implicit | MaximallyImplicit | NotImplicit
-
-and vernac_argument_status = {
- name : Name.t;
- recarg_like : bool;
- notation_scope : string Loc.located option;
- implicit_status : vernac_implicit_status;
-}
+type nonrec vernac_flag =
+ | VernacProgram
+ | VernacPolymorphic of bool
+ | VernacLocal of bool
type vernac_control =
- | VernacExpr of vernac_expr
+ | VernacExpr of vernac_flag list * vernac_expr
(* boolean is true when the `-time` batch-mode command line flag was set.
the flag is used to print differently in `-time` vs `Time foo` *)
| VernacTime of bool * vernac_control located
diff --git a/kernel/cClosure.ml b/kernel/cClosure.ml
index 11616da7b..219ea5b24 100644
--- a/kernel/cClosure.ml
+++ b/kernel/cClosure.ml
@@ -91,6 +91,7 @@ module type RedFlagsSig = sig
val red_add : reds -> red_kind -> reds
val red_sub : reds -> red_kind -> reds
val red_add_transparent : reds -> transparent_state -> reds
+ val red_transparent : reds -> transparent_state
val mkflags : red_kind list -> reds
val red_set : reds -> red_kind -> bool
val red_projection : reds -> projection -> bool
@@ -164,6 +165,8 @@ module RedFlags = (struct
let (l1,l2) = red.r_const in
{ red with r_const = Id.Pred.remove id l1, l2 }
+ let red_transparent red = red.r_const
+
let red_add_transparent red tr =
{ red with r_const = tr }
@@ -258,7 +261,7 @@ type 'a infos_cache = {
i_repr : 'a infos -> constr -> 'a;
i_env : env;
i_sigma : existential -> constr option;
- i_rels : constr option array;
+ i_rels : (Context.Rel.Declaration.t * Pre_env.lazy_val) Range.t;
i_tab : 'a KeyTable.t }
and 'a infos = {
@@ -282,13 +285,16 @@ let ref_value_cache ({i_cache = cache} as infos) ref =
let body =
match ref with
| RelKey n ->
- let len = Array.length cache.i_rels in
- let i = n - 1 in
- let () = if i < 0 || len <= i then raise Not_found in
- begin match Array.unsafe_get cache.i_rels i with
- | None -> raise Not_found
- | Some t -> lift n t
- end
+ let open Context.Rel.Declaration in
+ let i = n - 1 in
+ let (d, _) =
+ try Range.get cache.i_rels i
+ with Invalid_argument _ -> raise Not_found
+ in
+ begin match d with
+ | LocalAssum _ -> raise Not_found
+ | LocalDef (_, t, _) -> lift n t
+ end
| VarKey id -> assoc_defined id cache.i_env
| ConstKey cst -> constant_value_in cache.i_env cst
in
@@ -303,26 +309,13 @@ let ref_value_cache ({i_cache = cache} as infos) ref =
let evar_value cache ev =
cache.i_sigma ev
-let defined_rels flags env =
-(* if red_local_const (snd flags) then*)
- let ctx = rel_context env in
- let len = List.length ctx in
- let ans = Array.make len None in
- let open Context.Rel.Declaration in
- let iter i = function
- | LocalAssum _ -> ()
- | LocalDef (_,b,_) -> Array.unsafe_set ans i (Some b)
- in
- let () = List.iteri iter ctx in
- ans
-(* else (0,[])*)
-
let create mk_cl flgs env evars =
+ let open Pre_env in
let cache =
{ i_repr = mk_cl;
i_env = env;
i_sigma = evars;
- i_rels = defined_rels flgs env;
+ i_rels = (Environ.pre_env env).env_rel_context.env_rel_map;
i_tab = KeyTable.create 17 }
in { i_flags = flgs; i_cache = cache }
@@ -857,6 +850,14 @@ let contract_fix_vect fix =
in
(subs_cons(Array.init nfix make_body, env), thisbody)
+let unfold_projection info p =
+ if red_projection info.i_flags p
+ then
+ let open Declarations in
+ let pb = lookup_projection p (info_env info) in
+ Some (Zproj (pb.proj_npars, pb.proj_arg, Projection.constant p))
+ else None
+
(*********************************************************************)
(* A machine that inspects the head of a term until it finds an
atom or a subterm that may produce a redex (abstraction,
@@ -875,15 +876,9 @@ let rec knh info m stk =
| (None, stk') -> (m,stk'))
| FCast(t,_,_) -> knh info t stk
| FProj (p,c) ->
- let unf = Projection.unfolded p in
- if unf || red_set info.i_flags (fCONST (Projection.constant p)) then
- (match try Some (lookup_projection p (info_env info)) with Not_found -> None with
- | None -> (m, stk)
- | Some pb ->
- knh info c (Zproj (pb.Declarations.proj_npars, pb.Declarations.proj_arg,
- Projection.constant p)
- :: zupdate m stk))
- else (m,stk)
+ (match unfold_projection info p with
+ | None -> (m, stk)
+ | Some s -> knh info c (s :: zupdate m stk))
(* cases where knh stops *)
| (FFlex _|FLetIn _|FConstruct _|FEvar _|
diff --git a/kernel/cClosure.mli b/kernel/cClosure.mli
index 119b70e30..c43fc4623 100644
--- a/kernel/cClosure.mli
+++ b/kernel/cClosure.mli
@@ -61,6 +61,9 @@ module type RedFlagsSig = sig
(** Adds a reduction kind to a set *)
val red_add_transparent : reds -> transparent_state -> reds
+ (** Retrieve the transparent state of the reduction flags *)
+ val red_transparent : reds -> transparent_state
+
(** Build a reduction set from scratch = iter [red_add] on [no_red] *)
val mkflags : red_kind list -> reds
@@ -163,6 +166,7 @@ val stack_tail : int -> stack -> stack
val stack_nth : stack -> int -> fconstr
val zip_term : (fconstr -> constr) -> constr -> stack -> constr
val eta_expand_stack : stack -> stack
+val unfold_projection : 'a infos -> Projection.t -> stack_member option
(** To lazy reduce a constr, create a [clos_infos] with
[create_clos_infos], inject the term to reduce with [inject]; then use
diff --git a/kernel/cbytegen.ml b/kernel/cbytegen.ml
index 5dab2932d..4a34dbcff 100644
--- a/kernel/cbytegen.ml
+++ b/kernel/cbytegen.ml
@@ -628,27 +628,17 @@ let rec compile_constr reloc c sz cont =
of the structured constant, while the later (if any) will be applied as
arguments. *)
let open Univ in begin
- let levels = Universe.levels u in
- let global_levels =
- LSet.filter (fun x -> Level.var_index x = None) levels
- in
- let local_levels =
- List.map_filter (fun x -> Level.var_index x)
- (LSet.elements levels)
- in
+ let u,s = Universe.compact u in
(* We assume that [Universe.type0m] is a neutral element for [Universe.sup] *)
- let uglob =
- LSet.fold (fun lvl u -> Universe.sup u (Universe.make lvl)) global_levels Universe.type0m
- in
- if local_levels = [] then
- compile_str_cst reloc (Bstrconst (Const_sorts (Sorts.Type uglob))) sz cont
+ if List.is_empty s then
+ compile_str_cst reloc (Bstrconst (Const_sorts (Sorts.Type u))) sz cont
else
let compile_get_univ reloc idx sz cont =
set_max_stack_size sz;
compile_fv_elem reloc (FVuniv_var idx) sz cont
in
comp_app compile_str_cst compile_get_univ reloc
- (Bstrconst (Const_type u)) (Array.of_list local_levels) sz cont
+ (Bstrconst (Const_type u)) (Array.of_list s) sz cont
end
| LetIn(_,xb,_,body) ->
compile_constr reloc xb sz
diff --git a/kernel/constr.ml b/kernel/constr.ml
index 5930cfadc..1ff1fcc4c 100644
--- a/kernel/constr.ml
+++ b/kernel/constr.ml
@@ -1178,8 +1178,3 @@ let hcons =
Id.hcons)
(* let hcons_types = hcons_constr *)
-
-(*******)
-(* Type of abstract machine values *)
-(** FIXME: nothing to do there *)
-type values
diff --git a/kernel/constr.mli b/kernel/constr.mli
index 98bf71308..19ffa8fe3 100644
--- a/kernel/constr.mli
+++ b/kernel/constr.mli
@@ -459,7 +459,3 @@ val case_info_hash : case_info -> int
(*********************************************************************)
val hcons : constr -> constr
-
-(**************************************)
-
-type values
diff --git a/kernel/cooking.ml b/kernel/cooking.ml
index 7b921d35b..23a578d99 100644
--- a/kernel/cooking.ml
+++ b/kernel/cooking.ml
@@ -168,38 +168,47 @@ let on_body ml hy f = function
{ Opaqueproof.modlist = ml; abstract = hy } o)
let expmod_constr_subst cache modlist subst c =
+ let subst = Univ.make_instance_subst subst in
let c = expmod_constr cache modlist c in
Vars.subst_univs_level_constr subst c
-let cook_constr { Opaqueproof.modlist ; abstract } c =
+let cook_constr { Opaqueproof.modlist ; abstract = (vars, subst, _) } c =
let cache = RefTable.create 13 in
- let expmod = expmod_constr_subst cache modlist (pi2 abstract) in
- let hyps = Context.Named.map expmod (pi1 abstract) in
+ let expmod = expmod_constr_subst cache modlist subst in
+ let hyps = Context.Named.map expmod vars in
abstract_constant_body (expmod c) hyps
-let lift_univs cb subst =
+let lift_univs cb subst auctx0 =
match cb.const_universes with
- | Monomorphic_const ctx -> subst, (Monomorphic_const ctx)
- | Polymorphic_const auctx ->
- if (Univ.LMap.is_empty subst) then
- subst, (Polymorphic_const auctx)
+ | Monomorphic_const ctx ->
+ assert (AUContext.is_empty auctx0);
+ subst, (Monomorphic_const ctx)
+ | Polymorphic_const auctx ->
+ (** Given a named instance [subst := uâ‚€ ... uₙ₋â‚] together with an abstract
+ context [auctx0 := 0 ... n - 1 |= C{0, ..., n - 1}] of the same length,
+ and another abstract context relative to the former context
+ [auctx := 0 ... m - 1 |= C'{uâ‚€, ..., uₙ₋â‚, 0, ..., m - 1}],
+ construct the lifted abstract universe context
+ [0 ... n - 1 n ... n + m - 1 |=
+ C{0, ... n - 1} ∪
+ C'{0, ..., n - 1, n, ..., n + m - 1} ]
+ together with the instance
+ [u₀ ... uₙ₋₠Var(0) ... Var (m - 1)].
+ *)
+ if (Univ.Instance.is_empty subst) then
+ (** Still need to take the union for the constraints between globals *)
+ subst, (Polymorphic_const (AUContext.union auctx0 auctx))
else
- let len = Univ.LMap.cardinal subst in
- let rec gen_subst i acc =
- if i < 0 then acc
- else
- let acc = Univ.LMap.add (Level.var i) (Level.var (i + len)) acc in
- gen_subst (pred i) acc
- in
- let subst = gen_subst (Univ.AUContext.size auctx - 1) subst in
- let auctx' = Univ.subst_univs_level_abstract_universe_context subst auctx in
- subst, (Polymorphic_const auctx')
+ let ainst = Univ.make_abstract_instance auctx in
+ let subst = Instance.append subst ainst in
+ let auctx' = Univ.subst_univs_level_abstract_universe_context (Univ.make_instance_subst subst) auctx in
+ subst, (Polymorphic_const (AUContext.union auctx0 auctx'))
let cook_constant ~hcons env { from = cb; info } =
let { Opaqueproof.modlist; abstract } = info in
let cache = RefTable.create 13 in
let abstract, usubst, abs_ctx = abstract in
- let usubst, univs = lift_univs cb usubst in
+ let usubst, univs = lift_univs cb usubst abs_ctx in
let expmod = expmod_constr_subst cache modlist usubst in
let hyps = Context.Named.map expmod abstract in
let map c =
@@ -234,13 +243,6 @@ let cook_constant ~hcons env { from = cb; info } =
proj_eta = etab, etat;
proj_type = ty'; proj_body = c' }
in
- let univs =
- match univs with
- | Monomorphic_const ctx ->
- assert (AUContext.is_empty abs_ctx); univs
- | Polymorphic_const auctx ->
- Polymorphic_const (AUContext.union abs_ctx auctx)
- in
{
cook_body = body;
cook_type = typ;
diff --git a/kernel/csymtable.ml b/kernel/csymtable.ml
index 2ffe36fcf..bbd284bc1 100644
--- a/kernel/csymtable.ml
+++ b/kernel/csymtable.ml
@@ -15,7 +15,7 @@
open Util
open Names
open Constr
-open Vm
+open Vmvalues
open Cemitcodes
open Cbytecodes
open Declarations
@@ -70,7 +70,7 @@ let rec eq_structured_constant c1 c2 = match c1, c2 with
| Const_bn _, _ -> false
| Const_univ_level l1 , Const_univ_level l2 -> Univ.Level.equal l1 l2
| Const_univ_level _ , _ -> false
-| Const_type u1 , Const_type u2 -> Univ.Universe.equal u1 u2
+| Const_type u1, Const_type u2 -> Univ.Universe.equal u1 u2
| Const_type _ , _ -> false
let rec hash_structured_constant c =
@@ -198,7 +198,7 @@ and slot_for_fv env fv =
let rv = Pre_env.lookup_rel_val i env in
begin match force_lazy_val rv with
| None ->
- env.env_rel_context |> Context.Rel.lookup i |> RelDecl.get_value |> fill_fv_cache rv i val_of_rel env_of_rel
+ env |> Pre_env.lookup_rel i |> RelDecl.get_value |> fill_fv_cache rv i val_of_rel env_of_rel
| Some (v, _) -> v
end
| FVuniv_var idu ->
diff --git a/kernel/csymtable.mli b/kernel/csymtable.mli
index 91bb30e7e..fc935f6ee 100644
--- a/kernel/csymtable.mli
+++ b/kernel/csymtable.mli
@@ -12,7 +12,7 @@ open Names
open Constr
open Pre_env
-val val_of_constr : env -> constr -> values
+val val_of_constr : env -> constr -> Vmvalues.values
val set_opaque_const : Constant.t -> unit
val set_transparent_const : Constant.t -> unit
diff --git a/kernel/declarations.ml b/kernel/declarations.ml
index 7f4b85fd0..5b9e1a141 100644
--- a/kernel/declarations.ml
+++ b/kernel/declarations.ml
@@ -74,6 +74,7 @@ type typing_flags = {
check_guarded : bool; (** If [false] then fixed points and co-fixed
points are assumed to be total. *)
check_universes : bool; (** If [false] universe constraints are not checked *)
+ conv_oracle : Conv_oracle.oracle; (** Unfolding strategies for conversion *)
}
(* some contraints are in constant_constraints, some other may be in
diff --git a/kernel/declareops.ml b/kernel/declareops.ml
index d8768a0fc..9eed9efcb 100644
--- a/kernel/declareops.ml
+++ b/kernel/declareops.ml
@@ -15,9 +15,10 @@ module RelDecl = Context.Rel.Declaration
(** Operations concernings types in [Declarations] :
[constant_body], [mutual_inductive_body], [module_body] ... *)
-let safe_flags = {
+let safe_flags oracle = {
check_guarded = true;
check_universes = true;
+ conv_oracle = oracle;
}
(** {6 Arities } *)
diff --git a/kernel/declareops.mli b/kernel/declareops.mli
index 198831848..0eed11f49 100644
--- a/kernel/declareops.mli
+++ b/kernel/declareops.mli
@@ -67,7 +67,7 @@ val inductive_is_cumulative : mutual_inductive_body -> bool
(** {6 Kernel flags} *)
(** A default, safe set of flags for kernel type-checking *)
-val safe_flags : typing_flags
+val safe_flags : Conv_oracle.oracle -> typing_flags
(** {6 Hash-consing} *)
diff --git a/kernel/environ.ml b/kernel/environ.ml
index 1afab453a..738ecc6e1 100644
--- a/kernel/environ.ml
+++ b/kernel/environ.ml
@@ -37,8 +37,10 @@ type env = Pre_env.env
let pre_env env = env
let env_of_pre_env env = env
-let oracle env = env.env_conv_oracle
-let set_oracle env o = { env with env_conv_oracle = o }
+let oracle env = env.env_typing_flags.conv_oracle
+let set_oracle env o =
+ let env_typing_flags = { env.env_typing_flags with conv_oracle = o } in
+ { env with env_typing_flags }
let empty_named_context_val = empty_named_context_val
@@ -58,18 +60,17 @@ let deactivated_guard env = not (typing_flags env).check_guarded
let universes env = env.env_stratification.env_universes
let named_context env = env.env_named_context.env_named_ctx
let named_context_val env = env.env_named_context
-let rel_context env = env.env_rel_context
+let rel_context env = env.env_rel_context.env_rel_ctx
let opaque_tables env = env.indirect_pterms
let set_opaque_tables env indirect_pterms = { env with indirect_pterms }
let empty_context env =
- match env.env_rel_context, env.env_named_context.env_named_ctx with
+ match env.env_rel_context.env_rel_ctx, env.env_named_context.env_named_ctx with
| [], [] -> true
| _ -> false
(* Rel context *)
-let lookup_rel n env =
- Context.Rel.lookup n env.env_rel_context
+let lookup_rel = lookup_rel
let evaluable_rel n env =
is_local_def (lookup_rel n env)
@@ -86,13 +87,12 @@ let push_rec_types (lna,typarray,_) env =
let fold_rel_context f env ~init =
let rec fold_right env =
- match env.env_rel_context with
- | [] -> init
- | rd::rc ->
+ match match_rel_context_val env.env_rel_context with
+ | None -> init
+ | Some (rd, _, rc) ->
let env =
{ env with
env_rel_context = rc;
- env_rel_val = List.tl env.env_rel_val;
env_nb_rel = env.env_nb_rel - 1 } in
f env rd (fold_right env)
in fold_right env
@@ -142,16 +142,21 @@ let evaluable_named id env =
let reset_with_named_context ctxt env =
{ env with
env_named_context = ctxt;
- env_rel_context = Context.Rel.empty;
- env_rel_val = [];
+ env_rel_context = empty_rel_context_val;
env_nb_rel = 0 }
let reset_context = reset_with_named_context empty_named_context_val
let pop_rel_context n env =
+ let rec skip n ctx =
+ if Int.equal n 0 then ctx
+ else match match_rel_context_val ctx with
+ | None -> invalid_arg "List.skipn"
+ | Some (_, _, ctx) -> skip (pred n) ctx
+ in
let ctxt = env.env_rel_context in
{ env with
- env_rel_context = List.skipn n ctxt;
+ env_rel_context = skip n ctxt;
env_nb_rel = env.env_nb_rel - n }
let fold_named_context f env ~init =
@@ -249,31 +254,10 @@ let constant_context env kn =
| Monomorphic_const _ -> Univ.AUContext.empty
| Polymorphic_const ctx -> ctx
-type const_evaluation_result = NoBody | Opaque | IsProj
+type const_evaluation_result = NoBody | Opaque
exception NotEvaluableConst of const_evaluation_result
-let constant_value env (kn,u) =
- let cb = lookup_constant kn env in
- if cb.const_proj = None then
- match cb.const_body with
- | Def l_body ->
- begin
- match cb.const_universes with
- | Monomorphic_const _ ->
- (Mod_subst.force_constr l_body, Univ.Constraint.empty)
- | Polymorphic_const _ ->
- let csts = constraints_of cb u in
- (subst_instance_constr u (Mod_subst.force_constr l_body), csts)
- end
- | OpaqueDef _ -> raise (NotEvaluableConst Opaque)
- | Undef _ -> raise (NotEvaluableConst NoBody)
- else raise (NotEvaluableConst IsProj)
-
-let constant_opt_value env cst =
- try Some (constant_value env cst)
- with NotEvaluableConst _ -> None
-
let constant_value_and_type env (kn, u) =
let cb = lookup_constant kn env in
if Declareops.constant_is_polymorphic cb then
diff --git a/kernel/environ.mli b/kernel/environ.mli
index 7cc541258..69d811a64 100644
--- a/kernel/environ.mli
+++ b/kernel/environ.mli
@@ -146,13 +146,11 @@ val type_in_type_constant : Constant.t -> env -> bool
body and [NotEvaluableConst IsProj] if [c] is a projection
and [Not_found] if it does not exist in [env] *)
-type const_evaluation_result = NoBody | Opaque | IsProj
+type const_evaluation_result = NoBody | Opaque
exception NotEvaluableConst of const_evaluation_result
-val constant_value : env -> Constant.t puniverses -> constr constrained
val constant_type : env -> Constant.t puniverses -> types constrained
-val constant_opt_value : env -> Constant.t puniverses -> (constr * Univ.Constraint.t) option
val constant_value_and_type : env -> Constant.t puniverses ->
constr option * types * Univ.Constraint.t
(** The universe context associated to the constant, empty if not
diff --git a/kernel/indtypes.ml b/kernel/indtypes.ml
index 1f2ae0b6c..cfca335d3 100644
--- a/kernel/indtypes.ml
+++ b/kernel/indtypes.ml
@@ -234,22 +234,32 @@ let check_subtyping_arity_constructor env (subst : constr -> constr) (arcn : typ
(* This check produces a value of the unit type if successful or raises an anomaly if check fails. *)
let check_subtyping cumi paramsctxt env_ar inds =
let numparams = Context.Rel.nhyps paramsctxt in
- let sbsubst = CumulativityInfo.subtyping_susbst cumi in
- let dosubst = subst_univs_level_constr sbsubst in
let uctx = CumulativityInfo.univ_context cumi in
- let instance_other = Univ.subst_univs_level_instance sbsubst (Univ.UContext.instance uctx) in
- let constraints_other = Univ.subst_univs_level_constraints sbsubst (Univ.UContext.constraints uctx) in
+ let new_levels = Array.init (UContext.size uctx) (Level.make DirPath.empty) in
+ let lmap = Array.fold_left2 (fun lmap u u' -> LMap.add u u' lmap)
+ LMap.empty (Instance.to_array @@ UContext.instance uctx) new_levels
+ in
+ let dosubst = subst_univs_level_constr lmap in
+ let instance_other = Instance.of_array new_levels in
+ let constraints_other = Univ.subst_univs_level_constraints lmap (Univ.UContext.constraints uctx) in
let uctx_other = Univ.UContext.make (instance_other, constraints_other) in
let env = Environ.push_context uctx env_ar in
let env = Environ.push_context uctx_other env in
- let env = push_context (CumulativityInfo.subtyp_context cumi) env in
+ let subtyp_constraints =
+ CumulativityInfo.leq_constraints cumi
+ (UContext.instance uctx) instance_other
+ Constraint.empty
+ in
+ let env = Environ.add_constraints subtyp_constraints env in
(* process individual inductive types: *)
Array.iter (fun (id,cn,lc,(sign,arity)) ->
match arity with
| RegularArity (_, full_arity, _) ->
check_subtyping_arity_constructor env dosubst full_arity numparams true;
Array.iter (fun cnt -> check_subtyping_arity_constructor env dosubst cnt numparams false) lc
- | TemplateArity _ -> ()
+ | TemplateArity _ ->
+ anomaly ~label:"check_subtyping"
+ Pp.(str "template polymorphism and cumulative polymorphism are not compatible")
) inds
(* Type-check an inductive definition. Does not check positivity
@@ -879,9 +889,13 @@ let abstract_inductive_universes iu =
match iu with
| Monomorphic_ind_entry ctx -> (Univ.empty_level_subst, Monomorphic_ind ctx)
| Polymorphic_ind_entry ctx ->
- let (inst, auctx) = Univ.abstract_universes ctx in (inst, Polymorphic_ind auctx)
+ let (inst, auctx) = Univ.abstract_universes ctx in
+ let inst = Univ.make_instance_subst inst in
+ (inst, Polymorphic_ind auctx)
| Cumulative_ind_entry cumi ->
- let (inst, acumi) = Univ.abstract_cumulativity_info cumi in (inst, Cumulative_ind acumi)
+ let (inst, acumi) = Univ.abstract_cumulativity_info cumi in
+ let inst = Univ.make_instance_subst inst in
+ (inst, Cumulative_ind acumi)
let build_inductive env prv iu env_ar paramsctxt kn isrecord isfinite inds nmr recargs =
let ntypes = Array.length inds in
diff --git a/kernel/inductive.ml b/kernel/inductive.ml
index 28a09b81b..722705bd7 100644
--- a/kernel/inductive.ml
+++ b/kernel/inductive.ml
@@ -796,18 +796,18 @@ let rec subterm_specif renv stack t =
| Proj (p, c) ->
let subt = subterm_specif renv stack c in
- (match subt with
- | Subterm (s, wf) ->
- (* We take the subterm specs of the constructor of the record *)
- let wf_args = (dest_subterms wf).(0) in
- (* We extract the tree of the projected argument *)
- let kn = Projection.constant p in
- let cb = lookup_constant kn renv.env in
- let pb = Option.get cb.const_proj in
- let n = pb.proj_arg in
- Subterm (Strict, List.nth wf_args n)
- | Dead_code -> Dead_code
- | Not_subterm -> Not_subterm)
+ (match subt with
+ | Subterm (s, wf) ->
+ (* We take the subterm specs of the constructor of the record *)
+ let wf_args = (dest_subterms wf).(0) in
+ (* We extract the tree of the projected argument *)
+ let kn = Projection.constant p in
+ let cb = lookup_constant kn renv.env in
+ let pb = Option.get cb.const_proj in
+ let n = pb.proj_arg in
+ spec_of_tree (List.nth wf_args n)
+ | Dead_code -> Dead_code
+ | Not_subterm -> Not_subterm)
| Var _ | Sort _ | Cast _ | Prod _ | LetIn _ | App _ | Const _ | Ind _
| Construct _ | CoFix _ -> Not_subterm
diff --git a/kernel/kernel.mllib b/kernel/kernel.mllib
index 917e4f6f1..749854b8c 100644
--- a/kernel/kernel.mllib
+++ b/kernel/kernel.mllib
@@ -16,6 +16,7 @@ Cemitcodes
Opaqueproof
Declarations
Entries
+Vmvalues
Nativevalues
CPrimitives
Declareops
diff --git a/kernel/mod_typing.ml b/kernel/mod_typing.ml
index f7e755f00..b7eb481ee 100644
--- a/kernel/mod_typing.ml
+++ b/kernel/mod_typing.ml
@@ -94,8 +94,8 @@ let rec check_with_def env struc (idl,(c,ctx)) mp equiv =
let ctx = Univ.ContextSet.of_context ctx in
c', Monomorphic_const ctx, Univ.ContextSet.add_constraints cst ctx
| Polymorphic_const uctx ->
- let subst, ctx = Univ.abstract_universes ctx in
- let c = Vars.subst_univs_level_constr subst c in
+ let inst, ctx = Univ.abstract_universes ctx in
+ let c = Vars.subst_univs_level_constr (Univ.make_instance_subst inst) c in
let () =
if not (UGraph.check_subtype (Environ.universes env) uctx ctx) then
error_incorrect_with_constraint lab
diff --git a/kernel/names.mli b/kernel/names.mli
index 709ebeb7f..b1e8efd8d 100644
--- a/kernel/names.mli
+++ b/kernel/names.mli
@@ -40,19 +40,16 @@ sig
(** Hash over identifiers. *)
val is_valid : string -> bool
- (** Check that a string may be converted to an identifier.
- @raise Unicode.Unsupported if the provided string contains unsupported UTF-8 characters. *)
+ (** Check that a string may be converted to an identifier. *)
val of_bytes : bytes -> t
val of_string : string -> t
(** Converts a string into an identifier.
- @raise UserError if the string is invalid as an identifier.
- @raise Unicode.Unsupported if the provided string contains unsupported UTF-8 characters. *)
+ @raise UserError if the string is invalid as an identifier. *)
val of_string_soft : string -> t
(** Same as {!of_string} except that any string made of supported UTF-8 characters is accepted.
- @raise UserError if the string is invalid as an UTF-8 string.
- @raise Unicode.Unsupported if the provided string contains unsupported UTF-8 characters. *)
+ @raise UserError if the string is invalid as an UTF-8 string. *)
val to_string : t -> string
(** Converts a identifier into an string. *)
diff --git a/kernel/nativecode.ml b/kernel/nativecode.ml
index c558e9ed0..8fa254053 100644
--- a/kernel/nativecode.ml
+++ b/kernel/nativecode.ml
@@ -148,7 +148,7 @@ type symbol =
| SymbMatch of annot_sw
| SymbInd of inductive
| SymbMeta of metavariable
- | SymbEvar of existential
+ | SymbEvar of Evar.t
| SymbLevel of Univ.Level.t
let dummy_symb = SymbValue (dummy_value ())
@@ -162,8 +162,7 @@ let eq_symbol sy1 sy2 =
| SymbMatch sw1, SymbMatch sw2 -> eq_annot_sw sw1 sw2
| SymbInd ind1, SymbInd ind2 -> eq_ind ind1 ind2
| SymbMeta m1, SymbMeta m2 -> Int.equal m1 m2
- | SymbEvar (evk1,args1), SymbEvar (evk2,args2) ->
- Evar.equal evk1 evk2 && Array.for_all2 Constr.equal args1 args2
+ | SymbEvar evk1, SymbEvar evk2 -> Evar.equal evk1 evk2
| SymbLevel l1, SymbLevel l2 -> Univ.Level.equal l1 l2
| _, _ -> false
@@ -176,10 +175,7 @@ let hash_symbol symb =
| SymbMatch sw -> combinesmall 5 (hash_annot_sw sw)
| SymbInd ind -> combinesmall 6 (ind_hash ind)
| SymbMeta m -> combinesmall 7 m
- | SymbEvar (evk,args) ->
- let evh = Evar.hash evk in
- let hl = Array.fold_left (fun h t -> combine h (Constr.hash t)) evh args in
- combinesmall 8 hl
+ | SymbEvar evk -> combinesmall 8 (Evar.hash evk)
| SymbLevel l -> combinesmall 9 (Univ.Level.hash l)
module HashedTypeSymbol = struct
@@ -1047,11 +1043,12 @@ let ml_of_instance instance u =
let tyn = fresh_lname Anonymous in
let i = push_symbol (SymbMeta mv) in
MLapp(MLprimitive Mk_meta, [|get_meta_code i; MLlocal tyn|])
- | Levar(ev,ty) ->
+ | Levar(evk,ty,args) ->
let tyn = fresh_lname Anonymous in
- let i = push_symbol (SymbEvar ev) in
+ let i = push_symbol (SymbEvar evk) in
+ let args = MLarray(Array.map (ml_of_lam env l) args) in
MLlet(tyn, ml_of_lam env l ty,
- MLapp(MLprimitive Mk_evar, [|get_evar_code i;MLlocal tyn|]))
+ MLapp(MLprimitive Mk_evar, [|get_evar_code i;MLlocal tyn; args|]))
| Lprod(dom,codom) ->
let dom = ml_of_lam env l dom in
let codom = ml_of_lam env l codom in
@@ -1830,7 +1827,7 @@ and apply_fv env sigma univ (fv_named,fv_rel) auxdefs ml =
in
let auxdefs = List.fold_right get_rel_val fv_rel auxdefs in
let auxdefs = List.fold_right get_named_val fv_named auxdefs in
- let lvl = Context.Rel.length env.env_rel_context in
+ let lvl = Context.Rel.length env.env_rel_context.env_rel_ctx in
let fv_rel = List.map (fun (n,_) -> MLglobal (Grel (lvl-n))) fv_rel in
let fv_named = List.map (fun (id,_) -> MLglobal (Gnamed id)) fv_named in
let aux_name = fresh_lname Anonymous in
@@ -1838,8 +1835,8 @@ and apply_fv env sigma univ (fv_named,fv_rel) auxdefs ml =
and compile_rel env sigma univ auxdefs n =
let open Context.Rel.Declaration in
- let decl = Context.Rel.lookup n env.env_rel_context in
- let n = Context.Rel.length env.env_rel_context - n in
+ let decl = Pre_env.lookup_rel n env in
+ let n = List.length env.env_rel_context.env_rel_ctx - n in
match decl with
| LocalDef (_,t,_) ->
let code = lambda_of_constr env sigma t in
@@ -1919,15 +1916,17 @@ let compile_constant env sigma prefix ~interactive con cb =
let asw = { asw_ind = ind; asw_prefix = prefix; asw_ci = ci;
asw_reloc = tbl; asw_finite = true } in
let c_uid = fresh_lname Anonymous in
+ let cf_uid = fresh_lname Anonymous in
let _, arity = tbl.(0) in
let ci_uid = fresh_lname Anonymous in
let cargs = Array.init arity
(fun i -> if Int.equal i pb.proj_arg then Some ci_uid else None)
in
let i = push_symbol (SymbConst con) in
- let accu = MLapp (MLprimitive Cast_accu, [|MLlocal c_uid|]) in
+ let accu = MLapp (MLprimitive Cast_accu, [|MLlocal cf_uid|]) in
let accu_br = MLapp (MLprimitive Mk_proj, [|get_const_code i;accu|]) in
- let code = MLmatch(asw,MLlocal c_uid,accu_br,[|[((ind,1),cargs)],MLlocal ci_uid|]) in
+ let code = MLmatch(asw,MLlocal cf_uid,accu_br,[|[((ind,1),cargs)],MLlocal ci_uid|]) in
+ let code = MLlet(cf_uid, MLapp (MLprimitive Force_cofix, [|MLlocal c_uid|]), code) in
let gn = Gproj ("",con) in
let fargs = Array.init (pb.proj_npars + 1) (fun _ -> fresh_lname Anonymous) in
let arg = fargs.(pb.proj_npars) in
diff --git a/kernel/nativecode.mli b/kernel/nativecode.mli
index d08f49095..7d20054f7 100644
--- a/kernel/nativecode.mli
+++ b/kernel/nativecode.mli
@@ -44,7 +44,7 @@ val get_ind : symbols -> int -> inductive
val get_meta : symbols -> int -> metavariable
-val get_evar : symbols -> int -> existential
+val get_evar : symbols -> int -> Evar.t
val get_level : symbols -> int -> Univ.Level.t
diff --git a/kernel/nativeconv.ml b/kernel/nativeconv.ml
index 9f9102f7d..bfa982136 100644
--- a/kernel/nativeconv.ml
+++ b/kernel/nativeconv.ml
@@ -54,13 +54,18 @@ and conv_accu env pb lvl k1 k2 cu =
conv_atom env pb lvl (atom_of_accu k1) (atom_of_accu k2) cu
else
let cu = conv_atom env pb lvl (atom_of_accu k1) (atom_of_accu k2) cu in
- List.fold_right2 (conv_val env CONV lvl) (args_of_accu k1) (args_of_accu k2) cu
+ Array.fold_right2 (conv_val env CONV lvl) (args_of_accu k1) (args_of_accu k2) cu
and conv_atom env pb lvl a1 a2 cu =
if a1 == a2 then cu
else
match a1, a2 with
- | Ameta _, _ | _, Ameta _ | Aevar _, _ | _, Aevar _ -> assert false
+ | Ameta (m1,_), Ameta (m2,_) ->
+ if Int.equal m1 m2 then cu else raise NotConvertible
+ | Aevar (ev1,_,args1), Aevar (ev2,_,args2) ->
+ if Evar.equal ev1 ev2 then
+ Array.fold_right2 (conv_val env CONV lvl) args1 args2 cu
+ else raise NotConvertible
| Arel i1, Arel i2 ->
if Int.equal i1 i2 then cu else raise NotConvertible
| Aind (ind1,u1), Aind (ind2,u2) ->
@@ -112,7 +117,7 @@ and conv_atom env pb lvl a1 a2 cu =
else conv_accu env CONV lvl ac1 ac2 cu
| Arel _, _ | Aind _, _ | Aconstant _, _ | Asort _, _ | Avar _, _
| Acase _, _ | Afix _, _ | Acofix _, _ | Acofixe _, _ | Aprod _, _
- | Aproj _, _ -> raise NotConvertible
+ | Aproj _, _ | Ameta _, _ | Aevar _, _ -> raise NotConvertible
(* Precondition length t1 = length f1 = length f2 = length t2 *)
and conv_fix env lvl t1 f1 t2 f2 cu =
diff --git a/kernel/nativeinstr.mli b/kernel/nativeinstr.mli
index 928283a4d..48ad88444 100644
--- a/kernel/nativeinstr.mli
+++ b/kernel/nativeinstr.mli
@@ -23,7 +23,7 @@ and lambda =
| Lrel of Name.t * int
| Lvar of Id.t
| Lmeta of metavariable * lambda (* type *)
- | Levar of existential * lambda (* type *)
+ | Levar of Evar.t * lambda (* type *) * lambda array (* arguments *)
| Lprod of lambda * lambda
| Llam of Name.t array * lambda
| Llet of Name.t * lambda * lambda
diff --git a/kernel/nativelambda.ml b/kernel/nativelambda.ml
index 160a90dc2..29b3e59da 100644
--- a/kernel/nativelambda.ml
+++ b/kernel/nativelambda.ml
@@ -453,11 +453,12 @@ let rec lambda_of_constr env sigma c =
let ty = meta_type sigma mv in
Lmeta (mv, lambda_of_constr env sigma ty)
- | Evar ev ->
+ | Evar (evk,args as ev) ->
(match evar_value sigma ev with
| None ->
let ty = evar_type sigma ev in
- Levar(ev, lambda_of_constr env sigma ty)
+ let args = Array.map (lambda_of_constr env sigma) args in
+ Levar(evk, lambda_of_constr env sigma ty, args)
| Some t -> lambda_of_constr env sigma t)
| Cast (c, _, _) -> lambda_of_constr env sigma c
@@ -639,7 +640,7 @@ let optimize lam =
let lambda_of_constr env sigma c =
set_global_env env;
let env = Renv.make () in
- let ids = List.rev_map RelDecl.get_name !global_env.env_rel_context in
+ let ids = List.rev_map RelDecl.get_name !global_env.env_rel_context.env_rel_ctx in
Renv.push_rels env (Array.of_list ids);
let lam = lambda_of_constr env sigma c in
(* if Flags.vm_draw_opt () then begin
diff --git a/kernel/nativelib.ml b/kernel/nativelib.ml
index 4e7d6b218..1e35f6c03 100644
--- a/kernel/nativelib.ml
+++ b/kernel/nativelib.ml
@@ -157,9 +157,8 @@ let call_linker ?(fatal=true) prefix f upds =
register_native_file prefix
with Dynlink.Error e as exn ->
let exn = CErrors.push exn in
- let msg = "Dynlink error, " ^ Dynlink.error_message e in
- if fatal then (Feedback.msg_error (Pp.str msg); iraise exn)
- else if !Flags.debug then Feedback.msg_debug (Pp.str msg));
+ if fatal then iraise exn
+ else if !Flags.debug then Feedback.msg_debug CErrors.(iprint exn));
match upds with Some upds -> update_locations upds | _ -> ()
let link_library ~prefix ~dirname ~basename =
diff --git a/kernel/nativevalues.ml b/kernel/nativevalues.ml
index ae66362ca..3d47b1672 100644
--- a/kernel/nativevalues.ml
+++ b/kernel/nativevalues.ml
@@ -61,7 +61,7 @@ type atom =
| Acofixe of t array * t array * int * t
| Aprod of Name.t * t * (t -> t)
| Ameta of metavariable * t
- | Aevar of existential * t
+ | Aevar of Evar.t * t * t array
| Aproj of Constant.t * accumulator
let accumulate_tag = 0
@@ -132,8 +132,8 @@ let mk_prod_accu s dom codom =
let mk_meta_accu mv ty =
mk_accu (Ameta (mv,ty))
-let mk_evar_accu ev ty =
- mk_accu (Aevar (ev,ty))
+let mk_evar_accu ev ty args =
+ mk_accu (Aevar (ev,ty,args))
let mk_proj_accu kn c =
mk_accu (Aproj (kn,c))
@@ -153,8 +153,7 @@ let accu_nargs (k:accumulator) =
let args_of_accu (k:accumulator) =
let nargs = accu_nargs k in
let f i = (Obj.magic (Obj.field (Obj.magic k) (nargs-i+2)) : t) in
- let t = Array.init nargs f in
- Array.to_list t
+ Array.init nargs f
let is_accu x =
let o = Obj.repr x in
@@ -179,11 +178,10 @@ let force_cofix (cofix : t) =
let atom = atom_of_accu accu in
match atom with
| Acofix(typ,norm,pos,f) ->
- let f = ref f in
- let args = List.rev (args_of_accu accu) in
- List.iter (fun x -> f := !f x) args;
- let v = !f (Obj.magic ()) in
- set_atom_of_accu accu (Acofixe(typ,norm,pos,v));
+ let args = args_of_accu accu in
+ let f = Array.fold_right (fun arg f -> f arg) args f in
+ let v = f (Obj.magic ()) in
+ set_atom_of_accu accu (Acofixe(typ,norm,pos,v));
v
| Acofixe(_,_,_,v) -> v
| _ -> cofix
diff --git a/kernel/nativevalues.mli b/kernel/nativevalues.mli
index 18b877745..993842740 100644
--- a/kernel/nativevalues.mli
+++ b/kernel/nativevalues.mli
@@ -51,7 +51,7 @@ type atom =
| Acofixe of t array * t array * int * t
| Aprod of Name.t * t * (t -> t)
| Ameta of metavariable * t
- | Aevar of existential * t
+ | Aevar of Evar.t * t (* type *) * t array (* arguments *)
| Aproj of Constant.t * accumulator
(* Constructors *)
@@ -68,7 +68,7 @@ val mk_prod_accu : Name.t -> t -> t -> t
val mk_fix_accu : rec_pos -> int -> t array -> t array -> t
val mk_cofix_accu : int -> t array -> t array -> t
val mk_meta_accu : metavariable -> t
-val mk_evar_accu : existential -> t -> t
+val mk_evar_accu : Evar.t -> t -> t array -> t
val mk_proj_accu : Constant.t -> accumulator -> t
val upd_cofix : t -> t -> unit
val force_cofix : t -> t
@@ -84,7 +84,7 @@ val napply : t -> t array -> t
val dummy_value : unit -> t
val atom_of_accu : accumulator -> atom
-val args_of_accu : accumulator -> t list
+val args_of_accu : accumulator -> t array
val accu_nargs : accumulator -> int
val cast_accu : t -> accumulator
diff --git a/kernel/opaqueproof.ml b/kernel/opaqueproof.ml
index 45a62d55a..c2fcfbfd6 100644
--- a/kernel/opaqueproof.ml
+++ b/kernel/opaqueproof.ml
@@ -16,7 +16,7 @@ type work_list = (Instance.t * Id.t array) Cmap.t *
type cooking_info = {
modlist : work_list;
- abstract : Context.Named.t * Univ.universe_level_subst * Univ.AUContext.t }
+ abstract : Context.Named.t * Univ.Instance.t * Univ.AUContext.t }
type proofterm = (constr * Univ.ContextSet.t) Future.computation
type opaque =
| Indirect of substitution list * DirPath.t * int (* subst, lib, index *)
diff --git a/kernel/opaqueproof.mli b/kernel/opaqueproof.mli
index 20d76ce23..c8339e6eb 100644
--- a/kernel/opaqueproof.mli
+++ b/kernel/opaqueproof.mli
@@ -49,7 +49,7 @@ type work_list = (Univ.Instance.t * Id.t array) Cmap.t *
type cooking_info = {
modlist : work_list;
- abstract : Context.Named.t * Univ.universe_level_subst * Univ.AUContext.t }
+ abstract : Context.Named.t * Univ.Instance.t * Univ.AUContext.t }
(* The type has two caveats:
1) cook_constr is defined after
diff --git a/kernel/pre_env.ml b/kernel/pre_env.ml
index c5254b453..6c5e1cde5 100644
--- a/kernel/pre_env.ml
+++ b/kernel/pre_env.ml
@@ -15,7 +15,6 @@
open Util
open Names
-open Constr
open Declarations
module NamedDecl = Context.Named.Declaration
@@ -50,7 +49,7 @@ type stratification = {
}
type val_kind =
- | VKvalue of (values * Id.Set.t) CEphemeron.key
+ | VKvalue of (Vmvalues.values * Id.Set.t) CEphemeron.key
| VKnone
type lazy_val = val_kind ref
@@ -67,15 +66,18 @@ type named_context_val = {
env_named_map : (Context.Named.Declaration.t * lazy_val) Id.Map.t;
}
+type rel_context_val = {
+ env_rel_ctx : Context.Rel.t;
+ env_rel_map : (Context.Rel.Declaration.t * lazy_val) Range.t;
+}
+
type env = {
env_globals : globals; (* globals = constants + inductive types + modules + module-types *)
env_named_context : named_context_val; (* section variables *)
- env_rel_context : Context.Rel.t;
- env_rel_val : lazy_val list;
+ env_rel_context : rel_context_val;
env_nb_rel : int;
env_stratification : stratification;
env_typing_flags : typing_flags;
- env_conv_oracle : Conv_oracle.oracle;
retroknowledge : Retroknowledge.retroknowledge;
indirect_pterms : Opaqueproof.opaquetab;
}
@@ -85,6 +87,11 @@ let empty_named_context_val = {
env_named_map = Id.Map.empty;
}
+let empty_rel_context_val = {
+ env_rel_ctx = [];
+ env_rel_map = Range.empty;
+}
+
let empty_env = {
env_globals = {
env_constants = Cmap_env.empty;
@@ -92,14 +99,12 @@ let empty_env = {
env_modules = MPmap.empty;
env_modtypes = MPmap.empty};
env_named_context = empty_named_context_val;
- env_rel_context = Context.Rel.empty;
- env_rel_val = [];
+ env_rel_context = empty_rel_context_val;
env_nb_rel = 0;
env_stratification = {
env_universes = UGraph.initial_universes;
env_engagement = PredicativeSet };
- env_typing_flags = Declareops.safe_flags;
- env_conv_oracle = Conv_oracle.empty;
+ env_typing_flags = Declareops.safe_flags Conv_oracle.empty;
retroknowledge = Retroknowledge.initial_retroknowledge;
indirect_pterms = Opaqueproof.empty_opaquetab }
@@ -108,21 +113,39 @@ let empty_env = {
let nb_rel env = env.env_nb_rel
+let push_rel_context_val d ctx = {
+ env_rel_ctx = Context.Rel.add d ctx.env_rel_ctx;
+ env_rel_map = Range.cons (d, ref VKnone) ctx.env_rel_map;
+}
+
+let match_rel_context_val ctx = match ctx.env_rel_ctx with
+| [] -> None
+| decl :: rem ->
+ let (_, lval) = Range.hd ctx.env_rel_map in
+ let ctx = { env_rel_ctx = rem; env_rel_map = Range.tl ctx.env_rel_map } in
+ Some (decl, lval, ctx)
+
let push_rel d env =
- let rval = ref VKnone in
{ env with
- env_rel_context = Context.Rel.add d env.env_rel_context;
- env_rel_val = rval :: env.env_rel_val;
+ env_rel_context = push_rel_context_val d env.env_rel_context;
env_nb_rel = env.env_nb_rel + 1 }
+let lookup_rel n env =
+ try fst (Range.get env.env_rel_context.env_rel_map (n - 1))
+ with Invalid_argument _ -> raise Not_found
+
let lookup_rel_val n env =
- try List.nth env.env_rel_val (n - 1)
- with Failure _ -> raise Not_found
+ try snd (Range.get env.env_rel_context.env_rel_map (n - 1))
+ with Invalid_argument _ -> raise Not_found
+
+let rel_skipn n ctx = {
+ env_rel_ctx = Util.List.skipn n ctx.env_rel_ctx;
+ env_rel_map = Range.skipn n ctx.env_rel_map;
+}
let env_of_rel n env =
{ env with
- env_rel_context = Util.List.skipn n env.env_rel_context;
- env_rel_val = Util.List.skipn n env.env_rel_val;
+ env_rel_context = rel_skipn n env.env_rel_context;
env_nb_rel = env.env_nb_rel - n
}
diff --git a/kernel/pre_env.mli b/kernel/pre_env.mli
index 054ae1743..a6b57bd1b 100644
--- a/kernel/pre_env.mli
+++ b/kernel/pre_env.mli
@@ -36,24 +36,27 @@ type stratification = {
type lazy_val
-val force_lazy_val : lazy_val -> (values * Id.Set.t) option
+val force_lazy_val : lazy_val -> (Vmvalues.values * Id.Set.t) option
val dummy_lazy_val : unit -> lazy_val
-val build_lazy_val : lazy_val -> (values * Id.Set.t) -> unit
+val build_lazy_val : lazy_val -> (Vmvalues.values * Id.Set.t) -> unit
type named_context_val = private {
env_named_ctx : Context.Named.t;
env_named_map : (Context.Named.Declaration.t * lazy_val) Id.Map.t;
}
+type rel_context_val = private {
+ env_rel_ctx : Context.Rel.t;
+ env_rel_map : (Context.Rel.Declaration.t * lazy_val) Range.t;
+}
+
type env = {
env_globals : globals;
env_named_context : named_context_val;
- env_rel_context : Context.Rel.t;
- env_rel_val : lazy_val list;
+ env_rel_context : rel_context_val;
env_nb_rel : int;
env_stratification : stratification;
env_typing_flags : typing_flags;
- env_conv_oracle : Conv_oracle.oracle;
retroknowledge : Retroknowledge.retroknowledge;
indirect_pterms : Opaqueproof.opaquetab;
}
@@ -64,8 +67,15 @@ val empty_env : env
(** Rel context *)
+val empty_rel_context_val : rel_context_val
+val push_rel_context_val :
+ Context.Rel.Declaration.t -> rel_context_val -> rel_context_val
+val match_rel_context_val :
+ rel_context_val -> (Context.Rel.Declaration.t * lazy_val * rel_context_val) option
+
val nb_rel : env -> int
val push_rel : Context.Rel.Declaration.t -> env -> env
+val lookup_rel : int -> env -> Context.Rel.Declaration.t
val lookup_rel_val : int -> env -> lazy_val
val env_of_rel : int -> env -> env
diff --git a/kernel/reduction.ml b/kernel/reduction.ml
index c07ac973b..da7042713 100644
--- a/kernel/reduction.ml
+++ b/kernel/reduction.ml
@@ -200,13 +200,9 @@ let is_cumul = function CUMUL -> true | CONV -> false
type 'a universe_compare =
{ (* Might raise NotConvertible *)
- compare : env -> conv_pb -> Sorts.t -> Sorts.t -> 'a -> 'a;
+ compare_sorts : env -> conv_pb -> Sorts.t -> Sorts.t -> 'a -> 'a;
compare_instances: flex:bool -> Univ.Instance.t -> Univ.Instance.t -> 'a -> 'a;
- conv_inductives : conv_pb -> (Declarations.mutual_inductive_body * int) -> Univ.Instance.t -> int ->
- Univ.Instance.t -> int -> 'a -> 'a;
- conv_constructors : (Declarations.mutual_inductive_body * int * int) ->
- Univ.Instance.t -> int -> Univ.Instance.t -> int -> 'a -> 'a;
- }
+ compare_cumul_instances : Univ.Constraint.t -> 'a -> 'a }
type 'a universe_state = 'a * 'a universe_compare
@@ -215,18 +211,68 @@ type ('a,'b) generic_conversion_function = env -> 'b universe_state -> 'a -> 'a
type 'a infer_conversion_function = env -> UGraph.t -> 'a -> 'a -> Univ.Constraint.t
let sort_cmp_universes env pb s0 s1 (u, check) =
- (check.compare env pb s0 s1 u, check)
+ (check.compare_sorts env pb s0 s1 u, check)
(* [flex] should be true for constants, false for inductive types and
constructors. *)
let convert_instances ~flex u u' (s, check) =
(check.compare_instances ~flex u u' s, check)
-
-let convert_inductives cv_pb ind u1 sv1 u2 sv2 (s, check) =
- (check.conv_inductives cv_pb ind u1 sv1 u2 sv2 s, check)
-let convert_constructors cons u1 sv1 u2 sv2 (s, check) =
- (check.conv_constructors cons u1 sv1 u2 sv2 s, check)
+let get_cumulativity_constraints cv_pb cumi u u' =
+ match cv_pb with
+ | CONV ->
+ Univ.ACumulativityInfo.eq_constraints cumi u u' Univ.Constraint.empty
+ | CUMUL ->
+ Univ.ACumulativityInfo.leq_constraints cumi u u' Univ.Constraint.empty
+
+let inductive_cumulativity_arguments (mind,ind) =
+ mind.Declarations.mind_nparams +
+ mind.Declarations.mind_packets.(ind).Declarations.mind_nrealargs
+
+let convert_inductives_gen cmp_instances cmp_cumul cv_pb (mind,ind) nargs u1 u2 s =
+ match mind.Declarations.mind_universes with
+ | Declarations.Monomorphic_ind _ ->
+ assert (Univ.Instance.length u1 = 0 && Univ.Instance.length u2 = 0);
+ s
+ | Declarations.Polymorphic_ind _ ->
+ cmp_instances u1 u2 s
+ | Declarations.Cumulative_ind cumi ->
+ let num_param_arity = inductive_cumulativity_arguments (mind,ind) in
+ if not (Int.equal num_param_arity nargs) then
+ cmp_instances u1 u2 s
+ else
+ let csts = get_cumulativity_constraints cv_pb cumi u1 u2 in
+ cmp_cumul csts s
+
+let convert_inductives cv_pb ind nargs u1 u2 (s, check) =
+ convert_inductives_gen (check.compare_instances ~flex:false) check.compare_cumul_instances
+ cv_pb ind nargs u1 u2 s, check
+
+let constructor_cumulativity_arguments (mind, ind, ctor) =
+ let nparamsctxt =
+ mind.Declarations.mind_nparams +
+ mind.Declarations.mind_packets.(ind).Declarations.mind_nrealargs
+ (* Context.Rel.length mind.Declarations.mind_params_ctxt *) in
+ nparamsctxt + mind.Declarations.mind_packets.(ind).Declarations.mind_consnrealargs.(ctor - 1)
+
+let convert_constructors_gen cmp_instances cmp_cumul (mind, ind, cns) nargs u1 u2 s =
+ match mind.Declarations.mind_universes with
+ | Declarations.Monomorphic_ind _ ->
+ assert (Univ.Instance.length u1 = 0 && Univ.Instance.length u2 = 0);
+ s
+ | Declarations.Polymorphic_ind _ ->
+ cmp_instances u1 u2 s
+ | Declarations.Cumulative_ind cumi ->
+ let num_cnstr_args = constructor_cumulativity_arguments (mind,ind,cns) in
+ if not (Int.equal num_cnstr_args nargs) then
+ cmp_instances u1 u2 s
+ else
+ let csts = get_cumulativity_constraints CONV cumi u1 u2 in
+ cmp_cumul csts s
+
+let convert_constructors ctor nargs u1 u2 (s, check) =
+ convert_constructors_gen (check.compare_instances ~flex:false) check.compare_cumul_instances
+ ctor nargs u1 u2 s, check
let conv_table_key infos k1 k2 cuniv =
if k1 == k2 then cuniv else
@@ -308,17 +354,6 @@ let in_whnf (t,stk) =
| (FFlex _ | FProd _ | FEvar _ | FInd _ | FAtom _ | FRel _ | FProj _) -> true
| FLOCKED -> assert false
-let unfold_projection infos p c =
- let unf = Projection.unfolded p in
- if unf || RedFlags.red_set infos.i_flags (RedFlags.fCONST (Projection.constant p)) then
- (match try Some (lookup_projection p (info_env infos)) with Not_found -> None with
- | Some pb ->
- let s = Zproj (pb.Declarations.proj_npars, pb.Declarations.proj_arg,
- Projection.constant p) in
- Some (c, s)
- | None -> None)
- else None
-
(* Conversion between [lft1]term1 and [lft2]term2 *)
let rec ccnv cv_pb l2r infos lft1 lft2 term1 term2 cuniv =
eqappr cv_pb l2r infos (lft1, (term1,[])) (lft2, (term2,[])) cuniv
@@ -336,9 +371,8 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
if in_whnf st1' then (st1',st2') else whd_both st1' st2' in
let ((hd1,v1),(hd2,v2)) = whd_both st1 st2 in
let appr1 = (lft1,(hd1,v1)) and appr2 = (lft2,(hd2,v2)) in
- (* compute the lifts that apply to the head of the term (hd1 and hd2) *)
- let el1 = el_stack lft1 v1 in
- let el2 = el_stack lft2 v2 in
+ (** We delay the computation of the lifts that apply to the head of the term
+ with [el_stack] inside the branches where they are actually used. *)
match (fterm_of hd1, fterm_of hd2) with
(* case of leaves *)
| (FAtom a1, FAtom a2) ->
@@ -354,6 +388,8 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
| _ -> raise NotConvertible)
| (FEvar ((ev1,args1),env1), FEvar ((ev2,args2),env2)) ->
if Evar.equal ev1 ev2 then
+ let el1 = el_stack lft1 v1 in
+ let el2 = el_stack lft2 v2 in
let cuniv = convert_stacks l2r infos lft1 lft2 v1 v2 cuniv in
convert_vect l2r infos el1 el2
(Array.map (mk_clos env1) args1)
@@ -362,6 +398,8 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
(* 2 index known to be bound to no constant *)
| (FRel n, FRel m) ->
+ let el1 = el_stack lft1 v1 in
+ let el2 = el_stack lft2 v2 in
if Int.equal (reloc_rel n el1) (reloc_rel m el2)
then convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
else raise NotConvertible
@@ -396,25 +434,27 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
(* Projections: prefer unfolding to first-order unification,
which will happen naturally if the terms c1, c2 are not in constructor
form *)
- (match unfold_projection infos p1 c1 with
- | Some (def1,s1) ->
- eqappr cv_pb l2r infos (lft1, (def1, (s1 :: v1))) appr2 cuniv
+ (match unfold_projection infos p1 with
+ | Some s1 ->
+ eqappr cv_pb l2r infos (lft1, (c1, (s1 :: v1))) appr2 cuniv
| None ->
- match unfold_projection infos p2 c2 with
- | Some (def2,s2) ->
- eqappr cv_pb l2r infos appr1 (lft2, (def2, (s2 :: v2))) cuniv
+ match unfold_projection infos p2 with
+ | Some s2 ->
+ eqappr cv_pb l2r infos appr1 (lft2, (c2, (s2 :: v2))) cuniv
| None ->
if Constant.equal (Projection.constant p1) (Projection.constant p2)
&& compare_stack_shape v1 v2 then
+ let el1 = el_stack lft1 v1 in
+ let el2 = el_stack lft2 v2 in
let u1 = ccnv CONV l2r infos el1 el2 c1 c2 cuniv in
convert_stacks l2r infos lft1 lft2 v1 v2 u1
else (* Two projections in WHNF: unfold *)
raise NotConvertible)
| (FProj (p1,c1), t2) ->
- (match unfold_projection infos p1 c1 with
- | Some (def1,s1) ->
- eqappr cv_pb l2r infos (lft1, (def1, (s1 :: v1))) appr2 cuniv
+ (match unfold_projection infos p1 with
+ | Some s1 ->
+ eqappr cv_pb l2r infos (lft1, (c1, (s1 :: v1))) appr2 cuniv
| None ->
(match t2 with
| FFlex fl2 ->
@@ -425,9 +465,9 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
| _ -> raise NotConvertible))
| (t1, FProj (p2,c2)) ->
- (match unfold_projection infos p2 c2 with
- | Some (def2,s2) ->
- eqappr cv_pb l2r infos appr1 (lft2, (def2, (s2 :: v2))) cuniv
+ (match unfold_projection infos p2 with
+ | Some s2 ->
+ eqappr cv_pb l2r infos appr1 (lft2, (c2, (s2 :: v2))) cuniv
| None ->
(match t1 with
| FFlex fl1 ->
@@ -445,6 +485,8 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
anomaly (Pp.str "conversion was given ill-typed terms (FLambda).");
let (_,ty1,bd1) = destFLambda mk_clos hd1 in
let (_,ty2,bd2) = destFLambda mk_clos hd2 in
+ let el1 = el_stack lft1 v1 in
+ let el2 = el_stack lft2 v2 in
let cuniv = ccnv CONV l2r infos el1 el2 ty1 ty2 cuniv in
ccnv CONV l2r infos (el_lift el1) (el_lift el2) bd1 bd2 cuniv
@@ -452,6 +494,8 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
if not (is_empty_stack v1 && is_empty_stack v2) then
anomaly (Pp.str "conversion was given ill-typed terms (FProd).");
(* Luo's system *)
+ let el1 = el_stack lft1 v1 in
+ let el2 = el_stack lft2 v2 in
let cuniv = ccnv CONV l2r infos el1 el2 c1 c'1 cuniv in
ccnv cv_pb l2r infos (el_lift el1) (el_lift el2) c2 c'2 cuniv
@@ -479,7 +523,13 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
| (FFlex fl1, c2) ->
(match unfold_reference infos fl1 with
| Some def1 ->
- eqappr cv_pb l2r infos (lft1, (def1, v1)) appr2 cuniv
+ (** By virtue of the previous case analyses, we know [c2] is rigid.
+ Conversion check to rigid terms eventually implies full weak-head
+ reduction, so instead of repeatedly performing small-step
+ unfoldings, we perform reduction with all flags on. *)
+ let all = RedFlags.red_add_transparent all (RedFlags.red_transparent (info_flags infos)) in
+ let r1 = whd_stack (infos_with_reds infos all) def1 v1 in
+ eqappr cv_pb l2r infos (lft1, r1) appr2 cuniv
| None ->
match c2 with
| FConstruct ((ind2,j2),u2) ->
@@ -493,7 +543,10 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
| (c1, FFlex fl2) ->
(match unfold_reference infos fl2 with
| Some def2 ->
- eqappr cv_pb l2r infos appr1 (lft2, (def2, v2)) cuniv
+ (** Symmetrical case of above. *)
+ let all = RedFlags.red_add_transparent all (RedFlags.red_transparent (info_flags infos)) in
+ let r2 = whd_stack (infos_with_reds infos all) def2 v2 in
+ eqappr cv_pb l2r infos appr1 (lft2, r2) cuniv
| None ->
match c1 with
| FConstruct ((ind1,j1),u1) ->
@@ -511,15 +564,12 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
else
let mind = Environ.lookup_mind (fst ind1) (info_env infos) in
- let cuniv =
- match mind.Declarations.mind_universes with
- | Declarations.Monomorphic_ind _ | Declarations.Polymorphic_ind _ ->
- convert_instances ~flex:false u1 u2 cuniv
- | Declarations.Cumulative_ind cumi ->
- convert_inductives cv_pb (mind, snd ind1) u1 (CClosure.stack_args_size v1)
- u2 (CClosure.stack_args_size v2) cuniv
- in
- convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
+ let nargs = CClosure.stack_args_size v1 in
+ if not (Int.equal nargs (CClosure.stack_args_size v2))
+ then raise NotConvertible
+ else
+ let cuniv = convert_inductives cv_pb (mind, snd ind1) nargs u1 u2 cuniv in
+ convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
else raise NotConvertible
| (FConstruct ((ind1,j1),u1), FConstruct ((ind2,j2),u2)) ->
@@ -529,16 +579,12 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
else
let mind = Environ.lookup_mind (fst ind1) (info_env infos) in
- let cuniv =
- match mind.Declarations.mind_universes with
- | Declarations.Monomorphic_ind _ | Declarations.Polymorphic_ind _ ->
- convert_instances ~flex:false u1 u2 cuniv
- | Declarations.Cumulative_ind _ ->
- convert_constructors
- (mind, snd ind1, j1) u1 (CClosure.stack_args_size v1)
- u2 (CClosure.stack_args_size v2) cuniv
- in
- convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
+ let nargs = CClosure.stack_args_size v1 in
+ if not (Int.equal nargs (CClosure.stack_args_size v2))
+ then raise NotConvertible
+ else
+ let cuniv = convert_constructors (mind, snd ind1, j1) nargs u1 u2 cuniv in
+ convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
else raise NotConvertible
(* Eta expansion of records *)
@@ -564,6 +610,8 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
let fty2 = Array.map (mk_clos e2) tys2 in
let fcl1 = Array.map (mk_clos (subs_liftn n e1)) cl1 in
let fcl2 = Array.map (mk_clos (subs_liftn n e2)) cl2 in
+ let el1 = el_stack lft1 v1 in
+ let el2 = el_stack lft2 v2 in
let cuniv = convert_vect l2r infos el1 el2 fty1 fty2 cuniv in
let cuniv =
convert_vect l2r infos
@@ -579,6 +627,8 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
let fty2 = Array.map (mk_clos e2) tys2 in
let fcl1 = Array.map (mk_clos (subs_liftn n e1)) cl1 in
let fcl2 = Array.map (mk_clos (subs_liftn n e2)) cl2 in
+ let el1 = el_stack lft1 v1 in
+ let el2 = el_stack lft2 v2 in
let cuniv = convert_vect l2r infos el1 el2 fty1 fty2 cuniv in
let cuniv =
convert_vect l2r infos
@@ -655,84 +705,14 @@ let check_convert_instances ~flex u u' univs =
else raise NotConvertible
(* general conversion and inference functions *)
-let infer_check_conv_inductives
- infer_check_convert_instances
- infer_check_inductive_instances
- cv_pb (mind, ind) u1 sv1 u2 sv2 univs =
- match mind.Declarations.mind_universes with
- | Declarations.Monomorphic_ind _ | Declarations.Polymorphic_ind _ ->
- infer_check_convert_instances ~flex:false u1 u2 univs
- | Declarations.Cumulative_ind cumi ->
- let num_param_arity =
- mind.Declarations.mind_nparams + mind.Declarations.mind_packets.(ind).Declarations.mind_nrealargs
- in
- if not (num_param_arity = sv1 && num_param_arity = sv2) then
- infer_check_convert_instances ~flex:false u1 u2 univs
- else
- infer_check_inductive_instances cv_pb cumi u1 u2 univs
-
-let infer_check_conv_constructors
- infer_check_convert_instances
- infer_check_inductive_instances
- (mind, ind, cns) u1 sv1 u2 sv2 univs =
- match mind.Declarations.mind_universes with
- | Declarations.Monomorphic_ind _ | Declarations.Polymorphic_ind _ ->
- infer_check_convert_instances ~flex:false u1 u2 univs
- | Declarations.Cumulative_ind cumi ->
- let num_cnstr_args =
- let nparamsctxt =
- mind.Declarations.mind_nparams + mind.Declarations.mind_packets.(ind).Declarations.mind_nrealargs
- (* Context.Rel.length mind.Declarations.mind_params_ctxt *) in
- nparamsctxt + mind.Declarations.mind_packets.(ind).Declarations.mind_consnrealargs.(cns - 1)
- in
- if not (num_cnstr_args = sv1 && num_cnstr_args = sv2) then
- infer_check_convert_instances ~flex:false u1 u2 univs
- else
- infer_check_inductive_instances CONV cumi u1 u2 univs
-
-let check_inductive_instances cv_pb cumi u u' univs =
- let length_ind_instance =
- Univ.AUContext.size (Univ.ACumulativityInfo.univ_context cumi)
- in
- let ind_subtypctx = Univ.ACumulativityInfo.subtyp_context cumi in
- if not ((length_ind_instance = Univ.Instance.length u) &&
- (length_ind_instance = Univ.Instance.length u')) then
- anomaly (Pp.str "Invalid inductive subtyping encountered!")
- else
- let comp_cst =
- let comp_subst = (Univ.Instance.append u u') in
- Univ.AUContext.instantiate comp_subst ind_subtypctx
- in
- let comp_cst =
- match cv_pb with
- CONV ->
- let comp_cst' =
- let comp_subst = (Univ.Instance.append u' u) in
- Univ.AUContext.instantiate comp_subst ind_subtypctx
- in
- Univ.Constraint.union comp_cst comp_cst'
- | CUMUL -> comp_cst
- in
- if (UGraph.check_constraints comp_cst univs) then univs
- else raise NotConvertible
-
-let check_conv_inductives cv_pb ind u1 sv1 u2 sv2 univs =
- infer_check_conv_inductives
- check_convert_instances
- check_inductive_instances
- cv_pb ind u1 sv1 u2 sv2 univs
-
-let check_conv_constructors cns u1 sv1 u2 sv2 univs =
- infer_check_conv_constructors
- check_convert_instances
- check_inductive_instances
- cns u1 sv1 u2 sv2 univs
+let check_inductive_instances csts univs =
+ if (UGraph.check_constraints csts univs) then univs
+ else raise NotConvertible
let checked_universes =
- { compare = checked_sort_cmp_universes;
+ { compare_sorts = checked_sort_cmp_universes;
compare_instances = check_convert_instances;
- conv_inductives = check_conv_inductives;
- conv_constructors = check_conv_constructors}
+ compare_cumul_instances = check_inductive_instances; }
let infer_eq (univs, cstrs as cuniv) u u' =
if UGraph.check_eq univs u u' then cuniv
@@ -775,49 +755,13 @@ let infer_convert_instances ~flex u u' (univs,cstrs) =
else Univ.enforce_eq_instances u u' cstrs
in (univs, cstrs')
-let infer_inductive_instances cv_pb cumi u u' (univs, cstrs) =
- let length_ind_instance =
- Univ.AUContext.size (Univ.ACumulativityInfo.univ_context cumi)
- in
- let ind_subtypctx = Univ.ACumulativityInfo.subtyp_context cumi in
- if not ((length_ind_instance = Univ.Instance.length u) &&
- (length_ind_instance = Univ.Instance.length u')) then
- anomaly (Pp.str "Invalid inductive subtyping encountered!")
- else
- let comp_cst =
- let comp_subst = (Univ.Instance.append u u') in
- Univ.AUContext.instantiate comp_subst ind_subtypctx
- in
- let comp_cst =
- match cv_pb with
- CONV ->
- let comp_cst' =
- let comp_subst = (Univ.Instance.append u' u) in
- Univ.AUContext.instantiate comp_subst ind_subtypctx
- in
- Univ.Constraint.union comp_cst comp_cst'
- | CUMUL -> comp_cst
- in
- (univs, Univ.Constraint.union cstrs comp_cst)
-
-
-let infer_conv_inductives cv_pb ind u1 sv1 u2 sv2 univs =
- infer_check_conv_inductives
- infer_convert_instances
- infer_inductive_instances
- cv_pb ind u1 sv1 u2 sv2 univs
-
-let infer_conv_constructors cns u1 sv1 u2 sv2 univs =
- infer_check_conv_constructors
- infer_convert_instances
- infer_inductive_instances
- cns u1 sv1 u2 sv2 univs
-
-let inferred_universes : (UGraph.t * Univ.Constraint.t) universe_compare =
- { compare = infer_cmp_universes;
+let infer_inductive_instances csts (univs,csts') =
+ (univs, Univ.Constraint.union csts csts')
+
+let inferred_universes : (UGraph.t * Univ.Constraint.t) universe_compare =
+ { compare_sorts = infer_cmp_universes;
compare_instances = infer_convert_instances;
- conv_inductives = infer_conv_inductives;
- conv_constructors = infer_conv_constructors}
+ compare_cumul_instances = infer_inductive_instances; }
let gen_conv cv_pb l2r reds env evars univs t1 t2 =
let b =
@@ -938,6 +882,18 @@ let hnf_prod_app env t n =
let hnf_prod_applist env t nl =
List.fold_left (hnf_prod_app env) t nl
+let hnf_prod_applist_assum env n c l =
+ let rec app n subst t l =
+ if Int.equal n 0 then
+ if l == [] then substl subst t
+ else anomaly (Pp.str "Too many arguments.")
+ else match kind (whd_allnolet env t), l with
+ | Prod(_,_,c), arg::l -> app (n-1) (arg::subst) c l
+ | LetIn(_,b,_,c), _ -> app (n-1) (substl subst b::subst) c l
+ | _, [] -> anomaly (Pp.str "Not enough arguments.")
+ | _ -> anomaly (Pp.str "Not enough prod/let's.") in
+ app n [] c l
+
(* Dealing with arities *)
let dest_prod env =
diff --git a/kernel/reduction.mli b/kernel/reduction.mli
index 573e4c8bd..6f7e3f8f8 100644
--- a/kernel/reduction.mli
+++ b/kernel/reduction.mli
@@ -35,15 +35,11 @@ type 'a extended_conversion_function =
type conv_pb = CONV | CUMUL
-type 'a universe_compare =
+type 'a universe_compare =
{ (* Might raise NotConvertible *)
- compare : env -> conv_pb -> Sorts.t -> Sorts.t -> 'a -> 'a;
+ compare_sorts : env -> conv_pb -> Sorts.t -> Sorts.t -> 'a -> 'a;
compare_instances: flex:bool -> Univ.Instance.t -> Univ.Instance.t -> 'a -> 'a;
- conv_inductives : conv_pb -> (Declarations.mutual_inductive_body * int) -> Univ.Instance.t -> int ->
- Univ.Instance.t -> int -> 'a -> 'a;
- conv_constructors : (Declarations.mutual_inductive_body * int * int) ->
- Univ.Instance.t -> int -> Univ.Instance.t -> int -> 'a -> 'a;
- }
+ compare_cumul_instances : Univ.Constraint.t -> 'a -> 'a }
type 'a universe_state = 'a * 'a universe_compare
@@ -51,6 +47,12 @@ type ('a,'b) generic_conversion_function = env -> 'b universe_state -> 'a -> 'a
type 'a infer_conversion_function = env -> UGraph.t -> 'a -> 'a -> Univ.Constraint.t
+val get_cumulativity_constraints : conv_pb -> Univ.ACumulativityInfo.t ->
+ Univ.Instance.t -> Univ.Instance.t -> Univ.Constraint.t
+
+val inductive_cumulativity_arguments : (Declarations.mutual_inductive_body * int) -> int
+val constructor_cumulativity_arguments : (Declarations.mutual_inductive_body * int * int) -> int
+
val sort_cmp_universes : env -> conv_pb -> Sorts.t -> Sorts.t ->
'a * 'a universe_compare -> 'a * 'a universe_compare
@@ -103,6 +105,12 @@ val beta_app : constr -> constr -> constr
(** Pseudo-reduction rule Prod(x,A,B) a --> B[x\a] *)
val hnf_prod_applist : env -> types -> constr list -> types
+(** In [hnf_prod_applist_assum n c args], [c] is supposed to (whd-)reduce to
+ the form [∀Γ.t] with [Γ] of length [n] and possibly with let-ins; it
+ returns [t] with the assumptions of [Γ] instantiated by [args] and
+ the local definitions of [Γ] expanded. *)
+val hnf_prod_applist_assum : env -> int -> types -> constr list -> types
+
(** Compatibility alias for Term.lambda_appvect_assum *)
val betazeta_appvect : int -> constr -> constr array -> constr
diff --git a/kernel/term.ml b/kernel/term.ml
index aa8805952..a4c92bd33 100644
--- a/kernel/term.ml
+++ b/kernel/term.ml
@@ -92,7 +92,7 @@ type ('constr, 'types, 'sort, 'univs) kind_of_term =
| CoFix of ('constr, 'types) pcofixpoint
| Proj of projection * 'constr
-type values = Constr.values
+type values = Vmvalues.values
(**********************************************************************)
(** Redeclaration of functions from module Constr *)
@@ -352,10 +352,11 @@ let lambda_applist_assum n c l =
let rec app n subst t l =
if Int.equal n 0 then
if l == [] then substl subst t
- else anomaly (Pp.str "Not enough arguments.")
+ else anomaly (Pp.str "Too many arguments.")
else match kind_of_term t, l with
| Lambda(_,_,c), arg::l -> app (n-1) (arg::subst) c l
| LetIn(_,b,_,c), _ -> app (n-1) (substl subst b::subst) c l
+ | _, [] -> anomaly (Pp.str "Not enough arguments.")
| _ -> anomaly (Pp.str "Not enough lambda/let's.") in
app n [] c l
@@ -377,10 +378,11 @@ let prod_applist_assum n c l =
let rec app n subst t l =
if Int.equal n 0 then
if l == [] then substl subst t
- else anomaly (Pp.str "Not enough arguments.")
+ else anomaly (Pp.str "Too many arguments.")
else match kind_of_term t, l with
| Prod(_,_,c), arg::l -> app (n-1) (arg::subst) c l
| LetIn(_,b,_,c), _ -> app (n-1) (substl subst b::subst) c l
+ | _, [] -> anomaly (Pp.str "Not enough arguments.")
| _ -> anomaly (Pp.str "Not enough prod/let's.") in
app n [] c l
diff --git a/kernel/term.mli b/kernel/term.mli
index f5cb72f4e..b4597676a 100644
--- a/kernel/term.mli
+++ b/kernel/term.mli
@@ -242,7 +242,7 @@ val lambda_applist : constr -> constr list -> constr
val lambda_appvect : constr -> constr array -> constr
(** In [lambda_applist_assum n c args], [c] is supposed to have the
- form [λΓ.c] with [Γ] of length [m] and possibly with let-ins; it
+ form [λΓ.c] with [Γ] of length [n] and possibly with let-ins; it
returns [c] with the assumptions of [Γ] instantiated by [args] and
the local definitions of [Γ] expanded. *)
val lambda_applist_assum : int -> constr -> constr list -> constr
@@ -251,15 +251,15 @@ val lambda_appvect_assum : int -> constr -> constr array -> constr
(** pseudo-reduction rule *)
(** [prod_appvect] [forall (x1:B1;...;xn:Bn), B] [a1...an] @return [B[a1...an]] *)
-val prod_appvect : constr -> constr array -> constr
-val prod_applist : constr -> constr list -> constr
+val prod_appvect : types -> constr array -> types
+val prod_applist : types -> constr list -> types
(** In [prod_appvect_assum n c args], [c] is supposed to have the
- form [∀Γ.c] with [Γ] of length [m] and possibly with let-ins; it
+ form [∀Γ.c] with [Γ] of length [n] and possibly with let-ins; it
returns [c] with the assumptions of [Γ] instantiated by [args] and
the local definitions of [Γ] expanded. *)
-val prod_appvect_assum : int -> constr -> constr array -> constr
-val prod_applist_assum : int -> constr -> constr list -> constr
+val prod_appvect_assum : int -> types -> constr array -> types
+val prod_applist_assum : int -> types -> constr list -> types
(** {5 Other term destructors. } *)
@@ -572,8 +572,8 @@ type ('constr, 'types, 'sort, 'univs) kind_of_term =
| Proj of projection * 'constr
[@@ocaml.deprecated "Alias for Constr.kind_of_term"]
-type values = Constr.values
-[@@ocaml.deprecated "Alias for Constr.values"]
+type values = Vmvalues.values
+[@@ocaml.deprecated "Alias for Vmvalues.values"]
val hash_constr : Constr.constr -> int
[@@ocaml.deprecated "Alias for Constr.hash"]
diff --git a/kernel/term_typing.ml b/kernel/term_typing.ml
index 2e4426d62..9b864440d 100644
--- a/kernel/term_typing.ml
+++ b/kernel/term_typing.ml
@@ -223,15 +223,15 @@ let rec unzip ctx j =
unzip ctx { j with uj_val = mkApp (mkLambda (n,ty,j.uj_val),arg) }
let feedback_completion_typecheck =
- let open Feedback in
Option.iter (fun state_id ->
- feedback ~id:state_id Feedback.Complete)
+ Feedback.feedback ~id:state_id Feedback.Complete)
let abstract_constant_universes = function
| Monomorphic_const_entry uctx ->
Univ.empty_level_subst, Monomorphic_const uctx
| Polymorphic_const_entry uctx ->
let sbst, auctx = Univ.abstract_universes uctx in
+ let sbst = Univ.make_instance_subst sbst in
sbst, Polymorphic_const auctx
let infer_declaration (type a) ~(trust : a trust) env (dcl : a constant_entry) =
@@ -300,21 +300,29 @@ let infer_declaration (type a) ~(trust : a trust) env (dcl : a constant_entry) =
let { const_entry_type = typ; const_entry_opaque = opaque } = c in
let { const_entry_body = body; const_entry_feedback = feedback_id } = c in
let (body, ctx), side_eff = Future.join body in
- let poly, univsctx = match c.const_entry_universes with
- | Monomorphic_const_entry univs -> false, univs
- | Polymorphic_const_entry univs -> true, Univ.ContextSet.of_context univs
- in
- let ctx = Univ.ContextSet.union univsctx ctx in
let body, ctx, _ = match trust with
| Pure -> body, ctx, []
| SideEffects _ -> inline_side_effects env body ctx side_eff
in
- let env = push_context_set ~strict:(not poly) ctx env in
- let ctx = if poly
- then Polymorphic_const_entry (Univ.ContextSet.to_context ctx)
- else Monomorphic_const_entry ctx
+ let env, usubst, univs = match c.const_entry_universes with
+ | Monomorphic_const_entry univs ->
+ let ctx = Univ.ContextSet.union univs ctx in
+ let env = push_context_set ~strict:true ctx env in
+ env, Univ.empty_level_subst, Monomorphic_const ctx
+ | Polymorphic_const_entry uctx ->
+ (** Ensure not to generate internal constraints in polymorphic mode.
+ The only way for this to happen would be that either the body
+ contained deferred universes, or that it contains monomorphic
+ side-effects. The first property is ruled out by upper layers,
+ and the second one is ensured by the fact we currently
+ unconditionally export side-effects from polymorphic definitions,
+ i.e. [trust] is always [Pure]. *)
+ let () = assert (Univ.ContextSet.is_empty ctx) in
+ let env = push_context ~strict:false uctx env in
+ let sbst, auctx = Univ.abstract_universes uctx in
+ let sbst = Univ.make_instance_subst sbst in
+ env, sbst, Polymorphic_const auctx
in
- let usubst, univs = abstract_constant_universes ctx in
let j = infer env body in
let typ = match typ with
| None ->
diff --git a/kernel/univ.ml b/kernel/univ.ml
index 8cf9028fb..fbb047364 100644
--- a/kernel/univ.ml
+++ b/kernel/univ.ml
@@ -266,7 +266,7 @@ struct
module Expr =
struct
type t = Level.t * int
-
+
(* Hashing of expressions *)
module ExprHash =
struct
@@ -487,7 +487,40 @@ struct
| [] -> cons a l
in
List.fold_right (fun a acc -> aux a acc) u []
-
+
+ (** [max_var_pred p u] returns the maximum variable level in [u] satisfying
+ [p], -1 if not found *)
+ let rec max_var_pred p u =
+ let open Level in
+ match u with
+ | [] -> -1
+ | (v, _) :: u ->
+ match var_index v with
+ | Some i when p i -> max i (max_var_pred p u)
+ | _ -> max_var_pred p u
+
+ let rec remap_var u i j =
+ let open Level in
+ match u with
+ | [] -> []
+ | (v, incr) :: u when var_index v = Some i ->
+ (Level.var j, incr) :: remap_var u i j
+ | _ :: u -> remap_var u i j
+
+ let rec compact u max_var i =
+ if i >= max_var then (u,[]) else
+ let j = max_var_pred (fun j -> j < i) u in
+ if Int.equal i (j+1) then
+ let (u,s) = compact u max_var (i+1) in
+ (u, i :: s)
+ else
+ let (u,s) = compact (remap_var u i j) max_var (i+1) in
+ (u, j+1 :: s)
+
+ let compact u =
+ let max_var = max_var_pred (fun _ -> true) u in
+ compact u max_var 0
+
(* Returns the formal universe that is greater than the universes u and v.
Used to type the products. *)
let sup x y = merge_univs x y
@@ -686,12 +719,6 @@ let enforce_leq u v c =
let enforce_leq_level u v c =
if Level.equal u v then c else Constraint.add (u,Le,v) c
-let enforce_univ_constraint (u,d,v) =
- match d with
- | Eq -> enforce_eq u v
- | Le -> enforce_leq u v
- | Lt -> enforce_leq (super u) v
-
(* Miscellaneous functions to remove or test local univ assumed to
occur in a universe *)
@@ -718,15 +745,48 @@ type universe_level_subst = universe_level universe_map
(** A full substitution might involve algebraic universes *)
type universe_subst = universe universe_map
-let level_subst_of f =
- fun l ->
- try let u = f l in
- match Universe.level u with
- | None -> l
- | Some l -> l
- with Not_found -> l
-
-module Instance : sig
+module Variance =
+struct
+ (** A universe position in the instance given to a cumulative
+ inductive can be the following. Note there is no Contravariant
+ case because [forall x : A, B <= forall x : A', B'] requires [A =
+ A'] as opposed to [A' <= A]. *)
+ type t = Irrelevant | Covariant | Invariant
+
+ let sup x y =
+ match x, y with
+ | Irrelevant, s | s, Irrelevant -> s
+ | Invariant, _ | _, Invariant -> Invariant
+ | Covariant, Covariant -> Covariant
+
+ let pr = function
+ | Irrelevant -> str "*"
+ | Covariant -> str "+"
+ | Invariant -> str "="
+
+ let leq_constraint csts variance u u' =
+ match variance with
+ | Irrelevant -> csts
+ | Covariant -> enforce_leq_level u u' csts
+ | Invariant -> enforce_eq_level u u' csts
+
+ let eq_constraint csts variance u u' =
+ match variance with
+ | Irrelevant -> csts
+ | Covariant | Invariant -> enforce_eq_level u u' csts
+
+ let leq_constraints variance u u' csts =
+ let len = Array.length u in
+ assert (len = Array.length u' && len = Array.length variance);
+ Array.fold_left3 leq_constraint csts variance u u'
+
+ let eq_constraints variance u u' csts =
+ let len = Array.length u in
+ assert (len = Array.length u' && len = Array.length variance);
+ Array.fold_left3 eq_constraint csts variance u u'
+end
+
+module Instance : sig
type t = Level.t array
val empty : t
@@ -746,7 +806,7 @@ module Instance : sig
val subst_fn : universe_level_subst_fn -> t -> t
- val pr : (Level.t -> Pp.t) -> t -> Pp.t
+ val pr : (Level.t -> Pp.t) -> ?variance:Variance.t array -> t -> Pp.t
val levels : t -> LSet.t
end =
struct
@@ -822,8 +882,12 @@ struct
let levels x = LSet.of_array x
- let pr =
- prvect_with_sep spc
+ let pr prl ?variance =
+ let ppu i u =
+ let v = Option.map (fun v -> v.(i)) variance in
+ pr_opt_no_spc Variance.pr v ++ prl u
+ in
+ prvecti_with_sep spc ppu
let equal t u =
t == u ||
@@ -887,9 +951,9 @@ struct
let empty = (Instance.empty, Constraint.empty)
let is_empty (univs, cst) = Instance.is_empty univs && Constraint.is_empty cst
- let pr prl (univs, cst as ctx) =
+ let pr prl ?variance (univs, cst as ctx) =
if is_empty ctx then mt() else
- h 0 (Instance.pr prl univs ++ str " |= ") ++ h 0 (v 0 (Constraint.pr prl cst))
+ h 0 (Instance.pr prl ?variance univs ++ str " |= ") ++ h 0 (v 0 (Constraint.pr prl cst))
let hcons (univs, cst) =
(Instance.hcons univs, hcons_constraints cst)
@@ -925,66 +989,42 @@ end
type abstract_universe_context = AUContext.t
let hcons_abstract_universe_context = AUContext.hcons
-(** Universe info for cumulative inductive types:
- A context of universe levels
- with universe constraints, representing local universe variables
- and constraints, together with a context of universe levels with
- universe constraints, representing conditions for subtyping used
- for inductive types.
+(** Universe info for cumulative inductive types: A context of
+ universe levels with universe constraints, representing local
+ universe variables and constraints, together with an array of
+ Variance.t.
- This data structure maintains the invariant that the context for
- subtyping constraints is exactly twice as big as the context for
- universe constraints. *)
+ This data structure maintains the invariant that the variance
+ array has the same length as the universe instance. *)
module CumulativityInfo =
struct
- type t = universe_context * universe_context
+ type t = universe_context * Variance.t array
let make x =
- if (Instance.length (UContext.instance (snd x))) =
- (Instance.length (UContext.instance (fst x))) * 2 then x
+ if (Instance.length (UContext.instance (fst x))) =
+ (Array.length (snd x)) then x
else anomaly (Pp.str "Invalid subtyping information encountered!")
- let empty = (UContext.empty, UContext.empty)
- let is_empty (univcst, subtypcst) = UContext.is_empty univcst && UContext.is_empty subtypcst
+ let empty = (UContext.empty, [||])
+ let is_empty (univs, variance) = UContext.is_empty univs && Array.is_empty variance
- let halve_context ctx =
- let len = Array.length (Instance.to_array ctx) in
- let halflen = len / 2 in
- (Instance.of_array (Array.sub (Instance.to_array ctx) 0 halflen),
- Instance.of_array (Array.sub (Instance.to_array ctx) halflen halflen))
+ let pr prl (univs, variance) =
+ UContext.pr prl ~variance univs
- let pr prl (univcst, subtypcst) =
- if UContext.is_empty univcst then mt() else
- let (ctx, ctx') = halve_context (UContext.instance subtypcst) in
- (UContext.pr prl univcst) ++ fnl () ++ fnl () ++
- h 0 (str "~@{" ++ Instance.pr prl ctx ++ str "} <= ~@{" ++ Instance.pr prl ctx' ++ str "} iff ")
- ++ fnl () ++ h 0 (v 0 (Constraint.pr prl (UContext.constraints subtypcst)))
+ let hcons (univs, variance) = (* should variance be hconsed? *)
+ (UContext.hcons univs, variance)
- let hcons (univcst, subtypcst) =
- (UContext.hcons univcst, UContext.hcons subtypcst)
-
- let univ_context (univcst, subtypcst) = univcst
- let subtyp_context (univcst, subtypcst) = subtypcst
-
- let create_trivial_subtyping ctx ctx' =
- CArray.fold_left_i
- (fun i cst l -> Constraint.add (l, Eq, Array.get ctx' i) cst)
- Constraint.empty (Instance.to_array ctx)
+ let univ_context (univs, subtypcst) = univs
+ let variance (univs, variance) = variance
(** This function takes a universe context representing constraints
- of an inductive and a Instance.t of fresh universe names for the
- subtyping (with the same length as the context in the given
- universe context) and produces a UInfoInd.t that with the
- trivial subtyping relation. *)
- let from_universe_context univcst freshunivs =
- let inst = (UContext.instance univcst) in
- assert (Instance.length freshunivs = Instance.length inst);
- (univcst, UContext.make (Instance.append inst freshunivs,
- create_trivial_subtyping inst freshunivs))
-
- let subtyping_susbst (univcst, subtypcst) =
- let (ctx, ctx') = (halve_context (UContext.instance subtypcst))in
- Array.fold_left2 (fun subst l1 l2 -> LMap.add l1 l2 subst) LMap.empty ctx ctx'
+ of an inductive and produces a CumulativityInfo.t with the
+ trivial subtyping relation. *)
+ let from_universe_context univs =
+ (univs, Array.init (UContext.size univs) (fun _ -> Variance.Invariant))
+
+ let leq_constraints (_,variance) u u' csts = Variance.leq_constraints variance u u' csts
+ let eq_constraints (_,variance) u u' csts = Variance.eq_constraints variance u u' csts
end
@@ -1128,24 +1168,6 @@ let subst_univs_universe fn ul =
List.fold_left (fun acc u -> Universe.merge_univs acc (Universe.tip u))
substs nosubst
-let subst_univs_level fn l =
- try Some (fn l)
- with Not_found -> None
-
-let subst_univs_constraint fn (u,d,v as c) cstrs =
- let u' = subst_univs_level fn u in
- let v' = subst_univs_level fn v in
- match u', v' with
- | None, None -> Constraint.add c cstrs
- | Some u, None -> enforce_univ_constraint (u,d,make v) cstrs
- | None, Some v -> enforce_univ_constraint (make u,d,v) cstrs
- | Some u, Some v -> enforce_univ_constraint (u,d,v) cstrs
-
-let subst_univs_constraints subst csts =
- Constraint.fold
- (fun c cstrs -> subst_univs_constraint subst c cstrs)
- csts Constraint.empty
-
let make_instance_subst i =
let arr = Instance.to_array i in
Array.fold_left_i (fun i acc l ->
@@ -1168,12 +1190,11 @@ let abstract_universes ctx =
(UContext.constraints ctx)
in
let ctx = UContext.make (instance, cstrs) in
- subst, ctx
+ instance, ctx
-let abstract_cumulativity_info (univcst, substcst) =
- let instance, univcst = abstract_universes univcst in
- let _, substcst = abstract_universes substcst in
- (instance, (univcst, substcst))
+let abstract_cumulativity_info (univs, variance) =
+ let subst, univs = abstract_universes univs in
+ subst, (univs, variance)
(** Pretty-printing *)
diff --git a/kernel/univ.mli b/kernel/univ.mli
index 459394439..c45ebe21c 100644
--- a/kernel/univ.mli
+++ b/kernel/univ.mli
@@ -125,6 +125,13 @@ sig
val for_all : (Level.t * int -> bool) -> t -> bool
val map : (Level.t * int -> 'a) -> t -> 'a list
+
+ (** [compact u] remaps local variables in [u] such that their indices become
+ consecutive. It returns the new universe and the mapping.
+ Example: compact [(Var 0, i); (Prop, 0); (Var 2; j))] =
+ [(Var 0,i); (Prop, 0); (Var 1; j)], [0; 2]
+ *)
+ val compact : t -> t * int list
end
type universe = Universe.t
@@ -238,7 +245,19 @@ type universe_level_subst_fn = Level.t -> Level.t
type universe_subst = Universe.t universe_map
type universe_level_subst = Level.t universe_map
-val level_subst_of : universe_subst_fn -> universe_level_subst_fn
+module Variance :
+sig
+ (** A universe position in the instance given to a cumulative
+ inductive can be the following. Note there is no Contravariant
+ case because [forall x : A, B <= forall x : A', B'] requires [A =
+ A'] as opposed to [A' <= A]. *)
+ type t = Irrelevant | Covariant | Invariant
+
+ val sup : t -> t -> t
+
+ val pr : t -> Pp.t
+
+end
(** {6 Universe instances} *)
@@ -275,7 +294,7 @@ sig
val subst_fn : universe_level_subst_fn -> t -> t
(** Substitution by a level-to-level function. *)
- val pr : (Level.t -> Pp.t) -> t -> Pp.t
+ val pr : (Level.t -> Pp.t) -> ?variance:Variance.t array -> t -> Pp.t
(** Pretty-printing, no comments *)
val levels : t -> LSet.t
@@ -349,36 +368,32 @@ end
type abstract_universe_context = AUContext.t
[@@ocaml.deprecated "Use AUContext.t"]
-(** Universe info for inductive types: A context of universe levels
- with universe Constraint.t, representing local universe variables
- and Constraint.t, together with a context of universe levels with
- universe Constraint.t, representing conditions for subtyping used
- for inductive types.
+(** Universe info for cumulative inductive types: A context of
+ universe levels with universe constraints, representing local
+ universe variables and constraints, together with an array of
+ Variance.t.
- This data structure maintains the invariant that the context for
- subtyping Constraint.t is exactly twice as big as the context for
- universe Constraint.t. *)
+ This data structure maintains the invariant that the variance
+ array has the same length as the universe instance. *)
module CumulativityInfo :
sig
type t
- val make : UContext.t * UContext.t -> t
+ val make : UContext.t * Variance.t array -> t
val empty : t
val is_empty : t -> bool
val univ_context : t -> UContext.t
- val subtyp_context : t -> UContext.t
+ val variance : t -> Variance.t array
- (** This function takes a universe context representing Constraint.t
- of an inductive and a Instance.t of fresh universe names for the
- subtyping (with the same length as the context in the given
- universe context) and produces a UInfoInd.t that with the
- trivial subtyping relation. *)
- val from_universe_context : UContext.t -> Instance.t -> t
-
- val subtyping_susbst : t -> universe_level_subst
+ (** This function takes a universe context representing constraints
+ of an inductive and produces a CumulativityInfo.t with the
+ trivial subtyping relation. *)
+ val from_universe_context : UContext.t -> t
+ val leq_constraints : t -> Instance.t constraint_function
+ val eq_constraints : t -> Instance.t constraint_function
end
type cumulativity_info = CumulativityInfo.t
@@ -389,7 +404,9 @@ sig
type t
val univ_context : t -> AUContext.t
- val subtyp_context : t -> AUContext.t
+ val variance : t -> Variance.t array
+ val leq_constraints : t -> Instance.t constraint_function
+ val eq_constraints : t -> Instance.t constraint_function
end
type abstract_cumulativity_info = ACumulativityInfo.t
@@ -461,18 +478,21 @@ val is_empty_subst : universe_subst -> bool
val make_subst : universe_subst -> universe_subst_fn
val subst_univs_universe : universe_subst_fn -> Universe.t -> Universe.t
-val subst_univs_constraints : universe_subst_fn -> Constraint.t -> Constraint.t
+(** Only user in the kernel is template polymorphism. Ideally we get rid of
+ this code if it goes away. *)
(** Substitution of instances *)
val subst_instance_instance : Instance.t -> Instance.t -> Instance.t
val subst_instance_universe : Instance.t -> Universe.t -> Universe.t
val make_instance_subst : Instance.t -> universe_level_subst
-val make_inverse_instance_subst : Instance.t -> universe_level_subst
+(** Creates [u(0) ↦ 0; ...; u(n-1) ↦ n - 1] out of [u(0); ...; u(n - 1)] *)
-val abstract_universes : UContext.t -> universe_level_subst * AUContext.t
+val make_inverse_instance_subst : Instance.t -> universe_level_subst
-val abstract_cumulativity_info : CumulativityInfo.t -> universe_level_subst * ACumulativityInfo.t
+val abstract_universes : UContext.t -> Instance.t * AUContext.t
+val abstract_cumulativity_info : CumulativityInfo.t -> Instance.t * ACumulativityInfo.t
+(** TODO: move universe abstraction out of the kernel *)
val make_abstract_instance : AUContext.t -> Instance.t
@@ -480,9 +500,11 @@ val make_abstract_instance : AUContext.t -> Instance.t
val pr_constraint_type : constraint_type -> Pp.t
val pr_constraints : (Level.t -> Pp.t) -> Constraint.t -> Pp.t
-val pr_universe_context : (Level.t -> Pp.t) -> UContext.t -> Pp.t
+val pr_universe_context : (Level.t -> Pp.t) -> ?variance:Variance.t array ->
+ UContext.t -> Pp.t
val pr_cumulativity_info : (Level.t -> Pp.t) -> CumulativityInfo.t -> Pp.t
-val pr_abstract_universe_context : (Level.t -> Pp.t) -> AUContext.t -> Pp.t
+val pr_abstract_universe_context : (Level.t -> Pp.t) -> ?variance:Variance.t array ->
+ AUContext.t -> Pp.t
val pr_abstract_cumulativity_info : (Level.t -> Pp.t) -> ACumulativityInfo.t -> Pp.t
val pr_universe_context_set : (Level.t -> Pp.t) -> ContextSet.t -> Pp.t
val explain_universe_inconsistency : (Level.t -> Pp.t) ->
diff --git a/kernel/vars.ml b/kernel/vars.ml
index eae917b5a..b3b3eff62 100644
--- a/kernel/vars.ml
+++ b/kernel/vars.ml
@@ -235,49 +235,6 @@ let subst_vars subst c = substn_vars 1 subst c
(** Universe substitutions *)
open Constr
-let subst_univs_fn_puniverses fn =
- let f = Univ.Instance.subst_fn fn in
- fun ((c, u) as x) -> let u' = f u in if u' == u then x else (c, u')
-
-let subst_univs_fn_constr f c =
- let changed = ref false in
- let fu = Univ.subst_univs_universe f in
- let fi = Univ.Instance.subst_fn (Univ.level_subst_of f) in
- let rec aux t =
- match kind t with
- | Sort (Sorts.Type u) ->
- let u' = fu u in
- if u' == u then t else
- (changed := true; mkSort (Sorts.sort_of_univ u'))
- | Const (c, u) ->
- let u' = fi u in
- if u' == u then t
- else (changed := true; mkConstU (c, u'))
- | Ind (i, u) ->
- let u' = fi u in
- if u' == u then t
- else (changed := true; mkIndU (i, u'))
- | Construct (c, u) ->
- let u' = fi u in
- if u' == u then t
- else (changed := true; mkConstructU (c, u'))
- | _ -> map aux t
- in
- let c' = aux c in
- if !changed then c' else c
-
-let subst_univs_constr subst c =
- if Univ.is_empty_subst subst then c
- else
- let f = Univ.make_subst subst in
- subst_univs_fn_constr f c
-
-let subst_univs_constr =
- if Flags.profile then
- let subst_univs_constr_key = CProfile.declare_profile "subst_univs_constr" in
- CProfile.profile2 subst_univs_constr_key subst_univs_constr
- else subst_univs_constr
-
let subst_univs_level_constr subst c =
if Univ.is_empty_level_subst subst then c
else
diff --git a/kernel/vars.mli b/kernel/vars.mli
index 964de4e95..b74d25260 100644
--- a/kernel/vars.mli
+++ b/kernel/vars.mli
@@ -129,12 +129,6 @@ val subst_var : Id.t -> constr -> constr
open Univ
-val subst_univs_fn_constr : universe_subst_fn -> constr -> constr
-val subst_univs_fn_puniverses : universe_level_subst_fn ->
- 'a puniverses -> 'a puniverses
-
-val subst_univs_constr : universe_subst -> constr -> constr
-
(** Level substitutions for polymorphism. *)
val subst_univs_level_constr : universe_level_subst -> constr -> constr
diff --git a/kernel/vconv.ml b/kernel/vconv.ml
index 3ef297b1f..8c7658147 100644
--- a/kernel/vconv.ml
+++ b/kernel/vconv.ml
@@ -3,6 +3,7 @@ open Names
open Environ
open Reduction
open Vm
+open Vmvalues
open Csymtable
let val_of_constr env c =
diff --git a/kernel/vconv.mli b/kernel/vconv.mli
index 7f727df47..c3c9636e8 100644
--- a/kernel/vconv.mli
+++ b/kernel/vconv.mli
@@ -19,4 +19,4 @@ val vm_conv : conv_pb -> types kernel_conversion_function
val vm_conv_gen : conv_pb -> (types, 'a) generic_conversion_function
(** Precompute a VM value from a constr *)
-val val_of_constr : env -> constr -> values
+val val_of_constr : env -> constr -> Vmvalues.values
diff --git a/kernel/vm.ml b/kernel/vm.ml
index 51101f88e..352ea74a4 100644
--- a/kernel/vm.ml
+++ b/kernel/vm.ml
@@ -6,47 +6,13 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-open Names
-open Sorts
-open Constr
open Cbytecodes
+open Vmvalues
external set_drawinstr : unit -> unit = "coq_set_drawinstr"
-(******************************************)
-(* Utility Functions about Obj ************)
-(******************************************)
-
-external offset_closure : Obj.t -> int -> Obj.t = "coq_offset_closure"
-external offset : Obj.t -> int = "coq_offset"
-
-(*******************************************)
-(* Initalization of the abstract machine ***)
-(*******************************************)
-
-external init_vm : unit -> unit = "init_coq_vm"
-
-let _ = init_vm ()
-
-(*******************************************)
-(* Machine code *** ************************)
-(*******************************************)
-
-type tcode
-let tcode_of_obj v = ((Obj.obj v):tcode)
-let fun_code v = tcode_of_obj (Obj.field (Obj.repr v) 0)
-
-external mkAccuCode : int -> tcode = "coq_makeaccu"
external mkPopStopCode : int -> tcode = "coq_pushpop"
-external offset_tcode : tcode -> int -> tcode = "coq_offset_tcode"
-external int_tcode : tcode -> int -> int = "coq_int_tcode"
-
-external accumulate : unit -> tcode = "accumulate_code"
-let accumulate = accumulate ()
-
-external is_accumulate : tcode -> bool = "coq_is_accumulate_code"
-
let popstop_tbl = ref (Array.init 30 mkPopStopCode)
let popstop_code i =
@@ -62,106 +28,6 @@ let popstop_code i =
let stop = popstop_code 0
-(******************************************************)
-(* Abstract data types and utility functions **********)
-(******************************************************)
-
-(* Values of the abstract machine *)
-let val_of_obj v = ((Obj.obj v):values)
-let crazy_val = (val_of_obj (Obj.repr 0))
-
-(* Abstract data *)
-type vprod
-type vfun
-type vfix
-type vcofix
-type vblock
-type arguments
-
-type vm_env
-type vstack = values array
-
-type vswitch = {
- sw_type_code : tcode;
- sw_code : tcode;
- sw_annot : annot_switch;
- sw_stk : vstack;
- sw_env : vm_env
- }
-
-(* Representation of values *)
-(* + Products : *)
-(* - vprod = 0_[ dom | codom] *)
-(* dom : values, codom : vfun *)
-(* *)
-(* + Functions have two representations : *)
-(* - unapplied fun : vf = Ct_[ C | fv1 | ... | fvn] *)
-(* C:tcode, fvi : values *)
-(* Remark : a function and its environment is the same value. *)
-(* - partially applied fun : Ct_[Restart:C| vf | arg1 | ... argn] *)
-(* *)
-(* + Fixpoints : *)
-(* - Ct_[C1|Infix_t|C2|...|Infix_t|Cn|fv1|...|fvn] *)
-(* One single block to represent all of the fixpoints, each fixpoint *)
-(* is the pointer to the field holding the pointer to its code, and *)
-(* the infix tag is used to know where the block starts. *)
-(* - Partial application follows the scheme of partially applied *)
-(* functions. Note: only fixpoints not having been applied to its *)
-(* recursive argument are coded this way. When the rec. arg. is *)
-(* applied, either it's a constructor and the fix reduces, or it's *)
-(* and the fix is coded as an accumulator. *)
-(* *)
-(* + Cofixpoints : see cbytegen.ml *)
-(* *)
-(* + vblock's encode (non constant) constructors as in Ocaml, but *)
-(* starting from 0 up. tag 0 ( = accu_tag) is reserved for *)
-(* accumulators. *)
-(* *)
-(* + vm_env is the type of the machine environments (i.e. a function or *)
-(* a fixpoint) *)
-(* *)
-(* + Accumulators : At_[accumulate| accu | arg1 | ... | argn ] *)
-(* - representation of [accu] : tag_[....] *)
-(* -- tag <= 3 : encoding atom type (sorts, free vars, etc.) *)
-(* -- 10_[accu|proj name] : a projection blocked by an accu *)
-(* -- 11_[accu|fix_app] : a fixpoint blocked by an accu *)
-(* -- 12_[accu|vswitch] : a match blocked by an accu *)
-(* -- 13_[fcofix] : a cofix function *)
-(* -- 14_[fcofix|val] : a cofix function, val represent the value *)
-(* of the function applied to arg1 ... argn *)
-(* The [arguments] type, which is abstracted as an array, represents : *)
-(* tag[ _ | _ |v1|... | vn] *)
-(* Generally the first field is a code pointer. *)
-
-(* Do not edit this type without editing C code, especially "coq_values.h" *)
-
-type atom =
- | Aid of Vars.id_key
- | Aind of inductive
- | Atype of Univ.Universe.t
-
-(* Zippers *)
-
-type zipper =
- | Zapp of arguments
- | Zfix of vfix*arguments (* Possibly empty *)
- | Zswitch of vswitch
- | Zproj of Constant.t (* name of the projection *)
-
-type stack = zipper list
-
-type to_up = values
-
-type whd =
- | Vsort of Sorts.t
- | Vprod of vprod
- | Vfun of vfun
- | Vfix of vfix * arguments option
- | Vcofix of vcofix * to_up * arguments option
- | Vconstr_const of int
- | Vconstr_block of vblock
- | Vatom_stk of atom * stack
- | Vuniv_level of Univ.Level.t
(************************************************)
(* Abstract machine *****************************)
@@ -178,389 +44,72 @@ external push_vstack : vstack -> int -> unit = "coq_push_vstack"
external interprete : tcode -> values -> vm_env -> int -> values =
"coq_interprete_ml"
-
-
(* Functions over arguments *)
-let nargs : arguments -> int = fun args -> (Obj.size (Obj.repr args)) - 2
-let arg args i =
- if 0 <= i && i < (nargs args) then
- val_of_obj (Obj.field (Obj.repr args) (i+2))
- else invalid_arg
- ("Vm.arg size = "^(string_of_int (nargs args))^
- " acces "^(string_of_int i))
(* Apply a value to arguments contained in [vargs] *)
let apply_arguments vf vargs =
let n = nargs vargs in
- if Int.equal n 0 then vf
+ if Int.equal n 0 then fun_val vf
else
begin
push_ra stop;
push_arguments vargs;
- interprete (fun_code vf) vf (Obj.magic vf) (n - 1)
+ interprete (fun_code vf) (fun_val vf) (fun_env vf) (n - 1)
end
(* Apply value [vf] to an array of argument values [varray] *)
let apply_varray vf varray =
let n = Array.length varray in
- if Int.equal n 0 then vf
+ if Int.equal n 0 then fun_val vf
else
begin
push_ra stop;
(* The fun code of [vf] will make sure we have enough stack, so we put 0
here. *)
push_vstack varray 0;
- interprete (fun_code vf) vf (Obj.magic vf) (n - 1)
+ interprete (fun_code vf) (fun_val vf) (fun_env vf) (n - 1)
end
-(*************************************************)
-(* Destructors ***********************************)
-(*************************************************)
-
-let uni_lvl_val (v : values) : Univ.Level.t =
- let whd = Obj.magic v in
- match whd with
- | Vuniv_level lvl -> lvl
- | _ ->
- let pr =
- let open Pp in
- match whd with
- | Vsort _ -> str "Vsort"
- | Vprod _ -> str "Vprod"
- | Vfun _ -> str "Vfun"
- | Vfix _ -> str "Vfix"
- | Vcofix _ -> str "Vcofix"
- | Vconstr_const i -> str "Vconstr_const"
- | Vconstr_block b -> str "Vconstr_block"
- | Vatom_stk (a,stk) -> str "Vatom_stk"
- | _ -> assert false
- in
- CErrors.anomaly
- Pp.( strbrk "Parsing virtual machine value expected universe level, got "
- ++ pr ++ str ".")
-
-let rec whd_accu a stk =
- let stk =
- if Int.equal (Obj.size a) 2 then stk
- else Zapp (Obj.obj a) :: stk in
- let at = Obj.field a 1 in
- match Obj.tag at with
- | i when Int.equal i type_atom_tag ->
- begin match stk with
- | [Zapp args] ->
- let u = ref (Obj.obj (Obj.field at 0)) in
- for i = 0 to nargs args - 1 do
- u := Univ.Universe.sup !u (Univ.Universe.make (uni_lvl_val (arg args i)))
- done;
- Vsort (Type !u)
- | _ -> assert false
- end
- | i when i <= max_atom_tag ->
- Vatom_stk(Obj.magic at, stk)
- | i when Int.equal i proj_tag ->
- let zproj = Zproj (Obj.obj (Obj.field at 0)) in
- whd_accu (Obj.field at 1) (zproj :: stk)
- | i when Int.equal i fix_app_tag ->
- let fa = Obj.field at 1 in
- let zfix =
- Zfix (Obj.obj (Obj.field fa 1), Obj.obj fa) in
- whd_accu (Obj.field at 0) (zfix :: stk)
- | i when Int.equal i switch_tag ->
- let zswitch = Zswitch (Obj.obj (Obj.field at 1)) in
- whd_accu (Obj.field at 0) (zswitch :: stk)
- | i when Int.equal i cofix_tag ->
- let vcfx = Obj.obj (Obj.field at 0) in
- let to_up = Obj.obj a in
- begin match stk with
- | [] -> Vcofix(vcfx, to_up, None)
- | [Zapp args] -> Vcofix(vcfx, to_up, Some args)
- | _ -> assert false
- end
- | i when Int.equal i cofix_evaluated_tag ->
- let vcofix = Obj.obj (Obj.field at 0) in
- let res = Obj.obj a in
- begin match stk with
- | [] -> Vcofix(vcofix, res, None)
- | [Zapp args] -> Vcofix(vcofix, res, Some args)
- | _ -> assert false
- end
- | tg ->
- CErrors.anomaly
- Pp.(strbrk "Failed to parse VM value. Tag = " ++ int tg ++ str ".")
-
-external kind_of_closure : Obj.t -> int = "coq_kind_of_closure"
-
-let whd_val : values -> whd =
- fun v ->
- let o = Obj.repr v in
- if Obj.is_int o then Vconstr_const (Obj.obj o)
- else
- let tag = Obj.tag o in
- if tag = accu_tag then
- (
- if Int.equal (Obj.size o) 1 then Obj.obj o (* sort *)
- else
- if is_accumulate (fun_code o) then whd_accu o []
- else Vprod(Obj.obj o))
- else
- if tag = Obj.closure_tag || tag = Obj.infix_tag then
- (match kind_of_closure o with
- | 0 -> Vfun(Obj.obj o)
- | 1 -> Vfix(Obj.obj o, None)
- | 2 -> Vfix(Obj.obj (Obj.field o 1), Some (Obj.obj o))
- | 3 -> Vatom_stk(Aid(RelKey(int_tcode (fun_code o) 1)), [])
- | _ -> CErrors.anomaly ~label:"Vm.whd " (Pp.str "kind_of_closure does not work."))
- else
- Vconstr_block(Obj.obj o)
-
-(**********************************************)
-(* Constructors *******************************)
-(**********************************************)
-
-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);
- Obj.set_field res 1 (Obj.repr a);
- res
-
-(* obj_of_str_const : structured_constant -> Obj.t *)
-let rec obj_of_str_const str =
- match str with
- | Const_sorts s -> Obj.repr (Vsort s)
- | Const_ind ind -> obj_of_atom (Aind ind)
- | Const_proj p -> Obj.repr p
- | Const_b0 tag -> Obj.repr tag
- | Const_bn(tag, args) ->
- let len = Array.length args in
- let res = Obj.new_block tag len in
- for i = 0 to len - 1 do
- Obj.set_field res i (obj_of_str_const args.(i))
- done;
- res
- | Const_univ_level l -> Obj.repr (Vuniv_level l)
- | Const_type u -> obj_of_atom (Atype u)
-
-let val_of_obj o = ((Obj.obj o) : values)
-
-let val_of_str_const str = val_of_obj (obj_of_str_const str)
-
-let val_of_atom a = val_of_obj (obj_of_atom a)
-
-let atom_of_proj kn v =
- let r = Obj.new_block proj_tag 2 in
- Obj.set_field r 0 (Obj.repr kn);
- Obj.set_field r 1 (Obj.repr v);
- ((Obj.obj r) : atom)
-
-let val_of_proj kn v =
- val_of_atom (atom_of_proj kn v)
-
-module IdKeyHash =
-struct
- type t = Constant.t tableKey
- let equal = Names.eq_table_key Constant.equal
- open Hashset.Combine
- let hash = function
- | ConstKey c -> combinesmall 1 (Constant.hash c)
- | VarKey id -> combinesmall 2 (Id.hash id)
- | RelKey i -> combinesmall 3 (Int.hash i)
-end
-
-module KeyTable = Hashtbl.Make(IdKeyHash)
-
-let idkey_tbl = KeyTable.create 31
-
-let val_of_idkey key =
- try KeyTable.find idkey_tbl key
- with Not_found ->
- let v = val_of_atom (Aid key) in
- KeyTable.add idkey_tbl key v;
- v
-
-let val_of_rel k = val_of_idkey (RelKey k)
-
-let val_of_named id = val_of_idkey (VarKey id)
-
-let val_of_constant c = val_of_idkey (ConstKey c)
-
-external val_of_annot_switch : annot_switch -> values = "%identity"
-
+(* Functions over vfun *)
let mkrel_vstack k arity =
let max = k + arity - 1 in
Array.init arity (fun i -> val_of_rel (max - i))
-
-(*************************************************)
-(** Operations manipulating data types ***********)
-(*************************************************)
-
-(* Functions over products *)
-
-let dom : vprod -> values = fun p -> val_of_obj (Obj.field (Obj.repr p) 0)
-let codom : vprod -> vfun = fun p -> (Obj.obj (Obj.field (Obj.repr p) 1))
-
-(* Functions over vfun *)
-
-external closure_arity : vfun -> int = "coq_closure_arity"
-
-let body_of_vfun k vf =
+let reduce_fun k vf =
let vargs = mkrel_vstack k 1 in
- apply_varray (Obj.magic vf) vargs
+ apply_varray vf vargs
let decompose_vfun2 k vf1 vf2 =
let arity = min (closure_arity vf1) (closure_arity vf2) in
assert (0 < arity && arity < Sys.max_array_length);
let vargs = mkrel_vstack k arity in
- let v1 = apply_varray (Obj.magic vf1) vargs in
- let v2 = apply_varray (Obj.magic vf2) vargs in
+ let v1 = apply_varray vf1 vargs in
+ let v2 = apply_varray vf2 vargs in
arity, v1, v2
-(* Functions over fixpoint *)
-
-let first o = (offset_closure o (offset o))
-let last o = (Obj.field o (Obj.size o - 1))
-
-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_rec_arg fb i = int_tcode (unsafe_fb_code fb i) 1
-
-let rec_args vf =
- let fb = first (Obj.repr vf) in
- let size = Obj.size (last fb) in
- Array.init size (unsafe_rec_arg fb)
-
-exception FALSE
-
-let check_fix f1 f2 =
- let i1, i2 = current_fix f1, current_fix f2 in
- (* Checking starting point *)
- if i1 = i2 then
- let fb1,fb2 = first (Obj.repr f1), first (Obj.repr f2) in
- let n = Obj.size (last fb1) in
- (* Checking number of definitions *)
- if n = Obj.size (last fb2) then
- (* Checking recursive arguments *)
- try
- for i = 0 to n - 1 do
- if unsafe_rec_arg fb1 i <> unsafe_rec_arg fb2 i
- then raise FALSE
- done;
- true
- with FALSE -> false
- else false
- else false
-
(* Functions over vfix *)
-external atom_rel : unit -> atom array = "get_coq_atom_tbl"
-external realloc_atom_rel : int -> unit = "realloc_coq_atom_tbl"
-
-let relaccu_tbl =
- let atom_rel = atom_rel() in
- let len = Array.length atom_rel in
- for i = 0 to len - 1 do atom_rel.(i) <- Aid (RelKey i) done;
- ref (Array.init len mkAccuCode)
-
-let relaccu_code i =
- let len = Array.length !relaccu_tbl in
- if i < len then !relaccu_tbl.(i)
- else
- begin
- realloc_atom_rel i;
- let atom_rel = atom_rel () in
- let nl = Array.length atom_rel in
- for j = len to nl - 1 do atom_rel.(j) <- Aid(RelKey j) done;
- relaccu_tbl :=
- Array.init nl
- (fun j -> if j < len then !relaccu_tbl.(j) else mkAccuCode j);
- !relaccu_tbl.(i)
- end
let reduce_fix k vf =
- let fb = first (Obj.repr vf) in
+ let fb = first_fix vf in
(* computing types *)
- let fc_typ = ((Obj.obj (last fb)) : tcode array) in
+ let fc_typ = fix_types fb in
let ndef = Array.length fc_typ in
- let et = offset_closure fb (2*(ndef - 1)) in
+ let et = offset_closure_fix fb (2*(ndef - 1)) in
let ftyp =
Array.map
- (fun c -> interprete c crazy_val (Obj.magic et) 0) fc_typ in
+ (fun c -> interprete c crazy_val et 0) fc_typ in
(* Construction of the environment of fix bodies *)
- let e = Obj.dup fb in
- for i = 0 to ndef - 1 do
- Obj.set_field e (2 * i) (Obj.repr (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 res = Obj.new_block Obj.closure_tag 2 in
- Obj.set_field res 0 (Obj.repr c);
- Obj.set_field res 1 (offset_closure e (2*i));
- ((Obj.obj res) : vfun) in
- (Array.init ndef fix_body, ftyp)
-
-(* Functions over vcofix *)
-
-let get_fcofix vcf i =
- match whd_val (Obj.obj (Obj.field (Obj.repr vcf) (i+1))) with
- | Vcofix(vcfi, _, _) -> vcfi
- | _ -> assert false
-
-let current_cofix vcf =
- let ndef = Obj.size (last (Obj.repr vcf)) in
- let rec find_cofix pos =
- if pos < ndef then
- if get_fcofix vcf pos == vcf then pos
- else find_cofix (pos+1)
- else raise Not_found in
- try find_cofix 0
- with Not_found -> assert false
-
-let check_cofix vcf1 vcf2 =
- (current_cofix vcf1 = current_cofix vcf2) &&
- (Obj.size (last (Obj.repr vcf1)) = Obj.size (last (Obj.repr vcf2)))
+ (mk_fix_body k ndef fb, ftyp)
let reduce_cofix k vcf =
- let fc_typ = ((Obj.obj (last (Obj.repr vcf))) : tcode array) in
+ let fc_typ = cofix_types vcf in
let ndef = Array.length fc_typ in
let ftyp =
(* Evaluate types *)
- Array.map (fun c -> interprete c crazy_val (Obj.magic vcf) 0) fc_typ in
+ Array.map (fun c -> interprete c crazy_val (cofix_env vcf) 0) fc_typ in
(* Construction of the environment of cofix bodies *)
- let e = Obj.dup (Obj.repr vcf) in
- for i = 0 to ndef - 1 do
- Obj.set_field e (i+1) (Obj.repr (val_of_rel (k+i)))
- done;
-
- let cofix_body i =
- let vcfi = get_fcofix vcf i in
- let c = Obj.field (Obj.repr vcfi) 0 in
- 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);
- Obj.set_field self 1 (Obj.repr atom);
- apply_varray (Obj.obj e) [|Obj.obj self|] in
- (Array.init ndef cofix_body, ftyp)
-
-
-(* Functions over vblock *)
-
-let btag : vblock -> int = fun b -> Obj.tag (Obj.repr b)
-let bsize : vblock -> int = fun b -> Obj.size (Obj.repr b)
-let bfield b i =
- if 0 <= i && i < (bsize b) then val_of_obj (Obj.field (Obj.repr b) i)
- else invalid_arg "Vm.bfield"
-
-
-(* Functions over vswitch *)
-
-let check_switch sw1 sw2 = sw1.sw_annot.rtbl = sw2.sw_annot.rtbl
-
-let case_info sw = sw.sw_annot.ci
+ (mk_cofix_body apply_varray k ndef vcf, ftyp)
let type_of_switch sw =
(* The fun code of types will make sure we have enough stack, so we put 0
@@ -568,20 +117,6 @@ let type_of_switch sw =
push_vstack sw.sw_stk 0;
interprete sw.sw_type_code crazy_val sw.sw_env 0
-let branch_arg k (tag,arity) =
- if Int.equal arity 0 then ((Obj.magic tag):values)
- else
- let b, ofs =
- if tag < last_variant_tag then Obj.new_block tag arity, 0
- else
- let b = Obj.new_block last_variant_tag (arity+1) in
- Obj.set_field b 0 (Obj.repr (tag-last_variant_tag));
- b,1 in
- for i = ofs to ofs + arity - 1 do
- Obj.set_field b i (Obj.repr (val_of_rel (k+i)))
- done;
- val_of_obj b
-
let apply_switch sw arg =
let tc = sw.sw_annot.tailcall in
if tc then
@@ -603,8 +138,8 @@ let branch_of_switch k sw =
(* t = a stk --> t v *)
let rec apply_stack a stk v =
match stk with
- | [] -> apply_varray a [|v|]
- | Zapp args :: stk -> apply_stack (apply_arguments a args) stk v
+ | [] -> apply_varray (fun_of_val a) [|v|]
+ | Zapp args :: stk -> apply_stack (apply_arguments (fun_of_val a) args) stk v
| Zproj kn :: stk -> apply_stack (val_of_proj kn a) stk v
| Zfix(f,args) :: stk ->
let a,stk =
@@ -615,7 +150,7 @@ let rec apply_stack a stk v =
push_val a;
push_arguments args;
let a =
- interprete (fun_code f) (Obj.magic f) (Obj.magic f)
+ interprete (fix_code f) (fix_val f) (fix_env f)
(nargs args+ nargs args') in
a, stk
| _ ->
@@ -623,7 +158,7 @@ let rec apply_stack a stk v =
push_val a;
push_arguments args;
let a =
- interprete (fun_code f) (Obj.magic f) (Obj.magic f)
+ interprete (fix_code f) (fix_val f) (fix_env f)
(nargs args) in
a, stk in
apply_stack a stk v
@@ -634,50 +169,21 @@ let apply_whd k whd =
let v = val_of_rel k in
match whd with
| Vsort _ | Vprod _ | Vconstr_const _ | Vconstr_block _ -> assert false
- | Vfun f -> body_of_vfun k f
+ | Vfun f -> reduce_fun k f
| Vfix(f, None) ->
push_ra stop;
push_val v;
- interprete (fun_code f) (Obj.magic f) (Obj.magic f) 0
+ interprete (fix_code f) (fix_val f) (fix_env f) 0
| Vfix(f, Some args) ->
push_ra stop;
push_val v;
push_arguments args;
- interprete (fun_code f) (Obj.magic f) (Obj.magic f) (nargs args)
+ interprete (fix_code f) (fix_val f) (fix_env f) (nargs args)
| Vcofix(_,to_up,_) ->
push_ra stop;
push_val v;
- interprete (fun_code to_up) (Obj.magic to_up) (Obj.magic to_up) 0
+ interprete (cofix_upd_code to_up) (cofix_upd_val to_up) (cofix_upd_env to_up) 0
| Vatom_stk(a,stk) ->
apply_stack (val_of_atom a) stk v
| Vuniv_level lvl -> assert false
-let rec pr_atom a =
- Pp.(match a with
- | Aid c -> str "Aid(" ++ (match c with
- | ConstKey c -> Constant.print c
- | RelKey i -> str "#" ++ int i
- | _ -> str "...") ++ str ")"
- | Aind (mi,i) -> str "Aind(" ++ MutInd.print mi ++ str "#" ++ int i ++ str ")"
- | Atype _ -> str "Atype(")
-and pr_whd w =
- Pp.(match w with
- | Vsort _ -> str "Vsort"
- | Vprod _ -> str "Vprod"
- | Vfun _ -> str "Vfun"
- | Vfix _ -> str "Vfix"
- | Vcofix _ -> str "Vcofix"
- | Vconstr_const i -> str "Vconstr_const(" ++ int i ++ str ")"
- | Vconstr_block b -> str "Vconstr_block"
- | Vatom_stk (a,stk) -> str "Vatom_stk(" ++ pr_atom a ++ str ", " ++ pr_stack stk ++ str ")"
- | Vuniv_level _ -> assert false)
-and pr_stack stk =
- Pp.(match stk with
- | [] -> str "[]"
- | s :: stk -> pr_zipper s ++ str " :: " ++ pr_stack stk)
-and pr_zipper z =
- Pp.(match z with
- | Zapp args -> str "Zapp(len = " ++ int (nargs args) ++ str ")"
- | Zfix (f,args) -> str "Zfix(..., len=" ++ int (nargs args) ++ str ")"
- | Zswitch s -> str "Zswitch(...)"
- | Zproj c -> str "Zproj(" ++ Constant.print c ++ str ")")
diff --git a/kernel/vm.mli b/kernel/vm.mli
index bc38452d4..c6d92ba26 100644
--- a/kernel/vm.mli
+++ b/kernel/vm.mli
@@ -6,118 +6,28 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-open Names
-open Constr
-open Cbytecodes
+open Vmvalues
(** Debug printing *)
val set_drawinstr : unit -> unit
-(** Machine code *)
-
-type tcode
-
-(** Values *)
-
-type vprod
-type vfun
-type vfix
-type vcofix
-type vblock
-type vswitch
-type arguments
-
-type atom =
- | Aid of Vars.id_key
- | Aind of inductive
- | Atype of Univ.Universe.t
-
-(** Zippers *)
-
-type zipper =
- | Zapp of arguments
- | Zfix of vfix * arguments (** might be empty *)
- | Zswitch of vswitch
- | Zproj of Constant.t (* name of the projection *)
-
-type stack = zipper list
-
-type to_up
-
-type whd =
- | Vsort of Sorts.t
- | Vprod of vprod
- | Vfun of vfun
- | Vfix of vfix * arguments option
- | Vcofix of vcofix * to_up * arguments option
- | Vconstr_const of int
- | Vconstr_block of vblock
- | Vatom_stk of atom * stack
- | Vuniv_level of Univ.Level.t
-
-(** For debugging purposes only *)
-
-val pr_atom : atom -> Pp.t
-val pr_whd : whd -> Pp.t
-val pr_stack : stack -> Pp.t
-
-(** Constructors *)
-
-val val_of_str_const : structured_constant -> values
-val val_of_rel : int -> values
-val val_of_named : Id.t -> values
-val val_of_constant : Constant.t -> values
-
-external val_of_annot_switch : annot_switch -> values = "%identity"
-
-(** Destructors *)
-
-val whd_val : values -> whd
-val uni_lvl_val : values -> Univ.Level.t
-
-(** Arguments *)
-
-val nargs : arguments -> int
-val arg : arguments -> int -> values
-
-(** Product *)
-
-val dom : vprod -> values
-val codom : vprod -> vfun
-
-(** Function *)
-
-val body_of_vfun : int -> vfun -> values
-val decompose_vfun2 : int -> vfun -> vfun -> int * values * values
-
-(** Fix *)
-
-val current_fix : vfix -> int
-val check_fix : vfix -> vfix -> bool
-val rec_args : vfix -> int array
val reduce_fix : int -> vfix -> vfun array * values array
(** bodies , types *)
-(** CoFix *)
-
-val current_cofix : vcofix -> int
-val check_cofix : vcofix -> vcofix -> bool
val reduce_cofix : int -> vcofix -> values array * values array
(** bodies , types *)
-(** Block *)
+val type_of_switch : vswitch -> values
-val btag : vblock -> int
-val bsize : vblock -> int
-val bfield : vblock -> int -> values
+val branch_of_switch : int -> vswitch -> (int * values) array
-(** Switch *)
+val reduce_fun : int -> vfun -> values
-val check_switch : vswitch -> vswitch -> bool
-val case_info : vswitch -> case_info
-val type_of_switch : vswitch -> values
-val branch_of_switch : int -> vswitch -> (int * values) array
+(** [decompose_vfun2 k f1 f2] takes two functions [f1] and [f2] at current
+ DeBruijn level [k], with [n] lambdas in common, returns [n] and the reduced
+ bodies under those lambdas. *)
+val decompose_vfun2 : int -> vfun -> vfun -> int * values * values
(** Apply a value *)
diff --git a/kernel/vmvalues.ml b/kernel/vmvalues.ml
new file mode 100644
index 000000000..2d8a1d976
--- /dev/null
+++ b/kernel/vmvalues.ml
@@ -0,0 +1,526 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+open Names
+open Sorts
+open Cbytecodes
+open Univ
+
+(*******************************************)
+(* Initalization of the abstract machine ***)
+(* Necessary for [relaccu_tbl] *)
+(*******************************************)
+
+external init_vm : unit -> unit = "init_coq_vm"
+
+let _ = init_vm ()
+
+(******************************************************)
+(* Abstract data types and utility functions **********)
+(******************************************************)
+
+(* Values of the abstract machine *)
+type values
+let val_of_obj v = ((Obj.obj v):values)
+let crazy_val = (val_of_obj (Obj.repr 0))
+
+(* Abstract data *)
+type vprod
+type vfun
+type vfix
+type vcofix
+type vblock
+type arguments
+
+let fun_val v = (Obj.magic v : values)
+let fix_val v = (Obj.magic v : values)
+let cofix_upd_val v = (Obj.magic v : values)
+
+type vm_env
+let fun_env v = (Obj.magic v : vm_env)
+let fix_env v = (Obj.magic v : vm_env)
+let cofix_env v = (Obj.magic v : vm_env)
+let cofix_upd_env v = (Obj.magic v : vm_env)
+type vstack = values array
+
+let fun_of_val v = (Obj.magic v : vfun)
+
+(*******************************************)
+(* Machine code *** ************************)
+(*******************************************)
+
+type tcode
+
+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
+
+
+type vswitch = {
+ sw_type_code : tcode;
+ sw_code : tcode;
+ sw_annot : annot_switch;
+ sw_stk : vstack;
+ sw_env : vm_env
+ }
+
+(* Representation of values *)
+(* + Products : *)
+(* - vprod = 0_[ dom | codom] *)
+(* dom : values, codom : vfun *)
+(* *)
+(* + Functions have two representations : *)
+(* - unapplied fun : vf = Ct_[ C | fv1 | ... | fvn] *)
+(* C:tcode, fvi : values *)
+(* Remark : a function and its environment is the same value. *)
+(* - partially applied fun : Ct_[Restart:C| vf | arg1 | ... argn] *)
+(* *)
+(* + Fixpoints : *)
+(* - Ct_[C1|Infix_t|C2|...|Infix_t|Cn|fv1|...|fvn] *)
+(* One single block to represent all of the fixpoints, each fixpoint *)
+(* is the pointer to the field holding the pointer to its code, and *)
+(* the infix tag is used to know where the block starts. *)
+(* - Partial application follows the scheme of partially applied *)
+(* functions. Note: only fixpoints not having been applied to its *)
+(* recursive argument are coded this way. When the rec. arg. is *)
+(* applied, either it's a constructor and the fix reduces, or it's *)
+(* and the fix is coded as an accumulator. *)
+(* *)
+(* + Cofixpoints : see cbytegen.ml *)
+(* *)
+(* + vblock's encode (non constant) constructors as in Ocaml, but *)
+(* starting from 0 up. tag 0 ( = accu_tag) is reserved for *)
+(* accumulators. *)
+(* *)
+(* + vm_env is the type of the machine environments (i.e. a function or *)
+(* a fixpoint) *)
+(* *)
+(* + Accumulators : At_[accumulate| accu | arg1 | ... | argn ] *)
+(* - representation of [accu] : tag_[....] *)
+(* -- tag <= 3 : encoding atom type (sorts, free vars, etc.) *)
+(* -- 10_[accu|proj name] : a projection blocked by an accu *)
+(* -- 11_[accu|fix_app] : a fixpoint blocked by an accu *)
+(* -- 12_[accu|vswitch] : a match blocked by an accu *)
+(* -- 13_[fcofix] : a cofix function *)
+(* -- 14_[fcofix|val] : a cofix function, val represent the value *)
+(* of the function applied to arg1 ... argn *)
+(* The [arguments] type, which is abstracted as an array, represents : *)
+(* tag[ _ | _ |v1|... | vn] *)
+(* Generally the first field is a code pointer. *)
+
+(* Do not edit this type without editing C code, especially "coq_values.h" *)
+
+type atom =
+ | Aid of Vars.id_key
+ | Aind of inductive
+ | Atype of Univ.Universe.t
+
+(* Zippers *)
+
+type zipper =
+ | Zapp of arguments
+ | Zfix of vfix*arguments (* Possibly empty *)
+ | Zswitch of vswitch
+ | Zproj of Constant.t (* name of the projection *)
+
+type stack = zipper list
+
+type to_update = values
+
+type whd =
+ | Vsort of Sorts.t
+ | Vprod of vprod
+ | Vfun of vfun
+ | Vfix of vfix * arguments option
+ | Vcofix of vcofix * to_update * arguments option
+ | Vconstr_const of int
+ | Vconstr_block of vblock
+ | Vatom_stk of atom * stack
+ | Vuniv_level of Univ.Level.t
+
+(* Functions over arguments *)
+let nargs : arguments -> int = fun args -> (Obj.size (Obj.repr args)) - 2
+let arg args i =
+ if 0 <= i && i < (nargs args) then
+ val_of_obj (Obj.field (Obj.repr args) (i+2))
+ else invalid_arg
+ ("Vm.arg size = "^(string_of_int (nargs args))^
+ " acces "^(string_of_int i))
+
+(*************************************************)
+(* Destructors ***********************************)
+(*************************************************)
+
+let uni_lvl_val (v : values) : Univ.Level.t =
+ let whd = Obj.magic v in
+ match whd with
+ | Vuniv_level lvl -> lvl
+ | _ ->
+ let pr =
+ let open Pp in
+ match whd with
+ | Vsort _ -> str "Vsort"
+ | Vprod _ -> str "Vprod"
+ | Vfun _ -> str "Vfun"
+ | Vfix _ -> str "Vfix"
+ | Vcofix _ -> str "Vcofix"
+ | Vconstr_const i -> str "Vconstr_const"
+ | Vconstr_block b -> str "Vconstr_block"
+ | Vatom_stk (a,stk) -> str "Vatom_stk"
+ | _ -> assert false
+ in
+ CErrors.anomaly
+ Pp.( strbrk "Parsing virtual machine value expected universe level, got "
+ ++ pr ++ str ".")
+
+let rec whd_accu a stk =
+ let stk =
+ if Int.equal (Obj.size a) 2 then stk
+ else Zapp (Obj.obj a) :: stk in
+ let at = Obj.field a 1 in
+ match Obj.tag at with
+ | i when Int.equal i type_atom_tag ->
+ begin match stk with
+ | [Zapp args] ->
+ let args = Array.init (nargs args) (arg args) in
+ let u = Obj.obj (Obj.field at 0) in
+ let inst = Instance.of_array (Array.map uni_lvl_val args) in
+ let u = Univ.subst_instance_universe inst u in
+ Vsort (Type u)
+ | _ -> assert false
+ end
+ | i when i <= max_atom_tag ->
+ Vatom_stk(Obj.magic at, stk)
+ | i when Int.equal i proj_tag ->
+ let zproj = Zproj (Obj.obj (Obj.field at 0)) in
+ whd_accu (Obj.field at 1) (zproj :: stk)
+ | i when Int.equal i fix_app_tag ->
+ let fa = Obj.field at 1 in
+ let zfix =
+ Zfix (Obj.obj (Obj.field fa 1), Obj.obj fa) in
+ whd_accu (Obj.field at 0) (zfix :: stk)
+ | i when Int.equal i switch_tag ->
+ let zswitch = Zswitch (Obj.obj (Obj.field at 1)) in
+ whd_accu (Obj.field at 0) (zswitch :: stk)
+ | i when Int.equal i cofix_tag ->
+ let vcfx = Obj.obj (Obj.field at 0) in
+ let to_up = Obj.obj a in
+ begin match stk with
+ | [] -> Vcofix(vcfx, to_up, None)
+ | [Zapp args] -> Vcofix(vcfx, to_up, Some args)
+ | _ -> assert false
+ end
+ | i when Int.equal i cofix_evaluated_tag ->
+ let vcofix = Obj.obj (Obj.field at 0) in
+ let res = Obj.obj a in
+ begin match stk with
+ | [] -> Vcofix(vcofix, res, None)
+ | [Zapp args] -> Vcofix(vcofix, res, Some args)
+ | _ -> assert false
+ end
+ | tg ->
+ CErrors.anomaly
+ Pp.(strbrk "Failed to parse VM value. Tag = " ++ int tg ++ str ".")
+
+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"
+let accumulate = accumulate ()
+
+let whd_val : values -> whd =
+ fun v ->
+ let o = Obj.repr v in
+ if Obj.is_int o then Vconstr_const (Obj.obj o)
+ else
+ let tag = Obj.tag o in
+ if tag = accu_tag then
+ (
+ if Int.equal (Obj.size o) 1 then Obj.obj o (* sort *)
+ else
+ if is_accumulate (fun_code o) then whd_accu o []
+ else Vprod(Obj.obj o))
+ else
+ if tag = Obj.closure_tag || tag = Obj.infix_tag then
+ (match kind_of_closure o with
+ | 0 -> Vfun(Obj.obj o)
+ | 1 -> Vfix(Obj.obj o, None)
+ | 2 -> Vfix(Obj.obj (Obj.field o 1), Some (Obj.obj o))
+ | 3 -> Vatom_stk(Aid(RelKey(int_tcode (fun_code o) 1)), [])
+ | _ -> CErrors.anomaly ~label:"Vm.whd " (Pp.str "kind_of_closure does not work."))
+ else
+ Vconstr_block(Obj.obj o)
+
+(**********************************************)
+(* Constructors *******************************)
+(**********************************************)
+
+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);
+ Obj.set_field res 1 (Obj.repr a);
+ res
+
+(* obj_of_str_const : structured_constant -> Obj.t *)
+let rec obj_of_str_const str =
+ match str with
+ | Const_sorts s -> Obj.repr (Vsort s)
+ | Const_ind ind -> obj_of_atom (Aind ind)
+ | Const_proj p -> Obj.repr p
+ | Const_b0 tag -> Obj.repr tag
+ | Const_bn(tag, args) ->
+ let len = Array.length args in
+ let res = Obj.new_block tag len in
+ for i = 0 to len - 1 do
+ Obj.set_field res i (obj_of_str_const args.(i))
+ done;
+ res
+ | Const_univ_level l -> Obj.repr (Vuniv_level l)
+ | Const_type u -> obj_of_atom (Atype u)
+
+let val_of_obj o = ((Obj.obj o) : values)
+
+let val_of_str_const str = val_of_obj (obj_of_str_const str)
+
+let val_of_atom a = val_of_obj (obj_of_atom a)
+
+let atom_of_proj kn v =
+ let r = Obj.new_block proj_tag 2 in
+ Obj.set_field r 0 (Obj.repr kn);
+ Obj.set_field r 1 (Obj.repr v);
+ ((Obj.obj r) : atom)
+
+let val_of_proj kn v =
+ val_of_atom (atom_of_proj kn v)
+
+module IdKeyHash =
+struct
+ type t = Constant.t tableKey
+ let equal = Names.eq_table_key Constant.equal
+ open Hashset.Combine
+ let hash = function
+ | ConstKey c -> combinesmall 1 (Constant.hash c)
+ | VarKey id -> combinesmall 2 (Id.hash id)
+ | RelKey i -> combinesmall 3 (Int.hash i)
+end
+
+module KeyTable = Hashtbl.Make(IdKeyHash)
+
+let idkey_tbl = KeyTable.create 31
+
+let val_of_idkey key =
+ try KeyTable.find idkey_tbl key
+ with Not_found ->
+ let v = val_of_atom (Aid key) in
+ KeyTable.add idkey_tbl key v;
+ v
+
+let val_of_rel k = val_of_idkey (RelKey k)
+
+let val_of_named id = val_of_idkey (VarKey id)
+
+let val_of_constant c = val_of_idkey (ConstKey c)
+
+external val_of_annot_switch : annot_switch -> values = "%identity"
+
+(*************************************************)
+(** Operations manipulating data types ***********)
+(*************************************************)
+
+(* Functions over products *)
+
+let dom : vprod -> values = fun p -> val_of_obj (Obj.field (Obj.repr p) 0)
+let codom : vprod -> vfun = fun p -> (Obj.obj (Obj.field (Obj.repr p) 1))
+
+(* Functions over vfun *)
+
+external closure_arity : vfun -> int = "coq_closure_arity"
+
+(* Functions over fixpoint *)
+
+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"
+
+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 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_rec_arg fb i = int_tcode (unsafe_fb_code fb i) 1
+
+let rec_args vf =
+ let fb = first (Obj.repr vf) in
+ let size = Obj.size (last fb) in
+ Array.init size (unsafe_rec_arg fb)
+
+exception FALSE
+
+let check_fix f1 f2 =
+ let i1, i2 = current_fix f1, current_fix f2 in
+ (* Checking starting point *)
+ if i1 = i2 then
+ let fb1,fb2 = first (Obj.repr f1), first (Obj.repr f2) in
+ let n = Obj.size (last fb1) in
+ (* Checking number of definitions *)
+ if n = Obj.size (last fb2) then
+ (* Checking recursive arguments *)
+ try
+ for i = 0 to n - 1 do
+ if unsafe_rec_arg fb1 i <> unsafe_rec_arg fb2 i
+ then raise FALSE
+ done;
+ true
+ with FALSE -> false
+ else false
+ else false
+
+external atom_rel : unit -> atom array = "get_coq_atom_tbl"
+external realloc_atom_rel : int -> unit = "realloc_coq_atom_tbl"
+
+let relaccu_tbl =
+ let atom_rel = atom_rel() in
+ let len = Array.length atom_rel in
+ for i = 0 to len - 1 do atom_rel.(i) <- Aid (RelKey i) done;
+ ref (Array.init len mkAccuCode)
+
+let relaccu_code i =
+ let len = Array.length !relaccu_tbl in
+ if i < len then !relaccu_tbl.(i)
+ else
+ begin
+ realloc_atom_rel i;
+ let atom_rel = atom_rel () in
+ let nl = Array.length atom_rel in
+ for j = len to nl - 1 do atom_rel.(j) <- Aid(RelKey j) done;
+ relaccu_tbl :=
+ Array.init nl
+ (fun j -> if j < len then !relaccu_tbl.(j) else mkAccuCode j);
+ !relaccu_tbl.(i)
+ end
+
+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)))
+ 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 res = Obj.new_block Obj.closure_tag 2 in
+ Obj.set_field res 0 (Obj.repr c);
+ Obj.set_field res 1 (offset_closure e (2*i));
+ ((Obj.obj res) : vfun) in
+ Array.init ndef fix_body
+
+(* Functions over vcofix *)
+
+let get_fcofix vcf i =
+ match whd_val (Obj.obj (Obj.field (Obj.repr vcf) (i+1))) with
+ | Vcofix(vcfi, _, _) -> vcfi
+ | _ -> assert false
+
+let current_cofix vcf =
+ let ndef = Obj.size (last (Obj.repr vcf)) in
+ let rec find_cofix pos =
+ if pos < ndef then
+ if get_fcofix vcf pos == vcf then pos
+ else find_cofix (pos+1)
+ else raise Not_found in
+ try find_cofix 0
+ with Not_found -> assert false
+
+let check_cofix vcf1 vcf2 =
+ (current_cofix vcf1 = current_cofix vcf2) &&
+ (Obj.size (last (Obj.repr vcf1)) = Obj.size (last (Obj.repr vcf2)))
+
+let mk_cofix_body apply_varray k ndef vcf =
+ let e = Obj.dup (Obj.repr vcf) in
+ for i = 0 to ndef - 1 do
+ Obj.set_field e (i+1) (Obj.repr (val_of_rel (k+i)))
+ done;
+
+ let cofix_body i =
+ let vcfi = get_fcofix vcf i in
+ let c = Obj.field (Obj.repr vcfi) 0 in
+ 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);
+ Obj.set_field self 1 (Obj.repr atom);
+ apply_varray (Obj.obj e) [|Obj.obj self|] in
+ Array.init ndef cofix_body
+
+(* Functions over vblock *)
+
+let btag : vblock -> int = fun b -> Obj.tag (Obj.repr b)
+let bsize : vblock -> int = fun b -> Obj.size (Obj.repr b)
+let bfield b i =
+ if 0 <= i && i < (bsize b) then val_of_obj (Obj.field (Obj.repr b) i)
+ else invalid_arg "Vm.bfield"
+
+
+(* Functions over vswitch *)
+
+let check_switch sw1 sw2 = sw1.sw_annot.rtbl = sw2.sw_annot.rtbl
+
+let branch_arg k (tag,arity) =
+ if Int.equal arity 0 then ((Obj.magic tag):values)
+ else
+ let b, ofs =
+ if tag < last_variant_tag then Obj.new_block tag arity, 0
+ else
+ let b = Obj.new_block last_variant_tag (arity+1) in
+ Obj.set_field b 0 (Obj.repr (tag-last_variant_tag));
+ b,1 in
+ for i = ofs to ofs + arity - 1 do
+ Obj.set_field b i (Obj.repr (val_of_rel (k+i)))
+ done;
+ val_of_obj b
+
+(* Printing *)
+
+let rec pr_atom a =
+ Pp.(match a with
+ | Aid c -> str "Aid(" ++ (match c with
+ | ConstKey c -> Constant.print c
+ | RelKey i -> str "#" ++ int i
+ | _ -> str "...") ++ str ")"
+ | Aind (mi,i) -> str "Aind(" ++ MutInd.print mi ++ str "#" ++ int i ++ str ")"
+ | Atype _ -> str "Atype(")
+and pr_whd w =
+ Pp.(match w with
+ | Vsort _ -> str "Vsort"
+ | Vprod _ -> str "Vprod"
+ | Vfun _ -> str "Vfun"
+ | Vfix _ -> str "Vfix"
+ | Vcofix _ -> str "Vcofix"
+ | Vconstr_const i -> str "Vconstr_const(" ++ int i ++ str ")"
+ | Vconstr_block b -> str "Vconstr_block"
+ | Vatom_stk (a,stk) -> str "Vatom_stk(" ++ pr_atom a ++ str ", " ++ pr_stack stk ++ str ")"
+ | Vuniv_level _ -> assert false)
+and pr_stack stk =
+ Pp.(match stk with
+ | [] -> str "[]"
+ | s :: stk -> pr_zipper s ++ str " :: " ++ pr_stack stk)
+and pr_zipper z =
+ Pp.(match z with
+ | Zapp args -> str "Zapp(len = " ++ int (nargs args) ++ str ")"
+ | Zfix (f,args) -> str "Zfix(..., len=" ++ int (nargs args) ++ str ")"
+ | Zswitch s -> str "Zswitch(...)"
+ | Zproj c -> str "Zproj(" ++ Constant.print c ++ str ")")
diff --git a/kernel/vmvalues.mli b/kernel/vmvalues.mli
new file mode 100644
index 000000000..350f71372
--- /dev/null
+++ b/kernel/vmvalues.mli
@@ -0,0 +1,144 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+open Names
+open Cbytecodes
+
+(** Values *)
+
+type values
+type vm_env
+type vprod
+type vfun
+type vfix
+type vcofix
+type vblock
+type arguments
+type vstack = values array
+type to_update
+
+val fun_val : vfun -> values
+val fix_val : vfix -> values
+val cofix_upd_val : to_update -> values
+
+val fun_env : vfun -> vm_env
+val fix_env : vfix -> vm_env
+val cofix_env : vcofix -> vm_env
+val cofix_upd_env : to_update -> vm_env
+
+(** Cast a value known to be a function, unsafe in general *)
+val fun_of_val : values -> vfun
+
+val crazy_val : values
+
+(** Machine code *)
+
+type tcode
+
+type vswitch = {
+ sw_type_code : tcode;
+ sw_code : tcode;
+ sw_annot : annot_switch;
+ sw_stk : vstack;
+ sw_env : vm_env
+ }
+
+external mkAccuCode : int -> tcode = "coq_makeaccu"
+
+val fun_code : vfun -> tcode
+val fix_code : vfix -> tcode
+val cofix_upd_code : to_update -> tcode
+
+type atom =
+ | Aid of Vars.id_key
+ | Aind of inductive
+ | Atype of Univ.Universe.t
+
+(** Zippers *)
+
+type zipper =
+ | Zapp of arguments
+ | Zfix of vfix * arguments (** might be empty *)
+ | Zswitch of vswitch
+ | Zproj of Constant.t (* name of the projection *)
+
+type stack = zipper list
+
+type whd =
+ | Vsort of Sorts.t
+ | Vprod of vprod
+ | Vfun of vfun
+ | Vfix of vfix * arguments option
+ | Vcofix of vcofix * to_update * arguments option
+ | Vconstr_const of int
+ | Vconstr_block of vblock
+ | Vatom_stk of atom * stack
+ | Vuniv_level of Univ.Level.t
+
+(** For debugging purposes only *)
+
+val pr_atom : atom -> Pp.t
+val pr_whd : whd -> Pp.t
+val pr_stack : stack -> Pp.t
+
+(** Constructors *)
+
+val val_of_str_const : structured_constant -> values
+val val_of_rel : int -> values
+val val_of_named : Id.t -> values
+val val_of_constant : Constant.t -> values
+val val_of_proj : Constant.t -> values -> values
+val val_of_atom : atom -> values
+
+external val_of_annot_switch : annot_switch -> values = "%identity"
+
+(** Destructors *)
+
+val whd_val : values -> whd
+val uni_lvl_val : values -> Univ.Level.t
+
+(** Arguments *)
+
+val nargs : arguments -> int
+val arg : arguments -> int -> values
+
+(** Product *)
+
+val dom : vprod -> values
+val codom : vprod -> vfun
+
+(** Fun *)
+external closure_arity : vfun -> int = "coq_closure_arity"
+
+(** Fix *)
+
+val current_fix : vfix -> int
+val check_fix : vfix -> vfix -> bool
+val rec_args : vfix -> int array
+val first_fix : vfix -> vfix
+val fix_types : vfix -> tcode array
+val cofix_types : vcofix -> tcode array
+external offset_closure_fix : vfix -> int -> vm_env = "coq_offset_closure"
+val mk_fix_body : int -> int -> vfix -> vfun array
+
+(** CoFix *)
+
+val current_cofix : vcofix -> int
+val check_cofix : vcofix -> vcofix -> bool
+val mk_cofix_body : (vfun -> vstack -> values) -> int -> int -> vcofix -> values array
+
+(** Block *)
+
+val btag : vblock -> int
+val bsize : vblock -> int
+val bfield : vblock -> int -> values
+
+(** Switch *)
+
+val check_switch : vswitch -> vswitch -> bool
+val branch_arg : int -> Cbytecodes.tag * int -> values
diff --git a/lib/coqProject_file.ml4 b/lib/coqProject_file.ml4
index 1e52af0be..e6f1d7e06 100644
--- a/lib/coqProject_file.ml4
+++ b/lib/coqProject_file.ml4
@@ -114,7 +114,7 @@ let process_cmd_line orig_dir proj args =
let parsing_project_file = ref (proj.project_file <> None) in
let orig_dir = (* avoids turning foo.v in ./foo.v *)
if orig_dir = "." then "" else orig_dir in
- let error s = Feedback.msg_error (Pp.str (s^".")); exit 1 in
+ let error s = Format.eprintf "@[%a]@@\n%!" Pp.pp_with Pp.(str (s^".")); exit 1 in
let mk_path d =
let p = CUnix.correct_path d orig_dir in
{ path = CUnix.remove_path_dot (post_canonize p);
diff --git a/lib/feedback.mli b/lib/feedback.mli
index 62b909516..37f38c8ff 100644
--- a/lib/feedback.mli
+++ b/lib/feedback.mli
@@ -94,8 +94,9 @@ val msg_warning : ?loc:Loc.t -> Pp.t -> unit
consequences. *)
val msg_error : ?loc:Loc.t -> Pp.t -> unit
-(** Message indicating that something went really wrong, though still
- recoverable; otherwise an exception would have been raised. *)
+[@@ocaml.deprecated "msg_error is an internal function and should not be \
+ used unless you know what you are doing. Use \
+ [CErrors.user_err] instead."]
val msg_debug : ?loc:Loc.t -> Pp.t -> unit
(** For debugging purposes *)
diff --git a/lib/flags.ml b/lib/flags.ml
index ee4c0734a..01361dad5 100644
--- a/lib/flags.ml
+++ b/lib/flags.ml
@@ -6,18 +6,28 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-let with_modified_ref r nf f x =
+(* If [restore] is false, whenever [f] modifies the ref, we will
+ preserve the modification. *)
+let with_modified_ref ?(restore=true) r nf f x =
let old_ref = !r in r := nf !r;
- try let res = f x in r := old_ref; res
+ try
+ let pre = !r in
+ let res = f x in
+ (* If r was modified don't restore its old value *)
+ if restore || pre == !r then r := old_ref;
+ res
with reraise ->
let reraise = Backtrace.add_backtrace reraise in
r := old_ref;
Exninfo.iraise reraise
-let with_option o f x = with_modified_ref o (fun _ -> true) f x
-let without_option o f x = with_modified_ref o (fun _ -> false) f x
+let with_option o f x = with_modified_ref ~restore:false o (fun _ -> true) f x
+let without_option o f x = with_modified_ref ~restore:false o (fun _ -> false) f x
let with_extra_values o l f x = with_modified_ref o (fun ol -> ol@l) f x
+(* hide the [restore] option as internal *)
+let with_modified_ref r nf f x = with_modified_ref r nf f x
+
let with_options ol f x =
let vl = List.map (!) ol in
let () = List.iter (fun r -> r := true) ol in
diff --git a/library/globnames.ml b/library/globnames.ml
index 9d7ab2db8..a6e75fdb6 100644
--- a/library/globnames.ml
+++ b/library/globnames.ml
@@ -30,7 +30,7 @@ let eq_gr gr1 gr2 =
| IndRef kn1, IndRef kn2 -> eq_ind kn1 kn2
| ConstructRef kn1, ConstructRef kn2 -> eq_constructor kn1 kn2
| VarRef v1, VarRef v2 -> Id.equal v1 v2
- | _ -> false
+ | (ConstRef _ | IndRef _ | ConstructRef _ | VarRef _), _ -> false
let destVarRef = function VarRef ind -> ind | _ -> failwith "destVarRef"
let destConstRef = function ConstRef ind -> ind | _ -> failwith "destConstRef"
diff --git a/library/lib.ml b/library/lib.ml
index 499e2ae21..971089c17 100644
--- a/library/lib.ml
+++ b/library/lib.ml
@@ -417,8 +417,11 @@ let find_opening_node id =
type variable_info = Context.Named.Declaration.t * Decl_kinds.binding_kind
type variable_context = variable_info list
-type abstr_info = variable_context * Univ.universe_level_subst * Univ.AUContext.t
-
+type abstr_info = {
+ abstr_ctx : variable_context;
+ abstr_subst : Univ.Instance.t;
+ abstr_uctx : Univ.AUContext.t;
+}
type abstr_list = abstr_info Names.Cmap.t * abstr_info Names.Mindmap.t
type secentry =
@@ -483,8 +486,12 @@ let add_section_replacement f g poly hyps =
let inst = Univ.UContext.instance ctx in
let subst, ctx = Univ.abstract_universes ctx in
let args = instance_from_variable_context (List.rev sechyps) in
- sectab := (vars,f (inst,args) exps,
- g (sechyps,subst,ctx) abs)::sl
+ let info = {
+ abstr_ctx = sechyps;
+ abstr_subst = subst;
+ abstr_uctx = ctx;
+ } in
+ sectab := (vars,f (inst,args) exps, g info abs) :: sl
let add_section_kn poly kn =
let f x (l1,l2) = (l1,Names.Mindmap.add kn x l2) in
@@ -502,12 +509,21 @@ let section_segment_of_constant con =
let section_segment_of_mutual_inductive kn =
Names.Mindmap.find kn (snd (pi3 (List.hd !sectab)))
-let variable_section_segment_of_reference = function
- | ConstRef con -> pi1 (section_segment_of_constant con)
- | IndRef (kn,_) | ConstructRef ((kn,_),_) ->
- pi1 (section_segment_of_mutual_inductive kn)
- | _ -> []
-
+let empty_segment = {
+ abstr_ctx = [];
+ abstr_subst = Univ.Instance.empty;
+ abstr_uctx = Univ.AUContext.empty;
+}
+
+let section_segment_of_reference = function
+| ConstRef c -> section_segment_of_constant c
+| IndRef (kn,_) | ConstructRef ((kn,_),_) ->
+ section_segment_of_mutual_inductive kn
+| VarRef _ -> empty_segment
+
+let variable_section_segment_of_reference gr =
+ (section_segment_of_reference gr).abstr_ctx
+
let section_instance = function
| VarRef id ->
let eq = function
@@ -654,15 +670,10 @@ let discharge_con cst =
let discharge_inductive (kn,i) =
(discharge_kn kn,i)
-let discharge_abstract_universe_context (_, subst, abs_ctx) auctx =
+let discharge_abstract_universe_context { abstr_subst = subst; abstr_uctx = abs_ctx } auctx =
let open Univ in
- let len = LMap.cardinal subst in
- let rec gen_subst i acc =
- if i < 0 then acc
- else
- let acc = LMap.add (Level.var i) (Level.var (i + len)) acc in
- gen_subst (pred i) acc
- in
- let subst = gen_subst (AUContext.size auctx - 1) subst in
+ let ainst = make_abstract_instance auctx in
+ let subst = Instance.append subst ainst in
+ let subst = make_instance_subst subst in
let auctx = Univ.subst_univs_level_abstract_universe_context subst auctx in
subst, AUContext.union abs_ctx auctx
diff --git a/library/lib.mli b/library/lib.mli
index 721e2896f..cf75d5f8c 100644
--- a/library/lib.mli
+++ b/library/lib.mli
@@ -153,13 +153,22 @@ val init : unit -> unit
(** {6 Section management for discharge } *)
type variable_info = Context.Named.Declaration.t * Decl_kinds.binding_kind
type variable_context = variable_info list
-type abstr_info = variable_context * Univ.universe_level_subst * Univ.AUContext.t
+type abstr_info = private {
+ abstr_ctx : variable_context;
+ (** Section variables of this prefix *)
+ abstr_subst : Univ.Instance.t;
+ (** Actual names of the abstracted variables *)
+ abstr_uctx : Univ.AUContext.t;
+ (** Universe quantification, same length as the substitution *)
+}
val instance_from_variable_context : variable_context -> Names.Id.t array
val named_of_variable_context : variable_context -> Context.Named.t
val section_segment_of_constant : Names.Constant.t -> abstr_info
val section_segment_of_mutual_inductive: Names.MutInd.t -> abstr_info
+val section_segment_of_reference : Globnames.global_reference -> abstr_info
+
val variable_section_segment_of_reference : Globnames.global_reference -> variable_context
val section_instance : Globnames.global_reference -> Univ.Instance.t * Names.Id.t array
diff --git a/parsing/g_proofs.ml4 b/parsing/g_proofs.ml4
index d88f6fa0d..1c3ba7837 100644
--- a/parsing/g_proofs.ml4
+++ b/parsing/g_proofs.ml4
@@ -28,7 +28,8 @@ GEXTEND Gram
| ":"; l = LIST1 [id = IDENT -> id ] -> l ] ]
;
command:
- [ [ IDENT "Goal"; c = lconstr -> VernacGoal c
+ [ [ IDENT "Goal"; c = lconstr ->
+ VernacDefinition (Decl_kinds.(NoDischarge, Definition), ((Loc.tag ~loc:!@loc Names.Anonymous), None), ProveBody ([], c))
| IDENT "Proof" -> VernacProof (None,None)
| IDENT "Proof" ; IDENT "Mode" ; mn = string -> VernacProofMode mn
| IDENT "Proof"; c = lconstr -> VernacExactProof c
diff --git a/parsing/g_vernac.ml4 b/parsing/g_vernac.ml4
index 92e60f465..3244b0ff2 100644
--- a/parsing/g_vernac.ml4
+++ b/parsing/g_vernac.ml4
@@ -72,36 +72,36 @@ GEXTEND Gram
| IDENT "Redirect"; s = ne_string; c = located_vernac -> VernacRedirect (s, c)
| IDENT "Timeout"; n = natural; v = vernac_control -> VernacTimeout(n,v)
| IDENT "Fail"; v = vernac_control -> VernacFail v
- | v = vernac -> VernacExpr(v) ]
+ | (f, v) = vernac -> VernacExpr(f, v) ]
]
;
vernac:
- [ [ IDENT "Local"; v = vernac_poly -> VernacLocal (true, v)
- | IDENT "Global"; v = vernac_poly -> VernacLocal (false, v)
+ [ [ IDENT "Local"; (f, v) = vernac_poly -> (VernacLocal true :: f, v)
+ | IDENT "Global"; (f, v) = vernac_poly -> (VernacLocal false :: f, v)
| v = vernac_poly -> v ]
]
;
vernac_poly:
- [ [ IDENT "Polymorphic"; v = vernac_aux -> VernacPolymorphic (true, v)
- | IDENT "Monomorphic"; v = vernac_aux -> VernacPolymorphic (false, v)
+ [ [ IDENT "Polymorphic"; (f, v) = vernac_aux -> (VernacPolymorphic true :: f, v)
+ | IDENT "Monomorphic"; (f, v) = vernac_aux -> (VernacPolymorphic false :: f, v)
| v = vernac_aux -> v ]
]
;
vernac_aux:
(* Better to parse "." here: in case of failure (e.g. in coerce_to_var), *)
(* "." is still in the stream and discard_to_dot works correctly *)
- [ [ IDENT "Program"; g = gallina; "." -> VernacProgram g
- | IDENT "Program"; g = gallina_ext; "." -> VernacProgram g
- | g = gallina; "." -> g
- | g = gallina_ext; "." -> g
- | c = command; "." -> c
- | c = syntax; "." -> c
- | c = subprf -> c
+ [ [ IDENT "Program"; g = gallina; "." -> ([VernacProgram], g)
+ | IDENT "Program"; g = gallina_ext; "." -> ([VernacProgram], g)
+ | g = gallina; "." -> ([], g)
+ | g = gallina_ext; "." -> ([], g)
+ | c = command; "." -> ([], c)
+ | c = syntax; "." -> ([], c)
+ | c = subprf -> ([], c)
] ]
;
vernac_aux: LAST
- [ [ prfcom = command_entry -> prfcom ] ]
+ [ [ prfcom = command_entry -> ([], prfcom) ] ]
;
noedit_mode:
[ [ c = query_command -> c None] ]
@@ -133,6 +133,12 @@ let test_plural_form_types loc kwd = function
warn_plural_command ~loc:!@loc kwd
| _ -> ()
+let lname_of_lident : lident -> lname =
+ Loc.map (fun s -> Name s)
+
+let name_of_ident_decl : ident_decl -> name_decl =
+ on_fst lname_of_lident
+
(* Gallina declarations *)
GEXTEND Gram
GLOBAL: gallina gallina_ext thm_token def_body of_type_with_opt_coercion
@@ -143,17 +149,17 @@ GEXTEND Gram
[ [ thm = thm_token; id = ident_decl; bl = binders; ":"; c = lconstr;
l = LIST0
[ "with"; id = ident_decl; bl = binders; ":"; c = lconstr ->
- (Some id,(bl,c)) ] ->
- VernacStartTheoremProof (thm, (Some id,(bl,c))::l)
+ (id,(bl,c)) ] ->
+ VernacStartTheoremProof (thm, (id,(bl,c))::l)
| stre = assumption_token; nl = inline; bl = assum_list ->
VernacAssumption (stre, nl, bl)
| (kwd,stre) = assumptions_token; nl = inline; bl = assum_list ->
test_plural_form loc kwd bl;
VernacAssumption (stre, nl, bl)
| d = def_token; id = ident_decl; b = def_body ->
- VernacDefinition (d, id, b)
+ VernacDefinition (d, name_of_ident_decl id, b)
| IDENT "Let"; id = identref; b = def_body ->
- VernacDefinition ((DoDischarge, Let), (id, None), b)
+ VernacDefinition ((DoDischarge, Let), (lname_of_lident id, None), b)
(* Gallina inductive declarations *)
| cum = cumulativity_token; priv = private_token; f = finite_token;
indl = LIST1 inductive_definition SEP "with" ->
@@ -621,16 +627,14 @@ GEXTEND Gram
VernacCanonical (AN qid)
| IDENT "Canonical"; IDENT "Structure"; ntn = by_notation ->
VernacCanonical (ByNotation ntn)
- | IDENT "Canonical"; IDENT "Structure"; qid = global;
- d = def_body ->
+ | IDENT "Canonical"; IDENT "Structure"; qid = global; d = def_body ->
let s = coerce_reference_to_id qid in
- VernacLocal(false,
- VernacDefinition ((NoDischarge,CanonicalStructure),((Loc.tag s),None),d))
+ VernacDefinition ((NoDischarge,CanonicalStructure),((Loc.tag (Name s)),None),d)
(* Coercions *)
| IDENT "Coercion"; qid = global; d = def_body ->
let s = coerce_reference_to_id qid in
- VernacDefinition ((NoDischarge,Coercion),((Loc.tag s),None),d)
+ VernacDefinition ((NoDischarge,Coercion),((Loc.tag (Name s)),None),d)
| IDENT "Identity"; IDENT "Coercion"; f = identref; ":";
s = class_rawexpr; ">->"; t = class_rawexpr ->
VernacIdentityCoercion (f, s, t)
diff --git a/plugins/firstorder/formula.ml b/plugins/firstorder/formula.ml
index c55040df0..4c59996aa 100644
--- a/plugins/firstorder/formula.ml
+++ b/plugins/firstorder/formula.ml
@@ -55,7 +55,8 @@ let ind_hyps env sigma nevar ind largs =
let types= Inductiveops.arities_of_constructors env ind in
let myhyps t =
let t = EConstr.of_constr t in
- let t1=Termops.prod_applist sigma t largs in
+ let nparam_decls = Context.Rel.length (fst (Global.lookup_inductive (fst ind))).mind_params_ctxt in
+ let t1=Termops.prod_applist_assum sigma nparam_decls t largs in
let t2=snd (decompose_prod_n_assum sigma nevar t1) in
fst (decompose_prod_assum sigma t2) in
Array.map myhyps types
diff --git a/plugins/funind/functional_principles_proofs.ml b/plugins/funind/functional_principles_proofs.ml
index 62ca70626..d04887a48 100644
--- a/plugins/funind/functional_principles_proofs.ml
+++ b/plugins/funind/functional_principles_proofs.ml
@@ -324,7 +324,7 @@ let change_eq env sigma hyp_id (context:rel_context) x t end_of_type =
context
in
let new_type_of_hyp =
- Reductionops.nf_betaiota sigma new_type_of_hyp in
+ Reductionops.nf_betaiota env sigma new_type_of_hyp in
let new_ctxt,new_end_of_type =
decompose_prod_n_assum sigma ctxt_size new_type_of_hyp
in
@@ -698,6 +698,7 @@ let build_proof
: tactic =
let rec build_proof_aux do_finalize dyn_infos : tactic =
fun g ->
+ let env = pf_env g in
let sigma = project g in
(* observe (str "proving on " ++ Printer.pr_lconstr_env (pf_env g) term);*)
match EConstr.kind sigma dyn_infos.info with
@@ -794,7 +795,7 @@ let build_proof
do_finalize dyn_infos g
| Lambda _ ->
let new_term =
- Reductionops.nf_beta sigma dyn_infos.info in
+ Reductionops.nf_beta env sigma dyn_infos.info in
build_proof do_finalize {dyn_infos with info = new_term}
g
| LetIn _ ->
@@ -1153,7 +1154,7 @@ let prove_princ_for_struct (evd:Evd.evar_map ref) interactive_proof fun_num fnam
let bodies_with_all_params =
Array.map
(fun body ->
- Reductionops.nf_betaiota (project g)
+ Reductionops.nf_betaiota (pf_env g) (project g)
(applist(substl (List.rev (Array.to_list all_funs_with_full_params)) body,
List.rev_map var_of_decl princ_params))
)
@@ -1191,12 +1192,12 @@ let prove_princ_for_struct (evd:Evd.evar_map ref) interactive_proof fun_num fnam
let body_with_param,num =
let body = get_body fnames.(i) in
let body_with_full_params =
- Reductionops.nf_betaiota (project g) (
+ Reductionops.nf_betaiota (pf_env g) (project g) (
applist(body,List.rev_map var_of_decl full_params))
in
match EConstr.kind (project g) body_with_full_params with
| Fix((_,num),(_,_,bs)) ->
- Reductionops.nf_betaiota (project g)
+ Reductionops.nf_betaiota (pf_env g) (project g)
(
(applist
(substl
@@ -1279,7 +1280,7 @@ let prove_princ_for_struct (evd:Evd.evar_map ref) interactive_proof fun_num fnam
nb_rec_hyps = -100;
rec_hyps = [];
info =
- Reductionops.nf_betaiota (project g)
+ Reductionops.nf_betaiota (pf_env g) (project g)
(applist(fix_body,List.rev_map mkVar args_id));
eq_hyps = []
}
@@ -1339,7 +1340,7 @@ let prove_princ_for_struct (evd:Evd.evar_map ref) interactive_proof fun_num fnam
nb_rec_hyps = -100;
rec_hyps = [];
info =
- Reductionops.nf_betaiota Evd.empty
+ Reductionops.nf_betaiota (pf_env g) Evd.empty
(applist(fbody_with_full_params,
(List.rev_map var_of_decl princ_params)@
(List.rev_map mkVar args_id)
diff --git a/plugins/funind/functional_principles_types.mli b/plugins/funind/functional_principles_types.mli
index a3315f22c..ad396a2cb 100644
--- a/plugins/funind/functional_principles_types.mli
+++ b/plugins/funind/functional_principles_types.mli
@@ -29,10 +29,6 @@ val generate_functional_principle :
(EConstr.constr array -> int -> Tacmach.tactic) ->
unit
-val compute_new_princ_type_from_rel : constr array -> Sorts.t array ->
- types -> types
-
-
exception No_graph_found
val make_scheme : Evd.evar_map ref ->
diff --git a/plugins/funind/g_indfun.ml4 b/plugins/funind/g_indfun.ml4
index 2fd6f53c4..4b828a702 100644
--- a/plugins/funind/g_indfun.ml4
+++ b/plugins/funind/g_indfun.ml4
@@ -154,7 +154,7 @@ VERNAC COMMAND EXTEND Function
| _,((_,(_,CStructRec),_,_,_),_) -> false) recsl in
match
Vernac_classifier.classify_vernac
- (Vernacexpr.(VernacExpr(VernacFixpoint(Decl_kinds.NoDischarge, List.map snd recsl))))
+ (Vernacexpr.(VernacExpr([], VernacFixpoint(Decl_kinds.NoDischarge, List.map snd recsl))))
with
| Vernacexpr.VtSideff ids, _ when hard ->
Vernacexpr.(VtStartProof ("Classic", GuaranteesOpacity, ids), VtLater)
diff --git a/plugins/funind/glob_term_to_relation.ml b/plugins/funind/glob_term_to_relation.ml
index b4e17c5d1..f7639d22d 100644
--- a/plugins/funind/glob_term_to_relation.ml
+++ b/plugins/funind/glob_term_to_relation.ml
@@ -591,6 +591,7 @@ let rec build_entry_lc env funnames avoid rt : glob_constr build_entry_return =
*)
build_entry_lc env funnames avoid (mkGApp(b,args))
| GRec _ -> user_err Pp.(str "Not handled GRec")
+ | GProj _ -> user_err Pp.(str "Funind does not support primitive projections")
| GProd _ -> user_err Pp.(str "Cannot apply a type")
end (* end of the application treatement *)
@@ -697,6 +698,7 @@ let rec build_entry_lc env funnames avoid rt : glob_constr build_entry_return =
| GRec _ -> user_err Pp.(str "Not handled GRec")
| GCast(b,_) ->
build_entry_lc env funnames avoid b
+ | GProj(_,_) -> user_err Pp.(str "Funind does not support primitive projections")
and build_entry_lc_from_case env funname make_discr
(el:tomatch_tuples)
(brl:Glob_term.cases_clauses) avoid :
@@ -1245,7 +1247,7 @@ let rec compute_cst_params relnames params gt = DAst.with_val (function
discrimination ones *)
| GSort _ -> params
| GHole _ -> params
- | GIf _ | GRec _ | GCast _ ->
+ | GIf _ | GRec _ | GCast _ | GProj _ ->
raise (UserError(Some "compute_cst_params", str "Not handled case"))
) gt
and compute_cst_params_from_app acc (params,rtl) =
@@ -1509,7 +1511,7 @@ let do_build_inductive
in
let msg =
str "while trying to define"++ spc () ++
- Ppvernac.pr_vernac Vernacexpr.(VernacExpr(VernacInductive(GlobalNonCumulativity,false,Declarations.Finite,repacked_rel_inds)))
+ Ppvernac.pr_vernac Vernacexpr.(VernacExpr([], VernacInductive(GlobalNonCumulativity,false,Declarations.Finite,repacked_rel_inds)))
++ fnl () ++
msg
in
@@ -1524,7 +1526,7 @@ let do_build_inductive
in
let msg =
str "while trying to define"++ spc () ++
- Ppvernac.pr_vernac Vernacexpr.(VernacExpr(VernacInductive(GlobalNonCumulativity,false,Declarations.Finite,repacked_rel_inds)))
+ Ppvernac.pr_vernac Vernacexpr.(VernacExpr([], VernacInductive(GlobalNonCumulativity,false,Declarations.Finite,repacked_rel_inds)))
++ fnl () ++
CErrors.print reraise
in
diff --git a/plugins/funind/glob_termops.ml b/plugins/funind/glob_termops.ml
index 0666ab4f1..b4ca1073c 100644
--- a/plugins/funind/glob_termops.ml
+++ b/plugins/funind/glob_termops.ml
@@ -17,69 +17,12 @@ let mkGLambda(n,t,b) = DAst.make @@ GLambda(n,Explicit,t,b)
let mkGProd(n,t,b) = DAst.make @@ GProd(n,Explicit,t,b)
let mkGLetIn(n,b,t,c) = DAst.make @@ GLetIn(n,b,t,c)
let mkGCases(rto,l,brl) = DAst.make @@ GCases(Term.RegularStyle,rto,l,brl)
-let mkGSort s = DAst.make @@ GSort(s)
let mkGHole () = DAst.make @@ GHole(Evar_kinds.BinderType Anonymous,Misctypes.IntroAnonymous,None)
-let mkGCast(b,t) = DAst.make @@ GCast(b,CastConv t)
(*
Some basic functions to decompose glob_constrs
These are analogous to the ones constrs
*)
-let glob_decompose_prod =
- let rec glob_decompose_prod args c = match DAst.get c with
- | GProd(n,k,t,b) ->
- glob_decompose_prod ((n,t)::args) b
- | _ -> args,c
- in
- glob_decompose_prod []
-
-let glob_decompose_prod_or_letin =
- let rec glob_decompose_prod args rt = match DAst.get rt with
- | GProd(n,k,t,b) ->
- glob_decompose_prod ((n,None,Some t)::args) b
- | GLetIn(n,b,t,c) ->
- glob_decompose_prod ((n,Some b,t)::args) c
- | _ -> args,rt
- in
- glob_decompose_prod []
-
-let glob_compose_prod =
- List.fold_left (fun b (n,t) -> mkGProd(n,t,b))
-
-let glob_compose_prod_or_letin =
- List.fold_left (
- fun concl decl ->
- match decl with
- | (n,None,Some t) -> mkGProd(n,t,concl)
- | (n,Some bdy,t) -> mkGLetIn(n,bdy,t,concl)
- | _ -> assert false)
-
-let glob_decompose_prod_n n =
- let rec glob_decompose_prod i args c =
- if i<=0 then args,c
- else
- match DAst.get c with
- | GProd(n,_,t,b) ->
- glob_decompose_prod (i-1) ((n,t)::args) b
- | _ -> args,c
- in
- glob_decompose_prod n []
-
-
-let glob_decompose_prod_or_letin_n n =
- let rec glob_decompose_prod i args c =
- if i<=0 then args,c
- else
- match DAst.get c with
- | GProd(n,_,t,b) ->
- glob_decompose_prod (i-1) ((n,None,Some t)::args) b
- | GLetIn(n,b,t,c) ->
- glob_decompose_prod (i-1) ((n,Some b,t)::args) c
- | _ -> args,c
- in
- glob_decompose_prod n []
-
-
let glob_decompose_app =
let rec decompose_rapp acc rt =
(* msgnl (str "glob_decompose_app on : "++ Printer.pr_glob_constr rt); *)
@@ -101,18 +44,6 @@ let glob_make_eq ?(typ= mkGHole ()) t1 t2 =
let glob_make_neq t1 t2 =
mkGApp(mkGRef (Lazy.force Coqlib.coq_not_ref),[glob_make_eq t1 t2])
-(* [glob_make_or P1 P2] build the glob_constr corresponding to [P1 \/ P2] *)
-let glob_make_or t1 t2 = mkGApp (mkGRef(Lazy.force Coqlib.coq_or_ref),[t1;t2])
-
-(* [glob_make_or_list [P1;...;Pn]] build the glob_constr corresponding
- to [P1 \/ ( .... \/ Pn)]
-*)
-let rec glob_make_or_list = function
- | [] -> invalid_arg "mk_or"
- | [e] -> e
- | e::l -> glob_make_or e (glob_make_or_list l)
-
-
let remove_name_from_mapping mapping na =
match na with
| Anonymous -> mapping
@@ -178,6 +109,7 @@ let change_vars =
| GCast(b,c) ->
GCast(change_vars mapping b,
Miscops.map_cast_type (change_vars mapping) c)
+ | GProj(p,c) -> GProj(p, change_vars mapping c)
) rt
and change_vars_br mapping ((loc,(idl,patl,res)) as br) =
let new_mapping = List.fold_right Id.Map.remove idl mapping in
@@ -362,6 +294,7 @@ let rec alpha_rt excluded rt =
GApp(alpha_rt excluded f,
List.map (alpha_rt excluded) args
)
+ | GProj(p,c) -> GProj(p, alpha_rt excluded c)
in
new_rt
@@ -413,6 +346,7 @@ let is_free_in id =
| GHole _ -> false
| GCast (b,(CastConv t|CastVM t|CastNative t)) -> is_free_in b || is_free_in t
| GCast (b,CastCoerce) -> is_free_in b
+ | GProj (_,c) -> is_free_in c
) x
and is_free_in_br (_,(ids,_,rt)) =
(not (Id.List.mem id ids)) && is_free_in rt
@@ -506,6 +440,8 @@ let replace_var_by_term x_id term =
| GCast(b,c) ->
GCast(replace_var_by_pattern b,
Miscops.map_cast_type replace_var_by_pattern c)
+ | GProj(p,c) ->
+ GProj(p,replace_var_by_pattern c)
) x
and replace_var_by_pattern_br ((loc,(idl,patl,res)) as br) =
if List.exists (fun id -> Id.compare id x_id == 0) idl
@@ -575,97 +511,6 @@ let ids_of_pat =
in
ids_of_pat Id.Set.empty
-let id_of_name = function
- | Anonymous -> Id.of_string "x"
- | Name x -> x
-
-(* TODO: finish Rec caes *)
-let ids_of_glob_constr c =
- let rec ids_of_glob_constr acc c =
- let idof = id_of_name in
- match DAst.get c with
- | GVar id -> id::acc
- | GApp (g,args) ->
- ids_of_glob_constr [] g @ List.flatten (List.map (ids_of_glob_constr []) args) @ acc
- | GLambda (na,k,ty,c) -> idof na :: ids_of_glob_constr [] ty @ ids_of_glob_constr [] c @ acc
- | GProd (na,k,ty,c) -> idof na :: ids_of_glob_constr [] ty @ ids_of_glob_constr [] c @ acc
- | GLetIn (na,b,t,c) -> idof na :: ids_of_glob_constr [] b @ Option.cata (ids_of_glob_constr []) [] t @ ids_of_glob_constr [] c @ acc
- | GCast (c,(CastConv t|CastVM t|CastNative t)) -> ids_of_glob_constr [] c @ ids_of_glob_constr [] t @ acc
- | GCast (c,CastCoerce) -> ids_of_glob_constr [] c @ acc
- | GIf (c,(na,po),b1,b2) -> ids_of_glob_constr [] c @ ids_of_glob_constr [] b1 @ ids_of_glob_constr [] b2 @ acc
- | GLetTuple (nal,(na,po),b,c) ->
- List.map idof nal @ ids_of_glob_constr [] b @ ids_of_glob_constr [] c @ acc
- | GCases (sty,rtntypopt,tml,brchl) ->
- List.flatten (List.map (fun (_,(idl,patl,c)) -> idl @ ids_of_glob_constr [] c) brchl)
- | GRec _ -> failwith "Fix inside a constructor branch"
- | (GSort _ | GHole _ | GRef _ | GEvar _ | GPatVar _) -> []
- in
- (* build the set *)
- List.fold_left (fun acc x -> Id.Set.add x acc) Id.Set.empty (ids_of_glob_constr [] c)
-
-
-
-
-
-let zeta_normalize =
- let rec zeta_normalize_term x = DAst.map (function
- | GRef _
- | GVar _
- | GEvar _
- | GPatVar _ as rt -> rt
- | GApp(rt',rtl) ->
- GApp(zeta_normalize_term rt',
- List.map zeta_normalize_term rtl
- )
- | GLambda(name,k,t,b) ->
- GLambda(name,
- k,
- zeta_normalize_term t,
- zeta_normalize_term b
- )
- | GProd(name,k,t,b) ->
- GProd(name,
- k,
- zeta_normalize_term t,
- zeta_normalize_term b
- )
- | GLetIn(Name id,def,typ,b) ->
- DAst.get (zeta_normalize_term (replace_var_by_term id def b))
- | GLetIn(Anonymous,def,typ,b) ->
- DAst.get (zeta_normalize_term b)
- | GLetTuple(nal,(na,rto),def,b) ->
- GLetTuple(nal,
- (na,Option.map zeta_normalize_term rto),
- zeta_normalize_term def,
- zeta_normalize_term b
- )
- | GCases(sty,infos,el,brl) ->
- GCases(sty,
- infos,
- List.map (fun (e,x) -> (zeta_normalize_term e,x)) el,
- List.map zeta_normalize_br brl
- )
- | GIf(b,(na,e_option),lhs,rhs) ->
- GIf(zeta_normalize_term b,
- (na,Option.map zeta_normalize_term e_option),
- zeta_normalize_term lhs,
- zeta_normalize_term rhs
- )
- | GRec _ -> raise (UserError(None,str "Not handled GRec"))
- | GSort _
- | GHole _ as rt -> rt
- | GCast(b,c) ->
- GCast(zeta_normalize_term b,
- Miscops.map_cast_type zeta_normalize_term c)
- ) x
- and zeta_normalize_br (loc,(idl,patl,res)) =
- (loc,(idl,patl,zeta_normalize_term res))
- in
- zeta_normalize_term
-
-
-
-
let expand_as =
let rec add_as map rt =
@@ -700,6 +545,7 @@ let expand_as =
| GCases(sty,po,el,brl) ->
GCases(sty, Option.map (expand_as map) po, List.map (fun (rt,t) -> expand_as map rt,t) el,
List.map (expand_as_br map) brl)
+ | GProj(p,c) -> GProj(p, expand_as map c)
)
and expand_as_br map (loc,(idl,cpl,rt)) =
(loc,(idl,cpl, expand_as (List.fold_left add_as map cpl) rt))
diff --git a/plugins/funind/glob_termops.mli b/plugins/funind/glob_termops.mli
index 99a258de9..7088ae596 100644
--- a/plugins/funind/glob_termops.mli
+++ b/plugins/funind/glob_termops.mli
@@ -1,6 +1,5 @@
open Names
open Glob_term
-open Misctypes
(* [get_pattern_id pat] returns a list of all the variable appearing in [pat] *)
val get_pattern_id : cases_pattern -> Id.t list
@@ -21,22 +20,11 @@ val mkGLambda : Name.t * glob_constr * glob_constr -> glob_constr
val mkGProd : Name.t * glob_constr * glob_constr -> glob_constr
val mkGLetIn : Name.t * glob_constr * glob_constr option * glob_constr -> glob_constr
val mkGCases : glob_constr option * tomatch_tuples * cases_clauses -> glob_constr
-val mkGSort : glob_sort -> glob_constr
val mkGHole : unit -> glob_constr (* we only build Evd.BinderType Anonymous holes *)
-val mkGCast : glob_constr* glob_constr -> glob_constr
(*
Some basic functions to decompose glob_constrs
These are analogous to the ones constrs
*)
-val glob_decompose_prod : glob_constr -> (Name.t*glob_constr) list * glob_constr
-val glob_decompose_prod_or_letin :
- glob_constr -> (Name.t*glob_constr option*glob_constr option) list * glob_constr
-val glob_decompose_prod_n : int -> glob_constr -> (Name.t*glob_constr) list * glob_constr
-val glob_decompose_prod_or_letin_n : int -> glob_constr ->
- (Name.t*glob_constr option*glob_constr option) list * glob_constr
-val glob_compose_prod : glob_constr -> (Name.t*glob_constr) list -> glob_constr
-val glob_compose_prod_or_letin: glob_constr ->
- (Name.t*glob_constr option*glob_constr option) list -> glob_constr
val glob_decompose_app : glob_constr -> glob_constr*(glob_constr list)
@@ -44,14 +32,6 @@ val glob_decompose_app : glob_constr -> glob_constr*(glob_constr list)
val glob_make_eq : ?typ:glob_constr -> glob_constr -> glob_constr -> glob_constr
(* [glob_make_neq t1 t2] build the glob_constr corresponding to [t1 <> t2] *)
val glob_make_neq : glob_constr -> glob_constr -> glob_constr
-(* [glob_make_or P1 P2] build the glob_constr corresponding to [P1 \/ P2] *)
-val glob_make_or : glob_constr -> glob_constr -> glob_constr
-
-(* [glob_make_or_list [P1;...;Pn]] build the glob_constr corresponding
- to [P1 \/ ( .... \/ Pn)]
-*)
-val glob_make_or_list : glob_constr list -> glob_constr
-
(* alpha_conversion functions *)
@@ -109,18 +89,8 @@ val eq_cases_pattern : cases_pattern -> cases_pattern -> bool
*)
val ids_of_pat : cases_pattern -> Id.Set.t
-(* TODO: finish this function (Fix not treated) *)
-val ids_of_glob_constr: glob_constr -> Id.Set.t
-
-(*
- removing let_in construction in a glob_constr
-*)
-val zeta_normalize : Glob_term.glob_constr -> Glob_term.glob_constr
-
-
val expand_as : glob_constr -> glob_constr
-
(* [resolve_and_replace_implicits ?expected_type env sigma rt] solves implicits of [rt] w.r.t. [env] and [sigma] and then replace them by their solution
*)
val resolve_and_replace_implicits :
diff --git a/plugins/funind/indfun.ml b/plugins/funind/indfun.ml
index 071599d9c..58154d310 100644
--- a/plugins/funind/indfun.ml
+++ b/plugins/funind/indfun.ml
@@ -215,6 +215,7 @@ let is_rec names =
| GCases(_,_,el,brl) ->
List.exists (fun (e,_) -> lookup names e) el ||
List.exists (lookup_br names) brl
+ | GProj(_,c) -> lookup names c
and lookup_br names (_,(idl,_,rt)) =
let new_names = List.fold_right Id.Set.remove idl names in
lookup new_names rt
@@ -282,7 +283,6 @@ let derive_inversion fix_names =
in
Invfun.derive_correctness
Functional_principles_types.make_scheme
- functional_induction
fix_names_as_constant
lind;
with e when CErrors.noncritical e ->
@@ -780,6 +780,7 @@ let rec add_args id new_args = CAst.map (function
| CNotation _ -> anomaly ~label:"add_args " (Pp.str "CNotation.")
| CGeneralization _ -> anomaly ~label:"add_args " (Pp.str "CGeneralization.")
| CDelimiters _ -> anomaly ~label:"add_args " (Pp.str "CDelimiters.")
+ | CProj _ -> user_err Pp.(str "Funind does not support primitive projections")
)
exception Stop of Constrexpr.constr_expr
diff --git a/plugins/funind/indfun_common.ml b/plugins/funind/indfun_common.ml
index 5a9248d47..d6fd2f2a0 100644
--- a/plugins/funind/indfun_common.ml
+++ b/plugins/funind/indfun_common.ml
@@ -190,7 +190,6 @@ let with_full_print f a =
Impargs.make_implicit_args false;
Impargs.make_strict_implicit_args false;
Impargs.make_contextual_implicit_args false;
- Impargs.make_contextual_implicit_args false;
Dumpglob.pause ();
try
let res = f a in
diff --git a/plugins/funind/invfun.ml b/plugins/funind/invfun.ml
index 694c80051..4acf82d00 100644
--- a/plugins/funind/invfun.ml
+++ b/plugins/funind/invfun.ml
@@ -56,12 +56,6 @@ let do_observe_tac s tac g =
CErrors.iprint e ++ str " on goal" ++ fnl() ++ goal ));
iraise reraise;;
-
-let observe_tac_strm s tac g =
- if do_observe ()
- then do_observe_tac s tac g
- else tac g
-
let observe_tac s tac g =
if do_observe ()
then do_observe_tac (str s) tac g
@@ -87,10 +81,6 @@ let make_eq () =
try
EConstr.of_constr (Universes.constr_of_global (Coqlib.build_coq_eq ()))
with _ -> assert false
-let make_eq_refl () =
- try
- EConstr.of_constr (Universes.constr_of_global (Coqlib.build_coq_eq_refl ()))
- with _ -> assert false
(* [generate_type g_to_f f graph i] build the completeness (resp. correctness) lemma type if [g_to_f = true]
@@ -194,10 +184,9 @@ let rec generate_fresh_id x avoid i =
id::(generate_fresh_id x (id::avoid) (pred i))
-(* [prove_fun_correct functional_induction funs_constr graphs_constr schemes lemmas_types_infos i ]
+(* [prove_fun_correct funs_constr graphs_constr schemes lemmas_types_infos i ]
is the tactic used to prove correctness lemma.
- [functional_induction] is the tactic defined in [indfun] (dependency problem)
[funs_constr], [graphs_constr] [schemes] [lemmas_types_infos] are the mutually recursive functions
(resp. graphs of the functions and principles and correctness lemma types) to prove correct.
@@ -218,7 +207,7 @@ let rec generate_fresh_id x avoid i =
\end{enumerate}
*)
-let prove_fun_correct evd functional_induction funs_constr graphs_constr schemes lemmas_types_infos i : Tacmach.tactic =
+let prove_fun_correct evd funs_constr graphs_constr schemes lemmas_types_infos i : Tacmach.tactic =
fun g ->
(* first of all we recreate the lemmas types to be used as predicates of the induction principle
that is~:
@@ -752,14 +741,13 @@ let prove_fun_complete funcs graphs schemes lemmas_types_infos i : Tacmach.tacti
g
-(* [derive_correctness make_scheme functional_induction funs graphs] create correctness and completeness
+(* [derive_correctness make_scheme funs graphs] create correctness and completeness
lemmas for each function in [funs] w.r.t. [graphs]
[make_scheme] is Functional_principle_types.make_scheme (dependency pb) and
- [functional_induction] is Indfun.functional_induction (same pb)
*)
-let derive_correctness make_scheme functional_induction (funs: pconstant list) (graphs:inductive list) =
+let derive_correctness make_scheme (funs: pconstant list) (graphs:inductive list) =
assert (funs <> []);
assert (graphs <> []);
let funs = Array.of_list funs and graphs = Array.of_list graphs in
@@ -809,7 +797,7 @@ let derive_correctness make_scheme functional_induction (funs: pconstant list) (
)
in
let proving_tac =
- prove_fun_correct !evd functional_induction funs_constr graphs_constr schemes lemmas_types_infos
+ prove_fun_correct !evd funs_constr graphs_constr schemes lemmas_types_infos
in
Array.iteri
(fun i f_as_constant ->
diff --git a/plugins/funind/invfun.mli b/plugins/funind/invfun.mli
new file mode 100644
index 000000000..e07138596
--- /dev/null
+++ b/plugins/funind/invfun.mli
@@ -0,0 +1,17 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+val invfun :
+ Misctypes.quantified_hypothesis ->
+ Globnames.global_reference option ->
+ Evar.t Evd.sigma -> Evar.t list Evd.sigma
+val derive_correctness :
+ (Evd.evar_map ref ->
+ (Constr.pconstant * Sorts.family) list ->
+ 'a Entries.definition_entry list) ->
+ Constr.pconstant list -> Names.inductive list -> unit
diff --git a/plugins/funind/merge.ml b/plugins/funind/merge.ml
deleted file mode 100644
index 8f5d3f22f..000000000
--- a/plugins/funind/merge.ml
+++ /dev/null
@@ -1,1013 +0,0 @@
-(************************************************************************)
-(* v * The Coq Proof Assistant / The Coq Development Team *)
-(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(************************************************************************)
-
-(* Merging of induction principles. *)
-
-open Globnames
-open Tactics
-open Indfun_common
-open CErrors
-open Util
-open Constrexpr
-open Vernacexpr
-open Pp
-open Names
-open Term
-open Constr
-open Vars
-open Glob_term
-open Glob_termops
-open Decl_kinds
-open Declarations
-open Context.Rel.Declaration
-
-module RelDecl = Context.Rel.Declaration
-
-(** {1 Utilities} *)
-
-(** {2 Useful operations on constr and glob_constr} *)
-
-let pop c = Vars.lift (-1) c
-let rec popn i c = if i<=0 then c else pop (popn (i-1) c)
-
-(** Substitutions in constr *)
-let compare_constr_nosub t1 t2 =
- if Constr.compare_head (fun _ _ -> false) t1 t2
- then true
- else false
-
-let rec compare_constr' t1 t2 =
- if compare_constr_nosub t1 t2
- then true
- else (Constr.compare_head (compare_constr') t1 t2)
-
-let rec substitterm prof t by_t in_u =
- if (compare_constr' (lift prof t) in_u)
- then (lift prof by_t)
- else Constr.map_with_binders succ
- (fun i -> substitterm i t by_t) prof in_u
-
-let lift_ldecl n ldecl = List.map (fun (x,y) -> x,lift n y) ldecl
-
-let understand = Pretyping.understand (Global.env()) Evd.empty
-
-(** Operations on names and identifiers *)
-let id_of_name = function
- Anonymous -> Id.of_string "H"
- | Name id -> id;;
-let name_of_string = Id.of_string %> Name.mk_name
-let string_of_name = id_of_name %> Id.to_string
-
-(** [isVarf f x] returns [true] if term [x] is of the form [(Var f)]. *)
-let isVarf f x =
- match DAst.get x with
- | GVar x -> Id.equal x f
- | _ -> false
-
-(** [ident_global_exist id] returns true if identifier [id] is linked
- in global environment. *)
-let ident_global_exist id =
- try
- let ans = CAst.make @@ CRef (Libnames.Ident (Loc.tag id), None) in
- let _ = ignore (Constrintern.intern_constr (Global.env()) ans) in
- true
- with e when CErrors.noncritical e -> false
-
-(** [next_ident_fresh id] returns a fresh identifier (ie not linked in
- global env) with base [id]. *)
-let next_ident_fresh (id:Id.t) =
- let res = ref id in
- while ident_global_exist !res do res := Nameops.increment_subscript !res done;
- !res
-
-
-(** {2 Debugging} *)
-(* comment this line to see debug msgs *)
-let msg x = () ;; let pr_lconstr c = str ""
-(* uncomment this to see debugging *)
-let prconstr c =
- let sigma, env = Pfedit.get_current_context () in
- msg (str" " ++ Printer.pr_lconstr_env env sigma c)
-
-let prconstrnl c =
- let sigma, env = Pfedit.get_current_context () in
- msg (str" " ++ Printer.pr_lconstr_env env sigma c ++ str"\n")
-
-let prlistconstr lc = List.iter prconstr lc
-let prstr s = msg(str s)
-let prNamedConstr s c =
- let sigma, env = Pfedit.get_current_context () in
- begin
- msg(str "");
- msg(str(s^" {§ ") ++ Printer.pr_lconstr_env env sigma c ++ str " §} ");
- msg(str "");
- end
-let prNamedRConstr s c =
- let sigma, env = Pfedit.get_current_context () in
- begin
- msg(str "");
- msg(str(s^" {§ ") ++ Printer.pr_glob_constr_env env c ++ str " §} ");
- msg(str "");
- end
-let prNamedLConstr_aux lc = List.iter (prNamedConstr "\n") lc
-let prNamedLConstr s lc =
- begin
- prstr "[§§§ ";
- prstr s;
- prNamedLConstr_aux lc;
- prstr " §§§]\n";
- end
-let prNamedLDecl s lc =
- begin
- prstr s; prstr "\n";
- List.iter (fun (nm,_,tp) -> prNamedConstr (string_of_name nm) tp) lc;
- prstr "\n";
- end
-let prNamedRLDecl s lc =
- begin
- prstr s; prstr "\n"; prstr "{§§ ";
- List.iter
- (fun x ->
- match x with
- | (nm,None,Some tp) -> prNamedRConstr (string_of_name nm) tp
- | (nm,Some bdy,None) -> prNamedRConstr ("(letin) "^string_of_name nm) bdy
- | _ -> assert false
- ) lc;
- prstr " §§}\n";
- prstr "\n";
- end
-
-(** {2 Misc} *)
-
-exception Found of int
-
-(* Array scanning *)
-
-let array_prfx (arr: 'a array) (pred: int -> 'a -> bool): int =
-match Array.findi pred arr with
-| None -> Array.length arr (* all elt are positive *)
-| Some i -> i
-
-(* Like List.chop but except that [i] is the size of the suffix of [l]. *)
-let list_chop_end i l =
- let size_prefix = List.length l -i in
- if size_prefix < 0 then failwith "list_chop_end"
- else List.chop size_prefix l
-
-let list_fold_lefti (f: int -> 'a -> 'b -> 'a) (acc:'a) (arr:'b list): 'a =
- let i = ref 0 in
- List.fold_left
- (fun acc x ->
- let res = f !i acc x in i := !i + 1; res)
- acc arr
-
-let list_filteri (f: int -> 'a -> bool) (l:'a list):'a list =
- let i = ref 0 in
- List.filter (fun x -> let res = f !i x in i := !i + 1; res) l
-
-
-(** Iteration module *)
-module For =
-struct
- let rec map i j (f: int -> 'a) = if i>j then [] else f i :: (map (i+1) j f)
- let rec foldup i j (f: 'a -> int -> 'a) acc =
- if i>j then acc else let newacc = f acc i in foldup (i+1) j f newacc
- let rec folddown i j (f: 'a -> int -> 'a) acc =
- if i>j then acc else let newacc = f acc j in folddown i (j-1) f newacc
- let fold i j = if i<j then foldup i j else folddown i j
-end
-
-
-(** {1 Parameters shifting and linking information} *)
-
-(** This type is used to deal with debruijn linked indices. When a
- variable is linked to a previous one, we will ignore it and refer
- to previous one. *)
-type linked_var =
- | Linked of int
- | Unlinked
- | Funres
-
-(** When merging two graphs, parameters may become regular arguments,
- and thus be shifted. This type describes the result of computing
- the changes. *)
-type 'a shifted_params =
- {
- nprm1:'a;
- nprm2:'a;
- prm2_unlinked:'a list; (* ranks of unlinked params in nprms2 *)
- nuprm1:'a;
- nuprm2:'a;
- nargs1:'a;
- nargs2:'a;
- }
-
-
-let prlinked x =
- match x with
- | Linked i -> Printf.sprintf "Linked %d" i
- | Unlinked -> Printf.sprintf "Unlinked"
- | Funres -> Printf.sprintf "Funres"
-
-let linkmonad f lnkvar =
- match lnkvar with
- | Linked i -> Linked (f i)
- | Unlinked -> Unlinked
- | Funres -> Funres
-
-let linklift lnkvar i = linkmonad (fun x -> x+i) lnkvar
-
-(* This map is used to deal with debruijn linked indices. *)
-module Link = Map.Make (Int)
-
-let pr_links l =
- Printf.printf "links:\n";
- Link.iter (fun k e -> Printf.printf "%d : %s\n" k (prlinked e)) l;
- Printf.printf "_____________\n"
-
-type 'a merged_arg =
- | Prm_stable of 'a
- | Prm_linked of 'a
- | Prm_arg of 'a
- | Arg_stable of 'a
- | Arg_linked of 'a
- | Arg_funres
-
-(** Information about graph merging of two inductives.
- All rel_decl list are IN REVERSE ORDER (ie well suited for compose) *)
-
-type merge_infos =
- {
- ident:Id.t; (** new inductive name *)
- mib1: mutual_inductive_body;
- oib1: one_inductive_body;
- mib2: mutual_inductive_body;
- oib2: one_inductive_body;
-
- (** Array of links of the first inductive (should be all stable) *)
- lnk1: int merged_arg array;
-
- (** Array of links of the second inductive (point to the first ind param/args) *)
- lnk2: int merged_arg array;
-
- (** rec params which remain rec param (ie not linked) *)
- recprms1: Context.Rel.Declaration.t list;
- recprms2: Context.Rel.Declaration.t list;
- nrecprms1: int;
- nrecprms2: int;
-
- (** rec parms which became non parm (either linked to something
- or because after a rec parm that became non parm) *)
- otherprms1: Context.Rel.Declaration.t list;
- otherprms2: Context.Rel.Declaration.t list;
- notherprms1:int;
- notherprms2:int;
-
- (** args which remain args in merge *)
- args1:Context.Rel.Declaration.t list;
- args2:Context.Rel.Declaration.t list;
- nargs1:int;
- nargs2:int;
-
- (** functional result args *)
- funresprms1: Context.Rel.Declaration.t list;
- funresprms2: Context.Rel.Declaration.t list;
- nfunresprms1:int;
- nfunresprms2:int;
- }
-
-
-let pr_merginfo x =
- let i,s=
- match x with
- | Prm_linked i -> Some i,"Prm_linked"
- | Arg_linked i -> Some i,"Arg_linked"
- | Prm_stable i -> Some i,"Prm_stable"
- | Prm_arg i -> Some i,"Prm_arg"
- | Arg_stable i -> Some i,"Arg_stable"
- | Arg_funres -> None , "Arg_funres" in
- match i with
- | Some i -> Printf.sprintf "%s(%d)" s i
- | None -> Printf.sprintf "%s" s
-
-let isPrm_stable x = match x with Prm_stable _ -> true | _ -> false
-
-(* ?? prm_linked?? *)
-let isArg_stable x = match x with Arg_stable _ | Prm_arg _ -> true | _ -> false
-
-let is_stable x =
- match x with Arg_stable _ | Prm_stable _ | Prm_arg _ -> true | _ -> false
-
-let isArg_funres x = match x with Arg_funres -> true | _ -> false
-
-let filter_shift_stable (lnk:int merged_arg array) (l:'a list): 'a list =
- let prms = list_filteri (fun i _ -> isPrm_stable lnk.(i)) l in
- let args = list_filteri (fun i _ -> isArg_stable lnk.(i)) l in
- let fres = list_filteri (fun i _ -> isArg_funres lnk.(i)) l in
- prms@args@fres
-
-(** Reverse the link map, keeping only linked vars, elements are list
- of int as several vars may be linked to the same var. *)
-let revlinked lnk =
- For.fold 0 (Array.length lnk - 1)
- (fun acc k ->
- match lnk.(k) with
- | Unlinked | Funres -> acc
- | Linked i ->
- let old = try Link.find i acc with Not_found -> [] in
- Link.add i (k::old) acc)
- Link.empty
-
-let array_switch arr i j =
- let aux = arr.(j) in arr.(j) <- arr.(i); arr.(i) <- aux
-
-let filter_shift_stable_right (lnk:int merged_arg array) (l:'a list): 'a list =
- let larr = Array.of_list l in
- let _ =
- Array.iteri
- (fun j x ->
- match x with
- | Prm_linked i -> array_switch larr i j
- | Arg_linked i -> array_switch larr i j
- | Prm_stable i -> ()
- | Prm_arg i -> ()
- | Arg_stable i -> ()
- | Arg_funres -> ()
- ) lnk in
- filter_shift_stable lnk (Array.to_list larr)
-
-
-let error msg = user_err Pp.(str msg)
-
-(** {1 Utilities for merging} *)
-
-let ind1name = Id.of_string "__ind1"
-let ind2name = Id.of_string "__ind2"
-
-(** Performs verifications on two graphs before merging: they must not
- be co-inductive, and for the moment they must not be mutual
- either. *)
-let verify_inds mib1 mib2 =
- if mib1.mind_finite == CoFinite then error "First argument is coinductive";
- if mib2.mind_finite == CoFinite then error "Second argument is coinductive";
- if not (Int.equal mib1.mind_ntypes 1) then error "First argument is mutual";
- if not (Int.equal mib2.mind_ntypes 1) then error "Second argument is mutual";
- ()
-
-(*
-(** [build_raw_params prms_decl avoid] returns a list of variables
- attributed to the list of decl [prms_decl], avoiding names in
- [avoid]. *)
-let build_raw_params prms_decl avoid =
- let dummy_constr = compose_prod (List.map (fun (x,_,z) -> x,z) prms_decl) (mkRel 1) in
- let _ = prNamedConstr "DUMMY" dummy_constr in
- let dummy_glob_constr = Detyping.detype false avoid [] dummy_constr in
- let _ = prNamedRConstr "RAWDUMMY" dummy_glob_constr in
- let res,_ = glob_decompose_prod dummy_glob_constr in
- let comblist = List.combine prms_decl res in
- comblist, res , (avoid @ (Id.Set.elements (ids_of_glob_constr dummy_glob_constr)))
-*)
-
-let ids_of_rawlist avoid rawl =
- List.fold_left Id.Set.union avoid (List.map ids_of_glob_constr rawl)
-
-
-
-(** {1 Merging function graphs} *)
-
-(** [shift_linked_params mib1 mib2 lnk] Computes which parameters (rec
- uniform and ordinary ones) of mutual inductives [mib1] and [mib2]
- remain uniform when linked by [lnk]. All parameters are
- considered, ie we take parameters of the first inductive body of
- [mib1] and [mib2].
-
- Explanation: The two inductives have parameters, some of the first
- are recursively uniform, some of the last are functional result of
- the functional graph.
-
- (I x1 x2 ... xk ... xk' ... xn)
- (J y1 y2 ... xl ... yl' ... ym)
-
- Problem is, if some rec unif params are linked to non rec unif
- ones, they become non rec (and the following too). And functinal
- argument have to be shifted at the end *)
-let shift_linked_params mib1 mib2 (lnk1:linked_var array) (lnk2:linked_var array) id =
- let _ = prstr "\nYOUHOU shift\n" in
- let linked_targets = revlinked lnk2 in
- let is_param_of_mib1 x = x < mib1.mind_nparams_rec in
- let is_param_of_mib2 x = x < mib2.mind_nparams_rec in
- let is_targetted_by_non_recparam_lnk1 i =
- try
- let targets = Link.find i linked_targets in
- List.exists (fun x -> not (is_param_of_mib2 x)) targets
- with Not_found -> false in
- let mlnk1 =
- Array.mapi
- (fun i lkv ->
- let isprm = is_param_of_mib1 i in
- let prmlost = is_targetted_by_non_recparam_lnk1 i in
- match isprm , prmlost, lnk1.(i) with
- | true , true , _ -> Prm_arg i (* recparam becoming ordinary *)
- | true , false , _-> Prm_stable i (* recparam remains recparam*)
- | false , false , Funres -> Arg_funres
- | _ , _ , Funres -> assert false (* fun res cannot be a rec param or lost *)
- | false , _ , _ -> Arg_stable i) (* Args of lnk1 are not linked *)
- lnk1 in
- let mlnk2 =
- Array.mapi
- (fun i lkv ->
- (* Is this correct if some param of ind2 is lost? *)
- let isprm = is_param_of_mib2 i in
- match isprm , lnk2.(i) with
- | true , Linked j when not (is_param_of_mib1 j) ->
- Prm_arg j (* recparam becoming ordinary *)
- | true , Linked j -> Prm_linked j (*recparam linked to recparam*)
- | true , Unlinked -> Prm_stable i (* recparam remains recparam*)
- | false , Linked j -> Arg_linked j (* Args of lnk2 lost *)
- | false , Unlinked -> Arg_stable i (* Args of lnk2 remains *)
- | false , Funres -> Arg_funres
- | true , Funres -> assert false (* fun res cannot be a rec param *)
- )
- lnk2 in
- let oib1 = mib1.mind_packets.(0) in
- let oib2 = mib2.mind_packets.(0) in
- (* count params remaining params *)
- let n_params1 = array_prfx mlnk1 (fun i x -> not (isPrm_stable x)) in
- let n_params2 = array_prfx mlnk2 (fun i x -> not (isPrm_stable x)) in
- let bldprms arity_ctxt mlnk =
- list_fold_lefti
- (fun i (acc1,acc2,acc3,acc4) x ->
- prstr (pr_merginfo mlnk.(i));prstr "\n";
- match mlnk.(i) with
- | Prm_stable _ -> x::acc1 , acc2 , acc3, acc4
- | Prm_arg _ -> acc1 , x::acc2 , acc3, acc4
- | Arg_stable _ -> acc1 , acc2 , x::acc3, acc4
- | Arg_funres -> acc1 , acc2 , acc3, x::acc4
- | _ -> acc1 , acc2 , acc3, acc4)
- ([],[],[],[]) arity_ctxt in
-(* let arity_ctxt2 =
- build_raw_params oib2.mind_arity_ctxt
- (Id.Set.elements (ids_of_glob_constr oib1.mind_arity_ctxt)) in*)
- let recprms1,otherprms1,args1,funresprms1 = bldprms (List.rev oib1.mind_arity_ctxt) mlnk1 in
- let _ = prstr "\n\n\n" in
- let recprms2,otherprms2,args2,funresprms2 = bldprms (List.rev oib2.mind_arity_ctxt) mlnk2 in
- let _ = prstr "\notherprms1:\n" in
- let _ =
- List.iter (fun decl -> prstr (string_of_name (RelDecl.get_name decl) ^ " : ");
- prconstr (RelDecl.get_type decl); prstr "\n")
- otherprms1 in
- let _ = prstr "\notherprms2:\n" in
- let _ =
- List.iter (fun decl -> prstr (string_of_name (RelDecl.get_name decl) ^ " : "); prconstr (RelDecl.get_type decl); prstr "\n")
- otherprms2 in
- {
- ident=id;
- mib1=mib1;
- oib1 = oib1;
- mib2=mib2;
- oib2 = oib2;
- lnk1 = mlnk1;
- lnk2 = mlnk2;
- nrecprms1 = n_params1;
- recprms1 = recprms1;
- otherprms1 = otherprms1;
- args1 = args1;
- funresprms1 = funresprms1;
- notherprms1 = Array.length mlnk1 - n_params1;
- nfunresprms1 = List.length funresprms1;
- nargs1 = List.length args1;
- nrecprms2 = n_params2;
- recprms2 = recprms2;
- otherprms2 = otherprms2;
- args2 = args2;
- funresprms2 = funresprms2;
- notherprms2 = Array.length mlnk2 - n_params2;
- nargs2 = List.length args2;
- nfunresprms2 = List.length funresprms2;
- }
-
-
-
-
-(** {1 Merging functions} *)
-
-exception NoMerge
-
-let rec merge_app c1 c2 id1 id2 shift filter_shift_stable =
- let lnk = Array.append shift.lnk1 shift.lnk2 in
- match DAst.get c1, DAst.get c2 with
- | GApp(f1, arr1), GApp(f2,arr2) when isVarf id1 f1 && isVarf id2 f2 ->
- let _ = prstr "\nICI1!\n" in
- let args = filter_shift_stable lnk (arr1 @ arr2) in
- DAst.make @@ GApp ((DAst.make @@ GVar shift.ident) , args)
- | GApp(f1, arr1), GApp(f2,arr2) -> raise NoMerge
- | GLetIn(nme,bdy,typ,trm) , _ ->
- let _ = prstr "\nICI2!\n" in
- let newtrm = merge_app trm c2 id1 id2 shift filter_shift_stable in
- DAst.make @@ GLetIn(nme,bdy,typ,newtrm)
- | _, GLetIn(nme,bdy,typ,trm) ->
- let _ = prstr "\nICI3!\n" in
- let newtrm = merge_app c1 trm id1 id2 shift filter_shift_stable in
- DAst.make @@ GLetIn(nme,bdy,typ,newtrm)
- | _ -> let _ = prstr "\nICI4!\n" in
- raise NoMerge
-
-let rec merge_app_unsafe c1 c2 shift filter_shift_stable =
- let lnk = Array.append shift.lnk1 shift.lnk2 in
- match DAst.get c1, DAst.get c2 with
- | GApp(f1, arr1), GApp(f2,arr2) ->
- let args = filter_shift_stable lnk (arr1 @ arr2) in
- DAst.make @@ GApp (DAst.make @@ GVar shift.ident, args)
- (* FIXME: what if the function appears in the body of the let? *)
- | GLetIn(nme,bdy,typ,trm) , _ ->
- let _ = prstr "\nICI2 '!\n" in
- let newtrm = merge_app_unsafe trm c2 shift filter_shift_stable in
- DAst.make @@ GLetIn(nme,bdy,typ,newtrm)
- | _, GLetIn(nme,bdy,typ,trm) ->
- let _ = prstr "\nICI3 '!\n" in
- let newtrm = merge_app_unsafe c1 trm shift filter_shift_stable in
- DAst.make @@ GLetIn(nme,bdy,typ,newtrm)
- | _ -> let _ = prstr "\nICI4 '!\n" in raise NoMerge
-
-
-
-(* Heuristic when merging two lists of hypothesis: merge every rec
- calls of branch 1 with all rec calls of branch 2. *)
-(* TODO: reecrire cette heuristique (jusqu'a merge_types) *)
-let rec merge_rec_hyps shift accrec
- (ltyp:(Name.t * glob_constr option * glob_constr option) list)
- filter_shift_stable : (Name.t * glob_constr option * glob_constr option) list =
- let is_app c = match DAst.get c with GApp _ -> true | _ -> false in
- let mergeonehyp t reldecl =
- match reldecl with
- | (nme,x,Some ind) when is_app ind
- -> nme,x, Some (merge_app_unsafe ind t shift filter_shift_stable)
- | (nme,Some _,None) -> error "letins with recursive calls not treated yet"
- | (nme,None,Some _) -> assert false
- | (nme,None,None) | (nme,Some _,Some _) -> assert false in
- let is_app c = match DAst.get c with GApp (f, _) -> isVarf ind2name f | _ -> false in
- match ltyp with
- | [] -> []
- | (nme,None,Some t) :: lt when is_app t ->
- let rechyps = List.map (mergeonehyp t) accrec in
- rechyps @ merge_rec_hyps shift accrec lt filter_shift_stable
- | e::lt -> e :: merge_rec_hyps shift accrec lt filter_shift_stable
-
-
-let build_suppl_reccall (accrec:(Name.t * glob_constr) list) concl2 shift =
- List.map (fun (nm,tp) -> (nm,merge_app_unsafe tp concl2 shift)) accrec
-
-
-let find_app (nme:Id.t) ltyp =
- let is_app c = match DAst.get c with GApp (f, _) -> isVarf nme f | _ -> false in
- try
- ignore
- (List.map
- (fun x ->
- match x with
- | _,None,Some c when is_app c -> raise (Found 0)
- | _ -> ())
- ltyp);
- false
- with Found _ -> true
-
-let prnt_prod_or_letin nm letbdy typ =
- match letbdy , typ with
- | Some lbdy , None -> prNamedRConstr ("(letin) " ^ string_of_name nm) lbdy
- | None , Some tp -> prNamedRConstr (string_of_name nm) tp
- | _ , _ -> assert false
-
-
-let rec merge_types shift accrec1
- (ltyp1:(Name.t * glob_constr option * glob_constr option) list)
- (concl1:glob_constr) (ltyp2:(Name.t * glob_constr option * glob_constr option) list) concl2
- : (Name.t * glob_constr option * glob_constr option) list * glob_constr =
- let _ = prstr "MERGE_TYPES\n" in
- let _ = prstr "ltyp 1 : " in
- let _ = List.iter (fun (nm,lbdy,tp) -> prnt_prod_or_letin nm lbdy tp) ltyp1 in
- let _ = prstr "\nltyp 2 : " in
- let _ = List.iter (fun (nm,lbdy,tp) -> prnt_prod_or_letin nm lbdy tp) ltyp2 in
- let _ = prstr "\n" in
- let res =
- match ltyp1 with
- | [] ->
- let isrec1 = not (List.is_empty accrec1) in
- let isrec2 = find_app ind2name ltyp2 in
- let rechyps =
- if isrec1 && isrec2
- then (* merge_rec_hyps shift accrec1 ltyp2 filter_shift_stable *)
- merge_rec_hyps shift [name_of_string "concl1",None,Some concl1] ltyp2
- filter_shift_stable_right
- @ merge_rec_hyps shift accrec1 [name_of_string "concl2",None, Some concl2]
- filter_shift_stable
- else if isrec1
- (* if rec calls in accrec1 and not in ltyp2, add one to ltyp2 *)
- then
- merge_rec_hyps shift accrec1
- (ltyp2@[name_of_string "concl2",None,Some concl2]) filter_shift_stable
- else if isrec2
- then merge_rec_hyps shift [name_of_string "concl1",None,Some concl1] ltyp2
- filter_shift_stable_right
- else ltyp2 in
- let _ = prstr"\nrechyps : " in
- let _ = List.iter(fun (nm,lbdy,tp)-> prnt_prod_or_letin nm lbdy tp) rechyps in
- let _ = prstr "MERGE CONCL : " in
- let _ = prNamedRConstr "concl1" concl1 in
- let _ = prstr " with " in
- let _ = prNamedRConstr "concl2" concl2 in
- let _ = prstr "\n" in
- let concl =
- merge_app concl1 concl2 ind1name ind2name shift filter_shift_stable in
- let _ = prstr "FIN " in
- let _ = prNamedRConstr "concl" concl in
- let _ = prstr "\n" in
-
- rechyps , concl
- | (nme,None, Some t1)as e ::lt1 ->
- (match DAst.get t1 with
- | GApp(f,carr) when isVarf ind1name f ->
- merge_types shift (e::accrec1) lt1 concl1 ltyp2 concl2
- | _ ->
- let recres, recconcl2 =
- merge_types shift accrec1 lt1 concl1 ltyp2 concl2 in
- ((nme,None,Some t1) :: recres) , recconcl2)
- | (nme,Some bd, None) ::lt1 ->
- (* FIXME: what if ind1name appears in bd? *)
- let recres, recconcl2 =
- merge_types shift accrec1 lt1 concl1 ltyp2 concl2 in
- ((nme,Some bd,None) :: recres) , recconcl2
- | (_,None,None)::_ | (_,Some _,Some _)::_ -> assert false
- in
- res
-
-
-(** [build_link_map_aux allargs1 allargs2 shift] returns the mapping of
- linked args [allargs2] to target args of [allargs1] as specified
- in [shift]. [allargs1] and [allargs2] are in reverse order. Also
- returns the list of unlinked vars of [allargs2]. *)
-let build_link_map_aux (allargs1:Id.t array) (allargs2:Id.t array)
- (lnk:int merged_arg array) =
- Array.fold_left_i
- (fun i acc e ->
- if Int.equal i (Array.length lnk - 1) then acc (* functional arg, not in allargs *)
- else
- match e with
- | Prm_linked j | Arg_linked j -> Id.Map.add allargs2.(i) allargs1.(j) acc
- | _ -> acc)
- Id.Map.empty lnk
-
-let build_link_map allargs1 allargs2 lnk =
- let allargs1 =
- Array.of_list (List.rev_map (fun (x,_,_) -> id_of_name x) allargs1) in
- let allargs2 =
- Array.of_list (List.rev_map (fun (x,_,_) -> id_of_name x) allargs2) in
- build_link_map_aux allargs1 allargs2 lnk
-
-
-(** [merge_one_constructor lnk shift typcstr1 typcstr2] merges the two
- constructor rawtypes [typcstr1] and [typcstr2]. [typcstr1] and
- [typcstr2] contain all parameters (including rec. unif. ones) of
- their inductive.
-
- if [typcstr1] and [typcstr2] are of the form:
-
- forall recparams1, forall ordparams1, H1a -> H2a... (I1 x1 y1 ... z1)
- forall recparams2, forall ordparams2, H2b -> H2b... (I2 x2 y2 ... z2)
-
- we build:
-
- forall recparams1 (recparams2 without linked params),
- forall ordparams1 (ordparams2 without linked params),
- H1a' -> H2a' -> ... -> H2a' -> H2b'(shifted) -> ...
- -> (newI x1 ... z1 x2 y2 ...z2 without linked params)
-
- where Hix' have been adapted, ie:
- - linked vars have been changed,
- - rec calls to I1 and I2 have been replaced by rec calls to
- newI. More precisely calls to I1 and I2 have been merge by an
- experimental heuristic (in particular if n o rec calls for I1
- or I2 is found, we use the conclusion as a rec call). See
- [merge_types] above.
-
- Precond: vars sets of [typcstr1] and [typcstr2] must be disjoint.
-
- TODO: return nothing if equalities (after linking) are contradictory. *)
-let merge_one_constructor (shift:merge_infos) (typcstr1:glob_constr)
- (typcstr2:glob_constr) : glob_constr =
- (* FIXME: les noms des parametres corerspondent en principe au
- parametres du niveau mib, mais il faudrait s'en assurer *)
- (* shift.nfunresprmsx last args are functional result *)
- let nargs1 =
- shift.mib1.mind_nparams + shift.oib1.mind_nrealargs - shift.nfunresprms1 in
- let nargs2 =
- shift.mib2.mind_nparams + shift.oib2.mind_nrealargs - shift.nfunresprms2 in
- let allargs1,rest1 = glob_decompose_prod_or_letin_n nargs1 typcstr1 in
- let allargs2,rest2 = glob_decompose_prod_or_letin_n nargs2 typcstr2 in
- (* Build map of linked args of [typcstr2], and apply it to [typcstr2]. *)
- let linked_map = build_link_map allargs1 allargs2 shift.lnk2 in
- let rest2 = change_vars linked_map rest2 in
- let hyps1,concl1 = glob_decompose_prod_or_letin rest1 in
- let hyps2,concl2' = glob_decompose_prod_or_letin rest2 in
- let ltyp,concl2 =
- merge_types shift [] (List.rev hyps1) concl1 (List.rev hyps2) concl2' in
- let _ = prNamedRLDecl "ltyp result:" ltyp in
- let typ = glob_compose_prod_or_letin concl2 (List.rev ltyp) in
- let revargs1 =
- list_filteri (fun i _ -> isArg_stable shift.lnk1.(i)) (List.rev allargs1) in
- let _ = prNamedRLDecl "ltyp allargs1" allargs1 in
- let _ = prNamedRLDecl "ltyp revargs1" revargs1 in
- let revargs2 =
- list_filteri (fun i _ -> isArg_stable shift.lnk2.(i)) (List.rev allargs2) in
- let _ = prNamedRLDecl "ltyp allargs2" allargs2 in
- let _ = prNamedRLDecl "ltyp revargs2" revargs2 in
- let typwithprms =
- glob_compose_prod_or_letin typ (List.rev revargs2 @ List.rev revargs1) in
- typwithprms
-
-
-(** constructor numbering *)
-let fresh_cstror_suffix , cstror_suffix_init =
- let cstror_num = ref 0 in
- (fun () ->
- let res = string_of_int !cstror_num in
- cstror_num := !cstror_num + 1;
- res) ,
- (fun () -> cstror_num := 0)
-
-(** [merge_constructor_id id1 id2 shift] returns the identifier of the
- new constructor from the id of the two merged constructor and
- the merging info. *)
-let merge_constructor_id id1 id2 shift:Id.t =
- let id = Id.to_string shift.ident ^ "_" ^ fresh_cstror_suffix () in
- next_ident_fresh (Id.of_string id)
-
-
-
-(** [merge_constructors lnk shift avoid] merges the two list of
- constructor [(name*type)]. These are translated to glob_constr
- first, each of them having distinct var names. *)
-let merge_constructors (shift:merge_infos) (avoid:Id.Set.t)
- (typcstr1:(Id.t * glob_constr) list)
- (typcstr2:(Id.t * glob_constr) list) : (Id.t * glob_constr) list =
- List.flatten
- (List.map
- (fun (id1,rawtyp1) ->
- List.map
- (fun (id2,rawtyp2) ->
- let typ = merge_one_constructor shift rawtyp1 rawtyp2 in
- let newcstror_id = merge_constructor_id id1 id2 shift in
- let _ = prstr "\n**************\n" in
- newcstror_id , typ)
- typcstr2)
- typcstr1)
-
-(** [merge_inductive_body lnk shift avoid oib1 oib2] merges two
- inductive bodies [oib1] and [oib2], linking with [lnk], params
- info in [shift], avoiding identifiers in [avoid]. *)
-let merge_inductive_body (shift:merge_infos) avoid (oib1:one_inductive_body)
- (oib2:one_inductive_body) =
- (* building glob_constr type of constructors *)
- let mkrawcor nme avoid typ =
- (* first replace rel 1 by a varname *)
- let substindtyp = substitterm 0 (mkRel 1) (mkVar nme) typ in
- let substindtyp = EConstr.of_constr substindtyp in
- Detyping.detype Detyping.Now false avoid (Global.env()) Evd.empty substindtyp in
- let lcstr1: glob_constr list =
- Array.to_list (Array.map (mkrawcor ind1name avoid) oib1.mind_user_lc) in
- (* add to avoid all indentifiers of lcstr1 *)
- let avoid2 = Id.Set.union avoid (ids_of_rawlist avoid lcstr1) in
- let lcstr2 =
- Array.to_list (Array.map (mkrawcor ind2name avoid2) oib2.mind_user_lc) in
- let avoid3 = Id.Set.union avoid (ids_of_rawlist avoid lcstr2) in
-
- let params1 =
- try fst (glob_decompose_prod_n shift.nrecprms1 (List.hd lcstr1))
- with e when CErrors.noncritical e -> [] in
- let params2 =
- try fst (glob_decompose_prod_n shift.nrecprms2 (List.hd lcstr2))
- with e when CErrors.noncritical e -> [] in
-
- let lcstr1 = List.combine (Array.to_list oib1.mind_consnames) lcstr1 in
- let lcstr2 = List.combine (Array.to_list oib2.mind_consnames) lcstr2 in
-
- cstror_suffix_init();
- params1,params2,merge_constructors shift avoid3 lcstr1 lcstr2
-
-
-(** [merge_mutual_inductive_body lnk mib1 mib2 shift] merge mutual
- inductive bodies [mib1] and [mib2] linking vars with
- [lnk]. [shift] information on parameters of the new inductive.
- For the moment, inductives are supposed to be non mutual.
-*)
-let merge_mutual_inductive_body
- (mib1:mutual_inductive_body) (mib2:mutual_inductive_body) (shift:merge_infos) =
- (* Mutual not treated, we take first ind body of each. *)
- merge_inductive_body shift Id.Set.empty mib1.mind_packets.(0) mib2.mind_packets.(0)
-
-
-let glob_constr_to_constr_expr x = (* build a constr_expr from a glob_constr *)
- Flags.with_option Flags.raw_print (Constrextern.extern_glob_type Id.Set.empty) x
-
-let merge_rec_params_and_arity prms1 prms2 shift (concl:constr) =
- let params = prms2 @ prms1 in
- let resparams =
- List.fold_left
- (fun acc (nme,tp) ->
- let _ = prstr "param :" in
- let _ = prNamedRConstr (string_of_name nme) tp in
- let _ = prstr " ; " in
- let typ = glob_constr_to_constr_expr tp in
- CLocalAssum ([(Loc.tag nme)], Constrexpr_ops.default_binder_kind, typ) :: acc)
- [] params in
- let concl = Constrextern.extern_constr false (Global.env()) Evd.empty (EConstr.of_constr concl) in
- let arity,_ =
- List.fold_left
- (fun (acc,env) decl ->
- let nm = Context.Rel.Declaration.get_name decl in
- let c = RelDecl.get_type decl in
- let typ = Constrextern.extern_constr false env Evd.empty (EConstr.of_constr c) in
- let newenv = Environ.push_rel (LocalAssum (nm,c)) env in
- CAst.make @@ CProdN ([[(Loc.tag nm)],Constrexpr_ops.default_binder_kind,typ] , acc) , newenv)
- (concl,Global.env())
- (shift.funresprms2 @ shift.funresprms1
- @ shift.args2 @ shift.args1 @ shift.otherprms2 @ shift.otherprms1) in
- resparams,arity
-
-
-
-(** [glob_constr_list_to_inductive_expr ident rawlist] returns the
- induct_expr corresponding to the the list of constructor types
- [rawlist], named ident.
- FIXME: params et cstr_expr (arity) *)
-let glob_constr_list_to_inductive_expr prms1 prms2 mib1 mib2 shift
- (rawlist:(Id.t * glob_constr) list) =
- let lident = (Loc.tag shift.ident), None in
- let bindlist , cstr_expr = (* params , arities *)
- merge_rec_params_and_arity prms1 prms2 shift mkSet in
- let lcstor_expr : (bool * (lident * constr_expr)) list =
- List.map (* zeta_normalize t ? *)
- (fun (id,t) -> false, ((Loc.tag id),glob_constr_to_constr_expr t))
- rawlist in
- lident , bindlist , Some cstr_expr , lcstor_expr
-
-
-let mkProd_reldecl (rdecl:Context.Rel.Declaration.t) (t2:glob_constr) =
- match rdecl with
- | LocalAssum (nme,t) ->
- let t = EConstr.of_constr t in
- let traw = Detyping.detype Detyping.Now false Id.Set.empty (Global.env()) Evd.empty t in
- DAst.make @@ GProd (nme,Explicit,traw,t2)
- | LocalDef _ -> assert false
-
-
-(** [merge_inductive ind1 ind2 lnk] merges two graphs, linking
- variables specified in [lnk]. Graphs are not supposed to be mutual
- inductives for the moment. *)
-let merge_inductive (ind1: inductive) (ind2: inductive)
- (lnk1: linked_var array) (lnk2: linked_var array) id =
- let env = Global.env() in
- let mib1,_ = Inductive.lookup_mind_specif env ind1 in
- let mib2,_ = Inductive.lookup_mind_specif env ind2 in
- let _ = verify_inds mib1 mib2 in (* raises an exception if something wrong *)
- (* compute params that become ordinary args (because linked to ord. args) *)
- let shift_prm = shift_linked_params mib1 mib2 lnk1 lnk2 id in
- let prms1,prms2, rawlist = merge_mutual_inductive_body mib1 mib2 shift_prm in
- let _ = prstr "\nrawlist : " in
- let _ =
- List.iter (fun (nm,tp) -> prNamedRConstr (Id.to_string nm) tp;prstr "\n") rawlist in
- let _ = prstr "\nend rawlist\n" in
-(* FIX: retransformer en constr ici
- let shift_prm =
- { shift_prm with
- recprms1=prms1;
- recprms1=prms1;
- } in *)
- let indexpr = glob_constr_list_to_inductive_expr prms1 prms2 mib1 mib2 shift_prm rawlist in
- (* Declare inductive *)
- let indl,_,_ = ComInductive.extract_mutual_inductive_declaration_components [(indexpr,[])] in
- let mie,pl,impls = ComInductive.interp_mutual_inductive indl []
- false (* non-cumulative *) false (*FIXMEnon-poly *) false (* means not private *) Finite (* means: not coinductive *) in
- (* Declare the mutual inductive block with its associated schemes *)
- ignore (ComInductive.declare_mutual_inductive_with_eliminations mie pl impls)
-
-
-(* Find infos on identifier id. *)
-let find_Function_infos_safe (id:Id.t): Indfun_common.function_info =
- let kn_of_id x =
- let f_ref = Libnames.Ident (Loc.tag x) in
- locate_with_msg (str "Don't know what to do with " ++ Libnames.pr_reference f_ref)
- locate_constant f_ref in
- try find_Function_infos (kn_of_id id)
- with Not_found ->
- user_err ~hdr:"indfun" (Id.print id ++ str " has no functional scheme")
-
-(** [merge id1 id2 args1 args2 id] builds and declares a new inductive
- type called [id], representing the merged graphs of both graphs
- [ind1] and [ind2]. identifiers occurring in both arrays [args1] and
- [args2] are considered linked (i.e. are the same variable) in the
- new graph.
-
- Warning: For the moment, repetitions of an id in [args1] or
- [args2] are not supported. *)
-let merge (id1:Id.t) (id2:Id.t) (args1:Id.t array)
- (args2:Id.t array) id : unit =
- let finfo1 = find_Function_infos_safe id1 in
- let finfo2 = find_Function_infos_safe id2 in
- (* FIXME? args1 are supposed unlinked. mergescheme (G x x) ?? *)
- (* We add one arg (functional arg of the graph) *)
- let lnk1 = Array.make (Array.length args1 + 1) Unlinked in
- let lnk2' = (* args2 may be linked to args1 members. FIXME: same
- as above: vars may be linked inside args2?? *)
- Array.mapi
- (fun i c ->
- match Array.findi (fun i x -> Id.equal x c) args1 with
- | Some j -> Linked j
- | None -> Unlinked)
- args2 in
- (* We add one arg (functional arg of the graph) *)
- let lnk2 = Array.append lnk2' (Array.make 1 Unlinked) in
- (* setting functional results *)
- let _ = lnk1.(Array.length lnk1 - 1) <- Funres in
- let _ = lnk2.(Array.length lnk2 - 1) <- Funres in
- merge_inductive finfo1.graph_ind finfo2.graph_ind lnk1 lnk2 id
-
-
-let remove_last_arg c =
- let (x,y) = decompose_prod c in
- let xnolast = List.rev (List.tl (List.rev x)) in
- compose_prod xnolast y
-
-let rec remove_n_fst_list n l = if Int.equal n 0 then l else remove_n_fst_list (n-1) (List.tl l)
-let remove_n_last_list n l = List.rev (remove_n_fst_list n (List.rev l))
-
-let remove_last_n_arg n c =
- let (x,y) = decompose_prod c in
- let xnolast = remove_n_last_list n x in
- compose_prod xnolast y
-
-(* [funify_branches relinfo nfuns branch] returns the branch [branch]
- of the relinfo [relinfo] modified to fit in a functional principle.
- Things to do:
- - remove indargs from rel applications
- - replace *variables only* corresponding to function (recursive)
- results by the actual function application. *)
-let funify_branches relinfo nfuns branch =
- let mut_induct, induct =
- match relinfo.indref with
- | None -> assert false
- | Some (IndRef ((mutual_ind,i) as ind)) -> mutual_ind,ind
- | _ -> assert false in
- let is_dom c =
- match Constr.kind c with
- | Ind(((u,_),_)) | Construct(((u,_),_),_) -> MutInd.equal u mut_induct
- | _ -> false in
- let _dom_i c =
- assert (is_dom c);
- match Constr.kind c with
- | Ind((u,i)) | Construct((u,_),i) -> i
- | _ -> assert false in
- let _is_pred c shift =
- match Constr.kind c with
- | Rel i -> let reali = i-shift in (reali>=0 && reali<relinfo.nbranches)
- | _ -> false in
- (* FIXME: *)
- LocalDef (Anonymous,EConstr.mkProp,EConstr.mkProp)
-
-
-let relprinctype_to_funprinctype relprinctype nfuns =
- let relprinctype = EConstr.of_constr relprinctype in
- let relinfo = compute_elim_sig Evd.empty (** FIXME*) relprinctype in
- assert (not relinfo.farg_in_concl);
- assert (relinfo.indarg_in_concl);
- (* first remove indarg and indarg_in_concl *)
- let relinfo_noindarg = { relinfo with
- indarg_in_concl = false; indarg = None;
- concl = EConstr.of_constr (remove_last_arg (pop (EConstr.Unsafe.to_constr relinfo.concl))); } in
- (* the nfuns last induction arguments are functional ones: remove them *)
- let relinfo_argsok = { relinfo_noindarg with
- nargs = relinfo_noindarg.nargs - nfuns;
- (* args is in reverse order, so remove fst *)
- args = remove_n_fst_list nfuns relinfo_noindarg.args;
- concl = EConstr.of_constr (popn nfuns (EConstr.Unsafe.to_constr relinfo_noindarg.concl));
- } in
- let new_branches =
- List.map (funify_branches relinfo_argsok nfuns) relinfo_argsok.branches in
- let relinfo_branches = { relinfo_argsok with branches = new_branches } in
- relinfo_branches
-
-(* @article{ bundy93rippling,
- author = "Alan Bundy and Andrew Stevens and Frank van Harmelen and Andrew Ireland and Alan Smaill",
- title = "Rippling: A Heuristic for Guiding Inductive Proofs",
- journal = "Artificial Intelligence",
- volume = "62",
- number = "2",
- pages = "185-253",
- year = "1993",
- url = "citeseer.ist.psu.edu/bundy93rippling.html" }
-
- *)
diff --git a/plugins/funind/recdef.mli b/plugins/funind/recdef.mli
index 50b84731b..b95d64ce9 100644
--- a/plugins/funind/recdef.mli
+++ b/plugins/funind/recdef.mli
@@ -1,6 +1,5 @@
open Constr
-(* val evaluable_of_global_reference : Libnames.global_reference -> Names.evaluable_global_reference *)
val tclUSER_if_not_mes :
Tacmach.tactic ->
bool ->
diff --git a/plugins/funind/recdef_plugin.mlpack b/plugins/funind/recdef_plugin.mlpack
index 2b443f2a1..755fa4f87 100644
--- a/plugins/funind/recdef_plugin.mlpack
+++ b/plugins/funind/recdef_plugin.mlpack
@@ -6,5 +6,4 @@ Functional_principles_proofs
Functional_principles_types
Invfun
Indfun
-Merge
G_indfun
diff --git a/plugins/ltac/extratactics.ml4 b/plugins/ltac/extratactics.ml4
index cf5125757..3e3965b94 100644
--- a/plugins/ltac/extratactics.ml4
+++ b/plugins/ltac/extratactics.ml4
@@ -1125,3 +1125,12 @@ VERNAC COMMAND EXTEND OptimizeProof
| [ "Optimize" "Heap" ] => [ Vernac_classifier.classify_as_proofstep ] ->
[ Gc.compact () ]
END
+
+(** tactic analogous to "OPTIMIZE HEAP" *)
+
+let tclOPTIMIZE_HEAP =
+ Proofview.tclLIFT (Proofview.NonLogical.make (fun () -> Gc.compact ()))
+
+TACTIC EXTEND optimize_heap
+| [ "optimize_heap" ] -> [ tclOPTIMIZE_HEAP ]
+END
diff --git a/plugins/ltac/g_ltac.ml4 b/plugins/ltac/g_ltac.ml4
index ebf6e450b..cc7ce339b 100644
--- a/plugins/ltac/g_ltac.ml4
+++ b/plugins/ltac/g_ltac.ml4
@@ -327,7 +327,8 @@ GEXTEND Gram
| IDENT "all"; ":" -> SelectAll ] ]
;
tactic_mode:
- [ [ g = OPT toplevel_selector; tac = G_vernac.query_command -> tac g ] ]
+ [ [ g = OPT toplevel_selector; tac = G_vernac.query_command -> tac g
+ | g = OPT toplevel_selector; "{" -> Vernacexpr.VernacSubproof g ] ]
;
command:
[ [ IDENT "Proof"; "with"; ta = Pltac.tactic;
diff --git a/plugins/ltac/rewrite.ml b/plugins/ltac/rewrite.ml
index 3cbb11001..acd7a30c4 100644
--- a/plugins/ltac/rewrite.ml
+++ b/plugins/ltac/rewrite.ml
@@ -210,9 +210,9 @@ end) = struct
let t = Reductionops.whd_all env (goalevars evars) ty in
match EConstr.kind (goalevars evars) t, l with
| Prod (na, ty, b), obj :: cstrs ->
- let b = Reductionops.nf_betaiota (goalevars evars) b in
+ let b = Reductionops.nf_betaiota env (goalevars evars) b in
if noccurn (goalevars evars) 1 b (* non-dependent product *) then
- let ty = Reductionops.nf_betaiota (goalevars evars) ty in
+ let ty = Reductionops.nf_betaiota env (goalevars evars) ty in
let (evars, b', arg, cstrs) = aux env evars (subst1 mkProp b) cstrs in
let evars, relty = mk_relty evars env ty obj in
let evars, newarg = app_poly env evars respectful [| ty ; b' ; relty ; arg |] in
@@ -221,7 +221,7 @@ end) = struct
let (evars, b, arg, cstrs) =
aux (push_rel (LocalAssum (na, ty)) env) evars b cstrs
in
- let ty = Reductionops.nf_betaiota (goalevars evars) ty in
+ let ty = Reductionops.nf_betaiota env (goalevars evars) ty in
let pred = mkLambda (na, ty, b) in
let liftarg = mkLambda (na, ty, arg) in
let evars, arg' = app_poly env evars forall_relation [| ty ; pred ; liftarg |] in
@@ -231,7 +231,7 @@ end) = struct
| _, [] ->
(match finalcstr with
| None | Some (_, None) ->
- let t = Reductionops.nf_betaiota (fst evars) ty in
+ let t = Reductionops.nf_betaiota env (fst evars) ty in
let evars, rel = mk_relty evars env t None in
evars, t, rel, [t, Some rel]
| Some (t, Some rel) -> evars, t, rel, [t, Some rel])
@@ -1557,9 +1557,8 @@ let newfail n s =
let cl_rewrite_clause_newtac ?abs ?origsigma ~progress strat clause =
let open Proofview.Notations in
(** For compatibility *)
- let beta_red _ sigma c = Reductionops.nf_betaiota sigma c in
- let beta = Tactics.reduct_in_concl (beta_red, DEFAULTcast) in
- let beta_hyp id = Tactics.reduct_in_hyp beta_red (id, InHyp) in
+ let beta = Tactics.reduct_in_concl (Reductionops.nf_betaiota, DEFAULTcast) in
+ let beta_hyp id = Tactics.reduct_in_hyp Reductionops.nf_betaiota (id, InHyp) in
let treat sigma res =
match res with
| None -> newfail 0 (str "Nothing to rewrite")
diff --git a/plugins/omega/coq_omega.ml b/plugins/omega/coq_omega.ml
index 869284246..4271c80cd 100644
--- a/plugins/omega/coq_omega.ml
+++ b/plugins/omega/coq_omega.ml
@@ -652,7 +652,7 @@ let decompile af =
(** Backward compat to emulate the old Refine: normalize the goal conclusion *)
let new_hole env sigma c =
- let c = Reductionops.nf_betaiota sigma c in
+ let c = Reductionops.nf_betaiota env sigma c in
Evarutil.new_evar env sigma c
let clever_rewrite_base_poly typ p result theorem =
diff --git a/plugins/ssr/ssrcommon.ml b/plugins/ssr/ssrcommon.ml
index 8493dbdbb..7cdf05117 100644
--- a/plugins/ssr/ssrcommon.ml
+++ b/plugins/ssr/ssrcommon.ml
@@ -563,7 +563,7 @@ let pf_abs_evars_pirrel gl (sigma, c0) =
| _ -> Constr.fold put evlist c in
let evlist = put [] c0 in
if evlist = [] then 0, c0 else
- let pr_constr t = Printer.pr_econstr_env (pf_env gl) sigma (Reductionops.nf_beta (project gl) (EConstr.of_constr t)) in
+ let pr_constr t = Printer.pr_econstr_env (pf_env gl) sigma (Reductionops.nf_beta (pf_env gl) (project gl) (EConstr.of_constr t)) in
pp(lazy(str"evlist=" ++ pr_list (fun () -> str";")
(fun (k,_) -> Evar.print k) evlist));
let evplist =
@@ -894,7 +894,7 @@ let saturate ?(beta=false) ?(bi_types=false) env sigma c ?(ty=Retyping.get_type_
let sigma = create_evar_defs sigma in
let (sigma, x) =
Evarutil.new_evar env sigma
- (if bi_types then Reductionops.nf_betaiota sigma src else src) in
+ (if bi_types then Reductionops.nf_betaiota env sigma src else src) in
loop (EConstr.Vars.subst1 x tgt) ((m - n,x) :: args) sigma (n-1)
| CastType (t, _) -> loop t args sigma n
| LetInType (_, v, _, t) -> loop (EConstr.Vars.subst1 v t) args sigma n
diff --git a/plugins/ssr/ssrvernac.ml4 b/plugins/ssr/ssrvernac.ml4
index 4f530a0ae..d74ad06b3 100644
--- a/plugins/ssr/ssrvernac.ml4
+++ b/plugins/ssr/ssrvernac.ml4
@@ -551,9 +551,9 @@ GEXTEND Gram
| IDENT "Canonical"; qid = Constr.global;
d = G_vernac.def_body ->
let s = coerce_reference_to_id qid in
- Vernacexpr.VernacLocal(false,Vernacexpr.VernacDefinition
+ Vernacexpr.VernacDefinition
((Decl_kinds.NoDischarge,Decl_kinds.CanonicalStructure),
- ((Loc.tag s),None),(d )))
+ ((Loc.tag (Name s)),None), d)
]];
END
diff --git a/pretyping/arguments_renaming.ml b/pretyping/arguments_renaming.ml
index d59102b6c..8ac471404 100644
--- a/pretyping/arguments_renaming.ml
+++ b/pretyping/arguments_renaming.ml
@@ -40,16 +40,10 @@ let subst_rename_args (subst, (_, (r, names as orig))) =
let r' = fst (subst_global subst r) in
if r==r' then orig else (r', names)
-let section_segment_of_reference = function
- | ConstRef con -> Lib.section_segment_of_constant con
- | IndRef (kn,_) | ConstructRef ((kn,_),_) ->
- Lib.section_segment_of_mutual_inductive kn
- | _ -> [], Univ.LMap.empty, Univ.AUContext.empty
-
let discharge_rename_args = function
| _, (ReqGlobal (c, names), _ as req) ->
(try
- let vars,_,_ = section_segment_of_reference c in
+ let vars = Lib.variable_section_segment_of_reference c in
let c' = pop_global_reference c in
let var_names = List.map (fst %> NamedDecl.get_id %> Name.mk_name) vars in
let names' = var_names @ names in
diff --git a/pretyping/cases.ml b/pretyping/cases.ml
index 1207c967b..311c1c09e 100644
--- a/pretyping/cases.ml
+++ b/pretyping/cases.ml
@@ -1276,7 +1276,7 @@ let build_branch initial current realargs deps (realnames,curname) pb arsign eqn
(* This is a bit too strong I think, in the sense that what we would *)
(* really like is to have beta-iota reduction only at the positions where *)
(* parameters are substituted *)
- let typs = List.map (map_type (nf_betaiota !(pb.evdref))) typs in
+ let typs = List.map (map_type (nf_betaiota pb.env !(pb.evdref))) typs in
(* We build the matrix obtained by expanding the matching on *)
(* "C x1..xn as x" followed by a residual matching on eqn into *)
@@ -1426,7 +1426,7 @@ and match_current pb (initial,tomatch) =
find_predicate pb.caseloc pb.env pb.evdref
pred current indt (names,dep) tomatch in
let ci = make_case_info pb.env (fst mind) pb.casestyle in
- let pred = nf_betaiota !(pb.evdref) pred in
+ let pred = nf_betaiota pb.env !(pb.evdref) pred in
let case =
make_case_or_project pb.env !(pb.evdref) indf ci pred current brvals
in
@@ -1663,7 +1663,7 @@ let rec list_assoc_in_triple x = function
*)
let abstract_tycon ?loc env evdref subst tycon extenv t =
- let t = nf_betaiota !evdref t in (* it helps in some cases to remove K-redex*)
+ let t = nf_betaiota env !evdref t in (* it helps in some cases to remove K-redex*)
let src = match EConstr.kind !evdref t with
| Evar (evk,_) -> (Loc.tag ?loc @@ Evar_kinds.SubEvar evk)
| _ -> (Loc.tag ?loc @@ Evar_kinds.CasesType true) in
diff --git a/pretyping/cbv.ml b/pretyping/cbv.ml
index 192eca63b..e42576d95 100644
--- a/pretyping/cbv.ml
+++ b/pretyping/cbv.ml
@@ -171,7 +171,7 @@ let fixp_reducible flgs ((reci,i),_) stk =
let cofixp_reducible flgs _ stk =
if red_set flgs fCOFIX then
match stk with
- | (CASE _ | APP(_,CASE _)) -> true
+ | (CASE _ | PROJ _ | APP(_,CASE _) | APP(_,PROJ _)) -> true
| _ -> false
else
false
diff --git a/pretyping/constr_matching.ml b/pretyping/constr_matching.ml
index ec7c3077f..c3a221944 100644
--- a/pretyping/constr_matching.ml
+++ b/pretyping/constr_matching.ml
@@ -462,19 +462,21 @@ let sub_match ?(closed=true) env sigma pat c =
in
let sub = (env, c1) :: (env, hd) :: subargs env lc in
try_aux sub next_mk_ctx next
- | Fix (indx,(names,types,bodies)) ->
+ | Fix (indx,(names,types,bodies as recdefs)) ->
let nb_fix = Array.length types in
let next_mk_ctx le =
let (ntypes,nbodies) = CList.chop nb_fix le in
mk_ctx (mkFix (indx,(names, Array.of_list ntypes, Array.of_list nbodies))) in
- let sub = subargs env types @ subargs env bodies in
+ let env' = push_rec_types recdefs env in
+ let sub = subargs env types @ subargs env' bodies in
try_aux sub next_mk_ctx next
- | CoFix (i,(names,types,bodies)) ->
+ | CoFix (i,(names,types,bodies as recdefs)) ->
let nb_fix = Array.length types in
let next_mk_ctx le =
let (ntypes,nbodies) = CList.chop nb_fix le in
mk_ctx (mkCoFix (i,(names, Array.of_list ntypes, Array.of_list nbodies))) in
- let sub = subargs env types @ subargs env bodies in
+ let env' = push_rec_types recdefs env in
+ let sub = subargs env types @ subargs env' bodies in
try_aux sub next_mk_ctx next
| Proj (p,c') ->
begin try
diff --git a/pretyping/detyping.ml b/pretyping/detyping.ml
index 23993243f..754e88139 100644
--- a/pretyping/detyping.ml
+++ b/pretyping/detyping.ml
@@ -581,12 +581,7 @@ and detype_r d flags avoid env sigma t =
| Const (sp,u) -> GRef (ConstRef sp, detype_instance sigma u)
| Proj (p,c) ->
let noparams () =
- let pb = Environ.lookup_projection p (snd env) in
- let pars = pb.Declarations.proj_npars in
- let hole = DAst.make @@ GHole(Evar_kinds.InternalHole,Misctypes.IntroAnonymous,None) in
- let args = List.make pars hole in
- GApp (DAst.make @@ GRef (ConstRef (Projection.constant p), None),
- (args @ [detype d flags avoid env sigma c]))
+ GProj (p, detype d flags avoid env sigma c)
in
if fst flags || !Flags.in_debugger || !Flags.in_toplevel then
try noparams ()
@@ -1002,6 +997,13 @@ let rec subst_glob_constr subst = DAst.map (function
let r1' = subst_glob_constr subst r1 in
let k' = Miscops.smartmap_cast_type (subst_glob_constr subst) k in
if r1' == r1 && k' == k then raw else GCast (r1',k')
+
+ | GProj (p,c) as raw ->
+ let kn = Projection.constant p in
+ let b = Projection.unfolded p in
+ let kn' = subst_constant subst kn in
+ let c' = subst_glob_constr subst c in
+ if kn' == kn && c' == c then raw else GProj(Projection.make kn' b, c')
)
(* Utilities to transform kernel cases to simple pattern-matching problem *)
diff --git a/pretyping/evarconv.ml b/pretyping/evarconv.ml
index 788e4d268..dc3acbc3e 100644
--- a/pretyping/evarconv.ml
+++ b/pretyping/evarconv.ml
@@ -276,11 +276,6 @@ let rec ise_app_stack2 env f evd sk1 sk2 =
end
| _, _ -> (sk1,sk2), Success evd
-let push_rec_types pfix env =
- let (i, c, t) = pfix in
- let inj c = EConstr.Unsafe.to_constr c in
- push_rec_types (i, Array.map inj c, Array.map inj t) env
-
(* This function tries to unify 2 stacks element by element. It works
from the end to the beginning. If it unifies a non empty suffix of
stacks but not the entire stacks, the first part of the answer is
@@ -358,19 +353,7 @@ let exact_ise_stack2 env evd f sk1 sk2 =
let check_leq_inductives evd cumi u u' =
let u = EConstr.EInstance.kind evd u in
let u' = EConstr.EInstance.kind evd u' in
- let length_ind_instance =
- Univ.AUContext.size (Univ.ACumulativityInfo.univ_context cumi)
- in
- let ind_sbcst = Univ.ACumulativityInfo.subtyp_context cumi in
- if not ((length_ind_instance = Univ.Instance.length u) &&
- (length_ind_instance = Univ.Instance.length u')) then
- anomaly (Pp.str "Invalid inductive subtyping encountered!")
- else
- begin
- let comp_subst = (Univ.Instance.append u u') in
- let comp_cst = Univ.AUContext.instantiate comp_subst ind_sbcst in
- Evd.add_constraints evd comp_cst
- end
+ Evd.add_constraints evd (Reduction.get_cumulativity_constraints CUMUL cumi u u')
let rec evar_conv_x ts env evd pbty term1 term2 =
let term1 = whd_head_evar evd term1 in
diff --git a/pretyping/evardefine.ml b/pretyping/evardefine.ml
index b646a37f8..fd83795f5 100644
--- a/pretyping/evardefine.ml
+++ b/pretyping/evardefine.ml
@@ -28,8 +28,8 @@ let env_nf_evar sigma env =
let env_nf_betaiotaevar sigma env =
process_rel_context
- (fun d e ->
- push_rel (RelDecl.map_constr (fun c -> Reductionops.nf_betaiota sigma c) d) e) env
+ (fun d env ->
+ push_rel (RelDecl.map_constr (fun c -> Reductionops.nf_betaiota env sigma c) d) env) env
(****************************************)
(* Operations on value/type constraints *)
diff --git a/pretyping/glob_ops.ml b/pretyping/glob_ops.ml
index 093f1f0b6..a21137a05 100644
--- a/pretyping/glob_ops.ml
+++ b/pretyping/glob_ops.ml
@@ -133,8 +133,10 @@ let mk_glob_constr_eq f c1 c2 = match DAst.get c1, DAst.get c2 with
Miscops.intro_pattern_naming_eq nam1 nam2
| GCast (c1, t1), GCast (c2, t2) ->
f c1 c2 && cast_type_eq f t1 t2
+ | GProj (p1, t1), GProj (p2, t2) ->
+ Projection.equal p1 p2 && f t1 t2
| (GRef _ | GVar _ | GEvar _ | GPatVar _ | GApp _ | GLambda _ | GProd _ | GLetIn _ |
- GCases _ | GLetTuple _ | GIf _ | GRec _ | GSort _ | GHole _ | GCast _), _ -> false
+ GCases _ | GLetTuple _ | GIf _ | GRec _ | GSort _ | GHole _ | GCast _ | GProj _), _ -> false
let rec glob_constr_eq c = mk_glob_constr_eq glob_constr_eq c
@@ -180,6 +182,8 @@ let map_glob_constr_left_to_right f = DAst.map (function
let comp1 = f c in
let comp2 = Miscops.map_cast_type f k in
GCast (comp1,comp2)
+ | GProj (p,c) ->
+ GProj (p, f c)
| (GVar _ | GSort _ | GHole _ | GRef _ | GEvar _ | GPatVar _) as x -> x
)
@@ -212,6 +216,8 @@ let fold_glob_constr f acc = DAst.with_val (function
let acc = match k with
| CastConv t | CastVM t | CastNative t -> f acc t | CastCoerce -> acc in
f acc c
+ | GProj(_,c) ->
+ f acc c
| (GSort _ | GHole _ | GRef _ | GEvar _ | GPatVar _) -> acc
)
@@ -253,6 +259,8 @@ let fold_glob_constr_with_binders g f v acc = DAst.(with_val (function
let acc = match k with
| CastConv t | CastVM t | CastNative t -> f v acc t | CastCoerce -> acc in
f v acc c
+ | GProj(_,c) ->
+ f v acc c
| (GSort _ | GHole _ | GRef _ | GEvar _ | GPatVar _) -> acc))
let iter_glob_constr f = fold_glob_constr (fun () -> f) ()
diff --git a/pretyping/inductiveops.ml b/pretyping/inductiveops.ml
index 78e6bc6f1..275a079d5 100644
--- a/pretyping/inductiveops.ml
+++ b/pretyping/inductiveops.ml
@@ -84,7 +84,7 @@ let mis_is_recursive_subset listind rarg =
List.exists
(fun ra ->
match dest_recarg ra with
- | Mrec (_,i) -> Int.List.mem i listind
+ | Mrec (_,i) -> Int.List.mem i listind
| _ -> false) rvec
in
Array.exists one_is_rec (dest_subterms rarg)
@@ -361,20 +361,20 @@ let make_case_or_project env sigma indf ci pred c branches =
if (* dependent *) not (Vars.noccurn sigma 1 t) &&
not (has_dependent_elim mib) then
user_err ~hdr:"make_case_or_project"
- Pp.(str"Dependent case analysis not allowed" ++
- str" on inductive type " ++ Names.MutInd.print (fst ind))
+ Pp.(str"Dependent case analysis not allowed" ++
+ str" on inductive type " ++ Names.MutInd.print (fst ind))
in
let branch = branches.(0) in
let ctx, br = decompose_lam_n_assum sigma (Array.length ps) branch in
let n, subst =
List.fold_right
(fun decl (i, subst) ->
- match decl with
- | LocalAssum (na, t) ->
- let t = mkProj (Projection.make ps.(i) true, c) in
- (i + 1, t :: subst)
- | LocalDef (na, b, t) -> (i, Vars.substl subst b :: subst))
- ctx (0, [])
+ match decl with
+ | LocalAssum (na, t) ->
+ let t = mkProj (Projection.make ps.(i) true, c) in
+ (i + 1, t :: subst)
+ | LocalDef (na, b, t) -> (i, Vars.substl subst b :: subst))
+ ctx (0, [])
in Vars.substl subst br
(* substitution in a signature *)
@@ -511,25 +511,25 @@ let is_predicate_explicitly_dep env sigma pred arsign =
let pv' = whd_all env sigma pval in
match EConstr.kind sigma pv', arsign with
| Lambda (na,t,b), (LocalAssum _)::arsign ->
- srec (push_rel_assum (na, t) env) b arsign
+ srec (push_rel_assum (na, t) env) b arsign
| Lambda (na,_,t), _ ->
(* The following code has an impact on the introduction names
- given by the tactics "case" and "inversion": when the
- elimination is not dependent, "case" uses Anonymous for
- inductive types in Prop and names created by mkProd_name for
- inductive types in Set/Type while "inversion" uses anonymous
- for inductive types both in Prop and Set/Type !!
-
- Previously, whether names were created or not relied on
- whether the predicate created in Indrec.make_case_com had a
- dependent arity or not. To avoid different predicates
- printed the same in v8, all predicates built in indrec.ml
- got a dependent arity (Aug 2004). The new way to decide
- whether names have to be created or not is to use an
- Anonymous or Named variable to enforce the expected
- dependency status (of course, Anonymous implies non
- dependent, but not conversely).
+ given by the tactics "case" and "inversion": when the
+ elimination is not dependent, "case" uses Anonymous for
+ inductive types in Prop and names created by mkProd_name for
+ inductive types in Set/Type while "inversion" uses anonymous
+ for inductive types both in Prop and Set/Type !!
+
+ Previously, whether names were created or not relied on
+ whether the predicate created in Indrec.make_case_com had a
+ dependent arity or not. To avoid different predicates
+ printed the same in v8, all predicates built in indrec.ml
+ got a dependent arity (Aug 2004). The new way to decide
+ whether names have to be created or not is to use an
+ Anonymous or Named variable to enforce the expected
+ dependency status (of course, Anonymous implies non
+ dependent, but not conversely).
From Coq > 8.2, using or not the the effective dependency of
the predicate is parametrable! *)
@@ -600,15 +600,15 @@ let rec instantiate_universes env evdref scl is = function
let ctx,_ = Reduction.dest_arity env ty in
let u = Univ.Universe.make l in
let s =
- (* Does the sort of parameter [u] appear in (or equal)
+ (* Does the sort of parameter [u] appear in (or equal)
the sort of inductive [is] ? *)
if univ_level_mem l is then
scl (* constrained sort: replace by scl *)
else
(* unconstrained sort: replace by fresh universe *)
let evm, s = Evd.new_sort_variable Evd.univ_flexible !evdref in
- let evm = Evd.set_leq_sort env evm s (Sorts.sort_of_univ u) in
- evdref := evm; s
+ let evm = Evd.set_leq_sort env evm s (Sorts.sort_of_univ u) in
+ evdref := evm; s
in
(LocalAssum (na,mkArity(ctx,s))) :: instantiate_universes env evdref scl is (sign, exp)
| sign, [] -> sign (* Uniform parameters are exhausted *)
@@ -656,93 +656,3 @@ let control_only_guard env c =
iter_constr_with_full_binders push_rel iter env c
in
iter env c
-
-(* inference of subtyping condition for inductive types *)
-
-let infer_inductive_subtyping_arity_constructor
- (env, evd, csts) (subst : constr -> constr) (arcn : types) is_arity (params : Context.Rel.t) =
- let numchecked = ref 0 in
- let numparams = Context.Rel.nhyps params in
- let update_contexts (env, evd, csts) csts' =
- (Environ.add_constraints csts' env, Evd.add_constraints evd csts', Univ.Constraint.union csts csts')
- in
- let basic_check (env, evd, csts) tp =
- let result =
- if !numchecked >= numparams then
- let csts' =
- Reduction.infer_conv_leq ~evars:(Evd.existential_opt_value evd) env (Evd.universes evd) tp (subst tp)
- in update_contexts (env, evd, csts) csts'
- else
- (env, evd, csts)
- in
- numchecked := !numchecked + 1; result
- in
- let infer_typ typ ctxs =
- match typ with
- | LocalAssum (_, typ') ->
- begin
- try
- let (env, evd, csts) = basic_check ctxs typ' in (Environ.push_rel typ env, evd, csts)
- with Reduction.NotConvertible ->
- anomaly ~label:"inference of record/inductive subtyping relation failed"
- (Pp.str "Can't infer subtyping for record/inductive type")
- end
- | _ -> anomaly (Pp.str "")
- in
- let arcn' = Term.it_mkProd_or_LetIn arcn params in
- let typs, codom = Reduction.dest_prod env arcn' in
- let last_contexts = Context.Rel.fold_outside infer_typ typs ~init:(env, evd, csts) in
- if not is_arity then basic_check last_contexts codom else last_contexts
-
-let infer_inductive_subtyping env evd mind_ent =
- let { Entries.mind_entry_params = params;
- Entries.mind_entry_inds = entries;
- Entries.mind_entry_universes = ground_univs;
- } = mind_ent
- in
- let uinfind =
- match ground_univs with
- | Entries.Monomorphic_ind_entry _
- | Entries.Polymorphic_ind_entry _ -> ground_univs
- | Entries.Cumulative_ind_entry cumi ->
- begin
- let uctx = Univ.CumulativityInfo.univ_context cumi in
- let sbsubst = Univ.CumulativityInfo.subtyping_susbst cumi in
- let dosubst = subst_univs_level_constr sbsubst in
- let instance_other =
- Univ.subst_univs_level_instance sbsubst (Univ.UContext.instance uctx)
- in
- let constraints_other =
- Univ.subst_univs_level_constraints
- sbsubst (Univ.UContext.constraints uctx)
- in
- let uctx_other = Univ.UContext.make (instance_other, constraints_other) in
- let env = Environ.push_context uctx env in
- let env = Environ.push_context uctx_other env in
- let evd =
- Evd.merge_universe_context
- evd (UState.of_context_set (Univ.ContextSet.of_context uctx_other))
- in
- let (_, _, subtyp_constraints) =
- List.fold_left
- (fun ctxs indentry ->
- let _, params = Typeops.infer_local_decls env params in
- let ctxs' = infer_inductive_subtyping_arity_constructor
- ctxs dosubst indentry.Entries.mind_entry_arity true params
- in
- List.fold_left
- (fun ctxs cons ->
- infer_inductive_subtyping_arity_constructor
- ctxs dosubst cons false params
- )
- ctxs' indentry.Entries.mind_entry_lc
- ) (env, evd, Univ.Constraint.empty) entries
- in
- Entries.Cumulative_ind_entry
- (Univ.CumulativityInfo.make
- (Univ.CumulativityInfo.univ_context cumi,
- Univ.UContext.make
- (Univ.UContext.instance (Univ.CumulativityInfo.subtyp_context cumi),
- subtyp_constraints)))
- end
- in {mind_ent with Entries.mind_entry_universes = uinfind;}
diff --git a/pretyping/inductiveops.mli b/pretyping/inductiveops.mli
index 58b1ce6c3..55149552a 100644
--- a/pretyping/inductiveops.mli
+++ b/pretyping/inductiveops.mli
@@ -199,12 +199,3 @@ val type_of_inductive_knowing_conclusion :
(********************)
val control_only_guard : env -> types -> unit
-
-(* inference of subtyping condition for inductive types *)
-(* for debugging purposes only to be removed *)
-val infer_inductive_subtyping_arity_constructor : Environ.env * Evd.evar_map * Univ.Constraint.t ->
-(constr -> constr) ->
-types -> bool -> Context.Rel.t -> Environ.env * Evd.evar_map * Univ.Constraint.t
-
-val infer_inductive_subtyping : Environ.env -> Evd.evar_map -> Entries.mutual_inductive_entry ->
- Entries.mutual_inductive_entry
diff --git a/pretyping/inferCumulativity.ml b/pretyping/inferCumulativity.ml
new file mode 100644
index 000000000..a0a8276c5
--- /dev/null
+++ b/pretyping/inferCumulativity.ml
@@ -0,0 +1,224 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+open Reduction
+open Declarations
+open Constr
+open Univ
+open Util
+
+(** Throughout this module we modify a map [variances] from local
+ universes to [Variance.t]. It starts as a trivial mapping to
+ [Irrelevant] and every time we encounter a local universe we
+ restrict it accordingly. *)
+
+let infer_level_eq u variances =
+ if LMap.mem u variances
+ then LMap.set u Variance.Invariant variances
+ else variances
+
+let infer_level_leq u variances =
+ match LMap.find u variances with
+ | exception Not_found -> variances
+ | varu -> LMap.set u (Variance.sup varu Variance.Covariant) variances
+
+let infer_generic_instance_eq variances u =
+ Array.fold_left (fun variances u -> infer_level_eq u variances)
+ variances (Instance.to_array u)
+
+let variance_pb cv_pb var =
+ let open Variance in
+ match cv_pb, var with
+ | _, Irrelevant -> Irrelevant
+ | _, Invariant -> Invariant
+ | CONV, Covariant -> Invariant
+ | CUMUL, Covariant -> Covariant
+
+let infer_cumulative_ind_instance cv_pb cumi variances u =
+ Array.fold_left2 (fun variances varu u ->
+ match LMap.find u variances with
+ | exception Not_found -> variances
+ | varu' ->
+ LMap.set u (Variance.sup varu' (variance_pb cv_pb varu)) variances)
+ variances (ACumulativityInfo.variance cumi) (Instance.to_array u)
+
+let infer_inductive_instance cv_pb env variances ind nargs u =
+ let mind = Environ.lookup_mind (fst ind) env in
+ match mind.mind_universes with
+ | Monomorphic_ind _ -> assert (Instance.is_empty u); variances
+ | Polymorphic_ind _ -> infer_generic_instance_eq variances u
+ | Cumulative_ind cumi ->
+ if not (Int.equal (inductive_cumulativity_arguments (mind,snd ind)) nargs)
+ then infer_generic_instance_eq variances u
+ else infer_cumulative_ind_instance cv_pb cumi variances u
+
+let infer_constructor_instance_eq env variances ((mi,ind),ctor) nargs u =
+ let mind = Environ.lookup_mind mi env in
+ match mind.mind_universes with
+ | Monomorphic_ind _ -> assert (Instance.is_empty u); variances
+ | Polymorphic_ind _ -> infer_generic_instance_eq variances u
+ | Cumulative_ind cumi ->
+ if not (Int.equal (constructor_cumulativity_arguments (mind,ind,ctor)) nargs)
+ then infer_generic_instance_eq variances u
+ else infer_cumulative_ind_instance CONV cumi variances u
+
+let infer_sort cv_pb variances s =
+ match cv_pb with
+ | CONV ->
+ LSet.fold infer_level_eq (Universe.levels (Sorts.univ_of_sort s)) variances
+ | CUMUL ->
+ LSet.fold infer_level_leq (Universe.levels (Sorts.univ_of_sort s)) variances
+
+let infer_table_key infos variances c =
+ let open Names in
+ match c with
+ | ConstKey (_, u) ->
+ infer_generic_instance_eq variances u
+ | VarKey _ | RelKey _ -> variances
+
+let rec infer_fterm cv_pb infos variances hd stk =
+ Control.check_for_interrupt ();
+ let open CClosure in
+ let hd,stk = whd_stack infos hd stk in
+ match fterm_of hd with
+ | FAtom a ->
+ begin match kind a with
+ | Sort s -> infer_sort cv_pb variances s
+ | Meta _ -> infer_stack infos variances stk
+ | _ -> assert false
+ end
+ | FEvar ((_,args),e) ->
+ let variances = infer_stack infos variances stk in
+ infer_vect infos variances (Array.map (mk_clos e) args)
+ | FRel _ -> variances
+ | FFlex fl ->
+ let variances = infer_table_key infos variances fl in
+ infer_stack infos variances stk
+ | FProj (_,c) ->
+ let variances = infer_fterm CONV infos variances c [] in
+ infer_stack infos variances stk
+ | FLambda _ ->
+ let (_,ty,bd) = destFLambda mk_clos hd in
+ let variances = infer_fterm CONV infos variances ty [] in
+ infer_fterm CONV infos variances bd []
+ | FProd (_,dom,codom) ->
+ let variances = infer_fterm CONV infos variances dom [] in
+ infer_fterm cv_pb infos variances codom []
+ | FInd (ind, u) ->
+ let variances =
+ if Instance.is_empty u then variances
+ else
+ let nargs = stack_args_size stk in
+ infer_inductive_instance cv_pb (info_env infos) variances ind nargs u
+ in
+ infer_stack infos variances stk
+ | FConstruct (ctor,u) ->
+ let variances =
+ if Instance.is_empty u then variances
+ else
+ let nargs = stack_args_size stk in
+ infer_constructor_instance_eq (info_env infos) variances ctor nargs u
+ in
+ infer_stack infos variances stk
+ | FFix ((_,(_,tys,cl)),e) | FCoFix ((_,(_,tys,cl)),e) ->
+ let n = Array.length cl in
+ let variances = infer_vect infos variances (Array.map (mk_clos e) tys) in
+ let le = Esubst.subs_liftn n e in
+ let variances = infer_vect infos variances (Array.map (mk_clos le) cl) in
+ infer_stack infos variances stk
+
+ (* Removed by whnf *)
+ | FLOCKED | FCaseT _ | FCast _ | FLetIn _ | FApp _ | FLIFT _ | FCLOS _ -> assert false
+
+and infer_stack infos variances (stk:CClosure.stack) =
+ match stk with
+ | [] -> variances
+ | z :: stk ->
+ let open CClosure in
+ let variances = match z with
+ | Zapp v -> infer_vect infos variances v
+ | Zproj _ -> variances
+ | Zfix (fx,a) ->
+ let variances = infer_fterm CONV infos variances fx [] in
+ infer_stack infos variances a
+ | ZcaseT (ci,p,br,e) ->
+ let variances = infer_fterm CONV infos variances (mk_clos e p) [] in
+ infer_vect infos variances (Array.map (mk_clos e) br)
+ | Zshift _ -> variances
+ | Zupdate _ -> variances
+ in
+ infer_stack infos variances stk
+
+and infer_vect infos variances v =
+ Array.fold_left (fun variances c -> infer_fterm CONV infos variances c []) variances v
+
+let infer_term cv_pb env variances c =
+ let open CClosure in
+ let reds = RedFlags.red_add_transparent betaiotazeta Names.full_transparent_state in
+ let infos = create_clos_infos reds env in
+ infer_fterm cv_pb infos variances (CClosure.inject c) []
+
+let infer_arity_constructor env variances arcn is_arity params =
+ let numchecked = ref 0 in
+ let numparams = Context.Rel.nhyps params in
+ let basic_check env variances tp =
+ let variances =
+ if !numchecked >= numparams then
+ infer_term CUMUL env variances tp
+ else
+ variances
+ in
+ numchecked := !numchecked + 1; variances
+ in
+ let infer_typ typ (env,variances) =
+ match typ with
+ | Context.Rel.Declaration.LocalAssum (_, typ') ->
+ (Environ.push_rel typ env, basic_check env variances typ')
+ | Context.Rel.Declaration.LocalDef _ -> assert false
+ in
+ let arcn' = Term.it_mkProd_or_LetIn arcn params in
+ let typs, codom = Reduction.dest_prod env arcn' in
+ let env, variances = Context.Rel.fold_outside infer_typ typs ~init:(env, variances) in
+ (* If we have Inductive foo@{i j} : ... -> Type@{i} := C : ... -> foo Type@{j}
+ i is irrelevant, j is invariant. *)
+ if not is_arity then basic_check env variances codom else variances
+
+let infer_inductive env mie =
+ let open Entries in
+ let { mind_entry_params = params;
+ mind_entry_inds = entries; } = mie
+ in
+ let univs =
+ match mie.mind_entry_universes with
+ | Monomorphic_ind_entry _
+ | Polymorphic_ind_entry _ as univs -> univs
+ | Cumulative_ind_entry cumi ->
+ let uctx = CumulativityInfo.univ_context cumi in
+ let uarray = Instance.to_array @@ UContext.instance uctx in
+ let env = Environ.push_context uctx env in
+ let variances =
+ Array.fold_left (fun variances u -> LMap.add u Variance.Irrelevant variances)
+ LMap.empty uarray
+ in
+ let variances = List.fold_left (fun variances entry ->
+ let _, params = Typeops.infer_local_decls env params in
+ let variances = infer_arity_constructor
+ env variances entry.mind_entry_arity true params
+ in
+ List.fold_left
+ (fun variances cons ->
+ infer_arity_constructor
+ env variances cons false params)
+ variances entry.mind_entry_lc)
+ variances
+ entries
+ in
+ let variances = Array.map (fun u -> LMap.find u variances) uarray in
+ Cumulative_ind_entry (CumulativityInfo.make (uctx, variances))
+ in
+ { mie with mind_entry_universes = univs }
diff --git a/pretyping/inferCumulativity.mli b/pretyping/inferCumulativity.mli
new file mode 100644
index 000000000..a5037ea47
--- /dev/null
+++ b/pretyping/inferCumulativity.mli
@@ -0,0 +1,10 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+val infer_inductive : Environ.env -> Entries.mutual_inductive_entry ->
+ Entries.mutual_inductive_entry
diff --git a/pretyping/nativenorm.ml b/pretyping/nativenorm.ml
index 79e0afa72..b41e15f5a 100644
--- a/pretyping/nativenorm.ml
+++ b/pretyping/nativenorm.ml
@@ -224,7 +224,7 @@ and nf_accu env sigma accu =
if Int.equal (accu_nargs accu) 0 then nf_atom env sigma atom
else
let a,typ = nf_atom_type env sigma atom in
- let _, args = nf_args env sigma accu typ in
+ let _, args = nf_args env sigma (args_of_accu accu) typ in
mkApp(a,Array.of_list args)
and nf_accu_type env sigma accu =
@@ -232,10 +232,10 @@ and nf_accu_type env sigma accu =
if Int.equal (accu_nargs accu) 0 then nf_atom_type env sigma atom
else
let a,typ = nf_atom_type env sigma atom in
- let t, args = nf_args env sigma accu typ in
+ let t, args = nf_args env sigma (args_of_accu accu) typ in
mkApp(a,Array.of_list args), t
-and nf_args env sigma accu t =
+and nf_args env sigma args t =
let aux arg (t,l) =
let _,dom,codom =
try decompose_prod env t with
@@ -246,7 +246,7 @@ and nf_args env sigma accu t =
let c = nf_val env sigma arg dom in
(subst1 c codom, c::l)
in
- let t,l = List.fold_right aux (args_of_accu accu) (t,[]) in
+ let t,l = Array.fold_right aux args (t,[]) in
t, List.rev l
and nf_bargs env sigma b t =
@@ -277,7 +277,6 @@ and nf_atom env sigma atom =
let codom = nf_type env sigma (codom vn) in
mkProd(n,dom,codom)
| Ameta (mv,_) -> mkMeta mv
- | Aevar (ev,_) -> mkEvar ev
| Aproj(p,c) ->
let c = nf_accu env sigma c in
mkProj(Projection.make p true,c)
@@ -347,9 +346,9 @@ and nf_atom_type env sigma atom =
let env = push_rel (LocalAssum (n,dom)) env in
let codom,s2 = nf_type_sort env sigma (codom vn) in
mkProd(n,dom,codom), Typeops.type_of_product env n s1 s2
- | Aevar(ev,ty) ->
- let ty = nf_type env sigma ty in
- mkEvar ev, ty
+ | Aevar(evk,ty,args) ->
+ let ty = nf_type env sigma ty in
+ nf_evar env sigma evk ty args
| Ameta(mv,ty) ->
let ty = nf_type env sigma ty in
mkMeta mv, ty
@@ -386,6 +385,19 @@ and nf_predicate env sigma ind mip params v pT =
true, mkLambda(name,dom,body)
| _, _ -> false, nf_type env sigma v
+and nf_evar env sigma evk ty args =
+ let evi = try Evd.find sigma evk with Not_found -> assert false in
+ let hyps = Environ.named_context_of_val (Evd.evar_filtered_hyps evi) in
+ if List.is_empty hyps then begin
+ assert (Int.equal (Array.length args) 0);
+ mkEvar (evk, [||]), ty
+ end
+ else
+ let fold accu d = Term.mkNamedProd_or_LetIn d accu in
+ let t = List.fold_left fold ty hyps in
+ let ty, args = nf_args env sigma args t in
+ mkEvar (evk, Array.of_list args), ty
+
let evars_of_evar_map sigma =
{ Nativelambda.evars_val = Evd.existential_opt_value sigma;
Nativelambda.evars_typ = Evd.existential_type sigma;
diff --git a/pretyping/patternops.ml b/pretyping/patternops.ml
index 41e09004c..1bec4a6f1 100644
--- a/pretyping/patternops.ml
+++ b/pretyping/patternops.ml
@@ -137,8 +137,7 @@ let rec head_pattern_bound t =
| PCase (_,p,c,br) -> head_pattern_bound c
| PRef r -> r
| PVar id -> VarRef id
- | PProj (p,c) -> ConstRef (Projection.constant p)
- | PEvar _ | PRel _ | PMeta _ | PSoApp _ | PSort _ | PFix _
+ | PEvar _ | PRel _ | PMeta _ | PSoApp _ | PSort _ | PFix _ | PProj _
-> raise BoundPattern
(* Perhaps they were arguments, but we don't beta-reduce *)
| PLambda _ -> raise BoundPattern
@@ -446,6 +445,9 @@ let rec pat_of_raw metas vars = DAst.with_loc_val (fun ?loc -> function
one non-trivial branch. These facts are used in [Constrextern]. *)
PCase (info, pred, pat_of_raw metas vars c, brs)
+ | GProj(p,c) ->
+ PProj(p, pat_of_raw metas vars c)
+
| GPatVar _ | GIf _ | GLetTuple _ | GCases _ | GEvar _ | GRec _ ->
err ?loc (Pp.str "Non supported pattern."))
diff --git a/pretyping/pretyping.ml b/pretyping/pretyping.ml
index b930c5db8..8809558ff 100644
--- a/pretyping/pretyping.ml
+++ b/pretyping/pretyping.ml
@@ -70,7 +70,7 @@ let get_extra env sigma =
let ids = List.map get_id (named_context env) in
let avoid = List.fold_right Id.Set.add ids Id.Set.empty in
Context.Rel.fold_outside (fun d acc -> push_rel_decl_to_named_context sigma d acc)
- (rel_context env) ~init:(empty_csubst, [], avoid, named_context env)
+ (rel_context env) ~init:(empty_csubst, avoid, named_context env)
let make_env env sigma = { env = env; extra = lazy (get_extra env sigma) }
let rel_context env = rel_context env.env
@@ -90,12 +90,11 @@ let push_rel_context sigma ctx env = {
let lookup_named id env = lookup_named id env.env
let e_new_evar env evdref ?src ?naming typ =
- let subst2 subst vsubst c = csubst_subst subst (replace_vars vsubst c) in
let open Context.Named.Declaration in
let inst_vars = List.map (get_id %> mkVar) (named_context env.env) in
let inst_rels = List.rev (rel_list 0 (nb_rel env.env)) in
- let (subst, vsubst, _, nc) = Lazy.force env.extra in
- let typ' = subst2 subst vsubst typ in
+ let (subst, _, nc) = Lazy.force env.extra in
+ let typ' = csubst_subst subst typ in
let instance = inst_rels @ inst_vars in
let sign = val_of_named_context nc in
let sigma = !evdref in
@@ -738,6 +737,11 @@ let rec pretype k0 resolve_tc (tycon : type_constraint) (env : ExtraEnv.t) evdre
let j = pretype_sort ?loc evdref s in
inh_conv_coerce_to_tycon ?loc env evdref j tycon
+ | GProj (p, c) ->
+ (* TODO: once GProj is used as an input syntax, use bidirectional typing here *)
+ let cj = pretype empty_tycon env evdref lvar c in
+ judge_of_projection env.ExtraEnv.env !evdref p cj
+
| GApp (f,args) ->
let fj = pretype empty_tycon env evdref lvar f in
let floc = loc_of_glob_constr f in
diff --git a/pretyping/pretyping.mllib b/pretyping/pretyping.mllib
index 1da5b4567..ae4ad0be7 100644
--- a/pretyping/pretyping.mllib
+++ b/pretyping/pretyping.mllib
@@ -4,6 +4,7 @@ Locusops
Pretype_errors
Reductionops
Inductiveops
+InferCumulativity
Vnorm
Arguments_renaming
Nativenorm
diff --git a/pretyping/recordops.ml b/pretyping/recordops.ml
index 9ff9a75b3..ab1f3cd32 100644
--- a/pretyping/recordops.ml
+++ b/pretyping/recordops.ml
@@ -298,29 +298,40 @@ let add_canonical_structure x = Lib.add_anonymous_leaf (inCanonStruc x)
(*s High-level declaration of a canonical structure *)
-let error_not_structure ref =
+let error_not_structure ref description =
user_err ~hdr:"object_declare"
- (Id.print (basename_of_global ref) ++ str" is not a structure object.")
+ (str"Could not declare a canonical structure " ++
+ (Id.print (basename_of_global ref) ++ str"." ++ spc() ++
+ str(description)))
let check_and_decompose_canonical_structure ref =
- let sp = match ref with ConstRef sp -> sp | _ -> error_not_structure ref in
+ let sp =
+ match ref with
+ ConstRef sp -> sp
+ | _ -> error_not_structure ref "Expected an instance of a record or structure."
+ in
let env = Global.env () in
let u = Univ.make_abstract_instance (Environ.constant_context env sp) in
let vc = match Environ.constant_opt_value_in env (sp, u) with
| Some vc -> vc
- | None -> error_not_structure ref in
+ | None -> error_not_structure ref "Could not find its value in the global environment." in
let body = snd (splay_lam (Global.env()) Evd.empty (EConstr.of_constr vc)) (** FIXME *) in
let body = EConstr.Unsafe.to_constr body in
let f,args = match kind body with
| App (f,args) -> f,args
- | _ -> error_not_structure ref in
+ | _ ->
+ error_not_structure ref "Expected a record or structure constructor applied to arguments." in
let indsp = match kind f with
| Construct ((indsp,1),u) -> indsp
- | _ -> error_not_structure ref in
- let s = try lookup_structure indsp with Not_found -> error_not_structure ref in
+ | _ -> error_not_structure ref "Expected an instance of a record or structure." in
+ let s =
+ try lookup_structure indsp
+ with Not_found ->
+ error_not_structure ref
+ ("Could not find the record or structure " ^ (MutInd.to_string (fst indsp))) in
let ntrue_projs = List.count snd s.s_PROJKIND in
if s.s_EXPECTEDPARAM + ntrue_projs > Array.length args then
- error_not_structure ref;
+ error_not_structure ref "Got too few arguments to the record or structure constructor.";
(sp,indsp)
let declare_canonical_structure ref =
diff --git a/pretyping/reductionops.ml b/pretyping/reductionops.ml
index ac8846854..418ea271c 100644
--- a/pretyping/reductionops.ml
+++ b/pretyping/reductionops.ml
@@ -121,10 +121,10 @@ module ReductionBehaviour = struct
let r' = fst (subst_global subst r) in if r==r' then orig else (r',o)
let discharge = function
- | _,(ReqGlobal (ConstRef c, req), (_, b)) ->
+ | _,(ReqGlobal (ConstRef c as gr, req), (_, b)) ->
let b =
- if Lib.is_in_section (ConstRef c) then
- let vars, _, _ = Lib.section_segment_of_constant c in
+ if Lib.is_in_section gr then
+ let vars = Lib.variable_section_segment_of_reference gr in
let extra = List.length vars in
let nargs' =
if b.b_nargs = max_int then max_int
@@ -1241,9 +1241,9 @@ let clos_whd_flags flgs env sigma t =
(CClosure.inject (EConstr.Unsafe.to_constr t)))
with e when is_anomaly e -> user_err Pp.(str "Tried to normalize ill-typed term")
-let nf_beta = clos_norm_flags CClosure.beta (Global.env ())
-let nf_betaiota = clos_norm_flags CClosure.betaiota (Global.env ())
-let nf_betaiotazeta = clos_norm_flags CClosure.betaiotazeta (Global.env ())
+let nf_beta = clos_norm_flags CClosure.beta
+let nf_betaiota = clos_norm_flags CClosure.betaiota
+let nf_betaiotazeta = clos_norm_flags CClosure.betaiotazeta
let nf_all env sigma =
clos_norm_flags CClosure.all env sigma
@@ -1324,79 +1324,17 @@ let sigma_compare_instances ~flex i0 i1 sigma =
| Univ.UniverseInconsistency _ ->
raise Reduction.NotConvertible
-let sigma_check_inductive_instances cv_pb uinfind u u' sigma =
- let len_instance =
- Univ.AUContext.size (Univ.ACumulativityInfo.univ_context uinfind)
- in
- let ind_sbctx = Univ.ACumulativityInfo.subtyp_context uinfind in
- if not ((len_instance = Univ.Instance.length u) &&
- (len_instance = Univ.Instance.length u')) then
- anomaly (Pp.str "Invalid inductive subtyping encountered!")
- else
- let comp_cst =
- let comp_subst = (Univ.Instance.append u u') in
- Univ.AUContext.instantiate comp_subst ind_sbctx
- in
- let comp_cst =
- match cv_pb with
- Reduction.CONV ->
- let comp_subst = (Univ.Instance.append u' u) in
- let comp_cst' = Univ.AUContext.instantiate comp_subst ind_sbctx in
- Univ.Constraint.union comp_cst comp_cst'
- | Reduction.CUMUL -> comp_cst
- in
- try Evd.add_constraints sigma comp_cst
- with Evd.UniversesDiffer
- | Univ.UniverseInconsistency _ ->
- raise Reduction.NotConvertible
-
-let sigma_conv_inductives
- cv_pb (mind, ind) u1 sv1 u2 sv2 sigma =
- try sigma_compare_instances ~flex:false u1 u2 sigma with
- Reduction.NotConvertible ->
- match mind.Declarations.mind_universes with
- | Declarations.Monomorphic_ind _ ->
- raise Reduction.NotConvertible
- | Declarations.Polymorphic_ind _ ->
- raise Reduction.NotConvertible
- | Declarations.Cumulative_ind cumi ->
- let num_param_arity =
- mind.Declarations.mind_nparams +
- mind.Declarations.mind_packets.(ind).Declarations.mind_nrealargs
- in
- if not (num_param_arity = sv1 && num_param_arity = sv2) then
- raise Reduction.NotConvertible
- else
- sigma_check_inductive_instances cv_pb cumi u1 u2 sigma
-
-let sigma_conv_constructors
- (mind, ind, cns) u1 sv1 u2 sv2 sigma =
- try sigma_compare_instances ~flex:false u1 u2 sigma with
- Reduction.NotConvertible ->
- match mind.Declarations.mind_universes with
- | Declarations.Monomorphic_ind _ ->
- raise Reduction.NotConvertible
- | Declarations.Polymorphic_ind _ ->
- raise Reduction.NotConvertible
- | Declarations.Cumulative_ind cumi ->
- let num_cnstr_args =
- let nparamsctxt =
- mind.Declarations.mind_nparams +
- mind.Declarations.mind_packets.(ind).Declarations.mind_nrealargs
- in
- nparamsctxt +
- mind.Declarations.mind_packets.(ind).Declarations.mind_consnrealargs.(cns - 1)
- in
- if not (num_cnstr_args = sv1 && num_cnstr_args = sv2) then
- raise Reduction.NotConvertible
- else
- sigma_check_inductive_instances Reduction.CONV cumi u1 u2 sigma
+let sigma_check_inductive_instances csts sigma =
+ try Evd.add_constraints sigma csts
+ with Evd.UniversesDiffer
+ | Univ.UniverseInconsistency _ ->
+ raise Reduction.NotConvertible
let sigma_univ_state =
- { Reduction.compare = sigma_compare_sorts;
- Reduction.compare_instances = sigma_compare_instances;
- Reduction.conv_inductives = sigma_conv_inductives;
- Reduction.conv_constructors = sigma_conv_constructors}
+ let open Reduction in
+ { compare_sorts = sigma_compare_sorts;
+ compare_instances = sigma_compare_instances;
+ compare_cumul_instances = sigma_check_inductive_instances; }
let infer_conv_gen conv_fun ?(catch_incon=true) ?(pb=Reduction.CUMUL)
?(ts=full_transparent_state) env sigma x y =
diff --git a/pretyping/reductionops.mli b/pretyping/reductionops.mli
index a277864c9..0565baf45 100644
--- a/pretyping/reductionops.mli
+++ b/pretyping/reductionops.mli
@@ -168,9 +168,9 @@ val clos_norm_flags : CClosure.RedFlags.reds -> reduction_function
val clos_whd_flags : CClosure.RedFlags.reds -> reduction_function
(** Same as [(strong whd_beta[delta][iota])], but much faster on big terms *)
-val nf_beta : local_reduction_function
-val nf_betaiota : local_reduction_function
-val nf_betaiotazeta : local_reduction_function
+val nf_beta : reduction_function
+val nf_betaiota : reduction_function
+val nf_betaiotazeta : reduction_function
val nf_all : reduction_function
val nf_evar : evar_map -> constr -> constr
diff --git a/pretyping/tacred.ml b/pretyping/tacred.ml
index 5a522e06a..9b9408698 100644
--- a/pretyping/tacred.ml
+++ b/pretyping/tacred.ml
@@ -60,9 +60,7 @@ let value_of_evaluable_ref env evref u =
match evref with
| EvalConstRef con ->
let u = Unsafe.to_instance u in
- EConstr.of_constr (try constant_value_in env (con,u)
- with NotEvaluableConst IsProj ->
- raise (Invalid_argument "value_of_evaluable_ref"))
+ EConstr.of_constr (constant_value_in env (con, u))
| EvalVarRef id -> env |> lookup_named id |> NamedDecl.get_value |> Option.get
let evaluable_of_global_reference env = function
@@ -476,7 +474,7 @@ let contract_fix_use_function env sigma f
let nbodies = Array.length recindices in
let make_Fi j = (mkFix((recindices,j),typedbodies), f j) in
let lbodies = List.init nbodies make_Fi in
- substl_checking_arity env (List.rev lbodies) sigma (nf_beta sigma bodies.(bodynum))
+ substl_checking_arity env (List.rev lbodies) sigma (nf_beta env sigma bodies.(bodynum))
let reduce_fix_use_function env sigma f whfun fix stack =
match fix_recarg fix (Stack.append_app_list stack Stack.empty) with
@@ -500,7 +498,7 @@ let contract_cofix_use_function env sigma f
let make_Fi j = (mkCoFix(j,typedbodies), f j) in
let subbodies = List.init nbodies make_Fi in
substl_checking_arity env (List.rev subbodies)
- sigma (nf_beta sigma bodies.(bodynum))
+ sigma (nf_beta env sigma bodies.(bodynum))
let reduce_mind_case_use_function func env sigma mia =
match EConstr.kind sigma mia.mconstr with
@@ -697,7 +695,7 @@ let rec red_elim_const env sigma ref u largs =
let whfun = whd_construct_stack env sigma in
(match reduce_fix_use_function env sigma f whfun (destFix sigma d) lrest with
| NotReducible -> raise Redelimination
- | Reduced (c,rest) -> (nf_beta sigma c, rest), nocase)
+ | Reduced (c,rest) -> (nf_beta env sigma c, rest), nocase)
| EliminationMutualFix (min,refgoal,refinfos) when nargs >= min ->
let rec descend (ref,u) args =
let c = reference_value env sigma ref u in
@@ -712,7 +710,7 @@ let rec red_elim_const env sigma ref u largs =
let whfun = whd_construct_stack env sigma in
(match reduce_fix_use_function env sigma f whfun (destFix sigma d) lrest with
| NotReducible -> raise Redelimination
- | Reduced (c,rest) -> (nf_beta sigma c, rest), nocase)
+ | Reduced (c,rest) -> (nf_beta env sigma c, rest), nocase)
| NotAnElimination when unfold_nonelim ->
let c = reference_value env sigma ref u in
(whd_betaiotazeta sigma (applist (c, largs)), []), nocase
@@ -1103,7 +1101,7 @@ let unfoldoccs env sigma (occs,name) c =
| [] -> ()
| _ -> error_invalid_occurrence rest
in
- nf_betaiotazeta sigma uc
+ nf_betaiotazeta env sigma uc
in
match occs with
| NoOccurrences -> c
@@ -1284,7 +1282,7 @@ let reduce_to_ref_gen allow_product env sigma ref t =
else raise Not_found
with Not_found ->
try
- let t' = nf_betaiota sigma (one_step_reduce env sigma t) in
+ let t' = nf_betaiota env sigma (one_step_reduce env sigma t) in
elimrec env t' l
with NotStepReducible -> error_cannot_recognize ref
in
diff --git a/pretyping/typeclasses.ml b/pretyping/typeclasses.ml
index f153b6341..3f947fd23 100644
--- a/pretyping/typeclasses.ml
+++ b/pretyping/typeclasses.ml
@@ -219,7 +219,8 @@ let discharge_class (_,cl) =
in grs', discharge_rel_context subst 1 ctx @ ctx' in
let cl_impl' = Lib.discharge_global cl.cl_impl in
if cl_impl' == cl.cl_impl then cl else
- let ctx, _, _ as info = abs_context cl in
+ let info = abs_context cl in
+ let ctx = info.Lib.abstr_ctx in
let ctx, subst = rel_of_variable_context ctx in
let usubst, cl_univs' = Lib.discharge_abstract_universe_context info cl.cl_univs in
let context = discharge_context ctx (subst, usubst) cl.cl_context in
diff --git a/pretyping/typing.ml b/pretyping/typing.ml
index 43066c809..3132d2ad5 100644
--- a/pretyping/typing.ml
+++ b/pretyping/typing.ml
@@ -23,11 +23,6 @@ open Arguments_renaming
open Pretype_errors
open Context.Rel.Declaration
-let push_rec_types pfix env =
- let (i, c, t) = pfix in
- let inj c = EConstr.Unsafe.to_constr c in
- push_rec_types (i, Array.map inj c, Array.map inj t) env
-
let meta_type evd mv =
let ty =
try Evd.meta_ftype evd mv
diff --git a/pretyping/typing.mli b/pretyping/typing.mli
index 9f084ae8d..153a48a71 100644
--- a/pretyping/typing.mli
+++ b/pretyping/typing.mli
@@ -53,3 +53,4 @@ val judge_of_abstraction : Environ.env -> Name.t ->
unsafe_type_judgment -> unsafe_judgment -> unsafe_judgment
val judge_of_product : Environ.env -> Name.t ->
unsafe_type_judgment -> unsafe_type_judgment -> unsafe_judgment
+val judge_of_projection : env -> evar_map -> projection -> unsafe_judgment -> unsafe_judgment
diff --git a/pretyping/unification.ml b/pretyping/unification.ml
index b41fb4e4d..e1720ec95 100644
--- a/pretyping/unification.ml
+++ b/pretyping/unification.ml
@@ -6,8 +6,6 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-module CVars = Vars
-
open CErrors
open Pp
open Util
@@ -196,7 +194,7 @@ let pose_all_metas_as_evars env evd t =
let ty = if Evd.Metaset.is_empty mvs then ty else aux ty in
let ty =
if Flags.version_strictly_greater Flags.V8_6 || Flags.version_less_or_equal Flags.VOld
- then nf_betaiota evd ty (* How it was in Coq <= 8.4 (but done in logic.ml at this time) *)
+ then nf_betaiota env evd ty (* How it was in Coq <= 8.4 (but done in logic.ml at this time) *)
else ty (* some beta-iota-normalization "regression" in 8.5 and 8.6 *) in
let src = Evd.evar_source_of_meta mv !evdref in
let ev = Evarutil.e_new_evar env evdref ~src ty in
@@ -1279,7 +1277,7 @@ let w_coerce env evd mv c =
let unify_to_type env sigma flags c status u =
let sigma, c = refresh_universes (Some false) env sigma c in
let t = get_type_of env sigma (nf_meta sigma c) in
- let t = nf_betaiota sigma (nf_meta sigma t) in
+ let t = nf_betaiota env sigma (nf_meta sigma t) in
unify_0 env sigma CUMUL flags t u
let unify_type env sigma flags mv status c =
@@ -1527,7 +1525,7 @@ let indirectly_dependent sigma c d decls =
let finish_evar_resolution ?(flags=Pretyping.all_and_fail_flags) env current_sigma (pending,c) =
let sigma = Pretyping.solve_remaining_evars flags env current_sigma pending in
let sigma, subst = nf_univ_variables sigma in
- (sigma, EConstr.of_constr (CVars.subst_univs_constr subst (EConstr.Unsafe.to_constr (nf_evar sigma c))))
+ (sigma, EConstr.of_constr (Universes.subst_univs_constr subst (EConstr.Unsafe.to_constr (nf_evar sigma c))))
let default_matching_core_flags sigma =
let ts = Names.full_transparent_state in {
@@ -1617,7 +1615,7 @@ let make_pattern_test from_prefix_of_ind is_correct_type env sigma (pending,c) =
| Some (sigma,_,l) ->
let c = applist (nf_evar sigma (local_strong whd_meta sigma c), l) in
let univs, subst = nf_univ_variables sigma in
- Some (sigma,EConstr.of_constr (CVars.subst_univs_constr subst (EConstr.Unsafe.to_constr c))))
+ Some (sigma,EConstr.of_constr (Universes.subst_univs_constr subst (EConstr.Unsafe.to_constr c))))
let make_eq_test env evd c =
let out cstr =
diff --git a/pretyping/vnorm.ml b/pretyping/vnorm.ml
index e395bdbc6..c93b41786 100644
--- a/pretyping/vnorm.ml
+++ b/pretyping/vnorm.ml
@@ -15,6 +15,7 @@ open Vars
open Environ
open Inductive
open Reduction
+open Vmvalues
open Vm
open Context.Rel.Declaration
@@ -134,7 +135,7 @@ let build_case_type dep p realargs c =
(* La fonction de normalisation *)
-let rec nf_val env sigma v t = nf_whd env sigma (whd_val v) t
+let rec nf_val env sigma v t = nf_whd env sigma (Vmvalues.whd_val v) t
and nf_vtype env sigma v = nf_val env sigma v crazy_type
@@ -144,7 +145,7 @@ and nf_whd env sigma whd typ =
| Vprod p ->
let dom = nf_vtype env sigma (dom p) in
let name = Name (Id.of_string "x") in
- let vc = body_of_vfun (nb_rel env) (codom p) in
+ let vc = reduce_fun (nb_rel env) (codom p) in
let codom = nf_vtype (push_rel (LocalAssum (name,dom)) env) sigma vc in
mkProd(name,dom,codom)
| Vfun f -> nf_fun env sigma f typ
@@ -191,7 +192,7 @@ and nf_univ_args ~nb_univs mk env sigma stk =
else match stk with
| Zapp args :: _ ->
let inst =
- Array.init nb_univs (fun i -> Vm.uni_lvl_val (arg args i))
+ Array.init nb_univs (fun i -> uni_lvl_val (arg args i))
in
Univ.Instance.of_array inst
| _ -> assert false
@@ -239,8 +240,9 @@ and nf_stk ?from:(from=0) env sigma c t stk =
let (mib,mip) = Inductive.lookup_mind_specif env ind in
let nparams = mib.mind_nparams in
let params,realargs = Util.Array.chop nparams allargs in
+ let nparamdecls = Context.Rel.length (Inductive.inductive_paramdecls (mib,u)) in
let pT =
- hnf_prod_applist env (type_of_ind env (ind,u)) (Array.to_list params) in
+ hnf_prod_applist_assum env nparamdecls (type_of_ind env (ind,u)) (Array.to_list params) in
let pT = whd_all env pT in
let dep, p = nf_predicate env sigma (ind,u) mip params (type_of_switch sw) pT in
(* Calcul du type des branches *)
@@ -254,7 +256,7 @@ and nf_stk ?from:(from=0) env sigma c t stk =
in
let branchs = Array.mapi mkbranch bsw in
let tcase = build_case_type dep p realargs c in
- let ci = case_info sw in
+ let ci = sw.sw_annot.Cbytecodes.ci in
nf_stk env sigma (mkCase(ci, p, c, branchs)) tcase stk
| Zproj p :: stk ->
assert (from = 0) ;
@@ -266,14 +268,14 @@ and nf_predicate env sigma ind mip params v pT =
match whd_val v, kind pT with
| Vfun f, Prod _ ->
let k = nb_rel env in
- let vb = body_of_vfun k f in
+ let vb = reduce_fun k f in
let name,dom,codom = decompose_prod env pT in
let dep,body =
nf_predicate (push_rel (LocalAssum (name,dom)) env) sigma ind mip params vb codom in
dep, mkLambda(name,dom,body)
| Vfun f, _ ->
let k = nb_rel env in
- let vb = body_of_vfun k f in
+ let vb = reduce_fun k f in
let name = Name (Id.of_string "c") in
let n = mip.mind_nrealargs in
let rargs = Array.init n (fun i -> mkRel (n-i)) in
@@ -307,7 +309,7 @@ and nf_bargs env sigma b ofs t =
and nf_fun env sigma f typ =
let k = nb_rel env in
- let vb = body_of_vfun k f in
+ let vb = reduce_fun k f in
let name,dom,codom =
try decompose_prod env typ
with DestKO ->
diff --git a/printing/ppconstr.ml b/printing/ppconstr.ml
index 51735bc9e..1146b42a0 100644
--- a/printing/ppconstr.ml
+++ b/printing/ppconstr.ml
@@ -732,6 +732,9 @@ let tag_var = tag Tag.variable
return (pr_prim_token p, prec_of_prim_token p)
| CDelimiters (sc,a) ->
return (pr_delimiters sc (pr mt (ldelim,E) a), ldelim)
+ | CProj (p,c) ->
+ let p = pr_proj (pr mt) pr_app c (CAst.make (CRef (p,None))) [] in
+ return (p, lproj)
in
let loc = constr_loc a in
pr_with_comments ?loc
diff --git a/printing/ppvernac.ml b/printing/ppvernac.ml
index e88284fb1..950246c53 100644
--- a/printing/ppvernac.ml
+++ b/printing/ppvernac.ml
@@ -31,12 +31,6 @@ open Decl_kinds
let pr_lconstr = pr_lconstr_expr
let pr_spc_lconstr = pr_sep_com spc pr_lconstr_expr
- let pr_lident (loc,id) =
- match loc with
- | None -> pr_id id
- | Some loc -> let (b,_) = Loc.unloc loc in
- pr_located pr_id @@ Loc.tag ~loc:(Loc.make_loc (b,b + String.length (Id.to_string id))) id
-
let pr_uconstraint (l, d, r) =
pr_glob_level l ++ spc () ++ Univ.pr_constraint_type d ++ spc () ++
pr_glob_level r
@@ -77,9 +71,8 @@ open Decl_kinds
| Some loc -> let (b,_) = Loc.unloc loc in
pr_located pr_fqid @@ Loc.tag ~loc:(Loc.make_loc (b,b + String.length (string_of_fqid fqid))) fqid
- let pr_lname = function
- | (loc,Name id) -> pr_lident (loc,id)
- | lna -> pr_located Name.print lna
+ let pr_lname_decl (n, u) =
+ pr_lname n ++ pr_universe_decl u
let pr_smart_global = Pputils.pr_or_by_notation pr_reference
@@ -91,7 +84,7 @@ open Decl_kinds
let sep_end = function
| VernacBullet _
- | VernacSubproof None
+ | VernacSubproof _
| VernacEndSubproof -> str""
| _ -> str"."
@@ -398,8 +391,6 @@ open Decl_kinds
++ prlist (pr_decl_notation pr_constr) ntn
let pr_statement head (idpl,(bl,c)) =
- assert (not (Option.is_empty idpl));
- let idpl = Option.get idpl in
hov 2
(head ++ spc() ++ pr_ident_decl idpl ++ spc() ++
(match bl with [] -> mt() | _ -> pr_binders bl ++ spc()) ++
@@ -535,17 +526,25 @@ open Decl_kinds
| SsFwdClose e -> "("^aux e^")*"
in Pp.str (aux e)
- let rec pr_vernac_expr v =
+ let pr_extend s cl =
+ let pr_arg a =
+ try pr_gen a
+ with Failure _ -> str "<error in " ++ str (fst s) ++ str ">" in
+ try
+ let rl = Egramml.get_extend_vernac_rule s in
+ let rec aux rl cl =
+ match rl, cl with
+ | Egramml.GramNonTerminal _ :: rl, arg :: cl -> pr_arg arg :: aux rl cl
+ | Egramml.GramTerminal s :: rl, cl -> str s :: aux rl cl
+ | [], [] -> []
+ | _ -> assert false in
+ hov 1 (pr_sequence identity (aux rl cl))
+ with Not_found ->
+ hov 1 (str "TODO(" ++ str (fst s) ++ spc () ++ prlist_with_sep sep pr_arg cl ++ str ")")
+
+ let pr_vernac_expr v =
let return = tag_vernac v in
match v with
- | VernacPolymorphic (poly, v) ->
- let s = if poly then keyword "Polymorphic" else keyword "Monomorphic" in
- return (s ++ spc () ++ pr_vernac_expr v)
- | VernacProgram v ->
- return (keyword "Program" ++ spc() ++ pr_vernac_expr v)
- | VernacLocal (local, v) ->
- return (pr_locality local ++ spc() ++ pr_vernac_expr v)
-
| VernacLoad (f,s) ->
return (
keyword "Load"
@@ -564,8 +563,6 @@ open Decl_kinds
return (keyword "Unfocus")
| VernacUnfocused ->
return (keyword "Unfocused")
- | VernacGoal c ->
- return (keyword "Goal" ++ pr_lconstrarg c)
| VernacAbort id ->
return (keyword "Abort" ++ pr_opt pr_lident id)
| VernacUndo i ->
@@ -676,7 +673,10 @@ open Decl_kinds
(* Gallina *)
| VernacDefinition ((discharge,kind),id,b) -> (* A verifier... *)
let pr_def_token dk =
- keyword (Kindops.string_of_definition_object_kind dk)
+ keyword (
+ if Name.is_anonymous (snd (fst id))
+ then "Goal"
+ else Kindops.string_of_definition_object_kind dk)
in
let pr_reduce = function
| None -> mt()
@@ -693,12 +693,13 @@ open Decl_kinds
in
(pr_binders_arg bl,ty,Some (pr_reduce red ++ pr_lconstr body))
| ProveBody (bl,t) ->
- (pr_binders_arg bl, str" :" ++ pr_spc_lconstr t, None) in
+ let typ u = if snd (fst id) = Anonymous then (assert (bl = []); u) else (str" :" ++ u) in
+ (pr_binders_arg bl, typ (pr_spc_lconstr t), None) in
let (binds,typ,c) = pr_def_body b in
return (
hov 2 (
pr_def_token kind ++ spc()
- ++ pr_ident_decl id ++ binds ++ typ
+ ++ pr_lname_decl id ++ binds ++ typ
++ (match c with
| None -> mt()
| Some cc -> str" :=" ++ spc() ++ cc))
@@ -1199,30 +1200,25 @@ open Decl_kinds
| VernacSubproof None ->
return (str "{")
| VernacSubproof (Some i) ->
- return (keyword "BeginSubproof" ++ spc () ++ int i)
+ return (Proof_bullet.pr_goal_selector i ++ str ":" ++ spc () ++ str "{")
| VernacEndSubproof ->
return (str "}")
- and pr_extend s cl =
- let pr_arg a =
- try pr_gen a
- with Failure _ -> str "<error in " ++ str (fst s) ++ str ">" in
- try
- let rl = Egramml.get_extend_vernac_rule s in
- let rec aux rl cl =
- match rl, cl with
- | Egramml.GramNonTerminal _ :: rl, arg :: cl -> pr_arg arg :: aux rl cl
- | Egramml.GramTerminal s :: rl, cl -> str s :: aux rl cl
- | [], [] -> []
- | _ -> assert false in
- hov 1 (pr_sequence identity (aux rl cl))
- with Not_found ->
- hov 1 (str "TODO(" ++ str (fst s) ++ spc () ++ prlist_with_sep sep pr_arg cl ++ str ")")
+let pr_vernac_flag =
+ function
+ | VernacPolymorphic true -> keyword "Polymorphic"
+ | VernacPolymorphic false -> keyword "Monomorphic"
+ | VernacProgram -> keyword "Program"
+ | VernacLocal local -> pr_locality local
let rec pr_vernac_control v =
let return = tag_vernac v in
match v with
- | VernacExpr v' -> pr_vernac_expr v' ++ sep_end v'
+ | VernacExpr (f, v') ->
+ List.fold_right
+ (fun f a -> pr_vernac_flag f ++ spc() ++ a)
+ f
+ (pr_vernac_expr v' ++ sep_end v')
| VernacTime (_,(_,v)) ->
return (keyword "Time" ++ spc() ++ pr_vernac_control v)
| VernacRedirect (s, (_,v)) ->
diff --git a/printing/prettyp.ml b/printing/prettyp.ml
index 2b7886d11..114a071ee 100644
--- a/printing/prettyp.ml
+++ b/printing/prettyp.ml
@@ -78,6 +78,15 @@ let print_ref reduce ref udecl =
in EConstr.it_mkProd_or_LetIn ccl ctx
else typ in
let univs = Global.universes_of_global ref in
+ let variance = match ref with
+ | VarRef _ | ConstRef _ -> None
+ | IndRef (ind,_) | ConstructRef ((ind,_),_) ->
+ let mind = Environ.lookup_mind ind (Global.env ()) in
+ begin match mind.Declarations.mind_universes with
+ | Declarations.Monomorphic_ind _ | Declarations.Polymorphic_ind _ -> None
+ | Declarations.Cumulative_ind cumi -> Some (Univ.ACumulativityInfo.variance cumi)
+ end
+ in
let inst = Univ.AUContext.instance univs in
let univs = Univ.UContext.make (inst, Univ.AUContext.instantiate inst univs) in
let env = Global.env () in
@@ -89,7 +98,7 @@ let print_ref reduce ref udecl =
else mt ()
in
hov 0 (pr_global ref ++ inst ++ str " :" ++ spc () ++ pr_letype_env env sigma typ ++
- Printer.pr_universe_ctx sigma univs)
+ Printer.pr_universe_ctx sigma ?variance univs)
(********************************)
(** Printing implicit arguments *)
diff --git a/printing/printer.ml b/printing/printer.ml
index a63004ceb..d720bc2f8 100644
--- a/printing/printer.ml
+++ b/printing/printer.ml
@@ -263,10 +263,10 @@ let pr_universe_ctx_set sigma c =
else
mt()
-let pr_universe_ctx sigma c =
+let pr_universe_ctx sigma ?variance c =
if !Detyping.print_universes && not (Univ.UContext.is_empty c) then
fnl()++pr_in_comment (fun c -> v 0
- (Univ.pr_universe_context (Termops.pr_evd_level sigma) c)) c
+ (Univ.pr_universe_context (Termops.pr_evd_level sigma) ?variance c)) c
else
mt()
diff --git a/printing/printer.mli b/printing/printer.mli
index 804014745..a3427920a 100644
--- a/printing/printer.mli
+++ b/printing/printer.mli
@@ -120,7 +120,8 @@ val pr_sort : evar_map -> Sorts.t -> Pp.t
val pr_polymorphic : bool -> Pp.t
val pr_cumulative : bool -> bool -> Pp.t
val pr_universe_instance : evar_map -> Univ.UContext.t -> Pp.t
-val pr_universe_ctx : evar_map -> Univ.UContext.t -> Pp.t
+val pr_universe_ctx : evar_map -> ?variance:Univ.Variance.t array ->
+ Univ.UContext.t -> Pp.t
val pr_universe_ctx_set : evar_map -> Univ.ContextSet.t -> Pp.t
val pr_constant_universes : evar_map -> Entries.constant_universes_entry -> Pp.t
val pr_cumulativity_info : evar_map -> Univ.CumulativityInfo.t -> Pp.t
diff --git a/printing/printmod.ml b/printing/printmod.ml
index fb9d45a79..2cdb9be3f 100644
--- a/printing/printmod.ml
+++ b/printing/printmod.ml
@@ -93,10 +93,11 @@ let print_one_inductive env sigma mib ((_,i) as ind) =
else Univ.Instance.empty in
let mip = mib.mind_packets.(i) in
let params = Inductive.inductive_paramdecls (mib,u) in
+ let nparamdecls = Context.Rel.length params in
let args = Context.Rel.to_extended_list mkRel 0 params in
- let arity = hnf_prod_applist env (build_ind_type env ((mib,mip),u)) args in
+ let arity = hnf_prod_applist_assum env nparamdecls (build_ind_type env ((mib,mip),u)) args in
let cstrtypes = Inductive.type_of_constructors (ind,u) (mib,mip) in
- let cstrtypes = Array.map (fun c -> hnf_prod_applist env c args) cstrtypes in
+ let cstrtypes = Array.map (fun c -> hnf_prod_applist_assum env nparamdecls c args) cstrtypes in
let envpar = push_rel_context params env in
let inst =
if Declareops.inductive_is_polymorphic mib then
@@ -113,13 +114,12 @@ let print_one_inductive env sigma mib ((_,i) as ind) =
let instantiate_cumulativity_info cumi =
let open Univ in
let univs = ACumulativityInfo.univ_context cumi in
- let subtyp = ACumulativityInfo.subtyp_context cumi in
let expose ctx =
let inst = AUContext.instance ctx in
let cst = AUContext.instantiate inst ctx in
UContext.make (inst, cst)
in
- CumulativityInfo.make (expose univs, expose subtyp)
+ CumulativityInfo.make (expose univs, ACumulativityInfo.variance cumi)
let print_mutual_inductive env mind mib udecl =
let inds = List.init (Array.length mib.mind_packets) (fun x -> (mind, x))
@@ -174,10 +174,11 @@ let print_record env mind mib udecl =
in
let mip = mib.mind_packets.(0) in
let params = Inductive.inductive_paramdecls (mib,u) in
+ let nparamdecls = Context.Rel.length params in
let args = Context.Rel.to_extended_list mkRel 0 params in
- let arity = hnf_prod_applist env (build_ind_type env ((mib,mip),u)) args in
+ let arity = hnf_prod_applist_assum env nparamdecls (build_ind_type env ((mib,mip),u)) args in
let cstrtypes = Inductive.type_of_constructors ((mind,0),u) (mib,mip) in
- let cstrtype = hnf_prod_applist env cstrtypes.(0) args in
+ let cstrtype = hnf_prod_applist_assum env nparamdecls cstrtypes.(0) args in
let fields = get_fields cstrtype in
let envpar = push_rel_context params env in
let bl = Universes.universe_binders_with_opt_names (IndRef (mind,0))
diff --git a/proofs/clenv.ml b/proofs/clenv.ml
index 16798a1d5..9e06d913b 100644
--- a/proofs/clenv.ml
+++ b/proofs/clenv.ml
@@ -498,7 +498,7 @@ let clenv_unify_binding_type clenv c t u =
let clenv_assign_binding clenv k c =
let k_typ = clenv_hnf_constr clenv (clenv_meta_type clenv k) in
- let c_typ = nf_betaiota clenv.evd (clenv_get_type_of clenv c) in
+ let c_typ = nf_betaiota clenv.env clenv.evd (clenv_get_type_of clenv c) in
let status,clenv',c = clenv_unify_binding_type clenv c c_typ k_typ in
let c = EConstr.Unsafe.to_constr c in
{ clenv' with evd = meta_assign k (c,(Conv,status)) clenv'.evd }
diff --git a/proofs/logic.ml b/proofs/logic.ml
index 1d86a0909..5ff5fa38a 100644
--- a/proofs/logic.ml
+++ b/proofs/logic.ml
@@ -334,7 +334,7 @@ let rec mk_refgoals sigma goal goalacc conclty trm =
else
match kind trm with
| Meta _ ->
- let conclty = nf_betaiota sigma (EConstr.of_constr conclty) in
+ let conclty = nf_betaiota env sigma (EConstr.of_constr conclty) in
if !check && occur_meta sigma conclty then
raise (RefinerError (env, sigma, MetaInType conclty));
let (gl,ev,sigma) = mk_goal hyps conclty in
@@ -416,7 +416,7 @@ and mk_hdgoals sigma goal goalacc trm =
match kind trm with
| Cast (c,_, ty) when isMeta c ->
check_typability env sigma ty;
- let (gl,ev,sigma) = mk_goal hyps (nf_betaiota sigma (EConstr.of_constr ty)) in
+ let (gl,ev,sigma) = mk_goal hyps (nf_betaiota env sigma (EConstr.of_constr ty)) in
let ev = EConstr.Unsafe.to_constr ev in
gl::goalacc,ty,sigma,ev
diff --git a/proofs/proof_global.ml b/proofs/proof_global.ml
index 167d6bda0..fc94a1013 100644
--- a/proofs/proof_global.ml
+++ b/proofs/proof_global.ml
@@ -343,16 +343,15 @@ let close_proof ~keep_body_ucst_separate ?feedback_id ~now
if poly || now then
let make_body t (c, eff) =
let body = c in
- let typ =
- if not (keep_body_ucst_separate || not (Safe_typing.empty_private_constants = eff)) then
- nf t
- else t
+ let allow_deferred =
+ not poly && (keep_body_ucst_separate ||
+ not (Safe_typing.empty_private_constants = eff))
in
+ let typ = if allow_deferred then t else nf t in
let env = Global.env () in
let used_univs_body = Univops.universes_of_constr env body in
let used_univs_typ = Univops.universes_of_constr env typ in
- if keep_body_ucst_separate ||
- not (Safe_typing.empty_private_constants = eff) then
+ if allow_deferred then
let initunivs = UState.const_univ_entry ~poly initial_euctx in
let ctx = constrain_variables universes in
(* For vi2vo compilation proofs are computed now but we need to
@@ -486,7 +485,10 @@ let update_global_env () =
(* XXX: Bullet hook, should be really moved elsewhere *)
let _ =
let hook n =
- let prf = give_me_the_proof () in
- (Proof_bullet.suggest prf) in
+ try
+ let prf = give_me_the_proof () in
+ (Proof_bullet.suggest prf)
+ with NoCurrentProof -> mt ()
+ in
Proofview.set_nosuchgoals_hook hook
diff --git a/proofs/tacmach.ml b/proofs/tacmach.ml
index d41541251..bdcb4868b 100644
--- a/proofs/tacmach.ml
+++ b/proofs/tacmach.ml
@@ -87,7 +87,7 @@ let pf_e_reduce = pf_apply
let pf_whd_all = pf_reduce whd_all
let pf_hnf_constr = pf_reduce hnf_constr
let pf_nf = pf_reduce simpl
-let pf_nf_betaiota = pf_reduce (fun _ -> nf_betaiota)
+let pf_nf_betaiota = pf_reduce nf_betaiota
let pf_compute = pf_reduce compute
let pf_unfoldn ubinds = pf_reduce (unfoldn ubinds)
let pf_unsafe_type_of = pf_reduce unsafe_type_of
diff --git a/stm/asyncTaskQueue.mli b/stm/asyncTaskQueue.mli
index 07689389f..706d36e1d 100644
--- a/stm/asyncTaskQueue.mli
+++ b/stm/asyncTaskQueue.mli
@@ -71,7 +71,7 @@ module type Task = sig
(** Extra arguments of the task kind, for -toploop *)
val extra_env : unit -> string array
- (** {5} Master API, it is run by the master, on a thread *)
+ (** {5 Master API, it is run by the master, on a thread} *)
(** [request_of_task status t] takes the [status] of the worker
and a task [t] and creates the corresponding [Some request] to be
@@ -116,8 +116,8 @@ module type Task = sig
(** [forward_feedback fb] sends fb to all the workers. *)
val forward_feedback : Feedback.feedback -> unit
- (** {5} Worker API, it is run by worker, on a different fresh
- process *)
+ (** {5 Worker API, it is run by worker, on a different fresh
+ process} *)
(** [perform in] synchronously processes a request [in] *)
val perform : request -> response
diff --git a/stm/proofBlockDelimiter.ml b/stm/proofBlockDelimiter.ml
index 01b5b9a01..bebc4d5d5 100644
--- a/stm/proofBlockDelimiter.ml
+++ b/stm/proofBlockDelimiter.ml
@@ -96,7 +96,7 @@ let dynamic_bullet doc { dynamic_switch = id; carry_on_data = b } =
`ValidBlock {
base_state = id;
goals_to_admit = focused;
- recovery_command = Some (Vernacexpr.VernacExpr(Vernacexpr.VernacBullet (to_bullet_val b)))
+ recovery_command = Some (Vernacexpr.VernacExpr([], Vernacexpr.VernacBullet (to_bullet_val b)))
}
| `Not -> `Leaks
@@ -125,7 +125,7 @@ let dynamic_curly_brace doc { dynamic_switch = id } =
`ValidBlock {
base_state = id;
goals_to_admit = focused;
- recovery_command = Some (Vernacexpr.VernacExpr Vernacexpr.VernacEndSubproof)
+ recovery_command = Some (Vernacexpr.VernacExpr ([], Vernacexpr.VernacEndSubproof))
}
| `Not -> `Leaks
diff --git a/stm/proofworkertop.ml b/stm/proofworkertop.ml
index 10b42f7e9..def60d1b9 100644
--- a/stm/proofworkertop.ml
+++ b/stm/proofworkertop.ml
@@ -10,5 +10,5 @@ module W = AsyncTaskQueue.MakeWorker(Stm.ProofTask) ()
let () = Coqtop.toploop_init := WorkerLoop.loop W.init_stdout
-let () = Coqtop.toploop_run := (fun _ -> W.main_loop ())
+let () = Coqtop.toploop_run := (fun _ _ -> W.main_loop ())
diff --git a/stm/queryworkertop.ml b/stm/queryworkertop.ml
index a1fe50c63..928a6bfb0 100644
--- a/stm/queryworkertop.ml
+++ b/stm/queryworkertop.ml
@@ -10,5 +10,5 @@ module W = AsyncTaskQueue.MakeWorker(Stm.QueryTask) ()
let () = Coqtop.toploop_init := WorkerLoop.loop W.init_stdout
-let () = Coqtop.toploop_run := (fun _ -> W.main_loop ())
+let () = Coqtop.toploop_run := (fun _ _ -> W.main_loop ())
diff --git a/stm/stm.ml b/stm/stm.ml
index 7045df0ed..6c956e134 100644
--- a/stm/stm.ml
+++ b/stm/stm.ml
@@ -26,31 +26,50 @@ open Vernacexpr
module AsyncOpts = struct
- let async_proofs_n_workers = ref 1
- let async_proofs_n_tacworkers = ref 2
-
type cache = Force
- let async_proofs_cache : cache option ref = ref None
-
type async_proofs = APoff | APonLazy | APon
- let async_proofs_mode = ref APoff
+ type tac_error_filter = [ `None | `Only of string list | `All ]
- let async_proofs_private_flags = ref None
- let async_proofs_full = ref false
- let async_proofs_never_reopen_branch = ref false
+ type stm_opt = {
+ async_proofs_n_workers : int;
+ async_proofs_n_tacworkers : int;
- type tac_error_filter = [ `None | `Only of string list | `All ]
- let async_proofs_tac_error_resilience = ref (`Only [ "curly" ])
- let async_proofs_cmd_error_resilience = ref true
+ async_proofs_cache : cache option;
+ async_proofs_mode : async_proofs;
+
+ async_proofs_private_flags : string option;
+ async_proofs_full : bool;
+ async_proofs_never_reopen_branch : bool;
- let async_proofs_delegation_threshold = ref 0.03
+ async_proofs_tac_error_resilience : tac_error_filter;
+ async_proofs_cmd_error_resilience : bool;
+ async_proofs_delegation_threshold : float;
+ }
+ let default_opts = {
+ async_proofs_n_workers = 1;
+ async_proofs_n_tacworkers = 2;
+
+ async_proofs_cache = None;
+
+ async_proofs_mode = APoff;
+
+ async_proofs_private_flags = None;
+ async_proofs_full = false;
+ async_proofs_never_reopen_branch = false;
+
+ async_proofs_tac_error_resilience = `Only [ "curly" ];
+ async_proofs_cmd_error_resilience = true;
+ async_proofs_delegation_threshold = 0.03;
+ }
+
+ let cur_opt = ref default_opts
end
open AsyncOpts
-let async_proofs_is_master () =
- !async_proofs_mode = APon &&
+let async_proofs_is_master opt =
+ opt.async_proofs_mode = APon &&
!Flags.async_proofs_worker_id = "master"
(* Protect against state changes *)
@@ -66,8 +85,7 @@ let stm_purify f x =
Exninfo.iraise e
let execution_error ?loc state_id msg =
- feedback ~id:state_id
- (Message (Error, loc, msg))
+ feedback ~id:state_id (Message (Error, loc, msg))
module Hooks = struct
@@ -547,8 +565,8 @@ end = struct (* {{{ *)
let reachable id = reachable !vcs id
let mk_branch_name { expr = x } = Branch.make
(match Vernacprop.under_control x with
- | VernacDefinition (_,((_,i),_),_) -> Id.to_string i
- | VernacStartTheoremProof (_,[Some ((_,i),_),_]) -> Id.to_string i
+ | VernacDefinition (_,((_, Name i),_),_) -> Id.to_string i
+ | VernacStartTheoremProof (_,[((_,i),_),_]) -> Id.to_string i
| _ -> "branch")
let edit_branch = Branch.make "edit"
let branch ?root ?pos name kind = vcs := branch !vcs ?root ?pos name kind
@@ -558,7 +576,7 @@ end = struct (* {{{ *)
| None -> raise Vcs_aux.Expired
let set_state id s =
(get_info id).state <- s;
- if async_proofs_is_master () then Hooks.(call state_ready id)
+ if async_proofs_is_master !cur_opt then Hooks.(call state_ready id)
let get_state id = (get_info id).state
let reached id =
let info = get_info id in
@@ -1150,7 +1168,7 @@ end = struct (* {{{ *)
" the \"-async-proofs-cache force\" option to Coq."))
let undo_vernac_classifier v =
- if VCS.is_interactive () = `No && !async_proofs_cache <> Some Force
+ if VCS.is_interactive () = `No && !cur_opt.async_proofs_cache <> Some Force
then undo_costly_in_batch_mode v;
try
match Vernacprop.under_control v with
@@ -1286,7 +1304,7 @@ let prev_node { id } =
let cur_node id = mk_doc_node id (VCS.visit id)
let is_block_name_enabled name =
- match !async_proofs_tac_error_resilience with
+ match !cur_opt.async_proofs_tac_error_resilience with
| `None -> false
| `All -> true
| `Only l -> List.mem name l
@@ -1294,7 +1312,7 @@ let is_block_name_enabled name =
let detect_proof_block id name =
let name = match name with None -> "indent" | Some x -> x in
if is_block_name_enabled name &&
- (async_proofs_is_master () || Flags.async_proofs_is_worker ())
+ (async_proofs_is_master !cur_opt || Flags.async_proofs_is_worker ())
then (
match cur_node id with
| None -> ()
@@ -1396,7 +1414,7 @@ end = struct (* {{{ *)
let task_match age t =
match age, t with
| Fresh, BuildProof { t_states } ->
- not !async_proofs_full ||
+ not !cur_opt.async_proofs_full ||
List.exists (fun x -> CList.mem_f Stateid.equal x !perspective) t_states
| Old my_states, States l ->
List.for_all (fun x -> CList.mem_f Stateid.equal x my_states) l
@@ -1433,7 +1451,7 @@ end = struct (* {{{ *)
feedback (InProgress ~-1);
t_assign (`Val pl);
record_pb_time ?loc:t_loc t_name time;
- if !async_proofs_full || t_drop
+ if !cur_opt.async_proofs_full || t_drop
then `Stay(t_states,[States t_states])
else `End
| Fresh, BuildProof { t_assign; t_loc; t_name; t_states },
@@ -1498,7 +1516,7 @@ end = struct (* {{{ *)
stm_vernac_interp stop
~proof:(pobject, terminator) st
{ verbose = false; loc; indentation = 0; strlen = 0;
- expr = VernacExpr (VernacEndProof (Proved (Opaque,None))) }) in
+ expr = VernacExpr ([], VernacEndProof (Proved (Opaque,None))) }) in
ignore(Future.join checked_proof);
end;
(* STATE: Restore the state XXX: handle exn *)
@@ -1560,12 +1578,13 @@ end = struct (* {{{ *)
| ReqStates sl -> RespStates (perform_states sl)
let on_marshal_error s = function
- | States _ -> msg_error(Pp.strbrk("Marshalling error: "^s^". "^
- "The system state could not be sent to the master process."))
+ | States _ ->
+ msg_warning Pp.(strbrk("Marshalling error: "^s^". "^
+ "The system state could not be sent to the master process."))
| BuildProof { t_exn_info; t_stop; t_assign; t_loc; t_drop = drop_pt } ->
- msg_error(Pp.strbrk("Marshalling error: "^s^". "^
- "The system state could not be sent to the worker process. "^
- "Falling back to local, lazy, evaluation."));
+ msg_warning Pp.(strbrk("Marshalling error: "^s^". "^
+ "The system state could not be sent to the worker process. "^
+ "Falling back to local, lazy, evaluation."));
t_assign(`Comp(build_proof_here ?loc:t_loc ~drop_pt t_exn_info t_stop));
feedback (InProgress ~-1)
@@ -1607,8 +1626,8 @@ end = struct (* {{{ *)
let queue = ref None
let init () =
- if async_proofs_is_master () then
- queue := Some (TaskQueue.create !async_proofs_n_workers)
+ if async_proofs_is_master !cur_opt then
+ queue := Some (TaskQueue.create !cur_opt.async_proofs_n_workers)
else
queue := Some (TaskQueue.create 0)
@@ -1646,14 +1665,14 @@ end = struct (* {{{ *)
let st = Vernacstate.freeze_interp_state `No in
ignore(stm_vernac_interp stop ~proof st
{ verbose = false; loc; indentation = 0; strlen = 0;
- expr = VernacExpr (VernacEndProof (Proved (Opaque,None))) });
+ expr = VernacExpr ([], VernacEndProof (Proved (Opaque,None))) });
`OK proof
end
with e ->
let (e, info) = CErrors.push e in
(try match Stateid.get info with
| None ->
- msg_error Pp.(
+ msg_warning Pp.(
str"File " ++ str name ++ str ": proof of " ++ str r_name ++
spc () ++ iprint (e, info))
| Some (_, cur) ->
@@ -1663,17 +1682,17 @@ end = struct (* {{{ *)
| { step = `Qed ( { qast = { loc } }, _) }
| { step = `Sideff (ReplayCommand { loc }, _) } ->
let start, stop = Option.cata Loc.unloc (0,0) loc in
- msg_error Pp.(
+ msg_warning Pp.(
str"File " ++ str name ++ str ": proof of " ++ str r_name ++
str ": chars " ++ int start ++ str "-" ++ int stop ++
spc () ++ iprint (e, info))
| _ ->
- msg_error Pp.(
+ msg_warning Pp.(
str"File " ++ str name ++ str ": proof of " ++ str r_name ++
spc () ++ iprint (e, info))
with e ->
- msg_error Pp.(str"unable to print error message: " ++
- str (Printexc.to_string e)));
+ msg_warning Pp.(str"unable to print error message: " ++
+ str (Printexc.to_string e)));
if drop then `ERROR_ADMITTED else `ERROR
let finish_task name (u,cst,_) d p l i =
@@ -2074,7 +2093,7 @@ end = struct (* {{{ *)
QueryTask.({ t_where = prev; t_for = id; t_what = q }) ~cancel_switch
let init () = queue := Some (TaskQueue.create
- (if !async_proofs_full then 1 else 0))
+ (if !cur_opt.async_proofs_full then 1 else 0))
end (* }}} *)
@@ -2090,14 +2109,14 @@ let async_policy () =
let open Flags in
if is_universe_polymorphism () then false
else if VCS.is_interactive () = `Yes then
- (async_proofs_is_master () || !async_proofs_mode = APonLazy)
+ (async_proofs_is_master !cur_opt || !cur_opt.async_proofs_mode = APonLazy)
else
- (VCS.is_vio_doc () || !async_proofs_mode <> APoff)
+ (VCS.is_vio_doc () || !cur_opt.async_proofs_mode <> APoff)
let delegate name =
- get_hint_bp_time name >= !async_proofs_delegation_threshold
+ get_hint_bp_time name >= !cur_opt.async_proofs_delegation_threshold
|| VCS.is_vio_doc ()
- || !async_proofs_full
+ || !cur_opt.async_proofs_full
let warn_deprecated_nested_proofs =
CWarnings.create ~name:"deprecated-nested-proofs" ~category:"deprecated"
@@ -2177,7 +2196,7 @@ let collect_proof keep cur hd brkind id =
(try
let name, hint = name ids, get_hint_ctx loc in
let t, v = proof_no_using last in
- v.expr <- VernacExpr(VernacProof(t, Some hint));
+ v.expr <- VernacExpr([], VernacProof(t, Some hint));
`ASync (parent last,accn,name,delegate name)
with Not_found ->
let name = name ids in
@@ -2212,7 +2231,7 @@ let collect_proof keep cur hd brkind id =
let rc = collect (Some cur) [] id in
if is_empty rc then make_sync `AlreadyEvaluated rc
else if (keep == VtKeep || keep == VtKeepAsAxiom) &&
- (not(State.is_cached_and_valid id) || !async_proofs_full)
+ (not(State.is_cached_and_valid id) || !cur_opt.async_proofs_full)
then check_policy rc
else make_sync `AlreadyEvaluated rc
@@ -2294,9 +2313,9 @@ let known_state ?(redefine_qed=false) ~cache id =
(* Absorb tactic errors from f () *)
let resilient_tactic id blockname f =
- if !async_proofs_tac_error_resilience = `None ||
- (async_proofs_is_master () &&
- !async_proofs_mode = APoff)
+ if !cur_opt.async_proofs_tac_error_resilience = `None ||
+ (async_proofs_is_master !cur_opt &&
+ !cur_opt.async_proofs_mode = APoff)
then f ()
else
try f ()
@@ -2305,9 +2324,9 @@ let known_state ?(redefine_qed=false) ~cache id =
error_absorbing_tactic id blockname ie in
(* Absorb errors from f x *)
let resilient_command f x =
- if not !async_proofs_cmd_error_resilience ||
- (async_proofs_is_master () &&
- !async_proofs_mode = APoff)
+ if not !cur_opt.async_proofs_cmd_error_resilience ||
+ (async_proofs_is_master !cur_opt &&
+ !cur_opt.async_proofs_mode = APoff)
then f x
else
try f x
@@ -2353,10 +2372,10 @@ let known_state ?(redefine_qed=false) ~cache id =
resilient_tactic id cblock (fun () ->
reach ~cache:`Shallow view.next;
Partac.vernac_interp ~solve ~abstract ~cancel_switch
- !async_proofs_n_tacworkers view.next id x)
+ !cur_opt.async_proofs_n_tacworkers view.next id x)
), cache, true
| `Cmd { cast = x; cqueue = `QueryQueue cancel_switch }
- when async_proofs_is_master () -> (fun () ->
+ when async_proofs_is_master !cur_opt -> (fun () ->
reach view.next;
Query.vernac_interp ~cancel_switch view.next id x
), cache, false
@@ -2370,7 +2389,7 @@ let known_state ?(redefine_qed=false) ~cache id =
if eff then update_global_env ()
), (if eff then `Yes else cache), true
| `Cmd { cast = x; ceff = eff } -> (fun () ->
- (match !async_proofs_mode with
+ (match !cur_opt.async_proofs_mode with
| APon | APonLazy ->
resilient_command reach view.next
| APoff -> reach view.next);
@@ -2410,7 +2429,7 @@ let known_state ?(redefine_qed=false) ~cache id =
| { VCS.kind = `Edit (_,_,_, okeep, _) }, Some (ofp, cancel) ->
assert(redefine_qed = true);
if okeep != keep then
- msg_error(strbrk("The command closing the proof changed. "
+ msg_warning(strbrk("The command closing the proof changed. "
^"The kernel cannot take this into account and will "
^(if keep == VtKeep then "not check " else "reject ")
^"the "^(if keep == VtKeep then "new" else "incomplete")
@@ -2500,7 +2519,7 @@ let known_state ?(redefine_qed=false) ~cache id =
), cache, true
in
let cache_step =
- if !async_proofs_cache = Some Force then `Yes
+ if !cur_opt.async_proofs_cache = Some Force then `Yes
else cache_step in
State.define ?safe_id
~cache:cache_step ~redefine:redefine_qed ~feedback_processed step id;
@@ -2513,15 +2532,28 @@ end (* }}} *)
(********************************* STM API ************************************)
(******************************************************************************)
+(* Main initalization routine *)
type stm_init_options = {
+ (* The STM will set some internal flags differently depending on the
+ specified [doc_type]. This distinction should dissappear at some
+ some point. *)
doc_type : stm_doc_type;
+
+ (* Initial load path in scope for the document. Usually extracted
+ from -R options / _CoqProject *)
+ iload_path : Mltop.coq_path list;
+
+ (* Require [require_libs] before the initial state is
+ ready. Parameters follow [Library], that is to say,
+ [lib,prefix,import_export] means require library [lib] from
+ optional [prefix] and [import_export] if [Some false/Some true]
+ is used. *)
require_libs : (string * string option * bool option) list;
-(*
- fb_handler : Feedback.feedback -> unit;
- iload_path : (string list * string * bool) list;
- implicit_std : bool;
-*)
+
+ (* STM options that apply to the current document. *)
+ stm_options : AsyncOpts.stm_opt;
}
+(* fb_handler : Feedback.feedback -> unit; *)
(*
let doc_type_module_name (std : stm_doc_type) =
@@ -2531,10 +2563,11 @@ let doc_type_module_name (std : stm_doc_type) =
*)
let init_core () =
- if !async_proofs_mode = APon then Control.enable_thread_delay := true;
+ if !cur_opt.async_proofs_mode = APon then Control.enable_thread_delay := true;
State.register_root_state ()
-let new_doc { doc_type ; require_libs } =
+let new_doc { doc_type ; iload_path; require_libs; stm_options } =
+
let load_objs libs =
let rq_file (dir, from, exp) =
let mp = Libnames.(Qualid (Loc.tag @@ qualid_of_string dir)) in
@@ -2543,11 +2576,19 @@ let new_doc { doc_type ; require_libs } =
List.(iter rq_file (rev libs))
in
+ (* Set the options from the new documents *)
+ AsyncOpts.cur_opt := stm_options;
+
(* We must reset the whole state before creating a document! *)
State.restore_root_state ();
let doc = VCS.init doc_type Stateid.initial in
+ (* Set load path; important, this has to happen before we declare
+ the library below as [Declaremods/Library] will infer the module
+ name by looking at the load path! *)
+ List.iter Mltop.add_coq_path iload_path;
+
begin match doc_type with
| Interactive ln ->
Safe_typing.allow_delayed_constants := true;
@@ -2564,16 +2605,18 @@ let new_doc { doc_type ; require_libs } =
VCS.set_ldir ldir;
set_compilation_hints ln
end;
+
+ (* Import initial libraries. *)
load_objs require_libs;
- (* We record the state here! *)
+ (* We record the state at this point! *)
State.define ~cache:`Yes ~redefine:true (fun () -> ()) Stateid.initial;
Backtrack.record ();
Slaves.init ();
- if async_proofs_is_master () then begin
+ if async_proofs_is_master !cur_opt then begin
stm_prerr_endline (fun () -> "Initializing workers");
Query.init ();
- let opts = match !async_proofs_private_flags with
+ let opts = match !cur_opt.async_proofs_private_flags with
| None -> []
| Some s -> Str.split_delim (Str.regexp ",") s in
begin try
@@ -2659,7 +2702,7 @@ let finish_tasks name u d p (t,rcbackup as tasks) =
(u,a,true), p
with e ->
let e = CErrors.push e in
- msg_error (str"File " ++ str name ++ str ":" ++ spc () ++ iprint e);
+ msg_warning (str"File " ++ str name ++ str ":" ++ spc () ++ iprint e);
exit 1
let merge_proof_branch ~valid ?id qast keep brname =
@@ -2772,7 +2815,7 @@ let process_transaction ?(newtip=Stateid.fresh ()) ?(part_of_script=true)
| VtQuery (true, route), w ->
let id = VCS.new_node ~id:newtip () in
let queue =
- if !async_proofs_full then `QueryQueue (ref false)
+ if !cur_opt.async_proofs_full then `QueryQueue (ref false)
else if VCS.is_vio_doc () &&
VCS.((get_branch head).kind = `Master) &&
may_pierce_opaque (Vernacprop.under_control x.expr)
@@ -2872,10 +2915,9 @@ let process_transaction ?(newtip=Stateid.fresh ()) ?(part_of_script=true)
if not in_proof && Proof_global.there_are_pending_proofs () then
begin
let bname = VCS.mk_branch_name x in
- let rec opacity_of_produced_term = function
+ let opacity_of_produced_term = function
(* This AST is ambiguous, hence we check it dynamically *)
| VernacInstance (false, _,_ , None, _) -> GuaranteesOpacity
- | VernacLocal (_,e) -> opacity_of_produced_term e
| _ -> Doesn'tGuaranteeOpacity in
VCS.commit id (Fork (x,bname,opacity_of_produced_term (Vernacprop.under_control x.expr),[]));
let proof_mode = default_proof_mode () in
@@ -3105,7 +3147,7 @@ let edit_at ~doc id =
VCS.delete_boxes_of id;
VCS.gc ();
VCS.print ();
- if not !async_proofs_full then
+ if not !cur_opt.async_proofs_full then
Reach.known_state ~cache:(VCS.is_interactive ()) id;
VCS.checkout_shallowest_proof_branch ();
`NewTip in
@@ -3121,7 +3163,7 @@ let edit_at ~doc id =
| _, Some _, None -> assert false
| false, Some { qed = qed_id ; lemma = start }, Some(mode,bn) ->
let tip = VCS.cur_tip () in
- if has_failed qed_id && is_pure qed_id && not !async_proofs_never_reopen_branch
+ if has_failed qed_id && is_pure qed_id && not !cur_opt.async_proofs_never_reopen_branch
then reopen_branch start id mode qed_id tip bn
else backto id (Some bn)
| true, Some { qed = qed_id }, Some(mode,bn) ->
diff --git a/stm/stm.mli b/stm/stm.mli
index 587b75642..8a4de34b4 100644
--- a/stm/stm.mli
+++ b/stm/stm.mli
@@ -10,6 +10,33 @@ open Names
(** state-transaction-machine interface *)
+(* Flags *)
+module AsyncOpts : sig
+
+ type cache = Force
+ type async_proofs = APoff | APonLazy | APon
+ type tac_error_filter = [ `None | `Only of string list | `All ]
+
+ type stm_opt = {
+ async_proofs_n_workers : int;
+ async_proofs_n_tacworkers : int;
+
+ async_proofs_cache : cache option;
+ async_proofs_mode : async_proofs;
+
+ async_proofs_private_flags : string option;
+ async_proofs_full : bool;
+ async_proofs_never_reopen_branch : bool;
+
+ async_proofs_tac_error_resilience : tac_error_filter;
+ async_proofs_cmd_error_resilience : bool;
+ async_proofs_delegation_threshold : float;
+ }
+
+ val default_opts : stm_opt
+
+end
+
(** The STM doc type determines some properties such as what
uncompleted proofs are allowed and recording of aux files. *)
type stm_doc_type =
@@ -19,14 +46,26 @@ type stm_doc_type =
(* Main initalization routine *)
type stm_init_options = {
+ (* The STM will set some internal flags differently depending on the
+ specified [doc_type]. This distinction should dissappear at some
+ some point. *)
doc_type : stm_doc_type;
+
+ (* Initial load path in scope for the document. Usually extracted
+ from -R options / _CoqProject *)
+ iload_path : Mltop.coq_path list;
+
+ (* Require [require_libs] before the initial state is
+ ready. Parameters follow [Library], that is to say,
+ [lib,prefix,import_export] means require library [lib] from
+ optional [prefix] and [import_export] if [Some false/Some true]
+ is used. *)
require_libs : (string * string option * bool option) list;
-(*
- fb_handler : Feedback.feedback -> unit;
- iload_path : (string list * string * bool) list;
- implicit_std : bool;
-*)
+
+ (* STM options that apply to the current document. *)
+ stm_options : AsyncOpts.stm_opt;
}
+(* fb_handler : Feedback.feedback -> unit; *)
(** The type of a STM document *)
type doc
@@ -228,27 +267,3 @@ val get_all_proof_names : doc:doc -> Id.t list
(** Enable STM debugging *)
val stm_debug : bool ref
-
-(* Flags *)
-module AsyncOpts : sig
-
- (* Defaults for worker creation *)
- val async_proofs_n_workers : int ref
- val async_proofs_n_tacworkers : int ref
-
- type async_proofs = APoff | APonLazy | APon
- val async_proofs_mode : async_proofs ref
-
- type cache = Force
- val async_proofs_cache : cache option ref
-
- val async_proofs_private_flags : string option ref
- val async_proofs_full : bool ref
- val async_proofs_never_reopen_branch : bool ref
-
- type tac_error_filter = [ `None | `Only of string list | `All ]
- val async_proofs_tac_error_resilience : tac_error_filter ref
- val async_proofs_cmd_error_resilience : bool ref
- val async_proofs_delegation_threshold : float ref
-
-end
diff --git a/stm/tacworkertop.ml b/stm/tacworkertop.ml
index 17f90b7b1..f202fc7c5 100644
--- a/stm/tacworkertop.ml
+++ b/stm/tacworkertop.ml
@@ -10,5 +10,5 @@ module W = AsyncTaskQueue.MakeWorker(Stm.TacTask) ()
let () = Coqtop.toploop_init := WorkerLoop.loop W.init_stdout
-let () = Coqtop.toploop_run := (fun _ -> W.main_loop ())
+let () = Coqtop.toploop_run := (fun _ _ -> W.main_loop ())
diff --git a/stm/vernac_classifier.ml b/stm/vernac_classifier.ml
index 2fa47ba43..cbbb54e45 100644
--- a/stm/vernac_classifier.ml
+++ b/stm/vernac_classifier.ml
@@ -48,18 +48,19 @@ let declare_vernac_classifier
=
classifiers := !classifiers @ [s,f]
+let idents_of_name : Names.Name.t -> Names.Id.t list =
+ function
+ | Names.Anonymous -> []
+ | Names.Name n -> [n]
+
let classify_vernac e =
- let rec static_classifier ~poly e = match e with
+ let static_classifier ~poly e = match e with
(* Univ poly compatibility: we run it now, so that we can just
* look at Flags in stm.ml. Would be nicer to have the stm
* look at the entire dag to detect this option. *)
| ( VernacSetOption (l,_) | VernacUnsetOption l)
when CList.equal String.equal l Vernacentries.universe_polymorphism_option_name ->
VtSideff [], VtNow
- (* Nested vernac exprs *)
- | VernacProgram e -> static_classifier ~poly e
- | VernacLocal (_,e) -> static_classifier ~poly e
- | VernacPolymorphic (b, e) -> static_classifier ~poly:b e
(* Qed *)
| VernacAbort _ -> VtQed VtDrop, VtLater
| VernacEndProof Admitted -> VtQed VtKeepAsAxiom, VtLater
@@ -87,18 +88,14 @@ let classify_vernac e =
| VernacSetOption (["Default";"Proof";"Using"],_) -> VtSideff [], VtNow
(* StartProof *)
| VernacDefinition ((Decl_kinds.DoDischarge,_),((_,i),_),ProveBody _) ->
- VtStartProof(default_proof_mode (),Doesn'tGuaranteeOpacity,[i]), VtLater
+ VtStartProof(default_proof_mode (),Doesn'tGuaranteeOpacity, idents_of_name i), VtLater
| VernacDefinition (_,((_,i),_),ProveBody _) ->
let guarantee = if poly then Doesn'tGuaranteeOpacity else GuaranteesOpacity in
- VtStartProof(default_proof_mode (),guarantee,[i]), VtLater
+ VtStartProof(default_proof_mode (),guarantee, idents_of_name i), VtLater
| VernacStartTheoremProof (_,l) ->
- let ids =
- CList.map_filter (function (Some ((_,i),pl), _) -> Some i | _ -> None) l in
+ let ids = List.map (fun (((_, i), _), _) -> i) l in
let guarantee = if poly then Doesn'tGuaranteeOpacity else GuaranteesOpacity in
VtStartProof (default_proof_mode (),guarantee,ids), VtLater
- | VernacGoal _ ->
- let guarantee = if poly then Doesn'tGuaranteeOpacity else GuaranteesOpacity in
- VtStartProof (default_proof_mode (),guarantee,[]), VtLater
| VernacFixpoint (discharge,l) ->
let guarantee =
if discharge = Decl_kinds.DoDischarge || poly then Doesn'tGuaranteeOpacity
@@ -125,7 +122,7 @@ let classify_vernac e =
| VernacAssumption (_,_,l) ->
let ids = List.flatten (List.map (fun (_,(l,_)) -> List.map (fun (id, _) -> snd id) l) l) in
VtSideff ids, VtLater
- | VernacDefinition (_,((_,id),_),DefineBody _) -> VtSideff [id], VtLater
+ | VernacDefinition (_,((_,id),_),DefineBody _) -> VtSideff (idents_of_name id), VtLater
| VernacInductive (_, _,_,l) ->
let ids = List.map (fun (((_,((_,id),_)),_,_,_,cl),_) -> id :: match cl with
| Constructors l -> List.map (fun (_,((_,id),_)) -> id) l
@@ -193,7 +190,13 @@ let classify_vernac e =
with Not_found -> anomaly(str"No classifier for"++spc()++str (fst s)++str".")
in
let rec static_control_classifier ~poly = function
- | VernacExpr e -> static_classifier ~poly e
+ | VernacExpr (f, e) ->
+ let poly = List.fold_left (fun poly f ->
+ match f with
+ | VernacPolymorphic b -> b
+ | (VernacProgram | VernacLocal _) -> poly
+ ) poly f in
+ static_classifier ~poly e
| VernacTimeout (_,e) -> static_control_classifier ~poly e
| VernacTime (_,(_,e)) | VernacRedirect (_, (_,e)) ->
static_control_classifier ~poly e
diff --git a/stm/workerLoop.ml b/stm/workerLoop.ml
index 704119186..d606f19bf 100644
--- a/stm/workerLoop.ml
+++ b/stm/workerLoop.ml
@@ -15,8 +15,8 @@ let rec parse = function
| x :: rest -> x :: parse rest
| [] -> []
-let loop init args =
- let args = parse args in
+let loop init _coq_args extra_args =
+ let args = parse extra_args in
Flags.quiet := true;
init ();
CoqworkmgrApi.init !async_proofs_worker_priority;
diff --git a/stm/workerLoop.mli b/stm/workerLoop.mli
index da2e6fe0c..c42b48a28 100644
--- a/stm/workerLoop.mli
+++ b/stm/workerLoop.mli
@@ -9,4 +9,4 @@
(* Default priority *)
val async_proofs_worker_priority : CoqworkmgrApi.priority ref
-val loop : (unit -> unit) -> string list -> string list
+val loop : (unit -> unit) -> Coqargs.coq_cmdopts -> string list -> string list
diff --git a/tactics/class_tactics.ml b/tactics/class_tactics.ml
index 9e4d132d4..cfadfc535 100644
--- a/tactics/class_tactics.ml
+++ b/tactics/class_tactics.ml
@@ -1569,7 +1569,7 @@ let _ =
Hook.set Typeclasses.solve_all_instances_hook solve_inst
let resolve_one_typeclass env ?(sigma=Evd.empty) gl unique =
- let nc, gl, subst, _, _ = Evarutil.push_rel_context_to_named_context env sigma gl in
+ let nc, gl, subst, _ = Evarutil.push_rel_context_to_named_context env sigma gl in
let (gl,t,sigma) =
Goal.V82.mk_goal sigma nc gl Store.empty in
let (ev, _) = destEvar sigma t in
diff --git a/tactics/equality.ml b/tactics/equality.ml
index 22073d39b..450d68436 100644
--- a/tactics/equality.ml
+++ b/tactics/equality.ml
@@ -1583,7 +1583,7 @@ let subst_tuple_term env sigma dep_pair1 dep_pair2 b =
let body = mkApp (lambda_create env sigma (typ,pred_body),[|dep_pair1|]) in
let expected_goal = beta_applist sigma (abst_B,List.map fst e2_list) in
(* Simulate now the normalisation treatment made by Logic.mk_refgoals *)
- let expected_goal = nf_betaiota sigma expected_goal in
+ let expected_goal = nf_betaiota env sigma expected_goal in
(* Retype to get universes right *)
let sigma, expected_goal_ty = Typing.type_of env sigma expected_goal in
let sigma, _ = Typing.type_of env sigma body in
diff --git a/tactics/hipattern.ml b/tactics/hipattern.ml
index a3a3e0a9e..2bb9be66b 100644
--- a/tactics/hipattern.ml
+++ b/tactics/hipattern.ml
@@ -88,6 +88,12 @@ let is_lax_conjunction = function
let prod_assum sigma t = fst (decompose_prod_assum sigma t)
+(* whd_beta normalize the types of arguments in a product *)
+let rec whd_beta_prod sigma c = match EConstr.kind sigma c with
+ | Prod (n,t,c) -> mkProd (n,Reductionops.whd_beta sigma t,whd_beta_prod sigma c)
+ | LetIn (n,d,t,c) -> mkLetIn (n,d,t,whd_beta_prod sigma c)
+ | _ -> c
+
let match_with_one_constructor sigma style onlybinary allow_rec t =
let (hdapp,args) = decompose_app sigma t in
let res = match EConstr.kind sigma hdapp with
@@ -111,7 +117,9 @@ let match_with_one_constructor sigma style onlybinary allow_rec t =
Some (hdapp,args)
else None
else
- let ctyp = Termops.prod_applist sigma (EConstr.of_constr mip.mind_nf_lc.(0)) args in
+ let ctyp = whd_beta_prod sigma
+ (Termops.prod_applist_assum sigma (Context.Rel.length mib.mind_params_ctxt)
+ (EConstr.of_constr mip.mind_nf_lc.(0)) args) in
let cargs = List.map RelDecl.get_type (prod_assum sigma ctyp) in
if not (is_lax_conjunction style) || has_nodep_prod sigma ctyp then
(* Record or non strict conjunction *)
@@ -364,36 +372,39 @@ let is_forall_term sigma c = op2bool (match_with_forall_term sigma c)
let match_with_nodep_ind sigma t =
let (hdapp,args) = decompose_app sigma t in
- match EConstr.kind sigma hdapp with
- | Ind (ind, _) ->
- let (mib,mip) = Global.lookup_inductive ind in
- if Array.length (mib.mind_packets)>1 then None else
- let nodep_constr c = has_nodep_prod_after mib.mind_nparams sigma (EConstr.of_constr c) in
- if Array.for_all nodep_constr mip.mind_nf_lc then
- let params=
- if Int.equal mip.mind_nrealargs 0 then args else
- fst (List.chop mib.mind_nparams args) in
- Some (hdapp,params,mip.mind_nrealargs)
- else
- None
- | _ -> None
+ match EConstr.kind sigma hdapp with
+ | Ind (ind, _) ->
+ let (mib,mip) = Global.lookup_inductive ind in
+ if Array.length (mib.mind_packets)>1 then None else
+ let nodep_constr c =
+ has_nodep_prod_after (Context.Rel.length mib.mind_params_ctxt) sigma (EConstr.of_constr c) in
+ if Array.for_all nodep_constr mip.mind_nf_lc then
+ let params=
+ if Int.equal mip.mind_nrealargs 0 then args else
+ fst (List.chop mib.mind_nparams args) in
+ Some (hdapp,params,mip.mind_nrealargs)
+ else
+ None
+ | _ -> None
let is_nodep_ind sigma t = op2bool (match_with_nodep_ind sigma t)
let match_with_sigma_type sigma t =
let (hdapp,args) = decompose_app sigma t in
match EConstr.kind sigma hdapp with
- | Ind (ind, _) ->
- let (mib,mip) = Global.lookup_inductive ind in
- if Int.equal (Array.length (mib.mind_packets)) 1 &&
- (Int.equal mip.mind_nrealargs 0) &&
- (Int.equal (Array.length mip.mind_consnames)1) &&
- has_nodep_prod_after (mib.mind_nparams+1) sigma (EConstr.of_constr mip.mind_nf_lc.(0)) then
- (*allowing only 1 existential*)
- Some (hdapp,args)
- else
- None
- | _ -> None
+ | Ind (ind, _) ->
+ let (mib,mip) = Global.lookup_inductive ind in
+ if Int.equal (Array.length (mib.mind_packets)) 1
+ && (Int.equal mip.mind_nrealargs 0)
+ && (Int.equal (Array.length mip.mind_consnames)1)
+ && has_nodep_prod_after (Context.Rel.length mib.mind_params_ctxt + 1) sigma
+ (EConstr.of_constr mip.mind_nf_lc.(0))
+ then
+ (*allowing only 1 existential*)
+ Some (hdapp,args)
+ else
+ None
+ | _ -> None
let is_sigma_type sigma t = op2bool (match_with_sigma_type sigma t)
diff --git a/tactics/ind_tables.ml b/tactics/ind_tables.ml
index e1bf32f3c..bc2fea2bd 100644
--- a/tactics/ind_tables.ml
+++ b/tactics/ind_tables.ml
@@ -121,8 +121,7 @@ let define internal id c p univs =
let fd = declare_constant ~internal in
let id = compute_name internal id in
let ctx = Evd.normalize_evar_universe_context univs in
- let c = Vars.subst_univs_fn_constr
- (Universes.make_opt_subst (Evd.evar_universe_context_subst ctx)) c in
+ let c = Universes.subst_opt_univs_constr (Evd.evar_universe_context_subst ctx) c in
let univs =
if p then Polymorphic_const_entry (UState.context ctx)
else Monomorphic_const_entry (UState.context_set ctx)
diff --git a/tactics/tactics.ml b/tactics/tactics.ml
index 4ee0a8a7b..9fded04db 100644
--- a/tactics/tactics.ml
+++ b/tactics/tactics.ml
@@ -471,7 +471,7 @@ let internal_cut_gen ?(check=true) dir replace id t =
(if check && mem_named_context_val id sign then
user_err (str "Variable " ++ Id.print id ++ str " is already declared.");
push_named_context_val (LocalAssum (id,t)) sign,t,concl,sigma) in
- let nf_t = nf_betaiota sigma t in
+ let nf_t = nf_betaiota env sigma t in
Proofview.tclTHEN
(Proofview.Unsafe.tclEVARS sigma)
(Refine.refine ~typecheck:false begin fun sigma ->
@@ -1728,7 +1728,7 @@ let general_apply with_delta with_destruct with_evars clear_flag (loc,(c,lbind :
let env = Proofview.Goal.env gl in
let sigma = Tacmach.New.project gl in
- let thm_ty0 = nf_betaiota sigma (Retyping.get_type_of env sigma c) in
+ let thm_ty0 = nf_betaiota env sigma (Retyping.get_type_of env sigma c) in
let try_apply thm_ty nprod =
try
let n = nb_prod_modulo_zeta sigma thm_ty - nprod in
@@ -1864,7 +1864,7 @@ let explain_unable_to_apply_lemma ?loc env sigma thm innerclause =
str "."))
let apply_in_once_main flags innerclause env sigma (loc,d,lbind) =
- let thm = nf_betaiota sigma (Retyping.get_type_of env sigma d) in
+ let thm = nf_betaiota env sigma (Retyping.get_type_of env sigma d) in
let rec aux clause =
try progress_with_clause flags innerclause clause
with e when CErrors.noncritical e ->
@@ -2162,7 +2162,7 @@ let apply_type newcl args =
let env = Proofview.Goal.env gl in
let store = Proofview.Goal.extra gl in
Refine.refine ~typecheck:false begin fun sigma ->
- let newcl = nf_betaiota sigma newcl (* As in former Logic.refine *) in
+ let newcl = nf_betaiota env sigma newcl (* As in former Logic.refine *) in
let (sigma, ev) =
Evarutil.new_evar env sigma ~principal:true ~store newcl in
(sigma, applist (ev, args))
diff --git a/test-suite/Makefile b/test-suite/Makefile
index de669218c..16a56f440 100644
--- a/test-suite/Makefile
+++ b/test-suite/Makefile
@@ -40,6 +40,7 @@ coqtopload := $(coqtop) -top Top -async-proofs-cache force -load-vernac-source
coqtopcompile := $(coqtop) -compile
coqdep := $(BIN)coqdep -coqlib $(LIB)
+VERBOSE?=
SHOW := $(if $(VERBOSE),@true,@echo)
HIDE := $(if $(VERBOSE),,@)
REDIR := $(if $(VERBOSE),,> /dev/null 2>&1)
@@ -174,10 +175,20 @@ summary.log:
# if not on travis we can get the log files (they're just there for a
# local build, and downloadable on GitLab)
+PRINT_LOGS?=
+TRAVIS?= # special because we want to print travis_fold directives
+ifdef APPVEYOR
+PRINT_LOGS:=APPVEYOR
+else
+ifdef CIRCLECI
+PRINT_LOGS:=CIRCLECI
+endif #CIRCLECI
+endif #APPVEYOR
+
report: summary.log
$(HIDE)bash save-logs.sh
$(HIDE)if [ -n "${TRAVIS}" ]; then find logs/ -name '*.log' -not -name 'summary.log' -exec 'bash' '-c' 'echo "travis_fold:start:coq.logs.$$(echo '{}' | sed s,/,.,g)"' ';' -exec cat '{}' ';' -exec 'bash' '-c' 'echo "travis_fold:end:coq.logs.$$(echo '{}' | sed s,/,.,g)"' ';'; fi
- $(HIDE)if [ "(" -n "${APPVEYOR}" ")" -o "(" -n "${CIRCLECI}" ")" ]; then find logs/ -name '*.log' -not -name 'summary.log' -exec 'bash' '-c' 'echo {}' ';' -exec cat '{}' ';' -exec 'bash' '-c' 'echo' ';'; fi
+ $(HIDE)if [ -n "${PRINT_LOGS}" ]; then find logs/ -name '*.log' -not -name 'summary.log' -exec 'bash' '-c' 'echo {}' ';' -exec cat '{}' ';' -exec 'bash' '-c' 'echo' ';'; fi
$(HIDE)if grep -q -F 'Error!' summary.log ; then echo FAILURES; grep -F 'Error!' summary.log; false; else echo NO FAILURES; fi
#######################################################################
diff --git a/test-suite/README.md b/test-suite/README.md
new file mode 100644
index 000000000..1d1195646
--- /dev/null
+++ b/test-suite/README.md
@@ -0,0 +1,75 @@
+# Coq Test Suite
+
+The test suite can be run from the Coq root directory by `make test-suite`.
+This does a clean step first, so if you've already run it, then change something,
+you'll have to do a lot of work again.
+
+If you run `make` from the `test-suite` directory, there is no clean step.
+You can also run `make aaa/bbb/ccc.v.log` to build the log for one test,
+or `make ddd` where `ddd` is on of the sub-directories of `test-suite`
+to just build the logs for that directory.
+In these cases, a summary is not printed, but can be generated by `make summary`.
+
+`make -B` can be used to rerun tests ( -B meaning always remake).
+
+From the `test-suite` directory, `make report` (included in `make
+all`) prints a summary of which tests failed using the produced log
+files (this still works when only some tests are built as described
+above). Setting the `PRINT_LOGS` variable will make it print the logs
+of the failing tests.
+
+For instance, running the following in the `test-suite` directory:
+
+```bash
+$ echo Fail. > success/fail.v # make some failing test
+
+$ make
+TEST prerequisite/make_local.v
+...
+TEST success/fail.v
+...
+BUILDING SUMMARY FILE
+FAILURES
+ success/fail.v...Error! (should be accepted)
+Makefile:189: recipe for target 'all failed
+make: *** [report] Error 1
+
+$ make report PRINT_LOGS=1
+BUILDING SUMMARY FILE
+logs/success/fail.v.log
+==========> TESTING success/fail.v <==========
+Welcome to Coq (version information)
+Skipping rcfile loading.
+File "/path/to/success/fail.v", line 1, characters 4-5:
+Error:
+Syntax error: [vernac:Vernac.vernac_control] expected after 'Fail' (in [vernac:Vernac.vernac_control]).
+
+0m0.000000s 0m0.000000s
+0m0.040000s 0m0.000000s
+==========> FAILURE <==========
+ success/fail.v...Error! (should be accepted)
+
+FAILURES
+ success/fail.v...Error! (should be accepted)
+Makefile:189: recipe for target 'report' failed
+make: *** [report] Error 1
+
+$ echo 'Comments "foo".' > success/fail.v
+
+$ make
+TEST success/fail.v
+BUILDING SUMMARY FILE
+NO FAILURES
+```
+
+See [`test-suite/Makefile`](/test-suite/Makefile) for more information.
+
+## Adding a test
+
+Regression tests for closed bugs should be added to `test-suite/bugs/closed`, as `1234.v` where `1234` is the bug number.
+Files in this directory are tested for successful compilation.
+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.
diff --git a/test-suite/bugs/closed/5286.v b/test-suite/bugs/closed/5286.v
new file mode 100644
index 000000000..98d4e5c96
--- /dev/null
+++ b/test-suite/bugs/closed/5286.v
@@ -0,0 +1,9 @@
+Set Primitive Projections.
+
+CoInductive R := mkR { p : unit }.
+
+CoFixpoint foo := mkR tt.
+
+Check (eq_refl tt : p foo = tt).
+Check (eq_refl tt <: p foo = tt).
+Check (eq_refl tt <<: p foo = tt).
diff --git a/test-suite/bugs/closed/5726.v b/test-suite/bugs/closed/5726.v
new file mode 100644
index 000000000..53ef47357
--- /dev/null
+++ b/test-suite/bugs/closed/5726.v
@@ -0,0 +1,34 @@
+Set Universe Polymorphism.
+Set Printing Universes.
+
+Module GlobalReference.
+
+ Definition type' := Type.
+ Notation type := type'.
+ Check type@{Set}.
+
+End GlobalReference.
+
+Module TypeLiteral.
+
+ Notation type := Type.
+ Check type@{Set}.
+ Check type@{Prop}.
+
+End TypeLiteral.
+
+Module ExplicitSort.
+ Monomorphic Universe u.
+ Notation foo := Type@{u}.
+ Fail Check foo@{Set}.
+ Fail Check foo@{u}.
+
+ Notation bar := Type.
+ Check bar@{u}.
+End ExplicitSort.
+
+Module PropNotationUnsupported.
+ Notation foo := Prop.
+ Fail Check foo@{Set}.
+ Fail Check foo@{Type}.
+End PropNotationUnsupported.
diff --git a/test-suite/bugs/closed/6297.v b/test-suite/bugs/closed/6297.v
new file mode 100644
index 000000000..a28607058
--- /dev/null
+++ b/test-suite/bugs/closed/6297.v
@@ -0,0 +1,8 @@
+Set Printing Universes.
+
+(* Error: Anomaly "Uncaught exception "Anomaly: Incorrect universe Set
+ declared for inductive type, inferred level is max(Prop, Set+1)."."
+ Please report at http://coq.inria.fr/bugs/. *)
+Fail Record LTS: Set :=
+ lts { St: Set;
+ init: St }.
diff --git a/test-suite/bugs/closed/6490.v b/test-suite/bugs/closed/6490.v
new file mode 100644
index 000000000..dcf9ff29e
--- /dev/null
+++ b/test-suite/bugs/closed/6490.v
@@ -0,0 +1,4 @@
+Inductive Foo (A' := I) (B : Type) := foo : Foo B.
+
+Goal Foo True. dtauto. Qed.
+Goal Foo True. firstorder. Qed.
diff --git a/test-suite/bugs/closed/6534.v b/test-suite/bugs/closed/6534.v
new file mode 100644
index 000000000..f5013994c
--- /dev/null
+++ b/test-suite/bugs/closed/6534.v
@@ -0,0 +1,7 @@
+Goal forall x : nat, x = x.
+Proof.
+intros x.
+refine ((fun x x => _ tt) tt tt).
+let t := match goal with [ |- ?P ] => P end in
+let _ := type of t in
+idtac.
diff --git a/test-suite/bugs/closed/6617.v b/test-suite/bugs/closed/6617.v
new file mode 100644
index 000000000..9cabd62d4
--- /dev/null
+++ b/test-suite/bugs/closed/6617.v
@@ -0,0 +1,34 @@
+Definition MR {T M : Type} :=
+fun (R : M -> M -> Prop) (m : T -> M) (x y : T) => R (m x) (m y).
+
+Set Primitive Projections.
+
+Record sigma {A : Type} {B : A -> Type} : Type := sigmaI
+ { pr1 : A; pr2 : B pr1 }.
+
+Axiom F : forall {A : Type} {R : A -> A -> Prop},
+ (forall x, (forall y, R y x -> unit) -> unit) -> forall (x : A), unit.
+
+Definition foo (A : Type) (l : list A) :=
+ let y := {| pr1 := A; pr2 := l |} in
+ let bar := MR lt (fun p : sigma =>
+ (fix Ffix (x : list (pr1 p)) : nat :=
+ match x with
+ | nil => 0
+ | cons _ x1 => S (Ffix x1)
+ end) (pr2 p)) in
+fun (_ : bar y y) =>
+F (fun (r : sigma)
+ (X : forall q : sigma, bar q r -> unit) => tt).
+
+Definition fooT (A : Type) (l : list A) : Type :=
+ ltac:(let ty := type of (foo A l) in exact ty).
+Parameter P : forall A l, fooT A l -> Prop.
+
+Goal forall A l, P A l (foo A l).
+Proof.
+ intros; unfold foo.
+ Fail match goal with
+ | [ |- context [False]] => idtac
+ end.
+Admitted.
diff --git a/test-suite/bugs/closed/6677.v b/test-suite/bugs/closed/6677.v
new file mode 100644
index 000000000..99e47bb87
--- /dev/null
+++ b/test-suite/bugs/closed/6677.v
@@ -0,0 +1,5 @@
+Set Universe Polymorphism.
+
+Definition T@{i} := Type@{i}.
+Fail Definition U@{i} := (T@{i} <: Type@{i}).
+Fail Definition eqU@{i j} : @eq T@{j} U@{i} T@{i} := eq_refl.
diff --git a/test-suite/bugs/opened/6393.v b/test-suite/bugs/opened/6393.v
new file mode 100644
index 000000000..8d5d09233
--- /dev/null
+++ b/test-suite/bugs/opened/6393.v
@@ -0,0 +1,11 @@
+(* These always worked. *)
+Goal prod True True. firstorder. Qed.
+Goal True -> @sigT True (fun _ => True). firstorder. Qed.
+Goal prod True True. dtauto. Qed.
+Goal prod True True. tauto. Qed.
+
+(* These should work. *)
+Goal @sigT True (fun _ => True). dtauto. Qed.
+(* These should work, but don't *)
+(* Goal @sigT True (fun _ => True). firstorder. Qed. *)
+(* Goal @sigT True (fun _ => True). tauto. Qed. *)
diff --git a/test-suite/coq-makefile/emptyprefix/_CoqProject b/test-suite/coq-makefile/emptyprefix/_CoqProject
new file mode 100644
index 000000000..5678a8edb
--- /dev/null
+++ b/test-suite/coq-makefile/emptyprefix/_CoqProject
@@ -0,0 +1,11 @@
+-R theories ""
+-R src ""
+-I src
+-arg "-w default"
+
+src/test_plugin.mlpack
+src/test.ml4
+src/test.mli
+src/test_aux.ml
+src/test_aux.mli
+theories/test.v
diff --git a/test-suite/coq-makefile/emptyprefix/_CoqProject.sub b/test-suite/coq-makefile/emptyprefix/_CoqProject.sub
new file mode 100644
index 000000000..90ac541e0
--- /dev/null
+++ b/test-suite/coq-makefile/emptyprefix/_CoqProject.sub
@@ -0,0 +1,3 @@
+-R ../theories ""
+-I ../src
+testsub.v
diff --git a/test-suite/coq-makefile/emptyprefix/run.sh b/test-suite/coq-makefile/emptyprefix/run.sh
new file mode 100755
index 000000000..a10e63b42
--- /dev/null
+++ b/test-suite/coq-makefile/emptyprefix/run.sh
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+
+set -e
+
+. ../template/init.sh
+
+mv theories/sub theories2
+
+coq_makefile -f _CoqProject -o Makefile
+cat Makefile.conf
+make
+
+cp ../_CoqProject.sub theories2/_CoqProject
+cd theories2
+coq_makefile -f _CoqProject -o Makefile
+cat Makefile.conf
+make
diff --git a/test-suite/coq-makefile/quick2vo/_CoqProject b/test-suite/coq-makefile/quick2vo/_CoqProject
new file mode 100644
index 000000000..69f47302e
--- /dev/null
+++ b/test-suite/coq-makefile/quick2vo/_CoqProject
@@ -0,0 +1,10 @@
+-R src test
+-R theories test
+-I src
+
+src/test_plugin.mlpack
+src/test.ml4
+src/test.mli
+src/test_aux.ml
+src/test_aux.mli
+theories/test.v
diff --git a/test-suite/coq-makefile/quick2vo/run.sh b/test-suite/coq-makefile/quick2vo/run.sh
new file mode 100755
index 000000000..9e681223b
--- /dev/null
+++ b/test-suite/coq-makefile/quick2vo/run.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+a=`uname`
+
+. ../template/init.sh
+
+coq_makefile -f _CoqProject -o Makefile
+# vio2vo is broken on Windows (#6720)
+if [ "$a" = "Darwin" -o "$a" = "Linux" ]; then
+ make quick2vo J=2
+ test -f theories/test.vo
+ make validate
+fi
diff --git a/test-suite/coq-makefile/timing/run.sh b/test-suite/coq-makefile/timing/run.sh
index 898af5590..2439d3f37 100755
--- a/test-suite/coq-makefile/timing/run.sh
+++ b/test-suite/coq-makefile/timing/run.sh
@@ -31,16 +31,16 @@ coq_makefile -f _CoqProject -o Makefile
make cleanall
make make-pretty-timed-after TGTS="all" -j1 || exit $?
rm -f time-of-build-before.log
-make print-pretty-timed-diff TIME_OF_BUILD_BEFORE_FILE=../before/time-of-build-before.log
+make print-pretty-timed-diff TIMING_SORT_BY=diff TIME_OF_BUILD_BEFORE_FILE=../before/time-of-build-before.log
cp ../before/time-of-build-before.log ./
-make print-pretty-timed-diff || exit $?
+make print-pretty-timed-diff TIMING_SORT_BY=diff || exit $?
INFINITY="∞"
INFINITY_REPLACEMENT="+.%" # assume that if the before time is zero, we expected the time to increase
for ext in "" .desired; do
for file in time-of-build-before.log time-of-build-after.log time-of-build-both.log; do
- cat ${file}${ext} | grep -v 'warning: undefined variable' | sed s"/${INFINITY}/${INFINITY_REPLACEMENT}/g" | sed s'/[0-9]//g' | sed s'/ *$//g' | sed s":|\s*N/A\s*$:| ${INFINITY_REPLACEMENT}:g" | sed s'/^-*$/------/g' | sed s'/ */ /g' | sed s'/\(Total.*\)-\(.*\)-/\1+\2+/g' > ${file}${ext}.processed
+ cat ${file}${ext} | grep -v 'warning: undefined variable' | sed s"/${INFINITY}/${INFINITY_REPLACEMENT}/g" | sed s'/[0-9]//g' | sed s'/ *$//g' | sed s":|\s*N/A\s*$:| ${INFINITY_REPLACEMENT}:g" | sed s'/^-*$/------/g' | sed s'/ */ /g' | sed s'/\(Total.*\)-\(.*\)-/\1+\2+/g' > ${file}${ext}.processed
done
done
for file in time-of-build-before.log time-of-build-after.log time-of-build-both.log; do
@@ -74,7 +74,7 @@ echo
for ext in "" .desired; do
for file in A.v.timing.diff; do
- cat ${file}${ext} | sed s"/${INFINITY}/${INFINITY_REPLACEMENT}/g" | sed s":|\s*N/A\s*$:| ${INFINITY_REPLACEMENT}:g" | sed s'/[0-9]*\.[0-9]*//g' | sed s'/0//g' | sed s'/ */ /g' | sed s'/+/-/g' | sort > ${file}${ext}.processed
+ cat ${file}${ext} | sed s"/${INFINITY}/${INFINITY_REPLACEMENT}/g" | sed s":|\s*N/A\s*$:| ${INFINITY_REPLACEMENT}:g" | sed s'/[0-9]*\.[0-9]*//g' | sed s'/0//g' | sed s'/ */ /g' | sed s'/ *$//g' | sed s'/+/-/g' | sort > ${file}${ext}.processed
done
done
for file in A.v.timing.diff; do
diff --git a/test-suite/coq-makefile/vio2vo/_CoqProject b/test-suite/coq-makefile/vio2vo/_CoqProject
new file mode 100644
index 000000000..69f47302e
--- /dev/null
+++ b/test-suite/coq-makefile/vio2vo/_CoqProject
@@ -0,0 +1,10 @@
+-R src test
+-R theories test
+-I src
+
+src/test_plugin.mlpack
+src/test.ml4
+src/test.mli
+src/test_aux.ml
+src/test_aux.mli
+theories/test.v
diff --git a/test-suite/coq-makefile/vio2vo/run.sh b/test-suite/coq-makefile/vio2vo/run.sh
new file mode 100755
index 000000000..85656da41
--- /dev/null
+++ b/test-suite/coq-makefile/vio2vo/run.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+a=`uname`
+
+. ../template/init.sh
+
+coq_makefile -f _CoqProject -o Makefile
+make quick
+# vio2vo is broken on Windows (#6720)
+if [ "$a" = "Darwin" -o "$a" = "Linux" ]; then
+ make vio2vo J=2
+ test -f theories/test.vo
+ make validate
+fi
diff --git a/test-suite/coqchk/include.v b/test-suite/coqchk/include.v
new file mode 100644
index 000000000..6232c1b80
--- /dev/null
+++ b/test-suite/coqchk/include.v
@@ -0,0 +1,11 @@
+(* See https://github.com/coq/coq/issues/5747 *)
+Module Type S.
+End S.
+
+Module N.
+Inductive I := .
+End N.
+
+Module M : S.
+ Include N.
+End M.
diff --git a/test-suite/coqchk/primproj2.v b/test-suite/coqchk/primproj2.v
new file mode 100644
index 000000000..f73c627ee
--- /dev/null
+++ b/test-suite/coqchk/primproj2.v
@@ -0,0 +1,10 @@
+Set Primitive Projections.
+
+Record Pack (A : Type) := pack { unpack : A }.
+
+Definition p : Pack bool.
+Proof.
+refine (pack _ true).
+Qed.
+
+Definition boom : unpack bool p = let u := unpack _ in u p := eq_refl.
diff --git a/test-suite/output/ErrorInCanonicalStructures.out b/test-suite/output/ErrorInCanonicalStructures.out
new file mode 100644
index 000000000..73da4f44f
--- /dev/null
+++ b/test-suite/output/ErrorInCanonicalStructures.out
@@ -0,0 +1,5 @@
+File "stdin", line 3, characters 0-24:
+Error:
+Could not declare a canonical structure Foo.
+Expected an instance of a record or structure.
+
diff --git a/test-suite/output/ErrorInCanonicalStructures.v b/test-suite/output/ErrorInCanonicalStructures.v
new file mode 100644
index 000000000..49597df6f
--- /dev/null
+++ b/test-suite/output/ErrorInCanonicalStructures.v
@@ -0,0 +1,3 @@
+Record Foo := MkFoo { field1 : nat; field2 : nat -> nat }.
+
+Canonical Structure Foo.
diff --git a/test-suite/output/ErrorInCanonicalStructures2.out b/test-suite/output/ErrorInCanonicalStructures2.out
new file mode 100644
index 000000000..63a2871b8
--- /dev/null
+++ b/test-suite/output/ErrorInCanonicalStructures2.out
@@ -0,0 +1,5 @@
+File "stdin", line 3, characters 0-24:
+Error:
+Could not declare a canonical structure bar.
+Expected an instance of a record or structure.
+
diff --git a/test-suite/output/ErrorInCanonicalStructures2.v b/test-suite/output/ErrorInCanonicalStructures2.v
new file mode 100644
index 000000000..10ee177aa
--- /dev/null
+++ b/test-suite/output/ErrorInCanonicalStructures2.v
@@ -0,0 +1,3 @@
+Definition bar := 99.
+
+Canonical Structure bar.
diff --git a/test-suite/output/Inductive.out b/test-suite/output/Inductive.out
index e912003f0..af202ea01 100644
--- a/test-suite/output/Inductive.out
+++ b/test-suite/output/Inductive.out
@@ -1,3 +1,7 @@
The command has indeed failed with message:
Last occurrence of "list'" must have "A" as 1st argument in
"A -> list' A -> list' (A * A)%type".
+Inductive foo (A : Type) (x : A) (y : A := x) : Prop := Foo : foo A x
+
+For foo: Argument scopes are [type_scope _]
+For Foo: Argument scopes are [type_scope _]
diff --git a/test-suite/output/Inductive.v b/test-suite/output/Inductive.v
index 8db8956e3..8ff91268a 100644
--- a/test-suite/output/Inductive.v
+++ b/test-suite/output/Inductive.v
@@ -1,3 +1,7 @@
Fail Inductive list' (A:Set) : Set :=
| nil' : list' A
| cons' : A -> list' A -> list' (A*A).
+
+(* Check printing of let-ins *)
+Inductive foo (A : Type) (x : A) (y := x) := Foo.
+Print foo.
diff --git a/test-suite/output/UnivBinders.out b/test-suite/output/UnivBinders.out
index d6d410d1a..668b4e578 100644
--- a/test-suite/output/UnivBinders.out
+++ b/test-suite/output/UnivBinders.out
@@ -5,7 +5,7 @@ PWrap has primitive projections with eta conversion.
For PWrap: Argument scope is [type_scope]
For pwrap: Argument scopes are [type_scope _]
punwrap@{u} =
-fun (A : Type@{u}) (p : PWrap@{u} A) => punwrap _ p
+fun (A : Type@{u}) (p : PWrap@{u} A) => p.(punwrap)
: forall A : Type@{u}, PWrap@{u} A -> A
(* u |= *)
diff --git a/test-suite/output/optimize_heap.out b/test-suite/output/optimize_heap.out
new file mode 100644
index 000000000..94a0b1911
--- /dev/null
+++ b/test-suite/output/optimize_heap.out
@@ -0,0 +1,8 @@
+1 subgoal
+
+ ============================
+ True
+1 subgoal
+
+ ============================
+ True
diff --git a/test-suite/output/optimize_heap.v b/test-suite/output/optimize_heap.v
new file mode 100644
index 000000000..e566bd7ba
--- /dev/null
+++ b/test-suite/output/optimize_heap.v
@@ -0,0 +1,7 @@
+(* optimize_heap should not affect the proof state *)
+
+Goal True.
+ idtac.
+ Show.
+ optimize_heap.
+ Show.
diff --git a/test-suite/success/BracketsWithGoalSelector.v b/test-suite/success/BracketsWithGoalSelector.v
new file mode 100644
index 000000000..ed035f521
--- /dev/null
+++ b/test-suite/success/BracketsWithGoalSelector.v
@@ -0,0 +1,16 @@
+Goal forall A B, B \/ A -> A \/ B.
+Proof.
+ intros * [HB | HA].
+ 2: {
+ left.
+ exact HA.
+ Fail right. (* No such goal. Try unfocusing with "}". *)
+ }
+ Fail 2: { (* Non-existent goal. *)
+ idtac. (* The idtac is to get a dot, so that IDEs know to stop there. *)
+ 1:{ (* Syntactic test: no space before bracket. *)
+ right.
+ exact HB.
+Fail Qed.
+ }
+Qed.
diff --git a/test-suite/success/abstract_poly.v b/test-suite/success/abstract_poly.v
index b736b734f..aa8da5336 100644
--- a/test-suite/success/abstract_poly.v
+++ b/test-suite/success/abstract_poly.v
@@ -17,4 +17,4 @@ intros m n P e p.
abstract (rewrite e in p; exact p).
Defined.
-Check bar_subproof@{Set Set Set}.
+Check bar_subproof@{Set Set}.
diff --git a/test-suite/success/cumulativity.v b/test-suite/success/cumulativity.v
index 0ee85712e..1fb3abfe4 100644
--- a/test-suite/success/cumulativity.v
+++ b/test-suite/success/cumulativity.v
@@ -45,6 +45,15 @@ Section TpLift.
End TpLift.
+Record Tp' := { tp' : Tp }.
+
+Definition CTp := Tp.
+(* here we have to reduce a constant to infer the correct subtyping. *)
+Record Tp'' := { tp'' : CTp }.
+
+Definition LiftTp'@{i j|i < j} : Tp'@{i} -> Tp'@{j} := fun x => x.
+Definition LiftTp''@{i j|i < j} : Tp''@{i} -> Tp''@{j} := fun x => x.
+
Lemma LiftC_Lem (t : Tp) : LiftTp t = t.
Proof. reflexivity. Qed.
@@ -98,3 +107,20 @@ Section down.
intros H f g Hfg. exact (H f g Hfg).
Defined.
End down.
+
+Record Arrow@{i j} := { arrow : Type@{i} -> Type@{j} }.
+
+Fail Definition arrow_lift@{i i' j j' | i' < i, j < j'}
+ : Arrow@{i j} -> Arrow@{i' j'}
+ := fun x => x.
+
+Definition arrow_lift@{i i' j j' | i' = i, j < j'}
+ : Arrow@{i j} -> Arrow@{i' j'}
+ := fun x => x.
+
+Inductive Mut1 A :=
+| Base1 : Type -> Mut1 A
+| Node1 : (A -> Mut2 A) -> Mut1 A
+with Mut2 A :=
+ | Base2 : Type -> Mut2 A
+ | Node2 : Mut1 A -> Mut2 A.
diff --git a/test-suite/success/dtauto-let-deps.v b/test-suite/success/dtauto-let-deps.v
new file mode 100644
index 000000000..094b2f8b3
--- /dev/null
+++ b/test-suite/success/dtauto-let-deps.v
@@ -0,0 +1,24 @@
+(*
+This test is sensitive to changes in which let-ins are expanded when checking
+for dependencies in constructors.
+If the (x := X) is not reduced, Foo1 won't be recognized as a conjunction,
+and if the (y := X) is reduced, Foo2 will be recognized as a conjunction.
+
+This tests the behavior of engine/termops.ml : prod_applist_assum,
+which is currently specified to reduce exactly the parameters.
+
+If dtauto is changed to reduce lets in constructors before checking dependency,
+this test will need to be changed.
+*)
+
+Context (P Q : Type).
+Inductive Foo1 (X : Type) (x := X) := foo1 : let y := X in P -> Q -> Foo1 x.
+Inductive Foo2 (X : Type) (x := X) := foo2 : let y := X in P -> Q -> Foo2 y.
+
+Goal P -> Q -> Foo1 nat.
+solve [dtauto].
+Qed.
+
+Goal P -> Q -> Foo2 nat.
+Fail solve [dtauto].
+Abort.
diff --git a/theories/Arith/Between.v b/theories/Arith/Between.v
index 9b4071085..ead08b3eb 100644
--- a/theories/Arith/Between.v
+++ b/theories/Arith/Between.v
@@ -16,6 +16,8 @@ Implicit Types k l p q r : nat.
Section Between.
Variables P Q : nat -> Prop.
+ (** The [between] type expresses the concept
+ [forall i: nat, k <= i < l -> P i.]. *)
Inductive between k : nat -> Prop :=
| bet_emp : between k k
| bet_S : forall l, between k l -> P l -> between k (S l).
@@ -47,6 +49,8 @@ Section Between.
induction 1; auto with arith.
Qed.
+ (** The [exists_between] type expresses the concept
+ [exists i: nat, k <= i < l /\ Q i]. *)
Inductive exists_between k : nat -> Prop :=
| exists_S : forall l, exists_between k l -> exists_between k (S l)
| exists_le : forall l, k <= l -> Q l -> exists_between k (S l).
diff --git a/theories/Lists/List.v b/theories/Lists/List.v
index fbf992dbf..eae2c52de 100644
--- a/theories/Lists/List.v
+++ b/theories/Lists/List.v
@@ -2110,13 +2110,13 @@ Section Exists_Forall.
{Exists l} + {~ Exists l}.
Proof.
intro Pdec. induction l as [|a l' Hrec].
- - right. now rewrite Exists_nil.
+ - right. abstract now rewrite Exists_nil.
- destruct Hrec as [Hl'|Hl'].
* left. now apply Exists_cons_tl.
* destruct (Pdec a) as [Ha|Ha].
+ left. now apply Exists_cons_hd.
- + right. now inversion_clear 1.
- Qed.
+ + right. abstract now inversion 1.
+ Defined.
Inductive Forall : list A -> Prop :=
| Forall_nil : Forall nil
@@ -2152,9 +2152,9 @@ Section Exists_Forall.
- destruct Hrec as [Hl'|Hl'].
+ destruct (Pdec a) as [Ha|Ha].
* left. now apply Forall_cons.
- * right. now inversion_clear 1.
- + right. now inversion_clear 1.
- Qed.
+ * right. abstract now inversion 1.
+ + right. abstract now inversion 1.
+ Defined.
End One_predicate.
@@ -2179,6 +2179,16 @@ Section Exists_Forall.
* now apply Exists_cons_hd.
Qed.
+ Lemma neg_Forall_Exists_neg (P:A->Prop) (l:list A) :
+ (forall x:A, {P x} + { ~ P x }) ->
+ ~ Forall P l ->
+ Exists (fun x => ~ P x) l.
+ Proof.
+ intro Dec.
+ apply Exists_Forall_neg; intros.
+ destruct (Dec x); auto.
+ Qed.
+
Lemma Forall_Exists_dec (P:A->Prop) :
(forall x:A, {P x} + { ~ P x }) ->
forall l:list A,
@@ -2186,9 +2196,8 @@ Section Exists_Forall.
Proof.
intros Pdec l.
destruct (Forall_dec P Pdec l); [left|right]; trivial.
- apply Exists_Forall_neg; trivial.
- intro x. destruct (Pdec x); [now left|now right].
- Qed.
+ now apply neg_Forall_Exists_neg.
+ Defined.
Lemma Forall_impl : forall (P Q : A -> Prop), (forall a, P a -> Q a) ->
forall l, Forall P l -> Forall Q l.
diff --git a/tools/CoqMakefile.in b/tools/CoqMakefile.in
index de113df6a..23212ef84 100644
--- a/tools/CoqMakefile.in
+++ b/tools/CoqMakefile.in
@@ -119,6 +119,8 @@ CAMLPKGS ?=
# Option for making timing files
TIMING?=
+# Option for changing sorting of timing output file
+TIMING_SORT_BY ?= auto
# Output file names for timed builds
TIME_OF_BUILD_FILE ?= time-of-build.log
TIME_OF_BUILD_BEFORE_FILE ?= time-of-build-before.log
@@ -167,7 +169,8 @@ endif
COQFLAGS?=-q $(OPT) $(COQLIBS) $(OTHERFLAGS)
COQCHKFLAGS?=-silent -o $(COQLIBS)
-COQDOCFLAGS?=-interpolate -utf8 $(COQLIBS_NOML)
+COQDOCFLAGS?=-interpolate -utf8
+COQDOCLIBS?=$(COQLIBS_NOML)
# The version of Coq being run and the version of coq_makefile that
# generated this makefile
@@ -334,7 +337,7 @@ make-pretty-timed make-pretty-timed-before make-pretty-timed-after::
print-pretty-timed::
$(HIDE)$(COQMAKE_ONE_TIME_FILE) $(TIME_OF_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES)
print-pretty-timed-diff::
- $(HIDE)$(COQMAKE_BOTH_TIME_FILES) $(TIME_OF_BUILD_BEFORE_FILE) $(TIME_OF_BUILD_AFTER_FILE) $(TIME_OF_PRETTY_BOTH_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES)
+ $(HIDE)$(COQMAKE_BOTH_TIME_FILES) --sort-by=$(TIMING_SORT_BY) $(TIME_OF_BUILD_BEFORE_FILE) $(TIME_OF_BUILD_AFTER_FILE) $(TIME_OF_PRETTY_BOTH_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES)
ifeq (,$(BEFORE))
print-pretty-single-time-diff::
@echo 'Error: Usage: $(MAKE) print-pretty-single-time-diff BEFORE=path/to/file.v.before-timing AFTER=path/to/file.v.after-timing'
@@ -346,7 +349,7 @@ print-pretty-single-time-diff::
$(HIDE)false
else
print-pretty-single-time-diff::
- $(HIDE)$(COQMAKE_BOTH_SINGLE_TIMING_FILES) $(BEFORE) $(AFTER) $(TIME_OF_PRETTY_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES)
+ $(HIDE)$(COQMAKE_BOTH_SINGLE_TIMING_FILES) --sort-by=$(TIMING_SORT_BY) $(BEFORE) $(AFTER) $(TIME_OF_PRETTY_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES)
endif
endif
pretty-timed:
@@ -379,7 +382,7 @@ bytefiles: $(CMOFILES) $(CMAFILES)
optfiles: $(if $(DO_NATDYNLINK),$(CMXSFILES))
.PHONY: optfiles
-# FIXME, see Ralph's bugreport
+# FIXME, see Ralf's bugreport
quick: $(VOFILES:.vo=.vio)
.PHONY: quick
@@ -388,6 +391,18 @@ vio2vo:
-schedule-vio2vo $(J) $(VOFILES:%.vo=%.vio)
.PHONY: vio2vo
+quick2vo:
+ $(HIDE)make -j $(J) quick
+ $(HIDE)VIOFILES=$$(for vofile in $(VOFILES); do \
+ viofile="$$(echo "$$vofile" | sed "s/\.vo$$/.vio/")"; \
+ if [ "$$vofile" -ot "$$viofile" -o ! -e "$$vofile" ]; then printf "$$viofile "; fi; \
+ done); \
+ echo "VIO2VO: $$VIOFILES"; \
+ if [ -n "$$VIOFILES" ]; then \
+ $(TIMER) $(COQC) $(COQDEBUG) $(COQFLAGS) -schedule-vio2vo $(J) $$VIOFILES; \
+ fi
+.PHONY: quick2vo
+
checkproofs:
$(TIMER) $(COQC) $(COQDEBUG) $(COQFLAGS) \
-schedule-vio-checking $(J) $(VOFILES:%.vo=%.vio)
diff --git a/tools/TimeFileMaker.py b/tools/TimeFileMaker.py
index a5a5fa8fe..0d24332f1 100644
--- a/tools/TimeFileMaker.py
+++ b/tools/TimeFileMaker.py
@@ -10,6 +10,20 @@ STRIP_REG = re.compile('^(coq/|contrib/|)(?:theories/|src/)?')
STRIP_REP = r'\1'
INFINITY = '\xe2\x88\x9e'
+def parse_args(argv, USAGE, HELP_STRING):
+ sort_by = 'auto'
+ if any(arg.startswith('--sort-by=') for arg in argv[1:]):
+ sort_by = [arg for arg in argv[1:] if arg.startswith('--sort-by=')][-1][len('--sort-by='):]
+ args = [arg for arg in argv if not arg.startswith('--sort-by=')]
+ if len(args) < 3 or '--help' in args[1:] or '-h' in args[1:] or sort_by not in ('auto', 'absolute', 'diff'):
+ print(USAGE)
+ if '--help' in args[1:] or '-h' in args[1:]:
+ print(HELP_STRING)
+ if len(args) == 2: sys.exit(0)
+ sys.exit(1)
+ return sort_by, args
+
+
def reformat_time_string(time):
seconds, milliseconds = time.split('.')
seconds = int(seconds)
@@ -108,6 +122,7 @@ def format_percentage(num, signed=True):
return sign + '%d.%02d%%' % (whole_part, frac_part)
def make_diff_table_string(left_times_dict, right_times_dict,
+ sort_by='auto',
descending=True,
left_tag="After", tag="File Name", right_tag="Before", with_percent=True,
change_tag="Change", percent_change_tag="% Change"):
@@ -125,10 +140,15 @@ def make_diff_table_string(left_times_dict, right_times_dict,
if rseconds != 0 else (INFINITY if lseconds > 0 else 'N/A')))
for name, lseconds, rseconds in prediff_times)
# update to sort by approximate difference, first
- get_key = make_sorting_key(all_names_dict, descending=descending)
- all_names_dict = dict((name, (fix_sign_for_sorting(int(abs(to_seconds(diff_times_dict[name]))), descending=descending), get_key(name)))
- for name in all_names_dict.keys())
- names = sorted(all_names_dict.keys(), key=all_names_dict.get)
+ get_key_abs = make_sorting_key(all_names_dict, descending=descending)
+ get_key_diff = (lambda name: fix_sign_for_sorting(int(abs(to_seconds(diff_times_dict[name]))), descending=descending))
+ if sort_by == 'absolute':
+ get_key = get_key_abs
+ elif sort_by == 'diff':
+ get_key = get_key_diff
+ else: # sort_by == 'auto'
+ get_key = (lambda name: (get_key_diff(name), get_key_abs(name)))
+ names = sorted(all_names_dict.keys(), key=get_key)
#names = get_sorted_file_list_from_times_dict(all_names_dict, descending=descending)
# set the widths of each of the columns by the longest thing to go in that column
left_sum = sum_times(left_times_dict.values())
diff --git a/tools/coq_makefile.ml b/tools/coq_makefile.ml
index 091869407..1e1862220 100644
--- a/tools/coq_makefile.ml
+++ b/tools/coq_makefile.ml
@@ -124,7 +124,7 @@ let read_whole_file s =
close_in ic;
Buffer.contents b
-let quote s = if String.contains s ' ' then "'" ^ s ^ "'" else s
+let quote s = if String.contains s ' ' || CString.is_empty s then "'" ^ s ^ "'" else s
let generate_makefile oc conf_file local_file args project =
let makefile_template =
diff --git a/tools/coqdep.ml b/tools/coqdep.ml
index fd4be08b1..ca14b11bc 100644
--- a/tools/coqdep.ml
+++ b/tools/coqdep.ml
@@ -455,7 +455,7 @@ let usage () =
eprintf " -coqlib dir : set the coq standard library directory\n";
eprintf " -suffix s : \n";
eprintf " -slash : deprecated, no effect\n";
- eprintf " -dyndep (opt|byte|both|no|var) : set how dependencies over ML modules are printed";
+ eprintf " -dyndep (opt|byte|both|no|var) : set how dependencies over ML modules are printed\n";
exit 1
let split_period = Str.split (Str.regexp (Str.quote "."))
@@ -539,4 +539,4 @@ let _ =
coqdep ()
with CErrors.UserError(s,p) ->
let pp = (match s with | None -> p | Some s -> Pp.(str s ++ str ": " ++ p)) in
- Feedback.msg_error pp
+ Format.eprintf "%a@\n%!" Pp.pp_with pp
diff --git a/tools/make-both-single-timing-files.py b/tools/make-both-single-timing-files.py
index 2d33503c3..32c52c7a1 100755
--- a/tools/make-both-single-timing-files.py
+++ b/tools/make-both-single-timing-files.py
@@ -3,16 +3,10 @@ import sys
from TimeFileMaker import *
if __name__ == '__main__':
- USAGE = 'Usage: %s AFTER_FILE_NAME BEFORE_FILE_NAME [OUTPUT_FILE_NAME ..]' % sys.argv[0]
+ USAGE = 'Usage: %s [--sort-by=auto|absolute|diff] AFTER_FILE_NAME BEFORE_FILE_NAME [OUTPUT_FILE_NAME ..]' % sys.argv[0]
HELP_STRING = r'''Formats timing information from the output of two invocations of `coqc -time` into a sorted table'''
- if len(sys.argv) < 3 or '--help' in sys.argv[1:] or '-h' in sys.argv[1:]:
- print(USAGE)
- if '--help' in sys.argv[1:] or '-h' in sys.argv[1:]:
- print(HELP_STRING)
- if len(sys.argv) == 2: sys.exit(0)
- sys.exit(1)
- else:
- left_dict = get_single_file_times(sys.argv[1])
- right_dict = get_single_file_times(sys.argv[2])
- table = make_diff_table_string(left_dict, right_dict, tag="Code")
- print_or_write_table(table, sys.argv[3:])
+ sort_by, args = parse_args(sys.argv, USAGE, HELP_STRING)
+ left_dict = get_single_file_times(args[1])
+ right_dict = get_single_file_times(args[2])
+ table = make_diff_table_string(left_dict, right_dict, tag="Code", sort_by=sort_by)
+ print_or_write_table(table, args[3:])
diff --git a/tools/make-both-time-files.py b/tools/make-both-time-files.py
index 69ec5a663..f730a8d6b 100755
--- a/tools/make-both-time-files.py
+++ b/tools/make-both-time-files.py
@@ -3,20 +3,14 @@ import sys
from TimeFileMaker import *
if __name__ == '__main__':
- USAGE = 'Usage: %s AFTER_FILE_NAME BEFORE_FILE_NAME [OUTPUT_FILE_NAME ..]' % sys.argv[0]
+ USAGE = 'Usage: %s [--sort-by=auto|absolute|diff] AFTER_FILE_NAME BEFORE_FILE_NAME [OUTPUT_FILE_NAME ..]' % sys.argv[0]
HELP_STRING = r'''Formats timing information from the output of two invocations of `make TIMED=1` into a sorted table.
The input is expected to contain lines in the format:
FILE_NAME (...user: NUMBER_IN_SECONDS...)
'''
- if len(sys.argv) < 3 or '--help' in sys.argv[1:] or '-h' in sys.argv[1:]:
- print(USAGE)
- if '--help' in sys.argv[1:] or '-h' in sys.argv[1:]:
- print(HELP_STRING)
- if len(sys.argv) == 2: sys.exit(0)
- sys.exit(1)
- else:
- left_dict = get_times(sys.argv[1])
- right_dict = get_times(sys.argv[2])
- table = make_diff_table_string(left_dict, right_dict)
- print_or_write_table(table, sys.argv[3:])
+ sort_by, args = parse_args(sys.argv, USAGE, HELP_STRING)
+ left_dict = get_times(args[1])
+ right_dict = get_times(args[2])
+ table = make_diff_table_string(left_dict, right_dict, sort_by=sort_by)
+ print_or_write_table(table, args[3:])
diff --git a/tools/md5sum.ml b/tools/md5sum.ml
new file mode 100644
index 000000000..2fdcacc83
--- /dev/null
+++ b/tools/md5sum.ml
@@ -0,0 +1,24 @@
+let get_content file =
+ let ic = open_in_bin file in
+ let buf = Buffer.create 2048 in
+ let rec fill () =
+ match input_char ic with
+ | '\r' -> fill () (* NOTE: handles the case on Windows where the
+ git checkout has included return characters.
+ See: https://github.com/coq/coq/pull/6305 *)
+ | c -> Buffer.add_char buf c; fill ()
+ | exception End_of_file -> close_in ic; Buffer.contents buf
+ in
+ fill ()
+
+let () =
+ match Sys.argv with
+ | [|_; file|] ->
+ let content = get_content file in
+ let md5 = Digest.to_hex (Digest.string content) in
+ print_string (md5 ^ " " ^ file)
+ | _ ->
+ prerr_endline "Error: This program needs exactly one parameter.";
+ prerr_endline "Usage: ocaml md5sum.ml <FILE>";
+ prerr_endline "Print MD5 (128-bit) checksum of the file content modulo \\r.";
+ exit 1
diff --git a/toplevel/coqargs.ml b/toplevel/coqargs.ml
new file mode 100644
index 000000000..5b73471c5
--- /dev/null
+++ b/toplevel/coqargs.ml
@@ -0,0 +1,575 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2018 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+let warning s = Flags.(with_option warn Feedback.msg_warning (Pp.strbrk s))
+
+let fatal_error ?extra exn =
+ Topfmt.print_err_exn ?extra exn;
+ let exit_code = if CErrors.(is_anomaly exn || not (handled exn)) then 129 else 1 in
+ exit exit_code
+
+let error_missing_arg s =
+ prerr_endline ("Error: extra argument expected after option "^s);
+ prerr_endline "See -help for the syntax of supported options";
+ exit 1
+
+(******************************************************************************)
+(* Imperative effects! This must be fixed at some point. *)
+(******************************************************************************)
+let set_worker_id opt s =
+ assert (s <> "master");
+ Flags.async_proofs_worker_id := s
+
+let set_type_in_type () =
+ let typing_flags = Environ.typing_flags (Global.env ()) in
+ Global.set_typing_flags { typing_flags with Declarations.check_universes = false }
+
+(******************************************************************************)
+
+type compilation_mode = BuildVo | BuildVio | Vio2Vo
+type color = [`ON | `AUTO | `OFF]
+
+type coq_cmdopts = {
+
+ load_init : bool;
+ load_rcfile : bool;
+ rcfile : string option;
+
+ ml_includes : string list;
+ vo_includes : (string * Names.DirPath.t * bool) list;
+ vo_requires : (string * string option * bool option) list;
+ (* None = No Import; Some false = Import; Some true = Export *)
+
+ (* XXX: Fusion? *)
+ batch_mode : bool;
+ compilation_mode : compilation_mode;
+
+ toplevel_name : Names.DirPath.t;
+ toploop : string option;
+
+ compile_list: (string * bool) list; (* bool is verbosity *)
+ compilation_output_name : string option;
+
+ load_vernacular_list : (string * bool) list;
+
+ vio_checking: bool;
+ vio_tasks : (int list * string) list;
+ vio_files : string list;
+ vio_files_j : int;
+
+ color : color;
+
+ impredicative_set : Declarations.set_predicativity;
+ stm_flags : Stm.AsyncOpts.stm_opt;
+ debug : bool;
+ time : bool;
+
+ filter_opts : bool;
+
+ glob_opt : bool;
+
+ memory_stat : bool;
+ print_tags : bool;
+ print_where : bool;
+ print_config: bool;
+ output_context : bool;
+
+ inputstate : string option;
+ outputstate : string option;
+
+}
+
+let init_args = {
+
+ load_init = true;
+ load_rcfile = true;
+ rcfile = None;
+
+ ml_includes = [];
+ vo_includes = [];
+ vo_requires = [];
+
+ batch_mode = false;
+ compilation_mode = BuildVo;
+
+ toplevel_name = Names.(DirPath.make [Id.of_string "Top"]);
+ toploop = None;
+
+ compile_list = [];
+ compilation_output_name = None;
+
+ load_vernacular_list = [];
+
+ vio_checking = false;
+ vio_tasks = [];
+ vio_files = [];
+ vio_files_j = 0;
+
+ color = `AUTO;
+
+ impredicative_set = Declarations.PredicativeSet;
+ stm_flags = Stm.AsyncOpts.default_opts;
+ debug = false;
+ time = false;
+
+ filter_opts = false;
+
+ glob_opt = false;
+
+ memory_stat = false;
+ print_tags = false;
+ print_where = false;
+ print_config = false;
+ output_context = false;
+
+ inputstate = None;
+ outputstate = None;
+}
+
+(******************************************************************************)
+(* Functional arguments *)
+(******************************************************************************)
+let add_ml_include opts s =
+ { opts with ml_includes = s :: opts.ml_includes }
+
+let add_vo_include opts d p implicit =
+ let p = Libnames.dirpath_of_string p in
+ { opts with vo_includes = (d, p, implicit) :: opts.vo_includes }
+
+let add_vo_require opts d p export =
+ { opts with vo_requires = (d, p, export) :: opts.vo_requires }
+
+let add_compat_require opts v =
+ match v with
+ | Flags.V8_5 -> add_vo_require opts "Coq.Compat.Coq85" None (Some false)
+ | Flags.V8_6 -> add_vo_require opts "Coq.Compat.Coq86" None (Some false)
+ | Flags.V8_7 -> add_vo_require opts "Coq.Compat.Coq87" None (Some false)
+ | Flags.VOld | Flags.Current -> opts
+
+let set_batch_mode opts =
+ Flags.quiet := true;
+ System.trust_file_cache := false;
+ { opts with batch_mode = true }
+
+let add_compile opts verbose s =
+ let opts = set_batch_mode opts in
+ if not opts.glob_opt then Dumpglob.dump_to_dotglob ();
+ (** make the file name explicit; needed not to break up Coq loadpath stuff. *)
+ let s =
+ let open Filename in
+ if is_implicit s
+ then concat current_dir_name s
+ else s
+ in
+ { opts with compile_list = (s,verbose) :: opts.compile_list }
+
+let add_load_vernacular opts verb s =
+ { opts with load_vernacular_list = (CUnix.make_suffix s ".v",verb) :: opts.load_vernacular_list }
+
+let add_vio_task opts f =
+ let opts = set_batch_mode opts in
+ { opts with vio_tasks = f :: opts.vio_tasks }
+
+let add_vio_file opts f =
+ let opts = set_batch_mode opts in
+ { opts with vio_files = f :: opts.vio_files }
+
+let set_vio_checking_j opts opt j =
+ try { opts with vio_files_j = int_of_string j }
+ with Failure _ ->
+ prerr_endline ("The first argument of " ^ opt ^ " must the number");
+ prerr_endline "of concurrent workers to be used (a positive integer).";
+ prerr_endline "Makefiles generated by coq_makefile should be called";
+ prerr_endline "setting the J variable like in 'make vio2vo J=3'";
+ exit 1
+
+(** Options for proof general *)
+let set_emacs opts =
+ if not (Option.is_empty opts.toploop) then
+ CErrors.user_err Pp.(str "Flag -emacs is incompatible with a custom toplevel loop");
+ Coqloop.print_emacs := true;
+ Printer.enable_goal_tags_printing := true;
+ { opts with color = `OFF }
+
+let set_color opts = function
+| "yes" | "on" -> { opts with color = `ON }
+| "no" | "off" -> { opts with color = `OFF }
+| "auto" -> { opts with color = `AUTO }
+| _ -> prerr_endline ("Error: on/off/auto expected after option color"); exit 1
+
+let warn_deprecated_inputstate =
+ CWarnings.create ~name:"deprecated-inputstate" ~category:"deprecated"
+ (fun () -> Pp.strbrk "The inputstate option is deprecated and discouraged.")
+
+let set_inputstate opts s =
+ warn_deprecated_inputstate ();
+ { opts with inputstate = Some s }
+
+let warn_deprecated_outputstate =
+ CWarnings.create ~name:"deprecated-outputstate" ~category:"deprecated"
+ (fun () ->
+ Pp.strbrk "The outputstate option is deprecated and discouraged.")
+
+let set_outputstate opts s =
+ warn_deprecated_outputstate ();
+ { opts with outputstate = Some s }
+
+let exitcode opts = if opts.filter_opts then 2 else 0
+
+(******************************************************************************)
+(* Parsing helpers *)
+(******************************************************************************)
+let get_task_list s = List.map int_of_string (Str.split (Str.regexp ",") s)
+
+let get_bool opt = function
+ | "yes" | "on" -> true
+ | "no" | "off" -> false
+ | _ -> prerr_endline ("Error: yes/no expected after option "^opt); exit 1
+
+let get_int opt n =
+ try int_of_string n
+ with Failure _ ->
+ prerr_endline ("Error: integer expected after option "^opt); exit 1
+
+let get_float opt n =
+ try float_of_string n
+ with Failure _ ->
+ prerr_endline ("Error: float expected after option "^opt); exit 1
+
+let get_host_port opt s =
+ match CString.split ':' s with
+ | [host; portr; portw] ->
+ Some (Spawned.Socket(host, int_of_string portr, int_of_string portw))
+ | ["stdfds"] -> Some Spawned.AnonPipe
+ | _ ->
+ prerr_endline ("Error: host:portr:portw or stdfds expected after option "^opt);
+ exit 1
+
+let get_error_resilience opt = function
+ | "on" | "all" | "yes" -> `All
+ | "off" | "no" -> `None
+ | s -> `Only (CString.split ',' s)
+
+let get_priority opt s =
+ try CoqworkmgrApi.priority_of_string s
+ with Invalid_argument _ ->
+ prerr_endline ("Error: low/high expected after "^opt); exit 1
+
+let get_async_proofs_mode opt = let open Stm.AsyncOpts in function
+ | "no" | "off" -> APoff
+ | "yes" | "on" -> APon
+ | "lazy" -> APonLazy
+ | _ -> prerr_endline ("Error: on/off/lazy expected after "^opt); exit 1
+
+let get_cache opt = function
+ | "force" -> Some Stm.AsyncOpts.Force
+ | _ -> prerr_endline ("Error: force expected after "^opt); exit 1
+
+let is_not_dash_option = function
+ | Some f when String.length f > 0 && f.[0] <> '-' -> true
+ | _ -> false
+
+let rec add_vio_args peek next oval =
+ if is_not_dash_option (peek ()) then
+ let oval = add_vio_file oval (next ()) in
+ add_vio_args peek next oval
+ else oval
+
+let get_native_name s =
+ (* We ignore even critical errors because this mode has to be super silent *)
+ try
+ String.concat "/" [Filename.dirname s;
+ Nativelib.output_dir; Library.native_name_from_filename s]
+ with _ -> ""
+
+(*s Parsing of the command line.
+ We no longer use [Arg.parse], in order to use share [Usage.print_usage]
+ between coqtop and coqc. *)
+
+let usage_no_coqlib = CWarnings.create ~name:"usage-no-coqlib" ~category:"filesystem"
+ (fun () -> Pp.str "cannot guess a path for Coq libraries; dynaminally loaded flags will not be mentioned")
+
+exception NoCoqLib
+
+let usage batch =
+ begin
+ try Envars.set_coqlib ~fail:(fun x -> raise NoCoqLib)
+ with NoCoqLib -> usage_no_coqlib ()
+ end;
+ let lp = Coqinit.toplevel_init_load_path () in
+ (* Necessary for finding the toplevels below *)
+ List.iter Mltop.add_coq_path lp;
+ if batch then Usage.print_usage_coqc ()
+ else begin
+ Mltop.load_ml_objects_raw_rex
+ (Str.regexp (if Mltop.is_native then "^.*top.cmxs$" else "^.*top.cma$"));
+ Usage.print_usage_coqtop ()
+ end
+
+(* Main parsing routine *)
+let parse_args arglist : coq_cmdopts * string list =
+ let args = ref arglist in
+ let extras = ref [] in
+ let rec parse oval = match !args with
+ | [] ->
+ (oval, List.rev !extras)
+ | opt :: rem ->
+ args := rem;
+ let next () = match !args with
+ | x::rem -> args := rem; x
+ | [] -> error_missing_arg opt
+ in
+ let peek_next () = match !args with
+ | x::_ -> Some x
+ | [] -> None
+ in
+ let noval = begin match opt with
+
+ (* Complex options with many args *)
+ |"-I"|"-include" ->
+ begin match rem with
+ | d :: rem ->
+ args := rem;
+ add_ml_include oval d
+ | [] -> error_missing_arg opt
+ end
+ |"-Q" ->
+ begin match rem with
+ | d :: p :: rem ->
+ args := rem;
+ add_vo_include oval d p false
+ | _ -> error_missing_arg opt
+ end
+ |"-R" ->
+ begin match rem with
+ | d :: p :: rem ->
+ args := rem;
+ add_vo_include oval d p true
+ | _ -> error_missing_arg opt
+ end
+
+ (* Options with two arg *)
+ |"-check-vio-tasks" ->
+ let tno = get_task_list (next ()) in
+ let tfile = next () in
+ add_vio_task oval (tno,tfile)
+
+ |"-schedule-vio-checking" ->
+ let oval = { oval with vio_checking = true } in
+ let oval = set_vio_checking_j oval opt (next ()) in
+ let oval = add_vio_file oval (next ()) in
+ add_vio_args peek_next next oval
+
+ |"-schedule-vio2vo" ->
+ let oval = set_vio_checking_j oval opt (next ()) in
+ let oval = add_vio_file oval (next ()) in
+ add_vio_args peek_next next oval
+
+ (* Options with one arg *)
+ |"-coqlib" ->
+ Flags.coqlib_spec := true;
+ Flags.coqlib := (next ());
+ oval
+
+ |"-async-proofs" ->
+ { oval with stm_flags = { oval.stm_flags with
+ Stm.AsyncOpts.async_proofs_mode = get_async_proofs_mode opt (next())
+ }}
+ |"-async-proofs-j" ->
+ { oval with stm_flags = { oval.stm_flags with
+ Stm.AsyncOpts.async_proofs_n_workers = (get_int opt (next ()))
+ }}
+ |"-async-proofs-cache" ->
+ { oval with stm_flags = { oval.stm_flags with
+ Stm.AsyncOpts.async_proofs_cache = get_cache opt (next ())
+ }}
+
+ |"-async-proofs-tac-j" ->
+ { oval with stm_flags = { oval.stm_flags with
+ Stm.AsyncOpts.async_proofs_n_tacworkers = (get_int opt (next ()))
+ }}
+
+ |"-async-proofs-worker-priority" ->
+ WorkerLoop.async_proofs_worker_priority := get_priority opt (next ());
+ oval
+
+ |"-async-proofs-private-flags" ->
+ { oval with stm_flags = { oval.stm_flags with
+ Stm.AsyncOpts.async_proofs_private_flags = Some (next ());
+ }}
+
+ |"-async-proofs-tactic-error-resilience" ->
+ { oval with stm_flags = { oval.stm_flags with
+ Stm.AsyncOpts.async_proofs_tac_error_resilience = get_error_resilience opt (next ())
+ }}
+
+ |"-async-proofs-command-error-resilience" ->
+ { oval with stm_flags = { oval.stm_flags with
+ Stm.AsyncOpts.async_proofs_cmd_error_resilience = get_bool opt (next ())
+ }}
+
+ |"-async-proofs-delegation-threshold" ->
+ { oval with stm_flags = { oval.stm_flags with
+ Stm.AsyncOpts.async_proofs_delegation_threshold = get_float opt (next ())
+ }}
+
+ |"-worker-id" -> set_worker_id opt (next ()); oval
+
+ |"-compat" ->
+ let v = G_vernac.parse_compat_version ~allow_old:false (next ()) in
+ Flags.compat_version := v;
+ add_compat_require oval v
+
+ |"-compile" ->
+ add_compile oval false (next ())
+
+ |"-compile-verbose" ->
+ add_compile oval true (next ())
+
+ |"-dump-glob" ->
+ Dumpglob.dump_into_file (next ());
+ { oval with glob_opt = true }
+
+ |"-feedback-glob" ->
+ Dumpglob.feedback_glob (); oval
+
+ |"-exclude-dir" ->
+ System.exclude_directory (next ()); oval
+
+ |"-init-file" ->
+ { oval with rcfile = Some (next ()); }
+
+ |"-inputstate"|"-is" ->
+ set_inputstate oval (next ())
+
+ |"-outputstate" ->
+ set_outputstate oval (next ())
+
+ |"-load-ml-object" ->
+ Mltop.dir_ml_load (next ()); oval
+
+ |"-load-ml-source" ->
+ Mltop.dir_ml_use (next ()); oval
+
+ |"-load-vernac-object" ->
+ add_vo_require oval (next ()) None None
+
+ |"-load-vernac-source"|"-l" ->
+ add_load_vernacular oval false (next ())
+
+ |"-load-vernac-source-verbose"|"-lv" ->
+ add_load_vernacular oval true (next ())
+
+ |"-print-mod-uid" ->
+ let s = String.concat " " (List.map get_native_name rem) in print_endline s; exit 0
+
+ |"-profile-ltac-cutoff" ->
+ Flags.profile_ltac := true;
+ Flags.profile_ltac_cutoff := get_float opt (next ());
+ oval
+
+ |"-require" -> add_vo_require oval (next ()) None (Some false)
+
+ |"-top" ->
+ let topname = Libnames.dirpath_of_string (next ()) in
+ if Names.DirPath.is_empty topname then
+ CErrors.user_err Pp.(str "Need a non empty toplevel module name");
+ { oval with toplevel_name = topname }
+
+ |"-main-channel" ->
+ Spawned.main_channel := get_host_port opt (next()); oval
+
+ |"-control-channel" ->
+ Spawned.control_channel := get_host_port opt (next()); oval
+
+ |"-vio2vo" ->
+ let oval = add_compile oval false (next ()) in
+ { oval with compilation_mode = Vio2Vo }
+
+ |"-toploop" ->
+ if !Coqloop.print_emacs then
+ CErrors.user_err Pp.(str "Flags -toploop and -emacs are incompatible");
+ { oval with toploop = Some (next ()) }
+
+ |"-w" | "-W" ->
+ let w = next () in
+ if w = "none" then
+ (CWarnings.set_flags w; oval)
+ else
+ let w = CWarnings.get_flags () ^ "," ^ w in
+ CWarnings.set_flags (CWarnings.normalize_flags_string w);
+ oval
+
+ |"-o" -> { oval with compilation_output_name = Some (next()) }
+
+ (* Options with zero arg *)
+ |"-async-queries-always-delegate"
+ |"-async-proofs-always-delegate"
+ |"-async-proofs-full" ->
+ { oval with stm_flags = { oval.stm_flags with
+ Stm.AsyncOpts.async_proofs_full = true;
+ }}
+ |"-async-proofs-never-reopen-branch" ->
+ { oval with stm_flags = { oval.stm_flags with
+ Stm.AsyncOpts.async_proofs_never_reopen_branch = true
+ }}
+ |"-batch" -> set_batch_mode oval
+ |"-test-mode" -> Flags.test_mode := true; oval
+ |"-beautify" -> Flags.beautify := true; oval
+ |"-boot" -> Flags.boot := true; { oval with load_rcfile = false; }
+ |"-bt" -> Backtrace.record_backtrace true; oval
+ |"-color" -> set_color oval (next ())
+ |"-config"|"--config" -> { oval with print_config = true }
+ |"-debug" -> Coqinit.set_debug (); oval
+ |"-stm-debug" -> Stm.stm_debug := true; oval
+ |"-emacs" -> set_emacs oval
+ |"-filteropts" -> { oval with filter_opts = true }
+ |"-ideslave" ->
+ if !Coqloop.print_emacs then
+ CErrors.user_err Pp.(str "Flags -ideslave and -emacs are incompatible");
+ Flags.ide_slave := true;
+ { oval with toploop = Some "coqidetop" }
+
+ |"-impredicative-set" ->
+ { oval with impredicative_set = Declarations.ImpredicativeSet }
+ |"-indices-matter" -> Indtypes.enforce_indices_matter (); oval
+ |"-m"|"--memory" -> { oval with memory_stat = true }
+ |"-noinit"|"-nois" -> { oval with load_init = false }
+ |"-no-glob"|"-noglob" -> Dumpglob.noglob (); { oval with glob_opt = true }
+ |"-native-compiler" ->
+ if not Coq_config.native_compiler then
+ warning "Native compilation was disabled at configure time."
+ else Flags.output_native_objects := true; oval
+ |"-output-context" -> { oval with output_context = true }
+ |"-profile-ltac" -> Flags.profile_ltac := true; oval
+ |"-q" -> { oval with load_rcfile = false; }
+ |"-quiet"|"-silent" ->
+ Flags.quiet := true;
+ Flags.make_warn false;
+ oval
+ |"-quick" -> { oval with compilation_mode = BuildVio }
+ |"-list-tags" -> { oval with print_tags = true }
+ |"-time" -> { oval with time = true }
+ |"-type-in-type" -> set_type_in_type (); oval
+ |"-unicode" -> add_vo_require oval "Utf8_core" None (Some false)
+ |"-where" -> { oval with print_where = true }
+ |"-h"|"-H"|"-?"|"-help"|"--help" -> usage oval.batch_mode; oval
+ |"-v"|"--version" -> Usage.version (exitcode oval)
+ |"-print-version"|"--print-version" ->
+ Usage.machine_readable_version (exitcode oval)
+
+ (* Unknown option *)
+ | s ->
+ extras := s :: !extras;
+ oval
+ end in
+ parse noval
+ in
+ try
+ parse init_args
+ with any -> fatal_error any
diff --git a/toplevel/coqargs.mli b/toplevel/coqargs.mli
new file mode 100644
index 000000000..8ee1a8f55
--- /dev/null
+++ b/toplevel/coqargs.mli
@@ -0,0 +1,63 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2018 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+type compilation_mode = BuildVo | BuildVio | Vio2Vo
+type color = [`ON | `AUTO | `OFF]
+
+type coq_cmdopts = {
+
+ load_init : bool;
+ load_rcfile : bool;
+ rcfile : string option;
+
+ ml_includes : string list;
+ vo_includes : (string * Names.DirPath.t * bool) list;
+ vo_requires : (string * string option * bool option) list;
+
+ (* Fuse these two? Currently, [batch_mode] is only used to
+ distinguish coqc / coqtop in help display. *)
+ batch_mode : bool;
+ compilation_mode : compilation_mode;
+
+ toplevel_name : Names.DirPath.t;
+ toploop : string option;
+
+ compile_list: (string * bool) list; (* bool is verbosity *)
+ compilation_output_name : string option;
+
+ load_vernacular_list : (string * bool) list;
+
+ vio_checking: bool;
+ vio_tasks : (int list * string) list;
+ vio_files : string list;
+ vio_files_j : int;
+
+ color : color;
+
+ impredicative_set : Declarations.set_predicativity;
+ stm_flags : Stm.AsyncOpts.stm_opt;
+ debug : bool;
+ time : bool;
+
+ filter_opts : bool;
+
+ glob_opt : bool;
+
+ memory_stat : bool;
+ print_tags : bool;
+ print_where : bool;
+ print_config: bool;
+ output_context : bool;
+
+ inputstate : string option;
+ outputstate : string option;
+
+}
+
+val parse_args : string list -> coq_cmdopts * string list
+val exitcode : coq_cmdopts -> int
diff --git a/toplevel/coqinit.ml b/toplevel/coqinit.ml
index 176dfb3c9..8574092b8 100644
--- a/toplevel/coqinit.ml
+++ b/toplevel/coqinit.ml
@@ -20,21 +20,15 @@ let set_debug () =
does not exist. *)
let rcdefaultname = "coqrc"
-let rcfile = ref ""
-let rcfile_specified = ref false
-let set_rcfile s = rcfile := s; rcfile_specified := true
-let load_rc = ref true
-let no_load_rc () = load_rc := false
-
-let load_rcfile ~time doc sid =
- if !load_rc then
+let load_rcfile ~rcfile ~time doc sid =
try
- if !rcfile_specified then
- if CUnix.file_readable_p !rcfile then
- Vernac.load_vernac ~time ~verbosely:false ~interactive:false ~check:true doc sid !rcfile
- else raise (Sys_error ("Cannot read rcfile: "^ !rcfile))
- else
+ match rcfile with
+ | Some rcfile ->
+ if CUnix.file_readable_p rcfile then
+ Vernac.load_vernac ~time ~verbosely:false ~interactive:false ~check:true doc sid rcfile
+ else raise (Sys_error ("Cannot read rcfile: "^ rcfile))
+ | None ->
try
let warn x = Feedback.msg_warning (str x) in
let inferedrc = List.find CUnix.file_readable_p [
@@ -54,71 +48,79 @@ let load_rcfile ~time doc sid =
let reraise = CErrors.push reraise in
let () = Feedback.msg_info (str"Load of rcfile failed.") in
iraise reraise
- else
- (Flags.if_verbose Feedback.msg_info (str"Skipping rcfile loading.");
- doc, sid)
(* Recursively puts dir in the LoadPath if -nois was not passed *)
-let add_stdlib_path ~load_init ~unix_path ~coq_root ~with_ml =
- let add_ml = if with_ml then Mltop.AddRecML else Mltop.AddNoML in
- Mltop.add_rec_path add_ml ~unix_path ~coq_root ~implicit:load_init
-
-let add_userlib_path ~unix_path =
- Mltop.add_rec_path Mltop.AddRecML ~unix_path
- ~coq_root:Libnames.default_root_prefix ~implicit:false
-
-(* Options -I, -I-as, and -R of the command line *)
-let includes = ref []
-let push_include s alias implicit =
- includes := (s, alias, implicit) :: !includes
-let ml_includes = ref []
-let push_ml_include s = ml_includes := s :: !ml_includes
-
-(* Initializes the LoadPath *)
-let init_load_path ~load_init =
+let build_stdlib_path ~load_init ~unix_path ~coq_path ~with_ml =
+ let open Mltop in
+ let add_ml = if with_ml then AddRecML else AddNoML in
+ { recursive = true;
+ path_spec = VoPath { unix_path; coq_path ; has_ml = add_ml; implicit = load_init }
+ }
+
+let build_userlib_path ~unix_path =
+ let open Mltop in
+ { recursive = true;
+ path_spec = VoPath {
+ unix_path;
+ coq_path = Libnames.default_root_prefix;
+ has_ml = Mltop.AddRecML;
+ implicit = false;
+ }
+ }
+
+let ml_path_if c p =
+ let open Mltop in
+ let f x = { recursive = false; path_spec = MlPath x } in
+ if c then List.map f p else []
+
+(* LoadPath for toploop toplevels *)
+let toplevel_init_load_path () =
+ let coqlib = Envars.coqlib () in
+ (* NOTE: These directories are searched from last to first *)
+ (* first, developer specific directory to open *)
+ ml_path_if Coq_config.local [coqlib/"dev"] @
+
+ (* main loops *)
+ ml_path_if (Coq_config.local || !Flags.boot) [coqlib/"stm"; coqlib/"ide"] @
+ ml_path_if (System.exists_dir (coqlib/"toploop")) [coqlib/"toploop"]
+
+(* LoadPath for Coq user libraries *)
+let libs_init_load_path ~load_init =
+
+ let open Mltop in
let coqlib = Envars.coqlib () in
let user_contrib = coqlib/"user-contrib" in
let xdg_dirs = Envars.xdg_dirs ~warn:(fun x -> Feedback.msg_warning (str x)) in
let coqpath = Envars.coqpath in
- let coq_root = Names.DirPath.make [Libnames.coq_root] in
- (* NOTE: These directories are searched from last to first *)
- (* first, developer specific directory to open *)
- if Coq_config.local then
- Mltop.add_ml_dir (coqlib/"dev");
- (* main loops *)
- if Coq_config.local || !Flags.boot then begin
- Mltop.add_ml_dir (coqlib/"stm");
- Mltop.add_ml_dir (coqlib/"ide")
- end;
- if System.exists_dir (coqlib/"toploop") then
- Mltop.add_ml_dir (coqlib/"toploop");
- (* then standard library *)
- add_stdlib_path ~load_init ~unix_path:(coqlib/"theories") ~coq_root ~with_ml:false;
- (* then plugins *)
- add_stdlib_path ~load_init ~unix_path:(coqlib/"plugins") ~coq_root ~with_ml:true;
- (* then user-contrib *)
- if Sys.file_exists user_contrib then
- add_userlib_path ~unix_path:user_contrib;
- (* then directories in XDG_DATA_DIRS and XDG_DATA_HOME *)
- List.iter (fun s -> add_userlib_path ~unix_path:s) xdg_dirs;
- (* then directories in COQPATH *)
- List.iter (fun s -> add_userlib_path ~unix_path:s) coqpath;
- (* then current directory (not recursively!) *)
- Mltop.add_ml_dir ".";
- Loadpath.add_load_path "." Libnames.default_root_prefix ~implicit:false;
- (* additional loadpath, given with options -Q and -R *)
- List.iter
- (fun (unix_path, coq_root, implicit) ->
- Mltop.add_rec_path Mltop.AddNoML ~unix_path ~coq_root ~implicit)
- (List.rev !includes);
- (* additional ml directories, given with option -I *)
- List.iter Mltop.add_ml_dir (List.rev !ml_includes)
+ let coq_path = Names.DirPath.make [Libnames.coq_root] in
+
+ (* then standard library and plugins *)
+ [build_stdlib_path ~load_init ~unix_path:(coqlib/"theories") ~coq_path ~with_ml:false;
+ build_stdlib_path ~load_init ~unix_path:(coqlib/"plugins") ~coq_path ~with_ml:true ] @
+
+ (* then user-contrib *)
+ (if Sys.file_exists user_contrib then
+ [build_userlib_path ~unix_path:user_contrib] else []
+ ) @
+
+ (* then directories in XDG_DATA_DIRS and XDG_DATA_HOME and COQPATH *)
+ List.map (fun s -> build_userlib_path ~unix_path:s) (xdg_dirs @ coqpath) @
+
+ (* then current directory (not recursively!) *)
+ [ { recursive = false;
+ path_spec = VoPath { unix_path = ".";
+ coq_path = Libnames.default_root_prefix;
+ implicit = false;
+ has_ml = AddTopML }
+ } ]
(* Initialises the Ocaml toplevel before launching it, so that it can
find the "include" file in the *source* directory *)
let init_ocaml_path () =
+ let open Mltop in
+ let lp s = { recursive = false; path_spec = MlPath s } in
let add_subdir dl =
- Mltop.add_ml_dir (List.fold_left (/) Envars.coqroot [dl])
+ Mltop.add_coq_path (lp (List.fold_left (/) Envars.coqroot [dl]))
in
- Mltop.add_ml_dir (Envars.coqlib ());
+ Mltop.add_coq_path (lp (Envars.coqlib ()));
List.iter add_subdir Coq_config.all_src_dirs
diff --git a/toplevel/coqinit.mli b/toplevel/coqinit.mli
index c3fd72754..0ceba5b38 100644
--- a/toplevel/coqinit.mli
+++ b/toplevel/coqinit.mli
@@ -10,16 +10,12 @@
val set_debug : unit -> unit
-val set_rcfile : string -> unit
+val load_rcfile : rcfile:(string option) -> time:bool -> Stm.doc -> Stateid.t -> Stm.doc * Stateid.t
-val no_load_rc : unit -> unit
-val load_rcfile : time:bool -> Stm.doc -> Stateid.t -> Stm.doc * Stateid.t
-
-val push_include : string -> Names.DirPath.t -> bool -> unit
-(** [push_include phys_path log_path implicit] *)
-
-val push_ml_include : string -> unit
+val init_ocaml_path : unit -> unit
-val init_load_path : load_init:bool -> unit
+(* LoadPath for toploop toplevels *)
+val toplevel_init_load_path : unit -> Mltop.coq_path list
-val init_ocaml_path : unit -> unit
+(* LoadPath for Coq user libraries *)
+val libs_init_load_path : load_init:bool -> Mltop.coq_path list
diff --git a/toplevel/coqloop.ml b/toplevel/coqloop.ml
index 5c1b27c33..aade101a4 100644
--- a/toplevel/coqloop.ml
+++ b/toplevel/coqloop.ml
@@ -312,7 +312,7 @@ let do_vernac ~time doc sid =
top_stderr (fnl ()); raise CErrors.Quit
| CErrors.Drop -> (* Last chance *)
if Mltop.is_ocaml_top() then raise CErrors.Drop
- else (Feedback.msg_error (str "There is no ML toplevel."); doc, sid)
+ else (Feedback.msg_warning (str "There is no ML toplevel."); doc, sid)
(* Exception printing should be done by the feedback listener,
however this is not yet ready so we rely on the exception for
now. *)
@@ -353,7 +353,7 @@ let rec loop ~time doc =
| CErrors.Drop -> doc
| CErrors.Quit -> exit 0
| any ->
- Feedback.msg_error (str "Anomaly: main loop exited with exception: " ++
+ top_stderr (str "Anomaly: main loop exited with exception: " ++
str (Printexc.to_string any) ++
fnl() ++
str"Please report" ++
diff --git a/toplevel/coqtop.ml b/toplevel/coqtop.ml
index a3a4e20af..9058f0846 100644
--- a/toplevel/coqtop.ml
+++ b/toplevel/coqtop.ml
@@ -7,8 +7,7 @@
(************************************************************************)
open Pp
-open CErrors
-open Libnames
+open Coqargs
let () = at_exit flush_all
@@ -31,66 +30,21 @@ let print_header () =
let warning s = Flags.(with_option warn Feedback.msg_warning (strbrk s))
-let toploop = ref None
-
-let color : [`ON | `AUTO | `OFF] ref = ref `AUTO
-let set_color = function
-| "yes" | "on" -> color := `ON
-| "no" | "off" -> color := `OFF
-| "auto" -> color := `AUTO
-| _ -> prerr_endline ("Error: on/off/auto expected after option color"); exit 1
-
-let init_color () =
- let has_color = match !color with
- | `OFF -> false
- | `ON -> true
- | `AUTO ->
- Terminal.has_style Unix.stdout &&
- Terminal.has_style Unix.stderr &&
- (* emacs compilation buffer does not support colors by default,
- its TERM variable is set to "dumb". *)
- try Sys.getenv "TERM" <> "dumb" with Not_found -> false
- in
- if has_color then begin
- let colors = try Some (Sys.getenv "COQ_COLORS") with Not_found -> None in
- match colors with
- | None ->
- (** Default colors *)
- Topfmt.init_terminal_output ~color:true
- | Some "" ->
- (** No color output *)
- Topfmt.init_terminal_output ~color:false
- | Some s ->
- (** Overwrite all colors *)
- Topfmt.clear_styles ();
- Topfmt.parse_color_config s;
- Topfmt.init_terminal_output ~color:true
- end
- else
- Topfmt.init_terminal_output ~color:false
-
-let toploop_init = ref begin fun x ->
- let () = init_color () in
- let () = CoqworkmgrApi.init !WorkerLoop.async_proofs_worker_priority in
- x
- end
-
(* Feedback received in the init stage, this is different as the STM
will not be generally be initialized, thus stateid, etc... may be
bogus. For now we just print to the console too *)
let coqtop_init_feed = Coqloop.coqloop_feed
let drop_last_doc = ref None
-let measure_time = ref false
(* Default toplevel loop *)
-let console_toploop_run doc =
+let console_toploop_run opts doc =
(* We initialize the console only if we run the toploop_run *)
let tl_feed = Feedback.add_feeder Coqloop.coqloop_feed in
if Dumpglob.dump () then begin
Flags.if_verbose warning "Dumpglob cannot be used in interactive mode.";
Dumpglob.noglob ()
end;
- let doc = Coqloop.loop ~time:!measure_time doc in
+ let doc = Coqloop.loop ~time:opts.time doc in
(* Initialise and launch the Ocaml toplevel *)
drop_last_doc := Some doc;
Coqinit.init_ocaml_path();
@@ -100,10 +54,7 @@ let console_toploop_run doc =
let toploop_run = ref console_toploop_run
-let output_context = ref false
-
let memory_stat = ref false
-
let print_memory_stat () =
begin (* -m|--memory from the command-line *)
if !memory_stat then
@@ -124,133 +75,87 @@ let print_memory_stat () =
let _ = at_exit print_memory_stat
(******************************************************************************)
-(* Engagement *)
-(******************************************************************************)
-let impredicative_set = ref Declarations.PredicativeSet
-let set_impredicative_set c = impredicative_set := Declarations.ImpredicativeSet
-let set_type_in_type () =
- let typing_flags = Environ.typing_flags (Global.env ()) in
- Global.set_typing_flags { typing_flags with Declarations.check_universes = false }
-let engage () =
- Global.set_engagement !impredicative_set
-
-(******************************************************************************)
-(* Interactive toplevel name *)
-(******************************************************************************)
-let toplevel_default_name = Names.(DirPath.make [Id.of_string "Top"])
-let toplevel_name = ref toplevel_default_name
-let set_toplevel_name dir =
- if Names.DirPath.is_empty dir then user_err Pp.(str "Need a non empty toplevel module name");
- toplevel_name := dir
-
-(******************************************************************************)
(* Input/Output State *)
(******************************************************************************)
-let warn_deprecated_inputstate =
- CWarnings.create ~name:"deprecated-inputstate" ~category:"deprecated"
- (fun () -> strbrk "The inputstate option is deprecated and discouraged.")
-
-let inputstate = ref ""
-let set_inputstate s =
- warn_deprecated_inputstate ();
- inputstate:=s
-let inputstate () =
- if not (CString.is_empty !inputstate) then
- let fname = Loadpath.locate_file (CUnix.make_suffix !inputstate ".coq") in
- States.intern_state fname
-
-let warn_deprecated_outputstate =
- CWarnings.create ~name:"deprecated-outputstate" ~category:"deprecated"
- (fun () ->
- strbrk "The outputstate option is deprecated and discouraged.")
-
-let outputstate = ref ""
-let set_outputstate s =
- warn_deprecated_outputstate ();
- outputstate:=s
-let outputstate () =
- if not (CString.is_empty !outputstate) then
- let fname = CUnix.make_suffix !outputstate ".coq" in
- States.extern_state fname
+let inputstate opts =
+ Option.iter (fun istate_file ->
+ let fname = Loadpath.locate_file (CUnix.make_suffix istate_file ".coq") in
+ States.intern_state fname) opts.inputstate
+
+let outputstate opts =
+ Option.iter (fun ostate_file ->
+ let fname = CUnix.make_suffix ostate_file ".coq" in
+ States.extern_state fname) opts.outputstate
(******************************************************************************)
(* Interactive Load File Simulation *)
(******************************************************************************)
-let load_vernacular_list = ref ([] : (string * bool) list)
-
-let add_load_vernacular verb s =
- load_vernacular_list := ((CUnix.make_suffix s ".v"),verb) :: !load_vernacular_list
-
-let load_vernacular ~time doc sid =
+let load_vernacular opts doc sid =
List.fold_left
(fun (doc,sid) (f_in, verbosely) ->
let s = Loadpath.locate_file f_in in
if !Flags.beautify then
- Flags.with_option Flags.beautify_file (Vernac.load_vernac ~time ~verbosely ~interactive:false ~check:true doc sid) f_in
+ Flags.with_option Flags.beautify_file (Vernac.load_vernac ~time:opts.time ~verbosely ~interactive:false ~check:true doc sid) f_in
else
- Vernac.load_vernac ~time ~verbosely ~interactive:false ~check:true doc sid s)
- (doc, sid) (List.rev !load_vernacular_list)
-
-let load_init_vernaculars ~time doc sid =
- let doc, sid = Coqinit.load_rcfile ~time doc sid in
- load_vernacular ~time doc sid
+ Vernac.load_vernac ~time:opts.time ~verbosely ~interactive:false ~check:true doc sid s)
+ (doc, sid) (List.rev opts.load_vernacular_list)
+
+let load_init_vernaculars opts doc sid =
+ let doc, sid = if opts.load_rcfile then
+ Coqinit.load_rcfile ~rcfile:opts.rcfile ~time:opts.time doc sid
+ else begin
+ Flags.if_verbose Feedback.msg_info (str"Skipping rcfile loading.");
+ doc,sid
+ end in
+ load_vernacular opts doc sid
(******************************************************************************)
-(* Required Modules *)
+(* Startup LoadPath and Modules *)
(******************************************************************************)
-let set_include d p implicit =
- let p = dirpath_of_string p in
- Coqinit.push_include d p implicit
-
-(* None = No Import; Some false = Import; Some true = Export *)
-let require_list = ref ([] : (string * string option * bool option) list)
-let add_require s = require_list := s :: !require_list
+(* prelude_data == From Coq Require Export Prelude. *)
+let prelude_data = "Prelude", Some "Coq", Some true
-let load_init = ref true
+let require_libs opts =
+ if opts.load_init then prelude_data :: opts.vo_requires else opts.vo_requires
-(* From Coq Require Import Prelude. *)
-let prelude_data = "Prelude", Some "Coq", Some true
+let cmdline_load_path opts =
+ let open Mltop in
+ (* loadpaths given by options -Q and -R *)
+ List.map
+ (fun (unix_path, coq_path, implicit) ->
+ { recursive = true;
+ path_spec = VoPath { unix_path; coq_path; has_ml = Mltop.AddNoML; implicit } })
+ (List.rev opts.vo_includes) @
-let require_libs () =
- if !load_init then prelude_data :: !require_list else !require_list
+ (* additional ml directories, given with option -I *)
+ List.map (fun s -> {recursive = false; path_spec = MlPath s}) (List.rev opts.ml_includes)
-let add_compat_require v =
- match v with
- | Flags.V8_5 -> add_require ("Coq.Compat.Coq85", None, Some false)
- | Flags.V8_6 -> add_require ("Coq.Compat.Coq86", None, Some false)
- | Flags.V8_7 -> add_require ("Coq.Compat.Coq87", None, Some false)
- | Flags.VOld | Flags.Current -> ()
+let build_load_path opts =
+ Coqinit.libs_init_load_path ~load_init:opts.load_init @
+ cmdline_load_path opts
(******************************************************************************)
-(* File Compilation *)
+(* Fatal Errors *)
(******************************************************************************)
-let glob_opt = ref false
-
-let compile_list = ref ([] : (bool * string) list)
-
-type compilation_mode = BuildVo | BuildVio | Vio2Vo
-let compilation_mode = ref BuildVo
-let compilation_output_name = ref None
-
-let batch_mode = ref false
-let set_batch_mode () =
- System.trust_file_cache := false;
- batch_mode := true
-
-let add_compile verbose s =
- set_batch_mode ();
- Flags.quiet := true;
- if not !glob_opt then Dumpglob.dump_to_dotglob ();
- (** make the file name explicit; needed not to break up Coq loadpath stuff. *)
- let s =
- let open Filename in
- if is_implicit s
- then concat current_dir_name s
- else s
+(** Prints info which is either an error or an anomaly and then exits
+ with the appropriate error code *)
+let fatal_error msg =
+ Topfmt.std_logger Feedback.Error msg;
+ flush_all ();
+ exit 1
+
+let fatal_error_exn ?extra exn =
+ Topfmt.print_err_exn ?extra exn;
+ flush_all ();
+ let exit_code =
+ if CErrors.(is_anomaly exn || not (handled exn)) then 129 else 1
in
- compile_list := (verbose,s) :: !compile_list
+ exit exit_code
+(******************************************************************************)
+(* File Compilation *)
+(******************************************************************************)
let warn_file_no_extension =
CWarnings.create ~name:"file-no-extension" ~category:"filesystem"
(fun (f,ext) ->
@@ -268,16 +173,11 @@ let ensure_ext ext f =
let chop_extension f =
try Filename.chop_extension f with _ -> f
-let compile_error msg =
- Topfmt.std_logger Feedback.Error msg;
- flush_all ();
- exit 1
-
let ensure_bname src tgt =
let src, tgt = Filename.basename src, Filename.basename tgt in
let src, tgt = chop_extension src, chop_extension tgt in
if src <> tgt then
- compile_error (str "Source and target file names must coincide, directories can differ" ++ fnl () ++
+ fatal_error (str "Source and target file names must coincide, directories can differ" ++ fnl () ++
str "Source: " ++ str src ++ fnl () ++
str "Target: " ++ str tgt)
@@ -289,20 +189,23 @@ let ensure_vio v vio = ensure ".vio" v vio
let ensure_exists f =
if not (Sys.file_exists f) then
- compile_error (hov 0 (str "Can't find file" ++ spc () ++ str f))
+ fatal_error (hov 0 (str "Can't find file" ++ spc () ++ str f))
(* Compile a vernac file *)
-let compile ~time ~verbosely ~f_in ~f_out =
+let compile opts ~verbosely ~f_in ~f_out =
let check_pending_proofs () =
let pfs = Proof_global.get_all_proof_names () in
if not (CList.is_empty pfs) then
- compile_error (str "There are pending proofs: "
+ fatal_error (str "There are pending proofs: "
++ (pfs
|> List.rev
|> prlist_with_sep pr_comma Names.Id.print)
++ str ".")
in
- match !compilation_mode with
+ let iload_path = build_load_path opts in
+ let require_libs = require_libs opts in
+ let stm_options = opts.stm_flags in
+ match opts.compilation_mode with
| BuildVo ->
Flags.record_aux_file := true;
let long_f_dot_v = ensure_v f_in in
@@ -314,10 +217,10 @@ let compile ~time ~verbosely ~f_in ~f_out =
let doc, sid = Stm.(new_doc
{ doc_type = VoDoc long_f_dot_vo;
- require_libs = require_libs ()
+ iload_path; require_libs; stm_options;
}) in
- let doc, sid = load_init_vernaculars ~time doc sid in
+ let doc, sid = load_init_vernaculars opts doc sid in
let ldir = Stm.get_ldir ~doc in
Aux_file.(start_aux_file
~aux_file:(aux_file_name_for long_f_dot_vo)
@@ -325,7 +228,7 @@ let compile ~time ~verbosely ~f_in ~f_out =
Dumpglob.start_dump_glob ~vfile:long_f_dot_v ~vofile:long_f_dot_vo;
Dumpglob.dump_string ("F" ^ Names.DirPath.to_string ldir ^ "\n");
let wall_clock1 = Unix.gettimeofday () in
- let doc, _ = Vernac.load_vernac ~time ~verbosely ~check:true ~interactive:false doc (Stm.get_current_state ~doc) long_f_dot_v in
+ let doc, _ = Vernac.load_vernac ~time:opts.time ~verbosely ~check:true ~interactive:false doc (Stm.get_current_state ~doc) long_f_dot_v in
let _doc = Stm.join ~doc in
let wall_clock2 = Unix.gettimeofday () in
check_pending_proofs ();
@@ -347,15 +250,26 @@ let compile ~time ~verbosely ~f_in ~f_out =
| None -> long_f_dot_v ^ "io"
| Some f -> ensure_vio long_f_dot_v f in
+ (* We need to disable error resiliency, otherwise some errors
+ will be ignored in batch mode. c.f. #6707
+
+ This is not necessary in the vo case as it fully checks the
+ document anyways. *)
+ let stm_options = let open Stm.AsyncOpts in
+ { stm_options with
+ async_proofs_cmd_error_resilience = false;
+ async_proofs_tac_error_resilience = `None;
+ } in
+
let doc, sid = Stm.(new_doc
{ doc_type = VioDoc long_f_dot_vio;
- require_libs = require_libs ()
+ iload_path; require_libs; stm_options;
}) in
- let doc, sid = load_init_vernaculars ~time doc sid in
+ let doc, sid = load_init_vernaculars opts doc sid in
let ldir = Stm.get_ldir ~doc in
- let doc, _ = Vernac.load_vernac ~time ~verbosely ~check:false ~interactive:false doc (Stm.get_current_state ~doc) long_f_dot_v in
+ let doc, _ = Vernac.load_vernac ~time:opts.time ~verbosely ~check:false ~interactive:false doc (Stm.get_current_state ~doc) long_f_dot_v in
let doc = Stm.finish ~doc in
check_pending_proofs ();
let _doc = Stm.snapshot_vio ~doc ldir long_f_dot_vio in
@@ -370,88 +284,96 @@ let compile ~time ~verbosely ~f_in ~f_out =
let univs, proofs = Stm.finish_tasks lfdv univs disch proofs tasks in
Library.save_library_raw lfdv sum lib univs proofs
-let compile ~time ~verbosely ~f_in ~f_out =
+let compile opts ~verbosely ~f_in ~f_out =
ignore(CoqworkmgrApi.get 1);
- compile ~time ~verbosely ~f_in ~f_out;
+ compile opts ~verbosely ~f_in ~f_out;
CoqworkmgrApi.giveback 1
-let compile_file (verbosely,f_in) =
+let compile_file opts (f_in, verbosely) =
if !Flags.beautify then
Flags.with_option Flags.beautify_file
- (fun f_in -> compile ~verbosely ~f_in ~f_out:None) f_in
+ (fun f_in -> compile opts ~verbosely ~f_in ~f_out:None) f_in
else
- compile ~verbosely ~f_in ~f_out:None
+ compile opts ~verbosely ~f_in ~f_out:None
-let compile_files ~time =
- if !compile_list == [] then ()
- else List.iter (compile_file ~time) (List.rev !compile_list)
+let compile_files opts =
+ let compile_list = List.rev opts.compile_list in
+ List.iter (compile_file opts) compile_list
(******************************************************************************)
(* VIO Dispatching *)
(******************************************************************************)
-
-let vio_tasks = ref []
-let add_vio_task f =
- set_batch_mode ();
- Flags.quiet := true;
- vio_tasks := f :: !vio_tasks
-
-let check_vio_tasks () =
+let check_vio_tasks opts =
let rc =
List.fold_left (fun acc t -> Vio_checking.check_vio t && acc)
- true (List.rev !vio_tasks) in
- if not rc then exit 1
+ true (List.rev opts.vio_tasks) in
+ if not rc then fatal_error Pp.(str "VIO Task Check failed")
(* vio files *)
-let vio_files = ref []
-let vio_files_j = ref 0
-let vio_checking = ref false
-let add_vio_file f =
- set_batch_mode ();
- Flags.quiet := true;
- vio_files := f :: !vio_files
-
-let set_vio_checking_j opt j =
- try vio_files_j := int_of_string j
- with Failure _ ->
- prerr_endline ("The first argument of " ^ opt ^ " must the number");
- prerr_endline "of concurrent workers to be used (a positive integer).";
- prerr_endline "Makefiles generated by coq_makefile should be called";
- prerr_endline "setting the J variable like in 'make vio2vo J=3'";
- exit 1
-
-let schedule_vio_checking () =
- if !vio_files <> [] && !vio_checking then
- Vio_checking.schedule_vio_checking !vio_files_j !vio_files
-
-let schedule_vio_compilation () =
- if !vio_files <> [] && not !vio_checking then
- Vio_checking.schedule_vio_compilation !vio_files_j !vio_files
+let schedule_vio opts =
+ (* We must add update the loadpath here as the scheduling process
+ happens outside of the STM *)
+ let iload_path = build_load_path opts in
+ List.iter Mltop.add_coq_path iload_path;
+
+ if opts.vio_checking then
+ Vio_checking.schedule_vio_checking opts.vio_files_j opts.vio_files
+ else
+ Vio_checking.schedule_vio_compilation opts.vio_files_j opts.vio_files
(******************************************************************************)
-(* UI Options *)
+(* Color Options *)
(******************************************************************************)
-(** Options for proof general *)
-
-let set_emacs () =
- if not (Option.is_empty !toploop) then
- user_err Pp.(str "Flag -emacs is incompatible with a custom toplevel loop");
- Coqloop.print_emacs := true;
- Printer.enable_goal_tags_printing := true;
- color := `OFF
-
-(** Options for CoqIDE *)
-
-let set_ideslave () =
- if !Coqloop.print_emacs then user_err Pp.(str "Flags -ideslave and -emacs are incompatible");
- toploop := Some "coqidetop";
- Flags.ide_slave := true
+let init_color color_mode =
+ let has_color = match color_mode with
+ | `OFF -> false
+ | `ON -> true
+ | `AUTO ->
+ Terminal.has_style Unix.stdout &&
+ Terminal.has_style Unix.stderr &&
+ (* emacs compilation buffer does not support colors by default,
+ its TERM variable is set to "dumb". *)
+ try Sys.getenv "TERM" <> "dumb" with Not_found -> false
+ in
+ if has_color then begin
+ let colors = try Some (Sys.getenv "COQ_COLORS") with Not_found -> None in
+ match colors with
+ | None ->
+ (** Default colors *)
+ Topfmt.init_terminal_output ~color:true
+ | Some "" ->
+ (** No color output *)
+ Topfmt.init_terminal_output ~color:false
+ | Some s ->
+ (** Overwrite all colors *)
+ Topfmt.clear_styles ();
+ Topfmt.parse_color_config s;
+ Topfmt.init_terminal_output ~color:true
+ end
+ else
+ Topfmt.init_terminal_output ~color:false
-(** Options for slaves *)
+let toploop_init = ref begin fun opts x ->
+ let () = init_color opts.color in
+ let () = CoqworkmgrApi.init !WorkerLoop.async_proofs_worker_priority in
+ x
+ end
-let set_toploop name =
- if !Coqloop.print_emacs then user_err Pp.(str "Flags -toploop and -emacs are incompatible");
- toploop := Some name
+let print_style_tags opts =
+ let () = init_color opts.color in
+ let tags = Topfmt.dump_tags () in
+ let iter (t, st) =
+ let opt = Terminal.eval st ^ t ^ Terminal.reset ^ "\n" in
+ print_string opt
+ in
+ let make (t, st) =
+ let tags = List.map string_of_int (Terminal.repr st) in
+ (t ^ "=" ^ String.concat ";" tags)
+ in
+ let repr = List.map make tags in
+ let () = Printf.printf "COQ_COLORS=\"%s\"\n" (String.concat ":" repr) in
+ let () = List.iter iter tags in
+ flush_all ()
(** GC tweaking *)
@@ -478,307 +400,37 @@ let init_gc () =
Gc.minor_heap_size = 33554432; (** 4M *)
Gc.space_overhead = 120}
-(*s Parsing of the command line.
- We no longer use [Arg.parse], in order to use share [Usage.print_usage]
- between coqtop and coqc. *)
-
-let usage_no_coqlib = CWarnings.create ~name:"usage-no-coqlib" ~category:"filesystem"
- (fun () -> Pp.str "cannot guess a path for Coq libraries; dynaminally loaded flags will not be mentioned")
-
-exception NoCoqLib
-
-let usage batch =
- begin
- try
- Envars.set_coqlib ~fail:(fun x -> raise NoCoqLib);
- Coqinit.init_load_path ~load_init:!load_init;
- with NoCoqLib -> usage_no_coqlib ()
- end;
- if batch then Usage.print_usage_coqc ()
- else begin
- Mltop.load_ml_objects_raw_rex
- (Str.regexp (if Mltop.is_native then "^.*top.cmxs$" else "^.*top.cma$"));
- Usage.print_usage_coqtop ()
- end
-
-let print_style_tags () =
- let () = init_color () in
- let tags = Topfmt.dump_tags () in
- let iter (t, st) =
- let opt = Terminal.eval st ^ t ^ Terminal.reset ^ "\n" in
- print_string opt
- in
- let make (t, st) =
- let tags = List.map string_of_int (Terminal.repr st) in
- (t ^ "=" ^ String.concat ";" tags)
- in
- let repr = List.map make tags in
- let () = Printf.printf "COQ_COLORS=\"%s\"\n" (String.concat ":" repr) in
- let () = List.iter iter tags in
- flush_all ()
-
-let error_missing_arg s =
- prerr_endline ("Error: extra argument expected after option "^s);
- prerr_endline "See -help for the syntax of supported options";
- exit 1
-
-let filter_opts = ref false
-let exitcode () = if !filter_opts then 2 else 0
-
-let print_where = ref false
-let print_config = ref false
-let print_tags = ref false
-
-let get_priority opt s =
- try CoqworkmgrApi.priority_of_string s
- with Invalid_argument _ ->
- prerr_endline ("Error: low/high expected after "^opt); exit 1
-
-let get_async_proofs_mode opt = let open Stm.AsyncOpts in function
- | "no" | "off" -> APoff
- | "yes" | "on" -> APon
- | "lazy" -> APonLazy
- | _ -> prerr_endline ("Error: on/off/lazy expected after "^opt); exit 1
-
-let get_cache opt = function
- | "force" -> Some Stm.AsyncOpts.Force
- | _ -> prerr_endline ("Error: force expected after "^opt); exit 1
-
-
-let set_worker_id opt s =
- assert (s <> "master");
- Flags.async_proofs_worker_id := s
-
-let get_bool opt = function
- | "yes" | "on" -> true
- | "no" | "off" -> false
- | _ -> prerr_endline ("Error: yes/no expected after option "^opt); exit 1
-
-let get_int opt n =
- try int_of_string n
- with Failure _ ->
- prerr_endline ("Error: integer expected after option "^opt); exit 1
-
-let get_float opt n =
- try float_of_string n
- with Failure _ ->
- prerr_endline ("Error: float expected after option "^opt); exit 1
-
-let get_host_port opt s =
- match CString.split ':' s with
- | [host; portr; portw] ->
- Some (Spawned.Socket(host, int_of_string portr, int_of_string portw))
- | ["stdfds"] -> Some Spawned.AnonPipe
- | _ ->
- prerr_endline ("Error: host:portr:portw or stdfds expected after option "^opt);
- exit 1
-
-let get_error_resilience opt = function
- | "on" | "all" | "yes" -> `All
- | "off" | "no" -> `None
- | s -> `Only (CString.split ',' s)
-
-let get_task_list s = List.map int_of_string (Str.split (Str.regexp ",") s)
-
-let is_not_dash_option = function
- | Some f when String.length f > 0 && f.[0] <> '-' -> true
- | _ -> false
-
-let get_native_name s =
- (* We ignore even critical errors because this mode has to be super silent *)
- try
- String.concat "/" [Filename.dirname s;
- Nativelib.output_dir; Library.native_name_from_filename s]
- with _ -> ""
-
-(** Prints info which is either an error or an anomaly and then exits
- with the appropriate error code *)
-let fatal_error ?extra exn =
- Topfmt.print_err_exn ?extra exn;
- let exit_code = if CErrors.(is_anomaly exn || not (handled exn)) then 129 else 1 in
- exit exit_code
-
-let parse_args arglist =
- let args = ref arglist in
- let extras = ref [] in
- let rec parse () = match !args with
- | [] -> List.rev !extras
- | opt :: rem ->
- args := rem;
- let next () = match !args with
- | x::rem -> args := rem; x
- | [] -> error_missing_arg opt
- in
- let peek_next () = match !args with
- | x::_ -> Some x
- | [] -> None
- in
- begin match opt with
-
- (* Complex options with many args *)
- |"-I"|"-include" ->
- begin match rem with
- | d :: rem -> Coqinit.push_ml_include d; args := rem
- | [] -> error_missing_arg opt
- end
- |"-Q" ->
- begin match rem with
- | d :: p :: rem -> set_include d p false; args := rem
- | _ -> error_missing_arg opt
- end
- |"-R" ->
- begin match rem with
- | d :: p :: rem -> set_include d p true; args := rem
- | _ -> error_missing_arg opt
- end
-
- (* Options with two arg *)
- |"-check-vio-tasks" ->
- let tno = get_task_list (next ()) in
- let tfile = next () in
- add_vio_task (tno,tfile)
- |"-schedule-vio-checking" ->
- vio_checking := true;
- set_vio_checking_j opt (next ());
- add_vio_file (next ());
- while is_not_dash_option (peek_next ()) do add_vio_file (next ()); done
- |"-schedule-vio2vo" ->
- set_vio_checking_j opt (next ());
- add_vio_file (next ());
- while is_not_dash_option (peek_next ()) do add_vio_file (next ()); done
-
- (* Options with one arg *)
- |"-coqlib" -> Flags.coqlib_spec:=true; Flags.coqlib:=(next ())
- |"-async-proofs" ->
- Stm.AsyncOpts.async_proofs_mode := get_async_proofs_mode opt (next())
- |"-async-proofs-j" ->
- Stm.AsyncOpts.async_proofs_n_workers := (get_int opt (next ()))
- |"-async-proofs-cache" ->
- Stm.AsyncOpts.async_proofs_cache := get_cache opt (next ())
- |"-async-proofs-tac-j" ->
- Stm.AsyncOpts.async_proofs_n_tacworkers := (get_int opt (next ()))
- |"-async-proofs-worker-priority" ->
- WorkerLoop.async_proofs_worker_priority := get_priority opt (next ())
- |"-async-proofs-private-flags" ->
- Stm.AsyncOpts.async_proofs_private_flags := Some (next ());
- |"-async-proofs-tactic-error-resilience" ->
- Stm.AsyncOpts.async_proofs_tac_error_resilience := get_error_resilience opt (next ())
- |"-async-proofs-command-error-resilience" ->
- Stm.AsyncOpts.async_proofs_cmd_error_resilience := get_bool opt (next ())
- |"-async-proofs-delegation-threshold" ->
- Stm.AsyncOpts.async_proofs_delegation_threshold:= get_float opt (next ())
- |"-worker-id" -> set_worker_id opt (next ())
- |"-compat" ->
- let v = G_vernac.parse_compat_version ~allow_old:false (next ()) in
- Flags.compat_version := v; add_compat_require v
- |"-compile" -> add_compile false (next ())
- |"-compile-verbose" -> add_compile true (next ())
- |"-dump-glob" -> Dumpglob.dump_into_file (next ()); glob_opt := true
- |"-feedback-glob" -> Dumpglob.feedback_glob ()
- |"-exclude-dir" -> System.exclude_directory (next ())
- |"-init-file" -> Coqinit.set_rcfile (next ())
- |"-inputstate"|"-is" -> set_inputstate (next ())
- |"-load-ml-object" -> Mltop.dir_ml_load (next ())
- |"-load-ml-source" -> Mltop.dir_ml_use (next ())
- |"-load-vernac-object" -> add_require (next (), None, None)
- |"-load-vernac-source"|"-l" -> add_load_vernacular false (next ())
- |"-load-vernac-source-verbose"|"-lv" -> add_load_vernacular true (next ())
- |"-outputstate" -> set_outputstate (next ())
- |"-print-mod-uid" -> let s = String.concat " " (List.map get_native_name rem) in print_endline s; exit 0
- |"-profile-ltac-cutoff" -> Flags.profile_ltac := true; Flags.profile_ltac_cutoff := get_float opt (next ())
- |"-require" -> add_require (next (), None, Some false)
- |"-top" -> set_toplevel_name (dirpath_of_string (next ()))
- |"-main-channel" -> Spawned.main_channel := get_host_port opt (next())
- |"-control-channel" -> Spawned.control_channel := get_host_port opt (next())
- |"-vio2vo" ->
- add_compile false (next ());
- compilation_mode := Vio2Vo
- |"-toploop" -> set_toploop (next ())
- |"-w" | "-W" ->
- let w = next () in
- if w = "none" then CWarnings.set_flags w
- else
- let w = CWarnings.get_flags () ^ "," ^ w in
- CWarnings.set_flags (CWarnings.normalize_flags_string w)
- |"-o" -> compilation_output_name := Some (next())
-
- (* Options with zero arg *)
- |"-async-queries-always-delegate"
- |"-async-proofs-always-delegate"
- |"-async-proofs-full" ->
- Stm.AsyncOpts.async_proofs_full := true;
- |"-async-proofs-never-reopen-branch" ->
- Stm.AsyncOpts.async_proofs_never_reopen_branch := true;
- |"-batch" -> set_batch_mode ()
- |"-test-mode" -> Flags.test_mode := true
- |"-beautify" -> Flags.beautify := true
- |"-boot" -> Flags.boot := true; Coqinit.no_load_rc ()
- |"-bt" -> Backtrace.record_backtrace true
- |"-color" -> set_color (next ())
- |"-config"|"--config" -> print_config := true
- |"-debug" -> Coqinit.set_debug ()
- |"-stm-debug" -> Stm.stm_debug := true
- |"-emacs" -> set_emacs ()
- |"-filteropts" -> filter_opts := true
- |"-h"|"-H"|"-?"|"-help"|"--help" -> usage !batch_mode
- |"-ideslave" -> set_ideslave ()
- |"-impredicative-set" -> set_impredicative_set ()
- |"-indices-matter" -> Indtypes.enforce_indices_matter ()
- |"-m"|"--memory" -> memory_stat := true
- |"-noinit"|"-nois" -> load_init := false
- |"-no-glob"|"-noglob" -> Dumpglob.noglob (); glob_opt := true
- |"-native-compiler" ->
- if not Coq_config.native_compiler then
- warning "Native compilation was disabled at configure time."
- else Flags.output_native_objects := true
- |"-output-context" -> output_context := true
- |"-profile-ltac" -> Flags.profile_ltac := true
- |"-q" -> Coqinit.no_load_rc ()
- |"-quiet"|"-silent" -> Flags.quiet := true; Flags.make_warn false
- |"-quick" -> compilation_mode := BuildVio
- |"-list-tags" -> print_tags := true
- |"-time" -> measure_time := true
- |"-type-in-type" -> set_type_in_type ()
- |"-unicode" -> add_require ("Utf8_core", None, Some false)
- |"-v"|"--version" -> Usage.version (exitcode ())
- |"-print-version"|"--print-version" -> Usage.machine_readable_version (exitcode ())
- |"-where" -> print_where := true
-
- (* Unknown option *)
- | s -> extras := s :: !extras
- end;
- parse ()
- in
- try
- parse ()
- with any -> fatal_error any
-
+(** Main init routine *)
let init_toplevel arglist =
(* Coq's init process, phase 1:
- - OCaml parameters, and basic structures and IO
+ OCaml parameters, basic structures, and IO
*)
CProfile.init_profile ();
init_gc ();
Sys.catch_break false; (* Ctrl-C is fatal during the initialisation *)
let init_feeder = Feedback.add_feeder coqtop_init_feed in
Lib.init();
+
(* Coq's init process, phase 2:
- - Basic Coq environment, load-path, plugins.
+ Basic Coq environment, load-path, plugins.
*)
let res = begin
try
- let extras = parse_args arglist in
+ let opts,extras = parse_args arglist in
+ memory_stat := opts.memory_stat;
+
(* If we have been spawned by the Spawn module, this has to be done
* early since the master waits us to connect back *)
Spawned.init_channels ();
Envars.set_coqlib ~fail:(fun msg -> CErrors.user_err Pp.(str msg));
- if !print_where then (print_endline(Envars.coqlib ()); exit(exitcode ()));
- if !print_config then (Envars.print_config stdout Coq_config.all_src_dirs; exit (exitcode ()));
- if !print_tags then (print_style_tags (); exit (exitcode ()));
- if !filter_opts then (print_string (String.concat "\n" extras); exit 0);
- Coqinit.init_load_path ~load_init:!load_init;
- Option.iter Mltop.load_ml_object_raw !toploop;
- let extras = !toploop_init extras in
+ if opts.print_where then (print_endline(Envars.coqlib ()); exit(exitcode opts));
+ if opts.print_config then (Envars.print_config stdout Coq_config.all_src_dirs; exit (exitcode opts));
+ if opts.print_tags then (print_style_tags opts; exit (exitcode opts));
+ if opts.filter_opts then (print_string (String.concat "\n" extras); exit 0);
+ let top_lp = Coqinit.toplevel_init_load_path () in
+ List.iter Mltop.add_coq_path top_lp;
+ Option.iter Mltop.load_ml_object_raw opts.toploop;
+ let extras = !toploop_init opts extras in
if not (CList.is_empty extras) then begin
prerr_endline ("Don't know what to do with "^String.concat " " extras);
prerr_endline "See -help for the list of supported options";
@@ -786,10 +438,10 @@ let init_toplevel arglist =
end;
Flags.if_verbose print_header ();
Mltop.init_known_plugins ();
- engage ();
+ Global.set_engagement opts.impredicative_set;
(* Allow the user to load an arbitrary state here *)
- inputstate ();
+ inputstate opts;
(* This state will be shared by all the documents *)
Stm.init_core ();
@@ -798,39 +450,45 @@ let init_toplevel arglist =
It is essential that the module system is in a consistent
state before we take the first snapshot. This was not
- guaranteed in the past. In particular, we want to be sure we
- have called start_library before loading the prelude and rest
- of required files.
+ guaranteed in the past, but now is thanks to the STM API.
We split the codepath here depending whether coqtop is called
in interactive mode or not. *)
- if (not !batch_mode || CList.is_empty !compile_list)
+ (* The condition for starting the interactive mode is a bit
+ convoluted, we should really refactor batch/compilation_mode
+ more. *)
+ if (not opts.batch_mode
+ || CList.(is_empty opts.compile_list && is_empty opts.vio_files && is_empty opts.vio_tasks))
(* Interactive *)
then begin
- try
- let doc, sid = Stm.(new_doc
- { doc_type = Interactive !toplevel_name;
- require_libs = require_libs ()
- }) in
- Some (load_init_vernaculars ~time:!measure_time doc sid)
- with any -> flush_all(); fatal_error any
- (* Non interactive *)
+ let iload_path = build_load_path opts in
+ let require_libs = require_libs opts in
+ let stm_options = opts.stm_flags in
+ try let doc, sid =
+ Stm.(new_doc
+ { doc_type = Interactive opts.toplevel_name;
+ iload_path; require_libs; stm_options;
+ }) in
+ Some (load_init_vernaculars opts doc sid), opts
+ with any -> flush_all(); fatal_error_exn any
+ (* Non interactive: we perform a sequence of compilation steps *)
end else begin
try
- compile_files ~time:!measure_time;
- schedule_vio_checking ();
- schedule_vio_compilation ();
- check_vio_tasks ();
+ compile_files opts;
+ (* Vio compile pass *)
+ if opts.vio_files <> [] then schedule_vio opts;
+ (* Vio task pass *)
+ check_vio_tasks opts;
(* Allow the user to output an arbitrary state *)
- outputstate ();
- None
- with any -> flush_all(); fatal_error any
+ outputstate opts;
+ None, opts
+ with any -> flush_all(); fatal_error_exn any
end;
with any ->
flush_all();
let extra = Some (str "Error during initialization: ") in
- fatal_error ?extra any
+ fatal_error_exn ?extra any
end in
Feedback.del_feeder init_feeder;
res
@@ -838,12 +496,12 @@ let init_toplevel arglist =
let start () =
match init_toplevel (List.tl (Array.to_list Sys.argv)) with
(* Batch mode *)
- | Some (doc, sid) when not !batch_mode ->
- !toploop_run doc;
+ | Some (doc, sid), opts when not opts.batch_mode ->
+ !toploop_run opts doc;
exit 1
- | _ ->
+ | _ , opts ->
flush_all();
- if !output_context then begin
+ if opts.output_context then begin
let sigma, env = Pfedit.get_current_context () in
Feedback.msg_notice (Flags.(with_option raw_print (Prettyp.print_full_pure_context env) sigma) ++ fnl ())
end;
diff --git a/toplevel/coqtop.mli b/toplevel/coqtop.mli
index 5b9494eaa..4d625a03d 100644
--- a/toplevel/coqtop.mli
+++ b/toplevel/coqtop.mli
@@ -11,7 +11,7 @@
state, load the files given on the command line, load the resource file,
produce the output state if any, and finally will launch [Coqloop.loop]. *)
-val init_toplevel : string list -> (Stm.doc * Stateid.t) option
+val init_toplevel : string list -> (Stm.doc * Stateid.t) option * Coqargs.coq_cmdopts
val start : unit -> unit
@@ -19,6 +19,6 @@ val start : unit -> unit
val drop_last_doc : Stm.doc option ref
(* For other toploops *)
-val toploop_init : (string list -> string list) ref
-val toploop_run : (Stm.doc -> unit) ref
+val toploop_init : (Coqargs.coq_cmdopts -> string list -> string list) ref
+val toploop_run : (Coqargs.coq_cmdopts -> Stm.doc -> unit) ref
diff --git a/toplevel/toplevel.mllib b/toplevel/toplevel.mllib
index 10bf48647..9fb2e33d7 100644
--- a/toplevel/toplevel.mllib
+++ b/toplevel/toplevel.mllib
@@ -2,4 +2,5 @@ Vernac
Usage
Coqloop
Coqinit
+Coqargs
Coqtop
diff --git a/vernac/comInductive.ml b/vernac/comInductive.ml
index 1c8677e9c..41474fc63 100644
--- a/vernac/comInductive.ml
+++ b/vernac/comInductive.ml
@@ -340,7 +340,7 @@ let interp_mutual_inductive (paramsl,indl) notations cum poly prv finite =
match uctx with
| Polymorphic_const_entry uctx ->
if cum then
- Cumulative_ind_entry (Universes.univ_inf_ind_from_universe_context uctx)
+ Cumulative_ind_entry (Univ.CumulativityInfo.from_universe_context uctx)
else Polymorphic_ind_entry uctx
| Monomorphic_const_entry uctx ->
Monomorphic_ind_entry uctx
@@ -356,7 +356,7 @@ let interp_mutual_inductive (paramsl,indl) notations cum poly prv finite =
}
in
(if poly && cum then
- Inductiveops.infer_inductive_subtyping env_ar sigma mind_ent
+ InferCumulativity.infer_inductive env_ar mind_ent
else mind_ent), Evd.universe_binders sigma, impls
(* Very syntactical equality *)
diff --git a/vernac/explainErr.ml b/vernac/explainErr.ml
index d328ad0cf..fc3495796 100644
--- a/vernac/explainErr.ml
+++ b/vernac/explainErr.ml
@@ -32,6 +32,7 @@ let explain_exn_default = function
| Sys_error msg -> hov 0 (str "System error: " ++ guill msg)
| Out_of_memory -> hov 0 (str "Out of memory.")
| Stack_overflow -> hov 0 (str "Stack overflow.")
+ | Dynlink.Error e -> hov 0 (str "Dynlink error: " ++ str Dynlink.(error_message e))
| Timeout -> hov 0 (str "Timeout!")
| Sys.Break -> hov 0 (fnl () ++ str "User interrupt.")
(* Exceptions with pre-evaluated error messages *)
diff --git a/vernac/himsg.ml b/vernac/himsg.ml
index e8c5aeedd..f00c1e604 100644
--- a/vernac/himsg.ml
+++ b/vernac/himsg.ml
@@ -83,12 +83,12 @@ let rec contract3' env sigma a b c = function
(** Ad-hoc reductions *)
-let j_nf_betaiotaevar sigma j =
+let j_nf_betaiotaevar env sigma j =
{ uj_val = j.uj_val;
- uj_type = Reductionops.nf_betaiota sigma j.uj_type }
+ uj_type = Reductionops.nf_betaiota env sigma j.uj_type }
-let jv_nf_betaiotaevar sigma jl =
- Array.map (fun j -> j_nf_betaiotaevar sigma j) jl
+let jv_nf_betaiotaevar env sigma jl =
+ Array.map (fun j -> j_nf_betaiotaevar env sigma j) jl
(** Printers *)
@@ -258,7 +258,7 @@ let explain_number_branches env sigma cj expn =
str "expects " ++ int expn ++ str " branches."
let explain_ill_formed_branch env sigma c ci actty expty =
- let simp t = Reductionops.nf_betaiota sigma t in
+ let simp t = Reductionops.nf_betaiota env sigma t in
let env = make_all_name_different env sigma in
let pc = pr_leconstr_env env sigma c in
let pa, pe = pr_explicit env sigma (simp actty) (simp expty) in
@@ -295,8 +295,8 @@ let explain_unification_error env sigma p1 p2 = function
| NotSameArgSize | NotSameHead | NoCanonicalStructure ->
(* Error speaks from itself *) []
| ConversionFailed (env,t1,t2) ->
- let t1 = Reductionops.nf_betaiota sigma t1 in
- let t2 = Reductionops.nf_betaiota sigma t2 in
+ let t1 = Reductionops.nf_betaiota env sigma t1 in
+ let t2 = Reductionops.nf_betaiota env sigma t2 in
if EConstr.eq_constr sigma t1 p1 && EConstr.eq_constr sigma t2 p2 then [] else
let env = make_all_name_different env sigma in
if not (EConstr.eq_constr sigma t1 p1) || not (EConstr.eq_constr sigma t2 p2) then
@@ -336,8 +336,8 @@ let explain_unification_error env sigma p1 p2 = function
let explain_actual_type env sigma j t reason =
let env = make_all_name_different env sigma in
- let j = j_nf_betaiotaevar sigma j in
- let t = Reductionops.nf_betaiota sigma t in
+ let j = j_nf_betaiotaevar env sigma j in
+ let t = Reductionops.nf_betaiota env sigma t in
(** Actually print *)
let pe = pr_ne_context_of (str "In environment") env sigma in
let pc = pr_leconstr_env env sigma (Environ.j_val j) in
@@ -351,8 +351,8 @@ let explain_actual_type env sigma j t reason =
ppreason ++ str ".")
let explain_cant_apply_bad_type env sigma (n,exptyp,actualtyp) rator randl =
- let randl = jv_nf_betaiotaevar sigma randl in
- let actualtyp = Reductionops.nf_betaiota sigma actualtyp in
+ let randl = jv_nf_betaiotaevar env sigma randl in
+ let actualtyp = Reductionops.nf_betaiota env sigma actualtyp in
let env = make_all_name_different env sigma in
let actualtyp, exptyp = pr_explicit env sigma actualtyp exptyp in
let nargs = Array.length randl in
diff --git a/vernac/lemmas.ml b/vernac/lemmas.ml
index 6ef310837..57436784b 100644
--- a/vernac/lemmas.ml
+++ b/vernac/lemmas.ml
@@ -210,17 +210,16 @@ let save ?export_seff id const uctx do_guard (locality,poly,kind) hook =
let default_thm_id = Id.of_string "Unnamed_thm"
-let compute_proof_name locality = function
- | Some ((loc,id),pl) ->
- (* We check existence here: it's a bit late at Qed time *)
- if Nametab.exists_cci (Lib.make_path id) || is_section_variable id ||
- locality == Global && Nametab.exists_cci (Lib.make_path_except_section id)
- then
- user_err ?loc (Id.print id ++ str " already exists.");
- id
- | None ->
- let avoid = Id.Set.of_list (Proof_global.get_all_proof_names ()) in
- next_global_ident_away default_thm_id avoid
+let fresh_name_for_anonymous_theorem () =
+ let avoid = Id.Set.of_list (Proof_global.get_all_proof_names ()) in
+ next_global_ident_away default_thm_id avoid
+
+let check_name_freshness locality (loc,id) : unit =
+ (* We check existence here: it's a bit late at Qed time *)
+ if Nametab.exists_cci (Lib.make_path id) || is_section_variable id ||
+ locality == Global && Nametab.exists_cci (Lib.make_path_except_section id)
+ then
+ user_err ?loc (Id.print id ++ str " already exists.")
let save_remaining_recthms (locality,p,kind) norm univs body opaq i (id,(t_i,(_,imps))) =
let t_i = norm t_i in
@@ -435,20 +434,17 @@ let start_proof_with_initialization kind sigma decl recguard thms snl hook =
let start_proof_com ?inference_hook kind thms hook =
let env0 = Global.env () in
let decl = fst (List.hd thms) in
- let evd, decl =
- match decl with
- | None -> Evd.from_env env0, Univdecls.default_univ_decl
- | Some decl ->
- Univdecls.interp_univ_decl_opt env0 (snd decl) in
- let evd, thms = List.fold_left_map (fun evd (sopt,(bl,t)) ->
+ let evd, decl = Univdecls.interp_univ_decl_opt env0 (snd decl) in
+ let evd, thms = List.fold_left_map (fun evd ((id, _), (bl, t)) ->
let evd, (impls, ((env, ctx), imps)) = interp_context_evars env0 evd bl in
let evd, (t', imps') = interp_type_evars_impls ~impls env evd t in
let flags = all_and_fail_flags in
let flags = { flags with use_hook = inference_hook } in
let evd = solve_remaining_evars flags env evd Evd.empty in
let ids = List.map RelDecl.get_name ctx in
+ check_name_freshness (pi1 kind) id;
(* XXX: The nf_evar is critical !! *)
- evd, (compute_proof_name (pi1 kind) sopt,
+ evd, (snd id,
(Evarutil.nf_evar evd (EConstr.it_mkProd_or_LetIn t' ctx),
(ids, imps @ lift_implicits (Context.Rel.nhyps ctx) imps'))))
evd thms in
diff --git a/vernac/lemmas.mli b/vernac/lemmas.mli
index ca92e856b..126dcd8b0 100644
--- a/vernac/lemmas.mli
+++ b/vernac/lemmas.mli
@@ -52,6 +52,8 @@ val standard_proof_terminator :
Proof_global.lemma_possible_guards -> unit declaration_hook ->
Proof_global.proof_terminator
+val fresh_name_for_anonymous_theorem : unit -> Id.t
+
(** {6 ... } *)
(** A hook the next three functions pass to cook_proof *)
diff --git a/vernac/mltop.ml b/vernac/mltop.ml
index 00554e3ba..053b9d070 100644
--- a/vernac/mltop.ml
+++ b/vernac/mltop.ml
@@ -184,10 +184,28 @@ let warn_cannot_open_path =
type add_ml = AddNoML | AddTopML | AddRecML
-let add_rec_path add_ml ~unix_path ~coq_root ~implicit =
+type vo_path_spec = {
+ unix_path : string;
+ coq_path : Names.DirPath.t;
+ implicit : bool;
+ has_ml : add_ml;
+}
+
+type coq_path_spec =
+ | VoPath of vo_path_spec
+ | MlPath of string
+
+type coq_path = {
+ path_spec: coq_path_spec;
+ recursive: bool;
+}
+
+let add_vo_path ~recursive lp =
+ let unix_path = lp.unix_path in
+ let implicit = lp.implicit in
if exists_dir unix_path then
- let dirs = all_subdirs ~unix_path in
- let prefix = Names.DirPath.repr coq_root in
+ let dirs = if recursive then all_subdirs ~unix_path else [] in
+ let prefix = Names.DirPath.repr lp.coq_path in
let convert_dirs (lp, cp) =
try
let path = List.rev_map convert_string cp @ prefix in
@@ -195,17 +213,23 @@ let add_rec_path add_ml ~unix_path ~coq_root ~implicit =
with Exit -> None
in
let dirs = List.map_filter convert_dirs dirs in
- let () = match add_ml with
+ let () = match lp.has_ml with
| AddNoML -> ()
| AddTopML -> add_ml_dir unix_path
| AddRecML -> List.iter (fun (lp,_) -> add_ml_dir lp) dirs in
let add (path, dir) =
Loadpath.add_load_path path ~implicit dir in
let () = List.iter add dirs in
- Loadpath.add_load_path unix_path ~implicit coq_root
+ Loadpath.add_load_path unix_path ~implicit lp.coq_path
else
warn_cannot_open_path unix_path
+let add_coq_path { recursive; path_spec } = match path_spec with
+ | VoPath lp ->
+ add_vo_path ~recursive lp
+ | MlPath dir ->
+ if recursive then add_rec_ml_dir dir else add_ml_dir dir
+
(* convertit un nom quelconque en nom de fichier ou de module *)
let mod_of_name name =
if Filename.check_suffix name ".cmo" then
diff --git a/vernac/mltop.mli b/vernac/mltop.mli
index 324a66d38..e44a7c243 100644
--- a/vernac/mltop.mli
+++ b/vernac/mltop.mli
@@ -42,14 +42,26 @@ val dir_ml_load : string -> unit
(** Dynamic interpretation of .ml *)
val dir_ml_use : string -> unit
-(** Adds a path to the ML paths *)
-val add_ml_dir : string -> unit
-val add_rec_ml_dir : string -> unit
-
+(** Adds a path to the Coq and ML paths *)
type add_ml = AddNoML | AddTopML | AddRecML
-(** Adds a path to the Coq and ML paths *)
-val add_rec_path : add_ml -> unix_path:string -> coq_root:Names.DirPath.t -> implicit:bool -> unit
+type vo_path_spec = {
+ unix_path : string; (* Filesystem path contaning vo/ml files *)
+ coq_path : Names.DirPath.t; (* Coq prefix for the path *)
+ implicit : bool; (* [implicit = true] avoids having to qualify with [coq_path] *)
+ has_ml : add_ml; (* If [has_ml] is true, the directory will also be search for plugins *)
+}
+
+type coq_path_spec =
+ | VoPath of vo_path_spec
+ | MlPath of string
+
+type coq_path = {
+ path_spec: coq_path_spec;
+ recursive: bool;
+}
+
+val add_coq_path : coq_path -> unit
(** List of modules linked to the toplevel *)
val add_known_module : string -> unit
diff --git a/vernac/record.ml b/vernac/record.ml
index d9dc16d96..d9af5378f 100644
--- a/vernac/record.ml
+++ b/vernac/record.ml
@@ -423,16 +423,7 @@ let declare_structure finite ubinders univs id idbuild paramimpls params arity t
mind_entry_universes = univs;
}
in
- let mie =
- match ctx with
- | Polymorphic_const_entry ctx ->
- let env = Global.env () in
- let env' = Environ.push_context ctx env in
- let evd = Evd.from_env env' in
- Inductiveops.infer_inductive_subtyping env' evd mie
- | Monomorphic_const_entry _ ->
- mie
- in
+ let mie = InferCumulativity.infer_inductive (Global.env ()) mie in
let kn = ComInductive.declare_mutual_inductive_with_eliminations mie ubinders [(paramimpls,[])] in
let rsp = (kn,0) in (* This is ind path of idstruc *)
let cstr = (rsp,1) in
@@ -501,7 +492,7 @@ let declare_class finite def cum ubinders univs id idbuild paramimpls params ari
match univs with
| Polymorphic_const_entry univs ->
if cum then
- Cumulative_ind_entry (Universes.univ_inf_ind_from_universe_context univs)
+ Cumulative_ind_entry (Univ.CumulativityInfo.from_universe_context univs)
else
Polymorphic_ind_entry univs
| Monomorphic_const_entry univs ->
@@ -531,6 +522,7 @@ let declare_class finite def cum ubinders univs id idbuild paramimpls params ari
match univs with
| Polymorphic_const_entry univs ->
let usubst, auctx = Univ.abstract_universes univs in
+ let usubst = Univ.make_instance_subst usubst in
let map c = Vars.subst_univs_level_constr usubst c in
let fields = Context.Rel.map map fields in
let ctx_context = on_snd (fun d -> Context.Rel.map map d) ctx_context in
@@ -631,7 +623,7 @@ let definition_structure (kind,cum,poly,finite,(is_coe,((loc,idstruc),pl)),ps,cf
match univs with
| Polymorphic_const_entry univs ->
if cum then
- Cumulative_ind_entry (Universes.univ_inf_ind_from_universe_context univs)
+ Cumulative_ind_entry (Univ.CumulativityInfo.from_universe_context univs)
else
Polymorphic_ind_entry univs
| Monomorphic_const_entry univs ->
diff --git a/vernac/topfmt.ml b/vernac/topfmt.ml
index 7e96f28de..1ad7ead72 100644
--- a/vernac/topfmt.ml
+++ b/vernac/topfmt.ml
@@ -6,7 +6,6 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-open Feedback
open Pp
(** Pp control also belongs here as the terminal is private to the toplevel *)
@@ -138,7 +137,7 @@ let make_body quoter info ?pre_hdr s =
(* The empty quoter *)
let noq x = x
(* Generic logger *)
-let gen_logger dbg warn ?pre_hdr level msg = match level with
+let gen_logger dbg warn ?pre_hdr level msg = let open Feedback in match level with
| Debug -> msgnl_with !std_ft (make_body dbg dbg_hdr ?pre_hdr msg)
| Info -> msgnl_with !std_ft (make_body dbg info_hdr ?pre_hdr msg)
| Notice -> msgnl_with !std_ft (make_body noq info_hdr ?pre_hdr msg)
diff --git a/vernac/vernacentries.ml b/vernac/vernacentries.ml
index ded0d97e6..35ef4bfa4 100644
--- a/vernac/vernacentries.ml
+++ b/vernac/vernacentries.ml
@@ -58,20 +58,20 @@ let show_proof () =
let p = Proof_global.give_me_the_proof () in
let sigma, env = Pfedit.get_current_context () in
let pprf = Proof.partial_proof p in
- Feedback.msg_notice (Pp.prlist_with_sep Pp.fnl (Printer.pr_econstr_env env sigma) pprf)
+ Pp.prlist_with_sep Pp.fnl (Printer.pr_econstr_env env sigma) pprf
let show_top_evars () =
(* spiwack: new as of Feb. 2010: shows goal evars in addition to non-goal evars. *)
let pfts = Proof_global.give_me_the_proof () in
let gls,_,_,_,sigma = Proof.proof pfts in
- Feedback.msg_notice (pr_evars_int sigma 1 (Evd.undefined_map sigma))
+ pr_evars_int sigma 1 (Evd.undefined_map sigma)
let show_universes () =
let pfts = Proof_global.give_me_the_proof () in
let gls,_,_,_,sigma = Proof.proof pfts in
let ctx = Evd.universe_context_set (Evd.nf_constraints sigma) in
- Feedback.msg_notice (Termops.pr_evar_universe_context (Evd.evar_universe_context sigma));
- Feedback.msg_notice (str"Normalized constraints: " ++ Univ.pr_universe_context_set (Termops.pr_evd_level sigma) ctx)
+ Termops.pr_evar_universe_context (Evd.evar_universe_context sigma) ++ fnl () ++
+ str "Normalized constraints: " ++ Univ.pr_universe_context_set (Termops.pr_evd_level sigma) ctx
(* Simulate the Intro(s) tactic *)
let show_intro all =
@@ -83,11 +83,12 @@ let show_intro all =
let l,_= decompose_prod_assum sigma (Termops.strip_outer_cast sigma (pf_concl gl)) in
if all then
let lid = Tactics.find_intro_names l gl in
- Feedback.msg_notice (hov 0 (prlist_with_sep spc Id.print lid))
+ hov 0 (prlist_with_sep spc Id.print lid)
else if not (List.is_empty l) then
let n = List.last l in
- Feedback.msg_notice (Id.print (List.hd (Tactics.find_intro_names [n] gl)))
- end
+ Id.print (List.hd (Tactics.find_intro_names [n] gl))
+ else mt ()
+ end else mt ()
(** Prepare a "match" template for a given inductive type.
For each branch of the match, we list the constructor name
@@ -146,8 +147,8 @@ let show_match id =
let pr_branch l =
str "| " ++ hov 1 (prlist_with_sep spc str l) ++ str " =>"
in
- Feedback.msg_notice (v 1 (str "match # with" ++ fnl () ++
- prlist_with_sep fnl pr_branch patterns ++ fnl () ++ str "end" ++ fnl ()))
+ v 1 (str "match # with" ++ fnl () ++
+ prlist_with_sep fnl pr_branch patterns ++ fnl () ++ str "end" ++ fnl ())
(* "Print" commands *)
@@ -186,23 +187,23 @@ let print_module r =
let globdir = Nametab.locate_dir qid in
match globdir with
DirModule { obj_dir; obj_mp; _ } ->
- Feedback.msg_notice (Printmod.print_module (Printmod.printable_body obj_dir) obj_mp)
+ Printmod.print_module (Printmod.printable_body obj_dir) obj_mp
| _ -> raise Not_found
with
- Not_found -> Feedback.msg_error (str"Unknown Module " ++ pr_qualid qid)
+ Not_found -> user_err (str"Unknown Module " ++ pr_qualid qid)
let print_modtype r =
let (loc,qid) = qualid_of_reference r in
try
let kn = Nametab.locate_modtype qid in
- Feedback.msg_notice (Printmod.print_modtype kn)
+ Printmod.print_modtype kn
with Not_found ->
(* Is there a module of this name ? If yes we display its type *)
try
let mp = Nametab.locate_module qid in
- Feedback.msg_notice (Printmod.print_module false mp)
+ Printmod.print_module false mp
with Not_found ->
- Feedback.msg_error (str"Unknown Module Type or Module " ++ pr_qualid qid)
+ user_err (str"Unknown Module Type or Module " ++ pr_qualid qid)
let print_namespace ns =
let ns = List.rev (Names.DirPath.repr ns) in
@@ -272,7 +273,7 @@ let print_namespace ns =
acc
) constants (str"")
in
- Feedback.msg_notice ((print_list Id.print ns)++str":"++fnl()++constants_in_namespace)
+ (print_list Id.print ns)++str":"++fnl()++constants_in_namespace
let print_strategy r =
let open Conv_oracle in
@@ -302,7 +303,7 @@ let print_strategy r =
else str "Constant strategies" ++ fnl () ++
hov 0 (prlist_with_sep fnl pr_strategy cst_lvl)
in
- Feedback.msg_notice (var_msg ++ cst_msg)
+ var_msg ++ cst_msg
| Some r ->
let r = Smartlocate.smart_global r in
let key = match r with
@@ -311,7 +312,7 @@ let print_strategy r =
| IndRef _ | ConstructRef _ -> user_err Pp.(str "The reference is not unfoldable")
in
let lvl = get_strategy oracle key in
- Feedback.msg_notice (pr_strategy (r, lvl))
+ pr_strategy (r, lvl)
let dump_universes_gen g s =
let output = open_out s in
@@ -345,7 +346,7 @@ let dump_universes_gen g s =
try
UGraph.dump_universes output_constraint g;
close ();
- Feedback.msg_info (str "Universes written to file \"" ++ str s ++ str "\".")
+ str "Universes written to file \"" ++ str s ++ str "\"."
with reraise ->
let reraise = CErrors.push reraise in
close ();
@@ -360,12 +361,9 @@ let locate_file f =
let msg_found_library = function
| Library.LibLoaded, fulldir, file ->
- Feedback.msg_info (hov 0
- (DirPath.print fulldir ++ strbrk " has been loaded from file " ++
- str file))
+ hov 0 (DirPath.print fulldir ++ strbrk " has been loaded from file " ++ str file)
| Library.LibInPath, fulldir, file ->
- Feedback.msg_info (hov 0
- (DirPath.print fulldir ++ strbrk " is bound to file " ++ str file))
+ hov 0 (DirPath.print fulldir ++ strbrk " is bound to file " ++ str file)
let err_unmapped_library ?loc ?from qid =
let dir = fst (repr_qualid qid) in
@@ -471,33 +469,40 @@ let vernac_definition_hook p = function
| SubClass -> Class.add_subclass_hook p
| _ -> no_hook
-let vernac_definition ~atts discharge kind ((loc,id as lid),pl) def =
+let vernac_definition ~atts discharge kind ((loc, id), pl) def =
let local = enforce_locality_exp atts.locality discharge in
let hook = vernac_definition_hook atts.polymorphic kind in
- let () = match local with
- | Discharge -> Dumpglob.dump_definition lid true "var"
- | Local | Global -> Dumpglob.dump_definition lid false "def"
+ let () =
+ match id with
+ | Anonymous -> ()
+ | Name n -> let lid = (loc, n) in
+ match local with
+ | Discharge -> Dumpglob.dump_definition lid true "var"
+ | Local | Global -> Dumpglob.dump_definition lid false "def"
in
let program_mode = Flags.is_program_mode () in
+ let name =
+ match id with
+ | Anonymous -> fresh_name_for_anonymous_theorem ()
+ | Name n -> n
+ in
(match def with
| ProveBody (bl,t) -> (* local binders, typ *)
- start_proof_and_print (local, atts.polymorphic, DefinitionBody kind)
- [Some (lid,pl), (bl,t)] hook
+ start_proof_and_print (local, atts.polymorphic, DefinitionBody kind)
+ [((loc, name), pl), (bl, t)] hook
| DefineBody (bl,red_option,c,typ_opt) ->
let red_option = match red_option with
| None -> None
| Some r ->
let sigma, env = Pfedit.get_current_context () in
Some (snd (Hook.get f_interp_redexp env sigma r)) in
- ComDefinition.do_definition ~program_mode id (local, atts.polymorphic, kind) pl bl red_option c typ_opt hook)
+ ComDefinition.do_definition ~program_mode name
+ (local, atts.polymorphic, kind) pl bl red_option c typ_opt hook)
let vernac_start_proof ~atts kind l =
let local = enforce_locality_exp atts.locality NoDischarge in
if Dumpglob.dump () then
- List.iter (fun (id, _) ->
- match id with
- | Some (lid,_) -> Dumpglob.dump_definition lid false "prf"
- | None -> ()) l;
+ List.iter (fun ((id, _), _) -> Dumpglob.dump_definition id false "prf") l;
start_proof_and_print (local, atts.polymorphic, Proof kind) l no_hook
let vernac_end_proof ?proof = function
@@ -905,9 +910,11 @@ let expand filename =
Envars.expand_path_macros ~warn:(fun x -> Feedback.msg_warning (str x)) filename
let vernac_add_loadpath implicit pdir ldiropt =
+ let open Mltop in
let pdir = expand pdir in
let alias = Option.default Libnames.default_root_prefix ldiropt in
- Mltop.add_rec_path Mltop.AddTopML ~unix_path:pdir ~coq_root:alias ~implicit
+ add_coq_path { recursive = true;
+ path_spec = VoPath { unix_path = pdir; coq_path = alias; has_ml = AddTopML; implicit } }
let vernac_remove_loadpath path =
Loadpath.remove_load_path (expand path)
@@ -915,7 +922,8 @@ let vernac_remove_loadpath path =
(* Coq syntax for ML or system commands *)
let vernac_add_ml_path isrec path =
- (if isrec then Mltop.add_rec_ml_dir else Mltop.add_ml_dir) (expand path)
+ let open Mltop in
+ add_coq_path { recursive = isrec; path_spec = MlPath (expand path) }
let vernac_declare_ml_module ~atts l =
let local = make_locality atts.locality in
@@ -934,7 +942,6 @@ let vernac_chdir = function
end;
Flags.if_verbose Feedback.msg_info (str (Sys.getcwd()))
-
(********************)
(* State management *)
@@ -1584,10 +1591,10 @@ let vernac_check_may_eval ~atts redexp glopt rc =
| None ->
let evars_of_term c = Evarutil.undefined_evars_of_term sigma' c in
let l = Evar.Set.union (evars_of_term j.Environ.uj_val) (evars_of_term j.Environ.uj_type) in
- let j = { j with Environ.uj_type = Reductionops.nf_betaiota sigma' j.Environ.uj_type } in
- Feedback.msg_notice (print_judgment env sigma' j ++
- pr_ne_evar_set (fnl () ++ str "where" ++ fnl ()) (mt ()) sigma' l ++
- Printer.pr_universe_ctx_set sigma uctx)
+ let j = { j with Environ.uj_type = Reductionops.nf_betaiota env sigma' j.Environ.uj_type } in
+ print_judgment env sigma' j ++
+ pr_ne_evar_set (fnl () ++ str "where" ++ fnl ()) (mt ()) sigma' l ++
+ Printer.pr_universe_ctx_set sigma uctx
| Some r ->
let (sigma',r_interp) = Hook.get f_interp_redexp env sigma' r in
let redfun env evm c =
@@ -1595,7 +1602,7 @@ let vernac_check_may_eval ~atts redexp glopt rc =
let (_, c) = redfun env evm c in
c
in
- Feedback.msg_notice (print_eval redfun env sigma' rc j)
+ print_eval redfun env sigma' rc j
let vernac_declare_reduction ~atts s r =
let local = make_locality atts.locality in
@@ -1611,8 +1618,8 @@ let vernac_global_check c =
let senv = Safe_typing.push_context_set false uctx senv in
let j = Safe_typing.typing senv c in
let env = Safe_typing.env_of_safe_env senv in
- Feedback.msg_notice (print_safe_judgment env sigma j ++
- pr_universe_ctx_set sigma uctx)
+ print_safe_judgment env sigma j ++
+ pr_universe_ctx_set sigma uctx
let get_nth_goal n =
@@ -1620,7 +1627,7 @@ let get_nth_goal n =
let gls,_,_,_,sigma = Proof.proof pf in
let gl = {Evd.it=List.nth gls (n-1) ; sigma = sigma; } in
gl
-
+
exception NoHyp
(* Printing "About" information of a hypothesis of the current goal.
We only print the type and a small statement to this comes from the
@@ -1654,31 +1661,32 @@ let print_about_hyp_globs ?loc ref_or_by_not udecl glopt =
print_about env sigma ref_or_by_not udecl
let vernac_print ~atts env sigma =
- let open Feedback in
let loc = atts.loc in
function
- | PrintTables -> msg_notice (print_tables ())
- | PrintFullContext-> msg_notice (print_full_context_typ env sigma)
- | PrintSectionContext qid -> msg_notice (print_sec_context_typ env sigma qid)
- | PrintInspect n -> msg_notice (inspect env sigma n)
- | PrintGrammar ent -> msg_notice (Metasyntax.pr_grammar ent)
- | PrintLoadPath dir -> (* For compatibility ? *) msg_notice (print_loadpath dir)
- | PrintModules -> msg_notice (print_modules ())
+ | PrintTables -> print_tables ()
+ | PrintFullContext-> print_full_context_typ env sigma
+ | PrintSectionContext qid -> print_sec_context_typ env sigma qid
+ | PrintInspect n -> inspect env sigma n
+ | PrintGrammar ent -> Metasyntax.pr_grammar ent
+ | PrintLoadPath dir -> (* For compatibility ? *) print_loadpath dir
+ | PrintModules -> print_modules ()
| PrintModule qid -> print_module qid
| PrintModuleType qid -> print_modtype qid
| PrintNamespace ns -> print_namespace ns
- | PrintMLLoadPath -> msg_notice (Mltop.print_ml_path ())
- | PrintMLModules -> msg_notice (Mltop.print_ml_modules ())
- | PrintDebugGC -> msg_notice (Mltop.print_gc ())
- | PrintName (qid,udecl) -> dump_global qid; msg_notice (print_name env sigma qid udecl)
- | PrintGraph -> msg_notice (Prettyp.print_graph env sigma)
- | PrintClasses -> msg_notice (Prettyp.print_classes())
- | PrintTypeClasses -> msg_notice (Prettyp.print_typeclasses())
- | PrintInstances c -> msg_notice (Prettyp.print_instances (smart_global c))
- | PrintCoercions -> msg_notice (Prettyp.print_coercions env sigma)
+ | PrintMLLoadPath -> Mltop.print_ml_path ()
+ | PrintMLModules -> Mltop.print_ml_modules ()
+ | PrintDebugGC -> Mltop.print_gc ()
+ | PrintName (qid,udecl) ->
+ dump_global qid;
+ print_name env sigma qid udecl
+ | PrintGraph -> Prettyp.print_graph env sigma
+ | PrintClasses -> Prettyp.print_classes()
+ | PrintTypeClasses -> Prettyp.print_typeclasses()
+ | PrintInstances c -> Prettyp.print_instances (smart_global c)
+ | PrintCoercions -> Prettyp.print_coercions env sigma
| PrintCoercionPaths (cls,clt) ->
- msg_notice (Prettyp.print_path_between env sigma (cl_of_qualid cls) (cl_of_qualid clt))
- | PrintCanonicalConversions -> msg_notice (Prettyp.print_canonical_projections env sigma)
+ Prettyp.print_path_between env sigma (cl_of_qualid cls) (cl_of_qualid clt)
+ | PrintCanonicalConversions -> Prettyp.print_canonical_projections env sigma
| PrintUniverses (b, dst) ->
let univ = Global.universes () in
let univ = if b then UGraph.sort_universes univ else univ in
@@ -1687,23 +1695,24 @@ let vernac_print ~atts env sigma =
else str"There may remain asynchronous universe constraints"
in
begin match dst with
- | None -> msg_notice (UGraph.pr_universes Universes.pr_with_global_universes univ ++ pr_remaining)
+ | None -> UGraph.pr_universes Universes.pr_with_global_universes univ ++ pr_remaining
| Some s -> dump_universes_gen univ s
end
- | PrintHint r -> msg_notice (Hints.pr_hint_ref env sigma (smart_global r))
- | PrintHintGoal -> msg_notice (Hints.pr_applicable_hint ())
- | PrintHintDbName s -> msg_notice (Hints.pr_hint_db_by_name env sigma s)
- | PrintHintDb -> msg_notice (Hints.pr_searchtable env sigma)
+ | PrintHint r -> Hints.pr_hint_ref env sigma (smart_global r)
+ | PrintHintGoal -> Hints.pr_applicable_hint ()
+ | PrintHintDbName s -> Hints.pr_hint_db_by_name env sigma s
+ | PrintHintDb -> Hints.pr_searchtable env sigma
| PrintScopes ->
- msg_notice (Notation.pr_scopes (Constrextern.without_symbols (pr_lglob_constr_env env)))
+ Notation.pr_scopes (Constrextern.without_symbols (pr_lglob_constr_env env))
| PrintScope s ->
- msg_notice (Notation.pr_scope (Constrextern.without_symbols (pr_lglob_constr_env env)) s)
+ Notation.pr_scope (Constrextern.without_symbols (pr_lglob_constr_env env)) s
| PrintVisibility s ->
- msg_notice (Notation.pr_visibility (Constrextern.without_symbols (pr_lglob_constr_env env)) s)
+ Notation.pr_visibility (Constrextern.without_symbols (pr_lglob_constr_env env)) s
| PrintAbout (ref_or_by_not,udecl,glnumopt) ->
- msg_notice (print_about_hyp_globs ?loc ref_or_by_not udecl glnumopt)
+ print_about_hyp_globs ?loc ref_or_by_not udecl glnumopt
| PrintImplicit qid ->
- dump_global qid; msg_notice (print_impargs qid)
+ dump_global qid;
+ print_impargs qid
| PrintAssumptions (o,t,r) ->
(* Prints all the axioms and section variables used by a term *)
let gr = smart_global r in
@@ -1711,7 +1720,7 @@ let vernac_print ~atts env sigma =
let st = Conv_oracle.get_transp_state (Environ.oracle (Global.env())) in
let nassums =
Assumptions.assumptions st ~add_opaque:o ~add_transparent:t gr cstr in
- msg_notice (Printer.pr_assumptionset env sigma nassums)
+ Printer.pr_assumptionset env sigma nassums
| PrintStrategy r -> print_strategy r
let global_module r =
@@ -1797,19 +1806,18 @@ let vernac_search ~atts s gopt r =
| SearchAbout sl ->
(Search.search_about gopt (List.map (on_snd (interp_search_about_item env)) sl) r |> Search.prioritize_search) pr_search
-let vernac_locate = let open Feedback in function
- | LocateAny (AN qid) -> msg_notice (print_located_qualid qid)
- | LocateTerm (AN qid) -> msg_notice (print_located_term qid)
+let vernac_locate = function
+ | LocateAny (AN qid) -> print_located_qualid qid
+ | LocateTerm (AN qid) -> print_located_term qid
| LocateAny (ByNotation (_, (ntn, sc))) (** TODO : handle Ltac notations *)
| LocateTerm (ByNotation (_, (ntn, sc))) ->
let _, env = Pfedit.get_current_context () in
- msg_notice
- (Notation.locate_notation
- (Constrextern.without_symbols (pr_lglob_constr_env env)) ntn sc)
+ Notation.locate_notation
+ (Constrextern.without_symbols (pr_lglob_constr_env env)) ntn sc
| LocateLibrary qid -> print_located_library qid
- | LocateModule qid -> msg_notice (print_located_module qid)
- | LocateOther (s, qid) -> msg_notice (print_located_other s qid)
- | LocateFile f -> msg_notice (locate_file f)
+ | LocateModule qid -> print_located_module qid
+ | LocateOther (s, qid) -> print_located_other s qid
+ | LocateFile f -> locate_file f
let vernac_register id r =
if Proof_global.there_are_pending_proofs () then
@@ -1841,16 +1849,13 @@ let vernac_unfocus () =
let vernac_unfocused () =
let p = Proof_global.give_me_the_proof () in
if Proof.unfocused p then
- Feedback.msg_notice (str"The proof is indeed fully unfocused.")
+ str"The proof is indeed fully unfocused."
else
user_err Pp.(str "The proof is not fully unfocused.")
-(* BeginSubproof / EndSubproof.
- BeginSubproof (vernac_subproof) focuses on the first goal, or the goal
- given as argument.
- EndSubproof (vernac_end_subproof) unfocuses from a BeginSubproof, provided
- that the proof of the goal has been completed.
+(* "{" focuses on the first goal, "n: {" focuses on the n-th goal
+ "}" unfocuses, provided that the proof of the goal has been completed.
*)
let subproof_kind = Proof.new_focus_kind ()
let subproof_cond = Proof.done_cond subproof_kind
@@ -1859,7 +1864,9 @@ let vernac_subproof gln =
Proof_global.simple_with_current_proof (fun _ p ->
match gln with
| None -> Proof.focus subproof_cond () 1 p
- | Some n -> Proof.focus subproof_cond () n p)
+ | Some (SelectNth n) -> Proof.focus subproof_cond () n p
+ | _ -> user_err ~hdr:"bracket_selector"
+ (str "Brackets only support the single numbered goal selector."))
let vernac_end_subproof () =
Proof_global.simple_with_current_proof (fun _ p ->
@@ -1869,21 +1876,20 @@ let vernac_bullet (bullet : Proof_bullet.t) =
Proof_global.simple_with_current_proof (fun _ p ->
Proof_bullet.put p bullet)
-let vernac_show = let open Feedback in function
+let vernac_show = function
| ShowScript -> assert false (* Only the stm knows the script *)
| ShowGoal goalref ->
let proof = Proof_global.give_me_the_proof () in
- let info = match goalref with
- | OpenSubgoals -> pr_open_subgoals ~proof
- | NthGoal n -> pr_nth_open_subgoal ~proof n
- | GoalId id -> pr_goal_by_id ~proof id
- in
- msg_notice info
+ begin match goalref with
+ | OpenSubgoals -> pr_open_subgoals ~proof
+ | NthGoal n -> pr_nth_open_subgoal ~proof n
+ | GoalId id -> pr_goal_by_id ~proof id
+ end
| ShowProof -> show_proof ()
| ShowExistentials -> show_top_evars ()
| ShowUniverses -> show_universes ()
| ShowProofNames ->
- msg_notice (pr_sequence Id.print (Proof_global.get_all_proof_names()))
+ pr_sequence Id.print (Proof_global.get_all_proof_names())
| ShowIntros all -> show_intro all
| ShowMatch id -> show_match id
@@ -1898,8 +1904,7 @@ let vernac_check_guard () =
(str "The condition holds up to here")
with UserError(_,s) ->
(str ("Condition violated: ") ++s)
- in
- Feedback.msg_notice message
+ in message
exception End_of_input
@@ -1959,11 +1964,6 @@ let interp ?proof ~atts ~st c =
(* This one is possible to handle here *)
| VernacAbort id -> CErrors.user_err (str "Abort cannot be used through the Load command")
- (* Handled elsewhere *)
- | VernacProgram _
- | VernacPolymorphic _
- | VernacLocal _ -> assert false
-
(* Syntax *)
| VernacSyntaxExtension (infix, sl) ->
vernac_syntax_extension atts infix sl
@@ -2059,27 +2059,32 @@ let interp ?proof ~atts ~st c =
| VernacAddOption (key,v) -> vernac_add_option key v
| VernacMemOption (key,v) -> vernac_mem_option key v
| VernacPrintOption key -> vernac_print_option key
- | VernacCheckMayEval (r,g,c) -> vernac_check_may_eval ~atts r g c
+ | VernacCheckMayEval (r,g,c) ->
+ Feedback.msg_notice @@ vernac_check_may_eval ~atts r g c
| VernacDeclareReduction (s,r) -> vernac_declare_reduction ~atts s r
- | VernacGlobalCheck c -> vernac_global_check c
+ | VernacGlobalCheck c ->
+ Feedback.msg_notice @@ vernac_global_check c
| VernacPrint p ->
let sigma, env = Pfedit.get_current_context () in
- vernac_print ~atts env sigma p
+ Feedback.msg_notice @@ vernac_print ~atts env sigma p
| VernacSearch (s,g,r) -> vernac_search ~atts s g r
- | VernacLocate l -> vernac_locate l
+ | VernacLocate l ->
+ Feedback.msg_notice @@ vernac_locate l
| VernacRegister (id, r) -> vernac_register id r
| VernacComments l -> Flags.if_verbose Feedback.msg_info (str "Comments ok\n")
(* Proof management *)
- | VernacGoal t -> vernac_start_proof ~atts Theorem [None,([],t)]
| VernacFocus n -> vernac_focus n
| VernacUnfocus -> vernac_unfocus ()
- | VernacUnfocused -> vernac_unfocused ()
+ | VernacUnfocused ->
+ Feedback.msg_notice @@ vernac_unfocused ()
| VernacBullet b -> vernac_bullet b
| VernacSubproof n -> vernac_subproof n
| VernacEndSubproof -> vernac_end_subproof ()
- | VernacShow s -> vernac_show s
- | VernacCheckGuard -> vernac_check_guard ()
+ | VernacShow s ->
+ Feedback.msg_notice @@ vernac_show s
+ | VernacCheckGuard ->
+ Feedback.msg_notice @@ vernac_check_guard ()
| VernacProof (tac, using) ->
let using = Option.append using (Proof_using.get_default_proof_using ()) in
let tacs = if Option.is_empty tac then "tac:no" else "tac:yes" in
@@ -2200,10 +2205,30 @@ let with_fail st b f =
let interp ?(verbosely=true) ?proof ~st (loc,c) =
let orig_univ_poly = Flags.is_universe_polymorphism () in
let orig_program_mode = Flags.is_program_mode () in
+ let flags f atts =
+ List.fold_left
+ (fun (polymorphism, atts) f ->
+ match f with
+ | VernacProgram when not atts.program ->
+ (polymorphism, { atts with program = true })
+ | VernacProgram ->
+ user_err Pp.(str "Program mode specified twice")
+ | VernacPolymorphic b when polymorphism = None ->
+ (Some b, atts)
+ | VernacPolymorphic _ ->
+ user_err Pp.(str "Polymorphism specified twice")
+ | VernacLocal b when Option.is_empty atts.locality ->
+ (polymorphism, { atts with locality = Some b })
+ | VernacLocal _ ->
+ user_err Pp.(str "Locality specified twice")
+ )
+ (None, atts)
+ f
+ in
let rec control = function
- | VernacExpr v ->
- let atts = { loc; locality = None; polymorphic = false; } in
- aux ~atts orig_program_mode v
+ | VernacExpr (f, v) ->
+ let (polymorphism, atts) = flags f { loc; locality = None; polymorphic = false; program = orig_program_mode; } in
+ aux ~polymorphism ~atts v
| VernacFail v -> with_fail st true (fun () -> control v)
| VernacTimeout (n,v) ->
current_timeout := Some n;
@@ -2213,25 +2238,8 @@ let interp ?(verbosely=true) ?proof ~st (loc,c) =
| VernacTime (batch, (_loc,v)) ->
System.with_time ~batch control v;
- and aux ?polymorphism ~atts isprogcmd = function
-
- | VernacProgram c when not isprogcmd ->
- aux ?polymorphism ~atts true c
-
- | VernacProgram _ ->
- user_err Pp.(str "Program mode specified twice")
-
- | VernacPolymorphic (b, c) when polymorphism = None ->
- aux ~polymorphism:b ~atts:atts isprogcmd c
-
- | VernacPolymorphic (b, c) ->
- user_err Pp.(str "Polymorphism specified twice")
-
- | VernacLocal (b, c) when Option.is_empty atts.locality ->
- aux ?polymorphism ~atts:{atts with locality = Some b} isprogcmd c
-
- | VernacLocal _ ->
- user_err Pp.(str "Locality specified twice")
+ and aux ~polymorphism ~atts : _ -> unit =
+ function
| VernacLoad (_,fname) -> vernac_load control fname
@@ -2240,7 +2248,7 @@ let interp ?(verbosely=true) ?proof ~st (loc,c) =
check_vernac_supports_polymorphism c polymorphism;
let polymorphic = Option.default (Flags.is_universe_polymorphism ()) polymorphism in
Flags.make_universe_polymorphism polymorphic;
- Obligations.set_program_mode isprogcmd;
+ Obligations.set_program_mode atts.program;
try
vernac_timeout begin fun () ->
let atts = { atts with polymorphic } in
@@ -2249,7 +2257,7 @@ let interp ?(verbosely=true) ?proof ~st (loc,c) =
else Flags.silently (interp ?proof ~atts ~st) c;
(* If the command is `(Un)Set Program Mode` or `(Un)Set Universe Polymorphism`,
we should not restore the previous state of the flag... *)
- if orig_program_mode || not !Flags.program_mode || isprogcmd then
+ if orig_program_mode || not !Flags.program_mode || atts.program then
Flags.program_mode := orig_program_mode;
if (Flags.is_universe_polymorphism() = polymorphic) then
Flags.make_universe_polymorphism orig_univ_poly;
@@ -2271,8 +2279,7 @@ let interp ?(verbosely=true) ?proof ~st (loc,c) =
then Flags.verbosely control c
else control c
-(* XXX: There is a bug here in case of an exception, see @gares
- comments on the PR *)
+(* Be careful with the cache here in case of an exception. *)
let interp ?verbosely ?proof ~st cmd =
Vernacstate.unfreeze_interp_state st;
try
diff --git a/vernac/vernacinterp.ml b/vernac/vernacinterp.ml
index c0b93c163..c40ca27db 100644
--- a/vernac/vernacinterp.ml
+++ b/vernac/vernacinterp.ml
@@ -16,6 +16,7 @@ type atts = {
loc : Loc.t option;
locality : bool option;
polymorphic : bool;
+ program : bool;
}
type 'a vernac_command = 'a -> atts:atts -> st:Vernacstate.t -> Vernacstate.t
diff --git a/vernac/vernacinterp.mli b/vernac/vernacinterp.mli
index ab3d4bfc5..c5e610f89 100644
--- a/vernac/vernacinterp.mli
+++ b/vernac/vernacinterp.mli
@@ -14,6 +14,7 @@ type atts = {
loc : Loc.t option;
locality : bool option;
polymorphic : bool;
+ program : bool;
}
type 'a vernac_command = 'a -> atts:atts -> st:Vernacstate.t -> Vernacstate.t
diff --git a/vernac/vernacprop.ml b/vernac/vernacprop.ml
index 4fdc78dd2..3932d1c7b 100644
--- a/vernac/vernacprop.ml
+++ b/vernac/vernacprop.ml
@@ -12,14 +12,14 @@
open Vernacexpr
let rec under_control = function
- | VernacExpr c -> c
+ | VernacExpr (_, c) -> c
| VernacRedirect (_,(_,c))
| VernacTime (_,(_,c))
| VernacFail c
| VernacTimeout (_,c) -> under_control c
let rec has_Fail = function
- | VernacExpr c -> false
+ | VernacExpr _ -> false
| VernacRedirect (_,(_,c))
| VernacTime (_,(_,c))
| VernacTimeout (_,c) -> has_Fail c
@@ -45,8 +45,8 @@ let rec is_deep_navigation_vernac = function
(* NB: Reset is now allowed again as asked by A. Chlipala *)
let is_reset = function
- | VernacExpr VernacResetInitial
- | VernacExpr (VernacResetName _) -> true
+ | VernacExpr ( _, VernacResetInitial)
+ | VernacExpr (_, VernacResetName _) -> true
| _ -> false
let is_debug cmd = match under_control cmd with