diff options
137 files changed, 3751 insertions, 2849 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cf1dc47fab..39c801197b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -470,7 +470,7 @@ doc:refman:deploy: - rm -rf _deploy/$CI_COMMIT_REF_NAME/stdlib - mkdir -p _deploy/$CI_COMMIT_REF_NAME - cp -rv _build/default/_doc/_html _deploy/$CI_COMMIT_REF_NAME/api - - cp -rv _build/default/doc/sphinx_build/html _deploy/$CI_COMMIT_REF_NAME/refman + - cp -rv _build/default/doc/refman-html _deploy/$CI_COMMIT_REF_NAME/refman - cp -rv _build/default/doc/stdlib/html _deploy/$CI_COMMIT_REF_NAME/stdlib - cd _deploy/$CI_COMMIT_REF_NAME/ - git add api refman stdlib @@ -592,6 +592,9 @@ validate:quick: library:ci-argosy: extends: .ci-template +library:ci-bbv: + extends: .ci-template + library:ci-bedrock2: extends: .ci-template-flambda artifacts: diff --git a/.ocamlformat b/.ocamlformat index d5608839fb..6d73a5297f 100644 --- a/.ocamlformat +++ b/.ocamlformat @@ -6,3 +6,4 @@ cases-exp-indent=2 field-space=loose exp-grouping=preserve break-cases=fit +doc-comments=before diff --git a/Makefile.ci b/Makefile.ci index f58dd9f37a..d4383fd409 100644 --- a/Makefile.ci +++ b/Makefile.ci @@ -11,6 +11,7 @@ CI_TARGETS= \ ci-aac_tactics \ ci-argosy \ + ci-bbv \ ci-bedrock2 \ ci-bignums \ ci-color \ diff --git a/Makefile.dune b/Makefile.dune index 0520d43da9..b77e78db69 100644 --- a/Makefile.dune +++ b/Makefile.dune @@ -54,8 +54,10 @@ voboot: plugins/ltac/dune states: voboot dune build --display=short $(DUNEOPT) dev/shim/coqtop-prelude +NONDOC_INSTALL_TARGETS:=coq.install coqide-server.install coqide.install + world: voboot - dune build $(DUNEOPT) @install + dune build $(DUNEOPT) $(NONDOC_INSTALL_TARGETS) coq: voboot dune build $(DUNEOPT) coq.install @@ -67,7 +69,7 @@ coqide-server: voboot dune build $(DUNEOPT) coqide-server.install watch: voboot - dune build $(DUNEOPT) @install -w + dune build $(DUNEOPT) $(NONDOC_INSTALL_TARGETS) -w check: voboot dune build $(DUNEOPT) @check diff --git a/configure.ml b/configure.ml index 55d71f6c2e..ee2e50ef86 100644 --- a/configure.ml +++ b/configure.ml @@ -923,7 +923,11 @@ let datadir,datadirsuffix = let (_,_,d,s) = select "DATADIR" in d,s (** * CC runtime flags *) -let cflags_dflt = "-Wall -Wno-unused -g -O2 -std=c99 -fasm" +(* Note that Coq's VM requires at least C99-compliant floating-point + arithmetic; this should be ensured by OCaml's own C flags, which + set a minimum of [--std=gnu99] ; modern compilers by default assume + C11 or later, so no explicit [--std=] flags are added by OCaml *) +let cflags_dflt = "-Wall -Wno-unused -g -O2" let cflags_sse2 = "-msse2 -mfpmath=sse" diff --git a/coq.opam.docker b/coq.opam.docker new file mode 100644 index 0000000000..229a47a87b --- /dev/null +++ b/coq.opam.docker @@ -0,0 +1,38 @@ +synopsis: "The Coq Proof Assistant" +description: """ +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. Typical +applications include the certification of properties of programming +languages (e.g. the CompCert compiler certification project, or the +Bedrock verified low-level programming library), the formalization of +mathematics (e.g. the full formalization of the Feit-Thompson theorem +or homotopy type theory) and teaching. +""" +opam-version: "2.0" +maintainer: "The Coq development team <coqdev@inria.fr>" +authors: "The Coq development team, INRIA, CNRS, and contributors." +homepage: "https://coq.inria.fr/" +bug-reports: "https://github.com/coq/coq/issues" +dev-repo: "git+https://github.com/coq/coq.git" +license: "LGPL-2.1" + +version: "dev" + +depends: [ + "ocaml" { >= "4.05.0" } + "ocamlfind" { build } + "num" + "conf-findutils" {build} +] + +build: [ + [ "./configure" "-prefix" prefix "-coqide" "no" ] + [make "-j%{jobs}%"] + [make "-j%{jobs}%" "byte"] +] +install: [ + [make "install"] + [make "install-byte"] +] diff --git a/dev/ci/ci-basic-overlay.sh b/dev/ci/ci-basic-overlay.sh index 70e3fe5c69..c18e556da8 100755 --- a/dev/ci/ci-basic-overlay.sh +++ b/dev/ci/ci-basic-overlay.sh @@ -200,6 +200,13 @@ : "${coqprime_CI_ARCHIVEURL:=${coqprime_CI_GITURL}/archive}" ######################################################################## +# bbv +######################################################################## +: "${bbv_CI_REF:=master}" +: "${bbv_CI_GITURL:=https://github.com/mit-plv/bbv}" +: "${bbv_CI_ARCHIVEURL:=${bbv_CI_GITURL}/archive}" + +######################################################################## # bedrock2 ######################################################################## : "${bedrock2_CI_REF:=tested}" diff --git a/dev/ci/ci-bbv.sh b/dev/ci/ci-bbv.sh new file mode 100755 index 0000000000..6892cea3e4 --- /dev/null +++ b/dev/ci/ci-bbv.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +ci_dir="$(dirname "$0")" +. "${ci_dir}/ci-common.sh" + +git_download bbv + +( cd "${CI_BUILD_DIR}/bbv" && make && make install ) diff --git a/dev/ci/user-overlays/11703-herbelin-master+turning-numTok-into-a-numeral-API.sh b/dev/ci/user-overlays/11703-herbelin-master+turning-numTok-into-a-numeral-API.sh new file mode 100644 index 0000000000..8a734feada --- /dev/null +++ b/dev/ci/user-overlays/11703-herbelin-master+turning-numTok-into-a-numeral-API.sh @@ -0,0 +1,6 @@ +if [ "$CI_PULL_REQUEST" = "11703" ] || [ "$CI_BRANCH" = "master+turning-numTok-into-a-numeral-API" ]; then + + quickchick_CI_REF=master+adapting-numTok-new-api-pr11703 + quickchick_CI_GITURL=https://github.com/herbelin/QuickChick + +fi diff --git a/dev/doc/changes.md b/dev/doc/changes.md index b82388675c..eac8d86b0a 100644 --- a/dev/doc/changes.md +++ b/dev/doc/changes.md @@ -11,6 +11,8 @@ Notations: +- Most operators on numerals have moved to file numTok.ml. + - Types `precedence`, `parenRelation`, `tolerability` in `notgram_ops.ml` have been reworked. See `entry_level` and `entry_relative_level` in `constrexpr.ml`. diff --git a/dev/top_printers.dbg b/dev/top_printers.dbg index da224aa5ab..06db787488 100644 --- a/dev/top_printers.dbg +++ b/dev/top_printers.dbg @@ -24,6 +24,8 @@ install_printer Top_printers.ppglob_constr install_printer Top_printers.pppattern install_printer Top_printers.ppfconstr install_printer Top_printers.ppbigint +install_printer Top_printers.ppnumtokunsigned +install_printer Top_printers.ppnumtokunsignednat install_printer Top_printers.ppintset install_printer Top_printers.ppidset install_printer Top_printers.ppidmapgen diff --git a/dev/top_printers.ml b/dev/top_printers.ml index 96dbf9142b..7002cbffac 100644 --- a/dev/top_printers.ml +++ b/dev/top_printers.ml @@ -86,6 +86,8 @@ let pptype = (fun x -> try pp(envpp (fun env evm t -> pr_ltype_env env evm t) x) let ppfconstr c = ppconstr (CClosure.term_of_fconstr c) let ppbigint n = pp (str (Bigint.to_string n));; +let ppnumtokunsigned n = pp (NumTok.Unsigned.print n) +let ppnumtokunsignednat n = pp (NumTok.UnsignedNat.print n) let prset pr l = str "[" ++ hov 0 (prlist_with_sep spc pr l) ++ str "]" let ppintset l = pp (prset int (Int.Set.elements l)) diff --git a/dev/top_printers.mli b/dev/top_printers.mli index c5f97f5873..c826391cac 100644 --- a/dev/top_printers.mli +++ b/dev/top_printers.mli @@ -54,6 +54,8 @@ val pppattern : Pattern.constr_pattern -> unit val ppfconstr : CClosure.fconstr -> unit val ppbigint : Bigint.bigint -> unit +val ppnumtokunsigned : NumTok.Unsigned.t -> unit +val ppnumtokunsignednat : NumTok.UnsignedNat.t -> unit val ppintset : Int.Set.t -> unit val ppidset : Names.Id.Set.t -> unit diff --git a/doc/changelog/02-specification-language/11098-master+arguments-supports-anonymous-implicit.rst b/doc/changelog/02-specification-language/11098-master+arguments-supports-anonymous-implicit.rst index 633bb6731e..70c57c718f 100644 --- a/doc/changelog/02-specification-language/11098-master+arguments-supports-anonymous-implicit.rst +++ b/doc/changelog/02-specification-language/11098-master+arguments-supports-anonymous-implicit.rst @@ -1,6 +1,6 @@ - **Added:** - :cmd:`Arguments <Arguments (implicits)>` now supports setting - implicit an anonymous argument, as e.g. in :g:`Arguments id {A} {_}` + :cmd:`Arguments` now supports setting + implicit an anonymous argument, as e.g. in :g:`Arguments id {A} {_}`. (`#11098 <https://github.com/coq/coq/pull/11098>`_, by Hugo Herbelin, fixes `#4696 <https://github.com/coq/coq/pull/4696>`_, `#5173 diff --git a/doc/changelog/02-specification-language/11235-non_maximal_implicit.rst b/doc/changelog/02-specification-language/11235-non_maximal_implicit.rst index d8ff1fec31..67e43973ce 100644 --- a/doc/changelog/02-specification-language/11235-non_maximal_implicit.rst +++ b/doc/changelog/02-specification-language/11235-non_maximal_implicit.rst @@ -1,6 +1,6 @@ - **Added:** Syntax for non maximal implicit arguments in definitions and terms using square brackets. The syntax is ``[x : A]``, ``[x]``, ```[A]`` - to be consistent with the command :cmd:`Arguments (implicits)`. + to be consistent with the command :cmd:`Arguments`. (`#11235 <https://github.com/coq/coq/pull/11235>`_, by SimonBoulier). diff --git a/doc/changelog/02-specification-language/11368-trailing_implicit_error.rst b/doc/changelog/02-specification-language/11368-trailing_implicit_error.rst index b0e658998b..11d7218ed0 100644 --- a/doc/changelog/02-specification-language/11368-trailing_implicit_error.rst +++ b/doc/changelog/02-specification-language/11368-trailing_implicit_error.rst @@ -1,6 +1,6 @@ - **Changed:** The warning raised when a trailing implicit is declared to be non maximally - inserted (with the command :cmd:`Arguments <Arguments (implicits)>`) has been turned into an error. + inserted (with the command :cmd:`Arguments`) has been turned into an error. This was deprecated since Coq 8.10 (`#11368 <https://github.com/coq/coq/pull/11368>`_, by SimonBoulier). diff --git a/doc/changelog/03-notations/11848-nicer-decimal-printing.rst b/doc/changelog/03-notations/11848-nicer-decimal-printing.rst new file mode 100644 index 0000000000..1d3a390f36 --- /dev/null +++ b/doc/changelog/03-notations/11848-nicer-decimal-printing.rst @@ -0,0 +1,5 @@ +- **Changed:** + Nicer printing for decimal constants in R and Q. + 1.5 is now printed 1.5 rather than 15e-1. + (`#11848 <https://github.com/coq/coq/pull/11848>`_, + by Pierre Roux). diff --git a/doc/changelog/03-notations/11859-warn-inexact-float.rst b/doc/changelog/03-notations/11859-warn-inexact-float.rst new file mode 100644 index 0000000000..224ffdbe9b --- /dev/null +++ b/doc/changelog/03-notations/11859-warn-inexact-float.rst @@ -0,0 +1,6 @@ +- **Added:** + In primitive floats, print a warning when parsing a decimal value + that is not exactly a binary64 floating-point number. + For instance, parsing 0.1 will print a warning whereas parsing 0.5 won't. + (`#11859 <https://github.com/coq/coq/pull/11859>`_, + by Pierre Roux). diff --git a/doc/changelog/04-tactics/11877-master+deprecated-_eqn.rst b/doc/changelog/04-tactics/11877-master+deprecated-_eqn.rst new file mode 100644 index 0000000000..827d484b28 --- /dev/null +++ b/doc/changelog/04-tactics/11877-master+deprecated-_eqn.rst @@ -0,0 +1,5 @@ +- **Removed:** + Deprecated syntax `_eqn` for :tacn:`destruct` and :tacn:`remember`. + Use `eqn:` syntax instead + (`#11877 <https://github.com/coq/coq/pull/11877>`_, + by Hugo Herbelin). diff --git a/doc/changelog/07-commands-and-options/11944-rm-searchabout-cmd.rst b/doc/changelog/07-commands-and-options/11944-rm-searchabout-cmd.rst new file mode 100644 index 0000000000..e409c638bb --- /dev/null +++ b/doc/changelog/07-commands-and-options/11944-rm-searchabout-cmd.rst @@ -0,0 +1,3 @@ +- **Removed:** Removed SearchAbout command that was deprecated in 8.5. + Use :cmd:`Search` instead. + (`#11944 <https://github.com/coq/coq/pull/11944>`_, by Jim Fehrle). diff --git a/doc/changelog/10-standard-library/1185-sort.rst b/doc/changelog/10-standard-library/1185-sort.rst new file mode 100644 index 0000000000..edb5ee3ac4 --- /dev/null +++ b/doc/changelog/10-standard-library/1185-sort.rst @@ -0,0 +1,5 @@ +- **Changed:** + The names of ``Sorted_sort`` and ``LocallySorted_sort`` in ``Coq.Sorting.MergeSort`` + have been swapped to appropriately reflect their meanings + (`#1185 <https://github.com/coq/coq/pull/1185>`_, + by Lysxia). diff --git a/doc/changelog/10-standard-library/11891-fix-order-notations.rst b/doc/changelog/10-standard-library/11891-fix-order-notations.rst new file mode 100644 index 0000000000..d58d26244a --- /dev/null +++ b/doc/changelog/10-standard-library/11891-fix-order-notations.rst @@ -0,0 +1,10 @@ +- **Changed:** + Notations :g:`<=?` and :g:`<?` from ``Coq.Structures.Orders`` and + ``Coq.Sorting.Mergesort.NatOrder`` are now at level 70 rather than + 35, so as to be compatible with the notations defined everywhere + else in the standard library. This may require re-parenthesizing + some expressions. These notations were breaking the ability to + import modules from the standard library that were otherwise + compatible (fixes `#11890 + <https://github.com/coq/coq/issues/11890>`_, `#11891 + <https://github.com/coq/coq/pull/11891>`_, by Jason Gross). diff --git a/doc/sphinx/addendum/program.rst b/doc/sphinx/addendum/program.rst index cbb5c0db8a..5cffe9e435 100644 --- a/doc/sphinx/addendum/program.rst +++ b/doc/sphinx/addendum/program.rst @@ -162,7 +162,7 @@ Program Definition This command types the value term in Russell and generates proof obligations. Once solved using the commands shown below, it binds the - final |Coq| term to the name ``ident`` in the environment. + final |Coq| term to the name :n:`@ident` in the environment. .. exn:: @ident already exists. :name: @ident already exists. (Program Definition) @@ -170,12 +170,12 @@ Program Definition .. cmdv:: Program Definition @ident : @type := @term - It interprets the type ``type``, potentially generating proof + It interprets the type :n:`@type`, potentially generating proof obligations to be resolved. Once done with them, we have a |Coq| - type |type_0|. It then elaborates the preterm ``term`` into a |Coq| - term |term_0|, checking that the type of |term_0| is coercible to - |type_0|, and registers ``ident`` as being of type |type_0| once the - set of obligations generated during the interpretation of |term_0| + type :n:`@type__0`. It then elaborates the preterm :n:`@term` into a |Coq| + term :n:`@term__0`, checking that the type of :n:`@term__0` is coercible to + :n:`@type__0`, and registers :n:`@ident` as being of type :n:`@type__0` once the + set of obligations generated during the interpretation of :n:`@term__0` and the aforementioned coercion derivation are solved. .. exn:: In environment … the term: @term does not have type @type. Actually, it has type ... @@ -185,7 +185,7 @@ Program Definition This is equivalent to: - :g:`Program Definition ident : forall binders, type := fun binders => term`. + :n:`Program Definition @ident : forall {* @binder }, @type := fun {* @binder } => @term`. .. TODO refer to production in alias diff --git a/doc/sphinx/addendum/ring.rst b/doc/sphinx/addendum/ring.rst index 76174e32b5..2a321b5cbf 100644 --- a/doc/sphinx/addendum/ring.rst +++ b/doc/sphinx/addendum/ring.rst @@ -1,8 +1,12 @@ +.. |bdi| replace:: :math:`\beta\delta\iota` .. |ra| replace:: :math:`\rightarrow_{\beta\delta\iota}` .. |la| replace:: :math:`\leftarrow_{\beta\delta\iota}` .. |eq| replace:: `=`:sub:`(by the main correctness theorem)` .. |re| replace:: ``(PEeval`` `v` `ap`\ ``)`` .. |le| replace:: ``(Pphi_dev`` `v` ``(norm`` `ap`\ ``))`` +.. |N| replace:: ``N`` +.. |nat| replace:: ``nat`` +.. |Z| replace:: ``Z`` .. _theringandfieldtacticfamilies: diff --git a/doc/sphinx/changes.rst b/doc/sphinx/changes.rst index a0cf9730a9..7401aff48c 100644 --- a/doc/sphinx/changes.rst +++ b/doc/sphinx/changes.rst @@ -4,7 +4,7 @@ Recent changes -------------- -.. ifconfig:: not coq_config.is_a_released_version +.. ifconfig:: not is_a_released_version .. include:: ../unreleased.rst @@ -160,7 +160,7 @@ Changes in 8.11+beta1 Annotation in `Arguments` for bidirectionality hints: it is now possible to tell type inference to use type information from the context once the `n` first arguments of an application are known. The syntax is: - `Arguments foo x y & z`. See :cmd:`Arguments (bidirectionality hints)` + `Arguments foo x y & z`. See :ref:`bidirectionality_hints` (`#10049 <https://github.com/coq/coq/pull/10049>`_, by Maxime Dénès with help from Enrico Tassi). - **Added:** @@ -216,7 +216,7 @@ Changes in 8.11+beta1 - **Changed:** Output of the :cmd:`Print` and :cmd:`About` commands. Arguments meta-data is now displayed as the corresponding - :cmd:`Arguments <Arguments (implicits)>` command instead of the + :cmd:`Arguments` command instead of the human-targeted prose used in previous Coq versions. (`#10985 <https://github.com/coq/coq/pull/10985>`_, by Gaëtan Gilbert). @@ -383,6 +383,10 @@ Changes in 8.11+beta1 <https://github.com/coq/coq/issues/3890>`_ and `#4638 <https://github.com/coq/coq/issues/4638>`_ by Maxime Dénès, review by Gaëtan Gilbert). +- **Changed:** + :cmd:`Fail` does not catch critical errors (including "stack overflow") + anymore (`#10173 <https://github.com/coq/coq/pull/10173>`_, + by Gaëtan Gilbert). - **Removed:** Undocumented :n:`Instance : !@type` syntax (`#10185 <https://github.com/coq/coq/pull/10185>`_, by Gaëtan Gilbert). @@ -685,7 +689,7 @@ reference manual. Here are the most important user-visible changes: - Universes: - - Added :cmd:`Print Universes Subgraph` variant of :cmd:`Print Universes`. + - Added Subgraph variant to :cmd:`Print Universes`. Try for instance :g:`Print Universes Subgraph(sigT2.u1 sigT_of_sigT2.u1 projT3_eq.u1).` (`#8451 <https://github.com/coq/coq/pull/8451>`_, by Gaëtan Gilbert). @@ -1508,7 +1512,7 @@ changes: - Removed deprecated commands ``Arguments Scope`` and ``Implicit Arguments`` in favor of :cmd:`Arguments (scopes)` and - :cmd:`Arguments (implicits)`, with the help of Jasper Hugunin. + :cmd:`Arguments`, with the help of Jasper Hugunin. - New flag :flag:`Uniform Inductive Parameters` by Jasper Hugunin to avoid repeating uniform parameters in constructor declarations. @@ -4715,7 +4719,7 @@ Specification language Module system -- Include Type is now deprecated since Include now accept both modules and +- Include Type is now deprecated since Include now accepts both modules and module types. - Declare ML Module supports Local option. - The sharing between non-logical object and the management of the diff --git a/doc/sphinx/conf.py b/doc/sphinx/conf.py index c2c1c68f5c..2ed9ec21b3 100755 --- a/doc/sphinx/conf.py +++ b/doc/sphinx/conf.py @@ -100,7 +100,7 @@ def copy_formatspecific_files(app): def setup(app): app.connect('builder-inited', copy_formatspecific_files) - app.add_config_value('coq_config', coq_config, 'env') + app.add_config_value('is_a_released_version', coq_config.is_a_released_version, 'env') # The master toctree document. # We create this file in `copy_master_doc` above. diff --git a/doc/sphinx/language/cic.rst b/doc/sphinx/language/cic.rst index b0acd09af6..09a3897a06 100644 --- a/doc/sphinx/language/cic.rst +++ b/doc/sphinx/language/cic.rst @@ -47,8 +47,7 @@ provable. An object of type :math:`\Prop` is called a proposition. The sort :math:`\SProp` is like :math:`\Prop` but the propositions in :math:`\SProp` are known to have irrelevant proofs (all proofs are equal). Objects of type :math:`\SProp` are called strict propositions. -:math:`\SProp` is rejected except when using the compiler option -``-allow-sprop``. See :ref:`sprop` for information about using +See :ref:`sprop` for information about using :math:`\SProp`, and :cite:`Gilbert:POPL2019` for meta theoretical considerations. diff --git a/doc/sphinx/language/coq-library.rst b/doc/sphinx/language/coq-library.rst index 39f2ccec29..acdd4408ed 100644 --- a/doc/sphinx/language/coq-library.rst +++ b/doc/sphinx/language/coq-library.rst @@ -1062,6 +1062,11 @@ Floating-point constants are parsed and pretty-printed as (17-digit) decimal constants. This ensures that the composition :math:`\text{parse} \circ \text{print}` amounts to the identity. +.. warn:: The constant @numeral is not a binary64 floating-point value. A closest value will be used and unambiguously printed @numeral. [inexact-float,parsing] + + Not all decimal constants are floating-point values. This warning + is generated when parsing such a constant (for instance ``0.1``). + .. example:: .. coqtop:: all diff --git a/doc/sphinx/language/gallina-extensions.rst b/doc/sphinx/language/gallina-extensions.rst index eff5eb60eb..18b05e47d3 100644 --- a/doc/sphinx/language/gallina-extensions.rst +++ b/doc/sphinx/language/gallina-extensions.rst @@ -20,25 +20,31 @@ expressions. In this sense, the :cmd:`Record` construction allows defining .. _record_grammar: - .. productionlist:: sentence - 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` [ `decl_notations` ] - : `ident` [ `binders` ] [: `type` ] := `term` - -.. cmd:: {| Record | Structure } @inductive_definition {* with @inductive_definition } +.. cmd:: {| Record | Structure } @record_definition {* with @record_definition } :name: Record; Structure - The first identifier :token:`ident` is the name of the defined record and :token:`sort` is its - type. The optional identifier following ``:=`` is the name of its constructor. If it is omitted, - the default name :n:`Build_@ident`, where :token:`ident` is the record name, is used. If :token:`sort` is - omitted, the default sort is :math:`\Type`. The identifiers inside the brackets are the names of - fields. For a given field :token:`ident`, its type is :n:`forall {* @binder }, @type`. - Notice that the type of a particular identifier may depend on a previously-given identifier. Thus the - order of the fields is important. The record can depend as a whole on parameters :token:`binders` - and each field can also depend on its own :token:`binders`. Finally, notations can be attached to - fields using the :n:`decl_notations` annotation. + .. insertprodn record_definition field_body + + .. prodn:: + record_definition ::= {? > } @ident_decl {* @binder } {? : @type } {? @ident } %{ {*; @record_field } %} {? @decl_notations } + record_field ::= {* #[ {*, @attr } ] } @name {? @field_body } {? %| @num } {? @decl_notations } + field_body ::= {* @binder } @of_type + | {* @binder } @of_type := @term + | {* @binder } := @term + + Each :n:`@record_definition` defines a record named by :n:`@ident_decl`. + The constructor name is given by :n:`@ident`. + If the constructor name is not specified, then the default name :n:`Build_@ident` is used, + where :n:`@ident` is the record name. + + If :n:`@type` is + omitted, the default type is :math:`\Type`. The identifiers inside the brackets are the field names. + The type of each field :n:`@ident` is :n:`forall {* @binder }, @type`. + Notice that the type of an identifier can depend on a previously-given identifier. Thus the + order of the fields is important. :n:`@binder` parameters may be applied to the record as a whole + or to individual fields. + + Notations can be attached to fields using the :n:`@decl_notations` annotation. :cmd:`Record` and :cmd:`Structure` are synonyms. @@ -355,16 +361,12 @@ can be alternatively written Definition not (b:bool) := if b then false else true. -More generally, for an inductive type with constructors |C_1| and |C_2|, -we have the following equivalence +More generally, for an inductive type with constructors :n:`@ident__1` +and :n:`@ident__2`, the following terms are equal: -:: +:n:`if @term__0 {? {? as @name } return @term } then @term__1 else @term__2` - if term [dep_ret_type] then term₁ else term₂ ≡ - match term [dep_ret_type] with - | C₁ _ … _ => term₁ - | C₂ _ … _ => term₂ - end +:n:`match @term__0 {? {? as @name } return @term } with | @ident__1 {* _ } => @term__1 | @ident__2 {* _ } => @term__2 end` .. example:: @@ -392,11 +394,13 @@ constructions. There are two variants of them. First destructuring let syntax ++++++++++++++++++++++++++++++ -The expression :g:`let (`\ |ident_1|:g:`, … ,` |ident_n|\ :g:`) :=` |term_0|\ :g:`in` |term_1| performs -case analysis on |term_0| which must be in an inductive type with one -constructor having itself :math:`n` arguments. Variables |ident_1| … |ident_n| are -bound to the :math:`n` arguments of the constructor in expression |term_1|. For -instance, the definition +The expression :n:`let ( {*, @ident__i } ) := @term__0 in @term__1` +performs case analysis on :n:`@term__0` whose type must be an +inductive type with exactly one constructor. The number of variables +:n:`@ident__i` must correspond to the number of arguments of this +contrustor. Then, in :n:`@term__1`, these variables are bound to the +arguments of the constructor in :n:`@term__0`. For instance, the +definition .. coqtop:: reset all @@ -411,7 +415,7 @@ can be alternatively written Definition fst (A B:Set) (p:A * B) := let (x, _) := p in x. Notice that reduction is different from regular :g:`let … in …` -construction since it happens only if |term_0| is in constructor form. +construction since it happens only if :n:`@term__0` is in constructor form. Otherwise, the reduction is blocked. The pretty-printing of a definition by matching on a irrefutable @@ -591,29 +595,82 @@ This example emphasizes what the printing settings offer. Advanced recursive functions ---------------------------- -The following experimental command is available when the ``FunInd`` library has been loaded via ``Require Import FunInd``: +The following command is available when the ``FunInd`` library has been loaded via ``Require Import FunInd``: -.. cmd:: Function @ident {* @binder} { @fixannot } : @type := @term +.. cmd:: Function @fix_definition {* with @fix_definition } - This command can be seen as a generalization of ``Fixpoint``. It is actually a wrapper - for several ways of defining a function *and other useful related - objects*, namely: an induction principle that reflects the recursive + This command is a generalization of :cmd:`Fixpoint`. It is a wrapper + for several ways of defining a function *and* other useful related + objects, namely: an induction principle that reflects the recursive structure of the function (see :tacn:`function induction`) and its fixpoint equality. - The meaning of this declaration is to define a function ident, - similarly to ``Fixpoint``. Like in ``Fixpoint``, the decreasing argument must + This defines a function similar to those defined by :cmd:`Fixpoint`. + As in :cmd:`Fixpoint`, the decreasing argument must be given (unless the function is not recursive), but it might not - necessarily be *structurally* decreasing. The point of the :n:`{ @fixannot }` annotation - is to name the decreasing argument *and* to describe which kind of - decreasing criteria must be used to ensure termination of recursive + necessarily be *structurally* decreasing. Use the :n:`@fixannot` clause + to name the decreasing argument *and* to describe which kind of + decreasing criteria to use to ensure termination of recursive calls. -The ``Function`` construction also enjoys the ``with`` extension to define -mutually recursive definitions. However, this feature does not work -for non structurally recursive functions. - -See the documentation of functional induction (:tacn:`function induction`) -and ``Functional Scheme`` (:ref:`functional-scheme`) for how to use -the induction principle to easily reason about the function. + :cmd:`Function` also supports the :n:`with` clause to create + mutually recursive definitions, however this feature is limited + to structurally recursive functions (i.e. when :n:`@fixannot` is a :n:`struct` + clause). + + See :tacn:`function induction` and :cmd:`Functional Scheme` for how to use + the induction principle to reason easily about the function. + + The form of the :n:`@fixannot` clause determines which definition mechanism :cmd:`Function` uses. + (Note that references to :n:`ident` below refer to the name of the function being defined.): + + * If :n:`@fixannot` is not specified, :cmd:`Function` + defines the nonrecursive function :token:`ident` as if it was declared with + :cmd:`Definition`. In addition, the following are defined: + + + :token:`ident`\ ``_rect``, :token:`ident`\ ``_rec`` and :token:`ident`\ ``_ind``, + which reflect the pattern matching structure of :token:`term` (see :cmd:`Inductive`); + + The inductive :n:`R_@ident` corresponding to the graph of :token:`ident` (silently); + + :token:`ident`\ ``_complete`` and :token:`ident`\ ``_correct`` which + are inversion information linking the function and its graph. + + * If :n:`{ struct ... }` is specified, :cmd:`Function` + defines the structural recursive function :token:`ident` as if it was declared + with :cmd:`Fixpoint`. In addition, the following are defined: + + + The same objects as above; + + The fixpoint equation of :token:`ident`: :n:`@ident`\ ``_equation``. + + * If :n:`{ measure ... }` or :n:`{ wf ... }` are specified, :cmd:`Function` + defines a recursive function by well-founded recursion. The module ``Recdef`` + of the standard library must be loaded for this feature. + + + :n:`{measure @one_term__1 {? @ident } {? @one_term__2 } }`\: where :n:`@ident` is the decreasing argument + and :n:`@one_term__1` is a function from the type of :n:`@ident` to :g:`nat` for which + the decreasing argument decreases (for the :g:`lt` order on :g:`nat`) + for each recursive call of the function. The parameters of the function are + bound in :n:`@one_term__1`. + + :n:`{wf @one_term @ident }`\: where :n:`@ident` is the decreasing argument and + :n:`@one_term` is an ordering relation on the type of :n:`@ident` (i.e. of type + `T`\ :math:`_{\sf ident}` → `T`\ :math:`_{\sf ident}` → ``Prop``) for which the decreasing argument + decreases for each recursive call of the function. The order must be well-founded. + The parameters of the function are bound in :n:`@one_term`. + + If the clause is ``measure`` or ``wf``, the user is left with some proof + obligations that will be used to define the function. These proofs + are: proofs that each recursive call is actually decreasing with + respect to the given criteria, and (if the criteria is `wf`) a proof + that the ordering relation is well-founded. Once proof obligations are + discharged, the following objects are defined: + + + The same objects as with the ``struct`` clause; + + The lemma :n:`@ident`\ ``_tcc`` which collects all proof obligations in one + property; + + The lemmas :n:`@ident`\ ``_terminate`` and :n:`@ident`\ ``_F`` which will be inlined + during extraction of :n:`@ident`. + + The way this recursive function is defined is the subject of several + papers by Yves Bertot and Antonia Balaa on the one hand, and Gilles + Barthe, Julien Forest, David Pichardie, and Vlad Rusu on the other + hand. .. note:: @@ -653,7 +710,7 @@ the induction principle to easily reason about the function. :token:`term` must be built as a *pure pattern matching tree* (:g:`match … with`) with applications only *at the end* of each branch. -Function does not support partial application of the function being +:cmd:`Function` does not support partial application of the function being defined. Thus, the following example cannot be accepted due to the presence of partial application of :g:`wrong` in the body of :g:`wrong`: @@ -686,7 +743,7 @@ terminating functions. will not be generated. This error happens generally when: - the definition uses pattern matching on dependent types, - which ``Function`` cannot deal with yet. + which :cmd:`Function` cannot deal with yet. - the definition is not a *pattern matching tree* as explained above. .. warn:: Cannot define principle(s) for @ident. @@ -700,65 +757,6 @@ terminating functions. .. 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. - -.. cmdv:: Function @ident {* @binder } : @type := @term - - Defines the nonrecursive function :token:`ident` as if it was declared with - :cmd:`Definition`. Moreover the following are defined: - - + :token:`ident`\ ``_rect``, :token:`ident`\ ``_rec`` and :token:`ident`\ ``_ind``, - which reflect the pattern matching structure of :token:`term` (see :cmd:`Inductive`); - + The inductive :n:`R_@ident` corresponding to the graph of :token:`ident` (silently); - + :token:`ident`\ ``_complete`` and :token:`ident`\ ``_correct`` which - are inversion information linking the function and its graph. - -.. cmdv:: Function @ident {* @binder } { struct @ident } : @type := @term - - Defines the structural recursive function :token:`ident` as if declared - with :cmd:`Fixpoint`. Moreover the following are defined: - - + The same objects as above; - + The fixpoint equation of :token:`ident`: :token:`ident`\ ``_equation``. - -.. cmdv:: Function @ident {* @binder } { measure @term @ident } : @type := @term - Function @ident {* @binder } { wf @term @ident } : @type := @term - - Defines a recursive function by well-founded recursion. The module ``Recdef`` - of the standard library must be loaded for this feature. The ``{}`` - annotation is mandatory and must be one of the following: - - + :n:`{measure @term @ident }` with :token:`ident` being the decreasing argument - and :token:`term` being a function from type of :token:`ident` to :g:`nat` for which - value on the decreasing argument decreases (for the :g:`lt` order on :g:`nat`) - at each recursive call of :token:`term`. Parameters of the function are - bound in :token:`term`; - + :n:`{wf @term @ident }` with :token:`ident` being the decreasing argument and - :token:`term` an ordering relation on the type of :token:`ident` (i.e. of type - `T`\ :math:`_{\sf ident}` → `T`\ :math:`_{\sf ident}` → ``Prop``) for which the decreasing argument - decreases at each recursive call of :token:`term`. The order must be well-founded. - Parameters of the function are bound in :token:`term`. - - If the annotation is ``measure`` or ``fw``, the user is left with some proof - obligations that will be used to define the function. These proofs - are: proofs that each recursive call is actually decreasing with - respect to the given criteria, and (if the criteria is `wf`) a proof - that the ordering relation is well-founded. Once proof obligations are - discharged, the following objects are defined: - - + The same objects as with the struct; - + The lemma `ident`\ :math:`_{\sf tcc}` which collects all proof obligations in one - property; - + The lemmas `ident`\ :math:`_{\sf terminate}` and `ident`\ :math:`_{\sf F}` which is needed to be inlined - during extraction of ident. - - The way this recursive function is defined is the subject of several - papers by Yves Bertot and Antonia Balaa on the one hand, and Gilles - Barthe, Julien Forest, David Pichardie, and Vlad Rusu on the other - hand. Remark: Proof obligations are presented as several subgoals - belonging to a Lemma `ident`\ :math:`_{\sf tcc}`. - .. _section-mechanism: Section mechanism @@ -813,43 +811,44 @@ Sections create local contexts which can be shared across multiple definitions. .. cmd:: End @ident - This command closes the section named :token:`ident`. After closing of the - section, the local declarations (variables and local definitions, see :cmd:`Variable`) get + This command closes the section or module named :token:`ident`. + See :ref:`Terminating an interactive module or module type definition<terminating_module>` + for a description of its use with modules. + + After closing the + section, the local declarations (variables and local definitions, see :cmd:`Variable`) are *discharged*, meaning that they stop being visible and that all global objects defined in the section are generalized with respect to the variables and local definitions they each depended on in the section. - .. exn:: This is not the last opened section. + .. exn:: There is nothing to end. :undocumented: + .. exn:: Last block to end has name @ident. + :undocumented: + .. note:: Most commands, like :cmd:`Hint`, :cmd:`Notation`, option management, … which appear inside a section are canceled when the section is closed. -.. cmd:: Let @ident := @term - - This command binds the value :token:`term` to the name :token:`ident` in the - environment of the current section. The name :token:`ident` is accessible - only within the current section. When the section is closed, all persistent - definitions and theorems within it and depending on :token:`ident` - will be prefixed by the let-in definition :n:`let @ident := @term in`. - - .. exn:: @ident already exists. - :name: @ident already exists. (Let) - :undocumented: +.. cmd:: Let @ident @def_body + Let Fixpoint @fix_definition {* with @fix_definition } + Let CoFixpoint @cofix_definition {* with @cofix_definition } + :name: Let; Let Fixpoint; Let CoFixpoint - .. cmdv:: Let @ident {* @binder } {? : @type } := @term - :undocumented: + These commands behave like :cmd:`Definition`, :cmd:`Fixpoint` and :cmd:`CoFixpoint`, except that + the declared constant is local to the current section. + When the section is closed, all persistent + definitions and theorems within it that depend on the constant + will be wrapped with a :n:`@term_let` with the same declaration. - .. cmdv:: Let Fixpoint @ident @fix_body {* with @fix_body} - :name: Let Fixpoint - :undocumented: + As for :cmd:`Definition`, :cmd:`Fixpoint` and :cmd:`CoFixpoint`, + if :n:`@term` is omitted, :n:`@type` is required and Coq enters proof editing mode. + This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. + In this case, the proof should be terminated with :cmd:`Defined` in order to define a constant + for which the computational behavior is relevant. See :ref:`proof-editing-mode`. - .. cmdv:: Let CoFixpoint @ident @fix_body {* with @fix_body} - :name: Let CoFixpoint - :undocumented: - -.. cmd:: Context {* @binder } +.. cmd:: Context {+ @binder } Declare variables in the context of the current section, like :cmd:`Variable`, but also allowing implicit variables, :ref:`implicit-generalization`, and @@ -869,255 +868,297 @@ Module system The module system provides a way of packaging related elements together, as well as a means of massive abstraction. - .. productionlist:: modules - module_type : `qualid` - : `module_type` with Definition `qualid` := `term` - : `module_type` with Module `qualid` := `qualid` - : `qualid` `qualid` … `qualid` - : !`qualid` `qualid` … `qualid` - module_binding : ( [Import|Export] `ident` … `ident` : `module_type` ) - module_bindings : `module_binding` … `module_binding` - module_expression : `qualid` … `qualid` - : !`qualid` … `qualid` - Syntax of modules +.. cmd:: Module {? {| Import | Export } } @ident {* @module_binder } {? @of_module_type } {? := {+<+ @module_expr_inl } } -In the syntax of module application, the ! prefix indicates that any -`Inline` directive in the type of the functor arguments will be ignored -(see the :cmd:`Module Type` command below). + .. insertprodn module_binder module_expr_inl + .. prodn:: + module_binder ::= ( {? {| Import | Export } } {+ @ident } : @module_type_inl ) + module_type_inl ::= ! @module_type + | @module_type {? @functor_app_annot } + functor_app_annot ::= [ inline at level @num ] + | [ no inline ] + module_type ::= @qualid + | ( @module_type ) + | @module_type @module_expr_atom + | @module_type with @with_declaration + with_declaration ::= Definition @qualid {? @univ_decl } := @term + | Module @qualid := @qualid + module_expr_atom ::= @qualid + | ( {+ @module_expr_atom } ) + of_module_type ::= : @module_type_inl + | {* <: @module_type_inl } + module_expr_inl ::= ! {+ @module_expr_atom } + | {+ @module_expr_atom } {? @functor_app_annot } -.. cmd:: Module @ident + Defines a module named :token:`ident`. See the examples :ref:`here<module_examples>`. - This command is used to start an interactive module named :token:`ident`. + The :n:`Import` and :n:`Export` flags specify whether the module should be automatically + imported or exported. -.. cmdv:: Module @ident {* @module_binding} + Specifying :n:`{* @module_binder }` starts a functor with + parameters given by the :n:`@module_binder`\s. (A *functor* is a function + from modules to modules.) - Starts an interactive functor with - parameters given by module_bindings. + .. todo: would like to find a better term than "interactive", not very descriptive -.. cmdv:: Module @ident : @module_type + :n:`@of_module_type` specifies the module type. :n:`{+ <: @module_type_inl }` + starts a module that satisfies each :n:`@module_type_inl`. - Starts an interactive module specifying its module type. + :n:`:= {+<+ @module_expr_inl }` specifies the body of a module or functor + definition. If it's not specified, then the module is defined *interactively*, + meaning that the module is defined as a series of commands terminated with :cmd:`End` + instead of in a single :cmd:`Module` command. + Interactively defining the :n:`@module_expr_inl`\s in a series of + :cmd:`Include` commands is equivalent to giving them all in a single + non-interactive :cmd:`Module` command. -.. cmdv:: Module @ident {* @module_binding} : @module_type + The ! prefix indicates that any assumption command (such as :cmd:`Axiom`) with an :n:`Inline` clause + in the type of the functor arguments will be ignored. - Starts an interactive functor with parameters given by the list of - :token:`module_bindings`, and output module type :token:`module_type`. + .. todo: What is an Inline directive? sb command but still unclear. Maybe referring to the + "inline" in functor_app_annot? or assumption_token Inline assum_list? -.. cmdv:: Module @ident <: {+<: @module_type } +.. cmd:: Module Type @ident {* @module_binder } {* <: @module_type_inl } {? := {+<+ @module_type_inl } } - Starts an interactive module satisfying each :token:`module_type`. + Defines a module type named :n:`@ident`. See the example :ref:`here<example_def_simple_module_type>`. - .. cmdv:: Module @ident {* @module_binding} <: {+<: @module_type }. + Specifying :n:`{* @module_binder }` starts a functor type with + parameters given by the :n:`@module_binder`\s. - Starts an interactive functor with parameters given by the list of - :token:`module_binding`. The output module type - is verified against each :token:`module_type`. + :n:`:= {+<+ @module_type_inl }` specifies the body of a module or functor type + definition. If it's not specified, then the module type is defined *interactively*, + meaning that the module type is defined as a series of commands terminated with :cmd:`End` + instead of in a single :cmd:`Module Type` command. + Interactively defining the :n:`@module_type_inl`\s in a series of + :cmd:`Include` commands is equivalent to giving them all in a single + non-interactive :cmd:`Module Type` command. -.. cmdv:: Module {| Import | Export } +.. _terminating_module: - Behaves like :cmd:`Module`, but automatically imports or exports the module. +**Terminating an interactive module or module type definition** -Reserved commands inside an interactive module -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Interactive modules are terminated with the :cmd:`End` command, which +is also used to terminate :ref:`Sections<section-mechanism>`. +:n:`End @ident` closes the interactive module or module type :token:`ident`. +If the module type was given, the command verifies that the content of the module +matches the module type. If the module is not a +functor, its components (constants, inductive types, submodules etc.) +are now available through the dot notation. -.. cmd:: Include @module +.. exn:: No such label @ident. + :undocumented: - Includes the content of module in the current - interactive module. Here module can be a module expression or a module - type expression. If module is a high-order module or module type - expression then the system tries to instantiate module by the current - interactive module. +.. exn:: Signature components for label @ident do not match. + :undocumented: -.. cmd:: Include {+<+ @module} +.. exn:: The field @ident is missing in @qualid. + :undocumented: - is a shortcut for the commands :n:`Include @module` for each :token:`module`. +.. |br| raw:: html -.. cmd:: End @ident + <br> - This command closes the interactive module :token:`ident`. If the module type - was given the content of the module is matched against it and an error - is signaled if the matching fails. If the module is basic (is not a - functor) its components (constants, inductive types, submodules etc.) - are now available through the dot notation. +.. note:: - .. exn:: No such label @ident. - :undocumented: + #. Interactive modules and module types can be nested. + #. Interactive modules and module types can't be defined inside of :ref:`sections<section-mechanism>`. + Sections can be defined inside of interactive modules and module types. + #. Hints and notations (:cmd:`Hint` and :cmd:`Notation` commands) can also appear inside interactive + modules and module types. Note that with module definitions like: - .. exn:: Signature components for label @ident do not match. - :undocumented: + :n:`Module @ident__1 : @module_type := @ident__2.` - .. exn:: This is not the last opened module. - :undocumented: + or -.. cmd:: Module @ident := @module_expression + :n:`Module @ident__1 : @module_type.` |br| + :n:`Include @ident__2.` |br| + :n:`End @ident__1.` - This command defines the module identifier :token:`ident` to be equal - to :token:`module_expression`. + hints and the like valid for :n:`@ident__1` are the ones defined in :n:`@module_type` + rather then those defined in :n:`@ident__2` (or the module body). + #. Within an interactive module type definition, the :cmd:`Parameter` command declares a + constant instead of definining a new axiom (which it does when not in a module type definition). + #. Assumptions such as :cmd:`Axiom` that include the :n:`Inline` clause will be automatically + expanded when the functor is applied, except when the function application is prefixed by ``!``. - .. cmdv:: Module @ident {* @module_binding} := @module_expression +.. cmd:: Include @module_type_inl {* <+ @module_expr_inl } - Defines a functor with parameters given by the list of :token:`module_binding` and body :token:`module_expression`. + Includes the content of module(s) in the current + interactive module. Here :n:`@module_type_inl` can be a module expression or a module + type expression. If it is a high-order module or module type + expression then the system tries to instantiate :n:`@module_type_inl` with the current + interactive module. - .. cmdv:: Module @ident {* @module_binding} : @module_type := @module_expression + Including multiple modules is a single :cmd:`Include` is equivalent to including each module + in a separate :cmd:`Include` command. - Defines a functor with parameters given by the list of :token:`module_binding` (possibly none), and output module type :token:`module_type`, - with body :token:`module_expression`. +.. cmd:: Include Type {+<+ @module_type_inl } - .. cmdv:: Module @ident {* @module_binding} <: {+<: @module_type} := @module_expression + .. deprecated:: 8.3 - Defines a functor with parameters given by module_bindings (possibly none) with body :token:`module_expression`. - The body is checked against each :n:`@module_type__i`. + Use :cmd:`Include` instead. - .. cmdv:: Module @ident {* @module_binding} := {+<+ @module_expression} +.. cmd:: Declare Module {? {| Import | Export } } @ident {* @module_binder } : @module_type_inl - is equivalent to an interactive module where each :token:`module_expression` is included. + Declares a module :token:`ident` of type :token:`module_type_inl`. -.. cmd:: Module Type @ident + If :n:`@module_binder`\s are specified, declares a functor with parameters given by the list of + :token:`module_binder`\s. - This command is used to start an interactive module type :token:`ident`. +.. cmd:: Import {+ @qualid } - .. cmdv:: Module Type @ident {* @module_binding} + If :token:`qualid` denotes a valid basic module (i.e. its module type is a + signature), makes its components available by their short names. - Starts an interactive functor type with parameters given by :token:`module_bindings`. + .. example:: + .. coqtop:: reset in -Reserved commands inside an interactive module type: -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Module Mod. + Definition T:=nat. + Check T. + End Mod. + Check Mod.T. -.. cmd:: Include @module + .. coqtop:: all - Same as ``Include`` inside a module. + Fail Check T. + Import Mod. + Check T. -.. cmd:: Include {+<+ @module} + Some features defined in modules are activated only when a module is + imported. This is for instance the case of notations (see :ref:`Notations`). - This is a shortcut for the command :n:`Include @module` for each :token:`module`. + Declarations made with the :attr:`local` attribute are never imported by the :cmd:`Import` + command. Such declarations are only accessible through their fully + qualified name. -.. cmd:: @assumption_token Inline @assums - :name: Inline + .. example:: - The instance of this assumption will be automatically expanded at functor application, except when - this functor application is prefixed by a ``!`` annotation. + .. coqtop:: in -.. cmd:: End @ident + Module A. + Module B. + Local Definition T := nat. + End B. + End A. + Import A. - This command closes the interactive module type :token:`ident`. + .. coqtop:: all fail - .. exn:: This is not the last opened module type. - :undocumented: + Check B.T. -.. cmd:: Module Type @ident := @module_type +.. cmd:: Export {+ @qualid } + :name: Export - Defines a module type :token:`ident` equal to :token:`module_type`. + Similar to :cmd:`Import`, except that when the module containing this command + is imported, the :n:`{+ @qualid }` are imported as well. - .. cmdv:: Module Type @ident {* @module_binding} := @module_type + .. exn:: @qualid is not a module. + :undocumented: - Defines a functor type :token:`ident` specifying functors taking arguments :token:`module_bindings` and - returning :token:`module_type`. + .. warn:: Trying to mask the absolute name @qualid! + :undocumented: - .. cmdv:: Module Type @ident {* @module_binding} := {+<+ @module_type } +.. cmd:: Print Module @qualid - is equivalent to an interactive module type were each :token:`module_type` is included. + Prints the module type and (optionally) the body of the module :n:`@qualid`. -.. cmd:: Declare Module @ident : @module_type +.. cmd:: Print Module Type @qualid - Declares a module :token:`ident` of type :token:`module_type`. + Prints the module type corresponding to :n:`@qualid`. - .. cmdv:: Declare Module @ident {* @module_binding} : @module_type +.. flag:: Short Module Printing - Declares a functor with parameters given by the list of :token:`module_binding` and output module type - :token:`module_type`. + This flag (off by default) disables the printing of the types of fields, + leaving only their names, for the commands :cmd:`Print Module` and + :cmd:`Print Module Type`. -.. example:: +.. _module_examples: - Let us define a simple module. +Examples +~~~~~~~~ - .. coqtop:: all +.. example:: Defining a simple module interactively - Module M. + .. coqtop:: in + Module M. Definition T := nat. - Definition x := 0. - Definition y : bool. + .. coqtop:: all + Definition y : bool. exact true. - Defined. + .. coqtop:: in + Defined. End M. -Inside a module one can define constants, prove theorems and do any -other things that can be done in the toplevel. Components of a closed +Inside a module one can define constants, prove theorems and do anything +else that can be done in the toplevel. Components of a closed module can be accessed using the dot notation: .. coqtop:: all Print M.x. -A simple module type: - -.. coqtop:: all - - Module Type SIG. - - Parameter T : Set. - - Parameter x : T. - - End SIG. +.. _example_def_simple_module_type: -Now we can create a new module from M, giving it a less precise -specification: the y component is dropped as well as the body of x. - -.. coqtop:: all +.. example:: Defining a simple module type interactively - Module N : SIG with Definition T := nat := M. - - Print N.T. - - Print N.x. - - Fail Print N.y. - -.. reset to remove N (undo in last coqtop block doesn't seem to do that), invisibly redefine M, SIG -.. coqtop:: none reset - - Module M. + .. coqtop:: in - Definition T := nat. + Module Type SIG. + Parameter T : Set. + Parameter x : T. + End SIG. - Definition x := 0. +.. _example_filter_module: - Definition y : bool. +.. example:: Creating a new module that omits some items from an existing module - exact true. + Since :n:`SIG`, the type of the new module :n:`N`, doesn't define :n:`y` or + give the body of :n:`x`, which are not included in :n:`N`. - Defined. + .. coqtop:: all - End M. + Module N : SIG with Definition T := nat := M. + Print N.T. + Print N.x. + Fail Print N.y. - Module Type SIG. + .. reset to remove N (undo in last coqtop block doesn't seem to do that), invisibly redefine M, SIG + .. coqtop:: none reset - Parameter T : Set. + Module M. + Definition T := nat. + Definition x := 0. + Definition y : bool. + exact true. + Defined. + End M. - Parameter x : T. + Module Type SIG. + Parameter T : Set. + Parameter x : T. + End SIG. - End SIG. - -The definition of :g:`N` using the module type expression :g:`SIG` with +The following definition of :g:`N` using the module type expression :g:`SIG` with :g:`Definition T := nat` is equivalent to the following one: -.. coqtop:: all +.. todo: what is other definition referred to above? + "Module N' : SIG with Definition T := nat. End N`." is not it. - Module Type SIG'. +.. coqtop:: in + Module Type SIG'. Definition T : Set := nat. - Parameter x : T. - End SIG'. Module N : SIG' := M. @@ -1126,165 +1167,58 @@ 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 -.. coqtop:: all +.. coqtop:: in Module P <: SIG := M. - Print P.y. - -Now let us create a functor, i.e. a parametric module - .. coqtop:: all - Module Two (X Y: SIG). - - Definition T := (X.T * Y.T)%type. - - Definition x := (X.x, Y.x). - - End Two. - -and apply it to our modules and do some computations: - -.. coqtop:: all - - Module Q := Two M N. - - Eval compute in (fst Q.x + snd Q.x). - -In the end, let us define a module type with two sub-modules, sharing -some of the fields and give one of its possible implementations: - -.. coqtop:: all + Print P.y. - Module Type SIG2. +.. example:: Creating a functor (a module with parameters) - Declare Module M1 : SIG. + .. coqtop:: in - Module M2 <: SIG. + Module Two (X Y: SIG). + Definition T := (X.T * Y.T)%type. + Definition x := (X.x, Y.x). + End Two. - Definition T := M1.T. + and apply it to our modules and do some computations: - Parameter x : T. + .. coqtop:: in - End M2. - End SIG2. + Module Q := Two M N. - Module Mod <: SIG2. + .. coqtop:: all - Module M1. + Eval compute in (fst Q.x + snd Q.x). - Definition T := nat. +.. example:: A module type with two sub-modules, sharing some fields - Definition x := 1. + .. coqtop:: in - End M1. + Module Type SIG2. + Declare Module M1 : SIG. + Module M2 <: SIG. + Definition T := M1.T. + Parameter x : T. + End M2. + End SIG2. - Module M2 := M. + .. coqtop:: in - End Mod. + Module Mod <: SIG2. + Module M1. + Definition T := nat. + Definition x := 1. + End M1. + Module M2 := M. + End Mod. Notice that ``M`` is a correct body for the component ``M2`` since its ``T`` -component is equal ``nat`` and hence ``M1.T`` as specified. - -.. note:: - - #. Modules and module types can be nested components of each other. - #. One can have sections inside a module or a module type, but not a - module or a module type inside a section. - #. Commands like :cmd:`Hint` or :cmd:`Notation` can also appear inside modules and - module types. Note that in case of a module definition like: - - :: - - Module N : SIG := M. - - or:: - - Module N : SIG. … End N. - - hints and the like valid for ``N`` are not those defined in ``M`` - (or the module body) but the ones defined in ``SIG``. - - -.. _import_qualid: - -.. cmd:: Import @qualid - - If :token:`qualid` denotes a valid basic module (i.e. its module type is a - signature), makes its components available by their short names. - - .. example:: - - .. coqtop:: reset all - - Module Mod. - - Definition T:=nat. - - Check T. - - End Mod. - - Check Mod.T. - - Fail Check T. - - Import Mod. - - Check T. - - Some features defined in modules are activated only when a module is - imported. This is for instance the case of notations (see :ref:`Notations`). - - Declarations made with the ``Local`` flag are never imported by the :cmd:`Import` - command. Such declarations are only accessible through their fully - qualified name. - - .. example:: - - .. coqtop:: all - - Module A. - - Module B. - - Local Definition T := nat. - - End B. - - End A. - - Import A. - - Fail Check B.T. - - .. cmdv:: Export @qualid - :name: Export - - When the module containing the command ``Export`` qualid - is imported, qualid is imported as well. - - .. exn:: @qualid is not a module. - :undocumented: - - .. warn:: Trying to mask the absolute name @qualid! - :undocumented: - -.. cmd:: Print Module @ident - - Prints the module type and (optionally) the body of the module :token:`ident`. - -.. cmd:: Print Module Type @ident - - Prints the module type corresponding to :token:`ident`. - -.. flag:: Short Module Printing - - This flag (off by default) disables the printing of the types of fields, - leaving only their names, for the commands :cmd:`Print Module` and - :cmd:`Print Module Type`. +component is ``nat`` as specified for ``M1.T``. Libraries and qualified names --------------------------------- @@ -1347,7 +1281,7 @@ also each time a new declaration is added to the context. An absolute name is called visible from a given short or partially qualified name when this latter name is enough to denote it. This means that the short or partially qualified name is mapped to the absolute name in -|Coq| name table. Definitions flagged as Local are only accessible with +|Coq| name table. Definitions with the :attr:`local` attribute are only accessible with their fully qualified name (see :ref:`gallina-definitions`). It may happen that a visible name is hidden by the short name or a @@ -1414,7 +1348,7 @@ 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`` +similar to the :cmd:`Import` command. For instance, ``-R path Lib`` associates to the file ``/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 @@ -1603,6 +1537,12 @@ this, *a priori* and *a posteriori*. Implicit Argument Binders +++++++++++++++++++++++++ +.. insertprodn implicit_binders implicit_binders + +.. prodn:: + implicit_binders ::= %{ {+ @name } {? : @type } %} + | [ {+ @name } {? : @type } ] + In the first setting, one wants to explicitly give the implicit arguments of a declared object as part of its definition. To do this, one has to surround the bindings of implicit arguments by curly @@ -1696,48 +1636,79 @@ Declaring Implicit Arguments -.. cmd:: Arguments @qualid {* {| [ @name ] | { @name } | @name } } - :name: Arguments (implicits) - - This command is used to set implicit arguments *a posteriori*, - where the list of possibly bracketed :token:`name` is a prefix of the list of - arguments of :token:`qualid` where the ones to be declared implicit are - surrounded by square brackets and the ones to be declared as maximally - inserted implicits are surrounded by curly braces. - - After the above declaration is issued, implicit arguments can just - (and have to) be skipped in any expression involving an application - of :token:`qualid`. - -.. cmd:: Arguments @qualid : clear implicits - :name: Arguments (clear implicits) - - This command clears implicit arguments. - -.. cmdv:: Global Arguments @qualid {* {| [ @name ] | { @name } | @name } } - - This command is used to recompute the implicit arguments of - :token:`qualid` after ending of the current section if any, enforcing the - implicit arguments known from inside the section to be the ones - declared by the command. - -.. cmdv:: Local Arguments @qualid {* {| [ @name ] | { @name } | @name } } - - When in a module, tell not to activate the - implicit arguments of :token:`qualid` declared by this command to contexts that - require the module. - -.. cmdv:: {? {| Global | Local } } Arguments @qualid {*, {+ {| [ @name ] | { @name } | @name } } } +.. cmd:: Arguments @smart_qualid {* @argument_spec_block } {* , {* @more_implicits_block } } {? : {+, @arguments_modifier } } + :name: Arguments + + .. insertprodn smart_qualid arguments_modifier + + .. prodn:: + smart_qualid ::= @qualid + | @by_notation + by_notation ::= @string {? % @ident } + argument_spec_block ::= @argument_spec + | / + | & + | ( {+ @argument_spec } ) {? % @ident } + | [ {+ @argument_spec } ] {? % @ident } + | %{ {+ @argument_spec } %} {? % @ident } + argument_spec ::= {? ! } @name {? % @ident } + more_implicits_block ::= @name + | [ {+ @name } ] + | %{ {+ @name } %} + arguments_modifier ::= simpl nomatch + | simpl never + | default implicits + | clear bidirectionality hint + | clear implicits + | clear scopes + | clear scopes and implicits + | clear implicits and scopes + | rename + | assert + | extra scopes + + This command sets implicit arguments *a posteriori*, + where the list of :n:`@name`\s is a prefix of the list of + arguments of :n:`@smart_qualid`. Arguments in square + brackets are declared as implicit and arguments in curly brackets are declared as + maximally inserted. + + After the command is issued, implicit arguments can and must be + omitted in any expression that applies :token:`qualid`. + + This command supports the :attr:`local` and :attr:`global` attributes. + Default behavior is to limit the effect to the current section but also to + extend their effect outside the current module or library file. + Applying :attr:`local` limits the effect of the command to the current module if + it's not in a section. Applying :attr:`global` within a section extends the + effect outside the current sections and current module if the command occurs. + + A command containing :n:`@argument_spec_block & @argument_spec_block` + provides :ref:`bidirectionality_hints`. + + Use the :n:`@more_implicits_block` to specify multiple implicit arguments declarations + for names of constants, inductive types, constructors and lemmas that can only be + applied to a fixed number of arguments (excluding, for instance, + constants whose type is polymorphic). + The longest applicable list of implicit arguments will be used to select which + implicit arguments are inserted. + For printing, the omitted arguments are the ones of the longest list of implicit + arguments of the sequence. See the example :ref:`here<example_more_implicits>`. + + The :n:`@arguments_modifier` values have various effects: + + * :n:`clear implicits` - clears implicit arguments + * :n:`default implicits` - automatically determine the implicit arguments of the object. + See :ref:`auto_decl_implicit_args`. + * :n:`rename` - rename implicit arguments for the object + * :n:`assert` - assert that the object has the expected number of arguments with the + expected names. See the example here: :ref:`renaming_implicit_arguments`. + +.. exn:: The / modifier may only occur once. + :undocumented: - For names of constants, inductive types, - constructors, lemmas which can only be applied to a fixed number of - arguments (this excludes for instance constants whose type is - polymorphic), multiple implicit arguments declarations can be given. - Depending on the number of arguments qualid is applied to in practice, - the longest applicable list of implicit arguments is used to select - which implicit arguments are inserted. For printing, the omitted - arguments are the ones of the longest list of implicit arguments of - the sequence. +.. exn:: The & modifier may only occur once. + :undocumented: .. example:: @@ -1767,40 +1738,34 @@ Declaring Implicit Arguments Check (fun l:list (list nat) => map length l). +.. _example_more_implicits: + +.. example:: Multiple implicit arguments with :n:`@more_implicits_block` + + .. coqtop:: all + Arguments map [A B] f l, [A] B f l, A B f l. Check (fun l => map length l = map (list nat) nat length l). .. note:: - To know which are the implicit arguments of an object, use the - command :cmd:`Print Implicit` (see :ref:`displaying-implicit-args`). + Use the :cmd:`Print Implicit` command to see the implicit arguments + of an object (see :ref:`displaying-implicit-args`). + +.. _auto_decl_implicit_args: Automatic declaration of implicit arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. cmd:: Arguments @qualid : default implicits - :name: Arguments (default implicits) + The :n:`default implicits @arguments_modifier` clause tells |Coq| to automatically determine the + implicit arguments of the object. - This command tells |Coq| to automatically detect what are the implicit arguments of a - defined object. - - The auto-detection is governed by flags telling if strict, + Auto-detection is governed by flags specifying whether strict, contextual, or reversible-pattern implicit arguments must be - considered or not (see :ref:`controlling-strict-implicit-args`, :ref:`controlling-strict-implicit-args`, - :ref:`controlling-rev-pattern-implicit-args`, and also :ref:`controlling-insertion-implicit-args`). - - .. cmdv:: Global Arguments @qualid : default implicits + considered or not (see :ref:`controlling-strict-implicit-args`, :ref:`controlling-contextual-implicit-args`, + :ref:`controlling-rev-pattern-implicit-args` and also :ref:`controlling-insertion-implicit-args`). - Tell to recompute the - implicit arguments of qualid after ending of the current section if - any. - - .. cmdv:: Local Arguments @qualid : default implicits - - When in a module, tell not to activate the implicit arguments of :token:`qualid` computed by this - declaration to contexts that requires the module. - -.. example:: +.. example:: Default implicits .. coqtop:: reset all @@ -1957,21 +1922,12 @@ the hiding of implicit arguments for a single function application using the Check (p (x:=a) (y:=b) r1 (z:=c) r2). +.. _renaming_implicit_arguments: + Renaming implicit arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. cmd:: Arguments @qualid {* @name} : rename - :name: Arguments (rename) - - This command is used to redefine the names of implicit arguments. - -.. cmd:: Arguments @qualid {* @name} : assert - :name: Arguments (assert) - - This command is used to assert that a given object has the expected - number of arguments and that these arguments are named as expected. - -.. example:: (continued) +.. example:: (continued) Renaming implicit arguments .. coqtop:: all @@ -1985,27 +1941,27 @@ Renaming implicit arguments .. _displaying-implicit-args: -Displaying what the implicit arguments are -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Displaying implicit arguments +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. cmd:: Print Implicit @qualid +.. cmd:: Print Implicit @smart_qualid - Use this command to display the implicit arguments associated to an object, - and to know if each of them is to be used maximally or not. + Displays the implicit arguments associated with an object, + identifying which arguments are applied maximally or not. -Explicit displaying of implicit arguments for pretty-printing -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Displaying implicit arguments when pretty-printing +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. flag:: Printing Implicit - By default, the basic pretty-printing rules hide the inferable implicit + By default, the basic pretty-printing rules hide the inferrable implicit arguments of an application. Turn this flag on to force printing all implicit arguments. .. flag:: Printing Implicit Defensive - By default, the basic pretty-printing rules display the implicit + By default, the basic pretty-printing rules display implicit arguments that are not detected as strict implicit arguments. This “defensive” mode can quickly make the display cumbersome so this can be deactivated by turning this flag off. @@ -2055,15 +2011,19 @@ applied to an unknown structure instance (an implicit argument) and a value. The complete documentation of canonical structures can be found in :ref:`canonicalstructures`; here only a simple example is given. -.. cmd:: Canonical {? Structure } @qualid - :name: Canonical Structure +.. cmd:: Canonical {? Structure } @smart_qualid + Canonical {? Structure } @ident_decl @def_body + :name: Canonical Structure; _ + + The first form of this command declares an existing :n:`@smart_qualid` as a + canonical instance of a structure (a record). - This command declares :token:`qualid` as a canonical instance of a - structure (a record). + The second form defines a new constant as if the :cmd:`Definition` command + had been used, then declares it as a canonical instance as if the first + form had been used on the defined object. This command supports the :attr:`local` attribute. When used, the - structure stops being a canonical instance at the end of the - :cmd:`Section` containing it. + structure is canonical only within the :cmd:`Section` containing it. 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|. @@ -2129,18 +2089,13 @@ in :ref:`canonicalstructures`; here only a simple example is given. See :ref:`canonicalstructures` for a more realistic example. - .. cmdv:: Canonical {? Structure } @ident {? : @type } := @term - - This is equivalent to a regular definition of :token:`ident` followed by the - declaration :n:`Canonical @ident`. - .. attr:: canonical This attribute can decorate a :cmd:`Definition` or :cmd:`Let` command. It is equivalent to having a :cmd:`Canonical Structure` declaration just after the command. -.. cmd:: Print Canonical Projections {* @ident} +.. cmd:: Print Canonical Projections {* @smart_qualid } This displays the list of global names that are components of some canonical structure. For each of them, the canonical structure of @@ -2173,13 +2128,21 @@ It is possible to bind variable names to a given type (e.g. in a development using arithmetic, it may be convenient to bind the names :g:`n` or :g:`m` to the type :g:`nat` of natural numbers). -.. cmd:: Implicit Types {+ @ident } : @type +.. cmd:: Implicit {| Type | Types } @reserv_list + :name: Implicit Type; Implicit Types + + .. insertprodn reserv_list simple_reserv + + .. prodn:: + reserv_list ::= {+ ( @simple_reserv ) } + | @simple_reserv + simple_reserv ::= {+ @ident } : @type - The effect of the command is to automatically set the type of bound + Sets the type of bound variables starting with :token:`ident` (either :token:`ident` itself or :token:`ident` followed by one or more single quotes, underscore or - digits) to be :token:`type` (unless the bound variable is already declared - with an explicit type in which case, this latter type is considered). + digits) to :token:`type` (unless the bound variable is already declared + with an explicit type, in which case, that type will be used). .. example:: @@ -2195,14 +2158,6 @@ or :g:`m` to the type :g:`nat` of natural numbers). Lemma cons_inj_bool : forall (m n:bool) l, n :: l = m :: l -> n = m. Abort. -.. cmdv:: Implicit Type @ident : @type - - This is useful for declaring the implicit type of a single variable. - -.. cmdv:: Implicit Types {+ ( {+ @ident } : @type ) } - - Adds blocks of implicit types with different specifications. - .. flag:: Printing Use Implicit Types By default, the type of bound variables is not printed when @@ -2222,9 +2177,21 @@ Implicit generalization .. index:: `[! ] .. index:: `(! ) +.. insertprodn generalizing_binder typeclass_constraint + +.. prodn:: + generalizing_binder ::= `( {+, @typeclass_constraint } ) + | `%{ {+, @typeclass_constraint } %} + | `[ {+, @typeclass_constraint } ] + typeclass_constraint ::= {? ! } @term + | %{ @name %} : {? ! } @term + | @name : {? ! } @term + + Implicit generalization is an automatic elaboration of a statement with free variables into a closed statement where these variables are -quantified explicitly. +quantified explicitly. Use the :cmd:`Generalizable` command to designate +which variables should be generalized. It is activated for a binder by prefixing a \`, and for terms by surrounding it with \`{ }, or \`[ ] or \`( ). @@ -2286,31 +2253,26 @@ Multiple binders can be merged using ``,`` as a separator: Check (forall `{Commutative A, Hnat : !Commutative nat}, True). -One can control the set of generalizable identifiers with -the ``Generalizable`` vernacular command to avoid unexpected -generalizations when mistyping identifiers. There are several commands -that specify which variables should be generalizable. - -.. cmd:: Generalizable All Variables - - All variables are candidate for - generalization if they appear free in the context under a - generalization delimiter. This may result in confusing errors in case - of typos. In such cases, the context will probably contain some - unexpected generalized variable. +.. cmd:: Generalizable {| {| Variable | Variables } {+ @ident } | All Variables | No Variables } -.. cmd:: Generalizable No Variables + Controls the set of generalizable identifiers. By default, no variables are + generalizable. - Disable implicit generalization entirely. This is the default behavior. + This command supports the :attr:`global` attribute. -.. cmd:: Generalizable {| Variable | Variables } {+ @ident } + The :n:`{| Variable | Variables } {+ @ident }` form allows generalization of only the given :n:`@ident`\s. + Using this command multiple times adds to the allowed identifiers. The other forms clear + the list of :n:`@ident`\s. - Allow generalization of the given identifiers only. Calling this command multiple times - adds to the allowed identifiers. + The :n:`All Variables` form generalizes all free variables in + the context that appear under a + generalization delimiter. This may result in confusing errors in case + of typos. In such cases, the context will probably contain some + unexpected generalized variables. -.. cmd:: Global Generalizable + The :n:`No Variables` form disables implicit generalization entirely. This is + the default behavior (before any :cmd:`Generalizable` command has been entered). - Allows exporting the choice of generalizable variables. .. _Coercions: @@ -2322,7 +2284,7 @@ which they reside into another one. A *class* is either a sort (denoted by the keyword ``Sortclass``), a product type (denoted by the keyword ``Funclass``), or a type constructor (denoted by its name), e.g. an inductive type or any constant with a type of the form -``forall (`` |x_1| : |A_1| ) … ``(``\ |x_n| : |A_n|\ ``)``, `s` where `s` is a sort. +:n:`forall {+ @binder }, @sort`. Then the user is able to apply an object that is not a function, but can be coerced to a function, and more generally to consider that a @@ -2364,43 +2326,36 @@ Printing universes terms apparently identical but internally different in the Calculus of Inductive Constructions. -.. cmd:: Print {? Sorted} Universes +.. cmd:: Print {? Sorted } Universes {? Subgraph ( {* @qualid } ) } {? @string } :name: Print Universes This command can be used to print the constraints on the internal level of the occurrences of :math:`\Type` (see :ref:`Sorts`). - If the ``Sorted`` keyword is present, each universe will be made + The :n:`Subgraph` clause limits the printed graph to the requested names (adjusting + constraints to preserve the implied transitive constraints between + kept universes). + + The :n:`Sorted` clause makes each universe equivalent to a numbered label reflecting its level (with a linear ordering) in the universe hierarchy. - .. cmdv:: Print {? Sorted} Universes @string - - This variant accepts an optional output filename. - - If :token:`string` ends in ``.dot`` or ``.gv``, the constraints are printed in the DOT - language, and can be processed by Graphviz tools. The format is - unspecified if `string` doesn’t end in ``.dot`` or ``.gv``. - -.. cmdv:: Print Universes Subgraph({+ @qualid }) - :name: Print Universes Subgraph - - Prints the graph restricted to the requested names (adjusting - constraints to preserve the implied transitive constraints between - kept universes). + :n:`@string` is an optional output filename. + If :n:`@string` ends in ``.dot`` or ``.gv``, the constraints are printed in the DOT + language, and can be processed by Graphviz tools. The format is + unspecified if `string` doesn’t end in ``.dot`` or ``.gv``. .. _existential-variables: Existential variables --------------------- -.. insertprodn term_evar evar_binding +.. insertprodn term_evar term_evar .. prodn:: term_evar ::= ?[ @ident ] | ?[ ?@ident ] - | ?@ident {? @%{ {+; @evar_binding } %} } - evar_binding ::= @ident := @term + | ?@ident {? @%{ {+; @ident := @term } %} } |Coq| terms can include existential variables which represents unknown subterms to eventually be replaced by actual subterms. @@ -2592,6 +2547,8 @@ values (of type :g:`float`) written in hexadecimal notation and wrapped into the :g:`Float64.of_float` constructor, e.g.: :g:`Float64.of_float (0x1p+0)`. +.. _bidirectionality_hints: + Bidirectionality hints ---------------------- @@ -2602,15 +2559,14 @@ Bidirectionality hints make it possible to specify that after type-checking the first arguments of an application, typing information should be propagated from the context to help inferring the types of the remaining arguments. -.. cmd:: Arguments @qualid {* @ident__1 } & {* @ident__2} - :name: Arguments (bidirectionality hints) - - This commands tells the typechecking algorithm, when type-checking - applications of :n:`@qualid`, to first type-check the arguments in - :n:`@ident__1` and then propagate information from the typing context to - type-check the remaining arguments (in :n:`@ident__2`). +An :cmd:`Arguments` command containing :n:`@argument_spec_block__1 & @argument_spec_block__2` +provides :ref:`bidirectionality_hints`. +It tells the typechecking algorithm, when type-checking +applications of :n:`@qualid`, to first type-check the arguments in +:n:`@argument_spec_block__1` and then propagate information from the typing context to +type-check the remaining arguments (in :n:`@argument_spec_block__2`). -.. example:: +.. example:: Bidirectionality hints In a context where a coercion was declared from ``bool`` to ``nat``: diff --git a/doc/sphinx/language/gallina-specification-language.rst b/doc/sphinx/language/gallina-specification-language.rst index e710e19c12..f4592f8f37 100644 --- a/doc/sphinx/language/gallina-specification-language.rst +++ b/doc/sphinx/language/gallina-specification-language.rst @@ -117,7 +117,7 @@ Other tokens ! #[ % & ' ( () (bfs) (dfs) ) * ** + , - -> . .( .. ... / : ::= := :> :>> ; < <+ <- <: - <<: <= = => > >-> >= ? @ @{ [ [= ] _ _eqn + <<: <= = => > >-> >= ? @ @{ [ [= ] _ `( `{ { {| | |- || } When multiple tokens match the beginning of a sequence of characters, @@ -290,7 +290,7 @@ More on sorts can be found in Section :ref:`sorts`. Binders ------- -.. insertprodn open_binders typeclass_constraint +.. insertprodn open_binders binder .. prodn:: open_binders ::= {+ @name } : @term @@ -300,16 +300,10 @@ Binders binder ::= @name | ( {+ @name } : @type ) | ( @name {? : @type } := @term ) + | @implicit_binders + | @generalizing_binder | ( @name : @type %| @term ) - | %{ {+ @name } {? : @type } %} - | [ {+ @name } {? : @type } ] - | `( {+, @typeclass_constraint } ) - | `%{ {+, @typeclass_constraint } %} - | `[ {+, @typeclass_constraint } ] | ' @pattern0 - typeclass_constraint ::= {? ! } @term - | %{ @name %} : {? ! } @term - | @name : {? ! } @term Various constructions such as :g:`fun`, :g:`forall`, :g:`fix` and :g:`cofix` *bind* variables. A binding is represented by an identifier. If the binding @@ -620,6 +614,10 @@ The association of a single fixpoint and a local definition have a special syntax: :n:`let fix @ident {* @binder } := @term in` stands for :n:`let @ident := fix @ident {* @binder } := @term in`. The same applies for co-fixpoints. +Some options of :n:`@fixannot` are only supported in specific constructs. :n:`fix` and :n:`let fix` +only support the :n:`struct` option, while :n:`wf` and :n:`measure` are only supported in +commands such as :cmd:`Function` and :cmd:`Program Fixpoint`. + .. insertprodn term_cofix cofix_body .. prodn:: @@ -646,7 +644,7 @@ The Vernacular The top-level input to |Coq| is a series of :production:`command`\s and :production:`tactic`\s, each terminated with a period and optionally decorated with :ref:`gallina-attributes`. :n:`@ltac_expr` syntax supports both simple -and compound tactics. For example: ``split.`` is a simple tactic while ``split; auto.`` combines two +and compound tactics. For example: ``split`` is a simple tactic while ``split; auto`` combines two simple tactics. Tactics specify how to transform the current proof state as a step in creating a proof. They @@ -706,6 +704,8 @@ has type :n:`@type`. is closed, the :n:`@ident`\(s) become undefined and every object depending on them will be explicitly parameterized (i.e., the variables are *discharged*). See Section :ref:`section-mechanism`. + The :n:`Inline` clause is only relevant inside functors. See :cmd:`Module`. + .. example:: Simple assumptions .. coqtop:: reset in @@ -771,8 +771,8 @@ Section :ref:`typing-rules`. :attr:`universes(monomorphic)`, :attr:`program` and :attr:`canonical` attributes. - If :n:`@term` is omitted, Coq enters the proof editing mode. This can be - used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. + If :n:`@term` is omitted, :n:`@type` is required and Coq enters proof editing mode. + This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. In this case, the proof should be terminated with :cmd:`Defined` in order to define a constant for which the computational behavior is relevant. See :ref:`proof-editing-mode`. @@ -799,17 +799,13 @@ Inductive types .. cmd:: Inductive @inductive_definition {* with @inductive_definition } - .. insertprodn inductive_definition field_body + .. insertprodn inductive_definition constructor .. prodn:: inductive_definition ::= {? > } @ident_decl {* @binder } {? %| {* @binder } } {? : @type } {? := {? @constructors_or_record } } {? @decl_notations } constructors_or_record ::= {? %| } {+| @constructor } - | {? @ident } %{ {+; @record_field } %} + | {? @ident } %{ {*; @record_field } %} constructor ::= @ident {* @binder } {? @of_type } - record_field ::= {* #[ {*, @attr } ] } @name {? @field_body } {? %| @num } {? @decl_notations } - field_body ::= {* @binder } @of_type - | {* @binder } @of_type := @term - | {* @binder } := @term This command defines one or more inductive types and its constructors. Coq generates destructors @@ -866,7 +862,7 @@ mutually inductive types and private (matching) inductive types. Simple inductive types ~~~~~~~~~~~~~~~~~~~~~~ -A simple inductive type belongs to a universe that is a simple :n:`sort`. +A simple inductive type belongs to a universe that is a simple :n:`@sort`. .. example:: @@ -1156,9 +1152,14 @@ Private (matching) inductive types Variants ~~~~~~~~ -.. cmd:: Variant @inductive_definition {* with @inductive_definition } +.. cmd:: Variant @variant_definition {* with @variant_definition } + + .. insertprodn variant_definition variant_definition - The :cmd:`Variant` command is identical to the :cmd:`Inductive` command, except + .. prodn:: + variant_definition ::= @ident_decl {* @binder } {? %| {* @binder } } {? : @type } := {? %| } {+| @constructor } {? @decl_notations } + + The :cmd:`Variant` command is similar to the :cmd:`Inductive` command, except that it disallows recursive definition of types (for instance, lists cannot be defined using :cmd:`Variant`). No induction scheme is generated for this variant, unless the :flag:`Nonrecursive Elimination Schemes` flag is on. @@ -1319,7 +1320,7 @@ constructions. consequently :n:`forall {* @binder }, @type` and its value is equivalent to :n:`fun {* @binder } => @term`. - To be accepted, a :cmd:`Fixpoint` definition has to satisfy some syntactical + To be accepted, a :cmd:`Fixpoint` definition has to satisfy syntactical constraints on a special argument called the decreasing argument. They are needed to ensure that the :cmd:`Fixpoint` definition always terminates. The point of the :n:`{struct @ident}` annotation (see :n:`@fixannot`) is to @@ -1329,11 +1330,14 @@ constructions. system successively tries arguments from left to right until it finds one that satisfies the decreasing condition. + :cmd:`Fixpoint` without the :attr:`program` attribute does not support the + :n:`wf` or :n:`measure` clauses of :n:`@fixannot`. + The :n:`with` clause allows simultaneously defining several mutual fixpoints. It is especially useful when defining functions over mutually defined inductive types. Example: :ref:`Mutual Fixpoints<example_mutual_fixpoints>`. - If :n:`@term` is omitted, :n:`@type` is required and Coq enters the proof editing mode. + If :n:`@term` is omitted, :n:`@type` is required and Coq enters proof editing mode. This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. In this case, the proof should be terminated with :cmd:`Defined` in order to define a constant for which the computational behavior is relevant. See :ref:`proof-editing-mode`. @@ -1490,7 +1494,7 @@ Definitions of recursive objects in co-inductive types As in the :cmd:`Fixpoint` command, the :n:`with` clause allows simultaneously defining several mutual cofixpoints. - If :n:`@term` is omitted, :n:`@type` is required and Coq enters the proof editing mode. + If :n:`@term` is omitted, :n:`@type` is required and Coq enters proof editing mode. This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. In this case, the proof should be terminated with :cmd:`Defined` in order to define a constant for which the computational behavior is relevant. See :ref:`proof-editing-mode`. @@ -1518,9 +1522,6 @@ Computations | pattern {+, @pattern_occ } | @ident delta_flag ::= {? - } [ {+ @smart_qualid } ] - smart_qualid ::= @qualid - | @by_notation - by_notation ::= @string {? % @ident } strategy_flag ::= {+ @red_flags } | @delta_flag red_flags ::= beta @@ -1532,10 +1533,8 @@ Computations | delta {? @delta_flag } ref_or_pattern_occ ::= @smart_qualid {? at @occs_nums } | @one_term {? at @occs_nums } - occs_nums ::= {+ @num_or_var } - | - @num_or_var {* @int_or_var } - num_or_var ::= @num - | @ident + occs_nums ::= {+ {| @num | @ident } } + | - {| @num | @ident } {* @int_or_var } int_or_var ::= @int | @ident unfold_occ ::= @smart_qualid {? at @occs_nums } @@ -1649,12 +1648,9 @@ Attributes attr ::= @ident {? @attr_value } attr_value ::= = @string | ( {*, @attr } ) - legacy_attr ::= Local - | Global - | Polymorphic - | Monomorphic - | Cumulative - | NonCumulative + legacy_attr ::= {| Local | Global } + | {| Polymorphic | Monomorphic } + | {| Cumulative | NonCumulative } | Private | Program diff --git a/doc/sphinx/practical-tools/utilities.rst b/doc/sphinx/practical-tools/utilities.rst index e5ff26520a..d61e5ddce7 100644 --- a/doc/sphinx/practical-tools/utilities.rst +++ b/doc/sphinx/practical-tools/utilities.rst @@ -637,470 +637,6 @@ See the man page of ``coqdep`` for more details and options. Both Dune and ``coq_makefile`` use ``coqdep`` to compute the dependencies among the files part of a Coq project. -.. _coqdoc: - -Documenting |Coq| files with coqdoc ------------------------------------ - -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 |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. - - - -Principles -~~~~~~~~~~ - -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 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, -garbage out”. - - -|Coq| material inside documentation. -++++++++++++++++++++++++++++++++++++ - -|Coq| material is quoted between the delimiters ``[`` and ``]``. Square brackets -may be nested, the inner ones being understood as being part of the -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. - -Preformatted vernacular is enclosed by ``[[`` and ``]]``. The former must be -followed by a newline and the latter must follow a newline. - - -Pretty-printing. -++++++++++++++++ - -coqdoc uses different faces for identifiers and keywords. The pretty- -printing of |Coq| tokens (identifiers or symbols) can be controlled -using one of the following commands: - -:: - - - (** printing *token* %...LATEX...% #...html...# *) - - -or - -:: - - - (** printing *token* $...LATEX math...$ #...html...# *) - - -It gives the |Latex| and HTML texts to be produced for the given |Coq| -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 - -:: - - - (** remove printing *token* *) - - -Initially, the pretty-printing table contains the following mapping: - -===== === ==== ===== === ==== ==== === -`->` → `<-` ← `*` × -`<=` ≤ `>=` ≥ `=>` ⇒ -`<>` ≠ `<->` ↔ `|-` ⊢ -`\\/` ∨ `/\\` ∧ `~` ¬ -===== === ==== ===== === ==== ==== === - -Any of these can be overwritten or suppressed using the printing -commands. - -.. note:: - - The recognition of tokens is done by a (``ocaml``) lex - automaton and thus applies the longest-match rule. For instance, `->~` - is recognized as a single token, where |Coq| sees two tokens. It is the - responsibility of the user to insert space between tokens *or* to give - pretty-printing rules for the possible combinations, e.g. - - :: - - (** printing ->~ %\ensuremath{\rightarrow\lnot}% *) - - - -Sections -++++++++ - -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:: - - :: - - (** * Well-founded relations - - In this section, we introduce... *) - - -Lists. -++++++ - -List items are introduced by a leading dash. coqdoc uses whitespace to -determine the depth of a new list item and which text belongs in which -list items. A list ends when a line of text starts at or before the -level of indenting of the list’s dash. A list item’s dash must always -be the first non-space character on its line (so, in particular, a -list can not begin on the first line of a comment - start it on the -second line instead). - -.. example:: - - :: - - We go by induction on [n]: - - If [n] is 0... - - If [n] is [S n'] we require... - - two paragraphs of reasoning, and two subcases: - - - In the first case... - - In the second case... - - So the theorem holds. - - - -Rules. -++++++ - -More than 4 leading dashes produce a horizontal rule. - - -Emphasis. -+++++++++ - -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. - -:: - - This sentence contains some _emphasized text_. - - - -Escaping to |Latex| and HTML. -+++++++++++++++++++++++++++++++ - -Pure |Latex| or HTML material can be inserted using the following -escape sequences: - - -+ ``$...LATEX stuff...$`` inserts some |Latex| material in math mode. - Simply discarded in HTML output. -+ ``%...LATEX stuff...%`` inserts some |Latex| material. Simply - discarded in HTML output. -+ ``#...HTML stuff...#`` inserts some HTML material. Simply discarded in - |Latex| output. - -.. note:: - to simply output the characters ``$``, ``%`` and ``#`` and escaping - their escaping role, these characters must be doubled. - - -Verbatim -++++++++ - -Verbatim material is introduced by a leading ``<<`` and closed by ``>>`` -at the beginning of a line. - -.. example:: - - :: - - Here is the corresponding caml code: - << - let rec fact n = - if n <= 1 then 1 else n * fact (n-1) - >> - - - -Hyperlinks -++++++++++ - -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 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 in the file ``file`` (it will look in ``file.glob`` -by default). - -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. - - -Hiding / Showing parts of the source. -+++++++++++++++++++++++++++++++++++++ - -Some parts of the source can be hidden using command line options ``-g`` -and ``-l`` (see below), or using such comments: - -:: - - - (* begin hide *) - *some Coq material* - (* end hide *) - - -Conversely, some parts of the source which would be hidden can be -shown using such comments: - -:: - - - (* begin show *) - *some Coq material* - (* end show *) - - -The latter cannot be used around some inner parts of a proof, but can -be used around a whole proof. - - -Usage -~~~~~ - -coqdoc is invoked on a shell command line as follows: -``coqdoc <options and files>``. -Any command line argument which is not an option is considered to be a -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 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 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 - options ``-dvi`` and ``-ps`` respectively. -:TEXmacs output: To translate the input files to TEXmacs format, - to be used by the TEXmacs |Coq| interface. - - - -Command line options -++++++++++++++++++++ - - -**Overall options** - - - :--HTML: Select a HTML output. - :--|Latex|: Select a |Latex| output. - :--dvi: Select a DVI output. - :--ps: Select a PostScript output. - :--texmacs: Select a TEXmacs output. - :--stdout: Write output to stdout. - :-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 - 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 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. - :-h, --help: Give a short summary of the options and exit. - :-v, --version: Print the version and exit. - - - -**Index options** - - The default behavior is to build an index, for the HTML output only, - into ``index.html``. - - :--no-index: Do not output the index. - :--multi-index: Generate one page for each category and each letter in - the index, together with a top page ``index.html``. - :--index string: Make the filename of the index string instead of - “index”. Useful since “index.html” is special. - - - -**Table of contents option** - - :-toc, --table-of-contents: Insert a table of contents. For a |Latex| - output, it inserts a ``\tableofcontents`` at the beginning of the - document. For a HTML output, it builds a table of contents into - ``toc.html``. - :--toc-depth int: Only include headers up to depth ``int`` in the table of - contents. - - -**Hyperlink options** - - :--glob-from file: Make references using |Coq| globalizations from file - file. (Such globalizations are obtained with Coq option ``-dump-glob``). - :--no-externals: Do not insert links to the |Coq| standard library. - :--external url coqdir: Use given URL for linking references whose - name starts with prefix ``coqdir``. - :--coqlib url: Set base URL for the Coq standard library (default is - `<http://coq.inria.fr/library/>`_). This is equivalent to ``--external url - Coq``. - :-R dir coqdir: Recursively map physical directory dir to |Coq| logical - directory ``coqdir`` (similarly to |Coq| option ``-R``). - :-Q dir coqdir: Map physical directory dir to |Coq| logical - directory ``coqdir`` (similarly to |Coq| option ``-Q``). - - .. note:: - - options ``-R`` and ``-Q`` only have - effect on the files *following* them on the command line, so you will - probably need to put this option first. - - -**Title options** - - :-s , --short: Do not insert titles for the files. The default - behavior is to insert a title like “Library Foo” for each file. - :--lib-name string: Print “string Foo” instead of “Library Foo” in - titles. For example “Chapter” and “Module” are reasonable choices. - :--no-lib-name: Print just “Foo” instead of “Library Foo” in titles. - :--lib-subtitles: Look for library subtitles. When enabled, the - beginning of each file is checked for a comment of the form: - - :: - - (** * ModuleName : text *) - - where ``ModuleName`` must be the name of the file. If it is present, the - text is used as a subtitle for the module in appropriate places. - :-t string, --title string: Set the document title. - - -**Contents options** - - :-g, --gallina: Do not print proofs. - :-l, --light: Light mode. Suppress proofs (as with ``-g``) and the following commands: - - + [Recursive] Tactic Definition - + Hint / Hints - + Require - + Transparent / Opaque - + Implicit Argument / Implicits - + Section / Variable / Hypothesis / End - - - - 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 that control the parsing of comments: - - :--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. - :--interpolate: Use the globalization information to typeset - identifiers appearing in |Coq| escapings inside comments. - -**Language options** - - - 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. - :-utf8, --utf8: Set --inputenc utf8x for |Latex| output and--charset - utf-8 for HTML output. Also use Unicode replacements for a couple of - standard plain ASCII notations such as → for ``->`` and ∀ for ``forall``. |Latex| - UTF-8 support can be found - at `<http://www.ctan.org/pkg/unicode>`_. For the interpretation of Unicode - characters by |Latex|, extra packages which coqdoc does not provide - by default might be required, such as textgreek for some Greek letters - or ``stmaryrd`` for some mathematical symbols. If a Unicode character is - missing an interpretation in the utf8x input encoding, add - ``\DeclareUnicodeCharacter{code}{LATEX-interpretation}``. Packages - and declarations can be added with option ``-p``. - :--inputenc string: Give a |Latex| input encoding, as an option to |Latex| - package ``inputenc``. - :--charset string: Specify the HTML character set, to be inserted in - the HTML header. - - - -The coqdoc |Latex| style file -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In case you choose to produce a document without the default |Latex| -preamble (by using option ``--no-preamble``), then you must insert into -your own preamble the command - -:: - - \usepackage{coqdoc} - -The package optionally takes the argument ``[color]`` to typeset -identifiers with colors (this requires the ``xcolor`` package). - -Then you may alter the rendering of the document by redefining some -macros: - -:coqdockw, coqdocid, …: The one-argument macros for typesetting - keywords and identifiers. Defaults are sans-serif for keywords and - italic for identifiers.For example, if you would like a slanted font - for keywords, you may insert - - :: - - \renewcommand{\coqdockw}[1]{\textsl{#1}} - - - anywhere between ``\usepackage{coqdoc}`` and ``\begin{document}``. - - -:coqdocmodule: - One-argument macro for typesetting the title of a ``.v`` - file. Default is - - :: - - \newcommand{\coqdocmodule}[1]{\section*{Module #1}} - - and you may redefine it using ``\renewcommand``. - Embedded Coq phrases inside |Latex| documents --------------------------------------------- diff --git a/doc/sphinx/proof-engine/tactics.rst b/doc/sphinx/proof-engine/tactics.rst index d498c1ee2c..19573eee43 100644 --- a/doc/sphinx/proof-engine/tactics.rst +++ b/doc/sphinx/proof-engine/tactics.rst @@ -3222,7 +3222,7 @@ 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 argument list of the :cmd:`Arguments <Arguments (implicits)>` vernacular command. + ``/`` symbol in the argument list of the :cmd:`Arguments` command. .. example:: diff --git a/doc/sphinx/proof-engine/vernacular-commands.rst b/doc/sphinx/proof-engine/vernacular-commands.rst index 895886605d..b22c5286fe 100644 --- a/doc/sphinx/proof-engine/vernacular-commands.rst +++ b/doc/sphinx/proof-engine/vernacular-commands.rst @@ -321,18 +321,6 @@ Requests to the environment Search (?x * _ + ?x * _)%Z outside OmegaLemmas. - .. cmdv:: SearchAbout - :name: SearchAbout - - .. deprecated:: 8.5 - - Up to |Coq| version 8.4, :cmd:`Search` had the behavior of current - :cmd:`SearchHead` and the behavior of current :cmd:`Search` was obtained with - command :cmd:`SearchAbout`. For compatibility, the deprecated name - :cmd:`SearchAbout` can still be used as a synonym of :cmd:`Search`. For - compatibility, the list of objects to search when using :cmd:`SearchAbout` - may also be enclosed by optional ``[ ]`` delimiters. - .. cmd:: SearchHead @term @@ -608,11 +596,11 @@ file is a particular case of module called *library file*. This loads and declares the module :n:`@qualid` and its dependencies then imports the contents of :n:`@qualid` as described - :ref:`here <import_qualid>`. It does not import the modules on which - qualid depends unless these modules were themselves required in module + for :cmd:`Import`. It does not import the modules that + :n:`@qualid` depends on unless these modules were themselves required in module :n:`@qualid` - using :cmd:`Require Export`, as described below, or recursively required - through a sequence of :cmd:`Require Export`. If the module required has + using :cmd:`Require Export`, or recursively required + through a series of :cmd:`Require Export`. If the module required has already been loaded, :cmd:`Require Import` :n:`@qualid` simply imports it, as :cmd:`Import` :n:`@qualid` would. @@ -671,13 +659,9 @@ file is a particular case of module called *library file*. the time it was compiled. - .. exn:: Require is not allowed inside a module or a module type. + .. warn:: Require inside a module is deprecated and strongly discouraged. You can Require a module at toplevel and optionally Import it inside another one. - This command - is not allowed inside a module or a module type being defined. It is - meant to describe a dependency between compilation units. Note however - that the commands ``Import`` and ``Export`` alone can be used inside modules - (see Section :ref:`Import <import_qualid>`). + Note that the :cmd:`Import` and :cmd:`Export` commands can be used inside modules. .. seealso:: Chapter :ref:`thecoqcommands` @@ -933,16 +917,17 @@ Quitting and debugging .. cmd:: Fail @command - For debugging scripts, sometimes it is desirable to know - whether a command or a tactic fails. If the given :n:`@command` - fails, the ``Fail`` statement succeeds, without changing the proof - state, and in interactive mode, the system - prints a message confirming the failure. - If the given :n:`@command` succeeds, the statement is an error, and - it prints a message indicating that the failure did not occur. + For debugging scripts, sometimes it is desirable to know whether a + command or a tactic fails. If the given :n:`@command` fails, then + :n:`Fail @command` succeeds (excepts in the case of + critical errors, like a "stack overflow"), without changing the + proof state, and in interactive mode, the system prints a message + confirming the failure. .. exn:: The command has not failed! - :undocumented: + + If the given :n:`@command` succeeds, then :n:`Fail @command` + fails with this error message. .. _controlling-display: @@ -1178,7 +1163,7 @@ Controlling the locality of commands effect of the command to the current module if the command does not occur in a section and the :attr:`global` attribute extends the effect outside the current sections and current module if the command occurs in a section. As an example, - the :cmd:`Arguments <Arguments (implicits)>`, :cmd:`Ltac` or :cmd:`Notation` commands belong + the :cmd:`Arguments`, :cmd:`Ltac` or :cmd:`Notation` commands belong to this category. Notice that a subclass of these commands do not support extension of their scope outside sections at all and the :attr:`global` attribute is not applicable to them. diff --git a/doc/sphinx/refman-preamble.rst b/doc/sphinx/refman-preamble.rst index de95eda989..05e665a43b 100644 --- a/doc/sphinx/refman-preamble.rst +++ b/doc/sphinx/refman-preamble.rst @@ -11,60 +11,18 @@ .. role:: smallcaps -.. |A_1| replace:: `A`\ :math:`_{1}` -.. |A_n| replace:: `A`\ :math:`_{n}` -.. |arg_1| replace:: `arg`\ :math:`_{1}` -.. |arg_n| replace:: `arg`\ :math:`_{n}` -.. |bdi| replace:: :math:`\beta\delta\iota` -.. |binder_1| replace:: `binder`\ :math:`_{1}` -.. |binder_n| replace:: `binder`\ :math:`_{n}` -.. |binders_1| replace:: `binders`\ :math:`_{1}` -.. |binders_n| replace:: `binders`\ :math:`_{n}` -.. |C_1| replace:: `C`\ :math:`_{1}` .. |c_1| replace:: `c`\ :math:`_{1}` -.. |C_2| replace:: `C`\ :math:`_{2}` .. |c_i| replace:: `c`\ :math:`_{i}` .. |c_n| replace:: `c`\ :math:`_{n}` -.. |Cic| replace:: :smallcaps:`Cic` -.. |class_1| replace:: `class`\ :math:`_{1}` -.. |class_2| replace:: `class`\ :math:`_{2}` +.. |Cic| replace:: CIC .. |Coq| replace:: :smallcaps:`Coq` .. |CoqIDE| replace:: :smallcaps:`CoqIDE` .. |eq_beta_delta_iota_zeta| replace:: `=`\ :math:`_{\beta\delta\iota\zeta}` .. |Gallina| replace:: :smallcaps:`Gallina` -.. |ident_0| replace:: `ident`\ :math:`_{0}` -.. |ident_1,1| replace:: `ident`\ :math:`_{1,1}` -.. |ident_1,k_1| replace:: `ident`\ :math:`_{1,k_1}`) -.. |ident_1| replace:: `ident`\ :math:`_{1}` -.. |ident_2| replace:: `ident`\ :math:`_{2}` -.. |ident_3| replace:: `ident`\ :math:`_{3}` -.. |ident_i| replace:: `ident`\ :math:`_{i}` -.. |ident_j| replace:: `ident`\ :math:`_{j}` -.. |ident_k| replace:: `ident`\ :math:`_{k}` -.. |ident_n,1| replace:: `ident`\ :math:`_{n,1}` -.. |ident_n,k_n| replace:: `ident`\ :math:`_{n,k_n}` -.. |ident_n| replace:: `ident`\ :math:`_{n}` .. |Latex| replace:: :smallcaps:`LaTeX` .. |L_tac| replace:: `L`:sub:`tac` .. |Ltac| replace:: `L`:sub:`tac` .. |ML| replace:: :smallcaps:`ML` -.. |mod_0| replace:: `mod`\ :math:`_{0}` -.. |mod_1| replace:: `mod`\ :math:`_{1}` -.. |mod_2| replace:: `mod`\ :math:`_{1}` -.. |mod_n| replace:: `mod`\ :math:`_{n}` -.. |module_0| replace:: `module`\ :math:`_{0}` -.. |module_1| replace:: `module`\ :math:`_{1}` -.. |module_expression_0| replace:: `module_expression`\ :math:`_{0}` -.. |module_expression_1| replace:: `module_expression`\ :math:`_{1}` -.. |module_expression_i| replace:: `module_expression`\ :math:`_{i}` -.. |module_expression_n| replace:: `module_expression`\ :math:`_{n}` -.. |module_n| replace:: `module`\ :math:`_{n}` -.. |module_type_0| replace:: `module_type`\ :math:`_{0}` -.. |module_type_1| replace:: `module_type`\ :math:`_{1}` -.. |module_type_i| replace:: `module_type`\ :math:`_{i}` -.. |module_type_n| replace:: `module_type`\ :math:`_{n}` -.. |N| replace:: ``N`` -.. |nat| replace:: ``nat`` .. |OCaml| replace:: :smallcaps:`OCaml` .. |p_1| replace:: `p`\ :math:`_{1}` .. |p_i| replace:: `p`\ :math:`_{i}` @@ -79,24 +37,6 @@ .. |t_i| replace:: `t`\ :math:`_{i}` .. |t_m| replace:: `t`\ :math:`_{m}` .. |t_n| replace:: `t`\ :math:`_{n}` -.. |f_1| replace:: `f`\ :math:`_{1}` -.. |f_i| replace:: `f`\ :math:`_{i}` -.. |f_m| replace:: `f`\ :math:`_{m}` -.. |f_n| replace:: `f`\ :math:`_{n}` -.. |u_1| replace:: `u`\ :math:`_{1}` -.. |u_i| replace:: `u`\ :math:`_{i}` -.. |u_m| replace:: `u`\ :math:`_{m}` -.. |u_n| replace:: `u`\ :math:`_{n}` -.. |term_0| replace:: `term`\ :math:`_{0}` -.. |term_1| replace:: `term`\ :math:`_{1}` -.. |term_2| replace:: `term`\ :math:`_{2}` -.. |term_n| replace:: `term`\ :math:`_{n}` -.. |type_0| replace:: `type`\ :math:`_{0}` -.. |type_1| replace:: `type`\ :math:`_{1}` -.. |type_2| replace:: `type`\ :math:`_{2}` -.. |type_3| replace:: `type`\ :math:`_{3}` -.. |type_n| replace:: `type`\ :math:`_{n}` .. |x_1| replace:: `x`\ :math:`_{1}` .. |x_i| replace:: `x`\ :math:`_{i}` .. |x_n| replace:: `x`\ :math:`_{n}` -.. |Z| replace:: ``Z`` diff --git a/doc/sphinx/refman-preamble.sty b/doc/sphinx/refman-preamble.sty index 90a63a5a2d..629c30a793 100644 --- a/doc/sphinx/refman-preamble.sty +++ b/doc/sphinx/refman-preamble.sty @@ -1,32 +1,20 @@ -\newcommand{\alors}{\textsf{then}} -\newcommand{\alter}{\textsf{alter}} \newcommand{\as}{\kw{as}} \newcommand{\Assum}[3]{\kw{Assum}(#1)(#2:#3)} -\newcommand{\bool}{\textsf{bool}} \newcommand{\case}{\kw{case}} -\newcommand{\conc}{\textsf{conc}} \newcommand{\cons}{\textsf{cons}} \newcommand{\consf}{\textsf{consf}} -\newcommand{\conshl}{\textsf{cons\_hl}} \newcommand{\Def}[4]{\kw{Def}(#1)(#2:=#3:#4)} \newcommand{\emptyf}{\textsf{emptyf}} \newcommand{\End}{\kw{End}} \newcommand{\kwend}{\kw{end}} -\newcommand{\EqSt}{\textsf{EqSt}} \newcommand{\even}{\textsf{even}} \newcommand{\evenO}{\textsf{even}_\textsf{O}} \newcommand{\evenS}{\textsf{even}_\textsf{S}} -\newcommand{\false}{\textsf{false}} -\newcommand{\filter}{\textsf{filter}} \newcommand{\Fix}{\kw{Fix}} \newcommand{\fix}{\kw{fix}} \newcommand{\for}{\textsf{for}} \newcommand{\forest}{\textsf{forest}} -\newcommand{\from}{\textsf{from}} \newcommand{\Functor}{\kw{Functor}} -\newcommand{\haslength}{\textsf{has\_length}} -\newcommand{\hd}{\textsf{hd}} -\newcommand{\ident}{\textsf{ident}} \newcommand{\In}{\kw{in}} \newcommand{\Ind}[4]{\kw{Ind}[#2](#3:=#4)} \newcommand{\ind}[3]{\kw{Ind}~[#1]\left(#2\mathrm{~:=~}#3\right)} @@ -34,7 +22,6 @@ \newcommand{\Indpstr}[6]{\kw{Ind}_{#5}(#1)[#2](#3:=#4)/{#6}} \newcommand{\injective}{\kw{injective}} \newcommand{\kw}[1]{\textsf{#1}} -\newcommand{\lb}{\lambda} \newcommand{\length}{\textsf{length}} \newcommand{\letin}[3]{\kw{let}~#1:=#2~\kw{in}~#3} \newcommand{\List}{\textsf{list}} @@ -45,7 +32,6 @@ \newcommand{\ModS}[2]{{\kw{Mod}}({#1}:{#2})} \newcommand{\ModType}[2]{{\kw{ModType}}({#1}:={#2})} \newcommand{\mto}{.\;} -\newcommand{\Nat}{\mathbb{N}} \newcommand{\nat}{\textsf{nat}} \newcommand{\Nil}{\textsf{nil}} \newcommand{\nilhl}{\textsf{nil\_hl}} @@ -57,13 +43,10 @@ \newcommand{\ovl}[1]{\overline{#1}} \newcommand{\Pair}{\textsf{pair}} \newcommand{\plus}{\mathsf{plus}} -\newcommand{\Prod}{\textsf{prod}} \newcommand{\SProp}{\textsf{SProp}} \newcommand{\Prop}{\textsf{Prop}} \newcommand{\return}{\kw{return}} \newcommand{\Set}{\textsf{Set}} -\newcommand{\si}{\textsf{if}} -\newcommand{\sinon}{\textsf{else}} \newcommand{\Sort}{\mathcal{S}} \newcommand{\Str}{\textsf{Stream}} \newcommand{\Struct}{\kw{Struct}} @@ -71,9 +54,7 @@ \newcommand{\tl}{\textsf{tl}} \newcommand{\tree}{\textsf{tree}} \newcommand{\trii}{\triangleright_\iota} -\newcommand{\true}{\textsf{true}} \newcommand{\Type}{\textsf{Type}} -\newcommand{\unfold}{\textsf{unfold}} \newcommand{\WEV}[3]{\mbox{$#1[] \vdash #2 \lra #3$}} \newcommand{\WEVT}[3]{\mbox{$#1[] \vdash #2 \lra$}\\ \mbox{$ #3$}} \newcommand{\WF}[2]{{\mathcal{W\!F}}(#1)[#2]} @@ -88,4 +69,3 @@ \newcommand{\WTEG}[2]{\WTE{\Gamma}{#1}{#2}} \newcommand{\WTM}[3]{\WT{#1}{}{#2}{#3}} \newcommand{\zeroone}[1]{[{#1}]} -\newcommand{\zeros}{\textsf{zeros}} diff --git a/doc/sphinx/using/tools/coqdoc.rst b/doc/sphinx/using/tools/coqdoc.rst new file mode 100644 index 0000000000..cada680895 --- /dev/null +++ b/doc/sphinx/using/tools/coqdoc.rst @@ -0,0 +1,463 @@ +.. _coqdoc: + +Documenting |Coq| files with coqdoc +----------------------------------- + +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 |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. + + + +Principles +~~~~~~~~~~ + +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 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, +garbage out”. + + +|Coq| material inside documentation. +++++++++++++++++++++++++++++++++++++ + +|Coq| material is quoted between the delimiters ``[`` and ``]``. Square brackets +may be nested, the inner ones being understood as being part of the +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. + +Preformatted vernacular is enclosed by ``[[`` and ``]]``. The former must be +followed by a newline and the latter must follow a newline. + + +Pretty-printing. +++++++++++++++++ + +coqdoc uses different faces for identifiers and keywords. The pretty- +printing of |Coq| tokens (identifiers or symbols) can be controlled +using one of the following commands: + +:: + + + (** printing *token* %...LATEX...% #...html...# *) + + +or + +:: + + + (** printing *token* $...LATEX math...$ #...html...# *) + + +It gives the |Latex| and HTML texts to be produced for the given |Coq| +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 + +:: + + + (** remove printing *token* *) + + +Initially, the pretty-printing table contains the following mapping: + +===== === ==== ===== === ==== ==== === +`->` → `<-` ← `*` × +`<=` ≤ `>=` ≥ `=>` ⇒ +`<>` ≠ `<->` ↔ `|-` ⊢ +`\\/` ∨ `/\\` ∧ `~` ¬ +===== === ==== ===== === ==== ==== === + +Any of these can be overwritten or suppressed using the printing +commands. + +.. note:: + + The recognition of tokens is done by a (``ocaml``) lex + automaton and thus applies the longest-match rule. For instance, `->~` + is recognized as a single token, where |Coq| sees two tokens. It is the + responsibility of the user to insert space between tokens *or* to give + pretty-printing rules for the possible combinations, e.g. + + :: + + (** printing ->~ %\ensuremath{\rightarrow\lnot}% *) + + + +Sections +++++++++ + +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:: + + :: + + (** * Well-founded relations + + In this section, we introduce... *) + + +Lists. +++++++ + +List items are introduced by a leading dash. coqdoc uses whitespace to +determine the depth of a new list item and which text belongs in which +list items. A list ends when a line of text starts at or before the +level of indenting of the list’s dash. A list item’s dash must always +be the first non-space character on its line (so, in particular, a +list can not begin on the first line of a comment - start it on the +second line instead). + +.. example:: + + :: + + We go by induction on [n]: + - If [n] is 0... + - If [n] is [S n'] we require... + + two paragraphs of reasoning, and two subcases: + + - In the first case... + - In the second case... + + So the theorem holds. + + + +Rules. +++++++ + +More than 4 leading dashes produce a horizontal rule. + + +Emphasis. ++++++++++ + +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. + +:: + + This sentence contains some _emphasized text_. + + + +Escaping to |Latex| and HTML. ++++++++++++++++++++++++++++++++ + +Pure |Latex| or HTML material can be inserted using the following +escape sequences: + + ++ ``$...LATEX stuff...$`` inserts some |Latex| material in math mode. + Simply discarded in HTML output. ++ ``%...LATEX stuff...%`` inserts some |Latex| material. Simply + discarded in HTML output. ++ ``#...HTML stuff...#`` inserts some HTML material. Simply discarded in + |Latex| output. + +.. note:: + to simply output the characters ``$``, ``%`` and ``#`` and escaping + their escaping role, these characters must be doubled. + + +Verbatim +++++++++ + +Verbatim material is introduced by a leading ``<<`` and closed by ``>>`` +at the beginning of a line. + +.. example:: + + :: + + Here is the corresponding caml code: + << + let rec fact n = + if n <= 1 then 1 else n * fact (n-1) + >> + + + +Hyperlinks +++++++++++ + +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 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 in the file ``file`` (it will look in ``file.glob`` +by default). + +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. + + +Hiding / Showing parts of the source. ++++++++++++++++++++++++++++++++++++++ + +Some parts of the source can be hidden using command line options ``-g`` +and ``-l`` (see below), or using such comments: + +:: + + + (* begin hide *) + *some Coq material* + (* end hide *) + + +Conversely, some parts of the source which would be hidden can be +shown using such comments: + +:: + + + (* begin show *) + *some Coq material* + (* end show *) + + +The latter cannot be used around some inner parts of a proof, but can +be used around a whole proof. + + +Usage +~~~~~ + +coqdoc is invoked on a shell command line as follows: +``coqdoc <options and files>``. +Any command line argument which is not an option is considered to be a +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 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 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 + options ``-dvi`` and ``-ps`` respectively. +:TEXmacs output: To translate the input files to TEXmacs format, + to be used by the TEXmacs |Coq| interface. + + + +Command line options +++++++++++++++++++++ + + +**Overall options** + + + :--HTML: Select a HTML output. + :--|Latex|: Select a |Latex| output. + :--dvi: Select a DVI output. + :--ps: Select a PostScript output. + :--texmacs: Select a TEXmacs output. + :--stdout: Write output to stdout. + :-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 + 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 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. + :-h, --help: Give a short summary of the options and exit. + :-v, --version: Print the version and exit. + + + +**Index options** + + The default behavior is to build an index, for the HTML output only, + into ``index.html``. + + :--no-index: Do not output the index. + :--multi-index: Generate one page for each category and each letter in + the index, together with a top page ``index.html``. + :--index string: Make the filename of the index string instead of + “index”. Useful since “index.html” is special. + + + +**Table of contents option** + + :-toc, --table-of-contents: Insert a table of contents. For a |Latex| + output, it inserts a ``\tableofcontents`` at the beginning of the + document. For a HTML output, it builds a table of contents into + ``toc.html``. + :--toc-depth int: Only include headers up to depth ``int`` in the table of + contents. + + +**Hyperlink options** + + :--glob-from file: Make references using |Coq| globalizations from file + file. (Such globalizations are obtained with Coq option ``-dump-glob``). + :--no-externals: Do not insert links to the |Coq| standard library. + :--external url coqdir: Use given URL for linking references whose + name starts with prefix ``coqdir``. + :--coqlib url: Set base URL for the Coq standard library (default is + `<http://coq.inria.fr/library/>`_). This is equivalent to ``--external url + Coq``. + :-R dir coqdir: Recursively map physical directory dir to |Coq| logical + directory ``coqdir`` (similarly to |Coq| option ``-R``). + :-Q dir coqdir: Map physical directory dir to |Coq| logical + directory ``coqdir`` (similarly to |Coq| option ``-Q``). + + .. note:: + + options ``-R`` and ``-Q`` only have + effect on the files *following* them on the command line, so you will + probably need to put this option first. + + +**Title options** + + :-s , --short: Do not insert titles for the files. The default + behavior is to insert a title like “Library Foo” for each file. + :--lib-name string: Print “string Foo” instead of “Library Foo” in + titles. For example “Chapter” and “Module” are reasonable choices. + :--no-lib-name: Print just “Foo” instead of “Library Foo” in titles. + :--lib-subtitles: Look for library subtitles. When enabled, the + beginning of each file is checked for a comment of the form: + + :: + + (** * ModuleName : text *) + + where ``ModuleName`` must be the name of the file. If it is present, the + text is used as a subtitle for the module in appropriate places. + :-t string, --title string: Set the document title. + + +**Contents options** + + :-g, --gallina: Do not print proofs. + :-l, --light: Light mode. Suppress proofs (as with ``-g``) and the following commands: + + + [Recursive] Tactic Definition + + Hint / Hints + + Require + + Transparent / Opaque + + Implicit Argument / Implicits + + Section / Variable / Hypothesis / End + + + + 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 that control the parsing of comments: + + :--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. + :--interpolate: Use the globalization information to typeset + identifiers appearing in |Coq| escapings inside comments. + +**Language options** + + + 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. + :-utf8, --utf8: Set --inputenc utf8x for |Latex| output and--charset + utf-8 for HTML output. Also use Unicode replacements for a couple of + standard plain ASCII notations such as → for ``->`` and ∀ for ``forall``. |Latex| + UTF-8 support can be found + at `<http://www.ctan.org/pkg/unicode>`_. For the interpretation of Unicode + characters by |Latex|, extra packages which coqdoc does not provide + by default might be required, such as textgreek for some Greek letters + or ``stmaryrd`` for some mathematical symbols. If a Unicode character is + missing an interpretation in the utf8x input encoding, add + ``\DeclareUnicodeCharacter{code}{LATEX-interpretation}``. Packages + and declarations can be added with option ``-p``. + :--inputenc string: Give a |Latex| input encoding, as an option to |Latex| + package ``inputenc``. + :--charset string: Specify the HTML character set, to be inserted in + the HTML header. + + + +The coqdoc |Latex| style file +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In case you choose to produce a document without the default |Latex| +preamble (by using option ``--no-preamble``), then you must insert into +your own preamble the command + +:: + + \usepackage{coqdoc} + +The package optionally takes the argument ``[color]`` to typeset +identifiers with colors (this requires the ``xcolor`` package). + +Then you may alter the rendering of the document by redefining some +macros: + +:coqdockw, coqdocid, …: The one-argument macros for typesetting + keywords and identifiers. Defaults are sans-serif for keywords and + italic for identifiers.For example, if you would like a slanted font + for keywords, you may insert + + :: + + \renewcommand{\coqdockw}[1]{\textsl{#1}} + + + anywhere between ``\usepackage{coqdoc}`` and ``\begin{document}``. + + +:coqdocmodule: + One-argument macro for typesetting the title of a ``.v`` + file. Default is + + :: + + \newcommand{\coqdocmodule}[1]{\section*{Module #1}} + + and you may redefine it using ``\renewcommand``. diff --git a/doc/sphinx/using/tools/index.rst b/doc/sphinx/using/tools/index.rst index 4381c4d63d..dfe38dfce9 100644 --- a/doc/sphinx/using/tools/index.rst +++ b/doc/sphinx/using/tools/index.rst @@ -16,5 +16,6 @@ on the `Coq website <https://coq.inria.fr/user-interfaces.html>`_. ../../practical-tools/coq-commands ../../practical-tools/utilities + coqdoc ../../practical-tools/coqide ../../addendum/parallel-proof-processing diff --git a/doc/stdlib/make-library-index b/doc/stdlib/make-library-index index a51308f153..cb93a4c8cc 100755 --- a/doc/stdlib/make-library-index +++ b/doc/stdlib/make-library-index @@ -36,7 +36,8 @@ for k in $LIBDIRS; do fi else if [ $h = 0 ]; then - echo Warning: $k/$b.v will be hidden from the index + # Skipping file from the index + : else echo Error: none of $FILE and $HIDDEN mention $k/$b.v exit 1 diff --git a/doc/tools/coqrst/coqdomain.py b/doc/tools/coqrst/coqdomain.py index 0b94b0d675..6332c4c81d 100644 --- a/doc/tools/coqrst/coqdomain.py +++ b/doc/tools/coqrst/coqdomain.py @@ -337,7 +337,7 @@ class TacticNotationObject(NotationObject): """ subdomain = "tacn" index_suffix = "(tactic)" - annotation = None + annotation = "Tactic" class AttributeNotationObject(NotationObject): """An attribute. diff --git a/doc/tools/docgram/README.md b/doc/tools/docgram/README.md index 8f325f957a..7ae98f4cd2 100644 --- a/doc/tools/docgram/README.md +++ b/doc/tools/docgram/README.md @@ -1,13 +1,13 @@ # Grammar extraction tool for documentation -`doc_grammar` extracts Coq's grammar from `.mlg` files, edits it and -inserts it in chunks into `.rst` files. The tool currently inserts -Sphinx `productionlist` and `prodn` constructs (`productionlist` are -gradually being replaced by `prodn` in the manual). Updates to `tacn` -and `cmd` constructs must be done manually since the grammar doesn't -have names for them as it does for nonterminals. There is an option -to report which `tacn` and `cmd` were not found in the `.rst` files. -`tacv` and `cmdv` constructs are not processed at all. +`doc_grammar` extracts Coq's grammar from `.mlg` files, edits it and inserts it +into `.rst` files. The tool inserts `prodn` directives for grammar productions. +(`productionlist` are gradually being replaced by `prodn` in the manual.) +It also updates `tacn` and `cmd` directives when they can be unambiguously matched to +productions of the grammar (in practice, that's probably almost always). +`tacv` and `cmdv` directives are not updated because matching them appears to require +human judgement. `doc_grammar` generates a few files that may be useful to +developers and documentors. The mlg grammars present several challenges to generating an accurate grammar for documentation purposes: @@ -34,46 +34,49 @@ for documentation purposes: ## What the tool does -1. The tool reads all the `mlg` files and generates `fullGrammar`, which includes -all the grammar without the actions for each production or the OCaml code. This -file is provided as a convenience to make it easier to examine the (mostly) -unprocessed grammar of the mlg files with less clutter. Nonterminals that use -levels (`"5" RIGHTA` below) are modified, for example: - -``` -tactic_expr: - [ "5" RIGHTA - [ te = binder_tactic -> { te } ] -``` - -becomes - -``` -tactic_expr5: [ -| binder_tactic -| tactic_expr4 -] -``` - -2. The tool applies grammar editing operations specified by `common.edit_mlg` to -generate `editedGrammar`. - -3. `orderedGrammar` gives the desired order for the nonterminals and productions -in the documented grammar. Developers should edit this file to change the order. -`doc_grammar` updates `orderedGrammar` so it has the same set of nonterminals and productions -as `editedGrammar`. The update process removes manually-added comments from -`orderedGrammar` while automatically-generated comments will be regenerated. - -4. The tool applies further edits to the grammar specified by `productionlist.edit_mlg`, -then it updates the productionlists in the `.rst` files as specified by comments in the form -`.. insertgram <first nt> <last nt>`. The edits are primarily to expand -`.mlg` constructs such as `LIST1` and `OPT` into separate productions. The tool -generates `productionlistGrammar`, which has the entire grammar in the form of `productionlists`. - -5. Using the grammar produced in step 3, the tool applies edits specified by -`prodn.edit_mlg` and generates `prodnGrammar`, representing each production as -a Sphinx `prodn` construct. Differently-edited grammars are used because `prodn` -can naturally represent `LIST1 x SEP ','` whereas that is awkward for `productionlists`. +1. The tool reads all the `mlg` files and generates `fullGrammar`, which includes + all the grammar without the actions for each production or the OCaml code. This + file is provided as a convenience to make it easier to examine the (mostly) + unprocessed grammar of the mlg files with less clutter. Nonterminals that use + levels (`"5" RIGHTA` below) are modified, for example: + + ``` + tactic_expr: + [ "5" RIGHTA + [ te = binder_tactic -> { te } ] + ``` + + becomes + + ``` + tactic_expr5: [ + | binder_tactic + | tactic_expr4 + ] + ``` + +2. The tool applies grammar editing operations specified by `common.edit_mlg` to + generate `editedGrammar`. + +3. `orderedGrammar` gives the desired order for nonterminals and individual productions + in the documented grammar. Developers should edit this file only to reorder lines. + `doc_grammar` updates `orderedGrammar` so it has the same set of nonterminals and productions + as `editedGrammar` while retaining the previous ordering. Since the position of + new or renamed nonterminals is unspecified, they tend to show up in the wrong + place in `orderedGrammar`, therefore users should review the output and make + appropriate adjustments to the order. + + The update process removes manually-added comments from `orderedGrammar` while + automatically-generated comments will be regenerated. + +4. The tool updates the `.rst` files. Comments in the form + `.. insertprodn <first nt> <last nt>` indicate inserting the productions for a + range of nonterminals. `.. cmd::` and `.. tacn::` directives are updated using + prefixes in the form `[a-zA-Z0-9_ ]+` from the directive and the + grammar. If there is unique match in the grammar, the directive is updated, if needed. + Multiple matches or no match gives an error message. + +5. For reference, the tool generates `prodnGrammar`, which has the entire grammar in the form of `prodns`. ## How to use the tool @@ -115,12 +118,12 @@ Other command line arguments: ### Grammar editing scripts -The grammar editing scripts `*.edit_mlg` are similar in format to `.mlg` files stripped +The grammar editing script `common.edit_mlg` is similar in format to `.mlg` files but stripped of all OCaml features. This is an easy way to include productions to match or add without writing another parser. The `DOC_GRAMMAR` token at the beginning of each file -signals the use of streamlined syntax. +signals the use of the streamlined syntax. -Each edit file has a series of items in the form of productions. Items are applied +The edit file has a series of items in the form of productions. Items are applied in the order they appear. There are two types of editing operations: * Global edits - edit rules that apply to the entire grammar in a single operation. @@ -137,7 +140,7 @@ such as `empty: [ | ]`, which adds a new non-terminal `empty` with an empty production on the right-hand side. Another example: `LEFTQMARK: [ | "?" ]` is a local edit that treats `LEFTQMARK` as -the name of a non-terminal and adds one production for it. (We know that LEFTQMARK +the name of a non-terminal and adds a production for it. (We know that LEFTQMARK is a token but doc_grammar does not.) `SPLICE: [ | LEFTQMARK ]` requests replacing all uses of `LEFTQMARK` anywhere in the grammar with its productions and removing the non-terminal. The combined effect of these two is to replace all uses of @@ -192,7 +195,7 @@ that appear in the specified production: ``` `MOVETO <destination> <production>` - moves the production to `<destination>` and, - if needed, creates a new production <edited_nt> -> <destination>. + if needed, creates a new production <edited_nt> -> \<destination>. `OPTINREF` - verifies that <edited_nt> has an empty production. If so, it removes the empty production and replaces all references to <edited_nt> throughout the @@ -201,7 +204,7 @@ grammar with `OPT <edited_nt>` `PRINT` <nonterminal> - prints the nonterminal definition at that point in applying the edits. Most useful when the edits get a bit complicated to follow. -* (any other nonterminal name) - adds a new production (and possibly a new nonterminal) +`(any other nonterminal name)` - adds a new production (and possibly a new nonterminal) to the grammar. ### `.rst` file updates diff --git a/doc/tools/docgram/common.edit_mlg b/doc/tools/docgram/common.edit_mlg index 5bf122078d..60b845c4be 100644 --- a/doc/tools/docgram/common.edit_mlg +++ b/doc/tools/docgram/common.edit_mlg @@ -313,6 +313,7 @@ closed_binder: [ | REPLACE "{" name LIST1 name ":" lconstr "}" | WITH "{" LIST1 name type_cstr "}" | DELETE "{" name ":" lconstr "}" +| MOVETO implicit_binders "{" LIST1 name type_cstr "}" | DELETE "[" name "]" | DELETE "[" name LIST1 name "]" @@ -320,9 +321,14 @@ closed_binder: [ | REPLACE "[" name LIST1 name ":" lconstr "]" | WITH "[" LIST1 name type_cstr "]" | DELETE "[" name ":" lconstr "]" +| MOVETO implicit_binders "[" LIST1 name type_cstr "]" | REPLACE "(" Prim.name ":" lconstr "|" lconstr ")" | WITH "(" Prim.name ":" type "|" lconstr ")" + +| MOVETO generalizing_binder "`(" LIST1 typeclass_constraint SEP "," ")" +| MOVETO generalizing_binder "`{" LIST1 typeclass_constraint SEP "," "}" +| MOVETO generalizing_binder "`[" LIST1 typeclass_constraint SEP "," "]" ] name_colon: [ @@ -383,6 +389,16 @@ evar_instance: [ | OPTINREF ] +(* No constructor syntax, OPT [ "|" binders ] is not supported for Record *) +record_definition: [ +| opt_coercion ident_decl binders OPT [ ":" type ] OPT [ identref ] "{" record_fields "}" decl_notations +] + +(* No record syntax, opt_coercion not supported for Variant, := ... required *) +variant_definition: [ +| ident_decl binders OPT [ "|" binders ] OPT [ ":" type ] ":=" OPT "|" LIST1 constructor SEP "|" decl_notations +] + gallina: [ | REPLACE thm_token ident_decl binders ":" lconstr LIST0 [ "with" ident_decl binders ":" lconstr ] | WITH thm_token ident_decl binders ":" type LIST0 [ "with" ident_decl binders ":" type ] @@ -390,8 +406,8 @@ gallina: [ | REPLACE finite_token LIST1 inductive_definition SEP "with" | WITH "Inductive" inductive_definition LIST0 ( "with" inductive_definition ) | "CoInductive" inductive_definition LIST0 ( "with" inductive_definition ) -| "Variant" inductive_definition LIST0 ( "with" inductive_definition ) -| [ "Record" | "Structure" ] inductive_definition LIST0 ( "with" inductive_definition ) +| "Variant" variant_definition LIST0 ( "with" variant_definition ) +| [ "Record" | "Structure" ] record_definition LIST0 ( "with" record_definition ) | "Class" inductive_definition LIST0 ( "with" inductive_definition ) | REPLACE "Fixpoint" LIST1 rec_definition SEP "with" | WITH "Fixpoint" rec_definition LIST0 ( "with" rec_definition ) @@ -411,7 +427,7 @@ constructor_list_or_record_decl: [ record_fields: [ | REPLACE record_field ";" record_fields -| WITH LIST1 record_field SEP ";" +| WITH LIST0 record_field SEP ";" | DELETE record_field | DELETE (* empty *) ] @@ -487,16 +503,46 @@ functor_app_annot: [ ] is_module_expr: [ +| REPLACE ":=" module_expr_inl LIST0 ext_module_expr +| WITH ":=" LIST1 module_expr_inl SEP "<+" | OPTINREF ] is_module_type: [ +| REPLACE ":=" module_type_inl LIST0 ext_module_type +| WITH ":=" LIST1 module_type_inl SEP "<+" | OPTINREF ] gallina_ext: [ | REPLACE "Arguments" smart_global LIST0 argument_spec_block OPT [ "," LIST1 [ LIST0 more_implicits_block ] SEP "," ] OPT [ ":" LIST1 arguments_modifier SEP "," ] | WITH "Arguments" smart_global LIST0 argument_spec_block LIST0 [ "," LIST0 more_implicits_block ] OPT [ ":" LIST1 arguments_modifier SEP "," ] +| REPLACE "Implicit" "Type" reserv_list +| WITH "Implicit" [ "Type" | "Types" ] reserv_list +| DELETE "Implicit" "Types" reserv_list + +(* Per @Zimmi48, the global (qualid) must be a simple identifier if def_body is present + Note that smart_global is "qualid | by_notation" and that + ident_decl is "ident OPT univ_decl"; move + *) +| REPLACE "Canonical" OPT "Structure" global OPT [ OPT univ_decl def_body ] +| WITH "Canonical" OPT "Structure" ident_decl def_body +| REPLACE "Canonical" OPT "Structure" by_notation +| WITH "Canonical" OPT "Structure" smart_global + +| REPLACE "Include" "Type" module_type_inl LIST0 ext_module_type +| WITH "Include" "Type" LIST1 module_type_inl SEP "<+" + +| REPLACE "Generalizable" [ "All" "Variables" | "No" "Variables" | [ "Variable" | "Variables" ] LIST1 identref ] +| WITH "Generalizable" [ [ "Variable" | "Variables" ] LIST1 identref | "All" "Variables" | "No" "Variables" ] + +| REPLACE "Export" "Set" option_table option_setting +| WITH OPT "Export" "Set" option_table option_setting +| REPLACE "Export" "Unset" option_table +| WITH OPT "Export" "Unset" option_table +| REPLACE "Instance" instance_name ":" operconstr200 hint_info [ ":=" "{" record_declaration "}" | ":=" lconstr | ] +| WITH "Instance" instance_name ":" operconstr200 hint_info OPT [ ":=" "{" record_declaration "}" | ":=" lconstr ] + ] (* lexer stuff *) @@ -619,6 +665,19 @@ selector_body: [ range_selector_or_nth: [ | DELETENT ] +firstorder_rhs: [ +| firstorder_using +| "with" LIST1 preident +| firstorder_using "with" LIST1 preident +] + +where: [ +| "at" "top" +| "at" "bottom" +| "after" ident +| "before" ident +] + simple_tactic: [ | DELETE "intros" | REPLACE "intros" ne_intropatterns @@ -626,6 +685,158 @@ simple_tactic: [ | DELETE "eintros" | REPLACE "eintros" ne_intropatterns | WITH "eintros" intropatterns +| DELETE "autorewrite" "with" LIST1 preident clause +| DELETE "autorewrite" "with" LIST1 preident clause "using" tactic +| DELETE "autorewrite" "*" "with" LIST1 preident clause +| REPLACE "autorewrite" "*" "with" LIST1 preident clause "using" tactic +| WITH "autorewrite" OPT "*" "with" LIST1 preident clause_dft_concl OPT ( "using" tactic ) +| DELETE "cofix" ident +| REPLACE "cofix" ident "with" LIST1 cofixdecl +| WITH "cofix" ident OPT ( "with" LIST1 cofixdecl ) +| DELETE "constructor" +| DELETE "constructor" int_or_var +| REPLACE "constructor" int_or_var "with" bindings +| WITH "constructor" OPT int_or_var OPT ( "with" bindings ) +| DELETE "econstructor" +| DELETE "econstructor" int_or_var +| REPLACE "econstructor" int_or_var "with" bindings +| WITH "econstructor" OPT ( int_or_var OPT ( "with" bindings ) ) +| DELETE "dependent" "rewrite" orient constr +| REPLACE "dependent" "rewrite" orient constr "in" hyp +| WITH "dependent" "rewrite" orient constr OPT ( "in" hyp ) +| "firstorder" OPT tactic firstorder_rhs +| DELETE "firstorder" OPT tactic firstorder_using +| DELETE "firstorder" OPT tactic "with" LIST1 preident +| DELETE "firstorder" OPT tactic firstorder_using "with" LIST1 preident +| DELETE "fix" ident natural +| REPLACE "fix" ident natural "with" LIST1 fixdecl +| WITH "fix" ident natural OPT ( "with" LIST1 fixdecl ) +| DELETE "generalize" constr +| REPLACE "generalize" constr LIST1 constr +| WITH "generalize" constr OPT ( LIST1 constr ) +| EDIT "simplify_eq" ADD_OPT destruction_arg +| EDIT "esimplify_eq" ADD_OPT destruction_arg +| EDIT "discriminate" ADD_OPT destruction_arg +| EDIT "ediscriminate" ADD_OPT destruction_arg +| DELETE "injection" +| DELETE "injection" destruction_arg +| DELETE "injection" "as" LIST0 simple_intropattern +| REPLACE "injection" destruction_arg "as" LIST0 simple_intropattern +| WITH "injection" OPT destruction_arg OPT ( "as" LIST0 simple_intropattern ) +| DELETE "einjection" +| DELETE "einjection" destruction_arg +| DELETE "einjection" "as" LIST0 simple_intropattern +| REPLACE "einjection" destruction_arg "as" LIST0 simple_intropattern +| WITH "einjection" OPT destruction_arg OPT ( "as" LIST0 simple_intropattern ) +| EDIT "simple" "injection" ADD_OPT destruction_arg +| DELETE "intro" (* todo: change the mlg to simplify! *) +| DELETE "intro" ident +| DELETE "intro" ident "at" "top" +| DELETE "intro" ident "at" "bottom" +| DELETE "intro" ident "after" hyp +| DELETE "intro" ident "before" hyp +| DELETE "intro" "at" "top" +| DELETE "intro" "at" "bottom" +| DELETE "intro" "after" hyp +| DELETE "intro" "before" hyp +| "intro" OPT ident OPT where +| DELETE "move" hyp "at" "top" +| DELETE "move" hyp "at" "bottom" +| DELETE "move" hyp "after" hyp +| DELETE "move" hyp "before" hyp +| "move" ident OPT where +| DELETE "replace" "->" uconstr clause +| DELETE "replace" "<-" uconstr clause +| DELETE "replace" uconstr clause +| "replace" orient uconstr clause_dft_concl (* todo: fix 'clause' *) +| REPLACE "rewrite" "*" orient uconstr "in" hyp "at" occurrences by_arg_tac +| WITH "rewrite" "*" orient uconstr OPT ( "in" hyp ) OPT ( "at" occurrences by_arg_tac ) +| DELETE "rewrite" "*" orient uconstr "in" hyp by_arg_tac +| DELETE "rewrite" "*" orient uconstr "at" occurrences by_arg_tac +| DELETE "rewrite" "*" orient uconstr by_arg_tac +| DELETE "setoid_rewrite" orient glob_constr_with_bindings +| DELETE "setoid_rewrite" orient glob_constr_with_bindings "in" hyp +| DELETE "setoid_rewrite" orient glob_constr_with_bindings "at" occurrences +| REPLACE "setoid_rewrite" orient glob_constr_with_bindings "at" occurrences "in" hyp +| WITH "setoid_rewrite" orient glob_constr_with_bindings OPT ( "at" occurrences ) OPT ( "in" hyp ) +| REPLACE "stepl" constr "by" tactic +| WITH "stepl" constr OPT ( "by" tactic ) +| DELETE "stepl" constr +| REPLACE "stepr" constr "by" tactic +| WITH "stepr" constr OPT ( "by" tactic ) +| DELETE "stepr" constr +| DELETE "unify" constr constr +| REPLACE "unify" constr constr "with" preident +| WITH "unify" constr constr OPT ( "with" preident ) +| DELETE "cutrewrite" orient constr +| REPLACE "cutrewrite" orient constr "in" hyp +| WITH "cutrewrite" orient constr OPT ( "in" hyp ) +| DELETE "destauto" +| REPLACE "destauto" "in" hyp +| WITH "destauto" OPT ( "in" hyp ) +| REPLACE "autounfold_one" hintbases "in" hyp +| WITH "autounfold_one" hintbases OPT ( "in" hyp ) +| DELETE "autounfold_one" hintbases +| REPLACE "rewrite_db" preident "in" hyp +| WITH "rewrite_db" preident OPT ( "in" hyp ) +| DELETE "rewrite_db" preident +| DELETE "setoid_symmetry" +| REPLACE "setoid_symmetry" "in" hyp +| WITH "setoid_symmetry" OPT ( "in" hyp ) +| REPLACE "rewrite_strat" rewstrategy "in" hyp +| WITH "rewrite_strat" rewstrategy OPT ( "in" hyp ) +| DELETE "rewrite_strat" rewstrategy +| REPLACE "protect_fv" string "in" ident +| WITH "protect_fv" string OPT ( "in" ident ) +| DELETE "protect_fv" string +| DELETE "symmetry" +| REPLACE "symmetry" "in" in_clause +| WITH "symmetry" OPT ( "in" in_clause ) +| DELETE "split" +| REPLACE "split" "with" bindings +| WITH "split" OPT ( "with" bindings ) +| DELETE "esplit" +| REPLACE "esplit" "with" bindings +| WITH "esplit" OPT ( "with" bindings ) +| DELETE "specialize" constr_with_bindings +| REPLACE "specialize" constr_with_bindings "as" simple_intropattern +| WITH "specialize" constr_with_bindings OPT ( "as" simple_intropattern ) +| DELETE "exists" +| REPLACE "exists" LIST1 bindings SEP "," +| WITH "exists" OPT ( LIST1 bindings SEP "," ) +| DELETE "eexists" +| REPLACE "eexists" LIST1 bindings SEP "," +| WITH "eexists" OPT ( LIST1 bindings SEP "," ) +| DELETE "left" +| REPLACE "left" "with" bindings +| WITH "left" OPT ( "with" bindings ) +| DELETE "eleft" +| REPLACE "eleft" "with" bindings +| WITH "eleft" OPT ( "with" bindings ) +| DELETE "right" +| REPLACE "right" "with" bindings +| WITH "right" OPT ( "with" bindings ) +| DELETE "eright" +| REPLACE "eright" "with" bindings +| WITH "eright" OPT ( "with" bindings ) +| DELETE "finish_timing" OPT string +| REPLACE "finish_timing" "(" string ")" OPT string +| WITH "finish_timing" OPT ( "(" string ")" ) OPT string +| REPLACE "hresolve_core" "(" ident ":=" constr ")" "at" int_or_var "in" constr +| WITH "hresolve_core" "(" ident ":=" constr ")" OPT ( "at" int_or_var ) "in" constr +| DELETE "hresolve_core" "(" ident ":=" constr ")" "in" constr +| EDIT "psatz_R" ADD_OPT int_or_var tactic +| EDIT "psatz_Q" ADD_OPT int_or_var tactic +| EDIT "psatz_Z" ADD_OPT int_or_var tactic +| REPLACE "subst" LIST1 var +| WITH "subst" OPT ( LIST1 var ) +| DELETE "subst" +| DELETE "congruence" +| DELETE "congruence" int +| DELETE "congruence" "with" LIST1 constr +| REPLACE "congruence" int "with" LIST1 constr +| WITH "congruence" OPT int OPT ( "with" LIST1 constr ) + ] (* todo: don't use DELETENT for this *) @@ -661,6 +872,109 @@ command: [ | WITH "Function" function_rec_definition_loc LIST0 ( "with" function_rec_definition_loc ) (* funind plugin *) | REPLACE "Functional" "Scheme" LIST1 fun_scheme_arg SEP "with" (* funind plugin *) | WITH "Functional" "Scheme" fun_scheme_arg LIST0 ( "with" fun_scheme_arg ) (* funind plugin *) +| DELETE "Cd" +| REPLACE "Cd" ne_string +| WITH "Cd" OPT ne_string +| DELETE "Back" +| REPLACE "Back" natural +| WITH "Back" OPT natural +| REPLACE "Test" option_table "for" LIST1 option_ref_value +| WITH "Test" option_table OPT ( "for" LIST1 option_ref_value ) +| DELETE "Test" option_table +| REPLACE "Load" [ "Verbose" | ] [ ne_string | IDENT ] +| WITH "Load" OPT "Verbose" [ ne_string | IDENT ] +| DELETE "Unset" option_table +| DELETE "Set" option_table option_setting +| REPLACE "Add" IDENT IDENT LIST1 option_ref_value +| WITH "Add" IDENT OPT IDENT LIST1 option_ref_value +| DELETE "Add" IDENT LIST1 option_ref_value +| DELETE "Add" "Parametric" "Relation" binders ":" constr constr "reflexivity" "proved" "by" constr "symmetry" "proved" "by" constr "as" ident +| DELETE "Add" "Parametric" "Relation" binders ":" constr constr "reflexivity" "proved" "by" constr "as" ident +| DELETE "Add" "Parametric" "Relation" binders ":" constr constr "reflexivity" "proved" "by" constr "transitivity" "proved" "by" constr "as" ident +| DELETE "Add" "Parametric" "Relation" binders ":" constr constr "reflexivity" "proved" "by" constr "symmetry" "proved" "by" constr "transitivity" "proved" "by" constr "as" ident +| DELETE "Add" "Parametric" "Relation" binders ":" constr constr "symmetry" "proved" "by" constr "as" ident +| DELETE "Add" "Parametric" "Relation" binders ":" constr constr "symmetry" "proved" "by" constr "transitivity" "proved" "by" constr "as" ident +| DELETE "Add" "Parametric" "Relation" binders ":" constr constr "transitivity" "proved" "by" constr "as" ident +| DELETE "Add" "Parametric" "Relation" binders ":" constr constr "as" ident +| "Add" "Parametric" "Relation" binders ":" constr constr OPT ( "reflexivity" "proved" "by" constr ) OPT ( "symmetry" "proved" "by" constr ) OPT ("transitivity" "proved" "by" constr ) "as" ident +| DELETE "Add" "Relation" constr constr "reflexivity" "proved" "by" constr "symmetry" "proved" "by" constr "as" ident +| DELETE "Add" "Relation" constr constr "reflexivity" "proved" "by" constr "as" ident +| DELETE "Add" "Relation" constr constr "as" ident +| DELETE "Add" "Relation" constr constr "symmetry" "proved" "by" constr "as" ident +| DELETE "Add" "Relation" constr constr "symmetry" "proved" "by" constr "transitivity" "proved" "by" constr "as" ident +| DELETE "Add" "Relation" constr constr "reflexivity" "proved" "by" constr "transitivity" "proved" "by" constr "as" ident +| DELETE "Add" "Relation" constr constr "reflexivity" "proved" "by" constr "symmetry" "proved" "by" constr "transitivity" "proved" "by" constr "as" ident +| DELETE "Add" "Relation" constr constr "transitivity" "proved" "by" constr "as" ident +| "Add" "Relation" constr constr OPT ( "reflexivity" "proved" "by" constr ) OPT ( "symmetry" "proved" "by" constr ) OPT ( "transitivity" "proved" "by" constr ) "as" ident +| REPLACE "Admit" "Obligations" "of" ident +| WITH "Admit" "Obligations" OPT ( "of" ident ) +| DELETE "Admit" "Obligations" +| REPLACE "Create" "HintDb" IDENT; [ "discriminated" | ] +| WITH "Create" "HintDb" IDENT; OPT "discriminated" +| DELETE "Debug" "On" +| REPLACE "Debug" "Off" +| WITH "Debug" [ "On" | "Off" ] +| EDIT "Defined" ADD_OPT identref +| REPLACE "Derive" "Inversion" ident "with" constr "Sort" sort_family +| WITH "Derive" "Inversion" ident "with" constr OPT ( "Sort" sort_family ) +| DELETE "Derive" "Inversion" ident "with" constr +| REPLACE "Derive" "Inversion_clear" ident "with" constr "Sort" sort_family +| WITH "Derive" "Inversion_clear" ident "with" constr OPT ( "Sort" sort_family ) +| DELETE "Derive" "Inversion_clear" ident "with" constr +| EDIT "Focus" ADD_OPT natural +| DELETE "Hint" "Rewrite" orient LIST1 constr ":" LIST0 preident +| REPLACE "Hint" "Rewrite" orient LIST1 constr "using" tactic ":" LIST0 preident +| WITH "Hint" "Rewrite" orient LIST1 constr OPT ( "using" tactic ) OPT ( ":" LIST0 preident ) +| DELETE "Hint" "Rewrite" orient LIST1 constr +| DELETE "Hint" "Rewrite" orient LIST1 constr "using" tactic +| REPLACE "Next" "Obligation" "of" ident withtac +| WITH "Next" "Obligation" OPT ( "of" ident ) withtac +| DELETE "Next" "Obligation" withtac +| REPLACE "Obligation" int "of" ident ":" lglob withtac +| WITH "Obligation" int OPT ( "of" ident ) OPT ( ":" lglob withtac ) +| DELETE "Obligation" int "of" ident withtac +| DELETE "Obligation" int ":" lglob withtac +| DELETE "Obligation" int withtac +| REPLACE "Obligations" "of" ident +| WITH "Obligations" OPT ( "of" ident ) +| DELETE "Obligations" +| REPLACE "Preterm" "of" ident +| WITH "Preterm" OPT ( "of" ident ) +| DELETE "Preterm" +| EDIT "Remove" ADD_OPT IDENT IDENT LIST1 option_ref_value +| DELETE "Restore" "State" IDENT +| DELETE "Restore" "State" ne_string +| "Restore" "State" [ IDENT | ne_string ] +| DELETE "Show" +| DELETE "Show" natural +| DELETE "Show" ident +| "Show" OPT [ ident | natural ] +| DELETE "Show" "Ltac" "Profile" +| REPLACE "Show" "Ltac" "Profile" "CutOff" int +| WITH "Show" "Ltac" "Profile" OPT [ "CutOff" int | string ] +| DELETE "Show" "Ltac" "Profile" string +| DELETE "Show" "Proof" (* combined with Show Proof Diffs in vernac_toplevel *) +| REPLACE "Solve" "All" "Obligations" "with" tactic +| WITH "Solve" "All" "Obligations" OPT ( "with" tactic ) +| DELETE "Solve" "All" "Obligations" +| REPLACE "Solve" "Obligation" int "of" ident "with" tactic +| WITH "Solve" "Obligation" int OPT ( "of" ident ) "with" tactic +| DELETE "Solve" "Obligations" +| DELETE "Solve" "Obligation" int "with" tactic +| REPLACE "Solve" "Obligations" "of" ident "with" tactic +| WITH "Solve" "Obligations" OPT ( OPT ( "of" ident ) "with" tactic ) +| DELETE "Solve" "Obligations" "with" tactic +| DELETE "Undo" +| DELETE "Undo" natural +| REPLACE "Undo" "To" natural +| WITH "Undo" OPT ( OPT "To" natural ) +| DELETE "Write" "State" IDENT +| REPLACE "Write" "State" ne_string +| WITH "Write" "State" [ IDENT | ne_string ] +| DELETE "Abort" +| DELETE "Abort" "All" +| REPLACE "Abort" identref +| WITH "Abort" OPT [ "All" | identref ] ] @@ -736,6 +1050,18 @@ all_attrs: [ | LIST0 ( "#[" LIST0 attribute SEP "," "]" ) LIST0 legacy_attr ] +legacy_attr: [ +| REPLACE "Local" +| WITH [ "Local" | "Global" ] +| DELETE "Global" +| REPLACE "Polymorphic" +| WITH [ "Polymorphic" | "Monomorphic" ] +| DELETE "Monomorphic" +| REPLACE "Cumulative" +| WITH [ "Cumulative" | "NonCumulative" ] +| DELETE "NonCumulative" +] + vernacular: [ | LIST0 ( OPT all_attrs [ command | tactic ] "." ) ] @@ -761,6 +1087,7 @@ inductive_definition: [ | WITH opt_coercion ident_decl binders OPT [ "|" binders ] OPT [ ":" type ] opt_constructors_or_fields decl_notations ] +(* note that constructor -> identref constructor_type *) constructor_list_or_record_decl: [ | DELETE "|" LIST1 constructor SEP "|" | REPLACE identref constructor_type "|" LIST1 constructor SEP "|" @@ -777,6 +1104,222 @@ record_binder: [ | DELETE name ] +at_level_opt: [ +| OPTINREF +] + +query_command: [ +| REPLACE "Eval" red_expr "in" lconstr "." +| WITH "Eval" red_expr "in" lconstr +| REPLACE "Compute" lconstr "." +| WITH "Compute" lconstr +| REPLACE "Check" lconstr "." +| WITH "Check" lconstr +| REPLACE "About" smart_global OPT univ_name_list "." +| WITH "About" smart_global OPT univ_name_list +| REPLACE "SearchHead" constr_pattern in_or_out_modules "." +| WITH "SearchHead" constr_pattern in_or_out_modules +| REPLACE "SearchPattern" constr_pattern in_or_out_modules "." +| WITH "SearchPattern" constr_pattern in_or_out_modules +| REPLACE "SearchRewrite" constr_pattern in_or_out_modules "." +| WITH "SearchRewrite" constr_pattern in_or_out_modules +| REPLACE "Search" searchabout_query searchabout_queries "." +| WITH "Search" searchabout_query searchabout_queries +] + +vernac_toplevel: [ +(* note these commands can't be referenced by vernac_control commands *) +| REPLACE "Drop" "." +| WITH "Drop" +| REPLACE "Quit" "." +| WITH "Quit" +| REPLACE "BackTo" natural "." +| WITH "BackTo" natural +| REPLACE "Show" "Goal" natural "at" natural "." +| WITH "Show" "Goal" natural "at" natural +| REPLACE "Show" "Proof" "Diffs" OPT "removed" "." +| WITH "Show" "Proof" OPT ( "Diffs" OPT "removed" ) +| DELETE vernac_control +] + +positive_search_mark: [ +| OPTINREF +] + +in_or_out_modules: [ +| OPTINREF +] + +searchabout_queries: [ +| OPTINREF +] + +vernac_control: [ +(* replacing vernac_control with command is cheating a little; + they can't refer to the vernac_toplevel commands. + cover this the descriptions of these commands *) +| REPLACE "Time" vernac_control +| WITH "Time" command +| REPLACE "Redirect" ne_string vernac_control +| WITH "Redirect" ne_string command +| REPLACE "Timeout" natural vernac_control +| WITH "Timeout" natural command +| REPLACE "Fail" vernac_control +| WITH "Fail" command +| DELETE decorated_vernac +] + +option_setting: [ +| OPTINREF +] + +orient: [ +| OPTINREF +] + +in_hyp_as: [ +| OPTINREF +] + +as_name: [ +| OPTINREF +] + +hloc: [ +| OPTINREF +] + +as_or_and_ipat: [ +| OPTINREF +] + +hintbases: [ +| OPTINREF +] + +as_ipat: [ +| OPTINREF +] + +auto_using: [ +| OPTINREF +] + +with_bindings: [ +| OPTINREF +] + +eqn_ipat: [ +| OPTINREF +] + +withtac: [ +| OPTINREF +] + +of_module_type: [ +| (* empty *) +| OPTINREF +] + + +clause_dft_all: [ +| OPTINREF +] + +opt_clause: [ +| OPTINREF +] + +with_names: [ +| OPTINREF +] + +in_hyp_list: [ +| OPTINREF +] + +struct_annot: [ +| OPTINREF +] + +firstorder_using: [ +| OPTINREF +] + +fun_ind_using: [ +| OPTINREF +] + +by_arg_tac: [ +| OPTINREF +] + +by_tactic: [ +| OPTINREF +] + +rewriter: [ +| REPLACE [ "?" | LEFTQMARK ] constr_with_bindings_arg +| WITH "?" constr_with_bindings_arg +] + +intropattern_or_list_or: [ +(* todo: where does intropattern_or_list_or come from?? *) +| REPLACE intropattern_or_list_or "|" intropatterns +| WITH LIST0 intropattern LIST0 ( "|" intropatterns ) +| DELETE intropatterns +] + +record_declaration: [ +| DELETE fields_def +| LIST0 field_def +] + +fields_def: [ | DELETENT ] + +hint_info: [ +| OPTINREF +] + +debug: [ +| OPTINREF +] + +eauto_search_strategy: [ +| OPTINREF +] + + +constr_body: [ +| DELETE ":=" lconstr +| REPLACE ":" lconstr ":=" lconstr +| WITH OPT ( ":" lconstr ) ":=" lconstr +] + +opt_hintbases: [ +| OPTINREF +] + +opthints: [ +| OPTINREF +] + +scheme: [ +| DELETE scheme_kind +| REPLACE identref ":=" scheme_kind +| WITH OPT ( identref ":=" ) scheme_kind +] + +instance_name: [ +| OPTINREF +] + +simple_reserv: [ +| REPLACE LIST1 identref ":" lconstr +| WITH LIST1 identref ":" type +] + in_clause: [ | DELETE in_clause' | REPLACE LIST0 hypident_occ SEP "," "|-" concl_occ @@ -802,9 +1345,14 @@ decl_notations: [ | OPTINREF ] +module_expr: [ +| REPLACE module_expr_atom +| WITH LIST1 module_expr_atom +| DELETE module_expr module_expr_atom +] + SPLICE: [ | noedit_mode -| command_entry | bigint | match_list | match_context_list @@ -908,7 +1456,6 @@ SPLICE: [ | binders_fixannot | as_return_type | case_type -| fields_def | universe_increment | type_cstr | record_pattern @@ -935,8 +1482,42 @@ SPLICE: [ | record_fields | constructor_type | record_binder +| at_level_opt +| option_ref_value +| positive_search_mark +| in_or_out_modules +| register_prim_token +| option_setting +| orient +| with_bindings +| by_arg_tac +| by_tactic +| quantified_hypothesis +| nat_or_var +| in_hyp_list +| rename +| export_token +| reserv_tuple +| inst | opt_coercion | opt_constructors_or_fields +| is_module_type +| is_module_expr +| module_expr +| mlname +| withtac +| debug +| eauto_search_strategy +| constr_body +| reference_or_constr +| opt_hintbases +| hints_path_atom +| opthints +| scheme +| fresh_id +| ltac_def_kind +| intropatterns +| instance_name ] (* end SPLICE *) RENAME: [ @@ -953,7 +1534,6 @@ RENAME: [ | tactic_expr0 ltac_expr0 (* | nonsimple_intropattern intropattern (* ltac2 *) *) -| intropatterns intropattern_list_opt | operconstr200 term (* historical name *) | operconstr100 term100 @@ -972,14 +1552,12 @@ RENAME: [ | match_hyps match_hyp | BULLET bullet -| nat_or_var num_or_var | fix_decl fix_body | cofix_decl cofix_body | constr one_term | appl_arg arg | rec_definition fix_definition | corec_definition cofix_definition -| inst evar_binding | univ_instance univ_annot | simple_assum_coe assumpt | of_type_with_opt_coercion of_type @@ -991,5 +1569,90 @@ RENAME: [ | smart_global smart_qualid ] +(* todo: doesn't work if up above... maybe because 'clause' doesn't exist? *) +clause_dft_concl: [ +| OPTINREF +] + +(* add in ltac and Tactic Notation tactics that appear in the doc: *) +ltac_defined_tactics: [ +| "classical_left" +| "classical_right" +| "contradict" ident +| "discrR" +| "easy" +| "exfalso" +| "inversion_sigma" +| "lia" +| "lra" +| "nia" +| "nra" +| "split_Rabs" +| "split_Rmult" +| "tauto" +| "zify" +] + +(* todo: need careful review; assume that "[" ... "]" are literals *) +tactic_notation_tactics: [ +| "assert_fails" ltac_expr3 +| "assert_succeeds" ltac_expr3 +| "field" OPT ( "[" LIST1 term "]" ) +| "field_simplify" OPT ( "[" LIST1 term "]" ) LIST1 term OPT ( "in" ident ) +| "field_simplify_eq" OPT ( "[" LIST1 term "]" ) OPT ( "in" ident ) +| "intuition" OPT ltac_expr +| "nsatz" OPT ( "with" "radicalmax" ":=" term "strategy" ":=" term "parameters" ":=" term "variables" ":=" term ) +| "psatz" term OPT int_or_var +| "ring" OPT ( "[" LIST1 term "]" ) +| "ring_simplify" OPT ( "[" LIST1 term "]" ) LIST1 term OPT ( "in" ident ) (* todo: ident was "hyp", worth keeping? *) +] + +tacticals: [ +] +simple_tactic: [ +| ltac_defined_tactics +| tactic_notation_tactics +] + +(* move all commands under "command" *) + +DELETE: [ +| vernac +] + +tactic_mode: [ +(* todo: make sure to document this production! *) +(* deleting to allow splicing query_command into command *) +| DELETE OPT toplevel_selector query_command +] + +vernac_aux: [ +| DELETE gallina "." +| DELETE gallina_ext "." +| DELETE syntax "." +| DELETE command_entry +] + +command: [ +| gallina +| gallina_ext +| syntax +| query_command +| vernac_control +| vernac_toplevel +| command_entry +] + +SPLICE: [ +| gallina +| gallina_ext +| syntax +| query_command +| vernac_control +| vernac_toplevel +| command_entry +| ltac_defined_tactics +| tactic_notation_tactics +] (* todo: ssrreflect*.rst ref to fix_body is incorrect *) diff --git a/doc/tools/docgram/doc_grammar.ml b/doc/tools/docgram/doc_grammar.ml index 5c9a13668f..0450aee2ec 100644 --- a/doc/tools/docgram/doc_grammar.ml +++ b/doc/tools/docgram/doc_grammar.ml @@ -48,7 +48,7 @@ let default_args = { verify = false; } -let start_symbols = ["vernac_toplevel"] +let start_symbols = ["vernacular"] let tokens = [ "bullet"; "string"; "unicode_id_part"; "unicode_letter" ] (* translated symbols *) @@ -1165,7 +1165,7 @@ let apply_edit_file g edits = in aux tl prods' add_nt | (Snterm "OPTINREF" :: _) :: tl -> - if not (List.mem [] prods) then + if not (has_match [] prods) then error "OPTINREF but no empty production for %s\n" nt; global_repl g [(Snterm nt)] [(Sopt (Snterm nt))]; aux tl (remove_prod [] prods nt) add_nt @@ -1618,8 +1618,11 @@ let finish_with_file old_file verify = let open_temp_bin file = open_out_bin (sprintf "%s_temp" file) +let match_cmd_regex = Str.regexp "[a-zA-Z0-9_ ]+" + let find_longest_match prods str = - (* todo: require a minimum length? *) + let get_pfx str = String.trim (if Str.string_match match_cmd_regex str 0 then Str.matched_string str else "") in + let prods = StringSet.fold (fun a lst -> a :: lst) prods [] in (* todo: wasteful! *) let common_prefix_len s1 s2 = let limit = min (String.length s1) (String.length s2) in let rec aux off = @@ -1631,13 +1634,16 @@ let find_longest_match prods str = in let slen = String.length str in + let str_pfx = get_pfx str in let rec longest best multi best_len prods = match prods with | [] -> best, multi, best_len | prod :: tl -> - let pstr = String.trim (prod_to_prodn prod) in + let pstr = String.trim prod in (* todo: should be pretrimmed *) let clen = common_prefix_len str pstr in - if clen = slen && slen = String.length pstr then + if str_pfx = "" || str_pfx <> get_pfx pstr then + longest best multi best_len tl (* prefixes don't match *) + else if clen = slen && slen = String.length pstr then pstr, false, clen (* exact match *) else if clen > best_len then longest pstr false clen tl (* better match *) @@ -1651,6 +1657,7 @@ let find_longest_match prods str = type seen = { nts: (string * int) NTMap.t; tacs: (string * int) NTMap.t; + tacvs: (string * int) NTMap.t; cmds: (string * int) NTMap.t; cmdvs: (string * int) NTMap.t; } @@ -1659,8 +1666,9 @@ let process_rst g file args seen tac_prods cmd_prods = let old_rst = open_in file in let new_rst = open_temp_bin file in let linenum = ref 0 in - let dir_regex = Str.regexp "^\\([ \t]*\\)\\.\\.[ \t]*\\([a-zA-Z0-9:]*\\)\\(.*\\)" in - let ig_args_regex = Str.regexp "^[ \t]*\\([a-zA-Z0-9_\\.]*\\)[ \t]*\\([a-zA-Z0-9_\\.]*\\)" in + let dir_regex = Str.regexp "^\\([ \t]*\\)\\.\\.[ \t]*\\([a-zA-Z0-9:]* *\\)\\(.*\\)" in + let contin_regex = Str.regexp "^\\([ \t]*\\)\\(.*\\)" in + let ip_args_regex = Str.regexp "^[ \t]*\\([a-zA-Z0-9_\\.]*\\)[ \t]*\\([a-zA-Z0-9_\\.]*\\)" in let blank_regex = Str.regexp "^[ \t]*$" in let end_prodlist_regex = Str.regexp "^[ \t]*$" in let getline () = @@ -1692,7 +1700,7 @@ let process_rst g file args seen tac_prods cmd_prods = in let process_insertprodn line rhs = - if not (Str.string_match ig_args_regex rhs 0) then + if not (Str.string_match ip_args_regex rhs 0) then error "%s line %d: bad arguments '%s' for 'insertprodn'\n" file !linenum rhs else begin let start = Str.matched_group 1 rhs in @@ -1703,8 +1711,8 @@ let process_rst g file args seen tac_prods cmd_prods = error "%s line %d: '%s' is undefined in insertprodn\n" file !linenum start; if end_index = None then error "%s line %d: '%s' is undefined in insertprodn\n" file !linenum end_; - if start_index <> None && end_index <> None then - check_range_consistency g start end_; +(* if start_index <> None && end_index <> None then*) +(* check_range_consistency g start end_;*) match start_index, end_index with | Some start_index, Some end_index -> if start_index > end_index then @@ -1716,7 +1724,7 @@ let process_rst g file args seen tac_prods cmd_prods = error "%s line %d: expecting a blank line after 'insertprodn'\n" file !linenum else begin let line3 = getline() in - if not (Str.string_match dir_regex line3 0) || (Str.matched_group 2 line3) <> "prodn::" then + if not (Str.string_match dir_regex line3 0) || (String.trim (Str.matched_group 2 line3)) <> "prodn::" then error "%s line %d: expecting '.. prodn::' after 'insertprodn'\n" file !linenum else begin let indent = Str.matched_group 1 line3 in @@ -1736,38 +1744,82 @@ let process_rst g file args seen tac_prods cmd_prods = end | _ -> () end + in + +(* let skip_files = ["doc/sphinx/proof-engine/ltac.rst"; "doc/sphinx/proof-engine/ltac2.rst";*) +(* "doc/sphinx/proof-engine/ssreflect-proof-language.rst"]*) +(* in*) + let cmd_replace_files = [ + "doc/sphinx/language/gallina-specification-language.rst"; + "doc/sphinx/language/gallina-extensions.rst" + ] in + + let save_n_get_more direc pfx first_rhs seen_map prods = + let replace rhs prods = + if StringSet.is_empty prods || not (List.mem file cmd_replace_files) then + rhs (* no change *) + else + let mtch, multi, len = find_longest_match prods rhs in + if mtch = rhs then + rhs (* no change *) + else if mtch = "" then begin + warn "%s line %d: NO MATCH `%s`\n" file !linenum rhs; + rhs + end else if multi then begin + warn "%s line %d: MULTIMATCH `%s`\n" file !linenum rhs; + rhs + end else + mtch (* update cmd/tacn *) + in + let map = ref seen_map in + if NTMap.mem first_rhs !map then + warn "%s line %d: Repeated %s: '%s'\n" file !linenum direc first_rhs; +(* if not (StringSet.mem rhs seen_map) then*) +(* warn "%s line %d: Unknown tactic: '%s'\n" file !linenum rhs;*) + + fprintf new_rst "%s%s\n" pfx (replace first_rhs prods); + + map := NTMap.add first_rhs (file, !linenum) !map; + while + let nextline = getline() in + ignore (Str.string_match contin_regex nextline 0); + let indent = Str.matched_group 1 nextline in + let rhs = Str.matched_group 2 nextline in + let replaceable = rhs <> "" && rhs.[0] <> ':' in + let upd_rhs = if replaceable then (replace rhs prods) else rhs in + fprintf new_rst "%s%s\n" indent upd_rhs; + if replaceable then begin + map := NTMap.add rhs (file, !linenum) !map + end; + rhs <> "" + do + () + done; + !map + in + try while true do let line = getline() in if Str.string_match dir_regex line 0 then begin - let dir = Str.matched_group 2 line in - let rhs = String.trim (Str.matched_group 3 line) in + let dir = String.trim (Str.matched_group 2 line) in + let rhs = Str.matched_group 3 line in + let pfx = String.sub line 0 (Str.group_end 2) in match dir with | "prodn::" -> if rhs = "coq" then warn "%s line %d: Missing 'insertprodn' before 'prodn:: coq'\n" file !linenum; fprintf new_rst "%s\n" line; | "tacn::" when args.check_tacs -> - if not (StringSet.mem rhs tac_prods) then - warn "%s line %d: Unknown tactic: '%s'\n" file !linenum rhs; - if NTMap.mem rhs !seen.tacs then - warn "%s line %d: Repeated tactic: '%s'\n" file !linenum rhs; - seen := { !seen with tacs = (NTMap.add rhs (file, !linenum) !seen.tacs)}; - fprintf new_rst "%s\n" line + seen := { !seen with tacs = save_n_get_more "tacn" pfx rhs !seen.tacs tac_prods } + | "tacv::" when args.check_tacs -> + seen := { !seen with tacvs = save_n_get_more "tacv" pfx rhs !seen.tacvs StringSet.empty } | "cmd::" when args.check_cmds -> -(* - if not (StringSet.mem rhs cmd_prods) then - warn "%s line %d: Unknown command: '%s'\n" file !linenum rhs; - if NTMap.mem rhs !seen.cmds then - warn "%s line %d: Repeated command: '%s'\n" file !linenum rhs; -*) - seen := { !seen with cmds = (NTMap.add rhs (file, !linenum) !seen.cmds)}; - fprintf new_rst "%s\n" line + seen := { !seen with cmds = save_n_get_more "cmd" pfx rhs !seen.cmds cmd_prods } | "cmdv::" when args.check_cmds -> - seen := { !seen with cmdvs = (NTMap.add rhs (file, !linenum) !seen.cmdvs)}; - fprintf new_rst "%s\n" line + seen := { !seen with cmdvs = save_n_get_more "cmdv" pfx rhs !seen.cmdvs StringSet.empty } | "insertprodn" -> process_insertprodn line rhs | _ -> fprintf new_rst "%s\n" line @@ -1835,19 +1887,7 @@ let process_grammar args = let common_edits = read_mlg_edit "common.edit_mlg" in apply_edit_file g common_edits end; - let prodn_gram = ref { map = !g.map; order = !g.order } in - - if !exit_code = 0 && not args.verify then begin - let prodlist_edits = read_mlg_edit "productionlist.edit_mlg" in - apply_edit_file g prodlist_edits; - let out = open_temp_bin (dir "productionlistGrammar") in - if args.verbose then - report_info g !symdef_map; - print_in_order out g `PRODLIST !g.order StringSet.empty; - (*print_chunks g out `PRODLIST ();*) - close_out out; - finish_with_file (dir "productionlistGrammar") args.verify; - end; + let prodn_gram = ref { map = !g.map; order = !g.order } in (* todo: should just be 'g', right? *) if !exit_code = 0 && not args.verify then begin let out = open_temp_bin (dir "editedGrammar") in @@ -1864,7 +1904,7 @@ let process_grammar args = let ordered_grammar = read_mlg_edit "orderedGrammar" in let out = open_temp_bin (dir "orderedGrammar") in fprintf out "%s\n%s\n\n" - ("(* Defines the order to apply to editedGrammar to get productionlistGrammar.\n" ^ + ("(* Defines the order to apply to editedGrammar to get the final grammar for the doc.\n" ^ "doc_grammar will modify this file to add/remove nonterminals and productions\n" ^ "to match editedGrammar, which will remove comments. Not compiled into Coq *)") "DOC_GRAMMAR"; @@ -1883,7 +1923,7 @@ let process_grammar args = list, StringSet.of_list list in let tac_list, tac_prods = plist "simple_tactic" in let cmd_list, cmd_prods = plist "command" in - let seen = ref { nts=NTMap.empty; tacs=NTMap.empty; cmds=NTMap.empty; cmdvs=NTMap.empty } in + let seen = ref { nts=NTMap.empty; tacs=NTMap.empty; tacvs=NTMap.empty; cmds=NTMap.empty; cmdvs=NTMap.empty } in List.iter (fun file -> process_rst g file args seen tac_prods cmd_prods) args.rst_files; report_omitted_prods !g.order !seen.nts "Nonterminal" ""; let out = open_out (dir "updated_rsts") in @@ -1894,38 +1934,42 @@ let process_grammar args = if args.check_cmds then report_omitted_prods cmd_list !seen.cmds "Command" "\n "; *) + (* generate report on cmds or tacs *) + let cmdReport outfile cmdStr cmd_nts cmds cmdvs = + let rstCmds = StringSet.of_list (List.map (fun b -> let c, _ = b in c) (NTMap.bindings cmds)) in + let rstCmdvs = StringSet.of_list (List.map (fun b -> let c, _ = b in c) (NTMap.bindings cmdvs)) in + let gramCmds = List.fold_left (fun set nt -> + StringSet.union set (StringSet.of_list (List.map (fun p -> String.trim (prod_to_prodn p)) (NTMap.find nt !prodn_gram.map))) + ) StringSet.empty cmd_nts in + let allCmds = StringSet.union rstCmdvs (StringSet.union rstCmds gramCmds) in + let out = open_out_bin (dir outfile) in + StringSet.iter (fun c -> + let rsts = StringSet.mem c rstCmds in + let gram = StringSet.mem c gramCmds in + let pfx = match rsts, gram with + | true, false -> "+" + | false, true -> "-" + | false, false -> "?" + | _, _ -> " " + in + let var = if StringSet.mem c rstCmdvs then "v" else " " in + fprintf out "%s%s %s\n" pfx var c) + allCmds; + close_out out; + Printf.printf "# %s in rsts, gram, total = %d %d %d\n" cmdStr (StringSet.cardinal gramCmds) + (StringSet.cardinal rstCmds) (StringSet.cardinal allCmds); + in - let rstCmds = StringSet.of_list (List.map (fun b -> let c, _ = b in c) (NTMap.bindings !seen.cmds)) in - let rstCmdvs = StringSet.of_list (List.map (fun b -> let c, _ = b in c) (NTMap.bindings !seen.cmdvs)) in - let command_nts = ["command"; "gallina"; "gallina_ext"; "query_command"; "syntax"] in + let cmd_nts = ["command"] in (* TODO: need to handle tactic_mode (overlaps with query_command) and subprf *) - let gramCmds = List.fold_left (fun set nt -> - StringSet.union set (StringSet.of_list (List.map (fun p -> String.trim (prod_to_prodn p)) (NTMap.find nt !prodn_gram.map))) - ) StringSet.empty command_nts in - - let allCmds = StringSet.union rstCmdvs (StringSet.union rstCmds gramCmds) in - let out = open_out_bin (dir "prodnCommands") in - StringSet.iter (fun c -> - let rsts = StringSet.mem c rstCmds in - let gram = StringSet.mem c gramCmds in - let pfx = match rsts, gram with - | true, false -> "+" - | false, true -> "-" - | false, false -> "?" - | _, _ -> " " - in - let var = if StringSet.mem c rstCmdvs then "v" else " " in - fprintf out "%s%s %s\n" pfx var c) - allCmds; - close_out out; - Printf.printf "# cmds in rsts, gram, total = %d %d %d\n" (StringSet.cardinal gramCmds) - (StringSet.cardinal rstCmds) (StringSet.cardinal allCmds); + cmdReport "prodnCommands" "cmds" cmd_nts !seen.cmds !seen.cmdvs; + + let tac_nts = ["simple_tactic"] in + cmdReport "prodnTactics" "tacs" tac_nts !seen.tacs !seen.tacvs end; - (* generate output for prodn: simple_tactic, command, also for Ltac?? *) + (* generate prodnGrammar for reference *) if !exit_code = 0 && not args.verify then begin - let prodn_edits = read_mlg_edit "prodn.edit_mlg" in - apply_edit_file prodn_gram prodn_edits; let out = open_temp_bin (dir "prodnGrammar") in print_in_order out prodn_gram `PRODN !prodn_gram.order StringSet.empty; close_out out; diff --git a/doc/tools/docgram/dune b/doc/tools/docgram/dune index 3afa21f2cf..fba4856241 100644 --- a/doc/tools/docgram/dune +++ b/doc/tools/docgram/dune @@ -5,26 +5,47 @@ (env (_ (binaries doc_grammar.exe))) (rule - (targets fullGrammar) + (alias check-gram) (deps - ; Main grammar - (glob_files %{project_root}/parsing/*.mlg) - (glob_files %{project_root}/toplevel/*.mlg) - (glob_files %{project_root}/vernac/*.mlg) - ; All plugins except SSReflect for now (mimicking what is done in Makefile.doc) - (glob_files %{project_root}/plugins/btauto/*.mlg) - (glob_files %{project_root}/plugins/cc/*.mlg) - (glob_files %{project_root}/plugins/derive/*.mlg) - (glob_files %{project_root}/plugins/extraction/*.mlg) - (glob_files %{project_root}/plugins/firstorder/*.mlg) - (glob_files %{project_root}/plugins/funind/*.mlg) - (glob_files %{project_root}/plugins/ltac/*.mlg) - (glob_files %{project_root}/plugins/micromega/*.mlg) - (glob_files %{project_root}/plugins/nsatz/*.mlg) - (glob_files %{project_root}/plugins/omega/*.mlg) - (glob_files %{project_root}/plugins/rtauto/*.mlg) - (glob_files %{project_root}/plugins/setoid_ring/*.mlg) - (glob_files %{project_root}/plugins/syntax/*.mlg)) + (:input + ; Main grammar + (glob_files %{project_root}/parsing/*.mlg) + (glob_files %{project_root}/toplevel/*.mlg) + (glob_files %{project_root}/vernac/*.mlg) + ; All plugins except SSReflect and Ltac2 for now (mimicking what is done in Makefile.doc) + (glob_files %{project_root}/plugins/btauto/*.mlg) + (glob_files %{project_root}/plugins/cc/*.mlg) + (glob_files %{project_root}/plugins/derive/*.mlg) + (glob_files %{project_root}/plugins/extraction/*.mlg) + (glob_files %{project_root}/plugins/firstorder/*.mlg) + (glob_files %{project_root}/plugins/funind/*.mlg) + (glob_files %{project_root}/plugins/ltac/*.mlg) + (glob_files %{project_root}/plugins/micromega/*.mlg) + (glob_files %{project_root}/plugins/nsatz/*.mlg) + (glob_files %{project_root}/plugins/omega/*.mlg) + (glob_files %{project_root}/plugins/rtauto/*.mlg) + (glob_files %{project_root}/plugins/setoid_ring/*.mlg) + (glob_files %{project_root}/plugins/syntax/*.mlg) + ; Sphinx files + (glob_files %{project_root}/doc/sphinx/language/*.rst) + (glob_files %{project_root}/doc/sphinx/proof-engine/*.rst) + (glob_files %{project_root}/doc/sphinx/user-extensions/*.rst) + (glob_files %{project_root}/doc/sphinx/practical-tools/*.rst) + (glob_files %{project_root}/doc/sphinx/addendum/*.rst) + (glob_files %{project_root}/doc/sphinx/language/core/*.rst) + (glob_files %{project_root}/doc/sphinx/language/extensions/*.rst) + (glob_files %{project_root}/doc/sphinx/proofs/writing-proofs/*.rst) + (glob_files %{project_root}/doc/sphinx/proofs/automatic-tactics/*.rst) + (glob_files %{project_root}/doc/sphinx/proofs/creating-tactics/*.rst) + (glob_files %{project_root}/doc/sphinx/using/libraries/*.rst) + (glob_files %{project_root}/doc/sphinx/using/tools/*.rst)) + common.edit_mlg + orderedGrammar) (action - (chdir %{project_root} (run doc_grammar -short -no-warn %{deps}))) - (mode promote)) + (progn + (bash "for f in fullGrammar orderedGrammar; do cp ${f} ${f}.old; done") + (chdir %{project_root} (run doc_grammar -check-cmds %{input})) + (bash "for f in fullGrammar orderedGrammar; do cp ${f} ${f}.new; done") + (bash "for f in fullGrammar orderedGrammar; do cp ${f}.old ${f}; done") + (diff? fullGrammar fullGrammar.new) + (diff? orderedGrammar orderedGrammar.new)))) diff --git a/doc/tools/docgram/fullGrammar b/doc/tools/docgram/fullGrammar index 2fabf92b7f..272d17bb35 100644 --- a/doc/tools/docgram/fullGrammar +++ b/doc/tools/docgram/fullGrammar @@ -430,17 +430,21 @@ lstring: [ ] integer: [ -| NUMERAL -| test_minus_nat "-" NUMERAL +| bigint ] natural: [ -| NUMERAL +| bignat | _natural ] bigint: [ | NUMERAL +| test_minus_nat "-" NUMERAL +] + +bignat: [ +| NUMERAL ] bar_cbrace: [ @@ -1240,8 +1244,6 @@ query_command: [ | "SearchPattern" constr_pattern in_or_out_modules "." | "SearchRewrite" constr_pattern in_or_out_modules "." | "Search" searchabout_query searchabout_queries "." -| "SearchAbout" searchabout_query searchabout_queries "." -| "SearchAbout" "[" LIST1 searchabout_query "]" in_or_out_modules "." ] printable: [ @@ -2450,8 +2452,6 @@ as_or_and_ipat: [ eqn_ipat: [ | "eqn" ":" naming_intropattern -| "_eqn" ":" naming_intropattern -| "_eqn" | ] @@ -2516,7 +2516,7 @@ field_mods: [ numnotoption: [ | -| "(" "warning" "after" bigint ")" -| "(" "abstract" "after" bigint ")" +| "(" "warning" "after" bignat ")" +| "(" "abstract" "after" bignat ")" ] diff --git a/doc/tools/docgram/orderedGrammar b/doc/tools/docgram/orderedGrammar index c3634466cc..0c9d7a853b 100644 --- a/doc/tools/docgram/orderedGrammar +++ b/doc/tools/docgram/orderedGrammar @@ -1,19 +1,9 @@ -(* Defines the order to apply to editedGrammar to get productionlistGrammar. +(* Defines the order to apply to editedGrammar to get the final grammar for the doc. doc_grammar will modify this file to add/remove nonterminals and productions to match editedGrammar, which will remove comments. Not compiled into Coq *) DOC_GRAMMAR -vernac_toplevel: [ -| "Drop" "." -| "Quit" "." -| "BackTo" num "." -| "Show" "Goal" num "at" num "." -| "Show" "Proof" "Diffs" OPT "removed" "." -| vernac_control -] - tactic_mode: [ -| OPT toplevel_selector query_command | OPT toplevel_selector "{" | OPT toplevel_selector OPT ( "Info" num ) ltac_expr ltac_use_default | "par" ":" OPT ( "Info" num ) ltac_expr ltac_use_default @@ -24,14 +14,6 @@ ltac_use_default: [ | "..." ] -vernac_control: [ -| "Time" vernac_control -| "Redirect" string vernac_control -| "Timeout" num vernac_control -| "Fail" vernac_control -| LIST0 ( "#[" LIST0 attr SEP "," "]" ) vernac -] - term: [ | "forall" open_binders "," term | "fun" open_binders "=>" term @@ -96,11 +78,7 @@ term_projection: [ term_evar: [ | "?[" ident "]" | "?[" "?" ident "]" -| "?" ident OPT ( "@{" LIST1 evar_binding SEP ";" "}" ) -] - -evar_binding: [ -| ident ":=" term +| "?" ident OPT ( "@{" LIST1 ( ident ":=" term ) SEP ";" "}" ) ] dangling_pattern_extension_rule: [ @@ -167,10 +145,26 @@ subsequent_letter: [ | [ first_letter | digit | "'" | unicode_id_part ] ] +firstorder_rhs: [ +| OPT firstorder_using +| "with" LIST1 ident +| OPT firstorder_using "with" LIST1 ident +] + +where: [ +| "at" "top" +| "at" "bottom" +| "after" ident +| "before" ident +] + vernacular: [ | LIST0 ( OPT all_attrs [ command | ltac_expr ] "." ) ] +tacticals: [ +] + all_attrs: [ | LIST0 ( "#[" LIST0 attr SEP "," "]" ) LIST0 legacy_attr ] @@ -185,12 +179,9 @@ attr_value: [ ] legacy_attr: [ -| "Local" -| "Global" -| "Polymorphic" -| "Monomorphic" -| "Cumulative" -| "NonCumulative" +| [ "Local" | "Global" ] +| [ "Polymorphic" | "Monomorphic" ] +| [ "Cumulative" | "NonCumulative" ] | "Private" | "Program" ] @@ -285,13 +276,21 @@ binder: [ | name | "(" LIST1 name ":" type ")" | "(" name OPT ( ":" type ) ":=" term ")" +| implicit_binders +| generalizing_binder | "(" name ":" type "|" term ")" +| "'" pattern0 +] + +implicit_binders: [ | "{" LIST1 name OPT ( ":" type ) "}" | "[" LIST1 name OPT ( ":" type ) "]" +] + +generalizing_binder: [ | "`(" LIST1 typeclass_constraint SEP "," ")" | "`{" LIST1 typeclass_constraint SEP "," "}" | "`[" LIST1 typeclass_constraint SEP "," "]" -| "'" pattern0 ] typeclass_constraint: [ @@ -344,18 +343,10 @@ pattern0: [ | string ] -vernac: [ -| LIST0 legacy_attr vernac_aux -] - vernac_aux: [ -| gallina "." -| gallina_ext "." | command "." | tactic_mode "." -| syntax "." | subprf -| query_command ] subprf: [ @@ -364,30 +355,6 @@ subprf: [ | "}" ] -gallina: [ -| thm_token ident_decl LIST0 binder ":" type LIST0 [ "with" ident_decl LIST0 binder ":" type ] -| assumption_token OPT ( "Inline" OPT ( "(" num ")" ) ) [ LIST1 ( "(" assumpt ")" ) | assumpt ] -| [ "Definition" | "Example" ] ident_decl def_body -| "Let" ident def_body -| "Inductive" inductive_definition LIST0 ( "with" inductive_definition ) -| "CoInductive" inductive_definition LIST0 ( "with" inductive_definition ) -| "Variant" inductive_definition LIST0 ( "with" inductive_definition ) -| [ "Record" | "Structure" ] inductive_definition LIST0 ( "with" inductive_definition ) -| "Class" inductive_definition LIST0 ( "with" inductive_definition ) -| "Fixpoint" fix_definition LIST0 ( "with" fix_definition ) -| "Let" "Fixpoint" fix_definition LIST0 ( "with" fix_definition ) -| "CoFixpoint" cofix_definition LIST0 ( "with" cofix_definition ) -| "Let" "CoFixpoint" cofix_definition LIST0 ( "with" cofix_definition ) -| "Scheme" scheme LIST0 ( "with" scheme ) -| "Combined" "Scheme" ident "from" LIST1 ident SEP "," -| "Register" qualid "as" qualid -| "Register" "Inline" qualid -| "Primitive" ident OPT [ ":" term ] ":=" register_token -| "Universe" LIST1 ident -| "Universes" LIST1 ident -| "Constraint" LIST1 univ_constraint SEP "," -] - fix_definition: [ | ident_decl LIST0 binder OPT fixannot OPT ( ":" type ) OPT [ ":=" term ] OPT decl_notations ] @@ -401,12 +368,8 @@ decl_notation: [ ] register_token: [ -| register_prim_token | "#int63_type" | "#float64_type" -] - -register_prim_token: [ | "#int63_head0" | "#int63_tail0" | "#int63_add" @@ -490,15 +453,6 @@ delta_flag: [ | OPT "-" "[" LIST1 smart_qualid "]" ] -smart_qualid: [ -| qualid -| by_notation -] - -by_notation: [ -| string OPT [ "%" ident ] -] - strategy_flag: [ | LIST1 red_flags | delta_flag @@ -520,13 +474,8 @@ ref_or_pattern_occ: [ ] occs_nums: [ -| LIST1 num_or_var -| "-" num_or_var LIST0 int_or_var -] - -num_or_var: [ -| num -| ident +| LIST1 [ num | ident ] +| "-" [ num | ident ] LIST0 int_or_var ] int_or_var: [ @@ -551,17 +500,12 @@ finite_token: [ | "Class" ] -inductive_definition: [ -| OPT ">" ident_decl LIST0 binder OPT [ "|" LIST0 binder ] OPT [ ":" type ] OPT ( ":=" OPT constructors_or_record ) OPT decl_notations -] - -constructors_or_record: [ -| OPT "|" LIST1 constructor SEP "|" -| OPT ident "{" LIST1 record_field SEP ";" "}" +variant_definition: [ +| ident_decl LIST0 binder OPT [ "|" LIST0 binder ] OPT [ ":" type ] ":=" OPT "|" LIST1 constructor SEP "|" OPT decl_notations ] -constructor: [ -| ident LIST0 binder OPT of_type +record_definition: [ +| OPT ">" ident_decl LIST0 binder OPT [ ":" type ] OPT ident "{" LIST0 record_field SEP ";" "}" OPT decl_notations ] record_field: [ @@ -574,13 +518,21 @@ field_body: [ | LIST0 binder ":=" term ] -cofix_definition: [ -| ident_decl LIST0 binder OPT ( ":" type ) OPT [ ":=" term ] OPT decl_notations +inductive_definition: [ +| OPT ">" ident_decl LIST0 binder OPT [ "|" LIST0 binder ] OPT [ ":" type ] OPT ( ":=" OPT constructors_or_record ) OPT decl_notations +] + +constructors_or_record: [ +| OPT "|" LIST1 constructor SEP "|" +| OPT ident "{" LIST0 record_field SEP ";" "}" ] -scheme: [ -| scheme_kind -| ident ":=" scheme_kind +constructor: [ +| ident LIST0 binder OPT of_type +] + +cofix_definition: [ +| ident_decl LIST0 binder OPT ( ":" type ) OPT [ ":=" term ] OPT decl_notations ] scheme_kind: [ @@ -598,60 +550,12 @@ sort_family: [ | "Type" ] -gallina_ext: [ -| "Module" OPT export_token ident LIST0 module_binder of_module_type OPT is_module_expr -| "Module" "Type" ident LIST0 module_binder LIST0 ( "<:" module_type_inl ) OPT is_module_type -| "Declare" "Module" OPT export_token ident LIST0 module_binder ":" module_type_inl -| "Section" ident -| "Chapter" ident -| "End" ident -| "Collection" ident ":=" section_subset_expr -| "Require" OPT export_token LIST1 qualid -| "From" qualid "Require" OPT export_token LIST1 qualid -| "Import" LIST1 qualid -| "Export" LIST1 qualid -| "Include" module_type_inl LIST0 ( "<+" module_expr_inl ) -| "Include" "Type" module_type_inl LIST0 ( "<+" module_type_inl ) -| "Transparent" LIST1 smart_qualid -| "Opaque" LIST1 smart_qualid -| "Strategy" LIST1 [ strategy_level "[" LIST1 smart_qualid "]" ] -| "Canonical" OPT "Structure" qualid OPT [ OPT univ_decl def_body ] -| "Canonical" OPT "Structure" by_notation -| "Coercion" qualid OPT univ_decl def_body -| "Identity" "Coercion" ident ":" class ">->" class -| "Coercion" qualid ":" class ">->" class -| "Coercion" by_notation ":" class ">->" class -| "Context" LIST1 binder -| "Instance" instance_name ":" term hint_info [ ":=" "{" [ LIST1 field_def SEP ";" | ] "}" | ":=" term | ] -| "Existing" "Instance" qualid hint_info -| "Existing" "Instances" LIST1 qualid OPT [ "|" num ] -| "Existing" "Class" qualid -| "Arguments" smart_qualid LIST0 argument_spec_block LIST0 [ "," LIST0 more_implicits_block ] OPT [ ":" LIST1 arguments_modifier SEP "," ] -| "Implicit" "Type" reserv_list -| "Implicit" "Types" reserv_list -| "Generalizable" [ "All" "Variables" | "No" "Variables" | [ "Variable" | "Variables" ] LIST1 ident ] -| "Export" "Set" LIST1 ident option_setting -| "Export" "Unset" LIST1 ident -] - -option_setting: [ -| -| int -| string -] - hint_info: [ | "|" OPT num OPT one_term -| -] - -export_token: [ -| "Import" -| "Export" ] module_binder: [ -| "(" OPT export_token LIST1 ident ":" module_type_inl ")" +| "(" OPT [ "Import" | "Export" ] LIST1 ident ":" module_type_inl ")" ] module_type_inl: [ @@ -659,6 +563,11 @@ module_type_inl: [ | module_type OPT functor_app_annot ] +functor_app_annot: [ +| "[" "inline" "at" "level" num "]" +| "[" "no" "inline" "]" +] + module_type: [ | qualid | "(" module_type ")" @@ -671,9 +580,9 @@ with_declaration: [ | "Module" qualid ":=" qualid ] -functor_app_annot: [ -| "[" "inline" "at" "level" num "]" -| "[" "no" "inline" "]" +module_expr_atom: [ +| qualid +| "(" LIST1 module_expr_atom ")" ] of_module_type: [ @@ -681,27 +590,18 @@ of_module_type: [ | LIST0 ( "<:" module_type_inl ) ] -is_module_type: [ -| ":=" module_type_inl LIST0 ( "<+" module_type_inl ) +module_expr_inl: [ +| "!" LIST1 module_expr_atom +| LIST1 module_expr_atom OPT functor_app_annot ] -module_expr_atom: [ +smart_qualid: [ | qualid -| "(" module_expr ")" -] - -module_expr: [ -| module_expr_atom -| module_expr module_expr_atom -] - -is_module_expr: [ -| ":=" module_expr_inl LIST0 ( "<+" module_expr_inl ) +| by_notation ] -module_expr_inl: [ -| "!" module_expr -| module_expr OPT functor_app_annot +by_notation: [ +| string OPT [ "%" ident ] ] argument_spec_block: [ @@ -744,31 +644,21 @@ strategy_level: [ | "transparent" ] -instance_name: [ -| ident_decl LIST0 binder -| -] - reserv_list: [ -| LIST1 reserv_tuple +| LIST1 ( "(" simple_reserv ")" ) | simple_reserv ] -reserv_tuple: [ -| "(" simple_reserv ")" -] - simple_reserv: [ -| LIST1 ident ":" term +| LIST1 ident ":" type ] command: [ | "Goal" term | "Declare" "Scope" ident | "Pwd" -| "Cd" -| "Cd" string -| "Load" [ "Verbose" | ] [ string | ident ] +| "Cd" OPT string +| "Load" OPT "Verbose" [ string | ident ] | "Declare" "ML" "Module" LIST1 string | "Locate" locatable | "Add" "LoadPath" string "as" dirpath @@ -818,101 +708,61 @@ command: [ | "Print" "Namespace" dirpath | "Inspect" num | "Add" "ML" "Path" string -| "Set" LIST1 ident option_setting -| "Unset" LIST1 ident +| OPT "Export" "Set" LIST1 ident OPT [ int | string ] +| OPT "Export" "Unset" LIST1 ident | "Print" "Table" LIST1 ident -| "Add" ident ident LIST1 option_ref_value -| "Add" ident LIST1 option_ref_value -| "Test" LIST1 ident "for" LIST1 option_ref_value -| "Test" LIST1 ident -| "Remove" ident ident LIST1 option_ref_value -| "Remove" ident LIST1 option_ref_value -| "Write" "State" ident -| "Write" "State" string -| "Restore" "State" ident -| "Restore" "State" string +| "Add" ident OPT ident LIST1 [ qualid | string ] +| "Test" LIST1 ident OPT ( "for" LIST1 [ qualid | string ] ) +| "Remove" OPT ident ident LIST1 [ qualid | string ] +| "Write" "State" [ ident | string ] +| "Restore" "State" [ ident | string ] | "Reset" "Initial" | "Reset" ident -| "Back" -| "Back" num -| "Debug" "On" -| "Debug" "Off" +| "Back" OPT num +| "Debug" [ "On" | "Off" ] | "Declare" "Reduction" ident ":=" red_expr | "Declare" "Custom" "Entry" ident | "Derive" ident "SuchThat" one_term "As" ident (* derive plugin *) | "Proof" | "Proof" "Mode" string | "Proof" term -| "Abort" -| "Abort" "All" -| "Abort" ident -| "Existential" num constr_body +| "Abort" OPT [ "All" | ident ] +| "Existential" num OPT ( ":" term ) ":=" term | "Admitted" | "Qed" | "Save" ident -| "Defined" -| "Defined" ident +| "Defined" OPT ident | "Restart" -| "Undo" -| "Undo" num -| "Undo" "To" num -| "Focus" -| "Focus" num +| "Undo" OPT ( OPT "To" num ) +| "Focus" OPT num | "Unfocus" | "Unfocused" -| "Show" -| "Show" num -| "Show" ident +| "Show" OPT [ ident | num ] | "Show" "Existentials" | "Show" "Universes" | "Show" "Conjectures" -| "Show" "Proof" +| "Show" "Proof" OPT ( "Diffs" OPT "removed" ) | "Show" "Intro" | "Show" "Intros" | "Show" "Match" qualid | "Guarded" -| "Create" "HintDb" ident [ "discriminated" | ] -| "Remove" "Hints" LIST1 qualid opt_hintbases -| "Hint" hint opt_hintbases +| "Create" "HintDb" ident OPT "discriminated" +| "Remove" "Hints" LIST1 qualid OPT ( ":" LIST1 ident ) +| "Hint" hint OPT ( ":" LIST1 ident ) | "Comments" LIST0 comment -| "Declare" "Instance" ident_decl LIST0 binder ":" term hint_info -| "Obligation" int "of" ident ":" term withtac -| "Obligation" int "of" ident withtac -| "Obligation" int ":" term withtac -| "Obligation" int withtac -| "Next" "Obligation" "of" ident withtac -| "Next" "Obligation" withtac -| "Solve" "Obligation" int "of" ident "with" ltac_expr -| "Solve" "Obligation" int "with" ltac_expr -| "Solve" "Obligations" "of" ident "with" ltac_expr -| "Solve" "Obligations" "with" ltac_expr -| "Solve" "Obligations" -| "Solve" "All" "Obligations" "with" ltac_expr -| "Solve" "All" "Obligations" -| "Admit" "Obligations" "of" ident -| "Admit" "Obligations" +| "Declare" "Instance" ident_decl LIST0 binder ":" term OPT hint_info +| "Obligation" int OPT ( "of" ident ) OPT ( ":" term OPT ( "with" ltac_expr ) ) +| "Next" "Obligation" OPT ( "of" ident ) OPT ( "with" ltac_expr ) +| "Solve" "Obligation" int OPT ( "of" ident ) "with" ltac_expr +| "Solve" "Obligations" OPT ( OPT ( "of" ident ) "with" ltac_expr ) +| "Solve" "All" "Obligations" OPT ( "with" ltac_expr ) +| "Admit" "Obligations" OPT ( "of" ident ) | "Obligation" "Tactic" ":=" ltac_expr | "Show" "Obligation" "Tactic" -| "Obligations" "of" ident -| "Obligations" -| "Preterm" "of" ident -| "Preterm" -| "Add" "Relation" one_term one_term "reflexivity" "proved" "by" one_term "symmetry" "proved" "by" one_term "as" ident -| "Add" "Relation" one_term one_term "reflexivity" "proved" "by" one_term "as" ident -| "Add" "Relation" one_term one_term "as" ident -| "Add" "Relation" one_term one_term "symmetry" "proved" "by" one_term "as" ident -| "Add" "Relation" one_term one_term "symmetry" "proved" "by" one_term "transitivity" "proved" "by" one_term "as" ident -| "Add" "Relation" one_term one_term "reflexivity" "proved" "by" one_term "transitivity" "proved" "by" one_term "as" ident -| "Add" "Relation" one_term one_term "reflexivity" "proved" "by" one_term "symmetry" "proved" "by" one_term "transitivity" "proved" "by" one_term "as" ident -| "Add" "Relation" one_term one_term "transitivity" "proved" "by" one_term "as" ident -| "Add" "Parametric" "Relation" LIST0 binder ":" one_term one_term "reflexivity" "proved" "by" one_term "symmetry" "proved" "by" one_term "as" ident -| "Add" "Parametric" "Relation" LIST0 binder ":" one_term one_term "reflexivity" "proved" "by" one_term "as" ident -| "Add" "Parametric" "Relation" LIST0 binder ":" one_term one_term "as" ident -| "Add" "Parametric" "Relation" LIST0 binder ":" one_term one_term "symmetry" "proved" "by" one_term "as" ident -| "Add" "Parametric" "Relation" LIST0 binder ":" one_term one_term "symmetry" "proved" "by" one_term "transitivity" "proved" "by" one_term "as" ident -| "Add" "Parametric" "Relation" LIST0 binder ":" one_term one_term "reflexivity" "proved" "by" one_term "transitivity" "proved" "by" one_term "as" ident -| "Add" "Parametric" "Relation" LIST0 binder ":" one_term one_term "reflexivity" "proved" "by" one_term "symmetry" "proved" "by" one_term "transitivity" "proved" "by" one_term "as" ident -| "Add" "Parametric" "Relation" LIST0 binder ":" one_term one_term "transitivity" "proved" "by" one_term "as" ident +| "Obligations" OPT ( "of" ident ) +| "Preterm" OPT ( "of" ident ) +| "Add" "Relation" one_term one_term OPT ( "reflexivity" "proved" "by" one_term ) OPT ( "symmetry" "proved" "by" one_term ) OPT ( "transitivity" "proved" "by" one_term ) "as" ident +| "Add" "Parametric" "Relation" LIST0 binder ":" one_term one_term OPT ( "reflexivity" "proved" "by" one_term ) OPT ( "symmetry" "proved" "by" one_term ) OPT ( "transitivity" "proved" "by" one_term ) "as" ident | "Add" "Setoid" one_term one_term one_term "as" ident | "Add" "Parametric" "Setoid" LIST0 binder ":" one_term one_term one_term "as" ident | "Add" "Morphism" one_term ":" ident @@ -926,9 +776,7 @@ command: [ | "Optimize" "Proof" | "Optimize" "Heap" | "Reset" "Ltac" "Profile" -| "Show" "Ltac" "Profile" -| "Show" "Ltac" "Profile" "CutOff" int -| "Show" "Ltac" "Profile" string +| "Show" "Ltac" "Profile" OPT [ "CutOff" int | string ] | "Show" "Lia" "Profile" (* micromega plugin *) | "Add" "InjTyp" one_term (* micromega plugin *) | "Add" "BinOp" one_term (* micromega plugin *) @@ -949,10 +797,10 @@ command: [ | "Show" "Zify" "BinRel" (* micromega plugin *) | "Show" "Zify" "Spec" (* micromega plugin *) | "Add" "Ring" ident ":" one_term OPT ( "(" LIST1 ring_mod SEP "," ")" ) (* setoid_ring plugin *) -| "Hint" "Cut" "[" hints_path "]" opthints +| "Hint" "Cut" "[" hints_path "]" OPT ( ":" LIST1 ident ) | "Typeclasses" "Transparent" LIST0 qualid | "Typeclasses" "Opaque" LIST0 qualid -| "Typeclasses" "eauto" ":=" debug eauto_search_strategy OPT int +| "Typeclasses" "eauto" ":=" OPT "debug" OPT [ "(bfs)" | "(dfs)" ] OPT int | "Proof" "with" ltac_expr OPT [ "using" section_subset_expr ] | "Proof" "using" section_subset_expr OPT [ "with" ltac_expr ] | "Tactic" "Notation" OPT ( "(" "at" "level" num ")" ) LIST1 ltac_production_item ":=" ltac_expr @@ -981,20 +829,15 @@ command: [ | "Extraction" "Blacklist" LIST1 ident (* extraction plugin *) | "Print" "Extraction" "Blacklist" (* extraction plugin *) | "Reset" "Extraction" "Blacklist" (* extraction plugin *) -| "Extract" "Constant" qualid LIST0 string "=>" mlname (* extraction plugin *) -| "Extract" "Inlined" "Constant" qualid "=>" mlname (* extraction plugin *) -| "Extract" "Inductive" qualid "=>" mlname "[" LIST0 mlname "]" OPT string (* extraction plugin *) +| "Extract" "Constant" qualid LIST0 string "=>" [ ident | string ] (* extraction plugin *) +| "Extract" "Inlined" "Constant" qualid "=>" [ ident | string ] (* extraction plugin *) +| "Extract" "Inductive" qualid "=>" [ ident | string ] "[" LIST0 [ ident | string ] "]" OPT string (* extraction plugin *) | "Show" "Extraction" (* extraction plugin *) | "Functional" "Case" fun_scheme_arg (* funind plugin *) | "Generate" "graph" "for" qualid (* funind plugin *) -| "Hint" "Rewrite" orient LIST1 one_term ":" LIST0 ident -| "Hint" "Rewrite" orient LIST1 one_term "using" ltac_expr ":" LIST0 ident -| "Hint" "Rewrite" orient LIST1 one_term -| "Hint" "Rewrite" orient LIST1 one_term "using" ltac_expr -| "Derive" "Inversion_clear" ident "with" one_term "Sort" sort_family -| "Derive" "Inversion_clear" ident "with" one_term -| "Derive" "Inversion" ident "with" one_term "Sort" sort_family -| "Derive" "Inversion" ident "with" one_term +| "Hint" "Rewrite" OPT [ "->" | "<-" ] LIST1 one_term OPT ( "using" ltac_expr ) OPT ( ":" LIST0 ident ) +| "Derive" "Inversion_clear" ident "with" one_term OPT ( "Sort" sort_family ) +| "Derive" "Inversion" ident "with" one_term OPT ( "Sort" sort_family ) | "Derive" "Dependent" "Inversion" ident "with" one_term "Sort" sort_family | "Derive" "Dependent" "Inversion_clear" ident "with" one_term "Sort" sort_family | "Declare" "Left" "Step" one_term @@ -1005,12 +848,84 @@ command: [ | "Numeral" "Notation" qualid qualid qualid ":" ident OPT numnotoption | "String" "Notation" qualid qualid qualid ":" ident | "SubClass" ident_decl def_body -] - -orient: [ -| "->" -| "<-" -| +| thm_token ident_decl LIST0 binder ":" type LIST0 [ "with" ident_decl LIST0 binder ":" type ] +| assumption_token OPT ( "Inline" OPT ( "(" num ")" ) ) [ LIST1 ( "(" assumpt ")" ) | assumpt ] +| [ "Definition" | "Example" ] ident_decl def_body +| "Let" ident def_body +| "Inductive" inductive_definition LIST0 ( "with" inductive_definition ) +| "Fixpoint" fix_definition LIST0 ( "with" fix_definition ) +| "Let" "Fixpoint" fix_definition LIST0 ( "with" fix_definition ) +| "CoFixpoint" cofix_definition LIST0 ( "with" cofix_definition ) +| "Let" "CoFixpoint" cofix_definition LIST0 ( "with" cofix_definition ) +| "Scheme" OPT ( ident ":=" ) scheme_kind LIST0 ( "with" OPT ( ident ":=" ) scheme_kind ) +| "Combined" "Scheme" ident "from" LIST1 ident SEP "," +| "Register" qualid "as" qualid +| "Register" "Inline" qualid +| "Primitive" ident OPT [ ":" term ] ":=" register_token +| "Universe" LIST1 ident +| "Universes" LIST1 ident +| "Constraint" LIST1 univ_constraint SEP "," +| "CoInductive" inductive_definition LIST0 ( "with" inductive_definition ) +| "Variant" variant_definition LIST0 ( "with" variant_definition ) +| [ "Record" | "Structure" ] record_definition LIST0 ( "with" record_definition ) +| "Class" inductive_definition LIST0 ( "with" inductive_definition ) +| "Module" OPT [ "Import" | "Export" ] ident LIST0 module_binder OPT of_module_type OPT ( ":=" LIST1 module_expr_inl SEP "<+" ) +| "Module" "Type" ident LIST0 module_binder LIST0 ( "<:" module_type_inl ) OPT ( ":=" LIST1 module_type_inl SEP "<+" ) +| "Declare" "Module" OPT [ "Import" | "Export" ] ident LIST0 module_binder ":" module_type_inl +| "Section" ident +| "Chapter" ident +| "End" ident +| "Collection" ident ":=" section_subset_expr +| "Require" OPT [ "Import" | "Export" ] LIST1 qualid +| "From" qualid "Require" OPT [ "Import" | "Export" ] LIST1 qualid +| "Import" LIST1 qualid +| "Export" LIST1 qualid +| "Include" module_type_inl LIST0 ( "<+" module_expr_inl ) +| "Include" "Type" LIST1 module_type_inl SEP "<+" +| "Transparent" LIST1 smart_qualid +| "Opaque" LIST1 smart_qualid +| "Strategy" LIST1 [ strategy_level "[" LIST1 smart_qualid "]" ] +| "Canonical" OPT "Structure" ident_decl def_body +| "Canonical" OPT "Structure" smart_qualid +| "Coercion" qualid OPT univ_decl def_body +| "Identity" "Coercion" ident ":" class ">->" class +| "Coercion" qualid ":" class ">->" class +| "Coercion" by_notation ":" class ">->" class +| "Context" LIST1 binder +| "Instance" OPT ( ident_decl LIST0 binder ) ":" term OPT hint_info OPT [ ":=" "{" LIST0 field_def "}" | ":=" term ] +| "Existing" "Instance" qualid OPT hint_info +| "Existing" "Instances" LIST1 qualid OPT [ "|" num ] +| "Existing" "Class" qualid +| "Arguments" smart_qualid LIST0 argument_spec_block LIST0 [ "," LIST0 more_implicits_block ] OPT [ ":" LIST1 arguments_modifier SEP "," ] +| "Implicit" [ "Type" | "Types" ] reserv_list +| "Generalizable" [ [ "Variable" | "Variables" ] LIST1 ident | "All" "Variables" | "No" "Variables" ] +| "Open" "Scope" ident +| "Close" "Scope" ident +| "Delimit" "Scope" ident "with" ident +| "Undelimit" "Scope" ident +| "Bind" "Scope" ident "with" LIST1 class +| "Infix" string ":=" one_term OPT [ "(" LIST1 syntax_modifier SEP "," ")" ] OPT [ ":" ident ] +| "Notation" ident LIST0 ident ":=" one_term OPT ( "(" "only" "parsing" ")" ) +| "Notation" string ":=" one_term OPT [ "(" LIST1 syntax_modifier SEP "," ")" ] OPT [ ":" ident ] +| "Format" "Notation" string string string +| "Reserved" "Infix" string OPT [ "(" LIST1 syntax_modifier SEP "," ")" ] +| "Reserved" "Notation" string OPT [ "(" LIST1 syntax_modifier SEP "," ")" ] +| "Eval" red_expr "in" term +| "Compute" term +| "Check" term +| "About" smart_qualid OPT ( "@{" LIST0 name "}" ) +| "SearchHead" one_term OPT ne_in_or_out_modules +| "SearchPattern" one_term OPT ne_in_or_out_modules +| "SearchRewrite" one_term OPT ne_in_or_out_modules +| "Search" searchabout_query OPT searchabout_queries +| "Time" command +| "Redirect" string command +| "Timeout" num command +| "Fail" command +| "Drop" +| "Quit" +| "BackTo" num +| "Show" "Goal" num "at" num ] section_subset_expr: [ @@ -1049,6 +964,10 @@ dirpath: [ | dirpath field_ident ] +bignat: [ +| numeral +] + locatable: [ | smart_qualid | "Term" smart_qualid @@ -1057,27 +976,17 @@ locatable: [ | "Module" qualid ] -option_ref_value: [ -| qualid -| string -] - comment: [ | one_term | string | num ] -reference_or_constr: [ -| qualid -| one_term -] - hint: [ -| "Resolve" LIST1 reference_or_constr hint_info +| "Resolve" LIST1 [ qualid | one_term ] OPT hint_info | "Resolve" "->" LIST1 qualid OPT num | "Resolve" "<-" LIST1 qualid OPT num -| "Immediate" LIST1 reference_or_constr +| "Immediate" LIST1 [ qualid | one_term ] | "Variables" "Transparent" | "Variables" "Opaque" | "Constants" "Transparent" @@ -1090,24 +999,9 @@ hint: [ | "Extern" num OPT one_term "=>" ltac_expr ] -constr_body: [ -| ":=" term -| ":" term ":=" term -] - -withtac: [ -| "with" ltac_expr -| -] - -ltac_def_kind: [ -| ":=" -| "::=" -] - tacdef_body: [ -| qualid LIST1 fun_var ltac_def_kind ltac_expr -| qualid ltac_def_kind ltac_expr +| qualid LIST1 fun_var [ ":=" | "::=" ] ltac_expr +| qualid [ ":=" | "::=" ] ltac_expr ] ltac_production_item: [ @@ -1117,13 +1011,8 @@ ltac_production_item: [ ] numnotoption: [ -| "(" "warning" "after" num ")" -| "(" "abstract" "after" num ")" -] - -mlname: [ -| ident (* extraction plugin *) -| string (* extraction plugin *) +| "(" "warning" "after" bignat ")" +| "(" "abstract" "after" bignat ")" ] int_or_id: [ @@ -1163,55 +1052,17 @@ field_mod: [ | "completeness" one_term (* setoid_ring plugin *) ] -debug: [ -| "debug" -| -] - -eauto_search_strategy: [ -| "(bfs)" -| "(dfs)" -| -] - -hints_path_atom: [ -| LIST1 qualid -| "_" -] - hints_path: [ | "(" hints_path ")" | hints_path "*" | "emp" | "eps" | hints_path "|" hints_path -| hints_path_atom +| LIST1 qualid +| "_" | hints_path hints_path ] -opthints: [ -| ":" LIST1 ident -| -] - -opt_hintbases: [ -| -| ":" LIST1 ident -] - -query_command: [ -| "Eval" red_expr "in" term "." -| "Compute" term "." -| "Check" term "." -| "About" smart_qualid OPT ( "@{" LIST0 name "}" ) "." -| "SearchHead" one_term in_or_out_modules "." -| "SearchPattern" one_term in_or_out_modules "." -| "SearchRewrite" one_term in_or_out_modules "." -| "Search" searchabout_query searchabout_queries "." -| "SearchAbout" searchabout_query searchabout_queries "." -| "SearchAbout" "[" LIST1 searchabout_query "]" in_or_out_modules "." -] - class: [ | "Funclass" | "Sortclass" @@ -1223,39 +1074,14 @@ ne_in_or_out_modules: [ | "outside" LIST1 qualid ] -in_or_out_modules: [ -| ne_in_or_out_modules -| -] - -positive_search_mark: [ -| "-" -| -] - searchabout_query: [ -| positive_search_mark string OPT ( "%" ident ) -| positive_search_mark one_term +| OPT "-" string OPT ( "%" ident ) +| OPT "-" one_term ] searchabout_queries: [ | ne_in_or_out_modules | searchabout_query searchabout_queries -| -] - -syntax: [ -| "Open" "Scope" ident -| "Close" "Scope" ident -| "Delimit" "Scope" ident "with" ident -| "Undelimit" "Scope" ident -| "Bind" "Scope" ident "with" LIST1 class -| "Infix" string ":=" one_term OPT [ "(" LIST1 syntax_modifier SEP "," ")" ] OPT [ ":" ident ] -| "Notation" ident LIST0 ident ":=" one_term OPT ( "(" "only" "parsing" ")" ) -| "Notation" string ":=" one_term OPT [ "(" LIST1 syntax_modifier SEP "," ")" ] OPT [ ":" ident ] -| "Format" "Notation" string string string -| "Reserved" "Infix" string OPT [ "(" LIST1 syntax_modifier SEP "," ")" ] -| "Reserved" "Notation" string OPT [ "(" LIST1 syntax_modifier SEP "," ")" ] ] level: [ @@ -1291,18 +1117,13 @@ syntax_extension_type: [ | "bigint" | "binder" | "constr" -| "constr" at_level_opt OPT constr_as_binder_kind +| "constr" OPT ( "at" level ) OPT constr_as_binder_kind | "pattern" | "pattern" "at" "level" num | "strict" "pattern" | "strict" "pattern" "at" "level" num | "closed" "binder" -| "custom" ident at_level_opt OPT constr_as_binder_kind -] - -at_level_opt: [ -| "at" level -| +| "custom" ident OPT ( "at" level ) OPT constr_as_binder_kind ] simple_tactic: [ @@ -1318,125 +1139,71 @@ simple_tactic: [ | "elimtype" one_term | "lapply" one_term | "transitivity" one_term -| "left" -| "eleft" -| "left" "with" bindings -| "eleft" "with" bindings -| "right" -| "eright" -| "right" "with" bindings -| "eright" "with" bindings -| "constructor" -| "constructor" int_or_var -| "constructor" int_or_var "with" bindings -| "econstructor" -| "econstructor" int_or_var -| "econstructor" int_or_var "with" bindings -| "specialize" constr_with_bindings -| "specialize" constr_with_bindings "as" simple_intropattern -| "symmetry" -| "symmetry" "in" in_clause -| "split" -| "esplit" -| "split" "with" bindings -| "esplit" "with" bindings -| "exists" -| "exists" LIST1 bindings SEP "," -| "eexists" -| "eexists" LIST1 bindings SEP "," -| "intros" "until" quantified_hypothesis -| "intro" -| "intro" ident -| "intro" ident "at" "top" -| "intro" ident "at" "bottom" -| "intro" ident "after" ident -| "intro" ident "before" ident -| "intro" "at" "top" -| "intro" "at" "bottom" -| "intro" "after" ident -| "intro" "before" ident -| "move" ident "at" "top" -| "move" ident "at" "bottom" -| "move" ident "after" ident -| "move" ident "before" ident -| "rename" LIST1 rename SEP "," +| "left" OPT ( "with" bindings ) +| "eleft" OPT ( "with" bindings ) +| "right" OPT ( "with" bindings ) +| "eright" OPT ( "with" bindings ) +| "constructor" OPT int_or_var OPT ( "with" bindings ) +| "econstructor" OPT ( int_or_var OPT ( "with" bindings ) ) +| "specialize" constr_with_bindings OPT ( "as" simple_intropattern ) +| "symmetry" OPT ( "in" in_clause ) +| "split" OPT ( "with" bindings ) +| "esplit" OPT ( "with" bindings ) +| "exists" OPT ( LIST1 bindings SEP "," ) +| "eexists" OPT ( LIST1 bindings SEP "," ) +| "intros" "until" [ ident | num ] +| "intro" OPT ident OPT where +| "move" ident OPT where +| "rename" LIST1 ( ident "into" ident ) SEP "," | "revert" LIST1 ident -| "simple" "induction" quantified_hypothesis -| "simple" "destruct" quantified_hypothesis -| "double" "induction" quantified_hypothesis quantified_hypothesis +| "simple" "induction" [ ident | num ] +| "simple" "destruct" [ ident | num ] +| "double" "induction" [ ident | num ] [ ident | num ] | "admit" -| "fix" ident num -| "cofix" ident | "clear" LIST0 ident | "clear" "-" LIST1 ident | "clearbody" LIST1 ident | "generalize" "dependent" one_term -| "replace" one_term "with" one_term clause_dft_concl by_arg_tac -| "replace" "->" one_term clause_dft_concl -| "replace" "<-" one_term clause_dft_concl -| "replace" one_term clause_dft_concl -| "simplify_eq" -| "simplify_eq" destruction_arg -| "esimplify_eq" -| "esimplify_eq" destruction_arg -| "discriminate" -| "discriminate" destruction_arg -| "ediscriminate" -| "ediscriminate" destruction_arg -| "injection" -| "injection" destruction_arg -| "einjection" -| "einjection" destruction_arg -| "injection" "as" LIST0 simple_intropattern -| "injection" destruction_arg "as" LIST0 simple_intropattern -| "einjection" "as" LIST0 simple_intropattern -| "einjection" destruction_arg "as" LIST0 simple_intropattern -| "simple" "injection" -| "simple" "injection" destruction_arg -| "dependent" "rewrite" orient one_term -| "dependent" "rewrite" orient one_term "in" ident -| "cutrewrite" orient one_term -| "cutrewrite" orient one_term "in" ident +| "replace" one_term "with" one_term OPT clause_dft_concl OPT ( "by" ltac_expr3 ) +| "replace" OPT [ "->" | "<-" ] one_term OPT clause_dft_concl +| "simplify_eq" OPT destruction_arg +| "esimplify_eq" OPT destruction_arg +| "discriminate" OPT destruction_arg +| "ediscriminate" OPT destruction_arg +| "injection" OPT destruction_arg OPT ( "as" LIST0 simple_intropattern ) +| "einjection" OPT destruction_arg OPT ( "as" LIST0 simple_intropattern ) +| "simple" "injection" OPT destruction_arg +| "dependent" "rewrite" OPT [ "->" | "<-" ] one_term OPT ( "in" ident ) +| "cutrewrite" OPT [ "->" | "<-" ] one_term OPT ( "in" ident ) | "decompose" "sum" one_term | "decompose" "record" one_term | "absurd" one_term | "contradiction" OPT constr_with_bindings -| "autorewrite" "with" LIST1 ident clause_dft_concl -| "autorewrite" "with" LIST1 ident clause_dft_concl "using" ltac_expr -| "autorewrite" "*" "with" LIST1 ident clause_dft_concl -| "autorewrite" "*" "with" LIST1 ident clause_dft_concl "using" ltac_expr -| "rewrite" "*" orient one_term "in" ident "at" occurrences by_arg_tac -| "rewrite" "*" orient one_term "at" occurrences "in" ident by_arg_tac -| "rewrite" "*" orient one_term "in" ident by_arg_tac -| "rewrite" "*" orient one_term "at" occurrences by_arg_tac -| "rewrite" "*" orient one_term by_arg_tac +| "autorewrite" OPT "*" "with" LIST1 ident OPT clause_dft_concl OPT ( "using" ltac_expr ) +| "rewrite" "*" OPT [ "->" | "<-" ] one_term OPT ( "in" ident ) OPT ( "at" occurrences OPT ( "by" ltac_expr3 ) ) +| "rewrite" "*" OPT [ "->" | "<-" ] one_term "at" occurrences "in" ident OPT ( "by" ltac_expr3 ) | "refine" one_term | "simple" "refine" one_term | "notypeclasses" "refine" one_term | "simple" "notypeclasses" "refine" one_term | "solve_constraints" -| "subst" LIST1 ident -| "subst" +| "subst" OPT ( LIST1 ident ) | "simple" "subst" | "evar" "(" ident ":" term ")" | "evar" one_term | "instantiate" "(" ident ":=" term ")" -| "instantiate" "(" int ":=" term ")" hloc +| "instantiate" "(" int ":=" term ")" OPT hloc | "instantiate" -| "stepl" one_term "by" ltac_expr -| "stepl" one_term -| "stepr" one_term "by" ltac_expr -| "stepr" one_term +| "stepl" one_term OPT ( "by" ltac_expr ) +| "stepr" one_term OPT ( "by" ltac_expr ) | "generalize_eqs" ident | "dependent" "generalize_eqs" ident | "generalize_eqs_vars" ident | "dependent" "generalize_eqs_vars" ident | "specialize_eqs" ident -| "hresolve_core" "(" ident ":=" one_term ")" "at" int_or_var "in" one_term -| "hresolve_core" "(" ident ":=" one_term ")" "in" one_term +| "hresolve_core" "(" ident ":=" one_term ")" OPT ( "at" int_or_var ) "in" one_term | "hget_evar" int_or_var -| "destauto" -| "destauto" "in" ident +| "destauto" OPT ( "in" ident ) | "transparent_abstract" ltac_expr3 | "transparent_abstract" ltac_expr3 "using" ident | "constr_eq" one_term one_term @@ -1468,27 +1235,24 @@ simple_tactic: [ | "show" "ltac" "profile" "cutoff" int | "show" "ltac" "profile" string | "restart_timer" OPT string -| "finish_timing" OPT string -| "finish_timing" "(" string ")" OPT string +| "finish_timing" OPT ( "(" string ")" ) OPT string | "eassumption" | "eexact" one_term -| "trivial" auto_using hintbases -| "info_trivial" auto_using hintbases -| "debug" "trivial" auto_using hintbases -| "auto" OPT int_or_var auto_using hintbases -| "info_auto" OPT int_or_var auto_using hintbases -| "debug" "auto" OPT int_or_var auto_using hintbases +| "trivial" OPT auto_using OPT hintbases +| "info_trivial" OPT auto_using OPT hintbases +| "debug" "trivial" OPT auto_using OPT hintbases +| "auto" OPT int_or_var OPT auto_using OPT hintbases +| "info_auto" OPT int_or_var OPT auto_using OPT hintbases +| "debug" "auto" OPT int_or_var OPT auto_using OPT hintbases | "prolog" "[" LIST0 one_term "]" int_or_var -| "eauto" OPT int_or_var OPT int_or_var auto_using hintbases -| "new" "auto" OPT int_or_var auto_using hintbases -| "debug" "eauto" OPT int_or_var OPT int_or_var auto_using hintbases -| "info_eauto" OPT int_or_var OPT int_or_var auto_using hintbases -| "dfs" "eauto" OPT int_or_var auto_using hintbases -| "autounfold" hintbases clause_dft_concl -| "autounfold_one" hintbases "in" ident -| "autounfold_one" hintbases -| "unify" one_term one_term -| "unify" one_term one_term "with" ident +| "eauto" OPT int_or_var OPT int_or_var OPT auto_using OPT hintbases +| "new" "auto" OPT int_or_var OPT auto_using OPT hintbases +| "debug" "eauto" OPT int_or_var OPT int_or_var OPT auto_using OPT hintbases +| "info_eauto" OPT int_or_var OPT int_or_var OPT auto_using OPT hintbases +| "dfs" "eauto" OPT int_or_var OPT auto_using OPT hintbases +| "autounfold" OPT hintbases OPT clause_dft_concl +| "autounfold_one" OPT hintbases OPT ( "in" ident ) +| "unify" one_term one_term OPT ( "with" ident ) | "convert_concl_no_check" one_term | "typeclasses" "eauto" "bfs" OPT int_or_var "with" LIST1 ident | "typeclasses" "eauto" OPT int_or_var "with" LIST1 ident @@ -1499,103 +1263,90 @@ simple_tactic: [ | "autoapply" one_term "using" ident | "autoapply" one_term "with" ident | "progress_evars" ltac_expr -| "rewrite_strat" rewstrategy -| "rewrite_db" ident "in" ident -| "rewrite_db" ident -| "substitute" orient constr_with_bindings -| "setoid_rewrite" orient constr_with_bindings -| "setoid_rewrite" orient constr_with_bindings "in" ident -| "setoid_rewrite" orient constr_with_bindings "at" occurrences -| "setoid_rewrite" orient constr_with_bindings "at" occurrences "in" ident -| "setoid_rewrite" orient constr_with_bindings "in" ident "at" occurrences -| "setoid_symmetry" -| "setoid_symmetry" "in" ident +| "rewrite_strat" rewstrategy OPT ( "in" ident ) +| "rewrite_db" ident OPT ( "in" ident ) +| "substitute" OPT [ "->" | "<-" ] constr_with_bindings +| "setoid_rewrite" OPT [ "->" | "<-" ] constr_with_bindings OPT ( "at" occurrences ) OPT ( "in" ident ) +| "setoid_rewrite" OPT [ "->" | "<-" ] constr_with_bindings "in" ident "at" occurrences +| "setoid_symmetry" OPT ( "in" ident ) | "setoid_reflexivity" | "setoid_transitivity" one_term | "setoid_etransitivity" | "decide" "equality" | "compare" one_term one_term -| "rewrite_strat" rewstrategy "in" ident -| "intros" intropattern_list_opt -| "eintros" intropattern_list_opt -| "apply" LIST1 constr_with_bindings_arg SEP "," in_hyp_as -| "eapply" LIST1 constr_with_bindings_arg SEP "," in_hyp_as -| "simple" "apply" LIST1 constr_with_bindings_arg SEP "," in_hyp_as -| "simple" "eapply" LIST1 constr_with_bindings_arg SEP "," in_hyp_as +| "intros" LIST0 intropattern +| "eintros" LIST0 intropattern +| "apply" LIST1 constr_with_bindings_arg SEP "," OPT in_hyp_as +| "eapply" LIST1 constr_with_bindings_arg SEP "," OPT in_hyp_as +| "simple" "apply" LIST1 constr_with_bindings_arg SEP "," OPT in_hyp_as +| "simple" "eapply" LIST1 constr_with_bindings_arg SEP "," OPT in_hyp_as | "elim" constr_with_bindings_arg OPT ( "using" constr_with_bindings ) | "eelim" constr_with_bindings_arg OPT ( "using" constr_with_bindings ) | "case" induction_clause_list | "ecase" induction_clause_list -| "fix" ident num "with" LIST1 fixdecl -| "cofix" ident "with" LIST1 cofixdecl +| "fix" ident num OPT ( "with" LIST1 fixdecl ) +| "cofix" ident OPT ( "with" LIST1 cofixdecl ) | "pose" bindings_with_parameters -| "pose" one_term as_name +| "pose" one_term OPT as_name | "epose" bindings_with_parameters -| "epose" one_term as_name -| "set" bindings_with_parameters clause_dft_concl -| "set" one_term as_name clause_dft_concl -| "eset" bindings_with_parameters clause_dft_concl -| "eset" one_term as_name clause_dft_concl -| "remember" one_term as_name eqn_ipat clause_dft_all -| "eremember" one_term as_name eqn_ipat clause_dft_all +| "epose" one_term OPT as_name +| "set" bindings_with_parameters OPT clause_dft_concl +| "set" one_term OPT as_name OPT clause_dft_concl +| "eset" bindings_with_parameters OPT clause_dft_concl +| "eset" one_term OPT as_name OPT clause_dft_concl +| "remember" one_term OPT as_name OPT eqn_ipat OPT clause_dft_all +| "eremember" one_term OPT as_name OPT eqn_ipat OPT clause_dft_all | "assert" "(" ident ":=" term ")" | "eassert" "(" ident ":=" term ")" -| "assert" "(" ident ":" term ")" by_tactic -| "eassert" "(" ident ":" term ")" by_tactic -| "enough" "(" ident ":" term ")" by_tactic -| "eenough" "(" ident ":" term ")" by_tactic -| "assert" one_term as_ipat by_tactic -| "eassert" one_term as_ipat by_tactic +| "assert" "(" ident ":" term ")" OPT ( "by" ltac_expr3 ) +| "eassert" "(" ident ":" term ")" OPT ( "by" ltac_expr3 ) +| "enough" "(" ident ":" term ")" OPT ( "by" ltac_expr3 ) +| "eenough" "(" ident ":" term ")" OPT ( "by" ltac_expr3 ) +| "assert" one_term OPT as_ipat OPT ( "by" ltac_expr3 ) +| "eassert" one_term OPT as_ipat OPT ( "by" ltac_expr3 ) | "pose" "proof" "(" ident ":=" term ")" | "epose" "proof" "(" ident ":=" term ")" -| "pose" "proof" term as_ipat -| "epose" "proof" term as_ipat -| "enough" one_term as_ipat by_tactic -| "eenough" one_term as_ipat by_tactic -| "generalize" one_term -| "generalize" one_term LIST1 one_term -| "generalize" one_term OPT ( "at" occs_nums ) as_name LIST0 [ "," pattern_occ as_name ] +| "pose" "proof" term OPT as_ipat +| "epose" "proof" term OPT as_ipat +| "enough" one_term OPT as_ipat OPT ( "by" ltac_expr3 ) +| "eenough" one_term OPT as_ipat OPT ( "by" ltac_expr3 ) +| "generalize" one_term OPT ( LIST1 one_term ) +| "generalize" one_term OPT ( "at" occs_nums ) OPT as_name LIST0 [ "," pattern_occ OPT as_name ] | "induction" induction_clause_list | "einduction" induction_clause_list | "destruct" induction_clause_list | "edestruct" induction_clause_list -| "rewrite" LIST1 oriented_rewriter SEP "," clause_dft_concl by_tactic -| "erewrite" LIST1 oriented_rewriter SEP "," clause_dft_concl by_tactic -| "dependent" [ "simple" "inversion" | "inversion" | "inversion_clear" ] quantified_hypothesis as_or_and_ipat OPT [ "with" one_term ] -| "simple" "inversion" quantified_hypothesis as_or_and_ipat in_hyp_list -| "inversion" quantified_hypothesis as_or_and_ipat in_hyp_list -| "inversion_clear" quantified_hypothesis as_or_and_ipat in_hyp_list -| "inversion" quantified_hypothesis "using" one_term in_hyp_list -| "red" clause_dft_concl -| "hnf" clause_dft_concl -| "simpl" OPT delta_flag OPT ref_or_pattern_occ clause_dft_concl -| "cbv" OPT strategy_flag clause_dft_concl -| "cbn" OPT strategy_flag clause_dft_concl -| "lazy" OPT strategy_flag clause_dft_concl -| "compute" OPT delta_flag clause_dft_concl -| "vm_compute" OPT ref_or_pattern_occ clause_dft_concl -| "native_compute" OPT ref_or_pattern_occ clause_dft_concl -| "unfold" LIST1 unfold_occ SEP "," clause_dft_concl -| "fold" LIST1 one_term clause_dft_concl -| "pattern" LIST1 pattern_occ SEP "," clause_dft_concl -| "change" conversion clause_dft_concl -| "change_no_check" conversion clause_dft_concl +| "rewrite" LIST1 oriented_rewriter SEP "," OPT clause_dft_concl OPT ( "by" ltac_expr3 ) +| "erewrite" LIST1 oriented_rewriter SEP "," OPT clause_dft_concl OPT ( "by" ltac_expr3 ) +| "dependent" [ "simple" "inversion" | "inversion" | "inversion_clear" ] [ ident | num ] OPT as_or_and_ipat OPT [ "with" one_term ] +| "simple" "inversion" [ ident | num ] OPT as_or_and_ipat OPT ( "in" LIST1 ident ) +| "inversion" [ ident | num ] OPT as_or_and_ipat OPT ( "in" LIST1 ident ) +| "inversion_clear" [ ident | num ] OPT as_or_and_ipat OPT ( "in" LIST1 ident ) +| "inversion" [ ident | num ] "using" one_term OPT ( "in" LIST1 ident ) +| "red" OPT clause_dft_concl +| "hnf" OPT clause_dft_concl +| "simpl" OPT delta_flag OPT ref_or_pattern_occ OPT clause_dft_concl +| "cbv" OPT strategy_flag OPT clause_dft_concl +| "cbn" OPT strategy_flag OPT clause_dft_concl +| "lazy" OPT strategy_flag OPT clause_dft_concl +| "compute" OPT delta_flag OPT clause_dft_concl +| "vm_compute" OPT ref_or_pattern_occ OPT clause_dft_concl +| "native_compute" OPT ref_or_pattern_occ OPT clause_dft_concl +| "unfold" LIST1 unfold_occ SEP "," OPT clause_dft_concl +| "fold" LIST1 one_term OPT clause_dft_concl +| "pattern" LIST1 pattern_occ SEP "," OPT clause_dft_concl +| "change" conversion OPT clause_dft_concl +| "change_no_check" conversion OPT clause_dft_concl | "btauto" | "rtauto" -| "congruence" -| "congruence" int -| "congruence" "with" LIST1 one_term -| "congruence" int "with" LIST1 one_term +| "congruence" OPT int OPT ( "with" LIST1 one_term ) | "f_equal" -| "firstorder" OPT ltac_expr firstorder_using -| "firstorder" OPT ltac_expr "with" LIST1 ident -| "firstorder" OPT ltac_expr firstorder_using "with" LIST1 ident +| "firstorder" OPT ltac_expr firstorder_rhs | "gintuition" OPT ltac_expr -| "functional" "inversion" quantified_hypothesis OPT qualid (* funind plugin *) -| "functional" "induction" LIST1 one_term fun_ind_using with_names (* funind plugin *) -| "soft" "functional" "induction" LIST1 one_term fun_ind_using with_names (* funind plugin *) -| "psatz_Z" int_or_var ltac_expr (* micromega plugin *) -| "psatz_Z" ltac_expr (* micromega plugin *) +| "functional" "inversion" [ ident | num ] OPT qualid (* funind plugin *) +| "functional" "induction" LIST1 one_term OPT fun_ind_using OPT with_names (* funind plugin *) +| "soft" "functional" "induction" LIST1 one_term OPT fun_ind_using OPT with_names (* funind plugin *) +| "psatz_Z" OPT int_or_var ltac_expr | "xlia" ltac_expr (* micromega plugin *) | "xnlia" ltac_expr (* micromega plugin *) | "xnra" ltac_expr (* micromega plugin *) @@ -1605,10 +1356,8 @@ simple_tactic: [ | "sos_R" ltac_expr (* micromega plugin *) | "lra_Q" ltac_expr (* micromega plugin *) | "lra_R" ltac_expr (* micromega plugin *) -| "psatz_R" int_or_var ltac_expr (* micromega plugin *) -| "psatz_R" ltac_expr (* micromega plugin *) -| "psatz_Q" int_or_var ltac_expr (* micromega plugin *) -| "psatz_Q" ltac_expr (* micromega plugin *) +| "psatz_R" OPT int_or_var ltac_expr +| "psatz_Q" OPT int_or_var ltac_expr | "zify_iter_specs" (* micromega plugin *) | "zify_op" (* micromega plugin *) | "zify_saturate" (* micromega plugin *) @@ -1616,14 +1365,37 @@ simple_tactic: [ | "zify_elim_let" (* micromega plugin *) | "nsatz_compute" one_term (* nsatz plugin *) | "omega" (* omega plugin *) -| "protect_fv" string "in" ident (* setoid_ring plugin *) -| "protect_fv" string (* setoid_ring plugin *) +| "protect_fv" string OPT ( "in" ident ) | "ring_lookup" ltac_expr0 "[" LIST0 one_term "]" LIST1 one_term (* setoid_ring plugin *) | "field_lookup" ltac_expr "[" LIST0 one_term "]" LIST1 one_term (* setoid_ring plugin *) +| "classical_left" +| "classical_right" +| "contradict" ident +| "discrR" +| "easy" +| "exfalso" +| "inversion_sigma" +| "lia" +| "lra" +| "nia" +| "nra" +| "split_Rabs" +| "split_Rmult" +| "tauto" +| "zify" +| "assert_fails" ltac_expr3 +| "assert_succeeds" ltac_expr3 +| "field" OPT ( "[" LIST1 term "]" ) +| "field_simplify" OPT ( "[" LIST1 term "]" ) LIST1 term OPT ( "in" ident ) +| "field_simplify_eq" OPT ( "[" LIST1 term "]" ) OPT ( "in" ident ) +| "intuition" OPT ltac_expr +| "nsatz" OPT ( "with" "radicalmax" ":=" term "strategy" ":=" term "parameters" ":=" term "variables" ":=" term ) +| "psatz" term OPT int_or_var +| "ring" OPT ( "[" LIST1 term "]" ) +| "ring_simplify" OPT ( "[" LIST1 term "]" ) LIST1 term OPT ( "in" ident ) ] hloc: [ -| | "in" "|-" "*" | "in" ident | "in" "(" "Type" "of" ident ")" @@ -1632,15 +1404,6 @@ hloc: [ | "in" "(" "value" "of" ident ")" ] -rename: [ -| ident "into" ident -] - -by_arg_tac: [ -| "by" ltac_expr3 -| -] - in_clause: [ | LIST0 hypident_occ SEP "," OPT ( "|-" OPT concl_occ ) | "*" "|-" OPT concl_occ @@ -1663,7 +1426,6 @@ hypident: [ as_ipat: [ | "as" simple_intropattern -| ] or_and_intropattern_loc: [ @@ -1673,29 +1435,19 @@ or_and_intropattern_loc: [ as_or_and_ipat: [ | "as" or_and_intropattern_loc -| ] eqn_ipat: [ | "eqn" ":" naming_intropattern -| "_eqn" ":" naming_intropattern -| "_eqn" -| ] as_name: [ | "as" ident -| -] - -by_tactic: [ -| "by" ltac_expr3 -| ] rewriter: [ | "!" constr_with_bindings_arg -| [ "?" | "?" ] constr_with_bindings_arg +| "?" constr_with_bindings_arg | num "!" constr_with_bindings_arg | num [ "?" | "?" ] constr_with_bindings_arg | num constr_with_bindings_arg @@ -1703,24 +1455,19 @@ rewriter: [ ] oriented_rewriter: [ -| orient rewriter +| OPT [ "->" | "<-" ] rewriter ] induction_clause: [ -| destruction_arg as_or_and_ipat eqn_ipat opt_clause +| destruction_arg OPT as_or_and_ipat OPT eqn_ipat OPT opt_clause ] induction_clause_list: [ -| LIST1 induction_clause SEP "," OPT ( "using" constr_with_bindings ) opt_clause +| LIST1 induction_clause SEP "," OPT ( "using" constr_with_bindings ) OPT opt_clause ] auto_using: [ | "using" LIST1 one_term SEP "," -| -] - -intropattern_list_opt: [ -| LIST0 intropattern ] or_and_intropattern: [ @@ -1730,14 +1477,13 @@ or_and_intropattern: [ ] intropattern_or_list_or: [ -| intropattern_or_list_or "|" intropattern_list_opt -| intropattern_list_opt +| LIST0 intropattern LIST0 ( "|" LIST0 intropattern ) ] equality_intropattern: [ | "->" | "<-" -| "[=" intropattern_list_opt "]" +| "[=" LIST0 intropattern "]" ] naming_intropattern: [ @@ -1784,7 +1530,6 @@ comparison: [ hintbases: [ | "with" "*" | "with" LIST1 ident -| ] bindings_with_parameters: [ @@ -1794,28 +1539,19 @@ bindings_with_parameters: [ clause_dft_concl: [ | "in" in_clause | OPT ( "at" occs_nums ) -| ] clause_dft_all: [ | "in" in_clause -| ] opt_clause: [ | "in" in_clause | "at" occs_nums -| -] - -in_hyp_list: [ -| "in" LIST1 ident -| ] in_hyp_as: [ -| "in" ident as_ipat -| +| "in" ident OPT as_ipat ] simple_binder: [ @@ -1824,12 +1560,11 @@ simple_binder: [ ] fixdecl: [ -| "(" ident LIST0 simple_binder struct_annot ":" term ")" +| "(" ident LIST0 simple_binder OPT struct_annot ":" term ")" ] struct_annot: [ | "{" "struct" name "}" -| ] cofixdecl: [ @@ -1837,12 +1572,7 @@ cofixdecl: [ ] constr_with_bindings: [ -| one_term with_bindings -] - -with_bindings: [ -| "with" bindings -| +| one_term OPT ( "with" bindings ) ] destruction_arg: [ @@ -1856,11 +1586,6 @@ constr_with_bindings_arg: [ | constr_with_bindings ] -quantified_hypothesis: [ -| ident -| num -] - conversion: [ | one_term | one_term "with" one_term @@ -1871,17 +1596,14 @@ firstorder_using: [ | "using" qualid | "using" qualid "," LIST1 qualid SEP "," | "using" qualid qualid LIST0 qualid -| ] fun_ind_using: [ | "using" constr_with_bindings (* funind plugin *) -| (* funind plugin *) ] with_names: [ | "as" simple_intropattern (* funind plugin *) -| (* funind plugin *) ] occurrences: [ @@ -2029,16 +1751,11 @@ tactic_arg: [ | "eval" red_expr "in" term | "context" ident "[" term "]" | "type" "of" term -| "fresh" LIST0 fresh_id +| "fresh" LIST0 [ string | qualid ] | "type_term" one_term | "numgoals" ] -fresh_id: [ -| string -| qualid -] - tactic_arg_compat: [ | tactic_arg | term diff --git a/doc/tools/docgram/prodn.edit_mlg b/doc/tools/docgram/prodn.edit_mlg deleted file mode 100644 index 8bd8cad6b5..0000000000 --- a/doc/tools/docgram/prodn.edit_mlg +++ /dev/null @@ -1,24 +0,0 @@ -(************************************************************************) -(* * The Coq Proof Assistant / The Coq Development Team *) -(* v * Copyright INRIA, CNRS and contributors *) -(* <O___,, * (see version control and CREDITS file for authors & dates) *) -(* \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) *) -(************************************************************************) - -(* Defines additional productions and edits for use in documentation. Not compiled into Coq *) -(* Contents used to generate prodn in doc *) - -DOC_GRAMMAR - -(* todo: doesn't work, gives -ltac_match: @match_key @ltac_expr with {? %| } {+| @ltac_expr } end -instead of -ltac_match: @match_key @ltac_expr with {? %| } {+| {| @match_pattern | _ } => @ltac_expr } end - -SPLICE: [ -| match_rule -] -*) diff --git a/doc/tools/docgram/productionlist.edit_mlg b/doc/tools/docgram/productionlist.edit_mlg deleted file mode 100644 index 641ab8fbe5..0000000000 --- a/doc/tools/docgram/productionlist.edit_mlg +++ /dev/null @@ -1,14 +0,0 @@ -(************************************************************************) -(* * The Coq Proof Assistant / The Coq Development Team *) -(* v * Copyright INRIA, CNRS and contributors *) -(* <O___,, * (see version control and CREDITS file for authors & dates) *) -(* \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) *) -(************************************************************************) - -(* Defines additional productions and edits for use in documentation. Not compiled into Coq *) -(* Contents used to generate productionlists in doc *) - -DOC_GRAMMAR diff --git a/ide/coq_commands.ml b/ide/coq_commands.ml index c5883cef0d..711986c2b2 100644 --- a/ide/coq_commands.ml +++ b/ide/coq_commands.ml @@ -207,7 +207,6 @@ let state_preserving = [ "Recursive Extraction Library"; "Search"; - "SearchAbout (* deprecated *)"; "SearchHead"; "SearchPattern"; "SearchRewrite"; diff --git a/ide/microPG.ml b/ide/microPG.ml index 46d3316ef6..5a4871b70a 100644 --- a/ide/microPG.ml +++ b/ide/microPG.ml @@ -289,7 +289,6 @@ let pg = insert pg "Proof General" [mC,_c,"c"; mC,_a,"a"] [ mkE _p "p" "Print" (Callback (fun gui -> command gui "Print")); mkE _c "c" "Check" (Callback (fun gui -> command gui "Check")); mkE _b "b" "About" (Callback (fun gui -> command gui "About")); - mkE _a "a" "Search About" (Callback (fun gui -> command gui "SearchAbout")); mkE _o "o" "Search Pattern" (Callback (fun gui->command gui "SearchPattern")); mkE _l "l" "Locate" (Callback (fun gui -> command gui "Locate")); mkE _Return "RET" "match template" (Action("Templates","match")); diff --git a/interp/constrexpr.ml b/interp/constrexpr.ml index 8732b0e2c6..21f682ac0e 100644 --- a/interp/constrexpr.ml +++ b/interp/constrexpr.ml @@ -57,26 +57,8 @@ type abstraction_kind = AbsLambda | AbsPi type proj_flag = int option (** [Some n] = proj of the n-th visible argument *) -(** Representation of decimal literals that appear in Coq scripts. - We now use raw strings following the format defined by - [NumTok.t] and a separate sign flag. - - Note that this representation is not unique, due to possible - multiple leading or trailing zeros, and -0 = +0, for instances. - The reason to keep the numeral exactly as it was parsed is that - specific notations can be declared for specific numerals - (e.g. [Notation "0" := False], or [Notation "00" := (nil,nil)], or - [Notation "2e1" := ...]). Those notations, which override the - generic interpretation as numeral, use the same representation of - numeral using the Numeral constructor. So the latter should be able - to record the form of the numeral which exactly matches the - notation. *) - -type sign = SPlus | SMinus -type raw_numeral = NumTok.t - type prim_token = - | Numeral of sign * raw_numeral + | Numeral of NumTok.Signed.t | String of string type instance_expr = Glob_term.glob_level list diff --git a/interp/constrexpr_ops.ml b/interp/constrexpr_ops.ml index da5b8d9132..d4369e9bd1 100644 --- a/interp/constrexpr_ops.ml +++ b/interp/constrexpr_ops.ml @@ -48,10 +48,9 @@ let names_of_local_binders bl = are considered different here. *) let prim_token_eq t1 t2 = match t1, t2 with -| Numeral (SPlus,n1), Numeral (SPlus,n2) -| Numeral (SMinus,n1), Numeral (SMinus,n2) -> NumTok.equal n1 n2 +| Numeral n1, Numeral n2 -> NumTok.Signed.equal n1 n2 | String s1, String s2 -> String.equal s1 s2 -| (Numeral ((SPlus|SMinus),_) | String _), _ -> false +| (Numeral _ | String _), _ -> false let explicitation_eq ex1 ex2 = match ex1, ex2 with | ExplByPos (i1, id1), ExplByPos (i2, id2) -> diff --git a/interp/constrextern.ml b/interp/constrextern.ml index a16825b5c9..7a14ca3e48 100644 --- a/interp/constrextern.ml +++ b/interp/constrextern.ml @@ -354,27 +354,21 @@ let drop_implicits_in_patt cst nb_expl args = let destPrim = function { CAst.v = CPrim t } -> Some t | _ -> None let destPatPrim = function { CAst.v = CPatPrim t } -> Some t | _ -> None -let is_zero s = - let rec aux i = - Int.equal (String.length s) i || (s.[i] == '0' && aux (i+1)) - in aux 0 -let is_zero n = is_zero n.NumTok.int && is_zero n.NumTok.frac - let make_notation_gen loc ntn mknot mkprim destprim l bl = match snd ntn,List.map destprim l with (* Special case to avoid writing "- 3" for e.g. (Z.opp 3) *) - | "- _", [Some (Numeral (SPlus,p))] when not (is_zero p) -> + | "- _", [Some (Numeral p)] when not (NumTok.Signed.is_zero p) -> assert (bl=[]); mknot (loc,ntn,([mknot (loc,(InConstrEntrySomeLevel,"( _ )"),l,[])]),[]) | _ -> match decompose_notation_key ntn, l with | (InConstrEntrySomeLevel,[Terminal "-"; Terminal x]), [] -> - begin match NumTok.of_string x with - | Some n -> mkprim (loc, Numeral (SMinus,n)) + begin match NumTok.Unsigned.parse_string x with + | Some n -> mkprim (loc, Numeral (NumTok.SMinus,n)) | None -> mknot (loc,ntn,l,bl) end | (InConstrEntrySomeLevel,[Terminal x]), [] -> - begin match NumTok.of_string x with - | Some n -> mkprim (loc, Numeral (SPlus,n)) + begin match NumTok.Unsigned.parse_string x with + | Some n -> mkprim (loc, Numeral (NumTok.SPlus,n)) | None -> mknot (loc,ntn,l,bl) end | _ -> mknot (loc,ntn,l,bl) @@ -899,13 +893,10 @@ let extern_float f scopes = else if Float64.is_infinity f then CRef(q_infinity (), None) else if Float64.is_neg_infinity f then CRef(q_neg_infinity (), None) else - let sign = if Float64.sign f then SMinus else SPlus in - let s = Float64.(to_string (abs f)) in - match NumTok.of_string s with - | None -> assert false - | Some n -> - extern_prim_token_delimiter_if_required (Numeral (sign, n)) - "float" "float_scope" scopes + let s = Float64.(to_string f) in + let n = NumTok.Signed.of_string s in + extern_prim_token_delimiter_if_required (Numeral n) + "float" "float_scope" scopes (**********************************************************************) (* mapping glob_constr to constr_expr *) @@ -1085,7 +1076,7 @@ let rec extern inctx ?impargs scopes vars r = | GInt i -> extern_prim_token_delimiter_if_required - (Numeral (SPlus, NumTok.int (Uint63.to_string i))) + (Numeral (NumTok.Signed.of_int_string (Uint63.to_string i))) "int63" "int63_scope" (snd scopes) | GFloat f -> extern_float f (snd scopes) diff --git a/interp/constrintern.ml b/interp/constrintern.ml index abacadc43a..a071ba7ec9 100644 --- a/interp/constrintern.ml +++ b/interp/constrintern.ml @@ -32,6 +32,7 @@ open Notation_ops open Notation open Inductiveops open Context.Rel.Declaration +open NumTok (** constr_expr -> glob_constr translation: - it adds holes for implicit arguments @@ -1585,12 +1586,6 @@ let alias_of als = match als.alias_ids with *) -let is_zero s = - let rec aux i = - Int.equal (String.length s) i || ((s.[i] == '0' || s.[i] == '_') && aux (i+1)) - in aux 0 -let is_zero n = is_zero n.NumTok.int && is_zero n.NumTok.frac - let merge_subst s1 s2 = Id.Map.fold Id.Map.add s1 s2 let product_of_cases_patterns aliases idspl = @@ -1614,11 +1609,11 @@ let rec subst_pat_iterator y t = DAst.(map (function | RCPatOr pl -> RCPatOr (List.map (subst_pat_iterator y t) pl))) let is_non_zero c = match c with -| { CAst.v = CPrim (Numeral (SPlus, p)) } -> not (is_zero p) +| { CAst.v = CPrim (Numeral p) } -> not (NumTok.Signed.is_zero p) | _ -> false let is_non_zero_pat c = match c with -| { CAst.v = CPatPrim (Numeral (SPlus, p)) } -> not (is_zero p) +| { CAst.v = CPatPrim (Numeral p) } -> not (NumTok.Signed.is_zero p) | _ -> false let get_asymmetric_patterns = Goptions.declare_bool_option_and_ref diff --git a/interp/notation.ml b/interp/notation.ml index 4b73189ad3..6291a88bb0 100644 --- a/interp/notation.ml +++ b/interp/notation.ml @@ -21,6 +21,7 @@ open Notation_term open Glob_term open Glob_ops open Context.Named.Declaration +open NumTok (*i*) @@ -335,7 +336,7 @@ let notation_constr_key = function (* Rem: NApp(NRef ref,[]) stands for @ref *) (* Interpreting numbers (not in summary because functional objects) *) type required_module = full_path * string list -type rawnum = Constrexpr.sign * Constrexpr.raw_numeral +type rawnum = NumTok.Signed.t type prim_token_uid = string @@ -358,17 +359,13 @@ module InnerPrimToken = struct | StringInterp f, StringInterp f' -> f == f' | _ -> false - let ofNumeral s n = - let n = String.(concat "" (split_on_char '_' n)) in - match s with - | SPlus -> Bigint.of_string n - | SMinus -> Bigint.neg (Bigint.of_string n) - let do_interp ?loc interp primtok = match primtok, interp with - | Numeral (s,n), RawNumInterp interp -> interp ?loc (s,n) - | Numeral (s,{ NumTok.int = n; frac = ""; exp = "" }), - BigNumInterp interp -> interp ?loc (ofNumeral s n) + | Numeral n, RawNumInterp interp -> interp ?loc n + | Numeral n, BigNumInterp interp -> + (match NumTok.Signed.to_bigint n with + | Some n -> interp ?loc n + | None -> raise Not_found) | String s, StringInterp interp -> interp ?loc s | (Numeral _ | String _), (RawNumInterp _ | BigNumInterp _ | StringInterp _) -> raise Not_found @@ -385,10 +382,7 @@ module InnerPrimToken = struct | _ -> false let mkNumeral n = - if Bigint.is_pos_or_zero n then - Numeral (SPlus,NumTok.int (Bigint.to_string n)) - else - Numeral (SMinus,NumTok.int (Bigint.to_string (Bigint.neg n))) + Numeral (NumTok.Signed.of_bigint n) let mkString = function | None -> None @@ -425,8 +419,8 @@ exception PrimTokenNotationError of string * Environ.env * Evd.evar_map * prim_t type numnot_option = | Nop - | Warning of string - | Abstract of string + | Warning of NumTok.UnsignedNat.t + | Abstract of NumTok.UnsignedNat.t type int_ty = { uint : Names.inductive; @@ -567,7 +561,7 @@ let uninterp to_raw o (Glob_term.AnyGlobConstr n) = Some (to_raw (fst o.of_kind, c)) with | Type_errors.TypeError _ | Pretype_errors.PretypeError _ -> None (* cf. eval_constr_app *) - | NotAValidPrimToken -> None (* all other functions except big2raw *) + | NotAValidPrimToken -> None (* all other functions except NumTok.Signed.of_bigint *) end @@ -600,26 +594,6 @@ let warn_abstract_large_num = pr_qualid ty ++ strbrk " are interpreted as applications of " ++ Nametab.pr_global_env (Termops.vars_of_env (Global.env ())) f ++ strbrk ".") -(** Comparing two raw numbers (base 10, big-endian, non-negative). - A bit nasty, but not critical: only used to decide when a - number is considered as large (see warnings above). *) - -exception Comp of int - -let rec rawnum_compare s s' = - let l = String.length s and l' = String.length s' in - if l < l' then - rawnum_compare s' s - else - let d = l-l' in - try - for i = 0 to d-1 do if s.[i] != '0' then raise (Comp 1) done; - for i = d to l-1 do - let c = pervasives_compare s.[i] s'.[i-d] in - if c != 0 then raise (Comp c) - done; - 0 - with Comp c -> c - (***********************************************************************) (** ** Conversion between Coq [Decimal.int] and internal raw string *) @@ -634,32 +608,31 @@ let char_of_digit n = assert (2<=n && n<=11); Char.chr (n-2 + Char.code '0') -let coquint_of_rawnum uint str = +let coquint_of_rawnum uint n = let nil = mkConstruct (uint,1) in + match n with None -> nil | Some n -> + let str = NumTok.UnsignedNat.to_string n in let rec do_chars s i acc = if i < 0 then acc - else if s.[i] == '_' then do_chars s (i-1) acc else + else let dg = mkConstruct (uint, digit_of_char s.[i]) in do_chars s (i-1) (mkApp(dg,[|acc|])) in do_chars str (String.length str - 1) nil -let coqint_of_rawnum inds sign str = - let uint = coquint_of_rawnum inds.uint str in +let coqint_of_rawnum inds (sign,n) = + let uint = coquint_of_rawnum inds.uint (Some n) in let pos_neg = match sign with SPlus -> 1 | SMinus -> 2 in mkApp (mkConstruct (inds.int, pos_neg), [|uint|]) -let coqdecimal_of_rawnum inds sign n = - let i, f, e = NumTok.(n.int, n.frac, n.exp) in - let i = coqint_of_rawnum inds.int sign i in +let coqdecimal_of_rawnum inds n = + let i, f, e = NumTok.Signed.to_decimal_and_exponent n in + let i = coqint_of_rawnum inds.int i in let f = coquint_of_rawnum inds.int.uint f in - if e = "" then mkApp (mkConstruct (inds.decimal, 1), [|i; f|]) (* Decimal *) - else - let sign, e = match e.[1] with - | '-' -> SMinus, String.sub e 2 (String.length e - 2) - | '+' -> SPlus, String.sub e 2 (String.length e - 2) - | _ -> SPlus, String.sub e 1 (String.length e - 1) in - let e = coqint_of_rawnum inds.int sign e in + match e with + | None -> mkApp (mkConstruct (inds.decimal, 1), [|i; f|]) (* Decimal *) + | Some e -> + let e = coqint_of_rawnum inds.int e in mkApp (mkConstruct (inds.decimal, 2), [|i; f; e|]) (* DecimalExp *) let rawnum_of_coquint c = @@ -680,26 +653,23 @@ let rawnum_of_coquint c = (* To avoid ambiguities between Nil and (D0 Nil), we choose to not display Nil alone as "0" *) raise NotAValidPrimToken - else NumTok.int (Buffer.contents buf) + else NumTok.UnsignedNat.of_string (Buffer.contents buf) let rawnum_of_coqint c = match Constr.kind c with | App (c,[|c'|]) -> (match Constr.kind c with - | Construct ((_,1), _) (* Pos *) -> (SPlus, rawnum_of_coquint c') - | Construct ((_,2), _) (* Neg *) -> (SMinus, rawnum_of_coquint c') + | Construct ((_,1), _) (* Pos *) -> (SPlus,rawnum_of_coquint c') + | Construct ((_,2), _) (* Neg *) -> (SMinus,rawnum_of_coquint c') | _ -> raise NotAValidPrimToken) | _ -> raise NotAValidPrimToken let rawnum_of_decimal c = let of_ife i f e = - let sign, n = rawnum_of_coqint i in - let f = - try (rawnum_of_coquint f).NumTok.int with NotAValidPrimToken -> "" in - let e = match e with None -> "" | Some e -> match rawnum_of_coqint e with - | SPlus, e -> "e+" ^ e.NumTok.int - | SMinus, e -> "e-" ^ e.NumTok.int in - sign,{ n with NumTok.frac = f; exp = e } in + let n = rawnum_of_coqint i in + let f = try Some (rawnum_of_coquint f) with NotAValidPrimToken -> None in + let e = match e with None -> None | Some e -> Some (rawnum_of_coqint e) in + NumTok.Signed.of_decimal_and_exponent n f e in match Constr.kind c with | App (_,[|i; f|]) -> of_ife i f None | App (_,[|i; f; e|]) -> of_ife i f (Some e) @@ -789,43 +759,31 @@ let bigint_of_int63 c = | Int i -> Bigint.of_string (Uint63.to_string i) | _ -> raise NotAValidPrimToken -let big2raw n = - if Bigint.is_pos_or_zero n then - (SPlus, NumTok.int (Bigint.to_string n)) - else - (SMinus, NumTok.int (Bigint.to_string (Bigint.neg n))) - -let raw2big s n = match s with - | SPlus -> Bigint.of_string n - | SMinus -> Bigint.neg (Bigint.of_string n) - let interp o ?loc n = begin match o.warning, n with - | Warning threshold, (SPlus, { NumTok.int = n; frac = ""; exp = "" }) - when rawnum_compare n threshold >= 0 -> + | Warning threshold, n when NumTok.Signed.is_bigger_int_than n threshold -> warn_large_num o.ty_name | _ -> () end; - let c = match fst o.to_kind, n with - | Int int_ty, (s, { NumTok.int = n; frac = ""; exp = "" }) -> - coqint_of_rawnum int_ty s n - | UInt uint_ty, (SPlus, { NumTok.int = n; frac = ""; exp = "" }) -> - coquint_of_rawnum uint_ty n - | Z z_pos_ty, (s, { NumTok.int = n; frac = ""; exp = "" }) -> - z_of_bigint z_pos_ty (raw2big s n) - | Int63, (s, { NumTok.int = n; frac = ""; exp = "" }) -> - interp_int63 ?loc (raw2big s n) + let c = match fst o.to_kind, NumTok.Signed.to_int n with + | Int int_ty, Some n -> + coqint_of_rawnum int_ty n + | UInt uint_ty, Some (SPlus, n) -> + coquint_of_rawnum uint_ty (Some n) + | Z z_pos_ty, Some n -> + z_of_bigint z_pos_ty (NumTok.SignedNat.to_bigint n) + | Int63, Some n -> + interp_int63 ?loc (NumTok.SignedNat.to_bigint n) | (Int _ | UInt _ | Z _ | Int63), _ -> no_such_prim_token "number" ?loc o.ty_name - | Decimal decimal_ty, (s,n) -> coqdecimal_of_rawnum decimal_ty s n + | Decimal decimal_ty, _ -> coqdecimal_of_rawnum decimal_ty n in let env = Global.env () in let sigma = Evd.from_env env in let sigma,to_ty = Evd.fresh_global env sigma o.to_ty in let to_ty = EConstr.Unsafe.to_constr to_ty in match o.warning, snd o.to_kind with - | Abstract threshold, Direct - when rawnum_compare (snd n).NumTok.int threshold >= 0 -> + | Abstract threshold, Direct when NumTok.Signed.is_bigger_int_than n threshold -> warn_abstract_large_num (o.ty_name,o.to_ty); glob_of_constr "numeral" ?loc env sigma (mkApp (to_ty,[|c|])) | _ -> @@ -837,10 +795,10 @@ let interp o ?loc n = let uninterp o n = PrimTokenNotation.uninterp begin function - | (Int _, c) -> rawnum_of_coqint c - | (UInt _, c) -> (SPlus, rawnum_of_coquint c) - | (Z _, c) -> big2raw (bigint_of_z c) - | (Int63, c) -> big2raw (bigint_of_int63 c) + | (Int _, c) -> NumTok.Signed.of_int (rawnum_of_coqint c) + | (UInt _, c) -> NumTok.Signed.of_nat (rawnum_of_coquint c) + | (Z _, c) -> NumTok.Signed.of_bigint (bigint_of_z c) + | (Int63, c) -> NumTok.Signed.of_bigint (bigint_of_int63 c) | (Decimal _, c) -> rawnum_of_decimal c end o n end @@ -1162,8 +1120,8 @@ let find_notation ntn sc = NotationMap.find ntn (find_scope sc).notations let notation_of_prim_token = function - | Numeral (SPlus,n) -> InConstrEntrySomeLevel, NumTok.to_string n - | Numeral (SMinus,n) -> InConstrEntrySomeLevel, "- "^NumTok.to_string n + | Numeral (SPlus,n) -> InConstrEntrySomeLevel, NumTok.Unsigned.sprint n + | Numeral (SMinus,n) -> InConstrEntrySomeLevel, "- "^NumTok.Unsigned.sprint n | String _ -> raise Not_found let find_prim_token check_allowed ?loc p sc = diff --git a/interp/notation.mli b/interp/notation.mli index 8fcf9dc5dc..892eba8d11 100644 --- a/interp/notation.mli +++ b/interp/notation.mli @@ -81,7 +81,7 @@ val find_delimiters_scope : ?loc:Loc.t -> delimiters -> scope_name type notation_location = (DirPath.t * DirPath.t) * string type required_module = full_path * string list -type rawnum = Constrexpr.sign * Constrexpr.raw_numeral +type rawnum = NumTok.Signed.t (** The unique id string below will be used to refer to a particular registered interpreter/uninterpreter of numeral or string notation. @@ -116,8 +116,8 @@ exception PrimTokenNotationError of string * Environ.env * Evd.evar_map * prim_t type numnot_option = | Nop - | Warning of string - | Abstract of string + | Warning of NumTok.UnsignedNat.t + | Abstract of NumTok.UnsignedNat.t type int_ty = { uint : Names.inductive; diff --git a/interp/numTok.ml b/interp/numTok.ml index c11acdc8bd..e254e9e972 100644 --- a/interp/numTok.ml +++ b/interp/numTok.ml @@ -8,55 +8,243 @@ (* * (see LICENSE file for the text of the license) *) (************************************************************************) -type t = { - int : string; - frac : string; - exp : string -} - -let equal n1 n2 = - String.(equal n1.int n2.int && equal n1.frac n2.frac && equal n1.exp n2.exp) - -let int s = { int = s; frac = ""; exp = "" } - -let to_string n = n.int ^ (if n.frac = "" then "" else "." ^ n.frac) ^ n.exp - -let parse = - let buff = ref (Bytes.create 80) in - let store len x = - let open Bytes in - if len >= length !buff then - buff := cat !buff (create (length !buff)); - set !buff len x; - succ len in - let get_buff len = Bytes.sub_string !buff 0 len in - (* reads [0-9_]* *) - let rec number len s = match Stream.peek s with - | Some (('0'..'9' | '_') as c) -> Stream.junk s; number (store len c) s - | _ -> len in - fun s -> - let i = get_buff (number 0 s) in - let f = - match Stream.npeek 2 s with - | '.' :: (('0'..'9' | '_') as c) :: _ -> - Stream.junk s; Stream.junk s; get_buff (number (store 0 c) s) - | _ -> "" in - let e = - match (Stream.npeek 2 s) with - | (('e'|'E') as e) :: ('0'..'9' as c) :: _ -> - Stream.junk s; Stream.junk s; get_buff (number (store (store 0 e) c) s) - | (('e'|'E') as e) :: (('+'|'-') as sign) :: _ -> - begin match Stream.npeek 3 s with - | _ :: _ :: ('0'..'9' as c) :: _ -> - Stream.junk s; Stream.junk s; Stream.junk s; - get_buff (number (store (store (store 0 e) sign) c) s) - | _ -> "" - end - | _ -> "" in - { int = i; frac = f; exp = e } - -let of_string s = - if s = "" || s.[0] < '0' || s.[0] > '9' then None else - let strm = Stream.of_string (s ^ " ") in - let n = parse strm in - if Stream.count strm >= String.length s then Some n else None +(** We keep the string to preserve the user representation, + e.g. "e"/"E" or the presence of leading 0s, or the presence of a + + in the exponent *) + +module UnsignedNat = +struct + type t = string + let of_string s = + assert (String.length s > 0); + assert (s.[0] >= '0' && s.[0] <= '9'); + s + let to_string s = + String.(concat "" (split_on_char '_' s)) + + let sprint s = s + let print s = Pp.str (sprint s) + + (** Comparing two raw numbers (base 10, big-endian, non-negative). + A bit nasty, but not critical: used e.g. to decide when a number + is considered as large (see threshold warnings in notation.ml). *) + + exception Comp of int + + let rec compare s s' = + let l = String.length s and l' = String.length s' in + if l < l' then - compare s' s + else + let d = l-l' in + try + for i = 0 to d-1 do if s.[i] != '0' then raise (Comp 1) done; + for i = d to l-1 do + let c = Util.pervasives_compare s.[i] s'.[i-d] in + if c != 0 then raise (Comp c) + done; + 0 + with Comp c -> c + + let is_zero s = + compare s "0" = 0 +end + +type sign = SPlus | SMinus + +module SignedNat = +struct + type t = sign * UnsignedNat.t + let of_string s = + assert (String.length s > 0); + let sign,n = + match s.[0] with + | '-' -> (SMinus,String.sub s 1 (String.length s - 1)) + | '+' -> (SPlus,String.sub s 1 (String.length s - 1)) + | _ -> (SPlus,s) in + (sign,UnsignedNat.of_string n) + let to_string (sign,n) = + (match sign with SPlus -> "" | SMinus -> "-") ^ UnsignedNat.to_string n + let to_bigint n = Bigint.of_string (to_string n) + let of_bigint n = + let sign, n = if Bigint.is_strictly_neg n then (SMinus, Bigint.neg n) else (SPlus, n) in + (sign, Bigint.to_string n) +end + +module Unsigned = +struct + + type t = { + int : string; (** \[0-9\]\[0-9_\]* *) + frac : string; (** empty or \[0-9_\]+ *) + exp : string (** empty or \[eE\]\[+-\]?\[0-9\]\[0-9_\]* *) + } + + let equal n1 n2 = + String.(equal n1.int n2.int && equal n1.frac n2.frac && equal n1.exp n2.exp) + + let parse = + let buff = ref (Bytes.create 80) in + let store len x = + let open Bytes in + if len >= length !buff then + buff := cat !buff (create (length !buff)); + set !buff len x; + succ len in + let get_buff len = Bytes.sub_string !buff 0 len in + (* reads [0-9_]* *) + let rec number len s = match Stream.peek s with + | Some ('0'..'9' as c) -> Stream.junk s; number (store len c) s + | Some ('_' as c) when len > 0 -> Stream.junk s; number (store len c) s + | _ -> len in + fun s -> + let i = get_buff (number 0 s) in + assert (i <> ""); + let f = + match Stream.npeek 2 s with + | '.' :: (('0'..'9' | '_') as c) :: _ -> + Stream.junk s; Stream.junk s; get_buff (number (store 0 c) s) + | _ -> "" in + let e = + match (Stream.npeek 2 s) with + | (('e'|'E') as e) :: ('0'..'9' as c) :: _ -> + Stream.junk s; Stream.junk s; get_buff (number (store (store 0 e) c) s) + | (('e'|'E') as e) :: (('+'|'-') as sign) :: _ -> + begin match Stream.npeek 3 s with + | _ :: _ :: ('0'..'9' as c) :: _ -> + Stream.junk s; Stream.junk s; Stream.junk s; + get_buff (number (store (store (store 0 e) sign) c) s) + | _ -> "" + end + | _ -> "" in + { int = i; frac = f; exp = e } + + let sprint n = + n.int ^ (if n.frac = "" then "" else "." ^ n.frac) ^ n.exp + + let print n = + Pp.str (sprint n) + + let parse_string s = + if s = "" || s.[0] < '0' || s.[0] > '9' then None else + let strm = Stream.of_string (s ^ " ") in + let n = parse strm in + if Stream.count strm >= String.length s then Some n else None + + let of_string s = + match parse_string s with + | None -> assert false + | Some s -> s + + let to_string = + sprint (* We could remove the '_' but not necessary for float_of_string *) + + let to_nat = function + | { int = i; frac = ""; exp = "" } -> Some i + | _ -> None + + let is_nat = function + | { int = _; frac = ""; exp = "" } -> true + | _ -> false + +end + +open Unsigned + +module Signed = +struct + + type t = sign * Unsigned.t + + let equal (s1,n1) (s2,n2) = + s1 = s2 && equal n1 n2 + + let is_zero = function + | (SPlus,{int;frac;exp}) -> UnsignedNat.is_zero int && UnsignedNat.is_zero frac + | _ -> false + + let of_decimal_and_exponent (sign,int) f e = + let exp = match e with Some e -> "e" ^ SignedNat.to_string e | None -> "" in + let frac = match f with Some f -> UnsignedNat.to_string f | None -> "" in + sign, { int; frac; exp } + + let to_decimal_and_exponent (sign, { int; frac; exp }) = + let e = + if exp = "" then None else + Some (match exp.[1] with + | '-' -> SMinus, String.sub exp 2 (String.length exp - 2) + | '+' -> SPlus, String.sub exp 2 (String.length exp - 2) + | _ -> SPlus, String.sub exp 1 (String.length exp - 1)) in + let f = if frac = "" then None else Some frac in + (sign, int), f, e + + let of_nat i = + (SPlus,{ int = i; frac = ""; exp = "" }) + + let of_int (s,i) = + (s,{ int = i; frac = ""; exp = "" }) + + let of_int_string s = of_int (SignedNat.of_string s) + + let to_int = function + | (s, { int = i; frac = ""; exp = "" }) -> Some (s,i) + | _ -> None + + let is_int n = match to_int n with None -> false | Some _ -> true + + let sprint (s,i) = + (match s with SPlus -> "" | SMinus -> "-") ^ Unsigned.sprint i + + let print i = + Pp.str (sprint i) + + let parse_string s = + if s = "" || s = "-" || s = "+" || + (s.[0] < '0' || s.[0] > '9') && ((s.[0] <> '-' && s.[0] <> '+') || s.[1] < '0' || s.[1] > '9') then None else + let strm = Stream.of_string (s ^ " ") in + let sign = match s.[0] with + | '-' -> (Stream.junk strm; SMinus) + | '+' -> (Stream.junk strm; SPlus) + | _ -> SPlus in + let n = parse strm in + if Stream.count strm >= String.length s then Some (sign,n) else None + + let of_string s = + assert (s <> ""); + let sign,u = match s.[0] with + | '-' -> (SMinus, String.sub s 1 (String.length s - 1)) + | '+' -> (SPlus, String.sub s 1 (String.length s - 1)) + | _ -> (SPlus, s) in + (sign, Unsigned.of_string u) + + let to_string (sign,u) = + (match sign with SPlus -> "" | SMinus -> "-") ^ Unsigned.to_string u + + let to_bigint = function + | (sign, { int = n; frac = ""; exp = "" }) -> + Some (SignedNat.to_bigint (sign,UnsignedNat.to_string n)) + | _ -> None + + let of_bigint n = + let sign, int = SignedNat.of_bigint n in + (sign, { int; frac = ""; exp = "" }) + + let to_bigint_and_exponent (s, { int; frac; exp }) = + let s = match s with SPlus -> "" | SMinus -> "-" in + let int = UnsignedNat.to_string int in + let frac = UnsignedNat.to_string frac in + let i = Bigint.of_string (s ^ int ^ frac) in + let e = + let e = if exp = "" then Bigint.zero else match exp.[1] with + | '+' -> Bigint.of_string (UnsignedNat.to_string (String.sub exp 2 (String.length exp - 2))) + | '-' -> Bigint.(neg (of_string (UnsignedNat.to_string (String.sub exp 2 (String.length exp - 2))))) + | _ -> Bigint.of_string (UnsignedNat.to_string (String.sub exp 1 (String.length exp - 1))) in + Bigint.(sub e (of_int (String.length (String.concat "" (String.split_on_char '_' frac))))) in + (i,e) + + let of_bigint_and_exponent i e = + of_decimal_and_exponent (SignedNat.of_bigint i) None (Some (SignedNat.of_bigint e)) + + let is_bigger_int_than (s, { int; frac; exp }) i = + frac = "" && exp = "" && UnsignedNat.compare int i >= 0 + +end diff --git a/interp/numTok.mli b/interp/numTok.mli index 141f1be889..ea289df237 100644 --- a/interp/numTok.mli +++ b/interp/numTok.mli @@ -8,21 +8,125 @@ (* * (see LICENSE file for the text of the license) *) (************************************************************************) -type t = { - int : string; (** \[0-9\]\[0-9_\]* *) - frac : string; (** empty or \[0-9_\]+ *) - exp : string (** empty or \[eE\]\[+-\]?\[0-9\]\[0-9_\]* *) -} +(** Numerals in different forms: signed or unsigned, possibly with + fractional part and exponent. -val equal : t -> t -> bool + Numerals are represented using raw strings of decimal + literals and a separate sign flag. -(** [int s] amounts to [\{ int = s; frac = ""; exp = "" \}] *) -val int : string -> t + Note that this representation is not unique, due to possible + multiple leading or trailing zeros, and -0 = +0, for instances. + The reason to keep the numeral exactly as it was parsed is that + specific notations can be declared for specific numerals + (e.g. [Notation "0" := False], or [Notation "00" := (nil,nil)], or + [Notation "2e1" := ...]). Those notations override the generic + interpretation as numeral. So, one has to record the form of the + numeral which exactly matches the notation. *) -val to_string : t -> string +type sign = SPlus | SMinus -val of_string : string -> t option +(** {6 String representation of a natural number } *) -(** Precondition: the first char on the stream is a digit (\[0-9\]). - Precondition: at least two extra chars after the numeral to parse. *) -val parse : char Stream.t -> t +module UnsignedNat : +sig + type t + val of_string : string -> t + (** Convert from a non-empty sequence of digits (which may contain "_") *) + + val to_string : t -> string + (** Convert to a non-empty sequence of digit that does not contain "_" *) + + val sprint : t -> string + val print : t -> Pp.t + (** [sprint] and [print] returns the numeral as it was parsed, for printing *) + + val compare : t -> t -> int +end + +(** {6 String representation of a signed natural number } *) + +module SignedNat : +sig + type t = sign * UnsignedNat.t + val of_string : string -> t + (** Convert from a non-empty sequence of digits which may contain "_" *) + + val to_string : t -> string + (** Convert to a non-empty sequence of digit that does not contain "_" *) + + val to_bigint : t -> Bigint.bigint + val of_bigint : Bigint.bigint -> t +end + +(** {6 Unsigned decimal numerals } *) + +module Unsigned : +sig + type t + val equal : t -> t -> bool + val is_nat : t -> bool + val to_nat : t -> string option + + val sprint : t -> string + val print : t -> Pp.t + (** [sprint] and [print] returns the numeral as it was parsed, for printing *) + + val parse : char Stream.t -> t + (** Parse a positive Coq numeral. + Precondition: the first char on the stream is already known to be a digit (\[0-9\]). + Precondition: at least two extra chars after the numeral to parse. + + The recognized syntax is: + - integer part: \[0-9\]\[0-9_\]* + - decimal part: empty or .\[0-9_\]+ + - exponent part: empty or \[eE\]\[+-\]?\[0-9\]\[0-9_\]* *) + + val parse_string : string -> t option + (** Parse the string as a positive Coq numeral, if possible *) + +end + +(** {6 Signed decimal numerals } *) + +module Signed : +sig + type t = sign * Unsigned.t + val equal : t -> t -> bool + val is_zero : t -> bool + val of_nat : UnsignedNat.t -> t + val of_int : SignedNat.t -> t + val to_int : t -> SignedNat.t option + val is_int : t -> bool + + val sprint : t -> string + val print : t -> Pp.t + (** [sprint] and [print] returns the numeral as it was parsed, for printing *) + + val parse_string : string -> t option + (** Parse the string as a signed Coq numeral, if possible *) + + val of_int_string : string -> t + (** Convert from a string in the syntax of OCaml's int/int64 *) + + val of_string : string -> t + (** Convert from a string in the syntax of OCaml's string_of_float *) + + val to_string : t -> string + (** Returns a string in the syntax of OCaml's float_of_string *) + + val of_bigint : Bigint.bigint -> t + val to_bigint : t -> Bigint.bigint option + (** Convert from and to bigint when the denotation of a bigint *) + + val of_decimal_and_exponent : SignedNat.t -> UnsignedNat.t option -> SignedNat.t option -> t + val to_decimal_and_exponent : t -> SignedNat.t * UnsignedNat.t option * SignedNat.t option + (** n, p and q such that the number is n.p*10^q *) + + val to_bigint_and_exponent : t -> Bigint.bigint * Bigint.bigint + val of_bigint_and_exponent : Bigint.bigint -> Bigint.bigint -> t + (** n and p such that the number is n*10^p *) + + val is_bigger_int_than : t -> UnsignedNat.t -> bool + (** Test if an integer whose absolute value is bounded *) + +end diff --git a/kernel/byterun/coq_gc.h b/kernel/byterun/coq_gc.h deleted file mode 100644 index 38eda4d11f..0000000000 --- a/kernel/byterun/coq_gc.h +++ /dev/null @@ -1,59 +0,0 @@ -/***********************************************************************/ -/* */ -/* Coq Compiler */ -/* */ -/* Benjamin Gregoire, projets Logical and Cristal */ -/* INRIA Rocquencourt */ -/* */ -/* */ -/***********************************************************************/ - -#ifndef _COQ_CAML_GC_ -#define _COQ_CAML_GC_ -#include <caml/mlvalues.h> -#include <caml/alloc.h> -#include <caml/memory.h> - -typedef void (*scanning_action) (value, value *); - - -CAMLextern char *young_ptr; -CAMLextern char *young_limit; -CAMLextern void (*scan_roots_hook) (scanning_action); -CAMLextern void minor_collection (void); - -#define Caml_white (0 << 8) -#define Caml_black (3 << 8) - -#ifdef HAS_OCP_MEMPROF - -/* This code is necessary to make the OCamlPro memory profiling branch of - OCaml compile. */ - -#define Make_header(wosize, tag, color) \ - caml_make_header(wosize, tag, color) - -#else - -#define Make_header(wosize, tag, color) \ - (((header_t) (((header_t) (wosize) << 10) \ - + (color) \ - + (tag_t) (tag))) \ - ) -#endif - -#define Alloc_small(result, wosize, tag) do{ \ - young_ptr -= Bhsize_wosize (wosize); \ - if (young_ptr < young_limit){ \ - young_ptr += Bhsize_wosize (wosize); \ - Setup_for_gc; \ - minor_collection (); \ - Restore_after_gc; \ - young_ptr -= Bhsize_wosize (wosize); \ - } \ - Hd_hp (young_ptr) = Make_header ((wosize), (tag), Caml_black); \ - (result) = Val_hp (young_ptr); \ - }while(0) - - -#endif /*_COQ_CAML_GC_ */ diff --git a/kernel/byterun/coq_interp.c b/kernel/byterun/coq_interp.c index 606cce0127..7588c1ce07 100644 --- a/kernel/byterun/coq_interp.c +++ b/kernel/byterun/coq_interp.c @@ -16,17 +16,37 @@ #include <stdio.h> #include <signal.h> #include <stdint.h> +#include <math.h> + +#define CAML_INTERNALS #include <caml/memory.h> #include <caml/signals.h> #include <caml/version.h> -#include <math.h> -#include "coq_gc.h" + #include "coq_instruct.h" #include "coq_fix_code.h" #include "coq_memory.h" #include "coq_values.h" #include "coq_float64.h" +#if OCAML_VERSION < 41000 +extern void caml_minor_collection(void); + +#undef Alloc_small +#define Alloc_small(result, wosize, tag) do{ \ + caml_young_ptr -= Bhsize_wosize(wosize); \ + if (caml_young_ptr < caml_young_limit) { \ + caml_young_ptr += Bhsize_wosize(wosize); \ + Setup_for_gc; \ + caml_minor_collection(); \ + Restore_after_gc; \ + caml_young_ptr -= Bhsize_wosize(wosize); \ + } \ + Hd_hp(caml_young_ptr) = Make_header((wosize), (tag), Caml_black); \ + (result) = Val_hp(caml_young_ptr); \ + }while(0) +#endif + #ifdef ARCH_SIXTYFOUR #include "coq_uint63_native.h" #else diff --git a/kernel/byterun/coq_memory.c b/kernel/byterun/coq_memory.c index 91d6773b1f..6233675c66 100644 --- a/kernel/byterun/coq_memory.c +++ b/kernel/byterun/coq_memory.c @@ -10,9 +10,12 @@ #include <stdio.h> #include <string.h> + +#define CAML_INTERNALS #include <caml/alloc.h> #include <caml/address_class.h> -#include "coq_gc.h" +#include <caml/roots.h> + #include "coq_instruct.h" #include "coq_fix_code.h" #include "coq_memory.h" diff --git a/kernel/float64.ml b/kernel/float64.ml index 299f53e8ab..53fc13b04b 100644 --- a/kernel/float64.ml +++ b/kernel/float64.ml @@ -21,12 +21,19 @@ let is_neg_infinity f = f = neg_infinity (* Printing a binary64 float in 17 decimal places and parsing it again will yield the same float. We assume [to_string_raw] is not given a - [nan] as input. *) + [nan] or an infinity as input. *) let to_string_raw f = Printf.sprintf "%.17g" f (* OCaml gives a sign to nan values which should not be displayed as - all NaNs are considered equal here *) -let to_string f = if is_nan f then "nan" else to_string_raw f + all NaNs are considered equal here. + OCaml prints infinities as "inf" (resp. "-inf") + but we want "infinity" (resp. "neg_infinity"). *) +let to_string f = + if is_nan f then "nan" + else if is_infinity f then "infinity" + else if is_neg_infinity f then "neg_infinity" + else to_string_raw f + let of_string = float_of_string (* Compiles a float to OCaml code *) diff --git a/kernel/kernel.mllib b/kernel/kernel.mllib index f1e994b337..cc9da3a2ce 100644 --- a/kernel/kernel.mllib +++ b/kernel/kernel.mllib @@ -27,7 +27,7 @@ Conv_oracle Environ Primred CClosure -Retypeops +Relevanceops Reduction Clambda Nativelambda diff --git a/kernel/modops.ml b/kernel/modops.ml index 5dd5499a26..301af328e4 100644 --- a/kernel/modops.ml +++ b/kernel/modops.ml @@ -382,21 +382,21 @@ let inline_delta_resolver env inl mp mbid mtb delta = let rec make_inline delta = function | [] -> delta | (lev,kn)::r -> - let kn = replace_mp_in_kn (MPbound mbid) mp kn in - let con = constant_of_delta_kn delta kn in - try - let constant = lookup_constant con env in - let l = make_inline delta r in - match constant.const_body with - | Undef _ | OpaqueDef _ | Primitive _ -> l - | Def body -> - let constr = Mod_subst.force_constr body in - let ctx = Declareops.constant_polymorphic_context constant in - let constr = Univ.{univ_abstracted_value=constr; univ_abstracted_binder=ctx} in - add_inline_delta_resolver kn (lev, Some constr) l - with Not_found -> - error_no_such_label_sub (Constant.label con) - (ModPath.to_string (Constant.modpath con)) + let kn = replace_mp_in_kn (MPbound mbid) mp kn in + let con = constant_of_delta_kn delta kn in + if not (Environ.mem_constant con env) then + error_no_such_label_sub (Constant.label con) + (ModPath.to_string (Constant.modpath con)) + else + let constant = lookup_constant con env in + let l = make_inline delta r in + match constant.const_body with + | Undef _ | OpaqueDef _ | Primitive _ -> l + | Def body -> + let constr = Mod_subst.force_constr body in + let ctx = Declareops.constant_polymorphic_context constant in + let constr = Univ.{univ_abstracted_value=constr; univ_abstracted_binder=ctx} in + add_inline_delta_resolver kn (lev, Some constr) l in make_inline delta constants diff --git a/kernel/reduction.ml b/kernel/reduction.ml index 5fbe501169..469d5ccaa2 100644 --- a/kernel/reduction.ml +++ b/kernel/reduction.ml @@ -331,7 +331,7 @@ let skip_pattern infos n c1 c2 = let is_irrelevant infos lft c = let env = info_env infos.cnv_inf in - try Retypeops.relevance_of_fterm env infos.relevances lft c == Sorts.Irrelevant with _ -> false + try Relevanceops.relevance_of_fterm env infos.relevances lft c == Sorts.Irrelevant with _ -> false (* Conversion between [lft1]term1 and [lft2]term2 *) let rec ccnv cv_pb l2r infos lft1 lft2 term1 term2 cuniv = diff --git a/kernel/retypeops.ml b/kernel/relevanceops.ml index 3f3e722245..3f3e722245 100644 --- a/kernel/retypeops.ml +++ b/kernel/relevanceops.ml diff --git a/kernel/retypeops.mli b/kernel/relevanceops.mli index 86734e747e..86734e747e 100644 --- a/kernel/retypeops.mli +++ b/kernel/relevanceops.mli diff --git a/kernel/term_typing.ml b/kernel/term_typing.ml index 0c89d51033..c8c2301171 100644 --- a/kernel/term_typing.ml +++ b/kernel/term_typing.ml @@ -143,7 +143,7 @@ let infer_declaration env (dcl : constant_entry) = Cooking.cook_body = def; cook_type = typ; cook_universes = univs; - cook_relevance = Retypeops.relevance_of_term env j.uj_val; + cook_relevance = Relevanceops.relevance_of_term env j.uj_val; cook_inline = c.const_entry_inline_code; cook_context = c.const_entry_secctx; } diff --git a/parsing/cLexer.ml b/parsing/cLexer.ml index 6a436fbcb7..a39da96a53 100644 --- a/parsing/cLexer.ml +++ b/parsing/cLexer.ml @@ -723,7 +723,7 @@ let rec next_token ~diff_mode loc s = let ep = Stream.count s in IDENT id, set_loc_pos loc bp ep end | Some ('0'..'9') -> - let n = NumTok.parse s in + let n = NumTok.Unsigned.parse s in let ep = Stream.count s in comment_stop bp; (NUMERAL n, set_loc_pos loc bp ep) @@ -813,7 +813,7 @@ let token_text : type c. c Tok.p -> string = function | PIDENT None -> "identifier" | PIDENT (Some t) -> "'" ^ t ^ "'" | PNUMERAL None -> "numeral" - | PNUMERAL (Some n) -> "'" ^ NumTok.to_string n ^ "'" + | PNUMERAL (Some n) -> "'" ^ NumTok.Unsigned.sprint n ^ "'" | PSTRING None -> "string" | PSTRING (Some s) -> "STRING \"" ^ s ^ "\"" | PLEFTQMARK -> "LEFTQMARK" @@ -888,6 +888,6 @@ let terminal s = else PKEYWORD s (* Precondition: the input is a numeral (c.f. [NumTok.t]) *) -let terminal_numeral s = match NumTok.of_string s with +let terminal_numeral s = match NumTok.Unsigned.parse_string s with | Some n -> PNUMERAL (Some n) | None -> failwith "numeral token expected." diff --git a/parsing/cLexer.mli b/parsing/cLexer.mli index 3ce6981879..2c1284c4db 100644 --- a/parsing/cLexer.mli +++ b/parsing/cLexer.mli @@ -50,7 +50,7 @@ val check_keyword : string -> unit val terminal : string -> string Tok.p (** Precondition: the input is a numeral (c.f. [NumTok.t]) *) -val terminal_numeral : string -> NumTok.t Tok.p +val terminal_numeral : string -> NumTok.Unsigned.t Tok.p (** The lexer of Coq: *) diff --git a/parsing/g_constr.mlg b/parsing/g_constr.mlg index 3fd756e748..963f029766 100644 --- a/parsing/g_constr.mlg +++ b/parsing/g_constr.mlg @@ -174,7 +174,7 @@ GRAMMAR EXTEND Gram { (* Preserve parentheses around numerals so that constrintern does not collapse -(3) into the numeral -3. *) (match c.CAst.v with - | CPrim (Numeral (SPlus,n)) -> + | CPrim (Numeral (NumTok.SPlus,n)) -> CAst.make ~loc @@ CNotation(None,(InConstrEntrySomeLevel,"( _ )"),([c],[],[],[])) | _ -> c) } | "{|"; c = record_declaration; bar_cbrace -> { c } @@ -248,7 +248,7 @@ GRAMMAR EXTEND Gram atomic_constr: [ [ g = global; i = univ_instance -> { CAst.make ~loc @@ CRef (g,i) } | s = sort -> { CAst.make ~loc @@ CSort s } - | n = NUMERAL-> { CAst.make ~loc @@ CPrim (Numeral (SPlus,n)) } + | n = NUMERAL-> { CAst.make ~loc @@ CPrim (Numeral (NumTok.SPlus,n)) } | 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) } @@ -355,12 +355,12 @@ GRAMMAR EXTEND Gram { (* Preserve parentheses around numerals so that constrintern does not collapse -(3) into the numeral -3. *) match p.CAst.v with - | CPatPrim (Numeral (SPlus,n)) -> + | CPatPrim (Numeral (NumTok.SPlus,n)) -> CAst.make ~loc @@ CPatNotation(None,(InConstrEntrySomeLevel,"( _ )"),([p],[]),[]) | _ -> p } | "("; p = pattern LEVEL "200"; "|" ; pl = LIST1 pattern LEVEL "200" SEP "|"; ")" -> { CAst.make ~loc @@ CPatOr (p::pl) } - | n = NUMERAL-> { CAst.make ~loc @@ CPatPrim (Numeral (SPlus,n)) } + | n = NUMERAL-> { CAst.make ~loc @@ CPatPrim (Numeral (NumTok.SPlus,n)) } | s = string -> { CAst.make ~loc @@ CPatPrim (String s) } ] ] ; fixannot: diff --git a/parsing/g_prim.mlg b/parsing/g_prim.mlg index e8e802f606..9c50109bb3 100644 --- a/parsing/g_prim.mlg +++ b/parsing/g_prim.mlg @@ -21,15 +21,18 @@ let _ = List.iter CLexer.add_keyword prim_kw let local_make_qualid loc l id = make_qualid ~loc (DirPath.make l) id -let check_int loc = function - | { NumTok.int = i; frac = ""; exp = "" } -> i - | _ -> CErrors.user_err ~loc (Pp.str "This number is not an integer.") - -let my_int_of_string loc s = +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.") + CErrors.user_err ?loc (Pp.str "This number is too large.") + +let my_to_nat_string ?loc ispos s = + match NumTok.Unsigned.to_nat s with + | Some n -> n + | None -> + let pos = if ispos then "a natural" else "an integer" in + CErrors.user_err ?loc Pp.(str "This number is not " ++ str pos ++ str " number.") let test_pipe_closedcurly = let open Pcoq.Lookahead in @@ -47,7 +50,7 @@ let test_minus_nat = GRAMMAR EXTEND Gram GLOBAL: - bigint natural integer identref name ident var preident + bignat 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 bar_cbrace; @@ -122,15 +125,18 @@ GRAMMAR EXTEND Gram [ [ s = string -> { CAst.make ~loc s } ] ] ; integer: - [ [ i = NUMERAL -> { my_int_of_string loc (check_int loc i) } - | test_minus_nat; "-"; i = NUMERAL -> { - my_int_of_string loc (check_int loc i) } ] ] + [ [ i = bigint -> { my_int_of_string ~loc i } ] ] ; natural: - [ [ i = NUMERAL -> { my_int_of_string loc (check_int loc i) } ] ] + [ [ i = bignat -> { my_int_of_string ~loc i } ] ] ; - bigint: (* Negative numbers are dealt with elsewhere *) - [ [ i = NUMERAL -> { check_int loc i } ] ] + bigint: + [ [ i = NUMERAL -> { my_to_nat_string true ~loc i } + | test_minus_nat; "-"; i = NUMERAL -> { "-" ^ my_to_nat_string ~loc false i } ] ] ; + bignat: + [ [ i = NUMERAL -> { my_to_nat_string ~loc true i } ] ] + ; bar_cbrace: [ [ test_pipe_closedcurly; "|"; "}" -> { () } ] ] ; diff --git a/parsing/pcoq.ml b/parsing/pcoq.ml index fe2412fcd7..b3f997e1b3 100644 --- a/parsing/pcoq.ml +++ b/parsing/pcoq.ml @@ -166,7 +166,7 @@ struct | _ -> None let lk_nat tok n strm = match stream_nth n strm with - | Tok.NUMERAL { NumTok.int = _; frac = ""; exp = "" } -> Some (n + 1) + | Tok.NUMERAL p when NumTok.Unsigned.is_nat p -> Some (n + 1) | _ -> None let rec lk_list lk_elem n strm = @@ -462,6 +462,7 @@ module Prim = let ident = gec_gen "ident" let natural = gec_gen "natural" let integer = gec_gen "integer" + let bignat = Entry.create "Prim.bignat" let bigint = Entry.create "Prim.bigint" let string = gec_gen "string" let lstring = Entry.create "Prim.lstring" diff --git a/parsing/pcoq.mli b/parsing/pcoq.mli index cd97ea20fa..87c7f168ce 100644 --- a/parsing/pcoq.mli +++ b/parsing/pcoq.mli @@ -171,6 +171,7 @@ module Prim : val pattern_ident : Id.t Entry.t val pattern_identref : lident Entry.t val base_ident : Id.t Entry.t + val bignat : string Entry.t val natural : int Entry.t val bigint : string Entry.t val integer : int Entry.t diff --git a/parsing/tok.ml b/parsing/tok.ml index ff4433f18c..b1ceab8822 100644 --- a/parsing/tok.ml +++ b/parsing/tok.ml @@ -17,7 +17,7 @@ type 'c p = | PPATTERNIDENT : string option -> string p | PIDENT : string option -> string p | PFIELD : string option -> string p - | PNUMERAL : NumTok.t option -> NumTok.t p + | PNUMERAL : NumTok.Unsigned.t option -> NumTok.Unsigned.t p | PSTRING : string option -> string p | PLEFTQMARK : unit p | PBULLET : string option -> string p @@ -31,7 +31,7 @@ let pattern_strings : type c. c p -> string * string option = | PIDENT s -> "IDENT", s | PFIELD s -> "FIELD", s | PNUMERAL None -> "NUMERAL", None - | PNUMERAL (Some n) -> "NUMERAL", Some (NumTok.to_string n) + | PNUMERAL (Some n) -> "NUMERAL", Some (NumTok.Unsigned.sprint n) | PSTRING s -> "STRING", s | PLEFTQMARK -> "LEFTQMARK", None | PBULLET s -> "BULLET", s @@ -43,7 +43,7 @@ type t = | PATTERNIDENT of string | IDENT of string | FIELD of string - | NUMERAL of NumTok.t + | NUMERAL of NumTok.Unsigned.t | STRING of string | LEFTQMARK | BULLET of string @@ -59,7 +59,7 @@ let equal_p (type a b) (t1 : a p) (t2 : b p) : (a, b) Util.eq option = | PIDENT s1, PIDENT s2 when streq s1 s2 -> Some Util.Refl | PFIELD s1, PFIELD s2 when streq s1 s2 -> Some Util.Refl | PNUMERAL None, PNUMERAL None -> Some Util.Refl - | PNUMERAL (Some n1), PNUMERAL (Some n2) when NumTok.equal n1 n2 -> Some Util.Refl + | PNUMERAL (Some n1), PNUMERAL (Some n2) when NumTok.Unsigned.equal n1 n2 -> Some Util.Refl | PSTRING s1, PSTRING s2 when streq s1 s2 -> Some Util.Refl | PLEFTQMARK, PLEFTQMARK -> Some Util.Refl | PBULLET s1, PBULLET s2 when streq s1 s2 -> Some Util.Refl @@ -73,7 +73,7 @@ let equal t1 t2 = match t1, t2 with | PATTERNIDENT s1, PATTERNIDENT s2 -> string_equal s1 s2 | IDENT s1, IDENT s2 -> string_equal s1 s2 | FIELD s1, FIELD s2 -> string_equal s1 s2 -| NUMERAL n1, NUMERAL n2 -> NumTok.equal n1 n2 +| NUMERAL n1, NUMERAL n2 -> NumTok.Unsigned.equal n1 n2 | STRING s1, STRING s2 -> string_equal s1 s2 | LEFTQMARK, LEFTQMARK -> true | BULLET s1, BULLET s2 -> string_equal s1 s2 @@ -100,7 +100,7 @@ let extract_string diff_mode = function else s | PATTERNIDENT s -> s | FIELD s -> if diff_mode then "." ^ s else s - | NUMERAL n -> NumTok.to_string n + | NUMERAL n -> NumTok.Unsigned.sprint n | LEFTQMARK -> "?" | BULLET s -> s | QUOTATION(_,s) -> s @@ -124,7 +124,7 @@ let match_pattern (type c) (p : c p) : t -> c = let err () = raise Stream.Failure in let seq = string_equal in match p with - | PKEYWORD s -> (function KEYWORD s' when seq s s' -> s' | NUMERAL n when seq s (NumTok.to_string n) -> s | _ -> err ()) + | PKEYWORD s -> (function KEYWORD s' when seq s s' -> s' | NUMERAL n when seq s (NumTok.Unsigned.sprint n) -> s | _ -> err ()) | PIDENT None -> (function IDENT s' -> s' | _ -> err ()) | PIDENT (Some s) -> (function (IDENT s' | KEYWORD s') when seq s s' -> s' | _ -> err ()) | PPATTERNIDENT None -> (function PATTERNIDENT s -> s | _ -> err ()) @@ -132,7 +132,7 @@ let match_pattern (type c) (p : c p) : t -> c = | PFIELD None -> (function FIELD s -> s | _ -> err ()) | PFIELD (Some s) -> (function FIELD s' when seq s s' -> s' | _ -> err ()) | PNUMERAL None -> (function NUMERAL s -> s | _ -> err ()) - | PNUMERAL (Some n) -> let s = NumTok.to_string n in (function NUMERAL n' when s = NumTok.to_string n' -> n' | _ -> err ()) + | PNUMERAL (Some n) -> let s = NumTok.Unsigned.sprint n in (function NUMERAL n' when s = NumTok.Unsigned.sprint n' -> n' | _ -> err ()) | PSTRING None -> (function STRING s -> s | _ -> err ()) | PSTRING (Some s) -> (function STRING s' when seq s s' -> s' | _ -> err ()) | PLEFTQMARK -> (function LEFTQMARK -> () | _ -> err ()) diff --git a/parsing/tok.mli b/parsing/tok.mli index 6d0691a746..b556194eb3 100644 --- a/parsing/tok.mli +++ b/parsing/tok.mli @@ -15,7 +15,7 @@ type 'c p = | PPATTERNIDENT : string option -> string p | PIDENT : string option -> string p | PFIELD : string option -> string p - | PNUMERAL : NumTok.t option -> NumTok.t p + | PNUMERAL : NumTok.Unsigned.t option -> NumTok.Unsigned.t p | PSTRING : string option -> string p | PLEFTQMARK : unit p | PBULLET : string option -> string p @@ -29,7 +29,7 @@ type t = | PATTERNIDENT of string | IDENT of string | FIELD of string - | NUMERAL of NumTok.t + | NUMERAL of NumTok.Unsigned.t | STRING of string | LEFTQMARK | BULLET of string diff --git a/plugins/ltac/g_tactic.mlg b/plugins/ltac/g_tactic.mlg index 5bfbe7a49a..6a158bde17 100644 --- a/plugins/ltac/g_tactic.mlg +++ b/plugins/ltac/g_tactic.mlg @@ -125,7 +125,7 @@ let destruction_arg_of_constr (c,lbind as clbind) = match lbind with | _ -> ElimOnConstr clbind let mkNumeral n = - Numeral ((if 0<=n then SPlus else SMinus),NumTok.int (string_of_int (abs n))) + Numeral (NumTok.Signed.of_int_string (string_of_int n)) let mkTacCase with_evar = function | [(clear,ElimOnConstr cl),(None,None),None],None -> @@ -185,10 +185,6 @@ let merge_occurrences loc cl = function in (Some p, ans) -let warn_deprecated_eqn_syntax = - CWarnings.create ~name:"deprecated-eqn-syntax" ~category:"deprecated" - (fun arg -> strbrk (Printf.sprintf "Syntax \"_eqn:%s\" is deprecated. Please use \"eqn:%s\" instead." arg arg)) - (* Auxiliary grammar rules *) open Pvernac.Vernac_ @@ -461,10 +457,6 @@ GRAMMAR EXTEND Gram ; eqn_ipat: [ [ IDENT "eqn"; ":"; pat = naming_intropattern -> { Some (CAst.make ~loc pat) } - | IDENT "_eqn"; ":"; pat = naming_intropattern -> - { warn_deprecated_eqn_syntax ~loc "H"; Some (CAst.make ~loc pat) } - | IDENT "_eqn" -> - { warn_deprecated_eqn_syntax ~loc "?"; Some (CAst.make ~loc IntroAnonymous) } | -> { None } ] ] ; as_name: diff --git a/plugins/micromega/certificate.ml b/plugins/micromega/certificate.ml index 824abdaf89..1958fff4cc 100644 --- a/plugins/micromega/certificate.ml +++ b/plugins/micromega/certificate.ml @@ -651,10 +651,10 @@ let z_cert_of_pos pos = in simplify_cone z_spec (_cert_of_pos pos) -open Mutils (** All constraints (initial or derived) have an index and have a justification i.e., proof. Given a constraint, all the coefficients are always integers. *) +open Mutils open Polynomial diff --git a/plugins/micromega/certificate.mli b/plugins/micromega/certificate.mli index d8c9ade04d..cabd36ebb7 100644 --- a/plugins/micromega/certificate.mli +++ b/plugins/micromega/certificate.mli @@ -10,36 +10,36 @@ module Mc = Micromega -val use_simplex : bool ref (** [use_simplex] is bound to the Coq option Simplex. If set, use the Simplex method, otherwise use Fourier *) +val use_simplex : bool ref type ('prf, 'model) res = Prf of 'prf | Model of 'model | Unknown type zres = (Mc.zArithProof, int * Mc.z list) res type qres = (Mc.q Mc.psatz, int * Mc.q list) res -val dump_file : string option ref (** [dump_file] is bound to the Coq option Dump Arith. If set to some [file], arithmetic goals are dumped in filexxx.v *) +val dump_file : string option ref -val q_cert_of_pos : Sos_types.positivstellensatz -> Mc.q Mc.psatz (** [q_cert_of_pos prf] converts a Sos proof into a rational Coq proof *) +val q_cert_of_pos : Sos_types.positivstellensatz -> Mc.q Mc.psatz -val z_cert_of_pos : Sos_types.positivstellensatz -> Mc.z Mc.psatz (** [z_cert_of_pos prf] converts a Sos proof into an integer Coq proof *) +val z_cert_of_pos : Sos_types.positivstellensatz -> Mc.z Mc.psatz -val lia : bool -> int -> (Mc.z Mc.pExpr * Mc.op1) list -> zres (** [lia enum depth sys] generates an unsat proof for the linear constraints in [sys]. If the Simplex option is set, any failure to find a proof should be considered as a bug. *) +val lia : bool -> int -> (Mc.z Mc.pExpr * Mc.op1) list -> zres -val nlia : bool -> int -> (Mc.z Mc.pExpr * Mc.op1) list -> zres (** [nlia enum depth sys] generates an unsat proof for the non-linear constraints in [sys]. The solver is incomplete -- the problem is undecidable *) +val nlia : bool -> int -> (Mc.z Mc.pExpr * Mc.op1) list -> zres -val linear_prover_with_cert : int -> (Mc.q Mc.pExpr * Mc.op1) list -> qres (** [linear_prover_with_cert depth sys] generates an unsat proof for the linear constraints in [sys]. Over the rationals, the solver is complete. *) +val linear_prover_with_cert : int -> (Mc.q Mc.pExpr * Mc.op1) list -> qres -val nlinear_prover : int -> (Mc.q Mc.pExpr * Mc.op1) list -> qres (** [nlinear depth sys] generates an unsat proof for the non-linear constraints in [sys]. The solver is incompete -- the problem is decidable. *) +val nlinear_prover : int -> (Mc.q Mc.pExpr * Mc.op1) list -> qres diff --git a/plugins/micromega/coq_micromega.ml b/plugins/micromega/coq_micromega.ml index 82f8b5b3e2..43f6f5a35e 100644 --- a/plugins/micromega/coq_micromega.ml +++ b/plugins/micromega/coq_micromega.ml @@ -1476,6 +1476,9 @@ let parse_goal gl parse_arith (env : Env.t) hyps term = let lhyps, env, tg = parse_hyps gl parse_arith env tg hyps in (lhyps, f, env) +(** + * The datastructures that aggregate theory-dependent proof values. + *) type ('synt_c, 'prf) domain_spec = { typ : EConstr.constr ; (* is the type of the interpretation domain - Z, Q, R*) @@ -1485,9 +1488,6 @@ type ('synt_c, 'prf) domain_spec = ; proof_typ : EConstr.constr ; dump_proof : 'prf -> EConstr.constr ; coeff_eq : 'synt_c -> 'synt_c -> bool } -(** - * The datastructures that aggregate theory-dependent proof values. - *) let zz_domain_spec = lazy diff --git a/plugins/micromega/coq_micromega.mli b/plugins/micromega/coq_micromega.mli index f2f7fd424f..679290891d 100644 --- a/plugins/micromega/coq_micromega.mli +++ b/plugins/micromega/coq_micromega.mli @@ -24,5 +24,5 @@ val print_lia_profile : unit -> unit (** {5 Use Micromega independently from tactics. } *) -val dump_proof_term : Micromega.zArithProof -> EConstr.t (** [dump_proof_term] generates the Coq representation of a Micromega proof witness *) +val dump_proof_term : Micromega.zArithProof -> EConstr.t diff --git a/plugins/micromega/mfourier.ml b/plugins/micromega/mfourier.ml index 5ed7d9865e..3d1770a541 100644 --- a/plugins/micromega/mfourier.ml +++ b/plugins/micromega/mfourier.ml @@ -17,8 +17,8 @@ open Vect let debug = false let compare_float (p : float) q = pervasives_compare p q -open Itv (** Implementation of intervals *) +open Itv type vector = Vect.t @@ -47,8 +47,8 @@ and cstr_info = {bound : interval; prf : proof; pos : int; neg : int} [v] is an upper-bound of the set of variables which appear in [s]. *) -exception SystemContradiction of proof (** To be thrown when a system has no solution *) +exception SystemContradiction of proof (** Pretty printing *) let rec pp_proof o prf = diff --git a/plugins/micromega/mutils.mli b/plugins/micromega/mutils.mli index 146860ca00..09d55cf073 100644 --- a/plugins/micromega/mutils.mli +++ b/plugins/micromega/mutils.mli @@ -26,8 +26,8 @@ end module IMap : sig include Map.S with type key = int - val from : key -> 'elt t -> 'elt t (** [from k m] returns the submap of [m] with keys greater or equal k *) + val from : key -> 'elt t -> 'elt t end module Cmp : sig diff --git a/plugins/micromega/persistent_cache.mli b/plugins/micromega/persistent_cache.mli index 16d3f0a517..08e8c53757 100644 --- a/plugins/micromega/persistent_cache.mli +++ b/plugins/micromega/persistent_cache.mli @@ -14,25 +14,25 @@ module type PHashtable = sig type 'a t type key - val open_in : string -> 'a t (** [open_in f] rebuilds a table from the records stored in file [f]. As marshaling is not type-safe, it might segfault. *) + val open_in : string -> 'a t - val find : 'a t -> key -> 'a (** find has the specification of Hashtable.find *) + val find : 'a t -> key -> 'a - val add : 'a t -> key -> 'a -> unit (** [add tbl key elem] adds the binding [key] [elem] to the table [tbl]. (and writes the binding to the file associated with [tbl].) If [key] is already bound, raises KeyAlreadyBound *) + val add : 'a t -> key -> 'a -> unit - val memo : string -> (key -> 'a) -> key -> 'a (** [memo cache f] returns a memo function for [f] using file [cache] as persistent table. Note that the cache will only be loaded when the function is used for the first time *) + val memo : string -> (key -> 'a) -> key -> 'a - val memo_cond : string -> (key -> bool) -> (key -> 'a) -> key -> 'a (** [memo cache cond f] only use the cache if [cond k] holds for the key [k]. *) + val memo_cond : string -> (key -> bool) -> (key -> 'a) -> key -> 'a end module PHashtable (Key : HashedType) : PHashtable with type key = Key.t diff --git a/plugins/micromega/polynomial.mli b/plugins/micromega/polynomial.mli index bdd77440bb..9c09f76691 100644 --- a/plugins/micromega/polynomial.mli +++ b/plugins/micromega/polynomial.mli @@ -17,52 +17,52 @@ val max_nb_cstr : int ref type var = int module Monomial : sig - type t (** A monomial is represented by a multiset of variables *) + type t - val fold : (var -> int -> 'a -> 'a) -> t -> 'a -> 'a (** [fold f m acc] folds over the variables with multiplicities *) + val fold : (var -> int -> 'a -> 'a) -> t -> 'a -> 'a - val degree : t -> int (** [degree m] is the sum of the degrees of each variable *) + val degree : t -> int - val const : t (** [const] @return the empty monomial i.e. without any variable *) + val const : t val is_const : t -> bool - val var : var -> t (** [var x] @return the monomial x^1 *) + val var : var -> t - val prod : t -> t -> t (** [prod n m] @return the monomial n*m *) + val prod : t -> t -> t - val sqrt : t -> t option (** [sqrt m] @return [Some r] iff r^2 = m *) + val sqrt : t -> t option - val is_var : t -> bool (** [is_var m] @return [true] iff m = x^1 for some variable x *) + val is_var : t -> bool - val get_var : t -> var option (** [get_var m] @return [x] iff m = x^1 for variable x *) + val get_var : t -> var option - val div : t -> t -> t * int (** [div m1 m2] @return a pair [mr,n] such that mr * (m2)^n = m1 where n is maximum *) + val div : t -> t -> t * int - val compare : t -> t -> int (** [compare m1 m2] provides a total order over monomials*) + val compare : t -> t -> int - val variables : t -> ISet.t (** [variables m] @return the set of variables with (strictly) positive multiplicities *) + val variables : t -> ISet.t end module MonMap : sig @@ -82,36 +82,36 @@ module Poly : sig type t - val constant : Q.t -> t (** [constant c] @return the constant polynomial c *) + val constant : Q.t -> t - val variable : var -> t (** [variable x] @return the polynomial 1.x^1 *) + val variable : var -> t - val addition : t -> t -> t (** [addition p1 p2] @return the polynomial p1+p2 *) + val addition : t -> t -> t - val product : t -> t -> t (** [product p1 p2] @return the polynomial p1*p2 *) + val product : t -> t -> t - val uminus : t -> t (** [uminus p] @return the polynomial -p i.e product by -1 *) + val uminus : t -> t - val get : Monomial.t -> t -> Q.t (** [get mi p] @return the coefficient ai of the monomial mi. *) + val get : Monomial.t -> t -> Q.t - val fold : (Monomial.t -> Q.t -> 'a -> 'a) -> t -> 'a -> 'a (** [fold f p a] folds f over the monomials of p with non-zero coefficient *) + val fold : (Monomial.t -> Q.t -> 'a -> 'a) -> t -> 'a -> 'a - val add : Monomial.t -> Q.t -> t -> t (** [add m n p] @return the polynomial n*m + p *) + val add : Monomial.t -> Q.t -> t -> t end type cstr = {coeffs : Vect.t; op : op; cst : Q.t} @@ -125,9 +125,9 @@ val eval_op : op -> Q.t -> Q.t -> bool val opAdd : op -> op -> op -val is_strict : cstr -> bool (** [is_strict c] @return whether the constraint is strict i.e. c.op = Gt *) +val is_strict : cstr -> bool exception Strict @@ -147,70 +147,70 @@ module LinPoly : sig This is done using the monomial tables of the module MonT. *) module MonT : sig - val clear : unit -> unit (** [clear ()] clears the mapping. *) + val clear : unit -> unit - val reserve : int -> unit (** [reserve i] reserves the integer i *) + val reserve : int -> unit - val get_fresh : unit -> int (** [get_fresh ()] return the first fresh variable *) + val get_fresh : unit -> int - val retrieve : int -> Monomial.t (** [retrieve x] @return the monomial corresponding to the variable [x] *) + val retrieve : int -> Monomial.t - val register : Monomial.t -> int (** [register m] @return the variable index for the monomial m *) + val register : Monomial.t -> int end - val linpol_of_pol : Poly.t -> t (** [linpol_of_pol p] linearise the polynomial p *) + val linpol_of_pol : Poly.t -> t - val var : var -> t (** [var x] @return 1.y where y is the variable index of the monomial x^1. *) + val var : var -> t - val coq_poly_of_linpol : (Q.t -> 'a) -> t -> 'a Mc.pExpr (** [coq_poly_of_linpol c p] @param p is a multi-variate polynomial. @param c maps a rational to a Coq polynomial coefficient. @return the coq expression corresponding to polynomial [p].*) + val coq_poly_of_linpol : (Q.t -> 'a) -> t -> 'a Mc.pExpr - val of_monomial : Monomial.t -> t (** [of_monomial m] @returns 1.x where x is the variable (index) for monomial m *) + val of_monomial : Monomial.t -> t - val of_vect : Vect.t -> t (** [of_vect v] @returns a1.x1 + ... + an.xn This is not the identity because xi is the variable index of xi^1 *) + val of_vect : Vect.t -> t - val variables : t -> ISet.t (** [variables p] @return the set of variables of the polynomial p interpreted as a multi-variate polynomial *) + val variables : t -> ISet.t - val is_variable : t -> var option (** [is_variable p] @return Some x if p = a.x for a >= 0 *) + val is_variable : t -> var option - val is_linear : t -> bool (** [is_linear p] @return whether the multi-variate polynomial is linear. *) + val is_linear : t -> bool - val is_linear_for : var -> t -> bool (** [is_linear_for x p] @return true if the polynomial is linear in x i.e can be written c*x+r where c is a constant and r is independent from x *) + val is_linear_for : var -> t -> bool - val constant : Q.t -> t (** [constant c] @return the constant polynomial c *) + val constant : Q.t -> t (** [search_linear pred p] @return a variable x such p = a.x + b such that @@ -219,44 +219,44 @@ module LinPoly : sig val search_linear : (Q.t -> bool) -> t -> var option - val search_all_linear : (Q.t -> bool) -> t -> var list (** [search_all_linear pred p] @return all the variables x such p = a.x + b such that p is linear in x i.e x does not occur in b and a is a constant such that [pred a] *) + val search_all_linear : (Q.t -> bool) -> t -> var list val get_bound : t -> Vect.Bound.t option - val product : t -> t -> t (** [product p q] @return the product of the polynomial [p*q] *) + val product : t -> t -> t - val factorise : var -> t -> t * t (** [factorise x p] @return [a,b] such that [p = a.x + b] and [x] does not occur in [b] *) + val factorise : var -> t -> t * t - val collect_square : t -> Monomial.t MonMap.t (** [collect_square p] @return a mapping m such that m[s] = s^2 for every s^2 that is a monomial of [p] *) + val collect_square : t -> Monomial.t MonMap.t - val monomials : t -> ISet.t (** [monomials p] @return the set of monomials. *) + val monomials : t -> ISet.t - val degree : t -> int (** [degree p] @return return the maximum degree *) + val degree : t -> int - val pp_var : out_channel -> var -> unit (** [pp_var o v] pretty-prints a monomial indexed by v. *) + val pp_var : out_channel -> var -> unit - val pp : out_channel -> t -> unit (** [pp o p] pretty-prints a polynomial. *) + val pp : out_channel -> t -> unit - val pp_goal : string -> out_channel -> (t * op) list -> unit (** [pp_goal typ o l] pretty-prints the list of constraints as a Coq goal. *) + val pp_goal : string -> out_channel -> (t * op) list -> unit end module ProofFormat : sig @@ -318,47 +318,47 @@ val opMult : op -> op -> op module WithProof : sig type t = (LinPoly.t * op) * ProofFormat.prf_rule - exception InvalidProof (** [InvalidProof] is raised if the operation is invalid. *) + exception InvalidProof val compare : t -> t -> int val annot : string -> t -> t val of_cstr : cstr * ProofFormat.prf_rule -> t - val output : out_channel -> t -> unit (** [out_channel chan c] pretty-prints the constraint [c] over the channel [chan] *) + val output : out_channel -> t -> unit val output_sys : out_channel -> t list -> unit - val zero : t (** [zero] represents the tautology (0=0) *) + val zero : t - val const : Q.t -> t (** [const n] represents the tautology (n>=0) *) + val const : Q.t -> t - val product : t -> t -> t (** [product p q] @return the polynomial p*q with its sign and proof *) + val product : t -> t -> t - val addition : t -> t -> t (** [addition p q] @return the polynomial p+q with its sign and proof *) + val addition : t -> t -> t - val mult : LinPoly.t -> t -> t (** [mult p q] @return the polynomial p*q with its sign and proof. @raise InvalidProof if p is not a constant and p is not an equality *) + val mult : LinPoly.t -> t -> t - val cutting_plane : t -> t option (** [cutting_plane p] does integer reasoning and adjust the constant to be integral *) + val cutting_plane : t -> t option - val linear_pivot : t list -> t -> Vect.var -> t -> t option (** [linear_pivot sys p x q] @return the polynomial [q] where [x] is eliminated using the polynomial [p] The pivoting operation is only defined if - p is linear in x i.e p = a.x+b and x neither occurs in a and b - The pivoting also requires some sign conditions for [a] *) + val linear_pivot : t list -> t -> Vect.var -> t -> t option (** [subst sys] performs the equivalent of the 'subst' tactic of Coq. For every p=0 \in sys such that p is linear in x with coefficient +/- 1 @@ -371,8 +371,8 @@ module WithProof : sig val subst : t list -> t list - val subst1 : t list -> t list (** [subst1 sys] performs a single substitution *) + val subst1 : t list -> t list val saturate_subst : bool -> t list -> t list val is_substitution : bool -> t -> var option diff --git a/plugins/micromega/simplex.ml b/plugins/micromega/simplex.ml index 702099a95d..eaa26ded62 100644 --- a/plugins/micromega/simplex.ml +++ b/plugins/micromega/simplex.ml @@ -62,9 +62,9 @@ let get_profile_info () = type iset = unit IMap.t -type tableau = Vect.t IMap.t (** Mapping basic variables to their equation. All variables >= than a threshold rst are restricted.*) +type tableau = Vect.t IMap.t module Restricted = struct type t = @@ -366,9 +366,9 @@ let push_real (opt : bool) (nw : var) (v : Vect.t) (rst : Restricted.t) let v' = safe_find "push_real" nw t' in Unsat (Vect.set nw Q.one (Vect.set 0 Q.zero (Vect.mul Q.neg_one v'))) ) -open Mutils (** One complication is that equalities needs some pre-processing. *) +open Mutils open Polynomial diff --git a/plugins/micromega/vect.ml b/plugins/micromega/vect.ml index 15f37868f7..3e0b1f2cd9 100644 --- a/plugins/micromega/vect.ml +++ b/plugins/micromega/vect.ml @@ -12,12 +12,12 @@ open NumCompat open Q.Notations open Mutils -type var = int (** [t] is the type of vectors. A vector [(x1,v1) ; ... ; (xn,vn)] is such that: - variables indexes are ordered (x1 < ... < xn - values are all non-zero *) +type var = int type mono = {var : var; coe : Q.t} type t = mono list diff --git a/plugins/micromega/vect.mli b/plugins/micromega/vect.mli index 8a26337602..9db6c075f8 100644 --- a/plugins/micromega/vect.mli +++ b/plugins/micromega/vect.mli @@ -11,10 +11,9 @@ open NumCompat open Mutils -type var = int (** Variables are simply (positive) integers. *) +type var = int -type t (** The type of vectors or equivalently linear expressions. The current implementation is using association lists. A list [(0,c),(x1,ai),...,(xn,an)] represents the linear expression @@ -24,6 +23,7 @@ type t Moreover, the representation is spare and variables with a zero coefficient are not represented. *) +type t type vector = t @@ -38,147 +38,147 @@ val compare : t -> t -> int (** {1 Basic accessors and utility functions} *) -val pp_gen : (out_channel -> var -> unit) -> out_channel -> t -> unit (** [pp_gen pp_var o v] prints the representation of the vector [v] over the channel [o] *) +val pp_gen : (out_channel -> var -> unit) -> out_channel -> t -> unit -val pp : out_channel -> t -> unit (** [pp o v] prints the representation of the vector [v] over the channel [o] *) +val pp : out_channel -> t -> unit -val pp_smt : out_channel -> t -> unit (** [pp_smt o v] prints the representation of the vector [v] over the channel [o] using SMTLIB conventions *) +val pp_smt : out_channel -> t -> unit -val variables : t -> ISet.t (** [variables v] returns the set of variables with non-zero coefficients *) +val variables : t -> ISet.t -val get_cst : t -> Q.t (** [get_cst v] returns c i.e. the coefficient of the variable zero *) +val get_cst : t -> Q.t -val decomp_cst : t -> Q.t * t (** [decomp_cst v] returns the pair (c,a1.x1+...+an.xn) *) +val decomp_cst : t -> Q.t * t -val decomp_at : int -> t -> Q.t * t (** [decomp_cst v] returns the pair (ai, ai+1.xi+...+an.xn) *) +val decomp_at : int -> t -> Q.t * t val decomp_fst : t -> (var * Q.t) * t -val cst : Q.t -> t (** [cst c] returns the vector v=c+0.x1+...+0.xn *) +val cst : Q.t -> t -val is_constant : t -> bool (** [is_constant v] holds if [v] is a constant vector i.e. v=c+0.x1+...+0.xn *) +val is_constant : t -> bool -val null : t (** [null] is the empty vector i.e. 0+0.x1+...+0.xn *) +val null : t -val is_null : t -> bool (** [is_null v] returns whether [v] is the [null] vector i.e [equal v null] *) +val is_null : t -> bool -val get : var -> t -> Q.t (** [get xi v] returns the coefficient ai of the variable [xi]. [get] is also defined for the variable 0 *) +val get : var -> t -> Q.t -val set : var -> Q.t -> t -> t (** [set xi ai' v] returns the vector c+a1.x1+...ai'.xi+...+an.xn i.e. the coefficient of the variable xi is set to ai' *) +val set : var -> Q.t -> t -> t -val mkvar : var -> t (** [mkvar xi] returns 1.xi *) +val mkvar : var -> t -val update : var -> (Q.t -> Q.t) -> t -> t (** [update xi f v] returns c+a1.x1+...+f(ai).xi+...+an.xn *) +val update : var -> (Q.t -> Q.t) -> t -> t -val fresh : t -> int (** [fresh v] return the fresh variable with index 1+ max (variables v) *) +val fresh : t -> int -val choose : t -> (var * Q.t * t) option (** [choose v] decomposes a vector [v] depending on whether it is [null] or not. @return None if v is [null] @return Some(x,n,r) where v = r + n.x x is the smallest variable with non-zero coefficient n <> 0. *) +val choose : t -> (var * Q.t * t) option -val from_list : Q.t list -> t (** [from_list l] returns the vector c+a1.x1...an.xn from the list of coefficient [l=c;a1;...;an] *) +val from_list : Q.t list -> t -val to_list : t -> Q.t list (** [to_list v] returns the list of all coefficient of the vector v i.e. [c;a1;...;an] The list representation is (obviously) not sparsed and therefore certain ai may be 0 *) +val to_list : t -> Q.t list -val decr_var : int -> t -> t (** [decr_var i v] decrements the variables of the vector [v] by the amount [i]. Beware, it is only defined if all the variables of v are greater than i *) +val decr_var : int -> t -> t -val incr_var : int -> t -> t (** [incr_var i v] increments the variables of the vector [v] by the amount [i]. *) +val incr_var : int -> t -> t -val gcd : t -> Z.t (** [gcd v] returns gcd(num(c),num(a1),...,num(an)) where num extracts the numerator of a rational value. *) +val gcd : t -> Z.t -val normalise : t -> t (** [normalise v] returns a vector with only integer coefficients *) +val normalise : t -> t (** {1 Linear arithmetics} *) -val add : t -> t -> t (** [add v1 v2] is vector addition. @param v1 is of the form c +a1.x1 +...+an.xn @param v2 is of the form c'+a1'.x1 +...+an'.xn @return c1+c1'+ (a1+a1').x1 + ... + (an+an').xn *) +val add : t -> t -> t -val mul : Q.t -> t -> t (** [mul a v] is vector multiplication of vector [v] by a scalar [a]. @return a.v = a.c+a.a1.x1+...+a.an.xn *) +val mul : Q.t -> t -> t -val mul_add : Q.t -> t -> Q.t -> t -> t (** [mul_add c1 v1 c2 v2] returns the linear combination c1.v1+c2.v2 *) +val mul_add : Q.t -> t -> Q.t -> t -> t -val subst : int -> t -> t -> t (** [subst x v v'] replaces x by v in vector v' *) +val subst : int -> t -> t -> t -val div : Q.t -> t -> t (** [div c1 v1] returns the mutiplication by the inverse of c1 i.e (1/c1).v1 *) +val div : Q.t -> t -> t -val uminus : t -> t (** [uminus v] @return -v the opposite vector of v i.e. (-1).v *) +val uminus : t -> t (** {1 Iterators} *) -val fold : ('acc -> var -> Q.t -> 'acc) -> 'acc -> t -> 'acc (** [fold f acc v] returns f (f (f acc 0 c ) x1 a1 ) ... xn an *) +val fold : ('acc -> var -> Q.t -> 'acc) -> 'acc -> t -> 'acc -val fold_error : ('acc -> var -> Q.t -> 'acc option) -> 'acc -> t -> 'acc option (** [fold_error f acc v] is the same as [fold (fun acc x i -> match acc with None -> None | Some acc' -> f acc' x i) (Some acc) v] but with early exit... *) +val fold_error : ('acc -> var -> Q.t -> 'acc option) -> 'acc -> t -> 'acc option -val find : (var -> Q.t -> 'c option) -> t -> 'c option (** [find f v] returns the first [f xi ai] such that [f xi ai <> None]. If no such xi ai exists, it returns None *) +val find : (var -> Q.t -> 'c option) -> t -> 'c option -val for_all : (var -> Q.t -> bool) -> t -> bool (** [for_all p v] returns /\_{i>=0} (f xi ai) *) +val for_all : (var -> Q.t -> bool) -> t -> bool -val exists2 : (Q.t -> Q.t -> bool) -> t -> t -> (var * Q.t * Q.t) option (** [exists2 p v v'] returns Some(xi,ai,ai') if p(xi,ai,ai') holds and ai,ai' <> 0. It returns None if no such pair of coefficient exists. *) +val exists2 : (Q.t -> Q.t -> bool) -> t -> t -> (var * Q.t * Q.t) option -val dotproduct : t -> t -> Q.t (** [dotproduct v1 v2] is the dot product of v1 and v2. *) +val dotproduct : t -> t -> Q.t val map : (var -> Q.t -> 'a) -> t -> 'a list val abs_min_elt : t -> (var * Q.t) option val partition : (var -> Q.t -> bool) -> t -> t * t module Bound : sig - type t = {cst : Q.t; var : var; coeff : Q.t} (** represents a0 + ai.xi *) + type t = {cst : Q.t; var : var; coeff : Q.t} val of_vect : vector -> t option end diff --git a/plugins/micromega/zify.ml b/plugins/micromega/zify.ml index 53a58342d2..41579d5792 100644 --- a/plugins/micromega/zify.ml +++ b/plugins/micromega/zify.ml @@ -326,20 +326,20 @@ type term_kind = Application of EConstr.constr | OtherTerm of EConstr.constr module type Elt = sig type elt - val name : string (** name *) + val name : string val table : (term_kind * decl_kind) HConstr.t ref val cast : elt decl -> decl_kind val dest : decl_kind -> elt decl option - val get_key : int (** [get_key] is the type-index used as key for the instance *) + val get_key : int - val mk_elt : Evd.evar_map -> EConstr.t -> EConstr.t array -> elt (** [mk_elt evd i [a0,..,an] returns the element of the table built from the type-instance i and the arguments (type indexes and projections) of the type-class constructor. *) + val mk_elt : Evd.evar_map -> EConstr.t -> EConstr.t array -> elt (* val arity : int*) end diff --git a/plugins/ssr/ssrparser.mlg b/plugins/ssr/ssrparser.mlg index 1dca8fd57b..442b40221b 100644 --- a/plugins/ssr/ssrparser.mlg +++ b/plugins/ssr/ssrparser.mlg @@ -350,8 +350,8 @@ let interp_index ist gl idx = | Some c -> let rc = Detyping.detype Detyping.Now false Id.Set.empty (pf_env gl) (project gl) c in begin match Notation.uninterp_prim_token rc with - | _, Constrexpr.Numeral (b,{NumTok.int = s; frac = ""; exp = ""}) -> - let n = int_of_string s in (match b with SPlus -> n | SMinus -> -n) + | _, Constrexpr.Numeral n when NumTok.Signed.is_int n -> + int_of_string (NumTok.Signed.to_string n) | _ -> raise Not_found end | None -> raise Not_found diff --git a/plugins/ssr/ssrvernac.mlg b/plugins/ssr/ssrvernac.mlg index df6189f212..4b78e64d98 100644 --- a/plugins/ssr/ssrvernac.mlg +++ b/plugins/ssr/ssrvernac.mlg @@ -402,7 +402,7 @@ let rec interp_search_about args accu = match args with | [] -> accu | (flag, arg) :: rem -> fun gr env typ -> - let ans = Search.search_about_filter arg gr env typ in + let ans = Search.search_filter arg gr env typ in (if flag then ans else not ans) && interp_search_about rem accu gr env typ let interp_search_arg arg = diff --git a/plugins/syntax/float_syntax.ml b/plugins/syntax/float_syntax.ml index 23d4d63228..e0a9906689 100644 --- a/plugins/syntax/float_syntax.ml +++ b/plugins/syntax/float_syntax.ml @@ -22,9 +22,56 @@ let make_path dir id = Libnames.make_path (make_dir dir) (Id.of_string id) (*** Parsing for float in digital notation ***) -let interp_float ?loc (sign,n) = - let sign = Constrexpr.(match sign with SPlus -> "" | SMinus -> "-") in - DAst.make ?loc (GFloat (Float64.of_string (sign ^ NumTok.to_string n))) +let warn_inexact_float = + CWarnings.create ~name:"inexact-float" ~category:"parsing" + (fun (sn, f) -> + Pp.strbrk + (Printf.sprintf + "The constant %s is not a binary64 floating-point value. \ + A closest value will be used and unambiguously printed %s." + sn (Float64.to_string f))) + +let interp_float ?loc n = + let sn = NumTok.Signed.to_string n in + let f = Float64.of_string sn in + (* return true when f is not exactly equal to n, + this is only used to decide whether or not to display a warning + and does not play any actual role in the parsing *) + let inexact () = match Float64.classify f with + | Float64.(PInf | NInf | NaN) -> true + | Float64.(PZero | NZero) -> not (NumTok.Signed.is_zero n) + | Float64.(PNormal | NNormal | PSubn | NSubn) -> + let m, e = + let (_, i), f, e = NumTok.Signed.to_decimal_and_exponent n in + let i = NumTok.UnsignedNat.to_string i in + let f = match f with + | None -> "" | Some f -> NumTok.UnsignedNat.to_string f in + let e = match e with + | None -> "0" | Some e -> NumTok.SignedNat.to_string e in + Bigint.of_string (i ^ f), + (try int_of_string e with Failure _ -> 0) - String.length f in + let m', e' = + let m', e' = Float64.frshiftexp f in + let m' = Float64.normfr_mantissa m' in + let e' = Uint63.to_int_min e' 4096 - Float64.eshift - 53 in + Bigint.of_string (Uint63.to_string m'), + e' in + let c2, c5 = Bigint.(of_int 2, of_int 5) in + (* check m*5^e <> m'*2^e' *) + let check m e m' e' = + not (Bigint.(equal (mult m (pow c5 e)) (mult m' (pow c2 e')))) in + (* check m*5^e*2^e' <> m' *) + let check' m e e' m' = + not (Bigint.(equal (mult (mult m (pow c5 e)) (pow c2 e')) m')) in + (* we now have to check m*10^e <> m'*2^e' *) + if e >= 0 then + if e <= e' then check m e m' (e' - e) + else check' m e (e - e') m' + else (* e < 0 *) + if e' <= e then check m' (-e) m (e - e') + else check' m' (-e) (e' - e) m in + if inexact () then warn_inexact_float ?loc (sn, f); + DAst.make ?loc (GFloat f) (* Pretty printing is already handled in constrextern.ml *) diff --git a/plugins/syntax/g_numeral.mlg b/plugins/syntax/g_numeral.mlg index 49d29e7b63..e66dbe17b2 100644 --- a/plugins/syntax/g_numeral.mlg +++ b/plugins/syntax/g_numeral.mlg @@ -21,16 +21,16 @@ open Pcoq.Prim let pr_numnot_option = function | Nop -> mt () - | Warning n -> str "(warning after " ++ str n ++ str ")" - | Abstract n -> str "(abstract after " ++ str n ++ str ")" + | Warning n -> str "(warning after " ++ NumTok.UnsignedNat.print n ++ str ")" + | Abstract n -> str "(abstract after " ++ NumTok.UnsignedNat.print n ++ str ")" } VERNAC ARGUMENT EXTEND numnotoption PRINTED BY { pr_numnot_option } | [ ] -> { Nop } -| [ "(" "warning" "after" bigint(waft) ")" ] -> { Warning waft } -| [ "(" "abstract" "after" bigint(n) ")" ] -> { Abstract n } +| [ "(" "warning" "after" bignat(waft) ")" ] -> { Warning (NumTok.UnsignedNat.of_string waft) } +| [ "(" "abstract" "after" bignat(n) ")" ] -> { Abstract (NumTok.UnsignedNat.of_string n) } END VERNAC COMMAND EXTEND NumeralNotation CLASSIFIED AS SIDEFF diff --git a/plugins/syntax/r_syntax.ml b/plugins/syntax/r_syntax.ml index 7043653f7b..c4e9c8b73d 100644 --- a/plugins/syntax/r_syntax.ml +++ b/plugins/syntax/r_syntax.ml @@ -12,7 +12,6 @@ open Util open Names open Glob_term open Bigint -open Constrexpr (* Poor's man DECLARE PLUGIN *) let __coq_plugin_name = "r_syntax_plugin" @@ -113,8 +112,8 @@ let z_modpath = MPdot (MPfile (make_dir binintdef), Label.make "Z") let glob_pow_pos = GlobRef.ConstRef (Constant.make2 z_modpath @@ Label.make "pow_pos") -let r_of_rawnum ?loc (sign,n) = - let n, f, e = NumTok.(n.int, n.frac, n.exp) in +let r_of_rawnum ?loc n = + let n,e = NumTok.Signed.to_bigint_and_exponent n in let izr z = DAst.make @@ GApp (DAst.make @@ GRef(glob_IZR,None), [z]) in let rmult r r' = @@ -126,15 +125,7 @@ let r_of_rawnum ?loc (sign,n) = let e = pos_of_bignat e in DAst.make @@ GApp (DAst.make @@ GRef(glob_pow_pos,None), [ten; e]) in let n = - let n = Bigint.of_string (n ^ f) in - let n = match sign with SPlus -> n | SMinus -> Bigint.(neg n) in izr (z_of_int ?loc n) in - let e = - let e = if e = "" then Bigint.zero else match e.[1] with - | '+' -> Bigint.of_string (String.sub e 2 (String.length e - 2)) - | '-' -> Bigint.(neg (of_string (String.sub e 2 (String.length e - 2)))) - | _ -> Bigint.of_string (String.sub e 1 (String.length e - 1)) in - Bigint.(sub e (of_int (String.length (String.concat "" (String.split_on_char '_' f))))) in if Bigint.is_strictly_pos e then rmult n (izr (pow10 e)) else if Bigint.is_strictly_neg e then rdiv n (izr (pow10 (neg e))) else n (* e = 0 *) @@ -143,12 +134,41 @@ let r_of_rawnum ?loc (sign,n) = (* Printing R via scopes *) (**********************************************************************) -let rawnum_of_r c = match DAst.get c with +let rawnum_of_r c = + (* print i * 10^e, precondition: e <> 0 *) + let numTok_of_int_exp i e = + (* choose between 123e-2 and 1.23, this is purely heuristic + and doesn't play any soundness role *) + let choose_exponent = + if Bigint.is_strictly_pos e then + true (* don't print 12 * 10^2 as 1200 to distinguish them *) + else + let i = Bigint.to_string i in + let li = if i.[0] = '-' then String.length i - 1 else String.length i in + let e = Bigint.neg e in + let le = String.length (Bigint.to_string e) in + Bigint.(less_than (add (of_int li) (of_int le)) e) in + (* print 123 * 10^-2 as 123e-2 *) + let numTok_exponent () = NumTok.Signed.of_bigint_and_exponent i e in + (* print 123 * 10^-2 as 1.23, precondition e < 0 *) + let numTok_dot () = + let s, i = + if Bigint.is_pos_or_zero i then NumTok.SPlus, Bigint.to_string i + else NumTok.SMinus, Bigint.(to_string (neg i)) in + let ni = String.length i in + let e = - (Bigint.to_int e) in + assert (e > 0); + let i, f = + if e < ni then String.sub i 0 (ni - e), String.sub i (ni - e) e + else "0", String.make (e - ni) '0' ^ i in + let i = s, NumTok.UnsignedNat.of_string i in + let f = NumTok.UnsignedNat.of_string f in + NumTok.Signed.of_decimal_and_exponent i (Some f) None in + if choose_exponent then numTok_exponent () else numTok_dot () in + match DAst.get c with | GApp (r, [a]) when is_gr r glob_IZR -> let n = bigint_of_z a in - let s, n = - if is_strictly_neg n then SMinus, neg n else SPlus, n in - s, NumTok.int (to_string n) + NumTok.Signed.of_bigint n | GApp (md, [l; r]) when is_gr md glob_Rmult || is_gr md glob_Rdiv -> begin match DAst.get l, DAst.get r with | GApp (i, [l]), GApp (i', [r]) @@ -161,11 +181,8 @@ let rawnum_of_r c = match DAst.get c with else let i = bigint_of_z l in let e = bignat_of_pos e in - let s, i = if is_pos_or_zero i then SPlus, i else SMinus, neg i in - let i = Bigint.to_string i in - let se = if is_gr md glob_Rdiv then "-" else "" in - let e = "e" ^ se ^ Bigint.to_string e in - s, { NumTok.int = i; frac = ""; exp = e } + let e = if is_gr md glob_Rdiv then neg e else e in + numTok_of_int_exp i e | _ -> raise Non_closed_number end | _ -> raise Non_closed_number diff --git a/pretyping/retyping.ml b/pretyping/retyping.ml index d4fa2461b4..821c57d033 100644 --- a/pretyping/retyping.ml +++ b/pretyping/retyping.ml @@ -273,8 +273,8 @@ let relevance_of_term env sigma c = | Rel n -> let len = Range.length rels in if n <= len then Range.get rels (n - 1) - else Retypeops.relevance_of_rel env (n - len) - | Var x -> Retypeops.relevance_of_var env x + else Relevanceops.relevance_of_rel env (n - len) + | Var x -> Relevanceops.relevance_of_var env x | Sort _ -> Sorts.Relevant | Cast (c, _, _) -> aux rels c | Prod ({binder_relevance=r}, _, codom) -> @@ -284,13 +284,13 @@ let relevance_of_term env sigma c = | LetIn ({binder_relevance=r}, _, _, bdy) -> aux (Range.cons r rels) bdy | App (c, _) -> aux rels c - | Const (c,_) -> Retypeops.relevance_of_constant env c + | Const (c,_) -> Relevanceops.relevance_of_constant env c | Ind _ -> Sorts.Relevant - | Construct (c,_) -> Retypeops.relevance_of_constructor env c + | Construct (c,_) -> Relevanceops.relevance_of_constructor env c | Case (ci, _, _, _) -> ci.ci_relevance | Fix ((_,i),(lna,_,_)) -> (lna.(i)).binder_relevance | CoFix (i,(lna,_,_)) -> (lna.(i)).binder_relevance - | Proj (p, _) -> Retypeops.relevance_of_projection env p + | Proj (p, _) -> Relevanceops.relevance_of_projection env p | Int _ | Float _ -> Sorts.Relevant | Meta _ | Evar _ -> Sorts.Relevant diff --git a/printing/ppconstr.ml b/printing/ppconstr.ml index 21b9cd4f1f..b285c0abcc 100644 --- a/printing/ppconstr.ml +++ b/printing/ppconstr.ml @@ -77,8 +77,8 @@ let tag_var = tag Tag.variable | LevelSome -> true let prec_of_prim_token = function - | Numeral (SPlus,_) -> lposint - | Numeral (SMinus,_) -> lnegint + | Numeral (NumTok.SPlus,_) -> lposint + | Numeral (NumTok.SMinus,_) -> lnegint | String _ -> latom let print_hunks n pr pr_patt pr_binders (terms, termlists, binders, binderlists) unps = @@ -222,8 +222,7 @@ let tag_var = tag Tag.variable | t -> str " :" ++ pr_sep_com (fun()->brk(1,4)) (pr ltop) t let pr_prim_token = function - | Numeral (SPlus,n) -> str (NumTok.to_string n) - | Numeral (SMinus,n) -> str ("-"^NumTok.to_string n) + | Numeral n -> NumTok.Signed.print n | String s -> qs s let pr_evar pr id l = diff --git a/proofs/tacmach.mli b/proofs/tacmach.mli index 19d4ed91e6..d8f7b7eed8 100644 --- a/proofs/tacmach.mli +++ b/proofs/tacmach.mli @@ -37,6 +37,7 @@ val pf_unsafe_type_of : Goal.goal sigma -> constr -> types [@@ocaml.deprecated "Use [type_of] or retyping according to your needs."] val pf_type_of : Goal.goal sigma -> constr -> evar_map * types val pf_hnf_type_of : Goal.goal sigma -> constr -> types +[@@ocaml.deprecated "This is a no-op now"] val pf_get_hyp : Goal.goal sigma -> Id.t -> named_declaration val pf_get_hyp_typ : Goal.goal sigma -> Id.t -> types @@ -49,22 +50,33 @@ val pf_eapply : (env -> evar_map -> 'a -> evar_map * 'b) -> val pf_reduce : (env -> evar_map -> constr -> constr) -> Goal.goal sigma -> constr -> constr +[@@ocaml.deprecated "Use the version in Tacmach.New"] + val pf_e_reduce : (env -> evar_map -> constr -> evar_map * constr) -> Goal.goal sigma -> constr -> evar_map * constr +[@@ocaml.deprecated "Use the version in Tacmach.New"] val pf_whd_all : Goal.goal sigma -> constr -> constr +[@@ocaml.deprecated "Use the version in Tacmach.New"] val pf_hnf_constr : Goal.goal sigma -> constr -> constr +[@@ocaml.deprecated "Use the version in Tacmach.New"] val pf_nf : Goal.goal sigma -> constr -> constr +[@@ocaml.deprecated "Use the version in Tacmach.New"] val pf_nf_betaiota : Goal.goal sigma -> constr -> constr val pf_reduce_to_quantified_ind : Goal.goal sigma -> types -> (inductive * EInstance.t) * types val pf_reduce_to_atomic_ind : Goal.goal sigma -> types -> (inductive * EInstance.t) * types +[@@ocaml.deprecated "Use Tacred.pf_reduce_to_atomic_ind"] val pf_compute : Goal.goal sigma -> constr -> constr +[@@ocaml.deprecated "Use the version in Tacmach.New"] val pf_unfoldn : (occurrences * evaluable_global_reference) list -> Goal.goal sigma -> constr -> constr +[@@ocaml.deprecated "Use Tacred.unfoldn"] val pf_const_value : Goal.goal sigma -> pconstant -> constr +[@@ocaml.deprecated "Use Environ.constant_value_in"] val pf_conv_x : Goal.goal sigma -> constr -> constr -> bool +[@@ocaml.deprecated "Use the version in Tacmach.New"] (** {6 Pretty-printing functions (debug only). } *) val pr_gls : Goal.goal sigma -> Pp.t diff --git a/tactics/proof_global.ml b/tactics/proof_global.ml index 7fd1634dcf..623e6b8a42 100644 --- a/tactics/proof_global.ml +++ b/tactics/proof_global.ml @@ -8,14 +8,6 @@ (* * (see LICENSE file for the text of the license) *) (************************************************************************) -(***********************************************************************) -(* *) -(* This module defines proof facilities relevant to the *) -(* toplevel. In particular it defines the global proof *) -(* environment. *) -(* *) -(***********************************************************************) - open Util open Names open Context diff --git a/tactics/proof_global.mli b/tactics/proof_global.mli index f1281d1291..e1c75c0649 100644 --- a/tactics/proof_global.mli +++ b/tactics/proof_global.mli @@ -8,9 +8,7 @@ (* * (see LICENSE file for the text of the license) *) (************************************************************************) -(** This module defines proof facilities relevant to the - toplevel. In particular it defines the global proof - environment. *) +(** State for interactive proofs. *) type t diff --git a/test-suite/Makefile b/test-suite/Makefile index 6696f1431e..0d8a6ebed7 100644 --- a/test-suite/Makefile +++ b/test-suite/Makefile @@ -417,14 +417,16 @@ $(addsuffix .log,$(wildcard output/*.v)): %.v.log: %.v %.out $(PREREQUISITELOG) $(HIDE){ \ echo $(call log_intro,$<); \ output=$*.out.real; \ + export LC_CTYPE=C; \ + export LANG=C; \ $(coqc_interactive) "$<" $(call get_coq_prog_args,"$<") 2>&1 \ - | grep -v "Welcome to Coq" \ - | grep -v "\[Loading ML file" \ - | grep -v "Skipping rcfile loading" \ - | grep -v "^<W>" \ + | grep -a -v "Welcome to Coq" \ + | grep -a -v "\[Loading ML file" \ + | grep -a -v "Skipping rcfile loading" \ + | grep -a -v "^<W>" \ | sed 's/File "[^"]*"/File "stdin"/' \ > $$output; \ - diff -u --strip-trailing-cr $*.out $$output 2>&1; R=$$?; times; \ + diff -a -u --strip-trailing-cr $*.out $$output 2>&1; R=$$?; times; \ if [ $$R = 0 ]; then \ echo $(log_success); \ echo " $<...Ok"; \ diff --git a/test-suite/bugs/closed/HoTT_coq_010.v b/test-suite/bugs/closed/HoTT_coq_010.v index 42b1244fb5..caa7373f5e 100644 --- a/test-suite/bugs/closed/HoTT_coq_010.v +++ b/test-suite/bugs/closed/HoTT_coq_010.v @@ -1,3 +1,3 @@ -SearchAbout and. +Search and. (* Anomaly: Mismatched instance and context when building universe substitution. Please report. *) diff --git a/test-suite/bugs/closed/bug_11845.v b/test-suite/bugs/closed/bug_11845.v new file mode 100644 index 0000000000..d27f8c4ef0 --- /dev/null +++ b/test-suite/bugs/closed/bug_11845.v @@ -0,0 +1,6 @@ + +Module Type T. Parameter Inline v : Prop. End T. + +Module F(A:T). End F. + +Fail Include F. diff --git a/test-suite/bugs/closed/bug_11890.v b/test-suite/bugs/closed/bug_11890.v new file mode 100644 index 0000000000..c0426fcfda --- /dev/null +++ b/test-suite/bugs/closed/bug_11890.v @@ -0,0 +1,10 @@ +Require Import Coq.Structures.Orders Coq.ZArith.ZArith Coq.Sorting.Mergesort. +(* Note that this has always worked fine without the '; we are testing importing notations from the stdlib here *) +Declare Module A : LeBool'. +Declare Module B : LtBool'. +Import A B NatOrder. +(* +Error: Notation "_ <=? _" is already defined at level 70 with arguments constr +at next level, constr at next level while it is now required to be at level 35 +with arguments constr at next level, constr at next level. +*) diff --git a/test-suite/bugs/closed/bug_3900.v b/test-suite/bugs/closed/bug_3900.v index 6be2161c2f..ddede74acc 100644 --- a/test-suite/bugs/closed/bug_3900.v +++ b/test-suite/bugs/closed/bug_3900.v @@ -9,5 +9,5 @@ Variable Pmor : forall s d : obj, morphism A (projT1 s) (projT1 d) -> Type. Class Foo (x : Type) := { _ : forall y, y }. Local Instance ishset_pmor {s d m} : Foo (Pmor s d m). Proof. -SearchAbout ((forall _ _, _) -> Foo _). +Search ((forall _ _, _) -> Foo _). Abort. diff --git a/test-suite/output/FloatExtraction.out b/test-suite/output/FloatExtraction.out index cfd6633752..dd8189c56f 100644 --- a/test-suite/output/FloatExtraction.out +++ b/test-suite/output/FloatExtraction.out @@ -1,3 +1,17 @@ +File "stdin", line 25, characters 8-12: +Warning: The constant 0.01 is not a binary64 floating-point value. A closest +value will be used and unambiguously printed 0.01. [inexact-float,parsing] +File "stdin", line 25, characters 20-25: +Warning: The constant -0.01 is not a binary64 floating-point value. A closest +value will be used and unambiguously printed -0.01. [inexact-float,parsing] +File "stdin", line 25, characters 27-35: +Warning: The constant 1.7e+308 is not a binary64 floating-point value. A +closest value will be used and unambiguously printed 1.6999999999999999e+308. +[inexact-float,parsing] +File "stdin", line 25, characters 37-46: +Warning: The constant -1.7e-308 is not a binary64 floating-point value. A +closest value will be used and unambiguously printed +-1.7000000000000002e-308. [inexact-float,parsing] (** val infinity : Float64.t **) diff --git a/test-suite/output/FloatSyntax.out b/test-suite/output/FloatSyntax.out index 668a55977d..7941d2e647 100644 --- a/test-suite/output/FloatSyntax.out +++ b/test-suite/output/FloatSyntax.out @@ -4,8 +4,16 @@ : float (-2.5)%float : float +File "stdin", line 9, characters 6-13: +Warning: The constant 2.5e123 is not a binary64 floating-point value. A +closest value will be used and unambiguously printed 2.4999999999999999e+123. +[inexact-float,parsing] 2.4999999999999999e+123%float : float +File "stdin", line 10, characters 7-16: +Warning: The constant -2.5e-123 is not a binary64 floating-point value. A +closest value will be used and unambiguously printed +-2.5000000000000001e-123. [inexact-float,parsing] (-2.5000000000000001e-123)%float : float (2 + 2)%float @@ -18,14 +26,34 @@ : float -2.5 : float +File "stdin", line 19, characters 6-13: +Warning: The constant 2.5e123 is not a binary64 floating-point value. A +closest value will be used and unambiguously printed 2.4999999999999999e+123. +[inexact-float,parsing] 2.4999999999999999e+123 : float +File "stdin", line 20, characters 7-16: +Warning: The constant -2.5e-123 is not a binary64 floating-point value. A +closest value will be used and unambiguously printed +-2.5000000000000001e-123. [inexact-float,parsing] -2.5000000000000001e-123 : float 2 + 2 : float 2.5 + 2.5 : float +File "stdin", line 24, characters 6-11: +Warning: The constant 1e309 is not a binary64 floating-point value. A closest +value will be used and unambiguously printed infinity. +[inexact-float,parsing] +infinity + : float +File "stdin", line 25, characters 6-12: +Warning: The constant -1e309 is not a binary64 floating-point value. A +closest value will be used and unambiguously printed neg_infinity. +[inexact-float,parsing] +neg_infinity + : float 2 : nat 2%float diff --git a/test-suite/output/FloatSyntax.v b/test-suite/output/FloatSyntax.v index 85f611352c..eca712db10 100644 --- a/test-suite/output/FloatSyntax.v +++ b/test-suite/output/FloatSyntax.v @@ -21,6 +21,9 @@ Check (-2.5e-123). Check (2 + 2). Check (2.5 + 2.5). +Check 1e309. +Check -1e309. + Open Scope nat_scope. Check 2. diff --git a/test-suite/output/NumeralNotations.out b/test-suite/output/NumeralNotations.out index 113384e9cf..060877707b 100644 --- a/test-suite/output/NumeralNotations.out +++ b/test-suite/output/NumeralNotations.out @@ -218,3 +218,19 @@ let v : ty := Build_ty Set set in v : ty : ty let v : ty := Build_ty Type type in v : ty : ty +1 + : nat +(-1000)%Z + : Z +0 + : Prop ++0 + : bool +-0 + : bool +00 + : nat * nat +1000 + : Prop +1_000 + : list nat diff --git a/test-suite/output/NumeralNotations.v b/test-suite/output/NumeralNotations.v index 22aff36d67..47e1b127cb 100644 --- a/test-suite/output/NumeralNotations.v +++ b/test-suite/output/NumeralNotations.v @@ -457,3 +457,33 @@ Module Test20. Check let v := 4%kt in v : ty. Check let v := 5%kt in v : ty. End Test20. + +Module Test21. + + Check 00001. + Check (-1_000)%Z. + +End Test21. + +Module Test22. + +Notation "0" := False. +Notation "+0" := true. +Notation "-0" := false. +Notation "00" := (0%nat, 0%nat). +Check 0. +Check +0. +Check -0. +Check 00. + +Notation "1000" := True. +Notation "1_000" := (cons 1 nil). +Check 1000. +Check 1_000. + +(* To do: preserve parsing of -0: +Require Import ZArith. +Check (-0)%Z. +*) + +End Test22. diff --git a/test-suite/output/QArithSyntax.out b/test-suite/output/QArithSyntax.out index 6bc04f1cef..fe6a1d25c6 100644 --- a/test-suite/output/QArithSyntax.out +++ b/test-suite/output/QArithSyntax.out @@ -1,14 +1,14 @@ -eq_refl : 102e-2 = 102e-2 - : 102e-2 = 102e-2 -eq_refl : 102e-1 = 102e-1 - : 102e-1 = 102e-1 +eq_refl : 1.02 = 1.02 + : 1.02 = 1.02 +eq_refl : 10.2 = 10.2 + : 10.2 = 10.2 eq_refl : 1020 = 1020 : 1020 = 1020 eq_refl : 102 = 102 : 102 = 102 -eq_refl : 102e-2 = 102e-2 - : 102e-2 = 102e-2 +eq_refl : 1.02 = 1.02 + : 1.02 = 1.02 eq_refl : -1e-4 = -1e-4 : -1e-4 = -1e-4 -eq_refl : -50e-2 = -50e-2 - : -50e-2 = -50e-2 +eq_refl : -0.50 = -0.50 + : -0.50 = -0.50 diff --git a/test-suite/output/RealSyntax.out b/test-suite/output/RealSyntax.out index 2b14ca7069..1685964b0f 100644 --- a/test-suite/output/RealSyntax.out +++ b/test-suite/output/RealSyntax.out @@ -2,19 +2,21 @@ : R (-31)%R : R -15e-1%R +1.5%R : R -eq_refl : 102e-2 = 102e-2 - : 102e-2 = 102e-2 -eq_refl : 102e-1 = 102e-1 - : 102e-1 = 102e-1 +15%R + : R +eq_refl : 1.02 = 1.02 + : 1.02 = 1.02 +eq_refl : 10.2 = 10.2 + : 10.2 = 10.2 eq_refl : 102e1 = 102e1 : 102e1 = 102e1 eq_refl : 102 = 102 : 102 = 102 -eq_refl : 102e-2 = 102e-2 - : 102e-2 = 102e-2 +eq_refl : 1.02 = 1.02 + : 1.02 = 1.02 eq_refl : -1e-4 = -1e-4 : -1e-4 = -1e-4 -eq_refl : -50e-2 = -50e-2 - : -50e-2 = -50e-2 +eq_refl : -0.50 = -0.50 + : -0.50 = -0.50 diff --git a/test-suite/output/RealSyntax.v b/test-suite/output/RealSyntax.v index 7be8b18ac8..e5f9d06316 100644 --- a/test-suite/output/RealSyntax.v +++ b/test-suite/output/RealSyntax.v @@ -3,6 +3,7 @@ Check 32%R. Check (-31)%R. Check 1.5_%R. +Check 1_.5_e1_%R. Open Scope R_scope. diff --git a/test-suite/output/allBytes.out b/test-suite/output/allBytes.out new file mode 100644 index 0000000000..8d188c4c45 --- /dev/null +++ b/test-suite/output/allBytes.out @@ -0,0 +1 @@ +!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ diff --git a/test-suite/output/allBytes.v b/test-suite/output/allBytes.v new file mode 100644 index 0000000000..01a5161ef4 --- /dev/null +++ b/test-suite/output/allBytes.v @@ -0,0 +1,121 @@ +(* Taken from bedrock2 *) + +(* Note: not an utf8 file *) + +Require Import Coq.ZArith.BinInt Coq.Lists.List. +Require Coq.Init.Byte Coq.Strings.Byte Coq.Strings.String. + +Definition allBytes: list Byte.byte := + map (fun nn => match Byte.of_N (BinNat.N.of_nat nn) with + | Some b => b + | None => Byte.x00 (* won't happen *) + end) + (seq 32 95). + +Notation "a b" := (@cons Byte.byte a b) + (only printing, right associativity, at level 3, format "a b"). + +Notation "" := (@nil Byte.byte) + (only printing, right associativity, at level 3, format ""). + +Notation " " := (Byte.x20) (only printing). +Notation "'!'" := (Byte.x21) (only printing). +Notation "'""'" := (Byte.x22) (only printing). +Notation "'#'" := (Byte.x23) (only printing). +Notation "'$'" := (Byte.x24) (only printing). +Notation "'%'" := (Byte.x25) (only printing). +Notation "'&'" := (Byte.x26) (only printing). +Notation "'''" := (Byte.x27) (only printing). +Notation "'('" := (Byte.x28) (only printing). +Notation "')'" := (Byte.x29) (only printing). +Notation "'*'" := (Byte.x2a) (only printing). +Notation "'+'" := (Byte.x2b) (only printing). +Notation "','" := (Byte.x2c) (only printing). +Notation "'-'" := (Byte.x2d) (only printing). +Notation "'.'" := (Byte.x2e) (only printing). +Notation "'/'" := (Byte.x2f) (only printing). +Notation "'0'" := (Byte.x30) (only printing). +Notation "'1'" := (Byte.x31) (only printing). +Notation "'2'" := (Byte.x32) (only printing). +Notation "'3'" := (Byte.x33) (only printing). +Notation "'4'" := (Byte.x34) (only printing). +Notation "'5'" := (Byte.x35) (only printing). +Notation "'6'" := (Byte.x36) (only printing). +Notation "'7'" := (Byte.x37) (only printing). +Notation "'8'" := (Byte.x38) (only printing). +Notation "'9'" := (Byte.x39) (only printing). +Notation "':'" := (Byte.x3a) (only printing). +Notation "';'" := (Byte.x3b) (only printing). +Notation "'<'" := (Byte.x3c) (only printing). +Notation "'='" := (Byte.x3d) (only printing). +Notation "'>'" := (Byte.x3e) (only printing). +Notation "'?'" := (Byte.x3f) (only printing). +Notation "'@'" := (Byte.x40) (only printing). +Notation "'A'" := (Byte.x41) (only printing). +Notation "'B'" := (Byte.x42) (only printing). +Notation "'C'" := (Byte.x43) (only printing). +Notation "'D'" := (Byte.x44) (only printing). +Notation "'E'" := (Byte.x45) (only printing). +Notation "'F'" := (Byte.x46) (only printing). +Notation "'G'" := (Byte.x47) (only printing). +Notation "'H'" := (Byte.x48) (only printing). +Notation "'I'" := (Byte.x49) (only printing). +Notation "'J'" := (Byte.x4a) (only printing). +Notation "'K'" := (Byte.x4b) (only printing). +Notation "'L'" := (Byte.x4c) (only printing). +Notation "'M'" := (Byte.x4d) (only printing). +Notation "'N'" := (Byte.x4e) (only printing). +Notation "'O'" := (Byte.x4f) (only printing). +Notation "'P'" := (Byte.x50) (only printing). +Notation "'Q'" := (Byte.x51) (only printing). +Notation "'R'" := (Byte.x52) (only printing). +Notation "'S'" := (Byte.x53) (only printing). +Notation "'T'" := (Byte.x54) (only printing). +Notation "'U'" := (Byte.x55) (only printing). +Notation "'V'" := (Byte.x56) (only printing). +Notation "'W'" := (Byte.x57) (only printing). +Notation "'X'" := (Byte.x58) (only printing). +Notation "'Y'" := (Byte.x59) (only printing). +Notation "'Z'" := (Byte.x5a) (only printing). +Notation "'['" := (Byte.x5b) (only printing). +Notation "'\'" := (Byte.x5c) (only printing). +Notation "']'" := (Byte.x5d) (only printing). +Notation "'^'" := (Byte.x5e) (only printing). +Notation "'_'" := (Byte.x5f) (only printing). +Notation "'`'" := (Byte.x60) (only printing). +Notation "'a'" := (Byte.x61) (only printing). +Notation "'b'" := (Byte.x62) (only printing). +Notation "'c'" := (Byte.x63) (only printing). +Notation "'d'" := (Byte.x64) (only printing). +Notation "'e'" := (Byte.x65) (only printing). +Notation "'f'" := (Byte.x66) (only printing). +Notation "'g'" := (Byte.x67) (only printing). +Notation "'h'" := (Byte.x68) (only printing). +Notation "'i'" := (Byte.x69) (only printing). +Notation "'j'" := (Byte.x6a) (only printing). +Notation "'k'" := (Byte.x6b) (only printing). +Notation "'l'" := (Byte.x6c) (only printing). +Notation "'m'" := (Byte.x6d) (only printing). +Notation "'n'" := (Byte.x6e) (only printing). +Notation "'o'" := (Byte.x6f) (only printing). +Notation "'p'" := (Byte.x70) (only printing). +Notation "'q'" := (Byte.x71) (only printing). +Notation "'r'" := (Byte.x72) (only printing). +Notation "'s'" := (Byte.x73) (only printing). +Notation "'t'" := (Byte.x74) (only printing). +Notation "'u'" := (Byte.x75) (only printing). +Notation "'v'" := (Byte.x76) (only printing). +Notation "'w'" := (Byte.x77) (only printing). +Notation "'x'" := (Byte.x78) (only printing). +Notation "'y'" := (Byte.x79) (only printing). +Notation "'z'" := (Byte.x7a) (only printing). +Notation "'{'" := (Byte.x7b) (only printing). +Notation "'|'" := (Byte.x7c) (only printing). +Notation "'}'" := (Byte.x7d) (only printing). +Notation "'~'" := (Byte.x7e) (only printing). + +Global Set Printing Width 300. + +Goal False. + let cc := eval cbv in allBytes in idtac cc. +Abort. diff --git a/test-suite/success/search.v b/test-suite/success/search.v new file mode 100644 index 0000000000..92de43e052 --- /dev/null +++ b/test-suite/success/search.v @@ -0,0 +1,35 @@ + +(** Test of the different syntaxes of Search *) + +Search plus. +Search plus mult. +Search "plus_n". +Search plus "plus_n". +Search "*". +Search "*" "+". + +Search plus inside Peano. +Search plus mult inside Peano. +Search "plus_n" inside Peano. +Search plus "plus_n" inside Peano. +Search "*" inside Peano. +Search "*" "+" inside Peano. + +Search plus outside Peano Logic. +Search plus mult outside Peano Logic. +Search "plus_n" outside Peano Logic. +Search plus "plus_n" outside Peano Logic. +Search "*" outside Peano Logic. +Search "*" "+" outside Peano Logic. + +Search -"*" "+" outside Logic. +Search -"*"%nat "+"%nat outside Logic. + + +(** The example in the Reference Manual *) + +Require Import ZArith. + +Search Z.mul Z.add "distr". +Search "+"%Z "*"%Z "distr" -positive -Prop. +Search (?x * _ + ?x * _)%Z outside OmegaLemmas. diff --git a/test-suite/success/searchabout.v b/test-suite/success/searchabout.v deleted file mode 100644 index 9edfd82556..0000000000 --- a/test-suite/success/searchabout.v +++ /dev/null @@ -1,60 +0,0 @@ - -(** Test of the different syntaxes of SearchAbout, in particular - with and without the [ ... ] delimiters *) - -SearchAbout plus. -SearchAbout plus mult. -SearchAbout "plus_n". -SearchAbout plus "plus_n". -SearchAbout "*". -SearchAbout "*" "+". - -SearchAbout plus inside Peano. -SearchAbout plus mult inside Peano. -SearchAbout "plus_n" inside Peano. -SearchAbout plus "plus_n" inside Peano. -SearchAbout "*" inside Peano. -SearchAbout "*" "+" inside Peano. - -SearchAbout plus outside Peano Logic. -SearchAbout plus mult outside Peano Logic. -SearchAbout "plus_n" outside Peano Logic. -SearchAbout plus "plus_n" outside Peano Logic. -SearchAbout "*" outside Peano Logic. -SearchAbout "*" "+" outside Peano Logic. - -SearchAbout -"*" "+" outside Logic. -SearchAbout -"*"%nat "+"%nat outside Logic. - -SearchAbout [plus]. -SearchAbout [plus mult]. -SearchAbout ["plus_n"]. -SearchAbout [plus "plus_n"]. -SearchAbout ["*"]. -SearchAbout ["*" "+"]. - -SearchAbout [plus] inside Peano. -SearchAbout [plus mult] inside Peano. -SearchAbout ["plus_n"] inside Peano. -SearchAbout [plus "plus_n"] inside Peano. -SearchAbout ["*"] inside Peano. -SearchAbout ["*" "+"] inside Peano. - -SearchAbout [plus] outside Peano Logic. -SearchAbout [plus mult] outside Peano Logic. -SearchAbout ["plus_n"] outside Peano Logic. -SearchAbout [plus "plus_n"] outside Peano Logic. -SearchAbout ["*"] outside Peano Logic. -SearchAbout ["*" "+"] outside Peano Logic. - -SearchAbout [-"*" "+"] outside Logic. -SearchAbout [-"*"%nat "+"%nat] outside Logic. - - -(** The example in the Reference Manual *) - -Require Import ZArith. - -SearchAbout Z.mul Z.add "distr". -SearchAbout "+"%Z "*"%Z "distr" -positive -Prop. -SearchAbout (?x * _ + ?x * _)%Z outside OmegaLemmas. diff --git a/theories/Init/Decimal.v b/theories/Init/Decimal.v index 10c3baa2cd..855db8bc3f 100644 --- a/theories/Init/Decimal.v +++ b/theories/Init/Decimal.v @@ -156,6 +156,37 @@ Definition nztail_int d := | Neg d => let (r, n) := nztail d in pair (Neg r) n end. +(** [del_head n d] removes [n] digits at beginning of [d] + or returns [zero] if [d] has less than [n] digits. *) + +Fixpoint del_head n d := + match n with + | O => d + | S n => + match d with + | Nil => zero + | D0 d | D1 d | D2 d | D3 d | D4 d | D5 d | D6 d | D7 d | D8 d | D9 d => + del_head n d + end + end. + +Definition del_head_int n d := + match d with + | Pos d => Pos (del_head n d) + | Neg d => Neg (del_head n d) + end. + +(** [del_tail n d] removes [n] digits at end of [d] + or returns [zero] if [d] has less than [n] digits. *) + +Fixpoint del_tail n d := rev (del_head n (rev d)). + +Definition del_tail_int n d := + match d with + | Pos d => Pos (del_tail n d) + | Neg d => Neg (del_tail n d) + end. + Module Little. (** Successor of little-endian numbers *) diff --git a/theories/Init/Prelude.v b/theories/Init/Prelude.v index 6126d9c37d..71ba3e645d 100644 --- a/theories/Init/Prelude.v +++ b/theories/Init/Prelude.v @@ -43,5 +43,5 @@ Numeral Notation nat Nat.of_uint Nat.to_uint : nat_scope (abstract after 5001). (* Printing/Parsing of bytes *) Export Byte.ByteSyntaxNotations. -(* Default substrings not considered by queries like SearchAbout *) +(* Default substrings not considered by queries like Search *) Add Search Blacklist "_subproof" "_subterm" "Private_". diff --git a/theories/QArith/QArith_base.v b/theories/QArith/QArith_base.v index a7f338aec3..bd5225d9ef 100644 --- a/theories/QArith/QArith_base.v +++ b/theories/QArith/QArith_base.v @@ -44,13 +44,39 @@ Definition of_decimal (d:Decimal.decimal) : Q := end. Definition to_decimal (q:Q) : option Decimal.decimal := + (* choose between 123e-2 and 1.23, this is purely heuristic + and doesn't play any soundness role *) + let choose_exponent i ne := + let i := match i with Decimal.Pos i | Decimal.Neg i => i end in + let li := Decimal.nb_digits i in + let le := Decimal.nb_digits (Nat.to_uint ne) in + Nat.ltb (Nat.add li le) ne in + (* print 123 / 100 as 123e-2 *) + let decimal_exponent i ne := + let e := Z.to_int (Z.opp (Z.of_nat ne)) in + Decimal.DecimalExp i Decimal.Nil e in + (* print 123 / 100 as 1.23 *) + let decimal_dot i ne := + let ai := match i with Decimal.Pos i | Decimal.Neg i => i end in + let ni := Decimal.nb_digits ai in + if Nat.ltb ne ni then + let i := Decimal.del_tail_int ne i in + let f := Decimal.del_head (Nat.sub ni ne) ai in + Decimal.Decimal i f + else + let z := match i with + | Decimal.Pos _ => Decimal.Pos (Decimal.zero) + | Decimal.Neg _ => Decimal.Neg (Decimal.zero) end in + Decimal.Decimal z (Nat.iter (Nat.sub ne ni) Decimal.D0 ai) in let num := Z.to_int (Qnum q) in let (den, e_den) := Decimal.nztail (Pos.to_uint (Qden q)) in match den with | Decimal.D1 Decimal.Nil => - match Z.of_nat e_den with - | Z0 => Some (Decimal.Decimal num Decimal.Nil) - | e => Some (Decimal.DecimalExp num Decimal.Nil (Z.to_int (Z.opp e))) + match e_den with + | O => Some (Decimal.Decimal num Decimal.Nil) + | ne => + if choose_exponent num ne then Some (decimal_exponent num ne) + else Some (decimal_dot num ne) end | _ => None end. diff --git a/theories/Sorting/Mergesort.v b/theories/Sorting/Mergesort.v index a761dba62d..f6a1efdd37 100644 --- a/theories/Sorting/Mergesort.v +++ b/theories/Sorting/Mergesort.v @@ -230,13 +230,13 @@ Proof. apply IHl. Qed. -Theorem Sorted_sort : forall l, Sorted (sort l). +Theorem LocallySorted_sort : forall l, Sorted (sort l). Proof. intro; apply Sorted_iter_merge. constructor. Qed. -Corollary LocallySorted_sort : forall l, Sorted.Sorted leb (sort l). -Proof. intro; eapply Sorted_LocallySorted_iff, Sorted_sort; auto. Qed. +Corollary Sorted_sort : forall l, Sorted.Sorted leb (sort l). +Proof. intro; eapply Sorted_LocallySorted_iff, LocallySorted_sort; auto. Qed. Theorem Permuted_sort : forall l, Permutation l (sort l). Proof. @@ -245,7 +245,7 @@ Qed. Corollary StronglySorted_sort : forall l, Transitive leb -> StronglySorted leb (sort l). -Proof. auto using Sorted_StronglySorted, LocallySorted_sort. Qed. +Proof. auto using Sorted_StronglySorted, Sorted_sort. Qed. End Sort. @@ -259,7 +259,7 @@ Module NatOrder <: TotalLeBool. | _, 0 => false | S x', S y' => leb x' y' end. - Infix "<=?" := leb (at level 35). + Infix "<=?" := leb (at level 70, no associativity). Theorem leb_total : forall a1 a2, a1 <=? a2 \/ a2 <=? a1. Proof. induction a1; destruct a2; simpl; auto. @@ -269,4 +269,3 @@ End NatOrder. Module Import NatSort := Sort NatOrder. Example SimpleMergeExample := Eval compute in sort [5;3;6;1;8;6;0]. - diff --git a/theories/Structures/Orders.v b/theories/Structures/Orders.v index 6a0e7397eb..94938c1d4d 100644 --- a/theories/Structures/Orders.v +++ b/theories/Structures/Orders.v @@ -192,11 +192,11 @@ Module Type HasLtb (Import T:Typ). End HasLtb. Module Type LebNotation (T:Typ)(E:HasLeb T). - Infix "<=?" := E.leb (at level 35). + Infix "<=?" := E.leb (at level 70, no associativity). End LebNotation. Module Type LtbNotation (T:Typ)(E:HasLtb T). - Infix "<?" := E.ltb (at level 35). + Infix "<?" := E.ltb (at level 70, no associativity). End LtbNotation. Module Type LebSpec (T:Typ)(X:HasLe T)(Y:HasLeb T). diff --git a/tools/coqdoc/output.ml b/tools/coqdoc/output.ml index d2b0078a7c..862715753d 100644 --- a/tools/coqdoc/output.ml +++ b/tools/coqdoc/output.ml @@ -42,7 +42,7 @@ let is_keyword = "Mutual"; "Parameter"; "Parameters"; "Print"; "Printing"; "All"; "Proof"; "Proof with"; "Qed"; "Record"; "Recursive"; "Remark"; "Require"; "Save"; "Scheme"; "Assumptions"; "Axioms"; "Universes"; "Induction"; "for"; "Sort"; "Section"; "Show"; "Structure"; "Syntactic"; "Syntax"; "Tactic"; "Theorem"; - "Search"; "SearchAbout"; "SearchHead"; "SearchPattern"; "SearchRewrite"; + "Search"; "SearchHead"; "SearchPattern"; "SearchRewrite"; "Set"; "Types"; "Undo"; "Unset"; "Variable"; "Variables"; "Context"; "Notation"; "Reserved Notation"; "Tactic Notation"; "Delimit"; "Bind"; "Open"; "Scope"; "Inline"; diff --git a/vernac/comFixpoint.ml b/vernac/comFixpoint.ml index 0a70954dd2..6580495295 100644 --- a/vernac/comFixpoint.ml +++ b/vernac/comFixpoint.ml @@ -236,16 +236,22 @@ let interp_fixpoint ~cofix l = let uctx,fix = ground_fixpoint env evd fix in (fix,pl,uctx,info) -let declare_fixpoint_interactive_generic ?indexes ~scope ~poly ((fixnames,_fixrs,fixdefs,fixtypes),udecl,ctx,fiximps) ntns = - let fix_kind, cofix, indexes = match indexes with - | Some indexes -> Decls.Fixpoint, false, indexes - | None -> Decls.CoFixpoint, true, [] +let build_recthms ~indexes fixnames fixtypes fiximps = + let fix_kind, cofix = match indexes with + | Some indexes -> Decls.Fixpoint, false + | None -> Decls.CoFixpoint, true in let thms = List.map3 (fun name typ (ctx,impargs,_) -> - { Lemmas.Recthm.name; typ + { DeclareDef.Recthm.name; typ ; args = List.map Context.Rel.Declaration.get_name ctx; impargs}) - fixnames fixtypes fiximps in + fixnames fixtypes fiximps + in + fix_kind, cofix, thms + +let declare_fixpoint_interactive_generic ?indexes ~scope ~poly ((fixnames,_fixrs,fixdefs,fixtypes),udecl,ctx,fiximps) ntns = + let fix_kind, cofix, thms = build_recthms ~indexes fixnames fixtypes fiximps in + let indexes = Option.default [] indexes in let init_terms = Some fixdefs in let evd = Evd.from_ctx ctx in let lemma = @@ -255,40 +261,17 @@ let declare_fixpoint_interactive_generic ?indexes ~scope ~poly ((fixnames,_fixrs List.iter (Metasyntax.add_notation_interpretation (Global.env())) ntns; lemma -let declare_fixpoint_generic ?indexes ~scope ~poly ((fixnames,fixrs,fixdefs,fixtypes),pl,ctx,fiximps) ntns = - let indexes, cofix, fix_kind = - match indexes with - | Some indexes -> indexes, false, Decls.(IsDefinition Fixpoint) - | None -> [], true, Decls.(IsDefinition CoFixpoint) - in +let declare_fixpoint_generic ?indexes ~scope ~poly ((fixnames,fixrs,fixdefs,fixtypes),udecl,uctx,fiximps) ntns = (* We shortcut the proof process *) + let fix_kind, cofix, fixitems = build_recthms ~indexes fixnames fixtypes fiximps in let fixdefs = List.map Option.get fixdefs in - let fixdecls = prepare_recursive_declaration fixnames fixrs fixtypes fixdefs in - let vars, fixdecls, gidx = - if not cofix then - let env = Global.env() in - let indexes = Pretyping.search_guard env indexes fixdecls in - let vars = Vars.universes_of_constr (Constr.mkFix ((indexes,0),fixdecls)) in - let fixdecls = List.map_i (fun i _ -> Constr.mkFix ((indexes,i),fixdecls)) 0 fixnames in - vars, fixdecls, Some indexes - else (* cofix *) - let fixdecls = List.map_i (fun i _ -> Constr.mkCoFix (i,fixdecls)) 0 fixnames in - let vars = Vars.universes_of_constr (List.hd fixdecls) in - vars, fixdecls, None - in - let fiximps = List.map (fun (n,r,p) -> r) fiximps in - let evd = Evd.from_ctx ctx in - let evd = Evd.restrict_universe_context evd vars in - let ctx = Evd.check_univ_decl ~poly evd pl in - let ubind = Evd.universe_binders evd in + let rec_declaration = prepare_recursive_declaration fixnames fixrs fixtypes fixdefs in + let fix_kind = Decls.IsDefinition fix_kind in let _ : GlobRef.t list = - List.map4 (fun name body types impargs -> - let ce = Declare.definition_entry ~opaque:false ~types ~univs:ctx body in - DeclareDef.declare_definition ~name ~scope ~kind:fix_kind ~ubind ~impargs ce) - fixnames fixdecls fixtypes fiximps + DeclareDef.declare_mutually_recursive ~scope ~opaque:false ~kind:fix_kind ~poly ~uctx + ~possible_indexes:indexes ~restrict_ucontext:true ~udecl ~ntns ~rec_declaration + fixitems in - Declare.recursive_message (not cofix) gidx fixnames; - List.iter (Metasyntax.add_notation_interpretation (Global.env())) ntns; () let extract_decreasing_argument ~structonly { CAst.v = v; _ } = diff --git a/vernac/declareDef.ml b/vernac/declareDef.ml index 09582f4ef2..fc53abdcea 100644 --- a/vernac/declareDef.ml +++ b/vernac/declareDef.ml @@ -69,6 +69,59 @@ let declare_definition ~name ~scope ~kind ?hook_data ~ubind ~impargs ce = end; dref +let mutual_make_bodies ~fixitems ~rec_declaration ~possible_indexes = + match possible_indexes with + | Some possible_indexes -> + let env = Global.env() in + let indexes = Pretyping.search_guard env possible_indexes rec_declaration in + let vars = Vars.universes_of_constr (Constr.mkFix ((indexes,0),rec_declaration)) in + let fixdecls = CList.map_i (fun i _ -> Constr.mkFix ((indexes,i),rec_declaration)) 0 fixitems in + vars, fixdecls, Some indexes + | None -> + let fixdecls = CList.map_i (fun i _ -> Constr.mkCoFix (i,rec_declaration)) 0 fixitems in + let vars = Vars.universes_of_constr (List.hd fixdecls) in + vars, fixdecls, None + +module Recthm = struct + type t = + { name : Names.Id.t + (** Name of theorem *) + ; typ : Constr.t + (** Type of theorem *) + ; args : Names.Name.t list + (** Names to pre-introduce *) + ; impargs : Impargs.manual_implicits + (** Explicitily declared implicit arguments *) + } +end + +let declare_mutually_recursive ~opaque ~scope ~kind ~poly ~uctx ~udecl ~ntns ~rec_declaration ~possible_indexes ?(restrict_ucontext=true) fixitems = + let vars, fixdecls, indexes = + mutual_make_bodies ~fixitems ~rec_declaration ~possible_indexes in + let ubind, univs = + (* XXX: Obligations don't do this, this seems like a bug? *) + if restrict_ucontext + then + let evd = Evd.from_ctx uctx in + let evd = Evd.restrict_universe_context evd vars in + let univs = Evd.check_univ_decl ~poly evd udecl in + Evd.universe_binders evd, univs + else + let univs = UState.univ_entry ~poly uctx in + UnivNames.empty_binders, univs + in + let csts = CList.map2 + (fun Recthm.{ name; typ; impargs } body -> + let ce = Declare.definition_entry ~opaque ~types:typ ~univs body in + declare_definition ~name ~scope ~kind ~ubind ~impargs ce) + fixitems fixdecls + in + let isfix = Option.is_empty possible_indexes in + let fixnames = List.map (fun { Recthm.name } -> name) fixitems in + Declare.recursive_message isfix indexes fixnames; + List.iter (Metasyntax.add_notation_interpretation (Global.env())) ntns; + csts + let warn_let_as_axiom = CWarnings.create ~name:"let-as-axiom" ~category:"vernacular" Pp.(fun id -> strbrk "Let definition" ++ spc () ++ Names.Id.print id ++ diff --git a/vernac/declareDef.mli b/vernac/declareDef.mli index fb1fc9242c..1d7fd3a3bf 100644 --- a/vernac/declareDef.mli +++ b/vernac/declareDef.mli @@ -59,6 +59,35 @@ val declare_assumption -> Entries.parameter_entry -> GlobRef.t +module Recthm : sig + type t = + { name : Id.t + (** Name of theorem *) + ; typ : Constr.t + (** Type of theorem *) + ; args : Name.t list + (** Names to pre-introduce *) + ; impargs : Impargs.manual_implicits + (** Explicitily declared implicit arguments *) + } +end + +val declare_mutually_recursive + : opaque:bool + -> scope:locality + -> kind:Decls.logical_kind + -> poly:bool + -> uctx:UState.t + -> udecl:UState.universe_decl + -> ntns:Vernacexpr.decl_notation list + -> rec_declaration:Constr.rec_declaration + -> possible_indexes:int list list option + -> ?restrict_ucontext:bool + (** XXX: restrict_ucontext should be always true, this seems like a + bug in obligations, so this parameter should go away *) + -> Recthm.t list + -> Names.GlobRef.t list + val prepare_definition : allow_evars:bool -> ?opaque:bool diff --git a/vernac/declareObl.ml b/vernac/declareObl.ml index 626dcd5d34..98a9e4b9c9 100644 --- a/vernac/declareObl.ml +++ b/vernac/declareObl.ml @@ -251,43 +251,22 @@ let get_prg_info_map () = !from_prg let map_keys m = ProgMap.fold (fun k _ l -> k :: l) m [] -let close sec = +let check_can_close sec = if not (ProgMap.is_empty !from_prg) then let keys = map_keys !from_prg in CErrors.user_err ~hdr:"Program" Pp.( str "Unsolved obligations when closing " - ++ str sec ++ str ":" ++ spc () + ++ Id.print sec ++ str ":" ++ spc () ++ prlist_with_sep spc (fun x -> Id.print x) keys ++ ( str (if Int.equal (List.length keys) 1 then " has " else " have ") ++ str "unsolved obligations" )) -let input : ProgramDecl.t CEphemeron.key ProgMap.t -> Libobject.obj = - let open Libobject in - declare_object - { (default_object "Program state") with - cache_function = (fun (na, pi) -> from_prg := pi) - ; load_function = (fun _ (_, pi) -> from_prg := pi) - ; discharge_function = - (fun _ -> - close "section"; - None ) - ; classify_function = - (fun _ -> - close "module"; - Dispose ) } - -let map_replace k v m = - ProgMap.add k (CEphemeron.create v) (ProgMap.remove k m) - -let progmap_remove prg = - Lib.add_anonymous_leaf (input (ProgMap.remove prg.prg_name !from_prg)) - -let progmap_add n prg = - Lib.add_anonymous_leaf (input (ProgMap.add n prg !from_prg)) - -let progmap_replace prg' = - Lib.add_anonymous_leaf (input (map_replace prg'.prg_name prg' !from_prg)) +let map_replace k v m = ProgMap.add k (CEphemeron.create v) (ProgMap.remove k m) +let prgmap_op f = from_prg := f !from_prg +let progmap_remove prg = prgmap_op (ProgMap.remove prg.prg_name) +let progmap_add n prg = prgmap_op (ProgMap.add n prg) +let progmap_replace prg = prgmap_op (map_replace prg.prg_name prg) let obligations_solved prg = Int.equal prg.prg_obligations.remaining 0 @@ -457,48 +436,35 @@ let declare_mutual_definition l = (xdef :: defs, xobls @ obls)) l ([], []) in (* let fixdefs = List.map reduce_fix fixdefs in *) - let fixdefs, fixrs,fixtypes, fiximps = List.split4 defs in + let fixdefs, fixrs, fixtypes, fixitems = + List.fold_right2 (fun (d,r,typ,impargs) name (a1,a2,a3,a4) -> + d :: a1, r :: a2, typ :: a3, + DeclareDef.Recthm.{ name; typ; impargs; args = [] } :: a4 + ) defs first.prg_deps ([],[],[],[]) + in let fixkind = Option.get first.prg_fixkind in let arrrec, recvec = (Array.of_list fixtypes, Array.of_list fixdefs) in let rvec = Array.of_list fixrs in let namevec = Array.of_list (List.map (fun x -> Name x.prg_name) l) in - let fixdecls = (Array.map2 make_annot namevec rvec, arrrec, recvec) in - let fixnames = first.prg_deps in - let opaque = first.prg_opaque in - let indexes, fixdecls = + let rec_declaration = (Array.map2 make_annot namevec rvec, arrrec, recvec) in + let possible_indexes = match fixkind with | IsFixpoint wfl -> - let possible_indexes = - List.map3 compute_possible_guardness_evidences wfl fixdefs fixtypes - in - let indexes = - Pretyping.search_guard (Global.env ()) possible_indexes fixdecls - in - ( Some indexes - , List.map_i (fun i _ -> mkFix ((indexes, i), fixdecls)) 0 l - ) - | IsCoFixpoint -> - (None, List.map_i (fun i _ -> mkCoFix (i, fixdecls)) 0 l) + Some (List.map3 compute_possible_guardness_evidences wfl fixdefs fixtypes) + | IsCoFixpoint -> None in + (* In the future we will pack all this in a proper record *) + let poly, scope, ntns, opaque = first.prg_poly, first.prg_scope, first.prg_notations, first.prg_opaque in + let kind = if fixkind != IsCoFixpoint then Decls.(IsDefinition Fixpoint) else Decls.(IsDefinition CoFixpoint) in (* Declare the recursive definitions *) - let poly = first.prg_poly in - let scope = first.prg_scope in - let univs = UState.univ_entry ~poly first.prg_ctx in - let fix_exn = Hook.get get_fix_exn () in - let kind = Decls.IsDefinition (if fixkind != IsCoFixpoint then Decls.Fixpoint else Decls.CoFixpoint) in - let ubind = UnivNames.empty_binders in + let udecl = UState.default_univ_decl in let kns = - List.map4 - (fun name body types impargs -> - let ce = Declare.definition_entry ~opaque ~types ~univs body in - DeclareDef.declare_definition ~name ~scope ~kind ~ubind ~impargs ce) - fixnames fixdecls fixtypes fiximps + DeclareDef.declare_mutually_recursive ~scope ~opaque ~kind + ~udecl ~ntns ~uctx:first.prg_ctx ~rec_declaration ~possible_indexes ~poly + ~restrict_ucontext:false fixitems in - (* Declare notations *) - List.iter - (Metasyntax.add_notation_interpretation (Global.env ())) - first.prg_notations; - Declare.recursive_message (fixkind != IsCoFixpoint) indexes fixnames; + (* Only for the first constant *) + let fix_exn = Hook.get get_fix_exn () in let dref = List.hd kns in DeclareDef.Hook.(call ?hook:first.prg_hook ~fix_exn { S.uctx = first.prg_ctx; obls; scope; dref }); List.iter progmap_remove l; diff --git a/vernac/declareObl.mli b/vernac/declareObl.mli index 4e20c7c192..16c0413caf 100644 --- a/vernac/declareObl.mli +++ b/vernac/declareObl.mli @@ -139,6 +139,9 @@ val update_obls : (** { 2 Util } *) +(** Check obligations are properly solved before closing a section *) +val check_can_close : Id.t -> unit + val get_prg_info_map : unit -> ProgramDecl.t CEphemeron.key ProgMap.t val program_tcc_summary_tag : diff --git a/vernac/egramcoq.ml b/vernac/egramcoq.ml index 1d790e7cd2..5dae389a62 100644 --- a/vernac/egramcoq.ml +++ b/vernac/egramcoq.ml @@ -368,7 +368,7 @@ let symbol_of_entry : type s r. _ -> _ -> (s, r) entry -> (s, r) mayrec_symbol = | TTClosedBinderList tkl -> MayRecNo (Alist1sep (Aentry Constr.binder, make_sep_rules tkl)) | TTName -> MayRecNo (Aentry Prim.name) | TTOpenBinderList -> MayRecNo (Aentry Constr.open_binders) -| TTBigint -> MayRecNo (Aentry Prim.bigint) +| TTBigint -> MayRecNo (Aentry Prim.bignat) | TTReference -> MayRecNo (Aentry Constr.global) let interp_entry forpat e = match e with @@ -411,8 +411,8 @@ match e with | TTClosedBinderList _ -> { subst with binderlists = List.flatten v :: subst.binderlists } | TTBigint -> begin match forpat with - | ForConstr -> push_constr subst (CAst.make @@ CPrim (Numeral (SPlus,NumTok.int v))) - | ForPattern -> push_constr subst (CAst.make @@ CPatPrim (Numeral (SPlus,NumTok.int v))) + | ForConstr -> push_constr subst (CAst.make @@ CPrim (Numeral (NumTok.Signed.of_int_string v))) + | ForPattern -> push_constr subst (CAst.make @@ CPatPrim (Numeral (NumTok.Signed.of_int_string v))) end | TTReference -> begin match forpat with diff --git a/vernac/g_vernac.mlg b/vernac/g_vernac.mlg index dd75693c5b..a8f1a49086 100644 --- a/vernac/g_vernac.mlg +++ b/vernac/g_vernac.mlg @@ -983,13 +983,6 @@ GRAMMAR EXTEND Gram { fun g -> VernacSearch (SearchRewrite c,g, l) } | IDENT "Search"; s = searchabout_query; l = searchabout_queries; "." -> { let (sl,m) = l in fun g -> VernacSearch (Search (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: diff --git a/vernac/lemmas.ml b/vernac/lemmas.ml index 7782ff8ac9..e08d2ce117 100644 --- a/vernac/lemmas.ml +++ b/vernac/lemmas.ml @@ -39,15 +39,6 @@ module Proof_ending = struct end -module Recthm = struct - type t = - { name : Id.t - ; typ : Constr.t - ; args : Name.t list - ; impargs : Impargs.manual_implicits - } -end - module Info = struct type t = @@ -56,7 +47,7 @@ module Info = struct ; impargs : Impargs.manual_implicits ; proof_ending : Proof_ending.t CEphemeron.key (* This could be improved and the CEphemeron removed *) - ; other_thms : Recthm.t list + ; other_thms : DeclareDef.Recthm.t list ; scope : DeclareDef.locality ; kind : Decls.logical_kind } @@ -129,7 +120,7 @@ let start_dependent_lemma ~name ~poly let rec_tac_initializer finite guard thms snl = if finite then - match List.map (fun { Recthm.name; typ } -> name, (EConstr.of_constr typ)) thms with + match List.map (fun { DeclareDef.Recthm.name; typ } -> name, (EConstr.of_constr typ)) thms with | (id,_)::l -> Tactics.mutual_cofix id l 0 | _ -> assert false else @@ -137,12 +128,12 @@ let rec_tac_initializer finite guard thms snl = let nl = match snl with | None -> List.map succ (List.map List.last guard) | Some nl -> nl - in match List.map2 (fun { Recthm.name; typ } n -> (name, n, (EConstr.of_constr typ))) thms nl with + in match List.map2 (fun { DeclareDef.Recthm.name; typ } n -> (name, n, (EConstr.of_constr typ))) thms nl with | (id,n,_)::l -> Tactics.mutual_fix id n l 0 | _ -> assert false let start_lemma_with_initialization ?hook ~poly ~scope ~kind ~udecl sigma recguard thms snl = - let intro_tac { Recthm.args; _ } = Tactics.auto_intros_tac args in + let intro_tac { DeclareDef.Recthm.args; _ } = Tactics.auto_intros_tac args in let init_tac, compute_guard = match recguard with | Some (finite,guard,init_terms) -> let rec_tac = rec_tac_initializer finite guard thms snl in @@ -162,7 +153,7 @@ let start_lemma_with_initialization ?hook ~poly ~scope ~kind ~udecl sigma recgua intro_tac (List.hd thms), [] in match thms with | [] -> CErrors.anomaly (Pp.str "No proof to start.") - | { Recthm.name; typ; impargs; _}::other_thms -> + | { DeclareDef.Recthm.name; typ; impargs; _}::other_thms -> let info = Info.{ hook ; impargs @@ -185,25 +176,25 @@ let start_lemma_with_initialization ?hook ~poly ~scope ~kind ~udecl sigma recgua (* XXX: Most of this does belong to Declare, due to proof_entry manip *) module MutualEntry : sig - (* We keep this type abstract and to avoid uncontrolled hacks *) - type t - - val variable : info:Info.t -> Entries.parameter_entry -> t - - val adjust_guardness_conditions + val declare_variable : info:Info.t - -> Evd.side_effects Declare.proof_entry - -> t + -> uctx:UState.t + (* Only for the first constant, introduced by compat *) + -> ubind:UnivNames.universe_binders + -> name:Id.t + -> Entries.parameter_entry + -> Names.GlobRef.t list val declare_mutdef (* Common to all recthms *) - : ?fix_exn:(Exninfo.iexn -> Exninfo.iexn) + : info:Info.t + -> ?fix_exn:(Exninfo.iexn -> Exninfo.iexn) -> uctx:UState.t -> ?hook_data:DeclareDef.Hook.t * UState.t * (Names.Id.t * Constr.t) list (* Only for the first constant, introduced by compat *) -> ubind:UnivNames.universe_binders -> name:Id.t - -> t + -> Evd.side_effects Declare.proof_entry -> Names.GlobRef.t list end = struct @@ -219,8 +210,6 @@ end = struct ; info : Info.t } - let variable ~info t = { entry = NoBody t; info } - (* XXX: Refactor this with the code in [ComFixpoint.declare_fixpoint_generic] *) let guess_decreasing env possible_indexes ((body, ctx), eff) = @@ -290,9 +279,17 @@ end = struct let ubind = UnivNames.empty_binders in let rs = List.map_i ( - fun i { Recthm.name; typ; impargs } -> + fun i { DeclareDef.Recthm.name; typ; impargs } -> declare_mutdef ?fix_exn ~name ~info ~ubind ?hook_data ~uctx ~typ ~impargs entry i) 1 info.Info.other_thms in r :: rs + + let declare_variable ~info ~uctx ~ubind ~name pe = + declare_mutdef ~uctx ~ubind ~name { entry = NoBody pe; info } + + let declare_mutdef ~info ?fix_exn ~uctx ?hook_data ~ubind ~name const = + let mutpe = adjust_guardness_conditions ~info const in + declare_mutdef ?fix_exn ~uctx ?hook_data ~ubind ~name mutpe + end (************************************************************************) @@ -320,10 +317,8 @@ let compute_proof_using_for_admitted proof typ pproofs = | _ -> None let finish_admitted ~name ~info ~uctx pe = - let mutpe = MutualEntry.variable ~info pe in let ubind = UnivNames.empty_binders in - let _r : Names.GlobRef.t list = - MutualEntry.declare_mutdef ~uctx ~ubind ~name mutpe in + let _r : Names.GlobRef.t list = MutualEntry.declare_variable ~info ~uctx ~ubind ~name pe in () let save_lemma_admitted ~(lemma : t) : unit = @@ -361,11 +356,10 @@ let finish_proved idopt po info = | Some { CAst.v = save_id } -> check_anonymity name save_id; save_id in let fix_exn = Declare.Internal.get_fix_exn const in let () = try - let mutpe = MutualEntry.adjust_guardness_conditions ~info const in let hook_data = Option.map (fun hook -> hook, uctx, []) hook in let ubind = UState.universe_binders uctx in let _r : Names.GlobRef.t list = - MutualEntry.declare_mutdef ~fix_exn ~uctx ?hook_data ~ubind ~name mutpe + MutualEntry.declare_mutdef ~info ~fix_exn ~uctx ?hook_data ~ubind ~name const in () with e when CErrors.noncritical e -> let e = Exninfo.capture e in diff --git a/vernac/lemmas.mli b/vernac/lemmas.mli index 471c955311..6a1f8c09f3 100644 --- a/vernac/lemmas.mli +++ b/vernac/lemmas.mli @@ -44,19 +44,6 @@ module Proof_ending : sig end -module Recthm : sig - type t = - { name : Id.t - (** Name of theorem *) - ; typ : Constr.t - (** Type of theorem *) - ; args : Name.t list - (** Names to pre-introduce *) - ; impargs : Impargs.manual_implicits - (** Explicitily declared implicit arguments *) - } -end - module Info : sig type t @@ -104,7 +91,7 @@ val start_lemma_with_initialization -> udecl:UState.universe_decl -> Evd.evar_map -> (bool * lemma_possible_guards * Constr.t option list option) option - -> Recthm.t list + -> DeclareDef.Recthm.t list -> int list option -> t diff --git a/vernac/metasyntax.ml b/vernac/metasyntax.ml index 22e4e35ad4..475d5c31f7 100644 --- a/vernac/metasyntax.ml +++ b/vernac/metasyntax.ml @@ -252,7 +252,7 @@ let quote_notation_token x = let is_numeral symbs = match List.filter (function Break _ -> false | _ -> true) symbs with | ([Terminal "-"; Terminal x] | [Terminal x]) -> - NumTok.of_string x <> None + NumTok.Unsigned.parse_string x <> None | _ -> false diff --git a/vernac/obligations.ml b/vernac/obligations.ml index f449cb02f1..a29ba44907 100644 --- a/vernac/obligations.ml +++ b/vernac/obligations.ml @@ -17,11 +17,8 @@ open Printf - Apply term prefixed by quantification on "existentials". *) -open Term open Constr -open Vars open Names -open Evd open Pp open CErrors open Util @@ -41,7 +38,7 @@ let check_evars env evm = (fun key evi -> if Evd.is_obligation_evar evm key then () else - let (loc,k) = evar_source key evm in + let (loc,k) = Evd.evar_source key evm in Pretype_errors.error_unsolvable_implicit ?loc env evm key None) (Evd.undefined_map evm) @@ -133,14 +130,14 @@ let etype_of_evar evm evs hyps concl = | LocalDef (id,c,_) -> let c', s'', trans'' = subst_evar_constr evm evs n EConstr.mkVar c in let c' = subst_vars acc 0 c' in - mkNamedProd_or_LetIn (LocalDef (id, c', t'')) rest, + Term.mkNamedProd_or_LetIn (LocalDef (id, c', t'')) rest, Int.Set.union s'' s', Id.Set.union trans'' trans' | LocalAssum (id,_) -> - mkNamedProd_or_LetIn (LocalAssum (id, t'')) rest, s', trans') + Term.mkNamedProd_or_LetIn (LocalAssum (id, t'')) rest, s', trans') | [] -> - let t', s, trans = subst_evar_constr evm evs n EConstr.mkVar concl in - subst_vars acc 0 t', s, trans + let t', s, trans = subst_evar_constr evm evs n EConstr.mkVar concl in + subst_vars acc 0 t', s, trans in aux [] 0 (List.rev hyps) let trunc_named_context n ctx = @@ -152,14 +149,14 @@ let rec chop_product n t = if Int.equal n 0 then Some t else match Constr.kind t with - | Prod (_, _, b) -> if noccurn 1 b then chop_product (pred n) (pop b) else None + | Prod (_, _, b) -> if Vars.noccurn 1 b then chop_product (pred n) (pop b) else None | _ -> None let evar_dependencies evm oev = let one_step deps = Evar.Set.fold (fun ev s -> let evi = Evd.find evm ev in - let deps' = evars_of_filtered_evar_info evm evi in + let deps' = Evd.evars_of_filtered_evar_info evm evi in if Evar.Set.mem oev deps' then invalid_arg ("Ill-formed evar map: cycle detected for evar " ^ Pp.string_of_ppcmds @@ Evar.print oev) else Evar.Set.union deps' s) @@ -215,13 +212,13 @@ let eterm_obligations env name evm fs ?status t ty = (fun (id, (n, nstr), ev) l -> let hyps = Evd.evar_filtered_context ev in let hyps = trunc_named_context nc_len hyps in - let evtyp, deps, transp = etype_of_evar evm l hyps ev.evar_concl in + let evtyp, deps, transp = etype_of_evar evm l hyps ev.Evd.evar_concl in let evtyp, hyps, chop = match chop_product fs evtyp with | Some t -> t, trunc_named_context fs hyps, fs | None -> evtyp, hyps, 0 in - let loc, k = evar_source id evm in + let loc, k = Evd.evar_source id evm in let status = match k with | Evar_kinds.QuestionMark { Evar_kinds.qm_obligation=o } -> o | _ -> match status with @@ -282,7 +279,7 @@ let assumption_message = Declare.assumption_message let default_tactic = ref (Proofview.tclUNIT ()) -let evar_of_obligation o = make_evar (Global.named_context_val ()) (EConstr.of_constr o.obl_type) +let evar_of_obligation o = Evd.make_evar (Global.named_context_val ()) (EConstr.of_constr o.obl_type) let subst_deps expand obls deps t = let osubst = DeclareObl.obl_substitution expand obls deps in diff --git a/vernac/ppvernac.ml b/vernac/ppvernac.ml index a3de88d4dc..054b60853f 100644 --- a/vernac/ppvernac.ml +++ b/vernac/ppvernac.ml @@ -142,7 +142,7 @@ open Pputils | SearchOutside [] -> mt() | SearchOutside l -> spc() ++ keyword "outside" ++ spc() ++ prlist_with_sep sep pr_module l - let pr_search_about (b,c) = + let pr_search (b,c) = (if b then str "-" else mt()) ++ match c with | SearchSubPattern p -> @@ -158,10 +158,8 @@ open Pputils | SearchHead c -> keyword "SearchHead" ++ spc() ++ pr_p c ++ pr_in_out_modules b | SearchPattern c -> keyword "SearchPattern" ++ spc() ++ pr_p c ++ pr_in_out_modules b | SearchRewrite c -> keyword "SearchRewrite" ++ spc() ++ pr_p c ++ pr_in_out_modules b - | SearchAbout sl -> - keyword "SearchAbout" ++ spc() ++ prlist_with_sep spc pr_search_about sl ++ pr_in_out_modules b | Search sl -> - keyword "Search" ++ spc() ++ prlist_with_sep spc pr_search_about sl ++ pr_in_out_modules b + keyword "Search" ++ spc() ++ prlist_with_sep spc pr_search sl ++ pr_in_out_modules b let pr_option_ref_value = function | QualidRefValue id -> pr_qualid id diff --git a/vernac/search.ml b/vernac/search.ml index ceff8acc79..68a30b4231 100644 --- a/vernac/search.ml +++ b/vernac/search.ml @@ -23,8 +23,8 @@ module NamedDecl = Context.Named.Declaration type filter_function = GlobRef.t -> env -> constr -> bool type display_function = GlobRef.t -> env -> constr -> unit -(* This option restricts the output of [SearchPattern ...], -[SearchAbout ...], etc. to the names of the symbols matching the +(* This option restricts the output of [SearchPattern ...], etc. +to the names of the symbols matching the query, separated by a newline. This type of output is useful for editors (like emacs), to generate a list of completion candidates without having to parse through the types of all symbols. *) @@ -226,7 +226,7 @@ let module_filter (mods, outside) ref env typ = let name_of_reference ref = Id.to_string (Nametab.basename_of_global ref) -let search_about_filter query gr env typ = match query with +let search_filter query gr env typ = match query with | GlobSearchSubPattern pat -> Constr_matching.is_matching_appsubterm ~closed:false env (Evd.from_env env) pat (EConstr.of_constr typ) | GlobSearchString s -> @@ -283,14 +283,14 @@ let search_by_head ?pstate gopt pat mods pr_search = in generic_search ?pstate gopt iter -(** SearchAbout *) +(** Search *) -let search_about ?pstate gopt items mods pr_search = +let search ?pstate gopt items mods pr_search = let filter ref env typ = let eqb b1 b2 = if b1 then b2 else not b2 in module_filter mods ref env typ && List.for_all - (fun (b,i) -> eqb b (search_about_filter i ref env typ)) items && + (fun (b,i) -> eqb b (search_filter i ref env typ)) items && blacklist_filter ref env typ in let iter ref env typ = diff --git a/vernac/search.mli b/vernac/search.mli index 11dd0c6794..6dbbff3a8c 100644 --- a/vernac/search.mli +++ b/vernac/search.mli @@ -30,8 +30,7 @@ val blacklist_filter : filter_function val module_filter : DirPath.t list * bool -> filter_function (** Check whether a reference pertains or not to a set of modules *) -val search_about_filter : glob_search_about_item -> filter_function -(** Check whether a reference matches a SearchAbout query. *) +val search_filter : glob_search_about_item -> filter_function (** {6 Specialized search functions} @@ -45,7 +44,7 @@ val search_rewrite : ?pstate:Proof_global.t -> int option -> constr_pattern -> D -> display_function -> unit val search_pattern : ?pstate:Proof_global.t -> int option -> constr_pattern -> DirPath.t list * bool -> display_function -> unit -val search_about : ?pstate:Proof_global.t -> int option -> (bool * glob_search_about_item) list +val search : ?pstate:Proof_global.t -> int option -> (bool * glob_search_about_item) list -> DirPath.t list * bool -> display_function -> unit type search_constraint = diff --git a/vernac/vernacentries.ml b/vernac/vernacentries.ml index 8a4522296f..963b5f2084 100644 --- a/vernac/vernacentries.ml +++ b/vernac/vernacentries.ml @@ -501,7 +501,7 @@ let start_lemma_com ~program_mode ~poly ~scope ~kind ?hook thms = let recguard,thms,snl = RecLemmas.look_for_possibly_mutual_statements evd thms in let evd = Evd.minimize_universes evd in let thms = List.map (fun (name, (typ, (args, impargs))) -> - { Lemmas.Recthm.name; typ = EConstr.to_constr evd typ; args; impargs} ) thms in + { DeclareDef.Recthm.name; typ = EConstr.to_constr evd typ; args; impargs} ) thms in let () = let open UState in if not (udecl.univdecl_extensible_instance && udecl.univdecl_extensible_constraints) then @@ -983,7 +983,7 @@ let vernac_begin_section ~poly ({v=id} as lid) = to its current value ie noop. *) set_bool_option_value_gen ~locality:OptLocal ["Universe"; "Polymorphism"] poly -let vernac_end_section {CAst.loc} = +let vernac_end_section {CAst.loc; v} = Dumpglob.dump_reference ?loc (DirPath.to_string (Lib.current_dirpath true)) "<>" "sec"; Lib.close_section () @@ -993,6 +993,7 @@ let vernac_name_sec_hyp {v=id} set = Proof_using.name_set id set (* Dispatcher of the "End" command *) let vernac_end_segment ({v=id} as lid) = + DeclareObl.check_can_close lid.v; match Lib.find_opening_node id with | Lib.OpenedModule (false,export,_,_) -> vernac_end_module export lid | Lib.OpenedModule (true,_,_,_) -> vernac_end_modtype lid @@ -1772,10 +1773,6 @@ let () = optread = (fun () -> !search_output_name_only); optwrite = (:=) search_output_name_only } -let warn_deprecated_search_about = - CWarnings.create ~name:"deprecated-search-about" ~category:"deprecated" - (fun () -> strbrk "The SearchAbout command is deprecated. Please use Search instead.") - let vernac_search ~pstate ~atts s gopt r = let gopt = query_command_selector gopt in let r = interp_search_restriction r in @@ -1808,12 +1805,8 @@ let vernac_search ~pstate ~atts s gopt r = (Search.search_rewrite ?pstate gopt (get_pattern c) r |> Search.prioritize_search) pr_search | SearchHead c -> (Search.search_by_head ?pstate gopt (get_pattern c) r |> Search.prioritize_search) pr_search - | SearchAbout sl -> - warn_deprecated_search_about (); - (Search.search_about ?pstate gopt (List.map (on_snd (interp_search_about_item env Evd.(from_env env))) sl) r |> - Search.prioritize_search) pr_search | Search sl -> - (Search.search_about ?pstate gopt (List.map (on_snd (interp_search_about_item env Evd.(from_env env))) sl) r |> + (Search.search ?pstate gopt (List.map (on_snd (interp_search_about_item env Evd.(from_env env))) sl) r |> Search.prioritize_search) pr_search); Feedback.msg_notice (str "(use \"About\" for full details on implicit arguments)") diff --git a/vernac/vernacexpr.ml b/vernac/vernacexpr.ml index b7c6d3c490..d6e7a3947a 100644 --- a/vernac/vernacexpr.ml +++ b/vernac/vernacexpr.ml @@ -69,7 +69,6 @@ type searchable = | SearchPattern of constr_pattern_expr | SearchRewrite of constr_pattern_expr | SearchHead of constr_pattern_expr - | SearchAbout of (bool * search_about_item) list | Search of (bool * search_about_item) list type locatable = |
