aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.circleci/config.yml202
-rw-r--r--.github/CODEOWNERS94
-rw-r--r--.gitignore11
-rw-r--r--.gitlab-ci.yml78
-rw-r--r--.merlin.in (renamed from .merlin)0
-rw-r--r--.travis.yml79
-rw-r--r--CHANGES101
-rw-r--r--CONTRIBUTING.md29
-rw-r--r--CREDITS2
-rw-r--r--INSTALL37
-rw-r--r--INSTALL.doc91
-rw-r--r--INSTALL.ide123
-rw-r--r--META.coq.in (renamed from META.coq)12
-rw-r--r--Makefile54
-rw-r--r--Makefile.build55
-rw-r--r--Makefile.checker4
-rw-r--r--Makefile.ci7
-rw-r--r--Makefile.common21
-rw-r--r--Makefile.dev4
-rw-r--r--Makefile.doc6
-rw-r--r--Makefile.ide10
-rw-r--r--Makefile.install14
-rw-r--r--README.md13
-rw-r--r--checker/cic.mli20
-rw-r--r--checker/closure.ml49
-rw-r--r--checker/closure.mli2
-rw-r--r--checker/declarations.ml16
-rw-r--r--checker/declarations.mli3
-rw-r--r--checker/environ.ml27
-rw-r--r--checker/environ.mli4
-rw-r--r--checker/indtypes.ml22
-rw-r--r--checker/inductive.ml24
-rw-r--r--checker/mod_checking.ml27
-rw-r--r--checker/modops.ml22
-rw-r--r--checker/print.ml4
-rw-r--r--checker/reduction.ml65
-rw-r--r--checker/subtyping.ml102
-rw-r--r--checker/term.ml20
-rw-r--r--checker/typeops.ml21
-rw-r--r--checker/univ.ml42
-rw-r--r--checker/univ.mli2
-rw-r--r--checker/values.ml16
-rw-r--r--clib/cArray.ml7
-rw-r--r--clib/cArray.mli3
-rw-r--r--clib/cList.ml13
-rw-r--r--clib/cList.mli9
-rw-r--r--clib/clib.mllib2
-rw-r--r--clib/diff2.ml158
-rw-r--r--clib/diff2.mli101
-rw-r--r--clib/terminal.ml48
-rw-r--r--clib/terminal.mli6
-rw-r--r--configure.ml39
-rw-r--r--coqpp/coqpp_ast.mli95
-rw-r--r--coqpp/coqpp_lex.mll167
-rw-r--r--coqpp/coqpp_main.ml353
-rw-r--r--coqpp/coqpp_parse.mly256
-rw-r--r--default.nix98
-rw-r--r--dev/README50
-rw-r--r--dev/README.md46
-rwxr-xr-x[-rw-r--r--]dev/build/windows/MakeCoq_MinGW.bat8
-rw-r--r--dev/build/windows/makecoq_mingw.sh82
-rw-r--r--dev/ci/README.md18
-rw-r--r--dev/ci/appveyor.sh2
-rwxr-xr-xdev/ci/ci-basic-overlay.sh168
-rwxr-xr-xdev/ci/ci-bedrock2.sh9
-rwxr-xr-xdev/ci/ci-bignums.sh14
-rwxr-xr-xdev/ci/ci-color.sh6
-rw-r--r--dev/ci/ci-common.sh75
-rwxr-xr-xdev/ci/ci-compcert.sh7
-rwxr-xr-xdev/ci/ci-coq-dpdgraph.sh6
-rwxr-xr-xdev/ci/ci-coquelicot.sh7
-rwxr-xr-xdev/ci/ci-corn.sh6
-rwxr-xr-xdev/ci/ci-cross-crypto.sh8
-rwxr-xr-xdev/ci/ci-elpi.sh6
-rwxr-xr-xdev/ci/ci-equations.sh7
-rwxr-xr-xdev/ci/ci-ext-lib.sh14
-rwxr-xr-xdev/ci/ci-fcsl-pcm.sh6
-rwxr-xr-xdev/ci/ci-fiat-crypto-legacy.sh13
-rwxr-xr-xdev/ci/ci-fiat-crypto.sh14
-rwxr-xr-xdev/ci/ci-fiat-parsers.sh7
-rwxr-xr-xdev/ci/ci-flocq.sh6
-rwxr-xr-xdev/ci/ci-formal-topology.sh6
-rwxr-xr-xdev/ci/ci-geocoq.sh8
-rwxr-xr-xdev/ci/ci-hott.sh6
-rwxr-xr-xdev/ci/ci-iris-lambda-rust.sh22
-rwxr-xr-xdev/ci/ci-ltac2.sh6
-rwxr-xr-xdev/ci/ci-math-classes.sh6
-rwxr-xr-xdev/ci/ci-math-comp.sh11
-rwxr-xr-xdev/ci/ci-mtac2.sh15
-rwxr-xr-xdev/ci/ci-pidetop.sh9
-rwxr-xr-xdev/ci/ci-quickchick.sh14
-rwxr-xr-xdev/ci/ci-simple-io.sh8
-rwxr-xr-xdev/ci/ci-template.sh12
-rwxr-xr-xdev/ci/ci-tlc.sh7
-rwxr-xr-xdev/ci/ci-unimath.sh6
-rwxr-xr-xdev/ci/ci-vst.sh6
-rw-r--r--dev/ci/docker/bionic_coq/Dockerfile18
-rw-r--r--dev/ci/gitlab.bat2
-rw-r--r--dev/ci/user-overlays/00664-herbelin-master+change-for-coq-pr664-compatibility.sh4
-rw-r--r--dev/ci/user-overlays/00669-maximedenes-ssr-merge.sh4
-rw-r--r--dev/ci/user-overlays/06454-ejgallego-evar+strict_to_constr.sh8
-rw-r--r--dev/ci/user-overlays/06859-ejgallego-stm+top.sh9
-rw-r--r--dev/ci/user-overlays/06960-ejgallego-ltac+tacdepr.sh12
-rw-r--r--dev/ci/user-overlays/07085-ppedrot-pure-sharing-flag.sh8
-rw-r--r--dev/ci/user-overlays/07099-ppedrot-unification-returns-option.sh4
-rw-r--r--dev/ci/user-overlays/07136-evar-map-econstr.sh7
-rw-r--r--dev/ci/user-overlays/07152-ejgallego-api+vernac_expr_iso.sh12
-rw-r--r--dev/ci/user-overlays/07196-ejgallego-tactics+push_fix_naming_out.sh21
-rw-r--r--dev/ci/user-overlays/07213-ppedrot-fast-constr-match-no-context.sh6
-rw-r--r--dev/ci/user-overlays/07495-gares-elpi-test-bug.sh8
-rw-r--r--dev/ci/user-overlays/07558-ejgallego-vernac+move_parser.sh14
-rw-r--r--dev/ci/user-overlays/07677-ejgallego-misctypes+bye2.sh8
-rw-r--r--dev/ci/user-overlays/07797-rm-reference.sh20
-rw-r--r--dev/ci/user-overlays/README.md12
-rw-r--r--dev/doc/README.md77
-rw-r--r--dev/doc/changes.md118
-rw-r--r--dev/doc/critical-bugs252
-rw-r--r--dev/doc/setup.txt269
-rw-r--r--dev/doc/translate.txt495
-rw-r--r--dev/doc/versions-history.tex12
-rw-r--r--dev/doc/xml-protocol.md4
-rw-r--r--dev/ocamldebug-coq.run2
-rwxr-xr-xdev/tools/backport-pr.sh43
-rwxr-xr-xdev/tools/check-overlays.sh4
-rw-r--r--dev/tools/coqdev.el2
-rw-r--r--dev/top_printers.ml10
-rw-r--r--dev/vm_printers.ml6
-rw-r--r--doc/LICENSE4
-rw-r--r--doc/README.md114
-rw-r--r--doc/sphinx/README.rst7
-rw-r--r--doc/sphinx/README.template.rst2
-rw-r--r--doc/sphinx/addendum/canonical-structures.rst20
-rw-r--r--doc/sphinx/addendum/extended-pattern-matching.rst48
-rw-r--r--doc/sphinx/addendum/extraction.rst48
-rw-r--r--doc/sphinx/addendum/generalized-rewriting.rst588
-rw-r--r--doc/sphinx/addendum/implicit-coercions.rst32
-rw-r--r--doc/sphinx/addendum/micromega.rst27
-rw-r--r--doc/sphinx/addendum/miscellaneous-extensions.rst1
-rw-r--r--doc/sphinx/addendum/nsatz.rst103
-rw-r--r--doc/sphinx/addendum/omega.rst57
-rw-r--r--doc/sphinx/addendum/parallel-proof-processing.rst17
-rw-r--r--doc/sphinx/addendum/program.rst46
-rw-r--r--doc/sphinx/addendum/ring.rst108
-rw-r--r--doc/sphinx/addendum/type-classes.rst82
-rw-r--r--doc/sphinx/addendum/universe-polymorphism.rst4
-rw-r--r--doc/sphinx/biblio.bib38
-rw-r--r--doc/sphinx/credits.rst133
-rw-r--r--doc/sphinx/index.rst5
-rw-r--r--doc/sphinx/introduction.rst60
-rw-r--r--doc/sphinx/language/cic.rst274
-rw-r--r--doc/sphinx/language/coq-library.rst31
-rw-r--r--doc/sphinx/language/gallina-extensions.rst64
-rw-r--r--doc/sphinx/language/gallina-specification-language.rst102
-rw-r--r--doc/sphinx/practical-tools/coq-commands.rst71
-rw-r--r--doc/sphinx/practical-tools/coqide.rst33
-rw-r--r--doc/sphinx/practical-tools/utilities.rst142
-rw-r--r--doc/sphinx/proof-engine/detailed-tactic-examples.rst646
-rw-r--r--doc/sphinx/proof-engine/ltac.rst175
-rw-r--r--doc/sphinx/proof-engine/proof-handling.rst74
-rw-r--r--doc/sphinx/proof-engine/ssreflect-proof-language.rst172
-rw-r--r--doc/sphinx/proof-engine/tactics.rst1265
-rw-r--r--doc/sphinx/proof-engine/vernacular-commands.rst39
-rw-r--r--doc/sphinx/user-extensions/proof-schemes.rst34
-rw-r--r--doc/sphinx/user-extensions/syntax-extensions.rst533
-rw-r--r--doc/stdlib/index-list.html.template3
-rw-r--r--doc/tools/coqrst/coqdomain.py31
-rw-r--r--engine/eConstr.ml18
-rw-r--r--engine/eConstr.mli4
-rw-r--r--engine/evar_kinds.ml17
-rw-r--r--engine/evar_kinds.mli51
-rw-r--r--engine/evarutil.ml34
-rw-r--r--engine/evarutil.mli20
-rw-r--r--engine/evd.ml11
-rw-r--r--engine/evd.mli10
-rw-r--r--engine/namegen.ml5
-rw-r--r--engine/proofview.ml2
-rw-r--r--engine/termops.ml17
-rw-r--r--engine/termops.mli24
-rw-r--r--engine/uState.ml2
-rw-r--r--engine/univGen.ml4
-rw-r--r--engine/univGen.mli2
-rw-r--r--engine/univSubst.ml12
-rw-r--r--engine/univSubst.mli2
-rw-r--r--engine/universes.mli4
-rw-r--r--engine/univops.ml15
-rw-r--r--engine/univops.mli4
-rw-r--r--grammar/q_util.mli2
-rw-r--r--grammar/q_util.mlp16
-rw-r--r--grammar/tacextend.mlp29
-rw-r--r--grammar/vernacextend.mlp171
-rw-r--r--ide/.merlin.in (renamed from ide/.merlin)0
-rw-r--r--ide/MacOS/default_accel_map1
-rw-r--r--ide/coq.ml47
-rw-r--r--ide/coq.mli10
-rw-r--r--ide/coq_commands.ml1
-rw-r--r--ide/coq_lex.mll6
-rw-r--r--ide/coqide.ml29
-rw-r--r--ide/coqide_ui.ml4
-rw-r--r--ide/gtk_parsing.ml7
-rw-r--r--ide/idetop.ml36
-rw-r--r--ide/ideutils.ml43
-rw-r--r--ide/preferences.ml28
-rw-r--r--ide/preferences.mli2
-rw-r--r--ide/wg_ProofView.ml4
-rw-r--r--interp/constrexpr.ml5
-rw-r--r--interp/constrexpr_ops.ml5
-rw-r--r--interp/constrexpr_ops.mli4
-rw-r--r--interp/constrextern.ml204
-rw-r--r--interp/constrintern.ml70
-rw-r--r--interp/declare.ml121
-rw-r--r--interp/dumpglob.ml6
-rw-r--r--interp/impargs.ml4
-rw-r--r--interp/implicit_quantifiers.ml4
-rw-r--r--interp/implicit_quantifiers.mli8
-rw-r--r--interp/notation.ml231
-rw-r--r--interp/notation.mli45
-rw-r--r--interp/notation_ops.ml12
-rw-r--r--interp/notation_ops.mli10
-rw-r--r--interp/notation_term.ml4
-rw-r--r--interp/syntax_def.ml4
-rw-r--r--kernel/cClosure.ml98
-rw-r--r--kernel/cClosure.mli12
-rw-r--r--kernel/cbytecodes.ml10
-rw-r--r--kernel/cbytecodes.mli4
-rw-r--r--kernel/cbytegen.ml40
-rw-r--r--kernel/cemitcodes.ml10
-rw-r--r--kernel/cemitcodes.mli2
-rw-r--r--kernel/cinstr.mli2
-rw-r--r--kernel/clambda.ml16
-rw-r--r--kernel/constr.ml23
-rw-r--r--kernel/constr.mli9
-rw-r--r--kernel/context.ml21
-rw-r--r--kernel/context.mli21
-rw-r--r--kernel/cooking.ml21
-rw-r--r--kernel/cooking.mli5
-rw-r--r--kernel/csymtable.ml6
-rw-r--r--kernel/declarations.ml23
-rw-r--r--kernel/declareops.ml32
-rw-r--r--kernel/declareops.mli5
-rw-r--r--kernel/entries.ml6
-rw-r--r--kernel/environ.ml51
-rw-r--r--kernel/environ.mli66
-rw-r--r--kernel/indtypes.ml37
-rw-r--r--kernel/indtypes.mli3
-rw-r--r--kernel/inductive.ml24
-rw-r--r--kernel/inductive.mli8
-rw-r--r--kernel/kernel.mllib2
-rw-r--r--kernel/mod_subst.ml12
-rw-r--r--kernel/mod_subst.mli3
-rw-r--r--kernel/modops.ml5
-rw-r--r--kernel/modops.mli1
-rw-r--r--kernel/names.ml140
-rw-r--r--kernel/names.mli58
-rw-r--r--kernel/nativecode.ml66
-rw-r--r--kernel/nativecode.mli2
-rw-r--r--kernel/nativeconv.ml22
-rw-r--r--kernel/nativeinstr.mli2
-rw-r--r--kernel/nativelambda.ml240
-rw-r--r--kernel/nativelambda.mli2
-rw-r--r--kernel/nativelib.ml1
-rw-r--r--kernel/nativelibrary.ml2
-rw-r--r--kernel/nativevalues.ml65
-rw-r--r--kernel/nativevalues.mli3
-rw-r--r--kernel/opaqueproof.ml2
-rw-r--r--kernel/opaqueproof.mli2
-rw-r--r--kernel/reduction.ml77
-rw-r--r--kernel/reduction.mli8
-rw-r--r--kernel/retroknowledge.ml19
-rw-r--r--kernel/retroknowledge.mli20
-rw-r--r--kernel/safe_typing.ml4
-rw-r--r--kernel/safe_typing.mli1
-rw-r--r--kernel/sorts.ml57
-rw-r--r--kernel/sorts.mli7
-rw-r--r--kernel/subtyping.ml85
-rw-r--r--kernel/term.ml7
-rw-r--r--kernel/term.mli41
-rw-r--r--kernel/term_typing.ml6
-rw-r--r--kernel/typeops.ml22
-rw-r--r--kernel/typeops.mli5
-rw-r--r--kernel/uGraph.ml39
-rw-r--r--kernel/uGraph.mli3
-rw-r--r--kernel/univ.ml9
-rw-r--r--kernel/vars.mli14
-rw-r--r--kernel/vconv.ml2
-rw-r--r--kernel/vmvalues.ml6
-rw-r--r--kernel/vmvalues.mli6
-rw-r--r--lib/cWarnings.ml6
-rw-r--r--lib/coqProject_file.ml (renamed from lib/coqProject_file.ml4)64
-rw-r--r--lib/envars.ml2
-rw-r--r--lib/lib.mllib1
-rw-r--r--lib/pp.ml75
-rw-r--r--lib/pp.mli19
-rw-r--r--lib/pp_diff.ml303
-rw-r--r--lib/pp_diff.mli116
-rw-r--r--lib/system.ml2
-rw-r--r--lib/util.ml4
-rw-r--r--library/global.ml7
-rw-r--r--library/global.mli7
-rw-r--r--library/goptions.ml19
-rw-r--r--library/lib.ml27
-rw-r--r--library/lib.mli14
-rw-r--r--library/libobject.ml16
-rw-r--r--library/library.ml36
-rw-r--r--library/library.mllib1
-rw-r--r--man/gallina.174
-rw-r--r--parsing/extend.ml13
-rw-r--r--parsing/g_constr.mlg (renamed from parsing/g_constr.ml4)351
-rw-r--r--parsing/g_prim.ml4122
-rw-r--r--parsing/g_prim.mlg123
-rw-r--r--parsing/notation_gram.ml3
-rw-r--r--parsing/notgram_ops.ml46
-rw-r--r--parsing/pcoq.ml250
-rw-r--r--parsing/pcoq.mli223
-rw-r--r--parsing/ppextend.ml21
-rw-r--r--parsing/ppextend.mli1
-rw-r--r--plugins/.merlin.in (renamed from plugins/.merlin)0
-rw-r--r--plugins/btauto/g_btauto.mlg (renamed from plugins/btauto/g_btauto.ml4)6
-rw-r--r--plugins/cc/ccalgo.ml6
-rw-r--r--plugins/cc/cctac.ml4
-rw-r--r--plugins/cc/g_congruence.mlg (renamed from plugins/cc/g_congruence.ml4)14
-rw-r--r--plugins/extraction/ExtrHaskellString.v2
-rw-r--r--plugins/extraction/ExtrOcamlString.v1
-rw-r--r--plugins/extraction/extraction.ml24
-rw-r--r--plugins/firstorder/ground.ml16
-rw-r--r--plugins/fourier/Fourier.v20
-rw-r--r--plugins/fourier/Fourier_util.v222
-rw-r--r--plugins/fourier/fourier.ml204
-rw-r--r--plugins/fourier/fourierR.ml644
-rw-r--r--plugins/fourier/fourier_plugin.mlpack3
-rw-r--r--plugins/fourier/g_fourier.ml418
-rw-r--r--plugins/funind/functional_principles_types.ml11
-rw-r--r--plugins/funind/glob_term_to_relation.ml2
-rw-r--r--plugins/funind/invfun.ml2
-rw-r--r--plugins/funind/recdef.mli2
-rw-r--r--plugins/ltac/coretactics.mlg (renamed from plugins/ltac/coretactics.ml4)184
-rw-r--r--plugins/ltac/extraargs.ml439
-rw-r--r--plugins/ltac/extraargs.mli16
-rw-r--r--plugins/ltac/extratactics.ml421
-rw-r--r--plugins/ltac/g_eqdecide.mlg (renamed from plugins/ltac/g_eqdecide.ml4)8
-rw-r--r--plugins/ltac/g_ltac.ml416
-rw-r--r--plugins/ltac/g_tactic.mlg (renamed from plugins/ltac/g_tactic.ml4)452
-rw-r--r--plugins/ltac/pltac.ml9
-rw-r--r--plugins/ltac/pltac.mli38
-rw-r--r--plugins/ltac/pptactic.ml51
-rw-r--r--plugins/ltac/rewrite.ml2
-rw-r--r--plugins/ltac/taccoerce.ml32
-rw-r--r--plugins/ltac/taccoerce.mli14
-rw-r--r--plugins/ltac/tacentries.ml77
-rw-r--r--plugins/ltac/tacentries.mli19
-rw-r--r--plugins/ltac/tacenv.ml47
-rw-r--r--plugins/ltac/tacenv.mli20
-rw-r--r--plugins/ltac/tacexpr.ml4
-rw-r--r--plugins/ltac/tacexpr.mli4
-rw-r--r--plugins/ltac/tacintern.ml27
-rw-r--r--plugins/ltac/tacinterp.ml57
-rw-r--r--plugins/ltac/tacinterp.mli1
-rw-r--r--plugins/micromega/Fourier.v5
-rw-r--r--plugins/micromega/Fourier_util.v31
-rw-r--r--plugins/micromega/g_micromega.mlg (renamed from plugins/micromega/g_micromega.ml4)38
-rw-r--r--plugins/micromega/mutils.mli2
-rw-r--r--plugins/nsatz/g_nsatz.mlg (renamed from plugins/nsatz/g_nsatz.ml4)6
-rw-r--r--plugins/omega/coq_omega.ml10
-rw-r--r--plugins/omega/g_omega.mlg (renamed from plugins/omega/g_omega.ml4)9
-rw-r--r--plugins/quote/g_quote.mlg (renamed from plugins/quote/g_quote.ml4)16
-rw-r--r--plugins/romega/g_romega.mlg (renamed from plugins/romega/g_romega.ml4)12
-rw-r--r--plugins/rtauto/g_rtauto.mlg (renamed from plugins/rtauto/g_rtauto.ml4)5
-rw-r--r--plugins/setoid_ring/g_newring.ml45
-rw-r--r--plugins/setoid_ring/newring.ml60
-rw-r--r--plugins/setoid_ring/newring.mli2
-rw-r--r--plugins/ssr/ssrbool.v16
-rw-r--r--plugins/ssr/ssrcommon.ml2
-rw-r--r--plugins/ssr/ssreflect.v6
-rw-r--r--plugins/ssr/ssrequality.ml2
-rw-r--r--plugins/ssr/ssrfun.v4
-rw-r--r--plugins/ssr/ssrfwd.ml10
-rw-r--r--plugins/ssr/ssripats.ml5
-rw-r--r--plugins/ssr/ssrparser.ml43
-rw-r--r--plugins/ssr/ssrparser.mli4
-rw-r--r--plugins/ssr/ssrvernac.ml414
-rw-r--r--plugins/ssrmatching/g_ssrmatching.ml4101
-rw-r--r--plugins/ssrmatching/g_ssrmatching.mli17
-rw-r--r--plugins/ssrmatching/ssrmatching.ml (renamed from plugins/ssrmatching/ssrmatching.ml4)113
-rw-r--r--plugins/ssrmatching/ssrmatching.mli34
-rw-r--r--plugins/ssrmatching/ssrmatching_plugin.mlpack1
-rw-r--r--plugins/syntax/n_syntax.ml81
-rw-r--r--plugins/syntax/n_syntax_plugin.mlpack1
-rw-r--r--plugins/syntax/positive_syntax.ml101
-rw-r--r--plugins/syntax/positive_syntax_plugin.mlpack1
-rw-r--r--plugins/syntax/z_syntax.ml128
-rw-r--r--pretyping/cases.ml14
-rw-r--r--pretyping/cbv.ml23
-rw-r--r--pretyping/cbv.mli2
-rw-r--r--pretyping/classops.ml96
-rw-r--r--pretyping/classops.mli20
-rw-r--r--pretyping/coercion.ml39
-rw-r--r--pretyping/constr_matching.ml4
-rw-r--r--pretyping/detyping.ml15
-rw-r--r--pretyping/evarconv.ml17
-rw-r--r--pretyping/evarsolve.ml2
-rw-r--r--pretyping/glob_ops.ml8
-rw-r--r--pretyping/heads.ml (renamed from library/heads.ml)4
-rw-r--r--pretyping/heads.mli (renamed from library/heads.mli)0
-rw-r--r--pretyping/indrec.ml11
-rw-r--r--pretyping/inductiveops.ml62
-rw-r--r--pretyping/inductiveops.mli18
-rw-r--r--pretyping/nativenorm.ml54
-rw-r--r--pretyping/patternops.ml7
-rw-r--r--pretyping/pretyping.ml23
-rw-r--r--pretyping/pretyping.mllib1
-rw-r--r--pretyping/recordops.ml34
-rw-r--r--pretyping/recordops.mli7
-rw-r--r--pretyping/reductionops.ml89
-rw-r--r--pretyping/reductionops.mli6
-rw-r--r--pretyping/retyping.ml13
-rw-r--r--pretyping/tacred.ml37
-rw-r--r--pretyping/typeclasses.ml4
-rw-r--r--pretyping/typeclasses.mli4
-rw-r--r--pretyping/typing.ml23
-rw-r--r--pretyping/unification.ml18
-rw-r--r--pretyping/vnorm.ml42
-rw-r--r--printing/ppconstr.ml4
-rw-r--r--printing/pputils.ml2
-rw-r--r--printing/prettyp.ml17
-rw-r--r--printing/prettyp.mli2
-rw-r--r--printing/printer.ml112
-rw-r--r--printing/printer.mli38
-rw-r--r--printing/printing.mllib1
-rw-r--r--printing/printmod.ml4
-rw-r--r--printing/proof_diffs.ml347
-rw-r--r--printing/proof_diffs.mli73
-rw-r--r--proofs/pfedit.mli3
-rw-r--r--proofs/proof.ml36
-rw-r--r--proofs/proof.mli3
-rw-r--r--proofs/proof_global.ml7
-rw-r--r--proofs/proof_global.mli4
-rw-r--r--shell.nix4
-rw-r--r--stm/stm.ml31
-rw-r--r--stm/stm.mli10
-rw-r--r--stm/vernac_classifier.ml17
-rw-r--r--stm/vernac_classifier.mli5
-rw-r--r--stm/workerLoop.mli16
-rw-r--r--tactics/class_tactics.ml2
-rw-r--r--tactics/elimschemes.ml2
-rw-r--r--tactics/eqschemes.ml6
-rw-r--r--tactics/equality.ml2
-rw-r--r--tactics/hints.ml164
-rw-r--r--tactics/hints.mli9
-rw-r--r--tactics/hipattern.ml4
-rw-r--r--tactics/inv.ml4
-rw-r--r--tactics/leminv.ml2
-rw-r--r--tactics/tactics.ml14
-rw-r--r--test-suite/Makefile5
-rw-r--r--test-suite/bugs/closed/2733.v15
-rw-r--r--test-suite/bugs/closed/4202.v10
-rw-r--r--test-suite/bugs/closed/5012.v17
-rw-r--r--test-suite/bugs/closed/5696.v5
-rw-r--r--test-suite/bugs/closed/5719.v9
-rw-r--r--test-suite/bugs/closed/7695.v20
-rw-r--r--test-suite/bugs/closed/7712.v4
-rw-r--r--test-suite/bugs/closed/7723.v58
-rw-r--r--test-suite/bugs/closed/7854.v10
-rw-r--r--test-suite/bugs/closed/7867.v4
-rw-r--r--test-suite/bugs/closed/7903.v4
-rw-r--r--test-suite/bugs/closed/8004.v47
-rw-r--r--test-suite/bugs/closed/8081.v4
-rw-r--r--test-suite/bugs/closed/8106.v4
-rw-r--r--test-suite/bugs/closed/8119.v46
-rw-r--r--test-suite/bugs/closed/8126.v13
-rw-r--r--test-suite/coq-makefile/timing/after/time-of-build-both.log.desired6
-rw-r--r--test-suite/coq-makefile/timing/per-file-after/A.v.timing.diff.desired18
-rw-r--r--test-suite/coq-makefile/timing/precomputed-time-tests/001-correct-diff-sorting-order/time-of-build-both.log.expected2
-rw-r--r--test-suite/coq-makefile/timing/precomputed-time-tests/002-single-file-sorting/time-of-build-pretty.log.expected2
-rwxr-xr-xtest-suite/coq-makefile/timing/run.sh4
-rw-r--r--test-suite/coqchk/include_primproj.v13
-rw-r--r--test-suite/coqdoc/links.html.out34
-rw-r--r--test-suite/coqdoc/links.tex.out34
-rwxr-xr-xtest-suite/misc/7704.sh7
-rw-r--r--test-suite/misc/aux7704.v6
-rw-r--r--test-suite/output/BadOptionValueType.out8
-rw-r--r--test-suite/output/BadOptionValueType.v4
-rw-r--r--test-suite/output/Cases.out2
-rw-r--r--test-suite/output/Cases.v3
-rw-r--r--test-suite/output/Deprecation.out3
-rw-r--r--test-suite/output/Deprecation.v6
-rw-r--r--test-suite/output/Notations3.out11
-rw-r--r--test-suite/output/Notations3.v25
-rw-r--r--test-suite/output/Notations4.out17
-rw-r--r--test-suite/output/Notations4.v68
-rw-r--r--test-suite/output/RecordMissingField.out4
-rw-r--r--test-suite/output/RecordMissingField.v8
-rw-r--r--test-suite/output/ssr_explain_match.out22
-rw-r--r--test-suite/ssr/delayed_clear_rename.v (renamed from test-suite/success/ssr_delayed_clear_rename.v)0
-rw-r--r--test-suite/ssr/rewrite_illtyped.v9
-rw-r--r--test-suite/success/BracketsWithGoalSelector.v9
-rw-r--r--test-suite/success/Hints.v30
-rw-r--r--test-suite/success/LraTest.v (renamed from test-suite/success/Fourier.v)10
-rw-r--r--test-suite/success/LtacDeprecation.v32
-rw-r--r--test-suite/success/Notations2.v28
-rw-r--r--test-suite/success/attribute-syntax.v23
-rw-r--r--test-suite/success/mutual_record.v57
-rw-r--r--test-suite/success/primitiveproj.v9
-rw-r--r--test-suite/success/uniform_inductive_parameters.v13
-rw-r--r--test-suite/success/vm_records.v40
-rw-r--r--test-suite/unit-tests/.merlin.in (renamed from test-suite/unit-tests/.merlin)0
-rw-r--r--test-suite/unit-tests/clib/inteq.ml4
-rw-r--r--test-suite/unit-tests/clib/unicode_tests.ml4
-rw-r--r--test-suite/unit-tests/printing/proof_diffs_test.ml333
-rw-r--r--test-suite/unit-tests/src/utest.ml8
-rw-r--r--test-suite/unit-tests/src/utest.mli8
-rw-r--r--theories/Bool/Bool.v7
-rw-r--r--theories/FSets/FSetAVL.v2
-rw-r--r--theories/FSets/FSetEqProperties.v4
-rw-r--r--theories/Init/Logic.v9
-rw-r--r--theories/MSets/MSetEqProperties.v4
-rw-r--r--theories/MSets/MSetGenTree.v2
-rw-r--r--theories/NArith/Ndigits.v35
-rw-r--r--theories/Numbers/BinNums.v2
-rw-r--r--theories/Numbers/DecimalString.v20
-rw-r--r--theories/Numbers/Integer/Abstract/ZBits.v6
-rw-r--r--theories/Numbers/Natural/Abstract/NBits.v6
-rw-r--r--theories/Reals/Machin.v36
-rw-r--r--theories/Reals/PSeries_reg.v29
-rw-r--r--theories/Reals/R_sqrt.v20
-rw-r--r--theories/Reals/Ranalysis5.v90
-rw-r--r--theories/Reals/Ratan.v238
-rw-r--r--theories/Reals/Rbasic_fun.v4
-rw-r--r--theories/Reals/Rderiv.v6
-rw-r--r--theories/Reals/Reals.v1
-rw-r--r--theories/Reals/Rlimit.v8
-rw-r--r--theories/Reals/Rpower.v24
-rw-r--r--theories/Reals/Rsqrt_def.v2
-rw-r--r--theories/Reals/Rtrigo.v2
-rw-r--r--theories/Reals/Rtrigo1.v40
-rw-r--r--theories/Reals/Rtrigo_calc.v1
-rw-r--r--theories/Strings/Ascii.v34
-rw-r--r--theories/Strings/BinaryString.v147
-rw-r--r--theories/Strings/HexString.v229
-rw-r--r--theories/Strings/OctalString.v179
-rw-r--r--theories/Strings/String.v34
-rw-r--r--theories/Structures/GenericMinMax.v2
-rw-r--r--theories/Vectors/VectorDef.v1
-rw-r--r--tools/CoqMakefile.in27
-rw-r--r--tools/TimeFileMaker.py37
-rw-r--r--tools/coq-font-lock.el137
-rw-r--r--tools/coq_makefile.ml38
-rw-r--r--tools/coqdoc/index.ml16
-rw-r--r--tools/coqdoc/index.mli2
-rw-r--r--tools/coqdoc/output.ml6
-rw-r--r--tools/gallina-db.el240
-rw-r--r--tools/gallina-syntax.el979
-rw-r--r--tools/gallina.el142
-rw-r--r--tools/gallina.ml63
-rw-r--r--tools/gallina_lexer.mll126
-rw-r--r--tools/inferior-coq.el324
-rwxr-xr-xtools/make-both-single-timing-files.py2
-rwxr-xr-xtools/make-both-time-files.py2
-rwxr-xr-xtools/make-one-time-file.py2
-rw-r--r--toplevel/coqargs.ml10
-rw-r--r--toplevel/coqargs.mli1
-rw-r--r--toplevel/coqloop.ml40
-rw-r--r--toplevel/coqloop.mli2
-rw-r--r--toplevel/coqtop.ml41
-rw-r--r--toplevel/g_toplevel.mlg (renamed from toplevel/g_toplevel.ml4)25
-rw-r--r--toplevel/usage.ml3
-rw-r--r--toplevel/vernac.ml6
-rw-r--r--vernac/assumptions.mli2
-rw-r--r--vernac/auto_ind_decl.ml2
-rw-r--r--vernac/class.ml19
-rw-r--r--vernac/classes.ml7
-rw-r--r--vernac/classes.mli4
-rw-r--r--vernac/comAssumption.ml2
-rw-r--r--vernac/comDefinition.ml2
-rw-r--r--vernac/comFixpoint.ml5
-rw-r--r--vernac/comFixpoint.mli4
-rw-r--r--vernac/comInductive.ml57
-rw-r--r--vernac/comInductive.mli7
-rw-r--r--vernac/comProgramFixpoint.ml4
-rw-r--r--vernac/egramcoq.ml136
-rw-r--r--vernac/egramcoq.mli3
-rw-r--r--vernac/egramml.ml9
-rw-r--r--vernac/egramml.mli4
-rw-r--r--vernac/g_proofs.ml4131
-rw-r--r--vernac/g_proofs.mlg139
-rw-r--r--vernac/g_vernac.ml41156
-rw-r--r--vernac/g_vernac.mlg1208
-rw-r--r--vernac/himsg.ml26
-rw-r--r--vernac/himsg.mli2
-rw-r--r--vernac/metasyntax.ml400
-rw-r--r--vernac/metasyntax.mli2
-rw-r--r--vernac/misctypes.ml8
-rw-r--r--vernac/obligations.ml17
-rw-r--r--vernac/ppvernac.ml61
-rw-r--r--vernac/proof_using.ml12
-rw-r--r--vernac/pvernac.ml19
-rw-r--r--vernac/pvernac.mli26
-rw-r--r--vernac/record.ml282
-rw-r--r--vernac/record.mli13
-rw-r--r--vernac/topfmt.ml124
-rw-r--r--vernac/vernacentries.ml371
-rw-r--r--vernac/vernacentries.mli34
-rw-r--r--vernac/vernacexpr.ml23
-rw-r--r--vernac/vernacinterp.ml11
-rw-r--r--vernac/vernacinterp.mli10
603 files changed, 15520 insertions, 13663 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
deleted file mode 100644
index 03aeed2eb7..0000000000
--- a/.circleci/config.yml
+++ /dev/null
@@ -1,202 +0,0 @@
-# This file used to contain configuration to also build documentation and CoqIDE,
-# run the test-suite and the validate targets,
-# including with 32-bits architecture or bleeding-edge compiler.
-
-defaults:
- params: &params
- # Following parameters are used in Coq CircleCI Job (using yaml
- # reference syntax)
- working_directory: ~/coq
- docker:
- - image: $CI_REGISTRY_IMAGE:$CACHEKEY
-
- environment: &envvars
- CACHEKEY: "bionic_coq-V2018-06-13-V1"
- CI_REGISTRY_IMAGE: registry.gitlab.com/coq/coq
-
-version: 2
-
-before_script: &before_script
- name: Setup OPAM Switch
- command: |
- echo export TERM=xterm >> ~/.profile
- source ~/.profile
- echo . ~/.profile >> $BASH_ENV
- printenv | sort
- opam switch "$COMPILER"
- opam config list
- opam list
-
-.build-template: &build-template
- <<: *params
- steps:
- - checkout
- - run: *before_script
- - run: &build-clean
- name: Clean
- command: |
- make clean # ensure that `make clean` works on a fresh clone
- - run: &build-configure
- name: Configure
- command: |
- ./configure -local -native-compiler ${NATIVE_COMP} -coqide no
- - run: &build-build
- name: Build
- command: |
- make -j ${NJOBS} byte
- make -j ${NJOBS}
- make test-suite/misc/universes/all_stdlib.v
- - persist_to_workspace:
- root: &workspace ~/
- paths:
- - coq/
-
- environment:
- <<: *envvars
- NATIVE_COMP: "yes"
-
-.ci-template: &ci-template
- <<: *params
- steps:
- - run: *before_script
- - attach_workspace: &attach_workspace
- at: *workspace
-
- - run:
- name: Test
- command: |
- dev/ci/ci-wrapper.sh ${CIRCLE_JOB}
- - persist_to_workspace:
- root: *workspace
- paths:
- - coq/
- environment: *envvars
-
-# Defines individual jobs, see the workflows section below for job orchestration
-jobs:
-
- # Build and prepare test environment
- build: *build-template
-
- bignums:
- <<: *ci-template
-
- color:
- <<: *ci-template
-
- compcert:
- <<: *ci-template
-
- coq-dpdgraph:
- <<: *ci-template
-
- coquelicot:
- <<: *ci-template
-
- cross-crypto:
- <<: *ci-template
-
- elpi:
- <<: *ci-template
-
- equations:
- <<: *ci-template
-
- geocoq:
- <<: *ci-template
-
- fcsl-pcm:
- <<: *ci-template
-
- fiat-crypto:
- <<: *ci-template
-
- fiat-parsers:
- <<: *ci-template
-
- flocq:
- <<: *ci-template
-
- math-classes:
- <<: *ci-template
-
- corn:
- <<: *ci-template
-
- formal-topology:
- <<: *ci-template
-
- hott:
- <<: *ci-template
-
- iris-lambda-rust:
- <<: *ci-template
-
- ltac2:
- <<: *ci-template
-
- math-comp:
- <<: *ci-template
-
- mtac2:
- <<: *ci-template
-
- pidetop:
- <<: *ci-template
-
- sf:
- <<: *ci-template
-
- unimath:
- <<: *ci-template
-
- vst:
- <<: *ci-template
-
-workflows:
- version: 2
-
- # Run on each push
- main:
- jobs:
- - build
-
- - bignums: &req-main
- requires:
- - build
- - color:
- requires:
- - build
- - bignums
- # - compcert: *req-main
- # - coq-dpdgraph: *req-main
- # - coquelicot: *req-main
- # - cross-crypto: *req-main
- # - elpi: *req-main
- # - equations: *req-main
- # - geocoq: *req-main
- # - fcsl-pcm: *req-main
- # - fiat-crypto: *req-main
- # - fiat-parsers: *req-main
- # - flocq: *req-main
- - math-classes:
- requires:
- - build
- - bignums
- # - mtac2: *req-main
- - corn:
- requires:
- - build
- - math-classes
- - formal-topology:
- requires:
- - build
- - corn
- # - hott: *req-main
- # - iris-lambda-rust: *req-main
- # - ltac2: *req-main
- # - math-comp: *req-main
- # - pidetop: *req-main
- # - sf: *req-main
- # - unimath: *req-main
- # - vst: *req-main
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 3a762b42a9..5be434c8b7 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -8,22 +8,14 @@
########## CI infrastructure ##########
-/dev/ci/ @ejgallego
-# Secondary maintainer @SkySkimmer
+/dev/ci/ @coq/ci-maintainers
+/.travis.yml @coq/ci-maintainers
+/.gitlab-ci.yml @coq/ci-maintainers
/dev/ci/user-overlays/*.sh @ghost
# Trick to avoid getting review requests
# each time someone adds an overlay
-/.circleci/ @SkySkimmer
-# Secondary maintainer @ejgallego
-
-/.travis.yml @ejgallego
-# Secondary maintainer @SkySkimmer
-
-/.gitlab-ci.yml @SkySkimmer
-# Secondary maintainer @ejgallego
-
/appveyor.yml @maximedenes
/dev/ci/appveyor.* @maximedenes
/dev/ci/*.bat @maximedenes
@@ -50,11 +42,7 @@
# Trick to avoid getting review requests
# each time someone modifies the dev changelog
-/doc/ @maximedenes
-# Secondary maintainer @silene @Zimmi48
-
-/doc/tools/coqrst/ @maximedenes
-# Secondary maintainer @cpitclaudel
+/doc/ @coq/doc-maintainers
/man/ @silene
# Secondary maintainer @maximedenes
@@ -137,15 +125,11 @@
/plugins/derive/ @aspiwack
# Secondary maintainer @ppedrot
-/plugins/extraction/ @letouzey
-# Secondary maintainer @maximedenes
+/plugins/extraction/ @maximedenes
/plugins/firstorder/ @PierreCorbineau
# Secondary maintainer @herbelin
-/plugins/fourier/ @herbelin
-# Secondary maintainer @gares
-
/plugins/funind/ @forestjulien
# Secondary maintainer @Matafou
@@ -159,10 +143,6 @@
/plugins/nsatz/ @thery
# Secondary maintainer @ppedrot
-/plugins/omega/ @letouzey
-
-/plugins/romega/ @letouzey
-
/plugins/setoid_ring/ @amahboubi
# Secondary maintainer @bgregoir
@@ -186,6 +166,10 @@
/pretyping/ @mattam82
# Secondary maintainer @gares
+/pretyping/vnorm.* @maximedenes
+/pretyping/nativenorm.* @maximedenes
+# Secondary maintainer @ppedrot
+
########## Pretty printer ##########
/printing/ @herbelin
@@ -215,44 +199,34 @@
########## Standard library ##########
-/theories/Arith/ @letouzey
-# Secondary maintainer @herbelin
+/theories/Arith/ @herbelin
-/theories/Bool/ @letouzey
-# Secondary maintainer @herbelin
+/theories/Bool/ @herbelin
/theories/Classes/ @mattam82
# Secondary maintainer @herbelin
-/theories/FSets/ @letouzey
-# Secondary maintainer @herbelin
+/theories/FSets/ @herbelin
-/theories/Init/ @letouzey
-# Secondary maintainer @ppedrot
+/theories/Init/ @ppedrot
-/theories/Lists/ @letouzey
-# Secondary maintainer @ppedrot
+/theories/Lists/ @ppedrot
/theories/Logic/ @herbelin
# Secondary maintainer @ppedrot
-/theories/MSets/ @letouzey
-# Secondary maintainer @herbelin
+/theories/MSets/ @herbelin
-/theories/NArith/ @letouzey
-# Secondary maintainer @herbelin
+/theories/NArith/ @herbelin
-/theories/Numbers/ @letouzey
-# Secondary maintainer @herbelin
+/theories/Numbers/ @herbelin
-/theories/PArith/ @letouzey
-# Secondary maintainer @herbelin
+/theories/PArith/ @herbelin
/theories/Program/ @mattam82
# Secondary maintainer @herbelin
-/theories/QArith/ @letouzey
-# Secondary maintainer @herbelin
+/theories/QArith/ @herbelin
/theories/Reals/ @silene
# Secondary maintainer @ppedrot
@@ -263,26 +237,19 @@
/theories/Setoids/ @mattam82
# Secondary maintainer @ppedrot
-/theories/Sets/ @letouzey
-# Secondary maintainer @herbelin
+/theories/Sets/ @herbelin
-/theories/Sorting/ @letouzey
-# Secondary maintainer @herbelin
+/theories/Sorting/ @herbelin
-/theories/Strings/ @letouzey
-# Secondary maintainer @herbelin
+/theories/Strings/ @herbelin
-/theories/Structures/ @letouzey
-# Secondary maintainer @herbelin
+/theories/Structures/ @herbelin
-/theories/Unicode/ @letouzey
-# Secondary maintainer @herbelin
+/theories/Unicode/ @herbelin
-/theories/Wellfounded/ @letouzey
-# Secondary maintainer @mattam82
+/theories/Wellfounded/ @mattam82
-/theories/ZArith/ @letouzey
-# Secondary maintainer @herbelin
+/theories/ZArith/ @herbelin
/theories/Compat/ @JasonGross
# Secondary maintainer @Zimmi48
@@ -327,14 +294,11 @@
########## Build system ##########
-/Makefile* @letouzey
-# Secondary maintainer @gares
+/Makefile* @gares
-/configure* @letouzey
-# Secondary maintainer @ejgallego
+/configure* @ejgallego
-/META.coq @ejgallego
-# Secondary maintainer @letouzey
+/META.coq.in @ejgallego
/dev/build/windows @MSoegtropIMC
# Secondary maintainer @maximedenes
diff --git a/.gitignore b/.gitignore
index 6adbc9fb28..0e41d6a778 100644
--- a/.gitignore
+++ b/.gitignore
@@ -115,17 +115,22 @@ dev/ocamldoc/*.css
# .mll files
+coqpp/coqpp_lex.ml
dev/ocamlweb-doc/lex.ml
ide/coq_lex.ml
ide/config_lexer.ml
ide/utf8_convert.ml
-tools/gallina_lexer.ml
tools/coqwc.ml
tools/coqdep_lexer.ml
tools/ocamllibdep.ml
tools/coqdoc/cpretty.ml
ide/protocol/xml_lexer.ml
+# .mly files
+
+coqpp/coqpp_parse.ml
+coqpp/coqpp_parse.mli
+
# .ml4 / .mlp files
g_*.ml
@@ -174,3 +179,7 @@ test-suite/.nra.cache
plugins/ssr/ssrparser.ml
plugins/ssr/ssrvernac.ml
+
+# ocaml dev files
+.merlin
+META.coq
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 971a281ea1..f42d13e4c1 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -9,7 +9,7 @@ stages:
variables:
# Format: $IMAGE-V$DATE [Cache is not used as of today but kept here
# for reference]
- CACHEKEY: "bionic_coq-V2018-06-13-V1"
+ CACHEKEY: "bionic_coq-V2018-08-27-V2"
IMAGE: "$CI_REGISTRY_IMAGE:$CACHEKEY"
# By default, jobs run in the base switch; override to select another switch
OPAM_SWITCH: "base"
@@ -45,6 +45,9 @@ before_script:
- opam list
- opam config list
+after_script:
+ - echo "The build completed normally (not a runner failure)."
+
################ GITLAB CACHING ######################
# - use artifacts between jobs #
######################################################
@@ -52,7 +55,6 @@ before_script:
# TODO figure out how to build doc for installed Coq
.build-template: &build-template
stage: build
- retry: 1
artifacts:
name: "$CI_JOB_NAME"
paths:
@@ -69,7 +71,7 @@ before_script:
- echo 'end:coq.clean'
- echo 'start:coq.config'
- - ./configure -prefix "$(pwd)/_install_ci" ${COQ_EXTRA_CONF}"$COQ_EXTRA_CONF_QUOTE"
+ - ./configure -warn-error yes -prefix "$(pwd)/_install_ci" ${COQ_EXTRA_CONF}"$COQ_EXTRA_CONF_QUOTE"
- echo 'end:coq.config'
- echo 'start:coq.build'
@@ -86,28 +88,6 @@ before_script:
- set +e
-.warnings-template: &warnings-template
- # keep warnings in test stage so we can test things even when warnings occur
- stage: test
- script:
- - set -e
-
- - echo 'start:coq.clean'
- - make clean # ensure that `make clean` works on a fresh clone
- - echo 'end:coq.clean'
-
- - echo 'start:coq.config'
- - ./configure -local ${COQ_EXTRA_CONF}
- - echo 'end:coq.config'
-
- - echo 'start:coq.build'
- - make -j "$NJOBS" coqocaml
- - echo 'end:coq:build'
-
- - set +e
- variables: &warnings-variables
- COQ_EXTRA_CONF: "-native-compiler yes -coqide byte -byte-only -warn-error yes"
-
# every non build job must set dependencies otherwise all build
# artifacts are used together and we may get some random Coq. To that
# purpose, we add a spurious dependency `not-a-real-job` that must be
@@ -220,7 +200,7 @@ build:edge+flambda:
variables:
OPAM_SWITCH: edge
OPAM_VARIANT: "+flambda"
- COQ_EXTRA_CONF: "-native-compiler no -coqide opt -flambda-opts "
+ COQ_EXTRA_CONF: "-native-compiler yes -coqide opt -flambda-opts "
COQ_EXTRA_CONF_QUOTE: "-O3 -unbox-closures"
windows64:
@@ -232,20 +212,38 @@ windows32:
<<: *windows-template
variables:
ARCH: "32"
+ except:
+ - /^pr-.*$/
-warnings:base:
- <<: *warnings-template
-
-# warnings:32bit:
-# <<: *warnings-template
-# variables:
-# <<: *warnings-variables
-warnings:edge:
- <<: *warnings-template
+pkg:nix:
+ image: nixorg/nix:latest # Minimal NixOS image which doesn't even contain git
+ stage: test
variables:
- <<: *warnings-variables
- OPAM_SWITCH: edge
+ # By default we use coq.cachix.org as an extra substituter but this can be overridden
+ EXTRA_SUBSTITUTERS: https://coq.cachix.org
+ EXTRA_PUBLIC_KEYS: coq.cachix.org-1:Jgt0DwGAUo+wpxCM52k2V+E0hLoOzFPzvg94F65agtI=
+ # The following variables should not be overridden
+ GIT_STRATEGY: none
+ CACHIX_PUBLIC_KEY: cachix.cachix.org-1:eWNHQldwUO7G2VkjpnjDbWwy4KQ/HNxht7H4SSoMckM=
+ NIXOS_PUBLIC_KEY: cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
+
+ dependencies: [] # We don't need to download build artifacts
+ before_script: [] # We don't want to use the shared 'before_script'
+ script:
+ # Use current worktree as tmpdir to allow exporting artifacts in case of failure
+ - export TMPDIR=$PWD
+ # Install Cachix as documented at https://github.com/cachix/cachix
+ - nix-env -if https://github.com/cachix/cachix/tarball/master --substituters https://cachix.cachix.org --trusted-public-keys "$CACHIX_PUBLIC_KEY"
+ # We build an expression rather than a direct URL to not be dependent on
+ # the URL location; we are forced to put the public key of cache.nixos.org
+ # because there is no --extra-trusted-public-key option.
+ - nix-build -E "import (fetchTarball $CI_PROJECT_URL/-/archive/$CI_COMMIT_SHA.tar.gz) {}" -K --extra-substituters "$EXTRA_SUBSTITUTERS" --trusted-public-keys "$NIXOS_PUBLIC_KEY $EXTRA_PUBLIC_KEYS" | if [ ! -z "$CACHIX_SIGNING_KEY" ]; then cachix push coq; fi
+ artifacts:
+ name: "$CI_JOB_NAME.logs"
+ when: on_failure
+ paths:
+ - nix-build-coq.drv-0/*/test-suite/logs
documentation:
<<: *doc-template
@@ -306,6 +304,9 @@ validate:edge+flambda:
OPAM_SWITCH: edge
OPAM_VARIANT: "+flambda"
+ci-bedrock2:
+ <<: *ci-template
+
ci-bignums:
<<: *ci-template
@@ -336,6 +337,9 @@ ci-fcsl-pcm:
ci-fiat-crypto:
<<: *ci-template-flambda
+ci-fiat-crypto-legacy:
+ <<: *ci-template-flambda
+
ci-fiat-parsers:
<<: *ci-template
diff --git a/.merlin b/.merlin.in
index 404a7e7935..404a7e7935 100644
--- a/.merlin
+++ b/.merlin.in
diff --git a/.travis.yml b/.travis.yml
index 6273346906..dd28410bec 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -39,13 +39,14 @@ env:
- NJOBS=2
# system is == 4.02.3
- COMPILER="system"
- - COMPILER_BE="4.06.1"
+ - COMPILER_BE="4.07.0"
+ - DUNE_VER=".1.1.1"
- CAMLP5_VER=".6.14"
- - CAMLP5_VER_BE=".7.05"
+ - CAMLP5_VER_BE=".7.06"
- FINDLIB_VER=".1.4.1"
- FINDLIB_VER_BE=".1.8.0"
- - LABLGTK="lablgtk.2.18.3 lablgtk-extras.1.6"
- - LABLGTK_BE="lablgtk.2.18.6 lablgtk-extras.1.6"
+ - LABLGTK="lablgtk.2.18.3 conf-gtksourceview.2"
+ - LABLGTK_BE="lablgtk.2.18.6 conf-gtksourceview.2"
- NATIVE_COMP="yes"
- COQ_DEST="-local"
- MAIN_TARGET="world"
@@ -64,16 +65,7 @@ matrix:
- TEST_TARGET="validate" COMPILER="4.02.3+32bit" TW="travis_wait"
- if: NOT (type = pull_request)
env:
- - TEST_TARGET="validate" COMPILER="${COMPILER_BE}+flambda" CAMLP5_VER="${CAMLP5_VER_BE}" NATIVE_COMP="no" EXTRA_CONF="-flambda-opts -O3" FINDLIB_VER="${FINDLIB_VER_BE}"
- - if: NOT (type = pull_request)
- env:
- - TEST_TARGET="ci-bignums"
- - if: NOT (type = pull_request)
- env:
- - TEST_TARGET="ci-color"
- - if: NOT (type = pull_request)
- env:
- - TEST_TARGET="ci-compcert" EXTRA_OPAM="menhir"
+ - TEST_TARGET="validate" COMPILER="${COMPILER_BE}+flambda" CAMLP5_VER="${CAMLP5_VER_BE}" EXTRA_CONF="-flambda-opts -O3" FINDLIB_VER="${FINDLIB_VER_BE}"
- if: NOT (type = pull_request)
env:
- TEST_TARGET="ci-coq-dpdgraph" EXTRA_OPAM="ocamlgraph"
@@ -85,12 +77,6 @@ matrix:
- TEST_TARGET="ci-equations"
- if: NOT (type = pull_request)
env:
- - TEST_TARGET="ci-fcsl-pcm"
- - 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:
@@ -100,16 +86,10 @@ matrix:
- TEST_TARGET="ci-ltac2"
- if: NOT (type = pull_request)
env:
- - TEST_TARGET="ci-math-classes"
- - if: NOT (type = pull_request)
- env:
- TEST_TARGET="ci-mtac2"
- if: NOT (type = pull_request)
env:
- TEST_TARGET="ci-pidetop"
- - if: NOT (type = pull_request)
- env:
- - TEST_TARGET="ci-sf"
- env:
- TEST_TARGET="lint"
@@ -174,7 +154,6 @@ matrix:
- COMPILER="${COMPILER_BE}+flambda"
- FINDLIB_VER="${FINDLIB_VER_BE}"
- CAMLP5_VER="${CAMLP5_VER_BE}"
- - NATIVE_COMP="no"
- EXTRA_CONF="-coqide opt -with-doc yes -flambda-opts -O3"
- EXTRA_OPAM="${LABLGTK_BE} ounit"
before_install: *sphinx-install
@@ -184,41 +163,12 @@ matrix:
- avsm
packages: *extra-packages
- # Ocaml warnings with two compilers
- - if: NOT (type = pull_request)
- env:
- - MAIN_TARGET="coqocaml"
- - EXTRA_CONF="-byte-only -coqide byte -warn-error yes"
- - EXTRA_OPAM="${LABLGTK}"
- addons:
- apt:
- sources:
- - avsm
- packages: &coqide-packages
- - opam
- - aspcud
- - libgtk2.0-dev
- - libgtksourceview2.0-dev
-
- - if: NOT (type = pull_request)
+ - os: osx
env:
- - MAIN_TARGET="coqocaml"
+ - TEST_TARGET="test-suite"
- COMPILER="${COMPILER_BE}"
- FINDLIB_VER="${FINDLIB_VER_BE}"
- CAMLP5_VER="${CAMLP5_VER_BE}"
- - EXTRA_CONF="-byte-only -coqide byte -warn-error yes"
- - EXTRA_OPAM="${LABLGTK_BE}"
- addons:
- apt:
- sources:
- - avsm
- packages: *coqide-packages
-
- - os: osx
- env:
- - TEST_TARGET="test-suite"
- - COMPILER="4.02.3"
- - CAMLP5_VER=".6.17"
- NATIVE_COMP="no"
- COQ_DEST="-local"
- EXTRA_OPAM="ounit"
@@ -232,12 +182,13 @@ matrix:
osx_image: xcode7.3
env:
- TEST_TARGET=""
- - COMPILER="4.02.3"
- - CAMLP5_VER=".6.17"
+ - COMPILER="${COMPILER_BE}"
+ - FINDLIB_VER="${FINDLIB_VER_BE}"
+ - CAMLP5_VER="${CAMLP5_VER_BE}"
- NATIVE_COMP="no"
- COQ_DEST="-prefix ${PWD}/_install"
- EXTRA_CONF="-coqide opt -warn-error yes"
- - EXTRA_OPAM="${LABLGTK}"
+ - EXTRA_OPAM="${LABLGTK_BE}"
before_install:
- brew update
- brew unlink python
@@ -262,12 +213,12 @@ before_install:
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
+- if [ "${TRAVIS_OS_NAME}" == "linux" ]; then sudo apt-get install -y opam aspcud gcc-multilib --allow-unauthenticated; fi
- opam init -j ${NJOBS} --compiler=${COMPILER} -n -y
- opam switch "$COMPILER" && opam update
- eval $(opam config env)
- opam config list
-- opam install -j ${NJOBS} -y num ocamlfind${FINDLIB_VER} jbuilder camlp5${CAMLP5_VER} ${EXTRA_OPAM}
+- opam install -j ${NJOBS} -y num ocamlfind${FINDLIB_VER} dune${DUNE_VER} camlp5${CAMLP5_VER} ${EXTRA_OPAM}
- opam list
script:
@@ -278,7 +229,7 @@ script:
- echo -en 'travis_fold:end:coq.clean\\r'
- echo 'Configuring Coq...' && echo -en 'travis_fold:start:coq.config\\r'
-- ./configure ${COQ_DEST} -native-compiler ${NATIVE_COMP} ${EXTRA_CONF}
+- ./configure ${COQ_DEST} -warn-error yes -native-compiler ${NATIVE_COMP} ${EXTRA_CONF}
- echo -en 'travis_fold:end:coq.config\\r'
- echo 'Building Coq...' && echo -en 'travis_fold:start:coq.build\\r'
diff --git a/CHANGES b/CHANGES
index 6ad2cc5483..a42c44c09b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,15 @@
Changes from 8.8.2 to 8.9+beta1
===============================
+Kernel
+
+- Mutually defined records are now supported.
+
+Notations
+
+- New support for autonomous grammars of terms, called "custom
+ entries" (see chapter "Syntax extensions" of the reference manual).
+
Tactics
- Added toplevel goal selector ! which expects a single focused goal.
@@ -9,7 +18,7 @@ Tactics
- The undocumented "nameless" forms `fix N`, `cofix` that were
deprecated in 8.8 have been removed from LTAC's syntax; please use
- `fix ident N/cofix ident` to explicitely name the (co)fixpoint
+ `fix ident N/cofix ident` to explicitly name the (co)fixpoint
hypothesis to be introduced.
- Introduction tactics "intro"/"intros" on a goal which is an
@@ -34,6 +43,28 @@ Tactics
without adding new ones. Preexisting tactic `constr_eq_nounivs` can
still be used if you really want to ignore universe constraints.
+- Tactics and tactic notations now understand the `deprecated` attribute.
+- The `fourier` tactic has been removed. Please now use `lra` instead. You
+ may need to add `Require Import Lra` to your developments. For compatibility,
+ we now define `fourier` as a deprecated alias of `lra`.
+
+Focusing
+
+- Focusing bracket `{` now supports named goal selectors,
+ e.g. `[x]: {` will focus on a goal (existential variable) named `x`.
+ As usual, unfocus with `}` once the sub-goal is fully solved.
+
+Standard Library
+
+- Added `Ascii.eqb` and `String.eqb` and the `=?` notation for them,
+ and proved some lemmas about them. Note that this might cause
+ incompatibilities if you have, e.g., string_scope and Z_scope both
+ open with string_scope on top, and expect `=?` to refer to `Z.eqb`.
+ Solution: wrap `_ =? _` in `(_ =? _)%Z` (or whichever scope you
+ want).
+
+- Added `Ndigits.N2Bv_sized`, and proved some lemmas about it.
+
Tools
- Coq_makefile lets one override or extend the following variables from
@@ -41,6 +72,17 @@ Tools
COQFLAGS is now entirely separate from COQLIBS, so in custom Makefiles
$(COQFLAGS) should be replaced by $(COQFLAGS) $(COQLIBS).
+- Removed the gallina utility (extracts specification from Coq vernacular files).
+ If you would like to maintain this tool externally, please contact us.
+
+- Removed the Emacs modes distributed with Coq. You are advised to
+ use Proof-General <https://proofgeneral.github.io/> (and optionally
+ Company-Coq <https://github.com/cpitclaudel/company-coq>) instead.
+ If your use case is not covered by these alternative Emacs modes,
+ please open an issue. We can help set up external maintenance as part
+ of Proof-General, or independently as part of coq-community.
+
+
Vernacular Commands
- Removed deprecated commands Arguments Scope and Implicit Arguments
@@ -48,6 +90,18 @@ Vernacular Commands
- Nested proofs may be enabled through the option `Nested Proofs Allowed`.
By default, they are disabled and produce an error. The deprecation
warning which used to occur when using nested proofs has been removed.
+- Added option Uniform Inductive Parameters which abstracts over parameters
+ before typechecking constructors, allowing to write for example
+ `Inductive list (A : Type) := nil : list | cons : A -> list -> list.`
+- New Set Hint Variables/Constants Opaque/Transparent commands for setting
+ globally the opacity flag of variables and constants in hint databases,
+ overwritting the opacity set of the hint database.
+- Added generic syntax for “attributes”, as in:
+ `#[local] Lemma foo : bar.`
+- The `Set SsrHave NoTCResolution` command no longer has special global
+ scope. If you want the previous behavior, use `Global Set SsrHave
+ NoTCResolution`.
+- Multiple sections with the same name are allowed.
Coq binaries and process model
@@ -75,25 +129,68 @@ SSReflect
In particular rule 3 lets one write {x}/v even if v uses the variable x:
indeed the view is executed before the renaming.
-- An empty clear switch is now accepted in intro patterns before a
+- An empty clear switch is now accepted in intro patterns before a
view application whenever the view is a variable.
One can now write {}/v to mean {v}/v. Remark that {}/x is very similar
to the idiom {}e for the rewrite tactic (the equation e is used for
rewriting and then discarded).
+Standard Library
+
+- There are now conversions between [string] and [positive], [Z],
+ [nat], and [N] in binary, octal, and hex.
+
+Display diffs between proof steps
+
+- coqtop and coqide can now highlight the differences between proof steps
+ in color. This can be enabled from the command line or the
+ `Set Diffs "on"|"off"|"removed"` command. Please see the documentation for
+ details. Showing diffs in Proof General requires small changes to PG
+ (under discussion).
+
+Notations
+
+- Added `++` infix for `VectorDef.append`.
+ Note that this might cause incompatibilities if you have, e.g., list_scope
+ and vector_scope both open with vector_scope on top, and expect `++` to
+ refer to `app`.
+ Solution: wrap `_ ++ _` in `(_ ++ _)%list` (or whichever scope you want).
+
+Changes from 8.8.1 to 8.8.2
+===========================
+
+Tools
+
+- The coq-makefile targets `print-pretty-timed`, `print-pretty-timed-diff`,
+ and `print-pretty-single-time-diff` now correctly label the "before" and
+ "after" columns, rather than swapping them.
+
Changes from 8.8.0 to 8.8.1
===========================
Kernel
- Fix a critical bug with cofixpoints and vm_compute/native_compute (#7333).
+- Fix a critical bug with modules and algebraic universes (#7695)
- Fix a critical bug with inlining of polymorphic constants (#7615).
+- Fix a critical bug with universe polymorphism and vm_compute (#7723). Was
+ present since 8.5.
Notations
- Fixed unexpected collision between only-parsing and only-printing
notations (issue #7462).
+Windows installer
+
+- The Windows installer now includes external packages Ltac2 and Equations
+ (it included the Bignums package since 8.8+beta1).
+
+Many other bug fixes, documentation improvements (including fixes of
+regressions due to the Sphinx migration), and user message improvements
+(for details, see the 8.8.1 milestone at
+https://github.com/coq/coq/milestone/13?closed=1).
+
Changes from 8.8+beta1 to 8.8.0
===============================
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 2dffd2019c..de7fb9183c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -20,6 +20,9 @@ If you want to minimize your bug (or help minimize someone else's) for more extr
## Pull requests
+**Beginner's guide to hacking Coq: [`dev/doc/README.md`](dev/doc/README.md)** \
+**Development information and tools: [`dev/README.md`](dev/README.md)**
+
If you want to contribute a bug fix or feature yourself, pull requests on the [GitHub repository](https://github.com/coq/coq) are the way to contribute directly to the Coq implementation. We recommend you create a fork of the repository on GitHub and push your changes to a new "topic branch" in that fork. From there you can follow the [GitHub pull request documentation](https://help.github.com/articles/about-pull-requests/) to get your changes reviewed and pulled into the Coq source repository.
Documentation for getting started with the Coq sources is located in various
@@ -47,15 +50,28 @@ information on CI tests, including how to run them on your private branches.
If your pull request fixes a bug, please consider adding a regression test as
well. See [`test-suite/README.md`](test-suite/README.md) for how to do so.
+If your pull request fixes a critical bug (a bug allowing a proof of `False`),
+please add an entry to [`dev/doc/critical-bugs`](/dev/doc/critical-bugs).
+
Don't be alarmed if the pull request process takes some time. It can take a few days to get feedback, approval on the final changes, and then a merge. Coq doesn't release new versions very frequently so it can take a few months for your change to land in a released version. That said, you can start using the latest Coq `master` branch to take advantage of all the new features, improvements, and fixes.
Whitespace discipline (do not indent using tabs, no trailing spaces, text files end with newlines) is checked by Travis (using `git diff --check`). We ship a [`dev/tools/pre-commit`](/dev/tools/pre-commit) git hook which fixes these errors at commit time. `configure` automatically sets you up to use it, unless you already have a hook at `.git/hooks/pre-commit`.
Here are a few tags Coq developers may add to your PR and what they mean. In general feedback and requests for you as the pull request author will be in the comments and tags are only used to organize pull requests.
-- [needs: rebase](https://github.com/coq/coq/pulls?utf8=%E2%9C%93&q=is%3Aopen%20is%3Apr%20label%3A%22needs%3A%20rebase%22) indicates the PR should be rebased on top of the latest `master` branch. See the [GitHub documentation](https://help.github.com/articles/about-git-rebase/) for a brief introduction to using `git rebase`.
-- [needs: fixing](https://github.com/coq/coq/pulls?q=is%3Aopen+is%3Apr+label%3A%22needs%3A+fixing%22) indicates the PR needs a fix, as discussed in the comments.
-- [needs: benchmarking](https://github.com/coq/coq/pulls?q=is%3Aopen+is%3Apr+label%3A%22needs%3A+benchmarking%22) and [needs: testing](https://github.com/coq/coq/pulls?q=is%3Aopen+is%3Apr+label%3A%22needs%3A+testing%22) indicate the PR needs testing beyond what the test suite can handle. For example, performance benchmarking is currently performed with a different infrastructure. Unless some followup is specifically requested you aren't expected to do this additional testing.
+- [needs: rebase][rebase-label] indicates the PR should be rebased on top of
+ the latest base branch (usually `master`). See the
+ [GitHub documentation](https://help.github.com/articles/about-git-rebase/)
+ for a brief introduction to using `git rebase`.
+ This label will be automatically added if you open or synchronize your PR and
+ it is not up-to-date with the base branch. So please, do not forget to rebase
+ your branch every time you update it.
+- [needs: fixing][fixing-label] indicates the PR needs a fix, as discussed in the comments.
+- [needs: benchmarking][benchmarking-label] and [needs: testing][testing-label]
+ indicate the PR needs testing beyond what the test suite can handle.
+ For example, performance benchmarking is currently performed with a different
+ infrastructure ([documented in the wiki][jenkins-doc]). Unless some followup
+ is specifically requested you aren't expected to do this additional testing.
To learn more about the merging process, you can read the
[merging documentation for Coq maintainers](dev/doc/MERGING.md).
@@ -95,3 +111,10 @@ External plugins / libraries contribute to create a successful ecosystem around
Ask and answer questions on [Stack Exchange](https://stackexchange.com/filters/299857/questions-tagged-coq-on-stackexchange-sites) which has a helpful community of Coq users.
Hang out on the Coq IRC channel, `irc://irc.freenode.net/#coq`, and help answer questions.
+
+[rebase-label]: https://github.com/coq/coq/pulls?utf8=%E2%9C%93&q=is%3Aopen%20is%3Apr%20label%3A%22needs%3A%20rebase%22
+[fixing-label]: https://github.com/coq/coq/pulls?q=is%3Aopen+is%3Apr+label%3A%22needs%3A+fixing%22
+[benchmarking-label]: https://github.com/coq/coq/pulls?q=is%3Aopen+is%3Apr+label%3A%22needs%3A+benchmarking%22
+[testing-label]: https://github.com/coq/coq/pulls?q=is%3Aopen+is%3Apr+label%3A%22needs%3A+testing%22
+
+[jenkins-doc]: https://github.com/coq/coq/wiki/Jenkins-(automated-benchmarking)
diff --git a/CREDITS b/CREDITS
index f59bfca868..9c3a93da87 100644
--- a/CREDITS
+++ b/CREDITS
@@ -37,8 +37,6 @@ plugins/extraction
developed by Pierre Letouzey (LRI, 2000-2004, PPS, 2005-now)
plugins/firstorder
developed by Pierre Corbineau (LRI, 2003-2008)
-plugins/fourier
- developed by Loïc Pottier (INRIA-Lemme, 2001)
plugins/funind
developed by Pierre Courtieu (INRIA-Lemme, 2003-2004, CNAM, 2006-now),
Julien Forest (INRIA-Everest, 2006, CNAM, 2007-2008, ENSIIE, 2008-now)
diff --git a/INSTALL b/INSTALL
index 984b8e2908..6e7903a665 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,6 +1,6 @@
- INSTALLATION PROCEDURES FOR THE COQ V8.8 SYSTEM
- -----------------------------------------------
+ INSTALLATION PROCEDURE
+ ----------------------
WHAT DO YOU NEED ?
@@ -27,10 +27,14 @@ WHAT DO YOU NEED ?
port install coq
- To compile Coq V8.8 yourself, you need:
+ To compile Coq yourself, you need:
- - OCaml version 4.02.3 or later
+ - OCaml (version >= 4.02.3)
(available at https://ocaml.org/)
+ (This version of Coq has been tested up to OCaml 4.07.0)
+
+ - The Num package, which used to be part of the OCaml standard library,
+ if you are using an OCaml version >= 4.06.0
- Findlib (version >= 1.4.1)
(available at http://projects.camlcity.org/projects/findlib.html)
@@ -42,26 +46,30 @@ WHAT DO YOU NEED ?
- a C compiler
- - for Coqide, the Lablgtk development files, and the GTK libraries
- including gtksourceview, see INSTALL.ide for more details
+ - for CoqIDE, the lablgtk development files (version >= 2.18.3),
+ and the GTK 2.x libraries including gtksourceview2.
- Note that camlp5 and lablgtk should be properly registered with
+ Note that num, camlp5 and lablgtk should be properly registered with
findlib/ocamlfind as Coq's makefile will use it to locate the
libraries during the build.
- Opam (https://opam.ocaml.org/) is recommended to install ocaml and
+ Opam (https://opam.ocaml.org/) is recommended to install OCaml and
the corresponding packages.
- $ opam install ocamlfind camlp5 lablgtk-extras
+ $ opam install num ocamlfind camlp5 lablgtk conf-gtksourceview
should get you a reasonable OCaml environment to compile Coq.
+ Nix users can also get all the required dependencies by running:
+
+ $ nix-shell
+
Advanced users may want to experiment with the OCaml Flambda
compiler as way to improve the performance of Coq. In order to
profit from Flambda, a special build of the OCaml compiler that has
the Flambda optimizer enabled must be installed. For OPAM users,
this amounts to installing a compiler switch ending in `+flambda`,
- such as `4.06.1+flambda`. For other users, YMMV. Once `ocamlopt
+ such as `4.07.0+flambda`. For other users, YMMV. Once `ocamlopt
-config` reports that Flambda is available, some further
optimization options can be used; see the entry about -flambda-opts
below for more details.
@@ -76,7 +84,7 @@ QUICK INSTALLATION PROCEDURE.
INSTALLATION PROCEDURE IN DETAILS (NORMAL USERS).
=================================================
-1- Check that you have the Objective Caml compiler installed on your
+1- Check that you have the OCaml compiler installed on your
computer and that "ocamlc" (or, better, its native code version
"ocamlc.opt") lies in a directory which is present in your $PATH
environment variable. At the time of writing this sentence, all
@@ -183,11 +191,6 @@ INSTALLATION PROCEDURE IN DETAILS (NORMAL USERS).
make install
Of course, you may need superuser rights to do that.
- To use the Coq emacs mode you also need to put the following lines
- in you .emacs file:
-
- (setq auto-mode-alist (cons '("\\.v$" . coq-mode) auto-mode-alist))
- (autoload 'coq-mode "gallina" "Major mode for editing Coq vernacular." t)
7- Optionally, you could build the bytecode version of Coq via:
@@ -258,8 +261,6 @@ THE AVAILABLE COMMANDS.
directory, or read online on http://coq.inria.fr/doc/)
and in the corresponding manual pages.
- There is also a tutorial and a FAQ; see http://coq.inria.fr/getting-started
-
COMPILING FOR DIFFERENT ARCHITECTURES.
======================================
diff --git a/INSTALL.doc b/INSTALL.doc
deleted file mode 100644
index 13e6440d01..0000000000
--- a/INSTALL.doc
+++ /dev/null
@@ -1,91 +0,0 @@
- The Coq documentation
- =====================
-
-The Coq documentation includes
-
-- A Reference Manual
-- A document presenting the Coq standard library
-
-The reference manual is written is reStructuredText and compiled
-using Sphinx (see `doc/sphinx/README.rst`) to learn more.
-
-The documentation for the standard library is generated from
-the `.v` source files using coqdoc.
-
-Prerequisite
-------------
-
-To produce all the documents, the following tools are needed:
-
- - latex (latex2e)
- - pdflatex
- - dvips
- - makeindex
- - Python 3
- - Sphinx 1.6.5 (http://www.sphinx-doc.org/en/stable/)
- - sphinx_rtd_theme
- - pexpect
- - beautifulsoup4
- - Antlr4 runtime for Python 3
-
-
-Under recent Debian based operating systems (Debian 10 "Buster",
-Ubuntu 18.04, ...) a working set of packages for compiling the
-documentation for Coq is:
-
- texlive-latex-extra texlive-fonts-recommended python3-sphinx
- python3-pexpect python3-sphinx-rtd-theme python3-bs4
- python3-sphinxcontrib.bibtex python3-pip
-
-Then, install the Python3 Antlr4 package:
-
- pip3 install antlr4-python3-runtime
-
-Nix users should get the correct development environment to build the
-HTML documentation from Coq's `default.nix`. [Note Nix setup doesn't
-include the LaTeX packages needed to build the full documentation.]
-
-If you are in an older/different distribution you can install the
-Python packages required to build the user manual using python3-pip:
-
- pip3 install sphinx sphinx_rtd_theme beautifulsoup4 antlr4-python3-runtime pexpect sphinxcontrib-bibtex
-
-Compilation
------------
-
-To produce all documentation about Coq, just run:
-
- ./configure (if you hadn't already)
- make doc
-
-
-Alternatively, you can use some specific targets:
-
- make doc-ps
- to produce all PostScript documents
-
- make doc-pdf
- to produce all PDF documents
-
- make doc-html
- to produce all html documents
-
- make sphinx
- to produce the HTML version of the reference manual
-
- make stdlib
- to produce all formats of the Coq standard library
-
-
-Also note the "-with-doc yes" option of ./configure to enable the
-build of the documentation as part of the default make target.
-
-
-Installation
-------------
-
-To install all produced documents, do:
-
- make DOCDIR=/some/directory/for/documentation install-doc
-
-DOCDIR defaults to /usr/share/doc/coq
diff --git a/INSTALL.ide b/INSTALL.ide
deleted file mode 100644
index c4da84048a..0000000000
--- a/INSTALL.ide
+++ /dev/null
@@ -1,123 +0,0 @@
- CoqIde Installation procedure
-
-CoqIde is a graphical interface to perform interactive proofs.
-You should be able to do everything you do in coqtop inside CoqIde
-excepted dropping to the ML toplevel.
-
-
-DISTRIBUTION PACKAGES
-
-Your POSIX operating system may already contain precompiled packages
-for Coq, including CoqIde, or a ready-to-compile... If the version
-provided there suits you, follow the usual procedure for your
-operating system.
-
-E.g., on Debian GNU/Linux (or Debian GNU/k*BSD or ...), do:
- aptitude install coqide
-On Gentoo GNU/Linux, do:
- USE=ide emerge sci-mathematics/coq
-
-Else, read the rest of this document to compile your own CoqIde.
-
-
-COMPILATION REQUIREMENTS
-
-- OCaml >= 4.02.3 with native threads support.
-- make world must succeed.
-- The graphical toolkit GTK+ 2.x. See http://www.gtk.org.
- The official supported version is at least 2.24.x.
- You may still compile CoqIde with older versions and use all features.
- Run
-
- pkg-config --modversion gtk+-2.0
-
- to check your version.
- Do not forget to install the development headers packages.
-
- On Debian, installing lablgtk2 (see below) will automatically
- install GTK+. (But "aptitude install libgtk2.0-dev" will
- 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.18.3.
-
- Your distribution may contain precompiled packages. For example, for
- Debian, run
-
- aptitude install liblablgtksourceview2-ocaml-dev
-
- for Mandriva, run
-
- urpmi ocaml-lablgtk-devel
-
- If it does not, see http://lablgtk.forge.ocamlcore.org/
-
- The basic command installing lablgtk2 from the source package is:
-
- ./configure && make world && make install
-
- You must have write access to the OCaml standard library path.
- If this fails, read the README.
-
-
-INSTALLATION
-
-0) For optimal performance, OCaml must support native threads (aka pthreads).
- If this not the case, this means that Coq computations will be slow and
- "make ide" will fail. Use "make bin/coqide.byte" instead. To fix this
- problem, just recompile OCaml from source and configure OCaml with:
-
- "./configure --with-pthreads".
-
- In case you install over an existing copy of OCaml, you should better
- empty the OCaml installation directory.
-
-1) Go into your Coq source directory and, as usual, configure with:
-
- ./configure
-
- This should detect the ability of making CoqIde; check in the
- report printed by configure that ability to build CoqIde is detected.
-
- Then compile with
-
- make world
-
- and install with
-
- make install
-
- In case you are upgrading from an old version you may need to run
-
- make clean-ide
-
-2) You may now run bin/coqide
-
-
-NOTES
-
-There are three configuration files located in your $(XDG_CONFIG_HOME)/coq
-dir (defaulting to $HOME/.config/coq).
-
-- coqiderc is generated by coqide itself. It may be edited by hand or
- by using the Preference menu from coqide. It will be generated the first time
- you save your the preferences in Coqide.
-
-- coqide.keys is a standard Gtk2 accelerator dump. You may edit this file
- to change the default shortcuts for the menus.
-
-Read ide/FAQ for more informations.
-
-
-TROUBLESHOOTING
-
-- Problem with automatic templates
-
- Some users may experiment problems with unwanted automatic
- templates while using Coqide. This is due to a change in the
- modifiers keys available through GTK. The straightest way to get
- rid of the problem is to edit by hand your coqiderc (either
- /home/<user>/.config/coq/coqiderc under Linux, or
- C:\Documents and Settings\<user>\.config\coq\coqiderc under Windows)
- and replace any occurrence of MOD4 by MOD1.
-
diff --git a/META.coq b/META.coq.in
index a7c8da1638..b2924e3241 100644
--- a/META.coq
+++ b/META.coq.in
@@ -349,18 +349,6 @@ package "plugins" (
archive(native) = "newring_plugin.cmx"
)
- package "fourier" (
-
- description = "Coq fourier plugin"
- version = "8.9"
-
- requires = "coq.plugins.ltac"
- directory = "fourier"
-
- archive(byte) = "fourier_plugin.cmo"
- archive(native) = "fourier_plugin.cmx"
- )
-
package "extraction" (
description = "Coq extraction plugin"
diff --git a/Makefile b/Makefile
index 4787377ea1..344f2ee972 100644
--- a/Makefile
+++ b/Makefile
@@ -74,11 +74,15 @@ endef
## Files in the source tree
LEXFILES := $(call find, '*.mll')
+YACCFILES := $(call find, '*.mly')
export MLLIBFILES := $(call find, '*.mllib')
export MLPACKFILES := $(call find, '*.mlpack')
export ML4FILES := $(call find, '*.ml4')
+export MLGFILES := $(call find, '*.mlg')
export CFILES := $(call findindir, 'kernel/byterun', '*.c')
-export MERLINFILES := $(call find, '.merlin')
+
+MERLININFILES := $(call find, '.merlin.in')
+export MERLINFILES := $(MERLININFILES:.in=)
# NB: The lists of currently existing .ml and .mli files will change
# before and after a build or a make clean. Hence we do not export
@@ -90,7 +94,8 @@ EXISTINGMLI := $(call find, '*.mli')
## Files that will be generated
GENML4FILES:= $(ML4FILES:.ml4=.ml)
-export GENMLFILES:=$(LEXFILES:.mll=.ml) kernel/copcodes.ml
+GENMLGFILES:= $(MLGFILES:.mlg=.ml)
+export GENMLFILES:=$(LEXFILES:.mll=.ml) $(YACCFILES:.mly=.ml) $(GENMLGFILES) kernel/copcodes.ml
export GENHFILES:=kernel/byterun/coq_jumptbl.h
export GENFILES:=$(GENMLFILES) $(GENMLIFILES) $(GENHFILES)
@@ -100,7 +105,7 @@ export GENFILES:=$(GENMLFILES) $(GENMLIFILES) $(GENHFILES)
## More complex file lists
-export MLSTATICFILES := $(filter-out $(GENMLFILES) $(GENML4FILES), $(EXISTINGML))
+export MLSTATICFILES := $(filter-out $(GENMLFILES) $(GENML4FILES) $(GENMLGFILES), $(EXISTINGML))
export MLIFILES := $(sort $(GENMLIFILES) $(EXISTINGMLI))
include Makefile.common
@@ -111,7 +116,7 @@ include Makefile.common
NOARG: world
-.PHONY: NOARG help noconfig submake
+.PHONY: NOARG help noconfig submake camldevfiles
help:
@echo "Please use either:"
@@ -138,12 +143,13 @@ Then, you may want to consider whether you want to restore the autosaves)
#run.
endif
-# Apart from clean and tags, everything will be done in a sub-call to make
-# on Makefile.build. This way, we avoid doing here the -include of .d :
-# since they trigger some compilations, we do not want them for a mere clean.
-# Moreover, we regroup this sub-call in a common target named 'submake'.
-# This way, multiple user-given goals (cf the MAKECMDGOALS variable) won't
-# trigger multiple (possibly parallel) make sub-calls
+# Apart from clean and a few misc files, everything will be done in a
+# sub-call to make on Makefile.build. This way, we avoid doing here
+# the -include of .d : since they trigger some compilations, we do not
+# want them for a mere clean. Moreover, we regroup this sub-call in a
+# common target named 'submake'. This way, multiple user-given goals
+# (cf the MAKECMDGOALS variable) won't trigger multiple (possibly
+# parallel) make sub-calls
ifdef COQ_CONFIGURED
%:: submake ;
@@ -153,7 +159,10 @@ endif
MAKE_OPTS := --warn-undefined-variable --no-builtin-rules
-submake: alienclean
+bin:
+ mkdir bin
+
+submake: alienclean camldevfiles | bin
$(MAKE) $(MAKE_OPTS) -f Makefile.build $(MAKECMDGOALS)
noconfig:
@@ -164,12 +173,26 @@ noconfig:
Makefile $(wildcard Makefile.*) config/Makefile : ;
###########################################################################
+# OCaml dev files
+###########################################################################
+camldevfiles: $(MERLINFILES) META.coq
+
+.merlin: .merlin.in
+ cp -a "$<" "$@"
+
+%/.merlin: %/.merlin.in
+ cp -a "$<" "$@"
+
+META.coq: META.coq.in
+ cp -a "$<" "$@"
+
+###########################################################################
# Cleaning
###########################################################################
.PHONY: clean cleankeepvo objclean cruftclean indepclean docclean archclean optclean clean-ide ml4clean depclean cleanconfig distclean voclean timingclean devdocclean alienclean
-clean: objclean cruftclean depclean docclean devdocclean
+clean: objclean cruftclean depclean docclean devdocclean camldevfilesclean
cleankeepvo: indepclean clean-ide optclean cruftclean depclean docclean devdocclean
@@ -179,6 +202,9 @@ cruftclean: ml4clean
find . -name '*~' -o -name '*.annot' | xargs rm -f
rm -f gmon.out core
+camldevfilesclean:
+ rm -f $(MERLINFILES) META.coq
+
indepclean:
rm -f $(GENFILES)
rm -f $(COQTOPBYTE) $(CHICKENBYTE) $(TOPBYTE)
@@ -211,7 +237,7 @@ archclean: clean-ide optclean voclean
rm -f $(ALLSTDLIB).*
optclean:
- rm -f $(COQTOPEXE) $(CHICKEN) $(TOPBIN)
+ rm -f $(COQTOPEXE) $(CHICKEN) $(TOPBINOPT)
rm -f $(TOOLS) $(PRIVATEBINARIES) $(CSDPCERT)
find . -name '*.cmx' -o -name '*.cmx[as]' -o -name '*.[soa]' -o -name '*.so' | xargs rm -f
@@ -223,7 +249,7 @@ clean-ide:
rm -rf $(COQIDEAPP)
ml4clean:
- rm -f $(GENML4FILES)
+ rm -f $(GENML4FILES) $(GENMLGFILES)
depclean:
find . $(FIND_SKIP_DIRS) '(' -name '*.d' ')' -print | xargs rm -f
diff --git a/Makefile.build b/Makefile.build
index b854182435..c100eda400 100644
--- a/Makefile.build
+++ b/Makefile.build
@@ -195,7 +195,7 @@ TIMER=$(if $(TIMED), $(STDTIME), $(TIMECMD))
# the output format of the unix command time. For instance:
# TIME="%C (%U user, %S sys, %e total, %M maxres)"
-COQOPTS=$(NATIVECOMPUTE)
+COQOPTS=$(NATIVECOMPUTE) $(COQWARNERROR)
BOOTCOQC=$(TIMER) $(COQTOPBEST) -boot $(COQOPTS) -compile
LOCALINCLUDES=$(addprefix -I ,$(SRCDIRS))
@@ -212,9 +212,17 @@ DEPFLAGS=$(LOCALINCLUDES)$(if $(filter plugins/%,$@),, -I ide -I ide/protocol)
ifeq ($(shell which codesign > /dev/null 2>&1 && echo $(ARCH)),Darwin)
LINKMETADATA=$(if $(filter $(PRIVATEBINARIES),$@),,-ccopt "-sectcreate __TEXT __info_plist config/Info-$(notdir $@).plist")
CODESIGN=$(if $(filter $(PRIVATEBINARIES),$@),true,codesign -s -)
+CODESIGN_HIDE=$(CODESIGN)
else
LINKMETADATA=
CODESIGN=true
+CODESIGN_HIDE=$(HIDE)true
+endif
+
+ifeq ($(STRIP),true)
+STRIP_HIDE=$(HIDE)true
+else
+STRIP_HIDE=$(STRIP)
endif
# Best OCaml compiler, used in a generic way
@@ -342,6 +350,7 @@ kernel/copcodes.ml: kernel/byterun/coq_instruct.h
GRAMBASEDEPS := grammar/q_util.cmi
GRAMCMO := grammar/q_util.cmo \
grammar/argextend.cmo grammar/tacextend.cmo grammar/vernacextend.cmo
+COQPPCMO := $(addsuffix .cmo, $(addprefix coqpp/, coqpp_parse coqpp_lex))
grammar/argextend.cmo : $(GRAMBASEDEPS)
grammar/q_util.cmo : $(GRAMBASEDEPS)
@@ -349,6 +358,10 @@ grammar/tacextend.cmo : $(GRAMBASEDEPS) grammar/argextend.cmo
grammar/vernacextend.cmo : $(GRAMBASEDEPS) grammar/tacextend.cmo \
grammar/argextend.cmo
+coqpp/coqpp_parse.cmi: coqpp/coqpp_ast.cmi
+coqpp/coqpp_parse.cmo: coqpp/coqpp_ast.cmi coqpp/coqpp_parse.cmi
+coqpp/coqpp_lex.cmo: coqpp/coqpp_ast.cmi coqpp/coqpp_parse.cmo
+
## Ocaml compiler with the right options and -I for grammar
GRAMC := $(OCAMLFIND) ocamlc $(CAMLFLAGS) $(CAMLDEBUG) $(USERFLAGS) \
@@ -359,11 +372,15 @@ GRAMC := $(OCAMLFIND) ocamlc $(CAMLFLAGS) $(CAMLDEBUG) $(USERFLAGS) \
grammar/grammar.cma : $(GRAMCMO)
$(SHOW)'Testing $@'
@touch grammar/test.mlp
- $(HIDE)$(GRAMC) -pp '$(CAMLP5O) -I $(MYCAMLP5LIB) $^ -impl' -impl grammar/test.mlp -o grammar/test
+ $(HIDE)$(GRAMC) -pp '$(CAMLP5O) $^ -impl' -impl grammar/test.mlp -o grammar/test
@rm -f grammar/test.* grammar/test
$(SHOW)'OCAMLC -a $@'
$(HIDE)$(GRAMC) $^ -linkall -a -o $@
+$(COQPP): $(COQPPCMO) coqpp/coqpp_main.ml
+ $(SHOW)'OCAMLC -a $@'
+ $(HIDE)$(GRAMC) -I coqpp $^ -linkall -o $@
+
## Support of Camlp5 and Camlp5
COMPATCMO:=
@@ -376,6 +393,10 @@ grammar/%.cmo: grammar/%.mlp | $(COMPATCMO)
$(SHOW)'OCAMLC -c -pp $<'
$(HIDE)$(GRAMC) -c -pp '$(GRAMPP)' -impl $<
+grammar/%.cmo: grammar/%.ml | $(COMPATCMO)
+ $(SHOW)'OCAMLC -c -pp $<'
+ $(HIDE)$(GRAMC) -c $<
+
grammar/%.cmi: grammar/%.mli
$(SHOW)'OCAMLC -c $<'
$(HIDE)$(GRAMC) -c $<
@@ -387,20 +408,21 @@ grammar/%.cmi: grammar/%.mli
.PHONY: coqbinaries coqbyte
-coqbinaries: $(TOPBIN) $(CHICKEN) $(CSDPCERT) $(FAKEIDE)
+coqbinaries: $(TOPBINOPT) $(COQTOPEXE) $(CHICKEN) $(CSDPCERT) $(FAKEIDE)
coqbyte: $(TOPBYTE) $(CHICKENBYTE)
-# Special rule for coqtop
-$(COQTOPEXE): $(TOPBIN:.opt=.$(BEST))
- cp $< $@
+# Special rule for coqtop, we imitate `ocamlopt` can delete the target
+# to avoid #7666
+$(COQTOPEXE): $(TOPBINOPT:.opt=.$(BEST))
+ rm -f $@ && cp $< $@
bin/%.opt$(EXE): topbin/%_bin.ml $(LINKCMX) $(LIBCOQRUN)
$(SHOW)'COQMKTOP -o $@'
$(HIDE)$(OCAMLOPT) -linkall -linkpkg $(MLINCLUDES) \
$(SYSMOD) -package camlp5.gramlib \
$(LINKCMX) $(OPTFLAGS) $(LINKMETADATA) $< -o $@
- $(STRIP) $@
- $(CODESIGN) $@
+ $(STRIP_HIDE) $@
+ $(CODESIGN_HIDE) $@
bin/%.byte$(EXE): topbin/%_bin.ml $(LINKCMO) $(LIBCOQRUN)
$(SHOW)'COQMKTOP -o $@'
@@ -493,14 +515,6 @@ $(COQDEPBYTE): $(COQDEPCMO)
$(SHOW)'OCAMLC -o $@'
$(HIDE)$(call ocamlbyte, $(SYSMOD))
-$(GALLINA): $(call bestobj, tools/gallina_lexer.cmo tools/gallina.cmo)
- $(SHOW)'OCAMLBEST -o $@'
- $(HIDE)$(call bestocaml,)
-
-$(GALLINABYTE): tools/gallina_lexer.cmo tools/gallina.cmo
- $(SHOW)'OCAMLC -o $@'
- $(HIDE)$(call ocamlbyte,)
-
COQMAKEFILECMO:=clib/clib.cma lib/lib.cma tools/coq_makefile.cmo
$(COQMAKEFILE): $(call bestobj,$(COQMAKEFILECMO))
@@ -746,11 +760,18 @@ plugins/%.cmx: plugins/%.ml
$(SHOW)'OCAMLLEX $<'
$(HIDE)$(OCAMLLEX) -o $@ "$*.mll"
-%.ml: %.ml4 $(CAMLP5DEPS)
+%.ml %.mli: %.mly
+ $(SHOW)'OCAMLYACC $<'
+ $(HIDE)$(OCAMLYACC) --strict "$*.mly"
+
+%.ml: %.ml4 $(CAMLP5DEPS) $(COQPP)
$(SHOW)'CAMLP5O $<'
$(HIDE)$(CAMLP5O) -I $(MYCAMLP5LIB) $(PR_O) \
$(CAMLP5DEPS) $(CAMLP5USE) $(CAMLP5COMPAT) -impl $< -o $@
+%.ml: %.mlg $(COQPP)
+ $(SHOW)'COQPP $<'
+ $(HIDE)$(COQPP) $<
###########################################################################
# Dependencies of ML code
diff --git a/Makefile.checker b/Makefile.checker
index 0ec565d616..6c19a1a42b 100644
--- a/Makefile.checker
+++ b/Makefile.checker
@@ -52,8 +52,8 @@ ifeq ($(BEST),opt)
$(CHICKEN): checker/check.cmxa checker/main.mli checker/main.ml
$(SHOW)'OCAMLOPT -o $@'
$(HIDE)$(OCAMLOPT) -linkpkg $(SYSMOD) $(CHKLIBS) $(OPTFLAGS) $(LINKMETADATA) -o $@ $^
- $(STRIP) $@
- $(CODESIGN) $@
+ $(STRIP_HIDE) $@
+ $(CODESIGN_HIDE) $@
else
$(CHICKEN): $(CHICKENBYTE)
cp $< $@
diff --git a/Makefile.ci b/Makefile.ci
index 7f63157faf..e86504b76d 100644
--- a/Makefile.ci
+++ b/Makefile.ci
@@ -8,7 +8,8 @@
## # (see LICENSE file for the text of the license) ##
##########################################################################
-CI_TARGETS=ci-bignums \
+CI_TARGETS=ci-bedrock2 \
+ ci-bignums \
ci-color \
ci-compcert \
ci-coq-dpdgraph \
@@ -21,6 +22,7 @@ CI_TARGETS=ci-bignums \
ci-equations \
ci-fcsl-pcm \
ci-fiat-crypto \
+ ci-fiat-crypto-legacy \
ci-fiat-parsers \
ci-flocq \
ci-formal-topology \
@@ -34,6 +36,7 @@ CI_TARGETS=ci-bignums \
ci-pidetop \
ci-quickchick \
ci-sf \
+ ci-simple-io \
ci-tlc \
ci-unimath \
ci-vst
@@ -52,7 +55,7 @@ ci-math-classes: ci-bignums
ci-corn: ci-math-classes
-ci-quickchick: ci-ext-lib
+ci-quickchick: ci-ext-lib ci-simple-io
ci-formal-topology: ci-corn
diff --git a/Makefile.common b/Makefile.common
index 5b1def40aa..772561bd70 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -14,18 +14,17 @@
# Executables
###########################################################################
-TOPBIN:=$(addsuffix .opt$(EXE), $(addprefix bin/, coqtop coqproofworker coqtacticworker coqqueryworker))
-TOPBYTE:=$(TOPBIN:.opt$(EXE)=.byte$(EXE))
+TOPBINOPT:=$(addsuffix .opt$(EXE), $(addprefix bin/, coqtop coqproofworker coqtacticworker coqqueryworker))
+TOPBYTE:=$(TOPBINOPT:.opt$(EXE)=.byte$(EXE))
COQTOPEXE:=bin/coqtop$(EXE)
COQTOPBYTE:=bin/coqtop.byte$(EXE)
COQDEP:=bin/coqdep$(EXE)
+COQPP:=bin/coqpp$(EXE)
COQDEPBYTE:=bin/coqdep.byte$(EXE)
COQMAKEFILE:=bin/coq_makefile$(EXE)
COQMAKEFILEBYTE:=bin/coq_makefile.byte$(EXE)
-GALLINA:=bin/gallina$(EXE)
-GALLINABYTE:=bin/gallina.byte$(EXE)
COQTEX:=bin/coq-tex$(EXE)
COQTEXBYTE:=bin/coq-tex.byte$(EXE)
COQWC:=bin/coqwc$(EXE)
@@ -41,8 +40,8 @@ COQTIME_FILE_MAKER:=tools/TimeFileMaker.py
COQMAKE_BOTH_TIME_FILES:=tools/make-both-time-files.py
COQMAKE_BOTH_SINGLE_TIMING_FILES:=tools/make-both-single-timing-files.py
-TOOLS:=$(COQDEP) $(COQMAKEFILE) $(GALLINA) $(COQTEX) $(COQWC) $(COQDOC) $(COQC)\
- $(COQWORKMGR)
+TOOLS:=$(COQDEP) $(COQMAKEFILE) $(COQTEX) $(COQWC) $(COQDOC) $(COQC)\
+ $(COQWORKMGR) $(COQPP)
TOOLS_HELPERS:=tools/CoqMakefile.in $(COQMAKE_ONE_TIME_FILE) $(COQTIME_FILE_MAKER)\
$(COQMAKE_BOTH_TIME_FILES) $(COQMAKE_BOTH_SINGLE_TIMING_FILES)
@@ -90,13 +89,14 @@ INSTALLSH:=./install.sh
MKDIR:=install -d
CORESRCDIRS:=\
+ coqpp \
config clib lib kernel kernel/byterun library \
engine pretyping interp proofs parsing printing \
tactics vernac stm toplevel
PLUGINDIRS:=\
omega romega micromega quote \
- setoid_ring extraction fourier \
+ setoid_ring extraction \
cc funind firstorder derive \
rtauto nsatz syntax btauto \
ssrmatching ltac ssr
@@ -134,7 +134,6 @@ MICROMEGACMO:=plugins/micromega/micromega_plugin.cmo
QUOTECMO:=plugins/quote/quote_plugin.cmo
RINGCMO:=plugins/setoid_ring/newring_plugin.cmo
NSATZCMO:=plugins/nsatz/nsatz_plugin.cmo
-FOURIERCMO:=plugins/fourier/fourier_plugin.cmo
EXTRACTIONCMO:=plugins/extraction/extraction_plugin.cmo
FUNINDCMO:=plugins/funind/recdef_plugin.cmo
FOCMO:=plugins/firstorder/ground_plugin.cmo
@@ -143,8 +142,8 @@ BTAUTOCMO:=plugins/btauto/btauto_plugin.cmo
RTAUTOCMO:=plugins/rtauto/rtauto_plugin.cmo
NATSYNTAXCMO:=plugins/syntax/nat_syntax_plugin.cmo
OTHERSYNTAXCMO:=$(addprefix plugins/syntax/, \
- z_syntax_plugin.cmo \
- r_syntax_plugin.cmo \
+ positive_syntax_plugin.cmo n_syntax_plugin.cmo \
+ z_syntax_plugin.cmo r_syntax_plugin.cmo \
int31_syntax_plugin.cmo \
ascii_syntax_plugin.cmo \
string_syntax_plugin.cmo )
@@ -155,7 +154,7 @@ SSRCMO:=plugins/ssr/ssreflect_plugin.cmo
PLUGINSCMO:=$(LTACCMO) $(OMEGACMO) $(ROMEGACMO) $(MICROMEGACMO) \
$(QUOTECMO) $(RINGCMO) \
- $(FOURIERCMO) $(EXTRACTIONCMO) \
+ $(EXTRACTIONCMO) \
$(CCCMO) $(FOCMO) $(RTAUTOCMO) $(BTAUTOCMO) \
$(FUNINDCMO) $(NSATZCMO) $(NATSYNTAXCMO) $(OTHERSYNTAXCMO) \
$(DERIVECMO) $(SSRMATCHINGCMO) $(SSRCMO)
diff --git a/Makefile.dev b/Makefile.dev
index 8f7d21694a..7fc1076a8f 100644
--- a/Makefile.dev
+++ b/Makefile.dev
@@ -174,7 +174,6 @@ MICROMEGAVO:=$(filter plugins/micromega/%, $(PLUGINSVO))
QUOTEVO:=$(filter plugins/quote/%, $(PLUGINSVO))
RINGVO:=$(filter plugins/setoid_ring/%, $(PLUGINSVO))
NSATZVO:=$(filter plugins/nsatz/%, $(PLUGINSVO))
-FOURIERVO:=$(filter plugins/fourier/%, $(PLUGINSVO))
FUNINDVO:=$(filter plugins/funind/%, $(PLUGINSVO))
BTAUTOVO:=$(filter plugins/btauto/%, $(PLUGINSVO))
RTAUTOVO:=$(filter plugins/rtauto/%, $(PLUGINSVO))
@@ -188,7 +187,6 @@ micromega: $(MICROMEGAVO) $(MICROMEGACMO) $(CSDPCERT)
setoid_ring: $(RINGVO) $(RINGCMO)
nsatz: $(NSATZVO) $(NSATZCMO)
extraction: $(EXTRACTIONCMO) $(EXTRACTIONVO)
-fourier: $(FOURIERVO) $(FOURIERCMO)
funind: $(FUNINDCMO) $(FUNINDVO)
cc: $(CCVO) $(CCCMO)
rtauto: $(RTAUTOVO) $(RTAUTOCMO)
@@ -196,7 +194,7 @@ btauto: $(BTAUTOVO) $(BTAUTOCMO)
ltac: $(LTACVO) $(LTACCMO)
.PHONY: omega micromega setoid_ring nsatz extraction
-.PHONY: fourier funind cc rtauto btauto ltac
+.PHONY: funind cc rtauto btauto ltac
# For emacs:
# Local Variables:
diff --git a/Makefile.doc b/Makefile.doc
index dde3a37b70..1b1198c1f2 100644
--- a/Makefile.doc
+++ b/Makefile.doc
@@ -33,6 +33,10 @@ HTMLSTYLE:=coqremote
# Sphinx-related variables
SPHINXENV:=COQBIN="$(CURDIR)/bin/"
SPHINXOPTS= -j4
+SPHINXWARNERROR ?= 1
+ifeq ($(SPHINXWARNERROR),1)
+SPHINXOPTS += -W
+endif
SPHINXBUILD= sphinx-build
SPHINXBUILDDIR= doc/sphinx/_build
@@ -56,7 +60,7 @@ endif
sphinx: $(SPHINX_DEPS)
$(SHOW)'SPHINXBUILD doc/sphinx'
- $(HIDE)$(SPHINXENV) $(SPHINXBUILD) -W -b html $(ALLSPHINXOPTS) doc/sphinx $(SPHINXBUILDDIR)/html
+ $(HIDE)$(SPHINXENV) $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) doc/sphinx $(SPHINXBUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(SPHINXBUILDDIR)/html."
diff --git a/Makefile.ide b/Makefile.ide
index 6bb0f62f34..cb55960203 100644
--- a/Makefile.ide
+++ b/Makefile.ide
@@ -99,7 +99,7 @@ $(COQIDE): $(LINKIDEOPT)
$(SHOW)'OCAMLOPT -o $@'
$(HIDE)$(OCAMLOPT) $(COQIDEFLAGS) $(OPTFLAGS) -o $@ \
-linkpkg -package str,unix,dynlink,threads,lablgtk2.sourceview2 $(IDEFLAGS:.cma=.cmxa) $^
- $(STRIP) $@
+ $(STRIP_HIDE) $@
else
$(COQIDE): $(COQIDEBYTE)
cp $< $@
@@ -149,8 +149,8 @@ $(IDETOP): ide/idetop.ml $(LINKCMX) $(LIBCOQRUN) $(IDETOPCMX)
$(HIDE)$(OCAMLOPT) -linkall -linkpkg $(MLINCLUDES) -I ide -I ide/protocol/ \
$(SYSMOD) -package camlp5.gramlib \
$(LINKCMX) $(IDETOPCMX) $(OPTFLAGS) $(LINKMETADATA) $< -o $@
- $(STRIP) $@
- $(CODESIGN) $@
+ $(STRIP_HIDE) $@
+ $(CODESIGN_HIDE) $@
$(IDETOPBYTE): ide/idetop.ml $(LINKCMO) $(LIBCOQRUN) $(IDETOPCMA)
$(SHOW)'COQMKTOP -o $@'
@@ -229,7 +229,7 @@ $(COQIDEINAPP): ide/macos_prehook.cmx $(LINKIDEOPT) | $(COQIDEAPP)/Contents
$(SHOW)'OCAMLOPT -o $@'
$(HIDE)$(OCAMLOPT) $(COQIDEFLAGS) $(OPTFLAGS) -o $@ \
-linkpkg -package str,unix,dynlink,threads,lablgtk2.sourceview2 $(IDEFLAGS:.cma=.cmxa) $^
- $(STRIP) $@
+ $(STRIP_HIDE) $@
$(COQIDEAPP)/Contents/Resources/share: $(COQIDEAPP)/Contents
$(MKDIR) $@/coq/
@@ -275,7 +275,7 @@ $(COQIDEAPP)/Contents/Resources:$(COQIDEAPP)/Contents/Resources/etc $(COQIDEAPP)
$(INSTALLLIB) ide/MacOS/*.icns $@
$(COQIDEAPP):$(COQIDEAPP)/Contents/Resources
- $(CODESIGN) $@
+ $(CODESIGN_HIDE) $@
###########################################################################
# CoqIde for Windows special targets
diff --git a/Makefile.install b/Makefile.install
index 010e35d424..be6fe54933 100644
--- a/Makefile.install
+++ b/Makefile.install
@@ -43,7 +43,6 @@ FULLCOQLIB=$(COQLIBINSTALL:"$(OLDROOT)%="$(COQINSTALLPREFIX)%)
FULLCONFIGDIR=$(CONFIGDIR:"$(OLDROOT)%="$(COQINSTALLPREFIX)%)
FULLDATADIR=$(DATADIR:"$(OLDROOT)%="$(COQINSTALLPREFIX)%)
FULLMANDIR=$(MANDIR:"$(OLDROOT)%="$(COQINSTALLPREFIX)%)
-FULLEMACSLIB=$(EMACSLIB:"$(OLDROOT)%="$(COQINSTALLPREFIX)%)
FULLCOQDOCDIR=$(COQDOCDIR:"$(OLDROOT)%="$(COQINSTALLPREFIX)%)
FULLDOCDIR=$(DOCDIR:"$(OLDROOT)%="$(COQINSTALLPREFIX)%)
else
@@ -52,14 +51,13 @@ FULLCOQLIB=$(COQLIBINSTALL)
FULLCONFIGDIR=$(CONFIGDIR)
FULLDATADIR=$(DATADIR)
FULLMANDIR=$(MANDIR)
-FULLEMACSLIB=$(EMACSLIB)
FULLCOQDOCDIR=$(COQDOCDIR)
FULLDOCDIR=$(DOCDIR)
endif
.PHONY: install-coq install-binaries install-byte install-opt
.PHONY: install-tools install-library install-devfiles install-merlin
-.PHONY: install-coq-info install-coq-manpages install-emacs install-latex
+.PHONY: install-coq-info install-coq-manpages install-latex
.PHONY: install-meta
install-coq: install-binaries install-library install-coq-info install-devfiles
@@ -70,7 +68,7 @@ endif
install-binaries: install-tools
$(MKDIR) $(FULLBINDIR)
- $(INSTALLBIN) $(COQC) $(CHICKEN) $(COQTOPEXE) $(TOPBIN) $(FULLBINDIR)
+ $(INSTALLBIN) $(COQC) $(CHICKEN) $(COQTOPEXE) $(TOPBINOPT) $(FULLBINDIR)
install-byte: install-coqide-byte
$(MKDIR) $(FULLBINDIR)
@@ -136,9 +134,9 @@ endif
rm -f $(FULLCOQLIB)/revision
-$(INSTALLLIB) revision $(FULLCOQLIB)
-install-coq-info: install-coq-manpages install-emacs install-latex
+install-coq-info: install-coq-manpages install-latex
-MANPAGES:=man/coq-tex.1 man/coqdep.1 man/gallina.1 \
+MANPAGES:=man/coq-tex.1 man/coqdep.1 \
man/coqc.1 man/coqtop.1 man/coqtop.byte.1 man/coqtop.opt.1 \
man/coqwc.1 man/coqdoc.1 man/coqide.1 \
man/coq_makefile.1 man/coqchk.1
@@ -147,10 +145,6 @@ install-coq-manpages:
$(MKDIR) $(FULLMANDIR)/man1
$(INSTALLLIB) $(MANPAGES) $(FULLMANDIR)/man1
-install-emacs:
- $(MKDIR) $(FULLEMACSLIB)
- $(INSTALLLIB) tools/gallina-db.el tools/coq-font-lock.el tools/gallina-syntax.el tools/gallina.el tools/inferior-coq.el $(FULLEMACSLIB)
-
# command to update TeX' kpathsea database
#UPDATETEX = $(MKTEXLSR) /usr/share/texmf /var/spool/texmf $(BASETEXDIR) > /dev/null
diff --git a/README.md b/README.md
index 0903abdd41..fcf20f0097 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,6 @@
[![pipeline status](https://gitlab.com/coq/coq/badges/master/pipeline.svg)](https://gitlab.com/coq/coq/commits/master)
[![Travis](https://travis-ci.org/coq/coq.svg?branch=master)](https://travis-ci.org/coq/coq/builds)
[![Appveyor](https://ci.appveyor.com/api/projects/status/eln43k05pa2vm908/branch/master?svg=true)](https://ci.appveyor.com/project/coq/coq/branch/master)
-[![Circle CI](https://circleci.com/gh/coq/coq/tree/master.svg?style=shield)](https://circleci.com/gh/coq/workflows/coq/tree/master)
[![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)
@@ -18,7 +17,9 @@ or refer to the [`INSTALL` file](INSTALL) for the procedure to install from sour
## Documentation
-The sources of the documentation can be found in directory [`doc`](doc). The
+The sources of the documentation can be found in directory [`doc`](doc).
+See [`doc/README.md`](/doc/README.md) to learn more about the documentation,
+in particular how to build it. The
documentation of the last released version is available on the Coq
web site at [coq.inria.fr/documentation](http://coq.inria.fr/documentation).
See also [Cocorico](https://github.com/coq/coq/wiki) (the Coq wiki),
@@ -54,3 +55,11 @@ used, and include a complete source example leading to the bug.
## Contributing
Guidelines for contributing to Coq in various ways are listed in the [contributor's guide](CONTRIBUTING.md).
+
+## Supporting Coq
+
+Help the Coq community grow and prosper by becoming a sponsor! The [Coq
+Consortium](https://coq.inria.fr/consortium) can establish sponsorship contracts
+or receive donations. If you want to take an active role in shaping Coq's
+future, you can also become a Consortium member. If you are interested, please
+get in touch!
diff --git a/checker/cic.mli b/checker/cic.mli
index a890f2cef5..17259bb438 100644
--- a/checker/cic.mli
+++ b/checker/cic.mli
@@ -33,11 +33,10 @@ open Names
(** {6 The sorts of CCI. } *)
-type contents = Pos | Null
-
type sorts =
- | Prop of contents (** Prop and Set *)
- | Type of Univ.universe (** Type *)
+ | Prop
+ | Set
+ | Type of Univ.universe
(** {6 The sorts family of CCI. } *)
@@ -203,16 +202,6 @@ type inline = int option
(** A constant can have no body (axiom/parameter), or a
transparent body, or an opaque one *)
-(** Projections are a particular kind of constant:
- always transparent. *)
-
-type projection_body = {
- proj_ind : inductive;
- proj_npars : int;
- proj_arg : int;
- proj_type : constr; (* Type under params *)
-}
-
type constant_def =
| Undef of inline
| Def of constr_substituted
@@ -231,6 +220,7 @@ type typing_flags = {
points are assumed to be total. *)
check_universes : bool; (** If [false] universe constraints are not checked *)
conv_oracle : oracle; (** Unfolding strategies for conversion *)
+ share_reduction : bool; (** Use by-need reduction algorithm *)
}
type constant_body = {
@@ -255,7 +245,7 @@ type wf_paths = recarg Rtree.t
type record_info =
| NotRecord
| FakeRecord
-| PrimRecord of (Id.t * Constant.t array * projection_body array) array
+| PrimRecord of (Id.t * Label.t array * constr array) array
type regular_inductive_arity = {
mind_user_arity : constr;
diff --git a/checker/closure.ml b/checker/closure.ml
index 2dcc1a9840..5706011607 100644
--- a/checker/closure.ml
+++ b/checker/closure.ml
@@ -273,7 +273,7 @@ let update v1 (no,t) =
type stack_member =
| Zapp of fconstr array
| ZcaseT of case_info * constr * constr array * fconstr subs
- | Zproj of int * int * Projection.t
+ | Zproj of Projection.Repr.t
| Zfix of fconstr * stack
| Zshift of int
| Zupdate of fconstr
@@ -497,8 +497,8 @@ let rec zip m stk =
| ZcaseT(ci,p,br,e)::s ->
let t = FCaseT(ci, p, m, br, e) in
zip {norm=neutr m.norm; term=t} s
- | Zproj (i,j,cst) :: s ->
- zip {norm=neutr m.norm; term=FProj (cst,m)} s
+ | Zproj p :: s ->
+ zip {norm=neutr m.norm; term=FProj (Projection.make p true,m)} s
| Zfix(fx,par)::s ->
zip fx (par @ append_stack [|m|] s)
| Zshift(n)::s ->
@@ -618,21 +618,25 @@ let drop_parameters depth n argstk =
let eta_expand_ind_stack env ind m s (f, s') =
let mib = lookup_mind (fst ind) env in
- match mib.mind_record with
- | PrimRecord info when mib.mind_finite <> CoFinite ->
- let (_, projs, pbs) = info.(snd ind) in
- (* (Construct, pars1 .. parsm :: arg1...argn :: []) ~= (f, s') ->
- arg1..argn ~= (proj1 t...projn t) where t = zip (f,s') *)
- let pars = mib.mind_nparams in
- let right = fapp_stack (f, s') in
- let (depth, args, s) = strip_update_shift_app m s in
- (** Try to drop the params, might fail on partially applied constructors. *)
- let argss = try_drop_parameters depth pars args in
- let hstack =
- Array.map (fun p -> { norm = Red; (* right can't be a constructor though *)
- term = FProj (Projection.make p false, right) }) projs in
- argss, [Zapp hstack]
- | _ -> raise Not_found (* disallow eta-exp for non-primitive records *)
+ (* disallow eta-exp for non-primitive records *)
+ if not (mib.mind_finite == BiFinite) then raise Not_found;
+ match Declarations.inductive_make_projections ind mib with
+ | Some projs ->
+ (* (Construct, pars1 .. parsm :: arg1...argn :: []) ~= (f, s') ->
+ arg1..argn ~= (proj1 t...projn t) where t = zip (f,s') *)
+ let pars = mib.mind_nparams in
+ let right = fapp_stack (f, s') in
+ let (depth, args, s) = strip_update_shift_app m s in
+ (** Try to drop the params, might fail on partially applied constructors. *)
+ let argss = try_drop_parameters depth pars args in
+ let hstack =
+ Array.map (fun p ->
+ { norm = Red; (* right can't be a constructor though *)
+ term = FProj (Projection.make p false, right) })
+ projs
+ in
+ argss, [Zapp hstack]
+ | None -> raise Not_found (* disallow eta-exp for non-primitive records *)
let rec project_nth_arg n argstk =
match argstk with
@@ -669,8 +673,7 @@ let contract_fix_vect fix =
(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)
+ Zproj (Projection.repr p)
(*********************************************************************)
(* A machine that inspects the head of a term until it finds an
@@ -748,9 +751,9 @@ let rec knr info m stk =
let stk' = par @ append_stack [|rarg|] s in
let (fxe,fxbd) = contract_fix_vect fx.term in
knit info fxe fxbd stk'
- | (depth, args, Zproj (n, m, cst)::s) ->
- let rargs = drop_parameters depth n args in
- let rarg = project_nth_arg m rargs in
+ | (depth, args, Zproj p::s) ->
+ let rargs = drop_parameters depth (Projection.Repr.npars p) args in
+ let rarg = project_nth_arg (Projection.Repr.arg p) rargs in
kni info rarg s
| (_,args,s) -> (m,args@s))
| FCoFix _ when red_set info.i_flags fIOTA ->
diff --git a/checker/closure.mli b/checker/closure.mli
index 49b07f730d..cec785699d 100644
--- a/checker/closure.mli
+++ b/checker/closure.mli
@@ -103,7 +103,7 @@ type fterm =
type stack_member =
| Zapp of fconstr array
| ZcaseT of case_info * constr * constr array * fconstr subs
- | Zproj of int * int * Projection.t
+ | Zproj of Projection.Repr.t
| Zfix of fconstr * stack
| Zshift of int
| Zupdate of fconstr
diff --git a/checker/declarations.ml b/checker/declarations.ml
index a744a02279..0540227ccb 100644
--- a/checker/declarations.ml
+++ b/checker/declarations.ml
@@ -214,11 +214,7 @@ let rec map_kn f f' c =
match c with
| Const (kn, u) -> (try snd (f' kn u) with No_subst -> c)
| Proj (p,t) ->
- let p' =
- Projection.map (fun kn ->
- try fst (f' kn Univ.Instance.empty)
- with No_subst -> kn) p
- in
+ let p' = Projection.map f p in
let t' = func t in
if p' == p && t' == t then c
else Proj (p', t')
@@ -495,6 +491,16 @@ let eq_recarg r1 r2 = match r1, r2 with
let eq_wf_paths = Rtree.equal eq_recarg
+let inductive_make_projections ind mib =
+ match mib.mind_record with
+ | NotRecord | FakeRecord -> None
+ | PrimRecord infos ->
+ let projs = Array.mapi (fun proj_arg lab ->
+ Names.Projection.Repr.make ind ~proj_npars:mib.mind_nparams ~proj_arg lab)
+ (pi2 infos.(snd ind))
+ in
+ Some projs
+
(**********************************************************************)
(* Representation of mutual inductive types in the kernel *)
(*
diff --git a/checker/declarations.mli b/checker/declarations.mli
index 7458b3e0b0..ce852644ef 100644
--- a/checker/declarations.mli
+++ b/checker/declarations.mli
@@ -25,6 +25,9 @@ val dest_subterms : wf_paths -> wf_paths list array
val eq_recarg : recarg -> recarg -> bool
val eq_wf_paths : wf_paths -> wf_paths -> bool
+val inductive_make_projections : Names.inductive -> mutual_inductive_body ->
+ Names.Projection.Repr.t array option
+
(* Modules *)
val empty_delta_resolver : delta_resolver
diff --git a/checker/environ.ml b/checker/environ.ml
index ba1eb0ddb4..74cf237763 100644
--- a/checker/environ.ml
+++ b/checker/environ.ml
@@ -7,7 +7,6 @@ open Declarations
type globals = {
env_constants : constant_body Cmap_env.t;
- env_projections : projection_body Cmap_env.t;
env_inductives : mutual_inductive_body Mindmap_env.t;
env_inductives_eq : KerName.t KNmap.t;
env_modules : module_body MPmap.t;
@@ -35,7 +34,6 @@ let empty_oracle = {
let empty_env = {
env_globals =
{ env_constants = Cmap_env.empty;
- env_projections = Cmap_env.empty;
env_inductives = Mindmap_env.empty;
env_inductives_eq = KNmap.empty;
env_modules = MPmap.empty;
@@ -166,9 +164,6 @@ let evaluable_constant cst env =
try let _ = constant_value env (cst, Univ.Instance.empty) in true
with Not_found | NotEvaluableConst _ -> false
-let lookup_projection p env =
- Cmap_env.find (Projection.constant p) env.env_globals.env_projections
-
(* Mutual Inductives *)
let scrape_mind env kn=
try
@@ -191,14 +186,6 @@ let add_mind kn mib env =
Printf.ksprintf anomaly ("Inductive %s is already defined.")
(MutInd.to_string kn);
let new_inds = Mindmap_env.add kn mib env.env_globals.env_inductives in
- let new_projections = match mib.mind_record with
- | NotRecord | FakeRecord -> env.env_globals.env_projections
- | PrimRecord projs ->
- Array.fold_left (fun accu (id, kns, pbs) ->
- Array.fold_left2 (fun accu kn pb ->
- Cmap_env.add kn pb accu) accu kns pbs)
- env.env_globals.env_projections projs
- in
let kn1,kn2 = MutInd.user kn, MutInd.canonical kn in
let new_inds_eq = if KerName.equal kn1 kn2 then
env.env_globals.env_inductives_eq
@@ -207,10 +194,22 @@ let add_mind kn mib env =
let new_globals =
{ env.env_globals with
env_inductives = new_inds;
- env_projections = new_projections;
env_inductives_eq = new_inds_eq} in
{ env with env_globals = new_globals }
+let lookup_projection p env =
+ let mind,i = Projection.inductive p in
+ let mib = lookup_mind mind env in
+ match mib.mind_record with
+ | NotRecord | FakeRecord -> CErrors.anomaly ~label:"lookup_projection" Pp.(str "not a projection")
+ | PrimRecord infos ->
+ let _,labs,typs = infos.(i) in
+ let parg = Projection.arg p in
+ if not (Label.equal labs.(parg) (Projection.label p))
+ then CErrors.anomaly ~label:"lookup_projection" Pp.(str "incorrect label on projection")
+ else if not (Int.equal mib.mind_nparams (Projection.npars p))
+ then CErrors.anomaly ~label:"lookup_projection" Pp.(str "incorrect param number on projection")
+ else typs.(parg)
(* Modules *)
diff --git a/checker/environ.mli b/checker/environ.mli
index acb29d7d2d..af1b2a6228 100644
--- a/checker/environ.mli
+++ b/checker/environ.mli
@@ -5,7 +5,6 @@ open Cic
type globals = {
env_constants : constant_body Cmap_env.t;
- env_projections : projection_body Cmap_env.t;
env_inductives : mutual_inductive_body Mindmap_env.t;
env_inductives_eq : KerName.t KNmap.t;
env_modules : module_body MPmap.t;
@@ -58,7 +57,8 @@ exception NotEvaluableConst of const_evaluation_result
val constant_value : env -> Constant.t puniverses -> constr
val evaluable_constant : Constant.t -> env -> bool
-val lookup_projection : Projection.t -> env -> projection_body
+(** NB: here in the checker we check the inferred info (npars, label) *)
+val lookup_projection : Projection.t -> env -> constr
(* Inductives *)
val mind_equiv : env -> inductive -> inductive -> bool
diff --git a/checker/indtypes.ml b/checker/indtypes.ml
index 916934a81f..8f11e01c33 100644
--- a/checker/indtypes.ml
+++ b/checker/indtypes.ml
@@ -107,11 +107,11 @@ let rec sorts_of_constr_args env t =
(* Prop and Set are small *)
let is_small_sort = function
- | Prop _ -> true
+ | Prop | Set -> true
| _ -> false
let is_logic_sort = function
-| Prop Null -> true
+| Prop -> true
| _ -> false
(* [infos] is a sequence of pair [islogic,issmall] for each type in
@@ -186,10 +186,10 @@ let check_predicativity env s small level =
(* (universes env) in *)
if not (Univ.check_leq (universes env) level u) then
failwith "impredicative Type inductive type"
- | Prop Pos, ImpredicativeSet -> ()
- | Prop Pos, _ ->
+ | Set, ImpredicativeSet -> ()
+ | Set, _ ->
if not small then failwith "impredicative Set inductive type"
- | Prop Null,_ -> ()
+ | Prop,_ -> ()
let sort_of_ind = function
@@ -221,7 +221,7 @@ let allowed_sorts issmall isunit s =
-let compute_elim_sorts env_ar params mib arity lc =
+let compute_elim_sorts env_ar params arity lc =
let inst = extended_rel_list 0 params in
let env_params = push_rel_context params env_ar in
let lc = Array.map
@@ -239,7 +239,7 @@ let compute_elim_sorts env_ar params mib arity lc =
allowed_sorts small unit s
-let typecheck_one_inductive env params mib mip =
+let typecheck_one_inductive env params mip =
(* mind_typename and mind_consnames not checked *)
(* mind_reloc_tbl, mind_nb_constant, mind_nb_args not checked (VM) *)
(* mind_arity_ctxt, mind_arity, mind_nrealargs DONE (typecheck_arity) *)
@@ -256,7 +256,7 @@ let typecheck_one_inductive env params mib mip =
Array.iter2 check_cons_args mip.mind_nf_lc mip.mind_consnrealdecls;
(* mind_kelim: checked by positivity criterion ? *)
let sorts =
- compute_elim_sorts env params mib mip.mind_arity mip.mind_nf_lc in
+ compute_elim_sorts env params mip.mind_arity mip.mind_nf_lc in
let reject_sort s = not (List.mem_f family_equal s sorts) in
if List.exists reject_sort mip.mind_kelim then
failwith "elimination not allowed";
@@ -355,7 +355,7 @@ let lambda_implicit_lift n a =
(* This removes global parameters of the inductive types in lc (for
nested inductive types only ) *)
-let abstract_mind_lc env ntyps npars lc =
+let abstract_mind_lc ntyps npars lc =
if npars = 0 then
lc
else
@@ -448,7 +448,7 @@ let check_positivity_one (env, _,ntypes,_ as ienv) hyps nrecp (_,i as ind) indlc
let auxntyp = mib.mind_ntypes in
if auxntyp <> 1 then raise (IllFormedInd (LocalNonPos n));
(* The nested inductive type with parameters removed *)
- let auxlcvect = abstract_mind_lc env auxntyp auxnpar mip.mind_nf_lc in
+ let auxlcvect = abstract_mind_lc auxntyp auxnpar mip.mind_nf_lc in
(* Extends the environment with a variable corresponding to
the inductive def *)
let (env',_,_,_ as ienv') = ienv_push_inductive ienv ((mi,u),lpar) in
@@ -625,7 +625,7 @@ let check_inductive env kn mib =
(* - check arities *)
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;
+ Array.iter (typecheck_one_inductive env_ar params) mib.mind_packets;
(* check the inferred subtyping relation *)
let () =
match mib.mind_universes with
diff --git a/checker/inductive.ml b/checker/inductive.ml
index e1c6b135d7..d15380643f 100644
--- a/checker/inductive.ml
+++ b/checker/inductive.ml
@@ -101,7 +101,7 @@ let instantiate_params full t u args sign =
substl subs ty
let full_inductive_instantiate mib u params sign =
- let dummy = Prop Null in
+ let dummy = Prop in
let t = mkArity (Term.subst_instance_context u sign,dummy) in
fst (destArity (instantiate_params true t u params mib.mind_params_ctxt))
@@ -137,8 +137,8 @@ Remark: Set (predicative) is encoded as Type(0)
let sort_as_univ = function
| Type u -> u
-| Prop Null -> Univ.type0m_univ
-| Prop Pos -> Univ.type0_univ
+| Prop -> Univ.type0m_univ
+| Set -> Univ.type0_univ
(* cons_subst add the mapping [u |-> su] in subst if [u] is not *)
(* in the domain or add [u |-> sup x su] if [u] is already mapped *)
@@ -195,9 +195,9 @@ let instantiate_universes env ctx ar argsorts =
let level = Univ.subst_univs_universe (Univ.make_subst subst) ar.template_level in
let ty =
(* Singleton type not containing types are interpretable in Prop *)
- if Univ.is_type0m_univ level then Prop Null
+ if Univ.is_type0m_univ level then Prop
(* Non singleton type not containing types are interpretable in Set *)
- else if Univ.is_type0_univ level then Prop Pos
+ else if Univ.is_type0_univ level then Set
(* This is a Type with constraints *)
else Type level
in
@@ -226,8 +226,8 @@ let type_of_inductive env mip =
(* The max of an array of universes *)
let cumulate_constructor_univ u = function
- | Prop Null -> u
- | Prop Pos -> Univ.sup Univ.type0_univ u
+ | Prop -> u
+ | Set -> Univ.sup Univ.type0_univ u
| Type u' -> Univ.sup u u'
let max_inductive_sort =
@@ -797,7 +797,7 @@ let rec subterm_specif renv stack t =
| Lambda (x,a,b) ->
assert (l=[]);
- let spec,stack' = extract_stack renv a stack in
+ let spec,stack' = extract_stack stack in
subterm_specif (push_var renv (x,a,spec)) stack' b
(* Metas and evars are considered OK *)
@@ -813,7 +813,7 @@ and stack_element_specif = function
|SClosure (h_renv,h) -> lazy_subterm_specif h_renv [] h
|SArg x -> x
-and extract_stack renv a = function
+and extract_stack = function
| [] -> Lazy.from_val Not_subterm , []
| h::t -> stack_element_specif h, t
@@ -845,7 +845,7 @@ let error_illegal_rec_call renv fx (arg_renv,arg) =
let error_partial_apply renv fx =
raise (FixGuardError (renv.env,NotEnoughArgumentsForFixCall fx))
-let filter_stack_domain env ci p stack =
+let filter_stack_domain env p stack =
let absctx, ar = dest_lam_assum env p in
(* Optimization: if the predicate is not dependent, no restriction is needed
and we avoid building the recargs tree. *)
@@ -925,7 +925,7 @@ let check_one_fix renv recpos trees def =
let case_spec = branches_specif renv
(lazy_subterm_specif renv [] c_0) ci in
let stack' = push_stack_closures renv l stack in
- let stack' = filter_stack_domain renv.env ci p stack' in
+ let stack' = filter_stack_domain renv.env p stack' in
Array.iteri (fun k br' ->
let stack_br = push_stack_args case_spec.(k) stack' in
check_rec_call renv stack_br br') lrest
@@ -968,7 +968,7 @@ let check_one_fix renv recpos trees def =
| Lambda (x,a,b) ->
assert (l = []);
check_rec_call renv [] a ;
- let spec, stack' = extract_stack renv a stack in
+ let spec, stack' = extract_stack stack in
check_rec_call (push_var renv (x,a,spec)) stack' b
| Prod (x,a,b) ->
diff --git a/checker/mod_checking.ml b/checker/mod_checking.ml
index ca9581167f..6b2af71f33 100644
--- a/checker/mod_checking.ml
+++ b/checker/mod_checking.ml
@@ -2,7 +2,6 @@ open Pp
open Util
open Names
open Cic
-open Term
open Reduction
open Typeops
open Indtypes
@@ -13,17 +12,6 @@ open Environ
(** {6 Checking constants } *)
-let refresh_arity ar =
- let ctxt, hd = decompose_prod_assum ar in
- match hd with
- Sort (Type u) when not (Univ.is_univ_variable u) ->
- let ul = Univ.Level.make DirPath.empty 1 in
- let u' = Univ.Universe.make ul in
- let cst = Univ.enforce_leq u u' Univ.empty_constraint in
- let ctx = Univ.ContextSet.make (Univ.LSet.singleton ul) cst in
- mkArity (ctxt,Prop Null), ctx
- | _ -> ar, Univ.ContextSet.empty
-
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 *)
@@ -37,18 +25,13 @@ let check_constant_declaration env kn cb =
let ctx = Univ.AUContext.repr auctx in
push_context ~strict:false ctx env
in
- let envty, ty =
- let ty = cb.const_type in
- let ty', cu = refresh_arity ty in
- let envty = push_context_set cu env' in
- let _ = infer_type envty ty' in
- envty, ty
- in
- let () =
+ let ty = cb.const_type in
+ let _ = infer_type env' ty in
+ let () =
match body_of_constant cb with
| Some bd ->
- let j = infer envty bd in
- conv_leq envty j ty
+ let j = infer env' bd in
+ conv_leq env' j ty
| None -> ()
in
let env =
diff --git a/checker/modops.ml b/checker/modops.ml
index c7ad0977ac..b92d7bbf1f 100644
--- a/checker/modops.ml
+++ b/checker/modops.ml
@@ -80,7 +80,7 @@ and add_module mb env =
let add_module_type mp mtb env = add_module (module_body_of_type mp mtb) env
-let strengthen_const mp_from l cb resolver =
+let strengthen_const mp_from l cb =
match cb.const_body with
| Def _ -> cb
| _ ->
@@ -104,34 +104,34 @@ and strengthen_body : 'a. (_ -> 'a) -> _ -> _ -> 'a generic_module_body -> 'a ge
match mb.mod_type with
| MoreFunctor _ -> mb
| NoFunctor sign ->
- let resolve_out,sign_out = strengthen_sig mp_from sign mp_to mb.mod_delta
+ let resolve_out,sign_out = strengthen_sig mp_from sign mp_to
in
{ mb with
mod_expr = mk_expr mp_to;
mod_type = NoFunctor sign_out;
mod_delta = resolve_out }
-and strengthen_sig mp_from sign mp_to resolver =
+and strengthen_sig mp_from sign mp_to =
match sign with
| [] -> empty_delta_resolver,[]
| (l,SFBconst cb) :: rest ->
- let item' = l,SFBconst (strengthen_const mp_from l cb resolver) in
- let resolve_out,rest' = strengthen_sig mp_from rest mp_to resolver in
+ let item' = l,SFBconst (strengthen_const mp_from l cb) in
+ let resolve_out,rest' = strengthen_sig mp_from rest mp_to in
resolve_out,item'::rest'
| (_,SFBmind _ as item):: rest ->
- let resolve_out,rest' = strengthen_sig mp_from rest mp_to resolver in
+ let resolve_out,rest' = strengthen_sig mp_from rest mp_to in
resolve_out,item::rest'
| (l,SFBmodule mb) :: rest ->
let mp_from' = MPdot (mp_from,l) in
let mp_to' = MPdot(mp_to,l) in
let mb_out = strengthen_mod mp_from' mp_to' mb in
let item' = l,SFBmodule (mb_out) in
- let resolve_out,rest' = strengthen_sig mp_from rest mp_to resolver in
+ let resolve_out,rest' = strengthen_sig mp_from rest mp_to in
resolve_out (*add_delta_resolver resolve_out mb.mod_delta*),
- item':: rest'
- | (l,SFBmodtype mty as item) :: rest ->
- let resolve_out,rest' = strengthen_sig mp_from rest mp_to resolver in
- resolve_out,item::rest'
+ item':: rest'
+ | (_,SFBmodtype _ as item) :: rest ->
+ let resolve_out,rest' = strengthen_sig mp_from rest mp_to in
+ resolve_out,item::rest'
let strengthen mtb mp =
strengthen_body ignore mtb.mod_mp mp mtb
diff --git a/checker/print.ml b/checker/print.ml
index fc9cd687e8..247c811f80 100644
--- a/checker/print.ml
+++ b/checker/print.ml
@@ -57,8 +57,8 @@ let print_pure_constr fmt csr =
fprintf fmt "Proj(%a,@,@[%a@])" sp_con_display (Projection.constant p) pp_term c
and pp_sort fmt = function
- | Prop(Pos) -> pp_print_string fmt "Set"
- | Prop(Null) -> pp_print_string fmt "Prop"
+ | Set -> pp_print_string fmt "Set"
+ | Prop -> pp_print_string fmt "Prop"
| Type u -> fprintf fmt "Type(%a)" chk_pp (Univ.pr_uni u)
and pp_name fmt = function
diff --git a/checker/reduction.ml b/checker/reduction.ml
index 4e508dc772..d36c0ef2c9 100644
--- a/checker/reduction.ml
+++ b/checker/reduction.ml
@@ -43,7 +43,7 @@ let compare_stack_shape stk1 stk2 =
| (_, (Zupdate _|Zshift _)::s2) -> compare_rec bal stk1 s2
| (Zapp l1::s1, _) -> compare_rec (bal+Array.length l1) s1 stk2
| (_, Zapp l2::s2) -> compare_rec (bal-Array.length l2) stk1 s2
- | (Zproj (n1,m1,p1)::s1, Zproj (n2,m2,p2)::s2) ->
+ | (Zproj p1::s1, Zproj p2::s2) ->
Int.equal bal 0 && compare_rec 0 s1 s2
| ((ZcaseT(c1,_,_,_))::s1,
(ZcaseT(c2,_,_,_))::s2) ->
@@ -55,7 +55,7 @@ let compare_stack_shape stk1 stk2 =
type lft_constr_stack_elt =
Zlapp of (lift * fconstr) array
- | Zlproj of Names.Projection.t * lift
+ | Zlproj of Names.Projection.Repr.t * lift
| Zlfix of (lift * fconstr) * lft_constr_stack
| Zlcase of case_info * lift * fconstr * fconstr array
and lft_constr_stack = lft_constr_stack_elt list
@@ -74,8 +74,8 @@ let pure_stack lfts stk =
| (Zshift n,(l,pstk)) -> (el_shft n l, pstk)
| (Zapp a, (l,pstk)) ->
(l,zlapp (Array.map (fun t -> (l,t)) a) pstk)
- | (Zproj (n,m,c), (l,pstk)) ->
- (l, Zlproj (c,l)::pstk)
+ | (Zproj p, (l,pstk)) ->
+ (l, Zlproj (p,l)::pstk)
| (Zfix(fx,a),(l,pstk)) ->
let (lfx,pa) = pure_rec l a in
(l, Zlfix((lfx,fx),pa)::pstk)
@@ -133,7 +133,7 @@ let convert_universes univ u u' =
if Univ.Instance.check_eq univ u u' then ()
else raise NotConvertible
-let compare_stacks f fmind lft1 stk1 lft2 stk2 =
+let compare_stacks f fmind fproj lft1 stk1 lft2 stk2 =
let rec cmp_rec pstk1 pstk2 =
match (pstk1,pstk2) with
| (z1::s1, z2::s2) ->
@@ -143,10 +143,8 @@ let compare_stacks f fmind lft1 stk1 lft2 stk2 =
| (Zlfix(fx1,a1),Zlfix(fx2,a2)) ->
f fx1 fx2; cmp_rec a1 a2
| (Zlproj (c1,l1),Zlproj (c2,l2)) ->
- if not (Names.Constant.UserOrd.equal
- (Names.Projection.constant c1)
- (Names.Projection.constant c2)) then
- raise NotConvertible
+ if not (fproj c1 c2) then
+ raise NotConvertible
| (Zlcase(ci1,l1,p1,br1),Zlcase(ci2,l2,p2,br2)) ->
if not (fmind ci1.ci_ind ci2.ci_ind) then
raise NotConvertible;
@@ -210,29 +208,26 @@ let convert_constructors
let sort_cmp env univ pb s0 s1 =
match (s0,s1) with
- | (Prop c1, Prop c2) when pb = CUMUL -> if c1 = Pos && c2 = Null then raise NotConvertible
- | (Prop c1, Prop c2) -> if c1 <> c2 then raise NotConvertible
- | (Prop c1, Type u) ->
+ | Prop, Prop | Set, Set -> ()
+ | Prop, (Set | Type _) | Set, Type _ ->
+ if not (pb = CUMUL) then raise NotConvertible
+ | Type u1, Type u2 ->
+ (** FIXME: handle type-in-type option here *)
+ if (* snd (engagement env) == StratifiedType && *)
+ not
(match pb with
- CUMUL -> ()
- | _ -> raise NotConvertible)
- | (Type u1, Type u2) ->
- (** FIXME: handle type-in-type option here *)
- if (* snd (engagement env) == StratifiedType && *)
- not
- (match pb with
- | CONV -> Univ.check_eq univ u1 u2
- | CUMUL -> Univ.check_leq univ u1 u2)
- then begin
- if !Flags.debug then begin
- let op = match pb with CONV -> "=" | CUMUL -> "<=" in
- Format.eprintf "sort_cmp: @[%a@]\n%!" Pp.pp_with Pp.(
- str"Error: " ++ Univ.pr_uni u1 ++ str op ++ Univ.pr_uni u2 ++ str ":" ++ cut()
- ++ Univ.pr_universes univ)
- end;
- raise NotConvertible
- end
- | (_, _) -> raise NotConvertible
+ | CONV -> Univ.check_eq univ u1 u2
+ | CUMUL -> Univ.check_leq univ u1 u2)
+ then begin
+ if !Flags.debug then begin
+ let op = match pb with CONV -> "=" | CUMUL -> "<=" in
+ Format.eprintf "sort_cmp: @[%a@]\n%!" Pp.pp_with Pp.(
+ str"Error: " ++ Univ.pr_uni u1 ++ str op ++ Univ.pr_uni u2 ++ str ":" ++ cut()
+ ++ Univ.pr_universes univ)
+ end;
+ raise NotConvertible
+ end
+ | Set, Prop | Type _, (Prop | Set) -> raise NotConvertible
let rec no_arg_available = function
| [] -> true
@@ -260,7 +255,7 @@ let rec no_case_available = function
| Zupdate _ :: stk -> no_case_available stk
| Zshift _ :: stk -> no_case_available stk
| Zapp _ :: stk -> no_case_available stk
- | Zproj (_,_,_) :: _ -> false
+ | Zproj _ :: _ -> false
| ZcaseT _ :: _ -> false
| Zfix _ :: _ -> true
@@ -303,6 +298,10 @@ let eq_table_key univ =
Constant.UserOrd.equal c1 c2 &&
Univ.Instance.check_eq univ u1 u2)
+let proj_equiv_infos infos p1 p2 =
+ Int.equal (Projection.Repr.arg p1) (Projection.Repr.arg p2) &&
+ mind_equiv (infos_env infos) (Projection.Repr.inductive p1) (Projection.Repr.inductive p2)
+
(* Conversion between [lft1]term1 and [lft2]term2 *)
let rec ccnv univ cv_pb infos lft1 lft2 term1 term2 =
eqappr univ cv_pb infos (lft1, (term1,[])) (lft2, (term2,[]))
@@ -526,7 +525,7 @@ and eqappr univ cv_pb infos (lft1,st1) (lft2,st2) =
and convert_stacks univ infos lft1 lft2 stk1 stk2 =
compare_stacks
(fun (l1,t1) (l2,t2) -> ccnv univ CONV infos l1 l2 t1 t2)
- (mind_equiv_infos infos)
+ (mind_equiv_infos infos) (proj_equiv_infos infos)
lft1 stk1 lft2 stk2
and convert_vect univ infos lft1 lft2 v1 v2 =
diff --git a/checker/subtyping.ml b/checker/subtyping.ml
index a22af4e0f7..0916d98ddf 100644
--- a/checker/subtyping.ml
+++ b/checker/subtyping.ml
@@ -9,11 +9,9 @@
(************************************************************************)
(*i*)
-open CErrors
open Util
open Names
open Cic
-open Term
open Declarations
open Environ
open Reduction
@@ -124,48 +122,7 @@ let check_inductive env mp1 l info1 mib2 spec2 subst1 subst2=
env, Univ.make_abstract_instance auctx'
| _ -> error ()
in
- let eq_projection_body p1 p2 =
- let check eq f = if not (eq (f p1) (f p2)) then error () in
- check eq_ind (fun x -> x.proj_ind);
- check (==) (fun x -> x.proj_npars);
- check (==) (fun x -> x.proj_arg);
- check (eq_constr) (fun x -> x.proj_type);
- true
- in
- let check_inductive_type t1 t2 =
-
- (* Due to template polymorphism, the conclusions of
- t1 and t2, if in Type, are generated as the least upper bounds
- of the types of the constructors.
-
- By monotonicity of the infered l.u.b. wrt subtyping (i.e. if X:U
- |- T(X):s and |- M:U' and U'<=U then infer_type(T(M))<=s), each
- universe in the conclusion of t1 has an bounding universe in
- the conclusion of t2, so that we don't need to check the
- subtyping of the conclusions of t1 and t2.
-
- Even if we'd like to recheck it, the inference of constraints
- is not designed to deal with algebraic constraints of the form
- max-univ(u1..un) <= max-univ(u'1..u'n), so that it is not easy
- to recheck it (in short, we would need the actual graph of
- constraints as input while type checking is currently designed
- to output a set of constraints instead) *)
-
- (* So we cheat and replace the subtyping problem on algebraic
- constraints of the form max-univ(u1..un) <= max-univ(u'1..u'n)
- (that we know are necessary true) by trivial constraints that
- the constraint generator knows how to deal with *)
-
- let (ctx1,s1) = dest_arity env t1 in
- let (ctx2,s2) = dest_arity env t2 in
- let s1,s2 =
- match s1, s2 with
- | Type _, Type _ -> (* shortcut here *) Prop Null, Prop Null
- | (Prop _, Type _) | (Type _,Prop _) -> error ()
- | _ -> (s1, s2) in
- check_conv conv_leq env
- (mkArity (ctx1,s1)) (mkArity (ctx2,s2))
- in
+ let check_inductive_type t1 t2 = check_conv conv_leq env t1 t2 in
let check_packet p1 p2 =
let check eq f = if not (eq (f p1) (f p2)) then error () in
@@ -222,9 +179,9 @@ let check_inductive env mp1 l info1 mib2 spec2 subst1 subst2=
| FakeRecord, FakeRecord -> true
| PrimRecord info1, PrimRecord info2 ->
let check (id1, p1, pb1) (id2, p2, pb2) =
- Id.equal id1 id2 &&
- Array.for_all2 Constant.UserOrd.equal p1 p2 &&
- Array.for_all2 eq_projection_body pb1 pb2
+ (* we don't care about the id, the types are inferred from the inductive
+ (ie checked before now) *)
+ Array.for_all2 Label.equal p1 p2
in
Array.equal check info1 info2
| _, _ -> false
@@ -251,55 +208,10 @@ let check_inductive env mp1 l info1 mib2 spec2 subst1 subst2=
let _ = Array.map2_i check_cons_types mib1.mind_packets mib2.mind_packets
in ()
-let check_constant env mp1 l info1 cb2 spec2 subst1 subst2 =
+let check_constant env l info1 cb2 spec2 subst1 subst2 =
let error () = error_not_match l spec2 in
let check_conv f = check_conv_error error f in
- let check_type env t1 t2 =
-
- (* If the type of a constant is generated, it may mention
- non-variable algebraic universes that the general conversion
- algorithm is not ready to handle. Anyway, generated types of
- constants are functions of the body of the constant. If the
- bodies are the same in environments that are subtypes one of
- the other, the types are subtypes too (i.e. if Gamma <= Gamma',
- Gamma |- A |> T, Gamma |- A' |> T' and Gamma |- A=A' then T <= T').
- Hence they don't have to be checked again *)
-
- let t1,t2 =
- if isArity t2 then
- let (ctx2,s2) = destArity t2 in
- match s2 with
- | Type v when not (Univ.is_univ_variable v) ->
- (* The type in the interface is inferred and is made of algebraic
- universes *)
- begin try
- let (ctx1,s1) = dest_arity env t1 in
- match s1 with
- | Type u when not (Univ.is_univ_variable u) ->
- (* Both types are inferred, no need to recheck them. We
- cheat and collapse the types to Prop *)
- mkArity (ctx1,Prop Null), mkArity (ctx2,Prop Null)
- | Prop _ ->
- (* The type in the interface is inferred, it may be the case
- that the type in the implementation is smaller because
- the body is more reduced. We safely collapse the upper
- type to Prop *)
- mkArity (ctx1,Prop Null), mkArity (ctx2,Prop Null)
- | Type _ ->
- (* The type in the interface is inferred and the type in the
- implementation is not inferred or is inferred but from a
- more reduced body so that it is just a variable. Since
- constraints of the form "univ <= max(...)" are not
- expressible in the system of algebraic universes: we fail
- (the user has to use an explicit type in the interface *)
- error ()
- with UserError _ (* "not an arity" *) ->
- error () end
- | _ -> t1,t2
- else
- (t1,t2) in
- check_conv conv_leq env t1 t2
- in
+ let check_type env t1 t2 = check_conv conv_leq env t1 t2 in
match info1 with
| Constant cb1 ->
let cb1 = subst_const_body subst1 cb1 in
@@ -360,7 +272,7 @@ and check_signatures env mp1 sig1 sig2 subst1 subst2 =
let check_one_body (l,spec2) =
match spec2 with
| SFBconst cb2 ->
- check_constant env mp1 l (get_obj mp1 map1 l)
+ check_constant env l (get_obj mp1 map1 l)
cb2 spec2 subst1 subst2
| SFBmind mib2 ->
check_inductive env mp1 l (get_obj mp1 map1 l)
diff --git a/checker/term.ml b/checker/term.ml
index 509634bdba..d84491b38f 100644
--- a/checker/term.ml
+++ b/checker/term.ml
@@ -20,15 +20,15 @@ open Cic
(* Sorts. *)
let family_of_sort = function
- | Prop Null -> InProp
- | Prop Pos -> InSet
+ | Prop -> InProp
+ | Set -> InSet
| Type _ -> InType
let family_equal = (==)
let sort_of_univ u =
- if Univ.is_type0m_univ u then Prop Null
- else if Univ.is_type0_univ u then Prop Pos
+ if Univ.is_type0m_univ u then Prop
+ else if Univ.is_type0_univ u then Set
else Type u
(********************************************************************)
@@ -356,15 +356,11 @@ let rec isArity c =
(* alpha conversion : ignore print names and casts *)
let compare_sorts s1 s2 = match s1, s2 with
-| Prop c1, Prop c2 ->
- begin match c1, c2 with
- | Pos, Pos | Null, Null -> true
- | Pos, Null -> false
- | Null, Pos -> false
- end
+| Prop, Prop | Set, Set -> true
| Type u1, Type u2 -> Univ.Universe.equal u1 u2
-| Prop _, Type _ -> false
-| Type _, Prop _ -> false
+| Prop, Set | Set, Prop -> false
+| (Prop | Set), Type _ -> false
+| Type _, (Prop | Set) -> false
let eq_puniverses f (c1,u1) (c2,u2) =
Univ.Instance.equal u1 u2 && f c1 c2
diff --git a/checker/typeops.ml b/checker/typeops.ml
index 345ee5b8ff..138fe8bc95 100644
--- a/checker/typeops.ml
+++ b/checker/typeops.ml
@@ -103,11 +103,11 @@ let judge_of_apply env (f,funj) argjv =
let sort_of_product env domsort rangsort =
match (domsort, rangsort) with
(* Product rule (s,Prop,Prop) *)
- | (_, Prop Null) -> rangsort
+ | _, Prop -> rangsort
(* Product rule (Prop/Set,Set,Set) *)
- | (Prop _, Prop Pos) -> rangsort
+ | (Prop | Set), Set -> rangsort
(* Product rule (Type,Set,?) *)
- | (Type u1, Prop Pos) ->
+ | Type u1, Set ->
if engagement env = ImpredicativeSet then
(* Rule is (Type,Set,Set) in the Set-impredicative calculus *)
rangsort
@@ -115,11 +115,11 @@ let sort_of_product env domsort rangsort =
(* Rule is (Type_i,Set,Type_i) in the Set-predicative calculus *)
Type (Univ.sup u1 Univ.type0_univ)
(* Product rule (Prop,Type_i,Type_i) *)
- | (Prop Pos, Type u2) -> Type (Univ.sup Univ.type0_univ u2)
+ | Set, Type u2 -> Type (Univ.sup Univ.type0_univ u2)
(* Product rule (Prop,Type_i,Type_i) *)
- | (Prop Null, Type _) -> rangsort
+ | Prop, Type _ -> rangsort
(* Product rule (Type_i,Type_i,Type_i) *)
- | (Type u1, Type u2) -> Type (Univ.sup u1 u2)
+ | Type u1, Type u2 -> Type (Univ.sup u1 u2)
(* Type of a type cast *)
@@ -198,14 +198,13 @@ let judge_of_case env ci pj (c,cj) lfj =
(* Projection. *)
let judge_of_projection env p c ct =
- let pb = lookup_projection p env in
+ let pty = lookup_projection p env in
let (ind,u), args =
try find_rectype env ct
with Not_found -> error_case_not_inductive env (c, ct)
in
- assert(eq_ind pb.proj_ind ind);
- let ty = subst_instance_constr u pb.proj_type in
- substl (c :: List.rev args) ty
+ let ty = subst_instance_constr u pty in
+ substl (c :: List.rev args) ty
(* Fixpoints. *)
@@ -239,7 +238,7 @@ let type_fixpoint env lna lar lbody vdefj =
let rec execute env cstr =
match cstr with
(* Atomic terms *)
- | Sort (Prop _) -> judge_of_prop
+ | Sort (Prop | Set) -> judge_of_prop
| Sort (Type u) -> judge_of_type u
diff --git a/checker/univ.ml b/checker/univ.ml
index 15673736f2..e50e883adf 100644
--- a/checker/univ.ml
+++ b/checker/univ.ml
@@ -190,13 +190,6 @@ struct
(let (u,n) = x and (v,n') = y in
Int.equal n n' && Level.equal u v)
- let leq (u,n) (v,n') =
- let cmp = Level.compare u v in
- if Int.equal cmp 0 then n <= n'
- else if n <= n' then
- (Level.is_prop u && Level.is_small v)
- else false
-
let successor (u,n) =
if Level.is_prop u then type1
else (u, n + 1)
@@ -833,41 +826,6 @@ type 'a constrained = 'a * constraints
type 'a constraint_function = 'a -> 'a -> constraints -> constraints
-let constraint_add_leq v u c =
- (* We just discard trivial constraints like u<=u *)
- if Expr.equal v u then c
- else
- match v, u with
- | (x,n), (y,m) ->
- let j = m - n in
- if j = -1 (* n = m+1, v+1 <= u <-> v < u *) then
- Constraint.add (x,Lt,y) c
- else if j <= -1 (* n = m+k, v+k <= u <-> v+(k-1) < u *) then
- if Level.equal x y then (* u+(k+1) <= u *)
- raise (UniverseInconsistency (Le, Universe.tip v, Universe.tip u))
- else anomaly (Pp.str"Unable to handle arbitrary u+k <= v constraints.")
- else if j = 0 then
- Constraint.add (x,Le,y) c
- else (* j >= 1 *) (* m = n + k, u <= v+k *)
- if Level.equal x y then c (* u <= u+k, trivial *)
- else if Level.is_small x then c (* Prop,Set <= u+S k, trivial *)
- else anomaly (Pp.str"Unable to handle arbitrary u <= v+k constraints.")
-
-let check_univ_leq_one u v = Universe.exists (Expr.leq u) v
-
-let check_univ_leq u v =
- Universe.for_all (fun u -> check_univ_leq_one u v) u
-
-let enforce_leq u v c =
- match v with
- | [v] ->
- List.fold_right (fun u -> constraint_add_leq u v) u c
- | _ -> anomaly (Pp.str"A universe bound can only be a variable.")
-
-let enforce_leq u v c =
- if check_univ_leq u v then c
- else enforce_leq u v c
-
let check_constraint g (l,d,r) =
match d with
| Eq -> check_equal g l r
diff --git a/checker/univ.mli b/checker/univ.mli
index 6cd3b36382..3b29b158f2 100644
--- a/checker/univ.mli
+++ b/checker/univ.mli
@@ -109,8 +109,6 @@ type 'a constrained = 'a * constraints
type 'a constraint_function = 'a -> 'a -> constraints -> constraints
-val enforce_leq : universe constraint_function
-
(** {6 ... } *)
(** Merge of constraints in a universes graph.
The function [merge_constraints] merges a set of constraints in a given
diff --git a/checker/values.ml b/checker/values.ml
index 4f28d6e448..e1b5a949ac 100644
--- a/checker/values.ml
+++ b/checker/values.ml
@@ -15,7 +15,7 @@
To ensure this file is up-to-date, 'make' now compares the md5 of cic.mli
with a copy we maintain here:
-MD5 42fb0781dc5f7f2cbe3ca127f8249264 checker/cic.mli
+MD5 f7b267579138eabf86a74d6f2a7ed794 checker/cic.mli
*)
@@ -122,7 +122,7 @@ let v_context_set = v_tuple "universe_context_set" [|v_hset v_level;v_cstrs|]
(** kernel/term *)
-let v_sort = v_sum "sort" 0 [|[|v_enum "cnt" 2|];[|v_univ|]|]
+let v_sort = v_sum "sort" 2 (*Prop, Set*) [|[|v_univ(*Type*)|]|]
let v_sortfam = v_enum "sorts_family" 3
let v_puniverses v = v_tuple "punivs" [|v;v_instance|]
@@ -135,7 +135,9 @@ let v_caseinfo =
v_tuple "case_info" [|v_ind;Int;Array Int;Array Int;v_cprint|]
let v_cast = v_enum "cast_kind" 4
-let v_proj = v_tuple "projection" [|v_cst; v_bool|]
+
+let v_proj_repr = v_tuple "projection_repr" [|v_ind;Int;Int;v_id|]
+let v_proj = v_tuple "projection" [|v_proj_repr; v_bool|]
let rec v_constr =
Sum ("constr",0,[|
@@ -223,12 +225,8 @@ let v_cst_def =
v_sum "constant_def" 0
[|[|Opt Int|]; [|v_cstr_subst|]; [|v_lazy_constr|]|]
-let v_projbody =
- v_tuple "projection_body"
- [|v_ind;Int;Int;v_constr|]
-
let v_typing_flags =
- v_tuple "typing_flags" [|v_bool; v_bool; v_oracle|]
+ v_tuple "typing_flags" [|v_bool; v_bool; v_oracle; v_bool|]
let v_const_univs = v_sum "constant_universes" 0 [|[|v_context_set|]; [|v_abs_context|]|]
@@ -277,7 +275,7 @@ let v_finite = v_enum "recursivity_kind" 3
let v_record_info =
v_sum "record_info" 2
- [| [| Array (v_tuple "record" [| v_id; Array v_cst; Array v_projbody |]) |] |]
+ [| [| Array (v_tuple "record" [| v_id; Array v_id; Array v_constr |]) |] |]
let v_ind_pack_univs =
v_sum "abstract_inductive_universes" 0
diff --git a/clib/cArray.ml b/clib/cArray.ml
index fc87a74cf6..d509c55b9a 100644
--- a/clib/cArray.ml
+++ b/clib/cArray.ml
@@ -59,6 +59,7 @@ sig
('a -> 'b -> 'c -> 'd) -> 'a array -> 'b array -> 'c array -> 'd array
val map_left : ('a -> 'b) -> 'a array -> 'b array
val iter2 : ('a -> 'b -> unit) -> 'a array -> 'b array -> unit
+ val iter2_i : (int -> 'a -> 'b -> unit) -> 'a array -> 'b array -> unit
val fold_left_map : ('a -> 'b -> 'a * 'c) -> 'a -> 'b array -> 'a * 'c array
val fold_right_map : ('a -> 'c -> 'b * 'c) -> 'a array -> 'c -> 'b array * 'c
val fold_left2_map : ('a -> 'b -> 'c -> 'a * 'd) -> 'a -> 'b array -> 'c array -> 'a * 'd array
@@ -407,6 +408,12 @@ let iter2 f v1 v2 =
let () = if not (Int.equal len2 len1) then invalid_arg "Array.iter2" in
for i = 0 to len1 - 1 do f (uget v1 i) (uget v2 i) done
+let iter2_i f v1 v2 =
+ let len1 = Array.length v1 in
+ let len2 = Array.length v2 in
+ let () = if not (Int.equal len2 len1) then invalid_arg "Array.iter2" in
+ for i = 0 to len1 - 1 do f i (uget v1 i) (uget v2 i) done
+
let pure_functional = false
let fold_right_map f v e =
diff --git a/clib/cArray.mli b/clib/cArray.mli
index 8bf33f82f9..5c7e09eeac 100644
--- a/clib/cArray.mli
+++ b/clib/cArray.mli
@@ -101,6 +101,9 @@ sig
val iter2 : ('a -> 'b -> unit) -> 'a array -> 'b array -> unit
(** Iter on two arrays. Raise [Invalid_argument "Array.iter2"] if sizes differ. *)
+ val iter2_i : (int -> 'a -> 'b -> unit) -> 'a array -> 'b array -> unit
+ (** Iter on two arrays. Raise [Invalid_argument "Array.iter2_i"] if sizes differ. *)
+
val fold_left_map : ('a -> 'b -> 'a * 'c) -> 'a -> 'b array -> 'a * 'c array
(** [fold_left_map f e_0 [|l_1...l_n|] = e_n,[|k_1...k_n|]]
where [(e_i,k_i)=f e_{i-1} l_i]; see also [Smart.fold_left_map] *)
diff --git a/clib/cList.ml b/clib/cList.ml
index 2b627f7457..dc59ff2970 100644
--- a/clib/cList.ml
+++ b/clib/cList.ml
@@ -60,6 +60,7 @@ sig
val extend : bool list -> 'a -> 'a list -> 'a list
val count : ('a -> bool) -> 'a list -> int
val index : 'a eq -> 'a -> 'a list -> int
+ val safe_index : 'a eq -> 'a -> 'a list -> int option
val index0 : 'a eq -> 'a -> 'a list -> int
val fold_left_until : ('c -> 'a -> 'c CSig.until) -> 'c -> 'a list -> 'c
val fold_right_i : (int -> 'a -> 'b -> 'b) -> int -> 'a list -> 'b -> 'b
@@ -122,6 +123,7 @@ sig
val duplicates : 'a eq -> 'a list -> 'a list
val uniquize : 'a list -> 'a list
val sort_uniquize : 'a cmp -> 'a list -> 'a list
+ val min : 'a cmp -> 'a list -> 'a
val cartesian : ('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list
val cartesians : ('a -> 'b -> 'b) -> 'b -> 'a list list -> 'b list
val combinations : 'a list list -> 'a list list
@@ -537,6 +539,8 @@ let rec index_f f x l n = match l with
let index f x l = index_f f x l 1
+let safe_index f x l = try Some (index f x l) with Not_found -> None
+
let index0 f x l = index_f f x l 0
(** {6 Folding} *)
@@ -971,6 +975,15 @@ let rec uniquize_sorted cmp = function
let sort_uniquize cmp l =
uniquize_sorted cmp (List.sort cmp l)
+let min cmp l =
+ let rec aux cur = function
+ | [] -> cur
+ | x :: l -> if cmp x cur < 0 then aux x l else aux cur l
+ in
+ match l with
+ | x :: l -> aux x l
+ | [] -> raise Not_found
+
let rec duplicates cmp = function
| [] -> []
| x :: l ->
diff --git a/clib/cList.mli b/clib/cList.mli
index 13e069e94c..ed468cb977 100644
--- a/clib/cList.mli
+++ b/clib/cList.mli
@@ -155,6 +155,10 @@ sig
val index : 'a eq -> 'a -> 'a list -> int
(** [index] returns the 1st index of an element in a list (counting from 1). *)
+ val safe_index : 'a eq -> 'a -> 'a list -> int option
+ (** [safe_index] returns the 1st index of an element in a list (counting from 1)
+ and None otherwise. *)
+
val index0 : 'a eq -> 'a -> 'a list -> int
(** [index0] behaves as [index] except that it starts counting at 0. *)
@@ -376,6 +380,11 @@ sig
(** Return a sorted version of a list without duplicates
according to some comparison function. *)
+ val min : 'a cmp -> 'a list -> 'a
+ (** Return minimum element according to some comparison function.
+
+ @raise Not_found on an empty list. *)
+
(** {6 Cartesian product} *)
val cartesian : ('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list
diff --git a/clib/clib.mllib b/clib/clib.mllib
index afece4074c..5a2c9a9ce9 100644
--- a/clib/clib.mllib
+++ b/clib/clib.mllib
@@ -37,3 +37,5 @@ Backtrace
IStream
Terminal
Monad
+
+Diff2
diff --git a/clib/diff2.ml b/clib/diff2.ml
new file mode 100644
index 0000000000..42c4733fed
--- /dev/null
+++ b/clib/diff2.ml
@@ -0,0 +1,158 @@
+(* copied from https://github.com/leque/ocaml-diff.git and renamed from "diff.ml" *)
+
+(*
+ * Copyright (C) 2016 OOHASHI Daichi
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *)
+
+type 'a common =
+ [ `Common of int * int * 'a ]
+
+type 'a edit =
+ [ `Added of int * 'a
+ | `Removed of int * 'a
+ | 'a common
+ ]
+
+module type SeqType = sig
+ type t
+ type elem
+ val get : t -> int -> elem
+ val length : t -> int
+end
+
+module type S = sig
+ type t
+ type elem
+
+ val lcs :
+ ?equal:(elem -> elem -> bool) ->
+ t -> t -> elem common list
+
+ val diff :
+ ?equal:(elem -> elem -> bool) ->
+ t -> t -> elem edit list
+
+ val fold_left :
+ ?equal:(elem -> elem -> bool) ->
+ f:('a -> elem edit -> 'a) ->
+ init:'a ->
+ t -> t -> 'a
+
+ val iter :
+ ?equal:(elem -> elem -> bool) ->
+ f:(elem edit -> unit) ->
+ t -> t -> unit
+end
+
+module Make(M : SeqType) : (S with type t = M.t and type elem = M.elem) = struct
+ type t = M.t
+ type elem = M.elem
+
+ let lcs ?(equal = (=)) a b =
+ let n = M.length a in
+ let m = M.length b in
+ let mn = m + n in
+ let sz = 2 * mn + 1 in
+ let vd = Array.make sz 0 in
+ let vl = Array.make sz 0 in
+ let vr = Array.make sz [] in
+ let get v i = Array.get v (i + mn) in
+ let set v i x = Array.set v (i + mn) x in
+ let finish () =
+ let rec loop i maxl r =
+ if i > mn then
+ List.rev r
+ else if get vl i > maxl then
+ loop (i + 1) (get vl i) (get vr i)
+ else
+ loop (i + 1) maxl r
+ in loop (- mn) 0 []
+ in
+ if mn = 0 then
+ []
+ else
+ (* For d <- 0 to mn Do *)
+ let rec dloop d =
+ assert (d <= mn);
+ (* For k <- -d to d in steps of 2 Do *)
+ let rec kloop k =
+ if k > d then
+ dloop @@ d + 1
+ else
+ let x, l, r =
+ if k = -d || (k <> d && get vd (k - 1) < get vd (k + 1)) then
+ get vd (k + 1), get vl (k + 1), get vr (k + 1)
+ else
+ get vd (k - 1) + 1, get vl (k - 1), get vr (k - 1)
+ in
+ let x, y, l, r =
+ let rec xyloop x y l r =
+ if x < n && y < m && equal (M.get a x) (M.get b y) then
+ xyloop (x + 1) (y + 1) (l + 1) (`Common(x, y, M.get a x) :: r)
+ else
+ x, y, l, r
+ in xyloop x (x - k) l r
+ in
+ set vd k x;
+ set vl k l;
+ set vr k r;
+ if x >= n && y >= m then
+ (* Stop *)
+ finish ()
+ else
+ kloop @@ k + 2
+ in kloop @@ -d
+ in dloop 0
+
+ let fold_left ?(equal = (=)) ~f ~init a b =
+ let ff x y = f y x in
+ let fold_map f g x from to_ init =
+ let rec loop i init =
+ if i >= to_ then
+ init
+ else
+ loop (i + 1) (f (g i @@ M.get x i) init)
+ in loop from init
+ in
+ let added i x = `Added (i, x) in
+ let removed i x = `Removed (i, x) in
+ let rec loop cs apos bpos init =
+ match cs with
+ | [] ->
+ init
+ |> fold_map ff removed a apos (M.length a)
+ |> fold_map ff added b bpos (M.length b)
+ | `Common (aoff, boff, _) as e :: rest ->
+ init
+ |> fold_map ff removed a apos aoff
+ |> fold_map ff added b bpos boff
+ |> ff e
+ |> loop rest (aoff + 1) (boff + 1)
+ in loop (lcs ~equal a b) 0 0 init
+
+ let diff ?(equal = (=)) a b =
+ fold_left ~equal ~f:(fun xs x -> x::xs) ~init:[] a b
+
+ let iter ?(equal = (=)) ~f a b =
+ fold_left a b
+ ~equal
+ ~f:(fun () x -> f x)
+ ~init:()
+end
diff --git a/clib/diff2.mli b/clib/diff2.mli
new file mode 100644
index 0000000000..a085f4ffe8
--- /dev/null
+++ b/clib/diff2.mli
@@ -0,0 +1,101 @@
+(* copied from https://github.com/leque/ocaml-diff.git and renamed from "diff.mli" *)
+(**
+ An implementation of Eugene Myers' O(ND) Difference Algorithm\[1\].
+ This implementation is a port of util.lcs module of
+ {{:http://practical-scheme.net/gauche} Gauche Scheme interpreter}.
+
+ - \[1\] Eugene Myers, An O(ND) Difference Algorithm and Its Variations, Algorithmica Vol. 1 No. 2, pp. 251-266, 1986.
+ *)
+
+type 'a common = [
+ `Common of int * int * 'a
+ ]
+(** an element of lcs of seq1 and seq2 *)
+
+type 'a edit =
+ [ `Removed of int * 'a
+ | `Added of int * 'a
+ | 'a common
+ ]
+(** an element of diff of seq1 and seq2. *)
+
+module type SeqType = sig
+ type t
+ (** The type of the sequence. *)
+
+ type elem
+ (** The type of the elements of the sequence. *)
+
+ val get : t -> int -> elem
+ (** [get t n] returns [n]-th element of the sequence [t]. *)
+
+ val length : t -> int
+ (** [length t] returns the length of the sequence [t]. *)
+end
+(** Input signature of {!Diff.Make}. *)
+
+module type S = sig
+ type t
+ (** The type of input sequence. *)
+
+ type elem
+ (** The type of the elements of result / input sequence. *)
+
+ val lcs :
+ ?equal:(elem -> elem -> bool) ->
+ t -> t -> elem common list
+ (**
+ [lcs ~equal seq1 seq2] computes the LCS (longest common sequence) of
+ [seq1] and [seq2].
+ Elements of [seq1] and [seq2] are compared with [equal].
+ [equal] defaults to [Pervasives.(=)].
+
+ Elements of lcs are [`Common (pos1, pos2, e)]
+ where [e] is an element, [pos1] is a position in [seq1],
+ and [pos2] is a position in [seq2].
+ *)
+
+ val diff :
+ ?equal:(elem -> elem -> bool) ->
+ t -> t -> elem edit list
+ (**
+ [diff ~equal seq1 seq2] computes the diff of [seq1] and [seq2].
+ Elements of [seq1] and [seq2] are compared with [equal].
+
+ Elements only in [seq1] are represented as [`Removed (pos, e)]
+ where [e] is an element, and [pos] is a position in [seq1];
+ those only in [seq2] are represented as [`Added (pos, e)]
+ where [e] is an element, and [pos] is a position in [seq2];
+ those common in [seq1] and [seq2] are represented as
+ [`Common (pos1, pos2, e)]
+ where [e] is an element, [pos1] is a position in [seq1],
+ and [pos2] is a position in [seq2].
+ *)
+
+ val fold_left :
+ ?equal:(elem -> elem -> bool) ->
+ f:('a -> elem edit -> 'a) ->
+ init:'a ->
+ t -> t -> 'a
+ (**
+ [fold_left ~equal ~f ~init seq1 seq2] is same as
+ [diff ~equal seq1 seq2 |> ListLabels.fold_left ~f ~init],
+ but does not create an intermediate list.
+ *)
+
+ val iter :
+ ?equal:(elem -> elem -> bool) ->
+ f:(elem edit -> unit) ->
+ t -> t -> unit
+ (**
+ [iter ~equal ~f seq1 seq2] is same as
+ [diff ~equal seq1 seq2 |> ListLabels.iter ~f],
+ but does not create an intermediate list.
+ *)
+end
+(** Output signature of {!Diff.Make}. *)
+
+module Make :
+ functor (M : SeqType) -> (S with type t = M.t and type elem = M.elem)
+(** Functor building an implementation of the diff structure
+ given a sequence type. *)
diff --git a/clib/terminal.ml b/clib/terminal.ml
index 1d9468137b..d243d6599e 100644
--- a/clib/terminal.ml
+++ b/clib/terminal.ml
@@ -59,6 +59,19 @@ let default = {
suffix = None;
}
+let reset = "\027[0m"
+
+let reset_style = {
+ fg_color = Some `DEFAULT;
+ bg_color = Some `DEFAULT;
+ bold = Some false;
+ italic = Some false;
+ underline = Some false;
+ negative = Some false;
+ prefix = None;
+ suffix = None;
+}
+
let make ?fg_color ?bg_color ?bold ?italic ?underline ?negative ?style ?prefix ?suffix () =
let st = match style with
| None -> default
@@ -87,6 +100,25 @@ let merge s1 s2 =
suffix = set s1.suffix s2.suffix;
}
+let diff s1 s2 =
+ let diff_op o1 o2 reset_val = match o1 with
+ | None -> o2
+ | Some _ ->
+ match o2 with
+ | None -> reset_val
+ | Some _ -> if o1 = o2 then None else o2 in
+
+ {
+ fg_color = diff_op s1.fg_color s2.fg_color reset_style.fg_color;
+ bg_color = diff_op s1.bg_color s2.bg_color reset_style.bg_color;
+ bold = diff_op s1.bold s2.bold reset_style.bold;
+ italic = diff_op s1.italic s2.italic reset_style.italic;
+ underline = diff_op s1.underline s2.underline reset_style.underline;
+ negative = diff_op s1.negative s2.negative reset_style.negative;
+ prefix = diff_op s1.prefix s2.prefix reset_style.prefix;
+ suffix = diff_op s1.suffix s2.suffix reset_style.suffix;
+ }
+
let base_color = function
| `DEFAULT -> 9
| `BLACK -> 0
@@ -167,20 +199,8 @@ let repr st =
let eval st =
let tags = repr st in
let tags = List.map string_of_int tags in
- Printf.sprintf "\027[%sm" (String.concat ";" tags)
-
-let reset = "\027[0m"
-
-let reset_style = {
- fg_color = Some `DEFAULT;
- bg_color = Some `DEFAULT;
- bold = Some false;
- italic = Some false;
- underline = Some false;
- negative = Some false;
- prefix = None;
- suffix = None;
-}
+ if List.length tags = 0 then "" else
+ Printf.sprintf "\027[%sm" (String.concat ";" tags)
let has_style t =
Unix.isatty t && Sys.os_type = "Unix"
diff --git a/clib/terminal.mli b/clib/terminal.mli
index dbf8d4640c..bc30b0016f 100644
--- a/clib/terminal.mli
+++ b/clib/terminal.mli
@@ -51,6 +51,9 @@ val make : ?fg_color:color -> ?bg_color:color ->
val merge : style -> style -> style
(** [merge s1 s2] returns [s1] with all defined values of [s2] overwritten. *)
+val diff : style -> style -> style
+(** [diff s1 s2] returns the differences between [s1] and [s2]. *)
+
val repr : style -> int list
(** Generate the ANSI code representing the given style. *)
@@ -60,6 +63,9 @@ val eval : style -> string
val reset : string
(** This escape sequence resets all attributes. *)
+val reset_style : style
+(** The default style *)
+
val has_style : Unix.file_descr -> bool
(** Whether an output file descriptor handles styles. Very heuristic, only
checks it is a terminal. *)
diff --git a/configure.ml b/configure.ml
index b5d5a2419f..7e0fd4c8ac 100644
--- a/configure.ml
+++ b/configure.ml
@@ -18,7 +18,7 @@ let vo_magic = 8891
let state_magic = 58891
let distributed_exec =
["coqtop.opt"; "coqidetop.opt"; "coqqueryworker.opt"; "coqproofworker.opt"; "coqtacticworker.opt";
- "coqc";"coqchk";"coqdoc";"coqworkmgr";"coq_makefile";"coq-tex";"gallina";"coqwc";"csdpcert";"coqdep"]
+ "coqc";"coqchk";"coqdoc";"coqworkmgr";"coq_makefile";"coq-tex";"coqwc";"csdpcert";"coqdep"]
let verbose = ref false (* for debugging this script *)
@@ -235,12 +235,6 @@ let get_date () =
let short_date, full_date = get_date ()
-
-(** Create the bin/ directory if non-existent *)
-
-let _ = if not (dir_exists "bin") then Unix.mkdir "bin" 0o755
-
-
(** * Command-line parsing *)
type ide = Opt | Byte | No
@@ -256,7 +250,6 @@ type preferences = {
datadir : string option;
mandir : string option;
docdir : string option;
- emacslib : string option;
coqdocdir : string option;
ocamlfindcmd : string option;
lablgtkdir : string option;
@@ -294,7 +287,6 @@ let default = {
datadir = None;
mandir = None;
docdir = None;
- emacslib = None;
coqdocdir = None;
ocamlfindcmd = None;
lablgtkdir = None;
@@ -392,8 +384,6 @@ let args_options = Arg.align [
"<dir> Where to install man files";
"-docdir", arg_string_option (fun p docdir -> { p with docdir }),
"<dir> Where to install doc files";
- "-emacslib", arg_string_option (fun p emacslib -> { p with emacslib }),
- "<dir> Where to install emacs files";
"-coqdocdir", arg_string_option (fun p coqdocdir -> { p with coqdocdir }),
"<dir> Where to install Coqdoc style files";
"-ocamlfind", arg_string_option (fun p ocamlfindcmd -> { p with ocamlfindcmd }),
@@ -461,14 +451,19 @@ let _ = parse_args ()
type camlexec =
{ mutable find : string;
mutable top : string;
- mutable lex : string; }
+ mutable lex : string;
+ mutable yacc : string;
+ }
let camlexec =
{ find = "ocamlfind";
top = "ocaml";
- lex = "ocamllex"; }
+ lex = "ocamllex";
+ yacc = "ocamlyacc";
+ }
let reset_caml_lex c o = c.lex <- o
+let reset_caml_yacc c o = c.yacc <- o
let reset_caml_top c o = c.top <- o
let reset_caml_find c o = c.find <- o
@@ -480,6 +475,7 @@ 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. *)
let coq_safe_string = "-safe-string"
+let coq_strict_sequence = "-strict-sequence"
let cflags = "-Wall -Wno-unused -g -O2"
@@ -580,6 +576,9 @@ let camlbin, caml_version, camllib, findlib_version =
if is_executable (camlbin / "ocamllex")
then reset_caml_lex camlexec (camlbin / "ocamllex") in
let () =
+ if is_executable (camlbin / "ocamlyacc")
+ then reset_caml_yacc camlexec (camlbin / "ocamlyacc") in
+ let () =
if is_executable (camlbin / "ocaml")
then reset_caml_top camlexec (camlbin / "ocaml") in
camlbin, caml_version, camllib, findlib_version
@@ -649,8 +648,10 @@ let camltag = match caml_version_list with
48: implicit elimination of optional arguments: too common
50: unexpected documentation comment: too common and annoying to avoid
56: unreachable match case: the [_ -> .] syntax doesn't exist in 4.02.3
+ 58: "no cmx file was found in path": See https://github.com/ocaml/num/issues/9
+ 59: "potential assignment to a non-mutable value": See Coq's issue #8043
*)
-let coq_warnings = "-w +a-4-9-27-41-42-44-45-48-50"
+let coq_warnings = "-w +a-4-9-27-41-42-44-45-48-50-58-59"
let coq_warn_error =
if !prefs.warn_error
then "-warn-error +a"
@@ -661,7 +662,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 %s" coq_warnings coq_annot_flag coq_bin_annot_flag coq_safe_string
+ Printf.sprintf "-thread -rectypes %s %s %s %s %s" coq_warnings coq_annot_flag coq_bin_annot_flag coq_safe_string coq_strict_sequence
(* Flags used to compile Coq but _not_ plugins (via coq_makefile) *)
let coq_caml_flags =
@@ -1006,8 +1007,6 @@ let install = [
Relative "man", Relative "share/man", Relative "man";
"DOCDIR", "the Coq documentation", !prefs.docdir,
Relative "doc", Relative "share/doc/coq", Relative "doc";
- "EMACSLIB", "the Coq Emacs mode", !prefs.emacslib,
- Relative "emacs", Relative "share/emacs/site-lisp", Relative "tools";
"COQDOCDIR", "the Coqdoc LaTeX files", !prefs.coqdocdir,
Relative "latex", Relative "share/texmf/tex/latex/misc", Relative "tools/coqdoc";
]
@@ -1215,8 +1214,8 @@ let write_configml f =
pr_s "browser" browser;
pr_s "wwwcoq" !prefs.coqwebsite;
pr_s "wwwbugtracker" (!prefs.coqwebsite ^ "bugs/");
- pr_s "wwwrefman" (!prefs.coqwebsite ^ "distrib/" ^ coq_version ^ "/refman/");
- pr_s "wwwstdlib" (!prefs.coqwebsite ^ "distrib/" ^ coq_version ^ "/stdlib/");
+ pr_s "wwwrefman" (!prefs.coqwebsite ^ "distrib/V" ^ coq_version ^ "/refman/");
+ pr_s "wwwstdlib" (!prefs.coqwebsite ^ "distrib/V" ^ coq_version ^ "/stdlib/");
pr_s "localwwwrefman" ("file:/" ^ docdir ^ "/html/refman");
pr_b "bytecode_compiler" !prefs.bytecodecompiler;
pr_b "native_compiler" !prefs.nativecompiler;
@@ -1280,6 +1279,7 @@ let write_makefile f =
pr "OCAML=%S\n" camlexec.top;
pr "OCAMLFIND=%S\n" camlexec.find;
pr "OCAMLLEX=%S\n" camlexec.lex;
+ pr "OCAMLYACC=%S\n" camlexec.yacc;
pr "# The best compiler: native (=opt) or bytecode (=byte)\n";
pr "BEST=%s\n\n" best_compiler;
pr "# Ocaml version number\n";
@@ -1340,6 +1340,7 @@ let write_makefile f =
pr "WITHDOC=%s\n\n" (if !prefs.withdoc then "all" else "no");
pr "# Option to produce precompiled files for native_compute\n";
pr "NATIVECOMPUTE=%s\n" (if !prefs.nativecompiler then "-native-compiler" else "");
+ pr "COQWARNERROR=%s\n" (if !prefs.warn_error then "-w +default" else "");
close_out o;
Unix.chmod f 0o444
diff --git a/coqpp/coqpp_ast.mli b/coqpp/coqpp_ast.mli
new file mode 100644
index 0000000000..39b4d2ab34
--- /dev/null
+++ b/coqpp/coqpp_ast.mli
@@ -0,0 +1,95 @@
+(************************************************************************)
+(* 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 loc = {
+ loc_start : Lexing.position;
+ loc_end : Lexing.position;
+}
+
+type code = { code : string }
+
+type user_symbol =
+| Ulist1 of user_symbol
+| Ulist1sep of user_symbol * string
+| Ulist0 of user_symbol
+| Ulist0sep of user_symbol * string
+| Uopt of user_symbol
+| Uentry of string
+| Uentryl of string * int
+
+type token_data =
+| TokNone
+| TokName of string
+
+type ext_token =
+| ExtTerminal of string
+| ExtNonTerminal of user_symbol * token_data
+
+type tactic_rule = {
+ tac_toks : ext_token list;
+ tac_body : code;
+}
+
+type level = string
+
+type position =
+| First
+| Last
+| Before of level
+| After of level
+| Level of level
+
+type assoc =
+| LeftA
+| RightA
+| NonA
+
+type gram_symbol =
+| GSymbString of string
+| GSymbQualid of string * level option
+| GSymbParen of gram_symbol list
+| GSymbProd of gram_prod list
+
+and gram_prod = {
+ gprod_symbs : (string option * gram_symbol list) list;
+ gprod_body : code;
+}
+
+type gram_rule = {
+ grule_label : string option;
+ grule_assoc : assoc option;
+ grule_prods : gram_prod list;
+}
+
+type grammar_entry = {
+ gentry_name : string;
+ gentry_pos : position option;
+ gentry_rules : gram_rule list;
+}
+
+type grammar_ext = {
+ gramext_name : string;
+ gramext_globals : string list;
+ gramext_entries : grammar_entry list;
+}
+
+type tactic_ext = {
+ tacext_name : string;
+ tacext_level : int option;
+ tacext_rules : tactic_rule list;
+}
+
+type node =
+| Code of code
+| Comment of string
+| DeclarePlugin of string
+| GramExt of grammar_ext
+| VernacExt
+| TacticExt of tactic_ext
+
+type t = node list
diff --git a/coqpp/coqpp_lex.mll b/coqpp/coqpp_lex.mll
new file mode 100644
index 0000000000..6c6562c204
--- /dev/null
+++ b/coqpp/coqpp_lex.mll
@@ -0,0 +1,167 @@
+(************************************************************************)
+(* 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 Lexing
+open Coqpp_parse
+
+type mode =
+| OCaml
+| Extend
+
+exception Lex_error of Coqpp_ast.loc * string
+
+let loc lexbuf = {
+ Coqpp_ast.loc_start = lexeme_start_p lexbuf;
+ Coqpp_ast.loc_end = lexeme_end_p lexbuf;
+}
+
+let newline lexbuf =
+ let pos = lexbuf.lex_curr_p in
+ let pos = { pos with pos_lnum = pos.pos_lnum + 1; pos_bol = pos.pos_cnum } in
+ lexbuf.lex_curr_p <- pos
+
+let num_comments = ref 0
+let num_braces = ref 0
+
+let mode () = if !num_braces = 0 then Extend else OCaml
+
+let comment_buf = Buffer.create 512
+let ocaml_buf = Buffer.create 512
+let string_buf = Buffer.create 512
+
+let lex_error lexbuf msg =
+ raise (Lex_error (loc lexbuf, msg))
+
+let lex_unexpected_eof lexbuf where =
+ lex_error lexbuf (Printf.sprintf "Unexpected end of file in %s" where)
+
+let start_comment _ =
+ let () = incr num_comments in
+ Buffer.add_string comment_buf "(*"
+
+let end_comment lexbuf =
+ let () = decr num_comments in
+ let () = Buffer.add_string comment_buf "*)" in
+ if !num_comments < 0 then lex_error lexbuf "Unexpected end of comment"
+ else if !num_comments = 0 then
+ let s = Buffer.contents comment_buf in
+ let () = Buffer.reset comment_buf in
+ Some (COMMENT s)
+ else
+ None
+
+let start_ocaml _ =
+ let () = match mode () with
+ | OCaml -> Buffer.add_string ocaml_buf "{"
+ | Extend -> ()
+ in
+ incr num_braces
+
+let end_ocaml lexbuf =
+ let () = decr num_braces in
+ if !num_braces < 0 then lex_error lexbuf "Unexpected end of OCaml code"
+ else if !num_braces = 0 then
+ let s = Buffer.contents ocaml_buf in
+ let () = Buffer.reset ocaml_buf in
+ Some (CODE { Coqpp_ast.code = s })
+ else
+ let () = Buffer.add_string ocaml_buf "}" in
+ None
+
+}
+
+let letter = ['a'-'z' 'A'-'Z']
+let letterlike = ['_' 'a'-'z' 'A'-'Z']
+let alphanum = ['_' 'a'-'z' 'A'-'Z' '0'-'9' '\'']
+let ident = letterlike alphanum*
+let qualid = ident ('.' ident)*
+let space = [' ' '\t' '\r']
+let number = [ '0'-'9' ]
+
+rule extend = parse
+| "(*" { start_comment (); comment lexbuf }
+| "{" { start_ocaml (); ocaml lexbuf }
+| "GRAMMAR" { GRAMMAR }
+| "VERNAC" { VERNAC }
+| "TACTIC" { TACTIC }
+| "EXTEND" { EXTEND }
+| "END" { END }
+| "DECLARE" { DECLARE }
+| "PLUGIN" { PLUGIN }
+(** Camlp5 specific keywords *)
+| "GLOBAL" { GLOBAL }
+| "FIRST" { FIRST }
+| "LAST" { LAST }
+| "BEFORE" { BEFORE }
+| "AFTER" { AFTER }
+| "LEVEL" { LEVEL }
+| "LEFTA" { LEFTA }
+| "RIGHTA" { RIGHTA }
+| "NONA" { NONA }
+(** Standard *)
+| ident { IDENT (Lexing.lexeme lexbuf) }
+| qualid { QUALID (Lexing.lexeme lexbuf) }
+| number { INT (int_of_string (Lexing.lexeme lexbuf)) }
+| space { extend lexbuf }
+| '\"' { string lexbuf }
+| '\n' { newline lexbuf; extend lexbuf }
+| '[' { LBRACKET }
+| ']' { RBRACKET }
+| '|' { PIPE }
+| "->" { ARROW }
+| ',' { COMMA }
+| ':' { COLON }
+| ';' { SEMICOLON }
+| '(' { LPAREN }
+| ')' { RPAREN }
+| '=' { EQUAL }
+| _ { lex_error lexbuf "syntax error" }
+| eof { EOF }
+
+and ocaml = parse
+| "{" { start_ocaml (); ocaml lexbuf }
+| "}" { match end_ocaml lexbuf with Some tk -> tk | None -> ocaml lexbuf }
+| '\n' { newline lexbuf; Buffer.add_char ocaml_buf '\n'; ocaml lexbuf }
+| '\"' { Buffer.add_char ocaml_buf '\"'; ocaml_string lexbuf }
+| (_ as c) { Buffer.add_char ocaml_buf c; ocaml lexbuf }
+| eof { lex_unexpected_eof lexbuf "OCaml code" }
+
+and comment = parse
+| "*)" { match end_comment lexbuf with Some _ -> extend lexbuf | None -> comment lexbuf }
+| "(*" { start_comment lexbuf; comment lexbuf }
+| '\n' { newline lexbuf; Buffer.add_char comment_buf '\n'; comment lexbuf }
+| (_ as c) { Buffer.add_char comment_buf c; comment lexbuf }
+| eof { lex_unexpected_eof lexbuf "comment" }
+
+and string = parse
+| '\"'
+ {
+ let s = Buffer.contents string_buf in
+ let () = Buffer.reset string_buf in
+ STRING s
+ }
+| "\\\"" { Buffer.add_char string_buf '\"'; string lexbuf }
+| '\n' { newline lexbuf; Buffer.add_char string_buf '\n'; string lexbuf }
+| (_ as c) { Buffer.add_char string_buf c; string lexbuf }
+| eof { lex_unexpected_eof lexbuf "string" }
+
+and ocaml_string = parse
+| "\\\"" { Buffer.add_string ocaml_buf "\\\""; ocaml_string lexbuf }
+| '\"' { Buffer.add_char ocaml_buf '\"'; ocaml lexbuf }
+| (_ as c) { Buffer.add_char ocaml_buf c; ocaml_string lexbuf }
+| eof { lex_unexpected_eof lexbuf "OCaml string" }
+
+{
+
+let token lexbuf = match mode () with
+| OCaml -> ocaml lexbuf
+| Extend -> extend lexbuf
+
+}
diff --git a/coqpp/coqpp_main.ml b/coqpp/coqpp_main.ml
new file mode 100644
index 0000000000..fd425ef4ff
--- /dev/null
+++ b/coqpp/coqpp_main.ml
@@ -0,0 +1,353 @@
+(************************************************************************)
+(* 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 Lexing
+open Coqpp_ast
+open Format
+
+let fatal msg =
+ let () = Format.eprintf "Error: %s@\n%!" msg in
+ exit 1
+
+let pr_loc loc =
+ let file = loc.loc_start.pos_fname in
+ let line = loc.loc_start.pos_lnum in
+ let bpos = loc.loc_start.pos_cnum - loc.loc_start.pos_bol in
+ let epos = loc.loc_end.pos_cnum - loc.loc_start.pos_bol in
+ Printf.sprintf "File \"%s\", line %d, characters %d-%d:" file line bpos epos
+
+let parse_file f =
+ let chan = open_in f in
+ let lexbuf = Lexing.from_channel chan in
+ let () = lexbuf.lex_curr_p <- { lexbuf.lex_curr_p with pos_fname = f } in
+ let ans =
+ try Coqpp_parse.file Coqpp_lex.token lexbuf
+ with
+ | Coqpp_lex.Lex_error (loc, msg) ->
+ let () = close_in chan in
+ let () = Printf.eprintf "%s\n%!" (pr_loc loc) in
+ fatal msg
+ | Parsing.Parse_error ->
+ let () = close_in chan in
+ let loc = Coqpp_lex.loc lexbuf in
+ let () = Printf.eprintf "%s\n%!" (pr_loc loc) in
+ fatal "syntax error"
+ in
+ let () = close_in chan in
+ ans
+
+module StringSet = Set.Make(String)
+
+let string_split s =
+ let len = String.length s in
+ let rec split n =
+ try
+ let pos = String.index_from s n '.' in
+ let dir = String.sub s n (pos-n) in
+ dir :: split (succ pos)
+ with
+ | Not_found -> [String.sub s n (len-n)]
+ in
+ if len == 0 then [] else split 0
+
+let plugin_name = "__coq_plugin_name"
+
+module GramExt :
+sig
+
+val print_ast : Format.formatter -> grammar_ext -> unit
+
+end =
+struct
+
+let is_uident s = match s.[0] with
+| 'A'..'Z' -> true
+| _ -> false
+
+let is_qualified = is_uident
+
+let get_local_entries ext =
+ let global = StringSet.of_list ext.gramext_globals in
+ let map e = e.gentry_name in
+ let entries = List.map map ext.gramext_entries in
+ let local = List.filter (fun e -> not (is_qualified e || StringSet.mem e global)) entries in
+ let rec uniquize seen = function
+ | [] -> []
+ | id :: rem ->
+ let rem = uniquize (StringSet.add id seen) rem in
+ if StringSet.mem id seen then rem else id :: rem
+ in
+ uniquize StringSet.empty local
+
+let print_local fmt ext =
+ let locals = get_local_entries ext in
+ match locals with
+ | [] -> ()
+ | e :: locals ->
+ let mk_e fmt e = fprintf fmt "%s.Entry.create \"%s\"" ext.gramext_name e in
+ let () = fprintf fmt "@[<hv 2>let %s =@ @[%a@]@]@ " e mk_e e in
+ let iter e = fprintf fmt "@[<hv 2>and %s =@ @[%a@]@]@ " e mk_e e in
+ let () = List.iter iter locals in
+ fprintf fmt "in@ "
+
+let print_string fmt s = fprintf fmt "\"%s\"" s
+
+let print_list fmt pr l =
+ let rec prl fmt = function
+ | [] -> ()
+ | [x] -> fprintf fmt "%a" pr x
+ | x :: l -> fprintf fmt "%a;@ %a" pr x prl l
+ in
+ fprintf fmt "@[<hv>[%a]@]" prl l
+
+let print_opt fmt pr = function
+| None -> fprintf fmt "None"
+| Some x -> fprintf fmt "Some@ (%a)" pr x
+
+let print_position fmt pos = match pos with
+| First -> fprintf fmt "Extend.First"
+| Last -> fprintf fmt "Extend.Last"
+| Before s -> fprintf fmt "Extend.Before@ \"%s\"" s
+| After s -> fprintf fmt "Extend.After@ \"%s\"" s
+| Level s -> fprintf fmt "Extend.Level@ \"%s\"" s
+
+let print_assoc fmt = function
+| LeftA -> fprintf fmt "Extend.LeftA"
+| RightA -> fprintf fmt "Extend.RightA"
+| NonA -> fprintf fmt "Extend.NonA"
+
+type symb =
+| SymbToken of string * string option
+| SymbEntry of string * string option
+| SymbSelf
+| SymbNext
+| SymbList0 of symb * symb option
+| SymbList1 of symb * symb option
+| SymbOpt of symb
+| SymbRules of ((string option * symb) list * code) list
+
+let is_token s = match string_split s with
+| [s] -> is_uident s
+| _ -> false
+
+let rec parse_tokens = function
+| [GSymbString s] -> SymbToken ("", Some s)
+| [GSymbQualid ("SELF", None)] -> SymbSelf
+| [GSymbQualid ("NEXT", None)] -> SymbNext
+| [GSymbQualid ("LIST0", None); tkn] ->
+ SymbList0 (parse_token tkn, None)
+| [GSymbQualid ("LIST1", None); tkn] ->
+ SymbList1 (parse_token tkn, None)
+| [GSymbQualid ("LIST0", None); tkn; GSymbQualid ("SEP", None); tkn'] ->
+ SymbList0 (parse_token tkn, Some (parse_token tkn'))
+| [GSymbQualid ("LIST1", None); tkn; GSymbQualid ("SEP", None); tkn'] ->
+ SymbList1 (parse_token tkn, Some (parse_token tkn'))
+| [GSymbQualid ("OPT", None); tkn] ->
+ SymbOpt (parse_token tkn)
+| [GSymbQualid (e, None)] when is_token e -> SymbToken (e, None)
+| [GSymbQualid (e, None); GSymbString s] when is_token e -> SymbToken (e, Some s)
+| [GSymbQualid (e, lvl)] when not (is_token e) -> SymbEntry (e, lvl)
+| [GSymbParen tkns] -> parse_tokens tkns
+| [GSymbProd prds] ->
+ let map p =
+ let map (pat, tkns) = (pat, parse_tokens tkns) in
+ (List.map map p.gprod_symbs, p.gprod_body)
+ in
+ SymbRules (List.map map prds)
+| t ->
+ let rec db_token = function
+ | GSymbString s -> Printf.sprintf "\"%s\"" s
+ | GSymbQualid (s, _) -> Printf.sprintf "%s" s
+ | GSymbParen s -> Printf.sprintf "(%s)" (db_tokens s)
+ | GSymbProd _ -> Printf.sprintf "[...]"
+ and db_tokens tkns =
+ let s = List.map db_token tkns in
+ String.concat " " s
+ in
+ fatal (Printf.sprintf "Invalid token: %s" (db_tokens t))
+
+and parse_token tkn = parse_tokens [tkn]
+
+let print_fun fmt (vars, body) =
+ let vars = List.rev vars in
+ let iter = function
+ | None -> fprintf fmt "_@ "
+ | Some id -> fprintf fmt "%s@ " id
+ in
+ let () = fprintf fmt "fun@ " in
+ let () = List.iter iter vars in
+ (** FIXME: use Coq locations in the macros *)
+ let () = fprintf fmt "loc ->@ @[%s@]" body.code in
+ ()
+
+(** Meta-program instead of calling Tok.of_pattern here because otherwise
+ violates value restriction *)
+let print_tok fmt = function
+| "", s -> fprintf fmt "Tok.KEYWORD %a" print_string s
+| "IDENT", s -> fprintf fmt "Tok.IDENT %a" print_string s
+| "PATTERNIDENT", s -> fprintf fmt "Tok.PATTERNIDENT %a" print_string s
+| "FIELD", s -> fprintf fmt "Tok.FIELD %a" print_string s
+| "INT", s -> fprintf fmt "Tok.INT %a" print_string s
+| "STRING", s -> fprintf fmt "Tok.STRING %a" print_string s
+| "LEFTQMARK", _ -> fprintf fmt "Tok.LEFTQMARK"
+| "BULLET", s -> fprintf fmt "Tok.BULLET %a" print_string s
+| "EOI", _ -> fprintf fmt "Tok.EOI"
+| _ -> failwith "Tok.of_pattern: not a constructor"
+
+let rec print_prod fmt p =
+ let (vars, tkns) = List.split p.gprod_symbs in
+ let f = (vars, p.gprod_body) in
+ let tkn = List.rev_map parse_tokens tkns in
+ fprintf fmt "@[Extend.Rule@ (@[%a@],@ @[(%a)@])@]" print_symbols tkn print_fun f
+
+and print_symbols fmt = function
+| [] -> fprintf fmt "Extend.Stop"
+| tkn :: tkns ->
+ fprintf fmt "Extend.Next @[(%a,@ %a)@]" print_symbols tkns print_symbol tkn
+
+and print_symbol fmt tkn = match tkn with
+| SymbToken (t, s) ->
+ let s = match s with None -> "" | Some s -> s in
+ fprintf fmt "(Extend.Atoken (%a))" print_tok (t, s)
+| SymbEntry (e, None) ->
+ fprintf fmt "(Extend.Aentry %s)" e
+| SymbEntry (e, Some l) ->
+ fprintf fmt "(Extend.Aentryl (%s, %a))" e print_string l
+| SymbSelf ->
+ fprintf fmt "Extend.Aself"
+| SymbNext ->
+ fprintf fmt "Extend.Anext"
+| SymbList0 (s, None) ->
+ fprintf fmt "(Extend.Alist0 %a)" print_symbol s
+| SymbList0 (s, Some sep) ->
+ fprintf fmt "(Extend.Alist0sep (%a, %a))" print_symbol s print_symbol sep
+| SymbList1 (s, None) ->
+ fprintf fmt "(Extend.Alist1 %a)" print_symbol s
+| SymbList1 (s, Some sep) ->
+ fprintf fmt "(Extend.Alist1sep (%a, %a))" print_symbol s print_symbol sep
+| SymbOpt s ->
+ fprintf fmt "(Extend.Aopt %a)" print_symbol s
+| SymbRules rules ->
+ let pr fmt (r, body) =
+ let (vars, tkn) = List.split r in
+ let tkn = List.rev tkn in
+ fprintf fmt "Extend.Rules @[({ Extend.norec_rule = %a },@ (%a))@]" print_symbols tkn print_fun (vars, body)
+ in
+ let pr fmt rules = print_list fmt pr rules in
+ fprintf fmt "(Extend.Arules %a)" pr (List.rev rules)
+
+let print_rule fmt r =
+ let pr_lvl fmt lvl = print_opt fmt print_string lvl in
+ let pr_asc fmt asc = print_opt fmt print_assoc asc in
+ let pr_prd fmt prd = print_list fmt print_prod prd in
+ fprintf fmt "@[(%a,@ %a,@ %a)@]" pr_lvl r.grule_label pr_asc r.grule_assoc pr_prd (List.rev r.grule_prods)
+
+let print_entry fmt gram e =
+ let print_position_opt fmt pos = print_opt fmt print_position pos in
+ let print_rules fmt rules = print_list fmt print_rule rules in
+ fprintf fmt "let () =@ @[%s.gram_extend@ %s@ @[(%a, %a)@]@]@ in@ "
+ gram e.gentry_name print_position_opt e.gentry_pos print_rules e.gentry_rules
+
+let print_ast fmt ext =
+ let () = fprintf fmt "let _ = @[" in
+ let () = fprintf fmt "@[<v>%a@]" print_local ext in
+ let () = List.iter (fun e -> print_entry fmt ext.gramext_name e) ext.gramext_entries in
+ let () = fprintf fmt "()@]@\n" in
+ ()
+
+end
+
+module TacticExt :
+sig
+
+val print_ast : Format.formatter -> tactic_ext -> unit
+
+end =
+struct
+
+let rec print_symbol fmt = function
+| Ulist1 s ->
+ fprintf fmt "@[Extend.TUlist1 (%a)@]" print_symbol s
+| Ulist1sep (s, sep) ->
+ fprintf fmt "@[Extend.TUlist1sep (%a, \"%s\")@]" print_symbol s sep
+| Ulist0 s ->
+ fprintf fmt "@[Extend.TUlist0 (%a)@]" print_symbol s
+| Ulist0sep (s, sep) ->
+ fprintf fmt "@[Extend.TUlist0sep (%a, \"%s\")@]" print_symbol s sep
+| Uopt s ->
+ fprintf fmt "@[Extend.TUopt (%a)@]" print_symbol s
+| Uentry e ->
+ fprintf fmt "@[Extend.TUentry (Genarg.get_arg_tag wit_%s)@]" e
+| Uentryl (e, l) ->
+ assert (e = "tactic");
+ fprintf fmt "@[Extend.TUentryl (Genarg.get_arg_tag wit_%s, %i)@]" e l
+
+let rec print_clause fmt = function
+| [] -> fprintf fmt "@[TyNil@]"
+| ExtTerminal s :: cl -> fprintf fmt "@[TyIdent (\"%s\", %a)@]" s print_clause cl
+| ExtNonTerminal (g, TokNone) :: cl ->
+ fprintf fmt "@[TyAnonArg (%a, %a)@]"
+ print_symbol g print_clause cl
+| ExtNonTerminal (g, TokName id) :: cl ->
+ fprintf fmt "@[TyArg (%a, \"%s\", %a)@]"
+ print_symbol g id print_clause cl
+
+let rec print_binders fmt = function
+| [] -> fprintf fmt "ist@ "
+| (ExtTerminal _ | ExtNonTerminal (_, TokNone)) :: rem -> print_binders fmt rem
+| (ExtNonTerminal (_, TokName id)) :: rem ->
+ fprintf fmt "%s@ %a" id print_binders rem
+
+let print_rule fmt r =
+ fprintf fmt "@[TyML (%a, @[fun %a -> %s@])@]"
+ print_clause r.tac_toks print_binders r.tac_toks r.tac_body.code
+
+let rec print_rules fmt = function
+| [] -> ()
+| [r] -> fprintf fmt "(%a)@\n" print_rule r
+| r :: rem -> fprintf fmt "(%a);@\n%a" print_rule r print_rules rem
+
+let print_rules fmt rules =
+ fprintf fmt "Tacentries.([@[<v>%a@]])" print_rules rules
+
+let print_ast fmt ext =
+ let pr fmt () =
+ let level = match ext.tacext_level with None -> 0 | Some i -> i in
+ fprintf fmt "Tacentries.tactic_extend %s \"%s\" ~level:%i %a"
+ plugin_name ext.tacext_name level print_rules ext.tacext_rules
+ in
+ let () = fprintf fmt "let () = @[%a@]\n" pr () in
+ ()
+
+end
+
+let declare_plugin fmt name =
+ fprintf fmt "let %s = \"%s\"@\n" plugin_name name;
+ fprintf fmt "let _ = Mltop.add_known_module %s@\n" plugin_name
+
+let pr_ast fmt = function
+| Code s -> fprintf fmt "%s@\n" s.code
+| Comment s -> fprintf fmt "%s@\n" s
+| DeclarePlugin name -> declare_plugin fmt name
+| GramExt gram -> fprintf fmt "%a@\n" GramExt.print_ast gram
+| VernacExt -> fprintf fmt "VERNACEXT@\n"
+| TacticExt tac -> fprintf fmt "%a@\n" TacticExt.print_ast tac
+
+let () =
+ let () =
+ if Array.length Sys.argv <> 2 then fatal "Expected exactly one command line argument"
+ in
+ let file = Sys.argv.(1) in
+ let output = Filename.chop_extension file ^ ".ml" in
+ let ast = parse_file file in
+ let chan = open_out output in
+ let fmt = formatter_of_out_channel chan in
+ let iter ast = Format.fprintf fmt "@[%a@]%!"pr_ast ast in
+ let () = List.iter iter ast in
+ let () = close_out chan in
+ exit 0
diff --git a/coqpp/coqpp_parse.mly b/coqpp/coqpp_parse.mly
new file mode 100644
index 0000000000..baafd633c4
--- /dev/null
+++ b/coqpp/coqpp_parse.mly
@@ -0,0 +1,256 @@
+/************************************************************************/
+/* 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 Coqpp_ast
+
+let starts s pat =
+ let len = String.length s in
+ let patlen = String.length pat in
+ if patlen <= len && String.sub s 0 patlen = pat then
+ Some (String.sub s patlen (len - patlen))
+ else None
+
+let ends s pat =
+ let len = String.length s in
+ let patlen = String.length pat in
+ if patlen <= len && String.sub s (len - patlen) patlen = pat then
+ Some (String.sub s 0 (len - patlen))
+ else None
+
+let between s pat1 pat2 = match starts s pat1 with
+| None -> None
+| Some s -> ends s pat2
+
+let without_sep k sep r =
+ if sep <> "" then raise Parsing.Parse_error else k r
+
+let parse_user_entry s sep =
+ let table = [
+ "ne_", "_list", without_sep (fun r -> Ulist1 r);
+ "ne_", "_list_sep", (fun sep r -> Ulist1sep (r, sep));
+ "", "_list", without_sep (fun r -> Ulist0 r);
+ "", "_list_sep", (fun sep r -> Ulist0sep (r, sep));
+ "", "_opt", without_sep (fun r -> Uopt r);
+ ] in
+ let rec parse s sep = function
+ | [] ->
+ let () = without_sep ignore sep () in
+ begin match starts s "tactic" with
+ | Some ("0"|"1"|"2"|"3"|"4"|"5") -> Uentryl ("tactic", int_of_string s)
+ | Some _ | None -> Uentry s
+ end
+ | (pat1, pat2, k) :: rem ->
+ match between s pat1 pat2 with
+ | None -> parse s sep rem
+ | Some s ->
+ let r = parse s "" table in
+ k sep r
+ in
+ parse s sep table
+
+%}
+
+%token <Coqpp_ast.code> CODE
+%token <string> COMMENT
+%token <string> IDENT QUALID
+%token <string> STRING
+%token <int> INT
+%token VERNAC TACTIC GRAMMAR EXTEND END DECLARE PLUGIN
+%token LBRACKET RBRACKET PIPE ARROW COMMA EQUAL
+%token LPAREN RPAREN COLON SEMICOLON
+%token GLOBAL FIRST LAST BEFORE AFTER LEVEL LEFTA RIGHTA NONA
+%token EOF
+
+%type <Coqpp_ast.t> file
+%start file
+
+%%
+
+file:
+| nodes EOF
+ { $1 }
+;
+
+nodes:
+|
+ { [] }
+| node nodes
+ { $1 :: $2 }
+;
+
+node:
+| CODE { Code $1 }
+| COMMENT { Comment $1 }
+| declare_plugin { $1 }
+| grammar_extend { $1 }
+| vernac_extend { $1 }
+| tactic_extend { $1 }
+;
+
+declare_plugin:
+| DECLARE PLUGIN STRING { DeclarePlugin $3 }
+;
+
+grammar_extend:
+| GRAMMAR EXTEND qualid_or_ident globals gram_entries END
+ { GramExt { gramext_name = $3; gramext_globals = $4; gramext_entries = $5 } }
+;
+
+vernac_extend:
+| VERNAC EXTEND IDENT END { VernacExt }
+;
+
+tactic_extend:
+| TACTIC EXTEND IDENT tactic_level tactic_rules END
+ { TacticExt { tacext_name = $3; tacext_level = $4; tacext_rules = $5 } }
+;
+
+tactic_level:
+| { None }
+| LEVEL INT { Some $2 }
+;
+
+tactic_rules:
+| tactic_rule { [$1] }
+| tactic_rule tactic_rules { $1 :: $2 }
+;
+
+tactic_rule:
+| PIPE LBRACKET ext_tokens RBRACKET ARROW CODE
+ { { tac_toks = $3; tac_body = $6 } }
+;
+
+ext_tokens:
+| { [] }
+| ext_token ext_tokens { $1 :: $2 }
+;
+
+ext_token:
+| STRING { ExtTerminal $1 }
+| IDENT {
+ let e = parse_user_entry $1 "" in
+ ExtNonTerminal (e, TokNone)
+ }
+| IDENT LPAREN IDENT RPAREN {
+ let e = parse_user_entry $1 "" in
+ ExtNonTerminal (e, TokName $3)
+ }
+| IDENT LPAREN IDENT COMMA STRING RPAREN {
+ let e = parse_user_entry $1 $5 in
+ ExtNonTerminal (e, TokName $3)
+}
+;
+
+qualid_or_ident:
+| QUALID { $1 }
+| IDENT { $1 }
+;
+
+globals:
+| { [] }
+| GLOBAL COLON idents SEMICOLON { $3 }
+;
+
+idents:
+| { [] }
+| qualid_or_ident idents { $1 :: $2 }
+;
+
+gram_entries:
+| { [] }
+| gram_entry gram_entries { $1 :: $2 }
+;
+
+gram_entry:
+| qualid_or_ident COLON position_opt LBRACKET levels RBRACKET SEMICOLON
+ { { gentry_name = $1; gentry_pos = $3; gentry_rules = $5; } }
+;
+
+position_opt:
+| { None }
+| position { Some $1 }
+;
+
+position:
+| FIRST { First }
+| LAST { Last }
+| BEFORE STRING { Before $2 }
+| AFTER STRING { After $2 }
+| LEVEL STRING { Level $2 }
+;
+
+string_opt:
+| { None }
+| STRING { Some $1 }
+;
+
+assoc_opt:
+| { None }
+| assoc { Some $1 }
+;
+
+assoc:
+| LEFTA { LeftA }
+| RIGHTA { RightA }
+| NONA { NonA }
+;
+
+levels:
+| level { [$1] }
+| level PIPE levels { $1 :: $3 }
+;
+
+level:
+| string_opt assoc_opt LBRACKET rules_opt RBRACKET
+ { { grule_label = $1; grule_assoc = $2; grule_prods = $4; } }
+;
+
+rules_opt:
+| { [] }
+| rules { $1 }
+;
+
+rules:
+| rule { [$1] }
+| rule PIPE rules { $1 :: $3 }
+;
+
+rule:
+| symbols_opt ARROW CODE
+ { { gprod_symbs = $1; gprod_body = $3; } }
+;
+
+symbols_opt:
+| { [] }
+| symbols { $1 }
+;
+
+symbols:
+| symbol { [$1] }
+| symbol SEMICOLON symbols { $1 :: $3 }
+;
+
+symbol:
+| IDENT EQUAL gram_tokens { (Some $1, $3) }
+| gram_tokens { (None, $1) }
+;
+
+gram_token:
+| qualid_or_ident { GSymbQualid ($1, None) }
+| qualid_or_ident LEVEL STRING { GSymbQualid ($1, Some $3) }
+| LPAREN gram_tokens RPAREN { GSymbParen $2 }
+| LBRACKET rules RBRACKET { GSymbProd $2 }
+| STRING { GSymbString $1 }
+;
+
+gram_tokens:
+| gram_token { [$1] }
+| gram_token gram_tokens { $1 :: $2 }
+;
diff --git a/default.nix b/default.nix
index 91d9636041..d9317bccaf 100644
--- a/default.nix
+++ b/default.nix
@@ -9,23 +9,30 @@
# nix-shell supports the --arg option (see Nix doc) that allows you for
# instance to do this:
-# $ nix-shell --arg ocamlPackages "(import <nixpkgs> {}).ocamlPackages_latest" --arg buildIde false
+# $ nix-shell --arg ocamlPackages "(import <nixpkgs> {}).ocaml-ng.ocamlPackages_4_05" --arg buildIde false
# You can also compile Coq and "install" it by running:
# $ make clean # (only needed if you have left-over compilation files)
# $ nix-build
# at the root of the Coq repository.
# nix-build also supports the --arg option, so you will be able to do:
-# $ nix-build --arg doCheck false
+# $ nix-build --arg doInstallCheck false
# if you want to speed up things by not running the test-suite.
# Once the build is finished, you will find, in the current directory,
# a symlink to where Coq was installed.
-{ pkgs ? (import <nixpkgs> {})
+{ pkgs ?
+ (import (fetchTarball {
+ url = "https://github.com/NixOS/nixpkgs/archive/060a98e9f4ad879492e48d63e887b0b6db26299e.tar.gz";
+ sha256 = "1lzvp3md0hf6kp2bvc6dbzh40navlyd51qlns9wbkz6lqk3lgf6j";
+ }) {})
, ocamlPackages ? pkgs.ocaml-ng.ocamlPackages_4_06
, buildIde ? true
, buildDoc ? true
-, doCheck ? true
+, doInstallCheck ? true
+, shell ? false
+ # We don't use lib.inNixShell because that would also apply
+ # when in a nix-shell of some package depending on this one.
}:
with pkgs;
@@ -36,63 +43,64 @@ stdenv.mkDerivation rec {
name = "coq";
buildInputs = [
-
- # Coq dependencies
hostname
- ] ++ (with ocamlPackages; [
- ocaml
- findlib
- camlp5_strict
- num
-
- ]) ++ (if buildIde then [
-
- # CoqIDE dependencies
- ocamlPackages.lablgtk
-
- ] else []) ++ (if buildDoc then [
-
+ python2 time # coq-makefile timing tools
+ ]
+ ++ (with ocamlPackages; [ ocaml findlib camlp5_strict num ])
+ ++ optional buildIde ocamlPackages.lablgtk
+ ++ optionals buildDoc [
# Sphinx doc dependencies
pkgconfig (python3.withPackages
(ps: [ ps.sphinx ps.sphinx_rtd_theme ps.pexpect ps.beautifulsoup4
ps.antlr4-python3-runtime ps.sphinxcontrib-bibtex ]))
- antlr4
-
- ] else []) ++ (if doCheck then
-
+ antlr4
+ ]
+ ++ optionals doInstallCheck (
# Test-suite dependencies
# ncurses is required to build an OCaml REPL
optional (!versionAtLeast ocaml.version "4.07") ncurses
- ++ [
- python
- rsync
- which
- ocamlPackages.ounit
-
- ] else []) ++ (if lib.inNixShell then [
- ocamlPackages.merlin
- ocamlPackages.ocpIndent
-
- # Dependencies of the merging script
- jq
- curl
- git
- gnupg
-
- ] else []);
+ ++ [ ocamlPackages.ounit rsync which ]
+ )
+ ++ optionals shell (
+ [ jq curl git gnupg ] # Dependencies of the merging script
+ ++ (with ocamlPackages; [ merlin ocp-indent ocp-index ]) # Dev tools
+ );
src =
- if lib.inNixShell then null
+ if shell then null
else
with builtins; filterSource
- (path: _: !elem (baseNameOf path) [".git" "result" "bin"]) ./.;
+ (path: _:
+ !elem (baseNameOf path) [".git" "result" "bin" "_build_ci"]) ./.;
prefixKey = "-prefix ";
- buildFlags = [ "world" ] ++ optional buildDoc "doc-html";
+ buildFlags = [ "world" "byte" ] ++ optional buildDoc "doc-html";
+
+ installTargets =
+ [ "install" "install-byte" ] ++ optional buildDoc "install-doc-html";
+
+ inherit doInstallCheck;
+
+ preInstallCheck = ''
+ patchShebangs tools/
+ patchShebangs test-suite/
+ '';
+
+ installCheckTarget = [ "check" ];
- installTargets = [ "install" ] ++ optional buildDoc "install-doc-html";
+ passthru = { inherit ocamlPackages; };
- inherit doCheck;
+ meta = {
+ description = "Coq proof assistant";
+ longDescription = ''
+ Coq is a formal proof management system. It provides a formal language
+ to write mathematical definitions, executable algorithms and theorems
+ together with an environment for semi-interactive development of
+ machine-checked proofs.
+ '';
+ homepage = http://coq.inria.fr;
+ license = licenses.lgpl21;
+ };
}
diff --git a/dev/README b/dev/README
deleted file mode 100644
index 453f85f0d6..0000000000
--- a/dev/README
+++ /dev/null
@@ -1,50 +0,0 @@
-This directory contains information and tools to help develop the
- Coq system
- ======================
-
-
-Debugging and profiling (in current directory - see doc/debugging.txt)
------------------------
-
-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
-
-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, top_printers.ml: ML pretty-printers for debugging
-
-
-Miscellaneous information about the code (directory doc)
------------------------------------------
-
-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
-
-
-Documentation of ML interfaces using ocamldoc (directory ocamldoc/html)
-----------------------------------------
-"make mli-doc" in coq root directory.
-
-
-Other development tools (directory tools)
------------------------
-
-coqdev.el: helper customizations for everyday Coq development, eg
- making `compile' work in subdirectories
-
-objects.el: various development utilities at emacs level
-
-anomaly-traces-parser.el: a .emacs-ready elisp snippet to parse
- location of Anomaly backtraces and jump to them conveniently from
- the Emacs *compilation* output.
diff --git a/dev/README.md b/dev/README.md
new file mode 100644
index 0000000000..4642aaf06d
--- /dev/null
+++ b/dev/README.md
@@ -0,0 +1,46 @@
+# This directory contains information and tools to help develop the Coq system
+
+
+## Debugging and profiling (`dev/`)
+**More info on debugging: [`doc/debugging.md`](doc/debugging.md)**
+
+| File | Description |
+| ---- | ----------- |
+| dev/ocamldebug-coq | To launch ocaml debugger (generated by the configure script) |
+| dev/db | To install pretty-printers from ocaml debugger |
+| dev/base_db | To install raw pretty-printers from ocaml debugger |
+| dev/include | To install pretty-printers from ocaml toplevel (use with the coq Drop command) |
+| dev/base_include | To install raw pretty-printers from ocaml toplevel |
+| dev/vm_printers.ml, top_printers.ml | ML pretty-printers for debugging |
+
+
+## Miscellaneous information about the code (`dev/doc`)
+**Beginner's guide to hacking Coq: [`dev/doc/README.md`](doc/README.md)**
+
+| File | Description |
+| ---- | ----------- |
+| [`dev/doc/changes.md`](doc/changes.md) | (partial) Per-version summary of the evolution of Coq ML source |
+| [`dev/doc/style.txt`](doc/style.txt) | A few style recommendations for writing Coq ML files |
+| [`dev/doc/debugging.md`](doc/debugging.md) | Help for debugging or profiling |
+| [`dev/doc/universes.txt`](doc/universes.txt) | Help for debugging universes |
+| [`dev/doc/extensions.txt`](doc/extensions.txt) | Some help about TACTIC EXTEND |
+| [`dev/doc/perf-analysis`](doc/perf-analysis)| Analysis of perfs measured on the compilation of user contribs |
+| [`dev/doc/cic.dtd`](doc/cic.dtd) | Official dtd of the calc. of ind. constr. for im/ex-portation |
+| [`dev/doc/econstr.md`](doc/econstr.md) | Describes `Econstr`, implementation of treatment of `evar` in the engine |
+| [`dev/doc/primproj.md`](doc/primproj.md) | Describes primitive projections |
+| [`dev/doc/proof-engine.md`](doc/proof-engine.md) | Tutorial on new proof engine |
+| [`dev/doc/xml-protocol.md`](doc/proof-engine.md) | XML protocol that coqtop and IDEs use to communicate |
+| [`dev/doc/MERGING.md`](doc/MERGING.md) | How pull requests should be merged into `master` |
+| [`dev/doc/release-process.md`](doc/release-process.md) | Process of creating a new Coq release |
+
+
+## Documentation of ML interfaces using ocamldoc ( `dev/ocamldoc/html`)
+`make mli-doc` in coq root directory.
+
+
+## Other development tools (`dev/tools`)
+
+| File | Description |
+| ---- | ----------- |
+| [`dev/tools/coqdev.el`](tools/coqdev.el) | Helper customizations for everyday Coq development, eg making `compile` work in subdirectories
+| [`dev/tools/objects.el`](tools/objects.el) | Various development utilities at emacs level |
diff --git a/dev/build/windows/MakeCoq_MinGW.bat b/dev/build/windows/MakeCoq_MinGW.bat
index f960ff0087..5af0fcff3a 100644..100755
--- a/dev/build/windows/MakeCoq_MinGW.bat
+++ b/dev/build/windows/MakeCoq_MinGW.bat
@@ -255,6 +255,7 @@ IF NOT "%~0" == "" (
IF NOT EXIST %SETUP% (
ECHO The cygwin setup program %SETUP% doesn't exist. You must download it from https://cygwin.com/install.html.
+ ECHO If the setup is in a different folder, set the full path to %SETUP% using the -setup option.
GOTO :EOF
)
@@ -385,7 +386,6 @@ IF "%RUNSETUP%"=="Y" (
MKDIR "%CYGWIN_INSTALLDIR_WFMT%\build\buildlogs"
)
-
IF NOT "%CYGWIN_QUIET%" == "Y" (
REM Like most setup programs, cygwin setup starts the real setup as a separate process, so wait for it.
REM This is not required with the -cygquiet=Y and the resulting --no-admin option.
@@ -396,6 +396,12 @@ IF NOT "%CYGWIN_QUIET%" == "Y" (
ECHO ========== CONFIGURE CYGWIN USER ACCOUNT ==========
+REM In case this batch file is called from a cygwin bash (e.g. a git repo) we need to clear
+REM HOME (otherwise we get to the home directory of the other installation)
+REM PROFILEREAD (this is set to true if the /etc/profile has been read, which creates user)
+SET "HOME="
+SET "PROFILEREAD="
+
copy "%BATCHDIR%\configure_profile.sh" "%CYGWIN_INSTALLDIR_WFMT%\var\tmp" || GOTO ErrorExit
%BASH% --login "%CYGWIN_INSTALLDIR_CFMT%\var\tmp\configure_profile.sh" "%PROXY%" || GOTO ErrorExit
diff --git a/dev/build/windows/makecoq_mingw.sh b/dev/build/windows/makecoq_mingw.sh
index 508dcf5fb0..60108cda4f 100644
--- a/dev/build/windows/makecoq_mingw.sh
+++ b/dev/build/windows/makecoq_mingw.sh
@@ -118,6 +118,9 @@ mkdir -p "$PREFIX/bin"
mkdir -p "$PREFIXCOQ/bin"
mkdir -p "$PREFIXOCAML/bin"
+# This is required for building addons and plugins
+export COQBIN=$RESULT_INSTALLDIR_CFMT/bin/
+
###################### Copy Cygwin Setup Info #####################
# Copy Cygwin repo ini file and installed files db to tarballs folder.
@@ -790,7 +793,7 @@ function make_ln {
function make_ocaml {
get_flex_dll_link_bin
- if build_prep http://caml.inria.fr/pub/distrib/ocaml-4.06 ocaml-4.06.1 tar.gz 1 ; then
+ if build_prep https://github.com/ocaml/ocaml/archive 4.07.0 tar.gz 1 ocaml-4.07.0 ; then
# See README.win32.adoc
cp config/m-nt.h byterun/caml/m.h
cp config/s-nt.h byterun/caml/s.h
@@ -930,7 +933,7 @@ function make_camlp5 {
make_ocaml
make_findlib
- if build_prep https://github.com/camlp5/camlp5/archive rel705 tar.gz 1 camlp5-rel705; then
+ if build_prep https://github.com/camlp5/camlp5/archive rel706 tar.gz 1 camlp5-rel706; then
logn configure ./configure
# Somehow my virus scanner has the boot.new/SAVED directory locked after the move for a second => repeat until success
sed -i 's/mv boot.new boot/until mv boot.new boot; do sleep 1; done/' Makefile
@@ -1128,14 +1131,12 @@ function copy_coq_license {
install -D doc/LICENSE "$PREFIXCOQ/license_readme/coq/LicenseDoc.txt"
install -D LICENSE "$PREFIXCOQ/license_readme/coq/License.txt"
install -D plugins/micromega/LICENSE.sos "$PREFIXCOQ/license_readme/coq/LicenseMicromega.txt"
- install -D README "$PREFIXCOQ/license_readme/coq/ReadMe.txt" || true
- install -D README.md "$PREFIXCOQ/license_readme/coq/ReadMe.md" || true
- install -D README.win "$PREFIXCOQ/license_readme/coq/ReadMeWindows.txt" || true
- install -D README.doc "$PREFIXCOQ/license_readme/coq/ReadMeDoc.txt" || true
+ # FIXME: this is not the micromega license
+ # It only applies to code that was copied into one single file!
+ install -D README.md "$PREFIXCOQ/license_readme/coq/ReadMe.md"
install -D CHANGES "$PREFIXCOQ/license_readme/coq/Changes.txt"
install -D INSTALL "$PREFIXCOQ/license_readme/coq/Install.txt"
- install -D INSTALL.doc "$PREFIXCOQ/license_readme/coq/InstallDoc.txt"
- install -D INSTALL.ide "$PREFIXCOQ/license_readme/coq/InstallIde.txt"
+ install -D doc/README.md "$PREFIXCOQ/license_readme/coq/ReadMeDoc.md"
fi
}
@@ -1211,6 +1212,10 @@ function make_coq {
# 2.) clean of test suites fails with "cannot run complexity tests (no bogomips found)"
# make clean
+ # Copy these files somewhere the plugin builds can find them
+ cp dev/ci/ci-basic-overlay.sh /build/
+ cp -r dev/ci/user-overlays /build/
+
build_post
fi
}
@@ -1378,8 +1383,16 @@ function make_coq_installer {
###################### ADDONS #####################
+# The bignums library
+# Provides BigN, BigZ, BigQ that used to be part of Coq standard library
+
function make_addon_bignums {
- if build_prep https://github.com/coq/bignums/archive/ V8.8+beta1 zip 1 bignums-8.8+beta1; then
+ bignums_SHA=$(git ls-remote "$bignums_CI_GITURL" "refs/heads/$bignums_CI_REF" | cut -f 1)
+ if [[ "$bignums_SHA" == "" ]]; then
+ # $bignums_CI_REF must have been a tag / commit and not a branch
+ bignums_SHA="$bignums_CI_REF"
+ fi
+ if build_prep "$bignums_CI_ARCHIVEURL" "$bignums_SHA" zip 1 "bignums-$bignums_SHA"; then
# To make command lines shorter :-(
echo 'COQ_SRC_SUBDIRS:=$(filter-out plugins/%,$(COQ_SRC_SUBDIRS)) plugins/syntax' >> Makefile.coq.local
log1 make all
@@ -1388,7 +1401,58 @@ function make_addon_bignums {
fi
}
+# Ltac-2 plugin
+# A new (experimental) tactic language
+
+function make_addon_ltac2 {
+ ltac2_SHA=$(git ls-remote "$ltac2_CI_GITURL" "refs/heads/$ltac2_CI_REF" | cut -f 1)
+ if [[ "$ltac2_SHA" == "" ]]; then
+ # $ltac2_CI_REF must have been a tag / commit and not a branch
+ ltac2_SHA="$ltac2_CI_REF"
+ fi
+ if build_prep "$ltac2_CI_ARCHIVEURL" "$ltac2_SHA" zip 1 "ltac2-$ltac2_SHA"; then
+ log1 make all
+ log2 make install
+ build_post
+ fi
+}
+
+# Equations plugin
+# A function definition plugin
+
+function make_addon_equations {
+ Equations_SHA=$(git ls-remote "$Equations_CI_GITURL" "refs/heads/$Equations_CI_REF" | cut -f 1)
+ if [[ "$Equations_SHA" == "" ]]; then
+ # $Equations_CI_REF must have been a tag / commit and not a branch
+ Equations_SHA="$Equations_CI_REF"
+ fi
+ if build_prep "$Equations_CI_ARCHIVEURL" "$Equations_SHA" zip 1 "Equations-$Equations_SHA"; then
+ # Note: PATH is autmatically saved/restored by build_prep / build_post
+ PATH=$COQBIN:$PATH
+ logn coq_makefile ${COQBIN}coq_makefile -f _CoqProject -o Makefile
+ log1 make
+ log2 make install
+ build_post
+ fi
+}
+
function make_addons {
+ if [ -n "$GITLAB_CI" ]; then
+ export CI_BRANCH="$CI_COMMIT_REF_NAME"
+ if [[ ${CI_BRANCH#pr-} =~ ^[0-9]*$ ]]; then
+ export CI_PULL_REQUEST="${CI_BRANCH#pr-}"
+ else
+ export CI_PULL_REQUEST=""
+ fi
+ else
+ export CI_BRANCH=""
+ export CI_PULL_REQUEST=""
+ fi
+ . /build/ci-basic-overlay.sh
+ for overlay in /build/user-overlays/*.sh; do
+ . "$overlay"
+ done
+
for addon in $COQ_ADDONS; do
"make_addon_$addon"
done
diff --git a/dev/ci/README.md b/dev/ci/README.md
index 08364c897a..a814e4914e 100644
--- a/dev/ci/README.md
+++ b/dev/ci/README.md
@@ -75,9 +75,6 @@ We are currently running tests on the following platforms:
camlp5, and with warnings as errors; it runs the test-suite and tests the
compilation of several external developments.
-- Circle CI runs tests that are redundant with GitLab CI and may be removed
- eventually.
-
- Travis CI is used to test the compilation of Coq and run the test-suite on
macOS. It also runs a linter that checks whitespace discipline. A
[pre-commit hook](../tools/pre-commit) is automatically installed by
@@ -86,11 +83,6 @@ We are currently running tests on the following platforms:
- AppVeyor is used to test the compilation of Coq and run the test-suite on
Windows.
-GitLab CI and Travis CI and AppVeyor support putting `[ci skip]` in a commit
-message to bypass CI. Do not use this unless your commit only changes files
-that are not compiled (e.g. Markdown files like this one, or files under
-[`.github/`](../../.github/)).
-
You can anticipate the results of most of these tests prior to submitting your
PR by running GitLab CI on your private branches. To do so follow these steps:
@@ -146,14 +138,11 @@ persists to and is used by the next jobs.
Artifacts can also be downloaded from the GitLab repository.
Currently, available artifacts are:
-- the Coq executables and stdlib, in three copies varying in
+- the Coq executables and stdlib, in four copies varying in
architecture and OCaml version used to build Coq.
-- the Coq documentation, built only in the `build:base` job. When submitting
+- the Coq documentation, built in the `documentation` job. When submitting
a documentation PR, this can help reviewers checking the rendered result.
-As an exception to the above, jobs testing that compilation triggers
-no OCaml warnings build Coq in parallel with other tests.
-
### GitLab and Windows
If your repository has access to runners tagged `windows`, setting the
@@ -170,8 +159,7 @@ automatically built and uploaded to your GitLab registry, and is
loaded by subsequent jobs.
**IMPORTANT**: When updating Coq's CI docker image, you must modify
-the `CACHEKEY` variable in [`.gitlab-ci.yml`](../../.gitlab-ci.yml),
-[`.circleci/config.yml`](../../.circleci/config.yml),
+the `CACHEKEY` variable in [`.gitlab-ci.yml`](../../.gitlab-ci.yml)
and [`Dockerfile`](docker/bionic_coq/Dockerfile)
The Docker building job reuses the uploaded image if it is available,
diff --git a/dev/ci/appveyor.sh b/dev/ci/appveyor.sh
index 7bf9ad8c9b..d2176e326c 100644
--- a/dev/ci/appveyor.sh
+++ b/dev/ci/appveyor.sh
@@ -2,7 +2,7 @@
set -e -x
-APPVEYOR_OPAM_SWITCH=4.06.1+mingw64c
+APPVEYOR_OPAM_SWITCH=4.07.0+mingw64c
wget https://github.com/fdopen/opam-repository-mingw/releases/download/0.0.0.1/opam64.tar.xz
tar -xf opam64.tar.xz
diff --git a/dev/ci/ci-basic-overlay.sh b/dev/ci/ci-basic-overlay.sh
index 3807ff90c5..63d5541f48 100755
--- a/dev/ci/ci-basic-overlay.sh
+++ b/dev/ci/ci-basic-overlay.sh
@@ -9,124 +9,147 @@
########################################################################
# MathComp
########################################################################
-: "${mathcomp_CI_BRANCH:=master}"
-: "${mathcomp_CI_GITURL:=https://github.com/math-comp/math-comp.git}"
-: "${oddorder_CI_BRANCH:=master}"
-: "${oddorder_CI_GITURL:=https://github.com/math-comp/odd-order.git}"
+: "${mathcomp_CI_REF:=master}"
+: "${mathcomp_CI_GITURL:=https://github.com/math-comp/math-comp}"
+: "${mathcomp_CI_ARCHIVEURL:=${mathcomp_CI_GITURL}/archive}"
+
+: "${oddorder_CI_REF:=master}"
+: "${oddorder_CI_GITURL:=https://github.com/math-comp/odd-order}"
+: "${oddorder_CI_ARCHIVEURL:=${oddorder_CI_GITURL}/archive}"
########################################################################
# UniMath
########################################################################
-: "${UniMath_CI_BRANCH:=master}"
-: "${UniMath_CI_GITURL:=https://github.com/UniMath/UniMath.git}"
+: "${UniMath_CI_REF:=master}"
+: "${UniMath_CI_GITURL:=https://github.com/UniMath/UniMath}"
+: "${UniMath_CI_ARCHIVEURL:=${UniMath_CI_GITURL}/archive}"
########################################################################
# Unicoq + Mtac2
########################################################################
-: "${unicoq_CI_BRANCH:=master}"
-: "${unicoq_CI_GITURL:=https://github.com/unicoq/unicoq.git}"
+: "${unicoq_CI_REF:=master}"
+: "${unicoq_CI_GITURL:=https://github.com/unicoq/unicoq}"
+: "${unicoq_CI_ARCHIVEURL:=${unicoq_CI_GITURL}/archive}"
-: "${mtac2_CI_BRANCH:=master-sync}"
-: "${mtac2_CI_GITURL:=https://github.com/Mtac2/Mtac2.git}"
+: "${mtac2_CI_REF:=master-sync}"
+: "${mtac2_CI_GITURL:=https://github.com/Mtac2/Mtac2}"
+: "${mtac2_CI_ARCHIVEURL:=${mtac2_CI_GITURL}/archive}"
########################################################################
# Mathclasses + Corn
########################################################################
-: "${math_classes_CI_BRANCH:=master}"
-: "${math_classes_CI_GITURL:=https://github.com/math-classes/math-classes.git}"
+: "${math_classes_CI_REF:=master}"
+: "${math_classes_CI_GITURL:=https://github.com/coq-community/math-classes}"
+: "${math_classes_CI_ARCHIVEURL:=${math_classes_CI_GITURL}/archive}"
-: "${Corn_CI_BRANCH:=master}"
-: "${Corn_CI_GITURL:=https://github.com/c-corn/corn.git}"
+: "${Corn_CI_REF:=master}"
+: "${Corn_CI_GITURL:=https://github.com/coq-community/corn}"
+: "${Corn_CI_ARCHIVEURL:=${Corn_CI_GITURL}/archive}"
########################################################################
# Iris
########################################################################
-: "${stdpp_CI_BRANCH:=master}"
-: "${stdpp_CI_GITURL:=https://gitlab.mpi-sws.org/robbertkrebbers/coq-stdpp.git}"
+: "${stdpp_CI_REF:=master}"
+: "${stdpp_CI_GITURL:=https://gitlab.mpi-sws.org/robbertkrebbers/coq-stdpp}"
+: "${stdpp_CI_ARCHIVEURL:=${stdpp_CI_GITURL}/-/archive}"
-: "${Iris_CI_BRANCH:=master}"
-: "${Iris_CI_GITURL:=https://gitlab.mpi-sws.org/FP/iris-coq.git}"
+: "${Iris_CI_REF:=master}"
+: "${Iris_CI_GITURL:=https://gitlab.mpi-sws.org/FP/iris-coq}"
+: "${Iris_CI_ARCHIVEURL:=${Iris_CI_GITURL}/-/archive}"
-: "${lambdaRust_CI_BRANCH:=master}"
-: "${lambdaRust_CI_GITURL:=https://gitlab.mpi-sws.org/FP/LambdaRust-coq.git}"
+: "${lambdaRust_CI_REF:=master}"
+: "${lambdaRust_CI_GITURL:=https://gitlab.mpi-sws.org/FP/LambdaRust-coq}"
+: "${lambdaRust_CI_ARCHIVEURL:=${lambdaRust_CI_GITURL}/-/archive}"
########################################################################
# HoTT
########################################################################
-: "${HoTT_CI_BRANCH:=master}"
-: "${HoTT_CI_GITURL:=https://github.com/HoTT/HoTT.git}"
+: "${HoTT_CI_REF:=master}"
+: "${HoTT_CI_GITURL:=https://github.com/HoTT/HoTT}"
+: "${HoTT_CI_ARCHIVEURL:=${HoTT_CI_GITURL}/archive}"
########################################################################
# Ltac2
########################################################################
-: "${ltac2_CI_BRANCH:=master}"
-: "${ltac2_CI_GITURL:=https://github.com/ppedrot/ltac2.git}"
+: "${ltac2_CI_REF:=master}"
+: "${ltac2_CI_GITURL:=https://github.com/ppedrot/ltac2}"
+: "${ltac2_CI_ARCHIVEURL:=${ltac2_CI_GITURL}/archive}"
########################################################################
# GeoCoq
########################################################################
-: "${GeoCoq_CI_BRANCH:=master}"
-: "${GeoCoq_CI_GITURL:=https://github.com/GeoCoq/GeoCoq.git}"
+: "${GeoCoq_CI_REF:=master}"
+: "${GeoCoq_CI_GITURL:=https://github.com/GeoCoq/GeoCoq}"
+: "${GeoCoq_CI_ARCHIVEURL:=${GeoCoq_CI_GITURL}/archive}"
########################################################################
# Flocq
########################################################################
-: "${Flocq_CI_BRANCH:=master}"
-: "${Flocq_CI_GITURL:=https://gitlab.inria.fr/flocq/flocq.git}"
+: "${Flocq_CI_REF:=master}"
+: "${Flocq_CI_GITURL:=https://gitlab.inria.fr/flocq/flocq}"
+: "${Flocq_CI_ARCHIVEURL:=${Flocq_CI_GITURL}/-/archive}"
########################################################################
# Coquelicot
########################################################################
-: "${Coquelicot_CI_BRANCH:=master}"
-: "${Coquelicot_CI_GITURL:=https://scm.gforge.inria.fr/anonscm/git/coquelicot/coquelicot.git}"
+: "${Coquelicot_CI_REF:=master}"
+: "${Coquelicot_CI_GITURL:=https://scm.gforge.inria.fr/anonscm/git/coquelicot/coquelicot}"
########################################################################
# CompCert
########################################################################
-: "${CompCert_CI_BRANCH:=master}"
-: "${CompCert_CI_GITURL:=https://github.com/AbsInt/CompCert.git}"
+: "${CompCert_CI_REF:=master}"
+: "${CompCert_CI_GITURL:=https://github.com/AbsInt/CompCert}"
+: "${CompCert_CI_ARCHIVEURL:=${CompCert_CI_GITURL}/archive}"
########################################################################
# VST
########################################################################
-: "${VST_CI_BRANCH:=master}"
-: "${VST_CI_GITURL:=https://github.com/PrincetonUniversity/VST.git}"
+: "${VST_CI_REF:=master}"
+: "${VST_CI_GITURL:=https://github.com/PrincetonUniversity/VST}"
+: "${VST_CI_ARCHIVEURL:=${VST_CI_GITURL}/archive}"
########################################################################
# cross-crypto
########################################################################
-: "${cross_crypto_CI_BRANCH:=master}"
-: "${cross_crypto_CI_GITURL:=https://github.com/mit-plv/cross-crypto.git}"
+: "${cross_crypto_CI_REF:=master}"
+: "${cross_crypto_CI_GITURL:=https://github.com/mit-plv/cross-crypto}"
+: "${cross_crypto_CI_ARCHIVEURL:=${cross_crypto_CI_GITURL}/archive}"
########################################################################
# fiat_parsers
########################################################################
-: "${fiat_parsers_CI_BRANCH:=master}"
-: "${fiat_parsers_CI_GITURL:=https://github.com/mit-plv/fiat.git}"
+: "${fiat_parsers_CI_REF:=master}"
+: "${fiat_parsers_CI_GITURL:=https://github.com/mit-plv/fiat}"
+: "${fiat_parsers_CI_ARCHIVEURL:=${fiat_parsers_CI_GITURL}/archive}"
########################################################################
# fiat_crypto
########################################################################
-: "${fiat_crypto_CI_BRANCH:=master}"
-: "${fiat_crypto_CI_GITURL:=https://github.com/mit-plv/fiat-crypto.git}"
+: "${fiat_crypto_CI_REF:=master}"
+: "${fiat_crypto_CI_GITURL:=https://github.com/mit-plv/fiat-crypto}"
+: "${fiat_crypto_CI_ARCHIVEURL:=${fiat_crypto_CI_GITURL}/archive}"
########################################################################
# formal-topology
########################################################################
-: "${formal_topology_CI_BRANCH:=ci}"
-: "${formal_topology_CI_GITURL:=https://github.com/bmsherman/topology.git}"
+: "${formal_topology_CI_REF:=ci}"
+: "${formal_topology_CI_GITURL:=https://github.com/bmsherman/topology}"
+: "${formal_topology_CI_ARCHIVEURL:=${formal_topology_CI_GITURL}/archive}"
########################################################################
# coq-dpdgraph
########################################################################
-: "${coq_dpdgraph_CI_BRANCH:=coq-master}"
-: "${coq_dpdgraph_CI_GITURL:=https://github.com/Karmaki/coq-dpdgraph.git}"
+: "${coq_dpdgraph_CI_REF:=coq-master}"
+: "${coq_dpdgraph_CI_GITURL:=https://github.com/Karmaki/coq-dpdgraph}"
+: "${coq_dpdgraph_CI_ARCHIVEURL:=${coq_dpdgraph_CI_GITURL}/archive}"
########################################################################
# CoLoR
########################################################################
-: "${CoLoR_CI_BRANCH:=master}"
-: "${CoLoR_CI_GITURL:=https://github.com/fblanqui/color.git}"
+: "${CoLoR_CI_REF:=master}"
+: "${CoLoR_CI_GITURL:=https://github.com/fblanqui/color}"
+: "${CoLoR_CI_ARCHIVEURL:=${CoLoR_CI_GITURL}/archive}"
########################################################################
# SF
@@ -138,47 +161,68 @@
########################################################################
# TLC
########################################################################
-: "${tlc_CI_BRANCH:=master}"
-: "${tlc_CI_GITURL:=https://gforge.inria.fr/git/tlc/tlc.git}"
+: "${tlc_CI_REF:=master}"
+: "${tlc_CI_GITURL:=https://gforge.inria.fr/git/tlc/tlc}"
########################################################################
# Bignums
########################################################################
-: "${bignums_CI_BRANCH:=master}"
-: "${bignums_CI_GITURL:=https://github.com/coq/bignums.git}"
+: "${bignums_CI_REF:=master}"
+: "${bignums_CI_GITURL:=https://github.com/coq/bignums}"
+: "${bignums_CI_ARCHIVEURL:=${bignums_CI_GITURL}/archive}"
+
+########################################################################
+# bedrock2
+########################################################################
+: "${bedrock2_CI_REF:=master}"
+: "${bedrock2_CI_GITURL:=https://github.com/mit-plv/bedrock2}"
+: "${bedrock2_CI_ARCHIVEURL:=${bedrock2_CI_GITURL}/archive}"
########################################################################
# Equations
########################################################################
-: "${Equations_CI_BRANCH:=master}"
-: "${Equations_CI_GITURL:=https://github.com/mattam82/Coq-Equations.git}"
+: "${Equations_CI_REF:=master}"
+: "${Equations_CI_GITURL:=https://github.com/mattam82/Coq-Equations}"
+: "${Equations_CI_ARCHIVEURL:=${Equations_CI_GITURL}/archive}"
########################################################################
# Elpi
########################################################################
-: "${Elpi_CI_BRANCH:=coq-master}"
-: "${Elpi_CI_GITURL:=https://github.com/LPCIC/coq-elpi.git}"
+: "${Elpi_CI_REF:=coq-master}"
+: "${Elpi_CI_GITURL:=https://github.com/LPCIC/coq-elpi}"
+: "${Elpi_CI_ARCHIVEURL:=${Elpi_CI_GITURL}/archive}"
########################################################################
# fcsl-pcm
########################################################################
-: "${fcsl_pcm_CI_BRANCH:=master}"
-: "${fcsl_pcm_CI_GITURL:=https://github.com/imdea-software/fcsl-pcm.git}"
+: "${fcsl_pcm_CI_REF:=master}"
+: "${fcsl_pcm_CI_GITURL:=https://github.com/imdea-software/fcsl-pcm}"
+: "${fcsl_pcm_CI_ARCHIVEURL:=${fcsl_pcm_CI_GITURL}/archive}"
########################################################################
# pidetop
########################################################################
-: "${pidetop_CI_BRANCH:=v8.9}"
-: "${pidetop_CI_GITURL:=https://bitbucket.org/coqpide/pidetop.git}"
+: "${pidetop_CI_REF:=v8.9}"
+: "${pidetop_CI_GITURL:=https://bitbucket.org/coqpide/pidetop}"
+: "${pidetop_CI_ARCHIVEURL:=${pidetop_CI_GITURL}/get}"
########################################################################
# ext-lib
########################################################################
-: "${ext_lib_CI_BRANCH:=master}"
-: "${ext_lib_CI_GITURL:=https://github.com/coq-ext-lib/coq-ext-lib.git}"
+: "${ext_lib_CI_REF:=master}"
+: "${ext_lib_CI_GITURL:=https://github.com/coq-ext-lib/coq-ext-lib}"
+: "${ext_lib_CI_ARCHIVEURL:=${ext_lib_CI_GITURL}/archive}"
+
+########################################################################
+# simple-io
+########################################################################
+: "${simple_io_CI_REF:=master}"
+: "${simple_io_CI_GITURL:=https://github.com/Lysxia/coq-simple-io}"
+: "${simple_io_CI_ARCHIVEURL:=${simple_io_CI_GITURL}/archive}"
########################################################################
# quickchick
########################################################################
-: "${quickchick_CI_BRANCH:=master}"
-: "${quickchick_CI_GITURL:=https://github.com/QuickChick/QuickChick.git}"
+: "${quickchick_CI_REF:=master}"
+: "${quickchick_CI_GITURL:=https://github.com/QuickChick/QuickChick}"
+: "${quickchick_CI_ARCHIVEURL:=${quickchick_CI_GITURL}/archive}"
diff --git a/dev/ci/ci-bedrock2.sh b/dev/ci/ci-bedrock2.sh
new file mode 100755
index 0000000000..5205946261
--- /dev/null
+++ b/dev/ci/ci-bedrock2.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+ci_dir="$(dirname "$0")"
+. "${ci_dir}/ci-common.sh"
+
+FORCE_GIT=1
+git_download bedrock2
+
+( cd "${CI_BUILD_DIR}/bedrock2" && git submodule update --init --recursive && make )
diff --git a/dev/ci/ci-bignums.sh b/dev/ci/ci-bignums.sh
index 0082919679..756f54dfbd 100755
--- a/dev/ci/ci-bignums.sh
+++ b/dev/ci/ci-bignums.sh
@@ -1,16 +1,8 @@
#!/usr/bin/env bash
ci_dir="$(dirname "$0")"
+. "${ci_dir}/ci-common.sh"
-# This script could be included inside other ones
-# Let's avoid to source ci-common twice in this case
-if [ -z "${CI_BUILD_DIR}" ];
-then
- . "${ci_dir}/ci-common.sh"
-fi
+git_download bignums
-bignums_CI_DIR="${CI_BUILD_DIR}/Bignums"
-
-git_checkout "${bignums_CI_BRANCH}" "${bignums_CI_GITURL}" "${bignums_CI_DIR}"
-
-( cd "${bignums_CI_DIR}" && make && make install)
+( cd "${CI_BUILD_DIR}/bignums" && make && make install)
diff --git a/dev/ci/ci-color.sh b/dev/ci/ci-color.sh
index 8ce5f2418f..dc696f69d9 100755
--- a/dev/ci/ci-color.sh
+++ b/dev/ci/ci-color.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-CoLoR_CI_DIR=${CI_BUILD_DIR}/color
+git_download CoLoR
-# Compile CoLoR
-git_checkout "${CoLoR_CI_BRANCH}" "${CoLoR_CI_GITURL}" "${CoLoR_CI_DIR}"
-( cd "${CoLoR_CI_DIR}" && make )
+( cd "${CI_BUILD_DIR}/CoLoR" && make )
diff --git a/dev/ci/ci-common.sh b/dev/ci/ci-common.sh
index 85df249d38..3536cc70b2 100644
--- a/dev/ci/ci-common.sh
+++ b/dev/ci/ci-common.sh
@@ -20,10 +20,6 @@ else
then
export CI_PULL_REQUEST="$TRAVIS_PULL_REQUEST"
export CI_BRANCH="$TRAVIS_BRANCH"
- elif [ -n "${CIRCLECI}" ];
- then
- export CI_PULL_REQUEST="$CIRCLE_PR_NUMBER"
- export CI_BRANCH="$CIRCLE_BRANCH"
else # assume local
CI_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
export CI_BRANCH
@@ -38,7 +34,7 @@ export COQBIN="$COQBIN/"
ls "$COQBIN"
-# Where we clone and build external developments
+# Where we download and build external developments
CI_BUILD_DIR="$PWD/_build_ci"
# shellcheck source=ci-basic-overlay.sh
@@ -48,29 +44,38 @@ for overlay in "${ci_dir}"/user-overlays/*.sh; do
. "${overlay}"
done
-mathcomp_CI_DIR="${CI_BUILD_DIR}/math-comp"
-
-# git_checkout branch url dest will create a git repository
-# in <dest> (if it does not exist already) and checkout the
-# remote branch <branch> from <url>
-git_checkout()
+# [git_download project] will download [project] and unpack it
+# in [$CI_BUILD_DIR/project] if the folder does not exist already;
+# if it does, it will do nothing except print a warning (this can be
+# useful when building locally).
+# Note: when $FORCE_GIT is set to 1 or when $CI is unset or empty
+# (local build), it uses git clone to perform the download.
+git_download()
{
- local _BRANCH=${1}
- local _URL=${2}
- local _DEST=${3}
-
- # Allow an optional 4th argument for the commit
- local _COMMIT=${4:-FETCH_HEAD}
- local _DEPTH=()
- if [ -z "${4}" ]; then _DEPTH=(--depth 1); fi
-
- mkdir -p "${_DEST}"
- ( cd "${_DEST}" && \
- if [ ! -d .git ] ; then git clone "${_DEPTH[@]}" "${_URL}" . ; fi && \
- echo "Checking out ${_DEST}" && \
- git fetch "${_URL}" "${_BRANCH}" && \
- git checkout "${_COMMIT}" && \
- echo "${_DEST}: $(git log -1 --format='%s | %H | %cd | %aN')" )
+ local PROJECT=$1
+ local DEST="$CI_BUILD_DIR/$PROJECT"
+
+ if [ -d "$DEST" ]; then
+ echo "Warning: download and unpacking of $PROJECT skipped because $DEST already exists."
+ elif [ "$FORCE_GIT" = "1" ] || [ "$CI" = "" ]; then
+ local GITURL_VAR="${PROJECT}_CI_GITURL"
+ local GITURL="${!GITURL_VAR}"
+ local REF_VAR="${PROJECT}_CI_REF"
+ local REF="${!REF_VAR}"
+ git clone "$GITURL" "$DEST"
+ cd "$DEST"
+ git checkout "$REF"
+ else # When possible, we download tarballs to reduce bandwidth and latency
+ local ARCHIVEURL_VAR="${PROJECT}_CI_ARCHIVEURL"
+ local ARCHIVEURL="${!ARCHIVEURL_VAR}"
+ local REF_VAR="${PROJECT}_CI_REF"
+ local REF="${!REF_VAR}"
+ mkdir -p "$DEST"
+ cd "$DEST"
+ wget "$ARCHIVEURL/$REF.tar.gz"
+ tar xvfz "$REF.tar.gz" --strip-components=1
+ rm -f "$REF.tar.gz"
+ fi
}
make()
@@ -88,31 +93,27 @@ make()
# this installs just the ssreflect library of math-comp
install_ssreflect()
{
- echo 'Installing ssreflect' && echo -en 'travis_fold:start:ssr.install\\r'
+ echo 'Installing ssreflect'
- git_checkout "${mathcomp_CI_BRANCH}" "${mathcomp_CI_GITURL}" "${mathcomp_CI_DIR}"
+ git_download mathcomp
- ( cd "${mathcomp_CI_DIR}/mathcomp" && \
+ ( cd "${CI_BUILD_DIR}/mathcomp/mathcomp" && \
make Makefile.coq && \
make -f Makefile.coq ssreflect/all_ssreflect.vo && \
make -f Makefile.coq install )
- echo -en 'travis_fold:end:ssr.install\\r'
-
}
# this installs just the ssreflect + algebra library of math-comp
install_ssralg()
{
- echo 'Installing ssralg' && echo -en 'travis_fold:start:ssralg.install\\r'
+ echo 'Installing ssralg'
- git_checkout "${mathcomp_CI_BRANCH}" "${mathcomp_CI_GITURL}" "${mathcomp_CI_DIR}"
+ git_download mathcomp
- ( cd "${mathcomp_CI_DIR}/mathcomp" && \
+ ( cd "${CI_BUILD_DIR}/mathcomp/mathcomp" && \
make Makefile.coq && \
make -f Makefile.coq algebra/all_algebra.vo && \
make -f Makefile.coq install )
- echo -en 'travis_fold:end:ssralg.install\\r'
-
}
diff --git a/dev/ci/ci-compcert.sh b/dev/ci/ci-compcert.sh
index 8d490591b6..01c35ceb4a 100755
--- a/dev/ci/ci-compcert.sh
+++ b/dev/ci/ci-compcert.sh
@@ -3,8 +3,7 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-CompCert_CI_DIR="${CI_BUILD_DIR}/CompCert"
+git_download CompCert
-git_checkout "${CompCert_CI_BRANCH}" "${CompCert_CI_GITURL}" "${CompCert_CI_DIR}"
-
-( cd "${CompCert_CI_DIR}" && ./configure -ignore-coq-version x86_32-linux && make && make check-proof )
+( cd "${CI_BUILD_DIR}/CompCert" && \
+ ./configure -ignore-coq-version x86_32-linux && make && make check-proof )
diff --git a/dev/ci/ci-coq-dpdgraph.sh b/dev/ci/ci-coq-dpdgraph.sh
index 5d57fce1c7..2373ea6c62 100755
--- a/dev/ci/ci-coq-dpdgraph.sh
+++ b/dev/ci/ci-coq-dpdgraph.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-coq_dpdgraph_CI_DIR="${CI_BUILD_DIR}/coq-dpdgraph"
+git_download coq_dpdgraph
-git_checkout "${coq_dpdgraph_CI_BRANCH}" "${coq_dpdgraph_CI_GITURL}" "${coq_dpdgraph_CI_DIR}"
-
-( cd "${coq_dpdgraph_CI_DIR}" && autoconf && ./configure && make && make test-suite )
+( cd "${CI_BUILD_DIR}/coq_dpdgraph" && autoconf && ./configure && make && make test-suite )
diff --git a/dev/ci/ci-coquelicot.sh b/dev/ci/ci-coquelicot.sh
index d86d61ef6a..5d8817491d 100755
--- a/dev/ci/ci-coquelicot.sh
+++ b/dev/ci/ci-coquelicot.sh
@@ -3,10 +3,9 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-Coquelicot_CI_DIR="${CI_BUILD_DIR}/coquelicot"
-
install_ssreflect
-git_checkout "${Coquelicot_CI_BRANCH}" "${Coquelicot_CI_GITURL}" "${Coquelicot_CI_DIR}"
+FORCE_GIT=1
+git_download Coquelicot
-( cd "${Coquelicot_CI_DIR}" && ./autogen.sh && ./configure && ./remake "-j${NJOBS}" )
+( cd "${CI_BUILD_DIR}/Coquelicot" && ./autogen.sh && ./configure && ./remake "-j${NJOBS}" )
diff --git a/dev/ci/ci-corn.sh b/dev/ci/ci-corn.sh
index 9298fc70af..7d5d70cf90 100755
--- a/dev/ci/ci-corn.sh
+++ b/dev/ci/ci-corn.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-Corn_CI_DIR="${CI_BUILD_DIR}/corn"
+git_download Corn
-git_checkout "${Corn_CI_BRANCH}" "${Corn_CI_GITURL}" "${Corn_CI_DIR}"
-
-( cd "${Corn_CI_DIR}" && make && make install )
+( cd "${CI_BUILD_DIR}/Corn" && make && make install )
diff --git a/dev/ci/ci-cross-crypto.sh b/dev/ci/ci-cross-crypto.sh
index a0d3aa6551..900d12c1dd 100755
--- a/dev/ci/ci-cross-crypto.sh
+++ b/dev/ci/ci-cross-crypto.sh
@@ -3,9 +3,7 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-cross_crypto_CI_DIR="${CI_BUILD_DIR}/cross-crypto"
+FORCE_GIT=1
+git_download cross_crypto
-git_checkout "${cross_crypto_CI_BRANCH}" "${cross_crypto_CI_GITURL}" "${cross_crypto_CI_DIR}"
-( cd "${cross_crypto_CI_DIR}" && git submodule update --init --recursive )
-
-( cd "${cross_crypto_CI_DIR}" && make )
+( cd "${CI_BUILD_DIR}/cross_crypto" && git submodule update --init --recursive && make )
diff --git a/dev/ci/ci-elpi.sh b/dev/ci/ci-elpi.sh
index 9c58034be1..9b4a06fd5b 100755
--- a/dev/ci/ci-elpi.sh
+++ b/dev/ci/ci-elpi.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-Elpi_CI_DIR="${CI_BUILD_DIR}/elpi"
+git_download Elpi
-git_checkout "${Elpi_CI_BRANCH}" "${Elpi_CI_GITURL}" "${Elpi_CI_DIR}"
-
-( cd "${Elpi_CI_DIR}" && make && make install )
+( cd "${CI_BUILD_DIR}/Elpi" && make && make install )
diff --git a/dev/ci/ci-equations.sh b/dev/ci/ci-equations.sh
index 98735b4ec4..998d50faa7 100755
--- a/dev/ci/ci-equations.sh
+++ b/dev/ci/ci-equations.sh
@@ -3,8 +3,7 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-Equations_CI_DIR="${CI_BUILD_DIR}/Equations"
+git_download Equations
-git_checkout "${Equations_CI_BRANCH}" "${Equations_CI_GITURL}" "${Equations_CI_DIR}"
-
-( cd "${Equations_CI_DIR}" && coq_makefile -f _CoqProject -o Makefile && make && make test-suite && make examples && make install)
+( cd "${CI_BUILD_DIR}/Equations" && coq_makefile -f _CoqProject -o Makefile && \
+ make && make test-suite && make examples && make install)
diff --git a/dev/ci/ci-ext-lib.sh b/dev/ci/ci-ext-lib.sh
index cf212c2fb5..5eb167d97d 100755
--- a/dev/ci/ci-ext-lib.sh
+++ b/dev/ci/ci-ext-lib.sh
@@ -1,16 +1,8 @@
#!/usr/bin/env bash
ci_dir="$(dirname "$0")"
+. "${ci_dir}/ci-common.sh"
-# This script could be included inside other ones
-# Let's avoid to source ci-common twice in this case
-if [ -z "${CI_BUILD_DIR}" ];
-then
- . "${ci_dir}/ci-common.sh"
-fi
+git_download ext_lib
-ext_lib_CI_DIR="${CI_BUILD_DIR}/ExtLib"
-
-git_checkout "${ext_lib_CI_BRANCH}" "${ext_lib_CI_GITURL}" "${ext_lib_CI_DIR}"
-
-( cd "${ext_lib_CI_DIR}" && make && make install)
+( cd "${CI_BUILD_DIR}/ext_lib" && make && make install)
diff --git a/dev/ci/ci-fcsl-pcm.sh b/dev/ci/ci-fcsl-pcm.sh
index fdc4c729b6..cb951630c8 100755
--- a/dev/ci/ci-fcsl-pcm.sh
+++ b/dev/ci/ci-fcsl-pcm.sh
@@ -3,10 +3,8 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-fcsl_pcm_CI_DIR="${CI_BUILD_DIR}/fcsl-pcm"
-
install_ssreflect
-git_checkout "${fcsl_pcm_CI_BRANCH}" "${fcsl_pcm_CI_GITURL}" "${fcsl_pcm_CI_DIR}"
+git_download fcsl_pcm
-( cd "${fcsl_pcm_CI_DIR}" && make )
+( cd "${CI_BUILD_DIR}/fcsl_pcm" && make )
diff --git a/dev/ci/ci-fiat-crypto-legacy.sh b/dev/ci/ci-fiat-crypto-legacy.sh
new file mode 100755
index 0000000000..e0395754e5
--- /dev/null
+++ b/dev/ci/ci-fiat-crypto-legacy.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+
+ci_dir="$(dirname "$0")"
+. "${ci_dir}/ci-common.sh"
+
+FORCE_GIT=1
+git_download fiat_crypto
+
+fiat_crypto_legacy_CI_TARGETS1="print-old-pipeline-lite old-pipeline-lite lite-display"
+fiat_crypto_legacy_CI_TARGETS2="print-old-pipeline-nobigmem old-pipeline-nobigmem nonautogenerated-specific nonautogenerated-specific-display"
+
+( cd "${CI_BUILD_DIR}/fiat_crypto" && git submodule update --init --recursive && \
+ make ${fiat_crypto_legacy_CI_TARGETS1} && make -j 1 ${fiat_crypto_legacy_CI_TARGETS2} )
diff --git a/dev/ci/ci-fiat-crypto.sh b/dev/ci/ci-fiat-crypto.sh
index 48a1366aba..7e8013be9b 100755
--- a/dev/ci/ci-fiat-crypto.sh
+++ b/dev/ci/ci-fiat-crypto.sh
@@ -3,12 +3,12 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-fiat_crypto_CI_DIR="${CI_BUILD_DIR}/fiat-crypto"
+FORCE_GIT=1
+git_download fiat_crypto
-git_checkout "${fiat_crypto_CI_BRANCH}" "${fiat_crypto_CI_GITURL}" "${fiat_crypto_CI_DIR}"
+# We need a larger stack size to not overflow ocamlopt+flambda when
+# building the executables.
+# c.f. https://github.com/coq/coq/pull/8313#issuecomment-416650241
-( cd "${fiat_crypto_CI_DIR}" && git submodule update --init --recursive )
-
-fiat_crypto_CI_TARGETS1="printlite lite lite-display"
-fiat_crypto_CI_TARGETS2="print-nobigmem nobigmem nonautogenerated-specific nonautogenerated-specific-display"
-( cd "${fiat_crypto_CI_DIR}" && make ${fiat_crypto_CI_TARGETS1} && make -j 1 ${fiat_crypto_CI_TARGETS2} )
+( cd "${CI_BUILD_DIR}/fiat_crypto" && git submodule update --init --recursive && \
+ ulimit -s 32768 && make new-pipeline c-files )
diff --git a/dev/ci/ci-fiat-parsers.sh b/dev/ci/ci-fiat-parsers.sh
index 35c2284050..ac74ebf667 100755
--- a/dev/ci/ci-fiat-parsers.sh
+++ b/dev/ci/ci-fiat-parsers.sh
@@ -3,8 +3,7 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-fiat_parsers_CI_DIR="${CI_BUILD_DIR}/fiat"
+FORCE_GIT=1
+git_download fiat_parsers
-git_checkout "${fiat_parsers_CI_BRANCH}" "${fiat_parsers_CI_GITURL}" "${fiat_parsers_CI_DIR}"
-
-( cd "${fiat_parsers_CI_DIR}" && make parsers parsers-examples && make fiat-core )
+( cd "${CI_BUILD_DIR}/fiat_parsers" && make parsers parsers-examples && make fiat-core )
diff --git a/dev/ci/ci-flocq.sh b/dev/ci/ci-flocq.sh
index 8599e4d50e..e87483df0a 100755
--- a/dev/ci/ci-flocq.sh
+++ b/dev/ci/ci-flocq.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-Flocq_CI_DIR="${CI_BUILD_DIR}/flocq"
+git_download Flocq
-git_checkout "${Flocq_CI_BRANCH}" "${Flocq_CI_GITURL}" "${Flocq_CI_DIR}"
-
-( cd "${Flocq_CI_DIR}" && ./autogen.sh && ./configure && ./remake "-j${NJOBS}" )
+( cd "${CI_BUILD_DIR}/Flocq" && ./autogen.sh && ./configure && ./remake "-j${NJOBS}" )
diff --git a/dev/ci/ci-formal-topology.sh b/dev/ci/ci-formal-topology.sh
index 118d151500..8be5a06ed2 100755
--- a/dev/ci/ci-formal-topology.sh
+++ b/dev/ci/ci-formal-topology.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-formal_topology_CI_DIR="${CI_BUILD_DIR}/formal-topology"
+git_download formal_topology
-git_checkout "${formal_topology_CI_BRANCH}" "${formal_topology_CI_GITURL}" "${formal_topology_CI_DIR}"
-
-( cd "${formal_topology_CI_DIR}" && make )
+( cd "${CI_BUILD_DIR}/formal_topology" && make )
diff --git a/dev/ci/ci-geocoq.sh b/dev/ci/ci-geocoq.sh
index 24cd9c4272..8c57318477 100755
--- a/dev/ci/ci-geocoq.sh
+++ b/dev/ci/ci-geocoq.sh
@@ -3,10 +3,8 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-GeoCoq_CI_DIR="${CI_BUILD_DIR}/GeoCoq"
-
-git_checkout "${GeoCoq_CI_BRANCH}" "${GeoCoq_CI_GITURL}" "${GeoCoq_CI_DIR}"
-
install_ssralg
-( cd "${GeoCoq_CI_DIR}" && ./configure.sh && make )
+git_download GeoCoq
+
+( cd "${CI_BUILD_DIR}/GeoCoq" && ./configure.sh && make )
diff --git a/dev/ci/ci-hott.sh b/dev/ci/ci-hott.sh
index 6ded97984e..7eeeb09372 100755
--- a/dev/ci/ci-hott.sh
+++ b/dev/ci/ci-hott.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-HoTT_CI_DIR="${CI_BUILD_DIR}"/HoTT
+git_download HoTT
-git_checkout "${HoTT_CI_BRANCH}" "${HoTT_CI_GITURL}" "${HoTT_CI_DIR}"
-
-( cd "${HoTT_CI_DIR}" && ./autogen.sh && ./configure && make )
+( cd "${CI_BUILD_DIR}/HoTT" && ./autogen.sh && ./configure && make && make validate )
diff --git a/dev/ci/ci-iris-lambda-rust.sh b/dev/ci/ci-iris-lambda-rust.sh
index 1af0f634c4..6960a8b98a 100755
--- a/dev/ci/ci-iris-lambda-rust.sh
+++ b/dev/ci/ci-iris-lambda-rust.sh
@@ -3,32 +3,28 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-stdpp_CI_DIR="${CI_BUILD_DIR}/coq-stdpp"
-Iris_CI_DIR="${CI_BUILD_DIR}/iris-coq"
-lambdaRust_CI_DIR="${CI_BUILD_DIR}/lambdaRust"
-
install_ssreflect
# Setup lambdaRust first
-git_checkout "${lambdaRust_CI_BRANCH}" "${lambdaRust_CI_GITURL}" "${lambdaRust_CI_DIR}"
+git_download lambdaRust
# Extract required version of Iris
-Iris_SHA=$(grep -F coq-iris < "${lambdaRust_CI_DIR}/opam" | sed 's/.*"dev\.[0-9.-]\+\.\([0-9a-z]\+\)".*/\1/')
+Iris_REF=$(grep -F coq-iris < "${CI_BUILD_DIR}/lambdaRust/opam" | sed 's/.*"dev\.[0-9.-]\+\.\([0-9a-z]\+\)".*/\1/')
# Setup Iris
-git_checkout "${Iris_CI_BRANCH}" "${Iris_CI_GITURL}" "${Iris_CI_DIR}" "${Iris_SHA}"
+git_download Iris
# Extract required version of std++
-stdpp_SHA=$(grep -F coq-stdpp < "${Iris_CI_DIR}/opam" | sed 's/.*"dev\.[0-9.-]\+\.\([0-9a-z]\+\)".*/\1/')
+stdpp_REF=$(grep -F coq-stdpp < "${CI_BUILD_DIR}/Iris/opam" | sed 's/.*"dev\.[0-9.-]\+\.\([0-9a-z]\+\)".*/\1/')
# Setup std++
-git_checkout "${stdpp_CI_BRANCH}" "${stdpp_CI_GITURL}" "${stdpp_CI_DIR}" "${stdpp_SHA}"
+git_download stdpp
# Build std++
-( cd "${stdpp_CI_DIR}" && make && make install )
+( cd "${CI_BUILD_DIR}/stdpp" && make && make install )
-# Build and validate (except on Travis, i.e., skip if TRAVIS is non-empty) Iris
-( cd "${Iris_CI_DIR}" && make && (test -n "${TRAVIS}" || make validate) && make install )
+# Build and validate Iris
+( cd "${CI_BUILD_DIR}/Iris" && make && make validate && make install )
# Build lambdaRust
-( cd "${lambdaRust_CI_DIR}" && make && make install )
+( cd "${CI_BUILD_DIR}/lambdaRust" && make && make install )
diff --git a/dev/ci/ci-ltac2.sh b/dev/ci/ci-ltac2.sh
index 5981aaaae7..4df22bf249 100755
--- a/dev/ci/ci-ltac2.sh
+++ b/dev/ci/ci-ltac2.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-ltac2_CI_DIR="${CI_BUILD_DIR}/ltac2"
+git_download ltac2
-git_checkout "${ltac2_CI_BRANCH}" "${ltac2_CI_GITURL}" "${ltac2_CI_DIR}"
-
-( cd "${ltac2_CI_DIR}" && make && make tests && make install )
+( cd "${CI_BUILD_DIR}/ltac2" && make && make tests && make install )
diff --git a/dev/ci/ci-math-classes.sh b/dev/ci/ci-math-classes.sh
index 6a064b2971..ae31a8e7f8 100755
--- a/dev/ci/ci-math-classes.sh
+++ b/dev/ci/ci-math-classes.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-math_classes_CI_DIR="${CI_BUILD_DIR}/math-classes"
+git_download math_classes
-git_checkout "${math_classes_CI_BRANCH}" "${math_classes_CI_GITURL}" "${math_classes_CI_DIR}"
-
-( cd "${math_classes_CI_DIR}" && ./configure.sh && make && make install )
+( cd "${CI_BUILD_DIR}/math_classes" && ./configure.sh && make && make install )
diff --git a/dev/ci/ci-math-comp.sh b/dev/ci/ci-math-comp.sh
index 20328baf2a..a74f9fa4d3 100755
--- a/dev/ci/ci-math-comp.sh
+++ b/dev/ci/ci-math-comp.sh
@@ -4,11 +4,10 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-mathcomp_CI_DIR="${CI_BUILD_DIR}/math-comp"
-oddorder_CI_DIR="${CI_BUILD_DIR}/odd-order"
+git_download mathcomp
-git_checkout "${mathcomp_CI_BRANCH}" "${mathcomp_CI_GITURL}" "${mathcomp_CI_DIR}"
-git_checkout "${oddorder_CI_BRANCH}" "${oddorder_CI_GITURL}" "${oddorder_CI_DIR}"
+( cd "${CI_BUILD_DIR}/mathcomp/mathcomp" && make && make install )
-( cd "${mathcomp_CI_DIR}/mathcomp" && make && make install )
-( cd "${oddorder_CI_DIR}/" && make )
+git_download oddorder
+
+( cd "${CI_BUILD_DIR}/oddorder" && make )
diff --git a/dev/ci/ci-mtac2.sh b/dev/ci/ci-mtac2.sh
index 1372acb8e5..7075d4d7f6 100755
--- a/dev/ci/ci-mtac2.sh
+++ b/dev/ci/ci-mtac2.sh
@@ -3,17 +3,10 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-unicoq_CI_DIR=${CI_BUILD_DIR}/unicoq
-mtac2_CI_DIR=${CI_BUILD_DIR}/Mtac2
+git_download unicoq
-# Setup UniCoq
+( cd "${CI_BUILD_DIR}/unicoq" && coq_makefile -f Make -o Makefile && make && make install )
-git_checkout "${unicoq_CI_BRANCH}" "${unicoq_CI_GITURL}" "${unicoq_CI_DIR}"
+git_download mtac2
-( cd "${unicoq_CI_DIR}" && coq_makefile -f Make -o Makefile && make && make install )
-
-# Setup MetaCoq
-
-git_checkout "${mtac2_CI_BRANCH}" "${mtac2_CI_GITURL}" "${mtac2_CI_DIR}"
-
-( cd "${mtac2_CI_DIR}" && coq_makefile -f _CoqProject -o Makefile && make )
+( cd "${CI_BUILD_DIR}/mtac2" && coq_makefile -f _CoqProject -o Makefile && make )
diff --git a/dev/ci/ci-pidetop.sh b/dev/ci/ci-pidetop.sh
index 32cba0808e..d22b9c8f7c 100755
--- a/dev/ci/ci-pidetop.sh
+++ b/dev/ci/ci-pidetop.sh
@@ -1,12 +1,9 @@
#!/usr/bin/env bash
-# $0 is not the safest way, but...
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-pidetop_CI_DIR="${CI_BUILD_DIR}/pidetop"
-
-git_checkout "${pidetop_CI_BRANCH}" "${pidetop_CI_GITURL}" "${pidetop_CI_DIR}"
+git_download pidetop
# Travis / Gitlab have different filesystem layout due to use of
# `-local`. We need to improve this divergence but if we use Dune this
@@ -17,6 +14,6 @@ else
COQLIB="$COQBIN/../"
fi
-( cd "${pidetop_CI_DIR}" && jbuilder build @install )
+( cd "${CI_BUILD_DIR}/pidetop" && jbuilder build @install )
-echo -en '4\nexit' | "$pidetop_CI_DIR/_build/install/default/bin/pidetop" -coqlib "$COQLIB" -main-channel stdfds
+echo -en '4\nexit' | "${CI_BUILD_DIR}/pidetop/_build/install/default/bin/pidetop" -coqlib "$COQLIB" -main-channel stdfds
diff --git a/dev/ci/ci-quickchick.sh b/dev/ci/ci-quickchick.sh
index fc39e2685d..08686d7ced 100755
--- a/dev/ci/ci-quickchick.sh
+++ b/dev/ci/ci-quickchick.sh
@@ -1,18 +1,10 @@
#!/usr/bin/env bash
ci_dir="$(dirname "$0")"
-
-# This script could be included inside other ones
-# Let's avoid to source ci-common twice in this case
-if [ -z "${CI_BUILD_DIR}" ];
-then
- . "${ci_dir}/ci-common.sh"
-fi
-
-quickchick_CI_DIR="${CI_BUILD_DIR}/Quickchick"
+. "${ci_dir}/ci-common.sh"
install_ssreflect
-git_checkout "${quickchick_CI_BRANCH}" "${quickchick_CI_GITURL}" "${quickchick_CI_DIR}"
+git_download quickchick
-( cd "${quickchick_CI_DIR}" && make && make install)
+( cd "${CI_BUILD_DIR}/quickchick" && make && make install)
diff --git a/dev/ci/ci-simple-io.sh b/dev/ci/ci-simple-io.sh
new file mode 100755
index 0000000000..e7bcd80de7
--- /dev/null
+++ b/dev/ci/ci-simple-io.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+
+ci_dir="$(dirname "$0")"
+. "${ci_dir}/ci-common.sh"
+
+git_download simple_io
+
+( cd "${CI_BUILD_DIR}/simple_io" && make build && make install)
diff --git a/dev/ci/ci-template.sh b/dev/ci/ci-template.sh
deleted file mode 100755
index e77a553047..0000000000
--- a/dev/ci/ci-template.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env bash
-
-ci_dir="$(dirname "$0")"
-. "${ci_dir}/ci-common.sh"
-
-Template_CI_BRANCH=master
-Template_CI_GITURL=https://github.com/Template/Template
-Template_CI_DIR="${CI_BUILD_DIR}/Template"
-
-git_checkout "${Template_CI_BRANCH}" "${Template_CI_GITURL}" "${Template_CI_DIR}"
-
-( cd "${Template_CI_DIR}" && make )
diff --git a/dev/ci/ci-tlc.sh b/dev/ci/ci-tlc.sh
index 31387c8ddc..a2f0bea555 100755
--- a/dev/ci/ci-tlc.sh
+++ b/dev/ci/ci-tlc.sh
@@ -3,8 +3,7 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-tlc_CI_DIR="${CI_BUILD_DIR}/tlc"
+FORCE_GIT=1
+git_download tlc
-git_checkout "${tlc_CI_BRANCH}" "${tlc_CI_GITURL}" "${tlc_CI_DIR}"
-
-( cd "${tlc_CI_DIR}" && make )
+( cd "${CI_BUILD_DIR}/tlc" && make )
diff --git a/dev/ci/ci-unimath.sh b/dev/ci/ci-unimath.sh
index aa20fe1ff0..a7644fee23 100755
--- a/dev/ci/ci-unimath.sh
+++ b/dev/ci/ci-unimath.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-UniMath_CI_DIR="${CI_BUILD_DIR}/UniMath"
+git_download UniMath
-git_checkout "${UniMath_CI_BRANCH}" "${UniMath_CI_GITURL}" "${UniMath_CI_DIR}"
-
-( cd "${UniMath_CI_DIR}" && make BUILD_COQ=no )
+( cd "${CI_BUILD_DIR}/UniMath" && make BUILD_COQ=no )
diff --git a/dev/ci/ci-vst.sh b/dev/ci/ci-vst.sh
index 7a097eaab4..0fec19205a 100755
--- a/dev/ci/ci-vst.sh
+++ b/dev/ci/ci-vst.sh
@@ -3,8 +3,6 @@
ci_dir="$(dirname "$0")"
. "${ci_dir}/ci-common.sh"
-VST_CI_DIR="${CI_BUILD_DIR}/VST"
+git_download VST
-git_checkout "${VST_CI_BRANCH}" "${VST_CI_GITURL}" "${VST_CI_DIR}"
-
-( cd "${VST_CI_DIR}" && make IGNORECOQVERSION=true )
+( cd "${CI_BUILD_DIR}/VST" && make IGNORECOQVERSION=true )
diff --git a/dev/ci/docker/bionic_coq/Dockerfile b/dev/ci/docker/bionic_coq/Dockerfile
index 52f851917e..7a649591dd 100644
--- a/dev/ci/docker/bionic_coq/Dockerfile
+++ b/dev/ci/docker/bionic_coq/Dockerfile
@@ -1,4 +1,4 @@
-# CACHEKEY: "bionic_coq-V2018-06-13-V1"
+# CACHEKEY: "bionic_coq-V2018-08-27-V2"
# ^^ Update when modifying this file.
FROM ubuntu:bionic
@@ -6,10 +6,12 @@ LABEL maintainer="e@x80.org"
ENV DEBIAN_FRONTEND="noninteractive"
-RUN apt-get update -qq && apt-get install -y -qq m4 wget time gcc-multilib opam \
+RUN apt-get update -qq && apt-get install --no-install-recommends -y -qq \
+ m4 automake autoconf time wget rsync git gcc-multilib opam \
libgtk2.0-dev libgtksourceview2.0-dev \
- texlive-latex-extra texlive-fonts-recommended texlive-science \
- python3-sphinx python3-pexpect python3-sphinx-rtd-theme python3-bs4 python3-sphinxcontrib.bibtex python3-pip
+ texlive-latex-extra texlive-fonts-recommended texlive-science tipa \
+ python3-sphinx python3-pexpect python3-sphinx-rtd-theme python3-bs4 python3-sphinxcontrib.bibtex \
+ python3-setuptools python3-wheel python3-pip
RUN pip3 install antlr4-python3-runtime
@@ -26,8 +28,8 @@ RUN opam init -a -y -j $NJOBS --compiler="$COMPILER" default https://opam.ocaml.
# Common OPAM packages.
# `num` does not have a version number as the right version to install varies
# with the compiler version.
-ENV BASE_OPAM="num ocamlfind.1.8.0 jbuilder.1.0+beta20 ounit.2.0.8" \
- CI_OPAM="menhir.20180530 elpi.1.0.4 ocamlgraph.1.8.8"
+ENV BASE_OPAM="num ocamlfind.1.8.0 dune.1.1.1 ounit.2.0.8" \
+ CI_OPAM="menhir.20180530 elpi.1.0.5 ocamlgraph.1.8.8"
# BASE switch; CI_OPAM contains Coq's CI dependencies.
ENV CAMLP5_VER="6.14" \
@@ -41,8 +43,8 @@ RUN opam switch -y -j $NJOBS "${COMPILER}+32bit" && eval $(opam config env) && \
opam install -j $NJOBS $BASE_OPAM camlp5.$CAMLP5_VER
# EDGE switch
-ENV COMPILER_EDGE="4.06.1" \
- CAMLP5_VER_EDGE="7.05" \
+ENV COMPILER_EDGE="4.07.0" \
+ CAMLP5_VER_EDGE="7.06" \
COQIDE_OPAM_EDGE="lablgtk.2.18.6 conf-gtksourceview.2"
RUN opam switch -y -j $NJOBS $COMPILER_EDGE && eval $(opam config env) && \
diff --git a/dev/ci/gitlab.bat b/dev/ci/gitlab.bat
index 70278e6d09..973319de68 100644
--- a/dev/ci/gitlab.bat
+++ b/dev/ci/gitlab.bat
@@ -28,7 +28,7 @@ if exist %DESTCOQ%\ rd /s /q %DESTCOQ%
call %CI_PROJECT_DIR%\dev\build\windows\MakeCoq_MinGW.bat -threads=1 ^
-arch=%ARCH% -installer=Y -coqver=%CI_PROJECT_DIR_CFMT% ^
-destcyg=%CYGROOT% -destcoq=%DESTCOQ% -cygcache=%CYGCACHE% ^
- -addon=bignums -make=N ^
+ -addon="bignums ltac2 equations" -make=N ^
-setup %CI_PROJECT_DIR%\%SETUP% || GOTO ErrorExit
copy "%CYGROOT%\build\coq-local\dev\nsis\*.exe" dev\nsis || GOTO ErrorExit
diff --git a/dev/ci/user-overlays/00664-herbelin-master+change-for-coq-pr664-compatibility.sh b/dev/ci/user-overlays/00664-herbelin-master+change-for-coq-pr664-compatibility.sh
deleted file mode 100644
index 9d96b6d4cf..0000000000
--- a/dev/ci/user-overlays/00664-herbelin-master+change-for-coq-pr664-compatibility.sh
+++ /dev/null
@@ -1,4 +0,0 @@
- if [ "$CI_PULL_REQUEST" = "664" ] || [ "$CI_BRANCH" = "trunk+fix-5500-too-weak-test-return-clause" ]; then
- fiat_parsers_CI_BRANCH=master+change-for-coq-pr664-compatibility
- fiat_parsers_CI_GITURL=https://github.com/herbelin/fiat
-fi
diff --git a/dev/ci/user-overlays/00669-maximedenes-ssr-merge.sh b/dev/ci/user-overlays/00669-maximedenes-ssr-merge.sh
index e9ba114148..d812df3ec0 100644
--- a/dev/ci/user-overlays/00669-maximedenes-ssr-merge.sh
+++ b/dev/ci/user-overlays/00669-maximedenes-ssr-merge.sh
@@ -1,6 +1,6 @@
#!/bin/sh
if [ "$CI_PULL_REQUEST" = "669" ] || [ "$CI_BRANCH" = "ssr-merge" ]; then
- mathcomp_CI_BRANCH=ssr-merge
- mathcomp_CI_GITURL=https://github.com/maximedenes/math-comp.git
+ mathcomp_CI_REF=ssr-merge
+ mathcomp_CI_GITURL=https://github.com/maximedenes/math-comp
fi
diff --git a/dev/ci/user-overlays/06454-ejgallego-evar+strict_to_constr.sh b/dev/ci/user-overlays/06454-ejgallego-evar+strict_to_constr.sh
deleted file mode 100644
index f4cb71cf19..0000000000
--- a/dev/ci/user-overlays/06454-ejgallego-evar+strict_to_constr.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-if [ "$CI_PULL_REQUEST" = "6454" ] || [ "$CI_BRANCH" = "evar+strict_to_constr" ]; then
-
- # ltac2_CI_BRANCH=econstr+more_fix
- # ltac2_CI_GITURL=https://github.com/ejgallego/ltac2
-
- Equations_CI_BRANCH=evar+strict_to_constr
- Equations_CI_GITURL=https://github.com/ejgallego/Coq-Equations
-fi
diff --git a/dev/ci/user-overlays/06859-ejgallego-stm+top.sh b/dev/ci/user-overlays/06859-ejgallego-stm+top.sh
deleted file mode 100644
index b22ab36302..0000000000
--- a/dev/ci/user-overlays/06859-ejgallego-stm+top.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-
-if [ "$CI_PULL_REQUEST" = "6859" ] || [ "$CI_BRANCH" = "stm+top" ] || \
- [ "$CI_PULL_REQUEST" = "7543" ] || [ "$CI_BRANCH" = "ide+split" ] ; then
-
- pidetop_CI_BRANCH=stm+top
- pidetop_CI_GITURL=https://bitbucket.org/ejgallego/pidetop.git
-
-fi
diff --git a/dev/ci/user-overlays/06960-ejgallego-ltac+tacdepr.sh b/dev/ci/user-overlays/06960-ejgallego-ltac+tacdepr.sh
deleted file mode 100644
index cf2af9ae95..0000000000
--- a/dev/ci/user-overlays/06960-ejgallego-ltac+tacdepr.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-if [ "$CI_PULL_REQUEST" = "6960" ] || [ "$CI_BRANCH" = "ltac+tacdepr" ]; then
-
- # Equations_CI_BRANCH=ssr+correct_packing
- # Equations_CI_GITURL=https://github.com/ejgallego/Coq-Equations
-
- ltac2_CI_BRANCH=ltac+tacdepr
- ltac2_CI_GITURL=https://github.com/ejgallego/ltac2
-
- # Elpi_CI_BRANCH=ssr+correct_packing
- # Elpi_CI_GITURL=https://github.com/ejgallego/coq-elpi.git
-
-fi
diff --git a/dev/ci/user-overlays/07085-ppedrot-pure-sharing-flag.sh b/dev/ci/user-overlays/07085-ppedrot-pure-sharing-flag.sh
new file mode 100644
index 0000000000..575df07425
--- /dev/null
+++ b/dev/ci/user-overlays/07085-ppedrot-pure-sharing-flag.sh
@@ -0,0 +1,8 @@
+_OVERLAY_BRANCH=pure-sharing-flag
+
+if [ "$CI_PULL_REQUEST" = "7085" ] || [ "$CI_BRANCH" = "$_OVERLAY_BRANCH" ]; then
+
+ mtac2_CI_BRANCH="$_OVERLAY_BRANCH"
+ mtac2_CI_GITURL=https://github.com/ppedrot/Mtac2
+
+fi
diff --git a/dev/ci/user-overlays/07099-ppedrot-unification-returns-option.sh b/dev/ci/user-overlays/07099-ppedrot-unification-returns-option.sh
deleted file mode 100644
index e6c48d10a6..0000000000
--- a/dev/ci/user-overlays/07099-ppedrot-unification-returns-option.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-if [ "$CI_PULL_REQUEST" = "7099" ] || [ "$CI_BRANCH" = "unification-returns-option" ]; then
- Equations_CI_BRANCH=unification-returns-option
- Equations_CI_GITURL=https://github.com/ppedrot/Coq-Equations
-fi
diff --git a/dev/ci/user-overlays/07136-evar-map-econstr.sh b/dev/ci/user-overlays/07136-evar-map-econstr.sh
deleted file mode 100644
index 06aa62726d..0000000000
--- a/dev/ci/user-overlays/07136-evar-map-econstr.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-if [ "$CI_PULL_REQUEST" = "7136" ] || [ "$CI_BRANCH" = "evar-map-econstr" ]; then
- Equations_CI_BRANCH=8.9+alpha
- Equations_CI_GITURL=https://github.com/SkySkimmer/Coq-Equations.git
-
- Elpi_CI_BRANCH=coq-7136
- Elpi_CI_GITURL=https://github.com/SkySkimmer/coq-elpi.git
-fi
diff --git a/dev/ci/user-overlays/07152-ejgallego-api+vernac_expr_iso.sh b/dev/ci/user-overlays/07152-ejgallego-api+vernac_expr_iso.sh
deleted file mode 100644
index 7e554684e8..0000000000
--- a/dev/ci/user-overlays/07152-ejgallego-api+vernac_expr_iso.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-if [ "$CI_PULL_REQUEST" = "7152" ] || [ "$CI_BRANCH" = "api+vernac_expr_iso" ]; then
-
- # Equations_CI_BRANCH=ssr+correct_packing
- # Equations_CI_GITURL=https://github.com/ejgallego/Coq-Equations
-
- # ltac2_CI_BRANCH=ssr+correct_packing
- # ltac2_CI_GITURL=https://github.com/ejgallego/ltac2
-
- Elpi_CI_BRANCH=api+vernac_expr_iso
- Elpi_CI_GITURL=https://github.com/ejgallego/coq-elpi.git
-
-fi
diff --git a/dev/ci/user-overlays/07196-ejgallego-tactics+push_fix_naming_out.sh b/dev/ci/user-overlays/07196-ejgallego-tactics+push_fix_naming_out.sh
deleted file mode 100644
index ea9cd8ee07..0000000000
--- a/dev/ci/user-overlays/07196-ejgallego-tactics+push_fix_naming_out.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-if [ "$CI_PULL_REQUEST" = "7196" ] || [ "$CI_BRANCH" = "tactics+push_fix_naming_out" ] || [ "$CI_BRANCH" = "pr-7196" ]; then
-
- # Needed overlays: https://gitlab.com/coq/coq/pipelines/21244550
- #
- # equations
- # ltac2
-
- # The below developments should instead use a backwards compatible fix.
- #
- # color
- # iris-lambda-rust
- # math-classes
- # formal-topology
-
- ltac2_CI_BRANCH=tactics+push_fix_naming_out
- ltac2_CI_GITURL=https://github.com/ejgallego/ltac2
-
- Equations_CI_BRANCH=tactics+push_fix_naming_out
- Equations_CI_GITURL=https://github.com/ejgallego/Coq-Equations
-
-fi
diff --git a/dev/ci/user-overlays/07213-ppedrot-fast-constr-match-no-context.sh b/dev/ci/user-overlays/07213-ppedrot-fast-constr-match-no-context.sh
deleted file mode 100644
index 517088a247..0000000000
--- a/dev/ci/user-overlays/07213-ppedrot-fast-constr-match-no-context.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-if [ "$CI_PULL_REQUEST" = "7213" ] || [ "$CI_BRANCH" = "fast-constr-match-no-context" ]; then
-
- ltac2_CI_BRANCH=fast-constr-match-no-context
- ltac2_CI_GITURL=https://github.com/ppedrot/ltac2
-
-fi
diff --git a/dev/ci/user-overlays/07495-gares-elpi-test-bug.sh b/dev/ci/user-overlays/07495-gares-elpi-test-bug.sh
deleted file mode 100644
index 6939ead2ba..0000000000
--- a/dev/ci/user-overlays/07495-gares-elpi-test-bug.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-if [ "$CI_PULL_REQUEST" = "7495" ] || [ "$CI_BRANCH" = "fix-restrict" ]; then
-
- # this branch contains a commit not present on coq-master that triggers
- # the universe restriction bug #7472
- Elpi_CI_BRANCH=overlay-7495
- Elpi_CI_GITURL=https://github.com/LPCIC/coq-elpi.git
-
-fi
diff --git a/dev/ci/user-overlays/07558-ejgallego-vernac+move_parser.sh b/dev/ci/user-overlays/07558-ejgallego-vernac+move_parser.sh
deleted file mode 100644
index 115f29f1ee..0000000000
--- a/dev/ci/user-overlays/07558-ejgallego-vernac+move_parser.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-if [ "$CI_PULL_REQUEST" = "7558" ] || [ "$CI_BRANCH" = "vernac+move_parser" ]; then
-
- _OVERLAY_BRANCH=vernac+move_parser
-
- Equations_CI_BRANCH="$_OVERLAY_BRANCH"
- Equations_CI_GITURL=https://github.com/ejgallego/Coq-Equations
-
- ltac2_CI_BRANCH="$_OVERLAY_BRANCH"
- ltac2_CI_GITURL=https://github.com/ejgallego/ltac2
-
- mtac2_CI_BRANCH="$_OVERLAY_BRANCH"
- mtac2_CI_GITURL=https://github.com/ejgallego/Mtac2
-
-fi
diff --git a/dev/ci/user-overlays/07677-ejgallego-misctypes+bye2.sh b/dev/ci/user-overlays/07677-ejgallego-misctypes+bye2.sh
deleted file mode 100644
index b4f7161395..0000000000
--- a/dev/ci/user-overlays/07677-ejgallego-misctypes+bye2.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-_OVERLAY_BRANCH=misctypes+bye2
-
-if [ "$CI_PULL_REQUEST" = "7677" ] || [ "$CI_BRANCH" = "_OVERLAY_BRANCH" ]; then
-
- Equations_CI_BRANCH="$_OVERLAY_BRANCH"
- Equations_CI_GITURL=https://github.com/ejgallego/Coq-Equations
-
-fi
diff --git a/dev/ci/user-overlays/07797-rm-reference.sh b/dev/ci/user-overlays/07797-rm-reference.sh
deleted file mode 100644
index f7811cd6f8..0000000000
--- a/dev/ci/user-overlays/07797-rm-reference.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-_OVERLAY_BRANCH=rm-reference
-
-if [ "$CI_PULL_REQUEST" = "7797" ] || [ "$CI_BRANCH" = "_OVERLAY_BRANCH" ]; then
-
- Equations_CI_BRANCH="$_OVERLAY_BRANCH"
- Equations_CI_GITURL=https://github.com/maximedenes/Coq-Equations.git
-
- ltac2_CI_BRANCH="fix-7797"
- ltac2_CI_GITURL=https://github.com/ppedrot/Ltac2.git
-
- quickchick_CI_BRANCH="$_OVERLAY_BRANCH"
- quickchick_CI_GITURL=https://github.com/maximedenes/QuickChick.git
-
- coq_dpdgraph_CI_BRANCH="$_OVERLAY_BRANCH"
- coq_dpdgraph_CI_GITURL=https://github.com/maximedenes/coq-dpdgraph.git
-
- Elpi_CI_BRANCH="$_OVERLAY_BRANCH"
- Elpi_CI_GITURL=https://github.com/maximedenes/coq-elpi.git
-
-fi
diff --git a/dev/ci/user-overlays/README.md b/dev/ci/user-overlays/README.md
index 41212568d8..68afe7ee4a 100644
--- a/dev/ci/user-overlays/README.md
+++ b/dev/ci/user-overlays/README.md
@@ -7,8 +7,12 @@ request to test it with the adapted version of the external project.
An overlay is a file which defines where to look for the patched version so that
testing is possible. It redefines some variables from
[`ci-basic-overlay.sh`](../ci-basic-overlay.sh):
-give the name of your branch using a `_CI_BRANCH` variable and the location of
-your fork using a `_CI_GITURL` variable.
+give the name of your branch / commit using a `_CI_REF` variable and the
+location of your fork using a `_CI_GITURL` variable.
+The `_CI_GITURL` variable should be the URL of the repository without a
+trailing `.git`.
+If the fork is not on the same platform (e.g. GitHub instead of GitLab), it is
+necessary to redefine the `_CI_ARCHIVEURL` variable as well.
Moreover, the file contains very simple logic to test the pull request number
or branch name and apply it only in this case.
@@ -23,8 +27,8 @@ Example: `00669-maximedenes-ssr-merge.sh` containing
#!/bin/sh
if [ "$CI_PULL_REQUEST" = "669" ] || [ "$CI_BRANCH" = "ssr-merge" ]; then
- mathcomp_CI_BRANCH=ssr-merge
- mathcomp_CI_GITURL=https://github.com/maximedenes/math-comp.git
+ mathcomp_CI_REF=ssr-merge
+ mathcomp_CI_GITURL=https://github.com/maximedenes/math-comp
fi
```
diff --git a/dev/doc/README.md b/dev/doc/README.md
new file mode 100644
index 0000000000..223cf6286e
--- /dev/null
+++ b/dev/doc/README.md
@@ -0,0 +1,77 @@
+# Beginner's guide to hacking Coq
+
+## Getting dependencies
+
+Assuming one is running Ubuntu (if not, replace `apt` with the package manager of choice)
+
+```
+$ sudo apt-get install make opam git
+
+# At the time of writing, <latest-ocaml-version> is 4.07.0.
+# The latest version number is available at: https://ocaml.org/releases/
+
+$ opam init --comp <latest-ocaml-version>
+
+# Then follow the advice displayed at the end as how to update your
+ ~/.bashrc and ~/.ocamlinit files.
+
+$ source ~/.bashrc
+$ opam install camlp5
+
+# needed if you want to build "coqide" target
+
+$ sudo apt-get install liblablgtksourceview2-ocaml-dev \
+ libgtk2.0-dev libgtksourceview2.0-dev
+$ opam install lablgtk
+```
+
+## Building `coqtop`
+The general workflow is to first setup a development environment with
+the correct `configure` settings, then hacking on Coq, make-ing, and testing.
+
+
+This document will use `$JOBS` to refer to the number of parallel jobs one
+is willing to have with `make`.
+
+
+```
+$ git clone git clone https://github.com/coq/coq.git
+$ cd coq
+$ ./configure -profile devel
+$ make -j $JOBS # Make once for `merlin`(autocompletion tool)
+
+<hack>
+
+$ make -j $JOBS states # builds just enough to run coqtop
+$ bin/coqtop -compile <test_file_name.v>
+<goto hack until stuff works>
+
+<run test-suite>
+```
+
+To learn how to run the test suite, you can read
+[`test-suite/README.md`](../../test-suite/README.md).
+
+## Coq functions of interest
+- `Coqtop.start`: This function is the main entry point of coqtop.
+- `Coqtop.parse_args `: This function is responsible for parsing command-line arguments.
+- `Coqloop.loop`: This function implements the read-eval-print loop.
+- `Vernacentries.interp`: This function is called to execute the Vernacular command user have typed.
+ It dispatches the control to specific functions handling different Vernacular command.
+- `Vernacentries.vernac_check_may_eval`: This function handles the `Check ...` command.
+
+
+## Development environment + tooling
+- [`Merlin`](https://github.com/ocaml/merlin) for autocomplete.
+- [Wiki pages on tooling containing `emacs`, `vim`, and `git` information](https://github.com/coq/coq/wiki/DevelSetup)
+
+## A note about rlwrap
+
+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
+```
+
+If this happens either update or use an alternate readline wrapper like `ledit`.
diff --git a/dev/doc/changes.md b/dev/doc/changes.md
index f3fc126f92..1eea2443fe 100644
--- a/dev/doc/changes.md
+++ b/dev/doc/changes.md
@@ -53,6 +53,16 @@ Printer.ml API
pr_subgoal and pr_goal was removed to simplify the code. It was
earlierly used by PCoq.
+Kernel
+
+ The following renamings happened:
+ - `Context.Rel.t` into `Constr.rel_context`
+ - `Context.Named.t` into `Constr.named_context`
+ - `Context.Compacted.t` into `Constr.compacted_context`
+ - `Context.Rel.Declaration.t` into `Constr.rel_declaration`
+ - `Context.Named.Declaration.t` into `Constr.named_declaration`
+ - `Context.Compacted.Declaration.t` into `Constr.compacted_declaration`
+
Source code organization
- We have eliminated / fused some redundant modules and relocated a
@@ -72,11 +82,119 @@ Vernacular commands
`tactics/`. In all cases adapting is a matter of changing the module
name.
+Primitive number parsers
+
+- For better modularity, the primitive parsers for positive, N and Z
+ have been split over three files (plugins/syntax/positive_syntax.ml,
+ plugins/syntax/n_syntax.ml, plugins/syntax/z_syntax.ml).
+
+Parsing
+
+- Manual uses of the Pcoq.Gram module have been deprecated. Wrapper modules
+ Pcoq.Entry and Pcoq.Parsable were introduced to replace it.
+
### Unit testing
The test suite now allows writing unit tests against OCaml code in the Coq
code base. Those unit tests create a dependency on the OUnit test framework.
+### Transitioning away from Camlp5
+
+In an effort to reduce dependency on camlp5, the use of several grammar macros
+is discouraged. Coq is now shipped with its own preprocessor, called coqpp,
+which serves the same purpose as camlp5.
+
+To perform the transition to coqpp macros, one first needs to change the
+extension of a macro file from `.ml4` to `.mlg`. Not all camlp5 macros are
+handled yet.
+
+Due to parsing constraints, the syntax of the macros is slightly different, but
+updating the source code is mostly a matter of straightforward
+search-and-replace. The main differences are summarized below.
+
+#### OCaml code
+
+Every piece of toplevel OCaml code needs to be wrapped into braces.
+
+For instance, code of the form
+```
+let myval = 0
+```
+should be turned into
+```
+{
+let myval = 0
+}
+```
+
+#### TACTIC EXTEND
+
+Steps to perform:
+- replace the brackets enclosing OCaml code in actions with braces
+- if not there yet, add a leading `|̀ to the first rule
+
+For instance, code of the form:
+```
+TACTIC EXTEND my_tac
+ [ "tac1" int_or_var(i) tactic(t) ] -> [ mytac1 ist i t ]
+| [ "tac2" tactic(t) ] -> [ mytac2 t ]
+END
+```
+should be turned into
+```
+TACTIC EXTEND my_tac
+| [ "tac1" int_or_var(i) tactic(t) ] -> { mytac1 ist i t }
+| [ "tac2" tactic(t) ] -> { mytac2 t }
+END
+```
+
+#### VERNAC EXTEND
+
+Not handled yet.
+
+#### ARGUMENT EXTEND
+
+Not handled yet.
+
+#### GEXTEND
+
+Most plugin writers do not need this low-level interface, but for the sake of
+completeness we document it.
+
+Steps to perform are:
+- replace GEXTEND with GRAMMAR EXTEND
+- wrap every occurrence of OCaml code in actions into braces { }
+
+For instance, code of the form
+```
+GEXTEND Gram
+ GLOBAL: my_entry;
+
+my_entry:
+[ [ x = bar; y = qux -> do_something x y
+ | "("; z = LIST0 my_entry; ")" -> do_other_thing z
+] ];
+END
+```
+should be turned into
+```
+GRAMMAR EXTEND Gram
+ GLOBAL: my_entry;
+
+my_entry:
+[ [ x = bar; y = qux -> { do_something x y }
+ | "("; z = LIST0 my_entry; ")" -> { do_other_thing z }
+] ];
+END
+```
+
+Caveats:
+- No `GLOBAL` entries mean that they are all local, while camlp5 special-cases
+ this as a shorthand for all global entries. Solution: always define a `GLOBAL`
+ section.
+- No complex patterns allowed in token naming. Solution: match on it inside the
+ OCaml quotation.
+
## Changes between Coq 8.7 and Coq 8.8
### Bug tracker
diff --git a/dev/doc/critical-bugs b/dev/doc/critical-bugs
new file mode 100644
index 0000000000..6166d24b70
--- /dev/null
+++ b/dev/doc/critical-bugs
@@ -0,0 +1,252 @@
+Preliminary compilation of critical bugs in stable releases of Coq
+==================================================================
+ WORK IN PROGRESS WITH SEVERAL OPEN QUESTIONS
+
+
+To add: #7723 (vm_compute universe polymorphism), #7695 (modules and algebraic universes), #7615 (lost functor substitutions)
+
+Typing constructions
+
+ component: "match"
+ summary: substitution missing in the body of a let
+ introduced: ?
+ impacted released versions: V8.3-V8.3pl2, V8.4-V8.4pl4
+ impacted development branches: none
+ impacted coqchk versions: ?
+ fixed in: master/trunk/v8.5 (e583a79b5, 22 Nov 2015, Herbelin), v8.4 (525056f1, 22 Nov 2015, Herbelin), v8.3 (4bed0289, 22 Nov 2015, Herbelin)
+ found by: Herbelin
+ exploit: test-suite/success/Case22.v
+ GH issue number: ?
+ risk: ?
+
+ component: fixpoint, guard
+ summary: missing lift in checking guard
+ introduced: probably from V5.10
+ impacted released versions: probably V5-V7, V8.0-V8.0pl4, V8.1-V8.1pl4
+ impacted development branches: v8.0 ?
+ impacted coqchk versions: ?
+ fixed in: master/trunk/v8.2 (ff45afa8, r11646, 2 Dec 2008, Barras), v8.1 (f8e7f273, r11648, 2 Dec 2008, Barras)
+ found by: Barras
+ exploit: test-suite/failure/guard.v
+ GH issue number: none
+ risk: unprobable by chance
+
+ component: cofixpoint, guard
+ summary: de Bruijn indice bug in checking guard of nested cofixpoints
+ introduced: after V6.3.1, before V7.0
+ impacted released versions: V8.0-V8.0pl4, V8.1-V8.1pl4, V8.2-V8.2pl2, V8.3-V8.3pl2, V8.4-V8.4pl4
+ impacted development branches: none
+ impacted coqchk versions: ?
+ fixed in: master (9f81e2c36, 10 Apr 2014, Dénès), v8.4 (f50ec9e7d, 11 Apr 2014, Dénès), v8.3 (40c0fe7f4, 11 Apr 2014, Dénès), v8.2 (06d66df8c, 11 Apr 2014, Dénès), v8.1 (977afae90, 11 Apr 2014, Dénès), v8.0 (f1d632992, 29 Nov 2015, Herbelin, backport)
+ found by: Dénès
+ exploit: ?
+ GH issue number: none ?
+ risk: ?
+
+ component: inductive types, elimination principle
+ summary: de Bruijn indice bug in computing allowed elimination principle
+ introduced: 23 May 2006, 9c2d70b, r8845, Herbelin (part of universe polymorphism)
+ impacted released versions: V8.1-V8.1pl4, V8.2-V8.2pl2, V8.3-V8.3pl2, V8.4-V8.4pl4
+ impacted development branches: none
+ impacted coqchk versions: ?
+ fixed in: master (8a01c3685, 24 Jan 2014, Dénès), v8.4 (8a01c3685, 25 Feb 2014, Dénès), v8.3 (2b3cc4f85, 25 Feb 2014, Dénès), v8.2 (459888488, 25 Feb 2014, Dénès), v8.1 (79aa20872, 25 Feb 2014, Dénès)
+ found by: Dénès
+ exploit: see GH#3211
+ GH issue number: #3211
+ risk: ?
+
+ component: universe subtyping
+ summary: bug in Prop<=Set conversion which made Set identifiable with Prop, preventing a proof-irrelevant interpretation of Prop
+ introduced: V8.2 (bba897d5f, 12 May 2008, Herbelin)
+ impacted released versions: V8.2-V8.2pl2
+ impacted development branches: none
+ impacted coqchk versions: ?
+ fixed in: master/trunk (679801, r13450, 23 Sep 2010, Glondu), v8.3 (309a53f2, r13449, 22 Sep 2010, Glondu), v8.2 (41ea5f08, r14263, 6 Jul 2011, Herbelin, backport)
+ found by: Georgi Guninski
+ exploit: test-suite/bugs/closed/4294.v
+ GH issue number: #4294
+ risk: ?
+
+Module system
+
+ component: modules, universes
+ summary: missing universe constraints in typing "with" clause of a module type
+ introduced: ?
+ impacted released versions: V8.3-V8.3pl2, V8.4-V8.4pl6; unclear for V8.2 and previous versions
+ impacted development branches: none
+ impacted coqchk versions: ?
+ fixed in: master/trunk (d4869e059, 2 Oct 2015, Sozeau), v8.4 (40350ef3b, 9 Sep 2015, Sozeau)
+ found by: Dénès
+ exploit: test-suite/bugs/closed/4294.v
+ GH issue number: #4294
+ risk: ?
+
+Module system
+
+ component: modules, universes
+ summary: universe constraints for module subtyping not stored in vo files
+ introduced: presumably 8.2 (b3d3b56)
+ impacted released versions: 8.2, 8.3, 8.4
+ impacted development branches: v8.5
+ impacted coqchk versions: none
+ fixed in: v8.2 (c1d9889), v8.3 (8056d02), v8.4 (a07deb4), trunk (0cd0a3e) Mar 5, 2014, Tassi
+ found by: Tassi by running coqchk on the mathematical components library
+ exploit: requires multiple files, no test provided
+ GH issue number: #3243
+ risk: could be exploited by mistake
+
+Universes
+
+ component: template polymorphism
+ summary: issue with two parameters in the same universe level
+ introduced: 23 May 2006, 9c2d70b, r8845, Herbelin
+ impacted released versions: V8.1-V8.1pl4, V8.2-V8.2pl2, V8.3-V8.3pl2
+ impacted development branches: none
+ impacted coqchk versions: ?
+ fixed in: trunk/master/v8.4 (8082d1faf, 5 Oct 2011, Herbelin), V8.3pl3 (bb582bca2, 5 Oct 2011, Herbelin), v8.2 branch (3333e8d3, 5 Oct 2011, Herbelin), v8.1 branch (a8fc2027, 5 Oct 2011, Herbelin),
+ found by: Barras
+ exploit: test-suite/failure/inductive4.v
+ GH issue number: none
+ risk: unlikely to be activated by chance
+
+Primitive projections
+
+ component: primitive projections, guard condition
+ summary: check of guardedness of extra arguments of primitive projections missing
+ introduced: 6 May 2014, a4043608f, Sozeau
+ impacted released versions: V8.5-V8.5pl2,
+ impacted development branches: none
+ impacted coqchk versions: ?
+ fixed in: trunk/master/v8.5 (ba00867d5, 25 Jul 2016, Sozeau)
+ found by: Sozeau, by analyzing bug report #4876
+ exploit: to be done (?)
+ GH issue number: #4876
+ risk: consequence of bug found by chance, unlikely to be exploited by chance (MS?)
+
+ component: primitive projections, guard condition
+ summary: records based on primitive projections became possibly recursive without the guard condition being updated
+ introduced: 10 Sep 2014, 6624459e4, Sozeau (?)
+ impacted released versions: V8.5
+ impacted development branches: none
+ impacted coqchk versions: ?
+ fixed in: trunk/master/v8.5 (120053a50, 4 Mar 2016, Dénès)
+ found by: Dénès exploiting bug #4588
+ exploit: test-suite/bugs/closed/4588.v
+ GH issue number: #4588
+ risk: ?
+
+Conversion machines
+
+ component: "lazy machine" (lazy krivine abstract machine)
+ summary: the invariant justifying some optimization was wrong for some combination of sharing side effects
+ introduced: prior to V7.0
+ impacted released versions: V8.0-V8.0pl4, V8.1-V8.1pl3
+ impacted development branches: none
+ impacted coqchk versions: (eefe63d52, Barras, 20 May 2008), was in beta-development for 8.2 at this time
+ fixed in: master/trunk/8.2 (f13aaec57/a8b034513, 15 May 2008, Barras), v8.1 (e7611477a, 15 May 2008, Barras), v8.0 (6ed40a8bc, 29 Nov 2016, Herbelin, backport)
+ found by: Gonthier
+ exploit: by Gonthier
+ GH issue number: none
+ risk: unrealistic to be exploited by chance
+
+ component: "virtual machine" (compilation to bytecode ran by a C-interpreter)
+ summary: collision between constructors when more than 256 constructors in a type
+ introduced: V8.1
+ impacted released versions: V8.1-V8.5pl3, V8.2-V8.2pl2, V8.3-V8.3pl3, V8.4-V8.4pl5
+ impacted development branches: none
+ impacted coqchk versions: none (no virtual machine in coqchk)
+ fixed in: master/trunk/v8.5 (00894adf6/596a4a525, 26-39 Mar 2015, Grégoire), v8.4 (cd2101a39, 1 Apr 2015, Grégoire), v8.3 (a0c7fc05b, 1 Apr 2015, Grégoire), v8.2 (2c6189f61, 1 Apr 2015, Grégoire), v8.1 (bb877e5b5, 29 Nov 2015, Herbelin, backport)
+ found by: Dénès, Pédrot
+ exploit: test-suite/failure/vm-bug4157.v
+ GH issue number: #4157
+ risk:
+
+ component: "virtual machine" (compilation to bytecode ran by a C-interpreter)
+ summary: wrong universe constraints
+ introduced: possibly exploitable from V8.1; exploitable at least from V8.5
+ impacted released versions: V8.1-V8.4pl5 unknown, V8.5-V8.5pl3, V8.6-V8.6.1, V8.7.0-V8.7.1
+ impacted development branches: unknown for v8.1-v8.4, none from v8.5
+ impacted coqchk versions: none (no virtual machine in coqchk)
+ fixed in: master (c9f3a6cbe, 12 Feb 2018, PR#6713, Dénès), v8.7 (c058a4182, 15 Feb 2018, Zimmermann, backport), v8.6 (a2cc54c64, 21 Feb 2018, Herbelin, backport), v8.5 (d4d550d0f, 21 Feb 2018, Herbelin, backport)
+ found by: Dénès
+ exploit: test-suite/bugs/closed/6677.v
+ GH issue number: #6677
+ risk:
+
+ component: "virtual machine" (compilation to bytecode ran by a C-interpreter)
+ summary: missing pops in executing 31bit arithmetic
+ introduced: V8.5
+ impacted released versions: V8.1-V8.4pl5
+ impacted development branches: v8.1 (probably)
+ impacted coqchk versions: none (no virtual machine in coqchk)
+ fixed in: master/trunk/v8.5 (a5e04d9dd, 6 Sep 2015, Dénès), v8.4 (d5aa3bf6, 9 Sep 2015, Dénès), v8.3 (5da5d751, 9 Sep 2015, Dénès), v8.2 (369e82d2, 9 Sep 2015, Dénès),
+ found by: Catalin Hritcu
+ exploit: lost?
+ GH issue number: ?
+ risk:
+
+ component: "native" conversion machine (translation to OCaml which compiles to native code)
+ summary: translation of identifier from Coq to OCaml was not bijective, leading to identify True and False
+ introduced: V8.5
+ impacted released versions: V8.5-V8.5pl1
+ impacted development branches: none
+ impacted coqchk versions: none (no native computation in coqchk)
+ fixed in: master/trunk/v8.6 (244d7a9aa, 19 May 2016, letouzey), v8.5 (088b3161c, 19 May 2016, letouzey),
+ found by: Letouzey, Dénès
+ exploit: lost?
+ GH issue number: ?
+ risk:
+
+Conflicts with axioms in library
+
+ component: library of real numbers
+ summary: axiom of description and decidability of equality on real numbers in library Reals was inconsistent with impredicative Set
+ introduced: 67c75fa01, 20 Jun 2002
+ impacted released versions: 7.3.1, 7.4
+ impacted coqchk versions:
+ fixed by deciding to drop impredicativity of Set: bac707973, 28 Oct 2004
+ found by: Herbelin & Werner
+ exploit: need to find the example again
+ GH issue number: no
+ risk: unlikely to be exploited by chance
+
+ component: library of extensional sets, guard condition
+ summary: guard condition was unknown to be inconsistent with propositional extensionality in library Sets
+ introduced: not a bug per se but an incompatibility discovered late
+ impacted released versions: technically speaking from V6.1 with the introduction of the Sets library which was then inconsistent from the very beginning without we knew it
+ impacted coqchk versions: ?
+ fixed by constraining the guard condition: (9b272a8, ccd7546c 28 Oct 2014, Barras, Dénès)
+ found by: Schepler, Dénès, Azevedo de Amorim
+ exploit: ?
+ GH issue number: none
+ risk: unlikely to be exploited by chance (?)
+
+ component: library for axiom of choice and excluded-middle
+ summary: incompatibility axiom of choice and excluded-middle with elimination of large singletons to Set
+ introduced: not a bug but a change of intended "model"
+ impacted released versions: strictly before 8.1
+ impacted coqchk versions: ?
+ fixed by constraining singleton elimination: b19397ed8, r9633, 9 Feb 2007, Herbelin
+ found by: Benjamin Werner
+ exploit:
+ GH issue number: none
+ risk:
+
+There were otherwise several bugs in beta-releases, from memory, bugs with beta versions of primitive projections or template polymorphism or native compilation or guard (e7fc96366, 2a4d714a1).
+
+There were otherwise maybe unexploitable kernel bugs, e.g. 2df88d83 (Require overloading), 0adf0838 ("Univs: uncovered bug in strengthening of opaque polymorphic definitions."), 5122a398 (#3746 about functors), #4346 (casts in VM), a14bef4 (guard condition in 8.1), 6ed40a8 ("Georges' bug" with ill-typed lazy machine), and various other bugs in 8.0 or 8.1 w/o knowing if they are critical.
+
+Another non exploitable bug?
+
+ component: "virtual machine" (compilation to bytecode ran by a C-interpreter)
+ summary: bug in 31bit arithmetic
+ introduced: V8.1
+ impacted released versions: none
+ impacted development branches:
+ impacted coqchk versions: none (no virtual machine in coqchk)
+ fixed in: master/trunk/v8.5 (0f8d1b92c, 6 Sep 2015, Dénès)
+ found by: Dénès, from a bug report by Tahina Ramananandro
+ exploit: ?
+ GH issue number: ?
+ risk:
+
diff --git a/dev/doc/setup.txt b/dev/doc/setup.txt
deleted file mode 100644
index c48c2d5d16..0000000000
--- a/dev/doc/setup.txt
+++ /dev/null
@@ -1,269 +0,0 @@
-This document provides detailed guidance on how to:
-- compile Coq
-- take advantage of Merlin in Emacs
-- enable auto-completion for Ocaml source-code
-- use ocamldebug in Emacs for debugging coqtop
-The instructions were tested with Debian 8.3 (Jessie).
-
-The procedure is somewhat tedious, but the final results are (still) worth the effort.
-
-How to compile Coq
-------------------
-
-Getting build dependencies:
-
- sudo apt-get install make opam git
- opam init --comp 4.02.3
- # Then follow the advice displayed at the end as how to update your ~/.bashrc and ~/.ocamlinit files.
-
- source ~/.bashrc
-
- # needed if you want to build "coqtop" target
- opam install camlp5
-
- # needed if you want to build "coqide" target
- sudo apt-get install liblablgtksourceview2-ocaml-dev libgtk2.0-dev libgtksourceview2.0-dev
- opam install lablgtk
-
- # needed if you want to build "doc" target
- sudo apt-get install texlive-latex-recommended texlive-fonts-extra texlive-math-extra \
- hevea texlive-latex-extra latex-xcolor
-
-Cloning Coq:
-
- # Go to the directory where you want to clone Coq's source-code. E.g.:
- cd ~/git
-
- git clone https://github.com/coq/coq.git
-
-Building coqtop:
-
- cd ~/git/coq
- git checkout trunk
- make distclean
- ./configure -profile devel
- make clean
- make -j4 coqide printers
-
-The "-profile devel" enables all options recommended for developers (like
-warnings, support for Merlin, etc). Moreover Coq is configured so that
-it can be run without installing it (i.e. from the current directory).
-
-Once the compilation is over check if
-- bin/coqtop
-- bin/coqide
-behave as expected.
-
-
-A note about rlwrap
--------------------
-
-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
-
-If this happens either update or use an alternate readline wrapper like "ledit".
-
-
-How to install and configure Merlin (for Emacs)
------------------------------------------------
-
- sudo apt-get install emacs
-
- opam install tuareg
- # Follow the advice displayed at the end as how to update your ~/.emacs file.
-
- opam install merlin
- # Follow the advice displayed at the end as how to update your ~/.emacs file.
-
-Then add this:
-
- (push "~/.opam/4.02.3/share/emacs/site-lisp" load-path) ; directory containing merlin.el
- (setq merlin-command "~/.opam/4.02.3/bin/ocamlmerlin") ; needed only if ocamlmerlin not already in your PATH
- (autoload 'merlin-mode "merlin" "Merlin mode" t)
- (add-hook 'tuareg-mode-hook 'merlin-mode)
- (add-hook 'caml-mode-hook 'merlin-mode)
- (load "~/.opam/4.02.3/share/emacs/site-lisp/tuareg-site-file")
-
- ;; Do not use TABs. These confuse Merlin.
- (setq-default indent-tabs-mode nil)
-
-to your ~/.emacs file.
-
-Further Emacs configuration when we start it for the first time.
-
-Try to open some *.ml file in Emacs, e.g.:
-
- cd ~/git/coq
- emacs toplevel/coqtop.ml &
-
-Emacs display the following strange message:
-
- The local variables list in ~/git/coq
- contains values that may be safe (*).
-
- Do you want to apply it?
-
-Just press "!", i.e. "apply the local variable list, and permanently mark these values (\*) as safe."
-
-Emacs then shows two windows:
-- one window that shows the contents of the "toplevel/coqtop.ml" file
-- and the other window that shows greetings for new Emacs users.
-
-If you do not want to see the second window next time you start Emacs, just check "Never show it again" and click on "Dismiss this startup screen."
-
-The default key-bindings are described here:
-
- https://github.com/the-lambda-church/merlin/wiki/emacs-from-scratch
-
-If you want, you can customize them by replacing the following lines:
-
- (define-key merlin-map (kbd "C-c C-x") 'merlin-error-next)
- (define-key merlin-map (kbd "C-c C-l") 'merlin-locate)
- (define-key merlin-map (kbd "C-c &") 'merlin-pop-stack)
- (define-key merlin-map (kbd "C-c C-t") 'merlin-type-enclosing)
-
-in the file "~/.opam/4.02.3/share/emacs/site-lisp/merlin.el" with what you want.
-In the text below we assume that you changed the origin key-bindings in the following way:
-
- (define-key merlin-map (kbd "C-n") 'merlin-error-next)
- (define-key merlin-map (kbd "C-l") 'merlin-locate)
- (define-key merlin-map (kbd "C-b") 'merlin-pop-stack)
- (define-key merlin-map (kbd "C-t") 'merlin-type-enclosing)
-
-Now, when you press <Ctrl+L>, Merlin will show the definition of the symbol in a separate window.
-If you prefer to jump to the definition within the same window, do this:
-
- <Alt+X> customize-group <ENTER> merlin <ENTER>
-
- Merlin Locate In New Window
-
- Value Menu
-
- Never Open In New Window
-
- State
-
- Set For Future Sessions
-
-Testing (Merlin):
-
- cd ~/git/coq
- emacs toplevel/coqtop.ml &
-
-Go to the end of the file where you will see the "start" function.
-
-Go to a line where "init_toplevel" function is called.
-
-If you want to jump to the position where that function or datatype under the cursor is defined, press <Ctrl+L>.
-
-If you want to jump back, type: <Ctrl+B>
-
-If you want to learn the type of the value at current cursor's position, type: <Ctrl+T>
-
-
-Enabling auto-completion in emacs
----------------------------------
-
-In Emacs, type: <Alt+M> list-packages <ENTER>
-
-In the list that is displayed, click on "company".
-
-A new window appears where just click on "Install" and then answer "Yes".
-
-These lines:
-
- (package-initialize)
- (require 'company)
- ; Make company aware of merlin
- (add-to-list 'company-backends 'merlin-company-backend)
- ; Enable company on merlin managed buffers
- (add-hook 'merlin-mode-hook 'company-mode)
- (global-set-key [C-tab] 'company-complete)
-
-then need to be added to your "~/.emacs" file.
-
-Next time when you start emacs and partially type some identifier,
-emacs will offer the corresponding completions.
-Auto-completion can also be manually invoked by typing <Ctrl+TAB>.
-Description of various other shortcuts is here.
-
- http://company-mode.github.io/
-
-
-Getting along with ocamldebug
------------------------------
-
-The default ocamldebug key-bindings are described here.
-
- http://caml.inria.fr/pub/docs/manual-ocaml/debugger.html#sec369
-
-If you want, you can customize them by putting the following commands:
-
- (global-set-key (kbd "<f5>") 'ocamldebug-break)
- (global-set-key (kbd "<f6>") 'ocamldebug-run)
- (global-set-key (kbd "<f7>") 'ocamldebug-next)
- (global-set-key (kbd "<f8>") 'ocamldebug-step)
- (global-set-key (kbd "<f9>") 'ocamldebug-finish)
- (global-set-key (kbd "<f10>") 'ocamldebug-print)
- (global-set-key (kbd "<f12>") 'camldebug)
-
-to your "~/.emacs" file.
-
-Let us try whether ocamldebug in Emacs works for us.
-(If necessary, re-)compile coqtop:
-
- cd ~/git/coq
- make -j4 coqide printers
-
-open Emacs:
-
- emacs toplevel/coqtop.ml &
-
-and type:
-
- <F12> ../bin/coqtop.byte <ENTER> ../dev/ocamldebug-coq <ENTER>
-
-As a result, a new window is open at the bottom where you should see:
-
- (ocd)
-
-i.e. an ocamldebug shell.
-
- 1. Switch to the window that contains the "coqtop.ml" file.
- 2. Go to the end of the file.
- 3. Find the definition of the "start" function.
- 4. Go to the "let" keyword that is at the beginning of the first line.
- 5. By pressing <F5> you set a breakpoint to the cursor's position.
- 6. By pressing <F6> you start the bin/coqtop process.
- 7. Then you can:
- - step over function calls: <F7>
- - step into function calls: <F8>
- - or finish execution of the current function until it returns: <F9>.
-
-Other ocamldebug commands, can be typed to the window that holds the ocamldebug shell.
-
-The points at which the execution of Ocaml program can stop are defined here:
-
- http://caml.inria.fr/pub/docs/manual-ocaml/debugger.html#sec350
-
-
-Installing printers to ocamldebug
----------------------------------
-
-There is a pretty comprehensive set of printers defined for many common data types.
-You can load them by switching to the window holding the "ocamldebug" shell and typing:
-
- (ocd) source "../dev/db"
-
-
-Some of the functions were you might want to set a breakpoint and see what happens next
----------------------------------------------------------------------------------------
-
-- Coqtop.start : This function is the main entry point of coqtop.
-- Coqtop.parse_args : This function is responsible for parsing command-line arguments.
-- Coqloop.loop : This function implements the read-eval-print loop.
-- Vernacentries.interp : This function is called to execute the Vernacular command user have typed.\
- It dispatches the control to specific functions handling different Vernacular command.
-- Vernacentries.vernac_check_may_eval : This function handles the "Check ..." command.
diff --git a/dev/doc/translate.txt b/dev/doc/translate.txt
deleted file mode 100644
index 5b372c96c3..0000000000
--- a/dev/doc/translate.txt
+++ /dev/null
@@ -1,495 +0,0 @@
-
- How to use the translator
- =========================
-
- (temporary version to be included in the official
- TeX document describing the translator)
-
-The translator is a smart, robust and powerful tool to improve the
-readibility of your script. The current document describes the
-possibilities of the translator.
-
-In case of problem recompiling the translated files, don't waste time
-to modify the translated file by hand, read first the following
-document telling on how to modify the original files to get a smooth
-uniform safe translation. All 60000 lines of Coq lines on our
-user-contributions server have been translated without any change
-afterwards, and 0,5 % of the lines of the original files (mainly
-notations) had to be modified beforehand to get this result.
-
-Table of contents
------------------
-
-I) Implicit Arguments
- 1) Strict Implicit Arguments
- 2) Implicit Arguments in standard library
-
-II) Notations
- 1) Translating a V7 notation as it was
- 2) Translating a V7 notation which conflicts with the new syntax
- a) Associativity conflicts
- b) Conflicts with other notations
- b1) A notation hides another notation
- b2) A notation conflicts with the V8 grammar
- b3) My notation is already defined at another level
- c) How to use V8only with Distfix ?
- d) Can I overload a notation in V8, e.g. use "*" and "+" ?
- 3) Using the translator to have simplest notations
- 4) Setting the translator to automatically use new notations that
- wasn't used in old syntax
- 5) Defining a construction and its notation simultaneously
-
-III) Various pitfalls
- 1) New keywords
- 2) Old "Case" and "Match"
- 3) Change of definition or theorem names
- 4) Change of tactic names
-
----------------------------------------------------------------------
-
-I) Implicit Arguments
- ------------------
-
-1) Strict Implicit Arguments
-
- "Set Implicit Arguments" changes its meaning in V8: the default is
-to turn implicit only the arguments that are _strictly_ implicit (or
-rigid), i.e. that remains inferable whatever the other arguments
-are. E.g "x" inferable from "P x" is not strictly inferable since it
-can disappears if "P" is instanciated by a term which erase "x".
-
- To respect the old semantics, the default behaviour of the
-translator is to replace each occurrence "Set Implicit Arguments" by
-
- Set Implicit Arguments.
- Unset Strict Implicits.
-
- However, you may wish to adopt the new semantics of "Set Implicit
-Arguments" (for instance because you think that the choice of
-arguments it setsimplicit is more "natural" for you). In this case,
-add the option -strict-implicit to the translator.
-
- Warning: Changing the number of implicit arguments can break the
-notations. Then use the V8only modifier of Notations.
-
-2) Implicit Arguments in standard library
-
- Main definitions of standard library have now implicit
-arguments. These arguments are dropped in the translated files. This
-can exceptionally be a source of incompatibilities which has to be
-solved by hand (it typically happens for polymorphic functions applied
-to "nil" or "None").
-
-II) Notations
- ---------
-
- Grammar (on constr) and Syntax are no longer supported. Replace them by
-Notation before translation.
-
- Precedence levels are now from 0 to 200. In V8, the precedence and
-associativity of an operator cannot be redefined. Typical level are
-(refer to the chapter on notations in the Reference Manual for the
-full list):
-
- <-> : 95 (no associativity)
- -> : 90 (right associativity)
- \/ : 85 (right associativity)
- /\ : 80 (right associativity)
- ~ : 75 (right associativity)
- =, <, >, <=, >=, <> : 70 (no associativity)
- +, - : 50 (left associativity)
- *, / : 40 (left associativity)
- ^ : 30 (right associativity)
-
-1) Translating a V7 notation as it was
-
- By default, the translator keeps the associativity given in V7 while
-the levels are mapped according to the following table:
-
- the V7 levels [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
- are resp. mapped in V8 to [ 0; 20; 30; 40; 50; 70; 80; 85; 90; 95; 100]
- with predefined assoc [ No; L; R; L; L; No; R; R; R; No; L]
-
- If this is OK for you, just simply apply the translator.
-
-2) Translating a V7 notation which conflicts with the new syntax
-
-a) Associativity conflict
-
- Since the associativity of the levels obtained by translating a V7
-level (as shown on table above) cannot be changed, you have to choose
-another level with a compatible associativity.
-
- You can choose any level between 0 and 200, knowing that the
-standard operators are already set at the levels shown on the list
-above.
-
-Example 1: Assume you have a notation
-
-Infix NONA 2 "=_S" my_setoid_eq.
-
-By default, the translator moves it to level 30 which is right
-associative, hence a conflict with the expected no associativity.
-
-To solve the problem, just add the "V8only" modifier to reset the
-level and enforce the associativity as follows:
-
-Infix NONA 2 "=_S" my_setoid_eq V8only (at level 70, no associativity).
-
-The translator now knows that it has to translate "=_S" at level 70
-with no associativity.
-
-Rem: 70 is the "natural" level for relations, hence the choice of 70
-here, but any other level accepting a no-associativity would have been
-OK.
-
-Example 2: Assume you have a notation
-
-Infix RIGHTA 1 "o" my_comp.
-
-By default, the translator moves it to level 20 which is left
-associative, hence a conflict with the expected right associativity.
-
-To solve the problem, just add the "V8only" modifier to reset the
-level and enforce the associativity as follows:
-
-Infix RIGHTA 1 "o" my_comp V8only (at level 20, right associativity).
-
-The translator now knows that it has to translate "o" at level 20
-which has the correct "right associativity".
-
-Rem: We assumed here that the user wants a strong precedence for
-composition, in such a way, say, that "f o g + h" is parsed as
-"(f o g) + h". To get "o" binding less than the arithmetical operators,
-an appropriated level would have been close of 70, and below, e.g. 65.
-
-b) Conflicts with other notations
-
-Since the new syntax comes with new keywords and new predefined
-symbols, new conflicts can occur. Again, you can use the option V8only
-to inform the translator of the new syntax to use.
-
-b1) A notation hides another notation
-
-Rem: use Print Grammar constr in V8 to diagnose the overlap and see the
-section on factorization in the chapter on notations of the Reference
-Manual for hints on how to factorize.
-
-Example:
-
-Notation "{ x }" := (my_embedding x) (at level 1).
-
-overlaps in V8 with notation "{ x : A & P }" at level 0 and with x at
-level 99. The conflicts can be solved by left-factorizing the notation
-as follows:
-
-Notation "{ x }" := (my_embedding x) (at level 1)
- V8only (at level 0, x at level 99).
-
-b2) A notation conflicts with the V8 grammar.
-
-Again, use the V8only modifier to tell the translator to automatically
-take in charge the new syntax.
-
-Example:
-
-Infix 3 "@" app.
-
-Since "@" is used in the new syntax for deactivating the implicit
-arguments, another symbol has to be used, e.g. "@@". This is done via
-the V8only option as follows:
-
-Infix 3 "@" app V8only "@@" (at level 40, left associativity).
-
-or, alternatively by
-
-Notation "x @ y" := (app x y) (at level 3, left associativity)
- V8only "x @@ y" (at level 40, left associativity).
-
-b3) My notation is already defined at another level (or with another
-associativity)
-
-In V8, the level and associativity of a given notation can no longer
-be changed. Then, either you adopt the standard reserved levels and
-associativity for this notation (as given on the list above) or you
-change your notation.
-
-- To change the notation, follow the directions in section b2.
-
-- To adopt the standard level, just use V8only without any argument.
-
-Example.
-
-Infix 6 "*" my_mult.
-
-is not accepted as such in V8. Write
-
-Infix 6 "*" my_mult V8only.
-
-to tell the translator to use "*" at the reserved level (i.e. 40 with
-left associativity). Even better, use interpretation scopes (look at
-the Reference Manual).
-
-c) How to use V8only with Distfix ?
-
-You can't, use Notation instead of Distfix.
-
-d) Can I overload a notation in V8, e.g. use "*" and "+" for my own
-algebraic operations ?
-
-Yes, using interpretation scopes (see the corresponding chapter in the
-Reference Manual).
-
-3) Using the translator to have simplest notations
-
-Thanks to the new syntax, * has now the expected left associativity,
-and the symbols <, >, <= and >= are now available.
-
-Thanks to the interpretation scopes, you can overload the
-interpretation of these operators with the default interpretation
-provided in Coq.
-
-This may be a motivation to use the translator to automatically change
-the notations while switching to the new syntax.
-
-See sections b) and d) above for examples.
-
-4) Setting the translator to automatically use new notations that
-wasn't used in old syntax
-
-Thanks to the "Notation" mechanism, defining symbolic notations is
-simpler than in the previous versions of Coq.
-
-Thanks to the new syntax and interpretation scopes, new symbols and
-overloading is available.
-
-This may be a motivation for using the translator to automatically change
-the notations while switching to the new syntax.
-
-Use for that the commands V8Notation and V8Infix.
-
-Examples:
-
-V8Infix "==>" my_relation (at level 65, right associativity).
-
-tells the translator to write an infix "==>" instead of my_relation in
-the translated files.
-
-V8Infix ">=" my_ge.
-
-tells the translator to write an infix ">=" instead of my_ge in the
-translated files and that the level and associativity are the standard
-one (as defined in the chart above).
-
-V8Infix ">=" my_ge : my_scope.
-
-tells the translator to write an infix ">=" instead of my_ge in the
-translated files, that the level and associativity are the standard
-one (as defined in the chart above), but only if scope my_scope is
-open or if a delimiting key is available for "my_scope" (see the
-Reference Manual).
-
-5) Defining a construction and its notation simultaneously
-
-This is permitted by the new syntax. Look at the Reference Manual for
-explanation. The translator is not fully able to take this in charge...
-
-III) Various pitfalls
- ----------------
-
-1) New keywords
-
- The following identifiers are new keywords
-
- "forall"; "fun"; "match"; "fix"; "cofix"; "for"; "if"; "then";
- "else"; "return"; "mod"; "at"; "let"; "_"; ".("
-
- The translator automatically add a "_" to names clashing with a
-keyword, except for files. Hence users may need to rename the files
-whose name clashes with a keyword.
-
- Remark: "in"; "with"; "end"; "as"; "Prop"; "Set"; "Type"
- were already keywords
-
-2) Old "Case" and "Match"
-
- "Case" and "Match" are normally automatically translated into
- "match" or "match" and "fix", but sometimes it fails to do so. It
- typically fails when the Case or Match is argument of a tactic whose
- typing context is unknown because of a preceding Intro/Intros, as e.g. in
-
- Intros; Exists [m:nat](<quasiterm>Case m of t [p:nat](f m) end)
-
- The solution is then to replace the invocation of the sequence of
- tactics into several invocation of the elementary tactics as follows
-
- Intros. Exists [m:nat](<quasiterm>Case m of t [p:nat](f m) end)
- ^^^
-
-3) Change of definition or theorem names
-
- Type "entier" from fast_integer.v is renamed into "N" by the
-translator. As a consequence, user-defined objects of same name "N"
-are systematically qualified even tough it may not be necessary. The
-same apply for names "GREATER", "EQUAL", "LESS", etc... [COMPLETE LIST
-TO GIVE].
-
-4) Change of tactics names
-
- Since tactics names are now lowercase, this can clash with
-user-defined tactic definitions. To pally this, clashing names are
-renamed by adding an extra "_" to their name.
-
-======================================================================
-Main examples for new syntax
-----------------------------
-
-1) Constructions
-
- Applicative terms don't any longer require to be surrounded by parentheses as
-e.g in
-
- "x = f y -> S x = S (f y)"
-
-
- Product is written
-
- "forall x y : T, U"
- "forall x y, U"
- "forall (x y : T) z (v w : V), U"
- etc.
-
- Abstraction is written
-
- "fun x y : T, U"
- "fun x y, U"
- "fun (x y : T) z (v w : V), U"
- etc.
-
- Pattern-matching is written
-
- "match x with c1 x1 x2 => t | c2 y as z => u end"
- "match v1, v2 with c1 x1 x2, _ => t | c2 y, d z => u end"
- "match v1 as y in le _ n, v2 as z in I p q return P n y p q z with
- c1 x1 x2, _ => t | c2 y, d z => u end"
-
- The last example is the new form of what was written
-
- "<[n;y:(le ? n);p;q;z:(I p q)](P n y p q z)>Cases v1 v2 of
- (c1 x1 x2) _ => t | (c2 y) (d z) => u end"
-
- Pattern-matching of type with one constructors and no dependencies
-of the arguments in the resulting type can be written
-
- "let (x,y,z) as u return P u := t in v"
-
- Local fixpoints are written
-
- "fix f (n m:nat) z (x : X) {struct m} : nat := ...
- with ..."
-
- and "struct" tells which argument is structurally decreasing.
-
- Explicitation of implicit arguments is written
-
- "f @1:=u v @3:=w t"
- "@f u v w t"
-
-2) Tactics
-
- The main change is that tactics names are now lowercase. Besides
-this, the following renaming are applied:
-
- "NewDestruct" -> "destruct"
- "NewInduction" -> "induction"
- "Induction" -> "simple induction"
- "Destruct" -> "simple destruct"
-
- For tactics with occurrences, the occurrences now comes after and
- repeated use is separated by comma as in
-
- "Pattern 1 3 c d 4 e" -> "pattern c at 3 1, d, e at 4"
- "Unfold 1 3 f 4 g" -> "unfold f at 1 3, g at 4"
- "Simpl 1 3 e" -> "simpl e at 1 3"
-
-3) Tactic language
-
- Definitions are now introduced with keyword "Ltac" (instead of
-"Tactic"/"Meta" "Definition") and are implicitly recursive
-("Recursive" is no longer used).
-
- The new rule for distinguishing terms from ltac expressions is:
-
- Write "ltac:" in front of any tactic in argument position and
- "constr:" in front of any construction in head position
-
-4) Vernacular language
-
-a) Assumptions
-
- The syntax for commands is mainly unchanged. Declaration of
-assumptions is now done as follows
-
- Variable m : t.
- Variables m n p : t.
- Variables (m n : t) (u v : s) (w : r).
-
-b) Definitions
-
- Definitions are done as follows
-
- Definition f m n : t := ... .
- Definition f m n := ... .
- Definition f m n := ... : t.
- Definition f (m n : u) : t := ... .
- Definition f (m n : u) := ... : t.
- Definition f (m n : u) := ... .
- Definition f a b (p q : v) r s (m n : t) : t := ... .
- Definition f a b (p q : v) r s (m n : t) := ... .
- Definition f a b (p q : v) r s (m n : t) := ... : t.
-
-c) Fixpoints
-
- Fixpoints are done this way
-
- Fixpoint f x (y : t) z a (b c : u) {struct z} : v := ... with ... .
- Fixpoint f x : v := ... .
- Fixpoint f (x : t) : v := ... .
-
- It is possible to give a concrete notation to a fixpoint as follows
-
- Fixpoint plus (n m:nat) {struct n} : nat as "n + m" :=
- match n with
- | O => m
- | S p => S (p + m)
- end.
-
-d) Inductive types
-
- The syntax for inductive types is as follows
-
- Inductive t (a b : u) (d : e) : v :=
- c1 : w1 | c2 : w2 | ... .
-
- Inductive t (a b : u) (d : e) : v :=
- c1 : w1 | c2 : w2 | ... .
-
- Inductive t (a b : u) (d : e) : v :=
- c1 (x y : t) : w1 | c2 (z : r) : w2 | ... .
-
- As seen in the last example, arguments of the constructors can be
-given before the colon. If the type itself is omitted (allowed only in
-case the inductive type has no real arguments), this yields an
-ML-style notation as follows
-
- Inductive nat : Set := O | S (n:nat).
- Inductive bool : Set := true | false.
-
- It is even possible to define a syntax at the same time, as follows:
-
- Inductive or (A B:Prop) : Prop as "A \/ B":=
- | or_introl (a:A) : A \/ B
- | or_intror (b:B) : A \/ B.
-
- Inductive and (A B:Prop) : Prop as "A /\ B" := conj (a:A) (b:B).
-
diff --git a/dev/doc/versions-history.tex b/dev/doc/versions-history.tex
index 3867d4af90..8f9c3171da 100644
--- a/dev/doc/versions-history.tex
+++ b/dev/doc/versions-history.tex
@@ -395,7 +395,17 @@ Coq V8.7 beta 1 & released 6 September 2017 & \feature{bundled with Ssreflect pl
Coq V8.7 beta 2 & released 6 October 2017 & \\
-Coq V8.7 & released 18 October 2016 & \\
+Coq V8.7.0 & released 18 October 2017 & \\
+
+Coq V8.7.1 & released 15 December 2017 & \\
+
+Coq V8.7.2 & released 17 February 2018 & \\
+
+Coq V8.8 beta1 & released 19 March 2018 & \\
+
+Coq V8.8.0 & released 17 April 2018 & \feature{reference manual moved to Sphinx} \\
+&& \feature{effort towards better documented, better structured ML API}\\
+&& \feature{miscellaneous changes/improvements of existing features}\\
\end{tabular}
diff --git a/dev/doc/xml-protocol.md b/dev/doc/xml-protocol.md
index b35571e9ca..48671c03b6 100644
--- a/dev/doc/xml-protocol.md
+++ b/dev/doc/xml-protocol.md
@@ -10,9 +10,9 @@ versions of Proof General.
A somewhat out-of-date description of the async state machine is
[documented here](https://github.com/ejgallego/jscoq/blob/master/etc/notes/coq-notes.md).
-OCaml types for the protocol can be found in the [`ide/interface.mli` file](/ide/interface.mli).
+OCaml types for the protocol can be found in the [`ide/protocol/interface.ml` file](/ide/protocol/interface.ml).
-Changes to the XML protocol are documented as part of [`dev/doc/changes.txt`](/dev/doc/changes.txt).
+Changes to the XML protocol are documented as part of [`dev/doc/changes.md`](/dev/doc/changes.md).
* [Commands](#commands)
- [About](#command-about)
diff --git a/dev/ocamldebug-coq.run b/dev/ocamldebug-coq.run
index 2bec09de2b..bccd3fefb4 100644
--- a/dev/ocamldebug-coq.run
+++ b/dev/ocamldebug-coq.run
@@ -33,7 +33,7 @@ if [ -z "$GUESS_CHECKER" ]; then
-I $COQTOP/toplevel -I $COQTOP/dev -I $COQTOP/config -I $COQTOP/ltac \
-I $COQTOP/plugins/cc -I $COQTOP/plugins/dp \
-I $COQTOP/plugins/extraction -I $COQTOP/plugins/field \
- -I $COQTOP/plugins/firstorder -I $COQTOP/plugins/fourier \
+ -I $COQTOP/plugins/firstorder \
-I $COQTOP/plugins/funind -I $COQTOP/plugins/groebner \
-I $COQTOP/plugins/interface -I $COQTOP/plugins/micromega \
-I $COQTOP/plugins/omega -I $COQTOP/plugins/quote \
diff --git a/dev/tools/backport-pr.sh b/dev/tools/backport-pr.sh
index 5205350a61..9864fd4d69 100755
--- a/dev/tools/backport-pr.sh
+++ b/dev/tools/backport-pr.sh
@@ -1,11 +1,34 @@
#!/usr/bin/env bash
-# Usage: dev/tools/backport-pr.sh <PR number> [--stop-before-merging]
-
set -e
-PRNUM=$1
-OPTION=$2
+if [[ $# == 0 ]]; then
+ echo "Usage: $0 [--no-conflict] [--no-signature-check] [--stop-before-merging] prnum"
+ exit 1
+fi
+
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ --no-conflict)
+ NO_CONFLICTS="true"
+ shift
+ ;;
+ --no-signature-check)
+ NO_SIGNATURE_CHECK="true"
+ shift
+ ;;
+ --stop-before-merging)
+ STOP_BEFORE_MERGING="true"
+ shift
+ ;;
+ *)
+ if [[ "$PRNUM" != "" ]]; then
+ echo "PRNUM was already set to $PRNUM and is now being overridden with $1."
+ fi
+ PRNUM="$1"
+ shift
+ esac
+done
if ! git log master --grep "Merge PR #${PRNUM}" | grep "." > /dev/null; then
echo "PR #${PRNUM} does not exist."
@@ -14,7 +37,7 @@ fi
SIGNATURE_STATUS=$(git log master --grep "Merge PR #${PRNUM}" --format="%G?")
git log master --grep "Merge PR #${PRNUM}" --format="%GG"
-if [[ "${SIGNATURE_STATUS}" != "G" ]]; then
+if [[ "$NO_SIGNATURE_CHECK" != "true" && "$SIGNATURE_STATUS" != "G" ]]; then
echo
read -p "Merge commit does not have a good (valid) signature. Bypass? [y/N] " -n 1 -r
echo
@@ -30,6 +53,14 @@ MESSAGE=$(git log master --grep "Merge PR #${PRNUM}" --format="%s" | sed 's/Merg
if git checkout -b "${BRANCH}"; then
if ! git cherry-pick -x "${RANGE}"; then
+ if [[ "$NO_CONFLICTS" == "true" ]]; then
+ git status
+ echo "Conflicts! Aborting..."
+ git cherry-pick --abort
+ git checkout -
+ git branch -d "$BRANCH"
+ exit 1
+ fi
echo "Please fix the conflicts, then exit."
bash
while ! git cherry-pick --continue; do
@@ -59,7 +90,7 @@ if ! git diff --exit-code HEAD "${BRANCH}" -- "*.mli"; then
fi
fi
-if [[ "${OPTION}" == "--stop-before-merging" ]]; then
+if [[ "$STOP_BEFORE_MERGING" == "true" ]]; then
exit 0
fi
diff --git a/dev/tools/check-overlays.sh b/dev/tools/check-overlays.sh
index f7e05b51cd..33a9ff058e 100755
--- a/dev/tools/check-overlays.sh
+++ b/dev/tools/check-overlays.sh
@@ -1,8 +1,8 @@
#!/usr/bin/env bash
-for f in dev/ci/user-overlays/*
+for f in $(git ls-files "dev/ci/user-overlays/")
do
- if ! ([[ $f = dev/ci/user-overlays/README.md ]] || [[ $f == *.sh ]])
+ if ! ([[ "$f" = dev/ci/user-overlays/README.md ]] || [[ "$f" == *.sh ]])
then
>&2 echo "Bad overlay '$f'."
>&2 echo "User overlays need to have extension .sh to be picked up!"
diff --git a/dev/tools/coqdev.el b/dev/tools/coqdev.el
index 70a9756e51..ec72f96509 100644
--- a/dev/tools/coqdev.el
+++ b/dev/tools/coqdev.el
@@ -33,7 +33,7 @@
(defun coqdev-default-directory ()
"Return the Coq repository containing `default-directory'."
- (let ((dir (locate-dominating-file default-directory "META.coq")))
+ (let ((dir (locate-dominating-file default-directory "META.coq.in")))
(when dir (expand-file-name dir))))
(defun coqdev-setup-compile-command ()
diff --git a/dev/top_printers.ml b/dev/top_printers.ml
index 844ad9188a..ab679a71ce 100644
--- a/dev/top_printers.ml
+++ b/dev/top_printers.ml
@@ -232,7 +232,7 @@ let ppenv e = pp
let ppenvwithcst e = pp
(str "[" ++ pr_named_context_of e Evd.empty ++ str "]" ++ spc() ++
str "[" ++ pr_rel_context e Evd.empty (rel_context e) ++ str "]" ++ spc() ++
- str "{" ++ Cmap_env.fold (fun a _ s -> Constant.print a ++ spc () ++ s) (Obj.magic e).env_globals.env_constants (mt ()) ++ str "}")
+ str "{" ++ Environ.fold_constants (fun a _ s -> Constant.print a ++ spc () ++ s) e (mt ()) ++ str "}")
let pptac = (fun x -> pp(Ltac_plugin.Pptactic.pr_glob_tactic (Global.env()) x))
@@ -301,8 +301,8 @@ let constr_display csr =
incr cnt; pp (str "with " ++ int !cnt ++ str" " ++ Level.pr u ++ fnl ())
and sort_display = function
- | Prop(Pos) -> "Prop(Pos)"
- | Prop(Null) -> "Prop(Null)"
+ | Set -> "Set"
+ | Prop -> "Prop"
| Type u -> univ_display u;
"Type("^(string_of_int !cnt)^")"
@@ -423,8 +423,8 @@ let print_pure_constr csr =
Array.iter (fun u -> print_space (); pp (Level.pr u)) (Instance.to_array u)
and sort_display = function
- | Prop(Pos) -> print_string "Set"
- | Prop(Null) -> print_string "Prop"
+ | Set -> print_string "Set"
+ | Prop -> print_string "Prop"
| Type u -> open_hbox();
print_string "Type("; pp (pr_uni u); print_string ")"; close_box()
diff --git a/dev/vm_printers.ml b/dev/vm_printers.ml
index 7589e53489..98190b05b5 100644
--- a/dev/vm_printers.ml
+++ b/dev/vm_printers.ml
@@ -17,7 +17,7 @@ let ppripos (ri,pos) =
| Reloc_getglobal kn ->
print_string ("getglob "^(Constant.to_string kn)^"\n")
| Reloc_proj_name p ->
- print_string ("proj "^(Constant.to_string p)^"\n")
+ print_string ("proj "^(Projection.Repr.to_string p)^"\n")
);
print_flush ()
@@ -26,8 +26,8 @@ let print_vfix_app () = print_string "vfix_app"
let print_vswith () = print_string "switch"
let ppsort = function
- | Prop(Pos) -> print_string "Set"
- | Prop(Null) -> print_string "Prop"
+ | Set -> print_string "Set"
+ | Prop -> print_string "Prop"
| Type u -> print_string "Type"
diff --git a/doc/LICENSE b/doc/LICENSE
index c9f574afb8..3789d91040 100644
--- a/doc/LICENSE
+++ b/doc/LICENSE
@@ -2,7 +2,7 @@ The Coq Reference Manual is a collective work from the Coq Development
Team whose members are listed in the file CREDITS of the Coq source
package. All related documents (the LaTeX and BibTeX sources, the
embedded png files, and the PostScript, PDF and html outputs) are
-copyright (c) INRIA 1999-2006, with the exception of the Ubuntu font
+copyright (c) INRIA 1999-2018, with the exception of the Ubuntu font
file UbuntuMono-B.ttf, which is
Copyright 2010,2011 Canonical Ltd and licensed under the Ubuntu font
license, version 1.0
@@ -18,7 +18,7 @@ The Coq Standard Library is a collective work from the Coq Development
Team whose members are listed in the file CREDITS of the Coq source
package. All related documents (the Coq vernacular source files and
the PostScript, PDF and html outputs) are copyright (c) INRIA
-1999-2006. The material connected to the Standard Library is
+1999-2018. The material connected to the Standard Library is
distributed under the terms of the Lesser General Public License
version 2.1 or later.
diff --git a/doc/README.md b/doc/README.md
new file mode 100644
index 0000000000..3e70bc443d
--- /dev/null
+++ b/doc/README.md
@@ -0,0 +1,114 @@
+The Coq documentation
+=====================
+
+The Coq documentation includes
+
+- A Reference Manual
+- A document presenting the Coq standard library
+
+The documentation of the latest released version is available on the Coq
+web site at [coq.inria.fr/documentation](http://coq.inria.fr/documentation).
+
+Additionally, you can view the documentation for the current master version at
+<https://gitlab.com/coq/coq/-/jobs/artifacts/master/file/_install_ci/share/doc/coq/sphinx/html/index.html?job=documentation>.
+
+The reference manual is written is reStructuredText and compiled
+using Sphinx. See [`sphinx/README.rst`](sphinx/README.rst)
+to learn more about the format that is used.
+
+The documentation for the standard library is generated from
+the `.v` source files using coqdoc.
+
+Dependencies
+------------
+
+### HTML documentation
+
+To produce the complete documentation in HTML, you will need Coq dependencies
+listed in [`INSTALL`](../INSTALL). Additionally, the Sphinx-based
+reference manual requires Python 3, and the following Python packages:
+
+ sphinx sphinx_rtd_theme beautifulsoup4 antlr4-python3-runtime pexpect sphinxcontrib-bibtex
+
+You can install them using `pip3 install` or using your distribution's package
+manager. E.g. under recent Debian-based operating systems (Debian 10 "Buster",
+Ubuntu 18.04, ...) you can use:
+
+ apt install python3-sphinx python3-pexpect python3-sphinx-rtd-theme \
+ python3-bs4 python3-sphinxcontrib.bibtex python3-pip
+
+Then, install the missing Python3 Antlr4 package:
+
+ pip3 install antlr4-python3-runtime
+
+Nix users should get the correct development environment to build the
+HTML documentation from Coq's [`default.nix`](../default.nix) (note this
+doesn't include the LaTeX packages needed to build the full documentation).
+
+### Other formats
+
+To produce the documentation in PDF and PostScript formats, the following
+additional tools are required:
+
+ - latex (latex2e)
+ - pdflatex
+ - dvips
+ - makeindex
+
+Install them using your package manager. E.g. on Debian / Ubuntu:
+
+ apt install texlive-latex-extra texlive-fonts-recommended
+
+Compilation
+-----------
+
+To produce all documentation about Coq in all formats, just run:
+
+ ./configure # (if you hadn't already)
+ make doc
+
+
+Alternatively, you can use some specific targets:
+
+- `make doc-ps`
+ to produce all PostScript documents
+
+- `make doc-pdf`
+ to produce all PDF documents
+
+- `make doc-html`
+ to produce all HTML documents
+
+- `make sphinx`
+ to produce the HTML version of the reference manual
+
+- `make stdlib`
+ to produce all formats of the Coq standard library
+
+
+Also note the `-with-doc yes` option of `./configure` to enable the
+build of the documentation as part of the default make target.
+
+If you're editing Sphinx documentation, set SPHINXWARNERROR to 0
+to avoid treating Sphinx warnings as errors. Otherwise, Sphinx quits
+upon detecting the first warning. You can set this on the Sphinx `make`
+command line or as an environment variable:
+
+- `make sphinx SPINXWARNERROR=0`
+
+- ~~~
+ export SPHINXWARNERROR=0
+ ⋮
+ make sphinx
+ ~~~
+
+Installation
+------------
+
+To install all produced documents, do:
+
+ make install-doc
+
+This will install the documentation in `/usr/share/doc/coq` unless you
+specify another value through the `-docdir` option of `./configure` or the
+`DOCDIR` environment variable.
diff --git a/doc/sphinx/README.rst b/doc/sphinx/README.rst
index 32de15ee31..4673107e3d 100644
--- a/doc/sphinx/README.rst
+++ b/doc/sphinx/README.rst
@@ -32,7 +32,7 @@ Names (link targets) are auto-generated for most simple objects, though they can
- Vernacs (commands) have their name set to the first word of their signature. For example, the auto-generated name of ``Axiom @ident : @term`` is ``Axiom``, and a link to it would take the form ``:cmd:`Axiom```.
- Vernac variants, tactic notations, and tactic variants do not have a default name.
-Most objects should have a body (i.e. a block of indented text following the signature, called “contents” in Sphinx terms). Undocumented objects should have the `:undocumented:` flag instead, as shown above. When multiple objects have a single description, they can be grouped into a single object, like this (semicolons can be used to separate the names of the objects)::
+Most objects should have a body (i.e. a block of indented text following the signature, called “contents” in Sphinx terms). Undocumented objects should have the `:undocumented:` flag instead, as shown above. When multiple objects have a single description, they can be grouped into a single object, like this (semicolons can be used to separate the names of the objects; names starting with ``_`` will be omitted from the indexes)::
.. cmdv:: Lemma @ident {? @binders} : @type
Remark @ident {? @binders} : @type
@@ -239,6 +239,9 @@ In addition to the objects above, the ``coqrst`` Sphinx plugin defines the follo
http://docutils.sourceforge.net/docs/ref/rst/directives.html#generic-admonition
for more details.
+ Optionally, any text immediately following the ``.. example::`` header is
+ used as the example's title.
+
Example::
.. example:: Adding a hint to a database
@@ -300,7 +303,7 @@ In addition to the objects and directives above, the ``coqrst`` Sphinx plugin de
it names the introduced hypothesis :token:`ident`.
Note that this example also uses ``:token:``. That's because ``ident`` is
- defined in the the Coq manual as a grammar production, and ``:token:``
+ defined in the Coq manual as a grammar production, and ``:token:``
creates a link to that. When referring to a placeholder that happens to be
a grammar production, ``:token:`…``` is typically preferable to ``:n:`@…```.
diff --git a/doc/sphinx/README.template.rst b/doc/sphinx/README.template.rst
index f1d2541eb6..c333d6e9d5 100644
--- a/doc/sphinx/README.template.rst
+++ b/doc/sphinx/README.template.rst
@@ -32,7 +32,7 @@ Names (link targets) are auto-generated for most simple objects, though they can
- Vernacs (commands) have their name set to the first word of their signature. For example, the auto-generated name of ``Axiom @ident : @term`` is ``Axiom``, and a link to it would take the form ``:cmd:`Axiom```.
- Vernac variants, tactic notations, and tactic variants do not have a default name.
-Most objects should have a body (i.e. a block of indented text following the signature, called “contents” in Sphinx terms). Undocumented objects should have the `:undocumented:` flag instead, as shown above. When multiple objects have a single description, they can be grouped into a single object, like this (semicolons can be used to separate the names of the objects)::
+Most objects should have a body (i.e. a block of indented text following the signature, called “contents” in Sphinx terms). Undocumented objects should have the `:undocumented:` flag instead, as shown above. When multiple objects have a single description, they can be grouped into a single object, like this (semicolons can be used to separate the names of the objects; names starting with ``_`` will be omitted from the indexes)::
.. cmdv:: Lemma @ident {? @binders} : @type
Remark @ident {? @binders} : @type
diff --git a/doc/sphinx/addendum/canonical-structures.rst b/doc/sphinx/addendum/canonical-structures.rst
index 6843e9eaa1..2cc1f95c08 100644
--- a/doc/sphinx/addendum/canonical-structures.rst
+++ b/doc/sphinx/addendum/canonical-structures.rst
@@ -6,14 +6,14 @@ Canonical Structures
:Authors: Assia Mahboubi and Enrico Tassi
-This chapter explains the basics of Canonical Structure and how they can be used
+This chapter explains the basics of canonical structures and how they can be used
to overload notations and build a hierarchy of algebraic structures. The
examples are taken from :cite:`CSwcu`. We invite the interested reader to refer
to this paper for all the details that are omitted here for brevity. The
interested reader shall also find in :cite:`CSlessadhoc` a detailed description
-of another, complementary, use of Canonical Structures: advanced proof search.
+of another, complementary, use of canonical structures: advanced proof search.
This latter papers also presents many techniques one can employ to tune the
-inference of Canonical Structures.
+inference of canonical structures.
Notation overloading
@@ -38,21 +38,21 @@ of the terms that are compared.
End theory.
End EQ.
-We use Coq modules as name spaces. This allows us to follow the same
+We use Coq modules as namespaces. This allows us to follow the same
pattern and naming convention for the rest of the chapter. The base
-name space contains the definitions of the algebraic structure. To
+namespace contains the definitions of the algebraic structure. To
keep the example small, the algebraic structure ``EQ.type`` we are
defining is very simplistic, and characterizes terms on which a binary
relation is defined, without requiring such relation to validate any
property. The inner theory module contains the overloaded notation ``==``
-and will eventually contain lemmas holding on all the instances of the
+and will eventually contain lemmas holding all the instances of the
algebraic structure (in this case there are no lemmas).
Note that in practice the user may want to declare ``EQ.obj`` as a
coercion, but we will not do that here.
The following line tests that, when we assume a type ``e`` that is in
-theEQ class, then we can relates two of its objects with ``==``.
+theEQ class, we can relate two of its objects with ``==``.
.. coqtop:: all
@@ -75,7 +75,7 @@ We amend that by equipping ``nat`` with a comparison relation.
Check 3 == 3.
Eval compute in 3 == 4.
-This last test shows that |Coq| is now not only able to typecheck ``3 == 3``,
+This last test shows that |Coq| is now not only able to type check ``3 == 3``,
but also that the infix relation was bound to the ``nat_eq`` relation.
This relation is selected whenever ``==`` is used on terms of type nat.
This can be read in the line declaring the canonical structure
@@ -312,7 +312,7 @@ The following script registers an ``LEQ`` class for ``nat`` and for the type
constructor ``*``. It also tests that they work as expected.
Unfortunately, these declarations are very verbose. In the following
-subsection we show how to make these declaration more compact.
+subsection we show how to make them more compact.
.. coqtop:: all
@@ -385,7 +385,7 @@ with message "T is not an EQ.type"”.
The other utilities are used to ask |Coq| to solve a specific unification
problem, that will in turn require the inference of some canonical structures.
-They are explained in mode details in :cite:`CSwcu`.
+They are explained in more details in :cite:`CSwcu`.
We now have all we need to create a compact “packager” to declare
instances of the ``LEQ`` class.
diff --git a/doc/sphinx/addendum/extended-pattern-matching.rst b/doc/sphinx/addendum/extended-pattern-matching.rst
index c4f0147728..f7fd4b9146 100644
--- a/doc/sphinx/addendum/extended-pattern-matching.rst
+++ b/doc/sphinx/addendum/extended-pattern-matching.rst
@@ -11,7 +11,7 @@ Extended pattern-matching
This section describes the full form of pattern-matching in |Coq| terms.
-.. |rhs| replace:: right hand side
+.. |rhs| replace:: right hand sides
Patterns
--------
@@ -39,12 +39,12 @@ value. A pattern of the form :n:`pattern | pattern` is called disjunctive. A
list of patterns separated with commas is also considered as a pattern
and is called *multiple pattern*. However multiple patterns can only
occur at the root of pattern-matching equations. Disjunctions of
-*multiple pattern* are allowed though.
+*multiple patterns* are allowed though.
Since extended ``match`` expressions are compiled into the primitive ones,
-the expressiveness of the theory remains the same. Once the stage of
-parsing has finished only simple patterns remain. Re-nesting of
-pattern is performed at printing time. An easy way to see the result
+the expressiveness of the theory remains the same. Once parsing has finished
+only simple patterns remain. The original nesting of the ``match`` expressions
+is recovered at printing time. An easy way to see the result
of the expansion is to toggle off the nesting performed at printing
(use here :opt:`Printing Matching`), then by printing the term with :cmd:`Print`
if the term is a constant, or using the command :cmd:`Check`.
@@ -150,12 +150,12 @@ second one and :g:`false` otherwise. We can write it as follows:
| S n, S m => lef n m
end.
-Note that the first and the second multiple pattern superpose because
+Note that the first and the second multiple pattern overlap because
the couple of values ``O O`` matches both. Thus, what is the result of the
function on those values? To eliminate ambiguity we use the *textual
-priority rule*: we consider patterns ordered from top to bottom, then
-a value is matched by the pattern at the ith row if and only if it is
-not matched by some pattern of a previous row. Thus in the example,O O
+priority rule:* we consider patterns to be ordered from top to bottom. A
+value is matched by the pattern at the ith row if and only if it is
+not matched by some pattern from a previous row. Thus in the example, ``O O``
is matched by the first pattern, and so :g:`(lef O O)` yields true.
Another way to write this function is:
@@ -201,7 +201,7 @@ instance, :g:`max` can be rewritten as follows:
| 0, p | p, 0 => p
end.
-Similarly, factorization of (non necessary multiple) patterns that
+Similarly, factorization of (not necessarily multiple) patterns that
share the same variables is possible by using the notation :n:`{+| @pattern}`.
Here is an example:
@@ -312,7 +312,7 @@ Matching objects of dependent types
The previous examples illustrate pattern matching on objects of non-
dependent types, but we can also use the expansion strategy to
-destructure objects of dependent type. Consider the type :g:`listn` of
+destructure objects of dependent types. Consider the type :g:`listn` of
lists of a certain length:
.. coqtop:: in reset
@@ -353,12 +353,12 @@ Dependent pattern matching
~~~~~~~~~~~~~~~~~~~~~~~~~~
The examples given so far do not need an explicit elimination
-predicate because all the |rhs| have the same type and the strategy
+predicate because all the |rhs| have the same type and Coq
succeeds to synthesize it. Unfortunately when dealing with dependent
-patterns it often happens that we need to write cases where the type
+patterns it often happens that we need to write cases where the types
of the |rhs| are different instances of the elimination predicate. The
-function concat for listn is an example where the branches have
-different type and we need to provide the elimination predicate:
+function :g:`concat` for :g:`listn` is an example where the branches have
+different types and we need to provide the elimination predicate:
.. coqtop:: in
@@ -374,7 +374,7 @@ In general if :g:`m` has type :g:`(I q1 … qr t1 … ts)` where :g:`q1, …, qr
are parameters, the elimination predicate should be of the form :g:`fun y1 … ys x : (I q1 … qr y1 … ys ) => Q`.
In the concrete syntax, it should be written :
-``match m as x in (I _ … _ y1 … ys) return Q with … end``
+``match m as x in (I _ … _ y1 … ys) return Q with … end``.
The variables which appear in the ``in`` and ``as`` clause are new and bounded
in the property :g:`Q` in the return clause. The parameters of the
inductive definitions should not be mentioned and are replaced by ``_``.
@@ -385,9 +385,9 @@ Multiple dependent pattern matching
Recall that a list of patterns is also a pattern. So, when we
destructure several terms at the same time and the branches have
different types we need to provide the elimination predicate for this
-multiple pattern. It is done using the same scheme, each term may be
-associated to an as and in clause in order to introduce a dependent
-product.
+multiple pattern. It is done using the same scheme: each term may be
+associated to an ``as`` clause and an ``in`` clause in order to introduce
+a dependent product.
For example, an equivalent definition for :g:`concat` (even though the
matching on the second term is trivial) would have been:
@@ -414,7 +414,7 @@ length, by writing
| consn n' a y, x => consn (n' + m) a (concat n' y m x)
end.
-I have a copy of :g:`b` in type :g:`listn 0` resp :g:`listn (S n')`.
+we have a copy of :g:`b` in type :g:`listn 0` resp. :g:`listn (S n')`.
.. _match-in-patterns:
@@ -425,7 +425,7 @@ If the type of the matched term is more precise than an inductive
applied to variables, arguments of the inductive in the ``in`` branch can
be more complicated patterns than a variable.
-Moreover, constructors whose type do not follow the same pattern will
+Moreover, constructors whose types do not follow the same pattern will
become impossible branches. In an impossible branch, you can answer
anything but False_rect unit has the advantage to be subterm of
anything.
@@ -448,8 +448,8 @@ Using pattern matching to write proofs
In all the previous examples the elimination predicate does not depend
on the object(s) matched. But it may depend and the typical case is
when we write a proof by induction or a function that yields an object
-of dependent type. An example of proof using match in given in Section
-8.2.3.
+of a dependent type. An example of a proof written using ``match`` is given
+in the description of the tactic :tacn:`refine`.
For example, we can write the function :g:`buildlist` that given a natural
number :g:`n` builds a list of length :g:`n` containing zeros as follows:
@@ -572,7 +572,7 @@ When does the expansion strategy fail?
--------------------------------------
The strategy works very like in ML languages when treating patterns of
-non-dependent type. But there are new cases of failure that are due to
+non-dependent types. But there are new cases of failure that are due to
the presence of dependencies.
The error messages of the current implementation may be sometimes
diff --git a/doc/sphinx/addendum/extraction.rst b/doc/sphinx/addendum/extraction.rst
index cb93d48a41..e3d25cf5cf 100644
--- a/doc/sphinx/addendum/extraction.rst
+++ b/doc/sphinx/addendum/extraction.rst
@@ -116,13 +116,13 @@ be optimized in order to be efficient (for instance, when using
induction principles we do not want to compute all the recursive calls
but only the needed ones). So the extraction mechanism provides an
automatic optimization routine that will be called each time the user
-want to generate |OCaml| programs. The optimizations can be split in two
+wants to generate an |OCaml| program. The optimizations can be split in two
groups: the type-preserving ones (essentially constant inlining and
reductions) and the non type-preserving ones (some function
abstractions of dummy types are removed when it is deemed safe in order
to have more elegant types). Therefore some constants may not appear in the
resulting monolithic |OCaml| program. In the case of modular extraction,
-even if some inlining is done, the inlined constant are nevertheless
+even if some inlining is done, the inlined constants are nevertheless
printed, to ensure session-independent programs.
Concerning Haskell, type-preserving optimizations are less useful
@@ -185,7 +185,7 @@ The type-preserving optimizations are controlled by the following |Coq| options:
**Inlining and printing of a constant declaration:**
-A user can explicitly ask for a constant to be extracted by two means:
+The user can explicitly ask for a constant to be extracted by two means:
* by mentioning it on the extraction command line
@@ -224,19 +224,18 @@ principles of extraction (logical parts and types).
When an actual extraction takes place, an error is normally raised if the
:cmd:`Extraction Implicit` declarations cannot be honored, that is
-if any of the implicited variables still occurs in the final code.
+if any of the implicit arguments still occurs in the final code.
This behavior can be relaxed via the following option:
.. opt:: Extraction SafeImplicits
Default is on. When this option is off, a warning is emitted
- instead of an error if some implicited variables still occur in the
+ instead of an error if some implicit arguments still occur in the
final code of an extraction. This way, the extracted code may be
obtained nonetheless and reviewed manually to locate the source of the issue
- (in the code, some comments mark the location of these remaining
- implicited variables).
+ (in the code, some comments mark the location of these remaining implicit arguments).
Note that this extracted code might not compile or run properly,
- depending of the use of these remaining implicited variables.
+ depending of the use of these remaining implicit arguments.
Realizing axioms
~~~~~~~~~~~~~~~~
@@ -296,7 +295,7 @@ The number of type variables is checked by the system. For example:
Realizing an axiom via :cmd:`Extract Constant` is only useful in the
case of an informative axiom (of sort ``Type`` or ``Set``). A logical axiom
-have no computational content and hence will not appears in extracted
+has no computational content and hence will not appear in extracted
terms. But a warning is nonetheless issued if extraction encounters a
logical axiom. This warning reminds user that inconsistent logical
axioms may lead to incorrect or non-terminating extracted terms.
@@ -312,7 +311,7 @@ Realizing inductive types
The system also provides a mechanism to specify ML terms for inductive
types and constructors. For instance, the user may want to use the ML
-native boolean type instead of |Coq| one. The syntax is the following:
+native boolean type instead of the |Coq| one. The syntax is the following:
.. cmd:: Extract Inductive @qualid => @string [ {+ @string } ]
@@ -332,10 +331,10 @@ native boolean type instead of |Coq| one. The syntax is the following:
branches in functional form, and then the inductive element to
destruct. For instance, the match branch ``| S n => foo`` gives the
functional form ``(fun n -> foo)``. Note that a constructor with no
- argument is considered to have one unit argument, in order to block
+ arguments is considered to have one unit argument, in order to block
early evaluation of the branch: ``| O => bar`` leads to the functional
form ``(fun () -> bar)``. For instance, when extracting ``nat``
- into |OCaml| ``int``, the code to provide has type:
+ into |OCaml| ``int``, the code to be provided has type:
``(unit->'a)->(int->'a)->int->'a``.
.. caution:: As for :cmd:`Extract Constant`, this command should be used with care:
@@ -371,7 +370,7 @@ Typical examples are the following:
When extracting to |OCaml|, if an inductive constructor or type has arity 2 and
the corresponding string is enclosed by parentheses, and the string meets
|OCaml|'s lexical criteria for an infix symbol, then the rest of the string is
- used as infix constructor or type.
+ used as an infix constructor or type.
.. coqtop:: in
@@ -389,7 +388,7 @@ Avoiding conflicts with existing filenames
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When using :cmd:`Extraction Library`, the names of the extracted files
-directly depends from the names of the |Coq| files. It may happen that
+directly depend on the names of the |Coq| files. It may happen that
these filenames are in conflict with already existing files,
either in the standard library of the target language or in other
code that is meant to be linked with the extracted code.
@@ -424,7 +423,7 @@ a generic type ``'a`` to any term.
First, if some part of the program is *very* polymorphic, there
may be no ML type for it. In that case the extraction to ML works
alright but the generated code may be refused by the ML
-type-checker. A very well known example is the ``distr-pair``
+type checker. A very well known example is the ``distr-pair``
function:
.. coqtop:: in
@@ -459,7 +458,7 @@ In |OCaml|, we must cast any argument of the constructor dummy
Even with those unsafe castings, you should never get error like
``segmentation fault``. In fact even if your program may seem
-ill-typed to the |OCaml| type-checker, it can't go wrong : it comes
+ill-typed to the |OCaml| type checker, it can't go wrong : it comes
from a Coq well-typed terms, so for example inductive types will always
have the correct number of arguments, etc. Of course, when launching
manually some extracted function, you should apply it to arguments
@@ -470,22 +469,23 @@ found in :cite:`Let02`.
We have to say, though, that in most "realistic" programs, these problems do not
occur. For example all the programs of Coq library are accepted by the |OCaml|
-type-checker without any ``Obj.magic`` (see examples below).
+type checker without any ``Obj.magic`` (see examples below).
Some examples
-------------
-We present here two examples of extractions, taken from the
-|Coq| Standard Library. We choose |OCaml| as target language,
-but all can be done in the other dialects with slight modifications.
+We present here two examples of extraction, taken from the
+|Coq| Standard Library. We choose |OCaml| as the target language,
+but everything, with slight modifications, can also be done in the
+other languages supported by extraction.
We then indicate where to find other examples and tests of extraction.
A detailed example: Euclidean division
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The file ``Euclid`` contains the proof of Euclidean division.
-The natural numbers used there are unary integers of type ``nat``,
-defined by two constructors ``O`` and ``S``.
+The natural numbers used here are unary, represented by the type``nat``,
+which is defined by two constructors ``O`` and ``S``.
This module contains a theorem ``eucl_dev``, whose type is::
forall b:nat, b > 0 -> forall a:nat, diveucl a b
@@ -579,7 +579,7 @@ extraction test:
* ``stalmarck`` : https://github.com/coq-contribs/stalmarck
Note that ``continuations`` and ``multiplier`` are a bit particular. They are
-examples of developments where ``Obj.magic`` are needed. This is
-probably due to an heavy use of impredicativity. After compilation, those
+examples of developments where ``Obj.magic`` is needed. This is
+probably due to a heavy use of impredicativity. After compilation, those
two examples run nonetheless, thanks to the correction of the
extraction :cite:`Let02`.
diff --git a/doc/sphinx/addendum/generalized-rewriting.rst b/doc/sphinx/addendum/generalized-rewriting.rst
index e4d24a1f7e..e0babb6c4e 100644
--- a/doc/sphinx/addendum/generalized-rewriting.rst
+++ b/doc/sphinx/addendum/generalized-rewriting.rst
@@ -22,19 +22,18 @@ The new implementation is a drop-in replacement for the old one
[#tabareau]_, hence most of the documentation still applies.
The work is a complete rewrite of the previous implementation, based
-on the type class infrastructure. It also improves on and generalizes
+on the typeclass infrastructure. It also improves on and generalizes
the previous implementation in several ways:
-
-+ User-extensible algorithm. The algorithm is separated in two parts:
- generations of the rewriting constraints (done in ML) and solving of
- these constraints using type class resolution. As type class
++ User-extensible algorithm. The algorithm is separated into two parts:
+ generation of the rewriting constraints (written in ML) and solving
+ these constraints using typeclass resolution. As typeclass
resolution is extensible using tactics, this allows users to define
general ways to solve morphism constraints.
-+ Sub-relations. An example extension to the base algorithm is the
++ Subrelations. An example extension to the base algorithm is the
ability to define one relation as a subrelation of another so that
morphism declarations on one relation can be used automatically for
- the other. This is done purely using tactics and type class search.
+ the other. This is done purely using tactics and typeclass search.
+ Rewriting under binders. It is possible to rewrite under binders in
the new implementation, if one provides the proper morphisms. Again,
most of the work is handled in the tactics.
@@ -58,41 +57,41 @@ Relations and morphisms
~~~~~~~~~~~~~~~~~~~~~~~
A parametric *relation* ``R`` is any term of type
-``forall (x1 :T1 ) ... (xn :Tn ), relation A``.
+``forall (x1 : T1) ... (xn : Tn), relation A``.
The expression ``A``, which depends on ``x1 ... xn`` , is called the *carrier*
of the relation and ``R`` is said to be a relation over ``A``; the list
``x1,...,xn`` is the (possibly empty) list of parameters of the relation.
-**Example 1 (Parametric relation):**
+.. example:: Parametric relation
-It is possible to implement finite sets of elements of type ``A`` as
-unordered list of elements of type ``A``.
-The function ``set_eq: forall (A: Type), relation (list A)``
-satisfied by two lists with the same elements is a parametric relation
-over ``(list A)`` with one parameter ``A``. The type of ``set_eq``
-is convertible with ``forall (A: Type), list A -> list A -> Prop.``
+ It is possible to implement finite sets of elements of type ``A`` as
+ unordered lists of elements of type ``A``.
+ The function ``set_eq: forall (A : Type), relation (list A)``
+ satisfied by two lists with the same elements is a parametric relation
+ over ``(list A)`` with one parameter ``A``. The type of ``set_eq``
+ is convertible with ``forall (A : Type), list A -> list A -> Prop.``
An *instance* of a parametric relation ``R`` with n parameters is any term
-``(R t1 ... tn )``.
+``(R t1 ... tn)``.
Let ``R`` be a relation over ``A`` with ``n`` parameters. A term is a parametric
proof of reflexivity for ``R`` if it has type
-``forall (x1 :T1 ) ... (xn :Tn), reflexive (R x1 ... xn )``.
+``forall (x1 : T1) ... (xn : Tn), reflexive (R x1 ... xn)``.
Similar definitions are given for parametric proofs of symmetry and transitivity.
-**Example 2 (Parametric relation (cont.)):**
+.. example:: Parametric relation (continued)
-The ``set_eq`` relation of the previous example can be proved to be
-reflexive, symmetric and transitive. A parametric unary function ``f`` of type
-``forall (x1 :T1 ) ... (xn :Tn ), A1 -> A2`` covariantly respects two parametric relation instances
-``R1`` and ``R2`` if, whenever ``x``, ``y`` satisfy ``R1 x y``, their images (``f x``) and (``f y``)
-satisfy ``R2 (f x) (f y)``. An ``f`` that respects its input and output
-relations will be called a unary covariant *morphism*. We can also say
-that ``f`` is a monotone function with respect to ``R1`` and ``R2`` . The
-sequence ``x1 ... xn`` represents the parameters of the morphism.
+ The ``set_eq`` relation of the previous example can be proved to be
+ reflexive, symmetric and transitive. A parametric unary function ``f`` of type
+ ``forall (x1 : T1) ... (xn : Tn), A1 -> A2`` covariantly respects two parametric relation instances
+ ``R1`` and ``R2`` if, whenever ``x``, ``y`` satisfy ``R1 x y``, their images (``f x``) and (``f y``)
+ satisfy ``R2 (f x) (f y)``. An ``f`` that respects its input and output
+ relations will be called a unary covariant *morphism*. We can also say
+ that ``f`` is a monotone function with respect to ``R1`` and ``R2`` . The
+ sequence ``x1 ... xn`` represents the parameters of the morphism.
Let ``R1`` and ``R2`` be two parametric relations. The *signature* of a
-parametric morphism of type ``forall (x1 :T1 ) ... (xn :Tn ), A1 -> A2``
+parametric morphism of type ``forall (x1 : T1) ... (xn : Tn), A1 -> A2``
that covariantly respects two instances :math:`I_{R_1}` and :math:`I_{R_2}` of ``R1`` and ``R2``
is written :math:`I_{R_1} ++> I_{R_2}`. Notice that the special arrow ++>, which
reminds the reader of covariance, is placed between the two relation
@@ -118,29 +117,29 @@ covariant and contravariant.
An instance of a parametric morphism :math:`f` with :math:`n`
parameters is any term :math:`f \, t_1 \ldots t_n`.
-**Example 3 (Morphisms):**
+.. example:: Morphisms
-Continuing the previous example, let ``union: forall (A: Type), list A -> list A -> list A``
-perform the union of two sets by appending one list to the other. ``union` is a binary
-morphism parametric over ``A`` that respects the relation instance
-``(set_eq A)``. The latter condition is proved by showing:
+ Continuing the previous example, let ``union: forall (A : Type), list A -> list A -> list A``
+ perform the union of two sets by appending one list to the other. ``union` is a binary
+ morphism parametric over ``A`` that respects the relation instance
+ ``(set_eq A)``. The latter condition is proved by showing:
-.. coqtop:: in
+ .. coqtop:: in
- forall (A: Type) (S1 S1’ S2 S2’: list A),
- set_eq A S1 S1’ ->
- set_eq A S2 S2’ ->
- set_eq A (union A S1 S2) (union A S1’ S2’).
+ forall (A : Type) (S1 S1’ S2 S2’ : list A),
+ set_eq A S1 S1’ ->
+ set_eq A S2 S2’ ->
+ set_eq A (union A S1 S2) (union A S1’ S2’).
-The signature of the function ``union A`` is ``set_eq A ==> set_eq A ==> set_eq A``
-for all ``A``.
+ The signature of the function ``union A`` is ``set_eq A ==> set_eq A ==> set_eq A``
+ for all ``A``.
-**Example 4 (Contravariant morphism):**
+.. example:: Contravariant morphisms
-The division function ``Rdiv: R -> R -> R`` is a morphism of signature
-``le ++> le --> le`` where ``le`` is the usual order relation over
-real numbers. Notice that division is covariant in its first argument
-and contravariant in its second argument.
+ The division function ``Rdiv : R -> R -> R`` is a morphism of signature
+ ``le ++> le --> le`` where ``le`` is the usual order relation over
+ real numbers. Notice that division is covariant in its first argument
+ and contravariant in its second argument.
Leibniz equality is a relation and every function is a morphism that
respects Leibniz equality. Unfortunately, Leibniz equality is not
@@ -149,180 +148,178 @@ always the intended equality for a given structure.
In the next section we will describe the commands to register terms as
parametric relations and morphisms. Several tactics that deal with
equality in Coq can also work with the registered relations. The exact
-list of tactic will be given :ref:`in this section <tactics-enabled-on-user-provided-relations>`.
-For instance, the tactic reflexivity can be used to close a goal ``R n n`` whenever ``R``
+list of tactics will be given :ref:`in this section <tactics-enabled-on-user-provided-relations>`.
+For instance, the tactic reflexivity can be used to solve a goal ``R n n`` whenever ``R``
is an instance of a registered reflexive relation. However, the
tactics that replace in a context ``C[]`` one term with another one
related by ``R`` must verify that ``C[]`` is a morphism that respects the
-intended relation. Currently the verification consists in checking
+intended relation. Currently the verification consists of checking
whether ``C[]`` is a syntactic composition of morphism instances that respects some obvious
compatibility constraints.
+.. example:: Rewriting
-**Example 5 (Rewriting):**
-
-Continuing the previous examples, suppose that the user must prove
-``set_eq int (union int (union int S1 S2) S2) (f S1 S2)`` under the
-hypothesis ``H: set_eq int S2 (@nil int)``. It
-is possible to use the ``rewrite`` tactic to replace the first two
-occurrences of ``S2`` with ``@nil int`` in the goal since the
-context ``set_eq int (union int (union int S1 nil) nil) (f S1 S2)``,
-being a composition of morphisms instances, is a morphism. However the
-tactic will fail replacing the third occurrence of ``S2`` unless ``f``
-has also been declared as a morphism.
+ Continuing the previous examples, suppose that the user must prove
+ ``set_eq int (union int (union int S1 S2) S2) (f S1 S2)`` under the
+ hypothesis ``H : set_eq int S2 (@nil int)``. It
+ is possible to use the ``rewrite`` tactic to replace the first two
+ occurrences of ``S2`` with ``@nil int`` in the goal since the
+ context ``set_eq int (union int (union int S1 nil) nil) (f S1 S2)``,
+ being a composition of morphisms instances, is a morphism. However the
+ tactic will fail replacing the third occurrence of ``S2`` unless ``f``
+ has also been declared as a morphism.
Adding new relations and morphisms
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-A parametric relation :g:`Aeq: forall (y1 : β1 ... ym : βm )`,
-:g:`relation (A t1 ... tn)` over :g:`(A : αi -> ... αn -> Type)` can be
-declared with the following command:
+.. cmd:: Add Parametric Relation (x1 : T1) ... (xn : Tk) : (A t1 ... tn) (Aeq t′1 ... t′m) {? reflexivity proved by refl} {? symmetry proved by sym} {? transitivity proved by trans} as @ident
-.. cmd:: Add Parametric Relation (x1 : T1) ... (xn : Tk) : (A t1 ... tn) (Aeq t′1 ... t′m ) {? reflexivity proved by refl} {? symmetry proved by sym} {? transitivity proved by trans} as @ident
-
-after having required the ``Setoid`` module with the ``Require Setoid``
-command.
+ This command declares a parametric relation :g:`Aeq: forall (y1 : β1 ... ym : βm)`,
+ :g:`relation (A t1 ... tn)` over :g:`(A : αi -> ... αn -> Type)`.
-The :g:`@ident` gives a unique name to the morphism and it is used
-by the command to generate fresh names for automatically provided
-lemmas used internally.
+ The :token:`ident` gives a unique name to the morphism and it is used
+ by the command to generate fresh names for automatically provided
+ lemmas used internally.
-Notice that the carrier and relation parameters may refer to the
-context of variables introduced at the beginning of the declaration,
-but the instances need not be made only of variables. Also notice that
-``A`` is *not* required to be a term having the same parameters as ``Aeq``,
-although that is often the case in practice (this departs from the
-previous implementation).
+ Notice that the carrier and relation parameters may refer to the
+ context of variables introduced at the beginning of the declaration,
+ but the instances need not be made only of variables. Also notice that
+ ``A`` is *not* required to be a term having the same parameters as ``Aeq``,
+ although that is often the case in practice (this departs from the
+ previous implementation).
+ To use this command, you need to first import the module ``Setoid`` using
+ the command ``Require Import Setoid``.
.. cmd:: Add Relation
-In case the carrier and relations are not parametric, one can use this command
-instead, whose syntax is the same except there is no local context.
+ In case the carrier and relations are not parametric, one can use this command
+ instead, whose syntax is the same except there is no local context.
-The proofs of reflexivity, symmetry and transitivity can be omitted if
-the relation is not an equivalence relation. The proofs must be
-instances of the corresponding relation definitions: e.g. the proof of
-reflexivity must have a type convertible to
-:g:`reflexive (A t1 ... tn) (Aeq t′ 1 …t′ n )`.
-Each proof may refer to the introduced variables as well.
+ The proofs of reflexivity, symmetry and transitivity can be omitted if
+ the relation is not an equivalence relation. The proofs must be
+ instances of the corresponding relation definitions: e.g. the proof of
+ reflexivity must have a type convertible to
+ :g:`reflexive (A t1 ... tn) (Aeq t′ 1 …t′ n)`.
+ Each proof may refer to the introduced variables as well.
-**Example 6 (Parametric relation):**
+.. example:: Parametric relation
-For Leibniz equality, we may declare:
+ For Leibniz equality, we may declare:
-.. coqtop:: in
+ .. coqtop:: in
- Add Parametric Relation (A : Type) : A (@eq A)
- [reflexivity proved by @refl_equal A]
- ...
+ Add Parametric Relation (A : Type) : A (@eq A)
+ [reflexivity proved by @refl_equal A]
+ ...
Some tactics (:tacn:`reflexivity`, :tacn:`symmetry`, :tacn:`transitivity`) work only on
relations that respect the expected properties. The remaining tactics
-(`replace`, :tacn:`rewrite` and derived tactics such as :tacn:`autorewrite`) do not
+(:tacn:`replace`, :tacn:`rewrite` and derived tactics such as :tacn:`autorewrite`) do not
require any properties over the relation. However, they are able to
replace terms with related ones only in contexts that are syntactic
compositions of parametric morphism instances declared with the
following command.
-.. cmd:: Add Parametric Morphism (x1 : T1 ) ... (xk : Tk ) : (f t1 ... tn ) with signature sig as @ident
+.. cmd:: Add Parametric Morphism (x1 : T1) ... (xk : Tk) : (f t1 ... tn) with signature sig as @ident
-The command declares ``f`` as a parametric morphism of signature ``sig``. The
-identifier ``id`` gives a unique name to the morphism and it is used as
-the base name of the type class instance definition and as the name of
-the lemma that proves the well-definedness of the morphism. The
-parameters of the morphism as well as the signature may refer to the
-context of variables. The command asks the user to prove interactively
-that ``f`` respects the relations identified from the signature.
+ This command declares ``f`` as a parametric morphism of signature ``sig``. The
+ identifier :token:`ident` gives a unique name to the morphism and it is used as
+ the base name of the typeclass instance definition and as the name of
+ the lemma that proves the well-definedness of the morphism. The
+ parameters of the morphism as well as the signature may refer to the
+ context of variables. The command asks the user to prove interactively
+ that ``f`` respects the relations identified from the signature.
-**Example 7:**
+.. example::
-We start the example by assuming a small theory over
-homogeneous sets and we declare set equality as a parametric
-equivalence relation and union of two sets as a parametric morphism.
+ We start the example by assuming a small theory over
+ homogeneous sets and we declare set equality as a parametric
+ equivalence relation and union of two sets as a parametric morphism.
-.. coqtop:: in
+ .. coqtop:: in
- Require Export Setoid.
- Require Export Relation_Definitions.
+ Require Export Setoid.
+ Require Export Relation_Definitions.
- Set Implicit Arguments.
+ Set Implicit Arguments.
- Parameter set: Type -> Type.
- Parameter empty: forall A, set A.
- Parameter eq_set: forall A, set A -> set A -> Prop.
- Parameter union: forall A, set A -> set A -> set A.
+ Parameter set : Type -> Type.
+ Parameter empty : forall A, set A.
+ Parameter eq_set : forall A, set A -> set A -> Prop.
+ Parameter union : forall A, set A -> set A -> set A.
- Axiom eq_set_refl: forall A, reflexive _ (eq_set (A:=A)).
- Axiom eq_set_sym: forall A, symmetric _ (eq_set (A:=A)).
- Axiom eq_set_trans: forall A, transitive _ (eq_set (A:=A)).
- Axiom empty_neutral: forall A (S: set A), eq_set (union S (empty A)) S.
+ Axiom eq_set_refl : forall A, reflexive _ (eq_set (A:=A)).
+ Axiom eq_set_sym : forall A, symmetric _ (eq_set (A:=A)).
+ Axiom eq_set_trans : forall A, transitive _ (eq_set (A:=A)).
+ Axiom empty_neutral : forall A (S : set A), eq_set (union S (empty A)) S.
- Axiom union_compat: forall (A : Type),
- forall x x' : set A, eq_set x x' ->
- forall y y' : set A, eq_set y y' ->
- eq_set (union x y) (union x' y').
+ Axiom union_compat :
+ forall (A : Type),
+ forall x x' : set A, eq_set x x' ->
+ forall y y' : set A, eq_set y y' ->
+ eq_set (union x y) (union x' y').
- Add Parametric Relation A : (set A) (@eq_set A)
- reflexivity proved by (eq_set_refl (A:=A))
- symmetry proved by (eq_set_sym (A:=A))
- transitivity proved by (eq_set_trans (A:=A))
- as eq_set_rel.
+ Add Parametric Relation A : (set A) (@eq_set A)
+ reflexivity proved by (eq_set_refl (A:=A))
+ symmetry proved by (eq_set_sym (A:=A))
+ transitivity proved by (eq_set_trans (A:=A))
+ as eq_set_rel.
- Add Parametric Morphism A : (@union A) with
- signature (@eq_set A) ==> (@eq_set A) ==> (@eq_set A) as union_mor.
- Proof.
- exact (@union_compat A).
- Qed.
+ Add Parametric Morphism A : (@union A)
+ with signature (@eq_set A) ==> (@eq_set A) ==> (@eq_set A) as union_mor.
+ Proof.
+ exact (@union_compat A).
+ Qed.
-It is possible to reduce the burden of specifying parameters using
-(maximally inserted) implicit arguments. If ``A`` is always set as
-maximally implicit in the previous example, one can write:
+ It is possible to reduce the burden of specifying parameters using
+ (maximally inserted) implicit arguments. If ``A`` is always set as
+ maximally implicit in the previous example, one can write:
-.. coqtop:: in
+ .. coqtop:: in
- Add Parametric Relation A : (set A) eq_set
- reflexivity proved by eq_set_refl
- symmetry proved by eq_set_sym
- transitivity proved by eq_set_trans
- as eq_set_rel.
+ Add Parametric Relation A : (set A) eq_set
+ reflexivity proved by eq_set_refl
+ symmetry proved by eq_set_sym
+ transitivity proved by eq_set_trans
+ as eq_set_rel.
-.. coqtop:: in
+ .. coqtop:: in
- Add Parametric Morphism A : (@union A) with
- signature eq_set ==> eq_set ==> eq_set as union_mor.
+ Add Parametric Morphism A : (@union A) with
+ signature eq_set ==> eq_set ==> eq_set as union_mor.
-.. coqtop:: in
+ .. coqtop:: in
- Proof. exact (@union_compat A). Qed.
+ Proof. exact (@union_compat A). Qed.
-We proceed now by proving a simple lemma performing a rewrite step and
-then applying reflexivity, as we would do working with Leibniz
-equality. Both tactic applications are accepted since the required
-properties over ``eq_set`` and ``union`` can be established from the two
-declarations above.
+ We proceed now by proving a simple lemma performing a rewrite step and
+ then applying reflexivity, as we would do working with Leibniz
+ equality. Both tactic applications are accepted since the required
+ properties over ``eq_set`` and ``union`` can be established from the two
+ declarations above.
-.. coqtop:: in
+ .. coqtop:: in
- Goal forall (S: set nat),
- eq_set (union (union S empty) S) (union S S).
+ Goal forall (S : set nat),
+ eq_set (union (union S empty) S) (union S S).
-.. coqtop:: in
+ .. coqtop:: in
- Proof. intros. rewrite empty_neutral. reflexivity. Qed.
+ Proof. intros. rewrite empty_neutral. reflexivity. Qed.
-The tables of relations and morphisms are managed by the type class
-instance mechanism. The behavior on section close is to generalize the
-instances by the variables of the section (and possibly hypotheses
-used in the proofs of instance declarations) but not to export them in
-the rest of the development for proof search. One can use the
-cmd:`Existing Instance` command to do so outside the section, using the name of the
-declared morphism suffixed by ``_Morphism``, or use the ``Global`` modifier
-for the corresponding class instance declaration
-(see :ref:`First Class Setoids and Morphisms <first-class-setoids-and-morphisms>`) at
-definition time. When loading a compiled file or importing a module,
-all the declarations of this module will be loaded.
+ The tables of relations and morphisms are managed by the typeclass
+ instance mechanism. The behavior on section close is to generalize the
+ instances by the variables of the section (and possibly hypotheses
+ used in the proofs of instance declarations) but not to export them in
+ the rest of the development for proof search. One can use the
+ cmd:`Existing Instance` command to do so outside the section, using the name of the
+ declared morphism suffixed by ``_Morphism``, or use the ``Global`` modifier
+ for the corresponding class instance declaration
+ (see :ref:`First Class Setoids and Morphisms <first-class-setoids-and-morphisms>`) at
+ definition time. When loading a compiled file or importing a module,
+ all the declarations of this module will be loaded.
Rewriting and non reflexive relations
@@ -332,31 +329,31 @@ To replace only one argument of an n-ary morphism it is necessary to
prove that all the other arguments are related to themselves by the
respective relation instances.
-**Example 8:**
+.. example::
-To replace ``(union S empty)`` with ``S`` in ``(union (union S empty) S) (union S S)``
-the rewrite tactic must exploit the monotony of ``union`` (axiom ``union_compat``
-in the previous example). Applying ``union_compat`` by hand we are left with the
-goal ``eq_set (union S S) (union S S)``.
+ To replace ``(union S empty)`` with ``S`` in ``(union (union S empty) S) (union S S)``
+ the rewrite tactic must exploit the monotony of ``union`` (axiom ``union_compat``
+ in the previous example). Applying ``union_compat`` by hand we are left with the
+ goal ``eq_set (union S S) (union S S)``.
When the relations associated to some arguments are not reflexive, the
tactic cannot automatically prove the reflexivity goals, that are left
to the user.
-Setoids whose relation are partial equivalence relations (PER) are
-useful to deal with partial functions. Let ``R`` be a PER. We say that an
+Setoids whose relations are partial equivalence relations (PER) are
+useful for dealing with partial functions. Let ``R`` be a PER. We say that an
element ``x`` is defined if ``R x x``. A partial function whose domain
-comprises all the defined elements only is declared as a morphism that
+comprises all the defined elements is declared as a morphism that
respects ``R``. Every time a rewriting step is performed the user must
prove that the argument of the morphism is defined.
-**Example 9:**
+.. example::
-Let ``eqO`` be ``fun x y => x = y /\ x <> 0`` (the
-smaller PER over non zero elements). Division can be declared as a
-morphism of signature ``eq ==> eq0 ==> eq``. Replace ``x`` with
-``y`` in ``div x n = div y n`` opens the additional goal ``eq0 n n``
-that is equivalent to ``n = n /\ n <> 0``.
+ Let ``eqO`` be ``fun x y => x = y /\ x <> 0`` (the
+ smallest PER over nonzero elements). Division can be declared as a
+ morphism of signature ``eq ==> eq0 ==> eq``. Replacing ``x`` with
+ ``y`` in ``div x n = div y n`` opens an additional goal ``eq0 n n``
+ which is equivalent to ``n = n /\ n <> 0``.
Rewriting and non symmetric relations
@@ -371,44 +368,44 @@ a contravariant position. In a similar way, replacement in an
hypothesis can be performed only if the replaced term occurs in a
covariant position.
-**Example 10 (Covariance and contravariance):**
-
-Suppose that division over real numbers has been defined as a morphism of signature
-``Z.div: Z.lt ++> Z.lt --> Z.lt`` (i.e. ``Z.div`` is increasing in
-its first argument, but decreasing on the second one). Let ``<``
-denotes ``Z.lt``. Under the hypothesis ``H: x < y`` we have
-``k < x / y -> k < x / x``, but not ``k < y / x -> k < x / x``. Dually,
-under the same hypothesis ``k < x / y -> k < y / y`` holds, but
-``k < y / x -> k < y / y`` does not. Thus, if the current goal is
-``k < x / x``, it is possible to replace only the second occurrence of
-``x`` (in contravariant position) with ``y`` since the obtained goal
-must imply the current one. On the contrary, if ``k < x / x`` is an
-hypothesis, it is possible to replace only the first occurrence of
-``x`` (in covariant position) with ``y`` since the current
-hypothesis must imply the obtained one.
-
-Contrary to the previous implementation, no specific error message
-will be raised when trying to replace a term that occurs in the wrong
-position. It will only fail because the rewriting constraints are not
-satisfiable. However it is possible to use the at modifier to specify
-which occurrences should be rewritten.
-
-As expected, composing morphisms together propagates the variance
-annotations by switching the variance every time a contravariant
-position is traversed.
-
-**Example 11:**
-
-Let us continue the previous example and let us consider
-the goal ``x / (x / x) < k``. The first and third occurrences of
-``x`` are in a contravariant position, while the second one is in
-covariant position. More in detail, the second occurrence of ``x``
-occurs covariantly in ``(x / x)`` (since division is covariant in
-its first argument), and thus contravariantly in ``x / (x / x)``
-(since division is contravariant in its second argument), and finally
-covariantly in ``x / (x / x) < k`` (since ``<``, as every
-transitive relation, is contravariant in its first argument with
-respect to the relation itself).
+.. example:: Covariance and contravariance
+
+ Suppose that division over real numbers has been defined as a morphism of signature
+ ``Z.div : Z.lt ++> Z.lt --> Z.lt`` (i.e. ``Z.div`` is increasing in
+ its first argument, but decreasing on the second one). Let ``<``
+ denote ``Z.lt``. Under the hypothesis ``H : x < y`` we have
+ ``k < x / y -> k < x / x``, but not ``k < y / x -> k < x / x``. Dually,
+ under the same hypothesis ``k < x / y -> k < y / y`` holds, but
+ ``k < y / x -> k < y / y`` does not. Thus, if the current goal is
+ ``k < x / x``, it is possible to replace only the second occurrence of
+ ``x`` (in contravariant position) with ``y`` since the obtained goal
+ must imply the current one. On the contrary, if ``k < x / x`` is an
+ hypothesis, it is possible to replace only the first occurrence of
+ ``x`` (in covariant position) with ``y`` since the current
+ hypothesis must imply the obtained one.
+
+ Contrary to the previous implementation, no specific error message
+ will be raised when trying to replace a term that occurs in the wrong
+ position. It will only fail because the rewriting constraints are not
+ satisfiable. However it is possible to use the at modifier to specify
+ which occurrences should be rewritten.
+
+ As expected, composing morphisms together propagates the variance
+ annotations by switching the variance every time a contravariant
+ position is traversed.
+
+.. example::
+
+ Let us continue the previous example and let us consider
+ the goal ``x / (x / x) < k``. The first and third occurrences of
+ ``x`` are in a contravariant position, while the second one is in
+ covariant position. More in detail, the second occurrence of ``x``
+ occurs covariantly in ``(x / x)`` (since division is covariant in
+ its first argument), and thus contravariantly in ``x / (x / x)``
+ (since division is contravariant in its second argument), and finally
+ covariantly in ``x / (x / x) < k`` (since ``<``, as every
+ transitive relation, is contravariant in its first argument with
+ respect to the relation itself).
Rewriting in ambiguous setoid contexts
@@ -417,15 +414,14 @@ Rewriting in ambiguous setoid contexts
One function can respect several different relations and thus it can
be declared as a morphism having multiple signatures.
-**Example 12:**
-
+.. example::
-Union over homogeneous lists can be given all the
-following signatures: ``eq ==> eq ==> eq`` (``eq`` being the
-equality over ordered lists) ``set_eq ==> set_eq ==> set_eq``
-(``set_eq`` being the equality over unordered lists up to duplicates),
-``multiset_eq ==> multiset_eq ==> multiset_eq`` (``multiset_eq``
-being the equality over unordered lists).
+ Union over homogeneous lists can be given all the
+ following signatures: ``eq ==> eq ==> eq`` (``eq`` being the
+ equality over ordered lists) ``set_eq ==> set_eq ==> set_eq``
+ (``set_eq`` being the equality over unordered lists up to duplicates),
+ ``multiset_eq ==> multiset_eq ==> multiset_eq`` (``multiset_eq``
+ being the equality over unordered lists).
To declare multiple signatures for a morphism, repeat the :cmd:`Add Morphism`
command.
@@ -435,7 +431,7 @@ rewrite request is ambiguous, since it is unclear what relations
should be used to perform the rewriting. Contrary to the previous
implementation, the tactic will always choose the first possible
solution to the set of constraints generated by a rewrite and will not
-try to find *all* possible solutions to warn the user about.
+try to find *all* the possible solutions to warn the user about them.
Commands and tactics
@@ -450,14 +446,14 @@ First class setoids and morphisms
The implementation is based on a first-class representation of
-properties of relations and morphisms as type classes. That is, the
+properties of relations and morphisms as typeclasses. That is, the
various combinations of properties on relations and morphisms are
represented as records and instances of theses classes are put in a
hint database. For example, the declaration:
.. coqtop:: in
- Add Parametric Relation (x1 : T1) ... (xn : Tk) : (A t1 ... tn) (Aeq t′1 ... t′m)
+ Add Parametric Relation (x1 : T1) ... (xn : Tn) : (A t1 ... tn) (Aeq t′1 ... t′m)
[reflexivity proved by refl]
[symmetry proved by sym]
[transitivity proved by trans]
@@ -468,7 +464,7 @@ is equivalent to an instance declaration:
.. coqtop:: in
- Instance (x1 : T1) ... (xn : Tk) => id : @Equivalence (A t1 ... tn) (Aeq t′1 ... t′m) :=
+ Instance (x1 : T1) ... (xn : Tn) => id : @Equivalence (A t1 ... tn) (Aeq t′1 ... t′m) :=
[Equivalence_Reflexive := refl]
[Equivalence_Symmetric := sym]
[Equivalence_Transitive := trans].
@@ -476,9 +472,9 @@ is equivalent to an instance declaration:
The declaration itself amounts to the definition of an object of the
record type ``Coq.Classes.RelationClasses.Equivalence`` and a hint added
to the ``typeclass_instances`` hint database. Morphism declarations are
-also instances of a type class defined in ``Classes.Morphisms``. See the
-documentation on type classes :ref:`typeclasses`
-and the theories files in Classes for further explanations.
+also instances of a typeclass defined in ``Classes.Morphisms``. See the
+documentation on :ref:`typeclasses` and the theories files in Classes
+for further explanations.
One can inform the rewrite tactic about morphisms and relations just
by using the typeclass mechanism to declare them using Instance and
@@ -491,37 +487,37 @@ handled by encoding them as records. In the following example, the
projections of the setoid relation and of the morphism function can be
registered as parametric relations and morphisms.
-**Example 13 (First class setoids):**
+.. example:: First class setoids
-.. coqtop:: in
+ .. coqtop:: in
- Require Import Relation_Definitions Setoid.
+ Require Import Relation_Definitions Setoid.
- Record Setoid: Type :=
- { car: Type;
- eq: car -> car -> Prop;
- refl: reflexive _ eq;
- sym: symmetric _ eq;
- trans: transitive _ eq
- }.
+ Record Setoid : Type :=
+ { car: Type;
+ eq: car -> car -> Prop;
+ refl: reflexive _ eq;
+ sym: symmetric _ eq;
+ trans: transitive _ eq
+ }.
- Add Parametric Relation (s : Setoid) : (@car s) (@eq s)
- reflexivity proved by (refl s)
- symmetry proved by (sym s)
- transitivity proved by (trans s) as eq_rel.
+ Add Parametric Relation (s : Setoid) : (@car s) (@eq s)
+ reflexivity proved by (refl s)
+ symmetry proved by (sym s)
+ transitivity proved by (trans s) as eq_rel.
- Record Morphism (S1 S2:Setoid): Type :=
- { f: car S1 -> car S2;
- compat: forall (x1 x2: car S1), eq S1 x1 x2 -> eq S2 (f x1) (f x2)
- }.
+ Record Morphism (S1 S2 : Setoid) : Type :=
+ { f: car S1 -> car S2;
+ compat: forall (x1 x2 : car S1), eq S1 x1 x2 -> eq S2 (f x1) (f x2)
+ }.
- Add Parametric Morphism (S1 S2 : Setoid) (M : Morphism S1 S2) :
- (@f S1 S2 M) with signature (@eq S1 ==> @eq S2) as apply_mor.
- Proof. apply (compat S1 S2 M). Qed.
+ Add Parametric Morphism (S1 S2 : Setoid) (M : Morphism S1 S2) :
+ (@f S1 S2 M) with signature (@eq S1 ==> @eq S2) as apply_mor.
+ Proof. apply (compat S1 S2 M). Qed.
- Lemma test: forall (S1 S2:Setoid) (m: Morphism S1 S2)
- (x y: car S1), eq S1 x y -> eq S2 (f _ _ m x) (f _ _ m y).
- Proof. intros. rewrite H. reflexivity. Qed.
+ Lemma test : forall (S1 S2 : Setoid) (m : Morphism S1 S2)
+ (x y : car S1), eq S1 x y -> eq S2 (f _ _ m x) (f _ _ m y).
+ Proof. intros. rewrite H. reflexivity. Qed.
.. _tactics-enabled-on-user-provided-relations:
@@ -539,33 +535,32 @@ pass additional arguments such as ``using relation``.
.. tacv:: setoid_reflexivity
:name: setoid_reflexivity
-.. tacv:: setoid_symmetry [in @ident]
+.. tacv:: setoid_symmetry {? in @ident}
:name: setoid_symmetry
.. tacv:: setoid_transitivity
:name: setoid_transitivity
-.. tacv:: setoid_rewrite [@orientation] @term [at @occs] [in @ident]
+.. tacv:: setoid_rewrite {? @orientation} @term {? at @occs} {? in @ident}
:name: setoid_rewrite
-.. tacv:: setoid_replace @term with @term [in @ident] [using relation @term] [by @tactic]
+.. tacv:: setoid_replace @term with @term {? using relation @term} {? in @ident} {? by @tactic}
:name: setoid_replace
-
-The ``using relation`` arguments cannot be passed to the unprefixed form.
-The latter argument tells the tactic what parametric relation should
-be used to replace the first tactic argument with the second one. If
-omitted, it defaults to the ``DefaultRelation`` instance on the type of
-the objects. By default, it means the most recent ``Equivalence`` instance
-in the environment, but it can be customized by declaring
-new ``DefaultRelation`` instances. As Leibniz equality is a declared
-equivalence, it will fall back to it if no other relation is declared
-on a given type.
+ The ``using relation`` arguments cannot be passed to the unprefixed form.
+ The latter argument tells the tactic what parametric relation should
+ be used to replace the first tactic argument with the second one. If
+ omitted, it defaults to the ``DefaultRelation`` instance on the type of
+ the objects. By default, it means the most recent ``Equivalence`` instance
+ in the environment, but it can be customized by declaring
+ new ``DefaultRelation`` instances. As Leibniz equality is a declared
+ equivalence, it will fall back to it if no other relation is declared
+ on a given type.
Every derived tactic that is based on the unprefixed forms of the
tactics considered above will also work up to user defined relations.
For instance, it is possible to register hints for :tacn:`autorewrite` that
-are not proof of Leibniz equalities. In particular it is possible to
+are not proofs of Leibniz equalities. In particular it is possible to
exploit :tacn:`autorewrite` to simulate normalization in a term rewriting
system up to user defined equalities.
@@ -575,39 +570,39 @@ Printing relations and morphisms
.. cmd:: Print Instances
-This command can be used to show the list of currently
-registered ``Reflexive`` (using ``Print Instances Reflexive``), ``Symmetric``
-or ``Transitive`` relations, Equivalences, PreOrders, PERs, and Morphisms
-(implemented as ``Proper`` instances). When the rewriting tactics refuse
-to replace a term in a context because the latter is not a composition
-of morphisms, the :cmd:`Print Instances` command can be useful to understand
-what additional morphisms should be registered.
+ This command can be used to show the list of currently
+ registered ``Reflexive`` (using ``Print Instances Reflexive``), ``Symmetric``
+ or ``Transitive`` relations, Equivalences, PreOrders, PERs, and Morphisms
+ (implemented as ``Proper`` instances). When the rewriting tactics refuse
+ to replace a term in a context because the latter is not a composition
+ of morphisms, the :cmd:`Print Instances` command can be useful to understand
+ what additional morphisms should be registered.
Deprecated syntax and backward incompatibilities
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Due to backward compatibility reasons, the following syntax for the
-declaration of setoids and morphisms is also accepted.
-
.. cmd:: Add Setoid @A @Aeq @ST as @ident
-where ``Aeq`` is a congruence relation without parameters, ``A`` is its carrier
-and ``ST`` is an object of type (``Setoid_Theory A Aeq``) (i.e. a record
-packing together the reflexivity, symmetry and transitivity lemmas).
-Notice that the syntax is not completely backward compatible since the
-identifier was not required.
+ This command for declaring setoids and morphisms is also accepted due
+ to backward compatibility reasons.
+
+ Here ``Aeq`` is a congruence relation without parameters, ``A`` is its carrier
+ and ``ST`` is an object of type (``Setoid_Theory A Aeq``) (i.e. a record
+ packing together the reflexivity, symmetry and transitivity lemmas).
+ Notice that the syntax is not completely backward compatible since the
+ identifier was not required.
.. cmd:: Add Morphism f : @ident
:name: Add Morphism
-The latter command also is restricted to the declaration of morphisms
-without parameters. It is not fully backward compatible since the
-property the user is asked to prove is slightly different: for n-ary
-morphisms the hypotheses of the property are permuted; moreover, when
-the morphism returns a proposition, the property is now stated using a
-bi-implication in place of a simple implication. In practice, porting
-an old development to the new semantics is usually quite simple.
+ This command is restricted to the declaration of morphisms
+ without parameters. It is not fully backward compatible since the
+ property the user is asked to prove is slightly different: for n-ary
+ morphisms the hypotheses of the property are permuted; moreover, when
+ the morphism returns a proposition, the property is now stated using a
+ bi-implication in place of a simple implication. In practice, porting
+ an old development to the new semantics is usually quite simple.
Notice that several limitations of the old implementation have been
lifted. In particular, it is now possible to declare several relations
@@ -657,9 +652,8 @@ in ``Prop`` are implicitly translated to such applications).
Indeed, when rewriting under a lambda, binding variable ``x``, say from ``P x``
to ``Q x`` using the relation iff, the tactic will generate a proof of
``pointwise_relation A iff (fun x => P x) (fun x => Q x)`` from the proof
-of ``iff (P x) (Q x)`` and a constraint of the form Proper
-``(pointwise_relation A iff ==> ?) m`` will be generated for the
-surrounding morphism ``m``.
+of ``iff (P x) (Q x)`` and a constraint of the form ``Proper (pointwise_relation A iff ==> ?) m``
+will be generated for the surrounding morphism ``m``.
Hence, one can add higher-order combinators as morphisms by providing
signatures using pointwise extension for the relations on the
@@ -685,11 +679,11 @@ default. The semantics of the previous :tacn:`setoid_rewrite` implementation
can almost be recovered using the ``at 1`` modifier.
-Sub-relations
+Subrelations
~~~~~~~~~~~~~
-Sub-relations can be used to specify that one relation is included in
-another, so that morphisms signatures for one can be used for the
+Subrelations can be used to specify that one relation is included in
+another, so that morphism signatures for one can be used for the
other. If a signature mentions a relation ``R`` on the left of an
arrow ``==>``, then the signature also applies for any relation ``S`` that is
smaller than ``R``, and the inverse applies on the right of an arrow. One
@@ -702,14 +696,14 @@ two morphisms for conjunction: ``Proper (impl ==> impl ==> impl) and`` and
rewriting constraints arising from a rewrite using ``iff``, ``impl`` or
``inverse impl`` through ``and``.
-Sub-relations are implemented in ``Classes.Morphisms`` and are a prime
+Subrelations are implemented in ``Classes.Morphisms`` and are a prime
example of a mostly user-space extension of the algorithm.
Constant unfolding
~~~~~~~~~~~~~~~~~~
-The resolution tactic is based on type classes and hence regards user-
+The resolution tactic is based on typeclasses and hence regards user-
defined constants as transparent by default. This may slow down the
resolution due to a lot of unifications (all the declared ``Proper``
instances are tried at each node of the search tree). To speed it up,
diff --git a/doc/sphinx/addendum/implicit-coercions.rst b/doc/sphinx/addendum/implicit-coercions.rst
index 09faa06765..c0c4539564 100644
--- a/doc/sphinx/addendum/implicit-coercions.rst
+++ b/doc/sphinx/addendum/implicit-coercions.rst
@@ -31,7 +31,7 @@ A class with `n` parameters is any defined name with a type
:g:`forall (x₁:A₁)..(xₙ:Aₙ),s` where ``s`` is a sort. Thus a class with
parameters is considered as a single class and not as a family of
classes. An object of a class ``C`` is any term of type :g:`C t₁ .. tₙ`.
-In addition to these user-classes, we have two abstract classes:
+In addition to these user-defined classes, we have two built-in classes:
* ``Sortclass``, the class of sorts; its objects are the terms whose type is a
@@ -50,11 +50,11 @@ Formally, the syntax of a classes is defined as:
Coercions
---------
-A name ``f`` can be declared as a coercion between a source user-class
+A name ``f`` can be declared as a coercion between a source user-defined class
``C`` with `n` parameters and a target class ``D`` if one of these
conditions holds:
- * ``D`` is a user-class, then the type of ``f`` must have the form
+ * ``D`` is a user-defined class, then the type of ``f`` must have the form
:g:`forall (x₁:A₁)..(xₙ:Aₙ)(y:C x₁..xₙ), D u₁..uₘ` where `m`
is the number of parameters of ``D``.
* ``D`` is ``Funclass``, then the type of ``f`` must have the form
@@ -65,8 +65,8 @@ conditions holds:
We then write :g:`f : C >-> D`. The restriction on the type
of coercions is called *the uniform inheritance condition*.
-.. note:: The abstract class ``Sortclass`` can be used as a source class, but
- the abstract class ``Funclass`` cannot.
+.. note:: The built-in class ``Sortclass`` can be used as a source class, but
+ the built-in class ``Funclass`` cannot.
To coerce an object :g:`t:C t₁..tₙ` of ``C`` towards ``D``, we have to
apply the coercion ``f`` to it; the obtained term :g:`f t₁..tₙ t` is
@@ -95,7 +95,7 @@ We can now declare ``f`` as coercion from ``C'`` to ``D``, since we can
The identity coercions have a special status: to coerce an object
:g:`t:C' t₁..tₖ`
-of ``C'`` towards ``C``, we does not have to insert explicitly ``Id_C'_C``
+of ``C'`` towards ``C``, we do not have to insert explicitly ``Id_C'_C``
since :g:`Id_C'_C t₁..tₖ t` is convertible with ``t``. However we
"rewrite" the type of ``t`` to become an object of ``C``; in this case,
it becomes :g:`C uₙ'..uₖ'` where each ``uᵢ'`` is the result of the
@@ -121,7 +121,7 @@ by the coercions ``f₁..fₖ``. The application of a coercion path to a
term consists of the successive application of its coercions.
-Declaration of Coercions
+Declaring Coercions
-------------------------
.. cmd:: Coercion @qualid : @class >-> @class
@@ -140,8 +140,8 @@ Declaration of Coercions
.. warn:: Ambiguous path.
- When the coercion :token:`qualid` is added to the inheritance graph, non
- valid coercion paths are ignored; they are signaled by a warning
+ When the coercion :token:`qualid` is added to the inheritance graph,
+ invalid coercion paths are ignored; they are signaled by a warning
displaying these paths of the form :g:`[f₁;..;fₙ] : C >-> D`.
.. cmdv:: Local Coercion @qualid : @class >-> @class
@@ -215,7 +215,7 @@ declaration, this constructor is declared as a coercion.
.. cmdv:: Local Identity Coercion @ident : @ident >-> @ident
- Idem but locally to the current section.
+ Same as ``Identity Coercion`` but locally to the current section.
.. cmdv:: SubClass @ident := @type
:name: SubClass
@@ -319,7 +319,7 @@ Coercions and Modules
Since |Coq| version 8.3, the coercions present in a module are activated
only when the module is explicitly imported. Formerly, the coercions
- were activated as soon as the module was required, whatever it was
+ were activated as soon as the module was required, whether it was
imported or not.
This option makes it possible to recover the behavior of the versions of
@@ -352,7 +352,7 @@ We first give an example of coercion between atomic inductive types
.. warning::
- Note that ``Check true=O`` would fail. This is "normal" behaviour of
+ Note that ``Check true=O`` would fail. This is "normal" behavior of
coercions. To validate ``true=O``, the coercion is searched from
``nat`` to ``bool``. There is none.
@@ -387,8 +387,8 @@ We give now an example using identity coercions.
In the case of functional arguments, we use the monotonic rule of
-sub-typing. Approximatively, to coerce :g:`t:forall x:A,B` towards
-:g:`forall x:A',B'`, one have to coerce ``A'`` towards ``A`` and ``B``
+sub-typing. To coerce :g:`t : forall x : A, B` towards
+:g:`forall x : A', B'`, we have to coerce ``A'`` towards ``A`` and ``B``
towards ``B'``. An example is given below:
.. coqtop:: all
@@ -424,8 +424,8 @@ replaced by ``x:A'`` where ``A'`` is the result of the application to
``Sortclass`` if it exists. This case occurs in the abstraction
:g:`fun x:A => t`, universal quantification :g:`forall x:A,B`, global
variables and parameters of (co-)inductive definitions and
-functions. In :g:`forall x:A,B`, such a coercion path may be applied
-to ``B`` also if necessary.
+functions. In :g:`forall x:A,B`, such a coercion path may also be applied
+to ``B`` if necessary.
.. coqtop:: all
diff --git a/doc/sphinx/addendum/micromega.rst b/doc/sphinx/addendum/micromega.rst
index 0e9c23b9bb..d03a31c044 100644
--- a/doc/sphinx/addendum/micromega.rst
+++ b/doc/sphinx/addendum/micromega.rst
@@ -20,7 +20,7 @@ rationals ``Require Import Lqa`` and reals ``Require Import Lra``.
+ :tacn:`nra` is an incomplete proof procedure for non-linear (real or
rational) arithmetic;
+ :tacn:`psatz` ``D n`` where ``D`` is :math:`\mathbb{Z}` or :math:`\mathbb{Q}` or :math:`\mathbb{R}`, and
- ``n`` is an optional integer limiting the proof search depth
+ ``n`` is an optional integer limiting the proof search depth,
is an incomplete proof procedure for non-linear arithmetic.
It is based on John Harrison’s HOL Light
driver to the external prover `csdp` [#]_. Note that the `csdp` driver is
@@ -32,10 +32,10 @@ arithmetic expressions interpreted over a domain :math:`D` ∈ {ℤ, ℚ, ℝ}.
The syntax of the formulas is the following:
.. productionlist:: `F`
- F : A ∣ P ∣ True ∣ False ∣ F 1 ∧ F 2 ∣ F 1 ∨ F 2 ∣ F 1 ↔ F 2 ∣ F 1 → F 2 ∣ ¬ F
- A : p 1 = p 2 ∣ p 1 > p 2 ∣ p 1 < p 2 ∣ p 1 ≥ p 2 ∣ p 1 ≤ p 2
- p : c ∣ x ∣ −p ∣ p 1 − p 2 ∣ p 1 + p 2 ∣ p 1 × p 2 ∣ p ^ n
-
+ F : A ∣ P ∣ True ∣ False ∣ F ∧ F ∣ F ∨ F ∣ F ↔ F ∣ F → F ∣ ¬ F
+ A : p = p ∣ p > p ∣ p < p ∣ p ≥ p ∣ p ≤ p
+ p : c ∣ x ∣ −p ∣ p − p ∣ p + p ∣ p × p ∣ p ^ n
+
where :math:`c` is a numeric constant, :math:`x \in D` is a numeric variable, the
operators :math:`−, +, ×` are respectively subtraction, addition, and product;
:math:`p ^ n` is exponentiation by a constant :math:`n`, :math:`P` is an arbitrary proposition.
@@ -81,11 +81,11 @@ If :math:`-1` belongs to :math:`\mathit{Cone}(S)`, then the conjunction
A proof based on this theorem is called a *positivstellensatz*
refutation. The tactics work as follows. Formulas are normalized into
conjunctive normal form :math:`\bigwedge_i C_i` where :math:`C_i` has the
-general form :math:`(\bigwedge_{j\in S_i} p_j \Join 0) \to \mathit{False})` and
+general form :math:`(\bigwedge_{j\in S_i} p_j \Join 0) \to \mathit{False}` and
:math:`\Join \in \{>,\ge,=\}` for :math:`D\in \{\mathbb{Q},\mathbb{R}\}` and
:math:`\Join \in \{\ge, =\}` for :math:`\mathbb{Z}`.
-For each conjunct :math:`C_i`, the tactic calls a oracle which searches for
+For each conjunct :math:`C_i`, the tactic calls an oracle which searches for
:math:`-1` within the cone. Upon success, the oracle returns a *cone
expression* that is normalized by the ring tactic (see :ref:`theringandfieldtacticfamilies`)
and checked to be :math:`-1`.
@@ -96,15 +96,14 @@ and checked to be :math:`-1`.
.. tacn:: lra
:name: lra
-This tactic is searching for *linear* refutations using Fourier
-elimination [#]_. As a result, this tactic explores a subset of the *Cone*
-defined as
+ This tactic is searching for *linear* refutations using Fourier
+ elimination [#]_. As a result, this tactic explores a subset of the *Cone*
+ defined as
- :math:`\mathit{LinCone}(S) =\left\{ \left. \sum_{p \in S} \alpha_p \times p~\right|~\alpha_p \mbox{ are positive constants} \right\}`
+ :math:`\mathit{LinCone}(S) =\left\{ \left. \sum_{p \in S} \alpha_p \times p~\right|~\alpha_p \mbox{ are positive constants} \right\}`
-The deductive power of `lra` is the combined deductive power of
-`ring_simplify` and `fourier`. There is also an overlap with the field
-tactic *e.g.*, :math:`x = 10 * x / 10` is solved by `lra`.
+ The deductive power of :tacn:`lra` overlaps with the one of :tacn:`field`
+ tactic *e.g.*, :math:`x = 10 * x / 10` is solved by :tacn:`lra`.
`lia`: a tactic for linear integer arithmetic
diff --git a/doc/sphinx/addendum/miscellaneous-extensions.rst b/doc/sphinx/addendum/miscellaneous-extensions.rst
index b6c35d8fa7..0f2d35d044 100644
--- a/doc/sphinx/addendum/miscellaneous-extensions.rst
+++ b/doc/sphinx/addendum/miscellaneous-extensions.rst
@@ -32,6 +32,7 @@ When the proof ends two constants are defined:
ends with ``Qed``, and transparent if the proof ends with ``Defined``.
.. example::
+
.. coqtop:: all
Require Coq.derive.Derive.
diff --git a/doc/sphinx/addendum/nsatz.rst b/doc/sphinx/addendum/nsatz.rst
index 387d614956..9adeca46fc 100644
--- a/doc/sphinx/addendum/nsatz.rst
+++ b/doc/sphinx/addendum/nsatz.rst
@@ -1,63 +1,55 @@
.. include:: ../preamble.rst
-.. _nsatz:
+.. _nsatz_chapter:
Nsatz: tactics for proving equalities in integral domains
===========================================================
:Author: Loïc Pottier
-The tactic `nsatz` proves goals of the form
+.. tacn:: nsatz
+ :name: nsatz
-:math:`\begin{array}{l}
-\forall X_1,\ldots,X_n \in A,\\
-P_1(X_1,\ldots,X_n) = Q_1(X_1,\ldots,X_n) , \ldots , P_s(X_1,\ldots,X_n) =Q_s(X_1,\ldots,X_n)\\
-\vdash P(X_1,\ldots,X_n) = Q(X_1,\ldots,X_n)\\
-\end{array}`
+ This tactic is for solving goals of the form
-where :math:`P, Q, P₁,Q₁,\ldots,Pₛ, Qₛ` are polynomials and :math:`A` is an integral
-domain, i.e. a commutative ring with no zero divisor. For example, :math:`A`
-can be :math:`\mathbb{R}`, :math:`\mathbb{Z}`, or :math:`\mathbb{Q}`.
-Note that the equality :math:`=` used in these goals can be
-any setoid equality (see :ref:`tactics-enabled-on-user-provided-relations`) , not only Leibnitz equality.
+ :math:`\begin{array}{l}
+ \forall X_1, \ldots, X_n \in A, \\
+ P_1(X_1, \ldots, X_n) = Q_1(X_1, \ldots, X_n), \ldots, P_s(X_1, \ldots, X_n) = Q_s(X_1, \ldots, X_n) \\
+ \vdash P(X_1, \ldots, X_n) = Q(X_1, \ldots, X_n) \\
+ \end{array}`
-It also proves formulas
+ where :math:`P, Q, P_1, Q_1, \ldots, P_s, Q_s` are polynomials and :math:`A` is an integral
+ domain, i.e. a commutative ring with no zero divisors. For example, :math:`A`
+ can be :math:`\mathbb{R}`, :math:`\mathbb{Z}`, or :math:`\mathbb{Q}`.
+ Note that the equality :math:`=` used in these goals can be
+ any setoid equality (see :ref:`tactics-enabled-on-user-provided-relations`) , not only Leibniz equality.
-:math:`\begin{array}{l}
-\forall X_1,\ldots,X_n \in A,\\
-P_1(X_1,\ldots,X_n) = Q_1(X_1,\ldots,X_n) \wedge \ldots \wedge P_s(X_1,\ldots,X_n) =Q_s(X_1,\ldots,X_n)\\
-\rightarrow P(X_1,\ldots,X_n) = Q(X_1,\ldots,X_n)\\
-\end{array}`
+ It also proves formulas
-doing automatic introductions.
+ :math:`\begin{array}{l}
+ \forall X_1, \ldots, X_n \in A, \\
+ P_1(X_1, \ldots, X_n) = Q_1(X_1, \ldots, X_n) \wedge \ldots \wedge P_s(X_1, \ldots, X_n) = Q_s(X_1, \ldots, X_n) \\
+ \rightarrow P(X_1, \ldots, X_n) = Q(X_1, \ldots, X_n) \\
+ \end{array}`
+ doing automatic introductions.
-Using the basic tactic `nsatz`
-------------------------------
-
-
-Load the Nsatz module:
-
-.. coqtop:: all
-
- Require Import Nsatz.
-
-and use the tactic `nsatz`.
+ You can load the ``Nsatz`` module with the command ``Require Import Nsatz``.
More about `nsatz`
---------------------
Hilbert’s Nullstellensatz theorem shows how to reduce proofs of
-equalities on polynomials on a commutative ring :math:`A` with no zero divisor
+equalities on polynomials on a commutative ring :math:`A` with no zero divisors
to algebraic computations: it is easy to see that if a polynomial :math:`P` in
:math:`A[X_1,\ldots,X_n]` verifies :math:`c P^r = \sum_{i=1}^{s} S_i P_i`, with
:math:`c \in A`, :math:`c \not = 0`,
:math:`r` a positive integer, and the :math:`S_i` s in :math:`A[X_1,\ldots,X_n ]`,
then :math:`P` is zero whenever polynomials :math:`P_1,\ldots,P_s` are zero
-(the converse is also true when :math:`A` is an algebraic closed field: the method is
+(the converse is also true when :math:`A` is an algebraically closed field: the method is
complete).
-So, proving our initial problem can reduce into finding :math:`S_1,\ldots,S_s`,
+So, solving our initial problem reduces to finding :math:`S_1, \ldots, S_s`,
:math:`c` and :math:`r` such that :math:`c (P-Q)^r = \sum_{i} S_i (P_i-Q_i)`,
which will be proved by the tactic ring.
@@ -68,34 +60,31 @@ Buchberger algorithm.
This computation is done after a step of *reification*, which is
performed using :ref:`typeclasses`.
-The ``Nsatz`` module defines the tactic `nsatz`, which can be used without
-arguments, or with the syntax:
-
-| nsatz with radicalmax:=num%N strategy:=num%Z parameters:= :n:`{* var}` variables:= :n:`{* var}`
+.. tacv:: nsatz with radicalmax:=@num%N strategy:=@num%Z parameters:=[{*, @ident}] variables:=[{*, @ident}]
-where:
+ Most complete syntax for `nsatz`.
-* `radicalmax` is a bound when for searching r s.t.
- :math:`c (P−Q) r = \sum_{i=1..s} S_i (P i − Q i)`
+ * `radicalmax` is a bound when searching for r such that
+ :math:`c (P−Q) r = \sum_{i=1..s} S_i (P i − Q i)`
-* `strategy` gives the order on variables :math:`X_1,\ldots,X_n` and the strategy
- used in Buchberger algorithm (see :cite:`sugar` for details):
+ * `strategy` gives the order on variables :math:`X_1,\ldots,X_n` and the strategy
+ used in Buchberger algorithm (see :cite:`sugar` for details):
- * strategy = 0: reverse lexicographic order and newest s-polynomial.
- * strategy = 1: reverse lexicographic order and sugar strategy.
- * strategy = 2: pure lexicographic order and newest s-polynomial.
- * strategy = 3: pure lexicographic order and sugar strategy.
+ * strategy = 0: reverse lexicographic order and newest s-polynomial.
+ * strategy = 1: reverse lexicographic order and sugar strategy.
+ * strategy = 2: pure lexicographic order and newest s-polynomial.
+ * strategy = 3: pure lexicographic order and sugar strategy.
-* `parameters` is the list of variables :math:`X_{i_1},\ldots,X_{i_k}` among
- :math:`X_1,\ldots,X_n` which are considered as parameters: computation will be performed with
- rational fractions in these variables, i.e. polynomials are considered
- with coefficients in :math:`R(X_{i_1},\ldots,X_{i_k})`. In this case, the coefficient
- :math:`c` can be a non constant polynomial in :math:`X_{i_1},\ldots,X_{i_k}`, and the tactic
- produces a goal which states that :math:`c` is not zero.
+ * `parameters` is the list of variables :math:`X_{i_1},\ldots,X_{i_k}` among
+ :math:`X_1,\ldots,X_n` which are considered as parameters: computation will be performed with
+ rational fractions in these variables, i.e. polynomials are considered
+ with coefficients in :math:`R(X_{i_1},\ldots,X_{i_k})`. In this case, the coefficient
+ :math:`c` can be a non constant polynomial in :math:`X_{i_1},\ldots,X_{i_k}`, and the tactic
+ produces a goal which states that :math:`c` is not zero.
-* `variables` is the list of the variables in the decreasing order in
- which they will be used in Buchberger algorithm. If `variables` = `(@nil R)`,
- then `lvar` is replaced by all the variables which are not in
- `parameters`.
+ * `variables` is the list of the variables in the decreasing order in
+ which they will be used in the Buchberger algorithm. If `variables` = `(@nil R)`,
+ then `lvar` is replaced by all the variables which are not in
+ `parameters`.
-See file `Nsatz.v` for many examples, especially in geometry.
+See the file `Nsatz.v` for many examples, especially in geometry.
diff --git a/doc/sphinx/addendum/omega.rst b/doc/sphinx/addendum/omega.rst
index 80ce016200..1e92d01125 100644
--- a/doc/sphinx/addendum/omega.rst
+++ b/doc/sphinx/addendum/omega.rst
@@ -8,23 +8,20 @@ Omega: a solver for quantifier-free problems in Presburger Arithmetic
Description of ``omega``
------------------------
-This tactic does not need any parameter:
-
.. tacn:: omega
-:tacn:`omega` solves a goal in Presburger arithmetic, i.e. a universally
-quantified formula made of equations and inequations. Equations may
-be specified either on the type ``nat`` of natural numbers or on
-the type ``Z`` of binary-encoded integer numbers. Formulas on
-``nat`` are automatically injected into ``Z``. The procedure
-may use any hypothesis of the current proof session to solve the goal.
+ :tacn:`omega` is a tactic for solving goals in Presburger arithmetic,
+ i.e. for proving formulas made of equations and inequalities over the
+ type ``nat`` of natural numbers or the type ``Z`` of binary-encoded integers.
+ Formulas on ``nat`` are automatically injected into ``Z``. The procedure
+ may use any hypothesis of the current proof session to solve the goal.
-Multiplication is handled by :tacn:`omega` but only goals where at
-least one of the two multiplicands of products is a constant are
-solvable. This is the restriction meant by "Presburger arithmetic".
+ Multiplication is handled by :tacn:`omega` but only goals where at
+ least one of the two multiplicands of products is a constant are
+ solvable. This is the restriction meant by "Presburger arithmetic".
-If the tactic cannot solve the goal, it fails with an error message.
-In any case, the computation eventually stops.
+ If the tactic cannot solve the goal, it fails with an error message.
+ In any case, the computation eventually stops.
.. tacv:: romega
:name: romega
@@ -34,8 +31,7 @@ In any case, the computation eventually stops.
Arithmetical goals recognized by ``omega``
------------------------------------------
-:tacn:`omega` applied only to quantifier-free formulas built from the
-connectors::
+:tacn:`omega` applies only to quantifier-free formulas built from the connectives::
/\ \/ ~ ->
@@ -67,8 +63,8 @@ is generated:
universally quantified, try :tacn:`intros` first; if it contains
existentials quantifiers too, :tacn:`omega` is not strong enough to solve your
goal). This may happen also if your goal contains arithmetical
- operators unknown from :tacn:`omega`. Finally, your goal may be really
- wrong!
+ operators not recognized by :tacn:`omega`. Finally, your goal may be simply
+ not true!
.. exn:: omega: Not a quantifier-free goal.
@@ -144,12 +140,12 @@ Technical data
Overview of the tactic
~~~~~~~~~~~~~~~~~~~~~~
- * The goal is negated twice and the first negation is introduced as an hypothesis.
- * Hypothesis are decomposed in simple equations or inequations. Multiple
+ * The goal is negated twice and the first negation is introduced as a hypothesis.
+ * Hypotheses are decomposed in simple equations or inequalities. Multiple
goals may result from this phase.
- * Equations and inequations over ``nat`` are translated over
- ``Z``, multiple goals may result from the translation of substraction.
- * Equations and inequations are normalized.
+ * Equations and inequalities over ``nat`` are translated over
+ ``Z``, multiple goals may result from the translation of subtraction.
+ * Equations and inequalities are normalized.
* Goals are solved by the OMEGA decision procedure.
* The script of the solution is replayed.
@@ -158,26 +154,25 @@ Overview of the OMEGA decision procedure
The OMEGA decision procedure involved in the :tacn:`omega` tactic uses
a small subset of the decision procedure presented in :cite:`TheOmegaPaper`
-Here is an overview, look at the original paper for more information.
+Here is an overview, refer to the original paper for more information.
- * Equations and inequations are normalized by division by the GCD of their
+ * Equations and inequalities are normalized by division by the GCD of their
coefficients.
* Equations are eliminated, using the Banerjee test to get a coefficient
equal to one.
- * Note that each inequation defines a half space in the space of real value
- of the variables.
- * Inequations are solved by projecting on the hyperspace
- defined by cancelling one of the variable. They are partitioned
+ * Note that each inequality cuts the Euclidean space in half.
+ * Inequalities are solved by projecting on the hyperspace
+ defined by cancelling one of the variables. They are partitioned
according to the sign of the coefficient of the eliminated
- variable. Pairs of inequations from different classes define a
+ variable. Pairs of inequalities from different classes define a
new edge in the projection.
- * Redundant inequations are eliminated or merged in new
+ * Redundant inequalities are eliminated or merged in new
equations that can be eliminated by the Banerjee test.
* The last two steps are iterated until a contradiction is reached
(success) or there is no more variable to eliminate (failure).
It may happen that there is a real solution and no integer one. The last
-steps of the Omega procedure (dark shadow) are not implemented, so the
+steps of the Omega procedure are not implemented, so the
decision procedure is only partial.
Bugs
diff --git a/doc/sphinx/addendum/parallel-proof-processing.rst b/doc/sphinx/addendum/parallel-proof-processing.rst
index edb8676a5b..8ee8f52227 100644
--- a/doc/sphinx/addendum/parallel-proof-processing.rst
+++ b/doc/sphinx/addendum/parallel-proof-processing.rst
@@ -68,7 +68,7 @@ to modify the proof script accordingly.
Proof blocks and error resilience
--------------------------------------
-|Coq| 8.6 introduced a mechanism for error resiliency: in interactive
+|Coq| 8.6 introduced a mechanism for error resilience: in interactive
mode |Coq| is able to completely check a document containing errors
instead of bailing out at the first failure.
@@ -92,14 +92,14 @@ Caveats
````````
When a vernacular command fails the subsequent error messages may be
-bogus, i.e. caused by the first error. Error resiliency for vernacular
+bogus, i.e. caused by the first error. Error resilience for vernacular
commands can be switched off by passing ``-async-proofs-command-error-resilience off``
to |CoqIDE|.
An incorrect proof block detection can result into an incorrect error
recovery and hence in bogus errors. Proof block detection cannot be
precise for bullets or any other non well parenthesized proof
-structure. Error resiliency can be turned off or selectively activated
+structure. Error resilience can be turned off or selectively activated
for any set of block kind passing to |CoqIDE| one of the following
options:
@@ -127,13 +127,14 @@ the very same button, that can also be used to see the list of errors
and jump to the corresponding line.
If a proof is processed asynchronously the corresponding Qed command
-is colored using a lighter color that usual. This signals that the
+is colored using a lighter color than usual. This signals that the
proof has been delegated to a worker process (or will be processed
lazily if the ``-async-proofs lazy`` option is used). Once finished, the
worker process will provide the proof object, but this will not be
automatically checked by the kernel of the main process. To force the
kernel to check all the proof objects, one has to click the button
-with the gears. Only then are all the universe constraints checked.
+with the gears (Fully check the document) on the top bar.
+Only then all the universe constraints are checked.
Caveats
```````
@@ -149,7 +150,7 @@ To disable this feature, one can pass the ``-async-proofs off`` flag to
default, pass the ``-async-proofs on`` flag to enable it.
Proofs that are known to take little time to process are not delegated
-to a worker process. The threshold can be configure with
+to a worker process. The threshold can be configured with
``-async-proofs-delegation-threshold``. Default is 0.03 seconds.
Batch mode
@@ -157,7 +158,7 @@ Batch mode
When |Coq| is used as a batch compiler by running `coqc` or `coqtop`
-compile, it produces a `.vo` file for each `.v` file. A `.vo` file contains,
-among other things, theorems statements and proofs. Hence to produce a
+among other things, theorem statements and proofs. Hence to produce a
.vo |Coq| need to process all the proofs of the `.v` file.
The asynchronous processing of proofs can decouple the generation of a
@@ -225,5 +226,5 @@ in all the shells from which |Coq| processes will be started. If one
uses just one terminal running the bash shell, then
``export ‘coqworkmgr -j 4‘`` will do the job.
-After that, all |Coq| processes, e.g. `coqide` and `coqc`, will honor the
+After that, all |Coq| processes, e.g. `coqide` and `coqc`, will respect the
limit, globally.
diff --git a/doc/sphinx/addendum/program.rst b/doc/sphinx/addendum/program.rst
index b685e68e43..d6895f5fe5 100644
--- a/doc/sphinx/addendum/program.rst
+++ b/doc/sphinx/addendum/program.rst
@@ -18,7 +18,7 @@ program as in a regular functional programming language whilst using
as rich a specification as desired and proving that the code meets the
specification using the whole |Coq| proof apparatus. This is done using
a technique originating from the “Predicate subtyping” mechanism of
-PVS :cite:`Rushby98`, which generates type-checking conditions while typing a
+PVS :cite:`Rushby98`, which generates type checking conditions while typing a
term constrained to a particular type. Here we insert existential
variables in the term, which must be filled with proofs to get a
complete |Coq| term. |Program| replaces the |Program| tactic by Catherine
@@ -38,12 +38,12 @@ obligations which need to be resolved to create the final term.
Elaborating programs
---------------------
-The main difference from |Coq| is that an object in a type T : Set can
-be considered as an object of type { x : T | P} for any wellformed P :
-Prop. If we go from T to the subset of T verifying property P, we must
-prove that the object under consideration verifies it. Russell will
-generate an obligation for every such coercion. In the other
-direction, Russell will automatically insert a projection.
+The main difference from |Coq| is that an object in a type :g:`T : Set` can
+be considered as an object of type :g:`{x : T | P}` for any well-formed
+:g:`P : Prop`. If we go from :g:`T` to the subset of :g:`T` verifying property
+:g:`P`, we must prove that the object under consideration verifies it. Russell
+will generate an obligation for every such coercion. In the other direction,
+Russell will automatically insert a projection.
Another distinction is the treatment of pattern-matching. Apart from
the following differences, it is equivalent to the standard match
@@ -67,15 +67,15 @@ operation (see :ref:`extendedpatternmatching`).
(match x as y return (x = y -> _) with
| 0 => fun H : x = 0 -> t
| S n => fun H : x = S n -> u
- end) (eq_refl n).
+ end) (eq_refl x).
This permits to get the proper equalities in the context of proof
obligations inside clauses, without which reasoning is very limited.
-+ Generation of inequalities. If a pattern intersects with a previous
- one, an inequality is added in the context of the second branch. See
++ Generation of disequalities. If a pattern intersects with a previous
+ one, a disequality is added in the context of the second branch. See
for example the definition of div2 below, where the second branch is
- typed in a context where ∀ p, _ <> S (S p).
+ typed in a context where :g:`∀ p, _ <> S (S p)`.
+ Coercion. If the object being matched is coercible to an inductive
type, the corresponding coercion will be automatically inserted. This
also works with the previous mechanism.
@@ -87,8 +87,8 @@ coercions.
.. opt:: Program Cases
This controls the special treatment of pattern-matching generating equalities
- and inequalities when using |Program| (it is on by default). All
- pattern-matchings and let-patterns are handled using the standard algorithm
+ and disequalities when using |Program| (it is on by default). All
+ pattern-matches and let-patterns are handled using the standard algorithm
of |Coq| (see :ref:`extendedpatternmatching`) when this option is
deactivated.
@@ -104,13 +104,13 @@ Syntactic control over equalities
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To give more control over the generation of equalities, the
-typechecker will fall back directly to |Coq|’s usual typing of dependent
+type checker will fall back directly to |Coq|’s usual typing of dependent
pattern-matching if a return or in clause is specified. Likewise, the
if construct is not treated specially by |Program| so boolean tests in
the code are not automatically reflected in the obligations. One can
-use the dec combinator to get the correct hypotheses as in:
+use the :g:`dec` combinator to get the correct hypotheses as in:
-.. coqtop:: none
+.. coqtop:: in
Require Import Program Arith.
@@ -120,7 +120,7 @@ use the dec combinator to get the correct hypotheses as in:
if dec (leb n 0) then 0
else S (pred n).
-The let tupling construct :g:`let (x1, ..., xn) := t in b` does not
+The :g:`let` tupling construct :g:`let (x1, ..., xn) := t in b` does not
produce an equality, contrary to the let pattern construct :g:`let ’(x1,
..., xn) := t in b`. Also, :g:`term :>` explicitly asks the system to
coerce term to its support type. It can be useful in notations, for
@@ -175,7 +175,7 @@ Program Definition
.. TODO refer to production in alias
-See also: Sections :ref:`vernac-controlling-the-reduction-strategies`, :tacn:`unfold`
+.. seealso:: Sections :ref:`vernac-controlling-the-reduction-strategies`, :tacn:`unfold`
.. _program_fixpoint:
@@ -200,7 +200,7 @@ The structural fixpoint operator behaves just like the one of |Coq| (see
:cmd:`Fixpoint`), except it may also generate obligations. It works
with mutually recursive definitions too.
-.. coqtop:: reset none
+.. coqtop:: reset in
Require Import Program Arith.
@@ -264,7 +264,7 @@ Program Lemma
Definition` and use it as the goal afterwards. Otherwise the proof
will be started with the elaborated version as a goal. The
:g:`Program` prefix can similarly be used as a prefix for
- :g:`Variable`, :g:`Hypothesis`, :g:`Axiom` etc...
+ :g:`Variable`, :g:`Hypothesis`, :g:`Axiom` etc.
.. _solving_obligations:
@@ -300,7 +300,7 @@ optional tactic is replaced by the default one if not specified.
Start the proof of the next unsolved obligation.
-.. cmd:: Solve Obligations {? of @ident} {? with @tactic}
+.. cmd:: Solve Obligations {? {? of @ident} with @tactic}
Tries to solve each obligation of ``ident`` using the given ``tactic`` or the default one.
@@ -322,13 +322,13 @@ optional tactic is replaced by the default one if not specified.
.. opt:: Transparent Obligations
- Control whether all obligations should be declared as transparent
+ Controls whether all obligations should be declared as transparent
(the default), or if the system should infer which obligations can be
declared opaque.
.. opt:: Hide Obligations
- Control whether obligations appearing in the
+ Controls whether obligations appearing in the
term should be hidden as implicit arguments of the special
constantProgram.Tactics.obligation.
diff --git a/doc/sphinx/addendum/ring.rst b/doc/sphinx/addendum/ring.rst
index 6a9b343ba8..8cb86e2267 100644
--- a/doc/sphinx/addendum/ring.rst
+++ b/doc/sphinx/addendum/ring.rst
@@ -13,13 +13,13 @@ The ring and field tactic families
:Author: Bruno Barras, Benjamin Grégoire, Assia Mahboubi, Laurent Théry [#f1]_
-This chapter presents the tactics dedicated to deal with ring and
+This chapter presents the tactics dedicated to dealing with ring and
field equations.
What does this tactic do?
------------------------------
-``ring`` does associative-commutative rewriting in ring and semi-ring
+``ring`` does associative-commutative rewriting in ring and semiring
structures. Assume you have two binary functions :math:`\oplus` and
:math:`\otimes` that are associative and commutative, with :math:`\oplus`
distributive on :math:`\otimes`, and two constants 0 and 1 that are unities for
@@ -36,8 +36,8 @@ is strictly less than the following monomial according to the lexicographic
order. It is an easy theorem to show that every polynomial is equivalent (modulo
the ring properties) to exactly one canonical sum. This canonical sum is called
the normal form of the polynomial. In fact, the actual representation shares
-monomials with same prefixes. So what does ring? It normalizes polynomials over
-any ring or semi-ring structure. The basic use of ``ring`` is to simplify ring
+monomials with same prefixes. So what does the ``ring`` tactic do? It normalizes polynomials over
+any ring or semiring structure. The basic use of ``ring`` is to simplify ring
expressions, so that the user does not have to deal manually with the theorems
of associativity and commutativity.
@@ -59,9 +59,8 @@ The variables map
It is frequent to have an expression built with :math:`+` and :math:`\times`,
but rarely on variables only. Let us associate a number to each subterm of a
-ring expression in the Gallina language. For example in the ring |nat|, consider
-the expression:
-
+ring expression in the Gallina language. For example, consider this expression
+in the semiring ``nat``:
::
@@ -104,7 +103,7 @@ Concrete usage in Coq
.. tacn:: ring
The ``ring`` tactic solves equations upon polynomial expressions of a ring
-(or semi-ring) structure. It proceeds by normalizing both hand sides
+(or semiring) structure. It proceeds by normalizing both sides
of the equation (w.r.t. associativity, commutativity and
distributivity, constant propagation, rewriting of monomials) and
comparing syntactically the results.
@@ -112,9 +111,9 @@ comparing syntactically the results.
.. tacn:: ring_simplify
``ring_simplify`` applies the normalization procedure described above to
-the terms given. The tactic then replaces all occurrences of the terms
+the given terms. The tactic then replaces all occurrences of the terms
given in the conclusion of the goal by their normal forms. If no term
-is given, then the conclusion should be an equation and both hand
+is given, then the conclusion should be an equation and both
sides are normalized. The tactic can also be applied in a hypothesis.
The tactic must be loaded by ``Require Import Ring``. The ring structures
@@ -187,7 +186,7 @@ Error messages:
.. exn:: Cannot find a declared ring structure for equality @term.
- Same as above is the case of the ``ring`` tactic.
+ Same as above in the case of the ``ring`` tactic.
Adding a ring structure
@@ -198,8 +197,8 @@ carrier set, an equality, and ring operations: ``Ring_theory.ring_theory``
and ``Ring_theory.semi_ring_theory``) satisfies the ring axioms. Semi-
rings (rings without + inverse) are also supported. The equality can
be either Leibniz equality, or any relation declared as a setoid (see
-:ref:`tactics-enabled-on-user-provided-relations`). The definition of ring and semi-rings (see module
-``Ring_theory``) is:
+:ref:`tactics-enabled-on-user-provided-relations`).
+The definitions of ring and semiring (see module ``Ring_theory``) are:
.. coqtop:: in
@@ -265,13 +264,13 @@ are the implementations of the ring operations, ``==`` is the equality of
the coefficients, ``?+!`` is an implementation of this equality, and ``[x]``
is a notation for the image of ``x`` by the ring morphism.
-Since |Z| is an initial ring (and |N| is an initial semi-ring), it can
+Since |Z| is an initial ring (and |N| is an initial semiring), it can
always be considered as a set of coefficients. There are basically
three kinds of (semi-)rings:
abstract rings
to be used when operations are not effective. The set
- of coefficients is |Z| (or |N| for semi-rings).
+ of coefficients is |Z| (or |N| for semirings).
computational rings
to be used when operations are effective. The
@@ -305,7 +304,7 @@ The syntax for adding a new ring is
.. cmd:: Add Ring @ident : @term {? ( @ring_mod {* , @ring_mod } )}
-The :n:`@ident` is not relevant. It is just used for error messages. The
+The :n:`@ident` is not relevant. It is used just for error messages. The
:n:`@term` is a proof that the ring signature satisfies the (semi-)ring
axioms. The optional list of modifiers is used to tailor the behavior
of the tactic. The following list describes their syntax and effects:
@@ -386,7 +385,7 @@ sign :n:`@term`
div :n:`@term`
allows ``ring`` and ``ring_simplify`` to use monomials with
- coefficient other than 1 in the rewriting. The term :n:`@term` is a proof
+ coefficients other than 1 in the rewriting. The term :n:`@term` is a proof
that a given division function satisfies the specification of an
euclidean division function (:n:`@term` has to be a proof of
``Ring_theory.div_theory``). For example, this function is called when
@@ -414,13 +413,13 @@ Error messages:
How does it work?
----------------------
-The code of ring is a good example of tactic written using *reflection*.
-What is reflection? Basically, it is writing |Coq| tactics in |Coq|, rather
-than in |OCaml|. From the philosophical point of view, it is
-using the ability of the Calculus of Constructions to speak and reason
-about itself. For the ring tactic we used Coq as a programming
-language and also as a proof environment to build a tactic and to
-prove it correctness.
+The code of ``ring`` is a good example of a tactic written using *reflection*.
+What is reflection? Basically, using it means that a part of a tactic is written
+in Gallina, Coq's language of terms, rather than |Ltac| or |OCaml|. From the
+philosophical point of view, reflection is using the ability of the Calculus of
+Constructions to speak and reason about itself. For the ``ring`` tactic we used
+Coq as a programming language and also as a proof environment to build a tactic
+and to prove its correctness.
The interested reader is strongly advised to have a look at the
file ``Ring_polynom.v``. Here a type for polynomials is defined:
@@ -452,7 +451,7 @@ Polynomials in normal form are defined as:
where ``Pinj n P`` denotes ``P`` in which :math:`V_i` is replaced by :math:`V_{i+n}` ,
and ``PX P n Q`` denotes :math:`P \otimes V_1^n \oplus Q'`, `Q'` being `Q` where :math:`V_i` is replaced by :math:`V_{i+1}`.
-Variables maps are represented by list of ring elements, and two
+Variable maps are represented by lists of ring elements, and two
interpretation functions, one that maps a variables map and a
polynomial to an element of the concrete ring, and the second one that
does the same for normal forms:
@@ -490,26 +489,26 @@ concrete expression `p’`, which is the concrete normal form of `p`. This is su
`p’` |la| |le|
========= ====== ====
-The user do not see the right part of the diagram. From outside, the
-tactic behaves like a |bdi| simplification extended with AC rewriting
-rules. Basically, the proof is only the application of the main
-correctness theorem to well-chosen arguments.
+The user does not see the right part of the diagram. From outside, the
+tactic behaves like a |bdi| simplification extended with rewriting rules
+for associativity and commutativity. Basically, the proof is only the
+application of the main correctness theorem to well-chosen arguments.
Dealing with fields
------------------------
.. tacn:: field
-The ``field`` tactic is an extension of the ``ring`` to deal with rational
-expression. Given a rational expression :math:`F = 0`. It first reduces the
+The ``field`` tactic is an extension of the ``ring`` tactic that deals with rational
+expressions. Given a rational expression :math:`F = 0`. It first reduces the
expression `F` to a common denominator :math:`N/D = 0` where `N` and `D`
are two ring expressions. For example, if we take :math:`F = (1 − 1/x) x − x + 1`, this
gives :math:`N = (x − 1) x − x^2 + x` and :math:`D = x`. It then calls ring to solve
:math:`N = 0`.
-Note that ``field`` also generates non-zero conditions for all the
+Note that ``field`` also generates nonzero conditions for all the
denominators it encounters in the reduction. In our example, it
generates the condition :math:`x \neq 0`. These conditions appear as one subgoal
-which is a conjunction if there are several denominators. Non-zero
+which is a conjunction if there are several denominators. Nonzero
conditions are always polynomial expressions. For example when
reducing the expression :math:`1/(1 + 1/x)`, two side conditions are
generated: :math:`x \neq 0` and :math:`x + 1 \neq 0`. Factorized expressions are broken since
@@ -523,7 +522,7 @@ structures can be declared to the system with the ``Add Field`` command
(in ``plugins/setoid_ring``). It is exported by module ``Rbase``, so
that requiring ``Rbase`` or ``Reals`` is enough to use the field tactics on
real numbers. Rational numbers in canonical form are also declared as
-a field in module ``Qcanon``.
+a field in the module ``Qcanon``.
.. example::
@@ -559,8 +558,8 @@ a field in module ``Qcanon``.
performs the simplification in the conclusion of the
goal, :math:`F_1 = F_2` becomes :math:`N_1 / D_1 = N_2 / D_2`. A normalization step
(the same as the one for rings) is then applied to :math:`N_1`, :math:`D_1`,
- :math:`N_2` and :math:`D_2`. This way, polynomials remain in factorized form during the
- fraction simplifications. This yields smaller expressions when
+ :math:`N_2` and :math:`D_2`. This way, polynomials remain in factorized form during
+ fraction simplification. This yields smaller expressions when
reducing to the same denominator since common factors can be canceled.
.. tacv:: field_simplify [{* @term }]
@@ -617,7 +616,7 @@ carrier set, an equality, and field operations:
satisfies the field axioms. Semi-fields (fields without + inverse) are
also supported. The equality can be either Leibniz equality, or any
relation declared as a setoid (see :ref:`tactics-enabled-on-user-provided-relations`). The definition of
-fields and semi-fields is:
+fields and semifields is:
.. coqtop:: in
@@ -657,7 +656,7 @@ The syntax for adding a new field is
.. cmd:: Add Field @ident : @term {? ( @field_mod {* , @field_mod } )}
-The :n:`@ident` is not relevant. It is just used for error
+The :n:`@ident` is not relevant. It is used just for error
messages. :n:`@term` is a proof that the field signature satisfies the
(semi-)field axioms. The optional list of modifiers is used to tailor
the behavior of the tactic.
@@ -671,7 +670,7 @@ specific modifier:
completeness :n:`@term`
allows the field tactic to prove automatically
- that the image of non-zero coefficients are mapped to non-zero
+ that the image of nonzero coefficients are mapped to nonzero
elements of the field. :n:`@term` is a proof of
``forall x y, [x] == [y] -> x ?=! y = true``,
@@ -685,7 +684,7 @@ History of ring
First Samuel Boutin designed the tactic ``ACDSimpl``. This tactic did lot
of rewriting. But the proofs terms generated by rewriting were too big
-for |Coq|’s type-checker. Let us see why:
+for |Coq|’s type checker. Let us see why:
.. coqtop:: all
@@ -704,12 +703,11 @@ it using reflection (see :cite:`Bou97`). Later, it
was rewritten by Patrick Loiseleur: the new tactic does not any
more require ``ACDSimpl`` to compile and it makes use of |bdi|-reduction not
only to replace the rewriting steps, but also to achieve the
-interleaving of computation and reasoning (see :ref:`discussion_reflection`). He also wrote a
-few |ML| code for the ``Add Ring`` command, that allow to register new rings
-dynamically.
+interleaving of computation and reasoning (see :ref:`discussion_reflection`). He also wrote
+some |ML| code for the ``Add Ring`` command that allows registering new rings dynamically.
Proofs terms generated by ring are quite small, they are linear in the
-number of :math:`\oplus` and :math:`\otimes` operations in the normalized terms. Type-checking
+number of :math:`\oplus` and :math:`\otimes` operations in the normalized terms. Type checking
those terms requires some time because it makes a large use of the
conversion rule, but memory requirements are much smaller.
@@ -733,15 +731,15 @@ Then it is rewritten to ``34 − x + 2 * x + 12``, very far from the expected re
Here rewriting is not sufficient: you have to do some kind of reduction
(some kind of computation) to achieve the normalization.
-The tactic ``ring`` is not only faster than a classical one: using
-reflection, we get for free integration of computation and reasoning
-that would be very complex to implement in the classic fashion.
+The tactic ``ring`` is not only faster than the old one: by using
+reflection, we get for free the integration of computation and reasoning
+that would be very difficult to implement without it.
Is it the ultimate way to write tactics? The answer is: yes and no.
-The ``ring`` tactic uses intensively the conversion rule of |Cic|, that is
-replaces proof by computation the most as it is possible. It can be
-useful in all situations where a classical tactic generates huge proof
-terms. Symbolic Processing and Tautologies are in that case. But there
+The ``ring`` tactic intensively uses the conversion rules of the Calculus of
+Inductive Constructions, i.e. it replaces proofs by computations as much as possible.
+It can be useful in all situations where a classical tactic generates huge proof
+terms, like symbolic processing and tautologies. But there
are also tactics like ``auto`` or ``linear`` that do many complex computations,
using side-effects and backtracking, and generate a small proof term.
Clearly, it would be significantly less efficient to replace them by
@@ -750,12 +748,12 @@ tactics using reflection.
Another idea suggested by Benjamin Werner: reflection could be used to
couple an external tool (a rewriting program or a model checker)
with |Coq|. We define (in |Coq|) a type of terms, a type of *traces*, and
-prove a correction theorem that states that *replaying traces* is safe
-w.r.t some interpretation. Then we let the external tool do every
+prove a correctness theorem that states that *replaying traces* is safe
+with respect to some interpretation. Then we let the external tool do every
computation (using side-effects, backtracking, exception, or others
features that are not available in pure lambda calculus) to produce
-the trace: now we can check in |Coq| that the trace has the expected
-semantic by applying the correction lemma.
+the trace. Now we can check in |Coq| that the trace has the expected
+semantics by applying the correctness theorem.
diff --git a/doc/sphinx/addendum/type-classes.rst b/doc/sphinx/addendum/type-classes.rst
index 6c7258f9c5..ab4b4a9824 100644
--- a/doc/sphinx/addendum/type-classes.rst
+++ b/doc/sphinx/addendum/type-classes.rst
@@ -6,7 +6,7 @@ Type Classes
============
This chapter presents a quick reference of the commands related to type
-classes. For an actual introduction to type classes, there is a
+classes. For an actual introduction to typeclasses, there is a
description of the system :cite:`sozeau08` and the literature on type
classes in Haskell which also applies.
@@ -76,7 +76,7 @@ for dealing with obligations.
Binding classes
---------------
-Once a type class is declared, one can use it in class binders:
+Once a typeclass is declared, one can use it in class binders:
.. coqtop:: all
@@ -92,7 +92,7 @@ found, an error is raised:
Fail Definition neqb' (A : Type) (x y : A) := negb (eqb x y).
-The algorithm used to solve constraints is a variant of the eauto
+The algorithm used to solve constraints is a variant of the :tacn:`eauto`
tactic that does proof search with a set of lemmas (the instances). It
will use local hypotheses as well as declared lemmas in
the ``typeclass_instances`` database. Hence the example can also be
@@ -103,13 +103,13 @@ written:
Definition neqb' A (eqa : EqDec A) (x y : A) := negb (eqb x y).
However, the generalizing binders should be used instead as they have
-particular support for type classes:
+particular support for typeclasses:
-+ They automatically set the maximally implicit status for type class
++ They automatically set the maximally implicit status for typeclass
arguments, making derived functions as easy to use as class methods.
In the example above, ``A`` and ``eqa`` should be set maximally implicit.
+ They support implicit quantification on partially applied type
- classes (:ref:`implicit-generalization`). Any argument not given as part of a type class
+ classes (:ref:`implicit-generalization`). Any argument not given as part of a typeclass
binder will be automatically generalized.
+ They also support implicit quantification on :ref:`superclasses`.
@@ -120,7 +120,7 @@ Following the previous example, one can write:
Generalizable Variables A B C.
- Definition neqb_impl `{eqa : EqDec A} (x y : A) := negb (eqb x y).
+ Definition neqb_implicit `{eqa : EqDec A} (x y : A) := negb (eqb x y).
Here ``A`` is implicitly generalized, and the resulting function is
equivalent to the one above.
@@ -148,7 +148,7 @@ database.
Sections and contexts
---------------------
-To ease the parametrization of developments by type classes, we provide a new
+To ease the parametrization of developments by typeclasses, we provide a new
way to introduce variables into section contexts, compatible with the implicit
argument mechanism. The new command works similarly to the :cmd:`Variables`
vernacular, except it accepts any binding context as argument. For example:
@@ -193,7 +193,7 @@ superclasses as a binding context:
Class Ord `(E : EqDec A) := { le : A -> A -> bool }.
Contrary to Haskell, we have no special syntax for superclasses, but
-this declaration is morally equivalent to:
+this declaration is equivalent to:
::
@@ -248,7 +248,7 @@ properties, e.g.:
This declares singleton classes for reflexive and transitive relations,
(see the :ref:`singleton class <singleton-class>` variant for an
-explanation). These may be used as part of other classes:
+explanation). These may be used as parts of other classes:
.. coqtop:: all
@@ -271,7 +271,7 @@ Summary of the commands
.. cmd:: Class @ident {? @binders} : {? @sort} := {? @ident} { {+; @ident :{? >} @term } }
- The :cmd:`Class` command is used to declare a type class with parameters
+ The :cmd:`Class` command is used to declare a typeclass with parameters
``binders`` and fields the declared record fields.
Variants:
@@ -296,9 +296,13 @@ Variants:
This variant declares a class a posteriori from a constant or
inductive definition. No methods or instances are defined.
+ .. warn:: @ident is already declared as a typeclass
+
+ This command has no effect when used on a typeclass.
+
.. cmd:: Instance @ident {? @binders} : Class t1 … tn [| priority] := { field1 := b1 ; …; fieldi := bi }
-The :cmd:`Instance` command is used to declare a type class instance named
+The :cmd:`Instance` command is used to declare a typeclass instance named
``ident`` of the class :cmd:`Class` with parameters ``t1`` to ``tn`` and
fields ``b1`` to ``bi``, where each field must be a declared field of
the class. Missing fields must be filled in interactive proof mode.
@@ -306,7 +310,7 @@ the class. Missing fields must be filled in interactive proof mode.
An arbitrary context of ``binders`` can be put after the name of the
instance and before the colon to declare a parameterized instance. An
optional priority can be declared, 0 being the highest priority as for
-auto hints. If the priority is not specified, it defaults to the number
+:tacn:`auto` hints. If the priority is not specified, it defaults to the number
of non-dependent binders of the instance.
.. cmdv:: Instance @ident {? @binders} : forall {? @binders}, Class t1 … tn [| priority] := @term
@@ -325,7 +329,7 @@ of non-dependent binders of the instance.
.. cmdv:: Program Instance
:name: Program Instance
- Switches the type-checking to Program (chapter :ref:`programs`) and
+ Switches the type checking to Program (chapter :ref:`programs`) and
uses the obligation mechanism to manage missing fields.
.. cmdv:: Declare Instance
@@ -338,12 +342,12 @@ of non-dependent binders of the instance.
Besides the :cmd:`Class` and :cmd:`Instance` vernacular commands, there are a
-few other commands related to type classes.
+few other commands related to typeclasses.
.. cmd:: Existing Instance {+ @ident} [| priority]
- This commands adds an arbitrary list of constants whose type ends with
- an applied type class to the instance database with an optional
+ This command adds an arbitrary list of constants whose type ends with
+ an applied typeclass to the instance database with an optional
priority. It can be used for redeclaring instances at the end of
sections, or declaring structure projections as instances. This is
equivalent to ``Hint Resolve ident : typeclass_instances``, except it
@@ -363,11 +367,11 @@ few other commands related to type classes.
+ Contrary to :tacn:`eauto` and :tacn:`auto`, the resolution is done entirely in
the new proof engine (as of Coq 8.6), meaning that backtracking is
available among dependent subgoals, and shelving goals is supported.
- typeclasses eauto is a multi-goal tactic. It analyses the dependencies
+ ``typeclasses eauto`` is a multi-goal tactic. It analyses the dependencies
between subgoals to avoid backtracking on subgoals that are entirely
independent.
- + When called with no arguments, typeclasses eauto uses
+ + When called with no arguments, ``typeclasses eauto`` uses
the ``typeclass_instances`` database by default (instead of core).
Dependent subgoals are automatically shelved, and shelved goals can
remain after resolution ends (following the behavior of Coq 8.5).
@@ -375,22 +379,22 @@ few other commands related to type classes.
.. note::
As of Coq 8.6, ``all:once (typeclasses eauto)`` faithfully
mimicks what happens during typeclass resolution when it is called
- during refinement/type-inference, except that *only* declared class
+ during refinement/type inference, except that *only* declared class
subgoals are considered at the start of resolution during type
inference, while ``all`` can select non-class subgoals as well. It might
move to ``all:typeclasses eauto`` in future versions when the
refinement engine will be able to backtrack.
- + When called with specific databases (e.g. with), typeclasses eauto
+ + When called with specific databases (e.g. with), ``typeclasses eauto``
allows shelved goals to remain at any point during search and treat
- typeclasses goals like any other.
+ typeclass goals like any other.
+ The transparency information of databases is used consistently for
all hints declared in them. It is always used when calling the
- unifier. When considering the local hypotheses, we use the transparent
+ unifier. When considering local hypotheses, we use the transparent
state of the first hint database given. Using an empty database
(created with :cmd:`Create HintDb` for example) with unfoldable variables and
- constants as the first argument of typeclasses eauto hence makes
+ constants as the first argument of ``typeclasses eauto`` hence makes
resolution with the local hypotheses use full conversion during
unification.
@@ -399,10 +403,10 @@ few other commands related to type classes.
.. warning::
The semantics for the limit :n:`@num`
- is different than for auto. By default, if no limit is given the
- search is unbounded. Contrary to auto, introduction steps (intro) are
+ is different than for auto. By default, if no limit is given, the
+ search is unbounded. Contrary to :tacn:`auto`, introduction steps are
counted, which might result in larger limits being necessary when
- searching with typeclasses eauto than auto.
+ searching with ``typeclasses eauto`` than with :tacn:`auto`.
.. cmdv:: typeclasses eauto with {+ @ident}
@@ -413,11 +417,11 @@ few other commands related to type classes.
.. tacn:: autoapply @term with @ident
:name: autoapply
- The tactic autoapply applies a term using the transparency information
+ The tactic ``autoapply`` applies a term using the transparency information
of the hint database ident, and does *no* typeclass resolution. This can
be used in :cmd:`Hint Extern`’s for typeclass instances (in the hint
database ``typeclass_instances``) to allow backtracking on the typeclass
- subgoals created by the lemma application, rather than doing type class
+ subgoals created by the lemma application, rather than doing typeclass
resolution locally at the hint application time.
.. _TypeclassesTransparent:
@@ -427,7 +431,7 @@ Typeclasses Transparent, Typclasses Opaque
.. cmd:: Typeclasses Transparent {+ @ident}
- This command defines makes the identifiers transparent during type class
+ This command makes the identifiers transparent during typeclass
resolution.
.. cmd:: Typeclasses Opaque {+ @ident}
@@ -457,8 +461,8 @@ Options
.. opt:: Typeclasses Dependency Order
This option (on by default since 8.6) respects the dependency order
- between subgoals, meaning that subgoals which are depended on by other
- subgoals come first, while the non-dependent subgoals were put before
+ between subgoals, meaning that subgoals on which other subgoals depend
+ come first, while the non-dependent subgoals were put before
the dependent ones previously (Coq 8.5 and below). This can result in
quite different performance behaviors of proof search.
@@ -483,16 +487,18 @@ Options
avoiding (functional) eta-expansions in the generated proof term. It
does so by allowing hints that conclude in a product to apply to a
goal with a matching product directly, avoiding an introduction.
- *Warning:* this can be expensive as it requires rebuilding hint
- clauses dynamically, and does not benefit from the invertibility
- status of the product introduction rule, resulting in potentially more
- expensive proof-search (i.e. more useless backtracking).
+ .. warning::
+
+ This can be expensive as it requires rebuilding hint
+ clauses dynamically, and does not benefit from the invertibility
+ status of the product introduction rule, resulting in potentially more
+ expensive proof-search (i.e. more useless backtracking).
.. opt:: Typeclass Resolution For Conversion
This option (on by default) controls the use of typeclass resolution
- when a unification problem cannot be solved during elaboration/type-
+ when a unification problem cannot be solved during elaboration/type
inference. With this option on, when a unification fails, typeclass
resolution is tried before launching unification once again.
@@ -544,7 +550,7 @@ Typeclasses eauto `:=`
.. cmd:: Typeclasses eauto := {? debug} {? {dfs | bfs}} depth
- This command allows more global customization of the type class
+ This command allows more global customization of the typeclass
resolution tactic. The semantics of the options are:
+ ``debug`` In debug mode, the trace of successfully applied tactics is
diff --git a/doc/sphinx/addendum/universe-polymorphism.rst b/doc/sphinx/addendum/universe-polymorphism.rst
index 6e7ccba63c..7e77dea457 100644
--- a/doc/sphinx/addendum/universe-polymorphism.rst
+++ b/doc/sphinx/addendum/universe-polymorphism.rst
@@ -36,7 +36,7 @@ error:
Fail Definition selfid := identity (@identity).
Indeed, the global level ``Top.1`` would have to be strictly smaller than
-itself for this self-application to typecheck, as the type of
+itself for this self-application to type check, as the type of
:g:`(@identity)` is :g:`forall (A : Type@{Top.1}), A -> A` whose type is itself
:g:`Type@{Top.1+1}`.
@@ -72,7 +72,7 @@ different. This can be seen when the :opt:`Printing Universes` option is on:
Now :g:`pidentity` is used at two different levels: at the head of the
application it is instantiated at ``Top.3`` while in the argument position
it is instantiated at ``Top.4``. This definition is only valid as long as
-``Top.4`` is strictly smaller than ``Top.3``, as show by the constraints. Note
+``Top.4`` is strictly smaller than ``Top.3``, as shown by the constraints. Note
that this definition is monomorphic (not universe polymorphic), so the
two universes (in this case ``Top.3`` and ``Top.4``) are actually global
levels.
diff --git a/doc/sphinx/biblio.bib b/doc/sphinx/biblio.bib
index 3e988709c5..c74d8f540c 100644
--- a/doc/sphinx/biblio.bib
+++ b/doc/sphinx/biblio.bib
@@ -1,7 +1,22 @@
@String{jfp = "Journal of Functional Programming"}
@String{lncs = "Lecture Notes in Computer Science"}
@String{lnai = "Lecture Notes in Artificial Intelligence"}
-@String{SV = "{Sprin-ger-Verlag}"}
+@String{SV = "{Springer-Verlag}"}
+
+@InCollection{Asp00,
+ Title = {Proof General: A Generic Tool for Proof Development},
+ Author = {Aspinall, David},
+ Booktitle = {Tools and Algorithms for the Construction and
+ Analysis of Systems, {TACAS} 2000},
+ Publisher = {Springer Berlin Heidelberg},
+ Year = {2000},
+ Editor = {Graf, Susanne and Schwartzbach, Michael},
+ Pages = {38--43},
+ Series = {Lecture Notes in Computer Science},
+ Volume = {1785},
+ Doi = {10.1007/3-540-46419-0_3},
+ ISBN = {978-3-540-67282-1},
+}
@Book{Bar81,
author = {H.P. Barendregt},
@@ -237,13 +252,13 @@ s},
booktitle = {TYPES},
year = 2002,
crossref = {DBLP:conf/types/2002},
- url = {draft at \url{http://www.irif.fr/~letouzey/download/extraction2002.pdf}}
+ url = {http://www.irif.fr/~letouzey/download/extraction2002.pdf}
}
@InProceedings{Luttik97specificationof,
author = {Sebastiaan P. Luttik and Eelco Visser},
booktitle = {2nd International Workshop on the Theory and Practice of Algebraic Specifications (ASF+SDF'97), Electronic Workshops in Computing},
- publisher = {Springer-Verlag},
+ publisher = SV,
title = {Specification of Rewriting Strategies},
year = {1997}
}
@@ -290,16 +305,13 @@ the Calculus of Inductive Constructions}},
year = {1995}
}
-@Misc{Pcoq,
- author = {Lemme Team},
- title = {Pcoq a graphical user-interface for {Coq}},
- note = {\url{http://www-sop.inria.fr/lemme/pcoq/}}
-}
-
-@Misc{ProofGeneral,
- author = {David Aspinall},
- title = {Proof General},
- note = {\url{https://proofgeneral.github.io/}}
+@InProceedings{Pit16,
+ Title = {Company-Coq: Taking Proof General one step closer to a real IDE},
+ Author = {Pit-Claudel, Clément and Courtieu, Pierre},
+ Booktitle = {CoqPL'16: The Second International Workshop on Coq for PL},
+ Year = {2016},
+ Month = jan,
+ Doi = {10.5281/zenodo.44331},
}
@Book{RC95,
diff --git a/doc/sphinx/credits.rst b/doc/sphinx/credits.rst
index 2562dec468..be0b5d5f12 100644
--- a/doc/sphinx/credits.rst
+++ b/doc/sphinx/credits.rst
@@ -40,7 +40,7 @@ foundation of mathematics on constructive principles. The second one,
Girard’s polymorphic :math:`\lambda`-calculus :math:`F_\omega`, is a
very strong functional system in which we may represent higher-order
logic proof structures. Combining both systems in a higher-order
-extension of the Automath languages, T. Coquand presented in 1985 the
+extension of the Automath language, T. Coquand presented in 1985 the
first version of the *Calculus of Constructions*, CoC. This strong
logical system allowed powerful axiomatizations, but direct inductive
definitions were not possible, and inductive notions had to be defined
@@ -60,7 +60,7 @@ the language ML.
Automated theorem-proving was pioneered in the 1960’s by Davis and
Putnam in propositional calculus. A complete mechanization (in the sense
-of a semi-decision procedure) of classical first-order logic was
+of a semidecision procedure) of classical first-order logic was
proposed in 1965 by J.A. Robinson, with a single uniform inference rule
called *resolution*. Resolution relies on solving equations in free
algebras (i.e. term structures), using the *unification algorithm*. Many
@@ -246,14 +246,14 @@ pretty-printing rules has also changed.
Eduardo Giménez redesigned the internal tactic libraries, giving uniform
names to Caml functions corresponding to |Coq| tactic names.
-Bruno Barras wrote new more efficient reductions functions.
+Bruno Barras wrote new, more efficient reduction functions.
Hugo Herbelin introduced more uniform notations in the |Coq| specification
language: the definitions by fixpoints and pattern-matching have a more
readable syntax. Patrick Loiseleur introduced user-friendly notations
for arithmetic expressions.
-New tactics were introduced: Eduardo Giménez improved a mechanism to
+New tactics were introduced: Eduardo Giménez improved the mechanism to
introduce macros for tactics, and designed special tactics for
(co)inductive definitions; Patrick Loiseleur designed a tactic to
simplify polynomial expressions in an arbitrary commutative ring which
@@ -279,12 +279,12 @@ Loiseleur.
Credits: addendum for version 6.3
=================================
-The main changes in version V6.3 was the introduction of a few new
+The main changes in version V6.3 were the introduction of a few new
tactics and the extension of the guard condition for fixpoint
definitions.
B. Barras extended the unification algorithm to complete partial terms
-and solved various tricky bugs related to universes.
+and fixed various tricky bugs related to universes.
D. Delahaye developed the ``AutoRewrite`` tactic. He also designed the
new behavior of ``Intro`` and provided the tacticals ``First`` and
@@ -318,9 +318,9 @@ internal architecture of the system. The |Coq| version 7.0 was distributed
in March 2001, version 7.1 in September 2001, version 7.2 in January
2002, version 7.3 in May 2002 and version 7.4 in February 2003.
-Jean-Christophe Filliâtre designed the architecture of the new system,
-he introduced a new representation for environments and wrote a new
-kernel for type-checking terms. His approach was to use functional
+Jean-Christophe Filliâtre designed the architecture of the new system.
+He introduced a new representation for environments and wrote a new
+kernel for type checking terms. His approach was to use functional
data-structures in order to get more sharing, to prepare the addition of
modules and also to get closer to a certified kernel.
@@ -351,8 +351,8 @@ Letouzey adapted user contributions to extract ML programs when it was
sensible. Jean-Christophe Filliâtre wrote ``coqdoc``, a documentation
tool for |Coq| libraries usable from version 7.2.
-Bruno Barras improved the reduction algorithms efficiency and the
-confidence level in the correctness of |Coq| critical type-checking
+Bruno Barras improved the efficiency of the reduction algorithm and the
+confidence level in the correctness of |Coq| critical type checking
algorithm.
Yves Bertot designed the ``SearchPattern`` and ``SearchRewrite`` tools
@@ -368,8 +368,8 @@ propositional inductive types.
Loïc Pottier developed Fourier, a tactic solving linear inequalities on
real numbers.
-Pierre Crégut developed a new version based on reflexion of the Omega
-decision tactic.
+Pierre Crégut developed a new, reflection-based version of the Omega
+decision procedure.
Claudio Sacerdoti Coen designed an XML output for the |Coq| modules to be
used in the Hypertextual Electronic Library of Mathematics (HELM cf
@@ -419,7 +419,7 @@ main motivations were
with a functional programming perfume (e.g. abstraction is now
written fun), and more directly accessible to the novice (e.g.
dependent product is now written forall and allows omission of
- types). Also, parentheses and are no longer mandatory for function
+ types). Also, parentheses are no longer mandatory for function
application.
- extensibility: some standard notations (e.g. “<” and “>”) were
@@ -438,8 +438,8 @@ language and of the language of commands has been carried out. The
purpose here is a better uniformity making the tactics and commands
easier to use and to remember.
-Thirdly, a restructuration and uniformisation of the standard library of
-Coq has been performed. There is now just one Leibniz’ equality usable
+Thirdly, a restructuring and uniformization of the standard library of
+Coq has been performed. There is now just one Leibniz equality usable
for all the different kinds of |Coq| objects. Also, the set of real
numbers now lies at the same level as the sets of natural and integer
numbers. Finally, the names of the standard properties of numbers now
@@ -447,7 +447,7 @@ follow a standard pattern and the symbolic notations for the standard
definitions as well.
The fourth point is the release of |CoqIDE|, a new graphical gtk2-based
-interface fully integrated to |Coq|. Close in style from the Proof General
+interface fully integrated with |Coq|. Close in style to the Proof General
Emacs interface, it is faster and its integration with |Coq| makes
interactive developments more friendly. All mathematical Unicode symbols
are usable within |CoqIDE|.
@@ -461,18 +461,17 @@ improved tactics (including a new tactic for solving first-order
statements), new management commands, extended libraries.
Bruno Barras and Hugo Herbelin have been the main contributors of the
-reflexion and the implementation of the new syntax. The smart automatic
+reflection and the implementation of the new syntax. The smart automatic
translator from old to new syntax released with |Coq| is also their work
with contributions by Olivier Desmettre.
-Hugo Herbelin is the main designer and implementor of the notion of
+Hugo Herbelin is the main designer and implementer of the notion of
interpretation scopes and of the commands for easily adding new
notations.
-Hugo Herbelin is the main implementor of the restructuration of the
-standard library.
+Hugo Herbelin is the main implementer of the restructured standard library.
-Pierre Corbineau is the main designer and implementor of the new tactic
+Pierre Corbineau is the main designer and implementer of the new tactic
for solving first-order statements in presence of inductive types. He is
also the maintainer of the non-domain specific automation tactics.
@@ -487,14 +486,14 @@ Pierre Letouzey and Jacek Chrząszcz respectively maintained the
extraction tool and module system of |Coq|.
Jean-Christophe Filliâtre, Pierre Letouzey, Hugo Herbelin and other
-contributors from Sophia-Antipolis and Nijmegen participated to the
-extension of the library.
+contributors from Sophia-Antipolis and Nijmegen participated in
+extending the library.
Julien Narboux built a NSIS-based automatic |Coq| installation tool for
the Windows platform.
Hugo Herbelin and Christine Paulin coordinated the development which was
-under the responsability of Christine Paulin.
+under the responsibility of Christine Paulin.
| Palaiseau & Orsay, Apr. 2004
| Hugo Herbelin & Christine Paulin
@@ -507,7 +506,7 @@ Credits: version 8.1
Coq version 8.1 adds various new functionalities.
Benjamin Grégoire implemented an alternative algorithm to check the
-convertibility of terms in the |Coq| type-checker. This alternative
+convertibility of terms in the |Coq| type checker. This alternative
algorithm works by compilation to an efficient bytecode that is
interpreted in an abstract machine similar to Xavier Leroy’s ZINC
machine. Convertibility is performed by comparing the normal forms. This
@@ -525,12 +524,12 @@ arbitrary transition systems.
Claudio Sacerdoti Coen added new features to the module system.
-Benjamin Grégoire, Assia Mahboubi and Bruno Barras developed a new more
-efficient and more general simplification algorithm on rings and
-semi-rings.
+Benjamin Grégoire, Assia Mahboubi and Bruno Barras developed a new, more
+efficient and more general simplification algorithm for rings and
+semirings.
-Laurent Théry and Bruno Barras developed a new significantly more
-efficient simplification algorithm on fields.
+Laurent Théry and Bruno Barras developed a new, significantly more
+efficient simplification algorithm for fields.
Hugo Herbelin, Pierre Letouzey, Julien Forest, Julien Narboux and
Claudio Sacerdoti Coen added new tactic features.
@@ -554,7 +553,7 @@ Jean-Christophe Filliâtre’s contribution on finite maps have been
integrated to the |Coq| standard library. Pierre Letouzey developed a
library about finite sets “à la Objective Caml”. With Jean-Marc Notin,
he extended the library on lists. Pierre Letouzey’s contribution on
-rational numbers has been integrated and extended..
+rational numbers has been integrated and extended.
Pierre Corbineau extended his tactic for solving first-order statements.
He wrote a reflection-based intuitionistic tautology solver.
@@ -587,11 +586,11 @@ Coq version 8.2 adds new features, new libraries and improves on many
various aspects.
Regarding the language of |Coq|, the main novelty is the introduction by
-Matthieu Sozeau of a package of commands providing Haskell-style type
-classes. Type classes, that come with a few convenient features such as
-type-based resolution of implicit arguments, plays a new role of
-landmark in the architecture of |Coq| with respect to automatization. For
-instance, thanks to type classes support, Matthieu Sozeau could
+Matthieu Sozeau of a package of commands providing Haskell-style typeclasses.
+Typeclasses, which come with a few convenient features such as
+type-based resolution of implicit arguments, play a new landmark role
+in the architecture of |Coq| with respect to automation. For
+instance, thanks to typeclass support, Matthieu Sozeau could
implement a new resolution-based version of the tactics dedicated to
rewriting on arbitrary transitive relations.
@@ -599,13 +598,13 @@ Another major improvement of |Coq| 8.2 is the evolution of the arithmetic
libraries and of the tools associated to them. Benjamin Grégoire and
Laurent Théry contributed a modular library for building arbitrarily
large integers from bounded integers while Evgeny Makarov contributed a
-modular library of abstract natural and integer arithmetics together
+modular library of abstract natural and integer arithmetic together
with a few convenient tactics. On his side, Pierre Letouzey made
numerous extensions to the arithmetic libraries on :math:`\mathbb{Z}`
-and :math:`\mathbb{Q}`, including extra support for automatization in
+and :math:`\mathbb{Q}`, including extra support for automation in
presence of various number-theory concepts.
-Frédéric Besson contributed a reflexive tactic based on Krivine-Stengle
+Frédéric Besson contributed a reflective tactic based on Krivine-Stengle
Positivstellensatz (the easy way) for validating provability of systems
of inequalities. The platform is flexible enough to support the
validation of any algorithm able to produce a “certificate” for the
@@ -620,10 +619,10 @@ relying on Benjamin Grégoire and Laurent Théry’s library, delivered a
library of unbounded integers in base :math:`2^{31}`. As importantly, he
developed a notion of “retro-knowledge” so as to safely extend the
kernel-located bytecode-based efficient evaluation algorithm of |Coq|
-version 8.1 to use 31-bits machine arithmetics for efficiently computing
+version 8.1 to use 31-bits machine arithmetic for efficiently computing
with the library of integers he developed.
-Beside the libraries, various improvements contributed to provide a more
+Beside the libraries, various improvements were contributed to provide a more
comfortable end-user language and more expressive tactic language. Hugo
Herbelin and Matthieu Sozeau improved the pattern-matching compilation
algorithm (detection of impossible clauses in pattern-matching,
@@ -632,7 +631,7 @@ and Matthieu Sozeau contributed various new convenient syntactic
constructs and new tactics or tactic features: more inference of
redundant information, better unification, better support for proof or
definition by fixpoint, more expressive rewriting tactics, better
-support for meta-variables, more convenient notations, ...
+support for meta-variables, more convenient notations...
Élie Soubiran improved the module system, adding new features (such as
an “include” command) and making it more flexible and more general. He
@@ -641,7 +640,7 @@ mechanism.
Matthieu Sozeau extended the 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
+the Mathematical Proof Language and the automation tools that
accompany it, Pierre Letouzey supervised and extended various parts of the
standard library, Stéphane Glondu contributed a few tactics and
improvements, Jean-Marc Notin provided help in debugging, general
@@ -649,7 +648,7 @@ maintenance and coqdoc support, Vincent Siles contributed extensions of
the Scheme command and of injection.
Bruno Barras implemented the `coqchk` tool: this is a stand-alone
-type-checker that can be used to certify .vo files. Especially, as this
+type checker that can be used to certify .vo files. Especially, as this
verifier runs in a separate process, it is granted not to be “hijacked”
by virtually malicious extensions added to |Coq|.
@@ -662,7 +661,7 @@ adaptation of the interface of the old “setoid rewrite” tactic to the
new version. Lionel Mamane worked on 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 improve the libraries of integers,
+Kaliszyk, Milad Niqui contributed to 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
@@ -704,8 +703,8 @@ The module system evolved significantly. Besides the resolution of some
efficiency issues and a more flexible construction of module types, Élie
Soubiran brought a new model of name equivalence, the
:math:`\Delta`-equivalence, which respects as much as possible the names
-given by the users. He also designed with Pierre Letouzey a new
-convenient operator ``<+`` for nesting functor application, that
+given by the users. He also designed with Pierre Letouzey a new,
+convenient operator ``<+`` for nesting functor application that
provides a light notation for inheriting the properties of cascading
modules.
@@ -713,13 +712,13 @@ The new tactic nsatz is due to Loïc Pottier. It works by computing
Gröbner bases. Regarding the existing tactics, various improvements have
been done by Matthieu Sozeau, Hugo Herbelin and Pierre Letouzey.
-Matthieu Sozeau extended and refined the type classes and Program
+Matthieu Sozeau extended and refined the typeclasses and Program
features (the Russell language). Pierre Letouzey maintained and improved
the extraction mechanism. Bruno Barras and Élie Soubiran maintained the
Coq checker, Julien Forest maintained the Function mechanism for
reasoning over recursively defined functions. Matthieu Sozeau, Hugo
Herbelin and Jean-Marc Notin maintained coqdoc. Frédéric Besson
-maintained the Micromega plateform for deciding systems of inequalities.
+maintained the Micromega platform for deciding systems of inequalities.
Pierre Courtieu maintained the support for the Proof General Emacs
interface. Claude Marché maintained the plugin for calling external
provers (dp). Yves Bertot made some improvements to the libraries of
@@ -736,7 +735,7 @@ support for benchmarking and archiving.
Many users helped by reporting problems, providing patches, suggesting
improvements or making useful comments, either on the bug tracker or on
-the Coq-club mailing list. This includes but not exhaustively Cédric
+the Coq-Club mailing list. This includes but not exhaustively Cédric
Auger, Arthur Charguéraud, François Garillot, Georges Gonthier, Robin
Green, Stéphane Lescuyer, Eelis van der Weegen, ...
@@ -772,8 +771,8 @@ structured scripts (bullets and proof brackets) but, even if yet not
user-available, the new engine also provides the basis for refining
existential variables using tactics, for applying tactics to several
goals simultaneously, for reordering goals, all features which are
-planned for the next release. The new proof engine forced to reimplement
-info and Show Script differently, what was done by Pierre Letouzey.
+planned for the next release. The new proof engine forced Pierre Letouzey
+to reimplement info and Show Script differently.
Before version 8.4, |CoqIDE| was linked to |Coq| with the graphical
interface living in a separate thread. From version 8.4, |CoqIDE| is a
@@ -784,7 +783,7 @@ sessions in parallel. Relying on the infrastructure work made by Vincent
Gross, Pierre Letouzey, Pierre Boutillier and Pierre-Marie Pédrot
contributed many various refinements of |CoqIDE|.
-Coq 8.4 also comes with a bunch of many various smaller-scale changes
+Coq 8.4 also comes with a bunch of various smaller-scale changes
and improvements regarding the different components of the system.
The underlying logic has been extended with :math:`\eta`-conversion
@@ -811,7 +810,7 @@ Regarding the high-level specification language, Pierre Boutillier
introduced the ability to give implicit arguments to anonymous
functions, Hugo Herbelin introduced the ability to define notations with
several binders (e.g. ``exists x y z, P``), Matthieu Sozeau made the
-type classes inference mechanism more robust and predictable, Enrico
+typeclass inference mechanism more robust and predictable, Enrico
Tassi introduced a command Arguments that generalizes Implicit Arguments
and Arguments Scope for assigning various properties to arguments of
constants. Various improvements in the type inference algorithm were
@@ -831,8 +830,8 @@ Pierre Letouzey added a tactic timeout and the interruptibility of
vm\_compute. Bug fixes and miscellaneous improvements of the tactic
language came from Hugo Herbelin, Pierre Letouzey and Matthieu Sozeau.
-Regarding decision tactics, Loïc Pottier maintained Nsatz, moving in
-particular to a type-class based reification of goals while Frédéric
+Regarding decision tactics, Loïc Pottier maintained nsatz, moving in
+particular to a typeclass based reification of goals while Frédéric
Besson maintained Micromega, adding in particular support for division.
Regarding vernacular commands, Stéphane Glondu provided new commands to
@@ -894,7 +893,7 @@ Boutillier (MacOS), Stéphane Glondu (Debian). Releasing, testing and
benchmarking support was provided by Jean-Marc Notin.
Many suggestions for improvements were motivated by feedback from users,
-on either the bug tracker or the coq-club mailing list. Special thanks
+on either the bug tracker or the Coq-Club mailing list. Special thanks
are going to the users who contributed patches, starting with Tom
Prince. Other patch contributors include Cédric Auger, David Baelde, Dan
Grayson, Paolo Herms, Robbert Krebbers, Marc Lasson, Hendrik Tews and
@@ -1036,7 +1035,7 @@ X). Maxime Dénès improved significantly the testing and benchmarking
support.
Many power users helped to improve the design of the new features via
-the bug tracker, the coq development mailing list or the coq-club
+the bug tracker, the coq development mailing list or the Coq-Club
mailing list. Special thanks are going to the users who contributed
patches and intensive brain-storming, starting with Jason Gross,
Jonathan Leivent, Greg Malecha, Clément Pit-Claudel, Marc Lasson, Lionel
@@ -1075,7 +1074,7 @@ over 100 contributions integrated. The main user visible changes are:
document.
- More access to the proof engine features from Ltac: goal management
- primitives, range selectors and a typeclasses eauto engine handling
+ primitives, range selectors and a ``typeclasses eauto`` engine handling
multiple goals and multiple successes, by Cyprien Mangin, Matthieu
Sozeau and Arnaud Spiwack.
@@ -1154,13 +1153,13 @@ Gregory Malecha, and Matthieu Sozeau.
Matej Košík maintained and greatly improved the continuous integration
setup and the testing of |Coq| contributions. He also contributed many API
-improvement and code cleanups throughout the system.
+improvements and code cleanups throughout the system.
The contributors for this version are Bruno Barras, C.J. Bell, Yves
Bertot, Frédéric Besson, Pierre Boutillier, Tej Chajed, Guillaume
Claret, Xavier Clerc, Pierre Corbineau, Pierre Courtieu, Maxime Dénès,
Ricky Elrod, Emilio Jesús Gallego Arias, Jason Gross, Hugo Herbelin,
-Sébastien Hinderer, Jacques-Henri Jourdan, Matej Kosik, Xavier Leroy,
+Sébastien Hinderer, Jacques-Henri Jourdan, Matej Košík, Xavier Leroy,
Pierre Letouzey, Gregory Malecha, Cyprien Mangin, Erik Martin-Dorel,
Guillaume Melquiond, Clément Pit–Claudel, Pierre-Marie Pédrot, Daniel de
Rauglaudre, Lionel Rieg, Gabriel Scherer, Thomas Sibut-Pinote, Matthieu
@@ -1171,7 +1170,7 @@ Dénès, who was also in charge of the release process.
Many power users helped to improve the design of the new features via
the bug tracker, the pull request system, the |Coq| development mailing
-list or the coq-club mailing list. Special thanks to the users who
+list or the Coq-Club mailing list. Special thanks to the users who
contributed patches and intensive brain-storming and code reviews,
starting with Cyril Cohen, Jason Gross, Robbert Krebbers, Jonathan
Leivent, Xavier Leroy, Gregory Malecha, Clément Pit–Claudel, Gabriel
@@ -1235,7 +1234,7 @@ The efficiency of the whole system has been significantly improved thanks to
contributions from Pierre-Marie Pédrot, Maxime Dénès and Matthieu Sozeau and
performance issue tracking by Jason Gross and Paul Steckler.
-Thomas Sibut-Pinote and Hugo Herbelin added support for side effects hooks in
+Thomas Sibut-Pinote and Hugo Herbelin added support for side effect hooks in
cbv, cbn and simpl. The side effects are provided via a plugin available at
https://github.com/herbelin/reduction-effects/.
@@ -1279,7 +1278,7 @@ the maintainer of this release.
Many power users helped to improve the design of the new features via the bug
tracker, the pull request system, the |Coq| development mailing list or the
-coq-club mailing list. Special thanks to the users who contributed patches and
+Coq-Club mailing list. Special thanks to the users who contributed patches and
intensive brain-storming and code reviews, starting with Jason Gross, Ralf Jung,
Robbert Krebbers, Xavier Leroy, Clément Pit–Claudel and Gabriel Scherer. It
would however be impossible to mention exhaustively the names of everybody who
@@ -1293,7 +1292,7 @@ integration of new features, with an important focus given to compatibility and
performance issues, resulting in a hopefully more robust release than |Coq| 8.6
while maintaining compatibility.
-|Coq| Enhancement Proposals (CEPs for short) and open pull-requests discussions
+|Coq| Enhancement Proposals (CEPs for short) and open pull request discussions
were used to discuss publicly the new features.
The |Coq| consortium, an organization directed towards users and supporters of the
@@ -1393,7 +1392,7 @@ Version 8.8 is the third release of |Coq| developed on a time-based
development cycle. Its development spanned 6 months from the release of
|Coq| 8.7 and was based on a public roadmap. The development process
was coordinated by Matthieu Sozeau. Maxime Dénès was in charge of the
-release process.
+release process. Théo Zimmermann is the maintainer of this release.
Many power users helped to improve the design of the new features via
the bug tracker, the pull request system, the |Coq| development mailing
diff --git a/doc/sphinx/index.rst b/doc/sphinx/index.rst
index f3ae493817..baf2e0d981 100644
--- a/doc/sphinx/index.rst
+++ b/doc/sphinx/index.rst
@@ -84,3 +84,8 @@ This material (the Coq Reference Manual) may be distributed only subject to the
terms and conditions set forth in the Open Publication License, v1.0 or later
(the latest version is presently available at
http://www.opencontent.org/openpub). Options A and B are not elected.
+
+.. [#PG] Proof-General is available at https://proofgeneral.github.io/.
+ Optionally, you can enhance it with the minor mode
+ Company-Coq :cite:`Pit16`
+ (see https://github.com/cpitclaudel/company-coq).
diff --git a/doc/sphinx/introduction.rst b/doc/sphinx/introduction.rst
index bc72877b63..b57e4b209c 100644
--- a/doc/sphinx/introduction.rst
+++ b/doc/sphinx/introduction.rst
@@ -7,12 +7,12 @@ Introduction
This document is the Reference Manual of the |Coq| proof assistant.
To start using Coq, it is advised to first read a tutorial.
Links to several tutorials can be found at
-https://coq.inria.fr/documentation (see also
-https://github.com/coq/coq/wiki#coq-tutorials).
+https://coq.inria.fr/documentation and
+https://github.com/coq/coq/wiki#coq-tutorials
The |Coq| system is designed to develop mathematical proofs, and
especially to write formal specifications, programs and to verify that
-programs are correct with respect to their specification. It provides a
+programs are correct with respect to their specifications. It provides a
specification language named |Gallina|. Terms of |Gallina| can represent
programs as well as properties of these programs and proofs of these
properties. Using the so-called *Curry-Howard isomorphism*, programs,
@@ -20,7 +20,7 @@ properties and proofs are formalized in the same language called
*Calculus of Inductive Constructions*, that is a
:math:`\lambda`-calculus with a rich type system. All logical judgments
in |Coq| are typing judgments. The very heart of the |Coq| system is the
-type-checking algorithm that checks the correctness of proofs, in other
+type checking algorithm that checks the correctness of proofs, in other
words that checks that a program complies to its specification. |Coq| also
provides an interactive proof assistant to build proofs using specific
programs called *tactics*.
@@ -28,37 +28,35 @@ programs called *tactics*.
All services of the |Coq| proof assistant are accessible by interpretation
of a command language called *the vernacular*.
-Coq has an interactive mode in which commands are interpreted as the
+Coq has an interactive mode in which commands are interpreted as the
user types them in from the keyboard and a compiled mode where commands
are processed from a file.
-- The interactive mode may be used as a debugging mode in which the
- user can develop his theories and proofs step by step, backtracking
- if needed and so on. The interactive mode is run with the `coqtop`
- command from the operating system (which we shall assume to be some
- variety of UNIX in the rest of this document).
+- In interactive mode, users can develop their theories and proofs step by
+ step, and query the system for available theorems and definitions. The
+ interactive mode is generally run with the help of an IDE, such
+ as CoqIDE, documented in :ref:`coqintegrateddevelopmentenvironment`,
+ Emacs with Proof-General :cite:`Asp00` [#PG]_,
+ or jsCoq to run Coq in your browser (see https://github.com/ejgallego/jscoq).
+ The `coqtop` read-eval-print-loop can also be used directly, for debugging
+ purposes.
- The compiled mode acts as a proof checker taking a file containing a
whole development in order to ensure its correctness. Moreover,
|Coq|’s compiler provides an output file containing a compact
representation of its input. The compiled mode is run with the `coqc`
- command from the operating system.
+ command.
-These two modes are documented in Chapter :ref:`thecoqcommands`.
-
-Other modes of interaction with |Coq| are possible: through an emacs shell
-window, an emacs generic user-interface for proof assistant (Proof
-General :cite:`ProofGeneral`) or through a customized
-interface (PCoq :cite:`Pcoq`). These facilities are not
-documented here. There is also a |Coq| Integrated Development Environment
-described in :ref:`coqintegrateddevelopmentenvironment`.
+.. seealso:: :ref:`thecoqcommands`.
How to read this book
=====================
-This is a Reference Manual, not a User Manual, so it is not made for a
-continuous reading. However, it has some structure that is explained
-below.
+This is a Reference Manual, so it is not intended for continuous reading.
+We recommend using the various indexes to quickly locate the documentation
+you are looking for. There is a global index, and a number of specific indexes
+for tactics, vernacular commands, and error messages and warnings.
+Nonetheless, the manual has some structure that is explained below.
- The first part describes the specification language, |Gallina|.
Chapters :ref:`gallinaspecificationlanguage` and :ref:`extensionsofgallina` describe the concrete
@@ -68,7 +66,7 @@ below.
of the formalism. Chapter :ref:`themodulesystem` describes the module
system.
-- The second part describes the proof engine. It is divided in five
+- The second part describes the proof engine. It is divided in six
chapters. Chapter :ref:`vernacularcommands` presents all commands (we
call them *vernacular commands*) that are not directly related to
interactive proving: requests to the environment, complete or partial
@@ -79,24 +77,24 @@ below.
*tactics*. The language to combine these tactics into complex proof
strategies is given in Chapter :ref:`ltac`. Examples of tactics
are described in Chapter :ref:`detailedexamplesoftactics`.
+ Finally, the |SSR| proof language is presented in
+ Chapter :ref:`thessreflectprooflanguage`.
-- The third part describes how to extend the syntax of |Coq|. It
- corresponds to the Chapter :ref:`syntaxextensionsandinterpretationscopes`.
+- The third part describes how to extend the syntax of |Coq| in
+ Chapter :ref:`syntaxextensionsandinterpretationscopes` and how to define
+ new induction principles in Chapter :ref:`proofschemes`.
- In the fourth part more practical tools are documented. First in
Chapter :ref:`thecoqcommands`, the usage of `coqc` (batch mode) and
`coqtop` (interactive mode) with their options is described. Then,
in Chapter :ref:`utilities`, various utilities that come with the
|Coq| distribution are presented. Finally, Chapter :ref:`coqintegrateddevelopmentenvironment`
- describes the |Coq| integrated development environment.
+ describes CoqIDE.
- The fifth part documents a number of advanced features, including coercions,
canonical structures, typeclasses, program extraction, and specialized
solvers and tactics. See the table of contents for a complete list.
-At the end of the document, after the global index, the user can find
-specific indexes for tactics, vernacular commands, and error messages.
-
List of additional documentation
================================
@@ -109,5 +107,5 @@ Installation
The |Coq| standard library
A commented version of sources of the |Coq| standard library
- (including only the specifications, the proofs are removed) is given
- in the additional document `Library.ps`.
+ (including only the specifications, the proofs are removed) is
+ available at https://coq.inria.fr/stdlib/.
diff --git a/doc/sphinx/language/cic.rst b/doc/sphinx/language/cic.rst
index f6bab02673..3d3a1b11b1 100644
--- a/doc/sphinx/language/cic.rst
+++ b/doc/sphinx/language/cic.rst
@@ -96,8 +96,9 @@ constraints between the universe variables is maintained globally. To
ensure the existence of a mapping of the universes to the positive
integers, the graph of constraints must remain acyclic. Typing
expressions that violate the acyclicity of the graph of constraints
-results in a Universe inconsistency error (see also Section
-:ref:`printing-universes`).
+results in a Universe inconsistency error.
+
+.. seealso:: Section :ref:`printing-universes`.
.. _Terms:
@@ -721,67 +722,71 @@ called the *context of parameters*. Furthermore, we must have that
each :math:`T` in :math:`(t:T)∈Γ_I` can be written as: :math:`∀Γ_P,∀Γ_{\mathit{Arr}(t)}, S` where
:math:`Γ_{\mathit{Arr}(t)}` is called the *Arity* of the inductive type t and :math:`S` is called
the sort of the inductive type t (not to be confused with :math:`\Sort` which is the set of sorts).
-** Examples** The declaration for parameterized lists is:
-.. math::
- \ind{1}{[\List:\Set→\Set]}{\left[\begin{array}{rcl}
- \Nil & : & \forall A:\Set,\List~A \\
- \cons & : & \forall A:\Set, A→ \List~A→ \List~A
- \end{array}
- \right]}
+.. example::
-which corresponds to the result of the |Coq| declaration:
+ The declaration for parameterized lists is:
-.. example::
- .. coqtop:: in
-
- Inductive list (A:Set) : Set :=
- | nil : list A
- | cons : A -> list A -> list A.
+ .. math::
+ \ind{1}{[\List:\Set→\Set]}{\left[\begin{array}{rcl}
+ \Nil & : & \forall A:\Set,\List~A \\
+ \cons & : & \forall A:\Set, A→ \List~A→ \List~A
+ \end{array}
+ \right]}
-The declaration for a mutual inductive definition of tree and forest
-is:
+ which corresponds to the result of the |Coq| declaration:
-.. math::
- \ind{~}{\left[\begin{array}{rcl}\tree&:&\Set\\\forest&:&\Set\end{array}\right]}
- {\left[\begin{array}{rcl}
- \node &:& \forest → \tree\\
- \emptyf &:& \forest\\
- \consf &:& \tree → \forest → \forest\\
- \end{array}\right]}
+ .. coqtop:: in
-which corresponds to the result of the |Coq| declaration:
+ Inductive list (A:Set) : Set :=
+ | nil : list A
+ | cons : A -> list A -> list A.
.. example::
- .. coqtop:: in
- Inductive tree : Set :=
- | node : forest -> tree
- with forest : Set :=
- | emptyf : forest
- | consf : tree -> forest -> forest.
+ The declaration for a mutual inductive definition of tree and forest
+ is:
-The declaration for a mutual inductive definition of even and odd is:
+ .. math::
+ \ind{0}{\left[\begin{array}{rcl}\tree&:&\Set\\\forest&:&\Set\end{array}\right]}
+ {\left[\begin{array}{rcl}
+ \node &:& \forest → \tree\\
+ \emptyf &:& \forest\\
+ \consf &:& \tree → \forest → \forest\\
+ \end{array}\right]}
-.. math::
- \ind{1}{\left[\begin{array}{rcl}\even&:&\nat → \Prop \\
- \odd&:&\nat → \Prop \end{array}\right]}
- {\left[\begin{array}{rcl}
- \evenO &:& \even~0\\
- \evenS &:& \forall n, \odd~n -> \even~(\kw{S}~n)\\
- \oddS &:& \forall n, \even~n -> \odd~(\kw{S}~n)
- \end{array}\right]}
+ which corresponds to the result of the |Coq| declaration:
-which corresponds to the result of the |Coq| declaration:
+ .. coqtop:: in
+
+ Inductive tree : Set :=
+ | node : forest -> tree
+ with forest : Set :=
+ | emptyf : forest
+ | consf : tree -> forest -> forest.
.. example::
- .. coqtop:: in
- Inductive even : nat -> prop :=
- | even_O : even 0
- | even_S : forall n, odd n -> even (S n)
- with odd : nat -> prop :=
- | odd_S : forall n, even n -> odd (S n).
+ The declaration for a mutual inductive definition of even and odd is:
+
+ .. math::
+ \ind{0}{\left[\begin{array}{rcl}\even&:&\nat → \Prop \\
+ \odd&:&\nat → \Prop \end{array}\right]}
+ {\left[\begin{array}{rcl}
+ \evenO &:& \even~0\\
+ \evenS &:& \forall n, \odd~n -> \even~(\kw{S}~n)\\
+ \oddS &:& \forall n, \even~n -> \odd~(\kw{S}~n)
+ \end{array}\right]}
+
+ which corresponds to the result of the |Coq| declaration:
+
+ .. coqtop:: in
+
+ Inductive even : nat -> Prop :=
+ | even_O : even 0
+ | even_S : forall n, odd n -> even (S n)
+ with odd : nat -> prop :=
+ | odd_S : forall n, even n -> odd (S n).
@@ -810,6 +815,7 @@ contains an inductive declaration.
E[Γ] ⊢ c : C
.. example::
+
Provided that our environment :math:`E` contains inductive definitions we showed before,
these two inference rules above enable us to conclude that:
@@ -838,8 +844,8 @@ rules, we need a few definitions:
Arity of a given sort
+++++++++++++++++++++
-A type :math:`T` is an *arity of sort s* if it converts to the sort s or to a
-product :math:`∀ x:T,U` with :math:`U` an arity of sort s.
+A type :math:`T` is an *arity of sort* :math:`s` if it converts to the sort :math:`s` or to a
+product :math:`∀ x:T,U` with :math:`U` an arity of sort :math:`s`.
.. example::
@@ -850,7 +856,7 @@ product :math:`∀ x:T,U` with :math:`U` an arity of sort s.
Arity
+++++
A type :math:`T` is an *arity* if there is a :math:`s∈ \Sort` such that :math:`T` is an arity of
-sort s.
+sort :math:`s`.
.. example::
@@ -918,32 +924,33 @@ condition* for a constant :math:`X` in the following cases:
.. example::
+
For instance, if one considers the following variant of a tree type
branching over the natural numbers:
- .. coqtop:: in
+ .. coqtop:: in
- Inductive nattree (A:Type) : Type :=
- | leaf : nattree A
- | node : A -> (nat -> nattree A) -> nattree A.
- End TreeExample.
-
- Then every instantiated constructor of ``nattree A`` satisfies the nested positivity
- condition for ``nattree``:
+ Inductive nattree (A:Type) : Type :=
+ | leaf : nattree A
+ | node : A -> (nat -> nattree A) -> nattree A.
+ End TreeExample.
+
+ Then every instantiated constructor of ``nattree A`` satisfies the nested positivity
+ condition for ``nattree``:
- + Type ``nattree A`` of constructor ``leaf`` satisfies the positivity condition for
- ``nattree`` because ``nattree`` does not appear in any (real) arguments of the
- type of that constructor (primarily because ``nattree`` does not have any (real)
- arguments) ... (bullet 1)
+ + Type ``nattree A`` of constructor ``leaf`` satisfies the positivity condition for
+ ``nattree`` because ``nattree`` does not appear in any (real) arguments of the
+ type of that constructor (primarily because ``nattree`` does not have any (real)
+ arguments) ... (bullet 1)
- + Type ``A → (nat → nattree A) → nattree A`` of constructor ``node`` satisfies the
- positivity condition for ``nattree`` because:
+ + Type ``A → (nat → nattree A) → nattree A`` of constructor ``node`` satisfies the
+ positivity condition for ``nattree`` because:
- - ``nattree`` occurs only strictly positively in ``A`` ... (bullet 3)
+ - ``nattree`` occurs only strictly positively in ``A`` ... (bullet 3)
- - ``nattree`` occurs only strictly positively in ``nat → nattree A`` ... (bullet 3 + 2)
+ - ``nattree`` occurs only strictly positively in ``nat → nattree A`` ... (bullet 3 + 2)
- - ``nattree`` satisfies the positivity condition for ``nattree A`` ... (bullet 1)
+ - ``nattree`` satisfies the positivity condition for ``nattree A`` ... (bullet 1)
.. _Correctness-rules:
@@ -960,7 +967,7 @@ such that :math:`Γ_I` is :math:`[I_1 :∀ Γ_P ,A_1 ;…;I_k :∀ Γ_P ,A_k]`,
.. inference:: W-Ind
\WFE{Γ_P}
- (E[Γ_P ] ⊢ A_j : s_j' )_{j=1… k}
+ (E[Γ_P ] ⊢ A_j : s_j )_{j=1… k}
(E[Γ_I ;Γ_P ] ⊢ C_i : s_{q_i} )_{i=1… n}
------------------------------------------
\WF{E;\ind{p}{Γ_I}{Γ_C}}{Γ}
@@ -978,35 +985,34 @@ provided that the following side conditions hold:
One can remark that there is a constraint between the sort of the
arity of the inductive type and the sort of the type of its
constructors which will always be satisfied for the impredicative
-sortProp but may fail to define inductive definition on sort Set and
+sort :math:`\Prop` but may fail to define inductive definition on sort :math:`\Set` and
generate constraints between universes for inductive definitions in
the Type hierarchy.
-**Examples**. It is well known that the existential quantifier can be encoded as an
-inductive definition. The following declaration introduces the second-
-order existential quantifier :math:`∃ X.P(X)`.
-
.. example::
+
+ It is well known that the existential quantifier can be encoded as an
+ inductive definition. The following declaration introduces the second-
+ order existential quantifier :math:`∃ X.P(X)`.
+
.. coqtop:: in
-
+
Inductive exProp (P:Prop->Prop) : Prop :=
| exP_intro : forall X:Prop, P X -> exProp P.
-The same definition on Set is not allowed and fails:
+ The same definition on :math:`\Set` is not allowed and fails:
-.. example::
.. coqtop:: all
Fail Inductive exSet (P:Set->Prop) : Set :=
exS_intro : forall X:Set, P X -> exSet P.
-It is possible to declare the same inductive definition in the
-universe Type. The exType inductive definition has type
-:math:`(\Type(i)→\Prop)→\Type(j)` with the constraint that the parameter :math:`X` of :math:`\kw{exT_intro}`
-has type :math:`\Type(k)` with :math:`k<j` and :math:`k≤ i`.
+ It is possible to declare the same inductive definition in the
+ universe :math:`\Type`. The :g:`exType` inductive definition has type
+ :math:`(\Type(i)→\Prop)→\Type(j)` with the constraint that the parameter :math:`X` of :math:`\kw{exT_intro}`
+ has type :math:`\Type(k)` with :math:`k<j` and :math:`k≤ i`.
-.. example::
.. coqtop:: all
Inductive exType (P:Type->Prop) : Type :=
@@ -1019,9 +1025,9 @@ has type :math:`\Type(k)` with :math:`k<j` and :math:`k≤ i`.
Template polymorphism
+++++++++++++++++++++
-Inductive types declared in Type are polymorphic over their arguments
-in Type. If :math:`A` is an arity of some sort and s is a sort, we write :math:`A_{/s}`
-for the arity obtained from :math:`A` by replacing its sort with s.
+Inductive types declared in :math:`\Type` are polymorphic over their arguments
+in :math:`\Type`. If :math:`A` is an arity of some sort and :math:`s` is a sort, we write :math:`A_{/s}`
+for the arity obtained from :math:`A` by replacing its sort with :math:`s`.
Especially, if :math:`A` is well-typed in some global environment and local
context, then :math:`A_{/s}` is typable by typability of all products in the
Calculus of Inductive Constructions. The following typing rule is
@@ -1103,6 +1109,7 @@ sorts at each instance of a pattern-matching (see Section :ref:`Destructors`). A
an example, let us consider the following definition:
.. example::
+
.. coqtop:: in
Inductive option (A:Type) : Type :=
@@ -1119,6 +1126,7 @@ if :g:`option` is applied to a type in :math:`\Prop`, then, the result is not se
if set in :math:`\Prop`.
.. example::
+
.. coqtop:: all
Check (fun A:Set => option A).
@@ -1127,6 +1135,7 @@ if set in :math:`\Prop`.
Here is another example.
.. example::
+
.. coqtop:: in
Inductive prod (A B:Type) : Type := pair : A -> B -> prod A B.
@@ -1137,6 +1146,7 @@ none in :math:`\Type`, and in :math:`\Type` otherwise. In all cases, the three k
eliminations schemes are allowed.
.. example::
+
.. coqtop:: all
Check (fun A:Set => prod A).
@@ -1176,7 +1186,7 @@ ourselves to primitive recursive functions and functionals.
For instance, assuming a parameter :g:`A:Set` exists in the local context,
we want to build a function length of type :g:`list A -> nat` which computes
-the length of the list, so such that :g:`(length (nil A)) = O` and :g:`(length
+the length of the list, such that :g:`(length (nil A)) = O` and :g:`(length
(cons A a l)) = (S (length l))`. We want these equalities to be
recognized implicitly and taken into account in the conversion rule.
@@ -1243,7 +1253,7 @@ In this expression, if :math:`m` eventually happens to evaluate to
and it will reduce to :math:`f_i` where the :math:`x_{i1} …x_{ip_i}` are replaced by the
:math:`u_1 … u_{p_i}` according to the ι-reduction.
-Actually, for type-checking a :math:`\Match…\with…\endkw` expression we also need
+Actually, for type checking a :math:`\Match…\with…\endkw` expression we also need
to know the predicate P to be proved by case analysis. In the general
case where :math:`I` is an inductively defined :math:`n`-ary relation, :math:`P` is a predicate
over :math:`n+1` arguments: the :math:`n` first ones correspond to the arguments of :math:`I`
@@ -1325,6 +1335,7 @@ the extraction mechanism. Assume :math:`A` and :math:`B` are two propositions, a
logical disjunction :math:`A ∨ B` is defined inductively by:
.. example::
+
.. coqtop:: in
Inductive or (A B:Prop) : Prop :=
@@ -1335,6 +1346,7 @@ The following definition which computes a boolean value by case over
the proof of :g:`or A B` is not accepted:
.. example::
+
.. coqtop:: all
Fail Definition choice (A B: Prop) (x:or A B) :=
@@ -1358,6 +1370,7 @@ property which are provably different, contradicting the proof-
irrelevance property which is sometimes a useful axiom:
.. example::
+
.. coqtop:: all
Axiom proof_irrelevance : forall (P : Prop) (x y : P), x=y.
@@ -1365,7 +1378,7 @@ irrelevance property which is sometimes a useful axiom:
The elimination of an inductive definition of type :math:`\Prop` on a predicate
:math:`P` of type :math:`I→ Type` leads to a paradox when applied to impredicative
inductive definition like the second-order existential quantifier
-:g:`exProp` defined above, because it give access to the two projections on
+:g:`exProp` defined above, because it gives access to the two projections on
this type.
@@ -1382,15 +1395,16 @@ this type.
[I:Prop|I→ s]
A *singleton definition* has only one constructor and all the
-arguments of this constructor have type Prop. In that case, there is a
+arguments of this constructor have type :math:`\Prop`. In that case, there is a
canonical way to interpret the informative extraction on an object in
that type, such that the elimination on any sort :math:`s` is legal. Typical
examples are the conjunction of non-informative propositions and the
-equality. If there is an hypothesis :math:`h:a=b` in the local context, it can
+equality. If there is a hypothesis :math:`h:a=b` in the local context, it can
be used for rewriting not only in logical propositions but also in any
type.
.. example::
+
.. coqtop:: all
Print eq_rec.
@@ -1421,45 +1435,46 @@ corresponding to the :math:`c:C` constructor.
We write :math:`\{c\}^P` for :math:`\{c:C\}^P` with :math:`C` the type of :math:`c`.
-**Example.**
-The following term in concrete syntax::
+.. example::
- match t as l return P' with
- | nil _ => t1
- | cons _ hd tl => t2
- end
+ The following term in concrete syntax::
+ match t as l return P' with
+ | nil _ => t1
+ | cons _ hd tl => t2
+ end
-can be represented in abstract syntax as
-.. math::
- \case(t,P,f 1 | f 2 )
+ can be represented in abstract syntax as
-where
+ .. math::
+ \case(t,P,f 1 | f 2 )
-.. math::
- \begin{eqnarray*}
- P & = & \lambda~l~.~P^\prime\\
- f_1 & = & t_1\\
- f_2 & = & \lambda~(hd:\nat)~.~\lambda~(tl:\List~\nat)~.~t_2
- \end{eqnarray*}
+ where
-According to the definition:
+ .. math::
+ \begin{eqnarray*}
+ P & = & \lambda~l~.~P^\prime\\
+ f_1 & = & t_1\\
+ f_2 & = & \lambda~(hd:\nat)~.~\lambda~(tl:\List~\nat)~.~t_2
+ \end{eqnarray*}
-.. math::
- \{(\kw{nil}~\nat)\}^P ≡ \{(\kw{nil}~\nat) : (\List~\nat)\}^P ≡ (P~(\kw{nil}~\nat))
+ According to the definition:
-.. math::
-
- \begin{array}{rl}
- \{(\kw{cons}~\nat)\}^P & ≡\{(\kw{cons}~\nat) : (\nat→\List~\nat→\List~\nat)\}^P \\
- & ≡∀ n:\nat, \{(\kw{cons}~\nat~n) : \List~\nat→\List~\nat)\}^P \\
- & ≡∀ n:\nat, ∀ l:\List~\nat, \{(\kw{cons}~\nat~n~l) : \List~\nat)\}^P \\
- & ≡∀ n:\nat, ∀ l:\List~\nat,(P~(\kw{cons}~\nat~n~l)).
- \end{array}
+ .. math::
+ \{(\kw{nil}~\nat)\}^P ≡ \{(\kw{nil}~\nat) : (\List~\nat)\}^P ≡ (P~(\kw{nil}~\nat))
-Given some :math:`P` then :math:`\{(\kw{nil}~\nat)\}^P` represents the expected type of :math:`f_1` ,
-and :math:`\{(\kw{cons}~\nat)\}^P` represents the expected type of :math:`f_2`.
+ .. math::
+
+ \begin{array}{rl}
+ \{(\kw{cons}~\nat)\}^P & ≡\{(\kw{cons}~\nat) : (\nat→\List~\nat→\List~\nat)\}^P \\
+ & ≡∀ n:\nat, \{(\kw{cons}~\nat~n) : \List~\nat→\List~\nat)\}^P \\
+ & ≡∀ n:\nat, ∀ l:\List~\nat, \{(\kw{cons}~\nat~n~l) : \List~\nat)\}^P \\
+ & ≡∀ n:\nat, ∀ l:\List~\nat,(P~(\kw{cons}~\nat~n~l)).
+ \end{array}
+
+ Given some :math:`P` then :math:`\{(\kw{nil}~\nat)\}^P` represents the expected type of :math:`f_1` ,
+ and :math:`\{(\kw{cons}~\nat)\}^P` represents the expected type of :math:`f_2`.
.. _Typing-rule:
@@ -1486,6 +1501,7 @@ definition :math:`\ind{r}{Γ_I}{Γ_C}` with :math:`Γ_C = [c_1 :C_1 ;…;c_n :C_
.. example::
+
Below is a typing rule for the term shown in the previous example:
.. inference:: list example
@@ -1614,7 +1630,7 @@ then the recursive
arguments will correspond to :math:`T_i` in which one of the :math:`I_l` occurs.
The main rules for being structurally smaller are the following.
-Given a variable :math:`y` of type an inductive definition in a declaration
+Given a variable :math:`y` of an inductively defined type in a declaration
:math:`\ind{r}{Γ_I}{Γ_C}` where :math:`Γ_I` is :math:`[I_1 :A_1 ;…;I_k :A_k]`, and :math:`Γ_C` is
:math:`[c_1 :C_1 ;…;c_n :C_n ]`, the terms structurally smaller than :math:`y` are:
@@ -1626,7 +1642,7 @@ Given a variable :math:`y` of type an inductive definition in a declaration
Each :math:`f_i` corresponds to a type of constructor
:math:`C_q ≡ ∀ p_1 :P_1 ,…,∀ p_r :P_r , ∀ y_1 :B_1 , … ∀ y_k :B_k , (I~a_1 … a_k )`
and can consequently be written :math:`λ y_1 :B_1' . … λ y_k :B_k'. g_i`. (:math:`B_i'` is
- obtained from :math:`B_i` by substituting parameters variables) the variables
+ obtained from :math:`B_i` by substituting parameters for variables) the variables
:math:`y_j` occurring in :math:`g_i` corresponding to recursive arguments :math:`B_i` (the
ones in which one of the :math:`I_l` occurs) are structurally smaller than y.
@@ -1635,6 +1651,7 @@ The following definitions are correct, we enter them using the :cmd:`Fixpoint`
command and show the internal representation.
.. example::
+
.. coqtop:: all
Fixpoint plus (n m:nat) {struct n} : nat :=
@@ -1802,24 +1819,25 @@ definitions can be found in :cite:`Gimenez95b,Gim98,GimCas05`.
.. _The-Calculus-of-Inductive-Construction-with-impredicative-Set:
-The Calculus of Inductive Construction with impredicative Set
+The Calculus of Inductive Constructions with impredicative Set
-----------------------------------------------------------------
-|Coq| can be used as a type-checker for the Calculus of Inductive
+|Coq| can be used as a type checker for the Calculus of Inductive
Constructions with an impredicative sort :math:`\Set` by using the compiler
option ``-impredicative-set``. For example, using the ordinary `coqtop`
command, the following is rejected,
.. example::
+
.. coqtop:: all
Fail Definition id: Set := forall X:Set,X->X.
-while it will type-check, if one uses instead the `coqtop`
+while it will type check, if one uses instead the `coqtop`
``-impredicative-set`` option..
The major change in the theory concerns the rule for product formation
-in the sort Set, which is extended to a domain in any sort:
+in the sort :math:`\Set`, which is extended to a domain in any sort:
.. inference:: ProdImp
@@ -1832,11 +1850,11 @@ in the sort Set, which is extended to a domain in any sort:
This extension has consequences on the inductive definitions which are
allowed. In the impredicative system, one can build so-called *large
inductive definitions* like the example of second-order existential
-quantifier (exSet).
+quantifier (:g:`exSet`).
There should be restrictions on the eliminations which can be
-performed on such definitions. The eliminations rules in the
-impredicative system for sort Set become:
+performed on such definitions. The elimination rules in the
+impredicative system for sort :math:`\Set` become:
diff --git a/doc/sphinx/language/coq-library.rst b/doc/sphinx/language/coq-library.rst
index afb49413dd..9de30e2190 100644
--- a/doc/sphinx/language/coq-library.rst
+++ b/doc/sphinx/language/coq-library.rst
@@ -705,21 +705,29 @@ fixpoint equation can be proved.
Accessing the Type level
~~~~~~~~~~~~~~~~~~~~~~~~
-The basic library includes the definitions of the counterparts of some data-types and logical
-quantifiers at the ``Type``: level: negation, pair, and properties
-of ``identity``. This is the module ``Logic_Type.v``.
+The standard library includes ``Type`` level definitions of counterparts of some
+logic concepts and basic lemmas about them.
+
+The module ``Datatypes`` defines ``identity``, which is the ``Type`` level counterpart
+of equality:
+
+.. index::
+ single: identity (term)
+
+.. coqtop:: in
+
+ Inductive identity (A:Type) (a:A) : A -> Type :=
+ identity_refl : identity a a.
+
+Some properties of ``identity`` are proved in the module ``Logic_Type``, which also
+provides the definition of ``Type`` level negation:
.. index::
single: notT (term)
- single: prodT (term)
- single: pairT (term)
.. coqtop:: in
Definition notT (A:Type) := A -> False.
- Inductive prodT (A B:Type) : Type := pairT (_:A) (_:B).
-
-At the end, it defines data-types at the ``Type`` level.
Tactics
~~~~~~~
@@ -840,6 +848,7 @@ Notation Interpretation Precedence Associativity
.. example::
+
.. coqtop:: all reset
Require Import ZArith.
@@ -879,6 +888,7 @@ Notation Interpretation
=============== ===================
.. example::
+
.. coqtop:: all reset
Require Import Reals.
@@ -889,7 +899,7 @@ Notation Interpretation
Some tactics for real numbers
+++++++++++++++++++++++++++++
-In addition to the powerful ``ring``, ``field`` and ``fourier``
+In addition to the powerful ``ring``, ``field`` and ``lra``
tactics (see Chapter :ref:`tactics`), there are also:
.. tacn:: discrR
@@ -898,6 +908,7 @@ tactics (see Chapter :ref:`tactics`), there are also:
Proves that two real integer constants are different.
.. example::
+
.. coqtop:: all reset
Require Import DiscrR.
@@ -911,6 +922,7 @@ tactics (see Chapter :ref:`tactics`), there are also:
Allows unfolding the ``Rabs`` constant and splits corresponding conjunctions.
.. example::
+
.. coqtop:: all reset
Require Import Reals.
@@ -925,6 +937,7 @@ tactics (see Chapter :ref:`tactics`), there are also:
corresponding to the condition on each operand of the product.
.. example::
+
.. coqtop:: all reset
Require Import Reals.
diff --git a/doc/sphinx/language/gallina-extensions.rst b/doc/sphinx/language/gallina-extensions.rst
index c21d8d4ec8..0fbe7ac70b 100644
--- a/doc/sphinx/language/gallina-extensions.rst
+++ b/doc/sphinx/language/gallina-extensions.rst
@@ -23,8 +23,9 @@ expressions. In this sense, the :cmd:`Record` construction allows defining
.. _record_grammar:
.. productionlist:: `sentence`
- record : `record_keyword` `ident` [ `binders` ] [: `sort` ] := [ `ident` ] { [ `field` ; … ; `field` ] }.
+ record : `record_keyword` `record_body` with … with `record_body`
record_keyword : Record | Inductive | CoInductive
+ record_body : `ident` [ `binders` ] [: `sort` ] := [ `ident` ] { [ `field` ; … ; `field` ] }.
field : `ident` [ `binders` ] : `type` [ where `notation` ]
: | `ident` [ `binders` ] [: `type` ] := `term`
@@ -69,7 +70,9 @@ generates a variant type definition with just one constructor:
To build an object of type :n:`@ident`, one should provide the constructor
:n:`@ident₀` with the appropriate number of terms filling the fields of the record.
-.. example:: Let us define the rational :math:`1/2`:
+.. example::
+
+ Let us define the rational :math:`1/2`:
.. coqtop:: in
@@ -167,12 +170,13 @@ and the syntax `term.(@qualid` |term_1| |term_n| `)` to `@qualid` |term_1| `…`
In each case, `term` is the object projected and the
other arguments are the parameters of the inductive type.
+
.. note:: Records defined with the ``Record`` keyword are not allowed to be
recursive (references to the record's name in the type of its field
raises an error). To define recursive records, one can use the ``Inductive``
and ``CoInductive`` keywords, resulting in an inductive or co-inductive record.
- A *caveat*, however, is that records cannot appear in mutually inductive
- (or co-inductive) definitions.
+ Definition of mutal inductive or co-inductive records are also allowed, as long
+ as all of the types in the block are records.
.. note:: Induction schemes are automatically generated for inductive records.
Automatic generation of induction schemes for non-recursive records
@@ -208,7 +212,7 @@ During the definition of the one-constructor inductive definition, all
the errors of inductive definitions, as described in Section
:ref:`gallina-inductive-definitions`, may also occur.
-**See also** Coercions and records in Section :ref:`coercions-classes-as-records` of the chapter devoted to coercions.
+.. seealso:: Coercions and records in section :ref:`coercions-classes-as-records` of the chapter devoted to coercions.
.. _primitive_projections:
@@ -225,7 +229,7 @@ term constructor `r.(p)` representing a primitive projection `p` applied
to a record object `r` (i.e., primitive projections are always applied).
Even if the record type has parameters, these do not appear at
applications of the projection, considerably reducing the sizes of
-terms when manipulating parameterized records and typechecking time.
+terms when manipulating parameterized records and type checking time.
On the user level, primitive projections can be used as a replacement
for the usual defined ones, although there are a few notable differences.
@@ -324,7 +328,7 @@ into a sequence of match on simple patterns. Especially, a
construction defined using the extended match is generally printed
under its expanded form (see :opt:`Printing Matching`).
-See also: :ref:`extendedpatternmatching`.
+.. seealso:: :ref:`extendedpatternmatching`.
.. _if-then-else:
@@ -707,7 +711,7 @@ terminating functions.
`functional inversion` will not be available for the function.
-See also: :ref:`functional-scheme` and :tacn:`function induction`
+.. seealso:: :ref:`functional-scheme` and :tacn:`function induction`
Depending on the ``{…}`` annotation, different definition mechanisms are
used by ``Function``. A more precise description is given below.
@@ -779,7 +783,8 @@ Section :ref:`gallina-definitions`).
.. cmd:: Section @ident
- This command is used to open a section named `ident`.
+ This command is used to open a section named :token:`ident`.
+ Section names do not need to be unique.
.. cmd:: End @ident
@@ -1077,7 +1082,7 @@ The definition of ``N`` using the module type expression ``SIG`` with
Module N : SIG' := M.
-If we just want to be sure that the our implementation satisfies a
+If we just want to be sure that our implementation satisfies a
given module type without restricting the interface, we can use a
transparent constraint
@@ -1255,7 +1260,7 @@ identifiers qualid, i.e. as list of identifiers separated by dots (see
|Coq| library ``Arith`` is named ``Coq.Arith.Mult``. The identifier that starts
the name of a library is called a *library root*. All library files of
the standard library of |Coq| have the reserved root |Coq| but library
-file names based on other roots can be obtained by using |Coq| commands
+filenames based on other roots can be obtained by using |Coq| commands
(coqc, coqtop, coqdep, …) options ``-Q`` or ``-R`` (see :ref:`command-line-options`).
Also, when an interactive |Coq| session starts, a library of root ``Top`` is
started, unless option ``-top`` or ``-notop`` is set (see :ref:`command-line-options`).
@@ -1289,7 +1294,7 @@ short name (or even same partially qualified names as soon as the full
names are different).
Notice that the notion of absolute, partially qualified and short
-names also applies to library file names.
+names also applies to library filenames.
**Visibility**
@@ -1323,7 +1328,7 @@ accessible, absolute names can never be hidden.
Locate nat.
-See also: Commands :cmd:`Locate` and :cmd:`Locate Library`.
+.. seealso:: Commands :cmd:`Locate` and :cmd:`Locate Library`.
.. _libraries-and-filesystem:
@@ -1347,7 +1352,7 @@ folder ``path/fOO/Bar`` maps to ``Lib.fOO.Bar``. Subdirectories corresponding
to invalid |Coq| identifiers are skipped, and, by convention,
subdirectories named ``CVS`` or ``_darcs`` are skipped too.
-Thanks to this mechanism, .vo files are made available through the
+Thanks to this mechanism, ``.vo`` files are made available through the
logical name of the folder they are in, extended with their own
basename. For example, the name associated to the file
``path/fOO/Bar/File.vo`` is ``Lib.fOO.Bar.File``. The same caveat applies for
@@ -1358,17 +1363,17 @@ wrong loadpath afterwards.
Some folders have a special status and are automatically put in the
path. |Coq| commands associate automatically a logical path to files in
the repository trees rooted at the directory from where the command is
-launched, coqlib/user-contrib/, the directories listed in the
-`$COQPATH`, `${XDG_DATA_HOME}/coq/` and `${XDG_DATA_DIRS}/coq/`
-environment variables (see`http://standards.freedesktop.org/basedir-
-spec/basedir-spec-latest.html`_) with the same physical-to-logical
-translation and with an empty logical prefix.
+launched, ``coqlib/user-contrib/``, the directories listed in the
+``$COQPATH``, ``${XDG_DATA_HOME}/coq/`` and ``${XDG_DATA_DIRS}/coq/``
+environment variables (see `XDG base directory specification
+<http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html>`_)
+with the same physical-to-logical translation and with an empty logical prefix.
The command line option ``-R`` is a variant of ``-Q`` which has the strictly
same behavior regarding loadpaths, but which also makes the
corresponding ``.vo`` files available through their short names in a way
not unlike the ``Import`` command (see :ref:`here <import_qualid>`). For instance, ``-R`` `path` ``Lib``
-associates to the ``filepath/fOO/Bar/File.vo`` the logical name
+associates to the file path `path`\ ``/path/fOO/Bar/File.vo`` the logical name
``Lib.fOO.Bar.File``, but allows this file to be accessed through the
short names ``fOO.Bar.File,Bar.File`` and ``File``. If several files with
identical base name are present in different subdirectories of a
@@ -1509,7 +1514,8 @@ says that the implicit argument is maximally inserted.
Each implicit argument can be declared to have to be inserted maximally or non
maximally. This can be governed argument per argument by the command
:cmd:`Arguments (implicits)` or globally by the :opt:`Maximal Implicit Insertion` option.
-See also :ref:`displaying-implicit-args`.
+
+.. seealso:: :ref:`displaying-implicit-args`.
Casual use of implicit arguments
@@ -1846,15 +1852,15 @@ are named as expected.
.. example:: (continued)
-.. coqtop:: all
+ .. coqtop:: all
- Arguments p [s t] _ [u] _: rename.
+ Arguments p [s t] _ [u] _: rename.
- Check (p r1 (u:=c)).
+ Check (p r1 (u:=c)).
- Check (p (s:=a) (t:=b) r1 (u:=c) r2).
+ Check (p (s:=a) (t:=b) r1 (u:=c) r2).
- Fail Arguments p [s t] _ [w] _ : assert.
+ Fail Arguments p [s t] _ [w] _ : assert.
.. _displaying-implicit-args:
@@ -1882,7 +1888,7 @@ arguments that are not detected as strict implicit arguments. This
“defensive” mode can quickly make the display cumbersome so this can
be deactivated by turning this option off.
-See also: :opt:`Printing All`.
+.. seealso:: :opt:`Printing All`.
Interaction with subtyping
~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1932,7 +1938,7 @@ in :ref:`canonicalstructures`; here only a simple example is given.
Assume that :token:`qualid` denotes an object ``(Build_struct`` |c_1| … |c_n| ``)`` in the
structure :g:`struct` of which the fields are |x_1|, …, |x_n|.
Then, each time an equation of the form ``(``\ |x_i| ``_)`` |eq_beta_delta_iota_zeta| |c_i| has to be
- solved during the type-checking process, :token:`qualid` is used as a solution.
+ solved during the type checking process, :token:`qualid` is used as a solution.
Otherwise said, :token:`qualid` is canonically used to extend the field |c_i|
into a complete structure built on |c_i|.
@@ -2226,7 +2232,7 @@ existential variable used in the same context as its context of definition is wr
Check (fun x y => _) 0 1.
Existential variables can be named by the user upon creation using
-the syntax ``?``\ `ident`. This is useful when the existential
+the syntax :n:`?[@ident]`. This is useful when the existential
variable needs to be explicitly handled later in the script (e.g.
with a named-goal selector, see :ref:`goal-selectors`).
diff --git a/doc/sphinx/language/gallina-specification-language.rst b/doc/sphinx/language/gallina-specification-language.rst
index c26ae2a93b..075235a8e2 100644
--- a/doc/sphinx/language/gallina-specification-language.rst
+++ b/doc/sphinx/language/gallina-specification-language.rst
@@ -38,6 +38,7 @@ At the end, the notation “``[entry sep … sep entry]``” stands for a
possibly empty sequence of expressions parsed by the “``entry``” entry,
separated by the literal “``sep``”.
+.. _lexical-conventions:
Lexical conventions
===================
@@ -102,7 +103,7 @@ Special tokens
! % & && ( () ) * + ++ , - -> . .( ..
/ /\ : :: :< := :> ; < <- <-> <: <= <> =
=> =_D > >-> >= ? ?= @ [ \/ ] ^ { | |-
- || } ~
+ || } ~ #[
Lexical ambiguities are resolved according to the “longest match”
rule: when a sequence of non alphanumerical characters can be
@@ -494,6 +495,7 @@ The Vernacular
==============
.. productionlist:: coq
+ decorated-sentence : [`decoration`] `sentence`
sentence : `assumption`
: | `definition`
: | `inductive`
@@ -522,6 +524,11 @@ The Vernacular
proof : Proof . … Qed .
: | Proof . … Defined .
: | Proof . … Admitted .
+ decoration : #[ `attributes` ]
+ attributes : [`attribute`, … , `attribute`]
+ attribute : `ident`
+ :| `ident` = `string`
+ :| `ident` ( `attributes` )
.. todo:: This use of … in this grammar is inconsistent
What about removing the proof part of this grammar from this chapter
@@ -533,6 +540,9 @@ commands of Gallina. A sentence of the vernacular language, like in
many natural languages, begins with a capital letter and ends with a
dot.
+Sentences may be *decorated* with so-called *attributes*,
+which are described in the corresponding section (:ref:`gallina-attributes`).
+
The different kinds of command are described hereafter. They all suppose
that the terms occurring in the sentences are well-typed.
@@ -748,6 +758,7 @@ Simple inductive types
the case of annotated inductive types — cf. next section).
.. example::
+
The set of natural numbers is defined as:
.. coqtop:: all
@@ -905,6 +916,32 @@ Parametrized inductive types
sort for the inductive definition and will produce a less convenient
rule for case elimination.
+.. opt:: Uniform Inductive Parameters
+
+ When this option is set (it is off by default),
+ inductive definitions are abstracted over their parameters
+ before type checking constructors, allowing to write:
+
+ .. coqtop:: all undo
+
+ Set Uniform Inductive Parameters.
+ Inductive list3 (A:Set) : Set :=
+ | nil3 : list3
+ | cons3 : A -> list3 -> list3.
+
+ This behavior is essentially equivalent to starting a new section
+ and using :cmd:`Context` to give the uniform parameters, like so
+ (cf. :ref:`section-mechanism`):
+
+ .. coqtop:: all undo
+
+ Section list3.
+ Context (A:Set).
+ Inductive list3 : Set :=
+ | nil3 : list3
+ | cons3 : A -> list3 -> list3.
+ End list3.
+
.. seealso::
Section :ref:`inductive-definitions` and the :tacn:`induction` tactic.
@@ -940,6 +977,7 @@ Mutually defined inductive types
reason, the parameters must be strictly the same for each inductive types.
.. example::
+
The typical example of a mutual inductive data type is the one for trees and
forests. We assume given two types :g:`A` and :g:`B` as variables. It can
be declared the following way.
@@ -1012,6 +1050,7 @@ of the type.
For co-inductive types, the only elimination principle is case analysis.
.. example::
+
An example of a co-inductive type is the type of infinite sequences of
natural numbers, usually called streams.
@@ -1031,6 +1070,7 @@ Definition of co-inductive predicates and blocks of mutually
co-inductive definitions are also allowed.
.. example::
+
An example of a co-inductive predicate is the extensional equality on
streams:
@@ -1084,7 +1124,7 @@ constructions.
arguments, and this choice influences the reduction of the fixpoint.
Hence an explicit annotation must be used if the leftmost decreasing
argument is not the desired one. Writing explicit annotations can also
- speed up type-checking of large mutual fixpoints.
+ speed up type checking of large mutual fixpoints.
+ In order to keep the strong normalization property, the fixed point
reduction will only be performed when the argument in position of the
@@ -1093,6 +1133,7 @@ constructions.
.. example::
+
One can define the addition function as :
.. coqtop:: all
@@ -1165,6 +1206,7 @@ constructions.
inductive types.
.. example::
+
The size of trees and forests can be defined the following way:
.. coqtop:: all
@@ -1361,3 +1403,59 @@ using the keyword :cmd:`Qed`.
.. [2]
Except if the inductive type is empty in which case there is no
equation that can be used to infer the return type.
+
+.. _gallina-attributes:
+
+Attributes
+-----------
+
+Any vernacular command can be decorated with a list of attributes, enclosed
+between ``#[`` (hash and opening square bracket) and ``]`` (closing square bracket)
+and separated by commas ``,``.
+
+Each attribute has a name (an identifier) and may have a value.
+A value is either a :token:`string` (in which case it is specified with an equal ``=`` sign),
+or a list of attributes, enclosed within brackets.
+
+Currently,
+the following attributes names are recognized:
+
+``monomorphic``, ``polymorphic``
+ Take no value, analogous to the ``Monomorphic`` and ``Polymorphic`` flags
+ (see :ref:`polymorphicuniverses`).
+
+``program``
+ Takes no value, analogous to the ``Program`` flag
+ (see :ref:`programs`).
+
+``global``, ``local``
+ Take no value, analogous to the ``Global`` and ``Local`` flags
+ (see :ref:`controlling-locality-of-commands`).
+
+``deprecated``
+ Takes as value the optional attributes ``since`` and ``note``;
+ both have a string value.
+
+ This attribute can trigger the following warnings:
+
+ .. warn:: Tactic @qualid is deprecated since @string. @string.
+
+ .. warn:: Tactic Notation @qualid is deprecated since @string. @string.
+
+Here are a few examples:
+
+.. coqtop:: all reset
+
+ From Coq Require Program.
+ #[program] Definition one : nat := S _.
+ Next Obligation.
+ exact O.
+ Defined.
+
+ #[deprecated(since="8.9.0", note="Use idtac instead.")]
+ Ltac foo := idtac.
+
+ Goal True.
+ Proof.
+ now foo.
+ Abort.
diff --git a/doc/sphinx/practical-tools/coq-commands.rst b/doc/sphinx/practical-tools/coq-commands.rst
index ad1f0caa60..9498f37c7e 100644
--- a/doc/sphinx/practical-tools/coq-commands.rst
+++ b/doc/sphinx/practical-tools/coq-commands.rst
@@ -25,7 +25,7 @@ In the interactive mode, also known as the |Coq| toplevel, the user can
develop his theories and proofs step by step. The |Coq| toplevel is run
by the command ``coqtop``.
-They are two different binary images of |Coq|: the byte-code one and the
+There are two different binary images of |Coq|: the byte-code one and the
native-code one (if OCaml provides a native-code compiler for
your platform, which is supposed in the following). By default,
``coqtop`` executes the native-code version; run ``coqtop.byte`` to get
@@ -43,10 +43,11 @@ The ``coqc`` command takes a name *file* as argument. Then it looks for a
vernacular file named *file*.v, and tries to compile it into a
*file*.vo file (See :ref:`compiled-files`).
-.. caution:: The name *file* should be a
- regular |Coq| identifier, as defined in Section :ref:'TODO-1.1'. It should contain
- only letters, digits or underscores (_). For instance, ``/bar/foo/toto.v`` is valid, but
- ``/bar/foo/to-to.v`` is invalid.
+.. caution::
+
+ The name *file* should be a regular |Coq| identifier as defined in Section :ref:`lexical-conventions`.
+ It should contain only letters, digits or underscores (_). For example ``/bar/foo/toto.v`` is valid,
+ but ``/bar/foo/to-to.v`` is not.
Customization at launch time
@@ -59,8 +60,8 @@ When |Coq| is launched, with either ``coqtop`` or ``coqc``, the
resource file ``$XDG_CONFIG_HOME/coq/coqrc.xxx``, if it exists, will
be implicitly prepended to any document read by Coq, whether it is an
interactive session or a file to compile. Here, ``$XDG_CONFIG_HOME``
-is the configuration directory of the user (by default its home
-directory ``~/.config``) and ``xxx`` is the version number (e.g. 8.8). If
+is the configuration directory of the user (by default it's ``~/.config``)
+and ``xxx`` is the version number (e.g. 8.8). If
this file is not found, then the file ``$XDG_CONFIG_HOME/coqrc`` is
searched. If not found, it is the file ``~/.coqrc.xxx`` which is searched,
and, if still not found, the file ``~/.coqrc``. If the latter is also
@@ -89,8 +90,8 @@ not set, they look for the commands in the executable path.
The ``$COQ_COLORS`` environment variable can be used to specify the set
of colors used by ``coqtop`` to highlight its output. It uses the same
syntax as the ``$LS_COLORS`` variable from GNU’s ls, that is, a colon-separated
-list of assignments of the form ``name=``:n:``{*; attr}`` where
-``name`` is the name of the corresponding highlight tag and each ``attrᵢ`` is an
+list of assignments of the form :n:`name={*; attr}` where
+``name`` is the name of the corresponding highlight tag and each ``attr`` is an
ANSI escape code. The list of highlight tags can be retrieved with the
``-list-tags`` command-line option of ``coqtop``.
@@ -103,10 +104,14 @@ The following command-line options are recognized by the commands ``coqc``
and ``coqtop``, unless stated otherwise:
:-I *directory*, -include *directory*: Add physical path *directory*
- to the OCaml loadpath. See also: :ref:`names-of-libraries` and the
- command Declare ML Module Section :ref:`compiled-files`.
+ to the OCaml loadpath.
+
+ .. seealso::
+
+ :ref:`names-of-libraries` and the
+ command Declare ML Module Section :ref:`compiled-files`.
:-Q *directory* dirpath: Add physical path *directory* to the list of
- directories where |Coq| looks for a file and bind it to the the logical
+ directories where |Coq| looks for a file and bind it to the logical
directory *dirpath*. The subdirectory structure of *directory* is
recursively available from |Coq| using absolute names (extending the
dirpath prefix) (see Section :ref:`qualified-names`).Note that only those
@@ -114,14 +119,17 @@ and ``coqtop``, unless stated otherwise:
an :n:`@ident` are taken into account. Conversely, the
underlying file systems or operating systems may be more restrictive
than |Coq|. While Linux’s ext4 file system supports any |Coq| recursive
- layout (within the limit of 255 bytes per file name), the default on
+ layout (within the limit of 255 bytes per filename), the default on
NTFS (Windows) or HFS+ (MacOS X) file systems is on the contrary to
disallow two files differing only in the case in the same directory.
- See also: Section :ref:`names-of-libraries`.
+
+ .. seealso:: Section :ref:`names-of-libraries`.
:-R *directory* dirpath: Do as -Q *directory* dirpath but make the
subdirectory structure of *directory* recursively visible so that the
recursive contents of physical *directory* is available from |Coq| using
- short or partially qualified names. See also: Section :ref:`names-of-libraries`.
+ short or partially qualified names.
+
+ .. seealso:: Section :ref:`names-of-libraries`.
:-top dirpath: Set the toplevel module name to dirpath instead of Top.
Not valid for `coqc` as the toplevel module name is inferred from the
name of the output file.
@@ -140,15 +148,15 @@ and ``coqtop``, unless stated otherwise:
:-l *file*, -load-vernac-source *file*: Load and execute the |Coq|
script from *file.v*.
:-lv *file*, -load-vernac-source-verbose *file*: Load and execute the
- |Coq| script from *file.v*. Output its content on the standard input as
+ |Coq| script from *file.v*. Write its contents to the standard output as
it is executed.
:-load-vernac-object dirpath: Load |Coq| compiled library dirpath. This
is equivalent to runningRequire dirpath.
:-require dirpath: Load |Coq| compiled library dirpath and import it.
This is equivalent to running Require Import dirpath.
:-batch: Exit just after argument parsing. Available for `coqtop` only.
-:-compile *file.v*: Compile file *file.v* into *file.vo*. This options
- imply -batch (exit just after argument parsing). It is available only
+:-compile *file.v*: Compile file *file.v* into *file.vo*. This option
+ implies -batch (exit just after argument parsing). It is available only
for `coqtop`, as this behavior is the purpose of `coqc`.
:-compile-verbose *file.v*: Same as -compile but also output the
content of *file.v* as it is compiled.
@@ -167,11 +175,16 @@ and ``coqtop``, unless stated otherwise:
:-emacs, -ide-slave: Start a special toplevel to communicate with a
specific IDE.
:-impredicative-set: Change the logical theory of |Coq| by declaring the
- sort Set impredicative. Warning: This is known to be inconsistent with some
- standard axioms of classical mathematics such as the functional
- axiom of choice or the principle of description.
-:-type-in-type: Collapse the universe hierarchy of |Coq|. Warning: This makes the logic
- inconsistent.
+ sort Set impredicative.
+
+ .. warning::
+
+ This is known to be inconsistent with some
+ standard axioms of classical mathematics such as the functional
+ axiom of choice or the principle of description.
+:-type-in-type: Collapse the universe hierarchy of |Coq|.
+
+ .. warning:: This makes the logic inconsistent.
:-mangle-names *ident*: Experimental: Do not depend on this option. Replace
Coq's auto-generated name scheme with names of the form *ident0*, *ident1*,
etc. The command ``Set Mangle Names`` turns the behavior on in a document,
@@ -207,7 +220,7 @@ The ``coqchk`` command takes a list of library paths as argument, described eith
by their logical name or by their physical filename, hich must end in ``.vo``. The
corresponding compiled libraries (``.vo`` files) are searched in the path,
recursively processing the libraries they depend on. The content of all these
-libraries is then type-checked. The effect of ``coqchk`` is only to return with
+libraries is then type checked. The effect of ``coqchk`` is only to return with
normal exit code in case of success, and with positive exit code if an error has
been found. Error messages are not deemed to help the user understand what is
wrong. In the current version, it does not modify the compiled libraries to mark
@@ -237,7 +250,7 @@ relative paths in object files ``-Q`` and ``-R`` have exactly the same meaning.
unless explicitly required.
:-o: At exit, print a summary about the context. List the names of all
assumptions and variables (constants without body).
-:-silent: Do not write progress information in standard output.
+:-silent: Do not write progress information to the standard output.
Environment variable ``$COQLIB`` can be set to override the location of
the standard library.
@@ -247,15 +260,15 @@ the following: assuming that ``coqchk`` is called with argument ``M``, option
``-norec N``, and ``-admit A``. Let us write :math:`\overline{S}` for the
set of reflexive transitive dependencies of set :math:`S`. Then:
-+ Modules :math:`C = \overline{M} \backslash \overline{A} \cup M \cup N` are loaded and type-checked before being added
++ Modules :math:`C = \overline{M} \backslash \overline{A} \cup M \cup N` are loaded and type checked before being added
to the context.
+ And :math:`M \cup N \backslash C` is the set of modules that are loaded and added to the
- context without type-checking. Basic integrity checks (checksums) are
+ context without type checking. Basic integrity checks (checksums) are
nonetheless performed.
-As a rule of thumb, the -admit can be used to tell that some libraries
+As a rule of thumb, -admit can be used to tell Coq that some libraries
have already been checked. So ``coqchk A B`` can be split in ``coqchk A`` &&
-``coqchk B -admit A`` without type-checking any definition twice. Of
+``coqchk B -admit A`` without type checking any definition twice. Of
course, the latter is slightly slower since it makes more disk access.
It is also less secure since an attacker might have replaced the
compiled library ``A`` after it has been read by the first command, but
diff --git a/doc/sphinx/practical-tools/coqide.rst b/doc/sphinx/practical-tools/coqide.rst
index f9903e6104..bc6a074a27 100644
--- a/doc/sphinx/practical-tools/coqide.rst
+++ b/doc/sphinx/practical-tools/coqide.rst
@@ -12,7 +12,7 @@ file, executing corresponding commands or undoing them respectively.
|CoqIDE| is run by typing the command `coqide` on the command line.
Without argument, the main screen is displayed with an “unnamed
-buffer”, and with a file name as argument, another buffer displaying
+buffer”, and with a filename as argument, another buffer displaying
the contents of that file. Additionally, `coqide` accepts the same
options as `coqtop`, given in :ref:`thecoqcommands`, the ones having obviously
no meaning for |CoqIDE| being ignored.
@@ -27,7 +27,7 @@ is shown in the figure :ref:`CoqIDE main screen <coqide_mainscreen>`.
At the top is a menu bar, and a tool bar
below it. The large window on the left is displaying the various
*script buffers*. The upper right window is the *goal window*, where
-goals to prove are displayed. The lower right window is the *message
+goals to be proven are displayed. The lower right window is the *message
window*, where various messages resulting from commands are displayed.
At the bottom is the status bar.
@@ -62,8 +62,8 @@ In the figure :ref:`CoqIDE main screen <coqide_mainscreen>`,
the running buffer is `Fermat.v`, all commands until
the ``Theorem`` have been already executed, and the user tried to go
forward executing ``Induction n``. That command failed because no such
-tactic exists (tactics are now in lowercase…), and the wrong word is
-underlined.
+tactic exists (names of standard tactics are written in lowercase),
+and the failing command is underlined.
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
@@ -82,8 +82,8 @@ background in the error background color (pink by default). The same
characterization of error-handling applies when running several commands using
the "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
+If you ever try to execute a command that runs for a long time
+and would like to abort it before it terminates, you may
use the interrupt button (the white cross on a red circle).
There are other buttons on the |CoqIDE| toolbar: a button to save the running
@@ -92,7 +92,7 @@ buffers (left and right arrows); an "information" button; and a "gears" button.
The "information" button is described in Section :ref:`try-tactics-automatically`.
-The "gears" button submits proof terms to the |Coq| kernel for type-checking.
+The "gears" button submits proof terms to the |Coq| kernel for type checking.
When |Coq| uses asynchronous processing (see Chapter :ref:`asynchronousandparallelproofprocessing`),
proofs may have been completed without kernel-checking of generated proof terms.
The presence of unchecked proof terms is indicated by ``Qed`` statements that
@@ -141,11 +141,10 @@ Vernacular commands, templates
The Templates menu allows using shortcuts to insert vernacular
commands. This is a nice way to proceed if you are not sure of the
-spelling of the command you want.
+syntax of the command you want.
-Moreover, this menu offers some *templates* which will automatic
-insert a complex command like ``Fixpoint`` with a convenient shape for its
-arguments.
+Moreover, from this menu you can automatically insert templates of complex
+commands like ``Fixpoint`` that you can conveniently fill afterwards.
Queries
------------
@@ -177,7 +176,7 @@ The `Compile` menu offers direct commands to:
Customizations
-------------------
-You may customize your environment using menu Edit/Preferences. A new
+You may customize your environment using the menu Edit/Preferences. A new
window will be displayed, with several customization sections
presented as a notebook.
@@ -189,7 +188,7 @@ automatic saving of files, by periodically saving the contents into
files named `#f#` for each opened file `f`. You may also activate the
*revert* feature: in case a opened file is modified on the disk by a
third party, |CoqIDE| may read it again for you. Note that in the case
-you edited that same file, you will be prompt to choose to either
+you edited that same file, you will be prompted to choose to either
discard your changes or not. The File charset encoding choice is
described below in :ref:`character-encoding-saved-files`.
@@ -209,7 +208,7 @@ Notice that these settings are saved in the file `.coqiderc` of your
home directory.
A Gtk2 accelerator keymap is saved under the name `.coqide.keys`. It
-is not recommanded to edit this file manually: to modify a given menu
+is not recommended to edit this file manually: to modify a given menu
shortcut, go to the corresponding menu item without releasing the
mouse button, press the key you want for the new shortcut, and release
the mouse button afterwards. If your system does not allow it, you may
@@ -240,14 +239,14 @@ mathematical symbols ∀ and ∃, you may define:
There exists a small set of such notations already defined, in the
file `utf8.v` of Coq library, so you may enable them just by
-``Require utf8`` inside |CoqIDE|, or equivalently, by starting |CoqIDE| with
-``coqide -l utf8``.
+``Require Import Unicode.Utf8`` inside |CoqIDE|, or equivalently,
+by starting |CoqIDE| with ``coqide -l utf8``.
However, there are some issues when using such Unicode symbols: you of
course need to use a character font which supports them. In the Fonts
section of the preferences, the Preview line displays some Unicode
symbols, so you could figure out if the selected font is OK. Related
-to this, one thing you may need to do is choose whether GTK+ should
+to this, one thing you may need to do is choosing whether GTK+ should
use antialiased fonts or not, by setting the environment variable
`GDK_USE_XFT` to 1 or 0 respectively.
diff --git a/doc/sphinx/practical-tools/utilities.rst b/doc/sphinx/practical-tools/utilities.rst
index 5dba92429e..218a19c2e5 100644
--- a/doc/sphinx/practical-tools/utilities.rst
+++ b/doc/sphinx/practical-tools/utilities.rst
@@ -43,7 +43,7 @@ Building a |Coq| project with coq_makefile
The majority of |Coq| projects are very similar: a collection of ``.v``
files and eventually some ``.ml`` ones (a |Coq| plugin). The main piece of
metadata needed in order to build the project are the command line
-options to ``coqc`` (e.g. ``-R``, ``-I``, see also: Section
+options to ``coqc`` (e.g. ``-R``, ``-I``, see also: section
:ref:`command-line-options`). Collecting the list of files and options is the job
of the ``_CoqProject`` file.
@@ -107,7 +107,7 @@ decide how to build them. In particular:
The use of ``.mlpack`` files has to be preferred over ``.mllib`` files,
since it results in a “packed” plugin: All auxiliary modules (as
-``Baz`` and ``Bazaux``) are hidden inside the plugin’s “name space”
+``Baz`` and ``Bazaux``) are hidden inside the plugin’s "namespace"
(``Qux_plugin``). This reduces the chances of begin unable to load two
distinct plugins because of a clash in their auxiliary module names.
@@ -218,6 +218,7 @@ file timing data:
On ``Mac OS``, this works best if you’ve installed ``gnu-time``.
.. example::
+
For example, the output of ``make TIMED=1`` may look like
this:
@@ -295,6 +296,7 @@ file timing data:
files which take effectively no time to compile.
.. example::
+
For example, the output table from
``make print-pretty-timed-diff`` may look like this:
@@ -318,6 +320,7 @@ line timing data:
line-by-line timing information.
.. example::
+
For example, running ``make all TIMING=1`` may result in a file like this:
::
@@ -345,6 +348,7 @@ line timing data:
This target requires python to build the table.
.. example::
+
For example, running ``print-pretty-single-time-diff`` might give a table like this:
::
@@ -434,7 +438,7 @@ To build, say, two targets foo.vo and bar.vo in parallel one can use
For users of coq_makefile with version < 8.7
- + Support for “sub-directory” is deprecated. To perform actions before
+ + Support for "subdirectory" is deprecated. To perform actions before
or after the build (like invoking ``make`` on a subdirectory) one can hook
in pre-all and post-all extension points.
+ ``-extra-phony`` and ``-extra`` are deprecated. To provide additional target
@@ -442,10 +446,10 @@ To build, say, two targets foo.vo and bar.vo in parallel one can use
-Modules dependencies
+Module dependencies
--------------------
-In order to compute modules dependencies (so to use ``make``), |Coq| comes
+In order to compute module dependencies (so to use ``make``), |Coq| comes
with an appropriate tool, ``coqdep``.
``coqdep`` computes inter-module dependencies for |Coq| and |OCaml|
@@ -460,7 +464,7 @@ command ``Declare ML Module``.
Dependencies of |OCaml| modules are computed by looking at
`open` commands and the dot notation *module.value*. However, this is
done approximately and you are advised to use ``ocamldep`` instead for the
-|OCaml| modules dependencies.
+|OCaml| module dependencies.
See the man page of ``coqdep`` for more details and options.
@@ -478,9 +482,9 @@ coqdoc is a documentation tool for the proof assistant |Coq|, similar to
``javadoc`` or ``ocamldoc``. The task of coqdoc is
-#. to produce a nice |Latex| and/or HTML document from the |Coq|
- sources, readable for a human and not only for the proof assistant;
-#. to help the user navigating in his own (or third-party) sources.
+#. to produce a nice |Latex| and/or HTML document from |Coq| source files,
+ readable for a human and not only for the proof assistant;
+#. to help the user navigate his own (or third-party) sources.
@@ -491,7 +495,7 @@ Documentation is inserted into |Coq| files as *special comments*. Thus
your files will compile as usual, whether you use coqdoc or not. coqdoc
presupposes that the given |Coq| files are well-formed (at least
lexically). Documentation starts with ``(**``, followed by a space, and
-ends with the pending ``*)``. The documentation format is inspired by Todd
+ends with ``*)``. The documentation format is inspired by Todd
A. Coram’s *Almost Free Text (AFT)* tool: it is mainly ``ASCII`` text with
some syntax-light controls, described below. coqdoc is robust: it
shouldn’t fail, whatever the input is. But remember: “garbage in,
@@ -507,7 +511,7 @@ quoted code (thus you can quote a term like ``fun x => u`` by writing ``[fun
x => u]``). Inside quotations, the code is pretty-printed in the same
way as it is in code parts.
-Pre-formatted vernacular is enclosed by ``[[`` and ``]]``. The former must be
+Preformatted vernacular is enclosed by ``[[`` and ``]]``. The former must be
followed by a newline and the latter must follow a newline.
@@ -533,7 +537,7 @@ or
It gives the |Latex| and HTML texts to be produced for the given |Coq|
-token. One of the |Latex| or HTML text may be omitted, causing the
+token. Either the |Latex| or the HTML rule may be omitted, causing the
default pretty-printing to be used for this token.
The printing for one token can be removed with
@@ -546,12 +550,12 @@ The printing for one token can be removed with
Initially, the pretty-printing table contains the following mapping:
-==== === ==== ===== === ==== ==== ===
-`->` → `<-` ← `*` ×
-`<=` ≤ `>=` ≥ `=>` ⇒
-`<>` ≠ `<->` ↔ `|-` ⊢
-`\/` ∨ `/\\` ∧ `~` ¬
-==== === ==== ===== === ==== ==== ===
+===== === ==== ===== === ==== ==== ===
+`->` → `<-` ← `*` ×
+`<=` ≤ `>=` ≥ `=>` ⇒
+`<>` ≠ `<->` ↔ `|-` ⊢
+`\\/` ∨ `/\\` ∧ `~` ¬
+===== === ==== ===== === ==== ==== ===
Any of these can be overwritten or suppressed using the printing
commands.
@@ -573,10 +577,9 @@ commands.
Sections
++++++++
-Sections are introduced by 1 to 4 leading stars (i.e. at the beginning
-of the line) followed by a space. One star is a section, two stars a
-sub-section, etc. The section title is given on the remaining of the
-line.
+Sections are introduced by 1 to 4 asterisks at the beginning of a line
+followed by a space and the title of the section. One asterisk is a section,
+two a subsection, etc.
.. example::
@@ -624,7 +627,7 @@ More than 4 leading dashes produce a horizontal rule.
Emphasis.
+++++++++
-Text can be italicized by placing it in underscores. A non-identifier
+Text can be italicized by enclosing it in underscores. A non-identifier
character must precede the leading underscore and follow the trailing
underscore, so that uses of underscores in names aren’t mistaken for
emphasis. Usually, these are spaces or punctuation.
@@ -679,16 +682,16 @@ Hyperlinks can be inserted into the HTML output, so that any
identifier is linked to the place of its definition.
``coqc file.v`` automatically dumps localization information in
-``file.glob`` or appends it to a file specified using option ``--dump-glob
+``file.glob`` or appends it to a file specified using the option ``--dump-glob
file``. Take care of erasing this global file, if any, when starting
the whole compilation process.
Then invoke coqdoc or ``coqdoc --glob-from file`` to tell coqdoc to look
-for name resolutions into the file ``file`` (it will look in ``file.glob``
+for name resolutions in the file ``file`` (it will look in ``file.glob``
by default).
-Identifiers from the |Coq| standard library are linked to the Coq web
-site at `<http://coq.inria.fr/library/>`_. This behavior can be changed
+Identifiers from the |Coq| standard library are linked to the Coq website
+`<http://coq.inria.fr/library/>`_. This behavior can be changed
using command line options ``--no-externals`` and ``--coqlib``; see below.
@@ -731,12 +734,12 @@ file (even if it starts with a ``-``). |Coq| files are identified by the
suffixes ``.v`` and ``.g`` and |Latex| files by the suffix ``.tex``.
-:HTML output: This is the default output. One HTML file is created for
+:HTML output: This is the default output format. One HTML file is created for
each |Coq| file given on the command line, together with a file
``index.html`` (unless ``option-no-index is passed``). The HTML pages use a
style sheet named ``style.css``. Such a file is distributed with coqdoc.
:|Latex| output: A single |Latex| file is created, on standard
- output. It can be redirected to a file with option ``-o``. The order of
+ output. It can be redirected to a file using the option ``-o``. The order of
files on the command line is kept in the final document. |Latex|
files given on the command line are copied ‘as is’ in the final
document . DVI and PostScript can be produced directly with the
@@ -762,15 +765,15 @@ Command line options
:-o file, --output file: Redirect the output into the file ‘file’
(meaningless with ``-html``).
:-d dir, --directory dir: Output files into directory ‘dir’ instead of
- current directory (option ``-d`` does not change the filename specified
- with option ``-o``, if any).
+ the current directory (option ``-d`` does not change the filename specified
+ with the option ``-o``, if any).
:--body-only: Suppress the header and trailer of the final document.
Thus, you can insert the resulting document into a larger one.
:-p string, --preamble string: Insert some material in the |Latex|
preamble, right before ``\begin{document}`` (meaningless with ``-html``).
:--vernac-file file,--tex-file file: Considers the file ‘file’
respectively as a ``.v`` (or ``.g``) file or a ``.tex`` file.
- :--files-from file: Read file names to process in file ‘file’ as if
+ :--files-from file: Read filenames to be processed from the file ‘file’ as if
they were given on the command line. Useful for program sources split
up into several directories.
:-q, --quiet: Be quiet. Do not print anything except errors.
@@ -781,7 +784,7 @@ Command line options
**Index options**
- Default behavior is to build an index, for the HTML output only,
+ The default behavior is to build an index, for the HTML output only,
into ``index.html``.
:--no-index: Do not output the index.
@@ -802,7 +805,7 @@ Command line options
contents.
-**Hyperlinks options**
+**Hyperlink options**
:--glob-from file: Make references using |Coq| globalizations from file
file. (Such globalizations are obtained with Coq option ``-dump-glob``).
@@ -858,9 +861,9 @@ Command line options
The behavior of options ``-g`` and ``-l`` can be locally overridden using the
``(* begin show *) … (* end show *)`` environment (see above).
- There are a few options to drive the parsing of comments:
+ There are a few options that control the parsing of comments:
- :--parse-comments: Parses regular comments delimited by ``(*`` and ``*)`` as
+ :--parse-comments: Parse regular comments delimited by ``(*`` and ``*)`` as
well. They are typeset inline.
:--plain-comments: Do not interpret comments, simply copy them as
plain-text.
@@ -870,7 +873,7 @@ Command line options
**Language options**
- Default behavior is to assume ASCII 7 bits input files.
+ The default behavior is to assume ASCII 7 bit input files.
:-latin1, --latin1: Select ISO-8859-1 input files. It is equivalent to
--inputenc latin1 --charset iso-8859-1.
@@ -935,7 +938,7 @@ macros:
Embedded Coq phrases inside |Latex| documents
---------------------------------------------
-When writing a documentation about a proof development, one may want
+When writing documentation about a proof development, one may want
to insert |Coq| phrases inside a |Latex| document, possibly together
with the corresponding answers of the system. We provide a mechanical
way to process such |Coq| phrases embedded in |Latex| files: the ``coq-tex``
@@ -950,71 +953,10 @@ There are options to produce the |Coq| parts in smaller font, italic,
between horizontal rules, etc. See the man page of ``coq-tex`` for more
details.
-|Coq| and GNU Emacs
------------------------
-
-
-The |Coq| Emacs mode
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-|Coq| comes with a Major mode for GNU Emacs, ``gallina.el``. This mode
-provides syntax highlighting and also a rudimentary indentation
-facility in the style of the ``Caml`` GNU Emacs mode.
-
-Add the following lines to your ``.emacs`` file:
-
-::
-
- (setq auto-mode-alist (cons '("\\.v$" . coq-mode) auto-mode-alist))
- (autoload 'coq-mode "gallina" "Major mode for editing Coq vernacular." t)
-
-
-The |Coq| major mode is triggered by visiting a file with extension ``.v``,
-or manually with the command ``M-x coq-mode``. It gives you the correct
-syntax table for the |Coq| language, and also a rudimentary indentation
-facility:
-
-
-+ pressing ``Tab`` at the beginning of a line indents the line like the
- line above;
-+ extra tabulations increase the indentation level (by 2 spaces by default);
-+ ``M-Tab`` decreases the indentation level.
-
-
-An inferior mode to run |Coq| under Emacs, by Marco Maggesi, is also
-included in the distribution, in file ``inferior-coq.el``. Instructions to
-use it are contained in this file.
-
-
-Proof-General
-~~~~~~~~~~~~~
-
-Proof-General is a generic interface for proof assistants based on
-Emacs. The main idea is that the |Coq| commands you are editing are sent
-to a |Coq| toplevel running behind Emacs and the answers of the system
-automatically inserted into other Emacs buffers. Thus you don’t need
-to copy-paste the |Coq| material from your files to the |Coq| toplevel or
-conversely from the |Coq| toplevel to some files.
-
-Proof-General is developed and distributed independently of the system
-|Coq|. It is freely available at `<https://proofgeneral.github.io/>`_.
-
-
-Module specification
---------------------
-
-Given a |Coq| vernacular file, the gallina filter extracts its
-specification (inductive types declarations, definitions, type of
-lemmas and theorems), removing the proofs parts of the file. The |Coq|
-file ``file.v`` gives birth to the specification file ``file.g`` (where
-the suffix ``.g`` stands for |Gallina|).
-
-See the man page of ``gallina`` for more details and options.
-
Man pages
---------
-There are man pages for the commands ``coqdep``, ``gallina`` and ``coq-tex``. Man
+There are man pages for the commands ``coqdep`` and ``coq-tex``. Man
pages are installed at installation time (see installation
instructions in file ``INSTALL``, step 6).
diff --git a/doc/sphinx/proof-engine/detailed-tactic-examples.rst b/doc/sphinx/proof-engine/detailed-tactic-examples.rst
index 84810ddba5..72dd79d930 100644
--- a/doc/sphinx/proof-engine/detailed-tactic-examples.rst
+++ b/doc/sphinx/proof-engine/detailed-tactic-examples.rst
@@ -21,11 +21,11 @@ applied to the abstracted instance and after simplification of the
equalities we get the expected goals.
The abstracting tactic is called generalize_eqs and it takes as
-argument an hypothesis to generalize. It uses the JMeq datatype
+argument a hypothesis to generalize. It uses the JMeq datatype
defined in Coq.Logic.JMeq, hence we need to require it before. For
example, revisiting the first example of the inversion documentation:
-.. coqtop:: in
+.. coqtop:: in reset
Require Import Coq.Logic.JMeq.
@@ -63,6 +63,10 @@ to use an heterogeneous equality to relate the new hypothesis to the
old one (which just disappeared here). However, the tactic works just
as well in this case, e.g.:
+.. coqtop:: none
+
+ Abort.
+
.. coqtop:: in
Variable Q : forall (n m : nat), Le n m -> Prop.
@@ -80,7 +84,7 @@ to recover the needed equalities. Also, some subgoals should be
directly solved because of inconsistent contexts arising from the
constraints on indexes. The nice thing is that we can make a tactic
based on discriminate, injection and variants of substitution to
-automatically do such simplifications (which may involve the K axiom).
+automatically do such simplifications (which may involve the axiom K).
This is what the ``simplify_dep_elim`` tactic from ``Coq.Program.Equality``
does. For example, we might simplify the previous goals considerably:
@@ -101,9 +105,9 @@ are ``dependent induction`` and ``dependent destruction`` that do induction or
simply case analysis on the generalized hypothesis. For example we can
redo what we’ve done manually with dependent destruction:
-.. coqtop:: in
+.. coqtop:: none
- Require Import Coq.Program.Equality.
+ Abort.
.. coqtop:: in
@@ -122,9 +126,9 @@ destructed hypothesis actually appeared in the goal, the tactic would
still be able to invert it, contrary to dependent inversion. Consider
the following example on vectors:
-.. coqtop:: in
+.. coqtop:: none
- Require Import Coq.Program.Equality.
+ Abort.
.. coqtop:: in
@@ -167,7 +171,7 @@ predicates on a real example. We will develop an example application
to the theory of simply-typed lambda-calculus formalized in a
dependently-typed style:
-.. coqtop:: in
+.. coqtop:: in reset
Inductive type : Type :=
| base : type
@@ -226,11 +230,15 @@ name. A term is either an application of:
Once we have this datatype we want to do proofs on it, like weakening:
-.. coqtop:: in undo
+.. coqtop:: in
Lemma weakening : forall G D tau, term (G ; D) tau ->
forall tau', term (G , tau' ; D) tau.
+.. coqtop:: none
+
+ Abort.
+
The problem here is that we can’t just use induction on the typing
derivation because it will forget about the ``G ; D`` constraint appearing
in the instance. A solution would be to rewrite the goal as:
@@ -241,6 +249,10 @@ in the instance. A solution would be to rewrite the goal as:
forall G D, (G ; D) = G' ->
forall tau', term (G, tau' ; D) tau.
+.. coqtop:: none
+
+ Abort.
+
With this proper separation of the index from the instance and the
right induction loading (putting ``G`` and ``D`` after the inducted-on
hypothesis), the proof will go through, but it is a very tedious
@@ -252,6 +264,7 @@ back automatically. Indeed we can simply write:
.. coqtop:: in
Require Import Coq.Program.Tactics.
+ Require Import Coq.Program.Equality.
.. coqtop:: in
@@ -308,17 +321,14 @@ it can be used directly.
apply weak, IHterm.
-If there is an easy first-order solution to these equations as in this
-subgoal, the ``specialize_eqs`` tactic can be used instead of giving
-explicit proof terms:
-
-.. coqtop:: all
+Now concluding this subgoal is easy.
- specialize_eqs IHterm.
+.. coqtop:: in
-This concludes our example.
+ constructor; apply IHterm; reflexivity.
-See also: The :tacn:`induction`, :tacn:`case`, and :tacn:`inversion` tactics.
+.. seealso::
+ The :tacn:`induction`, :tacn:`case`, and :tacn:`inversion` tactics.
autorewrite
@@ -331,79 +341,81 @@ involves conditional rewritings and shows how to deal with them using
the optional tactic of the ``Hint Rewrite`` command.
-Example 1: Ackermann function
+.. example:: Ackermann function
-.. coqtop:: in
+ .. coqtop:: in reset
- Reset Initial.
+ Require Import Arith.
-.. coqtop:: in
+ .. coqtop:: in
- Require Import Arith.
+ Variable Ack : nat -> nat -> nat.
-.. coqtop:: in
+ .. coqtop:: in
- Variable Ack : nat -> nat -> nat.
+ Axiom Ack0 : forall m:nat, Ack 0 m = S m.
+ Axiom Ack1 : forall n:nat, Ack (S n) 0 = Ack n 1.
+ Axiom Ack2 : forall n m:nat, Ack (S n) (S m) = Ack n (Ack (S n) m).
-.. coqtop:: in
+ .. coqtop:: in
- Axiom Ack0 : forall m:nat, Ack 0 m = S m.
- Axiom Ack1 : forall n:nat, Ack (S n) 0 = Ack n 1.
- Axiom Ack2 : forall n m:nat, Ack (S n) (S m) = Ack n (Ack (S n) m).
+ Hint Rewrite Ack0 Ack1 Ack2 : base0.
-.. coqtop:: in
+ .. coqtop:: all
- Hint Rewrite Ack0 Ack1 Ack2 : base0.
+ Lemma ResAck0 : Ack 3 2 = 29.
-.. coqtop:: all
+ .. coqtop:: all
- Lemma ResAck0 : Ack 3 2 = 29.
+ autorewrite with base0 using try reflexivity.
-.. coqtop:: all
+.. example:: MacCarthy function
- autorewrite with base0 using try reflexivity.
+ .. coqtop:: in reset
-Example 2: Mac Carthy function
+ Require Import Omega.
-.. coqtop:: in
+ .. coqtop:: in
- Require Import Omega.
+ Variable g : nat -> nat -> nat.
-.. coqtop:: in
+ .. coqtop:: in
- Variable g : nat -> nat -> nat.
+ Axiom g0 : forall m:nat, g 0 m = m.
+ Axiom g1 : forall n m:nat, (n > 0) -> (m > 100) -> g n m = g (pred n) (m - 10).
+ Axiom g2 : forall n m:nat, (n > 0) -> (m <= 100) -> g n m = g (S n) (m + 11).
-.. coqtop:: in
+ .. coqtop:: in
- Axiom g0 : forall m:nat, g 0 m = m.
- Axiom g1 : forall n m:nat, (n > 0) -> (m > 100) -> g n m = g (pred n) (m - 10).
- Axiom g2 : forall n m:nat, (n > 0) -> (m <= 100) -> g n m = g (S n) (m + 11).
+ Hint Rewrite g0 g1 g2 using omega : base1.
+ .. coqtop:: in
-.. coqtop:: in
+ Lemma Resg0 : g 1 110 = 100.
- Hint Rewrite g0 g1 g2 using omega : base1.
+ .. coqtop:: out
-.. coqtop:: in
+ Show.
- Lemma Resg0 : g 1 110 = 100.
+ .. coqtop:: all
-.. coqtop:: out
+ autorewrite with base1 using reflexivity || simpl.
- Show.
+ .. coqtop:: none
-.. coqtop:: all
+ Qed.
- autorewrite with base1 using reflexivity || simpl.
+ .. coqtop:: all
-.. coqtop:: all
+ Lemma Resg1 : g 1 95 = 91.
- Lemma Resg1 : g 1 95 = 91.
+ .. coqtop:: all
-.. coqtop:: all
+ autorewrite with base1 using reflexivity || simpl.
- autorewrite with base1 using reflexivity || simpl.
+ .. coqtop:: none
+ Qed.
.. _quote:
@@ -419,7 +431,7 @@ the form ``(f t)``. ``L`` must have a constructor of type: ``A -> L``.
Here is an example:
-.. coqtop:: in
+.. coqtop:: in reset
Require Import Quote.
@@ -461,14 +473,8 @@ corresponding left-hand side and call yourself recursively on sub-
terms. If there is no match, we are at a leaf: return the
corresponding constructor (here ``f_const``) applied to the term.
-
-Error messages:
-
-
-#. quote: not a simple fixpoint
-
- Happens when ``quote`` is not able to perform inversion properly.
-
+When ``quote`` is not able to perform inversion properly, it will error out with
+:exn:`quote: not a simple fixpoint`.
Introducing variables map
@@ -553,7 +559,13 @@ example, this is the case for the :tacn:`ring` tactic. Then one must provide to
is ``[O S]`` then closed natural numbers will be considered as constants
and other terms as variables.
-Example:
+.. coqtop:: in reset
+
+ Require Import Quote.
+
+.. coqtop:: in
+
+ Parameters A B C : Prop.
.. coqtop:: in
@@ -594,8 +606,9 @@ Example:
quote interp_f [ B C iff ].
-Warning: Since function inversion is undecidable in general case,
-don’t expect miracles from it!
+.. warning::
+ Since functional inversion is undecidable in the general case,
+ don’t expect miracles from it!
.. tacv:: quote @ident in @term using @tactic
@@ -607,25 +620,28 @@ don’t expect miracles from it!
Same as above, but will use the additional ``ident`` list to chose
which subterms are constants (see above).
-See also: comments of source file ``plugins/quote/quote.ml``
+.. seealso::
+ Comments from the source file ``plugins/quote/quote.ml``
-See also: the :tacn:`ring` tactic.
+.. seealso::
+ The :tacn:`ring` tactic.
-Using the tactical language
+Using the tactic language
---------------------------
About the cardinality of the set of natural numbers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-A first example which shows how to use pattern matching over the
-proof contexts is the proof that natural numbers have more than two
-elements. The proof of such a lemma can be done as follows:
+The first example which shows how to use pattern matching over the
+proof context is a proof of the fact that natural numbers have more
+than two elements. This can be done as follows:
-.. coqtop:: in
+.. coqtop:: in reset
- Lemma card_nat : ~ (exists x : nat, exists y : nat, forall z:nat, x = z \/ y = z).
+ Lemma card_nat :
+ ~ exists x : nat, exists y : nat, forall z:nat, x = z \/ y = z.
Proof.
.. coqtop:: in
@@ -637,8 +653,8 @@ elements. The proof of such a lemma can be done as follows:
elim (Hy 0); elim (Hy 1); elim (Hy 2); intros;
match goal with
- | [_:(?a = ?b),_:(?a = ?c) |- _ ] =>
- cut (b = c); [ discriminate | transitivity a; auto ]
+ | _ : ?a = ?b, _ : ?a = ?c |- _ =>
+ cut (b = c); [ discriminate | transitivity a; auto ]
end.
.. coqtop:: in
@@ -651,16 +667,14 @@ solved by a match goal structure and, in particular, with only one
pattern (use of non-linear matching).
-Permutation on closed lists
+Permutations of lists
~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Another more complex example is the problem of permutation on closed
-lists. The aim is to show that a closed list is a permutation of
-another one.
+A more complex example is the problem of permutations of
+lists. The aim is to show that a list is a permutation of
+another list.
-First, we define the permutation predicate as shown here:
-
-.. coqtop:: in
+.. coqtop:: in reset
Section Sort.
@@ -670,205 +684,179 @@ First, we define the permutation predicate as shown here:
.. coqtop:: in
- Inductive permut : list A -> list A -> Prop :=
- | permut_refl : forall l, permut l l
- | permut_cons : forall a l0 l1, permut l0 l1 -> permut (a :: l0) (a :: l1)
- | permut_append : forall a l, permut (a :: l) (l ++ a :: nil)
- | permut_trans : forall l0 l1 l2, permut l0 l1 -> permut l1 l2 -> permut l0 l2.
+ Inductive perm : list A -> list A -> Prop :=
+ | perm_refl : forall l, perm l l
+ | perm_cons : forall a l0 l1, perm l0 l1 -> perm (a :: l0) (a :: l1)
+ | perm_append : forall a l, perm (a :: l) (l ++ a :: nil)
+ | perm_trans : forall l0 l1 l2, perm l0 l1 -> perm l1 l2 -> perm l0 l2.
.. coqtop:: in
End Sort.
-A more complex example is the problem of permutation on closed lists.
-The aim is to show that a closed list is a permutation of another one.
First, we define the permutation predicate as shown above.
-
.. coqtop:: none
Require Import List.
-.. coqtop:: all
-
- Ltac Permut n :=
- match goal with
- | |- (permut _ ?l ?l) => apply permut_refl
- | |- (permut _ (?a :: ?l1) (?a :: ?l2)) =>
- let newn := eval compute in (length l1) in
- (apply permut_cons; Permut newn)
- | |- (permut ?A (?a :: ?l1) ?l2) =>
- match eval compute in n with
- | 1 => fail
- | _ =>
- let l1' := constr:(l1 ++ a :: nil) in
- (apply (permut_trans A (a :: l1) l1' l2);
- [ apply permut_append | compute; Permut (pred n) ])
- end
- end.
-
-
-.. coqtop:: all
-
- Ltac PermutProve :=
- match goal with
- | |- (permut _ ?l1 ?l2) =>
- match eval compute in (length l1 = length l2) with
- | (?n = ?n) => Permut n
- end
- end.
-
-Next, we can write naturally the tactic and the result can be seen
-above. We can notice that we use two top level definitions
-``PermutProve`` and ``Permut``. The function to be called is
-``PermutProve`` which computes the lengths of the two lists and calls
-``Permut`` with the length if the two lists have the same
-length. ``Permut`` works as expected. If the two lists are equal, it
-concludes. Otherwise, if the lists have identical first elements, it
-applies ``Permut`` on the tail of the lists. Finally, if the lists
-have different first elements, it puts the first element of one of the
-lists (here the second one which appears in the permut predicate) at
-the end if that is possible, i.e., if the new first element has been
-at this place previously. To verify that all rotations have been done
-for a list, we use the length of the list as an argument for Permut
-and this length is decremented for each rotation down to, but not
-including, 1 because for a list of length ``n``, we can make exactly
-``n−1`` rotations to generate at most ``n`` distinct lists. Here, it
-must be noticed that we use the natural numbers of Coq for the
-rotation counter. In :ref:`ltac-syntax`, we can
-see that it is possible to use usual natural numbers but they are only
-used as arguments for primitive tactics and they cannot be handled, in
-particular, we cannot make computations with them. So, a natural
-choice is to use Coq data structures so that Coq makes the
-computations (reductions) by eval compute in and we can get the terms
-back by match.
-
-With ``PermutProve``, we can now prove lemmas as follows:
-
.. coqtop:: in
- Lemma permut_ex1 : permut nat (1 :: 2 :: 3 :: nil) (3 :: 2 :: 1 :: nil).
+ Ltac perm_aux n :=
+ match goal with
+ | |- (perm _ ?l ?l) => apply perm_refl
+ | |- (perm _ (?a :: ?l1) (?a :: ?l2)) =>
+ let newn := eval compute in (length l1) in
+ (apply perm_cons; perm_aux newn)
+ | |- (perm ?A (?a :: ?l1) ?l2) =>
+ match eval compute in n with
+ | 1 => fail
+ | _ =>
+ let l1' := constr:(l1 ++ a :: nil) in
+ (apply (perm_trans A (a :: l1) l1' l2);
+ [ apply perm_append | compute; perm_aux (pred n) ])
+ end
+ end.
-.. coqtop:: in
+Next we define an auxiliary tactic ``perm_aux`` which takes an argument
+used to control the recursion depth. This tactic behaves as follows. If
+the lists are identical (i.e. convertible), it concludes. Otherwise, if
+the lists have identical heads, it proceeds to look at their tails.
+Finally, if the lists have different heads, it rotates the first list by
+putting its head at the end if the new head hasn't been the head previously. To check this, we keep track of the
+number of performed rotations using the argument ``n``. We do this by
+decrementing ``n`` each time we perform a rotation. It works because
+for a list of length ``n`` we can make exactly ``n - 1`` rotations
+to generate at most ``n`` distinct lists. Notice that we use the natural
+numbers of Coq for the rotation counter. From :ref:`ltac-syntax` we know
+that it is possible to use the usual natural numbers, but they are only
+used as arguments for primitive tactics and they cannot be handled, so,
+in particular, we cannot make computations with them. Thus the natural
+choice is to use Coq data structures so that Coq makes the computations
+(reductions) by ``eval compute in`` and we can get the terms back by match.
+
+.. coqtop:: in
+
+ Ltac solve_perm :=
+ match goal with
+ | |- (perm _ ?l1 ?l2) =>
+ match eval compute in (length l1 = length l2) with
+ | (?n = ?n) => perm_aux n
+ end
+ end.
- Proof. PermutProve. Qed.
+The main tactic is ``solve_perm``. It computes the lengths of the two lists
+and uses them as arguments to call ``perm_aux`` if the lengths are equal (if they
+aren't, the lists cannot be permutations of each other). Using this tactic we
+can now prove lemmas as follows:
.. coqtop:: in
- Lemma permut_ex2 : permut nat
- (0 :: 1 :: 2 :: 3 :: 4 :: 5 :: 6 :: 7 :: 8 :: 9 :: nil)
- (0 :: 2 :: 4 :: 6 :: 8 :: 9 :: 7 :: 5 :: 3 :: 1 :: nil).
-
- Proof. PermutProve. Qed.
+ Lemma solve_perm_ex1 :
+ perm nat (1 :: 2 :: 3 :: nil) (3 :: 2 :: 1 :: nil).
+ Proof. solve_perm. Qed.
+.. coqtop:: in
+ Lemma solve_perm_ex2 :
+ perm nat
+ (0 :: 1 :: 2 :: 3 :: 4 :: 5 :: 6 :: 7 :: 8 :: 9 :: nil)
+ (0 :: 2 :: 4 :: 6 :: 8 :: 9 :: 7 :: 5 :: 3 :: 1 :: nil).
+ Proof. solve_perm. Qed.
Deciding intuitionistic propositional logic
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.. _decidingintuitionistic1:
-
-.. coqtop:: all
-
- Ltac Axioms :=
- match goal with
- | |- True => trivial
- | _:False |- _ => elimtype False; assumption
- | _:?A |- ?A => auto
- end.
-
-.. _decidingintuitionistic2:
-
-.. coqtop:: all
-
- Ltac DSimplif :=
- repeat
- (intros;
- match goal with
- | id:(~ _) |- _ => red in id
- | id:(_ /\ _) |- _ =>
- elim id; do 2 intro; clear id
- | id:(_ \/ _) |- _ =>
- elim id; intro; clear id
- | id:(?A /\ ?B -> ?C) |- _ =>
- cut (A -> B -> C);
- [ intro | intros; apply id; split; assumption ]
- | id:(?A \/ ?B -> ?C) |- _ =>
- cut (B -> C);
- [ cut (A -> C);
- [ intros; clear id
- | intro; apply id; left; assumption ]
- | intro; apply id; right; assumption ]
- | id0:(?A -> ?B),id1:?A |- _ =>
- cut B; [ intro; clear id0 | apply id0; assumption ]
- | |- (_ /\ _) => split
- | |- (~ _) => red
- end).
-
-.. coqtop:: all
-
- Ltac TautoProp :=
- DSimplif;
- Axioms ||
- match goal with
- | id:((?A -> ?B) -> ?C) |- _ =>
- cut (B -> C);
- [ intro; cut (A -> B);
- [ intro; cut C;
- [ intro; clear id | apply id; assumption ]
- | clear id ]
- | intro; apply id; intro; assumption ]; TautoProp
- | id:(~ ?A -> ?B) |- _ =>
- cut (False -> B);
- [ intro; cut (A -> False);
- [ intro; cut B;
- [ intro; clear id | apply id; assumption ]
- | clear id ]
- | intro; apply id; red; intro; assumption ]; TautoProp
- | |- (_ \/ _) => (left; TautoProp) || (right; TautoProp)
- end.
-
-The pattern matching on goals allows a complete and so a powerful
-backtracking when returning tactic values. An interesting application
-is the problem of deciding intuitionistic propositional logic.
-Considering the contraction-free sequent calculi LJT* of Roy Dyckhoff
-:cite:`Dyc92`, it is quite natural to code such a tactic
-using the tactic language as shown on figures: :ref:`Deciding
-intuitionistic propositions (1) <decidingintuitionistic1>` and
-:ref:`Deciding intuitionistic propositions (2)
-<decidingintuitionistic2>`. The tactic ``Axioms`` tries to conclude
-using usual axioms. The tactic ``DSimplif`` applies all the reversible
-rules of Dyckhoff’s system. Finally, the tactic ``TautoProp`` (the
-main tactic to be called) simplifies with ``DSimplif``, tries to
-conclude with ``Axioms`` and tries several paths using the
-backtracking rules (one of the four Dyckhoff’s rules for the left
-implication to get rid of the contraction and the right or).
-
-For example, with ``TautoProp``, we can prove tautologies like those:
-
-.. coqtop:: in
-
- Lemma tauto_ex1 : forall A B:Prop, A /\ B -> A \/ B.
-
-.. coqtop:: in
-
- Proof. TautoProp. Qed.
+Pattern matching on goals allows a powerful backtracking when returning tactic
+values. An interesting application is the problem of deciding intuitionistic
+propositional logic. Considering the contraction-free sequent calculi LJT* of
+Roy Dyckhoff :cite:`Dyc92`, it is quite natural to code such a tactic using the
+tactic language as shown below.
-.. coqtop:: in
+.. coqtop:: in reset
- Lemma tauto_ex2 :
- forall A B:Prop, (~ ~ B -> B) -> (A -> B) -> ~ ~ A -> B.
+ Ltac basic :=
+ match goal with
+ | |- True => trivial
+ | _ : False |- _ => contradiction
+ | _ : ?A |- ?A => assumption
+ end.
.. coqtop:: in
- Proof. TautoProp. Qed.
+ Ltac simplify :=
+ repeat (intros;
+ match goal with
+ | H : ~ _ |- _ => red in H
+ | H : _ /\ _ |- _ =>
+ elim H; do 2 intro; clear H
+ | H : _ \/ _ |- _ =>
+ elim H; intro; clear H
+ | H : ?A /\ ?B -> ?C |- _ =>
+ cut (A -> B -> C);
+ [ intro | intros; apply H; split; assumption ]
+ | H: ?A \/ ?B -> ?C |- _ =>
+ cut (B -> C);
+ [ cut (A -> C);
+ [ intros; clear H
+ | intro; apply H; left; assumption ]
+ | intro; apply H; right; assumption ]
+ | H0 : ?A -> ?B, H1 : ?A |- _ =>
+ cut B; [ intro; clear H0 | apply H0; assumption ]
+ | |- _ /\ _ => split
+ | |- ~ _ => red
+ end).
+
+.. coqtop:: in
+
+ Ltac my_tauto :=
+ simplify; basic ||
+ match goal with
+ | H : (?A -> ?B) -> ?C |- _ =>
+ cut (B -> C);
+ [ intro; cut (A -> B);
+ [ intro; cut C;
+ [ intro; clear H | apply H; assumption ]
+ | clear H ]
+ | intro; apply H; intro; assumption ]; my_tauto
+ | H : ~ ?A -> ?B |- _ =>
+ cut (False -> B);
+ [ intro; cut (A -> False);
+ [ intro; cut B;
+ [ intro; clear H | apply H; assumption ]
+ | clear H ]
+ | intro; apply H; red; intro; assumption ]; my_tauto
+ | |- _ \/ _ => (left; my_tauto) || (right; my_tauto)
+ end.
+
+The tactic ``basic`` tries to reason using simple rules involving truth, falsity
+and available assumptions. The tactic ``simplify`` applies all the reversible
+rules of Dyckhoff’s system. Finally, the tactic ``my_tauto`` (the main
+tactic to be called) simplifies with ``simplify``, tries to conclude with
+``basic`` and tries several paths using the backtracking rules (one of the
+four Dyckhoff’s rules for the left implication to get rid of the contraction
+and the right ``or``).
+
+Having defined ``my_tauto``, we can prove tautologies like these:
+
+.. coqtop:: in
+
+ Lemma my_tauto_ex1 :
+ forall A B : Prop, A /\ B -> A \/ B.
+ Proof. my_tauto. Qed.
+
+.. coqtop:: in
+
+ Lemma my_tauto_ex2 :
+ forall A B : Prop, (~ ~ B -> B) -> (A -> B) -> ~ ~ A -> B.
+ Proof. my_tauto. Qed.
Deciding type isomorphisms
~~~~~~~~~~~~~~~~~~~~~~~~~~
-A more tricky problem is to decide equalities between types and modulo
+A more tricky problem is to decide equalities between types modulo
isomorphisms. Here, we choose to use the isomorphisms of the simply
typed λ-calculus with Cartesian product and unit type (see, for
example, :cite:`RC95`). The axioms of this λ-calculus are given below.
@@ -915,112 +903,104 @@ example, :cite:`RC95`). The axioms of this λ-calculus are given below.
End Iso_axioms.
+.. coqtop:: in
+ Ltac simplify_type ty :=
+ match ty with
+ | ?A * ?B * ?C =>
+ rewrite <- (Ass A B C); try simplify_type_eq
+ | ?A * ?B -> ?C =>
+ rewrite (Cur A B C); try simplify_type_eq
+ | ?A -> ?B * ?C =>
+ rewrite (Dis A B C); try simplify_type_eq
+ | ?A * unit =>
+ rewrite (P_unit A); try simplify_type_eq
+ | unit * ?B =>
+ rewrite (Com unit B); try simplify_type_eq
+ | ?A -> unit =>
+ rewrite (AR_unit A); try simplify_type_eq
+ | unit -> ?B =>
+ rewrite (AL_unit B); try simplify_type_eq
+ | ?A * ?B =>
+ (simplify_type A; try simplify_type_eq) ||
+ (simplify_type B; try simplify_type_eq)
+ | ?A -> ?B =>
+ (simplify_type A; try simplify_type_eq) ||
+ (simplify_type B; try simplify_type_eq)
+ end
+ with simplify_type_eq :=
+ match goal with
+ | |- ?A = ?B => try simplify_type A; try simplify_type B
+ end.
-.. _typeisomorphism1:
-
-.. coqtop:: all
-
- Ltac DSimplif trm :=
- match trm with
- | (?A * ?B * ?C) =>
- rewrite <- (Ass A B C); try MainSimplif
- | (?A * ?B -> ?C) =>
- rewrite (Cur A B C); try MainSimplif
- | (?A -> ?B * ?C) =>
- rewrite (Dis A B C); try MainSimplif
- | (?A * unit) =>
- rewrite (P_unit A); try MainSimplif
- | (unit * ?B) =>
- rewrite (Com unit B); try MainSimplif
- | (?A -> unit) =>
- rewrite (AR_unit A); try MainSimplif
- | (unit -> ?B) =>
- rewrite (AL_unit B); try MainSimplif
- | (?A * ?B) =>
- (DSimplif A; try MainSimplif) || (DSimplif B; try MainSimplif)
- | (?A -> ?B) =>
- (DSimplif A; try MainSimplif) || (DSimplif B; try MainSimplif)
- end
- with MainSimplif :=
- match goal with
- | |- (?A = ?B) => try DSimplif A; try DSimplif B
- end.
-
-.. coqtop:: all
+.. coqtop:: in
- Ltac Length trm :=
- match trm with
- | (_ * ?B) => let succ := Length B in constr:(S succ)
- | _ => constr:(1)
- end.
+ Ltac len trm :=
+ match trm with
+ | _ * ?B => let succ := len B in constr:(S succ)
+ | _ => constr:(1)
+ end.
-.. coqtop:: all
+.. coqtop:: in
Ltac assoc := repeat rewrite <- Ass.
+.. coqtop:: in
-.. _typeisomorphism2:
-
-.. coqtop:: all
-
- Ltac DoCompare n :=
- match goal with
- | [ |- (?A = ?A) ] => reflexivity
- | [ |- (?A * ?B = ?A * ?C) ] =>
- apply Cons; let newn := Length B in
- DoCompare newn
- | [ |- (?A * ?B = ?C) ] =>
- match eval compute in n with
- | 1 => fail
- | _ =>
- pattern (A * B) at 1; rewrite Com; assoc; DoCompare (pred n)
- end
- end.
-
-.. coqtop:: all
+ Ltac solve_type_eq n :=
+ match goal with
+ | |- ?A = ?A => reflexivity
+ | |- ?A * ?B = ?A * ?C =>
+ apply Cons; let newn := len B in solve_type_eq newn
+ | |- ?A * ?B = ?C =>
+ match eval compute in n with
+ | 1 => fail
+ | _ =>
+ pattern (A * B) at 1; rewrite Com; assoc; solve_type_eq (pred n)
+ end
+ end.
- Ltac CompareStruct :=
- match goal with
- | [ |- (?A = ?B) ] =>
- let l1 := Length A
- with l2 := Length B in
- match eval compute in (l1 = l2) with
- | (?n = ?n) => DoCompare n
- end
- end.
+.. coqtop:: in
-.. coqtop:: all
+ Ltac compare_structure :=
+ match goal with
+ | |- ?A = ?B =>
+ let l1 := len A
+ with l2 := len B in
+ match eval compute in (l1 = l2) with
+ | ?n = ?n => solve_type_eq n
+ end
+ end.
- Ltac IsoProve := MainSimplif; CompareStruct.
+.. coqtop:: in
+ Ltac solve_iso := simplify_type_eq; compare_structure.
-The tactic to judge equalities modulo this axiomatization can be
-written as shown on these figures: :ref:`type isomorphism tactic (1)
-<typeisomorphism1>` and :ref:`type isomorphism tactic (2)
-<typeisomorphism2>`. The algorithm is quite simple. Types are reduced
-using axioms that can be oriented (this done by ``MainSimplif``). The
-normal forms are sequences of Cartesian products without Cartesian
-product in the left component. These normal forms are then compared
-modulo permutation of the components (this is done by
-``CompareStruct``). The main tactic to be called and realizing this
-algorithm isIsoProve.
+The tactic to judge equalities modulo this axiomatization is shown above.
+The algorithm is quite simple. First types are simplified using axioms that
+can be oriented (this is done by ``simplify_type`` and ``simplify_type_eq``).
+The normal forms are sequences of Cartesian products without Cartesian product
+in the left component. These normal forms are then compared modulo permutation
+of the components by the tactic ``compare_structure``. If they have the same
+lengths, the tactic ``solve_type_eq`` attempts to prove that the types are equal.
+The main tactic that puts all these components together is called ``solve_iso``.
-Here are examples of what can be solved by ``IsoProve``.
+Here are examples of what can be solved by ``solve_iso``.
.. coqtop:: in
- Lemma isos_ex1 :
- forall A B:Set, A * unit * B = B * (unit * A).
+ Lemma solve_iso_ex1 :
+ forall A B : Set, A * unit * B = B * (unit * A).
Proof.
- intros; IsoProve.
+ intros; solve_iso.
Qed.
.. coqtop:: in
- Lemma isos_ex2 :
- forall A B C:Set,
- (A * unit -> B * (C * unit)) = (A * unit -> (C -> unit) * C) * (unit -> A -> B).
+ Lemma solve_iso_ex2 :
+ forall A B C : Set,
+ (A * unit -> B * (C * unit)) =
+ (A * unit -> (C -> unit) * C) * (unit -> A -> B).
Proof.
- intros; IsoProve.
+ intros; solve_iso.
Qed.
diff --git a/doc/sphinx/proof-engine/ltac.rst b/doc/sphinx/proof-engine/ltac.rst
index 88c1e225fd..7608ea7245 100644
--- a/doc/sphinx/proof-engine/ltac.rst
+++ b/doc/sphinx/proof-engine/ltac.rst
@@ -10,8 +10,8 @@ This chapter gives a compact documentation of |Ltac|, the tactic language
available in |Coq|. We start by giving the syntax, and next, we present the
informal semantics. If you want to know more regarding this language and
especially about its foundations, you can refer to :cite:`Del00`. Chapter
-:ref:`detailedexamplesoftactics` is devoted to giving examples of use of this
-language on small but also with non-trivial problems.
+:ref:`detailedexamplesoftactics` is devoted to giving small but nontrivial
+use examples of this language.
.. _ltac-syntax:
@@ -33,7 +33,7 @@ notation :g:`_` can also be used to denote metavariable whose instance is
irrelevant. In the notation :g:`?id`, the identifier allows us to keep
instantiations and to make constraints whereas :g:`_` shows that we are not
interested in what will be matched. On the right hand side of pattern-matching
-clauses, the named metavariable are used without the question mark prefix. There
+clauses, the named metavariables are used without the question mark prefix. There
is also a special notation for second-order pattern-matching problems: in an
applicative pattern of the form :g:`@?id id1 … idn`, the variable id matches any
complex expression with (possible) dependencies in the variables :g:`id1 … idn`
@@ -117,7 +117,7 @@ mode but it can also be used in toplevel definitions as shown below.
: | numgoals
: | guard `test`
: | assert_fails `tacexpr3`
- : | assert_suceeds `tacexpr3`
+ : | assert_succeeds `tacexpr3`
: | `atomic_tactic`
: | `qualid` `tacarg` ... `tacarg`
: | `atom`
@@ -144,10 +144,11 @@ mode but it can also be used in toplevel definitions as shown below.
: | `integer` (< | <= | > | >=) `integer`
selector : [`ident`]
: | `integer`
- : (`integer` | `integer` - `integer`), ..., (`integer` | `integer` - `integer`)
+ : | (`integer` | `integer` - `integer`), ..., (`integer` | `integer` - `integer`)
toplevel_selector : `selector`
- : | `all`
- : | `par`
+ : | all
+ : | par
+ : | !
.. productionlist:: coq
top : [Local] Ltac `ltac_def` with ... with `ltac_def`
@@ -160,13 +161,13 @@ Semantics
---------
Tactic expressions can only be applied in the context of a proof. The
-evaluation yields either a term, an integer or a tactic. Intermediary
+evaluation yields either a term, an integer or a tactic. Intermediate
results can be terms or integers but the final result must be a tactic
which is then applied to the focused goals.
There is a special case for ``match goal`` expressions of which the clauses
evaluate to tactics. Such expressions can only be used as end result of
-a tactic expression (never as argument of a non recursive local
+a tactic expression (never as argument of a non-recursive local
definition or of an application).
The rest of this section explains the semantics of every construction of
@@ -177,7 +178,7 @@ Sequence
A sequence is an expression of the following form:
-.. tacn:: @expr ; @expr
+.. tacn:: @expr__1 ; @expr__2
:name: ltac-seq
The expression :n:`@expr__1` is evaluated to :n:`v__1`, which must be
@@ -197,8 +198,8 @@ following form:
:name: [> ... | ... | ... ] (dispatch)
The expressions :n:`@expr__i` are evaluated to :n:`v__i`, for
- i=0,...,n and all have to be tactics. The :n:`v__i` is applied to the
- i-th goal, for =1,...,n. It fails if the number of focused goals is not
+ i = 0, ..., n and all have to be tactics. The :n:`v__i` is applied to the
+ i-th goal, for i = 1, ..., n. It fails if the number of focused goals is not
exactly n.
.. note::
@@ -207,11 +208,11 @@ following form:
were given. For instance, ``[> | auto]`` is a shortcut for ``[> idtac | auto
]``.
- .. tacv:: [> {*| @expr} | @expr .. | {*| @expr}]
+ .. tacv:: [> {*| @expr__i} | @expr .. | {*| @expr__j}]
- In this variant, token:`expr` is used for each goal coming after those
- covered by the first list of :n:`@expr` but before those coevered by the
- last list of :n:`@expr`.
+ In this variant, :n:`@expr` is used for each goal coming after those
+ covered by the list of :n:`@expr__i` but before those covered by the
+ list of :n:`@expr__j`.
.. tacv:: [> {*| @expr} | .. | {*| @expr}]
@@ -221,15 +222,15 @@ following form:
.. tacv:: [> @expr .. ]
In this variant, the tactic :n:`@expr` is applied independently to each of
- the goals, rather than globally. In particular, if there are no goal, the
+ the goals, rather than globally. In particular, if there are no goals, the
tactic is not run at all. A tactic which expects multiple goals, such as
``swap``, would act as if a single goal is focused.
- .. tacv:: expr ; [{*| @expr}]
+ .. tacv:: @expr__0 ; [{*| @expr__i}]
This variant of local tactic application is paired with a sequence. In this
- variant, there must be as many :n:`@expr` in the list as goals generated
- by the application of the first :n:`@expr` to each of the individual goals
+ variant, there must be as many :n:`@expr__i` as goals generated
+ by the application of :n:`@expr__0` to each of the individual goals
independently. All the above variants work in this form too.
Formally, :n:`@expr ; [ ... ]` is equivalent to :n:`[> @expr ; [> ... ] .. ]`.
@@ -247,20 +248,20 @@ focused goals with:
We can also use selectors as a tactical, which allows to use them nested
in a tactic expression, by using the keyword ``only``:
- .. tacv:: only selector : expr
+ .. tacv:: only @selector : @expr
:name: only ... : ...
- When selecting several goals, the tactic expr is applied globally to all
+ When selecting several goals, the tactic :token:`expr` is applied globally to all
selected goals.
.. tacv:: [@ident] : @expr
- In this variant, :n:`@expr` is applied locally to a goal previously named
+ In this variant, :token:`expr` is applied locally to a goal previously named
by the user (see :ref:`existential-variables`).
.. tacv:: @num : @expr
- In this variant, :n:`@expr` is applied locally to the :token:`num`-th goal.
+ In this variant, :token:`expr` is applied locally to the :token:`num`-th goal.
.. tacv:: {+, @num-@num} : @expr
@@ -271,13 +272,13 @@ focused goals with:
.. tacv:: all: @expr
:name: all: ...
- In this variant, :n:`@expr` is applied to all focused goals. ``all:`` can only
+ In this variant, :token:`expr` is applied to all focused goals. ``all:`` can only
be used at the toplevel of a tactic expression.
.. tacv:: !: @expr
- In this variant, if exactly one goal is focused :n:`expr` is
- applied to it. Otherwise the tactical fails. ``!:`` can only be
+ In this variant, if exactly one goal is focused, :token:`expr` is
+ applied to it. Otherwise the tactic fails. ``!:`` can only be
used at the toplevel of a tactic expression.
.. tacv:: par: @expr
@@ -385,11 +386,12 @@ tactic to work (i.e. which does not fail) among a panel of tactics:
:name: first
The :n:`@expr__i` are evaluated to :n:`v__i` and :n:`v__i` must be
- tactic values, for i=1,...,n. Supposing n>1, it applies, in each focused
- goal independently, :n:`v__1`, if it works, it stops otherwise it
+ tactic values for i = 1, ..., n. Supposing n > 1,
+ :n:`first [@expr__1 | ... | @expr__n]` applies :n:`v__1` in each
+ focused goal independently and stops if it succeeds; otherwise it
tries to apply :n:`v__2` and so on. It fails when there is no
applicable tactic. In other words,
- :n:`first [:@expr__1 | ... | @expr__n]` behaves, in each goal, as the the first
+ :n:`first [@expr__1 | ... | @expr__n]` behaves, in each goal, as the first
:n:`v__i` to have *at least* one success.
.. exn:: No applicable tactic.
@@ -397,7 +399,7 @@ tactic to work (i.e. which does not fail) among a panel of tactics:
.. tacv:: first @expr
This is an |Ltac| alias that gives a primitive access to the first
- tactical as a |Ltac| definition without going through a parsing rule. It
+ tactical as an |Ltac| definition without going through a parsing rule. It
expects to be given a list of tactics through a ``Tactic Notation``,
allowing to write notations of the following form:
@@ -454,7 +456,7 @@ single success *a posteriori*:
:n:`@expr` is evaluated to ``v`` which must be a tactic value. The tactic value
``v`` is applied but only its first success is used. If ``v`` fails,
- :n:`once @expr` fails like ``v``. If ``v`` has a least one success,
+ :n:`once @expr` fails like ``v``. If ``v`` has at least one success,
:n:`once @expr` succeeds once, but cannot produce more successes.
Checking the successes
@@ -475,7 +477,7 @@ one* success:
.. warning::
The experimental status of this tactic pertains to the fact if ``v``
- performs side effects, they may occur in a unpredictable way. Indeed,
+ performs side effects, they may occur in an unpredictable way. Indeed,
normally ``v`` would only be executed up to the first success until
backtracking is needed, however exactly_once needs to look ahead to see
whether a second success exists, and may run further effects
@@ -500,7 +502,7 @@ Coq provides a derived tactic to check that a tactic has *at least one*
success:
.. tacn:: assert_succeeds @expr
- :name: assert_suceeds
+ :name: assert_succeeds
This behaves like
:n:`tryif (assert_fails tac) then fail 0 tac "fails" else idtac`.
@@ -515,8 +517,9 @@ among a panel of tactics:
:name: solve
The :n:`@expr__i` are evaluated to :n:`v__i` and :n:`v__i` must be
- tactic values, for i=1,...,n. Supposing n>1, it applies :n:`v__1` to
- each goal independently, if it doesn’t solve the goal then it tries to
+ tactic values, for i = 1, ..., n. Supposing n > 1,
+ :n:`solve [@expr__1 | ... | @expr__n]` applies :n:`v__1` to
+ each goal independently and stops if it succeeds; otherwise it tries to
apply :n:`v__2` and so on. It fails if there is no solving tactic.
.. exn:: Cannot solve the goal.
@@ -546,18 +549,16 @@ Failing
This is the always-failing tactic: it does not solve any
goal. It is useful for defining other tacticals since it can be caught by
- :tacn:`try`, :tacn:`repeat`, :tacn:`match goal`, or the branching tacticals. The
- :tacn:`fail` tactic will, however, succeed if all the goals have already been
- solved.
+ :tacn:`try`, :tacn:`repeat`, :tacn:`match goal`, or the branching tacticals.
.. tacv:: fail @num
The number is the failure level. If no level is specified, it defaults to 0.
The level is used by :tacn:`try`, :tacn:`repeat`, :tacn:`match goal` and the branching
- tacticals. If 0, it makes :tacn:`match goal` considering the next clause
- (backtracking). If non zero, the current :tacn:`match goal` block, :tacn:`try`,
+ tacticals. If 0, it makes :tacn:`match goal` consider the next clause
+ (backtracking). If nonzero, the current :tacn:`match goal` block, :tacn:`try`,
:tacn:`repeat`, or branching command is aborted and the level is decremented. In
- the case of :n:`+`, a non-zero level skips the first backtrack point, even if
+ the case of :n:`+`, a nonzero level skips the first backtrack point, even if
the call to :n:`fail @num` is not enclosed in a :n:`+` command,
respecting the algebraic identity.
@@ -572,7 +573,9 @@ Failing
.. tacv:: gfail
:name: gfail
- This variant fails even if there are no goals left.
+ This variant fails even when used after :n:`;` and there are no goals left.
+ Similarly, ``gfail`` fails even when used after ``all:`` and there are no
+ goals left. See the example for clarification.
.. tacv:: gfail {* message_token}
@@ -582,10 +585,41 @@ Failing
there are no goals left. Be careful however if Coq terms have to be
printed as part of the failure: term construction always forces the
tactic into the goals, meaning that if there are no goals when it is
- evaluated, a tactic call like :n:`let x:=H in fail 0 x` will succeed.
+ evaluated, a tactic call like :n:`let x := H in fail 0 x` will succeed.
.. exn:: Tactic Failure message (level @num).
+ .. exn:: No such goal.
+ :name: No such goal. (fail)
+
+ .. example::
+
+ .. coqtop:: all
+
+ Goal True.
+ Proof. fail. Abort.
+
+ Goal True.
+ Proof. trivial; fail. Qed.
+
+ Goal True.
+ Proof. trivial. fail. Abort.
+
+ Goal True.
+ Proof. trivial. all: fail. Qed.
+
+ Goal True.
+ Proof. gfail. Abort.
+
+ Goal True.
+ Proof. trivial; gfail. Abort.
+
+ Goal True.
+ Proof. trivial. gfail. Abort.
+
+ Goal True.
+ Proof. trivial. all: gfail. Abort.
+
Timeout
~~~~~~~
@@ -605,7 +639,7 @@ amount of time:
which is very machine-dependent: a script that works on a quick machine
may fail on a slow one. The converse is even possible if you combine a
timeout with some other tacticals. This tactical is hence proposed only
- for convenience during debug or other development phases, we strongly
+ for convenience during debugging or other development phases, we strongly
advise you to not leave any timeout in final scripts. Note also that
this tactical isn’t available on the native Windows port of Coq.
@@ -617,9 +651,9 @@ A tactic execution can be timed:
.. tacn:: time @string @expr
:name: time
- evaluates :n:`@expr` and displays the time the tactic expression ran, whether it
- fails or successes. In case of several successes, the time for each successive
- runs is displayed. Time is in seconds and is machine-dependent. The :n:`@string`
+ evaluates :n:`@expr` and displays the running time of the tactic expression, whether it
+ fails or succeeds. In case of several successes, the time for each successive
+ run is displayed. Time is in seconds and is machine-dependent. The :n:`@string`
argument is optional. When provided, it is used to identify this particular
occurrence of time.
@@ -685,12 +719,12 @@ Local definitions can be done as follows:
each :n:`@expr__i` is evaluated to :n:`v__i`, then, :n:`@expr` is evaluated
by substituting :n:`v__i` to each occurrence of :n:`@ident__i`, for
- i=1,...,n. There is no dependencies between the :n:`@expr__i` and the
+ i = 1, ..., n. There are no dependencies between the :n:`@expr__i` and the
:n:`@ident__i`.
- Local definitions can be recursive by using :n:`let rec` instead of :n:`let`.
+ Local definitions can be made recursive by using :n:`let rec` instead of :n:`let`.
In this latter case, the definitions are evaluated lazily so that the rec
- keyword can be used also in non recursive cases so as to avoid the eager
+ keyword can be used also in non-recursive cases so as to avoid the eager
evaluation of local definitions.
.. but rec changes the binding!!
@@ -704,7 +738,7 @@ An application is an expression of the following form:
The reference :n:`@qualid` must be bound to some defined tactic definition
expecting at least as many arguments as the provided :n:`tacarg`. The
- expressions :n:`@expr__i` are evaluated to :n:`v__i`, for i=1,...,n.
+ expressions :n:`@expr__i` are evaluated to :n:`v__i`, for i = 1, ..., n.
.. what expressions ??
@@ -755,7 +789,7 @@ We can carry out pattern matching on terms with:
evaluation of :n:`@expr__1` fails, or if the evaluation of
:n:`@expr__1` succeeds but returns a tactic in execution position whose
execution fails, then :n:`cpattern__2` is used and so on. The pattern
- :n:`_` matches any term and shunts all remaining patterns if any. If all
+ :n:`_` matches any term and shadows all remaining patterns if any. If all
clauses fail (in particular, there is no pattern :n:`_`) then a
no-matching-clause error is raised.
@@ -821,15 +855,15 @@ We can carry out pattern matching on terms with:
Pattern matching on goals
~~~~~~~~~~~~~~~~~~~~~~~~~
-We can make pattern matching on goals using the following expression:
+We can perform pattern matching on goals using the following expression:
.. we should provide the full grammar here
.. tacn:: match goal with {+| {+ hyp} |- @cpattern => @expr } | _ => @expr end
:name: match goal
- If each hypothesis pattern :n:`hyp`\ :sub:`1,i`, with i=1,...,m\ :sub:`1` is
- matched (non-linear first-order unification) by an hypothesis of the
+ If each hypothesis pattern :n:`hyp`\ :sub:`1,i`, with i = 1, ..., m\ :sub:`1` is
+ matched (non-linear first-order unification) by a hypothesis of the
goal and if :n:`cpattern_1` is matched by the conclusion of the goal,
then :n:`@expr__1` is evaluated to :n:`v__1` by substituting the
pattern matching to the metavariables and the real hypothesis names
@@ -857,10 +891,10 @@ We can make pattern matching on goals using the following expression:
It is important to know that each hypothesis of the goal can be matched
by at most one hypothesis pattern. The order of matching is the
- following: hypothesis patterns are examined from the right to the left
+ following: hypothesis patterns are examined from right to left
(i.e. hyp\ :sub:`i,m`\ :sub:`i`` before hyp\ :sub:`i,1`). For each
- hypothesis pattern, the goal hypothesis are matched in order (fresher
- hypothesis first), but it possible to reverse this order (older first)
+ hypothesis pattern, the goal hypotheses are matched in order (newest
+ first), but it possible to reverse this order (oldest first)
with the :n:`match reverse goal with` variant.
.. tacv:: multimatch goal with {+| {+ hyp} |- @cpattern => @expr } | _ => @expr end
@@ -896,6 +930,10 @@ produce subgoals but generates a term to be used in tactic expressions:
value of :n:`@ident` by the value of :n:`@expr`.
.. exn:: Not a context variable.
+ :undocumented:
+
+ .. exn:: Unbound context identifier @ident.
+ :undocumented:
Generating fresh hypothesis names
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -951,7 +989,7 @@ Manipulating untyped terms
An untyped term, in |Ltac|, can contain references to hypotheses or to
|Ltac| variables containing typed or untyped terms. An untyped term can be
- type-checked using the function type_term whose argument is parsed as an
+ type checked using the function type_term whose argument is parsed as an
untyped term and returns a well-typed term which can be used in tactics.
Untyped terms built using :n:`uconstr :` can also be used as arguments to the
@@ -1167,7 +1205,7 @@ Interactive debugger
This option governs the step-by-step debugger that comes with the |Ltac| interpreter
When the debugger is activated, it stops at every step of the evaluation of
-the current |Ltac| expression and it prints information on what it is doing.
+the current |Ltac| expression and prints information on what it is doing.
The debugger stops, prompting for a command which can be one of the
following:
@@ -1185,6 +1223,9 @@ following:
| r string: | advance up to the next call to “idtac string” |
+-----------------+-----------------------------------------------+
+.. exn:: Debug mode not available in the IDE
+ :undocumented:
+
A non-interactive mode for the debugger is available via the option:
.. opt:: Ltac Batch Debug
@@ -1204,9 +1245,9 @@ which can sometimes be so slow as to impede interactive usage. The
reasons for the performence degradation can be intricate, like a slowly
performing |Ltac| match or a sub-tactic whose performance only
degrades in certain situations. The profiler generates a call tree and
-indicates the time spent in a tactic depending its calling context. Thus
+indicates the time spent in a tactic depending on its calling context. Thus
it allows to locate the part of a tactic definition that contains the
-performance bug.
+performance issue.
.. opt:: Ltac Profiling
@@ -1240,8 +1281,12 @@ performance bug.
Goal forall x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z,
max x (max y z) = max (max x y) z /\ max x (max y z) = max (max x y) z
- /\ (A /\ B /\ C /\ D /\ E /\ F /\ G /\ H /\ I /\ J /\ K /\ L /\ M /\ N /\ O /\ P /\ Q /\ R /\ S /\ T /\ U /\ V /\ W /\ X /\ Y /\ Z
- -> Z /\ Y /\ X /\ W /\ V /\ U /\ T /\ S /\ R /\ Q /\ P /\ O /\ N /\ M /\ L /\ K /\ J /\ I /\ H /\ G /\ F /\ E /\ D /\ C /\ B /\ A).
+ /\
+ (A /\ B /\ C /\ D /\ E /\ F /\ G /\ H /\ I /\ J /\ K /\ L /\ M /\
+ N /\ O /\ P /\ Q /\ R /\ S /\ T /\ U /\ V /\ W /\ X /\ Y /\ Z
+ ->
+ Z /\ Y /\ X /\ W /\ V /\ U /\ T /\ S /\ R /\ Q /\ P /\ O /\ N /\
+ M /\ L /\ K /\ J /\ I /\ H /\ G /\ F /\ E /\ D /\ C /\ B /\ A).
Proof.
.. coqtop:: all
diff --git a/doc/sphinx/proof-engine/proof-handling.rst b/doc/sphinx/proof-engine/proof-handling.rst
index eba0db3ff5..b1e769c571 100644
--- a/doc/sphinx/proof-engine/proof-handling.rst
+++ b/doc/sphinx/proof-engine/proof-handling.rst
@@ -84,7 +84,7 @@ list of assertion commands is given in :ref:`Assertions`. The command
:name: Defined
Same as :cmd:`Qed` but the proof is then declared transparent, which means
- that its content can be explicitly used for type-checking and that it can be
+ that its content can be explicitly used for type checking and that it can be
unfolded in conversion tactics (see :ref:`performingcomputations`,
:cmd:`Opaque`, :cmd:`Transparent`).
@@ -315,13 +315,16 @@ Navigation in the proof tree
.. _curly-braces:
+.. index:: {
+ }
+
.. cmd:: %{ %| %}
The command ``{`` (without a terminating period) focuses on the first
goal, much like :cmd:`Focus` does, however, the subproof can only be
unfocused when it has been fully solved ( *i.e.* when there is no
focused goal left). Unfocusing is then handled by ``}`` (again, without a
- terminating period). See also example in next section.
+ terminating period). See also an example in the next section.
Note that when a focused goal is proved a message is displayed
together with a suggestion about the right bullet or ``}`` to unfocus it
@@ -329,20 +332,47 @@ Navigation in the proof tree
.. cmdv:: @num: %{
- This focuses on the :token:`num` th subgoal to prove.
+ This focuses on the :token:`num`\-th subgoal to prove.
+
+ .. cmdv:: [@ident]: %{
+
+ This focuses on the named goal :token:`ident`.
+
+ .. note::
+
+ Goals are just existential variables and existential variables do not
+ get a name by default. You can give a name to a goal by using :n:`refine ?[@ident]`.
- Error messages:
+ .. seealso:: :ref:`existential-variables`
+
+ .. example::
+
+ This can also be a way of focusing on a shelved goal, for instance:
+
+ .. coqtop:: all
+
+ Goal exists n : nat, n = n.
+ eexists ?[x].
+ reflexivity.
+ [x]: exact 0.
+ Qed.
.. exn:: This proof is focused, but cannot be unfocused this way.
You are trying to use ``}`` but the current subproof has not been fully solved.
- .. exn:: No such goal.
- :name: No such goal. (Focusing)
+ .. exn:: No such goal (@num).
+ :undocumented:
+
+ .. exn:: No such goal (@ident).
+ :undocumented:
+
+ .. exn:: Brackets do not support multi-goal selectors.
- .. exn:: Brackets only support the single numbered goal selector.
+ Brackets are used to focus on a single goal given either by its position
+ or by its name if it has one.
- See also error messages about bullets below.
+ .. seealso:: The error messages about bullets below.
.. _bullets:
@@ -358,8 +388,10 @@ same bullet ``b``. See the example below.
Different bullets can be used to nest levels. The scope of bullet does
not go beyond enclosing ``{`` and ``}``, so bullets can be reused as further
-nesting levels provided they are delimited by these. Available bullets
-are ``-``, ``+``, ``*``, ``--``, ``++``, ``**``, ``---``, ``+++``, ``***``, ... (without a terminating period).
+nesting levels provided they are delimited by these. Bullets are made of
+repeated ``-``, ``+`` or ``*`` symbols:
+
+.. prodn:: bullet ::= {+ - } %| {+ + } %| {+ * }
Note again that when a focused goal is proved a message is displayed
together with a suggestion about the right bullet or ``}`` to unfocus it
@@ -375,6 +407,7 @@ or focus the next one.
The following example script illustrates all these features:
.. example::
+
.. coqtop:: all
Goal (((True /\ True) /\ True) /\ True) /\ True.
@@ -391,19 +424,23 @@ The following example script illustrates all these features:
- assert True.
{ trivial. }
assumption.
+ Qed.
+.. exn:: Wrong bullet @bullet__1: Current bullet @bullet__2 is not finished.
-.. exn:: Wrong bullet @bullet1: Current bullet @bullet2 is not finished.
+ Before using bullet :n:`@bullet__1` again, you should first finish proving
+ the current focused goal.
+ Note that :n:`@bullet__1` and :n:`@bullet__2` may be the same.
- Before using bullet :n:`@bullet1` again, you should first finish proving the current focused goal. Note that :n:`@bullet1` and :n:`@bullet2` may be the same.
+.. exn:: Wrong bullet @bullet__1: Bullet @bullet__2 is mandatory here.
-.. exn:: Wrong bullet @bullet1: Bullet @bullet2 is mandatory here.
-
- You must put :n:`@bullet2` to focus next goal. No other bullet is allowed here.
+ You must put :n:`@bullet__2` to focus on the next goal. No other bullet is
+ allowed here.
.. exn:: No such goal. Focus next goal with bullet @bullet.
- You tried to apply a tactic but no goal where under focus. Using :n:`@bullet` is mandatory here.
+ You tried to apply a tactic but no goals were under focus.
+ Using :n:`@bullet` is mandatory here.
.. exn:: No such goal. Try unfocusing with %{.
@@ -432,7 +469,7 @@ Requesting information
.. cmdv:: Show @num
- Displays only the :token:`num` th subgoal.
+ Displays only the :token:`num`\-th subgoal.
.. exn:: No such goal.
@@ -470,7 +507,7 @@ Requesting information
constructed. These holes appear as a question mark indexed by an
integer, and applied to the list of variables in the context, since it
may depend on them. The types obtained by abstracting away the context
- from the type of each hole-placer are also printed.
+ from the type of each placeholder are also printed.
.. cmdv:: Show Conjectures
:name: Show Conjectures
@@ -511,6 +548,7 @@ Requesting information
:token:`ident`
.. example::
+
.. coqtop:: all
Show Match nat.
diff --git a/doc/sphinx/proof-engine/ssreflect-proof-language.rst b/doc/sphinx/proof-engine/ssreflect-proof-language.rst
index 6fb73a030f..7c3ea1a28c 100644
--- a/doc/sphinx/proof-engine/ssreflect-proof-language.rst
+++ b/doc/sphinx/proof-engine/ssreflect-proof-language.rst
@@ -37,7 +37,7 @@ bookkeeping is performed on the conclusion of the goal, using for that
purpose a couple of syntactic constructions behaving similar to tacticals
(and often named as such in this chapter). The ``:`` tactical moves hypotheses
from the context to the conclusion, while ``=>`` moves hypotheses from the
-conclusion to the context, and ``in`` moves back and forth an hypothesis from the
+conclusion to the context, and ``in`` moves back and forth a hypothesis from the
context to the conclusion for the time of applying an action to it.
While naming hypotheses is commonly done by means of an ``as`` clause in the
@@ -303,7 +303,7 @@ the ``if`` construct to all binary data types; compare
The latter appears to be marginally shorter, but it is quite
ambiguous, and indeed often requires an explicit annotation
-``(term : {_} + {_})`` to type-check, which evens the character count.
+``(term : {_} + {_})`` to type check, which evens the character count.
Therefore, |SSR| restricts by default the condition of a plain if
construct to the standard ``bool`` type; this avoids spurious type
@@ -385,7 +385,7 @@ expressions such as
Unfortunately, such higher-order expressions are quite frequent in
representation functions, especially those which use |Coq|'s
-``Structures`` to emulate Haskell type classes.
+``Structures`` to emulate Haskell typeclasses.
Therefore, |SSR| provides a variant of |Coq|’s implicit argument
declaration, which causes |Coq| to fill in some implicit parameters at
@@ -1285,7 +1285,7 @@ catch the appropriate number of wildcards to be inserted. Note that
this use of the refine tactic implies that the tactic tries to match
the goal up to expansion of constants and evaluation of subterms.
-|SSR|’s apply has a special behaviour on goals containing
+|SSR|’s apply has a special behavior on goals containing
existential metavariables of sort Prop.
.. example::
@@ -2064,26 +2064,27 @@ is equivalent to:
(see section :ref:`discharge_ssr` for the documentation of the apply: combination).
-Warning The list of tactics, possibly chained by semicolons, that
-follows a by keyword is considered as a parenthesized block applied to
-the current goal. Hence for example if the tactic:
+.. warning::
-.. coqtop:: in
+ The list of tactics (possibly chained by semicolons) that
+ follows the ``by`` keyword is considered to be a parenthesized block applied to
+ the current goal. Hence for example if the tactic:
- by rewrite my_lemma1.
+ .. coqtop:: in
-succeeds, then the tactic:
+ by rewrite my_lemma1.
-.. coqtop:: in
+ succeeds, then the tactic:
- by rewrite my_lemma1; apply my_lemma2.
+ .. coqtop:: in
-usually fails since it is equivalent to:
+ by rewrite my_lemma1; apply my_lemma2.
-.. coqtop:: in
+ usually fails since it is equivalent to:
- by (rewrite my_lemma1; apply my_lemma2).
+ .. coqtop:: in
+ by (rewrite my_lemma1; apply my_lemma2).
.. _selectors_ssr:
@@ -2522,7 +2523,8 @@ After the :token:`i_pattern`, a list of binders is allowed.
.. coqtop:: reset
- From Coq Require Import ssreflect Omega.
+ From Coq Require Import ssreflect.
+ From Coq Require Import Omega.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
@@ -2552,12 +2554,9 @@ copying the goal itself.
.. example::
- .. coqtop:: reset
+ .. coqtop:: none
- From Coq Require Import ssreflect.
- Set Implicit Arguments.
- Unset Strict Implicit.
- Unset Printing Implicit Defensive.
+ Abort All.
.. coqtop:: all
@@ -2581,12 +2580,9 @@ context entry name.
.. example::
- .. coqtop:: reset
+ .. coqtop:: none
- From Coq Require Import ssreflect Omega.
- Set Implicit Arguments.
- Unset Strict Implicit.
- Unset Printing Implicit Defensive.
+ Abort All.
Set Printing Depth 15.
.. coqtop:: all
@@ -2601,20 +2597,13 @@ context entry name.
Note that the sub-term produced by ``omega`` is in general huge and
uninteresting, and hence one may want to hide it.
For this purpose the ``[: name ]`` intro pattern and the tactic
-``abstract`` (see page :ref:`abstract_ssr`) are provided.
+``abstract`` (see :ref:`abstract_ssr`) are provided.
.. example::
- .. coqtop:: reset
+ .. coqtop:: none
- From Coq Require Import ssreflect Omega.
- Set Implicit Arguments.
- Unset Strict Implicit.
- Unset Printing Implicit Defensive.
-
- Inductive Ord n := Sub x of x < n.
- Notation "'I_ n" := (Ord n) (at level 8, n at level 2, format "''I_' n").
- Arguments Sub {_} _ _.
+ Abort All.
.. coqtop:: all
@@ -2629,16 +2618,9 @@ with have and an explicit term, they must be used as follows:
.. example::
- .. coqtop:: reset
-
- From Coq Require Import ssreflect Omega.
- Set Implicit Arguments.
- Unset Strict Implicit.
- Unset Printing Implicit Defensive.
+ .. coqtop:: none
- Inductive Ord n := Sub x of x < n.
- Notation "'I_ n" := (Ord n) (at level 8, n at level 2, format "''I_' n").
- Arguments Sub {_} _ _.
+ Abort All.
.. coqtop:: all
@@ -2659,16 +2641,9 @@ makes use of it).
.. example::
- .. coqtop:: reset
+ .. coqtop:: none
- From Coq Require Import ssreflect Omega.
- Set Implicit Arguments.
- Unset Strict Implicit.
- Unset Printing Implicit Defensive.
-
- Inductive Ord n := Sub x of x < n.
- Notation "'I_ n" := (Ord n) (at level 8, n at level 2, format "''I_' n").
- Arguments Sub {_} _ _.
+ Abort All.
.. coqtop:: all
@@ -2679,18 +2654,15 @@ Last, notice that the use of intro patterns for abstract constants is
orthogonal to the transparent flag ``@`` for have.
-The have tactic and type classes resolution
+The have tactic and typeclass resolution
```````````````````````````````````````````
-Since |SSR| 1.5 the have tactic behaves as follows with respect to
-type classes inference.
+Since |SSR| 1.5 the ``have`` tactic behaves as follows with respect to
+typeclass inference.
- .. coqtop:: reset
+ .. coqtop:: none
- From Coq Require Import ssreflect Omega.
- Set Implicit Arguments.
- Unset Strict Implicit.
- Unset Printing Implicit Defensive.
+ Abort All.
Axiom ty : Type.
Axiom t : ty.
@@ -2728,7 +2700,7 @@ type classes inference.
.. opt:: SsrHave NoTCResolution
- This option restores the behavior of |SSR| 1.4 and below (never resolve type classes).
+ This option restores the behavior of |SSR| 1.4 and below (never resolve typeclasses).
Variants: the suff and wlog tactics
```````````````````````````````````
@@ -2766,12 +2738,9 @@ The ``have`` modifier can follow the ``suff`` tactic.
.. example::
- .. coqtop:: reset
+ .. coqtop:: none
- From Coq Require Import ssreflect Omega.
- Set Implicit Arguments.
- Unset Strict Implicit.
- Unset Printing Implicit Defensive.
+ Abort All.
Axioms G P : Prop.
.. coqtop:: all
@@ -2839,12 +2808,9 @@ are unique.
.. example::
- .. coqtop:: reset
+ .. coqtop:: none
- From Coq Require Import ssreflect Omega.
- Set Implicit Arguments.
- Unset Strict Implicit.
- Unset Printing Implicit Defensive.
+ Abort All.
.. coqtop:: all
@@ -2935,12 +2901,10 @@ illustrated in the following example.
the pattern ``id (addx x)``, that would produce the following first
subgoal
- .. coqtop:: reset
+ .. coqtop:: none
- From Coq Require Import ssreflect Omega.
- Set Implicit Arguments.
- Unset Strict Implicit.
- Unset Printing Implicit Defensive.
+ Abort All.
+ From Coq Require Import Omega.
Section Test.
Variable x : nat.
Definition addx z := z + x.
@@ -3046,6 +3010,15 @@ An :token:`r_item` can be:
is equivalent to: ``change term1 with term2.`` If ``term2`` is a
single constant and ``term1`` head symbol is not ``term2``, then the head
symbol of ``term1`` is repeatedly unfolded until ``term2`` appears.
++ A :token:`term`, which can be:
+ + A term whose type has the form:
+ ``forall (x1 : A1 )…(xn : An ), eq term1 term2`` where
+ ``eq`` is the Leibniz equality or a registered setoid
+ equality.
+ + A list of terms ``(t1 ,…,tn)``, each ``ti`` having a type above.
+ The tactic: ``rewrite r_prefix (t1 ,…,tn ).``
+ is equivalent to: ``do [rewrite r_prefix t1 | … | rewrite r_prefix tn ].``
+ + An anonymous rewrite lemma ``(_ : term)``, where term has a type as above. tactic: ``rewrite (_ : term)`` is in fact synonym of: ``cutrewrite (term).``.
.. example::
@@ -3063,9 +3036,10 @@ An :token:`r_item` can be:
Lemma test x : ddouble x = 4 * x.
rewrite [ddouble _]/double.
- *Warning* The |SSR|
- terms containing holes are *not* typed as abstractions in this
- context. Hence the following script fails.
+ .. warning::
+
+ The |SSR| terms containing holes are *not* typed as
+ abstractions in this context. Hence the following script fails.
.. coqtop:: none
@@ -3087,17 +3061,6 @@ An :token:`r_item` can be:
rewrite -[f y x]/(y + _).
-+ A :token:`term`, which can be:
-
- + A term whose type has the form:
- ``forall (x1 : A1 )…(xn : An ), eq term1 term2`` where
- ``eq`` is the Leibniz equality or a registered setoid
- equality.
- + A list of terms ``(t1 ,…,tn)``, each ``ti`` having a type above.
- The tactic: ``rewrite r_prefix (t1 ,…,tn ).``
- is equivalent to: ``do [rewrite r_prefix t1 | … | rewrite r_prefix tn ].``
- + An anonymous rewrite lemma ``(_ : term)``, where term has a type as above. tactic: ``rewrite (_ : term)`` is in fact synonym of: ``cutrewrite (term).``.
-
Remarks and examples
~~~~~~~~~~~~~~~~~~~~
@@ -3738,20 +3701,22 @@ Note that ``nosimpl bar`` is simply notation for a term that reduces to
``bar``; hence ``unfold foo`` will replace ``foo`` by ``bar``, and
``fold foo`` will replace ``bar`` by ``foo``.
-*Warning* The ``nosimpl`` trick only works if no reduction is apparent in
-``t``; in particular, the declaration:
+.. warning::
-.. coqtop:: in
+ The ``nosimpl`` trick only works if no reduction is apparent in
+ ``t``; in particular, the declaration:
- Definition foo x := nosimpl (bar x).
+ .. coqtop:: in
-will usually not work. Anyway, the common practice is to tag only the
-function, and to use the following definition, which blocks the
-reduction as expected:
+ Definition foo x := nosimpl (bar x).
-.. coqtop:: in
+ will usually not work. Anyway, the common practice is to tag only the
+ function, and to use the following definition, which blocks the
+ reduction as expected:
- Definition foo x := nosimpl bar x.
+ .. coqtop:: in
+
+ Definition foo x := nosimpl bar x.
A standard example making this technique shine is the case of
arithmetic operations. We define for instance:
@@ -4632,6 +4597,7 @@ bookkeeping steps.
.. example::
+
The following example use the ``~~`` prenex notation for boolean negation:
@@ -4793,7 +4759,7 @@ equivalence property has been defined.
Lemma andE (b1 b2 : bool) : (b1 /\ b2) <-> (b1 && b2).
-Let us compare the respective behaviours of ``andE`` and ``andP``.
+Let us compare the respective behaviors of ``andE`` and ``andP``.
.. example::
@@ -4906,7 +4872,7 @@ The term , called the *view lemma* can be:
Let ``top`` be the top assumption in the goal.
-There are three steps in the behaviour of an assumption view tactic:
+There are three steps in the behavior of an assumption view tactic:
+ It first introduces ``top``.
+ If the type of :token:`term` is neither a double implication nor an
diff --git a/doc/sphinx/proof-engine/tactics.rst b/doc/sphinx/proof-engine/tactics.rst
index d0a0d568ea..241cdf5eea 100644
--- a/doc/sphinx/proof-engine/tactics.rst
+++ b/doc/sphinx/proof-engine/tactics.rst
@@ -26,8 +26,8 @@ address a particular goal in the list by writing n:tactic which means
“apply tactic tactic to goal number n”. We can show the list of
subgoals by typing Show (see Section :ref:`requestinginformation`).
-Since not every rule applies to a given statement, every tactic cannot
-be used to reduce any goal. In other words, before applying a tactic
+Since not every rule applies to a given statement, not every tactic can
+be used to reduce a given goal. In other words, before applying a tactic
to a given goal, the system checks that some *preconditions* are
satisfied. If it is not the case, the tactic raises an error message.
@@ -107,37 +107,37 @@ bindings_list`` where ``bindings_list`` may be of two different forms:
.. _occurencessets:
-Occurrences sets and occurrences clauses
+Occurrence sets and occurrence clauses
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-An occurrences clause is a modifier to some tactics that obeys the
+An occurrence clause is a modifier to some tactics that obeys the
following syntax:
-.. _tactic_occurence_grammar:
-
.. productionlist:: `sentence`
- occurence_clause : in `goal_occurences`
- goal_occurences : [ident [`at_occurences`], ... , ident [`at_occurences`] [|- [* [`at_occurences`]]]]
- :| * |- [* [`at_occurences`]]
+ occurrence_clause : in `goal_occurrences`
+ goal_occurrences : [`ident` [`at_occurrences`], ... , ident [`at_occurrences`] [|- [* [`at_occurrences`]]]]
+ :| * |- [* [`at_occurrences`]]
:| *
at_occurrences : at `occurrences`
- occurences : [-] `num` ... `num`
-
-The role of an occurrence clause is to select a set of occurrences of a term in
-a goal. In the first case, the :n:`@ident {? at {* num}}` parts indicate that
-occurrences have to be selected in the hypotheses named :n:`@ident`. If no
-numbers are given for hypothesis :n:`@ident`, then all the occurrences of `term`
-in the hypothesis are selected. If numbers are given, they refer to occurrences
-of `term` when the term is printed using option :opt:`Printing All`, counting
-from left to right. In particular, occurrences of `term` in implicit arguments
-(see :ref:`ImplicitArguments`) or coercions (see :ref:`Coercions`) are counted.
-
-If a minus sign is given between at and the list of occurrences, it
+ occurrences : [-] `num` ... `num`
+
+The role of an occurrence clause is to select a set of occurrences of a term
+in a goal. In the first case, the :n:`@ident {? at {* num}}` parts indicate
+that occurrences have to be selected in the hypotheses named :token:`ident`.
+If no numbers are given for hypothesis :token:`ident`, then all the
+occurrences of :token:`term` in the hypothesis are selected. If numbers are
+given, they refer to occurrences of :token:`term` when the term is printed
+using option :opt:`Printing All`, counting from left to right. In particular,
+occurrences of :token:`term` in implicit arguments
+(see :ref:`ImplicitArguments`) or coercions (see :ref:`Coercions`) are
+counted.
+
+If a minus sign is given between ``at`` and the list of occurrences, it
negates the condition so that the clause denotes all the occurrences
except the ones explicitly mentioned after the minus sign.
As an exception to the left-to-right order, the occurrences in
-thereturn subexpression of a match are considered *before* the
+the return subexpression of a match are considered *before* the
occurrences in the matched term.
In the second case, the ``*`` on the left of ``|-`` means that all occurrences
@@ -146,18 +146,20 @@ of term are selected in every hypothesis.
In the first and second case, if ``*`` is mentioned on the right of ``|-``, the
occurrences of the conclusion of the goal have to be selected. If some numbers
are given, then only the occurrences denoted by these numbers are selected. If
-no numbers are given, all occurrences of :n:`@term` in the goal are selected.
+no numbers are given, all occurrences of :token:`term` in the goal are selected.
Finally, the last notation is an abbreviation for ``* |- *``. Note also
that ``|-`` is optional in the first case when no ``*`` is given.
-Here are some tactics that understand occurrences clauses: :tacn:`set`, :tacn:`remember`
-, :tacn:`induction`, :tacn:`destruct`.
+Here are some tactics that understand occurrence clauses: :tacn:`set`,
+:tacn:`remember`, :tacn:`induction`, :tacn:`destruct`.
+
+
+.. seealso::
+ :ref:`Managingthelocalcontext`, :ref:`caseanalysisandinduction`,
+ :ref:`printing_constructions_full`.
-See also: :ref:`Managingthelocalcontext`,
-:ref:`caseanalysisandinduction`,
-:ref:`printing_constructions_full`.
.. _applyingtheorems:
@@ -173,40 +175,45 @@ Applying theorems
:ref:`Conversion-rules`).
.. exn:: Not an exact proof.
+ :undocumented:
.. tacv:: eexact @term.
:name: eexact
- This tactic behaves like exact but is able to handle terms and goals with
- meta-variables.
+ This tactic behaves like :tacn:`exact` but is able to handle terms and
+ goals with existential variables.
.. tacn:: assumption
:name: assumption
- This tactic looks in the local context for an hypothesis which type is equal to
- the goal. If it is the case, the subgoal is proved. Otherwise, it fails.
+ This tactic looks in the local context for a hypothesis whose type is
+ convertible to the goal. If it is the case, the subgoal is proved.
+ Otherwise, it fails.
.. exn:: No such assumption.
+ :undocumented:
.. tacv:: eassumption
:name: eassumption
- This tactic behaves like assumption but is able to handle goals with
- meta-variables.
+ This tactic behaves like :tacn:`assumption` but is able to handle
+ goals with existential variables.
.. tacn:: refine @term
:name: refine
This tactic applies to any goal. It behaves like :tacn:`exact` with a big
- difference: the user can leave some holes (denoted by ``_`` or ``(_:type)``) in
- the term. :tacn:`refine` will generate as many subgoals as there are holes in
- the term. The type of holes must be either synthesized by the system
- or declared by an explicit cast like ``(_:nat->Prop)``. Any subgoal that
+ difference: the user can leave some holes (denoted by ``_``
+ or :n:`(_ : @type)`) in the term. :tacn:`refine` will generate as many
+ subgoals as there are holes in the term. The type of holes must be either
+ synthesized by the system or declared by an explicit cast
+ like ``(_ : nat -> Prop)``. Any subgoal that
occurs in other subgoals is automatically shelved, as if calling
:tacn:`shelve_unifiable`. This low-level tactic can be
useful to advanced users.
.. example::
+
.. coqtop:: reset all
Inductive Option : Set :=
@@ -214,16 +221,13 @@ Applying theorems
| Ok : bool -> Option.
Definition get : forall x:Option, x <> Fail -> bool.
-
- refine
- (fun x:Option =>
- match x return x <> Fail -> bool with
- | Fail => _
- | Ok b => fun _ => b
- end).
-
- intros; absurd (Fail = Fail); trivial.
-
+ refine
+ (fun x:Option =>
+ match x return x <> Fail -> bool with
+ | Fail => _
+ | Ok b => fun _ => b
+ end).
+ intros; absurd (Fail = Fail); trivial.
Defined.
.. exn:: Invalid argument.
@@ -251,41 +255,43 @@ Applying theorems
.. tacv:: notypeclasses refine @term
:name: notypeclasses refine
- This tactic behaves like :tacn:`refine` except it performs typechecking without
+ This tactic behaves like :tacn:`refine` except it performs type checking without
resolution of typeclasses.
.. tacv:: simple notypeclasses refine @term
:name: simple notypeclasses refine
- This tactic behaves like :tacn:`simple refine` except it performs typechecking
+ This tactic behaves like :tacn:`simple refine` except it performs type checking
without resolution of typeclasses.
.. tacn:: apply @term
:name: apply
- This tactic applies to any goal. The argument term is a term well-formed in the
- local context. The tactic apply tries to match the current goal against the
- conclusion of the type of term. If it succeeds, then the tactic returns as many
- subgoals as the number of non-dependent premises of the type of term. If the
- conclusion of the type of term does not match the goal *and* the conclusion is
- an inductive type isomorphic to a tuple type, then each component of the tuple
- is recursively matched to the goal in the left-to-right order.
-
- The tactic :tacn:`apply` relies on first-order unification with dependent types
- unless the conclusion of the type of :token:`term` is of the form :g:`P (t`:sub:`1`
- :g:`...` :g:`t`:sub:`n` :g:`)` with `P` to be instantiated. In the latter case, the behavior
- depends on the form of the goal. If the goal is of the form
- :g:`(fun x => Q) u`:sub:`1` :g:`...` :g:`u`:sub:`n` and the :g:`t`:sub:`i` and
- :g:`u`:sub:`i` unifies, then :g:`P` is taken to be :g:`(fun x => Q)`. Otherwise,
- :tacn:`apply` tries to define :g:`P` by abstracting over :g:`t`:sub:`1` :g:`...`
- :g:`t`:sub:`n` in the goal. See :tacn:`pattern` to transform the goal so that it
- gets the form :g:`(fun x => Q) u`:sub:`1` :g:`...` :g:`u`:sub:`n`.
-
- .. exn:: Unable to unify ... with ... .
-
- The apply tactic failed to match the conclusion of :token:`term` and the
- current goal. You can help the apply tactic by transforming your goal with
- the :tacn:`change` or :tacn:`pattern` tactics.
+ This tactic applies to any goal. The argument term is a term well-formed in
+ the local context. The tactic :tacn:`apply` tries to match the current goal
+ against the conclusion of the type of :token:`term`. If it succeeds, then
+ the tactic returns as many subgoals as the number of non-dependent premises
+ of the type of term. If the conclusion of the type of :token:`term` does
+ not match the goal *and* the conclusion is an inductive type isomorphic to
+ a tuple type, then each component of the tuple is recursively matched to
+ the goal in the left-to-right order.
+
+ The tactic :tacn:`apply` relies on first-order unification with dependent
+ types unless the conclusion of the type of :token:`term` is of the form
+ :n:`P (t__1 ... t__n)` with ``P`` to be instantiated. In the latter case,
+ the behavior depends on the form of the goal. If the goal is of the form
+ :n:`(fun x => Q) u__1 ... u__n` and the :n:`t__i` and :n:`u__i` unify,
+ then :g:`P` is taken to be :g:`(fun x => Q)`. Otherwise, :tacn:`apply`
+ tries to define :g:`P` by abstracting over :g:`t_1 ... t__n` in the goal.
+ See :tacn:`pattern` to transform the goal so that it
+ gets the form :n:`(fun x => Q) u__1 ... u__n`.
+
+ .. exn:: Unable to unify @term with @term.
+
+ The :tacn:`apply` tactic failed to match the conclusion of :token:`term`
+ and the current goal. You can help the :tacn:`apply` tactic by
+ transforming your goal with the :tacn:`change` or :tacn:`pattern`
+ tactics.
.. exn:: Unable to find an instance for the variables {+ @ident}.
@@ -301,6 +307,7 @@ Applying theorems
according to the order of these dependent premises of the type of term.
.. exn:: Not the right number of missing arguments.
+ :undocumented:
.. tacv:: apply @term with @bindings_list
@@ -310,11 +317,9 @@ Applying theorems
.. tacv:: apply {+, @term}
- This is a shortcut for :n:`apply @term`:sub:`1`
- :n:`; [.. | ... ; [ .. | apply @term`:sub:`n` :n:`] ... ]`,
- i.e. for the successive applications of :token:`term`:sub:`i+1` on the last subgoal
- generated by :n:`apply @term`:sub:`i` , starting from the application of
- :token:`term`:sub:`1`.
+ This is a shortcut for :n:`apply @term__1; [.. | ... ; [ .. | apply @term__n] ... ]`,
+ i.e. for the successive applications of :n:`@term`:sub:`i+1` on the last subgoal
+ generated by :n:`apply @term__i` , starting from the application of :n:`@term__1`.
.. tacv:: eapply @term
:name: eapply
@@ -326,7 +331,6 @@ Applying theorems
intended to be found later in the proof.
.. tacv:: simple apply @term.
- :name: simple apply
This behaves like :tacn:`apply` but it reasons modulo conversion only on subterms
that contain no variables to instantiate. For instance, the following example
@@ -348,8 +352,8 @@ Applying theorems
does.
.. tacv:: {? simple} apply {+, @term {? with @bindings_list}}
- .. tacv:: {? simple} eapply {+, @term {? with @bindings_list}}
- :name: simple eapply
+ {? simple} eapply {+, @term {? with @bindings_list}}
+ :name: simple apply; simple eapply
This summarizes the different syntaxes for :tacn:`apply` and :tacn:`eapply`.
@@ -364,8 +368,10 @@ Applying theorems
sequence ``cut B. 2:apply H.`` where ``cut`` is described below.
.. warn:: When @term contains more than one non dependent product the tactic lapply only takes into account the first product.
+ :undocumented:
.. example::
+
Assume we have a transitive relation ``R`` on ``nat``:
.. coqtop:: reset in
@@ -453,164 +459,151 @@ Applying theorems
.. tacn:: apply @term in @ident
:name: apply ... in
- This tactic applies to any goal. The argument ``term`` is a term well-formed in
- the local context and the argument :n:`@ident` is an hypothesis of the context.
- The tactic ``apply term in ident`` tries to match the conclusion of the type
- of :n:`@ident` against a non-dependent premise of the type of ``term``, trying
- them from right to left. If it succeeds, the statement of hypothesis
- :n:`@ident` is replaced by the conclusion of the type of ``term``. The tactic
- also returns as many subgoals as the number of other non-dependent premises
- in the type of ``term`` and of the non-dependent premises of the type of
- :n:`@ident`. If the conclusion of the type of ``term`` does not match the goal
- *and* the conclusion is an inductive type isomorphic to a tuple type, then
+ This tactic applies to any goal. The argument :token:`term` is a term
+ well-formed in the local context and the argument :token:`ident` is an
+ hypothesis of the context.
+ The tactic :n:`apply @term in @ident` tries to match the conclusion of the
+ type of :token:`ident` against a non-dependent premise of the type
+ of :token:`term`, trying them from right to left. If it succeeds, the
+ statement of hypothesis :token:`ident` is replaced by the conclusion of
+ the type of :token:`term`. The tactic also returns as many subgoals as the
+ number of other non-dependent premises in the type of :token:`term` and of
+ the non-dependent premises of the type of :token:`ident`. If the conclusion
+ of the type of :token:`term` does not match the goal *and* the conclusion
+ is an inductive type isomorphic to a tuple type, then
the tuple is (recursively) decomposed and the first component of the tuple
of which a non-dependent premise matches the conclusion of the type of
- :n:`@ident`. Tuples are decomposed in a width-first left-to-right order (for
- instance if the type of :g:`H1` is a :g:`A <-> B` statement, and the type of
- :g:`H2` is :g:`A` then ``apply H1 in H2`` transforms the type of :g:`H2`
- into :g:`B`). The tactic ``apply`` relies on first-order pattern-matching
+ :token:`ident`. Tuples are decomposed in a width-first left-to-right order
+ (for instance if the type of :g:`H1` is :g:`A <-> B` and the type of
+ :g:`H2` is :g:`A` then :g:`apply H1 in H2` transforms the type of :g:`H2`
+ into :g:`B`). The tactic :tacn:`apply` relies on first-order pattern-matching
with dependent types.
-.. exn:: Statement without assumptions.
-
- This happens if the type of ``term`` has no non dependent premise.
+ .. exn:: Statement without assumptions.
-.. exn:: Unable to apply.
+ This happens if the type of :token:`term` has no non-dependent premise.
- This happens if the conclusion of :n:`@ident` does not match any of the non
- dependent premises of the type of ``term``.
+ .. exn:: Unable to apply.
-.. tacv:: apply {+, @term} in @ident
+ This happens if the conclusion of :token:`ident` does not match any of
+ the non-dependent premises of the type of :token:`term`.
- This applies each of ``term`` in sequence in :n:`@ident`.
+ .. tacv:: apply {+, @term} in @ident
-.. tacv:: apply {+, @term with @bindings_list} in @ident
+ This applies each :token:`term` in sequence in :token:`ident`.
- This does the same but uses the bindings in each :n:`(@id := @ val)` to
- instantiate the parameters of the corresponding type of ``term`` (see
- :ref:`bindings list <bindingslist>`).
+ .. tacv:: apply {+, @term with @bindings_list} in @ident
-.. tacv:: eapply {+, @term with @bindings_list} in @ident
+ This does the same but uses the bindings in each :n:`(@ident := @term)` to
+ instantiate the parameters of the corresponding type of :token:`term`
+ (see :ref:`bindings list <bindingslist>`).
- This works as :tacn:`apply ... in` but turns unresolved bindings into
- existential variables, if any, instead of failing.
+ .. tacv:: eapply {+, @term {? with @bindings_list } } in @ident
-.. tacv:: apply {+, @term with @bindings_list} in @ident as @intro_pattern
- :name: apply ... in ... as
+ This works as :tacn:`apply ... in` but turns unresolved bindings into
+ existential variables, if any, instead of failing.
- This works as :tacn:`apply ... in` then applies the
- :n:`@intro_pattern` to the hypothesis :n:`@ident`.
+ .. tacv:: apply {+, @term {? with @bindings_list } } in @ident as @intro_pattern
+ :name: apply ... in ... as
-.. tacv:: eapply {+, @term with @bindings_list} in @ident as @intro_pattern.
+ This works as :tacn:`apply ... in` then applies the :token:`intro_pattern`
+ to the hypothesis :token:`ident`.
- This works as :tacn:`apply ... in ... as` but using ``eapply``.
+ .. tacv:: simple apply @term in @ident
-.. tacv:: simple apply @term in @ident
+ This behaves like :tacn:`apply ... in` but it reasons modulo conversion
+ only on subterms that contain no variables to instantiate. For instance,
+ if :g:`id := fun x:nat => x` and :g:`H: forall y, id y = y -> True` and
+ :g:`H0 : O = O` then :g:`simple apply H in H0` does not succeed because it
+ would require the conversion of :g:`id ?x` and :g:`O` where :g:`?x` is
+ an existential variable to instantiate.
+ Tactic :n:`simple apply @term in @ident` does not
+ either traverse tuples as :n:`apply @term in @ident` does.
- This behaves like :tacn:`apply ... in` but it reasons modulo conversion only
- on subterms that contain no variables to instantiate. For instance, if
- :g:`id := fun x:nat => x` and :g:`H: forall y, id y = y -> True` and
- :g:`H0 : O = O` then ``simple apply H in H0`` does not succeed because it
- would require the conversion of :g:`id ?x` and :g:`O` where :g:`?x` is
- an existential variable to instantiate. Tactic :n:`simple apply @term in @ident` does not
- either traverse tuples as :n:`apply @term in @ident` does.
+ .. tacv:: {? simple} apply {+, @term {? with @bindings_list}} in @ident {? as @intro_pattern}
+ {? simple} eapply {+, @term {? with @bindings_list}} in @ident {? as @intro_pattern}
-.. tacv:: {? simple} apply {+, @term {? with @bindings_list}} in @ident {? as @intro_pattern}
-.. tacv:: {? simple} eapply {+, @term {? with @bindings_list}} in @ident {? as @intro_pattern}
-
- This summarizes the different syntactic variants of :n:`apply @term in @ident`
- and :n:`eapply @term in @ident`.
+ This summarizes the different syntactic variants of :n:`apply @term in @ident`
+ and :n:`eapply @term in @ident`.
.. tacn:: constructor @num
:name: constructor
This tactic applies to a goal such that its conclusion is an inductive
- type (say :g:`I`). The argument :n:`@num` must be less or equal to the
- numbers of constructor(s) of :g:`I`. Let :g:`c`:sub:`i` be the i-th
- constructor of :g:`I`, then ``constructor i`` is equivalent to
- ``intros; apply c``:sub:`i`.
-
-.. exn:: Not an inductive product.
-.. exn:: Not enough constructors.
-
-.. tacv:: constructor
-
- This tries :g:`constructor`:sub:`1` then :g:`constructor`:sub:`2`, ..., then
- :g:`constructor`:sub:`n` where `n` is the number of constructors of the head
- of the goal.
-
-.. tacv:: constructor @num with @bindings_list
-
- Let ``c`` be the i-th constructor of :g:`I`, then
- :n:`constructor i with @bindings_list` is equivalent to
- :n:`intros; apply c with @bindings_list`.
-
- .. warn::
- The terms in the @bindings_list are checked in the context where constructor is executed and not in the context where @apply is executed (the introductions are not taken into account).
+ type (say :g:`I`). The argument :token:`num` must be less or equal to the
+ numbers of constructor(s) of :g:`I`. Let :n:`c__i` be the i-th
+ constructor of :g:`I`, then :g:`constructor i` is equivalent to
+ :n:`intros; apply c__i`.
-.. tacv:: split
- :name: split
+ .. exn:: Not an inductive product.
+ :undocumented:
- This applies only if :g:`I` has a single constructor. It is then
- equivalent to :n:`constructor 1.`. It is typically used in the case of a
- conjunction :g:`A` :math:`\wedge` :g:`B`.
+ .. exn:: Not enough constructors.
+ :undocumented:
-.. exn:: Not an inductive goal with 1 constructor
+ .. tacv:: constructor
-.. tacv:: exists @val
- :name: exists
+ This tries :g:`constructor 1` then :g:`constructor 2`, ..., then
+ :g:`constructor n` where ``n`` is the number of constructors of the head
+ of the goal.
- This applies only if :g:`I` has a single constructor. It is then equivalent
- to :n:`intros; constructor 1 with @bindings_list.` It is typically used in
- the case of an existential quantification :math:`\exists`:g:`x, P(x).`
+ .. tacv:: constructor @num with @bindings_list
-.. exn:: Not an inductive goal with 1 constructor.
+ Let ``c`` be the i-th constructor of :g:`I`, then
+ :n:`constructor i with @bindings_list` is equivalent to
+ :n:`intros; apply c with @bindings_list`.
-.. tacv:: exists @bindings_list
+ .. warning::
- This iteratively applies :n:`exists @bindings_list`.
+ The terms in the :token:`bindings_list` are checked in the context
+ where constructor is executed and not in the context where :tacn:`apply`
+ is executed (the introductions are not taken into account).
-.. tacv:: left
- :name: left
+ .. tacv:: split {? with @bindings_list }
+ :name: split
-.. tacv:: right
- :name: right
+ This applies only if :g:`I` has a single constructor. It is then
+ equivalent to :n:`constructor 1 {? with @bindings_list }`. It is
+ typically used in the case of a conjunction :math:`A \wedge B`.
- These tactics apply only if :g:`I` has two constructors, for
- instance in the case of a disjunction :g:`A` :math:`\vee` :g:`B`.
- Then, they are respectively equivalent to ``constructor 1`` and
- ``constructor 2``.
+ .. tacv:: exists @bindings_list
+ :name: exists
-.. exn:: Not an inductive goal with 2 constructors.
+ This applies only if :g:`I` has a single constructor. It is then equivalent
+ to :n:`intros; constructor 1 with @bindings_list.` It is typically used in
+ the case of an existential quantification :math:`\exists x, P(x).`
-.. tacv:: left with @bindings_list
-.. tacv:: right with @bindings_list
-.. tacv:: split with @bindings_list
+ .. tacv:: exists {+, @bindings_list }
- As soon as the inductive type has the right number of constructors, these
- expressions are equivalent to calling :n:`constructor i with @bindings_list`
- for the appropriate ``i``.
+ This iteratively applies :n:`exists @bindings_list`.
-.. tacv:: econstructor
- :name: econstructor
+ .. exn:: Not an inductive goal with 1 constructor.
+ :undocumented:
-.. tacv:: eexists
- :name: eexists
+ .. tacv:: left {? with @bindings_list }
+ right {? with @bindings_list }
+ :name: left; right
-.. tacv:: esplit
- :name: esplit
+ These tactics apply only if :g:`I` has two constructors, for
+ instance in the case of a disjunction :math:`A \vee B`.
+ Then, they are respectively equivalent to
+ :n:`constructor 1 {? with @bindings_list }` and
+ :n:`constructor 2 {? with @bindings_list }`.
-.. tacv:: eleft
- :name: eleft
+ .. exn:: Not an inductive goal with 2 constructors.
-.. tacv:: eright
- :name: eright
+ .. tacv:: econstructor
+ eexists
+ esplit
+ eleft
+ eright
+ :name: econstructor; eexists; esplit; eleft; eright
- These tactics and their variants behave like :tacn:`constructor`,
- :tacn:`exists`, :tacn:`split`, :tacn:`left`, :tacn:`right` and their variants
- but they introduce existential variables instead of failing when the
- instantiation of a variable cannot be found (cf. :tacn:`eapply` and
- :tacn:`apply`).
+ These tactics and their variants behave like :tacn:`constructor`,
+ :tacn:`exists`, :tacn:`split`, :tacn:`left`, :tacn:`right` and their
+ variants but they introduce existential variables instead of failing
+ when the instantiation of a variable cannot be found
+ (cf. :tacn:`eapply` and :tacn:`apply`).
.. _managingthelocalcontext:
@@ -621,101 +614,107 @@ Managing the local context
.. tacn:: intro
:name: intro
-This tactic applies to a goal that is either a product or starts with a let
-binder. If the goal is a product, the tactic implements the "Lam" rule given in
-:ref:`Typing-rules` [1]_. If the goal starts with a let binder, then the
-tactic implements a mix of the "Let" and "Conv".
+ This tactic applies to a goal that is either a product or starts with a
+ let-binder. If the goal is a product, the tactic implements the "Lam" rule
+ given in :ref:`Typing-rules` [1]_. If the goal starts with a let-binder,
+ then the tactic implements a mix of the "Let" and "Conv".
-If the current goal is a dependent product :g:`forall x:T, U` (resp
-:g:`let x:=t in U`) then ``intro`` puts :g:`x:T` (resp :g:`x:=t`) in the local
-context. The new subgoal is :g:`U`.
+ If the current goal is a dependent product :g:`forall x:T, U`
+ (resp :g:`let x:=t in U`) then :tacn:`intro` puts :g:`x:T` (resp :g:`x:=t`)
+ in the local context. The new subgoal is :g:`U`.
-If the goal is a non-dependent product :g:`T`:math:`\rightarrow`:g:`U`, then it
-puts in the local context either :g:`Hn:T` (if :g:`T` is of type :g:`Set` or
-:g:`Prop`) or :g:`Xn:T` (if the type of :g:`T` is :g:`Type`). The optional index
-``n`` is such that ``Hn`` or ``Xn`` is a fresh identifier. In both cases, the
-new subgoal is :g:`U`.
+ If the goal is a non-dependent product :math:`T \rightarrow U`, then it
+ puts in the local context either :g:`Hn:T` (if :g:`T` is of type :g:`Set`
+ or :g:`Prop`) or :g:`Xn:T` (if the type of :g:`T` is :g:`Type`).
+ The optional index ``n`` is such that ``Hn`` or ``Xn`` is a fresh
+ identifier. In both cases, the new subgoal is :g:`U`.
-If the goal is an existential variable, ``intro`` forces the resolution of the
-existential variable into a dependent product :math:`forall`:g:`x:?X, ?Y`, puts
-:g:`x:?X` in the local context and leaves :g:`?Y` as a new subgoal allowed to
-depend on :g:`x`.
+ If the goal is an existential variable, :tacn:`intro` forces the resolution
+ of the existential variable into a dependent product :math:`\forall`\ :g:`x:?X, ?Y`,
+ puts :g:`x:?X` in the local context and leaves :g:`?Y` as a new subgoal
+ allowed to depend on :g:`x`.
-the tactic ``intro`` applies the tactic ``hnf`` until the tactic ``intro`` can
-be applied or the goal is not head-reducible.
+ The tactic :tacn:`intro` applies the tactic :tacn:`hnf`
+ until :tacn:`intro` can be applied or the goal is not head-reducible.
-.. exn:: No product even after head-reduction.
-.. exn:: @ident is already used.
+ .. exn:: No product even after head-reduction.
+ :undocumented:
-.. tacv:: intros
- :name: intros
+ .. tacv:: intro @ident
- This repeats ``intro`` until it meets the head-constant. It never
- reduces head-constants and it never fails.
+ This applies :tacn:`intro` but forces :token:`ident` to be the name of
+ the introduced hypothesis.
-.. tacn:: intro @ident
+ .. exn:: @ident is already used.
+ :undocumented:
- This applies ``intro`` but forces :n:`@ident` to be the name of the
- introduced hypothesis.
+ .. note::
-.. exn:: Name @ident is already used.
+ If a name used by intro hides the base name of a global constant then
+ the latter can still be referred to by a qualified name
+ (see :ref:`Qualified-names`).
-.. note:: If a name used by intro hides the base name of a global
- constant then the latter can still be referred to by a qualified name
- (see :ref:`Qualified-names`).
-.. tacv:: intros {+ @ident}.
+ .. tacv:: intros
+ :name: intros
- This is equivalent to the composed tactic
- :n:`intro @ident; ... ; intro @ident`. More generally, the ``intros`` tactic
- takes a pattern as argument in order to introduce names for components
- of an inductive definition or to clear introduced hypotheses. This is
- explained in :ref:`Managingthelocalcontext`.
+ This repeats :tacn:`intro` until it meets the head-constant. It never
+ reduces head-constants and it never fails.
-.. tacv:: intros until @ident
+ .. tacv:: intros {+ @ident}.
- This repeats intro until it meets a premise of the goal having form
- `(@ident:term)` and discharges the variable named `ident` of the current
- goal.
+ This is equivalent to the composed tactic :n:`intro @ident; ... ; intro @ident`.
-.. exn:: No such hypothesis in current goal.
+ .. tacv:: intros until @ident
-.. tacv:: intros until @num
+ This repeats intro until it meets a premise of the goal having the
+ form :n:`(@ident : @type)` and discharges the variable
+ named :token:`ident` of the current goal.
- This repeats intro until the `num`-th non-dependent product. For instance,
- on the subgoal :g:`forall x y:nat, x=y -> y=x` the tactic
- :n:`intros until 1` is equivalent to :n:`intros x y H`, as :g:`x=y -> y=x`
- is the first non-dependent product. And on the subgoal :g:`forall x y
- z:nat, x=y -> y=x` the tactic :n:`intros until 1` is equivalent to
- :n:`intros x y z` as the product on :g:`z` can be rewritten as a
- non-dependent product: :g:`forall x y:nat, nat -> x=y -> y=x`
+ .. exn:: No such hypothesis in current goal.
+ :undocumented:
-.. exn:: No such hypothesis in current goal.
+ .. tacv:: intros until @num
- This happens when `num` is 0 or is greater than the number of non-dependent
- products of the goal.
+ This repeats :tacn:`intro` until the :token:`num`\-th non-dependent
+ product.
-.. tacv:: intro after @ident
-.. tacv:: intro before @ident
-.. tacv:: intro at top
-.. tacv:: intro at bottom
+ .. example::
- These tactics apply :n:`intro` and move the freshly introduced hypothesis
- respectively after the hypothesis :n:`@ident`, before the hypothesis
- :n:`@ident`, at the top of the local context, or at the bottom of the local
- context. All hypotheses on which the new hypothesis depends are moved
- too so as to respect the order of dependencies between hypotheses.
- Note that :n:`intro at bottom` is a synonym for :n:`intro` with no argument.
+ On the subgoal :g:`forall x y : nat, x = y -> y = x` the
+ tactic :n:`intros until 1` is equivalent to :n:`intros x y H`,
+ as :g:`x = y -> y = x` is the first non-dependent product.
-.. exn:: No such hypothesis: @ident.
+ On the subgoal :g:`forall x y z : nat, x = y -> y = x` the
+ tactic :n:`intros until 1` is equivalent to :n:`intros x y z`
+ as the product on :g:`z` can be rewritten as a non-dependent
+ product: :g:`forall x y : nat, nat -> x = y -> y = x`.
-.. tacv:: intro @ident after @ident
-.. tacv:: intro @ident before @ident
-.. tacv:: intro @ident at top
-.. tacv:: intro @ident at bottom
+ .. exn:: No such hypothesis in current goal.
- These tactics behave as previously but naming the introduced hypothesis
- :n:`@ident`. It is equivalent to :n:`intro @ident` followed by the
- appropriate call to ``move`` (see :tacn:`move ... after ...`).
+ This happens when :token:`num` is 0 or is greater than the number of
+ non-dependent products of the goal.
+
+ .. tacv:: intro {? @ident__1 } after @ident__2
+ intro {? @ident__1 } before @ident__2
+ intro {? @ident__1 } at top
+ intro {? @ident__1 } at bottom
+
+ These tactics apply :n:`intro {? @ident__1}` and move the freshly
+ introduced hypothesis respectively after the hypothesis :n:`@ident__2`,
+ before the hypothesis :n:`@ident__2`, at the top of the local context,
+ or at the bottom of the local context. All hypotheses on which the new
+ hypothesis depends are moved too so as to respect the order of
+ dependencies between hypotheses. It is equivalent to :n:`intro {? @ident__1 }`
+ followed by the appropriate call to :tacn:`move ... after ...`,
+ :tacn:`move ... before ...`, :tacn:`move ... at top`,
+ or :tacn:`move ... at bottom`.
+
+ .. note::
+
+ :n:`intro at bottom` is a synonym for :n:`intro` with no argument.
+
+ .. exn:: No such hypothesis: @ident.
+ :undocumented:
.. tacn:: intros @intro_pattern_list
:name: intros ...
@@ -764,24 +763,22 @@ be applied or the goal is not head-reducible.
:n:`intros p` is defined inductively over the structure of the introduction
pattern :n:`p`:
-Introduction on :n:`?` performs the introduction, and lets Coq choose a fresh
-name for the variable;
-
-Introduction on :n:`?ident` performs the introduction, and lets Coq choose a
-fresh name for the variable based on :n:`@ident`;
+ Introduction on :n:`?` performs the introduction, and lets Coq choose a fresh
+ name for the variable;
-Introduction on :n:`@ident` behaves as described in :tacn:`intro`
+ Introduction on :n:`?@ident` performs the introduction, and lets Coq choose a
+ fresh name for the variable based on :n:`@ident`;
-Introduction over a disjunction of list of patterns
-:n:`[@intro_pattern_list | ... | @intro_pattern_list ]` expects the product
-to be over an inductive type whose number of constructors is `n` (or more
-generally over a type of conclusion an inductive type built from `n`
-constructors, e.g. :g:`C -> A\/B` with `n=2` since :g:`A\/B` has `2`
-constructors): it destructs the introduced hypothesis as :n:`destruct` (see
-:tacn:`destruct`) would and applies on each generated subgoal the
-corresponding tactic;
+ Introduction on :n:`@ident` behaves as described in :tacn:`intro`
-.. tacv:: intros @intro_pattern_list
+ Introduction over a disjunction of list of patterns
+ :n:`[@intro_pattern_list | ... | @intro_pattern_list ]` expects the product
+ to be over an inductive type whose number of constructors is `n` (or more
+ generally over a type of conclusion an inductive type built from `n`
+ constructors, e.g. :g:`C -> A\/B` with `n=2` since :g:`A\/B` has `2`
+ constructors): it destructs the introduced hypothesis as :n:`destruct` (see
+ :tacn:`destruct`) would and applies on each generated subgoal the
+ corresponding tactic;
The introduction patterns in :n:`@intro_pattern_list` are expected to consume
no more than the number of arguments of the `i`-th constructor. If it
@@ -790,67 +787,68 @@ corresponding tactic;
list of patterns :n:`[ | ] H` applied on goal :g:`forall x:nat, x=0 -> 0=x`
behaves the same as the list of patterns :n:`[ | ? ] H`);
-Introduction over a conjunction of patterns :n:`({+, p})` expects
-the goal to be a product over an inductive type :g:`I` with a single
-constructor that itself has at least `n` arguments: It performs a case
-analysis over the hypothesis, as :n:`destruct` would, and applies the
-patterns :n:`{+ p}` to the arguments of the constructor of :g:`I` (observe
-that :n:`({+ p})` is an alternative notation for :n:`[{+ p}]`);
-
-Introduction via :n:`({+& p})` is a shortcut for introduction via
-:n:`(p,( ... ,( ..., p ) ... ))`; it expects the hypothesis to be a sequence of
-right-associative binary inductive constructors such as :g:`conj` or
-:g:`ex_intro`; for instance, an hypothesis with type
-:g:`A /\(exists x, B /\ C /\ D)` can be introduced via pattern
-:n:`(a & x & b & c & d)`;
-
-If the product is over an equality type, then a pattern of the form
-:n:`[= {+ p}]` applies either :tacn:`injection` or :tacn:`discriminate`
-instead of :tacn:`destruct`; if :tacn:`injection` is applicable, the patterns
-:n:`{+, p}` are used on the hypotheses generated by :tacn:`injection`; if the
-number of patterns is smaller than the number of hypotheses generated, the
-pattern :n:`?` is used to complete the list;
-
-.. tacv:: introduction over ->
-.. tacv:: introduction over <-
-
+ Introduction over a conjunction of patterns :n:`({+, p})` expects
+ the goal to be a product over an inductive type :g:`I` with a single
+ constructor that itself has at least `n` arguments: It performs a case
+ analysis over the hypothesis, as :n:`destruct` would, and applies the
+ patterns :n:`{+ p}` to the arguments of the constructor of :g:`I` (observe
+ that :n:`({+ p})` is an alternative notation for :n:`[{+ p}]`);
+
+ Introduction via :n:`({+& p})` is a shortcut for introduction via
+ :n:`(p,( ... ,( ..., p ) ... ))`; it expects the hypothesis to be a sequence of
+ right-associative binary inductive constructors such as :g:`conj` or
+ :g:`ex_intro`; for instance, a hypothesis with type
+ :g:`A /\(exists x, B /\ C /\ D)` can be introduced via pattern
+ :n:`(a & x & b & c & d)`;
+
+ If the product is over an equality type, then a pattern of the form
+ :n:`[= {+ p}]` applies either :tacn:`injection` or :tacn:`discriminate`
+ instead of :tacn:`destruct`; if :tacn:`injection` is applicable, the patterns
+ :n:`{+, p}` are used on the hypotheses generated by :tacn:`injection`; if the
+ number of patterns is smaller than the number of hypotheses generated, the
+ pattern :n:`?` is used to complete the list.
+
+ Introduction over ``->`` (respectively over ``<-``)
expects the hypothesis to be an equality and the right-hand-side
(respectively the left-hand-side) is replaced by the left-hand-side
(respectively the right-hand-side) in the conclusion of the goal;
the hypothesis itself is erased; if the term to substitute is a variable, it
- is substituted also in the context of goal and the variable is removed too;
+ is substituted also in the context of goal and the variable is removed too.
-Introduction over a pattern :n:`p{+ %term}` first applies :n:`{+ term}`
-on the hypothesis to be introduced (as in :n:`apply {+, term}`) prior to the
-application of the introduction pattern :n:`p`;
+ Introduction over a pattern :n:`p{+ %term}` first applies :n:`{+ term}`
+ on the hypothesis to be introduced (as in :n:`apply {+, term}`) prior to the
+ application of the introduction pattern :n:`p`;
-Introduction on the wildcard depends on whether the product is dependent or not:
-in the non-dependent case, it erases the corresponding hypothesis (i.e. it
-behaves as an :tacn:`intro` followed by a :tacn:`clear`) while in the
-dependent case, it succeeds and erases the variable only if the wildcard is part
-of a more complex list of introduction patterns that also erases the hypotheses
-depending on this variable;
+ Introduction on the wildcard depends on whether the product is dependent or not:
+ in the non-dependent case, it erases the corresponding hypothesis (i.e. it
+ behaves as an :tacn:`intro` followed by a :tacn:`clear`) while in the
+ dependent case, it succeeds and erases the variable only if the wildcard is part
+ of a more complex list of introduction patterns that also erases the hypotheses
+ depending on this variable;
-Introduction over :n:`*` introduces all forthcoming quantified variables
-appearing in a row; introduction over :n:`**` introduces all forthcoming
-quantified variables or hypotheses until the goal is not any more a
-quantification or an implication.
+ Introduction over :n:`*` introduces all forthcoming quantified variables
+ appearing in a row; introduction over :n:`**` introduces all forthcoming
+ quantified variables or hypotheses until the goal is not any more a
+ quantification or an implication.
-.. example::
- .. coqtop:: all
+ .. example::
+
+ .. coqtop:: reset all
- Goal forall A B C:Prop, A \/ B /\ C -> (A -> C) -> C.
- intros * [a | (_,c)] f.
+ Goal forall A B C:Prop, A \/ B /\ C -> (A -> C) -> C.
+ intros * [a | (_,c)] f.
.. note::
+
:n:`intros {+ p}` is not equivalent to :n:`intros p; ... ; intros p`
for the following reason: If one of the :n:`p` is a wildcard pattern, it
might succeed in the first case because the further hypotheses it
- depends in are eventually erased too while it might fail in the second
+ depends on are eventually erased too while it might fail in the second
case because of dependencies in hypotheses which are not yet
introduced (and a fortiori not yet erased).
.. note::
+
In :n:`intros @intro_pattern_list`, if the last introduction pattern
is a disjunctive or conjunctive pattern
:n:`[{+| @intro_pattern_list}]`, the completion of :n:`@intro_pattern_list`
@@ -869,38 +867,42 @@ quantification or an implication.
the current goal. As a consequence, :n:`@ident` is no more displayed and no
more usable in the proof development.
-.. exn:: No such hypothesis.
+ .. exn:: No such hypothesis.
+ :undocumented:
-.. exn:: @ident is used in the conclusion.
+ .. exn:: @ident is used in the conclusion.
+ :undocumented:
-.. exn:: @ident is used in the hypothesis @ident.
+ .. exn:: @ident is used in the hypothesis @ident.
+ :undocumented:
-.. tacv:: clear {+ @ident}
+ .. tacv:: clear {+ @ident}
- This is equivalent to :n:`clear @ident. ... clear @ident.`
+ This is equivalent to :n:`clear @ident. ... clear @ident.`
-.. tacv:: clear - {+ @ident}
+ .. tacv:: clear - {+ @ident}
- This tactic clears all the hypotheses except the ones depending in the
- hypotheses named :n:`{+ @ident}` and in the goal.
+ This variant clears all the hypotheses except the ones depending in the
+ hypotheses named :n:`{+ @ident}` and in the goal.
-.. tacv:: clear
+ .. tacv:: clear
- This tactic clears all the hypotheses except the ones the goal depends on.
+ This variants clears all the hypotheses except the ones the goal depends on.
-.. tacv:: clear dependent @ident
+ .. tacv:: clear dependent @ident
- This clears the hypothesis :n:`@ident` and all the hypotheses that depend on
- it.
+ This clears the hypothesis :token:`ident` and all the hypotheses that
+ depend on it.
-.. tacv:: clearbody {+ @ident}
- :name: clearbody
+ .. tacv:: clearbody {+ @ident}
+ :name: clearbody
- This tactic expects :n:`{+ @ident}` to be local definitions and clears their
- respective bodies.
- In other words, it turns the given definitions into assumptions.
+ This tactic expects :n:`{+ @ident}` to be local definitions and clears
+ their respective bodies.
+ In other words, it turns the given definitions into assumptions.
-.. exn:: @ident is not a local definition.
+ .. exn:: @ident is not a local definition.
+ :undocumented:
.. tacn:: revert {+ @ident}
:name: revert
@@ -909,171 +911,184 @@ quantification or an implication.
(possibly defined) to the goal, if this respects dependencies. This tactic is
the inverse of :tacn:`intro`.
-.. exn:: No such hypothesis.
+ .. exn:: No such hypothesis.
+ :undocumented:
-.. exn:: @ident is used in the hypothesis @ident.
+ .. exn:: @ident__1 is used in the hypothesis @ident__2.
+ :undocumented:
-.. tacn:: revert dependent @ident
+ .. tacv:: revert dependent @ident
+ :name: revert dependent
- This moves to the goal the hypothesis :n:`@ident` and all the hypotheses that
- depend on it.
+ This moves to the goal the hypothesis :token:`ident` and all the
+ hypotheses that depend on it.
-.. tacn:: move @ident after @ident
+.. tacn:: move @ident__1 after @ident__2
:name: move ... after ...
- This moves the hypothesis named :n:`@ident` in the local context after the
- hypothesis named :n:`@ident`, where “after” is in reference to the
+ This moves the hypothesis named :n:`@ident__1` in the local context after
+ the hypothesis named :n:`@ident__2`, where “after” is in reference to the
direction of the move. The proof term is not changed.
- If :n:`@ident` comes before :n:`@ident` in the order of dependencies, then
- all the hypotheses between :n:`@ident` and :n:`ident@` that (possibly
- indirectly) depend on :n:`@ident` are moved too, and all of them are thus
- moved after :n:`@ident` in the order of dependencies.
+ If :n:`@ident__1` comes before :n:`@ident__2` in the order of dependencies,
+ then all the hypotheses between :n:`@ident__1` and :n:`@ident__2` that
+ (possibly indirectly) depend on :n:`@ident__1` are moved too, and all of
+ them are thus moved after :n:`@ident__2` in the order of dependencies.
- If :n:`@ident` comes after :n:`@ident` in the order of dependencies, then all
- the hypotheses between :n:`@ident` and :n:`@ident` that (possibly indirectly)
- occur in the type of :n:`@ident` are moved too, and all of them are thus
- moved before :n:`@ident` in the order of dependencies.
+ If :n:`@ident__1` comes after :n:`@ident__2` in the order of dependencies,
+ then all the hypotheses between :n:`@ident__1` and :n:`@ident__2` that
+ (possibly indirectly) occur in the type of :n:`@ident__1` are moved too,
+ and all of them are thus moved before :n:`@ident__2` in the order of
+ dependencies.
-.. tacv:: move @ident before @ident
+ .. tacv:: move @ident__1 before @ident__2
+ :name: move ... before ...
- This moves :n:`@ident` towards and just before the hypothesis named
- :n:`@ident`. As for :tacn:`move ... after ...`, dependencies over
- :n:`@ident` (when :n:`@ident` comes before :n:`@ident` in the order of
- dependencies) or in the type of :n:`@ident` (when :n:`@ident` comes after
- :n:`@ident` in the order of dependencies) are moved too.
+ This moves :n:`@ident__1` towards and just before the hypothesis
+ named :n:`@ident__2`. As for :tacn:`move ... after ...`, dependencies
+ over :n:`@ident__1` (when :n:`@ident__1` comes before :n:`@ident__2` in
+ the order of dependencies) or in the type of :n:`@ident__1`
+ (when :n:`@ident__1` comes after :n:`@ident__2` in the order of
+ dependencies) are moved too.
-.. tacv:: move @ident at top
+ .. tacv:: move @ident at top
+ :name: move ... at top
- This moves :n:`@ident` at the top of the local context (at the beginning of
- the context).
+ This moves :token:`ident` at the top of the local context (at the beginning
+ of the context).
-.. tacv:: move @ident at bottom
+ .. tacv:: move @ident at bottom
+ :name: move ... at bottom
- This moves ident at the bottom of the local context (at the end of the
- context).
+ This moves :token:`ident` at the bottom of the local context (at the end of
+ the context).
-.. exn:: No such hypothesis.
-.. exn:: Cannot move @ident after @ident : it occurs in the type of @ident.
-.. exn:: Cannot move @ident after @ident : it depends on @ident.
+ .. exn:: No such hypothesis.
+ :undocumented:
-.. example::
- .. coqtop:: all
+ .. exn:: Cannot move @ident__1 after @ident__2: it occurs in the type of @ident__2.
+ :undocumented:
+
+ .. exn:: Cannot move @ident__1 after @ident__2: it depends on @ident__2.
+ :undocumented:
- Goal forall x :nat, x = 0 -> forall z y:nat, y=y-> 0=x.
- intros x H z y H0.
- move x after H0.
- Undo.
- move x before H0.
- Undo.
- move H0 after H.
- Undo.
- move H0 before H.
-
-.. tacn:: rename @ident into @ident
+ .. example::
+
+ .. coqtop:: reset all
+
+ Goal forall x :nat, x = 0 -> forall z y:nat, y=y-> 0=x.
+ intros x H z y H0.
+ move x after H0.
+ Undo.
+ move x before H0.
+ Undo.
+ move H0 after H.
+ Undo.
+ move H0 before H.
+
+.. tacn:: rename @ident__1 into @ident__2
:name: rename
-This renames hypothesis :n:`@ident` into :n:`@ident` in the current context.
-The name of the hypothesis in the proof-term, however, is left unchanged.
+ This renames hypothesis :n:`@ident__1` into :n:`@ident__2` in the current
+ context. The name of the hypothesis in the proof-term, however, is left
+ unchanged.
+
+ .. tacv:: rename {+, @ident__i into @ident__j}
-.. tacv:: rename {+, @ident into @ident}
+ This renames the variables :n:`@ident__i` into :n:`@ident__j` in parallel.
+ In particular, the target identifiers may contain identifiers that exist in
+ the source context, as long as the latter are also renamed by the same
+ tactic.
- This renames the variables :n:`@ident` into :n:`@ident` in parallel. In
- particular, the target identifiers may contain identifiers that exist in the
- source context, as long as the latter are also renamed by the same tactic.
+ .. exn:: No such hypothesis.
+ :undocumented:
-.. exn:: No such hypothesis.
-.. exn:: @ident is already used.
+ .. exn:: @ident is already used.
+ :undocumented:
.. tacn:: set (@ident := @term)
:name: set
- This replaces :n:`@term` by :n:`@ident` in the conclusion of the current goal
- and adds the new definition :g:`ident := term` to the local context.
-
- If :n:`@term` has holes (i.e. subexpressions of the form “`_`”), the tactic
- first checks that all subterms matching the pattern are compatible before
- doing the replacement using the leftmost subterm matching the pattern.
+ This replaces :token:`term` by :token:`ident` in the conclusion of the
+ current goal and adds the new definition :n:`@ident := @term` to the
+ local context.
-.. exn:: The variable @ident is already defined.
+ If :token:`term` has holes (i.e. subexpressions of the form “`_`”), the
+ tactic first checks that all subterms matching the pattern are compatible
+ before doing the replacement using the leftmost subterm matching the
+ pattern.
-.. tacv:: set (@ident := @term ) in @goal_occurrences
+ .. exn:: The variable @ident is already defined.
+ :undocumented:
- This notation allows specifying which occurrences of :n:`@term` have to be
- substituted in the context. The :n:`in @goal_occurrences` clause is an
- occurrence clause whose syntax and behavior are described in
- :ref:`goal occurences <occurencessets>`.
+ .. tacv:: set (@ident := @term) in @goal_occurrences
-.. tacv:: set (@ident {+ @binder} := @term )
+ This notation allows specifying which occurrences of :token:`term` have
+ to be substituted in the context. The :n:`in @goal_occurrences` clause
+ is an occurrence clause whose syntax and behavior are described in
+ :ref:`goal occurences <occurencessets>`.
- This is equivalent to :n:`set (@ident := funbinder {+ binder} => @term )`.
+ .. tacv:: set (@ident @binders := @term) {? in @goal_occurrences }
-.. tacv:: set term
- This behaves as :n:`set(@ident := @term)` but :n:`@ident` is generated by
- Coq. This variant also supports an occurrence clause.
+ This is equivalent to :n:`set (@ident := fun @binders => @term) {? in @goal_occurrences }`.
-.. tacv:: set (@ident {+ @binder} := @term) in @goal_occurrences
-.. tacv:: set @term in @goal_occurrences
+ .. tacv:: set @term {? in @goal_occurrences }
- These are the general forms that combine the previous possibilities.
+ This behaves as :n:`set (@ident := @term) {? in @goal_occurrences }`
+ but :token:`ident` is generated by Coq.
-.. tacv:: eset (@ident {+ @binder} := @term ) in @goal_occurrences
-.. tacv:: eset @term in @goal_occurrences
- :name: eset
+ .. tacv:: eset (@ident {? @binders } := @term) {? in @goal_occurrences }
+ eset @term {? in @goal_occurrences }
+ :name: eset; _
- While the different variants of :tacn:`set` expect that no existential
- variables are generated by the tactic, :n:`eset` removes this constraint. In
- practice, this is relevant only when :n:`eset` is used as a synonym of
- :tacn:`epose`, i.e. when the :`@term` does not occur in the goal.
+ While the different variants of :tacn:`set` expect that no existential
+ variables are generated by the tactic, :tacn:`eset` removes this
+ constraint. In practice, this is relevant only when :tacn:`eset` is
+ used as a synonym of :tacn:`epose`, i.e. when the :token:`term` does
+ not occur in the goal.
-.. tacv:: remember @term as @ident
+.. tacn:: remember @term as @ident__1 {? eqn:@ident__2 }
:name: remember
- This behaves as :n:`set (@ident:= @term ) in *` and using a logical
+ This behaves as :n:`set (@ident__1 := @term) in *`, using a logical
(Leibniz’s) equality instead of a local definition.
+ If :n:`@ident__2` is provided, it will be the name of the new equation.
-.. tacv:: remember @term as @ident eqn:@ident
-
- This behaves as :n:`remember @term as @ident`, except that the name of the
- generated equality is also given.
+ .. tacv:: remember @term as @ident__1 {? eqn:@ident__2 } in @goal_occurrences
-.. tacv:: remember @term as @ident in @goal_occurrences
+ This is a more general form of :tacn:`remember` that remembers the
+ occurrences of :token:`term` specified by an occurrence set.
- This is a more general form of :n:`remember` that remembers the occurrences
- of term specified by an occurrences set.
+ .. tacv:: eremember @term as @ident__1 {? eqn:@ident__2 } {? in @goal_occurrences }
+ :name: eremember
-.. tacv:: eremember @term as @ident
-.. tacv:: eremember @term as @ident in @goal_occurrences
-.. tacv:: eremember @term as @ident eqn:@ident
- :name: eremember
+ While the different variants of :tacn:`remember` expect that no
+ existential variables are generated by the tactic, :tacn:`eremember`
+ removes this constraint.
- While the different variants of :n:`remember` expect that no existential
- variables are generated by the tactic, :n:`eremember` removes this constraint.
-
-.. tacv:: pose ( @ident := @term )
+.. tacn:: pose (@ident := @term)
:name: pose
This adds the local definition :n:`@ident := @term` to the current context
without performing any replacement in the goal or in the hypotheses. It is
- equivalent to :n:`set ( @ident := @term ) in |-`.
+ equivalent to :n:`set (@ident := @term) in |-`.
-.. tacv:: pose ( @ident {+ @binder} := @term )
+ .. tacv:: pose (@ident @binders := @term)
- This is equivalent to :n:`pose (@ident := funbinder {+ binder} => @term)`.
+ This is equivalent to :n:`pose (@ident := fun @binders => @term)`.
-.. tacv:: pose @term
+ .. tacv:: pose @term
- This behaves as :n:`pose (@ident := @term )` but :n:`@ident` is generated by
- Coq.
+ This behaves as :n:`pose (@ident := @term)` but :token:`ident` is
+ generated by Coq.
-.. tacv:: epose (@ident := @term )
-.. tacv:: epose (@ident {+ @binder} := @term )
-.. tacv:: epose term
- :name: epose
+ .. tacv:: epose (@ident {? @binders} := @term)
+ .. tacv:: epose term
+ :name: epose
- While the different variants of :tacn:`pose` expect that no
- existential variables are generated by the tactic, epose removes this
- constraint.
+ While the different variants of :tacn:`pose` expect that no
+ existential variables are generated by the tactic, :tacn:`epose`
+ removes this constraint.
.. tacn:: decompose [{+ @qualid}] @term
:name: decompose
@@ -1081,24 +1096,30 @@ The name of the hypothesis in the proof-term, however, is left unchanged.
This tactic recursively decomposes a complex proposition in order to
obtain atomic ones.
-.. example::
- .. coqtop:: all
+ .. example::
- Goal forall A B C:Prop, A /\ B /\ C \/ B /\ C \/ C /\ A -> C.
- intros A B C H; decompose [and or] H; assumption.
- Qed.
+ .. coqtop:: reset all
+
+ Goal forall A B C:Prop, A /\ B /\ C \/ B /\ C \/ C /\ A -> C.
+ intros A B C H; decompose [and or] H.
+ all: assumption.
+ Qed.
-:n:`decompose` does not work on right-hand sides of implications or products.
+ .. note::
+
+ :tacn:`decompose` does not work on right-hand sides of implications or
+ products.
+
+ .. tacv:: decompose sum @term
-.. tacv:: decompose sum @term
+ This decomposes sum types (like :g:`or`).
- This decomposes sum types (like or).
+ .. tacv:: decompose record @term
-.. tacv:: decompose record @term
+ This decomposes record types (inductive types with one constructor,
+ like :g:`and` and :g:`exists` and those defined with the :cmd:`Record`
+ command.
- This decomposes record types (inductive types with one constructor, like
- "and" and "exists" and those defined with the Record macro, see
- :ref:`record-types`).
.. _controllingtheproofflow:
@@ -1252,6 +1273,7 @@ Controlling the proof flow
respect to some term.
.. example::
+
.. coqtop:: reset none
Goal forall x y:nat, 0 <= x + y + y.
@@ -1362,7 +1384,7 @@ goals cannot be closed with :g:`Qed` but only with :g:`Admitted`.
:name: contradiction
This tactic applies to any goal. The contradiction tactic attempts to
- find in the current context (after all intros) an hypothesis that is
+ find in the current context (after all intros) a hypothesis that is
equivalent to an empty inductive type (e.g. :g:`False`), to the negation of
a singleton inductive type (e.g. :g:`True` or :g:`x=x`), or two contradictory
hypotheses.
@@ -1404,94 +1426,101 @@ analysis on inductive or co-inductive objects (see :ref:`inductive-definitions`)
.. tacn:: destruct @term
:name: destruct
- This tactic applies to any goal. The argument :n:`@term` must be of
+ This tactic applies to any goal. The argument :token:`term` must be of
inductive or co-inductive type and the tactic generates subgoals, one
- for each possible form of :n:`@term`, i.e. one for each constructor of the
- inductive or co-inductive type. Unlike :n:`induction`, no induction
- hypothesis is generated by :n:`destruct`.
+ for each possible form of :token:`term`, i.e. one for each constructor of the
+ inductive or co-inductive type. Unlike :tacn:`induction`, no induction
+ hypothesis is generated by :tacn:`destruct`.
+
+ .. tacv:: destruct @ident
- There are special cases:
+ If :token:`ident` denotes a quantified variable of the conclusion
+ of the goal, then :n:`destruct @ident` behaves
+ as :n:`intros until @ident; destruct @ident`. If :token:`ident` is not
+ anymore dependent in the goal after application of :tacn:`destruct`, it
+ is erased (to avoid erasure, use parentheses, as in :n:`destruct (@ident)`).
- + If :n:`@term` is an identifier :n:`@ident` denoting a quantified variable
- of the conclusion of the goal, then :n:`destruct @ident` behaves as
- :n:`intros until @ident; destruct @ident`. If :n:`@ident` is not anymore
- dependent in the goal after application of :n:`destruct`, it is erased
- (to avoid erasure, use parentheses, as in :n:`destruct (@ident)`).
+ If :token:`ident` is a hypothesis of the context, and :token:`ident`
+ is not anymore dependent in the goal after application
+ of :tacn:`destruct`, it is erased (to avoid erasure, use parentheses, as
+ in :n:`destruct (@ident)`).
- + If term is a num, then destruct num behaves asintros until num
- followed by destruct applied to the last introduced hypothesis.
+ .. tacv:: destruct @num
+
+ :n:`destruct @num` behaves as :n:`intros until @num`
+ followed by destruct applied to the last introduced hypothesis.
.. note::
- For destruction of a numeral, use syntax destruct (num) (not
+ For destruction of a numeral, use syntax :n:`destruct (@num)` (not
very interesting anyway).
- + In case term is an hypothesis :n:`@ident` of the context, and :n:`@ident`
- is not anymore dependent in the goal after application of :n:`destruct`, it
- is erased (to avoid erasure, use parentheses, as in :n:`destruct (@ident)`).
+ .. tacv:: destruct @pattern
- + The argument :n:`@term` can also be a pattern of which holes are denoted
- by “_”. In this case, the tactic checks that all subterms matching the
- pattern in the conclusion and the hypotheses are compatible and
- performs case analysis using this subterm.
+ The argument of :tacn:`destruct` can also be a pattern of which holes are
+ denoted by “_”. In this case, the tactic checks that all subterms
+ matching the pattern in the conclusion and the hypotheses are compatible
+ and performs case analysis using this subterm.
-.. tacv:: destruct {+, @term}
+ .. tacv:: destruct {+, @term}
- This is a shortcut for :n:`destruct term; ...; destruct term`.
+ This is a shortcut for :n:`destruct @term; ...; destruct @term`.
-.. tacv:: destruct @term as @disj_conj_intro_pattern
+ .. tacv:: destruct @term as @disj_conj_intro_pattern
- This behaves as :n:`destruct @term` but uses the names in :n:`@intro_pattern`
- to name the variables introduced in the context. The :n:`@intro_pattern` must
- have the form :n:`[p11 ... p1n | ... | pm1 ... pmn ]` with `m` being the
- number of constructors of the type of :n:`@term`. Each variable introduced
- by :n:`destruct` in the context of the `i`-th goal gets its name from the
- list :n:`pi1 ... pin` in order. If there are not enough names,
- :n:`@destruct` invents names for the remaining variables to introduce. More
- generally, the :n:`pij` can be any introduction pattern (see
- :tacn:`intros`). This provides a concise notation for chaining destruction of
- an hypothesis.
+ This behaves as :n:`destruct @term` but uses the names
+ in :token:`disj_conj_intro_pattern` to name the variables introduced in the
+ context. The :token:`disj_conj_intro_pattern` must have the
+ form :n:`[p11 ... p1n | ... | pm1 ... pmn ]` with ``m`` being the
+ number of constructors of the type of :token:`term`. Each variable
+ introduced by :tacn:`destruct` in the context of the ``i``-th goal
+ gets its name from the list :n:`pi1 ... pin` in order. If there are not
+ enough names, :tacn:`destruct` invents names for the remaining variables
+ to introduce. More generally, the :n:`pij` can be any introduction
+ pattern (see :tacn:`intros`). This provides a concise notation for
+ chaining destruction of a hypothesis.
-.. tacv:: destruct @term eqn:@naming_intro_pattern
+ .. tacv:: destruct @term eqn:@naming_intro_pattern
+ :name: destruct ... eqn:
- This behaves as :n:`destruct @term` but adds an equation between :n:`@term`
- and the value that :n:`@term` takes in each of the possible cases. The name
- of the equation is specified by :n:`@naming_intro_pattern` (see
- :tacn:`intros`), in particular `?` can be used to let Coq generate a fresh
- name.
+ This behaves as :n:`destruct @term` but adds an equation
+ between :token:`term` and the value that it takes in each of the
+ possible cases. The name of the equation is specified
+ by :token:`naming_intro_pattern` (see :tacn:`intros`),
+ in particular ``?`` can be used to let Coq generate a fresh name.
-.. tacv:: destruct @term with @bindings_list
+ .. tacv:: destruct @term with @bindings_list
- This behaves like :n:`destruct @term` providing explicit instances for the
- dependent premises of the type of :n:`@term` (see :ref:`syntax of bindings <bindingslist>`).
+ This behaves like :n:`destruct @term` providing explicit instances for
+ the dependent premises of the type of :token:`term`.
-.. tacv:: edestruct @term
- :name: edestruct
+ .. tacv:: edestruct @term
+ :name: edestruct
- This tactic behaves like :n:`destruct @term` except that it does not fail if
- the instance of a dependent premises of the type of :n:`@term` is not
- inferable. Instead, the unresolved instances are left as existential
- variables to be inferred later, in the same way as :tacn:`eapply` does.
+ This tactic behaves like :n:`destruct @term` except that it does not
+ fail if the instance of a dependent premises of the type
+ of :token:`term` is not inferable. Instead, the unresolved instances
+ are left as existential variables to be inferred later, in the same way
+ as :tacn:`eapply` does.
-.. tacv:: destruct @term using @term
-.. tacv:: destruct @term using @term with @bindings_list
+ .. tacv:: destruct @term using @term {? with @bindings_list }
- These are synonyms of :n:`induction @term using @term` and
- :n:`induction @term using @term with @bindings_list`.
+ This is synonym of :n:`induction @term using @term {? with @bindings_list }`.
-.. tacv:: destruct @term in @goal_occurrences
+ .. tacv:: destruct @term in @goal_occurrences
- This syntax is used for selecting which occurrences of :n:`@term` the case
- analysis has to be done on. The :n:`in @goal_occurrences` clause is an
- occurrence clause whose syntax and behavior is described in
- :ref:`occurences sets <occurencessets>`.
+ This syntax is used for selecting which occurrences of :token:`term`
+ the case analysis has to be done on. The :n:`in @goal_occurrences`
+ clause is an occurrence clause whose syntax and behavior is described
+ in :ref:`occurences sets <occurencessets>`.
-.. tacv:: destruct @term with @bindings_list as @disj_conj_intro_pattern eqn:@naming_intro_pattern using @term with @bindings_list in @goal_occurrences
-.. tacv:: edestruct @term with @bindings_list as @disj_conj_intro_pattern eqn:@naming_intro_pattern using @term with @bindings_list in @goal_occurrences
+ .. tacv:: destruct @term {? with @bindings_list } {? as @disj_conj_intro_pattern } {? eqn:@naming_intro_pattern } {? using @term {? with @bindings_list } } {? in @goal_occurrences }
+ edestruct @term {? with @bindings_list } {? as @disj_conj_intro_pattern } {? eqn:@naming_intro_pattern } {? using @term {? with @bindings_list } } {? in @goal_occurrences }
- These are the general forms of :n:`destruct` and :n:`edestruct`. They combine
- the effects of the `with`, `as`, `eqn:`, `using`, and `in` clauses.
+ These are the general forms of :tacn:`destruct` and :tacn:`edestruct`.
+ They combine the effects of the ``with``, ``as``, ``eqn:``, ``using``,
+ and ``in`` clauses.
-.. tacv:: case term
+.. tacn:: case term
:name: case
The tactic :n:`case` is a more basic tactic to perform case analysis without
@@ -1523,7 +1552,7 @@ analysis on inductive or co-inductive objects (see :ref:`inductive-definitions`)
.. tacv:: case_eq @term
- The tactic :n:`case_eq` is a variant of the :n:`case` tactic that allow to
+ The tactic :n:`case_eq` is a variant of the :n:`case` tactic that allows to
perform case analysis on a term without completely forgetting its original
form. This is done by generating equalities between the original form of the
term and the outcomes of the case analysis.
@@ -1557,7 +1586,7 @@ analysis on inductive or co-inductive objects (see :ref:`inductive-definitions`)
For simple induction on a numeral, use syntax induction (num)
(not very interesting anyway).
- + In case term is an hypothesis :n:`@ident` of the context, and :n:`@ident`
+ + In case term is a hypothesis :n:`@ident` of the context, and :n:`@ident`
is not anymore dependent in the goal after application of :n:`induction`,
it is erased (to avoid erasure, use parentheses, as in
:n:`induction (@ident)`).
@@ -1567,6 +1596,7 @@ analysis on inductive or co-inductive objects (see :ref:`inductive-definitions`)
performs induction using this subterm.
.. example::
+
.. coqtop:: reset all
Lemma induction_test : forall n:nat, n = n -> n <= n.
@@ -1636,6 +1666,7 @@ analysis on inductive or co-inductive objects (see :ref:`inductive-definitions`)
those are generalized as well in the statement to prove.
.. example::
+
.. coqtop:: reset all
Lemma comm x y : x + y = y + x.
@@ -1744,6 +1775,7 @@ analysis on inductive or co-inductive objects (see :ref:`inductive-definitions`)
still get enough information in the proofs.
.. example::
+
.. coqtop:: reset all
Lemma le_minus : forall n:nat, n < 1 -> n = 0.
@@ -1806,9 +1838,10 @@ and an explanation of the underlying technique.
following the definition of a function. It makes use of a principle
generated by ``Function`` (see :ref:`advanced-recursive-functions`) or
``Functional Scheme`` (see :ref:`functional-scheme`).
- Note that this tactic is only available after a
+ Note that this tactic is only available after a ``Require Import FunInd``.
.. example::
+
.. coqtop:: reset all
Require Import FunInd.
@@ -1825,7 +1858,7 @@ and an explanation of the underlying technique.
arguments explicitly.
.. note::
- Parentheses over :n:`@qualid {+ @term}` are mandatory.
+ Parentheses around :n:`@qualid {+ @term}` are not mandatory and can be skipped.
.. note::
:n:`functional induction (f x1 x2 x3)` is actually a wrapper for
@@ -1845,9 +1878,7 @@ and an explanation of the underlying technique.
:g:`Fixpoint` or :g:`Definition`. See :ref:`advanced-recursive-functions`
for details.
-See also: :ref:`advanced-recursive-functions`
- :ref:`functional-scheme`
- :tacn:`inversion`
+.. seealso:: :ref:`advanced-recursive-functions`, :ref:`functional-scheme` and :tacn:`inversion`
.. exn:: Cannot find induction information on @qualid.
.. exn:: Not the right number of induction arguments.
@@ -2008,7 +2039,7 @@ See also: :ref:`advanced-recursive-functions`
the number of equalities newly generated. If it is smaller, fresh
names are automatically generated to adjust the list of :n:`@intro_pattern`
to the number of new equalities. The original equality is erased if it
- corresponds to an hypothesis.
+ corresponds to a hypothesis.
.. opt:: Structural Injection
@@ -2237,7 +2268,7 @@ See also: :ref:`advanced-recursive-functions`
To prove the goal, we may need to reason by cases on H and to derive
that m is necessarily of the form (S m 0 ) for certain m 0 and that
- (Le n m 0 ). Deriving these conditions corresponds to prove that the
+ (Le n m 0 ). Deriving these conditions corresponds to proving that the
only possible constructor of (Le (S n) m) isLeS and that we can invert
the-> in the type of LeS. This inversion is possible because Le is the
smallest set closed by the constructors LeO and LeS.
@@ -2279,8 +2310,8 @@ See also: :ref:`advanced-recursive-functions`
As H occurs in the goal, we may want to reason by cases on its
structure and so, we would like inversion tactics to substitute H by
- the corresponding @term in constructor form. Neither Inversion nor
- Inversion_clear make such a substitution. To have such a behavior we
+ the corresponding @term in constructor form. Neither :tacn:`inversion` nor
+ :n:`inversion_clear` do such a substitution. To have such a behavior we
use the dependent inversion tactics:
.. coqtop:: all
@@ -2598,7 +2629,7 @@ simply :g:`t=u` dropping the implicit type of :g:`t` and :g:`u`.
Adds :n:`@term` to the database used by :tacn:`stepl`.
- The tactic is especially useful for parametric setoids which are not accepted
+ This tactic is especially useful for parametric setoids which are not accepted
as regular setoids for :tacn:`rewrite` and :tacn:`setoid_replace` (see
:ref:`Generalizedrewriting`).
@@ -2708,7 +2739,7 @@ the conversion in hypotheses :n:`{+ @ident}`.
Normalization according to the flags is done by first evaluating the
head of the expression into a *weak-head* normal form, i.e. until the
- evaluation is bloked by a variable (or an opaque constant, or an
+ evaluation is blocked by a variable (or an opaque constant, or an
axiom), as e.g. in :g:`x u1 ... un` , or :g:`match x with ... end`, or
:g:`(fix f x {struct x} := ...) x`, or is a constructed form (a
:math:`\lambda`-expression, a constructor, a cofixpoint, an inductive type, a
@@ -2804,14 +2835,18 @@ the conversion in hypotheses :n:`{+ @ident}`.
This tactic applies to a goal that has the form::
- forall (x:T1) ... (xk:Tk), t
+ forall (x:T1) ... (xk:Tk), T
- with :g:`t` :math:`\beta`:math:`\iota`:math:`\zeta`-reducing to :g:`c t`:sub:`1` :g:`... t`:sub:`n` and :g:`c` a
+ with :g:`T` :math:`\beta`:math:`\iota`:math:`\zeta`-reducing to :g:`c t`:sub:`1` :g:`... t`:sub:`n` and :g:`c` a
constant. If :g:`c` is transparent then it replaces :g:`c` with its
definition (say :g:`t`) and then reduces
:g:`(t t`:sub:`1` :g:`... t`:sub:`n` :g:`)` according to :math:`\beta`:math:`\iota`:math:`\zeta`-reduction rules.
.. exn:: Not reducible.
+ :undocumented:
+
+.. exn:: No head constant to reduce.
+ :undocumented:
.. tacn:: hnf
:name: hnf
@@ -2821,8 +2856,7 @@ the conversion in hypotheses :n:`{+ @ident}`.
reduces the head of the goal until it becomes a product or an
irreducible term. All inner :math:`\beta`:math:`\iota`-redexes are also reduced.
- Example: The term :g:`forall n:nat, (plus (S n) (S n))` is not reduced by
- :n:`hnf`.
+ Example: The term :g:`fun n : nat => S n + S n` is not reduced by :n:`hnf`.
.. note::
The :math:`\delta` rule only applies to transparent constants (see :ref:`vernac-controlling-the-reduction-strategies`
@@ -2853,6 +2887,7 @@ the conversion in hypotheses :n:`{+ @ident}`.
+ A constant can be marked to be never unfolded by ``cbn`` or ``simpl``:
.. example::
+
.. coqtop:: all
Arguments minus n m : simpl never.
@@ -2862,9 +2897,10 @@ the conversion in hypotheses :n:`{+ @ident}`.
+ A constant can be marked to be unfolded only if applied to enough
arguments. The number of arguments required can be specified using the
- ``/`` symbol in the arguments list of the ``Arguments`` vernacular command.
+ ``/`` symbol in the argument list of the :cmd:`Arguments` vernacular command.
.. example::
+
.. coqtop:: all
Definition fcomp A B C f (g : A -> B) (x : A) : C := f (g x).
@@ -2877,6 +2913,7 @@ the conversion in hypotheses :n:`{+ @ident}`.
always unfolded.
.. example::
+
.. coqtop:: all
Definition volatile := fun x : nat => x.
@@ -2887,6 +2924,7 @@ the conversion in hypotheses :n:`{+ @ident}`.
such arguments.
.. example::
+
.. coqtop:: all
Arguments minus !n !m.
@@ -3030,7 +3068,7 @@ the conversion in hypotheses :n:`{+ @ident}`.
For instance, if the current goal :g:`T` is expressible as
:math:`\varphi`:g:`(t)` where the notation captures all the instances of :g:`t`
in :math:`\varphi`:g:`(t)`, then :n:`pattern t` transforms it into
- :g:`(fun x:A =>` :math:`\varphi`:g:`(x)) t`. This command can be used, for
+ :g:`(fun x:A =>` :math:`\varphi`:g:`(x)) t`. This tactic can be used, for
instance, when the tactic ``apply`` fails on matching.
.. tacv:: pattern @term at {+ @num}
@@ -3072,10 +3110,10 @@ Conversion tactics applied to hypotheses
listed in this section.
If :n:`@ident` is a local definition, then :n:`@ident` can be replaced by
- (Type of :n:`@ident`) to address not the body but the type of the local
+ (type of :n:`@ident`) to address not the body but the type of the local
definition.
- Example: :n:`unfold not in (Type of H1) (Type of H3)`.
+ Example: :n:`unfold not in (type of H1) (type of H3)`.
.. exn:: No such hypothesis: @ident.
@@ -3165,7 +3203,7 @@ the :tacn:`auto` and :tacn:`trivial` tactics:
.. opt:: Info Trivial
.. opt:: Debug Trivial
-See also: :ref:`The Hints Databases for auto and eauto <thehintsdatabasesforautoandeauto>`
+.. seealso:: :ref:`The Hints Databases for auto and eauto <thehintsdatabasesforautoandeauto>`
.. tacn:: eauto
:name: eauto
@@ -3177,6 +3215,7 @@ where :tacn:`auto` uses simple :tacn:`apply`). As a consequence, :tacn:`eauto`
can solve such a goal:
.. example::
+
.. coqtop:: all
Hint Resolve ex_intro.
@@ -3195,7 +3234,7 @@ Note that ``ex_intro`` should be declared as a hint.
.. opt:: Info Eauto
.. opt:: Debug Eauto
-See also: :ref:`The Hints Databases for auto and eauto <thehintsdatabasesforautoandeauto>`
+.. seealso:: :ref:`The Hints Databases for auto and eauto <thehintsdatabasesforautoandeauto>`
.. tacn:: autounfold with {+ @ident}
@@ -3216,10 +3255,10 @@ in the given databases.
.. tacn:: autorewrite with {+ @ident}
:name: autorewrite
-This tactic [4]_ carries out rewritings according the rewriting rule
+This tactic [4]_ carries out rewritings according to the rewriting rule
bases :n:`{+ @ident}`.
-Each rewriting rule of a base :n:`@ident` is applied to the main subgoal until
+Each rewriting rule from the base :n:`@ident` is applied to the main subgoal until
it fails. Once all the rules have been processed, if the main subgoal has
progressed (e.g., if it is distinct from the initial main goal) then the rules
of this base are processed again. If the main subgoal has not progressed then
@@ -3252,10 +3291,10 @@ command.
Performs all the rewriting in the clause :n:`@clause`. The clause argument
must not contain any ``type of`` nor ``value of``.
-See also: :ref:`Hint-Rewrite <hintrewrite>` for feeding the database of lemmas used by
-:tacn:`autorewrite`.
+.. seealso::
-See also: :tacn:`autorewrite` for examples showing the use of this tactic.
+ :ref:`Hint-Rewrite <hintrewrite>` for feeding the database of lemmas used by
+ :tacn:`autorewrite` and :tacn:`autorewrite` for examples showing the use of this tactic.
.. tacn:: easy
:name: easy
@@ -3312,7 +3351,7 @@ automatically created.
(c.f. :ref:`The hints databases for auto and eauto <thehintsdatabasesforautoandeauto>`),
making the retrieval more efficient. The legacy implementation (the default one
for new databases) uses the DT only on goals without existentials (i.e., :tacn:`auto`
- goals), for non-Immediate hints and do not make use of transparency
+ goals), for non-Immediate hints and does not make use of transparency
hints, putting more work on the unification that is run after
retrieval (it keeps a list of the lemmas in case the DT is not used).
The new implementation enabled by the discriminated option makes use
@@ -3422,18 +3461,24 @@ The general command to add a hint to some databases :n:`{+ @ident}` is
Adds each :n:`Hint Unfold @ident`.
- .. cmdv:: Hint %( Transparent %| Opaque %) @qualid
- :name: Hint ( Transparent | Opaque )
+ .. cmdv:: Hint Transparent {+ @qualid}
+ Hint Opaque {+ @qualid}
+ :name: Hint Transparent; Hint Opaque
- This adds a transparency hint to the database, making :n:`@qualid` a
- transparent or opaque constant during resolution. This information is used
+ This adds transparency hints to the database, making :n:`@qualid`
+ transparent or opaque constants during resolution. This information is used
during unification of the goal with any lemma in the database and inside the
discrimination network to relax or constrain it in the case of discriminated
databases.
- .. cmdv:: Hint %( Transparent %| Opaque %) {+ @ident}
+ .. cmdv:: Hint Variables %( Transparent %| Opaque %)
+ Hint Constants %( Transparent %| Opaque %)
+ :name: Hint Variables; Hint Constants
- Declares each :n:`@ident` as a transparent or opaque constant.
+ This sets the transparency flag used during unification of
+ hints in the database for all constants or all variables,
+ overwritting the existing settings of opacity. It is advised
+ to use this just after a :cmd:`Create HintDb` command.
.. cmdv:: Hint Extern @num {? @pattern} => @tactic
:name: Hint Extern
@@ -3490,7 +3535,7 @@ The general command to add a hint to some databases :n:`{+ @ident}` is
The `emp` regexp does not match any search path while `eps`
matches the empty path. During proof search, the path of
successive successful hints on a search branch is recorded, as a
- list of identifiers for the hints (note Hint Extern’s do not have
+ list of identifiers for the hints (note that Hint Extern’s do not have
an associated identifier).
Before applying any hint :n:`@ident` the current path `p` extended with
:n:`@ident` is matched against the current cut expression `c` associated to
@@ -3529,15 +3574,14 @@ Hint databases defined in the Coq standard library
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Several hint databases are defined in the Coq standard library. The
-actual content of a database is the collection of the hints declared
+actual content of a database is the collection of hints declared
to belong to this database in each of the various modules currently
-loaded. Especially, requiring new modules potentially extend a
-database. At Coq startup, only the core database is non empty and can
-be used.
+loaded. Especially, requiring new modules may extend the database.
+At Coq startup, only the core database is nonempty and can be used.
:core: This special database is automatically used by ``auto``, except when
pseudo-database ``nocore`` is given to ``auto``. The core database
- contains only basic lemmas about negation, conjunction, and so on from.
+ contains only basic lemmas about negation, conjunction, and so on.
Most of the hints in this database come from the Init and Logic directories.
:arith: This database contains all lemmas about Peano’s arithmetic proved in the
@@ -3546,7 +3590,7 @@ be used.
:zarith: contains lemmas about binary signed integers from the directories
theories/ZArith. When required, the module Omega also extends the
database zarith with a high-cost hint that calls ``omega`` on equations
- and inequalities in nat or Z.
+ and inequalities in ``nat`` or ``Z``.
:bool: contains lemmas about booleans, mostly from directory theories/Bool.
@@ -3556,7 +3600,7 @@ be used.
:sets: contains lemmas about sets and relations from the directories Sets and
Relations.
-:typeclass_instances: contains all the type class instances declared in the
+:typeclass_instances: contains all the typeclass instances declared in the
environment, including those used for ``setoid_rewrite``,
from the Classes directory.
@@ -3649,7 +3693,7 @@ but this is a mere workaround and has some limitations (for instance, external
hints cannot be removed).
A proper way to fix this issue is to bind the hints to their module scope, as
-for most of the other objects Coq uses. Hints should only made available when
+for most of the other objects Coq uses. Hints should only be made available when
the module they are defined in is imported, not just required. It is very
difficult to change the historical behavior, as it would break a lot of scripts.
We propose a smooth transitional path by providing the :opt:`Loose Hint Behavior`
@@ -3685,7 +3729,7 @@ Setting implicit automation tactics
In this case the tactic command typed by the user is equivalent to
``tactic``:sub:`1` ``;tactic``.
- See also: ``Proof.`` in :ref:`proof-editing-mode`.
+ .. seealso:: :cmd:`Proof` in :ref:`proof-editing-mode`.
.. cmdv:: Proof with tactic using {+ @ident}
@@ -3740,6 +3784,7 @@ The following goal can be proved by :tacn:`tauto` whereas :tacn:`auto` would
fail:
.. example::
+
.. coqtop:: reset all
Goal forall (x:nat) (P:nat -> Prop), x = 0 \/ P x -> x <> 0 -> P x.
@@ -3768,9 +3813,9 @@ Therefore, the use of :tacn:`intros` in the previous proof is unnecessary.
:name: dtauto
While :tacn:`tauto` recognizes inductively defined connectives isomorphic to
- the standard connective ``and, prod, or, sum, False, Empty_set, unit, True``,
- :tacn:`dtauto` recognizes also all inductive types with one constructors and
- no indices, i.e. record-style connectives.
+ the standard connectives ``and``, ``prod``, ``or``, ``sum``, ``False``,
+ ``Empty_set``, ``unit``, ``True``, :tacn:`dtauto` also recognizes all inductive
+ types with one constructor and no indices, i.e. record-style connectives.
.. tacn:: intuition @tactic
:name: intuition
@@ -3786,7 +3831,7 @@ For instance, the tactic :g:`intuition auto` applied to the goal
::
- (forall (x:nat), P x)/\B -> (forall (y:nat),P y)/\ P O \/B/\ P O
+ (forall (x:nat), P x) /\ B -> (forall (y:nat), P y) /\ P O \/ B /\ P O
internally replaces it by the equivalent one:
@@ -3813,9 +3858,9 @@ some incompatibilities.
:name: dintuition
While :tacn:`intuition` recognizes inductively defined connectives
- isomorphic to the standard connective ``and``, ``prod``, ``or``, ``sum``, ``False``,
- ``Empty_set``, ``unit``, ``True``, :tacn:`dintuition` recognizes also all inductive
- types with one constructors and no indices, i.e. record-style connectives.
+ isomorphic to the standard connectives ``and``, ``prod``, ``or``, ``sum``, ``False``,
+ ``Empty_set``, ``unit``, ``True``, :tacn:`dintuition` also recognizes all inductive
+ types with one constructor and no indices, i.e. record-style connectives.
.. opt:: Intuition Negation Unfolding
@@ -3830,11 +3875,12 @@ The :tacn:`rtauto` tactic solves propositional tautologies similarly to what
reflection scheme applied to a sequent calculus proof of the goal. The search
procedure is also implemented using a different technique.
-Users should be aware that this difference may result in faster proof- search
+Users should be aware that this difference may result in faster proof-search
but slower proof-checking, and :tacn:`rtauto` might not solve goals that
:tacn:`tauto` would be able to solve (e.g. goals involving universal
quantifiers).
+Note that this tactic is only available after a ``Require Import Rtauto``.
.. tacn:: firstorder
:name: firstorder
@@ -3881,7 +3927,7 @@ inductive definition.
The tactic :tacn:`congruence`, by Pierre Corbineau, implements the standard
Nelson and Oppen congruence closure algorithm, which is a decision procedure
-for ground equalities with uninterpreted symbols. It also include the
+for ground equalities with uninterpreted symbols. It also includes
constructor theory (see :tacn:`injection` and :tacn:`discriminate`). If the goal
is a non-quantified equality, congruence tries to prove it with non-quantified
equalities in the context. Otherwise it tries to infer a discriminable equality
@@ -3889,12 +3935,13 @@ from those in the context. Alternatively, congruence tries to prove that a
hypothesis is equal to the goal or to the negation of another hypothesis.
:tacn:`congruence` is also able to take advantage of hypotheses stating
-quantified equalities, you have to provide a bound for the number of extra
-equalities generated that way. Please note that one of the members of the
+quantified equalities, but you have to provide a bound for the number of extra
+equalities generated that way. Please note that one of the sides of the
equality must contain all the quantified variables in order for congruence to
match against it.
.. example::
+
.. coqtop:: reset all
Theorem T (A:Type) (f:A -> A) (g: A -> A -> A) a b: a=(f a) -> (g b (f a))=(f (f a)) -> (g a b)=(f (g b a)) -> (g a b)=a.
@@ -3926,7 +3973,7 @@ match against it.
discriminable equality but this proof could not be built in Coq because of
dependently-typed functions.
-.. exn:: Goal is solvable by congruence but some arguments are missing. Try congruence with ..., replacing metavariables by arbitrary terms.
+.. exn:: Goal is solvable by congruence but some arguments are missing. Try congruence with {+ @term}, replacing metavariables by arbitrary terms.
The decision procedure could solve the goal with the provision that additional
arguments are supplied for some partially applied constructors. Any term of an
@@ -3970,7 +4017,7 @@ succeeds, and results in an error otherwise.
This tactic checks whether its arguments are unifiable, potentially
instantiating existential variables.
-.. exn:: Not unifiable.
+.. exn:: Unable to unify @term with @term.
.. tacv:: unify @term @term with @ident
@@ -4065,10 +4112,10 @@ symbol :g:`=`.
.. tacn:: decide equality
:name: decide equality
- This tactic solves a goal of the form :g:`forall x y:R, {x=y}+{ ~x=y}`,
+ This tactic solves a goal of the form :g:`forall x y : R, {x = y} + {~ x = y}`,
where :g:`R` is an inductive type such that its constructors do not take
proofs or functions as arguments, nor objects in dependent types. It
- solves goals of the form :g:`{x=y}+{ ~x=y}` as well.
+ solves goals of the form :g:`{x = y} + {~ x = y}` as well.
.. tacn:: compare @term @term
:name: compare
@@ -4156,8 +4203,9 @@ available after a ``Require Import FunInd``.
.. tacv:: functional inversion @num
- This does the same thing as intros until num thenfunctional inversion ident
- where ident is the identifier for the last introduced hypothesis.
+ This does the same thing as :n:`intros until @num` folowed by
+ :n:`functional inversion @ident` where :token:`ident` is the
+ identifier for the last introduced hypothesis.
.. tacv:: functional inversion ident qualid
.. tacv:: functional inversion num qualid
@@ -4184,7 +4232,7 @@ datatype: see :ref:`quote` for the full details.
Happens when quote is not able to perform inversion properly.
-.. tacv:: quote ident {* @ident}
+.. tacv:: quote @ident {* @ident}
All terms that are built only with :n:`{* @ident}` will be considered by quote
as constants rather than variables.
@@ -4208,9 +4256,9 @@ using the ``Require Import`` command.
Use ``classical_right`` to prove the right part of the disjunction with
the assumption that the negation of left part holds.
-.. _tactics-automatizing:
+.. _tactics-automating:
-Automatizing
+Automating
------------
@@ -4239,6 +4287,12 @@ constructed over the following grammar:
Internally, it uses a system very similar to the one of the ring
tactic.
+ Note that this tactic is only available after a ``Require Import Btauto``.
+
+.. exn:: Cannot recognize a boolean equality.
+
+ The goal is not of the form :g:`t = u`. Especially note that :tacn:`btauto`
+ doesn't introduce variables into the context on its own.
.. tacn:: omega
:name: omega
@@ -4258,13 +4312,13 @@ and :g:`Z` of binary integers. This tactic must be loaded by the command
:name: ring_simplify
The :n:`ring` tactic solves equations upon polynomial expressions of a ring
-(or semi-ring) structure. It proceeds by normalizing both hand sides
+(or semiring) structure. It proceeds by normalizing both hand sides
of the equation (w.r.t. associativity, commutativity and
distributivity, constant propagation) and comparing syntactically the
results.
:n:`ring_simplify` applies the normalization procedure described above to
-the terms given. The tactic then replaces all occurrences of the terms
+the given terms. The tactic then replaces all occurrences of the terms
given in the conclusion of the goal by their normal forms. If no term
is given, then the conclusion should be an equation and both hand
sides are normalized.
@@ -4300,6 +4354,7 @@ declare new field structures. All declared field structures can be
printed with the Print Fields command.
.. example::
+
.. coqtop:: reset all
Require Import Reals.
@@ -4310,23 +4365,10 @@ printed with the Print Fields command.
intros; field.
-See also: file plugins/setoid_ring/RealField.v for an example of instantiation,
-theory theories/Reals for many examples of use of field.
-
-.. tacn:: fourier
- :name: fourier
+.. seealso::
-This tactic written by Loïc Pottier solves linear inequalities on real
-numbers using Fourier’s method :cite:`Fourier`. This tactic must be loaded by
-``Require Import Fourier``.
-
-.. example::
- .. coqtop:: reset all
-
- Require Import Reals.
- Require Import Fourier.
- Goal forall x y:R, (x < y)%R -> (y + 1 >= x - 1)%R.
- intros; fourier.
+ File plugins/setoid_ring/RealField.v for an example of instantiation,
+ theory theories/Reals for many examples of use of field.
Non-logical tactics
------------------------
@@ -4426,6 +4468,7 @@ Simple tactic macros
A simple example has more value than a long explanation:
.. example::
+
.. coqtop:: reset all
Ltac Solve := simpl; intros; auto.
@@ -4446,7 +4489,7 @@ user-defined tactics.
other one can be automatically checked.
.. [2] This corresponds to the cut rule of sequent calculus.
.. [3] Reminder: opaque constants will not be expanded by δ reductions.
-.. [4] The behavior of this tactic has much changed compared to the
+.. [4] The behavior of this tactic has changed a lot compared to the
versions available in the previous distributions (V6). This may cause
significant changes in your theories to obtain the same result. As a
drawback of the re-engineering of the code, this tactic has also been
diff --git a/doc/sphinx/proof-engine/vernacular-commands.rst b/doc/sphinx/proof-engine/vernacular-commands.rst
index c37233734b..584193b9c6 100644
--- a/doc/sphinx/proof-engine/vernacular-commands.rst
+++ b/doc/sphinx/proof-engine/vernacular-commands.rst
@@ -246,7 +246,7 @@ Requests to the environment
hypothesis introduced in the first subgoal (if a proof is in
progress).
- See also: Section :ref:`performingcomputations`.
+ .. seealso:: Section :ref:`performingcomputations`.
.. cmd:: Compute @term
@@ -255,7 +255,7 @@ Requests to the environment
bytecode-based virtual machine. It is a shortcut for ``Eval vm_compute in``
:n:`@term`.
- See also: Section :ref:`performingcomputations`.
+ .. seealso:: Section :ref:`performingcomputations`.
.. cmd:: Print Assumptions @qualid
@@ -521,7 +521,7 @@ Requests to the environment
This command displays the full name of objects whose name is a prefix
of the qualified identifier :n:`@qualid`, and consequently the |Coq| module in
which they are defined. It searches for objects from the different
- qualified name spaces of |Coq|: terms, modules, Ltac, etc.
+ qualified namespaces of |Coq|: terms, modules, Ltac, etc.
.. example::
@@ -549,7 +549,7 @@ Requests to the environment
As Locate but restricted to tactics.
-See also: Section :ref:`locating-notations`
+.. seealso:: Section :ref:`locating-notations`
.. _loading-files:
@@ -587,7 +587,9 @@ toplevel. This kind of file is called a *script* for |Coq|. The standard
Display, while loading,
the answers of |Coq| to each command (including tactics) contained in
- the loaded file See also: Section :ref:`controlling-display`.
+ the loaded file.
+
+ .. seealso:: Section :ref:`controlling-display`.
.. exn:: Can’t find file @ident on loadpath.
@@ -699,10 +701,7 @@ file is a particular case of module called *library file*.
that the commands ``Import`` and ``Export`` alone can be used inside modules
(see Section :ref:`Import <import_qualid>`).
-
-
-See also: Chapter :ref:`thecoqcommands`
-
+ .. seealso:: Chapter :ref:`thecoqcommands`
.. cmd:: Print Libraries
@@ -930,7 +929,7 @@ Quitting and debugging
.. cmd:: Drop
- This is used mostly as a debug facility by |Coq|’s implementors and does
+ This is used mostly as a debug facility by |Coq|’s implementers and does
not concern the casual user. This command permits to leave |Coq|
temporarily and enter the OCaml toplevel. The OCaml
command:
@@ -1097,8 +1096,10 @@ described first.
The scope of :cmd:`Opaque` is limited to the current section, or current
file, unless the variant :cmd:`Global Opaque` is used.
- See also: sections :ref:`performingcomputations`, :ref:`tactics-automatizing`,
- :ref:`proof-editing-mode`
+ .. seealso::
+
+ Sections :ref:`performingcomputations`, :ref:`tactics-automating`,
+ :ref:`proof-editing-mode`
.. exn:: The reference @qualid was not found in the current environment.
@@ -1130,8 +1131,10 @@ described first.
There is no constant referred by :n:`@qualid` in the environment.
- See also: sections :ref:`performingcomputations`,
- :ref:`tactics-automatizing`, :ref:`proof-editing-mode`
+ .. seealso::
+
+ Sections :ref:`performingcomputations`,
+ :ref:`tactics-automating`, :ref:`proof-editing-mode`
.. _vernac-strategy:
@@ -1195,7 +1198,7 @@ described first.
nothing prevents the user to also perform a
``Ltac`` `ident` ``:=`` `convtactic`.
- See also: sections :ref:`performingcomputations`
+ .. seealso:: :ref:`performingcomputations`
.. _controlling-locality-of-commands:
@@ -1217,19 +1220,19 @@ scope of their effect. There are four kinds of commands:
current section or module it occurs in. As an example, the :cmd:`Coercion`
and :cmd:`Strategy` commands belong to this category.
+ Commands whose default behavior is to stop their effect at the end
- of the section they occur in but to extent their effect outside the module or
+ of the section they occur in but to extend their effect outside the module or
library file they occur in. For these commands, the Local modifier limits the
effect of the command to the current module if the command does not occur in a
section and the Global modifier extends the effect outside the current
sections and current module if the command occurs in a section. As an example,
the :cmd:`Arguments`, :cmd:`Ltac` or :cmd:`Notation` commands belong
to this category. Notice that a subclass of these commands do not support
- extension of their scope outside sections at all and the Global is not
+ extension of their scope outside sections at all and the Global modifier is not
applicable to them.
+ Commands whose default behavior is to stop their effect at the end
of the section or module they occur in. For these commands, the ``Global``
modifier extends their effect outside the sections and modules they
- occurs in. The :cmd:`Transparent` and :cmd:`Opaque`
+ occur in. The :cmd:`Transparent` and :cmd:`Opaque`
(see Section :ref:`vernac-controlling-the-reduction-strategies`) commands
belong to this category.
+ Commands whose default behavior is to extend their effect outside
diff --git a/doc/sphinx/user-extensions/proof-schemes.rst b/doc/sphinx/user-extensions/proof-schemes.rst
index 838926d651..ab1edc0b27 100644
--- a/doc/sphinx/user-extensions/proof-schemes.rst
+++ b/doc/sphinx/user-extensions/proof-schemes.rst
@@ -40,8 +40,7 @@ induction for objects in type `identᵢ`.
Induction scheme for tree and forest.
- The definition of principle of mutual induction for tree and forest
- over the sort Set is defined by the command:
+ A mutual induction principle for tree and forest in sort ``Set`` can be defined using the command
.. coqtop:: none
@@ -193,10 +192,12 @@ command generates the induction principle for each `identᵢ`, following
the recursive structure and case analyses of the corresponding function
identᵢ’.
-Remark: There is a difference between obtaining an induction scheme by
-using ``Functional Scheme`` on a function defined by ``Function`` or not.
-Indeed, ``Function`` generally produces smaller principles, closer to the
-definition written by the user.
+.. warning::
+
+ There is a difference between induction schemes generated by the command
+ :cmd:`Functional Scheme` and these generated by the :cmd:`Function`. Indeed,
+ :cmd:`Function` generally produces smaller principles that are closer to how
+ a user would implement them. See :ref:`advanced-recursive-functions` for details.
.. example::
@@ -257,11 +258,6 @@ definition written by the user.
auto with arith.
Qed.
- Remark: There is a difference between obtaining an induction scheme
- for a function by using ``Function`` (see :ref:`advanced-recursive-functions`) and by using
- ``Functional Scheme`` after a normal definition using ``Fixpoint`` or
- ``Definition``. See :ref:`advanced-recursive-functions` for details.
-
.. example::
Induction scheme for tree_size.
@@ -298,15 +294,15 @@ definition written by the user.
| cons t f' => (tree_size t + forest_size f')
end.
- Remark: Function generates itself non mutual induction principles
- tree_size_ind and forest_size_ind:
+ Notice that the induction principles ``tree_size_ind`` and ``forest_size_ind``
+ generated by ``Function`` are not mutual.
.. coqtop:: all
Check tree_size_ind.
- The definition of mutual induction principles following the recursive
- structure of `tree_size` and `forest_size` is defined by the command:
+ Mutual induction principles following the recursive structure of ``tree_size``
+ and ``forest_size`` can be generated by the following command:
.. coqtop:: all
@@ -352,10 +348,8 @@ having inverted the instance with the tactic `inversion`.
.. example::
- Let us consider the relation `Le` over natural numbers and the following
- variable:
-
- .. original LaTeX had "Variable" instead of "Axiom", which generates an ugly warning
+ Consider the relation `Le` over natural numbers and the following
+ parameter ``P``:
.. coqtop:: all
@@ -363,7 +357,7 @@ having inverted the instance with the tactic `inversion`.
| LeO : forall n:nat, Le 0 n
| LeS : forall n m:nat, Le n m -> Le (S n) (S m).
- Axiom P : nat -> nat -> Prop.
+ Parameter P : nat -> nat -> Prop.
To generate the inversion lemma for the instance `(Le (S n) m)` and the
sort `Prop`, we do:
diff --git a/doc/sphinx/user-extensions/syntax-extensions.rst b/doc/sphinx/user-extensions/syntax-extensions.rst
index 3b95a37ed3..5089a1b3e3 100644
--- a/doc/sphinx/user-extensions/syntax-extensions.rst
+++ b/doc/sphinx/user-extensions/syntax-extensions.rst
@@ -10,15 +10,14 @@ parses and prints objects, i.e. the translations between the concrete
and internal representations of terms and commands.
The main commands to provide custom symbolic notations for terms are
-``Notation`` and ``Infix``. They are described in section :ref:`Notations`. There is also a
-variant of ``Notation`` which does not modify the parser. This provides with a
-form of abbreviation and it is described in Section :ref:`Abbreviations`. It is
+:cmd:`Notation` and :cmd:`Infix`; they will be described in the
+:ref:`next section <Notations>`. There is also a
+variant of :cmd:`Notation` which does not modify the parser; this provides a
+form of :ref:`abbreviation <Abbreviations>`. It is
sometimes expected that the same symbolic notation has different meanings in
-different contexts. To achieve this form of overloading, |Coq| offers a notion
-of interpretation scope. This is described in Section :ref:`Scopes`.
-
-The main command to provide custom notations for tactics is ``Tactic Notation``.
-It is described in Section :ref:`TacticNotation`.
+different contexts; to achieve this form of overloading, |Coq| offers a notion
+of :ref:`interpretation scopes <Scopes>`.
+The main command to provide custom notations for tactics is :cmd:`Tactic Notation`.
.. coqtop:: none
@@ -44,18 +43,18 @@ logical conjunction (and). Such a notation is declared by
Notation "A /\ B" := (and A B).
-The expression :g:`(and A B)` is the abbreviated term and the string ``"A /\ B"``
+The expression :g:`(and A B)` is the abbreviated term and the string :g:`"A /\ B"`
(called a *notation*) tells how it is symbolically written.
A notation is always surrounded by double quotes (except when the
abbreviation has the form of an ordinary applicative expression;
see :ref:`Abbreviations`). The notation is composed of *tokens* separated by
spaces. Identifiers in the string (such as ``A`` and ``B``) are the *parameters*
-of the notation. They must occur at least once each in the denoted term. The
+of the notation. Each of them must occur at least once in the denoted term. The
other elements of the string (such as ``/\``) are the *symbols*.
An identifier can be used as a symbol but it must be surrounded by
-simple quotes to avoid the confusion with a parameter. Similarly,
+single quotes to avoid the confusion with a parameter. Similarly,
every symbol of at least 3 characters and starting with a simple quote
must be quoted (then it starts by two single quotes). Here is an
example.
@@ -66,15 +65,15 @@ example.
A notation binds a syntactic expression to a term. Unless the parser
and pretty-printer of Coq already know how to deal with the syntactic
-expression (see 12.1.7), explicit precedences and associativity rules
-have to be given.
+expression (see :ref:`ReservingNotations`), explicit precedences and
+associativity rules have to be given.
.. note::
The right-hand side of a notation is interpreted at the time the notation is
- given. In particular, disambiguation of constants, implicit arguments (see
- Section :ref:`ImplicitArguments`), coercions (see Section :ref:`Coercions`),
- etc. are resolved at the time of the declaration of the notation.
+ given. In particular, disambiguation of constants, :ref:`implicit arguments
+ <ImplicitArguments>`, :ref:`coercions <Coercions>`, etc. are resolved at the
+ time of the declaration of the notation.
Precedences and associativity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -106,13 +105,13 @@ is 100, for example 85 for disjunction and 80 for conjunction [#and_or_levels]_.
Similarly, an associativity is needed to decide whether :g:`True /\ False /\ False`
defaults to :g:`True /\ (False /\ False)` (right associativity) or to
:g:`(True /\ False) /\ False` (left associativity). We may even consider that the
-expression is not well- formed and that parentheses are mandatory (this is a “no
+expression is not well-formed and that parentheses are mandatory (this is a “no
associativity”) [#no_associativity]_. We do not know of a special convention of
the associativity of disjunction and conjunction, so let us apply for instance a
right associativity (which is the choice of Coq).
Precedence levels and associativity rules of notations have to be
-given between parentheses in a list of modifiers that the ``Notation``
+given between parentheses in a list of modifiers that the :cmd:`Notation`
command understands. Here is how the previous examples refine.
.. coqtop:: in
@@ -120,11 +119,12 @@ command understands. Here is how the previous examples refine.
Notation "A /\ B" := (and A B) (at level 80, right associativity).
Notation "A \/ B" := (or A B) (at level 85, right associativity).
-By default, a notation is considered non associative, but the
+By default, a notation is considered nonassociative, but the
precedence level is mandatory (except for special cases whose level is
-canonical). The level is either a number or the phrase `next level`
-whose meaning is obvious. The list of levels already assigned is on
-Figure 3.1.
+canonical). The level is either a number or the phrase ``next level``
+whose meaning is obvious.
+Some :ref:`associativities are predefined <init-notations>` in the
+``Notations`` module.
.. TODO I don't find it obvious -- CPC
@@ -139,14 +139,14 @@ instance define prefix notations.
Notation "~ x" := (not x) (at level 75, right associativity).
One can also define notations for incomplete terms, with the hole
-expected to be inferred at typing time.
+expected to be inferred during type checking.
.. coqtop:: in
Notation "x = y" := (@eq _ x y) (at level 70, no associativity).
One can define *closed* notations whose both sides are symbols. In this case,
-the default precedence level for the inner subexpression is 200, and the default
+the default precedence level for the inner sub-expression is 200, and the default
level for the notation itself is 0.
.. coqtop:: in
@@ -162,7 +162,7 @@ One can also define notations for binders.
In the last case though, there is a conflict with the notation for
type casts. The notation for types casts, as shown by the command :cmd:`Print
Grammar constr` is at level 100. To avoid ``x : A`` being parsed as a type cast,
-it is necessary to put x at a level below 100, typically 99. Hence, a correct
+it is necessary to put ``x`` at a level below 100, typically 99. Hence, a correct
definition is the following:
.. coqtop:: all
@@ -176,7 +176,7 @@ Simple factorization rules
~~~~~~~~~~~~~~~~~~~~~~~~~~
Coq extensible parsing is performed by *Camlp5* which is essentially a LL1
-parser: it decides which notation to parse by looking tokens from left to right.
+parser: it decides which notation to parse by looking at tokens from left to right.
Hence, some care has to be taken not to hide already existing rules by new
rules. Some simple left factorization work has to be done. Here is an example.
@@ -186,21 +186,21 @@ rules. Some simple left factorization work has to be done. Here is an example.
Notation "x < y < z" := (x < y /\ y < z) (at level 70).
In order to factorize the left part of the rules, the subexpression
-referred by y has to be at the same level in both rules. However the
-default behavior puts y at the next level below 70 in the first rule
-(no associativity is the default), and at the level 200 in the second
-rule (level 200 is the default for inner expressions). To fix this, we
-need to force the parsing level of y, as follows.
+referred to by ``y`` has to be at the same level in both rules. However the
+default behavior puts ``y`` at the next level below 70 in the first rule
+(``no associativity`` is the default), and at level 200 in the second
+rule (``level 200`` is the default for inner expressions). To fix this, we
+need to force the parsing level of ``y``, as follows.
-.. coqtop:: all
+.. coqtop:: in
Notation "x < y" := (lt x y) (at level 70).
Notation "x < y < z" := (x < y /\ y < z) (at level 70, y at next level).
For the sake of factorization with Coq predefined rules, simple rules
-have to be observed for notations starting with a symbol: e.g. rules
-starting with “{” or “(” should be put at level 0. The list of Coq
-predefined notations can be found in Chapter :ref:`thecoqlibrary`.
+have to be observed for notations starting with a symbol, e.g., rules
+starting with “\ ``{``\ ” or “\ ``(``\ ” should be put at level 0. The list
+of Coq predefined notations can be found in the chapter on :ref:`thecoqlibrary`.
.. cmd:: Print Grammar constr.
@@ -209,13 +209,13 @@ predefined notations can be found in Chapter :ref:`thecoqlibrary`.
.. cmd:: Print Grammar pattern.
This displays the state of the subparser of patterns (the parser used in the
- grammar of the match with constructions).
+ grammar of the ``match with`` constructions).
Displaying symbolic notations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The command ``Notation`` has an effect both on the Coq parser and on the
+The command :cmd:`Notation` has an effect both on the Coq parser and on the
Coq printer. For example:
.. coqtop:: all
@@ -283,7 +283,7 @@ the possible following elements delimited by single quotes:
(4 spaces in the example)
- well-bracketed pairs of tokens of the form ``'[hv '`` and ``']'`` are
- translated into horizontal-orelse-vertical printing boxes; if the
+ translated into horizontal-or-else-vertical printing boxes; if the
content of the box does not fit on a single line, then every breaking
point forces a newline and an extra indentation of the number of
spaces given after the “ ``[``” is applied at the beginning of each
@@ -295,13 +295,13 @@ the possible following elements delimited by single quotes:
of the box, and an extra indentation of the number of spaces given
after the “``[``” is applied at the beginning of each newline
-Notations do not survive the end of sections. No typing of the denoted
-expression is performed at definition time. Type-checking is done only
+Notations disappear when a section is closed. No typing of the denoted
+expression is performed at definition time. Type checking is done only
at the time of use of the notation.
.. note:: Sometimes, a notation is expected only for the parser. To do
so, the option ``only parsing`` is allowed in the list of modifiers
- of ``Notation``. Conversely, the ``only printing`` modifier can be
+ of :cmd:`Notation`. Conversely, the ``only printing`` modifier can be
used to declare that a notation should only be used for printing and
should not declare a parsing rule. In particular, such notations do
not modify the parser.
@@ -309,7 +309,7 @@ at the time of use of the notation.
The Infix command
~~~~~~~~~~~~~~~~~~
-The ``Infix`` command is a shortening for declaring notations of infix
+The :cmd:`Infix` command is a shortening for declaring notations of infix
symbols.
.. cmd:: Infix "@symbol" := @term ({+, @modifier}).
@@ -324,6 +324,8 @@ symbols.
Infix "/\" := and (at level 80, right associativity).
+.. _ReservingNotations:
+
Reserving notations
~~~~~~~~~~~~~~~~~~~
@@ -341,14 +343,14 @@ state of Coq.
Reserving a notation is also useful for simultaneously defining an
inductive type or a recursive constant and a notation for it.
-.. note:: The notations mentioned on Figure 3.1 are reserved. Hence
+.. note:: The notations mentioned in the module :ref:`init-notations` are reserved. Hence
their precedence and associativity cannot be changed.
Simultaneous definition of terms and notations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Thanks to reserved notations, the inductive, co-inductive, record, recursive and
-corecursive definitions can benefit of customized notations. To do this, insert
+corecursive definitions can benefit from customized notations. To do this, insert
a ``where`` notation clause after the definition of the (co)inductive type or
(co)recursive term (or after the definition of each of them in case of mutual
definitions). The exact syntax is given by :token:`decl_notation` for inductive,
@@ -357,17 +359,23 @@ for records. Here are examples:
.. coqtop:: in
- Inductive and (A B:Prop) : Prop := conj : A -> B -> A /\ B
- where "A /\ B" := (and A B).
+ Reserved Notation "A & B" (at level 80).
+
+.. coqtop:: in
+
+ Inductive and' (A B : Prop) : Prop := conj' : A -> B -> A & B
+ where "A & B" := (and' A B).
- Fixpoint plus (n m:nat) {struct n} : nat :=
- match n with
- | O => m
- | S p => S (p+m)
- end
+.. coqtop:: in
+
+ Fixpoint plus (n m : nat) {struct n} : nat :=
+ match n with
+ | O => m
+ | S p => S (p+m)
+ end
where "n + m" := (plus n m).
-Displaying informations about notations
+Displaying information about notations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. opt:: Printing Notations
@@ -391,7 +399,7 @@ Locating notations
To know to which notations a given symbol belongs to, use the :cmd:`Locate`
command. You can call it on any (composite) symbol surrounded by double quotes.
To locate a particular notation, use a string where the variables of the
-notation are replaced by “_” and where possible single quotes inserted around
+notation are replaced by “``_``” and where possible single quotes inserted around
identifiers or tokens starting with a single quote are dropped.
.. coqtop:: all
@@ -404,7 +412,7 @@ Notations and binders
Notations can include binders. This section lists
different ways to deal with binders. For further examples, see also
-Section :ref:`RecursiveNotationsWithBinders`.
+:ref:`RecursiveNotationsWithBinders`.
Binders bound in the notation and parsed as identifiers
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -490,7 +498,7 @@ the following:
This is so because the grammar also contains rules starting with :g:`{}` and
followed by a term, such as the rule for the notation :g:`{ A } + { B }` for the
-constant :g:`sumbool` (see Section :ref:`specification`).
+constant :g:`sumbool` (see :ref:`specification`).
Then, in the rule, ``x ident`` is replaced by ``x at level 99 as ident`` meaning
that ``x`` is parsed as a term at level 99 (as done in the notation for
@@ -517,7 +525,7 @@ is just an identifier, one could have said
``p at level 99 as strict pattern``.
Note also that in the absence of a ``as ident``, ``as strict pattern`` or
-``as pattern`` modifiers, the default is to consider subexpressions occurring
+``as pattern`` modifiers, the default is to consider sub-expressions occurring
in binding position and parsed as terms to be ``as ident``.
.. _NotationsWithBinders:
@@ -545,7 +553,7 @@ the next command fails because p does not bind in the instance of n.
Notation "[> a , .. , b <]" :=
(cons a .. (cons b nil) .., cons b .. (cons a nil) ..).
-.. _RecursiveNotationsWithBinders:
+.. _RecursiveNotations:
Notations with recursive patterns
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -563,7 +571,7 @@ confused with the three-dots notation “``…``” used in this manual to denot
a sequence of arbitrary size.
On the left-hand side, the part “``x s .. s y``” of the notation parses
-any number of time (but at least one time) a sequence of expressions
+any number of times (but at least once) a sequence of expressions
separated by the sequence of tokens ``s`` (in the example, ``s`` is just “``;``”).
The right-hand side must contain a subterm of the form either
@@ -572,7 +580,7 @@ called the *iterator* of the recursive notation is an arbitrary expression with
distinguished placeholders and where :math:`t` is called the *terminating
expression* of the recursive notation. In the example, we choose the names
:math:`x` and :math:`y` but in practice they can of course be chosen
-arbitrarily. Not atht the placeholder :math:`[~]_I` has to occur only once but
+arbitrarily. Note that the placeholder :math:`[~]_I` has to occur only once but
:math:`[~]_E` can occur several times.
Parsing the notation produces a list of expressions which are used to
@@ -595,9 +603,10 @@ and the terminating expression is ``nil``. Here are other examples:
(t at level 39).
Notations with recursive patterns can be reserved like standard
-notations, they can also be declared within interpretation scopes (see
-section 12.2).
+notations, they can also be declared within
+:ref:`interpretation scopes <Scopes>`.
+.. _RecursiveNotationsWithBinders:
Notations with recursive patterns involving binders
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -605,13 +614,14 @@ Notations with recursive patterns involving binders
Recursive notations can also be used with binders. The basic example
is:
-.. coqtop:: all
+.. coqtop:: in
Notation "'exists' x .. y , p" :=
(ex (fun x => .. (ex (fun y => p)) ..))
(at level 200, x binder, y binder, right associativity).
-The principle is the same as in Section 12.1.12 except that in the iterator
+The principle is the same as in :ref:`RecursiveNotations`
+except that in the iterator
:math:`φ([~]_E , [~]_I)`, the placeholder :math:`[~]_E` can also occur in
position of the binding variable of a ``fun`` or a ``forall``.
@@ -620,10 +630,10 @@ binders, ``x`` and ``y`` must be marked as ``binder`` in the list of modifiers
of the notation. The binders of the parsed sequence are used to fill the
occurrences of the first placeholder of the iterating pattern which is
repeatedly nested as many times as the number of binders generated. If ever the
-generalization operator ``'`` (see Section 2.7.19) is used in the binding list,
-the added binders are taken into account too.
+generalization operator ``'`` (see :ref:`implicit-generalization`) is
+used in the binding list, the added binders are taken into account too.
-Binders parsing exist in two flavors. If ``x`` and ``y`` are marked as binder,
+There are two flavors of binder parsing. If ``x`` and ``y`` are marked as binder,
then a sequence such as :g:`a b c : T` will be accepted and interpreted as
the sequence of binders :g:`(a:T) (b:T) (c:T)`. For instance, in the
notation above, the syntax :g:`exists a b : nat, a = b` is valid.
@@ -646,7 +656,7 @@ example of recursive notation with closed binders:
A recursive pattern for binders can be used in position of a recursive
pattern for terms. Here is an example:
-.. coqtop:: in
+.. coqtop:: in
Notation "'FUNAPP' x .. y , f" :=
(fun x => .. (fun y => (.. (f x) ..) y ) ..)
@@ -678,7 +688,7 @@ position of :g:`x`:
In addition to ``global``, one can restrict the syntax of a
sub-expression by using the entry names ``ident`` or ``pattern``
-already seen in Section :ref:`NotationsWithBinders`, even when the
+already seen in :ref:`NotationsWithBinders`, even when the
corresponding expression is not used as a binder in the right-hand
side. E.g.:
@@ -687,13 +697,168 @@ side. E.g.:
Notation "'apply_id' f a1 .. an" := (.. (f a1) .. an)
(at level 10, f ident, a1, an at level 9).
+Custom entries
+~~~~~~~~~~~~~~
+
+.. cmd:: Declare Custom Entry @ident
+
+ This command allows to define new grammar entries, called *custom
+ entries*, that can later be referred to using the entry name
+ :n:`custom @ident`.
+
+.. example::
+
+ For instance, we may want to define an ad hoc
+ parser for arithmetical operations and proceed as follows:
+
+ .. coqtop:: all
+
+ Inductive Expr :=
+ | One : Expr
+ | Mul : Expr -> Expr -> Expr
+ | Add : Expr -> Expr -> Expr.
+
+ Declare Custom Entry expr.
+ Notation "[ e ]" := e (e custom expr at level 2).
+ Notation "1" := One (in custom expr at level 0).
+ Notation "x y" := (Mul x y) (in custom expr at level 1, left associativity).
+ Notation "x + y" := (Add x y) (in custom expr at level 2, left associativity).
+ Notation "( x )" := x (in custom expr, x at level 2).
+ Notation "{ x }" := x (in custom expr, x constr).
+ Notation "x" := x (in custom expr at level 0, x ident).
+
+ Axiom f : nat -> Expr.
+ Check fun x y z => [1 + y z + {f x}].
+ Unset Printing Notations.
+ Check fun x y z => [1 + y z + {f x}].
+ Set Printing Notations.
+ Check fun e => match e with
+ | [1 + 1] => [1]
+ | [x y + z] => [x + y z]
+ | y => [y + e]
+ end.
+
+Custom entries have levels, like the main grammar of terms and grammar
+of patterns have. The lower level is 0 and this is the level used by
+default to put rules delimited with tokens on both ends. The level is
+left to be inferred by Coq when using :n:`in custom @ident`. The
+level is otherwise given explicitly by using the syntax
+:n:`in custom @ident at level @num`, where :n:`@num` refers to the level.
+
+Levels are cumulative: a notation at level ``n`` of which the left end
+is a term shall use rules at level less than ``n`` to parse this
+sub-term. More precisely, it shall use rules at level strictly less
+than ``n`` if the rule is declared with ``right associativity`` and
+rules at level less or equal than ``n`` if the rule is declared with
+``left associativity``. Similarly, a notation at level ``n`` of which
+the right end is a term shall use by default rules at level strictly
+less than ``n`` to parse this sub-term if the rule is declared left
+associative and rules at level less or equal than ``n`` if the rule is
+declared right associative. This is what happens for instance in the
+rule
+
+.. coqtop:: in
+
+ Notation "x + y" := (Add x y) (in custom expr at level 2, left associativity).
+
+where ``x`` is any expression parsed in entry
+``expr`` at level less or equal than ``2`` (including, recursively,
+the given rule) and ``y`` is any expression parsed in entry ``expr``
+at level strictly less than ``2``.
+
+Rules associated to an entry can refer different sub-entries. The
+grammar entry name ``constr`` can be used to refer to the main grammar
+of term as in the rule
+
+.. coqtop:: in
+
+ Notation "{ x }" := x (in custom expr at level 0, x constr).
+
+which indicates that the subterm ``x`` should be
+parsed using the main grammar. If not indicated, the level is computed
+as for notations in ``constr``, e.g. using 200 as default level for
+inner sub-expressions. The level can otherwise be indicated explicitly
+by using ``constr at level n`` for some ``n``, or ``constr at next
+level``.
+
+Conversely, custom entries can be used to parse sub-expressions of the
+main grammar, or from another custom entry as is the case in
+
+.. coqtop:: in
+
+ Notation "[ e ]" := e (e custom expr at level 2).
+
+to indicate that ``e`` has to be parsed at level ``2`` of the grammar
+associated to the custom entry ``expr``. The level can be omitted, as in
+
+.. coqtop:: in
+
+ Notation "[ e ]" := e (e custom expr)`.
+
+in which case Coq tries to infer it.
+
+In the absence of an explicit entry for parsing or printing a
+sub-expression of a notation in a custom entry, the default is to
+consider that this sub-expression is parsed or printed in the same
+custom entry where the notation is defined. In particular, if ``x at
+level n`` is used for a sub-expression of a notation defined in custom
+entry ``foo``, it shall be understood the same as ``x custom foo at
+level n``.
+
+In general, rules are required to be *productive* on the right-hand
+side, i.e. that they are bound to an expression which is not
+reduced to a single variable. If the rule is not productive on the
+right-hand side, as it is the case above for
+
+.. coqtop:: in
+
+ Notation "( x )" := x (in custom expr at level 0, x at level 2).
+
+and
+
+.. coqtop:: in
+
+ Notation "{ x }" := x (in custom expr at level 0, x constr).
+
+it is used as a *grammar coercion* which means that it is used to parse or
+print an expression which is not available in the current grammar at the
+current level of parsing or printing for this grammar but which is available
+in another grammar or in another level of the current grammar. For instance,
+
+.. coqtop:: in
+
+ Notation "( x )" := x (in custom expr at level 0, x at level 2).
+
+tells that parentheses can be inserted to parse or print an expression
+declared at level ``2`` of ``expr`` whenever this expression is
+expected to be used as a subterm at level 0 or 1. This allows for
+instance to parse and print :g:`Add x y` as a subterm of :g:`Mul (Add
+x y) z` using the syntax ``(x + y) z``. Similarly,
+
+.. coqtop:: in
+
+ Notation "{ x }" := x (in custom expr at level 0, x constr).
+
+gives a way to let any arbitrary expression which is not handled by the
+custom entry ``expr`` be parsed or printed by the main grammar of term
+up to the insertion of a pair of curly brackets.
+
+.. cmd:: Print Grammar @ident.
+
+ This displays the state of the grammar for terms and grammar for
+ patterns associated to the custom entry :token:`ident`.
+
Summary
~~~~~~~
-**Syntax of notations**
+.. _NotationSyntax:
+
+Syntax of notations
++++++++++++++++++++
-The different syntactic variants of the command Notation are given on the
-following figure. The optional :token:`scope` is described in the Section 12.2.
+The different syntactic forms taken by the commands declaring
+notations are given below. The optional :production:`scope` is described in
+:ref:`Scopes`.
.. productionlist:: coq
notation : [Local] Notation `string` := `term` [`modifiers`] [: `scope`].
@@ -703,33 +868,44 @@ following figure. The optional :token:`scope` is described in the Section 12.2.
: | CoInductive `ind_body` [`decl_notation`] with … with `ind_body` [`decl_notation`].
: | Fixpoint `fix_body` [`decl_notation`] with … with `fix_body` [`decl_notation`].
: | CoFixpoint `cofix_body` [`decl_notation`] with … with `cofix_body` [`decl_notation`].
+ : | [Local] Declare Custom Entry `ident`.
decl_notation : [where `string` := `term` [: `scope`] and … and `string` := `term` [: `scope`]].
- modifiers : at level `natural`
- : | `ident` , … , `ident` at level `natural` [`binderinterp`]
+ modifiers : at level `num`
+ : in custom `ident`
+ : in custom `ident` at level `num`
+ : | `ident` , … , `ident` at level `num` [`binderinterp`]
: | `ident` , … , `ident` at next level [`binderinterp`]
- : | `ident` ident
- : | `ident` global
- : | `ident` bigint
- : | `ident` [strict] pattern [at level `natural`]
- : | `ident` binder
- : | `ident` closed binder
+ : | `ident` `explicit_subentry`
: | left associativity
: | right associativity
: | no associativity
: | only parsing
: | only printing
: | format `string`
+ explicit_subentry : ident
+ : | global
+ : | bigint
+ : | [strict] pattern [at level `num`]
+ : | binder
+ : | closed binder
+ : | constr [`binderinterp`]
+ : | constr at level `num` [`binderinterp`]
+ : | constr at next level [`binderinterp`]
+ : | custom [`binderinterp`]
+ : | custom at level `num` [`binderinterp`]
+ : | custom at next level [`binderinterp`]
binderinterp : as ident
: | as pattern
: | as strict pattern
.. note:: No typing of the denoted expression is performed at definition
- time. Type-checking is done only at the time of use of the notation.
+ time. Type checking is done only at the time of use of the notation.
-.. note:: Many examples of Notation may be found in the files composing
+.. note:: Some examples of Notation may be found in the files composing
the initial state of Coq (see directory :file:`$COQLIB/theories/Init`).
-.. note:: The notation ``"{ x }"`` has a special status in such a way that
+.. note:: The notation ``"{ x }"`` has a special status in the main grammars of
+ terms and patterns so that
complex notations of the form ``"x + { y }"`` or ``"x * { y }"`` can be
nested with correct precedences. Especially, every notation involving
a pattern of the form ``"{ x }"`` is parsed as a notation where the
@@ -743,14 +919,20 @@ following figure. The optional :token:`scope` is described in the Section 12.2.
given to some notation, say ``"{ y } & { z }"`` in fact applies to the
underlying ``"{ x }"``\-free rule which is ``"y & z"``).
-**Persistence of notations**
+Persistence of notations
+++++++++++++++++++++++++
-Notations do not survive the end of sections.
+Notations disappear when a section is closed.
.. cmd:: Local Notation @notation
Notations survive modules unless the command ``Local Notation`` is used instead
- of ``Notation``.
+ of :cmd:`Notation`.
+
+.. cmd:: Local Declare Custom Entry @ident
+
+ Custom entries survive modules unless the command ``Local Declare
+ Custom Entry`` is used instead of :cmd:`Declare Custom Entry`.
.. _Scopes:
@@ -758,20 +940,20 @@ Interpretation scopes
----------------------
An *interpretation scope* is a set of notations for terms with their
-interpretation. Interpretation scopes provide a weak, purely
-syntactical form of notations overloading: the same notation, for
-instance the infix symbol ``+`` can be used to denote distinct
+interpretations. Interpretation scopes provide a weak, purely
+syntactical form of notation overloading: the same notation, for
+instance the infix symbol ``+``, can be used to denote distinct
definitions of the additive operator. Depending on which interpretation
-scopes is currently open, the interpretation is different.
+scopes are currently open, the interpretation is different.
Interpretation scopes can include an interpretation for numerals and
strings. However, this is only made possible at the Objective Caml
level.
-See Figure 12.1 for the syntax of notations including the possibility
-to declare them in a given scope. Here is a typical example which
+See :ref:`above <NotationSyntax>` for the syntax of notations including the
+possibility to declare them in a given scope. Here is a typical example which
declares the notation for conjunction in the scope ``type_scope``.
-.. coqdoc::
+.. coqtop:: in
Notation "A /\ B" := (and A B) : type_scope.
@@ -781,10 +963,10 @@ declares the notation for conjunction in the scope ``type_scope``.
Global interpretation rules for notations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-At any time, the interpretation of a notation for term is done within
+At any time, the interpretation of a notation for a term is done within
a *stack* of interpretation scopes and lonely notations. In case a
notation has several interpretations, the actual interpretation is the
-one defined by (or in) the more recently declared (or open) lonely
+one defined by (or in) the more recently declared (or opened) lonely
notation (or interpretation scope) which defines this notation.
Typically if a given notation is defined in some scope ``scope`` but has
also an interpretation not assigned to a scope, then, if ``scope`` is open
@@ -810,7 +992,7 @@ lonely notations. These scopes, in opening order, are ``core_scope``,
stack by using the command :n:`Close Scope @scope`.
Notice that this command does not only cancel the last :n:`Open Scope @scope`
- but all the invocations of it.
+ but all its invocations.
.. note:: ``Open Scope`` and ``Close Scope`` do not survive the end of sections
where they occur. When defined outside of a section, they are exported
@@ -890,29 +1072,29 @@ Binding arguments of a constant to an interpretation scope
the scope is limited to the argument itself. It does not propagate to
subterms but the subterms that, after interpretation of the notation,
turn to be themselves arguments of a reference are interpreted
- accordingly to the arguments scopes bound to this reference.
+ accordingly to the argument scopes bound to this reference.
-.. cmdv:: Arguments @qualid : clear scopes
+ .. cmdv:: Arguments @qualid : clear scopes
- Arguments scopes can be cleared with :n:`Arguments @qualid : clear scopes`.
+ This command can be used to clear argument scopes of :token:`qualid`.
-.. cmdv:: Arguments @qualid {+ @name%scope} : extra scopes
+ .. cmdv:: Arguments @qualid {+ @name%scope} : extra scopes
- Defines extra argument scopes, to be used in case of coercion to Funclass
- (see Chapter :ref:`implicitcoercions`) or with a computed type.
+ Defines extra argument scopes, to be used in case of coercion to ``Funclass``
+ (see the :ref:`implicitcoercions` chapter) or with a computed type.
-.. cmdv:: Global Arguments @qualid {+ @name%@scope}
+ .. cmdv:: Global Arguments @qualid {+ @name%@scope}
- This behaves like :n:`Arguments qualid {+ @name%@scope}` but survives when a
- section is closed instead of stopping working at section closing. Without the
- ``Global`` modifier, the effect of the command stops when the section it belongs
- to ends.
+ This behaves like :n:`Arguments qualid {+ @name%@scope}` but survives when a
+ section is closed instead of stopping working at section closing. Without the
+ ``Global`` modifier, the effect of the command stops when the section it belongs
+ to ends.
-.. cmdv:: Local Arguments @qualid {+ @name%@scope}
+ .. cmdv:: Local Arguments @qualid {+ @name%@scope}
- This behaves like :n:`Arguments @qualid {+ @name%@scope}` but does not
- survive modules and files. Without the ``Local`` modifier, the effect of the
- command is visible from within other modules or files.
+ This behaves like :n:`Arguments @qualid {+ @name%@scope}` but does not
+ survive modules and files. Without the ``Local`` modifier, the effect of the
+ command is visible from within other modules or files.
.. seealso::
@@ -947,18 +1129,18 @@ Binding types of arguments to an interpretation scope
When an interpretation scope is naturally associated to a type (e.g. the
scope of operations on the natural numbers), it may be convenient to bind it
- to this type. When a scope ``scope`` is bound to a type type, any new function
- defined later on gets its arguments of type type interpreted by default in
+ to this type. When a scope ``scope`` is bound to a type ``type``, any new function
+ defined later on gets its arguments of type ``type`` interpreted by default in
scope scope (this default behavior can however be overwritten by explicitly
- using the command ``Arguments``).
+ using the command :cmd:`Arguments`).
Whether the argument of a function has some type ``type`` is determined
- statically. For instance, if f is a polymorphic function of type :g:`forall
- X:Type, X -> X` and type :g:`t` is bound to a scope ``scope``, then :g:`a` of
- type :g:`t` in :g:`f t a` is not recognized as an argument to be interpreted
- in scope ``scope``.
+ statically. For instance, if ``f`` is a polymorphic function of type
+ :g:`forall X:Type, X -> X` and type :g:`t` is bound to a scope ``scope``,
+ then :g:`a` of type :g:`t` in :g:`f t a` is not recognized as an argument to
+ be interpreted in scope ``scope``.
- More generally, any coercion :n:`@class` (see Chapter :ref:`implicitcoercions`)
+ More generally, any coercion :n:`@class` (see the :ref:`implicitcoercions` chapter)
can be bound to an interpretation scope. The command to do it is
:n:`Bind Scope @scope with @class`
@@ -980,12 +1162,6 @@ Binding types of arguments to an interpretation scope
.. note:: The scopes ``type_scope`` and ``function_scope`` also have a local
effect on interpretation. See the next section.
-.. seealso::
-
- :cmd:`About`
- The command to show the scopes bound to the arguments of a
- function is described in Section 2.
-
The ``type_scope`` interpretation scope
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -996,7 +1172,7 @@ scope which is temporarily activated each time a subterm of an expression is
expected to be a type. It is delimited by the key ``type``, and bound to the
coercion class ``Sortclass``. It is also used in certain situations where an
expression is statically known to be a type, including the conclusion and the
-type of hypotheses within an Ltac goal match (see Section
+type of hypotheses within an Ltac goal match (see
:ref:`ltac-match-goal`), the statement of a theorem, the type of a definition,
the type of a binder, the domain and codomain of implication, the codomain of
products, and more generally any type argument of a declared or defined
@@ -1007,7 +1183,7 @@ The ``function_scope`` interpretation scope
.. index:: function_scope
-The scope ``function_scope`` also has a special status.
+The scope ``function_scope`` also has a special status.
It is temporarily activated each time the argument of a global reference is
recognized to be a ``Funclass`` istance, i.e., of type :g:`forall x:A, B` or
:g:`A -> B`.
@@ -1017,39 +1193,39 @@ Interpretation scopes used in the standard library of Coq
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We give an overview of the scopes used in the standard library of Coq.
-For a complete list of notations in each scope, use the commands Print
-Scopes or Print Scope scope.
+For a complete list of notations in each scope, use the commands :cmd:`Print
+Scopes` or :cmd:`Print Scope`.
``type_scope``
This scope includes infix * for product types and infix + for sum types. It
- is delimited by key ``type``, and bound to the coercion class
+ is delimited by the key ``type``, and bound to the coercion class
``Sortclass``, as described above.
``function_scope``
- This scope is delimited by key ``function``, and bound to the coercion class
+ This scope is delimited by the key ``function``, and bound to the coercion class
``Funclass``, as described above.
``nat_scope``
This scope includes the standard arithmetical operators and relations on type
nat. Positive numerals in this scope are mapped to their canonical
- representent built from :g:`O` and :g:`S`. The scope is delimited by key
+ representent built from :g:`O` and :g:`S`. The scope is delimited by the key
``nat``, and bound to the type :g:`nat` (see above).
``N_scope``
This scope includes the standard arithmetical operators and relations on
- type :g:`N` (binary natural numbers). It is delimited by key ``N`` and comes
+ type :g:`N` (binary natural numbers). It is delimited by the key ``N`` and comes
with an interpretation for numerals as closed terms of type :g:`N`.
``Z_scope``
This scope includes the standard arithmetical operators and relations on
- type :g:`Z` (binary integer numbers). It is delimited by key ``Z`` and comes
- with an interpretation for numerals as closed term of type :g:`Z`.
+ type :g:`Z` (binary integer numbers). It is delimited by the key ``Z`` and comes
+ with an interpretation for numerals as closed terms of type :g:`Z`.
``positive_scope``
This scope includes the standard arithmetical operators and relations on
type :g:`positive` (binary strictly positive numbers). It is delimited by
key ``positive`` and comes with an interpretation for numerals as closed
- term of type :g:`positive`.
+ terms of type :g:`positive`.
``Q_scope``
This scope includes the standard arithmetical operators and relations on
@@ -1066,25 +1242,25 @@ Scopes or Print Scope scope.
``real_scope``
This scope includes the standard arithmetical operators and relations on
- type :g:`R` (axiomatic real numbers). It is delimited by key ``R`` and comes
+ type :g:`R` (axiomatic real numbers). It is delimited by the key ``R`` and comes
with an interpretation for numerals using the :g:`IZR` morphism from binary
integer numbers to :g:`R`.
``bool_scope``
- This scope includes notations for the boolean operators. It is delimited by
+ This scope includes notations for the boolean operators. It is delimited by the
key ``bool``, and bound to the type :g:`bool` (see above).
``list_scope``
- This scope includes notations for the list operators. It is delimited by key
+ This scope includes notations for the list operators. It is delimited by the key
``list``, and bound to the type :g:`list` (see above).
``core_scope``
- This scope includes the notation for pairs. It is delimited by key ``core``.
+ This scope includes the notation for pairs. It is delimited by the key ``core``.
``string_scope``
This scope includes notation for strings as elements of the type string.
Special characters and escaping follow Coq conventions on strings (see
- Section 1.1). Especially, there is no convention to visualize non
+ :ref:`lexical-conventions`). Especially, there is no convention to visualize non
printable characters of a string. The file :file:`String.v` shows an example
that contains quotes, a newline and a beep (i.e. the ASCII character
of code 7).
@@ -1093,12 +1269,12 @@ Scopes or Print Scope scope.
This scope includes interpretation for all strings of the form ``"c"``
where :g:`c` is an ASCII character, or of the form ``"nnn"`` where nnn is
a three-digits number (possibly with leading 0's), or of the form
- ``""""``. Their respective denotations are the ASCII code of c, the
- decimal ASCII code nnn, or the ascii code of the character ``"`` (i.e.
+ ``""""``. Their respective denotations are the ASCII code of :g:`c`, the
+ decimal ASCII code ``nnn``, or the ascii code of the character ``"`` (i.e.
the ASCII code 34), all of them being represented in the type :g:`ascii`.
-Displaying informations about scopes
+Displaying information about scopes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. cmd:: Print Visibility
@@ -1106,28 +1282,29 @@ Displaying informations about scopes
This displays the current stack of notations in scopes and lonely
notations that is used to interpret a notation. The top of the stack
is displayed last. Notations in scopes whose interpretation is hidden
- by the same notation in a more recently open scope are not displayed.
+ by the same notation in a more recently opened scope are not displayed.
Hence each notation is displayed only once.
-.. cmdv:: Print Visibility scope
-
- This displays the current stack of notations in scopes and lonely
- notations assuming that scope is pushed on top of the stack. This is
- useful to know how a subterm locally occurring in the scope ofscope is
- interpreted.
+ .. cmdv:: Print Visibility @scope
-.. cmdv:: Print Scope scope
+ This displays the current stack of notations in scopes and lonely
+ notations assuming that :token:`scope` is pushed on top of the stack. This is
+ useful to know how a subterm locally occurring in the scope :token:`scope` is
+ interpreted.
- This displays all the notations defined in interpretation scopescope.
- It also displays the delimiting key if any and the class to which the
- scope is bound, if any.
-
-.. cmdv:: Print Scopes
+.. cmd:: Print Scopes
This displays all the notations, delimiting keys and corresponding
- class of all the existing interpretation scopes. It also displays the
+ classes of all the existing interpretation scopes. It also displays the
lonely notations.
+ .. cmdv:: Print Scope @scope
+ :name: Print Scope
+
+ This displays all the notations defined in the interpretation scope :token:`scope`.
+ It also displays the delimiting key if any and the class to which the
+ scope is bound, if any.
+
.. _Abbreviations:
Abbreviations
@@ -1166,13 +1343,13 @@ Abbreviations
much as possible by the Coq printers unless the modifier ``(only
parsing)`` is given.
- Abbreviations are bound to an absolute name as an ordinary definition
- is, and they can be referred by qualified names too.
+ An abbreviation is bound to an absolute name as an ordinary definition is
+ and it also can be referred to by a qualified name.
Abbreviations are syntactic in the sense that they are bound to
expressions which are not typed at the time of the definition of the
- abbreviation but at the time it is used. Especially, abbreviations can
- be bound to terms with holes (i.e. with “``_``”). For example:
+ abbreviation but at the time they are used. Especially, abbreviations
+ can be bound to terms with holes (i.e. with “``_``”). For example:
.. coqtop:: none reset
@@ -1182,14 +1359,17 @@ Abbreviations
.. coqtop:: in
Definition explicit_id (A:Set) (a:A) := a.
+
+ .. coqtop:: in
+
Notation id := (explicit_id _).
.. coqtop:: all
Check (id 0).
- Abbreviations do not survive the end of sections. No typing of the
- denoted expression is performed at definition time. Type-checking is
+ Abbreviations disappear when a section is closed. No typing of the
+ denoted expression is performed at definition time. Type checking is
done only at the time of use of the abbreviation.
.. _TacticNotation:
@@ -1197,13 +1377,12 @@ Abbreviations
Tactic Notations
-----------------
-Tactic notations allow to customize the syntax of the tactics of the
-tactic language. Tactic notations obey the following syntax:
+Tactic notations allow to customize the syntax of tactics. They have the following syntax:
.. productionlist:: coq
tacn : Tactic Notation [`tactic_level`] [`prod_item` … `prod_item`] := `tactic`.
prod_item : `string` | `tactic_argument_type`(`ident`)
- tactic_level : (at level `natural`)
+ tactic_level : (at level `num`)
tactic_argument_type : ident | simple_intropattern | reference
: | hyp | hyp_list | ne_hyp_list
: | constr | uconstr | constr_list | ne_constr_list
@@ -1220,7 +1399,7 @@ tactic language. Tactic notations obey the following syntax:
a terminal symbol, i.e. a string, for the first production item. The
tactic level indicates the parsing precedence of the tactic notation.
This information is particularly relevant for notations of tacticals.
- Levels 0 to 5 are available (default is 0).
+ Levels 0 to 5 are available (default is 5).
.. cmd:: Print Grammar tactic
@@ -1247,12 +1426,12 @@ tactic language. Tactic notations obey the following syntax:
* - ``simple_intropattern``
- intro_pattern
- - an intro_pattern
+ - an intro pattern
- intros
* - ``hyp``
- identifier
- - an hypothesis defined in context
+ - a hypothesis defined in context
- clear
* - ``reference``
@@ -1301,7 +1480,7 @@ tactic language. Tactic notations obey the following syntax:
-
.. note:: In order to be bound in tactic definitions, each syntactic
- entry for argument type must include the case of simple L tac
+ entry for argument type must include the case of a simple |Ltac|
identifier as part of what it parses. This is naturally the case for
``ident``, ``simple_intropattern``, ``reference``, ``constr``, ... but not for ``integer``.
This is the reason for introducing a special entry ``int_or_var`` which
@@ -1315,16 +1494,16 @@ tactic language. Tactic notations obey the following syntax:
.. cmdv:: Local Tactic Notation
- Tactic notations do not survive the end of sections. They survive
- modules unless the command Local Tactic Notation is used instead of
- Tactic Notation.
+ Tactic notations disappear when a section is closed. They survive when
+ a module is closed unless the command ``Local Tactic Notation`` is used instead
+ of :cmd:`Tactic Notation`.
.. rubric:: Footnotes
.. [#and_or_levels] which are the levels effectively chosen in the current
implementation of Coq
-.. [#no_associativity] Coq accepts notations declared as no associative but the parser on
- which Coq is built, namely Camlp4, currently does not implement the
- no-associativity and replaces it by a left associativity; hence it is
- the same for Coq: no-associativity is in fact left associativity
+.. [#no_associativity] Coq accepts notations declared as nonassociative but the parser on
+ which Coq is built, namely Camlp5, currently does not implement ``no associativity`` and
+ replaces it with ``left associativity``; hence it is the same for Coq: ``no associativity``
+ is in fact ``left associativity`` for the purposes of parsing
diff --git a/doc/stdlib/index-list.html.template b/doc/stdlib/index-list.html.template
index 8c09b23a5a..f448248468 100644
--- a/doc/stdlib/index-list.html.template
+++ b/doc/stdlib/index-list.html.template
@@ -498,6 +498,9 @@ through the <tt>Require Import</tt> command.</p>
<dd>
theories/Strings/Ascii.v
theories/Strings/String.v
+ theories/Strings/BinaryString.v
+ theories/Strings/HexString.v
+ theories/Strings/OctalString.v
</dd>
<dt> <b>Reals</b>:
diff --git a/doc/tools/coqrst/coqdomain.py b/doc/tools/coqrst/coqdomain.py
index c9487abf03..40554c3ca3 100644
--- a/doc/tools/coqrst/coqdomain.py
+++ b/doc/tools/coqrst/coqdomain.py
@@ -123,7 +123,13 @@ class CoqObject(ObjectDescription):
"""
self._render_annotation(signode)
self._render_signature(signature, signode)
- return self._names.get(signature) or self._name_from_signature(signature)
+ name = self._names.get(signature)
+ if name is None:
+ name = self._name_from_signature(signature)
+ # remove trailing ‘.’ found in commands, but not ‘...’ (ellipsis)
+ if name is not None and name.endswith(".") and not name.endswith("..."):
+ name = name[:-1]
+ return name
def _warn_if_duplicate_name(self, objects, name):
"""Check that two objects in the same domain don't have the same name."""
@@ -157,18 +163,17 @@ class CoqObject(ObjectDescription):
def _add_index_entry(self, name, target):
"""Add `name` (pointing to `target`) to the main index."""
- index_text = name
- if self.index_suffix:
- index_text += " " + self.index_suffix
- self.indexnode['entries'].append(('single', index_text, target, '', None))
+ assert isinstance(name, str)
+ if not name.startswith("_"):
+ index_text = name
+ if self.index_suffix:
+ index_text += " " + self.index_suffix
+ self.indexnode['entries'].append(('single', index_text, target, '', None))
def add_target_and_index(self, name, _, signode):
"""Attach a link target to `signode` and an index entry for `name`."""
if name:
target = self._add_target(signode, name)
- # remove trailing . , found in commands, but not ... (ellipsis)
- if name[-1] == "." and not name[-3:] == "..." :
- name = name[0:-1]
self._add_index_entry(name, target)
return target
@@ -449,7 +454,7 @@ def NotationRole(role, rawtext, text, lineno, inliner, options={}, content=[]):
it names the introduced hypothesis :token:`ident`.
Note that this example also uses ``:token:``. That's because ``ident`` is
- defined in the the Coq manual as a grammar production, and ``:token:``
+ defined in the Coq manual as a grammar production, and ``:token:``
creates a link to that. When referring to a placeholder that happens to be
a grammar production, ``:token:`…``` is typically preferable to ``:n:`@…```.
"""
@@ -571,6 +576,9 @@ class ExampleDirective(BaseAdmonition):
http://docutils.sourceforge.net/docs/ref/rst/directives.html#generic-admonition
for more details.
+ Optionally, any text immediately following the ``.. example::`` header is
+ used as the example's title.
+
Example::
.. example:: Adding a hint to a database
@@ -583,13 +591,14 @@ class ExampleDirective(BaseAdmonition):
"""
node_class = nodes.admonition
directive_name = "example"
+ optional_arguments = 1
def run(self):
# ‘BaseAdmonition’ checks whether ‘node_class’ is ‘nodes.admonition’,
# and uses arguments[0] as the title in that case (in other cases, the
# title is unset, and it is instead set in the HTML visitor).
- assert not self.arguments # Arguments have been parsed as content
- self.arguments = ['Example']
+ assert len(self.arguments) <= 1
+ self.arguments = [": ".join(['Example'] + self.arguments)]
self.options['classes'] = ['admonition', 'note']
return super().run()
diff --git a/engine/eConstr.ml b/engine/eConstr.ml
index 6810626ad3..3dc1933a14 100644
--- a/engine/eConstr.ml
+++ b/engine/eConstr.ml
@@ -565,9 +565,8 @@ let compare_head_gen_proj env sigma equ eqs eqc' nargs m n =
| App (f, args), Proj (p, c) ->
(match kind_upto sigma f with
| Const (p', u) when Constant.equal (Projection.constant p) p' ->
- let pb = Environ.lookup_projection p env in
- let npars = pb.Declarations.proj_npars in
- if Array.length args == npars + 1 then
+ let npars = Projection.npars p in
+ if Array.length args == npars + 1 then
eqc' 0 c args.(npars)
else false
| _ -> false)
@@ -592,25 +591,14 @@ let eq_constr_universes_proj env sigma m n =
let res = eq_constr' 0 (unsafe_to_constr m) (unsafe_to_constr n) in
if res then Some !cstrs else None
-let universes_of_constr env sigma c =
+let universes_of_constr sigma c =
let open Univ in
- let open Declarations in
let rec aux s c =
match kind sigma c with
| Const (c, u) ->
- begin match (Environ.lookup_constant c env).const_universes with
- | Polymorphic_const _ ->
LSet.fold LSet.add (Instance.levels (EInstance.kind sigma u)) s
- | Monomorphic_const (univs, _) ->
- LSet.union s univs
- end
| Ind ((mind,_), u) | Construct (((mind,_),_), u) ->
- begin match (Environ.lookup_mind mind env).mind_universes with
- | Cumulative_ind _ | Polymorphic_ind _ ->
LSet.fold LSet.add (Instance.levels (EInstance.kind sigma u)) s
- | Monomorphic_ind (univs,_) ->
- LSet.union s univs
- end
| Sort u ->
let sort = ESorts.kind sigma u in
if Sorts.is_small sort then s
diff --git a/engine/eConstr.mli b/engine/eConstr.mli
index e9d3e782bc..ecb36615f3 100644
--- a/engine/eConstr.mli
+++ b/engine/eConstr.mli
@@ -232,7 +232,7 @@ val fold : Evd.evar_map -> ('a -> t -> 'a) -> 'a -> t -> 'a
(** Gather the universes transitively used in the term, including in the
type of evars appearing in it. *)
-val universes_of_constr : Environ.env -> Evd.evar_map -> t -> Univ.LSet.t
+val universes_of_constr : Evd.evar_map -> t -> Univ.LSet.t
(** {6 Substitutions} *)
@@ -321,7 +321,7 @@ sig
val to_named_decl : (t, types) Context.Named.Declaration.pt -> (Constr.t, Constr.types) Context.Named.Declaration.pt
(** Physical identity. Does not care for defined evars. *)
- val to_named_context : (t, types) Context.Named.pt -> Context.Named.t
+ val to_named_context : (t, types) Context.Named.pt -> Constr.named_context
val to_sorts : ESorts.t -> Sorts.t
(** Physical identity. Does not care for normalization. *)
diff --git a/engine/evar_kinds.ml b/engine/evar_kinds.ml
index 12e2fda8e2..ea1e572548 100644
--- a/engine/evar_kinds.ml
+++ b/engine/evar_kinds.ml
@@ -21,12 +21,27 @@ type matching_var_kind = FirstOrderPatVar of Id.t | SecondOrderPatVar of Id.t
type subevar_kind = Domain | Codomain | Body
+(* maybe this should be a Projection.t *)
+type record_field = { fieldname : Constant.t; recordname : Names.inductive }
+
+type question_mark = {
+ qm_obligation: obligation_definition_status;
+ qm_name: Name.t;
+ qm_record_field: record_field option;
+}
+
+let default_question_mark = {
+ qm_obligation=Define true;
+ qm_name=Anonymous;
+ qm_record_field=None;
+}
+
type t =
| ImplicitArg of GlobRef.t * (int * Id.t option)
* bool (** Force inference *)
| BinderType of Name.t
| NamedHole of Id.t (* coming from some ?[id] syntax *)
- | QuestionMark of obligation_definition_status * Name.t
+ | QuestionMark of question_mark
| CasesType of bool (* true = a subterm of the type *)
| InternalHole
| TomatchTypeParameter of inductive * int
diff --git a/engine/evar_kinds.mli b/engine/evar_kinds.mli
new file mode 100644
index 0000000000..4facdb2005
--- /dev/null
+++ b/engine/evar_kinds.mli
@@ -0,0 +1,51 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+open Names
+
+(** The kinds of existential variable *)
+
+(** Should the obligation be defined (opaque or transparent (default)) or
+ defined transparent and expanded in the term? *)
+
+type obligation_definition_status = Define of bool | Expand
+
+type matching_var_kind = FirstOrderPatVar of Id.t | SecondOrderPatVar of Id.t
+
+type subevar_kind = Domain | Codomain | Body
+
+(* maybe this should be a Projection.t *)
+(* Represents missing record field *)
+type record_field = { fieldname : Constant.t; recordname : Names.inductive }
+
+type question_mark = {
+ qm_obligation: obligation_definition_status;
+ qm_name: Name.t;
+ (* Tracks if the evar represents a missing record field *)
+ qm_record_field: record_field option;
+}
+
+(* Default value of question_mark which is used most often *)
+val default_question_mark : question_mark
+
+type t =
+ | ImplicitArg of GlobRef.t * (int * Id.t option)
+ * bool (** Force inference *)
+ | BinderType of Name.t
+ | NamedHole of Id.t (* coming from some ?[id] syntax *)
+ | QuestionMark of question_mark
+ | CasesType of bool (* true = a subterm of the type *)
+ | InternalHole
+ | TomatchTypeParameter of inductive * int
+ | GoalEvar
+ | ImpossibleCase
+ | MatchingVar of matching_var_kind
+ | VarInstance of Id.t
+ | SubEvar of subevar_kind option * Evar.t
diff --git a/engine/evarutil.ml b/engine/evarutil.ml
index 1625f6fc81..b77bf55d8d 100644
--- a/engine/evarutil.ml
+++ b/engine/evarutil.ml
@@ -426,10 +426,6 @@ let push_rel_context_to_named_context ?hypnaming env sigma typ =
let default_source = Loc.tag @@ Evar_kinds.InternalHole
-let restrict_evar evd evk filter ?src candidates =
- let evd, evk' = Evd.restrict evk filter ?candidates ?src evd in
- Evd.declare_future_goal evk' evd, evk'
-
let new_pure_evar_full evd evi =
let (evd, evk) = Evd.new_evar evd evi in
let evd = Evd.declare_future_goal evk evd in
@@ -499,12 +495,12 @@ let e_new_type_evar env evdref ?src ?filter ?naming ?principal ?hypnaming rigid
evdref := evd;
c
-let new_Type ?(rigid=Evd.univ_flexible) env evd =
+let new_Type ?(rigid=Evd.univ_flexible) evd =
let open EConstr in
let (evd, s) = new_sort_variable rigid evd in
(evd, mkSort s)
-let e_new_Type ?(rigid=Evd.univ_flexible) env evdref =
+let e_new_Type ?(rigid=Evd.univ_flexible) evdref =
let evd', s = new_sort_variable rigid !evdref in
evdref := evd'; EConstr.mkSort s
@@ -547,11 +543,33 @@ let generalize_evar_over_rels sigma (ev,args) =
type clear_dependency_error =
| OccurHypInSimpleClause of Id.t option
| EvarTypingBreak of existential
+| NoCandidatesLeft of Evar.t
exception ClearDependencyError of Id.t * clear_dependency_error * GlobRef.t option
exception Depends of Id.t
+let set_of_evctx l =
+ List.fold_left (fun s decl -> Id.Set.add (NamedDecl.get_id decl) s) Id.Set.empty l
+
+let filter_effective_candidates evd evi filter candidates =
+ let ids = set_of_evctx (Filter.filter_list filter (evar_context evi)) in
+ List.filter (fun a -> Id.Set.subset (collect_vars evd a) ids) candidates
+
+let restrict_evar evd evk filter ?src candidates =
+ let evar_info = Evd.find_undefined evd evk in
+ let candidates = Option.map (filter_effective_candidates evd evar_info filter) candidates in
+ match candidates with
+ | Some [] -> raise (ClearDependencyError (*FIXME*)(Id.of_string "blah", (NoCandidatesLeft evk), None))
+ | _ ->
+ let evd, evk' = Evd.restrict evk filter ?candidates ?src evd in
+ (** Mark new evar as future goal, removing previous one,
+ circumventing Proofview.advance but making Proof.run_tactic catch these. *)
+ let future_goals = Evd.save_future_goals evd in
+ let future_goals = Evd.filter_future_goals (fun evk' -> not (Evar.equal evk evk')) future_goals in
+ let evd = Evd.restore_future_goals evd future_goals in
+ (Evd.declare_future_goal evk' evd, evk')
+
let rec check_and_clear_in_constr env evdref err ids global c =
(* returns a new constr where all the evars have been 'cleaned'
(ie the hypotheses ids have been removed from the contexts of
@@ -621,7 +639,9 @@ let rec check_and_clear_in_constr env evdref err ids global c =
let origfilter = Evd.evar_filter evi in
let filter = Evd.Filter.apply_subfilter origfilter filter in
let evd = !evdref in
- let (evd,_) = restrict_evar evd evk filter None in
+ let candidates = Evd.evar_candidates evi in
+ let candidates = Option.map (List.map EConstr.of_constr) candidates in
+ let (evd,_) = restrict_evar evd evk filter candidates in
evdref := evd;
Evd.existential_value0 !evdref ev
diff --git a/engine/evarutil.mli b/engine/evarutil.mli
index db638be9e2..0ad323ac4b 100644
--- a/engine/evarutil.mli
+++ b/engine/evarutil.mli
@@ -63,10 +63,7 @@ val new_type_evar :
env -> evar_map -> rigid ->
evar_map * (constr * Sorts.t)
-val new_Type : ?rigid:rigid -> env -> evar_map -> evar_map * constr
-
-val restrict_evar : evar_map -> Evar.t -> Filter.t ->
- ?src:Evar_kinds.t Loc.located -> constr list option -> evar_map * Evar.t
+val new_Type : ?rigid:rigid -> evar_map -> evar_map * constr
(** Polymorphic constants *)
@@ -131,7 +128,7 @@ val advance : evar_map -> Evar.t -> Evar.t option
[nf_evar]. *)
val undefined_evars_of_term : evar_map -> constr -> Evar.Set.t
-val undefined_evars_of_named_context : evar_map -> Context.Named.t -> Evar.Set.t
+val undefined_evars_of_named_context : evar_map -> Constr.named_context -> Evar.Set.t
val undefined_evars_of_evar_info : evar_map -> evar_info -> Evar.Set.t
type undefined_evars_cache
@@ -164,7 +161,7 @@ val jv_nf_evar :
val tj_nf_evar :
evar_map -> unsafe_type_judgment -> unsafe_type_judgment
-val nf_named_context_evar : evar_map -> Context.Named.t -> Context.Named.t
+val nf_named_context_evar : evar_map -> Constr.named_context -> Constr.named_context
val nf_rel_context_evar : evar_map -> rel_context -> rel_context
val nf_env_evar : evar_map -> env -> env
@@ -231,9 +228,18 @@ raise OccurHypInSimpleClause if the removal breaks dependencies *)
type clear_dependency_error =
| OccurHypInSimpleClause of Id.t option
| EvarTypingBreak of Constr.existential
+| NoCandidatesLeft of Evar.t
exception ClearDependencyError of Id.t * clear_dependency_error * GlobRef.t option
+(** Restrict an undefined evar according to a (sub)filter and candidates.
+ The evar will be defined if there is only one candidate left,
+@raise ClearDependencyError NoCandidatesLeft if the filter turns the candidates
+ into an empty list. *)
+
+val restrict_evar : evar_map -> Evar.t -> Filter.t ->
+ ?src:Evar_kinds.t Loc.located -> constr list option -> evar_map * Evar.t
+
val clear_hyps_in_evi : env -> evar_map -> named_context_val -> types ->
Id.Set.t -> evar_map * named_context_val * types
@@ -281,7 +287,7 @@ val e_new_type_evar : env -> evar_map ref ->
?principal:bool -> ?hypnaming:naming_mode -> rigid -> constr * Sorts.t
[@@ocaml.deprecated "Use [Evarutil.new_type_evar]"]
-val e_new_Type : ?rigid:rigid -> env -> evar_map ref -> constr
+val e_new_Type : ?rigid:rigid -> evar_map ref -> constr
[@@ocaml.deprecated "Use [Evarutil.new_Type]"]
val e_new_global : evar_map ref -> GlobRef.t -> constr
diff --git a/engine/evd.ml b/engine/evd.ml
index 714a0b645d..d1c7fef738 100644
--- a/engine/evd.ml
+++ b/engine/evd.ml
@@ -171,6 +171,8 @@ let evar_context evi = named_context_of_val evi.evar_hyps
let evar_filtered_context evi =
Filter.filter_list (evar_filter evi) (evar_context evi)
+let evar_candidates evi = evi.evar_candidates
+
let evar_hyps evi = evi.evar_hyps
let evar_filtered_hyps evi = match Filter.repr (evar_filter evi) with
@@ -620,6 +622,7 @@ let merge_universe_context evd uctx' =
let set_universe_context evd uctx' =
{ evd with universes = uctx' }
+(* TODO: make unique *)
let add_conv_pb ?(tail=false) pb d =
if tail then {d with conv_pbs = d.conv_pbs @ [pb]}
else {d with conv_pbs = pb::d.conv_pbs}
@@ -802,8 +805,8 @@ let make_flexible_variable evd ~algebraic u =
(* Operations on constants *)
(****************************************)
-let fresh_sort_in_family ?loc ?(rigid=univ_flexible) env evd s =
- with_context_set ?loc rigid evd (UnivGen.fresh_sort_in_family env s)
+let fresh_sort_in_family ?loc ?(rigid=univ_flexible) evd s =
+ with_context_set ?loc rigid evd (UnivGen.fresh_sort_in_family s)
let fresh_constant_instance ?loc env evd c =
with_context_set ?loc univ_flexible evd (UnivGen.fresh_constant_instance env c)
@@ -817,8 +820,6 @@ let fresh_constructor_instance ?loc env evd c =
let fresh_global ?loc ?(rigid=univ_flexible) ?names env evd gr =
with_context_set ?loc rigid evd (UnivGen.fresh_global_instance ?names env gr)
-let whd_sort_variable evd t = t
-
let is_sort_variable evd s = UState.is_sort_variable evd.universes s
let is_flexible_level evd l =
@@ -852,7 +853,7 @@ let normalize_universe_instance evd l =
let normalize_sort evars s =
match s with
- | Prop _ -> s
+ | Prop | Set -> s
| Type u ->
let u' = normalize_universe evars u in
if u' == u then s else Type u'
diff --git a/engine/evd.mli b/engine/evd.mli
index d166fd8048..db2bd4eedf 100644
--- a/engine/evd.mli
+++ b/engine/evd.mli
@@ -113,6 +113,7 @@ val evar_filtered_context : evar_info -> (econstr, etypes) Context.Named.pt
val evar_hyps : evar_info -> named_context_val
val evar_filtered_hyps : evar_info -> named_context_val
val evar_body : evar_info -> evar_body
+val evar_candidates : evar_info -> constr list option
val evar_filter : evar_info -> Filter.t
val evar_env : evar_info -> env
val evar_filtered_env : evar_info -> env
@@ -229,7 +230,7 @@ val existential_opt_value : evar_map -> econstr pexistential -> econstr option
val existential_opt_value0 : evar_map -> existential -> constr option
-val evar_instance_array : (Context.Named.Declaration.t -> 'a -> bool) -> evar_info ->
+val evar_instance_array : (Constr.named_declaration -> 'a -> bool) -> evar_info ->
'a array -> (Id.t * 'a) list
val instantiate_evar_array : evar_info -> econstr -> econstr array -> econstr
@@ -243,7 +244,8 @@ val evars_reset_evd : ?with_conv_pbs:bool -> ?with_univs:bool ->
val restrict : Evar.t-> Filter.t -> ?candidates:econstr list ->
?src:Evar_kinds.t located -> evar_map -> evar_map * Evar.t
(** Restrict an undefined evar into a new evar by filtering context and
- possibly limiting the instances to a set of candidates *)
+ possibly limiting the instances to a set of candidates (candidates
+ are filtered according to the filter) *)
val is_restricted_evar : evar_info -> Evar.t option
(** Tell if an evar comes from restriction of another evar, and if yes, which *)
@@ -338,8 +340,6 @@ val shelve_on_future_goals : Evar.t list -> future_goals -> future_goals
Evar maps also keep track of the universe constraints defined at a given
point. This section defines the relevant manipulation functions. *)
-val whd_sort_variable : evar_map -> econstr -> econstr
-
exception UniversesDiffer
val add_universe_constraints : evar_map -> UnivProblem.Set.t -> evar_map
@@ -596,7 +596,7 @@ val update_sigma_env : evar_map -> env -> evar_map
(** Polymorphic universes *)
-val fresh_sort_in_family : ?loc:Loc.t -> ?rigid:rigid -> env -> evar_map -> Sorts.family -> evar_map * Sorts.t
+val fresh_sort_in_family : ?loc:Loc.t -> ?rigid:rigid -> evar_map -> Sorts.family -> evar_map * Sorts.t
val fresh_constant_instance : ?loc:Loc.t -> env -> evar_map -> Constant.t -> evar_map * pconstant
val fresh_inductive_instance : ?loc:Loc.t -> env -> evar_map -> inductive -> evar_map * pinductive
val fresh_constructor_instance : ?loc:Loc.t -> env -> evar_map -> constructor -> evar_map * pconstructor
diff --git a/engine/namegen.ml b/engine/namegen.ml
index 23c6911396..978f33b683 100644
--- a/engine/namegen.ml
+++ b/engine/namegen.ml
@@ -137,8 +137,9 @@ let lowercase_first_char id = (* First character of a constr *)
s ^ Unicode.lowercase_first_char s'
let sort_hdchar = function
- | Prop(_) -> "P"
- | Type(_) -> "T"
+ | Prop -> "P"
+ | Set -> "S"
+ | Type _ -> "T"
let hdchar env sigma c =
let rec hdrec k c =
diff --git a/engine/proofview.ml b/engine/proofview.ml
index b4afb6415e..12d31e5f46 100644
--- a/engine/proofview.ml
+++ b/engine/proofview.ml
@@ -754,7 +754,7 @@ let mark_in_evm ~goal evd content =
- GoalEvar (morally not dependent)
- VarInstance (morally dependent of some name).
This is a heuristic for naming these evars. *)
- | loc, (Evar_kinds.QuestionMark (_,Names.Name id) |
+ | loc, (Evar_kinds.QuestionMark { Evar_kinds.qm_name=Names.Name id} |
Evar_kinds.ImplicitArg (_,(_,Some id),_)) -> loc, Evar_kinds.VarInstance id
| _, (Evar_kinds.VarInstance _ | Evar_kinds.GoalEvar) as x -> x
| loc,_ -> loc,Evar_kinds.GoalEvar }
diff --git a/engine/termops.ml b/engine/termops.ml
index 2db2e07bf3..e4c8ae66bc 100644
--- a/engine/termops.ml
+++ b/engine/termops.ml
@@ -25,8 +25,8 @@ module CompactedDecl = Context.Compacted.Declaration
(* Sorts and sort family *)
let print_sort = function
- | Prop Pos -> (str "Set")
- | Prop Null -> (str "Prop")
+ | Set -> (str "Set")
+ | Prop -> (str "Prop")
| Type u -> (str "Type(" ++ Univ.Universe.pr u ++ str ")")
let pr_sort_family = function
@@ -114,7 +114,7 @@ let pr_evar_suggested_name evk sigma =
| None -> match evi.evar_source with
| _,Evar_kinds.ImplicitArg (c,(n,Some id),b) -> id
| _,Evar_kinds.VarInstance id -> id
- | _,Evar_kinds.QuestionMark (_,Name id) -> id
+ | _,Evar_kinds.QuestionMark {Evar_kinds.qm_name = Name id} -> id
| _,Evar_kinds.GoalEvar -> Id.of_string "Goal"
| _ ->
let env = reset_with_named_context evi.evar_hyps (Global.env()) in
@@ -1162,15 +1162,14 @@ let is_template_polymorphic env sigma f =
let base_sort_cmp pb s0 s1 =
match (s0,s1) with
- | (Prop c1, Prop c2) -> c1 == Null || c2 == Pos (* Prop <= Set *)
- | (Prop c1, Type u) -> pb == Reduction.CUMUL
- | (Type u1, Type u2) -> true
- | _ -> false
+ | Prop, Prop | Set, Set | Type _, Type _ -> true
+ | Prop, Set | Prop, Type _ | Set, Type _ -> pb == Reduction.CUMUL
+ | Set, Prop | Type _, Prop | Type _, Set -> false
let rec is_Prop sigma c = match EConstr.kind sigma c with
| Sort u ->
begin match EConstr.ESorts.kind sigma u with
- | Prop Null -> true
+ | Prop -> true
| _ -> false
end
| Cast (c,_,_) -> is_Prop sigma c
@@ -1179,7 +1178,7 @@ let rec is_Prop sigma c = match EConstr.kind sigma c with
let rec is_Set sigma c = match EConstr.kind sigma c with
| Sort u ->
begin match EConstr.ESorts.kind sigma u with
- | Prop Pos -> true
+ | Set -> true
| _ -> false
end
| Cast (c,_,_) -> is_Set sigma c
diff --git a/engine/termops.mli b/engine/termops.mli
index f9aa6ba63c..80988989f1 100644
--- a/engine/termops.mli
+++ b/engine/termops.mli
@@ -43,14 +43,14 @@ val it_mkProd : types -> (Name.t * types) list -> types
val it_mkLambda : constr -> (Name.t * types) list -> constr
val it_mkProd_or_LetIn : types -> rel_context -> types
val it_mkProd_wo_LetIn : types -> rel_context -> types
-val it_mkLambda_or_LetIn : Constr.constr -> Context.Rel.t -> Constr.constr
+val it_mkLambda_or_LetIn : Constr.constr -> Constr.rel_context -> Constr.constr
val it_mkNamedProd_or_LetIn : types -> named_context -> types
-val it_mkNamedProd_wo_LetIn : Constr.types -> Context.Named.t -> Constr.types
+val it_mkNamedProd_wo_LetIn : Constr.types -> Constr.named_context -> Constr.types
val it_mkNamedLambda_or_LetIn : constr -> named_context -> constr
(* Ad hoc version reinserting letin, assuming the body is defined in
the context where the letins are expanded *)
-val it_mkLambda_or_LetIn_from_no_LetIn : Constr.constr -> Context.Rel.t -> Constr.constr
+val it_mkLambda_or_LetIn_from_no_LetIn : Constr.constr -> Constr.rel_context -> Constr.constr
(** {6 Generic iterators on constr} *)
@@ -225,7 +225,7 @@ val names_of_rel_context : env -> names_context
(* [context_chop n Γ] returns (Γ₁,Γ₂) such that [Γ]=[Γ₂Γ₁], [Γ₁] has
[n] hypotheses, excluding local definitions, and [Γ₁], if not empty,
starts with an hypothesis (i.e. [Γ₁] has the form empty or [x:A;Γ₁'] *)
-val context_chop : int -> Context.Rel.t -> Context.Rel.t * Context.Rel.t
+val context_chop : int -> Constr.rel_context -> Constr.rel_context * Constr.rel_context
(* [env_rel_context_chop n env] extracts out the [n] top declarations
of the rel_context part of [env], counting both local definitions and
@@ -239,19 +239,19 @@ val add_vname : Id.Set.t -> Name.t -> Id.Set.t
(** other signature iterators *)
val process_rel_context : (rel_declaration -> env -> env) -> env -> env
val assums_of_rel_context : ('c, 't) Context.Rel.pt -> (Name.t * 't) list
-val lift_rel_context : int -> Context.Rel.t -> Context.Rel.t
-val substl_rel_context : Constr.constr list -> Context.Rel.t -> Context.Rel.t
-val smash_rel_context : Context.Rel.t -> Context.Rel.t (** expand lets in context *)
+val lift_rel_context : int -> Constr.rel_context -> Constr.rel_context
+val substl_rel_context : Constr.constr list -> Constr.rel_context -> Constr.rel_context
+val smash_rel_context : Constr.rel_context -> Constr.rel_context (** expand lets in context *)
val map_rel_context_in_env :
- (env -> Constr.constr -> Constr.constr) -> env -> Context.Rel.t -> Context.Rel.t
+ (env -> Constr.constr -> Constr.constr) -> env -> Constr.rel_context -> Constr.rel_context
val map_rel_context_with_binders :
(int -> 'c -> 'c) -> ('c, 'c) Context.Rel.pt -> ('c, 'c) Context.Rel.pt
val fold_named_context_both_sides :
- ('a -> Context.Named.Declaration.t -> Context.Named.Declaration.t list -> 'a) ->
- Context.Named.t -> init:'a -> 'a
+ ('a -> Constr.named_declaration -> Constr.named_declaration list -> 'a) ->
+ Constr.named_context -> init:'a -> 'a
val mem_named_context_val : Id.t -> named_context_val -> bool
-val compact_named_context : Context.Named.t -> Context.Compacted.t
+val compact_named_context : Constr.named_context -> Constr.compacted_context
val map_rel_decl : ('a -> 'b) -> ('a, 'a) Context.Rel.Declaration.pt -> ('b, 'b) Context.Rel.Declaration.pt
val map_named_decl : ('a -> 'b) -> ('a, 'a) Context.Named.Declaration.pt -> ('b, 'b) Context.Named.Declaration.pt
@@ -313,6 +313,6 @@ val set_print_constr : (env -> Evd.evar_map -> constr -> Pp.t) -> unit
val print_constr : constr -> Pp.t
val print_constr_env : env -> Evd.evar_map -> constr -> Pp.t
val print_named_context : env -> Pp.t
-val pr_rel_decl : env -> Context.Rel.Declaration.t -> Pp.t
+val pr_rel_decl : env -> Constr.rel_declaration -> Pp.t
val print_rel_context : env -> Pp.t
val print_env : env -> Pp.t
diff --git a/engine/uState.ml b/engine/uState.ml
index 81ab3dd665..0791e4c277 100644
--- a/engine/uState.ml
+++ b/engine/uState.ml
@@ -583,7 +583,7 @@ let refresh_constraints univs (ctx, cstrs) =
in ((ctx, cstrs'), univs')
let normalize_variables uctx =
- let normalized_variables, undef, def, subst =
+ let normalized_variables, def, subst =
UnivSubst.normalize_univ_variables uctx.uctx_univ_variables
in
let ctx_local = subst_univs_context_with_def def (Univ.make_subst subst) uctx.uctx_local in
diff --git a/engine/univGen.ml b/engine/univGen.ml
index 796a1bcc16..b07d4848ff 100644
--- a/engine/univGen.ml
+++ b/engine/univGen.ml
@@ -215,7 +215,7 @@ let type_of_reference env r =
let type_of_global t = type_of_reference (Global.env ()) t
-let fresh_sort_in_family env = function
+let fresh_sort_in_family = function
| InProp -> Sorts.prop, ContextSet.empty
| InSet -> Sorts.set, ContextSet.empty
| InType ->
@@ -223,7 +223,7 @@ let fresh_sort_in_family env = function
Type (Univ.Universe.make u), ContextSet.singleton u
let new_sort_in_family sf =
- fst (fresh_sort_in_family (Global.env ()) sf)
+ fst (fresh_sort_in_family sf)
let extend_context (a, ctx) (ctx') =
(a, ContextSet.union ctx ctx')
diff --git a/engine/univGen.mli b/engine/univGen.mli
index 8169dbda4a..439424934c 100644
--- a/engine/univGen.mli
+++ b/engine/univGen.mli
@@ -39,7 +39,7 @@ val fresh_instance_from_context : AUContext.t ->
val fresh_instance_from : AUContext.t -> Instance.t option ->
Instance.t in_universe_context_set
-val fresh_sort_in_family : env -> Sorts.family ->
+val fresh_sort_in_family : Sorts.family ->
Sorts.t in_universe_context_set
val fresh_constant_instance : env -> Constant.t ->
pconstant in_universe_context_set
diff --git a/engine/univSubst.ml b/engine/univSubst.ml
index 6a433d9fbc..2f59a3fa85 100644
--- a/engine/univSubst.ml
+++ b/engine/univSubst.ml
@@ -162,13 +162,13 @@ let subst_opt_univs_constr s =
let normalize_univ_variables ctx =
let ctx = normalize_opt_subst ctx in
- let undef, def, subst =
- Univ.LMap.fold (fun u v (undef, def, subst) ->
+ let def, subst =
+ Univ.LMap.fold (fun u v (def, subst) ->
match v with
- | None -> (Univ.LSet.add u undef, def, subst)
- | Some b -> (undef, Univ.LSet.add u def, Univ.LMap.add u b subst))
- ctx (Univ.LSet.empty, Univ.LSet.empty, Univ.LMap.empty)
- in ctx, undef, def, subst
+ | None -> (def, subst)
+ | Some b -> (Univ.LSet.add u def, Univ.LMap.add u b subst))
+ ctx (Univ.LSet.empty, Univ.LMap.empty)
+ in ctx, def, subst
let pr_universe_body = function
| None -> mt ()
diff --git a/engine/univSubst.mli b/engine/univSubst.mli
index 26e8d1db95..e76d253336 100644
--- a/engine/univSubst.mli
+++ b/engine/univSubst.mli
@@ -23,7 +23,7 @@ val make_opt_subst : universe_opt_subst -> universe_subst_fn
val subst_opt_univs_constr : universe_opt_subst -> constr -> constr
val normalize_univ_variables : universe_opt_subst ->
- universe_opt_subst * LSet.t * LSet.t * universe_subst
+ universe_opt_subst * LSet.t * universe_subst
val normalize_univ_variable :
find:(Level.t -> Universe.t) ->
diff --git a/engine/universes.mli b/engine/universes.mli
index 29673de1e6..ad937471e9 100644
--- a/engine/universes.mli
+++ b/engine/universes.mli
@@ -86,7 +86,7 @@ val fresh_instance_from : AUContext.t -> Instance.t option ->
Instance.t in_universe_context_set
[@@ocaml.deprecated "Use [UnivGen.fresh_instance_from]"]
-val fresh_sort_in_family : env -> Sorts.family ->
+val fresh_sort_in_family : Sorts.family ->
Sorts.t in_universe_context_set
[@@ocaml.deprecated "Use [UnivGen.fresh_sort_in_family]"]
@@ -154,7 +154,7 @@ val subst_opt_univs_constr : universe_opt_subst -> constr -> constr
[@@ocaml.deprecated "Use [UnivSubst.subst_opt_univs_constr]"]
val normalize_univ_variables : universe_opt_subst ->
- universe_opt_subst * LSet.t * LSet.t * universe_subst
+ universe_opt_subst * LSet.t * universe_subst
[@@ocaml.deprecated "Use [UnivSubst.normalize_univ_variables]"]
val normalize_univ_variable :
diff --git a/engine/univops.ml b/engine/univops.ml
index 3fd518490a..7f9672f828 100644
--- a/engine/univops.ml
+++ b/engine/univops.ml
@@ -11,24 +11,13 @@
open Univ
open Constr
-let universes_of_constr env c =
- let open Declarations in
- let rec aux s c =
+let universes_of_constr c =
+ let rec aux s c =
match kind c with
| Const (c, u) ->
- begin match (Environ.lookup_constant c env).const_universes with
- | Polymorphic_const _ ->
LSet.fold LSet.add (Instance.levels u) s
- | Monomorphic_const (univs, _) ->
- LSet.union s univs
- end
| Ind ((mind,_), u) | Construct (((mind,_),_), u) ->
- begin match (Environ.lookup_mind mind env).mind_universes with
- | Cumulative_ind _ | Polymorphic_ind _ ->
LSet.fold LSet.add (Instance.levels u) s
- | Monomorphic_ind (univs,_) ->
- LSet.union s univs
- end
| Sort u when not (Sorts.is_small u) ->
let u = Sorts.univ_of_sort u in
LSet.fold LSet.add (Universe.levels u) s
diff --git a/engine/univops.mli b/engine/univops.mli
index 0b37ab975d..57a53597b9 100644
--- a/engine/univops.mli
+++ b/engine/univops.mli
@@ -11,8 +11,8 @@
open Constr
open Univ
-(** The universes of monomorphic constants appear. *)
-val universes_of_constr : Environ.env -> constr -> LSet.t
+(** Return the set of all universes appearing in [constr]. *)
+val universes_of_constr : constr -> LSet.t
(** [restrict_universe_context (univs,csts) keep] restricts [univs] to
the universes in [keep]. The constraints [csts] are adjusted so
diff --git a/grammar/q_util.mli b/grammar/q_util.mli
index 323a12357d..f3af318b60 100644
--- a/grammar/q_util.mli
+++ b/grammar/q_util.mli
@@ -48,3 +48,5 @@ val mlexpr_of_prod_entry_key : (string -> MLast.expr) -> user_symbol -> MLast.ex
val type_of_user_symbol : user_symbol -> argument_type
val parse_user_entry : string -> string -> user_symbol
+
+val mlexpr_of_symbol : user_symbol -> MLast.expr
diff --git a/grammar/q_util.mlp b/grammar/q_util.mlp
index 6cdd2ec194..0e2bf55d86 100644
--- a/grammar/q_util.mlp
+++ b/grammar/q_util.mlp
@@ -75,7 +75,7 @@ let rec mlexpr_of_prod_entry_key f = function
(** Keep in sync with Pcoq! *)
assert (e = "tactic");
if l = 5 then <:expr< Extend.Aentry Pltac.binder_tactic >>
- else <:expr< Extend.Aentryl (Pltac.tactic_expr) $mlexpr_of_int l$ >>
+ else <:expr< Extend.Aentryl (Pltac.tactic_expr) $mlexpr_of_string (string_of_int l)$ >>
let rec type_of_user_symbol = function
| Ulist1 s | Ulist1sep (s, _) | Ulist0 s | Ulist0sep (s, _) ->
@@ -128,3 +128,17 @@ let rec parse_user_entry s sep =
let s = match s with "hyp" -> "var" | _ -> s in
check_separator sep;
Uentry s
+
+let rec mlexpr_of_symbol = function
+| Ulist1 s -> <:expr< Extend.TUlist1 $mlexpr_of_symbol s$ >>
+| Ulist1sep (s,sep) -> <:expr< Extend.TUlist1sep $mlexpr_of_symbol s$ $str:sep$ >>
+| Ulist0 s -> <:expr< Extend.TUlist0 $mlexpr_of_symbol s$ >>
+| Ulist0sep (s,sep) -> <:expr< Extend.TUlist0sep $mlexpr_of_symbol s$ $str:sep$ >>
+| Uopt s -> <:expr< Extend.TUopt $mlexpr_of_symbol s$ >>
+| Uentry e ->
+ let wit = <:expr< $lid:"wit_"^e$ >> in
+ <:expr< Extend.TUentry (Genarg.get_arg_tag $wit$) >>
+| Uentryl (e, l) ->
+ assert (e = "tactic");
+ let wit = <:expr< $lid:"wit_"^e$ >> in
+ <:expr< Extend.TUentryl (Genarg.get_arg_tag $wit$) $mlexpr_of_int l$>>
diff --git a/grammar/tacextend.mlp b/grammar/tacextend.mlp
index 525be64325..07239e7af0 100644
--- a/grammar/tacextend.mlp
+++ b/grammar/tacextend.mlp
@@ -15,32 +15,13 @@ open Argextend
let plugin_name = <:expr< __coq_plugin_name >>
-let mlexpr_of_ident id =
- (** Workaround for badly-designed generic arguments lacking a closure *)
- let id = "$" ^ id in
- <:expr< Names.Id.of_string_soft $str:id$ >>
-
-let rec mlexpr_of_symbol = function
-| Ulist1 s -> <:expr< Extend.TUlist1 $mlexpr_of_symbol s$ >>
-| Ulist1sep (s,sep) -> <:expr< Extend.TUlist1sep $mlexpr_of_symbol s$ $str:sep$ >>
-| Ulist0 s -> <:expr< Extend.TUlist0 $mlexpr_of_symbol s$ >>
-| Ulist0sep (s,sep) -> <:expr< Extend.TUlist0sep $mlexpr_of_symbol s$ $str:sep$ >>
-| Uopt s -> <:expr< Extend.TUopt $mlexpr_of_symbol s$ >>
-| Uentry e ->
- let wit = <:expr< $lid:"wit_"^e$ >> in
- <:expr< Extend.TUentry (Genarg.get_arg_tag $wit$) >>
-| Uentryl (e, l) ->
- assert (e = "tactic");
- let wit = <:expr< $lid:"wit_"^e$ >> in
- <:expr< Extend.TUentryl (Genarg.get_arg_tag $wit$) $mlexpr_of_int l$>>
-
let rec mlexpr_of_clause = function
| [] -> <:expr< TyNil >>
| ExtTerminal s :: cl -> <:expr< TyIdent($str:s$, $mlexpr_of_clause cl$) >>
| ExtNonTerminal(g,None) :: cl ->
- <:expr< TyAnonArg(Loc.tag($mlexpr_of_symbol g$), $mlexpr_of_clause cl$) >>
+ <:expr< TyAnonArg($mlexpr_of_symbol g$, $mlexpr_of_clause cl$) >>
| ExtNonTerminal(g,Some id) :: cl ->
- <:expr< TyArg(Loc.tag($mlexpr_of_symbol g$, $mlexpr_of_ident id$), $mlexpr_of_clause cl$) >>
+ <:expr< TyArg($mlexpr_of_symbol g$, $mlexpr_of_string id$, $mlexpr_of_clause cl$) >>
let rec binders_of_clause e = function
| [] -> <:expr< fun ist -> $e$ >>
@@ -54,13 +35,17 @@ EXTEND
GLOBAL: str_item;
str_item:
[ [ "TACTIC"; "EXTEND"; s = tac_name;
+ depr = OPT [ "DEPRECATED"; depr = LIDENT -> depr ];
level = OPT [ "AT"; UIDENT "LEVEL"; level = INT -> level ];
OPT "|"; l = LIST1 tacrule SEP "|";
"END" ->
let level = match level with Some i -> int_of_string i | None -> 0 in
let level = mlexpr_of_int level in
+ let depr = mlexpr_of_option (fun l -> <:expr< $lid:l$ >>) depr in
let l = <:expr< Tacentries.($mlexpr_of_list (fun x -> x) l$) >> in
- declare_str_items loc [ <:str_item< Tacentries.tactic_extend $plugin_name$ $str:s$ ~{ level = $level$ } $l$ >> ] ] ]
+ declare_str_items loc [ <:str_item< Tacentries.tactic_extend
+ $plugin_name$ $str:s$ ~{ level = $level$ } ?{ deprecation =
+ $depr$ } $l$ >> ] ] ]
;
tacrule:
[ [ "["; l = LIST1 tacargs; "]";
diff --git a/grammar/vernacextend.mlp b/grammar/vernacextend.mlp
index a2872d07f6..f30c96a7f5 100644
--- a/grammar/vernacextend.mlp
+++ b/grammar/vernacextend.mlp
@@ -14,134 +14,42 @@ open Q_util
open Argextend
type rule = {
- r_head : string option;
- (** The first terminal grammar token *)
r_patt : extend_token list;
(** The remaining tokens of the parsing rule *)
r_class : MLast.expr option;
(** An optional classifier for the STM *)
r_branch : MLast.expr;
(** The action performed by this rule. *)
- r_depr : unit option;
+ r_depr : bool;
(** Whether this entry is deprecated *)
}
-(** Quotation difference for match clauses *)
-
-let default_patt loc =
- (<:patt< _ >>, ploc_vala None, <:expr< failwith "Extension: cannot occur" >>)
-
-let make_fun loc cl =
- let l = cl @ [default_patt loc] in
- MLast.ExFun (loc, ploc_vala l) (* correspond to <:expr< fun [ $list:l$ ] >> *)
-
-let rec make_patt = function
- | [] -> <:patt< [] >>
- | ExtNonTerminal (_, Some p) :: l ->
- <:patt< [ $lid:p$ :: $make_patt l$ ] >>
- | _::l -> make_patt l
-
-let rec make_let e = function
- | [] -> e
- | ExtNonTerminal (g, Some p) :: l ->
- let t = type_of_user_symbol g in
- let loc = MLast.loc_of_expr e in
- let e = make_let e l in
- <:expr< let $lid:p$ = Genarg.out_gen $make_rawwit loc t$ $lid:p$ in $e$ >>
- | _::l -> make_let e l
-
-let make_clause { r_patt = pt; r_branch = e; } =
- (make_patt pt,
- ploc_vala None,
- make_let e pt)
-
-(* To avoid warnings *)
-let mk_ignore c pt =
- let fold accu = function
- | ExtNonTerminal (_, Some p) -> p :: accu
- | _ -> accu
- in
- let names = List.fold_left fold [] pt in
- let fold accu id = <:expr< let _ = $lid:id$ in $accu$ >> in
- let names = List.fold_left fold <:expr< () >> names in
- <:expr< do { let _ = $names$ in $c$ } >>
-
-let make_clause_classifier cg s { r_patt = pt; r_class = c; } =
- match c ,cg with
- | Some c, _ ->
- (make_patt pt,
- ploc_vala None,
- make_let (mk_ignore c pt) pt)
- | None, Some cg ->
- (make_patt pt,
- ploc_vala None,
- <:expr< fun loc -> $cg$ $str:s$ >>)
- | None, None -> prerr_endline
- (("Vernac entry \""^s^"\" misses a classifier. "^
- "A classifier is a function that returns an expression "^
- "of type vernac_classification (see Vernacexpr). You can: ") ^
- "- " ^ (
- ("Use '... EXTEND "^s^" CLASSIFIED AS QUERY ...' if the "^
- "new vernacular command does not alter the system state;"))^ "\n" ^
- "- " ^ (
- ("Use '... EXTEND "^s^" CLASSIFIED AS SIDEFF ...' if the "^
- "new vernacular command alters the system state but not the "^
- "parser nor it starts a proof or ends one;"))^ "\n" ^
- "- " ^ (
- ("Use '... EXTEND "^s^" CLASSIFIED BY f ...' to specify "^
- "a global function f. The function f will be called passing "^
- "\""^s^"\" as the only argument;")) ^ "\n" ^
- "- " ^ (
- "Add a specific classifier in each clause using the syntax:"
- ^ "\n" ^("'[...] => [ f ] -> [...]'. "))^ "\n" ^
- ("Specific classifiers have precedence over global "^
- "classifiers. Only one classifier is called.") ^ "\n");
- (make_patt pt,
- ploc_vala None,
- <:expr< fun () -> ( CErrors.anomaly (Pp.str "No classification given for command " ^ s ) ) >>)
-
-let make_fun_clauses loc s l =
- let map c =
- let depr = match c.r_depr with
- | None -> false
- | Some () -> true
- in
- let cl = make_fun loc [make_clause c] in
- <:expr< ($mlexpr_of_bool depr$, $cl$)>>
- in
- mlexpr_of_list map l
-
-let make_fun_classifiers loc s c l =
- let cl = List.map (fun x -> make_fun loc [make_clause_classifier c s x]) l in
- mlexpr_of_list (fun x -> x) cl
-
-let make_prod_item = function
- | ExtTerminal s -> <:expr< Egramml.GramTerminal $str:s$ >>
- | ExtNonTerminal (g, ido) ->
- let nt = type_of_user_symbol g in
- let base s = <:expr< Pcoq.genarg_grammar ($mk_extraarg loc s$) >> in
- let typ = match ido with None -> None | Some _ -> Some nt in
- <:expr< Egramml.GramNonTerminal ( Loc.tag ( $mlexpr_of_option (make_rawwit loc) typ$ ,
- $mlexpr_of_prod_entry_key base g$ ) ) >>
-
-let mlexpr_of_clause cl =
- let mkexpr { r_head = a; r_patt = b; } = match a with
- | None -> mlexpr_of_list make_prod_item b
- | Some a -> mlexpr_of_list make_prod_item (ExtTerminal a :: b)
- in
- mlexpr_of_list mkexpr cl
+let rec make_patt r = function
+| [] -> r
+| ExtNonTerminal (_, Some p) :: l -> <:expr< fun $lid:p$ -> $make_patt r l$ >>
+| ExtNonTerminal (_, None) :: l -> <:expr< fun _ -> $make_patt r l$ >>
+| ExtTerminal _ :: l -> make_patt r l
+
+let rec mlexpr_of_clause = function
+| [] -> <:expr< Vernacentries.TyNil >>
+| ExtTerminal s :: cl -> <:expr< Vernacentries.TyTerminal ($str:s$, $mlexpr_of_clause cl$) >>
+| ExtNonTerminal (g, id) :: cl ->
+ let id = mlexpr_of_option mlexpr_of_string id in
+ <:expr< Vernacentries.TyNonTerminal ($id$, $mlexpr_of_symbol g$, $mlexpr_of_clause cl$) >>
+
+let make_rule r =
+ let ty = mlexpr_of_clause r.r_patt in
+ let cmd = make_patt r.r_branch r.r_patt in
+ let make_classifier c = make_patt c r.r_patt in
+ let classif = mlexpr_of_option make_classifier r.r_class in
+ <:expr< Vernacentries.TyML ($mlexpr_of_bool r.r_depr$, $ty$, $cmd$, $classif$) >>
let declare_command loc s c nt cl =
let se = mlexpr_of_string s in
- let gl = mlexpr_of_clause cl in
- let funcl = make_fun_clauses loc s cl in
- let classl = make_fun_classifiers loc s c cl in
+ let c = mlexpr_of_option (fun x -> x) c in
+ let rules = mlexpr_of_list make_rule cl in
declare_str_items loc
- [ <:str_item< do {
- CList.iteri (fun i (depr, f) -> Vernacinterp.vinterp_add depr ($se$, i) f) $funcl$;
- CList.iteri (fun i f -> Vernac_classifier.declare_vernac_classifier ($se$, i) f) $classl$;
- CList.iteri (fun i r -> Egramml.extend_vernac_command_grammar ($se$, i) $nt$ r) $gl$;
- } >> ]
+ [ <:str_item< Vernacentries.vernac_extend ?{ classifier = $c$ } ~{ command = $se$ } ?{ entry = $nt$ } $rules$ >> ]
open Pcaml
@@ -176,38 +84,25 @@ EXTEND
] ]
;
deprecation:
- [ [ "DEPRECATED" -> () ] ]
+ [ [ -> false | "DEPRECATED" -> true ] ]
;
- (* spiwack: comment-by-guessing: it seems that the isolated string
- (which otherwise could have been another argument) is not passed
- to the VernacExtend interpreter function to discriminate between
- the clauses. *)
rule:
- [ [ "["; s = STRING; l = LIST0 args; "]";
- d = OPT deprecation; c = OPT classifier; "->"; "["; e = Pcaml.expr; "]" ->
- let () = if s = "" then failwith "Command name is empty." in
- let b = <:expr< fun ~{atts} ~{st} -> ( let () = $e$ in st ) >> in
- { r_head = Some s; r_patt = l; r_class = c; r_branch = b; r_depr = d; }
- | "[" ; "-" ; l = LIST1 args ; "]" ;
- d = OPT deprecation; c = OPT classifier; "->"; "["; e = Pcaml.expr; "]" ->
+ [ [ "["; OPT "-"; l = LIST1 args; "]";
+ d = deprecation; c = OPT classifier; "->"; "["; e = Pcaml.expr; "]" ->
let b = <:expr< fun ~{atts} ~{st} -> ( let () = $e$ in st ) >> in
- { r_head = None; r_patt = l; r_class = c; r_branch = b; r_depr = d; }
+ { r_patt = l; r_class = c; r_branch = b; r_depr = d; }
] ]
;
+ (** The [OPT "-"] argument serves no purpose nowadays, it is left here for
+ backward compatibility. *)
fun_rule:
- [ [ "["; s = STRING; l = LIST0 args; "]";
- d = OPT deprecation; c = OPT classifier; "->"; "["; e = Pcaml.expr; "]" ->
- let () = if s = "" then failwith "Command name is empty." in
- let b = <:expr< $e$ >> in
- { r_head = Some s; r_patt = l; r_class = c; r_branch = b; r_depr = d; }
- | "[" ; "-" ; l = LIST1 args ; "]" ;
- d = OPT deprecation; c = OPT classifier; "->"; "["; e = Pcaml.expr; "]" ->
- let b = <:expr< $e$ >> in
- { r_head = None; r_patt = l; r_class = c; r_branch = b; r_depr = d; }
+ [ [ "["; OPT "-"; l = LIST1 args; "]";
+ d = deprecation; c = OPT classifier; "->"; "["; e = Pcaml.expr; "]" ->
+ { r_patt = l; r_class = c; r_branch = e; r_depr = d; }
] ]
;
classifier:
- [ [ "=>"; "["; c = Pcaml.expr; "]" -> <:expr< fun loc -> $c$>> ] ]
+ [ [ "=>"; "["; c = Pcaml.expr; "]" -> <:expr< $c$>> ] ]
;
args:
[ [ e = LIDENT; "("; s = LIDENT; ")" ->
diff --git a/ide/.merlin b/ide/.merlin.in
index 953b5dce4c..953b5dce4c 100644
--- a/ide/.merlin
+++ b/ide/.merlin.in
diff --git a/ide/MacOS/default_accel_map b/ide/MacOS/default_accel_map
index 47612cdf72..54a592a04d 100644
--- a/ide/MacOS/default_accel_map
+++ b/ide/MacOS/default_accel_map
@@ -217,7 +217,6 @@
; (gtk_accel_path "<Actions>/Tactics/Tactic casetype" "")
; (gtk_accel_path "<Actions>/Tactics/Tactic cbv in" "")
; (gtk_accel_path "<Actions>/Templates/Template Load" "")
-; (gtk_accel_path "<Actions>/Tactics/Tactic fourier" "")
; (gtk_accel_path "<Actions>/Templates/Template Goal" "")
; (gtk_accel_path "<Actions>/Tactics/Tactic exists" "")
; (gtk_accel_path "<Actions>/Tactics/Tactic decompose record" "")
diff --git a/ide/coq.ml b/ide/coq.ml
index 63986935aa..e948360191 100644
--- a/ide/coq.ml
+++ b/ide/coq.ml
@@ -530,20 +530,31 @@ let break_coqtop coqtop workers =
module PrintOpt =
struct
- type t = string list
+ type _ t =
+ | BoolOpt : string list -> bool t
+ | StringOpt : string list -> string t
+
+ let opt_name (type a) : a t -> string list = function
+ | BoolOpt l -> l
+ | StringOpt l -> l
+
+ let opt_data (type a) (key : a t) (v : a) = match key with
+ | BoolOpt l -> Interface.BoolValue v
+ | StringOpt l -> Interface.StringValue v
(* Boolean options *)
- let implicit = ["Printing"; "Implicit"]
- let coercions = ["Printing"; "Coercions"]
- let raw_matching = ["Printing"; "Matching"]
- let notations = ["Printing"; "Notations"]
- let all_basic = ["Printing"; "All"]
- let existential = ["Printing"; "Existential"; "Instances"]
- let universes = ["Printing"; "Universes"]
- let unfocused = ["Printing"; "Unfocused"]
+ let implicit = BoolOpt ["Printing"; "Implicit"]
+ let coercions = BoolOpt ["Printing"; "Coercions"]
+ let raw_matching = BoolOpt ["Printing"; "Matching"]
+ let notations = BoolOpt ["Printing"; "Notations"]
+ let all_basic = BoolOpt ["Printing"; "All"]
+ let existential = BoolOpt ["Printing"; "Existential"; "Instances"]
+ let universes = BoolOpt ["Printing"; "Universes"]
+ let unfocused = BoolOpt ["Printing"; "Unfocused"]
+ let diff = StringOpt ["Diffs"]
- type bool_descr = { opts : t list; init : bool; label : string }
+ type 'a descr = { opts : 'a t list; init : 'a; label : string }
let bool_items = [
{ opts = [implicit]; init = false; label = "Display _implicit arguments" };
@@ -561,24 +572,32 @@ struct
{ opts = [unfocused]; init = false; label = "Display _unfocused goals" }
]
+ let diff_item = { opts = [diff]; init = "off"; label = "Display _proof diffs" }
+
(** The current status of the boolean options *)
let current_state = Hashtbl.create 11
- let set opt v = Hashtbl.replace current_state opt v
+ let set (type a) (opt : a t) (v : a) =
+ Hashtbl.replace current_state (opt_name opt) (opt_data opt v)
let reset () =
let init_descr d = List.iter (fun o -> set o d.init) d.opts in
- List.iter init_descr bool_items
+ List.iter init_descr bool_items;
+ List.iter (fun o -> set o diff_item.init) diff_item.opts
let _ = reset ()
- let printing_unfocused () = Hashtbl.find current_state unfocused
+ let printing_unfocused () =
+ let BoolOpt unfocused = unfocused in
+ match Hashtbl.find current_state unfocused with
+ | Interface.BoolValue b -> b
+ | _ -> assert false
(** Transmitting options to coqtop *)
let enforce h k =
- let mkopt o v acc = (o, Interface.BoolValue v) :: acc in
+ let mkopt o v acc = (o, v) :: acc in
let opts = Hashtbl.fold mkopt current_state [] in
eval_call (Xmlprotocol.set_options opts) h
(function
diff --git a/ide/coq.mli b/ide/coq.mli
index 40a6dea8d3..3af0aa697e 100644
--- a/ide/coq.mli
+++ b/ide/coq.mli
@@ -134,13 +134,15 @@ val stop_worker: Interface.stop_worker_sty-> Interface.stop_worker_rty query
module PrintOpt :
sig
- type t (** Representation of an option *)
+ type 'a t (** Representation of an option *)
- type bool_descr = { opts : t list; init : bool; label : string }
+ type 'a descr = { opts : 'a t list; init : 'a; label : string }
- val bool_items : bool_descr list
+ val bool_items : bool descr list
- val set : t -> bool -> unit
+ val diff_item : string descr
+
+ val set : 'a t -> 'a -> unit
val printing_unfocused: unit -> bool
diff --git a/ide/coq_commands.ml b/ide/coq_commands.ml
index f5dba2085a..b0bafb7930 100644
--- a/ide/coq_commands.ml
+++ b/ide/coq_commands.ml
@@ -311,7 +311,6 @@ let tactics =
"fix __ with";
"fold";
"fold __ in";
- "fourier";
"functional induction";
];
diff --git a/ide/coq_lex.mll b/ide/coq_lex.mll
index 1fdd7317b5..b6654f6d7a 100644
--- a/ide/coq_lex.mll
+++ b/ide/coq_lex.mll
@@ -23,7 +23,11 @@ let number = [ '0'-'9' ]+
let string = "\"" _+ "\""
-let undotted_sep = (number space* ':' space*)? '{' | '}' | '-'+ | '+'+ | '*'+
+let alpha = ['a'-'z' 'A'-'Z']
+
+let ident = alpha (alpha | number | '_' | "'")*
+
+let undotted_sep = ((number | '[' ident ']') space* ':' space*)? '{' | '}' | '-'+ | '+'+ | '*'+
let vernac_control = "Fail" | "Time" | "Redirect" space+ string | "Timeout" space+ number
diff --git a/ide/coqide.ml b/ide/coqide.ml
index aa816f2b8b..00d43e6e64 100644
--- a/ide/coqide.ml
+++ b/ide/coqide.ml
@@ -826,6 +826,7 @@ let refresh_notebook_pos () =
let menu = GAction.add_actions
let item = GAction.add_action
+let radio = GAction.add_radio_action
(** Toggle items in menus for printing options *)
@@ -1043,7 +1044,27 @@ let build_ui () =
~callback:(fun _ -> show_toolbar#set (not show_toolbar#get));
item "Query Pane" ~label:"_Query Pane"
~accel:"F1"
- ~callback:(cb_on_current_term MiscMenu.show_hide_query_pane)
+ ~callback:(cb_on_current_term MiscMenu.show_hide_query_pane);
+ GAction.group_radio_actions
+ ~init_value:(
+ let v = diffs#get in
+ List.iter (fun o -> Opt.set o v) Opt.diff_item.Opt.opts;
+ if v = "on" then 1
+ else if v = "removed" then 2
+ else 0)
+ ~callback:begin fun n ->
+ (match n with
+ | 0 -> List.iter (fun o -> Opt.set o "off"; diffs#set "off") Opt.diff_item.Opt.opts
+ | 1 -> List.iter (fun o -> Opt.set o "on"; diffs#set "on") Opt.diff_item.Opt.opts
+ | 2 -> List.iter (fun o -> Opt.set o "removed"; diffs#set "removed") Opt.diff_item.Opt.opts
+ | _ -> assert false);
+ send_to_coq (fun sn -> sn.coqops#show_goals)
+ end
+ [
+ radio "Unset diff" 0 ~label:"_Don't show diffs";
+ radio "Set diff" 1 ~label:"Show diffs: only _added";
+ radio "Set removed diff" 2 ~label:"Show diffs: added and _removed";
+ ];
];
toggle_items view_menu Coq.PrintOpt.bool_items;
@@ -1106,15 +1127,15 @@ let build_ui () =
];
alpha_items templates_menu "Template" Coq_commands.commands;
- let qitem s sc ?(dots = true) =
- let query = if dots then s ^ "..." else s in
+ let qitem s sc =
+ let query = s ^ "..." in
item s ~label:("_"^s)
~accel:(modifier_for_queries#get^sc)
~callback:(Query.query query)
in
menu queries_menu [
item "Queries" ~label:"_Queries";
- qitem "Search" "K" ~dots:false;
+ qitem "Search" "K";
qitem "Check" "C";
qitem "Print" "P";
qitem "About" "A";
diff --git a/ide/coqide_ui.ml b/ide/coqide_ui.ml
index 717c4000f5..91c529932f 100644
--- a/ide/coqide_ui.ml
+++ b/ide/coqide_ui.ml
@@ -86,6 +86,10 @@ let init () =
\n <menuitem action='Display universe levels' />\
\n <menuitem action='Display all low-level contents' />\
\n <menuitem action='Display unfocused goals' />\
+\n <separator/>\
+\n <menuitem action='Unset diff' />\
+\n <menuitem action='Set diff' />\
+\n <menuitem action='Set removed diff' />\
\n </menu>\
\n <menu action='Navigation'>\
\n <menuitem action='Forward' />\
diff --git a/ide/gtk_parsing.ml b/ide/gtk_parsing.ml
index 9f5c992444..d554bebdd3 100644
--- a/ide/gtk_parsing.ml
+++ b/ide/gtk_parsing.ml
@@ -35,8 +35,11 @@ let find_word_start (it:GText.iter) =
(Minilib.log "find_word_start: cannot backward"; it)
else if is_word_char it#char
then step_to_start it
- else (it#nocopy#forward_char;
- Minilib.log ("Word start at: "^(string_of_int it#offset));it)
+ else begin
+ ignore(it#nocopy#forward_char);
+ Minilib.log ("Word start at: "^(string_of_int it#offset));
+ it
+ end
in
step_to_start it#copy
diff --git a/ide/idetop.ml b/ide/idetop.ml
index 7abbf239b2..d846b3abb5 100644
--- a/ide/idetop.ml
+++ b/ide/idetop.ml
@@ -53,10 +53,12 @@ let coqide_known_option table = List.mem table [
["Printing";"Records"];
["Printing";"Existential";"Instances"];
["Printing";"Universes"];
- ["Printing";"Unfocused"]]
+ ["Printing";"Unfocused"];
+ ["Diffs"]]
let is_known_option cmd = match Vernacprop.under_control cmd with
| VernacSetOption (_, o, BoolValue true)
+ | VernacSetOption (_, o, StringValue _)
| VernacUnsetOption (_, o) -> coqide_known_option o
| _ -> false
@@ -80,7 +82,7 @@ let set_doc doc = ide_doc := Some doc
let add ((s,eid),(sid,verbose)) =
let doc = get_doc () in
- let pa = Pcoq.Gram.parsable (Stream.of_string s) in
+ let pa = Pcoq.Parsable.make (Stream.of_string s) in
let loc_ast = Stm.parse_sentence ~doc sid pa in
let doc, newid, rc = Stm.add ~doc ~ontop:sid verbose loc_ast in
set_doc doc;
@@ -113,14 +115,14 @@ let edit_at id =
* be removed in the next version of the protocol.
*)
let query (route, (s,id)) =
- let pa = Pcoq.Gram.parsable (Stream.of_string s) in
+ let pa = Pcoq.Parsable.make (Stream.of_string s) in
let doc = get_doc () in
Stm.query ~at:id ~doc ~route pa
let annotate phrase =
let doc = get_doc () in
let {CAst.loc;v=ast} =
- let pa = Pcoq.Gram.parsable (Stream.of_string phrase) in
+ let pa = Pcoq.Parsable.make (Stream.of_string phrase) in
Stm.parse_sentence ~doc (Stm.get_current_state ~doc) pa
in
(* XXX: Width should be a parameter of annotate... *)
@@ -151,7 +153,7 @@ let hyp_next_tac sigma env decl =
("inversion clear "^id_s), ("inversion_clear "^id_s^".")
]
-let concl_next_tac sigma concl =
+let concl_next_tac =
let expand s = (s,s^".") in
List.map expand ([
"intro";
@@ -202,13 +204,28 @@ let export_pre_goals pgs =
Interface.given_up_goals = pgs.Proof.given_up_goals
}
+let add_diffs oldp newp intf =
+ let open Interface in
+ let (hyps_pp_list, concl_pp) = Proof_diffs.diff_first_goal oldp newp in
+ match intf.fg_goals with
+ | [] -> intf
+ | first_goal :: tl ->
+ { intf with fg_goals = { first_goal with goal_hyp = hyps_pp_list; goal_ccl = concl_pp } :: tl }
+
let goals () =
let doc = get_doc () in
set_doc @@ Stm.finish ~doc;
try
- let pfts = Proof_global.give_me_the_proof () in
- Some (export_pre_goals (Proof.map_structured_proof pfts process_goal))
- with Proof_global.NoCurrentProof -> None
+ let newp = Proof_global.give_me_the_proof () in
+ let intf = export_pre_goals (Proof.map_structured_proof newp process_goal) in
+ if Proof_diffs.show_diffs () then
+ let oldp = Stm.get_prev_proof ~doc (Stm.get_current_state ~doc) in
+ try
+ Some (add_diffs oldp (Some newp) intf)
+ with Pp_diff.Diff_Failure _ -> Some intf
+ else
+ Some intf
+ with Proof_global.NoCurrentProof -> None;;
let evars () =
try
@@ -230,10 +247,9 @@ let hints () =
| [] -> None
| g :: _ ->
let env = Goal.V82.env sigma g in
- let hint_goal = concl_next_tac sigma g in
let get_hint_hyp env d accu = hyp_next_tac sigma env d :: accu in
let hint_hyps = List.rev (Environ.fold_named_context get_hint_hyp env ~init: []) in
- Some (hint_hyps, hint_goal)
+ Some (hint_hyps, concl_next_tac)
with Proof_global.NoCurrentProof -> None
diff --git a/ide/ideutils.ml b/ide/ideutils.ml
index e96b992999..960beb8455 100644
--- a/ide/ideutils.ml
+++ b/ide/ideutils.ml
@@ -37,6 +37,11 @@ let flash_info =
let flash_context = status#new_context ~name:"Flash" in
(fun ?(delay=5000) s -> flash_context#flash ~delay s)
+(* Note: Setting the same attribute with two separate tags appears to use
+the first value applied and not the second. I saw this trying to set the background
+color on Windows. A clean fix, if ever needed, would be to combine the attributes
+of the tags into a single composite tag before applying. This is left as an
+exercise for the reader. *)
let insert_with_tags (buf : #GText.buffer_skel) mark rmark tags text =
(** FIXME: LablGTK2 does not export the C insert_with_tags function, so that
it has to reimplement its own helper function. Unluckily, it relies on
@@ -50,21 +55,51 @@ let insert_with_tags (buf : #GText.buffer_skel) mark rmark tags text =
let start = buf#get_iter_at_mark mark in
let stop = buf#get_iter_at_mark rmark in
let iter tag = buf#apply_tag tag ~start ~stop in
- List.iter iter tags
+ List.iter iter (List.rev tags)
+
+let nl_white_regex = Str.regexp "^\\( *\n *\\)"
+let diff_regex = Str.regexp "^diff."
let insert_xml ?(mark = `INSERT) ?(tags = []) (buf : #GText.buffer_skel) msg =
let open Xml_datatype in
+ let dtags = ref [] in
let tag name =
match GtkText.TagTable.lookup buf#tag_table name with
| None -> raise Not_found
| Some tag -> new GText.tag tag
in
let rmark = `MARK (buf#create_mark buf#start_iter) in
+ (* insert the string, but don't apply diff highlights to white space at the begin/end of line *)
+ let rec insert_str tags s =
+ try
+ let _ = Str.search_forward nl_white_regex s 0 in
+ insert_with_tags buf mark rmark tags (Str.matched_group 1 s);
+ let mend = Str.match_end () in
+ insert_str tags (String.sub s mend (String.length s - mend))
+ with Not_found -> begin
+ let etags = try List.hd !dtags :: tags with hd -> tags in
+ insert_with_tags buf mark rmark etags s
+ end
+ in
let rec insert tags = function
- | PCData s -> insert_with_tags buf mark rmark tags s
+ | PCData s -> insert_str tags s
| Element (t, _, children) ->
- let tags = try tag t :: tags with Not_found -> tags in
- List.iter (fun xml -> insert tags xml) children
+ let (pfx, tname) = Pp.split_tag t in
+ let is_diff = try let _ = Str.search_forward diff_regex tname 0 in true with Not_found -> false in
+ let (tags, have_tag) =
+ try
+ let t = tag tname in
+ if is_diff && pfx <> Pp.end_pfx then
+ dtags := t :: !dtags;
+ if pfx = "" then
+ ((if is_diff then tags else t :: tags), true)
+ else
+ (tags, true)
+ with Not_found -> (tags, false)
+ in
+ List.iter (fun xml -> insert tags xml) children;
+ if have_tag && is_diff && pfx <> Pp.start_pfx then
+ dtags := (try List.tl !dtags with tl -> []);
in
let () = try insert tags msg with _ -> () in
buf#delete_mark rmark
diff --git a/ide/preferences.ml b/ide/preferences.ml
index 11aaf6e8cc..955ee87840 100644
--- a/ide/preferences.ml
+++ b/ide/preferences.ml
@@ -25,6 +25,7 @@ type tag = {
tag_bold : bool;
tag_italic : bool;
tag_underline : bool;
+ tag_strikethrough : bool;
}
(** Generic preferences *)
@@ -215,15 +216,17 @@ object
string_of_bool tag.tag_bold;
string_of_bool tag.tag_italic;
string_of_bool tag.tag_underline;
+ string_of_bool tag.tag_strikethrough;
]
method into = function
- | [fg; bg; bd; it; ul] ->
+ | [fg; bg; bd; it; ul; st] ->
(try Some {
tag_fg_color = _to fg;
tag_bg_color = _to bg;
tag_bold = bool_of_string bd;
tag_italic = bool_of_string it;
tag_underline = bool_of_string ul;
+ tag_strikethrough = bool_of_string st;
}
with _ -> None)
| _ -> None
@@ -429,12 +432,13 @@ let tags = ref Util.String.Map.empty
let list_tags () = !tags
-let make_tag ?fg ?bg ?(bold = false) ?(italic = false) ?(underline = false) () = {
+let make_tag ?fg ?bg ?(bold = false) ?(italic = false) ?(underline = false) ?(strikethrough = false) () = {
tag_fg_color = fg;
tag_bg_color = bg;
tag_bold = bold;
tag_italic = italic;
tag_underline = underline;
+ tag_strikethrough = strikethrough;
}
let create_tag name default =
@@ -470,6 +474,12 @@ let create_tag name default =
tag#set_property (`UNDERLINE_SET true);
tag#set_property (`UNDERLINE `SINGLE)
end;
+ begin match pref#get.tag_strikethrough with
+ | false -> tag#set_property (`STRIKETHROUGH_SET false)
+ | true ->
+ tag#set_property (`STRIKETHROUGH_SET true);
+ tag#set_property (`STRIKETHROUGH true)
+ end;
in
let iter table =
let tag = GText.tag ~name () in
@@ -480,6 +490,8 @@ let create_tag name default =
List.iter iter [Tags.Script.table; Tags.Proof.table; Tags.Message.table];
tags := Util.String.Map.add name pref !tags
+(* note these appear to only set the defaults; they don't override
+the user selection from the Edit/Preferences/Tags dialog *)
let () =
let iter (name, tag) = create_tag name tag in
List.iter iter [
@@ -498,6 +510,10 @@ let () =
("tactic.keyword", make_tag ());
("tactic.primitive", make_tag ());
("tactic.string", make_tag ());
+ ("diff.added", make_tag ~bg:"#b6f1c0" ~underline:true ());
+ ("diff.removed", make_tag ~bg:"#f6b9c1" ~strikethrough:true ());
+ ("diff.added.bg", make_tag ~bg:"#e9feee" ());
+ ("diff.removed.bg", make_tag ~bg:"#fce9eb" ());
]
let processed_color =
@@ -549,6 +565,9 @@ let nanoPG =
let user_queries =
new preference ~name:["user_queries"] ~init:[] ~repr:Repr.(string_pair_list '$')
+let diffs =
+ new preference ~name:["diffs"] ~init:"off" ~repr:Repr.(string)
+
class tag_button (box : Gtk.box Gtk.obj) =
object (self)
@@ -561,6 +580,7 @@ object (self)
val bold = GButton.toggle_button ()
val italic = GButton.toggle_button ()
val underline = GButton.toggle_button ()
+ val strikethrough = GButton.toggle_button ()
method set_tag tag =
let track c but set = match c with
@@ -574,6 +594,7 @@ object (self)
bold#set_active tag.tag_bold;
italic#set_active tag.tag_italic;
underline#set_active tag.tag_underline;
+ strikethrough#set_active tag.tag_strikethrough;
method tag =
let get but set =
@@ -586,6 +607,7 @@ object (self)
tag_bold = bold#active;
tag_italic = italic#active;
tag_underline = underline#active;
+ tag_strikethrough = strikethrough#active;
}
initializer
@@ -599,6 +621,7 @@ object (self)
set_stock bold `BOLD;
set_stock italic `ITALIC;
set_stock underline `UNDERLINE;
+ set_stock strikethrough `STRIKETHROUGH;
box#pack fg_color#coerce;
box#pack fg_unset#coerce;
box#pack bg_color#coerce;
@@ -606,6 +629,7 @@ object (self)
box#pack bold#coerce;
box#pack italic#coerce;
box#pack underline#coerce;
+ box#pack strikethrough#coerce;
let cb but obj = obj#set_sensitive (not but#active) in
let _ = fg_unset#connect#toggled ~callback:(fun () -> cb fg_unset fg_color#misc) in
let _ = bg_unset#connect#toggled ~callback:(fun () -> cb bg_unset bg_color#misc) in
diff --git a/ide/preferences.mli b/ide/preferences.mli
index ccf028aee4..dd2976efc2 100644
--- a/ide/preferences.mli
+++ b/ide/preferences.mli
@@ -21,6 +21,7 @@ type tag = {
tag_bold : bool;
tag_italic : bool;
tag_underline : bool;
+ tag_strikethrough : bool;
}
class type ['a] repr =
@@ -101,6 +102,7 @@ val tab_length : int preference
val highlight_current_line : bool preference
val nanoPG : bool preference
val user_queries : (string * string) list preference
+val diffs : string preference
val save_pref : unit -> unit
val load_pref : unit -> unit
diff --git a/ide/wg_ProofView.ml b/ide/wg_ProofView.ml
index b3088ee288..9be562d3ed 100644
--- a/ide/wg_ProofView.ml
+++ b/ide/wg_ProofView.ml
@@ -103,7 +103,7 @@ let mode_tactic sel_cb (proof : #GText.view_skel) goals ~unfoc_goals hints = mat
else []
in
proof#buffer#insert (goal_str ~shownum:true 1 goals_cnt);
- insert_xml proof#buffer (Richpp.richpp_of_pp width cur_goal);
+ insert_xml ~tags:[Tags.Proof.goal] proof#buffer (Richpp.richpp_of_pp width cur_goal);
proof#buffer#insert "\n"
in
(* Insert remaining goals (no hypotheses) *)
@@ -128,7 +128,7 @@ let mode_tactic sel_cb (proof : #GText.view_skel) goals ~unfoc_goals hints = mat
ignore(proof#buffer#place_cursor
~where:(proof#buffer#end_iter#backward_to_tag_toggle
(Some Tags.Proof.goal)));
- ignore(proof#scroll_to_mark ~use_align:true ~yalign:0.95 `INSERT)
+ ignore(proof#scroll_to_mark `INSERT)
let rec flatten = function
| [] -> []
diff --git a/interp/constrexpr.ml b/interp/constrexpr.ml
index 521eeb8e96..d8dd4ef6dd 100644
--- a/interp/constrexpr.ml
+++ b/interp/constrexpr.ml
@@ -20,7 +20,10 @@ type universe_decl_expr = (lident list, Glob_term.glob_constraint list) UState.g
type ident_decl = lident * universe_decl_expr option
type name_decl = lname * universe_decl_expr option
-type notation = string
+type notation_entry = InConstrEntry | InCustomEntry of string
+type notation_entry_level = InConstrEntrySomeLevel | InCustomEntryLevel of string * int
+type notation_key = string
+type notation = notation_entry_level * notation_key
type 'a or_by_notation_r =
| AN of 'a
diff --git a/interp/constrexpr_ops.ml b/interp/constrexpr_ops.ml
index 4b1af9147c..011c4a6e4e 100644
--- a/interp/constrexpr_ops.ml
+++ b/interp/constrexpr_ops.ml
@@ -16,6 +16,7 @@ open Libnames
open Namegen
open Glob_term
open Constrexpr
+open Notation
open Decl_kinds
(***********************)
@@ -80,7 +81,7 @@ let rec cases_pattern_expr_eq p1 p2 =
| CPatOr a1, CPatOr a2 ->
List.equal cases_pattern_expr_eq a1 a2
| CPatNotation (n1, s1, l1), CPatNotation (n2, s2, l2) ->
- String.equal n1 n2 &&
+ notation_eq n1 n2 &&
cases_pattern_notation_substitution_eq s1 s2 &&
List.equal cases_pattern_expr_eq l1 l2
| CPatPrim i1, CPatPrim i2 ->
@@ -165,7 +166,7 @@ let rec constr_expr_eq e1 e2 =
| CCast(t1,c1), CCast(t2,c2) ->
constr_expr_eq t1 t2 && cast_expr_eq c1 c2
| CNotation(n1, s1), CNotation(n2, s2) ->
- String.equal n1 n2 &&
+ notation_eq n1 n2 &&
constr_notation_substitution_eq s1 s2
| CPrim i1, CPrim i2 ->
prim_token_eq i1 i2
diff --git a/interp/constrexpr_ops.mli b/interp/constrexpr_ops.mli
index 46aef1c788..61e8aa1b51 100644
--- a/interp/constrexpr_ops.mli
+++ b/interp/constrexpr_ops.mli
@@ -107,8 +107,8 @@ val occur_var_constr_expr : Id.t -> constr_expr -> bool
val split_at_annot : local_binder_expr list -> lident option -> local_binder_expr list * local_binder_expr list
-val ntn_loc : ?loc:Loc.t -> constr_notation_substitution -> string -> (int * int) list
-val patntn_loc : ?loc:Loc.t -> cases_pattern_notation_substitution -> string -> (int * int) list
+val ntn_loc : ?loc:Loc.t -> constr_notation_substitution -> notation -> (int * int) list
+val patntn_loc : ?loc:Loc.t -> cases_pattern_notation_substitution -> notation -> (int * int) list
(** For cases pattern parsing errors *)
val error_invalid_pattern_notation : ?loc:Loc.t -> unit -> 'a
diff --git a/interp/constrextern.ml b/interp/constrextern.ml
index 2538c77722..009894fddb 100644
--- a/interp/constrextern.ml
+++ b/interp/constrextern.ml
@@ -101,7 +101,7 @@ let _show_inactive_notations () =
IRuleSet.iter
(function
| NotationRule (scopt, ntn) ->
- Feedback.msg_notice (str ntn ++ show_scope scopt)
+ Feedback.msg_notice (pr_notation ntn ++ show_scope scopt)
| SynDefRule kn -> Feedback.msg_notice (str (Names.KerName.to_string kn)))
!inactive_notations_table
@@ -113,14 +113,14 @@ let deactivate_notation nr =
| NotationRule (scopt, ntn) ->
match availability_of_notation (scopt, ntn) (scopt, []) with
| None -> user_err ~hdr:"Notation"
- (str ntn ++ spc () ++ str "does not exist"
+ (pr_notation ntn ++ spc () ++ str "does not exist"
++ (match scopt with
| None -> spc () ++ str "in the empty scope."
| Some _ -> show_scope scopt ++ str "."))
| Some _ ->
if IRuleSet.mem nr !inactive_notations_table then
Feedback.msg_warning
- (str "Notation" ++ spc () ++ str ntn ++ spc ()
+ (str "Notation" ++ spc () ++ pr_notation ntn ++ spc ()
++ str "is already inactive" ++ show_scope scopt ++ str ".")
else inactive_notations_table := IRuleSet.add nr !inactive_notations_table
@@ -131,7 +131,7 @@ let reactivate_notation nr =
with Not_found ->
match nr with
| NotationRule (scopt, ntn) ->
- Feedback.msg_warning (str "Notation" ++ spc () ++ str ntn ++ spc ()
+ Feedback.msg_warning (str "Notation" ++ spc () ++ pr_notation ntn ++ spc ()
++ str "is already active" ++ show_scope scopt ++
str ".")
| SynDefRule kn ->
@@ -260,6 +260,14 @@ let insert_pat_alias ?loc p = function
| Anonymous -> p
| Name _ as na -> CAst.make ?loc @@ CPatAlias (p,(CAst.make ?loc na))
+let rec insert_coercion ?loc l c = match l with
+ | [] -> c
+ | ntn::l -> CAst.make ?loc @@ CNotation (ntn,([insert_coercion ?loc l c],[],[],[]))
+
+let rec insert_pat_coercion ?loc l c = match l with
+ | [] -> c
+ | ntn::l -> CAst.make ?loc @@ CPatNotation (ntn,([insert_pat_coercion ?loc l c],[]),[])
+
(**********************************************************************)
(* conversion of references *)
@@ -325,16 +333,16 @@ let is_zero s =
in aux 0
let make_notation_gen loc ntn mknot mkprim destprim l bl =
- match ntn,List.map destprim l with
+ match snd ntn,List.map destprim l with
(* Special case to avoid writing "- 3" for e.g. (Z.opp 3) *)
| "- _", [Some (Numeral (p,true))] when not (is_zero p) ->
assert (bl=[]);
- mknot (loc,ntn,([mknot (loc,"( _ )",l,[])]),[])
+ mknot (loc,ntn,([mknot (loc,(InConstrEntrySomeLevel,"( _ )"),l,[])]),[])
| _ ->
match decompose_notation_key ntn, l with
- | [Terminal "-"; Terminal x], [] when is_number x ->
+ | (InConstrEntrySomeLevel,[Terminal "-"; Terminal x]), [] when is_number x ->
mkprim (loc, Numeral (x,false))
- | [Terminal x], [] when is_number x ->
+ | (InConstrEntrySomeLevel,[Terminal x]), [] when is_number x ->
mkprim (loc, Numeral (x,true))
| _ -> mknot (loc,ntn,l,bl)
@@ -367,31 +375,39 @@ let pattern_printable_in_both_syntax (ind,_ as c) =
(List.for_all is_status_implicit params)&&(List.for_all (fun x -> not (is_status_implicit x)) args)
) impl_st
-let lift f c =
- let loc = c.CAst.loc in
- CAst.make ?loc (f ?loc (DAst.get c))
-
(* Better to use extern_glob_constr composed with injection/retraction ?? *)
-let rec extern_cases_pattern_in_scope (scopes:local_scopes) vars pat =
+let rec extern_cases_pattern_in_scope (custom,scopes as allscopes) vars pat =
try
if !Flags.in_debugger || !Flags.raw_print || !print_no_symbol then raise No_match;
let (na,sc,p) = uninterp_prim_token_cases_pattern pat in
+ match availability_of_entry_coercion custom InConstrEntrySomeLevel with
+ | None -> raise No_match
+ | Some coercion ->
match availability_of_prim_token p sc scopes with
| None -> raise No_match
| Some key ->
let loc = cases_pattern_loc pat in
- insert_pat_alias ?loc (insert_pat_delimiters ?loc (CAst.make ?loc @@ CPatPrim p) key) na
+ insert_pat_coercion ?loc coercion
+ (insert_pat_alias ?loc (insert_pat_delimiters ?loc (CAst.make ?loc @@ CPatPrim p) key) na)
with No_match ->
try
if !Flags.in_debugger || !Flags.raw_print || !print_no_symbol then raise No_match;
- extern_notation_pattern scopes vars pat
+ extern_notation_pattern allscopes vars pat
(uninterp_cases_pattern_notations pat)
with No_match ->
- lift (fun ?loc -> function
- | PatVar (Name id) -> CPatAtom (Some (qualid_of_ident ?loc id))
- | PatVar (Anonymous) -> CPatAtom None
+ let loc = pat.CAst.loc in
+ match DAst.get pat with
+ | PatVar (Name id) when entry_has_ident custom -> CAst.make ?loc (CPatAtom (Some (qualid_of_ident ?loc id)))
+ | pat ->
+ match availability_of_entry_coercion custom InConstrEntrySomeLevel with
+ | None -> raise No_match
+ | Some coercion ->
+ let allscopes = (InConstrEntrySomeLevel,scopes) in
+ let pat = match pat with
+ | PatVar (Name id) -> CAst.make ?loc (CPatAtom (Some (qualid_of_ident ?loc id)))
+ | PatVar (Anonymous) -> CAst.make ?loc (CPatAtom None)
| PatCstr(cstrsp,args,na) ->
- let args = List.map (extern_cases_pattern_in_scope scopes vars) args in
+ let args = List.map (extern_cases_pattern_in_scope allscopes vars) args in
let p =
try
if !Flags.raw_print then raise Exit;
@@ -424,26 +440,32 @@ let rec extern_cases_pattern_in_scope (scopes:local_scopes) vars pat =
match drop_implicits_in_patt (ConstructRef cstrsp) 0 full_args with
| Some true_args -> CPatCstr (c, None, true_args)
| None -> CPatCstr (c, Some full_args, [])
- in (insert_pat_alias ?loc (CAst.make ?loc p) na).v
- ) pat
+ in
+ insert_pat_alias ?loc (CAst.make ?loc p) na
+ in
+ insert_pat_coercion coercion pat
+
and apply_notation_to_pattern ?loc gr ((subst,substlist),(nb_to_drop,more_args))
- (tmp_scope, scopes as allscopes) vars =
+ (custom, (tmp_scope, scopes) as allscopes) vars =
function
| NotationRule (sc,ntn) ->
begin
- match availability_of_notation (sc,ntn) allscopes with
+ match availability_of_entry_coercion custom (fst ntn) with
+ | None -> raise No_match
+ | Some coercion ->
+ match availability_of_notation (sc,ntn) (tmp_scope,scopes) with
(* Uninterpretation is not allowed in current context *)
| None -> raise No_match
(* Uninterpretation is allowed in current context *)
| Some (scopt,key) ->
let scopes' = Option.List.cons scopt scopes in
let l =
- List.map (fun (c,(scopt,scl)) ->
- extern_cases_pattern_in_scope (scopt,scl@scopes') vars c)
+ List.map (fun (c,(subentry,(scopt,scl))) ->
+ extern_cases_pattern_in_scope (subentry,(scopt,scl@scopes')) vars c)
subst in
let ll =
- List.map (fun (c,(scopt,scl)) ->
- let subscope = (scopt,scl@scopes') in
+ List.map (fun (c,(subentry,(scopt,scl))) ->
+ let subscope = (subentry,(scopt,scl@scopes')) in
List.map (extern_cases_pattern_in_scope subscope vars) c)
substlist in
let l2 = List.map (extern_cases_pattern_in_scope allscopes vars) more_args in
@@ -453,14 +475,15 @@ and apply_notation_to_pattern ?loc gr ((subst,substlist),(nb_to_drop,more_args))
|Some true_args -> true_args
|None -> raise No_match
in
- insert_pat_delimiters ?loc
- (make_pat_notation ?loc ntn (l,ll) l2') key
+ insert_pat_coercion coercion
+ (insert_pat_delimiters ?loc
+ (make_pat_notation ?loc ntn (l,ll) l2') key)
end
| SynDefRule kn ->
let qid = shortest_qualid_of_syndef ?loc vars kn in
let l1 =
- List.rev_map (fun (c,(scopt,scl)) ->
- extern_cases_pattern_in_scope (scopt,scl@scopes) vars c)
+ List.rev_map (fun (c,(subentry,(scopt,scl))) ->
+ extern_cases_pattern_in_scope (subentry,(scopt,scl@scopes)) vars c)
subst in
let l2 = List.map (extern_cases_pattern_in_scope allscopes vars) more_args in
let l2' = if !asymmetric_patterns then l2
@@ -471,7 +494,7 @@ and apply_notation_to_pattern ?loc gr ((subst,substlist),(nb_to_drop,more_args))
in
assert (List.is_empty substlist);
mkPat ?loc qid (List.rev_append l1 l2')
-and extern_notation_pattern (tmp_scope,scopes as allscopes) vars t = function
+and extern_notation_pattern allscopes vars t = function
| [] -> raise No_match
| (keyrule,pat,n as _rule)::rules ->
try
@@ -498,35 +521,38 @@ let rec extern_notation_ind_pattern allscopes vars ind args = function
with
No_match -> extern_notation_ind_pattern allscopes vars ind args rules
-let extern_ind_pattern_in_scope (scopes:local_scopes) vars ind args =
+let extern_ind_pattern_in_scope (custom,scopes as allscopes) vars ind args =
(* pboutill: There are letins in pat which is incompatible with notations and
not explicit application. *)
if !Flags.in_debugger||Inductiveops.inductive_has_local_defs ind then
let c = extern_reference vars (IndRef ind) in
- let args = List.map (extern_cases_pattern_in_scope scopes vars) args in
+ let args = List.map (extern_cases_pattern_in_scope allscopes vars) args in
CAst.make @@ CPatCstr (c, Some (add_patt_for_params ind args), [])
else
try
if !Flags.raw_print || !print_no_symbol then raise No_match;
let (sc,p) = uninterp_prim_token_ind_pattern ind args in
+ match availability_of_entry_coercion custom InConstrEntrySomeLevel with
+ | None -> raise No_match
+ | Some coercion ->
match availability_of_prim_token p sc scopes with
| None -> raise No_match
| Some key ->
- insert_pat_delimiters (CAst.make @@ CPatPrim p) key
+ insert_pat_coercion coercion (insert_pat_delimiters (CAst.make @@ CPatPrim p) key)
with No_match ->
try
if !Flags.raw_print || !print_no_symbol then raise No_match;
- extern_notation_ind_pattern scopes vars ind args
+ extern_notation_ind_pattern allscopes vars ind args
(uninterp_ind_pattern_notations ind)
with No_match ->
let c = extern_reference vars (IndRef ind) in
- let args = List.map (extern_cases_pattern_in_scope scopes vars) args in
+ let args = List.map (extern_cases_pattern_in_scope allscopes vars) args in
match drop_implicits_in_patt (IndRef ind) 0 args with
|Some true_args -> CAst.make @@ CPatCstr (c, None, true_args)
|None -> CAst.make @@ CPatCstr (c, Some args, [])
let extern_cases_pattern vars p =
- extern_cases_pattern_in_scope (None,[]) vars p
+ extern_cases_pattern_in_scope (InConstrEntrySomeLevel,(None,[])) vars p
(**********************************************************************)
(* Externalising applications *)
@@ -640,12 +666,12 @@ let extern_app inctx impl (cf,f) us args =
else
explicitize inctx impl (cf, CAst.make @@ CRef (f,us)) args
-let rec fill_arg_scopes args subscopes scopes = match args, subscopes with
+let rec fill_arg_scopes args subscopes (entry,(_,scopes) as all) = match args, subscopes with
| [], _ -> []
| a :: args, scopt :: subscopes ->
- (a, (scopt, scopes)) :: fill_arg_scopes args subscopes scopes
+ (a, (entry, (scopt, scopes))) :: fill_arg_scopes args subscopes all
| a :: args, [] ->
- (a, (None, scopes)) :: fill_arg_scopes args [] scopes
+ (a, (entry, (None, scopes))) :: fill_arg_scopes args [] all
let extern_args extern env args =
let map (arg, argscopes) = lazy (extern argscopes env arg) in
@@ -697,12 +723,15 @@ let rec flatten_application c = match DAst.get c with
(* mapping glob_constr to numerals (in presence of coercions, choose the *)
(* one with no delimiter if possible) *)
-let extern_possible_prim_token scopes r =
+let extern_possible_prim_token (custom,scopes) r =
try
let (sc,n) = uninterp_prim_token r in
+ match availability_of_entry_coercion custom InConstrEntrySomeLevel with
+ | None -> raise No_match
+ | Some coercion ->
match availability_of_prim_token n sc scopes with
| None -> None
- | Some key -> Some (insert_delimiters (CAst.make ?loc:(loc_of_glob_constr r) @@ CPrim n) key)
+ | Some key -> Some (insert_coercion coercion (insert_delimiters (CAst.make ?loc:(loc_of_glob_constr r) @@ CPrim n) key))
with No_match ->
None
@@ -737,7 +766,13 @@ let extern_glob_sort = function
let extern_universes = function
| Some _ as l when !print_universes -> l
| _ -> None
-
+
+let extern_ref vars ref us =
+ extern_global (select_stronger_impargs (implicits_of_global ref))
+ (extern_reference vars ref) (extern_universes us)
+
+let extern_var ?loc id = CRef (qualid_of_ident ?loc id,None)
+
let rec extern inctx scopes vars r =
let r' = remove_coercions inctx r in
try
@@ -748,12 +783,27 @@ let rec extern inctx scopes vars r =
let r'' = flatten_application r' in
if !Flags.raw_print || !print_no_symbol then raise No_match;
extern_notation scopes vars r'' (uninterp_notations r'')
- with No_match -> lift (fun ?loc -> function
- | GRef (ref,us) ->
- extern_global (select_stronger_impargs (implicits_of_global ref))
- (extern_reference vars ref) (extern_universes us)
+ with No_match ->
+ let loc = r'.CAst.loc in
+ match DAst.get r' with
+ | GRef (ref,us) when entry_has_global (fst scopes) -> CAst.make ?loc (extern_ref vars ref us)
+
+ | GVar id when entry_has_ident (fst scopes) -> CAst.make ?loc (extern_var ?loc id)
+
+ | c ->
+
+ match availability_of_entry_coercion (fst scopes) InConstrEntrySomeLevel with
+ | None -> raise No_match
+ | Some coercion ->
- | GVar id -> CRef (qualid_of_ident ?loc id,None)
+ let scopes = (InConstrEntrySomeLevel, snd scopes) in
+ let c = match c with
+
+ (* The remaining cases are only for the constr entry *)
+
+ | GRef (ref,us) -> extern_ref vars ref us
+
+ | GVar id -> extern_var ?loc id
| GEvar (n,[]) when !print_meta_as_hole -> CHole (None, IntroAnonymous, None)
@@ -770,7 +820,7 @@ let rec extern inctx scopes vars r =
(match DAst.get f with
| GRef (ref,us) ->
let subscopes = find_arguments_scope ref in
- let args = fill_arg_scopes args subscopes (snd scopes) in
+ let args = fill_arg_scopes args subscopes scopes in
begin
try
if !Flags.raw_print then raise Exit;
@@ -921,12 +971,13 @@ let rec extern inctx scopes vars r =
| 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) =
- extern true (Notation.current_type_scope_name (),scopes)
+ in insert_coercion coercion (CAst.make ?loc c)
+
+and extern_typ (subentry,(_,scopes)) =
+ extern true (subentry,(Notation.current_type_scope_name (),scopes))
-and sub_extern inctx (_,scopes) = extern inctx (None,scopes)
+and sub_extern inctx (subentry,(_,scopes)) = extern inctx (subentry,(None,scopes))
and factorize_prod scopes vars na bk aty c =
let store, get = set_temporary_memory () in
@@ -1019,7 +1070,7 @@ and extern_eqn inctx scopes vars {CAst.loc;v=(ids,pll,c)} =
let pll = List.map (List.map (extern_cases_pattern_in_scope scopes vars)) pll in
make ?loc (pll,extern inctx scopes vars c)
-and extern_notation (tmp_scope,scopes as allscopes) vars t = function
+and extern_notation (custom,scopes as allscopes) vars t = function
| [] -> raise No_match
| (keyrule,pat,n as _rule)::rules ->
let loc = Glob_ops.loc_of_glob_constr t in
@@ -1066,40 +1117,43 @@ and extern_notation (tmp_scope,scopes as allscopes) vars t = function
let e =
match keyrule with
| NotationRule (sc,ntn) ->
- (match availability_of_notation (sc,ntn) allscopes with
+ (match availability_of_entry_coercion custom (fst ntn) with
+ | None -> raise No_match
+ | Some coercion ->
+ match availability_of_notation (sc,ntn) scopes with
(* Uninterpretation is not allowed in current context *)
| None -> raise No_match
(* Uninterpretation is allowed in current context *)
| Some (scopt,key) ->
- let scopes' = Option.List.cons scopt scopes in
+ let scopes' = Option.List.cons scopt (snd scopes) in
let l =
- List.map (fun (c,(scopt,scl)) ->
+ List.map (fun (c,(subentry,(scopt,scl))) ->
extern (* assuming no overloading: *) true
- (scopt,scl@scopes') vars c)
+ (subentry,(scopt,scl@scopes')) vars c)
terms in
let ll =
- List.map (fun (c,(scopt,scl)) ->
- List.map (extern true (scopt,scl@scopes') vars) c)
+ List.map (fun (c,(subentry,(scopt,scl))) ->
+ List.map (extern true (subentry,(scopt,scl@scopes')) vars) c)
termlists in
let bl =
- List.map (fun (bl,(scopt,scl)) ->
- mkCPatOr (List.map (extern_cases_pattern_in_scope (scopt,scl@scopes') vars) bl))
+ List.map (fun (bl,(subentry,(scopt,scl))) ->
+ mkCPatOr (List.map (extern_cases_pattern_in_scope (subentry,(scopt,scl@scopes')) vars) bl))
binders in
let bll =
- List.map (fun (bl,(scopt,scl)) ->
- pi3 (extern_local_binder (scopt,scl@scopes') vars bl))
+ List.map (fun (bl,(subentry,(scopt,scl))) ->
+ pi3 (extern_local_binder (subentry,(scopt,scl@scopes')) vars bl))
binderlists in
- insert_delimiters (make_notation loc ntn (l,ll,bl,bll)) key)
+ insert_coercion coercion (insert_delimiters (make_notation loc ntn (l,ll,bl,bll)) key))
| SynDefRule kn ->
let l =
- List.map (fun (c,(scopt,scl)) ->
- extern true (scopt,scl@scopes) vars c, None)
+ List.map (fun (c,(subentry,(scopt,scl))) ->
+ extern true (subentry,(scopt,scl@snd scopes)) vars c, None)
terms in
let a = CRef (shortest_qualid_of_syndef ?loc vars kn,None) in
CAst.make ?loc @@ if List.is_empty l then a else CApp ((None, CAst.make a),l) in
if List.is_empty args then e
else
- let args = fill_arg_scopes args argsscopes scopes in
+ let args = fill_arg_scopes args argsscopes allscopes in
let args = extern_args (extern true) vars args in
CAst.make ?loc @@ explicitize false argsimpls (None,e) args
with
@@ -1113,10 +1167,10 @@ and extern_recursion_order scopes vars = function
let extern_glob_constr vars c =
- extern false (None,[]) vars c
+ extern false (InConstrEntrySomeLevel,(None,[])) vars c
let extern_glob_type vars c =
- extern_typ (None,[]) vars c
+ extern_typ (InConstrEntrySomeLevel,(None,[])) vars c
(******************************************************************)
(* Main translation function from constr -> constr_expr *)
@@ -1132,7 +1186,7 @@ let extern_constr_gen lax goal_concl_style scopt env sigma t =
let avoid = if goal_concl_style then vars_of_env env else Id.Set.empty in
let r = Detyping.detype Detyping.Later ~lax:lax goal_concl_style avoid env sigma t in
let vars = vars_of_env env in
- extern false (scopt,[]) vars r
+ extern false (InConstrEntrySomeLevel,(scopt,[])) vars r
let extern_constr_in_scope goal_concl_style scope env sigma t =
extern_constr_gen false goal_concl_style (Some scope) env sigma t
@@ -1153,7 +1207,7 @@ let extern_closed_glob ?lax goal_concl_style env sigma t =
Detyping.detype_closed_glob ?lax goal_concl_style avoid env sigma t
in
let vars = vars_of_env env in
- extern false (None,[]) vars r
+ extern false (InConstrEntrySomeLevel,(None,[])) vars r
(******************************************************************)
(* Main translation function from pattern -> constr_expr *)
@@ -1262,10 +1316,10 @@ let rec glob_of_pat avoid env sigma pat = DAst.make @@ match pat with
| PSort s -> GSort s
let extern_constr_pattern env sigma pat =
- extern true (None,[]) Id.Set.empty (glob_of_pat Id.Set.empty env sigma pat)
+ extern true (InConstrEntrySomeLevel,(None,[])) Id.Set.empty (glob_of_pat Id.Set.empty env sigma pat)
let extern_rel_context where env sigma sign =
let a = detype_rel_context Detyping.Later where Id.Set.empty (names_of_rel_context env,env) sigma sign in
let vars = vars_of_env env in
let a = List.map (extended_glob_local_binder_of_decl) a in
- pi3 (extern_local_binder (None,[]) vars a)
+ pi3 (extern_local_binder (InConstrEntrySomeLevel,(None,[])) vars a)
diff --git a/interp/constrintern.ml b/interp/constrintern.ml
index 4e217b2cdd..1c8d957014 100644
--- a/interp/constrintern.ml
+++ b/interp/constrintern.ml
@@ -218,30 +218,36 @@ let expand_notation_string ntn n =
(* This contracts the special case of "{ _ }" for sumbool, sumor notations *)
(* Remark: expansion of squash at definition is done in metasyntax.ml *)
let contract_curly_brackets ntn (l,ll,bl,bll) =
+ match ntn with
+ | InCustomEntryLevel _,_ -> ntn,(l,ll,bl,bll)
+ | InConstrEntrySomeLevel, ntn ->
let ntn' = ref ntn in
let rec contract_squash n = function
| [] -> []
- | { CAst.v = CNotation ("{ _ }",([a],[],[],[])) } :: l ->
+ | { CAst.v = CNotation ((InConstrEntrySomeLevel,"{ _ }"),([a],[],[],[])) } :: l ->
ntn' := expand_notation_string !ntn' n;
contract_squash n (a::l)
| a :: l ->
a::contract_squash (n+1) l in
let l = contract_squash 0 l in
(* side effect; don't inline *)
- !ntn',(l,ll,bl,bll)
+ (InConstrEntrySomeLevel,!ntn'),(l,ll,bl,bll)
let contract_curly_brackets_pat ntn (l,ll) =
+ match ntn with
+ | InCustomEntryLevel _,_ -> ntn,(l,ll)
+ | InConstrEntrySomeLevel, ntn ->
let ntn' = ref ntn in
let rec contract_squash n = function
| [] -> []
- | { CAst.v = CPatNotation ("{ _ }",([a],[]),[]) } :: l ->
+ | { CAst.v = CPatNotation ((InConstrEntrySomeLevel,"{ _ }"),([a],[]),[]) } :: l ->
ntn' := expand_notation_string !ntn' n;
contract_squash n (a::l)
| a :: l ->
a::contract_squash (n+1) l in
let l = contract_squash 0 l in
(* side effect; don't inline *)
- !ntn',(l,ll)
+ (InConstrEntrySomeLevel,!ntn'),(l,ll)
type intern_env = {
ids: Names.Id.Set.t;
@@ -552,7 +558,7 @@ let find_fresh_name renaming (terms,termlists,binders,binderlists) avoid id =
let is_var store pat =
match DAst.get pat with
- | PatVar na -> store na; true
+ | PatVar na -> ignore(store na); true
| _ -> false
let out_var pat =
@@ -566,7 +572,7 @@ let term_of_name = function
| Name id -> DAst.make (GVar id)
| Anonymous ->
let st = Evar_kinds.Define (not (Program.get_proofs_transparency ())) in
- DAst.make (GHole (Evar_kinds.QuestionMark (st,Anonymous), IntroAnonymous, None))
+ DAst.make (GHole (Evar_kinds.QuestionMark { Evar_kinds.default_question_mark with Evar_kinds.qm_obligation=st }, IntroAnonymous, None))
let traverse_binder intern_pat ntnvars (terms,_,binders,_ as subst) avoid (renaming,env) = function
| Anonymous -> (renaming,env), None, Anonymous
@@ -710,10 +716,12 @@ let instantiate_notation_constr loc intern intern_pat ntnvars subst infos c =
let arg = match arg with
| None -> None
| Some arg ->
- let mk_env (c, (tmp_scope, subscopes)) =
+ let mk_env id (c, (tmp_scope, subscopes)) map =
let nenv = {env with tmp_scope; scopes = subscopes @ env.scopes} in
- let gc = intern nenv c in
- (gc, Some c)
+ try
+ let gc = intern nenv c in
+ Id.Map.add id (gc, Some c) map
+ with GlobalizationError _ -> map
in
let mk_env' (c, (onlyident,(tmp_scope,subscopes))) =
let nenv = {env with tmp_scope; scopes = subscopes @ env.scopes} in
@@ -725,7 +733,7 @@ let instantiate_notation_constr loc intern intern_pat ntnvars subst infos c =
| [pat] -> (glob_constr_of_cases_pattern pat, None)
| _ -> error_cannot_coerce_disjunctive_pattern_term ?loc:c.loc ()
in
- let terms = Id.Map.map mk_env terms in
+ let terms = Id.Map.fold mk_env terms Id.Map.empty in
let binders = Id.Map.map mk_env' binders in
let bindings = Id.Map.fold Id.Map.add terms binders in
Some (Genintern.generic_substitute_notation bindings arg)
@@ -817,7 +825,7 @@ let split_by_type ids subst =
| [] -> assert false
| a::l -> l, Id.Map.add id (a,scl) s in
let (terms,termlists,binders,binderlists),subst =
- List.fold_left (fun ((terms,termlists,binders,binderlists),(terms',termlists',binders',binderlists')) (id,(scl,typ)) ->
+ List.fold_left (fun ((terms,termlists,binders,binderlists),(terms',termlists',binders',binderlists')) (id,((_,scl),typ)) ->
match typ with
| NtnTypeConstr ->
let terms,terms' = bind id scl terms terms' in
@@ -845,10 +853,10 @@ let split_by_type ids subst =
subst
let split_by_type_pat ?loc ids subst =
- let bind id scl l s =
+ let bind id (_,scopes) l s =
match l with
| [] -> assert false
- | a::l -> l, Id.Map.add id (a,scl) s in
+ | a::l -> l, Id.Map.add id (a,scopes) s in
let (terms,termlists),subst =
List.fold_left (fun ((terms,termlists),(terms',termlists')) (id,(scl,typ)) ->
match typ with
@@ -864,7 +872,7 @@ let split_by_type_pat ?loc ids subst =
subst
let make_subst ids l =
- let fold accu (id, scl) a = Id.Map.add id (a, scl) accu in
+ let fold accu (id, scopes) a = Id.Map.add id (a, scopes) accu in
List.fold_left2 fold Id.Map.empty ids l
let intern_notation intern env ntnvars loc ntn fullargs =
@@ -1368,7 +1376,8 @@ let sort_fields ~complete loc fields completer =
(* the order does not matter as we sort them next,
List.rev_* is just for efficiency *)
let remaining_fields =
- let complete_field (idx, _field_ref) = (idx, completer idx) in
+ let complete_field (idx, field_ref) = (idx,
+ completer idx field_ref record.Recordops.s_CONST) in
List.rev_map complete_field remaining_projs in
List.rev_append remaining_fields acc
in
@@ -1522,7 +1531,7 @@ let drop_notations_pattern looked_for genv =
| CPatAlias (p, id) -> DAst.make ?loc @@ RCPatAlias (in_pat top scopes p, id)
| CPatRecord l ->
let sorted_fields =
- sort_fields ~complete:false loc l (fun _idx -> CAst.make ?loc @@ CPatAtom None) in
+ sort_fields ~complete:false loc l (fun _idx fieldname constructor -> CAst.make ?loc @@ CPatAtom None) in
begin match sorted_fields with
| None -> DAst.make ?loc @@ RCPatAtom None
| Some (n, head, pl) ->
@@ -1552,11 +1561,11 @@ let drop_notations_pattern looked_for genv =
(* but not scopes in expl_pl *)
let (argscs1,_) = find_remaining_scopes expl_pl pl g in
DAst.make ?loc @@ RCPatCstr (g, List.map2 (in_pat_sc scopes) argscs1 expl_pl @ List.map (in_pat false scopes) pl, [])
- | CPatNotation ("- _",([a],[]),[]) when is_non_zero_pat a ->
+ | CPatNotation ((InConstrEntrySomeLevel,"- _"),([a],[]),[]) when is_non_zero_pat a ->
let p = match a.CAst.v with CPatPrim (Numeral (p, _)) -> p | _ -> assert false in
let pat, _df = Notation.interp_prim_token_cases_pattern_expr ?loc (ensure_kind false loc) (Numeral (p,false)) scopes in
rcp_of_glob scopes pat
- | CPatNotation ("( _ )",([a],[]),[]) ->
+ | CPatNotation ((InConstrEntrySomeLevel,"( _ )"),([a],[]),[]) ->
in_pat top scopes a
| CPatNotation (ntn,fullargs,extrargs) ->
let ntn,(terms,termlists) = contract_curly_brackets_pat ntn fullargs in
@@ -1869,10 +1878,10 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
DAst.make ?loc @@
GLetIn (na.CAst.v, inc1, int,
intern (push_name_env ntnvars (impls_term_list inc1) env na) c2)
- | CNotation ("- _", ([a],[],[],[])) when is_non_zero a ->
+ | CNotation ((InConstrEntrySomeLevel,"- _"), ([a],[],[],[])) when is_non_zero a ->
let p = match a.CAst.v with CPrim (Numeral (p, _)) -> p | _ -> assert false in
intern env (CAst.make ?loc @@ CPrim (Numeral (p,false)))
- | CNotation ("( _ )",([a],[],[],[])) -> intern env a
+ | CNotation ((InConstrEntrySomeLevel,"( _ )"),([a],[],[],[])) -> intern env a
| CNotation (ntn,args) ->
intern_notation intern env ntnvars loc ntn args
| CGeneralization (b,a,c) ->
@@ -1888,9 +1897,9 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
intern_applied_reference intern env (Environ.named_context globalenv)
lvar us args ref
in
- (* Rem: GApp(_,f,[]) stands for @f *)
- DAst.make ?loc @@
- GApp (f, intern_args env args_scopes (List.map fst args))
+ (* Rem: GApp(_,f,[]) stands for @f *)
+ if args = [] then DAst.make ?loc @@ GApp (f,[]) else
+ smart_gapp f loc (intern_args env args_scopes (List.map fst args))
| CApp ((isproj,f), args) ->
let f,args = match f.CAst.v with
@@ -1916,8 +1925,16 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
let st = Evar_kinds.Define (not (Program.get_proofs_transparency ())) in
let fields =
sort_fields ~complete:true loc fs
- (fun _idx -> CAst.make ?loc @@ CHole (Some (Evar_kinds.QuestionMark (st,Anonymous)),
- IntroAnonymous, None))
+ (fun _idx fieldname constructorname ->
+ let open Evar_kinds in
+ let fieldinfo : Evar_kinds.record_field =
+ {fieldname=fieldname; recordname=inductive_of_constructor constructorname}
+ in
+ CAst.make ?loc @@ CHole (Some
+ (Evar_kinds.QuestionMark { Evar_kinds.default_question_mark with
+ Evar_kinds.qm_obligation=st;
+ Evar_kinds.qm_record_field=Some fieldinfo
+ }) , IntroAnonymous, None))
in
begin
match fields with
@@ -2000,7 +2017,7 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
let st = Evar_kinds.Define (not (Program.get_proofs_transparency ())) in
(match naming with
| IntroIdentifier id -> Evar_kinds.NamedHole id
- | _ -> Evar_kinds.QuestionMark (st,Anonymous))
+ | _ -> Evar_kinds.QuestionMark { Evar_kinds.default_question_mark with Evar_kinds.qm_obligation=st; })
| Some k -> k
in
let solve = match solve with
@@ -2048,6 +2065,7 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
| CProj (pr, c) ->
match intern_reference pr with
| ConstRef p ->
+ let p = Option.get @@ Recordops.find_primitive_projection p in
DAst.make ?loc @@ GProj (Projection.make p false, intern env c)
| _ ->
raise (InternalizationError (loc,IllegalMetavariable)) (* FIXME *)
diff --git a/interp/declare.ml b/interp/declare.ml
index c6de5b2a1b..a82e6b35a6 100644
--- a/interp/declare.ml
+++ b/interp/declare.ml
@@ -382,39 +382,44 @@ let inInductive : inductive_obj -> obj =
discharge_function = discharge_inductive;
rebuild_function = infer_inductive_subtyping }
+let declare_one_projection univs (mind,_ as ind) ~proj_npars proj_arg label (term,types) =
+ let id = Label.to_id label in
+ let p = Projection.Repr.make ind ~proj_npars ~proj_arg label in
+ Recordops.declare_primitive_projection p;
+ (* ^ needs to happen before declaring the constant, otherwise
+ Heads gets confused. *)
+ let univs = match univs with
+ | Monomorphic_ind_entry _ ->
+ (** Global constraints already defined through the inductive *)
+ Monomorphic_const_entry Univ.ContextSet.empty
+ | Polymorphic_ind_entry ctx ->
+ Polymorphic_const_entry ctx
+ | Cumulative_ind_entry ctx ->
+ Polymorphic_const_entry (Univ.CumulativityInfo.univ_context ctx)
+ in
+ let term, types = match univs with
+ | Monomorphic_const_entry _ -> term, types
+ | Polymorphic_const_entry ctx ->
+ let u = Univ.UContext.instance ctx in
+ Vars.subst_instance_constr u term, Vars.subst_instance_constr u types
+ in
+ let entry = definition_entry ~types ~univs term in
+ ignore(declare_constant id (DefinitionEntry entry, IsDefinition StructureComponent))
+
let declare_projections univs mind =
- (** FIXME: handle mutual records *)
- let mind = (mind, 0) in
let env = Global.env () in
- let spec,_ = Inductive.lookup_mind_specif env mind in
- match spec.mind_record with
- | PrimRecord info ->
- let _, kns, _ = info.(0) in
- let projs = Inductiveops.compute_projections env mind in
- Array.iter2 (fun kn (term, types) ->
- let id = Label.to_id (Constant.label kn) in
- let univs = match univs with
- | Monomorphic_ind_entry _ ->
- (** Global constraints already defined through the inductive *)
- Monomorphic_const_entry Univ.ContextSet.empty
- | Polymorphic_ind_entry ctx ->
- Polymorphic_const_entry ctx
- | Cumulative_ind_entry ctx ->
- Polymorphic_const_entry (Univ.CumulativityInfo.univ_context ctx)
- in
- let term, types = match univs with
- | Monomorphic_const_entry _ -> term, types
- | Polymorphic_const_entry ctx ->
- let u = Univ.UContext.instance ctx in
- Vars.subst_instance_constr u term, Vars.subst_instance_constr u types
- in
- let entry = definition_entry ~types ~univs term in
- let kn' = declare_constant id (DefinitionEntry entry, IsDefinition StructureComponent) in
- assert (Constant.equal kn kn')
- ) kns projs;
- true, true
- | FakeRecord -> true,false
- | NotRecord -> false,false
+ let mib = Environ.lookup_mind mind env in
+ match mib.mind_record with
+ | PrimRecord info ->
+ let iter_ind i (_, labs, _) =
+ let ind = (mind, i) in
+ let projs = Inductiveops.compute_projections env ind in
+ Array.iter2_i (declare_one_projection univs ind ~proj_npars:mib.mind_nparams) labs projs
+ in
+ let () = Array.iteri iter_ind info in
+ true
+ | FakeRecord -> false
+ | NotRecord -> false
(* for initial declaration *)
let declare_mind mie =
@@ -423,7 +428,7 @@ let declare_mind mie =
| [] -> anomaly (Pp.str "cannot declare an empty list of inductives.") in
let (sp,kn as oname) = add_leaf id (inInductive ([],mie)) in
let mind = Global.mind_of_delta_kn kn in
- let isrecord,isprim = declare_projections mie.mind_entry_universes mind in
+ let isprim = declare_projections mie.mind_entry_universes mind in
declare_mib_implicits mind;
declare_inductive_argument_scopes mind mie;
oname, isprim
@@ -466,24 +471,20 @@ let assumption_message id =
discussion on coqdev: "Chapter 4 of the Reference Manual", 8/10/2015) *)
Flags.if_verbose Feedback.msg_info (Id.print id ++ str " is declared")
-(** Global universe names, in a different summary *)
-
-type universe_context_decl = polymorphic * Univ.ContextSet.t
-
-let cache_universe_context (p, ctx) =
- Global.push_context_set p ctx;
- if p then Lib.add_section_context ctx
+(** Monomorphic universes need to survive sections. *)
-let input_universe_context : universe_context_decl -> Libobject.obj =
+let input_universe_context : Univ.ContextSet.t -> Libobject.obj =
declare_object
- { (default_object "Global universe context state") with
- cache_function = (fun (na, pi) -> cache_universe_context pi);
- load_function = (fun _ (_, pi) -> cache_universe_context pi);
- discharge_function = (fun (_, (p, _ as x)) -> if p then None else Some x);
- classify_function = (fun a -> Keep a) }
+ { (default_object "Monomorphic section universes") with
+ cache_function = (fun (na, uctx) -> Global.push_context_set false uctx);
+ discharge_function = (fun (_, x) -> Some x);
+ classify_function = (fun a -> Dispose) }
let declare_universe_context poly ctx =
- Lib.add_anonymous_leaf (input_universe_context (poly, ctx))
+ if poly then
+ (Global.push_context_set true ctx; Lib.add_section_context ctx)
+ else
+ Lib.add_anonymous_leaf (input_universe_context ctx)
(** Global universes are not substitutive objects but global objects
bound at the *library* or *module* level. The polymorphic flag is
@@ -592,27 +593,8 @@ let do_universe poly l =
ignore(Lib.add_leaf id (input_universe (src, lev))))
l
-type constraint_decl = polymorphic * Univ.Constraint.t
-
-let cache_constraints (na, (p, c)) =
- let ctx =
- Univ.ContextSet.add_constraints c
- Univ.ContextSet.empty (* No declared universes here, just constraints *)
- in cache_universe_context (p,ctx)
-
-let discharge_constraints (_, (p, c as a)) =
- if p then None else Some a
-
-let input_constraints : constraint_decl -> Libobject.obj =
- let open Libobject in
- declare_object
- { (default_object "Global universe constraints") with
- cache_function = cache_constraints;
- load_function = (fun _ -> cache_constraints);
- discharge_function = discharge_constraints;
- classify_function = (fun a -> Keep a) }
-
let do_constraint poly l =
+ let open Univ in
let u_of_id x =
let level = Pretyping.interp_known_glob_level (Evd.from_env (Global.env ())) x in
UnivNames.is_polymorphic level, level
@@ -634,7 +616,8 @@ let do_constraint poly l =
let constraints = List.fold_left (fun acc (l, d, r) ->
let p, lu = u_of_id l and p', ru = u_of_id r in
check_poly p p';
- Univ.Constraint.add (lu, d, ru) acc)
- Univ.Constraint.empty l
+ Constraint.add (lu, d, ru) acc)
+ Constraint.empty l
in
- Lib.add_anonymous_leaf (input_constraints (poly, constraints))
+ let uctx = ContextSet.add_constraints constraints ContextSet.empty in
+ declare_universe_context poly uctx
diff --git a/interp/dumpglob.ml b/interp/dumpglob.ml
index 5bf46282fd..ccad6b19eb 100644
--- a/interp/dumpglob.ml
+++ b/interp/dumpglob.ml
@@ -167,7 +167,7 @@ let dump_modref ?loc mp ty =
let dump_libref ?loc dp ty =
dump_ref ?loc (Names.DirPath.to_string dp) "<>" "<>" ty
-let cook_notation df sc =
+let cook_notation (from,df) sc =
(* We encode notations so that they are space-free and still human-readable *)
(* - all spaces are replaced by _ *)
(* - all _ denoting a non-terminal symbol are replaced by x *)
@@ -203,7 +203,9 @@ let cook_notation df sc =
if !i <= l then (set ntn !j '_'; incr j; incr i)
done;
let df = Bytes.sub_string ntn 0 !j in
- match sc with Some sc -> ":" ^ sc ^ ":" ^ df | _ -> "::" ^ df
+ let df_sc = match sc with Some sc -> ":" ^ sc ^ ":" ^ df | _ -> "::" ^ df in
+ let from_df_sc = match from with Constrexpr.InCustomEntryLevel (from,_) -> ":" ^ from ^ df_sc | Constrexpr.InConstrEntrySomeLevel -> ":" ^ df_sc in
+ from_df_sc
let dump_notation_location posl df (((path,secpath),_),sc) =
if dump () then
diff --git a/interp/impargs.ml b/interp/impargs.ml
index 8aa1e62504..e542b818f6 100644
--- a/interp/impargs.ml
+++ b/interp/impargs.ml
@@ -689,8 +689,8 @@ let check_rigidity isrigid =
user_err (strbrk "Multiple sequences of implicit arguments available only for references that cannot be applied to an arbitrarily large number of arguments.")
let projection_implicits env p impls =
- let pb = Environ.lookup_projection p env in
- CList.skipn_at_least pb.Declarations.proj_npars impls
+ let npars = Projection.npars p in
+ CList.skipn_at_least npars impls
let declare_manual_implicits local ref ?enriching l =
let flags = !implicit_args in
diff --git a/interp/implicit_quantifiers.ml b/interp/implicit_quantifiers.ml
index 83ad9af338..4f3037b1fc 100644
--- a/interp/implicit_quantifiers.ml
+++ b/interp/implicit_quantifiers.ml
@@ -22,7 +22,7 @@ open Libobject
open Nameops
open Context.Rel.Declaration
-exception MismatchedContextInstance of Environ.env * Typeclasses_errors.contexts * constr_expr list * Context.Rel.t (* found, expected *)
+exception MismatchedContextInstance of Environ.env * Typeclasses_errors.contexts * constr_expr list * Constr.rel_context (* found, expected *)
let mismatched_ctx_inst_err env c n m = raise (MismatchedContextInstance (env, c, n, m))
module RelDecl = Context.Rel.Declaration
@@ -98,7 +98,7 @@ let free_vars_of_constr_expr c ?(bound=Id.Set.empty) l =
let rec aux bdvars l c = match CAst.(c.v) with
| CRef (qid,_) when qualid_is_ident qid ->
found c.CAst.loc (qualid_basename qid) bdvars l
- | CNotation ("{ _ : _ | _ }", ({ CAst.v = CRef (qid,_) } :: _, [], [], [])) when
+ | CNotation ((InConstrEntrySomeLevel,"{ _ : _ | _ }"), ({ CAst.v = CRef (qid,_) } :: _, [], [], [])) when
qualid_is_ident qid && not (Id.Set.mem (qualid_basename qid) bdvars) ->
Constrexpr_ops.fold_constr_expr_with_binders (fun a l -> Id.Set.add a l) aux (Id.Set.add (qualid_basename qid) bdvars) l c
| _ -> Constrexpr_ops.fold_constr_expr_with_binders (fun a l -> Id.Set.add a l) aux bdvars l c
diff --git a/interp/implicit_quantifiers.mli b/interp/implicit_quantifiers.mli
index a8492095ec..437fef1753 100644
--- a/interp/implicit_quantifiers.mli
+++ b/interp/implicit_quantifiers.mli
@@ -38,14 +38,14 @@ val make_fresh : Id.Set.t -> Environ.env -> Id.t -> Id.t
val implicits_of_glob_constr : ?with_products:bool -> Glob_term.glob_constr -> Impargs.manual_implicits
val combine_params_freevar :
- Id.Set.t -> GlobRef.t option * Context.Rel.Declaration.t ->
+ Id.Set.t -> GlobRef.t option * Constr.rel_declaration ->
Constrexpr.constr_expr * Id.Set.t
val implicit_application : Id.Set.t -> ?allow_partial:bool ->
- (Id.Set.t -> GlobRef.t option * Context.Rel.Declaration.t ->
+ (Id.Set.t -> GlobRef.t option * Constr.rel_declaration ->
Constrexpr.constr_expr * Id.Set.t) ->
constr_expr -> constr_expr * Id.Set.t
(* Should be likely located elsewhere *)
-exception MismatchedContextInstance of Environ.env * Typeclasses_errors.contexts * constr_expr list * Context.Rel.t (* found, expected *)
-val mismatched_ctx_inst_err : Environ.env -> Typeclasses_errors.contexts -> constr_expr list -> Context.Rel.t -> 'a
+exception MismatchedContextInstance of Environ.env * Typeclasses_errors.contexts * constr_expr list * Constr.rel_context (* found, expected *)
+val mismatched_ctx_inst_err : Environ.env -> Typeclasses_errors.contexts -> constr_expr list -> Constr.rel_context -> 'a
diff --git a/interp/notation.ml b/interp/notation.ml
index 05fcd0e7f5..625d072b9f 100644
--- a/interp/notation.ml
+++ b/interp/notation.ml
@@ -39,6 +39,30 @@ open Context.Named.Declaration
expression, set this scope to be the current scope
*)
+let notation_entry_eq s1 s2 = match (s1,s2) with
+| InConstrEntry, InConstrEntry -> true
+| InCustomEntry s1, InCustomEntry s2 -> String.equal s1 s2
+| (InConstrEntry | InCustomEntry _), _ -> false
+
+let notation_entry_level_eq s1 s2 = match (s1,s2) with
+| InConstrEntrySomeLevel, InConstrEntrySomeLevel -> true
+| InCustomEntryLevel (s1,n1), InCustomEntryLevel (s2,n2) -> String.equal s1 s2 && n1 = n2
+| (InConstrEntrySomeLevel | InCustomEntryLevel _), _ -> false
+
+let notation_eq (from1,ntn1) (from2,ntn2) =
+ notation_entry_level_eq from1 from2 && String.equal ntn1 ntn2
+
+let pr_notation (from,ntn) = qstring ntn ++ match from with InConstrEntrySomeLevel -> mt () | InCustomEntryLevel (s,n) -> str " in custom " ++ str s
+
+module NotationOrd =
+ struct
+ type t = notation
+ let compare = Pervasives.compare
+ end
+
+module NotationSet = Set.Make(NotationOrd)
+module NotationMap = CMap.Make(NotationOrd)
+
(**********************************************************************)
(* Scope of symbols *)
@@ -51,7 +75,7 @@ type notation_data = {
}
type scope = {
- notations: notation_data String.Map.t;
+ notations: notation_data NotationMap.t;
delimiters: delimiters option
}
@@ -62,7 +86,7 @@ let scope_map = ref String.Map.empty
let delimiters_map = ref String.Map.empty
let empty_scope = {
- notations = String.Map.empty;
+ notations = NotationMap.empty;
delimiters = None
}
@@ -71,6 +95,9 @@ let default_scope = "" (* empty name, not available from outside *)
let init_scope_map () =
scope_map := String.Map.add default_scope empty_scope !scope_map
+(**********************************************************************)
+(* Operations on scopes *)
+
let declare_scope scope =
try let _ = String.Map.find scope !scope_map in ()
with Not_found ->
@@ -101,12 +128,12 @@ let normalize_scope sc =
(**********************************************************************)
(* The global stack of scopes *)
-type scope_elem = Scope of scope_name | SingleNotation of string
+type scope_elem = Scope of scope_name | SingleNotation of notation
type scopes = scope_elem list
let scope_eq s1 s2 = match s1, s2 with
-| Scope s1, Scope s2
-| SingleNotation s1, SingleNotation s2 -> String.equal s1 s2
+| Scope s1, Scope s2 -> String.equal s1 s2
+| SingleNotation s1, SingleNotation s2 -> notation_eq s1 s2
| Scope _, SingleNotation _
| SingleNotation _, Scope _ -> false
@@ -158,8 +185,6 @@ let push_scope sc scopes = Scope sc :: scopes
let push_scopes = List.fold_right push_scope
-type local_scopes = tmp_scope_name option * scope_name list
-
let make_current_scopes (tmp_scope,scopes) =
Option.fold_right push_scope tmp_scope (push_scopes scopes !scope_stack)
@@ -376,7 +401,7 @@ let rec find_without_delimiters find (ntn_scope,ntn) = function
end
| SingleNotation ntn' :: scopes ->
begin match ntn_scope, ntn with
- | None, Some ntn when String.equal ntn ntn' ->
+ | None, Some ntn when notation_eq ntn ntn' ->
Some (None, None)
| _ ->
find_without_delimiters find (ntn_scope,ntn) scopes
@@ -390,7 +415,7 @@ let rec find_without_delimiters find (ntn_scope,ntn) = function
let warn_notation_overridden =
CWarnings.create ~name:"notation-overridden" ~category:"parsing"
(fun (ntn,which_scope) ->
- str "Notation" ++ spc () ++ str ntn ++ spc ()
+ str "Notation" ++ spc () ++ pr_notation ntn ++ spc ()
++ strbrk "was already used" ++ which_scope ++ str ".")
let declare_notation_interpretation ntn scopt pat df ~onlyprint =
@@ -398,7 +423,7 @@ let declare_notation_interpretation ntn scopt pat df ~onlyprint =
let sc = find_scope scope in
if not onlyprint then begin
let () =
- if String.Map.mem ntn sc.notations then
+ if NotationMap.mem ntn sc.notations then
let which_scope = match scopt with
| None -> mt ()
| Some _ -> spc () ++ strbrk "in scope" ++ spc () ++ str scope in
@@ -408,7 +433,7 @@ let declare_notation_interpretation ntn scopt pat df ~onlyprint =
not_interp = pat;
not_location = df;
} in
- let sc = { sc with notations = String.Map.add ntn notdata sc.notations } in
+ let sc = { sc with notations = NotationMap.add ntn notdata sc.notations } in
scope_map := String.Map.add scope sc !scope_map
end;
begin match scopt with
@@ -425,7 +450,7 @@ let rec find_interpretation ntn find = function
| Scope scope :: scopes ->
(try let (pat,df) = find scope in pat,(df,Some scope)
with Not_found -> find_interpretation ntn find scopes)
- | SingleNotation ntn'::scopes when String.equal ntn' ntn ->
+ | SingleNotation ntn'::scopes when notation_eq ntn' ntn ->
(try let (pat,df) = find default_scope in pat,(df,None)
with Not_found ->
(* e.g. because single notation only for constr, not cases_pattern *)
@@ -434,12 +459,12 @@ let rec find_interpretation ntn find = function
find_interpretation ntn find scopes
let find_notation ntn sc =
- let n = String.Map.find ntn (find_scope sc).notations in
+ let n = NotationMap.find ntn (find_scope sc).notations in
(n.not_interp, n.not_location)
let notation_of_prim_token = function
- | Numeral (n,true) -> n
- | Numeral (n,false) -> "- "^n
+ | Numeral (n,true) -> InConstrEntrySomeLevel, n
+ | Numeral (n,false) -> InConstrEntrySomeLevel, "- "^n
| String _ -> raise Not_found
let find_prim_token check_allowed ?loc p sc =
@@ -459,13 +484,13 @@ let find_prim_token check_allowed ?loc p sc =
let interp_prim_token_gen ?loc g p local_scopes =
let scopes = make_current_scopes local_scopes in
- let p_as_ntn = try notation_of_prim_token p with Not_found -> "" in
+ let p_as_ntn = try notation_of_prim_token p with Not_found -> InConstrEntrySomeLevel,"" in
try find_interpretation p_as_ntn (find_prim_token ?loc g p) scopes
with Not_found ->
user_err ?loc ~hdr:"interp_prim_token"
((match p with
| Numeral _ ->
- str "No interpretation for numeral " ++ str (notation_of_prim_token p)
+ str "No interpretation for numeral " ++ pr_notation (notation_of_prim_token p)
| String s -> str "No interpretation for string " ++ qs s) ++ str ".")
let interp_prim_token ?loc =
@@ -490,7 +515,7 @@ let interp_notation ?loc ntn local_scopes =
try find_interpretation ntn (find_notation ntn) scopes
with Not_found ->
user_err ?loc
- (str "Unknown interpretation for notation \"" ++ str ntn ++ str "\".")
+ (str "Unknown interpretation for notation " ++ pr_notation ntn ++ str ".")
let uninterp_notations c =
List.map_append (fun key -> keymap_find key !notations_key_table)
@@ -504,9 +529,125 @@ let uninterp_ind_pattern_notations ind =
let availability_of_notation (ntn_scope,ntn) scopes =
let f scope =
- String.Map.mem ntn (String.Map.find scope !scope_map).notations in
+ NotationMap.mem ntn (String.Map.find scope !scope_map).notations in
find_without_delimiters f (ntn_scope,Some ntn) (make_current_scopes scopes)
+(* We support coercions from a custom entry at some level to an entry
+ at some level (possibly the same), and from and to the constr entry. E.g.:
+
+ Notation "[ expr ]" := expr (expr custom group at level 1).
+ Notation "( x )" := x (in custom group at level 0, x at level 1).
+ Notation "{ x }" := x (in custom group at level 0, x constr).
+
+ Supporting any level is maybe overkill in that coercions are
+ commonly from the lowest level of the source entry to the highest
+ level of the target entry. *)
+
+type entry_coercion = notation list
+
+module EntryCoercionOrd =
+ struct
+ type t = notation_entry * notation_entry
+ let compare = Pervasives.compare
+ end
+
+module EntryCoercionMap = Map.Make(EntryCoercionOrd)
+
+let entry_coercion_map = ref EntryCoercionMap.empty
+
+let level_ord lev lev' =
+ match lev, lev' with
+ | None, _ -> true
+ | _, None -> true
+ | Some n, Some n' -> n <= n'
+
+let rec search nfrom nto = function
+ | [] -> raise Not_found
+ | ((pfrom,pto),coe)::l ->
+ if level_ord pfrom nfrom && level_ord nto pto then coe else search nfrom nto l
+
+let decompose_custom_entry = function
+ | InConstrEntrySomeLevel -> InConstrEntry, None
+ | InCustomEntryLevel (s,n) -> InCustomEntry s, Some n
+
+let availability_of_entry_coercion entry entry' =
+ let entry, lev = decompose_custom_entry entry in
+ let entry', lev' = decompose_custom_entry entry' in
+ if notation_entry_eq entry entry' && level_ord lev' lev then Some []
+ else
+ try Some (search lev lev' (EntryCoercionMap.find (entry,entry') !entry_coercion_map))
+ with Not_found -> None
+
+let better_path ((lev1,lev2),path) ((lev1',lev2'),path') =
+ (* better = shorter and lower source and higher target *)
+ level_ord lev1 lev1' && level_ord lev2' lev2 && List.length path <= List.length path'
+
+let shorter_path (_,path) (_,path') =
+ List.length path <= List.length path'
+
+let rec insert_coercion_path path = function
+ | [] -> [path]
+ | path'::paths as allpaths ->
+ (* If better or equal we keep the more recent one *)
+ if better_path path path' then path::paths
+ else if better_path path' path then allpaths
+ else if shorter_path path path' then path::allpaths
+ else path'::insert_coercion_path path paths
+
+let declare_entry_coercion (entry,_ as ntn) entry' =
+ let entry, lev = decompose_custom_entry entry in
+ let entry', lev' = decompose_custom_entry entry' in
+ (* Transitive closure *)
+ let toaddleft =
+ EntryCoercionMap.fold (fun (entry'',entry''') paths l ->
+ List.fold_right (fun ((lev'',lev'''),path) l ->
+ if notation_entry_eq entry entry''' && level_ord lev lev''' &&
+ not (notation_entry_eq entry' entry'')
+ then ((entry'',entry'),((lev'',lev'),path@[ntn]))::l else l) paths l)
+ !entry_coercion_map [] in
+ let toaddright =
+ EntryCoercionMap.fold (fun (entry'',entry''') paths l ->
+ List.fold_right (fun ((lev'',lev'''),path) l ->
+ if entry' = entry'' && level_ord lev' lev'' && entry <> entry'''
+ then ((entry,entry'''),((lev,lev'''),path@[ntn]))::l else l) paths l)
+ !entry_coercion_map [] in
+ entry_coercion_map :=
+ List.fold_right (fun (pair,path) ->
+ let olds = try EntryCoercionMap.find pair !entry_coercion_map with Not_found -> [] in
+ EntryCoercionMap.add pair (insert_coercion_path path olds))
+ (((entry,entry'),((lev,lev'),[ntn]))::toaddright@toaddleft)
+ !entry_coercion_map
+
+let entry_has_global_map = ref String.Map.empty
+
+let declare_custom_entry_has_global s n =
+ try
+ let p = String.Map.find s !entry_has_global_map in
+ user_err (str "Custom entry " ++ str s ++
+ str " has already a rule for global references at level " ++ int p ++ str ".")
+ with Not_found ->
+ entry_has_global_map := String.Map.add s n !entry_has_global_map
+
+let entry_has_global = function
+ | InConstrEntrySomeLevel -> true
+ | InCustomEntryLevel (s,n) ->
+ try String.Map.find s !entry_has_global_map <= n with Not_found -> false
+
+let entry_has_ident_map = ref String.Map.empty
+
+let declare_custom_entry_has_ident s n =
+ try
+ let p = String.Map.find s !entry_has_ident_map in
+ user_err (str "Custom entry " ++ str s ++
+ str " has already a rule for global references at level " ++ int p ++ str ".")
+ with Not_found ->
+ entry_has_ident_map := String.Map.add s n !entry_has_ident_map
+
+let entry_has_ident = function
+ | InConstrEntrySomeLevel -> true
+ | InCustomEntryLevel (s,n) ->
+ try String.Map.find s !entry_has_ident_map <= n with Not_found -> false
+
let uninterp_prim_token c =
try
let (sc,numpr,_) =
@@ -565,7 +706,8 @@ let ntpe_eq t1 t2 = match t1, t2 with
| NtnTypeBinderList, NtnTypeBinderList -> true
| (NtnTypeConstr | NtnTypeBinder _ | NtnTypeConstrList | NtnTypeBinderList), _ -> false
-let var_attributes_eq (_, (sc1, tp1)) (_, (sc2, tp2)) =
+let var_attributes_eq (_, ((entry1, sc1), tp1)) (_, ((entry2, sc2), tp2)) =
+ notation_entry_level_eq entry1 entry2 &&
pair_eq (Option.equal String.equal) (List.equal String.equal) sc1 sc2 &&
ntpe_eq tp1 tp2
@@ -577,7 +719,7 @@ let exists_notation_in_scope scopt ntn onlyprint r =
let scope = match scopt with Some s -> s | None -> default_scope in
try
let sc = String.Map.find scope !scope_map in
- let n = String.Map.find ntn sc.notations in
+ let n = NotationMap.find ntn sc.notations in
interpretation_eq n.not_interp r
with Not_found -> false
@@ -793,10 +935,10 @@ let rec string_of_symbol = function
let l = List.flatten (List.map string_of_symbol l) in "_"::l@".."::l@["_"]
| Break _ -> []
-let make_notation_key symbols =
- String.concat " " (List.flatten (List.map string_of_symbol symbols))
+let make_notation_key from symbols =
+ (from,String.concat " " (List.flatten (List.map string_of_symbol symbols)))
-let decompose_notation_key s =
+let decompose_notation_key (from,s) =
let len = String.length s in
let rec decomp_ntn dirs n =
if n>=len then List.rev dirs else
@@ -811,7 +953,7 @@ let decompose_notation_key s =
| s -> Terminal (String.drop_simple_quotes s) in
decomp_ntn (tok::dirs) (pos+1)
in
- decomp_ntn [] 0
+ from, decomp_ntn [] 0
(************)
(* Printing *)
@@ -840,14 +982,14 @@ let pr_notation_info prglob ntn c =
let pr_named_scope prglob scope sc =
(if String.equal scope default_scope then
- match String.Map.cardinal sc.notations with
+ match NotationMap.cardinal sc.notations with
| 0 -> str "No lonely notation"
| n -> str "Lonely notation" ++ (if Int.equal n 1 then mt() else str"s")
else
str "Scope " ++ str scope ++ fnl () ++ pr_delimiters_info sc.delimiters)
++ fnl ()
++ pr_scope_classes scope
- ++ String.Map.fold
+ ++ NotationMap.fold
(fun ntn { not_interp = (_, r); not_location = (_, df) } strm ->
pr_notation_info prglob df r ++ fnl () ++ strm)
sc.notations (mt ())
@@ -862,11 +1004,11 @@ let pr_scopes prglob =
let rec find_default ntn = function
| [] -> None
| Scope scope :: scopes ->
- if String.Map.mem ntn (find_scope scope).notations then
+ if NotationMap.mem ntn (find_scope scope).notations then
Some scope
else find_default ntn scopes
| SingleNotation ntn' :: scopes ->
- if String.equal ntn ntn' then Some default_scope
+ if notation_eq ntn ntn' then Some default_scope
else find_default ntn scopes
let factorize_entries = function
@@ -875,7 +1017,7 @@ let factorize_entries = function
let (ntn,l_of_ntn,rest) =
List.fold_left
(fun (a',l,rest) (a,c) ->
- if String.equal a a' then (a',c::l,rest) else (a,[c],(a',l)::rest))
+ if notation_eq a a' then (a',c::l,rest) else (a,[c],(a',l)::rest))
(ntn,[c],[]) l in
(ntn,l_of_ntn)::rest
@@ -930,15 +1072,15 @@ let possible_notations ntn =
(* Only "_ U _" format *)
[ntn]
else
- let ntn' = make_notation_key (raw_analyze_notation_tokens toks) in
+ let _,ntn' = make_notation_key None (raw_analyze_notation_tokens toks) in
if String.equal ntn ntn' then (* Only symbols *) [ntn] else [ntn;ntn']
let browse_notation strict ntn map =
let ntns = possible_notations ntn in
- let find ntn' ntn =
+ let find (from,ntn' as fullntn') ntn =
if String.contains ntn ' ' then String.equal ntn ntn'
else
- let toks = decompose_notation_key ntn' in
+ let _,toks = decompose_notation_key fullntn' in
let get_terminals = function Terminal ntn -> Some ntn | _ -> None in
let trms = List.map_filter get_terminals toks in
if strict then String.List.equal [ntn] trms
@@ -947,10 +1089,10 @@ let browse_notation strict ntn map =
let l =
String.Map.fold
(fun scope_name sc ->
- String.Map.fold (fun ntn { not_interp = (_, r); not_location = df } l ->
+ NotationMap.fold (fun ntn { not_interp = (_, r); not_location = df } l ->
if List.exists (find ntn) ntns then (ntn,(scope_name,r,df))::l else l) sc.notations)
map [] in
- List.sort (fun x y -> String.compare (fst x) (fst y)) l
+ List.sort (fun x y -> String.compare (snd (fst x)) (snd (fst y))) l
let global_reference_of_notation test (ntn,(sc,c,_)) =
match c with
@@ -1011,9 +1153,9 @@ let locate_notation prglob ntn scope =
let collect_notation_in_scope scope sc known =
assert (not (String.equal scope default_scope));
- String.Map.fold
+ NotationMap.fold
(fun ntn { not_interp = (_, r); not_location = (_, df) } (l,known as acc) ->
- if String.List.mem ntn known then acc else ((df,r)::l,ntn::known))
+ if List.mem_f notation_eq ntn known then acc else ((df,r)::l,ntn::known))
sc.notations ([],known)
let collect_notations stack =
@@ -1026,10 +1168,10 @@ let collect_notations stack =
collect_notation_in_scope scope (find_scope scope) knownntn in
((scope,l)::all,knownntn)
| SingleNotation ntn ->
- if String.List.mem ntn knownntn then (all,knownntn)
+ if List.mem_f notation_eq ntn knownntn then (all,knownntn)
else
let { not_interp = (_, r); not_location = (_, df) } =
- String.Map.find ntn (find_scope default_scope).notations in
+ NotationMap.find ntn (find_scope default_scope).notations in
let all' = match all with
| (s,lonelyntn)::rest when String.equal s default_scope ->
(s,(df,r)::lonelyntn)::rest
@@ -1063,15 +1205,20 @@ let pr_visibility prglob = function
let freeze _ =
(!scope_map, !scope_stack, !arguments_scope,
- !delimiters_map, !notations_key_table, !scope_class_map)
+ !delimiters_map, !notations_key_table, !scope_class_map,
+ !entry_coercion_map, !entry_has_global_map,
+ !entry_has_ident_map)
-let unfreeze (scm,scs,asc,dlm,fkm,clsc) =
+let unfreeze (scm,scs,asc,dlm,fkm,clsc,coe,globs,ids) =
scope_map := scm;
scope_stack := scs;
delimiters_map := dlm;
arguments_scope := asc;
notations_key_table := fkm;
- scope_class_map := clsc
+ scope_class_map := clsc;
+ entry_coercion_map := coe;
+ entry_has_global_map := globs;
+ entry_has_ident_map := ids
let init () =
init_scope_map ();
diff --git a/interp/notation.mli b/interp/notation.mli
index b177b7f1e0..c921606484 100644
--- a/interp/notation.mli
+++ b/interp/notation.mli
@@ -17,6 +17,21 @@ open Notation_term
(** Notations *)
+val pr_notation : notation -> Pp.t
+(** Printing *)
+
+val notation_entry_eq : notation_entry -> notation_entry -> bool
+(** Equality on [notation_entry]. *)
+
+val notation_entry_level_eq : notation_entry_level -> notation_entry_level -> bool
+(** Equality on [notation_entry_level]. *)
+
+val notation_eq : notation -> notation -> bool
+(** Equality on [notation]. *)
+
+module NotationSet : Set.S with type elt = notation
+module NotationMap : CMap.ExtS with type key = notation and module Set := NotationSet
+
(** {6 Scopes } *)
(** A scope is a set of interpreters for symbols + optional
interpreter and printers for integers + optional delimiters *)
@@ -25,8 +40,6 @@ type delimiters = string
type scope
type scopes (** = [scope_name list] *)
-type local_scopes = tmp_scope_name option * scope_name list
-
val declare_scope : scope_name -> unit
val current_scopes : unit -> scopes
@@ -84,11 +97,11 @@ val declare_string_interpreter : scope_name -> required_module ->
(** Return the [term]/[cases_pattern] bound to a primitive token in a
given scope context*)
-val interp_prim_token : ?loc:Loc.t -> prim_token -> local_scopes ->
+val interp_prim_token : ?loc:Loc.t -> prim_token -> subscopes ->
glob_constr * (notation_location * scope_name option)
(* This function returns a glob_const representing a pattern *)
val interp_prim_token_cases_pattern_expr : ?loc:Loc.t -> (GlobRef.t -> unit) -> prim_token ->
- local_scopes -> glob_constr * (notation_location * scope_name option)
+ subscopes -> glob_constr * (notation_location * scope_name option)
(** Return the primitive token associated to a [term]/[cases_pattern];
raise [No_match] if no such token *)
@@ -101,7 +114,7 @@ val uninterp_prim_token_ind_pattern :
inductive -> cases_pattern list -> scope_name * prim_token
val availability_of_prim_token :
- prim_token -> scope_name -> local_scopes -> delimiters option option
+ prim_token -> scope_name -> subscopes -> delimiters option option
(** {6 Declare and interpret back and forth a notation } *)
@@ -116,7 +129,7 @@ val declare_notation_interpretation : notation -> scope_name option ->
val declare_uninterpretation : interp_rule -> interpretation -> unit
(** Return the interpretation bound to a notation *)
-val interp_notation : ?loc:Loc.t -> notation -> local_scopes ->
+val interp_notation : ?loc:Loc.t -> notation -> subscopes ->
interpretation * (notation_location * scope_name option)
type notation_rule = interp_rule * interpretation * int option
@@ -129,13 +142,13 @@ val uninterp_ind_pattern_notations : inductive -> notation_rule list
(** Test if a notation is available in the scopes
context [scopes]; if available, the result is not None; the first
argument is itself not None if a delimiters is needed *)
-val availability_of_notation : scope_name option * notation -> local_scopes ->
+val availability_of_notation : scope_name option * notation -> subscopes ->
(scope_name option * delimiters option) option
(** {6 Miscellaneous} *)
val interp_notation_as_global_reference : ?loc:Loc.t -> (GlobRef.t -> bool) ->
- notation -> delimiters option -> GlobRef.t
+ notation_key -> delimiters option -> GlobRef.t
(** Checks for already existing notations *)
val exists_notation_in_scope : scope_name option -> notation ->
@@ -177,8 +190,8 @@ type symbol =
val symbol_eq : symbol -> symbol -> bool
(** Make/decompose a notation of the form "_ U _" *)
-val make_notation_key : symbol list -> notation
-val decompose_notation_key : notation -> symbol list
+val make_notation_key : notation_entry_level -> symbol list -> notation
+val decompose_notation_key : notation -> notation_entry_level * symbol list
(** Decompose a notation of the form "a 'U' b" *)
val decompose_raw_notation : string -> symbol list
@@ -187,11 +200,21 @@ val decompose_raw_notation : string -> symbol list
val pr_scope_class : scope_class -> Pp.t
val pr_scope : (glob_constr -> Pp.t) -> scope_name -> Pp.t
val pr_scopes : (glob_constr -> Pp.t) -> Pp.t
-val locate_notation : (glob_constr -> Pp.t) -> notation ->
+val locate_notation : (glob_constr -> Pp.t) -> notation_key ->
scope_name option -> Pp.t
val pr_visibility: (glob_constr -> Pp.t) -> scope_name option -> Pp.t
+type entry_coercion = notation list
+val declare_entry_coercion : notation -> notation_entry_level -> unit
+val availability_of_entry_coercion : notation_entry_level -> notation_entry_level -> entry_coercion option
+
+val declare_custom_entry_has_global : string -> int -> unit
+val declare_custom_entry_has_ident : string -> int -> unit
+
+val entry_has_global : notation_entry_level -> bool
+val entry_has_ident : notation_entry_level -> bool
+
(** Rem: printing rules for primitive token are canonical *)
val with_notation_protection : ('a -> 'b) -> 'a -> 'b
diff --git a/interp/notation_ops.ml b/interp/notation_ops.ml
index ab0bf9c6fe..06943ce7b9 100644
--- a/interp/notation_ops.ml
+++ b/interp/notation_ops.ml
@@ -641,11 +641,9 @@ let rec subst_notation_constr subst bound raw =
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 p' = subst_proj subst p in
let c' = subst_notation_constr subst bound c in
- if kn' == kn && c' == c then raw else NProj(Projection.make kn' b, c')
+ if p' == p && c' == c then raw else NProj(p', c')
let subst_interpretation subst (metas,pat) =
@@ -1010,9 +1008,9 @@ let remove_sigma x (terms,termlists,binders,binderlists) =
let remove_bindinglist_sigma x (terms,termlists,binders,binderlists) =
(terms,termlists,binders,Id.List.remove_assoc x binderlists)
-let add_ldots_var metas = (ldots_var,((None,[]),NtnTypeConstr))::metas
+let add_ldots_var metas = (ldots_var,((Constrexpr.InConstrEntrySomeLevel,(None,[])),NtnTypeConstr))::metas
-let add_meta_bindinglist x metas = (x,((None,[]),NtnTypeBinderList))::metas
+let add_meta_bindinglist x metas = (x,((Constrexpr.InConstrEntrySomeLevel,(None,[])),NtnTypeBinderList))::metas
(* This tells if letins in the middle of binders should be included in
the sequence of binders *)
@@ -1057,7 +1055,7 @@ let match_binderlist match_fun alp metas sigma rest x y iter termin revert =
let alp,sigma = bind_bindinglist_env alp sigma x bl in
match_fun alp metas sigma rest termin
-let add_meta_term x metas = (x,((None,[]),NtnTypeConstr))::metas
+let add_meta_term x metas = (x,((Constrexpr.InConstrEntrySomeLevel,(None,[])),NtnTypeConstr))::metas (* Should reuse the scope of the partner of x! *)
let match_termlist match_fun alp metas sigma rest x y iter termin revert =
let rec aux sigma acc rest =
diff --git a/interp/notation_ops.mli b/interp/notation_ops.mli
index f038b5be1a..58fa221b16 100644
--- a/interp/notation_ops.mli
+++ b/interp/notation_ops.mli
@@ -53,18 +53,18 @@ val glob_constr_of_notation_constr : ?loc:Loc.t -> notation_constr -> glob_const
exception No_match
val match_notation_constr : bool -> 'a glob_constr_g -> interpretation ->
- ('a glob_constr_g * subscopes) list * ('a glob_constr_g list * subscopes) list *
- ('a cases_pattern_disjunction_g * subscopes) list *
- ('a extended_glob_local_binder_g list * subscopes) list
+ ('a glob_constr_g * extended_subscopes) list * ('a glob_constr_g list * extended_subscopes) list *
+ ('a cases_pattern_disjunction_g * extended_subscopes) list *
+ ('a extended_glob_local_binder_g list * extended_subscopes) list
val match_notation_constr_cases_pattern :
'a cases_pattern_g -> interpretation ->
- (('a cases_pattern_g * subscopes) list * ('a cases_pattern_g list * subscopes) list) *
+ (('a cases_pattern_g * extended_subscopes) list * ('a cases_pattern_g list * extended_subscopes) list) *
(int * 'a cases_pattern_g list)
val match_notation_constr_ind_pattern :
inductive -> 'a cases_pattern_g list -> interpretation ->
- (('a cases_pattern_g * subscopes) list * ('a cases_pattern_g list * subscopes) list) *
+ (('a cases_pattern_g * extended_subscopes) list * ('a cases_pattern_g list * extended_subscopes) list) *
(int * 'a cases_pattern_g list)
(** {5 Matching a notation pattern against a [glob_constr]} *)
diff --git a/interp/notation_term.ml b/interp/notation_term.ml
index 6d9effcef4..942ea5ff3f 100644
--- a/interp/notation_term.ml
+++ b/interp/notation_term.ml
@@ -58,6 +58,8 @@ type tmp_scope_name = scope_name
type subscopes = tmp_scope_name option * scope_name list
+type extended_subscopes = Constrexpr.notation_entry_level * subscopes
+
(** Type of the meta-variables of an notation_constr: in a recursive pattern x..y,
x carries the sequence of objects bound to the list x..y *)
@@ -86,7 +88,7 @@ type notation_var_internalization_type =
(** This characterizes to what a notation is interpreted to *)
type interpretation =
- (Id.t * (subscopes * notation_var_instance_type)) list *
+ (Id.t * (extended_subscopes * notation_var_instance_type)) list *
notation_constr
type reversibility_status = APrioriReversible | HasLtac | NonInjective of Id.t list
diff --git a/interp/syntax_def.ml b/interp/syntax_def.ml
index a4f20fd739..e3d490a1ad 100644
--- a/interp/syntax_def.ml
+++ b/interp/syntax_def.ml
@@ -77,8 +77,8 @@ type syndef_interpretation = (Id.t * subscopes) list * notation_constr
(* Coercions to the general format of notation that also supports
variables bound to list of expressions *)
-let in_pat (ids,ac) = (List.map (fun (id,sc) -> (id,(sc,NtnTypeConstr))) ids,ac)
-let out_pat (ids,ac) = (List.map (fun (id,(sc,typ)) -> (id,sc)) ids,ac)
+let in_pat (ids,ac) = (List.map (fun (id,sc) -> (id,((Constrexpr.InConstrEntrySomeLevel,sc),NtnTypeConstr))) ids,ac)
+let out_pat (ids,ac) = (List.map (fun (id,((_,sc),typ)) -> (id,sc)) ids,ac)
let declare_syntactic_definition local id onlyparse pat =
let _ = add_leaf id (in_syntax_constant (local,in_pat pat,onlyparse)) in ()
diff --git a/kernel/cClosure.ml b/kernel/cClosure.ml
index 1d5142a5c2..fd9394025a 100644
--- a/kernel/cClosure.ml
+++ b/kernel/cClosure.ml
@@ -31,7 +31,6 @@ open Environ
open Esubst
let stats = ref false
-let share = ref true
(* Profiling *)
let beta = ref 0
@@ -265,7 +264,8 @@ type 'a infos_cache = {
i_repr : 'a infos -> 'a infos_tab -> constr -> 'a;
i_env : env;
i_sigma : existential -> constr option;
- i_rels : (Context.Rel.Declaration.t * lazy_val) Range.t;
+ i_rels : (Constr.rel_declaration * lazy_val) Range.t;
+ i_share : bool;
}
and 'a infos = {
@@ -313,12 +313,13 @@ let ref_value_cache ({i_cache = cache} as infos) tab ref =
let evar_value cache ev =
cache.i_sigma ev
-let create mk_cl flgs env evars =
+let create ~repr ~share flgs env evars =
let cache =
- { i_repr = mk_cl;
+ { i_repr = repr;
i_env = env;
i_sigma = evars;
i_rels = env.env_rel_context.env_rel_map;
+ i_share = share;
}
in { i_flags = flgs; i_cache = cache }
@@ -384,8 +385,8 @@ let mk_red f = {norm=Red;term=f}
(* Could issue a warning if no is still Red, pointing out that we loose
sharing. *)
-let update v1 no t =
- if !share then
+let update ~share v1 no t =
+ if share then
(v1.norm <- no;
v1.term <- t;
v1)
@@ -397,7 +398,7 @@ let update v1 no t =
type stack_member =
| Zapp of fconstr array
| ZcaseT of case_info * constr * constr array * fconstr subs
- | Zproj of int * int * Constant.t
+ | Zproj of Projection.Repr.t
| Zfix of fconstr * stack
| Zshift of int
| Zupdate of fconstr
@@ -498,14 +499,16 @@ let compact_stack head stk =
(* Be sure to create a new cell otherwise sharing would be
lost by the update operation *)
let h' = lft_fconstr depth head in
- let _ = update m h'.norm h'.term in
+ (** The stack contains [Zupdate] marks only if in sharing mode *)
+ let _ = update ~share:true m h'.norm h'.term in
strip_rec depth s
| stk -> zshift depth stk in
strip_rec 0 stk
(* Put an update mark in the stack, only if needed *)
-let zupdate m s =
- if !share && begin match m.norm with Red -> true | _ -> false end
+let zupdate info m s =
+ let share = info.i_cache.i_share in
+ if share && begin match m.norm with Red -> true | _ -> false end
then
let s' = compact_stack m s in
let _ = m.term <- FLOCKED in
@@ -691,14 +694,15 @@ let rec zip m stk =
| ZcaseT(ci,p,br,e)::s ->
let t = FCaseT(ci, p, m, br, e) in
zip {norm=neutr m.norm; term=t} s
- | Zproj (i,j,cst) :: s ->
- zip {norm=neutr m.norm; term=FProj(Projection.make cst true,m)} s
+ | Zproj p :: s ->
+ zip {norm=neutr m.norm; term=FProj(Projection.make p true,m)} s
| Zfix(fx,par)::s ->
zip fx (par @ append_stack [|m|] s)
| Zshift(n)::s ->
zip (lift_fconstr n m) s
| Zupdate(rf)::s ->
- zip (update rf m.norm m.term) s
+ (** The stack contains [Zupdate] marks only if in sharing mode *)
+ zip (update ~share:true rf m.norm m.term) s
let fapp_stack (m,stk) = zip m stk
@@ -718,7 +722,8 @@ let strip_update_shift_app_red head stk =
strip_rec (Zapp args :: rstk)
{norm=h.norm;term=FApp(h,args)} depth s
| Zupdate(m)::s ->
- strip_rec rstk (update m h.norm h.term) depth s
+ (** The stack contains [Zupdate] marks only if in sharing mode *)
+ strip_rec rstk (update ~share:true m h.norm h.term) depth s
| stk -> (depth,List.rev rstk, stk) in
strip_rec [] head 0 stk
@@ -743,7 +748,8 @@ let get_nth_arg head n stk =
List.rev (if Int.equal n 0 then rstk else (Zapp bef :: rstk)) in
(Some (stk', args.(n)), append_stack aft s')
| Zupdate(m)::s ->
- strip_rec rstk (update m h.norm h.term) n s
+ (** The stack contains [Zupdate] mark only if in sharing mode *)
+ strip_rec rstk (update ~share:true m h.norm h.term) n s
| s -> (None, List.rev rstk @ s) in
strip_rec [] head n stk
@@ -752,7 +758,8 @@ let get_nth_arg head n stk =
let rec get_args n tys f e stk =
match stk with
Zupdate r :: s ->
- let _hd = update r Cstr (FLambda(n,tys,f,e)) in
+ (** The stack contains [Zupdate] mark only if in sharing mode *)
+ let _hd = update ~share:true r Cstr (FLambda(n,tys,f,e)) in
get_args n tys f e s
| Zshift k :: s ->
get_args n tys f (subs_shft (k,e)) s
@@ -822,21 +829,24 @@ let drop_parameters depth n argstk =
let eta_expand_ind_stack env ind m s (f, s') =
let open Declarations in
let mib = lookup_mind (fst ind) env in
- match mib.Declarations.mind_record with
- | PrimRecord infos when
- mib.Declarations.mind_finite == Declarations.BiFinite ->
- let (_, projs, _) = infos.(snd ind) in
- (* (Construct, pars1 .. parsm :: arg1...argn :: []) ~= (f, s') ->
+ (* disallow eta-exp for non-primitive records *)
+ if not (mib.mind_finite == BiFinite) then raise Not_found;
+ match Declareops.inductive_make_projections ind mib with
+ | Some projs ->
+ (* (Construct, pars1 .. parsm :: arg1...argn :: []) ~= (f, s') ->
arg1..argn ~= (proj1 t...projn t) where t = zip (f,s') *)
- let pars = mib.Declarations.mind_nparams in
- let right = fapp_stack (f, s') in
- let (depth, args, s) = strip_update_shift_app m s in
- (** Try to drop the params, might fail on partially applied constructors. *)
- let argss = try_drop_parameters depth pars args in
- let hstack = Array.map (fun p -> { norm = Red; (* right can't be a constructor though *)
- term = FProj (Projection.make p true, right) }) projs in
- argss, [Zapp hstack]
- | PrimRecord _ | NotRecord | FakeRecord -> raise Not_found (* disallow eta-exp for non-primitive records *)
+ let pars = mib.Declarations.mind_nparams in
+ let right = fapp_stack (f, s') in
+ let (depth, args, s) = strip_update_shift_app m s in
+ (** Try to drop the params, might fail on partially applied constructors. *)
+ let argss = try_drop_parameters depth pars args in
+ let hstack = Array.map (fun p ->
+ { norm = Red; (* right can't be a constructor though *)
+ term = FProj (Projection.make p true, right) })
+ projs
+ in
+ argss, [Zapp hstack]
+ | None -> raise Not_found (* disallow eta-exp for non-primitive records *)
let rec project_nth_arg n argstk =
match argstk with
@@ -875,9 +885,7 @@ let contract_fix_vect fix =
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))
+ Some (Zproj (Projection.repr p))
else None
(*********************************************************************)
@@ -888,10 +896,10 @@ let unfold_projection info p =
let rec knh info m stk =
match m.term with
| FLIFT(k,a) -> knh info a (zshift k stk)
- | FCLOS(t,e) -> knht info e t (zupdate m stk)
+ | FCLOS(t,e) -> knht info e t (zupdate info m stk)
| FLOCKED -> assert false
- | FApp(a,b) -> knh info a (append_stack b (zupdate m stk))
- | FCaseT(ci,p,t,br,e) -> knh info t (ZcaseT(ci,p,br,e)::zupdate m stk)
+ | FApp(a,b) -> knh info a (append_stack b (zupdate info m stk))
+ | FCaseT(ci,p,t,br,e) -> knh info t (ZcaseT(ci,p,br,e)::zupdate info m stk)
| FFix(((ri,n),(_,_,_)),_) ->
(match get_nth_arg m ri.(n) stk with
(Some(pars,arg),stk') -> knh info arg (Zfix(m,pars)::stk')
@@ -900,7 +908,7 @@ let rec knh info m stk =
| FProj (p,c) ->
(match unfold_projection info p with
| None -> (m, stk)
- | Some s -> knh info c (s :: zupdate m stk))
+ | Some s -> knh info c (s :: zupdate info m stk))
(* cases where knh stops *)
| (FFlex _|FLetIn _|FConstruct _|FEvar _|
@@ -958,9 +966,9 @@ let rec knr info tab m stk =
let stk' = par @ append_stack [|rarg|] s in
let (fxe,fxbd) = contract_fix_vect fx.term in
knit info tab fxe fxbd stk'
- | (depth, args, Zproj (n, m, cst)::s) when use_match ->
- let rargs = drop_parameters depth n args in
- let rarg = project_nth_arg m rargs in
+ | (depth, args, Zproj p::s) when use_match ->
+ let rargs = drop_parameters depth (Projection.Repr.npars p) args in
+ let rarg = project_nth_arg (Projection.Repr.arg p) rargs in
kni info tab rarg s
| (_,args,s) -> (m,args@s))
else (m,stk)
@@ -1002,7 +1010,7 @@ let rec zip_term zfun m stk =
let t = mkCase(ci, zfun (mk_clos e p), m,
Array.map (fun b -> zfun (mk_clos e b)) br) in
zip_term zfun t s
- | Zproj(_,_,p)::s ->
+ | Zproj p::s ->
let t = mkProj (Projection.make p true, m) in
zip_term zfun t s
| Zfix(fx,par)::s ->
@@ -1018,10 +1026,11 @@ let rec zip_term zfun m stk =
2- tries to rebuild the term. If a closure still has to be computed,
calls itself recursively. *)
let rec kl info tab m =
+ let share = info.i_cache.i_share in
if is_val m then (incr prune; term_of_fconstr m)
else
let (nm,s) = kni info tab m [] in
- let () = if !share then ignore (fapp_stack (nm, s)) in (* to unlock Zupdates! *)
+ let () = if share then ignore (fapp_stack (nm, s)) in (* to unlock Zupdates! *)
zip_term (kl info tab) (norm_head info tab nm) s
(* no redex: go up for atoms and already normalized terms, go down
@@ -1077,14 +1086,15 @@ let whd_stack infos tab m stk = match m.norm with
knh infos m stk
| Red | Cstr ->
let k = kni infos tab m stk in
- let () = if !share then ignore (fapp_stack k) in (* to unlock Zupdates! *)
+ let () = if infos.i_cache.i_share then ignore (fapp_stack k) in (* to unlock Zupdates! *)
k
(* cache of constants: the body is computed only when needed. *)
type clos_infos = fconstr infos
let create_clos_infos ?(evars=fun _ -> None) flgs env =
- create (fun _ _ c -> inject c) flgs env evars
+ let share = (Environ.typing_flags env).Declarations.share_reduction in
+ create ~share ~repr:(fun _ _ c -> inject c) flgs env evars
let create_tab () = KeyTable.create 17
diff --git a/kernel/cClosure.mli b/kernel/cClosure.mli
index f8f98f0abe..6121b3a1ec 100644
--- a/kernel/cClosure.mli
+++ b/kernel/cClosure.mli
@@ -15,7 +15,6 @@ open Esubst
(** Flags for profiling reductions. *)
val stats : bool ref
-val share : bool ref
val with_stats: 'a Lazy.t -> 'a
@@ -106,8 +105,13 @@ type 'a infos = {
i_cache : 'a infos_cache }
val ref_value_cache: 'a infos -> 'a infos_tab -> table_key -> 'a option
-val create: ('a infos -> 'a infos_tab -> constr -> 'a) -> reds -> env ->
- (existential -> constr option) -> 'a infos
+val create:
+ repr:('a infos -> 'a infos_tab -> constr -> 'a) ->
+ share:bool ->
+ reds ->
+ env ->
+ (existential -> constr option) ->
+ 'a infos
val create_tab : unit -> 'a infos_tab
val evar_value : 'a infos_cache -> existential -> constr option
@@ -152,7 +156,7 @@ type fterm =
type stack_member =
| Zapp of fconstr array
| ZcaseT of case_info * constr * constr array * fconstr subs
- | Zproj of int * int * Constant.t
+ | Zproj of Projection.Repr.t
| Zfix of fconstr * stack
| Zshift of int
| Zupdate of fconstr
diff --git a/kernel/cbytecodes.ml b/kernel/cbytecodes.ml
index 521f540d22..9a1224aab2 100644
--- a/kernel/cbytecodes.ml
+++ b/kernel/cbytecodes.ml
@@ -128,8 +128,7 @@ type instruction =
| Ksetfield of int
| Kstop
| Ksequence of bytecodes * bytecodes
- | Kproj of int * Constant.t (* index of the projected argument,
- name of projection *)
+ | Kproj of Projection.Repr.t
| Kensurestackcapacity of int
(* spiwack: instructions concerning integers *)
| Kbranch of Label.t (* jump to label *)
@@ -217,6 +216,7 @@ type vm_env = {
type comp_env = {
+ arity : int; (* arity of the current function, 0 if none *)
nb_uni_stack : int ; (* number of universes on the stack, *)
(* universes are always at the bottom. *)
nb_stack : int; (* number of variables on the stack *)
@@ -235,8 +235,8 @@ open Util
let pp_sort s =
let open Sorts in
match s with
- | Prop Null -> str "Prop"
- | Prop Pos -> str "Set"
+ | Prop -> str "Prop"
+ | Set -> str "Set"
| Type u -> str "Type@{" ++ Univ.pr_uni u ++ str "}"
let rec pp_struct_const = function
@@ -310,7 +310,7 @@ let rec pp_instr i =
| Kbranch lbl -> str "branch " ++ pp_lbl lbl
- | Kproj(n,p) -> str "proj " ++ int n ++ str " " ++ Constant.print p
+ | Kproj p -> str "proj " ++ Projection.Repr.print p
| Kensurestackcapacity size -> str "growstack " ++ int size
diff --git a/kernel/cbytecodes.mli b/kernel/cbytecodes.mli
index 238edc0af5..f17a1e657e 100644
--- a/kernel/cbytecodes.mli
+++ b/kernel/cbytecodes.mli
@@ -88,8 +88,7 @@ type instruction =
| Ksetfield of int (** accu[n] = sp[0] ; sp = pop sp *)
| Kstop
| Ksequence of bytecodes * bytecodes
- | Kproj of int * Constant.t (** index of the projected argument,
- name of projection *)
+ | Kproj of Projection.Repr.t
| Kensurestackcapacity of int
(** spiwack: instructions concerning integers *)
@@ -159,6 +158,7 @@ type vm_env = {
type comp_env = {
+ arity : int; (* arity of the current function, 0 if none *)
nb_uni_stack : int ; (** number of universes on the stack *)
nb_stack : int; (** number of variables on the stack *)
in_stack : int list; (** position in the stack *)
diff --git a/kernel/cbytegen.ml b/kernel/cbytegen.ml
index 7a27a3d206..e336ea922d 100644
--- a/kernel/cbytegen.ml
+++ b/kernel/cbytegen.ml
@@ -112,8 +112,9 @@ let push_fv d e = {
let fv r = !(r.in_env)
-let empty_comp_env ?(univs=0) ()=
- { nb_uni_stack = univs;
+let empty_comp_env ()=
+ { arity = 0;
+ nb_uni_stack = 0;
nb_stack = 0;
in_stack = [];
nb_rec = 0;
@@ -148,7 +149,8 @@ let rec add_param n sz l =
if Int.equal n 0 then l else add_param (n - 1) sz (n+sz::l)
let comp_env_fun ?(univs=0) arity =
- { nb_uni_stack = univs ;
+ { arity;
+ nb_uni_stack = univs ;
nb_stack = arity;
in_stack = add_param arity 0 [];
nb_rec = 0;
@@ -159,7 +161,8 @@ let comp_env_fun ?(univs=0) arity =
let comp_env_fix_type rfv =
- { nb_uni_stack = 0;
+ { arity = 0;
+ nb_uni_stack = 0;
nb_stack = 0;
in_stack = [];
nb_rec = 0;
@@ -173,7 +176,8 @@ let comp_env_fix ndef curr_pos arity rfv =
for i = ndef downto 1 do
prec := Koffsetclosure (2 * (ndef - curr_pos - i)) :: !prec
done;
- { nb_uni_stack = 0;
+ { arity;
+ nb_uni_stack = 0;
nb_stack = arity;
in_stack = add_param arity 0 [];
nb_rec = ndef;
@@ -183,7 +187,8 @@ let comp_env_fix ndef curr_pos arity rfv =
}
let comp_env_cofix_type ndef rfv =
- { nb_uni_stack = 0;
+ { arity = 0;
+ nb_uni_stack = 0;
nb_stack = 0;
in_stack = [];
nb_rec = 0;
@@ -197,7 +202,8 @@ let comp_env_cofix ndef arity rfv =
for i = 1 to ndef do
prec := Kenvacc i :: !prec
done;
- { nb_uni_stack = 0;
+ { arity;
+ nb_uni_stack = 0;
nb_stack = arity;
in_stack = add_param arity 0 [];
nb_rec = ndef;
@@ -249,8 +255,15 @@ let pos_rel i r sz =
Kenvacc(r.offset + pos)
let pos_universe_var i r sz =
- if i < r.nb_uni_stack then
- Kacc (sz - r.nb_stack - (r.nb_uni_stack - i))
+ (* Compilation of a universe variable can happen either at toplevel (the
+ current closure correspond to a constant and has local universes) or in a
+ local closure (which has no local universes). *)
+ if r.nb_uni_stack != 0 then
+ (* Universe variables are represented by De Bruijn levels (not indices),
+ starting at 0. The shape of the stack will be [v1|..|vn|u1..up|arg1..argq]
+ with size = n + p + q, and q = r.arity. So Kacc (sz - r.arity - 1) will access
+ the last universe. *)
+ Kacc (sz - r.arity - (r.nb_uni_stack - i))
else
let env = !(r.in_env) in
let db = FVuniv_var i in
@@ -479,8 +492,8 @@ let rec compile_lam env cenv lam sz cont =
| Lval v -> compile_structured_constant cenv v sz cont
- | Lproj (n,kn,arg) ->
- compile_lam env cenv arg sz (Kproj (n,kn) :: cont)
+ | Lproj (p,arg) ->
+ compile_lam env cenv arg sz (Kproj p :: cont)
| Lvar id -> pos_named id cenv :: cont
@@ -488,6 +501,9 @@ let rec compile_lam env cenv lam sz cont =
if Array.is_empty args then
compile_fv_elem cenv (FVevar evk) sz cont
else
+ (** Arguments are reversed in evar instances *)
+ let args = Array.copy args in
+ let () = Array.rev args in
comp_app compile_fv_elem (compile_lam env) cenv (FVevar evk) args sz cont
| Lconst (kn,u) -> compile_constant env cenv kn u [||] sz cont
@@ -498,7 +514,7 @@ let rec compile_lam env cenv lam sz cont =
else comp_app compile_structured_constant compile_universe cenv
(Const_ind ind) (Univ.Instance.to_array u) sz cont
- | Lsort (Sorts.Prop _ as s) ->
+ | Lsort (Sorts.Prop | Sorts.Set as s) ->
compile_structured_constant cenv (Const_sort s) sz cont
| Lsort (Sorts.Type u) ->
(* We represent universes as a global constant with local universes
diff --git a/kernel/cemitcodes.ml b/kernel/cemitcodes.ml
index 2426255e48..ca24f9b689 100644
--- a/kernel/cemitcodes.ml
+++ b/kernel/cemitcodes.ml
@@ -27,7 +27,7 @@ type reloc_info =
| Reloc_annot of annot_switch
| Reloc_const of structured_constant
| Reloc_getglobal of Names.Constant.t
- | Reloc_proj_name of Constant.t
+ | Reloc_proj_name of Projection.Repr.t
let eq_reloc_info r1 r2 = match r1, r2 with
| Reloc_annot sw1, Reloc_annot sw2 -> eq_annot_switch sw1 sw2
@@ -36,7 +36,7 @@ let eq_reloc_info r1 r2 = match r1, r2 with
| Reloc_const _, _ -> false
| Reloc_getglobal c1, Reloc_getglobal c2 -> Constant.equal c1 c2
| Reloc_getglobal _, _ -> false
-| Reloc_proj_name p1, Reloc_proj_name p2 -> Constant.equal p1 p2
+| Reloc_proj_name p1, Reloc_proj_name p2 -> Projection.Repr.equal p1 p2
| Reloc_proj_name _, _ -> false
let hash_reloc_info r =
@@ -45,7 +45,7 @@ let hash_reloc_info r =
| Reloc_annot sw -> combinesmall 1 (hash_annot_switch sw)
| Reloc_const c -> combinesmall 2 (hash_structured_constant c)
| Reloc_getglobal c -> combinesmall 3 (Constant.hash c)
- | Reloc_proj_name p -> combinesmall 4 (Constant.hash p)
+ | Reloc_proj_name p -> combinesmall 4 (Projection.Repr.hash p)
module RelocTable = Hashtbl.Make(struct
type t = reloc_info
@@ -284,7 +284,7 @@ let emit_instr env = function
if n <= 1 then out env (opSETFIELD0+n)
else (out env opSETFIELD;out_int env n)
| Ksequence _ -> invalid_arg "Cemitcodes.emit_instr"
- | Kproj (n,p) -> out env opPROJ; out_int env n; slot_for_proj_name env p
+ | Kproj p -> out env opPROJ; out_int env (Projection.Repr.arg p); slot_for_proj_name env p
| Kensurestackcapacity size -> out env opENSURESTACKCAPACITY; out_int env size
(* spiwack *)
| Kbranch lbl -> out env opBRANCH; out_label env lbl
@@ -371,7 +371,7 @@ let subst_reloc s ri =
Reloc_annot {a with ci = ci}
| Reloc_const sc -> Reloc_const (subst_strcst s sc)
| Reloc_getglobal kn -> Reloc_getglobal (subst_constant s kn)
- | Reloc_proj_name p -> Reloc_proj_name (subst_constant s p)
+ | Reloc_proj_name p -> Reloc_proj_name (subst_proj_repr s p)
let subst_patches subst p =
let infos = CArray.map (fun (r, pos) -> (subst_reloc subst r, pos)) p.reloc_infos in
diff --git a/kernel/cemitcodes.mli b/kernel/cemitcodes.mli
index 696721c375..9009926bdb 100644
--- a/kernel/cemitcodes.mli
+++ b/kernel/cemitcodes.mli
@@ -5,7 +5,7 @@ type reloc_info =
| Reloc_annot of annot_switch
| Reloc_const of structured_constant
| Reloc_getglobal of Constant.t
- | Reloc_proj_name of Constant.t
+ | Reloc_proj_name of Projection.Repr.t
type patches
type emitcodes
diff --git a/kernel/cinstr.mli b/kernel/cinstr.mli
index f42c46175c..171ca38830 100644
--- a/kernel/cinstr.mli
+++ b/kernel/cinstr.mli
@@ -36,7 +36,7 @@ and lambda =
| Lval of structured_constant
| Lsort of Sorts.t
| Lind of pinductive
- | Lproj of int * Constant.t * lambda
+ | Lproj of Projection.Repr.t * lambda
| Luint of uint
(* Cofixpoints have to be in eta-expanded form for their call-by-need evaluation
diff --git a/kernel/clambda.ml b/kernel/clambda.ml
index b722e42008..7c00e40fb0 100644
--- a/kernel/clambda.ml
+++ b/kernel/clambda.ml
@@ -111,9 +111,9 @@ let rec pp_lam lam =
(str "(PRIM " ++ pr_con kn ++ spc() ++
prlist_with_sep spc pp_lam (Array.to_list args) ++
str")")
- | Lproj(i,kn,arg) ->
+ | Lproj(p,arg) ->
hov 1
- (str "(proj#" ++ int i ++ spc() ++ pr_con kn ++ str "(" ++ pp_lam arg
+ (str "(proj " ++ Projection.Repr.print p ++ str "(" ++ pp_lam arg
++ str ")")
| Luint _ ->
str "(uint)"
@@ -205,9 +205,9 @@ let rec map_lam_with_binders g f n lam =
| Lprim(kn,ar,op,args) ->
let args' = Array.Smart.map (f n) args in
if args == args' then lam else Lprim(kn,ar,op,args')
- | Lproj(i,kn,arg) ->
+ | Lproj(p,arg) ->
let arg' = f n arg in
- if arg == arg' then lam else Lproj(i,kn,arg')
+ if arg == arg' then lam else Lproj(p,arg')
| Luint u ->
let u' = map_uint g f n u in
if u == u' then lam else Luint u'
@@ -376,7 +376,7 @@ let rec occurrence k kind lam =
let kind = occurrence_args k kind ltypes in
let _ = occurrence_args (k+Array.length ids) false lbodies in
kind
- | Lproj(_,_,arg) ->
+ | Lproj(_,arg) ->
occurrence k kind arg
| Luint u -> occurrence_uint k kind u
@@ -708,10 +708,8 @@ let rec lambda_of_constr env c =
Lcofix(init, (names, ltypes, lbodies))
| Proj (p,c) ->
- let pb = lookup_projection p env.global_env in
- let n = pb.proj_arg in
let lc = lambda_of_constr env c in
- Lproj (n,Projection.constant p,lc)
+ Lproj (Projection.repr p,lc)
and lambda_of_app env f args =
match Constr.kind f with
@@ -814,7 +812,7 @@ let optimize_lambda lam =
let lambda_of_constr ~optimize genv c =
let env = Renv.make genv in
- let ids = List.rev_map Context.Rel.Declaration.get_name genv.env_rel_context.env_rel_ctx in
+ let ids = List.rev_map Context.Rel.Declaration.get_name (rel_context genv) in
Renv.push_rels env (Array.of_list ids);
let lam = lambda_of_constr env c in
let lam = if optimize then optimize_lambda lam else lam in
diff --git a/kernel/constr.ml b/kernel/constr.ml
index 4182293301..9bf743152f 100644
--- a/kernel/constr.ml
+++ b/kernel/constr.ml
@@ -130,8 +130,8 @@ let mkProp = Sort Sorts.prop
let mkSet = Sort Sorts.set
let mkType u = Sort (Sorts.Type u)
let mkSort = function
- | Sorts.Prop Sorts.Null -> mkProp (* Easy sharing *)
- | Sorts.Prop Sorts.Pos -> mkSet
+ | Sorts.Prop -> mkProp (* Easy sharing *)
+ | Sorts.Set -> mkSet
| s -> Sort s
(* Constructs the term t1::t2, i.e. the term t1 casted with the type t2 *)
@@ -260,17 +260,17 @@ let isSort c = match kind c with
| _ -> false
let rec isprop c = match kind c with
- | Sort (Sorts.Prop _) -> true
+ | Sort (Sorts.Prop | Sorts.Set) -> true
| Cast (c,_,_) -> isprop c
| _ -> false
let rec is_Prop c = match kind c with
- | Sort (Sorts.Prop Sorts.Null) -> true
+ | Sort Sorts.Prop -> true
| Cast (c,_,_) -> is_Prop c
| _ -> false
let rec is_Set c = match kind c with
- | Sort (Sorts.Prop Sorts.Pos) -> true
+ | Sort Sorts.Set -> true
| Cast (c,_,_) -> is_Set c
| _ -> false
@@ -828,8 +828,10 @@ let leq_constr_univs_infer univs m n =
let u1 = Sorts.univ_of_sort s1 and u2 = Sorts.univ_of_sort s2 in
if UGraph.check_leq univs u1 u2 then true
else
- (cstrs := Univ.enforce_leq u1 u2 !cstrs;
- true)
+ (try let c, _ = UGraph.enforce_leq_alg u1 u2 univs in
+ cstrs := Univ.Constraint.union c !cstrs;
+ true
+ with Univ.UniverseInconsistency _ -> false)
in
let rec eq_constr' nargs m n =
m == n || compare_head_gen eq_universes eq_sorts eq_constr' nargs m n
@@ -1207,3 +1209,10 @@ let hcons =
Id.hcons)
(* let hcons_types = hcons_constr *)
+
+type rel_declaration = (constr, types) Context.Rel.Declaration.pt
+type named_declaration = (constr, types) Context.Named.Declaration.pt
+type compacted_declaration = (constr, types) Context.Compacted.Declaration.pt
+type rel_context = rel_declaration list
+type named_context = named_declaration list
+type compacted_context = compacted_declaration list
diff --git a/kernel/constr.mli b/kernel/constr.mli
index bf7b5e87b5..70acf19328 100644
--- a/kernel/constr.mli
+++ b/kernel/constr.mli
@@ -372,6 +372,15 @@ val eq_constr_nounivs : constr -> constr -> bool
(** Total ordering compatible with [equal] *)
val compare : constr -> constr -> int
+(** {6 Extension of Context with declarations on constr} *)
+
+type rel_declaration = (constr, types) Context.Rel.Declaration.pt
+type named_declaration = (constr, types) Context.Named.Declaration.pt
+type compacted_declaration = (constr, types) Context.Compacted.Declaration.pt
+type rel_context = rel_declaration list
+type named_context = named_declaration list
+type compacted_context = compacted_declaration list
+
(** {6 Functionals working on the immediate subterm of a construction } *)
(** [fold f acc c] folds [f] on the immediate subterms of [c]
diff --git a/kernel/context.ml b/kernel/context.ml
index 5d4a101840..4a7204b75c 100644
--- a/kernel/context.ml
+++ b/kernel/context.ml
@@ -43,8 +43,6 @@ struct
| LocalAssum of Name.t * 'types (** name, type *)
| LocalDef of Name.t * 'constr * 'types (** name, value, type *)
- type t = (Constr.constr, Constr.types) pt
-
(** Return the name bound by a given declaration. *)
let get_name = function
| LocalAssum (na,_)
@@ -151,13 +149,16 @@ struct
| LocalAssum (na, ty) -> na, None, ty
| LocalDef (na, v, ty) -> na, Some v, ty
+ let drop_body = function
+ | LocalAssum _ as d -> d
+ | LocalDef (na, v, ty) -> LocalAssum (na, ty)
+
end
(** Rel-context is represented as a list of declarations.
Inner-most declarations are at the beginning of the list.
Outer-most declarations are at the end of the list. *)
type ('constr, 'types) pt = ('constr, 'types) Declaration.pt list
- type t = Declaration.t list
(** empty rel-context *)
let empty = []
@@ -214,6 +215,8 @@ struct
| Declaration.LocalAssum _ :: ctx -> aux (false::l) ctx
in aux [] l
+ let drop_bodies l = List.Smart.map Declaration.drop_body l
+
(** [extended_list n Γ] builds an instance [args] such that [Γ,Δ ⊢ args:Γ]
with n = |Δ| and with the {e local definitions} of [Γ] skipped in
[args]. Example: for [x:T, y:=c, z:U] and [n]=2, it gives [Rel 5, Rel 3]. *)
@@ -241,8 +244,6 @@ struct
| LocalAssum of Id.t * 'types (** identifier, type *)
| LocalDef of Id.t * 'constr * 'types (** identifier, value, type *)
- type t = (Constr.constr, Constr.types) pt
-
(** Return the identifier bound by a given declaration. *)
let get_id = function
| LocalAssum (id,_) -> id
@@ -353,6 +354,10 @@ struct
| id, None, ty -> LocalAssum (id, ty)
| id, Some v, ty -> LocalDef (id, v, ty)
+ let drop_body = function
+ | LocalAssum _ as d -> d
+ | LocalDef (id, v, ty) -> LocalAssum (id, ty)
+
let of_rel_decl f = function
| Rel.Declaration.LocalAssum (na,t) ->
LocalAssum (f na, t)
@@ -370,7 +375,6 @@ struct
Inner-most declarations are at the beginning of the list.
Outer-most declarations are at the end of the list. *)
type ('constr, 'types) pt = ('constr, 'types) Declaration.pt list
- type t = Declaration.t list
(** empty named-context *)
let empty = []
@@ -409,6 +413,8 @@ struct
let to_vars l =
List.fold_left (fun accu decl -> Id.Set.add (Declaration.get_id decl) accu) Id.Set.empty l
+ let drop_bodies l = List.Smart.map Declaration.drop_body l
+
(** [instance_from_named_context Ω] builds an instance [args] such
that [Ω ⊢ args:Ω] where [Ω] is a named context and with the local
definitions of [Ω] skipped. Example: for [id1:T,id2:=c,id3:U], it
@@ -429,8 +435,6 @@ module Compacted =
| LocalAssum of Id.t list * 'types
| LocalDef of Id.t list * 'constr * 'types
- type t = (Constr.constr, Constr.types) pt
-
let map_constr f = function
| LocalAssum (ids, ty) as decl ->
let ty' = f ty in
@@ -454,7 +458,6 @@ module Compacted =
end
type ('constr, 'types) pt = ('constr, 'types) Declaration.pt list
- type t = Declaration.t list
let fold f l ~init = List.fold_right f l init
end
diff --git a/kernel/context.mli b/kernel/context.mli
index c97db4348e..2b0d36cb8c 100644
--- a/kernel/context.mli
+++ b/kernel/context.mli
@@ -35,8 +35,6 @@ sig
| LocalAssum of Name.t * 'types (** name, type *)
| LocalDef of Name.t * 'constr * 'types (** name, value, type *)
- type t = (Constr.constr, Constr.types) pt
-
(** Return the name bound by a given declaration. *)
val get_name : ('c, 't) pt -> Name.t
@@ -87,13 +85,15 @@ sig
val fold_constr : ('c -> 'a -> 'a) -> ('c, 'c) pt -> 'a -> 'a
val to_tuple : ('c, 't) pt -> Name.t * 'c option * 't
+
+ (** Turn [LocalDef] into [LocalAssum], identity otherwise. *)
+ val drop_body : ('c, 't) pt -> ('c, 't) pt
end
(** Rel-context is represented as a list of declarations.
Inner-most declarations are at the beginning of the list.
Outer-most declarations are at the end of the list. *)
type ('constr, 'types) pt = ('constr, 'types) Declaration.pt list
- type t = Declaration.t list
(** empty rel-context *)
val empty : ('c, 't) pt
@@ -132,6 +132,9 @@ sig
and each {e local definition} is mapped to [false]. *)
val to_tags : ('c, 't) pt -> bool list
+ (** Turn all [LocalDef] into [LocalAssum], leave [LocalAssum] unchanged. *)
+ val drop_bodies : ('c, 't) pt -> ('c, 't) pt
+
(** [extended_list mk n Γ] builds an instance [args] such that [Γ,Δ ⊢ args:Γ]
with n = |Δ| and with the {e local definitions} of [Γ] skipped in
[args] where [mk] is used to build the corresponding variables.
@@ -153,8 +156,6 @@ sig
| LocalAssum of Id.t * 'types (** identifier, type *)
| LocalDef of Id.t * 'constr * 'types (** identifier, value, type *)
- type t = (Constr.constr, Constr.types) pt
-
(** Return the identifier bound by a given declaration. *)
val get_id : ('c, 't) pt -> Id.t
@@ -207,6 +208,9 @@ sig
val to_tuple : ('c, 't) pt -> Id.t * 'c option * 't
val of_tuple : Id.t * 'c option * 't -> ('c, 't) pt
+ (** Turn [LocalDef] into [LocalAssum], identity otherwise. *)
+ val drop_body : ('c, 't) pt -> ('c, 't) pt
+
(** Convert [Rel.Declaration.t] value to the corresponding [Named.Declaration.t] value.
The function provided as the first parameter determines how to translate "names" to "ids". *)
val of_rel_decl : (Name.t -> Id.t) -> ('c, 't) Rel.Declaration.pt -> ('c, 't) pt
@@ -220,7 +224,6 @@ sig
Inner-most declarations are at the beginning of the list.
Outer-most declarations are at the end of the list. *)
type ('constr, 'types) pt = ('constr, 'types) Declaration.pt list
- type t = Declaration.t list
(** empty named-context *)
val empty : ('c, 't) pt
@@ -255,6 +258,9 @@ sig
(** Return the set of all identifiers bound in a given named-context. *)
val to_vars : ('c, 't) pt -> Id.Set.t
+ (** Turn all [LocalDef] into [LocalAssum], leave [LocalAssum] unchanged. *)
+ val drop_bodies : ('c, 't) pt -> ('c, 't) pt
+
(** [to_instance Ω] builds an instance [args] such
that [Ω ⊢ args:Ω] where [Ω] is a named-context and with the local
definitions of [Ω] skipped. Example: for [id1:T,id2:=c,id3:U], it
@@ -270,15 +276,12 @@ sig
| LocalAssum of Id.t list * 'types
| LocalDef of Id.t list * 'constr * 'types
- type t = (Constr.constr, Constr.types) pt
-
val map_constr : ('c -> 'c) -> ('c, 'c) pt -> ('c, 'c) pt
val of_named_decl : ('c, 't) Named.Declaration.pt -> ('c, 't) pt
val to_named_context : ('c, 't) pt -> ('c, 't) Named.pt
end
type ('constr, 'types) pt = ('constr, 'types) Declaration.pt list
- type t = Declaration.t list
val fold : (('c, 't) Declaration.pt -> 'a -> 'a) -> ('c, 't) pt -> init:'a -> 'a
end
diff --git a/kernel/cooking.ml b/kernel/cooking.ml
index c7a84f6170..c06358054e 100644
--- a/kernel/cooking.ml
+++ b/kernel/cooking.ml
@@ -126,16 +126,13 @@ let expmod_constr cache modlist c =
| Not_found -> Constr.map substrec c)
| Proj (p, c') ->
- (try
- (** No need to expand parameters or universes for projections *)
- let map cst =
- let _ = Cmap.find cst (fst modlist) in
- pop_con cst
- in
- let p = Projection.map map p in
- let c' = substrec c' in
- mkProj (p, c')
- with Not_found -> Constr.map substrec c)
+ let map cst npars =
+ let _, newpars = Mindmap.find cst (snd modlist) in
+ pop_mind cst, npars + Array.length newpars
+ in
+ let p' = try Projection.map_npars map p with Not_found -> p in
+ let c'' = substrec c' in
+ if p == p' && c' == c'' then c else mkProj (p', c'')
| _ -> Constr.map substrec c
@@ -157,7 +154,7 @@ type result = {
cook_type : types;
cook_universes : constant_universes;
cook_inline : inline;
- cook_context : Context.Named.t option;
+ cook_context : Constr.named_context option;
}
let on_body ml hy f = function
@@ -204,7 +201,7 @@ let lift_univs cb subst auctx0 =
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 cook_constant ~hcons { from = cb; info } =
let { Opaqueproof.modlist; abstract } = info in
let cache = RefTable.create 13 in
let abstract, usubst, abs_ctx = abstract in
diff --git a/kernel/cooking.mli b/kernel/cooking.mli
index 76c79335f1..6ebe691b83 100644
--- a/kernel/cooking.mli
+++ b/kernel/cooking.mli
@@ -10,7 +10,6 @@
open Constr
open Declarations
-open Environ
(** {6 Cooking the constants. } *)
@@ -23,10 +22,10 @@ type result = {
cook_type : types;
cook_universes : constant_universes;
cook_inline : inline;
- cook_context : Context.Named.t option;
+ cook_context : Constr.named_context option;
}
-val cook_constant : hcons:bool -> env -> recipe -> result
+val cook_constant : hcons:bool -> recipe -> result
val cook_constr : Opaqueproof.cooking_info -> constr -> constr
(** {6 Utility functions used in module [Discharge]. } *)
diff --git a/kernel/csymtable.ml b/kernel/csymtable.ml
index bbe0937820..bb9231d000 100644
--- a/kernel/csymtable.ml
+++ b/kernel/csymtable.ml
@@ -77,11 +77,7 @@ module AnnotTable = Hashtbl.Make (struct
let hash = hash_annot_switch
end)
-module ProjNameTable = Hashtbl.Make (struct
- type t = Constant.t
- let equal = Constant.equal
- let hash = Constant.hash
-end)
+module ProjNameTable = Hashtbl.Make (Projection.Repr)
let str_cst_tbl : int SConstTable.t = SConstTable.create 31
diff --git a/kernel/declarations.ml b/kernel/declarations.ml
index 58fb5d66b7..1d49550442 100644
--- a/kernel/declarations.ml
+++ b/kernel/declarations.ml
@@ -46,16 +46,6 @@ type inline = int option
(** A constant can have no body (axiom/parameter), or a
transparent body, or an opaque one *)
-(** Projections are a particular kind of constant:
- always transparent. *)
-
-type projection_body = {
- proj_ind : inductive;
- proj_npars : int;
- proj_arg : int; (** Projection index, starting from 0 *)
- proj_type : types; (* Type under params *)
-}
-
(* Global declarations (i.e. constants) can be either: *)
type constant_def =
| Undef of inline (** a global assumption *)
@@ -75,12 +65,13 @@ type typing_flags = {
points are assumed to be total. *)
check_universes : bool; (** If [false] universe constraints are not checked *)
conv_oracle : Conv_oracle.oracle; (** Unfolding strategies for conversion *)
+ share_reduction : bool; (** Use by-need reduction algorithm *)
}
(* some contraints are in constant_constraints, some other may be in
* the OpaqueDef *)
type constant_body = {
- const_hyps : Context.Named.t; (** New: younger hyp at top *)
+ const_hyps : Constr.named_context; (** New: younger hyp at top *)
const_body : constant_def;
const_type : types;
const_body_code : Cemitcodes.to_patch_substituted option;
@@ -114,7 +105,7 @@ v}
If it is a primitive record, for every type in the block, we get:
- The identifier for the binder name of the record in primitive projections.
- The constants associated to each projection.
- - The checked projection bodies.
+ - The projection types (under parameters).
The kernel does not exploit the difference between [NotRecord] and
[FakeRecord]. It is mostly used by extraction, and should be extruded from
@@ -124,7 +115,7 @@ v}
type record_info =
| NotRecord
| FakeRecord
-| PrimRecord of (Id.t * Constant.t array * projection_body array) array
+| PrimRecord of (Id.t * Label.t array * types array) array
type regular_inductive_arity = {
mind_user_arity : types;
@@ -138,7 +129,7 @@ type one_inductive_body = {
mind_typename : Id.t; (** Name of the type: [Ii] *)
- mind_arity_ctxt : Context.Rel.t; (** Arity context of [Ii] with parameters: [forall params, Ui] *)
+ mind_arity_ctxt : Constr.rel_context; (** Arity context of [Ii] with parameters: [forall params, Ui] *)
mind_arity : inductive_arity; (** Arity sort and original user arity *)
@@ -196,13 +187,13 @@ type mutual_inductive_body = {
mind_ntypes : int; (** Number of types in the block *)
- mind_hyps : Context.Named.t; (** Section hypotheses on which the block depends *)
+ mind_hyps : Constr.named_context; (** Section hypotheses on which the block depends *)
mind_nparams : int; (** Number of expected parameters including non-uniform ones (i.e. length of mind_params_ctxt w/o let-in) *)
mind_nparams_rec : int; (** Number of recursively uniform (i.e. ordinary) parameters *)
- mind_params_ctxt : Context.Rel.t; (** The context of parameters (includes let-in declaration) *)
+ mind_params_ctxt : Constr.rel_context; (** The context of parameters (includes let-in declaration) *)
mind_universes : abstract_inductive_universes; (** Information about monomorphic/polymorphic/cumulative inductives and their universes *)
diff --git a/kernel/declareops.ml b/kernel/declareops.ml
index 5db5de21b4..51ec3defb3 100644
--- a/kernel/declareops.ml
+++ b/kernel/declareops.ml
@@ -21,6 +21,7 @@ let safe_flags oracle = {
check_guarded = true;
check_universes = true;
conv_oracle = oracle;
+ share_reduction = true;
}
(** {6 Arities } *)
@@ -83,11 +84,6 @@ let subst_const_def sub def = match def with
| Def c -> Def (subst_constr sub c)
| OpaqueDef o -> OpaqueDef (Opaqueproof.subst_opaque sub o)
-let subst_const_proj sub pb =
- { pb with proj_ind = subst_ind sub pb.proj_ind;
- proj_type = subst_mps sub pb.proj_type;
- }
-
let subst_const_body sub cb =
assert (List.is_empty cb.const_hyps); (* we're outside sections *)
if is_empty_subst sub then cb
@@ -213,10 +209,9 @@ let subst_mind_record sub r = match r with
| FakeRecord -> FakeRecord
| PrimRecord infos ->
let map (id, ps, pb as info) =
- let ps' = Array.Smart.map (subst_constant sub) ps in
- let pb' = Array.Smart.map (subst_const_proj sub) pb in
- if ps' == ps && pb' == pb then info
- else (id, ps', pb')
+ let pb' = Array.Smart.map (subst_mps sub) pb in
+ if pb' == pb then info
+ else (id, ps, pb')
in
let infos' = Array.Smart.map map infos in
if infos' == infos then r else PrimRecord infos'
@@ -254,6 +249,25 @@ let inductive_is_cumulative mib =
| Polymorphic_ind ctx -> false
| Cumulative_ind cumi -> true
+let inductive_make_projection ind mib ~proj_arg =
+ match mib.mind_record with
+ | NotRecord | FakeRecord -> None
+ | PrimRecord infos ->
+ Some (Names.Projection.Repr.make ind
+ ~proj_npars:mib.mind_nparams
+ ~proj_arg
+ (pi2 infos.(snd ind)).(proj_arg))
+
+let inductive_make_projections ind mib =
+ match mib.mind_record with
+ | NotRecord | FakeRecord -> None
+ | PrimRecord infos ->
+ let projs = Array.mapi (fun proj_arg lab ->
+ Names.Projection.Repr.make ind ~proj_npars:mib.mind_nparams ~proj_arg lab)
+ (pi2 infos.(snd ind))
+ in
+ Some projs
+
(** {6 Hash-consing of inductive declarations } *)
let hcons_regular_ind_arity a =
diff --git a/kernel/declareops.mli b/kernel/declareops.mli
index 7170a8b642..35490ceef9 100644
--- a/kernel/declareops.mli
+++ b/kernel/declareops.mli
@@ -61,6 +61,11 @@ val inductive_is_polymorphic : mutual_inductive_body -> bool
(** Is the inductive cumulative? *)
val inductive_is_cumulative : mutual_inductive_body -> bool
+val inductive_make_projection : Names.inductive -> mutual_inductive_body -> proj_arg:int ->
+ Names.Projection.Repr.t option
+val inductive_make_projections : Names.inductive -> mutual_inductive_body ->
+ Names.Projection.Repr.t array option
+
(** {6 Kernel flags} *)
(** A default, safe set of flags for kernel type-checking *)
diff --git a/kernel/entries.ml b/kernel/entries.ml
index 53284e0e9a..94248ad26b 100644
--- a/kernel/entries.ml
+++ b/kernel/entries.ml
@@ -75,7 +75,7 @@ type 'a in_constant_universes_entry = 'a * constant_universes_entry
type 'a definition_entry = {
const_entry_body : 'a const_entry_body;
(* List of section variables *)
- const_entry_secctx : Context.Named.t option;
+ const_entry_secctx : Constr.named_context option;
(* State id on which the completion of type checking is reported *)
const_entry_feedback : Stateid.t option;
const_entry_type : types option;
@@ -85,7 +85,7 @@ type 'a definition_entry = {
type section_def_entry = {
secdef_body : constr;
- secdef_secctx : Context.Named.t option;
+ secdef_secctx : Constr.named_context option;
secdef_feedback : Stateid.t option;
secdef_type : types option;
}
@@ -93,7 +93,7 @@ type section_def_entry = {
type inline = int option (* inlining level, None for no inlining *)
type parameter_entry =
- Context.Named.t option * types in_constant_universes_entry * inline
+ Constr.named_context option * types in_constant_universes_entry * inline
type 'a constant_entry =
| DefinitionEntry of 'a definition_entry
diff --git a/kernel/environ.ml b/kernel/environ.ml
index 0e34a71650..e7efa5e2c9 100644
--- a/kernel/environ.ml
+++ b/kernel/environ.ml
@@ -52,10 +52,10 @@ type mind_key = mutual_inductive_body * link_info ref
type globals = {
env_constants : constant_key Cmap_env.t;
- env_projections : projection_body Cmap_env.t;
env_inductives : mind_key Mindmap_env.t;
env_modules : module_body MPmap.t;
- env_modtypes : module_type_body MPmap.t}
+ env_modtypes : module_type_body MPmap.t;
+}
type stratification = {
env_universes : UGraph.t;
@@ -76,17 +76,17 @@ let dummy_lazy_val () = ref VKnone
let build_lazy_val vk key = vk := VKvalue (CEphemeron.create key)
type named_context_val = {
- env_named_ctx : Context.Named.t;
- env_named_map : (Context.Named.Declaration.t * lazy_val) Id.Map.t;
+ env_named_ctx : Constr.named_context;
+ env_named_map : (Constr.named_declaration * 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;
+ env_rel_ctx : Constr.rel_context;
+ env_rel_map : (Constr.rel_declaration * lazy_val) Range.t;
}
type env = {
- env_globals : globals; (* globals = constants + inductive types + modules + module-types *)
+ env_globals : globals;
env_named_context : named_context_val; (* section variables *)
env_rel_context : rel_context_val;
env_nb_rel : int;
@@ -109,7 +109,6 @@ let empty_rel_context_val = {
let empty_env = {
env_globals = {
env_constants = Cmap_env.empty;
- env_projections = Cmap_env.empty;
env_inductives = Mindmap_env.empty;
env_modules = MPmap.empty;
env_modtypes = MPmap.empty};
@@ -208,6 +207,9 @@ let lookup_named_val id env =
let lookup_named_ctxt id ctxt =
fst (Id.Map.find id ctxt.env_named_map)
+let fold_constants f env acc =
+ Cmap_env.fold (fun c (body,_) acc -> f c body acc) env.env_globals.env_constants acc
+
(* Global constants *)
let lookup_constant_key kn env =
@@ -486,11 +488,24 @@ let polymorphic_pconstant (cst,u) env =
let type_in_type_constant cst env =
not (lookup_constant cst env).const_typing_flags.check_universes
-let lookup_projection cst env =
- Cmap_env.find (Projection.constant cst) env.env_globals.env_projections
-
-let is_projection cst env =
- Cmap_env.mem cst env.env_globals.env_projections
+let lookup_projection p env =
+ let mind,i = Projection.inductive p in
+ let mib = lookup_mind mind env in
+ (if not (Int.equal mib.mind_nparams (Projection.npars p))
+ then anomaly ~label:"lookup_projection" Pp.(str "Bad number of parameters on projection."));
+ match mib.mind_record with
+ | NotRecord | FakeRecord -> anomaly ~label:"lookup_projection" Pp.(str "not a projection")
+ | PrimRecord infos ->
+ let _,_,typs = infos.(i) in
+ typs.(Projection.arg p)
+
+let get_projection env ind ~proj_arg =
+ let mib = lookup_mind (fst ind) env in
+ Declareops.inductive_make_projection ind mib ~proj_arg
+
+let get_projections env ind =
+ let mib = lookup_mind (fst ind) env in
+ Declareops.inductive_make_projections ind mib
(* Mutual Inductives *)
let polymorphic_ind (mind,i) env =
@@ -514,17 +529,9 @@ let template_polymorphic_pind (ind,u) env =
let add_mind_key kn (mind, _ as mind_key) env =
let new_inds = Mindmap_env.add kn mind_key env.env_globals.env_inductives in
- let new_projections = match mind.mind_record with
- | NotRecord | FakeRecord -> env.env_globals.env_projections
- | PrimRecord projs ->
- Array.fold_left (fun accu (id, kns, pbs) ->
- Array.fold_left2 (fun accu kn pb ->
- Cmap_env.add kn pb accu) accu kns pbs)
- env.env_globals.env_projections projs
- in
let new_globals =
{ env.env_globals with
- env_inductives = new_inds; env_projections = new_projections; } in
+ env_inductives = new_inds; } in
{ env with env_globals = new_globals }
let add_mind kn mib env =
diff --git a/kernel/environ.mli b/kernel/environ.mli
index 8928b32f1b..f45b7be821 100644
--- a/kernel/environ.mli
+++ b/kernel/environ.mli
@@ -46,13 +46,8 @@ type constant_key = constant_body * (link_info ref * key)
type mind_key = mutual_inductive_body * link_info ref
-type globals = {
- env_constants : constant_key Cmap_env.t;
- env_projections : projection_body Cmap_env.t;
- env_inductives : mind_key Mindmap_env.t;
- env_modules : module_body MPmap.t;
- env_modtypes : module_type_body MPmap.t
-}
+type globals
+(** globals = constants + projections + inductive types + modules + module-types *)
type stratification = {
env_universes : UGraph.t;
@@ -60,17 +55,17 @@ type stratification = {
}
type named_context_val = private {
- env_named_ctx : Context.Named.t;
- env_named_map : (Context.Named.Declaration.t * lazy_val) Id.Map.t;
+ env_named_ctx : Constr.named_context;
+ env_named_map : (Constr.named_declaration * 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;
+ env_rel_ctx : Constr.rel_context;
+ env_rel_map : (Constr.rel_declaration * lazy_val) Range.t;
}
type env = private {
- env_globals : globals; (* globals = constants + inductive types + modules + module-types *)
+ env_globals : globals;
env_named_context : named_context_val; (* section variables *)
env_rel_context : rel_context_val;
env_nb_rel : int;
@@ -88,8 +83,8 @@ val eq_named_context_val : named_context_val -> named_context_val -> bool
val empty_env : env
val universes : env -> UGraph.t
-val rel_context : env -> Context.Rel.t
-val named_context : env -> Context.Named.t
+val rel_context : env -> Constr.rel_context
+val named_context : env -> Constr.named_context
val named_context_val : env -> named_context_val
val opaque_tables : env -> Opaqueproof.opaquetab
@@ -108,13 +103,13 @@ val empty_context : env -> bool
(** {5 Context of de Bruijn variables ([rel_context]) } *)
val nb_rel : env -> int
-val push_rel : Context.Rel.Declaration.t -> env -> env
-val push_rel_context : Context.Rel.t -> env -> env
+val push_rel : Constr.rel_declaration -> env -> env
+val push_rel_context : Constr.rel_context -> env -> env
val push_rec_types : rec_declaration -> env -> env
(** Looks up in the context of local vars referred by indice ([rel_context])
raises [Not_found] if the index points out of the context *)
-val lookup_rel : int -> env -> Context.Rel.Declaration.t
+val lookup_rel : int -> env -> Constr.rel_declaration
val lookup_rel_val : int -> env -> lazy_val
val evaluable_rel : int -> env -> bool
val env_of_rel : int -> env -> env
@@ -122,12 +117,12 @@ val env_of_rel : int -> env -> env
(** {6 Recurrence on [rel_context] } *)
val fold_rel_context :
- (env -> Context.Rel.Declaration.t -> 'a -> 'a) -> env -> init:'a -> 'a
+ (env -> Constr.rel_declaration -> 'a -> 'a) -> env -> init:'a -> 'a
(** {5 Context of variables (section variables and goal assumptions) } *)
-val named_context_of_val : named_context_val -> Context.Named.t
-val val_of_named_context : Context.Named.t -> named_context_val
+val named_context_of_val : named_context_val -> Constr.named_context
+val val_of_named_context : Constr.named_context -> named_context_val
val empty_named_context_val : named_context_val
val ids_of_named_context_val : named_context_val -> Id.Set.t
@@ -138,19 +133,19 @@ val ids_of_named_context_val : named_context_val -> Id.Set.t
val map_named_val :
(constr -> constr) -> named_context_val -> named_context_val
-val push_named : Context.Named.Declaration.t -> env -> env
-val push_named_context : Context.Named.t -> env -> env
+val push_named : Constr.named_declaration -> env -> env
+val push_named_context : Constr.named_context -> env -> env
val push_named_context_val :
- Context.Named.Declaration.t -> named_context_val -> named_context_val
+ Constr.named_declaration -> named_context_val -> named_context_val
(** Looks up in the context of local vars referred by names ([named_context])
raises [Not_found] if the Id.t is not found *)
-val lookup_named : variable -> env -> Context.Named.Declaration.t
+val lookup_named : variable -> env -> Constr.named_declaration
val lookup_named_val : variable -> env -> lazy_val
-val lookup_named_ctxt : variable -> named_context_val -> Context.Named.Declaration.t
+val lookup_named_ctxt : variable -> named_context_val -> Constr.named_declaration
val evaluable_named : variable -> env -> bool
val named_type : variable -> env -> types
val named_body : variable -> env -> constr option
@@ -158,13 +153,13 @@ val named_body : variable -> env -> constr option
(** {6 Recurrence on [named_context]: older declarations processed first } *)
val fold_named_context :
- (env -> Context.Named.Declaration.t -> 'a -> 'a) -> env -> init:'a -> 'a
+ (env -> Constr.named_declaration -> 'a -> 'a) -> env -> init:'a -> 'a
val set_universes : env -> UGraph.t -> env
(** Recurrence on [named_context] starting from younger decl *)
val fold_named_context_reverse :
- ('a -> Context.Named.Declaration.t -> 'a) -> init:'a -> env -> 'a
+ ('a -> Constr.named_declaration -> 'a) -> init:'a -> env -> 'a
(** This forgets named and rel contexts *)
val reset_context : env -> env
@@ -175,6 +170,9 @@ val reset_with_named_context : named_context_val -> env -> env
(** This removes the [n] last declarations from the rel context *)
val pop_rel_context : int -> env -> env
+(** Useful for printing *)
+val fold_constants : (Constant.t -> constant_body -> 'a -> 'a) -> env -> 'a -> 'a
+
(** {5 Global constants }
{6 Add entries to global environment } *)
@@ -219,8 +217,11 @@ val constant_opt_value_in : env -> Constant.t puniverses -> constr option
(** {6 Primitive projections} *)
-val lookup_projection : Names.Projection.t -> env -> projection_body
-val is_projection : Constant.t -> env -> bool
+(** Checks that the number of parameters is correct. *)
+val lookup_projection : Names.Projection.t -> env -> types
+
+val get_projection : env -> inductive -> proj_arg:int -> Names.Projection.Repr.t option
+val get_projections : env -> inductive -> Names.Projection.Repr.t array option
(** {5 Inductive types } *)
val lookup_mind_key : MutInd.t -> env -> mind_key
@@ -280,7 +281,7 @@ val vars_of_global : env -> constr -> Id.Set.t
val really_needed : env -> Id.Set.t -> Id.Set.t
(** like [really_needed] but computes a well ordered named context *)
-val keep_hyps : env -> Id.Set.t -> Context.Named.t
+val keep_hyps : env -> Id.Set.t -> Constr.named_context
(** {5 Unsafe judgments. }
We introduce here the pre-type of judgments, which is
@@ -309,10 +310,10 @@ exception Hyp_not_found
return [tail::(f head (id,_,_) (rev tail))::head].
the value associated to id should not change *)
val apply_to_hyp : named_context_val -> variable ->
- (Context.Named.t -> Context.Named.Declaration.t -> Context.Named.t -> Context.Named.Declaration.t) ->
+ (Constr.named_context -> Constr.named_declaration -> Constr.named_context -> Constr.named_declaration) ->
named_context_val
-val remove_hyps : Id.Set.t -> (Context.Named.Declaration.t -> Context.Named.Declaration.t) -> (lazy_val -> lazy_val) -> named_context_val -> named_context_val
+val remove_hyps : Id.Set.t -> (Constr.named_declaration -> Constr.named_declaration) -> (lazy_val -> lazy_val) -> named_context_val -> named_context_val
@@ -320,6 +321,7 @@ open Retroknowledge
(** functions manipulating the retroknowledge
@author spiwack *)
val retroknowledge : (retroknowledge->'a) -> env -> 'a
+[@@ocaml.deprecated "Use the record projection."]
val registered : env -> field -> bool
diff --git a/kernel/indtypes.ml b/kernel/indtypes.ml
index e63f43849a..d7eb865e0a 100644
--- a/kernel/indtypes.ml
+++ b/kernel/indtypes.ml
@@ -120,16 +120,6 @@ let mind_check_names mie =
(* Typing the arities and constructor types *)
-(* An inductive definition is a "unit" if it has only one constructor
- and that all arguments expected by this constructor are
- logical, this is the case for equality, conjunction of logical properties
-*)
-let is_unit constrsinfos =
- match constrsinfos with (* One info = One constructor *)
- | [level] -> is_type0m_univ level
- | [] -> (* type without constructors *) true
- | _ -> false
-
let infos_and_sort env t =
let rec aux env t max =
let t = whd_all env t in
@@ -174,10 +164,9 @@ let infer_constructor_packet env_ar_par params lc =
let lc'' = Array.map (fun j -> Term.it_mkProd_or_LetIn j.utj_val params) jlc in
(* compute the max of the sorts of the products of the constructors types *)
let levels = List.map (infos_and_sort env_ar_par) lc in
- let isunit = is_unit levels in
let min = if Array.length jlc > 1 then Universe.type0 else Universe.type0m in
let level = List.fold_left (fun max l -> Universe.sup max l) min levels in
- (lc'', (isunit, level))
+ (lc'', level)
(* If indices matter *)
let cumulate_arity_large_levels env sign =
@@ -354,7 +343,7 @@ let typecheck_inductive env mie =
(* Compute/check the sorts of the inductive types *)
let inds =
- Array.map (fun ((id,full_arity,sign,expltype,def_level,inf_level),cn,lc,(is_unit,clev)) ->
+ Array.map (fun ((id,full_arity,sign,expltype,def_level,inf_level),cn,lc,clev) ->
let infu =
(** Inferred level, with parameters and constructors. *)
match inf_level with
@@ -425,7 +414,7 @@ let typecheck_inductive env mie =
type ill_formed_ind =
| LocalNonPos of int
| LocalNotEnoughArgs of int
- | LocalNotConstructor of Context.Rel.t * int
+ | LocalNotConstructor of Constr.rel_context * int
| LocalNonPar of int * int * int
exception IllFormedInd of ill_formed_ind
@@ -807,7 +796,6 @@ let compute_projections (kn, i as ind) mib =
let subst = List.init mib.mind_ntypes (fun i -> mkIndU ((kn, mib.mind_ntypes - i - 1), u)) in
let rctx, _ = decompose_prod_assum (substl subst pkt.mind_nf_lc.(0)) in
let ctx, paramslet = List.chop pkt.mind_consnrealdecls.(0) rctx in
- let mp, dp, l = MutInd.repr3 kn in
(** We build a substitution smashing the lets in the record parameters so
that typechecking projections requires just a substitution and not
matching with a parameter context. *)
@@ -821,7 +809,7 @@ let compute_projections (kn, i as ind) mib =
mkRel 1 :: List.map (lift 1) subst in
subst
in
- let projections decl (i, j, kns, pbs, letsubst) =
+ let projections decl (i, j, labs, pbs, letsubst) =
match decl with
| LocalDef (na,c,t) ->
(* From [params, field1,..,fieldj |- c(params,field1,..,fieldj)]
@@ -833,11 +821,12 @@ let compute_projections (kn, i as ind) mib =
(* From [params-wo-let, x:I |- subst:(params, x:I, field1,..,fieldj)]
to [params-wo-let, x:I |- subst:(params, x:I, field1,..,fieldj+1)] *)
let letsubst = c2 :: letsubst in
- (i, j+1, kns, pbs, letsubst)
+ (i, j+1, labs, pbs, letsubst)
| LocalAssum (na,t) ->
match na with
| Name id ->
- let kn = Constant.make1 (KerName.make mp dp (Label.of_id id)) in
+ let lab = Label.of_id id in
+ let kn = Projection.Repr.make ind ~proj_npars:mib.mind_nparams ~proj_arg:i lab in
(* from [params, field1,..,fieldj |- t(params,field1,..,fieldj)]
to [params, x:I, field1,..,fieldj |- t(params,field1,..,fieldj] *)
let t = liftn 1 j t in
@@ -847,15 +836,13 @@ let compute_projections (kn, i as ind) mib =
(* from [params, x:I, field1,..,fieldj |- t(field1,..,fieldj)]
to [params, x:I |- t(proj1 x,..,projj x)] *)
let fterm = mkProj (Projection.make kn false, mkRel 1) in
- let body = { proj_ind = ind; proj_npars = mib.mind_nparams;
- proj_arg = i; proj_type = projty; } in
- (i + 1, j + 1, kn :: kns, body :: pbs, fterm :: letsubst)
+ (i + 1, j + 1, lab :: labs, projty :: pbs, fterm :: letsubst)
| Anonymous -> raise UndefinableExpansion
in
- let (_, _, kns, pbs, letsubst) =
+ let (_, _, labs, pbs, letsubst) =
List.fold_right projections ctx (0, 1, [], [], paramsletsubst)
in
- Array.of_list (List.rev kns),
+ Array.of_list (List.rev labs),
Array.of_list (List.rev pbs)
let abstract_inductive_universes iu =
@@ -965,8 +952,8 @@ let build_inductive env prv iu env_ar paramsctxt kn isrecord isfinite inds nmr r
(** The elimination criterion ensures that all projections can be defined. *)
if Array.for_all is_record packets then
let map i id =
- let kn, projs = compute_projections (kn, i) mib in
- (id, kn, projs)
+ let labs, projs = compute_projections (kn, i) mib in
+ (id, labs, projs)
in
try PrimRecord (Array.mapi map rid)
with UndefinableExpansion -> FakeRecord
diff --git a/kernel/indtypes.mli b/kernel/indtypes.mli
index 7c36dac67d..cb09cfa827 100644
--- a/kernel/indtypes.mli
+++ b/kernel/indtypes.mli
@@ -42,6 +42,3 @@ val check_inductive : env -> MutInd.t -> mutual_inductive_entry -> mutual_induct
val enforce_indices_matter : unit -> unit
val is_indices_matter : unit -> bool
-
-val compute_projections : inductive ->
- mutual_inductive_body -> (Constant.t array * projection_body array)
diff --git a/kernel/inductive.ml b/kernel/inductive.ml
index 9130b8778c..4d13a5fcb8 100644
--- a/kernel/inductive.ml
+++ b/kernel/inductive.ml
@@ -130,11 +130,6 @@ where
Remark: Set (predicative) is encoded as Type(0)
*)
-let sort_as_univ = let open Sorts in function
-| Type u -> u
-| Prop Null -> Universe.type0m
-| Prop Pos -> Universe.type0
-
(* Template polymorphism *)
(* cons_subst add the mapping [u |-> su] in subst if [u] is not *)
@@ -168,7 +163,7 @@ let make_subst env =
(* arity is a global level which, at typing time, will be enforce *)
(* to be greater than the level of the argument; this is probably *)
(* a useless extra constraint *)
- let s = sort_as_univ (snd (dest_arity env (Lazy.force a))) in
+ let s = Sorts.univ_of_sort (snd (dest_arity env (Lazy.force a))) in
make (cons_subst u s subst) (sign, exp, args)
| LocalAssum (na,t) :: sign, Some u::exp, [] ->
(* No more argument here: we add the remaining universes to the *)
@@ -236,8 +231,8 @@ let type_of_inductive_knowing_parameters env ?(polyprop=true) mip args =
(* The max of an array of universes *)
let cumulate_constructor_univ u = let open Sorts in function
- | Prop Null -> u
- | Prop Pos -> Universe.sup Universe.type0 u
+ | Prop -> u
+ | Set -> Universe.sup Universe.type0 u
| Type u' -> Universe.sup u u'
let max_inductive_sort =
@@ -790,7 +785,7 @@ let rec subterm_specif renv stack t =
| Lambda (x,a,b) ->
let () = assert (List.is_empty l) in
- let spec,stack' = extract_stack renv a stack in
+ let spec,stack' = extract_stack stack in
subterm_specif (push_var renv (x,a,spec)) stack' b
(* Metas and evars are considered OK *)
@@ -803,8 +798,7 @@ let rec subterm_specif renv stack t =
(* 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 pb = lookup_projection p renv.env in
- let n = pb.proj_arg in
+ let n = Projection.arg p in
spec_of_tree (List.nth wf_args n)
| Dead_code -> Dead_code
| Not_subterm -> Not_subterm)
@@ -822,7 +816,7 @@ and stack_element_specif = function
|SClosure (h_renv,h) -> lazy_subterm_specif h_renv [] h
|SArg x -> x
-and extract_stack renv a = function
+and extract_stack = function
| [] -> Lazy.from_val Not_subterm , []
| h::t -> stack_element_specif h, t
@@ -853,7 +847,7 @@ let error_illegal_rec_call renv fx (arg_renv,arg) =
let error_partial_apply renv fx =
raise (FixGuardError (renv.env,NotEnoughArgumentsForFixCall fx))
-let filter_stack_domain env ci p stack =
+let filter_stack_domain env p stack =
let absctx, ar = dest_lam_assum env p in
(* Optimization: if the predicate is not dependent, no restriction is needed
and we avoid building the recargs tree. *)
@@ -938,7 +932,7 @@ let check_one_fix renv recpos trees def =
let case_spec = branches_specif renv
(lazy_subterm_specif renv [] c_0) ci in
let stack' = push_stack_closures renv l stack in
- let stack' = filter_stack_domain renv.env ci p stack' in
+ let stack' = filter_stack_domain renv.env p stack' in
Array.iteri (fun k br' ->
let stack_br = push_stack_args case_spec.(k) stack' in
check_rec_call renv stack_br br') lrest
@@ -981,7 +975,7 @@ let check_one_fix renv recpos trees def =
| Lambda (x,a,b) ->
let () = assert (List.is_empty l) in
check_rec_call renv [] a ;
- let spec, stack' = extract_stack renv a stack in
+ let spec, stack' = extract_stack stack in
check_rec_call (push_var renv (x,a,spec)) stack' b
| Prod (x,a,b) ->
diff --git a/kernel/inductive.mli b/kernel/inductive.mli
index c7982f1fc1..3c1464c6c9 100644
--- a/kernel/inductive.mli
+++ b/kernel/inductive.mli
@@ -36,7 +36,7 @@ val lookup_mind_specif : env -> inductive -> mind_specif
(** {6 Functions to build standard types related to inductive } *)
val ind_subst : MutInd.t -> mutual_inductive_body -> Instance.t -> constr list
-val inductive_paramdecls : mutual_inductive_body puniverses -> Context.Rel.t
+val inductive_paramdecls : mutual_inductive_body puniverses -> Constr.rel_context
val instantiate_inductive_constraints :
mutual_inductive_body -> Instance.t -> Constraint.t
@@ -87,7 +87,7 @@ val build_branches_type :
constr list -> constr -> types array
(** Return the arity of an inductive type *)
-val mind_arity : one_inductive_body -> Context.Rel.t * Sorts.family
+val mind_arity : one_inductive_body -> Constr.rel_context * Sorts.family
val inductive_sort_family : one_inductive_body -> Sorts.family
@@ -115,8 +115,8 @@ exception SingletonInductiveBecomesProp of Id.t
val max_inductive_sort : Sorts.t array -> Universe.t
-val instantiate_universes : env -> Context.Rel.t ->
- template_arity -> constr Lazy.t array -> Context.Rel.t * Sorts.t
+val instantiate_universes : env -> Constr.rel_context ->
+ template_arity -> constr Lazy.t array -> Constr.rel_context * Sorts.t
(** {6 Debug} *)
diff --git a/kernel/kernel.mllib b/kernel/kernel.mllib
index 50713b9579..07a02f6ef5 100644
--- a/kernel/kernel.mllib
+++ b/kernel/kernel.mllib
@@ -5,8 +5,8 @@ UGraph
Esubst
Sorts
Evar
-Constr
Context
+Constr
Vars
Term
Mod_subst
diff --git a/kernel/mod_subst.ml b/kernel/mod_subst.ml
index a47af56ca5..b35b9dda31 100644
--- a/kernel/mod_subst.ml
+++ b/kernel/mod_subst.ml
@@ -332,6 +332,12 @@ let subst_constant sub con =
try fst (subst_con0 sub (con,Univ.Instance.empty))
with No_subst -> con
+let subst_proj_repr sub p =
+ Projection.Repr.map (subst_mind sub) p
+
+let subst_proj sub p =
+ Projection.map (subst_mind sub) p
+
(* Here the semantics is completely unclear.
What does "Hint Unfold t" means when "t" is a parameter?
Does the user mean "Unfold X.t" or does she mean "Unfold y"
@@ -346,11 +352,7 @@ let rec map_kn f f' c =
match kind c with
| Const kn -> (try snd (f' kn) with No_subst -> c)
| Proj (p,t) ->
- let p' =
- try
- Projection.map (fun kn -> fst (f' (kn,Univ.Instance.empty))) p
- with No_subst -> p
- in
+ let p' = Projection.map f p in
let t' = func t in
if p' == p && t' == t then c
else mkProj (p', t')
diff --git a/kernel/mod_subst.mli b/kernel/mod_subst.mli
index 76a1d173b9..2e5211c770 100644
--- a/kernel/mod_subst.mli
+++ b/kernel/mod_subst.mli
@@ -147,6 +147,9 @@ val subst_con_kn :
val subst_constant :
substitution -> Constant.t -> Constant.t
+val subst_proj_repr : substitution -> Projection.Repr.t -> Projection.Repr.t
+val subst_proj : substitution -> Projection.t -> Projection.t
+
(** Here the semantics is completely unclear.
What does "Hint Unfold t" means when "t" is a parameter?
Does the user mean "Unfold X.t" or does she mean "Unfold y"
diff --git a/kernel/modops.ml b/kernel/modops.ml
index 22f523a9ae..98a9973117 100644
--- a/kernel/modops.ml
+++ b/kernel/modops.ml
@@ -47,7 +47,6 @@ type signature_mismatch_error =
| RecordFieldExpected of bool
| RecordProjectionsExpected of Name.t list
| NotEqualInductiveAliases
- | NoTypeConstraintExpected
| IncompatibleInstances
| IncompatibleUniverses of Univ.univ_inconsistency
| IncompatiblePolymorphism of env * types * types
@@ -266,7 +265,7 @@ let subst_structure subst = subst_structure subst do_delta_codom
(* spiwack: here comes the function which takes care of importing
the retroknowledge declared in the library *)
(* lclrk : retroknowledge_action list, rkaction : retroknowledge action *)
-let add_retroknowledge mp =
+let add_retroknowledge =
let perform rkaction env = match rkaction with
| Retroknowledge.RKRegister (f, e) when (isConst e || isInd e) ->
Environ.register env f e
@@ -310,7 +309,7 @@ and add_module mb linkinfo env =
let env = Environ.shallow_add_module mb env in
match mb.mod_type with
|NoFunctor struc ->
- add_retroknowledge mp mb.mod_retroknowledge
+ add_retroknowledge mb.mod_retroknowledge
(add_structure mp struc mb.mod_delta linkinfo env)
|MoreFunctor _ -> env
diff --git a/kernel/modops.mli b/kernel/modops.mli
index ac76d28cf3..8e7e618fcd 100644
--- a/kernel/modops.mli
+++ b/kernel/modops.mli
@@ -106,7 +106,6 @@ type signature_mismatch_error =
| RecordFieldExpected of bool
| RecordProjectionsExpected of Name.t list
| NotEqualInductiveAliases
- | NoTypeConstraintExpected
| IncompatibleInstances
| IncompatibleUniverses of Univ.univ_inconsistency
| IncompatiblePolymorphism of env * types * types
diff --git a/kernel/names.ml b/kernel/names.ml
index 1d2a7c4ce5..e1d70e8111 100644
--- a/kernel/names.ml
+++ b/kernel/names.ml
@@ -771,29 +771,141 @@ type module_path = ModPath.t =
module Projection =
struct
- type t = Constant.t * bool
+ module Repr = struct
+ type t =
+ { proj_ind : inductive;
+ proj_npars : int;
+ proj_arg : int;
+ proj_name : Label.t; }
+
+ let make proj_ind ~proj_npars ~proj_arg proj_name =
+ {proj_ind;proj_npars;proj_arg;proj_name}
+
+ let inductive c = c.proj_ind
+
+ let mind c = fst c.proj_ind
+
+ let constant c = KerPair.change_label (mind c) c.proj_name
+
+ let label c = c.proj_name
+
+ let npars c = c.proj_npars
+
+ let arg c = c.proj_arg
+
+ let equal a b =
+ eq_ind a.proj_ind b.proj_ind && Int.equal a.proj_arg b.proj_arg
+
+ let hash p =
+ Hashset.Combine.combinesmall p.proj_arg (ind_hash p.proj_ind)
+
+ module SyntacticOrd = struct
+ let compare a b =
+ let c = ind_syntactic_ord a.proj_ind b.proj_ind in
+ if c == 0 then Int.compare a.proj_arg b.proj_arg
+ else c
+
+ let equal a b =
+ a.proj_arg == b.proj_arg && eq_syntactic_ind a.proj_ind b.proj_ind
+
+ let hash p =
+ Hashset.Combine.combinesmall p.proj_arg (ind_hash p.proj_ind)
+ end
+ module CanOrd = struct
+ let compare a b =
+ let c = ind_ord a.proj_ind b.proj_ind in
+ if c == 0 then Int.compare a.proj_arg b.proj_arg
+ else c
+
+ let equal a b =
+ a.proj_arg == b.proj_arg && eq_ind a.proj_ind b.proj_ind
+
+ let hash p =
+ Hashset.Combine.combinesmall p.proj_arg (ind_hash p.proj_ind)
+ end
+ module UserOrd = struct
+ let compare a b =
+ let c = ind_user_ord a.proj_ind b.proj_ind in
+ if c == 0 then Int.compare a.proj_arg b.proj_arg
+ else c
+
+ let equal a b =
+ a.proj_arg == b.proj_arg && eq_user_ind a.proj_ind b.proj_ind
+
+ let hash p =
+ Hashset.Combine.combinesmall p.proj_arg (ind_user_hash p.proj_ind)
+ end
+
+ let compare a b =
+ let c = ind_ord a.proj_ind b.proj_ind in
+ if c == 0 then Int.compare a.proj_arg b.proj_arg
+ else c
+
+ module Self_Hashcons = struct
+ type nonrec t = t
+ type u = (inductive -> inductive) * (Id.t -> Id.t)
+ let hashcons (hind,hid) p =
+ { proj_ind = hind p.proj_ind;
+ proj_npars = p.proj_npars;
+ proj_arg = p.proj_arg;
+ proj_name = hid p.proj_name }
+ let eq p p' =
+ p == p' || (p.proj_ind == p'.proj_ind && p.proj_npars == p'.proj_npars && p.proj_arg == p'.proj_arg && p.proj_name == p'.proj_name)
+ let hash = hash
+ end
+ module HashRepr = Hashcons.Make(Self_Hashcons)
+ let hcons = Hashcons.simple_hcons HashRepr.generate HashRepr.hcons (hcons_ind,Id.hcons)
+
+ let map_npars f p =
+ let ind = fst p.proj_ind in
+ let npars = p.proj_npars in
+ let ind', npars' = f ind npars in
+ if ind == ind' && npars == npars' then p
+ else {p with proj_ind = (ind',snd p.proj_ind); proj_npars = npars'}
+
+ let map f p = map_npars (fun mind n -> f mind, n) p
+
+ let to_string p = Constant.to_string (constant p)
+ let print p = Constant.print (constant p)
+ end
+
+ type t = Repr.t * bool
let make c b = (c, b)
- let constant = fst
+ let mind (c,_) = Repr.mind c
+ let inductive (c,_) = Repr.inductive c
+ let npars (c,_) = Repr.npars c
+ let arg (c,_) = Repr.arg c
+ let constant (c,_) = Repr.constant c
+ let label (c,_) = Repr.label c
+ let repr = fst
let unfolded = snd
let unfold (c, b as p) = if b then p else (c, true)
- let equal (c, b) (c', b') = Constant.equal c c' && b == b'
- let hash (c, b) = (if b then 0 else 1) + Constant.hash c
+ let equal (c, b) (c', b') = Repr.equal c c' && b == b'
+
+ let hash (c, b) = (if b then 0 else 1) + Repr.hash c
module SyntacticOrd = struct
let compare (c, b) (c', b') =
- if b = b' then Constant.SyntacticOrd.compare c c' else -1
+ if b = b' then Repr.SyntacticOrd.compare c c' else -1
+ let equal (c, b as x) (c', b' as x') =
+ x == x' || b = b' && Repr.SyntacticOrd.equal c c'
+ let hash (c, b) = (if b then 0 else 1) + Repr.SyntacticOrd.hash c
+ end
+ module CanOrd = struct
+ let compare (c, b) (c', b') =
+ if b = b' then Repr.CanOrd.compare c c' else -1
let equal (c, b as x) (c', b' as x') =
- x == x' || b = b' && Constant.SyntacticOrd.equal c c'
- let hash (c, b) = (if b then 0 else 1) + Constant.SyntacticOrd.hash c
+ x == x' || b = b' && Repr.CanOrd.equal c c'
+ let hash (c, b) = (if b then 0 else 1) + Repr.CanOrd.hash c
end
module Self_Hashcons =
struct
type nonrec t = t
- type u = Constant.t -> Constant.t
+ type u = Repr.t -> Repr.t
let hashcons hc (c,b) = (hc c,b)
let eq ((c,b) as x) ((c',b') as y) =
x == y || (c == c' && b == b')
@@ -802,15 +914,19 @@ struct
module HashProjection = Hashcons.Make(Self_Hashcons)
- let hcons = Hashcons.simple_hcons HashProjection.generate HashProjection.hcons hcons_con
+ let hcons = Hashcons.simple_hcons HashProjection.generate HashProjection.hcons Repr.hcons
let compare (c, b) (c', b') =
- if b == b' then Constant.CanOrd.compare c c'
+ if b == b' then Repr.compare c c'
else if b then 1 else -1
let map f (c, b as x) =
- let c' = f c in
- if c' == c then x else (c', b)
+ let c' = Repr.map f c in
+ if c' == c then x else (c', b)
+
+ let map_npars f (c, b as x) =
+ let c' = Repr.map_npars f c in
+ if c' == c then x else (c', b)
let to_string p = Constant.to_string (constant p)
let print p = Constant.print (constant p)
diff --git a/kernel/names.mli b/kernel/names.mli
index 4eb5adb62f..1cdf5c2402 100644
--- a/kernel/names.mli
+++ b/kernel/names.mli
@@ -549,17 +549,68 @@ type module_path = ModPath.t =
[@@ocaml.deprecated "Alias type"]
module Projection : sig
- type t
+ module Repr : sig
+ type t
+
+ val make : inductive -> proj_npars:int -> proj_arg:int -> Label.t -> t
+
+ module SyntacticOrd : sig
+ val compare : t -> t -> int
+ val equal : t -> t -> bool
+ val hash : t -> int
+ end
+ module CanOrd : sig
+ val compare : t -> t -> int
+ val equal : t -> t -> bool
+ val hash : t -> int
+ end
+ module UserOrd : sig
+ val compare : t -> t -> int
+ val equal : t -> t -> bool
+ val hash : t -> int
+ end
+
+ val constant : t -> Constant.t
+ (** Don't use this if you don't have to. *)
+
+ val inductive : t -> inductive
+ val mind : t -> MutInd.t
+ val npars : t -> int
+ val arg : t -> int
+ val label : t -> Label.t
+
+ val equal : t -> t -> bool
+ val hash : t -> int
+ val compare : t -> t -> int
+
+ val map : (MutInd.t -> MutInd.t) -> t -> t
+ val map_npars : (MutInd.t -> int -> MutInd.t * int) -> t -> t
+
+ val print : t -> Pp.t
+ val to_string : t -> string
+ end
+ type t (* = Repr.t * bool *)
- val make : Constant.t -> bool -> t
+ val make : Repr.t -> bool -> t
+ val repr : t -> Repr.t
module SyntacticOrd : sig
val compare : t -> t -> int
val equal : t -> t -> bool
val hash : t -> int
end
+ module CanOrd : sig
+ val compare : t -> t -> int
+ val equal : t -> t -> bool
+ val hash : t -> int
+ end
val constant : t -> Constant.t
+ val mind : t -> MutInd.t
+ val inductive : t -> inductive
+ val npars : t -> int
+ val arg : t -> int
+ val label : t -> Label.t
val unfolded : t -> bool
val unfold : t -> t
@@ -570,7 +621,8 @@ module Projection : sig
val compare : t -> t -> int
- val map : (Constant.t -> Constant.t) -> t -> t
+ val map : (MutInd.t -> MutInd.t) -> t -> t
+ val map_npars : (MutInd.t -> int -> MutInd.t * int) -> t -> t
val to_string : t -> string
val print : t -> Pp.t
diff --git a/kernel/nativecode.ml b/kernel/nativecode.ml
index 6821fc980c..cc35a70cbf 100644
--- a/kernel/nativecode.ml
+++ b/kernel/nativecode.ml
@@ -71,6 +71,8 @@ let eq_gname gn1 gn2 =
String.equal s1 s2 && eq_constructor c1 c2
| Gconstant (s1, c1), Gconstant (s2, c2) ->
String.equal s1 s2 && Constant.equal c1 c2
+ | Gproj (s1, ind1, i1), Gproj (s2, ind2, i2) ->
+ String.equal s1 s2 && eq_ind ind1 ind2 && Int.equal i1 i2
| Gcase (None, i1), Gcase (None, i2) -> Int.equal i1 i2
| Gcase (Some l1, i1), Gcase (Some l2, i2) -> Int.equal i1 i2 && Label.equal l1 l2
| Gpred (None, i1), Gpred (None, i2) -> Int.equal i1 i2
@@ -86,7 +88,9 @@ let eq_gname gn1 gn2 =
| Ginternal s1, Ginternal s2 -> String.equal s1 s2
| Grel i1, Grel i2 -> Int.equal i1 i2
| Gnamed id1, Gnamed id2 -> Id.equal id1 id2
- | _ -> false
+ | (Gind _| Gconstruct _ | Gconstant _ | Gproj _ | Gcase _ | Gpred _
+ | Gfixtype _ | Gnorm _ | Gnormtbl _ | Ginternal _ | Grel _ | Gnamed _), _ ->
+ false
let dummy_gname =
Grel 0
@@ -274,7 +278,6 @@ type primitive =
| Mk_rel of int
| Mk_var of Id.t
| Mk_proj
- | Is_accu
| Is_int
| Cast_accu
| Upd_cofix
@@ -315,7 +318,6 @@ let eq_primitive p1 p2 =
| Mk_cofix i1, Mk_cofix i2 -> Int.equal i1 i2
| Mk_rel i1, Mk_rel i2 -> Int.equal i1 i2
| Mk_var id1, Mk_var id2 -> Id.equal id1 id2
- | Is_accu, Is_accu -> true
| Cast_accu, Cast_accu -> true
| Upd_cofix, Upd_cofix -> true
| Force_cofix, Force_cofix -> true
@@ -341,7 +343,6 @@ let primitive_hash = function
combinesmall 8 (Int.hash i)
| Mk_var id ->
combinesmall 9 (Id.hash id)
- | Is_accu -> 10
| Is_int -> 11
| Cast_accu -> 12
| Upd_cofix -> 13
@@ -392,6 +393,7 @@ type mllambda =
| MLsetref of string * mllambda
| MLsequence of mllambda * mllambda
| MLarray of mllambda array
+ | MLisaccu of string * inductive * mllambda
and mllam_branches = ((constructor * lname option array) list * mllambda) array
@@ -463,7 +465,12 @@ let rec eq_mllambda gn1 gn2 n env1 env2 t1 t2 =
| MLarray arr1, MLarray arr2 ->
Array.equal (eq_mllambda gn1 gn2 n env1 env2) arr1 arr2
- | _, _ -> false
+ | MLisaccu (s1, ind1, ml1), MLisaccu (s2, ind2, ml2) ->
+ String.equal s1 s2 && eq_ind ind1 ind2 &&
+ eq_mllambda gn1 gn2 n env1 env2 ml1 ml2
+ | (MLlocal _ | MLglobal _ | MLprimitive _ | MLlam _ | MLletrec _ | MLlet _ |
+ MLapp _ | MLif _ | MLmatch _ | MLconstruct _ | MLint _ | MLuint _ |
+ MLsetref _ | MLsequence _ | MLarray _ | MLisaccu _), _ -> false
and eq_letrec gn1 gn2 n env1 env2 defs1 defs2 =
let eq_def (_,args1,ml1) (_,args2,ml2) =
@@ -538,6 +545,8 @@ let rec hash_mllambda gn n env t =
combinesmall 14 (combine hml hml')
| MLarray arr ->
combinesmall 15 (hash_mllambda_array gn n env 1 arr)
+ | MLisaccu (s, ind, c) ->
+ combinesmall 16 (combine (String.hash s) (combine (ind_hash ind) (hash_mllambda gn n env c)))
and hash_mllambda_letrec gn n env init defs =
let hash_def (_,args,ml) =
@@ -604,6 +613,7 @@ let fv_lam l =
| MLsetref(_,l) -> aux l bind fv
| MLsequence(l1,l2) -> aux l1 bind (aux l2 bind fv)
| MLarray arr -> Array.fold_right (fun a fv -> aux a bind fv) arr fv
+ | MLisaccu (_, _, body) -> aux body bind fv
in
aux l LNset.empty LNset.empty
@@ -1138,7 +1148,7 @@ let ml_of_instance instance u =
mkMLapp (MLapp (MLglobal cn, fv_args env fvn fvr)) [|force|]
| Lif(t,bt,bf) ->
MLif(ml_of_lam env l t, ml_of_lam env l bt, ml_of_lam env l bf)
- | Lfix ((rec_pos,start), (ids, tt, tb)) ->
+ | Lfix ((rec_pos, inds, start), (ids, tt, tb)) ->
(* let type_f fvt = [| type fix |]
let norm_f1 fv f1 .. fn params1 = body1
..
@@ -1207,8 +1217,9 @@ let ml_of_instance instance u =
let paramsi = t_params.(i) in
let reci = MLlocal (paramsi.(rec_pos.(i))) in
let pargsi = Array.map (fun id -> MLlocal id) paramsi in
+ let (prefix, ind) = inds.(i) in
let body =
- MLif(MLapp(MLprimitive Is_accu,[|reci|]),
+ MLif(MLisaccu (prefix, ind, reci),
mkMLapp
(MLapp(MLprimitive (Mk_fix(rec_pos,i)),
[|mk_type; mk_norm|]))
@@ -1370,6 +1381,7 @@ let subst s l =
| MLsetref(s,l1) -> MLsetref(s,aux l1)
| MLsequence(l1,l2) -> MLsequence(aux l1, aux l2)
| MLarray arr -> MLarray (Array.map aux arr)
+ | MLisaccu (s, ind, l) -> MLisaccu (s, ind, aux l)
in
aux l
@@ -1467,7 +1479,7 @@ let optimize gdef l =
let b1 = optimize s b1 in
let b2 = optimize s b2 in
begin match t, b2 with
- | MLapp(MLprimitive Is_accu,[| l1 |]), MLmatch(annot, l2, _, bs)
+ | MLisaccu (_, _, l1), MLmatch(annot, l2, _, bs)
when eq_mllambda l1 l2 -> MLmatch(annot, l1, b1, bs)
| _, _ -> MLif(t, b1, b2)
end
@@ -1479,6 +1491,7 @@ let optimize gdef l =
| MLsetref(r,l) -> MLsetref(r, optimize s l)
| MLsequence(l1,l2) -> MLsequence(optimize s l1, optimize s l2)
| MLarray arr -> MLarray (Array.map (optimize s) arr)
+ | MLisaccu (pf, ind, l) -> MLisaccu (pf, ind, optimize s l)
in
optimize LNmap.empty l
@@ -1641,19 +1654,23 @@ let pp_mllam fmt l =
pp_mllam fmt arr.(len-1)
end;
Format.fprintf fmt "|]@]"
-
+ | MLisaccu (prefix, (mind, i), c) ->
+ let accu = Format.sprintf "%sAccu_%s_%i" prefix (string_of_mind mind) i in
+ Format.fprintf fmt
+ "@[begin match Obj.magic (%a) with@\n| %s _ ->@\n true@\n| _ ->@\n false@\nend@]"
+ pp_mllam c accu
and pp_letrec fmt defs =
let len = Array.length defs in
- let pp_one_rec i (fn, argsn, body) =
+ let pp_one_rec (fn, argsn, body) =
Format.fprintf fmt "%a%a =@\n %a"
pp_lname fn
pp_ldecls argsn pp_mllam body in
Format.fprintf fmt "@[let rec ";
- pp_one_rec 0 defs.(0);
+ pp_one_rec defs.(0);
for i = 1 to len - 1 do
Format.fprintf fmt "@\nand ";
- pp_one_rec i defs.(i)
+ pp_one_rec defs.(i)
done;
and pp_blam fmt l =
@@ -1734,7 +1751,6 @@ let pp_mllam fmt l =
| Mk_var id ->
Format.fprintf fmt "mk_var_accu (Names.id_of_string \"%s\")" (string_of_id id)
| Mk_proj -> Format.fprintf fmt "mk_proj_accu"
- | Is_accu -> Format.fprintf fmt "is_accu"
| Is_int -> Format.fprintf fmt "is_int"
| Cast_accu -> Format.fprintf fmt "cast_accu"
| Upd_cofix -> Format.fprintf fmt "upd_cofix"
@@ -1841,7 +1857,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.env_rel_ctx in
+ let lvl = Context.Rel.length (rel_context env) 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
@@ -1850,7 +1866,7 @@ 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 = lookup_rel n env in
- let n = List.length env.env_rel_context.env_rel_ctx - n in
+ let n = List.length (rel_context env) - n in
match decl with
| LocalDef (_,t,_) ->
let code = lambda_of_constr env sigma t in
@@ -1880,7 +1896,7 @@ let compile_constant env sigma prefix ~interactive con cb =
let t = Mod_subst.force_constr t in
let code = lambda_of_constr env sigma t in
if !Flags.debug then Feedback.msg_debug (Pp.str "Generated lambda code");
- let is_lazy = is_lazy prefix t in
+ let is_lazy = is_lazy env prefix t in
let code = if is_lazy then mk_lazy code else code in
let name =
if interactive then LinkedInteractive prefix
@@ -1937,7 +1953,7 @@ let is_code_loaded ~interactive name =
let param_name = Name (Id.of_string "params")
let arg_name = Name (Id.of_string "arg")
-let compile_mind prefix ~interactive mb mind stack =
+let compile_mind mb mind stack =
let u = Declareops.inductive_polymorphic_context mb in
(** Generate data for every block *)
let f i stack ob =
@@ -1964,8 +1980,7 @@ let compile_mind prefix ~interactive mb mind stack =
(MLconstruct("", c, Array.map (fun id -> MLlocal id) args)))::acc
in
let constructors = Array.fold_left_i add_construct [] ob.mind_reloc_tbl in
- let add_proj j acc pb =
- let () = assert (eq_ind ind pb.proj_ind) in
+ let add_proj proj_arg acc pb =
let tbl = ob.mind_reloc_tbl in
(* Building info *)
let ci = { ci_ind = ind; ci_npar = nparams;
@@ -1979,14 +1994,14 @@ let compile_mind prefix ~interactive mb mind stack =
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)
+ (fun i -> if Int.equal i proj_arg then Some ci_uid else None)
in
let i = push_symbol (SymbProj (ind, j)) in
let accu = MLapp (MLprimitive Cast_accu, [|MLlocal cf_uid|]) in
let accu_br = MLapp (MLprimitive Mk_proj, [|get_proj_code i;accu|]) in
let code = MLmatch(asw,MLlocal cf_uid,accu_br,[|[((ind,1),cargs)],MLlocal ci_uid|]) in
let code = MLlet(cf_uid, MLapp (MLprimitive Force_cofix, [|MLlocal c_uid|]), code) in
- let gn = Gproj ("", ind, pb.proj_arg) in
+ let gn = Gproj ("", ind, proj_arg) in
Glet (gn, mkMLlam [|c_uid|] code) :: acc
in
let projs = match mb.mind_record with
@@ -2016,7 +2031,7 @@ let compile_mind_deps env prefix ~interactive
then init
else
let comp_stack =
- compile_mind prefix ~interactive mib mind comp_stack
+ compile_mind mib mind comp_stack
in
let name =
if interactive then LinkedInteractive prefix
@@ -2054,8 +2069,7 @@ let compile_deps env sigma prefix ~interactive init t =
comp_stack, (mind_updates, const_updates)
| Construct (((mind,_),_),u) -> compile_mind_deps env prefix ~interactive init mind
| Proj (p,c) ->
- let pb = lookup_projection p env in
- let init = compile_mind_deps env prefix ~interactive init (fst pb.proj_ind) in
+ let init = compile_mind_deps env prefix ~interactive init (Projection.mind p) in
aux env lvl init c
| Case (ci, p, c, ac) ->
let mind = fst ci.ci_ind in
@@ -2088,9 +2102,9 @@ let compile_constant_field env prefix con acc cb =
in
gl@acc
-let compile_mind_field prefix mp l acc mb =
+let compile_mind_field mp l acc mb =
let mind = MutInd.make2 mp l in
- compile_mind prefix ~interactive:false mb mind acc
+ compile_mind mb mind acc
let mk_open s = Gopen s
diff --git a/kernel/nativecode.mli b/kernel/nativecode.mli
index 684983a876..96efa7faa5 100644
--- a/kernel/nativecode.mli
+++ b/kernel/nativecode.mli
@@ -67,7 +67,7 @@ val register_native_file : string -> unit
val compile_constant_field : env -> string -> Constant.t ->
global list -> constant_body -> global list
-val compile_mind_field : string -> ModPath.t -> Label.t ->
+val compile_mind_field : ModPath.t -> Label.t ->
global list -> mutual_inductive_body -> global list
val mk_conv_code : env -> evars -> string -> constr -> constr -> linkable_code
diff --git a/kernel/nativeconv.ml b/kernel/nativeconv.ml
index e97dbd0d67..931b8bbc86 100644
--- a/kernel/nativeconv.ml
+++ b/kernel/nativeconv.ml
@@ -135,7 +135,18 @@ and conv_fix env lvl t1 f1 t2 f2 cu =
else aux (i+1) (conv_val env CONV flvl fi1 fi2 cu) in
aux 0 cu
+let warn_no_native_compiler =
+ let open Pp in
+ CWarnings.create ~name:"native-compiler-disabled" ~category:"native-compiler"
+ (fun () -> strbrk "Native compiler is disabled," ++
+ strbrk " falling back to VM conversion test.")
+
let native_conv_gen pb sigma env univs t1 t2 =
+ if not Coq_config.native_compiler then begin
+ warn_no_native_compiler ();
+ Vconv.vm_conv_gen pb env univs t1 t2
+ end
+ else
let ml_filename, prefix = get_ml_filename () in
let code, upds = mk_conv_code env sigma prefix t1 t2 in
match compile ml_filename code ~profile:false with
@@ -152,19 +163,8 @@ let native_conv_gen pb sigma env univs t1 t2 =
end
| _ -> anomaly (Pp.str "Compilation failure.")
-let warn_no_native_compiler =
- let open Pp in
- CWarnings.create ~name:"native-compiler-disabled" ~category:"native-compiler"
- (fun () -> strbrk "Native compiler is disabled," ++
- strbrk " falling back to VM conversion test.")
-
(* Wrapper for [native_conv] above *)
let native_conv cv_pb sigma env t1 t2 =
- if not Coq_config.native_compiler then begin
- warn_no_native_compiler ();
- Vconv.vm_conv cv_pb env t1 t2
- end
- else
let univs = Environ.universes env in
let b =
if cv_pb = CUMUL then Constr.leq_constr_univs univs t1 t2
diff --git a/kernel/nativeinstr.mli b/kernel/nativeinstr.mli
index eaad8ee0c2..5075bd3d14 100644
--- a/kernel/nativeinstr.mli
+++ b/kernel/nativeinstr.mli
@@ -36,7 +36,7 @@ and lambda =
| Lcase of annot_sw * lambda * lambda * lam_branches
(* annotations, term being matched, accu, branches *)
| Lif of lambda * lambda * lambda
- | Lfix of (int array * int) * fix_decl
+ | Lfix of (int array * (string * inductive) array * int) * fix_decl
| Lcofix of int * fix_decl (* must be in eta-expanded form *)
| Lmakeblock of prefix * pconstructor * int * lambda array
(* prefix, constructor name, constructor tag, arguments *)
diff --git a/kernel/nativelambda.ml b/kernel/nativelambda.ml
index 244e5e0dd9..cec0ee57d5 100644
--- a/kernel/nativelambda.ml
+++ b/kernel/nativelambda.ml
@@ -333,54 +333,13 @@ let rec get_alias env (kn, u as p) =
(*i Global environment *)
-let global_env = ref empty_env
-
-let set_global_env env = global_env := env
-
let get_names decl =
let decl = Array.of_list decl in
Array.map fst decl
-(* Rel Environment *)
-module Vect =
- struct
- type 'a t = {
- mutable elems : 'a array;
- mutable size : int;
- }
-
- let make n a = {
- elems = Array.make n a;
- size = 0;
- }
-
- let extend v =
- if Int.equal v.size (Array.length v.elems) then
- let new_size = min (2*v.size) Sys.max_array_length in
- if new_size <= v.size then invalid_arg "Vect.extend";
- let new_elems = Array.make new_size v.elems.(0) in
- Array.blit v.elems 0 new_elems 0 (v.size);
- v.elems <- new_elems
-
- let push v a =
- extend v;
- v.elems.(v.size) <- a;
- v.size <- v.size + 1
-
- let popn v n =
- v.size <- max 0 (v.size - n)
-
- let pop v = popn v 1
-
- let get_last v n =
- if v.size <= n then invalid_arg "Vect.get:index out of bounds";
- v.elems.(v.size - n - 1)
-
- end
-
let empty_args = [||]
-module Renv =
+module Cache =
struct
module ConstrHash =
@@ -394,45 +353,20 @@ module Renv =
type constructor_info = tag * int * int (* nparam nrealargs *)
- type t = {
- name_rel : Name.t Vect.t;
- construct_tbl : constructor_info ConstrTable.t;
-
- }
-
-
- let make () = {
- name_rel = Vect.make 16 Anonymous;
- construct_tbl = ConstrTable.create 111
- }
-
- let push_rel env id = Vect.push env.name_rel id
-
- let push_rels env ids =
- Array.iter (push_rel env) ids
-
- let pop env = Vect.pop env.name_rel
-
- let popn env n =
- for _i = 1 to n do pop env done
-
- let get env n =
- Lrel (Vect.get_last env.name_rel (n-1), n)
-
- let get_construct_info env c =
- try ConstrTable.find env.construct_tbl c
+ let get_construct_info cache env c : constructor_info =
+ try ConstrTable.find cache c
with Not_found ->
let ((mind,j), i) = c in
- let oib = lookup_mind mind !global_env in
+ let oib = lookup_mind mind env in
let oip = oib.mind_packets.(j) in
let tag,arity = oip.mind_reloc_tbl.(i-1) in
let nparams = oib.mind_nparams in
let r = (tag, nparams, arity) in
- ConstrTable.add env.construct_tbl c r;
+ ConstrTable.add cache c r;
r
end
-let is_lazy prefix t =
+let is_lazy env prefix t =
match kind t with
| App (f,args) ->
begin match kind f with
@@ -440,7 +374,7 @@ let is_lazy prefix t =
let entry = mkInd (fst c) in
(try
let _ =
- Retroknowledge.get_native_before_match_info (!global_env).retroknowledge
+ Retroknowledge.get_native_before_match_info env.retroknowledge
entry prefix c Llazy;
in
false
@@ -463,73 +397,84 @@ let empty_evars =
let empty_ids = [||]
-let rec lambda_of_constr env sigma c =
+(** Extract the inductive type over which a fixpoint is decreasing *)
+let rec get_fix_struct env i t = match kind (Reduction.whd_all env t) with
+| Prod (na, dom, t) ->
+ if Int.equal i 0 then
+ let dom = Reduction.whd_all env dom in
+ let (dom, _) = decompose_appvect dom in
+ match kind dom with
+ | Ind (ind, _) -> ind
+ | _ -> assert false
+ else
+ let env = Environ.push_rel (RelDecl.LocalAssum (na, dom)) env in
+ get_fix_struct env (i - 1) t
+| _ -> assert false
+
+let rec lambda_of_constr cache env sigma c =
match kind c with
| Meta mv ->
let ty = meta_type sigma mv in
- Lmeta (mv, lambda_of_constr env sigma ty)
+ Lmeta (mv, lambda_of_constr cache env sigma ty)
| Evar (evk,args as ev) ->
(match evar_value sigma ev with
| None ->
let ty = evar_type sigma ev in
- let args = Array.map (lambda_of_constr env sigma) args in
- Levar(evk, lambda_of_constr env sigma ty, args)
- | Some t -> lambda_of_constr env sigma t)
+ let args = Array.map (lambda_of_constr cache env sigma) args in
+ Levar(evk, lambda_of_constr cache env sigma ty, args)
+ | Some t -> lambda_of_constr cache env sigma t)
- | Cast (c, _, _) -> lambda_of_constr env sigma c
+ | Cast (c, _, _) -> lambda_of_constr cache env sigma c
- | Rel i -> Renv.get env i
+ | Rel i -> Lrel (RelDecl.get_name (Environ.lookup_rel i env), i)
| Var id -> Lvar id
| Sort s -> Lsort s
| Ind (ind,u as pind) ->
- let prefix = get_mind_prefix !global_env (fst ind) in
+ let prefix = get_mind_prefix env (fst ind) in
Lind (prefix, pind)
| Prod(id, dom, codom) ->
- let ld = lambda_of_constr env sigma dom in
- Renv.push_rel env id;
- let lc = lambda_of_constr env sigma codom in
- Renv.pop env;
+ let ld = lambda_of_constr cache env sigma dom in
+ let env = Environ.push_rel (RelDecl.LocalAssum (id, dom)) env in
+ let lc = lambda_of_constr cache env sigma codom in
Lprod(ld, Llam([|id|], lc))
| Lambda _ ->
let params, body = Term.decompose_lam c in
+ let fold (na, t) env = Environ.push_rel (RelDecl.LocalAssum (na, t)) env in
+ let env = List.fold_right fold params env in
+ let lb = lambda_of_constr cache env sigma body in
let ids = get_names (List.rev params) in
- Renv.push_rels env ids;
- let lb = lambda_of_constr env sigma body in
- Renv.popn env (Array.length ids);
mkLlam ids lb
- | LetIn(id, def, _, body) ->
- let ld = lambda_of_constr env sigma def in
- Renv.push_rel env id;
- let lb = lambda_of_constr env sigma body in
- Renv.pop env;
+ | LetIn(id, def, t, body) ->
+ let ld = lambda_of_constr cache env sigma def in
+ let env = Environ.push_rel (RelDecl.LocalDef (id, def, t)) env in
+ let lb = lambda_of_constr cache env sigma body in
Llet(id, ld, lb)
- | App(f, args) -> lambda_of_app env sigma f args
+ | App(f, args) -> lambda_of_app cache env sigma f args
- | Const _ -> lambda_of_app env sigma c empty_args
+ | Const _ -> lambda_of_app cache env sigma c empty_args
- | Construct _ -> lambda_of_app env sigma c empty_args
+ | Construct _ -> lambda_of_app cache env sigma c empty_args
| Proj (p, c) ->
- let pb = lookup_projection p !global_env in
- let ind = pb.proj_ind in
- let prefix = get_mind_prefix !global_env (fst ind) in
- mkLapp (Lproj (prefix, ind, pb.proj_arg)) [|lambda_of_constr env sigma c|]
+ let ind = Projection.inductive p in
+ let prefix = get_mind_prefix env (fst ind) in
+ mkLapp (Lproj (prefix, ind, Projection.arg p)) [|lambda_of_constr cache env sigma c|]
| Case(ci,t,a,branches) ->
let (mind,i as ind) = ci.ci_ind in
- let mib = lookup_mind mind !global_env in
+ let mib = lookup_mind mind env in
let oib = mib.mind_packets.(i) in
let tbl = oib.mind_reloc_tbl in
(* Building info *)
- let prefix = get_mind_prefix !global_env mind in
+ let prefix = get_mind_prefix env mind in
let annot_sw =
{ asw_ind = ind;
asw_ci = ci;
@@ -538,21 +483,21 @@ let rec lambda_of_constr env sigma c =
asw_prefix = prefix}
in
(* translation of the argument *)
- let la = lambda_of_constr env sigma a in
+ let la = lambda_of_constr cache env sigma a in
let entry = mkInd ind in
let la =
try
- Retroknowledge.get_native_before_match_info (!global_env).retroknowledge
+ Retroknowledge.get_native_before_match_info (env).retroknowledge
entry prefix (ind,1) la
with Not_found -> la
in
(* translation of the type *)
- let lt = lambda_of_constr env sigma t in
+ let lt = lambda_of_constr cache env sigma t in
(* translation of branches *)
let mk_branch i b =
let cn = (ind,i+1) in
let _, arity = tbl.(i) in
- let b = lambda_of_constr env sigma b in
+ let b = lambda_of_constr cache env sigma b in
if Int.equal arity 0 then (cn, empty_ids, b)
else
match b with
@@ -565,86 +510,90 @@ let rec lambda_of_constr env sigma c =
let bs = Array.mapi mk_branch branches in
Lcase(annot_sw, lt, la, bs)
- | Fix(rec_init,(names,type_bodies,rec_bodies)) ->
- let ltypes = lambda_of_args env sigma 0 type_bodies in
- Renv.push_rels env names;
- let lbodies = lambda_of_args env sigma 0 rec_bodies in
- Renv.popn env (Array.length names);
- Lfix(rec_init, (names, ltypes, lbodies))
+ | Fix((pos, i), (names,type_bodies,rec_bodies)) ->
+ let ltypes = lambda_of_args cache env sigma 0 type_bodies in
+ let map i t =
+ let ind = get_fix_struct env i t in
+ let prefix = get_mind_prefix env (fst ind) in
+ (prefix, ind)
+ in
+ let inds = Array.map2 map pos type_bodies in
+ let env = Environ.push_rec_types (names, type_bodies, rec_bodies) env in
+ let lbodies = lambda_of_args cache env sigma 0 rec_bodies in
+ Lfix((pos, inds, i), (names, ltypes, lbodies))
| CoFix(init,(names,type_bodies,rec_bodies)) ->
- let rec_bodies = Array.map2 (Reduction.eta_expand !global_env) rec_bodies type_bodies in
- let ltypes = lambda_of_args env sigma 0 type_bodies in
- Renv.push_rels env names;
- let lbodies = lambda_of_args env sigma 0 rec_bodies in
- Renv.popn env (Array.length names);
+ let rec_bodies = Array.map2 (Reduction.eta_expand env) rec_bodies type_bodies in
+ let ltypes = lambda_of_args cache env sigma 0 type_bodies in
+ let env = Environ.push_rec_types (names, type_bodies, rec_bodies) env in
+ let lbodies = lambda_of_args cache env sigma 0 rec_bodies in
Lcofix(init, (names, ltypes, lbodies))
-and lambda_of_app env sigma f args =
+and lambda_of_app cache env sigma f args =
match kind f with
| Const (kn,u as c) ->
- let kn,u = get_alias !global_env c in
- let cb = lookup_constant kn !global_env in
+ let kn,u = get_alias env c in
+ let cb = lookup_constant kn env in
(try
- let prefix = get_const_prefix !global_env kn in
+ let prefix = get_const_prefix env kn in
(* We delay the compilation of arguments to avoid an exponential behavior *)
let f = Retroknowledge.get_native_compiling_info
- (!global_env).retroknowledge (mkConst kn) prefix in
- let args = lambda_of_args env sigma 0 args in
+ (env).retroknowledge (mkConst kn) prefix in
+ let args = lambda_of_args cache env sigma 0 args in
f args
with Not_found ->
begin match cb.const_body with
| Def csubst -> (* TODO optimize if f is a proj and argument is known *)
if cb.const_inline_code then
- lambda_of_app env sigma (Mod_subst.force_constr csubst) args
+ lambda_of_app cache env sigma (Mod_subst.force_constr csubst) args
else
- let prefix = get_const_prefix !global_env kn in
+ let prefix = get_const_prefix env kn in
let t =
- if is_lazy prefix (Mod_subst.force_constr csubst) then
+ if is_lazy env prefix (Mod_subst.force_constr csubst) then
mkLapp Lforce [|Lconst (prefix, (kn,u))|]
else Lconst (prefix, (kn,u))
in
- mkLapp t (lambda_of_args env sigma 0 args)
+ mkLapp t (lambda_of_args cache env sigma 0 args)
| OpaqueDef _ | Undef _ ->
- let prefix = get_const_prefix !global_env kn in
- mkLapp (Lconst (prefix, (kn,u))) (lambda_of_args env sigma 0 args)
+ let prefix = get_const_prefix env kn in
+ mkLapp (Lconst (prefix, (kn,u))) (lambda_of_args cache env sigma 0 args)
end)
| Construct (c,u) ->
- let tag, nparams, arity = Renv.get_construct_info env c in
+ let tag, nparams, arity = Cache.get_construct_info cache env c in
let expected = nparams + arity in
let nargs = Array.length args in
- let prefix = get_mind_prefix !global_env (fst (fst c)) in
+ let prefix = get_mind_prefix env (fst (fst c)) in
if Int.equal nargs expected then
try
try
Retroknowledge.get_native_constant_static_info
- (!global_env).retroknowledge
+ (env).retroknowledge
f args
with NotClosed ->
assert (Int.equal nparams 0); (* should be fine for int31 *)
- let args = lambda_of_args env sigma nparams args in
+ let args = lambda_of_args cache env sigma nparams args in
Retroknowledge.get_native_constant_dynamic_info
- (!global_env).retroknowledge f prefix c args
+ (env).retroknowledge f prefix c args
with Not_found ->
- let args = lambda_of_args env sigma nparams args in
- makeblock !global_env c u tag args
+ let args = lambda_of_args cache env sigma nparams args in
+ makeblock env c u tag args
else
- let args = lambda_of_args env sigma 0 args in
+ let args = lambda_of_args cache env sigma 0 args in
(try
Retroknowledge.get_native_constant_dynamic_info
- (!global_env).retroknowledge f prefix c args
+ (env).retroknowledge f prefix c args
with Not_found ->
mkLapp (Lconstruct (prefix, (c,u))) args)
| _ ->
- let f = lambda_of_constr env sigma f in
- let args = lambda_of_args env sigma 0 args in
+ let f = lambda_of_constr cache env sigma f in
+ let args = lambda_of_args cache env sigma 0 args in
mkLapp f args
-and lambda_of_args env sigma start args =
+and lambda_of_args cache env sigma start args =
let nargs = Array.length args in
if start < nargs then
Array.init (nargs - start)
- (fun i -> lambda_of_constr env sigma args.(start + i))
+ (fun i -> lambda_of_constr cache env sigma args.(start + i))
else empty_args
let optimize lam =
@@ -657,11 +606,8 @@ let optimize lam =
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.env_rel_ctx in
- Renv.push_rels env (Array.of_list ids);
- let lam = lambda_of_constr env sigma c in
+ let cache = Cache.ConstrTable.create 91 in
+ let lam = lambda_of_constr cache env sigma c in
(* if Flags.vm_draw_opt () then begin
(msgerrnl (str "Constr = \n" ++ pr_constr c);flush_all());
(msgerrnl (str "Lambda = \n" ++ pp_lam lam);flush_all());
diff --git a/kernel/nativelambda.mli b/kernel/nativelambda.mli
index 26bfeb7e0e..efe1700cd7 100644
--- a/kernel/nativelambda.mli
+++ b/kernel/nativelambda.mli
@@ -23,7 +23,7 @@ val empty_evars : evars
val decompose_Llam : lambda -> Name.t array * lambda
val decompose_Llam_Llet : lambda -> (Name.t * lambda option) array * lambda
-val is_lazy : prefix -> constr -> bool
+val is_lazy : env -> prefix -> constr -> bool
val mk_lazy : lambda -> lambda
val get_mind_prefix : env -> MutInd.t -> string
diff --git a/kernel/nativelib.ml b/kernel/nativelib.ml
index 31ad364911..f784509b6f 100644
--- a/kernel/nativelib.ml
+++ b/kernel/nativelib.ml
@@ -67,6 +67,7 @@ let warn_native_compiler_failed =
CWarnings.create ~name:"native-compiler-failed" ~category:"native-compiler" print
let call_compiler ?profile:(profile=false) ml_filename =
+ let () = assert Coq_config.native_compiler in
let load_path = !get_load_paths () in
let load_path = List.map (fun dn -> dn / output_dir) load_path in
let include_dirs = List.flatten (List.map (fun x -> ["-I"; x]) (include_dirs () @ load_path)) in
diff --git a/kernel/nativelibrary.ml b/kernel/nativelibrary.ml
index 8bff436322..edce9367fc 100644
--- a/kernel/nativelibrary.ml
+++ b/kernel/nativelibrary.ml
@@ -37,7 +37,7 @@ and translate_field prefix mp env acc (l,x) =
let id = mb.mind_packets.(0).mind_typename in
let msg = Printf.sprintf "Compiling inductive %s..." (Id.to_string id) in
Feedback.msg_debug (Pp.str msg));
- compile_mind_field prefix mp l acc mb
+ compile_mind_field mp l acc mb
| SFBmodule md ->
let mp = md.mod_mp in
(if !Flags.debug then
diff --git a/kernel/nativevalues.ml b/kernel/nativevalues.ml
index da4413a0ad..91f6add1c3 100644
--- a/kernel/nativevalues.ml
+++ b/kernel/nativevalues.ml
@@ -68,28 +68,29 @@ type atom =
let accumulate_tag = 0
-let accumulate_code (k:accumulator) (x:t) =
- let o = Obj.repr k in
- let osize = Obj.size o in
- let r = Obj.new_block accumulate_tag (osize + 1) in
- for i = 0 to osize - 1 do
- Obj.set_field r i (Obj.field o i)
- done;
- Obj.set_field r osize (Obj.repr x);
- (Obj.obj r:t)
-
-let rec accumulate (x:t) =
- accumulate_code (Obj.magic accumulate) x
-
-let mk_accu_gen rcode (a:atom) =
-(* Format.eprintf "size rcode =%i\n" (Obj.size (Obj.magic rcode)); *)
- let r = Obj.new_block 0 3 in
- Obj.set_field r 0 (Obj.field (Obj.magic rcode) 0);
- Obj.set_field r 1 (Obj.field (Obj.magic rcode) 1);
- Obj.set_field r 2 (Obj.magic a);
- (Obj.magic r:t);;
-
-let mk_accu (a:atom) = mk_accu_gen accumulate a
+(** Unique pointer used to drive the accumulator function *)
+let ret_accu = Obj.repr (ref ())
+
+type accu_val = { mutable acc_atm : atom; acc_arg : Obj.t list }
+
+let mk_accu (a : atom) : t =
+ let rec accumulate data x =
+ if x == ret_accu then Obj.repr data
+ else
+ let data = { data with acc_arg = x :: data.acc_arg } in
+ let ans = Obj.repr (accumulate data) in
+ let () = Obj.set_tag ans accumulate_tag in
+ ans
+ in
+ let acc = { acc_atm = a; acc_arg = [] } in
+ let ans = Obj.repr (accumulate acc) in
+ (** FIXME: use another representation for accumulators, this causes naked
+ pointers. *)
+ let () = Obj.set_tag ans accumulate_tag in
+ (Obj.obj ans : t)
+
+let get_accu (k : accumulator) =
+ (Obj.magic k : Obj.t -> accu_val) ret_accu
let mk_rel_accu i =
mk_accu (Arel i)
@@ -116,7 +117,7 @@ let mk_ind_accu ind u =
let mk_sort_accu s u =
let open Sorts in
match s with
- | Prop _ -> mk_accu (Asort s)
+ | Prop | Set -> mk_accu (Asort s)
| Type s ->
let u = Univ.Instance.of_array u in
let s = Univ.subst_instance_universe u s in
@@ -141,31 +142,27 @@ let mk_proj_accu kn c =
mk_accu (Aproj (kn,c))
let atom_of_accu (k:accumulator) =
- (Obj.magic (Obj.field (Obj.magic k) 2) : atom)
+ (get_accu k).acc_atm
let set_atom_of_accu (k:accumulator) (a:atom) =
- Obj.set_field (Obj.magic k) 2 (Obj.magic a)
+ (get_accu k).acc_atm <- a
let accu_nargs (k:accumulator) =
- let nargs = Obj.size (Obj.magic k) - 3 in
-(* if nargs < 0 then Format.eprintf "nargs = %i\n" nargs; *)
- assert (nargs >= 0);
- nargs
+ List.length (get_accu k).acc_arg
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
- Array.init nargs f
+ let acc = (get_accu k).acc_arg in
+ (Obj.magic (Array.of_list acc) : t array)
let is_accu x =
let o = Obj.repr x in
Obj.is_block o && Int.equal (Obj.tag o) accumulate_tag
let mk_fix_accu rec_pos pos types bodies =
- mk_accu_gen accumulate (Afix(types,bodies,rec_pos, pos))
+ mk_accu (Afix(types,bodies,rec_pos, pos))
let mk_cofix_accu pos types norm =
- mk_accu_gen accumulate (Acofix(types,norm,pos,(Obj.magic 0 : t)))
+ mk_accu (Acofix(types,norm,pos,(Obj.magic 0 : t)))
let upd_cofix (cofix :t) (cofix_fun : t) =
let atom = atom_of_accu (Obj.magic cofix) in
diff --git a/kernel/nativevalues.mli b/kernel/nativevalues.mli
index 649853f069..6bbf15160c 100644
--- a/kernel/nativevalues.mli
+++ b/kernel/nativevalues.mli
@@ -110,9 +110,6 @@ type kind_of_value =
val kind_of_value : t -> kind_of_value
-(* *)
-val is_accu : t -> bool
-
val str_encode : 'a -> string
val str_decode : string -> 'a
diff --git a/kernel/opaqueproof.ml b/kernel/opaqueproof.ml
index a484c08e8d..f8b71e4564 100644
--- a/kernel/opaqueproof.ml
+++ b/kernel/opaqueproof.ml
@@ -18,7 +18,7 @@ type work_list = (Instance.t * Id.t array) Cmap.t *
type cooking_info = {
modlist : work_list;
- abstract : Context.Named.t * Univ.Instance.t * Univ.AUContext.t }
+ abstract : Constr.named_context * 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 b6ae80b46a..5ea6da649b 100644
--- a/kernel/opaqueproof.mli
+++ b/kernel/opaqueproof.mli
@@ -51,7 +51,7 @@ type work_list = (Univ.Instance.t * Id.t array) Cmap.t *
type cooking_info = {
modlist : work_list;
- abstract : Context.Named.t * Univ.Instance.t * Univ.AUContext.t }
+ abstract : Constr.named_context * Univ.Instance.t * Univ.AUContext.t }
(* The type has two caveats:
1) cook_constr is defined after
diff --git a/kernel/reduction.ml b/kernel/reduction.ml
index f4af313867..c701b53fe4 100644
--- a/kernel/reduction.ml
+++ b/kernel/reduction.ml
@@ -53,7 +53,7 @@ let compare_stack_shape stk1 stk2 =
| (_, (Zupdate _|Zshift _)::s2) -> compare_rec bal stk1 s2
| (Zapp l1::s1, _) -> compare_rec (bal+Array.length l1) s1 stk2
| (_, Zapp l2::s2) -> compare_rec (bal-Array.length l2) stk1 s2
- | (Zproj (n1,m1,p1)::s1, Zproj (n2,m2,p2)::s2) ->
+ | (Zproj p1::s1, Zproj p2::s2) ->
Int.equal bal 0 && compare_rec 0 s1 s2
| (ZcaseT(c1,_,_,_)::s1, ZcaseT(c2,_,_,_)::s2) ->
Int.equal bal 0 (* && c1.ci_ind = c2.ci_ind *) && compare_rec 0 s1 s2
@@ -66,7 +66,7 @@ let compare_stack_shape stk1 stk2 =
type lft_constr_stack_elt =
Zlapp of (lift * fconstr) array
- | Zlproj of Constant.t * lift
+ | Zlproj of Projection.Repr.t * lift
| Zlfix of (lift * fconstr) * lft_constr_stack
| Zlcase of case_info * lift * fconstr * fconstr array
and lft_constr_stack = lft_constr_stack_elt list
@@ -96,8 +96,8 @@ let pure_stack lfts stk =
| (Zshift n,(l,pstk)) -> (el_shft n l, pstk)
| (Zapp a, (l,pstk)) ->
(l,zlapp (map_lift l a) pstk)
- | (Zproj (n,m,c), (l,pstk)) ->
- (l, Zlproj (c,l)::pstk)
+ | (Zproj p, (l,pstk)) ->
+ (l, Zlproj (p,l)::pstk)
| (Zfix(fx,a),(l,pstk)) ->
let (lfx,pa) = pure_rec l a in
(l, Zlfix((lfx,fx),pa)::pstk)
@@ -297,7 +297,7 @@ let compare_stacks f fmind lft1 stk1 lft2 stk2 cuniv =
| (Zlapp a1,Zlapp a2) ->
Array.fold_right2 f a1 a2 cu1
| (Zlproj (c1,l1),Zlproj (c2,l2)) ->
- if not (Constant.equal c1 c2) then
+ if not (Projection.Repr.equal c1 c2) then
raise NotConvertible
else cu1
| (Zlfix(fx1,a1),Zlfix(fx2,a2)) ->
@@ -408,7 +408,7 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
| Some s2 ->
eqappr cv_pb l2r infos appr1 (lft2, (c2, (s2 :: v2))) cuniv
| None ->
- if Constant.equal (Projection.constant p1) (Projection.constant p2)
+ if Projection.Repr.equal (Projection.repr p1) (Projection.repr p2)
&& compare_stack_shape v1 v2 then
let el1 = el_stack lft1 v1 in
let el2 = el_stack lft2 v2 in
@@ -649,23 +649,19 @@ let check_leq univs u u' =
let check_sort_cmp_universes env pb s0 s1 univs =
let open Sorts in
if not (type_in_type env) then
+ let check_pb u0 u1 =
+ match pb with
+ | CUMUL -> check_leq univs u0 u1
+ | CONV -> check_eq univs u0 u1
+ in
match (s0,s1) with
- | (Prop c1, Prop c2) when is_cumul pb ->
- begin match c1, c2 with
- | Null, _ | _, Pos -> () (* Prop <= Set *)
- | _ -> raise NotConvertible
- end
- | (Prop c1, Prop c2) -> if c1 != c2 then raise NotConvertible
- | (Prop c1, Type u) ->
- let u0 = univ_of_sort s0 in
- (match pb with
- | CUMUL -> check_leq univs u0 u
- | CONV -> check_eq univs u0 u)
- | (Type u, Prop c) -> raise NotConvertible
- | (Type u1, Type u2) ->
- (match pb with
- | CUMUL -> check_leq univs u1 u2
- | CONV -> check_eq univs u1 u2)
+ | Prop, Prop | Set, Set -> ()
+ | Prop, (Set | Type _) -> if not (is_cumul pb) then raise NotConvertible
+ | Set, Prop -> raise NotConvertible
+ | Set, Type u -> check_pb Univ.type0_univ u
+ | Type u, Prop -> raise NotConvertible
+ | Type u, Set -> check_pb u Univ.type0_univ
+ | Type u0, Type u1 -> check_pb u0 u1
let checked_sort_cmp_universes env pb s0 s1 univs =
check_sort_cmp_universes env pb s0 s1 univs; univs
@@ -693,30 +689,27 @@ let infer_eq (univs, cstrs as cuniv) u u' =
let infer_leq (univs, cstrs as cuniv) u u' =
if UGraph.check_leq univs u u' then cuniv
else
- let cstrs' = Univ.enforce_leq u u' cstrs in
- univs, cstrs'
+ let cstrs', _ = UGraph.enforce_leq_alg u u' univs in
+ univs, Univ.Constraint.union cstrs cstrs'
let infer_cmp_universes env pb s0 s1 univs =
- let open Sorts in
- if type_in_type env then univs
+ if type_in_type env
+ then univs
else
+ let open Sorts in
+ let infer_pb u0 u1 =
+ match pb with
+ | CUMUL -> infer_leq univs u0 u1
+ | CONV -> infer_eq univs u0 u1
+ in
match (s0,s1) with
- | (Prop c1, Prop c2) when is_cumul pb ->
- begin match c1, c2 with
- | Null, _ | _, Pos -> univs (* Prop <= Set *)
- | _ -> raise NotConvertible
- end
- | (Prop c1, Prop c2) -> if c1 == c2 then univs else raise NotConvertible
- | (Prop c1, Type u) ->
- let u0 = univ_of_sort s0 in
- (match pb with
- | CUMUL -> infer_leq univs u0 u
- | CONV -> infer_eq univs u0 u)
- | (Type u, Prop c) -> raise NotConvertible
- | (Type u1, Type u2) ->
- (match pb with
- | CUMUL -> infer_leq univs u1 u2
- | CONV -> infer_eq univs u1 u2)
+ | Prop, Prop | Set, Set -> univs
+ | Prop, (Set | Type _) -> if not (is_cumul pb) then raise NotConvertible else univs
+ | Set, Prop -> raise NotConvertible
+ | Set, Type u -> infer_pb Univ.type0_univ u
+ | Type u, Prop -> raise NotConvertible
+ | Type u, Set -> infer_pb u Univ.type0_univ
+ | Type u0, Type u1 -> infer_pb u0 u1
let infer_convert_instances ~flex u u' (univs,cstrs) =
let cstrs' =
diff --git a/kernel/reduction.mli b/kernel/reduction.mli
index e53ab6aefb..581e8bd88a 100644
--- a/kernel/reduction.mli
+++ b/kernel/reduction.mli
@@ -116,10 +116,10 @@ val betazeta_appvect : int -> constr -> constr array -> constr
(***********************************************************************
s Recognizing products and arities modulo reduction *)
-val dest_prod : env -> types -> Context.Rel.t * types
-val dest_prod_assum : env -> types -> Context.Rel.t * types
-val dest_lam : env -> types -> Context.Rel.t * constr
-val dest_lam_assum : env -> types -> Context.Rel.t * types
+val dest_prod : env -> types -> Constr.rel_context * types
+val dest_prod_assum : env -> types -> Constr.rel_context * types
+val dest_lam : env -> constr -> Constr.rel_context * constr
+val dest_lam_assum : env -> constr -> Constr.rel_context * constr
exception NotArity
diff --git a/kernel/retroknowledge.ml b/kernel/retroknowledge.ml
index d76b05a8bb..34f62defb8 100644
--- a/kernel/retroknowledge.ml
+++ b/kernel/retroknowledge.ml
@@ -25,22 +25,6 @@ open Constr
(* aliased type for clarity purpose*)
type entry = Constr.t
-(* [field]-s are the roles the kernel can learn of. *)
-type nat_field =
- | NatType
- | NatPlus
- | NatTimes
-
-type n_field =
- | NPositive
- | NType
- | NTwice
- | NTwicePlusOne
- | NPhi
- | NPhiInv
- | NPlus
- | NTimes
-
type int31_field =
| Int31Bits
| Int31Type
@@ -69,9 +53,6 @@ type int31_field =
| Int31Lxor
type field =
- (* | KEq
- | KNat of nat_field
- | KN of n_field *)
| KInt31 of string*int31_field
diff --git a/kernel/retroknowledge.mli b/kernel/retroknowledge.mli
index 281c37b851..02d961d893 100644
--- a/kernel/retroknowledge.mli
+++ b/kernel/retroknowledge.mli
@@ -18,21 +18,6 @@ type entry = Constr.t
(** the following types correspond to the different "things"
the kernel can learn about.*)
-type nat_field =
- | NatType
- | NatPlus
- | NatTimes
-
-type n_field =
- | NPositive
- | NType
- | NTwice
- | NTwicePlusOne
- | NPhi
- | NPhiInv
- | NPlus
- | NTimes
-
type int31_field =
| Int31Bits
| Int31Type
@@ -61,13 +46,8 @@ type int31_field =
| Int31Lxor
type field =
-
-(** | KEq
- | KNat of nat_field
- | KN of n_field *)
| KInt31 of string*int31_field
-
(** This type represent an atomic action of the retroknowledge. It
is stored in the compiled libraries
As per now, there is only the possibility of registering things
diff --git a/kernel/safe_typing.ml b/kernel/safe_typing.ml
index f2b5ed4383..6c87ff570f 100644
--- a/kernel/safe_typing.ml
+++ b/kernel/safe_typing.ml
@@ -886,9 +886,11 @@ let typing senv = Typeops.infer (env_of_senv senv)
(** {6 Retroknowledge / native compiler } *)
+[@@@ocaml.warning "-3"]
(** universal lifting, used for the "get" operations mostly *)
let retroknowledge f senv =
Environ.retroknowledge f (env_of_senv senv)
+[@@@ocaml.warning "+3"]
let register field value by_clause senv =
(* todo : value closed, by_clause safe, by_clause of the proper type*)
@@ -907,7 +909,7 @@ let register_inline kn senv =
if not (evaluable_constant kn senv.env) then
CErrors.user_err Pp.(str "Register inline: an evaluable constant is expected");
let env = senv.env in
- let (cb,r) = Cmap_env.find kn env.env_globals.env_constants in
+ let cb = lookup_constant kn env in
let cb = {cb with const_inline_code = true} in
let env = add_constant kn cb env in { senv with env}
diff --git a/kernel/safe_typing.mli b/kernel/safe_typing.mli
index 990e07da45..502e2970a1 100644
--- a/kernel/safe_typing.mli
+++ b/kernel/safe_typing.mli
@@ -212,6 +212,7 @@ val delta_of_senv :
open Retroknowledge
val retroknowledge : (retroknowledge-> 'a) -> safe_environment -> 'a
+[@@ocaml.deprecated "Use the projection of Environ.env"]
val register :
field -> Retroknowledge.entry -> Constr.constr -> safe_transformer0
diff --git a/kernel/sorts.ml b/kernel/sorts.ml
index daeb90be7f..a7bb08f5b6 100644
--- a/kernel/sorts.ml
+++ b/kernel/sorts.ml
@@ -10,22 +10,21 @@
open Univ
-type contents = Pos | Null
-
type family = InProp | InSet | InType
type t =
- | Prop of contents (* proposition types *)
+ | Prop
+ | Set
| Type of Universe.t
-let prop = Prop Null
-let set = Prop Pos
+let prop = Prop
+let set = Set
let type1 = Type type1_univ
let univ_of_sort = function
| Type u -> u
- | Prop Pos -> Universe.type0
- | Prop Null -> Universe.type0m
+ | Set -> Universe.type0
+ | Prop -> Universe.type0m
let sort_of_univ u =
if is_type0m_univ u then prop
@@ -34,36 +33,34 @@ let sort_of_univ u =
let compare s1 s2 =
if s1 == s2 then 0 else
- match s1, s2 with
- | Prop c1, Prop c2 ->
- begin match c1, c2 with
- | Pos, Pos | Null, Null -> 0
- | Pos, Null -> -1
- | Null, Pos -> 1
- end
- | Type u1, Type u2 -> Universe.compare u1 u2
- | Prop _, Type _ -> -1
- | Type _, Prop _ -> 1
+ match s1, s2 with
+ | Prop, Prop -> 0
+ | Prop, _ -> -1
+ | Set, Prop -> 1
+ | Set, Set -> 0
+ | Set, _ -> -1
+ | Type u1, Type u2 -> Universe.compare u1 u2
+ | Type _, _ -> -1
let equal s1 s2 = Int.equal (compare s1 s2) 0
let is_prop = function
- | Prop Null -> true
+ | Prop -> true
| Type u when Universe.equal Universe.type0m u -> true
| _ -> false
let is_set = function
- | Prop Pos -> true
+ | Set -> true
| Type u when Universe.equal Universe.type0 u -> true
| _ -> false
let is_small = function
- | Prop _ -> true
+ | Prop | Set -> true
| Type u -> is_small_univ u
let family = function
- | Prop Null -> InProp
- | Prop Pos -> InSet
+ | Prop -> InProp
+ | Set -> InSet
| Type u when is_type0m_univ u -> InProp
| Type u when is_type0_univ u -> InSet
| Type _ -> InType
@@ -73,15 +70,11 @@ let family_equal = (==)
open Hashset.Combine
let hash = function
-| Prop p ->
- let h = match p with
- | Pos -> 0
- | Null -> 1
- in
- combinesmall 1 h
-| Type u ->
- let h = Univ.Universe.hash u in
- combinesmall 2 h
+ | Prop -> combinesmall 1 0
+ | Set -> combinesmall 1 1
+ | Type u ->
+ let h = Univ.Universe.hash u in
+ combinesmall 2 h
module List = struct
let mem = List.memq
@@ -101,7 +94,7 @@ module Hsorts =
if u' == u then c else Type u'
| s -> s
let eq s1 s2 = match (s1,s2) with
- | (Prop c1, Prop c2) -> c1 == c2
+ | Prop, Prop | Set, Set -> true
| (Type u1, Type u2) -> u1 == u2
|_ -> false
diff --git a/kernel/sorts.mli b/kernel/sorts.mli
index 1bbde26083..cac6229b91 100644
--- a/kernel/sorts.mli
+++ b/kernel/sorts.mli
@@ -10,13 +10,12 @@
(** {6 The sorts of CCI. } *)
-type contents = Pos | Null
-
type family = InProp | InSet | InType
type t =
-| Prop of contents (** Prop and Set *)
-| Type of Univ.Universe.t (** Type *)
+ | Prop
+ | Set
+ | Type of Univ.Universe.t
val set : t
val prop : t
diff --git a/kernel/subtyping.ml b/kernel/subtyping.ml
index 13701d4894..74042f9e04 100644
--- a/kernel/subtyping.ml
+++ b/kernel/subtyping.ml
@@ -17,7 +17,6 @@
open Names
open Univ
open Util
-open Term
open Constr
open Declarations
open Declareops
@@ -138,39 +137,8 @@ let check_inductive cst env mp1 l info1 mp2 mib2 spec2 subst1 subst2 reso1 reso2
in
let mib2 = Declareops.subst_mind_body subst2 mib2 in
let check_inductive_type cst name t1 t2 =
-
- (* Due to template polymorphism, the conclusions of
- t1 and t2, if in Type, are generated as the least upper bounds
- of the types of the constructors.
-
- By monotonicity of the infered l.u.b. wrt subtyping (i.e. if X:U
- |- T(X):s and |- M:U' and U'<=U then infer_type(T(M))<=s), each
- universe in the conclusion of t1 has an bounding universe in
- the conclusion of t2, so that we don't need to check the
- subtyping of the conclusions of t1 and t2.
-
- Even if we'd like to recheck it, the inference of constraints
- is not designed to deal with algebraic constraints of the form
- max-univ(u1..un) <= max-univ(u'1..u'n), so that it is not easy
- to recheck it (in short, we would need the actual graph of
- constraints as input while type checking is currently designed
- to output a set of constraints instead) *)
-
- (* So we cheat and replace the subtyping problem on algebraic
- constraints of the form max-univ(u1..un) <= max-univ(u'1..u'n)
- (that we know are necessary true) by trivial constraints that
- the constraint generator knows how to deal with *)
-
- let (ctx1,s1) = dest_arity env t1 in
- let (ctx2,s2) = dest_arity env t2 in
- let s1,s2 =
- match s1, s2 with
- | Type _, Type _ -> (* shortcut here *) Sorts.prop, Sorts.prop
- | (Prop _, Type _) | (Type _,Prop _) ->
- error (NotConvertibleInductiveField name)
- | _ -> (s1, s2) in
check_conv (NotConvertibleInductiveField name)
- cst (inductive_is_polymorphic mib1) infer_conv_leq env (mkArity (ctx1,s1)) (mkArity (ctx2,s2))
+ cst (inductive_is_polymorphic mib1) infer_conv_leq env t1 t2
in
let check_packet cst p1 p2 =
@@ -256,57 +224,12 @@ let check_inductive cst env mp1 l info1 mp2 mib2 spec2 subst1 subst2 reso1 reso2
cst
-let check_constant cst env mp1 l info1 cb2 spec2 subst1 subst2 =
+let check_constant cst env l info1 cb2 spec2 subst1 subst2 =
let error why = error_signature_mismatch l spec2 why in
let check_conv cst poly f = check_conv_error error cst poly f in
let check_type poly cst env t1 t2 =
-
let err = NotConvertibleTypeField (env, t1, t2) in
-
- (* If the type of a constant is generated, it may mention
- non-variable algebraic universes that the general conversion
- algorithm is not ready to handle. Anyway, generated types of
- constants are functions of the body of the constant. If the
- bodies are the same in environments that are subtypes one of
- the other, the types are subtypes too (i.e. if Gamma <= Gamma',
- Gamma |- A |> T, Gamma |- A' |> T' and Gamma |- A=A' then T <= T').
- Hence they don't have to be checked again *)
-
- let t1,t2 =
- if isArity t2 then
- let (ctx2,s2) = destArity t2 in
- match s2 with
- | Type v when not (is_univ_variable v) ->
- (* The type in the interface is inferred and is made of algebraic
- universes *)
- begin try
- let (ctx1,s1) = dest_arity env t1 in
- match s1 with
- | Type u when not (is_univ_variable u) ->
- (* Both types are inferred, no need to recheck them. We
- cheat and collapse the types to Prop *)
- mkArity (ctx1,Sorts.prop), mkArity (ctx2,Sorts.prop)
- | Prop _ ->
- (* The type in the interface is inferred, it may be the case
- that the type in the implementation is smaller because
- the body is more reduced. We safely collapse the upper
- type to Prop *)
- mkArity (ctx1,Sorts.prop), mkArity (ctx2,Sorts.prop)
- | Type _ ->
- (* The type in the interface is inferred and the type in the
- implementation is not inferred or is inferred but from a
- more reduced body so that it is just a variable. Since
- constraints of the form "univ <= max(...)" are not
- expressible in the system of algebraic universes: we fail
- (the user has to use an explicit type in the interface *)
- error NoTypeConstraintExpected
- with NotArity ->
- error err end
- | _ ->
- t1,t2
- else
- (t1,t2) in
- check_conv err cst poly infer_conv_leq env t1 t2
+ check_conv err cst poly infer_conv_leq env t1 t2
in
match info1 with
| Constant cb1 ->
@@ -369,7 +292,7 @@ and check_signatures cst env mp1 sig1 mp2 sig2 subst1 subst2 reso1 reso2=
let check_one_body cst (l,spec2) =
match spec2 with
| SFBconst cb2 ->
- check_constant cst env mp1 l (get_obj mp1 map1 l)
+ check_constant cst env l (get_obj mp1 map1 l)
cb2 spec2 subst1 subst2
| SFBmind mib2 ->
check_inductive cst env mp1 l (get_obj mp1 map1 l)
diff --git a/kernel/term.ml b/kernel/term.ml
index b44e038e9f..4851a9c0d0 100644
--- a/kernel/term.ml
+++ b/kernel/term.ml
@@ -16,14 +16,11 @@ open Vars
open Constr
(* Deprecated *)
-type contents = Sorts.contents = Pos | Null
-[@@ocaml.deprecated "Alias for Sorts.contents"]
-
type sorts_family = Sorts.family = InProp | InSet | InType
[@@ocaml.deprecated "Alias for Sorts.family"]
type sorts = Sorts.t =
- | Prop of Sorts.contents (** Prop and Set *)
+ | Prop | Set
| Type of Univ.Universe.t (** Type *)
[@@ocaml.deprecated "Alias for Sorts.t"]
@@ -339,7 +336,7 @@ let strip_lam_n n t = snd (decompose_lam_n n t)
Such a term can canonically be seen as the pair of a context of types
and of a sort *)
-type arity = Context.Rel.t * Sorts.t
+type arity = Constr.rel_context * Sorts.t
let destArity =
let open Context.Rel.Declaration in
diff --git a/kernel/term.mli b/kernel/term.mli
index f651d1a580..181d714ed7 100644
--- a/kernel/term.mli
+++ b/kernel/term.mli
@@ -25,14 +25,14 @@ val mkNamedLetIn : Id.t -> constr -> types -> constr -> constr
val mkNamedProd : Id.t -> types -> types -> types
(** Constructs either [(x:t)c] or [[x=b:t]c] *)
-val mkProd_or_LetIn : Context.Rel.Declaration.t -> types -> types
-val mkProd_wo_LetIn : Context.Rel.Declaration.t -> types -> types
-val mkNamedProd_or_LetIn : Context.Named.Declaration.t -> types -> types
-val mkNamedProd_wo_LetIn : Context.Named.Declaration.t -> types -> types
+val mkProd_or_LetIn : Constr.rel_declaration -> types -> types
+val mkProd_wo_LetIn : Constr.rel_declaration -> types -> types
+val mkNamedProd_or_LetIn : Constr.named_declaration -> types -> types
+val mkNamedProd_wo_LetIn : Constr.named_declaration -> types -> types
(** Constructs either [[x:t]c] or [[x=b:t]c] *)
-val mkLambda_or_LetIn : Context.Rel.Declaration.t -> constr -> constr
-val mkNamedLambda_or_LetIn : Context.Named.Declaration.t -> constr -> constr
+val mkLambda_or_LetIn : Constr.rel_declaration -> constr -> constr
+val mkNamedLambda_or_LetIn : Constr.named_declaration -> constr -> constr
(** {5 Other term constructors. } *)
@@ -74,8 +74,8 @@ val to_lambda : int -> constr -> constr
where [l] is [fun (x_1:T_1)...(x_n:T_n) => T] *)
val to_prod : int -> constr -> constr
-val it_mkLambda_or_LetIn : constr -> Context.Rel.t -> constr
-val it_mkProd_or_LetIn : types -> Context.Rel.t -> types
+val it_mkLambda_or_LetIn : constr -> Constr.rel_context -> constr
+val it_mkProd_or_LetIn : types -> Constr.rel_context -> types
(** In [lambda_applist c args], [c] is supposed to have the form
[λΓ.c] with [Γ] without let-in; it returns [c] with the variables
@@ -126,29 +126,29 @@ val decompose_lam_n : int -> constr -> (Name.t * constr) list * constr
(** Extract the premisses and the conclusion of a term of the form
"(xi:Ti) ... (xj:=cj:Tj) ..., T" where T is not a product nor a let *)
-val decompose_prod_assum : types -> Context.Rel.t * types
+val decompose_prod_assum : types -> Constr.rel_context * types
(** Idem with lambda's and let's *)
-val decompose_lam_assum : constr -> Context.Rel.t * constr
+val decompose_lam_assum : constr -> Constr.rel_context * constr
(** Idem but extract the first [n] premisses, counting let-ins. *)
-val decompose_prod_n_assum : int -> types -> Context.Rel.t * types
+val decompose_prod_n_assum : int -> types -> Constr.rel_context * types
(** Idem for lambdas, _not_ counting let-ins *)
-val decompose_lam_n_assum : int -> constr -> Context.Rel.t * constr
+val decompose_lam_n_assum : int -> constr -> Constr.rel_context * constr
(** Idem, counting let-ins *)
-val decompose_lam_n_decls : int -> constr -> Context.Rel.t * constr
+val decompose_lam_n_decls : int -> constr -> Constr.rel_context * constr
(** Return the premisses/parameters of a type/term (let-in included) *)
-val prod_assum : types -> Context.Rel.t
-val lam_assum : constr -> Context.Rel.t
+val prod_assum : types -> Constr.rel_context
+val lam_assum : constr -> Constr.rel_context
(** Return the first n-th premisses/parameters of a type (let included and counted) *)
-val prod_n_assum : int -> types -> Context.Rel.t
+val prod_n_assum : int -> types -> Constr.rel_context
(** Return the first n-th premisses/parameters of a term (let included but not counted) *)
-val lam_n_assum : int -> constr -> Context.Rel.t
+val lam_n_assum : int -> constr -> Constr.rel_context
(** Remove the premisses/parameters of a type/term *)
val strip_prod : types -> types
@@ -167,7 +167,7 @@ val strip_lam_assum : constr -> constr
Such a term can canonically be seen as the pair of a context of types
and of a sort *)
-type arity = Context.Rel.t * Sorts.t
+type arity = Constr.rel_context * Sorts.t
(** Build an "arity" from its canonical form *)
val mkArity : arity -> types
@@ -190,13 +190,10 @@ type ('constr, 'types) kind_of_type =
val kind_of_type : types -> (constr, types) kind_of_type
(* Deprecated *)
-type contents = Sorts.contents = Pos | Null
-[@@ocaml.deprecated "Alias for Sorts.contents"]
-
type sorts_family = Sorts.family = InProp | InSet | InType
[@@ocaml.deprecated "Alias for Sorts.family"]
type sorts = Sorts.t =
- | Prop of Sorts.contents (** Prop and Set *)
+ | Prop | Set
| Type of Univ.Universe.t (** Type *)
[@@ocaml.deprecated "Alias for Sorts.t"]
diff --git a/kernel/term_typing.ml b/kernel/term_typing.ml
index 84fc505c4f..43351737e5 100644
--- a/kernel/term_typing.ml
+++ b/kernel/term_typing.ml
@@ -367,7 +367,7 @@ let build_constant_declaration kn env result =
str "Proof using " ++ declared_vars ++ fnl () ++
str "to" ++ fnl () ++
str "Proof using " ++ inferred_vars) in
- let sort evn l =
+ let sort l =
List.filter (fun decl ->
let id = NamedDecl.get_id decl in
List.exists (NamedDecl.get_id %> Names.Id.equal id) l)
@@ -400,7 +400,7 @@ let build_constant_declaration kn env result =
[], def (* Empty section context: no need to check *)
| Some declared ->
(* We use the declared set and chain a check of correctness *)
- sort env declared,
+ sort declared,
match def with
| Undef _ as x -> x (* nothing to check *)
| Def cs as x ->
@@ -539,7 +539,7 @@ let translate_recipe env kn r =
be useless. It is detected by the dirpath of the constant being empty. *)
let (_, dir, _) = Constant.repr3 kn in
let hcons = DirPath.is_empty dir in
- build_constant_declaration kn env (Cooking.cook_constant ~hcons env r)
+ build_constant_declaration kn env (Cooking.cook_constant ~hcons r)
let translate_local_def env id centry =
let open Cooking in
diff --git a/kernel/typeops.ml b/kernel/typeops.ml
index 34ed2afb27..7f36f3813f 100644
--- a/kernel/typeops.ml
+++ b/kernel/typeops.ml
@@ -69,7 +69,7 @@ let type_of_type u =
mkType uu
let type_of_sort = function
- | Prop c -> type1
+ | Prop | Set -> type1
| Type u -> type_of_type u
(*s Type of a de Bruijn index. *)
@@ -178,11 +178,11 @@ let type_of_apply env func funt argsv argstv =
let sort_of_product env domsort rangsort =
match (domsort, rangsort) with
(* Product rule (s,Prop,Prop) *)
- | (_, Prop Null) -> rangsort
+ | (_, Prop) -> rangsort
(* Product rule (Prop/Set,Set,Set) *)
- | (Prop _, Prop Pos) -> rangsort
+ | ((Prop | Set), Set) -> rangsort
(* Product rule (Type,Set,?) *)
- | (Type u1, Prop Pos) ->
+ | (Type u1, Set) ->
if is_impredicative_set env then
(* Rule is (Type,Set,Set) in the Set-impredicative calculus *)
rangsort
@@ -190,9 +190,9 @@ let sort_of_product env domsort rangsort =
(* Rule is (Type_i,Set,Type_i) in the Set-predicative calculus *)
Type (Universe.sup Universe.type0 u1)
(* Product rule (Prop,Type_i,Type_i) *)
- | (Prop Pos, Type u2) -> Type (Universe.sup Universe.type0 u2)
+ | (Set, Type u2) -> Type (Universe.sup Universe.type0 u2)
(* Product rule (Prop,Type_i,Type_i) *)
- | (Prop Null, Type _) -> rangsort
+ | (Prop, Type _) -> rangsort
(* Product rule (Type_i,Type_i,Type_i) *)
| (Type u1, Type u2) -> Type (Universe.sup u1 u2)
@@ -296,13 +296,13 @@ let type_of_case env ci p pt c ct lf lft =
rslty
let type_of_projection env p c ct =
- let pb = lookup_projection p env in
+ let pty = lookup_projection p env in
let (ind,u), args =
try find_rectype env ct
with Not_found -> error_case_not_inductive env (make_judge c ct)
in
- assert(eq_ind pb.proj_ind ind);
- let ty = Vars.subst_instance_constr u pb.Declarations.proj_type in
+ assert(eq_ind (Projection.inductive p) ind);
+ let ty = Vars.subst_instance_constr u pty in
substl (c :: CList.rev args) ty
@@ -481,10 +481,6 @@ let judge_of_prop = make_judge mkProp type1
let judge_of_set = make_judge mkSet type1
let judge_of_type u = make_judge (mkType u) (type_of_type u)
-let judge_of_prop_contents = function
- | Null -> judge_of_prop
- | Pos -> judge_of_set
-
let judge_of_relative env k = make_judge (mkRel k) (type_of_relative env k)
let judge_of_variable env x = make_judge (mkVar x) (type_of_variable env x)
diff --git a/kernel/typeops.mli b/kernel/typeops.mli
index 546f2d2b4d..57acdfe4b5 100644
--- a/kernel/typeops.mli
+++ b/kernel/typeops.mli
@@ -28,7 +28,7 @@ val infer_v : env -> constr array -> unsafe_judgment array
val infer_type : env -> types -> unsafe_type_judgment
val infer_local_decls :
- env -> (Id.t * local_entry) list -> (env * Context.Rel.t)
+ env -> (Id.t * local_entry) list -> (env * Constr.rel_context)
(** {6 Basic operations of the typing machine. } *)
@@ -43,7 +43,6 @@ val type1 : types
val type_of_sort : Sorts.t -> types
val judge_of_prop : unsafe_judgment
val judge_of_set : unsafe_judgment
-val judge_of_prop_contents : Sorts.contents -> unsafe_judgment
val judge_of_type : Universe.t -> unsafe_judgment
(** {6 Type of a bound variable. } *)
@@ -103,4 +102,4 @@ val judge_of_case : env -> case_info
val type_of_constant_in : env -> pconstant -> types
(** Check that hyps are included in env and fails with error otherwise *)
-val check_hyps_inclusion : env -> ('a -> constr) -> 'a -> Context.Named.t -> unit
+val check_hyps_inclusion : env -> ('a -> constr) -> 'a -> Constr.named_context -> unit
diff --git a/kernel/uGraph.ml b/kernel/uGraph.ml
index 4a9467de52..bc624ba56d 100644
--- a/kernel/uGraph.ml
+++ b/kernel/uGraph.ml
@@ -747,6 +747,45 @@ let check_constraint g (l,d,r) =
let check_constraints c g =
Constraint.for_all (check_constraint g) c
+let leq_expr (u,m) (v,n) =
+ let d = match m - n with
+ | 1 -> Lt
+ | diff -> assert (diff <= 0); Le
+ in
+ (u,d,v)
+
+let enforce_leq_alg u v g =
+ let enforce_one (u,v) = function
+ | Inr _ as orig -> orig
+ | Inl (cstrs,g) as orig ->
+ if check_smaller_expr g u v then orig
+ else
+ (let c = leq_expr u v in
+ match enforce_constraint c g with
+ | g -> Inl (Constraint.add c cstrs,g)
+ | exception (UniverseInconsistency _ as e) -> Inr e)
+ in
+ (* max(us) <= max(vs) <-> forall u in us, exists v in vs, u <= v *)
+ let c = Universe.map (fun u -> Universe.map (fun v -> (u,v)) v) u in
+ let c = List.cartesians enforce_one (Inl (Constraint.empty,g)) c in
+ (* We pick a best constraint: smallest number of constraints, not an error if possible. *)
+ let order x y = match x, y with
+ | Inr _, Inr _ -> 0
+ | Inl _, Inr _ -> -1
+ | Inr _, Inl _ -> 1
+ | Inl (c,_), Inl (c',_) ->
+ Int.compare (Constraint.cardinal c) (Constraint.cardinal c')
+ in
+ match List.min order c with
+ | Inl x -> x
+ | Inr e -> raise e
+
+(* sanity check wrapper *)
+let enforce_leq_alg u v g =
+ let _,g as cg = enforce_leq_alg u v g in
+ assert (check_leq g u v);
+ cg
+
(* Normalization *)
(** [normalize_universes g] returns a graph where all edges point
diff --git a/kernel/uGraph.mli b/kernel/uGraph.mli
index e6dd629e45..8c2d877b0b 100644
--- a/kernel/uGraph.mli
+++ b/kernel/uGraph.mli
@@ -42,6 +42,9 @@ val merge_constraints : Constraint.t -> t -> t
val check_constraint : t -> univ_constraint -> bool
val check_constraints : Constraint.t -> t -> bool
+(** Picks an arbitrary set of constraints sufficient to ensure [u <= v]. *)
+val enforce_leq_alg : Universe.t -> Universe.t -> t -> Constraint.t * t
+
(** Adds a universe to the graph, ensuring it is >= or > Set.
@raise AlreadyDeclared if the level is already declared in the graph. *)
diff --git a/kernel/univ.ml b/kernel/univ.ml
index 9782312cae..311477daca 100644
--- a/kernel/univ.ml
+++ b/kernel/univ.ml
@@ -666,7 +666,7 @@ let constraint_add_leq v u c =
else (* j >= 1 *) (* m = n + k, u <= v+k *)
if Level.equal x y then c (* u <= u+k, trivial *)
else if Level.is_small x then c (* Prop,Set <= u+S k, trivial *)
- else anomaly (Pp.str"Unable to handle arbitrary u <= v+k constraints.")
+ else Constraint.add (x,Le,y) c (* u <= v implies u <= v+k *)
let check_univ_leq_one u v = Universe.exists (Expr.leq u) v
@@ -674,12 +674,7 @@ let check_univ_leq u v =
Universe.for_all (fun u -> check_univ_leq_one u v) u
let enforce_leq u v c =
- let rec aux acc v =
- match v with
- | v :: l ->
- aux (List.fold_right (fun u -> constraint_add_leq u v) u c) l
- | [] -> acc
- in aux c v
+ List.fold_left (fun c v -> (List.fold_left (fun c u -> constraint_add_leq u v c) c u)) c v
let enforce_leq u v c =
if check_univ_leq u v then c
diff --git a/kernel/vars.mli b/kernel/vars.mli
index a0c7ba4bd2..fdddbdb342 100644
--- a/kernel/vars.mli
+++ b/kernel/vars.mli
@@ -70,10 +70,10 @@ type substl = constr list
as if usable in [applist] while the substitution is
represented the other way round, i.e. ending with either [u₁] or
[c₁], as if usable for [substl]. *)
-val subst_of_rel_context_instance : Context.Rel.t -> constr list -> substl
+val subst_of_rel_context_instance : Constr.rel_context -> constr list -> substl
(** For compatibility: returns the substitution reversed *)
-val adjust_subst_to_rel_context : Context.Rel.t -> constr list -> constr list
+val adjust_subst_to_rel_context : Constr.rel_context -> constr list -> constr list
(** Take an index in an instance of a context and returns its index wrt to
the full context (e.g. 2 in [x:A;y:=b;z:C] is 3, i.e. a reference to z) *)
@@ -97,13 +97,13 @@ val subst1 : constr -> constr -> constr
accordingly indexes in [a₁],...,[an] and [c]. In terms of typing, if
Γ ⊢ a{_n}..a₁ : Δ and Γ, Δ, Γ', Ω ⊢ with |Γ'|=[k], then
Γ, Γ', [substnl_decl [a₁;...;an]] k Ω ⊢. *)
-val substnl_decl : substl -> int -> Context.Rel.Declaration.t -> Context.Rel.Declaration.t
+val substnl_decl : substl -> int -> Constr.rel_declaration -> Constr.rel_declaration
(** [substl_decl σ Ω] is a short-hand for [substnl_decl σ 0 Ω] *)
-val substl_decl : substl -> Context.Rel.Declaration.t -> Context.Rel.Declaration.t
+val substl_decl : substl -> Constr.rel_declaration -> Constr.rel_declaration
(** [subst1_decl a Ω] is a short-hand for [substnl_decl [a] 0 Ω] *)
-val subst1_decl : constr -> Context.Rel.Declaration.t -> Context.Rel.Declaration.t
+val subst1_decl : constr -> Constr.rel_declaration -> Constr.rel_declaration
(** [replace_vars k [(id₁,c₁);...;(idn,cn)] t] substitutes [Var idj] by
[cj] in [t]. *)
@@ -134,8 +134,8 @@ open Univ
(** Level substitutions for polymorphism. *)
val subst_univs_level_constr : universe_level_subst -> constr -> constr
-val subst_univs_level_context : Univ.universe_level_subst -> Context.Rel.t -> Context.Rel.t
+val subst_univs_level_context : Univ.universe_level_subst -> Constr.rel_context -> Constr.rel_context
(** Instance substitution for polymorphism. *)
val subst_instance_constr : Instance.t -> constr -> constr
-val subst_instance_context : Instance.t -> Context.Rel.t -> Context.Rel.t
+val subst_instance_context : Instance.t -> Constr.rel_context -> Constr.rel_context
diff --git a/kernel/vconv.ml b/kernel/vconv.ml
index 4e4168922d..d19bea5199 100644
--- a/kernel/vconv.ml
+++ b/kernel/vconv.ml
@@ -139,7 +139,7 @@ and conv_stack env k stk1 stk2 cu =
conv_stack env k stk1 stk2 !rcu
else raise NotConvertible
| Zproj p1 :: stk1, Zproj p2 :: stk2 ->
- if Constant.equal p1 p2 then conv_stack env k stk1 stk2 cu
+ if Projection.Repr.equal p1 p2 then conv_stack env k stk1 stk2 cu
else raise NotConvertible
| [], _ | Zapp _ :: _, _ | Zfix _ :: _, _ | Zswitch _ :: _, _
| Zproj _ :: _, _ -> raise NotConvertible
diff --git a/kernel/vmvalues.ml b/kernel/vmvalues.ml
index 8524c44d21..d6d9312938 100644
--- a/kernel/vmvalues.ml
+++ b/kernel/vmvalues.ml
@@ -150,7 +150,7 @@ type zipper =
| Zapp of arguments
| Zfix of vfix*arguments (* Possibly empty *)
| Zswitch of vswitch
- | Zproj of Constant.t (* name of the projection *)
+ | Zproj of Projection.Repr.t (* name of the projection *)
type stack = zipper list
@@ -354,7 +354,7 @@ let val_of_constant c = val_of_idkey (ConstKey c)
let val_of_evar evk = val_of_idkey (EvarKey evk)
external val_of_annot_switch : annot_switch -> values = "%identity"
-external val_of_proj_name : Constant.t -> values = "%identity"
+external val_of_proj_name : Projection.Repr.t -> values = "%identity"
(*************************************************)
(** Operations manipulating data types ***********)
@@ -553,4 +553,4 @@ and pr_zipper z =
| 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 ")")
+ | Zproj c -> str "Zproj(" ++ Projection.Repr.print c ++ str ")")
diff --git a/kernel/vmvalues.mli b/kernel/vmvalues.mli
index 08d05a038c..6eedcf1d37 100644
--- a/kernel/vmvalues.mli
+++ b/kernel/vmvalues.mli
@@ -81,7 +81,7 @@ type zipper =
| Zapp of arguments
| Zfix of vfix * arguments (** might be empty *)
| Zswitch of vswitch
- | Zproj of Constant.t (* name of the projection *)
+ | Zproj of Projection.Repr.t (* name of the projection *)
type stack = zipper list
@@ -108,11 +108,11 @@ val val_of_rel : int -> values
val val_of_named : Id.t -> values
val val_of_constant : Constant.t -> values
val val_of_evar : Evar.t -> values
-val val_of_proj : Constant.t -> values -> values
+val val_of_proj : Projection.Repr.t -> values -> values
val val_of_atom : atom -> values
external val_of_annot_switch : annot_switch -> values = "%identity"
-external val_of_proj_name : Constant.t -> values = "%identity"
+external val_of_proj_name : Projection.Repr.t -> values = "%identity"
(** Destructors *)
diff --git a/lib/cWarnings.ml b/lib/cWarnings.ml
index fda25a0a60..0cf989e494 100644
--- a/lib/cWarnings.ml
+++ b/lib/cWarnings.ml
@@ -120,7 +120,7 @@ let uniquize_flags_rev flags =
(** [normalize_flags] removes redundant warnings. Unknown warnings are kept
because they may be declared in a plugin that will be linked later. *)
-let normalize_flags ~silent warnings =
+let normalize_flags warnings =
let warnings = cut_before_all_rev warnings in
uniquize_flags_rev warnings
@@ -130,7 +130,7 @@ let normalize_flags_string s =
if is_none_keyword s then s
else
let flags = flags_of_string s in
- let flags = normalize_flags ~silent:false flags in
+ let flags = normalize_flags flags in
string_of_flags flags
let parse_warnings items =
@@ -146,7 +146,7 @@ let parse_flags s =
else begin
Flags.make_warn true;
let flags = flags_of_string s in
- let flags = normalize_flags ~silent:true flags in
+ let flags = normalize_flags flags in
parse_warnings flags;
string_of_flags flags
end
diff --git a/lib/coqProject_file.ml4 b/lib/coqProject_file.ml
index 61eb1dafdf..c2bcd73fff 100644
--- a/lib/coqProject_file.ml4
+++ b/lib/coqProject_file.ml
@@ -90,30 +90,50 @@ let rec post_canonize f =
exception Parsing_error of string
-let rec parse_string = parser
- | [< '' ' | '\n' | '\t' >] -> ""
- | [< 'c; s >] -> (String.make 1 c)^(parse_string s)
- | [< >] -> ""
-and parse_string2 = parser
- | [< ''"' >] -> ""
- | [< 'c; s >] -> (String.make 1 c)^(parse_string2 s)
- | [< >] -> raise (Parsing_error "unterminated string")
-and parse_skip_comment = parser
- | [< ''\n'; s >] -> s
- | [< 'c; s >] -> parse_skip_comment s
- | [< >] -> [< >]
-and parse_args = parser
- | [< '' ' | '\n' | '\t'; s >] -> parse_args s
- | [< ''#'; s >] -> parse_args (parse_skip_comment s)
- | [< ''"'; str = parse_string2; s >] -> ("" ^ str) :: parse_args s
- | [< 'c; str = parse_string; s >] -> ((String.make 1 c) ^ str) :: (parse_args s)
- | [< >] -> []
+let buffer buf =
+ let ans = Buffer.contents buf in
+ let () = Buffer.clear buf in
+ ans
+
+let rec parse_string buf s = match Stream.next s with
+| ' ' | '\n' | '\t' -> buffer buf
+| c ->
+ let () = Buffer.add_char buf c in
+ parse_string buf s
+| exception Stream.Failure -> buffer buf
+
+and parse_string2 buf s = match Stream.next s with
+| '"' -> buffer buf
+| c ->
+ let () = Buffer.add_char buf c in
+ parse_string2 buf s
+| exception Stream.Failure -> raise (Parsing_error "unterminated string")
+
+and parse_skip_comment s = match Stream.next s with
+| '\n' -> ()
+| _ -> parse_skip_comment s
+| exception Stream.Failure -> ()
+
+and parse_args buf accu s = match Stream.next s with
+| ' ' | '\n' | '\t' -> parse_args buf accu s
+| '#' ->
+ let () = parse_skip_comment s in
+ parse_args buf accu s
+| '"' ->
+ let str = parse_string2 buf s in
+ parse_args buf (str :: accu) s
+| c ->
+ let () = Buffer.add_char buf c in
+ let str = parse_string buf s in
+ parse_args buf (str :: accu) s
+| exception Stream.Failure -> accu
let parse f =
let c = open_in f in
- let res = parse_args (Stream.of_channel c) in
+ let buf = Buffer.create 64 in
+ let res = parse_args buf [] (Stream.of_channel c) in
close_in c;
- res
+ List.rev res
;;
(* Copy from minisys.ml, since we don't see that file here *)
@@ -143,7 +163,7 @@ let process_cmd_line orig_dir proj args =
error "Use \"-install none\" instead of \"-no-install\""
| "-custom" :: _ ->
error "Use \"-extra[-phony] target deps command\" instead of \"-custom command deps target\""
-
+
| ("-no-opt"|"-byte") :: r -> aux { proj with use_ocamlopt = false } r
| ("-full"|"-opt") :: r -> aux { proj with use_ocamlopt = true } r
| "-install" :: d :: r ->
@@ -189,7 +209,7 @@ let process_cmd_line orig_dir proj args =
error "Output file must be in the current directory";
if proj.makefile <> None then
error "Option -o given more than once";
- aux { proj with makefile = Some file } r
+ aux { proj with makefile = Some file } r
| v :: "=" :: def :: r ->
aux { proj with defs = proj.defs @ [sourced (v,def)] } r
| "-arg" :: a :: r ->
diff --git a/lib/envars.ml b/lib/envars.ml
index be82bfe9bb..3ee0c7106b 100644
--- a/lib/envars.ml
+++ b/lib/envars.ml
@@ -110,6 +110,7 @@ let check_file_else ~dir ~file oth =
if Sys.file_exists (path / file) then path else oth ()
let guess_coqlib fail =
+ getenv_else "COQLIB" (fun () ->
let prelude = "theories/Init/Prelude.vo" in
check_file_else ~dir:Coq_config.coqlibsuffix ~file:prelude
(fun () ->
@@ -117,6 +118,7 @@ let guess_coqlib fail =
then Coq_config.coqlib
else
fail "cannot guess a path for Coq libraries; please use -coqlib option")
+ )
(** coqlib is now computed once during coqtop initialization *)
diff --git a/lib/lib.mllib b/lib/lib.mllib
index 0891859423..41b3622a99 100644
--- a/lib/lib.mllib
+++ b/lib/lib.mllib
@@ -6,6 +6,7 @@ Control
Util
Pp
+Pp_diff
Stateid
Loc
Feedback
diff --git a/lib/pp.ml b/lib/pp.ml
index cd81f6e768..7f132686db 100644
--- a/lib/pp.ml
+++ b/lib/pp.ml
@@ -139,7 +139,7 @@ let v n s = Ppcmd_box(Pp_vbox n,s)
let hv n s = Ppcmd_box(Pp_hvbox n,s)
let hov n s = Ppcmd_box(Pp_hovbox n,s)
-(* Opening and closed of tags *)
+(* Opening and closing of tags *)
let tag t s = Ppcmd_tag(t,s)
(* In new syntax only double quote char is escaped by repeating it *)
@@ -167,6 +167,20 @@ let rec pr_com ft s =
Some s2 -> Format.pp_force_newline ft (); pr_com ft s2
| None -> ()
+let start_pfx = "start."
+let end_pfx = "end."
+
+let split_pfx pfx str =
+ let (str_len, pfx_len) = (String.length str, String.length pfx) in
+ if str_len >= pfx_len && (String.sub str 0 pfx_len) = pfx then
+ (pfx, String.sub str pfx_len (str_len - pfx_len)) else ("", str);;
+
+let split_tag tag =
+ let (pfx, ttag) = split_pfx start_pfx tag in
+ if pfx <> "" then (pfx, ttag) else
+ let (pfx, ttag) = split_pfx end_pfx tag in
+ (pfx, ttag);;
+
(* pretty printing functions *)
let pp_with ft pp =
let cpp_open_box = function
@@ -297,3 +311,62 @@ let prvect_with_sep sep elem v = prvecti_with_sep sep (fun _ -> elem) v
let prvect elem v = prvect_with_sep mt elem v
let surround p = hov 1 (str"(" ++ p ++ str")")
+
+(*** DEBUG code ***)
+
+let db_print_pp fmt pp =
+ let open Format in
+ let block_type fmt btype =
+ let (bt, v) =
+ match btype with
+ | Pp_hbox v -> ("Pp_hbox", v)
+ | Pp_vbox v -> ("Pp_vbox", v)
+ | Pp_hvbox v -> ("Pp_hvbox", v)
+ | Pp_hovbox v -> ("Pp_hovbox", v)
+ in
+ fprintf fmt "%s %d" bt v
+ in
+ let rec db_print_pp_r indent pp =
+ let ind () = fprintf fmt "%s" (String.make (2 * indent) ' ') in
+ ind();
+ match pp with
+ | Ppcmd_empty ->
+ fprintf fmt "Ppcmd_empty@;"
+ | Ppcmd_string str ->
+ fprintf fmt "Ppcmd_string '%s'@;" str
+ | Ppcmd_glue list ->
+ fprintf fmt "Ppcmd_glue@;";
+ List.iter (fun x -> db_print_pp_r (indent + 1) (repr x)) list;
+ | Ppcmd_box (block, pp) ->
+ fprintf fmt "Ppcmd_box %a@;" block_type block;
+ db_print_pp_r (indent + 1) (repr pp);
+ | Ppcmd_tag (tag, pp) ->
+ fprintf fmt "Ppcmd_tag %s@;" tag;
+ db_print_pp_r (indent + 1) (repr pp);
+ | Ppcmd_print_break (i, j) ->
+ fprintf fmt "Ppcmd_print_break %d %d@;" i j
+ | Ppcmd_force_newline ->
+ fprintf fmt "Ppcmd_force_newline@;"
+ | Ppcmd_comment list ->
+ fprintf fmt "Ppcmd_comment@;";
+ List.iter (fun x -> ind(); (fprintf fmt "%s@;" x)) list
+ in
+ pp_open_vbox fmt 0;
+ db_print_pp_r 0 pp;
+ pp_close_box fmt ();
+ pp_print_flush fmt ()
+
+let db_string_of_pp pp =
+ Format.asprintf "%a" db_print_pp pp
+
+let rec flatten pp =
+ match pp with
+ | Ppcmd_glue l -> Ppcmd_glue (List.concat (List.map
+ (fun x -> let x = flatten x in
+ match x with
+ | Ppcmd_glue l2 -> l2
+ | p -> [p])
+ l))
+ | Ppcmd_box (block, pp) -> Ppcmd_box (block, flatten pp)
+ | Ppcmd_tag (tag, pp) -> Ppcmd_tag (tag, flatten pp)
+ | p -> p
diff --git a/lib/pp.mli b/lib/pp.mli
index f3a0a29b8a..ed31daa561 100644
--- a/lib/pp.mli
+++ b/lib/pp.mli
@@ -189,3 +189,22 @@ val pr_vertical_list : ('b -> t) -> 'b list -> t
val pp_with : Format.formatter -> t -> unit
val string_of_ppcmds : t -> string
+
+
+(** Tag prefix to start a multi-token diff span *)
+val start_pfx : string
+
+(** Tag prefix to end a multi-token diff span *)
+val end_pfx : string
+
+(** Split a tag into prefix and base tag *)
+val split_tag : string -> string * string
+
+(** Print the Pp in tree form for debugging *)
+val db_print_pp : Format.formatter -> t -> unit
+
+(** Print the Pp in tree form for debugging, return as a string *)
+val db_string_of_pp : t -> string
+
+(** Combine nested Ppcmd_glues *)
+val flatten : t -> t
diff --git a/lib/pp_diff.ml b/lib/pp_diff.ml
new file mode 100644
index 0000000000..7b4b1eab73
--- /dev/null
+++ b/lib/pp_diff.ml
@@ -0,0 +1,303 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+(* DEBUG/UNIT TEST *)
+let cfprintf oc = Printf.(kfprintf (fun oc -> fprintf oc "") oc)
+let log_out_ch = ref stdout
+let cprintf s = cfprintf !log_out_ch s
+
+
+module StringDiff = Diff2.Make(struct
+ type elem = String.t
+ type t = elem array
+ let get t i = Array.get t i
+ let length t = Array.length t
+end)
+
+type diff_type =
+ [ `Removed
+ | `Added
+ | `Common
+ ]
+
+type diff_list = StringDiff.elem Diff2.edit list
+
+(* debug print diff data structure *)
+let db_print_diffs fmt diffs =
+ let open Format in
+ let print_diff = function
+ | `Common (opos, npos, s) ->
+ fprintf fmt "Common '%s' opos = %d npos = %d\n" s opos npos;
+ | `Removed (pos, s) ->
+ fprintf fmt "Removed '%s' opos = %d\n" s pos;
+ | `Added (pos, s) ->
+ fprintf fmt "Added '%s' npos = %d\n" s pos;
+ in
+ pp_open_vbox fmt 0;
+ List.iter print_diff diffs;
+ pp_close_box fmt ();
+ pp_print_flush fmt ()
+
+let string_of_diffs diffs =
+ Format.asprintf "%a" db_print_diffs diffs
+
+(* Adjust the diffs returned by the Myers algorithm to reduce the span of the
+changes. This gives more natural-looking diffs.
+
+While the Myers algorithm minimizes the number of changes between two
+sequences, it doesn't minimize the span of the changes. For example,
+representing elements in common in lower case and inserted elements in upper
+case (but ignoring case in the algorithm), ABabC and abABC both have 3 changes
+(A, B and C). However the span of the first sequence is 5 elements (ABabC)
+while the span of the second is 3 elements (ABC).
+
+The algorithm modifies the changes iteratively, for example ABabC -> aBAbC -> abABC
+
+dtype: identifies which of Added OR Removed to use; the other one is ignored.
+diff_list: output from the Myers algorithm
+*)
+let shorten_diff_span dtype diff_list =
+ let changed = ref false in
+ let diffs = Array.of_list diff_list in
+ let len = Array.length diffs in
+ let vinfo index =
+ match diffs.(index) with
+ | `Common (opos, npos, s) -> (`Common, opos, npos, s)
+ | `Removed (pos, s) -> (`Removed, pos, 0, s)
+ | `Added (pos, s) -> (`Added, 0, pos, s) in
+ let get_variant index =
+ let (v, _, _, _) = vinfo index in
+ v in
+ let get_str index =
+ let (_, _, _, s) = vinfo index in
+ s in
+
+ let iter start len lt incr = begin
+ let src = ref start in
+ let dst = ref start in
+ while (lt !src len) do
+ if (get_variant !src) = dtype then begin
+ if (lt !dst !src) then
+ dst := !src;
+ while (lt !dst len) && (get_variant !dst) <> `Common do
+ dst := !dst + incr;
+ done;
+ if (lt !dst len) && (get_str !src) = (get_str !dst) then begin
+ (* swap diff *)
+ let (_, c_opos, c_npos, str) = vinfo !dst
+ and (_, v_opos, v_npos, _) = vinfo !src in
+ changed := true;
+ if dtype = `Added then begin
+ diffs.(!src) <- `Common (c_opos, v_npos, str);
+ diffs.(!dst) <- `Added (c_npos, str);
+ end else begin
+ diffs.(!src) <- `Common (v_opos, c_npos, str);
+ diffs.(!dst) <- `Removed (c_opos, str)
+ end
+ end
+ end;
+ src := !src + incr
+ done
+ end in
+
+ iter 0 len (<) 1; (* left to right *)
+ iter (len-1) (-1) (>) (-1); (* right to left *)
+ if !changed then Array.to_list diffs else diff_list;;
+
+let has_changes diffs =
+ let rec has_changes_r diffs added removed =
+ match diffs with
+ | `Added _ :: t -> has_changes_r t true removed
+ | `Removed _ :: t -> has_changes_r t added true
+ | h :: t -> has_changes_r t added removed
+ | [] -> (added, removed) in
+ has_changes_r diffs false false;;
+
+(* get the Myers diff of 2 lists of strings *)
+let diff_strs old_strs new_strs =
+ let diffs = List.rev (StringDiff.diff old_strs new_strs) in
+ shorten_diff_span `Removed (shorten_diff_span `Added diffs);;
+
+(* Default string tokenizer. Makes each character a separate strin.
+Whitespace is not ignored. Doesn't handle UTF-8 differences well. *)
+let def_tokenize_string s =
+ let limit = (String.length s) - 1 in
+ let strs : string list ref = ref [] in
+ for i = 0 to limit do
+ strs := (String.make 1 s.[i]) :: !strs
+ done;
+ List.rev !strs
+
+(* get the Myers diff of 2 strings *)
+let diff_str ?(tokenize_string=def_tokenize_string) old_str new_str =
+ let old_toks = Array.of_list (tokenize_string old_str)
+ and new_toks = Array.of_list (tokenize_string new_str) in
+ diff_strs old_toks new_toks;;
+
+let get_dinfo = function
+ | `Common (_, _, s) -> (`Common, s)
+ | `Removed (_, s) -> (`Removed, s)
+ | `Added (_, s) -> (`Added, s)
+
+[@@@ocaml.warning "-32"]
+let string_of_diff_type = function
+ | `Common -> "Common"
+ | `Removed -> "Removed"
+ | `Added -> "Added"
+[@@@ocaml.warning "+32"]
+
+let wrap_in_bg diff_tag pp =
+ let open Pp in
+ (tag (Pp.start_pfx ^ diff_tag ^ ".bg") (str "")) ++ pp ++
+ (tag (Pp.end_pfx ^ diff_tag ^ ".bg") (str ""))
+
+exception Diff_Failure of string
+
+let add_diff_tags which pp diffs =
+ let open Pp in
+ let diff_tag = if which = `Added then "diff.added" else "diff.removed" in
+ let diffs : diff_list ref = ref diffs in
+ let in_diff = ref false in (* true = buf chars need a tag *)
+ let in_span = ref false in (* true = last pp had a start tag *)
+ let trans = ref false in (* true = this diff starts/ends highlight *)
+ let buf = Buffer.create 16 in
+ let acc_pp = ref [] in
+ let diff_str, diff_ind, diff_len = ref "", ref 0, ref 0 in
+ let prev_dtype, dtype, next_dtype = ref `Common, ref `Common, ref `Common in
+ let is_white c = List.mem c [' '; '\t'; '\n'; '\r'] in
+
+ let skip () =
+ while !diffs <> [] &&
+ (let (t, _) = get_dinfo (List.hd !diffs) in
+ t <> `Common && t <> which)
+ do
+ diffs := List.tl !diffs
+ done
+ in
+
+ let put_tagged case =
+ if Buffer.length buf > 0 then begin
+ let pp = str (Buffer.contents buf) in
+ Buffer.clear buf;
+ let tagged = match case with
+ | "" -> pp
+ | "tag" -> tag diff_tag pp
+ | "start" -> in_span := true; tag (start_pfx ^ diff_tag) pp
+ | "end" -> in_span := false; tag (end_pfx ^ diff_tag) pp
+ | _ -> raise (Diff_Failure "invalid tag id in put_tagged, should be impossible") in
+ acc_pp := tagged :: !acc_pp
+ end
+ in
+
+ let output_pps () =
+ let next_diff_char_hl = if !diff_ind < !diff_len then !dtype = which else !next_dtype = which in
+ let tag = if not !in_diff then ""
+ else if !in_span then
+ if next_diff_char_hl then "" else "end"
+ else
+ if next_diff_char_hl then "start" else "tag" in
+ put_tagged tag; (* flush any remainder *)
+ let l = !acc_pp in
+ acc_pp := [];
+ match List.length l with
+ | 0 -> str ""
+ | 1 -> List.hd l
+ | _ -> seq (List.rev l)
+ in
+
+ let maybe_next_diff () =
+ if !diff_ind = !diff_len && (skip(); !diffs <> []) then begin
+ let (t, s) = get_dinfo (List.hd !diffs) in
+ diff_str := s; diff_ind := 0; diff_len := String.length !diff_str;
+ diffs := List.tl !diffs; skip();
+ prev_dtype := !dtype;
+ dtype := t;
+ next_dtype := (match !diffs with
+ | diff2 :: _ -> let (nt, _) = get_dinfo diff2 in nt
+ | [] -> `Common);
+ trans := !dtype <> !prev_dtype
+ end;
+ in
+
+ let s_char c =
+ maybe_next_diff ();
+ (* matching first should handle tokens with spaces, e.g. in comments/strings *)
+ if !diff_ind < !diff_len && c = !diff_str.[!diff_ind] then begin
+ if !dtype = which && !trans && !diff_ind = 0 then begin
+ put_tagged "";
+ in_diff := true
+ end;
+ Buffer.add_char buf c;
+ diff_ind := !diff_ind + 1;
+ if !dtype = which && !dtype <> !next_dtype && !diff_ind = !diff_len then begin
+ put_tagged (if !in_span then "end" else "tag");
+ in_diff := false
+ end
+ end else if is_white c then
+ Buffer.add_char buf c
+ else begin
+ cprintf "mismatch: expected '%c' but got '%c'\n" !diff_str.[!diff_ind] c;
+ raise (Diff_Failure "string mismatch, shouldn't happen")
+ end
+ in
+
+ (* rearrange so existing tags are inside diff tags, provided that those tags
+ only contain Ppcmd_string's. Other cases (e.g. tag of a box) are not supported. *)
+ (* todo: Is there a better way to do this in OCaml without multiple 'repr's? *)
+ let reorder_tags child pp_tag pp =
+ match repr child with
+ | Ppcmd_tag (t1, pp) -> tag t1 (tag pp_tag pp)
+ | Ppcmd_glue l ->
+ if List.exists (fun x ->
+ match repr x with
+ | Ppcmd_tag (_, _) -> true
+ | _ -> false) l
+ then seq (List.map (fun x ->
+ match repr x with
+ | Ppcmd_tag (t2, pp2) -> tag t2 (tag pp_tag pp2)
+ | pp2 -> tag pp_tag (unrepr pp2)) l)
+ else child
+ | _ -> tag pp_tag child
+ in
+
+ let rec add_tags_r pp =
+ let r_pp = repr pp in
+ match r_pp with
+ | Ppcmd_string s -> String.iter s_char s; output_pps ()
+ | Ppcmd_glue l -> seq (List.map add_tags_r l)
+ | Ppcmd_box (block_type, pp) -> unrepr (Ppcmd_box (block_type, add_tags_r pp))
+ | Ppcmd_tag (pp_tag, pp) -> reorder_tags (add_tags_r pp) pp_tag pp
+ | _ -> pp
+ in
+ let (has_added, has_removed) = has_changes !diffs in
+ let rv = add_tags_r pp in
+ skip ();
+ if !diffs <> [] then
+ raise (Diff_Failure "left-over diff info at end of Pp.t, should be impossible");
+ if has_added || has_removed then wrap_in_bg diff_tag rv else rv;;
+
+let diff_pp ?(tokenize_string=def_tokenize_string) o_pp n_pp =
+ let open Pp in
+ let o_str = string_of_ppcmds o_pp in
+ let n_str = string_of_ppcmds n_pp in
+ let diffs = diff_str ~tokenize_string o_str n_str in
+ (add_diff_tags `Removed o_pp diffs, add_diff_tags `Added n_pp diffs);;
+
+let diff_pp_combined ?(tokenize_string=def_tokenize_string) ?(show_removed=false) o_pp n_pp =
+ let open Pp in
+ let o_str = string_of_ppcmds o_pp in
+ let n_str = string_of_ppcmds n_pp in
+ let diffs = diff_str ~tokenize_string o_str n_str in
+ let (_, has_removed) = has_changes diffs in
+ let added = add_diff_tags `Added n_pp diffs in
+ if show_removed && has_removed then
+ let removed = add_diff_tags `Removed o_pp diffs in
+ (v 0 (removed ++ cut() ++ added))
+ else added;;
diff --git a/lib/pp_diff.mli b/lib/pp_diff.mli
new file mode 100644
index 0000000000..03468271d2
--- /dev/null
+++ b/lib/pp_diff.mli
@@ -0,0 +1,116 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+(**
+Computes the differences between 2 Pp's and adds additional tags to a Pp
+to highlight them. Strings are split into tokens using the Coq lexer,
+then the lists of tokens are diffed using the Myers algorithm. A fixup routine,
+shorten_diff_span, shortens the span of the diff result in some cases.
+
+Highlights use 4 tags to specify the color and underline/strikeout. These are
+"diffs.added", "diffs.removed", "diffs.added.bg" and "diffs.removed.bg". The
+first two are for added or removed text; the last two are for unmodified parts
+of a modified item. Diffs that span multiple strings in the Pp are tagged with
+"start.diff.*" and "end.diff.*", but only on the first and last strings of the span.
+
+If the inputs are not acceptable to the lexer, break the strings into
+lists of tokens and call diff_strs, then add_diff_tags with a Pp.t that matches
+the input lists of strings. Tokens that the lexer doesn't return exactly as they
+appeared in the input will raise an exception in add_diff_tags (e.g. comments
+and quoted strings). Fixing that requires tweaking the lexer.
+
+Limitations/Possible enhancements:
+
+- Make diff_pp immune to unlexable strings by adding a flag to the lexer.
+*)
+
+(** Compute the diff between two Pp.t structures and return
+versions of each with diffs highlighted as (old, new) *)
+val diff_pp : ?tokenize_string:(string -> string list) -> Pp.t -> Pp.t -> Pp.t * Pp.t
+
+(** Compute the diff between two Pp.t structures and return
+a highlighted Pp.t. If [show_removed] is true, show separate lines for
+removals and additions, otherwise only show additions *)
+val diff_pp_combined : ?tokenize_string:(string -> string list) -> ?show_removed:bool -> Pp.t -> Pp.t -> Pp.t
+
+(** Raised if the diff fails *)
+exception Diff_Failure of string
+
+module StringDiff :
+sig
+ type elem = String.t
+ type t = elem array
+end
+
+type diff_type =
+ [ `Removed
+ | `Added
+ | `Common
+ ]
+
+type diff_list = StringDiff.elem Diff2.edit list
+
+(** Compute the difference between 2 strings in terms of tokens, using the
+lexer to identify tokens.
+
+If the strings are not lexable, this routine will raise Diff_Failure.
+(I expect to modify the lexer soon so this won't happen.)
+
+Therefore you should catch any exceptions. The workaround for now is for the
+caller to tokenize the strings itself and then call diff_strs.
+*)
+val diff_str : ?tokenize_string:(string -> string list) -> string -> string -> StringDiff.elem Diff2.edit list
+
+(** Compute the differences between 2 lists of strings, treating the strings
+in the lists as indivisible units.
+*)
+val diff_strs : StringDiff.t -> StringDiff.t -> StringDiff.elem Diff2.edit list
+
+(** Generate a new Pp that adds tags marking diffs to a Pp structure:
+which: either `Added or `Removed, indicates which type of diffs to add
+pp: the original structure. For `Added, must be the new pp passed to diff_pp
+ For `Removed, must be the old pp passed to diff_pp. Passing the wrong one
+ will likely raise Diff_Failure.
+diffs: the diff list returned by diff_pp
+
+Diffs of single strings in the Pp are tagged with "diff.added" or "diff.removed".
+Diffs that span multiple strings in the Pp are tagged with "start.diff.*" or
+"end.diff.*", but only on the first and last strings of the span.
+
+Ppcmd_strings will be split into multiple Ppcmd_strings if a diff starts or ends
+in the middle of the string. Whitespace just before or just after a diff will
+not be part of the highlight.
+
+Prexisting tags in pp may contain only a single Ppcmd_string. Those tags will be
+placed inside the diff tags to ensure proper nesting of tags within spans of
+"start.diff.*" ... "end.diff.*".
+
+Under some "impossible" conditions, this routine may raise Diff_Failure.
+If you want to make your call especially bulletproof, catch this
+exception, print a user-visible message, then recall this routine with
+the first argument set to None, which will skip the diff.
+*)
+val add_diff_tags : diff_type -> Pp.t -> StringDiff.elem Diff2.edit list -> Pp.t
+
+(** Returns a boolean pair (added, removed) for [diffs] where a true value
+indicates that something was added/removed in the diffs.
+*)
+val has_changes : diff_list -> bool * bool
+
+val get_dinfo : StringDiff.elem Diff2.edit -> diff_type * string
+
+(** Returns a modified [pp] with the background highlighted with
+"start.<diff_tag>.bg" and "end.<diff_tag>.bg" tags at the beginning
+and end of the returned Pp.t
+*)
+val wrap_in_bg : string -> Pp.t -> Pp.t
+
+(** Displays the diffs to a printable format for debugging *)
+val string_of_diffs : diff_list -> string
diff --git a/lib/system.ml b/lib/system.ml
index f109c71925..eef65a4e3d 100644
--- a/lib/system.ml
+++ b/lib/system.ml
@@ -302,7 +302,7 @@ let with_time ~batch f x =
raise e
let get_toplevel_path top =
- let dir = Filename.dirname Sys.argv.(0) in
+ let dir = Filename.dirname Sys.executable_name in
let exe = if Sys.(os_type = "Win32" || os_type = "Cygwin") then ".exe" else "" in
let eff = if Dynlink.is_native then ".opt" else ".byte" in
dir ^ Filename.dir_sep ^ top ^ eff ^ exe
diff --git a/lib/util.ml b/lib/util.ml
index 7d7d380b26..38d73d3453 100644
--- a/lib/util.ml
+++ b/lib/util.ml
@@ -38,8 +38,8 @@ let is_blank = function
module Empty =
struct
- type t
- let abort (x : t) = assert false
+ type t = { abort : 'a. 'a }
+ let abort (x : t) = x.abort
end
(* Strings *)
diff --git a/library/global.ml b/library/global.ml
index dcb20a280e..e833f71142 100644
--- a/library/global.ml
+++ b/library/global.ml
@@ -90,6 +90,7 @@ let push_context b c = globalize0 (Safe_typing.push_context b c)
let set_engagement c = globalize0 (Safe_typing.set_engagement c)
let set_typing_flags c = globalize0 (Safe_typing.set_typing_flags c)
+let typing_flags () = Environ.typing_flags (env ())
let export_private_constants ~in_section cd = globalize (Safe_typing.export_private_constants ~in_section cd)
let add_constant dir id d = globalize (Safe_typing.add_constant dir (i2l id) d)
let add_mind dir id mie = globalize (Safe_typing.add_mind dir (i2l id) mie)
@@ -278,3 +279,9 @@ let register_inline c = globalize0 (Safe_typing.register_inline c)
let set_strategy k l =
GlobalSafeEnv.set_safe_env (Safe_typing.set_strategy (safe_env ()) k l)
+let set_reduction_sharing b =
+ let env = safe_env () in
+ let flags = Environ.typing_flags (Safe_typing.env_of_safe_env env) in
+ let flags = { flags with Declarations.share_reduction = b } in
+ let env = Safe_typing.set_typing_flags flags env in
+ GlobalSafeEnv.set_safe_env env
diff --git a/library/global.mli b/library/global.mli
index 57e173cb93..2819c187ed 100644
--- a/library/global.mli
+++ b/library/global.mli
@@ -23,13 +23,14 @@ val env_is_initial : unit -> bool
val universes : unit -> UGraph.t
val named_context_val : unit -> Environ.named_context_val
-val named_context : unit -> Context.Named.t
+val named_context : unit -> Constr.named_context
(** {6 Enriching the global environment } *)
(** Changing the (im)predicativity of the system *)
val set_engagement : Declarations.engagement -> unit
val set_typing_flags : Declarations.typing_flags -> unit
+val typing_flags : unit -> Declarations.typing_flags
(** Variables, Local definitions, constants, inductive types *)
@@ -79,7 +80,7 @@ val add_module_parameter :
(** {6 Queries in the global environment } *)
-val lookup_named : variable -> Context.Named.Declaration.t
+val lookup_named : variable -> Constr.named_declaration
val lookup_constant : Constant.t -> Declarations.constant_body
val lookup_inductive : inductive ->
Declarations.mutual_inductive_body * Declarations.one_inductive_body
@@ -155,6 +156,8 @@ val register_inline : Constant.t -> unit
val set_strategy : Constant.t Names.tableKey -> Conv_oracle.level -> unit
+val set_reduction_sharing : bool -> unit
+
(* Modifies the global state, registering new universes *)
val current_modpath : unit -> ModPath.t
diff --git a/library/goptions.ml b/library/goptions.ml
index f14ad333e9..eafcb8fea6 100644
--- a/library/goptions.ml
+++ b/library/goptions.ml
@@ -318,26 +318,35 @@ let set_option_value ?(locality = OptDefault) check_and_cast key v =
| Some (name, depr, (read,write,append)) ->
write locality (check_and_cast v (read ()))
-let bad_type_error () = user_err Pp.(str "Bad type of value for this option.")
+let show_value_type = function
+ | BoolValue _ -> "bool"
+ | IntValue _ -> "int"
+ | StringValue _ -> "string"
+ | StringOptValue _ -> "string"
+
+let bad_type_error opt_value actual_type =
+ user_err Pp.(str "Bad type of value for this option:" ++ spc() ++
+ str "expected " ++ str (show_value_type opt_value) ++
+ str ", got " ++ str actual_type ++ str ".")
let check_int_value v = function
| IntValue _ -> IntValue v
- | _ -> bad_type_error ()
+ | optv -> bad_type_error optv "int"
let check_bool_value v = function
| BoolValue _ -> BoolValue v
- | _ -> bad_type_error ()
+ | optv -> bad_type_error optv "bool"
let check_string_value v = function
| StringValue _ -> StringValue v
| StringOptValue _ -> StringOptValue (Some v)
- | _ -> bad_type_error ()
+ | optv -> bad_type_error optv "string"
let check_unset_value v = function
| BoolValue _ -> BoolValue false
| IntValue _ -> IntValue None
| StringOptValue _ -> StringOptValue None
- | _ -> bad_type_error ()
+ | optv -> bad_type_error optv "nothing"
(* Nota: For compatibility reasons, some errors are treated as
warning. This allows a script to refer to an option that doesn't
diff --git a/library/lib.ml b/library/lib.ml
index 128b27e757..8ebe44890c 100644
--- a/library/lib.ml
+++ b/library/lib.ml
@@ -26,13 +26,11 @@ type node =
| Leaf of obj
| CompilingLibrary of object_prefix
| OpenedModule of is_type * export * object_prefix * Summary.frozen
- | ClosedModule of library_segment
| OpenedSection of object_prefix * Summary.frozen
- | ClosedSection of library_segment
-and library_entry = object_name * node
+type library_entry = object_name * node
-and library_segment = library_entry list
+type library_segment = library_entry list
type lib_objects = (Names.Id.t * obj) list
@@ -73,10 +71,6 @@ let classify_segment seg =
clean ((id,o')::substl, keepl, anticipl) stk
| Anticipate o' ->
clean (substl, keepl, o'::anticipl) stk)
- | (_,ClosedSection _) :: stk -> clean acc stk
- (* LEM; TODO: Understand what this does and see if what I do is the
- correct thing for ClosedMod(ule|type) *)
- | (_,ClosedModule _) :: stk -> clean acc stk
| (_,OpenedSection _) :: _ -> user_err Pp.(str "there are still opened sections")
| (_,OpenedModule (ty,_,_,_)) :: _ ->
user_err ~hdr:"Lib.classify_segment"
@@ -307,7 +301,6 @@ let end_mod is_type =
in
let (after,mark,before) = split_lib_at_opening oname in
lib_state := { !lib_state with lib_stk = before };
- add_entry oname (ClosedModule (List.rev (mark::after)));
let prefix = !lib_state.path_prefix in
recalc_path_prefix ();
(oname, prefix, fs, after)
@@ -405,7 +398,7 @@ let find_opening_node id =
- the list of substitution to do at section closing
*)
-type variable_info = Context.Named.Declaration.t * Decl_kinds.binding_kind
+type variable_info = Constr.named_declaration * Decl_kinds.binding_kind
type variable_context = variable_info list
type abstr_info = {
@@ -555,7 +548,6 @@ let discharge_item ((sp,_ as oname),e) =
match e with
| Leaf lobj ->
Option.map (fun o -> (basename sp,o)) (discharge_object (oname,lobj))
- | ClosedSection _ | ClosedModule _ -> None
| OpenedSection _ | OpenedModule _ | CompilingLibrary _ ->
anomaly (Pp.str "discharge_item.")
@@ -570,7 +562,6 @@ let close_section () =
let (secdecls,mark,before) = split_lib_at_opening oname in
lib_state := { !lib_state with lib_stk = before };
pop_path_prefix ();
- add_entry oname (ClosedSection (List.rev (mark::secdecls)));
let newdecls = List.map discharge_item secdecls in
Summary.unfreeze_summaries fs;
List.iter (Option.iter (fun (id,o) -> add_discharged_leaf id o)) newdecls
@@ -589,10 +580,8 @@ let freeze ~marshallable =
| n, (CompilingLibrary _ as x) -> Some (n,x)
| n, OpenedModule (it,e,op,_) ->
Some(n,OpenedModule(it,e,op,Summary.empty_frozen))
- | n, ClosedModule _ -> Some (n,ClosedModule [])
| n, OpenedSection (op, _) ->
- Some(n,OpenedSection(op,Summary.empty_frozen))
- | n, ClosedSection _ -> Some (n,ClosedSection []))
+ Some(n,OpenedSection(op,Summary.empty_frozen)))
!lib_state.lib_stk in
{ !lib_state with lib_stk }
| _ ->
@@ -656,6 +645,14 @@ let discharge_kn kn =
let discharge_con cst =
if con_defined_in_sec cst then Globnames.pop_con cst else cst
+let discharge_proj_repr =
+ Projection.Repr.map_npars (fun mind npars ->
+ if not (defined_in_sec mind) then mind, npars
+ else
+ let modlist = replacement_context () in
+ let _, newpars = Mindmap.find mind (snd modlist) in
+ Globnames.pop_kn mind, npars + Array.length newpars)
+
let discharge_inductive (kn,i) =
(discharge_kn kn,i)
diff --git a/library/lib.mli b/library/lib.mli
index 1d77212e9d..9933b762ba 100644
--- a/library/lib.mli
+++ b/library/lib.mli
@@ -9,6 +9,7 @@
(************************************************************************)
open Names
+
(** Lib: record of operations, backtrack, low-level sections *)
(** This module provides a general mechanism to keep a trace of all operations
@@ -22,11 +23,9 @@ type node =
| Leaf of Libobject.obj
| CompilingLibrary of Libnames.object_prefix
| OpenedModule of is_type * export * Libnames.object_prefix * Summary.frozen
- | ClosedModule of library_segment
| OpenedSection of Libnames.object_prefix * Summary.frozen
- | ClosedSection of library_segment
-and library_segment = (Libnames.object_name * node) list
+type library_segment = (Libnames.object_name * node) list
type lib_objects = (Id.t * Libobject.obj) list
@@ -153,7 +152,7 @@ val unfreeze : frozen -> unit
val init : unit -> unit
(** {6 Section management for discharge } *)
-type variable_info = Context.Named.Declaration.t * Decl_kinds.binding_kind
+type variable_info = Constr.named_declaration * Decl_kinds.binding_kind
type variable_context = variable_info list
type abstr_info = private {
abstr_ctx : variable_context;
@@ -165,7 +164,7 @@ type abstr_info = private {
}
val instance_from_variable_context : variable_context -> Id.t array
-val named_of_variable_context : variable_context -> Context.Named.t
+val named_of_variable_context : variable_context -> Constr.named_context
val section_segment_of_constant : Constant.t -> abstr_info
val section_segment_of_mutual_inductive: MutInd.t -> abstr_info
@@ -179,15 +178,16 @@ val is_in_section : GlobRef.t -> bool
val add_section_variable : Id.t -> Decl_kinds.binding_kind -> Decl_kinds.polymorphic -> Univ.ContextSet.t -> unit
val add_section_context : Univ.ContextSet.t -> unit
val add_section_constant : Decl_kinds.polymorphic ->
- Constant.t -> Context.Named.t -> unit
+ Constant.t -> Constr.named_context -> unit
val add_section_kn : Decl_kinds.polymorphic ->
- MutInd.t -> Context.Named.t -> unit
+ MutInd.t -> Constr.named_context -> unit
val replacement_context : unit -> Opaqueproof.work_list
(** {6 Discharge: decrease the section level if in the current section } *)
val discharge_kn : MutInd.t -> MutInd.t
val discharge_con : Constant.t -> Constant.t
+val discharge_proj_repr : Projection.Repr.t -> Projection.Repr.t
val discharge_global : GlobRef.t -> GlobRef.t
val discharge_inductive : inductive -> inductive
val discharge_abstract_universe_context :
diff --git a/library/libobject.ml b/library/libobject.ml
index c5cd015256..79a3fed1b9 100644
--- a/library/libobject.ml
+++ b/library/libobject.ml
@@ -98,7 +98,7 @@ let declare_object_full odecl = declare_object_full odecl
(* this function describes how the cache, load, open, and export functions
are triggered. *)
-let apply_dyn_fun deflt f lobj =
+let apply_dyn_fun f lobj =
let tag = object_tag lobj in
let dodecl =
try Hashtbl.find cache_tab tag
@@ -107,24 +107,24 @@ let apply_dyn_fun deflt f lobj =
f dodecl
let cache_object ((_,lobj) as node) =
- apply_dyn_fun () (fun d -> d.dyn_cache_function node) lobj
+ apply_dyn_fun (fun d -> d.dyn_cache_function node) lobj
let load_object i ((_,lobj) as node) =
- apply_dyn_fun () (fun d -> d.dyn_load_function i node) lobj
+ apply_dyn_fun (fun d -> d.dyn_load_function i node) lobj
let open_object i ((_,lobj) as node) =
- apply_dyn_fun () (fun d -> d.dyn_open_function i node) lobj
+ apply_dyn_fun (fun d -> d.dyn_open_function i node) lobj
let subst_object ((_,lobj) as node) =
- apply_dyn_fun lobj (fun d -> d.dyn_subst_function node) lobj
+ apply_dyn_fun (fun d -> d.dyn_subst_function node) lobj
let classify_object lobj =
- apply_dyn_fun Dispose (fun d -> d.dyn_classify_function lobj) lobj
+ apply_dyn_fun (fun d -> d.dyn_classify_function lobj) lobj
let discharge_object ((_,lobj) as node) =
- apply_dyn_fun None (fun d -> d.dyn_discharge_function node) lobj
+ apply_dyn_fun (fun d -> d.dyn_discharge_function node) lobj
let rebuild_object lobj =
- apply_dyn_fun lobj (fun d -> d.dyn_rebuild_function lobj) lobj
+ apply_dyn_fun (fun d -> d.dyn_rebuild_function lobj) lobj
let dump = Dyn.dump
diff --git a/library/library.ml b/library/library.ml
index 400f3dcf13..0ff82d7cc4 100644
--- a/library/library.ml
+++ b/library/library.ml
@@ -167,7 +167,7 @@ let opened_libraries () = !libraries_imports_list
let register_loaded_library m =
let libname = m.libsum_name in
- let link m =
+ let link () =
let dirname = Filename.dirname (library_full_filename libname) in
let prefix = Nativecode.mod_uid_of_dirpath libname ^ "." in
let f = prefix ^ "cmo" in
@@ -176,7 +176,7 @@ let register_loaded_library m =
Nativelib.link_library ~prefix ~dirname ~basename:f
in
let rec aux = function
- | [] -> link m; [libname]
+ | [] -> link (); [libname]
| m'::_ as l when DirPath.equal m' libname -> l
| m'::l' -> m' :: aux l' in
libraries_loaded_list := aux !libraries_loaded_list;
@@ -288,16 +288,15 @@ let locate_absolute_library dir =
try
let name = Id.to_string base ^ ext in
let _, file = System.where_in_path ~warn:false loadpath name in
- [file]
- with Not_found -> [] in
- match find ".vo" @ find ".vio" with
- | [] -> raise LibNotFound
- | [file] -> file
- | [vo;vi] when Unix.((stat vo).st_mtime < (stat vi).st_mtime) ->
+ Some file
+ with Not_found -> None in
+ match find ".vo", find ".vio" with
+ | None, None -> raise LibNotFound
+ | Some file, None | None, Some file -> file
+ | Some vo, Some vi when Unix.((stat vo).st_mtime < (stat vi).st_mtime) ->
warn_several_object_files (vi, vo);
vi
- | [vo;vi] -> vo
- | _ -> assert false
+ | Some vo, Some _ -> vo
let locate_qualified_library ?root ?(warn = true) qid =
(* Search library in loadpath *)
@@ -309,18 +308,17 @@ let locate_qualified_library ?root ?(warn = true) qid =
let name = Id.to_string base ^ ext in
let lpath, file =
System.where_in_path ~warn (List.map fst loadpath) name in
- [lpath, file]
- with Not_found -> [] in
+ Some (lpath, file)
+ with Not_found -> None in
let lpath, file =
- match find ".vo" @ find ".vio" with
- | [] -> raise LibNotFound
- | [lpath, file] -> lpath, file
- | [lpath_vo, vo; lpath_vi, vi]
+ match find ".vo", find ".vio" with
+ | None, None -> raise LibNotFound
+ | Some res, None | None, Some res -> res
+ | Some (_, vo), Some (_, vi as resvi)
when Unix.((stat vo).st_mtime < (stat vi).st_mtime) ->
warn_several_object_files (vi, vo);
- lpath_vi, vi
- | [lpath_vo, vo; _ ] -> lpath_vo, vo
- | _ -> assert false
+ resvi
+ | Some resvo, Some _ -> resvo
in
let dir = add_dirpath_suffix (String.List.assoc lpath loadpath) base in
(* Look if loaded *)
diff --git a/library/library.mllib b/library/library.mllib
index 2ac4266fc0..9cacaba4a7 100644
--- a/library/library.mllib
+++ b/library/library.mllib
@@ -14,6 +14,5 @@ Kindops
Dischargedhypsmap
Goptions
Decls
-Heads
Keys
Coqlib
diff --git a/man/gallina.1 b/man/gallina.1
deleted file mode 100644
index f8879c457b..0000000000
--- a/man/gallina.1
+++ /dev/null
@@ -1,74 +0,0 @@
-.TH COQ 1 "29 March 1995" "Coq tools"
-
-.SH NAME
-gallina \- extracts specification from Coq vernacular files
-
-.SH SYNOPSIS
-.B gallina
-[
-.BI \-
-]
-[
-.BI \-stdout
-]
-[
-.BI \-nocomments
-]
-.I file ...
-
-.SH DESCRIPTION
-
-.B gallina
-takes Coq files as arguments and builds the corresponding
-specification files.
-The Coq file
-.IR foo.v \&
-gives bearth to the specification file
-.IR foo.g. \&
-The suffix '.g' stands for Gallina.
-
-For that purpose, gallina removes all commands that follow a
-"Theorem", "Lemma", "Fact", "Remark" or "Goal" statement until it
-reaches a command "Abort.", "Qed.", "Defined." or "Proof
-<...>.". It also removes every "Hint", "Syntax",
-"Immediate" or "Transparent" command.
-
-Files without the .v suffix are ignored.
-
-
-.SH OPTIONS
-
-.TP
-.BI \-stdout
-Prints the result on standard output.
-.TP
-.BI \-
-Coq source is taken on standard input. The result is printed on
-standard output.
-.TP
-.BI \-nocomments
-Comments are removed in the *.g file.
-
-.SH NOTES
-
-Nested comments are correctly handled. In particular, every command
-"Qed." or "Abort." in a comment is not taken into account.
-
-
-.SH BUGS
-
-Please report any bug to
-.B coq@pauillac.inria.fr
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/parsing/extend.ml b/parsing/extend.ml
index 6805a96edc..6fe2956643 100644
--- a/parsing/extend.ml
+++ b/parsing/extend.ml
@@ -34,14 +34,12 @@ type production_level =
(** User-level types used to tell how to parse or interpret of the non-terminal *)
type 'a constr_entry_key_gen =
- | ETName
- | ETReference
+ | ETIdent
+ | ETGlobal
| ETBigint
| ETBinder of bool (* open list of binders if true, closed list of binders otherwise *)
- | ETConstr of 'a
- | ETConstrAsBinder of Notation_term.constr_as_binder_kind * 'a
+ | ETConstr of Constrexpr.notation_entry * Notation_term.constr_as_binder_kind option * 'a
| ETPattern of bool * int option (* true = strict pattern, i.e. not a single variable *)
- | ETOther of string * string
(** Entries level (left-hand side of grammar rules) *)
@@ -63,9 +61,8 @@ type constr_prod_entry_key =
| ETProdName (* Parsed as a name (ident or _) *)
| ETProdReference (* Parsed as a global reference *)
| ETProdBigint (* Parsed as an (unbounded) integer *)
- | ETProdConstr of (production_level * production_position) (* Parsed as constr or pattern *)
+ | ETProdConstr of Constrexpr.notation_entry * (production_level * production_position) (* Parsed as constr or pattern, or a subentry of those *)
| ETProdPattern of int (* Parsed as pattern as a binder (as subpart of a constr) *)
- | ETProdOther of string * string (* Intended for embedding custom entries in constr or pattern *)
| ETProdConstrList of (production_level * production_position) * Tok.t list (* Parsed as non-empty list of constr *)
| ETProdBinderList of binder_entry_kind (* Parsed as non-empty list of local binders *)
@@ -101,7 +98,7 @@ type ('self, 'a) symbol =
| Aself : ('self, 'self) symbol
| Anext : ('self, 'self) symbol
| Aentry : 'a entry -> ('self, 'a) symbol
-| Aentryl : 'a entry * int -> ('self, 'a) symbol
+| Aentryl : 'a entry * string -> ('self, 'a) symbol
| Arules : 'a rules list -> ('self, 'a) symbol
and ('self, _, 'r) rule =
diff --git a/parsing/g_constr.ml4 b/parsing/g_constr.mlg
index 1fa26b4556..7cb5af787b 100644
--- a/parsing/g_constr.ml4
+++ b/parsing/g_constr.mlg
@@ -8,6 +8,8 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
+{
+
open Names
open Constr
open Libnames
@@ -126,396 +128,399 @@ let name_colon =
let aliasvar = function { CAst.v = CPatAlias (_, na) } -> Some na | _ -> None
-GEXTEND Gram
+}
+
+GRAMMAR EXTEND Gram
GLOBAL: binder_constr lconstr constr operconstr universe_level sort sort_family
global constr_pattern lconstr_pattern Constr.ident
closed_binder open_binders binder binders binders_fixannot
record_declaration typeclass_constraint pattern appl_arg;
Constr.ident:
- [ [ id = Prim.ident -> id ] ]
+ [ [ id = Prim.ident -> { id } ] ]
;
Prim.name:
- [ [ "_" -> CAst.make ~loc:!@loc Anonymous ] ]
+ [ [ "_" -> { CAst.make ~loc Anonymous } ] ]
;
global:
- [ [ r = Prim.reference -> r ] ]
+ [ [ r = Prim.reference -> { r } ] ]
;
constr_pattern:
- [ [ c = constr -> c ] ]
+ [ [ c = constr -> { c } ] ]
;
lconstr_pattern:
- [ [ c = lconstr -> c ] ]
+ [ [ c = lconstr -> { c } ] ]
;
sort:
- [ [ "Set" -> GSet
- | "Prop" -> GProp
- | "Type" -> GType []
- | "Type"; "@{"; u = universe; "}" -> GType u
+ [ [ "Set" -> { GSet }
+ | "Prop" -> { GProp }
+ | "Type" -> { GType [] }
+ | "Type"; "@{"; u = universe; "}" -> { GType u }
] ]
;
sort_family:
- [ [ "Set" -> Sorts.InSet
- | "Prop" -> Sorts.InProp
- | "Type" -> Sorts.InType
+ [ [ "Set" -> { Sorts.InSet }
+ | "Prop" -> { Sorts.InProp }
+ | "Type" -> { Sorts.InType }
] ]
;
universe_expr:
- [ [ id = global; "+"; n = natural -> Some (id,n)
- | id = global -> Some (id,0)
- | "_" -> None
+ [ [ id = global; "+"; n = natural -> { Some (id,n) }
+ | id = global -> { Some (id,0) }
+ | "_" -> { None }
] ]
;
universe:
- [ [ IDENT "max"; "("; ids = LIST1 universe_expr SEP ","; ")" -> ids
- | u = universe_expr -> [u]
+ [ [ IDENT "max"; "("; ids = LIST1 universe_expr SEP ","; ")" -> { ids }
+ | u = universe_expr -> { [u] }
] ]
;
lconstr:
- [ [ c = operconstr LEVEL "200" -> c ] ]
+ [ [ c = operconstr LEVEL "200" -> { c } ] ]
;
constr:
- [ [ c = operconstr LEVEL "8" -> c
- | "@"; f=global; i = instance -> CAst.make ~loc:!@loc @@ CAppExpl((None,f,i),[]) ] ]
+ [ [ c = operconstr LEVEL "8" -> { c }
+ | "@"; f=global; i = instance -> { CAst.make ~loc @@ CAppExpl((None,f,i),[]) } ] ]
;
operconstr:
[ "200" RIGHTA
- [ c = binder_constr -> c ]
+ [ c = binder_constr -> { c } ]
| "100" RIGHTA
[ c1 = operconstr; "<:"; c2 = binder_constr ->
- CAst.make ~loc:(!@loc) @@ CCast(c1, CastVM c2)
+ { CAst.make ~loc @@ CCast(c1, CastVM c2) }
| c1 = operconstr; "<:"; c2 = SELF ->
- CAst.make ~loc:(!@loc) @@ CCast(c1, CastVM c2)
+ { CAst.make ~loc @@ CCast(c1, CastVM c2) }
| c1 = operconstr; "<<:"; c2 = binder_constr ->
- CAst.make ~loc:(!@loc) @@ CCast(c1, CastNative c2)
+ { CAst.make ~loc @@ CCast(c1, CastNative c2) }
| c1 = operconstr; "<<:"; c2 = SELF ->
- CAst.make ~loc:(!@loc) @@ CCast(c1, CastNative c2)
+ { CAst.make ~loc @@ CCast(c1, CastNative c2) }
| c1 = operconstr; ":";c2 = binder_constr ->
- CAst.make ~loc:(!@loc) @@ CCast(c1, CastConv c2)
+ { CAst.make ~loc @@ CCast(c1, CastConv c2) }
| c1 = operconstr; ":"; c2 = SELF ->
- CAst.make ~loc:(!@loc) @@ CCast(c1, CastConv c2)
+ { CAst.make ~loc @@ CCast(c1, CastConv c2) }
| c1 = operconstr; ":>" ->
- CAst.make ~loc:(!@loc) @@ CCast(c1, CastCoerce) ]
+ { CAst.make ~loc @@ CCast(c1, CastCoerce) } ]
| "99" RIGHTA [ ]
| "90" RIGHTA [ ]
| "10" LEFTA
- [ f=operconstr; args=LIST1 appl_arg -> CAst.make ~loc:(!@loc) @@ CApp((None,f),args)
- | "@"; f=global; i = instance; args=LIST0 NEXT -> CAst.make ~loc:!@loc @@ CAppExpl((None,f,i),args)
+ [ f=operconstr; args=LIST1 appl_arg -> { CAst.make ~loc @@ CApp((None,f),args) }
+ | "@"; f=global; i = instance; args=LIST0 NEXT -> { CAst.make ~loc @@ CAppExpl((None,f,i),args) }
| "@"; lid = pattern_identref; args=LIST1 identref ->
- let { CAst.loc = locid; v = id } = lid in
+ { let { CAst.loc = locid; v = id } = lid in
let args = List.map (fun x -> CAst.make @@ CRef (qualid_of_ident ?loc:x.CAst.loc x.CAst.v, None), None) args in
- CAst.make ~loc:(!@loc) @@ CApp((None, CAst.make ?loc:locid @@ CPatVar id),args) ]
+ CAst.make ~loc @@ CApp((None, CAst.make ?loc:locid @@ CPatVar id),args) } ]
| "9"
[ ".."; c = operconstr LEVEL "0"; ".." ->
- CAst.make ~loc:!@loc @@ CAppExpl ((None, (qualid_of_ident ~loc:!@loc ldots_var), None),[c]) ]
+ { CAst.make ~loc @@ CAppExpl ((None, (qualid_of_ident ~loc ldots_var), None),[c]) } ]
| "8" [ ]
| "1" LEFTA
[ c=operconstr; ".("; f=global; args=LIST0 appl_arg; ")" ->
- CAst.make ~loc:(!@loc) @@ CApp((Some (List.length args+1), CAst.make @@ CRef (f,None)),args@[c,None])
+ { CAst.make ~loc @@ CApp((Some (List.length args+1), CAst.make @@ CRef (f,None)),args@[c,None]) }
| c=operconstr; ".("; "@"; f=global;
args=LIST0 (operconstr LEVEL "9"); ")" ->
- CAst.make ~loc:(!@loc) @@ CAppExpl((Some (List.length args+1),f,None),args@[c])
- | c=operconstr; "%"; key=IDENT -> CAst.make ~loc:(!@loc) @@ CDelimiters (key,c) ]
+ { CAst.make ~loc @@ CAppExpl((Some (List.length args+1),f,None),args@[c]) }
+ | c=operconstr; "%"; key=IDENT -> { CAst.make ~loc @@ CDelimiters (key,c) } ]
| "0"
- [ c=atomic_constr -> c
- | c=match_constr -> c
+ [ c=atomic_constr -> { c }
+ | c=match_constr -> { c }
| "("; c = operconstr LEVEL "200"; ")" ->
- (match c.CAst.v with
+ { (match c.CAst.v with
| CPrim (Numeral (n,true)) ->
- CAst.make ~loc:(!@loc) @@ CNotation("( _ )",([c],[],[],[]))
- | _ -> c)
- | "{|"; c = record_declaration; "|}" -> c
+ CAst.make ~loc @@ CNotation((InConstrEntrySomeLevel,"( _ )"),([c],[],[],[]))
+ | _ -> c) }
+ | "{|"; c = record_declaration; "|}" -> { c }
| "{"; c = binder_constr ; "}" ->
- CAst.make ~loc:(!@loc) @@ CNotation(("{ _ }"),([c],[],[],[]))
+ { CAst.make ~loc @@ CNotation((InConstrEntrySomeLevel,"{ _ }"),([c],[],[],[])) }
| "`{"; c = operconstr LEVEL "200"; "}" ->
- CAst.make ~loc:(!@loc) @@ CGeneralization (Implicit, None, c)
+ { CAst.make ~loc @@ CGeneralization (Implicit, None, c) }
| "`("; c = operconstr LEVEL "200"; ")" ->
- CAst.make ~loc:(!@loc) @@ CGeneralization (Explicit, None, c)
+ { CAst.make ~loc @@ CGeneralization (Explicit, None, c) }
] ]
;
record_declaration:
- [ [ fs = record_fields -> CAst.make ~loc:(!@loc) @@ CRecord fs ] ]
+ [ [ fs = record_fields -> { CAst.make ~loc @@ CRecord fs } ] ]
;
record_fields:
- [ [ f = record_field_declaration; ";"; fs = record_fields -> f :: fs
- | f = record_field_declaration -> [f]
- | -> []
+ [ [ f = record_field_declaration; ";"; fs = record_fields -> { f :: fs }
+ | f = record_field_declaration -> { [f] }
+ | -> { [] }
] ]
;
record_field_declaration:
[ [ id = global; bl = binders; ":="; c = lconstr ->
- (id, mkCLambdaN ~loc:!@loc bl c) ] ]
+ { (id, if bl = [] then c else mkCLambdaN ~loc bl c) } ] ]
;
binder_constr:
[ [ "forall"; bl = open_binders; ","; c = operconstr LEVEL "200" ->
- mkCProdN ~loc:!@loc bl c
+ { mkCProdN ~loc bl c }
| "fun"; bl = open_binders; "=>"; c = operconstr LEVEL "200" ->
- mkCLambdaN ~loc:!@loc bl c
+ { mkCLambdaN ~loc bl c }
| "let"; id=name; bl = binders; ty = type_cstr; ":=";
c1 = operconstr LEVEL "200"; "in"; c2 = operconstr LEVEL "200" ->
- let ty,c1 = match ty, c1 with
+ { let ty,c1 = match ty, c1 with
| (_,None), { CAst.v = CCast(c, CastConv t) } -> (Loc.tag ?loc:(constr_loc t) @@ Some t), c (* Tolerance, see G_vernac.def_body *)
| _, _ -> ty, c1 in
- CAst.make ~loc:!@loc @@ CLetIn(id,mkCLambdaN ?loc:(constr_loc c1) bl c1,
- Option.map (mkCProdN ?loc:(fst ty) bl) (snd ty), c2)
+ CAst.make ~loc @@ CLetIn(id,mkCLambdaN ?loc:(constr_loc c1) bl c1,
+ Option.map (mkCProdN ?loc:(fst ty) bl) (snd ty), c2) }
| "let"; fx = single_fix; "in"; c = operconstr LEVEL "200" ->
- let fixp = mk_single_fix fx in
+ { let fixp = mk_single_fix fx in
let { CAst.loc = li; v = id } = match fixp.CAst.v with
CFix(id,_) -> id
| CCoFix(id,_) -> id
| _ -> assert false in
- CAst.make ~loc:!@loc @@ CLetIn( CAst.make ?loc:li @@ Name id,fixp,None,c)
- | "let"; lb = ["("; l=LIST0 name SEP ","; ")" -> l | "()" -> []];
+ CAst.make ~loc @@ CLetIn( CAst.make ?loc:li @@ Name id,fixp,None,c) }
+ | "let"; lb = ["("; l=LIST0 name SEP ","; ")" -> { l } | "()" -> { [] } ];
po = return_type;
":="; c1 = operconstr LEVEL "200"; "in";
c2 = operconstr LEVEL "200" ->
- CAst.make ~loc:!@loc @@ CLetTuple (lb,po,c1,c2)
+ { CAst.make ~loc @@ CLetTuple (lb,po,c1,c2) }
| "let"; "'"; p=pattern; ":="; c1 = operconstr LEVEL "200";
"in"; c2 = operconstr LEVEL "200" ->
- CAst.make ~loc:!@loc @@
- CCases (LetPatternStyle, None, [c1, None, None], [CAst.make ~loc:!@loc ([[p]], c2)])
+ { CAst.make ~loc @@
+ CCases (LetPatternStyle, None, [c1, None, None], [CAst.make ~loc ([[p]], c2)]) }
| "let"; "'"; p=pattern; ":="; c1 = operconstr LEVEL "200";
rt = case_type; "in"; c2 = operconstr LEVEL "200" ->
- CAst.make ~loc:!@loc @@
- CCases (LetPatternStyle, Some rt, [c1, aliasvar p, None], [CAst.make ~loc:!@loc ([[p]], c2)])
+ { CAst.make ~loc @@
+ CCases (LetPatternStyle, Some rt, [c1, aliasvar p, None], [CAst.make ~loc ([[p]], c2)]) }
| "let"; "'"; p=pattern; "in"; t = pattern LEVEL "200";
":="; c1 = operconstr LEVEL "200"; rt = case_type;
"in"; c2 = operconstr LEVEL "200" ->
- CAst.make ~loc:!@loc @@
- CCases (LetPatternStyle, Some rt, [c1, aliasvar p, Some t], [CAst.make ~loc:!@loc ([[p]], c2)])
+ { CAst.make ~loc @@
+ CCases (LetPatternStyle, Some rt, [c1, aliasvar p, Some t], [CAst.make ~loc ([[p]], c2)]) }
| "if"; c=operconstr LEVEL "200"; po = return_type;
"then"; b1=operconstr LEVEL "200";
"else"; b2=operconstr LEVEL "200" ->
- CAst.make ~loc:(!@loc) @@ CIf (c, po, b1, b2)
- | c=fix_constr -> c ] ]
+ { CAst.make ~loc @@ CIf (c, po, b1, b2) }
+ | c=fix_constr -> { c } ] ]
;
appl_arg:
[ [ id = lpar_id_coloneq; c=lconstr; ")" ->
- (c,Some (CAst.make ~loc:!@loc @@ ExplByName id))
- | c=operconstr LEVEL "9" -> (c,None) ] ]
+ { (c,Some (CAst.make ~loc @@ ExplByName id)) }
+ | c=operconstr LEVEL "9" -> { (c,None) } ] ]
;
atomic_constr:
- [ [ g=global; i=instance -> CAst.make ~loc:!@loc @@ CRef (g,i)
- | s=sort -> CAst.make ~loc:!@loc @@ CSort s
- | n=INT -> CAst.make ~loc:!@loc @@ CPrim (Numeral (n,true))
- | s=string -> CAst.make ~loc:!@loc @@ CPrim (String s)
- | "_" -> CAst.make ~loc:!@loc @@ CHole (None, IntroAnonymous, None)
- | "?"; "["; id=ident; "]" -> CAst.make ~loc:!@loc @@ CHole (None, IntroIdentifier id, None)
- | "?"; "["; id=pattern_ident; "]" -> CAst.make ~loc:!@loc @@ CHole (None, IntroFresh id, None)
- | id=pattern_ident; inst = evar_instance -> CAst.make ~loc:!@loc @@ CEvar(id,inst) ] ]
+ [ [ g=global; i=instance -> { CAst.make ~loc @@ CRef (g,i) }
+ | s=sort -> { CAst.make ~loc @@ CSort s }
+ | n=INT -> { CAst.make ~loc @@ CPrim (Numeral (n,true)) }
+ | s=string -> { CAst.make ~loc @@ CPrim (String s) }
+ | "_" -> { CAst.make ~loc @@ CHole (None, IntroAnonymous, None) }
+ | "?"; "["; id=ident; "]" -> { CAst.make ~loc @@ CHole (None, IntroIdentifier id, None) }
+ | "?"; "["; id=pattern_ident; "]" -> { CAst.make ~loc @@ CHole (None, IntroFresh id, None) }
+ | id=pattern_ident; inst = evar_instance -> { CAst.make ~loc @@ CEvar(id,inst) } ] ]
;
inst:
- [ [ id = ident; ":="; c = lconstr -> (id,c) ] ]
+ [ [ id = ident; ":="; c = lconstr -> { (id,c) } ] ]
;
evar_instance:
- [ [ "@{"; l = LIST1 inst SEP ";"; "}" -> l
- | -> [] ] ]
+ [ [ "@{"; l = LIST1 inst SEP ";"; "}" -> { l }
+ | -> { [] } ] ]
;
instance:
- [ [ "@{"; l = LIST0 universe_level; "}" -> Some l
- | -> None ] ]
+ [ [ "@{"; l = LIST0 universe_level; "}" -> { Some l }
+ | -> { None } ] ]
;
universe_level:
- [ [ "Set" -> GSet
- | "Prop" -> GProp
- | "Type" -> GType UUnknown
- | "_" -> GType UAnonymous
- | id = global -> GType (UNamed id)
+ [ [ "Set" -> { GSet }
+ | "Prop" -> { GProp }
+ | "Type" -> { GType UUnknown }
+ | "_" -> { GType UAnonymous }
+ | id = global -> { GType (UNamed id) }
] ]
;
fix_constr:
- [ [ fx1=single_fix -> mk_single_fix fx1
- | (_,kw,dcl1)=single_fix; "with"; dcls=LIST1 fix_decl SEP "with";
+ [ [ fx1=single_fix -> { mk_single_fix fx1 }
+ | f=single_fix; "with"; dcls=LIST1 fix_decl SEP "with";
"for"; id=identref ->
- mk_fix(!@loc,kw,id,dcl1::dcls)
+ { let (_,kw,dcl1) = f in
+ mk_fix(loc,kw,id,dcl1::dcls) }
] ]
;
single_fix:
- [ [ kw=fix_kw; dcl=fix_decl -> (!@loc,kw,dcl) ] ]
+ [ [ kw=fix_kw; dcl=fix_decl -> { (loc,kw,dcl) } ] ]
;
fix_kw:
- [ [ "fix" -> true
- | "cofix" -> false ] ]
+ [ [ "fix" -> { true }
+ | "cofix" -> { false } ] ]
;
fix_decl:
[ [ id=identref; bl=binders_fixannot; ty=type_cstr; ":=";
c=operconstr LEVEL "200" ->
- (id,fst bl,snd bl,c,ty) ] ]
+ { (id,fst bl,snd bl,c,ty) } ] ]
;
match_constr:
[ [ "match"; ci=LIST1 case_item SEP ","; ty=OPT case_type; "with";
- br=branches; "end" -> CAst.make ~loc:!@loc @@ CCases(RegularStyle,ty,ci,br) ] ]
+ br=branches; "end" -> { CAst.make ~loc @@ CCases(RegularStyle,ty,ci,br) } ] ]
;
case_item:
[ [ c=operconstr LEVEL "100";
- ona = OPT ["as"; id=name -> id];
- ty = OPT ["in"; t=pattern -> t] ->
- (c,ona,ty) ] ]
+ ona = OPT ["as"; id=name -> { id } ];
+ ty = OPT ["in"; t=pattern -> { t } ] ->
+ { (c,ona,ty) } ] ]
;
case_type:
- [ [ "return"; ty = operconstr LEVEL "100" -> ty ] ]
+ [ [ "return"; ty = operconstr LEVEL "100" -> { ty } ] ]
;
return_type:
- [ [ a = OPT [ na = OPT["as"; na=name -> na];
- ty = case_type -> (na,ty) ] ->
- match a with
+ [ [ a = OPT [ na = OPT["as"; na=name -> { na } ];
+ ty = case_type -> { (na,ty) } ] ->
+ { match a with
| None -> None, None
- | Some (na,t) -> (na, Some t)
+ | Some (na,t) -> (na, Some t) }
] ]
;
branches:
- [ [ OPT"|"; br=LIST0 eqn SEP "|" -> br ] ]
+ [ [ OPT"|"; br=LIST0 eqn SEP "|" -> { br } ] ]
;
mult_pattern:
- [ [ pl = LIST1 pattern LEVEL "99" SEP "," -> pl ] ]
+ [ [ pl = LIST1 pattern LEVEL "99" SEP "," -> { pl } ] ]
;
eqn:
[ [ pll = LIST1 mult_pattern SEP "|";
- "=>"; rhs = lconstr -> (CAst.make ~loc:!@loc (pll,rhs)) ] ]
+ "=>"; rhs = lconstr -> { (CAst.make ~loc (pll,rhs)) } ] ]
;
record_pattern:
- [ [ id = global; ":="; pat = pattern -> (id, pat) ] ]
+ [ [ id = global; ":="; pat = pattern -> { (id, pat) } ] ]
;
record_patterns:
- [ [ p = record_pattern; ";"; ps = record_patterns -> p :: ps
- | p = record_pattern; ";" -> [p]
- | p = record_pattern-> [p]
- | -> []
+ [ [ p = record_pattern; ";"; ps = record_patterns -> { p :: ps }
+ | p = record_pattern; ";" -> { [p] }
+ | p = record_pattern-> { [p] }
+ | -> { [] }
] ]
;
pattern:
[ "200" RIGHTA [ ]
| "100" RIGHTA
- [ p = pattern; "|"; pl = LIST1 pattern SEP "|" -> CAst.make ~loc:!@loc @@ CPatOr (p::pl) ]
+ [ p = pattern; "|"; pl = LIST1 pattern SEP "|" -> { CAst.make ~loc @@ CPatOr (p::pl) } ]
| "99" RIGHTA [ ]
| "90" RIGHTA [ ]
| "10" LEFTA
[ p = pattern; "as"; na = name ->
- CAst.make ~loc:!@loc @@ CPatAlias (p, na)
- | p = pattern; lp = LIST1 NEXT -> mkAppPattern ~loc:!@loc p lp
+ { CAst.make ~loc @@ CPatAlias (p, na) }
+ | p = pattern; lp = LIST1 NEXT -> { mkAppPattern ~loc p lp }
| "@"; r = Prim.reference; lp = LIST0 NEXT ->
- CAst.make ~loc:!@loc @@ CPatCstr (r, Some lp, []) ]
+ { CAst.make ~loc @@ CPatCstr (r, Some lp, []) } ]
| "1" LEFTA
- [ c = pattern; "%"; key=IDENT -> CAst.make ~loc:!@loc @@ CPatDelimiters (key,c) ]
+ [ c = pattern; "%"; key=IDENT -> { CAst.make ~loc @@ CPatDelimiters (key,c) } ]
| "0"
- [ r = Prim.reference -> CAst.make ~loc:!@loc @@ CPatAtom (Some r)
- | "{|"; pat = record_patterns; "|}" -> CAst.make ~loc:!@loc @@ CPatRecord pat
- | "_" -> CAst.make ~loc:!@loc @@ CPatAtom None
+ [ r = Prim.reference -> { CAst.make ~loc @@ CPatAtom (Some r) }
+ | "{|"; pat = record_patterns; "|}" -> { CAst.make ~loc @@ CPatRecord pat }
+ | "_" -> { CAst.make ~loc @@ CPatAtom None }
| "("; p = pattern LEVEL "200"; ")" ->
- (match p.CAst.v with
+ { (match p.CAst.v with
| CPatPrim (Numeral (n,true)) ->
- CAst.make ~loc:!@loc @@ CPatNotation("( _ )",([p],[]),[])
- | _ -> p)
+ CAst.make ~loc @@ CPatNotation((InConstrEntrySomeLevel,"( _ )"),([p],[]),[])
+ | _ -> p) }
| "("; p = pattern LEVEL "200"; ":"; ty = lconstr; ")" ->
- let p =
+ { let p =
match p with
| { CAst.v = CPatPrim (Numeral (n,true)) } ->
- CAst.make ~loc:!@loc @@ CPatNotation("( _ )",([p],[]),[])
+ CAst.make ~loc @@ CPatNotation((InConstrEntrySomeLevel,"( _ )"),([p],[]),[])
| _ -> p
in
- CAst.make ~loc:!@loc @@ CPatCast (p, ty)
- | n = INT -> CAst.make ~loc:!@loc @@ CPatPrim (Numeral (n,true))
- | s = string -> CAst.make ~loc:!@loc @@ CPatPrim (String s) ] ]
+ CAst.make ~loc @@ CPatCast (p, ty) }
+ | n = INT -> { CAst.make ~loc @@ CPatPrim (Numeral (n,true)) }
+ | s = string -> { CAst.make ~loc @@ CPatPrim (String s) } ] ]
;
impl_ident_tail:
- [ [ "}" -> binder_of_name Implicit
+ [ [ "}" -> { binder_of_name Implicit }
| nal=LIST1 name; ":"; c=lconstr; "}" ->
- (fun na -> CLocalAssum (na::nal,Default Implicit,c))
+ { (fun na -> CLocalAssum (na::nal,Default Implicit,c)) }
| nal=LIST1 name; "}" ->
- (fun na -> CLocalAssum (na::nal,Default Implicit,
- CAst.make ?loc:(Loc.merge_opt na.CAst.loc (Some !@loc)) @@
- CHole (Some (Evar_kinds.BinderType na.CAst.v), IntroAnonymous, None)))
+ { (fun na -> CLocalAssum (na::nal,Default Implicit,
+ CAst.make ?loc:(Loc.merge_opt na.CAst.loc (Some loc)) @@
+ CHole (Some (Evar_kinds.BinderType na.CAst.v), IntroAnonymous, None))) }
| ":"; c=lconstr; "}" ->
- (fun na -> CLocalAssum ([na],Default Implicit,c))
+ { (fun na -> CLocalAssum ([na],Default Implicit,c)) }
] ]
;
fixannot:
- [ [ "{"; IDENT "struct"; id=identref; "}" -> (Some id, CStructRec)
- | "{"; IDENT "wf"; rel=constr; id=OPT identref; "}" -> (id, CWfRec rel)
+ [ [ "{"; IDENT "struct"; id=identref; "}" -> { (Some id, CStructRec) }
+ | "{"; IDENT "wf"; rel=constr; id=OPT identref; "}" -> { (id, CWfRec rel) }
| "{"; IDENT "measure"; m=constr; id=OPT identref;
- rel=OPT constr; "}" -> (id, CMeasureRec (m,rel))
+ rel=OPT constr; "}" -> { (id, CMeasureRec (m,rel)) }
] ]
;
impl_name_head:
- [ [ id = impl_ident_head -> (CAst.make ~loc:!@loc @@ Name id) ] ]
+ [ [ id = impl_ident_head -> { CAst.make ~loc @@ Name id } ] ]
;
binders_fixannot:
[ [ na = impl_name_head; assum = impl_ident_tail; bl = binders_fixannot ->
- (assum na :: fst bl), snd bl
- | f = fixannot -> [], f
- | b = binder; bl = binders_fixannot -> b @ fst bl, snd bl
- | -> [], (None, CStructRec)
+ { (assum na :: fst bl), snd bl }
+ | f = fixannot -> { [], f }
+ | b = binder; bl = binders_fixannot -> { b @ fst bl, snd bl }
+ | -> { [], (None, CStructRec) }
] ]
;
open_binders:
(* Same as binders but parentheses around a closed binder are optional if
the latter is unique *)
- [ [ (* open binder *)
+ [ [
id = name; idl = LIST0 name; ":"; c = lconstr ->
- [CLocalAssum (id::idl,Default Explicit,c)]
- (* binders factorized with open binder *)
+ { [CLocalAssum (id::idl,Default Explicit,c)]
+ (* binders factorized with open binder *) }
| id = name; idl = LIST0 name; bl = binders ->
- binders_of_names (id::idl) @ bl
+ { binders_of_names (id::idl) @ bl }
| id1 = name; ".."; id2 = name ->
- [CLocalAssum ([id1;(CAst.make ~loc:!@loc (Name ldots_var));id2],
- Default Explicit, CAst.make ~loc:!@loc @@ CHole (None, IntroAnonymous, None))]
+ { [CLocalAssum ([id1;(CAst.make ~loc (Name ldots_var));id2],
+ Default Explicit, CAst.make ~loc @@ CHole (None, IntroAnonymous, None))] }
| bl = closed_binder; bl' = binders ->
- bl@bl'
+ { bl@bl' }
] ]
;
binders:
- [ [ l = LIST0 binder -> List.flatten l ] ]
+ [ [ l = LIST0 binder -> { List.flatten l } ] ]
;
binder:
- [ [ id = name -> [CLocalAssum ([id],Default Explicit, CAst.make ~loc:!@loc @@ CHole (None, IntroAnonymous, None))]
- | bl = closed_binder -> bl ] ]
+ [ [ id = name -> { [CLocalAssum ([id],Default Explicit, CAst.make ~loc @@ CHole (None, IntroAnonymous, None))] }
+ | bl = closed_binder -> { bl } ] ]
;
closed_binder:
[ [ "("; id=name; idl=LIST1 name; ":"; c=lconstr; ")" ->
- [CLocalAssum (id::idl,Default Explicit,c)]
+ { [CLocalAssum (id::idl,Default Explicit,c)] }
| "("; id=name; ":"; c=lconstr; ")" ->
- [CLocalAssum ([id],Default Explicit,c)]
+ { [CLocalAssum ([id],Default Explicit,c)] }
| "("; id=name; ":="; c=lconstr; ")" ->
- (match c.CAst.v with
+ { (match c.CAst.v with
| CCast(c, CastConv t) -> [CLocalDef (id,c,Some t)]
- | _ -> [CLocalDef (id,c,None)])
+ | _ -> [CLocalDef (id,c,None)]) }
| "("; id=name; ":"; t=lconstr; ":="; c=lconstr; ")" ->
- [CLocalDef (id,c,Some t)]
+ { [CLocalDef (id,c,Some t)] }
| "{"; id=name; "}" ->
- [CLocalAssum ([id],Default Implicit, CAst.make ~loc:!@loc @@ CHole (None, IntroAnonymous, None))]
+ { [CLocalAssum ([id],Default Implicit, CAst.make ~loc @@ CHole (None, IntroAnonymous, None))] }
| "{"; id=name; idl=LIST1 name; ":"; c=lconstr; "}" ->
- [CLocalAssum (id::idl,Default Implicit,c)]
+ { [CLocalAssum (id::idl,Default Implicit,c)] }
| "{"; id=name; ":"; c=lconstr; "}" ->
- [CLocalAssum ([id],Default Implicit,c)]
+ { [CLocalAssum ([id],Default Implicit,c)] }
| "{"; id=name; idl=LIST1 name; "}" ->
- List.map (fun id -> CLocalAssum ([id],Default Implicit, CAst.make ~loc:!@loc @@ CHole (None, IntroAnonymous, None))) (id::idl)
+ { List.map (fun id -> CLocalAssum ([id],Default Implicit, CAst.make ~loc @@ CHole (None, IntroAnonymous, None))) (id::idl) }
| "`("; tc = LIST1 typeclass_constraint SEP "," ; ")" ->
- List.map (fun (n, b, t) -> CLocalAssum ([n], Generalized (Implicit, Explicit, b), t)) tc
+ { List.map (fun (n, b, t) -> CLocalAssum ([n], Generalized (Implicit, Explicit, b), t)) tc }
| "`{"; tc = LIST1 typeclass_constraint SEP "," ; "}" ->
- List.map (fun (n, b, t) -> CLocalAssum ([n], Generalized (Implicit, Implicit, b), t)) tc
+ { List.map (fun (n, b, t) -> CLocalAssum ([n], Generalized (Implicit, Implicit, b), t)) tc }
| "'"; p = pattern LEVEL "0" ->
- let (p, ty) =
+ { let (p, ty) =
match p.CAst.v with
| CPatCast (p, ty) -> (p, Some ty)
| _ -> (p, None)
in
- [CLocalPattern (CAst.make ~loc:!@loc (p, ty))]
+ [CLocalPattern (CAst.make ~loc (p, ty))] }
] ]
;
typeclass_constraint:
- [ [ "!" ; c = operconstr LEVEL "200" -> (CAst.make ~loc:!@loc Anonymous), true, c
- | "{"; id = name; "}"; ":" ; expl = [ "!" -> true | -> false ] ; c = operconstr LEVEL "200" ->
- id, expl, c
- | iid=name_colon ; expl = [ "!" -> true | -> false ] ; c = operconstr LEVEL "200" ->
- (CAst.make ~loc:!@loc iid), expl, c
+ [ [ "!" ; c = operconstr LEVEL "200" -> { (CAst.make ~loc Anonymous), true, c }
+ | "{"; id = name; "}"; ":" ; expl = [ "!" -> { true } | -> { false } ] ; c = operconstr LEVEL "200" ->
+ { id, expl, c }
+ | iid=name_colon ; expl = [ "!" -> { true } | -> { false } ] ; c = operconstr LEVEL "200" ->
+ { (CAst.make ~loc iid), expl, c }
| c = operconstr LEVEL "200" ->
- (CAst.make ~loc:!@loc Anonymous), false, c
+ { (CAst.make ~loc Anonymous), false, c }
] ]
;
type_cstr:
- [ [ c=OPT [":"; c=lconstr -> c] -> Loc.tag ~loc:!@loc c ] ]
+ [ [ c=OPT [":"; c=lconstr -> { c } ] -> { Loc.tag ~loc c } ] ]
;
- END;;
+ END
diff --git a/parsing/g_prim.ml4 b/parsing/g_prim.ml4
deleted file mode 100644
index 91dce27fe1..0000000000
--- a/parsing/g_prim.ml4
+++ /dev/null
@@ -1,122 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-open Names
-open Libnames
-
-open Pcoq
-open Pcoq.Prim
-
-let prim_kw = ["{"; "}"; "["; "]"; "("; ")"; "'"]
-let _ = List.iter CLexer.add_keyword prim_kw
-
-
-let local_make_qualid loc l id = make_qualid ~loc (DirPath.make l) id
-
-let my_int_of_string loc s =
- try
- let n = int_of_string s in
- (* To avoid Array.make errors (that e.g. Undo uses), we set a *)
- (* more restricted limit than int_of_string does *)
- if n > 1024 * 2048 then raise Exit;
- n
- with Failure _ | Exit ->
- CErrors.user_err ~loc (Pp.str "Cannot support a so large number.")
-
-GEXTEND Gram
- GLOBAL:
- bigint natural integer identref name ident var preident
- fullyqualid qualid reference dirpath ne_lstring
- ne_string string lstring pattern_ident pattern_identref by_notation smart_global;
- preident:
- [ [ s = IDENT -> s ] ]
- ;
- ident:
- [ [ s = IDENT -> Id.of_string s ] ]
- ;
- pattern_ident:
- [ [ LEFTQMARK; id = ident -> id ] ]
- ;
- pattern_identref:
- [ [ id = pattern_ident -> CAst.make ~loc:!@loc id ] ]
- ;
- var: (* as identref, but interpret as a term identifier in ltac *)
- [ [ id = ident -> CAst.make ~loc:!@loc id ] ]
- ;
- identref:
- [ [ id = ident -> CAst.make ~loc:!@loc id ] ]
- ;
- field:
- [ [ s = FIELD -> Id.of_string s ] ]
- ;
- fields:
- [ [ id = field; (l,id') = fields -> (l@[id],id')
- | id = field -> ([],id)
- ] ]
- ;
- fullyqualid:
- [ [ id = ident; (l,id')=fields -> CAst.make ~loc:!@loc @@ id::List.rev (id'::l)
- | id = ident -> CAst.make ~loc:!@loc [id]
- ] ]
- ;
- basequalid:
- [ [ id = ident; (l,id')=fields -> local_make_qualid !@loc (l@[id]) id'
- | id = ident -> qualid_of_ident ~loc:!@loc id
- ] ]
- ;
- name:
- [ [ IDENT "_" -> CAst.make ~loc:!@loc Anonymous
- | id = ident -> CAst.make ~loc:!@loc @@ Name id ] ]
- ;
- reference:
- [ [ id = ident; (l,id') = fields ->
- local_make_qualid !@loc (l@[id]) id'
- | id = ident -> local_make_qualid !@loc [] id
- ] ]
- ;
- by_notation:
- [ [ s = ne_string; sc = OPT ["%"; key = IDENT -> key ] -> (s, sc) ] ]
- ;
- smart_global:
- [ [ c = reference -> CAst.make ~loc:!@loc @@ Constrexpr.AN c
- | ntn = by_notation -> CAst.make ~loc:!@loc @@ Constrexpr.ByNotation ntn ] ]
- ;
- qualid:
- [ [ qid = basequalid -> qid ] ]
- ;
- ne_string:
- [ [ s = STRING ->
- if s="" then CErrors.user_err ~loc:!@loc (Pp.str"Empty string."); s
- ] ]
- ;
- ne_lstring:
- [ [ s = ne_string -> CAst.make ~loc:!@loc s ] ]
- ;
- dirpath:
- [ [ id = ident; l = LIST0 field ->
- DirPath.make (List.rev (id::l)) ] ]
- ;
- string:
- [ [ s = STRING -> s ] ]
- ;
- lstring:
- [ [ s = string -> (CAst.make ~loc:!@loc s) ] ]
- ;
- integer:
- [ [ i = INT -> my_int_of_string (!@loc) i
- | "-"; i = INT -> - my_int_of_string (!@loc) i ] ]
- ;
- natural:
- [ [ i = INT -> my_int_of_string (!@loc) i ] ]
- ;
- bigint: (* Negative numbers are dealt with elsewhere *)
- [ [ i = INT -> i ] ]
- ;
-END
diff --git a/parsing/g_prim.mlg b/parsing/g_prim.mlg
new file mode 100644
index 0000000000..dfb788907e
--- /dev/null
+++ b/parsing/g_prim.mlg
@@ -0,0 +1,123 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+{
+
+open Names
+open Libnames
+
+open Pcoq
+open Pcoq.Prim
+
+let prim_kw = ["{"; "}"; "["; "]"; "("; ")"; "'"]
+let _ = List.iter CLexer.add_keyword prim_kw
+
+
+let local_make_qualid loc l id = make_qualid ~loc (DirPath.make l) id
+
+let my_int_of_string loc s =
+ try
+ int_of_string s
+ with Failure _ ->
+ CErrors.user_err ~loc (Pp.str "This number is too large.")
+
+}
+
+GRAMMAR EXTEND Gram
+ GLOBAL:
+ bigint natural integer identref name ident var preident
+ fullyqualid qualid reference dirpath ne_lstring
+ ne_string string lstring pattern_ident pattern_identref by_notation smart_global;
+ preident:
+ [ [ s = IDENT -> { s } ] ]
+ ;
+ ident:
+ [ [ s = IDENT -> { Id.of_string s } ] ]
+ ;
+ pattern_ident:
+ [ [ LEFTQMARK; id = ident -> { id } ] ]
+ ;
+ pattern_identref:
+ [ [ id = pattern_ident -> { CAst.make ~loc id } ] ]
+ ;
+ var: (* as identref, but interpret as a term identifier in ltac *)
+ [ [ id = ident -> { CAst.make ~loc id } ] ]
+ ;
+ identref:
+ [ [ id = ident -> { CAst.make ~loc id } ] ]
+ ;
+ field:
+ [ [ s = FIELD -> { Id.of_string s } ] ]
+ ;
+ fields:
+ [ [ id = field; f = fields -> { let (l,id') = f in (l@[id],id') }
+ | id = field -> { ([],id) }
+ ] ]
+ ;
+ fullyqualid:
+ [ [ id = ident; f=fields -> { let (l,id') = f in CAst.make ~loc @@ id::List.rev (id'::l) }
+ | id = ident -> { CAst.make ~loc [id] }
+ ] ]
+ ;
+ basequalid:
+ [ [ id = ident; f=fields -> { let (l,id') = f in local_make_qualid loc (l@[id]) id' }
+ | id = ident -> { qualid_of_ident ~loc id }
+ ] ]
+ ;
+ name:
+ [ [ IDENT "_" -> { CAst.make ~loc Anonymous }
+ | id = ident -> { CAst.make ~loc @@ Name id } ] ]
+ ;
+ reference:
+ [ [ id = ident; f = fields -> {
+ let (l,id') = f in
+ local_make_qualid loc (l@[id]) id' }
+ | id = ident -> { local_make_qualid loc [] id }
+ ] ]
+ ;
+ by_notation:
+ [ [ s = ne_string; sc = OPT ["%"; key = IDENT -> { key } ] -> { (s, sc) } ] ]
+ ;
+ smart_global:
+ [ [ c = reference -> { CAst.make ~loc @@ Constrexpr.AN c }
+ | ntn = by_notation -> { CAst.make ~loc @@ Constrexpr.ByNotation ntn } ] ]
+ ;
+ qualid:
+ [ [ qid = basequalid -> { qid } ] ]
+ ;
+ ne_string:
+ [ [ s = STRING ->
+ { if s="" then CErrors.user_err ~loc (Pp.str"Empty string."); s }
+ ] ]
+ ;
+ ne_lstring:
+ [ [ s = ne_string -> { CAst.make ~loc s } ] ]
+ ;
+ dirpath:
+ [ [ id = ident; l = LIST0 field ->
+ { DirPath.make (List.rev (id::l)) } ] ]
+ ;
+ string:
+ [ [ s = STRING -> { s } ] ]
+ ;
+ lstring:
+ [ [ s = string -> { CAst.make ~loc s } ] ]
+ ;
+ integer:
+ [ [ i = INT -> { my_int_of_string loc i }
+ | "-"; i = INT -> { - my_int_of_string loc i } ] ]
+ ;
+ natural:
+ [ [ i = INT -> { my_int_of_string loc i } ] ]
+ ;
+ bigint: (* Negative numbers are dealt with elsewhere *)
+ [ [ i = INT -> { i } ] ]
+ ;
+END
diff --git a/parsing/notation_gram.ml b/parsing/notation_gram.ml
index 346350641f..d8c08803b6 100644
--- a/parsing/notation_gram.ml
+++ b/parsing/notation_gram.ml
@@ -17,7 +17,8 @@ type precedence = int
type parenRelation = L | E | Any | Prec of precedence
type tolerability = precedence * parenRelation
-type level = precedence * tolerability list * constr_entry_key list
+type level = Constrexpr.notation_entry * precedence * tolerability list * constr_entry_key list
+ (* first argument is InCustomEntry s for custom entries *)
type grammar_constr_prod_item =
| GramConstrTerminal of Tok.t
diff --git a/parsing/notgram_ops.ml b/parsing/notgram_ops.ml
index 071e6db205..5cc1292c92 100644
--- a/parsing/notgram_ops.ml
+++ b/parsing/notgram_ops.ml
@@ -11,55 +11,61 @@
open Pp
open CErrors
open Util
-open Extend
+open Notation
open Notation_gram
(* Uninterpreted notation levels *)
-let notation_level_map = Summary.ref ~name:"notation_level_map" String.Map.empty
+let notation_level_map = Summary.ref ~name:"notation_level_map" NotationMap.empty
let declare_notation_level ?(onlyprint=false) ntn level =
- if String.Map.mem ntn !notation_level_map then
- anomaly (str "Notation " ++ str ntn ++ str " is already assigned a level.");
- notation_level_map := String.Map.add ntn (level,onlyprint) !notation_level_map
+ try
+ let (level,onlyprint) = NotationMap.find ntn !notation_level_map in
+ if not onlyprint then anomaly (str "Notation " ++ pr_notation ntn ++ str " is already assigned a level.")
+ with Not_found ->
+ notation_level_map := NotationMap.add ntn (level,onlyprint) !notation_level_map
let level_of_notation ?(onlyprint=false) ntn =
- let (level,onlyprint') = String.Map.find ntn !notation_level_map in
+ let (level,onlyprint') = NotationMap.find ntn !notation_level_map in
if onlyprint' && not onlyprint then raise Not_found;
level
(**********************************************************************)
-(* Operations on scopes *)
+(* Equality *)
+
+open Extend
let parenRelation_eq t1 t2 = match t1, t2 with
| L, L | E, E | Any, Any -> true
| Prec l1, Prec l2 -> Int.equal l1 l2
| _ -> false
-let production_level_eq l1 l2 = true (* (l1 = l2) *)
+let production_position_eq pp1 pp2 = match (pp1,pp2) with
+| BorderProd (side1,assoc1), BorderProd (side2,assoc2) -> side1 = side2 && assoc1 = assoc2
+| InternalProd, InternalProd -> true
+| (BorderProd _ | InternalProd), _ -> false
-let production_position_eq pp1 pp2 = true (* pp1 = pp2 *) (* match pp1, pp2 with
+let production_level_eq l1 l2 = match (l1,l2) with
| NextLevel, NextLevel -> true
| NumLevel n1, NumLevel n2 -> Int.equal n1 n2
-| (NextLevel | NumLevel _), _ -> false *)
+| (NextLevel | NumLevel _), _ -> false
let constr_entry_key_eq eq v1 v2 = match v1, v2 with
-| ETName, ETName -> true
-| ETReference, ETReference -> true
+| ETIdent, ETIdent -> true
+| ETGlobal, ETGlobal -> true
| ETBigint, ETBigint -> true
| ETBinder b1, ETBinder b2 -> b1 == b2
-| ETConstr lev1, ETConstr lev2 -> eq lev1 lev2
-| ETConstrAsBinder (bk1,lev1), ETConstrAsBinder (bk2,lev2) -> eq lev1 lev2 && bk1 = bk2
+| ETConstr (s1,bko1,lev1), ETConstr (s2,bko2,lev2) ->
+ notation_entry_eq s1 s2 && eq lev1 lev2 && Option.equal (=) bko1 bko2
| ETPattern (b1,n1), ETPattern (b2,n2) -> b1 = b2 && Option.equal Int.equal n1 n2
-| ETOther (s1,s1'), ETOther (s2,s2') -> String.equal s1 s2 && String.equal s1' s2'
-| (ETName | ETReference | ETBigint | ETBinder _ | ETConstr _ | ETPattern _ | ETOther _ | ETConstrAsBinder _), _ -> false
+| (ETIdent | ETGlobal | ETBigint | ETBinder _ | ETConstr _ | ETPattern _), _ -> false
-let level_eq_gen strict (l1, t1, u1) (l2, t2, u2) =
+let level_eq_gen strict (s1, l1, t1, u1) (s2, l2, t2, u2) =
let tolerability_eq (i1, r1) (i2, r2) = Int.equal i1 i2 && parenRelation_eq r1 r2 in
let prod_eq (l1,pp1) (l2,pp2) =
- if strict then production_level_eq l1 l2 && production_position_eq pp1 pp2
- else production_level_eq l1 l2 in
- Int.equal l1 l2 && List.equal tolerability_eq t1 t2
+ not strict ||
+ (production_level_eq l1 l2 && production_position_eq pp1 pp2) in
+ notation_entry_eq s1 s2 && Int.equal l1 l2 && List.equal tolerability_eq t1 t2
&& List.equal (constr_entry_key_eq prod_eq) u1 u2
let level_eq = level_eq_gen false
diff --git a/parsing/pcoq.ml b/parsing/pcoq.ml
index 6fdd9ea9b9..eb3e633892 100644
--- a/parsing/pcoq.ml
+++ b/parsing/pcoq.ml
@@ -17,9 +17,17 @@ let curry f x y = f (x, y)
let uncurry f (x,y) = f x y
(** Location Utils *)
+let ploc_file_of_coq_file = function
+| Loc.ToplevelInput -> ""
+| Loc.InFile f -> f
+
let coq_file_of_ploc_file s =
if s = "" then Loc.ToplevelInput else Loc.InFile s
+let of_coqloc loc =
+ let open Loc in
+ Ploc.make_loc (ploc_file_of_coq_file loc.fname) loc.line_nb loc.bol_pos (loc.bp, loc.ep) ""
+
let to_coqloc loc =
{ Loc.fname = coq_file_of_ploc_file (Ploc.file_name loc);
Loc.line_nb = Ploc.line_nb loc;
@@ -78,24 +86,15 @@ module type S =
type internal_entry = Tok.t Gramext.g_entry
type symbol = Tok.t Gramext.g_symbol
type action = Gramext.g_action
- type production_rule = symbol list * action
- type single_extend_statement =
- string option * Gramext.g_assoc option * production_rule list
- type extend_statement =
- Gramext.position option * single_extend_statement list
type coq_parsable
- val parsable : ?file:Loc.source -> char Stream.t -> coq_parsable
+ val coq_parsable : ?file:Loc.source -> char Stream.t -> coq_parsable
val action : 'a -> action
val entry_create : string -> 'a entry
val entry_parse : 'a entry -> coq_parsable -> 'a
- val entry_print : Format.formatter -> 'a entry -> unit
val comment_state : coq_parsable -> ((int * int) * string) list
- val srules' : production_rule list -> symbol
- val parse_tokens_after_filter : 'a entry -> Tok.t Stream.t -> 'a
-
end with type 'a Entry.e = 'a Grammar.GMake(CLexer).Entry.e = struct
include Grammar.GMake(CLexer)
@@ -104,15 +103,10 @@ end with type 'a Entry.e = 'a Grammar.GMake(CLexer).Entry.e = struct
type internal_entry = Tok.t Gramext.g_entry
type symbol = Tok.t Gramext.g_symbol
type action = Gramext.g_action
- type production_rule = symbol list * action
- type single_extend_statement =
- string option * Gramext.g_assoc option * production_rule list
- type extend_statement =
- Gramext.position option * single_extend_statement list
type coq_parsable = parsable * CLexer.lexer_state ref
- let parsable ?(file=Loc.ToplevelInput) c =
+ let coq_parsable ?(file=Loc.ToplevelInput) c =
let state = ref (CLexer.init_lexer_state file) in
CLexer.set_lexer_state !state;
let a = parsable c in
@@ -137,11 +131,23 @@ end with type 'a Entry.e = 'a Grammar.GMake(CLexer).Entry.e = struct
let comment_state (p,state) =
CLexer.get_comment_state !state
- let entry_print ft x = Entry.print ft x
+end
+
+module Parsable =
+struct
+ type t = G.coq_parsable
+ let make = G.coq_parsable
+ let comment_state = G.comment_state
+end
+
+module Entry =
+struct
+
+ type 'a t = 'a Grammar.GMake(CLexer).Entry.e
- (* Not used *)
- let srules' = Gramext.srules
- let parse_tokens_after_filter = Entry.parse_token
+ let create = G.Entry.create
+ let parse = G.entry_parse
+ let print = G.Entry.print
end
@@ -236,9 +242,9 @@ let rec symbol_of_prod_entry_key : type s a. (s, a) symbol -> _ = function
| Aentry e ->
Symbols.snterm (G.Entry.obj e)
| Aentryl (e, n) ->
- Symbols.snterml (G.Entry.obj e, string_of_int n)
+ Symbols.snterml (G.Entry.obj e, n)
| Arules rs ->
- G.srules' (List.map symbol_of_rules rs)
+ Gramext.srules (List.map symbol_of_rules rs)
and symbol_of_rule : type s a r. (s, a, r) Extend.rule -> _ = function
| Stop -> fun accu -> accu
@@ -265,14 +271,21 @@ type gram_reinit = gram_assoc * gram_position
type extend_rule =
| ExtendRule : 'a G.entry * gram_reinit option * 'a extend_statement -> extend_rule
+module EntryCommand = Dyn.Make ()
+module EntryData = struct type _ t = Ex : 'b G.entry String.Map.t -> ('a * 'b) t end
+module EntryDataMap = EntryCommand.Map(EntryData)
+
type ext_kind =
| ByGrammar of extend_rule
| ByEXTEND of (unit -> unit) * (unit -> unit)
+ | ByEntry : ('a * 'b) EntryCommand.tag * string * 'b G.entry -> ext_kind
(** The list of extensions *)
let camlp5_state = ref []
+let camlp5_entries = ref EntryDataMap.empty
+
(** Deletion *)
let grammar_delete e reinit (pos,rls) =
@@ -328,6 +341,7 @@ module Gram =
I'm not entirely sure it makes sense, but at least it would be more correct.
*)
G.delete_rule e pil
+ let gram_extend e ext = grammar_extend e None ext
end
(** Remove extensions
@@ -337,7 +351,7 @@ module Gram =
let rec remove_grammars n =
if n>0 then
- (match !camlp5_state with
+ match !camlp5_state with
| [] -> anomaly ~label:"Pcoq.remove_grammars" (Pp.str "too many rules to remove.")
| ByGrammar (ExtendRule (g, reinit, ext)) :: t ->
grammar_delete g reinit (of_coq_extend_statement ext);
@@ -348,21 +362,31 @@ let rec remove_grammars n =
camlp5_state := t;
remove_grammars n;
redo();
- camlp5_state := ByEXTEND (undo,redo) :: !camlp5_state)
+ camlp5_state := ByEXTEND (undo,redo) :: !camlp5_state
+ | ByEntry (tag, name, e) :: t ->
+ G.Unsafe.clear_entry e;
+ camlp5_state := t;
+ let EntryData.Ex entries =
+ try EntryDataMap.find tag !camlp5_entries
+ with Not_found -> EntryData.Ex String.Map.empty
+ in
+ let entries = String.Map.remove name entries in
+ camlp5_entries := EntryDataMap.add tag (EntryData.Ex entries) !camlp5_entries;
+ remove_grammars (n - 1)
let make_rule r = [None, None, r]
(** An entry that checks we reached the end of the input. *)
let eoi_entry en =
- let e = Gram.entry_create ((Gram.Entry.name en) ^ "_eoi") in
+ let e = Entry.create ((Gram.Entry.name en) ^ "_eoi") in
let symbs = [Symbols.snterm (Gram.Entry.obj en); Symbols.stoken Tok.EOI] in
let act = Gram.action (fun _ x loc -> x) in
uncurry (Gram.extend e) (None, make_rule [symbs, act]);
e
let map_entry f en =
- let e = Gram.entry_create ((Gram.Entry.name en) ^ "_map") in
+ let e = Entry.create ((Gram.Entry.name en) ^ "_map") in
let symbs = [Symbols.snterm (Gram.Entry.obj en)] in
let act = Gram.action (fun x loc -> f x) in
uncurry (Gram.extend e) (None, make_rule [symbs, act]);
@@ -372,7 +396,7 @@ let map_entry f en =
(use eoi_entry) *)
let parse_string f x =
- let strm = Stream.of_string x in Gram.entry_parse f (Gram.parsable strm)
+ let strm = Stream.of_string x in Gram.entry_parse f (Gram.coq_parsable strm)
type gram_universe = string
@@ -393,14 +417,14 @@ let get_univ u =
let new_entry u s =
let ename = u ^ ":" ^ s in
- let e = Gram.entry_create ename in
+ let e = Entry.create ename in
e
let make_gen_entry u s = new_entry u s
module GrammarObj =
struct
- type ('r, _, _) obj = 'r Gram.entry
+ type ('r, _, _) obj = 'r Entry.t
let name = "grammar"
let default _ = None
end
@@ -410,7 +434,7 @@ module Grammar = Register(GrammarObj)
let register_grammar = Grammar.register0
let genarg_grammar = Grammar.obj
-let create_generic_entry (type a) u s (etyp : a raw_abstract_argument_type) : a Gram.entry =
+let create_generic_entry (type a) u s (etyp : a raw_abstract_argument_type) : a Entry.t =
let e = new_entry u s in
let Rawwit t = etyp in
let () = Grammar.register0 t e in
@@ -422,38 +446,38 @@ module Prim =
struct
let gec_gen n = make_gen_entry uprim n
- (* Entries that can be referred via the string -> Gram.entry table *)
+ (* Entries that can be referred via the string -> Entry.t table *)
(* Typically for tactic or vernac extensions *)
let preident = gec_gen "preident"
let ident = gec_gen "ident"
let natural = gec_gen "natural"
let integer = gec_gen "integer"
- let bigint = Gram.entry_create "Prim.bigint"
+ let bigint = Entry.create "Prim.bigint"
let string = gec_gen "string"
- let lstring = Gram.entry_create "Prim.lstring"
+ let lstring = Entry.create "Prim.lstring"
let reference = make_gen_entry uprim "reference"
- let by_notation = Gram.entry_create "by_notation"
- let smart_global = Gram.entry_create "smart_global"
+ let by_notation = Entry.create "by_notation"
+ let smart_global = Entry.create "smart_global"
(* parsed like ident but interpreted as a term *)
let var = gec_gen "var"
- let name = Gram.entry_create "Prim.name"
- let identref = Gram.entry_create "Prim.identref"
- let univ_decl = Gram.entry_create "Prim.univ_decl"
- let ident_decl = Gram.entry_create "Prim.ident_decl"
- let pattern_ident = Gram.entry_create "pattern_ident"
- let pattern_identref = Gram.entry_create "pattern_identref"
+ let name = Entry.create "Prim.name"
+ let identref = Entry.create "Prim.identref"
+ let univ_decl = Entry.create "Prim.univ_decl"
+ let ident_decl = Entry.create "Prim.ident_decl"
+ let pattern_ident = Entry.create "pattern_ident"
+ let pattern_identref = Entry.create "pattern_identref"
(* A synonym of ident - maybe ident will be located one day *)
- let base_ident = Gram.entry_create "Prim.base_ident"
+ let base_ident = Entry.create "Prim.base_ident"
- let qualid = Gram.entry_create "Prim.qualid"
- let fullyqualid = Gram.entry_create "Prim.fullyqualid"
- let dirpath = Gram.entry_create "Prim.dirpath"
+ let qualid = Entry.create "Prim.qualid"
+ let fullyqualid = Entry.create "Prim.fullyqualid"
+ let dirpath = Entry.create "Prim.dirpath"
- let ne_string = Gram.entry_create "Prim.ne_string"
- let ne_lstring = Gram.entry_create "Prim.ne_lstring"
+ let ne_string = Entry.create "Prim.ne_string"
+ let ne_lstring = Entry.create "Prim.ne_lstring"
end
@@ -461,7 +485,7 @@ module Constr =
struct
let gec_constr = make_gen_entry uconstr
- (* Entries that can be referred via the string -> Gram.entry table *)
+ (* Entries that can be referred via the string -> Entry.t table *)
let constr = gec_constr "constr"
let operconstr = gec_constr "operconstr"
let constr_eoi = eoi_entry constr
@@ -472,29 +496,29 @@ module Constr =
let universe_level = make_gen_entry uconstr "universe_level"
let sort = make_gen_entry uconstr "sort"
let sort_family = make_gen_entry uconstr "sort_family"
- let pattern = Gram.entry_create "constr:pattern"
+ let pattern = Entry.create "constr:pattern"
let constr_pattern = gec_constr "constr_pattern"
let lconstr_pattern = gec_constr "lconstr_pattern"
- let closed_binder = Gram.entry_create "constr:closed_binder"
- let binder = Gram.entry_create "constr:binder"
- let binders = Gram.entry_create "constr:binders"
- let open_binders = Gram.entry_create "constr:open_binders"
- let binders_fixannot = Gram.entry_create "constr:binders_fixannot"
- let typeclass_constraint = Gram.entry_create "constr:typeclass_constraint"
- let record_declaration = Gram.entry_create "constr:record_declaration"
- let appl_arg = Gram.entry_create "constr:appl_arg"
+ let closed_binder = Entry.create "constr:closed_binder"
+ let binder = Entry.create "constr:binder"
+ let binders = Entry.create "constr:binders"
+ let open_binders = Entry.create "constr:open_binders"
+ let binders_fixannot = Entry.create "constr:binders_fixannot"
+ let typeclass_constraint = Entry.create "constr:typeclass_constraint"
+ let record_declaration = Entry.create "constr:record_declaration"
+ let appl_arg = Entry.create "constr:appl_arg"
end
module Module =
struct
- let module_expr = Gram.entry_create "module_expr"
- let module_type = Gram.entry_create "module_type"
+ let module_expr = Entry.create "module_expr"
+ let module_type = Entry.create "module_type"
end
let epsilon_value f e =
let r = Rule (Next (Stop, e), fun x _ -> f x) in
let ext = of_coq_extend_statement (None, [None, None, [r]]) in
- let entry = G.entry_create "epsilon" in
+ let entry = Gram.entry_create "epsilon" in
let () = uncurry (G.extend entry) ext in
try Some (parse_string entry "") with _ -> None
@@ -510,59 +534,119 @@ module GrammarInterpMap = GrammarCommand.Map(GrammarInterp)
let grammar_interp = ref GrammarInterpMap.empty
-let (grammar_stack : (int * GrammarCommand.t * GramState.t) list ref) = ref []
+type ('a, 'b) entry_extension = 'a -> GramState.t -> string list * GramState.t
+
+module EntryInterp = struct type _ t = Ex : ('a, 'b) entry_extension -> ('a * 'b) t end
+module EntryInterpMap = EntryCommand.Map(EntryInterp)
+
+let entry_interp = ref EntryInterpMap.empty
+
+type grammar_entry =
+| GramExt of int * GrammarCommand.t
+| EntryExt : int * ('a * 'b) EntryCommand.tag * 'a -> grammar_entry
+
+let (grammar_stack : (grammar_entry * GramState.t) list ref) = ref []
type 'a grammar_command = 'a GrammarCommand.tag
+type ('a, 'b) entry_command = ('a * 'b) EntryCommand.tag
let create_grammar_command name interp : _ grammar_command =
let obj = GrammarCommand.create name in
let () = grammar_interp := GrammarInterpMap.add obj interp !grammar_interp in
obj
+let create_entry_command name (interp : ('a, 'b) entry_extension) : ('a, 'b) entry_command =
+ let obj = EntryCommand.create name in
+ let () = entry_interp := EntryInterpMap.add obj (EntryInterp.Ex interp) !entry_interp in
+ obj
+
let extend_grammar_command tag g =
let modify = GrammarInterpMap.find tag !grammar_interp in
let grammar_state = match !grammar_stack with
| [] -> GramState.empty
- | (_, _, st) :: _ -> st
+ | (_, st) :: _ -> st
in
let (rules, st) = modify g grammar_state in
let iter (ExtendRule (e, reinit, ext)) = grammar_extend_sync e reinit ext in
let () = List.iter iter rules in
let nb = List.length rules in
- grammar_stack := (nb, GrammarCommand.Dyn (tag, g), st) :: !grammar_stack
+ grammar_stack := (GramExt (nb, GrammarCommand.Dyn (tag, g)), st) :: !grammar_stack
-let recover_grammar_command (type a) (tag : a grammar_command) : a list =
- let filter : _ -> a option = fun (_, GrammarCommand.Dyn (tag', v), _) ->
- match GrammarCommand.eq tag tag' with
- | None -> None
- | Some Refl -> Some v
+let extend_entry_command (type a) (type b) (tag : (a, b) entry_command) (g : a) : b Gram.entry list =
+ let EntryInterp.Ex modify = EntryInterpMap.find tag !entry_interp in
+ let grammar_state = match !grammar_stack with
+ | [] -> GramState.empty
+ | (_, st) :: _ -> st
in
- List.map_filter filter !grammar_stack
+ let (names, st) = modify g grammar_state in
+ let entries = List.map (fun name -> Gram.entry_create name) names in
+ let iter name e =
+ camlp5_state := ByEntry (tag, name, e) :: !camlp5_state;
+ let EntryData.Ex old =
+ try EntryDataMap.find tag !camlp5_entries
+ with Not_found -> EntryData.Ex String.Map.empty
+ in
+ let entries = String.Map.add name e old in
+ camlp5_entries := EntryDataMap.add tag (EntryData.Ex entries) !camlp5_entries
+ in
+ let () = List.iter2 iter names entries in
+ let nb = List.length entries in
+ let () = grammar_stack := (EntryExt (nb, tag, g), st) :: !grammar_stack in
+ entries
+
+let find_custom_entry tag name =
+ let EntryData.Ex map = EntryDataMap.find tag !camlp5_entries in
+ String.Map.find name map
-let extend_dyn_grammar (GrammarCommand.Dyn (tag, g)) = extend_grammar_command tag g
+let extend_dyn_grammar (e, _) = match e with
+| GramExt (_, (GrammarCommand.Dyn (tag, g))) -> extend_grammar_command tag g
+| EntryExt (_, tag, g) -> ignore (extend_entry_command tag g)
-(* Summary functions: the state of the lexer is included in that of the parser.
+(** Registering extra grammar *)
+
+type any_entry = AnyEntry : 'a Gram.entry -> any_entry
+
+let grammar_names : any_entry list String.Map.t ref = ref String.Map.empty
+
+let register_grammars_by_name name grams =
+ grammar_names := String.Map.add name grams !grammar_names
+
+let find_grammars_by_name name =
+ try String.Map.find name !grammar_names
+ with Not_found ->
+ let fold (EntryDataMap.Any (tag, EntryData.Ex map)) accu =
+ try AnyEntry (String.Map.find name map) :: accu
+ with Not_found -> accu
+ in
+ EntryDataMap.fold fold !camlp5_entries []
+
+(** Summary functions: the state of the lexer is included in that of the parser.
Because the grammar affects the set of keywords when adding or removing
grammar rules. *)
-type frozen_t = (int * GrammarCommand.t * GramState.t) list * CLexer.keyword_state
+type frozen_t =
+ (grammar_entry * GramState.t) list *
+ CLexer.keyword_state
-let freeze _ : frozen_t = (!grammar_stack, CLexer.get_keyword_state ())
+let freeze _ : frozen_t =
+ (!grammar_stack, CLexer.get_keyword_state ())
(* We compare the current state of the grammar and the state to unfreeze,
by computing the longest common suffixes *)
let factorize_grams l1 l2 =
if l1 == l2 then ([], [], l1) else List.share_tails l1 l2
-let number_of_entries gcl =
- List.fold_left (fun n (p,_,_) -> n + p) 0 gcl
+let rec number_of_entries accu = function
+| [] -> accu
+| ((GramExt (p, _) | EntryExt (p, _, _)), _) :: rem ->
+ number_of_entries (p + accu) rem
let unfreeze (grams, lex) =
let (undo, redo, common) = factorize_grams !grammar_stack grams in
- let n = number_of_entries undo in
+ let n = number_of_entries 0 undo in
remove_grammars n;
grammar_stack := common;
CLexer.set_keyword_state lex;
- List.iter extend_dyn_grammar (List.rev_map pi2 redo)
+ List.iter extend_dyn_grammar (List.rev redo)
(** No need to provide an init function : the grammar state is
statically available, and already empty initially, while
@@ -596,15 +680,3 @@ let () =
Grammar.register0 wit_sort_family (Constr.sort_family);
Grammar.register0 wit_constr (Constr.constr);
()
-
-(** Registering extra grammar *)
-
-type any_entry = AnyEntry : 'a Gram.entry -> any_entry
-
-let grammar_names : any_entry list String.Map.t ref = ref String.Map.empty
-
-let register_grammars_by_name name grams =
- grammar_names := String.Map.add name grams !grammar_names
-
-let find_grammars_by_name name =
- String.Map.find name !grammar_names
diff --git a/parsing/pcoq.mli b/parsing/pcoq.mli
index f959bd80c0..e12ccaa636 100644
--- a/parsing/pcoq.mli
+++ b/parsing/pcoq.mli
@@ -16,80 +16,40 @@ open Libnames
(** The parser of Coq *)
+(** DO NOT USE EXTENSION FUNCTIONS IN THIS MODULE.
+ We only have it here to work with Camlp5. Handwritten grammar extensions
+ should use the safe [Pcoq.grammar_extend] function below. *)
module Gram : sig
include Grammar.S with type te = Tok.t
-(* Where Grammar.S is
-
-module type S =
- sig
- type te = 'x;
- type parsable = 'x;
- value parsable : Stream.t char -> parsable;
- value tokens : string -> list (string * int);
- value glexer : Plexing.lexer te;
- value set_algorithm : parse_algorithm -> unit;
- module Entry :
- sig
- type e 'a = 'y;
- value create : string -> e 'a;
- value parse : e 'a -> parsable -> 'a;
- value parse_token : e 'a -> Stream.t te -> 'a;
- value name : e 'a -> string;
- value of_parser : string -> (Stream.t te -> 'a) -> e 'a;
- value print : Format.formatter -> e 'a -> unit;
- external obj : e 'a -> Gramext.g_entry te = "%identity";
- end
- ;
- module Unsafe :
- sig
- value gram_reinit : Plexing.lexer te -> unit;
- value clear_entry : Entry.e 'a -> unit;
- end
- ;
- value extend :
- Entry.e 'a -> option Gramext.position ->
- list
- (option string * option Gramext.g_assoc *
- list (list (Gramext.g_symbol te) * Gramext.g_action)) ->
- unit;
- value delete_rule : Entry.e 'a -> list (Gramext.g_symbol te) -> unit;
- end
+ type 'a entry = 'a Entry.e
+ [@@ocaml.deprecated "Use [Pcoq.Entry.t]"]
-*)
+ [@@@ocaml.warning "-3"]
- type 'a entry = 'a Entry.e
- type internal_entry = Tok.t Gramext.g_entry
- type symbol = Tok.t Gramext.g_symbol
- type action = Gramext.g_action
- type production_rule = symbol list * action
- type single_extend_statement =
- string option * Gramext.g_assoc option * production_rule list
- type extend_statement =
- Gramext.position option * single_extend_statement list
-
- type coq_parsable
-
- val parsable : ?file:Loc.source -> char Stream.t -> coq_parsable
- val action : 'a -> action
val entry_create : string -> 'a entry
- val entry_parse : 'a entry -> coq_parsable -> 'a
- val entry_print : Format.formatter -> 'a entry -> unit
+ [@@ocaml.deprecated "Use [Pcoq.Entry.create]"]
- (* Get comment parsing information from the Lexer *)
- val comment_state : coq_parsable -> ((int * int) * string) list
+ val gram_extend : 'a entry -> 'a Extend.extend_statement -> unit
- (* Apparently not used *)
- val srules' : production_rule list -> symbol
- val parse_tokens_after_filter : 'a entry -> Tok.t Stream.t -> 'a
+ [@@@ocaml.warning "+3"]
end with type 'a Entry.e = 'a Grammar.GMake(CLexer).Entry.e
-module Symbols : sig
+module Parsable :
+sig
+ type t
+ val make : ?file:Loc.source -> char Stream.t -> t
+ (* Get comment parsing information from the Lexer *)
+ val comment_state : t -> ((int * int) * string) list
+end
- val stoken : Tok.t -> Gram.symbol
- val snterm : Gram.internal_entry -> Gram.symbol
+module Entry : sig
+ type 'a t = 'a Grammar.GMake(CLexer).Entry.e
+ val create : string -> 'a t
+ val parse : 'a t -> Parsable.t -> 'a
+ val print : Format.formatter -> 'a t -> unit
end
(** The parser of Coq is built from three kinds of rule declarations:
@@ -173,86 +133,86 @@ val camlp5_verbosity : bool -> ('a -> unit) -> 'a -> unit
(** Parse a string *)
-val parse_string : 'a Gram.entry -> string -> 'a
-val eoi_entry : 'a Gram.entry -> 'a Gram.entry
-val map_entry : ('a -> 'b) -> 'a Gram.entry -> 'b Gram.entry
+val parse_string : 'a Entry.t -> string -> 'a
+val eoi_entry : 'a Entry.t -> 'a Entry.t
+val map_entry : ('a -> 'b) -> 'a Entry.t -> 'b Entry.t
type gram_universe
val get_univ : string -> gram_universe
val create_universe : string -> gram_universe
-val new_entry : gram_universe -> string -> 'a Gram.entry
+val new_entry : gram_universe -> string -> 'a Entry.t
val uprim : gram_universe
val uconstr : gram_universe
val utactic : gram_universe
-val register_grammar : ('raw, 'glb, 'top) genarg_type -> 'raw Gram.entry -> unit
-val genarg_grammar : ('raw, 'glb, 'top) genarg_type -> 'raw Gram.entry
+val register_grammar : ('raw, 'glb, 'top) genarg_type -> 'raw Entry.t -> unit
+val genarg_grammar : ('raw, 'glb, 'top) genarg_type -> 'raw Entry.t
val create_generic_entry : gram_universe -> string ->
- ('a, rlevel) abstract_argument_type -> 'a Gram.entry
+ ('a, rlevel) abstract_argument_type -> 'a Entry.t
module Prim :
sig
open Names
open Libnames
- val preident : string Gram.entry
- val ident : Id.t Gram.entry
- val name : lname Gram.entry
- val identref : lident Gram.entry
- val univ_decl : universe_decl_expr Gram.entry
- val ident_decl : ident_decl Gram.entry
- val pattern_ident : Id.t Gram.entry
- val pattern_identref : lident Gram.entry
- val base_ident : Id.t Gram.entry
- val natural : int Gram.entry
- val bigint : Constrexpr.raw_natural_number Gram.entry
- val integer : int Gram.entry
- val string : string Gram.entry
- val lstring : lstring Gram.entry
- val reference : qualid Gram.entry
- val qualid : qualid Gram.entry
- val fullyqualid : Id.t list CAst.t Gram.entry
- val by_notation : (string * string option) Gram.entry
- val smart_global : qualid or_by_notation Gram.entry
- val dirpath : DirPath.t Gram.entry
- val ne_string : string Gram.entry
- val ne_lstring : lstring Gram.entry
- val var : lident Gram.entry
+ val preident : string Entry.t
+ val ident : Id.t Entry.t
+ val name : lname Entry.t
+ val identref : lident Entry.t
+ val univ_decl : universe_decl_expr Entry.t
+ val ident_decl : ident_decl Entry.t
+ val pattern_ident : Id.t Entry.t
+ val pattern_identref : lident Entry.t
+ val base_ident : Id.t Entry.t
+ val natural : int Entry.t
+ val bigint : Constrexpr.raw_natural_number Entry.t
+ val integer : int Entry.t
+ val string : string Entry.t
+ val lstring : lstring Entry.t
+ val reference : qualid Entry.t
+ val qualid : qualid Entry.t
+ val fullyqualid : Id.t list CAst.t Entry.t
+ val by_notation : (string * string option) Entry.t
+ val smart_global : qualid or_by_notation Entry.t
+ val dirpath : DirPath.t Entry.t
+ val ne_string : string Entry.t
+ val ne_lstring : lstring Entry.t
+ val var : lident Entry.t
end
module Constr :
sig
- val constr : constr_expr Gram.entry
- val constr_eoi : constr_expr Gram.entry
- val lconstr : constr_expr Gram.entry
- val binder_constr : constr_expr Gram.entry
- val operconstr : constr_expr Gram.entry
- val ident : Id.t Gram.entry
- val global : qualid Gram.entry
- val universe_level : Glob_term.glob_level Gram.entry
- val sort : Glob_term.glob_sort Gram.entry
- val sort_family : Sorts.family Gram.entry
- val pattern : cases_pattern_expr Gram.entry
- val constr_pattern : constr_expr Gram.entry
- val lconstr_pattern : constr_expr Gram.entry
- val closed_binder : local_binder_expr list Gram.entry
- val binder : local_binder_expr list Gram.entry (* closed_binder or variable *)
- val binders : local_binder_expr list Gram.entry (* list of binder *)
- val open_binders : local_binder_expr list Gram.entry
- val binders_fixannot : (local_binder_expr list * (lident option * recursion_order_expr)) Gram.entry
- val typeclass_constraint : (lname * bool * constr_expr) Gram.entry
- val record_declaration : constr_expr Gram.entry
- val appl_arg : (constr_expr * explicitation CAst.t option) Gram.entry
+ val constr : constr_expr Entry.t
+ val constr_eoi : constr_expr Entry.t
+ val lconstr : constr_expr Entry.t
+ val binder_constr : constr_expr Entry.t
+ val operconstr : constr_expr Entry.t
+ val ident : Id.t Entry.t
+ val global : qualid Entry.t
+ val universe_level : Glob_term.glob_level Entry.t
+ val sort : Glob_term.glob_sort Entry.t
+ val sort_family : Sorts.family Entry.t
+ val pattern : cases_pattern_expr Entry.t
+ val constr_pattern : constr_expr Entry.t
+ val lconstr_pattern : constr_expr Entry.t
+ val closed_binder : local_binder_expr list Entry.t
+ val binder : local_binder_expr list Entry.t (* closed_binder or variable *)
+ val binders : local_binder_expr list Entry.t (* list of binder *)
+ val open_binders : local_binder_expr list Entry.t
+ val binders_fixannot : (local_binder_expr list * (lident option * recursion_order_expr)) Entry.t
+ val typeclass_constraint : (lname * bool * constr_expr) Entry.t
+ val record_declaration : constr_expr Entry.t
+ val appl_arg : (constr_expr * explicitation CAst.t option) Entry.t
end
module Module :
sig
- val module_expr : module_ast Gram.entry
- val module_type : module_ast Gram.entry
+ val module_expr : module_ast Entry.t
+ val module_type : module_ast Entry.t
end
val epsilon_value : ('a -> 'self) -> ('self, 'a) Extend.symbol -> 'self option
@@ -262,7 +222,7 @@ val epsilon_value : ('a -> 'self) -> ('self, 'a) Extend.symbol -> 'self option
type gram_reinit = gram_assoc * gram_position
(** Type of reinitialization data *)
-val grammar_extend : 'a Gram.entry -> gram_reinit option ->
+val grammar_extend : 'a Entry.t -> gram_reinit option ->
'a Extend.extend_statement -> unit
(** Extend the grammar of Coq, without synchronizing it with the backtracking
mechanism. This means that grammar extensions defined this way will survive
@@ -273,12 +233,14 @@ val grammar_extend : 'a Gram.entry -> gram_reinit option ->
module GramState : Store.S
(** Auxiliary state of the grammar. Any added data must be marshallable. *)
+(** {6 Extension with parsing rules} *)
+
type 'a grammar_command
(** Type of synchronized parsing extensions. The ['a] type should be
marshallable. *)
type extend_rule =
-| ExtendRule : 'a Gram.entry * gram_reinit option * 'a extend_statement -> extend_rule
+| ExtendRule : 'a Entry.t * gram_reinit option * 'a extend_statement -> extend_rule
type 'a grammar_extension = 'a -> GramState.t -> extend_rule list * GramState.t
(** Grammar extension entry point. Given some ['a] and a current grammar state,
@@ -293,12 +255,35 @@ val create_grammar_command : string -> 'a grammar_extension -> 'a grammar_comman
val extend_grammar_command : 'a grammar_command -> 'a -> unit
(** Extend the grammar of Coq with the given data. *)
-val recover_grammar_command : 'a grammar_command -> 'a list
-(** Recover the current stack of grammar extensions. *)
+(** {6 Extension with parsing entries} *)
+
+type ('a, 'b) entry_command
+(** Type of synchronized entry creation. The ['a] type should be
+ marshallable. *)
+
+type ('a, 'b) entry_extension = 'a -> GramState.t -> string list * GramState.t
+(** Entry extension entry point. Given some ['a] and a current grammar state,
+ such a function must produce the list of entry extensions that will be
+ created and kept synchronized w.r.t. the summary, together
+ with a new state. It should be pure. *)
+
+val create_entry_command : string -> ('a, 'b) entry_extension -> ('a, 'b) entry_command
+(** Create a new entry-creating command with the given name. The extension
+ function is called to generate the new entries for a given data. *)
+
+val extend_entry_command : ('a, 'b) entry_command -> 'a -> 'b Entry.t list
+(** Create new synchronized entries using the provided data. *)
+
+val find_custom_entry : ('a, 'b) entry_command -> string -> 'b Entry.t
+(** Find an entry generated by the synchronized system in the current state.
+ @raise Not_found if non-existent. *)
+
+(** {6 Protection w.r.t. backtrack} *)
val with_grammar_rule_protection : ('a -> 'b) -> 'a -> 'b
(** Location Utils *)
+val of_coqloc : Loc.t -> Ploc.t
val to_coqloc : Ploc.t -> Loc.t
val (!@) : Ploc.t -> Loc.t
@@ -307,7 +292,7 @@ val parser_summary_tag : frozen_t Summary.Dyn.tag
(** Registering grammars by name *)
-type any_entry = AnyEntry : 'a Gram.entry -> any_entry
+type any_entry = AnyEntry : 'a Entry.t -> any_entry
val register_grammars_by_name : string -> any_entry list -> unit
val find_grammars_by_name : string -> any_entry list
diff --git a/parsing/ppextend.ml b/parsing/ppextend.ml
index d2b50fa83d..e1f5e20117 100644
--- a/parsing/ppextend.ml
+++ b/parsing/ppextend.ml
@@ -11,6 +11,7 @@
open Util
open Pp
open CErrors
+open Notation
open Notation_gram
(*s Pretty-print. *)
@@ -48,29 +49,29 @@ type unparsing_rule = unparsing list * precedence
type extra_unparsing_rules = (string * string) list
(* Concrete syntax for symbolic-extension table *)
let notation_rules =
- Summary.ref ~name:"notation-rules" (String.Map.empty : (unparsing_rule * extra_unparsing_rules * notation_grammar) String.Map.t)
+ Summary.ref ~name:"notation-rules" (NotationMap.empty : (unparsing_rule * extra_unparsing_rules * notation_grammar) NotationMap.t)
let declare_notation_rule ntn ~extra unpl gram =
- notation_rules := String.Map.add ntn (unpl,extra,gram) !notation_rules
+ notation_rules := NotationMap.add ntn (unpl,extra,gram) !notation_rules
let find_notation_printing_rule ntn =
- try pi1 (String.Map.find ntn !notation_rules)
- with Not_found -> anomaly (str "No printing rule found for " ++ str ntn ++ str ".")
+ try pi1 (NotationMap.find ntn !notation_rules)
+ with Not_found -> anomaly (str "No printing rule found for " ++ pr_notation ntn ++ str ".")
let find_notation_extra_printing_rules ntn =
- try pi2 (String.Map.find ntn !notation_rules)
+ try pi2 (NotationMap.find ntn !notation_rules)
with Not_found -> []
let find_notation_parsing_rules ntn =
- try pi3 (String.Map.find ntn !notation_rules)
- with Not_found -> anomaly (str "No parsing rule found for " ++ str ntn ++ str ".")
+ try pi3 (NotationMap.find ntn !notation_rules)
+ with Not_found -> anomaly (str "No parsing rule found for " ++ pr_notation ntn ++ str ".")
let get_defined_notations () =
- String.Set.elements @@ String.Map.domain !notation_rules
+ NotationSet.elements @@ NotationMap.domain !notation_rules
let add_notation_extra_printing_rule ntn k v =
try
notation_rules :=
- let p, pp, gr = String.Map.find ntn !notation_rules in
- String.Map.add ntn (p, (k,v) :: pp, gr) !notation_rules
+ let p, pp, gr = NotationMap.find ntn !notation_rules in
+ NotationMap.add ntn (p, (k,v) :: pp, gr) !notation_rules
with Not_found ->
user_err ~hdr:"add_notation_extra_printing_rule"
(str "No such Notation.")
diff --git a/parsing/ppextend.mli b/parsing/ppextend.mli
index 9f61e121a4..7eb5967a3e 100644
--- a/parsing/ppextend.mli
+++ b/parsing/ppextend.mli
@@ -41,7 +41,6 @@ type unparsing =
type unparsing_rule = unparsing list * precedence
type extra_unparsing_rules = (string * string) list
-
val declare_notation_rule : notation -> extra:extra_unparsing_rules -> unparsing_rule -> notation_grammar -> unit
val find_notation_printing_rule : notation -> unparsing_rule
val find_notation_extra_printing_rules : notation -> extra_unparsing_rules
diff --git a/plugins/.merlin b/plugins/.merlin.in
index 2ba6169622..2ba6169622 100644
--- a/plugins/.merlin
+++ b/plugins/.merlin.in
diff --git a/plugins/btauto/g_btauto.ml4 b/plugins/btauto/g_btauto.mlg
index 3ae0f45cb7..312ef1e555 100644
--- a/plugins/btauto/g_btauto.ml4
+++ b/plugins/btauto/g_btauto.mlg
@@ -8,11 +8,15 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
+{
+
open Ltac_plugin
+}
+
DECLARE PLUGIN "btauto_plugin"
TACTIC EXTEND btauto
-| [ "btauto" ] -> [ Refl_btauto.Btauto.tac ]
+| [ "btauto" ] -> { Refl_btauto.Btauto.tac }
END
diff --git a/plugins/cc/ccalgo.ml b/plugins/cc/ccalgo.ml
index 4c6156a38b..ce620d5312 100644
--- a/plugins/cc/ccalgo.ml
+++ b/plugins/cc/ccalgo.ml
@@ -130,8 +130,8 @@ type cinfo=
ci_nhyps: int} (* # projectable args *)
let family_eq f1 f2 = match f1, f2 with
- | Prop Pos, Prop Pos
- | Prop Null, Prop Null
+ | Set, Set
+ | Prop, Prop
| Type _, Type _ -> true
| _ -> false
@@ -460,7 +460,7 @@ let rec canonize_name sigma c =
mkApp (func ct,Array.Smart.map func l)
| Proj(p,c) ->
let p' = Projection.map (fun kn ->
- Constant.make1 (Constant.canonical kn)) p in
+ MutInd.make1 (MutInd.canonical kn)) p in
(mkProj (p', func c))
| _ -> c
diff --git a/plugins/cc/cctac.ml b/plugins/cc/cctac.ml
index 04ff11fc49..2eaa6146e1 100644
--- a/plugins/cc/cctac.ml
+++ b/plugins/cc/cctac.ml
@@ -84,8 +84,8 @@ let rec decompose_term env sigma t=
let canon_const = Constant.make1 (Constant.canonical c) in
(Symb (Constr.mkConstU (canon_const,u)))
| Proj (p, c) ->
- let canon_const kn = Constant.make1 (Constant.canonical kn) in
- let p' = Projection.map canon_const p in
+ let canon_mind kn = MutInd.make1 (MutInd.canonical kn) in
+ let p' = Projection.map canon_mind p in
let c = Retyping.expand_projection env sigma p' c [] in
decompose_term env sigma c
| _ ->
diff --git a/plugins/cc/g_congruence.ml4 b/plugins/cc/g_congruence.mlg
index fb013ac131..685059294f 100644
--- a/plugins/cc/g_congruence.ml4
+++ b/plugins/cc/g_congruence.mlg
@@ -8,22 +8,26 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
+{
+
open Ltac_plugin
open Cctac
open Stdarg
+}
+
DECLARE PLUGIN "cc_plugin"
(* Tactic registration *)
TACTIC EXTEND cc
- [ "congruence" ] -> [ congruence_tac 1000 [] ]
- |[ "congruence" integer(n) ] -> [ congruence_tac n [] ]
- |[ "congruence" "with" ne_constr_list(l) ] -> [ congruence_tac 1000 l ]
+| [ "congruence" ] -> { congruence_tac 1000 [] }
+| [ "congruence" integer(n) ] -> { congruence_tac n [] }
+| [ "congruence" "with" ne_constr_list(l) ] -> { congruence_tac 1000 l }
|[ "congruence" integer(n) "with" ne_constr_list(l) ] ->
- [ congruence_tac n l ]
+ { congruence_tac n l }
END
TACTIC EXTEND f_equal
- [ "f_equal" ] -> [ f_equal ]
+| [ "f_equal" ] -> { f_equal }
END
diff --git a/plugins/extraction/ExtrHaskellString.v b/plugins/extraction/ExtrHaskellString.v
index ac1f6f9130..a4a40d3c5a 100644
--- a/plugins/extraction/ExtrHaskellString.v
+++ b/plugins/extraction/ExtrHaskellString.v
@@ -35,6 +35,8 @@ Extract Inductive ascii => "Prelude.Char"
(Data.Bits.testBit (Data.Char.ord a) 6)
(Data.Bits.testBit (Data.Char.ord a) 7))".
Extract Inlined Constant Ascii.ascii_dec => "(Prelude.==)".
+Extract Inlined Constant Ascii.eqb => "(Prelude.==)".
Extract Inductive string => "Prelude.String" [ "([])" "(:)" ].
Extract Inlined Constant String.string_dec => "(Prelude.==)".
+Extract Inlined Constant String.eqb => "(Prelude.==)".
diff --git a/plugins/extraction/ExtrOcamlString.v b/plugins/extraction/ExtrOcamlString.v
index 030b486b26..a2a6a8fe67 100644
--- a/plugins/extraction/ExtrOcamlString.v
+++ b/plugins/extraction/ExtrOcamlString.v
@@ -33,6 +33,7 @@ Extract Constant shift =>
"fun b c -> Char.chr (((Char.code c) lsl 1) land 255 + if b then 1 else 0)".
Extract Inlined Constant ascii_dec => "(=)".
+Extract Inlined Constant Ascii.eqb => "(=)".
Extract Inductive string => "char list" [ "[]" "(::)" ].
diff --git a/plugins/extraction/extraction.ml b/plugins/extraction/extraction.ml
index 71e09992cc..67c605ea1d 100644
--- a/plugins/extraction/extraction.ml
+++ b/plugins/extraction/extraction.ml
@@ -1065,13 +1065,13 @@ let extract_constant env kn cb =
(match cb.const_body with
| Undef _ -> warn_info (); mk_typ_ax ()
| Def c ->
- (match Environ.is_projection kn env with
- | false -> mk_typ (get_body c)
- | true ->
- let pb = lookup_projection (Projection.make kn false) env in
- let ind = pb.Declarations.proj_ind in
+ (match Recordops.find_primitive_projection kn with
+ | None -> mk_typ (get_body c)
+ | Some p ->
+ let p = Projection.make p false in
+ let ind = Projection.inductive p in
let bodies = Inductiveops.legacy_match_projection env ind in
- let body = bodies.(pb.Declarations.proj_arg) in
+ let body = bodies.(Projection.arg p) in
mk_typ (EConstr.of_constr body))
| OpaqueDef c ->
add_opaque r;
@@ -1081,13 +1081,13 @@ let extract_constant env kn cb =
(match cb.const_body with
| Undef _ -> warn_info (); mk_ax ()
| Def c ->
- (match Environ.is_projection kn env with
- | false -> mk_def (get_body c)
- | true ->
- let pb = lookup_projection (Projection.make kn false) env in
- let ind = pb.Declarations.proj_ind in
+ (match Recordops.find_primitive_projection kn with
+ | None -> mk_def (get_body c)
+ | Some p ->
+ let p = Projection.make p false in
+ let ind = Projection.inductive p in
let bodies = Inductiveops.legacy_match_projection env ind in
- let body = bodies.(pb.Declarations.proj_arg) in
+ let body = bodies.(Projection.arg p) in
mk_def (EConstr.of_constr body))
| OpaqueDef c ->
add_opaque r;
diff --git a/plugins/firstorder/ground.ml b/plugins/firstorder/ground.ml
index 4e3ba57308..516b04ea21 100644
--- a/plugins/firstorder/ground.ml
+++ b/plugins/firstorder/ground.ml
@@ -13,23 +13,21 @@ open Formula
open Sequent
open Rules
open Instances
-open Constr
open Tacmach.New
open Tacticals.New
+open Globnames
let update_flags ()=
- let predref=ref Names.Cpred.empty in
- let f coe=
- try
- let kn= fst (destConst (Classops.get_coercion_value coe)) in
- predref:=Names.Cpred.add kn !predref
- with DestKO -> ()
+ let f acc coe =
+ match coe.Classops.coe_value with
+ | ConstRef c -> Names.Cpred.add c acc
+ | _ -> acc
in
- List.iter f (Classops.coercions ());
+ let pred = List.fold_left f Names.Cpred.empty (Classops.coercions ()) in
red_flags:=
CClosure.RedFlags.red_add_transparent
CClosure.betaiotazeta
- (Names.Id.Pred.full,Names.Cpred.complement !predref)
+ (Names.Id.Pred.full,Names.Cpred.complement pred)
let ground_tac solver startseq =
Proofview.Goal.enter begin fun gl ->
diff --git a/plugins/fourier/Fourier.v b/plugins/fourier/Fourier.v
deleted file mode 100644
index 07f32be8e6..0000000000
--- a/plugins/fourier/Fourier.v
+++ /dev/null
@@ -1,20 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-(* "Fourier's method to solve linear inequations/equations systems.".*)
-
-Require Export Field.
-Require Export DiscrR.
-Require Export Fourier_util.
-Declare ML Module "fourier_plugin".
-
-Ltac fourier := abstract (compute [IZR IPR IPR_2] in *; fourierz; field; discrR).
-
-Ltac fourier_eq := apply Rge_antisym; fourier.
diff --git a/plugins/fourier/Fourier_util.v b/plugins/fourier/Fourier_util.v
deleted file mode 100644
index d3159698b1..0000000000
--- a/plugins/fourier/Fourier_util.v
+++ /dev/null
@@ -1,222 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-Require Export Rbase.
-Comments "Lemmas used by the tactic Fourier".
-
-Open Scope R_scope.
-
-Lemma Rfourier_lt : forall x1 y1 a:R, x1 < y1 -> 0 < a -> a * x1 < a * y1.
-intros; apply Rmult_lt_compat_l; assumption.
-Qed.
-
-Lemma Rfourier_le : forall x1 y1 a:R, x1 <= y1 -> 0 < a -> a * x1 <= a * y1.
-red.
-intros.
-case H; auto with real.
-Qed.
-
-Lemma Rfourier_lt_lt :
- forall x1 y1 x2 y2 a:R,
- x1 < y1 -> x2 < y2 -> 0 < a -> x1 + a * x2 < y1 + a * y2.
-intros x1 y1 x2 y2 a H H0 H1; try assumption.
-apply Rplus_lt_compat.
-try exact H.
-apply Rfourier_lt.
-try exact H0.
-try exact H1.
-Qed.
-
-Lemma Rfourier_lt_le :
- forall x1 y1 x2 y2 a:R,
- x1 < y1 -> x2 <= y2 -> 0 < a -> x1 + a * x2 < y1 + a * y2.
-intros x1 y1 x2 y2 a H H0 H1; try assumption.
-case H0; intros.
-apply Rplus_lt_compat.
-try exact H.
-apply Rfourier_lt; auto with real.
-rewrite H2.
-rewrite (Rplus_comm y1 (a * y2)).
-rewrite (Rplus_comm x1 (a * y2)).
-apply Rplus_lt_compat_l.
-try exact H.
-Qed.
-
-Lemma Rfourier_le_lt :
- forall x1 y1 x2 y2 a:R,
- x1 <= y1 -> x2 < y2 -> 0 < a -> x1 + a * x2 < y1 + a * y2.
-intros x1 y1 x2 y2 a H H0 H1; try assumption.
-case H; intros.
-apply Rfourier_lt_le; auto with real.
-rewrite H2.
-apply Rplus_lt_compat_l.
-apply Rfourier_lt; auto with real.
-Qed.
-
-Lemma Rfourier_le_le :
- forall x1 y1 x2 y2 a:R,
- x1 <= y1 -> x2 <= y2 -> 0 < a -> x1 + a * x2 <= y1 + a * y2.
-intros x1 y1 x2 y2 a H H0 H1; try assumption.
-case H0; intros.
-red.
-left; try assumption.
-apply Rfourier_le_lt; auto with real.
-rewrite H2.
-case H; intros.
-red.
-left; try assumption.
-rewrite (Rplus_comm x1 (a * y2)).
-rewrite (Rplus_comm y1 (a * y2)).
-apply Rplus_lt_compat_l.
-try exact H3.
-rewrite H3.
-red.
-right; try assumption.
-auto with real.
-Qed.
-
-Lemma Rlt_zero_pos_plus1 : forall x:R, 0 < x -> 0 < 1 + x.
-intros x H; try assumption.
-rewrite Rplus_comm.
-apply Rle_lt_0_plus_1.
-red; auto with real.
-Qed.
-
-Lemma Rlt_mult_inv_pos : forall x y:R, 0 < x -> 0 < y -> 0 < x * / y.
-intros x y H H0; try assumption.
-replace 0 with (x * 0).
-apply Rmult_lt_compat_l; auto with real.
-ring.
-Qed.
-
-Lemma Rlt_zero_1 : 0 < 1.
-exact Rlt_0_1.
-Qed.
-
-Lemma Rle_zero_pos_plus1 : forall x:R, 0 <= x -> 0 <= 1 + x.
-intros x H; try assumption.
-case H; intros.
-red.
-left; try assumption.
-apply Rlt_zero_pos_plus1; auto with real.
-rewrite <- H0.
-replace (1 + 0) with 1.
-red; left.
-exact Rlt_zero_1.
-ring.
-Qed.
-
-Lemma Rle_mult_inv_pos : forall x y:R, 0 <= x -> 0 < y -> 0 <= x * / y.
-intros x y H H0; try assumption.
-case H; intros.
-red; left.
-apply Rlt_mult_inv_pos; auto with real.
-rewrite <- H1.
-red; right; ring.
-Qed.
-
-Lemma Rle_zero_1 : 0 <= 1.
-red; left.
-exact Rlt_zero_1.
-Qed.
-
-Lemma Rle_not_lt : forall n d:R, 0 <= n * / d -> ~ 0 < - n * / d.
-intros n d H; red; intros H0; try exact H0.
-generalize (Rgt_not_le 0 (n * / d)).
-intros H1; elim H1; try assumption.
-replace (n * / d) with (- - (n * / d)).
-replace 0 with (- -0).
-replace (- (n * / d)) with (- n * / d).
-replace (-0) with 0.
-red.
-apply Ropp_gt_lt_contravar.
-red.
-exact H0.
-ring.
-ring.
-ring.
-ring.
-Qed.
-
-Lemma Rnot_lt0 : forall x:R, ~ 0 < 0 * x.
-intros x; try assumption.
-replace (0 * x) with 0.
-apply Rlt_irrefl.
-ring.
-Qed.
-
-Lemma Rlt_not_le_frac_opp : forall n d:R, 0 < n * / d -> ~ 0 <= - n * / d.
-intros n d H; try assumption.
-apply Rgt_not_le.
-replace 0 with (-0).
-replace (- n * / d) with (- (n * / d)).
-apply Ropp_lt_gt_contravar.
-try exact H.
-ring.
-ring.
-Qed.
-
-Lemma Rnot_lt_lt : forall x y:R, ~ 0 < y - x -> ~ x < y.
-unfold not; intros.
-apply H.
-apply Rplus_lt_reg_l with x.
-replace (x + 0) with x.
-replace (x + (y - x)) with y.
-try exact H0.
-ring.
-ring.
-Qed.
-
-Lemma Rnot_le_le : forall x y:R, ~ 0 <= y - x -> ~ x <= y.
-unfold not; intros.
-apply H.
-case H0; intros.
-left.
-apply Rplus_lt_reg_l with x.
-replace (x + 0) with x.
-replace (x + (y - x)) with y.
-try exact H1.
-ring.
-ring.
-right.
-rewrite H1; ring.
-Qed.
-
-Lemma Rfourier_gt_to_lt : forall x y:R, y > x -> x < y.
-unfold Rgt; intros; assumption.
-Qed.
-
-Lemma Rfourier_ge_to_le : forall x y:R, y >= x -> x <= y.
-intros x y; exact (Rge_le y x).
-Qed.
-
-Lemma Rfourier_eqLR_to_le : forall x y:R, x = y -> x <= y.
-exact Req_le.
-Qed.
-
-Lemma Rfourier_eqRL_to_le : forall x y:R, y = x -> x <= y.
-exact Req_le_sym.
-Qed.
-
-Lemma Rfourier_not_ge_lt : forall x y:R, (x >= y -> False) -> x < y.
-exact Rnot_ge_lt.
-Qed.
-
-Lemma Rfourier_not_gt_le : forall x y:R, (x > y -> False) -> x <= y.
-exact Rnot_gt_le.
-Qed.
-
-Lemma Rfourier_not_le_gt : forall x y:R, (x <= y -> False) -> x > y.
-exact Rnot_le_lt.
-Qed.
-
-Lemma Rfourier_not_lt_ge : forall x y:R, (x < y -> False) -> x >= y.
-exact Rnot_lt_ge.
-Qed.
diff --git a/plugins/fourier/fourier.ml b/plugins/fourier/fourier.ml
deleted file mode 100644
index bee2b3b581..0000000000
--- a/plugins/fourier/fourier.ml
+++ /dev/null
@@ -1,204 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-(* Méthode d'élimination de Fourier *)
-(* Référence:
-Auteur(s) : Fourier, Jean-Baptiste-Joseph
-
-Titre(s) : Oeuvres de Fourier [Document électronique]. Tome second. Mémoires publiés dans divers recueils / publ. par les soins de M. Gaston Darboux,...
-
-Publication : Numérisation BnF de l'édition de Paris : Gauthier-Villars, 1890
-
-Pages: 326-327
-
-http://gallica.bnf.fr/
-*)
-
-(* Un peu de calcul sur les rationnels...
-Les opérations rendent des rationnels normalisés,
-i.e. le numérateur et le dénominateur sont premiers entre eux.
-*)
-type rational = {num:int;
- den:int}
-;;
-let print_rational x =
- print_int x.num;
- print_string "/";
- print_int x.den
-;;
-
-let rec pgcd x y = if y = 0 then x else pgcd y (x mod y);;
-
-
-let r0 = {num=0;den=1};;
-let r1 = {num=1;den=1};;
-
-let rnorm x = let x = (if x.den<0 then {num=(-x.num);den=(-x.den)} else x) in
- if x.num=0 then r0
- else (let d=pgcd x.num x.den in
- let d= (if d<0 then -d else d) in
- {num=(x.num)/d;den=(x.den)/d});;
-
-let rop x = rnorm {num=(-x.num);den=x.den};;
-
-let rplus x y = rnorm {num=x.num*y.den + y.num*x.den;den=x.den*y.den};;
-
-let rminus x y = rnorm {num=x.num*y.den - y.num*x.den;den=x.den*y.den};;
-
-let rmult x y = rnorm {num=x.num*y.num;den=x.den*y.den};;
-
-let rinv x = rnorm {num=x.den;den=x.num};;
-
-let rdiv x y = rnorm {num=x.num*y.den;den=x.den*y.num};;
-
-let rinf x y = x.num*y.den < y.num*x.den;;
-let rinfeq x y = x.num*y.den <= y.num*x.den;;
-
-(* {coef;hist;strict}, où coef=[c1; ...; cn; d], représente l'inéquation
-c1x1+...+cnxn < d si strict=true, <= sinon,
-hist donnant les coefficients (positifs) d'une combinaison linéaire qui permet d'obtenir l'inéquation à partir de celles du départ.
-*)
-
-type ineq = {coef:rational list;
- hist:rational list;
- strict:bool};;
-
-let pop x l = l:=x::(!l);;
-
-(* sépare la liste d'inéquations s selon que leur premier coefficient est
-négatif, nul ou positif. *)
-let partitionne s =
- let lpos=ref [] in
- let lneg=ref [] in
- let lnul=ref [] in
- List.iter (fun ie -> match ie.coef with
- [] -> raise (Failure "empty ineq")
- |(c::r) -> if rinf c r0
- then pop ie lneg
- else if rinf r0 c then pop ie lpos
- else pop ie lnul)
- s;
- [!lneg;!lnul;!lpos]
-;;
-(* initialise les histoires d'une liste d'inéquations données par leurs listes de coefficients et leurs strictitudes (!):
-(add_hist [(equation 1, s1);...;(équation n, sn)])
-=
-[{équation 1, [1;0;...;0], s1};
- {équation 2, [0;1;...;0], s2};
- ...
- {équation n, [0;0;...;1], sn}]
-*)
-let add_hist le =
- let n = List.length le in
- let i = ref 0 in
- List.map (fun (ie,s) ->
- let h = ref [] in
- for _k = 1 to (n - (!i) - 1) do pop r0 h; done;
- pop r1 h;
- for _k = 1 to !i do pop r0 h; done;
- i:=!i+1;
- {coef=ie;hist=(!h);strict=s})
- le
-;;
-(* additionne deux inéquations *)
-let ie_add ie1 ie2 = {coef=List.map2 rplus ie1.coef ie2.coef;
- hist=List.map2 rplus ie1.hist ie2.hist;
- strict=ie1.strict || ie2.strict}
-;;
-(* multiplication d'une inéquation par un rationnel (positif) *)
-let ie_emult a ie = {coef=List.map (fun x -> rmult a x) ie.coef;
- hist=List.map (fun x -> rmult a x) ie.hist;
- strict= ie.strict}
-;;
-(* on enlève le premier coefficient *)
-let ie_tl ie = {coef=List.tl ie.coef;hist=ie.hist;strict=ie.strict}
-;;
-(* le premier coefficient: "tête" de l'inéquation *)
-let hd_coef ie = List.hd ie.coef
-;;
-
-(* calcule toutes les combinaisons entre inéquations de tête négative et inéquations de tête positive qui annulent le premier coefficient.
-*)
-let deduce_add lneg lpos =
- let res=ref [] in
- List.iter (fun i1 ->
- List.iter (fun i2 ->
- let a = rop (hd_coef i1) in
- let b = hd_coef i2 in
- pop (ie_tl (ie_add (ie_emult b i1)
- (ie_emult a i2))) res)
- lpos)
- lneg;
- !res
-;;
-(* élimination de la première variable à partir d'une liste d'inéquations:
-opération qu'on itère dans l'algorithme de Fourier.
-*)
-let deduce1 s =
- match (partitionne s) with
- [lneg;lnul;lpos] ->
- let lnew = deduce_add lneg lpos in
- (List.map ie_tl lnul)@lnew
- |_->assert false
-;;
-(* algorithme de Fourier: on élimine successivement toutes les variables.
-*)
-let deduce lie =
- let n = List.length (fst (List.hd lie)) in
- let lie=ref (add_hist lie) in
- for _i = 1 to n - 1 do
- lie:= deduce1 !lie;
- done;
- !lie
-;;
-
-(* donne [] si le système a des solutions,
-sinon donne [c,s,lc]
-où lc est la combinaison linéaire des inéquations de départ
-qui donne 0 < c si s=true
- ou 0 <= c sinon
-cette inéquation étant absurde.
-*)
-
-exception Contradiction of (rational * bool * rational list) list
-
-let unsolvable lie =
- let lr = deduce lie in
- let check = function
- | {coef=[c];hist=lc;strict=s} ->
- if (rinf c r0 && (not s)) || (rinfeq c r0 && s)
- then raise (Contradiction [c,s,lc])
- |_->assert false
- in
- try List.iter check lr; []
- with Contradiction l -> l
-
-(* Exemples:
-
-let test1=[[r1;r1;r0],true;[rop r1;r1;r1],false;[r0;rop r1;rop r1],false];;
-deduce test1;;
-unsolvable test1;;
-
-let test2=[
-[r1;r1;r0;r0;r0],false;
-[r0;r1;r1;r0;r0],false;
-[r0;r0;r1;r1;r0],false;
-[r0;r0;r0;r1;r1],false;
-[r1;r0;r0;r0;r1],false;
-[rop r1;rop r1;r0;r0;r0],false;
-[r0;rop r1;rop r1;r0;r0],false;
-[r0;r0;rop r1;rop r1;r0],false;
-[r0;r0;r0;rop r1;rop r1],false;
-[rop r1;r0;r0;r0;rop r1],false
-];;
-deduce test2;;
-unsolvable test2;;
-
-*)
diff --git a/plugins/fourier/fourierR.ml b/plugins/fourier/fourierR.ml
deleted file mode 100644
index 96be1d8934..0000000000
--- a/plugins/fourier/fourierR.ml
+++ /dev/null
@@ -1,644 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-
-
-(* La tactique Fourier ne fonctionne de manière sûre que si les coefficients
-des inéquations et équations sont entiers. En attendant la tactique Field.
-*)
-
-open Constr
-open Tactics
-open Names
-open Globnames
-open Fourier
-open Contradiction
-open Proofview.Notations
-
-(******************************************************************************
-Opérations sur les combinaisons linéaires affines.
-La partie homogène d'une combinaison linéaire est en fait une table de hash
-qui donne le coefficient d'un terme du calcul des constructions,
-qui est zéro si le terme n'y est pas.
-*)
-
-module Constrhash = Hashtbl.Make(Constr)
-
-type flin = {fhom: rational Constrhash.t;
- fcste:rational};;
-
-let flin_zero () = {fhom=Constrhash.create 50;fcste=r0};;
-
-let flin_coef f x = try Constrhash.find f.fhom x with Not_found -> r0;;
-
-let flin_add f x c =
- let cx = flin_coef f x in
- Constrhash.replace f.fhom x (rplus cx c);
- f
-;;
-let flin_add_cste f c =
- {fhom=f.fhom;
- fcste=rplus f.fcste c}
-;;
-
-let flin_one () = flin_add_cste (flin_zero()) r1;;
-
-let flin_plus f1 f2 =
- let f3 = flin_zero() in
- Constrhash.iter (fun x c -> let _=flin_add f3 x c in ()) f1.fhom;
- Constrhash.iter (fun x c -> let _=flin_add f3 x c in ()) f2.fhom;
- flin_add_cste (flin_add_cste f3 f1.fcste) f2.fcste;
-;;
-
-let flin_minus f1 f2 =
- let f3 = flin_zero() in
- Constrhash.iter (fun x c -> let _=flin_add f3 x c in ()) f1.fhom;
- Constrhash.iter (fun x c -> let _=flin_add f3 x (rop c) in ()) f2.fhom;
- flin_add_cste (flin_add_cste f3 f1.fcste) (rop f2.fcste);
-;;
-let flin_emult a f =
- let f2 = flin_zero() in
- Constrhash.iter (fun x c -> let _=flin_add f2 x (rmult a c) in ()) f.fhom;
- flin_add_cste f2 (rmult a f.fcste);
-;;
-
-(*****************************************************************************)
-
-type ineq = Rlt | Rle | Rgt | Rge
-
-let string_of_R_constant kn =
- match Constant.repr3 kn with
- | ModPath.MPfile dir, sec_dir, id when
- sec_dir = DirPath.empty &&
- DirPath.to_string dir = "Coq.Reals.Rdefinitions"
- -> Label.to_string id
- | _ -> "constant_not_of_R"
-
-let rec string_of_R_constr c =
- match Constr.kind c with
- Cast (c,_,_) -> string_of_R_constr c
- |Const (c,_) -> string_of_R_constant c
- | _ -> "not_of_constant"
-
-exception NoRational
-
-let rec rational_of_constr c =
- match Constr.kind c with
- | Cast (c,_,_) -> (rational_of_constr c)
- | App (c,args) ->
- (match (string_of_R_constr c) with
- | "Ropp" ->
- rop (rational_of_constr args.(0))
- | "Rinv" ->
- rinv (rational_of_constr args.(0))
- | "Rmult" ->
- rmult (rational_of_constr args.(0))
- (rational_of_constr args.(1))
- | "Rdiv" ->
- rdiv (rational_of_constr args.(0))
- (rational_of_constr args.(1))
- | "Rplus" ->
- rplus (rational_of_constr args.(0))
- (rational_of_constr args.(1))
- | "Rminus" ->
- rminus (rational_of_constr args.(0))
- (rational_of_constr args.(1))
- | _ -> raise NoRational)
- | Const (kn,_) ->
- (match (string_of_R_constant kn) with
- "R1" -> r1
- |"R0" -> r0
- | _ -> raise NoRational)
- | _ -> raise NoRational
-;;
-
-exception NoLinear
-
-let rec flin_of_constr c =
- try(
- match Constr.kind c with
- | Cast (c,_,_) -> (flin_of_constr c)
- | App (c,args) ->
- (match (string_of_R_constr c) with
- "Ropp" ->
- flin_emult (rop r1) (flin_of_constr args.(0))
- | "Rplus"->
- flin_plus (flin_of_constr args.(0))
- (flin_of_constr args.(1))
- | "Rminus"->
- flin_minus (flin_of_constr args.(0))
- (flin_of_constr args.(1))
- | "Rmult"->
- (try
- let a = rational_of_constr args.(0) in
- try
- let b = rational_of_constr args.(1) in
- flin_add_cste (flin_zero()) (rmult a b)
- with NoRational ->
- flin_add (flin_zero()) args.(1) a
- with NoRational ->
- flin_add (flin_zero()) args.(0)
- (rational_of_constr args.(1)))
- | "Rinv"->
- let a = rational_of_constr args.(0) in
- flin_add_cste (flin_zero()) (rinv a)
- | "Rdiv"->
- (let b = rational_of_constr args.(1) in
- try
- let a = rational_of_constr args.(0) in
- flin_add_cste (flin_zero()) (rdiv a b)
- with NoRational ->
- flin_add (flin_zero()) args.(0) (rinv b))
- |_-> raise NoLinear)
- | Const (c,_) ->
- (match (string_of_R_constant c) with
- "R1" -> flin_one ()
- |"R0" -> flin_zero ()
- |_-> raise NoLinear)
- |_-> raise NoLinear)
- with NoRational | NoLinear -> flin_add (flin_zero()) c r1
-;;
-
-let flin_to_alist f =
- let res=ref [] in
- Constrhash.iter (fun x c -> res:=(c,x)::(!res)) f;
- !res
-;;
-
-(* Représentation des hypothèses qui sont des inéquations ou des équations.
-*)
-type hineq={hname:constr; (* le nom de l'hypothèse *)
- htype:string; (* Rlt, Rgt, Rle, Rge, eqTLR ou eqTRL *)
- hleft:constr;
- hright:constr;
- hflin:flin;
- hstrict:bool}
-;;
-
-(* Transforme une hypothese h:t en inéquation flin<0 ou flin<=0
-*)
-
-exception NoIneq
-
-let ineq1_of_constr (h,t) =
- let h = EConstr.Unsafe.to_constr h in
- let t = EConstr.Unsafe.to_constr t in
- match (Constr.kind t) with
- | App (f,args) ->
- (match Constr.kind f with
- | Const (c,_) when Array.length args = 2 ->
- let t1= args.(0) in
- let t2= args.(1) in
- (match (string_of_R_constant c) with
- |"Rlt" -> [{hname=h;
- htype="Rlt";
- hleft=t1;
- hright=t2;
- hflin= flin_minus (flin_of_constr t1)
- (flin_of_constr t2);
- hstrict=true}]
- |"Rgt" -> [{hname=h;
- htype="Rgt";
- hleft=t2;
- hright=t1;
- hflin= flin_minus (flin_of_constr t2)
- (flin_of_constr t1);
- hstrict=true}]
- |"Rle" -> [{hname=h;
- htype="Rle";
- hleft=t1;
- hright=t2;
- hflin= flin_minus (flin_of_constr t1)
- (flin_of_constr t2);
- hstrict=false}]
- |"Rge" -> [{hname=h;
- htype="Rge";
- hleft=t2;
- hright=t1;
- hflin= flin_minus (flin_of_constr t2)
- (flin_of_constr t1);
- hstrict=false}]
- |_-> raise NoIneq)
- | Ind ((kn,i),_) ->
- if not (GlobRef.equal (IndRef(kn,i)) Coqlib.glob_eq) then raise NoIneq;
- let t0= args.(0) in
- let t1= args.(1) in
- let t2= args.(2) in
- (match (Constr.kind t0) with
- | Const (c,_) ->
- (match (string_of_R_constant c) with
- | "R"->
- [{hname=h;
- htype="eqTLR";
- hleft=t1;
- hright=t2;
- hflin= flin_minus (flin_of_constr t1)
- (flin_of_constr t2);
- hstrict=false};
- {hname=h;
- htype="eqTRL";
- hleft=t2;
- hright=t1;
- hflin= flin_minus (flin_of_constr t2)
- (flin_of_constr t1);
- hstrict=false}]
- |_-> raise NoIneq)
- |_-> raise NoIneq)
- |_-> raise NoIneq)
- |_-> raise NoIneq
-;;
-
-(* Applique la méthode de Fourier à une liste d'hypothèses (type hineq)
-*)
-
-let fourier_lineq lineq1 =
- let nvar=ref (-1) in
- let hvar=Constrhash.create 50 in (* la table des variables des inéquations *)
- List.iter (fun f ->
- Constrhash.iter (fun x _ -> if not (Constrhash.mem hvar x) then begin
- nvar:=(!nvar)+1;
- Constrhash.add hvar x (!nvar)
- end)
- f.hflin.fhom)
- lineq1;
- let sys= List.map (fun h->
- let v=Array.make ((!nvar)+1) r0 in
- Constrhash.iter (fun x c -> v.(Constrhash.find hvar x)<-c)
- h.hflin.fhom;
- ((Array.to_list v)@[rop h.hflin.fcste],h.hstrict))
- lineq1 in
- unsolvable sys
-;;
-
-(*********************************************************************)
-(* Defined constants *)
-
-let get = Lazy.force
-let cget = get
-let eget c = EConstr.of_constr (Lazy.force c)
-let constant path s = UnivGen.constr_of_global @@
- Coqlib.coq_reference "Fourier" path s
-
-(* Standard library *)
-open Coqlib
-let coq_sym_eqT = lazy (build_coq_eq_sym ())
-let coq_False = lazy (UnivGen.constr_of_global @@ build_coq_False ())
-let coq_not = lazy (UnivGen.constr_of_global @@ build_coq_not ())
-let coq_eq = lazy (UnivGen.constr_of_global @@ build_coq_eq ())
-
-(* Rdefinitions *)
-let constant_real = constant ["Reals";"Rdefinitions"]
-
-let coq_Rlt = lazy (constant_real "Rlt")
-let coq_Rgt = lazy (constant_real "Rgt")
-let coq_Rle = lazy (constant_real "Rle")
-let coq_Rge = lazy (constant_real "Rge")
-let coq_R = lazy (constant_real "R")
-let coq_Rminus = lazy (constant_real "Rminus")
-let coq_Rmult = lazy (constant_real "Rmult")
-let coq_Rplus = lazy (constant_real "Rplus")
-let coq_Ropp = lazy (constant_real "Ropp")
-let coq_Rinv = lazy (constant_real "Rinv")
-let coq_R0 = lazy (constant_real "R0")
-let coq_R1 = lazy (constant_real "R1")
-
-(* RIneq *)
-let coq_Rinv_1 = lazy (constant ["Reals";"RIneq"] "Rinv_1")
-
-(* Fourier_util *)
-let constant_fourier = constant ["fourier";"Fourier_util"]
-
-let coq_Rlt_zero_1 = lazy (constant_fourier "Rlt_zero_1")
-let coq_Rlt_zero_pos_plus1 = lazy (constant_fourier "Rlt_zero_pos_plus1")
-let coq_Rle_zero_pos_plus1 = lazy (constant_fourier "Rle_zero_pos_plus1")
-let coq_Rlt_mult_inv_pos = lazy (constant_fourier "Rlt_mult_inv_pos")
-let coq_Rle_zero_zero = lazy (constant_fourier "Rle_zero_zero")
-let coq_Rle_zero_1 = lazy (constant_fourier "Rle_zero_1")
-let coq_Rle_mult_inv_pos = lazy (constant_fourier "Rle_mult_inv_pos")
-let coq_Rnot_lt0 = lazy (constant_fourier "Rnot_lt0")
-let coq_Rle_not_lt = lazy (constant_fourier "Rle_not_lt")
-let coq_Rfourier_gt_to_lt = lazy (constant_fourier "Rfourier_gt_to_lt")
-let coq_Rfourier_ge_to_le = lazy (constant_fourier "Rfourier_ge_to_le")
-let coq_Rfourier_eqLR_to_le = lazy (constant_fourier "Rfourier_eqLR_to_le")
-let coq_Rfourier_eqRL_to_le = lazy (constant_fourier "Rfourier_eqRL_to_le")
-
-let coq_Rfourier_not_ge_lt = lazy (constant_fourier "Rfourier_not_ge_lt")
-let coq_Rfourier_not_gt_le = lazy (constant_fourier "Rfourier_not_gt_le")
-let coq_Rfourier_not_le_gt = lazy (constant_fourier "Rfourier_not_le_gt")
-let coq_Rfourier_not_lt_ge = lazy (constant_fourier "Rfourier_not_lt_ge")
-let coq_Rfourier_lt = lazy (constant_fourier "Rfourier_lt")
-let coq_Rfourier_le = lazy (constant_fourier "Rfourier_le")
-let coq_Rfourier_lt_lt = lazy (constant_fourier "Rfourier_lt_lt")
-let coq_Rfourier_lt_le = lazy (constant_fourier "Rfourier_lt_le")
-let coq_Rfourier_le_lt = lazy (constant_fourier "Rfourier_le_lt")
-let coq_Rfourier_le_le = lazy (constant_fourier "Rfourier_le_le")
-let coq_Rnot_lt_lt = lazy (constant_fourier "Rnot_lt_lt")
-let coq_Rnot_le_le = lazy (constant_fourier "Rnot_le_le")
-let coq_Rlt_not_le_frac_opp = lazy (constant_fourier "Rlt_not_le_frac_opp")
-
-(******************************************************************************
-Construction de la preuve en cas de succès de la méthode de Fourier,
-i.e. on obtient une contradiction.
-*)
-let is_int x = (x.den)=1
-;;
-
-(* fraction = couple (num,den) *)
-let rational_to_fraction x= (x.num,x.den)
-;;
-
-(* traduction -3 -> (Ropp (Rplus R1 (Rplus R1 R1)))
-*)
-let int_to_real n =
- let nn=abs n in
- if nn=0
- then get coq_R0
- else
- (let s=ref (get coq_R1) in
- for _i = 1 to (nn-1) do s:=mkApp (get coq_Rplus,[|get coq_R1;!s|]) done;
- if n<0 then mkApp (get coq_Ropp, [|!s|]) else !s)
-;;
-(* -1/2 -> (Rmult (Ropp R1) (Rinv (Rplus R1 R1)))
-*)
-let rational_to_real x =
- let (n,d)=rational_to_fraction x in
- mkApp (get coq_Rmult,
- [|int_to_real n;mkApp(get coq_Rinv,[|int_to_real d|])|])
-;;
-
-(* preuve que 0<n*1/d
-*)
-let tac_zero_inf_pos gl (n,d) =
- let get = eget in
- let tacn=ref (apply (get coq_Rlt_zero_1)) in
- let tacd=ref (apply (get coq_Rlt_zero_1)) in
- for _i = 1 to n - 1 do
- tacn:=(Tacticals.New.tclTHEN (apply (get coq_Rlt_zero_pos_plus1)) !tacn); done;
- for _i = 1 to d - 1 do
- tacd:=(Tacticals.New.tclTHEN (apply (get coq_Rlt_zero_pos_plus1)) !tacd); done;
- (Tacticals.New.tclTHENS (apply (get coq_Rlt_mult_inv_pos)) [!tacn;!tacd])
-;;
-
-(* preuve que 0<=n*1/d
-*)
-let tac_zero_infeq_pos gl (n,d)=
- let get = eget in
- let tacn=ref (if n=0
- then (apply (get coq_Rle_zero_zero))
- else (apply (get coq_Rle_zero_1))) in
- let tacd=ref (apply (get coq_Rlt_zero_1)) in
- for _i = 1 to n - 1 do
- tacn:=(Tacticals.New.tclTHEN (apply (get coq_Rle_zero_pos_plus1)) !tacn); done;
- for _i = 1 to d - 1 do
- tacd:=(Tacticals.New.tclTHEN (apply (get coq_Rlt_zero_pos_plus1)) !tacd); done;
- (Tacticals.New.tclTHENS (apply (get coq_Rle_mult_inv_pos)) [!tacn;!tacd])
-;;
-
-(* preuve que 0<(-n)*(1/d) => False
-*)
-let tac_zero_inf_false gl (n,d) =
- let get = eget in
-if n=0 then (apply (get coq_Rnot_lt0))
- else
- (Tacticals.New.tclTHEN (apply (get coq_Rle_not_lt))
- (tac_zero_infeq_pos gl (-n,d)))
-;;
-
-(* preuve que 0<=(-n)*(1/d) => False
-*)
-let tac_zero_infeq_false gl (n,d) =
- let get = eget in
- (Tacticals.New.tclTHEN (apply (get coq_Rlt_not_le_frac_opp))
- (tac_zero_inf_pos gl (-n,d)))
-;;
-
-let exact = exact_check;;
-
-let tac_use h =
- let get = eget in
- let tac = exact (EConstr.of_constr h.hname) in
- match h.htype with
- "Rlt" -> tac
- |"Rle" -> tac
- |"Rgt" -> (Tacticals.New.tclTHEN (apply (get coq_Rfourier_gt_to_lt)) tac)
- |"Rge" -> (Tacticals.New.tclTHEN (apply (get coq_Rfourier_ge_to_le)) tac)
- |"eqTLR" -> (Tacticals.New.tclTHEN (apply (get coq_Rfourier_eqLR_to_le)) tac)
- |"eqTRL" -> (Tacticals.New.tclTHEN (apply (get coq_Rfourier_eqRL_to_le)) tac)
- |_->assert false
-;;
-
-(*
-let is_ineq (h,t) =
- match (Constr.kind t) with
- App (f,args) ->
- (match (string_of_R_constr f) with
- "Rlt" -> true
- | "Rgt" -> true
- | "Rle" -> true
- | "Rge" -> true
-(* Wrong:not in Rdefinitions: *) | "eqT" ->
- (match (string_of_R_constr args.(0)) with
- "R" -> true
- | _ -> false)
- | _ ->false)
- |_->false
-;;
-*)
-
-let list_of_sign s =
- let open Context.Named.Declaration in
- List.map (function LocalAssum (name, typ) -> name, typ
- | LocalDef (name, _, typ) -> name, typ)
- s;;
-
-let mkAppL a =
- let l = Array.to_list a in
- mkApp(List.hd l, Array.of_list (List.tl l))
-;;
-
-exception GoalDone
-
-(* Résolution d'inéquations linéaires dans R *)
-let rec fourier () =
- Proofview.Goal.nf_enter begin fun gl ->
- let concl = Proofview.Goal.concl gl in
- let sigma = Tacmach.New.project gl in
- Coqlib.check_required_library ["Coq";"fourier";"Fourier"];
- let goal = Termops.strip_outer_cast sigma concl in
- let goal = EConstr.Unsafe.to_constr goal in
- let fhyp=Id.of_string "new_hyp_for_fourier" in
- (* si le but est une inéquation, on introduit son contraire,
- et le but à prouver devient False *)
- try
- match (Constr.kind goal) with
- App (f,args) ->
- let get = eget in
- (match (string_of_R_constr f) with
- "Rlt" ->
- (Tacticals.New.tclTHEN
- (Tacticals.New.tclTHEN (apply (get coq_Rfourier_not_ge_lt))
- (intro_using fhyp))
- (fourier ()))
- |"Rle" ->
- (Tacticals.New.tclTHEN
- (Tacticals.New.tclTHEN (apply (get coq_Rfourier_not_gt_le))
- (intro_using fhyp))
- (fourier ()))
- |"Rgt" ->
- (Tacticals.New.tclTHEN
- (Tacticals.New.tclTHEN (apply (get coq_Rfourier_not_le_gt))
- (intro_using fhyp))
- (fourier ()))
- |"Rge" ->
- (Tacticals.New.tclTHEN
- (Tacticals.New.tclTHEN (apply (get coq_Rfourier_not_lt_ge))
- (intro_using fhyp))
- (fourier ()))
- |_-> raise GoalDone)
- |_-> raise GoalDone
- with GoalDone ->
- (* les hypothèses *)
- let hyps = List.map (fun (h,t)-> (EConstr.mkVar h,t))
- (list_of_sign (Proofview.Goal.hyps gl)) in
- let lineq =ref [] in
- List.iter (fun h -> try (lineq:=(ineq1_of_constr h)@(!lineq))
- with NoIneq -> ())
- hyps;
- (* lineq = les inéquations découlant des hypothèses *)
- if !lineq=[] then CErrors.user_err Pp.(str "No inequalities");
- let res=fourier_lineq (!lineq) in
- let tac=ref (Proofview.tclUNIT ()) in
- if res=[]
- then CErrors.user_err Pp.(str "fourier failed")
- (* l'algorithme de Fourier a réussi: on va en tirer une preuve Coq *)
- else (match res with
- [(cres,sres,lc)]->
- (* lc=coefficients multiplicateurs des inéquations
- qui donnent 0<cres ou 0<=cres selon sres *)
- (*print_string "Fourier's method can prove the goal...";flush stdout;*)
- let lutil=ref [] in
- List.iter
- (fun (h,c) ->
- if c<>r0
- then (lutil:=(h,c)::(!lutil)(*;
- print_rational(c);print_string " "*)))
- (List.combine (!lineq) lc);
- (* on construit la combinaison linéaire des inéquation *)
- (match (!lutil) with
- (h1,c1)::lutil ->
- let s=ref (h1.hstrict) in
- let t1=ref (mkAppL [|get coq_Rmult;
- rational_to_real c1;
- h1.hleft|]) in
- let t2=ref (mkAppL [|get coq_Rmult;
- rational_to_real c1;
- h1.hright|]) in
- List.iter (fun (h,c) ->
- s:=(!s)||(h.hstrict);
- t1:=(mkAppL [|get coq_Rplus;
- !t1;
- mkAppL [|get coq_Rmult;
- rational_to_real c;
- h.hleft|] |]);
- t2:=(mkAppL [|get coq_Rplus;
- !t2;
- mkAppL [|get coq_Rmult;
- rational_to_real c;
- h.hright|] |]))
- lutil;
- let ineq=mkAppL [|if (!s) then get coq_Rlt else get coq_Rle;
- !t1;
- !t2 |] in
- let tc=rational_to_real cres in
- (* puis sa preuve *)
- let get = eget in
- let tac1=ref (if h1.hstrict
- then (Tacticals.New.tclTHENS (apply (get coq_Rfourier_lt))
- [tac_use h1;
- tac_zero_inf_pos gl
- (rational_to_fraction c1)])
- else (Tacticals.New.tclTHENS (apply (get coq_Rfourier_le))
- [tac_use h1;
- tac_zero_inf_pos gl
- (rational_to_fraction c1)])) in
- s:=h1.hstrict;
- List.iter (fun (h,c)->
- (if (!s)
- then (if h.hstrict
- then tac1:=(Tacticals.New.tclTHENS (apply (get coq_Rfourier_lt_lt))
- [!tac1;tac_use h;
- tac_zero_inf_pos gl
- (rational_to_fraction c)])
- else tac1:=(Tacticals.New.tclTHENS (apply (get coq_Rfourier_lt_le))
- [!tac1;tac_use h;
- tac_zero_inf_pos gl
- (rational_to_fraction c)]))
- else (if h.hstrict
- then tac1:=(Tacticals.New.tclTHENS (apply (get coq_Rfourier_le_lt))
- [!tac1;tac_use h;
- tac_zero_inf_pos gl
- (rational_to_fraction c)])
- else tac1:=(Tacticals.New.tclTHENS (apply (get coq_Rfourier_le_le))
- [!tac1;tac_use h;
- tac_zero_inf_pos gl
- (rational_to_fraction c)])));
- s:=(!s)||(h.hstrict))
- lutil;
- let tac2= if sres
- then tac_zero_inf_false gl (rational_to_fraction cres)
- else tac_zero_infeq_false gl (rational_to_fraction cres)
- in
- tac:=(Tacticals.New.tclTHENS (cut (EConstr.of_constr ineq))
- [Tacticals.New.tclTHEN (change_concl
- (EConstr.of_constr (mkAppL [| cget coq_not; ineq|]
- )))
- (Tacticals.New.tclTHEN (apply (if sres then get coq_Rnot_lt_lt
- else get coq_Rnot_le_le))
- (Tacticals.New.tclTHENS (Equality.replace
- (EConstr.of_constr (mkAppL [|cget coq_Rminus;!t2;!t1|]
- ))
- (EConstr.of_constr tc))
- [tac2;
- (Tacticals.New.tclTHENS
- (Equality.replace
- (EConstr.of_constr (mkApp (cget coq_Rinv,
- [|cget coq_R1|])))
- (get coq_R1))
-(* en attendant Field, ça peut aider Ring de remplacer 1/1 par 1 ... *)
-
- [Tacticals.New.tclORELSE
- (* TODO : Ring.polynom []*) (Proofview.tclUNIT ())
- (Proofview.tclUNIT ());
- Tacticals.New.pf_constr_of_global (cget coq_sym_eqT) >>= fun symeq ->
- (Tacticals.New.tclTHEN (apply symeq)
- (apply (get coq_Rinv_1)))]
-
- )
- ]));
- !tac1]);
- tac:=(Tacticals.New.tclTHENS (cut (get coq_False))
- [Tacticals.New.tclTHEN intro (contradiction None);
- !tac])
- |_-> assert false) |_-> assert false
- );
-(* ((tclTHEN !tac (tclFAIL 1 (* 1 au hasard... *))) gl) *)
- !tac
-(* ((tclABSTRACT None !tac) gl) *)
- end
-;;
-
-(*
-let fourier_tac x gl =
- fourier gl
-;;
-
-let v_fourier = add_tactic "Fourier" fourier_tac
-*)
-
diff --git a/plugins/fourier/fourier_plugin.mlpack b/plugins/fourier/fourier_plugin.mlpack
deleted file mode 100644
index b6262f8aeb..0000000000
--- a/plugins/fourier/fourier_plugin.mlpack
+++ /dev/null
@@ -1,3 +0,0 @@
-Fourier
-FourierR
-G_fourier
diff --git a/plugins/fourier/g_fourier.ml4 b/plugins/fourier/g_fourier.ml4
deleted file mode 100644
index 44560ac18e..0000000000
--- a/plugins/fourier/g_fourier.ml4
+++ /dev/null
@@ -1,18 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-open Ltac_plugin
-open FourierR
-
-DECLARE PLUGIN "fourier_plugin"
-
-TACTIC EXTEND fourier
- [ "fourierz" ] -> [ fourier () ]
-END
diff --git a/plugins/funind/functional_principles_types.ml b/plugins/funind/functional_principles_types.ml
index 31496513a7..b2a528a1fd 100644
--- a/plugins/funind/functional_principles_types.ml
+++ b/plugins/funind/functional_principles_types.ml
@@ -322,8 +322,7 @@ let generate_functional_principle (evd: Evd.evar_map ref)
try
let f = funs.(i) in
- let env = Global.env () in
- let type_sort = Evarutil.evd_comb1 (Evd.fresh_sort_in_family env) evd InType in
+ let type_sort = Evarutil.evd_comb1 Evd.fresh_sort_in_family evd InType in
let new_sorts =
match sorts with
| None -> Array.make (Array.length funs) (type_sort)
@@ -344,7 +343,7 @@ let generate_functional_principle (evd: Evd.evar_map ref)
(* let id_of_f = Label.to_id (con_label f) in *)
let register_with_sort fam_sort =
let evd' = Evd.from_env (Global.env ()) in
- let evd',s = Evd.fresh_sort_in_family env evd' fam_sort in
+ let evd',s = Evd.fresh_sort_in_family evd' fam_sort in
let name = Indrec.make_elimination_ident base_new_princ_name fam_sort in
let evd',value = change_property_sort evd' s new_principle_type new_princ_name in
let evd' = fst (Typing.type_of ~refresh:true (Global.env ()) evd' (EConstr.of_constr value)) in
@@ -354,7 +353,7 @@ let generate_functional_principle (evd: Evd.evar_map ref)
Evd.const_univ_entry ~poly evd'
in
let ce = Declare.definition_entry ~univs value in
- ignore(
+ ignore(
Declare.declare_constant
name
(DefinitionEntry ce,
@@ -508,8 +507,8 @@ let make_scheme evd (fas : (pconstant*Sorts.family) list) : Safe_typing.private_
let i = ref (-1) in
let sorts =
List.rev_map (fun (_,x) ->
- Evarutil.evd_comb1 (Evd.fresh_sort_in_family env) evd x
- )
+ Evarutil.evd_comb1 Evd.fresh_sort_in_family evd x
+ )
fas
in
(* We create the first priciple by tactic *)
diff --git a/plugins/funind/glob_term_to_relation.ml b/plugins/funind/glob_term_to_relation.ml
index 6b9b103122..5fc4293cbb 100644
--- a/plugins/funind/glob_term_to_relation.ml
+++ b/plugins/funind/glob_term_to_relation.ml
@@ -1499,7 +1499,7 @@ let do_build_inductive
let _time2 = System.get_time () in
try
with_full_print
- (Flags.silently (ComInductive.do_mutual_inductive rel_inds (Flags.is_universe_polymorphism ()) false false))
+ (Flags.silently (ComInductive.do_mutual_inductive rel_inds (Flags.is_universe_polymorphism ()) false false ~uniform:ComInductive.NonUniformParameters))
Declarations.Finite
with
| UserError(s,msg) as e ->
diff --git a/plugins/funind/invfun.ml b/plugins/funind/invfun.ml
index 439274240f..ad11f853ca 100644
--- a/plugins/funind/invfun.ml
+++ b/plugins/funind/invfun.ml
@@ -351,7 +351,7 @@ let prove_fun_correct evd funs_constr graphs_constr schemes lemmas_types_infos i
Locusops.onConcl);
observe_tac ("toto ") tclIDTAC;
- (* introducing the the result of the graph and the equality hypothesis *)
+ (* introducing the result of the graph and the equality hypothesis *)
observe_tac "introducing" (tclMAP (fun x -> Proofview.V82.of_tactic (Simple.intro x)) [res;hres]);
(* replacing [res] with its value *)
observe_tac "rewriting res value" (Proofview.V82.of_tactic (Equality.rewriteLR (mkVar hres)));
diff --git a/plugins/funind/recdef.mli b/plugins/funind/recdef.mli
index b95d64ce9e..549f1fc0e4 100644
--- a/plugins/funind/recdef.mli
+++ b/plugins/funind/recdef.mli
@@ -14,6 +14,6 @@ bool ->
int -> Constrexpr.constr_expr -> (pconstant ->
Indfun_common.tcc_lemma_value ref ->
pconstant ->
- pconstant -> int -> EConstr.types -> int -> EConstr.constr -> 'a) -> Constrexpr.constr_expr list -> unit
+ pconstant -> int -> EConstr.types -> int -> EConstr.constr -> unit) -> Constrexpr.constr_expr list -> unit
diff --git a/plugins/ltac/coretactics.ml4 b/plugins/ltac/coretactics.mlg
index 61525cb49d..6388906f5e 100644
--- a/plugins/ltac/coretactics.ml4
+++ b/plugins/ltac/coretactics.mlg
@@ -8,6 +8,8 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
+{
+
open Util
open Locus
open Tactypes
@@ -18,147 +20,153 @@ open Tacarg
open Names
open Logic
+let wit_hyp = wit_var
+
+}
+
DECLARE PLUGIN "ltac_plugin"
(** Basic tactics *)
TACTIC EXTEND reflexivity
- [ "reflexivity" ] -> [ Tactics.intros_reflexivity ]
+| [ "reflexivity" ] -> { Tactics.intros_reflexivity }
END
TACTIC EXTEND exact
- [ "exact" casted_constr(c) ] -> [ Tactics.exact_no_check c ]
+| [ "exact" casted_constr(c) ] -> { Tactics.exact_no_check c }
END
TACTIC EXTEND assumption
- [ "assumption" ] -> [ Tactics.assumption ]
+| [ "assumption" ] -> { Tactics.assumption }
END
TACTIC EXTEND etransitivity
- [ "etransitivity" ] -> [ Tactics.intros_transitivity None ]
+| [ "etransitivity" ] -> { Tactics.intros_transitivity None }
END
TACTIC EXTEND cut
- [ "cut" constr(c) ] -> [ Tactics.cut c ]
+| [ "cut" constr(c) ] -> { Tactics.cut c }
END
TACTIC EXTEND exact_no_check
- [ "exact_no_check" constr(c) ] -> [ Tactics.exact_no_check c ]
+| [ "exact_no_check" constr(c) ] -> { Tactics.exact_no_check c }
END
TACTIC EXTEND vm_cast_no_check
- [ "vm_cast_no_check" constr(c) ] -> [ Tactics.vm_cast_no_check c ]
+| [ "vm_cast_no_check" constr(c) ] -> { Tactics.vm_cast_no_check c }
END
TACTIC EXTEND native_cast_no_check
- [ "native_cast_no_check" constr(c) ] -> [ Tactics.native_cast_no_check c ]
+| [ "native_cast_no_check" constr(c) ] -> { Tactics.native_cast_no_check c }
END
TACTIC EXTEND casetype
- [ "casetype" constr(c) ] -> [ Tactics.case_type c ]
+| [ "casetype" constr(c) ] -> { Tactics.case_type c }
END
TACTIC EXTEND elimtype
- [ "elimtype" constr(c) ] -> [ Tactics.elim_type c ]
+| [ "elimtype" constr(c) ] -> { Tactics.elim_type c }
END
TACTIC EXTEND lapply
- [ "lapply" constr(c) ] -> [ Tactics.cut_and_apply c ]
+| [ "lapply" constr(c) ] -> { Tactics.cut_and_apply c }
END
TACTIC EXTEND transitivity
- [ "transitivity" constr(c) ] -> [ Tactics.intros_transitivity (Some c) ]
+| [ "transitivity" constr(c) ] -> { Tactics.intros_transitivity (Some c) }
END
(** Left *)
TACTIC EXTEND left
- [ "left" ] -> [ Tactics.left_with_bindings false NoBindings ]
+| [ "left" ] -> { Tactics.left_with_bindings false NoBindings }
END
TACTIC EXTEND eleft
- [ "eleft" ] -> [ Tactics.left_with_bindings true NoBindings ]
+| [ "eleft" ] -> { Tactics.left_with_bindings true NoBindings }
END
TACTIC EXTEND left_with
- [ "left" "with" bindings(bl) ] -> [
+| [ "left" "with" bindings(bl) ] -> {
Tacticals.New.tclDELAYEDWITHHOLES false bl (fun bl -> Tactics.left_with_bindings false bl)
- ]
+ }
END
TACTIC EXTEND eleft_with
- [ "eleft" "with" bindings(bl) ] -> [
+| [ "eleft" "with" bindings(bl) ] -> {
Tacticals.New.tclDELAYEDWITHHOLES true bl (fun bl -> Tactics.left_with_bindings true bl)
- ]
+ }
END
(** Right *)
TACTIC EXTEND right
- [ "right" ] -> [ Tactics.right_with_bindings false NoBindings ]
+| [ "right" ] -> { Tactics.right_with_bindings false NoBindings }
END
TACTIC EXTEND eright
- [ "eright" ] -> [ Tactics.right_with_bindings true NoBindings ]
+| [ "eright" ] -> { Tactics.right_with_bindings true NoBindings }
END
TACTIC EXTEND right_with
- [ "right" "with" bindings(bl) ] -> [
+| [ "right" "with" bindings(bl) ] -> {
Tacticals.New.tclDELAYEDWITHHOLES false bl (fun bl -> Tactics.right_with_bindings false bl)
- ]
+ }
END
TACTIC EXTEND eright_with
- [ "eright" "with" bindings(bl) ] -> [
+| [ "eright" "with" bindings(bl) ] -> {
Tacticals.New.tclDELAYEDWITHHOLES true bl (fun bl -> Tactics.right_with_bindings true bl)
- ]
+ }
END
(** Constructor *)
TACTIC EXTEND constructor
- [ "constructor" ] -> [ Tactics.any_constructor false None ]
-| [ "constructor" int_or_var(i) ] -> [
+| [ "constructor" ] -> { Tactics.any_constructor false None }
+| [ "constructor" int_or_var(i) ] -> {
Tactics.constructor_tac false None i NoBindings
- ]
-| [ "constructor" int_or_var(i) "with" bindings(bl) ] -> [
+ }
+| [ "constructor" int_or_var(i) "with" bindings(bl) ] -> {
let tac bl = Tactics.constructor_tac false None i bl in
Tacticals.New.tclDELAYEDWITHHOLES false bl tac
- ]
+ }
END
TACTIC EXTEND econstructor
- [ "econstructor" ] -> [ Tactics.any_constructor true None ]
-| [ "econstructor" int_or_var(i) ] -> [
+| [ "econstructor" ] -> { Tactics.any_constructor true None }
+| [ "econstructor" int_or_var(i) ] -> {
Tactics.constructor_tac true None i NoBindings
- ]
-| [ "econstructor" int_or_var(i) "with" bindings(bl) ] -> [
+ }
+| [ "econstructor" int_or_var(i) "with" bindings(bl) ] -> {
let tac bl = Tactics.constructor_tac true None i bl in
Tacticals.New.tclDELAYEDWITHHOLES true bl tac
- ]
+ }
END
(** Specialize *)
TACTIC EXTEND specialize
- [ "specialize" constr_with_bindings(c) ] -> [
+| [ "specialize" constr_with_bindings(c) ] -> {
Tacticals.New.tclDELAYEDWITHHOLES false c (fun c -> Tactics.specialize c None)
- ]
-| [ "specialize" constr_with_bindings(c) "as" intropattern(ipat) ] -> [
+ }
+| [ "specialize" constr_with_bindings(c) "as" intropattern(ipat) ] -> {
Tacticals.New.tclDELAYEDWITHHOLES false c (fun c -> Tactics.specialize c (Some ipat))
- ]
+ }
END
TACTIC EXTEND symmetry
- [ "symmetry" ] -> [ Tactics.intros_symmetry {onhyps=Some[];concl_occs=AllOccurrences} ]
+| [ "symmetry" ] -> { Tactics.intros_symmetry {onhyps=Some[];concl_occs=AllOccurrences} }
END
TACTIC EXTEND symmetry_in
-| [ "symmetry" "in" in_clause(cl) ] -> [ Tactics.intros_symmetry cl ]
+| [ "symmetry" "in" in_clause(cl) ] -> { Tactics.intros_symmetry cl }
END
(** Split *)
+{
+
let rec delayed_list = function
| [] -> fun _ sigma -> (sigma, [])
| x :: l ->
@@ -167,147 +175,159 @@ let rec delayed_list = function
let (sigma, l) = delayed_list l env sigma in
(sigma, x :: l)
+}
+
TACTIC EXTEND split
- [ "split" ] -> [ Tactics.split_with_bindings false [NoBindings] ]
+| [ "split" ] -> { Tactics.split_with_bindings false [NoBindings] }
END
TACTIC EXTEND esplit
- [ "esplit" ] -> [ Tactics.split_with_bindings true [NoBindings] ]
+| [ "esplit" ] -> { Tactics.split_with_bindings true [NoBindings] }
END
TACTIC EXTEND split_with
- [ "split" "with" bindings(bl) ] -> [
+| [ "split" "with" bindings(bl) ] -> {
Tacticals.New.tclDELAYEDWITHHOLES false bl (fun bl -> Tactics.split_with_bindings false [bl])
- ]
+ }
END
TACTIC EXTEND esplit_with
- [ "esplit" "with" bindings(bl) ] -> [
+| [ "esplit" "with" bindings(bl) ] -> {
Tacticals.New.tclDELAYEDWITHHOLES true bl (fun bl -> Tactics.split_with_bindings true [bl])
- ]
+ }
END
TACTIC EXTEND exists
- [ "exists" ] -> [ Tactics.split_with_bindings false [NoBindings] ]
-| [ "exists" ne_bindings_list_sep(bll, ",") ] -> [
+| [ "exists" ] -> { Tactics.split_with_bindings false [NoBindings] }
+| [ "exists" ne_bindings_list_sep(bll, ",") ] -> {
Tacticals.New.tclDELAYEDWITHHOLES false (delayed_list bll) (fun bll -> Tactics.split_with_bindings false bll)
- ]
+ }
END
TACTIC EXTEND eexists
- [ "eexists" ] -> [ Tactics.split_with_bindings true [NoBindings] ]
-| [ "eexists" ne_bindings_list_sep(bll, ",") ] -> [
+| [ "eexists" ] -> { Tactics.split_with_bindings true [NoBindings] }
+| [ "eexists" ne_bindings_list_sep(bll, ",") ] -> {
Tacticals.New.tclDELAYEDWITHHOLES true (delayed_list bll) (fun bll -> Tactics.split_with_bindings true bll)
- ]
+ }
END
(** Intro *)
TACTIC EXTEND intros_until
- [ "intros" "until" quantified_hypothesis(h) ] -> [ Tactics.intros_until h ]
+| [ "intros" "until" quantified_hypothesis(h) ] -> { Tactics.intros_until h }
END
TACTIC EXTEND intro
-| [ "intro" ] -> [ Tactics.intro_move None MoveLast ]
-| [ "intro" ident(id) ] -> [ Tactics.intro_move (Some id) MoveLast ]
-| [ "intro" ident(id) "at" "top" ] -> [ Tactics.intro_move (Some id) MoveFirst ]
-| [ "intro" ident(id) "at" "bottom" ] -> [ Tactics.intro_move (Some id) MoveLast ]
-| [ "intro" ident(id) "after" hyp(h) ] -> [ Tactics.intro_move (Some id) (MoveAfter h) ]
-| [ "intro" ident(id) "before" hyp(h) ] -> [ Tactics.intro_move (Some id) (MoveBefore h) ]
-| [ "intro" "at" "top" ] -> [ Tactics.intro_move None MoveFirst ]
-| [ "intro" "at" "bottom" ] -> [ Tactics.intro_move None MoveLast ]
-| [ "intro" "after" hyp(h) ] -> [ Tactics.intro_move None (MoveAfter h) ]
-| [ "intro" "before" hyp(h) ] -> [ Tactics.intro_move None (MoveBefore h) ]
+| [ "intro" ] -> { Tactics.intro_move None MoveLast }
+| [ "intro" ident(id) ] -> { Tactics.intro_move (Some id) MoveLast }
+| [ "intro" ident(id) "at" "top" ] -> { Tactics.intro_move (Some id) MoveFirst }
+| [ "intro" ident(id) "at" "bottom" ] -> { Tactics.intro_move (Some id) MoveLast }
+| [ "intro" ident(id) "after" hyp(h) ] -> { Tactics.intro_move (Some id) (MoveAfter h) }
+| [ "intro" ident(id) "before" hyp(h) ] -> { Tactics.intro_move (Some id) (MoveBefore h) }
+| [ "intro" "at" "top" ] -> { Tactics.intro_move None MoveFirst }
+| [ "intro" "at" "bottom" ] -> { Tactics.intro_move None MoveLast }
+| [ "intro" "after" hyp(h) ] -> { Tactics.intro_move None (MoveAfter h) }
+| [ "intro" "before" hyp(h) ] -> { Tactics.intro_move None (MoveBefore h) }
END
(** Move *)
TACTIC EXTEND move
- [ "move" hyp(id) "at" "top" ] -> [ Tactics.move_hyp id MoveFirst ]
-| [ "move" hyp(id) "at" "bottom" ] -> [ Tactics.move_hyp id MoveLast ]
-| [ "move" hyp(id) "after" hyp(h) ] -> [ Tactics.move_hyp id (MoveAfter h) ]
-| [ "move" hyp(id) "before" hyp(h) ] -> [ Tactics.move_hyp id (MoveBefore h) ]
+| [ "move" hyp(id) "at" "top" ] -> { Tactics.move_hyp id MoveFirst }
+| [ "move" hyp(id) "at" "bottom" ] -> { Tactics.move_hyp id MoveLast }
+| [ "move" hyp(id) "after" hyp(h) ] -> { Tactics.move_hyp id (MoveAfter h) }
+| [ "move" hyp(id) "before" hyp(h) ] -> { Tactics.move_hyp id (MoveBefore h) }
END
(** Rename *)
TACTIC EXTEND rename
-| [ "rename" ne_rename_list_sep(ids, ",") ] -> [ Tactics.rename_hyp ids ]
+| [ "rename" ne_rename_list_sep(ids, ",") ] -> { Tactics.rename_hyp ids }
END
(** Revert *)
TACTIC EXTEND revert
- [ "revert" ne_hyp_list(hl) ] -> [ Tactics.revert hl ]
+| [ "revert" ne_hyp_list(hl) ] -> { Tactics.revert hl }
END
(** Simple induction / destruct *)
+{
+
let simple_induct h =
Tacticals.New.tclTHEN (Tactics.intros_until h)
(Tacticals.New.onLastHyp Tactics.simplest_elim)
+}
+
TACTIC EXTEND simple_induction
- [ "simple" "induction" quantified_hypothesis(h) ] -> [ simple_induct h ]
+| [ "simple" "induction" quantified_hypothesis(h) ] -> { simple_induct h }
END
+{
+
let simple_destruct h =
Tacticals.New.tclTHEN (Tactics.intros_until h)
(Tacticals.New.onLastHyp Tactics.simplest_case)
+}
+
TACTIC EXTEND simple_destruct
- [ "simple" "destruct" quantified_hypothesis(h) ] -> [ simple_destruct h ]
+| [ "simple" "destruct" quantified_hypothesis(h) ] -> { simple_destruct h }
END
(** Double induction *)
TACTIC EXTEND double_induction
- [ "double" "induction" quantified_hypothesis(h1) quantified_hypothesis(h2) ] ->
- [ Elim.h_double_induction h1 h2 ]
+| [ "double" "induction" quantified_hypothesis(h1) quantified_hypothesis(h2) ] ->
+ { Elim.h_double_induction h1 h2 }
END
(* Admit *)
TACTIC EXTEND admit
- [ "admit" ] -> [ Proofview.give_up ]
+|[ "admit" ] -> { Proofview.give_up }
END
(* Fix *)
TACTIC EXTEND fix
- [ "fix" ident(id) natural(n) ] -> [ Tactics.fix id n ]
+| [ "fix" ident(id) natural(n) ] -> { Tactics.fix id n }
END
(* Cofix *)
TACTIC EXTEND cofix
- [ "cofix" ident(id) ] -> [ Tactics.cofix id ]
+| [ "cofix" ident(id) ] -> { Tactics.cofix id }
END
(* Clear *)
TACTIC EXTEND clear
- [ "clear" hyp_list(ids) ] -> [
+| [ "clear" hyp_list(ids) ] -> {
if List.is_empty ids then Tactics.keep []
else Tactics.clear ids
- ]
-| [ "clear" "-" ne_hyp_list(ids) ] -> [ Tactics.keep ids ]
+ }
+| [ "clear" "-" ne_hyp_list(ids) ] -> { Tactics.keep ids }
END
(* Clearbody *)
TACTIC EXTEND clearbody
- [ "clearbody" ne_hyp_list(ids) ] -> [ Tactics.clear_body ids ]
+| [ "clearbody" ne_hyp_list(ids) ] -> { Tactics.clear_body ids }
END
(* Generalize dependent *)
TACTIC EXTEND generalize_dependent
- [ "generalize" "dependent" constr(c) ] -> [ Tactics.generalize_dep c ]
+| [ "generalize" "dependent" constr(c) ] -> { Tactics.generalize_dep c }
END
(* Table of "pervasives" macros tactics (e.g. auto, simpl, etc.) *)
+{
+
open Tacexpr
let initial_atomic () =
@@ -364,3 +384,5 @@ let initial_tacticals () =
]
let () = Mltop.declare_cache_obj initial_tacticals "ltac_plugin"
+
+}
diff --git a/plugins/ltac/extraargs.ml4 b/plugins/ltac/extraargs.ml4
index dae2582bd4..dbbdbfa396 100644
--- a/plugins/ltac/extraargs.ml4
+++ b/plugins/ltac/extraargs.ml4
@@ -297,25 +297,6 @@ END
(* spiwack: the print functions are incomplete, but I don't know what they are
used for *)
-let pr_r_nat_field natf =
- str "nat " ++
- match natf with
- | Retroknowledge.NatType -> str "type"
- | Retroknowledge.NatPlus -> str "plus"
- | Retroknowledge.NatTimes -> str "times"
-
-let pr_r_n_field nf =
- str "binary N " ++
- match nf with
- | Retroknowledge.NPositive -> str "positive"
- | Retroknowledge.NType -> str "type"
- | Retroknowledge.NTwice -> str "twice"
- | Retroknowledge.NTwicePlusOne -> str "twice plus one"
- | Retroknowledge.NPhi -> str "phi"
- | Retroknowledge.NPhiInv -> str "phi inv"
- | Retroknowledge.NPlus -> str "plus"
- | Retroknowledge.NTimes -> str "times"
-
let pr_r_int31_field i31f =
str "int31 " ++
match i31f with
@@ -353,26 +334,6 @@ let pr_retroknowledge_field f =
| Retroknowledge.KInt31 (group, i31f) -> (pr_r_int31_field i31f) ++
spc () ++ str "in " ++ qs group
-VERNAC ARGUMENT EXTEND retroknowledge_nat
-PRINTED BY pr_r_nat_field
-| [ "nat" "type" ] -> [ Retroknowledge.NatType ]
-| [ "nat" "plus" ] -> [ Retroknowledge.NatPlus ]
-| [ "nat" "times" ] -> [ Retroknowledge.NatTimes ]
-END
-
-
-VERNAC ARGUMENT EXTEND retroknowledge_binary_n
-PRINTED BY pr_r_n_field
-| [ "binary" "N" "positive" ] -> [ Retroknowledge.NPositive ]
-| [ "binary" "N" "type" ] -> [ Retroknowledge.NType ]
-| [ "binary" "N" "twice" ] -> [ Retroknowledge.NTwice ]
-| [ "binary" "N" "twice" "plus" "one" ] -> [ Retroknowledge.NTwicePlusOne ]
-| [ "binary" "N" "phi" ] -> [ Retroknowledge.NPhi ]
-| [ "binary" "N" "phi" "inv" ] -> [ Retroknowledge.NPhiInv ]
-| [ "binary" "N" "plus" ] -> [ Retroknowledge.NPlus ]
-| [ "binary" "N" "times" ] -> [ Retroknowledge.NTimes ]
-END
-
VERNAC ARGUMENT EXTEND retroknowledge_int31
PRINTED BY pr_r_int31_field
| [ "int31" "bits" ] -> [ Retroknowledge.Int31Bits ]
diff --git a/plugins/ltac/extraargs.mli b/plugins/ltac/extraargs.mli
index 7371478848..e477b12cd3 100644
--- a/plugins/ltac/extraargs.mli
+++ b/plugins/ltac/extraargs.mli
@@ -14,12 +14,12 @@ open Constrexpr
open Glob_term
val wit_orient : bool Genarg.uniform_genarg_type
-val orient : bool Pcoq.Gram.entry
+val orient : bool Pcoq.Entry.t
val pr_orient : bool -> Pp.t
val wit_rename : (Id.t * Id.t) Genarg.uniform_genarg_type
-val occurrences : (int list Locus.or_var) Pcoq.Gram.entry
+val occurrences : (int list Locus.or_var) Pcoq.Entry.t
val wit_occurrences : (int list Locus.or_var, int list Locus.or_var, int list) Genarg.genarg_type
val pr_occurrences : int list Locus.or_var -> Pp.t
val occurrences_of : int list -> Locus.occurrences
@@ -46,8 +46,8 @@ val wit_casted_constr :
Tacexpr.glob_constr_and_expr,
EConstr.t) Genarg.genarg_type
-val glob : constr_expr Pcoq.Gram.entry
-val lglob : constr_expr Pcoq.Gram.entry
+val glob : constr_expr Pcoq.Entry.t
+val lglob : constr_expr Pcoq.Entry.t
type 'id gen_place= ('id * Locus.hyp_location_flag,unit) location
@@ -55,10 +55,10 @@ type loc_place = lident gen_place
type place = Id.t gen_place
val wit_hloc : (loc_place, loc_place, place) Genarg.genarg_type
-val hloc : loc_place Pcoq.Gram.entry
+val hloc : loc_place Pcoq.Entry.t
val pr_hloc : loc_place -> Pp.t
-val by_arg_tac : Tacexpr.raw_tactic_expr option Pcoq.Gram.entry
+val by_arg_tac : Tacexpr.raw_tactic_expr option Pcoq.Entry.t
val wit_by_arg_tac :
(raw_tactic_expr option,
glob_tactic_expr option,
@@ -68,13 +68,13 @@ val pr_by_arg_tac :
(int * Notation_gram.parenRelation -> raw_tactic_expr -> Pp.t) ->
raw_tactic_expr option -> Pp.t
-val test_lpar_id_colon : unit Pcoq.Gram.entry
+val test_lpar_id_colon : unit Pcoq.Entry.t
val wit_test_lpar_id_colon : (unit, unit, unit) Genarg.genarg_type
(** Spiwack: Primitive for retroknowledge registration *)
-val retroknowledge_field : Retroknowledge.field Pcoq.Gram.entry
+val retroknowledge_field : Retroknowledge.field Pcoq.Entry.t
val wit_retroknowledge_field : (Retroknowledge.field, unit, unit) Genarg.genarg_type
val wit_in_clause :
diff --git a/plugins/ltac/extratactics.ml4 b/plugins/ltac/extratactics.ml4
index 660e29ca82..dc027c4041 100644
--- a/plugins/ltac/extratactics.ml4
+++ b/plugins/ltac/extratactics.ml4
@@ -293,7 +293,7 @@ open Vars
let constr_flags () = {
Pretyping.use_typeclasses = true;
- Pretyping.solve_unification_constraints = true;
+ Pretyping.solve_unification_constraints = Pfedit.use_unification_heuristics ();
Pretyping.use_hook = Pfedit.solve_by_implicit_tactic ();
Pretyping.fail_evar = false;
Pretyping.expand_evars = true }
@@ -604,8 +604,11 @@ let subst_var_with_hole occ tid t =
else
(incr locref;
DAst.make ~loc:(Loc.make_loc (!locref,0)) @@
- GHole (Evar_kinds.QuestionMark(Evar_kinds.Define true,Anonymous),
- IntroAnonymous, None)))
+ GHole (Evar_kinds.QuestionMark {
+ Evar_kinds.qm_obligation=Evar_kinds.Define true;
+ Evar_kinds.qm_name=Anonymous;
+ Evar_kinds.qm_record_field=None;
+ }, IntroAnonymous, None)))
else x
| _ -> map_glob_constr_left_to_right substrec x in
let t' = substrec t
@@ -616,13 +619,21 @@ let subst_hole_with_term occ tc t =
let locref = ref 0 in
let occref = ref occ in
let rec substrec c = match DAst.get c with
- | GHole (Evar_kinds.QuestionMark(Evar_kinds.Define true,Anonymous),IntroAnonymous,s) ->
+ | GHole (Evar_kinds.QuestionMark {
+ Evar_kinds.qm_obligation=Evar_kinds.Define true;
+ Evar_kinds.qm_name=Anonymous;
+ Evar_kinds.qm_record_field=None;
+ }, IntroAnonymous, s) ->
decr occref;
if Int.equal !occref 0 then tc
else
(incr locref;
DAst.make ~loc:(Loc.make_loc (!locref,0)) @@
- GHole (Evar_kinds.QuestionMark(Evar_kinds.Define true,Anonymous),IntroAnonymous,s))
+ GHole (Evar_kinds.QuestionMark {
+ Evar_kinds.qm_obligation=Evar_kinds.Define true;
+ Evar_kinds.qm_name=Anonymous;
+ Evar_kinds.qm_record_field=None;
+ },IntroAnonymous,s))
| _ -> map_glob_constr_left_to_right substrec c
in
substrec t
diff --git a/plugins/ltac/g_eqdecide.ml4 b/plugins/ltac/g_eqdecide.mlg
index 2251a66204..e57afe3e33 100644
--- a/plugins/ltac/g_eqdecide.ml4
+++ b/plugins/ltac/g_eqdecide.mlg
@@ -14,15 +14,19 @@
(* by Eduardo Gimenez *)
(************************************************************************)
+{
+
open Eqdecide
open Stdarg
+}
+
DECLARE PLUGIN "ltac_plugin"
TACTIC EXTEND decide_equality
-| [ "decide" "equality" ] -> [ decideEqualityGoal ]
+| [ "decide" "equality" ] -> { decideEqualityGoal }
END
TACTIC EXTEND compare
-| [ "compare" constr(c1) constr(c2) ] -> [ compare c1 c2 ]
+| [ "compare" constr(c1) constr(c2) ] -> { compare c1 c2 }
END
diff --git a/plugins/ltac/g_ltac.ml4 b/plugins/ltac/g_ltac.ml4
index 620f147077..c13bd69daf 100644
--- a/plugins/ltac/g_ltac.ml4
+++ b/plugins/ltac/g_ltac.ml4
@@ -46,10 +46,10 @@ let reference_to_id qid =
CErrors.user_err ?loc:qid.CAst.loc
(str "This expression should be a simple identifier.")
-let tactic_mode = Gram.entry_create "vernac:tactic_command"
+let tactic_mode = Entry.create "vernac:tactic_command"
let new_entry name =
- let e = Gram.entry_create name in
+ let e = Entry.create name in
e
let toplevel_selector = new_entry "vernac:toplevel_selector"
@@ -287,12 +287,14 @@ GEXTEND Gram
(* Definitions for tactics *)
tacdef_body:
- [ [ name = Constr.global; it=LIST1 input_fun; redef = ltac_def_kind; body = tactic_expr ->
+ [ [ name = Constr.global; it=LIST1 input_fun;
+ redef = ltac_def_kind; body = tactic_expr ->
if redef then Tacexpr.TacticRedefinition (name, TacFun (it, body))
else
let id = reference_to_id name in
Tacexpr.TacticDefinition (id, TacFun (it, body))
- | name = Constr.global; redef = ltac_def_kind; body = tactic_expr ->
+ | name = Constr.global; redef = ltac_def_kind;
+ body = tactic_expr ->
if redef then Tacexpr.TacticRedefinition (name, body)
else
let id = reference_to_id name in
@@ -468,7 +470,8 @@ VERNAC COMMAND FUNCTIONAL EXTEND VernacTacticNotation
[ VtSideff [], VtNow ] ->
[ fun ~atts ~st -> let open Vernacinterp in
let n = Option.default 0 n in
- Tacentries.add_tactic_notation (Locality.make_module_locality atts.locality) n r e;
+ let deprecation = atts.deprecated in
+ Tacentries.add_tactic_notation (Locality.make_module_locality atts.locality) n ?deprecation r e;
st
]
END
@@ -512,7 +515,8 @@ VERNAC COMMAND FUNCTIONAL EXTEND VernacDeclareTacticDefinition
| TacticDefinition ({CAst.v=r},_) -> r
| TacticRedefinition (qid,_) -> qualid_basename qid) l), VtLater
] -> [ fun ~atts ~st -> let open Vernacinterp in
- Tacentries.register_ltac (Locality.make_module_locality atts.locality) l;
+ let deprecation = atts.deprecated in
+ Tacentries.register_ltac (Locality.make_module_locality atts.locality) ?deprecation l;
st
]
END
diff --git a/plugins/ltac/g_tactic.ml4 b/plugins/ltac/g_tactic.mlg
index 31bc34a325..2e1ce814aa 100644
--- a/plugins/ltac/g_tactic.ml4
+++ b/plugins/ltac/g_tactic.mlg
@@ -8,6 +8,8 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
+{
+
open Pp
open CErrors
open Util
@@ -215,486 +217,488 @@ let warn_deprecated_eqn_syntax =
open Pvernac.Vernac_
-GEXTEND Gram
+}
+
+GRAMMAR EXTEND Gram
GLOBAL: simple_tactic constr_with_bindings quantified_hypothesis
bindings red_expr int_or_var open_constr uconstr
simple_intropattern in_clause clause_dft_concl hypident destruction_arg;
int_or_var:
- [ [ n = integer -> ArgArg n
- | id = identref -> ArgVar id ] ]
+ [ [ n = integer -> { ArgArg n }
+ | id = identref -> { ArgVar id } ] ]
;
nat_or_var:
- [ [ n = natural -> ArgArg n
- | id = identref -> ArgVar id ] ]
+ [ [ n = natural -> { ArgArg n }
+ | id = identref -> { ArgVar id } ] ]
;
(* An identifier or a quotation meta-variable *)
id_or_meta:
- [ [ id = identref -> id ] ]
+ [ [ id = identref -> { id } ] ]
;
open_constr:
- [ [ c = constr -> c ] ]
+ [ [ c = constr -> { c } ] ]
;
uconstr:
- [ [ c = constr -> c ] ]
+ [ [ c = constr -> { c } ] ]
;
destruction_arg:
- [ [ n = natural -> (None,ElimOnAnonHyp n)
+ [ [ n = natural -> { (None,ElimOnAnonHyp n) }
| test_lpar_id_rpar; c = constr_with_bindings ->
- (Some false,destruction_arg_of_constr c)
- | c = constr_with_bindings_arg -> on_snd destruction_arg_of_constr c
+ { (Some false,destruction_arg_of_constr c) }
+ | c = constr_with_bindings_arg -> { on_snd destruction_arg_of_constr c }
] ]
;
constr_with_bindings_arg:
- [ [ ">"; c = constr_with_bindings -> (Some true,c)
- | c = constr_with_bindings -> (None,c) ] ]
+ [ [ ">"; c = constr_with_bindings -> { (Some true,c) }
+ | c = constr_with_bindings -> { (None,c) } ] ]
;
quantified_hypothesis:
- [ [ id = ident -> NamedHyp id
- | n = natural -> AnonHyp n ] ]
+ [ [ id = ident -> { NamedHyp id }
+ | n = natural -> { AnonHyp n } ] ]
;
conversion:
- [ [ c = constr -> (None, c)
- | c1 = constr; "with"; c2 = constr -> (Some (AllOccurrences,c1),c2)
+ [ [ c = constr -> { (None, c) }
+ | c1 = constr; "with"; c2 = constr -> { (Some (AllOccurrences,c1),c2) }
| c1 = constr; "at"; occs = occs_nums; "with"; c2 = constr ->
- (Some (occs,c1), c2) ] ]
+ { (Some (occs,c1), c2) } ] ]
;
occs_nums:
- [ [ nl = LIST1 nat_or_var -> OnlyOccurrences nl
+ [ [ nl = LIST1 nat_or_var -> { OnlyOccurrences nl }
| "-"; n = nat_or_var; nl = LIST0 int_or_var ->
(* have used int_or_var instead of nat_or_var for compatibility *)
- AllOccurrencesBut (List.map (map_int_or_var abs) (n::nl)) ] ]
+ { AllOccurrencesBut (List.map (map_int_or_var abs) (n::nl)) } ] ]
;
occs:
- [ [ "at"; occs = occs_nums -> occs | -> AllOccurrences ] ]
+ [ [ "at"; occs = occs_nums -> { occs } | -> { AllOccurrences } ] ]
;
pattern_occ:
- [ [ c = constr; nl = occs -> (nl,c) ] ]
+ [ [ c = constr; nl = occs -> { (nl,c) } ] ]
;
ref_or_pattern_occ:
(* If a string, it is interpreted as a ref
(anyway a Coq string does not reduce) *)
- [ [ c = smart_global; nl = occs -> nl,Inl c
- | c = constr; nl = occs -> nl,Inr c ] ]
+ [ [ c = smart_global; nl = occs -> { nl,Inl c }
+ | c = constr; nl = occs -> { nl,Inr c } ] ]
;
unfold_occ:
- [ [ c = smart_global; nl = occs -> (nl,c) ] ]
+ [ [ c = smart_global; nl = occs -> { (nl,c) } ] ]
;
intropatterns:
- [ [ l = LIST0 nonsimple_intropattern -> l ]]
+ [ [ l = LIST0 nonsimple_intropattern -> { l } ] ]
;
ne_intropatterns:
- [ [ l = LIST1 nonsimple_intropattern -> l ]]
+ [ [ l = LIST1 nonsimple_intropattern -> { l } ] ]
;
or_and_intropattern:
- [ [ "["; tc = LIST1 intropatterns SEP "|"; "]" -> IntroOrPattern tc
- | "()" -> IntroAndPattern []
- | "("; si = simple_intropattern; ")" -> IntroAndPattern [si]
+ [ [ "["; tc = LIST1 intropatterns SEP "|"; "]" -> { IntroOrPattern tc }
+ | "()" -> { IntroAndPattern [] }
+ | "("; si = simple_intropattern; ")" -> { IntroAndPattern [si] }
| "("; si = simple_intropattern; ",";
tc = LIST1 simple_intropattern SEP "," ; ")" ->
- IntroAndPattern (si::tc)
+ { IntroAndPattern (si::tc) }
| "("; si = simple_intropattern; "&";
tc = LIST1 simple_intropattern SEP "&" ; ")" ->
(* (A & B & C) is translated into (A,(B,C)) *)
- let rec pairify = function
+ { let rec pairify = function
| ([]|[_]|[_;_]) as l -> l
| t::q -> [t; CAst.make ?loc:(loc_of_ne_list q) (IntroAction (IntroOrAndPattern (IntroAndPattern (pairify q))))]
- in IntroAndPattern (pairify (si::tc)) ] ]
+ in IntroAndPattern (pairify (si::tc)) } ] ]
;
equality_intropattern:
- [ [ "->" -> IntroRewrite true
- | "<-" -> IntroRewrite false
- | "[="; tc = intropatterns; "]" -> IntroInjection tc ] ]
+ [ [ "->" -> { IntroRewrite true }
+ | "<-" -> { IntroRewrite false }
+ | "[="; tc = intropatterns; "]" -> { IntroInjection tc } ] ]
;
naming_intropattern:
- [ [ prefix = pattern_ident -> IntroFresh prefix
- | "?" -> IntroAnonymous
- | id = ident -> IntroIdentifier id ] ]
+ [ [ prefix = pattern_ident -> { IntroFresh prefix }
+ | "?" -> { IntroAnonymous }
+ | id = ident -> { IntroIdentifier id } ] ]
;
nonsimple_intropattern:
- [ [ l = simple_intropattern -> l
- | "*" -> CAst.make ~loc:!@loc @@ IntroForthcoming true
- | "**" -> CAst.make ~loc:!@loc @@ IntroForthcoming false ]]
+ [ [ l = simple_intropattern -> { l }
+ | "*" -> { CAst.make ~loc @@ IntroForthcoming true }
+ | "**" -> { CAst.make ~loc @@ IntroForthcoming false } ] ]
;
simple_intropattern:
[ [ pat = simple_intropattern_closed;
- l = LIST0 ["%"; c = operconstr LEVEL "0" -> c] ->
- let {CAst.loc=loc0;v=pat} = pat in
+ l = LIST0 ["%"; c = operconstr LEVEL "0" -> { c } ] ->
+ { let {CAst.loc=loc0;v=pat} = pat in
let f c pat =
let loc1 = Constrexpr_ops.constr_loc c in
let loc = Loc.merge_opt loc0 loc1 in
IntroAction (IntroApplyOn (CAst.(make ?loc:loc1 c),CAst.(make ?loc pat))) in
- CAst.make ~loc:!@loc @@ List.fold_right f l pat ] ]
+ CAst.make ~loc @@ List.fold_right f l pat } ] ]
;
simple_intropattern_closed:
- [ [ pat = or_and_intropattern -> CAst.make ~loc:!@loc @@ IntroAction (IntroOrAndPattern pat)
- | pat = equality_intropattern -> CAst.make ~loc:!@loc @@ IntroAction pat
- | "_" -> CAst.make ~loc:!@loc @@ IntroAction IntroWildcard
- | pat = naming_intropattern -> CAst.make ~loc:!@loc @@ IntroNaming pat ] ]
+ [ [ pat = or_and_intropattern -> { CAst.make ~loc @@ IntroAction (IntroOrAndPattern pat) }
+ | pat = equality_intropattern -> { CAst.make ~loc @@ IntroAction pat }
+ | "_" -> { CAst.make ~loc @@ IntroAction IntroWildcard }
+ | pat = naming_intropattern -> { CAst.make ~loc @@ IntroNaming pat } ] ]
;
simple_binding:
- [ [ "("; id = ident; ":="; c = lconstr; ")" -> CAst.make ~loc:!@loc (NamedHyp id, c)
- | "("; n = natural; ":="; c = lconstr; ")" -> CAst.make ~loc:!@loc (AnonHyp n, c) ] ]
+ [ [ "("; id = ident; ":="; c = lconstr; ")" -> { CAst.make ~loc (NamedHyp id, c) }
+ | "("; n = natural; ":="; c = lconstr; ")" -> { CAst.make ~loc (AnonHyp n, c) } ] ]
;
bindings:
[ [ test_lpar_idnum_coloneq; bl = LIST1 simple_binding ->
- ExplicitBindings bl
- | bl = LIST1 constr -> ImplicitBindings bl ] ]
+ { ExplicitBindings bl }
+ | bl = LIST1 constr -> { ImplicitBindings bl } ] ]
;
constr_with_bindings:
- [ [ c = constr; l = with_bindings -> (c, l) ] ]
+ [ [ c = constr; l = with_bindings -> { (c, l) } ] ]
;
with_bindings:
- [ [ "with"; bl = bindings -> bl | -> NoBindings ] ]
+ [ [ "with"; bl = bindings -> { bl } | -> { NoBindings } ] ]
;
red_flags:
- [ [ IDENT "beta" -> [FBeta]
- | IDENT "iota" -> [FMatch;FFix;FCofix]
- | IDENT "match" -> [FMatch]
- | IDENT "fix" -> [FFix]
- | IDENT "cofix" -> [FCofix]
- | IDENT "zeta" -> [FZeta]
- | IDENT "delta"; d = delta_flag -> [d]
+ [ [ IDENT "beta" -> { [FBeta] }
+ | IDENT "iota" -> { [FMatch;FFix;FCofix] }
+ | IDENT "match" -> { [FMatch] }
+ | IDENT "fix" -> { [FFix] }
+ | IDENT "cofix" -> { [FCofix] }
+ | IDENT "zeta" -> { [FZeta] }
+ | IDENT "delta"; d = delta_flag -> { [d] }
] ]
;
delta_flag:
- [ [ "-"; "["; idl = LIST1 smart_global; "]" -> FDeltaBut idl
- | "["; idl = LIST1 smart_global; "]" -> FConst idl
- | -> FDeltaBut []
+ [ [ "-"; "["; idl = LIST1 smart_global; "]" -> { FDeltaBut idl }
+ | "["; idl = LIST1 smart_global; "]" -> { FConst idl }
+ | -> { FDeltaBut [] }
] ]
;
strategy_flag:
- [ [ s = LIST1 red_flags -> Redops.make_red_flag (List.flatten s)
- | d = delta_flag -> all_with d
+ [ [ s = LIST1 red_flags -> { Redops.make_red_flag (List.flatten s) }
+ | d = delta_flag -> { all_with d }
] ]
;
red_expr:
- [ [ IDENT "red" -> Red false
- | IDENT "hnf" -> Hnf
- | IDENT "simpl"; d = delta_flag; po = OPT ref_or_pattern_occ -> Simpl (all_with d,po)
- | IDENT "cbv"; s = strategy_flag -> Cbv s
- | IDENT "cbn"; s = strategy_flag -> Cbn s
- | IDENT "lazy"; s = strategy_flag -> Lazy s
- | IDENT "compute"; delta = delta_flag -> Cbv (all_with delta)
- | IDENT "vm_compute"; po = OPT ref_or_pattern_occ -> CbvVm po
- | IDENT "native_compute"; po = OPT ref_or_pattern_occ -> CbvNative po
- | IDENT "unfold"; ul = LIST1 unfold_occ SEP "," -> Unfold ul
- | IDENT "fold"; cl = LIST1 constr -> Fold cl
- | IDENT "pattern"; pl = LIST1 pattern_occ SEP"," -> Pattern pl
- | s = IDENT -> ExtraRedExpr s ] ]
+ [ [ IDENT "red" -> { Red false }
+ | IDENT "hnf" -> { Hnf }
+ | IDENT "simpl"; d = delta_flag; po = OPT ref_or_pattern_occ -> { Simpl (all_with d,po) }
+ | IDENT "cbv"; s = strategy_flag -> { Cbv s }
+ | IDENT "cbn"; s = strategy_flag -> { Cbn s }
+ | IDENT "lazy"; s = strategy_flag -> { Lazy s }
+ | IDENT "compute"; delta = delta_flag -> { Cbv (all_with delta) }
+ | IDENT "vm_compute"; po = OPT ref_or_pattern_occ -> { CbvVm po }
+ | IDENT "native_compute"; po = OPT ref_or_pattern_occ -> { CbvNative po }
+ | IDENT "unfold"; ul = LIST1 unfold_occ SEP "," -> { Unfold ul }
+ | IDENT "fold"; cl = LIST1 constr -> { Fold cl }
+ | IDENT "pattern"; pl = LIST1 pattern_occ SEP"," -> { Pattern pl }
+ | s = IDENT -> { ExtraRedExpr s } ] ]
;
hypident:
[ [ id = id_or_meta ->
- let id : lident = id in
- id,InHyp
+ { let id : lident = id in
+ id,InHyp }
| "("; IDENT "type"; IDENT "of"; id = id_or_meta; ")" ->
- let id : lident = id in
- id,InHypTypeOnly
+ { let id : lident = id in
+ id,InHypTypeOnly }
| "("; IDENT "value"; IDENT "of"; id = id_or_meta; ")" ->
- let id : lident = id in
- id,InHypValueOnly
+ { let id : lident = id in
+ id,InHypValueOnly }
] ]
;
hypident_occ:
- [ [ (id,l)=hypident; occs=occs ->
+ [ [ h=hypident; occs=occs ->
+ { let (id,l) = h in
let id : lident = id in
- ((occs,id),l) ] ]
+ ((occs,id),l) } ] ]
;
in_clause:
[ [ "*"; occs=occs ->
- {onhyps=None; concl_occs=occs}
+ { {onhyps=None; concl_occs=occs} }
| "*"; "|-"; occs=concl_occ ->
- {onhyps=None; concl_occs=occs}
+ { {onhyps=None; concl_occs=occs} }
| hl=LIST0 hypident_occ SEP","; "|-"; occs=concl_occ ->
- {onhyps=Some hl; concl_occs=occs}
+ { {onhyps=Some hl; concl_occs=occs} }
| hl=LIST0 hypident_occ SEP"," ->
- {onhyps=Some hl; concl_occs=NoOccurrences} ] ]
+ { {onhyps=Some hl; concl_occs=NoOccurrences} } ] ]
;
clause_dft_concl:
- [ [ "in"; cl = in_clause -> cl
- | occs=occs -> {onhyps=Some[]; concl_occs=occs}
- | -> all_concl_occs_clause ] ]
+ [ [ "in"; cl = in_clause -> { cl }
+ | occs=occs -> { {onhyps=Some[]; concl_occs=occs} }
+ | -> { all_concl_occs_clause } ] ]
;
clause_dft_all:
- [ [ "in"; cl = in_clause -> cl
- | -> {onhyps=None; concl_occs=AllOccurrences} ] ]
+ [ [ "in"; cl = in_clause -> { cl }
+ | -> { {onhyps=None; concl_occs=AllOccurrences} } ] ]
;
opt_clause:
- [ [ "in"; cl = in_clause -> Some cl
- | "at"; occs = occs_nums -> Some {onhyps=Some[]; concl_occs=occs}
- | -> None ] ]
+ [ [ "in"; cl = in_clause -> { Some cl }
+ | "at"; occs = occs_nums -> { Some {onhyps=Some[]; concl_occs=occs} }
+ | -> { None } ] ]
;
concl_occ:
- [ [ "*"; occs = occs -> occs
- | -> NoOccurrences ] ]
+ [ [ "*"; occs = occs -> { occs }
+ | -> { NoOccurrences } ] ]
;
in_hyp_list:
- [ [ "in"; idl = LIST1 id_or_meta -> idl
- | -> [] ] ]
+ [ [ "in"; idl = LIST1 id_or_meta -> { idl }
+ | -> { [] } ] ]
;
in_hyp_as:
- [ [ "in"; id = id_or_meta; ipat = as_ipat -> Some (id,ipat)
- | -> None ] ]
+ [ [ "in"; id = id_or_meta; ipat = as_ipat -> { Some (id,ipat) }
+ | -> { None } ] ]
;
orient:
- [ [ "->" -> true
- | "<-" -> false
- | -> true ]]
+ [ [ "->" -> { true }
+ | "<-" -> { false }
+ | -> { true } ] ]
;
simple_binder:
- [ [ na=name -> ([na],Default Explicit, CAst.make ~loc:!@loc @@
- CHole (Some (Evar_kinds.BinderType na.CAst.v), IntroAnonymous, None))
- | "("; nal=LIST1 name; ":"; c=lconstr; ")" -> (nal,Default Explicit,c)
+ [ [ na=name -> { ([na],Default Explicit, CAst.make ~loc @@
+ CHole (Some (Evar_kinds.BinderType na.CAst.v), IntroAnonymous, None)) }
+ | "("; nal=LIST1 name; ":"; c=lconstr; ")" -> { (nal,Default Explicit,c) }
] ]
;
fixdecl:
[ [ "("; id = ident; bl=LIST0 simple_binder; ann=fixannot;
- ":"; ty=lconstr; ")" -> (!@loc, id, bl, ann, ty) ] ]
+ ":"; ty=lconstr; ")" -> { (loc, id, bl, ann, ty) } ] ]
;
fixannot:
- [ [ "{"; IDENT "struct"; id=name; "}" -> Some id
- | -> None ] ]
+ [ [ "{"; IDENT "struct"; id=name; "}" -> { Some id }
+ | -> { None } ] ]
;
cofixdecl:
[ [ "("; id = ident; bl=LIST0 simple_binder; ":"; ty=lconstr; ")" ->
- (!@loc, id, bl, None, ty) ] ]
+ { (loc, id, bl, None, ty) } ] ]
;
bindings_with_parameters:
[ [ check_for_coloneq; "("; id = ident; bl = LIST0 simple_binder;
- ":="; c = lconstr; ")" -> (id, mkCLambdaN_simple bl c) ] ]
+ ":="; c = lconstr; ")" -> { (id, mkCLambdaN_simple bl c) } ] ]
;
eliminator:
- [ [ "using"; el = constr_with_bindings -> el ] ]
+ [ [ "using"; el = constr_with_bindings -> { el } ] ]
;
as_ipat:
- [ [ "as"; ipat = simple_intropattern -> Some ipat
- | -> None ] ]
+ [ [ "as"; ipat = simple_intropattern -> { Some ipat }
+ | -> { None } ] ]
;
or_and_intropattern_loc:
- [ [ ipat = or_and_intropattern -> ArgArg (CAst.make ~loc:!@loc ipat)
- | locid = identref -> ArgVar locid ] ]
+ [ [ ipat = or_and_intropattern -> { ArgArg (CAst.make ~loc ipat) }
+ | locid = identref -> { ArgVar locid } ] ]
;
as_or_and_ipat:
- [ [ "as"; ipat = or_and_intropattern_loc -> Some ipat
- | -> None ] ]
+ [ [ "as"; ipat = or_and_intropattern_loc -> { Some ipat }
+ | -> { None } ] ]
;
eqn_ipat:
- [ [ IDENT "eqn"; ":"; pat = naming_intropattern -> Some (CAst.make ~loc:!@loc pat)
+ [ [ IDENT "eqn"; ":"; pat = naming_intropattern -> { Some (CAst.make ~loc pat) }
| IDENT "_eqn"; ":"; pat = naming_intropattern ->
- let loc = !@loc in
- warn_deprecated_eqn_syntax ~loc "H"; Some (CAst.make ~loc pat)
+ { warn_deprecated_eqn_syntax ~loc "H"; Some (CAst.make ~loc pat) }
| IDENT "_eqn" ->
- let loc = !@loc in
- warn_deprecated_eqn_syntax ~loc "?"; Some (CAst.make ~loc IntroAnonymous)
- | -> None ] ]
+ { warn_deprecated_eqn_syntax ~loc "?"; Some (CAst.make ~loc IntroAnonymous) }
+ | -> { None } ] ]
;
as_name:
- [ [ "as"; id = ident ->Names.Name.Name id | -> Names.Name.Anonymous ] ]
+ [ [ "as"; id = ident -> { Names.Name.Name id } | -> { Names.Name.Anonymous } ] ]
;
by_tactic:
- [ [ "by"; tac = tactic_expr LEVEL "3" -> Some tac
- | -> None ] ]
+ [ [ "by"; tac = tactic_expr LEVEL "3" -> { Some tac }
+ | -> { None } ] ]
;
rewriter :
- [ [ "!"; c = constr_with_bindings_arg -> (Equality.RepeatPlus,c)
- | ["?"| LEFTQMARK]; c = constr_with_bindings_arg -> (Equality.RepeatStar,c)
- | n = natural; "!"; c = constr_with_bindings_arg -> (Equality.Precisely n,c)
- | n = natural; ["?" | LEFTQMARK]; c = constr_with_bindings_arg -> (Equality.UpTo n,c)
- | n = natural; c = constr_with_bindings_arg -> (Equality.Precisely n,c)
- | c = constr_with_bindings_arg -> (Equality.Precisely 1, c)
+ [ [ "!"; c = constr_with_bindings_arg -> { (Equality.RepeatPlus,c) }
+ | ["?" -> { () } | LEFTQMARK -> { () } ]; c = constr_with_bindings_arg -> { (Equality.RepeatStar,c) }
+ | n = natural; "!"; c = constr_with_bindings_arg -> { (Equality.Precisely n,c) }
+ | n = natural; ["?" -> { () } | LEFTQMARK -> { () } ]; c = constr_with_bindings_arg -> { (Equality.UpTo n,c) }
+ | n = natural; c = constr_with_bindings_arg -> { (Equality.Precisely n,c) }
+ | c = constr_with_bindings_arg -> { (Equality.Precisely 1, c) }
] ]
;
oriented_rewriter :
- [ [ b = orient; p = rewriter -> let (m,c) = p in (b,m,c) ] ]
+ [ [ b = orient; p = rewriter -> { let (m,c) = p in (b,m,c) } ] ]
;
induction_clause:
[ [ c = destruction_arg; pat = as_or_and_ipat; eq = eqn_ipat;
- cl = opt_clause -> (c,(eq,pat),cl) ] ]
+ cl = opt_clause -> { (c,(eq,pat),cl) } ] ]
;
induction_clause_list:
[ [ ic = LIST1 induction_clause SEP ","; el = OPT eliminator;
cl_tolerance = opt_clause ->
(* Condition for accepting "in" at the end by compatibility *)
- match ic,el,cl_tolerance with
+ { match ic,el,cl_tolerance with
| [c,pat,None],Some _,Some _ -> ([c,pat,cl_tolerance],el)
| _,_,Some _ -> err ()
- | _,_,None -> (ic,el) ]]
+ | _,_,None -> (ic,el) } ] ]
;
simple_tactic:
[ [
(* Basic tactics *)
IDENT "intros"; pl = ne_intropatterns ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacIntroPattern (false,pl))
+ { TacAtom (Loc.tag ~loc @@ TacIntroPattern (false,pl)) }
| IDENT "intros" ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacIntroPattern (false,[CAst.make ~loc:!@loc @@IntroForthcoming false]))
+ { TacAtom (Loc.tag ~loc @@ TacIntroPattern (false,[CAst.make ~loc @@IntroForthcoming false])) }
| IDENT "eintros"; pl = ne_intropatterns ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacIntroPattern (true,pl))
+ { TacAtom (Loc.tag ~loc @@ TacIntroPattern (true,pl)) }
| IDENT "apply"; cl = LIST1 constr_with_bindings_arg SEP ",";
- inhyp = in_hyp_as -> TacAtom (Loc.tag ~loc:!@loc @@ TacApply (true,false,cl,inhyp))
+ inhyp = in_hyp_as -> { TacAtom (Loc.tag ~loc @@ TacApply (true,false,cl,inhyp)) }
| IDENT "eapply"; cl = LIST1 constr_with_bindings_arg SEP ",";
- inhyp = in_hyp_as -> TacAtom (Loc.tag ~loc:!@loc @@ TacApply (true,true,cl,inhyp))
+ inhyp = in_hyp_as -> { TacAtom (Loc.tag ~loc @@ TacApply (true,true,cl,inhyp)) }
| IDENT "simple"; IDENT "apply";
cl = LIST1 constr_with_bindings_arg SEP ",";
- inhyp = in_hyp_as -> TacAtom (Loc.tag ~loc:!@loc @@ TacApply (false,false,cl,inhyp))
+ inhyp = in_hyp_as -> { TacAtom (Loc.tag ~loc @@ TacApply (false,false,cl,inhyp)) }
| IDENT "simple"; IDENT "eapply";
cl = LIST1 constr_with_bindings_arg SEP",";
- inhyp = in_hyp_as -> TacAtom (Loc.tag ~loc:!@loc @@ TacApply (false,true,cl,inhyp))
+ inhyp = in_hyp_as -> { TacAtom (Loc.tag ~loc @@ TacApply (false,true,cl,inhyp)) }
| IDENT "elim"; cl = constr_with_bindings_arg; el = OPT eliminator ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacElim (false,cl,el))
+ { TacAtom (Loc.tag ~loc @@ TacElim (false,cl,el)) }
| IDENT "eelim"; cl = constr_with_bindings_arg; el = OPT eliminator ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacElim (true,cl,el))
- | IDENT "case"; icl = induction_clause_list -> TacAtom (Loc.tag ~loc:!@loc @@ mkTacCase false icl)
- | IDENT "ecase"; icl = induction_clause_list -> TacAtom (Loc.tag ~loc:!@loc @@ mkTacCase true icl)
+ { TacAtom (Loc.tag ~loc @@ TacElim (true,cl,el)) }
+ | IDENT "case"; icl = induction_clause_list -> { TacAtom (Loc.tag ~loc @@ mkTacCase false icl) }
+ | IDENT "ecase"; icl = induction_clause_list -> { TacAtom (Loc.tag ~loc @@ mkTacCase true icl) }
| "fix"; id = ident; n = natural; "with"; fd = LIST1 fixdecl ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacMutualFix (id,n,List.map mk_fix_tac fd))
+ { TacAtom (Loc.tag ~loc @@ TacMutualFix (id,n,List.map mk_fix_tac fd)) }
| "cofix"; id = ident; "with"; fd = LIST1 cofixdecl ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacMutualCofix (id,List.map mk_cofix_tac fd))
+ { TacAtom (Loc.tag ~loc @@ TacMutualCofix (id,List.map mk_cofix_tac fd)) }
- | IDENT "pose"; (id,b) = bindings_with_parameters ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacLetTac (false,Names.Name.Name id,b,Locusops.nowhere,true,None))
+ | IDENT "pose"; bl = bindings_with_parameters ->
+ { let (id,b) = bl in TacAtom (Loc.tag ~loc @@ TacLetTac (false,Names.Name.Name id,b,Locusops.nowhere,true,None)) }
| IDENT "pose"; b = constr; na = as_name ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacLetTac (false,na,b,Locusops.nowhere,true,None))
- | IDENT "epose"; (id,b) = bindings_with_parameters ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacLetTac (true,Names.Name id,b,Locusops.nowhere,true,None))
+ { TacAtom (Loc.tag ~loc @@ TacLetTac (false,na,b,Locusops.nowhere,true,None)) }
+ | IDENT "epose"; bl = bindings_with_parameters ->
+ { let (id,b) = bl in TacAtom (Loc.tag ~loc @@ TacLetTac (true,Names.Name id,b,Locusops.nowhere,true,None)) }
| IDENT "epose"; b = constr; na = as_name ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacLetTac (true,na,b,Locusops.nowhere,true,None))
- | IDENT "set"; (id,c) = bindings_with_parameters; p = clause_dft_concl ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacLetTac (false,Names.Name.Name id,c,p,true,None))
+ { TacAtom (Loc.tag ~loc @@ TacLetTac (true,na,b,Locusops.nowhere,true,None)) }
+ | IDENT "set"; bl = bindings_with_parameters; p = clause_dft_concl ->
+ { let (id,c) = bl in TacAtom (Loc.tag ~loc @@ TacLetTac (false,Names.Name.Name id,c,p,true,None)) }
| IDENT "set"; c = constr; na = as_name; p = clause_dft_concl ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacLetTac (false,na,c,p,true,None))
- | IDENT "eset"; (id,c) = bindings_with_parameters; p = clause_dft_concl ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacLetTac (true,Names.Name id,c,p,true,None))
+ { TacAtom (Loc.tag ~loc @@ TacLetTac (false,na,c,p,true,None)) }
+ | IDENT "eset"; bl = bindings_with_parameters; p = clause_dft_concl ->
+ { let (id,c) = bl in TacAtom (Loc.tag ~loc @@ TacLetTac (true,Names.Name id,c,p,true,None)) }
| IDENT "eset"; c = constr; na = as_name; p = clause_dft_concl ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacLetTac (true,na,c,p,true,None))
+ { TacAtom (Loc.tag ~loc @@ TacLetTac (true,na,c,p,true,None)) }
| IDENT "remember"; c = constr; na = as_name; e = eqn_ipat;
p = clause_dft_all ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacLetTac (false,na,c,p,false,e))
+ { TacAtom (Loc.tag ~loc @@ TacLetTac (false,na,c,p,false,e)) }
| IDENT "eremember"; c = constr; na = as_name; e = eqn_ipat;
p = clause_dft_all ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacLetTac (true,na,c,p,false,e))
+ { TacAtom (Loc.tag ~loc @@ TacLetTac (true,na,c,p,false,e)) }
(* Alternative syntax for "pose proof c as id" *)
| IDENT "assert"; test_lpar_id_coloneq; "("; lid = identref; ":=";
c = lconstr; ")" ->
- let { CAst.loc = loc; v = id } = lid in
- TacAtom (Loc.tag ?loc @@ TacAssert (false,true,None,Some (CAst.make ?loc @@ IntroNaming (IntroIdentifier id)),c))
+ { let { CAst.loc = loc; v = id } = lid in
+ TacAtom (Loc.tag ?loc @@ TacAssert (false,true,None,Some (CAst.make ?loc @@ IntroNaming (IntroIdentifier id)),c)) }
| IDENT "eassert"; test_lpar_id_coloneq; "("; lid = identref; ":=";
c = lconstr; ")" ->
- let { CAst.loc = loc; v = id } = lid in
- TacAtom (Loc.tag ?loc @@ TacAssert (true,true,None,Some (CAst.make ?loc @@ IntroNaming (IntroIdentifier id)),c))
+ { let { CAst.loc = loc; v = id } = lid in
+ TacAtom (Loc.tag ?loc @@ TacAssert (true,true,None,Some (CAst.make ?loc @@ IntroNaming (IntroIdentifier id)),c)) }
(* Alternative syntax for "assert c as id by tac" *)
| IDENT "assert"; test_lpar_id_colon; "("; lid = identref; ":";
c = lconstr; ")"; tac=by_tactic ->
- let { CAst.loc = loc; v = id } = lid in
- TacAtom (Loc.tag ?loc @@ TacAssert (false,true,Some tac,Some (CAst.make ?loc @@ IntroNaming (IntroIdentifier id)),c))
+ { let { CAst.loc = loc; v = id } = lid in
+ TacAtom (Loc.tag ?loc @@ TacAssert (false,true,Some tac,Some (CAst.make ?loc @@ IntroNaming (IntroIdentifier id)),c)) }
| IDENT "eassert"; test_lpar_id_colon; "("; lid = identref; ":";
c = lconstr; ")"; tac=by_tactic ->
- let { CAst.loc = loc; v = id } = lid in
- TacAtom (Loc.tag ?loc @@ TacAssert (true,true,Some tac,Some (CAst.make ?loc @@ IntroNaming (IntroIdentifier id)),c))
+ { let { CAst.loc = loc; v = id } = lid in
+ TacAtom (Loc.tag ?loc @@ TacAssert (true,true,Some tac,Some (CAst.make ?loc @@ IntroNaming (IntroIdentifier id)),c)) }
(* Alternative syntax for "enough c as id by tac" *)
| IDENT "enough"; test_lpar_id_colon; "("; lid = identref; ":";
c = lconstr; ")"; tac=by_tactic ->
- let { CAst.loc = loc; v = id } = lid in
- TacAtom (Loc.tag ?loc @@ TacAssert (false,false,Some tac,Some (CAst.make ?loc @@ IntroNaming (IntroIdentifier id)),c))
+ { let { CAst.loc = loc; v = id } = lid in
+ TacAtom (Loc.tag ?loc @@ TacAssert (false,false,Some tac,Some (CAst.make ?loc @@ IntroNaming (IntroIdentifier id)),c)) }
| IDENT "eenough"; test_lpar_id_colon; "("; lid = identref; ":";
c = lconstr; ")"; tac=by_tactic ->
- let { CAst.loc = loc; v = id } = lid in
- TacAtom (Loc.tag ?loc @@ TacAssert (true,false,Some tac,Some (CAst.make ?loc @@ IntroNaming (IntroIdentifier id)),c))
+ { let { CAst.loc = loc; v = id } = lid in
+ TacAtom (Loc.tag ?loc @@ TacAssert (true,false,Some tac,Some (CAst.make ?loc @@ IntroNaming (IntroIdentifier id)),c)) }
| IDENT "assert"; c = constr; ipat = as_ipat; tac = by_tactic ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacAssert (false,true,Some tac,ipat,c))
+ { TacAtom (Loc.tag ~loc @@ TacAssert (false,true,Some tac,ipat,c)) }
| IDENT "eassert"; c = constr; ipat = as_ipat; tac = by_tactic ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacAssert (true,true,Some tac,ipat,c))
+ { TacAtom (Loc.tag ~loc @@ TacAssert (true,true,Some tac,ipat,c)) }
| IDENT "pose"; IDENT "proof"; c = lconstr; ipat = as_ipat ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacAssert (false,true,None,ipat,c))
+ { TacAtom (Loc.tag ~loc @@ TacAssert (false,true,None,ipat,c)) }
| IDENT "epose"; IDENT "proof"; c = lconstr; ipat = as_ipat ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacAssert (true,true,None,ipat,c))
+ { TacAtom (Loc.tag ~loc @@ TacAssert (true,true,None,ipat,c)) }
| IDENT "enough"; c = constr; ipat = as_ipat; tac = by_tactic ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacAssert (false,false,Some tac,ipat,c))
+ { TacAtom (Loc.tag ~loc @@ TacAssert (false,false,Some tac,ipat,c)) }
| IDENT "eenough"; c = constr; ipat = as_ipat; tac = by_tactic ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacAssert (true,false,Some tac,ipat,c))
+ { TacAtom (Loc.tag ~loc @@ TacAssert (true,false,Some tac,ipat,c)) }
| IDENT "generalize"; c = constr ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacGeneralize [((AllOccurrences,c),Names.Name.Anonymous)])
+ { TacAtom (Loc.tag ~loc @@ TacGeneralize [((AllOccurrences,c),Names.Name.Anonymous)]) }
| IDENT "generalize"; c = constr; l = LIST1 constr ->
- let gen_everywhere c = ((AllOccurrences,c),Names.Name.Anonymous) in
- TacAtom (Loc.tag ~loc:!@loc @@ TacGeneralize (List.map gen_everywhere (c::l)))
+ { let gen_everywhere c = ((AllOccurrences,c),Names.Name.Anonymous) in
+ TacAtom (Loc.tag ~loc @@ TacGeneralize (List.map gen_everywhere (c::l))) }
| IDENT "generalize"; c = constr; lookup_at_as_comma; nl = occs;
na = as_name;
- l = LIST0 [","; c = pattern_occ; na = as_name -> (c,na)] ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacGeneralize (((nl,c),na)::l))
+ l = LIST0 [","; c = pattern_occ; na = as_name -> { (c,na) } ] ->
+ { TacAtom (Loc.tag ~loc @@ TacGeneralize (((nl,c),na)::l)) }
(* Derived basic tactics *)
| IDENT "induction"; ic = induction_clause_list ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacInductionDestruct (true,false,ic))
+ { TacAtom (Loc.tag ~loc @@ TacInductionDestruct (true,false,ic)) }
| IDENT "einduction"; ic = induction_clause_list ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacInductionDestruct(true,true,ic))
+ { TacAtom (Loc.tag ~loc @@ TacInductionDestruct(true,true,ic)) }
| IDENT "destruct"; icl = induction_clause_list ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacInductionDestruct(false,false,icl))
+ { TacAtom (Loc.tag ~loc @@ TacInductionDestruct(false,false,icl)) }
| IDENT "edestruct"; icl = induction_clause_list ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacInductionDestruct(false,true,icl))
+ { TacAtom (Loc.tag ~loc @@ TacInductionDestruct(false,true,icl)) }
(* Equality and inversion *)
| IDENT "rewrite"; l = LIST1 oriented_rewriter SEP ",";
- cl = clause_dft_concl; t=by_tactic -> TacAtom (Loc.tag ~loc:!@loc @@ TacRewrite (false,l,cl,t))
+ cl = clause_dft_concl; t=by_tactic -> { TacAtom (Loc.tag ~loc @@ TacRewrite (false,l,cl,t)) }
| IDENT "erewrite"; l = LIST1 oriented_rewriter SEP ",";
- cl = clause_dft_concl; t=by_tactic -> TacAtom (Loc.tag ~loc:!@loc @@ TacRewrite (true,l,cl,t))
+ cl = clause_dft_concl; t=by_tactic -> { TacAtom (Loc.tag ~loc @@ TacRewrite (true,l,cl,t)) }
| IDENT "dependent"; k =
- [ IDENT "simple"; IDENT "inversion" -> SimpleInversion
- | IDENT "inversion" -> FullInversion
- | IDENT "inversion_clear" -> FullInversionClear ];
+ [ IDENT "simple"; IDENT "inversion" -> { SimpleInversion }
+ | IDENT "inversion" -> { FullInversion }
+ | IDENT "inversion_clear" -> { FullInversionClear } ];
hyp = quantified_hypothesis;
- ids = as_or_and_ipat; co = OPT ["with"; c = constr -> c] ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacInversion (DepInversion (k,co,ids),hyp))
+ ids = as_or_and_ipat; co = OPT ["with"; c = constr -> { c } ] ->
+ { TacAtom (Loc.tag ~loc @@ TacInversion (DepInversion (k,co,ids),hyp)) }
| IDENT "simple"; IDENT "inversion";
hyp = quantified_hypothesis; ids = as_or_and_ipat;
cl = in_hyp_list ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacInversion (NonDepInversion (SimpleInversion, cl, ids), hyp))
+ { TacAtom (Loc.tag ~loc @@ TacInversion (NonDepInversion (SimpleInversion, cl, ids), hyp)) }
| IDENT "inversion";
hyp = quantified_hypothesis; ids = as_or_and_ipat;
cl = in_hyp_list ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacInversion (NonDepInversion (FullInversion, cl, ids), hyp))
+ { TacAtom (Loc.tag ~loc @@ TacInversion (NonDepInversion (FullInversion, cl, ids), hyp)) }
| IDENT "inversion_clear";
hyp = quantified_hypothesis; ids = as_or_and_ipat;
cl = in_hyp_list ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacInversion (NonDepInversion (FullInversionClear, cl, ids), hyp))
+ { TacAtom (Loc.tag ~loc @@ TacInversion (NonDepInversion (FullInversionClear, cl, ids), hyp)) }
| IDENT "inversion"; hyp = quantified_hypothesis;
"using"; c = constr; cl = in_hyp_list ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacInversion (InversionUsing (c,cl), hyp))
+ { TacAtom (Loc.tag ~loc @@ TacInversion (InversionUsing (c,cl), hyp)) }
(* Conversion *)
| IDENT "red"; cl = clause_dft_concl ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacReduce (Red false, cl))
+ { TacAtom (Loc.tag ~loc @@ TacReduce (Red false, cl)) }
| IDENT "hnf"; cl = clause_dft_concl ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacReduce (Hnf, cl))
+ { TacAtom (Loc.tag ~loc @@ TacReduce (Hnf, cl)) }
| IDENT "simpl"; d = delta_flag; po = OPT ref_or_pattern_occ; cl = clause_dft_concl ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacReduce (Simpl (all_with d, po), cl))
+ { TacAtom (Loc.tag ~loc @@ TacReduce (Simpl (all_with d, po), cl)) }
| IDENT "cbv"; s = strategy_flag; cl = clause_dft_concl ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacReduce (Cbv s, cl))
+ { TacAtom (Loc.tag ~loc @@ TacReduce (Cbv s, cl)) }
| IDENT "cbn"; s = strategy_flag; cl = clause_dft_concl ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacReduce (Cbn s, cl))
+ { TacAtom (Loc.tag ~loc @@ TacReduce (Cbn s, cl)) }
| IDENT "lazy"; s = strategy_flag; cl = clause_dft_concl ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacReduce (Lazy s, cl))
+ { TacAtom (Loc.tag ~loc @@ TacReduce (Lazy s, cl)) }
| IDENT "compute"; delta = delta_flag; cl = clause_dft_concl ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacReduce (Cbv (all_with delta), cl))
+ { TacAtom (Loc.tag ~loc @@ TacReduce (Cbv (all_with delta), cl)) }
| IDENT "vm_compute"; po = OPT ref_or_pattern_occ; cl = clause_dft_concl ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacReduce (CbvVm po, cl))
+ { TacAtom (Loc.tag ~loc @@ TacReduce (CbvVm po, cl)) }
| IDENT "native_compute"; po = OPT ref_or_pattern_occ; cl = clause_dft_concl ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacReduce (CbvNative po, cl))
+ { TacAtom (Loc.tag ~loc @@ TacReduce (CbvNative po, cl)) }
| IDENT "unfold"; ul = LIST1 unfold_occ SEP ","; cl = clause_dft_concl ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacReduce (Unfold ul, cl))
+ { TacAtom (Loc.tag ~loc @@ TacReduce (Unfold ul, cl)) }
| IDENT "fold"; l = LIST1 constr; cl = clause_dft_concl ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacReduce (Fold l, cl))
+ { TacAtom (Loc.tag ~loc @@ TacReduce (Fold l, cl)) }
| IDENT "pattern"; pl = LIST1 pattern_occ SEP","; cl = clause_dft_concl ->
- TacAtom (Loc.tag ~loc:!@loc @@ TacReduce (Pattern pl, cl))
+ { TacAtom (Loc.tag ~loc @@ TacReduce (Pattern pl, cl)) }
(* Change ne doit pas s'appliquer dans un Definition t := Eval ... *)
- | IDENT "change"; (oc,c) = conversion; cl = clause_dft_concl ->
- let p,cl = merge_occurrences (!@loc) cl oc in
- TacAtom (Loc.tag ~loc:!@loc @@ TacChange (p,c,cl))
+ | IDENT "change"; c = conversion; cl = clause_dft_concl ->
+ { let (oc, c) = c in
+ let p,cl = merge_occurrences loc cl oc in
+ TacAtom (Loc.tag ~loc @@ TacChange (p,c,cl)) }
] ]
;
-END;;
+END
diff --git a/plugins/ltac/pltac.ml b/plugins/ltac/pltac.ml
index e9711268c2..759bb62fdd 100644
--- a/plugins/ltac/pltac.ml
+++ b/plugins/ltac/pltac.ml
@@ -11,11 +11,10 @@
open Pcoq
(* Main entry for extensions *)
-let simple_tactic = Gram.entry_create "tactic:simple_tactic"
+let simple_tactic = Entry.create "tactic:simple_tactic"
-let make_gen_entry _ name = Gram.entry_create ("tactic:" ^ name)
+let make_gen_entry _ name = Entry.create ("tactic:" ^ name)
-(* Entries that can be referred via the string -> Gram.entry table *)
(* Typically for tactic user extensions *)
let open_constr =
make_gen_entry utactic "open_constr"
@@ -23,7 +22,7 @@ let constr_with_bindings =
make_gen_entry utactic "constr_with_bindings"
let bindings =
make_gen_entry utactic "bindings"
-let hypident = Gram.entry_create "hypident"
+let hypident = Entry.create "hypident"
let constr_may_eval = make_gen_entry utactic "constr_may_eval"
let constr_eval = make_gen_entry utactic "constr_eval"
let uconstr =
@@ -40,7 +39,7 @@ let clause_dft_concl =
(* Main entries for ltac *)
-let tactic_arg = Gram.entry_create "tactic:tactic_arg"
+let tactic_arg = Entry.create "tactic:tactic_arg"
let tactic_expr = make_gen_entry utactic "tactic_expr"
let binder_tactic = make_gen_entry utactic "binder_tactic"
diff --git a/plugins/ltac/pltac.mli b/plugins/ltac/pltac.mli
index c5aa542fd1..9bff98b6c3 100644
--- a/plugins/ltac/pltac.mli
+++ b/plugins/ltac/pltac.mli
@@ -17,22 +17,22 @@ open Tacexpr
open Genredexpr
open Tactypes
-val open_constr : constr_expr Gram.entry
-val constr_with_bindings : constr_expr with_bindings Gram.entry
-val bindings : constr_expr bindings Gram.entry
-val hypident : (Names.lident * Locus.hyp_location_flag) Gram.entry
-val constr_may_eval : (constr_expr,qualid or_by_notation,constr_expr) may_eval Gram.entry
-val constr_eval : (constr_expr,qualid or_by_notation,constr_expr) may_eval Gram.entry
-val uconstr : constr_expr Gram.entry
-val quantified_hypothesis : quantified_hypothesis Gram.entry
-val destruction_arg : constr_expr with_bindings Tactics.destruction_arg Gram.entry
-val int_or_var : int Locus.or_var Gram.entry
-val simple_tactic : raw_tactic_expr Gram.entry
-val simple_intropattern : constr_expr intro_pattern_expr CAst.t Gram.entry
-val in_clause : Names.lident Locus.clause_expr Gram.entry
-val clause_dft_concl : Names.lident Locus.clause_expr Gram.entry
-val tactic_arg : raw_tactic_arg Gram.entry
-val tactic_expr : raw_tactic_expr Gram.entry
-val binder_tactic : raw_tactic_expr Gram.entry
-val tactic : raw_tactic_expr Gram.entry
-val tactic_eoi : raw_tactic_expr Gram.entry
+val open_constr : constr_expr Entry.t
+val constr_with_bindings : constr_expr with_bindings Entry.t
+val bindings : constr_expr bindings Entry.t
+val hypident : (Names.lident * Locus.hyp_location_flag) Entry.t
+val constr_may_eval : (constr_expr,qualid or_by_notation,constr_expr) may_eval Entry.t
+val constr_eval : (constr_expr,qualid or_by_notation,constr_expr) may_eval Entry.t
+val uconstr : constr_expr Entry.t
+val quantified_hypothesis : quantified_hypothesis Entry.t
+val destruction_arg : constr_expr with_bindings Tactics.destruction_arg Entry.t
+val int_or_var : int Locus.or_var Entry.t
+val simple_tactic : raw_tactic_expr Entry.t
+val simple_intropattern : constr_expr intro_pattern_expr CAst.t Entry.t
+val in_clause : Names.lident Locus.clause_expr Entry.t
+val clause_dft_concl : Names.lident Locus.clause_expr Entry.t
+val tactic_arg : raw_tactic_arg Entry.t
+val tactic_expr : raw_tactic_expr Entry.t
+val binder_tactic : raw_tactic_expr Entry.t
+val tactic : raw_tactic_expr Entry.t
+val tactic_eoi : raw_tactic_expr Entry.t
diff --git a/plugins/ltac/pptactic.ml b/plugins/ltac/pptactic.ml
index 09179dad34..4357689ee2 100644
--- a/plugins/ltac/pptactic.ml
+++ b/plugins/ltac/pptactic.ml
@@ -115,7 +115,7 @@ let string_of_genarg_arg (ArgumentType arg) =
let keyword x = tag_keyword (str x)
let primitive x = tag_primitive (str x)
- let has_type (Val.Dyn (tag, x)) t = match Val.eq tag t with
+ let has_type (Val.Dyn (tag, _)) t = match Val.eq tag t with
| None -> false
| Some _ -> true
@@ -188,7 +188,7 @@ let string_of_genarg_arg (ArgumentType arg) =
| AN v -> f v
| ByNotation (s,sc) -> qs s ++ pr_opt (fun sc -> str "%" ++ str sc) sc)
- let pr_located pr (loc,x) = pr x
+ let pr_located pr (_,x) = pr x
let pr_evaluable_reference = function
| EvalVarRef id -> pr_id id
@@ -240,7 +240,7 @@ let string_of_genarg_arg (ArgumentType arg) =
in
pr_sequence (fun x -> x) l
- let pr_extend_gen pr_gen lev { mltac_name = s; mltac_index = i } l =
+ let pr_extend_gen pr_gen _ { mltac_name = s; mltac_index = i } l =
let name =
str s.mltac_plugin ++ str "::" ++ str s.mltac_tactic ++
str "@" ++ int i
@@ -260,7 +260,7 @@ let string_of_genarg_arg (ArgumentType arg) =
| Extend.Uentry tag ->
let ArgT.Any tag = tag in
ArgT.repr tag
- | Extend.Uentryl (tkn, lvl) -> "tactic" ^ string_of_int lvl
+ | Extend.Uentryl (_, lvl) -> "tactic" ^ string_of_int lvl
let pr_alias_key key =
try
@@ -288,7 +288,7 @@ let string_of_genarg_arg (ArgumentType arg) =
let p = pr_tacarg_using_rule pr_gen prods in
if pp.pptac_level > lev then surround p else p
with Not_found ->
- let pr arg = str "_" in
+ let pr _ = str "_" in
KerName.print key ++ spc() ++ pr_sequence pr l ++ str" (* Generic printer *)"
let pr_farg prtac arg = prtac (1, Any) (TacArg (Loc.tag arg))
@@ -341,14 +341,14 @@ let string_of_genarg_arg (ArgumentType arg) =
pr_any_arg pr symb arg
| _ -> str "ltac:(" ++ prtac (1, Any) arg ++ str ")"
- let pr_raw_extend_rec prc prlc prtac prpat =
+ let pr_raw_extend_rec prtac =
pr_extend_gen (pr_farg prtac)
- let pr_glob_extend_rec prc prlc prtac prpat =
+ let pr_glob_extend_rec prtac =
pr_extend_gen (pr_farg prtac)
- let pr_raw_alias prc prlc prtac prpat lev key args =
+ let pr_raw_alias prtac lev key args =
pr_alias_gen (pr_targ (fun l a -> prtac l (TacArg (Loc.tag a)))) lev key args
- let pr_glob_alias prc prlc prtac prpat lev key args =
+ let pr_glob_alias prtac lev key args =
pr_alias_gen (pr_targ (fun l a -> prtac l (TacArg (Loc.tag a)))) lev key args
(**********************************************************************)
@@ -743,7 +743,7 @@ let pr_goal_selector ~toplevel s =
(* Main tactic printer *)
and pr_atom1 a = tag_atom a (match a with
(* Basic tactics *)
- | TacIntroPattern (ev,[]) as t ->
+ | TacIntroPattern (_,[]) as t ->
pr_atom0 t
| TacIntroPattern (ev,(_::_ as p)) ->
hov 1 (primitive (if ev then "eintros" else "intros") ++
@@ -1054,7 +1054,7 @@ let pr_goal_selector ~toplevel s =
primitive "fresh" ++ pr_fresh_ids l, latom
| TacArg(_,TacGeneric arg) ->
pr.pr_generic arg, latom
- | TacArg(_,TacCall(loc,(f,[]))) ->
+ | TacArg(_,TacCall(_,(f,[]))) ->
pr.pr_reference f, latom
| TacArg(_,TacCall(loc,(f,l))) ->
pr_with_comments ?loc (hov 1 (
@@ -1112,8 +1112,8 @@ let pr_goal_selector ~toplevel s =
pr_reference = pr_qualid;
pr_name = pr_lident;
pr_generic = (fun arg -> Pputils.pr_raw_generic (Global.env ()) arg);
- pr_extend = pr_raw_extend_rec pr_constr_expr pr_lconstr_expr pr_raw_tactic_level pr_constr_pattern_expr;
- pr_alias = pr_raw_alias pr_constr_expr pr_lconstr_expr pr_raw_tactic_level pr_constr_pattern_expr;
+ pr_extend = pr_raw_extend_rec pr_raw_tactic_level;
+ pr_alias = pr_raw_alias pr_raw_tactic_level;
} in
make_pr_tac
pr raw_printers
@@ -1142,12 +1142,8 @@ let pr_goal_selector ~toplevel s =
pr_reference = pr_ltac_or_var (pr_located pr_ltac_constant);
pr_name = pr_lident;
pr_generic = (fun arg -> Pputils.pr_glb_generic (Global.env ()) arg);
- pr_extend = pr_glob_extend_rec
- (pr_and_constr_expr (pr_glob_constr_env env)) (pr_and_constr_expr (pr_lglob_constr_env env))
- prtac (pr_pat_and_constr_expr (pr_glob_constr_env env));
- pr_alias = pr_glob_alias
- (pr_and_constr_expr (pr_glob_constr_env env)) (pr_and_constr_expr (pr_lglob_constr_env env))
- prtac (pr_pat_and_constr_expr (pr_glob_constr_env env));
+ pr_extend = pr_glob_extend_rec prtac;
+ pr_alias = pr_glob_alias prtac;
} in
make_pr_tac
pr glob_printers
@@ -1168,8 +1164,8 @@ let pr_goal_selector ~toplevel s =
| _ -> user_err Pp.(str "Cannot translate fix tactic: not enough products") in
strip_ty [] n ty
- let pr_atomic_tactic_level env sigma n t =
- let prtac n (t:atomic_tactic_expr) =
+ let pr_atomic_tactic_level env sigma t =
+ let prtac (t:atomic_tactic_expr) =
let pr = {
pr_tactic = (fun _ _ -> str "<tactic>");
pr_constr = (fun c -> pr_econstr_env env sigma c);
@@ -1188,18 +1184,15 @@ let pr_goal_selector ~toplevel s =
in
pr_atom pr strip_prod_binders_constr tag_atomic_tactic_expr t
in
- prtac n t
+ prtac t
let pr_raw_generic = Pputils.pr_raw_generic
let pr_glb_generic = Pputils.pr_glb_generic
- let pr_raw_extend env = pr_raw_extend_rec
- pr_constr_expr pr_lconstr_expr pr_raw_tactic_level pr_constr_pattern_expr
+ let pr_raw_extend _ = pr_raw_extend_rec pr_raw_tactic_level
- let pr_glob_extend env = pr_glob_extend_rec
- (pr_and_constr_expr (pr_glob_constr_env env)) (pr_and_constr_expr (pr_lglob_constr_env env))
- (pr_glob_tactic_level env) (pr_pat_and_constr_expr (pr_glob_constr_env env))
+ let pr_glob_extend env = pr_glob_extend_rec (pr_glob_tactic_level env)
let pr_alias pr lev key args =
pr_alias_gen (fun _ arg -> pr arg) lev key args
@@ -1207,14 +1200,14 @@ let pr_goal_selector ~toplevel s =
let pr_extend pr lev ml args =
pr_extend_gen pr lev ml args
- let pr_atomic_tactic env sigma c = pr_atomic_tactic_level env sigma ltop c
+ let pr_atomic_tactic env sigma c = pr_atomic_tactic_level env sigma c
let declare_extra_genarg_pprule wit
(f : 'a raw_extra_genarg_printer)
(g : 'b glob_extra_genarg_printer)
(h : 'c extra_genarg_printer) =
begin match wit with
- | ExtraArg s -> ()
+ | ExtraArg _ -> ()
| _ -> user_err Pp.(str "Can declare a pretty-printing rule only for extra argument types.")
end;
let f x =
diff --git a/plugins/ltac/rewrite.ml b/plugins/ltac/rewrite.ml
index 01c52c413c..9f8cd2fc4e 100644
--- a/plugins/ltac/rewrite.ml
+++ b/plugins/ltac/rewrite.ml
@@ -409,7 +409,7 @@ module TypeGlobal = struct
let inverse env (evd,cstrs) car rel =
- let (evd, sort) = Evarutil.new_Type ~rigid:Evd.univ_flexible env evd in
+ let (evd, sort) = Evarutil.new_Type ~rigid:Evd.univ_flexible evd in
app_poly_check env (evd,cstrs) coq_inverse [| car ; car; sort; rel |]
end
diff --git a/plugins/ltac/taccoerce.ml b/plugins/ltac/taccoerce.ml
index cc9c2046d8..026c00b849 100644
--- a/plugins/ltac/taccoerce.ml
+++ b/plugins/ltac/taccoerce.ml
@@ -165,8 +165,7 @@ let coerce_var_to_ident fresh env sigma v =
(* Interprets, if possible, a constr to an identifier which may not
be fresh but suitable to be given to the fresh tactic. Works for
vars, constants, inductive, constructors and sorts. *)
-let coerce_to_ident_not_fresh env sigma v =
-let g = sigma in
+let coerce_to_ident_not_fresh sigma v =
let id_of_name = function
| Name.Anonymous -> Id.of_string "x"
| Name.Name x -> x in
@@ -183,9 +182,9 @@ let id_of_name = function
| Some c ->
match EConstr.kind sigma c with
| Var id -> id
- | Meta m -> id_of_name (Evd.meta_name g m)
+ | Meta m -> id_of_name (Evd.meta_name sigma m)
| Evar (kn,_) ->
- begin match Evd.evar_ident kn g with
+ begin match Evd.evar_ident kn sigma with
| None -> fail ()
| Some id -> id
end
@@ -199,15 +198,16 @@ let id_of_name = function
let basename = Nametab.basename_of_global ref in
basename
| Sort s ->
- begin
+ begin
match ESorts.kind sigma s with
- | Sorts.Prop _ -> Label.to_id (Label.make "Prop")
- | Sorts.Type _ -> Label.to_id (Label.make "Type")
- end
+ | Sorts.Prop -> Label.to_id (Label.make "Prop")
+ | Sorts.Set -> Label.to_id (Label.make "Set")
+ | Sorts.Type _ -> Label.to_id (Label.make "Type")
+ end
| _ -> fail()
-let coerce_to_intro_pattern env sigma v =
+let coerce_to_intro_pattern sigma v =
if has_type v (topwit wit_intro_pattern) then
(out_gen (topwit wit_intro_pattern) v).CAst.v
else if has_type v (topwit wit_var) then
@@ -220,8 +220,8 @@ let coerce_to_intro_pattern env sigma v =
IntroNaming (IntroIdentifier (destVar sigma c))
| _ -> raise (CannotCoerceTo "an introduction pattern")
-let coerce_to_intro_pattern_naming env sigma v =
- match coerce_to_intro_pattern env sigma v with
+let coerce_to_intro_pattern_naming sigma v =
+ match coerce_to_intro_pattern sigma v with
| IntroNaming pat -> pat
| _ -> raise (CannotCoerceTo "a naming introduction pattern")
@@ -254,7 +254,7 @@ let coerce_to_constr env v =
(try [], constr_of_id env id with Not_found -> fail ())
else fail ()
-let coerce_to_uconstr env v =
+let coerce_to_uconstr v =
if has_type v (topwit wit_uconstr) then
out_gen (topwit wit_uconstr) v
else
@@ -298,11 +298,11 @@ let coerce_to_constr_list env v =
List.map map l
| None -> raise (CannotCoerceTo "a term list")
-let coerce_to_intro_pattern_list ?loc env sigma v =
+let coerce_to_intro_pattern_list ?loc sigma v =
match Value.to_list v with
| None -> raise (CannotCoerceTo "an intro pattern list")
| Some l ->
- let map v = CAst.make ?loc @@ coerce_to_intro_pattern env sigma v in
+ let map v = CAst.make ?loc @@ coerce_to_intro_pattern sigma v in
List.map map l
let coerce_to_hyp env sigma v =
@@ -327,7 +327,7 @@ let coerce_to_hyp_list env sigma v =
| None -> raise (CannotCoerceTo "a variable list")
(* Interprets a qualified name *)
-let coerce_to_reference env sigma v =
+let coerce_to_reference sigma v =
match Value.to_constr v with
| Some c ->
begin
@@ -355,7 +355,7 @@ let coerce_to_quantified_hypothesis sigma v =
(* Quantified named or numbered hypothesis or hypothesis in context *)
(* (as in Inversion) *)
-let coerce_to_decl_or_quant_hyp env sigma v =
+let coerce_to_decl_or_quant_hyp sigma v =
if has_type v (topwit wit_int) then
AnonHyp (out_gen (topwit wit_int) v)
else
diff --git a/plugins/ltac/taccoerce.mli b/plugins/ltac/taccoerce.mli
index 56f8816840..d2ae92f6ce 100644
--- a/plugins/ltac/taccoerce.mli
+++ b/plugins/ltac/taccoerce.mli
@@ -51,12 +51,12 @@ val coerce_to_constr_context : Value.t -> constr
val coerce_var_to_ident : bool -> Environ.env -> Evd.evar_map -> Value.t -> Id.t
-val coerce_to_ident_not_fresh : Environ.env -> Evd.evar_map -> Value.t -> Id.t
+val coerce_to_ident_not_fresh : Evd.evar_map -> Value.t -> Id.t
-val coerce_to_intro_pattern : Environ.env -> Evd.evar_map -> Value.t -> Tacexpr.delayed_open_constr intro_pattern_expr
+val coerce_to_intro_pattern : Evd.evar_map -> Value.t -> Tacexpr.delayed_open_constr intro_pattern_expr
val coerce_to_intro_pattern_naming :
- Environ.env -> Evd.evar_map -> Value.t -> Namegen.intro_pattern_naming_expr
+ Evd.evar_map -> Value.t -> Namegen.intro_pattern_naming_expr
val coerce_to_hint_base : Value.t -> string
@@ -64,7 +64,7 @@ val coerce_to_int : Value.t -> int
val coerce_to_constr : Environ.env -> Value.t -> Ltac_pretype.constr_under_binders
-val coerce_to_uconstr : Environ.env -> Value.t -> Ltac_pretype.closed_glob_constr
+val coerce_to_uconstr : Value.t -> Ltac_pretype.closed_glob_constr
val coerce_to_closed_constr : Environ.env -> Value.t -> constr
@@ -74,17 +74,17 @@ val coerce_to_evaluable_ref :
val coerce_to_constr_list : Environ.env -> Value.t -> constr list
val coerce_to_intro_pattern_list :
- ?loc:Loc.t -> Environ.env -> Evd.evar_map -> Value.t -> Tacexpr.intro_patterns
+ ?loc:Loc.t -> Evd.evar_map -> Value.t -> Tacexpr.intro_patterns
val coerce_to_hyp : Environ.env -> Evd.evar_map -> Value.t -> Id.t
val coerce_to_hyp_list : Environ.env -> Evd.evar_map -> Value.t -> Id.t list
-val coerce_to_reference : Environ.env -> Evd.evar_map -> Value.t -> GlobRef.t
+val coerce_to_reference : Evd.evar_map -> Value.t -> GlobRef.t
val coerce_to_quantified_hypothesis : Evd.evar_map -> Value.t -> quantified_hypothesis
-val coerce_to_decl_or_quant_hyp : Environ.env -> Evd.evar_map -> Value.t -> quantified_hypothesis
+val coerce_to_decl_or_quant_hyp : Evd.evar_map -> Value.t -> quantified_hypothesis
val coerce_to_int_or_var_list : Value.t -> int Locus.or_var list
diff --git a/plugins/ltac/tacentries.ml b/plugins/ltac/tacentries.ml
index 98d4515367..636cb8ebf8 100644
--- a/plugins/ltac/tacentries.ml
+++ b/plugins/ltac/tacentries.ml
@@ -45,7 +45,7 @@ let coincide s pat off =
let atactic n =
if n = 5 then Aentry Pltac.binder_tactic
- else Aentryl (Pltac.tactic_expr, n)
+ else Aentryl (Pltac.tactic_expr, string_of_int n)
type entry_name = EntryName :
'a raw_abstract_argument_type * (Tacexpr.raw_tactic_expr, 'a) Extend.symbol -> entry_name
@@ -252,7 +252,7 @@ type tactic_grammar_obj = {
tacobj_key : KerName.t;
tacobj_local : locality_flag;
tacobj_tacgram : tactic_grammar;
- tacobj_body : Id.t list * Tacexpr.glob_tactic_expr;
+ tacobj_body : Tacenv.alias_tactic;
tacobj_forml : bool;
}
@@ -288,10 +288,11 @@ let load_tactic_notation i (_, tobj) =
extend_tactic_grammar key tobj.tacobj_forml tobj.tacobj_tacgram
let subst_tactic_notation (subst, tobj) =
- let (ids, body) = tobj.tacobj_body in
+ let open Tacenv in
+ let alias = tobj.tacobj_body in
{ tobj with
tacobj_key = Mod_subst.subst_kn subst tobj.tacobj_key;
- tacobj_body = (ids, Tacsubst.subst_tactic subst body);
+ tacobj_body = { alias with alias_body = Tacsubst.subst_tactic subst alias.alias_body };
}
let classify_tactic_notation tacobj = Substitute tacobj
@@ -308,25 +309,26 @@ let cons_production_parameter = function
| TacTerm _ -> None
| TacNonTerm (_, (_, ido)) -> ido
-let add_glob_tactic_notation local ~level prods forml ids tac =
+let add_glob_tactic_notation local ~level ?deprecation prods forml ids tac =
let parule = {
tacgram_level = level;
tacgram_prods = prods;
} in
+ let open Tacenv in
let tacobj = {
tacobj_key = make_fresh_key prods;
tacobj_local = local;
tacobj_tacgram = parule;
- tacobj_body = (ids, tac);
+ tacobj_body = { alias_args = ids; alias_body = tac; alias_deprecation = deprecation };
tacobj_forml = forml;
} in
Lib.add_anonymous_leaf (inTacticGrammar tacobj)
-let add_tactic_notation local n prods e =
+let add_tactic_notation local n ?deprecation prods e =
let ids = List.map_filter cons_production_parameter prods in
let prods = List.map interp_prod_item prods in
let tac = Tacintern.glob_tactic_env ids (Global.env()) e in
- add_glob_tactic_notation local ~level:n prods false ids tac
+ add_glob_tactic_notation local ~level:n ?deprecation prods false ids tac
(**********************************************************************)
(* ML Tactic entries *)
@@ -366,7 +368,7 @@ let extend_atomic_tactic name entries =
in
List.iteri add_atomic entries
-let add_ml_tactic_notation name ~level prods =
+let add_ml_tactic_notation name ~level ?deprecation prods =
let len = List.length prods in
let iter i prods =
let open Tacexpr in
@@ -378,7 +380,7 @@ let add_ml_tactic_notation name ~level prods =
let entry = { mltac_name = name; mltac_index = len - i - 1 } in
let map id = Reference (Locus.ArgVar (CAst.make id)) in
let tac = TacML (Loc.tag (entry, List.map map ids)) in
- add_glob_tactic_notation false ~level prods true ids tac
+ add_glob_tactic_notation false ~level ?deprecation prods true ids tac
in
List.iteri iter (List.rev prods);
(** We call [extend_atomic_tactic] only for "basic tactics" (the ones at
@@ -398,7 +400,7 @@ let create_ltac_quotation name cast (e, l) =
let () = ltac_quotations := String.Set.add name !ltac_quotations in
let entry = match l with
| None -> Aentry e
- | Some l -> Aentryl (e, l)
+ | Some l -> Aentryl (e, string_of_int l)
in
(* let level = Some "1" in *)
let level = None in
@@ -430,7 +432,7 @@ let warn_unusable_identifier =
(fun id -> strbrk "The Ltac name" ++ spc () ++ Id.print id ++ spc () ++
strbrk "may be unusable because of a conflict with a notation.")
-let register_ltac local tacl =
+let register_ltac local ?deprecation tacl =
let map tactic_body =
match tactic_body with
| Tacexpr.TacticDefinition ({CAst.loc;v=id}, body) ->
@@ -483,10 +485,10 @@ let register_ltac local tacl =
let defs = States.with_state_protection defs () in
let iter (def, tac) = match def with
| NewTac id ->
- Tacenv.register_ltac false local id tac;
+ Tacenv.register_ltac false local id tac ?deprecation;
Flags.if_verbose Feedback.msg_info (Id.print id ++ str " is defined")
| UpdateTac kn ->
- Tacenv.redefine_ltac local kn tac;
+ Tacenv.redefine_ltac local kn tac ?deprecation;
let name = Tacenv.shortest_qualid_of_tactic kn in
Flags.if_verbose Feedback.msg_info (Libnames.pr_qualid name ++ str " is redefined")
in
@@ -554,13 +556,18 @@ let () =
] in
register_grammars_by_name "tactic" entries
+let get_identifier id =
+ (** Workaround for badly-designed generic arguments lacking a closure *)
+ Names.Id.of_string_soft ("$" ^ id)
+
+
type _ ty_sig =
| TyNil : (Geninterp.interp_sign -> unit Proofview.tactic) ty_sig
| TyIdent : string * 'r ty_sig -> 'r ty_sig
| TyArg :
- (('a, 'b, 'c) Extend.ty_user_symbol * Id.t) Loc.located * 'r ty_sig -> ('c -> 'r) ty_sig
+ ('a, 'b, 'c) Extend.ty_user_symbol * string * 'r ty_sig -> ('c -> 'r) ty_sig
| TyAnonArg :
- ('a, 'b, 'c) Extend.ty_user_symbol Loc.located * 'r ty_sig -> 'r ty_sig
+ ('a, 'b, 'c) Extend.ty_user_symbol * 'r ty_sig -> 'r ty_sig
type ty_ml = TyML : 'r ty_sig * 'r -> ty_ml
@@ -578,23 +585,15 @@ let rec clause_of_sign : type a. a ty_sig -> Genarg.ArgT.any Extend.user_symbol
fun sign -> match sign with
| TyNil -> []
| TyIdent (s, sig') -> TacTerm s :: clause_of_sign sig'
- | TyArg ((loc,(a,id)),sig') ->
- TacNonTerm (loc,(untype_user_symbol a,Some id)) :: clause_of_sign sig'
- | TyAnonArg ((loc,a),sig') ->
- TacNonTerm (loc,(untype_user_symbol a,None)) :: clause_of_sign sig'
+ | TyArg (a, id, sig') ->
+ let id = get_identifier id in
+ TacNonTerm (None,(untype_user_symbol a,Some id)) :: clause_of_sign sig'
+ | TyAnonArg (a, sig') ->
+ TacNonTerm (None,(untype_user_symbol a,None)) :: clause_of_sign sig'
let clause_of_ty_ml = function
| TyML (t,_) -> clause_of_sign t
-let rec prj : type a b c. (a,b,c) Extend.ty_user_symbol -> (a,b,c) genarg_type = function
- | TUentry a -> ExtraArg a
- | TUentryl (a,l) -> ExtraArg a
- | TUopt(o) -> OptArg (prj o)
- | TUlist1 l -> ListArg (prj l)
- | TUlist1sep (l,_) -> ListArg (prj l)
- | TUlist0 l -> ListArg (prj l)
- | TUlist0sep (l,_) -> ListArg (prj l)
-
let rec eval_sign : type a. a ty_sig -> a -> Geninterp.Val.t list -> Geninterp.interp_sign -> unit Proofview.tactic =
fun sign tac ->
match sign with
@@ -604,15 +603,15 @@ let rec eval_sign : type a. a ty_sig -> a -> Geninterp.Val.t list -> Geninterp.i
| _ :: _ -> assert false
end
| TyIdent (s, sig') -> eval_sign sig' tac
- | TyArg ((_loc,(a,id)), sig') ->
+ | TyArg (a, _, sig') ->
let f = eval_sign sig' in
begin fun tac vals ist -> match vals with
| [] -> assert false
| v :: vals ->
- let v' = Taccoerce.Value.cast (topwit (prj a)) v in
+ let v' = Taccoerce.Value.cast (topwit (Egramml.proj_symbol a)) v in
f (tac v') vals ist
end tac
- | TyAnonArg ((_loc,a), sig') -> eval_sign sig' tac
+ | TyAnonArg (a, sig') -> eval_sign sig' tac
let eval : ty_ml -> Geninterp.Val.t list -> Geninterp.interp_sign -> unit Proofview.tactic = function
| TyML (t,tac) -> eval_sign t tac
@@ -624,14 +623,14 @@ let is_constr_entry = function
let rec only_constr : type a. a ty_sig -> bool = function
| TyNil -> true
| TyIdent(_,_) -> false
-| TyArg((_,(u,_)),s) -> if is_constr_entry u then only_constr s else false
-| TyAnonArg((_,u),s) -> if is_constr_entry u then only_constr s else false
+| TyArg (u, _, s) -> if is_constr_entry u then only_constr s else false
+| TyAnonArg (u, s) -> if is_constr_entry u then only_constr s else false
let rec mk_sign_vars : type a. a ty_sig -> Name.t list = function
| TyNil -> []
| TyIdent (_,s) -> mk_sign_vars s
-| TyArg((_,(_,name)),s) -> Name name :: mk_sign_vars s
-| TyAnonArg((_,_),s) -> Anonymous :: mk_sign_vars s
+| TyArg (_, name, s) -> Name (get_identifier name) :: mk_sign_vars s
+| TyAnonArg (_, s) -> Anonymous :: mk_sign_vars s
let dummy_id = Id.of_string "_"
@@ -652,7 +651,7 @@ let lift_constr_tac_to_ml_tac vars tac =
end in
tac
-let tactic_extend plugin_name tacname ~level sign =
+let tactic_extend plugin_name tacname ~level ?deprecation sign =
let open Tacexpr in
let ml_tactic_name =
{ mltac_tactic = tacname;
@@ -681,10 +680,10 @@ let tactic_extend plugin_name tacname ~level sign =
This is the rôle of the [lift_constr_tac_to_ml_tac] function. *)
let body = Tacexpr.TacFun (vars, Tacexpr.TacML (Loc.tag (ml, [])))in
let id = Names.Id.of_string name in
- let obj () = Tacenv.register_ltac true false id body in
+ let obj () = Tacenv.register_ltac true false id body ?deprecation in
let () = Tacenv.register_ml_tactic ml_tactic_name [|tac|] in
Mltop.declare_cache_obj obj plugin_name
| _ ->
- let obj () = add_ml_tactic_notation ml_tactic_name ~level (List.map clause_of_ty_ml sign) in
+ let obj () = add_ml_tactic_notation ml_tactic_name ~level ?deprecation (List.map clause_of_ty_ml sign) in
Tacenv.register_ml_tactic ml_tactic_name @@ Array.of_list (List.map eval sign);
Mltop.declare_cache_obj obj plugin_name
diff --git a/plugins/ltac/tacentries.mli b/plugins/ltac/tacentries.mli
index 2bfbbe2e16..138a584e01 100644
--- a/plugins/ltac/tacentries.mli
+++ b/plugins/ltac/tacentries.mli
@@ -12,10 +12,12 @@
open Vernacexpr
open Tacexpr
+open Vernacinterp
(** {5 Tactic Definitions} *)
-val register_ltac : locality_flag -> Tacexpr.tacdef_body list -> unit
+val register_ltac : locality_flag -> ?deprecation:deprecation ->
+ Tacexpr.tacdef_body list -> unit
(** Adds new Ltac definitions to the environment. *)
(** {5 Tactic Notations} *)
@@ -34,8 +36,8 @@ type argument = Genarg.ArgT.any Extend.user_symbol
leaves. *)
val add_tactic_notation :
- locality_flag -> int -> raw_argument grammar_tactic_prod_item_expr list ->
- raw_tactic_expr -> unit
+ locality_flag -> int -> ?deprecation:deprecation -> raw_argument
+ grammar_tactic_prod_item_expr list -> raw_tactic_expr -> unit
(** [add_tactic_notation local level prods expr] adds a tactic notation in the
environment at level [level] with locality [local] made of the grammar
productions [prods] and returning the body [expr] *)
@@ -47,7 +49,7 @@ val register_tactic_notation_entry : string -> ('a, 'b, 'c) Genarg.genarg_type -
to finding an argument by name (as in {!Genarg}) if there is none
matching. *)
-val add_ml_tactic_notation : ml_tactic_name -> level:int ->
+val add_ml_tactic_notation : ml_tactic_name -> level:int -> ?deprecation:deprecation ->
argument grammar_tactic_prod_item_expr list list -> unit
(** A low-level variant of {!add_tactic_notation} used by the TACTIC EXTEND
ML-side macro. *)
@@ -55,7 +57,7 @@ val add_ml_tactic_notation : ml_tactic_name -> level:int ->
(** {5 Tactic Quotations} *)
val create_ltac_quotation : string ->
- ('grm Loc.located -> raw_tactic_arg) -> ('grm Pcoq.Gram.entry * int option) -> unit
+ ('grm Loc.located -> raw_tactic_arg) -> ('grm Pcoq.Entry.t * int option) -> unit
(** [create_ltac_quotation name f e] adds a quotation rule to Ltac, that is,
Ltac grammar now accepts arguments of the form ["name" ":" "(" <e> ")"], and
generates an argument using [f] on the entry parsed by [e]. *)
@@ -72,10 +74,11 @@ type _ ty_sig =
| TyNil : (Geninterp.interp_sign -> unit Proofview.tactic) ty_sig
| TyIdent : string * 'r ty_sig -> 'r ty_sig
| TyArg :
- (('a, 'b, 'c) Extend.ty_user_symbol * Names.Id.t) Loc.located * 'r ty_sig -> ('c -> 'r) ty_sig
+ ('a, 'b, 'c) Extend.ty_user_symbol * string * 'r ty_sig -> ('c -> 'r) ty_sig
| TyAnonArg :
- ('a, 'b, 'c) Extend.ty_user_symbol Loc.located * 'r ty_sig -> 'r ty_sig
+ ('a, 'b, 'c) Extend.ty_user_symbol * 'r ty_sig -> 'r ty_sig
type ty_ml = TyML : 'r ty_sig * 'r -> ty_ml
-val tactic_extend : string -> string -> level:Int.t -> ty_ml list -> unit
+val tactic_extend : string -> string -> level:Int.t ->
+ ?deprecation:deprecation -> ty_ml list -> unit
diff --git a/plugins/ltac/tacenv.ml b/plugins/ltac/tacenv.ml
index d5ab2d690d..0bb9ccb1d8 100644
--- a/plugins/ltac/tacenv.ml
+++ b/plugins/ltac/tacenv.ml
@@ -52,7 +52,11 @@ let shortest_qualid_of_tactic kn =
(** Tactic notations (TacAlias) *)
type alias = KerName.t
-type alias_tactic = Id.t list * glob_tactic_expr
+type alias_tactic =
+ { alias_args: Id.t list;
+ alias_body: glob_tactic_expr;
+ alias_deprecation: Vernacinterp.deprecation option;
+ }
let alias_map = Summary.ref ~name:"tactic-alias"
(KNmap.empty : alias_tactic KNmap.t)
@@ -118,6 +122,7 @@ type ltac_entry = {
tac_for_ml : bool;
tac_body : glob_tactic_expr;
tac_redef : ModPath.t list;
+ tac_deprecation : Vernacinterp.deprecation option
}
let mactab =
@@ -130,8 +135,12 @@ let interp_ltac r = (KNmap.find r !mactab).tac_body
let is_ltac_for_ml_tactic r = (KNmap.find r !mactab).tac_for_ml
-let add kn b t =
- let entry = { tac_for_ml = b; tac_body = t; tac_redef = [] } in
+let add ~deprecation kn b t =
+ let entry = { tac_for_ml = b;
+ tac_body = t;
+ tac_redef = [];
+ tac_deprecation = deprecation;
+ } in
mactab := KNmap.add kn entry !mactab
let replace kn path t =
@@ -139,34 +148,38 @@ let replace kn path t =
let entry _ e = { e with tac_body = t; tac_redef = path :: e.tac_redef } in
mactab := KNmap.modify kn entry !mactab
-let load_md i ((sp, kn), (local, id, b, t)) = match id with
+let tac_deprecation kn =
+ try (KNmap.find kn !mactab).tac_deprecation with Not_found -> None
+
+let load_md i ((sp, kn), (local, id, b, t, deprecation)) = match id with
| None ->
let () = if not local then push_tactic (Until i) sp kn in
- add kn b t
+ add ~deprecation kn b t
| Some kn0 -> replace kn0 kn t
-let open_md i ((sp, kn), (local, id, b, t)) = match id with
+let open_md i ((sp, kn), (local, id, b, t, deprecation)) = match id with
| None ->
let () = if not local then push_tactic (Exactly i) sp kn in
- add kn b t
+ add ~deprecation kn b t
| Some kn0 -> replace kn0 kn t
-let cache_md ((sp, kn), (local, id ,b, t)) = match id with
+let cache_md ((sp, kn), (local, id ,b, t, deprecation)) = match id with
| None ->
let () = push_tactic (Until 1) sp kn in
- add kn b t
+ add ~deprecation kn b t
| Some kn0 -> replace kn0 kn t
let subst_kind subst id = match id with
| None -> None
| Some kn -> Some (Mod_subst.subst_kn subst kn)
-let subst_md (subst, (local, id, b, t)) =
- (local, subst_kind subst id, b, Tacsubst.subst_tactic subst t)
+let subst_md (subst, (local, id, b, t, deprecation)) =
+ (local, subst_kind subst id, b, Tacsubst.subst_tactic subst t, deprecation)
-let classify_md (local, _, _, _ as o) = Substitute o
+let classify_md (local, _, _, _, _ as o) = Substitute o
-let inMD : bool * ltac_constant option * bool * glob_tactic_expr -> obj =
+let inMD : bool * ltac_constant option * bool * glob_tactic_expr *
+ Vernacinterp.deprecation option -> obj =
declare_object {(default_object "TAC-DEFINITION") with
cache_function = cache_md;
load_function = load_md;
@@ -174,8 +187,8 @@ let inMD : bool * ltac_constant option * bool * glob_tactic_expr -> obj =
subst_function = subst_md;
classify_function = classify_md}
-let register_ltac for_ml local id tac =
- ignore (Lib.add_leaf id (inMD (local, None, for_ml, tac)))
+let register_ltac for_ml local ?deprecation id tac =
+ ignore (Lib.add_leaf id (inMD (local, None, for_ml, tac, deprecation)))
-let redefine_ltac local kn tac =
- Lib.add_anonymous_leaf (inMD (local, Some kn, false, tac))
+let redefine_ltac local ?deprecation kn tac =
+ Lib.add_anonymous_leaf (inMD (local, Some kn, false, tac, deprecation))
diff --git a/plugins/ltac/tacenv.mli b/plugins/ltac/tacenv.mli
index 3af2f2a460..d5d36c97fa 100644
--- a/plugins/ltac/tacenv.mli
+++ b/plugins/ltac/tacenv.mli
@@ -12,6 +12,7 @@ open Names
open Libnames
open Tacexpr
open Geninterp
+open Vernacinterp
(** This module centralizes the various ways of registering tactics. *)
@@ -29,21 +30,26 @@ val shortest_qualid_of_tactic : ltac_constant -> qualid
type alias = KerName.t
(** Type of tactic alias, used in the [TacAlias] node. *)
-type alias_tactic = Id.t list * glob_tactic_expr
+type alias_tactic =
+ { alias_args: Id.t list;
+ alias_body: glob_tactic_expr;
+ alias_deprecation: Vernacinterp.deprecation option;
+ }
(** Contents of a tactic notation *)
val register_alias : alias -> alias_tactic -> unit
(** Register a tactic alias. *)
val interp_alias : alias -> alias_tactic
-(** Recover the the body of an alias. Raises an anomaly if it does not exist. *)
+(** Recover the body of an alias. Raises an anomaly if it does not exist. *)
val check_alias : alias -> bool
(** Returns [true] if an alias is defined, false otherwise. *)
(** {5 Coq tactic definitions} *)
-val register_ltac : bool -> bool -> Id.t -> glob_tactic_expr -> unit
+val register_ltac : bool -> bool -> ?deprecation:deprecation -> Id.t ->
+ glob_tactic_expr -> unit
(** Register a new Ltac with the given name and body.
The first boolean indicates whether this is done from ML side, rather than
@@ -51,7 +57,8 @@ val register_ltac : bool -> bool -> Id.t -> glob_tactic_expr -> unit
definition. It also puts the Ltac name in the nametab, so that it can be
used unqualified. *)
-val redefine_ltac : bool -> KerName.t -> glob_tactic_expr -> unit
+val redefine_ltac : bool -> ?deprecation:deprecation -> KerName.t ->
+ glob_tactic_expr -> unit
(** Replace a Ltac with the given name and body. If the boolean flag is set
to true, then this is a local redefinition. *)
@@ -61,6 +68,9 @@ val interp_ltac : KerName.t -> glob_tactic_expr
val is_ltac_for_ml_tactic : KerName.t -> bool
(** Whether the tactic is defined from ML-side *)
+val tac_deprecation : KerName.t -> deprecation option
+(** The tactic deprecation notice, if any *)
+
type ltac_entry = {
tac_for_ml : bool;
(** Whether the tactic is defined from ML-side *)
@@ -68,6 +78,8 @@ type ltac_entry = {
(** The current body of the tactic *)
tac_redef : ModPath.t list;
(** List of modules redefining the tactic in reverse chronological order *)
+ tac_deprecation : deprecation option;
+ (** Deprecation notice to be printed when the tactic is used *)
}
val ltac_entries : unit -> ltac_entry KNmap.t
diff --git a/plugins/ltac/tacexpr.ml b/plugins/ltac/tacexpr.ml
index 06d2711ad1..59b748e25e 100644
--- a/plugins/ltac/tacexpr.ml
+++ b/plugins/ltac/tacexpr.ml
@@ -398,5 +398,5 @@ type ltac_call_kind =
type ltac_trace = ltac_call_kind Loc.located list
type tacdef_body =
- | TacticDefinition of lident * raw_tactic_expr (* indicates that user employed ':=' in Ltac body *)
- | TacticRedefinition of qualid * raw_tactic_expr (* indicates that user employed '::=' in Ltac body *)
+ | TacticDefinition of lident * raw_tactic_expr (* indicates that user employed ':=' in Ltac body *)
+ | TacticRedefinition of qualid * raw_tactic_expr (* indicates that user employed '::=' in Ltac body *)
diff --git a/plugins/ltac/tacexpr.mli b/plugins/ltac/tacexpr.mli
index 71e1edfd7d..3a0badb28f 100644
--- a/plugins/ltac/tacexpr.mli
+++ b/plugins/ltac/tacexpr.mli
@@ -398,5 +398,5 @@ type ltac_call_kind =
type ltac_trace = ltac_call_kind Loc.located list
type tacdef_body =
- | TacticDefinition of lident * raw_tactic_expr (* indicates that user employed ':=' in Ltac body *)
- | TacticRedefinition of qualid * raw_tactic_expr (* indicates that user employed '::=' in Ltac body *)
+ | TacticDefinition of lident * raw_tactic_expr (* indicates that user employed ':=' in Ltac body *)
+ | TacticRedefinition of qualid * raw_tactic_expr (* indicates that user employed '::=' in Ltac body *)
diff --git a/plugins/ltac/tacintern.ml b/plugins/ltac/tacintern.ml
index 481fc30df2..1444800624 100644
--- a/plugins/ltac/tacintern.ml
+++ b/plugins/ltac/tacintern.ml
@@ -117,9 +117,26 @@ let intern_constr_reference strict ist qid =
(* Internalize an isolated reference in position of tactic *)
+let warn_deprecated_tactic =
+ CWarnings.create ~name:"deprecated-tactic" ~category:"deprecated"
+ (fun (qid,depr) -> str "Tactic " ++ pr_qualid qid ++
+ strbrk " is deprecated" ++
+ pr_opt (fun since -> str "since " ++ str since) depr.Vernacinterp.since ++
+ str "." ++ pr_opt (fun note -> str note) depr.Vernacinterp.note)
+
+let warn_deprecated_alias =
+ CWarnings.create ~name:"deprecated-tactic-notation" ~category:"deprecated"
+ (fun (kn,depr) -> str "Tactic Notation " ++ Pptactic.pr_alias_key kn ++
+ strbrk " is deprecated since" ++
+ pr_opt (fun since -> str "since " ++ str since) depr.Vernacinterp.since ++
+ str "." ++ pr_opt (fun note -> str note) depr.Vernacinterp.note)
+
let intern_isolated_global_tactic_reference qid =
let loc = qid.CAst.loc in
- TacCall (Loc.tag ?loc (ArgArg (loc,Tacenv.locate_tactic qid),[]))
+ let kn = Tacenv.locate_tactic qid in
+ Option.iter (fun depr -> warn_deprecated_tactic ?loc (qid,depr)) @@
+ Tacenv.tac_deprecation kn;
+ TacCall (Loc.tag ?loc (ArgArg (loc,kn),[]))
let intern_isolated_tactic_reference strict ist qid =
(* An ltac reference *)
@@ -137,7 +154,11 @@ let intern_isolated_tactic_reference strict ist qid =
(* Internalize an applied tactic reference *)
let intern_applied_global_tactic_reference qid =
- ArgArg (qid.CAst.loc,Tacenv.locate_tactic qid)
+ let loc = qid.CAst.loc in
+ let kn = Tacenv.locate_tactic qid in
+ Option.iter (fun depr -> warn_deprecated_tactic ?loc (qid,depr)) @@
+ Tacenv.tac_deprecation kn;
+ ArgArg (loc,kn)
let intern_applied_tactic_reference ist qid =
(* An ltac reference *)
@@ -643,6 +664,8 @@ and intern_tactic_seq onlytac ist = function
(* For extensions *)
| TacAlias (loc,(s,l)) ->
+ let alias = Tacenv.interp_alias s in
+ Option.iter (fun o -> warn_deprecated_alias ?loc (s,o)) @@ alias.Tacenv.alias_deprecation;
let l = List.map (intern_tacarg !strict_check false ist) l in
ist.ltacvars, TacAlias (Loc.tag ?loc (s,l))
| TacML (loc,(opn,l)) ->
diff --git a/plugins/ltac/tacinterp.ml b/plugins/ltac/tacinterp.ml
index 9d1cc1643c..a0446bd6a0 100644
--- a/plugins/ltac/tacinterp.ml
+++ b/plugins/ltac/tacinterp.ml
@@ -141,16 +141,6 @@ let extract_trace ist = match TacStore.get ist.extra f_trace with
| None -> []
| Some l -> l
-module Value = struct
-
- include Taccoerce.Value
-
- let of_closure ist tac =
- let closure = VFun (UnnamedAppl,extract_trace ist, ist.lfun, [], tac) in
- of_tacvalue closure
-
-end
-
let print_top_val env v = Pptactic.pr_value Pptactic.ltop v
let catching_error call_trace fail (e, info) =
@@ -312,11 +302,11 @@ let interp_name ist env sigma = function
| Name id -> Name (interp_ident ist env sigma id)
let interp_intro_pattern_var loc ist env sigma id =
- try try_interp_ltac_var (coerce_to_intro_pattern env sigma) ist (Some (env,sigma)) (make ?loc id)
+ try try_interp_ltac_var (coerce_to_intro_pattern sigma) ist (Some (env,sigma)) (make ?loc id)
with Not_found -> IntroNaming (IntroIdentifier id)
let interp_intro_pattern_naming_var loc ist env sigma id =
- try try_interp_ltac_var (coerce_to_intro_pattern_naming env sigma) ist (Some (env,sigma)) (make ?loc id)
+ try try_interp_ltac_var (coerce_to_intro_pattern_naming sigma) ist (Some (env,sigma)) (make ?loc id)
with Not_found -> IntroIdentifier id
let interp_int ist ({loc;v=id} as locid) =
@@ -357,7 +347,7 @@ let interp_hyp_list ist env sigma l =
let interp_reference ist env sigma = function
| ArgArg (_,r) -> r
| ArgVar {loc;v=id} ->
- try try_interp_ltac_var (coerce_to_reference env sigma) ist (Some (env,sigma)) (make ?loc id)
+ try try_interp_ltac_var (coerce_to_reference sigma) ist (Some (env,sigma)) (make ?loc id)
with Not_found ->
try
VarRef (get_id (Environ.lookup_named id env))
@@ -451,7 +441,7 @@ let default_fresh_id = Id.of_string "H"
let interp_fresh_id ist env sigma l =
let extract_ident ist env sigma id =
- try try_interp_ltac_var (coerce_to_ident_not_fresh env sigma)
+ try try_interp_ltac_var (coerce_to_ident_not_fresh sigma)
ist (Some (env,sigma)) (make id)
with Not_found -> id in
let ids = List.map_filter (function ArgVar {v=id} -> Some id | _ -> None) l in
@@ -474,7 +464,7 @@ let interp_fresh_id ist env sigma l =
(* Extract the uconstr list from lfun *)
let extract_ltac_constr_context ist env sigma =
let add_uconstr id v map =
- try Id.Map.add id (coerce_to_uconstr env v) map
+ try Id.Map.add id (coerce_to_uconstr v) map
with CannotCoerceTo _ -> map
in
let add_constr id v map =
@@ -799,7 +789,7 @@ and interp_or_and_intro_pattern ist env sigma = function
and interp_intro_pattern_list_as_list ist env sigma = function
| [{loc;v=IntroNaming (IntroIdentifier id)}] as l ->
- (try sigma, coerce_to_intro_pattern_list ?loc env sigma (Id.Map.find id ist.lfun)
+ (try sigma, coerce_to_intro_pattern_list ?loc sigma (Id.Map.find id ist.lfun)
with Not_found | CannotCoerceTo _ ->
List.fold_left_map (interp_intro_pattern ist env) sigma l)
| l -> List.fold_left_map (interp_intro_pattern ist env) sigma l
@@ -842,7 +832,7 @@ let interp_declared_or_quantified_hypothesis ist env sigma = function
| AnonHyp n -> AnonHyp n
| NamedHyp id ->
try try_interp_ltac_var
- (coerce_to_decl_or_quant_hyp env sigma) ist (Some (env,sigma)) (make id)
+ (coerce_to_decl_or_quant_hyp sigma) ist (Some (env,sigma)) (make id)
with Not_found -> NamedHyp id
let interp_binding ist env sigma {loc;v=(b,c)} =
@@ -1125,17 +1115,17 @@ and eval_tactic ist tac : unit Proofview.tactic = match tac with
| TacSelect (sel, tac) -> Tacticals.New.tclSELECT sel (interp_tactic ist tac)
(* For extensions *)
| TacAlias (loc,(s,l)) ->
- let (ids, body) = Tacenv.interp_alias s in
+ let alias = Tacenv.interp_alias s in
let (>>=) = Ftactic.bind in
let interp_vars = Ftactic.List.map (fun v -> interp_tacarg ist v) l in
let tac l =
let addvar x v accu = Id.Map.add x v accu in
- let lfun = List.fold_right2 addvar ids l ist.lfun in
+ let lfun = List.fold_right2 addvar alias.Tacenv.alias_args l ist.lfun in
Ftactic.lift (push_trace (loc,LtacNotationCall s) ist) >>= fun trace ->
let ist = {
lfun = lfun;
extra = TacStore.set ist.extra f_trace trace; } in
- val_interp ist body >>= fun v ->
+ val_interp ist alias.Tacenv.alias_body >>= fun v ->
Ftactic.lift (tactic_of_value ist v)
in
let tac =
@@ -1147,7 +1137,7 @@ and eval_tactic ist tac : unit Proofview.tactic = match tac with
some more elaborate solution will have to be used. *)
in
let tac =
- let len1 = List.length ids in
+ let len1 = List.length alias.Tacenv.alias_args in
let len2 = List.length l in
if len1 = len2 then tac
else Tacticals.New.tclZEROMSG (str "Arguments length mismatch: \
@@ -1860,6 +1850,31 @@ let eval_tactic_ist ist t =
Proofview.tclLIFT db_initialize <*>
interp_tactic ist t
+(** FFI *)
+
+module Value = struct
+
+ include Taccoerce.Value
+
+ let of_closure ist tac =
+ let closure = VFun (UnnamedAppl,extract_trace ist, ist.lfun, [], tac) in
+ of_tacvalue closure
+
+ (** Apply toplevel tactic values *)
+ let apply (f : value) (args: value list) =
+ let fold arg (i, vars, lfun) =
+ let id = Id.of_string ("x" ^ string_of_int i) in
+ let x = Reference (ArgVar CAst.(make id)) in
+ (succ i, x :: vars, Id.Map.add id arg lfun)
+ in
+ let (_, args, lfun) = List.fold_right fold args (0, [], Id.Map.empty) in
+ let lfun = Id.Map.add (Id.of_string "F") f lfun in
+ let ist = { (default_ist ()) with lfun = lfun; } in
+ let tac = TacArg(Loc.tag @@ TacCall (Loc.tag (ArgVar CAst.(make @@ Id.of_string "F"),args))) in
+ eval_tactic_ist ist tac
+
+end
+
(* globalization + interpretation *)
diff --git a/plugins/ltac/tacinterp.mli b/plugins/ltac/tacinterp.mli
index fd2d96bd62..f9883e4441 100644
--- a/plugins/ltac/tacinterp.mli
+++ b/plugins/ltac/tacinterp.mli
@@ -28,6 +28,7 @@ sig
val to_list : t -> t list option
val of_closure : Geninterp.interp_sign -> glob_tactic_expr -> t
val cast : 'a typed_abstract_argument_type -> Geninterp.Val.t -> 'a
+ val apply : t -> t list -> unit Proofview.tactic
end
(** Values for interpretation *)
diff --git a/plugins/micromega/Fourier.v b/plugins/micromega/Fourier.v
new file mode 100644
index 0000000000..0153de1dab
--- /dev/null
+++ b/plugins/micromega/Fourier.v
@@ -0,0 +1,5 @@
+Require Import Lra.
+Require Export Fourier_util.
+
+#[deprecated(since = "8.9.0", note = "Use lra instead.")]
+Ltac fourier := lra.
diff --git a/plugins/micromega/Fourier_util.v b/plugins/micromega/Fourier_util.v
new file mode 100644
index 0000000000..b62153dee4
--- /dev/null
+++ b/plugins/micromega/Fourier_util.v
@@ -0,0 +1,31 @@
+Require Export Rbase.
+Require Import Lra.
+
+Open Scope R_scope.
+
+Lemma Rlt_mult_inv_pos : forall x y:R, 0 < x -> 0 < y -> 0 < x * / y.
+intros x y H H0; try assumption.
+replace 0 with (x * 0).
+apply Rmult_lt_compat_l; auto with real.
+ring.
+Qed.
+
+Lemma Rlt_zero_pos_plus1 : forall x:R, 0 < x -> 0 < 1 + x.
+intros x H; try assumption.
+rewrite Rplus_comm.
+apply Rle_lt_0_plus_1.
+red; auto with real.
+Qed.
+
+Lemma Rle_zero_pos_plus1 : forall x:R, 0 <= x -> 0 <= 1 + x.
+ intros; lra.
+Qed.
+
+Lemma Rle_mult_inv_pos : forall x y:R, 0 <= x -> 0 < y -> 0 <= x * / y.
+intros x y H H0; try assumption.
+case H; intros.
+red; left.
+apply Rlt_mult_inv_pos; auto with real.
+rewrite <- H1.
+red; right; ring.
+Qed.
diff --git a/plugins/micromega/g_micromega.ml4 b/plugins/micromega/g_micromega.mlg
index 81140a46a9..21f0414e9c 100644
--- a/plugins/micromega/g_micromega.ml4
+++ b/plugins/micromega/g_micromega.mlg
@@ -16,70 +16,74 @@
(* *)
(************************************************************************)
+{
+
open Ltac_plugin
open Stdarg
open Tacarg
+}
+
DECLARE PLUGIN "micromega_plugin"
TACTIC EXTEND RED
-| [ "myred" ] -> [ Tactics.red_in_concl ]
+| [ "myred" ] -> { Tactics.red_in_concl }
END
TACTIC EXTEND PsatzZ
-| [ "psatz_Z" int_or_var(i) tactic(t) ] -> [ (Coq_micromega.psatz_Z i
+| [ "psatz_Z" int_or_var(i) tactic(t) ] -> { (Coq_micromega.psatz_Z i
(Tacinterp.tactic_of_value ist t))
- ]
-| [ "psatz_Z" tactic(t)] -> [ (Coq_micromega.psatz_Z (-1)) (Tacinterp.tactic_of_value ist t) ]
+ }
+| [ "psatz_Z" tactic(t)] -> { (Coq_micromega.psatz_Z (-1)) (Tacinterp.tactic_of_value ist t) }
END
TACTIC EXTEND Lia
-[ "xlia" tactic(t) ] -> [ (Coq_micromega.xlia (Tacinterp.tactic_of_value ist t)) ]
+| [ "xlia" tactic(t) ] -> { (Coq_micromega.xlia (Tacinterp.tactic_of_value ist t)) }
END
TACTIC EXTEND Nia
-[ "xnlia" tactic(t) ] -> [ (Coq_micromega.xnlia (Tacinterp.tactic_of_value ist t)) ]
+| [ "xnlia" tactic(t) ] -> { (Coq_micromega.xnlia (Tacinterp.tactic_of_value ist t)) }
END
TACTIC EXTEND NRA
-[ "xnra" tactic(t) ] -> [ (Coq_micromega.nra (Tacinterp.tactic_of_value ist t))]
+| [ "xnra" tactic(t) ] -> { (Coq_micromega.nra (Tacinterp.tactic_of_value ist t))}
END
TACTIC EXTEND NQA
-[ "xnqa" tactic(t) ] -> [ (Coq_micromega.nqa (Tacinterp.tactic_of_value ist t))]
+| [ "xnqa" tactic(t) ] -> { (Coq_micromega.nqa (Tacinterp.tactic_of_value ist t))}
END
TACTIC EXTEND Sos_Z
-| [ "sos_Z" tactic(t) ] -> [ (Coq_micromega.sos_Z (Tacinterp.tactic_of_value ist t)) ]
+| [ "sos_Z" tactic(t) ] -> { (Coq_micromega.sos_Z (Tacinterp.tactic_of_value ist t)) }
END
TACTIC EXTEND Sos_Q
-| [ "sos_Q" tactic(t) ] -> [ (Coq_micromega.sos_Q (Tacinterp.tactic_of_value ist t)) ]
+| [ "sos_Q" tactic(t) ] -> { (Coq_micromega.sos_Q (Tacinterp.tactic_of_value ist t)) }
END
TACTIC EXTEND Sos_R
-| [ "sos_R" tactic(t) ] -> [ (Coq_micromega.sos_R (Tacinterp.tactic_of_value ist t)) ]
+| [ "sos_R" tactic(t) ] -> { (Coq_micromega.sos_R (Tacinterp.tactic_of_value ist t)) }
END
TACTIC EXTEND LRA_Q
-[ "lra_Q" tactic(t) ] -> [ (Coq_micromega.lra_Q (Tacinterp.tactic_of_value ist t)) ]
+| [ "lra_Q" tactic(t) ] -> { (Coq_micromega.lra_Q (Tacinterp.tactic_of_value ist t)) }
END
TACTIC EXTEND LRA_R
-[ "lra_R" tactic(t) ] -> [ (Coq_micromega.lra_R (Tacinterp.tactic_of_value ist t)) ]
+| [ "lra_R" tactic(t) ] -> { (Coq_micromega.lra_R (Tacinterp.tactic_of_value ist t)) }
END
TACTIC EXTEND PsatzR
-| [ "psatz_R" int_or_var(i) tactic(t) ] -> [ (Coq_micromega.psatz_R i (Tacinterp.tactic_of_value ist t)) ]
-| [ "psatz_R" tactic(t) ] -> [ (Coq_micromega.psatz_R (-1) (Tacinterp.tactic_of_value ist t)) ]
+| [ "psatz_R" int_or_var(i) tactic(t) ] -> { (Coq_micromega.psatz_R i (Tacinterp.tactic_of_value ist t)) }
+| [ "psatz_R" tactic(t) ] -> { (Coq_micromega.psatz_R (-1) (Tacinterp.tactic_of_value ist t)) }
END
TACTIC EXTEND PsatzQ
-| [ "psatz_Q" int_or_var(i) tactic(t) ] -> [ (Coq_micromega.psatz_Q i (Tacinterp.tactic_of_value ist t)) ]
-| [ "psatz_Q" tactic(t) ] -> [ (Coq_micromega.psatz_Q (-1) (Tacinterp.tactic_of_value ist t)) ]
+| [ "psatz_Q" int_or_var(i) tactic(t) ] -> { (Coq_micromega.psatz_Q i (Tacinterp.tactic_of_value ist t)) }
+| [ "psatz_Q" tactic(t) ] -> { (Coq_micromega.psatz_Q (-1) (Tacinterp.tactic_of_value ist t)) }
END
diff --git a/plugins/micromega/mutils.mli b/plugins/micromega/mutils.mli
index 7b7a090de0..094429ea18 100644
--- a/plugins/micromega/mutils.mli
+++ b/plugins/micromega/mutils.mli
@@ -30,7 +30,7 @@ end
module TagSet : CSig.SetS with type elt = Tag.t
-val pp_list : (out_channel -> 'a -> 'b) -> out_channel -> 'a list -> unit
+val pp_list : (out_channel -> 'a -> unit) -> out_channel -> 'a list -> unit
module CamlToCoq : sig
diff --git a/plugins/nsatz/g_nsatz.ml4 b/plugins/nsatz/g_nsatz.mlg
index 4ac49adb90..16ff512e8d 100644
--- a/plugins/nsatz/g_nsatz.ml4
+++ b/plugins/nsatz/g_nsatz.mlg
@@ -8,11 +8,15 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
+{
+
open Ltac_plugin
open Stdarg
+}
+
DECLARE PLUGIN "nsatz_plugin"
TACTIC EXTEND nsatz_compute
-| [ "nsatz_compute" constr(lt) ] -> [ Nsatz.nsatz_compute (EConstr.Unsafe.to_constr lt) ]
+| [ "nsatz_compute" constr(lt) ] -> { Nsatz.nsatz_compute (EConstr.Unsafe.to_constr lt) }
END
diff --git a/plugins/omega/coq_omega.ml b/plugins/omega/coq_omega.ml
index 6f41388284..e14c4e2ec1 100644
--- a/plugins/omega/coq_omega.ml
+++ b/plugins/omega/coq_omega.ml
@@ -38,15 +38,9 @@ open OmegaSolver
(* Added by JCF, 09/03/98 *)
-let elim_id id =
- Proofview.Goal.enter begin fun gl ->
- simplest_elim (mkVar id)
- end
-let resolve_id id = Proofview.Goal.enter begin fun gl ->
- apply (mkVar id)
-end
+let elim_id id = simplest_elim (mkVar id)
-let timing timer_name f arg = f arg
+let resolve_id id = apply (mkVar id)
let display_time_flag = ref false
let display_system_flag = ref false
diff --git a/plugins/omega/g_omega.ml4 b/plugins/omega/g_omega.mlg
index 170b937c99..c3d063cff8 100644
--- a/plugins/omega/g_omega.ml4
+++ b/plugins/omega/g_omega.mlg
@@ -18,6 +18,8 @@
DECLARE PLUGIN "omega_plugin"
+{
+
open Ltac_plugin
open Names
open Coq_omega
@@ -43,14 +45,15 @@ let omega_tactic l =
(Tacticals.New.tclREPEAT (Tacticals.New.tclTHENLIST tacs))
(omega_solver)
+}
TACTIC EXTEND omega
-| [ "omega" ] -> [ omega_tactic [] ]
+| [ "omega" ] -> { omega_tactic [] }
END
TACTIC EXTEND omega'
| [ "omega" "with" ne_ident_list(l) ] ->
- [ omega_tactic (List.map Names.Id.to_string l) ]
-| [ "omega" "with" "*" ] -> [ omega_tactic ["nat";"positive";"N";"Z"] ]
+ { omega_tactic (List.map Names.Id.to_string l) }
+| [ "omega" "with" "*" ] -> { omega_tactic ["nat";"positive";"N";"Z"] }
END
diff --git a/plugins/quote/g_quote.ml4 b/plugins/quote/g_quote.mlg
index 09209dc228..749903c3ad 100644
--- a/plugins/quote/g_quote.ml4
+++ b/plugins/quote/g_quote.mlg
@@ -8,6 +8,8 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
+{
+
open Ltac_plugin
open Names
open Tacexpr
@@ -16,8 +18,12 @@ open Quote
open Stdarg
open Tacarg
+}
+
DECLARE PLUGIN "quote_plugin"
+{
+
let cont = Id.of_string "cont"
let x = Id.of_string "x"
@@ -27,12 +33,14 @@ let make_cont (k : Val.t) (c : EConstr.t) =
let ist = { lfun = Id.Map.add cont k (Id.Map.singleton x c); extra = TacStore.empty; } in
Tacinterp.eval_tactic_ist ist (TacArg (Loc.tag tac))
+}
+
TACTIC EXTEND quote
- [ "quote" ident(f) ] -> [ quote f [] ]
-| [ "quote" ident(f) "[" ne_ident_list(lc) "]"] -> [ quote f lc ]
+| [ "quote" ident(f) ] -> { quote f [] }
+| [ "quote" ident(f) "[" ne_ident_list(lc) "]"] -> { quote f lc }
| [ "quote" ident(f) "in" constr(c) "using" tactic(k) ] ->
- [ gen_quote (make_cont k) c f [] ]
+ { gen_quote (make_cont k) c f [] }
| [ "quote" ident(f) "[" ne_ident_list(lc) "]"
"in" constr(c) "using" tactic(k) ] ->
- [ gen_quote (make_cont k) c f lc ]
+ { gen_quote (make_cont k) c f lc }
END
diff --git a/plugins/romega/g_romega.ml4 b/plugins/romega/g_romega.mlg
index 5b77d08dea..c1ce30027e 100644
--- a/plugins/romega/g_romega.ml4
+++ b/plugins/romega/g_romega.mlg
@@ -9,6 +9,8 @@
DECLARE PLUGIN "romega_plugin"
+{
+
open Ltac_plugin
open Names
open Refl_omega
@@ -39,13 +41,15 @@ let romega_tactic unsafe l =
(Tactics.intros)
(total_reflexive_omega_tactic unsafe))
+}
+
TACTIC EXTEND romega
-| [ "romega" ] -> [ romega_tactic false [] ]
-| [ "unsafe_romega" ] -> [ romega_tactic true [] ]
+| [ "romega" ] -> { romega_tactic false [] }
+| [ "unsafe_romega" ] -> { romega_tactic true [] }
END
TACTIC EXTEND romega'
| [ "romega" "with" ne_ident_list(l) ] ->
- [ romega_tactic false (List.map Names.Id.to_string l) ]
-| [ "romega" "with" "*" ] -> [ romega_tactic false ["nat";"positive";"N";"Z"] ]
+ { romega_tactic false (List.map Names.Id.to_string l) }
+| [ "romega" "with" "*" ] -> { romega_tactic false ["nat";"positive";"N";"Z"] }
END
diff --git a/plugins/rtauto/g_rtauto.ml4 b/plugins/rtauto/g_rtauto.mlg
index aa67576348..9c9fdcfa2f 100644
--- a/plugins/rtauto/g_rtauto.ml4
+++ b/plugins/rtauto/g_rtauto.mlg
@@ -8,12 +8,15 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
+{
open Ltac_plugin
+}
+
DECLARE PLUGIN "rtauto_plugin"
TACTIC EXTEND rtauto
- [ "rtauto" ] -> [ Proofview.V82.tactic (Refl_tauto.rtauto_tac) ]
+| [ "rtauto" ] -> { Proofview.V82.tactic (Refl_tauto.rtauto_tac) }
END
diff --git a/plugins/setoid_ring/g_newring.ml4 b/plugins/setoid_ring/g_newring.ml4
index e9ce306e86..4ea0b30bd7 100644
--- a/plugins/setoid_ring/g_newring.ml4
+++ b/plugins/setoid_ring/g_newring.ml4
@@ -29,11 +29,6 @@ TACTIC EXTEND protect_fv
[ protect_tac map ]
END
-TACTIC EXTEND closed_term
- [ "closed_term" constr(t) "[" ne_reference_list(l) "]" ] ->
- [ closed_term t l ]
-END
-
open Pptactic
open Ppconstr
diff --git a/plugins/setoid_ring/newring.ml b/plugins/setoid_ring/newring.ml
index 84b29a0bfb..a736eec5e7 100644
--- a/plugins/setoid_ring/newring.ml
+++ b/plugins/setoid_ring/newring.ml
@@ -96,34 +96,36 @@ let protect_tac_in map id =
(****************************************************************************)
-let closed_term t l =
- let open Quote_plugin in
+let rec closed_under sigma cset t =
+ try
+ let (gr, _) = Termops.global_of_constr sigma t in
+ Refset_env.mem gr cset
+ with Not_found ->
+ match EConstr.kind sigma t with
+ | Cast(c,_,_) -> closed_under sigma cset c
+ | App(f,l) -> closed_under sigma cset f && Array.for_all (closed_under sigma cset) l
+ | _ -> false
+
+let closed_term args _ = match args with
+| [t; l] ->
+ let t = Option.get (Value.to_constr t) in
+ let l = List.map (fun c -> Value.cast (Genarg.topwit Stdarg.wit_ref) c) (Option.get (Value.to_list l)) in
Proofview.tclEVARMAP >>= fun sigma ->
- let l = List.map UnivGen.constr_of_global l in
- let cs = List.fold_right Quote.ConstrSet.add l Quote.ConstrSet.empty in
- if Quote.closed_under sigma cs t then Proofview.tclUNIT () else Tacticals.New.tclFAIL 0 (mt())
+ let cs = List.fold_right Refset_env.add l Refset_env.empty in
+ if closed_under sigma cs t then Proofview.tclUNIT () else Tacticals.New.tclFAIL 0 (mt())
+| _ -> assert false
-(* TACTIC EXTEND echo
-| [ "echo" constr(t) ] ->
- [ Pp.msg (Termops.print_constr t); Tacinterp.eval_tactic (TacId []) ]
-END;;*)
-
-(*
-let closed_term_ast l =
- TacFun([Some(Id.of_string"t")],
- TacAtom(Loc.ghost,TacExtend(Loc.ghost,"closed_term",
- [Genarg.in_gen Constrarg.wit_constr (mkVar(Id.of_string"t"));
- Genarg.in_gen (Genarg.wit_list Constrarg.wit_ref) l])))
-*)
-let closed_term_ast l =
+let closed_term_ast =
let tacname = {
mltac_plugin = "newring_plugin";
mltac_tactic = "closed_term";
} in
+ let () = Tacenv.register_ml_tactic tacname [|closed_term|] in
let tacname = {
mltac_name = tacname;
mltac_index = 0;
} in
+ fun l ->
let l = List.map (fun gr -> ArgArg(Loc.tag gr)) l in
TacFun([Name(Id.of_string"t")],
TacML(Loc.tag (tacname,
@@ -148,8 +150,7 @@ let ic_unsafe c = (*FIXME remove *)
let decl_constant na univs c =
let open Constr in
- let env = Global.env () in
- let vars = Univops.universes_of_constr env c in
+ let vars = Univops.universes_of_constr c in
let univs = Univops.restrict_universe_context univs vars in
let univs = Monomorphic_const_entry univs in
mkConst(declare_constant (Id.of_string na)
@@ -160,21 +161,6 @@ let decl_constant na univs c =
let ltac_call tac (args:glob_tactic_arg list) =
TacArg(Loc.tag @@ TacCall (Loc.tag (ArgArg(Loc.tag @@ Lazy.force tac),args)))
-(* Calling a locally bound tactic *)
-let ltac_lcall tac args =
- TacArg(Loc.tag @@ TacCall (Loc.tag (ArgVar CAst.(make @@ Id.of_string tac),args)))
-
-let ltac_apply (f : Value.t) (args: Tacinterp.Value.t list) =
- let fold arg (i, vars, lfun) =
- let id = Id.of_string ("x" ^ string_of_int i) in
- let x = Reference (ArgVar CAst.(make id)) in
- (succ i, x :: vars, Id.Map.add id arg lfun)
- in
- let (_, args, lfun) = List.fold_right fold args (0, [], Id.Map.empty) in
- let lfun = Id.Map.add (Id.of_string "F") f lfun in
- let ist = { (Tacinterp.default_ist ()) with Tacinterp.lfun = lfun; } in
- Tacinterp.eval_tactic_ist ist (ltac_lcall "F" args)
-
let dummy_goal env sigma =
let (gl,_,sigma) =
Goal.V82.mk_goal sigma (named_context_val env) EConstr.mkProp Evd.Store.empty in
@@ -764,7 +750,7 @@ let ring_lookup (f : Value.t) lH rl t =
let rl = Value.of_constr (make_term_list env evdref (EConstr.of_constr e.ring_carrier) rl) in
let lH = carg (make_hyp_list env evdref lH) in
let ring = ltac_ring_structure e in
- Proofview.tclTHEN (Proofview.Unsafe.tclEVARS !evdref) (ltac_apply f (ring@[lH;rl]))
+ Proofview.tclTHEN (Proofview.Unsafe.tclEVARS !evdref) (Value.apply f (ring@[lH;rl]))
with e when Proofview.V82.catchable_exception e -> Proofview.tclZERO e
end
@@ -1050,6 +1036,6 @@ let field_lookup (f : Value.t) lH rl t =
let rl = Value.of_constr (make_term_list env evdref (EConstr.of_constr e.field_carrier) rl) in
let lH = carg (make_hyp_list env evdref lH) in
let field = ltac_field_structure e in
- Proofview.tclTHEN (Proofview.Unsafe.tclEVARS !evdref) (ltac_apply f (field@[lH;rl]))
+ Proofview.tclTHEN (Proofview.Unsafe.tclEVARS !evdref) (Value.apply f (field@[lH;rl]))
with e when Proofview.V82.catchable_exception e -> Proofview.tclZERO e
end
diff --git a/plugins/setoid_ring/newring.mli b/plugins/setoid_ring/newring.mli
index 0e056a4722..fcd04a2e73 100644
--- a/plugins/setoid_ring/newring.mli
+++ b/plugins/setoid_ring/newring.mli
@@ -18,8 +18,6 @@ val protect_tac_in : string -> Id.t -> unit Proofview.tactic
val protect_tac : string -> unit Proofview.tactic
-val closed_term : EConstr.constr -> GlobRef.t list -> unit Proofview.tactic
-
val add_theory :
Id.t ->
constr_expr ->
diff --git a/plugins/ssr/ssrbool.v b/plugins/ssr/ssrbool.v
index 7d05b64384..0865f75ec5 100644
--- a/plugins/ssr/ssrbool.v
+++ b/plugins/ssr/ssrbool.v
@@ -61,8 +61,8 @@ Require Import ssreflect ssrfun.
(* classically P <-> we can assume P when proving is_true b. *)
(* := forall b : bool, (P -> b) -> b. *)
(* This is equivalent to ~ (~ P) when P : Prop. *)
-(* implies P Q == wrapper coinductive type that coerces to P -> Q *)
-(* and can be used as a P -> Q view unambigously. *)
+(* implies P Q == wrapper variant type that coerces to P -> Q and *)
+(* can be used as a P -> Q view unambigously. *)
(* Useful to avoid spurious insertion of <-> views *)
(* when Q is a conjunction of foralls, as in Lemma *)
(* all_and2 below; conversely, avoids confusion in *)
@@ -456,7 +456,7 @@ Section BoolIf.
Variables (A B : Type) (x : A) (f : A -> B) (b : bool) (vT vF : A).
-CoInductive if_spec (not_b : Prop) : bool -> A -> Set :=
+Variant if_spec (not_b : Prop) : bool -> A -> Set :=
| IfSpecTrue of b : if_spec not_b true vT
| IfSpecFalse of not_b : if_spec not_b false vF.
@@ -585,7 +585,7 @@ Lemma rwP2 : reflect Q b -> (P <-> Q).
Proof. by move=> Qb; split=> ?; [apply: appP | apply: elimT; case: Qb]. Qed.
(* Predicate family to reflect excluded middle in bool. *)
-CoInductive alt_spec : bool -> Type :=
+Variant alt_spec : bool -> Type :=
| AltTrue of P : alt_spec true
| AltFalse of ~~ b : alt_spec false.
@@ -603,7 +603,7 @@ Hint View for apply// equivPif|3 xorPif|3 equivPifn|3 xorPifn|3.
(* Allow the direct application of a reflection lemma to a boolean assertion. *)
Coercion elimT : reflect >-> Funclass.
-CoInductive implies P Q := Implies of P -> Q.
+Variant implies P Q := Implies of P -> Q.
Lemma impliesP P Q : implies P Q -> P -> Q. Proof. by case. Qed.
Lemma impliesPn (P Q : Prop) : implies P Q -> ~ Q -> ~ P.
Proof. by case=> iP ? /iP. Qed.
@@ -1119,7 +1119,7 @@ Proof. by move=> *; apply/orP; left. Qed.
Lemma subrelUr r1 r2 : subrel r2 (relU r1 r2).
Proof. by move=> *; apply/orP; right. Qed.
-CoInductive mem_pred := Mem of pred T.
+Variant mem_pred := Mem of pred T.
Definition isMem pT topred mem := mem = (fun p : pT => Mem [eta topred p]).
@@ -1329,7 +1329,7 @@ End simpl_mem.
(* Qualifiers and keyed predicates. *)
-CoInductive qualifier (q : nat) T := Qualifier of predPredType T.
+Variant qualifier (q : nat) T := Qualifier of predPredType T.
Coercion has_quality n T (q : qualifier n T) : pred_class :=
fun x => let: Qualifier _ p := q in p x.
@@ -1376,7 +1376,7 @@ Notation "[ 'qualify' 'an' x : T | P ]" := (Qualifier 2 (fun x : T => P%B))
Section KeyPred.
Variable T : Type.
-CoInductive pred_key (p : predPredType T) := DefaultPredKey.
+Variant pred_key (p : predPredType T) := DefaultPredKey.
Variable p : predPredType T.
Structure keyed_pred (k : pred_key p) :=
diff --git a/plugins/ssr/ssrcommon.ml b/plugins/ssr/ssrcommon.ml
index 54f3f9c718..1f3c758e5c 100644
--- a/plugins/ssr/ssrcommon.ml
+++ b/plugins/ssr/ssrcommon.ml
@@ -469,7 +469,7 @@ let ssrevaltac ist gtac = Tacinterp.tactic_of_value ist gtac
(* term mkApp (t', args) is convertible to t. *)
(* This makes a useful shorthand for local definitions in proofs, *)
(* i.e., pose succ := _ + 1 means pose succ := fun n : nat => n + 1, *)
-(* and, in context of the the 4CT library, pose mid := maps id means *)
+(* and, in context of the 4CT library, pose mid := maps id means *)
(* pose mid := fun d : detaSet => @maps d d (@id (datum d)) *)
(* Note that this facility does not extend to set, which tries *)
(* instead to fill holes by matching a goal subterm. *)
diff --git a/plugins/ssr/ssreflect.v b/plugins/ssr/ssreflect.v
index b0a9441385..b4144aa45e 100644
--- a/plugins/ssr/ssreflect.v
+++ b/plugins/ssr/ssreflect.v
@@ -184,7 +184,7 @@ Inductive external_view : Type := tactic_view of Type.
Module TheCanonical.
-CoInductive put vT sT (v1 v2 : vT) (s : sT) := Put.
+Variant put vT sT (v1 v2 : vT) (s : sT) := Put.
Definition get vT sT v s (p : @put vT sT v v s) := let: Put _ _ _ := p in s.
@@ -275,10 +275,10 @@ Notation "{ 'type' 'of' c 'for' s }" := (dependentReturnType c s)
(* We also define a simpler version ("phant" / "Phant") of phantom for the *)
(* common case where p_type is Type. *)
-CoInductive phantom T (p : T) := Phantom.
+Variant phantom T (p : T) := Phantom.
Arguments phantom : clear implicits.
Arguments Phantom : clear implicits.
-CoInductive phant (p : Type) := Phant.
+Variant phant (p : Type) := Phant.
(* Internal tagging used by the implementation of the ssreflect elim. *)
diff --git a/plugins/ssr/ssrequality.ml b/plugins/ssr/ssrequality.ml
index f929e94309..23cbf49c05 100644
--- a/plugins/ssr/ssrequality.ml
+++ b/plugins/ssr/ssrequality.ml
@@ -417,8 +417,6 @@ let rwcltac cl rdx dir sr gl =
then errorstrm Pp.(str "Rewriting impacts evars")
else errorstrm Pp.(str "Dependent type error in rewrite of "
++ pr_constr_env (pf_env gl) (project gl) (Term.mkNamedLambda pattern_id (EConstr.Unsafe.to_constr rdxt) (EConstr.Unsafe.to_constr cl)))
- | CErrors.UserError _ as e -> raise e
- | e -> anomaly ("cvtac's exception: " ^ Printexc.to_string e);
in
tclTHEN cvtac' rwtac gl
diff --git a/plugins/ssr/ssrfun.v b/plugins/ssr/ssrfun.v
index ac2c78249b..b2d5143e36 100644
--- a/plugins/ssr/ssrfun.v
+++ b/plugins/ssr/ssrfun.v
@@ -326,7 +326,7 @@ Section SimplFun.
Variables aT rT : Type.
-CoInductive simpl_fun := SimplFun of aT -> rT.
+Variant simpl_fun := SimplFun of aT -> rT.
Definition fun_of_simpl f := fun x => let: SimplFun lam := f in lam x.
@@ -684,7 +684,7 @@ Section Bijections.
Variables (A B : Type) (f : B -> A).
-CoInductive bijective : Prop := Bijective g of cancel f g & cancel g f.
+Variant bijective : Prop := Bijective g of cancel f g & cancel g f.
Hypothesis bijf : bijective.
diff --git a/plugins/ssr/ssrfwd.ml b/plugins/ssr/ssrfwd.ml
index 7fe2421f90..e367cd32d6 100644
--- a/plugins/ssr/ssrfwd.ml
+++ b/plugins/ssr/ssrfwd.ml
@@ -68,20 +68,14 @@ open Ssripats
let ssrhaveNOtcresolution = Summary.ref ~name:"SSR:havenotcresolution" false
-let inHaveTCResolution = Libobject.declare_object {
- (Libobject.default_object "SSRHAVETCRESOLUTION") with
- Libobject.cache_function = (fun (_,v) -> ssrhaveNOtcresolution := v);
- Libobject.load_function = (fun _ (_,v) -> ssrhaveNOtcresolution := v);
- Libobject.classify_function = (fun v -> Libobject.Keep v);
-}
let _ =
Goptions.declare_bool_option
{ Goptions.optname = "have type classes";
Goptions.optkey = ["SsrHave";"NoTCResolution"];
Goptions.optread = (fun _ -> !ssrhaveNOtcresolution);
Goptions.optdepr = false;
- Goptions.optwrite = (fun b ->
- Lib.add_anonymous_leaf (inHaveTCResolution b)) }
+ Goptions.optwrite = (fun b -> ssrhaveNOtcresolution := b);
+ }
open Constrexpr
diff --git a/plugins/ssr/ssripats.ml b/plugins/ssr/ssripats.ml
index 46fde41150..1dbacf0ff7 100644
--- a/plugins/ssr/ssripats.ml
+++ b/plugins/ssr/ssripats.ml
@@ -379,8 +379,9 @@ let elim_intro_tac ipats ?ist what eqid ssrelim is_rec clr =
let ctx, last = EConstr.decompose_prod_assum sigma concl in
let args = match EConstr.kind_of_type sigma last with
| Term.AtomicType (hd, args) ->
- assert(Ssrcommon.is_protect hd env sigma);
- args
+ if Ssrcommon.is_protect hd env sigma then args
+ else Ssrcommon.errorstrm
+ (Pp.str "Too many names in intro pattern")
| _ -> assert false in
let case = args.(Array.length args-1) in
if not(EConstr.Vars.closed0 sigma case)
diff --git a/plugins/ssr/ssrparser.ml4 b/plugins/ssr/ssrparser.ml4
index 347a1e4e26..8b9c94f2db 100644
--- a/plugins/ssr/ssrparser.ml4
+++ b/plugins/ssr/ssrparser.ml4
@@ -962,6 +962,7 @@ END
(* the default simpl and unfold tactics would erase blindly. *)
open Ssrmatching_plugin.Ssrmatching
+open Ssrmatching_plugin.G_ssrmatching
let pr_wgen = function
| (clr, Some((id,k),None)) -> spc() ++ pr_clear mt clr ++ str k ++ pr_hoi id
@@ -1407,7 +1408,7 @@ let check_seqtacarg dir arg = match snd arg, dir with
CErrors.user_err ?loc (str "expected \"first\"")
| _, _ -> arg
-let ssrorelse = Gram.entry_create "ssrorelse"
+let ssrorelse = Entry.create "ssrorelse"
GEXTEND Gram
GLOBAL: ssrorelse ssrseqarg;
ssrseqidx: [
diff --git a/plugins/ssr/ssrparser.mli b/plugins/ssr/ssrparser.mli
index 7cd3751cef..862a93765d 100644
--- a/plugins/ssr/ssrparser.mli
+++ b/plugins/ssr/ssrparser.mli
@@ -12,11 +12,11 @@
open Ltac_plugin
-val ssrtacarg : Tacexpr.raw_tactic_expr Pcoq.Gram.entry
+val ssrtacarg : Tacexpr.raw_tactic_expr Pcoq.Entry.t
val wit_ssrtacarg : (Tacexpr.raw_tactic_expr, Tacexpr.glob_tactic_expr, Geninterp.Val.t) Genarg.genarg_type
val pr_ssrtacarg : 'a -> 'b -> (Notation_gram.tolerability -> 'c) -> 'c
-val ssrtclarg : Tacexpr.raw_tactic_expr Pcoq.Gram.entry
+val ssrtclarg : Tacexpr.raw_tactic_expr Pcoq.Entry.t
val wit_ssrtclarg : (Tacexpr.raw_tactic_expr, Tacexpr.glob_tactic_expr, Geninterp.Val.t) Genarg.genarg_type
val pr_ssrtclarg : 'a -> 'b -> (Notation_gram.tolerability -> 'c -> 'd) -> 'c -> 'd
diff --git a/plugins/ssr/ssrvernac.ml4 b/plugins/ssr/ssrvernac.ml4
index 7ce2dd64af..989a6c5bf1 100644
--- a/plugins/ssr/ssrvernac.ml4
+++ b/plugins/ssr/ssrvernac.ml4
@@ -24,7 +24,6 @@ open Ltac_plugin
open Notation_ops
open Notation_term
open Glob_term
-open Globnames
open Stdarg
open Genarg
open Decl_kinds
@@ -218,8 +217,8 @@ let interp_search_notation ?loc tag okey =
(Bytes.set s' i' '_'; loop (j + 1) (i' + 2))
else (String.blit s i s' i' m; loop (j + 1) (i' + m + 1)) in
loop 0 1 in
- let trim_ntn (pntn, m) = Bytes.sub_string pntn 1 (max 0 m) in
- let pr_ntn ntn = str "(" ++ str ntn ++ str ")" in
+ let trim_ntn (pntn, m) = (InConstrEntrySomeLevel,Bytes.sub_string pntn 1 (max 0 m)) in
+ let pr_ntn ntn = str "(" ++ Notation.pr_notation ntn ++ str ")" in
let pr_and_list pr = function
| [x] -> pr x
| x :: lx -> pr_list pr_comma pr lx ++ pr_comma () ++ str "and " ++ pr x
@@ -294,7 +293,7 @@ let interp_search_notation ?loc tag okey =
let scs' = List.remove (=) sc !scs in
let w = pr_ntn ntn ++ str " is also defined " ++ pr_scs scs' in
Feedback.msg_warning (hov 4 w)
- else if String.string_contains ~where:ntn ~what:" .. " then
+ else if String.string_contains ~where:(snd ntn) ~what:" .. " then
err (pr_ntn ntn ++ str " is an n-ary notation");
let nvars = List.filter (fun (_,(_,typ)) -> typ = NtnTypeConstr) nvars in
let rec sub () = function
@@ -359,13 +358,12 @@ let coerce_search_pattern_to_sort hpat =
true, cp
with _ -> false, [] in
let coerce hp coe_index =
- let coe = Classops.get_coercion_value coe_index in
+ let coe_ref = coe_index.Classops.coe_value in
try
- let coe_ref = global_of_constr coe in
let n_imps = Option.get (Classops.hide_coercion coe_ref) in
mkPApp (Pattern.PRef coe_ref) n_imps [|hp|]
- with _ ->
- errorstrm (str "need explicit coercion " ++ pr_constr_env env sigma coe ++ spc ()
+ with Not_found | Option.IsNone ->
+ errorstrm (str "need explicit coercion " ++ pr_global coe_ref ++ spc ()
++ str "to interpret head search pattern as type") in
filter_head, List.fold_left coerce hpat' coe_path
diff --git a/plugins/ssrmatching/g_ssrmatching.ml4 b/plugins/ssrmatching/g_ssrmatching.ml4
new file mode 100644
index 0000000000..746c368aa9
--- /dev/null
+++ b/plugins/ssrmatching/g_ssrmatching.ml4
@@ -0,0 +1,101 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+open Ltac_plugin
+open Genarg
+open Pcoq
+open Pcoq.Constr
+open Ssrmatching
+open Ssrmatching.Internal
+
+(* Defining grammar rules with "xx" in it automatically declares keywords too,
+ * we thus save the lexer to restore it at the end of the file *)
+let frozen_lexer = CLexer.get_keyword_state () ;;
+
+DECLARE PLUGIN "ssrmatching_plugin"
+
+let pr_rpattern _ _ _ = pr_rpattern
+
+ARGUMENT EXTEND rpattern
+ TYPED AS rpatternty
+ PRINTED BY pr_rpattern
+ INTERPRETED BY interp_rpattern
+ GLOBALIZED BY glob_rpattern
+ SUBSTITUTED BY subst_rpattern
+ | [ lconstr(c) ] -> [ mk_rpattern (T (mk_lterm c None)) ]
+ | [ "in" lconstr(c) ] -> [ mk_rpattern (In_T (mk_lterm c None)) ]
+ | [ lconstr(x) "in" lconstr(c) ] ->
+ [ mk_rpattern (X_In_T (mk_lterm x None, mk_lterm c None)) ]
+ | [ "in" lconstr(x) "in" lconstr(c) ] ->
+ [ mk_rpattern (In_X_In_T (mk_lterm x None, mk_lterm c None)) ]
+ | [ lconstr(e) "in" lconstr(x) "in" lconstr(c) ] ->
+ [ mk_rpattern (E_In_X_In_T (mk_lterm e None, mk_lterm x None, mk_lterm c None)) ]
+ | [ lconstr(e) "as" lconstr(x) "in" lconstr(c) ] ->
+ [ mk_rpattern (E_As_X_In_T (mk_lterm e None, mk_lterm x None, mk_lterm c None)) ]
+END
+
+let pr_ssrterm _ _ _ = pr_ssrterm
+
+ARGUMENT EXTEND cpattern
+ PRINTED BY pr_ssrterm
+ INTERPRETED BY interp_ssrterm
+ GLOBALIZED BY glob_cpattern SUBSTITUTED BY subst_ssrterm
+ RAW_PRINTED BY pr_ssrterm
+ GLOB_PRINTED BY pr_ssrterm
+| [ "Qed" constr(c) ] -> [ mk_lterm c None ]
+END
+
+let input_ssrtermkind strm = match Util.stream_nth 0 strm with
+ | Tok.KEYWORD "(" -> '('
+ | Tok.KEYWORD "@" -> '@'
+ | _ -> ' '
+let ssrtermkind = Pcoq.Gram.Entry.of_parser "ssrtermkind" input_ssrtermkind
+
+GEXTEND Gram
+ GLOBAL: cpattern;
+ cpattern: [[ k = ssrtermkind; c = constr ->
+ let pattern = mk_term k c None in
+ if loc_of_cpattern pattern <> Some !@loc && k = '('
+ then mk_term 'x' c None
+ else pattern ]];
+END
+
+ARGUMENT EXTEND lcpattern
+ TYPED AS cpattern
+ PRINTED BY pr_ssrterm
+ INTERPRETED BY interp_ssrterm
+ GLOBALIZED BY glob_cpattern SUBSTITUTED BY subst_ssrterm
+ RAW_PRINTED BY pr_ssrterm
+ GLOB_PRINTED BY pr_ssrterm
+| [ "Qed" lconstr(c) ] -> [ mk_lterm c None ]
+END
+
+GEXTEND Gram
+ GLOBAL: lcpattern;
+ lcpattern: [[ k = ssrtermkind; c = lconstr ->
+ let pattern = mk_term k c None in
+ if loc_of_cpattern pattern <> Some !@loc && k = '('
+ then mk_term 'x' c None
+ else pattern ]];
+END
+
+ARGUMENT EXTEND ssrpatternarg TYPED AS rpattern PRINTED BY pr_rpattern
+| [ rpattern(pat) ] -> [ pat ]
+END
+
+TACTIC EXTEND ssrinstoftpat
+| [ "ssrinstancesoftpat" cpattern(arg) ] -> [ Proofview.V82.tactic (ssrinstancesof arg) ]
+END
+
+(* We wipe out all the keywords generated by the grammar rules we defined. *)
+(* The user is supposed to Require Import ssreflect or Require ssreflect *)
+(* and Import ssreflect.SsrSyntax to obtain these keywords and as a *)
+(* consequence the extended ssreflect grammar. *)
+let () = CLexer.set_keyword_state frozen_lexer ;;
diff --git a/plugins/ssrmatching/g_ssrmatching.mli b/plugins/ssrmatching/g_ssrmatching.mli
new file mode 100644
index 0000000000..588a1a3eac
--- /dev/null
+++ b/plugins/ssrmatching/g_ssrmatching.mli
@@ -0,0 +1,17 @@
+(* (c) Copyright 2006-2015 Microsoft Corporation and Inria. *)
+(* Distributed under the terms of CeCILL-B. *)
+
+open Genarg
+open Ssrmatching
+
+(** CS cpattern: (f _), (X in t), (t in X in t), (t as X in t) *)
+val cpattern : cpattern Pcoq.Entry.t
+val wit_cpattern : cpattern uniform_genarg_type
+
+(** OS cpattern: f _, (X in t), (t in X in t), (t as X in t) *)
+val lcpattern : cpattern Pcoq.Entry.t
+val wit_lcpattern : cpattern uniform_genarg_type
+
+(** OS rpattern: f _, in t, X in t, in X in t, t in X in t, t as X in t *)
+val rpattern : rpattern Pcoq.Entry.t
+val wit_rpattern : rpattern uniform_genarg_type
diff --git a/plugins/ssrmatching/ssrmatching.ml4 b/plugins/ssrmatching/ssrmatching.ml
index 9d9b1b2e8c..30a998c6ce 100644
--- a/plugins/ssrmatching/ssrmatching.ml4
+++ b/plugins/ssrmatching/ssrmatching.ml
@@ -10,10 +10,6 @@
(* This file is (C) Copyright 2006-2015 Microsoft Corporation and Inria. *)
-(* Defining grammar rules with "xx" in it automatically declares keywords too,
- * we thus save the lexer to restore it at the end of the file *)
-let frozen_lexer = CLexer.get_keyword_state () ;;
-
open Ltac_plugin
open Names
open Pp
@@ -22,8 +18,6 @@ open Stdarg
open Term
module CoqConstr = Constr
open CoqConstr
-open Pcoq
-open Pcoq.Constr
open Vars
open Libnames
open Tactics
@@ -46,8 +40,6 @@ open Evar_kinds
open Constrexpr
open Constrexpr_ops
-DECLARE PLUGIN "ssrmatching_plugin"
-
let errorstrm = CErrors.user_err ~hdr:"ssrmatching"
let loc_error loc msg = CErrors.user_err ?loc ~hdr:msg (str msg)
let ppnl = Feedback.msg_info
@@ -907,7 +899,6 @@ let pr_pattern_aux pr_constr = function
let pp_pattern (sigma, p) =
pr_pattern_aux (fun t -> pr_constr_pat (EConstr.Unsafe.to_constr (pi3 (nf_open_term sigma sigma (EConstr.of_constr t))))) p
let pr_cpattern = pr_term
-let pr_rpattern _ _ _ = pr_pattern
let wit_rpatternty = add_genarg "rpatternty" pr_pattern
@@ -938,7 +929,7 @@ let glob_cpattern gs p =
| k, (v, Some t), _ as orig ->
if k = 'x' then glob_ssrterm gs ('(', (v, Some t), None) else
match t.CAst.v with
- | CNotation("( _ in _ )", ([t1; t2], [], [], [])) ->
+ | CNotation((InConstrEntrySomeLevel,"( _ in _ )"), ([t1; t2], [], [], [])) ->
(try match glob t1, glob t2 with
| (r1, None), (r2, None) -> encode k "In" [r1;r2]
| (r1, Some _), (r2, Some _) when isCVar t1 ->
@@ -946,11 +937,11 @@ let glob_cpattern gs p =
| (r1, Some _), (r2, Some _) -> encode k "In" [r1; r2]
| _ -> CErrors.anomaly (str"where are we?.")
with _ when isCVar t1 -> encode k "In" [bind_in t1 t2])
- | CNotation("( _ in _ in _ )", ([t1; t2; t3], [], [], [])) ->
+ | CNotation((InConstrEntrySomeLevel,"( _ in _ in _ )"), ([t1; t2; t3], [], [], [])) ->
check_var t2; encode k "In" [fst (glob t1); bind_in t2 t3]
- | CNotation("( _ as _ )", ([t1; t2], [], [], [])) ->
+ | CNotation((InConstrEntrySomeLevel,"( _ as _ )"), ([t1; t2], [], [], [])) ->
encode k "As" [fst (glob t1); fst (glob t2)]
- | CNotation("( _ as _ in _ )", ([t1; t2; t3], [], [], [])) ->
+ | CNotation((InConstrEntrySomeLevel,"( _ as _ in _ )"), ([t1; t2; t3], [], [], [])) ->
check_var t2; encode k "As" [fst (glob t1); bind_in t2 t3]
| _ -> glob_ssrterm gs orig
;;
@@ -987,27 +978,7 @@ let interp_rpattern s = function
| E_As_X_In_T(e,x,t) ->
E_As_X_In_T (interp_ssrterm s e,interp_ssrterm s x,interp_ssrterm s t)
-let interp_rpattern ist gl t = Tacmach.project gl, interp_rpattern ist t
-
-ARGUMENT EXTEND rpattern
- TYPED AS rpatternty
- PRINTED BY pr_rpattern
- INTERPRETED BY interp_rpattern
- GLOBALIZED BY glob_rpattern
- SUBSTITUTED BY subst_rpattern
- | [ lconstr(c) ] -> [ T (mk_lterm c None) ]
- | [ "in" lconstr(c) ] -> [ In_T (mk_lterm c None) ]
- | [ lconstr(x) "in" lconstr(c) ] ->
- [ X_In_T (mk_lterm x None, mk_lterm c None) ]
- | [ "in" lconstr(x) "in" lconstr(c) ] ->
- [ In_X_In_T (mk_lterm x None, mk_lterm c None) ]
- | [ lconstr(e) "in" lconstr(x) "in" lconstr(c) ] ->
- [ E_In_X_In_T (mk_lterm e None, mk_lterm x None, mk_lterm c None) ]
- | [ lconstr(e) "as" lconstr(x) "in" lconstr(c) ] ->
- [ E_As_X_In_T (mk_lterm e None, mk_lterm x None, mk_lterm c None) ]
-END
-
-
+let interp_rpattern0 ist gl t = Tacmach.project gl, interp_rpattern ist t
type cpattern = char * glob_constr_and_expr * Geninterp.interp_sign option
let tag_of_cpattern = pi1
@@ -1051,52 +1022,9 @@ let interp_wit wit ist gl x =
let interp_open_constr ist gl gc =
interp_wit wit_open_constr ist gl gc
let pf_intern_term gl (_, c, ist) = glob_constr ist (pf_env gl) (project gl) c
-let pr_ssrterm _ _ _ = pr_term
-let input_ssrtermkind strm = match stream_nth 0 strm with
- | Tok.KEYWORD "(" -> '('
- | Tok.KEYWORD "@" -> '@'
- | _ -> ' '
-let ssrtermkind = Pcoq.Gram.Entry.of_parser "ssrtermkind" input_ssrtermkind
let interp_ssrterm ist gl t = Tacmach.project gl, interp_ssrterm ist t
-ARGUMENT EXTEND cpattern
- PRINTED BY pr_ssrterm
- INTERPRETED BY interp_ssrterm
- GLOBALIZED BY glob_cpattern SUBSTITUTED BY subst_ssrterm
- RAW_PRINTED BY pr_ssrterm
- GLOB_PRINTED BY pr_ssrterm
-| [ "Qed" constr(c) ] -> [ mk_lterm c None ]
-END
-
-GEXTEND Gram
- GLOBAL: cpattern;
- cpattern: [[ k = ssrtermkind; c = constr ->
- let pattern = mk_term k c None in
- if loc_ofCG pattern <> Some !@loc && k = '('
- then mk_term 'x' c None
- else pattern ]];
-END
-
-ARGUMENT EXTEND lcpattern
- TYPED AS cpattern
- PRINTED BY pr_ssrterm
- INTERPRETED BY interp_ssrterm
- GLOBALIZED BY glob_cpattern SUBSTITUTED BY subst_ssrterm
- RAW_PRINTED BY pr_ssrterm
- GLOB_PRINTED BY pr_ssrterm
-| [ "Qed" lconstr(c) ] -> [ mk_lterm c None ]
-END
-
-GEXTEND Gram
- GLOBAL: lcpattern;
- lcpattern: [[ k = ssrtermkind; c = lconstr ->
- let pattern = mk_term k c None in
- if loc_ofCG pattern <> Some !@loc && k = '('
- then mk_term 'x' c None
- else pattern ]];
-END
-
let interp_term gl = function
| (_, c, Some ist) ->
on_snd EConstr.Unsafe.to_constr (interp_open_constr ist gl c)
@@ -1416,10 +1344,6 @@ let is_wildcard ((_, (l, r), _) : cpattern) : bool = match DAst.get l, r with
(* "ssrpattern" *)
-ARGUMENT EXTEND ssrpatternarg TYPED AS rpattern PRINTED BY pr_rpattern
-| [ rpattern(pat) ] -> [ pat ]
-END
-
let pr_rpattern = pr_pattern
let pf_merge_uc uc gl =
@@ -1428,6 +1352,9 @@ let pf_merge_uc uc gl =
let pf_unsafe_merge_uc uc gl =
re_sig (sig_it gl) (Evd.set_universe_context (project gl) uc)
+(** All the pattern types reuse the same dynamic toplevel tag *)
+let wit_ssrpatternarg = wit_rpatternty
+
let interp_rpattern = interp_rpattern ~wit_ssrpatternarg
let ssrpatterntac _ist arg gl =
@@ -1479,14 +1406,20 @@ let ssrinstancesof arg gl =
done; raise NoMatch
with NoMatch -> ppnl (str"END INSTANCES"); tclIDTAC gl
-TACTIC EXTEND ssrinstoftpat
-| [ "ssrinstancesoftpat" cpattern(arg) ] -> [ Proofview.V82.tactic (ssrinstancesof arg) ]
-END
-
-(* We wipe out all the keywords generated by the grammar rules we defined. *)
-(* The user is supposed to Require Import ssreflect or Require ssreflect *)
-(* and Import ssreflect.SsrSyntax to obtain these keywords and as a *)
-(* consequence the extended ssreflect grammar. *)
-let () = CLexer.set_keyword_state frozen_lexer ;;
+module Internal =
+struct
+ let wit_rpatternty = wit_rpatternty
+ let glob_rpattern = glob_rpattern
+ let subst_rpattern = subst_rpattern
+ let interp_rpattern = interp_rpattern0
+ let pr_rpattern = pr_rpattern
+ let mk_rpattern x = x
+ let mk_lterm = mk_lterm
+ let mk_term = mk_term
+ let glob_cpattern = glob_cpattern
+ let subst_ssrterm = subst_ssrterm
+ let interp_ssrterm = interp_ssrterm
+ let pr_ssrterm = pr_term
+end
(* vim: set filetype=ocaml foldmethod=marker: *)
diff --git a/plugins/ssrmatching/ssrmatching.mli b/plugins/ssrmatching/ssrmatching.mli
index c55081e0f7..f478d48ea3 100644
--- a/plugins/ssrmatching/ssrmatching.mli
+++ b/plugins/ssrmatching/ssrmatching.mli
@@ -2,7 +2,6 @@
(* Distributed under the terms of CeCILL-B. *)
open Goal
-open Genarg
open Environ
open Evd
open Constr
@@ -19,24 +18,12 @@ open Tacexpr
type cpattern
val pr_cpattern : cpattern -> Pp.t
-(** CS cpattern: (f _), (X in t), (t in X in t), (t as X in t) *)
-val cpattern : cpattern Pcoq.Gram.entry
-val wit_cpattern : cpattern uniform_genarg_type
-
-(** OS cpattern: f _, (X in t), (t in X in t), (t as X in t) *)
-val lcpattern : cpattern Pcoq.Gram.entry
-val wit_lcpattern : cpattern uniform_genarg_type
-
(** The type of rewrite patterns, the patterns of the [rewrite] tactic.
These patterns also include patterns that identify all the subterms
of a context (i.e. "in" prefix) *)
type rpattern
val pr_rpattern : rpattern -> Pp.t
-(** OS rpattern: f _, in t, X in t, in X in t, t in X in t, t as X in t *)
-val rpattern : rpattern Pcoq.Gram.entry
-val wit_rpattern : rpattern uniform_genarg_type
-
(** Pattern interpretation and matching *)
exception NoMatch
@@ -238,4 +225,25 @@ val debug : bool -> unit
* "Unset SsrMatchingProfiling" to get timings *)
val profile : bool -> unit
+val ssrinstancesof : cpattern -> Tacmach.tactic
+
+(** Functions used for grammar extensions. Do not use. *)
+
+module Internal :
+sig
+ val wit_rpatternty : (rpattern, rpattern, rpattern) Genarg.genarg_type
+ val glob_rpattern : Genintern.glob_sign -> rpattern -> rpattern
+ val subst_rpattern : Mod_subst.substitution -> rpattern -> rpattern
+ val interp_rpattern : Geninterp.interp_sign -> Proof_type.goal Evd.sigma -> rpattern -> Evd.evar_map * rpattern
+ val pr_rpattern : rpattern -> Pp.t
+ val mk_rpattern : (cpattern, cpattern) ssrpattern -> rpattern
+ val mk_lterm : Constrexpr.constr_expr -> Geninterp.interp_sign option -> cpattern
+ val mk_term : char -> Constrexpr.constr_expr -> Geninterp.interp_sign option -> cpattern
+
+ val glob_cpattern : Genintern.glob_sign -> cpattern -> cpattern
+ val subst_ssrterm : Mod_subst.substitution -> cpattern -> cpattern
+ val interp_ssrterm : Geninterp.interp_sign -> Proof_type.goal Evd.sigma -> cpattern -> Evd.evar_map * cpattern
+ val pr_ssrterm : cpattern -> Pp.t
+end
+
(* eof *)
diff --git a/plugins/ssrmatching/ssrmatching_plugin.mlpack b/plugins/ssrmatching/ssrmatching_plugin.mlpack
index 5fb1f1567d..02c75f14ed 100644
--- a/plugins/ssrmatching/ssrmatching_plugin.mlpack
+++ b/plugins/ssrmatching/ssrmatching_plugin.mlpack
@@ -1 +1,2 @@
Ssrmatching
+G_ssrmatching
diff --git a/plugins/syntax/n_syntax.ml b/plugins/syntax/n_syntax.ml
new file mode 100644
index 0000000000..0e202be47f
--- /dev/null
+++ b/plugins/syntax/n_syntax.ml
@@ -0,0 +1,81 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+open Pp
+open CErrors
+open Names
+open Bigint
+open Positive_syntax_plugin.Positive_syntax
+
+(* Poor's man DECLARE PLUGIN *)
+let __coq_plugin_name = "n_syntax_plugin"
+let () = Mltop.add_known_module __coq_plugin_name
+
+(**********************************************************************)
+(* Parsing N via scopes *)
+(**********************************************************************)
+
+open Globnames
+open Glob_term
+
+let binnums = ["Coq";"Numbers";"BinNums"]
+
+let make_dir l = DirPath.make (List.rev_map Id.of_string l)
+let make_path dir id = Libnames.make_path (make_dir dir) (Id.of_string id)
+
+(* TODO: temporary hack *)
+let make_kn dir id = Globnames.encode_mind dir id
+
+let n_kn = make_kn (make_dir binnums) (Id.of_string "N")
+let glob_n = IndRef (n_kn,0)
+let path_of_N0 = ((n_kn,0),1)
+let path_of_Npos = ((n_kn,0),2)
+let glob_N0 = ConstructRef path_of_N0
+let glob_Npos = ConstructRef path_of_Npos
+
+let n_path = make_path binnums "N"
+
+let n_of_binnat ?loc pos_or_neg n = DAst.make ?loc @@
+ if not (Bigint.equal n zero) then
+ GApp(DAst.make @@ GRef (glob_Npos,None), [pos_of_bignat ?loc n])
+ else
+ GRef(glob_N0, None)
+
+let error_negative ?loc =
+ user_err ?loc ~hdr:"interp_N" (str "No negative numbers in type \"N\".")
+
+let n_of_int ?loc n =
+ if is_pos_or_zero n then n_of_binnat ?loc true n
+ else error_negative ?loc
+
+(**********************************************************************)
+(* Printing N via scopes *)
+(**********************************************************************)
+
+let bignat_of_n n = DAst.with_val (function
+ | GApp (r, [a]) when is_gr r glob_Npos -> bignat_of_pos a
+ | GRef (a,_) when GlobRef.equal a glob_N0 -> Bigint.zero
+ | _ -> raise Non_closed_number
+ ) n
+
+let uninterp_n (AnyGlobConstr p) =
+ try Some (bignat_of_n p)
+ with Non_closed_number -> None
+
+(************************************************************************)
+(* Declaring interpreters and uninterpreters for N *)
+
+let _ = Notation.declare_numeral_interpreter "N_scope"
+ (n_path,binnums)
+ n_of_int
+ ([DAst.make @@ GRef (glob_N0, None);
+ DAst.make @@ GRef (glob_Npos, None)],
+ uninterp_n,
+ true)
diff --git a/plugins/syntax/n_syntax_plugin.mlpack b/plugins/syntax/n_syntax_plugin.mlpack
new file mode 100644
index 0000000000..4c56645f07
--- /dev/null
+++ b/plugins/syntax/n_syntax_plugin.mlpack
@@ -0,0 +1 @@
+N_syntax
diff --git a/plugins/syntax/positive_syntax.ml b/plugins/syntax/positive_syntax.ml
new file mode 100644
index 0000000000..0c82e47445
--- /dev/null
+++ b/plugins/syntax/positive_syntax.ml
@@ -0,0 +1,101 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+open Pp
+open CErrors
+open Util
+open Names
+open Bigint
+
+(* Poor's man DECLARE PLUGIN *)
+let __coq_plugin_name = "positive_syntax_plugin"
+let () = Mltop.add_known_module __coq_plugin_name
+
+exception Non_closed_number
+
+(**********************************************************************)
+(* Parsing positive via scopes *)
+(**********************************************************************)
+
+open Globnames
+open Glob_term
+
+let binnums = ["Coq";"Numbers";"BinNums"]
+
+let make_dir l = DirPath.make (List.rev_map Id.of_string l)
+let make_path dir id = Libnames.make_path (make_dir dir) (Id.of_string id)
+
+let positive_path = make_path binnums "positive"
+
+(* TODO: temporary hack *)
+let make_kn dir id = Globnames.encode_mind dir id
+
+let positive_kn = make_kn (make_dir binnums) (Id.of_string "positive")
+let glob_positive = IndRef (positive_kn,0)
+let path_of_xI = ((positive_kn,0),1)
+let path_of_xO = ((positive_kn,0),2)
+let path_of_xH = ((positive_kn,0),3)
+let glob_xI = ConstructRef path_of_xI
+let glob_xO = ConstructRef path_of_xO
+let glob_xH = ConstructRef path_of_xH
+
+let pos_of_bignat ?loc x =
+ let ref_xI = DAst.make ?loc @@ GRef (glob_xI, None) in
+ let ref_xH = DAst.make ?loc @@ GRef (glob_xH, None) in
+ let ref_xO = DAst.make ?loc @@ GRef (glob_xO, None) in
+ let rec pos_of x =
+ match div2_with_rest x with
+ | (q,false) -> DAst.make ?loc @@ GApp (ref_xO,[pos_of q])
+ | (q,true) when not (Bigint.equal q zero) -> DAst.make ?loc @@ GApp (ref_xI,[pos_of q])
+ | (q,true) -> ref_xH
+ in
+ pos_of x
+
+let error_non_positive ?loc =
+ user_err ?loc ~hdr:"interp_positive"
+ (str "Only strictly positive numbers in type \"positive\".")
+
+let interp_positive ?loc n =
+ if is_strictly_pos n then pos_of_bignat ?loc n
+ else error_non_positive ?loc
+
+(**********************************************************************)
+(* Printing positive via scopes *)
+(**********************************************************************)
+
+let is_gr c gr = match DAst.get c with
+| GRef (r, _) -> GlobRef.equal r gr
+| _ -> false
+
+let rec bignat_of_pos x = DAst.with_val (function
+ | GApp (r ,[a]) when is_gr r glob_xO -> mult_2(bignat_of_pos a)
+ | GApp (r ,[a]) when is_gr r glob_xI -> add_1(mult_2(bignat_of_pos a))
+ | GRef (a, _) when GlobRef.equal a glob_xH -> Bigint.one
+ | _ -> raise Non_closed_number
+ ) x
+
+let uninterp_positive (AnyGlobConstr p) =
+ try
+ Some (bignat_of_pos p)
+ with Non_closed_number ->
+ None
+
+(************************************************************************)
+(* Declaring interpreters and uninterpreters for positive *)
+(************************************************************************)
+
+let _ = Notation.declare_numeral_interpreter "positive_scope"
+ (positive_path,binnums)
+ interp_positive
+ ([DAst.make @@ GRef (glob_xI, None);
+ DAst.make @@ GRef (glob_xO, None);
+ DAst.make @@ GRef (glob_xH, None)],
+ uninterp_positive,
+ true)
diff --git a/plugins/syntax/positive_syntax_plugin.mlpack b/plugins/syntax/positive_syntax_plugin.mlpack
new file mode 100644
index 0000000000..ac8f3c425c
--- /dev/null
+++ b/plugins/syntax/positive_syntax_plugin.mlpack
@@ -0,0 +1 @@
+Positive_syntax
diff --git a/plugins/syntax/z_syntax.ml b/plugins/syntax/z_syntax.ml
index 09fe8bf70a..2534162e36 100644
--- a/plugins/syntax/z_syntax.ml
+++ b/plugins/syntax/z_syntax.ml
@@ -8,20 +8,16 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
-open Pp
-open CErrors
-open Util
open Names
open Bigint
+open Positive_syntax_plugin.Positive_syntax
(* Poor's man DECLARE PLUGIN *)
let __coq_plugin_name = "z_syntax_plugin"
let () = Mltop.add_known_module __coq_plugin_name
-exception Non_closed_number
-
(**********************************************************************)
-(* Parsing positive via scopes *)
+(* Parsing Z via scopes *)
(**********************************************************************)
open Globnames
@@ -32,129 +28,9 @@ let binnums = ["Coq";"Numbers";"BinNums"]
let make_dir l = DirPath.make (List.rev_map Id.of_string l)
let make_path dir id = Libnames.make_path (make_dir dir) (Id.of_string id)
-let positive_path = make_path binnums "positive"
-
(* TODO: temporary hack *)
let make_kn dir id = Globnames.encode_mind dir id
-let positive_kn = make_kn (make_dir binnums) (Id.of_string "positive")
-let glob_positive = IndRef (positive_kn,0)
-let path_of_xI = ((positive_kn,0),1)
-let path_of_xO = ((positive_kn,0),2)
-let path_of_xH = ((positive_kn,0),3)
-let glob_xI = ConstructRef path_of_xI
-let glob_xO = ConstructRef path_of_xO
-let glob_xH = ConstructRef path_of_xH
-
-let pos_of_bignat ?loc x =
- let ref_xI = DAst.make ?loc @@ GRef (glob_xI, None) in
- let ref_xH = DAst.make ?loc @@ GRef (glob_xH, None) in
- let ref_xO = DAst.make ?loc @@ GRef (glob_xO, None) in
- let rec pos_of x =
- match div2_with_rest x with
- | (q,false) -> DAst.make ?loc @@ GApp (ref_xO,[pos_of q])
- | (q,true) when not (Bigint.equal q zero) -> DAst.make ?loc @@ GApp (ref_xI,[pos_of q])
- | (q,true) -> ref_xH
- in
- pos_of x
-
-let error_non_positive ?loc =
- user_err ?loc ~hdr:"interp_positive"
- (str "Only strictly positive numbers in type \"positive\".")
-
-let interp_positive ?loc n =
- if is_strictly_pos n then pos_of_bignat ?loc n
- else error_non_positive ?loc
-
-(**********************************************************************)
-(* Printing positive via scopes *)
-(**********************************************************************)
-
-let is_gr c gr = match DAst.get c with
-| GRef (r, _) -> GlobRef.equal r gr
-| _ -> false
-
-let rec bignat_of_pos x = DAst.with_val (function
- | GApp (r ,[a]) when is_gr r glob_xO -> mult_2(bignat_of_pos a)
- | GApp (r ,[a]) when is_gr r glob_xI -> add_1(mult_2(bignat_of_pos a))
- | GRef (a, _) when GlobRef.equal a glob_xH -> Bigint.one
- | _ -> raise Non_closed_number
- ) x
-
-let uninterp_positive (AnyGlobConstr p) =
- try
- Some (bignat_of_pos p)
- with Non_closed_number ->
- None
-
-(************************************************************************)
-(* Declaring interpreters and uninterpreters for positive *)
-(************************************************************************)
-
-let _ = Notation.declare_numeral_interpreter "positive_scope"
- (positive_path,binnums)
- interp_positive
- ([DAst.make @@ GRef (glob_xI, None);
- DAst.make @@ GRef (glob_xO, None);
- DAst.make @@ GRef (glob_xH, None)],
- uninterp_positive,
- true)
-
-(**********************************************************************)
-(* Parsing N via scopes *)
-(**********************************************************************)
-
-let n_kn = make_kn (make_dir binnums) (Id.of_string "N")
-let glob_n = IndRef (n_kn,0)
-let path_of_N0 = ((n_kn,0),1)
-let path_of_Npos = ((n_kn,0),2)
-let glob_N0 = ConstructRef path_of_N0
-let glob_Npos = ConstructRef path_of_Npos
-
-let n_path = make_path binnums "N"
-
-let n_of_binnat ?loc pos_or_neg n = DAst.make ?loc @@
- if not (Bigint.equal n zero) then
- GApp(DAst.make @@ GRef (glob_Npos,None), [pos_of_bignat ?loc n])
- else
- GRef(glob_N0, None)
-
-let error_negative ?loc =
- user_err ?loc ~hdr:"interp_N" (str "No negative numbers in type \"N\".")
-
-let n_of_int ?loc n =
- if is_pos_or_zero n then n_of_binnat ?loc true n
- else error_negative ?loc
-
-(**********************************************************************)
-(* Printing N via scopes *)
-(**********************************************************************)
-
-let bignat_of_n n = DAst.with_val (function
- | GApp (r, [a]) when is_gr r glob_Npos -> bignat_of_pos a
- | GRef (a,_) when GlobRef.equal a glob_N0 -> Bigint.zero
- | _ -> raise Non_closed_number
- ) n
-
-let uninterp_n (AnyGlobConstr p) =
- try Some (bignat_of_n p)
- with Non_closed_number -> None
-
-(************************************************************************)
-(* Declaring interpreters and uninterpreters for N *)
-
-let _ = Notation.declare_numeral_interpreter "N_scope"
- (n_path,binnums)
- n_of_int
- ([DAst.make @@ GRef (glob_N0, None);
- DAst.make @@ GRef (glob_Npos, None)],
- uninterp_n,
- true)
-
-(**********************************************************************)
-(* Parsing Z via scopes *)
-(**********************************************************************)
-
let z_path = make_path binnums "Z"
let z_kn = make_kn (make_dir binnums) (Id.of_string "Z")
let glob_z = IndRef (z_kn,0)
diff --git a/pretyping/cases.ml b/pretyping/cases.ml
index 93ca9dc5e5..ad33297f0a 100644
--- a/pretyping/cases.ml
+++ b/pretyping/cases.ml
@@ -373,6 +373,11 @@ let ltac_interp_realnames lvar = function
| t, IsInd (ty,ind,realnal) -> t, IsInd (ty,ind,List.map (ltac_interp_name lvar) realnal)
| _ as x -> x
+let is_patvar pat =
+ match DAst.get pat with
+ | PatVar _ -> true
+ | _ -> false
+
let coerce_row typing_fun evdref env lvar pats (tomatch,(na,indopt)) =
let loc = loc_of_glob_constr tomatch in
let tycon,realnames = find_tomatch_tycon evdref env loc indopt in
@@ -381,6 +386,7 @@ let coerce_row typing_fun evdref env lvar pats (tomatch,(na,indopt)) =
let typ = nf_evar !evdref j.uj_type in
lvar := make_return_predicate_ltac_lvar !evdref na tomatch j.uj_val !lvar;
let t =
+ if realnames = None && pats <> [] && List.for_all is_patvar pats then NotInd (None,typ) else
try try_find_ind env !evdref typ realnames
with Not_found ->
unify_tomatch_with_patterns evdref env loc typ pats realnames in
@@ -1699,7 +1705,8 @@ let abstract_tycon ?loc env evdref subst tycon extenv t =
let ty = get_type_of env !evdref t in
Evarutil.evd_comb1 (refresh_universes (Some false) env) evdref ty
in
- let ty = lift (-k) (aux x ty) in
+ let dummy_subst = List.init k (fun _ -> mkProp) in
+ let ty = substl dummy_subst (aux x ty) in
let depvl = free_rels !evdref ty in
let inst =
List.map_i
@@ -2103,7 +2110,10 @@ let mk_JMeq_refl evdref typ x =
papp evdref coq_JMeq_refl [| typ; x |]
let hole na = DAst.make @@
- GHole (Evar_kinds.QuestionMark (Evar_kinds.Define false,na),
+ GHole (Evar_kinds.QuestionMark {
+ Evar_kinds.qm_obligation= Evar_kinds.Define false;
+ Evar_kinds.qm_name=na;
+ Evar_kinds.qm_record_field=None},
IntroAnonymous, None)
let constr_of_pat env evdref arsign pat avoid =
diff --git a/pretyping/cbv.ml b/pretyping/cbv.ml
index cb0fc32575..fc24e9b3a9 100644
--- a/pretyping/cbv.ml
+++ b/pretyping/cbv.ml
@@ -71,7 +71,7 @@ and cbv_stack =
| TOP
| APP of cbv_value array * cbv_stack
| CASE of constr * constr array * case_info * cbv_value subs * cbv_stack
- | PROJ of Projection.t * Declarations.projection_body * cbv_stack
+ | PROJ of Projection.t * cbv_stack
(* les vars pourraient etre des constr,
cela permet de retarder les lift: utile ?? *)
@@ -126,7 +126,7 @@ let rec stack_concat stk1 stk2 =
TOP -> stk2
| APP(v,stk1') -> APP(v,stack_concat stk1' stk2)
| CASE(c,b,i,s,stk1') -> CASE(c,b,i,s,stack_concat stk1' stk2)
- | PROJ (p,pinfo,stk1') -> PROJ (p,pinfo,stack_concat stk1' stk2)
+ | PROJ (p,stk1') -> PROJ (p,stack_concat stk1' stk2)
(* merge stacks when there is no shifts in between *)
let mkSTACK = function
@@ -200,7 +200,7 @@ let rec reify_stack t = function
reify_stack
(mkCase (ci, ty, t,br))
st
- | PROJ (p, pinfo, st) ->
+ | PROJ (p, st) ->
reify_stack (mkProj (p, t)) st
and reify_value = function (* reduction under binders *)
@@ -265,8 +265,7 @@ let rec norm_head info env t stack =
then Projection.unfold p
else p
in
- let pinfo = Environ.lookup_projection p (info_env info.infos) in
- norm_head info env c (PROJ (p', pinfo, stack))
+ norm_head info env c (PROJ (p', stack))
(* constants, axioms
* the first pattern is CRUCIAL, n=0 happens very often:
@@ -281,8 +280,9 @@ let rec norm_head info env t stack =
| Var id -> norm_head_ref 0 info env stack (VarKey id)
| Const sp ->
- Reductionops.reduction_effect_hook (env_of_infos info.infos) info.sigma t (lazy (reify_stack t stack));
- norm_head_ref 0 info env stack (ConstKey sp)
+ Reductionops.reduction_effect_hook (env_of_infos info.infos) info.sigma
+ (fst sp) (lazy (reify_stack t stack));
+ norm_head_ref 0 info env stack (ConstKey sp)
| LetIn (_, b, _, c) ->
(* zeta means letin are contracted; delta without zeta means we *)
@@ -380,9 +380,9 @@ and cbv_stack_value info env = function
cbv_stack_term info stk env br.(n-1)
(* constructor in a Projection -> IOTA *)
- | (CONSTR(((sp,n),u),[||]), APP(args,PROJ(p,pi,stk)))
+ | (CONSTR(((sp,n),u),[||]), APP(args,PROJ(p,stk)))
when red_set (info_flags info.infos) fMATCH && Projection.unfolded p ->
- let arg = args.(pi.Declarations.proj_npars + pi.Declarations.proj_arg) in
+ let arg = args.(Projection.npars p + Projection.arg p) in
cbv_stack_value info env (strip_appl arg stk)
(* may be reduced later by application *)
@@ -407,7 +407,7 @@ let rec apply_stack info t = function
(mkCase (ci, cbv_norm_term info env ty, t,
Array.map (cbv_norm_term info env) br))
st
- | PROJ (p, pinfo, st) ->
+ | PROJ (p, st) ->
apply_stack info (mkProj (p, t)) st
(* performs the reduction on a constr, and returns a constr *)
@@ -455,7 +455,8 @@ let cbv_norm infos constr =
(* constant bodies are normalized at the first expansion *)
let create_cbv_infos flgs env sigma =
let infos = create
- (fun old_info tab c -> cbv_stack_term { tab; infos = old_info; sigma } TOP (subs_id 0) c)
+ ~share:true (** Not used by cbv *)
+ ~repr:(fun old_info tab c -> cbv_stack_term { tab; infos = old_info; sigma } TOP (subs_id 0) c)
flgs
env
(Reductionops.safe_evar_value sigma) in
diff --git a/pretyping/cbv.mli b/pretyping/cbv.mli
index cdaa39c53c..83844c95a7 100644
--- a/pretyping/cbv.mli
+++ b/pretyping/cbv.mli
@@ -41,7 +41,7 @@ and cbv_stack =
| TOP
| APP of cbv_value array * cbv_stack
| CASE of constr * constr array * case_info * cbv_value subs * cbv_stack
- | PROJ of Projection.t * Declarations.projection_body * cbv_stack
+ | PROJ of Projection.t * cbv_stack
val shift_value : int -> cbv_value -> cbv_value
diff --git a/pretyping/classops.ml b/pretyping/classops.ml
index 7dbef01c22..542fb5456c 100644
--- a/pretyping/classops.ml
+++ b/pretyping/classops.ml
@@ -31,7 +31,7 @@ type cl_typ =
| CL_SECVAR of variable
| CL_CONST of Constant.t
| CL_IND of inductive
- | CL_PROJ of Constant.t
+ | CL_PROJ of Projection.Repr.t
type cl_info_typ = {
cl_param : int
@@ -42,18 +42,15 @@ type coe_typ = GlobRef.t
module CoeTypMap = Refmap_env
type coe_info_typ = {
- coe_value : constr;
- coe_type : types;
+ coe_value : GlobRef.t;
coe_local : bool;
- coe_context : Univ.ContextSet.t;
coe_is_identity : bool;
- coe_is_projection : bool;
- coe_param : int }
+ coe_is_projection : Projection.Repr.t option;
+ coe_param : int;
+}
let coe_info_typ_equal c1 c2 =
- let eq_constr c1 c2 = Termops.eq_constr Evd.empty (EConstr.of_constr c1) (EConstr.of_constr c2) in
- eq_constr c1.coe_value c2.coe_value &&
- eq_constr c1.coe_type c2.coe_type &&
+ GlobRef.equal c1.coe_value c2.coe_value &&
c1.coe_local == c2.coe_local &&
c1.coe_is_identity == c2.coe_is_identity &&
c1.coe_is_projection == c2.coe_is_projection &&
@@ -62,7 +59,7 @@ let coe_info_typ_equal c1 c2 =
let cl_typ_ord t1 t2 = match t1, t2 with
| CL_SECVAR v1, CL_SECVAR v2 -> Id.compare v1 v2
| CL_CONST c1, CL_CONST c2 -> Constant.CanOrd.compare c1 c2
- | CL_PROJ c1, CL_PROJ c2 -> Constant.CanOrd.compare c1 c2
+ | CL_PROJ c1, CL_PROJ c2 -> Projection.Repr.CanOrd.compare c1 c2
| CL_IND i1, CL_IND i2 -> ind_ord i1 i2
| _ -> Pervasives.compare t1 t2 (** OK *)
@@ -77,9 +74,7 @@ module IntMap = Map.Make(Int)
let cl_typ_eq t1 t2 = Int.equal (cl_typ_ord t1 t2) 0
-type coe_index = coe_info_typ
-
-type inheritance_path = coe_index list
+type inheritance_path = coe_info_typ list
(* table des classes, des coercions et graphe d'heritage *)
@@ -199,7 +194,7 @@ let find_class_type sigma t =
| Var id -> CL_SECVAR id, EInstance.empty, args
| Const (sp,u) -> CL_CONST sp, u, args
| Proj (p, c) when not (Projection.unfolded p) ->
- CL_PROJ (Projection.constant p), EInstance.empty, (c :: args)
+ CL_PROJ (Projection.repr p), EInstance.empty, (c :: args)
| Ind (ind_sp,u) -> CL_IND ind_sp, u, args
| Prod (_,_,_) -> CL_FUN, EInstance.empty, []
| Sort _ -> CL_SORT, EInstance.empty, []
@@ -211,7 +206,7 @@ let subst_cl_typ subst ct = match ct with
| CL_FUN
| CL_SECVAR _ -> ct
| CL_PROJ c ->
- let c',t = subst_con_kn subst c in
+ let c' = subst_proj_repr subst c in
if c' == c then ct else CL_PROJ c'
| CL_CONST c ->
let c',t = subst_con_kn subst c in
@@ -248,8 +243,11 @@ let class_args_of env sigma c = pi3 (find_class_type sigma c)
let string_of_class = function
| CL_FUN -> "Funclass"
| CL_SORT -> "Sortclass"
- | CL_CONST sp | CL_PROJ sp ->
- string_of_qualid (shortest_qualid_of_global Id.Set.empty (ConstRef sp))
+ | CL_CONST sp ->
+ string_of_qualid (shortest_qualid_of_global Id.Set.empty (ConstRef sp))
+ | CL_PROJ sp ->
+ let sp = Projection.Repr.constant sp in
+ string_of_qualid (shortest_qualid_of_global Id.Set.empty (ConstRef sp))
| CL_IND sp ->
string_of_qualid (shortest_qualid_of_global Id.Set.empty (IndRef sp))
| CL_SECVAR sp ->
@@ -297,31 +295,25 @@ let lookup_path_to_fun_from env sigma s =
let lookup_path_to_sort_from env sigma s =
apply_on_class_of env sigma s lookup_path_to_sort_from_class
+let mkNamed = function
+ | GlobRef.ConstRef c -> EConstr.mkConst c
+ | VarRef v -> EConstr.mkVar v
+ | ConstructRef c -> EConstr.mkConstruct c
+ | IndRef i -> EConstr.mkInd i
+
let get_coercion_constructor env coe =
- let c, _ =
- Reductionops.whd_all_stack env Evd.empty (EConstr.of_constr coe.coe_value)
- in
- match EConstr.kind Evd.empty (** FIXME *) c with
- | Construct (cstr,u) ->
- (cstr, Inductiveops.constructor_nrealargs cstr -1)
- | _ ->
- raise Not_found
+ let evd = Evd.from_env env in
+ let red x = fst (Reductionops.whd_all_stack env evd x) in
+ match EConstr.kind evd (red (mkNamed coe.coe_value)) with
+ | Constr.Construct (c, _) ->
+ c, Inductiveops.constructor_nrealargs c -1
+ | _ -> raise Not_found
let lookup_pattern_path_between env (s,t) =
let i = inductive_class_of s in
let j = inductive_class_of t in
List.map (get_coercion_constructor env) (ClPairMap.find (i,j) !inheritance_graph)
-(* coercion_value : coe_index -> unsafe_judgment * bool *)
-
-let coercion_value { coe_value = c; coe_type = t; coe_context = ctx;
- coe_is_identity = b; coe_is_projection = b' } =
- let subst, ctx = UnivGen.fresh_universe_context_set_instance ctx in
- let c' = Vars.subst_univs_level_constr subst c
- and t' = Vars.subst_univs_level_constr subst t in
- (make_judge (EConstr.of_constr c') (EConstr.of_constr t'), b, b'), ctx
-
-(* pretty-print functions are now in Pretty *)
(* rajouter une coercion dans le graphe *)
let path_printer : (env -> Evd.evar_map -> (Bijint.Index.t * Bijint.Index.t) * inheritance_path -> Pp.t) ref =
@@ -395,7 +387,7 @@ type coercion = {
coercion_type : coe_typ;
coercion_local : bool;
coercion_is_id : bool;
- coercion_is_proj : bool;
+ coercion_is_proj : Projection.Repr.t option;
coercion_source : cl_typ;
coercion_target : cl_typ;
coercion_params : int;
@@ -408,9 +400,8 @@ let reference_arity_length ref =
List.length (fst (Reductionops.splay_arity (Global.env()) Evd.empty (EConstr.of_constr t))) (** FIXME *)
let projection_arity_length p =
- let len = reference_arity_length (ConstRef p) in
- let pb = Environ.lookup_projection (Projection.make p false) (Global.env ()) in
- len - pb.Declarations.proj_npars
+ let len = reference_arity_length (ConstRef (Projection.Repr.constant p)) in
+ len - Projection.Repr.npars p
let class_params = function
| CL_FUN | CL_SORT -> 0
@@ -440,17 +431,13 @@ let cache_coercion env sigma (_, c) =
let () = add_class c.coercion_target in
let is, _ = class_info c.coercion_source in
let it, _ = class_info c.coercion_target in
- let value, ctx = UnivGen.fresh_global_instance env c.coercion_type in
- let typ = Retyping.get_type_of env sigma (EConstr.of_constr value) in
- let typ = EConstr.Unsafe.to_constr typ in
let xf =
- { coe_value = value;
- coe_type = typ;
- coe_context = ctx;
+ { coe_value = c.coercion_type;
coe_local = c.coercion_local;
coe_is_identity = c.coercion_is_id;
coe_is_projection = c.coercion_is_proj;
- coe_param = c.coercion_params } in
+ coe_param = c.coercion_params;
+ } in
let () = add_new_coercion c.coercion_type xf in
add_coercion_in_graph env sigma (xf,is,it)
@@ -466,13 +453,17 @@ let subst_coercion (subst, c) =
let coe = subst_coe_typ subst c.coercion_type in
let cls = subst_cl_typ subst c.coercion_source in
let clt = subst_cl_typ subst c.coercion_target in
- if c.coercion_type == coe && c.coercion_source == cls && c.coercion_target == clt then c
- else { c with coercion_type = coe; coercion_source = cls; coercion_target = clt }
+ let clp = Option.Smart.map (subst_proj_repr subst) c.coercion_is_proj in
+ if c.coercion_type == coe && c.coercion_source == cls &&
+ c.coercion_target == clt && c.coercion_is_proj == clp
+ then c
+ else { c with coercion_type = coe; coercion_source = cls;
+ coercion_target = clt; coercion_is_proj = clp; }
let discharge_cl = function
| CL_CONST kn -> CL_CONST (Lib.discharge_con kn)
| CL_IND ind -> CL_IND (Lib.discharge_inductive ind)
- | CL_PROJ p -> CL_PROJ (Lib.discharge_con p)
+ | CL_PROJ p -> CL_PROJ (Lib.discharge_proj_repr p)
| cl -> cl
let discharge_coercion (_, c) =
@@ -489,6 +480,7 @@ let discharge_coercion (_, c) =
coercion_source = discharge_cl c.coercion_source;
coercion_target = discharge_cl c.coercion_target;
coercion_params = n + c.coercion_params;
+ coercion_is_proj = Option.map Lib.discharge_proj_repr c.coercion_is_proj;
} in
Some nc
@@ -509,8 +501,8 @@ let inCoercion : coercion -> obj =
let declare_coercion coef ?(local = false) ~isid ~src:cls ~target:clt ~params:ps =
let isproj =
match coef with
- | ConstRef c -> Environ.is_projection c (Global.env ())
- | _ -> false
+ | ConstRef c -> Recordops.find_primitive_projection c
+ | _ -> None
in
let c = {
coercion_type = coef;
@@ -524,8 +516,6 @@ let declare_coercion coef ?(local = false) ~isid ~src:cls ~target:clt ~params:ps
Lib.add_anonymous_leaf (inCoercion c)
(* For printing purpose *)
-let get_coercion_value v = v.coe_value
-
let pr_cl_index = Bijint.Index.print
let classes () = Bijint.dom !class_tab
diff --git a/pretyping/classops.mli b/pretyping/classops.mli
index 35691ea37a..af00c0a8dc 100644
--- a/pretyping/classops.mli
+++ b/pretyping/classops.mli
@@ -21,7 +21,7 @@ type cl_typ =
| CL_SECVAR of variable
| CL_CONST of Constant.t
| CL_IND of inductive
- | CL_PROJ of Constant.t
+ | CL_PROJ of Projection.Repr.t
(** Equality over [cl_typ] *)
val cl_typ_eq : cl_typ -> cl_typ -> bool
@@ -39,16 +39,19 @@ type cl_info_typ = {
type coe_typ = GlobRef.t
(** This is the type of infos for declared coercions *)
-type coe_info_typ
+type coe_info_typ = {
+ coe_value : GlobRef.t;
+ coe_local : bool;
+ coe_is_identity : bool;
+ coe_is_projection : Projection.Repr.t option;
+ coe_param : int;
+}
(** [cl_index] is the type of class keys *)
type cl_index
-(** [coe_index] is the type of coercion keys *)
-type coe_index
-
(** This is the type of paths from a class to another *)
-type inheritance_path = coe_index list
+type inheritance_path = coe_info_typ list
(** {6 Access to classes infos } *)
@@ -79,8 +82,6 @@ val declare_coercion :
(** {6 Access to coercions infos } *)
val coercion_exists : coe_typ -> bool
-val coercion_value : coe_index -> (unsafe_judgment * bool * bool) Univ.in_universe_context_set
-
(** {6 Lookup functions for coercion paths } *)
(** @raise Not_found in the following functions when no path exists *)
@@ -105,10 +106,9 @@ val install_path_printer :
val string_of_class : cl_typ -> string
val pr_class : cl_typ -> Pp.t
val pr_cl_index : cl_index -> Pp.t
-val get_coercion_value : coe_index -> Constr.t
val inheritance_graph : unit -> ((cl_index * cl_index) * inheritance_path) list
val classes : unit -> cl_typ list
-val coercions : unit -> coe_index list
+val coercions : unit -> coe_info_typ list
(** [hide_coercion] returns the number of params to skip if the coercion must
be hidden, [None] otherwise; it raises [Not_found] if not a coercion *)
diff --git a/pretyping/coercion.ml b/pretyping/coercion.ml
index bf9e37aa74..5e3821edf1 100644
--- a/pretyping/coercion.ml
+++ b/pretyping/coercion.ml
@@ -52,17 +52,17 @@ exception NoCoercionNoUnifier of evar_map * unification_error
let apply_coercion_args env sigma check isproj argl funj =
let rec apply_rec sigma acc typ = function
| [] ->
- if isproj then
- let cst = fst (destConst sigma (j_val funj)) in
- let p = Projection.make cst false in
- let pb = lookup_projection p env in
- let args = List.skipn pb.Declarations.proj_npars argl in
- let hd, tl = match args with hd :: tl -> hd, tl | [] -> assert false in
- sigma, { uj_val = applist (mkProj (p, hd), tl);
- uj_type = typ }
- else
- sigma, { uj_val = applist (j_val funj,argl);
- uj_type = typ }
+ (match isproj with
+ | Some p ->
+ let npars = Projection.Repr.npars p in
+ let p = Projection.make p false in
+ let args = List.skipn npars argl in
+ let hd, tl = match args with hd :: tl -> hd, tl | [] -> assert false in
+ sigma, { uj_val = applist (mkProj (p, hd), tl);
+ uj_type = typ }
+ | None ->
+ sigma, { uj_val = applist (j_val funj,argl);
+ uj_type = typ })
| h::restl -> (* On devrait pouvoir s'arranger pour qu'on n'ait pas a faire hnf_constr *)
match EConstr.kind sigma (whd_all env sigma typ) with
| Prod (_,c1,c2) ->
@@ -98,7 +98,11 @@ let inh_pattern_coerce_to ?loc env pat ind1 ind2 =
open Program
let make_existential ?loc ?(opaque = not (get_proofs_transparency ())) na env evdref c =
- let src = Loc.tag ?loc (Evar_kinds.QuestionMark (Evar_kinds.Define opaque,na)) in
+ let src = Loc.tag ?loc (Evar_kinds.QuestionMark {
+ Evar_kinds.default_question_mark with
+ Evar_kinds.qm_obligation=Evar_kinds.Define opaque;
+ Evar_kinds.qm_name=na;
+ }) in
let evd, v = Evarutil.new_evar env !evdref ~src c in
evdref := evd;
v
@@ -209,8 +213,8 @@ and coerce ?loc env evdref (x : EConstr.constr) (y : EConstr.constr)
match (EConstr.kind !evdref x, EConstr.kind !evdref y) with
| Sort s, Sort s' ->
(match ESorts.kind !evdref s, ESorts.kind !evdref s' with
- | Prop x, Prop y when x == y -> None
- | Prop _, Type _ -> None
+ | Prop, Prop | Set, Set -> None
+ | (Prop | Set), Type _ -> None
| Type x, Type y when Univ.Universe.equal x y -> None (* false *)
| _ -> subco ())
| Prod (name, a, b), Prod (name', a', b') ->
@@ -365,8 +369,11 @@ let apply_coercion env sigma p hj typ_cl =
let j,t,evd =
List.fold_left
(fun (ja,typ_cl,sigma) i ->
- let ((fv,isid,isproj),ctx) = coercion_value i in
- let sigma = Evd.merge_context_set Evd.univ_flexible sigma ctx in
+ let isid = i.coe_is_identity in
+ let isproj = i.coe_is_projection in
+ let sigma, c = new_global sigma i.coe_value in
+ let typ = Retyping.get_type_of env sigma c in
+ let fv = make_judge c typ in
let argl = (class_args_of env sigma typ_cl)@[ja.uj_val] in
let sigma, jres =
apply_coercion_args env sigma true isproj argl fv
diff --git a/pretyping/constr_matching.ml b/pretyping/constr_matching.ml
index 2bc603a902..d7118efd7a 100644
--- a/pretyping/constr_matching.ml
+++ b/pretyping/constr_matching.ml
@@ -281,8 +281,8 @@ let matches_core env sigma allow_bound_rels
let open Glob_term in
begin match ps, ESorts.kind sigma s with
- | GProp, Prop Null -> subst
- | GSet, Prop Pos -> subst
+ | GProp, Prop -> subst
+ | GSet, Set -> subst
| GType _, Type _ -> subst
| _ -> raise PatternMatchingFailure
end
diff --git a/pretyping/detyping.ml b/pretyping/detyping.ml
index 23a985dc3e..6a9a042f57 100644
--- a/pretyping/detyping.ml
+++ b/pretyping/detyping.ml
@@ -597,8 +597,8 @@ let detype_universe sigma u =
Univ.Universe.map fn u
let detype_sort sigma = function
- | Prop Null -> GProp
- | Prop Pos -> GSet
+ | Prop -> GProp
+ | Set -> GSet
| Type u ->
GType
(if !print_universes
@@ -689,10 +689,9 @@ and detype_r d flags avoid env sigma t =
(** Print the compatibility match version *)
let c' =
try
- let pb = Environ.lookup_projection p (snd env) in
- let ind = pb.Declarations.proj_ind in
+ let ind = Projection.inductive p in
let bodies = Inductiveops.legacy_match_projection (snd env) ind in
- let body = bodies.(pb.Declarations.proj_arg) in
+ let body = bodies.(Projection.arg p) in
let ty = Retyping.get_type_of (snd env) sigma c in
let ((ind,u), args) = Inductiveops.find_mrectype (snd env) sigma ty in
let body' = strip_lam_assum body in
@@ -1032,11 +1031,9 @@ let rec subst_glob_constr subst = DAst.map (function
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 p' = subst_proj subst p in
let c' = subst_glob_constr subst c in
- if kn' == kn && c' == c then raw else GProj(Projection.make kn' b, c')
+ if p' == p && c' == c then raw else GProj(p', c')
)
(* Utilities to transform kernel cases to simple pattern-matching problem *)
diff --git a/pretyping/evarconv.ml b/pretyping/evarconv.ml
index a71ef65081..984fa92c0e 100644
--- a/pretyping/evarconv.ml
+++ b/pretyping/evarconv.ml
@@ -71,7 +71,7 @@ let coq_unit_judge =
let unfold_projection env evd ts p c =
let cst = Projection.constant p in
if is_transparent_constant ts cst then
- Some (mkProj (Projection.make cst true, c))
+ Some (mkProj (Projection.unfold p, c))
else None
let eval_flexible_term ts env evd c =
@@ -292,8 +292,8 @@ let ise_stack2 no_app env evd f sk1 sk2 =
| Success i'' -> ise_stack2 true i'' q1 q2
| UnifFailure _ as x -> fail x)
| UnifFailure _ as x -> fail x)
- | Stack.Proj (n1,a1,p1,_)::q1, Stack.Proj (n2,a2,p2,_)::q2 ->
- if Constant.equal (Projection.constant p1) (Projection.constant p2)
+ | Stack.Proj (p1,_)::q1, Stack.Proj (p2,_)::q2 ->
+ if Projection.Repr.equal (Projection.repr p1) (Projection.repr p2)
then ise_stack2 true i q1 q2
else fail (UnifFailure (i, NotSameHead))
| Stack.Fix (((li1, i1),(_,tys1,bds1 as recdef1)),a1,_)::q1,
@@ -334,8 +334,8 @@ let exact_ise_stack2 env evd f sk1 sk2 =
(fun i -> ise_array2 i (fun ii -> f (push_rec_types recdef1 env) ii CONV) bds1 bds2);
(fun i -> ise_stack2 i a1 a2)]
else UnifFailure (i,NotSameHead)
- | Stack.Proj (n1,a1,p1,_)::q1, Stack.Proj (n2,a2,p2,_)::q2 ->
- if Constant.equal (Projection.constant p1) (Projection.constant p2)
+ | Stack.Proj (p1,_)::q1, Stack.Proj (p2,_)::q2 ->
+ if Projection.Repr.equal (Projection.repr p1) (Projection.repr p2)
then ise_stack2 i q1 q2
else (UnifFailure (i, NotSameHead))
| Stack.App _ :: _, Stack.App _ :: _ ->
@@ -986,10 +986,9 @@ and conv_record trs env evd (ctx,(h,h2),c,bs,(params,params1),(us,us2),(sk1,sk2)
and eta_constructor ts env evd sk1 ((ind, i), u) sk2 term2 =
let open Declarations in
let mib = lookup_mind (fst ind) env in
- match mib.Declarations.mind_record with
- | PrimRecord info when mib.Declarations.mind_finite == Declarations.BiFinite ->
- let (_, projs, _) = info.(snd ind) in
- let pars = mib.Declarations.mind_nparams in
+ match get_projections env ind with
+ | Some projs when mib.mind_finite == BiFinite ->
+ let pars = mib.mind_nparams in
(try
let l1' = Stack.tail pars sk1 in
let l2' =
diff --git a/pretyping/evarsolve.ml b/pretyping/evarsolve.ml
index 8afb9b9421..3f5d186d4e 100644
--- a/pretyping/evarsolve.ml
+++ b/pretyping/evarsolve.ml
@@ -69,7 +69,7 @@ let refresh_universes ?(status=univ_rigid) ?(onlyalg=false) ?(refreshset=false)
if onlyalg && alg then
(evdref := Evd.make_flexible_variable !evdref ~algebraic:false l; t)
else t))
- | Prop Pos when refreshset && not direction ->
+ | Set when refreshset && not direction ->
(* Cannot make a universe "lower" than "Set",
only refreshing when we want higher universes. *)
refresh_sort status ~direction s
diff --git a/pretyping/glob_ops.ml b/pretyping/glob_ops.ml
index ba193da60d..24eb666828 100644
--- a/pretyping/glob_ops.ml
+++ b/pretyping/glob_ops.ml
@@ -112,7 +112,7 @@ let fix_kind_eq f k1 k2 = match k1, k2 with
let eq (i1, o1) (i2, o2) =
Option.equal Int.equal i1 i2 && fix_recursion_order_eq f o1 o2
in
- Int.equal i1 i2 && Array.equal eq a1 a1
+ Int.equal i1 i2 && Array.equal eq a1 a2
| GCoFix i1, GCoFix i2 -> Int.equal i1 i2
| (GFix _ | GCoFix _), _ -> false
@@ -452,7 +452,7 @@ let rec rename_glob_vars l c = force @@ DAst.map_with_loc (fun ?loc -> function
else r
| GProd (na,bk,t,c) ->
let na',l' = update_subst na l in
- GProd (na,bk,rename_glob_vars l t,rename_glob_vars l' c)
+ GProd (na',bk,rename_glob_vars l t,rename_glob_vars l' c)
| GLambda (na,bk,t,c) ->
let na',l' = update_subst na l in
GLambda (na',bk,rename_glob_vars l t,rename_glob_vars l' c)
@@ -562,7 +562,9 @@ let rec glob_constr_of_cases_pattern_aux isclosed x = DAst.map_with_loc (fun ?lo
| PatVar (Name id) when not isclosed ->
GVar id
| PatVar Anonymous when not isclosed ->
- GHole (Evar_kinds.QuestionMark (Define false,Anonymous),Namegen.IntroAnonymous,None)
+ GHole (Evar_kinds.QuestionMark {
+ Evar_kinds.default_question_mark with Evar_kinds.qm_obligation=Define false;
+ },Namegen.IntroAnonymous,None)
| _ -> raise Not_found
) x
diff --git a/library/heads.ml b/pretyping/heads.ml
index d9d650ac07..7d9debce34 100644
--- a/library/heads.ml
+++ b/pretyping/heads.ml
@@ -128,8 +128,8 @@ let compute_head = function
let env = Global.env() in
let cb = Environ.lookup_constant cst env in
let is_Def = function Declarations.Def _ -> true | _ -> false in
- let body =
- if not (Environ.is_projection cst env) && is_Def cb.Declarations.const_body
+ let body =
+ if not (Recordops.is_primitive_projection cst) && is_Def cb.Declarations.const_body
then Global.body_of_constant cst else None
in
(match body with
diff --git a/library/heads.mli b/pretyping/heads.mli
index 421242996c..421242996c 100644
--- a/library/heads.mli
+++ b/pretyping/heads.mli
diff --git a/pretyping/indrec.ml b/pretyping/indrec.ml
index 4ab932723e..dc900ab814 100644
--- a/pretyping/indrec.ml
+++ b/pretyping/indrec.ml
@@ -79,14 +79,14 @@ let mis_make_case_com dep env sigma (ind, u as pind) (mib,mip as specif) kind =
let lnamespar = Vars.subst_instance_context u mib.mind_params_ctxt in
let indf = make_ind_family(pind, Context.Rel.to_extended_list mkRel 0 lnamespar) in
let constrs = get_constructors env indf in
- let projs = get_projections env indf in
+ let projs = get_projections env ind in
let () = if Option.is_empty projs then check_privacy_block mib in
let () =
if not (Sorts.List.mem kind (elim_sorts specif)) then
raise
(RecursionSchemeError
- (NotAllowedCaseAnalysis (false, fst (UnivGen.fresh_sort_in_family env kind), pind)))
+ (NotAllowedCaseAnalysis (false, fst (UnivGen.fresh_sort_in_family kind), pind)))
in
let ndepar = mip.mind_nrealdecls + 1 in
@@ -136,7 +136,7 @@ let mis_make_case_com dep env sigma (ind, u as pind) (mib,mip as specif) kind =
mkLambda_string "f" t
(add_branch (push_rel (LocalAssum (Anonymous, t)) env) (k+1))
in
- let (sigma, s) = Evd.fresh_sort_in_family ~rigid:Evd.univ_flexible_alg env sigma kind in
+ let (sigma, s) = Evd.fresh_sort_in_family ~rigid:Evd.univ_flexible_alg sigma kind in
let typP = make_arity env' sigma dep indf s in
let typP = EConstr.Unsafe.to_constr typP in
let c =
@@ -455,7 +455,7 @@ let mis_make_indrec env sigma ?(force_mutual=false) listdepkind mib u =
| ((indi,u),_,_,dep,kinds)::rest ->
let indf = make_ind_family ((indi,u), Context.Rel.to_extended_list mkRel i lnamesparrec) in
let s =
- Evarutil.evd_comb1 (Evd.fresh_sort_in_family ~rigid:Evd.univ_flexible_alg env)
+ Evarutil.evd_comb1 (Evd.fresh_sort_in_family ~rigid:Evd.univ_flexible_alg)
evdref kinds
in
let typP = make_arity env !evdref dep indf s in
@@ -550,8 +550,7 @@ let check_arities env listdepkind =
let kelim = elim_sorts (mibi,mipi) in
if not (Sorts.List.mem kind kelim) then raise
(RecursionSchemeError
- (NotAllowedCaseAnalysis (true, fst (UnivGen.fresh_sort_in_family env
- kind),(mind,u))))
+ (NotAllowedCaseAnalysis (true, fst (UnivGen.fresh_sort_in_family kind),(mind,u))))
else if Int.List.mem ni ln then raise
(RecursionSchemeError (NotMutualInScheme (mind,mind)))
else ni::ln)
diff --git a/pretyping/inductiveops.ml b/pretyping/inductiveops.ml
index d599afe699..ec0ff73062 100644
--- a/pretyping/inductiveops.ml
+++ b/pretyping/inductiveops.ml
@@ -51,7 +51,7 @@ let arities_of_constructors env (ind,u as indu) =
type inductive_family = pinductive * constr list
let make_ind_family (mis, params) = (mis,params)
-let dest_ind_family (mis,params) = (mis,params)
+let dest_ind_family (mis,params) : inductive_family = (mis,params)
let map_ind_family f (mis,params) = (mis, List.map f params)
@@ -269,11 +269,9 @@ let allowed_sorts env (kn,i as ind) =
let (mib,mip) = Inductive.lookup_mind_specif env ind in
mip.mind_kelim
-let projection_nparams_env env p =
- let pb = lookup_projection p env in
- pb.proj_npars
+let projection_nparams_env _ p = Projection.npars p
-let projection_nparams p = projection_nparams_env (Global.env ()) p
+let projection_nparams p = Projection.npars p
let has_dependent_elim mib =
match mib.mind_record with
@@ -303,7 +301,7 @@ type constructor_summary = {
cs_cstr : pconstructor;
cs_params : constr list;
cs_nargs : int;
- cs_args : Context.Rel.t;
+ cs_args : Constr.rel_context;
cs_concl_realargs : constr array
}
@@ -343,17 +341,11 @@ let get_constructors env (ind,params) =
Array.init (Array.length mip.mind_consnames)
(fun j -> get_constructor (ind,mib,mip,params) (j+1))
-let get_projections env (ind,params) =
- let (mib,mip) = Inductive.lookup_mind_specif env (fst ind) in
- match mib.mind_record with
- | PrimRecord infos ->
- let (_, projs, _) = infos.(snd (fst ind)) in
- Some projs
- | NotRecord | FakeRecord -> None
+let get_projections = Environ.get_projections
let make_case_or_project env sigma indf ci pred c branches =
let open EConstr in
- let projs = get_projections env indf in
+ let projs = get_projections env (fst (fst indf)) in
match projs with
| None -> (mkCase (ci, pred, c, branches))
| Some ps ->
@@ -465,30 +457,29 @@ let build_branch_type env sigma dep p cs =
let compute_projections env (kn, i as ind) =
let open Term in
let mib = Environ.lookup_mind kn env in
- let indu = match mib.mind_universes with
- | Monomorphic_ind _ -> mkInd ind
- | Polymorphic_ind ctx -> mkIndU (ind, make_abstract_instance ctx)
- | Cumulative_ind ctx ->
- mkIndU (ind, make_abstract_instance (ACumulativityInfo.univ_context ctx))
+ let u = match mib.mind_universes with
+ | Monomorphic_ind _ -> Instance.empty
+ | Polymorphic_ind auctx -> make_abstract_instance auctx
+ | Cumulative_ind acumi ->
+ make_abstract_instance (ACumulativityInfo.univ_context acumi)
in
let x = match mib.mind_record with
| NotRecord | FakeRecord ->
anomaly Pp.(str "Trying to build primitive projections for a non-primitive record")
| PrimRecord info-> Name (pi1 (info.(i)))
in
- (** FIXME: handle mutual records *)
- let pkt = mib.mind_packets.(0) in
- let { mind_consnrealargs; mind_consnrealdecls } = pkt in
+ let pkt = mib.mind_packets.(i) in
let { mind_nparams = nparamargs; mind_params_ctxt = params } = mib in
- let rctx, _ = decompose_prod_assum (subst1 indu pkt.mind_nf_lc.(0)) in
+ let subst = List.init mib.mind_ntypes (fun i -> mkIndU ((kn, mib.mind_ntypes - i - 1), u)) in
+ let rctx, _ = decompose_prod_assum (substl subst pkt.mind_nf_lc.(0)) in
let ctx, paramslet = List.chop pkt.mind_consnrealdecls.(0) rctx in
- let mp, dp, l = MutInd.repr3 kn in
(** We build a substitution smashing the lets in the record parameters so
that typechecking projections requires just a substitution and not
matching with a parameter context. *)
let indty =
(* [ty] = [Ind inst] is typed in context [params] *)
let inst = Context.Rel.to_extended_vect mkRel 0 paramslet in
+ let indu = mkIndU (ind, u) in
let ty = mkApp (indu, inst) in
(* [Ind inst] is typed in context [params-wo-let] *)
ty
@@ -498,8 +489,8 @@ let compute_projections env (kn, i as ind) =
{ ind_tags = []; cstr_tags = [|Context.Rel.to_tags ctx|]; style = LetStyle } in
{ ci_ind = ind;
ci_npar = nparamargs;
- ci_cstr_ndecls = mind_consnrealdecls;
- ci_cstr_nargs = mind_consnrealargs;
+ ci_cstr_ndecls = pkt.mind_consnrealdecls;
+ ci_cstr_nargs = pkt.mind_consnrealargs;
ci_pp_info = print_info }
in
let len = List.length ctx in
@@ -512,7 +503,7 @@ let compute_projections env (kn, i as ind) =
let body = mkCase (ci, p, mkRel 1, [|lift 1 branch|]) in
it_mkLambda_or_LetIn (mkLambda (x,indty,body)) params
in
- let projections decl (j, pbs, subst) =
+ let projections decl (proj_arg, j, pbs, subst) =
match decl with
| LocalDef (na,c,t) ->
(* From [params, field1,..,fieldj |- c(params,field1,..,fieldj)]
@@ -525,11 +516,12 @@ let compute_projections env (kn, i as ind) =
to [params, x:I |- subst:field1,..,fieldj+1] where [subst]
is represented with instance of field1 last *)
let subst = c1 :: subst in
- (j+1, pbs, subst)
+ (proj_arg, j+1, pbs, subst)
| LocalAssum (na,t) ->
match na with
| Name id ->
- let kn = Constant.make1 (KerName.make mp dp (Label.of_id id)) in
+ let lab = Label.of_id id in
+ let kn = Projection.Repr.make ind ~proj_npars:mib.mind_nparams ~proj_arg lab in
(* from [params, field1,..,fieldj |- t(params,field1,..,fieldj)]
to [params, x:I, field1,..,fieldj |- t(params,field1,..,fieldj] *)
let t = liftn 1 j t in
@@ -544,12 +536,12 @@ let compute_projections env (kn, i as ind) =
let etab = it_mkLambda_or_LetIn (mkLambda (x, indty, term)) params in
let etat = it_mkProd_or_LetIn (mkProd (x, indty, ty)) params in
let body = (etab, etat, compat) in
- (j + 1, body :: pbs, fterm :: subst)
+ (proj_arg + 1, j + 1, body :: pbs, fterm :: subst)
| Anonymous ->
anomaly Pp.(str "Trying to build primitive projections for a non-primitive record")
in
- let (_, pbs, subst) =
- List.fold_right projections ctx (1, [], [])
+ let (_, _, pbs, subst) =
+ List.fold_right projections ctx (0, 1, [], [])
in
Array.rev_of_list pbs
@@ -641,7 +633,7 @@ let is_predicate_explicitly_dep env sigma pred arsign =
dependency status (of course, Anonymous implies non
dependent, but not conversely).
- From Coq > 8.2, using or not the the effective dependency of
+ From Coq > 8.2, using or not the effective dependency of
the predicate is parametrable! *)
begin match na with
@@ -738,8 +730,8 @@ let type_of_inductive_knowing_conclusion env sigma ((mib,mip),u) conclty =
!evdref, EConstr.of_constr (mkArity (List.rev ctx,scl))
let type_of_projection_constant env (p,u) =
- let pb = lookup_projection p env in
- Vars.subst_instance_constr u pb.proj_type
+ let pty = lookup_projection p env in
+ Vars.subst_instance_constr u pty
let type_of_projection_knowing_arg env sigma p c ty =
let c = EConstr.Unsafe.to_constr c in
diff --git a/pretyping/inductiveops.mli b/pretyping/inductiveops.mli
index aa53f7e67c..ea34707bfc 100644
--- a/pretyping/inductiveops.mli
+++ b/pretyping/inductiveops.mli
@@ -93,12 +93,12 @@ val inductive_nparamdecls : inductive -> int
val inductive_nparamdecls_env : env -> inductive -> int
(** @return params context *)
-val inductive_paramdecls : pinductive -> Context.Rel.t
-val inductive_paramdecls_env : env -> pinductive -> Context.Rel.t
+val inductive_paramdecls : pinductive -> Constr.rel_context
+val inductive_paramdecls_env : env -> pinductive -> Constr.rel_context
(** @return full arity context, hence with letin *)
-val inductive_alldecls : pinductive -> Context.Rel.t
-val inductive_alldecls_env : env -> pinductive -> Context.Rel.t
+val inductive_alldecls : pinductive -> Constr.rel_context
+val inductive_alldecls_env : env -> pinductive -> Constr.rel_context
(** {7 Extract information from a constructor name} *)
@@ -130,7 +130,10 @@ val has_dependent_elim : mutual_inductive_body -> bool
(** Primitive projections *)
val projection_nparams : Projection.t -> int
+[@@ocaml.deprecated "Use [Projection.npars]"]
val projection_nparams_env : env -> Projection.t -> int
+[@@ocaml.deprecated "Use [Projection.npars]"]
+
val type_of_projection_knowing_arg : env -> evar_map -> Projection.t ->
EConstr.t -> EConstr.types -> types
@@ -141,7 +144,7 @@ type constructor_summary = {
cs_cstr : pconstructor; (* internal name of the constructor plus universes *)
cs_params : constr list; (* parameters of the constructor in current ctx *)
cs_nargs : int; (* length of arguments signature (letin included) *)
- cs_args : Context.Rel.t; (* signature of the arguments (letin included) *)
+ cs_args : Constr.rel_context; (* signature of the arguments (letin included) *)
cs_concl_realargs : constr array; (* actual realargs in the concl of cstr *)
}
val lift_constructor : int -> constructor_summary -> constructor_summary
@@ -149,12 +152,13 @@ val get_constructor :
pinductive * mutual_inductive_body * one_inductive_body * constr list ->
int -> constructor_summary
val get_constructors : env -> inductive_family -> constructor_summary array
-val get_projections : env -> inductive_family -> Constant.t array option
+val get_projections : env -> inductive -> Projection.Repr.t array option
+[@@ocaml.deprecated "Use [Environ.get_projections]"]
(** [get_arity] returns the arity of the inductive family instantiated
with the parameters; if recursively non-uniform parameters are not
part of the inductive family, they appears in the arity *)
-val get_arity : env -> inductive_family -> Context.Rel.t * Sorts.family
+val get_arity : env -> inductive_family -> Constr.rel_context * Sorts.family
val build_dependent_constructor : constructor_summary -> constr
val build_dependent_inductive : env -> inductive_family -> constr
diff --git a/pretyping/nativenorm.ml b/pretyping/nativenorm.ml
index 7319846fb3..5df41ef76a 100644
--- a/pretyping/nativenorm.ml
+++ b/pretyping/nativenorm.ml
@@ -123,7 +123,7 @@ let construct_of_constr_notnative const env tag (mind, _ as ind) u allargs =
try
if const then
let ctyp = type_constructor mind mib u (mip.mind_nf_lc.(0)) params in
- retroknowledge Retroknowledge.get_vm_decompile_constant_info env (mkInd ind) tag, ctyp
+ Retroknowledge.get_vm_decompile_constant_info env.retroknowledge (mkInd ind) tag, ctyp
else
raise Not_found
with Not_found ->
@@ -144,7 +144,7 @@ let construct_of_constr_const env tag typ =
let construct_of_constr_block = construct_of_constr false
-let build_branches_type env sigma (mind,_ as _ind) mib mip u params dep p =
+let build_branches_type env sigma (mind,_ as _ind) mib mip u params p =
let rtbl = mip.mind_reloc_tbl in
(* [build_one_branch i cty] construit le type de la ieme branche (commence
a 0) et les lambda correspondant aux realargs *)
@@ -161,20 +161,17 @@ let build_branches_type env sigma (mind,_ as _ind) mib mip u params dep p =
let codom =
let ndecl = List.length decl in
let papp = mkApp(lift ndecl p,crealargs) in
- if dep then
- let cstr = ith_constructor_of_inductive (fst ind) (i+1) in
- let relargs = Array.init carity (fun i -> mkRel (carity-i)) in
- let params = Array.map (lift ndecl) params in
- let dep_cstr = mkApp(mkApp(mkConstructU (cstr,snd ind),params),relargs) in
- mkApp(papp,[|dep_cstr|])
- else papp
+ let cstr = ith_constructor_of_inductive (fst ind) (i+1) in
+ let relargs = Array.init carity (fun i -> mkRel (carity-i)) in
+ let params = Array.map (lift ndecl) params in
+ let dep_cstr = mkApp(mkApp(mkConstructU (cstr,snd ind),params),relargs) in
+ mkApp(papp,[|dep_cstr|])
in
decl, decl_with_letin, codom
in Array.mapi build_one_branch mip.mind_nf_lc
-let build_case_type dep p realargs c =
- if dep then mkApp(mkApp(p, realargs), [|c|])
- else mkApp(p, realargs)
+let build_case_type p realargs c =
+ mkApp(mkApp(p, realargs), [|c|])
(* normalisation of values *)
@@ -188,14 +185,13 @@ let branch_of_switch lvl ans bs =
bs ci in
Array.init (Array.length tbl) branch
-let get_proj env ((mind, n), i) =
- let mib = Environ.lookup_mind mind env in
- match mib.mind_record with
- | NotRecord | FakeRecord ->
+let get_proj env (ind, proj_arg) =
+ let mib = Environ.lookup_mind (fst ind) env in
+ match Declareops.inductive_make_projection ind mib ~proj_arg with
+ | None ->
CErrors.anomaly (Pp.strbrk "Return type is not a primitive record")
- | PrimRecord info ->
- let _, projs, _ = info.(n) in
- Projection.make projs.(i) true
+ | Some p ->
+ Projection.make p true
let rec nf_val env sigma v typ =
match kind_of_value v with
@@ -317,9 +313,9 @@ and nf_atom_type env sigma atom =
let pT =
hnf_prod_applist_assum env nparamdecls
(Inductiveops.type_of_inductive env ind) (Array.to_list params) in
- let dep, p = nf_predicate env sigma ind mip params p pT in
+ let p = nf_predicate env sigma ind mip params p pT in
(* Calcul du type des branches *)
- let btypes = build_branches_type env sigma (fst ind) mib mip u params dep p in
+ let btypes = build_branches_type env sigma (fst ind) mib mip u params p in
(* calcul des branches *)
let bsw = branch_of_switch (nb_rel env) ans bs in
let mkbranch i v =
@@ -328,7 +324,7 @@ and nf_atom_type env sigma atom =
Termops.it_mkLambda_or_LetIn_from_no_LetIn b decl_with_letin
in
let branchs = Array.mapi mkbranch bsw in
- let tcase = build_case_type dep p realargs a in
+ let tcase = build_case_type p realargs a in
let ci = ans.asw_ci in
mkCase(ci, p, a, branchs), tcase
| Afix(tt,ft,rp,s) ->
@@ -375,18 +371,18 @@ and nf_atom_type env sigma atom =
and nf_predicate env sigma ind mip params v pT =
match kind (whd_allnolet env pT) with
| LetIn (name,b,t,pT) ->
- let dep,body =
+ let body =
nf_predicate (push_rel (LocalDef (name,b,t)) env) sigma ind mip params v pT in
- dep, mkLetIn (name,b,t,body)
+ mkLetIn (name,b,t,body)
| Prod (name,dom,codom) -> begin
match kind_of_value v with
| Vfun f ->
let k = nb_rel env in
let vb = f (mk_rel_accu k) in
- let dep,body =
+ let body =
nf_predicate (push_rel (LocalAssum (name,dom)) env) sigma ind mip params vb codom in
- dep, mkLambda(name,dom,body)
- | _ -> false, nf_type env sigma v
+ mkLambda(name,dom,body)
+ | _ -> nf_type env sigma v
end
| _ ->
match kind_of_value v with
@@ -399,8 +395,8 @@ and nf_predicate env sigma ind mip params v pT =
let params = if Int.equal n 0 then params else Array.map (lift n) params in
let dom = mkApp(mkIndU ind,Array.append params rargs) in
let body = nf_type (push_rel (LocalAssum (name,dom)) env) sigma vb in
- true, mkLambda(name,dom,body)
- | _ -> false, nf_type env sigma v
+ mkLambda(name,dom,body)
+ | _ -> 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
diff --git a/pretyping/patternops.ml b/pretyping/patternops.ml
index 622a8e982e..f7fea22c0f 100644
--- a/pretyping/patternops.ml
+++ b/pretyping/patternops.ml
@@ -150,8 +150,8 @@ let pattern_of_constr env sigma t =
| Rel n -> PRel n
| Meta n -> PMeta (Some (Id.of_string ("META" ^ string_of_int n)))
| Var id -> PVar id
- | Sort (Prop Null) -> PSort GProp
- | Sort (Prop Pos) -> PSort GSet
+ | Sort Prop -> PSort GProp
+ | Sort Set -> PSort GSet
| Sort (Type _) -> PSort (GType [])
| Cast (c,_,_) -> pattern_of_constr env c
| LetIn (na,c,t,b) -> PLetIn (na,pattern_of_constr env c,Some (pattern_of_constr env t),
@@ -287,8 +287,7 @@ let rec subst_pattern subst pat =
| PEvar _
| PRel _ -> pat
| PProj (p,c) ->
- let p' = Projection.map (fun p ->
- destConstRef (fst (subst_global subst (ConstRef p)))) p in
+ let p' = Projection.map (subst_mind subst) p in
let c' = subst_pattern subst c in
if p' == p && c' == c then pat else
PProj(p',c')
diff --git a/pretyping/pretyping.ml b/pretyping/pretyping.ml
index 57c4d363b2..3b9a8e6a1d 100644
--- a/pretyping/pretyping.ml
+++ b/pretyping/pretyping.ml
@@ -381,8 +381,16 @@ let adjust_evar_source evdref na c =
| Name id, Evar (evk,args) ->
let evi = Evd.find !evdref evk in
begin match evi.evar_source with
- | loc, Evar_kinds.QuestionMark (b,Anonymous) ->
- let src = (loc,Evar_kinds.QuestionMark (b,na)) in
+ | loc, Evar_kinds.QuestionMark {
+ Evar_kinds.qm_obligation=b;
+ Evar_kinds.qm_name=Anonymous;
+ Evar_kinds.qm_record_field=recfieldname;
+ } ->
+ let src = (loc,Evar_kinds.QuestionMark {
+ Evar_kinds.qm_obligation=b;
+ Evar_kinds.qm_name=na;
+ Evar_kinds.qm_record_field=recfieldname;
+ }) in
let (evd, evk') = restrict_evar !evdref evk (evar_filter evi) ~src None in
evdref := evd;
mkEvar (evk',args)
@@ -765,11 +773,11 @@ let rec pretype k0 resolve_tc (tycon : type_constraint) (env : ExtraEnv.t) evdre
in
let app_f =
match EConstr.kind !evdref fj.uj_val with
- | Const (p, u) when Environ.is_projection p env.ExtraEnv.env ->
+ | Const (p, u) when Recordops.is_primitive_projection p ->
+ let p = Option.get @@ Recordops.find_primitive_projection p in
let p = Projection.make p false in
- let pb = Environ.lookup_projection p env.ExtraEnv.env in
- let npars = pb.Declarations.proj_npars in
- fun n ->
+ let npars = Projection.npars p in
+ fun n ->
if n == npars + 1 then fun _ v -> mkProj (p, v)
else fun f v -> applist (f, [v])
| _ -> fun _ f v -> applist (f, [v])
@@ -897,6 +905,7 @@ let rec pretype k0 resolve_tc (tycon : type_constraint) (env : ExtraEnv.t) evdre
let cloc = loc_of_glob_constr c in
error_case_not_inductive ?loc:cloc env.ExtraEnv.env !evdref cj
in
+ let ind = fst (fst (dest_ind_family indf)) in
let cstrs = get_constructors env.ExtraEnv.env indf in
if not (Int.equal (Array.length cstrs) 1) then
user_err ?loc (str "Destructing let is only for inductive types" ++
@@ -907,7 +916,7 @@ let rec pretype k0 resolve_tc (tycon : type_constraint) (env : ExtraEnv.t) evdre
int cs.cs_nargs ++ str " variables.");
let fsign, record =
let set_name na d = set_name na (map_rel_decl EConstr.of_constr d) in
- match get_projections env.ExtraEnv.env indf with
+ match Environ.get_projections env.ExtraEnv.env ind with
| None ->
List.map2 set_name (List.rev nal) cs.cs_args, false
| Some ps ->
diff --git a/pretyping/pretyping.mllib b/pretyping/pretyping.mllib
index 3d9b5d3cfc..5da5aff449 100644
--- a/pretyping/pretyping.mllib
+++ b/pretyping/pretyping.mllib
@@ -14,6 +14,7 @@ Find_subterm
Evardefine
Evarsolve
Recordops
+Heads
Evarconv
Typing
Miscops
diff --git a/pretyping/recordops.ml b/pretyping/recordops.ml
index 56a8830991..2f861c117b 100644
--- a/pretyping/recordops.ml
+++ b/pretyping/recordops.ml
@@ -44,7 +44,7 @@ type struc_typ = {
let structure_table =
Summary.ref (Indmap.empty : struc_typ Indmap.t) ~name:"record-structs"
let projection_table =
- Summary.ref Cmap.empty ~name:"record-projs"
+ Summary.ref (Cmap.empty : struc_typ Cmap.t) ~name:"record-projs"
(* TODO: could be unify struc_typ and struc_tuple ? in particular,
is the inductive always (fst constructor) ? It seems so... *)
@@ -53,7 +53,9 @@ type struc_tuple =
inductive * constructor * (Name.t * bool) list * Constant.t option list
let load_structure i (_,(ind,id,kl,projs)) =
- let n = (fst (Global.lookup_inductive ind)).Declarations.mind_nparams in
+ let open Declarations in
+ let mib, mip = Global.lookup_inductive ind in
+ let n = mib.mind_nparams in
let struc =
{ s_CONST = id; s_EXPECTEDPARAM = n; s_PROJ = projs; s_PROJKIND = kl } in
structure_table := Indmap.add ind struc !structure_table;
@@ -107,6 +109,34 @@ let find_projection = function
| ConstRef cst -> Cmap.find cst !projection_table
| _ -> raise Not_found
+let prim_table =
+ Summary.ref (Cmap_env.empty : Projection.Repr.t Cmap_env.t) ~name:"record-prim-projs"
+
+let load_prim i (_,p) =
+ prim_table := Cmap_env.add (Projection.Repr.constant p) p !prim_table
+
+let cache_prim p = load_prim 1 p
+
+let subst_prim (subst,p) = subst_proj_repr subst p
+
+let discharge_prim (_,p) = Some (Lib.discharge_proj_repr p)
+
+let inPrim : Projection.Repr.t -> obj =
+ declare_object {
+ (default_object "PRIMPROJS") with
+ cache_function = cache_prim ;
+ load_function = load_prim;
+ subst_function = subst_prim;
+ classify_function = (fun x -> Substitute x);
+ discharge_function = discharge_prim }
+
+let declare_primitive_projection p = Lib.add_anonymous_leaf (inPrim p)
+
+let is_primitive_projection c = Cmap_env.mem c !prim_table
+
+let find_primitive_projection c =
+ try Some (Cmap_env.find c !prim_table) with Not_found -> None
+
(************************************************************************)
(*s A canonical structure declares "canonical" conversion hints between *)
(* the effective components of a structure and the projections of the *)
diff --git a/pretyping/recordops.mli b/pretyping/recordops.mli
index 748f053b2f..415b964168 100644
--- a/pretyping/recordops.mli
+++ b/pretyping/recordops.mli
@@ -44,6 +44,13 @@ val find_projection_nparams : GlobRef.t -> int
(** raise [Not_found] if not a projection *)
val find_projection : GlobRef.t -> struc_typ
+(** Sets up the mapping from constants to primitive projections *)
+val declare_primitive_projection : Projection.Repr.t -> unit
+
+val is_primitive_projection : Constant.t -> bool
+
+val find_primitive_projection : Constant.t -> Projection.Repr.t option
+
(** {6 Canonical structures } *)
(** A canonical structure declares "canonical" conversion hints between
the effective components of a structure and the projections of the
diff --git a/pretyping/reductionops.ml b/pretyping/reductionops.ml
index 7fb1a0a578..ba40262815 100644
--- a/pretyping/reductionops.ml
+++ b/pretyping/reductionops.ml
@@ -47,29 +47,28 @@ open Libobject
type effect_name = string
(** create a persistent set to store effect functions *)
-module ConstrMap = Map.Make (Constr)
(* Table bindings a constant to an effect *)
-let constant_effect_table = Summary.ref ~name:"reduction-side-effect" ConstrMap.empty
+let constant_effect_table = Summary.ref ~name:"reduction-side-effect" Cmap.empty
(* Table bindings function key to effective functions *)
let effect_table = Summary.ref ~name:"reduction-function-effect" String.Map.empty
(** a test to know whether a constant is actually the effect function *)
-let reduction_effect_hook env sigma termkey c =
+let reduction_effect_hook env sigma con c =
try
- let funkey = ConstrMap.find termkey !constant_effect_table in
+ let funkey = Cmap.find con !constant_effect_table in
let effect = String.Map.find funkey !effect_table in
effect env sigma (Lazy.force c)
with Not_found -> ()
-let cache_reduction_effect (_,(termkey,funkey)) =
- constant_effect_table := ConstrMap.add termkey funkey !constant_effect_table
+let cache_reduction_effect (_,(con,funkey)) =
+ constant_effect_table := Cmap.add con funkey !constant_effect_table
-let subst_reduction_effect (subst,(termkey,funkey)) =
- (subst_mps subst termkey,funkey)
+let subst_reduction_effect (subst,(con,funkey)) =
+ (subst_constant subst con,funkey)
-let inReductionEffect : Constr.constr * string -> obj =
+let inReductionEffect : Constant.t * string -> obj =
declare_object {(default_object "REDUCTION-EFFECT") with
cache_function = cache_reduction_effect;
open_function = (fun i o -> if Int.equal i 1 then cache_reduction_effect o);
@@ -83,8 +82,7 @@ let declare_reduction_effect funkey f =
(** A function to set the value of the print function *)
let set_reduction_effect x funkey =
- let termkey = UnivGen.constr_of_global x in
- Lib.add_anonymous_leaf (inReductionEffect (termkey,funkey))
+ Lib.add_anonymous_leaf (inReductionEffect (x,funkey))
(** Machinery to custom the behavior of the reduction *)
@@ -280,7 +278,7 @@ sig
type 'a member =
| App of 'a app_node
| Case of case_info * 'a * 'a array * Cst_stack.t
- | Proj of int * int * Projection.t * Cst_stack.t
+ | Proj of Projection.t * Cst_stack.t
| Fix of ('a, 'a) pfixpoint * 'a t * Cst_stack.t
| Cst of cst_member * int * int list * 'a t * Cst_stack.t
and 'a t = 'a member list
@@ -337,7 +335,7 @@ struct
type 'a member =
| App of 'a app_node
| Case of case_info * 'a * 'a array * Cst_stack.t
- | Proj of int * int * Projection.t * Cst_stack.t
+ | Proj of Projection.t * Cst_stack.t
| Fix of ('a, 'a) pfixpoint * 'a t * Cst_stack.t
| Cst of cst_member * int * int list * 'a t * Cst_stack.t
and 'a t = 'a member list
@@ -351,9 +349,8 @@ struct
str "ZCase(" ++
prvect_with_sep (pr_bar) pr_c br
++ str ")"
- | Proj (n,m,p,cst) ->
- str "ZProj(" ++ int n ++ pr_comma () ++ int m ++
- pr_comma () ++ Constant.print (Projection.constant p) ++ str ")"
+ | Proj (p,cst) ->
+ str "ZProj(" ++ Constant.print (Projection.constant p) ++ str ")"
| Fix (f,args,cst) ->
str "ZFix(" ++ Termops.pr_fix pr_c f
++ pr_comma () ++ pr pr_c args ++ str ")"
@@ -413,10 +410,9 @@ struct
(f t1 t2) && (equal_rec s1' s2')
| Case (_,t1,a1,_) :: s1, Case (_,t2,a2,_) :: s2 ->
f t1 t2 && CArray.equal (fun x y -> f x y) a1 a2 && equal_rec s1 s2
- | (Proj (n1,m1,p,_)::s1, Proj(n2,m2,p2,_)::s2) ->
- Int.equal n1 n2 && Int.equal m1 m2
- && Constant.equal (Projection.constant p) (Projection.constant p2)
- && equal_rec s1 s2
+ | (Proj (p,_)::s1, Proj(p2,_)::s2) ->
+ Projection.Repr.equal (Projection.repr p) (Projection.repr p2)
+ && equal_rec s1 s2
| Fix (f1,s1,_) :: s1', Fix (f2,s2,_) :: s2' ->
f_fix f1 f2
&& equal_rec (List.rev s1) (List.rev s2)
@@ -436,7 +432,7 @@ struct
| (_, App (i,_,j)::s2) -> compare_rec (bal - j - 1 + i) stk1 s2
| (Case(c1,_,_,_)::s1, Case(c2,_,_,_)::s2) ->
Int.equal bal 0 (* && c1.ci_ind = c2.ci_ind *) && compare_rec 0 s1 s2
- | (Proj (n1,m1,p,_)::s1, Proj(n2,m2,p2,_)::s2) ->
+ | (Proj (p,_)::s1, Proj(p2,_)::s2) ->
Int.equal bal 0 && compare_rec 0 s1 s2
| (Fix(_,a1,_)::s1, Fix(_,a2,_)::s2) ->
Int.equal bal 0 && compare_rec 0 a1 a2 && compare_rec 0 s1 s2
@@ -456,7 +452,7 @@ struct
aux (f o t1 t2) l1 l2
| Case (_,t1,a1,_) :: q1, Case (_,t2,a2,_) :: q2 ->
aux (Array.fold_left2 f (f o t1 t2) a1 a2) q1 q2
- | Proj (n1,m1,p1,_) :: q1, Proj (n2,m2,p2,_) :: q2 ->
+ | Proj (p1,_) :: q1, Proj (p2,_) :: q2 ->
aux o q1 q2
| Fix ((_,(_,a1,b1)),s1,_) :: q1, Fix ((_,(_,a2,b2)),s2,_) :: q2 ->
let o' = aux (Array.fold_left2 f (Array.fold_left2 f o b1 b2) a1 a2) (List.rev s1) (List.rev s2) in
@@ -469,7 +465,7 @@ struct
in aux o (List.rev sk1) (List.rev sk2)
let rec map f x = List.map (function
- | (Proj (_,_,_,_)) as e -> e
+ | (Proj (_,_)) as e -> e
| App (i,a,j) ->
let le = j - i + 1 in
App (0,Array.map f (Array.sub a i le), le-1)
@@ -513,7 +509,7 @@ struct
let will_expose_iota args =
List.exists
(function (Fix (_,_,l) | Case (_,_,_,l) |
- Proj (_,_,_,l) | Cst (_,_,_,_,l)) when Cst_stack.is_empty l -> true | _ -> false)
+ Proj (_,l) | Cst (_,_,_,_,l)) when Cst_stack.is_empty l -> true | _ -> false)
args
let list_of_app_stack s =
@@ -590,9 +586,9 @@ struct
zip (best_state sigma (constr_of_cst_member cst (params @ (append_app [|f|] s))) cst_l)
| f, (Cst (cst,_,_,params,_)::s) ->
zip (constr_of_cst_member cst (params @ (append_app [|f|] s)))
- | f, (Proj (n,m,p,cst_l)::s) when refold ->
+ | f, (Proj (p,cst_l)::s) when refold ->
zip (best_state sigma (mkProj (p,f),s) cst_l)
- | f, (Proj (n,m,p,_)::s) -> zip (mkProj (p,f),s)
+ | f, (Proj (p,_)::s) -> zip (mkProj (p,f),s)
in
zip s
@@ -874,7 +870,7 @@ let rec whd_state_gen ?csts ~refold ~tactic_mode flags env sigma =
| Some body -> whrec cst_l (body, stack)
| None -> fold ())
| Const (c,u as const) ->
- reduction_effect_hook env sigma (EConstr.to_constr sigma x)
+ reduction_effect_hook env sigma c
(lazy (EConstr.to_constr sigma (Stack.zip sigma (x,stack))));
if CClosure.RedFlags.red_set flags (CClosure.RedFlags.fCONST c) then
let u' = EInstance.kind sigma u in
@@ -920,16 +916,13 @@ let rec whd_state_gen ?csts ~refold ~tactic_mode flags env sigma =
(arg,Stack.Cst(Stack.Cst_const (fst const, u'),curr,remains,bef,cst_l)::s')
) else fold ()
| Proj (p, c) when CClosure.RedFlags.red_projection flags p ->
- (let pb = lookup_projection p env in
- let kn = Projection.constant p in
- let npars = pb.Declarations.proj_npars
- and arg = pb.Declarations.proj_arg in
- if not tactic_mode then
- let stack' = (c, Stack.Proj (npars, arg, p, Cst_stack.empty (*cst_l*)) :: stack) in
+ (let npars = Projection.npars p in
+ if not tactic_mode then
+ let stack' = (c, Stack.Proj (p, Cst_stack.empty (*cst_l*)) :: stack) in
whrec Cst_stack.empty stack'
- else match ReductionBehaviour.get (Globnames.ConstRef kn) with
+ else match ReductionBehaviour.get (Globnames.ConstRef (Projection.constant p)) with
| None ->
- let stack' = (c, Stack.Proj (npars, arg, p, cst_l) :: stack) in
+ let stack' = (c, Stack.Proj (p, cst_l) :: stack) in
let stack'', csts = whrec Cst_stack.empty stack' in
if equal_stacks sigma stack' stack'' then fold ()
else stack'', csts
@@ -946,7 +939,7 @@ let rec whd_state_gen ?csts ~refold ~tactic_mode flags env sigma =
|[] -> (* if nargs has been specified *)
(* CAUTION : the constant is NEVER refold
(even when it hides a (co)fix) *)
- let stack' = (c, Stack.Proj (npars, arg, p, cst_l) :: stack) in
+ let stack' = (c, Stack.Proj (p, cst_l) :: stack) in
whrec Cst_stack.empty(* cst_l *) stack'
| curr::remains ->
if curr == 0 then (* Try to reduce the record argument *)
@@ -1005,8 +998,8 @@ let rec whd_state_gen ?csts ~refold ~tactic_mode flags env sigma =
match Stack.strip_app stack with
|args, (Stack.Case(ci, _, lf,_)::s') when use_match ->
whrec Cst_stack.empty (lf.(c-1), (Stack.tail ci.ci_npar args) @ s')
- |args, (Stack.Proj (n,m,p,_)::s') when use_match ->
- whrec Cst_stack.empty (Stack.nth args (n+m), s')
+ |args, (Stack.Proj (p,_)::s') when use_match ->
+ whrec Cst_stack.empty (Stack.nth args (Projection.npars p + Projection.arg p), s')
|args, (Stack.Fix (f,s',cst_l)::s'') when use_fix ->
let x' = Stack.zip sigma (x, args) in
let out_sk = s' @ (Stack.append_app [|x'|] s'') in
@@ -1025,14 +1018,11 @@ let rec whd_state_gen ?csts ~refold ~tactic_mode flags env sigma =
whrec (if refold then Cst_stack.add_cst (mkConstU const) cst_l else cst_l)
(body, s' @ (Stack.append_app [|x'|] s'')))
| Stack.Cst_proj p ->
- let pb = lookup_projection p env in
- let npars = pb.Declarations.proj_npars in
- let narg = pb.Declarations.proj_arg in
- let stack = s' @ (Stack.append_app [|x'|] s'') in
+ let stack = s' @ (Stack.append_app [|x'|] s'') in
match Stack.strip_n_app 0 stack with
| None -> assert false
| Some (_,arg,s'') ->
- whrec Cst_stack.empty (arg, Stack.Proj (npars,narg,p,cst_l) :: s''))
+ whrec Cst_stack.empty (arg, Stack.Proj (p,cst_l) :: s''))
| next :: remains' -> match Stack.strip_n_app (next-curr-1) s'' with
| None -> fold ()
| Some (bef,arg,s''') ->
@@ -1090,10 +1080,7 @@ let local_whd_state_gen flags sigma =
| _ -> s)
| Proj (p,c) when CClosure.RedFlags.red_projection flags p ->
- (let pb = lookup_projection p (Global.env ()) in
- whrec (c, Stack.Proj (pb.Declarations.proj_npars, pb.Declarations.proj_arg,
- p, Cst_stack.empty)
- :: stack))
+ (whrec (c, Stack.Proj (p, Cst_stack.empty) :: stack))
| Case (ci,p,d,lf) ->
whrec (d, Stack.Case (ci,p,lf,Cst_stack.empty) :: stack)
@@ -1116,8 +1103,8 @@ let local_whd_state_gen flags sigma =
match Stack.strip_app stack with
|args, (Stack.Case(ci, _, lf,_)::s') when use_match ->
whrec (lf.(c-1), (Stack.tail ci.ci_npar args) @ s')
- |args, (Stack.Proj (n,m,p,_) :: s') when use_match ->
- whrec (Stack.nth args (n+m), s')
+ |args, (Stack.Proj (p,_) :: s') when use_match ->
+ whrec (Stack.nth args (Projection.npars p + Projection.arg p), s')
|args, (Stack.Fix (f,s',cst)::s'') when use_fix ->
let x' = Stack.zip sigma (x,args) in
whrec (contract_fix sigma f, s' @ (Stack.append_app [|x'|] s''))
@@ -1576,11 +1563,11 @@ let whd_betaiota_deltazeta_for_iota_state ts env sigma csts s =
let (t_o,stack_o),csts_o = whd_state_gen ~csts:csts' ~refold ~tactic_mode
(CClosure.RedFlags.red_add_transparent CClosure.all ts) env sigma (t,args) in
if isConstruct sigma t_o then whrec csts_o (t_o, stack_o@stack') else s,csts'
- |args, (Stack.Proj (n,m,p,_) :: stack'') ->
+ |args, (Stack.Proj (p,_) :: stack'') ->
let (t_o,stack_o),csts_o = whd_state_gen ~csts:csts' ~refold ~tactic_mode
(CClosure.RedFlags.red_add_transparent CClosure.all ts) env sigma (t,args) in
if isConstruct sigma t_o then
- whrec Cst_stack.empty (Stack.nth stack_o (n+m), stack'')
+ whrec Cst_stack.empty (Stack.nth stack_o (Projection.npars p + Projection.arg p), stack'')
else s,csts'
|_, ((Stack.App _|Stack.Cst _) :: _|[]) -> s,csts'
in whrec csts s
diff --git a/pretyping/reductionops.mli b/pretyping/reductionops.mli
index 9256fa7ce6..07eeec9276 100644
--- a/pretyping/reductionops.mli
+++ b/pretyping/reductionops.mli
@@ -41,10 +41,10 @@ val declare_reduction_effect : effect_name ->
(Environ.env -> Evd.evar_map -> Constr.constr -> unit) -> unit
(* [set_reduction_effect cst name] declares effect [name] to be called when [cst] is found *)
-val set_reduction_effect : GlobRef.t -> effect_name -> unit
+val set_reduction_effect : Constant.t -> effect_name -> unit
(* [effect_hook env sigma key term] apply effect associated to [key] on [term] *)
-val reduction_effect_hook : Environ.env -> Evd.evar_map -> Constr.constr ->
+val reduction_effect_hook : Environ.env -> Evd.evar_map -> Constant.t ->
Constr.constr Lazy.t -> unit
(** {6 Machinery about a stack of unfolded constant }
@@ -75,7 +75,7 @@ module Stack : sig
type 'a member =
| App of 'a app_node
| Case of case_info * 'a * 'a array * Cst_stack.t
- | Proj of int * int * Projection.t * Cst_stack.t
+ | Proj of Projection.t * Cst_stack.t
| Fix of ('a, 'a) pfixpoint * 'a t * Cst_stack.t
| Cst of cst_member * int (** current foccussed arg *) * int list (** remaining args *)
* 'a t * Cst_stack.t
diff --git a/pretyping/retyping.ml b/pretyping/retyping.ml
index 746a68b217..7e43c5e41d 100644
--- a/pretyping/retyping.ml
+++ b/pretyping/retyping.ml
@@ -149,18 +149,13 @@ let retype ?(polyprop=true) sigma =
| Cast (c,_, s) when isSort sigma s -> destSort sigma s
| Sort s ->
begin match ESorts.kind sigma s with
- | Prop _ -> Sorts.type1
+ | Prop | Set -> Sorts.type1
| Type u -> Type (Univ.super u)
end
| Prod (name,t,c2) ->
- (match (sort_of env t, sort_of (push_rel (LocalAssum (name,t)) env) c2) with
- | _, (Prop Null as s) -> s
- | Prop _, (Prop Pos as s) -> s
- | Type _, (Prop Pos as s) when is_impredicative_set env -> s
- | Type u1, Prop Pos -> Type (Univ.sup u1 Univ.type0_univ)
- | Prop Pos, (Type u2) -> Type (Univ.sup Univ.type0_univ u2)
- | Prop Null, (Type _ as s) -> s
- | Type u1, Type u2 -> Type (Univ.sup u1 u2))
+ let dom = sort_of env t in
+ let rang = sort_of (push_rel (LocalAssum (name,t)) env) c2 in
+ Typeops.sort_of_product env dom rang
| App(f,args) when is_template_polymorphic env sigma f ->
let t = type_of_global_reference_knowing_parameters env f args in
sort_of_atomic_type env sigma t args
diff --git a/pretyping/tacred.ml b/pretyping/tacred.ml
index 40c4cfaa45..8911a2f343 100644
--- a/pretyping/tacred.ml
+++ b/pretyping/tacred.ml
@@ -49,7 +49,7 @@ let error_not_evaluable r =
let is_evaluable_const env cst =
is_transparent env (ConstKey cst) &&
- (evaluable_constant cst env || is_projection cst env)
+ evaluable_constant cst env
let is_evaluable_var env id =
is_transparent env (VarKey id) && evaluable_named id env
@@ -539,7 +539,7 @@ let reduce_mind_case_use_function func env sigma mia =
let match_eval_ref env sigma constr stack =
match EConstr.kind sigma constr with
| Const (sp, u) ->
- reduction_effect_hook env sigma (EConstr.to_constr sigma constr)
+ reduction_effect_hook env sigma sp
(lazy (EConstr.to_constr sigma (applist (constr,stack))));
if is_evaluable env (EvalConstRef sp) then Some (EvalConst sp, u) else None
| Var id when is_evaluable env (EvalVarRef id) -> Some (EvalVar id, EInstance.empty)
@@ -550,7 +550,7 @@ let match_eval_ref env sigma constr stack =
let match_eval_ref_value env sigma constr stack =
match EConstr.kind sigma constr with
| Const (sp, u) ->
- reduction_effect_hook env sigma (EConstr.to_constr sigma constr)
+ reduction_effect_hook env sigma sp
(lazy (EConstr.to_constr sigma (applist (constr,stack))));
if is_evaluable env (EvalConstRef sp) then
let u = EInstance.kind sigma u in
@@ -558,8 +558,6 @@ let match_eval_ref_value env sigma constr stack =
else
None
| Proj (p, c) when not (Projection.unfolded p) ->
- reduction_effect_hook env sigma (EConstr.to_constr ~abort_on_undefined_evars:false sigma constr)
- (lazy (EConstr.to_constr sigma (applist (constr,stack))));
if is_evaluable env (EvalConstRef (Projection.constant p)) then
Some (mkProj (Projection.unfold p, c))
else None
@@ -597,12 +595,11 @@ let recargs = function
| EvalVar _ | EvalRel _ | EvalEvar _ -> None
| EvalConst c -> ReductionBehaviour.get (ConstRef c)
-let reduce_projection env sigma pb (recarg'hd,stack') stack =
+let reduce_projection env sigma p ~npars (recarg'hd,stack') stack =
(match EConstr.kind sigma recarg'hd with
| Construct _ ->
- let proj_narg =
- pb.Declarations.proj_npars + pb.Declarations.proj_arg
- in Reduced (List.nth stack' proj_narg, stack)
+ let proj_narg = npars + Projection.arg p in
+ Reduced (List.nth stack' proj_narg, stack)
| _ -> NotReducible)
let reduce_proj env sigma whfun whfun' c =
@@ -613,10 +610,8 @@ let reduce_proj env sigma whfun whfun' c =
let constr, cargs = whfun c' in
(match EConstr.kind sigma constr with
| Construct _ ->
- let proj_narg =
- let pb = lookup_projection proj env in
- pb.Declarations.proj_npars + pb.Declarations.proj_arg
- in List.nth cargs proj_narg
+ let proj_narg = Projection.npars proj + Projection.arg proj in
+ List.nth cargs proj_narg
| _ -> raise Redelimination)
| Case (n,p,c,brs) ->
let c' = redrec c in
@@ -765,22 +760,22 @@ and whd_simpl_stack env sigma =
(try
let unf = Projection.unfolded p in
if unf || is_evaluable env (EvalConstRef (Projection.constant p)) then
- let pb = lookup_projection p env in
+ let npars = Projection.npars p in
(match unf, ReductionBehaviour.get (ConstRef (Projection.constant p)) with
| false, Some (l, n, f) when List.mem `ReductionNeverUnfold f ->
(* simpl never *) s'
| false, Some (l, n, f) when not (List.is_empty l) ->
let l' = List.map_filter (fun i ->
- let idx = (i - (pb.Declarations.proj_npars + 1)) in
+ let idx = (i - (npars + 1)) in
if idx < 0 then None else Some idx) l in
let stack = reduce_params env sigma stack l' in
- (match reduce_projection env sigma pb
+ (match reduce_projection env sigma p ~npars
(whd_construct_stack env sigma c) stack
with
| Reduced s' -> redrec (applist s')
| NotReducible -> s')
| _ ->
- match reduce_projection env sigma pb (whd_construct_stack env sigma c) stack with
+ match reduce_projection env sigma p ~npars (whd_construct_stack env sigma c) stack with
| Reduced s' -> redrec (applist s')
| NotReducible -> s')
else s'
@@ -852,8 +847,8 @@ let try_red_product env sigma c =
| Construct _ -> c
| _ -> redrec env c
in
- let pb = lookup_projection p env in
- (match reduce_projection env sigma pb (whd_betaiotazeta_stack sigma c') [] with
+ let npars = Projection.npars p in
+ (match reduce_projection env sigma p ~npars (whd_betaiotazeta_stack sigma c') [] with
| Reduced s -> simpfun (applist s)
| NotReducible -> raise Redelimination)
| _ ->
@@ -946,8 +941,8 @@ let whd_simpl_orelse_delta_but_fix env sigma c =
(match EConstr.kind sigma constr with
| Const (c', _) -> Constant.equal (Projection.constant p) c'
| _ -> false) ->
- let pb = Environ.lookup_projection p env in
- if List.length stack <= pb.Declarations.proj_npars then
+ let npars = Projection.npars p in
+ if List.length stack <= npars then
(** Do not show the eta-expanded form *)
s'
else redrec (applist (c, stack))
diff --git a/pretyping/typeclasses.ml b/pretyping/typeclasses.ml
index d3aa7ac643..efb3c339ac 100644
--- a/pretyping/typeclasses.ml
+++ b/pretyping/typeclasses.ml
@@ -74,10 +74,10 @@ type typeclass = {
cl_impl : GlobRef.t;
(* Context in which the definitions are typed. Includes both typeclass parameters and superclasses. *)
- cl_context : GlobRef.t option list * Context.Rel.t;
+ cl_context : GlobRef.t option list * Constr.rel_context;
(* Context of definitions and properties on defs, will not be shared *)
- cl_props : Context.Rel.t;
+ cl_props : Constr.rel_context;
(* The method implementaions as projections. *)
cl_projs : (Name.t * (direction * hint_info) option
diff --git a/pretyping/typeclasses.mli b/pretyping/typeclasses.mli
index e4a56960cf..80c6d82397 100644
--- a/pretyping/typeclasses.mli
+++ b/pretyping/typeclasses.mli
@@ -35,10 +35,10 @@ type typeclass = {
(** Context in which the definitions are typed. Includes both typeclass parameters and superclasses.
The global reference gives a direct link to the class itself. *)
- cl_context : GlobRef.t option list * Context.Rel.t;
+ cl_context : GlobRef.t option list * Constr.rel_context;
(** Context of definitions and properties on defs, will not be shared *)
- cl_props : Context.Rel.t;
+ cl_props : Constr.rel_context;
(** The methods implementations of the typeclass as projections.
Some may be undefinable due to sorting restrictions or simply undefined if
diff --git a/pretyping/typing.ml b/pretyping/typing.ml
index cf34ac0164..4ba715f0d5 100644
--- a/pretyping/typing.ml
+++ b/pretyping/typing.ml
@@ -138,7 +138,7 @@ let is_correct_arity env sigma c pj ind specif params =
then error ()
else sigma
| Evar (ev,_), [] ->
- let sigma, s = Evd.fresh_sort_in_family env sigma (max_sort allowed_sorts) in
+ let sigma, s = Evd.fresh_sort_in_family sigma (max_sort allowed_sorts) in
let sigma = Evd.define ev (mkSort s) sigma in
sigma
| _, (LocalDef _ as d)::ar' ->
@@ -241,10 +241,6 @@ let judge_of_set =
{ uj_val = EConstr.mkSet;
uj_type = EConstr.mkSort Sorts.type1 }
-let judge_of_prop_contents = function
- | Null -> judge_of_prop
- | Pos -> judge_of_set
-
let judge_of_type u =
let uu = Univ.Universe.super u in
{ uj_val = EConstr.mkType u;
@@ -257,16 +253,16 @@ let judge_of_variable env id =
Termops.on_judgment EConstr.of_constr (judge_of_variable env id)
let judge_of_projection env sigma p cj =
- let pb = lookup_projection p env in
+ let pty = lookup_projection p env in
let (ind,u), args =
try find_mrectype env sigma cj.uj_type
with Not_found -> error_case_not_inductive env sigma cj
in
let u = EInstance.kind sigma u in
- let ty = EConstr.of_constr (CVars.subst_instance_constr u pb.Declarations.proj_type) in
- let ty = substl (cj.uj_val :: List.rev args) ty in
- {uj_val = EConstr.mkProj (p,cj.uj_val);
- uj_type = ty}
+ let ty = EConstr.of_constr (CVars.subst_instance_constr u pty) in
+ let ty = substl (cj.uj_val :: List.rev args) ty in
+ {uj_val = EConstr.mkProj (p,cj.uj_val);
+ uj_type = ty}
let judge_of_abstraction env name var j =
{ uj_val = mkLambda (name, var.utj_val, j.uj_val);
@@ -333,10 +329,9 @@ let rec execute env sigma cstr =
| Sort s ->
begin match ESorts.kind sigma s with
- | Prop c ->
- sigma, judge_of_prop_contents c
- | Type u ->
- sigma, judge_of_type u
+ | Prop -> sigma, judge_of_prop
+ | Set -> sigma, judge_of_set
+ | Type u -> sigma, judge_of_type u
end
| Proj (p, c) ->
diff --git a/pretyping/unification.ml b/pretyping/unification.ml
index 4ba5d27947..fc1f6fc81e 100644
--- a/pretyping/unification.ml
+++ b/pretyping/unification.ml
@@ -478,12 +478,8 @@ let expand_table_key env = function
| RelKey _ -> None
let unfold_projection env p stk =
- (match try Some (lookup_projection p env) with Not_found -> None with
- | Some pb ->
- let s = Stack.Proj (pb.Declarations.proj_npars, pb.Declarations.proj_arg,
- p, Cst_stack.empty) in
- s :: stk
- | None -> assert false)
+ let s = Stack.Proj (p, Cst_stack.empty) in
+ s :: stk
let expand_key ts env sigma = function
| Some (IsKey k) -> Option.map EConstr.of_constr (expand_table_key env k)
@@ -512,7 +508,7 @@ let key_of env sigma b flags f =
match EConstr.kind sigma f with
| Const (cst, u) when is_transparent env (ConstKey cst) &&
(Cpred.mem cst (snd flags.modulo_delta)
- || Environ.is_projection cst env) ->
+ || Recordops.is_primitive_projection cst) ->
let u = EInstance.kind sigma u in
Some (IsKey (ConstKey (cst, u)))
| Var id when is_transparent env (VarKey id) &&
@@ -669,17 +665,15 @@ let is_eta_constructor_app env sigma ts f l1 term =
| _ -> false
let eta_constructor_app env sigma f l1 term =
- let open Declarations in
match EConstr.kind sigma f with
| Construct (((_, i as ind), j), u) ->
let mib = lookup_mind (fst ind) env in
- (match mib.Declarations.mind_record with
- | PrimRecord info ->
- let (_, projs, _) = info.(i) in
+ (match get_projections env ind with
+ | Some projs ->
let npars = mib.Declarations.mind_nparams in
let pars, l1' = Array.chop npars l1 in
let arg = Array.append pars [|term|] in
- let l2 = Array.map (fun p -> mkApp (mkConstU (p,u), arg)) projs in
+ let l2 = Array.map (fun p -> mkApp (mkConstU (Projection.Repr.constant p,u), arg)) projs in
l1', l2
| _ -> assert false)
| _ -> assert false
diff --git a/pretyping/vnorm.ml b/pretyping/vnorm.ml
index 14c9f49b12..255707dc7b 100644
--- a/pretyping/vnorm.ml
+++ b/pretyping/vnorm.ml
@@ -79,7 +79,7 @@ let construct_of_constr const env tag typ =
(* spiwack : here be a branch for specific decompilation handled by retroknowledge *)
try
if const then
- ((retroknowledge Retroknowledge.get_vm_decompile_constant_info env (mkIndU indu) tag),
+ ((Retroknowledge.get_vm_decompile_constant_info env.retroknowledge (mkIndU indu) tag),
typ) (*spiwack: this may need to be changed in case there are parameters in the
type which may cause a constant value to have an arity.
(type_constructor seems to be all about parameters actually)
@@ -103,7 +103,7 @@ let construct_of_constr_block = construct_of_constr false
let type_of_ind env (ind, u) =
type_of_inductive env (Inductive.lookup_mind_specif env ind, u)
-let build_branches_type env sigma (mind,_ as _ind) mib mip u params dep p =
+let build_branches_type env sigma (mind,_ as _ind) mib mip u params p =
let rtbl = mip.mind_reloc_tbl in
(* [build_one_branch i cty] construit le type de la ieme branche (commence
a 0) et les lambda correspondant aux realargs *)
@@ -120,20 +120,17 @@ let build_branches_type env sigma (mind,_ as _ind) mib mip u params dep p =
let codom =
let ndecl = List.length decl in
let papp = mkApp(lift ndecl p,crealargs) in
- if dep then
- let cstr = ith_constructor_of_inductive ind (i+1) in
- let relargs = Array.init carity (fun i -> mkRel (carity-i)) in
- let params = Array.map (lift ndecl) params in
- let dep_cstr = mkApp(mkApp(mkConstructU (cstr,u),params),relargs) in
- mkApp(papp,[|dep_cstr|])
- else papp
+ let cstr = ith_constructor_of_inductive ind (i+1) in
+ let relargs = Array.init carity (fun i -> mkRel (carity-i)) in
+ let params = Array.map (lift ndecl) params in
+ let dep_cstr = mkApp(mkApp(mkConstructU (cstr,u),params),relargs) in
+ mkApp(papp,[|dep_cstr|])
in
decl, decl_with_letin, codom
in Array.mapi build_one_branch mip.mind_nf_lc
-let build_case_type dep p realargs c =
- if dep then mkApp(mkApp(p, realargs), [|c|])
- else mkApp(p, realargs)
+let build_case_type p realargs c =
+ mkApp(mkApp(p, realargs), [|c|])
(* La fonction de normalisation *)
@@ -212,6 +209,9 @@ and nf_evar env sigma evk stk =
| Zapp args :: stk ->
(** We assume that there is no consecutive Zapp nodes in a VM stack. Is that
really an invariant? *)
+ (** Let-bound arguments are present in the evar arguments but not in the
+ type, so we turn the let into a product. *)
+ let hyps = Context.Named.drop_bodies hyps in
let fold accu d = Term.mkNamedProd_or_LetIn d accu in
let t = List.fold_left fold concl hyps in
let t, args = nf_args env sigma args t in
@@ -266,9 +266,9 @@ and nf_stk ?from:(from=0) env sigma c t stk =
let nparamdecls = Context.Rel.length (Inductive.inductive_paramdecls (mib,u)) in
let pT =
hnf_prod_applist_assum env nparamdecls (type_of_ind env (ind,u)) (Array.to_list params) in
- let dep, p = nf_predicate env sigma (ind,u) mip params (type_of_switch sw) pT in
+ let p = nf_predicate env sigma (ind,u) mip params (type_of_switch sw) pT in
(* Calcul du type des branches *)
- let btypes = build_branches_type env sigma ind mib mip u params dep p in
+ let btypes = build_branches_type env sigma ind mib mip u params p in
(* calcul des branches *)
let bsw = branch_of_switch (nb_rel env) sw in
let mkbranch i (n,v) =
@@ -277,7 +277,7 @@ and nf_stk ?from:(from=0) env sigma c t stk =
Termops.it_mkLambda_or_LetIn_from_no_LetIn b decl_with_letin
in
let branchs = Array.mapi mkbranch bsw in
- let tcase = build_case_type dep p realargs c in
+ let tcase = build_case_type p realargs c in
let ci = sw.sw_annot.Cbytecodes.ci in
nf_stk env sigma (mkCase(ci, p, c, branchs)) tcase stk
| Zproj p :: stk ->
@@ -289,17 +289,17 @@ and nf_stk ?from:(from=0) env sigma c t stk =
and nf_predicate env sigma ind mip params v pT =
match kind (whd_allnolet env pT) with
| LetIn (name,b,t,pT) ->
- let dep,body =
+ let body =
nf_predicate (push_rel (LocalDef (name,b,t)) env) sigma ind mip params v pT in
- dep, mkLetIn (name,b,t,body)
+ mkLetIn (name,b,t,body)
| Prod (name,dom,codom) -> begin
match whd_val v with
| Vfun f ->
let k = nb_rel env in
let vb = reduce_fun k f in
- let dep,body =
+ let body =
nf_predicate (push_rel (LocalAssum (name,dom)) env) sigma ind mip params vb codom in
- dep, mkLambda(name,dom,body)
+ mkLambda(name,dom,body)
| _ -> assert false
end
| _ ->
@@ -313,8 +313,8 @@ and nf_predicate env sigma ind mip params v pT =
let params = if Int.equal n 0 then params else Array.map (lift n) params in
let dom = mkApp(mkIndU ind,Array.append params rargs) in
let body = nf_vtype (push_rel (LocalAssum (name,dom)) env) sigma vb in
- true, mkLambda(name,dom,body)
- | _ -> false, nf_val env sigma v crazy_type
+ mkLambda(name,dom,body)
+ | _ -> assert false
and nf_args env sigma vargs ?from:(f=0) t =
let t = ref t in
diff --git a/printing/ppconstr.ml b/printing/ppconstr.ml
index e38da45b95..418e13759b 100644
--- a/printing/ppconstr.ml
+++ b/printing/ppconstr.ml
@@ -295,7 +295,7 @@ let tag_var = tag Tag.variable
| CPatOr pl ->
hov 0 (prlist_with_sep pr_spcbar (pr_patt mt (lpator,L)) pl), lpator
- | CPatNotation ("( _ )",([p],[]),[]) ->
+ | CPatNotation ((_,"( _ )"),([p],[]),[]) ->
pr_patt (fun()->str"(") (max_int,E) p ++ str")", latom
| CPatNotation (s,(l,ll),args) ->
@@ -665,7 +665,7 @@ let tag_var = tag Tag.variable
| CastCoerce -> str ":>"),
lcast
)
- | CNotation ("( _ )",([t],[],[],[])) ->
+ | CNotation ((_,"( _ )"),([t],[],[],[])) ->
return (pr (fun()->str"(") (max_int,L) t ++ str")", latom)
| CNotation (s,env) ->
pr_notation (pr mt) pr_patt (pr_binders_gen (pr mt ltop)) s env
diff --git a/printing/pputils.ml b/printing/pputils.ml
index c6b8d50222..59e5f68f22 100644
--- a/printing/pputils.ml
+++ b/printing/pputils.ml
@@ -68,7 +68,7 @@ let pr_short_red_flag pr r =
let pr_red_flag pr r =
try pr_short_red_flag pr r
- with complexRedFlags ->
+ with ComplexRedFlag ->
(if r.rBeta then pr_arg str "beta" else mt ()) ++
(if r.rMatch && r.rFix && r.rCofix then pr_arg str "iota" else
(if r.rMatch then pr_arg str "match" else mt ()) ++
diff --git a/printing/prettyp.ml b/printing/prettyp.ml
index f926e82751..1810cc6588 100644
--- a/printing/prettyp.ml
+++ b/printing/prettyp.ml
@@ -40,7 +40,7 @@ type object_pr = {
print_syntactic_def : env -> KerName.t -> Pp.t;
print_module : bool -> ModPath.t -> Pp.t;
print_modtype : ModPath.t -> Pp.t;
- print_named_decl : env -> Evd.evar_map -> Context.Named.Declaration.t -> Pp.t;
+ print_named_decl : env -> Evd.evar_map -> Constr.named_declaration -> Pp.t;
print_library_entry : env -> Evd.evar_map -> bool -> (object_name * Lib.node) -> Pp.t option;
print_context : env -> Evd.evar_map -> bool -> int option -> Lib.library_segment -> Pp.t;
print_typed_value_in_env : Environ.env -> Evd.evar_map -> EConstr.constr * EConstr.types -> Pp.t;
@@ -98,7 +98,8 @@ let print_ref reduce ref udecl =
(Array.to_list (Univ.Instance.to_array inst)) udecl in
let sigma = Evd.from_ctx (UState.of_binders bl) in
let inst =
- if Global.is_polymorphic ref then Printer.pr_universe_instance sigma univs
+ if Global.is_polymorphic ref
+ then Printer.pr_universe_instance sigma (Univ.UContext.instance univs)
else mt ()
in
hov 0 (pr_global ref ++ inst ++ str " :" ++ spc () ++ pr_letype_env env sigma typ ++
@@ -552,8 +553,7 @@ let print_instance sigma cb =
if Declareops.constant_is_polymorphic cb then
let univs = Declareops.constant_polymorphic_context cb in
let inst = Univ.AUContext.instance univs in
- let univs = Univ.UContext.make (inst, Univ.AUContext.instantiate inst univs) in
- pr_universe_instance sigma univs
+ pr_universe_instance sigma inst
else mt()
let print_constant with_values sep sp udecl =
@@ -657,14 +657,10 @@ let gallina_print_library_entry env sigma with_values ent =
gallina_print_leaf_entry env sigma with_values (oname,lobj)
| (oname,Lib.OpenedSection (dir,_)) ->
Some (str " >>>>>>> Section " ++ pr_name oname)
- | (oname,Lib.ClosedSection _) ->
- Some (str " >>>>>>> Closed Section " ++ pr_name oname)
| (_,Lib.CompilingLibrary { obj_dir; _ }) ->
Some (str " >>>>>>> Library " ++ DirPath.print obj_dir)
| (oname,Lib.OpenedModule _) ->
Some (str " >>>>>>> Module " ++ pr_name oname)
- | (oname,Lib.ClosedModule _) ->
- Some (str " >>>>>>> Closed Module " ++ pr_name oname)
let gallina_print_context env sigma with_values =
let rec prec n = function
@@ -793,9 +789,6 @@ let read_sec_context qid =
let rec get_cxt in_cxt = function
| (_,Lib.OpenedSection ({obj_dir;_},_) as hd)::rest ->
if DirPath.equal dir obj_dir then (hd::in_cxt) else get_cxt (hd::in_cxt) rest
- | (_,Lib.ClosedSection _)::rest ->
- user_err Pp.(str "Cannot print the contents of a closed section.")
- (* LEM: Actually, we could if we wanted to. *)
| [] -> []
| hd::rest -> get_cxt (hd::in_cxt) rest
in
@@ -909,7 +902,7 @@ let inspect env sigma depth =
open Classops
-let print_coercion_value env sigma v = pr_lconstr_env env sigma (get_coercion_value v)
+let print_coercion_value env sigma v = Printer.pr_global v.coe_value
let print_class i =
let cl,_ = class_info_from_index i in
diff --git a/printing/prettyp.mli b/printing/prettyp.mli
index 8dd7296100..1668bce297 100644
--- a/printing/prettyp.mli
+++ b/printing/prettyp.mli
@@ -89,7 +89,7 @@ type object_pr = {
print_syntactic_def : env -> KerName.t -> Pp.t;
print_module : bool -> ModPath.t -> Pp.t;
print_modtype : ModPath.t -> Pp.t;
- print_named_decl : env -> Evd.evar_map -> Context.Named.Declaration.t -> Pp.t;
+ print_named_decl : env -> Evd.evar_map -> Constr.named_declaration -> Pp.t;
print_library_entry : env -> Evd.evar_map -> bool -> (object_name * Lib.node) -> Pp.t option;
print_context : env -> Evd.evar_map -> bool -> int option -> Lib.library_segment -> Pp.t;
print_typed_value_in_env : Environ.env -> Evd.evar_map -> EConstr.constr * EConstr.types -> Pp.t;
diff --git a/printing/printer.ml b/printing/printer.ml
index d76bd1e2b2..5b3ead181f 100644
--- a/printing/printer.ml
+++ b/printing/printer.ml
@@ -82,11 +82,10 @@ let pr_econstr_n_core goal_concl_style env sigma n t =
pr_constr_expr_n n (extern_constr goal_concl_style env sigma t)
let pr_econstr_core goal_concl_style env sigma t =
pr_constr_expr (extern_constr goal_concl_style env sigma t)
-let pr_leconstr_core goal_concl_style env sigma t =
- pr_lconstr_expr (extern_constr goal_concl_style env sigma t)
+let pr_leconstr_core = Proof_diffs.pr_leconstr_core
let pr_constr_n_env env sigma n c = pr_econstr_n_core false env sigma n (EConstr.of_constr c)
-let pr_lconstr_env env sigma c = pr_leconstr_core false env sigma (EConstr.of_constr c)
+let pr_lconstr_env = Proof_diffs.pr_lconstr_env
let pr_constr_env env sigma c = pr_econstr_core false env sigma (EConstr.of_constr c)
let _ = Hook.set Refine.pr_constr pr_constr_env
@@ -133,8 +132,7 @@ let pr_lconstr_under_binders c =
let pr_etype_core goal_concl_style env sigma t =
pr_constr_expr (extern_type goal_concl_style env sigma t)
-let pr_letype_core goal_concl_style env sigma t =
- pr_lconstr_expr (extern_type goal_concl_style env sigma t)
+let pr_letype_core = Proof_diffs.pr_letype_core
let pr_ltype_env env sigma c = pr_letype_core false env sigma (EConstr.of_constr c)
let pr_type_env env sigma c = pr_etype_core false env sigma (EConstr.of_constr c)
@@ -290,11 +288,13 @@ let pr_cumulativity_info sigma cumi =
let pr_global_env = pr_global_env
let pr_global = pr_global_env Id.Set.empty
-let pr_puniverses f env (c,u) =
- f env c ++
- (if !Constrextern.print_universes then
- str"(*" ++ Univ.Instance.pr UnivNames.pr_with_global_universes u ++ str"*)"
- else mt ())
+let pr_universe_instance evd inst =
+ str"@{" ++ Univ.Instance.pr (Termops.pr_evd_level evd) inst ++ str"}"
+
+let pr_puniverses f env sigma (c,u) =
+ if !Constrextern.print_universes
+ then f env c ++ pr_universe_instance sigma u
+ else f env c
let pr_constant env cst = pr_global_env (Termops.vars_of_env env) (ConstRef cst)
let pr_existential_key = Termops.pr_existential_key
@@ -493,16 +493,23 @@ let pr_transparent_state (ids, csts) =
hv 0 (str"VARIABLES: " ++ pr_idpred ids ++ fnl () ++
str"CONSTANTS: " ++ pr_cpred csts ++ fnl ())
-(* display complete goal *)
-let pr_goal gs =
+(* display complete goal
+ prev_gs has info on the previous proof step for diffs
+ gs has info on the current proof step
+ *)
+let pr_goal ?(diffs=false) ?prev_gs gs =
let g = sig_it gs in
let sigma = project gs in
let env = Goal.V82.env sigma g in
let concl = Goal.V82.concl sigma g in
let goal =
- pr_context_of env sigma ++ cut () ++
- str "============================" ++ cut () ++
- pr_goal_concl_style_env env sigma concl in
+ if diffs then
+ Proof_diffs.diff_goals ?prev_gs (Some gs)
+ else
+ pr_context_of env sigma ++ cut () ++
+ str "============================" ++ cut () ++
+ pr_goal_concl_style_env env sigma concl
+ in
str " " ++ v 0 goal
(* display a goal tag *)
@@ -695,7 +702,8 @@ let print_dependent_evars gl sigma seeds =
(* spiwack: [seeds] is for printing dependent evars in emacs mode. *)
(* spiwack: [pr_first] is true when the first goal must be singled out
and printed in its entirety. *)
-let pr_subgoals ?(pr_first=true)
+(* [prev] is the previous proof step, used for diffs *)
+let pr_subgoals ?(pr_first=true) ?(diffs=false) ?prev
close_cmd sigma ~seeds ~shelf ~stack ~unfocused ~goals =
(** Printing functions for the extra informations. *)
let rec print_stack a = function
@@ -729,7 +737,7 @@ let pr_subgoals ?(pr_first=true)
if needed then str" focused "
else str" " (* non-breakable space *)
in
- (** Main function *)
+
let rec pr_rec n = function
| [] -> (mt ())
| g::rest ->
@@ -739,7 +747,14 @@ let pr_subgoals ?(pr_first=true)
in
let print_multiple_goals g l =
if pr_first then
- pr_goal { it = g ; sigma = sigma; }
+ let prev_gs =
+ match prev with
+ | Some (prev_goals, prev_sigma) ->
+ if prev_goals = [] then None
+ else Some { it = List.hd prev_goals; sigma = prev_sigma}
+ | None -> None
+ in
+ pr_goal ~diffs ?prev_gs { it = g ; sigma = sigma }
++ (if l=[] then mt () else cut ())
++ pr_rec 2 l
else
@@ -751,6 +766,8 @@ let pr_subgoals ?(pr_first=true)
| Some cmd -> Feedback.msg_info cmd
| None -> ()
in
+
+ (** Main function *)
match goals with
| [] ->
begin
@@ -780,7 +797,7 @@ let pr_subgoals ?(pr_first=true)
++ print_dependent_evars (Some g1) sigma seeds
)
-let pr_open_subgoals ~proof =
+let pr_open_subgoals_diff ?(quiet=false) ?(diffs=false) ?prev_proof proof =
(* spiwack: it shouldn't be the job of the printer to look up stuff
in the [evar_map], I did stuff that way because it was more
straightforward, but seriously, [Proof.proof] should return
@@ -803,21 +820,33 @@ let pr_open_subgoals ~proof =
fnl ()
++ pr_subgoals ~pr_first:false None bsigma ~seeds ~shelf:[] ~stack:[] ~unfocused:[] ~goals:shelf
| _ , _, _ ->
- let end_cmd =
- str "This subproof is complete, but there are some unfocused goals." ++
- (let s = Proof_bullet.suggest p in
- if Pp.ismt s then s else fnl () ++ s) ++
- fnl ()
+ let cmd = if quiet then None else
+ Some
+ (str "This subproof is complete, but there are some unfocused goals." ++
+ (let s = Proof_bullet.suggest p in
+ if Pp.ismt s then s else fnl () ++ s) ++
+ fnl ())
in
- pr_subgoals ~pr_first:false (Some end_cmd) bsigma ~seeds ~shelf ~stack:[] ~unfocused:[] ~goals:bgoals
+ pr_subgoals ~pr_first:false cmd bsigma ~seeds ~shelf ~stack:[] ~unfocused:[] ~goals:bgoals
end
| _ ->
let { Evd.it = bgoals ; sigma = bsigma } = Proof.V82.background_subgoals p in
let bgoals_focused, bgoals_unfocused = List.partition (fun x -> List.mem x goals) bgoals in
let unfocused_if_needed = if should_unfoc() then bgoals_unfocused else [] in
- pr_subgoals ~pr_first:true None bsigma ~seeds ~shelf ~stack:[] ~unfocused:unfocused_if_needed ~goals:bgoals_focused
+ let prev = match prev_proof with
+ | Some op ->
+ let (ogoals , _, _, _, _) = Proof.proof op in
+ let { Evd.it = obgoals; sigma = osigma } = Proof.V82.background_subgoals op in
+ let obgoals_focused = List.filter (fun x -> List.mem x ogoals) obgoals in
+ Some (obgoals_focused, osigma)
+ | None -> None
+ in
+ pr_subgoals ~pr_first:true ~diffs ?prev None bsigma ~seeds ~shelf ~stack:[] ~unfocused:unfocused_if_needed ~goals:bgoals_focused
end
+let pr_open_subgoals ~proof =
+ pr_open_subgoals_diff proof
+
let pr_nth_open_subgoal ~proof n =
let gls,_,_,_,sigma = Proof.proof proof in
pr_subgoal n sigma gls
@@ -852,7 +881,7 @@ type axiom =
type context_object =
| Variable of Id.t (* A section variable or a Let definition *)
- | Axiom of axiom * (Label.t * Context.Rel.t * types) list
+ | Axiom of axiom * (Label.t * Constr.rel_context * types) list
| Opaque of Constant.t (* An opaque constant. *)
| Transparent of Constant.t
@@ -987,6 +1016,29 @@ let pr_polymorphic b =
if b then str"Polymorphic " else str"Monomorphic "
else mt ()
-let pr_universe_instance evd ctx =
- let inst = Univ.UContext.instance ctx in
- str"@{" ++ Univ.Instance.pr (Termops.pr_evd_level evd) inst ++ str"}"
+(* print the proof step, possibly with diffs highlighted, *)
+let print_and_diff oldp newp =
+ match newp with
+ | None -> ()
+ | Some proof ->
+ let output =
+ if Proof_diffs.show_diffs () then
+ try pr_open_subgoals_diff ~diffs:true ?prev_proof:oldp proof
+ with Pp_diff.Diff_Failure msg -> begin
+ (* todo: print the unparsable string (if we know it) *)
+ Feedback.msg_warning Pp.(str ("Diff failure:" ^ msg ^ "; showing results without diff highlighting" ));
+ pr_open_subgoals ~proof
+ end
+ else
+ pr_open_subgoals ~proof
+ in
+ Feedback.msg_notice output;;
+
+(* Do diffs on the first goal returning a Pp. *)
+let diff_pr_open_subgoals ?(quiet=false) o_proof n_proof =
+ match n_proof with
+ | None -> Pp.mt ()
+ | Some proof ->
+ try pr_open_subgoals_diff ~quiet ~diffs:true ?prev_proof:o_proof proof
+ with Pp_diff.Diff_Failure _ -> pr_open_subgoals ~proof
+ (* todo: print the unparsable string (if we know it) *)
diff --git a/printing/printer.mli b/printing/printer.mli
index 7a8b963d25..971241d5f9 100644
--- a/printing/printer.mli
+++ b/printing/printer.mli
@@ -120,7 +120,7 @@ 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_instance : evar_map -> Univ.Instance.t -> Pp.t
val pr_universe_ctx : evar_map -> ?variance:Univ.Variance.t array ->
Univ.UContext.t -> Pp.t
val pr_universe_ctx_set : evar_map -> Univ.ContextSet.t -> Pp.t
@@ -139,9 +139,9 @@ val pr_constructor : env -> constructor -> Pp.t
val pr_inductive : env -> inductive -> Pp.t
val pr_evaluable_reference : evaluable_global_reference -> Pp.t
-val pr_pconstant : env -> pconstant -> Pp.t
-val pr_pinductive : env -> pinductive -> Pp.t
-val pr_pconstructor : env -> pconstructor -> Pp.t
+val pr_pconstant : env -> evar_map -> pconstant -> Pp.t
+val pr_pinductive : env -> evar_map -> pinductive -> Pp.t
+val pr_pconstructor : env -> evar_map -> pconstructor -> Pp.t
(** Contexts *)
@@ -152,13 +152,13 @@ val get_compact_context : unit -> bool
val pr_context_unlimited : env -> evar_map -> Pp.t
val pr_ne_context_of : Pp.t -> env -> evar_map -> Pp.t
-val pr_named_decl : env -> evar_map -> Context.Named.Declaration.t -> Pp.t
-val pr_compacted_decl : env -> evar_map -> Context.Compacted.Declaration.t -> Pp.t
-val pr_rel_decl : env -> evar_map -> Context.Rel.Declaration.t -> Pp.t
+val pr_named_decl : env -> evar_map -> Constr.named_declaration -> Pp.t
+val pr_compacted_decl : env -> evar_map -> Constr.compacted_declaration -> Pp.t
+val pr_rel_decl : env -> evar_map -> Constr.rel_declaration -> Pp.t
-val pr_named_context : env -> evar_map -> Context.Named.t -> Pp.t
+val pr_named_context : env -> evar_map -> Constr.named_context -> Pp.t
val pr_named_context_of : env -> evar_map -> Pp.t
-val pr_rel_context : env -> evar_map -> Context.Rel.t -> Pp.t
+val pr_rel_context : env -> evar_map -> Constr.rel_context -> Pp.t
val pr_rel_context_of : env -> evar_map -> Pp.t
val pr_context_of : env -> evar_map -> Pp.t
@@ -171,22 +171,26 @@ val pr_transparent_state : transparent_state -> Pp.t
(** Proofs, these functions obey [Hyps Limit] and [Compact contexts]. *)
-val pr_goal : goal sigma -> Pp.t
+val pr_goal : ?diffs:bool -> ?prev_gs:(goal sigma) -> goal sigma -> Pp.t
-(** [pr_subgoals ~pr_first pp sigma seeds shelf focus_stack unfocused goals]
+(** [pr_subgoals ~pr_first ~prev_proof pp sigma seeds shelf focus_stack unfocused goals]
prints the goals of the list [goals] followed by the goals in
[unfocused], in a short way (typically only the conclusion) except
- for the first goal if [pr_first] is true. This function can be
- replaced by another one by calling [set_printer_pr] (see below),
- typically by plugin writers. The default printer prints only the
+ for the first goal if [pr_first] is true. Also, if [diffs] is true
+ and [pr_first] is true, then highlight diffs relative to [prev] in the
+ output for first goal. This function prints only the
focused goals unless the conrresponding option
[enable_unfocused_goal_printing] is set. [seeds] is for printing
dependent evars (mainly for emacs proof tree mode). *)
-val pr_subgoals : ?pr_first:bool -> Pp.t option -> evar_map -> seeds:goal list -> shelf:goal list -> stack:int list -> unfocused:goal list -> goals:goal list -> Pp.t
+val pr_subgoals : ?pr_first:bool -> ?diffs:bool -> ?prev:(goal list * evar_map) -> Pp.t option -> evar_map
+ -> seeds:goal list -> shelf:goal list -> stack:int list
+ -> unfocused: goal list -> goals:goal list -> Pp.t
val pr_subgoal : int -> evar_map -> goal list -> Pp.t
val pr_concl : int -> evar_map -> goal -> Pp.t
+val pr_open_subgoals_diff : ?quiet:bool -> ?diffs:bool -> ?prev_proof:Proof.t -> Proof.t -> Pp.t
+val diff_pr_open_subgoals : ?quiet:bool -> Proof.t option -> Proof.t option -> Pp.t
val pr_open_subgoals : proof:Proof.t -> Pp.t
val pr_nth_open_subgoal : proof:Proof.t -> int -> Pp.t
val pr_evar : evar_map -> (Evar.t * evar_info) -> Pp.t
@@ -197,6 +201,8 @@ val pr_ne_evar_set : Pp.t -> Pp.t -> evar_map ->
val pr_prim_rule : prim_rule -> Pp.t
+val print_and_diff : Proof.t option -> Proof.t option -> unit
+
(** Backwards compatibility *)
val prterm : constr -> Pp.t (** = pr_lconstr *)
@@ -210,7 +216,7 @@ type axiom =
type context_object =
| Variable of Id.t (* A section variable or a Let definition *)
- | Axiom of axiom * (Label.t * Context.Rel.t * types) list
+ | Axiom of axiom * (Label.t * Constr.rel_context * types) list
| Opaque of Constant.t (* An opaque constant. *)
| Transparent of Constant.t
diff --git a/printing/printing.mllib b/printing/printing.mllib
index b69d8a9ef8..deb52ad270 100644
--- a/printing/printing.mllib
+++ b/printing/printing.mllib
@@ -1,6 +1,7 @@
Genprint
Pputils
Ppconstr
+Proof_diffs
Printer
Printmod
Prettyp
diff --git a/printing/printmod.ml b/printing/printmod.ml
index 3f95dcfb6d..e2d9850bf8 100644
--- a/printing/printmod.ml
+++ b/printing/printmod.ml
@@ -103,9 +103,7 @@ let print_one_inductive env sigma mib ((_,i) as ind) =
let envpar = push_rel_context params env in
let inst =
if Declareops.inductive_is_polymorphic mib then
- let ctx = Declareops.inductive_polymorphic_context mib in
- let ctx = Univ.UContext.make (u, Univ.AUContext.instantiate u ctx) in
- Printer.pr_universe_instance sigma ctx
+ Printer.pr_universe_instance sigma u
else mt ()
in
hov 0 (
diff --git a/printing/proof_diffs.ml b/printing/proof_diffs.ml
new file mode 100644
index 0000000000..3a81e908a7
--- /dev/null
+++ b/printing/proof_diffs.ml
@@ -0,0 +1,347 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+(*
+Displays the differences between successive proof steps in coqtop and CoqIDE.
+Proof General requires minor changes to make the diffs visible, but this code
+shouldn't break the existing version of PG. See pp_diff.ml for details on how
+the diff works.
+
+Diffs are computed for the hypotheses and conclusion of the first goal between
+the old and new proofs.
+
+Diffs can be enabled with the Coq commmand "Set Diffs on|off|removed." or
+'-diffs "on"|"off"|"removed"' on the OS command line. The "on" option shows only the
+new item with added text, while "removed" shows each modified item twice--once
+with the old value showing removed text and once with the new value showing
+added text.
+
+In CoqIDE, colors and highlights can be set in the Edit/Preferences/Tags panel.
+For coqtop, these can be set through the COQ_COLORS environment variable.
+
+Limitations/Possible enhancements:
+
+- If you go back to a prior proof step, diffs are not shown on the new current
+step. Diffs will be shown again once you do another proof step.
+
+- Diffs are done between the first active goal in the old and new proofs.
+If, for example, the proof step completed a goal, then the new goal is a
+different goal, not a transformation of the old goal, so a diff is probably
+not appropriate. (There's currently no way to tell when this happens or to
+accurately match goals across old and new proofs.
+See https://github.com/coq/coq/issues/7653) This is also why only the
+first goal is diffed.
+
+- "Set Diffs "xx"." should reprint the current goal using the new option.
+
+- coqtop colors were chosen for white text on a black background. They're
+not the greatest. I didn't want to change the existing green highlight.
+Suggestions welcome.
+
+- coqtop underlines removed text because (per Wikipedia) the ANSI escape code
+for strikeout is not commonly supported (it didn't work on mine). CoqIDE
+uses strikeout on removed text.
+*)
+
+open Pp_diff
+
+let diff_option = ref `OFF
+
+(* todo: Is there a way to persist the setting between sessions?
+ Eg if the user wants this as a permanent config setting? *)
+let read_diffs_option () = match !diff_option with
+| `OFF -> "off"
+| `ON -> "on"
+| `REMOVED -> "removed"
+
+let write_diffs_option = function
+| "off" -> diff_option := `OFF
+| "on" -> diff_option := `ON
+| "removed" -> diff_option := `REMOVED
+| _ -> CErrors.user_err Pp.(str "Diffs option only accepts the following values: \"off\", \"on\", \"removed\".")
+
+let _ =
+ Goptions.(declare_string_option {
+ optdepr = false;
+ optname = "show diffs in proofs";
+ optkey = ["Diffs"];
+ optread = read_diffs_option;
+ optwrite = write_diffs_option
+ })
+
+let show_diffs () = !diff_option <> `OFF;;
+let show_removed () = !diff_option = `REMOVED;;
+
+
+(* DEBUG/UNIT TEST *)
+let cfprintf oc = Printf.(kfprintf (fun oc -> fprintf oc "") oc)
+let log_out_ch = ref stdout
+[@@@ocaml.warning "-32"]
+let cprintf s = cfprintf !log_out_ch s
+[@@@ocaml.warning "+32"]
+
+module StringMap = Map.Make(String);;
+
+let tokenize_string s =
+ (* todo: cLexer changes buff as it proceeds. Seems like that should be saved, too.
+ But I don't understand how it's used--it looks like things get appended to it but
+ it never gets cleared. *)
+ let rec stream_tok acc str =
+ let e = Stream.next str in
+ if Tok.(equal e EOI) then
+ List.rev acc
+ else
+ stream_tok ((Tok.extract_string e) :: acc) str
+ in
+ let st = CLexer.get_lexer_state () in
+ try
+ let istr = Stream.of_string s in
+ let lex = CLexer.lexer.Plexing.tok_func istr in
+ let toks = stream_tok [] (fst lex) in
+ CLexer.set_lexer_state st;
+ toks
+ with exn ->
+ CLexer.set_lexer_state st;
+ raise (Diff_Failure "Input string is not lexable");;
+
+
+type hyp_info = {
+ idents: string list;
+ rhs_pp: Pp.t;
+ mutable done_: bool;
+}
+
+(* Generate the diffs between the old and new hyps.
+ This works by matching lines with the hypothesis name and diffing the right-hand side.
+ Lines that have multiple names such as "n, m : nat" are handled specially to account
+ for, say, the addition of m to a pre-existing "n : nat".
+ *)
+let diff_hyps o_line_idents o_map n_line_idents n_map =
+ let rv : Pp.t list ref = ref [] in
+
+ let is_done ident map = (StringMap.find ident map).done_ in
+ let exists ident map =
+ try let _ = StringMap.find ident map in true
+ with Not_found -> false in
+ let contains l ident = try [List.find (fun x -> x = ident) l] with Not_found -> [] in
+
+ let output old_ids_uo new_ids =
+ (* use the order from the old line in case it's changed in the new *)
+ let old_ids = if old_ids_uo = [] then [] else
+ let orig = (StringMap.find (List.hd old_ids_uo) o_map).idents in
+ List.concat (List.map (contains orig) old_ids_uo) in
+
+ let setup ids map = if ids = [] then ("", Pp.mt ()) else
+ let open Pp in
+ let rhs_pp = (StringMap.find (List.hd ids) map).rhs_pp in
+ let pp_ids = List.map (fun x -> str x) ids in
+ let hyp_pp = List.fold_left (fun l1 l2 -> l1 ++ str ", " ++ l2) (List.hd pp_ids) (List.tl pp_ids) ++ rhs_pp in
+ (string_of_ppcmds hyp_pp, hyp_pp)
+ in
+
+ let (o_line, o_pp) = setup old_ids o_map in
+ let (n_line, n_pp) = setup new_ids n_map in
+
+ let hyp_diffs = diff_str ~tokenize_string o_line n_line in
+ let (has_added, has_removed) = has_changes hyp_diffs in
+ if show_removed () && has_removed then begin
+ let o_entry = StringMap.find (List.hd old_ids) o_map in
+ o_entry.done_ <- true;
+ rv := (add_diff_tags `Removed o_pp hyp_diffs) :: !rv;
+ end;
+ if n_line <> "" then begin
+ let n_entry = StringMap.find (List.hd new_ids) n_map in
+ n_entry.done_ <- true;
+ rv := (add_diff_tags `Added n_pp hyp_diffs) :: !rv
+ end
+ in
+
+ (* process identifier level diff *)
+ let process_ident_diff diff =
+ let (dtype, ident) = get_dinfo diff in
+ match dtype with
+ | `Removed ->
+ if dtype = `Removed then begin
+ let o_idents = (StringMap.find ident o_map).idents in
+ (* only show lines that have all idents removed here; other removed idents appear later *)
+ if show_removed () &&
+ List.for_all (fun x -> not (exists x n_map)) o_idents then
+ output (List.rev o_idents) []
+ end
+ | _ -> begin (* Added or Common case *)
+ let n_idents = (StringMap.find ident n_map).idents in
+
+ (* Process a new hyp line, possibly splitting it. Duplicates some of
+ process_ident iteration, but easier to understand this way *)
+ let process_line ident2 =
+ if not (is_done ident2 n_map) then begin
+ let n_ids_list : string list ref = ref [] in
+ let o_ids_list : string list ref = ref [] in
+ let fst_omap_idents = ref None in
+ let add ids id map =
+ ids := id :: !ids;
+ (StringMap.find id map).done_ <- true in
+
+ (* get identifiers shared by one old and one new line, plus
+ other Added in new and other Removed in old *)
+ let process_split ident3 =
+ if not (is_done ident3 n_map) then begin
+ let this_omap_idents = try Some (StringMap.find ident3 o_map).idents
+ with Not_found -> None in
+ if !fst_omap_idents = None then
+ fst_omap_idents := this_omap_idents;
+ match (!fst_omap_idents, this_omap_idents) with
+ | (Some fst, Some this) when fst == this -> (* yes, == *)
+ add n_ids_list ident3 n_map;
+ (* include, in old order, all undone Removed idents in old *)
+ List.iter (fun x -> if x = ident3 || not (is_done x o_map) && not (exists x n_map) then
+ (add o_ids_list x o_map)) fst
+ | (_, None) ->
+ add n_ids_list ident3 n_map (* include all undone Added idents in new *)
+ | _ -> ()
+ end in
+ List.iter process_split n_idents;
+ output (List.rev !o_ids_list) (List.rev !n_ids_list)
+ end in
+ List.iter process_line n_idents (* O(n^2), so sue me *)
+ end in
+
+ let cvt s = Array.of_list (List.concat s) in
+ let ident_diffs = diff_strs (cvt o_line_idents) (cvt n_line_idents) in
+ List.iter process_ident_diff ident_diffs;
+ List.rev !rv;;
+
+
+type 'a hyp = (Names.Id.t list * 'a option * 'a)
+type 'a reified_goal = { name: string; ty: 'a; hyps: 'a hyp list; env : Environ.env; sigma: Evd.evar_map }
+
+(* XXX: Port to proofview, one day. *)
+(* open Proofview *)
+module CDC = Context.Compacted.Declaration
+
+let to_tuple : Constr.compacted_declaration -> (Names.Id.t list * 'pc option * 'pc) =
+ let open CDC in function
+ | LocalAssum(idl, tm) -> (idl, None, tm)
+ | LocalDef(idl,tdef,tm) -> (idl, Some tdef, tm);;
+
+(* XXX: Very unfortunately we cannot use the Proofview interface as
+ Proof is still using the "legacy" one. *)
+let process_goal sigma g : Constr.t reified_goal =
+ let env = Goal.V82.env sigma g in
+ let hyps = Goal.V82.hyps sigma g in
+ let ty = Goal.V82.concl sigma g in
+ let name = Goal.uid g in
+ (* There is a Constr/Econstr mess here... *)
+ let ty = EConstr.to_constr sigma ty in
+ (* compaction is usually desired [eg for better display] *)
+ let hyps = Termops.compact_named_context (Environ.named_context_of_val hyps) in
+ let hyps = List.map to_tuple hyps in
+ { name; ty; hyps; env; sigma };;
+
+let pr_letype_core goal_concl_style env sigma t =
+ Ppconstr.pr_lconstr_expr (Constrextern.extern_type goal_concl_style env sigma t)
+
+let pp_of_type env sigma ty =
+ pr_letype_core true env sigma EConstr.(of_constr ty)
+
+let pr_leconstr_core goal_concl_style env sigma t =
+ Ppconstr.pr_lconstr_expr (Constrextern.extern_constr goal_concl_style env sigma t)
+
+let pr_lconstr_env env sigma c = pr_leconstr_core false env sigma (EConstr.of_constr c)
+
+(* fetch info from a goal, returning (idents, map, concl_pp) where
+idents is a list with one entry for each hypothesis, each entry is the list of
+idents on the lhs of the hypothesis. map is a map from ident to hyp_info
+reoords. For example: for the hypotheses:
+ b : bool
+ n, m : nat
+
+list will be [ ["b"]; ["n"; "m"] ]
+
+map will contain:
+ "b" -> { ["b"], Pp.t for ": bool"; false }
+ "n" -> { ["n"; "m"], Pp.t for ": nat"; false }
+ "m" -> { ["n"; "m"], Pp.t for ": nat"; false }
+ where the last two entries share the idents list.
+
+concl_pp is the conclusion as a Pp.t
+*)
+let goal_info goal sigma =
+ let map = ref StringMap.empty in
+ let line_idents = ref [] in
+ let build_hyp_info env sigma hyp =
+ let (names, body, ty) = hyp in
+ let open Pp in
+ let idents = List.map (fun x -> Names.Id.to_string x) names in
+
+ line_idents := idents :: !line_idents;
+ let mid = match body with
+ | Some c ->
+ let pb = pr_lconstr_env env sigma c in
+ let pb = if Constr.isCast c then surround pb else pb in
+ str " := " ++ pb
+ | None -> mt() in
+ let ts = pp_of_type env sigma ty in
+ let rhs_pp = mid ++ str " : " ++ ts in
+
+ let make_entry () = { idents; rhs_pp; done_ = false } in
+ List.iter (fun ident -> map := (StringMap.add ident (make_entry ()) !map); ()) idents
+ in
+
+ try
+ let { ty=ty; hyps=hyps; env=env } = process_goal sigma goal in
+ List.iter (build_hyp_info env sigma) (List.rev hyps);
+ let concl_pp = pp_of_type env sigma ty in
+ ( List.rev !line_idents, !map, concl_pp )
+ with _ -> ([], !map, Pp.mt ());;
+
+let diff_goal_info o_info n_info =
+ let (o_line_idents, o_hyp_map, o_concl_pp) = o_info in
+ let (n_line_idents, n_hyp_map, n_concl_pp) = n_info in
+ let show_removed = Some (show_removed ()) in
+ let concl_pp = diff_pp_combined ~tokenize_string ?show_removed o_concl_pp n_concl_pp in
+
+ let hyp_diffs_list = diff_hyps o_line_idents o_hyp_map n_line_idents n_hyp_map in
+ (hyp_diffs_list, concl_pp)
+
+let hyp_list_to_pp hyps =
+ let open Pp in
+ match hyps with
+ | h :: tl -> List.fold_left (fun x y -> x ++ cut () ++ y) h tl
+ | [] -> mt ();;
+
+(* Special purpuse, use only for the IDE interface, *)
+let diff_first_goal o_proof n_proof =
+ let first_goal_info proof =
+ match proof with
+ | None -> ([], StringMap.empty, Pp.mt ())
+ | Some proof2 ->
+ let (goals,_,_,_,sigma) = Proof.proof proof2 in
+ match goals with
+ | hd :: tl -> goal_info hd sigma;
+ | _ -> ([], StringMap.empty, Pp.mt ())
+ in
+ diff_goal_info (first_goal_info o_proof) (first_goal_info n_proof);;
+
+let diff_goals ?prev_gs n_gs =
+ let unwrap gs =
+ match gs with
+ | Some gs ->
+ let goal = Evd.sig_it gs in
+ let sigma = Refiner.project gs in
+ goal_info goal sigma
+ | None -> ([], StringMap.empty, Pp.mt ())
+ in
+ let (hyps_pp_list, concl_pp) = diff_goal_info (unwrap prev_gs) (unwrap n_gs) in
+ let open Pp in
+ v 0 (
+ (hyp_list_to_pp hyps_pp_list) ++ cut () ++
+ str "============================" ++ cut () ++
+ concl_pp);;
diff --git a/printing/proof_diffs.mli b/printing/proof_diffs.mli
new file mode 100644
index 0000000000..482f03b686
--- /dev/null
+++ b/printing/proof_diffs.mli
@@ -0,0 +1,73 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+(* diff options *)
+
+(** Controls whether to show diffs. Takes values "on", "off", "removed" *)
+val write_diffs_option : string -> unit
+(** Returns true if the diffs option is "on" or "removed" *)
+val show_diffs : unit -> bool
+
+(** Computes the diff between the first goal of two Proofs and returns
+the highlighted hypotheses and conclusion.
+
+If the strings used to display the goal are not lexable (this is believed
+unlikely), this routine will generate a Diff_Failure. This routine may also
+raise Diff_Failure under some "impossible" conditions.
+
+If you want to make your call especially bulletproof, catch these
+exceptions, print a user-visible message, then recall this routine with
+the first argument set to None, which will skip the diff.
+*)
+val diff_first_goal : Proof.t option -> Proof.t option -> Pp.t list * Pp.t
+
+open Evd
+open Proof_type
+open Environ
+open Constr
+
+(** Computes the diff between two goals
+
+If the strings used to display the goal are not lexable (this is believed
+unlikely), this routine will generate a Diff_Failure. This routine may also
+raise Diff_Failure under some "impossible" conditions.
+
+If you want to make your call especially bulletproof, catch these
+exceptions, print a user-visible message, then recall this routine with
+the first argument set to None, which will skip the diff.
+*)
+val diff_goals : ?prev_gs:(goal sigma) -> goal sigma option -> Pp.t
+
+(** Convert a string to a list of token strings using the lexer *)
+val tokenize_string : string -> string list
+
+val pr_letype_core : bool -> Environ.env -> Evd.evar_map -> EConstr.types -> Pp.t
+val pr_leconstr_core : bool -> Environ.env -> Evd.evar_map -> EConstr.constr -> Pp.t
+val pr_lconstr_env : env -> evar_map -> constr -> Pp.t
+
+(* Exposed for unit test, don't use these otherwise *)
+(* output channel for the test log file *)
+val log_out_ch : out_channel ref
+
+
+type hyp_info = {
+ idents: string list;
+ rhs_pp: Pp.t;
+ mutable done_: bool;
+}
+
+module StringMap :
+sig
+ type +'a t
+ val empty: hyp_info t
+ val add : string -> hyp_info -> hyp_info t -> hyp_info t
+end
+
+val diff_hyps : string list list -> hyp_info StringMap.t -> string list list -> hyp_info StringMap.t -> Pp.t list
diff --git a/proofs/pfedit.mli b/proofs/pfedit.mli
index 7b79732249..e02b5ab956 100644
--- a/proofs/pfedit.mli
+++ b/proofs/pfedit.mli
@@ -85,6 +85,9 @@ val solve : ?with_end_tac:unit Proofview.tactic ->
val by : unit Proofview.tactic -> bool
+(** Option telling if unification heuristics should be used. *)
+val use_unification_heuristics : unit -> bool
+
(** [instantiate_nth_evar_com n c] instantiate the [n]th undefined
existential variable of the current focused proof by [c] or raises a
UserError if no proof is focused or if there is no such [n]th
diff --git a/proofs/proof.ml b/proofs/proof.ml
index 51e0a1d614..0d355890c5 100644
--- a/proofs/proof.ml
+++ b/proofs/proof.ml
@@ -63,6 +63,7 @@ exception CannotUnfocusThisWay
(* Cannot focus on non-existing subgoals *)
exception NoSuchGoals of int * int
+exception NoSuchGoal of Names.Id.t
exception FullyUnfocused
@@ -75,6 +76,10 @@ let _ = CErrors.register_handler begin function
CErrors.user_err ~hdr:"Focus" Pp.(
str"Not every goal in range ["++ int i ++ str","++int j++str"] exist."
)
+ | NoSuchGoal id ->
+ CErrors.user_err
+ ~hdr:"Focus"
+ Pp.(str "No such goal: " ++ str (Names.Id.to_string id) ++ str ".")
| FullyUnfocused -> CErrors.user_err Pp.(str "The proof is not focused")
| _ -> raise CErrors.Unhandled
end
@@ -230,6 +235,37 @@ let focus cond inf i pr =
try _focus cond (Obj.repr inf) i i pr
with CList.IndexOutOfRange -> raise (NoSuchGoals (i,i))
+(* Focus on the goal named id *)
+let focus_id cond inf id pr =
+ let (focused_goals, evar_map) = Proofview.proofview pr.proofview in
+ begin match try Some (Evd.evar_key id evar_map) with Not_found -> None with
+ | Some ev ->
+ begin match CList.safe_index Evar.equal ev focused_goals with
+ | Some i ->
+ (* goal is already under focus *)
+ _focus cond (Obj.repr inf) i i pr
+ | None ->
+ if CList.mem_f Evar.equal ev pr.shelf then
+ (* goal is on the shelf, put it in focus *)
+ let proofview = Proofview.unshelve [ev] pr.proofview in
+ let shelf =
+ CList.filter (fun ev' -> Evar.equal ev ev' |> not) pr.shelf
+ in
+ let pr = { pr with proofview; shelf } in
+ let (focused_goals, _) = Proofview.proofview pr.proofview in
+ let i =
+ (* Now we know that this will succeed *)
+ try CList.index Evar.equal ev focused_goals
+ with Not_found -> assert false
+ in
+ _focus cond (Obj.repr inf) i i pr
+ else
+ raise CannotUnfocusThisWay
+ end
+ | None ->
+ raise (NoSuchGoal id)
+ end
+
let rec unfocus kind pr () =
let cond = cond_of_focus pr in
match test_cond cond kind pr.proofview with
diff --git a/proofs/proof.mli b/proofs/proof.mli
index c0e832fb8c..33addf13d7 100644
--- a/proofs/proof.mli
+++ b/proofs/proof.mli
@@ -137,6 +137,9 @@ val done_cond : ?loose_end:bool -> 'a focus_kind -> 'a focus_condition
a need for it? *)
val focus : 'a focus_condition -> 'a -> int -> t -> t
+(* focus on goal named id *)
+val focus_id : 'aa focus_condition -> 'a -> Names.Id.t -> t -> t
+
exception FullyUnfocused
exception CannotUnfocusThisWay
diff --git a/proofs/proof_global.ml b/proofs/proof_global.ml
index 3120c97b58..7e250faa86 100644
--- a/proofs/proof_global.ml
+++ b/proofs/proof_global.ml
@@ -93,7 +93,7 @@ type pstate = {
pid : Id.t; (* the name of the theorem whose proof is being constructed *)
terminator : proof_terminator CEphemeron.key;
endline_tactic : Genarg.glob_generic_argument option;
- section_vars : Context.Named.t option;
+ section_vars : Constr.named_context option;
proof : Proof.t;
strength : Decl_kinds.goal_kind;
mode : proof_mode CEphemeron.key;
@@ -348,9 +348,8 @@ let close_proof ~keep_body_ucst_separate ?feedback_id ~now
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
+ let used_univs_body = Univops.universes_of_constr body in
+ let used_univs_typ = Univops.universes_of_constr typ in
if allow_deferred then
let initunivs = UState.const_univ_entry ~poly initial_euctx in
let ctx = constrain_variables universes in
diff --git a/proofs/proof_global.mli b/proofs/proof_global.mli
index 9e07ed2d05..854ceaa41a 100644
--- a/proofs/proof_global.mli
+++ b/proofs/proof_global.mli
@@ -126,8 +126,8 @@ val set_endline_tactic : Genarg.glob_generic_argument -> unit
* (w.r.t. type dependencies and let-ins covered by it) + a list of
* ids to be cleared *)
val set_used_variables :
- Names.Id.t list -> Context.Named.t * Names.lident list
-val get_used_variables : unit -> Context.Named.t option
+ Names.Id.t list -> Constr.named_context * Names.lident list
+val get_used_variables : unit -> Constr.named_context option
(** Get the universe declaration associated to the current proof. *)
val get_universe_decl : unit -> UState.universe_decl
diff --git a/shell.nix b/shell.nix
new file mode 100644
index 0000000000..3201c50501
--- /dev/null
+++ b/shell.nix
@@ -0,0 +1,4 @@
+# Some developers don't want a pinned nix-shell by default.
+# If you want to use the pin nix-shell or a more sophisticated set of arguments:
+# $ nix-shell default.nix --arg shell true
+import ./default.nix { pkgs = import <nixpkgs> {}; shell = true; }
diff --git a/stm/stm.ml b/stm/stm.ml
index 0aed88a53f..2e9bf71e49 100644
--- a/stm/stm.ml
+++ b/stm/stm.ml
@@ -1103,7 +1103,8 @@ module Backtrack : sig
val branches_of : Stateid.t -> backup
(* Returns the state that the command should backtract to *)
- val undo_vernac_classifier : vernac_control -> Stateid.t * vernac_when
+ val undo_vernac_classifier : vernac_control -> doc:doc -> Stateid.t * vernac_when
+ val get_prev_proof : doc:doc -> Stateid.t -> Proof.t option
end = struct (* {{{ *)
@@ -1161,7 +1162,17 @@ end = struct (* {{{ *)
" If your use is intentional, you may want to disable this warning and pass" ^
" the \"-async-proofs-cache force\" option to Coq."))
- let undo_vernac_classifier v =
+ let back_tactic n (id,_,_,tactic,undo) =
+ let value = (if tactic then 1 else 0) - undo in
+ if Int.equal n 0 then `Stop id else `Cont (n-value)
+
+ let get_proof ~doc id =
+ let open Vernacstate in
+ match state_of_id ~doc id with
+ | `Valid (Some vstate) -> Some (Proof_global.proof_of_state vstate.proof)
+ | _ -> None
+
+ let undo_vernac_classifier v ~doc =
if VCS.is_interactive () = `No && !cur_opt.async_proofs_cache <> Some Force
then undo_costly_in_batch_mode v;
try
@@ -1185,9 +1196,7 @@ end = struct (* {{{ *)
oid, VtNow
| VernacUndo n ->
let id = VCS.get_branch_pos (VCS.current_branch ()) in
- let oid = fold_until (fun n (id,_,_,tactic,undo) ->
- let value = (if tactic then 1 else 0) - undo in
- if Int.equal n 0 then `Stop id else `Cont (n-value)) n id in
+ let oid = fold_until back_tactic n id in
oid, VtLater
| VernacUndoTo _
| VernacRestart as e ->
@@ -1220,8 +1229,16 @@ end = struct (* {{{ *)
CErrors.user_err ~hdr:"undo_vernac_classifier"
Pp.(str "Cannot undo")
+ let get_prev_proof ~doc id =
+ try
+ let did = fold_until back_tactic 1 id in
+ get_proof ~doc did
+ with Not_found -> None
+
end (* }}} *)
+let get_prev_proof = Backtrack.get_prev_proof
+
let hints = ref Aux_file.empty_aux_file
let set_compilation_hints file =
hints := Aux_file.load_aux_file_for file
@@ -2785,7 +2802,7 @@ let process_transaction ~doc ?(newtip=Stateid.fresh ())
match c with
(* Meta *)
| VtMeta, _ ->
- let id, w = Backtrack.undo_vernac_classifier expr in
+ let id, w = Backtrack.undo_vernac_classifier expr ~doc in
process_back_meta_command ~newtip ~head id x w
(* Query *)
@@ -2976,7 +2993,7 @@ let parse_sentence ~doc sid pa =
str "All is good if not parsing changes occur between the two states, however if they do, a problem might occur.");
Flags.with_option Flags.we_are_parsing (fun () ->
try
- match Pcoq.Gram.entry_parse Pvernac.main_entry pa with
+ match Pcoq.Entry.parse Pvernac.main_entry pa with
| None -> raise End_of_input
| Some (loc, cmd) -> CAst.make ~loc cmd
with e when CErrors.noncritical e ->
diff --git a/stm/stm.mli b/stm/stm.mli
index aed7274d06..7f70ea18da 100644
--- a/stm/stm.mli
+++ b/stm/stm.mli
@@ -92,11 +92,11 @@ val new_doc : stm_init_options -> doc * Stateid.t
(** [parse_sentence sid pa] Reads a sentence from [pa] with parsing
state [sid] Returns [End_of_input] if the stream ends *)
-val parse_sentence : doc:doc -> Stateid.t -> Pcoq.Gram.coq_parsable ->
+val parse_sentence : doc:doc -> Stateid.t -> Pcoq.Parsable.t ->
Vernacexpr.vernac_control CAst.t
(* Reminder: A parsable [pa] is constructed using
- [Pcoq.Gram.coq_parsable stream], where [stream : char Stream.t]. *)
+ [Pcoq.Parsable.t stream], where [stream : char Stream.t]. *)
exception End_of_input
@@ -110,11 +110,15 @@ val add : doc:doc -> ontop:Stateid.t -> ?newtip:Stateid.t ->
bool -> Vernacexpr.vernac_control CAst.t ->
doc * Stateid.t * [ `NewTip | `Unfocus of Stateid.t ]
+(* Returns the proof state before the last tactic that was applied at or before
+the specified state. Used to compute proof diffs. *)
+val get_prev_proof : doc:doc -> Stateid.t -> Proof.t option
+
(* [query at ?report_with cmd] Executes [cmd] at a given state [at],
throwing away side effects except messages. Feedback will
be sent with [report_with], which defaults to the dummy state id *)
val query : doc:doc ->
- at:Stateid.t -> route:Feedback.route_id -> Pcoq.Gram.coq_parsable -> unit
+ at:Stateid.t -> route:Feedback.route_id -> Pcoq.Parsable.t -> unit
(* [edit_at id] is issued to change the editing zone. [`NewTip] is returned if
the requested id is the new document tip hence the document portion following
diff --git a/stm/vernac_classifier.ml b/stm/vernac_classifier.ml
index e01dcbcb6e..2170477938 100644
--- a/stm/vernac_classifier.ml
+++ b/stm/vernac_classifier.ml
@@ -42,13 +42,6 @@ let string_of_vernac_when = function
let string_of_vernac_classification (t,w) =
string_of_vernac_type t ^ " " ^ string_of_vernac_when w
-let classifiers = ref []
-let declare_vernac_classifier
- (s : Vernacexpr.extend_name)
- (f : Genarg.raw_generic_argument list -> unit -> vernac_classification)
-=
- classifiers := !classifiers @ [s,f]
-
let idents_of_name : Names.Name.t -> Names.Id.t list =
function
| Names.Anonymous -> []
@@ -162,6 +155,7 @@ let classify_vernac e =
| VernacDeclareClass _ | VernacDeclareInstances _
| VernacRegister _
| VernacNameSectionHypSet _
+ | VernacDeclareCustomEntry _
| VernacComments _ -> VtSideff [], VtLater
(* Who knows *)
| VernacLoad _ -> VtSideff [], VtNow
@@ -194,16 +188,13 @@ let classify_vernac e =
| VernacWriteState _ -> VtSideff [], VtNow
(* Plugins should classify their commands *)
| VernacExtend (s,l) ->
- try List.assoc s !classifiers l ()
+ try Vernacentries.get_vernac_classifier s l
with Not_found -> anomaly(str"No classifier for"++spc()++str (fst s)++str".")
in
let rec static_control_classifier ~poly = function
| VernacExpr (f, e) ->
- let poly = List.fold_left (fun poly f ->
- match f with
- | VernacPolymorphic b -> b
- | (VernacProgram | VernacLocal _) -> poly
- ) poly f in
+ let _, atts = Vernacentries.attributes_of_flags f Vernacinterp.(mk_atts ~polymorphic:poly ()) in
+ let poly = atts.Vernacinterp.polymorphic in
static_classifier ~poly e
| VernacTimeout (_,e) -> static_control_classifier ~poly e
| VernacTime (_,{v=e}) | VernacRedirect (_, {v=e}) ->
diff --git a/stm/vernac_classifier.mli b/stm/vernac_classifier.mli
index 45fbfb42af..e82b191418 100644
--- a/stm/vernac_classifier.mli
+++ b/stm/vernac_classifier.mli
@@ -9,17 +9,12 @@
(************************************************************************)
open Vernacexpr
-open Genarg
val string_of_vernac_classification : vernac_classification -> string
(** What does a vernacular do *)
val classify_vernac : vernac_control -> vernac_classification
-(** Install a vernacular classifier for VernacExtend *)
-val declare_vernac_classifier :
- Vernacexpr.extend_name -> (raw_generic_argument list -> unit -> vernac_classification) -> unit
-
(** Standard constant classifiers *)
val classify_as_query : vernac_classification
val classify_as_sideeff : vernac_classification
diff --git a/stm/workerLoop.mli b/stm/workerLoop.mli
deleted file mode 100644
index 37ec6dacca..0000000000
--- a/stm/workerLoop.mli
+++ /dev/null
@@ -1,16 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-(* Default priority *)
-val async_proofs_worker_priority : CoqworkmgrApi.priority ref
-
-val loop :
- (unit -> unit) -> Coqargs.coq_cmdopts -> string list ->
- Coqargs.coq_cmdopts * string list
diff --git a/tactics/class_tactics.ml b/tactics/class_tactics.ml
index 773fc15208..9c5fdcd1ce 100644
--- a/tactics/class_tactics.ml
+++ b/tactics/class_tactics.ml
@@ -477,7 +477,7 @@ let is_Prop env sigma concl =
match EConstr.kind sigma ty with
| Sort s ->
begin match ESorts.kind sigma s with
- | Prop Null -> true
+ | Prop -> true
| _ -> false
end
| _ -> false
diff --git a/tactics/elimschemes.ml b/tactics/elimschemes.ml
index 70f73df5c1..3b69d9922d 100644
--- a/tactics/elimschemes.ml
+++ b/tactics/elimschemes.ml
@@ -44,7 +44,7 @@ let optimize_non_type_induction_scheme kind dep sort _ ind =
mib.mind_nparams_rec
else
mib.mind_nparams in
- let sigma, sort = Evd.fresh_sort_in_family env sigma sort in
+ let sigma, sort = Evd.fresh_sort_in_family sigma sort in
let sigma, t', c' = weaken_sort_scheme env sigma false sort npars c t in
let sigma = Evd.minimize_universes sigma in
(Evarutil.nf_evars_universes sigma c', Evd.evar_universe_context sigma), eff
diff --git a/tactics/eqschemes.ml b/tactics/eqschemes.ml
index ad5239116a..ea5ff4a6cb 100644
--- a/tactics/eqschemes.ml
+++ b/tactics/eqschemes.ml
@@ -397,7 +397,7 @@ let build_l2r_rew_scheme dep env ind kind =
rel_vect (nrealargs+4) nrealargs;
rel_vect 1 nrealargs;
[|mkRel 1|]]) in
- let s, ctx' = UnivGen.fresh_sort_in_family (Global.env ()) kind in
+ let s, ctx' = UnivGen.fresh_sort_in_family kind in
let ctx = Univ.ContextSet.union ctx ctx' in
let s = mkSort s in
let ci = make_case_info (Global.env()) ind RegularStyle in
@@ -500,7 +500,7 @@ let build_l2r_forward_rew_scheme dep env ind kind =
name_context env ((LocalAssum (Name varH,applied_ind))::realsign) in
let realsign_ind_P n aP =
name_context env ((LocalAssum (Name varH,aP))::realsign_P n) in
- let s, ctx' = UnivGen.fresh_sort_in_family (Global.env ()) kind in
+ let s, ctx' = UnivGen.fresh_sort_in_family kind in
let ctx = Univ.ContextSet.union ctx ctx' in
let s = mkSort s in
let ci = make_case_info (Global.env()) ind RegularStyle in
@@ -578,7 +578,7 @@ let build_r2l_forward_rew_scheme dep env ind kind =
let applied_ind = build_dependent_inductive indu specif in
let realsign_ind =
name_context env ((LocalAssum (Name varH,applied_ind))::realsign) in
- let s, ctx' = UnivGen.fresh_sort_in_family (Global.env ()) kind in
+ let s, ctx' = UnivGen.fresh_sort_in_family kind in
let ctx = Univ.ContextSet.union ctx ctx' in
let s = mkSort s in
let ci = make_case_info (Global.env()) ind RegularStyle in
diff --git a/tactics/equality.ml b/tactics/equality.ml
index 91c5774051..0e39215701 100644
--- a/tactics/equality.ml
+++ b/tactics/equality.ml
@@ -942,7 +942,7 @@ let rec build_discriminator env sigma true_0 false_0 dirn c = function
let (cnum_nlams,cnum_env,kont) = descend_then env sigma c cnum in
let newc = mkRel(cnum_nlams-argnum) in
let subval = build_discriminator cnum_env sigma true_0 false_0 dirn newc l in
- kont sigma subval (false_0,mkSort (Prop Null))
+ kont sigma subval (false_0,mkProp)
(* Note: discrimination could be more clever: if some elimination is
not allowed because of a large impredicative constructor in the
diff --git a/tactics/hints.ml b/tactics/hints.ml
index 85ff028249..43a450ea71 100644
--- a/tactics/hints.ml
+++ b/tactics/hints.ml
@@ -165,12 +165,17 @@ type hint_mode =
| ModeNoHeadEvar (* No evar at the head *)
| ModeOutput (* Anything *)
+type 'a hints_transparency_target =
+ | HintsVariables
+ | HintsConstants
+ | HintsReferences of 'a list
+
type hints_expr =
| HintsResolve of (hint_info_expr * bool * reference_or_constr) list
| HintsResolveIFF of bool * qualid list * int option
| HintsImmediate of reference_or_constr list
| HintsUnfold of qualid list
- | HintsTransparency of qualid list * bool
+ | HintsTransparency of qualid hints_transparency_target * bool
| HintsMode of qualid * hint_mode list
| HintsConstructors of qualid list
| HintsExtern of int * Constrexpr.constr_expr option * Genarg.raw_generic_argument
@@ -294,16 +299,16 @@ let strip_params env sigma c =
match EConstr.kind sigma c with
| App (f, args) ->
(match EConstr.kind sigma f with
- | Const (p,_) ->
- let p = Projection.make p false in
- (match lookup_projection p env with
- | pb ->
- let n = pb.Declarations.proj_npars in
- if Array.length args > n then
- mkApp (mkProj (p, args.(n)),
- Array.sub args (n+1) (Array.length args - (n + 1)))
+ | Const (cst,_) ->
+ (match Recordops.find_primitive_projection cst with
+ | Some p ->
+ let p = Projection.make p false in
+ let npars = Projection.npars p in
+ if Array.length args > npars then
+ mkApp (mkProj (p, args.(npars)),
+ Array.sub args (npars+1) (Array.length args - (npars + 1)))
else c
- | exception Not_found -> c)
+ | None -> c)
| _ -> c)
| _ -> c
@@ -828,38 +833,48 @@ let make_exact_entry env sigma info poly ?(name=PathAny) (c, cty, ctx) =
let make_apply_entry env sigma (eapply,hnf,verbose) info poly ?(name=PathAny) (c, cty, ctx) =
let cty = if hnf then hnf_constr env sigma cty else cty in
- match EConstr.kind sigma cty with
- | Prod _ ->
- let sigma' = Evd.merge_context_set univ_flexible sigma ctx in
- let ce = mk_clenv_from_env env sigma' None (c,cty) in
- let c' = clenv_type (* ~reduce:false *) ce in
- let pat = Patternops.pattern_of_constr env ce.evd (EConstr.to_constr ~abort_on_undefined_evars:false sigma c') in
- let hd =
- try head_pattern_bound pat
- with BoundPattern -> failwith "make_apply_entry" in
- let nmiss = List.length (clenv_missing ce) in
- let secvars = secvars_of_constr env sigma c in
- let pri = match info.hint_priority with None -> nb_hyp sigma' cty + nmiss | Some p -> p in
- let pat = match info.hint_pattern with
- | Some p -> snd p | None -> pat
- in
- if Int.equal nmiss 0 then
- (Some hd,
- { pri; poly; pat = Some pat; name;
- db = None;
- secvars;
- code = with_uid (Res_pf(c,cty,ctx)); })
- else begin
- if not eapply then failwith "make_apply_entry";
- if verbose then
- Feedback.msg_info (str "the hint: eapply " ++ pr_leconstr_env env sigma' c ++
- str " will only be used by eauto");
- (Some hd,
- { pri; poly; pat = Some pat; name;
- db = None; secvars;
- code = with_uid (ERes_pf(c,cty,ctx)); })
- end
- | _ -> failwith "make_apply_entry"
+ match EConstr.kind sigma cty with
+ | Prod _ ->
+ let sigma' = Evd.merge_context_set univ_flexible sigma ctx in
+ let ce = mk_clenv_from_env env sigma' None (c,cty) in
+ let c' = clenv_type (* ~reduce:false *) ce in
+ let pat = Patternops.pattern_of_constr env ce.evd (EConstr.to_constr ~abort_on_undefined_evars:false sigma c') in
+ let hd =
+ try head_pattern_bound pat
+ with BoundPattern -> failwith "make_apply_entry" in
+ let miss = clenv_missing ce in
+ let nmiss = List.length miss in
+ let secvars = secvars_of_constr env sigma c in
+ let pri = match info.hint_priority with None -> nb_hyp sigma' cty + nmiss | Some p -> p in
+ let pat = match info.hint_pattern with
+ | Some p -> snd p | None -> pat
+ in
+ if Int.equal nmiss 0 then
+ (Some hd,
+ { pri; poly; pat = Some pat; name;
+ db = None;
+ secvars;
+ code = with_uid (Res_pf(c,cty,ctx)); })
+ else begin
+ if not eapply then failwith "make_apply_entry";
+ if verbose then begin
+ let variables = str (CString.plural nmiss "variable") in
+ Feedback.msg_info (
+ strbrk "The hint " ++
+ pr_leconstr_env env sigma' c ++
+ strbrk " will only be used by eauto, because applying " ++
+ pr_leconstr_env env sigma' c ++
+ strbrk " would leave " ++ variables ++ Pp.spc () ++
+ Pp.prlist_with_sep Pp.pr_comma Name.print (List.map (Evd.meta_name ce.evd) miss) ++
+ strbrk " as unresolved existential " ++ variables ++ str "."
+ )
+ end;
+ (Some hd,
+ { pri; poly; pat = Some pat; name;
+ db = None; secvars;
+ code = with_uid (ERes_pf(c,cty,ctx)); })
+ end
+ | _ -> failwith "make_apply_entry"
(* flags is (e,h,v) with e=true if eapply and h=true if hnf and v=true if verbose
c is a constr
@@ -871,20 +886,6 @@ let pr_hint_term env sigma ctx = function
let sigma = Evd.merge_context_set Evd.univ_flexible sigma ctx in
pr_econstr_env env sigma c
-(** We need an object to record the side-effect of registering
- global universes associated with a hint. *)
-let cache_context_set (_,c) =
- Global.push_context_set false c
-
-let input_context_set : Univ.ContextSet.t -> Libobject.obj =
- let open Libobject in
- declare_object
- { (default_object "Global universe context") with
- cache_function = cache_context_set;
- load_function = (fun _ -> cache_context_set);
- discharge_function = (fun (_,a) -> Some a);
- classify_function = (fun a -> Keep a) }
-
let warn_polymorphic_hint =
CWarnings.create ~name:"polymorphic-hint" ~category:"automation"
(fun hint -> strbrk"Using polymorphic hint " ++ hint ++
@@ -904,7 +905,7 @@ let fresh_global_or_constr env sigma poly cr =
else begin
if isgr then
warn_polymorphic_hint (pr_hint_term env sigma ctx cr);
- Lib.add_anonymous_leaf (input_context_set ctx);
+ Declare.declare_universe_context false ctx;
(c, Univ.ContextSet.empty)
end
@@ -1014,15 +1015,19 @@ let add_hint dbname hintlist =
let db' = Hint_db.add_list env sigma hintlist db in
searchtable_add (dbname,db')
-let add_transparency dbname grs b =
+let add_transparency dbname target b =
let db = get_db dbname in
- let st = Hint_db.transparent_state db in
+ let (ids, csts as st) = Hint_db.transparent_state db in
let st' =
- List.fold_left (fun (ids, csts) gr ->
- match gr with
- | EvalConstRef c -> (ids, (if b then Cpred.add else Cpred.remove) c csts)
- | EvalVarRef v -> (if b then Id.Pred.add else Id.Pred.remove) v ids, csts)
- st grs
+ match target with
+ | HintsVariables -> (if b then Id.Pred.full else Id.Pred.empty), csts
+ | HintsConstants -> ids, if b then Cpred.full else Cpred.empty
+ | HintsReferences grs ->
+ List.fold_left (fun (ids, csts) gr ->
+ match gr with
+ | EvalConstRef c -> (ids, (if b then Cpred.add else Cpred.remove) c csts)
+ | EvalVarRef v -> (if b then Id.Pred.add else Id.Pred.remove) v ids, csts)
+ st grs
in searchtable_add (dbname, Hint_db.set_transparent_state db st')
let remove_hint dbname grs =
@@ -1032,7 +1037,7 @@ let remove_hint dbname grs =
type hint_action =
| CreateDB of bool * transparent_state
- | AddTransparency of evaluable_global_reference list * bool
+ | AddTransparency of evaluable_global_reference hints_transparency_target * bool
| AddHints of hint_entry list
| RemoveHints of GlobRef.t list
| AddCut of hints_path
@@ -1122,9 +1127,17 @@ let subst_autohint (subst, obj) =
in
let action = match obj.hint_action with
| CreateDB _ -> obj.hint_action
- | AddTransparency (grs, b) ->
- let grs' = List.Smart.map (subst_evaluable_reference subst) grs in
- if grs == grs' then obj.hint_action else AddTransparency (grs', b)
+ | AddTransparency (target, b) ->
+ let target' =
+ match target with
+ | HintsVariables -> target
+ | HintsConstants -> target
+ | HintsReferences grs ->
+ let grs' = List.Smart.map (subst_evaluable_reference subst) grs in
+ if grs == grs' then target
+ else HintsReferences grs'
+ in
+ if target' == target then obj.hint_action else AddTransparency (target', b)
| AddHints hintlist ->
let hintlist' = List.Smart.map subst_hint hintlist in
if hintlist' == hintlist then obj.hint_action else AddHints hintlist'
@@ -1244,7 +1257,7 @@ type hints_entry =
| HintsImmediateEntry of (hints_path_atom * polymorphic * hint_term) list
| HintsCutEntry of hints_path
| HintsUnfoldEntry of evaluable_global_reference list
- | HintsTransparencyEntry of evaluable_global_reference list * bool
+ | HintsTransparencyEntry of evaluable_global_reference hints_transparency_target * bool
| HintsModeEntry of GlobRef.t * hint_mode list
| HintsExternEntry of hint_info * Genarg.glob_generic_argument
@@ -1288,7 +1301,7 @@ let prepare_hint check (poly,local) env init (sigma,c) =
let diff = Univ.ContextSet.diff (Evd.universe_context_set sigma) (Evd.universe_context_set init) in
if poly then IsConstr (c', diff)
else if local then IsConstr (c', diff)
- else (Lib.add_anonymous_leaf (input_context_set diff);
+ else (Declare.declare_universe_context false diff;
IsConstr (c', Univ.ContextSet.empty))
let project_hint ~poly pri l2r r =
@@ -1347,14 +1360,19 @@ let interp_hints poly =
let info = { info with hint_pattern = Option.map fp info.hint_pattern } in
(info, poly, b, path, gr)
in
+ let ft = function
+ | HintsVariables -> HintsVariables
+ | HintsConstants -> HintsConstants
+ | HintsReferences lhints -> HintsReferences (List.map fr lhints)
+ in
+ let fp = Constrintern.intern_constr_pattern (Global.env()) in
match h with
| HintsResolve lhints -> HintsResolveEntry (List.map fres lhints)
| HintsResolveIFF (l2r, lc, n) ->
HintsResolveEntry (List.map (project_hint ~poly n l2r) lc)
| HintsImmediate lhints -> HintsImmediateEntry (List.map fi lhints)
| HintsUnfold lhints -> HintsUnfoldEntry (List.map fr lhints)
- | HintsTransparency (lhints, b) ->
- HintsTransparencyEntry (List.map fr lhints, b)
+ | HintsTransparency (t, b) -> HintsTransparencyEntry (ft t, b)
| HintsMode (r, l) -> HintsModeEntry (fref r, l)
| HintsConstructors lqid ->
let constr_hints_of_ind qid =
@@ -1369,7 +1387,7 @@ let interp_hints poly =
PathHints [gr], IsGlobRef gr)
in HintsResolveEntry (List.flatten (List.map constr_hints_of_ind lqid))
| HintsExtern (pri, patcom, tacexp) ->
- let pat = Option.map fp patcom in
+ let pat = Option.map (fp sigma) patcom in
let l = match pat with None -> [] | Some (l, _) -> l in
let ltacvars = List.fold_left (fun accu x -> Id.Set.add x accu) Id.Set.empty l in
let env = Genintern.({ (empty_glob_sign env) with ltacvars }) in
diff --git a/tactics/hints.mli b/tactics/hints.mli
index ca18f835a5..9bf6c175a5 100644
--- a/tactics/hints.mli
+++ b/tactics/hints.mli
@@ -81,12 +81,17 @@ type hint_mode =
| ModeNoHeadEvar (* No evar at the head *)
| ModeOutput (* Anything *)
+type 'a hints_transparency_target =
+ | HintsVariables
+ | HintsConstants
+ | HintsReferences of 'a list
+
type hints_expr =
| HintsResolve of (hint_info_expr * bool * reference_or_constr) list
| HintsResolveIFF of bool * Libnames.qualid list * int option
| HintsImmediate of reference_or_constr list
| HintsUnfold of Libnames.qualid list
- | HintsTransparency of Libnames.qualid list * bool
+ | HintsTransparency of Libnames.qualid hints_transparency_target * bool
| HintsMode of Libnames.qualid * hint_mode list
| HintsConstructors of Libnames.qualid list
| HintsExtern of int * Constrexpr.constr_expr option * Genarg.raw_generic_argument
@@ -173,7 +178,7 @@ type hints_entry =
| HintsImmediateEntry of (hints_path_atom * polymorphic * hint_term) list
| HintsCutEntry of hints_path
| HintsUnfoldEntry of evaluable_global_reference list
- | HintsTransparencyEntry of evaluable_global_reference list * bool
+ | HintsTransparencyEntry of evaluable_global_reference hints_transparency_target * bool
| HintsModeEntry of GlobRef.t * hint_mode list
| HintsExternEntry of hint_info * Genarg.glob_generic_argument
diff --git a/tactics/hipattern.ml b/tactics/hipattern.ml
index f9c4bed352..7da059ae35 100644
--- a/tactics/hipattern.ml
+++ b/tactics/hipattern.ml
@@ -263,7 +263,9 @@ open Evar_kinds
let mkPattern c = snd (Patternops.pattern_of_glob_constr c)
let mkGApp f args = DAst.make @@ GApp (f, args)
let mkGHole = DAst.make @@
- GHole (QuestionMark (Define false,Anonymous), Namegen.IntroAnonymous, None)
+ GHole (QuestionMark {
+ Evar_kinds.default_question_mark with Evar_kinds.qm_obligation=Define false;
+ }, Namegen.IntroAnonymous, None)
let mkGProd id c1 c2 = DAst.make @@
GProd (Name (Id.of_string id), Explicit, c1, c2)
let mkGArrow c1 c2 = DAst.make @@
diff --git a/tactics/inv.ml b/tactics/inv.ml
index 755494c2d2..43786c8e19 100644
--- a/tactics/inv.ml
+++ b/tactics/inv.ml
@@ -94,7 +94,7 @@ let make_inv_predicate env evd indf realargs id status concl =
| Some concl -> concl (*assumed it's some [x1..xn,H:I(x1..xn)]C*)
| None ->
let sort = get_sort_family_of env !evd concl in
- let sort = Evarutil.evd_comb1 (Evd.fresh_sort_in_family env) evd sort in
+ let sort = Evarutil.evd_comb1 Evd.fresh_sort_in_family evd sort in
let p = make_arity env !evd true indf sort in
let evd',(p,ptyp) = Unification.abstract_list_all env
!evd p concl (realargs@[mkVar id])
@@ -495,7 +495,7 @@ let raw_inversion inv_kind id status names =
(* Error messages of the inversion tactics *)
let wrap_inv_error id = function (e, info) -> match e with
| Indrec.RecursionSchemeError
- (Indrec.NotAllowedCaseAnalysis (_,(Type _ | Prop Pos as k),i)) ->
+ (Indrec.NotAllowedCaseAnalysis (_,(Type _ | Set as k),i)) ->
Proofview.tclENV >>= fun env ->
Proofview.tclEVARMAP >>= fun sigma ->
tclZEROMSG (
diff --git a/tactics/leminv.ml b/tactics/leminv.ml
index 10937322e7..caf4c1eca3 100644
--- a/tactics/leminv.ml
+++ b/tactics/leminv.ml
@@ -251,7 +251,7 @@ let add_inversion_lemma_exn ~poly na com comsort bool tac =
let env = Global.env () in
let sigma = Evd.from_env env in
let sigma, c = Constrintern.interp_type_evars env sigma com in
- let sigma, sort = Evd.fresh_sort_in_family ~rigid:univ_rigid env sigma comsort in
+ let sigma, sort = Evd.fresh_sort_in_family ~rigid:univ_rigid sigma comsort in
try
add_inversion_lemma ~poly na env sigma c sort bool tac
with
diff --git a/tactics/tactics.ml b/tactics/tactics.ml
index 2a9d89fe5b..2d02c3ca6e 100644
--- a/tactics/tactics.ml
+++ b/tactics/tactics.ml
@@ -212,6 +212,9 @@ let clear_dependency_msg env sigma id err inglobal =
str "Cannot remove " ++ Id.print id ++
strbrk " without breaking the typing of " ++
Printer.pr_existential env sigma ev ++ str"."
+ | Evarutil.NoCandidatesLeft ev ->
+ str "Cannot remove " ++ Id.print id ++ str " as it would leave the existential " ++
+ Printer.pr_existential_key sigma ev ++ str" without candidates."
let error_clear_dependency env sigma id err inglobal =
user_err (clear_dependency_msg env sigma id err inglobal)
@@ -228,6 +231,9 @@ let replacing_dependency_msg env sigma id err inglobal =
str "Cannot change " ++ Id.print id ++
strbrk " without breaking the typing of " ++
Printer.pr_existential env sigma ev ++ str"."
+ | Evarutil.NoCandidatesLeft ev ->
+ str "Cannot change " ++ Id.print id ++ str " as it would leave the existential " ++
+ Printer.pr_existential_key sigma ev ++ str" without candidates."
let error_replacing_dependency env sigma id err inglobal =
user_err (replacing_dependency_msg env sigma id err inglobal)
@@ -1575,9 +1581,10 @@ let make_projection env sigma params cstr sign elim i n c u =
| Some proj ->
let args = Context.Rel.to_extended_vect mkRel 0 sign in
let proj =
- if Environ.is_projection proj env then
+ match Recordops.find_primitive_projection proj with
+ | Some proj ->
mkProj (Projection.make proj false, mkApp (c, args))
- else
+ | None ->
mkApp (mkConstU (proj,u), Array.append (Array.of_list params)
[|mkApp (c, args)|])
in
@@ -5056,6 +5063,7 @@ let constr_eq ~strict x y =
let unify ?(state=full_transparent_state) x y =
Proofview.Goal.enter begin fun gl ->
+ let env = Proofview.Goal.env gl in
let sigma = Proofview.Goal.sigma gl in
try
let core_flags =
@@ -5071,7 +5079,7 @@ let unify ?(state=full_transparent_state) x y =
let sigma = w_unify (Tacmach.New.pf_env gl) sigma Reduction.CONV ~flags x y in
Proofview.Unsafe.tclEVARS sigma
with e when CErrors.noncritical e ->
- Tacticals.New.tclFAIL 0 (str"Not unifiable")
+ Proofview.tclZERO (PretypeError (env, sigma, CannotUnify (x, y, None)))
end
module Simple = struct
diff --git a/test-suite/Makefile b/test-suite/Makefile
index 32e245e362..b8aac8b6f8 100644
--- a/test-suite/Makefile
+++ b/test-suite/Makefile
@@ -192,10 +192,6 @@ 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
@@ -519,6 +515,7 @@ $(patsubst %.sh,%.log,$(wildcard misc/*.sh)): %.log: %.sh $(PREREQUISITELOG)
@echo "TEST $<"
$(HIDE){ \
echo $(call log_intro,$<); \
+ export BIN="$(BIN)"; \
export coqc="$(coqc)"; \
export coqtop="$(coqtop)"; \
export coqdep="$(coqdep)"; \
diff --git a/test-suite/bugs/closed/2733.v b/test-suite/bugs/closed/2733.v
index 832de4f913..24dd30b32e 100644
--- a/test-suite/bugs/closed/2733.v
+++ b/test-suite/bugs/closed/2733.v
@@ -16,6 +16,21 @@ match k,l with
|B,l' => Bcons true (Ncons 0 l')
end.
+(* At some time, the success of trullynul was dependent on the name of
+ the variables! *)
+
+Definition trullynul2 k {a} (l : alt_list k a) :=
+match k,l with
+ |N,l' => Ncons 0 (Bcons true l')
+ |B,l' => Bcons true (Ncons 0 l')
+end.
+
+Definition trullynul3 k {z} (l : alt_list k z) :=
+match k,l with
+ |N,l' => Ncons 0 (Bcons true l')
+ |B,l' => Bcons true (Ncons 0 l')
+end.
+
Fixpoint app (P : forall {k k'}, alt_list k k' -> alt_list k k') {t1 t2} (l : alt_list t1 t2) {struct l}: forall {t3}, alt_list t2 t3 ->
alt_list t1 t3 :=
match l with
diff --git a/test-suite/bugs/closed/4202.v b/test-suite/bugs/closed/4202.v
new file mode 100644
index 0000000000..522a3604a3
--- /dev/null
+++ b/test-suite/bugs/closed/4202.v
@@ -0,0 +1,10 @@
+Parameter g : nat -> Prop.
+Axiom a : forall n, g (S n).
+Lemma foo (H : True) : exists n, g n /\ g n.
+eexists.
+clear H.
+split.
+simple apply a.
+(* goal is "g (S ?Goal0@ {H:=H})" while H has long ceased to exist *)
+simpl.
+Abort.
diff --git a/test-suite/bugs/closed/5012.v b/test-suite/bugs/closed/5012.v
new file mode 100644
index 0000000000..5326c0fbb1
--- /dev/null
+++ b/test-suite/bugs/closed/5012.v
@@ -0,0 +1,17 @@
+Class Foo := { foo : Set }.
+
+Axiom admit : forall {T}, T.
+
+Global Instance Foo0 : Foo
+ := {| foo := admit |}.
+
+Global Instance Foo1 : Foo
+ := { foo := admit }.
+
+Existing Class Foo.
+
+Global Instance Foo2 : Foo
+ := { foo := admit }. (* Error: Unbound method name foo of class Foo. *)
+
+Set Warnings "+already-existing-class".
+Fail Existing Class Foo.
diff --git a/test-suite/bugs/closed/5696.v b/test-suite/bugs/closed/5696.v
new file mode 100644
index 0000000000..a20ad1b4da
--- /dev/null
+++ b/test-suite/bugs/closed/5696.v
@@ -0,0 +1,5 @@
+(* Slightly improving interpretation of Ltac subterms in notations *)
+
+Notation "'var2' x .. y = z ; e" := (ltac:(exact z), (fun x => .. (fun y => e)
+..)) (at level 200, x binder, y binder, e at level 220).
+Check (var2 a = 1; a).
diff --git a/test-suite/bugs/closed/5719.v b/test-suite/bugs/closed/5719.v
new file mode 100644
index 0000000000..0fad5f54ea
--- /dev/null
+++ b/test-suite/bugs/closed/5719.v
@@ -0,0 +1,9 @@
+Axiom cons_data_one :
+ forall (Aone : unit -> Set) (i : unit) (a : Aone i), nat.
+Axiom P : nat -> Prop.
+Axiom children_data_rect3 : forall {Aone : unit -> Set}
+ (cons_one_case : forall (i : unit) (b : Aone i),
+ nat -> nat -> P (cons_data_one Aone i b)),
+ P 0.
+Fail Definition decide_children_equality IH := children_data_rect3
+ (fun _ '(existT _ _ _) => match IH with tt => _ end).
diff --git a/test-suite/bugs/closed/7695.v b/test-suite/bugs/closed/7695.v
new file mode 100644
index 0000000000..42bdb076b6
--- /dev/null
+++ b/test-suite/bugs/closed/7695.v
@@ -0,0 +1,20 @@
+Require Import Hurkens.
+
+Universes i j k.
+Module Type T.
+ Parameter T1 : Type@{i+1}.
+ Parameter e : Type@{j} = T1 : Type@{k}.
+End T.
+
+Module M.
+ Definition T1 := Type@{j}.
+ Definition e : Type@{j} = T1 : Type@{k} := eq_refl.
+End M.
+
+Module F (A:T).
+ Definition bad := TypeNeqSmallType.paradox _ A.e.
+End F.
+
+Set Printing Universes.
+Fail Module X := F M.
+(* Universe inconsistency. Cannot enforce j <= i because i < Coq.Logic.Hurkens.105 = j. *)
diff --git a/test-suite/bugs/closed/7712.v b/test-suite/bugs/closed/7712.v
new file mode 100644
index 0000000000..a4e9697fad
--- /dev/null
+++ b/test-suite/bugs/closed/7712.v
@@ -0,0 +1,4 @@
+(* This used to raise an anomaly *)
+
+Fail Reserved Notation "'[tele_arg' x ';' .. ';' z ]"
+ (format "[tele_arg '[hv' x .. z ']' ]").
diff --git a/test-suite/bugs/closed/7723.v b/test-suite/bugs/closed/7723.v
new file mode 100644
index 0000000000..2162901231
--- /dev/null
+++ b/test-suite/bugs/closed/7723.v
@@ -0,0 +1,58 @@
+Set Universe Polymorphism.
+
+Module Segfault.
+
+Inductive decision_tree : Type := .
+
+Fixpoint first_satisfying_helper {A B} (f : A -> option B) (ls : list A) : option B
+ := match ls with
+ | nil => None
+ | cons x xs
+ => match f x with
+ | Some v => Some v
+ | None => first_satisfying_helper f xs
+ end
+ end.
+
+Axiom admit : forall {T}, T.
+Definition dtree4 : option decision_tree :=
+ match first_satisfying_helper (fun pat : nat => Some pat) (cons 0 nil)
+ with
+ | Some _ => admit
+ | None => admit
+ end
+.
+Definition dtree'' := Eval vm_compute in dtree4. (* segfault *)
+
+End Segfault.
+
+Module OtherExample.
+
+Definition bar@{i} := Type@{i}.
+Definition foo@{i j} (x y z : nat) :=
+ @id Type@{j} bar@{i}.
+Eval vm_compute in foo.
+
+End OtherExample.
+
+Module LocalClosure.
+
+Definition bar@{i} := Type@{i}.
+
+Definition foo@{i j} (x y z : nat) :=
+ @id (nat -> Type@{j}) (fun _ => Type@{i}).
+Eval vm_compute in foo.
+
+End LocalClosure.
+
+Require Import Hurkens.
+Polymorphic Inductive unit := tt.
+
+Polymorphic Definition foo :=
+ let x := id tt in (x, x, Type).
+
+Lemma bad : False.
+ refine (TypeNeqSmallType.paradox (snd foo) _).
+ vm_compute.
+ Fail reflexivity.
+Abort.
diff --git a/test-suite/bugs/closed/7854.v b/test-suite/bugs/closed/7854.v
new file mode 100644
index 0000000000..ab1a29b632
--- /dev/null
+++ b/test-suite/bugs/closed/7854.v
@@ -0,0 +1,10 @@
+Set Primitive Projections.
+
+CoInductive stream (A : Type) := cons {
+ hd : A;
+ tl : stream A;
+}.
+
+CoFixpoint const {A} (x : A) := cons A x (const x).
+
+Check (@eq_refl _ (const tt) <<: tl unit (const tt) = const tt).
diff --git a/test-suite/bugs/closed/7867.v b/test-suite/bugs/closed/7867.v
new file mode 100644
index 0000000000..d0c7902756
--- /dev/null
+++ b/test-suite/bugs/closed/7867.v
@@ -0,0 +1,4 @@
+(* Was a printer anomaly due to an internal lambda with no binders *)
+
+Class class := { foo : nat }.
+Fail Instance : class := { foo := 0 ; bar := 0 }.
diff --git a/test-suite/bugs/closed/7903.v b/test-suite/bugs/closed/7903.v
new file mode 100644
index 0000000000..55c7ee99a7
--- /dev/null
+++ b/test-suite/bugs/closed/7903.v
@@ -0,0 +1,4 @@
+(* Slightly improving interpretation of Ltac subterms in notations *)
+
+Notation bar x f := (let z := ltac:(exact 1) in (fun x : nat => f)).
+Check bar x (x + x).
diff --git a/test-suite/bugs/closed/8004.v b/test-suite/bugs/closed/8004.v
new file mode 100644
index 0000000000..818639997a
--- /dev/null
+++ b/test-suite/bugs/closed/8004.v
@@ -0,0 +1,47 @@
+Require Export Coq.Program.Tactics Coq.Classes.SetoidTactics Coq.Classes.CMorphisms .
+
+Set Universe Polymorphism.
+
+Delimit Scope category_theory_scope with category_theory.
+Open Scope category_theory_scope.
+
+Infix "∧" := prod (at level 80, right associativity) : category_theory_scope.
+
+Class Setoid A := {
+ equiv : crelation A;
+ setoid_equiv :> Equivalence equiv
+}.
+
+Notation "f ≈ g" := (equiv f g) (at level 79) : category_theory_scope.
+
+Open Scope list_scope.
+
+Generalizable All Variables.
+
+Fixpoint list_equiv `{Setoid A} (xs ys : list A) : Type :=
+ match xs, ys with
+ | nil, nil => True
+ | x :: xs, y :: ys => x ≈ y ∧ list_equiv xs ys
+ | _, _ => False
+ end.
+
+Axiom proof_admitted : False.
+Tactic Notation "admit" := abstract case proof_admitted.
+
+Program Instance list_equivalence `{Setoid A} : Equivalence list_equiv.
+Next Obligation.
+ repeat intro.
+ induction x; simpl; split; auto.
+ reflexivity.
+Qed.
+Next Obligation.
+ repeat intro.
+ generalize dependent y.
+ induction x, y; simpl; intros; auto.
+ destruct X; split.
+ now symmetry.
+ intuition.
+Qed.
+Next Obligation.
+admit.
+Defined.
diff --git a/test-suite/bugs/closed/8081.v b/test-suite/bugs/closed/8081.v
new file mode 100644
index 0000000000..0f2501aaa8
--- /dev/null
+++ b/test-suite/bugs/closed/8081.v
@@ -0,0 +1,4 @@
+Section foo.
+End foo.
+Section foo.
+End foo.
diff --git a/test-suite/bugs/closed/8106.v b/test-suite/bugs/closed/8106.v
new file mode 100644
index 0000000000..a711c5adef
--- /dev/null
+++ b/test-suite/bugs/closed/8106.v
@@ -0,0 +1,4 @@
+(* Was raising an anomaly "already assigned a level" on the second line *)
+
+Notation "c1 ; c2" := (c1 + c2) (only printing, at level 76, right associativity, c1 at level 76, c2 at level 76).
+Notation "c1 ; c2" := (c1 + c2) (only parsing, at level 76, right associativity, c2 at level 76).
diff --git a/test-suite/bugs/closed/8119.v b/test-suite/bugs/closed/8119.v
new file mode 100644
index 0000000000..c6329a7328
--- /dev/null
+++ b/test-suite/bugs/closed/8119.v
@@ -0,0 +1,46 @@
+Require Import Coq.Strings.String.
+
+Section T.
+ Eval vm_compute in let x := tt in _.
+(* Error: Anomaly "Uncaught exception Constr.DestKO." Please report at http://coq.inria.fr/bugs/. *)
+ Eval vm_compute in let _ := Set in _.
+(* Error: Anomaly "Uncaught exception Constr.DestKO." Please report at http://coq.inria.fr/bugs/. *)
+ Eval vm_compute in let _ := Prop in _.
+(* Error: Anomaly "Uncaught exception Constr.DestKO." Please report at http://coq.inria.fr/bugs/. *)
+End T.
+
+Section U0.
+ Let n : unit := tt.
+ Eval vm_compute in _.
+(* Error: Anomaly "Uncaught exception Constr.DestKO." Please report at http://coq.inria.fr/bugs/. *)
+ Goal exists tt : unit, tt = tt. eexists. vm_compute. Abort.
+(* Error: Anomaly "Uncaught exception Constr.DestKO." Please report at http://coq.inria.fr/bugs/. *)
+End U0.
+
+Section S0.
+ Let LF : string := String (Coq.Strings.Ascii.Ascii false true false true false false false false) "".
+ Eval vm_compute in _.
+(* Error: Anomaly "Uncaught exception Constr.DestKO." Please report at http://coq.inria.fr/bugs/. *)
+ Goal exists tt : unit, tt = tt. eexists. vm_compute. Abort.
+(* Error: Anomaly "Uncaught exception Constr.DestKO." Please report at http://coq.inria.fr/bugs/. *)
+End S0.
+
+Class T := { }.
+Section S1.
+ Context {p : T}.
+ Let LF : string := String (Coq.Strings.Ascii.Ascii false true false true false false false false) "".
+ Eval vm_compute in _.
+(* Error: Anomaly "Uncaught exception Not_found." Please report at http://coq.inria.fr/bugs/. *)
+ Goal exists tt : unit, tt = tt. eexists. vm_compute. Abort.
+(* Error: Anomaly "Uncaught exception Not_found." Please report at http://coq.inria.fr/bugs/. *)
+End S1.
+
+Class M := { m : Type }.
+Section S2.
+ Context {p : M}.
+ Let LF : string := String (Coq.Strings.Ascii.Ascii false true false true false false false false) "".
+ Eval vm_compute in _.
+(* Error: Anomaly "File "pretyping/vnorm.ml", line 60, characters 9-15: Assertion failed." *)
+ Goal exists tt : unit, tt = tt. eexists. vm_compute. Abort.
+(* Error: Anomaly "File "pretyping/vnorm.ml", line 60, characters 9-15: Assertion failed." *)
+End S2.
diff --git a/test-suite/bugs/closed/8126.v b/test-suite/bugs/closed/8126.v
new file mode 100644
index 0000000000..f52dfc6b47
--- /dev/null
+++ b/test-suite/bugs/closed/8126.v
@@ -0,0 +1,13 @@
+(* See also output test Notations4.v *)
+
+Inductive foo := tt.
+Bind Scope foo_scope with foo.
+Delimit Scope foo_scope with foo.
+Notation "'HI'" := tt : foo_scope.
+Definition myfoo (x : nat) (y : nat) (z : foo) := y.
+Notation myfoo0 := (@myfoo 0).
+Notation myfoo01 := (@myfoo0 1).
+Check myfoo 0 1 HI. (* prints [myfoo0 1 HI], but should print [myfoo01 HI] *)
+Check myfoo0 1 HI. (* prints [myfoo0 1 HI], but should print [myfoo01 HI] *)
+Check myfoo01 tt. (* prints [myfoo0 1 HI], but should print [myfoo01 HI] *)
+Check myfoo01 HI. (* was failing *)
diff --git a/test-suite/coq-makefile/timing/after/time-of-build-both.log.desired b/test-suite/coq-makefile/timing/after/time-of-build-both.log.desired
index 56815d241e..72c520218c 100644
--- a/test-suite/coq-makefile/timing/after/time-of-build-both.log.desired
+++ b/test-suite/coq-makefile/timing/after/time-of-build-both.log.desired
@@ -1,6 +1,6 @@
After | File Name | Before || Change | % Change
--------------------------------------------------------
-0m00.38s | Total | 0m00.39s || -0m00.01s | -2.56%
+0m00.34s | Total | 0m00.49s || -0m00.14s | -30.61%
--------------------------------------------------------
-0m00.35s | Slow | 0m00.02s || +0m00.32s | +1649.99%
-0m00.03s | Fast | 0m00.37s || -0m00.34s | -91.89% \ No newline at end of file
+0m00.32s | Fast | 0m00.02s || +0m00.30s | +1500.00%
+0m00.02s | Slow | 0m00.47s || -0m00.44s | -95.74% \ No newline at end of file
diff --git a/test-suite/coq-makefile/timing/per-file-after/A.v.timing.diff.desired b/test-suite/coq-makefile/timing/per-file-after/A.v.timing.diff.desired
index 18f0f34b28..74dad73332 100644
--- a/test-suite/coq-makefile/timing/per-file-after/A.v.timing.diff.desired
+++ b/test-suite/coq-makefile/timing/per-file-after/A.v.timing.diff.desired
@@ -1,9 +1,9 @@
-After | Code | Before || Change | % Change
----------------------------------------------------------------------------------------------------
-0m00.50s | Total | 0m04.17s || -0m03.66s | -87.96%
----------------------------------------------------------------------------------------------------
-0m00.145s | Chars 069 - 162 [Definition~foo0~:=~Eval~comp~i...] | 0m00.192s || -0m00.04s | -24.47%
-0m00.126s | Chars 000 - 026 [Require~Coq.ZArith.BinInt.] | 0m00.143s || -0m00.01s | -11.88%
- N/A | Chars 027 - 068 [Declare~Reduction~comp~:=~nati...] | 0m00.s || +0m00.00s | N/A
-0m00.s | Chars 027 - 068 [Declare~Reduction~comp~:=~vm_c...] | N/A || +0m00.00s | N/A
-0m00.231s | Chars 163 - 208 [Definition~foo1~:=~Eval~comp~i...] | 0m03.836s || -0m03.60s | -93.97% \ No newline at end of file
+After | Code | Before || Change | % Change
+----------------------------------------------------------------------------------------------------
+0m04.35s | Total | 0m00.58s || +0m03.77s | +649.05%
+----------------------------------------------------------------------------------------------------
+0m03.87s | Chars 163 - 208 [Definition~foo1~:=~Eval~comp~i...] | 0m00.246s || +0m03.62s | +1473.17%
+0m00.322s | Chars 069 - 162 [Definition~foo0~:=~Eval~comp~i...] | 0m00.189s || +0m00.13s | +70.37%
+0m00.16s | Chars 000 - 026 [Require~Coq.ZArith.BinInt.] | 0m00.146s || +0m00.01s | +9.58%
+0m00.s | Chars 027 - 068 [Declare~Reduction~comp~:=~nati...] | N/A || +0m00.00s | N/A
+ N/A | Chars 027 - 068 [Declare~Reduction~comp~:=~vm_c...] | 0m00.s || +0m00.00s | N/A \ No newline at end of file
diff --git a/test-suite/coq-makefile/timing/precomputed-time-tests/001-correct-diff-sorting-order/time-of-build-both.log.expected b/test-suite/coq-makefile/timing/precomputed-time-tests/001-correct-diff-sorting-order/time-of-build-both.log.expected
index 975e359b78..159e645512 100644
--- a/test-suite/coq-makefile/timing/precomputed-time-tests/001-correct-diff-sorting-order/time-of-build-both.log.expected
+++ b/test-suite/coq-makefile/timing/precomputed-time-tests/001-correct-diff-sorting-order/time-of-build-both.log.expected
@@ -1,6 +1,6 @@
After | File Name | Before || Change | % Change
----------------------------------------------------------------------------------------------
-19m16.05s | Total | 21m25.28s || -2m09.23s | -10.05%
+19m16.04s | Total | 21m25.27s || -2m09.23s | -10.05%
----------------------------------------------------------------------------------------------
4m01.34s | Specific/X25519/C64/ladderstep | 4m59.49s || -0m58.15s | -19.41%
2m48.52s | Specific/solinas32_2e255m765_13limbs/femul | 3m12.95s || -0m24.42s | -12.66%
diff --git a/test-suite/coq-makefile/timing/precomputed-time-tests/002-single-file-sorting/time-of-build-pretty.log.expected b/test-suite/coq-makefile/timing/precomputed-time-tests/002-single-file-sorting/time-of-build-pretty.log.expected
index fdd5ec21d6..b9739ddb1d 100644
--- a/test-suite/coq-makefile/timing/precomputed-time-tests/002-single-file-sorting/time-of-build-pretty.log.expected
+++ b/test-suite/coq-makefile/timing/precomputed-time-tests/002-single-file-sorting/time-of-build-pretty.log.expected
@@ -1,6 +1,6 @@
Time | File Name
----------------------------------------------------------
-19m16.05s | Total
+19m16.04s | Total
----------------------------------------------------------
4m01.34s | Specific/X25519/C64/ladderstep
3m09.62s | Specific/NISTP256/AMD64/femul
diff --git a/test-suite/coq-makefile/timing/run.sh b/test-suite/coq-makefile/timing/run.sh
index 6737197ee4..78a3f7c63a 100755
--- a/test-suite/coq-makefile/timing/run.sh
+++ b/test-suite/coq-makefile/timing/run.sh
@@ -5,6 +5,10 @@ set -e
. ../template/path-init.sh
+# reset MAKEFLAGS so that, e.g., `make -C test-suite -B coq-makefile` doesn't give us issues
+
+MAKEFLAGS=
+
cd precomputed-time-tests
./run.sh || exit $?
diff --git a/test-suite/coqchk/include_primproj.v b/test-suite/coqchk/include_primproj.v
new file mode 100644
index 0000000000..804ba1d378
--- /dev/null
+++ b/test-suite/coqchk/include_primproj.v
@@ -0,0 +1,13 @@
+(* #7329 *)
+Set Primitive Projections.
+
+Module M.
+ Module Bar.
+ Record Box := box { unbox : Type }.
+
+ Axiom foo : Box.
+ Axiom baz : forall _ : unbox foo, unbox foo.
+ End Bar.
+End M.
+
+Include M.
diff --git a/test-suite/coqdoc/links.html.out b/test-suite/coqdoc/links.html.out
index 5e4b676c2f..d2d4d5d764 100644
--- a/test-suite/coqdoc/links.html.out
+++ b/test-suite/coqdoc/links.html.out
@@ -60,32 +60,32 @@ Various checks for coqdoc
<span class="id" title="keyword">Definition</span> <a name="f"><span class="id" title="definition">f</span></a> := <span class="id" title="keyword">∀</span> <span class="id" title="var">C</span>:<span class="id" title="keyword">Prop</span>, <a class="idref" href="Coqdoc.links.html#C"><span class="id" title="variable">C</span></a>.<br/>
<br/>
-<span class="id" title="keyword">Notation</span> <a name="1a1c7f13320341c3638e9edcc3e6389d"><span class="id" title="notation">&quot;</span></a>n ++ m" := (<a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Peano.html#plus"><span class="id" title="abbreviation">plus</span></a> <span class="id" title="var">n</span> <span class="id" title="var">m</span>).<br/>
+<span class="id" title="keyword">Notation</span> <a name="f03f7a04ef75ff3ac66ca5c23554e52e"><span class="id" title="notation">&quot;</span></a>n ++ m" := (<a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Peano.html#plus"><span class="id" title="abbreviation">plus</span></a> <span class="id" title="var">n</span> <span class="id" title="var">m</span>).<br/>
<br/>
-<span class="id" title="keyword">Notation</span> <a name="1a1c7f13320341c3638e9edcc3e6389d"><span class="id" title="notation">&quot;</span></a>n ++ m" := (<a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Peano.html#mult"><span class="id" title="abbreviation">mult</span></a> <span class="id" title="var">n</span> <span class="id" title="var">m</span>).
+<span class="id" title="keyword">Notation</span> <a name="f03f7a04ef75ff3ac66ca5c23554e52e"><span class="id" title="notation">&quot;</span></a>n ++ m" := (<a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Peano.html#mult"><span class="id" title="abbreviation">mult</span></a> <span class="id" title="var">n</span> <span class="id" title="var">m</span>).
<br/>
-<span class="id" title="keyword">Notation</span> <a name="6b97e27793a3d22f5c0d1dd63170fd68"><span class="id" title="notation">&quot;</span></a>n ** m" := (<a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Peano.html#plus"><span class="id" title="abbreviation">plus</span></a> <span class="id" title="var">n</span> <span class="id" title="var">m</span>) (<span class="id" title="tactic">at</span> <span class="id" title="keyword">level</span> 60).<br/>
+<span class="id" title="keyword">Notation</span> <a name="f07b3676d96b68749d342542fd80e2b0"><span class="id" title="notation">&quot;</span></a>n ** m" := (<a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Peano.html#plus"><span class="id" title="abbreviation">plus</span></a> <span class="id" title="var">n</span> <span class="id" title="var">m</span>) (<span class="id" title="tactic">at</span> <span class="id" title="keyword">level</span> 60).<br/>
<br/>
-<span class="id" title="keyword">Notation</span> <a name="3e01fbae4590c7b7699ff99ce61580e1"><span class="id" title="notation">&quot;</span></a>n ▵ m" := (<a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Peano.html#plus"><span class="id" title="abbreviation">plus</span></a> <span class="id" title="var">n</span> <span class="id" title="var">m</span>) (<span class="id" title="tactic">at</span> <span class="id" title="keyword">level</span> 60).<br/>
+<span class="id" title="keyword">Notation</span> <a name="a647c51c9816a1b44fcfa5312db8344a"><span class="id" title="notation">&quot;</span></a>n ▵ m" := (<a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Peano.html#plus"><span class="id" title="abbreviation">plus</span></a> <span class="id" title="var">n</span> <span class="id" title="var">m</span>) (<span class="id" title="tactic">at</span> <span class="id" title="keyword">level</span> 60).<br/>
<br/>
-<span class="id" title="keyword">Notation</span> <a name="347f39a83bf7d45676cff54fd7e8966f"><span class="id" title="notation">&quot;</span></a>n '_' ++ 'x' m" := (<a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Peano.html#plus"><span class="id" title="abbreviation">plus</span></a> <span class="id" title="var">n</span> <span class="id" title="var">m</span>) (<span class="id" title="tactic">at</span> <span class="id" title="keyword">level</span> 3).<br/>
+<span class="id" title="keyword">Notation</span> <a name="3dd9eae9daa65efe5444f5fc3529a2e7"><span class="id" title="notation">&quot;</span></a>n '_' ++ 'x' m" := (<a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Peano.html#plus"><span class="id" title="abbreviation">plus</span></a> <span class="id" title="var">n</span> <span class="id" title="var">m</span>) (<span class="id" title="tactic">at</span> <span class="id" title="keyword">level</span> 3).<br/>
<br/>
-<span class="id" title="keyword">Inductive</span> <a name="eq"><span class="id" title="inductive">eq</span></a> (<span class="id" title="var">A</span>:<span class="id" title="keyword">Type</span>) (<span class="id" title="var">x</span>:<a class="idref" href="Coqdoc.links.html#A"><span class="id" title="variable">A</span></a>) : <span class="id" title="var">A</span> <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Logic.html#d43e996736952df71ebeeae74d10a287"><span class="id" title="notation">→</span></a> <span class="id" title="keyword">Prop</span> := <a name="eq_refl"><span class="id" title="constructor">eq_refl</span></a> : <a class="idref" href="Coqdoc.links.html#x"><span class="id" title="variable">x</span></a> <a class="idref" href="Coqdoc.links.html#8f9364556521ebb498093f28eea2240f"><span class="id" title="notation">=</span></a> <a class="idref" href="Coqdoc.links.html#x"><span class="id" title="variable">x</span></a> <a class="idref" href="Coqdoc.links.html#8f9364556521ebb498093f28eea2240f"><span class="id" title="notation">:&gt;</span></a><a class="idref" href="Coqdoc.links.html#A"><span class="id" title="variable">A</span></a><br/>
+<span class="id" title="keyword">Inductive</span> <a name="eq"><span class="id" title="inductive">eq</span></a> (<span class="id" title="var">A</span>:<span class="id" title="keyword">Type</span>) (<span class="id" title="var">x</span>:<a class="idref" href="Coqdoc.links.html#A"><span class="id" title="variable">A</span></a>) : <span class="id" title="var">A</span> <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Logic.html#1c93e43e07fbeaeb6a625cb6614beb5d"><span class="id" title="notation">→</span></a> <span class="id" title="keyword">Prop</span> := <a name="eq_refl"><span class="id" title="constructor">eq_refl</span></a> : <a class="idref" href="Coqdoc.links.html#x"><span class="id" title="variable">x</span></a> <a class="idref" href="Coqdoc.links.html#b8b2ebc8e1a8b9aa935c0702efb5dccf"><span class="id" title="notation">=</span></a> <a class="idref" href="Coqdoc.links.html#x"><span class="id" title="variable">x</span></a> <a class="idref" href="Coqdoc.links.html#b8b2ebc8e1a8b9aa935c0702efb5dccf"><span class="id" title="notation">:&gt;</span></a><a class="idref" href="Coqdoc.links.html#A"><span class="id" title="variable">A</span></a><br/>
<br/>
-<span class="id" title="keyword">where</span> <a name="8f9364556521ebb498093f28eea2240f"><span class="id" title="notation">&quot;</span></a>x = y :&gt; A" := (@<a class="idref" href="Coqdoc.links.html#eq"><span class="id" title="inductive">eq</span></a> <span class="id" title="var">A</span> <span class="id" title="var">x</span> <span class="id" title="var">y</span>) : <span class="id" title="var">type_scope</span>.<br/>
+<span class="id" title="keyword">where</span> <a name="b8b2ebc8e1a8b9aa935c0702efb5dccf"><span class="id" title="notation">&quot;</span></a>x = y :&gt; A" := (@<a class="idref" href="Coqdoc.links.html#eq"><span class="id" title="inductive">eq</span></a> <span class="id" title="var">A</span> <span class="id" title="var">x</span> <span class="id" title="var">y</span>) : <span class="id" title="var">type_scope</span>.<br/>
<br/>
-<span class="id" title="keyword">Definition</span> <a name="eq0"><span class="id" title="definition">eq0</span></a> := 0 <a class="idref" href="Coqdoc.links.html#8f9364556521ebb498093f28eea2240f"><span class="id" title="notation">=</span></a> 0 <a class="idref" href="Coqdoc.links.html#8f9364556521ebb498093f28eea2240f"><span class="id" title="notation">:&gt;</span></a> <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#nat"><span class="id" title="inductive">nat</span></a>.<br/>
+<span class="id" title="keyword">Definition</span> <a name="eq0"><span class="id" title="definition">eq0</span></a> := 0 <a class="idref" href="Coqdoc.links.html#b8b2ebc8e1a8b9aa935c0702efb5dccf"><span class="id" title="notation">=</span></a> 0 <a class="idref" href="Coqdoc.links.html#b8b2ebc8e1a8b9aa935c0702efb5dccf"><span class="id" title="notation">:&gt;</span></a> <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#nat"><span class="id" title="inductive">nat</span></a>.<br/>
<br/>
-<span class="id" title="keyword">Notation</span> <a name="548d1059c499c9b2a9b95b07e68c2090"><span class="id" title="notation">&quot;</span></a>( x # y ; .. ; z )" := (<a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#pair"><span class="id" title="constructor">pair</span></a> .. (<a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#pair"><span class="id" title="constructor">pair</span></a> <span class="id" title="var">x</span> <span class="id" title="var">y</span>) .. <span class="id" title="var">z</span>).<br/>
+<span class="id" title="keyword">Notation</span> <a name="2c0c193cd2aedf7ecdb713db64dbfce6"><span class="id" title="notation">&quot;</span></a>( x # y ; .. ; z )" := (<a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#pair"><span class="id" title="constructor">pair</span></a> .. (<a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#pair"><span class="id" title="constructor">pair</span></a> <span class="id" title="var">x</span> <span class="id" title="var">y</span>) .. <span class="id" title="var">z</span>).<br/>
<br/>
-<span class="id" title="keyword">Definition</span> <a name="9f5a1d89cbd4d38f5e289576db7123d1"><span class="id" title="definition">b_α</span></a> := <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#44400027531d4bc3f586a1997dc874c0"><span class="id" title="notation">(</span></a><a class="idref" href="Coqdoc.links.html#548d1059c499c9b2a9b95b07e68c2090"><span class="id" title="notation">(</span></a>0<a class="idref" href="Coqdoc.links.html#548d1059c499c9b2a9b95b07e68c2090"><span class="id" title="notation">#</span></a>0<a class="idref" href="Coqdoc.links.html#548d1059c499c9b2a9b95b07e68c2090"><span class="id" title="notation">;</span></a>0<a class="idref" href="Coqdoc.links.html#548d1059c499c9b2a9b95b07e68c2090"><span class="id" title="notation">)</span></a> <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#44400027531d4bc3f586a1997dc874c0"><span class="id" title="notation">,</span></a> <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#44400027531d4bc3f586a1997dc874c0"><span class="id" title="notation">(</span></a>0 <a class="idref" href="Coqdoc.links.html#6b97e27793a3d22f5c0d1dd63170fd68"><span class="id" title="notation">**</span></a> 0<a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#44400027531d4bc3f586a1997dc874c0"><span class="id" title="notation">))</span></a>.<br/>
+<span class="id" title="keyword">Definition</span> <a name="9f5a1d89cbd4d38f5e289576db7123d1"><span class="id" title="definition">b_α</span></a> := <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#e6756e10c36f149b18b4a8741ed83079"><span class="id" title="notation">(</span></a><a class="idref" href="Coqdoc.links.html#2c0c193cd2aedf7ecdb713db64dbfce6"><span class="id" title="notation">(</span></a>0<a class="idref" href="Coqdoc.links.html#2c0c193cd2aedf7ecdb713db64dbfce6"><span class="id" title="notation">#</span></a>0<a class="idref" href="Coqdoc.links.html#2c0c193cd2aedf7ecdb713db64dbfce6"><span class="id" title="notation">;</span></a>0<a class="idref" href="Coqdoc.links.html#2c0c193cd2aedf7ecdb713db64dbfce6"><span class="id" title="notation">)</span></a> <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#e6756e10c36f149b18b4a8741ed83079"><span class="id" title="notation">,</span></a> <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#e6756e10c36f149b18b4a8741ed83079"><span class="id" title="notation">(</span></a>0 <a class="idref" href="Coqdoc.links.html#f07b3676d96b68749d342542fd80e2b0"><span class="id" title="notation">**</span></a> 0<a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#e6756e10c36f149b18b4a8741ed83079"><span class="id" title="notation">))</span></a>.<br/>
<br/>
<span class="id" title="keyword">Notation</span> <a name="h"><span class="id" title="abbreviation">h</span></a> := <a class="idref" href="Coqdoc.links.html#a"><span class="id" title="definition">a</span></a>.<br/>
@@ -97,7 +97,7 @@ Various checks for coqdoc
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" title="keyword">Variables</span> <a name="test.b'"><span class="id" title="variable">b'</span></a> <a name="test.b2"><span class="id" title="variable">b2</span></a>: <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#nat"><span class="id" title="inductive">nat</span></a>.<br/>
<br/>
-&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" title="keyword">Notation</span> <a name="4ab0449b36c75cf94e08c5822ea83e3d"><span class="id" title="notation">&quot;</span></a>n + m" := (<span class="id" title="var">n</span> <a class="idref" href="Coqdoc.links.html#3e01fbae4590c7b7699ff99ce61580e1"><span class="id" title="notation">▵</span></a> <span class="id" title="var">m</span>) : <span class="id" title="var">my_scope</span>.<br/>
+&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" title="keyword">Notation</span> <a name="2158f15740ce05a939b657be222c26d6"><span class="id" title="notation">&quot;</span></a>n + m" := (<span class="id" title="var">n</span> <a class="idref" href="Coqdoc.links.html#a647c51c9816a1b44fcfa5312db8344a"><span class="id" title="notation">▵</span></a> <span class="id" title="var">m</span>) : <span class="id" title="var">my_scope</span>.<br/>
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" title="keyword">Delimit</span> <span class="id" title="keyword">Scope</span> <span class="id" title="var">my_scope</span> <span class="id" title="keyword">with</span> <span class="id" title="var">my</span>.<br/>
@@ -106,19 +106,19 @@ Various checks for coqdoc
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" title="keyword">Notation</span> <a name="l"><span class="id" title="abbreviation">l</span></a> := 0.<br/>
<br/>
-&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" title="keyword">Definition</span> <a name="ab410a966ac148e9b78c65c6cdf301fd"><span class="id" title="definition">α</span></a> := (0 <a class="idref" href="Coqdoc.links.html#4ab0449b36c75cf94e08c5822ea83e3d"><span class="id" title="notation">+</span></a> <a class="idref" href="Coqdoc.links.html#l"><span class="id" title="abbreviation">l</span></a>)%<span class="id" title="var">my</span>.<br/>
+&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" title="keyword">Definition</span> <a name="ab410a966ac148e9b78c65c6cdf301fd"><span class="id" title="definition">α</span></a> := (0 <a class="idref" href="Coqdoc.links.html#2158f15740ce05a939b657be222c26d6"><span class="id" title="notation">+</span></a> <a class="idref" href="Coqdoc.links.html#l"><span class="id" title="abbreviation">l</span></a>)%<span class="id" title="var">my</span>.<br/>
<br/>
-&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" title="keyword">Definition</span> <a name="a'"><span class="id" title="definition">a'</span></a> <span class="id" title="var">b</span> := <a class="idref" href="Coqdoc.links.html#test.b'"><span class="id" title="variable">b'</span></a><a class="idref" href="Coqdoc.links.html#1a1c7f13320341c3638e9edcc3e6389d"><span class="id" title="notation">++</span></a>0<a class="idref" href="Coqdoc.links.html#1a1c7f13320341c3638e9edcc3e6389d"><span class="id" title="notation">++</span></a><a class="idref" href="Coqdoc.links.html#test.b2"><span class="id" title="variable">b2</span></a> <a class="idref" href="Coqdoc.links.html#347f39a83bf7d45676cff54fd7e8966f"><span class="id" title="notation">_</span></a> <a class="idref" href="Coqdoc.links.html#347f39a83bf7d45676cff54fd7e8966f"><span class="id" title="notation">++</span></a><a class="idref" href="Coqdoc.links.html#347f39a83bf7d45676cff54fd7e8966f"><span class="id" title="notation">x</span></a> <a class="idref" href="Coqdoc.links.html#b"><span class="id" title="variable">b</span></a>.<br/>
+&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" title="keyword">Definition</span> <a name="a'"><span class="id" title="definition">a'</span></a> <span class="id" title="var">b</span> := <a class="idref" href="Coqdoc.links.html#test.b'"><span class="id" title="variable">b'</span></a><a class="idref" href="Coqdoc.links.html#f03f7a04ef75ff3ac66ca5c23554e52e"><span class="id" title="notation">++</span></a>0<a class="idref" href="Coqdoc.links.html#f03f7a04ef75ff3ac66ca5c23554e52e"><span class="id" title="notation">++</span></a><a class="idref" href="Coqdoc.links.html#test.b2"><span class="id" title="variable">b2</span></a> <a class="idref" href="Coqdoc.links.html#3dd9eae9daa65efe5444f5fc3529a2e7"><span class="id" title="notation">_</span></a> <a class="idref" href="Coqdoc.links.html#3dd9eae9daa65efe5444f5fc3529a2e7"><span class="id" title="notation">++</span></a><a class="idref" href="Coqdoc.links.html#3dd9eae9daa65efe5444f5fc3529a2e7"><span class="id" title="notation">x</span></a> <a class="idref" href="Coqdoc.links.html#b"><span class="id" title="variable">b</span></a>.<br/>
<br/>
-&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" title="keyword">Definition</span> <a name="c"><span class="id" title="definition">c</span></a> := <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Specif.html#5bf2050e90b21ebc82dc5463d1ba338e"><span class="id" title="notation">{</span></a><a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Logic.html#True"><span class="id" title="inductive">True</span></a><a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Specif.html#5bf2050e90b21ebc82dc5463d1ba338e"><span class="id" title="notation">}+{</span></a><a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Logic.html#True"><span class="id" title="inductive">True</span></a><a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Specif.html#5bf2050e90b21ebc82dc5463d1ba338e"><span class="id" title="notation">}</span></a>.<br/>
+&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" title="keyword">Definition</span> <a name="c"><span class="id" title="definition">c</span></a> := <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Specif.html#87727981cdc1579fef00b9d9c1d3b9da"><span class="id" title="notation">{</span></a><a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Logic.html#True"><span class="id" title="inductive">True</span></a><a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Specif.html#87727981cdc1579fef00b9d9c1d3b9da"><span class="id" title="notation">}+{</span></a><a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Logic.html#True"><span class="id" title="inductive">True</span></a><a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Specif.html#87727981cdc1579fef00b9d9c1d3b9da"><span class="id" title="notation">}</span></a>.<br/>
<br/>
-&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" title="keyword">Definition</span> <a name="d"><span class="id" title="definition">d</span></a> := (1<a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Peano.html#b3eea360671e1b32b18a26e15b3aace3"><span class="id" title="notation">+</span></a>2)%<span class="id" title="var">nat</span>.<br/>
+&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" title="keyword">Definition</span> <a name="d"><span class="id" title="definition">d</span></a> := (1<a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Peano.html#0dacc1786c5ba797d47dd85006231633"><span class="id" title="notation">+</span></a>2)%<span class="id" title="var">nat</span>.<br/>
<br/>
-&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" title="keyword">Lemma</span> <a name="e"><span class="id" title="lemma">e</span></a> : <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#nat"><span class="id" title="inductive">nat</span></a> <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#3dcaec3b772747610227247939f96b01"><span class="id" title="notation">+</span></a> <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#nat"><span class="id" title="inductive">nat</span></a>.<br/>
+&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" title="keyword">Lemma</span> <a name="e"><span class="id" title="lemma">e</span></a> : <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#nat"><span class="id" title="inductive">nat</span></a> <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#e03f39daf98516fa530d3f6f5a1b4d92"><span class="id" title="notation">+</span></a> <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#nat"><span class="id" title="inductive">nat</span></a>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" title="var">Admitted</span>.<br/>
<br/>
@@ -137,7 +137,7 @@ Various checks for coqdoc
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" title="keyword">Variables</span> <a name="test2.test.b2"><span class="id" title="variable">b2</span></a>: <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#nat"><span class="id" title="inductive">nat</span></a>.<br/>
<br/>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" title="keyword">Definition</span> <a name="a''"><span class="id" title="definition">a''</span></a> <span class="id" title="var">b</span> := <a class="idref" href="Coqdoc.links.html#test2.b'"><span class="id" title="variable">b'</span></a> <a class="idref" href="Coqdoc.links.html#1a1c7f13320341c3638e9edcc3e6389d"><span class="id" title="notation">++</span></a> <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#O"><span class="id" title="constructor">O</span></a> <a class="idref" href="Coqdoc.links.html#1a1c7f13320341c3638e9edcc3e6389d"><span class="id" title="notation">++</span></a> <a class="idref" href="Coqdoc.links.html#test2.test.b2"><span class="id" title="variable">b2</span></a> <a class="idref" href="Coqdoc.links.html#347f39a83bf7d45676cff54fd7e8966f"><span class="id" title="notation">_</span></a> <a class="idref" href="Coqdoc.links.html#347f39a83bf7d45676cff54fd7e8966f"><span class="id" title="notation">++</span></a> <a class="idref" href="Coqdoc.links.html#347f39a83bf7d45676cff54fd7e8966f"><span class="id" title="notation">x</span></a> <a class="idref" href="Coqdoc.links.html#b"><span class="id" title="variable">b</span></a> <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Peano.html#b3eea360671e1b32b18a26e15b3aace3"><span class="id" title="notation">+</span></a> <a class="idref" href="Coqdoc.links.html#h"><span class="id" title="abbreviation">h</span></a> 0.<br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" title="keyword">Definition</span> <a name="a''"><span class="id" title="definition">a''</span></a> <span class="id" title="var">b</span> := <a class="idref" href="Coqdoc.links.html#test2.b'"><span class="id" title="variable">b'</span></a> <a class="idref" href="Coqdoc.links.html#f03f7a04ef75ff3ac66ca5c23554e52e"><span class="id" title="notation">++</span></a> <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html#O"><span class="id" title="constructor">O</span></a> <a class="idref" href="Coqdoc.links.html#f03f7a04ef75ff3ac66ca5c23554e52e"><span class="id" title="notation">++</span></a> <a class="idref" href="Coqdoc.links.html#test2.test.b2"><span class="id" title="variable">b2</span></a> <a class="idref" href="Coqdoc.links.html#3dd9eae9daa65efe5444f5fc3529a2e7"><span class="id" title="notation">_</span></a> <a class="idref" href="Coqdoc.links.html#3dd9eae9daa65efe5444f5fc3529a2e7"><span class="id" title="notation">++</span></a> <a class="idref" href="Coqdoc.links.html#3dd9eae9daa65efe5444f5fc3529a2e7"><span class="id" title="notation">x</span></a> <a class="idref" href="Coqdoc.links.html#b"><span class="id" title="variable">b</span></a> <a class="idref" href="http://coq.inria.fr/stdlib/Coq.Init.Peano.html#0dacc1786c5ba797d47dd85006231633"><span class="id" title="notation">+</span></a> <a class="idref" href="Coqdoc.links.html#h"><span class="id" title="abbreviation">h</span></a> 0.<br/>
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" title="keyword">End</span> <a class="idref" href="Coqdoc.links.html#test2.test"><span class="id" title="section">test</span></a>.<br/>
diff --git a/test-suite/coqdoc/links.tex.out b/test-suite/coqdoc/links.tex.out
index f42db99dc2..24f96ff1e6 100644
--- a/test-suite/coqdoc/links.tex.out
+++ b/test-suite/coqdoc/links.tex.out
@@ -51,34 +51,34 @@ Various checks for coqdoc
\coqdockw{Definition} \coqdef{Coqdoc.links.f}{f}{\coqdocdefinition{f}} := \coqdockw{\ensuremath{\forall}} \coqdocvar{C}:\coqdockw{Prop}, \coqdocvariable{C}.\coqdoceol
\coqdocemptyline
\coqdocnoindent
-\coqdockw{Notation} \coqdef{Coqdoc.links.::x '++' x}{"}{"}n ++ m" := (\coqexternalref{plus}{http://coq.inria.fr/stdlib/Coq.Init.Peano}{\coqdocabbreviation{plus}} \coqdocvar{n} \coqdocvar{m}).\coqdoceol
+\coqdockw{Notation} \coqdef{Coqdoc.links.:::x '++' x}{"}{"}n ++ m" := (\coqexternalref{plus}{http://coq.inria.fr/stdlib/Coq.Init.Peano}{\coqdocabbreviation{plus}} \coqdocvar{n} \coqdocvar{m}).\coqdoceol
\coqdocemptyline
\coqdocnoindent
-\coqdockw{Notation} \coqdef{Coqdoc.links.::x '++' x}{"}{"}n ++ m" := (\coqexternalref{mult}{http://coq.inria.fr/stdlib/Coq.Init.Peano}{\coqdocabbreviation{mult}} \coqdocvar{n} \coqdocvar{m}). \coqdocemptyline
+\coqdockw{Notation} \coqdef{Coqdoc.links.:::x '++' x}{"}{"}n ++ m" := (\coqexternalref{mult}{http://coq.inria.fr/stdlib/Coq.Init.Peano}{\coqdocabbreviation{mult}} \coqdocvar{n} \coqdocvar{m}). \coqdocemptyline
\coqdocnoindent
-\coqdockw{Notation} \coqdef{Coqdoc.links.::x '**' x}{"}{"}n ** m" := (\coqexternalref{plus}{http://coq.inria.fr/stdlib/Coq.Init.Peano}{\coqdocabbreviation{plus}} \coqdocvar{n} \coqdocvar{m}) (\coqdoctac{at} \coqdockw{level} 60).\coqdoceol
+\coqdockw{Notation} \coqdef{Coqdoc.links.:::x '**' x}{"}{"}n ** m" := (\coqexternalref{plus}{http://coq.inria.fr/stdlib/Coq.Init.Peano}{\coqdocabbreviation{plus}} \coqdocvar{n} \coqdocvar{m}) (\coqdoctac{at} \coqdockw{level} 60).\coqdoceol
\coqdocemptyline
\coqdocnoindent
-\coqdockw{Notation} \coqdef{Coqdoc.links.::x 'xE2x96xB5' x}{"}{"}n ▵ m" := (\coqexternalref{plus}{http://coq.inria.fr/stdlib/Coq.Init.Peano}{\coqdocabbreviation{plus}} \coqdocvar{n} \coqdocvar{m}) (\coqdoctac{at} \coqdockw{level} 60).\coqdoceol
+\coqdockw{Notation} \coqdef{Coqdoc.links.:::x 'xE2x96xB5' x}{"}{"}n ▵ m" := (\coqexternalref{plus}{http://coq.inria.fr/stdlib/Coq.Init.Peano}{\coqdocabbreviation{plus}} \coqdocvar{n} \coqdocvar{m}) (\coqdoctac{at} \coqdockw{level} 60).\coqdoceol
\coqdocemptyline
\coqdocnoindent
-\coqdockw{Notation} \coqdef{Coqdoc.links.::x ''' ''' '++' 'x' x}{"}{"}n '\_' ++ 'x' m" := (\coqexternalref{plus}{http://coq.inria.fr/stdlib/Coq.Init.Peano}{\coqdocabbreviation{plus}} \coqdocvar{n} \coqdocvar{m}) (\coqdoctac{at} \coqdockw{level} 3).\coqdoceol
+\coqdockw{Notation} \coqdef{Coqdoc.links.:::x ''' ''' '++' 'x' x}{"}{"}n '\_' ++ 'x' m" := (\coqexternalref{plus}{http://coq.inria.fr/stdlib/Coq.Init.Peano}{\coqdocabbreviation{plus}} \coqdocvar{n} \coqdocvar{m}) (\coqdoctac{at} \coqdockw{level} 3).\coqdoceol
\coqdocemptyline
\coqdocnoindent
-\coqdockw{Inductive} \coqdef{Coqdoc.links.eq}{eq}{\coqdocinductive{eq}} (\coqdocvar{A}:\coqdockw{Type}) (\coqdocvar{x}:\coqdocvariable{A}) : \coqdocvar{A} \coqexternalref{:type scope:x '->' x}{http://coq.inria.fr/stdlib/Coq.Init.Logic}{\coqdocnotation{\ensuremath{\rightarrow}}} \coqdockw{Prop} := \coqdef{Coqdoc.links.eq refl}{eq\_refl}{\coqdocconstructor{eq\_refl}} : \coqdocvariable{x} \coqref{Coqdoc.links.:type scope:x '=' x ':>' x}{\coqdocnotation{=}} \coqdocvariable{x} \coqref{Coqdoc.links.:type scope:x '=' x ':>' x}{\coqdocnotation{:>}}\coqdocvariable{A}\coqdoceol
+\coqdockw{Inductive} \coqdef{Coqdoc.links.eq}{eq}{\coqdocinductive{eq}} (\coqdocvar{A}:\coqdockw{Type}) (\coqdocvar{x}:\coqdocvariable{A}) : \coqdocvar{A} \coqexternalref{::type scope:x '->' x}{http://coq.inria.fr/stdlib/Coq.Init.Logic}{\coqdocnotation{\ensuremath{\rightarrow}}} \coqdockw{Prop} := \coqdef{Coqdoc.links.eq refl}{eq\_refl}{\coqdocconstructor{eq\_refl}} : \coqdocvariable{x} \coqref{Coqdoc.links.::type scope:x '=' x ':>' x}{\coqdocnotation{=}} \coqdocvariable{x} \coqref{Coqdoc.links.::type scope:x '=' x ':>' x}{\coqdocnotation{:>}}\coqdocvariable{A}\coqdoceol
\coqdocnoindent
\coqdoceol
\coqdocnoindent
-\coqdockw{where} \coqdef{Coqdoc.links.:type scope:x '=' x ':>' x}{"}{"}x = y :> A" := (@\coqref{Coqdoc.links.eq}{\coqdocinductive{eq}} \coqdocvar{A} \coqdocvar{x} \coqdocvar{y}) : \coqdocvar{type\_scope}.\coqdoceol
+\coqdockw{where} \coqdef{Coqdoc.links.::type scope:x '=' x ':>' x}{"}{"}x = y :> A" := (@\coqref{Coqdoc.links.eq}{\coqdocinductive{eq}} \coqdocvar{A} \coqdocvar{x} \coqdocvar{y}) : \coqdocvar{type\_scope}.\coqdoceol
\coqdocemptyline
\coqdocnoindent
-\coqdockw{Definition} \coqdef{Coqdoc.links.eq0}{eq0}{\coqdocdefinition{eq0}} := 0 \coqref{Coqdoc.links.:type scope:x '=' x ':>' x}{\coqdocnotation{=}} 0 \coqref{Coqdoc.links.:type scope:x '=' x ':>' x}{\coqdocnotation{:>}} \coqexternalref{nat}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocinductive{nat}}.\coqdoceol
+\coqdockw{Definition} \coqdef{Coqdoc.links.eq0}{eq0}{\coqdocdefinition{eq0}} := 0 \coqref{Coqdoc.links.::type scope:x '=' x ':>' x}{\coqdocnotation{=}} 0 \coqref{Coqdoc.links.::type scope:x '=' x ':>' x}{\coqdocnotation{:>}} \coqexternalref{nat}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocinductive{nat}}.\coqdoceol
\coqdocemptyline
\coqdocnoindent
-\coqdockw{Notation} \coqdef{Coqdoc.links.::'(' x 'x23' x ';' '..' ';' x ')'}{"}{"}( x \# y ; .. ; z )" := (\coqexternalref{pair}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocconstructor{pair}} .. (\coqexternalref{pair}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocconstructor{pair}} \coqdocvar{x} \coqdocvar{y}) .. \coqdocvar{z}).\coqdoceol
+\coqdockw{Notation} \coqdef{Coqdoc.links.:::'(' x 'x23' x ';' '..' ';' x ')'}{"}{"}( x \# y ; .. ; z )" := (\coqexternalref{pair}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocconstructor{pair}} .. (\coqexternalref{pair}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocconstructor{pair}} \coqdocvar{x} \coqdocvar{y}) .. \coqdocvar{z}).\coqdoceol
\coqdocemptyline
\coqdocnoindent
-\coqdockw{Definition} \coqdef{Coqdoc.links.b xCExB1}{b\_α}{\coqdocdefinition{b\_α}} := \coqexternalref{:core scope:'(' x ',' x ',' '..' ',' x ')'}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocnotation{(}}\coqref{Coqdoc.links.::'(' x 'x23' x ';' '..' ';' x ')'}{\coqdocnotation{(}}0\coqref{Coqdoc.links.::'(' x 'x23' x ';' '..' ';' x ')'}{\coqdocnotation{\#}}0\coqref{Coqdoc.links.::'(' x 'x23' x ';' '..' ';' x ')'}{\coqdocnotation{;}}0\coqref{Coqdoc.links.::'(' x 'x23' x ';' '..' ';' x ')'}{\coqdocnotation{)}} \coqexternalref{:core scope:'(' x ',' x ',' '..' ',' x ')'}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocnotation{,}} \coqexternalref{:core scope:'(' x ',' x ',' '..' ',' x ')'}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocnotation{(}}0 \coqref{Coqdoc.links.::x '**' x}{\coqdocnotation{**}} 0\coqexternalref{:core scope:'(' x ',' x ',' '..' ',' x ')'}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocnotation{))}}.\coqdoceol
+\coqdockw{Definition} \coqdef{Coqdoc.links.b xCExB1}{b\_α}{\coqdocdefinition{b\_α}} := \coqexternalref{::core scope:'(' x ',' x ',' '..' ',' x ')'}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocnotation{(}}\coqref{Coqdoc.links.:::'(' x 'x23' x ';' '..' ';' x ')'}{\coqdocnotation{(}}0\coqref{Coqdoc.links.:::'(' x 'x23' x ';' '..' ';' x ')'}{\coqdocnotation{\#}}0\coqref{Coqdoc.links.:::'(' x 'x23' x ';' '..' ';' x ')'}{\coqdocnotation{;}}0\coqref{Coqdoc.links.:::'(' x 'x23' x ';' '..' ';' x ')'}{\coqdocnotation{)}} \coqexternalref{::core scope:'(' x ',' x ',' '..' ',' x ')'}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocnotation{,}} \coqexternalref{::core scope:'(' x ',' x ',' '..' ',' x ')'}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocnotation{(}}0 \coqref{Coqdoc.links.:::x '**' x}{\coqdocnotation{**}} 0\coqexternalref{::core scope:'(' x ',' x ',' '..' ',' x ')'}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocnotation{))}}.\coqdoceol
\coqdocemptyline
\coqdocnoindent
\coqdockw{Notation} \coqdef{Coqdoc.links.h}{h}{\coqdocabbreviation{h}} := \coqref{Coqdoc.links.a}{\coqdocdefinition{a}}.\coqdoceol
@@ -90,7 +90,7 @@ Various checks for coqdoc
\coqdockw{Variables} \coqdef{Coqdoc.links.test.b'}{b'}{\coqdocvariable{b'}} \coqdef{Coqdoc.links.test.b2}{b2}{\coqdocvariable{b2}}: \coqexternalref{nat}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocinductive{nat}}.\coqdoceol
\coqdocemptyline
\coqdocindent{2.00em}
-\coqdockw{Notation} \coqdef{Coqdoc.links.test.:my scope:x '+' x}{"}{"}n + m" := (\coqdocvar{n} \coqref{Coqdoc.links.::x 'xE2x96xB5' x}{\coqdocnotation{▵}} \coqdocvar{m}) : \coqdocvar{my\_scope}.\coqdoceol
+\coqdockw{Notation} \coqdef{Coqdoc.links.test.::my scope:x '+' x}{"}{"}n + m" := (\coqdocvar{n} \coqref{Coqdoc.links.:::x 'xE2x96xB5' x}{\coqdocnotation{▵}} \coqdocvar{m}) : \coqdocvar{my\_scope}.\coqdoceol
\coqdocemptyline
\coqdocindent{2.00em}
\coqdockw{Delimit} \coqdockw{Scope} \coqdocvar{my\_scope} \coqdockw{with} \coqdocvar{my}.\coqdoceol
@@ -99,19 +99,19 @@ Various checks for coqdoc
\coqdockw{Notation} \coqdef{Coqdoc.links.l}{l}{\coqdocabbreviation{l}} := 0.\coqdoceol
\coqdocemptyline
\coqdocindent{2.00em}
-\coqdockw{Definition} \coqdef{Coqdoc.links.xCExB1}{α}{\coqdocdefinition{α}} := (0 \coqref{Coqdoc.links.test.:my scope:x '+' x}{\coqdocnotation{+}} \coqref{Coqdoc.links.l}{\coqdocabbreviation{l}})\%\coqdocvar{my}.\coqdoceol
+\coqdockw{Definition} \coqdef{Coqdoc.links.xCExB1}{α}{\coqdocdefinition{α}} := (0 \coqref{Coqdoc.links.test.::my scope:x '+' x}{\coqdocnotation{+}} \coqref{Coqdoc.links.l}{\coqdocabbreviation{l}})\%\coqdocvar{my}.\coqdoceol
\coqdocemptyline
\coqdocindent{2.00em}
-\coqdockw{Definition} \coqdef{Coqdoc.links.a'}{a'}{\coqdocdefinition{a'}} \coqdocvar{b} := \coqdocvariable{b'}\coqref{Coqdoc.links.::x '++' x}{\coqdocnotation{++}}0\coqref{Coqdoc.links.::x '++' x}{\coqdocnotation{++}}\coqdocvariable{b2} \coqref{Coqdoc.links.::x ''' ''' '++' 'x' x}{\coqdocnotation{\_}} \coqref{Coqdoc.links.::x ''' ''' '++' 'x' x}{\coqdocnotation{++}}\coqref{Coqdoc.links.::x ''' ''' '++' 'x' x}{\coqdocnotation{x}} \coqdocvariable{b}.\coqdoceol
+\coqdockw{Definition} \coqdef{Coqdoc.links.a'}{a'}{\coqdocdefinition{a'}} \coqdocvar{b} := \coqdocvariable{b'}\coqref{Coqdoc.links.:::x '++' x}{\coqdocnotation{++}}0\coqref{Coqdoc.links.:::x '++' x}{\coqdocnotation{++}}\coqdocvariable{b2} \coqref{Coqdoc.links.:::x ''' ''' '++' 'x' x}{\coqdocnotation{\_}} \coqref{Coqdoc.links.:::x ''' ''' '++' 'x' x}{\coqdocnotation{++}}\coqref{Coqdoc.links.:::x ''' ''' '++' 'x' x}{\coqdocnotation{x}} \coqdocvariable{b}.\coqdoceol
\coqdocemptyline
\coqdocindent{2.00em}
-\coqdockw{Definition} \coqdef{Coqdoc.links.c}{c}{\coqdocdefinition{c}} := \coqexternalref{:type scope:'x7B' x 'x7D' '+' 'x7B' x 'x7D'}{http://coq.inria.fr/stdlib/Coq.Init.Specif}{\coqdocnotation{\{}}\coqexternalref{True}{http://coq.inria.fr/stdlib/Coq.Init.Logic}{\coqdocinductive{True}}\coqexternalref{:type scope:'x7B' x 'x7D' '+' 'x7B' x 'x7D'}{http://coq.inria.fr/stdlib/Coq.Init.Specif}{\coqdocnotation{\}+\{}}\coqexternalref{True}{http://coq.inria.fr/stdlib/Coq.Init.Logic}{\coqdocinductive{True}}\coqexternalref{:type scope:'x7B' x 'x7D' '+' 'x7B' x 'x7D'}{http://coq.inria.fr/stdlib/Coq.Init.Specif}{\coqdocnotation{\}}}.\coqdoceol
+\coqdockw{Definition} \coqdef{Coqdoc.links.c}{c}{\coqdocdefinition{c}} := \coqexternalref{::type scope:'x7B' x 'x7D' '+' 'x7B' x 'x7D'}{http://coq.inria.fr/stdlib/Coq.Init.Specif}{\coqdocnotation{\{}}\coqexternalref{True}{http://coq.inria.fr/stdlib/Coq.Init.Logic}{\coqdocinductive{True}}\coqexternalref{::type scope:'x7B' x 'x7D' '+' 'x7B' x 'x7D'}{http://coq.inria.fr/stdlib/Coq.Init.Specif}{\coqdocnotation{\}+\{}}\coqexternalref{True}{http://coq.inria.fr/stdlib/Coq.Init.Logic}{\coqdocinductive{True}}\coqexternalref{::type scope:'x7B' x 'x7D' '+' 'x7B' x 'x7D'}{http://coq.inria.fr/stdlib/Coq.Init.Specif}{\coqdocnotation{\}}}.\coqdoceol
\coqdocemptyline
\coqdocindent{2.00em}
-\coqdockw{Definition} \coqdef{Coqdoc.links.d}{d}{\coqdocdefinition{d}} := (1\coqexternalref{:nat scope:x '+' x}{http://coq.inria.fr/stdlib/Coq.Init.Peano}{\coqdocnotation{+}}2)\%\coqdocvar{nat}.\coqdoceol
+\coqdockw{Definition} \coqdef{Coqdoc.links.d}{d}{\coqdocdefinition{d}} := (1\coqexternalref{::nat scope:x '+' x}{http://coq.inria.fr/stdlib/Coq.Init.Peano}{\coqdocnotation{+}}2)\%\coqdocvar{nat}.\coqdoceol
\coqdocemptyline
\coqdocindent{2.00em}
-\coqdockw{Lemma} \coqdef{Coqdoc.links.e}{e}{\coqdoclemma{e}} : \coqexternalref{nat}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocinductive{nat}} \coqexternalref{:type scope:x '+' x}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocnotation{+}} \coqexternalref{nat}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocinductive{nat}}.\coqdoceol
+\coqdockw{Lemma} \coqdef{Coqdoc.links.e}{e}{\coqdoclemma{e}} : \coqexternalref{nat}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocinductive{nat}} \coqexternalref{::type scope:x '+' x}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocnotation{+}} \coqexternalref{nat}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocinductive{nat}}.\coqdoceol
\coqdocindent{2.00em}
\coqdocvar{Admitted}.\coqdoceol
\coqdocemptyline
@@ -131,7 +131,7 @@ Various checks for coqdoc
\coqdockw{Variables} \coqdef{Coqdoc.links.test2.test.b2}{b2}{\coqdocvariable{b2}}: \coqexternalref{nat}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocinductive{nat}}.\coqdoceol
\coqdocemptyline
\coqdocindent{3.00em}
-\coqdockw{Definition} \coqdef{Coqdoc.links.a''}{a'{}'}{\coqdocdefinition{a'{}'}} \coqdocvar{b} := \coqdocvariable{b'} \coqref{Coqdoc.links.::x '++' x}{\coqdocnotation{++}} \coqexternalref{O}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocconstructor{O}} \coqref{Coqdoc.links.::x '++' x}{\coqdocnotation{++}} \coqdocvariable{b2} \coqref{Coqdoc.links.::x ''' ''' '++' 'x' x}{\coqdocnotation{\_}} \coqref{Coqdoc.links.::x ''' ''' '++' 'x' x}{\coqdocnotation{++}} \coqref{Coqdoc.links.::x ''' ''' '++' 'x' x}{\coqdocnotation{x}} \coqdocvariable{b} \coqexternalref{:nat scope:x '+' x}{http://coq.inria.fr/stdlib/Coq.Init.Peano}{\coqdocnotation{+}} \coqref{Coqdoc.links.h}{\coqdocabbreviation{h}} 0.\coqdoceol
+\coqdockw{Definition} \coqdef{Coqdoc.links.a''}{a'{}'}{\coqdocdefinition{a'{}'}} \coqdocvar{b} := \coqdocvariable{b'} \coqref{Coqdoc.links.:::x '++' x}{\coqdocnotation{++}} \coqexternalref{O}{http://coq.inria.fr/stdlib/Coq.Init.Datatypes}{\coqdocconstructor{O}} \coqref{Coqdoc.links.:::x '++' x}{\coqdocnotation{++}} \coqdocvariable{b2} \coqref{Coqdoc.links.:::x ''' ''' '++' 'x' x}{\coqdocnotation{\_}} \coqref{Coqdoc.links.:::x ''' ''' '++' 'x' x}{\coqdocnotation{++}} \coqref{Coqdoc.links.:::x ''' ''' '++' 'x' x}{\coqdocnotation{x}} \coqdocvariable{b} \coqexternalref{::nat scope:x '+' x}{http://coq.inria.fr/stdlib/Coq.Init.Peano}{\coqdocnotation{+}} \coqref{Coqdoc.links.h}{\coqdocabbreviation{h}} 0.\coqdoceol
\coqdocemptyline
\coqdocindent{2.00em}
\coqdockw{End} \coqref{Coqdoc.links.test2.test}{\coqdocsection{test}}.\coqdoceol
diff --git a/test-suite/misc/7704.sh b/test-suite/misc/7704.sh
new file mode 100755
index 0000000000..0ca2c97d24
--- /dev/null
+++ b/test-suite/misc/7704.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+set -e
+
+export PATH=$BIN:$PATH
+
+${coqtop#"$BIN"} -compile misc/aux7704.v
diff --git a/test-suite/misc/aux7704.v b/test-suite/misc/aux7704.v
new file mode 100644
index 0000000000..6fdcf67684
--- /dev/null
+++ b/test-suite/misc/aux7704.v
@@ -0,0 +1,6 @@
+
+Goal True /\ True.
+Proof.
+ split.
+ par:exact I.
+Qed.
diff --git a/test-suite/output/BadOptionValueType.out b/test-suite/output/BadOptionValueType.out
new file mode 100644
index 0000000000..34d8518a75
--- /dev/null
+++ b/test-suite/output/BadOptionValueType.out
@@ -0,0 +1,8 @@
+The command has indeed failed with message:
+Bad type of value for this option: expected int, got string.
+The command has indeed failed with message:
+Bad type of value for this option: expected bool, got string.
+The command has indeed failed with message:
+Bad type of value for this option: expected bool, got int.
+The command has indeed failed with message:
+Bad type of value for this option: expected bool, got int.
diff --git a/test-suite/output/BadOptionValueType.v b/test-suite/output/BadOptionValueType.v
new file mode 100644
index 0000000000..b61c3757ba
--- /dev/null
+++ b/test-suite/output/BadOptionValueType.v
@@ -0,0 +1,4 @@
+Fail Set Default Timeout "2".
+Fail Set Debug Eauto "yes".
+Fail Set Debug Eauto 1.
+Fail Set Implicit Arguments 1.
diff --git a/test-suite/output/Cases.out b/test-suite/output/Cases.out
index 419dcadb4c..dfab400baa 100644
--- a/test-suite/output/Cases.out
+++ b/test-suite/output/Cases.out
@@ -169,3 +169,5 @@ fun x : K => match x with
| _ => 2
end
: K -> nat
+The command has indeed failed with message:
+Pattern "S _, _" is redundant in this clause.
diff --git a/test-suite/output/Cases.v b/test-suite/output/Cases.v
index 4740c009a4..e4fa7044e7 100644
--- a/test-suite/output/Cases.v
+++ b/test-suite/output/Cases.v
@@ -217,3 +217,6 @@ Check fun x => match x with a3 | a4 => 3 | _ => 2 end.
Check fun x => match x with a3 => 3 | a2 | a1 => 4 | _ => 2 end.
Check fun x => match x with a4 => 3 | a2 | a1 => 4 | _ => 2 end.
Check fun x => match x with a3 | a4 | a1 => 3 | _ => 2 end.
+
+(* Test redundant clause within a disjunctive pattern *)
+Fail Check fun n m => match n, m with 0, 0 | _, S _ | S 0, _ | S (S _ | _), _ => false end.
diff --git a/test-suite/output/Deprecation.out b/test-suite/output/Deprecation.out
new file mode 100644
index 0000000000..7e290847c1
--- /dev/null
+++ b/test-suite/output/Deprecation.out
@@ -0,0 +1,3 @@
+File "stdin", line 5, characters 0-3:
+Warning: Tactic foo is deprecated since X.Y. Use idtac instead.
+[deprecated-tactic,deprecated]
diff --git a/test-suite/output/Deprecation.v b/test-suite/output/Deprecation.v
new file mode 100644
index 0000000000..04d5eb3d4a
--- /dev/null
+++ b/test-suite/output/Deprecation.v
@@ -0,0 +1,6 @@
+#[deprecated(since = "X.Y", note = "Use idtac instead.")]
+ Ltac foo := idtac.
+
+Goal True.
+foo.
+Abort.
diff --git a/test-suite/output/Notations3.out b/test-suite/output/Notations3.out
index 996af59270..d32cf67e28 100644
--- a/test-suite/output/Notations3.out
+++ b/test-suite/output/Notations3.out
@@ -241,3 +241,14 @@ Notation
Notation
"( x , y , .. , z )" := pair .. (pair x y) .. z : core_scope
(default interpretation)
+1 subgoal
+
+ ============================
+ ##@%
+ ^^^
+myfoo01 tt
+ : nat
+myfoo01 tt
+ : nat
+myfoo01 tt
+ : nat
diff --git a/test-suite/output/Notations3.v b/test-suite/output/Notations3.v
index 3cf0c913f7..180e8d337e 100644
--- a/test-suite/output/Notations3.v
+++ b/test-suite/output/Notations3.v
@@ -385,3 +385,28 @@ Module LocateNotations.
Locate "exists".
Locate "( _ , _ , .. , _ )".
End LocateNotations.
+
+Module Issue7731.
+
+Axiom (P : nat -> Prop).
+Parameter (X : nat).
+Notation "## @ E ^^^" := (P E) (at level 20, E at level 1, format "'[ ' ## '/' @ E '/' ^^^ ']'").
+Notation "%" := X.
+
+Set Printing Width 7.
+Goal ## @ % ^^^.
+Show.
+Abort.
+
+End Issue7731.
+
+Module Issue8126.
+
+Definition myfoo (x : nat) (y : nat) (z : unit) := y.
+Notation myfoo0 := (@myfoo 0).
+Notation myfoo01 := (@myfoo0 1).
+Check myfoo 0 1 tt. (* was printing [myfoo0 1 HI], but should print [myfoo01 HI] *)
+Check myfoo0 1 tt. (* was printing [myfoo0 1 HI], but should print [myfoo01 HI] *)
+Check myfoo01 tt. (* was printing [myfoo0 1 HI], but should print [myfoo01 HI] *)
+
+End Issue8126.
diff --git a/test-suite/output/Notations4.out b/test-suite/output/Notations4.out
new file mode 100644
index 0000000000..cef7d1a702
--- /dev/null
+++ b/test-suite/output/Notations4.out
@@ -0,0 +1,17 @@
+[< 0 > + < 1 > * < 2 >]
+ : nat
+[<< # 0 >>]
+ : option nat
+[1 {f 1}]
+ : Expr
+fun (x : nat) (y z : Expr) => [1 + y z + {f x}]
+ : nat -> Expr -> Expr -> Expr
+fun e : Expr =>
+match e with
+| [x y + z] => [x + y z]
+| [1 + 1] => [1]
+| _ => [e + e]
+end
+ : Expr -> Expr
+[(1 + 1)]
+ : Expr
diff --git a/test-suite/output/Notations4.v b/test-suite/output/Notations4.v
new file mode 100644
index 0000000000..9738ce5a5e
--- /dev/null
+++ b/test-suite/output/Notations4.v
@@ -0,0 +1,68 @@
+(* An example with constr subentries *)
+
+Module A.
+
+Declare Custom Entry myconstr.
+
+Notation "[ x ]" := x (x custom myconstr at level 6).
+Notation "x + y" := (Nat.add x y) (in custom myconstr at level 5).
+Notation "x * y" := (Nat.mul x y) (in custom myconstr at level 4).
+Notation "< x >" := x (in custom myconstr at level 3, x constr at level 10).
+Check [ < 0 > + < 1 > * < 2 >].
+
+Declare Custom Entry anotherconstr.
+
+Notation "[ x ]" := x (x custom myconstr at level 6).
+Notation "<< x >>" := x (in custom myconstr at level 3, x custom anotherconstr at level 10).
+Notation "# x" := (Some x) (in custom anotherconstr at level 8, x constr at level 9).
+Check [ << # 0 >> ].
+
+End A.
+
+Module B.
+
+Inductive Expr :=
+ | Mul : Expr -> Expr -> Expr
+ | Add : Expr -> Expr -> Expr
+ | One : Expr.
+
+Declare Custom Entry expr.
+Notation "[ expr ]" := expr (expr custom expr at level 2).
+Notation "1" := One (in custom expr at level 0).
+Notation "x y" := (Mul x y) (in custom expr at level 1, left associativity).
+Notation "x + y" := (Add x y) (in custom expr at level 2, left associativity).
+Notation "( x )" := x (in custom expr at level 0, x at level 2).
+Notation "{ x }" := x (in custom expr at level 0, x constr).
+Notation "x" := x (in custom expr at level 0, x ident).
+
+Axiom f : nat -> Expr.
+Check [1 {f 1}].
+Check fun x y z => [1 + y z + {f x}].
+Check fun e => match e with
+| [x y + z] => [x + y z]
+| [1 + 1] => [1]
+| y => [y + e]
+end.
+
+End B.
+
+Module C.
+
+Inductive Expr :=
+ | Add : Expr -> Expr -> Expr
+ | One : Expr.
+
+Declare Custom Entry expr.
+Notation "[ expr ]" := expr (expr custom expr at level 1).
+Notation "1" := One (in custom expr at level 0).
+Notation "x + y" := (Add x y) (in custom expr at level 2, left associativity).
+Notation "( x )" := x (in custom expr at level 0, x at level 2).
+
+(* Check the use of a two-steps coercion from constr to expr 1 then
+ from expr 0 to expr 2 (note that camlp5 parsing is more tolerant
+ and does not require parentheses to parse from level 2 while at
+ level 1) *)
+
+Check [1 + 1].
+
+End C.
diff --git a/test-suite/output/RecordMissingField.out b/test-suite/output/RecordMissingField.out
new file mode 100644
index 0000000000..7c80a6065f
--- /dev/null
+++ b/test-suite/output/RecordMissingField.out
@@ -0,0 +1,4 @@
+File "stdin", line 8, characters 5-22:
+Error: Cannot infer field y2p of record point2d in environment:
+p : point2d
+
diff --git a/test-suite/output/RecordMissingField.v b/test-suite/output/RecordMissingField.v
new file mode 100644
index 0000000000..84f1748fa0
--- /dev/null
+++ b/test-suite/output/RecordMissingField.v
@@ -0,0 +1,8 @@
+(** Check for error message when missing a record field. Error message
+should contain missing field, and the inferred type of the record **)
+
+Record point2d := mkPoint { x2p: nat; y2p: nat }.
+
+
+Definition increment_x (p: point2d) : point2d :=
+ {| x2p := x2p p + 1; |}.
diff --git a/test-suite/output/ssr_explain_match.out b/test-suite/output/ssr_explain_match.out
index fa2393b910..32cfb354bf 100644
--- a/test-suite/output/ssr_explain_match.out
+++ b/test-suite/output/ssr_explain_match.out
@@ -1,35 +1,35 @@
File "stdin", line 12, characters 0-61:
-Warning: Notation _ - _ was already used in scope nat_scope.
+Warning: Notation "_ - _" was already used in scope nat_scope.
[notation-overridden,parsing]
File "stdin", line 12, characters 0-61:
-Warning: Notation _ <= _ was already used in scope nat_scope.
+Warning: Notation "_ <= _" was already used in scope nat_scope.
[notation-overridden,parsing]
File "stdin", line 12, characters 0-61:
-Warning: Notation _ < _ was already used in scope nat_scope.
+Warning: Notation "_ < _" was already used in scope nat_scope.
[notation-overridden,parsing]
File "stdin", line 12, characters 0-61:
-Warning: Notation _ >= _ was already used in scope nat_scope.
+Warning: Notation "_ >= _" was already used in scope nat_scope.
[notation-overridden,parsing]
File "stdin", line 12, characters 0-61:
-Warning: Notation _ > _ was already used in scope nat_scope.
+Warning: Notation "_ > _" was already used in scope nat_scope.
[notation-overridden,parsing]
File "stdin", line 12, characters 0-61:
-Warning: Notation _ <= _ <= _ was already used in scope nat_scope.
+Warning: Notation "_ <= _ <= _" was already used in scope nat_scope.
[notation-overridden,parsing]
File "stdin", line 12, characters 0-61:
-Warning: Notation _ < _ <= _ was already used in scope nat_scope.
+Warning: Notation "_ < _ <= _" was already used in scope nat_scope.
[notation-overridden,parsing]
File "stdin", line 12, characters 0-61:
-Warning: Notation _ <= _ < _ was already used in scope nat_scope.
+Warning: Notation "_ <= _ < _" was already used in scope nat_scope.
[notation-overridden,parsing]
File "stdin", line 12, characters 0-61:
-Warning: Notation _ < _ < _ was already used in scope nat_scope.
+Warning: Notation "_ < _ < _" was already used in scope nat_scope.
[notation-overridden,parsing]
File "stdin", line 12, characters 0-61:
-Warning: Notation _ + _ was already used in scope nat_scope.
+Warning: Notation "_ + _" was already used in scope nat_scope.
[notation-overridden,parsing]
File "stdin", line 12, characters 0-61:
-Warning: Notation _ * _ was already used in scope nat_scope.
+Warning: Notation "_ * _" was already used in scope nat_scope.
[notation-overridden,parsing]
BEGIN INSTANCES
instance: (x + y + z) matches: (x + y + z)
diff --git a/test-suite/success/ssr_delayed_clear_rename.v b/test-suite/ssr/delayed_clear_rename.v
index 951e5aff79..951e5aff79 100644
--- a/test-suite/success/ssr_delayed_clear_rename.v
+++ b/test-suite/ssr/delayed_clear_rename.v
diff --git a/test-suite/ssr/rewrite_illtyped.v b/test-suite/ssr/rewrite_illtyped.v
new file mode 100644
index 0000000000..7358068c8d
--- /dev/null
+++ b/test-suite/ssr/rewrite_illtyped.v
@@ -0,0 +1,9 @@
+From Coq Require Import ssreflect Setoid.
+
+Structure SEProp := {prop_of : Prop; _ : prop_of <-> True}.
+
+Fact anomaly: forall P : SEProp, prop_of P.
+Proof.
+move=> [P E].
+Fail rewrite E.
+Abort.
diff --git a/test-suite/success/BracketsWithGoalSelector.v b/test-suite/success/BracketsWithGoalSelector.v
index ed035f5213..2f7425bce6 100644
--- a/test-suite/success/BracketsWithGoalSelector.v
+++ b/test-suite/success/BracketsWithGoalSelector.v
@@ -14,3 +14,12 @@ Proof.
Fail Qed.
}
Qed.
+
+Lemma foo (n: nat) (P : nat -> Prop):
+ P n.
+Proof.
+ intros.
+ refine (nat_ind _ ?[Base] ?[Step] _).
+ [Base]: { admit. }
+ [Step]: { admit. }
+Abort.
diff --git a/test-suite/success/Hints.v b/test-suite/success/Hints.v
index 717dc0debe..ebf5b094e1 100644
--- a/test-suite/success/Hints.v
+++ b/test-suite/success/Hints.v
@@ -183,3 +183,33 @@ End HintCut.
Goal forall (m : nat), exists n, m = n /\ m = n.
intros m; eexists; split; [trivial | reflexivity].
Qed.
+
+Section HintTransparent.
+
+ Definition fn (x : nat) := S x.
+
+ Create HintDb trans.
+
+ Hint Resolve eq_refl | (_ = _) : trans.
+
+ (* No reduction *)
+ Hint Variables Opaque : trans. Hint Constants Opaque : trans.
+
+ Goal forall x : nat, fn x = S x.
+ Proof.
+ intros.
+ Fail typeclasses eauto with trans.
+ unfold fn.
+ typeclasses eauto with trans.
+ Qed.
+
+ (** Now allow unfolding fn *)
+ Hint Constants Transparent : trans.
+
+ Goal forall x : nat, fn x = S x.
+ Proof.
+ intros.
+ typeclasses eauto with trans.
+ Qed.
+
+End HintTransparent.
diff --git a/test-suite/success/Fourier.v b/test-suite/success/LraTest.v
index b63bead477..bf3a87da25 100644
--- a/test-suite/success/Fourier.v
+++ b/test-suite/success/LraTest.v
@@ -1,12 +1,14 @@
-Require Import Rfunctions.
-Require Import Fourier.
+Require Import Reals.
+Require Import Lra.
+
+Open Scope R_scope.
Lemma l1 : forall x y z : R, Rabs (x - z) <= Rabs (x - y) + Rabs (y - z).
-intros; split_Rabs; fourier.
+intros; split_Rabs; lra.
Qed.
Lemma l2 :
forall x y : R, x < Rabs y -> y < 1 -> x >= 0 -> - y <= 1 -> Rabs x <= 1.
intros.
-split_Rabs; fourier.
+split_Rabs; lra.
Qed.
diff --git a/test-suite/success/LtacDeprecation.v b/test-suite/success/LtacDeprecation.v
new file mode 100644
index 0000000000..633a5e4749
--- /dev/null
+++ b/test-suite/success/LtacDeprecation.v
@@ -0,0 +1,32 @@
+Set Warnings "+deprecated".
+
+#[deprecated(since = "8.8", note = "Use idtac instead")]
+Ltac foo x := idtac.
+
+Goal True.
+Fail (foo true).
+Abort.
+
+Fail Ltac bar := foo.
+Fail Tactic Notation "bar" := foo.
+
+#[deprecated(since = "8.8", note = "Use idtac instead")]
+Tactic Notation "bar" := idtac.
+
+Goal True.
+Fail bar.
+Abort.
+
+Fail Ltac zar := bar.
+
+Set Warnings "-deprecated".
+
+Ltac zar := foo.
+Ltac zarzar := bar.
+
+Set Warnings "+deprecated".
+
+Goal True.
+zar x.
+zarzar.
+Abort.
diff --git a/test-suite/success/Notations2.v b/test-suite/success/Notations2.v
index 7c2cf3ee52..1b33863e3b 100644
--- a/test-suite/success/Notations2.v
+++ b/test-suite/success/Notations2.v
@@ -126,3 +126,31 @@ Notation "'myexists' x , p" := (ex (fun x => p))
(at level 200, x ident, p at level 200, right associativity) : type_scope.
Check myexists I, I = 0. (* Should not be seen as a constructor *)
End M14.
+
+(* 15. Testing different ways to give the same levels without failing *)
+
+Module M15.
+ Local Notation "###### x" := (S x) (right associativity, at level 79, x at next level).
+ Fail Local Notation "###### x" := (S x) (right associativity, at level 79).
+ Local Notation "###### x" := (S x) (at level 79).
+End M15.
+
+(* 16. Some test about custom entries *)
+Module M16.
+ (* Test locality *)
+ Local Declare Custom Entry foo.
+ Fail Notation "#" := 0 (in custom foo). (* Should be local *)
+ Local Notation "#" := 0 (in custom foo).
+
+ (* Test import *)
+ Module A.
+ Declare Custom Entry foo2.
+ End A.
+ Fail Notation "##" := 0 (in custom foo2).
+ Import A.
+ Local Notation "##" := 0 (in custom foo2).
+
+ (* Test Print Grammar *)
+ Print Grammar foo.
+ Print Grammar foo2.
+End M16.
diff --git a/test-suite/success/attribute-syntax.v b/test-suite/success/attribute-syntax.v
new file mode 100644
index 0000000000..83fb3d0c8e
--- /dev/null
+++ b/test-suite/success/attribute-syntax.v
@@ -0,0 +1,23 @@
+From Coq Require Program.
+
+Section Scope.
+
+#[local] Coercion nat_of_bool (b: bool) : nat :=
+ if b then 0 else 1.
+
+Check (refl_equal : true = 0 :> nat).
+
+End Scope.
+
+Fail Check 0 = true :> nat.
+
+#[polymorphic]
+Definition ι T (x: T) := x.
+
+Check ι _ ι.
+
+#[program]
+Fixpoint f (n: nat) {wf lt n} : nat := _.
+
+#[deprecated(since="8.9.0")]
+Ltac foo := foo.
diff --git a/test-suite/success/mutual_record.v b/test-suite/success/mutual_record.v
new file mode 100644
index 0000000000..77529733be
--- /dev/null
+++ b/test-suite/success/mutual_record.v
@@ -0,0 +1,57 @@
+Module M0.
+
+Inductive foo (A : Type) := Foo {
+ foo0 : option (bar A);
+ foo1 : nat;
+ foo2 := foo1 = 0;
+ foo3 : foo2;
+}
+
+with bar (A : Type) := Bar {
+ bar0 : A;
+ bar1 := 0;
+ bar2 : bar1 = 0;
+ bar3 : nat -> foo A;
+}.
+
+End M0.
+
+Module M1.
+
+Set Primitive Projections.
+
+Inductive foo (A : Type) := Foo {
+ foo0 : option (bar A);
+ foo1 : nat;
+ foo2 := foo1 = 0;
+ foo3 : foo2;
+}
+
+with bar (A : Type) := Bar {
+ bar0 : A;
+ bar1 := 0;
+ bar2 : bar1 = 0;
+ bar3 : nat -> foo A;
+}.
+
+End M1.
+
+Module M2.
+
+Set Primitive Projections.
+
+CoInductive foo (A : Type) := Foo {
+ foo0 : option (bar A);
+ foo1 : nat;
+ foo2 := foo1 = 0;
+ foo3 : foo2;
+}
+
+with bar (A : Type) := Bar {
+ bar0 : A;
+ bar1 := 0;
+ bar2 : bar1 = 0;
+ bar3 : nat -> foo A;
+}.
+
+End M2.
diff --git a/test-suite/success/primitiveproj.v b/test-suite/success/primitiveproj.v
index 7ca2767a53..299b08bdd1 100644
--- a/test-suite/success/primitiveproj.v
+++ b/test-suite/success/primitiveproj.v
@@ -193,12 +193,13 @@ Set Primitive Projections.
Record s (x:nat) (y:=S x) := {c:=x; d:x=c}.
Lemma f : 0=1.
Proof.
-Fail apply d.
+ Fail apply d.
(*
split.
reflexivity.
Qed.
*)
+Abort.
(* Primitive projection match compilation *)
Require Import List.
@@ -220,3 +221,9 @@ Fixpoint split_at {A} (l : list A) (n : nat) : prod (list A) (list A) :=
Time Eval vm_compute in split_at (repeat 0 20) 10. (* Takes 0s *)
Time Eval vm_compute in split_at (repeat 0 40) 20. (* Takes 0.001s *)
Timeout 1 Time Eval vm_compute in split_at (repeat 0 60) 30. (* Used to take 60s, now takes 0.001s *)
+
+Check (@eq_refl _ 0 <: 0 = fst (pair 0 1)).
+Fail Check (@eq_refl _ 0 <: 0 = snd (pair 0 1)).
+
+Check (@eq_refl _ 0 <<: 0 = fst (pair 0 1)).
+Fail Check (@eq_refl _ 0 <<: 0 = snd (pair 0 1)).
diff --git a/test-suite/success/uniform_inductive_parameters.v b/test-suite/success/uniform_inductive_parameters.v
new file mode 100644
index 0000000000..42236a5313
--- /dev/null
+++ b/test-suite/success/uniform_inductive_parameters.v
@@ -0,0 +1,13 @@
+Set Uniform Inductive Parameters.
+
+Inductive list (A : Type) :=
+ | nil : list
+ | cons : A -> list -> list.
+Check (list : Type -> Type).
+Check (cons : forall A, A -> list A -> list A).
+
+Inductive list2 (A : Type) (A' := prod A A) :=
+ | nil2 : list2
+ | cons2 : A' -> list2 -> list2.
+Check (list2 : Type -> Type).
+Check (cons2 : forall A (A' := prod A A), A' -> list2 A -> list2 A).
diff --git a/test-suite/success/vm_records.v b/test-suite/success/vm_records.v
new file mode 100644
index 0000000000..8a1544c8ea
--- /dev/null
+++ b/test-suite/success/vm_records.v
@@ -0,0 +1,40 @@
+Set Primitive Projections.
+
+Module M.
+
+CoInductive foo := Foo {
+ foo0 : foo;
+ foo1 : bar;
+}
+with bar := Bar {
+ bar0 : foo;
+ bar1 : bar;
+}.
+
+CoFixpoint f : foo := Foo f g
+with g : bar := Bar f g.
+
+Check (@eq_refl _ g.(bar0) <: f.(foo0).(foo0) = g.(bar0)).
+Check (@eq_refl _ g <: g.(bar1).(bar0).(foo1) = g).
+
+End M.
+
+Module N.
+
+Inductive foo := Foo {
+ foo0 : option foo;
+ foo1 : list bar;
+}
+with bar := Bar {
+ bar0 : option bar;
+ bar1 : list foo;
+}.
+
+Definition f_0 := Foo None nil.
+Definition g_0 := Bar None nil.
+
+Definition f := Foo (Some f_0) (cons g_0 nil).
+
+Check (@eq_refl _ f.(foo1) <: f.(foo1) = cons g_0 nil).
+
+End N.
diff --git a/test-suite/unit-tests/.merlin b/test-suite/unit-tests/.merlin.in
index b2279de74e..b2279de74e 100644
--- a/test-suite/unit-tests/.merlin
+++ b/test-suite/unit-tests/.merlin.in
diff --git a/test-suite/unit-tests/clib/inteq.ml b/test-suite/unit-tests/clib/inteq.ml
index c07ec293f0..89717c79d5 100644
--- a/test-suite/unit-tests/clib/inteq.ml
+++ b/test-suite/unit-tests/clib/inteq.ml
@@ -1,5 +1,7 @@
open Utest
+let log_out_ch = open_log_out_ch __FILE__
+
let eq0 = mk_bool_test "clib-inteq0"
"Int.equal on 0"
(Int.equal 0 0)
@@ -10,4 +12,4 @@ let eq42 = mk_bool_test "clib-inteq42"
let tests = [ eq0; eq42 ]
-let _ = run_tests __FILE__ tests
+let _ = run_tests __FILE__ log_out_ch tests
diff --git a/test-suite/unit-tests/clib/unicode_tests.ml b/test-suite/unit-tests/clib/unicode_tests.ml
index 9ae405977b..95316ad3aa 100644
--- a/test-suite/unit-tests/clib/unicode_tests.ml
+++ b/test-suite/unit-tests/clib/unicode_tests.ml
@@ -1,5 +1,7 @@
open Utest
+let log_out_ch = open_log_out_ch __FILE__
+
let unicode0 = mk_eq_test "clib-unicode0"
"split_at_first_letter, first letter is character"
None
@@ -12,4 +14,4 @@ let unicode1 = mk_eq_test "clib-unicode1"
let tests = [ unicode0; unicode1 ]
-let _ = run_tests __FILE__ tests
+let _ = run_tests __FILE__ log_out_ch tests
diff --git a/test-suite/unit-tests/printing/proof_diffs_test.ml b/test-suite/unit-tests/printing/proof_diffs_test.ml
new file mode 100644
index 0000000000..526cefec44
--- /dev/null
+++ b/test-suite/unit-tests/printing/proof_diffs_test.ml
@@ -0,0 +1,333 @@
+open OUnit
+open Utest
+open Pp_diff
+open Proof_diffs
+
+let tokenize_string = Proof_diffs.tokenize_string
+let diff_pp = diff_pp ~tokenize_string
+let diff_str = diff_str ~tokenize_string
+
+let tests = ref []
+let add_test name test = tests := (mk_test name (TestCase test)) :: !tests
+
+let log_out_ch = open_log_out_ch __FILE__
+let cfprintf oc = Printf.(kfprintf (fun oc -> fprintf oc "") oc)
+let cprintf s = cfprintf log_out_ch s
+let _ = Proof_diffs.log_out_ch := log_out_ch
+
+let string_of_string s : string = "\"" ^ s ^ "\""
+
+(* todo: OCaml: why can't the body of the test function be given in the add_test line? *)
+
+let t () =
+ let expected : diff_list = [] in
+ let diffs = diff_str "" " " in
+
+ assert_equal ~msg:"empty" ~printer:string_of_diffs expected diffs;
+ let (has_added, has_removed) = has_changes diffs in
+ assert_equal ~msg:"has `Added" ~printer:string_of_bool false has_added;
+ assert_equal ~msg:"has `Removed" ~printer:string_of_bool false has_removed
+let _ = add_test "diff_str empty" t
+
+
+let t () =
+ let expected : diff_list =
+ [ `Common (0, 0, "a"); `Common (1, 1, "b"); `Common (2, 2, "c")] in
+ let diffs = diff_str "a b c" " a b\t c\n" in
+
+ assert_equal ~msg:"white space" ~printer:string_of_diffs expected diffs;
+ let (has_added, has_removed) = has_changes diffs in
+ assert_equal ~msg:"no `Added" ~printer:string_of_bool false has_added;
+ assert_equal ~msg:"no `Removed" ~printer:string_of_bool false has_removed
+let _ = add_test "diff_str white space" t
+
+let t () =
+ let expected : diff_list = [ `Removed (0, "a"); `Added (0, "b")] in
+ let diffs = diff_str "a" "b" in
+
+ assert_equal ~msg:"add/remove" ~printer:string_of_diffs expected diffs;
+ let (has_added, has_removed) = has_changes diffs in
+ assert_equal ~msg:"has `Added" ~printer:string_of_bool true has_added;
+ assert_equal ~msg:"has `Removed" ~printer:string_of_bool true has_removed
+let _ = add_test "diff_str add/remove" t
+
+(* example of a limitation, not really a test *)
+let t () =
+ try
+ let _ = diff_str "a" "&gt;" in
+ assert_failure "unlexable string gives an exception"
+ with _ -> ()
+let _ = add_test "diff_str unlexable" t
+
+(* problematic examples for tokenize_string:
+ comments omitted
+ quoted string loses quote marks (are escapes supported/handled?)
+ char constant split into 2
+ *)
+let t () =
+ List.iter (fun x -> cprintf "'%s' " x) (tokenize_string "(* comment *) \"string\" 'c' xx");
+ cprintf "\n"
+let _ = add_test "tokenize_string examples" t
+
+open Pp
+
+(* note pp_to_string concatenates adjacent strings, could become one token,
+e.g. str " a" ++ str "b " will give a token "ab" *)
+(* checks background is present and correct *)
+let t () =
+ let o_pp = str "a" ++ str "!" ++ str "c" in
+ let n_pp = str "a" ++ str "?" ++ str "c" in
+ let (o_exp, n_exp) = (wrap_in_bg "diff.removed" (str "a" ++ (tag "diff.removed" (str "!")) ++ str "c"),
+ wrap_in_bg "diff.added" (str "a" ++ (tag "diff.added" (str "?")) ++ str "c")) in
+ let (o_diff, n_diff) = diff_pp o_pp n_pp in
+
+ assert_equal ~msg:"removed" ~printer:db_string_of_pp o_exp o_diff;
+ assert_equal ~msg:"added" ~printer:db_string_of_pp n_exp n_diff
+let _ = add_test "diff_pp/add_diff_tags add/remove" t
+
+let t () =
+ (*Printf.printf "%s\n" (string_of_diffs (diff_str "a d" "a b c d"));*)
+ let o_pp = str "a" ++ str " d" in
+ let n_pp = str "a" ++ str " b " ++ str " c " ++ str "d" ++ str " e " in
+ let n_exp = flatten (wrap_in_bg "diff.added" (seq [
+ str "a";
+ str " "; (tag "start.diff.added" (str "b "));
+ (tag "end.diff.added" (str " c")); str " ";
+ (str "d");
+ str " "; (tag "diff.added" (str "e")); str " "
+ ])) in
+ let (_, n_diff) = diff_pp o_pp n_pp in
+
+ assert_equal ~msg:"added" ~printer:db_string_of_pp n_exp (flatten n_diff);;
+let _ = add_test "diff_pp/add_diff_tags a span with spaces" t
+
+
+let t () =
+ let o_pp = str " " in
+ let n_pp = tag "sometag" (str "a") in
+ let n_exp = flatten (wrap_in_bg "diff.added" (tag "diff.added" (tag "sometag" (str "a")))) in
+ let (_, n_diff) = diff_pp o_pp n_pp in
+
+ assert_equal ~msg:"added" ~printer:db_string_of_pp n_exp (flatten n_diff)
+let _ = add_test "diff_pp/add_diff_tags diff tags outside existing tags" t
+
+let t () =
+ let o_pp = str " " in
+ let n_pp = seq [(tag "sometag" (str " a ")); str "b"] in
+ let n_exp = flatten (wrap_in_bg "diff.added"
+ (seq [tag "sometag" (str " "); (tag "start.diff.added" (tag "sometag" (str "a ")));
+ (tag "end.diff.added" (str "b"))]) ) in
+ let (_, n_diff) = diff_pp o_pp n_pp in
+
+ assert_equal ~msg:"added" ~printer:db_string_of_pp n_exp (flatten n_diff)
+let _ = add_test "diff_pp/add_diff_tags existing tagged values with spaces" t
+
+let t () =
+ let o_pp = str " " in
+ let n_pp = str " a b " in
+ let n_exp = flatten (wrap_in_bg "diff.added"
+ (seq [str " "; tag "diff.added" (str "a b"); str " "])) in
+ let (_, n_diff) = diff_pp o_pp n_pp in
+
+ assert_equal ~msg:"added" ~printer:db_string_of_pp n_exp (flatten n_diff)
+let _ = add_test "diff_pp/add_diff_tags multiple tokens in pp" t
+
+let t () =
+ let o_pp = str "a d" in
+ let n_pp = seq [str "a b"; str "c d"] in
+ let n_exp = flatten (wrap_in_bg "diff.added"
+ (seq [str "a "; tag "start.diff.added" (str "b");
+ tag "end.diff.added" (str "c"); str " d"])) in
+ let (_, n_diff) = diff_pp o_pp n_pp in
+
+ assert_equal ~msg:"added" ~printer:db_string_of_pp n_exp (flatten n_diff)
+let _ = add_test "diff_pp/add_diff_tags token spanning multiple Ppcmd_strs" t
+
+let t () =
+ let o_pp = seq [str ""; str "a"] in
+ let n_pp = seq [str ""; str "a b"] in
+ let n_exp = flatten (wrap_in_bg "diff.added"
+ (seq [str ""; str "a "; tag "diff.added" (str "b")])) in
+ let (_, n_diff) = diff_pp o_pp n_pp in
+
+ assert_equal ~msg:"added" ~printer:db_string_of_pp n_exp (flatten n_diff)
+let _ = add_test "diff_pp/add_diff_tags empty string preserved" t
+
+(* todo: awaiting a change in the lexer to return the quotes of the string token *)
+let t () =
+ let s = "\"a b\"" in
+ let o_pp = seq [str s] in
+ let n_pp = seq [str "\"a b\" "] in
+ cprintf "ppcmds: %s\n" (string_of_ppcmds n_pp);
+ let n_exp = flatten (wrap_in_bg "diff.added"
+ (seq [str ""; str "a "; tag "diff.added" (str "b")])) in
+ let (_, n_diff) = diff_pp o_pp n_pp in
+
+ assert_equal ~msg:"string" ~printer:string_of_string "a b" (List.hd (tokenize_string s));
+ assert_equal ~msg:"added" ~printer:db_string_of_pp n_exp (flatten n_diff)
+let _ = if false then add_test "diff_pp/add_diff_tags token containing white space" t
+
+let add_entries map idents rhs_pp =
+ let make_entry() = { idents; rhs_pp; done_ = false } in
+ List.iter (fun ident -> map := (StringMap.add ident (make_entry ()) !map); ()) idents;;
+
+let print_list hyps = List.iter (fun x -> cprintf "%s\n" (string_of_ppcmds (flatten x))) hyps
+let db_print_list hyps = List.iter (fun x -> cprintf "%s\n" (db_string_of_pp (flatten x))) hyps
+
+
+(* a : foo
+ b : bar car ->
+ b : car
+ a : foo bar *)
+let t () =
+ write_diffs_option "removed"; (* turn on "removed" option *)
+ let o_line_idents = [ ["a"]; ["b"]] in
+ let o_hyp_map = ref StringMap.empty in
+ add_entries o_hyp_map ["a"] (str " : foo");
+ add_entries o_hyp_map ["b"] (str " : bar car");
+ let n_line_idents = [ ["b"]; ["a"]] in
+ let n_hyp_map = ref StringMap.empty in
+ add_entries n_hyp_map ["b"] (str " : car");
+ add_entries n_hyp_map ["a"] (str " : foo bar");
+ let expected = [flatten (wrap_in_bg "diff.removed" (seq [str "b"; str " : "; (tag "diff.removed" (str "bar")); str " car" ]));
+ flatten (wrap_in_bg "diff.added" (seq [str "b"; str " : car" ]));
+ flatten (wrap_in_bg "diff.added" (seq [str "a"; str " : foo "; (tag "diff.added" (str "bar")) ]))
+ ] in
+
+ let hyps_diff_list = diff_hyps o_line_idents !o_hyp_map n_line_idents !n_hyp_map in
+
+ (*print_list hyps_diff_list;*)
+ (*db_print_list hyps_diff_list;*)
+
+ List.iter2 (fun exp act ->
+ assert_equal ~msg:"added" ~printer:db_string_of_pp exp (flatten act))
+ expected hyps_diff_list
+let _ = add_test "diff_hyps simple diffs" t
+
+(* a : nat
+ c, d : int ->
+ a, b : nat
+ d : int
+ and keeps old order *)
+let t () =
+ write_diffs_option "removed"; (* turn on "removed" option *)
+ let o_line_idents = [ ["a"]; ["c"; "d"]] in
+ let o_hyp_map = ref StringMap.empty in
+ add_entries o_hyp_map ["a"] (str " : nat");
+ add_entries o_hyp_map ["c"; "d"] (str " : int");
+ let n_line_idents = [ ["a"; "b"]; ["d"]] in
+ let n_hyp_map = ref StringMap.empty in
+ add_entries n_hyp_map ["a"; "b"] (str " : nat");
+ add_entries n_hyp_map ["d"] (str " : int");
+ let expected = [flatten (wrap_in_bg "diff.added" (seq [str "a"; (tag "start.diff.added" (str ", ")); (tag "end.diff.added" (str "b")); str " : nat" ]));
+ flatten (wrap_in_bg "diff.removed" (seq [(tag "start.diff.removed" (str "c")); (tag "end.diff.removed" (str ",")); str " "; str "d"; str " : int" ]));
+ flatten (wrap_in_bg "diff.added" (seq [str "d"; str " : int" ]))
+ ] in
+
+ let hyps_diff_list = diff_hyps o_line_idents !o_hyp_map n_line_idents !n_hyp_map in
+
+ (*print_list hyps_diff_list;*)
+ (*print_list expected;*)
+
+ (*db_print_list hyps_diff_list;*)
+ (*db_print_list expected;*)
+
+ List.iter2 (fun exp act ->
+ assert_equal ~msg:"added" ~printer:db_string_of_pp exp (flatten act))
+ expected hyps_diff_list
+let _ = add_test "diff_hyps compacted" t
+
+(* a : foo
+ b : bar
+ c : nat ->
+ b, a, c : nat
+DIFFS
+ b : bar (remove bar)
+ b : nat (add nat)
+ a : foo (remove foo)
+ a : nat (add nat)
+ c : nat
+ is this a realistic use case?
+*)
+let t () =
+ write_diffs_option "removed"; (* turn on "removed" option *)
+ let o_line_idents = [ ["a"]; ["b"]; ["c"]] in
+ let o_hyp_map = ref StringMap.empty in
+ add_entries o_hyp_map ["a"] (str " : foo");
+ add_entries o_hyp_map ["b"] (str " : bar");
+ add_entries o_hyp_map ["c"] (str " : nat");
+ let n_line_idents = [ ["b"; "a"; "c"] ] in
+ let n_hyp_map = ref StringMap.empty in
+ add_entries n_hyp_map ["b"; "a"; "c"] (str " : nat");
+ let expected = [flatten (wrap_in_bg "diff.removed" (seq [str "b"; str " : "; (tag "diff.removed" (str "bar"))]));
+ flatten (wrap_in_bg "diff.added" (seq [str "b"; str " : "; (tag "diff.added" (str "nat"))]));
+ flatten (wrap_in_bg "diff.removed" (seq [str "a"; str " : "; (tag "diff.removed" (str "foo"))]));
+ flatten (wrap_in_bg "diff.added" (seq [str "a"; str " : "; (tag "diff.added" (str "nat"))]));
+ flatten (seq [str "c"; str " : nat"])
+ ] in
+
+ let hyps_diff_list = diff_hyps o_line_idents !o_hyp_map n_line_idents !n_hyp_map in
+
+ (*print_list hyps_diff_list;*)
+ (*db_print_list hyps_diff_list;*)
+
+ List.iter2 (fun exp act ->
+ assert_equal ~msg:"added" ~printer:db_string_of_pp exp (flatten act))
+ expected hyps_diff_list
+let _ = add_test "diff_hyps compacted with join" t
+
+(* b, a, c : nat ->
+ a : foo
+ b : bar
+ c : nat
+DIFFS
+ a : nat (remove nat)
+ a : foo (add foo)
+ b : nat (remove nat)
+ b : bar (add bar)
+ c : nat
+ is this a realistic use case? *)
+let t () =
+ write_diffs_option "removed"; (* turn on "removed" option *)
+ let o_line_idents = [ ["b"; "a"; "c"] ] in
+ let o_hyp_map = ref StringMap.empty in
+ add_entries o_hyp_map ["b"; "a"; "c"] (str " : nat");
+ let n_line_idents = [ ["a"]; ["b"]; ["c"]] in
+ let n_hyp_map = ref StringMap.empty in
+ add_entries n_hyp_map ["a"] (str " : foo");
+ add_entries n_hyp_map ["b"] (str " : bar");
+ add_entries n_hyp_map ["c"] (str " : nat");
+ let expected = [flatten (wrap_in_bg "diff.removed" (seq [str "a"; str " : "; (tag "diff.removed" (str "nat"))]));
+ flatten (wrap_in_bg "diff.added" (seq [str "a"; str " : "; (tag "diff.added" (str "foo"))]));
+ flatten (wrap_in_bg "diff.removed" (seq [str "b"; str " : "; (tag "diff.removed" (str "nat"))]));
+ flatten (wrap_in_bg "diff.added" (seq [str "b"; str " : "; (tag "diff.added" (str "bar"))]));
+ flatten (seq [str "c"; str " : nat"])
+ ] in
+
+ let hyps_diff_list = diff_hyps o_line_idents !o_hyp_map n_line_idents !n_hyp_map in
+
+ (*print_list hyps_diff_list;*)
+ (*db_print_list hyps_diff_list;*)
+
+ List.iter2 (fun exp act ->
+ assert_equal ~msg:"added" ~printer:db_string_of_pp exp (flatten act))
+ expected hyps_diff_list
+let _ = add_test "diff_hyps compacted with split" t
+
+
+(* other potential tests
+coqtop/terminal formatting BLOCKED: CAN'T GET TAGS IN FORMATTER
+ white space at end of line
+ spanning diffs
+shorten_diff_span
+
+MAYBE NOT WORTH IT
+diff_pp/add_diff_tags
+ add/remove - show it preserves, recurs and processes:
+ nested in boxes
+ breaks, etc. preserved
+diff_pp_combined with/without removed
+*)
+
+
+let _ = run_tests __FILE__ log_out_ch (List.rev !tests)
diff --git a/test-suite/unit-tests/src/utest.ml b/test-suite/unit-tests/src/utest.ml
index 069e6a4bf3..0cb1780ec9 100644
--- a/test-suite/unit-tests/src/utest.ml
+++ b/test-suite/unit-tests/src/utest.ml
@@ -42,10 +42,12 @@ let run_one logit test =
let results = perform_test (fun _ -> ()) test in
process_results results
-(* run list of OUnit test cases, log results *)
-let run_tests ml_fn tests =
+let open_log_out_ch ml_fn =
let log_fn = ml_fn ^ ".log" in
- let out_ch = open_out log_fn in
+ open_out log_fn
+
+(* run list of OUnit test cases, log results *)
+let run_tests ml_fn out_ch tests =
let cprintf s = cfprintf out_ch s in
let ceprintf s = cfprintf stderr s in
let logit = logger out_ch in
diff --git a/test-suite/unit-tests/src/utest.mli b/test-suite/unit-tests/src/utest.mli
index 70928228bf..2e0f26e96b 100644
--- a/test-suite/unit-tests/src/utest.mli
+++ b/test-suite/unit-tests/src/utest.mli
@@ -9,4 +9,10 @@ val mk_bool_test : string -> string -> bool -> OUnit.test
(* the string argument should be the name of the .ml file
containing the tests; use __FILE__ for that purpose.
*)
-val run_tests : string -> OUnit.test list -> unit
+val run_tests : string -> out_channel -> OUnit.test list -> unit
+
+(** open output channel for the test log file *)
+(* the string argument should be the name of the .ml file
+ containing the tests; use __FILE__ for that purpose.
+ *)
+val open_log_out_ch : string -> out_channel
diff --git a/theories/Bool/Bool.v b/theories/Bool/Bool.v
index edf78ed52d..66a82008d8 100644
--- a/theories/Bool/Bool.v
+++ b/theories/Bool/Bool.v
@@ -814,3 +814,10 @@ Defined.
(** Reciprocally, from a decidability, we could state a
[reflect] as soon as we have a [bool_of_sumbool]. *)
+
+(** For instance, we could state the correctness of [Bool.eqb] via [reflect]: *)
+
+Lemma eqb_spec (b b' : bool) : reflect (b = b') (eqb b b').
+Proof.
+ destruct b, b'; now constructor.
+Qed.
diff --git a/theories/FSets/FSetAVL.v b/theories/FSets/FSetAVL.v
index 3c9b6b428b..dcaea894eb 100644
--- a/theories/FSets/FSetAVL.v
+++ b/theories/FSets/FSetAVL.v
@@ -15,7 +15,7 @@
It follows the implementation from Ocaml's standard library,
All operations given here expect and produce well-balanced trees
- (in the ocaml sense: heigths of subtrees shouldn't differ by more
+ (in the ocaml sense: heights of subtrees shouldn't differ by more
than 2), and hence has low complexities (e.g. add is logarithmic
in the size of the set). But proving these balancing preservations
is in fact not necessary for ensuring correct operational behavior
diff --git a/theories/FSets/FSetEqProperties.v b/theories/FSets/FSetEqProperties.v
index 56844f4773..59b2f789ab 100644
--- a/theories/FSets/FSetEqProperties.v
+++ b/theories/FSets/FSetEqProperties.v
@@ -333,7 +333,7 @@ Proof.
auto with set.
Qed.
-(* caracterisation of [union] via [subset] *)
+(* characterisation of [union] via [subset] *)
Lemma union_subset_1: subset s (union s s')=true.
Proof.
@@ -408,7 +408,7 @@ intros; apply equal_1; apply inter_add_2.
rewrite not_mem_iff; auto.
Qed.
-(* caracterisation of [union] via [subset] *)
+(* characterisation of [union] via [subset] *)
Lemma inter_subset_1: subset (inter s s') s=true.
Proof.
diff --git a/theories/Init/Logic.v b/theories/Init/Logic.v
index 10ca9ecc92..9d60cf54c3 100644
--- a/theories/Init/Logic.v
+++ b/theories/Init/Logic.v
@@ -29,6 +29,13 @@ Definition not (A:Prop) := A -> False.
Notation "~ x" := (not x) : type_scope.
+(** Create the "core" hint database, and set its transparent state for
+ variables and constants explicitely. *)
+
+Create HintDb core.
+Hint Variables Opaque : core.
+Hint Constants Opaque : core.
+
Hint Unfold not: core.
(** [and A B], written [A /\ B], is the conjunction of [A] and [B]
@@ -452,7 +459,7 @@ Proof.
destruct e. reflexivity.
Defined.
-(** The goupoid structure of equality *)
+(** The groupoid structure of equality *)
Theorem eq_trans_refl_l : forall A (x y:A) (e:x=y), eq_trans eq_refl e = e.
Proof.
diff --git a/theories/MSets/MSetEqProperties.v b/theories/MSets/MSetEqProperties.v
index 1ee098cb07..4f2fdcf94c 100644
--- a/theories/MSets/MSetEqProperties.v
+++ b/theories/MSets/MSetEqProperties.v
@@ -333,7 +333,7 @@ Proof.
auto with set.
Qed.
-(* caracterisation of [union] via [subset] *)
+(* characterisation of [union] via [subset] *)
Lemma union_subset_1: subset s (union s s')=true.
Proof.
@@ -408,7 +408,7 @@ intros; apply equal_1; apply inter_add_2.
rewrite not_mem_iff; auto.
Qed.
-(* caracterisation of [union] via [subset] *)
+(* characterisation of [union] via [subset] *)
Lemma inter_subset_1: subset (inter s s') s=true.
Proof.
diff --git a/theories/MSets/MSetGenTree.v b/theories/MSets/MSetGenTree.v
index 9d2a73ed0f..95868861fa 100644
--- a/theories/MSets/MSetGenTree.v
+++ b/theories/MSets/MSetGenTree.v
@@ -13,7 +13,7 @@
This module factorizes common parts in implementations
of finite sets as AVL trees and as Red-Black trees. The nodes
of the trees defined here include an generic information
- parameter, that will be the heigth in AVL trees and the color
+ parameter, that will be the height in AVL trees and the color
in Red-Black trees. Without more details here about these
information parameters, trees here are not known to be
well-balanced, but simply binary-search-trees.
diff --git a/theories/NArith/Ndigits.v b/theories/NArith/Ndigits.v
index 3ccaa7211a..68a98e4292 100644
--- a/theories/NArith/Ndigits.v
+++ b/theories/NArith/Ndigits.v
@@ -517,6 +517,23 @@ Definition N2Bv (n:N) : Bvector (N.size_nat n) :=
| Npos p => P2Bv p
end.
+Fixpoint P2Bv_sized (m : nat) (p : positive) : Bvector m :=
+ match m with
+ | O => []
+ | S m =>
+ match p with
+ | xI p => true :: P2Bv_sized m p
+ | xO p => false :: P2Bv_sized m p
+ | xH => true :: Bvect_false m
+ end
+ end.
+
+Definition N2Bv_sized (m : nat) (n : N) : Bvector m :=
+ match n with
+ | N0 => Bvect_false m
+ | Npos p => P2Bv_sized m p
+ end.
+
Fixpoint Bv2N (n:nat)(bv:Bvector n) : N :=
match bv with
| Vector.nil _ => N0
@@ -670,3 +687,21 @@ rewrite H.
destruct a, b, (Bv2N n v1), (Bv2N n v2);
simpl; auto.
Qed.
+
+Lemma N2Bv_sized_Nsize (n : N) :
+ N2Bv_sized (N.size_nat n) n = N2Bv n.
+Proof with simpl; auto.
+ destruct n...
+ induction p...
+ all: rewrite IHp...
+Qed.
+
+Lemma N2Bv_sized_Bv2N (n : nat) (v : Bvector n) :
+ N2Bv_sized n (Bv2N n v) = v.
+Proof with simpl; auto.
+ induction v...
+ destruct h;
+ unfold N2Bv_sized;
+ destruct (Bv2N n v) as [|[]];
+ rewrite <- IHv...
+Qed.
diff --git a/theories/Numbers/BinNums.v b/theories/Numbers/BinNums.v
index f8b3d9e1d9..d5eb4f2681 100644
--- a/theories/Numbers/BinNums.v
+++ b/theories/Numbers/BinNums.v
@@ -12,6 +12,8 @@
Set Implicit Arguments.
+Declare ML Module "positive_syntax_plugin".
+Declare ML Module "n_syntax_plugin".
Declare ML Module "z_syntax_plugin".
(** [positive] is a datatype representing the strictly positive integers
diff --git a/theories/Numbers/DecimalString.v b/theories/Numbers/DecimalString.v
index 1a3220f63a..591024baec 100644
--- a/theories/Numbers/DecimalString.v
+++ b/theories/Numbers/DecimalString.v
@@ -94,7 +94,7 @@ Definition int_of_string s :=
match s with
| EmptyString => Some (Pos Nil)
| String a s' =>
- if ascii_dec a "-" then option_map Neg (uint_of_string s')
+ if Ascii.eqb a "-" then option_map Neg (uint_of_string s')
else option_map Pos (uint_of_string s)
end.
@@ -131,8 +131,8 @@ Proof.
- unfold int_of_string.
destruct (string_of_uint d) eqn:Hd.
+ now destruct d.
- + destruct ascii_dec; subst.
- * now destruct d.
+ + case Ascii.eqb_spec.
+ * intros ->. now destruct d.
* rewrite <- Hd, usu; auto.
- rewrite usu; auto.
Qed.
@@ -141,8 +141,8 @@ Lemma sis s d :
int_of_string s = Some d -> string_of_int d = s.
Proof.
destruct s; [intros [= <-]| ]; simpl; trivial.
- destruct ascii_dec; subst; simpl.
- - destruct (uint_of_string s) eqn:Hs; simpl; intros [= <-].
+ case Ascii.eqb_spec.
+ - intros ->. destruct (uint_of_string s) eqn:Hs; simpl; intros [= <-].
simpl; f_equal. now apply sus.
- destruct d; [ | now destruct uint_of_char].
simpl string_of_int.
@@ -178,7 +178,7 @@ Definition int_of_string s :=
match s with
| EmptyString => None
| String a s' =>
- if ascii_dec a "-" then option_map Neg (uint_of_string s')
+ if Ascii.eqb a "-" then option_map Neg (uint_of_string s')
else option_map Pos (uint_of_string s)
end.
@@ -228,8 +228,8 @@ Proof.
unfold int_of_string.
destruct (string_of_uint d) eqn:Hd.
+ now destruct d.
- + destruct ascii_dec; subst.
- * now destruct d.
+ + case Ascii.eqb_spec.
+ * intros ->. now destruct d.
* rewrite <- Hd, usu; auto. now intros ->.
- intros _ H.
rewrite usu; auto. now intros ->.
@@ -253,8 +253,8 @@ Lemma sis s d :
int_of_string s = Some d -> string_of_int d = s.
Proof.
destruct s; [intros [=]| ]; simpl.
- destruct ascii_dec; subst; simpl.
- - destruct (uint_of_string s) eqn:Hs; simpl; intros [= <-].
+ case Ascii.eqb_spec.
+ - intros ->. destruct (uint_of_string s) eqn:Hs; simpl; intros [= <-].
simpl; f_equal. now apply sus.
- destruct d; [ | now destruct uint_of_char].
simpl string_of_int.
diff --git a/theories/Numbers/Integer/Abstract/ZBits.v b/theories/Numbers/Integer/Abstract/ZBits.v
index 2da4452819..4aabda77ee 100644
--- a/theories/Numbers/Integer/Abstract/ZBits.v
+++ b/theories/Numbers/Integer/Abstract/ZBits.v
@@ -80,7 +80,7 @@ Proof.
now apply testbit_even_succ.
Qed.
-(** Alternative caracterisations of [testbit] *)
+(** Alternative characterisations of [testbit] *)
(** This concise equation could have been taken as specification
for testbit in the interface, but it would have been hard to
@@ -102,10 +102,10 @@ Proof.
left. destruct b; split; simpl; order'.
Qed.
-(** This caracterisation that uses only basic operations and
+(** This characterisation that uses only basic operations and
power was initially taken as specification for testbit.
We describe [a] as having a low part and a high part, with
- the corresponding bit in the middle. This caracterisation
+ the corresponding bit in the middle. This characterisation
is moderatly complex to implement, but also moderately
usable... *)
diff --git a/theories/Numbers/Natural/Abstract/NBits.v b/theories/Numbers/Natural/Abstract/NBits.v
index e1391f5990..90663de3f2 100644
--- a/theories/Numbers/Natural/Abstract/NBits.v
+++ b/theories/Numbers/Natural/Abstract/NBits.v
@@ -78,7 +78,7 @@ Proof.
apply testbit_even_succ, le_0_l.
Qed.
-(** Alternative caracterisations of [testbit] *)
+(** Alternative characterisations of [testbit] *)
(** This concise equation could have been taken as specification
for testbit in the interface, but it would have been hard to
@@ -99,10 +99,10 @@ Proof.
destruct b; order'.
Qed.
-(** This caracterisation that uses only basic operations and
+(** This characterisation that uses only basic operations and
power was initially taken as specification for testbit.
We describe [a] as having a low part and a high part, with
- the corresponding bit in the middle. This caracterisation
+ the corresponding bit in the middle. This characterisation
is moderatly complex to implement, but also moderately
usable... *)
diff --git a/theories/Reals/Machin.v b/theories/Reals/Machin.v
index cdf98cbdef..8f7e07ac4d 100644
--- a/theories/Reals/Machin.v
+++ b/theories/Reals/Machin.v
@@ -8,7 +8,7 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
-Require Import Fourier.
+Require Import Lra.
Require Import Rbase.
Require Import Rtrigo1.
Require Import Ranalysis_reg.
@@ -67,7 +67,7 @@ assert (atan x <= PI/4).
assert (atan y < PI/4).
rewrite <- atan_1; apply atan_increasing.
assumption.
-rewrite Ropp_div; split; fourier.
+rewrite Ropp_div; split; lra.
Qed.
(* A simple formula, reasonably efficient. *)
@@ -77,8 +77,8 @@ assert (utility : 0 < PI/2) by (apply PI2_RGT_0).
rewrite <- atan_1.
rewrite (atan_sub_correct 1 (/2)).
apply f_equal, f_equal; unfold atan_sub; field.
- apply Rgt_not_eq; fourier.
- apply tech; try split; try fourier.
+ apply Rgt_not_eq; lra.
+ apply tech; try split; try lra.
apply atan_bound.
Qed.
@@ -86,7 +86,7 @@ Lemma Machin_4_5_239 : PI/4 = 4 * atan (/5) - atan(/239).
Proof.
rewrite <- atan_1.
rewrite (atan_sub_correct 1 (/5));
- [ | apply Rgt_not_eq; fourier | apply tech; try split; fourier |
+ [ | apply Rgt_not_eq; lra | apply tech; try split; lra |
apply atan_bound ].
replace (4 * atan (/5) - atan (/239)) with
(atan (/5) + (atan (/5) + (atan (/5) + (atan (/5) + -
@@ -95,17 +95,17 @@ apply f_equal.
replace (atan_sub 1 (/5)) with (2/3) by
(unfold atan_sub; field).
rewrite (atan_sub_correct (2/3) (/5));
- [apply f_equal | apply Rgt_not_eq; fourier | apply tech; try split; fourier |
+ [apply f_equal | apply Rgt_not_eq; lra | apply tech; try split; lra |
apply atan_bound ].
replace (atan_sub (2/3) (/5)) with (7/17) by
(unfold atan_sub; field).
rewrite (atan_sub_correct (7/17) (/5));
- [apply f_equal | apply Rgt_not_eq; fourier | apply tech; try split; fourier |
+ [apply f_equal | apply Rgt_not_eq; lra | apply tech; try split; lra |
apply atan_bound ].
replace (atan_sub (7/17) (/5)) with (9/46) by
(unfold atan_sub; field).
rewrite (atan_sub_correct (9/46) (/5));
- [apply f_equal | apply Rgt_not_eq; fourier | apply tech; try split; fourier |
+ [apply f_equal | apply Rgt_not_eq; lra | apply tech; try split; lra |
apply atan_bound ].
rewrite <- atan_opp; apply f_equal.
unfold atan_sub; field.
@@ -115,7 +115,7 @@ Lemma Machin_2_3_7 : PI/4 = 2 * atan(/3) + (atan (/7)).
Proof.
rewrite <- atan_1.
rewrite (atan_sub_correct 1 (/3));
- [ | apply Rgt_not_eq; fourier | apply tech; try split; fourier |
+ [ | apply Rgt_not_eq; lra | apply tech; try split; lra |
apply atan_bound ].
replace (2 * atan (/3) + atan (/7)) with
(atan (/3) + (atan (/3) + atan (/7))) by ring.
@@ -123,7 +123,7 @@ apply f_equal.
replace (atan_sub 1 (/3)) with (/2) by
(unfold atan_sub; field).
rewrite (atan_sub_correct (/2) (/3));
- [apply f_equal | apply Rgt_not_eq; fourier | apply tech; try split; fourier |
+ [apply f_equal | apply Rgt_not_eq; lra | apply tech; try split; lra |
apply atan_bound ].
apply f_equal; unfold atan_sub; field.
Qed.
@@ -138,19 +138,19 @@ Lemma PI_2_3_7_ineq :
sum_f_R0 (tg_alt PI_2_3_7_tg) (S (2 * N)) <= PI / 4 <=
sum_f_R0 (tg_alt PI_2_3_7_tg) (2 * N).
Proof.
-assert (dec3 : 0 <= /3 <= 1) by (split; fourier).
-assert (dec7 : 0 <= /7 <= 1) by (split; fourier).
+assert (dec3 : 0 <= /3 <= 1) by (split; lra).
+assert (dec7 : 0 <= /7 <= 1) by (split; lra).
assert (decr : Un_decreasing PI_2_3_7_tg).
apply Ratan_seq_decreasing in dec3.
apply Ratan_seq_decreasing in dec7.
intros n; apply Rplus_le_compat.
- apply Rmult_le_compat_l; [ fourier | exact (dec3 n)].
+ apply Rmult_le_compat_l; [ lra | exact (dec3 n)].
exact (dec7 n).
assert (cv : Un_cv PI_2_3_7_tg 0).
apply Ratan_seq_converging in dec3.
apply Ratan_seq_converging in dec7.
intros eps ep.
- assert (ep' : 0 < eps /3) by fourier.
+ assert (ep' : 0 < eps /3) by lra.
destruct (dec3 _ ep') as [N1 Pn1]; destruct (dec7 _ ep') as [N2 Pn2].
exists (N1 + N2)%nat; intros n Nn.
unfold PI_2_3_7_tg.
@@ -161,14 +161,14 @@ assert (cv : Un_cv PI_2_3_7_tg 0).
apply Rplus_lt_compat.
unfold R_dist, Rminus, Rdiv.
rewrite <- (Rmult_0_r 2), <- Ropp_mult_distr_r_reverse.
- rewrite <- Rmult_plus_distr_l, Rabs_mult, (Rabs_pos_eq 2);[|fourier].
- rewrite Rmult_assoc; apply Rmult_lt_compat_l;[fourier | ].
+ rewrite <- Rmult_plus_distr_l, Rabs_mult, (Rabs_pos_eq 2);[|lra].
+ rewrite Rmult_assoc; apply Rmult_lt_compat_l;[lra | ].
apply (Pn1 n); omega.
apply (Pn2 n); omega.
rewrite Machin_2_3_7.
-rewrite !atan_eq_ps_atan; try (split; fourier).
+rewrite !atan_eq_ps_atan; try (split; lra).
unfold ps_atan; destruct (in_int (/3)); destruct (in_int (/7));
- try match goal with id : ~ _ |- _ => case id; split; fourier end.
+ try match goal with id : ~ _ |- _ => case id; split; lra end.
destruct (ps_atan_exists_1 (/3)) as [v3 Pv3].
destruct (ps_atan_exists_1 (/7)) as [v7 Pv7].
assert (main : Un_cv (sum_f_R0 (tg_alt PI_2_3_7_tg)) (2 * v3 + v7)).
diff --git a/theories/Reals/PSeries_reg.v b/theories/Reals/PSeries_reg.v
index 61d1b5afea..146d691018 100644
--- a/theories/Reals/PSeries_reg.v
+++ b/theories/Reals/PSeries_reg.v
@@ -15,7 +15,7 @@ Require Import Ranalysis1.
Require Import MVT.
Require Import Max.
Require Import Even.
-Require Import Fourier.
+Require Import Lra.
Local Open Scope R_scope.
(* Boule is French for Ball *)
@@ -431,7 +431,7 @@ assert (ctrho : forall n z, Boule c d z -> continuity_pt (rho_ n) z).
intros y dyz; unfold rho_; destruct (Req_EM_T y x) as [xy | xny].
rewrite xy in dyz.
destruct (Rle_dec delta (Rabs (z - x))).
- rewrite Rmin_left, R_dist_sym in dyz; unfold R_dist in dyz; fourier.
+ rewrite Rmin_left, R_dist_sym in dyz; unfold R_dist in dyz; lra.
rewrite Rmin_right, R_dist_sym in dyz; unfold R_dist in dyz;
[case (Rlt_irrefl _ dyz) |apply Rlt_le, Rnot_le_gt; assumption].
reflexivity.
@@ -449,7 +449,7 @@ assert (ctrho : forall n z, Boule c d z -> continuity_pt (rho_ n) z).
assert (CVU rho_ rho c d ).
intros eps ep.
assert (ep8 : 0 < eps/8).
- fourier.
+ lra.
destruct (cvu _ ep8) as [N Pn1].
assert (cauchy1 : forall n p, (N <= n)%nat -> (N <= p)%nat ->
forall z, Boule c d z -> Rabs (f' n z - f' p z) < eps/4).
@@ -537,7 +537,7 @@ assert (CVU rho_ rho c d ).
simpl; unfold R_dist.
unfold Rminus; rewrite (Rplus_comm y), Rplus_assoc, Rplus_opp_r, Rplus_0_r.
rewrite Rabs_pos_eq;[ |apply Rlt_le; assumption ].
- apply Rlt_le_trans with (Rmin (Rmin d' d2) delta);[fourier | ].
+ apply Rlt_le_trans with (Rmin (Rmin d' d2) delta);[lra | ].
apply Rle_trans with (Rmin d' d2); apply Rmin_l.
apply Rle_trans with (1 := R_dist_tri _ _ (rho_ p (y + Rmin (Rmin d' d2) delta/2))).
apply Rplus_le_compat.
@@ -548,33 +548,32 @@ assert (CVU rho_ rho c d ).
replace (rho_ p (y + Rmin (Rmin d' d2) delta / 2)) with
((f p (y + Rmin (Rmin d' d2) delta / 2) - f p x)/
((y + Rmin (Rmin d' d2) delta / 2) - x)).
- apply step_2; auto; try fourier.
+ apply step_2; auto; try lra.
assert (0 < pos delta) by (apply cond_pos).
apply Boule_convex with y (y + delta/2).
assumption.
destruct (Pdelta (y + delta/2)); auto.
- rewrite xy; unfold Boule; rewrite Rabs_pos_eq; try fourier; auto.
- split; try fourier.
+ rewrite xy; unfold Boule; rewrite Rabs_pos_eq; try lra; auto.
+ split; try lra.
apply Rplus_le_compat_l, Rmult_le_compat_r;[ | apply Rmin_r].
now apply Rlt_le, Rinv_0_lt_compat, Rlt_0_2.
- apply Rminus_not_eq_right; rewrite xy; apply Rgt_not_eq; fourier.
unfold rho_.
destruct (Req_EM_T (y + Rmin (Rmin d' d2) delta/2) x) as [ymx | ymnx].
- case (RIneq.Rle_not_lt _ _ (Req_le _ _ ymx)); fourier.
+ case (RIneq.Rle_not_lt _ _ (Req_le _ _ ymx)); lra.
reflexivity.
unfold rho_.
destruct (Req_EM_T (y + Rmin (Rmin d' d2) delta / 2) x) as [ymx | ymnx].
- case (RIneq.Rle_not_lt _ _ (Req_le _ _ ymx)); fourier.
+ case (RIneq.Rle_not_lt _ _ (Req_le _ _ ymx)); lra.
reflexivity.
- apply Rlt_le, Pd2; split;[split;[exact I | apply Rlt_not_eq; fourier] | ].
+ apply Rlt_le, Pd2; split;[split;[exact I | apply Rlt_not_eq; lra] | ].
simpl; unfold R_dist.
unfold Rminus; rewrite (Rplus_comm y), Rplus_assoc, Rplus_opp_r, Rplus_0_r.
- rewrite Rabs_pos_eq;[ | fourier].
- apply Rlt_le_trans with (Rmin (Rmin d' d2) delta); [fourier |].
+ rewrite Rabs_pos_eq;[ | lra].
+ apply Rlt_le_trans with (Rmin (Rmin d' d2) delta); [lra |].
apply Rle_trans with (Rmin d' d2).
solve[apply Rmin_l].
solve[apply Rmin_r].
- apply Rlt_le, Rlt_le_trans with (eps/4);[ | fourier].
+ apply Rlt_le, Rlt_le_trans with (eps/4);[ | lra].
unfold rho_; destruct (Req_EM_T y x); solve[auto].
assert (unif_ac' : forall p, (N <= p)%nat ->
forall y, Boule c d y -> Rabs (rho y - rho_ p y) < eps).
@@ -589,7 +588,7 @@ assert (CVU rho_ rho c d ).
intros eps' ep'; simpl; exists 0%nat; intros; rewrite R_dist_eq; assumption.
intros p pN y b_y.
replace eps with (eps/2 + eps/2) by field.
- assert (ep2 : 0 < eps/2) by fourier.
+ assert (ep2 : 0 < eps/2) by lra.
destruct (cvrho y b_y _ ep2) as [N2 Pn2].
apply Rle_lt_trans with (1 := R_dist_tri _ _ (rho_ (max N N2) y)).
apply Rplus_lt_le_compat.
diff --git a/theories/Reals/R_sqrt.v b/theories/Reals/R_sqrt.v
index d4035fad62..6991923b13 100644
--- a/theories/Reals/R_sqrt.v
+++ b/theories/Reals/R_sqrt.v
@@ -155,6 +155,22 @@ Proof.
| apply (sqrt_positivity x (Rlt_le 0 x H1)) ].
Qed.
+Lemma Rlt_mult_inv_pos : forall x y:R, 0 < x -> 0 < y -> 0 < x * / y.
+intros x y H H0; try assumption.
+replace 0 with (x * 0).
+apply Rmult_lt_compat_l; auto with real.
+ring.
+Qed.
+
+Lemma Rle_mult_inv_pos : forall x y:R, 0 <= x -> 0 < y -> 0 <= x * / y.
+intros x y H H0; try assumption.
+case H; intros.
+red; left.
+apply Rlt_mult_inv_pos; auto with real.
+rewrite <- H1.
+red; right; ring.
+Qed.
+
Lemma sqrt_div_alt :
forall x y : R, 0 < y -> sqrt (x / y) = sqrt x / sqrt y.
Proof.
@@ -176,14 +192,14 @@ Proof.
clearbody Hx'. clear Hx.
apply Rsqr_inj.
apply sqrt_pos.
- apply Fourier_util.Rle_mult_inv_pos.
+ apply Rle_mult_inv_pos.
apply Rsqrt_positivity.
now apply sqrt_lt_R0.
rewrite Rsqr_div, 2!Rsqr_sqrt.
unfold Rsqr.
now rewrite Rsqrt_Rsqrt.
now apply Rlt_le.
- now apply Fourier_util.Rle_mult_inv_pos.
+ now apply Rle_mult_inv_pos.
apply Rgt_not_eq.
now apply sqrt_lt_R0.
Qed.
diff --git a/theories/Reals/Ranalysis5.v b/theories/Reals/Ranalysis5.v
index afb78e1c8e..e66130b347 100644
--- a/theories/Reals/Ranalysis5.v
+++ b/theories/Reals/Ranalysis5.v
@@ -12,7 +12,7 @@ Require Import Rbase.
Require Import Ranalysis_reg.
Require Import Rfunctions.
Require Import Rseries.
-Require Import Fourier.
+Require Import Lra.
Require Import RiemannInt.
Require Import SeqProp.
Require Import Max.
@@ -56,7 +56,7 @@ Proof.
}
rewrite f_eq_g in Htemp by easy.
unfold id in Htemp.
- fourier.
+ lra.
Qed.
Lemma derivable_pt_id_interv : forall (lb ub x:R),
@@ -99,7 +99,7 @@ assert (forall x l, lb < x < ub -> (derivable_pt_abs f x l <-> derivable_pt_abs
apply Req_le ; apply Rabs_right ; apply Rgt_ge ; assumption.
split.
assert (Sublemma : forall x y z, -z < y - x -> x < y + z).
- intros ; fourier.
+ intros ; lra.
apply Sublemma.
apply Sublemma2. rewrite Rabs_Ropp.
apply Rlt_le_trans with (r2:=a-lb) ; [| apply RRle_abs] ;
@@ -108,7 +108,7 @@ assert (forall x l, lb < x < ub -> (derivable_pt_abs f x l <-> derivable_pt_abs
apply Rlt_le_trans with (r2:=Rmin (ub - a) (a - lb)) ; [| apply Rmin_r] ;
apply Rlt_le_trans with (r2:=Rmin delta (Rmin (ub - a) (a - lb))) ; [| apply Rmin_r] ; assumption.
assert (Sublemma : forall x y z, y < z - x -> x + y < z).
- intros ; fourier.
+ intros ; lra.
apply Sublemma.
apply Sublemma2.
apply Rlt_le_trans with (r2:=ub-a) ; [| apply RRle_abs] ;
@@ -137,7 +137,7 @@ assert (forall x l, lb < x < ub -> (derivable_pt_abs f x l <-> derivable_pt_abs
apply Req_le ; apply Rabs_right ; apply Rgt_ge ; assumption.
split.
assert (Sublemma : forall x y z, -z < y - x -> x < y + z).
- intros ; fourier.
+ intros ; lra.
apply Sublemma.
apply Sublemma2. rewrite Rabs_Ropp.
apply Rlt_le_trans with (r2:=a-lb) ; [| apply RRle_abs] ;
@@ -146,7 +146,7 @@ assert (forall x l, lb < x < ub -> (derivable_pt_abs f x l <-> derivable_pt_abs
apply Rlt_le_trans with (r2:=Rmin (ub - a) (a - lb)) ; [| apply Rmin_r] ;
apply Rlt_le_trans with (r2:=Rmin delta (Rmin (ub - a) (a - lb))) ; [| apply Rmin_r] ; assumption.
assert (Sublemma : forall x y z, y < z - x -> x + y < z).
- intros ; fourier.
+ intros ; lra.
apply Sublemma.
apply Sublemma2.
apply Rlt_le_trans with (r2:=ub-a) ; [| apply RRle_abs] ;
@@ -415,7 +415,7 @@ Ltac case_le H :=
let h' := fresh in
match t with ?x <= ?y => case (total_order_T x y);
[intros h'; case h'; clear h' |
- intros h'; clear -H h'; elimtype False; fourier ] end.
+ intros h'; clear -H h'; elimtype False; lra ] end.
(* end hide *)
@@ -539,37 +539,37 @@ intros f g lb ub lb_lt_ub f_incr_interv f_eq_g f_cont_interv b b_encad.
assert (x1_encad : lb <= x1 <= ub).
split. apply RmaxLess2.
apply Rlt_le. rewrite Hx1. rewrite Sublemma.
- split. apply Rlt_trans with (r2:=x) ; fourier.
+ split. apply Rlt_trans with (r2:=x) ; lra.
assumption.
assert (x2_encad : lb <= x2 <= ub).
split. apply Rlt_le ; rewrite Hx2 ; apply Rgt_lt ; rewrite Sublemma2.
- split. apply Rgt_trans with (r2:=x) ; fourier.
+ split. apply Rgt_trans with (r2:=x) ; lra.
assumption.
apply Rmin_r.
assert (x_lt_x2 : x < x2).
rewrite Hx2.
apply Rgt_lt. rewrite Sublemma2.
- split ; fourier.
+ split ; lra.
assert (x1_lt_x : x1 < x).
rewrite Hx1.
rewrite Sublemma.
- split ; fourier.
+ split ; lra.
exists (Rmin (f x - f x1) (f x2 - f x)).
- split. apply Rmin_pos ; apply Rgt_minus. apply f_incr_interv ; [apply RmaxLess2 | | ] ; fourier.
+ split. apply Rmin_pos ; apply Rgt_minus. apply f_incr_interv ; [apply RmaxLess2 | | ] ; lra.
apply f_incr_interv ; intuition.
intros y Temp.
destruct Temp as (_,y_cond).
rewrite <- f_x_b in y_cond.
assert (Temp : forall x y d1 d2, d1 > 0 -> d2 > 0 -> Rabs (y - x) < Rmin d1 d2 -> x - d1 <= y <= x + d2).
intros.
- split. assert (H10 : forall x y z, x - y <= z -> x - z <= y). intuition. fourier.
+ split. assert (H10 : forall x y z, x - y <= z -> x - z <= y). intuition. lra.
apply H10. apply Rle_trans with (r2:=Rabs (y0 - x0)).
replace (Rabs (y0 - x0)) with (Rabs (x0 - y0)). apply RRle_abs.
rewrite <- Rabs_Ropp. unfold Rminus ; rewrite Ropp_plus_distr. rewrite Ropp_involutive.
intuition.
apply Rle_trans with (r2:= Rmin d1 d2). apply Rlt_le ; assumption.
apply Rmin_l.
- assert (H10 : forall x y z, x - y <= z -> x <= y + z). intuition. fourier.
+ assert (H10 : forall x y z, x - y <= z -> x <= y + z). intuition. lra.
apply H10. apply Rle_trans with (r2:=Rabs (y0 - x0)). apply RRle_abs.
apply Rle_trans with (r2:= Rmin d1 d2). apply Rlt_le ; assumption.
apply Rmin_r.
@@ -602,12 +602,12 @@ intros f g lb ub lb_lt_ub f_incr_interv f_eq_g f_cont_interv b b_encad.
assert (x1_neq_x' : x1 <> x').
intro Hfalse. rewrite Hfalse, f_x'_y in y_cond.
assert (Hf : Rabs (y - f x) < f x - y).
- apply Rlt_le_trans with (r2:=Rmin (f x - y) (f x2 - f x)). fourier.
+ apply Rlt_le_trans with (r2:=Rmin (f x - y) (f x2 - f x)). lra.
apply Rmin_l.
assert(Hfin : f x - y < f x - y).
apply Rle_lt_trans with (r2:=Rabs (y - f x)).
replace (Rabs (y - f x)) with (Rabs (f x - y)). apply RRle_abs.
- rewrite <- Rabs_Ropp. replace (- (f x - y)) with (y - f x) by field ; reflexivity. fourier.
+ rewrite <- Rabs_Ropp. replace (- (f x - y)) with (y - f x) by field ; reflexivity. lra.
apply (Rlt_irrefl (f x - y)) ; assumption.
split ; intuition.
assert (x'_lb : x - eps < x').
@@ -619,17 +619,17 @@ intros f g lb ub lb_lt_ub f_incr_interv f_eq_g f_cont_interv b b_encad.
assert (x1_neq_x' : x' <> x2).
intro Hfalse. rewrite <- Hfalse, f_x'_y in y_cond.
assert (Hf : Rabs (y - f x) < y - f x).
- apply Rlt_le_trans with (r2:=Rmin (f x - f x1) (y - f x)). fourier.
+ apply Rlt_le_trans with (r2:=Rmin (f x - f x1) (y - f x)). lra.
apply Rmin_r.
assert(Hfin : y - f x < y - f x).
- apply Rle_lt_trans with (r2:=Rabs (y - f x)). apply RRle_abs. fourier.
+ apply Rle_lt_trans with (r2:=Rabs (y - f x)). apply RRle_abs. lra.
apply (Rlt_irrefl (y - f x)) ; assumption.
split ; intuition.
assert (x'_ub : x' < x + eps).
apply Sublemma3.
split. intuition. apply Rlt_not_eq.
apply Rlt_le_trans with (r2:=x2) ; [ |rewrite Hx2 ; apply Rmin_l] ; intuition.
- apply Rabs_def1 ; fourier.
+ apply Rabs_def1 ; lra.
assumption.
split. apply Rle_trans with (r2:=x1) ; intuition.
apply Rle_trans with (r2:=x2) ; intuition.
@@ -742,7 +742,7 @@ intros f g lb ub x Prf g_cont_pur lb_lt_ub x_encad Prg_incr f_eq_g df_neq.
assert (lb <= x + h <= ub).
split.
assert (Sublemma : forall x y z, -z <= y - x -> x <= y + z).
- intros ; fourier.
+ intros ; lra.
apply Sublemma.
apply Rlt_le ; apply Sublemma2. rewrite Rabs_Ropp.
apply Rlt_le_trans with (r2:=x-lb) ; [| apply RRle_abs] ;
@@ -751,7 +751,7 @@ intros f g lb ub x Prf g_cont_pur lb_lt_ub x_encad Prg_incr f_eq_g df_neq.
apply Rlt_le_trans with (r2:=delta''). assumption. intuition. apply Rmin_r.
apply Rgt_minus. intuition.
assert (Sublemma : forall x y z, y <= z - x -> x + y <= z).
- intros ; fourier.
+ intros ; lra.
apply Sublemma.
apply Rlt_le ; apply Sublemma2.
apply Rlt_le_trans with (r2:=ub-x) ; [| apply RRle_abs] ;
@@ -767,7 +767,7 @@ intros f g lb ub x Prf g_cont_pur lb_lt_ub x_encad Prg_incr f_eq_g df_neq.
assumption.
split ; [|intuition].
assert (Sublemma : forall x y z, - z <= y - x -> x <= y + z).
- intros ; fourier.
+ intros ; lra.
apply Sublemma ; apply Rlt_le ; apply Sublemma2. rewrite Rabs_Ropp.
apply Rlt_le_trans with (r2:=x-lb) ; [| apply RRle_abs] ;
apply Rlt_le_trans with (r2:=Rmin (x - lb) (ub - x)) ; [| apply Rmin_l] ;
@@ -1031,7 +1031,7 @@ Lemma derivable_pt_lim_CVU : forall (fn fn':nat -> R -> R) (f g:R->R)
derivable_pt_lim f x (g x).
Proof.
intros fn fn' f g x c' r xinb Dfn_eq_fn' fn_CV_f fn'_CVU_g g_cont eps eps_pos.
-assert (eps_8_pos : 0 < eps / 8) by fourier.
+assert (eps_8_pos : 0 < eps / 8) by lra.
elim (g_cont x xinb _ eps_8_pos) ; clear g_cont ;
intros delta1 (delta1_pos, g_cont).
destruct (Ball_in_inter _ _ _ _ _ xinb
@@ -1041,11 +1041,11 @@ exists delta; intros h hpos hinbdelta.
assert (eps'_pos : 0 < (Rabs h) * eps / 4).
unfold Rdiv ; rewrite Rmult_assoc ; apply Rmult_lt_0_compat.
apply Rabs_pos_lt ; assumption.
-fourier.
+lra.
destruct (fn_CV_f x xinb ((Rabs h) * eps / 4) eps'_pos) as [N2 fnx_CV_fx].
assert (xhinbxdelta : Boule x delta (x + h)).
clear -hinbdelta; apply Rabs_def2 in hinbdelta; unfold Boule; simpl.
- destruct hinbdelta; apply Rabs_def1; fourier.
+ destruct hinbdelta; apply Rabs_def1; lra.
assert (t : Boule c' r (x + h)).
apply Pdelta in xhinbxdelta; tauto.
destruct (fn_CV_f (x+h) t ((Rabs h) * eps / 4) eps'_pos) as [N1 fnxh_CV_fxh].
@@ -1064,17 +1064,17 @@ assert (Main : Rabs ((f (x+h) - fn N (x+h)) - (f x - fn N x) + (fn N (x+h) - fn
exists (fn' N c) ; apply Dfn_eq_fn'.
assert (t : Boule x delta c).
apply Rabs_def2 in xhinbxdelta; destruct xhinbxdelta; destruct c_encad.
- apply Rabs_def2 in xinb; apply Rabs_def1; fourier.
+ apply Rabs_def2 in xinb; apply Rabs_def1; lra.
apply Pdelta in t; tauto.
assert (pr2 : forall c : R, x + h < c < x -> derivable_pt id c).
solve[intros; apply derivable_id].
- assert (xh_x : x+h < x) by fourier.
+ assert (xh_x : x+h < x) by lra.
assert (pr3 : forall c : R, x + h <= c <= x -> continuity_pt (fn N) c).
intros c c_encad ; apply derivable_continuous_pt.
exists (fn' N c) ; apply Dfn_eq_fn' ; intuition.
assert (t : Boule x delta c).
apply Rabs_def2 in xhinbxdelta; destruct xhinbxdelta.
- apply Rabs_def2 in xinb; apply Rabs_def1; fourier.
+ apply Rabs_def2 in xinb; apply Rabs_def1; lra.
apply Pdelta in t; tauto.
assert (pr4 : forall c : R, x + h <= c <= x -> continuity_pt id c).
solve[intros; apply derivable_continuous ; apply derivable_id].
@@ -1117,7 +1117,7 @@ assert (Main : Rabs ((f (x+h) - fn N (x+h)) - (f x - fn N x) + (fn N (x+h) - fn
assert (t : Boule x delta c).
destruct P.
apply Rabs_def2 in xhinbxdelta; destruct xhinbxdelta.
- apply Rabs_def2 in xinb; apply Rabs_def1; fourier.
+ apply Rabs_def2 in xinb; apply Rabs_def1; lra.
apply Pdelta in t; tauto.
apply Rlt_trans with (Rabs h * eps / 4 + Rabs h * eps / 4 + Rabs h * (eps / 8) +
Rabs h * (eps / 8)).
@@ -1131,27 +1131,27 @@ assert (Main : Rabs ((f (x+h) - fn N (x+h)) - (f x - fn N x) + (fn N (x+h) - fn
apply Rlt_trans with (Rabs h).
apply Rabs_def1.
apply Rlt_trans with 0.
- destruct P; fourier.
+ destruct P; lra.
apply Rabs_pos_lt ; assumption.
- rewrite <- Rabs_Ropp, Rabs_pos_eq, Ropp_involutive;[ | fourier].
- destruct P; fourier.
+ rewrite <- Rabs_Ropp, Rabs_pos_eq, Ropp_involutive;[ | lra].
+ destruct P; lra.
clear -Pdelta xhinbxdelta.
apply Pdelta in xhinbxdelta; destruct xhinbxdelta as [_ P'].
apply Rabs_def2 in P'; simpl in P'; destruct P';
- apply Rabs_def1; fourier.
+ apply Rabs_def1; lra.
rewrite Rplus_assoc ; rewrite Rplus_assoc ; rewrite <- Rmult_plus_distr_l.
replace (Rabs h * eps / 4 + (Rabs h * eps / 4 + Rabs h * (eps / 8 + eps / 8))) with
(Rabs h * (eps / 4 + eps / 4 + eps / 8 + eps / 8)) by field.
apply Rmult_lt_compat_l.
apply Rabs_pos_lt ; assumption.
- fourier.
+ lra.
assert (H := pr1 c P) ; elim H ; clear H ; intros l Hl.
assert (Temp : l = fn' N c).
assert (bc'rc : Boule c' r c).
assert (t : Boule x delta c).
clear - xhinbxdelta P.
destruct P; apply Rabs_def2 in xhinbxdelta; destruct xhinbxdelta.
- apply Rabs_def1; fourier.
+ apply Rabs_def1; lra.
apply Pdelta in t; tauto.
assert (Hl' := Dfn_eq_fn' c N bc'rc).
unfold derivable_pt_abs in Hl; clear -Hl Hl'.
@@ -1175,17 +1175,17 @@ assert (Main : Rabs ((f (x+h) - fn N (x+h)) - (f x - fn N x) + (fn N (x+h) - fn
exists (fn' N c) ; apply Dfn_eq_fn'.
assert (t : Boule x delta c).
apply Rabs_def2 in xhinbxdelta; destruct xhinbxdelta; destruct c_encad.
- apply Rabs_def2 in xinb; apply Rabs_def1; fourier.
+ apply Rabs_def2 in xinb; apply Rabs_def1; lra.
apply Pdelta in t; tauto.
assert (pr2 : forall c : R, x < c < x + h -> derivable_pt id c).
solve[intros; apply derivable_id].
- assert (xh_x : x < x + h) by fourier.
+ assert (xh_x : x < x + h) by lra.
assert (pr3 : forall c : R, x <= c <= x + h -> continuity_pt (fn N) c).
intros c c_encad ; apply derivable_continuous_pt.
exists (fn' N c) ; apply Dfn_eq_fn' ; intuition.
assert (t : Boule x delta c).
apply Rabs_def2 in xhinbxdelta; destruct xhinbxdelta.
- apply Rabs_def2 in xinb; apply Rabs_def1; fourier.
+ apply Rabs_def2 in xinb; apply Rabs_def1; lra.
apply Pdelta in t; tauto.
assert (pr4 : forall c : R, x <= c <= x + h -> continuity_pt id c).
solve[intros; apply derivable_continuous ; apply derivable_id].
@@ -1223,7 +1223,7 @@ assert (Main : Rabs ((f (x+h) - fn N (x+h)) - (f x - fn N x) + (fn N (x+h) - fn
assert (t : Boule x delta c).
destruct P.
apply Rabs_def2 in xhinbxdelta; destruct xhinbxdelta.
- apply Rabs_def2 in xinb; apply Rabs_def1; fourier.
+ apply Rabs_def2 in xinb; apply Rabs_def1; lra.
apply Pdelta in t; tauto.
apply Rlt_trans with (Rabs h * eps / 4 + Rabs h * eps / 4 + Rabs h * (eps / 8) +
Rabs h * (eps / 8)).
@@ -1236,27 +1236,27 @@ assert (Main : Rabs ((f (x+h) - fn N (x+h)) - (f x - fn N x) + (fn N (x+h) - fn
apply Rlt_not_eq ; exact (proj1 P).
apply Rlt_trans with (Rabs h).
apply Rabs_def1.
- destruct P; rewrite Rabs_pos_eq;fourier.
+ destruct P; rewrite Rabs_pos_eq;lra.
apply Rle_lt_trans with 0.
- assert (t := Rabs_pos h); clear -t; fourier.
- clear -P; destruct P; fourier.
+ assert (t := Rabs_pos h); clear -t; lra.
+ clear -P; destruct P; lra.
clear -Pdelta xhinbxdelta.
apply Pdelta in xhinbxdelta; destruct xhinbxdelta as [_ P'].
apply Rabs_def2 in P'; simpl in P'; destruct P';
- apply Rabs_def1; fourier.
+ apply Rabs_def1; lra.
rewrite Rplus_assoc ; rewrite Rplus_assoc ; rewrite <- Rmult_plus_distr_l.
replace (Rabs h * eps / 4 + (Rabs h * eps / 4 + Rabs h * (eps / 8 + eps / 8))) with
(Rabs h * (eps / 4 + eps / 4 + eps / 8 + eps / 8)) by field.
apply Rmult_lt_compat_l.
apply Rabs_pos_lt ; assumption.
- fourier.
+ lra.
assert (H := pr1 c P) ; elim H ; clear H ; intros l Hl.
assert (Temp : l = fn' N c).
assert (bc'rc : Boule c' r c).
assert (t : Boule x delta c).
clear - xhinbxdelta P.
destruct P; apply Rabs_def2 in xhinbxdelta; destruct xhinbxdelta.
- apply Rabs_def1; fourier.
+ apply Rabs_def1; lra.
apply Pdelta in t; tauto.
assert (Hl' := Dfn_eq_fn' c N bc'rc).
unfold derivable_pt_abs in Hl; clear -Hl Hl'.
diff --git a/theories/Reals/Ratan.v b/theories/Reals/Ratan.v
index ce39d5ffe4..03e6ff61ab 100644
--- a/theories/Reals/Ratan.v
+++ b/theories/Reals/Ratan.v
@@ -8,7 +8,7 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
-Require Import Fourier.
+Require Import Lra.
Require Import Rbase.
Require Import PSeries_reg.
Require Import Rtrigo1.
@@ -32,7 +32,7 @@ intros x y; unfold Rdiv; rewrite <-Ropp_mult_distr_l_reverse; reflexivity.
Qed.
Definition pos_half_prf : 0 < /2.
-Proof. fourier. Qed.
+Proof. lra. Qed.
Definition pos_half := mkposreal (/2) pos_half_prf.
@@ -40,15 +40,15 @@ Lemma Boule_half_to_interval :
forall x , Boule (/2) pos_half x -> 0 <= x <= 1.
Proof.
unfold Boule, pos_half; simpl.
-intros x b; apply Rabs_def2 in b; destruct b; split; fourier.
+intros x b; apply Rabs_def2 in b; destruct b; split; lra.
Qed.
Lemma Boule_lt : forall c r x, Boule c r x -> Rabs x < Rabs c + r.
Proof.
unfold Boule; intros c r x h.
apply Rabs_def2 in h; destruct h; apply Rabs_def1;
- (destruct (Rle_lt_dec 0 c);[rewrite Rabs_pos_eq; fourier |
- rewrite <- Rabs_Ropp, Rabs_pos_eq; fourier]).
+ (destruct (Rle_lt_dec 0 c);[rewrite Rabs_pos_eq; lra |
+ rewrite <- Rabs_Ropp, Rabs_pos_eq; lra]).
Qed.
(* The following lemma does not belong here. *)
@@ -117,53 +117,53 @@ intros [ | N] Npos n decr to0 cv nN.
case (even_odd_cor n) as [p' [neven | nodd]].
rewrite neven.
destruct (alternated_series_ineq _ _ p' decr to0 cv) as [D E].
- unfold R_dist; rewrite Rabs_pos_eq;[ | fourier].
+ unfold R_dist; rewrite Rabs_pos_eq;[ | lra].
assert (dist : (p <= p')%nat) by omega.
assert (t := decreasing_prop _ _ _ (CV_ALT_step1 f decr) dist).
apply Rle_trans with (sum_f_R0 (tg_alt f) (2 * p) - l).
unfold Rminus; apply Rplus_le_compat_r; exact t.
match goal with _ : ?a <= l, _ : l <= ?b |- _ =>
replace (f (S (2 * p))) with (b - a) by
- (rewrite tech5; unfold tg_alt; rewrite pow_1_odd; ring); fourier
+ (rewrite tech5; unfold tg_alt; rewrite pow_1_odd; ring); lra
end.
rewrite nodd; destruct (alternated_series_ineq _ _ p' decr to0 cv) as [D E].
unfold R_dist; rewrite <- Rabs_Ropp, Rabs_pos_eq, Ropp_minus_distr;
- [ | fourier].
+ [ | lra].
assert (dist : (p <= p')%nat) by omega.
apply Rle_trans with (l - sum_f_R0 (tg_alt f) (S (2 * p))).
unfold Rminus; apply Rplus_le_compat_l, Ropp_le_contravar.
solve[apply Rge_le, (growing_prop _ _ _ (CV_ALT_step0 f decr) dist)].
unfold Rminus; rewrite tech5, Ropp_plus_distr, <- Rplus_assoc.
- unfold tg_alt at 2; rewrite pow_1_odd; fourier.
+ unfold tg_alt at 2; rewrite pow_1_odd; lra.
rewrite Nodd; destruct (alternated_series_ineq _ _ p decr to0 cv) as [B _].
destruct (alternated_series_ineq _ _ (S p) decr to0 cv) as [_ C].
assert (keep : (2 * S p = S (S ( 2 * p)))%nat) by ring.
case (even_odd_cor n) as [p' [neven | nodd]].
rewrite neven;
destruct (alternated_series_ineq _ _ p' decr to0 cv) as [D E].
- unfold R_dist; rewrite Rabs_pos_eq;[ | fourier].
+ unfold R_dist; rewrite Rabs_pos_eq;[ | lra].
assert (dist : (S p < S p')%nat) by omega.
apply Rle_trans with (sum_f_R0 (tg_alt f) (2 * S p) - l).
unfold Rminus; apply Rplus_le_compat_r,
(decreasing_prop _ _ _ (CV_ALT_step1 f decr)).
omega.
rewrite keep, tech5; unfold tg_alt at 2; rewrite <- keep, pow_1_even.
- fourier.
+ lra.
rewrite nodd; destruct (alternated_series_ineq _ _ p' decr to0 cv) as [D E].
- unfold R_dist; rewrite <- Rabs_Ropp, Rabs_pos_eq;[ | fourier].
+ unfold R_dist; rewrite <- Rabs_Ropp, Rabs_pos_eq;[ | lra].
rewrite Ropp_minus_distr.
apply Rle_trans with (l - sum_f_R0 (tg_alt f) (S (2 * p))).
unfold Rminus; apply Rplus_le_compat_l, Ropp_le_contravar, Rge_le,
(growing_prop _ _ _ (CV_ALT_step0 f decr)); omega.
generalize C; rewrite keep, tech5; unfold tg_alt.
rewrite <- keep, pow_1_even.
- assert (t : forall a b c, a <= b + 1 * c -> a - b <= c) by (intros; fourier).
+ assert (t : forall a b c, a <= b + 1 * c -> a - b <= c) by (intros; lra).
solve[apply t].
clear WLOG; intros Hyp [ | n] decr to0 cv _.
generalize (alternated_series_ineq f l 0 decr to0 cv).
unfold R_dist, tg_alt; simpl; rewrite !Rmult_1_l, !Rmult_1_r.
assert (f 1%nat <= f 0%nat) by apply decr.
- intros [A B]; rewrite Rabs_pos_eq; fourier.
+ intros [A B]; rewrite Rabs_pos_eq; lra.
apply Rle_trans with (f 1%nat).
apply (Hyp 1%nat (le_n 1) (S n) decr to0 cv).
omega.
@@ -180,7 +180,7 @@ Lemma Alt_CVU : forall (f : nat -> R -> R) g h c r,
CVU (fun N x => sum_f_R0 (tg_alt (fun i => f i x)) N) g c r.
Proof.
intros f g h c r decr to0 to_g bound bound0 eps ep.
-assert (ep' : 0 <eps/2) by fourier.
+assert (ep' : 0 <eps/2) by lra.
destruct (bound0 _ ep) as [N Pn]; exists N.
intros n y nN dy.
rewrite <- Rabs_Ropp, Ropp_minus_distr; apply Rle_lt_trans with (f n y).
@@ -201,14 +201,14 @@ intros x; destruct (Rle_lt_dec 0 x).
replace (x ^ 2) with (x * x) by field.
apply Rmult_le_pos; assumption.
replace (x ^ 2) with ((-x) * (-x)) by field.
-apply Rmult_le_pos; fourier.
+apply Rmult_le_pos; lra.
Qed.
Lemma pow2_abs : forall x, Rabs x ^ 2 = x ^ 2.
Proof.
intros x; destruct (Rle_lt_dec 0 x).
rewrite Rabs_pos_eq;[field | assumption].
-rewrite <- Rabs_Ropp, Rabs_pos_eq;[field | fourier].
+rewrite <- Rabs_Ropp, Rabs_pos_eq;[field | lra].
Qed.
(** * Properties of tangent *)
@@ -307,18 +307,18 @@ destruct (MVT_cor1 cos (PI/2) x derivable_cos xgtpi2) as
[c [Pc [cint1 cint2]]].
revert Pc; rewrite cos_PI2, Rminus_0_r.
rewrite <- (pr_nu cos c (derivable_pt_cos c)), derive_pt_cos.
-assert (0 < c < 2) by (split; assert (t := PI2_RGT_0); fourier).
+assert (0 < c < 2) by (split; assert (t := PI2_RGT_0); lra).
assert (0 < sin c) by now apply sin_pos_tech.
intros Pc.
case (Rlt_not_le _ _ cx).
rewrite <- (Rplus_0_l (cos x)), Pc, Ropp_mult_distr_l_reverse.
-apply Rle_minus, Rmult_le_pos;[apply Rlt_le; assumption | fourier ].
+apply Rle_minus, Rmult_le_pos;[apply Rlt_le; assumption | lra ].
Qed.
Lemma PI2_3_2 : 3/2 < PI/2.
Proof.
-apply PI2_lower_bound;[split; fourier | ].
-destruct (pre_cos_bound (3/2) 1) as [t _]; [fourier | fourier | ].
+apply PI2_lower_bound;[split; lra | ].
+destruct (pre_cos_bound (3/2) 1) as [t _]; [lra | lra | ].
apply Rlt_le_trans with (2 := t); clear t.
unfold cos_approx; simpl; unfold cos_term.
rewrite !INR_IZR_INZ.
@@ -330,7 +330,7 @@ apply Rdiv_lt_0_compat ; now apply IZR_lt.
Qed.
Lemma PI2_1 : 1 < PI/2.
-Proof. assert (t := PI2_3_2); fourier. Qed.
+Proof. assert (t := PI2_3_2); lra. Qed.
Lemma tan_increasing :
forall x y:R,
@@ -347,7 +347,7 @@ intros x y Z_le_x x_lt_y y_le_1.
derivable_pt tan x).
intros ; apply derivable_pt_tan ; intuition.
apply derive_increasing_interv with (a:=-PI/2) (b:=PI/2) (pr:=local_derivable_pt_tan) ; intuition.
- fourier.
+ lra.
assert (Temp := pr_nu tan t (derivable_pt_tan t t_encad) (local_derivable_pt_tan t t_encad)) ;
rewrite <- Temp ; clear Temp.
assert (Temp := derive_pt_tan t t_encad) ; rewrite Temp ; clear Temp.
@@ -414,49 +414,49 @@ Qed.
(** * Definition of arctangent as the reciprocal function of tangent and proof of this status *)
Lemma tan_1_gt_1 : tan 1 > 1.
Proof.
-assert (0 < cos 1) by (apply cos_gt_0; assert (t:=PI2_1); fourier).
+assert (0 < cos 1) by (apply cos_gt_0; assert (t:=PI2_1); lra).
assert (t1 : cos 1 <= 1 - 1/2 + 1/24).
- destruct (pre_cos_bound 1 0) as [_ t]; try fourier; revert t.
+ destruct (pre_cos_bound 1 0) as [_ t]; try lra; revert t.
unfold cos_approx, cos_term; simpl; intros t; apply Rle_trans with (1:=t).
clear t; apply Req_le; field.
assert (t2 : 1 - 1/6 <= sin 1).
- destruct (pre_sin_bound 1 0) as [t _]; try fourier; revert t.
+ destruct (pre_sin_bound 1 0) as [t _]; try lra; revert t.
unfold sin_approx, sin_term; simpl; intros t; apply Rle_trans with (2:=t).
clear t; apply Req_le; field.
pattern 1 at 2; replace 1 with
- (cos 1 / cos 1) by (field; apply Rgt_not_eq; fourier).
+ (cos 1 / cos 1) by (field; apply Rgt_not_eq; lra).
apply Rlt_gt; apply (Rmult_lt_compat_r (/ cos 1) (cos 1) (sin 1)).
apply Rinv_0_lt_compat; assumption.
apply Rle_lt_trans with (1 := t1); apply Rlt_le_trans with (2 := t2).
-fourier.
+lra.
Qed.
Definition frame_tan y : {x | 0 < x < PI/2 /\ Rabs y < tan x}.
Proof.
destruct (total_order_T (Rabs y) 1) as [Hs|Hgt].
- assert (yle1 : Rabs y <= 1) by (destruct Hs; fourier).
+ assert (yle1 : Rabs y <= 1) by (destruct Hs; lra).
clear Hs; exists 1; split;[split; [exact Rlt_0_1 | exact PI2_1] | ].
apply Rle_lt_trans with (1 := yle1); exact tan_1_gt_1.
assert (0 < / (Rabs y + 1)).
- apply Rinv_0_lt_compat; fourier.
+ apply Rinv_0_lt_compat; lra.
set (u := /2 * / (Rabs y + 1)).
assert (0 < u).
- apply Rmult_lt_0_compat; [fourier | assumption].
+ apply Rmult_lt_0_compat; [lra | assumption].
assert (vlt1 : / (Rabs y + 1) < 1).
apply Rmult_lt_reg_r with (Rabs y + 1).
- assert (t := Rabs_pos y); fourier.
- rewrite Rinv_l; [rewrite Rmult_1_l | apply Rgt_not_eq]; fourier.
+ assert (t := Rabs_pos y); lra.
+ rewrite Rinv_l; [rewrite Rmult_1_l | apply Rgt_not_eq]; lra.
assert (vlt2 : u < 1).
apply Rlt_trans with (/ (Rabs y + 1)).
rewrite double_var.
- assert (t : forall x, 0 < x -> x < x + x) by (clear; intros; fourier).
+ assert (t : forall x, 0 < x -> x < x + x) by (clear; intros; lra).
unfold u; rewrite Rmult_comm; apply t.
unfold Rdiv; rewrite Rmult_comm; assumption.
assumption.
assert(int : 0 < PI / 2 - u < PI / 2).
split.
assert (t := PI2_1); apply Rlt_Rminus, Rlt_trans with (2 := t); assumption.
- assert (dumb : forall x y, 0 < y -> x - y < x) by (clear; intros; fourier).
+ assert (dumb : forall x y, 0 < y -> x - y < x) by (clear; intros; lra).
apply dumb; clear dumb; assumption.
exists (PI/2 - u).
assert (tmp : forall x y, 0 < x -> y < 1 -> x * y < x).
@@ -473,7 +473,7 @@ split.
assert (sin u < u).
assert (t1 : 0 <= u) by (apply Rlt_le; assumption).
assert (t2 : u <= 4) by
- (apply Rle_trans with 1;[apply Rlt_le | fourier]; assumption).
+ (apply Rle_trans with 1;[apply Rlt_le | lra]; assumption).
destruct (pre_sin_bound u 0 t1 t2) as [_ t].
apply Rle_lt_trans with (1 := t); clear t1 t2 t.
unfold sin_approx; simpl; unfold sin_term; simpl ((-1) ^ 0);
@@ -503,17 +503,17 @@ split.
solve[apply Rinv_0_lt_compat, INR_fact_lt_0].
apply Rlt_trans with (2 := vlt2).
simpl; unfold u; apply tmp; auto; rewrite Rmult_1_r; assumption.
- apply Rlt_trans with (Rabs y + 1);[fourier | ].
+ apply Rlt_trans with (Rabs y + 1);[lra | ].
pattern (Rabs y + 1) at 1; rewrite <- (Rinv_involutive (Rabs y + 1));
- [ | apply Rgt_not_eq; fourier].
+ [ | apply Rgt_not_eq; lra].
rewrite <- Rinv_mult_distr.
apply Rinv_lt_contravar.
apply Rmult_lt_0_compat.
- apply Rmult_lt_0_compat;[fourier | assumption].
+ apply Rmult_lt_0_compat;[lra | assumption].
assumption.
replace (/(Rabs y + 1)) with (2 * u).
- fourier.
- unfold u; field; apply Rgt_not_eq; clear -Hgt; fourier.
+ lra.
+ unfold u; field; apply Rgt_not_eq; clear -Hgt; lra.
solve[discrR].
apply Rgt_not_eq; assumption.
unfold tan.
@@ -522,22 +522,22 @@ set (u' := PI / 2); unfold Rdiv; apply Rmult_lt_compat_r; unfold u'.
rewrite cos_shift; assumption.
assert (vlt3 : u < /4).
replace (/4) with (/2 * /2) by field.
- unfold u; apply Rmult_lt_compat_l;[fourier | ].
+ unfold u; apply Rmult_lt_compat_l;[lra | ].
apply Rinv_lt_contravar.
- apply Rmult_lt_0_compat; fourier.
- fourier.
-assert (1 < PI / 2 - u) by (assert (t := PI2_3_2); fourier).
+ apply Rmult_lt_0_compat; lra.
+ lra.
+assert (1 < PI / 2 - u) by (assert (t := PI2_3_2); lra).
apply Rlt_trans with (sin 1).
- assert (t' : 1 <= 4) by fourier.
+ assert (t' : 1 <= 4) by lra.
destruct (pre_sin_bound 1 0 (Rlt_le _ _ Rlt_0_1) t') as [t _].
apply Rlt_le_trans with (2 := t); clear t.
- simpl plus; replace (sin_approx 1 1) with (5/6);[fourier | ].
+ simpl plus; replace (sin_approx 1 1) with (5/6);[lra | ].
unfold sin_approx, sin_term; simpl; field.
apply sin_increasing_1.
- assert (t := PI2_1); fourier.
+ assert (t := PI2_1); lra.
apply Rlt_le, PI2_1.
- assert (t := PI2_1); fourier.
- fourier.
+ assert (t := PI2_1); lra.
+ lra.
assumption.
Qed.
@@ -547,7 +547,7 @@ intros x h; rewrite Ropp_div; apply Ropp_lt_contravar; assumption.
Qed.
Lemma pos_opp_lt : forall x, 0 < x -> -x < x.
-Proof. intros; fourier. Qed.
+Proof. intros; lra. Qed.
Lemma tech_opp_tan : forall x y, -tan x < y -> tan (-x) < y.
Proof.
@@ -562,7 +562,7 @@ set (pr := (conj (tech_opp_tan _ _ (proj2 (Rabs_def2 _ _ Ptan_ub)))
destruct (exists_atan_in_frame (-ub) ub y (pos_opp_lt _ ub0) (ub_opp _ ubpi2)
ubpi2 pr) as [v [[vl vu] vq]].
exists v; clear pr.
-split;[rewrite Ropp_div; split; fourier | assumption].
+split;[rewrite Ropp_div; split; lra | assumption].
Qed.
Definition atan x := let (v, _) := pre_atan x in v.
@@ -581,7 +581,7 @@ Lemma atan_opp : forall x, atan (- x) = - atan x.
Proof.
intros x; generalize (atan_bound (-x)); rewrite Ropp_div;intros [a b].
generalize (atan_bound x); rewrite Ropp_div; intros [c d].
-apply tan_is_inj; try rewrite Ropp_div; try split; try fourier.
+apply tan_is_inj; try rewrite Ropp_div; try split; try lra.
rewrite tan_neg, !atan_right_inv; reflexivity.
Qed.
@@ -604,23 +604,23 @@ assert (int_tan : forall y, tan (- ub) <= y -> y <= tan ub ->
rewrite <- (atan_right_inv y); apply tan_increasing.
destruct (atan_bound y); assumption.
assumption.
- fourier.
- fourier.
+ lra.
+ lra.
destruct (Rle_lt_dec (atan y) ub) as [h | abs]; auto.
assert (tan ub < y).
rewrite <- (atan_right_inv y); apply tan_increasing.
- rewrite Ropp_div; fourier.
+ rewrite Ropp_div; lra.
assumption.
destruct (atan_bound y); assumption.
- fourier.
+ lra.
assert (incr : forall x y, -ub <= x -> x < y -> y <= ub -> tan x < tan y).
intros y z l yz u; apply tan_increasing.
- rewrite Ropp_div; fourier.
+ rewrite Ropp_div; lra.
assumption.
- fourier.
+ lra.
assert (der : forall a, -ub <= a <= ub -> derivable_pt tan a).
intros a [la ua]; apply derivable_pt_tan.
- rewrite Ropp_div; split; fourier.
+ rewrite Ropp_div; split; lra.
assert (df_neq : derive_pt tan (atan x)
(derivable_pt_recip_interv_prelim1 tan atan
(- ub) ub x lb_lt_ub xint inv_p int_tan incr der) <> 0).
@@ -651,7 +651,7 @@ Qed.
Lemma atan_0 : atan 0 = 0.
Proof.
apply tan_is_inj; try (apply atan_bound).
- assert (t := PI_RGT_0); rewrite Ropp_div; split; fourier.
+ assert (t := PI_RGT_0); rewrite Ropp_div; split; lra.
rewrite atan_right_inv, tan_0.
reflexivity.
Qed.
@@ -659,7 +659,7 @@ Qed.
Lemma atan_1 : atan 1 = PI/4.
Proof.
assert (ut := PI_RGT_0).
-assert (-PI/2 < PI/4 < PI/2) by (rewrite Ropp_div; split; fourier).
+assert (-PI/2 < PI/4 < PI/2) by (rewrite Ropp_div; split; lra).
assert (t := atan_bound 1).
apply tan_is_inj; auto.
rewrite tan_PI4, atan_right_inv; reflexivity.
@@ -688,23 +688,23 @@ assert (int_tan : forall y, tan (- ub) <= y -> y <= tan ub ->
rewrite <- (atan_right_inv y); apply tan_increasing.
destruct (atan_bound y); assumption.
assumption.
- fourier.
- fourier.
+ lra.
+ lra.
destruct (Rle_lt_dec (atan y) ub) as [h | abs]; auto.
assert (tan ub < y).
rewrite <- (atan_right_inv y); apply tan_increasing.
- rewrite Ropp_div; fourier.
+ rewrite Ropp_div; lra.
assumption.
destruct (atan_bound y); assumption.
- fourier.
+ lra.
assert (incr : forall x y, -ub <= x -> x < y -> y <= ub -> tan x < tan y).
intros y z l yz u; apply tan_increasing.
- rewrite Ropp_div; fourier.
+ rewrite Ropp_div; lra.
assumption.
- fourier.
+ lra.
assert (der : forall a, -ub <= a <= ub -> derivable_pt tan a).
intros a [la ua]; apply derivable_pt_tan.
- rewrite Ropp_div; split; fourier.
+ rewrite Ropp_div; split; lra.
assert (df_neq : derive_pt tan (atan x)
(derivable_pt_recip_interv_prelim1 tan atan
(- ub) ub x lb_lt_ub xint inv_p int_tan incr der) <> 0).
@@ -883,7 +883,7 @@ Proof.
destruct (Rle_lt_dec 0 x).
assert (pr : 0 <= x <= 1) by tauto.
exact (ps_atan_exists_01 x pr).
-assert (pr : 0 <= -x <= 1) by (destruct Hx; split; fourier).
+assert (pr : 0 <= -x <= 1) by (destruct Hx; split; lra).
destruct (ps_atan_exists_01 _ pr) as [v Pv].
exists (-v).
apply (Un_cv_ext (fun n => (- 1) * sum_f_R0 (tg_alt (Ratan_seq (- x))) n)).
@@ -898,8 +898,8 @@ Proof.
destruct (Rle_lt_dec x 1).
destruct (Rle_lt_dec (-1) x).
left;split; auto.
- right;intros [a1 a2]; fourier.
-right;intros [a1 a2]; fourier.
+ right;intros [a1 a2]; lra.
+right;intros [a1 a2]; lra.
Qed.
Definition ps_atan (x : R) : R :=
@@ -922,7 +922,7 @@ unfold ps_atan.
unfold Rdiv; rewrite !Rmult_0_l, Rmult_0_r; reflexivity.
intros eps ep; exists 0%nat; intros n _; unfold R_dist.
rewrite Rminus_0_r, Rabs_pos_eq; auto with real.
-case h2; split; fourier.
+case h2; split; lra.
Qed.
Lemma ps_atan_exists_1_opp :
@@ -948,9 +948,9 @@ destruct (in_int (- x)) as [inside | outside].
destruct (in_int x) as [ins' | outs'].
generalize (ps_atan_exists_1_opp x inside ins').
intros h; exact h.
- destruct inside; case outs'; split; fourier.
+ destruct inside; case outs'; split; lra.
destruct (in_int x) as [ins' | outs'].
- destruct outside; case ins'; split; fourier.
+ destruct outside; case ins'; split; lra.
apply atan_opp.
Qed.
@@ -1057,7 +1057,7 @@ Proof.
intros x n.
assert (dif : - x ^ 2 <> 1).
apply Rlt_not_eq; apply Rle_lt_trans with 0;[ | apply Rlt_0_1].
-assert (t := pow2_ge_0 x); fourier.
+assert (t := pow2_ge_0 x); lra.
replace (1 + x ^ 2) with (1 - - (x ^ 2)) by ring; rewrite <- (tech3 _ n dif).
apply sum_eq; unfold tg_alt, Datan_seq; intros i _.
rewrite pow_mult, <- Rpow_mult_distr.
@@ -1073,7 +1073,7 @@ intros x y n n_lb x_encad ; assert (x_pos : x >= 0) by intuition.
apply False_ind ; intuition.
clear -x_encad x_pos y_pos ; induction n ; unfold Datan_seq.
case x_pos ; clear x_pos ; intro x_pos.
- simpl ; apply Rmult_gt_0_lt_compat ; intuition. fourier.
+ simpl ; apply Rmult_gt_0_lt_compat ; intuition. lra.
rewrite x_pos ; rewrite pow_i. replace (y ^ (2*1)) with (y*y).
apply Rmult_gt_0_compat ; assumption.
simpl ; field.
@@ -1084,7 +1084,7 @@ intros x y n n_lb x_encad ; assert (x_pos : x >= 0) by intuition.
case x_pos ; clear x_pos ; intro x_pos.
rewrite Hrew ; rewrite Hrew.
apply Rmult_gt_0_lt_compat ; intuition.
- apply Rmult_gt_0_lt_compat ; intuition ; fourier.
+ apply Rmult_gt_0_lt_compat ; intuition ; lra.
rewrite x_pos.
rewrite pow_i ; intuition.
Qed.
@@ -1141,7 +1141,7 @@ elim (pow_lt_1_zero _ x_ub2 _ eps'_pos) ; intros N HN ; exists N.
intros n Hn.
assert (H1 : - x^2 <> 1).
apply Rlt_not_eq; apply Rle_lt_trans with (2 := Rlt_0_1).
-assert (t := pow2_ge_0 x); fourier.
+assert (t := pow2_ge_0 x); lra.
rewrite Datan_sum_eq.
unfold R_dist.
assert (tool : forall a b, a / b - /b = (-1 + a) /b).
@@ -1179,13 +1179,13 @@ apply (Alt_CVU (fun x n => Datan_seq n x)
(Datan_seq (Rabs c + r)) c r).
intros x inb; apply Datan_seq_decreasing;
try (apply Boule_lt in inb; apply Rabs_def2 in inb;
- destruct inb; fourier).
+ destruct inb; lra).
intros x inb; apply Datan_seq_CV_0;
try (apply Boule_lt in inb; apply Rabs_def2 in inb;
- destruct inb; fourier).
+ destruct inb; lra).
intros x inb; apply (Datan_lim x);
try (apply Boule_lt in inb; apply Rabs_def2 in inb;
- destruct inb; fourier).
+ destruct inb; lra).
intros x [ | n] inb.
solve[unfold Datan_seq; apply Rle_refl].
rewrite <- (Datan_seq_Rabs x); apply Rlt_le, Datan_seq_increasing.
@@ -1193,7 +1193,7 @@ apply (Alt_CVU (fun x n => Datan_seq n x)
apply Boule_lt in inb; intuition.
solve[apply Rabs_pos].
apply Datan_seq_CV_0.
- apply Rlt_trans with 0;[fourier | ].
+ apply Rlt_trans with 0;[lra | ].
apply Rplus_le_lt_0_compat.
solve[apply Rabs_pos].
destruct r; assumption.
@@ -1226,7 +1226,7 @@ intros N x x_lb x_ub.
apply Hdelta ; assumption.
unfold id ; field ; assumption.
intros eps eps_pos.
- assert (eps_3_pos : (eps/3) > 0) by fourier.
+ assert (eps_3_pos : (eps/3) > 0) by lra.
elim (IHN (eps/3) eps_3_pos) ; intros delta1 Hdelta1.
assert (Main : derivable_pt_lim (fun x : R =>tg_alt (Ratan_seq x) (S N)) x ((tg_alt (Datan_seq x)) (S N))).
clear -Tool ; intros eps' eps'_pos.
@@ -1297,7 +1297,7 @@ intros N x x_lb x_ub.
intuition ; apply Rlt_le_trans with (r2:=delta) ; intuition unfold delta, mydelta.
apply Rmin_l.
apply Rmin_r.
- fourier.
+ lra.
Qed.
Lemma Ratan_CVU' :
@@ -1310,7 +1310,7 @@ apply (Alt_CVU (fun i r => Ratan_seq r i) ps_atan PI_tg (/2) pos_half);
now intros; apply Ratan_seq_converging, Boule_half_to_interval.
intros x b; apply Boule_half_to_interval in b.
unfold ps_atan; destruct (in_int x) as [inside | outside];
- [ | destruct b; case outside; split; fourier].
+ [ | destruct b; case outside; split; lra].
destruct (ps_atan_exists_1 x inside) as [v Pv].
apply Un_cv_ext with (2 := Pv);[reflexivity].
intros x n b; apply Boule_half_to_interval in b.
@@ -1330,7 +1330,7 @@ exists N; intros n x nN b_y.
case (Rtotal_order 0 x) as [xgt0 | [x0 | x0]].
assert (Boule (/2) {| pos := / 2; cond_pos := pos_half_prf|} x).
revert b_y; unfold Boule; simpl; intros b_y; apply Rabs_def2 in b_y.
- destruct b_y; unfold Boule; simpl; apply Rabs_def1; fourier.
+ destruct b_y; unfold Boule; simpl; apply Rabs_def1; lra.
apply Pn; assumption.
rewrite <- x0, ps_atan0_0.
rewrite <- (sum_eq (fun _ => 0)), sum_cte, Rmult_0_l, Rminus_0_r, Rabs_pos_eq.
@@ -1343,7 +1343,7 @@ replace (ps_atan x - sum_f_R0 (tg_alt (Ratan_seq x)) n) with
rewrite Rabs_Ropp.
assert (Boule (/2) {| pos := / 2; cond_pos := pos_half_prf|} (-x)).
revert b_y; unfold Boule; simpl; intros b_y; apply Rabs_def2 in b_y.
- destruct b_y; unfold Boule; simpl; apply Rabs_def1; fourier.
+ destruct b_y; unfold Boule; simpl; apply Rabs_def1; lra.
apply Pn; assumption.
unfold Rminus; rewrite ps_atan_opp, Ropp_plus_distr, sum_Ratan_seq_opp.
rewrite !Ropp_involutive; reflexivity.
@@ -1372,7 +1372,7 @@ apply continuity_inv.
apply continuity_plus.
apply continuity_const ; unfold constant ; intuition.
apply derivable_continuous ; apply derivable_pow.
-intro x ; apply Rgt_not_eq ; apply Rge_gt_trans with (1+0) ; [|fourier] ;
+intro x ; apply Rgt_not_eq ; apply Rge_gt_trans with (1+0) ; [|lra] ;
apply Rplus_ge_compat_l.
replace (x^2) with (x²).
apply Rle_ge ; apply Rle_0_sqr.
@@ -1393,11 +1393,11 @@ apply derivable_pt_lim_CVU with
assumption.
intros y N inb; apply Rabs_def2 in inb; destruct inb.
apply Datan_is_datan.
- fourier.
- fourier.
+ lra.
+ lra.
intros y inb; apply Rabs_def2 in inb; destruct inb.
- assert (y_gt_0 : -1 < y) by fourier.
- assert (y_lt_1 : y < 1) by fourier.
+ assert (y_gt_0 : -1 < y) by lra.
+ assert (y_lt_1 : y < 1) by lra.
intros eps eps_pos ; elim (Ratan_is_ps_atan eps eps_pos).
intros N HN ; exists N; intros n n_lb ; apply HN ; tauto.
apply Datan_CVU_prelim.
@@ -1406,8 +1406,8 @@ apply derivable_pt_lim_CVU with
replace ((c + r - (c - r)) / 2) with (r :R) by field.
assert (Rabs c < 1 - r).
unfold Boule in Pcr1; destruct r; simpl in *; apply Rabs_def1;
- apply Rabs_def2 in Pcr1; destruct Pcr1; fourier.
- fourier.
+ apply Rabs_def2 in Pcr1; destruct Pcr1; lra.
+ lra.
intros; apply Datan_continuity.
Qed.
@@ -1426,7 +1426,7 @@ Lemma ps_atan_continuity_pt_1 : forall eps : R,
dist R_met (ps_atan x) (Alt_PI/4) < eps).
Proof.
intros eps eps_pos.
-assert (eps_3_pos : eps / 3 > 0) by fourier.
+assert (eps_3_pos : eps / 3 > 0) by lra.
elim (Ratan_is_ps_atan (eps / 3) eps_3_pos) ; intros N1 HN1.
unfold Alt_PI.
destruct exist_PI as [v Pv]; replace ((4 * v)/4) with v by field.
@@ -1461,10 +1461,10 @@ rewrite Rplus_assoc ; apply Rabs_triang.
unfold D_x, no_cond ; split ; [ | apply Rgt_not_eq ] ; intuition.
intuition.
apply HN2; unfold N; omega.
- fourier.
+ lra.
rewrite <- Rabs_Ropp, Ropp_minus_distr; apply HN1.
unfold N; omega.
- fourier.
+ lra.
assumption.
field.
ring.
@@ -1486,11 +1486,11 @@ intros x x_encad Pratan Prmymeta.
rewrite Hrew1.
replace (Rsqr x) with (x ^ 2) by (unfold Rsqr; ring).
unfold Rdiv; rewrite Rmult_1_l; reflexivity.
- fourier.
+ lra.
assumption.
intros; reflexivity.
- fourier.
- assert (t := tan_1_gt_1); split;destruct x_encad; fourier.
+ lra.
+ assert (t := tan_1_gt_1); split;destruct x_encad; lra.
intros; reflexivity.
Qed.
@@ -1503,46 +1503,46 @@ assert (pr1 : forall c : R, 0 < c < x -> derivable_pt (atan - ps_atan) c).
apply derivable_pt_minus.
exact (derivable_pt_atan c).
apply derivable_pt_ps_atan.
- destruct x_encad; destruct c_encad; split; fourier.
+ destruct x_encad; destruct c_encad; split; lra.
assert (pr2 : forall c : R, 0 < c < x -> derivable_pt id c).
- intros ; apply derivable_pt_id; fourier.
+ intros ; apply derivable_pt_id; lra.
assert (delta_cont : forall c : R, 0 <= c <= x -> continuity_pt (atan - ps_atan) c).
intros c [[c_encad1 | c_encad1 ] [c_encad2 | c_encad2]];
apply continuity_pt_minus.
apply derivable_continuous_pt ; apply derivable_pt_atan.
apply derivable_continuous_pt ; apply derivable_pt_ps_atan.
- split; destruct x_encad; fourier.
+ split; destruct x_encad; lra.
apply derivable_continuous_pt, derivable_pt_atan.
apply derivable_continuous_pt, derivable_pt_ps_atan.
- subst c; destruct x_encad; split; fourier.
+ subst c; destruct x_encad; split; lra.
apply derivable_continuous_pt, derivable_pt_atan.
apply derivable_continuous_pt, derivable_pt_ps_atan.
- subst c; split; fourier.
+ subst c; split; lra.
apply derivable_continuous_pt, derivable_pt_atan.
apply derivable_continuous_pt, derivable_pt_ps_atan.
- subst c; destruct x_encad; split; fourier.
+ subst c; destruct x_encad; split; lra.
assert (id_cont : forall c : R, 0 <= c <= x -> continuity_pt id c).
intros ; apply derivable_continuous ; apply derivable_id.
-assert (x_lb : 0 < x) by (destruct x_encad; fourier).
+assert (x_lb : 0 < x) by (destruct x_encad; lra).
elim (MVT (atan - ps_atan)%F id 0 x pr1 pr2 x_lb delta_cont id_cont) ; intros d Temp ; elim Temp ; intros d_encad Main.
clear - Main x_encad.
assert (Temp : forall (pr: derivable_pt (atan - ps_atan) d), derive_pt (atan - ps_atan) d pr = 0).
intro pr.
assert (d_encad3 : -1 < d < 1).
- destruct d_encad; destruct x_encad; split; fourier.
+ destruct d_encad; destruct x_encad; split; lra.
pose (pr3 := derivable_pt_minus atan ps_atan d (derivable_pt_atan d) (derivable_pt_ps_atan d d_encad3)).
rewrite <- pr_nu_var2_interv with (f:=(atan - ps_atan)%F) (g:=(atan - ps_atan)%F) (lb:=0) (ub:=x) (pr1:=pr3) (pr2:=pr).
unfold pr3. rewrite derive_pt_minus.
rewrite Datan_eq_DatanSeq_interv with (Prmymeta := derivable_pt_atan d).
intuition.
assumption.
- destruct d_encad; fourier.
+ destruct d_encad; lra.
assumption.
reflexivity.
assert (iatan0 : atan 0 = 0).
apply tan_is_inj.
apply atan_bound.
- rewrite Ropp_div; assert (t := PI2_RGT_0); split; fourier.
+ rewrite Ropp_div; assert (t := PI2_RGT_0); split; lra.
rewrite tan_0, atan_right_inv; reflexivity.
generalize Main; rewrite Temp, Rmult_0_r.
replace ((atan - ps_atan)%F x) with (atan x - ps_atan x) by intuition.
@@ -1560,19 +1560,19 @@ Qed.
Theorem Alt_PI_eq : Alt_PI = PI.
Proof.
apply Rmult_eq_reg_r with (/4); fold (Alt_PI/4); fold (PI/4);
- [ | apply Rgt_not_eq; fourier].
+ [ | apply Rgt_not_eq; lra].
assert (0 < PI/6) by (apply PI6_RGT_0).
assert (t1:= PI2_1).
assert (t2 := PI_4).
assert (m := Alt_PI_RGT_0).
-assert (-PI/2 < 1 < PI/2) by (rewrite Ropp_div; split; fourier).
+assert (-PI/2 < 1 < PI/2) by (rewrite Ropp_div; split; lra).
apply cond_eq; intros eps ep.
change (R_dist (Alt_PI/4) (PI/4) < eps).
assert (ca : continuity_pt atan 1).
apply derivable_continuous_pt, derivable_pt_atan.
assert (Xe : exists eps', exists eps'',
eps' + eps'' <= eps /\ 0 < eps' /\ 0 < eps'').
- exists (eps/2); exists (eps/2); repeat apply conj; fourier.
+ exists (eps/2); exists (eps/2); repeat apply conj; lra.
destruct Xe as [eps' [eps'' [eps_ineq [ep' ep'']]]].
destruct (ps_atan_continuity_pt_1 _ ep') as [alpha [a0 Palpha]].
destruct (ca _ ep'') as [beta [b0 Pbeta]].
@@ -1585,14 +1585,14 @@ assert (Xa : exists a, 0 < a < 1 /\ R_dist a 1 < alpha /\
assert ((1 - alpha /2) <= Rmax (1 - alpha /2) (1 - beta /2)) by apply Rmax_l.
assert ((1 - beta /2) <= Rmax (1 - alpha /2) (1 - beta /2)) by apply Rmax_r.
assert (Rmax (1 - alpha /2) (1 - beta /2) < 1)
- by (apply Rmax_lub_lt; fourier).
- split;[split;[ | apply Rmax_lub_lt]; fourier | ].
+ by (apply Rmax_lub_lt; lra).
+ split;[split;[ | apply Rmax_lub_lt]; lra | ].
assert (0 <= 1 - Rmax (/ 2) (Rmax (1 - alpha / 2) (1 - beta / 2))).
assert (Rmax (/2) (Rmax (1 - alpha / 2)
- (1 - beta /2)) <= 1) by (apply Rmax_lub; fourier).
- fourier.
+ (1 - beta /2)) <= 1) by (apply Rmax_lub; lra).
+ lra.
split; unfold R_dist; rewrite <-Rabs_Ropp, Ropp_minus_distr,
- Rabs_pos_eq;fourier.
+ Rabs_pos_eq;lra.
destruct Xa as [a [[Pa0 Pa1] [P1 P2]]].
apply Rle_lt_trans with (1 := R_dist_tri _ _ (ps_atan a)).
apply Rlt_le_trans with (2 := eps_ineq).
diff --git a/theories/Reals/Rbasic_fun.v b/theories/Reals/Rbasic_fun.v
index aa886cee03..59e0148625 100644
--- a/theories/Reals/Rbasic_fun.v
+++ b/theories/Reals/Rbasic_fun.v
@@ -15,7 +15,7 @@
Require Import Rbase.
Require Import R_Ifp.
-Require Import Fourier.
+Require Import Lra.
Local Open Scope R_scope.
Implicit Type r : R.
@@ -357,7 +357,7 @@ Qed.
Lemma Rle_abs : forall x:R, x <= Rabs x.
Proof.
- intro; unfold Rabs; case (Rcase_abs x); intros; fourier.
+ intro; unfold Rabs; case (Rcase_abs x); intros; lra.
Qed.
Definition RRle_abs := Rle_abs.
diff --git a/theories/Reals/Rderiv.v b/theories/Reals/Rderiv.v
index dfa5c7104c..aaf691ed1a 100644
--- a/theories/Reals/Rderiv.v
+++ b/theories/Reals/Rderiv.v
@@ -16,7 +16,7 @@
Require Import Rbase.
Require Import Rfunctions.
Require Import Rlimit.
-Require Import Fourier.
+Require Import Lra.
Require Import Omega.
Local Open Scope R_scope.
@@ -77,7 +77,7 @@ Proof.
elim (Rmin_Rgt (/ 2) x 0); intros a b; cut (0 < 2).
intro; generalize (Rinv_0_lt_compat 2 H3); intro; fold (/ 2 > 0) in H4;
apply (b (conj H4 H)).
- fourier.
+ lra.
intros; elim H3; clear H3; intros;
generalize
(let (H1, H2) :=
@@ -167,7 +167,7 @@ Proof.
unfold Rabs; destruct (Rcase_abs 2) as [Hlt|Hge]; auto.
cut (0 < 2).
intro H7; elim (Rlt_asym 0 2 H7 Hlt).
- fourier.
+ lra.
apply Rabs_no_R0.
discrR.
Qed.
diff --git a/theories/Reals/Reals.v b/theories/Reals/Reals.v
index b249b519f5..3ef368bb4f 100644
--- a/theories/Reals/Reals.v
+++ b/theories/Reals/Reals.v
@@ -30,3 +30,4 @@ Require Export SeqSeries.
Require Export Rtrigo.
Require Export Ranalysis.
Require Export Integration.
+Require Import Fourier.
diff --git a/theories/Reals/Rlimit.v b/theories/Reals/Rlimit.v
index b14fcc4d36..e3e995d201 100644
--- a/theories/Reals/Rlimit.v
+++ b/theories/Reals/Rlimit.v
@@ -15,7 +15,7 @@
Require Import Rbase.
Require Import Rfunctions.
-Require Import Fourier.
+Require Import Lra.
Local Open Scope R_scope.
(*******************************)
@@ -24,7 +24,7 @@ Local Open Scope R_scope.
(*********)
Lemma eps2_Rgt_R0 : forall eps:R, eps > 0 -> eps * / 2 > 0.
Proof.
- intros; fourier.
+ intros; lra.
Qed.
(*********)
@@ -45,14 +45,14 @@ Qed.
Lemma Rlt_eps2_eps : forall eps:R, eps > 0 -> eps * / 2 < eps.
Proof.
intros.
- fourier.
+ lra.
Qed.
(*********)
Lemma Rlt_eps4_eps : forall eps:R, eps > 0 -> eps * / (2 + 2) < eps.
Proof.
intros.
- fourier.
+ lra.
Qed.
(*********)
diff --git a/theories/Reals/Rpower.v b/theories/Reals/Rpower.v
index c6fac951b6..d465523a70 100644
--- a/theories/Reals/Rpower.v
+++ b/theories/Reals/Rpower.v
@@ -25,7 +25,7 @@ Require Import R_sqrt.
Require Import Sqrt_reg.
Require Import MVT.
Require Import Ranalysis4.
-Require Import Fourier.
+Require Import Lra.
Local Open Scope R_scope.
Lemma P_Rmin : forall (P:R -> Prop) (x y:R), P x -> P y -> P (Rmin x y).
@@ -714,7 +714,7 @@ Qed.
Lemma Rlt_Rpower_l a b c: 0 < c -> 0 < a < b -> a ^R c < b ^R c.
Proof.
intros c0 [a0 ab]; apply exp_increasing.
-now apply Rmult_lt_compat_l; auto; apply ln_increasing; fourier.
+now apply Rmult_lt_compat_l; auto; apply ln_increasing; lra.
Qed.
Lemma Rle_Rpower_l a b c: 0 <= c -> 0 < a <= b -> a ^R c <= b ^R c.
@@ -722,7 +722,7 @@ Proof.
intros [c0 | c0];
[ | intros; rewrite <- c0, !Rpower_O; [apply Rle_refl | |] ].
intros [a0 [ab|ab]].
- now apply Rlt_le, Rlt_Rpower_l;[ | split]; fourier.
+ now apply Rlt_le, Rlt_Rpower_l;[ | split]; lra.
rewrite ab; apply Rle_refl.
apply Rlt_le_trans with a; tauto.
tauto.
@@ -754,10 +754,10 @@ assert (cmp : 0 < x + sqrt (x ^ 2 + 1)).
replace (x ^ 2) with ((-x) ^ 2) by ring.
assert (sqrt ((- x) ^ 2) < sqrt ((-x)^2+1)).
apply sqrt_lt_1_alt.
- split;[apply pow_le | ]; fourier.
+ split;[apply pow_le | ]; lra.
pattern x at 1; replace x with (- (sqrt ((- x) ^ 2))).
- assert (t:= sqrt_pos ((-x)^2)); fourier.
- simpl; rewrite Rmult_1_r, sqrt_square, Ropp_involutive;[reflexivity | fourier].
+ assert (t:= sqrt_pos ((-x)^2)); lra.
+ simpl; rewrite Rmult_1_r, sqrt_square, Ropp_involutive;[reflexivity | lra].
apply Rplus_lt_le_0_compat;[apply Rnot_le_gt; assumption | apply sqrt_pos].
rewrite exp_ln;[ | assumption].
rewrite exp_Ropp, exp_ln;[ | assumption].
@@ -770,7 +770,7 @@ apply Rmult_eq_reg_l with (2 * (x + sqrt (x ^ 2 + 1)));[ |
apply Rgt_not_eq, Rmult_lt_0_compat;[apply Rlt_0_2 | assumption]].
assert (pow2_sqrt : forall x, 0 <= x -> sqrt x ^ 2 = x) by
(intros; simpl; rewrite Rmult_1_r, sqrt_sqrt; auto).
-field_simplify;[rewrite pow2_sqrt;[field | ] | apply Rgt_not_eq; fourier].
+field_simplify;[rewrite pow2_sqrt;[field | ] | apply Rgt_not_eq; lra].
apply Rplus_le_le_0_compat;[simpl; rewrite Rmult_1_r; apply (Rle_0_sqr x)|apply Rlt_le, Rlt_0_1].
Qed.
@@ -784,12 +784,12 @@ assert (0 < x + sqrt (x ^ 2 + 1)).
replace (x ^ 2) with ((-x) ^ 2) by ring.
assert (sqrt ((- x) ^ 2) < sqrt ((-x)^2+1)).
apply sqrt_lt_1_alt.
- split;[apply pow_le|]; fourier.
+ split;[apply pow_le|]; lra.
pattern x at 1; replace x with (- (sqrt ((- x) ^ 2))).
- assert (t:= sqrt_pos ((-x)^2)); fourier.
- simpl; rewrite Rmult_1_r, sqrt_square, Ropp_involutive; auto; fourier.
+ assert (t:= sqrt_pos ((-x)^2)); lra.
+ simpl; rewrite Rmult_1_r, sqrt_square, Ropp_involutive; auto; lra.
assert (0 < x ^ 2 + 1).
- apply Rplus_le_lt_0_compat;[simpl; rewrite Rmult_1_r; apply Rle_0_sqr|fourier].
+ apply Rplus_le_lt_0_compat;[simpl; rewrite Rmult_1_r; apply Rle_0_sqr|lra].
replace (/sqrt (x ^ 2 + 1)) with
(/(x + sqrt (x ^ 2 + 1)) *
(1 + (/(2 * sqrt (x ^ 2 + 1)) * (INR 2 * x ^ 1 + 0)))).
@@ -817,7 +817,7 @@ intros x y xy.
case (Rle_dec (arcsinh y) (arcsinh x));[ | apply Rnot_le_lt ].
intros abs; case (Rlt_not_le _ _ xy).
rewrite <- (sinh_arcsinh y), <- (sinh_arcsinh x).
-destruct abs as [lt | q];[| rewrite q; fourier].
+destruct abs as [lt | q];[| rewrite q; lra].
apply Rlt_le, sinh_lt; assumption.
Qed.
diff --git a/theories/Reals/Rsqrt_def.v b/theories/Reals/Rsqrt_def.v
index 6a3dd97656..9b8dd1db0b 100644
--- a/theories/Reals/Rsqrt_def.v
+++ b/theories/Reals/Rsqrt_def.v
@@ -392,7 +392,7 @@ Definition cond_positivity (x:R) : bool :=
| right _ => false
end.
-(** Sequential caracterisation of continuity *)
+(** Sequential characterisation of continuity *)
Lemma continuity_seq :
forall (f:R -> R) (Un:nat -> R) (l:R),
continuity_pt f l -> Un_cv Un l -> Un_cv (fun i:nat => f (Un i)) (f l).
diff --git a/theories/Reals/Rtrigo.v b/theories/Reals/Rtrigo.v
index ffc0adf509..ddd8722e1e 100644
--- a/theories/Reals/Rtrigo.v
+++ b/theories/Reals/Rtrigo.v
@@ -18,7 +18,7 @@ Require Export Cos_rel.
Require Export Cos_plus.
Require Import ZArith_base.
Require Import Zcomplements.
-Require Import Fourier.
+Require Import Lra.
Require Import Ranalysis1.
Require Import Rsqrt_def.
Require Import PSeries_reg.
diff --git a/theories/Reals/Rtrigo1.v b/theories/Reals/Rtrigo1.v
index bf00f736f7..a75fd2ddeb 100644
--- a/theories/Reals/Rtrigo1.v
+++ b/theories/Reals/Rtrigo1.v
@@ -18,7 +18,7 @@ Require Export Cos_rel.
Require Export Cos_plus.
Require Import ZArith_base.
Require Import Zcomplements.
-Require Import Fourier.
+Require Import Lra.
Require Import Ranalysis1.
Require Import Rsqrt_def.
Require Import PSeries_reg.
@@ -175,10 +175,10 @@ Qed.
Lemma sin_gt_cos_7_8 : sin (7 / 8) > cos (7 / 8).
Proof.
-assert (lo1 : 0 <= 7/8) by fourier.
-assert (up1 : 7/8 <= 4) by fourier.
-assert (lo : -2 <= 7/8) by fourier.
-assert (up : 7/8 <= 2) by fourier.
+assert (lo1 : 0 <= 7/8) by lra.
+assert (up1 : 7/8 <= 4) by lra.
+assert (lo : -2 <= 7/8) by lra.
+assert (up : 7/8 <= 2) by lra.
destruct (pre_sin_bound _ 0 lo1 up1) as [lower _ ].
destruct (pre_cos_bound _ 0 lo up) as [_ upper].
apply Rle_lt_trans with (1 := upper).
@@ -205,12 +205,12 @@ Definition PI_2_aux : {z | 7/8 <= z <= 7/4 /\ -cos z = 0}.
assert (cc : continuity (fun r =>- cos r)).
apply continuity_opp, continuity_cos.
assert (cvp : 0 < cos (7/8)).
- assert (int78 : -2 <= 7/8 <= 2) by (split; fourier).
+ assert (int78 : -2 <= 7/8 <= 2) by (split; lra).
destruct int78 as [lower upper].
case (pre_cos_bound _ 0 lower upper).
unfold cos_approx; simpl sum_f_R0; unfold cos_term.
intros cl _; apply Rlt_le_trans with (2 := cl); simpl.
- fourier.
+ lra.
assert (cun : cos (7/4) < 0).
replace (7/4) with (7/8 + 7/8) by field.
rewrite cos_plus.
@@ -218,7 +218,7 @@ assert (cun : cos (7/4) < 0).
exact sin_gt_cos_7_8.
apply Rlt_le; assumption.
apply Rlt_le; apply Rlt_trans with (1 := cvp); exact sin_gt_cos_7_8.
-apply IVT; auto; fourier.
+apply IVT; auto; lra.
Qed.
Definition PI2 := proj1_sig PI_2_aux.
@@ -270,7 +270,7 @@ Qed.
Lemma sin_pos_tech : forall x, 0 < x < 2 -> 0 < sin x.
intros x [int1 int2].
assert (lo : 0 <= x) by (apply Rlt_le; assumption).
-assert (up : x <= 4) by (apply Rlt_le, Rlt_trans with (1:=int2); fourier).
+assert (up : x <= 4) by (apply Rlt_le, Rlt_trans with (1:=int2); lra).
destruct (pre_sin_bound _ 0 lo up) as [t _]; clear lo up.
apply Rlt_le_trans with (2:= t); clear t.
unfold sin_approx; simpl sum_f_R0; unfold sin_term; simpl.
@@ -280,13 +280,13 @@ end.
assert (t' : x ^ 2 <= 4).
replace 4 with (2 ^ 2) by field.
apply (pow_incr x 2); split; apply Rlt_le; assumption.
-apply Rmult_lt_0_compat;[assumption | fourier ].
+apply Rmult_lt_0_compat;[assumption | lra ].
Qed.
Lemma sin_PI2 : sin (PI / 2) = 1.
replace (PI / 2) with PI2 by (unfold PI; field).
assert (int' : 0 < PI2 < 2).
- destruct pi2_int; split; fourier.
+ destruct pi2_int; split; lra.
assert (lo2 := sin_pos_tech PI2 int').
assert (t2 : Rabs (sin PI2) = 1).
rewrite <- Rabs_R1; apply Rsqr_eq_abs_0.
@@ -295,10 +295,10 @@ revert t2; rewrite Rabs_pos_eq;[| apply Rlt_le]; tauto.
Qed.
Lemma PI_RGT_0 : PI > 0.
-Proof. unfold PI; destruct pi2_int; fourier. Qed.
+Proof. unfold PI; destruct pi2_int; lra. Qed.
Lemma PI_4 : PI <= 4.
-Proof. unfold PI; destruct pi2_int; fourier. Qed.
+Proof. unfold PI; destruct pi2_int; lra. Qed.
(**********)
Lemma PI_neq0 : PI <> 0.
@@ -344,13 +344,13 @@ Lemma cos_bound : forall (a : R) (n : nat), - PI / 2 <= a -> a <= PI / 2 ->
Proof.
intros a n lower upper; apply pre_cos_bound.
apply Rle_trans with (2 := lower).
- apply Rmult_le_reg_r with 2; [fourier |].
+ apply Rmult_le_reg_r with 2; [lra |].
replace ((-PI/2) * 2) with (-PI) by field.
- assert (t := PI_4); fourier.
+ assert (t := PI_4); lra.
apply Rle_trans with (1 := upper).
-apply Rmult_le_reg_r with 2; [fourier | ].
+apply Rmult_le_reg_r with 2; [lra | ].
replace ((PI/2) * 2) with PI by field.
-generalize PI_4; intros; fourier.
+generalize PI_4; intros; lra.
Qed.
(**********)
Lemma neg_cos : forall x:R, cos (x + PI) = - cos x.
@@ -749,19 +749,19 @@ Qed.
Lemma _PI2_RLT_0 : - (PI / 2) < 0.
Proof.
assert (H := PI_RGT_0).
- fourier.
+ lra.
Qed.
Lemma PI4_RLT_PI2 : PI / 4 < PI / 2.
Proof.
assert (H := PI_RGT_0).
- fourier.
+ lra.
Qed.
Lemma PI2_Rlt_PI : PI / 2 < PI.
Proof.
assert (H := PI_RGT_0).
- fourier.
+ lra.
Qed.
(***************************************************)
diff --git a/theories/Reals/Rtrigo_calc.v b/theories/Reals/Rtrigo_calc.v
index 7cbfc63033..78797c87c8 100644
--- a/theories/Reals/Rtrigo_calc.v
+++ b/theories/Reals/Rtrigo_calc.v
@@ -205,7 +205,6 @@ Proof with trivial.
rewrite cos2; unfold Rsqr; rewrite sin_PI6; rewrite sqrt_def...
field.
left ; prove_sup0.
- discrR.
Qed.
Lemma tan_PI6 : tan (PI / 6) = 1 / sqrt 3.
diff --git a/theories/Strings/Ascii.v b/theories/Strings/Ascii.v
index 5154b75b3f..31a7fb8ad6 100644
--- a/theories/Strings/Ascii.v
+++ b/theories/Strings/Ascii.v
@@ -40,6 +40,40 @@ Proof.
decide equality; apply bool_dec.
Defined.
+Local Open Scope lazy_bool_scope.
+
+Definition eqb (a b : ascii) : bool :=
+ match a, b with
+ | Ascii a0 a1 a2 a3 a4 a5 a6 a7,
+ Ascii b0 b1 b2 b3 b4 b5 b6 b7 =>
+ Bool.eqb a0 b0 &&& Bool.eqb a1 b1 &&& Bool.eqb a2 b2 &&& Bool.eqb a3 b3
+ &&& Bool.eqb a4 b4 &&& Bool.eqb a5 b5 &&& Bool.eqb a6 b6 &&& Bool.eqb a7 b7
+ end.
+
+Infix "=?" := eqb : char_scope.
+
+Lemma eqb_spec (a b : ascii) : reflect (a = b) (a =? b)%char.
+Proof.
+ destruct a, b; simpl.
+ do 8 (case Bool.eqb_spec; [ intros -> | constructor; now intros [= ] ]).
+ now constructor.
+Qed.
+
+Local Ltac t_eqb :=
+ repeat first [ congruence
+ | progress subst
+ | apply conj
+ | match goal with
+ | [ |- context[eqb ?x ?y] ] => destruct (eqb_spec x y)
+ end
+ | intro ].
+Lemma eqb_refl x : (x =? x)%char = true. Proof. t_eqb. Qed.
+Lemma eqb_sym x y : (x =? y)%char = (y =? x)%char. Proof. t_eqb. Qed.
+Lemma eqb_eq n m : (n =? m)%char = true <-> n = m. Proof. t_eqb. Qed.
+Lemma eqb_neq x y : (x =? y)%char = false <-> x <> y. Proof. t_eqb. Qed.
+Lemma eqb_compat: Morphisms.Proper (Morphisms.respectful eq (Morphisms.respectful eq eq)) eqb.
+Proof. t_eqb. Qed.
+
(** * Conversion between natural numbers modulo 256 and ascii characters *)
(** Auxiliary function that turns a positive into an ascii by
diff --git a/theories/Strings/BinaryString.v b/theories/Strings/BinaryString.v
new file mode 100644
index 0000000000..6df0a9170a
--- /dev/null
+++ b/theories/Strings/BinaryString.v
@@ -0,0 +1,147 @@
+(************************************************************************)
+(* 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 *)
+(************************************************************************)
+
+Require Import Ascii String.
+Require Import BinNums.
+Import BinNatDef.
+Import BinIntDef.
+Import BinPosDef.
+
+Local Open Scope positive_scope.
+Local Open Scope string_scope.
+
+Definition ascii_to_digit (ch : ascii) : option N
+ := (if ascii_dec ch "0" then Some 0
+ else if ascii_dec ch "1" then Some 1
+ else None)%N.
+
+Fixpoint pos_bin_app (p q:positive) : positive :=
+ match q with
+ | q~0 => (pos_bin_app p q)~0
+ | q~1 => (pos_bin_app p q)~1
+ | 1 => p~1
+ end.
+
+Module Raw.
+ Fixpoint of_pos (p : positive) (rest : string) : string
+ := match p with
+ | 1 => String "1" rest
+ | p'~0 => of_pos p' (String "0" rest)
+ | p'~1 => of_pos p' (String "1" rest)
+ end.
+
+ Fixpoint to_N (s : string) (rest : N)
+ : N
+ := match s with
+ | "" => rest
+ | String ch s'
+ => to_N
+ s'
+ match ascii_to_digit ch with
+ | Some v => N.add v (N.double rest)
+ | None => N0
+ end
+ end.
+
+ Fixpoint to_N_of_pos (p : positive) (rest : string) (base : N)
+ : to_N (of_pos p rest) base
+ = to_N rest match base with
+ | N0 => N.pos p
+ | Npos v => Npos (pos_bin_app v p)
+ end.
+ Proof.
+ destruct p as [p|p|]; destruct base; try reflexivity;
+ cbn; rewrite to_N_of_pos; reflexivity.
+ Qed.
+End Raw.
+
+Definition of_pos (p : positive) : string
+ := String "0" (String "b" (Raw.of_pos p "")).
+Definition of_N (n : N) : string
+ := match n with
+ | N0 => "0b0"
+ | Npos p => of_pos p
+ end.
+Definition of_Z (z : Z) : string
+ := match z with
+ | Zneg p => String "-" (of_pos p)
+ | Z0 => "0b0"
+ | Zpos p => of_pos p
+ end.
+Definition of_nat (n : nat) : string
+ := of_N (N.of_nat n).
+
+Definition to_N (s : string) : N
+ := match s with
+ | String s0 (String sb s)
+ => if ascii_dec s0 "0"
+ then if ascii_dec sb "b"
+ then Raw.to_N s N0
+ else N0
+ else N0
+ | _ => N0
+ end.
+Definition to_pos (s : string) : positive
+ := match to_N s with
+ | N0 => 1
+ | Npos p => p
+ end.
+Definition to_Z (s : string) : Z
+ := let '(is_neg, n) := match s with
+ | String s0 s'
+ => if ascii_dec s0 "-"
+ then (true, to_N s')
+ else (false, to_N s)
+ | EmptyString => (false, to_N s)
+ end in
+ match n with
+ | N0 => Z0
+ | Npos p => if is_neg then Zneg p else Zpos p
+ end.
+Definition to_nat (s : string) : nat
+ := N.to_nat (to_N s).
+
+Lemma to_N_of_N (n : N)
+ : to_N (of_N n)
+ = n.
+Proof.
+ destruct n; [ reflexivity | apply Raw.to_N_of_pos ].
+Qed.
+
+Lemma Z_of_of_Z (z : Z)
+ : to_Z (of_Z z)
+ = z.
+Proof.
+ cbv [of_Z to_Z]; destruct z as [|z|z]; cbn;
+ try reflexivity;
+ rewrite Raw.to_N_of_pos; cbn; reflexivity.
+Qed.
+
+Lemma to_nat_of_nat (n : nat)
+ : to_nat (of_nat n)
+ = n.
+Proof.
+ cbv [to_nat of_nat];
+ rewrite to_N_of_N, Nnat.Nat2N.id; reflexivity.
+Qed.
+
+Lemma to_pos_of_pos (p : positive)
+ : to_pos (of_pos p)
+ = p.
+Proof.
+ cbv [of_pos to_pos to_N]; cbn;
+ rewrite Raw.to_N_of_pos; cbn; reflexivity.
+Qed.
+
+Example of_pos_1 : of_pos 1 = "0b1" := eq_refl.
+Example of_pos_2 : of_pos 2 = "0b10" := eq_refl.
+Example of_pos_3 : of_pos 3 = "0b11" := eq_refl.
+Example of_N_0 : of_N 0 = "0b0" := eq_refl.
+Example of_Z_0 : of_Z 0 = "0b0" := eq_refl.
+Example of_Z_m1 : of_Z (-1) = "-0b1" := eq_refl.
+Example of_nat_0 : of_nat 0 = "0b0" := eq_refl.
diff --git a/theories/Strings/HexString.v b/theories/Strings/HexString.v
new file mode 100644
index 0000000000..9ea93c909e
--- /dev/null
+++ b/theories/Strings/HexString.v
@@ -0,0 +1,229 @@
+(************************************************************************)
+(* 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 *)
+(************************************************************************)
+
+Require Import Ascii String.
+Require Import BinNums.
+Import BinNatDef.
+Import BinIntDef.
+Import BinPosDef.
+
+Local Open Scope positive_scope.
+Local Open Scope string_scope.
+
+Local Notation "a || b"
+ := (if a then true else if b then true else false).
+Definition ascii_to_digit (ch : ascii) : option N
+ := (if ascii_dec ch "0" then Some 0
+ else if ascii_dec ch "1" then Some 1
+ else if ascii_dec ch "2" then Some 2
+ else if ascii_dec ch "3" then Some 3
+ else if ascii_dec ch "4" then Some 4
+ else if ascii_dec ch "5" then Some 5
+ else if ascii_dec ch "6" then Some 6
+ else if ascii_dec ch "7" then Some 7
+ else if ascii_dec ch "8" then Some 8
+ else if ascii_dec ch "9" then Some 9
+ else if ascii_dec ch "a" || ascii_dec ch "A" then Some 10
+ else if ascii_dec ch "b" || ascii_dec ch "B" then Some 11
+ else if ascii_dec ch "c" || ascii_dec ch "C" then Some 12
+ else if ascii_dec ch "d" || ascii_dec ch "D" then Some 13
+ else if ascii_dec ch "e" || ascii_dec ch "E" then Some 14
+ else if ascii_dec ch "f" || ascii_dec ch "F" then Some 15
+ else None)%N.
+
+Fixpoint pos_hex_app (p q:positive) : positive :=
+ match q with
+ | 1 => p~0~0~0~1
+ | 2 => p~0~0~1~0
+ | 3 => p~0~0~1~1
+ | 4 => p~0~1~0~0
+ | 5 => p~0~1~0~1
+ | 6 => p~0~1~1~0
+ | 7 => p~0~1~1~1
+ | 8 => p~1~0~0~0
+ | 9 => p~1~0~0~1
+ | 10 => p~1~0~1~0
+ | 11 => p~1~0~1~1
+ | 12 => p~1~1~0~0
+ | 13 => p~1~1~0~1
+ | 14 => p~1~1~1~0
+ | 15 => p~1~1~1~1
+ | q~0~0~0~0 => (pos_hex_app p q)~0~0~0~0
+ | q~0~0~0~1 => (pos_hex_app p q)~0~0~0~1
+ | q~0~0~1~0 => (pos_hex_app p q)~0~0~1~0
+ | q~0~0~1~1 => (pos_hex_app p q)~0~0~1~1
+ | q~0~1~0~0 => (pos_hex_app p q)~0~1~0~0
+ | q~0~1~0~1 => (pos_hex_app p q)~0~1~0~1
+ | q~0~1~1~0 => (pos_hex_app p q)~0~1~1~0
+ | q~0~1~1~1 => (pos_hex_app p q)~0~1~1~1
+ | q~1~0~0~0 => (pos_hex_app p q)~1~0~0~0
+ | q~1~0~0~1 => (pos_hex_app p q)~1~0~0~1
+ | q~1~0~1~0 => (pos_hex_app p q)~1~0~1~0
+ | q~1~0~1~1 => (pos_hex_app p q)~1~0~1~1
+ | q~1~1~0~0 => (pos_hex_app p q)~1~1~0~0
+ | q~1~1~0~1 => (pos_hex_app p q)~1~1~0~1
+ | q~1~1~1~0 => (pos_hex_app p q)~1~1~1~0
+ | q~1~1~1~1 => (pos_hex_app p q)~1~1~1~1
+ end.
+
+Module Raw.
+ Fixpoint of_pos (p : positive) (rest : string) : string
+ := match p with
+ | 1 => String "1" rest
+ | 2 => String "2" rest
+ | 3 => String "3" rest
+ | 4 => String "4" rest
+ | 5 => String "5" rest
+ | 6 => String "6" rest
+ | 7 => String "7" rest
+ | 8 => String "8" rest
+ | 9 => String "9" rest
+ | 10 => String "a" rest
+ | 11 => String "b" rest
+ | 12 => String "c" rest
+ | 13 => String "d" rest
+ | 14 => String "e" rest
+ | 15 => String "f" rest
+ | p'~0~0~0~0 => of_pos p' (String "0" rest)
+ | p'~0~0~0~1 => of_pos p' (String "1" rest)
+ | p'~0~0~1~0 => of_pos p' (String "2" rest)
+ | p'~0~0~1~1 => of_pos p' (String "3" rest)
+ | p'~0~1~0~0 => of_pos p' (String "4" rest)
+ | p'~0~1~0~1 => of_pos p' (String "5" rest)
+ | p'~0~1~1~0 => of_pos p' (String "6" rest)
+ | p'~0~1~1~1 => of_pos p' (String "7" rest)
+ | p'~1~0~0~0 => of_pos p' (String "8" rest)
+ | p'~1~0~0~1 => of_pos p' (String "9" rest)
+ | p'~1~0~1~0 => of_pos p' (String "a" rest)
+ | p'~1~0~1~1 => of_pos p' (String "b" rest)
+ | p'~1~1~0~0 => of_pos p' (String "c" rest)
+ | p'~1~1~0~1 => of_pos p' (String "d" rest)
+ | p'~1~1~1~0 => of_pos p' (String "e" rest)
+ | p'~1~1~1~1 => of_pos p' (String "f" rest)
+ end.
+
+ Fixpoint to_N (s : string) (rest : N)
+ : N
+ := match s with
+ | "" => rest
+ | String ch s'
+ => to_N
+ s'
+ match ascii_to_digit ch with
+ | Some v => N.add v (N.mul 16 rest)
+ | None => N0
+ end
+ end.
+
+ Fixpoint to_N_of_pos (p : positive) (rest : string) (base : N)
+ : to_N (of_pos p rest) base
+ = to_N rest match base with
+ | N0 => N.pos p
+ | Npos v => Npos (pos_hex_app v p)
+ end.
+ Proof.
+ do 4 try destruct p as [p|p|]; destruct base; try reflexivity;
+ cbn; rewrite to_N_of_pos; reflexivity.
+ Qed.
+End Raw.
+
+Definition of_pos (p : positive) : string
+ := String "0" (String "x" (Raw.of_pos p "")).
+Definition of_N (n : N) : string
+ := match n with
+ | N0 => "0x0"
+ | Npos p => of_pos p
+ end.
+Definition of_Z (z : Z) : string
+ := match z with
+ | Zneg p => String "-" (of_pos p)
+ | Z0 => "0x0"
+ | Zpos p => of_pos p
+ end.
+Definition of_nat (n : nat) : string
+ := of_N (N.of_nat n).
+
+Definition to_N (s : string) : N
+ := match s with
+ | String s0 (String so s)
+ => if ascii_dec s0 "0"
+ then if ascii_dec so "x"
+ then Raw.to_N s N0
+ else N0
+ else N0
+ | _ => N0
+ end.
+Definition to_pos (s : string) : positive
+ := match to_N s with
+ | N0 => 1
+ | Npos p => p
+ end.
+Definition to_Z (s : string) : Z
+ := let '(is_neg, n) := match s with
+ | String s0 s'
+ => if ascii_dec s0 "-"
+ then (true, to_N s')
+ else (false, to_N s)
+ | EmptyString => (false, to_N s)
+ end in
+ match n with
+ | N0 => Z0
+ | Npos p => if is_neg then Zneg p else Zpos p
+ end.
+Definition to_nat (s : string) : nat
+ := N.to_nat (to_N s).
+
+Lemma to_N_of_N (n : N)
+ : to_N (of_N n)
+ = n.
+Proof.
+ destruct n; [ reflexivity | apply Raw.to_N_of_pos ].
+Qed.
+
+Lemma to_Z_of_Z (z : Z)
+ : to_Z (of_Z z)
+ = z.
+Proof.
+ cbv [of_Z to_Z]; destruct z as [|z|z]; cbn;
+ try reflexivity;
+ rewrite Raw.to_N_of_pos; cbn; reflexivity.
+Qed.
+
+Lemma to_nat_of_nat (n : nat)
+ : to_nat (of_nat n)
+ = n.
+Proof.
+ cbv [to_nat of_nat];
+ rewrite to_N_of_N, Nnat.Nat2N.id; reflexivity.
+Qed.
+
+Lemma to_pos_of_pos (p : positive)
+ : to_pos (of_pos p)
+ = p.
+Proof.
+ cbv [of_pos to_pos to_N]; cbn;
+ rewrite Raw.to_N_of_pos; cbn; reflexivity.
+Qed.
+
+Example of_pos_1 : of_pos 1 = "0x1" := eq_refl.
+Example of_pos_2 : of_pos 2 = "0x2" := eq_refl.
+Example of_pos_3 : of_pos 3 = "0x3" := eq_refl.
+Example of_pos_7 : of_pos 7 = "0x7" := eq_refl.
+Example of_pos_8 : of_pos 8 = "0x8" := eq_refl.
+Example of_pos_9 : of_pos 9 = "0x9" := eq_refl.
+Example of_pos_10 : of_pos 10 = "0xa" := eq_refl.
+Example of_pos_11 : of_pos 11 = "0xb" := eq_refl.
+Example of_pos_12 : of_pos 12 = "0xc" := eq_refl.
+Example of_pos_13 : of_pos 13 = "0xd" := eq_refl.
+Example of_pos_14 : of_pos 14 = "0xe" := eq_refl.
+Example of_pos_15 : of_pos 15 = "0xf" := eq_refl.
+Example of_pos_16 : of_pos 16 = "0x10" := eq_refl.
+Example of_N_0 : of_N 0 = "0x0" := eq_refl.
+Example of_Z_0 : of_Z 0 = "0x0" := eq_refl.
+Example of_Z_m1 : of_Z (-1) = "-0x1" := eq_refl.
+Example of_nat_0 : of_nat 0 = "0x0" := eq_refl.
diff --git a/theories/Strings/OctalString.v b/theories/Strings/OctalString.v
new file mode 100644
index 0000000000..fe8cc9aae9
--- /dev/null
+++ b/theories/Strings/OctalString.v
@@ -0,0 +1,179 @@
+(************************************************************************)
+(* 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 *)
+(************************************************************************)
+
+Require Import Ascii String.
+Require Import BinNums.
+Import BinNatDef.
+Import BinIntDef.
+Import BinPosDef.
+
+Local Open Scope positive_scope.
+Local Open Scope string_scope.
+
+Definition ascii_to_digit (ch : ascii) : option N
+ := (if ascii_dec ch "0" then Some 0
+ else if ascii_dec ch "1" then Some 1
+ else if ascii_dec ch "2" then Some 2
+ else if ascii_dec ch "3" then Some 3
+ else if ascii_dec ch "4" then Some 4
+ else if ascii_dec ch "5" then Some 5
+ else if ascii_dec ch "6" then Some 6
+ else if ascii_dec ch "7" then Some 7
+ else None)%N.
+
+Fixpoint pos_oct_app (p q:positive) : positive :=
+ match q with
+ | 1 => p~0~0~1
+ | 2 => p~0~1~0
+ | 3 => p~0~1~1
+ | 4 => p~1~0~0
+ | 5 => p~1~0~1
+ | 6 => p~1~1~0
+ | 7 => p~1~1~1
+ | q~0~0~0 => (pos_oct_app p q)~0~0~0
+ | q~0~0~1 => (pos_oct_app p q)~0~0~1
+ | q~0~1~0 => (pos_oct_app p q)~0~1~0
+ | q~0~1~1 => (pos_oct_app p q)~0~1~1
+ | q~1~0~0 => (pos_oct_app p q)~1~0~0
+ | q~1~0~1 => (pos_oct_app p q)~1~0~1
+ | q~1~1~0 => (pos_oct_app p q)~1~1~0
+ | q~1~1~1 => (pos_oct_app p q)~1~1~1
+ end.
+
+Module Raw.
+ Fixpoint of_pos (p : positive) (rest : string) : string
+ := match p with
+ | 1 => String "1" rest
+ | 2 => String "2" rest
+ | 3 => String "3" rest
+ | 4 => String "4" rest
+ | 5 => String "5" rest
+ | 6 => String "6" rest
+ | 7 => String "7" rest
+ | p'~0~0~0 => of_pos p' (String "0" rest)
+ | p'~0~0~1 => of_pos p' (String "1" rest)
+ | p'~0~1~0 => of_pos p' (String "2" rest)
+ | p'~0~1~1 => of_pos p' (String "3" rest)
+ | p'~1~0~0 => of_pos p' (String "4" rest)
+ | p'~1~0~1 => of_pos p' (String "5" rest)
+ | p'~1~1~0 => of_pos p' (String "6" rest)
+ | p'~1~1~1 => of_pos p' (String "7" rest)
+ end.
+
+ Fixpoint to_N (s : string) (rest : N)
+ : N
+ := match s with
+ | "" => rest
+ | String ch s'
+ => to_N
+ s'
+ match ascii_to_digit ch with
+ | Some v => N.add v (N.mul 8 rest)
+ | None => N0
+ end
+ end.
+
+ Fixpoint to_N_of_pos (p : positive) (rest : string) (base : N)
+ : to_N (of_pos p rest) base
+ = to_N rest match base with
+ | N0 => N.pos p
+ | Npos v => Npos (pos_oct_app v p)
+ end.
+ Proof.
+ do 3 try destruct p as [p|p|]; destruct base; try reflexivity;
+ cbn; rewrite to_N_of_pos; reflexivity.
+ Qed.
+End Raw.
+
+Definition of_pos (p : positive) : string
+ := String "0" (String "o" (Raw.of_pos p "")).
+Definition of_N (n : N) : string
+ := match n with
+ | N0 => "0o0"
+ | Npos p => of_pos p
+ end.
+Definition of_Z (z : Z) : string
+ := match z with
+ | Zneg p => String "-" (of_pos p)
+ | Z0 => "0o0"
+ | Zpos p => of_pos p
+ end.
+Definition of_nat (n : nat) : string
+ := of_N (N.of_nat n).
+
+Definition to_N (s : string) : N
+ := match s with
+ | String s0 (String so s)
+ => if ascii_dec s0 "0"
+ then if ascii_dec so "o"
+ then Raw.to_N s N0
+ else N0
+ else N0
+ | _ => N0
+ end.
+Definition to_pos (s : string) : positive
+ := match to_N s with
+ | N0 => 1
+ | Npos p => p
+ end.
+Definition to_Z (s : string) : Z
+ := let '(is_neg, n) := match s with
+ | String s0 s'
+ => if ascii_dec s0 "-"
+ then (true, to_N s')
+ else (false, to_N s)
+ | EmptyString => (false, to_N s)
+ end in
+ match n with
+ | N0 => Z0
+ | Npos p => if is_neg then Zneg p else Zpos p
+ end.
+Definition to_nat (s : string) : nat
+ := N.to_nat (to_N s).
+
+Lemma to_N_of_N (n : N)
+ : to_N (of_N n)
+ = n.
+Proof.
+ destruct n; [ reflexivity | apply Raw.to_N_of_pos ].
+Qed.
+
+Lemma to_Z_of_Z (z : Z)
+ : to_Z (of_Z z)
+ = z.
+Proof.
+ cbv [of_Z to_Z]; destruct z as [|z|z]; cbn;
+ try reflexivity;
+ rewrite Raw.to_N_of_pos; cbn; reflexivity.
+Qed.
+
+Lemma to_nat_of_nat (n : nat)
+ : to_nat (of_nat n)
+ = n.
+Proof.
+ cbv [to_nat of_nat];
+ rewrite to_N_of_N, Nnat.Nat2N.id; reflexivity.
+Qed.
+
+Lemma to_pos_of_pos (p : positive)
+ : to_pos (of_pos p)
+ = p.
+Proof.
+ cbv [of_pos to_pos to_N]; cbn;
+ rewrite Raw.to_N_of_pos; cbn; reflexivity.
+Qed.
+
+Example of_pos_1 : of_pos 1 = "0o1" := eq_refl.
+Example of_pos_2 : of_pos 2 = "0o2" := eq_refl.
+Example of_pos_3 : of_pos 3 = "0o3" := eq_refl.
+Example of_pos_7 : of_pos 7 = "0o7" := eq_refl.
+Example of_pos_8 : of_pos 8 = "0o10" := eq_refl.
+Example of_N_0 : of_N 0 = "0o0" := eq_refl.
+Example of_Z_0 : of_Z 0 = "0o0" := eq_refl.
+Example of_Z_m1 : of_Z (-1) = "-0o1" := eq_refl.
+Example of_nat_0 : of_nat 0 = "0o0" := eq_refl.
diff --git a/theories/Strings/String.v b/theories/Strings/String.v
index 2be6618ad6..be9a10c6dc 100644
--- a/theories/Strings/String.v
+++ b/theories/Strings/String.v
@@ -14,6 +14,7 @@
Require Import Arith.
Require Import Ascii.
+Require Import Bool.
Declare ML Module "string_syntax_plugin".
(** *** Definition of strings *)
@@ -35,6 +36,39 @@ Proof.
decide equality; apply ascii_dec.
Defined.
+Local Open Scope lazy_bool_scope.
+
+Fixpoint eqb s1 s2 : bool :=
+ match s1, s2 with
+ | EmptyString, EmptyString => true
+ | String c1 s1', String c2 s2' => Ascii.eqb c1 c2 &&& eqb s1' s2'
+ | _,_ => false
+ end.
+
+Infix "=?" := eqb : string_scope.
+
+Lemma eqb_spec s1 s2 : Bool.reflect (s1 = s2) (s1 =? s2)%string.
+Proof.
+ revert s2. induction s1; destruct s2; try (constructor; easy); simpl.
+ case Ascii.eqb_spec; simpl; [intros -> | constructor; now intros [= ]].
+ case IHs1; [intros ->; now constructor | constructor; now intros [= ]].
+Qed.
+
+Local Ltac t_eqb :=
+ repeat first [ congruence
+ | progress subst
+ | apply conj
+ | match goal with
+ | [ |- context[eqb ?x ?y] ] => destruct (eqb_spec x y)
+ end
+ | intro ].
+Lemma eqb_refl x : (x =? x)%string = true. Proof. t_eqb. Qed.
+Lemma eqb_sym x y : (x =? y)%string = (y =? x)%string. Proof. t_eqb. Qed.
+Lemma eqb_eq n m : (n =? m)%string = true <-> n = m. Proof. t_eqb. Qed.
+Lemma eqb_neq x y : (x =? y)%string = false <-> x <> y. Proof. t_eqb. Qed.
+Lemma eqb_compat: Morphisms.Proper (Morphisms.respectful eq (Morphisms.respectful eq eq)) eqb.
+Proof. t_eqb. Qed.
+
(** *** Concatenation of strings *)
Reserved Notation "x ++ y" (right associativity, at level 60).
diff --git a/theories/Structures/GenericMinMax.v b/theories/Structures/GenericMinMax.v
index 05edc6ccde..4d04667c01 100644
--- a/theories/Structures/GenericMinMax.v
+++ b/theories/Structures/GenericMinMax.v
@@ -83,7 +83,7 @@ End GenericMinMax.
Module MinMaxLogicalProperties (Import O:TotalOrder')(Import M:HasMinMax O).
Module Import Private_Tac := !MakeOrderTac O O.
-(** An alternative caracterisation of [max], equivalent to
+(** An alternative characterisation of [max], equivalent to
[max_l /\ max_r] *)
Lemma max_spec n m :
diff --git a/theories/Vectors/VectorDef.v b/theories/Vectors/VectorDef.v
index f6f3cafa21..ba3e411091 100644
--- a/theories/Vectors/VectorDef.v
+++ b/theories/Vectors/VectorDef.v
@@ -312,5 +312,6 @@ Notation "h :: t" := (h :: t) (at level 60, right associativity)
Notation "[ x ]" := (x :: []) : vector_scope.
Notation "[ x ; y ; .. ; z ]" := (cons _ x _ (cons _ y _ .. (cons _ z _ (nil _)) ..)) : vector_scope.
Notation "v [@ p ]" := (nth v p) (at level 1, format "v [@ p ]") : vector_scope.
+Infix "++" := append : vector_scope.
Open Scope vector_scope.
End VectorNotations.
diff --git a/tools/CoqMakefile.in b/tools/CoqMakefile.in
index 8e60d3932a..403ad61798 100644
--- a/tools/CoqMakefile.in
+++ b/tools/CoqMakefile.in
@@ -65,20 +65,20 @@ VERBOSE ?=
# Time the Coq process (set to non empty), and how (see default value)
TIMED?=
TIMECMD?=
-# Use /usr/bin/env time on linux, gtime on Mac OS
+# Use command time on linux, gtime on Mac OS
TIMEFMT?="$* (real: %e, user: %U, sys: %S, mem: %M ko)"
ifneq (,$(TIMED))
-ifeq (0,$(shell /usr/bin/env time -f $(TIMEFMT) true >/dev/null 2>/dev/null; echo $$?))
-STDTIME?=/usr/bin/env time -f $(TIMEFMT)
+ifeq (0,$(shell command time -f $(TIMEFMT) true >/dev/null 2>/dev/null; echo $$?))
+STDTIME?=command time -f $(TIMEFMT)
else
ifeq (0,$(shell gtime -f $(TIMEFMT) true >/dev/null 2>/dev/null; echo $$?))
STDTIME?=gtime -f $(TIMEFMT)
else
-STDTIME?=time
+STDTIME?=command time
endif
endif
else
-STDTIME?=/usr/bin/env time -f $(TIMEFMT)
+STDTIME?=command time -f $(TIMEFMT)
endif
# Coq binaries
@@ -86,7 +86,6 @@ COQC ?= "$(COQBIN)coqc"
COQTOP ?= "$(COQBIN)coqtop"
COQCHK ?= "$(COQBIN)coqchk"
COQDEP ?= "$(COQBIN)coqdep"
-GALLINA ?= "$(COQBIN)gallina"
COQDOC ?= "$(COQBIN)coqdoc"
COQMKFILE ?= "$(COQBIN)coq_makefile"
@@ -256,7 +255,6 @@ VO = vo
VOFILES = $(VFILES:.v=.$(VO))
GLOBFILES = $(VFILES:.v=.glob)
-GFILES = $(VFILES:.v=.g)
HTMLFILES = $(VFILES:.v=.html)
GHTMLFILES = $(VFILES:.v=.g.html)
BEAUTYFILES = $(addsuffix .beautified,$(VFILES))
@@ -345,19 +343,19 @@ make-pretty-timed make-pretty-timed-before make-pretty-timed-after::
print-pretty-timed::
$(HIDE)$(COQMAKE_ONE_TIME_FILE) $(TIME_OF_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES)
print-pretty-timed-diff::
- $(HIDE)$(COQMAKE_BOTH_TIME_FILES) --sort-by=$(TIMING_SORT_BY) $(TIME_OF_BUILD_BEFORE_FILE) $(TIME_OF_BUILD_AFTER_FILE) $(TIME_OF_PRETTY_BOTH_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES)
+ $(HIDE)$(COQMAKE_BOTH_TIME_FILES) --sort-by=$(TIMING_SORT_BY) $(TIME_OF_BUILD_AFTER_FILE) $(TIME_OF_BUILD_BEFORE_FILE) $(TIME_OF_PRETTY_BOTH_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES)
ifeq (,$(BEFORE))
print-pretty-single-time-diff::
- @echo 'Error: Usage: $(MAKE) print-pretty-single-time-diff BEFORE=path/to/file.v.before-timing AFTER=path/to/file.v.after-timing'
+ @echo 'Error: Usage: $(MAKE) print-pretty-single-time-diff AFTER=path/to/file.v.after-timing BEFORE=path/to/file.v.before-timing'
$(HIDE)false
else
ifeq (,$(AFTER))
print-pretty-single-time-diff::
- @echo 'Error: Usage: $(MAKE) print-pretty-single-time-diff BEFORE=path/to/file.v.before-timing AFTER=path/to/file.v.after-timing'
+ @echo 'Error: Usage: $(MAKE) print-pretty-single-time-diff AFTER=path/to/file.v.after-timing BEFORE=path/to/file.v.before-timing'
$(HIDE)false
else
print-pretty-single-time-diff::
- $(HIDE)$(COQMAKE_BOTH_SINGLE_TIMING_FILES) --sort-by=$(TIMING_SORT_BY) $(BEFORE) $(AFTER) $(TIME_OF_PRETTY_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES)
+ $(HIDE)$(COQMAKE_BOTH_SINGLE_TIMING_FILES) --sort-by=$(TIMING_SORT_BY) $(AFTER) $(BEFORE) $(TIME_OF_PRETTY_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES)
endif
endif
pretty-timed:
@@ -442,8 +440,6 @@ all-mli.tex: $(MLIFILES:.mli=.cmi)
$(HIDE)$(CAMLDOC) -latex \
-o $@ -m A $(CAMLDEBUG) $(CAMLDOCFLAGS) $(MLIFILES)
-gallina: $(GFILES)
-
all.ps: $(VFILES)
$(SHOW)'COQDOC -ps $(GAL)'
$(HIDE)$(COQDOC) \
@@ -564,7 +560,6 @@ clean::
$(HIDE)find . -name .coq-native -type d -empty -delete
$(HIDE)rm -f $(VOFILES)
$(HIDE)rm -f $(VOFILES:.vo=.vio)
- $(HIDE)rm -f $(GFILES)
$(HIDE)rm -f $(BEAUTYFILES) $(VFILES:=.old)
$(HIDE)rm -f all.ps all-gal.ps all.pdf all-gal.pdf all.glob all-mli.tex
$(HIDE)rm -f $(VFILES:.v=.glob)
@@ -683,10 +678,6 @@ $(BEAUTYFILES): %.v.beautified: %.v
$(SHOW)'BEAUTIFY $<'
$(HIDE)$(TIMER) $(COQC) $(COQDEBUG) $(COQFLAGS) $(COQLIBS) -beautify $<
-$(GFILES): %.g: %.v
- $(SHOW)'GALLINA $<'
- $(HIDE)$(GALLINA) $<
-
$(TEXFILES): %.tex: %.v
$(SHOW)'COQDOC -latex $<'
$(HIDE)$(COQDOC) $(COQDOCFLAGS) -latex $< -o $@
diff --git a/tools/TimeFileMaker.py b/tools/TimeFileMaker.py
index 0d24332f1e..8564aeff64 100644
--- a/tools/TimeFileMaker.py
+++ b/tools/TimeFileMaker.py
@@ -1,6 +1,9 @@
-#!/usr/bin/env python
from __future__ import with_statement
+from __future__ import division
+from __future__ import unicode_literals
+from __future__ import print_function
import os, sys, re
+from io import open
# This script parses the output of `make TIMED=1` into a dictionary
# mapping names of compiled files to the number of minutes and seconds
@@ -8,7 +11,7 @@ import os, sys, re
STRIP_REG = re.compile('^(coq/|contrib/|)(?:theories/|src/)?')
STRIP_REP = r'\1'
-INFINITY = '\xe2\x88\x9e'
+INFINITY = '\u221e'
def parse_args(argv, USAGE, HELP_STRING):
sort_by = 'auto'
@@ -27,7 +30,7 @@ def parse_args(argv, USAGE, HELP_STRING):
def reformat_time_string(time):
seconds, milliseconds = time.split('.')
seconds = int(seconds)
- minutes, seconds = int(seconds / 60), seconds % 60
+ minutes, seconds = divmod(seconds, 60)
return '%dm%02d.%ss' % (minutes, seconds, milliseconds)
def get_times(file_name):
@@ -40,7 +43,7 @@ def get_times(file_name):
if file_name == '-':
lines = sys.stdin.read()
else:
- with open(file_name, 'r') as f:
+ with open(file_name, 'r', encoding="utf-8") as f:
lines = f.read()
reg = re.compile(r'^([^\s]+) \([^\)]*?user: ([0-9\.]+)[^\)]*?\)\s*$', re.MULTILINE)
times = reg.findall(lines)
@@ -60,7 +63,7 @@ def get_single_file_times(file_name):
if file_name == '-':
lines = sys.stdin.read()
else:
- with open(file_name, 'r') as f:
+ with open(file_name, 'r', encoding="utf-8") as f:
lines = f.read()
reg = re.compile(r'^Chars ([0-9]+) - ([0-9]+) ([^ ]+) ([0-9\.]+) secs (.*)$', re.MULTILINE)
times = reg.findall(lines)
@@ -101,7 +104,7 @@ def from_seconds(seconds, signed=False):
'''
sign = ('-' if seconds < 0 else '+') if signed else ''
seconds = abs(seconds)
- minutes = int(seconds) / 60
+ minutes = int(seconds) // 60
seconds -= minutes * 60
full_seconds = int(seconds)
partial_seconds = int(100 * (seconds - full_seconds))
@@ -112,7 +115,8 @@ def sum_times(times, signed=False):
Takes the values of an output from get_times, parses the time
strings, and returns their sum, in the same string format.
'''
- return from_seconds(sum(map(to_seconds, times)), signed=signed)
+ # sort the times before summing because floating point addition is not associative
+ return from_seconds(sum(sorted(map(to_seconds, times))), signed=signed)
def format_percentage(num, signed=True):
sign = ('-' if num < 0 else '+') if signed else ''
@@ -141,20 +145,21 @@ def make_diff_table_string(left_times_dict, right_times_dict,
for name, lseconds, rseconds in prediff_times)
# update to sort by approximate difference, first
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))
+ get_key_diff_float = (lambda name: fix_sign_for_sorting(to_seconds(diff_times_dict[name]), descending=descending))
+ get_key_diff_absint = (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
+ get_key = get_key_diff_float
else: # sort_by == 'auto'
- get_key = (lambda name: (get_key_diff(name), get_key_abs(name)))
+ get_key = (lambda name: (get_key_diff_absint(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())
right_sum = sum_times(right_times_dict.values())
- left_sum_float = sum(map(to_seconds, left_times_dict.values()))
- right_sum_float = sum(map(to_seconds, right_times_dict.values()))
+ left_sum_float = sum(sorted(map(to_seconds, left_times_dict.values())))
+ right_sum_float = sum(sorted(map(to_seconds, right_times_dict.values())))
diff_sum = from_seconds(left_sum_float - right_sum_float, signed=True)
percent_diff_sum = (format_percentage((left_sum_float - right_sum_float) / right_sum_float)
if right_sum_float > 0 else 'N/A')
@@ -203,8 +208,12 @@ def make_table_string(times_dict,
def print_or_write_table(table, files):
if len(files) == 0 or '-' in files:
- print(table)
+ try:
+ binary_stdout = sys.stdout.buffer
+ except AttributeError:
+ binary_stdout = sys.stdout
+ print(table.encode("utf-8"), file=binary_stdout)
for file_name in files:
if file_name != '-':
- with open(file_name, 'w') as f:
+ with open(file_name, 'w', encoding="utf-8") as f:
f.write(table)
diff --git a/tools/coq-font-lock.el b/tools/coq-font-lock.el
deleted file mode 100644
index 068e640025..0000000000
--- a/tools/coq-font-lock.el
+++ /dev/null
@@ -1,137 +0,0 @@
-;; coq-font-lock.el --- Coq syntax highlighting for Emacs - compatibilty code
-;; Pierre Courtieu, may 2009
-;;
-;; Authors: Pierre Courtieu
-;; License: GPL (GNU GENERAL PUBLIC LICENSE)
-;; Maintainer: Pierre Courtieu <Pierre.Courtieu@cnam.fr>
-
-;; This is copy paste from ProofGeneral by David Aspinall
-;; <David.Aspinall@ed.ac.uk>. ProofGeneral is under GPL and Copyright
-;; (C) LFCS Edinburgh.
-
-
-;;; Commentary:
-;; This file contains the code necessary to coq-syntax.el and
-;; coq-db.el from ProofGeneral. It is also pocked from ProofGeneral.
-
-
-;;; History:
-;; First created from ProofGeneral may 28th 2009
-
-
-;;; Code:
-
-(setq coq-version-is-V8-1 t)
-(defun coq-build-regexp-list-from-db (db &optional filter)
- "Take a keyword database DB and return the list of regexps for font-lock.
-If non-nil Optional argument FILTER is a function applying to each line of DB.
-For each line if FILTER returns nil, then the keyword is not added to the
-regexp. See `coq-syntax-db' for DB structure."
- (let ((l db) (res ()))
- (while l
- (let* ((hd (car l)) (tl (cdr l)) ; hd is the first infos list
- (e1 (car hd)) (tl1 (cdr hd)) ; e1 = menu entry
- (e2 (car tl1)) (tl2 (cdr tl1)) ; e2 = abbreviation
- (e3 (car tl2)) (tl3 (cdr tl2)) ; e3 = completion
- (e4 (car-safe tl3)) (tl4 (cdr-safe tl3)) ; e4 = state changing
- (e5 (car-safe tl4)) (tl5 (cdr-safe tl4)) ; e5 = colorization string
- )
- ;; TODO delete doublons
- (when (and e5 (or (not filter) (funcall filter hd)))
- (setq res (nconc res (list e5)))) ; careful: nconc destructive!
- (setq l tl)))
- res
- ))
-(defun filter-state-preserving (l)
- ; checkdoc-params: (l)
- "Not documented."
- (not (nth 3 l))) ; fourth argument is nil --> state preserving command
-
-(defun filter-state-changing (l)
- ; checkdoc-params: (l)
- "Not documented."
- (nth 3 l)) ; fourth argument is nil --> state preserving command
-
-;; Generic font-lock
-
-(defvar proof-id "\\(\\w\\(\\w\\|\\s_\\)*\\)"
- "A regular expression for parsing identifiers.")
-
-;; For font-lock, we treat ,-separated identifiers as one identifier
-;; and refontify commata using \{proof-zap-commas}.
-
-(defun proof-anchor-regexp (e)
- "Anchor (\\`) and group the regexp E."
- (concat "\\`\\(" e "\\)"))
-
-(defun proof-ids (proof-id &optional sepregexp)
- "Generate a regular expression for separated lists of identifiers PROOF-ID.
-Default is comma separated, or SEPREGEXP if set."
- (concat proof-id "\\(\\s-*" (or sepregexp ",") "\\s-*"
- proof-id "\\)*"))
-
-(defun proof-ids-to-regexp (l)
- "Maps a non-empty list of tokens `L' to a regexp matching any element."
- (if (featurep 'xemacs)
- (mapconcat (lambda (s) (concat "\\_<" s "\\_>")) l "\\|") ;; old version
- (concat "\\_<\\(?:" (mapconcat 'identity l "\\|") "\\)\\_>")))
-
-;; TODO: get rid of this list. Does 'default work widely enough
-;; by now?
-(defconst pg-defface-window-systems
- '(x ;; bog standard
- mswindows ;; Windows
- w32 ;; Windows
- gtk ;; gtk emacs (obsolete?)
- mac ;; used by Aquamacs
- carbon ;; used by Carbon XEmacs
- ns ;; NeXTstep Emacs (Emacs.app)
- x-toolkit) ;; possible catch all (but probably not)
- "A list of possible values for variable `window-system'.
-If you are on a window system and your value of variable
-`window-system' is not listed here, you may not get the correct
-syntax colouring behaviour.")
-
-(defmacro proof-face-specs (bl bd ow)
- "Return a spec for `defface' with BL for light bg, BD for dark, OW o/w."
- `(append
- (apply 'append
- (mapcar
- (lambda (ty) (list
- (list (list (list 'type ty) '(class color)
- (list 'background 'light))
- (quote ,bl))
- (list (list (list 'type ty) '(class color)
- (list 'background 'dark))
- (quote ,bd))))
- pg-defface-window-systems))
- (list (list t (quote ,ow)))))
-
-;;A new face for tactics
-(defface coq-solve-tactics-face
- (proof-face-specs
- (:foreground "forestgreen" t) ; for bright backgrounds
- (:foreground "forestgreen" t) ; for dark backgrounds
- ()) ; for black and white
- "Face for names of closing tactics in proof scripts."
- :group 'proof-faces)
-
-;;A new face for tactics which fail when they don't kill the current goal
-(defface coq-solve-tactics-face
- (proof-face-specs
- (:foreground "red" t) ; for bright backgrounds
- (:foreground "red" t) ; for dark backgrounds
- ()) ; for black and white
- "Face for names of closing tactics in proof scripts."
- :group 'proof-faces)
-
-
-(defconst coq-solve-tactics-face 'coq-solve-tactics-face
- "Expression that evaluates to a face.
-Required so that 'proof-solve-tactics-face is a proper facename")
-
-(defconst proof-tactics-name-face 'coq-solve-tactics-face)
-(defconst proof-tacticals-name-face 'coq-solve-tactics-face)
-
-(provide 'coq-font-lock)
-;;; coq-font-lock.el ends here
diff --git a/tools/coq_makefile.ml b/tools/coq_makefile.ml
index 6f11ee3977..c3bdf656d1 100644
--- a/tools/coq_makefile.ml
+++ b/tools/coq_makefile.ml
@@ -31,8 +31,19 @@ let rec print_prefix_list sep = function
| x :: l -> print sep; print x; print_prefix_list sep l
| [] -> ()
-let usage_common () =
+let usage_coq_makefile () =
+ output_string stderr "Usage summary:\
+\n\
+\ncoq_makefile .... [file.v] ... [file.ml[i4]?] ... [file.ml{lib,pack}]\
+\n ... [any] ... [-extra[-phony] result dependencies command]\
+\n ... [-I dir] ... [-R physicalpath logicalpath]\
+\n ... [-Q physicalpath logicalpath] ... [VARIABLE = value]\
+\n ... [-arg opt] ... [-opt|-byte] [-no-install] [-f file] [-o file]\
+\n [-h] [--help]\
+\n";
output_string stderr "\
+\nFull list of options:\
+\n\
\n[file.v]: Coq file to be compiled\
\n[file.ml[i4]?]: Objective Caml file to be compiled\
\n[file.ml{lib,pack}]: ocamlbuild file that describes a Objective Caml\
@@ -61,25 +72,6 @@ let usage_common () =
\n[-install opt]: where opt is \"user\" to force install into user directory,\
\n \"none\" to build a makefile with no install target or\
\n \"global\" to force install in $COQLIB directory\
-\n"
-
-let usage_coq_project () =
- output_string stderr "Available arguments:";
- usage_common ();
- exit 1
-
-let usage_coq_makefile () =
- output_string stderr "Usage summary:\
-\n\
-\ncoq_makefile .... [file.v] ... [file.ml[i4]?] ... [file.ml{lib,pack}]\
-\n ... [any] ... [-extra[-phony] result dependencies command]\
-\n ... [-I dir] ... [-R physicalpath logicalpath]\
-\n ... [-Q physicalpath logicalpath] ... [VARIABLE = value]\
-\n ... [-arg opt] ... [-opt|-byte] [-no-install] [-f file] [-o file]\
-\n [-h] [--help]\
-\n";
- usage_common ();
- output_string stderr "\
\n[-f file]: take the contents of file as arguments\
\n[-o file]: output should go in file file (recommended)\
\n Output file outside the current directory is forbidden.\
@@ -218,7 +210,7 @@ let windrive s =
else ""
;;
-let generate_conf_coq_config oc args =
+let generate_conf_coq_config oc =
section oc "Coq configuration.";
let src_dirs = Coq_config.all_src_dirs in
Envars.print_config ~prefix_var_name:"COQMF_" oc src_dirs;
@@ -282,7 +274,7 @@ let generate_conf oc project args =
fprintf oc "# %s\n\n" (String.concat " " (List.map quote args));
generate_conf_files oc project;
generate_conf_includes oc project;
- generate_conf_coq_config oc args;
+ generate_conf_coq_config oc;
generate_conf_defs oc project;
generate_conf_doc oc project;
generate_conf_extra_target oc project.extra_targets;
@@ -405,7 +397,7 @@ let _ =
let project =
try cmdline_args_to_project ~curdir:Filename.current_dir_name args
- with Parsing_error s -> prerr_endline s; usage_coq_project () in
+ with Parsing_error s -> prerr_endline s; usage_coq_makefile () in
if only_destination <> None then begin
destination_of project (Option.get only_destination);
diff --git a/tools/coqdoc/index.ml b/tools/coqdoc/index.ml
index df493fdf7f..724d3838b0 100644
--- a/tools/coqdoc/index.ml
+++ b/tools/coqdoc/index.ml
@@ -77,7 +77,7 @@ let add_ref m loc m' sp id ty =
let find m l = Hashtbl.find reftable (m, l)
-let find_string m s = let (m,s,t) = Hashtbl.find byidtable s in Ref (m,s,t)
+let find_string s = let (m,s,t) = Hashtbl.find byidtable s in Ref (m,s,t)
(* Coq modules *)
@@ -185,7 +185,8 @@ let type_name = function
let prepare_entry s = function
| Notation ->
(* We decode the encoding done in Dumpglob.cook_notation of coqtop *)
- (* Encoded notations have the form section:sc:x_'++'_x where: *)
+ (* Encoded notations have the form section:entry:sc:x_'++'_x *)
+ (* where: *)
(* - the section, if any, ends with a "." *)
(* - the scope can be empty *)
(* - tokens are separated with "_" *)
@@ -202,10 +203,12 @@ let prepare_entry s = function
let err () = eprintf "Invalid notation in globalization file\n"; exit 1 in
let h = try String.index_from s 0 ':' with _ -> err () in
let i = try String.index_from s (h+1) ':' with _ -> err () in
- let sc = String.sub s (h+1) (i-h-1) in
- let ntn = Bytes.make (String.length s - i) ' ' in
+ let m = try String.index_from s (i+1) ':' with _ -> err () in
+ let entry = String.sub s (h+1) (i-h-1) in
+ let sc = String.sub s (i+1) (m-i-1) in
+ let ntn = Bytes.make (String.length s - m) ' ' in
let k = ref 0 in
- let j = ref (i+1) in
+ let j = ref (m+1) in
let quoted = ref false in
let l = String.length s - 1 in
while !j <= l do
@@ -227,7 +230,8 @@ let prepare_entry s = function
incr j
done;
let ntn = Bytes.sub_string ntn 0 !k in
- if sc = "" then ntn else ntn ^ " (" ^ sc ^ ")"
+ let ntn = if sc = "" then ntn else ntn ^ " (" ^ sc ^ ")" in
+ if entry = "" then ntn else entry ^ ":" ^ ntn
| _ ->
s
diff --git a/tools/coqdoc/index.mli b/tools/coqdoc/index.mli
index 5cd301389b..7c9aad67fc 100644
--- a/tools/coqdoc/index.mli
+++ b/tools/coqdoc/index.mli
@@ -41,7 +41,7 @@ type index_entry =
val find : coq_module -> loc -> index_entry
(* Find what data is referred to by some string in some coq module *)
-val find_string : coq_module -> string -> index_entry
+val find_string : string -> index_entry
val add_module : coq_module -> unit
diff --git a/tools/coqdoc/output.ml b/tools/coqdoc/output.ml
index d252270021..05bc6aea9b 100644
--- a/tools/coqdoc/output.ml
+++ b/tools/coqdoc/output.ml
@@ -76,7 +76,7 @@ let is_tactic =
[ "intro"; "intros"; "apply"; "rewrite"; "refine"; "case"; "clear"; "injection";
"elimtype"; "progress"; "setoid_rewrite"; "left"; "right"; "constructor";
"econstructor"; "decide equality"; "abstract"; "exists"; "cbv"; "simple destruct";
- "info"; "fourier"; "field"; "specialize"; "evar"; "solve"; "instanciate"; "info_auto"; "info_eauto";
+ "info"; "field"; "specialize"; "evar"; "solve"; "instanciate"; "info_auto"; "info_eauto";
"quote"; "eexact"; "autorewrite";
"destruct"; "destruction"; "destruct_call"; "dependent"; "elim"; "extensionality";
"f_equal"; "generalize"; "generalize_eqs"; "generalize_eqs_vars"; "induction"; "rename"; "move"; "omega";
@@ -431,7 +431,7 @@ module Latex = struct
else if !Cdglobals.interpolate && !in_doc (* always a var otherwise *)
then
try
- let tag = Index.find_string (get_module false) s in
+ let tag = Index.find_string s in
reference (translate s) tag
with _ -> Tokens.output_tagged_ident_string s
else Tokens.output_tagged_ident_string s
@@ -706,7 +706,7 @@ module Html = struct
else if is_keyword s then
printf "<span class=\"id\" title=\"keyword\">%s</span>" (translate s)
else if !Cdglobals.interpolate && !in_doc (* always a var otherwise *) then
- try reference (translate s) (Index.find_string (get_module false) s)
+ try reference (translate s) (Index.find_string s)
with Not_found -> Tokens.output_tagged_ident_string s
else
Tokens.output_tagged_ident_string s
diff --git a/tools/gallina-db.el b/tools/gallina-db.el
deleted file mode 100644
index 9664f69f8b..0000000000
--- a/tools/gallina-db.el
+++ /dev/null
@@ -1,240 +0,0 @@
-;;; gallina-db.el --- coq keywords database utility functions
-;;
-;; Author: Pierre Courtieu <courtieu@lri.fr>
-;; License: GPL (GNU GENERAL PUBLIC LICENSE)
-;;
-
-;;; We store all information on keywords (tactics or command) in big
-;; tables (ex: `coq-tactics-db') From there we get: menus including
-;; "smart" commands, completions for command coq-insert-...
-;; abbrev tables and font-lock keyword
-
-;;; real value defined below
-
-;;; Commentary:
-;;
-
-;;; Code:
-
-;(require 'proof-config) ; for proof-face-specs, a macro
-;(require 'holes)
-
-(defconst coq-syntax-db nil
- "Documentation-only variable, for coq keyword databases.
-Each element of a keyword database contains the definition of a \"form\", of the
-form:
-
-(MENUNAME ABBREV INSERT STATECH KWREG INSERT-FUN HIDE)
-
-MENUNAME is the name of form (or form variant) as it should appear in menus or
-completion lists.
-
-ABBREV is the abbreviation for completion via \\[expand-abbrev].
-
-INSERT is the complete text of the form, which may contain holes denoted by
-\"#\" or \"@{xxx}\".
-
-If non-nil the optional STATECH specifies that the command is not state
-preserving for coq.
-
-If non-nil the optional KWREG is the regexp to colorize correponding to the
-keyword. ex: \"simple\\\\s-+destruct\" (\\\\s-+ meaning \"one or more spaces\").
-*WARNING*: A regexp longer than another one should be put FIRST. For example:
-
- (\"Module Type\" ... ... t \"Module\\s-+Type\")
- (\"Module\" ... ... t \"Module\")
-
-Is ok because the longer regexp is recognized first.
-
-If non-nil the optional INSERT-FUN is the function to be called when inserting
-the form (instead of inserting INSERT, except when using \\[expand-abbrev]). This
-allows writing functions asking for more information to assist the user.
-
-If non-nil the optional HIDE specifies that this form should not appear in the
-menu but only in interactive completions.
-
-Example of what could be in your emacs init file:
-
-(defvar coq-user-tactics-db
- '(
- (\"mytac\" \"mt\" \"mytac # #\" t \"mytac\")
- (\"myassert by\" \"massb\" \"myassert ( # : # ) by #\" t \"assert\")
- ))
-
-Explanation of the first line: the tactic menu entry mytac, abbreviated by mt,
-will insert \"mytac # #\" where #s are holes to fill, and \"mytac\" becomes a
-new keyword to colorize." )
-
-(defun coq-insert-from-db (db prompt)
- "Ask for a keyword, with completion on keyword database DB and insert.
-Insert corresponding string with holes at point. If an insertion function is
-present for the keyword, call it instead. see `coq-syntax-db' for DB
-structure."
- (let* ((tac (completing-read (concat prompt " (tab for completion) : ")
- db nil nil))
- (infos (cddr (assoc tac db)))
- (s (car infos)) ; completion to insert
- (f (car-safe (cdr-safe (cdr-safe (cdr infos))))) ; insertion function
- (pt (point)))
- (if f (funcall f) ; call f if present
- (insert (or s tac)) ; insert completion and indent otherwise
- (holes-replace-string-by-holes-backward-jump pt)
- (indent-according-to-mode))))
-
-
-
-(defun coq-build-regexp-list-from-db (db &optional filter)
- "Take a keyword database DB and return the list of regexps for font-lock.
-If non-nil Optional argument FILTER is a function applying to each line of DB.
-For each line if FILTER returns nil, then the keyword is not added to the
-regexp. See `coq-syntax-db' for DB structure."
- (let ((l db) (res ()))
- (while l
- (let* ((hd (car l)) (tl (cdr l)) ; hd is the first infos list
- (e1 (car hd)) (tl1 (cdr hd)) ; e1 = menu entry
- (e2 (car tl1)) (tl2 (cdr tl1)) ; e2 = abbreviation
- (e3 (car tl2)) (tl3 (cdr tl2)) ; e3 = completion
- (e4 (car-safe tl3)) (tl4 (cdr-safe tl3)) ; e4 = state changing
- (e5 (car-safe tl4)) (tl5 (cdr-safe tl4)) ; e5 = colorization string
- )
- ;; TODO delete doublons
- (when (and e5 (or (not filter) (funcall filter hd)))
- (setq res (nconc res (list e5)))) ; careful: nconc destructive!
- (setq l tl)))
- res
- ))
-
-;; Computes the max length of strings in a list
-(defun max-length-db (db)
- "Return the length of the longest first element (menu label) of DB.
-See `coq-syntax-db' for DB structure."
- (let ((l db) (res 0))
- (while l
- (let ((lgth (length (car (car l)))))
- (setq res (max lgth res))
- (setq l (cdr l))))
- res))
-
-
-
-(defun coq-build-menu-from-db-internal (db lgth menuwidth)
- "Take a keyword database DB and return one insertion submenu.
-Argument LGTH is the max size of the submenu. Argument MENUWIDTH is the width
-of the largest line in the menu (without abbrev and shortcut specifications).
-Used by `coq-build-menu-from-db', which you should probably use instead. See
-`coq-syntax-db' for DB structure."
- (let ((l db) (res ()) (size lgth)
- (keybind-abbrev (substitute-command-keys " \\[expand-abbrev]")))
- (while (and l (> size 0))
- (let* ((hd (car l))(tl (cdr l)) ; hd is a list of length 3 or 4
- (e1 (car hd)) (tl1 (cdr hd)) ; e1 = menu entry
- (e2 (car tl1)) (tl2 (cdr tl1)) ; e2 = abbreviation
- (e3 (car tl2)) (tl3 (cdr tl2)) ; e3 = completion
- (e4 (car-safe tl3)) (tl4 (cdr-safe tl3)) ; e4 = state changing
- (e5 (car-safe tl4)) (tl5 (cdr-safe tl4)) ; e5 = colorization string
- (e6 (car-safe tl5)) ; e6 = function for smart insertion
- (e7 (car-safe (cdr-safe tl5))) ; e7 = if non-nil : hide in menu
- (entry-with (max (- menuwidth (length e1)) 0))
- (spaces (make-string entry-with ? ))
- ;;(restofmenu (coq-build-menu-from-db-internal tl (- size 1) menuwidth))
- )
- (when (not e7) ;; if not hidden
- (let ((menu-entry
- (vector
- ;; menu entry label
- (concat e1 (if (not e2) "" (concat spaces "(" e2 keybind-abbrev ")")))
- ;;insertion function if present otherwise insert completion
- (if e6 e6 `(holes-insert-and-expand ,e3))
- t)))
- (setq res (nconc res (list menu-entry)))));; append *in place*
- (setq l tl)
- (setq size (- size 1))))
- res))
-
-
-(defun coq-build-title-menu (db size)
- "Build a title for the first submenu of DB, of size SIZE.
-Return the string made of the first and the SIZE nth first element of DB,
-separated by \"...\". Used by `coq-build-menu-from-db'. See `coq-syntax-db'
-for DB structure."
- (concat (car-safe (car-safe db))
- " ... "
- (car-safe (car-safe (nthcdr (- size 1) db)))))
-
-(defun coq-sort-menu-entries (menu)
- (sort menu
- (lambda (x y) (string<
- (downcase (elt x 0))
- (downcase (elt y 0))))))
-
-(defun coq-build-menu-from-db (db &optional size)
- "Take a keyword database DB and return a list of insertion menus for them.
-Submenus contain SIZE entries (default 30). See `coq-syntax-db' for DB
-structure."
- ;; sort is destructive for the list, so copy list before sorting
- (let* ((l (coq-sort-menu-entries (copy-list db))) (res ())
- (wdth (+ 2 (max-length-db db)))
- (sz (or size 30)) (lgth (length l)))
- (while l
- (if (<= lgth sz)
- (setq res ;; careful: nconc destructive!
- (nconc res (list (cons
- (coq-build-title-menu l lgth)
- (coq-build-menu-from-db-internal l lgth wdth)))))
- (setq res ; careful: nconc destructive!
- (nconc res (list (cons
- (coq-build-title-menu l sz)
- (coq-build-menu-from-db-internal l sz wdth))))))
- (setq l (nthcdr sz l))
- (setq lgth (length l)))
- res))
-
-(defun coq-build-abbrev-table-from-db (db)
- "Take a keyword database DB and return an abbrev table.
-See `coq-syntax-db' for DB structure."
- (let ((l db) (res ()))
- (while l
- (let* ((hd (car l))(tl (cdr l)) ; hd is a list of length 3 or 4
- (e1 (car hd)) (tl1 (cdr hd)) ; e1 = menu entry
- (e2 (car tl1)) (tl2 (cdr tl1)) ; e2 = abbreviation
- (e3 (car tl2)) (tl3 (cdr tl2)) ; e3 = completion
- )
- ;; careful: nconc destructive!
- (when e2
- (setq res (nconc res (list `(,e2 ,e3 holes-abbrev-complete)))))
- (setq l tl)))
- res))
-
-
-(defun filter-state-preserving (l)
- ; checkdoc-params: (l)
- "Not documented."
- (not (nth 3 l))) ; fourth argument is nil --> state preserving command
-
-(defun filter-state-changing (l)
- ; checkdoc-params: (l)
- "Not documented."
- (nth 3 l)) ; fourth argument is nil --> state preserving command
-
-(defconst coq-solve-tactics-face 'coq-solve-tactics-face
- "Expression that evaluates to a face.
-Required so that 'proof-solve-tactics-face is a proper facename")
-
-
-;;A new face for tactics which fail when they don't kill the current goal
-(defface coq-solve-tactics-face
- '((t (:background "red")))
- "Face for names of closing tactics in proof scripts."
- :group 'proof-faces)
-
-
-
-
-
-(provide 'gallina-db)
-
-;;; gallina-db.el ends here
-
-;** Local Variables: ***
-;** fill-column: 80 ***
-;** End: ***
diff --git a/tools/gallina-syntax.el b/tools/gallina-syntax.el
deleted file mode 100644
index 7c59fb6ae8..0000000000
--- a/tools/gallina-syntax.el
+++ /dev/null
@@ -1,979 +0,0 @@
-;; gallina-syntax.el Font lock expressions for Coq
-;; Copyright (C) 1997-2007 LFCS Edinburgh.
-;; Authors: Thomas Kleymann, Healfdene Goguen, Pierre Courtieu
-;; License: GPL (GNU GENERAL PUBLIC LICENSE)
-;; Maintainer: Pierre Courtieu <courtieu@lri.fr>
-
-;; gallina-syntax.el,v 9.9 2008/07/21 15:14:58 pier Exp
-
-;(require 'proof-syntax)
-;(require 'proof-utils) ; proof-locate-executable
-(require 'gallina-db)
-
-
-
- ;;; keyword databases
-
-
-(defcustom coq-user-tactics-db nil
- "User defined tactic information. See `coq-syntax-db' for
- syntax. It is not necessary to add your own tactics here (it is not
- needed by the synchronizing/backtracking system). You may however do
- so for the following reasons:
-
- 1 your tactics will be colorized by font-lock
-
- 2 your tactics will be added to the menu and to completion when
- calling \\[coq-insert-tactic]
-
- 3 you may define an abbreviation for your tactic."
-
- :type '(repeat sexp)
- :group 'coq)
-
-
-(defcustom coq-user-commands-db nil
- "User defined command information. See `coq-syntax-db' for
- syntax. It is not necessary to add your own commands here (it is not
- needed by the synchronizing/backtracking system). You may however do
- so for the following reasons:
-
- 1 your commands will be colorized by font-lock
-
- 2 your commands will be added to the menu and to completion when
- calling \\[coq-insert-command]
-
- 3 you may define an abbreviation for your command."
-
- :type '(repeat sexp)
- :group 'coq)
-
-(defcustom coq-user-tacticals-db nil
- "User defined tactical information. See `coq-syntax-db' for
- syntax. It is not necessary to add your own commands here (it is not
- needed by the synchronizing/backtracking system). You may however do
- so for the following reasons:
-
- 1 your commands will be colorized by font-lock
-
- 2 your commands will be added to the menu and to completion when
- calling \\[coq-insert-command]
-
- 3 you may define an abbreviation for your command."
-
- :type '(repeat sexp)
- :group 'coq)
-
-(defcustom coq-user-solve-tactics-db nil
- "User defined closing tactics. See `coq-syntax-db' for
- syntax. It is not necessary to add your own commands here (it is not
- needed by the synchronizing/backtracking system). You may however do
- so for the following reasons:
-
- 1 your commands will be colorized by font-lock
-
- 2 your commands will be added to the menu and to completion when
- calling \\[coq-insert-command]
-
- 3 you may define an abbreviation for your command."
-
- :type '(repeat sexp)
- :group 'coq)
-
-
-
-(defcustom coq-user-reserved-db nil
- "User defined reserved keywords information. See `coq-syntax-db' for
- syntax. It is not necessary to add your own commands here (it is not
- needed by the synchronizing/backtracking system). You may however do
- so for the following reasons:
-
- 1 your commands will be colorized by font-lock
-
- 2 your commands will be added to the menu and to completion when
- calling \\[coq-insert-command]
-
- 3 you may define an abbreviation for your command."
-
- :type '(repeat sexp)
- :group 'coq)
-
-
-
-(defvar coq-tactics-db
- (append
- coq-user-tactics-db
- '(
- ("absurd " "abs" "absurd " t "absurd")
- ("apply" "ap" "apply " t "apply")
- ("assert by" "assb" "assert ( # : # ) by #" t "assert")
- ("assert" "ass" "assert ( # : # )" t)
- ;; ("assumption" "as" "assumption" t "assumption")
- ("auto with arith" "awa" "auto with arith" t)
- ("auto with" "aw" "auto with @{db}" t)
- ("auto" "a" "auto" t "auto")
- ("autorewrite with in using" "arwiu" "autorewrite with @{db,db...} in @{hyp} using @{tac}" t)
- ("autorewrite with in" "arwi" "autorewrite with @{db,db...} in @{hyp}" t)
- ("autorewrite with using" "arwu" "autorewrite with @{db,db...} using @{tac}" t)
- ("autorewrite with" "ar" "autorewrite with @{db,db...}" t "autorewrite")
- ("case" "c" "case " t "case")
- ("cbv" "cbv" "cbv beta [#] delta iota zeta" t "cbv")
- ("change in" "chi" "change # in #" t)
- ("change with in" "chwi" "change # with # in #" t)
- ("change with" "chw" "change # with" t)
- ("change" "ch" "change " t "change")
- ("clear" "cl" "clear" t "clear")
- ("clearbody" "cl" "clearbody" t "clearbody")
- ("cofix" "cof" "cofix" t "cofix")
- ("coinduction" "coind" "coinduction" t "coinduction")
- ("compare" "cmpa" "compare # #" t "compare")
- ("compute" "cmpu" "compute" t "compute")
- ;; ("congruence" "cong" "congruence" t "congruence")
- ("constructor" "cons" "constructor" t "constructor")
- ;; ("contradiction" "contr" "contradiction" t "contradiction")
- ("cut" "cut" "cut" t "cut")
- ("cutrewrite" "cutr" "cutrewrite -> # = #" t "cutrewrite")
- ;; ("decide equality" "deg" "decide equality" t "decide\\s-+equality")
- ("decompose record" "decr" "decompose record #" t "decompose\\s-+record")
- ("decompose sum" "decs" "decompose sum #" t "decompose\\s-+sum")
- ("decompose" "dec" "decompose [#] #" t "decompose")
- ("dependent inversion" "depinv" "dependent inversion" t "dependent\\s-+inversion")
- ("dependent inversion with" "depinvw" "dependent inversion # with #" t)
- ("dependent inversion_clear" "depinvc" "dependent inversion_clear" t "dependent\\s-+inversion_clear")
- ("dependent inversion_clear with" "depinvw" "dependent inversion_clear # with #" t)
- ("dependent rewrite ->" "depr" "dependent rewrite -> @{id}" t "dependent\\s-+rewrite")
- ("dependent rewrite <-" "depr<" "dependent rewrite <- @{id}" t)
- ("destruct as" "desa" "destruct # as #" t)
- ("destruct using" "desu" "destruct # using #" t)
- ("destruct" "des" "destruct " t "destruct")
- ;; ("discriminate" "dis" "discriminate" t "discriminate")
- ("discrR" "discrR" "discrR" t "discrR")
- ("double induction" "dind" "double induction # #" t "double\\s-+induction")
- ("eapply" "eap" "eapply #" t "eapply")
- ("eauto with arith" "eawa" "eauto with arith" t)
- ("eauto with" "eaw" "eauto with @{db}" t)
- ("eauto" "ea" "eauto" t "eauto")
- ("econstructor" "econs" "econstructor" t "econstructor")
- ("eexists" "eex" "eexists" t "eexists")
- ("eleft" "eleft" "eleft" t "eleft")
- ("elim using" "elu" "elim # using #" t)
- ("elim" "e" "elim #" t "elim")
- ("elimtype" "elt" "elimtype" "elimtype")
- ("eright" "erig" "eright" "eright")
- ("esplit" "esp" "esplit" t "esplit")
- ;; ("exact" "exa" "exact" t "exact")
- ("exists" "ex" "exists #" t "exists")
- ;; ("fail" "fa" "fail" nil)
- ;; ("field" "field" "field" t "field")
- ("firstorder" "fsto" "firstorder" t "firstorder")
- ("firstorder with" "fsto" "firstorder with #" t)
- ("firstorder with using" "fsto" "firstorder # with #" t)
- ("fold" "fold" "fold #" t "fold")
- ;; ("fourier" "four" "fourier" t "fourier")
- ("functional induction" "fi" "functional induction @{f} @{args}" t "functional\\s-+induction")
- ("generalize dependent" "gd" "generalize dependent #" t "generalize\\s-+dependent")
- ("generalize" "g" "generalize #" t "generalize")
- ("hnf" "hnf" "hnf" t "hnf")
- ("idtac" "id" "idtac" nil "idtac") ; also in tacticals with abbrev id
- ("idtac \"" "id\"" "idtac \"#\"") ; also in tacticals
- ("induction" "ind" "induction #" t "induction")
- ("induction using" "indu" "induction # using #" t)
- ("injection" "inj" "injection #" t "injection")
- ("instantiate" "inst" "instantiate" t "instantiate")
- ("intro" "i" "intro" t "intro")
- ("intro after" "ia" "intro # after #" t)
- ("intros" "is" "intros #" t "intros")
- ("intros! (guess names)" nil "intros #" nil nil coq-insert-intros)
- ("intros until" "isu" "intros until #" t)
- ("intuition" "intu" "intuition #" t "intuition")
- ("inversion" "inv" "inversion #" t "inversion")
- ("inversion in" "invi" "inversion # in #" t)
- ("inversion using" "invu" "inversion # using #" t)
- ("inversion using in" "invui" "inversion # using # in #" t)
- ("inversion_clear" "invcl" "inversion_clear" t "inversion_clear")
- ("lapply" "lap" "lapply" t "lapply")
- ("lazy" "lazy" "lazy beta [#] delta iota zeta" t "lazy")
- ("left" "left" "left" t "left")
- ("linear" "lin" "linear" t "linear")
- ("load" "load" "load" t "load")
- ("move after" "mov" "move # after #" t "move")
- ("omega" "o" "omega" t "omega")
- ("pattern" "pat" "pattern" t "pattern")
- ("pattern(s)" "pats" "pattern # , #" t)
- ("pattern at" "pata" "pattern # at #" t)
- ("pose" "po" "pose ( # := # )" t "pose")
- ("prolog" "prol" "prolog" t "prolog")
- ("quote" "quote" "quote" t "quote")
- ("quote []" "quote2" "quote # [#]" t)
- ("red" "red" "red" t "red")
- ("refine" "ref" "refine" t "refine")
- ;; ("reflexivity" "refl" "reflexivity #" t "reflexivity")
- ("rename into" "ren" "rename # into #" t "rename")
- ("replace with" "rep" "replace # with #" t "replace")
- ("replace with in" "repi" "replace # with # in #" t)
- ("rewrite <- in" "ri<" "rewrite <- # in #" t)
- ("rewrite <-" "r<" "rewrite <- #" t)
- ("rewrite in" "ri" "rewrite # in #" t)
- ("rewrite" "r" "rewrite #" t "rewrite")
- ("right" "rig" "right" t "right")
- ;; ("ring" "ring" "ring #" t "ring")
- ("set in * |-" "seth" "set ( # := #) in * |-" t)
- ("set in *" "set*" "set ( # := #) in *" t)
- ("set in |- *" "setg" "set ( # := #) in |- *" t)
- ("set in" "seti" "set ( # := #) in #" t)
- ("set" "set" "set ( # := #)" t "set")
- ("setoid_replace with" "strep2" "setoid_replace # with #" t "setoid_replace")
- ("setoid replace with" "strep" "setoid replace # with #" t "setoid\\s-+replace")
- ("setoid_rewrite" "strew" "setoid_rewrite #" t "setoid_rewrite")
- ("setoid rewrite" "strew" "setoid rewrite #" t "setoid\\s-+rewrite")
- ("simpl" "s" "simpl" t "simpl")
- ("simpl" "sa" "simpl # at #" t)
- ("simple destruct" "sdes" "simple destruct" t "simple\\s-+destruct")
- ("simple inversion" "sinv" "simple inversion" t "simple\\s-+inversion")
- ("simple induction" "sind" "simple induction" t "simple\\s-+induction")
- ("simplify_eq" "simeq" "simplify_eq @{hyp}" t "simplify_eq")
- ("specialize" "spec" "specialize" t "specialize")
- ("split" "sp" "split" t "split")
- ("split_Rabs" "spra" "splitRabs" t "split_Rabs")
- ("split_Rmult" "sprm" "splitRmult" t "split_Rmult")
- ("stepl" "stl" "stepl #" t "stepl")
- ("stepl by" "stlb" "stepl # by #" t)
- ("stepr" "str" "stepr #" t "stepr")
- ("stepr by" "strb" "stepr # by #" t)
- ("subst" "su" "subst #" t "subst")
- ("symmetry" "sy" "symmetry" t "symmetry")
- ("symmetry in" "syi" "symmetry in #" t)
- ;; ("tauto" "ta" "tauto" t "tauto")
- ("transitivity" "trans" "transitivity #" t "transitivity")
- ("trivial" "t" "trivial" t "trivial")
- ("trivial with" "tw" "trivial with @{db}" t)
- ("unfold" "u" "unfold #" t "unfold")
- ("unfold(s)" "us" "unfold # , #" t)
- ("unfold in" "unfi" "unfold # in #" t)
- ("unfold at" "unfa" "unfold # at #" t)
- ))
- "Coq tactics information list. See `coq-syntax-db' for syntax. "
- )
-
-(defvar coq-solve-tactics-db
- (append
- coq-user-solve-tactics-db
- '(
- ("assumption" "as" "assumption" t "assumption")
- ("by" "by" "by #" t "by")
- ("congruence" "cong" "congruence" t "congruence")
- ("contradiction" "contr" "contradiction" t "contradiction")
- ("decide equality" "deg" "decide equality" t "decide\\s-+equality")
- ("discriminate" "dis" "discriminate" t "discriminate")
- ("exact" "exa" "exact" t "exact")
- ("fourier" "four" "fourier" t "fourier")
- ("fail" "fa" "fail" nil)
- ("field" "field" "field" t "field")
- ("omega" "o" "omega" t "omega")
- ("reflexivity" "refl" "reflexivity #" t "reflexivity")
- ("ring" "ring" "ring #" t "ring")
- ("solve" nil "solve [ # | # ]" nil "solve")
- ("tauto" "ta" "tauto" t "tauto")
- ))
- "Coq tactic(al)s that solve a subgoal."
- )
-
-
-(defvar coq-tacticals-db
- (append
- coq-user-tacticals-db
- '(
- ("info" nil "info #" nil "info")
- ("first" nil "first [ # | # ]" nil "first")
- ("abstract" nil "abstract @{tac} using @{name}." nil "abstract")
- ("do" nil "do @{num} @{tac}" nil "do")
- ("idtac" nil "idtac") ; also in tactics
- ; ("idtac \"" nil "idtac \"#\"") ; also in tactics
- ("fail" "fa" "fail" nil "fail")
- ; ("fail \"" "fa\"" "fail" nil) ;
- ; ("orelse" nil "orelse #" t "orelse")
- ("repeat" nil "repeat #" nil "repeat")
- ("try" nil "try #" nil "try")
- ("progress" nil "progress #" nil "progress")
- ("|" nil "[ # | # ]" nil)
- ("||" nil "# || #" nil)
- ))
- "Coq tacticals information list. See `coq-syntax-db' for syntax.")
-
-
-
-
-(defvar coq-decl-db
- '(
- ("Axiom" "ax" "Axiom # : #" t "Axiom")
- ("Hint Constructors" "hc" "Hint Constructors # : #." t "Hint\\s-+Constructors")
- ("Hint Extern" "he" "Hint Extern @{cost} @{pat} => @{tac} : @{db}." t "Hint\\s-+Extern")
- ("Hint Immediate" "hi" "Hint Immediate # : @{db}." t "Hint\\s-+Immediate")
- ("Hint Resolve" "hr" "Hint Resolve # : @{db}." t "Hint\\s-+Resolve")
- ("Hint Rewrite ->" "hrw" "Hint Rewrite -> @{t1,t2...} using @{tac} : @{db}." t "Hint\\s-+Rewrite")
- ("Hint Rewrite <-" "hrw" "Hint Rewrite <- @{t1,t2...} using @{tac} : @{db}." t )
- ("Hint Unfold" "hu" "Hint Unfold # : #." t "Hint\\s-+Unfold")
- ("Hypothesis" "hyp" "Hypothesis #: #" t "Hypothesis")
- ("Hypotheses" "hyp" "Hypotheses #: #" t "Hypotheses")
- ("Parameter" "par" "Parameter #: #" t "Parameter")
- ("Parameters" "par" "Parameter #: #" t "Parameters")
- ("Conjecture" "conj" "Conjecture #: #." t "Conjecture")
- ("Variable" "v" "Variable #: #." t "Variable")
- ("Variables" "vs" "Variables # , #: #." t "Variables")
- ("Coercion" "coerc" "Coercion @{id} : @{typ1} >-> @{typ2}." t "Coercion")
- )
- "Coq declaration keywords information list. See `coq-syntax-db' for syntax."
- )
-
-(defvar coq-defn-db
- '(
- ("CoFixpoint" "cfix" "CoFixpoint # (#:#) : # :=\n#." t "CoFixpoint")
- ("CoInductive" "coindv" "CoInductive # : # :=\n|# : #." t "CoInductive")
- ("Declare Module : :=" "dm" "Declare Module # : # := #." t "Declare\\s-+Module")
- ("Declare Module <: :=" "dm2" "Declare Module # <: # := #." t);; careful
- ("Declare Module Import : :=" "dmi" "Declare Module # : # := #." t)
- ("Declare Module Import <: :=" "dmi2" "Declare Module # <: # := #." t);; careful
- ("Declare Module Export : :=" "dme" "Declare Module # : # := #." t)
- ("Declare Module Export <: :=" "dme2" "Declare Module # <: # := #." t);; careful
- ("Definition" "def" "Definition #:# := #." t "Definition");; careful
- ("Definition (2 args)" "def2" "Definition # (# : #) (# : #):# := #." t)
- ("Definition (3 args)" "def3" "Definition # (# : #) (# : #) (# : #):# := #." t)
- ("Definition (4 args)" "def4" "Definition # (# : #) (# : #) (# : #) (# : #):# := #." t)
- ("Program Definition" "pdef" "Program Definition #:# := #." t "Program\\s-+Definition");; careful ?
- ("Program Definition (2 args)" "pdef2" "Program Definition # (# : #) (# : #):# := #." t)
- ("Program Definition (3 args)" "pdef3" "Program Definition # (# : #) (# : #) (# : #):# := #." t)
- ("Program Definition (4 args)" "pdef4" "Program Definition # (# : #) (# : #) (# : #) (# : #):# := #." t)
- ("Derive Inversion" nil "Derive Inversion @{id} with # Sort #." t "Derive\\s-+Inversion")
- ("Derive Dependent Inversion" nil "Derive Dependent Inversion @{id} with # Sort #." t "Derive\\s-+Dependent\\s-+Inversion")
- ("Derive Inversion_clear" nil "Derive Inversion_clear @{id} with # Sort #." t)
- ("Fixpoint" "fix" "Fixpoint # (#:#) {struct @{arg}} : # :=\n#." t "Fixpoint")
- ("Program Fixpoint" "pfix" "Program Fixpoint # (#:#) {struct @{arg}} : # :=\n#." t "Program\\s-+Fixpoint")
- ("Program Fixpoint measure" "pfixm" "Program Fixpoint # (#:#) {measure @{arg} @{f}} : # :=\n#." t)
- ("Program Fixpoint wf" "pfixwf" "Program Fixpoint # (#:#) {wf @{arg} @{f}} : # :=\n#." t)
- ("Function" "func" "Function # (#:#) {struct @{arg}} : # :=\n#." t "Function")
- ("Function measure" "funcm" "Function # (#:#) {measure @{f} @{arg}} : # :=\n#." t)
- ("Function wf" "func wf" "Function # (#:#) {wf @{R} @{arg}} : # :=\n#." t)
- ("Functional Scheme with" "fsw" "Functional Scheme @{name} := Induction for @{fun} with @{mutfuns}." t )
- ("Functional Scheme" "fs" "Functional Scheme @{name} := Induction for @{fun}." t "Functional\\s-+Scheme")
- ("Inductive" "indv" "Inductive # : # := # : #." t "Inductive")
- ("Inductive (2 args)" "indv2" "Inductive # : # :=\n| # : #\n| # : #." t )
- ("Inductive (3 args)" "indv3" "Inductive # : # :=\n| # : #\n| # : #\n| # : #." t )
- ("Inductive (4 args)" "indv4" "Inductive # : # :=\n| # : #\n| # : #\n| # : #\n| # : #." t )
- ("Inductive (5 args)" "indv5" "Inductive # : # :=\n| # : #\n| # : #\n| # : #\n| # : #\n| # : #." t )
- ("Variant" "indv" "Variant # : # := # : #." t "Variant")
- ("Variant (2 args)" "indv2" "Variant # : # :=\n| # : #\n| # : #." t )
- ("Variant (3 args)" "indv3" "Variant # : # :=\n| # : #\n| # : #\n| # : #." t )
- ("Variant (4 args)" "indv4" "Variant # : # :=\n| # : #\n| # : #\n| # : #\n| # : #." t )
- ("Variant (5 args)" "indv5" "Variant # : # :=\n| # : #\n| # : #\n| # : #\n| # : #\n| # : #." t )
- ("Let" "Let" "Let # : # := #." t "Let")
- ("Ltac" "ltac" "Ltac # := #" t "Ltac")
- ("Module :=" "mo" "Module # : # := #." t ) ; careful
- ("Module <: :=" "mo2" "Module # <: # := #." t ) ; careful
- ("Module Import :=" "moi" "Module Import # : # := #." t ) ; careful
- ("Module Import <: :=" "moi2" "Module Import # <: # := #." t ) ; careful
- ("Module Export :=" "moe" "Module Export # : # := #." t ) ; careful
- ("Module Export <: :=" "moe2" "Module Export# <: # := #." t ) ; careful
- ("Record" "rec" "Record # : # := {\n# : #;\n# : # }" t "Record")
- ("Scheme" "sc" "Scheme @{name} := #." t "Scheme")
- ("Scheme Induction" "sci" "Scheme @{name} := Induction for # Sort #." t)
- ("Scheme Minimality" "scm" "Scheme @{name} := Minimality for # Sort #." t)
- ("Structure" "str" "Structure # : # := {\n# : #;\n# : # }" t "Structure")
- )
- "Coq definition keywords information list. See `coq-syntax-db' for syntax. "
- )
-
-;; modules and section are indented like goal starters
-(defvar coq-goal-starters-db
- '(
- ("Add Morphism" "addmor" "Add Morphism @{f} : @{id}" t "Add\\s-+Morphism")
- ("Chapter" "chp" "Chapter # : #." t "Chapter")
- ("Corollary" "cor" "Corollary # : #.\nProof.\n#\nQed." t "Corollary")
- ("Declare Module :" "dmi" "Declare Module # : #.\n#\nEnd #." t)
- ("Declare Module <:" "dmi2" "Declare Module # <: #.\n#\nEnd #." t)
- ("Definition goal" "defg" "Definition #:#.\n#\nQed." t);; careful
- ("Fact" "fct" "Fact # : #." t "Fact")
- ("Goal" nil "Goal #." t "Goal")
- ("Lemma" "l" "Lemma # : #.\nProof.\n#\nQed." t "Lemma")
- ("Program Lemma" "pl" "Program Lemma # : #.\nProof.\n#\nQed." t "Program\\s-+Lemma")
- ("Module! (interactive)" nil "Module # : #.\n#\nEnd #." nil nil coq-insert-section-or-module)
- ("Module Type" "mti" "Module Type #.\n#\nEnd #." t "Module\\s-+Type") ; careful
- ("Module :" "moi" "Module # : #.\n#\nEnd #." t "Module") ; careful
- ("Module <:" "moi2" "Module # <: #.\n#\nEnd #." t ) ; careful
- ("Remark" "rk" "Remark # : #.\n#\nQed." t "Remark")
- ("Section" "sec" "Section #." t "Section")
- ("Theorem" "th" "Theorem # : #.\n#\nQed." t "Theorem")
- ("Program Theorem" "pth" "Program Theorem # : #.\nProof.\n#\nQed." t "Program\\s-+Theorem")
- ("Obligation" "obl" "Obligation #.\n#\nQed." t "Obligation")
- ("Next Obligation" "nobl" "Next Obligation.\n#\nQed." t "Next Obligation")
- )
- "Coq goal starters keywords information list. See `coq-syntax-db' for syntax. "
- )
-
-;; command that are not declarations, definition or goal starters
-(defvar coq-other-commands-db
- '(
- ;; ("Abort" nil "Abort." t "Abort" nil nil);don't appear in menu
- ("About" nil "About #." nil "About")
- ("Add" nil "Add #." nil "Add" nil t)
- ("Add Abstract Ring" nil "Add Abstract Ring #." t "Add\\s-+Abstract\\s-+Ring")
- ("Add Abstract Semi Ring" nil "Add Abstract Semi Ring #." t "Add\\s-+Abstract\\s-+Semi\\s-+Ring")
- ("Add Field" nil "Add Field #." t "Add\\s-+Field")
- ("Add LoadPath" nil "Add LoadPath #." nil "Add\\s-+LoadPath")
- ("Add ML Path" nil "Add ML Path #." nil "Add\\s-+ML\\s-+Path")
- ("Add Morphism" nil "Add Morphism #." t "Add\\s-+Morphism")
- ("Add Printing" nil "Add Printing #." t "Add\\s-+Printing")
- ("Add Printing Constructor" nil "Add Printing Constructor #." t "Add\\s-+Printing\\s-+Constructor")
- ("Add Printing If" nil "Add Printing If #." t "Add\\s-+Printing\\s-+If")
- ("Add Printing Let" nil "Add Printing Let #." t "Add\\s-+Printing\\s-+Let")
- ("Add Printing Record" nil "Add Printing Record #." t "Add\\s-+Printing\\s-+Record")
- ("Add Rec LoadPath" nil "Add Rec LoadPath #." nil "Add\\s-+Rec\\s-+LoadPath")
- ("Add Rec ML Path" nil "Add Rec ML Path #." nil "Add\\s-+Rec\\s-+ML\\s-+Path")
- ("Add Ring" nil "Add Ring #." t "Add\\s-+Ring")
- ("Add Semi Ring" nil "Add Semi Ring #." t "Add\\s-+Semi\\s-+Ring")
- ("Add Setoid" nil "Add Setoid #." t "Add\\s-+Setoid")
- ("Admit Obligations" "oblsadmit" "Admit Obligations." nil "Admit\\s-+Obligations")
- ("Bind Scope" "bndsc" "Bind Scope @{scope} with @{type}" t "Bind\\s-+Scope")
- ("Canonical Structure" nil "Canonical Structure #." t "Canonical\\s-+Structure")
- ("Cd" nil "Cd #." nil "Cd")
- ("Check" nil "Check" nil "Check")
- ("Close Local Scope" "cllsc" "Close Local Scope #" t "Close\\s-+Local\\s-+Scope")
- ("Close Scope" "clsc" "Close Scope #" t "Close\\s-+Scope")
- ("Comments" nil "Comments #." nil "Comments")
- ("Delimit Scope" "delsc" "Delimit Scope @{scope} with @{id}." t "Delimit\\s-+Scope" )
- ("Eval" nil "Eval #." nil "Eval")
- ("Export" nil "Export #." t "Export")
- ("Extract Constant" "extrc" "Extract Constant @{id} => \"@{id}\"." nil "Extract\\s-+Constant")
- ("Extract Inlined Constant" "extric" "Extract Inlined Constant @{id} => \"@{id}\"." nil "Extract\\s-+Inlined\\s-+Constant")
- ("Extract Inductive" "extri" "Extract Inductive @{id} => \"@{id}\" [\"@{id}\" \"@{id...}\"]." nil "Extract")
- ("Extraction" "extr" "Extraction @{id}." nil "Extraction")
- ("Extraction (in a file)" "extrf" "Extraction \"@{file}\" @{id}." nil)
- ("Extraction Inline" nil "Extraction Inline #." t "Extraction\\s-+Inline")
- ("Extraction NoInline" nil "Extraction NoInline #." t "Extraction\\s-+NoInline")
- ("Extraction Language" "extrlang" "Extraction Language #." t "Extraction\\s-+Language")
- ("Extraction Library" "extrl" "Extraction Library @{id}." nil "Extraction\\s-+Library")
- ("Focus" nil "Focus #." nil "Focus")
- ("Identity Coercion" nil "Identity Coercion #." t "Identity\\s-+Coercion")
- ("Implicit Arguments Off" nil "Implicit Arguments Off." t "Implicit\\s-+Arguments\\s-+Off")
- ("Implicit Arguments On" nil "Implicit Arguments On." t "Implicit\\s-+Arguments\\s-+On")
- ("Implicit Arguments" nil "Implicit Arguments # [#]." t "Implicit\\s-+Arguments")
- ("Import" nil "Import #." t "Import")
- ("Infix" "inf" "Infix \"#\" := # (at level #) : @{scope}." t "Infix")
- ("Inspect" nil "Inspect #." nil "Inspect")
- ("Locate" nil "Locate" nil "Locate")
- ("Locate File" nil "Locate File \"#\"." nil "Locate\\s-+File")
- ("Locate Library" nil "Locate Library #." nil "Locate\\s-+Library")
- ("Notation (assoc)" "notas" "Notation \"#\" := # (at level #, # associativity)." t)
- ("Notation (at assoc)" "notassc" "Notation \"#\" := # (at level #, # associativity) : @{scope}." t)
- ("Notation (at at scope)" "notasc" "Notation \"#\" := # (at level #, # at level #) : @{scope}." t)
- ("Notation (at at)" "nota" "Notation \"#\" := # (at level #, # at level #)." t)
- ("Notation (only parsing)" "notsp" "Notation # := # (only parsing)." t)
- ("Notation Local (only parsing)" "notslp" "Notation Local # := # (only parsing)." t)
- ("Notation Local" "notsl" "Notation Local # := #." t "Notation\\s-+Local")
- ("Notation (simple)" "nots" "Notation # := #." t "Notation")
- ("Opaque" nil "Opaque #." nil "Opaque")
- ("Obligations Tactic" nil "Obligations Tactic := #." t "Obligations\\s-+Tactic")
- ("Open Local Scope" "oplsc" "Open Local Scope #" t "Open\\s-+Local\\s-+Scope")
- ("Open Scope" "opsc" "Open Scope #" t "Open\\s-+Scope")
- ("Print Coercions" nil "Print Coercions." nil "Print\\s-+Coercions")
- ("Print Hint" nil "Print Hint." nil "Print\\s-+Hint" coq-PrintHint)
- ("Print" "p" "Print #." nil "Print")
- ("Qed" nil "Qed." nil "Qed")
- ("Pwd" nil "Pwd." nil "Pwd")
- ("Recursive Extraction" "recextr" "Recursive Extraction @{id}." nil "Recursive\\s-+Extraction")
- ("Recursive Extraction Library" "recextrl" "Recursive Extraction Library @{id}." nil "Recursive\\s-+Extraction\\s-+Library")
- ("Recursive Extraction Module" "recextrm" "Recursive Extraction Module @{id}." nil "Recursive\\s-+Extraction\\s-+Module")
- ("Remove LoadPath" nil "Remove LoadPath" nil "Remove\\s-+LoadPath")
- ("Remove LoadPath" nil "Remove LoadPath" nil "Remove\\s-+LoadPath")
- ("Remove Printing If" nil "Remove Printing If #." t "Remove\\s-+Printing\\s-+If")
- ("Remove Printing Let" nil "Remove Printing Let #." t "Remove\\s-+Printing\\s-+Let")
- ("Require Export" nil "Require Export #." t "Require\\s-+Export")
- ("Require Import" nil "Require Import #." t "Require\\s-+Import")
- ("Require" nil "Require #." t "Require")
- ("Reserved Notation" nil "Reserved Notation" nil "Reserved\\s-+Notation")
- ("Reset Extraction Inline" nil "Reset Extraction Inline." t "Reset\\s-+Extraction\\s-+Inline")
- ("Search" nil "Search #" nil "Search")
- ("SearchAbout" nil "SearchAbout #" nil "SearchAbout")
- ("SearchPattern" nil "SearchPattern #" nil "SearchPattern")
- ("SearchRewrite" nil "SearchRewrite #" nil "SearchRewrite")
- ("Set Extraction AutoInline" nil "Set Extraction AutoInline" t "Set\\s-+Extraction\\s-+AutoInline")
- ("Set Extraction Optimize" nil "Set Extraction Optimize" t "Set\\s-+Extraction\\s-+Optimize")
- ("Set Implicit Arguments" nil "Set Implicit Arguments" t "Set\\s-+Implicit\\s-+Arguments")
- ("Set Strict Implicit" nil "Set Strict Implicit" t "Set\\s-+Strict\\s-+Implicit")
- ("Set Printing Synth" nil "Set Printing Synth" t "Set\\s-+Printing\\s-+Synth")
- ("Set Printing Wildcard" nil "Set Printing Wildcard" t "Set\\s-+Printing\\s-+Wildcard")
- ("Set Printing All" "sprall" "Set Printing All" t "Set\\s-+Printing\\s-+All")
- ("Set Printing Records" nil "Set Printing Records" t "Set\\s-+Printing\\s-+Records")
- ("Set Hyps Limit" nil "Set Hyps Limit #." nil "Set\\s-+Hyps\\s-+Limit")
- ("Set Printing Coercions" nil "Set Printing Coercions." t "Set\\s-+Printing\\s-+Coercions")
- ("Set Printing Notations" "sprn" "Set Printing Notations" t "Set\\s-+Printing\\s-+Notations")
- ("Set Undo" nil "Set Undo #." nil "Set\\s-+Undo")
- ("Show" nil "Show #." nil "Show")
- ("Solve Obligations" "oblssolve" "Solve Obligations using #." nil "Solve\\s-+Obligations")
- ("Test" nil "Test" nil "Test" nil t)
- ("Test Printing Depth" nil "Test Printing Depth." nil "Test\\s-+Printing\\s-+Depth")
- ("Test Printing If" nil "Test Printing If #." nil "Test\\s-+Printing\\s-+If")
- ("Test Printing Let" nil "Test Printing Let #." nil "Test\\s-+Printing\\s-+Let")
- ("Test Printing Synth" nil "Test Printing Synth." nil "Test\\s-+Printing\\s-+Synth")
- ("Test Printing Width" nil "Test Printing Width." nil "Test\\s-+Printing\\s-+Width")
- ("Test Printing Wildcard" nil "Test Printing Wildcard." nil "Test\\s-+Printing\\s-+Wildcard")
- ("Transparent" nil "Transparent #." nil "Transparent")
- ("Unfocus" nil "Unfocus." nil "Unfocus")
- ("Unset Extraction AutoInline" nil "Unset Extraction AutoInline" t "Unset\\s-+Extraction\\s-+AutoInline")
- ("Unset Extraction Optimize" nil "Unset Extraction Optimize" t "Unset\\s-+Extraction\\s-+Optimize")
- ("Unset Implicit Arguments" nil "Unset Implicit Arguments" t "Unset\\s-+Implicit\\s-+Arguments")
- ("Unset Strict Implicit" nil "Unset Strict Implicit" t "Unset\\s-+Strict\\s-+Implicit")
- ("Unset Printing Synth" nil "Unset Printing Synth" t "Unset\\s-+Printing\\s-+Synth")
- ("Unset Printing Wildcard" nil "Unset Printing Wildcard" t "Unset\\s-+Printing\\s-+Wildcard")
- ("Unset Hyps Limit" nil "Unset Hyps Limit" nil "Unset\\s-+Hyps\\s-+Limit")
- ("Unset Printing All" "unsprall" "Unset Printing All" nil "Unset\\s-+Printing\\s-+All")
- ("Unset Printing Coercion" nil "Unset Printing Coercion #." t "Unset\\s-+Printing\\s-+Coercion")
- ("Unset Printing Coercions" nil "Unset Printing Coercions." nil "Unset\\s-+Printing\\s-+Coercions")
- ("Unset Printing Notations" "unsprn" "Unset Printing Notations" nil "Unset\\s-+Printing\\s-+Notations")
- ("Unset Undo" nil "Unset Undo." nil "Unset\\s-+Undo")
- ; ("print" "pr" "print #" "print")
- )
- "Command that are not declarations, definition or goal starters."
- )
-
-(defvar coq-commands-db
- (append coq-decl-db coq-defn-db coq-goal-starters-db
- coq-other-commands-db coq-user-commands-db)
- "Coq all commands keywords information list. See `coq-syntax-db' for syntax. "
- )
-
-
-(defvar coq-terms-db
- '(
- ("fun (1 args)" "f" "fun #:# => #" nil "fun")
- ("fun (2 args)" "f2" "fun (#:#) (#:#) => #")
- ("fun (3 args)" "f3" "fun (#:#) (#:#) (#:#) => #")
- ("fun (4 args)" "f4" "fun (#:#) (#:#) (#:#) (#:#) => #")
- ("forall" "fo" "forall #:#,#" nil "forall")
- ("forall (2 args)" "fo2" "forall (#:#) (#:#), #")
- ("forall (3 args)" "fo3" "forall (#:#) (#:#) (#:#), #")
- ("forall (4 args)" "fo4" "forall (#:#) (#:#) (#:#) (#:#), #")
- ("if" "if" "if # then # else #" nil "if")
- ("let in" "li" "let # := # in #" nil "let")
- ("match! (from type)" nil "" nil "match" coq-insert-match)
- ("match with" "m" "match # with\n| # => #\nend")
- ("match with 2" "m2" "match # with\n| # => #\n| # => #\nend")
- ("match with 3" "m3" "match # with\n| # => #\n| # => #\n| # => #\nend")
- ("match with 4" "m4" "match # with\n| # => #\n| # => #\n| # => #\n| # => #\nend")
- ("match with 5" "m5" "match # with\n| # => #\n| # => #\n| # => #\n| # => #\n| # => #\nend")
- )
- "Coq terms keywords information list. See `coq-syntax-db' for syntax. "
- )
-
-
-
-
-
-
-
- ;;; Goals (and module/sections) starters detection
-
-
-;; ----- keywords for font-lock.
-
-;; FIXME da: this one function breaks the nice configuration of Proof General:
-;; would like to have proof-goal-regexp instead.
-;; Unfortunately Coq allows "Definition" and friends to perhaps have a goal,
-;; so it appears more difficult than just a proof-goal-regexp setting.
-;; Future improvement may simply to be allow a function value for
-;; proof-goal-regexp.
-
-;; FIXME Pierre: the right way IMHO here would be to set a span
-;; property 'goalcommand when coq prompt says it (if the name of
-;; current proof has changed).
-
-;; excerpt of Jacek Chrzaszcz, implementer of the module system: sorry
-;; for the french:
-;;*) suivant les suggestions de Chritine, pas de mode preuve dans un type de
-;; module (donc pas de Definition truc:machin. Lemma, Theorem ... )
-;;
-;; *) la commande Module M [ ( : | <: ) MTYP ] [ := MEXPR ] est valable
-;; uniquement hors d'un MT
-;; - si :=MEXPR est absent, elle demarre un nouveau module interactif
-;; - si :=MEXPR est present, elle definit un module
-;; (la fonction vernac_define_module dans toplevel/vernacentries)
-;;
-;; *) la nouvelle commande Declare Module M [ ( : | <: ) MTYP ] [ := MEXPR ]
-;; est valable uniquement dans un MT
-;; - si :=MEXPR absent, :MTYP absent, elle demarre un nouveau module
-;; interactif
-;; - si (:=MEXPR absent, :MTYP present)
-;; ou (:=MEXPR present, :MTYP absent)
-;; elle declare un module.
-;; (la fonction vernac_declare_module dans toplevel/vernacentries)
-
-(defun coq-count-match (regexp strg)
- "Count the number of (maximum, non overlapping) matching substring
- of STRG matching REGEXP. Empty match are counted once."
- (let ((nbmatch 0) (str strg))
- (while (and (proof-string-match regexp str) (not (string-equal str "")))
- (incf nbmatch)
- (if (= (match-end 0) 0) (setq str (substring str 1))
- (setq str (substring str (match-end 0)))))
- nbmatch))
-
-;; This function is used for amalgamating a proof into a single
-;; goal-save region (proof-goal-command-p used in
-;; proof-done-advancing-save in generic/proof-script.el) for coq <
-;; 8.0. It is the test when looking backward the start of the proof.
-;; It is NOT used for coq > v8.1
-;; (coq-find-and-forget in gallina.el uses state numbers, proof numbers and
-;; lemma names given in the prompt)
-
-;; compatibility with v8.0, will delete it some day
-(defun coq-goal-command-str-v80-p (str)
- "See `coq-goal-command-p'."
- (let* ((match (coq-count-match "\\<match\\>" str))
- (with (coq-count-match "\\<with\\>" str))
- (letwith (+ (coq-count-match "\\<let\\>" str) (- with match)))
- (affect (coq-count-match ":=" str)))
-
- (and (proof-string-match coq-goal-command-regexp str)
- (not ;
- (and
- (proof-string-match "\\`\\(Local\\|Definition\\|Lemma\\|Module\\)\\>" str)
- (not (= letwith affect))))
- (not (proof-string-match "\\`Declare\\s-+Module\\(\\w\\|\\s-\\|<\\)*:" str))
- )
- )
- )
-
-;; Module and or section openings are detected syntactically. Module
-;; *openings* are difficult to detect because there can be Module
-;; ...with X := ... . So we need to count :='s to detect real openings.
-
-;; TODO: have opened section/chapter in the prompt too, and get rid of
-;; syntactical tests everywhere
-(defun coq-module-opening-p (str)
- "Decide whether STR is a module or section opening or not.
-Used by `coq-goal-command-p'"
- (let* ((match (coq-count-match "\\<match\\>" str))
- (with (coq-count-match "\\<with\\>" str))
- (letwith (+ (coq-count-match "\\<let\\>" str) (- with match)))
- (affect (coq-count-match ":=" str)))
- (and (proof-string-match "\\`\\(Module\\)\\>" str)
- (= letwith affect))
- ))
-
-(defun coq-section-command-p (str)
- (proof-string-match "\\`\\(Section\\|Chapter\\)\\>" str))
-
-
-(defun coq-goal-command-str-v81-p (str)
- "Decide syntactically whether STR is a goal start or not. Use
- `coq-goal-command-p-v81' on a span instead if possible."
- (coq-goal-command-str-v80-p str)
- )
-
-;; This is the function that tests if a SPAN is a goal start. All it
-;; has to do is look at the 'goalcmd attribute of the span.
-;; It also looks if this is not a module start.
-
-;; TODO: have also attributes 'modulecmd and 'sectioncmd. This needs
-;; something in the coq prompt telling the name of all opened modules
-;; (like for open goals), and use it to set goalcmd --> no more need
-;; to look at Modules and section (actually indentation will still
-;; need it)
-(defun coq-goal-command-p-v81 (span)
- "see `coq-goal-command-p'"
- (or (span-property span 'goalcmd)
- ;; module and section starts are detected here
- (let ((str (or (span-property span 'cmd) "")))
- (or (coq-section-command-p str)
- (coq-module-opening-p str))
- )))
-
-;; In coq > 8.1 This is used only for indentation.
-(defun coq-goal-command-str-p (str)
- "Decide whether argument is a goal or not. Use
- `coq-goal-command-p' on a span instead if posible."
- (cond
- (coq-version-is-V8-1 (coq-goal-command-str-v81-p str))
- (coq-version-is-V8-0 (coq-goal-command-str-v80-p str))
- (t (coq-goal-command-str-v80-p str));; this is temporary
- ))
-
-;; This is used for backtracking
-(defun coq-goal-command-p (span)
- "Decide whether argument is a goal or not."
- (cond
- (coq-version-is-V8-1 (coq-goal-command-p-v81 span))
- (coq-version-is-V8-0 (coq-goal-command-str-v80-p (span-property span 'cmd)))
- (t (coq-goal-command-str-v80-p (span-property span 'cmd)));; this is temporary
- ))
-
-(defvar coq-keywords-save-strict
- '("Defined"
- "Qed"
- "End"
- "Admitted"
- "Abort"
- ))
-
-(defvar coq-keywords-save
- (append coq-keywords-save-strict '("Proof"))
- )
-
-(defun coq-save-command-p (span str)
- "Decide whether argument is a Save command or not"
- (or (proof-string-match coq-save-command-regexp-strict str)
- (and (proof-string-match "\\`Proof\\>" str)
- (not (proof-string-match "Proof\\s-*\\(\\.\\|\\<with\\>\\)" str)))
- )
- )
-
-
-(defvar coq-keywords-kill-goal
- '("Abort"))
-
-;; Following regexps are all state changing
-(defvar coq-keywords-state-changing-misc-commands
- (coq-build-regexp-list-from-db coq-commands-db 'filter-state-changing))
-
-(defvar coq-keywords-goal
- (coq-build-regexp-list-from-db coq-goal-starters-db))
-
-(defvar coq-keywords-decl
- (coq-build-regexp-list-from-db coq-decl-db))
-
-(defvar coq-keywords-defn
- (coq-build-regexp-list-from-db coq-defn-db))
-
-
-(defvar coq-keywords-state-changing-commands
- (append
- coq-keywords-state-changing-misc-commands
- coq-keywords-decl ; all state changing
- coq-keywords-defn ; idem
- coq-keywords-goal)) ; idem
-
-
-;;
-(defvar coq-keywords-state-preserving-commands
- (coq-build-regexp-list-from-db coq-commands-db 'filter-state-preserving))
-
-;; concat this is faster that redoing coq-build-regexp-list-from-db on
-;; whole commands-db
-(defvar coq-keywords-commands
- (append coq-keywords-state-changing-commands
- coq-keywords-state-preserving-commands)
- "All commands keyword.")
-
-(defvar coq-solve-tactics
- (coq-build-regexp-list-from-db coq-solve-tactics-db)
- "Keywords for closing tactic(al)s.")
-
-(defvar coq-tacticals
- (coq-build-regexp-list-from-db coq-tacticals-db)
- "Keywords for tacticals in a Coq script.")
-
-
- ;; From JF Monin:
-(defvar coq-reserved
- (append
- coq-user-reserved-db
- '(
- "False" "True" "after" "as" "cofix" "fix" "forall" "fun" "match"
- "return" "struct" "else" "end" "if" "in" "into" "let" "then"
- "using" "with" "beta" "delta" "iota" "zeta" "after" "until"
- "at" "Sort" "Time"))
- "Reserved keywords of Coq.")
-
-
-(defvar coq-state-changing-tactics
- (coq-build-regexp-list-from-db coq-tactics-db 'filter-state-changing))
-
-(defvar coq-state-preserving-tactics
- (coq-build-regexp-list-from-db coq-tactics-db 'filter-state-preserving))
-
-
-(defvar coq-tactics
- (append coq-state-changing-tactics coq-state-preserving-tactics))
-
-(defvar coq-retractable-instruct
- (append coq-state-changing-tactics coq-keywords-state-changing-commands))
-
-(defvar coq-non-retractable-instruct
- (append coq-state-preserving-tactics
- coq-keywords-state-preserving-commands))
-
-(defvar coq-keywords
- (append coq-keywords-goal coq-keywords-save coq-keywords-decl
- coq-keywords-defn coq-keywords-commands)
- "All keywords in a Coq script.")
-
-
-
-(defvar coq-symbols
- '("|"
- "||"
- ":"
- ";"
- ","
- "("
- ")"
- "["
- "]"
- "{"
- "}"
- ":="
- "=>"
- "->"
- ".")
- "Punctuation Symbols used by Coq.")
-
-;; ----- regular expressions
-(defvar coq-error-regexp "^\\(Error:\\|Discarding pattern\\|Syntax error:\\|System Error:\\|User Error:\\|User error:\\|Anomaly[:.]\\|Toplevel input[,]\\)"
- "A regexp indicating that the Coq process has identified an error.")
-
-(defvar coq-id proof-id)
-(defvar coq-id-shy "\\(?:\\w\\(?:\\w\\|\\s_\\)*\\)")
-
-(defvar coq-ids (proof-ids coq-id " "))
-
-(defun coq-first-abstr-regexp (paren end)
- (concat paren "\\s-*\\(" coq-ids "\\)\\s-*" end))
-
-(defcustom coq-variable-highlight-enable t
- "Activates partial bound variable highlighting"
- :type 'boolean
- :group 'coq)
-
-
-(defvar coq-font-lock-terms
- (if coq-variable-highlight-enable
- (list
- ;; lambda binders
- (list (coq-first-abstr-regexp "\\<fun\\>" "\\(?:=>\\|:\\)") 1 'font-lock-variable-name-face)
- ;; forall binder
- (list (coq-first-abstr-regexp "\\<forall\\>" "\\(?:,\\|:\\)") 1 'font-lock-variable-name-face)
- ; (list "\\<forall\\>"
- ; (list 0 font-lock-type-face)
- ; (list (concat "[^ :]\\s-*\\(" coq-ids "\\)\\s-*") nil nil
- ; (list 0 font-lock-variable-name-face)))
- ;; parenthesized binders
- (list (coq-first-abstr-regexp "(" ":[ a-zA-Z]") 1 'font-lock-variable-name-face)
- ))
- "*Font-lock table for Coq terms.")
-
-
-
-;; According to Coq, "Definition" is both a declaration and a goal.
-;; It is understood here as being a goal. This is important for
-;; recognizing global identifiers, see coq-global-p.
-(defconst coq-save-command-regexp-strict
- (proof-anchor-regexp
- (concat "\\(Time\\s-+\\|\\)\\(" (proof-ids-to-regexp coq-keywords-save-strict)
- "\\)")))
-(defconst coq-save-command-regexp
- (proof-anchor-regexp
- (concat "\\(Time\\s-+\\|\\)\\(" (proof-ids-to-regexp coq-keywords-save)
- "\\)")))
-(defconst coq-save-with-hole-regexp
- (concat "\\(Time\\s-+\\|\\)\\(" (proof-ids-to-regexp coq-keywords-save-strict)
- "\\)\\s-+\\(" coq-id "\\)\\s-*\\."))
-
-(defconst coq-goal-command-regexp
- (proof-anchor-regexp (proof-ids-to-regexp coq-keywords-goal)))
-
-(defconst coq-goal-with-hole-regexp
- (concat "\\(" (proof-ids-to-regexp coq-keywords-goal)
- "\\)\\s-+\\(" coq-id "\\)\\s-*:?"))
-
-(defconst coq-decl-with-hole-regexp
- (concat "\\(" (proof-ids-to-regexp coq-keywords-decl)
- "\\)\\s-+\\(" coq-ids "\\)\\s-*:"))
-
-;; (defconst coq-decl-with-hole-regexp
-;; (if coq-variable-highlight-enable coq-decl-with-hole-regexp-1 'nil))
-
-(defconst coq-defn-with-hole-regexp
- (concat "\\(" (proof-ids-to-regexp coq-keywords-defn)
- "\\)\\s-+\\(" coq-id "\\)"))
-
-;; must match:
-;; "with f x y :" (followed by = or not)
-;; "with f x y (z:" (not followed by =)
-;; BUT NOT:
-;; "with f ... (x:="
-;; "match ... with .. => "
-(defconst coq-with-with-hole-regexp
- (concat "\\(with\\)\\s-+\\(" coq-id "\\)\\s-*\\([^=(.]*:\\|[^(]*(\\s-*"
- coq-id "\\s-*:[^=]\\)"))
-;; marche aussi a peu pres
-;; (concat "\\(with\\)\\s-+\\(" coq-id "\\)\\s-*\\([^(.]*:\\|.*)[^(.]*:=\\)"))
-;;"\\<Prop\\>\\|\\<Set\\>\\|\\<Type\\>"
-(defvar coq-font-lock-keywords-1
- (append
- coq-font-lock-terms
- (list
- (cons (proof-ids-to-regexp coq-solve-tactics) 'coq-solve-tactics-face)
- (cons (proof-ids-to-regexp coq-keywords) 'font-lock-keyword-face)
- (cons (proof-ids-to-regexp coq-reserved) 'font-lock-type-face)
- (cons (proof-ids-to-regexp coq-tactics ) 'proof-tactics-name-face)
- (cons (proof-ids-to-regexp coq-tacticals) 'proof-tacticals-name-face)
- (cons (proof-ids-to-regexp (list "Set" "Type" "Prop")) 'font-lock-type-face)
- (cons "============================" 'font-lock-keyword-face)
- (cons "Subtree proved!" 'font-lock-keyword-face)
- (cons "subgoal [0-9]+ is:" 'font-lock-keyword-face)
- (list "^\\([^ \n]+\\) \\(is defined\\)"
- (list 2 'font-lock-keyword-face t)
- (list 1 'font-lock-function-name-face t))
-
- (list coq-goal-with-hole-regexp 2 'font-lock-function-name-face))
- (if coq-variable-highlight-enable (list (list coq-decl-with-hole-regexp 2 'font-lock-variable-name-face)))
- (list
- (list coq-defn-with-hole-regexp 2 'font-lock-function-name-face)
- (list coq-with-with-hole-regexp 2 'font-lock-function-name-face)
- (list coq-save-with-hole-regexp 2 'font-lock-function-name-face)
- ;; Remove spurious variable and function faces on commas.
- '(proof-zap-commas))))
-
-(defvar coq-font-lock-keywords coq-font-lock-keywords-1)
-
-(defun coq-init-syntax-table ()
- "Set appropriate values for syntax table in current buffer."
-
- (modify-syntax-entry ?\$ ".")
- (modify-syntax-entry ?\/ ".")
- (modify-syntax-entry ?\\ ".")
- (modify-syntax-entry ?+ ".")
- (modify-syntax-entry ?- ".")
- (modify-syntax-entry ?= ".")
- (modify-syntax-entry ?% ".")
- (modify-syntax-entry ?< ".")
- (modify-syntax-entry ?> ".")
- (modify-syntax-entry ?\& ".")
- (modify-syntax-entry ?_ "_")
- (modify-syntax-entry ?\' "_")
- (modify-syntax-entry ?\| ".")
-
-;; should maybe be "_" but it makes coq-find-and-forget (in gallina.el) bug
- (modify-syntax-entry ?\. ".")
-
- (condition-case nil
- ;; Try to use Emacs-21's nested comments.
- (modify-syntax-entry ?\* ". 23n")
- ;; Revert to non-nested comments if that failed.
- (error (modify-syntax-entry ?\* ". 23")))
- (modify-syntax-entry ?\( "()1")
- (modify-syntax-entry ?\) ")(4"))
-
-
-(defconst coq-generic-expression
- (mapcar (lambda (kw)
- (list (capitalize kw)
- (concat "\\<" kw "\\>" "\\s-+\\(\\w+\\)\\W" )
- 1))
- (append coq-keywords-decl coq-keywords-defn coq-keywords-goal)))
-
-(provide 'gallina-syntax)
- ;;; gallina-syntax.el ends here
-
-; Local Variables: ***
-; indent-tabs-mode: nil ***
-; End: ***
diff --git a/tools/gallina.el b/tools/gallina.el
deleted file mode 100644
index cbc13118a6..0000000000
--- a/tools/gallina.el
+++ /dev/null
@@ -1,142 +0,0 @@
-;; gallina.el --- Coq mode editing commands for Emacs
-;;
-;; Jean-Christophe Filliatre, march 1995
-;; Shamelessly copied from caml.el, Xavier Leroy, july 1993.
-;;
-;; modified by Marco Maggesi <maggesi@math.unifi.it> for gallina-inferior
-
-; compatibility code for proofgeneral files
-(require 'coq-font-lock)
-; ProofGeneral files. remember to remove coq version tests in
-; gallina-syntax.el
-(require 'gallina-syntax)
-
-(defvar coq-mode-map nil
- "Keymap used in Coq mode.")
-(if coq-mode-map
- ()
- (setq coq-mode-map (make-sparse-keymap))
- (define-key coq-mode-map "\t" 'coq-indent-command)
- (define-key coq-mode-map "\M-\t" 'coq-unindent-command)
- (define-key coq-mode-map "\C-c\C-c" 'compile)
-)
-
-(defvar coq-mode-syntax-table nil
- "Syntax table in use in Coq mode buffers.")
-(if coq-mode-syntax-table
- ()
- (setq coq-mode-syntax-table (make-syntax-table))
- ; ( is first character of comment start
- (modify-syntax-entry ?\( "()1" coq-mode-syntax-table)
- ; * is second character of comment start,
- ; and first character of comment end
- (modify-syntax-entry ?* ". 23" coq-mode-syntax-table)
- ; ) is last character of comment end
- (modify-syntax-entry ?\) ")(4" coq-mode-syntax-table)
- ; quote is a string-like delimiter (for character literals)
- (modify-syntax-entry ?' "\"" coq-mode-syntax-table)
- ; quote is part of words
- (modify-syntax-entry ?' "w" coq-mode-syntax-table)
-)
-
-(defvar coq-mode-indentation 2
- "*Indentation for each extra tab in Coq mode.")
-
-(defun coq-mode-variables ()
- (set-syntax-table coq-mode-syntax-table)
- (make-local-variable 'paragraph-start)
- (setq paragraph-start (concat "^$\\|" page-delimiter))
- (make-local-variable 'paragraph-separate)
- (setq paragraph-separate paragraph-start)
- (make-local-variable 'paragraph-ignore-fill-prefix)
- (setq paragraph-ignore-fill-prefix t)
- (make-local-variable 'require-final-newline)
- (setq require-final-newline t)
- (make-local-variable 'comment-start)
- (setq comment-start "(* ")
- (make-local-variable 'comment-end)
- (setq comment-end " *)")
- (make-local-variable 'comment-column)
- (setq comment-column 40)
- (make-local-variable 'comment-start-skip)
- (setq comment-start-skip "(\\*+ *")
- (make-local-variable 'parse-sexp-ignore-comments)
- (setq parse-sexp-ignore-comments nil)
- (make-local-variable 'indent-line-function)
- (setq indent-line-function 'coq-indent-command)
- (make-local-variable 'font-lock-keywords)
- (setq font-lock-defaults '(coq-font-lock-keywords-1)))
-
-;;; The major mode
-
-(defun coq-mode ()
- "Major mode for editing Coq code.
-Tab at the beginning of a line indents this line like the line above.
-Extra tabs increase the indentation level.
-\\{coq-mode-map}
-The variable coq-mode-indentation indicates how many spaces are
-inserted for each indentation level."
- (interactive)
- (kill-all-local-variables)
- (setq major-mode 'coq-mode)
- (setq mode-name "coq")
- (use-local-map coq-mode-map)
- (coq-mode-variables)
- (run-hooks 'coq-mode-hook))
-
-;;; Indentation stuff
-
-(defun coq-in-indentation ()
- "Tests whether all characters between beginning of line and point
-are blanks."
- (save-excursion
- (skip-chars-backward " \t")
- (bolp)))
-
-(defun coq-indent-command ()
- "Indent the current line in Coq mode.
-When the point is at the beginning of an empty line, indent this line like
-the line above.
-When the point is at the beginning of an indented line
-\(i.e. all characters between beginning of line and point are blanks\),
-increase the indentation by one level.
-The indentation size is given by the variable coq-mode-indentation.
-In all other cases, insert a tabulation (using insert-tab)."
- (interactive)
- (let* ((begline
- (save-excursion
- (beginning-of-line)
- (point)))
- (current-offset
- (- (point) begline))
- (previous-indentation
- (save-excursion
- (if (eq (forward-line -1) 0) (current-indentation) 0))))
- (cond ((and (bolp)
- (looking-at "[ \t]*$")
- (> previous-indentation 0))
- (indent-to previous-indentation))
- ((coq-in-indentation)
- (indent-to (+ current-offset coq-mode-indentation)))
- (t
- (insert-tab)))))
-
-(defun coq-unindent-command ()
- "Decrease indentation by one level in Coq mode.
-Works only if the point is at the beginning of an indented line
-\(i.e. all characters between beginning of line and point are blanks\).
-Does nothing otherwise."
- (interactive)
- (let* ((begline
- (save-excursion
- (beginning-of-line)
- (point)))
- (current-offset
- (- (point) begline)))
- (if (and (>= current-offset coq-mode-indentation)
- (coq-in-indentation))
- (backward-delete-char-untabify coq-mode-indentation))))
-
-;;; gallina.el ends here
-
-(provide 'gallina)
diff --git a/tools/gallina.ml b/tools/gallina.ml
deleted file mode 100644
index c7ff76becd..0000000000
--- a/tools/gallina.ml
+++ /dev/null
@@ -1,63 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-open Gallina_lexer
-
-let vfiles = ref ([] : string list)
-
-let option_moins = ref false
-
-let option_stdout = ref false
-
-let traite_fichier f =
- try
- let chan_in = open_in (f^".v") in
- let buf = Lexing.from_channel chan_in in
- if not !option_stdout then chan_out := open_out (f ^ ".g");
- try
- while true do Gallina_lexer.action buf done
- with Fin_fichier -> begin
- flush !chan_out;
- close_in chan_in;
- if not !option_stdout then close_out !chan_out
- end
- with Sys_error _ ->
- ()
-
-let traite_stdin () =
- try
- let buf = Lexing.from_channel stdin in
- try
- while true do Gallina_lexer.action buf done
- with Fin_fichier ->
- flush !chan_out
- with Sys_error _ ->
- ()
-
-let _ =
- let lg_command = Array.length Sys.argv in
- if lg_command < 2 then begin
- output_string stderr "Usage: gallina [-] [-stdout] file1 file2 ...\n";
- flush stderr;
- exit 1
- end;
- let treat = function
- | "-" -> option_moins := true
- | "-stdout" -> option_stdout := true
- | "-nocomments" -> comments := false
- | f ->
- if Filename.check_suffix f ".v" then
- vfiles := (Filename.chop_suffix f ".v") :: !vfiles
- in
- Array.iter treat Sys.argv;
- if !option_moins then
- traite_stdin ()
- else
- List.iter traite_fichier !vfiles
diff --git a/tools/gallina_lexer.mll b/tools/gallina_lexer.mll
deleted file mode 100644
index 1a594aebbf..0000000000
--- a/tools/gallina_lexer.mll
+++ /dev/null
@@ -1,126 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-{
-
- let chan_out = ref stdout
-
- let comment_depth = ref 0
- let cRcpt = ref 0
- let comments = ref true
- let print s = output_string !chan_out s
-
- exception Fin_fichier
-
-}
-
-let space = [' ' '\t' '\n' '\r']
-let enddot = '.' (' ' | '\t' | '\n' | '\r' | eof)
-
-rule action = parse
- | "Theorem" space { print "Theorem "; body lexbuf;
- cRcpt := 1; action lexbuf }
- | "Lemma" space { print "Lemma "; body lexbuf;
- cRcpt := 1; action lexbuf }
- | "Fact" space { print "Fact "; body lexbuf;
- cRcpt := 1; action lexbuf }
- | "Remark" space { print "Remark "; body lexbuf;
- cRcpt := 1; action lexbuf }
- | "Goal" space { print "Goal "; body lexbuf;
- cRcpt := 1; action lexbuf }
- | "Correctness" space { print "Correctness "; body_pgm lexbuf;
- cRcpt := 1; action lexbuf }
- | "Definition" space { print "Definition "; body_def lexbuf;
- cRcpt := 1; action lexbuf }
- | "Hint" space { skip_until_point lexbuf ; action lexbuf }
- | "Hints" space { skip_until_point lexbuf ; action lexbuf }
- | "Transparent" space { skip_until_point lexbuf ; action lexbuf }
- | "Immediate" space { skip_until_point lexbuf ; action lexbuf }
- | "Syntax" space { skip_until_point lexbuf ; action lexbuf }
- | "(*" { (if !comments then print "(*");
- comment_depth := 1;
- comment lexbuf;
- cRcpt := 0; action lexbuf }
- | [' ' '\t']* '\n' { if !cRcpt < 2 then print "\n";
- cRcpt := !cRcpt+1; action lexbuf}
- | eof { (raise Fin_fichier : unit)}
- | _ { print (Lexing.lexeme lexbuf); cRcpt := 0; action lexbuf }
-
-and comment = parse
- | "(*" { (if !comments then print "(*");
- comment_depth := succ !comment_depth; comment lexbuf }
- | "*)" { (if !comments then print "*)");
- comment_depth := pred !comment_depth;
- if !comment_depth > 0 then comment lexbuf }
- | "*)" [' ''\t']*'\n' { (if !comments then print (Lexing.lexeme lexbuf));
- comment_depth := pred !comment_depth;
- if !comment_depth > 0 then comment lexbuf }
- | eof { raise Fin_fichier }
- | _ { (if !comments then print (Lexing.lexeme lexbuf));
- comment lexbuf }
-
-and skip_comment = parse
- | "(*" { comment_depth := succ !comment_depth; skip_comment lexbuf }
- | "*)" { comment_depth := pred !comment_depth;
- if !comment_depth > 0 then skip_comment lexbuf }
- | eof { raise Fin_fichier }
- | _ { skip_comment lexbuf }
-
-and body_def = parse
- | [^'.']* ":=" { print (Lexing.lexeme lexbuf); () }
- | _ { print (Lexing.lexeme lexbuf); body lexbuf }
-
-and body = parse
- | enddot { print ".\n"; skip_proof lexbuf }
- | ":=" { print ".\n"; skip_proof lexbuf }
- | "(*" { print "(*"; comment_depth := 1;
- comment lexbuf; body lexbuf }
- | eof { raise Fin_fichier }
- | _ { print (Lexing.lexeme lexbuf); body lexbuf }
-
-and body_pgm = parse
- | enddot { print ".\n"; skip_proof lexbuf }
- | "(*" { print "(*"; comment_depth := 1;
- comment lexbuf; body_pgm lexbuf }
- | eof { raise Fin_fichier }
- | _ { print (Lexing.lexeme lexbuf); body_pgm lexbuf }
-
-and skip_until_point = parse
- | '.' '\n' { () }
- | enddot { end_of_line lexbuf }
- | "(*" { comment_depth := 1;
- skip_comment lexbuf; skip_until_point lexbuf }
- | eof { raise Fin_fichier }
- | _ { skip_until_point lexbuf }
-
-and end_of_line = parse
- | [' ' '\t' ]* { end_of_line lexbuf }
- | '\n' { () }
- | eof { raise Fin_fichier }
- | _ { print (Lexing.lexeme lexbuf) }
-
-and skip_proof = parse
- | "Save" space
- { skip_until_point lexbuf }
- | "Qed." { end_of_line lexbuf }
- | "Qed" space
- { skip_until_point lexbuf }
- | "Defined." { end_of_line lexbuf }
- | "Defined" space
- { skip_until_point lexbuf }
- | "Abort." { end_of_line lexbuf }
- | "Abort" space
- { skip_until_point lexbuf }
- | "Proof" space { skip_until_point lexbuf }
- | "Proof" [' ' '\t']* '.' { skip_proof lexbuf }
- | "(*" { comment_depth := 1;
- skip_comment lexbuf; skip_proof lexbuf }
- | eof { raise Fin_fichier }
- | _ { skip_proof lexbuf }
diff --git a/tools/inferior-coq.el b/tools/inferior-coq.el
deleted file mode 100644
index 453bd13915..0000000000
--- a/tools/inferior-coq.el
+++ /dev/null
@@ -1,324 +0,0 @@
-;;; inferior-coq.el --- Run an inferior Coq process.
-;;;
-;;; Copyright (C) Marco Maggesi <maggesi@math.unifi.it>
-;;; Time-stamp: "2002-02-28 12:15:04 maggesi"
-
-
-;; Emacs Lisp Archive Entry
-;; Filename: inferior-coq.el
-;; Version: 1.0
-;; Keywords: process coq
-;; Author: Marco Maggesi <maggesi@math.unifi.it>
-;; Maintainer: Marco Maggesi <maggesi@math.unifi.it>
-;; Description: Run an inferior Coq process.
-;; URL: http://www.math.unifi.it/~maggesi/
-;; Compatibility: Emacs20, Emacs21, XEmacs21
-
-;; This is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-;; MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; Coq is a proof assistant (http://coq.inria.fr/). This code run an
-;; inferior Coq process and defines functions to send bits of code
-;; from other buffers to the inferior process. This is a
-;; customisation of comint-mode (see comint.el). For a more complex
-;; and full featured Coq interface under Emacs look at Proof General
-;; (http://zermelo.dcs.ed.ac.uk/~proofgen/).
-;;
-;; Written by Marco Maggesi <maggesi@math.unifi.it> with code heavly
-;; borrowed from emacs cmuscheme.el
-;;
-;; Please send me bug reports, bug fixes, and extensions, so that I can
-;; merge them into the master source.
-
-;;; Installation:
-
-;; You need to have gallina.el already installed (it comes with the
-;; standard Coq distribution) in order to use this code. Put this
-;; file somewhere in you load-path and add the following lines in your
-;; "~/.emacs":
-;;
-;; (setq auto-mode-alist (cons '("\\.v$" . coq-mode) auto-mode-alist))
-;; (autoload 'coq-mode "gallina" "Major mode for editing Coq vernacular." t)
-;; (autoload 'run-coq "inferior-coq" "Run an inferior Coq process." t)
-;; (autoload 'run-coq-other-window "inferior-coq"
-;; "Run an inferior Coq process in a new window." t)
-;; (autoload 'run-coq-other-frame "inferior-coq"
-;; "Run an inferior Coq process in a new frame." t)
-
-;;; Usage:
-
-;; Call `M-x "run-coq'.
-;;
-;; Functions and key bindings (Learn more keys with `C-c C-h' or `C-h m'):
-;; C-return ('M-x coq-send-line) send the current line.
-;; C-c C-r (`M-x coq-send-region') send the current region.
-;; C-c C-a (`M-x coq-send-abort') send the command "Abort".
-;; C-c C-t (`M-x coq-send-restart') send the command "Restart".
-;; C-c C-s (`M-x coq-send-show') send the command "Show".
-;; C-c C-u (`M-x coq-send-undo') send the command "Undo".
-;; C-c C-v (`M-x coq-check-region') run command "Check" on region.
-;; C-c . (`M-x coq-come-here') Restart and send until current point.
-
-;;; Change Log:
-
-;; From -0.0 to 1.0 brought into existence.
-
-
-(require 'gallina)
-(require 'comint)
-
-(setq coq-program-name "coqtop")
-
-(defgroup inferior-coq nil
- "Run a coq process in a buffer."
- :group 'coq)
-
-(defcustom inferior-coq-mode-hook nil
- "*Hook for customising inferior-coq mode."
- :type 'hook
- :group 'coq)
-
-(defvar inferior-coq-mode-map
- (let ((m (make-sparse-keymap)))
- (define-key m "\C-c\C-r" 'coq-send-region)
- (define-key m "\C-c\C-a" 'coq-send-abort)
- (define-key m "\C-c\C-t" 'coq-send-restart)
- (define-key m "\C-c\C-s" 'coq-send-show)
- (define-key m "\C-c\C-u" 'coq-send-undo)
- (define-key m "\C-c\C-v" 'coq-check-region)
- m))
-
-;; Install the process communication commands in the coq-mode keymap.
-(define-key coq-mode-map [(control return)] 'coq-send-line)
-(define-key coq-mode-map "\C-c\C-r" 'coq-send-region)
-(define-key coq-mode-map "\C-c\C-a" 'coq-send-abort)
-(define-key coq-mode-map "\C-c\C-t" 'coq-send-restart)
-(define-key coq-mode-map "\C-c\C-s" 'coq-send-show)
-(define-key coq-mode-map "\C-c\C-u" 'coq-send-undo)
-(define-key coq-mode-map "\C-c\C-v" 'coq-check-region)
-(define-key coq-mode-map "\C-c." 'coq-come-here)
-
-(defvar coq-buffer)
-
-(define-derived-mode inferior-coq-mode comint-mode "Inferior Coq"
- "\
-Major mode for interacting with an inferior Coq process.
-
-The following commands are available:
-\\{inferior-coq-mode-map}
-
-A Coq process can be fired up with M-x run-coq.
-
-Customisation: Entry to this mode runs the hooks on comint-mode-hook
-and inferior-coq-mode-hook (in that order).
-
-You can send text to the inferior Coq process from other buffers
-containing Coq source.
-
-Functions and key bindings (Learn more keys with `C-c C-h'):
- C-return ('M-x coq-send-line) send the current line.
- C-c C-r (`M-x coq-send-region') send the current region.
- C-c C-a (`M-x coq-send-abort') send the command \"Abort\".
- C-c C-t (`M-x coq-send-restart') send the command \"Restart\".
- C-c C-s (`M-x coq-send-show') send the command \"Show\".
- C-c C-u (`M-x coq-send-undo') send the command \"Undo\".
- C-c C-v (`M-x coq-check-region') run command \"Check\" on region.
- C-c . (`M-x coq-come-here') Restart and send until current point.
-"
- ;; Customise in inferior-coq-mode-hook
- (setq comint-prompt-regexp "^[^<]* < *")
- (coq-mode-variables)
- (setq mode-line-process '(":%s"))
- (setq comint-input-filter (function coq-input-filter))
- (setq comint-get-old-input (function coq-get-old-input)))
-
-(defcustom inferior-coq-filter-regexp "\\`\\s *\\S ?\\S ?\\s *\\'"
- "*Input matching this regexp are not saved on the history list.
-Defaults to a regexp ignoring all inputs of 0, 1, or 2 letters."
- :type 'regexp
- :group 'inferior-coq)
-
-(defun coq-input-filter (str)
- "Don't save anything matching `inferior-coq-filter-regexp'."
- (not (string-match inferior-coq-filter-regexp str)))
-
-(defun coq-get-old-input ()
- "Snarf the sexp ending at point."
- (save-excursion
- (let ((end (point)))
- (backward-sexp)
- (buffer-substring (point) end))))
-
-(defun coq-args-to-list (string)
- (let ((where (string-match "[ \t]" string)))
- (cond ((null where) (list string))
- ((not (= where 0))
- (cons (substring string 0 where)
- (coq-args-to-list (substring string (+ 1 where)
- (length string)))))
- (t (let ((pos (string-match "[^ \t]" string)))
- (if (null pos)
- nil
- (coq-args-to-list (substring string pos
- (length string)))))))))
-
-;;;###autoload
-(defun run-coq (cmd)
- "Run an inferior Coq process, input and output via buffer *coq*.
-If there is a process already running in `*coq*', switch to that buffer.
-With argument, allows you to edit the command line (default is value
-of `coq-program-name'). Runs the hooks `inferior-coq-mode-hook'
-\(after the `comint-mode-hook' is run).
-\(Type \\[describe-mode] in the process buffer for a list of commands.)"
-
- (interactive (list (if current-prefix-arg
- (read-string "Run Coq: " coq-program-name)
- coq-program-name)))
- (if (not (comint-check-proc "*coq*"))
- (let ((cmdlist (coq-args-to-list cmd)))
- (set-buffer (apply 'make-comint "coq" (car cmdlist)
- nil (cdr cmdlist)))
- (inferior-coq-mode)))
- (setq coq-program-name cmd)
- (setq coq-buffer "*coq*")
- (switch-to-buffer "*coq*"))
-;;;###autoload (add-hook 'same-window-buffer-names "*coq*")
-
-;;;###autoload
-(defun run-coq-other-window (cmd)
- "Run an inferior Coq process, input and output via buffer *coq*.
-If there is a process already running in `*coq*', switch to that buffer.
-With argument, allows you to edit the command line (default is value
-of `coq-program-name'). Runs the hooks `inferior-coq-mode-hook'
-\(after the `comint-mode-hook' is run).
-\(Type \\[describe-mode] in the process buffer for a list of commands.)"
-
- (interactive (list (if current-prefix-arg
- (read-string "Run Coq: " coq-program-name)
- coq-program-name)))
- (if (not (comint-check-proc "*coq*"))
- (let ((cmdlist (coq-args-to-list cmd)))
- (set-buffer (apply 'make-comint "coq" (car cmdlist)
- nil (cdr cmdlist)))
- (inferior-coq-mode)))
- (setq coq-program-name cmd)
- (setq coq-buffer "*coq*")
- (pop-to-buffer "*coq*"))
-;;;###autoload (add-hook 'same-window-buffer-names "*coq*")
-
-(defun run-coq-other-frame (cmd)
- "Run an inferior Coq process, input and output via buffer *coq*.
-If there is a process already running in `*coq*', switch to that buffer.
-With argument, allows you to edit the command line (default is value
-of `coq-program-name'). Runs the hooks `inferior-coq-mode-hook'
-\(after the `comint-mode-hook' is run).
-\(Type \\[describe-mode] in the process buffer for a list of commands.)"
-
- (interactive (list (if current-prefix-arg
- (read-string "Run Coq: " coq-program-name)
- coq-program-name)))
- (if (not (comint-check-proc "*coq*"))
- (let ((cmdlist (coq-args-to-list cmd)))
- (set-buffer (apply 'make-comint "coq" (car cmdlist)
- nil (cdr cmdlist)))
- (inferior-coq-mode)))
- (setq coq-program-name cmd)
- (setq coq-buffer "*coq*")
- (switch-to-buffer-other-frame "*coq*"))
-
-(defun switch-to-coq (eob-p)
- "Switch to the coq process buffer.
-With argument, position cursor at end of buffer."
- (interactive "P")
- (if (get-buffer coq-buffer)
- (pop-to-buffer coq-buffer)
- (error "No current process buffer. See variable `coq-buffer'"))
- (cond (eob-p
- (push-mark)
- (goto-char (point-max)))))
-
-(defun coq-send-region (start end)
- "Send the current region to the inferior Coq process."
- (interactive "r")
- (comint-send-region (coq-proc) start end)
- (comint-send-string (coq-proc) "\n"))
-
-(defun coq-send-line ()
- "Send the current line to the Coq process."
- (interactive)
- (save-excursion
- (end-of-line)
- (let ((end (point)))
- (beginning-of-line)
- (coq-send-region (point) end)))
- (forward-line 1))
-
-(defun coq-send-abort ()
- "Send the command \"Abort.\" to the inferior Coq process."
- (interactive)
- (comint-send-string (coq-proc) "Abort.\n"))
-
-(defun coq-send-restart ()
- "Send the command \"Restart.\" to the inferior Coq process."
- (interactive)
- (comint-send-string (coq-proc) "Restart.\n"))
-
-(defun coq-send-undo ()
- "Reset coq to the initial state and send the region between the
- beginning of file and the point."
- (interactive)
- (comint-send-string (coq-proc) "Undo.\n"))
-
-(defun coq-check-region (start end)
- "Run the commmand \"Check\" on the current region."
- (interactive "r")
- (comint-proc-query (coq-proc)
- (concat "Check "
- (buffer-substring start end)
- ".\n")))
-
-(defun coq-send-show ()
- "Send the command \"Show.\" to the inferior Coq process."
- (interactive)
- (comint-send-string (coq-proc) "Show.\n"))
-
-(defun coq-come-here ()
- "Reset coq to the initial state and send the region between the
- beginning of file and the point."
- (interactive)
- (comint-send-string (coq-proc) "Reset Initial.\n")
- (coq-send-region 1 (point)))
-
-(defvar coq-buffer nil "*The current coq process buffer.")
-
-(defun coq-proc ()
- "Return the current coq process. See variable `coq-buffer'."
- (let ((proc (get-buffer-process (if (eq major-mode 'inferior-coq-mode)
- (current-buffer)
- coq-buffer))))
- (or proc
- (error "No current process. See variable `coq-buffer'"))))
-
-(defcustom inferior-coq-load-hook nil
- "This hook is run when inferior-coq is loaded in.
-This is a good place to put keybindings."
- :type 'hook
- :group 'inferior-coq)
-
-(run-hooks 'inferior-coq-load-hook)
-
-(provide 'inferior-coq)
diff --git a/tools/make-both-single-timing-files.py b/tools/make-both-single-timing-files.py
index c6af2ff1f8..32c52c7a17 100755
--- a/tools/make-both-single-timing-files.py
+++ b/tools/make-both-single-timing-files.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python
import sys
from TimeFileMaker import *
diff --git a/tools/make-both-time-files.py b/tools/make-both-time-files.py
index 6434296793..f730a8d6bd 100755
--- a/tools/make-both-time-files.py
+++ b/tools/make-both-time-files.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python
import sys
from TimeFileMaker import *
diff --git a/tools/make-one-time-file.py b/tools/make-one-time-file.py
index c9905249e6..e66136df9d 100755
--- a/tools/make-one-time-file.py
+++ b/tools/make-one-time-file.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python
import sys
from TimeFileMaker import *
diff --git a/toplevel/coqargs.ml b/toplevel/coqargs.ml
index 89602c9b56..113ba3684c 100644
--- a/toplevel/coqargs.ml
+++ b/toplevel/coqargs.ml
@@ -68,6 +68,7 @@ type coq_cmdopts = {
impredicative_set : Declarations.set_predicativity;
stm_flags : Stm.AsyncOpts.stm_opt;
debug : bool;
+ diffs_set : bool;
time : bool;
filter_opts : bool;
@@ -117,6 +118,7 @@ let init_args = {
impredicative_set = Declarations.PredicativeSet;
stm_flags = Stm.AsyncOpts.default_opts;
debug = false;
+ diffs_set = false;
time = false;
filter_opts = false;
@@ -423,7 +425,7 @@ let parse_args arglist : coq_cmdopts * string list =
|"-worker-id" -> set_worker_id opt (next ()); oval
|"-compat" ->
- let v = G_vernac.parse_compat_version ~allow_old:false (next ()) in
+ let v = G_vernac.parse_compat_version (next ()) in
Flags.compat_version := v;
add_compat_require oval v
@@ -526,6 +528,12 @@ let parse_args arglist : coq_cmdopts * string list =
|"-color" -> set_color oval (next ())
|"-config"|"--config" -> { oval with print_config = true }
|"-debug" -> Coqinit.set_debug (); oval
+ |"-diffs" -> let opt = next () in
+ if List.exists (fun x -> opt = x) ["off"; "on"; "removed"] then
+ Proof_diffs.write_diffs_option opt
+ else
+ (prerr_endline ("Error: on|off|removed expected after -diffs"); exit 1);
+ { oval with diffs_set = true }
|"-stm-debug" -> Stm.stm_debug := true; oval
|"-emacs" -> set_emacs oval
|"-filteropts" -> { oval with filter_opts = true }
diff --git a/toplevel/coqargs.mli b/toplevel/coqargs.mli
index 9fb6219a61..7b0cdcf127 100644
--- a/toplevel/coqargs.mli
+++ b/toplevel/coqargs.mli
@@ -43,6 +43,7 @@ type coq_cmdopts = {
impredicative_set : Declarations.set_predicativity;
stm_flags : Stm.AsyncOpts.stm_opt;
debug : bool;
+ diffs_set : bool;
time : bool;
filter_opts : bool;
diff --git a/toplevel/coqloop.ml b/toplevel/coqloop.ml
index d7ede1c2ee..59a464a22e 100644
--- a/toplevel/coqloop.ml
+++ b/toplevel/coqloop.ml
@@ -23,7 +23,7 @@ type input_buffer = {
mutable str : Bytes.t; (* buffer of already read characters *)
mutable len : int; (* number of chars in the buffer *)
mutable bols : int list; (* offsets in str of beginning of lines *)
- mutable tokens : Pcoq.Gram.coq_parsable; (* stream of tokens *)
+ mutable tokens : Pcoq.Parsable.t; (* stream of tokens *)
mutable start : int } (* stream count of the first char of the buffer *)
(* Double the size of the buffer. *)
@@ -76,7 +76,7 @@ let reset_input_buffer doc ic ibuf =
ibuf.str <- Bytes.empty;
ibuf.len <- 0;
ibuf.bols <- [];
- ibuf.tokens <- Pcoq.Gram.parsable (Stream.from (prompt_char doc ic ibuf));
+ ibuf.tokens <- Pcoq.Parsable.make (Stream.from (prompt_char doc ic ibuf));
ibuf.start <- 0
(* Functions to print underlined locations from an input buffer. *)
@@ -228,7 +228,7 @@ let top_buffer =
str = Bytes.empty;
len = 0;
bols = [];
- tokens = Pcoq.Gram.parsable (Stream.of_list []);
+ tokens = Pcoq.Parsable.make (Stream.of_list []);
start = 0 }
let set_prompt prompt =
@@ -253,7 +253,7 @@ let parse_to_dot =
let rec discard_to_dot () =
try
- Pcoq.Gram.entry_parse parse_to_dot top_buffer.tokens
+ Pcoq.Entry.parse parse_to_dot top_buffer.tokens
with
| Token.Error _ | CLexer.Error.E _ -> discard_to_dot ()
| Stm.End_of_input -> raise Stm.End_of_input
@@ -318,12 +318,6 @@ let loop_flush_all () =
Format.pp_print_flush !Topfmt.std_ft ();
Format.pp_print_flush !Topfmt.err_ft ()
-let pr_open_cur_subgoals () =
- try
- let proof = Proof_global.give_me_the_proof () in
- Printer.pr_open_subgoals ~proof
- with Proof_global.NoCurrentProof -> Pp.str ""
-
(* Goal equality heuristic. *)
let pequal cmp1 cmp2 (a1,a2) (b1,b2) = cmp1 a1 b1 && cmp2 a2 b2
let evleq e1 e2 = CList.equal Evar.equal e1 e2
@@ -336,17 +330,33 @@ let cproof p1 p2 =
let drop_last_doc = ref None
+(* todo: could add other Set/Unset commands, such as "Printing Universes" *)
+let print_anyway_opts = [
+ [ "Diffs" ];
+ ]
+
+let print_anyway c =
+ let open Vernacexpr in
+ match c with
+ | VernacExpr (_, VernacSetOption (_, opt, _))
+ | VernacExpr (_, VernacUnsetOption (_, opt)) ->
+ List.mem opt print_anyway_opts
+ | _ -> false
+
(* We try to behave better when goal printing raises an exception
[usually Ctrl-C]
This is mostly a hack as we should protect printing in a more
generic way, but that'll do for now *)
-let top_goal_print oldp newp =
+let top_goal_print ~doc c oldp newp =
try
let proof_changed = not (Option.equal cproof oldp newp) in
- let print_goals = not !Flags.quiet &&
- proof_changed && Proof_global.there_are_pending_proofs () in
- if print_goals then Feedback.msg_notice (pr_open_cur_subgoals ())
+ let print_goals = proof_changed && Proof_global.there_are_pending_proofs () ||
+ print_anyway c in
+ if not !Flags.quiet && print_goals then begin
+ let dproof = Stm.get_prev_proof ~doc (Stm.get_current_state ~doc) in
+ Printer.print_and_diff dproof newp
+ end
with
| exn ->
let (e, info) = CErrors.push exn in
@@ -382,7 +392,7 @@ let rec vernac_loop ~state =
else (Feedback.msg_warning (str "There is no ML toplevel."); vernac_loop ~state)
| {v=VernacControl c; loc} ->
let nstate = Vernac.process_expr ~state (make ?loc c) in
- top_goal_print state.proof nstate.proof;
+ top_goal_print ~doc:state.doc c state.proof nstate.proof;
vernac_loop ~state:nstate
with
| Stm.End_of_input ->
diff --git a/toplevel/coqloop.mli b/toplevel/coqloop.mli
index 5c07a8bf3b..b11f13d3cb 100644
--- a/toplevel/coqloop.mli
+++ b/toplevel/coqloop.mli
@@ -18,7 +18,7 @@ type input_buffer = {
mutable str : Bytes.t; (** buffer of already read characters *)
mutable len : int; (** number of chars in the buffer *)
mutable bols : int list; (** offsets in str of begining of lines *)
- mutable tokens : Pcoq.Gram.coq_parsable; (** stream of tokens *)
+ mutable tokens : Pcoq.Parsable.t; (** stream of tokens *)
mutable start : int } (** stream count of the first char of the buffer *)
(** The input buffer of stdin. *)
diff --git a/toplevel/coqtop.ml b/toplevel/coqtop.ml
index e979d0e544..8cd262c6d6 100644
--- a/toplevel/coqtop.ml
+++ b/toplevel/coqtop.ml
@@ -339,8 +339,8 @@ let do_vio opts =
(******************************************************************************)
(* Color Options *)
(******************************************************************************)
-let init_color color_mode =
- let has_color = match color_mode with
+let init_color opts =
+ let has_color = match opts.color with
| `OFF -> false
| `ON -> true
| `AUTO ->
@@ -350,26 +350,23 @@ let init_color color_mode =
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.default_styles ();
- Topfmt.init_terminal_output ~color:true
- | Some "" ->
- (** No color output *)
- Topfmt.init_terminal_output ~color:false
- | Some s ->
- (** Overwrite all colors *)
- Topfmt.parse_color_config s;
- Topfmt.init_terminal_output ~color:true
- end
- else
- Topfmt.init_terminal_output ~color:false
+ let term_color =
+ if has_color then begin
+ let colors = try Some (Sys.getenv "COQ_COLORS") with Not_found -> None in
+ match colors with
+ | None -> Topfmt.default_styles (); true (** Default colors *)
+ | Some "" -> false (** No color output *)
+ | Some s -> Topfmt.parse_color_config s; true (** Overwrite all colors *)
+ end
+ else
+ false
+ in
+ if Proof_diffs.show_diffs () && not term_color && not opts.batch_mode then
+ (prerr_endline "Error: -diffs requires enabling -color"; exit 1);
+ Topfmt.init_terminal_output ~color:term_color
let print_style_tags opts =
- let () = init_color opts.color in
+ let () = init_color opts in
let tags = Topfmt.dump_tags () in
let iter (t, st) =
let opt = Terminal.eval st ^ t ^ Terminal.reset ^ "\n" in
@@ -387,7 +384,7 @@ let print_style_tags opts =
(** GC tweaking *)
(** Coq is a heavy user of persistent data structures and symbolic ASTs, so the
- minor heap is heavily sollicited. Unfortunately, the default size is far too
+ minor heap is heavily solicited. Unfortunately, the default size is far too
small, so we enlarge it a lot (128 times larger).
To better handle huge memory consumers, we also augment the default major
@@ -520,7 +517,7 @@ type custom_toplevel = {
}
let coqtop_init ~opts extra =
- init_color opts.color;
+ init_color opts;
CoqworkmgrApi.(init !async_proofs_worker_priority);
opts, extra
diff --git a/toplevel/g_toplevel.ml4 b/toplevel/g_toplevel.mlg
index e3cefe2363..5aba3d6b0b 100644
--- a/toplevel/g_toplevel.ml4
+++ b/toplevel/g_toplevel.mlg
@@ -8,6 +8,7 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
+{
open Pcoq
open Pcoq.Prim
open Vernacexpr
@@ -20,28 +21,34 @@ type vernac_toplevel =
| VernacControl of vernac_control
module Toplevel_ : sig
- val vernac_toplevel : vernac_toplevel CAst.t Gram.entry
+ val vernac_toplevel : vernac_toplevel CAst.t Entry.t
end = struct
- let gec_vernac s = Gram.entry_create ("toplevel:" ^ s)
+ let gec_vernac s = Entry.create ("toplevel:" ^ s)
let vernac_toplevel = gec_vernac "vernac_toplevel"
end
open Toplevel_
-GEXTEND Gram
+}
+
+GRAMMAR EXTEND Gram
GLOBAL: vernac_toplevel;
vernac_toplevel: FIRST
- [ [ IDENT "Drop"; "." -> CAst.make VernacDrop
- | IDENT "Quit"; "." -> CAst.make VernacQuit
+ [ [ IDENT "Drop"; "." -> { CAst.make VernacDrop }
+ | IDENT "Quit"; "." -> { CAst.make VernacQuit }
| IDENT "Backtrack"; n = natural ; m = natural ; p = natural; "." ->
- CAst.make (VernacBacktrack (n,m,p))
+ { CAst.make (VernacBacktrack (n,m,p)) }
| cmd = Pvernac.main_entry ->
- match cmd with
+ { match cmd with
| None -> raise Stm.End_of_input
- | Some (loc,c) -> CAst.make ~loc (VernacControl c)
+ | Some (loc,c) -> CAst.make ~loc (VernacControl c) }
]
]
;
END
-let parse_toplevel pa = Pcoq.Gram.entry_parse vernac_toplevel pa
+{
+
+let parse_toplevel pa = Pcoq.Entry.parse vernac_toplevel pa
+
+}
diff --git a/toplevel/usage.ml b/toplevel/usage.ml
index 504ffa521b..d85fed5f43 100644
--- a/toplevel/usage.ml
+++ b/toplevel/usage.ml
@@ -72,7 +72,8 @@ let print_usage_channel co command =
\n -boot boot mode (implies -q and -batch)\
\n -bt print backtraces (requires configure debug flag)\
\n -debug debug mode (implies -bt)\
-\n -stm-debug STM debug mode (will trace every transaction) \
+\n -diffs (on|off|removed) highlight differences between proof steps\
+\n -stm-debug STM debug mode (will trace every transaction)\
\n -emacs tells Coq it is executed under Emacs\
\n -noglob do not dump globalizations\
\n -dump-glob f dump globalizations in file f (to be used by coqdoc)\
diff --git a/toplevel/vernac.ml b/toplevel/vernac.ml
index c1bbb20d5e..c914bbecff 100644
--- a/toplevel/vernac.ml
+++ b/toplevel/vernac.ml
@@ -121,7 +121,7 @@ let load_vernac_core ~echo ~check ~interactive ~state file =
let in_echo = if echo then Some (open_utf8_file_in file) else None in
let input_cleanup () = close_in in_chan; Option.iter close_in in_echo in
- let in_pa = Pcoq.Gram.parsable ~file:(Loc.InFile file) (Stream.of_channel in_chan) in
+ let in_pa = Pcoq.Parsable.make ~file:(Loc.InFile file) (Stream.of_channel in_chan) in
let rstate = ref state in
(* For beautify, list of parsed sids *)
let rids = ref [] in
@@ -159,12 +159,12 @@ let load_vernac_core ~echo ~check ~interactive ~state file =
rstate := state;
done;
input_cleanup ();
- !rstate, !rids, Pcoq.Gram.comment_state in_pa
+ !rstate, !rids, Pcoq.Parsable.comment_state in_pa
with any -> (* whatever the exception *)
let (e, info) = CErrors.push any in
input_cleanup ();
match e with
- | Stm.End_of_input -> !rstate, !rids, Pcoq.Gram.comment_state in_pa
+ | Stm.End_of_input -> !rstate, !rids, Pcoq.Parsable.comment_state in_pa
| reraise -> iraise (e, info)
let process_expr ~state loc_ast =
diff --git a/vernac/assumptions.mli b/vernac/assumptions.mli
index 0e2b0c80e8..751e79d89c 100644
--- a/vernac/assumptions.mli
+++ b/vernac/assumptions.mli
@@ -23,7 +23,7 @@ open Printer
val traverse :
Label.t -> constr ->
(Refset_env.t * Refset_env.t Refmap_env.t *
- (Label.t * Context.Rel.t * types) list Refmap_env.t)
+ (Label.t * Constr.rel_context * types) list Refmap_env.t)
(** Collects all the assumptions (optionally including opaque definitions)
on which a term relies (together with their type). The above warning of
diff --git a/vernac/auto_ind_decl.ml b/vernac/auto_ind_decl.ml
index ee578669c2..e33aa38173 100644
--- a/vernac/auto_ind_decl.ml
+++ b/vernac/auto_ind_decl.ml
@@ -355,7 +355,7 @@ let destruct_ind sigma c =
then avoid should be
[| lb_An ... lb _A1 (resp. bl_An ... bl_A1)
eq_An .... eq_A1 An ... A1 |]
-so from Ai we can find the the correct eq_Ai bl_ai or lb_ai
+so from Ai we can find the correct eq_Ai bl_ai or lb_ai
*)
(* used in the leib -> bool side*)
let do_replace_lb mode lb_scheme_key aavoid narg p q =
diff --git a/vernac/class.ml b/vernac/class.ml
index 1337267020..614b2181d9 100644
--- a/vernac/class.ml
+++ b/vernac/class.ml
@@ -73,7 +73,7 @@ let check_reference_arity ref =
let check_arity = function
| CL_FUN | CL_SORT -> ()
| CL_CONST cst -> check_reference_arity (ConstRef cst)
- | CL_PROJ cst -> check_reference_arity (ConstRef cst)
+ | CL_PROJ p -> check_reference_arity (ConstRef (Projection.Repr.constant p))
| CL_SECVAR id -> check_reference_arity (VarRef id)
| CL_IND kn -> check_reference_arity (IndRef kn)
@@ -92,8 +92,8 @@ let uniform_cond sigma ctx lt =
let class_of_global = function
| ConstRef sp ->
- if Environ.is_projection sp (Global.env ())
- then CL_PROJ sp else CL_CONST sp
+ (match Recordops.find_primitive_projection sp with
+ | Some p -> CL_PROJ p | None -> CL_CONST sp)
| IndRef sp -> CL_IND sp
| VarRef id -> CL_SECVAR id
| ConstructRef _ as c ->
@@ -143,8 +143,8 @@ let get_target t ind =
CL_FUN
else
match pi1 (find_class_type Evd.empty (EConstr.of_constr t)) with
- | CL_CONST p when Environ.is_projection p (Global.env ()) ->
- CL_PROJ p
+ | CL_CONST p when Recordops.is_primitive_projection p ->
+ CL_PROJ (Option.get @@ Recordops.find_primitive_projection p)
| x -> x
let strength_of_cl = function
@@ -165,7 +165,8 @@ let get_strength stre ref cls clt =
let ident_key_of_class = function
| CL_FUN -> "Funclass"
| CL_SORT -> "Sortclass"
- | CL_CONST sp | CL_PROJ sp -> Label.to_string (Constant.label sp)
+ | CL_CONST sp -> Label.to_string (Constant.label sp)
+ | CL_PROJ sp -> Label.to_string (Projection.Repr.label sp)
| CL_IND (sp,_) -> Label.to_string (MutInd.label sp)
| CL_SECVAR id -> Id.to_string id
@@ -303,12 +304,12 @@ let try_add_new_coercion_with_source ref ~local poly ~source =
try_add_new_coercion_core ref ~local poly (Some source) None false
let add_coercion_hook poly local ref =
- let stre = match local with
+ let local = match local with
+ | Discharge
| Local -> true
| Global -> false
- | Discharge -> assert false
in
- let () = try_add_new_coercion ref ~local:stre poly in
+ let () = try_add_new_coercion ref ~local poly in
let msg = pr_global_env Id.Set.empty ref ++ str " is now a coercion" in
Flags.if_verbose Feedback.msg_info msg
diff --git a/vernac/classes.ml b/vernac/classes.ml
index 382d18b095..bf734ab36d 100644
--- a/vernac/classes.ml
+++ b/vernac/classes.ml
@@ -42,7 +42,7 @@ let typeclasses_db = "typeclass_instances"
let set_typeclass_transparency c local b =
Hints.add_hints ~local [typeclasses_db]
- (Hints.HintsTransparencyEntry ([c], b))
+ (Hints.HintsTransparencyEntry (Vernacexpr.HintsReferences [c], b))
let _ =
Hook.set Typeclasses.add_instance_hint_hook
@@ -116,9 +116,8 @@ let instance_hook k info global imps ?hook cst =
let declare_instance_constant k info global imps ?hook id decl poly sigma term termtype =
let kind = IsDefinition Instance in
let sigma =
- let env = Global.env () in
- let levels = Univ.LSet.union (Univops.universes_of_constr env termtype)
- (Univops.universes_of_constr env term) in
+ let levels = Univ.LSet.union (Univops.universes_of_constr termtype)
+ (Univops.universes_of_constr term) in
Evd.restrict_universe_context sigma levels
in
let uctx = Evd.check_univ_decl ~poly sigma decl in
diff --git a/vernac/classes.mli b/vernac/classes.mli
index bd30b2d60e..9c37364cb0 100644
--- a/vernac/classes.mli
+++ b/vernac/classes.mli
@@ -16,9 +16,9 @@ open Libnames
(** Errors *)
-val mismatched_params : env -> constr_expr list -> Context.Rel.t -> 'a
+val mismatched_params : env -> constr_expr list -> Constr.rel_context -> 'a
-val mismatched_props : env -> constr_expr list -> Context.Rel.t -> 'a
+val mismatched_props : env -> constr_expr list -> Constr.rel_context -> 'a
(** Instance declaration *)
diff --git a/vernac/comAssumption.ml b/vernac/comAssumption.ml
index a8ac528466..750ed35cbc 100644
--- a/vernac/comAssumption.ml
+++ b/vernac/comAssumption.ml
@@ -163,7 +163,7 @@ let do_assumptions kind nl l =
let nf_evar c = EConstr.to_constr sigma c in
let uvars, l = List.fold_left_map (fun uvars (coe,t,imps) ->
let t = nf_evar t in
- let uvars = Univ.LSet.union uvars (Univops.universes_of_constr env t) in
+ let uvars = Univ.LSet.union uvars (Univops.universes_of_constr t) in
uvars, (coe,t,imps))
Univ.LSet.empty l
in
diff --git a/vernac/comDefinition.ml b/vernac/comDefinition.ml
index f55c852c0d..a8d7946429 100644
--- a/vernac/comDefinition.ml
+++ b/vernac/comDefinition.ml
@@ -93,7 +93,7 @@ let interp_definition pl bl poly red_option c ctypopt =
let tyopt = Option.map (fun ty -> Term.it_mkProd_or_LetIn (EConstr.to_constr ~abort_on_undefined_evars:false evd ty) ctx) tyopt in
(* Keep only useful universes. *)
let uvars_fold uvars c =
- Univ.LSet.union uvars (universes_of_constr env evd (of_constr c))
+ Univ.LSet.union uvars (universes_of_constr evd (of_constr c))
in
let uvars = List.fold_left uvars_fold Univ.LSet.empty (Option.List.cons tyopt [c]) in
let evd = Evd.restrict_universe_context evd uvars in
diff --git a/vernac/comFixpoint.ml b/vernac/comFixpoint.ml
index 1d1cc62dea..37258c2d45 100644
--- a/vernac/comFixpoint.ml
+++ b/vernac/comFixpoint.ml
@@ -262,7 +262,7 @@ let declare_fixpoint local poly ((fixnames,fixdefs,fixtypes),pl,ctx,fiximps) ind
let env = Global.env() in
let indexes = search_guard env indexes fixdecls in
let fiximps = List.map (fun (n,r,p) -> r) fiximps in
- let vars = Univops.universes_of_constr env (mkFix ((indexes,0),fixdecls)) in
+ let vars = Univops.universes_of_constr (mkFix ((indexes,0),fixdecls)) in
let fixdecls =
List.map_i (fun i _ -> mkFix ((indexes,i),fixdecls)) 0 fixnames in
let evd = Evd.from_ctx ctx in
@@ -295,8 +295,7 @@ let declare_cofixpoint local poly ((fixnames,fixdefs,fixtypes),pl,ctx,fiximps) n
let fixdefs = List.map Option.get fixdefs in
let fixdecls = prepare_recursive_declaration fixnames fixtypes fixdefs in
let fixdecls = List.map_i (fun i _ -> mkCoFix (i,fixdecls)) 0 fixnames in
- let env = Global.env () in
- let vars = Univops.universes_of_constr env (List.hd fixdecls) in
+ let vars = Univops.universes_of_constr (List.hd fixdecls) in
let fixdecls = List.map Safe_typing.mk_pure_proof fixdecls in
let fiximps = List.map (fun (len,imps,idx) -> imps) fiximps in
let evd = Evd.from_ctx ctx in
diff --git a/vernac/comFixpoint.mli b/vernac/comFixpoint.mli
index f51bfbad59..b1a9c8a5a3 100644
--- a/vernac/comFixpoint.mli
+++ b/vernac/comFixpoint.mli
@@ -82,12 +82,12 @@ val interp_fixpoint :
val declare_fixpoint :
locality -> polymorphic ->
recursive_preentry * UState.universe_decl * UState.t *
- (Context.Rel.t * Impargs.manual_implicits * int option) list ->
+ (Constr.rel_context * Impargs.manual_implicits * int option) list ->
Proof_global.lemma_possible_guards -> decl_notation list -> unit
val declare_cofixpoint : locality -> polymorphic ->
recursive_preentry * UState.universe_decl * UState.t *
- (Context.Rel.t * Impargs.manual_implicits * int option) list ->
+ (Constr.rel_context * Impargs.manual_implicits * int option) list ->
decl_notation list -> unit
(** Very private function, do not use *)
diff --git a/vernac/comInductive.ml b/vernac/comInductive.ml
index 6057c05f58..ad1ffa35a1 100644
--- a/vernac/comInductive.ml
+++ b/vernac/comInductive.ml
@@ -126,7 +126,7 @@ let make_conclusion_flexible sigma ty poly =
else sigma
let is_impredicative env u =
- u = Prop Null || (is_impredicative_set env && u = Prop Pos)
+ u = Prop || (is_impredicative_set env && u = Set)
let interp_ind_arity env sigma ind =
let c = intern_gen IsType env sigma ind.ind_arity in
@@ -146,7 +146,6 @@ let interp_cstrs env sigma impls mldata arity ind =
let sigma, (ctyps'', cimpls) =
on_snd List.split @@
List.fold_left_map (fun sigma l ->
- on_snd (on_fst EConstr.Unsafe.to_constr) @@
interp_type_evars_impls env sigma ~impls l) sigma ctyps' in
sigma, (cnames, ctyps'', cimpls)
@@ -245,7 +244,7 @@ let solve_constraints_system levels level_bounds =
let inductive_levels env evd poly arities inds =
let destarities = List.map (fun x -> x, Reduction.dest_arity env x) arities in
let levels = List.map (fun (x,(ctx,a)) ->
- if a = Prop Null then None
+ if a = Prop then None
else Some (univ_of_sort a)) destarities
in
let cstrs_levels, min_levels, sizes =
@@ -298,14 +297,14 @@ let inductive_levels env evd poly arities inds =
(** "Polymorphic" type constraint and more than one constructor,
should not land in Prop. Add constraint only if it would
land in Prop directly (no informative arguments as well). *)
- Evd.set_leq_sort env evd (Prop Pos) du
+ Evd.set_leq_sort env evd Set du
else evd
in
let duu = Sorts.univ_of_sort du in
let evd =
if not (Univ.is_small_univ duu) && Univ.Universe.equal cu duu then
if is_flexible_sort evd duu && not (Evd.check_leq evd Univ.type0_univ duu) then
- Evd.set_eq_sort env evd (Prop Null) du
+ Evd.set_eq_sort env evd Prop du
else evd
else Evd.set_eq_sort env evd (Type cu) du
in
@@ -327,14 +326,17 @@ let check_param = function
| CLocalPattern {CAst.loc} ->
Loc.raise ?loc (Stream.Error "pattern with quote not allowed here")
-let interp_mutual_inductive (paramsl,indl) notations cum poly prv finite =
+let interp_mutual_inductive_gen env0 (uparamsl,paramsl,indl) notations cum poly prv finite =
check_all_names_different indl;
List.iter check_param paramsl;
- let env0 = Global.env() in
+ if not (List.is_empty uparamsl) && not (List.is_empty notations)
+ then user_err (str "Inductives with uniform parameters may not have attached notations.");
let pl = (List.hd indl).ind_univs in
let sigma, decl = interp_univ_decl_opt env0 pl in
+ let sigma, (uimpls, ((env_uparams, ctx_uparams), useruimpls)) =
+ interp_context_evars env0 sigma uparamsl in
let sigma, (impls, ((env_params, ctx_params), userimpls)) =
- interp_context_evars env0 sigma paramsl
+ interp_context_evars ~impl_env:uimpls env_uparams sigma paramsl
in
let indnames = List.map (fun ind -> ind.ind_name) indl in
@@ -346,15 +348,15 @@ let interp_mutual_inductive (paramsl,indl) notations cum poly prv finite =
let sigma, arities = List.fold_left_map (fun sigma -> interp_ind_arity env_params sigma) sigma indl in
let fullarities = List.map (fun (c, _, _) -> EConstr.it_mkProd_or_LetIn c ctx_params) arities in
- let env_ar = push_types env0 indnames fullarities in
+ let env_ar = push_types env_uparams indnames fullarities in
let env_ar_params = EConstr.push_rel_context ctx_params env_ar in
(* Compute interpretation metadatas *)
let indimpls = List.map (fun (_, _, impls) -> userimpls @
lift_implicits (Context.Rel.nhyps ctx_params) impls) arities in
let arities = List.map pi1 arities and aritypoly = List.map pi2 arities in
- let impls = compute_internalization_env env0 sigma ~impls (Inductive (params,true)) indnames fullarities indimpls in
- let ntn_impls = compute_internalization_env env0 sigma (Inductive (params,true)) indnames fullarities indimpls in
+ let impls = compute_internalization_env env_uparams sigma ~impls (Inductive (params,true)) indnames fullarities indimpls in
+ let ntn_impls = compute_internalization_env env_uparams sigma (Inductive (params,true)) indnames fullarities indimpls in
let mldatas = List.map2 (mk_mltype_data sigma env_params params) arities indnames in
let sigma, constructors =
@@ -365,6 +367,25 @@ let interp_mutual_inductive (paramsl,indl) notations cum poly prv finite =
List.fold_left3_map (fun sigma -> interp_cstrs env_ar_params sigma impls) sigma mldatas arities indl)
() in
+ (* generalize over the uniform parameters *)
+ let nparams = Context.Rel.length ctx_params in
+ let nuparams = Context.Rel.length ctx_uparams in
+ let uargs = Context.Rel.to_extended_vect EConstr.mkRel 0 ctx_uparams in
+ let uparam_subst =
+ List.init (List.length indl) EConstr.(fun i -> mkApp (mkRel (i + 1 + nuparams), uargs))
+ @ List.init nuparams EConstr.(fun i -> mkRel (i + 1)) in
+ let generalize_constructor c = EConstr.Unsafe.to_constr (EConstr.Vars.substnl uparam_subst nparams c) in
+ let constructors = List.map (fun (cnames,ctypes,cimpls) ->
+ (cnames,List.map generalize_constructor ctypes,cimpls))
+ constructors
+ in
+ let ctx_params = ctx_params @ ctx_uparams in
+ let userimpls = useruimpls @ (lift_implicits (Context.Rel.nhyps ctx_uparams) userimpls) in
+ let indimpls = List.map (fun iimpl -> useruimpls @ (lift_implicits (Context.Rel.nhyps ctx_uparams) iimpl)) indimpls in
+ let fullarities = List.map (fun c -> EConstr.it_mkProd_or_LetIn c ctx_uparams) fullarities in
+ let env_ar = push_types env0 indnames fullarities in
+ let env_ar_params = EConstr.push_rel_context ctx_params env_ar in
+
(* Try further to solve evars, and instantiate them *)
let sigma = solve_remaining_evars all_and_fail_flags env_params sigma (Evd.from_env env_params) in
(* Compute renewed arities *)
@@ -423,6 +444,9 @@ let interp_mutual_inductive (paramsl,indl) notations cum poly prv finite =
InferCumulativity.infer_inductive env_ar mind_ent
else mind_ent), Evd.universe_binders sigma, impls
+let interp_mutual_inductive (paramsl,indl) notations cum poly prv finite =
+ interp_mutual_inductive_gen (Global.env()) ([],paramsl,indl) notations cum poly prv finite
+
(* Very syntactical equality *)
let eq_local_binders bl1 bl2 =
List.equal local_binder_eq bl1 bl2
@@ -505,10 +529,15 @@ type one_inductive_impls =
Impargs.manual_explicitation list (* for inds *)*
Impargs.manual_explicitation list list (* for constrs *)
-let do_mutual_inductive indl cum poly prv finite =
- let indl,coes,ntns = extract_mutual_inductive_declaration_components indl in
+type uniform_inductive_flag =
+ | UniformParameters
+ | NonUniformParameters
+
+let do_mutual_inductive indl cum poly prv ~uniform finite =
+ let (params,indl),coes,ntns = extract_mutual_inductive_declaration_components indl in
(* Interpret the types *)
- let mie,pl,impls = interp_mutual_inductive indl ntns cum poly prv finite in
+ let indl = match uniform with UniformParameters -> (params, [], indl) | NonUniformParameters -> ([], params, indl) in
+ let mie,pl,impls = interp_mutual_inductive_gen (Global.env()) indl ntns cum poly prv finite in
(* Declare the mutual inductive block with its associated schemes *)
ignore (declare_mutual_inductive_with_eliminations mie pl impls);
(* Declare the possible notations of inductive types *)
diff --git a/vernac/comInductive.mli b/vernac/comInductive.mli
index 7ae8e8f716..4e30ed7de5 100644
--- a/vernac/comInductive.mli
+++ b/vernac/comInductive.mli
@@ -19,9 +19,14 @@ open Decl_kinds
(** Entry points for the vernacular commands Inductive and CoInductive *)
+type uniform_inductive_flag =
+ | UniformParameters
+ | NonUniformParameters
+
val do_mutual_inductive :
(one_inductive_expr * decl_notation list) list -> cumulative_inductive_flag ->
- polymorphic -> private_flag -> Declarations.recursivity_kind -> unit
+ polymorphic -> private_flag -> uniform:uniform_inductive_flag ->
+ Declarations.recursivity_kind -> unit
(************************************************************************)
(** Internal API *)
diff --git a/vernac/comProgramFixpoint.ml b/vernac/comProgramFixpoint.ml
index eef7afbfba..102a98f046 100644
--- a/vernac/comProgramFixpoint.ml
+++ b/vernac/comProgramFixpoint.ml
@@ -187,7 +187,9 @@ let build_wellfounded (recname,pl,n,bl,arityc,body) poly r measure notation =
let sigma, def =
let sigma, h_a_term = Evarutil.new_global sigma (delayed_force fix_sub_ref) in
let sigma, h_e_term = Evarutil.new_evar env sigma
- ~src:(Loc.tag @@ Evar_kinds.QuestionMark (Evar_kinds.Define false,Anonymous)) wf_proof in
+ ~src:(Loc.tag @@ Evar_kinds.QuestionMark {
+ Evar_kinds.default_question_mark with Evar_kinds.qm_obligation=Evar_kinds.Define false;
+ }) wf_proof in
sigma, mkApp (h_a_term, [| argtyp ; wf_rel ; h_e_term; prop |])
in
let sigma, def = Typing.solve_evars env sigma def in
diff --git a/vernac/egramcoq.ml b/vernac/egramcoq.ml
index cc9be7b0e5..16101396cf 100644
--- a/vernac/egramcoq.ml
+++ b/vernac/egramcoq.ml
@@ -54,6 +54,17 @@ let default_pattern_levels =
let default_constr_levels = (default_levels, default_pattern_levels)
+let find_levels levels = function
+ | InConstrEntry -> levels, String.Map.find "constr" levels
+ | InCustomEntry s ->
+ try levels, String.Map.find s levels
+ with Not_found ->
+ String.Map.add s ([],[]) levels, ([],[])
+
+let save_levels levels custom lev =
+ let s = match custom with InConstrEntry -> "constr" | InCustomEntry s -> s in
+ String.Map.add s lev levels
+
(* At a same level, LeftA takes precedence over RightA and NoneA *)
(* In case, several associativity exists for a level, we make two levels, *)
(* first LeftA, then RightA and NoneA together *)
@@ -125,24 +136,24 @@ let rec list_mem_assoc_triple x = function
let register_empty_levels accu forpat levels =
let rec filter accu = function
| [] -> ([], accu)
- | n :: rem ->
+ | (where,n) :: rem ->
let rem, accu = filter accu rem in
- let (clev, plev) = accu in
+ let accu, (clev, plev) = find_levels accu where in
let levels = if forpat then plev else clev in
if not (list_mem_assoc_triple n levels) then
let nlev, ans = find_position_gen levels true None (Some n) in
let nlev = if forpat then (clev, nlev) else (nlev, plev) in
- ans :: rem, nlev
+ (where, ans) :: rem, save_levels accu where nlev
else rem, accu
in
filter accu levels
-let find_position accu forpat assoc level =
- let (clev, plev) = accu in
+let find_position accu custom forpat assoc level =
+ let accu, (clev, plev) = find_levels accu custom in
let levels = if forpat then plev else clev in
let nlev, ans = find_position_gen levels false assoc level in
let nlev = if forpat then (clev, nlev) else (nlev, plev) in
- (ans, nlev)
+ (ans, save_levels accu custom nlev)
(**************************************************************************)
(*
@@ -231,7 +242,7 @@ type (_, _) entry =
| TTName : ('self, lname) entry
| TTReference : ('self, qualid) entry
| TTBigint : ('self, Constrexpr.raw_natural_number) entry
-| TTConstr : prod_info * 'r target -> ('r, 'r) entry
+| TTConstr : notation_entry * prod_info * 'r target -> ('r, 'r) entry
| TTConstrList : prod_info * Tok.t list * 'r target -> ('r, 'r list) entry
| TTPattern : int -> ('self, cases_pattern_expr) entry
| TTOpenBinderList : ('self, local_binder_expr list) entry
@@ -239,17 +250,58 @@ type (_, _) entry =
type _ any_entry = TTAny : ('s, 'r) entry -> 's any_entry
+let constr_custom_entry : (string, Constrexpr.constr_expr) entry_command =
+ create_entry_command "constr" (fun s st -> [s], st)
+let pattern_custom_entry : (string, Constrexpr.cases_pattern_expr) entry_command =
+ create_entry_command "pattern" (fun s st -> [s], st)
+
+let custom_entry_locality = Summary.ref ~name:"LOCAL-CUSTOM-ENTRY" String.Set.empty
+(** If the entry is present then local *)
+
+let create_custom_entry ~local s =
+ if List.mem s ["constr";"pattern";"ident";"global";"binder";"bigint"] then
+ user_err Pp.(quote (str s) ++ str " is a reserved entry name.");
+ let sc = "constr:"^s in
+ let sp = "pattern:"^s in
+ let _ = extend_entry_command constr_custom_entry sc in
+ let _ = extend_entry_command pattern_custom_entry sp in
+ let () = if local then custom_entry_locality := String.Set.add s !custom_entry_locality in
+ ()
+
+let find_custom_entry s =
+ let sc = "constr:"^s in
+ let sp = "pattern:"^s in
+ try (find_custom_entry constr_custom_entry sc, find_custom_entry pattern_custom_entry sp)
+ with Not_found -> user_err Pp.(str "Undeclared custom entry: " ++ str s ++ str ".")
+
+let locality_of_custom_entry s = String.Set.mem s !custom_entry_locality
+
(* This computes the name of the level where to add a new rule *)
-let interp_constr_entry_key : type r. r target -> int -> r Gram.entry * int option =
- fun forpat level -> match forpat with
+let interp_constr_entry_key : type r. _ -> r target -> int -> r Entry.t * int option =
+ fun custom forpat level ->
+ match custom with
+ | InCustomEntry s ->
+ (let (entry_for_constr, entry_for_patttern) = find_custom_entry s in
+ match forpat with
+ | ForConstr -> entry_for_constr, Some level
+ | ForPattern -> entry_for_patttern, Some level)
+ | InConstrEntry ->
+ match forpat with
| ForConstr ->
if level = 200 then Constr.binder_constr, None
else Constr.operconstr, Some level
| ForPattern -> Constr.pattern, Some level
-let target_entry : type s. s target -> s Gram.entry = function
-| ForConstr -> Constr.operconstr
-| ForPattern -> Constr.pattern
+let target_entry : type s. notation_entry -> s target -> s Entry.t = function
+| InConstrEntry ->
+ (function
+ | ForConstr -> Constr.operconstr
+ | ForPattern -> Constr.pattern)
+| InCustomEntry s ->
+ let (entry_for_constr, entry_for_patttern) = find_custom_entry s in
+ function
+ | ForConstr -> entry_for_constr
+ | ForPattern -> entry_for_patttern
let is_self from e = match e with
| (NumLevel n, BorderProd (Right, _ (* Some(NonA|LeftA) *))) -> false
@@ -273,25 +325,25 @@ let make_sep_rules = function
let r = mkrule (List.rev tkl) in
Arules [r]
-let symbol_of_target : type s. _ -> _ -> _ -> s target -> (s, s) symbol = fun p assoc from forpat ->
- if is_binder_level from p then Aentryl (target_entry forpat, 200)
+let symbol_of_target : type s. _ -> _ -> _ -> _ -> s target -> (s, s) symbol = fun custom p assoc from forpat ->
+ if custom = InConstrEntry && is_binder_level from p then Aentryl (target_entry InConstrEntry forpat, "200")
else if is_self from p then Aself
else
- let g = target_entry forpat in
+ let g = target_entry custom forpat in
let lev = adjust_level assoc from p in
begin match lev with
| None -> Aentry g
| Some None -> Anext
- | Some (Some (lev, cur)) -> Aentryl (g, lev)
+ | Some (Some (lev, cur)) -> Aentryl (g, string_of_int lev)
end
let symbol_of_entry : type s r. _ -> _ -> (s, r) entry -> (s, r) symbol = fun assoc from typ -> match typ with
-| TTConstr (p, forpat) -> symbol_of_target p assoc from forpat
+| TTConstr (s, p, forpat) -> symbol_of_target s p assoc from forpat
| TTConstrList (typ', [], forpat) ->
- Alist1 (symbol_of_target typ' assoc from forpat)
+ Alist1 (symbol_of_target InConstrEntry typ' assoc from forpat)
| TTConstrList (typ', tkl, forpat) ->
- Alist1sep (symbol_of_target typ' assoc from forpat, make_sep_rules tkl)
-| TTPattern p -> Aentryl (Constr.pattern, p)
+ Alist1sep (symbol_of_target InConstrEntry typ' assoc from forpat, make_sep_rules tkl)
+| TTPattern p -> Aentryl (Constr.pattern, string_of_int p)
| TTClosedBinderList [] -> Alist1 (Aentry Constr.binder)
| TTClosedBinderList tkl -> Alist1sep (Aentry Constr.binder, make_sep_rules tkl)
| TTName -> Aentry Prim.name
@@ -303,9 +355,8 @@ let interp_entry forpat e = match e with
| ETProdName -> TTAny TTName
| ETProdReference -> TTAny TTReference
| ETProdBigint -> TTAny TTBigint
-| ETProdConstr p -> TTAny (TTConstr (p, forpat))
+| ETProdConstr (s,p) -> TTAny (TTConstr (s, p, forpat))
| ETProdPattern p -> TTAny (TTPattern p)
-| ETProdOther _ -> assert false (** not used *)
| ETProdConstrList (p, tkl) -> TTAny (TTConstrList (p, tkl, forpat))
| ETProdBinderList ETBinderOpen -> TTAny TTOpenBinderList
| ETProdBinderList (ETBinderClosed tkl) -> TTAny (TTClosedBinderList tkl)
@@ -420,20 +471,23 @@ let target_to_bool : type r. r target -> bool = function
| ForConstr -> false
| ForPattern -> true
-let prepare_empty_levels forpat (pos,p4assoc,name,reinit) =
+let prepare_empty_levels forpat (where,(pos,p4assoc,name,reinit)) =
let empty = (pos, [(name, p4assoc, [])]) in
- if forpat then ExtendRule (Constr.pattern, reinit, empty)
- else ExtendRule (Constr.operconstr, reinit, empty)
-
-let rec pure_sublevels : type a b c. int option -> (a, b, c) rule -> int list = fun level r -> match r with
-| Stop -> []
-| Next (rem, Aentryl (_, i)) ->
- let rem = pure_sublevels level rem in
- begin match level with
- | Some j when Int.equal i j -> rem
- | _ -> i :: rem
- end
-| Next (rem, _) -> pure_sublevels level rem
+ ExtendRule (target_entry where forpat, reinit, empty)
+
+let rec pure_sublevels' custom assoc from forpat level = function
+| [] -> []
+| GramConstrNonTerminal (e,_) :: rem ->
+ let rem = pure_sublevels' custom assoc from forpat level rem in
+ let push where p rem =
+ match symbol_of_target custom p assoc from forpat with
+ | Aentryl (_,i) when level <> Some (int_of_string i) -> (where,int_of_string i) :: rem
+ | _ -> rem in
+ (match e with
+ | ETProdPattern i -> push InConstrEntry (NumLevel i,InternalProd) rem
+ | ETProdConstr (s,p) -> push s p rem
+ | _ -> rem)
+| (GramConstrTerminal _ | GramConstrListMark _) :: rem -> pure_sublevels' custom assoc from forpat level rem
let make_act : type r. r target -> _ -> r gen_eval = function
| ForConstr -> fun notation loc env ->
@@ -444,17 +498,17 @@ let make_act : type r. r target -> _ -> r gen_eval = function
CAst.make ~loc @@ CPatNotation (notation, env, [])
let extend_constr state forpat ng =
- let n,_,_ = ng.notgram_level in
+ let custom,n,_,_ = ng.notgram_level in
let assoc = ng.notgram_assoc in
- let (entry, level) = interp_constr_entry_key forpat n in
+ let (entry, level) = interp_constr_entry_key custom forpat n in
let fold (accu, state) pt =
let AnyTyRule r = make_ty_rule assoc n forpat pt in
let symbs = ty_erase r in
- let pure_sublevels = pure_sublevels level symbs in
+ let pure_sublevels = pure_sublevels' custom assoc n forpat level pt in
let isforpat = target_to_bool forpat in
let needed_levels, state = register_empty_levels state isforpat pure_sublevels in
- let (pos,p4assoc,name,reinit), state = find_position state isforpat assoc level in
- let empty_rules = List.map (prepare_empty_levels isforpat) needed_levels in
+ let (pos,p4assoc,name,reinit), state = find_position state custom isforpat assoc level in
+ let empty_rules = List.map (prepare_empty_levels forpat) needed_levels in
let empty = { constrs = []; constrlists = []; binders = []; binderlists = [] } in
let act = ty_eval r (make_act forpat ng.notgram_notation) empty in
let rule = (name, p4assoc, [Rule (symbs, act)]) in
@@ -467,7 +521,7 @@ let constr_levels = GramState.field ()
let extend_constr_notation ng state =
let levels = match GramState.get state constr_levels with
- | None -> default_constr_levels
+ | None -> String.Map.add "constr" default_constr_levels String.Map.empty
| Some lev -> lev
in
(* Add the notation in constr *)
diff --git a/vernac/egramcoq.mli b/vernac/egramcoq.mli
index b0341e6a17..3a6f8ae015 100644
--- a/vernac/egramcoq.mli
+++ b/vernac/egramcoq.mli
@@ -17,3 +17,6 @@
val extend_constr_grammar : Notation_gram.one_notation_grammar -> unit
(** Add a term notation rule to the parsing system. *)
+
+val create_custom_entry : local:bool -> string -> unit
+val locality_of_custom_entry : string -> bool
diff --git a/vernac/egramml.ml b/vernac/egramml.ml
index 048d4d93a0..c5dedc880e 100644
--- a/vernac/egramml.ml
+++ b/vernac/egramml.ml
@@ -64,6 +64,15 @@ let make_rule f prod =
let act = ty_eval ty_rule f in
Extend.Rule (symb, act)
+let rec proj_symbol : type a b c. (a, b, c) ty_user_symbol -> (a, b, c) genarg_type = function
+| TUentry a -> ExtraArg a
+| TUentryl (a,l) -> ExtraArg a
+| TUopt(o) -> OptArg (proj_symbol o)
+| TUlist1 l -> ListArg (proj_symbol l)
+| TUlist1sep (l,_) -> ListArg (proj_symbol l)
+| TUlist0 l -> ListArg (proj_symbol l)
+| TUlist0sep (l,_) -> ListArg (proj_symbol l)
+
(** Vernac grammar extensions *)
let vernac_exts = ref []
diff --git a/vernac/egramml.mli b/vernac/egramml.mli
index 31aa1a9891..c4f4fcfaa4 100644
--- a/vernac/egramml.mli
+++ b/vernac/egramml.mli
@@ -21,11 +21,13 @@ type 's grammar_prod_item =
('s, 'a) Extend.symbol) Loc.located -> 's grammar_prod_item
val extend_vernac_command_grammar :
- Vernacexpr.extend_name -> vernac_expr Pcoq.Gram.entry option ->
+ Vernacexpr.extend_name -> vernac_expr Pcoq.Entry.t option ->
vernac_expr grammar_prod_item list -> unit
val get_extend_vernac_rule : Vernacexpr.extend_name -> vernac_expr grammar_prod_item list
+val proj_symbol : ('a, 'b, 'c) Extend.ty_user_symbol -> ('a, 'b, 'c) Genarg.genarg_type
+
(** Utility function reused in Egramcoq : *)
val make_rule :
diff --git a/vernac/g_proofs.ml4 b/vernac/g_proofs.ml4
deleted file mode 100644
index 4b11276af3..0000000000
--- a/vernac/g_proofs.ml4
+++ /dev/null
@@ -1,131 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-open Glob_term
-open Constrexpr
-open Vernacexpr
-open Proof_global
-
-open Pcoq
-open Pcoq.Prim
-open Pcoq.Constr
-open Pvernac.Vernac_
-
-let thm_token = G_vernac.thm_token
-
-let hint = Gram.entry_create "hint"
-
-let warn_deprecated_focus =
- CWarnings.create ~name:"deprecated-focus" ~category:"deprecated"
- (fun () ->
- Pp.strbrk
- "The Focus command is deprecated; use bullets or focusing brackets instead"
- )
-
-let warn_deprecated_focus_n n =
- CWarnings.create ~name:"deprecated-focus" ~category:"deprecated"
- (fun () ->
- Pp.(str "The Focus command is deprecated;" ++ spc ()
- ++ str "use '" ++ int n ++ str ": {' instead")
- )
-
-let warn_deprecated_unfocus =
- CWarnings.create ~name:"deprecated-unfocus" ~category:"deprecated"
- (fun () -> Pp.strbrk "The Unfocus command is deprecated")
-
-(* Proof commands *)
-GEXTEND Gram
- GLOBAL: hint command;
-
- opt_hintbases:
- [ [ -> []
- | ":"; l = LIST1 [id = IDENT -> id ] -> l ] ]
- ;
- command:
- [ [ IDENT "Goal"; c = lconstr ->
- VernacDefinition (Decl_kinds.(NoDischarge, Definition), ((CAst.make ~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
- | IDENT "Abort" -> VernacAbort None
- | IDENT "Abort"; IDENT "All" -> VernacAbortAll
- | IDENT "Abort"; id = identref -> VernacAbort (Some id)
- | IDENT "Existential"; n = natural; c = constr_body ->
- VernacSolveExistential (n,c)
- | IDENT "Admitted" -> VernacEndProof Admitted
- | IDENT "Qed" -> VernacEndProof (Proved (Opaque,None))
- | IDENT "Save"; id = identref ->
- VernacEndProof (Proved (Opaque, Some id))
- | IDENT "Defined" -> VernacEndProof (Proved (Transparent,None))
- | IDENT "Defined"; id=identref ->
- VernacEndProof (Proved (Transparent,Some id))
- | IDENT "Restart" -> VernacRestart
- | IDENT "Undo" -> VernacUndo 1
- | IDENT "Undo"; n = natural -> VernacUndo n
- | IDENT "Undo"; IDENT "To"; n = natural -> VernacUndoTo n
- | IDENT "Focus" ->
- warn_deprecated_focus ~loc:!@loc ();
- VernacFocus None
- | IDENT "Focus"; n = natural ->
- warn_deprecated_focus_n n ~loc:!@loc ();
- VernacFocus (Some n)
- | IDENT "Unfocus" ->
- warn_deprecated_unfocus ~loc:!@loc ();
- VernacUnfocus
- | IDENT "Unfocused" -> VernacUnfocused
- | IDENT "Show" -> VernacShow (ShowGoal OpenSubgoals)
- | IDENT "Show"; n = natural -> VernacShow (ShowGoal (NthGoal n))
- | IDENT "Show"; id = ident -> VernacShow (ShowGoal (GoalId id))
- | IDENT "Show"; IDENT "Script" -> VernacShow ShowScript
- | IDENT "Show"; IDENT "Existentials" -> VernacShow ShowExistentials
- | IDENT "Show"; IDENT "Universes" -> VernacShow ShowUniverses
- | IDENT "Show"; IDENT "Conjectures" -> VernacShow ShowProofNames
- | IDENT "Show"; IDENT "Proof" -> VernacShow ShowProof
- | IDENT "Show"; IDENT "Intro" -> VernacShow (ShowIntros false)
- | IDENT "Show"; IDENT "Intros" -> VernacShow (ShowIntros true)
- | IDENT "Show"; IDENT "Match"; id = reference -> VernacShow (ShowMatch id)
- | IDENT "Guarded" -> VernacCheckGuard
- (* Hints for Auto and EAuto *)
- | IDENT "Create"; IDENT "HintDb" ;
- id = IDENT ; b = [ "discriminated" -> true | -> false ] ->
- VernacCreateHintDb (id, b)
- | IDENT "Remove"; IDENT "Hints"; ids = LIST1 global; dbnames = opt_hintbases ->
- VernacRemoveHints (dbnames, ids)
- | IDENT "Hint"; h = hint; dbnames = opt_hintbases ->
- VernacHints (dbnames, h)
- ] ];
- reference_or_constr:
- [ [ r = global -> HintsReference r
- | c = constr -> HintsConstr c ] ]
- ;
- hint:
- [ [ IDENT "Resolve"; lc = LIST1 reference_or_constr; info = hint_info ->
- HintsResolve (List.map (fun x -> (info, true, x)) lc)
- | IDENT "Resolve"; "->"; lc = LIST1 global; n = OPT natural ->
- HintsResolveIFF (true, lc, n)
- | IDENT "Resolve"; "<-"; lc = LIST1 global; n = OPT natural ->
- HintsResolveIFF (false, lc, n)
- | IDENT "Immediate"; lc = LIST1 reference_or_constr -> HintsImmediate lc
- | IDENT "Transparent"; lc = LIST1 global -> HintsTransparency (lc, true)
- | IDENT "Opaque"; lc = LIST1 global -> HintsTransparency (lc, false)
- | IDENT "Mode"; l = global; m = mode -> HintsMode (l, m)
- | IDENT "Unfold"; lqid = LIST1 global -> HintsUnfold lqid
- | IDENT "Constructors"; lc = LIST1 global -> HintsConstructors lc ] ]
- ;
- constr_body:
- [ [ ":="; c = lconstr -> c
- | ":"; t = lconstr; ":="; c = lconstr -> CAst.make ~loc:!@loc @@ CCast(c,CastConv t) ] ]
- ;
- mode:
- [ [ l = LIST1 [ "+" -> ModeInput
- | "!" -> ModeNoHeadEvar
- | "-" -> ModeOutput ] -> l ] ]
- ;
-END
diff --git a/vernac/g_proofs.mlg b/vernac/g_proofs.mlg
new file mode 100644
index 0000000000..dacef6e211
--- /dev/null
+++ b/vernac/g_proofs.mlg
@@ -0,0 +1,139 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+{
+
+open Glob_term
+open Constrexpr
+open Vernacexpr
+open Proof_global
+
+open Pcoq
+open Pcoq.Prim
+open Pcoq.Constr
+open Pvernac.Vernac_
+
+let thm_token = G_vernac.thm_token
+
+let hint = Entry.create "hint"
+
+let warn_deprecated_focus =
+ CWarnings.create ~name:"deprecated-focus" ~category:"deprecated"
+ (fun () ->
+ Pp.strbrk
+ "The Focus command is deprecated; use bullets or focusing brackets instead"
+ )
+
+let warn_deprecated_focus_n n =
+ CWarnings.create ~name:"deprecated-focus" ~category:"deprecated"
+ (fun () ->
+ Pp.(str "The Focus command is deprecated;" ++ spc ()
+ ++ str "use '" ++ int n ++ str ": {' instead")
+ )
+
+let warn_deprecated_unfocus =
+ CWarnings.create ~name:"deprecated-unfocus" ~category:"deprecated"
+ (fun () -> Pp.strbrk "The Unfocus command is deprecated")
+
+}
+
+(* Proof commands *)
+GRAMMAR EXTEND Gram
+ GLOBAL: hint command;
+
+ opt_hintbases:
+ [ [ -> { [] }
+ | ":"; l = LIST1 [id = IDENT -> { id } ] -> { l } ] ]
+ ;
+ command:
+ [ [ IDENT "Goal"; c = lconstr ->
+ { VernacDefinition (Decl_kinds.(NoDischarge, Definition), ((CAst.make ~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 }
+ | IDENT "Abort" -> { VernacAbort None }
+ | IDENT "Abort"; IDENT "All" -> { VernacAbortAll }
+ | IDENT "Abort"; id = identref -> { VernacAbort (Some id) }
+ | IDENT "Existential"; n = natural; c = constr_body ->
+ { VernacSolveExistential (n,c) }
+ | IDENT "Admitted" -> { VernacEndProof Admitted }
+ | IDENT "Qed" -> { VernacEndProof (Proved (Opaque,None)) }
+ | IDENT "Save"; id = identref ->
+ { VernacEndProof (Proved (Opaque, Some id)) }
+ | IDENT "Defined" -> { VernacEndProof (Proved (Transparent,None)) }
+ | IDENT "Defined"; id=identref ->
+ { VernacEndProof (Proved (Transparent,Some id)) }
+ | IDENT "Restart" -> { VernacRestart }
+ | IDENT "Undo" -> { VernacUndo 1 }
+ | IDENT "Undo"; n = natural -> { VernacUndo n }
+ | IDENT "Undo"; IDENT "To"; n = natural -> { VernacUndoTo n }
+ | IDENT "Focus" ->
+ { warn_deprecated_focus ~loc ();
+ VernacFocus None }
+ | IDENT "Focus"; n = natural ->
+ { warn_deprecated_focus_n n ~loc ();
+ VernacFocus (Some n) }
+ | IDENT "Unfocus" ->
+ { warn_deprecated_unfocus ~loc ();
+ VernacUnfocus }
+ | IDENT "Unfocused" -> { VernacUnfocused }
+ | IDENT "Show" -> { VernacShow (ShowGoal OpenSubgoals) }
+ | IDENT "Show"; n = natural -> { VernacShow (ShowGoal (NthGoal n)) }
+ | IDENT "Show"; id = ident -> { VernacShow (ShowGoal (GoalId id)) }
+ | IDENT "Show"; IDENT "Script" -> { VernacShow ShowScript }
+ | IDENT "Show"; IDENT "Existentials" -> { VernacShow ShowExistentials }
+ | IDENT "Show"; IDENT "Universes" -> { VernacShow ShowUniverses }
+ | IDENT "Show"; IDENT "Conjectures" -> { VernacShow ShowProofNames }
+ | IDENT "Show"; IDENT "Proof" -> { VernacShow ShowProof }
+ | IDENT "Show"; IDENT "Intro" -> { VernacShow (ShowIntros false) }
+ | IDENT "Show"; IDENT "Intros" -> { VernacShow (ShowIntros true) }
+ | IDENT "Show"; IDENT "Match"; id = reference -> { VernacShow (ShowMatch id) }
+ | IDENT "Guarded" -> { VernacCheckGuard }
+ (* Hints for Auto and EAuto *)
+ | IDENT "Create"; IDENT "HintDb" ;
+ id = IDENT ; b = [ "discriminated" -> { true } | -> { false } ] ->
+ { VernacCreateHintDb (id, b) }
+ | IDENT "Remove"; IDENT "Hints"; ids = LIST1 global; dbnames = opt_hintbases ->
+ { VernacRemoveHints (dbnames, ids) }
+ | IDENT "Hint"; h = hint; dbnames = opt_hintbases ->
+ { VernacHints (dbnames, h) }
+ ] ];
+ reference_or_constr:
+ [ [ r = global -> { HintsReference r }
+ | c = constr -> { HintsConstr c } ] ]
+ ;
+ hint:
+ [ [ IDENT "Resolve"; lc = LIST1 reference_or_constr; info = hint_info ->
+ { HintsResolve (List.map (fun x -> (info, true, x)) lc) }
+ | IDENT "Resolve"; "->"; lc = LIST1 global; n = OPT natural ->
+ { HintsResolveIFF (true, lc, n) }
+ | IDENT "Resolve"; "<-"; lc = LIST1 global; n = OPT natural ->
+ { HintsResolveIFF (false, lc, n) }
+ | IDENT "Immediate"; lc = LIST1 reference_or_constr -> { HintsImmediate lc }
+ | IDENT "Variables"; IDENT "Transparent" -> { HintsTransparency (HintsVariables, true) }
+ | IDENT "Variables"; IDENT "Opaque" -> { HintsTransparency (HintsVariables, false) }
+ | IDENT "Constants"; IDENT "Transparent" -> { HintsTransparency (HintsConstants, true) }
+ | IDENT "Constants"; IDENT "Opaque" -> { HintsTransparency (HintsConstants, false) }
+ | IDENT "Transparent"; lc = LIST1 global -> { HintsTransparency (HintsReferences lc, true) }
+ | IDENT "Opaque"; lc = LIST1 global -> { HintsTransparency (HintsReferences lc, false) }
+ | IDENT "Mode"; l = global; m = mode -> { HintsMode (l, m) }
+ | IDENT "Unfold"; lqid = LIST1 global -> { HintsUnfold lqid }
+ | IDENT "Constructors"; lc = LIST1 global -> { HintsConstructors lc } ] ]
+ ;
+ constr_body:
+ [ [ ":="; c = lconstr -> { c }
+ | ":"; t = lconstr; ":="; c = lconstr -> { CAst.make ~loc @@ CCast(c,CastConv t) } ] ]
+ ;
+ mode:
+ [ [ l = LIST1 [ "+" -> { ModeInput }
+ | "!" -> { ModeNoHeadEvar }
+ | "-" -> { ModeOutput } ] -> { l } ] ]
+ ;
+END
diff --git a/vernac/g_vernac.ml4 b/vernac/g_vernac.ml4
deleted file mode 100644
index 16934fc868..0000000000
--- a/vernac/g_vernac.ml4
+++ /dev/null
@@ -1,1156 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-open Pp
-open CErrors
-open Util
-open Names
-open Glob_term
-open Vernacexpr
-open Constrexpr
-open Constrexpr_ops
-open Extend
-open Decl_kinds
-open Declaremods
-open Declarations
-open Namegen
-open Tok (* necessary for camlp5 *)
-
-open Pcoq
-open Pcoq.Prim
-open Pcoq.Constr
-open Pcoq.Module
-open Pvernac.Vernac_
-
-let vernac_kw = [ ";"; ","; ">->"; ":<"; "<:"; "where"; "at" ]
-let _ = List.iter CLexer.add_keyword vernac_kw
-
-(* Rem: do not join the different GEXTEND into one, it breaks native *)
-(* compilation on PowerPC and Sun architectures *)
-
-let query_command = Gram.entry_create "vernac:query_command"
-
-let subprf = Gram.entry_create "vernac:subprf"
-
-let class_rawexpr = Gram.entry_create "vernac:class_rawexpr"
-let thm_token = Gram.entry_create "vernac:thm_token"
-let def_body = Gram.entry_create "vernac:def_body"
-let decl_notation = Gram.entry_create "vernac:decl_notation"
-let record_field = Gram.entry_create "vernac:record_field"
-let of_type_with_opt_coercion = Gram.entry_create "vernac:of_type_with_opt_coercion"
-let instance_name = Gram.entry_create "vernac:instance_name"
-let section_subset_expr = Gram.entry_create "vernac:section_subset_expr"
-
-let make_bullet s =
- let open Proof_bullet in
- let n = String.length s in
- match s.[0] with
- | '-' -> Dash n
- | '+' -> Plus n
- | '*' -> Star n
- | _ -> assert false
-
-let parse_compat_version ?(allow_old = true) = let open Flags in function
- | "8.8" -> Current
- | "8.7" -> V8_7
- | "8.6" -> V8_6
- | ("8.5" | "8.4" | "8.3" | "8.2" | "8.1" | "8.0") as s ->
- CErrors.user_err ~hdr:"get_compat_version"
- Pp.(str "Compatibility with version " ++ str s ++ str " not supported.")
- | s ->
- CErrors.user_err ~hdr:"get_compat_version"
- Pp.(str "Unknown compatibility version \"" ++ str s ++ str "\".")
-
-GEXTEND Gram
- GLOBAL: vernac_control gallina_ext noedit_mode subprf;
- vernac_control: FIRST
- [ [ IDENT "Time"; c = located_vernac -> VernacTime (false,c)
- | 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
- | (f, v) = vernac -> VernacExpr(f, v) ]
- ]
- ;
- vernac:
- [ [ 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"; (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)
- ] ]
- ;
- vernac_aux: LAST
- [ [ prfcom = command_entry -> ([], prfcom) ] ]
- ;
- noedit_mode:
- [ [ c = query_command -> c None] ]
- ;
-
- subprf:
- [ [ s = BULLET -> VernacBullet (make_bullet s)
- | "{" -> VernacSubproof None
- | "}" -> VernacEndSubproof
- ] ]
- ;
-
- located_vernac:
- [ [ v = vernac_control -> CAst.make ~loc:!@loc v ] ]
- ;
-END
-
-let warn_plural_command =
- CWarnings.create ~name:"plural-command" ~category:"pedantic" ~default:CWarnings.Disabled
- (fun kwd -> strbrk (Printf.sprintf "Command \"%s\" expects more than one assumption." kwd))
-
-let test_plural_form loc kwd = function
- | [(_,([_],_))] ->
- warn_plural_command ~loc:!@loc kwd
- | _ -> ()
-
-let test_plural_form_types loc kwd = function
- | [([_],_)] ->
- warn_plural_command ~loc:!@loc kwd
- | _ -> ()
-
-let lname_of_lident : lident -> lname =
- CAst.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
- record_field decl_notation rec_definition ident_decl univ_decl;
-
- gallina:
- (* Definition, Theorem, Variable, Axiom, ... *)
- [ [ thm = thm_token; id = ident_decl; bl = binders; ":"; c = lconstr;
- l = LIST0
- [ "with"; id = ident_decl; bl = binders; ":"; c = lconstr ->
- (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, name_of_ident_decl id, b)
- | IDENT "Let"; id = identref; b = def_body ->
- VernacDefinition ((DoDischarge, Let), (lname_of_lident id, None), b)
- (* Gallina inductive declarations *)
- | cum = OPT cumulativity_token; priv = private_token; f = finite_token;
- indl = LIST1 inductive_definition SEP "with" ->
- let (k,f) = f in
- let indl=List.map (fun ((a,b,c,d),e) -> ((a,b,c,k,d),e)) indl in
- VernacInductive (cum, priv,f,indl)
- | "Fixpoint"; recs = LIST1 rec_definition SEP "with" ->
- VernacFixpoint (NoDischarge, recs)
- | IDENT "Let"; "Fixpoint"; recs = LIST1 rec_definition SEP "with" ->
- VernacFixpoint (DoDischarge, recs)
- | "CoFixpoint"; corecs = LIST1 corec_definition SEP "with" ->
- VernacCoFixpoint (NoDischarge, corecs)
- | IDENT "Let"; "CoFixpoint"; corecs = LIST1 corec_definition SEP "with" ->
- VernacCoFixpoint (DoDischarge, corecs)
- | IDENT "Scheme"; l = LIST1 scheme SEP "with" -> VernacScheme l
- | IDENT "Combined"; IDENT "Scheme"; id = identref; IDENT "from";
- l = LIST1 identref SEP "," -> VernacCombinedScheme (id, l)
- | IDENT "Register"; IDENT "Inline"; id = identref ->
- VernacRegister(id, RegisterInline)
- | IDENT "Universe"; l = LIST1 identref -> VernacUniverse l
- | IDENT "Universes"; l = LIST1 identref -> VernacUniverse l
- | IDENT "Constraint"; l = LIST1 univ_constraint SEP "," -> VernacConstraint l
- ] ]
- ;
-
- thm_token:
- [ [ "Theorem" -> Theorem
- | IDENT "Lemma" -> Lemma
- | IDENT "Fact" -> Fact
- | IDENT "Remark" -> Remark
- | IDENT "Corollary" -> Corollary
- | IDENT "Proposition" -> Proposition
- | IDENT "Property" -> Property ] ]
- ;
- def_token:
- [ [ "Definition" -> (NoDischarge,Definition)
- | IDENT "Example" -> (NoDischarge,Example)
- | IDENT "SubClass" -> (NoDischarge,SubClass) ] ]
- ;
- assumption_token:
- [ [ "Hypothesis" -> (DoDischarge, Logical)
- | "Variable" -> (DoDischarge, Definitional)
- | "Axiom" -> (NoDischarge, Logical)
- | "Parameter" -> (NoDischarge, Definitional)
- | IDENT "Conjecture" -> (NoDischarge, Conjectural) ] ]
- ;
- assumptions_token:
- [ [ IDENT "Hypotheses" -> ("Hypotheses", (DoDischarge, Logical))
- | IDENT "Variables" -> ("Variables", (DoDischarge, Definitional))
- | IDENT "Axioms" -> ("Axioms", (NoDischarge, Logical))
- | IDENT "Parameters" -> ("Parameters", (NoDischarge, Definitional))
- | IDENT "Conjectures" -> ("Conjectures", (NoDischarge, Conjectural)) ] ]
- ;
- inline:
- [ [ IDENT "Inline"; "("; i = INT; ")" -> InlineAt (int_of_string i)
- | IDENT "Inline" -> DefaultInline
- | -> NoInline] ]
- ;
- univ_constraint:
- [ [ l = universe_level; ord = [ "<" -> Univ.Lt | "=" -> Univ.Eq | "<=" -> Univ.Le ];
- r = universe_level -> (l, ord, r) ] ]
- ;
- univ_decl :
- [ [ "@{" ; l = LIST0 identref; ext = [ "+" -> true | -> false ];
- cs = [ "|"; l' = LIST0 univ_constraint SEP ",";
- ext = [ "+" -> true | -> false ]; "}" -> (l',ext)
- | ext = [ "}" -> true | "|}" -> false ] -> ([], ext) ]
- ->
- let open UState in
- { univdecl_instance = l;
- univdecl_extensible_instance = ext;
- univdecl_constraints = fst cs;
- univdecl_extensible_constraints = snd cs }
- ] ]
- ;
- ident_decl:
- [ [ i = identref; l = OPT univ_decl -> (i, l)
- ] ]
- ;
- finite_token:
- [ [ IDENT "Inductive" -> (Inductive_kw,Finite)
- | IDENT "CoInductive" -> (CoInductive,CoFinite)
- | IDENT "Variant" -> (Variant,BiFinite)
- | IDENT "Record" -> (Record,BiFinite)
- | IDENT "Structure" -> (Structure,BiFinite)
- | IDENT "Class" -> (Class true,BiFinite) ] ]
- ;
- cumulativity_token:
- [ [ IDENT "Cumulative" -> VernacCumulative
- | IDENT "NonCumulative" -> VernacNonCumulative ] ]
- ;
- private_token:
- [ [ IDENT "Private" -> true | -> false ] ]
- ;
- (* Simple definitions *)
- def_body:
- [ [ bl = binders; ":="; red = reduce; c = lconstr ->
- if List.exists (function CLocalPattern _ -> true | _ -> false) bl
- then
- (* FIXME: "red" will be applied to types in bl and Cast with remain *)
- let c = mkCLambdaN ~loc:!@loc bl c in
- DefineBody ([], red, c, None)
- else
- (match c with
- | { CAst.v = CCast(c, CastConv t) } -> DefineBody (bl, red, c, Some t)
- | _ -> DefineBody (bl, red, c, None))
- | bl = binders; ":"; t = lconstr; ":="; red = reduce; c = lconstr ->
- let ((bl, c), tyo) =
- if List.exists (function CLocalPattern _ -> true | _ -> false) bl
- then
- (* FIXME: "red" will be applied to types in bl and Cast with remain *)
- let c = CAst.make ~loc:!@loc @@ CCast (c, CastConv t) in
- (([],mkCLambdaN ~loc:!@loc bl c), None)
- else ((bl, c), Some t)
- in
- DefineBody (bl, red, c, tyo)
- | bl = binders; ":"; t = lconstr ->
- ProveBody (bl, t) ] ]
- ;
- reduce:
- [ [ IDENT "Eval"; r = red_expr; "in" -> Some r
- | -> None ] ]
- ;
- one_decl_notation:
- [ [ ntn = ne_lstring; ":="; c = constr;
- scopt = OPT [ ":"; sc = IDENT -> sc] -> (ntn,c,scopt) ] ]
- ;
- decl_notation:
- [ [ "where"; l = LIST1 one_decl_notation SEP IDENT "and" -> l
- | -> [] ] ]
- ;
- (* Inductives and records *)
- opt_constructors_or_fields:
- [ [ ":="; lc = constructor_list_or_record_decl -> lc
- | -> RecordDecl (None, []) ] ]
- ;
- inductive_definition:
- [ [ oc = opt_coercion; id = ident_decl; indpar = binders;
- c = OPT [ ":"; c = lconstr -> c ];
- lc=opt_constructors_or_fields; ntn = decl_notation ->
- (((oc,id),indpar,c,lc),ntn) ] ]
- ;
- constructor_list_or_record_decl:
- [ [ "|"; l = LIST1 constructor SEP "|" -> Constructors l
- | id = identref ; c = constructor_type; "|"; l = LIST0 constructor SEP "|" ->
- Constructors ((c id)::l)
- | id = identref ; c = constructor_type -> Constructors [ c id ]
- | cstr = identref; "{"; fs = record_fields; "}" ->
- RecordDecl (Some cstr,fs)
- | "{";fs = record_fields; "}" -> RecordDecl (None,fs)
- | -> Constructors [] ] ]
- ;
-(*
- csort:
- [ [ s = sort -> CSort (loc,s) ] ]
- ;
-*)
- opt_coercion:
- [ [ ">" -> true
- | -> false ] ]
- ;
- (* (co)-fixpoints *)
- rec_definition:
- [ [ id = ident_decl;
- bl = binders_fixannot;
- ty = type_cstr;
- def = OPT [":="; def = lconstr -> def]; ntn = decl_notation ->
- let bl, annot = bl in ((id,annot,bl,ty,def),ntn) ] ]
- ;
- corec_definition:
- [ [ id = ident_decl; bl = binders; ty = type_cstr;
- def = OPT [":="; def = lconstr -> def]; ntn = decl_notation ->
- ((id,bl,ty,def),ntn) ] ]
- ;
- type_cstr:
- [ [ ":"; c=lconstr -> c
- | -> CAst.make ~loc:!@loc @@ CHole (None, IntroAnonymous, None) ] ]
- ;
- (* Inductive schemes *)
- scheme:
- [ [ kind = scheme_kind -> (None,kind)
- | id = identref; ":="; kind = scheme_kind -> (Some id,kind) ] ]
- ;
- scheme_kind:
- [ [ IDENT "Induction"; "for"; ind = smart_global;
- IDENT "Sort"; s = sort_family-> InductionScheme(true,ind,s)
- | IDENT "Minimality"; "for"; ind = smart_global;
- IDENT "Sort"; s = sort_family-> InductionScheme(false,ind,s)
- | IDENT "Elimination"; "for"; ind = smart_global;
- IDENT "Sort"; s = sort_family-> CaseScheme(true,ind,s)
- | IDENT "Case"; "for"; ind = smart_global;
- IDENT "Sort"; s = sort_family-> CaseScheme(false,ind,s)
- | IDENT "Equality"; "for" ; ind = smart_global -> EqualityScheme(ind) ] ]
- ;
- (* Various Binders *)
-(*
- (* ... without coercions *)
- binder_nodef:
- [ [ b = binder_let ->
- (match b with
- CLocalAssum(l,ty) -> (l,ty)
- | CLocalDef _ ->
- Util.user_err_loc
- (loc,"fix_param",Pp.str"defined binder not allowed here.")) ] ]
- ;
-*)
- (* ... with coercions *)
- record_field:
- [ [ bd = record_binder; pri = OPT [ "|"; n = natural -> n ];
- ntn = decl_notation -> (bd,pri),ntn ] ]
- ;
- record_fields:
- [ [ f = record_field; ";"; fs = record_fields -> f :: fs
- | f = record_field; ";" -> [f]
- | f = record_field -> [f]
- | -> []
- ] ]
- ;
- record_binder_body:
- [ [ l = binders; oc = of_type_with_opt_coercion;
- t = lconstr -> fun id -> (oc,AssumExpr (id,mkCProdN ~loc:!@loc l t))
- | l = binders; oc = of_type_with_opt_coercion;
- t = lconstr; ":="; b = lconstr -> fun id ->
- (oc,DefExpr (id,mkCLambdaN ~loc:!@loc l b,Some (mkCProdN ~loc:!@loc l t)))
- | l = binders; ":="; b = lconstr -> fun id ->
- match b.CAst.v with
- | CCast(b', (CastConv t|CastVM t|CastNative t)) ->
- (None,DefExpr(id,mkCLambdaN ~loc:!@loc l b',Some (mkCProdN ~loc:!@loc l t)))
- | _ ->
- (None,DefExpr(id,mkCLambdaN ~loc:!@loc l b,None)) ] ]
- ;
- record_binder:
- [ [ id = name -> (None,AssumExpr(id, CAst.make ~loc:!@loc @@ CHole (None, IntroAnonymous, None)))
- | id = name; f = record_binder_body -> f id ] ]
- ;
- assum_list:
- [ [ bl = LIST1 assum_coe -> bl | b = simple_assum_coe -> [b] ] ]
- ;
- assum_coe:
- [ [ "("; a = simple_assum_coe; ")" -> a ] ]
- ;
- simple_assum_coe:
- [ [ idl = LIST1 ident_decl; oc = of_type_with_opt_coercion; c = lconstr ->
- (not (Option.is_empty oc),(idl,c)) ] ]
- ;
-
- constructor_type:
- [[ l = binders;
- t= [ coe = of_type_with_opt_coercion; c = lconstr ->
- fun l id -> (not (Option.is_empty coe),(id,mkCProdN ~loc:!@loc l c))
- | ->
- fun l id -> (false,(id,mkCProdN ~loc:!@loc l (CAst.make ~loc:!@loc @@ CHole (None, IntroAnonymous, None)))) ]
- -> t l
- ]]
-;
-
- constructor:
- [ [ id = identref; c=constructor_type -> c id ] ]
- ;
- of_type_with_opt_coercion:
- [ [ ":>>" -> Some false
- | ":>"; ">" -> Some false
- | ":>" -> Some true
- | ":"; ">"; ">" -> Some false
- | ":"; ">" -> Some true
- | ":" -> None ] ]
- ;
-END
-
-let only_starredidentrefs =
- Gram.Entry.of_parser "test_only_starredidentrefs"
- (fun strm ->
- let rec aux n =
- match Util.stream_nth n strm with
- | KEYWORD "." -> ()
- | KEYWORD ")" -> ()
- | (IDENT _ | KEYWORD "Type" | KEYWORD "*") -> aux (n+1)
- | _ -> raise Stream.Failure in
- aux 0)
-let starredidentreflist_to_expr l =
- match l with
- | [] -> SsEmpty
- | x :: xs -> List.fold_right (fun i acc -> SsUnion(i,acc)) xs x
-
-let warn_deprecated_include_type =
- CWarnings.create ~name:"deprecated-include-type" ~category:"deprecated"
- (fun () -> strbrk "Include Type is deprecated; use Include instead")
-
-(* Modules and Sections *)
-GEXTEND Gram
- GLOBAL: gallina_ext module_expr module_type section_subset_expr;
-
- gallina_ext:
- [ [ (* Interactive module declaration *)
- IDENT "Module"; export = export_token; id = identref;
- bl = LIST0 module_binder; sign = of_module_type;
- body = is_module_expr ->
- VernacDefineModule (export, id, bl, sign, body)
- | IDENT "Module"; "Type"; id = identref;
- bl = LIST0 module_binder; sign = check_module_types;
- body = is_module_type ->
- VernacDeclareModuleType (id, bl, sign, body)
- | IDENT "Declare"; IDENT "Module"; export = export_token; id = identref;
- bl = LIST0 module_binder; ":"; mty = module_type_inl ->
- VernacDeclareModule (export, id, bl, mty)
- (* Section beginning *)
- | IDENT "Section"; id = identref -> VernacBeginSection id
- | IDENT "Chapter"; id = identref -> VernacBeginSection id
-
- (* This end a Section a Module or a Module Type *)
- | IDENT "End"; id = identref -> VernacEndSegment id
-
- (* Naming a set of section hyps *)
- | IDENT "Collection"; id = identref; ":="; expr = section_subset_expr ->
- VernacNameSectionHypSet (id, expr)
-
- (* Requiring an already compiled module *)
- | IDENT "Require"; export = export_token; qidl = LIST1 global ->
- VernacRequire (None, export, qidl)
- | IDENT "From" ; ns = global ; IDENT "Require"; export = export_token
- ; qidl = LIST1 global ->
- VernacRequire (Some ns, export, qidl)
- | IDENT "Import"; qidl = LIST1 global -> VernacImport (false,qidl)
- | IDENT "Export"; qidl = LIST1 global -> VernacImport (true,qidl)
- | IDENT "Include"; e = module_type_inl; l = LIST0 ext_module_expr ->
- VernacInclude(e::l)
- | IDENT "Include"; "Type"; e = module_type_inl; l = LIST0 ext_module_type ->
- warn_deprecated_include_type ~loc:!@loc ();
- VernacInclude(e::l) ] ]
- ;
- export_token:
- [ [ IDENT "Import" -> Some false
- | IDENT "Export" -> Some true
- | -> None ] ]
- ;
- ext_module_type:
- [ [ "<+"; mty = module_type_inl -> mty ] ]
- ;
- ext_module_expr:
- [ [ "<+"; mexpr = module_expr_inl -> mexpr ] ]
- ;
- check_module_type:
- [ [ "<:"; mty = module_type_inl -> mty ] ]
- ;
- check_module_types:
- [ [ mtys = LIST0 check_module_type -> mtys ] ]
- ;
- of_module_type:
- [ [ ":"; mty = module_type_inl -> Enforce mty
- | mtys = check_module_types -> Check mtys ] ]
- ;
- is_module_type:
- [ [ ":="; mty = module_type_inl ; l = LIST0 ext_module_type -> (mty::l)
- | -> [] ] ]
- ;
- is_module_expr:
- [ [ ":="; mexpr = module_expr_inl; l = LIST0 ext_module_expr -> (mexpr::l)
- | -> [] ] ]
- ;
- functor_app_annot:
- [ [ "["; IDENT "inline"; "at"; IDENT "level"; i = INT; "]" ->
- InlineAt (int_of_string i)
- | "["; IDENT "no"; IDENT "inline"; "]" -> NoInline
- | -> DefaultInline
- ] ]
- ;
- module_expr_inl:
- [ [ "!"; me = module_expr -> (me,NoInline)
- | me = module_expr; a = functor_app_annot -> (me,a) ] ]
- ;
- module_type_inl:
- [ [ "!"; me = module_type -> (me,NoInline)
- | me = module_type; a = functor_app_annot -> (me,a) ] ]
- ;
- (* Module binder *)
- module_binder:
- [ [ "("; export = export_token; idl = LIST1 identref; ":";
- mty = module_type_inl; ")" -> (export,idl,mty) ] ]
- ;
- (* Module expressions *)
- module_expr:
- [ [ me = module_expr_atom -> me
- | me1 = module_expr; me2 = module_expr_atom -> CAst.make ~loc:!@loc @@ CMapply (me1,me2)
- ] ]
- ;
- module_expr_atom:
- [ [ qid = qualid -> CAst.make ~loc:!@loc @@ CMident qid | "("; me = module_expr; ")" -> me ] ]
- ;
- with_declaration:
- [ [ "Definition"; fqid = fullyqualid; udecl = OPT univ_decl; ":="; c = Constr.lconstr ->
- CWith_Definition (fqid,udecl,c)
- | IDENT "Module"; fqid = fullyqualid; ":="; qid = qualid ->
- CWith_Module (fqid,qid)
- ] ]
- ;
- module_type:
- [ [ qid = qualid -> CAst.make ~loc:!@loc @@ CMident qid
- | "("; mt = module_type; ")" -> mt
- | mty = module_type; me = module_expr_atom ->
- CAst.make ~loc:!@loc @@ CMapply (mty,me)
- | mty = module_type; "with"; decl = with_declaration ->
- CAst.make ~loc:!@loc @@ CMwith (mty,decl)
- ] ]
- ;
- (* Proof using *)
- section_subset_expr:
- [ [ only_starredidentrefs; l = LIST0 starredidentref ->
- starredidentreflist_to_expr l
- | e = ssexpr -> e ]]
- ;
- starredidentref:
- [ [ i = identref -> SsSingl i
- | i = identref; "*" -> SsFwdClose(SsSingl i)
- | "Type" -> SsType
- | "Type"; "*" -> SsFwdClose SsType ]]
- ;
- ssexpr:
- [ "35"
- [ "-"; e = ssexpr -> SsCompl e ]
- | "50"
- [ e1 = ssexpr; "-"; e2 = ssexpr->SsSubstr(e1,e2)
- | e1 = ssexpr; "+"; e2 = ssexpr->SsUnion(e1,e2)]
- | "0"
- [ i = starredidentref -> i
- | "("; only_starredidentrefs; l = LIST0 starredidentref; ")"->
- starredidentreflist_to_expr l
- | "("; only_starredidentrefs; l = LIST0 starredidentref; ")"; "*" ->
- SsFwdClose(starredidentreflist_to_expr l)
- | "("; e = ssexpr; ")"-> e
- | "("; e = ssexpr; ")"; "*" -> SsFwdClose e ] ]
- ;
-END
-
-(* Extensions: implicits, coercions, etc. *)
-GEXTEND Gram
- GLOBAL: gallina_ext instance_name hint_info;
-
- gallina_ext:
- [ [ (* Transparent and Opaque *)
- IDENT "Transparent"; l = LIST1 smart_global ->
- VernacSetOpacity (Conv_oracle.transparent, l)
- | IDENT "Opaque"; l = LIST1 smart_global ->
- VernacSetOpacity (Conv_oracle.Opaque, l)
- | IDENT "Strategy"; l =
- LIST1 [ v=strategy_level; "["; q=LIST1 smart_global; "]" -> (v,q)] ->
- VernacSetStrategy l
- (* Canonical structure *)
- | IDENT "Canonical"; IDENT "Structure"; qid = global ->
- VernacCanonical CAst.(make ~loc:!@loc @@ AN qid)
- | IDENT "Canonical"; IDENT "Structure"; ntn = by_notation ->
- VernacCanonical CAst.(make ~loc:!@loc @@ ByNotation ntn)
- | IDENT "Canonical"; IDENT "Structure"; qid = global; d = def_body ->
- let s = coerce_reference_to_id qid in
- VernacDefinition ((NoDischarge,CanonicalStructure),((CAst.make (Name s)),None),d)
-
- (* Coercions *)
- | IDENT "Coercion"; qid = global; d = def_body ->
- let s = coerce_reference_to_id qid in
- VernacDefinition ((NoDischarge,Coercion),((CAst.make (Name s)),None),d)
- | IDENT "Identity"; IDENT "Coercion"; f = identref; ":";
- s = class_rawexpr; ">->"; t = class_rawexpr ->
- VernacIdentityCoercion (f, s, t)
- | IDENT "Coercion"; qid = global; ":"; s = class_rawexpr; ">->";
- t = class_rawexpr ->
- VernacCoercion (CAst.make ~loc:!@loc @@ AN qid, s, t)
- | IDENT "Coercion"; ntn = by_notation; ":"; s = class_rawexpr; ">->";
- t = class_rawexpr ->
- VernacCoercion (CAst.make ~loc:!@loc @@ ByNotation ntn, s, t)
-
- | IDENT "Context"; c = LIST1 binder ->
- VernacContext (List.flatten c)
-
- | IDENT "Instance"; namesup = instance_name; ":";
- expl = [ "!" -> Decl_kinds.Implicit | -> Decl_kinds.Explicit ] ; t = operconstr LEVEL "200";
- info = hint_info ;
- props = [ ":="; "{"; r = record_declaration; "}" -> Some (true,r) |
- ":="; c = lconstr -> Some (false,c) | -> None ] ->
- VernacInstance (false,snd namesup,(fst namesup,expl,t),props,info)
-
- | IDENT "Existing"; IDENT "Instance"; id = global;
- info = hint_info ->
- VernacDeclareInstances [id, info]
-
- | IDENT "Existing"; IDENT "Instances"; ids = LIST1 global;
- pri = OPT [ "|"; i = natural -> i ] ->
- let info = { Typeclasses.hint_priority = pri; hint_pattern = None } in
- let insts = List.map (fun i -> (i, info)) ids in
- VernacDeclareInstances insts
-
- | IDENT "Existing"; IDENT "Class"; is = global -> VernacDeclareClass is
-
- (* Arguments *)
- | IDENT "Arguments"; qid = smart_global;
- args = LIST0 argument_spec_block;
- more_implicits = OPT
- [ ","; impl = LIST1
- [ impl = LIST0 more_implicits_block -> List.flatten impl]
- SEP "," -> impl
- ];
- mods = OPT [ ":"; l = LIST1 arguments_modifier SEP "," -> l ] ->
- let mods = match mods with None -> [] | Some l -> List.flatten l in
- let slash_position = ref None in
- let rec parse_args i = function
- | [] -> []
- | `Id x :: args -> x :: parse_args (i+1) args
- | `Slash :: args ->
- if Option.is_empty !slash_position then
- (slash_position := Some i; parse_args i args)
- else
- user_err Pp.(str "The \"/\" modifier can occur only once")
- in
- let args = parse_args 0 (List.flatten args) in
- let more_implicits = Option.default [] more_implicits in
- VernacArguments (qid, args, more_implicits, !slash_position, mods)
-
- | IDENT "Implicit"; "Type"; bl = reserv_list ->
- VernacReserve bl
-
- | IDENT "Implicit"; IDENT "Types"; bl = reserv_list ->
- test_plural_form_types loc "Implicit Types" bl;
- VernacReserve bl
-
- | IDENT "Generalizable";
- gen = [IDENT "All"; IDENT "Variables" -> Some []
- | IDENT "No"; IDENT "Variables" -> None
- | ["Variable" | IDENT "Variables"];
- idl = LIST1 identref -> Some idl ] ->
- VernacGeneralizable gen ] ]
- ;
- arguments_modifier:
- [ [ IDENT "simpl"; IDENT "nomatch" -> [`ReductionDontExposeCase]
- | IDENT "simpl"; IDENT "never" -> [`ReductionNeverUnfold]
- | IDENT "default"; IDENT "implicits" -> [`DefaultImplicits]
- | IDENT "clear"; IDENT "implicits" -> [`ClearImplicits]
- | IDENT "clear"; IDENT "scopes" -> [`ClearScopes]
- | IDENT "rename" -> [`Rename]
- | IDENT "assert" -> [`Assert]
- | IDENT "extra"; IDENT "scopes" -> [`ExtraScopes]
- | IDENT "clear"; IDENT "scopes"; IDENT "and"; IDENT "implicits" ->
- [`ClearImplicits; `ClearScopes]
- | IDENT "clear"; IDENT "implicits"; IDENT "and"; IDENT "scopes" ->
- [`ClearImplicits; `ClearScopes]
- ] ]
- ;
- scope:
- [ [ "%"; key = IDENT -> key ] ]
- ;
- argument_spec: [
- [ b = OPT "!"; id = name ; s = OPT scope ->
- id.CAst.v, not (Option.is_empty b), Option.map (fun x -> CAst.make ~loc:!@loc x) s
- ]
- ];
- (* List of arguments implicit status, scope, modifiers *)
- argument_spec_block: [
- [ item = argument_spec ->
- let name, recarg_like, notation_scope = item in
- [`Id { name=name; recarg_like=recarg_like;
- notation_scope=notation_scope;
- implicit_status = NotImplicit}]
- | "/" -> [`Slash]
- | "("; items = LIST1 argument_spec; ")"; sc = OPT scope ->
- let f x = match sc, x with
- | None, x -> x | x, None -> Option.map (fun y -> CAst.make ~loc:!@loc y) x
- | Some _, Some _ -> user_err Pp.(str "scope declared twice") in
- List.map (fun (name,recarg_like,notation_scope) ->
- `Id { name=name; recarg_like=recarg_like;
- notation_scope=f notation_scope;
- implicit_status = NotImplicit}) items
- | "["; items = LIST1 argument_spec; "]"; sc = OPT scope ->
- let f x = match sc, x with
- | None, x -> x | x, None -> Option.map (fun y -> CAst.make ~loc:!@loc y) x
- | Some _, Some _ -> user_err Pp.(str "scope declared twice") in
- List.map (fun (name,recarg_like,notation_scope) ->
- `Id { name=name; recarg_like=recarg_like;
- notation_scope=f notation_scope;
- implicit_status = Implicit}) items
- | "{"; items = LIST1 argument_spec; "}"; sc = OPT scope ->
- let f x = match sc, x with
- | None, x -> x | x, None -> Option.map (fun y -> CAst.make ~loc:!@loc y) x
- | Some _, Some _ -> user_err Pp.(str "scope declared twice") in
- List.map (fun (name,recarg_like,notation_scope) ->
- `Id { name=name; recarg_like=recarg_like;
- notation_scope=f notation_scope;
- implicit_status = MaximallyImplicit}) items
- ]
- ];
- (* Same as [argument_spec_block], but with only implicit status and names *)
- more_implicits_block: [
- [ name = name -> [(name.CAst.v, Vernacexpr.NotImplicit)]
- | "["; items = LIST1 name; "]" ->
- List.map (fun name -> (name.CAst.v, Vernacexpr.Implicit)) items
- | "{"; items = LIST1 name; "}" ->
- List.map (fun name -> (name.CAst.v, Vernacexpr.MaximallyImplicit)) items
- ]
- ];
- strategy_level:
- [ [ IDENT "expand" -> Conv_oracle.Expand
- | IDENT "opaque" -> Conv_oracle.Opaque
- | n=INT -> Conv_oracle.Level (int_of_string n)
- | "-"; n=INT -> Conv_oracle.Level (- int_of_string n)
- | IDENT "transparent" -> Conv_oracle.transparent ] ]
- ;
- instance_name:
- [ [ name = ident_decl; sup = OPT binders ->
- (CAst.map (fun id -> Name id) (fst name), snd name),
- (Option.default [] sup)
- | -> ((CAst.make ~loc:!@loc Anonymous), None), [] ] ]
- ;
- hint_info:
- [ [ "|"; i = OPT natural; pat = OPT constr_pattern ->
- { Typeclasses.hint_priority = i; hint_pattern = pat }
- | -> { Typeclasses.hint_priority = None; hint_pattern = None } ] ]
- ;
- reserv_list:
- [ [ bl = LIST1 reserv_tuple -> bl | b = simple_reserv -> [b] ] ]
- ;
- reserv_tuple:
- [ [ "("; a = simple_reserv; ")" -> a ] ]
- ;
- simple_reserv:
- [ [ idl = LIST1 identref; ":"; c = lconstr -> (idl,c) ] ]
- ;
-
-END
-
-GEXTEND Gram
- GLOBAL: command query_command class_rawexpr gallina_ext;
-
- gallina_ext:
- [ [ IDENT "Export"; "Set"; table = option_table; v = option_value ->
- VernacSetOption (true, table, v)
- | IDENT "Export"; IDENT "Unset"; table = option_table ->
- VernacUnsetOption (true, table)
- ] ];
-
- command:
- [ [ IDENT "Comments"; l = LIST0 comment -> VernacComments l
-
- (* Hack! Should be in grammar_ext, but camlp5 factorizes badly *)
- | IDENT "Declare"; IDENT "Instance"; namesup = instance_name; ":";
- expl = [ "!" -> Decl_kinds.Implicit | -> Decl_kinds.Explicit ] ; t = operconstr LEVEL "200";
- info = hint_info ->
- VernacInstance (true, snd namesup, (fst namesup, expl, t), None, info)
-
- (* System directory *)
- | IDENT "Pwd" -> VernacChdir None
- | IDENT "Cd" -> VernacChdir None
- | IDENT "Cd"; dir = ne_string -> VernacChdir (Some dir)
-
- | IDENT "Load"; verbosely = [ IDENT "Verbose" -> true | -> false ];
- s = [ s = ne_string -> s | s = IDENT -> s ] ->
- VernacLoad (verbosely, s)
- | IDENT "Declare"; IDENT "ML"; IDENT "Module"; l = LIST1 ne_string ->
- VernacDeclareMLModule l
-
- | IDENT "Locate"; l = locatable -> VernacLocate l
-
- (* Managing load paths *)
- | IDENT "Add"; IDENT "LoadPath"; dir = ne_string; alias = as_dirpath ->
- VernacAddLoadPath (false, dir, alias)
- | IDENT "Add"; IDENT "Rec"; IDENT "LoadPath"; dir = ne_string;
- alias = as_dirpath -> VernacAddLoadPath (true, dir, alias)
- | IDENT "Remove"; IDENT "LoadPath"; dir = ne_string ->
- VernacRemoveLoadPath dir
-
- (* For compatibility *)
- | IDENT "AddPath"; dir = ne_string; "as"; alias = as_dirpath ->
- VernacAddLoadPath (false, dir, alias)
- | IDENT "AddRecPath"; dir = ne_string; "as"; alias = as_dirpath ->
- VernacAddLoadPath (true, dir, alias)
- | IDENT "DelPath"; dir = ne_string ->
- VernacRemoveLoadPath dir
-
- (* Type-Checking (pas dans le refman) *)
- | "Type"; c = lconstr -> VernacGlobalCheck c
-
- (* Printing (careful factorization of entries) *)
- | IDENT "Print"; p = printable -> VernacPrint p
- | IDENT "Print"; qid = smart_global; l = OPT univ_name_list -> VernacPrint (PrintName (qid,l))
- | IDENT "Print"; IDENT "Module"; "Type"; qid = global ->
- VernacPrint (PrintModuleType qid)
- | IDENT "Print"; IDENT "Module"; qid = global ->
- VernacPrint (PrintModule qid)
- | IDENT "Print"; IDENT "Namespace" ; ns = dirpath ->
- VernacPrint (PrintNamespace ns)
- | IDENT "Inspect"; n = natural -> VernacPrint (PrintInspect n)
-
- | IDENT "Add"; IDENT "ML"; IDENT "Path"; dir = ne_string ->
- VernacAddMLPath (false, dir)
- | IDENT "Add"; IDENT "Rec"; IDENT "ML"; IDENT "Path"; dir = ne_string ->
- VernacAddMLPath (true, dir)
-
- (* For acting on parameter tables *)
- | "Set"; table = option_table; v = option_value ->
- VernacSetOption (false, table, v)
- | IDENT "Unset"; table = option_table ->
- VernacUnsetOption (false, table)
-
- | IDENT "Print"; IDENT "Table"; table = option_table ->
- VernacPrintOption table
-
- | IDENT "Add"; table = IDENT; field = IDENT; v = LIST1 option_ref_value
- -> VernacAddOption ([table;field], v)
- (* A global value below will be hidden by a field above! *)
- (* In fact, we give priority to secondary tables *)
- (* No syntax for tertiary tables due to conflict *)
- (* (but they are unused anyway) *)
- | IDENT "Add"; table = IDENT; v = LIST1 option_ref_value ->
- VernacAddOption ([table], v)
-
- | IDENT "Test"; table = option_table; "for"; v = LIST1 option_ref_value
- -> VernacMemOption (table, v)
- | IDENT "Test"; table = option_table ->
- VernacPrintOption table
-
- | IDENT "Remove"; table = IDENT; field = IDENT; v= LIST1 option_ref_value
- -> VernacRemoveOption ([table;field], v)
- | IDENT "Remove"; table = IDENT; v = LIST1 option_ref_value ->
- VernacRemoveOption ([table], v) ]]
- ;
- query_command: (* TODO: rapprocher Eval et Check *)
- [ [ IDENT "Eval"; r = red_expr; "in"; c = lconstr; "." ->
- fun g -> VernacCheckMayEval (Some r, g, c)
- | IDENT "Compute"; c = lconstr; "." ->
- fun g -> VernacCheckMayEval (Some (Genredexpr.CbvVm None), g, c)
- | IDENT "Check"; c = lconstr; "." ->
- fun g -> VernacCheckMayEval (None, g, c)
- (* Searching the environment *)
- | IDENT "About"; qid = smart_global; l = OPT univ_name_list; "." ->
- fun g -> VernacPrint (PrintAbout (qid,l,g))
- | IDENT "SearchHead"; c = constr_pattern; l = in_or_out_modules; "." ->
- fun g -> VernacSearch (SearchHead c,g, l)
- | IDENT "SearchPattern"; c = constr_pattern; l = in_or_out_modules; "." ->
- fun g -> VernacSearch (SearchPattern c,g, l)
- | IDENT "SearchRewrite"; c = constr_pattern; l = in_or_out_modules; "." ->
- fun g -> VernacSearch (SearchRewrite c,g, l)
- | IDENT "Search"; s = searchabout_query; l = searchabout_queries; "." ->
- let (sl,m) = l in fun g -> VernacSearch (SearchAbout (s::sl),g, m)
- (* compatibility: SearchAbout *)
- | IDENT "SearchAbout"; s = searchabout_query; l = searchabout_queries; "." ->
- fun g -> let (sl,m) = l in VernacSearch (SearchAbout (s::sl),g, m)
- (* compatibility: SearchAbout with "[ ... ]" *)
- | IDENT "SearchAbout"; "["; sl = LIST1 searchabout_query; "]";
- l = in_or_out_modules; "." ->
- fun g -> VernacSearch (SearchAbout sl,g, l)
- ] ]
- ;
- printable:
- [ [ IDENT "Term"; qid = smart_global; l = OPT univ_name_list -> PrintName (qid,l)
- | IDENT "All" -> PrintFullContext
- | IDENT "Section"; s = global -> PrintSectionContext s
- | IDENT "Grammar"; ent = IDENT ->
- (* This should be in "syntax" section but is here for factorization*)
- PrintGrammar ent
- | IDENT "LoadPath"; dir = OPT dirpath -> PrintLoadPath dir
- | IDENT "Modules" ->
- user_err Pp.(str "Print Modules is obsolete; use Print Libraries instead")
- | IDENT "Libraries" -> PrintModules
-
- | IDENT "ML"; IDENT "Path" -> PrintMLLoadPath
- | IDENT "ML"; IDENT "Modules" -> PrintMLModules
- | IDENT "Debug"; IDENT "GC" -> PrintDebugGC
- | IDENT "Graph" -> PrintGraph
- | IDENT "Classes" -> PrintClasses
- | IDENT "TypeClasses" -> PrintTypeClasses
- | IDENT "Instances"; qid = smart_global -> PrintInstances qid
- | IDENT "Coercions" -> PrintCoercions
- | IDENT "Coercion"; IDENT "Paths"; s = class_rawexpr; t = class_rawexpr
- -> PrintCoercionPaths (s,t)
- | IDENT "Canonical"; IDENT "Projections" -> PrintCanonicalConversions
- | IDENT "Tables" -> PrintTables
- | IDENT "Options" -> PrintTables (* A Synonymous to Tables *)
- | IDENT "Hint" -> PrintHintGoal
- | IDENT "Hint"; qid = smart_global -> PrintHint qid
- | IDENT "Hint"; "*" -> PrintHintDb
- | IDENT "HintDb"; s = IDENT -> PrintHintDbName s
- | IDENT "Scopes" -> PrintScopes
- | IDENT "Scope"; s = IDENT -> PrintScope s
- | IDENT "Visibility"; s = OPT [x = IDENT -> x ] -> PrintVisibility s
- | IDENT "Implicit"; qid = smart_global -> PrintImplicit qid
- | IDENT "Universes"; fopt = OPT ne_string -> PrintUniverses (false, fopt)
- | IDENT "Sorted"; IDENT "Universes"; fopt = OPT ne_string -> PrintUniverses (true, fopt)
- | IDENT "Assumptions"; qid = smart_global -> PrintAssumptions (false, false, qid)
- | IDENT "Opaque"; IDENT "Dependencies"; qid = smart_global -> PrintAssumptions (true, false, qid)
- | IDENT "Transparent"; IDENT "Dependencies"; qid = smart_global -> PrintAssumptions (false, true, qid)
- | IDENT "All"; IDENT "Dependencies"; qid = smart_global -> PrintAssumptions (true, true, qid)
- | IDENT "Strategy"; qid = smart_global -> PrintStrategy (Some qid)
- | IDENT "Strategies" -> PrintStrategy None ] ]
- ;
- class_rawexpr:
- [ [ IDENT "Funclass" -> FunClass
- | IDENT "Sortclass" -> SortClass
- | qid = smart_global -> RefClass qid ] ]
- ;
- locatable:
- [ [ qid = smart_global -> LocateAny qid
- | IDENT "Term"; qid = smart_global -> LocateTerm qid
- | IDENT "File"; f = ne_string -> LocateFile f
- | IDENT "Library"; qid = global -> LocateLibrary qid
- | IDENT "Module"; qid = global -> LocateModule qid ] ]
- ;
- option_value:
- [ [ -> BoolValue true
- | n = integer -> IntValue (Some n)
- | s = STRING -> StringValue s ] ]
- ;
- option_ref_value:
- [ [ id = global -> QualidRefValue id
- | s = STRING -> StringRefValue s ] ]
- ;
- option_table:
- [ [ fl = LIST1 [ x = IDENT -> x ] -> fl ]]
- ;
- as_dirpath:
- [ [ d = OPT [ "as"; d = dirpath -> d ] -> d ] ]
- ;
- ne_in_or_out_modules:
- [ [ IDENT "inside"; l = LIST1 global -> SearchInside l
- | IDENT "outside"; l = LIST1 global -> SearchOutside l ] ]
- ;
- in_or_out_modules:
- [ [ m = ne_in_or_out_modules -> m
- | -> SearchOutside [] ] ]
- ;
- comment:
- [ [ c = constr -> CommentConstr c
- | s = STRING -> CommentString s
- | n = natural -> CommentInt n ] ]
- ;
- positive_search_mark:
- [ [ "-" -> false | -> true ] ]
- ;
- scope:
- [ [ "%"; key = IDENT -> key ] ]
- ;
- searchabout_query:
- [ [ b = positive_search_mark; s = ne_string; sc = OPT scope ->
- (b, SearchString (s,sc))
- | b = positive_search_mark; p = constr_pattern ->
- (b, SearchSubPattern p)
- ] ]
- ;
- searchabout_queries:
- [ [ m = ne_in_or_out_modules -> ([],m)
- | s = searchabout_query; l = searchabout_queries ->
- let (sl,m) = l in (s::sl,m)
- | -> ([],SearchOutside [])
- ] ]
- ;
- univ_name_list:
- [ [ "@{" ; l = LIST0 name; "}" -> l ] ]
- ;
-END;
-
-GEXTEND Gram
- command:
- [ [
-(* State management *)
- IDENT "Write"; IDENT "State"; s = IDENT -> VernacWriteState s
- | IDENT "Write"; IDENT "State"; s = ne_string -> VernacWriteState s
- | IDENT "Restore"; IDENT "State"; s = IDENT -> VernacRestoreState s
- | IDENT "Restore"; IDENT "State"; s = ne_string -> VernacRestoreState s
-
-(* Resetting *)
- | IDENT "Reset"; IDENT "Initial" -> VernacResetInitial
- | IDENT "Reset"; id = identref -> VernacResetName id
- | IDENT "Back" -> VernacBack 1
- | IDENT "Back"; n = natural -> VernacBack n
- | IDENT "BackTo"; n = natural -> VernacBackTo n
-
-(* Tactic Debugger *)
- | IDENT "Debug"; IDENT "On" ->
- VernacSetOption (false, ["Ltac";"Debug"], BoolValue true)
-
- | IDENT "Debug"; IDENT "Off" ->
- VernacSetOption (false, ["Ltac";"Debug"], BoolValue false)
-
-(* registration of a custom reduction *)
-
- | IDENT "Declare"; IDENT "Reduction"; s = IDENT; ":=";
- r = red_expr ->
- VernacDeclareReduction (s,r)
-
- ] ];
- END
-;;
-
-(* Grammar extensions *)
-
-GEXTEND Gram
- GLOBAL: syntax;
-
- syntax:
- [ [ IDENT "Open"; IDENT "Scope"; sc = IDENT ->
- VernacOpenCloseScope (true,sc)
-
- | IDENT "Close"; IDENT "Scope"; sc = IDENT ->
- VernacOpenCloseScope (false,sc)
-
- | IDENT "Delimit"; IDENT "Scope"; sc = IDENT; "with"; key = IDENT ->
- VernacDelimiters (sc, Some key)
- | IDENT "Undelimit"; IDENT "Scope"; sc = IDENT ->
- VernacDelimiters (sc, None)
-
- | IDENT "Bind"; IDENT "Scope"; sc = IDENT; "with";
- refl = LIST1 class_rawexpr -> VernacBindScope (sc,refl)
-
- | IDENT "Infix"; op = ne_lstring; ":="; p = constr;
- modl = [ "("; l = LIST1 syntax_modifier SEP ","; ")" -> l | -> [] ];
- sc = OPT [ ":"; sc = IDENT -> sc ] ->
- VernacInfix ((op,modl),p,sc)
- | IDENT "Notation"; id = identref;
- idl = LIST0 ident; ":="; c = constr; b = only_parsing ->
- VernacSyntacticDefinition
- (id,(idl,c),b)
- | IDENT "Notation"; s = lstring; ":=";
- c = constr;
- modl = [ "("; l = LIST1 syntax_modifier SEP ","; ")" -> l | -> [] ];
- sc = OPT [ ":"; sc = IDENT -> sc ] ->
- VernacNotation (c,(s,modl),sc)
- | IDENT "Format"; IDENT "Notation"; n = STRING; s = STRING; fmt = STRING ->
- VernacNotationAddFormat (n,s,fmt)
-
- | IDENT "Reserved"; IDENT "Infix"; s = ne_lstring;
- l = [ "("; l = LIST1 syntax_modifier SEP ","; ")" -> l | -> [] ] ->
- let s = CAst.map (fun s -> "x '"^s^"' y") s in
- VernacSyntaxExtension (true,(s,l))
-
- | IDENT "Reserved"; IDENT "Notation";
- s = ne_lstring;
- l = [ "("; l = LIST1 syntax_modifier SEP ","; ")" -> l | -> [] ]
- -> VernacSyntaxExtension (false, (s,l))
-
- (* "Print" "Grammar" should be here but is in "command" entry in order
- to factorize with other "Print"-based vernac entries *)
- ] ]
- ;
- only_parsing:
- [ [ "("; IDENT "only"; IDENT "parsing"; ")" ->
- Some Flags.Current
- | "("; IDENT "compat"; s = STRING; ")" ->
- Some (parse_compat_version s)
- | -> None ] ]
- ;
- level:
- [ [ IDENT "level"; n = natural -> NumLevel n
- | IDENT "next"; IDENT "level" -> NextLevel ] ]
- ;
- syntax_modifier:
- [ [ "at"; IDENT "level"; n = natural -> SetLevel n
- | IDENT "left"; IDENT "associativity" -> SetAssoc LeftA
- | IDENT "right"; IDENT "associativity" -> SetAssoc RightA
- | IDENT "no"; IDENT "associativity" -> SetAssoc NonA
- | IDENT "only"; IDENT "printing" -> SetOnlyPrinting
- | IDENT "only"; IDENT "parsing" -> SetOnlyParsing
- | IDENT "compat"; s = STRING ->
- SetCompatVersion (parse_compat_version s)
- | IDENT "format"; s1 = [s = STRING -> CAst.make ~loc:!@loc s];
- s2 = OPT [s = STRING -> CAst.make ~loc:!@loc s] ->
- begin match s1, s2 with
- | { CAst.v = k }, Some s -> SetFormat(k,s)
- | s, None -> SetFormat ("text",s) end
- | x = IDENT; ","; l = LIST1 [id = IDENT -> id ] SEP ","; "at";
- lev = level -> SetItemLevel (x::l,lev)
- | x = IDENT; "at"; lev = level -> SetItemLevel ([x],lev)
- | x = IDENT; "at"; lev = level; b = constr_as_binder_kind -> SetItemLevelAsBinder ([x],b,Some lev)
- | x = IDENT; b = constr_as_binder_kind -> SetItemLevelAsBinder ([x],b,None)
- | x = IDENT; typ = syntax_extension_type -> SetEntryType (x,typ)
- ] ]
- ;
- syntax_extension_type:
- [ [ IDENT "ident" -> ETName | IDENT "global" -> ETReference
- | IDENT "bigint" -> ETBigint
- | IDENT "binder" -> ETBinder true
- | IDENT "constr"; n = OPT at_level; b = constr_as_binder_kind -> ETConstrAsBinder (b,n)
- | IDENT "pattern" -> ETPattern (false,None)
- | IDENT "pattern"; "at"; IDENT "level"; n = natural -> ETPattern (false,Some n)
- | IDENT "strict"; IDENT "pattern" -> ETPattern (true,None)
- | IDENT "strict"; IDENT "pattern"; "at"; IDENT "level"; n = natural -> ETPattern (true,Some n)
- | IDENT "closed"; IDENT "binder" -> ETBinder false
- ] ]
- ;
- at_level:
- [ [ "at"; n = level -> n ] ]
- ;
- constr_as_binder_kind:
- [ [ "as"; IDENT "ident" -> Notation_term.AsIdent
- | "as"; IDENT "pattern" -> Notation_term.AsIdentOrPattern
- | "as"; IDENT "strict"; IDENT "pattern" -> Notation_term.AsStrictPattern ] ]
- ;
-END
diff --git a/vernac/g_vernac.mlg b/vernac/g_vernac.mlg
new file mode 100644
index 0000000000..74516e320c
--- /dev/null
+++ b/vernac/g_vernac.mlg
@@ -0,0 +1,1208 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+{
+
+open Pp
+open CErrors
+open Util
+open Names
+open Glob_term
+open Vernacexpr
+open Constrexpr
+open Constrexpr_ops
+open Extend
+open Decl_kinds
+open Declaremods
+open Declarations
+open Namegen
+open Tok (* necessary for camlp5 *)
+
+open Pcoq
+open Pcoq.Prim
+open Pcoq.Constr
+open Pcoq.Module
+open Pvernac.Vernac_
+
+let vernac_kw = [ ";"; ","; ">->"; ":<"; "<:"; "where"; "at" ]
+let _ = List.iter CLexer.add_keyword vernac_kw
+
+(* Rem: do not join the different GEXTEND into one, it breaks native *)
+(* compilation on PowerPC and Sun architectures *)
+
+let query_command = Entry.create "vernac:query_command"
+
+let subprf = Entry.create "vernac:subprf"
+
+let class_rawexpr = Entry.create "vernac:class_rawexpr"
+let thm_token = Entry.create "vernac:thm_token"
+let def_body = Entry.create "vernac:def_body"
+let decl_notation = Entry.create "vernac:decl_notation"
+let record_field = Entry.create "vernac:record_field"
+let of_type_with_opt_coercion = Entry.create "vernac:of_type_with_opt_coercion"
+let instance_name = Entry.create "vernac:instance_name"
+let section_subset_expr = Entry.create "vernac:section_subset_expr"
+
+let make_bullet s =
+ let open Proof_bullet in
+ let n = String.length s in
+ match s.[0] with
+ | '-' -> Dash n
+ | '+' -> Plus n
+ | '*' -> Star n
+ | _ -> assert false
+
+let parse_compat_version = let open Flags in function
+ | "8.8" -> Current
+ | "8.7" -> V8_7
+ | "8.6" -> V8_6
+ | ("8.5" | "8.4" | "8.3" | "8.2" | "8.1" | "8.0") as s ->
+ CErrors.user_err ~hdr:"get_compat_version"
+ Pp.(str "Compatibility with version " ++ str s ++ str " not supported.")
+ | s ->
+ CErrors.user_err ~hdr:"get_compat_version"
+ Pp.(str "Unknown compatibility version \"" ++ str s ++ str "\".")
+
+}
+
+GRAMMAR EXTEND Gram
+ GLOBAL: vernac_control gallina_ext noedit_mode subprf;
+ vernac_control: FIRST
+ [ [ IDENT "Time"; c = located_vernac -> { VernacTime (false,c) }
+ | 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 = decorated_vernac -> { let (f, v) = v in VernacExpr(f, v) } ]
+ ]
+ ;
+ decorated_vernac:
+ [ [ a = attributes ; fv = vernac -> { let (f, v) = fv in (List.append a f, v) }
+ | fv = vernac -> { fv } ]
+ ]
+ ;
+ attributes:
+ [ [ "#[" ; a = attribute_list ; "]" -> { a } ]
+ ]
+ ;
+ attribute_list:
+ [ [ a = LIST0 attribute SEP "," -> { a } ]
+ ]
+ ;
+ attribute:
+ [ [ k = ident ; v = attribute_value -> { Names.Id.to_string k, v } ]
+ ]
+ ;
+ attribute_value:
+ [ [ "=" ; v = string -> { VernacFlagLeaf v }
+ | "(" ; a = attribute_list ; ")" -> { VernacFlagList a }
+ | -> { VernacFlagEmpty } ]
+ ]
+ ;
+ vernac:
+ [ [ IDENT "Local"; v = vernac_poly -> { let (f, v) = v in (("local", VernacFlagEmpty) :: f, v) }
+ | IDENT "Global"; v = vernac_poly -> { let (f, v) = v in (("global", VernacFlagEmpty) :: f, v) }
+
+ | v = vernac_poly -> { v } ]
+ ]
+ ;
+ vernac_poly:
+ [ [ IDENT "Polymorphic"; v = vernac_aux -> { let (f, v) = v in (("polymorphic", VernacFlagEmpty) :: f, v) }
+ | IDENT "Monomorphic"; v = vernac_aux -> { let (f, v) = v in (("monomorphic", VernacFlagEmpty) :: 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; "." -> { (["program", VernacFlagEmpty], g) }
+ | IDENT "Program"; g = gallina_ext; "." -> { (["program", VernacFlagEmpty], g) }
+ | g = gallina; "." -> { ([], g) }
+ | g = gallina_ext; "." -> { ([], g) }
+ | c = command; "." -> { ([], c) }
+ | c = syntax; "." -> { ([], c) }
+ | c = subprf -> { ([], c) }
+ ] ]
+ ;
+ vernac_aux: LAST
+ [ [ prfcom = command_entry -> { ([], prfcom) } ] ]
+ ;
+ noedit_mode:
+ [ [ c = query_command -> { c None } ] ]
+ ;
+
+ subprf:
+ [ [ s = BULLET -> { VernacBullet (make_bullet s) }
+ | "{" -> { VernacSubproof None }
+ | "}" -> { VernacEndSubproof }
+ ] ]
+ ;
+
+ located_vernac:
+ [ [ v = vernac_control -> { CAst.make ~loc v } ] ]
+ ;
+END
+
+{
+
+let warn_plural_command =
+ CWarnings.create ~name:"plural-command" ~category:"pedantic" ~default:CWarnings.Disabled
+ (fun kwd -> strbrk (Printf.sprintf "Command \"%s\" expects more than one assumption." kwd))
+
+let test_plural_form loc kwd = function
+ | [(_,([_],_))] ->
+ warn_plural_command ~loc kwd
+ | _ -> ()
+
+let test_plural_form_types loc kwd = function
+ | [([_],_)] ->
+ warn_plural_command ~loc kwd
+ | _ -> ()
+
+let lname_of_lident : lident -> lname =
+ CAst.map (fun s -> Name s)
+
+let name_of_ident_decl : ident_decl -> name_decl =
+ on_fst lname_of_lident
+
+}
+
+(* Gallina declarations *)
+GRAMMAR EXTEND Gram
+ GLOBAL: gallina gallina_ext thm_token def_body of_type_with_opt_coercion
+ record_field decl_notation rec_definition ident_decl univ_decl;
+
+ gallina:
+ (* Definition, Theorem, Variable, Axiom, ... *)
+ [ [ thm = thm_token; id = ident_decl; bl = binders; ":"; c = lconstr;
+ l = LIST0
+ [ "with"; id = ident_decl; bl = binders; ":"; c = lconstr ->
+ { (id,(bl,c)) } ] ->
+ { VernacStartTheoremProof (thm, (id,(bl,c))::l) }
+ | stre = assumption_token; nl = inline; bl = assum_list ->
+ { VernacAssumption (stre, nl, bl) }
+ | tk = assumptions_token; nl = inline; bl = assum_list ->
+ { let (kwd,stre) = tk in
+ test_plural_form loc kwd bl;
+ VernacAssumption (stre, nl, bl) }
+ | d = def_token; id = ident_decl; b = def_body ->
+ { VernacDefinition (d, name_of_ident_decl id, b) }
+ | IDENT "Let"; id = identref; b = def_body ->
+ { VernacDefinition ((DoDischarge, Let), (lname_of_lident id, None), b) }
+ (* Gallina inductive declarations *)
+ | cum = OPT cumulativity_token; priv = private_token; f = finite_token;
+ indl = LIST1 inductive_definition SEP "with" ->
+ { let (k,f) = f in
+ let indl=List.map (fun ((a,b,c,d),e) -> ((a,b,c,k,d),e)) indl in
+ VernacInductive (cum, priv,f,indl) }
+ | "Fixpoint"; recs = LIST1 rec_definition SEP "with" ->
+ { VernacFixpoint (NoDischarge, recs) }
+ | IDENT "Let"; "Fixpoint"; recs = LIST1 rec_definition SEP "with" ->
+ { VernacFixpoint (DoDischarge, recs) }
+ | "CoFixpoint"; corecs = LIST1 corec_definition SEP "with" ->
+ { VernacCoFixpoint (NoDischarge, corecs) }
+ | IDENT "Let"; "CoFixpoint"; corecs = LIST1 corec_definition SEP "with" ->
+ { VernacCoFixpoint (DoDischarge, corecs) }
+ | IDENT "Scheme"; l = LIST1 scheme SEP "with" -> { VernacScheme l }
+ | IDENT "Combined"; IDENT "Scheme"; id = identref; IDENT "from";
+ l = LIST1 identref SEP "," -> { VernacCombinedScheme (id, l) }
+ | IDENT "Register"; IDENT "Inline"; id = identref ->
+ { VernacRegister(id, RegisterInline) }
+ | IDENT "Universe"; l = LIST1 identref -> { VernacUniverse l }
+ | IDENT "Universes"; l = LIST1 identref -> { VernacUniverse l }
+ | IDENT "Constraint"; l = LIST1 univ_constraint SEP "," -> { VernacConstraint l }
+ ] ]
+ ;
+
+ thm_token:
+ [ [ "Theorem" -> { Theorem }
+ | IDENT "Lemma" -> { Lemma }
+ | IDENT "Fact" -> { Fact }
+ | IDENT "Remark" -> { Remark }
+ | IDENT "Corollary" -> { Corollary }
+ | IDENT "Proposition" -> { Proposition }
+ | IDENT "Property" -> { Property } ] ]
+ ;
+ def_token:
+ [ [ "Definition" -> { (NoDischarge,Definition) }
+ | IDENT "Example" -> { (NoDischarge,Example) }
+ | IDENT "SubClass" -> { (NoDischarge,SubClass) } ] ]
+ ;
+ assumption_token:
+ [ [ "Hypothesis" -> { (DoDischarge, Logical) }
+ | "Variable" -> { (DoDischarge, Definitional) }
+ | "Axiom" -> { (NoDischarge, Logical) }
+ | "Parameter" -> { (NoDischarge, Definitional) }
+ | IDENT "Conjecture" -> { (NoDischarge, Conjectural) } ] ]
+ ;
+ assumptions_token:
+ [ [ IDENT "Hypotheses" -> { ("Hypotheses", (DoDischarge, Logical)) }
+ | IDENT "Variables" -> { ("Variables", (DoDischarge, Definitional)) }
+ | IDENT "Axioms" -> { ("Axioms", (NoDischarge, Logical)) }
+ | IDENT "Parameters" -> { ("Parameters", (NoDischarge, Definitional)) }
+ | IDENT "Conjectures" -> { ("Conjectures", (NoDischarge, Conjectural)) } ] ]
+ ;
+ inline:
+ [ [ IDENT "Inline"; "("; i = INT; ")" -> { InlineAt (int_of_string i) }
+ | IDENT "Inline" -> { DefaultInline }
+ | -> { NoInline } ] ]
+ ;
+ univ_constraint:
+ [ [ l = universe_level; ord = [ "<" -> { Univ.Lt } | "=" -> { Univ.Eq } | "<=" -> { Univ.Le } ];
+ r = universe_level -> { (l, ord, r) } ] ]
+ ;
+ univ_decl :
+ [ [ "@{" ; l = LIST0 identref; ext = [ "+" -> { true } | -> { false } ];
+ cs = [ "|"; l' = LIST0 univ_constraint SEP ",";
+ ext = [ "+" -> { true } | -> { false } ]; "}" -> { (l',ext) }
+ | ext = [ "}" -> { true } | "|}" -> { false } ] -> { ([], ext) } ]
+ ->
+ { let open UState in
+ { univdecl_instance = l;
+ univdecl_extensible_instance = ext;
+ univdecl_constraints = fst cs;
+ univdecl_extensible_constraints = snd cs } }
+ ] ]
+ ;
+ ident_decl:
+ [ [ i = identref; l = OPT univ_decl -> { (i, l) }
+ ] ]
+ ;
+ finite_token:
+ [ [ IDENT "Inductive" -> { (Inductive_kw,Finite) }
+ | IDENT "CoInductive" -> { (CoInductive,CoFinite) }
+ | IDENT "Variant" -> { (Variant,BiFinite) }
+ | IDENT "Record" -> { (Record,BiFinite) }
+ | IDENT "Structure" -> { (Structure,BiFinite) }
+ | IDENT "Class" -> { (Class true,BiFinite) } ] ]
+ ;
+ cumulativity_token:
+ [ [ IDENT "Cumulative" -> { VernacCumulative }
+ | IDENT "NonCumulative" -> { VernacNonCumulative } ] ]
+ ;
+ private_token:
+ [ [ IDENT "Private" -> { true } | -> { false } ] ]
+ ;
+ (* Simple definitions *)
+ def_body:
+ [ [ bl = binders; ":="; red = reduce; c = lconstr ->
+ { if List.exists (function CLocalPattern _ -> true | _ -> false) bl
+ then
+ (* FIXME: "red" will be applied to types in bl and Cast with remain *)
+ let c = mkCLambdaN ~loc bl c in
+ DefineBody ([], red, c, None)
+ else
+ (match c with
+ | { CAst.v = CCast(c, CastConv t) } -> DefineBody (bl, red, c, Some t)
+ | _ -> DefineBody (bl, red, c, None)) }
+ | bl = binders; ":"; t = lconstr; ":="; red = reduce; c = lconstr ->
+ { let ((bl, c), tyo) =
+ if List.exists (function CLocalPattern _ -> true | _ -> false) bl
+ then
+ (* FIXME: "red" will be applied to types in bl and Cast with remain *)
+ let c = CAst.make ~loc @@ CCast (c, CastConv t) in
+ (([],mkCLambdaN ~loc bl c), None)
+ else ((bl, c), Some t)
+ in
+ DefineBody (bl, red, c, tyo) }
+ | bl = binders; ":"; t = lconstr ->
+ { ProveBody (bl, t) } ] ]
+ ;
+ reduce:
+ [ [ IDENT "Eval"; r = red_expr; "in" -> { Some r }
+ | -> { None } ] ]
+ ;
+ one_decl_notation:
+ [ [ ntn = ne_lstring; ":="; c = constr;
+ scopt = OPT [ ":"; sc = IDENT -> { sc } ] -> { (ntn,c,scopt) } ] ]
+ ;
+ decl_sep:
+ [ [ IDENT "and" -> { () } ] ]
+ ;
+ decl_notation:
+ [ [ "where"; l = LIST1 one_decl_notation SEP decl_sep -> { l }
+ | -> { [] } ] ]
+ ;
+ (* Inductives and records *)
+ opt_constructors_or_fields:
+ [ [ ":="; lc = constructor_list_or_record_decl -> { lc }
+ | -> { RecordDecl (None, []) } ] ]
+ ;
+ inductive_definition:
+ [ [ oc = opt_coercion; id = ident_decl; indpar = binders;
+ c = OPT [ ":"; c = lconstr -> { c } ];
+ lc=opt_constructors_or_fields; ntn = decl_notation ->
+ { (((oc,id),indpar,c,lc),ntn) } ] ]
+ ;
+ constructor_list_or_record_decl:
+ [ [ "|"; l = LIST1 constructor SEP "|" -> { Constructors l }
+ | id = identref ; c = constructor_type; "|"; l = LIST0 constructor SEP "|" ->
+ { Constructors ((c id)::l) }
+ | id = identref ; c = constructor_type -> { Constructors [ c id ] }
+ | cstr = identref; "{"; fs = record_fields; "}" ->
+ { RecordDecl (Some cstr,fs) }
+ | "{";fs = record_fields; "}" -> { RecordDecl (None,fs) }
+ | -> { Constructors [] } ] ]
+ ;
+(*
+ csort:
+ [ [ s = sort -> CSort (loc,s) ] ]
+ ;
+*)
+ opt_coercion:
+ [ [ ">" -> { true }
+ | -> { false } ] ]
+ ;
+ (* (co)-fixpoints *)
+ rec_definition:
+ [ [ id = ident_decl;
+ bl = binders_fixannot;
+ ty = type_cstr;
+ def = OPT [":="; def = lconstr -> { def } ]; ntn = decl_notation ->
+ { let bl, annot = bl in ((id,annot,bl,ty,def),ntn) } ] ]
+ ;
+ corec_definition:
+ [ [ id = ident_decl; bl = binders; ty = type_cstr;
+ def = OPT [":="; def = lconstr -> { def }]; ntn = decl_notation ->
+ { ((id,bl,ty,def),ntn) } ] ]
+ ;
+ type_cstr:
+ [ [ ":"; c=lconstr -> { c }
+ | -> { CAst.make ~loc @@ CHole (None, IntroAnonymous, None) } ] ]
+ ;
+ (* Inductive schemes *)
+ scheme:
+ [ [ kind = scheme_kind -> { (None,kind) }
+ | id = identref; ":="; kind = scheme_kind -> { (Some id,kind) } ] ]
+ ;
+ scheme_kind:
+ [ [ IDENT "Induction"; "for"; ind = smart_global;
+ IDENT "Sort"; s = sort_family-> { InductionScheme(true,ind,s) }
+ | IDENT "Minimality"; "for"; ind = smart_global;
+ IDENT "Sort"; s = sort_family-> { InductionScheme(false,ind,s) }
+ | IDENT "Elimination"; "for"; ind = smart_global;
+ IDENT "Sort"; s = sort_family-> { CaseScheme(true,ind,s) }
+ | IDENT "Case"; "for"; ind = smart_global;
+ IDENT "Sort"; s = sort_family-> { CaseScheme(false,ind,s) }
+ | IDENT "Equality"; "for" ; ind = smart_global -> { EqualityScheme(ind) } ] ]
+ ;
+ (* Various Binders *)
+(*
+ (* ... without coercions *)
+ binder_nodef:
+ [ [ b = binder_let ->
+ (match b with
+ CLocalAssum(l,ty) -> (l,ty)
+ | CLocalDef _ ->
+ Util.user_err_loc
+ (loc,"fix_param",Pp.str"defined binder not allowed here.")) ] ]
+ ;
+*)
+ (* ... with coercions *)
+ record_field:
+ [ [ bd = record_binder; pri = OPT [ "|"; n = natural -> { n } ];
+ ntn = decl_notation -> { (bd,pri),ntn } ] ]
+ ;
+ record_fields:
+ [ [ f = record_field; ";"; fs = record_fields -> { f :: fs }
+ | f = record_field; ";" -> { [f] }
+ | f = record_field -> { [f] }
+ | -> { [] }
+ ] ]
+ ;
+ record_binder_body:
+ [ [ l = binders; oc = of_type_with_opt_coercion;
+ t = lconstr -> { fun id -> (oc,AssumExpr (id,mkCProdN ~loc l t)) }
+ | l = binders; oc = of_type_with_opt_coercion;
+ t = lconstr; ":="; b = lconstr -> { fun id ->
+ (oc,DefExpr (id,mkCLambdaN ~loc l b,Some (mkCProdN ~loc l t))) }
+ | l = binders; ":="; b = lconstr -> { fun id ->
+ match b.CAst.v with
+ | CCast(b', (CastConv t|CastVM t|CastNative t)) ->
+ (None,DefExpr(id,mkCLambdaN ~loc l b',Some (mkCProdN ~loc l t)))
+ | _ ->
+ (None,DefExpr(id,mkCLambdaN ~loc l b,None)) } ] ]
+ ;
+ record_binder:
+ [ [ id = name -> { (None,AssumExpr(id, CAst.make ~loc @@ CHole (None, IntroAnonymous, None))) }
+ | id = name; f = record_binder_body -> { f id } ] ]
+ ;
+ assum_list:
+ [ [ bl = LIST1 assum_coe -> { bl } | b = simple_assum_coe -> { [b] } ] ]
+ ;
+ assum_coe:
+ [ [ "("; a = simple_assum_coe; ")" -> { a } ] ]
+ ;
+ simple_assum_coe:
+ [ [ idl = LIST1 ident_decl; oc = of_type_with_opt_coercion; c = lconstr ->
+ { (not (Option.is_empty oc),(idl,c)) } ] ]
+ ;
+
+ constructor_type:
+ [[ l = binders;
+ t= [ coe = of_type_with_opt_coercion; c = lconstr ->
+ { fun l id -> (not (Option.is_empty coe),(id,mkCProdN ~loc l c)) }
+ | ->
+ { fun l id -> (false,(id,mkCProdN ~loc l (CAst.make ~loc @@ CHole (None, IntroAnonymous, None)))) } ]
+ -> { t l }
+ ]]
+;
+
+ constructor:
+ [ [ id = identref; c=constructor_type -> { c id } ] ]
+ ;
+ of_type_with_opt_coercion:
+ [ [ ":>>" -> { Some false }
+ | ":>"; ">" -> { Some false }
+ | ":>" -> { Some true }
+ | ":"; ">"; ">" -> { Some false }
+ | ":"; ">" -> { Some true }
+ | ":" -> { None } ] ]
+ ;
+END
+
+{
+
+let only_starredidentrefs =
+ Gram.Entry.of_parser "test_only_starredidentrefs"
+ (fun strm ->
+ let rec aux n =
+ match Util.stream_nth n strm with
+ | KEYWORD "." -> ()
+ | KEYWORD ")" -> ()
+ | (IDENT _ | KEYWORD "Type" | KEYWORD "*") -> aux (n+1)
+ | _ -> raise Stream.Failure in
+ aux 0)
+let starredidentreflist_to_expr l =
+ match l with
+ | [] -> SsEmpty
+ | x :: xs -> List.fold_right (fun i acc -> SsUnion(i,acc)) xs x
+
+let warn_deprecated_include_type =
+ CWarnings.create ~name:"deprecated-include-type" ~category:"deprecated"
+ (fun () -> strbrk "Include Type is deprecated; use Include instead")
+
+}
+
+(* Modules and Sections *)
+GRAMMAR EXTEND Gram
+ GLOBAL: gallina_ext module_expr module_type section_subset_expr;
+
+ gallina_ext:
+ [ [ (* Interactive module declaration *)
+ IDENT "Module"; export = export_token; id = identref;
+ bl = LIST0 module_binder; sign = of_module_type;
+ body = is_module_expr ->
+ { VernacDefineModule (export, id, bl, sign, body) }
+ | IDENT "Module"; "Type"; id = identref;
+ bl = LIST0 module_binder; sign = check_module_types;
+ body = is_module_type ->
+ { VernacDeclareModuleType (id, bl, sign, body) }
+ | IDENT "Declare"; IDENT "Module"; export = export_token; id = identref;
+ bl = LIST0 module_binder; ":"; mty = module_type_inl ->
+ { VernacDeclareModule (export, id, bl, mty) }
+ (* Section beginning *)
+ | IDENT "Section"; id = identref -> { VernacBeginSection id }
+ | IDENT "Chapter"; id = identref -> { VernacBeginSection id }
+
+ (* This end a Section a Module or a Module Type *)
+ | IDENT "End"; id = identref -> { VernacEndSegment id }
+
+ (* Naming a set of section hyps *)
+ | IDENT "Collection"; id = identref; ":="; expr = section_subset_expr ->
+ { VernacNameSectionHypSet (id, expr) }
+
+ (* Requiring an already compiled module *)
+ | IDENT "Require"; export = export_token; qidl = LIST1 global ->
+ { VernacRequire (None, export, qidl) }
+ | IDENT "From" ; ns = global ; IDENT "Require"; export = export_token
+ ; qidl = LIST1 global ->
+ { VernacRequire (Some ns, export, qidl) }
+ | IDENT "Import"; qidl = LIST1 global -> { VernacImport (false,qidl) }
+ | IDENT "Export"; qidl = LIST1 global -> { VernacImport (true,qidl) }
+ | IDENT "Include"; e = module_type_inl; l = LIST0 ext_module_expr ->
+ { VernacInclude(e::l) }
+ | IDENT "Include"; "Type"; e = module_type_inl; l = LIST0 ext_module_type ->
+ { warn_deprecated_include_type ~loc ();
+ VernacInclude(e::l) } ] ]
+ ;
+ export_token:
+ [ [ IDENT "Import" -> { Some false }
+ | IDENT "Export" -> { Some true }
+ | -> { None } ] ]
+ ;
+ ext_module_type:
+ [ [ "<+"; mty = module_type_inl -> { mty } ] ]
+ ;
+ ext_module_expr:
+ [ [ "<+"; mexpr = module_expr_inl -> { mexpr } ] ]
+ ;
+ check_module_type:
+ [ [ "<:"; mty = module_type_inl -> { mty } ] ]
+ ;
+ check_module_types:
+ [ [ mtys = LIST0 check_module_type -> { mtys } ] ]
+ ;
+ of_module_type:
+ [ [ ":"; mty = module_type_inl -> { Enforce mty }
+ | mtys = check_module_types -> { Check mtys } ] ]
+ ;
+ is_module_type:
+ [ [ ":="; mty = module_type_inl ; l = LIST0 ext_module_type -> { (mty::l) }
+ | -> { [] } ] ]
+ ;
+ is_module_expr:
+ [ [ ":="; mexpr = module_expr_inl; l = LIST0 ext_module_expr -> { (mexpr::l) }
+ | -> { [] } ] ]
+ ;
+ functor_app_annot:
+ [ [ "["; IDENT "inline"; "at"; IDENT "level"; i = INT; "]" ->
+ { InlineAt (int_of_string i) }
+ | "["; IDENT "no"; IDENT "inline"; "]" -> { NoInline }
+ | -> { DefaultInline }
+ ] ]
+ ;
+ module_expr_inl:
+ [ [ "!"; me = module_expr -> { (me,NoInline) }
+ | me = module_expr; a = functor_app_annot -> { (me,a) } ] ]
+ ;
+ module_type_inl:
+ [ [ "!"; me = module_type -> { (me,NoInline) }
+ | me = module_type; a = functor_app_annot -> { (me,a) } ] ]
+ ;
+ (* Module binder *)
+ module_binder:
+ [ [ "("; export = export_token; idl = LIST1 identref; ":";
+ mty = module_type_inl; ")" -> { (export,idl,mty) } ] ]
+ ;
+ (* Module expressions *)
+ module_expr:
+ [ [ me = module_expr_atom -> { me }
+ | me1 = module_expr; me2 = module_expr_atom -> { CAst.make ~loc @@ CMapply (me1,me2) }
+ ] ]
+ ;
+ module_expr_atom:
+ [ [ qid = qualid -> { CAst.make ~loc @@ CMident qid } | "("; me = module_expr; ")" -> { me } ] ]
+ ;
+ with_declaration:
+ [ [ "Definition"; fqid = fullyqualid; udecl = OPT univ_decl; ":="; c = Constr.lconstr ->
+ { CWith_Definition (fqid,udecl,c) }
+ | IDENT "Module"; fqid = fullyqualid; ":="; qid = qualid ->
+ { CWith_Module (fqid,qid) }
+ ] ]
+ ;
+ module_type:
+ [ [ qid = qualid -> { CAst.make ~loc @@ CMident qid }
+ | "("; mt = module_type; ")" -> { mt }
+ | mty = module_type; me = module_expr_atom ->
+ { CAst.make ~loc @@ CMapply (mty,me) }
+ | mty = module_type; "with"; decl = with_declaration ->
+ { CAst.make ~loc @@ CMwith (mty,decl) }
+ ] ]
+ ;
+ (* Proof using *)
+ section_subset_expr:
+ [ [ only_starredidentrefs; l = LIST0 starredidentref ->
+ { starredidentreflist_to_expr l }
+ | e = ssexpr -> { e } ]]
+ ;
+ starredidentref:
+ [ [ i = identref -> { SsSingl i }
+ | i = identref; "*" -> { SsFwdClose(SsSingl i) }
+ | "Type" -> { SsType }
+ | "Type"; "*" -> { SsFwdClose SsType } ]]
+ ;
+ ssexpr:
+ [ "35"
+ [ "-"; e = ssexpr -> { SsCompl e } ]
+ | "50"
+ [ e1 = ssexpr; "-"; e2 = ssexpr-> { SsSubstr(e1,e2) }
+ | e1 = ssexpr; "+"; e2 = ssexpr-> { SsUnion(e1,e2) } ]
+ | "0"
+ [ i = starredidentref -> { i }
+ | "("; only_starredidentrefs; l = LIST0 starredidentref; ")"->
+ { starredidentreflist_to_expr l }
+ | "("; only_starredidentrefs; l = LIST0 starredidentref; ")"; "*" ->
+ { SsFwdClose(starredidentreflist_to_expr l) }
+ | "("; e = ssexpr; ")"-> { e }
+ | "("; e = ssexpr; ")"; "*" -> { SsFwdClose e } ] ]
+ ;
+END
+
+(* Extensions: implicits, coercions, etc. *)
+GRAMMAR EXTEND Gram
+ GLOBAL: gallina_ext instance_name hint_info;
+
+ gallina_ext:
+ [ [ (* Transparent and Opaque *)
+ IDENT "Transparent"; l = LIST1 smart_global ->
+ { VernacSetOpacity (Conv_oracle.transparent, l) }
+ | IDENT "Opaque"; l = LIST1 smart_global ->
+ { VernacSetOpacity (Conv_oracle.Opaque, l) }
+ | IDENT "Strategy"; l =
+ LIST1 [ v=strategy_level; "["; q=LIST1 smart_global; "]" -> { (v,q) } ] ->
+ { VernacSetStrategy l }
+ (* Canonical structure *)
+ | IDENT "Canonical"; IDENT "Structure"; qid = global ->
+ { VernacCanonical CAst.(make ~loc @@ AN qid) }
+ | IDENT "Canonical"; IDENT "Structure"; ntn = by_notation ->
+ { VernacCanonical CAst.(make ~loc @@ ByNotation ntn) }
+ | IDENT "Canonical"; IDENT "Structure"; qid = global; d = def_body ->
+ { let s = coerce_reference_to_id qid in
+ VernacDefinition ((NoDischarge,CanonicalStructure),((CAst.make (Name s)),None),d) }
+
+ (* Coercions *)
+ | IDENT "Coercion"; qid = global; d = def_body ->
+ { let s = coerce_reference_to_id qid in
+ VernacDefinition ((NoDischarge,Coercion),((CAst.make (Name s)),None),d) }
+ | IDENT "Identity"; IDENT "Coercion"; f = identref; ":";
+ s = class_rawexpr; ">->"; t = class_rawexpr ->
+ { VernacIdentityCoercion (f, s, t) }
+ | IDENT "Coercion"; qid = global; ":"; s = class_rawexpr; ">->";
+ t = class_rawexpr ->
+ { VernacCoercion (CAst.make ~loc @@ AN qid, s, t) }
+ | IDENT "Coercion"; ntn = by_notation; ":"; s = class_rawexpr; ">->";
+ t = class_rawexpr ->
+ { VernacCoercion (CAst.make ~loc @@ ByNotation ntn, s, t) }
+
+ | IDENT "Context"; c = LIST1 binder ->
+ { VernacContext (List.flatten c) }
+
+ | IDENT "Instance"; namesup = instance_name; ":";
+ expl = [ "!" -> { Decl_kinds.Implicit } | -> { Decl_kinds.Explicit } ] ; t = operconstr LEVEL "200";
+ info = hint_info ;
+ props = [ ":="; "{"; r = record_declaration; "}" -> { Some (true,r) } |
+ ":="; c = lconstr -> { Some (false,c) } | -> { None } ] ->
+ { VernacInstance (false,snd namesup,(fst namesup,expl,t),props,info) }
+
+ | IDENT "Existing"; IDENT "Instance"; id = global;
+ info = hint_info ->
+ { VernacDeclareInstances [id, info] }
+
+ | IDENT "Existing"; IDENT "Instances"; ids = LIST1 global;
+ pri = OPT [ "|"; i = natural -> { i } ] ->
+ { let info = { Typeclasses.hint_priority = pri; hint_pattern = None } in
+ let insts = List.map (fun i -> (i, info)) ids in
+ VernacDeclareInstances insts }
+
+ | IDENT "Existing"; IDENT "Class"; is = global -> { VernacDeclareClass is }
+
+ (* Arguments *)
+ | IDENT "Arguments"; qid = smart_global;
+ args = LIST0 argument_spec_block;
+ more_implicits = OPT
+ [ ","; impl = LIST1
+ [ impl = LIST0 more_implicits_block -> { List.flatten impl } ]
+ SEP "," -> { impl }
+ ];
+ mods = OPT [ ":"; l = LIST1 arguments_modifier SEP "," -> { l } ] ->
+ { let mods = match mods with None -> [] | Some l -> List.flatten l in
+ let slash_position = ref None in
+ let rec parse_args i = function
+ | [] -> []
+ | `Id x :: args -> x :: parse_args (i+1) args
+ | `Slash :: args ->
+ if Option.is_empty !slash_position then
+ (slash_position := Some i; parse_args i args)
+ else
+ user_err Pp.(str "The \"/\" modifier can occur only once")
+ in
+ let args = parse_args 0 (List.flatten args) in
+ let more_implicits = Option.default [] more_implicits in
+ VernacArguments (qid, args, more_implicits, !slash_position, mods) }
+
+ | IDENT "Implicit"; "Type"; bl = reserv_list ->
+ { VernacReserve bl }
+
+ | IDENT "Implicit"; IDENT "Types"; bl = reserv_list ->
+ { test_plural_form_types loc "Implicit Types" bl;
+ VernacReserve bl }
+
+ | IDENT "Generalizable";
+ gen = [IDENT "All"; IDENT "Variables" -> { Some [] }
+ | IDENT "No"; IDENT "Variables" -> { None }
+ | ["Variable" -> { () } | IDENT "Variables" -> { () } ];
+ idl = LIST1 identref -> { Some idl } ] ->
+ { VernacGeneralizable gen } ] ]
+ ;
+ arguments_modifier:
+ [ [ IDENT "simpl"; IDENT "nomatch" -> { [`ReductionDontExposeCase] }
+ | IDENT "simpl"; IDENT "never" -> { [`ReductionNeverUnfold] }
+ | IDENT "default"; IDENT "implicits" -> { [`DefaultImplicits] }
+ | IDENT "clear"; IDENT "implicits" -> { [`ClearImplicits] }
+ | IDENT "clear"; IDENT "scopes" -> { [`ClearScopes] }
+ | IDENT "rename" -> { [`Rename] }
+ | IDENT "assert" -> { [`Assert] }
+ | IDENT "extra"; IDENT "scopes" -> { [`ExtraScopes] }
+ | IDENT "clear"; IDENT "scopes"; IDENT "and"; IDENT "implicits" ->
+ { [`ClearImplicits; `ClearScopes] }
+ | IDENT "clear"; IDENT "implicits"; IDENT "and"; IDENT "scopes" ->
+ { [`ClearImplicits; `ClearScopes] }
+ ] ]
+ ;
+ scope:
+ [ [ "%"; key = IDENT -> { key } ] ]
+ ;
+ argument_spec: [
+ [ b = OPT "!"; id = name ; s = OPT scope ->
+ { id.CAst.v, not (Option.is_empty b), Option.map (fun x -> CAst.make ~loc x) s }
+ ]
+ ];
+ (* List of arguments implicit status, scope, modifiers *)
+ argument_spec_block: [
+ [ item = argument_spec ->
+ { let name, recarg_like, notation_scope = item in
+ [`Id { name=name; recarg_like=recarg_like;
+ notation_scope=notation_scope;
+ implicit_status = NotImplicit}] }
+ | "/" -> { [`Slash] }
+ | "("; items = LIST1 argument_spec; ")"; sc = OPT scope ->
+ { let f x = match sc, x with
+ | None, x -> x | x, None -> Option.map (fun y -> CAst.make ~loc y) x
+ | Some _, Some _ -> user_err Pp.(str "scope declared twice") in
+ List.map (fun (name,recarg_like,notation_scope) ->
+ `Id { name=name; recarg_like=recarg_like;
+ notation_scope=f notation_scope;
+ implicit_status = NotImplicit}) items }
+ | "["; items = LIST1 argument_spec; "]"; sc = OPT scope ->
+ { let f x = match sc, x with
+ | None, x -> x | x, None -> Option.map (fun y -> CAst.make ~loc y) x
+ | Some _, Some _ -> user_err Pp.(str "scope declared twice") in
+ List.map (fun (name,recarg_like,notation_scope) ->
+ `Id { name=name; recarg_like=recarg_like;
+ notation_scope=f notation_scope;
+ implicit_status = Implicit}) items }
+ | "{"; items = LIST1 argument_spec; "}"; sc = OPT scope ->
+ { let f x = match sc, x with
+ | None, x -> x | x, None -> Option.map (fun y -> CAst.make ~loc y) x
+ | Some _, Some _ -> user_err Pp.(str "scope declared twice") in
+ List.map (fun (name,recarg_like,notation_scope) ->
+ `Id { name=name; recarg_like=recarg_like;
+ notation_scope=f notation_scope;
+ implicit_status = MaximallyImplicit}) items }
+ ]
+ ];
+ (* Same as [argument_spec_block], but with only implicit status and names *)
+ more_implicits_block: [
+ [ name = name -> { [(name.CAst.v, Vernacexpr.NotImplicit)] }
+ | "["; items = LIST1 name; "]" ->
+ { List.map (fun name -> (name.CAst.v, Vernacexpr.Implicit)) items }
+ | "{"; items = LIST1 name; "}" ->
+ { List.map (fun name -> (name.CAst.v, Vernacexpr.MaximallyImplicit)) items }
+ ]
+ ];
+ strategy_level:
+ [ [ IDENT "expand" -> { Conv_oracle.Expand }
+ | IDENT "opaque" -> { Conv_oracle.Opaque }
+ | n=INT -> { Conv_oracle.Level (int_of_string n) }
+ | "-"; n=INT -> { Conv_oracle.Level (- int_of_string n) }
+ | IDENT "transparent" -> { Conv_oracle.transparent } ] ]
+ ;
+ instance_name:
+ [ [ name = ident_decl; sup = OPT binders ->
+ { (CAst.map (fun id -> Name id) (fst name), snd name),
+ (Option.default [] sup) }
+ | -> { ((CAst.make ~loc Anonymous), None), [] } ] ]
+ ;
+ hint_info:
+ [ [ "|"; i = OPT natural; pat = OPT constr_pattern ->
+ { { Typeclasses.hint_priority = i; hint_pattern = pat } }
+ | -> { { Typeclasses.hint_priority = None; hint_pattern = None } } ] ]
+ ;
+ reserv_list:
+ [ [ bl = LIST1 reserv_tuple -> { bl } | b = simple_reserv -> { [b] } ] ]
+ ;
+ reserv_tuple:
+ [ [ "("; a = simple_reserv; ")" -> { a } ] ]
+ ;
+ simple_reserv:
+ [ [ idl = LIST1 identref; ":"; c = lconstr -> { (idl,c) } ] ]
+ ;
+
+END
+
+GRAMMAR EXTEND Gram
+ GLOBAL: command query_command class_rawexpr gallina_ext;
+
+ gallina_ext:
+ [ [ IDENT "Export"; "Set"; table = option_table; v = option_value ->
+ { VernacSetOption (true, table, v) }
+ | IDENT "Export"; IDENT "Unset"; table = option_table ->
+ { VernacUnsetOption (true, table) }
+ ] ];
+
+ command:
+ [ [ IDENT "Comments"; l = LIST0 comment -> { VernacComments l }
+
+ (* Hack! Should be in grammar_ext, but camlp5 factorizes badly *)
+ | IDENT "Declare"; IDENT "Instance"; namesup = instance_name; ":";
+ expl = [ "!" -> { Decl_kinds.Implicit } | -> { Decl_kinds.Explicit } ] ; t = operconstr LEVEL "200";
+ info = hint_info ->
+ { VernacInstance (true, snd namesup, (fst namesup, expl, t), None, info) }
+
+ (* System directory *)
+ | IDENT "Pwd" -> { VernacChdir None }
+ | IDENT "Cd" -> { VernacChdir None }
+ | IDENT "Cd"; dir = ne_string -> { VernacChdir (Some dir) }
+
+ | IDENT "Load"; verbosely = [ IDENT "Verbose" -> { true } | -> { false } ];
+ s = [ s = ne_string -> { s } | s = IDENT -> { s } ] ->
+ { VernacLoad (verbosely, s) }
+ | IDENT "Declare"; IDENT "ML"; IDENT "Module"; l = LIST1 ne_string ->
+ { VernacDeclareMLModule l }
+
+ | IDENT "Locate"; l = locatable -> { VernacLocate l }
+
+ (* Managing load paths *)
+ | IDENT "Add"; IDENT "LoadPath"; dir = ne_string; alias = as_dirpath ->
+ { VernacAddLoadPath (false, dir, alias) }
+ | IDENT "Add"; IDENT "Rec"; IDENT "LoadPath"; dir = ne_string;
+ alias = as_dirpath -> { VernacAddLoadPath (true, dir, alias) }
+ | IDENT "Remove"; IDENT "LoadPath"; dir = ne_string ->
+ { VernacRemoveLoadPath dir }
+
+ (* For compatibility *)
+ | IDENT "AddPath"; dir = ne_string; "as"; alias = as_dirpath ->
+ { VernacAddLoadPath (false, dir, alias) }
+ | IDENT "AddRecPath"; dir = ne_string; "as"; alias = as_dirpath ->
+ { VernacAddLoadPath (true, dir, alias) }
+ | IDENT "DelPath"; dir = ne_string ->
+ { VernacRemoveLoadPath dir }
+
+ (* Type-Checking (pas dans le refman) *)
+ | "Type"; c = lconstr -> { VernacGlobalCheck c }
+
+ (* Printing (careful factorization of entries) *)
+ | IDENT "Print"; p = printable -> { VernacPrint p }
+ | IDENT "Print"; qid = smart_global; l = OPT univ_name_list -> { VernacPrint (PrintName (qid,l)) }
+ | IDENT "Print"; IDENT "Module"; "Type"; qid = global ->
+ { VernacPrint (PrintModuleType qid) }
+ | IDENT "Print"; IDENT "Module"; qid = global ->
+ { VernacPrint (PrintModule qid) }
+ | IDENT "Print"; IDENT "Namespace" ; ns = dirpath ->
+ { VernacPrint (PrintNamespace ns) }
+ | IDENT "Inspect"; n = natural -> { VernacPrint (PrintInspect n) }
+
+ | IDENT "Add"; IDENT "ML"; IDENT "Path"; dir = ne_string ->
+ { VernacAddMLPath (false, dir) }
+ | IDENT "Add"; IDENT "Rec"; IDENT "ML"; IDENT "Path"; dir = ne_string ->
+ { VernacAddMLPath (true, dir) }
+
+ (* For acting on parameter tables *)
+ | "Set"; table = option_table; v = option_value ->
+ { VernacSetOption (false, table, v) }
+ | IDENT "Unset"; table = option_table ->
+ { VernacUnsetOption (false, table) }
+
+ | IDENT "Print"; IDENT "Table"; table = option_table ->
+ { VernacPrintOption table }
+
+ | IDENT "Add"; table = IDENT; field = IDENT; v = LIST1 option_ref_value
+ -> { VernacAddOption ([table;field], v) }
+ (* A global value below will be hidden by a field above! *)
+ (* In fact, we give priority to secondary tables *)
+ (* No syntax for tertiary tables due to conflict *)
+ (* (but they are unused anyway) *)
+ | IDENT "Add"; table = IDENT; v = LIST1 option_ref_value ->
+ { VernacAddOption ([table], v) }
+
+ | IDENT "Test"; table = option_table; "for"; v = LIST1 option_ref_value
+ -> { VernacMemOption (table, v) }
+ | IDENT "Test"; table = option_table ->
+ { VernacPrintOption table }
+
+ | IDENT "Remove"; table = IDENT; field = IDENT; v= LIST1 option_ref_value
+ -> { VernacRemoveOption ([table;field], v) }
+ | IDENT "Remove"; table = IDENT; v = LIST1 option_ref_value ->
+ { VernacRemoveOption ([table], v) } ]]
+ ;
+ query_command: (* TODO: rapprocher Eval et Check *)
+ [ [ IDENT "Eval"; r = red_expr; "in"; c = lconstr; "." ->
+ { fun g -> VernacCheckMayEval (Some r, g, c) }
+ | IDENT "Compute"; c = lconstr; "." ->
+ { fun g -> VernacCheckMayEval (Some (Genredexpr.CbvVm None), g, c) }
+ | IDENT "Check"; c = lconstr; "." ->
+ { fun g -> VernacCheckMayEval (None, g, c) }
+ (* Searching the environment *)
+ | IDENT "About"; qid = smart_global; l = OPT univ_name_list; "." ->
+ { fun g -> VernacPrint (PrintAbout (qid,l,g)) }
+ | IDENT "SearchHead"; c = constr_pattern; l = in_or_out_modules; "." ->
+ { fun g -> VernacSearch (SearchHead c,g, l) }
+ | IDENT "SearchPattern"; c = constr_pattern; l = in_or_out_modules; "." ->
+ { fun g -> VernacSearch (SearchPattern c,g, l) }
+ | IDENT "SearchRewrite"; c = constr_pattern; l = in_or_out_modules; "." ->
+ { fun g -> VernacSearch (SearchRewrite c,g, l) }
+ | IDENT "Search"; s = searchabout_query; l = searchabout_queries; "." ->
+ { let (sl,m) = l in fun g -> VernacSearch (SearchAbout (s::sl),g, m) }
+ (* compatibility: SearchAbout *)
+ | IDENT "SearchAbout"; s = searchabout_query; l = searchabout_queries; "." ->
+ { fun g -> let (sl,m) = l in VernacSearch (SearchAbout (s::sl),g, m) }
+ (* compatibility: SearchAbout with "[ ... ]" *)
+ | IDENT "SearchAbout"; "["; sl = LIST1 searchabout_query; "]";
+ l = in_or_out_modules; "." ->
+ { fun g -> VernacSearch (SearchAbout sl,g, l) }
+ ] ]
+ ;
+ printable:
+ [ [ IDENT "Term"; qid = smart_global; l = OPT univ_name_list -> { PrintName (qid,l) }
+ | IDENT "All" -> { PrintFullContext }
+ | IDENT "Section"; s = global -> { PrintSectionContext s }
+ | IDENT "Grammar"; ent = IDENT ->
+ (* This should be in "syntax" section but is here for factorization*)
+ { PrintGrammar ent }
+ | IDENT "LoadPath"; dir = OPT dirpath -> { PrintLoadPath dir }
+ | IDENT "Modules" ->
+ { user_err Pp.(str "Print Modules is obsolete; use Print Libraries instead") }
+ | IDENT "Libraries" -> { PrintModules }
+
+ | IDENT "ML"; IDENT "Path" -> { PrintMLLoadPath }
+ | IDENT "ML"; IDENT "Modules" -> { PrintMLModules }
+ | IDENT "Debug"; IDENT "GC" -> { PrintDebugGC }
+ | IDENT "Graph" -> { PrintGraph }
+ | IDENT "Classes" -> { PrintClasses }
+ | IDENT "TypeClasses" -> { PrintTypeClasses }
+ | IDENT "Instances"; qid = smart_global -> { PrintInstances qid }
+ | IDENT "Coercions" -> { PrintCoercions }
+ | IDENT "Coercion"; IDENT "Paths"; s = class_rawexpr; t = class_rawexpr
+ -> { PrintCoercionPaths (s,t) }
+ | IDENT "Canonical"; IDENT "Projections" -> { PrintCanonicalConversions }
+ | IDENT "Tables" -> { PrintTables }
+ | IDENT "Options" -> { PrintTables (* A Synonymous to Tables *) }
+ | IDENT "Hint" -> { PrintHintGoal }
+ | IDENT "Hint"; qid = smart_global -> { PrintHint qid }
+ | IDENT "Hint"; "*" -> { PrintHintDb }
+ | IDENT "HintDb"; s = IDENT -> { PrintHintDbName s }
+ | IDENT "Scopes" -> { PrintScopes }
+ | IDENT "Scope"; s = IDENT -> { PrintScope s }
+ | IDENT "Visibility"; s = OPT IDENT -> { PrintVisibility s }
+ | IDENT "Implicit"; qid = smart_global -> { PrintImplicit qid }
+ | IDENT "Universes"; fopt = OPT ne_string -> { PrintUniverses (false, fopt) }
+ | IDENT "Sorted"; IDENT "Universes"; fopt = OPT ne_string -> { PrintUniverses (true, fopt) }
+ | IDENT "Assumptions"; qid = smart_global -> { PrintAssumptions (false, false, qid) }
+ | IDENT "Opaque"; IDENT "Dependencies"; qid = smart_global -> { PrintAssumptions (true, false, qid) }
+ | IDENT "Transparent"; IDENT "Dependencies"; qid = smart_global -> { PrintAssumptions (false, true, qid) }
+ | IDENT "All"; IDENT "Dependencies"; qid = smart_global -> { PrintAssumptions (true, true, qid) }
+ | IDENT "Strategy"; qid = smart_global -> { PrintStrategy (Some qid) }
+ | IDENT "Strategies" -> { PrintStrategy None } ] ]
+ ;
+ class_rawexpr:
+ [ [ IDENT "Funclass" -> { FunClass }
+ | IDENT "Sortclass" -> { SortClass }
+ | qid = smart_global -> { RefClass qid } ] ]
+ ;
+ locatable:
+ [ [ qid = smart_global -> { LocateAny qid }
+ | IDENT "Term"; qid = smart_global -> { LocateTerm qid }
+ | IDENT "File"; f = ne_string -> { LocateFile f }
+ | IDENT "Library"; qid = global -> { LocateLibrary qid }
+ | IDENT "Module"; qid = global -> { LocateModule qid } ] ]
+ ;
+ option_value:
+ [ [ -> { BoolValue true }
+ | n = integer -> { IntValue (Some n) }
+ | s = STRING -> { StringValue s } ] ]
+ ;
+ option_ref_value:
+ [ [ id = global -> { QualidRefValue id }
+ | s = STRING -> { StringRefValue s } ] ]
+ ;
+ option_table:
+ [ [ fl = LIST1 [ x = IDENT -> { x } ] -> { fl } ]]
+ ;
+ as_dirpath:
+ [ [ d = OPT [ "as"; d = dirpath -> { d } ] -> { d } ] ]
+ ;
+ ne_in_or_out_modules:
+ [ [ IDENT "inside"; l = LIST1 global -> { SearchInside l }
+ | IDENT "outside"; l = LIST1 global -> { SearchOutside l } ] ]
+ ;
+ in_or_out_modules:
+ [ [ m = ne_in_or_out_modules -> { m }
+ | -> { SearchOutside [] } ] ]
+ ;
+ comment:
+ [ [ c = constr -> { CommentConstr c }
+ | s = STRING -> { CommentString s }
+ | n = natural -> { CommentInt n } ] ]
+ ;
+ positive_search_mark:
+ [ [ "-" -> { false } | -> { true } ] ]
+ ;
+ scope:
+ [ [ "%"; key = IDENT -> { key } ] ]
+ ;
+ searchabout_query:
+ [ [ b = positive_search_mark; s = ne_string; sc = OPT scope ->
+ { (b, SearchString (s,sc)) }
+ | b = positive_search_mark; p = constr_pattern ->
+ { (b, SearchSubPattern p) }
+ ] ]
+ ;
+ searchabout_queries:
+ [ [ m = ne_in_or_out_modules -> { ([],m) }
+ | s = searchabout_query; l = searchabout_queries ->
+ { let (sl,m) = l in (s::sl,m) }
+ | -> { ([],SearchOutside []) }
+ ] ]
+ ;
+ univ_name_list:
+ [ [ "@{" ; l = LIST0 name; "}" -> { l } ] ]
+ ;
+END
+
+GRAMMAR EXTEND Gram
+ GLOBAL: command;
+
+ command:
+ [ [
+(* State management *)
+ IDENT "Write"; IDENT "State"; s = IDENT -> { VernacWriteState s }
+ | IDENT "Write"; IDENT "State"; s = ne_string -> { VernacWriteState s }
+ | IDENT "Restore"; IDENT "State"; s = IDENT -> { VernacRestoreState s }
+ | IDENT "Restore"; IDENT "State"; s = ne_string -> { VernacRestoreState s }
+
+(* Resetting *)
+ | IDENT "Reset"; IDENT "Initial" -> { VernacResetInitial }
+ | IDENT "Reset"; id = identref -> { VernacResetName id }
+ | IDENT "Back" -> { VernacBack 1 }
+ | IDENT "Back"; n = natural -> { VernacBack n }
+ | IDENT "BackTo"; n = natural -> { VernacBackTo n }
+
+(* Tactic Debugger *)
+ | IDENT "Debug"; IDENT "On" ->
+ { VernacSetOption (false, ["Ltac";"Debug"], BoolValue true) }
+
+ | IDENT "Debug"; IDENT "Off" ->
+ { VernacSetOption (false, ["Ltac";"Debug"], BoolValue false) }
+
+(* registration of a custom reduction *)
+
+ | IDENT "Declare"; IDENT "Reduction"; s = IDENT; ":=";
+ r = red_expr ->
+ { VernacDeclareReduction (s,r) }
+
+(* factorized here, though relevant for syntax extensions *)
+
+ | IDENT "Declare"; IDENT "Custom"; IDENT "Entry"; s = IDENT ->
+ { VernacDeclareCustomEntry s }
+
+ ] ];
+ END
+
+(* Grammar extensions *)
+
+GRAMMAR EXTEND Gram
+ GLOBAL: syntax;
+
+ syntax:
+ [ [ IDENT "Open"; IDENT "Scope"; sc = IDENT ->
+ { VernacOpenCloseScope (true,sc) }
+
+ | IDENT "Close"; IDENT "Scope"; sc = IDENT ->
+ { VernacOpenCloseScope (false,sc) }
+
+ | IDENT "Delimit"; IDENT "Scope"; sc = IDENT; "with"; key = IDENT ->
+ { VernacDelimiters (sc, Some key) }
+ | IDENT "Undelimit"; IDENT "Scope"; sc = IDENT ->
+ { VernacDelimiters (sc, None) }
+
+ | IDENT "Bind"; IDENT "Scope"; sc = IDENT; "with";
+ refl = LIST1 class_rawexpr -> { VernacBindScope (sc,refl) }
+
+ | IDENT "Infix"; op = ne_lstring; ":="; p = constr;
+ modl = [ "("; l = LIST1 syntax_modifier SEP ","; ")" -> { l } | -> { [] } ];
+ sc = OPT [ ":"; sc = IDENT -> { sc } ] ->
+ { VernacInfix ((op,modl),p,sc) }
+ | IDENT "Notation"; id = identref;
+ idl = LIST0 ident; ":="; c = constr; b = only_parsing ->
+ { VernacSyntacticDefinition
+ (id,(idl,c),b) }
+ | IDENT "Notation"; s = lstring; ":=";
+ c = constr;
+ modl = [ "("; l = LIST1 syntax_modifier SEP ","; ")" -> { l } | -> { [] } ];
+ sc = OPT [ ":"; sc = IDENT -> { sc } ] ->
+ { VernacNotation (c,(s,modl),sc) }
+ | IDENT "Format"; IDENT "Notation"; n = STRING; s = STRING; fmt = STRING ->
+ { VernacNotationAddFormat (n,s,fmt) }
+
+ | IDENT "Reserved"; IDENT "Infix"; s = ne_lstring;
+ l = [ "("; l = LIST1 syntax_modifier SEP ","; ")" -> { l } | -> { [] } ] ->
+ { let s = CAst.map (fun s -> "x '"^s^"' y") s in
+ VernacSyntaxExtension (true,(s,l)) }
+
+ | IDENT "Reserved"; IDENT "Notation";
+ s = ne_lstring;
+ l = [ "("; l = LIST1 syntax_modifier SEP ","; ")" -> { l } | -> { [] } ]
+ -> { VernacSyntaxExtension (false, (s,l)) }
+
+ (* "Print" "Grammar" should be here but is in "command" entry in order
+ to factorize with other "Print"-based vernac entries *)
+ ] ]
+ ;
+ only_parsing:
+ [ [ "("; IDENT "only"; IDENT "parsing"; ")" ->
+ { Some Flags.Current }
+ | "("; IDENT "compat"; s = STRING; ")" ->
+ { Some (parse_compat_version s) }
+ | -> { None } ] ]
+ ;
+ level:
+ [ [ IDENT "level"; n = natural -> { NumLevel n }
+ | IDENT "next"; IDENT "level" -> { NextLevel } ] ]
+ ;
+ syntax_modifier:
+ [ [ "at"; IDENT "level"; n = natural -> { SetLevel n }
+ | "in"; IDENT "custom"; x = IDENT -> { SetCustomEntry (x,None) }
+ | "in"; IDENT "custom"; x = IDENT; "at"; IDENT "level"; n = natural ->
+ { SetCustomEntry (x,Some n) }
+ | IDENT "left"; IDENT "associativity" -> { SetAssoc LeftA }
+ | IDENT "right"; IDENT "associativity" -> { SetAssoc RightA }
+ | IDENT "no"; IDENT "associativity" -> { SetAssoc NonA }
+ | IDENT "only"; IDENT "printing" -> { SetOnlyPrinting }
+ | IDENT "only"; IDENT "parsing" -> { SetOnlyParsing }
+ | IDENT "compat"; s = STRING ->
+ { SetCompatVersion (parse_compat_version s) }
+ | IDENT "format"; s1 = [s = STRING -> { CAst.make ~loc s } ];
+ s2 = OPT [s = STRING -> { CAst.make ~loc s } ] ->
+ { begin match s1, s2 with
+ | { CAst.v = k }, Some s -> SetFormat(k,s)
+ | s, None -> SetFormat ("text",s) end }
+ | x = IDENT; ","; l = LIST1 [id = IDENT -> { id } ] SEP ","; "at";
+ lev = level -> { SetItemLevel (x::l,None,Some lev) }
+ | x = IDENT; "at"; lev = level -> { SetItemLevel ([x],None,Some lev) }
+ | x = IDENT; "at"; lev = level; b = constr_as_binder_kind ->
+ { SetItemLevel ([x],Some b,Some lev) }
+ | x = IDENT; b = constr_as_binder_kind -> { SetItemLevel ([x],Some b,None) }
+ | x = IDENT; typ = syntax_extension_type -> { SetEntryType (x,typ) }
+ ] ]
+ ;
+ syntax_extension_type:
+ [ [ IDENT "ident" -> { ETIdent } | IDENT "global" -> { ETGlobal }
+ | IDENT "bigint" -> { ETBigint }
+ | IDENT "binder" -> { ETBinder true }
+ | IDENT "constr" -> { ETConstr (InConstrEntry,None,None) }
+ | IDENT "constr"; n = OPT at_level; b = OPT constr_as_binder_kind -> { ETConstr (InConstrEntry,b,n) }
+ | IDENT "pattern" -> { ETPattern (false,None) }
+ | IDENT "pattern"; "at"; IDENT "level"; n = natural -> { ETPattern (false,Some n) }
+ | IDENT "strict"; IDENT "pattern" -> { ETPattern (true,None) }
+ | IDENT "strict"; IDENT "pattern"; "at"; IDENT "level"; n = natural -> { ETPattern (true,Some n) }
+ | IDENT "closed"; IDENT "binder" -> { ETBinder false }
+ | IDENT "custom"; x = IDENT; n = OPT at_level; b = OPT constr_as_binder_kind ->
+ { ETConstr (InCustomEntry x,b,n) }
+ ] ]
+ ;
+ at_level:
+ [ [ "at"; n = level -> { n } ] ]
+ ;
+ constr_as_binder_kind:
+ [ [ "as"; IDENT "ident" -> { Notation_term.AsIdent }
+ | "as"; IDENT "pattern" -> { Notation_term.AsIdentOrPattern }
+ | "as"; IDENT "strict"; IDENT "pattern" -> { Notation_term.AsStrictPattern } ] ]
+ ;
+END
diff --git a/vernac/himsg.ml b/vernac/himsg.ml
index 5d671ef529..b9c47ff475 100644
--- a/vernac/himsg.ml
+++ b/vernac/himsg.ml
@@ -194,12 +194,6 @@ let rec pr_disjunction pr = function
| a::l -> pr a ++ str "," ++ spc () ++ pr_disjunction pr l
| [] -> assert false
-let pr_puniverses f env (c,u) =
- f env c ++
- (if Flags.is_universe_polymorphism () && not (Univ.Instance.is_empty u) then
- str"(*" ++ Univ.Instance.pr UnivNames.pr_with_global_universes u ++ str"*)"
- else mt())
-
let explain_elim_arity env sigma ind sorts c pj okinds =
let open EConstr in
let env = make_all_name_different env sigma in
@@ -262,7 +256,7 @@ let explain_ill_formed_branch env sigma c ci actty expty =
let pa, pe = pr_explicit env sigma (simp actty) (simp expty) in
strbrk "In pattern-matching on term" ++ brk(1,1) ++ pc ++
spc () ++ strbrk "the branch for constructor" ++ spc () ++
- quote (pr_puniverses pr_constructor env ci) ++
+ quote (pr_pconstructor env sigma ci) ++
spc () ++ str "has type" ++ brk(1,1) ++ pa ++ spc () ++
str "which should be" ++ brk(1,1) ++ pe ++ str "."
@@ -520,11 +514,15 @@ let pr_trailing_ne_context_of env sigma =
then str "."
else (str " in environment:"++ pr_context_unlimited env sigma)
-let rec explain_evar_kind env sigma evk ty = function
+let rec explain_evar_kind env sigma evk ty =
+ let open Evar_kinds in
+ function
| Evar_kinds.NamedHole id ->
strbrk "the existential variable named " ++ Id.print id
- | Evar_kinds.QuestionMark _ ->
+ | Evar_kinds.QuestionMark {qm_record_field=None} ->
strbrk "this placeholder of type " ++ ty
+ | Evar_kinds.QuestionMark {qm_record_field=Some {fieldname; recordname}} ->
+ str "field " ++ (Printer.pr_constant env fieldname) ++ str " of record " ++ (Printer.pr_inductive env recordname)
| Evar_kinds.CasesType false ->
strbrk "the type of this pattern-matching problem"
| Evar_kinds.CasesType true ->
@@ -871,9 +869,6 @@ let explain_not_match_error = function
pr_enum (function Name id -> Id.print id | _ -> str "_") nal
| NotEqualInductiveAliases ->
str "Aliases to inductive types do not match"
- | NoTypeConstraintExpected ->
- strbrk "a definition whose type is constrained can only be subtype " ++
- strbrk "of a definition whose type is itself constrained"
| CumulativeStatusExpected b ->
let status b = if b then str"cumulative" else str"non-cumulative" in
str "a " ++ status b ++ str" declaration was expected, but a " ++
@@ -1232,12 +1227,7 @@ let explain_wrong_numarg_inductive env ind n =
str " expects " ++ decline_string n "argument" ++ str "."
let explain_unused_clause env pats =
-(* Without localisation
- let s = if List.length pats > 1 then "s" else "" in
- (str ("Unused clause with pattern"^s) ++ spc () ++
- hov 0 (pr_sequence pr_cases_pattern pats) ++ str ")")
-*)
- str "This clause is redundant."
+ str "Pattern \"" ++ hov 0 (prlist_with_sep pr_comma pr_cases_pattern pats) ++ strbrk "\" is redundant in this clause."
let explain_non_exhaustive env pats =
str "Non exhaustive pattern-matching: no clause found for " ++
diff --git a/vernac/himsg.mli b/vernac/himsg.mli
index 1d38075022..91caddcf13 100644
--- a/vernac/himsg.mli
+++ b/vernac/himsg.mli
@@ -25,7 +25,7 @@ val explain_pretype_error : env -> Evd.evar_map -> pretype_error -> Pp.t
val explain_inductive_error : inductive_error -> Pp.t
-val explain_mismatched_contexts : env -> contexts -> Constrexpr.constr_expr list -> Context.Rel.t -> Pp.t
+val explain_mismatched_contexts : env -> contexts -> Constrexpr.constr_expr list -> Constr.rel_context -> Pp.t
val explain_typeclass_error : env -> typeclass_error -> Pp.t
diff --git a/vernac/metasyntax.ml b/vernac/metasyntax.ml
index da14358ef5..d66a121437 100644
--- a/vernac/metasyntax.ml
+++ b/vernac/metasyntax.ml
@@ -49,7 +49,7 @@ let entry_buf = Buffer.create 64
let pr_entry e =
let () = Buffer.clear entry_buf in
let ft = Format.formatter_of_buffer entry_buf in
- let () = Pcoq.Gram.entry_print ft e in
+ let () = Pcoq.Entry.print ft e in
str (Buffer.contents entry_buf)
let pr_registered_grammar name =
@@ -283,20 +283,30 @@ let error_not_same_scope x y =
(**********************************************************************)
(* Build pretty-printing rules *)
+let pr_notation_entry = function
+ | InConstrEntry -> str "constr"
+ | InCustomEntry s -> str "custom " ++ str s
+
let prec_assoc = function
| RightA -> (L,E)
| LeftA -> (E,L)
| NonA -> (L,L)
-let precedence_of_position_and_level from = function
+let precedence_of_position_and_level from_level = function
| NumLevel n, BorderProd (_,None) -> n, Prec n
| NumLevel n, BorderProd (b,Some a) ->
n, let (lp,rp) = prec_assoc a in if b == Left then lp else rp
| NumLevel n, InternalProd -> n, Prec n
- | NextLevel, _ -> from, L
-
-let precedence_of_entry_type from = function
- | ETConstr x | ETConstrAsBinder (_,x) -> precedence_of_position_and_level from x
+ | NextLevel, _ -> from_level, L
+
+let precedence_of_entry_type (from_custom,from_level) = function
+ | ETConstr (custom,_,x) when notation_entry_eq custom from_custom ->
+ precedence_of_position_and_level from_level x
+ | ETConstr (custom,_,(NumLevel n,_)) -> n, Prec n
+ | ETConstr (custom,_,(NextLevel,_)) ->
+ user_err (strbrk "\"next level\" is only for sub-expressions in the same entry as where the notation is (" ++
+ quote (pr_notation_entry custom) ++ strbrk " is different from " ++
+ quote (pr_notation_entry from_custom) ++ str ").")
| ETPattern (_,n) -> let n = match n with None -> 0 | Some n -> n in n, Prec n
| _ -> 0, E (* should not matter *)
@@ -367,15 +377,14 @@ let unparsing_metavar i from typs =
let x = List.nth typs (i-1) in
let prec = snd (precedence_of_entry_type from x) in
match x with
- | ETConstr _ | ETConstrAsBinder _ | ETReference | ETBigint ->
+ | ETConstr _ | ETGlobal | ETBigint ->
UnpMetaVar (i,prec)
| ETPattern _ ->
UnpBinderMetaVar (i,prec)
- | ETName ->
- UnpBinderMetaVar (i,Prec 0)
+ | ETIdent ->
+ UnpBinderMetaVar (i,prec)
| ETBinder isopen ->
assert false
- | ETOther _ -> failwith "TODO"
(* Heuristics for building default printing rules *)
@@ -487,6 +496,15 @@ and check_no_ldots_in_box = function
let error_not_same ?loc () =
user_err ?loc Pp.(str "The format is not the same on the right- and left-hand sides of the special token \"..\".")
+let find_prod_list_loc sfmt fmt =
+ (* [fmt] is some [UnpTerminal x :: sfmt @ UnpTerminal ".." :: sfmt @ UnpTerminal y :: rest] *)
+ if List.is_empty sfmt then
+ (* No separators; we highlight the sequence "x .." *)
+ Loc.merge_opt (fst (List.hd fmt)) (fst (List.hd (List.tl fmt)))
+ else
+ (* A separator; we highlight the separating sequence *)
+ Loc.merge_opt (fst (List.hd sfmt)) (fst (List.last sfmt))
+
let skip_var_in_recursive_format = function
| (_,UnpTerminal s) :: sl (* skip first var *) when not (List.for_all (fun c -> c = " ") (String.explode s)) ->
(* To do, though not so important: check that the names match
@@ -496,6 +514,8 @@ let skip_var_in_recursive_format = function
| [] -> assert false
let read_recursive_format sl fmt =
+ (* Turn [[UnpTerminal s :: some-list @ UnpTerminal ".." :: same-some-list @ UnpTerminal s' :: rest] *)
+ (* into [(some-list,rest)] *)
let get_head fmt =
let sl = skip_var_in_recursive_format fmt in
try split_format_at_ldots [] sl with Exit -> error_not_same ?loc:(fst (List.last (if sl = [] then fmt else sl))) () in
@@ -528,10 +548,10 @@ let hunks_of_format (from,(vars,typs)) symfmt =
let i = index_id m vars in
let typ = List.nth typs (i-1) in
let _,prec = precedence_of_entry_type from typ in
- let slfmt,fmt = read_recursive_format sl fmt in
- let sl, slfmt = aux (sl,slfmt) in
- if not (List.is_empty sl) then error_format ?loc:(fst (List.last fmt)) ();
- let symbs, l = aux (symbs,fmt) in
+ let loc_slfmt,rfmt = read_recursive_format sl fmt in
+ let sl, slfmt = aux (sl,loc_slfmt) in
+ if not (List.is_empty sl) then error_format ?loc:(find_prod_list_loc loc_slfmt fmt) ();
+ let symbs, l = aux (symbs,rfmt) in
let hunk = match typ with
| ETConstr _ -> UnpListMetaVar (i,prec,slfmt)
| ETBinder isopen ->
@@ -550,11 +570,10 @@ let hunks_of_format (from,(vars,typs)) symfmt =
(**********************************************************************)
(* Build parsing rules *)
-let assoc_of_type n (_,typ) = precedence_of_entry_type n typ
+let assoc_of_type from n (_,typ) = precedence_of_entry_type (from,n) typ
let is_not_small_constr = function
ETProdConstr _ -> true
- | ETProdOther("constr","binder_constr") -> true
| _ -> false
let rec define_keywords_aux = function
@@ -584,9 +603,9 @@ let distribute a ll = List.map (fun l -> a @ l) ll
t;sep;t;...;t;sep;t;...;t;sep;t (p+n times)
t;sep;t;...;t;sep;t;...;t;sep;t;LIST1(t,sep) *)
-let expand_list_rule typ tkl x n p ll =
+let expand_list_rule s typ tkl x n p ll =
let camlp5_message_name = Some (add_suffix x ("_"^string_of_int n)) in
- let main = GramConstrNonTerminal (ETProdConstr typ, camlp5_message_name) in
+ let main = GramConstrNonTerminal (ETProdConstr (s,typ), camlp5_message_name) in
let tks = List.map (fun x -> GramConstrTerminal x) tkl in
let rec aux i hds ll =
if i < p then aux (i+1) (main :: tks @ hds) ll
@@ -602,7 +621,7 @@ let expand_list_rule typ tkl x n p ll =
let is_constr_typ typ x etyps =
match List.assoc x etyps with
- | ETConstr typ' | ETConstrAsBinder (_,typ') -> typ = typ'
+ | ETConstr (_,_,typ') -> typ = typ'
| _ -> false
let include_possible_similar_trailing_pattern typ etyps sl l =
@@ -616,13 +635,12 @@ let include_possible_similar_trailing_pattern typ etyps sl l =
try_aux 0 l
let prod_entry_type = function
- | ETName -> ETProdName
- | ETReference -> ETProdReference
+ | ETIdent -> ETProdName
+ | ETGlobal -> ETProdReference
| ETBigint -> ETProdBigint
| ETBinder _ -> assert false (* See check_binder_type *)
- | ETConstr p | ETConstrAsBinder (_,p) -> ETProdConstr p
+ | ETConstr (s,_,p) -> ETProdConstr (s,p)
| ETPattern (_,n) -> ETProdPattern (match n with None -> 0 | Some n -> n)
- | ETOther (s,t) -> ETProdOther (s,t)
let make_production etyps symbols =
let rec aux = function
@@ -640,9 +658,9 @@ let make_production etyps symbols =
| Break _ -> []
| _ -> anomaly (Pp.str "Found a non terminal token in recursive notation separator.")) sl) in
match List.assoc x etyps with
- | ETConstr typ ->
+ | ETConstr (s,_,typ) ->
let p,l' = include_possible_similar_trailing_pattern typ etyps sl l in
- expand_list_rule typ tkl x 1 p (aux l')
+ expand_list_rule s typ tkl x 1 p (aux l')
| ETBinder o ->
check_open_binder o sl x;
let typ = if o then (assert (tkl = []); ETBinderOpen) else ETBinderClosed tkl in
@@ -664,8 +682,7 @@ let rec find_symbols c_current c_next c_last = function
(x,c_next)::(find_symbols c_next c_next c_last sl')
let border = function
- | (_,ETConstr(_,BorderProd (_,a))) :: _ -> a
- | (_,(ETConstrAsBinder(_,(_,BorderProd (_,a))))) :: _ -> a
+ | (_,(ETConstr(_,_,(_,BorderProd (_,a))))) :: _ -> a
| _ -> None
let recompute_assoc typs =
@@ -687,23 +704,24 @@ let pr_arg_level from (lev,typ) =
| (n,_) -> str "Unknown level" in
Ppvernac.pr_set_entry_type (fun _ -> (*TO CHECK*) mt()) typ ++
(match typ with
- | ETConstr _ | ETConstrAsBinder _ | ETPattern _ -> spc () ++ pplev lev
+ | ETConstr _ | ETPattern _ -> spc () ++ pplev lev
| _ -> mt ())
-let pr_level ntn (from,args,typs) =
- str "at level " ++ int from ++ spc () ++ str "with arguments" ++ spc() ++
- prlist_with_sep pr_comma (pr_arg_level from) (List.combine args typs)
+let pr_level ntn (from,fromlevel,args,typs) =
+ (match from with InConstrEntry -> mt () | InCustomEntry s -> str "in " ++ str s ++ spc()) ++
+ str "at level " ++ int fromlevel ++ spc () ++ str "with arguments" ++ spc() ++
+ prlist_with_sep pr_comma (pr_arg_level fromlevel) (List.combine args typs)
let error_incompatible_level ntn oldprec prec =
user_err
- (str "Notation " ++ qstring ntn ++ str " is already defined" ++ spc() ++
+ (str "Notation " ++ pr_notation ntn ++ str " is already defined" ++ spc() ++
pr_level ntn oldprec ++
spc() ++ str "while it is now required to be" ++ spc() ++
pr_level ntn prec ++ str ".")
let error_parsing_incompatible_level ntn ntn' oldprec prec =
user_err
- (str "Notation " ++ qstring ntn ++ str " relies on a parsing rule for " ++ qstring ntn' ++ spc() ++
+ (str "Notation " ++ pr_notation ntn ++ str " relies on a parsing rule for " ++ pr_notation ntn' ++ spc() ++
str " which is already defined" ++ spc() ++
pr_level ntn oldprec ++
spc() ++ str "while it is now required to be" ++ spc() ++
@@ -727,7 +745,7 @@ type syntax_extension_obj = locality_flag * syntax_extension
let check_and_extend_constr_grammar ntn rule =
try
let ntn_for_grammar = rule.notgram_notation in
- if String.equal ntn ntn_for_grammar then raise Not_found;
+ if notation_eq ntn ntn_for_grammar then raise Not_found;
let prec = rule.notgram_level in
let oldprec = Notgram_ops.level_of_notation ntn_for_grammar in
if not (Notgram_ops.level_eq prec oldprec) then error_parsing_incompatible_level ntn ntn_for_grammar oldprec prec;
@@ -749,7 +767,7 @@ let cache_one_syntax_extension se =
if not onlyprint then List.iter (check_and_extend_constr_grammar ntn) se.synext_notgram.notgram_rules;
(* Declare the notation rule *)
declare_notation_rule ntn
- ~extra:se.synext_extra (se.synext_unparsing, pi1 prec) se.synext_notgram
+ ~extra:se.synext_extra (se.synext_unparsing, let (_,lev,_,_) = prec in lev) se.synext_notgram
end
let cache_syntax_extension (_, (_, sy)) =
@@ -786,7 +804,9 @@ module NotationMods = struct
type notation_modifier = {
assoc : gram_assoc option;
level : int option;
+ custom : notation_entry;
etyps : (Id.t * simple_constr_prod_entry_key) list;
+ subtyps : (Id.t * production_level) list;
(* common to syn_data below *)
only_parsing : bool;
@@ -799,7 +819,9 @@ type notation_modifier = {
let default = {
assoc = None;
level = None;
+ custom = InConstrEntry;
etyps = [];
+ subtyps = [];
only_parsing = false;
only_printing = false;
compat = None;
@@ -810,53 +832,75 @@ let default = {
end
let interp_modifiers modl = let open NotationMods in
- let rec interp acc = function
- | [] -> acc
+ let rec interp subtyps acc = function
+ | [] -> subtyps, acc
| SetEntryType (s,typ) :: l ->
let id = Id.of_string s in
if Id.List.mem_assoc id acc.etyps then
user_err ~hdr:"Metasyntax.interp_modifiers"
(str s ++ str " is already assigned to an entry or constr level.");
- interp { acc with etyps = (id,typ) :: acc.etyps; } l
- | SetItemLevel ([],n) :: l ->
- interp acc l
- | SetItemLevelAsBinder ([],_,_) :: l ->
- interp acc l
- | SetItemLevel (s::idl,n) :: l ->
+ interp subtyps { acc with etyps = (id,typ) :: acc.etyps; } l
+ | SetItemLevel ([],bko,n) :: l ->
+ interp subtyps acc l
+ | SetItemLevel (s::idl,bko,n) :: l ->
let id = Id.of_string s in
if Id.List.mem_assoc id acc.etyps then
user_err ~hdr:"Metasyntax.interp_modifiers"
(str s ++ str " is already assigned to an entry or constr level.");
- let typ = ETConstr (Some n) in
- interp { acc with etyps = (id,typ)::acc.etyps; } (SetItemLevel (idl,n)::l)
- | SetItemLevelAsBinder (s::idl,bk,n) :: l ->
- let id = Id.of_string s in
- if Id.List.mem_assoc id acc.etyps then
- user_err ~hdr:"Metasyntax.interp_modifiers"
- (str s ++ str " is already assigned to an entry or constr level.");
- let typ = ETConstrAsBinder (bk,n) in
- interp { acc with etyps = (id,typ)::acc.etyps; } (SetItemLevelAsBinder (idl,bk,n)::l)
+ interp ((id,bko,n)::subtyps) acc (SetItemLevel (idl,bko,n)::l)
| SetLevel n :: l ->
- interp { acc with level = Some n; } l
+ (match acc.custom with
+ | InCustomEntry s ->
+ if acc.level <> None then
+ user_err (str ("isolated \"at level " ^ string_of_int n ^ "\" unexpected."))
+ else
+ user_err (str ("use \"in custom " ^ s ^ " at level " ^ string_of_int n ^
+ "\"") ++ spc () ++ str "rather than" ++ spc () ++
+ str ("\"at level " ^ string_of_int n ^ "\"") ++
+ spc () ++ str "isolated.")
+ | InConstrEntry ->
+ if acc.level <> None then
+ user_err (str "A level is already assigned.");
+ interp subtyps { acc with level = Some n; } l)
+ | SetCustomEntry (s,n) :: l ->
+ if acc.level <> None then
+ (if n = None then
+ user_err (str ("use \"in custom " ^ s ^ " at level " ^
+ string_of_int (Option.get acc.level) ^
+ "\"") ++ spc () ++ str "rather than" ++ spc () ++
+ str ("\"at level " ^
+ string_of_int (Option.get acc.level) ^ "\"") ++
+ spc () ++ str "isolated.")
+ else
+ user_err (str ("isolated \"at level " ^ string_of_int (Option.get acc.level) ^ "\" unexpected.")));
+ if acc.custom <> InConstrEntry then
+ user_err (str "Entry is already assigned to custom " ++ str s ++ (match acc.level with None -> mt () | Some lev -> str " at level " ++ int lev) ++ str ".");
+ interp subtyps { acc with custom = InCustomEntry s; level = n } l
| SetAssoc a :: l ->
if not (Option.is_empty acc.assoc) then user_err Pp.(str "An associativity is given more than once.");
- interp { acc with assoc = Some a; } l
+ interp subtyps { acc with assoc = Some a; } l
| SetOnlyParsing :: l ->
- interp { acc with only_parsing = true; } l
+ interp subtyps { acc with only_parsing = true; } l
| SetOnlyPrinting :: l ->
- interp { acc with only_printing = true; } l
+ interp subtyps { acc with only_printing = true; } l
| SetCompatVersion v :: l ->
- interp { acc with compat = Some v; } l
+ interp subtyps { acc with compat = Some v; } l
| SetFormat ("text",s) :: l ->
if not (Option.is_empty acc.format) then user_err Pp.(str "A format is given more than once.");
- interp { acc with format = Some s; } l
- | SetFormat (k,{CAst.v=s}) :: l ->
- interp { acc with extra = (k,s)::acc.extra; } l
- in interp default modl
+ interp subtyps { acc with format = Some s; } l
+ | SetFormat (k,s) :: l ->
+ interp subtyps { acc with extra = (k,s.CAst.v)::acc.extra; } l
+ in
+ let subtyps,mods = interp [] default modl in
+ (* interpret item levels wrt to main entry *)
+ let extra_etyps = List.map (fun (id,bko,n) -> (id,ETConstr (mods.custom,bko,n))) subtyps in
+ { mods with etyps = extra_etyps@mods.etyps }
let check_infix_modifiers modifiers =
- let t = (interp_modifiers modifiers).NotationMods.etyps in
- if not (List.is_empty t) then
+ let mods = interp_modifiers modifiers in
+ let t = mods.NotationMods.etyps in
+ let u = mods.NotationMods.subtyps in
+ if not (List.is_empty t) || not (List.is_empty u) then
user_err Pp.(str "Explicit entry level or type unexpected in infix notation.")
let check_useless_entry_types recvars mainvars etyps =
@@ -897,21 +941,18 @@ let get_compat_version mods =
(* Compute precedences from modifiers (or find default ones) *)
-let set_entry_type etyps (x,typ) =
+let set_entry_type from etyps (x,typ) =
let typ = try
match List.assoc x etyps, typ with
- | ETConstr (Some n), (_,BorderProd (left,_)) ->
- ETConstr (n,BorderProd (left,None))
- | ETConstr (Some n), (_,InternalProd) -> ETConstr (n,InternalProd)
- | ETConstrAsBinder (bk, Some n), (_,BorderProd (left,_)) ->
- ETConstrAsBinder (bk, (n,BorderProd (left,None)))
- | ETConstrAsBinder (bk, Some n), (_,InternalProd) ->
- ETConstrAsBinder (bk, (n,InternalProd))
+ | ETConstr (s,bko,Some n), (_,BorderProd (left,_)) ->
+ ETConstr (s,bko,(n,BorderProd (left,None)))
+ | ETConstr (s,bko,Some n), (_,InternalProd) ->
+ ETConstr (s,bko,(n,InternalProd))
| ETPattern (b,n), _ -> ETPattern (b,n)
- | (ETName | ETBigint | ETReference | ETBinder _ | ETOther _ as x), _ -> x
- | ETConstr None, _ -> ETConstr typ
- | ETConstrAsBinder (bk,None), _ -> ETConstrAsBinder (bk,typ)
- with Not_found -> ETConstr typ
+ | (ETIdent | ETBigint | ETGlobal | ETBinder _ as x), _ -> x
+ | ETConstr (s,bko,None), _ -> ETConstr (s,bko,typ)
+ with Not_found ->
+ ETConstr (from,None,typ)
in (x,typ)
let join_auxiliary_recursive_types recvars etyps =
@@ -931,8 +972,8 @@ let join_auxiliary_recursive_types recvars etyps =
let internalization_type_of_entry_type = function
| ETBinder _ -> NtnInternTypeOnlyBinder
- | ETConstr _ | ETConstrAsBinder _ | ETBigint | ETReference
- | ETName | ETPattern _ | ETOther _ -> NtnInternTypeAny
+ | ETConstr _ | ETBigint | ETGlobal
+ | ETIdent | ETPattern _ -> NtnInternTypeAny
let set_internalization_type typs =
List.map (fun (_, e) -> internalization_type_of_entry_type e) typs
@@ -943,20 +984,28 @@ let make_internalization_vars recvars mainvars typs =
maintyps @ extratyps
let make_interpretation_type isrec isonlybinding = function
- | ETConstr _ ->
- if isrec then NtnTypeConstrList else
- if isonlybinding then
- (* Parsed as constr, but interpreted as a binder: default is to parse it as an ident only *)
- NtnTypeBinder (NtnBinderParsedAsConstr AsIdent)
- else NtnTypeConstr
- | ETConstrAsBinder (bk,_) -> NtnTypeBinder (NtnBinderParsedAsConstr bk)
- | ETName -> NtnTypeBinder NtnParsedAsIdent
+ (* Parsed as constr list *)
+ | ETConstr (_,None,_) when isrec -> NtnTypeConstrList
+ (* Parsed as constr, but interpreted as a binder: default is to parse it as an ident only *)
+ | ETConstr (_,Some bk,_) -> NtnTypeBinder (NtnBinderParsedAsConstr bk)
+ | ETConstr (_,None,_) when isonlybinding -> NtnTypeBinder (NtnBinderParsedAsConstr AsIdent)
+ (* Parsed as constr, interpreted as constr *)
+ | ETConstr (_,None,_) -> NtnTypeConstr
+ (* Others *)
+ | ETIdent -> NtnTypeBinder NtnParsedAsIdent
| ETPattern (ppstrict,_) -> NtnTypeBinder (NtnParsedAsPattern ppstrict) (* Parsed as ident/pattern, primarily interpreted as binder; maybe strict at printing *)
- | ETBigint | ETReference | ETOther _ -> NtnTypeConstr
+ | ETBigint | ETGlobal -> NtnTypeConstr
| ETBinder _ ->
if isrec then NtnTypeBinderList
else anomaly Pp.(str "Type binder is only for use in recursive notations for binders.")
+let subentry_of_constr_prod_entry = function
+ | ETConstr (InCustomEntry s,_,(NumLevel n,_)) -> InCustomEntryLevel (s,n)
+ (* level and use of parentheses for coercion is hard-wired for "constr";
+ we don't remember the level *)
+ | ETConstr (InConstrEntry,_,_) -> InConstrEntrySomeLevel
+ | _ -> InConstrEntrySomeLevel
+
let make_interpretation_vars recvars allvars typs =
let eq_subscope (sc1, l1) (sc2, l2) =
Option.equal String.equal sc1 sc2 &&
@@ -972,7 +1021,9 @@ let make_interpretation_vars recvars allvars typs =
let mainvars =
Id.Map.filter (fun x _ -> not (Id.List.mem x useless_recvars)) allvars in
Id.Map.mapi (fun x (isonlybinding, sc) ->
- (sc, make_interpretation_type (Id.List.mem_assoc x recvars) isonlybinding (Id.List.assoc x typs))) mainvars
+ let typ = Id.List.assoc x typs in
+ ((subentry_of_constr_prod_entry typ,sc),
+ make_interpretation_type (Id.List.mem_assoc x recvars) isonlybinding typ)) mainvars
let check_rule_productivity l =
if List.for_all (function NonTerminal _ | Break _ -> true | _ -> false) l then
@@ -998,17 +1049,42 @@ let warn_non_reversible_notation =
str " not occur in the right-hand side." ++ spc() ++
strbrk "The notation will not be used for printing as it is not reversible.")
-let is_not_printable onlyparse reversibility = function
-| NVar _ ->
- if not onlyparse then warn_notation_bound_to_variable ();
- true
+let make_custom_entry custom level =
+ match custom with
+ | InConstrEntry -> InConstrEntrySomeLevel
+ | InCustomEntry s -> InCustomEntryLevel (s,level)
+
+type entry_coercion_kind =
+ | IsEntryCoercion of notation_entry_level
+ | IsEntryGlobal of string * int
+ | IsEntryIdent of string * int
+
+let is_coercion = function
+ | Some (custom,n,_,[e]) ->
+ (match e, custom with
+ | ETConstr _, _ ->
+ let customkey = make_custom_entry custom n in
+ let subentry = subentry_of_constr_prod_entry e in
+ if notation_entry_level_eq subentry customkey then None
+ else Some (IsEntryCoercion subentry)
+ | ETGlobal, InCustomEntry s -> Some (IsEntryGlobal (s,n))
+ | ETIdent, InCustomEntry s -> Some (IsEntryIdent (s,n))
+ | _ -> None)
+ | Some _ -> assert false
+ | None -> None
+
+let printability level onlyparse reversibility = function
+| NVar _ when reversibility = APrioriReversible ->
+ let coe = is_coercion level in
+ if not onlyparse && coe = None then
+ warn_notation_bound_to_variable ();
+ true, coe
| _ ->
- if not onlyparse && reversibility <> APrioriReversible then
+ (if not onlyparse && reversibility <> APrioriReversible then
(warn_non_reversible_notation reversibility; true)
- else onlyparse
-
+ else onlyparse),None
-let find_precedence lev etyps symbols onlyprint =
+let find_precedence custom lev etyps symbols onlyprint =
let first_symbol =
let rec aux = function
| Break _ :: t -> aux t
@@ -1032,10 +1108,9 @@ let find_precedence lev etyps symbols onlyprint =
else [],Option.get lev
else
user_err Pp.(str "The level of the leftmost non-terminal cannot be changed.") in
- (try match List.assoc x etyps with
- | ETConstr _ -> test ()
- | ETConstrAsBinder (_,Some _) -> test ()
- | (ETName | ETBigint | ETReference) ->
+ (try match List.assoc x etyps, custom with
+ | ETConstr (s,_,Some _), s' when s = s' -> test ()
+ | (ETIdent | ETBigint | ETGlobal), _ ->
begin match lev with
| None ->
([Feedback.msg_info ?loc:None ,strbrk "Setting notation at level 0."],0)
@@ -1044,7 +1119,7 @@ let find_precedence lev etyps symbols onlyprint =
| _ ->
user_err Pp.(str "A notation starting with an atomic expression must be at level 0.")
end
- | (ETPattern _ | ETBinder _ | ETOther _ | ETConstrAsBinder _) ->
+ | (ETPattern _ | ETBinder _ | ETConstr _), _ ->
(* Give a default ? *)
if Option.is_empty lev then
user_err Pp.(str "Need an explicit level.")
@@ -1062,7 +1137,7 @@ let find_precedence lev etyps symbols onlyprint =
[],Option.get lev
let check_curly_brackets_notation_exists () =
- try let _ = Notgram_ops.level_of_notation "{ _ }" in ()
+ try let _ = Notgram_ops.level_of_notation (InConstrEntrySomeLevel,"{ _ }") in ()
with Not_found ->
user_err Pp.(str "Notations involving patterns of the form \"{ _ }\" are treated \n\
specially and require that the notation \"{ _ }\" is already reserved.")
@@ -1092,7 +1167,7 @@ let remove_curly_brackets l =
module SynData = struct
- type subentry_types = (Id.t * (production_level * production_position) constr_entry_key_gen) list
+ type subentry_types = (Id.t * constr_entry_key) list
(* XXX: Document *)
type syn_data = {
@@ -1126,7 +1201,7 @@ module SynData = struct
end
-let find_subentry_types n assoc etyps symbols =
+let find_subentry_types from n assoc etyps symbols =
let innerlevel = NumLevel 200 in
let typs =
find_symbols
@@ -1134,11 +1209,21 @@ let find_subentry_types n assoc etyps symbols =
(innerlevel,InternalProd)
(NumLevel n,BorderProd(Right,assoc))
symbols in
- let sy_typs = List.map (set_entry_type etyps) typs in
- let prec = List.map (assoc_of_type n) sy_typs in
+ let sy_typs = List.map (set_entry_type from etyps) typs in
+ let prec = List.map (assoc_of_type from n) sy_typs in
sy_typs, prec
-let compute_syntax_data df modifiers =
+let check_locality_compatibility local custom i_typs =
+ if not local then
+ let subcustom = List.map_filter (function _,ETConstr (InCustomEntry s,_,_) -> Some s | _ -> None) i_typs in
+ let allcustoms = match custom with InCustomEntry s -> s::subcustom | _ -> subcustom in
+ List.iter (fun s ->
+ if Egramcoq.locality_of_custom_entry s then
+ user_err (strbrk "Notation has to be declared local as it depends on custom entry " ++ str s ++
+ strbrk " which is local."))
+ (List.uniquize allcustoms)
+
+let compute_syntax_data local df modifiers =
let open SynData in
let open NotationMods in
let mods = interp_modifiers modifiers in
@@ -1151,25 +1236,28 @@ let compute_syntax_data df modifiers =
let _ = check_binder_type recvars mods.etyps in
(* Notations for interp and grammar *)
- let ntn_for_interp = make_notation_key symbols in
- let symbols_for_grammar = remove_curly_brackets symbols in
+ let msgs,n = find_precedence mods.custom mods.level mods.etyps symbols onlyprint in
+ let custom = make_custom_entry mods.custom n in
+ let ntn_for_interp = make_notation_key custom symbols in
+ let symbols_for_grammar =
+ if custom = InConstrEntrySomeLevel then remove_curly_brackets symbols else symbols in
let need_squash = not (List.equal Notation.symbol_eq symbols symbols_for_grammar) in
- let ntn_for_grammar = if need_squash then make_notation_key symbols_for_grammar else ntn_for_interp in
- if not onlyprint then check_rule_productivity symbols_for_grammar;
- let msgs,n = find_precedence mods.level mods.etyps symbols onlyprint in
+ let ntn_for_grammar = if need_squash then make_notation_key custom symbols_for_grammar else ntn_for_interp in
+ if mods.custom = InConstrEntry && not onlyprint then check_rule_productivity symbols_for_grammar;
(* To globalize... *)
let etyps = join_auxiliary_recursive_types recvars mods.etyps in
let sy_typs, prec =
- find_subentry_types n assoc etyps symbols in
+ find_subentry_types mods.custom n assoc etyps symbols in
let sy_typs_for_grammar, prec_for_grammar =
if need_squash then
- find_subentry_types n assoc etyps symbols_for_grammar
+ find_subentry_types mods.custom n assoc etyps symbols_for_grammar
else
sy_typs, prec in
let i_typs = set_internalization_type sy_typs in
+ check_locality_compatibility local mods.custom sy_typs;
let pa_sy_data = (sy_typs_for_grammar,symbols_for_grammar) in
let pp_sy_data = (sy_typs,symbols) in
- let sy_fulldata = (ntn_for_grammar,(n,prec_for_grammar,List.map snd sy_typs_for_grammar),need_squash) in
+ let sy_fulldata = (ntn_for_grammar,(mods.custom,n,prec_for_grammar,List.map snd sy_typs_for_grammar),need_squash) in
let df' = ((Lib.library_dp(),Lib.current_dirpath true),df) in
let i_data = ntn_for_interp, df' in
@@ -1188,15 +1276,15 @@ let compute_syntax_data df modifiers =
mainvars;
intern_typs = i_typs;
- level = (n,prec,List.map snd sy_typs);
+ level = (mods.custom,n,prec,List.map snd sy_typs);
pa_syntax_data = pa_sy_data;
pp_syntax_data = pp_sy_data;
not_data = sy_fulldata;
}
-let compute_pure_syntax_data df mods =
+let compute_pure_syntax_data local df mods =
let open SynData in
- let sd = compute_syntax_data df mods in
+ let sd = compute_syntax_data local df mods in
let msgs =
if sd.only_parsing then
(Feedback.msg_warning ?loc:None,
@@ -1211,6 +1299,7 @@ type notation_obj = {
notobj_local : bool;
notobj_scope : scope_name option;
notobj_interp : interpretation;
+ notobj_coercion : entry_coercion_kind option;
notobj_onlyparse : bool;
notobj_onlyprint : bool;
notobj_compat : Flags.compat_version option;
@@ -1232,7 +1321,13 @@ let open_notation i (_, nobj) =
let () = Notation.declare_notation_interpretation ntn scope pat df ~onlyprint in
(* Declare the uninterpretation *)
if not nobj.notobj_onlyparse then
- Notation.declare_uninterpretation (NotationRule (scope, ntn)) pat
+ Notation.declare_uninterpretation (NotationRule (scope, ntn)) pat;
+ (* Declare a possible coercion *)
+ (match nobj.notobj_coercion with
+ | Some (IsEntryCoercion entry) -> Notation.declare_entry_coercion ntn entry
+ | Some (IsEntryGlobal (entry,n)) -> Notation.declare_custom_entry_has_global entry n
+ | Some (IsEntryIdent (entry,n)) -> Notation.declare_custom_entry_has_ident entry n
+ | None -> ())
end
let cache_notation o =
@@ -1290,7 +1385,7 @@ let recover_notation_syntax ntn =
raise NoSyntaxRule
let recover_squash_syntax sy =
- let sq = recover_notation_syntax "{ _ }" in
+ let sq = recover_notation_syntax (InConstrEntrySomeLevel,"{ _ }") in
sy :: sq.synext_notgram.notgram_rules
(**********************************************************************)
@@ -1312,14 +1407,22 @@ let make_pa_rule level (typs,symbols) ntn need_squash =
let make_pp_rule level (typs,symbols) fmt =
match fmt with
- | None -> [UnpBox (PpHOVB 0, make_hunks typs symbols level)]
- | Some fmt -> hunks_of_format (level, List.split typs) (symbols, parse_format fmt)
+ | None ->
+ let hunks = make_hunks typs symbols level in
+ if List.exists (function _,(UnpCut (PpBrk _) | UnpListMetaVar _) -> true | _ -> false) hunks then
+ [UnpBox (PpHOVB 0,hunks)]
+ else
+ (* Optimization to work around what seems an ocaml Format bug (see Mantis #7804/#7807) *)
+ List.map snd hunks (* drop locations which are dummy *)
+ | Some fmt ->
+ hunks_of_format (level, List.split typs) (symbols, parse_format fmt)
(* let make_syntax_rules i_typs (ntn,prec,need_squash) sy_data fmt extra onlyprint compat = *)
let make_syntax_rules (sd : SynData.syn_data) = let open SynData in
let ntn_for_grammar, prec_for_grammar, need_squash = sd.not_data in
+ let custom,level,_,_ = sd.level in
let pa_rule = make_pa_rule prec_for_grammar sd.pa_syntax_data ntn_for_grammar need_squash in
- let pp_rule = make_pp_rule (pi1 sd.level) sd.pp_syntax_data sd.format in {
+ let pp_rule = make_pp_rule (custom,level) sd.pp_syntax_data sd.format in {
synext_level = sd.level;
synext_notation = fst sd.info;
synext_notgram = { notgram_onlyprinting = sd.only_printing; notgram_rules = pa_rule };
@@ -1337,7 +1440,7 @@ let to_map l =
let add_notation_in_scope local df env c mods scope =
let open SynData in
- let sd = compute_syntax_data df mods in
+ let sd = compute_syntax_data local df mods in
(* Prepare the interpretation *)
(* Prepare the parsing and printing rules *)
let sy_rules = make_syntax_rules sd in
@@ -1349,13 +1452,14 @@ let add_notation_in_scope local df env c mods scope =
let (acvars, ac, reversibility) = interp_notation_constr env nenv c in
let interp = make_interpretation_vars sd.recvars acvars (fst sd.pa_syntax_data) in
let map (x, _) = try Some (x, Id.Map.find x interp) with Not_found -> None in
- let onlyparse = is_not_printable sd.only_parsing reversibility ac in
+ let onlyparse,coe = printability (Some sd.level) sd.only_parsing reversibility ac in
let notation = {
notobj_local = local;
notobj_scope = scope;
notobj_interp = (List.map_filter map i_vars, ac);
(** Order is important here! *)
notobj_onlyparse = onlyparse;
+ notobj_coercion = coe;
notobj_onlyprint = sd.only_printing;
notobj_compat = sd.compat;
notobj_notation = sd.info;
@@ -1369,16 +1473,17 @@ let add_notation_in_scope local df env c mods scope =
let add_notation_interpretation_core local df env ?(impls=empty_internalization_env) c scope onlyparse onlyprint compat =
let (recvars,mainvars,symbs) = analyze_notation_tokens ~onlyprint df in
(* Recover types of variables and pa/pp rules; redeclare them if needed *)
- let i_typs, onlyprint = if not (is_numeral symbs) then begin
- let sy = recover_notation_syntax (make_notation_key symbs) in
+ let level, i_typs, onlyprint = if not (is_numeral symbs) then begin
+ let sy = recover_notation_syntax (make_notation_key InConstrEntrySomeLevel symbs) in
let () = Lib.add_anonymous_leaf (inSyntaxExtension (local,sy)) in
(** If the only printing flag has been explicitly requested, put it back *)
let onlyprint = onlyprint || sy.synext_notgram.notgram_onlyprinting in
- pi3 sy.synext_level, onlyprint
- end else [], false in
+ let _,_,_,typs = sy.synext_level in
+ Some sy.synext_level, typs, onlyprint
+ end else None, [], false in
(* Declare interpretation *)
let path = (Lib.library_dp(), Lib.current_dirpath true) in
- let df' = (make_notation_key symbs, (path,df)) in
+ let df' = (make_notation_key InConstrEntrySomeLevel symbs, (path,df)) in
let i_vars = make_internalization_vars recvars mainvars (List.map internalization_type_of_entry_type i_typs) in
let nenv = {
ninterp_var_type = to_map i_vars;
@@ -1387,13 +1492,14 @@ let add_notation_interpretation_core local df env ?(impls=empty_internalization_
let (acvars, ac, reversibility) = interp_notation_constr env ~impls nenv c in
let interp = make_interpretation_vars recvars acvars (List.combine mainvars i_typs) in
let map (x, _) = try Some (x, Id.Map.find x interp) with Not_found -> None in
- let onlyparse = is_not_printable onlyparse reversibility ac in
+ let onlyparse,coe = printability level onlyparse reversibility ac in
let notation = {
notobj_local = local;
notobj_scope = scope;
notobj_interp = (List.map_filter map i_vars, ac);
(** Order is important here! *)
notobj_onlyparse = onlyparse;
+ notobj_coercion = coe;
notobj_onlyprint = onlyprint;
notobj_compat = compat;
notobj_notation = df';
@@ -1404,7 +1510,7 @@ let add_notation_interpretation_core local df env ?(impls=empty_internalization_
(* Notations without interpretation (Reserved Notation) *)
let add_syntax_extension local ({CAst.loc;v=df},mods) = let open SynData in
- let psd = compute_pure_syntax_data df mods in
+ let psd = compute_pure_syntax_data local df mods in
let sy_rules = make_syntax_rules {psd with compat = None} in
Flags.if_verbose (List.iter (fun (f,x) -> f x)) psd.msgs;
Lib.add_anonymous_leaf (inSyntaxExtension(local,sy_rules))
@@ -1444,7 +1550,7 @@ let add_notation local env c ({CAst.loc;v=df},modifiers) sc =
let add_notation_extra_printing_rule df k v =
let notk =
let _,_, symbs = analyze_notation_tokens ~onlyprint:true df in
- make_notation_key symbs in
+ make_notation_key InConstrEntrySomeLevel symbs in
add_notation_extra_printing_rule notk k v
(* Infix notations *)
@@ -1528,7 +1634,35 @@ let add_syntactic_definition env ident (vars,c) local onlyparse =
List.map map vars, reversibility, pat
in
let onlyparse = match onlyparse with
- | None when (is_not_printable false reversibility pat) -> Some Flags.Current
+ | None when fst (printability None false reversibility pat) -> Some Flags.Current
| p -> p
in
Syntax_def.declare_syntactic_definition local ident onlyparse (vars,pat)
+
+(**********************************************************************)
+(* Declaration of custom entry *)
+
+let load_custom_entry _ _ = ()
+
+let open_custom_entry _ (_,(local,s)) =
+ Egramcoq.create_custom_entry ~local s
+
+let cache_custom_entry o =
+ load_custom_entry 1 o;
+ open_custom_entry 1 o
+
+let subst_custom_entry (subst,x) = x
+
+let classify_custom_entry (local,s as o) =
+ if local then Dispose else Substitute o
+
+let inCustomEntry : locality_flag * string -> obj =
+ declare_object {(default_object "CUSTOM-ENTRIES") with
+ cache_function = cache_custom_entry;
+ open_function = open_custom_entry;
+ load_function = load_custom_entry;
+ subst_function = subst_custom_entry;
+ classify_function = classify_custom_entry}
+
+let declare_custom_entry local s =
+ Lib.add_anonymous_leaf (inCustomEntry (local,s))
diff --git a/vernac/metasyntax.mli b/vernac/metasyntax.mli
index f6de75b079..73bee7121b 100644
--- a/vernac/metasyntax.mli
+++ b/vernac/metasyntax.mli
@@ -60,3 +60,5 @@ val pr_grammar : string -> Pp.t
val check_infix_modifiers : syntax_modifier list -> unit
val with_syntax_protection : ('a -> 'b) -> 'a -> 'b
+
+val declare_custom_entry : locality_flag -> string -> unit
diff --git a/vernac/misctypes.ml b/vernac/misctypes.ml
index ae725efaaf..ef9cd3c351 100644
--- a/vernac/misctypes.ml
+++ b/vernac/misctypes.ml
@@ -17,10 +17,10 @@ type 'a or_by_notation = 'a Constrexpr.or_by_notation
[@@ocaml.deprecated "use [Constrexpr.or_by_notation]"]
type intro_pattern_naming_expr = Namegen.intro_pattern_naming_expr =
- | IntroIdentifier of Id.t [@ocaml.deprecated "Use version in [Evarutil]"]
- | IntroFresh of Id.t [@ocaml.deprecated "Use version in [Evarutil]"]
- | IntroAnonymous [@ocaml.deprecated "Use version in [Evarutil]"]
-[@@ocaml.deprecated "use [Evarutil.intro_pattern_naming_expr]"]
+ | IntroIdentifier of Id.t [@ocaml.deprecated "Use version in [Namegen]"]
+ | IntroFresh of Id.t [@ocaml.deprecated "Use version in [Namegen]"]
+ | IntroAnonymous [@ocaml.deprecated "Use version in [Namegen]"]
+[@@ocaml.deprecated "use [Namegen.intro_pattern_naming_expr]"]
type 'a or_var = 'a Locus.or_var =
| ArgArg of 'a [@ocaml.deprecated "Use version in [Locus]"]
diff --git a/vernac/obligations.ml b/vernac/obligations.ml
index 1ab24b670b..14d7642328 100644
--- a/vernac/obligations.ml
+++ b/vernac/obligations.ml
@@ -40,7 +40,7 @@ let check_evars env evm =
type oblinfo =
{ ev_name: int * Id.t;
- ev_hyps: Context.Named.t;
+ ev_hyps: Constr.named_context;
ev_status: bool * Evar_kinds.obligation_definition_status;
ev_chop: int option;
ev_src: Evar_kinds.t Loc.located;
@@ -220,7 +220,7 @@ let eterm_obligations env name evm fs ?status t ty =
in
let loc, k = evar_source id evm in
let status = match k with
- | Evar_kinds.QuestionMark (o,_) -> o
+ | Evar_kinds.QuestionMark { Evar_kinds.qm_obligation=o } -> o
| _ -> match status with
| Some o -> o
| None -> Evar_kinds.Define (not (Program.get_proofs_transparency ()))
@@ -480,10 +480,9 @@ let declare_definition prg =
let fix_exn = Hook.get get_fix_exn () in
let typ = nf typ in
let body = nf body in
- let env = Global.env () in
let uvars = Univ.LSet.union
- (Univops.universes_of_constr env typ)
- (Univops.universes_of_constr env body) in
+ (Univops.universes_of_constr typ)
+ (Univops.universes_of_constr body) in
let uctx = UState.restrict prg.prg_ctx uvars in
let univs = UState.check_univ_decl ~poly:(pi2 prg.prg_kind) uctx prg.prg_univdecl in
let ce = definition_entry ~fix_exn ~opaque ~types:typ ~univs body in
@@ -865,7 +864,7 @@ let obligation_terminator name num guard hook auto pf =
else UState.union prg.prg_ctx ctx
in
let uctx = UState.const_univ_entry ~poly:(pi2 prg.prg_kind) ctx in
- let (_, obl) = declare_obligation prg obl body ty uctx in
+ let (defined, obl) = declare_obligation prg obl body ty uctx in
let obls = Array.copy obls in
let _ = obls.(num) <- obl in
let prg_ctx =
@@ -874,10 +873,12 @@ let obligation_terminator name num guard hook auto pf =
polymorphic obligation with the existing ones *)
UState.union prg.prg_ctx ctx
else
- (** The first obligation declares the univs of the constant,
+ (** The first obligation, if defined,
+ declares the univs of the constant,
each subsequent obligation declares its own additional
universes and constraints if any *)
- UState.make (Global.universes ())
+ if defined then UState.make (Global.universes ())
+ else ctx
in
let prg = { prg with prg_ctx } in
try
diff --git a/vernac/ppvernac.ml b/vernac/ppvernac.ml
index 56dfaa54a1..93e4e89a12 100644
--- a/vernac/ppvernac.ml
+++ b/vernac/ppvernac.ml
@@ -97,25 +97,27 @@ open Pputils
let sep = fun _ -> spc()
let sep_v2 = fun _ -> str"," ++ spc()
+ let pr_notation_entry = function
+ | InConstrEntry -> keyword "constr"
+ | InCustomEntry s -> keyword "custom" ++ spc () ++ str s
+
let pr_at_level = function
| NumLevel n -> keyword "at" ++ spc () ++ keyword "level" ++ spc () ++ int n
| NextLevel -> keyword "at" ++ spc () ++ keyword "next" ++ spc () ++ keyword "level"
let pr_constr_as_binder_kind = let open Notation_term in function
- | AsIdent -> keyword "as ident"
- | AsIdentOrPattern -> keyword "as pattern"
- | AsStrictPattern -> keyword "as strict pattern"
+ | AsIdent -> spc () ++ keyword "as ident"
+ | AsIdentOrPattern -> spc () ++ keyword "as pattern"
+ | AsStrictPattern -> spc () ++ keyword "as strict pattern"
let pr_strict b = if b then str "strict " else mt ()
let pr_set_entry_type pr = function
- | ETName -> str"ident"
- | ETReference -> str"global"
+ | ETIdent -> str"ident"
+ | ETGlobal -> str"global"
| ETPattern (b,None) -> pr_strict b ++ str"pattern"
| ETPattern (b,Some n) -> pr_strict b ++ str"pattern" ++ spc () ++ pr_at_level (NumLevel n)
- | ETConstr lev -> str"constr" ++ pr lev
- | ETOther (_,e) -> str e
- | ETConstrAsBinder (bk,lev) -> pr lev ++ spc () ++ pr_constr_as_binder_kind bk
+ | ETConstr (s,bko,lev) -> pr_notation_entry s ++ pr lev ++ pr_opt pr_constr_as_binder_kind bko
| ETBigint -> str "bigint"
| ETBinder true -> str "binder"
| ETBinder false -> str "closed binder"
@@ -153,8 +155,6 @@ open Pputils
| SearchAbout sl ->
keyword "Search" ++ spc() ++ prlist_with_sep spc pr_search_about sl ++ pr_in_out_modules b
- let pr_locality local = if local then keyword "Local" else keyword "Global"
-
let pr_option_ref_value = function
| QualidRefValue id -> pr_qualid id
| StringRefValue s -> qs s
@@ -210,7 +210,10 @@ open Pputils
| HintsTransparency (l, b) ->
keyword (if b then "Transparent" else "Opaque")
++ spc ()
- ++ prlist_with_sep sep pr_qualid l
+ ++ (match l with
+ | HintsVariables -> keyword "Variables"
+ | HintsConstants -> keyword "Constants"
+ | HintsReferences l -> prlist_with_sep sep pr_qualid l)
| HintsMode (m, l) ->
keyword "Mode"
++ spc ()
@@ -377,12 +380,11 @@ open Pputils
let pr_thm_token k = keyword (Kindops.string_of_theorem_kind k)
let pr_syntax_modifier = function
- | SetItemLevel (l,n) ->
- prlist_with_sep sep_v2 str l ++ spc () ++ pr_at_level n
- | SetItemLevelAsBinder (l,bk,n) ->
- prlist_with_sep sep_v2 str l ++
- spc() ++ pr_at_level_opt n ++ spc() ++ pr_constr_as_binder_kind bk
+ | SetItemLevel (l,bko,n) ->
+ prlist_with_sep sep_v2 str l ++ spc () ++ pr_at_level_opt n ++
+ pr_opt pr_constr_as_binder_kind bko
| SetLevel n -> pr_at_level (NumLevel n)
+ | SetCustomEntry (s,n) -> keyword "in" ++ spc() ++ keyword "custom" ++ spc() ++ str s ++ (match n with None -> mt () | Some n -> pr_at_level (NumLevel n))
| SetAssoc LeftA -> keyword "left associativity"
| SetAssoc RightA -> keyword "right associativity"
| SetAssoc NonA -> keyword "no associativity"
@@ -673,6 +675,10 @@ open Pputils
return (
keyword "Format Notation " ++ qs s ++ spc () ++ qs k ++ spc() ++ qs v
)
+ | VernacDeclareCustomEntry s ->
+ return (
+ keyword "Declare Custom Entry " ++ str s
+ )
(* Gallina *)
| VernacDefinition ((discharge,kind),id,b) -> (* A verifier... *)
@@ -1192,21 +1198,24 @@ open Pputils
| VernacEndSubproof ->
return (str "}")
-let pr_vernac_flag =
+let rec pr_vernac_flag (k, v) =
+ let k = keyword k in
+ match v with
+ | VernacFlagEmpty -> k
+ | VernacFlagLeaf v -> k ++ str " = " ++ qs v
+ | VernacFlagList m -> k ++ str "( " ++ pr_vernac_flags m ++ str " )"
+and pr_vernac_flags m =
+ prlist_with_sep (fun () -> str ", ") pr_vernac_flag m
+
+let pr_vernac_attributes =
function
- | VernacPolymorphic true -> keyword "Polymorphic"
- | VernacPolymorphic false -> keyword "Monomorphic"
- | VernacProgram -> keyword "Program"
- | VernacLocal local -> pr_locality local
+ | [] -> mt ()
+ | flags -> str "#[" ++ pr_vernac_flags flags ++ str "]" ++ cut ()
let rec pr_vernac_control v =
let return = tag_vernac v in
match v with
- | VernacExpr (f, v') ->
- List.fold_right
- (fun f a -> pr_vernac_flag f ++ spc() ++ a)
- f
- (pr_vernac_expr v' ++ sep_end v')
+ | VernacExpr (f, v') -> pr_vernac_attributes f ++ pr_vernac_expr v' ++ sep_end v'
| VernacTime (_,{v}) ->
return (keyword "Time" ++ spc() ++ pr_vernac_control v)
| VernacRedirect (s, {v}) ->
diff --git a/vernac/proof_using.ml b/vernac/proof_using.ml
index f8b085f3ef..3e2bd98720 100644
--- a/vernac/proof_using.ml
+++ b/vernac/proof_using.ml
@@ -18,14 +18,6 @@ module NamedDecl = Context.Named.Declaration
let known_names = Summary.ref [] ~name:"proofusing-nameset"
-let in_nameset =
- let open Libobject in
- declare_object { (default_object "proofusing-nameset") with
- cache_function = (fun (_,x) -> known_names := x :: !known_names);
- classify_function = (fun _ -> Dispose);
- discharge_function = (fun _ -> None)
- }
-
let rec close_fwd e s =
let s' =
List.fold_left (fun s decl ->
@@ -73,7 +65,7 @@ let process_expr env e ty =
let s = Id.Set.union v_ty (process_expr env e ty) in
Id.Set.elements s
-let name_set id expr = Lib.add_anonymous_leaf (in_nameset (id,expr))
+let name_set id expr = known_names := (id,expr) :: !known_names
let minimize_hyps env ids =
let rec aux ids =
@@ -178,7 +170,7 @@ let suggest_variable env id =
let value = ref None
let using_to_string us = Pp.string_of_ppcmds (Ppvernac.pr_using us)
-let using_from_string us = Pcoq.Gram.(entry_parse G_vernac.section_subset_expr (parsable (Stream.of_string us)))
+let using_from_string us = Pcoq.Entry.parse G_vernac.section_subset_expr (Pcoq.Parsable.make (Stream.of_string us))
let _ =
Goptions.declare_stringopt_option
diff --git a/vernac/pvernac.ml b/vernac/pvernac.ml
index bac8823811..b2fa8ec99f 100644
--- a/vernac/pvernac.ml
+++ b/vernac/pvernac.ml
@@ -10,13 +10,11 @@
open Pcoq
-let uncurry f (x,y) = f x y
-
let uvernac = create_universe "vernac"
module Vernac_ =
struct
- let gec_vernac s = Gram.entry_create ("vernac:" ^ s)
+ let gec_vernac s = Entry.create ("vernac:" ^ s)
(* The different kinds of vernacular commands *)
let gallina = gec_vernac "gallina"
@@ -28,22 +26,23 @@ module Vernac_ =
let red_expr = new_entry utactic "red_expr"
let hint_info = gec_vernac "hint_info"
(* Main vernac entry *)
- let main_entry = Gram.entry_create "vernac"
+ let main_entry = Entry.create "vernac"
let noedit_mode = gec_vernac "noedit_command"
let () =
- let act_vernac = Gram.action (fun v loc -> Some (to_coqloc loc, v)) in
- let act_eoi = Gram.action (fun _ loc -> None) in
+ let open Extend in
+ let act_vernac v loc = Some (loc, v) in
+ let act_eoi _ loc = None in
let rule = [
- ([ Symbols.stoken Tok.EOI ], act_eoi);
- ([ Symbols.snterm (Gram.Entry.obj vernac_control) ], act_vernac );
+ Rule (Next (Stop, Atoken Tok.EOI), act_eoi);
+ Rule (Next (Stop, Aentry vernac_control), act_vernac);
] in
- uncurry (Gram.extend main_entry) (None, [None, None, rule])
+ Pcoq.grammar_extend main_entry None (None, [None, None, rule])
let command_entry_ref = ref noedit_mode
let command_entry =
Gram.Entry.of_parser "command_entry"
- (fun strm -> Gram.parse_tokens_after_filter !command_entry_ref strm)
+ (fun strm -> Gram.Entry.parse_token !command_entry_ref strm)
end
diff --git a/vernac/pvernac.mli b/vernac/pvernac.mli
index 2993a1661b..b2f8f71462 100644
--- a/vernac/pvernac.mli
+++ b/vernac/pvernac.mli
@@ -16,21 +16,21 @@ val uvernac : gram_universe
module Vernac_ :
sig
- val gallina : vernac_expr Gram.entry
- val gallina_ext : vernac_expr Gram.entry
- val command : vernac_expr Gram.entry
- val syntax : vernac_expr Gram.entry
- val vernac_control : vernac_control Gram.entry
- val rec_definition : (fixpoint_expr * decl_notation list) Gram.entry
- val noedit_mode : vernac_expr Gram.entry
- val command_entry : vernac_expr Gram.entry
- val red_expr : raw_red_expr Gram.entry
- val hint_info : Hints.hint_info_expr Gram.entry
+ val gallina : vernac_expr Entry.t
+ val gallina_ext : vernac_expr Entry.t
+ val command : vernac_expr Entry.t
+ val syntax : vernac_expr Entry.t
+ val vernac_control : vernac_control Entry.t
+ val rec_definition : (fixpoint_expr * decl_notation list) Entry.t
+ val noedit_mode : vernac_expr Entry.t
+ val command_entry : vernac_expr Entry.t
+ val red_expr : raw_red_expr Entry.t
+ val hint_info : Hints.hint_info_expr Entry.t
end
(** The main entry: reads an optional vernac command *)
-val main_entry : (Loc.t * vernac_control) option Gram.entry
+val main_entry : (Loc.t * vernac_control) option Entry.t
(** Handling of the proof mode entry *)
-val get_command_entry : unit -> vernac_expr Gram.entry
-val set_command_entry : vernac_expr Gram.entry -> unit
+val get_command_entry : unit -> vernac_expr Entry.t
+val set_command_entry : vernac_expr Entry.t -> unit
diff --git a/vernac/record.ml b/vernac/record.ml
index a97a1662e5..6b5c538df2 100644
--- a/vernac/record.ml
+++ b/vernac/record.ml
@@ -100,7 +100,7 @@ let binder_of_decl = function
let binders_of_decls = List.map binder_of_decl
-let typecheck_params_and_fields finite def id poly pl t ps nots fs =
+let typecheck_params_and_fields finite def poly pl ps records =
let env0 = Global.env () in
let sigma, decl = Constrexpr_ops.interp_univ_decl_opt env0 pl in
let _ =
@@ -117,7 +117,7 @@ let typecheck_params_and_fields finite def id poly pl t ps nots fs =
Loc.raise ?loc (Stream.Error "pattern with quote not allowed in record parameters")) ps
in
let sigma, (impls_env, ((env1,newps), imps)) = interp_context_evars env0 sigma ps in
- let sigma, typ, sort, template = match t with
+ let fold (sigma, template) (_, t, _, _) = match t with
| Some t ->
let env = EConstr.push_rel_context newps env0 in
let poly =
@@ -132,28 +132,36 @@ let typecheck_params_and_fields finite def id poly pl t ps nots fs =
match Evd.is_sort_variable sigma s' with
| Some l ->
let sigma = Evd.make_flexible_variable sigma ~algebraic:true l in
- sigma, s, s', true
+ (sigma, template), (s, s')
| None ->
- sigma, s, s', false
- else sigma, s, s', false)
+ (sigma, false), (s, s')
+ else (sigma, false), (s, s'))
| _ -> user_err ?loc:(constr_loc t) (str"Sort expected."))
| None ->
let uvarkind = Evd.univ_flexible_alg in
let sigma, s = Evd.new_sort_variable uvarkind sigma in
- sigma, EConstr.mkSort s, s, true
+ (sigma, template), (EConstr.mkSort s, s)
in
- let arity = EConstr.it_mkProd_or_LetIn typ newps in
- let env_ar = EConstr.push_rel_context newps (EConstr.push_rel (LocalAssum (Name id,arity)) env0) in
+ let (sigma, template), typs = List.fold_left_map fold (sigma, true) records in
+ let arities = List.map (fun (typ, _) -> EConstr.it_mkProd_or_LetIn typ newps) typs in
+ let fold accu (id, _, _, _) arity = EConstr.push_rel (LocalAssum (Name id,arity)) accu in
+ let env_ar = EConstr.push_rel_context newps (List.fold_left2 fold env0 records arities) in
let assums = List.filter is_local_assum newps in
- let params = List.map (RelDecl.get_name %> Name.get_id) assums in
- let ty = Inductive (params,(finite != Declarations.BiFinite)) in
- let impls_env = compute_internalization_env env0 sigma ~impls:impls_env ty [id] [arity] [imps] in
- let env2,sigma,impls,newfs,data =
- interp_fields_evars env_ar sigma impls_env nots (binders_of_decls fs)
+ let impls_env =
+ let params = List.map (RelDecl.get_name %> Name.get_id) assums in
+ let ty = Inductive (params, (finite != Declarations.BiFinite)) in
+ let ids = List.map (fun (id, _, _, _) -> id) records in
+ let imps = List.map (fun _ -> imps) arities in
+ compute_internalization_env env0 sigma ~impls:impls_env ty ids arities imps
in
+ let fold sigma (_, _, nots, fs) arity =
+ let _, sigma, impls, newfs, _ = interp_fields_evars env_ar sigma impls_env nots (binders_of_decls fs) in
+ (sigma, (impls, newfs))
+ in
+ let (sigma, data) = List.fold_left2_map fold sigma records arities in
let sigma =
Pretyping.solve_remaining_evars Pretyping.all_and_fail_flags env_ar sigma (Evd.from_env env_ar) in
- let sigma, typ =
+ let fold sigma (typ, sort) (_, newfs) =
let _, univ = compute_constructor_level sigma env_ar newfs in
if not def && (Sorts.is_prop sort ||
(Sorts.is_set sort && is_impredicative_set env0)) then
@@ -164,20 +172,24 @@ let typecheck_params_and_fields finite def id poly pl t ps nots fs =
Option.cata (Evd.is_flexible_level sigma) false (Evd.is_sort_variable sigma sort) then
(* We can assume that the level in aritysort is not constrained
and clear it, if it is flexible *)
- Evd.set_eq_sort env_ar sigma (Prop Pos) sort,
- EConstr.mkSort (Sorts.sort_of_univ univ)
+ Evd.set_eq_sort env_ar sigma Set sort, EConstr.mkSort (Sorts.sort_of_univ univ)
else sigma, typ
in
+ let (sigma, typs) = List.fold_left2_map fold sigma typs data in
let sigma = Evd.minimize_universes sigma in
- let newfs = List.map (EConstr.to_rel_decl sigma) newfs in
let newps = List.map (EConstr.to_rel_decl sigma) newps in
- let typ = EConstr.to_constr sigma typ in
- let ce t = Pretyping.check_evars env0 (Evd.from_env env0) sigma (EConstr.of_constr t) in
let univs = Evd.check_univ_decl ~poly sigma decl in
let ubinders = Evd.universe_binders sigma in
- List.iter (iter_constr ce) (List.rev newps);
+ let ce t = Pretyping.check_evars env0 (Evd.from_env env0) sigma (EConstr.of_constr t) in
+ let () = List.iter (iter_constr ce) (List.rev newps) in
+ let map (impls, newfs) typ =
+ let newfs = List.map (EConstr.to_rel_decl sigma) newfs in
+ let typ = EConstr.to_constr sigma typ in
List.iter (iter_constr ce) (List.rev newfs);
- ubinders, univs, typ, template, imps, newps, impls, newfs
+ (typ, impls, newfs)
+ in
+ let ans = List.map2 map data typs in
+ ubinders, univs, template, newps, imps, ans
let degenerate_decl decl =
let id = match RelDecl.get_name decl with
@@ -261,9 +273,10 @@ let subst_projection fid l c =
raise (NotDefinable (MissingProj (fid,List.rev !bad_projs)));
c''
-let instantiate_possibly_recursive_type indu paramdecls fields =
+let instantiate_possibly_recursive_type ind u ntypes paramdecls fields =
let subst = List.map_i (fun i _ -> mkRel i) 1 paramdecls in
- Termops.substl_rel_context (subst@[mkIndU indu]) fields
+ let subst' = List.init ntypes (fun i -> mkIndU ((ind, ntypes - i - 1), u)) in
+ Termops.substl_rel_context (subst @ subst') fields
let warn_non_primitive_record =
CWarnings.create ~name:"non-primitive-record" ~category:"record"
@@ -281,12 +294,11 @@ let declare_projections indsp ctx ?(kind=StructureComponent) binder_name coers u
| Monomorphic_const_entry ctx -> Univ.Instance.empty
in
let paramdecls = Inductive.inductive_paramdecls (mib, u) in
- let indu = indsp, u in
let r = mkIndU (indsp,u) in
let rp = applist (r, Context.Rel.to_extended_list mkRel 0 paramdecls) in
let paramargs = Context.Rel.to_extended_list mkRel 1 paramdecls in (*def in [[params;x:rp]]*)
let x = Name binder_name in
- let fields = instantiate_possibly_recursive_type indu paramdecls fields in
+ let fields = instantiate_possibly_recursive_type (fst indsp) u mib.mind_ntypes paramdecls fields in
let lifted_fields = Termops.lift_rel_context 1 fields in
let primitive =
if !primitive_flag then
@@ -312,12 +324,16 @@ let declare_projections indsp ctx ?(kind=StructureComponent) binder_name coers u
| Name fid -> try
let kn, term =
if is_local_assum decl && primitive then
- (** Already defined in the kernel silently *)
- let gr = Nametab.locate (Libnames.qualid_of_ident fid) in
- let kn = destConstRef gr in
+ let p = Projection.Repr.make indsp
+ ~proj_npars:mib.mind_nparams
+ ~proj_arg:i
+ (Label.of_id fid)
+ in
+ (** Already defined by declare_mind silently *)
+ let kn = Projection.Repr.constant p in
Declare.definition_message fid;
- UnivNames.register_universe_binders gr ubinders;
- kn, mkProj (Projection.make kn false,mkRel 1)
+ UnivNames.register_universe_binders (ConstRef kn) ubinders;
+ kn, mkProj (Projection.make p false,mkRel 1)
else
let ccl = subst_projection fid subst ti in
let body = match decl with
@@ -374,12 +390,9 @@ let declare_projections indsp ctx ?(kind=StructureComponent) binder_name coers u
open Typeclasses
-let declare_structure finite ubinders univs id idbuild paramimpls params arity template
- fieldimpls fields ?(kind=StructureComponent) ?name is_coe coers =
- let nparams = List.length params and nfields = List.length fields in
- let args = Context.Rel.to_extended_list mkRel nfields params in
- let ind = applist (mkRel (1+nparams+nfields), args) in
- let type_constructor = it_mkProd_or_LetIn ind fields in
+
+let declare_structure finite ubinders univs paramimpls params template ?(kind=StructureComponent) ?name record_data =
+ let nparams = List.length params in
let template, ctx =
match univs with
| Monomorphic_ind_entry ctx ->
@@ -389,37 +402,51 @@ let declare_structure finite ubinders univs id idbuild paramimpls params arity t
| Cumulative_ind_entry cumi ->
false, Polymorphic_const_entry (Univ.CumulativityInfo.univ_context cumi)
in
- let binder_name =
+ let binder_name =
match name with
- | None -> Id.of_string (Unicode.lowercase_first_char (Id.to_string id))
+ | None ->
+ let map (id, _, _, _, _, _, _) =
+ Id.of_string (Unicode.lowercase_first_char (Id.to_string id))
+ in
+ Array.map_of_list map record_data
| Some n -> n
in
- let mie_ind =
+ let ntypes = List.length record_data in
+ let mk_block i (id, idbuild, arity, _, fields, _, _) =
+ let nfields = List.length fields in
+ let args = Context.Rel.to_extended_list mkRel nfields params in
+ let ind = applist (mkRel (ntypes - i + nparams + nfields), args) in
+ let type_constructor = it_mkProd_or_LetIn ind fields in
{ mind_entry_typename = id;
mind_entry_arity = arity;
mind_entry_template = template;
mind_entry_consnames = [idbuild];
mind_entry_lc = [type_constructor] }
in
+ let blocks = List.mapi mk_block record_data in
let mie =
{ mind_entry_params = List.map degenerate_decl params;
- mind_entry_record = Some (if !primitive_flag then Some [|binder_name|] else None);
+ mind_entry_record = Some (if !primitive_flag then Some binder_name else None);
mind_entry_finite = finite;
- mind_entry_inds = [mie_ind];
+ mind_entry_inds = blocks;
mind_entry_private = None;
mind_entry_universes = univs;
}
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
- let kinds,sp_projs = declare_projections rsp ctx ~kind binder_name coers ubinders fieldimpls fields in
- let build = ConstructRef cstr in
- let poly = match ctx with | Polymorphic_const_entry _ -> true | Monomorphic_const_entry _ -> false in
- let () = if is_coe then Class.try_add_new_coercion build ~local:false poly in
- Recordops.declare_structure(rsp,cstr,List.rev kinds,List.rev sp_projs);
- rsp
+ let impls = List.map (fun _ -> paramimpls, []) record_data in
+ let kn = ComInductive.declare_mutual_inductive_with_eliminations mie ubinders impls in
+ let map i (_, _, _, fieldimpls, fields, is_coe, coers) =
+ let rsp = (kn, i) in (* This is ind path of idstruc *)
+ let cstr = (rsp, 1) in
+ let kinds,sp_projs = declare_projections rsp ctx ~kind binder_name.(i) coers ubinders fieldimpls fields in
+ let build = ConstructRef cstr in
+ let poly = match ctx with | Polymorphic_const_entry _ -> true | Monomorphic_const_entry _ -> false in
+ let () = if is_coe then Class.try_add_new_coercion build ~local:false poly in
+ let () = Recordops.declare_structure(rsp,cstr,List.rev kinds,List.rev sp_projs) in
+ rsp
+ in
+ List.mapi map record_data
let implicits_of_context ctx =
List.map_i (fun i name ->
@@ -431,22 +458,22 @@ let implicits_of_context ctx =
1 (List.rev (Anonymous :: (List.map RelDecl.get_name ctx)))
let declare_class finite def cum ubinders univs id idbuild paramimpls params arity
- template fieldimpls fields ?(kind=StructureComponent) is_coe coers priorities =
+ template fieldimpls fields ?(kind=StructureComponent) coers priorities =
let fieldimpls =
(* Make the class implicit in the projections, and the params if applicable. *)
let len = List.length params in
let impls = implicits_of_context params in
List.map (fun x -> impls @ Impargs.lift_implicits (succ len) x) fieldimpls
in
- let binder_name = Namegen.next_ident_away (snd id) (Termops.vars_of_env (Global.env())) in
- let impl, projs =
+ let binder_name = Namegen.next_ident_away id (Termops.vars_of_env (Global.env())) in
+ let data =
match fields with
| [LocalAssum (Name proj_name, field) | LocalDef (Name proj_name, _, field)] when def ->
let class_body = it_mkLambda_or_LetIn field params in
let class_type = it_mkProd_or_LetIn arity params in
let class_entry =
Declare.definition_entry ~types:class_type ~univs class_body in
- let cst = Declare.declare_constant (snd id)
+ let cst = Declare.declare_constant id
(DefinitionEntry class_entry, IsDefinition Definition)
in
let cstu = (cst, match univs with
@@ -473,7 +500,7 @@ let declare_class finite def cum ubinders univs id idbuild paramimpls params ari
| Some b -> Some ((if b then Backward else Forward), List.hd priorities)
| None -> None
in
- cref, [Name proj_name, sub, Some proj_cst]
+ [cref, [Name proj_name, sub, Some proj_cst]]
| _ ->
let univs =
match univs with
@@ -485,18 +512,21 @@ let declare_class finite def cum ubinders univs id idbuild paramimpls params ari
| Monomorphic_const_entry univs ->
Monomorphic_ind_entry univs
in
- let ind = declare_structure Declarations.BiFinite ubinders univs (snd id) idbuild paramimpls
- params arity template fieldimpls fields
- ~kind:Method ~name:binder_name false (List.map (fun _ -> false) fields)
- in
+ let record_data = [id, idbuild, arity, fieldimpls, fields, false, List.map (fun _ -> false) fields] in
+ let inds = declare_structure Declarations.BiFinite ubinders univs paramimpls
+ params template ~kind:Method ~name:[|binder_name|] record_data
+ in
let coers = List.map2 (fun coe pri ->
Option.map (fun b ->
if b then Backward, pri else Forward, pri) coe)
coers priorities
in
- let l = List.map3 (fun decl b y -> RelDecl.get_name decl, b, y)
- (List.rev fields) coers (Recordops.lookup_projections ind)
- in IndRef ind, l
+ let map ind =
+ let l = List.map3 (fun decl b y -> RelDecl.get_name decl, b, y)
+ (List.rev fields) coers (Recordops.lookup_projections ind)
+ in IndRef ind, l
+ in
+ List.map map inds
in
let ctx_context =
List.map (fun decl ->
@@ -517,16 +547,19 @@ let declare_class finite def cum ubinders univs id idbuild paramimpls params ari
| Monomorphic_const_entry _ ->
Univ.AUContext.empty, ctx_context, fields
in
- let k =
- { cl_univs = univs;
- cl_impl = impl;
- cl_strict = !typeclasses_strict;
- cl_unique = !typeclasses_unique;
- cl_context = ctx_context;
- cl_props = fields;
- cl_projs = projs }
- in
+ let map (impl, projs) =
+ let k =
+ { cl_univs = univs;
+ cl_impl = impl;
+ cl_strict = !typeclasses_strict;
+ cl_unique = !typeclasses_unique;
+ cl_context = ctx_context;
+ cl_props = fields;
+ cl_projs = projs }
+ in
add_class k; impl
+ in
+ List.map map data
let add_constant_class cst =
@@ -562,48 +595,87 @@ let add_inductive_class ind =
cl_unique = !typeclasses_unique }
in add_class k
+let warn_already_existing_class =
+ CWarnings.create ~name:"already-existing-class" ~category:"automation" Pp.(fun g ->
+ Printer.pr_global g ++ str " is already declared as a typeclass.")
+
let declare_existing_class g =
- match g with
- | ConstRef x -> add_constant_class x
- | IndRef x -> add_inductive_class x
- | _ -> user_err ~hdr:"declare_existing_class"
- (Pp.str"Unsupported class type, only constants and inductives are allowed")
+ if Typeclasses.is_class g then warn_already_existing_class g
+ else
+ match g with
+ | ConstRef x -> add_constant_class x
+ | IndRef x -> add_inductive_class x
+ | _ -> user_err ~hdr:"declare_existing_class"
+ (Pp.str"Unsupported class type, only constants and inductives are allowed")
open Vernacexpr
-(* [fs] corresponds to fields and [ps] to parameters; [coers] is a
- list telling if the corresponding fields must me declared as coercions
- or subinstances. *)
-let definition_structure (kind,cum,poly,finite,(is_coe,({CAst.loc;v=idstruc},pl)),ps,cfs,idbuild,s) =
- let cfs,notations = List.split cfs in
- let cfs,priorities = List.split cfs in
- let coers,fs = List.split cfs in
- let extract_name acc = function
+let check_unique_names records =
+ let extract_name acc (((_, bnd), _), _) = match bnd with
Vernacexpr.AssumExpr({CAst.v=Name id},_) -> id::acc
| Vernacexpr.DefExpr ({CAst.v=Name id},_,_) -> id::acc
| _ -> acc in
- let allnames = idstruc::(List.fold_left extract_name [] fs) in
- let () = match List.duplicates Id.equal allnames with
+ let allnames =
+ List.fold_left (fun acc (_, id, _, _, cfs, _, _) ->
+ id.CAst.v :: (List.fold_left extract_name acc cfs)) [] records
+ in
+ match List.duplicates Id.equal allnames with
| [] -> ()
| id :: _ -> user_err (str "Two objects have the same name" ++ spc () ++ quote (Id.print id))
- in
+
+let check_priorities kind records =
let isnot_class = match kind with Class false -> false | _ -> true in
- if isnot_class && List.exists (fun opt -> not (Option.is_empty opt)) priorities then
- user_err Pp.(str "Priorities only allowed for type class substructures");
- (* Now, younger decl in params and fields is on top *)
- let pl, univs, arity, template, implpars, params, implfs, fields =
+ let has_priority (_, _, _, _, cfs, _, _) =
+ List.exists (fun ((_, pri), _) -> not (Option.is_empty pri)) cfs
+ in
+ if isnot_class && List.exists has_priority records then
+ user_err Pp.(str "Priorities only allowed for type class substructures")
+
+let extract_record_data records =
+ let map (is_coe, id, _, _, cfs, idbuild, s) =
+ let fs = List.map (fun (((_, f), _), _) -> f) cfs in
+ id.CAst.v, s, List.map snd cfs, fs
+ in
+ let data = List.map map records in
+ let pss = List.map (fun (_, _, _, ps, _, _, _) -> ps) records in
+ let ps = match pss with
+ | [] -> CErrors.anomaly (str "Empty record block")
+ | ps :: rem ->
+ let eq_local_binders bl1 bl2 = List.equal local_binder_eq bl1 bl2 in
+ let () =
+ if not (List.for_all (eq_local_binders ps) rem) then
+ user_err (str "Parameters should be syntactically the \
+ same for each inductive type.")
+ in
+ ps
+ in
+ (** FIXME: Same issue as #7754 *)
+ let _, _, pl, _, _, _, _ = List.hd records in
+ pl, ps, data
+
+(* [fs] corresponds to fields and [ps] to parameters; [coers] is a
+ list telling if the corresponding fields must me declared as coercions
+ or subinstances. *)
+let definition_structure kind cum poly finite records =
+ let () = check_unique_names records in
+ let () = check_priorities kind records in
+ let pl, ps, data = extract_record_data records in
+ let pl, univs, template, params, implpars, data =
States.with_state_protection (fun () ->
- typecheck_params_and_fields finite (kind = Class true) idstruc poly pl s ps notations fs) () in
+ typecheck_params_and_fields finite (kind = Class true) poly pl ps data) () in
match kind with
| Class def ->
- let priorities = List.map (fun id -> {hint_priority = id; hint_pattern = None}) priorities in
- declare_class finite def cum pl univs (loc,idstruc) idbuild
- implpars params arity template implfs fields is_coe coers priorities
+ let (_, id, _, _, cfs, idbuild, _), (arity, implfs, fields) = match records, data with
+ | [r], [d] -> r, d
+ | _, _ -> CErrors.user_err (str "Mutual definitional classes are not handled")
+ in
+ let priorities = List.map (fun ((_, id), _) -> {hint_priority = id; hint_pattern = None}) cfs in
+ let coers = List.map (fun (((coe, _), _), _) -> coe) cfs in
+ declare_class finite def cum pl univs id.CAst.v idbuild
+ implpars params arity template implfs fields coers priorities
| _ ->
- let implfs = List.map
- (fun impls -> implpars @ Impargs.lift_implicits
- (succ (List.length params)) impls) implfs
- in
+ let map impls = implpars @ Impargs.lift_implicits (succ (List.length params)) impls in
+ let data = List.map (fun (arity, implfs, fields) -> (arity, List.map map implfs, fields)) data in
let univs =
match univs with
| Polymorphic_const_entry univs ->
@@ -614,7 +686,11 @@ let definition_structure (kind,cum,poly,finite,(is_coe,({CAst.loc;v=idstruc},pl)
| Monomorphic_const_entry univs ->
Monomorphic_ind_entry univs
in
- let ind = declare_structure finite pl univs idstruc
- idbuild implpars params arity template implfs
- fields is_coe (List.map (fun coe -> not (Option.is_empty coe)) coers) in
- IndRef ind
+ let map (arity, implfs, fields) (is_coe, id, _, _, cfs, idbuild, _) =
+ let coers = List.map (fun (((coe, _), _), _) -> coe) cfs in
+ let coe = List.map (fun coe -> not (Option.is_empty coe)) coers in
+ id.CAst.v, idbuild, arity, implfs, fields, is_coe, coe
+ in
+ let data = List.map2 map data records in
+ let inds = declare_structure finite pl univs implpars params template data in
+ List.map (fun ind -> IndRef ind) inds
diff --git a/vernac/record.mli b/vernac/record.mli
index b2c039f0b5..567f2b3138 100644
--- a/vernac/record.mli
+++ b/vernac/record.mli
@@ -22,13 +22,18 @@ val declare_projections :
bool list ->
UnivNames.universe_binders ->
Impargs.manual_implicits list ->
- Context.Rel.t ->
+ Constr.rel_context ->
(Name.t * bool) list * Constant.t option list
val definition_structure :
- inductive_kind * Decl_kinds.cumulative_inductive_flag * Decl_kinds.polymorphic *
- Declarations.recursivity_kind * ident_decl with_coercion * local_binder_expr list *
+ inductive_kind -> Decl_kinds.cumulative_inductive_flag -> Decl_kinds.polymorphic ->
+ Declarations.recursivity_kind ->
+ (coercion_flag *
+ Names.lident *
+ universe_decl_expr option *
+ local_binder_expr list *
(local_decl_expr with_instance with_priority with_notation) list *
- Id.t * constr_expr option -> GlobRef.t
+ Id.t * constr_expr option) list ->
+ GlobRef.t list
val declare_existing_class : GlobRef.t -> unit
diff --git a/vernac/topfmt.ml b/vernac/topfmt.ml
index 609dac69aa..f842ca5ead 100644
--- a/vernac/topfmt.ml
+++ b/vernac/topfmt.ml
@@ -181,6 +181,10 @@ let default_tag_map () = let open Terminal in [
; "tactic.keyword" , make ~bold:true ()
; "tactic.primitive" , make ~fg_color:`LIGHT_GREEN ()
; "tactic.string" , make ~fg_color:`LIGHT_RED ()
+ ; "diff.added" , make ~bg_color:(`RGB(0,141,0)) ~underline:true ()
+ ; "diff.removed" , make ~bg_color:(`RGB(170,0,0)) ~underline:true ()
+ ; "diff.added.bg" , make ~bg_color:(`RGB(0,91,0)) ()
+ ; "diff.removed.bg" , make ~bg_color:(`RGB(91,0,0)) ()
]
let tag_map = ref CString.Map.empty
@@ -198,72 +202,103 @@ let parse_color_config file =
let dump_tags () = CString.Map.bindings !tag_map
+let empty = Terminal.make ()
+let default_style = Terminal.reset_style
+
+let get_style tag =
+ try CString.Map.find tag !tag_map
+ with Not_found -> empty;;
+
+let get_open_seq tags =
+ let style = List.fold_left (fun a b -> Terminal.merge a (get_style b)) default_style tags in
+ Terminal.eval (Terminal.diff default_style style);;
+
+let get_close_seq tags =
+ let style = List.fold_left (fun a b -> Terminal.merge a (get_style b)) default_style tags in
+ Terminal.eval (Terminal.diff style default_style);;
+
+let diff_tag_stack = ref [] (* global, just like std_ft *)
+
(** Not thread-safe. We should put a lock somewhere if we print from
different threads. Do we? *)
let make_style_stack () =
(** Default tag is to reset everything *)
- let empty = Terminal.make () in
- let default_tag = Terminal.({
- fg_color = Some `DEFAULT;
- bg_color = Some `DEFAULT;
- bold = Some false;
- italic = Some false;
- underline = Some false;
- negative = Some false;
- prefix = None;
- suffix = None;
- })
- in
let style_stack = ref [] in
let peek () = match !style_stack with
- | [] -> default_tag (** Anomalous case, but for robustness *)
+ | [] -> default_style (** Anomalous case, but for robustness *)
| st :: _ -> st
in
- let push tag =
- let style =
- try CString.Map.find tag !tag_map
- with | Not_found -> empty
- in
- (** Use the merging of the latest tag and the one being currently pushed.
- This may be useful if for instance the latest tag changes the background and
- the current one the foreground, so that the two effects are additioned. *)
+ let open_tag tag =
+ let (tpfx, ttag) = split_tag tag in
+ if tpfx = end_pfx then "" else
+ let style = get_style ttag in
+ (** Merge the current settings and the style being pushed. This allows
+ restoring the previous settings correctly in a pop when both set the same
+ attribute. Example: current settings have red FG, the pushed style has
+ green FG. When popping the style, we should set red FG, not default FG. *)
let style = Terminal.merge (peek ()) style in
+ let diff = Terminal.diff (peek ()) style in
style_stack := style :: !style_stack;
- Terminal.eval style
+ if tpfx = start_pfx then diff_tag_stack := ttag :: !diff_tag_stack;
+ Terminal.eval diff
in
- let pop _ = match !style_stack with
- | [] -> (** Something went wrong, we fallback *)
- Terminal.eval default_tag
- | _ :: rem -> style_stack := rem;
- Terminal.eval (peek ())
+ let close_tag tag =
+ let (tpfx, _) = split_tag tag in
+ if tpfx = start_pfx then "" else begin
+ if tpfx = end_pfx then diff_tag_stack := (try List.tl !diff_tag_stack with tl -> []);
+ match !style_stack with
+ | [] -> (** Something went wrong, we fallback *)
+ Terminal.eval default_style
+ | cur :: rem -> style_stack := rem;
+ if cur = (peek ()) then "" else
+ if rem = [] then Terminal.reset else
+ Terminal.eval (Terminal.diff cur (peek ()))
+ end
in
let clear () = style_stack := [] in
- push, pop, clear
+ open_tag, close_tag, clear
let make_printing_functions () =
- let empty = Terminal.make () in
let print_prefix ft tag =
- let style =
- try CString.Map.find tag !tag_map
- with | Not_found -> empty
- in
- match style.Terminal.prefix with Some s -> Format.pp_print_string ft s | None -> ()
- in
+ let (tpfx, ttag) = split_tag tag in
+ if tpfx <> end_pfx then
+ let style = get_style ttag in
+ match style.Terminal.prefix with Some s -> Format.pp_print_string ft s | None -> () in
+
let print_suffix ft tag =
- let style =
- try CString.Map.find tag !tag_map
- with | Not_found -> empty
- in
- match style.Terminal.suffix with Some s -> Format.pp_print_string ft s | None -> ()
- in
+ let (tpfx, ttag) = split_tag tag in
+ if tpfx <> start_pfx then
+ let style = get_style ttag in
+ match style.Terminal.suffix with Some s -> Format.pp_print_string ft s | None -> () in
+
print_prefix, print_suffix
+let init_output_fns () =
+ let reopen_highlight = ref "" in
+ let open Format in
+ let fns = Format.pp_get_formatter_out_functions !std_ft () in
+ let newline () =
+ if !diff_tag_stack <> [] then begin
+ let close = get_close_seq !diff_tag_stack in
+ fns.out_string close 0 (String.length close);
+ reopen_highlight := get_open_seq (List.rev !diff_tag_stack);
+ end;
+ fns.out_string "\n" 0 1 in
+ let string s off n =
+ if !reopen_highlight <> "" && String.trim (String.sub s off n) <> "" then begin
+ fns.out_string !reopen_highlight 0 (String.length !reopen_highlight);
+ reopen_highlight := ""
+ end;
+ fns.out_string s off n in
+ let new_fns = { fns with out_string = string; out_newline = newline } in
+ Format.pp_set_formatter_out_functions !std_ft new_fns;;
+
let init_terminal_output ~color =
- let push_tag, pop_tag, clear_tag = make_style_stack () in
+ let open_tag, close_tag, clear_tag = make_style_stack () in
let print_prefix, print_suffix = make_printing_functions () in
let tag_handler ft = {
- Format.mark_open_tag = push_tag;
- Format.mark_close_tag = pop_tag;
+ Format.mark_open_tag = open_tag;
+ Format.mark_close_tag = close_tag;
Format.print_open_tag = print_prefix ft;
Format.print_close_tag = print_suffix ft;
} in
@@ -271,6 +306,7 @@ let init_terminal_output ~color =
(* Use 0-length markers *)
begin
std_logger_cleanup := clear_tag;
+ init_output_fns ();
Format.pp_set_mark_tags !std_ft true;
Format.pp_set_mark_tags !err_ft true
end
diff --git a/vernac/vernacentries.ml b/vernac/vernacentries.ml
index 479482095c..e1c9712135 100644
--- a/vernac/vernacentries.ml
+++ b/vernac/vernacentries.ml
@@ -263,15 +263,13 @@ let print_namespace ns =
let matches mp = match match_modulepath ns mp with
| Some [] -> true
| _ -> false in
- let constants = (Global.env ()).Environ.env_globals.Environ.env_constants in
let constants_in_namespace =
- Cmap_env.fold (fun c (body,_) acc ->
- let kn = Constant.user c in
- if matches (KerName.modpath kn) then
- acc++fnl()++hov 2 (print_constant kn body)
- else
- acc
- ) constants (str"")
+ Environ.fold_constants (fun c body acc ->
+ let kn = Constant.user c in
+ if matches (KerName.modpath kn)
+ then acc++fnl()++hov 2 (print_constant kn body)
+ else acc)
+ (Global.env ()) (str"")
in
(print_list Id.print ns)++str":"++fnl()++constants_in_namespace
@@ -433,6 +431,10 @@ let vernac_notation ~atts =
let local = enforce_module_locality atts.locality in
Metasyntax.add_notation local (Global.env())
+let vernac_custom_entry ~atts s =
+ let local = enforce_module_locality atts.locality in
+ Metasyntax.declare_custom_entry local s
+
(***********)
(* Gallina *)
@@ -539,25 +541,43 @@ let should_treat_as_cumulative cum poly =
else user_err Pp.(str "The NonCumulative prefix can only be used in a polymorphic context.")
| None -> poly && Flags.is_polymorphic_inductive_cumulativity ()
-let vernac_record cum k poly finite struc binders sort nameopt cfs =
+let uniform_inductive_parameters = ref false
+
+let should_treat_as_uniform () =
+ if !uniform_inductive_parameters
+ then ComInductive.UniformParameters
+ else ComInductive.NonUniformParameters
+
+let vernac_record cum k poly finite records =
let is_cumulative = should_treat_as_cumulative cum poly in
- let const = match nameopt with
- | None -> add_prefix "Build_" (fst (snd struc)).v
- | Some ({v=id} as lid) ->
- Dumpglob.dump_definition lid false "constr"; id in
- if Dumpglob.dump () then (
- Dumpglob.dump_definition (fst (snd struc)) false "rec";
- List.iter (fun (((_, x), _), _) ->
- match x with
- | Vernacexpr.AssumExpr ({loc;v=Name id}, _) -> Dumpglob.dump_definition (make ?loc id) false "proj"
- | _ -> ()) cfs);
- ignore(Record.definition_structure (k,is_cumulative,poly,finite,struc,binders,cfs,const,sort))
+ let map ((coe, (id, pl)), binders, sort, nameopt, cfs) =
+ let const = match nameopt with
+ | None -> add_prefix "Build_" id.v
+ | Some lid ->
+ let () = Dumpglob.dump_definition lid false "constr" in
+ lid.v
+ in
+ let () =
+ if Dumpglob.dump () then
+ let () = Dumpglob.dump_definition id false "rec" in
+ let iter (((_, x), _), _) = match x with
+ | Vernacexpr.AssumExpr ({loc;v=Name id}, _) ->
+ Dumpglob.dump_definition (make ?loc id) false "proj"
+ | _ -> ()
+ in
+ List.iter iter cfs
+ in
+ coe, id, pl, binders, cfs, const, sort
+ in
+ let records = List.map map records in
+ ignore(Record.definition_structure k is_cumulative poly finite records)
(** When [poly] is true the type is declared polymorphic. When [lo] is true,
then the type is declared private (as per the [Private] keyword). [finite]
indicates whether the type is inductive, co-inductive or
neither. *)
let vernac_inductive ~atts cum lo finite indl =
+ let open Pp in
if Dumpglob.dump () then
List.iter (fun (((coe,(lid,_)), _, _, _, cstrs), _) ->
match cstrs with
@@ -567,35 +587,86 @@ let vernac_inductive ~atts cum lo finite indl =
Dumpglob.dump_definition lid false "constr") cstrs
| _ -> () (* dumping is done by vernac_record (called below) *) )
indl;
+ let is_record = function
+ | ((_ , _ , _ , _, RecordDecl _), _) -> true
+ | _ -> false
+ in
+ let is_constructor = function
+ | ((_ , _ , _ , _, Constructors _), _) -> true
+ | _ -> false
+ in
+ let is_defclass = match indl with
+ | [ ( id , bl , c , Class _, Constructors [l]), [] ] -> Some (id, bl, c, l)
+ | _ -> None
+ in
+ if Option.has_some is_defclass then
+ (** Definitional class case *)
+ let (id, bl, c, l) = Option.get is_defclass in
+ let (coe, (lid, ce)) = l in
+ let coe' = if coe then Some true else None in
+ let f = (((coe', AssumExpr ((make ?loc:lid.loc @@ Name lid.v), ce)), None), []) in
+ vernac_record cum (Class true) atts.polymorphic finite [id, bl, c, None, [f]]
+ else if List.for_all is_record indl then
+ (** Mutual record case *)
+ let check_kind ((_, _, _, kind, _), _) = match kind with
+ | Variant ->
+ user_err (str "The Variant keyword does not support syntax { ... }.")
+ | Record | Structure | Class _ | Inductive_kw | CoInductive -> ()
+ in
+ let () = List.iter check_kind indl in
+ let check_where ((_, _, _, _, _), wh) = match wh with
+ | [] -> ()
+ | _ :: _ ->
+ user_err (str "where clause not supported for records")
+ in
+ let () = List.iter check_where indl in
+ let unpack ((id, bl, c, _, decl), _) = match decl with
+ | RecordDecl (oc, fs) ->
+ (id, bl, c, oc, fs)
+ | Constructors _ -> assert false (** ruled out above *)
+ in
+ let ((_, _, _, kind, _), _) = List.hd indl in
+ let kind = match kind with Class _ -> Class false | _ -> kind in
+ let recordl = List.map unpack indl in
+ vernac_record cum kind atts.polymorphic finite recordl
+ else if List.for_all is_constructor indl then
+ (** Mutual inductive case *)
+ let check_kind ((_, _, _, kind, _), _) = match kind with
+ | (Record | Structure) ->
+ user_err (str "The Record keyword is for types defined using the syntax { ... }.")
+ | Class _ ->
+ user_err (str "Inductive classes not supported")
+ | Variant | Inductive_kw | CoInductive -> ()
+ in
+ let () = List.iter check_kind indl in
+ let check_name ((na, _, _, _, _), _) = match na with
+ | (true, _) ->
+ user_err (str "Variant types do not handle the \"> Name\" \
+ syntax, which is reserved for records. Use the \":>\" \
+ syntax on constructors instead.")
+ | _ -> ()
+ in
+ let () = List.iter check_name indl in
+ let unpack (((_, id) , bl, c, _, decl), ntn) = match decl with
+ | Constructors l -> (id, bl, c, l), ntn
+ | RecordDecl _ -> assert false (* ruled out above *)
+ in
+ let indl = List.map unpack indl in
+ let is_cumulative = should_treat_as_cumulative cum atts.polymorphic in
+ let uniform = should_treat_as_uniform () in
+ ComInductive.do_mutual_inductive indl is_cumulative atts.polymorphic lo ~uniform finite
+ else
+ user_err (str "Mixed record-inductive definitions are not allowed")
+(*
+
match indl with
- | [ ( _ , _ , _ ,(Record|Structure), Constructors _ ),_ ] ->
- user_err Pp.(str "The Record keyword is for types defined using the syntax { ... }.")
- | [ (_ , _ , _ ,Variant, RecordDecl _),_ ] ->
- user_err Pp.(str "The Variant keyword does not support syntax { ... }.")
- | [ ( id , bl , c , b, RecordDecl (oc,fs) ), [] ] ->
- vernac_record cum (match b with Class _ -> Class false | _ -> b)
- atts.polymorphic finite id bl c oc fs
| [ ( id , bl , c , Class _, Constructors [l]), [] ] ->
let f =
let (coe, ({loc;v=id}, ce)) = l in
let coe' = if coe then Some true else None in
(((coe', AssumExpr ((make ?loc @@ Name id), ce)), None), [])
- in vernac_record cum (Class true) atts.polymorphic finite id bl c None [f]
- | [ ( _ , _, _, Class _, Constructors _), [] ] ->
- user_err Pp.(str "Inductive classes not supported")
- | [ ( id , bl , c , Class _, _), _ :: _ ] ->
- user_err Pp.(str "where clause not supported for classes")
- | [ ( _ , _ , _ , _, RecordDecl _ ) , _ ] ->
- user_err Pp.(str "where clause not supported for (co)inductive records")
- | _ -> let unpack = function
- | ( (false, id) , bl , c , _ , Constructors l ) , ntn -> ( id , bl , c , l ) , ntn
- | ( (true,_),_,_,_,Constructors _),_ ->
- user_err Pp.(str "Variant types do not handle the \"> Name\" syntax, which is reserved for records. Use the \":>\" syntax on constructors instead.")
- | _ -> user_err Pp.(str "Cannot handle mutually (co)inductive records.")
- in
- let indl = List.map unpack indl in
- let is_cumulative = should_treat_as_cumulative cum atts.polymorphic in
- ComInductive.do_mutual_inductive indl is_cumulative atts.polymorphic lo finite
+ in vernac_record cum (Class true) atts.polymorphic finite [id, bl, c, None, [f]]
+ *)
let vernac_fixpoint ~atts discharge l =
let local = enforce_locality_exp atts.locality discharge in
@@ -1412,6 +1483,14 @@ let _ =
optwrite = Flags.make_polymorphic_inductive_cumulativity }
let _ =
+ declare_bool_option
+ { optdepr = false;
+ optname = "Uniform inductive parameters";
+ optkey = ["Uniform"; "Inductive"; "Parameters"];
+ optread = (fun () -> !uniform_inductive_parameters);
+ optwrite = (fun b -> uniform_inductive_parameters := b) }
+
+let _ =
declare_int_option
{ optdepr = false;
optname = "the level of inlining during functor application";
@@ -1426,8 +1505,8 @@ let _ =
{ optdepr = false;
optname = "kernel term sharing";
optkey = ["Kernel"; "Term"; "Sharing"];
- optread = (fun () -> !CClosure.share);
- optwrite = (fun b -> CClosure.share := b) }
+ optread = (fun () -> (Global.typing_flags ()).Declarations.share_reduction);
+ optwrite = (fun b -> Global.set_reduction_sharing b) }
let _ =
declare_bool_option
@@ -1908,8 +1987,9 @@ let vernac_subproof gln =
match gln with
| None -> Proof.focus subproof_cond () 1 p
| Some (Goal_select.SelectNth n) -> Proof.focus subproof_cond () n p
+ | Some (Goal_select.SelectId id) -> Proof.focus_id subproof_cond () id p
| _ -> user_err ~hdr:"bracket_selector"
- (str "Brackets only support the single numbered goal selector."))
+ (str "Brackets do not support multi-goal selectors."))
let vernac_end_subproof () =
Proof_global.simple_with_current_proof (fun _ p ->
@@ -1965,7 +2045,7 @@ let vernac_load interp fname =
interp x in
let parse_sentence = Flags.with_option Flags.we_are_parsing
(fun po ->
- match Pcoq.Gram.entry_parse Pvernac.main_entry po with
+ match Pcoq.Entry.parse Pvernac.main_entry po with
| Some x -> x
| None -> raise End_of_input) in
let fname =
@@ -1974,7 +2054,7 @@ let vernac_load interp fname =
let input =
let longfname = Loadpath.locate_file fname in
let in_chan = open_utf8_file_in longfname in
- Pcoq.Gram.parsable ~file:(Loc.InFile longfname) (Stream.of_channel in_chan) in
+ Pcoq.Parsable.make ~file:(Loc.InFile longfname) (Stream.of_channel in_chan) in
begin
try while true do interp (snd (parse_sentence input)) done
with End_of_input -> ()
@@ -2021,6 +2101,8 @@ let interp ?proof ~atts ~st c =
vernac_notation ~atts c infpl sc
| VernacNotationAddFormat(n,k,v) ->
Metasyntax.add_notation_extra_printing_rule n k v
+ | VernacDeclareCustomEntry s ->
+ vernac_custom_entry ~atts s
(* Gallina *)
| VernacDefinition ((discharge,kind),lid,d) ->
@@ -2030,7 +2112,7 @@ let interp ?proof ~atts ~st c =
| VernacExactProof c -> vernac_exact_proof c
| VernacAssumption ((discharge,kind),nl,l) ->
vernac_assumption ~atts discharge kind l nl
- | VernacInductive (cum, priv,finite,l) -> vernac_inductive ~atts cum priv finite l
+ | VernacInductive (cum, priv, finite, l) -> vernac_inductive ~atts cum priv finite l
| VernacFixpoint (discharge, l) -> vernac_fixpoint ~atts discharge l
| VernacCoFixpoint (discharge, l) -> vernac_cofixpoint ~atts discharge l
| VernacScheme l -> vernac_scheme l
@@ -2149,6 +2231,7 @@ let check_vernac_supports_locality c l =
| Some _, (
VernacOpenCloseScope _
| VernacSyntaxExtension _ | VernacInfix _ | VernacNotation _
+ | VernacDeclareCustomEntry _
| VernacDefinition _ | VernacFixpoint _ | VernacCoFixpoint _
| VernacAssumption _ | VernacStartTheoremProof _
| VernacCoercion _ | VernacIdentityCoercion _
@@ -2244,32 +2327,62 @@ let with_fail st b f =
| _ -> assert false
end
+let attributes_of_flags f atts =
+ let assert_empty k v =
+ if v <> VernacFlagEmpty
+ then user_err Pp.(str "Attribute " ++ str k ++ str " does not accept arguments")
+ in
+ List.fold_left
+ (fun (polymorphism, atts) (k, v) ->
+ match k with
+ | "program" when not atts.program ->
+ assert_empty k v;
+ (polymorphism, { atts with program = true })
+ | "program" ->
+ user_err Pp.(str "Program mode specified twice")
+ | "polymorphic" when polymorphism = None ->
+ assert_empty k v;
+ (Some true, atts)
+ | "monomorphic" when polymorphism = None ->
+ assert_empty k v;
+ (Some false, atts)
+ | ("polymorphic" | "monomorphic") ->
+ user_err Pp.(str "Polymorphism specified twice")
+ | "local" when Option.is_empty atts.locality ->
+ assert_empty k v;
+ (polymorphism, { atts with locality = Some true })
+ | "global" when Option.is_empty atts.locality ->
+ assert_empty k v;
+ (polymorphism, { atts with locality = Some false })
+ | ("local" | "global") ->
+ user_err Pp.(str "Locality specified twice")
+ | "deprecated" when Option.is_empty atts.deprecated ->
+ begin match v with
+ | VernacFlagList [ "since", VernacFlagLeaf since ; "note", VernacFlagLeaf note ]
+ | VernacFlagList [ "note", VernacFlagLeaf note ; "since", VernacFlagLeaf since ] ->
+ let since = Some since and note = Some note in
+ (polymorphism, { atts with deprecated = Some (mk_deprecation ~since ~note ()) })
+ | VernacFlagList [ "since", VernacFlagLeaf since ] ->
+ let since = Some since in
+ (polymorphism, { atts with deprecated = Some (mk_deprecation ~since ()) })
+ | VernacFlagList [ "note", VernacFlagLeaf note ] ->
+ let note = Some note in
+ (polymorphism, { atts with deprecated = Some (mk_deprecation ~note ()) })
+ | _ -> CErrors.user_err (Pp.str "Ill formed “deprecated” attribute")
+ end
+ | "deprecated" ->
+ user_err Pp.(str "Deprecation specified twice")
+ | _ -> user_err Pp.(str "Unknown attribute " ++ str k)
+ )
+ (None, atts)
+ f
+
let interp ?(verbosely=true) ?proof ~st {CAst.loc;v=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 (f, v) ->
- let (polymorphism, atts) = flags f { loc; locality = None; polymorphic = false; program = orig_program_mode; } in
+ let (polymorphism, atts) = attributes_of_flags f (mk_atts ~program:orig_program_mode ()) in
aux ~polymorphism ~atts v
| VernacFail v -> with_fail st true (fun () -> control v)
| VernacTimeout (n,v) ->
@@ -2331,3 +2444,121 @@ let interp ?verbosely ?proof ~st cmd =
let exn = CErrors.push exn in
Vernacstate.invalidate_cache ();
iraise exn
+
+(** VERNAC EXTEND registering *)
+
+open Genarg
+open Extend
+
+type classifier = Genarg.raw_generic_argument list -> vernac_classification
+
+type (_, _) ty_sig =
+| TyNil : (atts:atts -> st:Vernacstate.t -> Vernacstate.t, Vernacexpr.vernac_classification) ty_sig
+| TyTerminal : string * ('r, 's) ty_sig -> ('r, 's) ty_sig
+| TyNonTerminal :
+ string option * ('a, 'b, 'c) Extend.ty_user_symbol * ('r, 's) ty_sig -> ('a -> 'r, 'a -> 's) ty_sig
+
+type ty_ml = TyML : bool * ('r, 's) ty_sig * 'r * 's option -> ty_ml
+
+let type_error () = CErrors.anomaly (Pp.str "Ill-typed VERNAC EXTEND")
+
+let rec untype_classifier : type r s. (r, s) ty_sig -> s -> classifier = function
+| TyNil -> fun f args ->
+ begin match args with
+ | [] -> f
+ | _ :: _ -> type_error ()
+ end
+| TyTerminal (_, ty) -> fun f args -> untype_classifier ty f args
+| TyNonTerminal (_, tu, ty) -> fun f args ->
+ begin match args with
+ | [] -> type_error ()
+ | Genarg.GenArg (Rawwit tag, v) :: args ->
+ match Genarg.genarg_type_eq tag (Egramml.proj_symbol tu) with
+ | None -> type_error ()
+ | Some Refl -> untype_classifier ty (f v) args
+ end
+
+(** Stupid GADTs forces us to duplicate the definition just for typing *)
+let rec untype_command : type r s. (r, s) ty_sig -> r -> plugin_args vernac_command = function
+| TyNil -> fun f args ->
+ begin match args with
+ | [] -> f
+ | _ :: _ -> type_error ()
+ end
+| TyTerminal (_, ty) -> fun f args -> untype_command ty f args
+| TyNonTerminal (_, tu, ty) -> fun f args ->
+ begin match args with
+ | [] -> type_error ()
+ | Genarg.GenArg (Rawwit tag, v) :: args ->
+ match Genarg.genarg_type_eq tag (Egramml.proj_symbol tu) with
+ | None -> type_error ()
+ | Some Refl -> untype_command ty (f v) args
+ end
+
+let rec untype_user_symbol : type s a b c. (a, b, c) Extend.ty_user_symbol -> (s, a) Extend.symbol = function
+| TUlist1 l -> Alist1 (untype_user_symbol l)
+| TUlist1sep (l, s) -> Alist1sep (untype_user_symbol l, Atoken (CLexer.terminal s))
+| TUlist0 l -> Alist0 (untype_user_symbol l)
+| TUlist0sep (l, s) -> Alist0sep (untype_user_symbol l, Atoken (CLexer.terminal s))
+| TUopt o -> Aopt (untype_user_symbol o)
+| TUentry a -> Aentry (Pcoq.genarg_grammar (ExtraArg a))
+| TUentryl (a, i) -> Aentryl (Pcoq.genarg_grammar (ExtraArg a), string_of_int i)
+
+let rec untype_grammar : type r s. (r, s) ty_sig -> vernac_expr Egramml.grammar_prod_item list = function
+| TyNil -> []
+| TyTerminal (tok, ty) -> Egramml.GramTerminal tok :: untype_grammar ty
+| TyNonTerminal (id, tu, ty) ->
+ let t = Option.map (fun _ -> rawwit (Egramml.proj_symbol tu)) id in
+ let symb = untype_user_symbol tu in
+ Egramml.GramNonTerminal (Loc.tag (t, symb)) :: untype_grammar ty
+
+let _ = untype_classifier, untype_command, untype_grammar, untype_user_symbol
+
+let classifiers : classifier array String.Map.t ref = ref String.Map.empty
+
+let get_vernac_classifier (name, i) args =
+ (String.Map.find name !classifiers).(i) args
+
+let declare_vernac_classifier name f =
+ classifiers := String.Map.add name f !classifiers
+
+let vernac_extend ~command ?classifier ?entry ext =
+ let get_classifier (TyML (_, ty, _, cl)) = match cl with
+ | Some cl -> untype_classifier ty cl
+ | None ->
+ match classifier with
+ | Some cl -> fun _ -> cl command
+ | None ->
+ let e = match entry with
+ | None -> "COMMAND"
+ | Some e -> Pcoq.Gram.Entry.name e
+ in
+ let msg = Printf.sprintf "\
+ Vernac entry \"%s\" misses a classifier. \
+ A classifier is a function that returns an expression \
+ of type vernac_classification (see Vernacexpr). You can: \n\
+ - Use '... EXTEND %s CLASSIFIED AS QUERY ...' if the \
+ new vernacular command does not alter the system state;\n\
+ - Use '... EXTEND %s CLASSIFIED AS SIDEFF ...' if the \
+ new vernacular command alters the system state but not the \
+ parser nor it starts a proof or ends one;\n\
+ - Use '... EXTEND %s CLASSIFIED BY f ...' to specify \
+ a global function f. The function f will be called passing\
+ \"%s\" as the only argument;\n\
+ - Add a specific classifier in each clause using the syntax:\n\
+ '[...] => [ f ] -> [...]'.\n\
+ Specific classifiers have precedence over global \
+ classifiers. Only one classifier is called."
+ command e e e command
+ in
+ CErrors.user_err (Pp.strbrk msg)
+ in
+ let cl = Array.map_of_list get_classifier ext in
+ let iter i (TyML (depr, ty, f, _)) =
+ let f = untype_command ty f in
+ let r = untype_grammar ty in
+ let () = vinterp_add depr (command, i) f in
+ Egramml.extend_vernac_command_grammar (command, i) entry r
+ in
+ let () = declare_vernac_classifier command cl in
+ List.iteri iter ext
diff --git a/vernac/vernacentries.mli b/vernac/vernacentries.mli
index 02a3b2bd61..fb2a30bac7 100644
--- a/vernac/vernacentries.mli
+++ b/vernac/vernacentries.mli
@@ -38,3 +38,37 @@ val interp_redexp_hook : (Environ.env -> Evd.evar_map -> Genredexpr.raw_red_expr
Evd.evar_map * Redexpr.red_expr) Hook.t
val universe_polymorphism_option_name : string list
+
+(** Elaborate a [atts] record out of a list of flags.
+ Also returns whether polymorphism is explicitly (un)set. *)
+val attributes_of_flags : Vernacexpr.vernac_flags -> Vernacinterp.atts -> bool option * Vernacinterp.atts
+
+(** {5 VERNAC EXTEND} *)
+
+type classifier = Genarg.raw_generic_argument list -> Vernacexpr.vernac_classification
+
+type (_, _) ty_sig =
+| TyNil : (atts:Vernacinterp.atts -> st:Vernacstate.t -> Vernacstate.t, Vernacexpr.vernac_classification) ty_sig
+| TyTerminal : string * ('r, 's) ty_sig -> ('r, 's) ty_sig
+| TyNonTerminal :
+ string option *
+ ('a, 'b, 'c) Extend.ty_user_symbol * ('r, 's) ty_sig ->
+ ('a -> 'r, 'a -> 's) ty_sig
+
+type ty_ml = TyML : bool (** deprecated *) * ('r, 's) ty_sig * 'r * 's option -> ty_ml
+
+(** Wrapper to dynamically extend vernacular commands. *)
+val vernac_extend :
+ command:string ->
+ ?classifier:(string -> Vernacexpr.vernac_classification) ->
+ ?entry:Vernacexpr.vernac_expr Pcoq.Entry.t ->
+ ty_ml list -> unit
+
+(** {5 STM classifiers} *)
+
+val get_vernac_classifier :
+ Vernacexpr.extend_name -> classifier
+
+(** Low-level API, not for casual user. *)
+val declare_vernac_classifier :
+ string -> classifier array -> unit
diff --git a/vernac/vernacexpr.ml b/vernac/vernacexpr.ml
index f74383b026..8fb74e6d78 100644
--- a/vernac/vernacexpr.ml
+++ b/vernac/vernacexpr.ml
@@ -121,12 +121,17 @@ type 'a hint_info_gen = 'a Typeclasses.hint_info_gen =
type hint_info_expr = Hints.hint_info_expr
[@@ocaml.deprecated "Please use [Hints.hint_info_expr]"]
+type 'a hints_transparency_target = 'a Hints.hints_transparency_target =
+ | HintsVariables
+ | HintsConstants
+ | HintsReferences of 'a list
+
type hints_expr = Hints.hints_expr =
| HintsResolve of (Hints.hint_info_expr * bool * Hints.reference_or_constr) list
| HintsResolveIFF of bool * qualid list * int option
| HintsImmediate of Hints.reference_or_constr list
| HintsUnfold of qualid list
- | HintsTransparency of qualid list * bool
+ | HintsTransparency of qualid hints_transparency_target * bool
| HintsMode of qualid * Hints.hint_mode list
| HintsConstructors of qualid list
| HintsExtern of int * constr_expr option * Genarg.raw_generic_argument
@@ -206,9 +211,9 @@ type proof_expr =
ident_decl * (local_binder_expr list * constr_expr)
type syntax_modifier =
- | SetItemLevel of string list * Extend.production_level
- | SetItemLevelAsBinder of string list * Notation_term.constr_as_binder_kind * Extend.production_level option
+ | SetItemLevel of string list * Notation_term.constr_as_binder_kind option * Extend.production_level option
| SetLevel of int
+ | SetCustomEntry of string * int option
| SetAssoc of Extend.gram_assoc
| SetEntryType of string * Extend.simple_constr_prod_entry_key
| SetOnlyParsing
@@ -328,6 +333,7 @@ type nonrec vernac_expr =
constr_expr * (lstring * syntax_modifier list) *
scope_name option
| VernacNotationAddFormat of string * string * string
+ | VernacDeclareCustomEntry of string
(* Gallina *)
| VernacDefinition of (Decl_kinds.discharge * Decl_kinds.definition_object_kind) * name_decl * definition_expr
@@ -454,13 +460,14 @@ type nonrec vernac_expr =
(* For extension *)
| VernacExtend of extend_name * Genarg.raw_generic_argument list
-type nonrec vernac_flag =
- | VernacProgram
- | VernacPolymorphic of bool
- | VernacLocal of bool
+type vernac_flags = (string * vernac_flag_value) list
+and vernac_flag_value =
+ | VernacFlagEmpty
+ | VernacFlagLeaf of string
+ | VernacFlagList of vernac_flags
type vernac_control =
- | VernacExpr of vernac_flag list * vernac_expr
+ | VernacExpr of vernac_flags * 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 CAst.t
diff --git a/vernac/vernacinterp.ml b/vernac/vernacinterp.ml
index d4f2a753ff..1bb1414f3d 100644
--- a/vernac/vernacinterp.ml
+++ b/vernac/vernacinterp.ml
@@ -12,15 +12,22 @@ open Util
open Pp
open CErrors
-type deprecation = bool
+type deprecation = { since : string option ; note : string option }
+
+let mk_deprecation ?(since=None) ?(note=None) () =
+ { since ; note }
type atts = {
loc : Loc.t option;
locality : bool option;
polymorphic : bool;
program : bool;
+ deprecated : deprecation option;
}
+let mk_atts ?(loc=None) ?(locality=None) ?(polymorphic=false) ?(program=false) ?(deprecated=None) () : atts =
+ { loc ; locality ; polymorphic ; program ; deprecated }
+
type 'a vernac_command = 'a -> atts:atts -> st:Vernacstate.t -> Vernacstate.t
type plugin_args = Genarg.raw_generic_argument list
@@ -28,7 +35,7 @@ type plugin_args = Genarg.raw_generic_argument list
(* Table of vernac entries *)
let vernac_tab =
(Hashtbl.create 211 :
- (Vernacexpr.extend_name, deprecation * plugin_args vernac_command) Hashtbl.t)
+ (Vernacexpr.extend_name, bool * plugin_args vernac_command) Hashtbl.t)
let vinterp_add depr s f =
try
diff --git a/vernac/vernacinterp.mli b/vernac/vernacinterp.mli
index 935cacf77b..46468b3098 100644
--- a/vernac/vernacinterp.mli
+++ b/vernac/vernacinterp.mli
@@ -10,21 +10,27 @@
(** Interpretation of extended vernac phrases. *)
-type deprecation = bool
+type deprecation = { since : string option ; note : string option }
+
+val mk_deprecation : ?since: string option -> ?note: string option -> unit -> deprecation
type atts = {
loc : Loc.t option;
locality : bool option;
polymorphic : bool;
program : bool;
+ deprecated : deprecation option;
}
+val mk_atts : ?loc: Loc.t option -> ?locality: bool option ->
+ ?polymorphic: bool -> ?program: bool -> ?deprecated: deprecation option -> unit -> atts
+
type 'a vernac_command = 'a -> atts:atts -> st:Vernacstate.t -> Vernacstate.t
type plugin_args = Genarg.raw_generic_argument list
val vinterp_init : unit -> unit
-val vinterp_add : deprecation -> Vernacexpr.extend_name -> plugin_args vernac_command -> unit
+val vinterp_add : bool -> Vernacexpr.extend_name -> plugin_args vernac_command -> unit
val overwriting_vinterp_add : Vernacexpr.extend_name -> plugin_args vernac_command -> unit
val call : Vernacexpr.extend_name -> plugin_args -> atts:atts -> st:Vernacstate.t -> Vernacstate.t